xref: /freebsd/lib/libc/net/ether_addr.c (revision dab8ffaac3d0c9d1968744cc1ab485283acfcf5a)
17680d1b0SBill Paul /*
27680d1b0SBill Paul  * Copyright (c) 1995
37680d1b0SBill Paul  *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
47680d1b0SBill Paul  *
57680d1b0SBill Paul  * Redistribution and use in source and binary forms, with or without
67680d1b0SBill Paul  * modification, are permitted provided that the following conditions
77680d1b0SBill Paul  * are met:
87680d1b0SBill Paul  * 1. Redistributions of source code must retain the above copyright
97680d1b0SBill Paul  *    notice, this list of conditions and the following disclaimer.
107680d1b0SBill Paul  * 2. Redistributions in binary form must reproduce the above copyright
117680d1b0SBill Paul  *    notice, this list of conditions and the following disclaimer in the
127680d1b0SBill Paul  *    documentation and/or other materials provided with the distribution.
137680d1b0SBill Paul  * 3. All advertising materials mentioning features or use of this software
147680d1b0SBill Paul  *    must display the following acknowledgement:
157680d1b0SBill Paul  *	This product includes software developed by Bill Paul.
167680d1b0SBill Paul  * 4. Neither the name of the author nor the names of any co-contributors
177680d1b0SBill Paul  *    may be used to endorse or promote products derived from this software
187680d1b0SBill Paul  *    without specific prior written permission.
197680d1b0SBill Paul  *
207680d1b0SBill Paul  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
217680d1b0SBill Paul  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
227680d1b0SBill Paul  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237680d1b0SBill Paul  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
247680d1b0SBill Paul  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257680d1b0SBill Paul  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267680d1b0SBill Paul  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277680d1b0SBill Paul  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
287680d1b0SBill Paul  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
297680d1b0SBill Paul  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
307680d1b0SBill Paul  * SUCH DAMAGE.
317680d1b0SBill Paul  *
327680d1b0SBill Paul  * ethernet address conversion and lookup routines
337680d1b0SBill Paul  *
347680d1b0SBill Paul  * Written by Bill Paul <wpaul@ctr.columbia.edu>
357680d1b0SBill Paul  * Center for Telecommunications Research
367680d1b0SBill Paul  * Columbia University, New York City
377680d1b0SBill Paul  */
387680d1b0SBill Paul 
39ee6c974dSEric Melville #include <sys/cdefs.h>
40ee6c974dSEric Melville __FBSDID("$FreeBSD$");
417680d1b0SBill Paul 
427680d1b0SBill Paul #include <stdio.h>
437680d1b0SBill Paul #include <paths.h>
447680d1b0SBill Paul #include <sys/types.h>
457680d1b0SBill Paul #include <string.h>
467680d1b0SBill Paul #include <stdlib.h>
477680d1b0SBill Paul #include <sys/param.h>
487680d1b0SBill Paul #include <sys/socket.h>
4913629194SGarrett Wollman #include <net/ethernet.h>
507680d1b0SBill Paul #ifdef YP
517680d1b0SBill Paul #include <rpc/rpc.h>
527680d1b0SBill Paul #include <rpcsvc/yp_prot.h>
537680d1b0SBill Paul #include <rpcsvc/ypclnt.h>
547680d1b0SBill Paul #endif
557680d1b0SBill Paul 
567680d1b0SBill Paul #ifndef _PATH_ETHERS
577680d1b0SBill Paul #define _PATH_ETHERS "/etc/ethers"
587680d1b0SBill Paul #endif
597680d1b0SBill Paul 
607680d1b0SBill Paul /*
617680d1b0SBill Paul  * Parse a string of text containing an ethernet address and hostname
627680d1b0SBill Paul  * and separate it into its component parts.
637680d1b0SBill Paul  */
64ee6c974dSEric Melville int
65ee6c974dSEric Melville ether_line(l, e, hostname)
666e641683SArchie Cobbs 	const char *l;
677680d1b0SBill Paul 	struct ether_addr *e;
687680d1b0SBill Paul 	char *hostname;
697680d1b0SBill Paul {
707680d1b0SBill Paul         int i, o[6];
717680d1b0SBill Paul 
727680d1b0SBill Paul         i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2],
737680d1b0SBill Paul                                               &o[3], &o[4], &o[5],
747680d1b0SBill Paul 					      hostname);
757680d1b0SBill Paul 	if (i != 7)
767680d1b0SBill Paul                 return (i);
777680d1b0SBill Paul 
787680d1b0SBill Paul         for (i=0; i<6; i++)
797680d1b0SBill Paul                 e->octet[i] = o[i];
807680d1b0SBill Paul         return (0);
817680d1b0SBill Paul }
827680d1b0SBill Paul 
837680d1b0SBill Paul /*
847680d1b0SBill Paul  * Convert an ASCII representation of an ethernet address to
857680d1b0SBill Paul  * binary form.
867680d1b0SBill Paul  */
87ee6c974dSEric Melville struct
88ee6c974dSEric Melville ether_addr *ether_aton(a)
896e641683SArchie Cobbs 	const char *a;
907680d1b0SBill Paul {
917680d1b0SBill Paul         int i;
927680d1b0SBill Paul 	static struct ether_addr o;
9351295a4dSJordan K. Hubbard 	unsigned int o0, o1, o2, o3, o4, o5;
947680d1b0SBill Paul 
9551295a4dSJordan K. Hubbard         i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
9651295a4dSJordan K. Hubbard 
977680d1b0SBill Paul         if (i != 6)
987680d1b0SBill Paul                 return (NULL);
9951295a4dSJordan K. Hubbard 
10051295a4dSJordan K. Hubbard         o.octet[0]=o0;
10151295a4dSJordan K. Hubbard 	o.octet[1]=o1;
10251295a4dSJordan K. Hubbard 	o.octet[2]=o2;
10351295a4dSJordan K. Hubbard 	o.octet[3]=o3;
10451295a4dSJordan K. Hubbard 	o.octet[4]=o4;
10551295a4dSJordan K. Hubbard 	o.octet[5]=o5;
10651295a4dSJordan K. Hubbard 
1077680d1b0SBill Paul         return ((struct ether_addr *)&o);
1087680d1b0SBill Paul }
1097680d1b0SBill Paul 
1107680d1b0SBill Paul /*
1117680d1b0SBill Paul  * Convert a binary representation of an ethernet address to
1127680d1b0SBill Paul  * an ASCII string.
1137680d1b0SBill Paul  */
114ee6c974dSEric Melville char
115ee6c974dSEric Melville *ether_ntoa(n)
1166e641683SArchie Cobbs 	const struct ether_addr *n;
1177680d1b0SBill Paul {
1187680d1b0SBill Paul         int i;
1197680d1b0SBill Paul 	static char a[18];
1207680d1b0SBill Paul 
12187bd4d6cSMatthew Dillon         i = sprintf(a,"%02x:%02x:%02x:%02x:%02x:%02x",
12287bd4d6cSMatthew Dillon 			n->octet[0],n->octet[1],n->octet[2],
1237680d1b0SBill Paul 			n->octet[3],n->octet[4],n->octet[5]);
124dab8ffaaSRuslan Ermilov         if (i < 17)
1257680d1b0SBill Paul                 return (NULL);
1267680d1b0SBill Paul         return ((char *)&a);
1277680d1b0SBill Paul }
1287680d1b0SBill Paul 
1297680d1b0SBill Paul /*
1307680d1b0SBill Paul  * Map an ethernet address to a hostname. Use either /etc/ethers or
1317680d1b0SBill Paul  * NIS/YP.
1327680d1b0SBill Paul  */
133ee6c974dSEric Melville int
134ee6c974dSEric Melville ether_ntohost(hostname, e)
1357680d1b0SBill Paul 	char *hostname;
1366e641683SArchie Cobbs 	const struct ether_addr *e;
1377680d1b0SBill Paul {
1387680d1b0SBill Paul 	FILE *fp;
1393951b8e3SBill Paul 	char buf[BUFSIZ + 2];
1407680d1b0SBill Paul 	struct ether_addr local_ether;
1417680d1b0SBill Paul 	char local_host[MAXHOSTNAMELEN];
1427680d1b0SBill Paul #ifdef YP
1437680d1b0SBill Paul 	char *result;
1447680d1b0SBill Paul 	int resultlen;
1457680d1b0SBill Paul 	char *ether_a;
1467680d1b0SBill Paul 	char *yp_domain;
1477680d1b0SBill Paul #endif
1487680d1b0SBill Paul 	if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
1497680d1b0SBill Paul 		return (1);
1507680d1b0SBill Paul 
1517680d1b0SBill Paul 	while (fgets(buf,BUFSIZ,fp)) {
1527680d1b0SBill Paul 		if (buf[0] == '#')
1537680d1b0SBill Paul 			continue;
1547680d1b0SBill Paul #ifdef YP
1557680d1b0SBill Paul 		if (buf[0] == '+') {
1567680d1b0SBill Paul 			if (yp_get_default_domain(&yp_domain))
1571e890b05SBill Paul 				continue;
1587680d1b0SBill Paul 			ether_a = ether_ntoa(e);
1597680d1b0SBill Paul 			if (yp_match(yp_domain, "ethers.byaddr", ether_a,
1607680d1b0SBill Paul 				strlen(ether_a), &result, &resultlen)) {
1611e890b05SBill Paul 				continue;
1627680d1b0SBill Paul 			}
1632696fe9cSJordan K. Hubbard 			strncpy(buf, result, resultlen);
1643951b8e3SBill Paul 			buf[resultlen] = '\0';
1657680d1b0SBill Paul 			free(result);
1667680d1b0SBill Paul 		}
1677680d1b0SBill Paul #endif
1682696fe9cSJordan K. Hubbard 		if (!ether_line(buf, &local_ether, local_host)) {
1697680d1b0SBill Paul 			if (!bcmp((char *)&local_ether.octet[0],
1707680d1b0SBill Paul 				(char *)&e->octet[0], 6)) {
1717680d1b0SBill Paul 			/* We have a match */
1722696fe9cSJordan K. Hubbard 				strcpy(hostname, local_host);
1737680d1b0SBill Paul 				fclose(fp);
1747680d1b0SBill Paul 				return(0);
1757680d1b0SBill Paul 			}
1767680d1b0SBill Paul 		}
1777680d1b0SBill Paul 	}
1787680d1b0SBill Paul 	fclose(fp);
1797680d1b0SBill Paul 	return (1);
1807680d1b0SBill Paul }
1817680d1b0SBill Paul 
1827680d1b0SBill Paul /*
1837680d1b0SBill Paul  * Map a hostname to an ethernet address using /etc/ethers or
1847680d1b0SBill Paul  * NIS/YP.
1857680d1b0SBill Paul  */
186ee6c974dSEric Melville int
187ee6c974dSEric Melville ether_hostton(hostname, e)
1886e641683SArchie Cobbs 	const char *hostname;
1897680d1b0SBill Paul 	struct ether_addr *e;
1907680d1b0SBill Paul {
1917680d1b0SBill Paul 	FILE *fp;
1923951b8e3SBill Paul 	char buf[BUFSIZ + 2];
1937680d1b0SBill Paul 	struct ether_addr local_ether;
1947680d1b0SBill Paul 	char local_host[MAXHOSTNAMELEN];
1957680d1b0SBill Paul #ifdef YP
1967680d1b0SBill Paul 	char *result;
1977680d1b0SBill Paul 	int resultlen;
1987680d1b0SBill Paul 	char *yp_domain;
1997680d1b0SBill Paul #endif
2007680d1b0SBill Paul 	if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
2017680d1b0SBill Paul 		return (1);
2027680d1b0SBill Paul 
2037680d1b0SBill Paul 	while (fgets(buf,BUFSIZ,fp)) {
2047680d1b0SBill Paul 		if (buf[0] == '#')
2057680d1b0SBill Paul 			continue;
2067680d1b0SBill Paul #ifdef YP
2077680d1b0SBill Paul 		if (buf[0] == '+') {
2087680d1b0SBill Paul 			if (yp_get_default_domain(&yp_domain))
2091e890b05SBill Paul 				continue;
2107680d1b0SBill Paul 			if (yp_match(yp_domain, "ethers.byname", hostname,
2117680d1b0SBill Paul 				strlen(hostname), &result, &resultlen)) {
2121e890b05SBill Paul 				continue;
2137680d1b0SBill Paul 			}
2142696fe9cSJordan K. Hubbard 			strncpy(buf, result, resultlen);
2153951b8e3SBill Paul 			buf[resultlen] = '\0';
2167680d1b0SBill Paul 			free(result);
2177680d1b0SBill Paul 		}
2187680d1b0SBill Paul #endif
2192696fe9cSJordan K. Hubbard 		if (!ether_line(buf, &local_ether, local_host)) {
2202696fe9cSJordan K. Hubbard 			if (!strcmp(hostname, local_host)) {
2217680d1b0SBill Paul 				/* We have a match */
2227680d1b0SBill Paul 				bcopy((char *)&local_ether.octet[0],
2237680d1b0SBill Paul 					(char *)&e->octet[0], 6);
2247680d1b0SBill Paul 				fclose(fp);
2257680d1b0SBill Paul 				return(0);
2267680d1b0SBill Paul 			}
2277680d1b0SBill Paul 		}
2287680d1b0SBill Paul 	}
2297680d1b0SBill Paul 	fclose(fp);
2307680d1b0SBill Paul 	return (1);
2317680d1b0SBill Paul }
232