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