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); 75264592Sjmmv if (i == 7) { 76264592Sjmmv for (i = 0; i < 6; i++) 77264592Sjmmv e->octet[i] = o[i]; 78264592Sjmmv return (0); 79264592Sjmmv } else { 80264592Sjmmv return (-1); 81264592Sjmmv } 827576Swpaul} 837576Swpaul 847576Swpaul/* 85169520Srwatson * Convert an ASCII representation of an ethernet address to binary form. 867576Swpaul */ 87169520Srwatsonstruct ether_addr * 88169522Srwatsonether_aton_r(const char *a, struct ether_addr *e) 897576Swpaul{ 90169522Srwatson int i; 9117141Sjkh unsigned int o0, o1, o2, o3, o4, o5; 927576Swpaul 93169522Srwatson i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5); 94169522Srwatson if (i != 6) 95169522Srwatson return (NULL); 96169522Srwatson e->octet[0]=o0; 97169522Srwatson e->octet[1]=o1; 98169522Srwatson e->octet[2]=o2; 99169522Srwatson e->octet[3]=o3; 100169522Srwatson e->octet[4]=o4; 101169522Srwatson e->octet[5]=o5; 102169522Srwatson return (e); 1037576Swpaul} 1047576Swpaul 105169522Srwatsonstruct ether_addr * 106169522Srwatsonether_aton(const char *a) 107169522Srwatson{ 108169522Srwatson static struct ether_addr e; 109169522Srwatson 110169522Srwatson return (ether_aton_r(a, &e)); 111169522Srwatson} 112169522Srwatson 1137576Swpaul/* 114169520Srwatson * Convert a binary representation of an ethernet address to an ASCII string. 1157576Swpaul */ 116169520Srwatsonchar * 117169522Srwatsonether_ntoa_r(const struct ether_addr *n, char *a) 118169522Srwatson{ 119169522Srwatson int i; 120169522Srwatson 121169522Srwatson i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0], 122169522Srwatson n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]); 123169522Srwatson if (i < 17) 124169522Srwatson return (NULL); 125169522Srwatson return (a); 126169522Srwatson} 127169522Srwatson 128169522Srwatsonchar * 129169520Srwatsonether_ntoa(const struct ether_addr *n) 1307576Swpaul{ 1317576Swpaul static char a[18]; 1327576Swpaul 133169522Srwatson return (ether_ntoa_r(n, a)); 1347576Swpaul} 1357576Swpaul 1367576Swpaul/* 137169520Srwatson * Map an ethernet address to a hostname. Use either /etc/ethers or NIS/YP. 1387576Swpaul */ 13991725Sericint 140169520Srwatsonether_ntohost(char *hostname, const struct ether_addr *e) 1417576Swpaul{ 1427576Swpaul FILE *fp; 14320953Swpaul char buf[BUFSIZ + 2]; 1447576Swpaul struct ether_addr local_ether; 1457576Swpaul char local_host[MAXHOSTNAMELEN]; 1467576Swpaul#ifdef YP 1477576Swpaul char *result; 1487576Swpaul int resultlen; 1497576Swpaul char *ether_a; 1507576Swpaul char *yp_domain; 1517576Swpaul#endif 152169520Srwatson 153254700Sjilles if ((fp = fopen(_PATH_ETHERS, "re")) == NULL) 1547576Swpaul return (1); 1557576Swpaul while (fgets(buf,BUFSIZ,fp)) { 1567576Swpaul if (buf[0] == '#') 1577576Swpaul continue; 1587576Swpaul#ifdef YP 1597576Swpaul if (buf[0] == '+') { 1607576Swpaul if (yp_get_default_domain(&yp_domain)) 1619978Swpaul continue; 1627576Swpaul ether_a = ether_ntoa(e); 1637576Swpaul if (yp_match(yp_domain, "ethers.byaddr", ether_a, 164169520Srwatson strlen(ether_a), &result, &resultlen)) { 1659978Swpaul continue; 1667576Swpaul } 16720164Sjkh strncpy(buf, result, resultlen); 16820953Swpaul buf[resultlen] = '\0'; 16920953Swpaul free(result); 1707576Swpaul } 1717576Swpaul#endif 17220164Sjkh if (!ether_line(buf, &local_ether, local_host)) { 1737576Swpaul if (!bcmp((char *)&local_ether.octet[0], 174169520Srwatson (char *)&e->octet[0], 6)) { 175169520Srwatson /* We have a match. */ 17620164Sjkh strcpy(hostname, local_host); 1777576Swpaul fclose(fp); 1787576Swpaul return(0); 1797576Swpaul } 1807576Swpaul } 1817576Swpaul } 1827576Swpaul fclose(fp); 1837576Swpaul return (1); 1847576Swpaul} 1857576Swpaul 1867576Swpaul/* 187169520Srwatson * Map a hostname to an ethernet address using /etc/ethers or NIS/YP. 1887576Swpaul */ 18991725Sericint 190169520Srwatsonether_hostton(const char *hostname, struct ether_addr *e) 1917576Swpaul{ 1927576Swpaul FILE *fp; 19320953Swpaul char buf[BUFSIZ + 2]; 1947576Swpaul struct ether_addr local_ether; 1957576Swpaul char local_host[MAXHOSTNAMELEN]; 1967576Swpaul#ifdef YP 1977576Swpaul char *result; 1987576Swpaul int resultlen; 1997576Swpaul char *yp_domain; 2007576Swpaul#endif 201169520Srwatson 202254700Sjilles if ((fp = fopen(_PATH_ETHERS, "re")) == NULL) 2037576Swpaul return (1); 2047576Swpaul while (fgets(buf,BUFSIZ,fp)) { 2057576Swpaul if (buf[0] == '#') 2067576Swpaul continue; 2077576Swpaul#ifdef YP 2087576Swpaul if (buf[0] == '+') { 2097576Swpaul if (yp_get_default_domain(&yp_domain)) 2109978Swpaul continue; 2117576Swpaul if (yp_match(yp_domain, "ethers.byname", hostname, 212169520Srwatson strlen(hostname), &result, &resultlen)) { 2139978Swpaul continue; 2147576Swpaul } 21520164Sjkh strncpy(buf, result, resultlen); 21620953Swpaul buf[resultlen] = '\0'; 2179978Swpaul free(result); 2187576Swpaul } 2197576Swpaul#endif 22020164Sjkh if (!ether_line(buf, &local_ether, local_host)) { 22120164Sjkh if (!strcmp(hostname, local_host)) { 222169520Srwatson /* We have a match. */ 2237576Swpaul bcopy((char *)&local_ether.octet[0], 224169520Srwatson (char *)&e->octet[0], 6); 2257576Swpaul fclose(fp); 2267576Swpaul return(0); 2277576Swpaul } 2287576Swpaul } 2297576Swpaul } 2307576Swpaul fclose(fp); 2317576Swpaul return (1); 2327576Swpaul} 233