xref: /freebsd/lib/libc/net/ether_addr.c (revision 3951b8e32c209792888f07b4511810e03ac61278)
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  *
383951b8e3SBill Paul  *	$Id: ether_addr.c,v 1.6 1996/12/10 17:19:09 wollman 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>
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  */
647680d1b0SBill Paul int ether_line(l, e, hostname)
657680d1b0SBill Paul         char *l;
667680d1b0SBill Paul 	struct ether_addr *e;
677680d1b0SBill Paul 	char *hostname;
687680d1b0SBill Paul {
697680d1b0SBill Paul         int i, o[6];
707680d1b0SBill Paul 
717680d1b0SBill Paul         i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2],
727680d1b0SBill Paul                                               &o[3], &o[4], &o[5],
737680d1b0SBill Paul 					      hostname);
747680d1b0SBill Paul 	if (i != 7)
757680d1b0SBill Paul                 return (i);
767680d1b0SBill Paul 
777680d1b0SBill Paul         for (i=0; i<6; i++)
787680d1b0SBill Paul                 e->octet[i] = o[i];
797680d1b0SBill Paul         return (0);
807680d1b0SBill Paul }
817680d1b0SBill Paul 
827680d1b0SBill Paul /*
837680d1b0SBill Paul  * Convert an ASCII representation of an ethernet address to
847680d1b0SBill Paul  * binary form.
857680d1b0SBill Paul  */
867680d1b0SBill Paul struct ether_addr *ether_aton(a)
877680d1b0SBill Paul         char *a;
887680d1b0SBill Paul {
897680d1b0SBill Paul         int i;
907680d1b0SBill Paul 	static struct ether_addr o;
9151295a4dSJordan K. Hubbard 	unsigned int o0, o1, o2, o3, o4, o5;
927680d1b0SBill Paul 
9351295a4dSJordan K. Hubbard         i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
9451295a4dSJordan K. Hubbard 
957680d1b0SBill Paul         if (i != 6)
967680d1b0SBill Paul                 return (NULL);
9751295a4dSJordan K. Hubbard 
9851295a4dSJordan K. Hubbard         o.octet[0]=o0;
9951295a4dSJordan K. Hubbard 	o.octet[1]=o1;
10051295a4dSJordan K. Hubbard 	o.octet[2]=o2;
10151295a4dSJordan K. Hubbard 	o.octet[3]=o3;
10251295a4dSJordan K. Hubbard 	o.octet[4]=o4;
10351295a4dSJordan K. Hubbard 	o.octet[5]=o5;
10451295a4dSJordan K. Hubbard 
1057680d1b0SBill Paul         return ((struct ether_addr *)&o);
1067680d1b0SBill Paul }
1077680d1b0SBill Paul 
1087680d1b0SBill Paul /*
1097680d1b0SBill Paul  * Convert a binary representation of an ethernet address to
1107680d1b0SBill Paul  * an ASCII string.
1117680d1b0SBill Paul  */
1127680d1b0SBill Paul char *ether_ntoa(n)
1137680d1b0SBill Paul         struct ether_addr *n;
1147680d1b0SBill Paul {
1157680d1b0SBill Paul         int i;
1167680d1b0SBill Paul 	static char a[18];
1177680d1b0SBill Paul 
1187680d1b0SBill Paul         i = sprintf(a,"%x:%x:%x:%x:%x:%x",n->octet[0],n->octet[1],n->octet[2],
1197680d1b0SBill Paul                                           n->octet[3],n->octet[4],n->octet[5]);
1207680d1b0SBill Paul         if (i < 11)
1217680d1b0SBill Paul                 return (NULL);
1227680d1b0SBill Paul         return ((char *)&a);
1237680d1b0SBill Paul }
1247680d1b0SBill Paul 
1257680d1b0SBill Paul /*
1267680d1b0SBill Paul  * Map an ethernet address to a hostname. Use either /etc/ethers or
1277680d1b0SBill Paul  * NIS/YP.
1287680d1b0SBill Paul  */
1297680d1b0SBill Paul 
1307680d1b0SBill Paul int ether_ntohost(hostname, e)
1317680d1b0SBill Paul 	char *hostname;
1327680d1b0SBill Paul 	struct ether_addr *e;
1337680d1b0SBill Paul {
1347680d1b0SBill Paul 	FILE *fp;
1353951b8e3SBill Paul 	char buf[BUFSIZ + 2];
1367680d1b0SBill Paul 	struct ether_addr local_ether;
1377680d1b0SBill Paul 	char local_host[MAXHOSTNAMELEN];
1387680d1b0SBill Paul #ifdef YP
1397680d1b0SBill Paul 	char *result;
1407680d1b0SBill Paul 	int resultlen;
1417680d1b0SBill Paul 	char *ether_a;
1427680d1b0SBill Paul 	char *yp_domain;
1437680d1b0SBill Paul #endif
1447680d1b0SBill Paul 	if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
1457680d1b0SBill Paul 		return (1);
1467680d1b0SBill Paul 
1477680d1b0SBill Paul 	while (fgets(buf,BUFSIZ,fp)) {
1487680d1b0SBill Paul 		if (buf[0] == '#')
1497680d1b0SBill Paul 			continue;
1507680d1b0SBill Paul #ifdef YP
1517680d1b0SBill Paul 		if (buf[0] == '+') {
1527680d1b0SBill Paul 			if (yp_get_default_domain(&yp_domain))
1531e890b05SBill Paul 				continue;
1547680d1b0SBill Paul 			ether_a = ether_ntoa(e);
1557680d1b0SBill Paul 			if (yp_match(yp_domain, "ethers.byaddr", ether_a,
1567680d1b0SBill Paul 				strlen(ether_a), &result, &resultlen)) {
1571e890b05SBill Paul 				continue;
1587680d1b0SBill Paul 			}
1592696fe9cSJordan K. Hubbard 			strncpy(buf, result, resultlen);
1603951b8e3SBill Paul 			buf[resultlen] = '\0';
1617680d1b0SBill Paul 			free(result);
1627680d1b0SBill Paul 		}
1637680d1b0SBill Paul #endif
1642696fe9cSJordan K. Hubbard 		if (!ether_line(buf, &local_ether, local_host)) {
1657680d1b0SBill Paul 			if (!bcmp((char *)&local_ether.octet[0],
1667680d1b0SBill Paul 				(char *)&e->octet[0], 6)) {
1677680d1b0SBill Paul 			/* We have a match */
1682696fe9cSJordan K. Hubbard 				strcpy(hostname, local_host);
1697680d1b0SBill Paul 				fclose(fp);
1707680d1b0SBill Paul 				return(0);
1717680d1b0SBill Paul 			}
1727680d1b0SBill Paul 		}
1737680d1b0SBill Paul 	}
1747680d1b0SBill Paul 	fclose(fp);
1757680d1b0SBill Paul 	return (1);
1767680d1b0SBill Paul }
1777680d1b0SBill Paul 
1787680d1b0SBill Paul /*
1797680d1b0SBill Paul  * Map a hostname to an ethernet address using /etc/ethers or
1807680d1b0SBill Paul  * NIS/YP.
1817680d1b0SBill Paul  */
1827680d1b0SBill Paul int ether_hostton(hostname, e)
1837680d1b0SBill Paul 	char *hostname;
1847680d1b0SBill Paul 	struct ether_addr *e;
1857680d1b0SBill Paul {
1867680d1b0SBill Paul 	FILE *fp;
1873951b8e3SBill Paul 	char buf[BUFSIZ + 2];
1887680d1b0SBill Paul 	struct ether_addr local_ether;
1897680d1b0SBill Paul 	char local_host[MAXHOSTNAMELEN];
1907680d1b0SBill Paul #ifdef YP
1917680d1b0SBill Paul 	char *result;
1927680d1b0SBill Paul 	int resultlen;
1937680d1b0SBill Paul 	char *yp_domain;
1947680d1b0SBill Paul #endif
1957680d1b0SBill Paul 	if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
1967680d1b0SBill Paul 		return (1);
1977680d1b0SBill Paul 
1987680d1b0SBill Paul 	while (fgets(buf,BUFSIZ,fp)) {
1997680d1b0SBill Paul 		if (buf[0] == '#')
2007680d1b0SBill Paul 			continue;
2017680d1b0SBill Paul #ifdef YP
2027680d1b0SBill Paul 		if (buf[0] == '+') {
2037680d1b0SBill Paul 			if (yp_get_default_domain(&yp_domain))
2041e890b05SBill Paul 				continue;
2057680d1b0SBill Paul 			if (yp_match(yp_domain, "ethers.byname", hostname,
2067680d1b0SBill Paul 				strlen(hostname), &result, &resultlen)) {
2071e890b05SBill Paul 				continue;
2087680d1b0SBill Paul 			}
2092696fe9cSJordan K. Hubbard 			strncpy(buf, result, resultlen);
2103951b8e3SBill Paul 			buf[resultlen] = '\0';
2117680d1b0SBill Paul 			free(result);
2127680d1b0SBill Paul 		}
2137680d1b0SBill Paul #endif
2142696fe9cSJordan K. Hubbard 		if (!ether_line(buf, &local_ether, local_host)) {
2152696fe9cSJordan K. Hubbard 			if (!strcmp(hostname, 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