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 */ 67 int 68 ether_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 */ 86 struct ether_addr * 87 ether_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 104 struct ether_addr * 105 ether_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 */ 115 char * 116 ether_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 127 char * 128 ether_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 */ 138 int 139 ether_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 */ 188 int 189 ether_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