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