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