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/types.h> 44 #include <sys/param.h> 45 #include <sys/socket.h> 46 47 #include <net/ethernet.h> 48 49 #ifdef YP 50 #include <rpc/rpc.h> 51 #include <rpcsvc/yp_prot.h> 52 #include <rpcsvc/ypclnt.h> 53 #endif 54 55 #include <paths.h> 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <string.h> 59 60 #ifndef _PATH_ETHERS 61 #define _PATH_ETHERS "/etc/ethers" 62 #endif 63 64 /* 65 * Parse a string of text containing an ethernet address and hostname and 66 * separate it into its component parts. 67 */ 68 int 69 ether_line(const char *l, struct ether_addr *e, char *hostname) 70 { 71 int i, o[6]; 72 73 i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2], &o[3], 74 &o[4], &o[5], hostname); 75 if (i != 7) 76 return (i); 77 for (i=0; i<6; i++) 78 e->octet[i] = o[i]; 79 return (0); 80 } 81 82 /* 83 * Convert an ASCII representation of an ethernet address to binary form. 84 */ 85 struct ether_addr * 86 ether_aton_r(const char *a, struct ether_addr *e) 87 { 88 int i; 89 unsigned int o0, o1, o2, o3, o4, o5; 90 91 i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5); 92 if (i != 6) 93 return (NULL); 94 e->octet[0]=o0; 95 e->octet[1]=o1; 96 e->octet[2]=o2; 97 e->octet[3]=o3; 98 e->octet[4]=o4; 99 e->octet[5]=o5; 100 return (e); 101 } 102 103 struct ether_addr * 104 ether_aton(const char *a) 105 { 106 static struct ether_addr e; 107 108 return (ether_aton_r(a, &e)); 109 } 110 111 /* 112 * Convert a binary representation of an ethernet address to an ASCII string. 113 */ 114 char * 115 ether_ntoa_r(const struct ether_addr *n, char *a) 116 { 117 int i; 118 119 i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0], 120 n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]); 121 if (i < 17) 122 return (NULL); 123 return (a); 124 } 125 126 char * 127 ether_ntoa(const struct ether_addr *n) 128 { 129 static char a[18]; 130 131 return (ether_ntoa_r(n, a)); 132 } 133 134 /* 135 * Map an ethernet address to a hostname. Use either /etc/ethers or NIS/YP. 136 */ 137 int 138 ether_ntohost(char *hostname, const struct ether_addr *e) 139 { 140 FILE *fp; 141 char buf[BUFSIZ + 2]; 142 struct ether_addr local_ether; 143 char local_host[MAXHOSTNAMELEN]; 144 #ifdef YP 145 char *result; 146 int resultlen; 147 char *ether_a; 148 char *yp_domain; 149 #endif 150 151 if ((fp = fopen(_PATH_ETHERS, "re")) == NULL) 152 return (1); 153 while (fgets(buf,BUFSIZ,fp)) { 154 if (buf[0] == '#') 155 continue; 156 #ifdef YP 157 if (buf[0] == '+') { 158 if (yp_get_default_domain(&yp_domain)) 159 continue; 160 ether_a = ether_ntoa(e); 161 if (yp_match(yp_domain, "ethers.byaddr", ether_a, 162 strlen(ether_a), &result, &resultlen)) { 163 continue; 164 } 165 strncpy(buf, result, resultlen); 166 buf[resultlen] = '\0'; 167 free(result); 168 } 169 #endif 170 if (!ether_line(buf, &local_ether, local_host)) { 171 if (!bcmp((char *)&local_ether.octet[0], 172 (char *)&e->octet[0], 6)) { 173 /* We have a match. */ 174 strcpy(hostname, local_host); 175 fclose(fp); 176 return(0); 177 } 178 } 179 } 180 fclose(fp); 181 return (1); 182 } 183 184 /* 185 * Map a hostname to an ethernet address using /etc/ethers or NIS/YP. 186 */ 187 int 188 ether_hostton(const char *hostname, struct ether_addr *e) 189 { 190 FILE *fp; 191 char buf[BUFSIZ + 2]; 192 struct ether_addr local_ether; 193 char local_host[MAXHOSTNAMELEN]; 194 #ifdef YP 195 char *result; 196 int resultlen; 197 char *yp_domain; 198 #endif 199 200 if ((fp = fopen(_PATH_ETHERS, "re")) == NULL) 201 return (1); 202 while (fgets(buf,BUFSIZ,fp)) { 203 if (buf[0] == '#') 204 continue; 205 #ifdef YP 206 if (buf[0] == '+') { 207 if (yp_get_default_domain(&yp_domain)) 208 continue; 209 if (yp_match(yp_domain, "ethers.byname", hostname, 210 strlen(hostname), &result, &resultlen)) { 211 continue; 212 } 213 strncpy(buf, result, resultlen); 214 buf[resultlen] = '\0'; 215 free(result); 216 } 217 #endif 218 if (!ether_line(buf, &local_ether, local_host)) { 219 if (!strcmp(hostname, local_host)) { 220 /* We have a match. */ 221 bcopy((char *)&local_ether.octet[0], 222 (char *)&e->octet[0], 6); 223 fclose(fp); 224 return(0); 225 } 226 } 227 } 228 fclose(fp); 229 return (1); 230 } 231