17576Swpaul/* 2169520Srwatson * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>. 3169522Srwatson * Copyright (c) 2007 Robert N. M. Watson 4169520Srwatson * All rights reserved. 57576Swpaul * 67576Swpaul * Redistribution and use in source and binary forms, with or without 77576Swpaul * modification, are permitted provided that the following conditions 87576Swpaul * are met: 97576Swpaul * 1. Redistributions of source code must retain the above copyright 107576Swpaul * notice, this list of conditions and the following disclaimer. 117576Swpaul * 2. Redistributions in binary form must reproduce the above copyright 127576Swpaul * notice, this list of conditions and the following disclaimer in the 137576Swpaul * documentation and/or other materials provided with the distribution. 147576Swpaul * 3. All advertising materials mentioning features or use of this software 157576Swpaul * must display the following acknowledgement: 167576Swpaul * This product includes software developed by Bill Paul. 177576Swpaul * 4. Neither the name of the author nor the names of any co-contributors 187576Swpaul * may be used to endorse or promote products derived from this software 197576Swpaul * without specific prior written permission. 207576Swpaul * 217576Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 227576Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 237576Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 247576Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 257576Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 267576Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 277576Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 287576Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 297576Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 307576Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 317576Swpaul * SUCH DAMAGE. 327576Swpaul * 337576Swpaul * ethernet address conversion and lookup routines 347576Swpaul * 357576Swpaul * Written by Bill Paul <wpaul@ctr.columbia.edu> 367576Swpaul * Center for Telecommunications Research 377576Swpaul * Columbia University, New York City 387576Swpaul */ 397576Swpaul 4091725Seric#include <sys/cdefs.h> 4191725Seric__FBSDID("$FreeBSD$"); 427576Swpaul 437576Swpaul#include <sys/types.h> 447576Swpaul#include <sys/param.h> 457576Swpaul#include <sys/socket.h> 46169520Srwatson 4720288Swollman#include <net/ethernet.h> 48169520Srwatson 497576Swpaul#ifdef YP 507576Swpaul#include <rpc/rpc.h> 517576Swpaul#include <rpcsvc/yp_prot.h> 527576Swpaul#include <rpcsvc/ypclnt.h> 537576Swpaul#endif 547576Swpaul 55169520Srwatson#include <paths.h> 56169520Srwatson#include <stdio.h> 57169520Srwatson#include <stdlib.h> 58169520Srwatson#include <string.h> 59169520Srwatson 607576Swpaul#ifndef _PATH_ETHERS 61169520Srwatson#define _PATH_ETHERS "/etc/ethers" 627576Swpaul#endif 637576Swpaul 647576Swpaul/* 65169520Srwatson * Parse a string of text containing an ethernet address and hostname and 66169520Srwatson * separate it into its component parts. 677576Swpaul */ 6891725Sericint 69169520Srwatsonether_line(const char *l, struct ether_addr *e, char *hostname) 707576Swpaul{ 71169522Srwatson int i, o[6]; 727576Swpaul 73169522Srwatson i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2], &o[3], 74169520Srwatson &o[4], &o[5], hostname); 757576Swpaul if (i != 7) 76169522Srwatson return (i); 77169522Srwatson for (i=0; i<6; i++) 78169522Srwatson e->octet[i] = o[i]; 79169522Srwatson return (0); 807576Swpaul} 817576Swpaul 827576Swpaul/* 83169520Srwatson * Convert an ASCII representation of an ethernet address to binary form. 847576Swpaul */ 85169520Srwatsonstruct ether_addr * 86169522Srwatsonether_aton_r(const char *a, struct ether_addr *e) 877576Swpaul{ 88169522Srwatson int i; 8917141Sjkh unsigned int o0, o1, o2, o3, o4, o5; 907576Swpaul 91169522Srwatson i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5); 92169522Srwatson if (i != 6) 93169522Srwatson return (NULL); 94169522Srwatson e->octet[0]=o0; 95169522Srwatson e->octet[1]=o1; 96169522Srwatson e->octet[2]=o2; 97169522Srwatson e->octet[3]=o3; 98169522Srwatson e->octet[4]=o4; 99169522Srwatson e->octet[5]=o5; 100169522Srwatson return (e); 1017576Swpaul} 1027576Swpaul 103169522Srwatsonstruct ether_addr * 104169522Srwatsonether_aton(const char *a) 105169522Srwatson{ 106169522Srwatson static struct ether_addr e; 107169522Srwatson 108169522Srwatson return (ether_aton_r(a, &e)); 109169522Srwatson} 110169522Srwatson 1117576Swpaul/* 112169520Srwatson * Convert a binary representation of an ethernet address to an ASCII string. 1137576Swpaul */ 114169520Srwatsonchar * 115169522Srwatsonether_ntoa_r(const struct ether_addr *n, char *a) 116169522Srwatson{ 117169522Srwatson int i; 118169522Srwatson 119169522Srwatson i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0], 120169522Srwatson n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]); 121169522Srwatson if (i < 17) 122169522Srwatson return (NULL); 123169522Srwatson return (a); 124169522Srwatson} 125169522Srwatson 126169522Srwatsonchar * 127169520Srwatsonether_ntoa(const struct ether_addr *n) 1287576Swpaul{ 1297576Swpaul static char a[18]; 1307576Swpaul 131169522Srwatson return (ether_ntoa_r(n, a)); 1327576Swpaul} 1337576Swpaul 1347576Swpaul/* 135169520Srwatson * Map an ethernet address to a hostname. Use either /etc/ethers or NIS/YP. 1367576Swpaul */ 13791725Sericint 138169520Srwatsonether_ntohost(char *hostname, const struct ether_addr *e) 1397576Swpaul{ 1407576Swpaul FILE *fp; 14120953Swpaul char buf[BUFSIZ + 2]; 1427576Swpaul struct ether_addr local_ether; 1437576Swpaul char local_host[MAXHOSTNAMELEN]; 1447576Swpaul#ifdef YP 1457576Swpaul char *result; 1467576Swpaul int resultlen; 1477576Swpaul char *ether_a; 1487576Swpaul char *yp_domain; 1497576Swpaul#endif 150169520Srwatson 1517576Swpaul if ((fp = fopen(_PATH_ETHERS, "r")) == NULL) 1527576Swpaul return (1); 1537576Swpaul while (fgets(buf,BUFSIZ,fp)) { 1547576Swpaul if (buf[0] == '#') 1557576Swpaul continue; 1567576Swpaul#ifdef YP 1577576Swpaul if (buf[0] == '+') { 1587576Swpaul if (yp_get_default_domain(&yp_domain)) 1599978Swpaul continue; 1607576Swpaul ether_a = ether_ntoa(e); 1617576Swpaul if (yp_match(yp_domain, "ethers.byaddr", ether_a, 162169520Srwatson strlen(ether_a), &result, &resultlen)) { 1639978Swpaul continue; 1647576Swpaul } 16520164Sjkh strncpy(buf, result, resultlen); 16620953Swpaul buf[resultlen] = '\0'; 16720953Swpaul free(result); 1687576Swpaul } 1697576Swpaul#endif 17020164Sjkh if (!ether_line(buf, &local_ether, local_host)) { 1717576Swpaul if (!bcmp((char *)&local_ether.octet[0], 172169520Srwatson (char *)&e->octet[0], 6)) { 173169520Srwatson /* We have a match. */ 17420164Sjkh strcpy(hostname, local_host); 1757576Swpaul fclose(fp); 1767576Swpaul return(0); 1777576Swpaul } 1787576Swpaul } 1797576Swpaul } 1807576Swpaul fclose(fp); 1817576Swpaul return (1); 1827576Swpaul} 1837576Swpaul 1847576Swpaul/* 185169520Srwatson * Map a hostname to an ethernet address using /etc/ethers or NIS/YP. 1867576Swpaul */ 18791725Sericint 188169520Srwatsonether_hostton(const char *hostname, struct ether_addr *e) 1897576Swpaul{ 1907576Swpaul FILE *fp; 19120953Swpaul char buf[BUFSIZ + 2]; 1927576Swpaul struct ether_addr local_ether; 1937576Swpaul char local_host[MAXHOSTNAMELEN]; 1947576Swpaul#ifdef YP 1957576Swpaul char *result; 1967576Swpaul int resultlen; 1977576Swpaul char *yp_domain; 1987576Swpaul#endif 199169520Srwatson 2007576Swpaul if ((fp = fopen(_PATH_ETHERS, "r")) == NULL) 2017576Swpaul return (1); 2027576Swpaul while (fgets(buf,BUFSIZ,fp)) { 2037576Swpaul if (buf[0] == '#') 2047576Swpaul continue; 2057576Swpaul#ifdef YP 2067576Swpaul if (buf[0] == '+') { 2077576Swpaul if (yp_get_default_domain(&yp_domain)) 2089978Swpaul continue; 2097576Swpaul if (yp_match(yp_domain, "ethers.byname", hostname, 210169520Srwatson strlen(hostname), &result, &resultlen)) { 2119978Swpaul continue; 2127576Swpaul } 21320164Sjkh strncpy(buf, result, resultlen); 21420953Swpaul buf[resultlen] = '\0'; 2159978Swpaul free(result); 2167576Swpaul } 2177576Swpaul#endif 21820164Sjkh if (!ether_line(buf, &local_ether, local_host)) { 21920164Sjkh if (!strcmp(hostname, local_host)) { 220169520Srwatson /* We have a match. */ 2217576Swpaul bcopy((char *)&local_ether.octet[0], 222169520Srwatson (char *)&e->octet[0], 6); 2237576Swpaul fclose(fp); 2247576Swpaul return(0); 2257576Swpaul } 2267576Swpaul } 2277576Swpaul } 2287576Swpaul fclose(fp); 2297576Swpaul return (1); 2307576Swpaul} 231