1 /* 2 * Copyright 2004 The Aerospace Corporation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions, and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of The Aerospace Corporation may not be used to endorse or 14 * promote products derived from this software. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * Copyright (c) 1995 29 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 1. Redistributions of source code must retain the above copyright 35 * notice, this list of conditions and the following disclaimer. 36 * 2. Redistributions in binary form must reproduce the above copyright 37 * notice, this list of conditions and the following disclaimer in the 38 * documentation and/or other materials provided with the distribution. 39 * 3. All advertising materials mentioning features or use of this software 40 * must display the following acknowledgement: 41 * This product includes software developed by Bill Paul. 42 * 4. Neither the name of the author nor the names of any co-contributors 43 * may be used to endorse or promote products derived from this software 44 * without specific prior written permission. 45 * 46 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 56 * SUCH DAMAGE. 57 * 58 * EUI-64 conversion and lookup routines 59 * 60 * 61 * Converted from ether_addr.c rev 62 * FreeBSD: src/lib/libc/net/eui64.c,v 1.15 2002/04/08 07:51:10 ru Exp 63 * by Brooks Davis 64 * 65 * Written by Bill Paul <wpaul@ctr.columbia.edu> 66 * Center for Telecommunications Research 67 * Columbia University, New York City 68 * 69 * $DragonFly: src/lib/libc/net/eui64.c,v 1.1 2004/09/23 06:33:04 simokawa Exp $ 70 */ 71 72 #include <sys/cdefs.h> 73 #ifdef __FBSDID__ 74 __FBSDID("$FreeBSD: src/lib/libc/net/eui64.c,v 1.2 2004/06/01 19:30:13 brooks Exp $"); 75 #endif 76 77 #include <stdio.h> 78 #include <paths.h> 79 #include <sys/types.h> 80 #include <sys/eui64.h> 81 #include <string.h> 82 #include <stdlib.h> 83 #include <sys/param.h> 84 #ifdef YP 85 #include <rpc/rpc.h> 86 #include <rpcsvc/yp_prot.h> 87 #include <rpcsvc/ypclnt.h> 88 #endif 89 90 #ifndef _PATH_EUI64 91 #define _PATH_EUI64 "/etc/eui64" 92 #endif 93 94 static int eui64_line(const char *l, struct eui64 *e, char *hostname, 95 size_t len); 96 97 /* 98 * Parse a string of text containing an EUI-64 and hostname 99 * and separate it into its component parts. 100 */ 101 static int 102 eui64_line(const char *l, struct eui64 *e, char *hostname, size_t len) 103 { 104 char *line, *linehead, *cur; 105 106 linehead = strdup(l); 107 if (linehead == NULL) 108 return (-1); 109 line = linehead; 110 111 /* Find and parse the EUI64 */ 112 while ((cur = strsep(&line, " \t\r\n")) != NULL) { 113 if (*cur != '\0') { 114 if (eui64_aton(cur, e) == 0) 115 break; 116 else 117 goto bad; 118 } 119 } 120 121 /* Find the hostname */ 122 while ((cur = strsep(&line, " \t\r\n")) != NULL) { 123 if (*cur != '\0') { 124 if (strlcpy(hostname, cur, len) <= len) 125 break; 126 else 127 goto bad; 128 } 129 } 130 131 /* Make sure what remains is either whitespace or a comment */ 132 while ((cur = strsep(&line, " \t\r\n")) != NULL) { 133 if (*cur == '#') 134 break; 135 if (*cur != '\0') 136 goto bad; 137 } 138 139 return (0); 140 141 bad: 142 free(linehead); 143 return (-1); 144 } 145 146 /* 147 * Convert an ASCII representation of an EUI-64 to binary form. 148 */ 149 int 150 eui64_aton(const char *a, struct eui64 *e) 151 { 152 int i; 153 unsigned int o0, o1, o2, o3, o4, o5, o6, o7; 154 155 /* canonical form */ 156 i = sscanf(a, "%x-%x-%x-%x-%x-%x-%x-%x", 157 &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7); 158 if (i == EUI64_LEN) 159 goto good; 160 /* ethernet form */ 161 i = sscanf(a, "%x:%x:%x:%x:%x:%x:%x:%x", 162 &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7); 163 if (i == EUI64_LEN) 164 goto good; 165 /* classic fwcontrol/dconschat form */ 166 i = sscanf(a, "0x%2x%2x%2x%2x%2x%2x%2x%2x", 167 &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7); 168 if (i == EUI64_LEN) 169 goto good; 170 /* MAC format (-) */ 171 i = sscanf(a, "%x-%x-%x-%x-%x-%x", 172 &o0, &o1, &o2, &o5, &o6, &o7); 173 if (i == 6) { 174 o3 = 0xff; 175 o4 = 0xfe; 176 goto good; 177 } 178 /* MAC format (:) */ 179 i = sscanf(a, "%x:%x:%x:%x:%x:%x", 180 &o0, &o1, &o2, &o5, &o6, &o7); 181 if (i == 6) { 182 o3 = 0xff; 183 o4 = 0xfe; 184 goto good; 185 } 186 187 return (-1); 188 189 good: 190 e->octet[0]=o0; 191 e->octet[1]=o1; 192 e->octet[2]=o2; 193 e->octet[3]=o3; 194 e->octet[4]=o4; 195 e->octet[5]=o5; 196 e->octet[6]=o6; 197 e->octet[7]=o7; 198 199 return (0); 200 } 201 202 /* 203 * Convert a binary representation of an EUI-64 to an ASCII string. 204 */ 205 int 206 eui64_ntoa(const struct eui64 *id, char *a, size_t len) 207 { 208 int i; 209 210 i = snprintf(a, len, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", 211 id->octet[0], id->octet[1], id->octet[2], id->octet[3], 212 id->octet[4], id->octet[5], id->octet[6], id->octet[7]); 213 if (i < 23 || i >= len) 214 return (-1); 215 return (0); 216 } 217 218 /* 219 * Map an EUI-64 to a hostname. Use either /etc/eui64 or NIS/YP. 220 */ 221 int 222 eui64_ntohost(char *hostname, size_t len, const struct eui64 *id) 223 { 224 FILE *fp; 225 char buf[BUFSIZ + 2]; 226 struct eui64 local_eui64; 227 char local_host[MAXHOSTNAMELEN]; 228 #ifdef YP 229 char *result; 230 int resultlen; 231 char eui64_a[24]; 232 char *yp_domain; 233 #endif 234 if ((fp = fopen(_PATH_EUI64, "r")) == NULL) 235 return (1); 236 237 while (fgets(buf,BUFSIZ,fp)) { 238 if (buf[0] == '#') 239 continue; 240 #ifdef YP 241 if (buf[0] == '+') { 242 if (yp_get_default_domain(&yp_domain)) 243 continue; 244 eui64_ntoa(id, eui64_a, sizeof(eui64_a)); 245 if (yp_match(yp_domain, "eui64.byid", eui64_a, 246 strlen(eui64_a), &result, &resultlen)) { 247 continue; 248 } 249 strncpy(buf, result, resultlen); 250 buf[resultlen] = '\0'; 251 free(result); 252 } 253 #endif 254 if (eui64_line(buf, &local_eui64, local_host, 255 sizeof(local_host)) == 0) { 256 if (bcmp(&local_eui64.octet[0], 257 &id->octet[0], EUI64_LEN) == 0) { 258 /* We have a match */ 259 strcpy(hostname, local_host); 260 fclose(fp); 261 return(0); 262 } 263 } 264 } 265 fclose(fp); 266 return (1); 267 } 268 269 /* 270 * Map a hostname to an EUI-64 using /etc/eui64 or NIS/YP. 271 */ 272 int 273 eui64_hostton(const char *hostname, struct eui64 *id) 274 { 275 FILE *fp; 276 char buf[BUFSIZ + 2]; 277 struct eui64 local_eui64; 278 char local_host[MAXHOSTNAMELEN]; 279 #ifdef YP 280 char *result; 281 int resultlen; 282 char *yp_domain; 283 #endif 284 if ((fp = fopen(_PATH_EUI64, "r")) == NULL) 285 return (1); 286 287 while (fgets(buf,BUFSIZ,fp)) { 288 if (buf[0] == '#') 289 continue; 290 #ifdef YP 291 if (buf[0] == '+') { 292 if (yp_get_default_domain(&yp_domain)) 293 continue; 294 if (yp_match(yp_domain, "eui64.byname", hostname, 295 strlen(hostname), &result, &resultlen)) { 296 continue; 297 } 298 strncpy(buf, result, resultlen); 299 buf[resultlen] = '\0'; 300 free(result); 301 } 302 #endif 303 if (eui64_line(buf, &local_eui64, local_host, 304 sizeof(local_host)) == 0) { 305 if (strcmp(hostname, local_host) == 0) { 306 /* We have a match */ 307 bcopy(&local_eui64, id, sizeof(struct eui64)); 308 fclose(fp); 309 return(0); 310 } 311 } 312 } 313 fclose(fp); 314 return (1); 315 } 316