1/* 2 * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>. 3 * Copyright (c) 2007 Robert N. M. Watson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Bill Paul. 17 * 4. Neither the name of the author nor the names of any co-contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * ethernet address conversion and lookup routines 34 * 35 * Written by Bill Paul <wpaul@ctr.columbia.edu> 36 * Center for Telecommunications Research 37 * Columbia University, New York City 38 */ 39 40#include <sys/cdefs.h> 41__FBSDID("$FreeBSD$"); 42 43#include <sys/param.h> 44#include <sys/socket.h> 45 46#include <net/ethernet.h> 47 48#ifdef YP 49#include <rpc/rpc.h> 50#include <rpcsvc/yp_prot.h> 51#include <rpcsvc/ypclnt.h> 52#endif 53 54#include <paths.h> 55#include <stdio.h> 56#include <stdlib.h> 57#include <string.h> 58 59#ifndef _PATH_ETHERS 60#define _PATH_ETHERS "/etc/ethers" 61#endif 62 63/* 64 * Parse a string of text containing an ethernet address and hostname and 65 * separate it into its component parts. 66 */ 67int 68ether_line(const char *l, struct ether_addr *e, char *hostname) 69{ 70 int i, o[6]; 71 72 i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2], &o[3], 73 &o[4], &o[5], hostname); 74 if (i == 7) { 75 for (i = 0; i < 6; i++) 76 e->octet[i] = o[i]; 77 return (0); 78 } else { 79 return (-1); 80 } 81} 82 83/* 84 * Convert an ASCII representation of an ethernet address to binary form. 85 */ 86struct ether_addr * 87ether_aton_r(const char *a, struct ether_addr *e) 88{ 89 int i; 90 unsigned int o0, o1, o2, o3, o4, o5; 91 92 i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5); 93 if (i != 6) 94 return (NULL); 95 e->octet[0]=o0; 96 e->octet[1]=o1; 97 e->octet[2]=o2; 98 e->octet[3]=o3; 99 e->octet[4]=o4; 100 e->octet[5]=o5; 101 return (e); 102} 103 104struct ether_addr * 105ether_aton(const char *a) 106{ 107 static struct ether_addr e; 108 109 return (ether_aton_r(a, &e)); 110} 111 112/* 113 * Convert a binary representation of an ethernet address to an ASCII string. 114 */ 115char * 116ether_ntoa_r(const struct ether_addr *n, char *a) 117{ 118 int i; 119 120 i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0], 121 n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]); 122 if (i < 17) 123 return (NULL); 124 return (a); 125} 126 127char * 128ether_ntoa(const struct ether_addr *n) 129{ 130 static char a[18]; 131 132 return (ether_ntoa_r(n, a)); 133} 134 135/* 136 * Map an ethernet address to a hostname. Use either /etc/ethers or NIS/YP. 137 */ 138int 139ether_ntohost(char *hostname, const struct ether_addr *e) 140{ 141 FILE *fp; 142 char buf[BUFSIZ + 2]; 143 struct ether_addr local_ether; 144 char local_host[MAXHOSTNAMELEN]; 145#ifdef YP 146 char *result; 147 int resultlen; 148 char *ether_a; 149 char *yp_domain; 150#endif 151 152 if ((fp = fopen(_PATH_ETHERS, "re")) == NULL) 153 return (1); 154 while (fgets(buf,BUFSIZ,fp)) { 155 if (buf[0] == '#') 156 continue; 157#ifdef YP 158 if (buf[0] == '+') { 159 if (yp_get_default_domain(&yp_domain)) 160 continue; 161 ether_a = ether_ntoa(e); 162 if (yp_match(yp_domain, "ethers.byaddr", ether_a, 163 strlen(ether_a), &result, &resultlen)) { 164 continue; 165 } 166 strncpy(buf, result, resultlen); 167 buf[resultlen] = '\0'; 168 free(result); 169 } 170#endif 171 if (!ether_line(buf, &local_ether, local_host)) { 172 if (!bcmp((char *)&local_ether.octet[0], 173 (char *)&e->octet[0], 6)) { 174 /* We have a match. */ 175 strcpy(hostname, local_host); 176 fclose(fp); 177 return(0); 178 } 179 } 180 } 181 fclose(fp); 182 return (1); 183} 184 185/* 186 * Map a hostname to an ethernet address using /etc/ethers or NIS/YP. 187 */ 188int 189ether_hostton(const char *hostname, struct ether_addr *e) 190{ 191 FILE *fp; 192 char buf[BUFSIZ + 2]; 193 struct ether_addr local_ether; 194 char local_host[MAXHOSTNAMELEN]; 195#ifdef YP 196 char *result; 197 int resultlen; 198 char *yp_domain; 199#endif 200 201 if ((fp = fopen(_PATH_ETHERS, "re")) == NULL) 202 return (1); 203 while (fgets(buf,BUFSIZ,fp)) { 204 if (buf[0] == '#') 205 continue; 206#ifdef YP 207 if (buf[0] == '+') { 208 if (yp_get_default_domain(&yp_domain)) 209 continue; 210 if (yp_match(yp_domain, "ethers.byname", hostname, 211 strlen(hostname), &result, &resultlen)) { 212 continue; 213 } 214 strncpy(buf, result, resultlen); 215 buf[resultlen] = '\0'; 216 free(result); 217 } 218#endif 219 if (!ether_line(buf, &local_ether, local_host)) { 220 if (!strcmp(hostname, local_host)) { 221 /* We have a match. */ 222 bcopy((char *)&local_ether.octet[0], 223 (char *)&e->octet[0], 6); 224 fclose(fp); 225 return(0); 226 } 227 } 228 } 229 fclose(fp); 230 return (1); 231} 232