xref: /freebsd/lib/libc/net/ether_addr.c (revision b06619453fa6a8c9a344dcc59e1bbf1b78a9f4b3)
17680d1b0SBill Paul /*
2b0661945SRobert Watson  * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>.
3b0661945SRobert Watson  * 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 <sys/types.h>
437680d1b0SBill Paul #include <sys/param.h>
447680d1b0SBill Paul #include <sys/socket.h>
45b0661945SRobert Watson 
4613629194SGarrett Wollman #include <net/ethernet.h>
47b0661945SRobert Watson 
487680d1b0SBill Paul #ifdef YP
497680d1b0SBill Paul #include <rpc/rpc.h>
507680d1b0SBill Paul #include <rpcsvc/yp_prot.h>
517680d1b0SBill Paul #include <rpcsvc/ypclnt.h>
527680d1b0SBill Paul #endif
537680d1b0SBill Paul 
54b0661945SRobert Watson #include <paths.h>
55b0661945SRobert Watson #include <stdio.h>
56b0661945SRobert Watson #include <stdlib.h>
57b0661945SRobert Watson #include <string.h>
58b0661945SRobert Watson 
597680d1b0SBill Paul #ifndef _PATH_ETHERS
607680d1b0SBill Paul #define	_PATH_ETHERS	"/etc/ethers"
617680d1b0SBill Paul #endif
627680d1b0SBill Paul 
637680d1b0SBill Paul /*
64b0661945SRobert Watson  * Parse a string of text containing an ethernet address and hostname and
65b0661945SRobert Watson  * separate it into its component parts.
667680d1b0SBill Paul  */
67ee6c974dSEric Melville int
68b0661945SRobert Watson ether_line(const char *l, struct ether_addr *e, char *hostname)
697680d1b0SBill Paul {
707680d1b0SBill Paul         int i, o[6];
717680d1b0SBill Paul 
72b0661945SRobert Watson         i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2], &o[3],
73b0661945SRobert Watson 	    &o[4], &o[5], hostname);
747680d1b0SBill Paul 	if (i != 7)
757680d1b0SBill Paul                 return (i);
767680d1b0SBill Paul         for (i=0; i<6; i++)
777680d1b0SBill Paul                 e->octet[i] = o[i];
787680d1b0SBill Paul         return (0);
797680d1b0SBill Paul }
807680d1b0SBill Paul 
817680d1b0SBill Paul /*
82b0661945SRobert Watson  * Convert an ASCII representation of an ethernet address to binary form.
837680d1b0SBill Paul  */
84b0661945SRobert Watson struct ether_addr *
85b0661945SRobert Watson ether_aton(const char *a)
867680d1b0SBill Paul {
877680d1b0SBill Paul         int i;
887680d1b0SBill Paul 	static struct ether_addr o;
8951295a4dSJordan K. Hubbard 	unsigned int o0, o1, o2, o3, o4, o5;
907680d1b0SBill Paul 
9151295a4dSJordan K. Hubbard         i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
927680d1b0SBill Paul         if (i != 6)
937680d1b0SBill Paul                 return (NULL);
9451295a4dSJordan K. Hubbard         o.octet[0]=o0;
9551295a4dSJordan K. Hubbard 	o.octet[1]=o1;
9651295a4dSJordan K. Hubbard 	o.octet[2]=o2;
9751295a4dSJordan K. Hubbard 	o.octet[3]=o3;
9851295a4dSJordan K. Hubbard 	o.octet[4]=o4;
9951295a4dSJordan K. Hubbard 	o.octet[5]=o5;
1007680d1b0SBill Paul         return ((struct ether_addr *)&o);
1017680d1b0SBill Paul }
1027680d1b0SBill Paul 
1037680d1b0SBill Paul /*
104b0661945SRobert Watson  * Convert a binary representation of an ethernet address to an ASCII string.
1057680d1b0SBill Paul  */
106b0661945SRobert Watson char *
107b0661945SRobert Watson ether_ntoa(const struct ether_addr *n)
1087680d1b0SBill Paul {
1097680d1b0SBill Paul         int i;
1107680d1b0SBill Paul 	static char a[18];
1117680d1b0SBill Paul 
112b0661945SRobert Watson         i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0],
113b0661945SRobert Watson 	    n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]);
114dab8ffaaSRuslan Ermilov         if (i < 17)
1157680d1b0SBill Paul                 return (NULL);
1167680d1b0SBill Paul         return ((char *)&a);
1177680d1b0SBill Paul }
1187680d1b0SBill Paul 
1197680d1b0SBill Paul /*
120b0661945SRobert Watson  * Map an ethernet address to a hostname. Use either /etc/ethers or NIS/YP.
1217680d1b0SBill Paul  */
122ee6c974dSEric Melville int
123b0661945SRobert Watson ether_ntohost(char *hostname, const struct ether_addr *e)
1247680d1b0SBill Paul {
1257680d1b0SBill Paul 	FILE *fp;
1263951b8e3SBill Paul 	char buf[BUFSIZ + 2];
1277680d1b0SBill Paul 	struct ether_addr local_ether;
1287680d1b0SBill Paul 	char local_host[MAXHOSTNAMELEN];
1297680d1b0SBill Paul #ifdef YP
1307680d1b0SBill Paul 	char *result;
1317680d1b0SBill Paul 	int resultlen;
1327680d1b0SBill Paul 	char *ether_a;
1337680d1b0SBill Paul 	char *yp_domain;
1347680d1b0SBill Paul #endif
135b0661945SRobert Watson 
1367680d1b0SBill Paul 	if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
1377680d1b0SBill Paul 		return (1);
1387680d1b0SBill Paul 	while (fgets(buf,BUFSIZ,fp)) {
1397680d1b0SBill Paul 		if (buf[0] == '#')
1407680d1b0SBill Paul 			continue;
1417680d1b0SBill Paul #ifdef YP
1427680d1b0SBill Paul 		if (buf[0] == '+') {
1437680d1b0SBill Paul 			if (yp_get_default_domain(&yp_domain))
1441e890b05SBill Paul 				continue;
1457680d1b0SBill Paul 			ether_a = ether_ntoa(e);
1467680d1b0SBill Paul 			if (yp_match(yp_domain, "ethers.byaddr", ether_a,
1477680d1b0SBill Paul 			    strlen(ether_a), &result, &resultlen)) {
1481e890b05SBill Paul 				continue;
1497680d1b0SBill Paul 			}
1502696fe9cSJordan K. Hubbard 			strncpy(buf, result, resultlen);
1513951b8e3SBill Paul 			buf[resultlen] = '\0';
1527680d1b0SBill Paul 			free(result);
1537680d1b0SBill Paul 		}
1547680d1b0SBill Paul #endif
1552696fe9cSJordan K. Hubbard 		if (!ether_line(buf, &local_ether, local_host)) {
1567680d1b0SBill Paul 			if (!bcmp((char *)&local_ether.octet[0],
1577680d1b0SBill Paul 			    (char *)&e->octet[0], 6)) {
158b0661945SRobert Watson 				/* We have a match. */
1592696fe9cSJordan K. Hubbard 				strcpy(hostname, local_host);
1607680d1b0SBill Paul 				fclose(fp);
1617680d1b0SBill Paul 				return(0);
1627680d1b0SBill Paul 			}
1637680d1b0SBill Paul 		}
1647680d1b0SBill Paul 	}
1657680d1b0SBill Paul 	fclose(fp);
1667680d1b0SBill Paul 	return (1);
1677680d1b0SBill Paul }
1687680d1b0SBill Paul 
1697680d1b0SBill Paul /*
170b0661945SRobert Watson  * Map a hostname to an ethernet address using /etc/ethers or NIS/YP.
1717680d1b0SBill Paul  */
172ee6c974dSEric Melville int
173b0661945SRobert Watson ether_hostton(const char *hostname, struct ether_addr *e)
1747680d1b0SBill Paul {
1757680d1b0SBill Paul 	FILE *fp;
1763951b8e3SBill Paul 	char buf[BUFSIZ + 2];
1777680d1b0SBill Paul 	struct ether_addr local_ether;
1787680d1b0SBill Paul 	char local_host[MAXHOSTNAMELEN];
1797680d1b0SBill Paul #ifdef YP
1807680d1b0SBill Paul 	char *result;
1817680d1b0SBill Paul 	int resultlen;
1827680d1b0SBill Paul 	char *yp_domain;
1837680d1b0SBill Paul #endif
184b0661945SRobert Watson 
1857680d1b0SBill Paul 	if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
1867680d1b0SBill Paul 		return (1);
1877680d1b0SBill Paul 	while (fgets(buf,BUFSIZ,fp)) {
1887680d1b0SBill Paul 		if (buf[0] == '#')
1897680d1b0SBill Paul 			continue;
1907680d1b0SBill Paul #ifdef YP
1917680d1b0SBill Paul 		if (buf[0] == '+') {
1927680d1b0SBill Paul 			if (yp_get_default_domain(&yp_domain))
1931e890b05SBill Paul 				continue;
1947680d1b0SBill Paul 			if (yp_match(yp_domain, "ethers.byname", hostname,
1957680d1b0SBill Paul 			    strlen(hostname), &result, &resultlen)) {
1961e890b05SBill Paul 				continue;
1977680d1b0SBill Paul 			}
1982696fe9cSJordan K. Hubbard 			strncpy(buf, result, resultlen);
1993951b8e3SBill Paul 			buf[resultlen] = '\0';
2007680d1b0SBill Paul 			free(result);
2017680d1b0SBill Paul 		}
2027680d1b0SBill Paul #endif
2032696fe9cSJordan K. Hubbard 		if (!ether_line(buf, &local_ether, local_host)) {
2042696fe9cSJordan K. Hubbard 			if (!strcmp(hostname, local_host)) {
205b0661945SRobert Watson 				/* We have a match. */
2067680d1b0SBill Paul 				bcopy((char *)&local_ether.octet[0],
2077680d1b0SBill Paul 				    (char *)&e->octet[0], 6);
2087680d1b0SBill Paul 				fclose(fp);
2097680d1b0SBill Paul 				return(0);
2107680d1b0SBill Paul 			}
2117680d1b0SBill Paul 		}
2127680d1b0SBill Paul 	}
2137680d1b0SBill Paul 	fclose(fp);
2147680d1b0SBill Paul 	return (1);
2157680d1b0SBill Paul }
216