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