xref: /freebsd/lib/libc/net/ether_addr.c (revision 51295a4d3e4c551df85249433c490208dc7fd23d)
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  *
3851295a4dSJordan K. Hubbard  *	$Id: ether_addr.c,v 1.3 1996/03/16 21:25:59 wpaul Exp $
397680d1b0SBill Paul  */
407680d1b0SBill Paul 
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>
497680d1b0SBill Paul #include <net/if.h>
507680d1b0SBill Paul #include <netinet/in.h>
517680d1b0SBill Paul #include <netinet/if_ether.h>
527680d1b0SBill Paul #ifdef YP
537680d1b0SBill Paul #include <rpc/rpc.h>
547680d1b0SBill Paul #include <rpcsvc/yp_prot.h>
557680d1b0SBill Paul #include <rpcsvc/ypclnt.h>
567680d1b0SBill Paul #endif
577680d1b0SBill Paul 
587680d1b0SBill Paul #ifndef _PATH_ETHERS
597680d1b0SBill Paul #define _PATH_ETHERS "/etc/ethers"
607680d1b0SBill Paul #endif
617680d1b0SBill Paul 
627680d1b0SBill Paul /*
637680d1b0SBill Paul  * Parse a string of text containing an ethernet address and hostname
647680d1b0SBill Paul  * and separate it into its component parts.
657680d1b0SBill Paul  */
667680d1b0SBill Paul int ether_line(l, e, hostname)
677680d1b0SBill Paul         char *l;
687680d1b0SBill Paul 	struct ether_addr *e;
697680d1b0SBill Paul 	char *hostname;
707680d1b0SBill Paul {
717680d1b0SBill Paul         int i, o[6];
727680d1b0SBill Paul 
737680d1b0SBill Paul         i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2],
747680d1b0SBill Paul                                               &o[3], &o[4], &o[5],
757680d1b0SBill Paul 					      hostname);
767680d1b0SBill Paul 	if (i != 7)
777680d1b0SBill Paul                 return (i);
787680d1b0SBill Paul 
797680d1b0SBill Paul         for (i=0; i<6; i++)
807680d1b0SBill Paul                 e->octet[i] = o[i];
817680d1b0SBill Paul         return (0);
827680d1b0SBill Paul }
837680d1b0SBill Paul 
847680d1b0SBill Paul /*
857680d1b0SBill Paul  * Convert an ASCII representation of an ethernet address to
867680d1b0SBill Paul  * binary form.
877680d1b0SBill Paul  */
887680d1b0SBill Paul struct ether_addr *ether_aton(a)
897680d1b0SBill Paul         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  */
1147680d1b0SBill Paul char *ether_ntoa(n)
1157680d1b0SBill Paul         struct ether_addr *n;
1167680d1b0SBill Paul {
1177680d1b0SBill Paul         int i;
1187680d1b0SBill Paul 	static char a[18];
1197680d1b0SBill Paul 
1207680d1b0SBill Paul         i = sprintf(a,"%x:%x:%x:%x:%x:%x",n->octet[0],n->octet[1],n->octet[2],
1217680d1b0SBill Paul                                           n->octet[3],n->octet[4],n->octet[5]);
1227680d1b0SBill Paul         if (i < 11)
1237680d1b0SBill Paul                 return (NULL);
1247680d1b0SBill Paul         return ((char *)&a);
1257680d1b0SBill Paul }
1267680d1b0SBill Paul 
1277680d1b0SBill Paul /*
1287680d1b0SBill Paul  * Map an ethernet address to a hostname. Use either /etc/ethers or
1297680d1b0SBill Paul  * NIS/YP.
1307680d1b0SBill Paul  */
1317680d1b0SBill Paul 
1327680d1b0SBill Paul int ether_ntohost(hostname, e)
1337680d1b0SBill Paul 	char *hostname;
1347680d1b0SBill Paul 	struct ether_addr *e;
1357680d1b0SBill Paul {
1367680d1b0SBill Paul 	FILE *fp;
1377680d1b0SBill Paul 	char buf[BUFSIZ];
1387680d1b0SBill Paul 	struct ether_addr local_ether;
1397680d1b0SBill Paul 	char local_host[MAXHOSTNAMELEN];
1407680d1b0SBill Paul #ifdef YP
1417680d1b0SBill Paul 	char *result;
1427680d1b0SBill Paul 	int resultlen;
1437680d1b0SBill Paul 	char *ether_a;
1447680d1b0SBill Paul 	char *yp_domain;
1457680d1b0SBill Paul #endif
1467680d1b0SBill Paul 	if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
1477680d1b0SBill Paul 		return (1);
1487680d1b0SBill Paul 
1497680d1b0SBill Paul 	while (fgets(buf,BUFSIZ,fp)) {
1507680d1b0SBill Paul 		if (buf[0] == '#')
1517680d1b0SBill Paul 			continue;
1527680d1b0SBill Paul #ifdef YP
1537680d1b0SBill Paul 		if (buf[0] == '+') {
1547680d1b0SBill Paul 			if (yp_get_default_domain(&yp_domain))
1551e890b05SBill Paul 				continue;
1567680d1b0SBill Paul 			ether_a = ether_ntoa(e);
1577680d1b0SBill Paul 			if (yp_match(yp_domain, "ethers.byaddr", ether_a,
1587680d1b0SBill Paul 				strlen(ether_a), &result, &resultlen)) {
1591e890b05SBill Paul 				continue;
1607680d1b0SBill Paul 			}
1611e890b05SBill Paul 			strncpy((char *)&buf, result, resultlen);
1627680d1b0SBill Paul 				free(result);
1637680d1b0SBill Paul 		}
1647680d1b0SBill Paul #endif
1657680d1b0SBill Paul 		if (!ether_line(&buf, &local_ether, &local_host)) {
1667680d1b0SBill Paul 			if (!bcmp((char *)&local_ether.octet[0],
1677680d1b0SBill Paul 				(char *)&e->octet[0], 6)) {
1687680d1b0SBill Paul 			/* We have a match */
1697680d1b0SBill Paul 				strcpy(hostname, (char *)&local_host);
1707680d1b0SBill Paul 				fclose(fp);
1717680d1b0SBill Paul 				return(0);
1727680d1b0SBill Paul 			}
1737680d1b0SBill Paul 		}
1747680d1b0SBill Paul 	}
1757680d1b0SBill Paul 	fclose(fp);
1767680d1b0SBill Paul 	return (1);
1777680d1b0SBill Paul }
1787680d1b0SBill Paul 
1797680d1b0SBill Paul /*
1807680d1b0SBill Paul  * Map a hostname to an ethernet address using /etc/ethers or
1817680d1b0SBill Paul  * NIS/YP.
1827680d1b0SBill Paul  */
1837680d1b0SBill Paul int ether_hostton(hostname, e)
1847680d1b0SBill Paul 	char *hostname;
1857680d1b0SBill Paul 	struct ether_addr *e;
1867680d1b0SBill Paul {
1877680d1b0SBill Paul 	FILE *fp;
1887680d1b0SBill Paul 	char buf[BUFSIZ];
1897680d1b0SBill Paul 	struct ether_addr local_ether;
1907680d1b0SBill Paul 	char local_host[MAXHOSTNAMELEN];
1917680d1b0SBill Paul #ifdef YP
1927680d1b0SBill Paul 	char *result;
1937680d1b0SBill Paul 	int resultlen;
1947680d1b0SBill Paul 	char *yp_domain;
1957680d1b0SBill Paul #endif
1967680d1b0SBill Paul 	if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
1977680d1b0SBill Paul 		return (1);
1987680d1b0SBill Paul 
1997680d1b0SBill Paul 	while (fgets(buf,BUFSIZ,fp)) {
2007680d1b0SBill Paul 		if (buf[0] == '#')
2017680d1b0SBill Paul 			continue;
2027680d1b0SBill Paul #ifdef YP
2037680d1b0SBill Paul 		if (buf[0] == '+') {
2047680d1b0SBill Paul 			if (yp_get_default_domain(&yp_domain))
2051e890b05SBill Paul 				continue;
2067680d1b0SBill Paul 			if (yp_match(yp_domain, "ethers.byname", hostname,
2077680d1b0SBill Paul 				strlen(hostname), &result, &resultlen)) {
2081e890b05SBill Paul 				continue;
2097680d1b0SBill Paul 			}
2101e890b05SBill Paul 			strncpy((char *)&buf, result, resultlen);
2117680d1b0SBill Paul 			free(result);
2127680d1b0SBill Paul 		}
2137680d1b0SBill Paul #endif
2147680d1b0SBill Paul 		if (!ether_line(&buf, &local_ether, &local_host)) {
2157680d1b0SBill Paul 			if (!strcmp(hostname, (char *)&local_host)) {
2167680d1b0SBill Paul 				/* We have a match */
2177680d1b0SBill Paul 				bcopy((char *)&local_ether.octet[0],
2187680d1b0SBill Paul 					(char *)&e->octet[0], 6);
2197680d1b0SBill Paul 				fclose(fp);
2207680d1b0SBill Paul 				return(0);
2217680d1b0SBill Paul 			}
2227680d1b0SBill Paul 		}
2237680d1b0SBill Paul 	}
2247680d1b0SBill Paul 	fclose(fp);
2257680d1b0SBill Paul 	return (1);
2267680d1b0SBill Paul }
227