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