17387768eSBrooks Davis /* 2cf754908SBrooks Davis * Copyright 2004 The Aerospace Corporation. All rights reserved. 3cf754908SBrooks Davis * 4cf754908SBrooks Davis * Redistribution and use in source and binary forms, with or without 5cf754908SBrooks Davis * modification, are permitted provided that the following conditions 6cf754908SBrooks Davis * are met: 7cf754908SBrooks Davis * 8cf754908SBrooks Davis * 1. Redistributions of source code must retain the above copyright 9cf754908SBrooks Davis * notice, this list of conditions, and the following disclaimer. 10cf754908SBrooks Davis * 2. Redistributions in binary form must reproduce the above copyright 11cf754908SBrooks Davis * notice, this list of conditions, and the following disclaimer in the 12cf754908SBrooks Davis * documentation and/or other materials provided with the distribution. 13cf754908SBrooks Davis * 3. The name of The Aerospace Corporation may not be used to endorse or 14cf754908SBrooks Davis * promote products derived from this software. 15cf754908SBrooks Davis * 16cf754908SBrooks Davis * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND 17cf754908SBrooks Davis * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18cf754908SBrooks Davis * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19cf754908SBrooks Davis * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE 20cf754908SBrooks Davis * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21cf754908SBrooks Davis * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22cf754908SBrooks Davis * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23cf754908SBrooks Davis * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24cf754908SBrooks Davis * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25cf754908SBrooks Davis * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26cf754908SBrooks Davis * SUCH DAMAGE. 27cf754908SBrooks Davis * 287387768eSBrooks Davis * Copyright (c) 1995 297387768eSBrooks Davis * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 307387768eSBrooks Davis * 317387768eSBrooks Davis * Redistribution and use in source and binary forms, with or without 327387768eSBrooks Davis * modification, are permitted provided that the following conditions 337387768eSBrooks Davis * are met: 347387768eSBrooks Davis * 1. Redistributions of source code must retain the above copyright 357387768eSBrooks Davis * notice, this list of conditions and the following disclaimer. 367387768eSBrooks Davis * 2. Redistributions in binary form must reproduce the above copyright 377387768eSBrooks Davis * notice, this list of conditions and the following disclaimer in the 387387768eSBrooks Davis * documentation and/or other materials provided with the distribution. 397387768eSBrooks Davis * 3. All advertising materials mentioning features or use of this software 407387768eSBrooks Davis * must display the following acknowledgement: 417387768eSBrooks Davis * This product includes software developed by Bill Paul. 427387768eSBrooks Davis * 4. Neither the name of the author nor the names of any co-contributors 437387768eSBrooks Davis * may be used to endorse or promote products derived from this software 447387768eSBrooks Davis * without specific prior written permission. 457387768eSBrooks Davis * 467387768eSBrooks Davis * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 477387768eSBrooks Davis * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 487387768eSBrooks Davis * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 497387768eSBrooks Davis * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 507387768eSBrooks Davis * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 517387768eSBrooks Davis * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 527387768eSBrooks Davis * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 537387768eSBrooks Davis * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 547387768eSBrooks Davis * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 557387768eSBrooks Davis * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 567387768eSBrooks Davis * SUCH DAMAGE. 577387768eSBrooks Davis * 587387768eSBrooks Davis * EUI-64 conversion and lookup routines 597387768eSBrooks Davis * 607387768eSBrooks Davis * 617387768eSBrooks Davis * Converted from ether_addr.c rev 627387768eSBrooks Davis * FreeBSD: src/lib/libc/net/eui64.c,v 1.15 2002/04/08 07:51:10 ru Exp 637387768eSBrooks Davis * by Brooks Davis 647387768eSBrooks Davis * 657387768eSBrooks Davis * Written by Bill Paul <wpaul@ctr.columbia.edu> 667387768eSBrooks Davis * Center for Telecommunications Research 677387768eSBrooks Davis * Columbia University, New York City 687387768eSBrooks Davis */ 697387768eSBrooks Davis 707387768eSBrooks Davis #include <sys/cdefs.h> 717387768eSBrooks Davis __FBSDID("$FreeBSD$"); 727387768eSBrooks Davis 737387768eSBrooks Davis #include <stdio.h> 747387768eSBrooks Davis #include <paths.h> 757387768eSBrooks Davis #include <sys/types.h> 767387768eSBrooks Davis #include <sys/eui64.h> 777387768eSBrooks Davis #include <string.h> 787387768eSBrooks Davis #include <stdlib.h> 797387768eSBrooks Davis #include <sys/param.h> 807387768eSBrooks Davis #ifdef YP 817387768eSBrooks Davis #include <rpc/rpc.h> 827387768eSBrooks Davis #include <rpcsvc/yp_prot.h> 837387768eSBrooks Davis #include <rpcsvc/ypclnt.h> 847387768eSBrooks Davis #endif 857387768eSBrooks Davis 867387768eSBrooks Davis #ifndef _PATH_EUI64 877387768eSBrooks Davis #define _PATH_EUI64 "/etc/eui64" 887387768eSBrooks Davis #endif 897387768eSBrooks Davis 907387768eSBrooks Davis static int eui64_line(const char *l, struct eui64 *e, char *hostname, 917387768eSBrooks Davis size_t len); 927387768eSBrooks Davis 937387768eSBrooks Davis /* 947387768eSBrooks Davis * Parse a string of text containing an EUI-64 and hostname 957387768eSBrooks Davis * and separate it into its component parts. 967387768eSBrooks Davis */ 977387768eSBrooks Davis static int 987387768eSBrooks Davis eui64_line(const char *l, struct eui64 *e, char *hostname, size_t len) 997387768eSBrooks Davis { 1007387768eSBrooks Davis char *line, *linehead, *cur; 1017387768eSBrooks Davis 1027387768eSBrooks Davis linehead = strdup(l); 1037387768eSBrooks Davis if (linehead == NULL) 1047387768eSBrooks Davis return (-1); 1057387768eSBrooks Davis line = linehead; 1067387768eSBrooks Davis 1077387768eSBrooks Davis /* Find and parse the EUI64 */ 1087387768eSBrooks Davis while ((cur = strsep(&line, " \t\r\n")) != NULL) { 1097387768eSBrooks Davis if (*cur != '\0') { 1107387768eSBrooks Davis if (eui64_aton(cur, e) == 0) 1117387768eSBrooks Davis break; 1127387768eSBrooks Davis else 1137387768eSBrooks Davis goto bad; 1147387768eSBrooks Davis } 1157387768eSBrooks Davis } 1167387768eSBrooks Davis 1177387768eSBrooks Davis /* Find the hostname */ 1187387768eSBrooks Davis while ((cur = strsep(&line, " \t\r\n")) != NULL) { 1197387768eSBrooks Davis if (*cur != '\0') { 1207387768eSBrooks Davis if (strlcpy(hostname, cur, len) <= len) 1217387768eSBrooks Davis break; 1227387768eSBrooks Davis else 1237387768eSBrooks Davis goto bad; 1247387768eSBrooks Davis } 1257387768eSBrooks Davis } 1267387768eSBrooks Davis 1277387768eSBrooks Davis /* Make sure what remains is either whitespace or a comment */ 1287387768eSBrooks Davis while ((cur = strsep(&line, " \t\r\n")) != NULL) { 1297387768eSBrooks Davis if (*cur == '#') 1307387768eSBrooks Davis break; 1317387768eSBrooks Davis if (*cur != '\0') 1327387768eSBrooks Davis goto bad; 1337387768eSBrooks Davis } 1347387768eSBrooks Davis 135*726b99f9SPedro F. Giffuni free(linehead); 1367387768eSBrooks Davis return (0); 1377387768eSBrooks Davis 1387387768eSBrooks Davis bad: 1397387768eSBrooks Davis free(linehead); 1407387768eSBrooks Davis return (-1); 1417387768eSBrooks Davis } 1427387768eSBrooks Davis 1437387768eSBrooks Davis /* 1447387768eSBrooks Davis * Convert an ASCII representation of an EUI-64 to binary form. 1457387768eSBrooks Davis */ 1467387768eSBrooks Davis int 1477387768eSBrooks Davis eui64_aton(const char *a, struct eui64 *e) 1487387768eSBrooks Davis { 1497387768eSBrooks Davis int i; 1507387768eSBrooks Davis unsigned int o0, o1, o2, o3, o4, o5, o6, o7; 1517387768eSBrooks Davis 1527387768eSBrooks Davis /* canonical form */ 1537387768eSBrooks Davis i = sscanf(a, "%x-%x-%x-%x-%x-%x-%x-%x", 1547387768eSBrooks Davis &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7); 1557387768eSBrooks Davis if (i == EUI64_LEN) 1567387768eSBrooks Davis goto good; 1577387768eSBrooks Davis /* ethernet form */ 1587387768eSBrooks Davis i = sscanf(a, "%x:%x:%x:%x:%x:%x:%x:%x", 1597387768eSBrooks Davis &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7); 1607387768eSBrooks Davis if (i == EUI64_LEN) 1617387768eSBrooks Davis goto good; 1627387768eSBrooks Davis /* classic fwcontrol/dconschat form */ 1637387768eSBrooks Davis i = sscanf(a, "0x%2x%2x%2x%2x%2x%2x%2x%2x", 1647387768eSBrooks Davis &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7); 1657387768eSBrooks Davis if (i == EUI64_LEN) 1667387768eSBrooks Davis goto good; 1677387768eSBrooks Davis /* MAC format (-) */ 1687387768eSBrooks Davis i = sscanf(a, "%x-%x-%x-%x-%x-%x", 1697387768eSBrooks Davis &o0, &o1, &o2, &o5, &o6, &o7); 1707387768eSBrooks Davis if (i == 6) { 1717387768eSBrooks Davis o3 = 0xff; 1727387768eSBrooks Davis o4 = 0xfe; 1737387768eSBrooks Davis goto good; 1747387768eSBrooks Davis } 1757387768eSBrooks Davis /* MAC format (:) */ 1767387768eSBrooks Davis i = sscanf(a, "%x:%x:%x:%x:%x:%x", 1777387768eSBrooks Davis &o0, &o1, &o2, &o5, &o6, &o7); 1787387768eSBrooks Davis if (i == 6) { 1797387768eSBrooks Davis o3 = 0xff; 1807387768eSBrooks Davis o4 = 0xfe; 1817387768eSBrooks Davis goto good; 1827387768eSBrooks Davis } 1837387768eSBrooks Davis 1847387768eSBrooks Davis return (-1); 1857387768eSBrooks Davis 1867387768eSBrooks Davis good: 1877387768eSBrooks Davis e->octet[0]=o0; 1887387768eSBrooks Davis e->octet[1]=o1; 1897387768eSBrooks Davis e->octet[2]=o2; 1907387768eSBrooks Davis e->octet[3]=o3; 1917387768eSBrooks Davis e->octet[4]=o4; 1927387768eSBrooks Davis e->octet[5]=o5; 1937387768eSBrooks Davis e->octet[6]=o6; 1947387768eSBrooks Davis e->octet[7]=o7; 1957387768eSBrooks Davis 1967387768eSBrooks Davis return (0); 1977387768eSBrooks Davis } 1987387768eSBrooks Davis 1997387768eSBrooks Davis /* 2007387768eSBrooks Davis * Convert a binary representation of an EUI-64 to an ASCII string. 2017387768eSBrooks Davis */ 2027387768eSBrooks Davis int 2037387768eSBrooks Davis eui64_ntoa(const struct eui64 *id, char *a, size_t len) 2047387768eSBrooks Davis { 2057387768eSBrooks Davis int i; 2067387768eSBrooks Davis 2077387768eSBrooks Davis i = snprintf(a, len, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", 2087387768eSBrooks Davis id->octet[0], id->octet[1], id->octet[2], id->octet[3], 2097387768eSBrooks Davis id->octet[4], id->octet[5], id->octet[6], id->octet[7]); 2107387768eSBrooks Davis if (i < 23 || i >= len) 2117387768eSBrooks Davis return (-1); 2127387768eSBrooks Davis return (0); 2137387768eSBrooks Davis } 2147387768eSBrooks Davis 2157387768eSBrooks Davis /* 2167387768eSBrooks Davis * Map an EUI-64 to a hostname. Use either /etc/eui64 or NIS/YP. 2177387768eSBrooks Davis */ 2187387768eSBrooks Davis int 2197387768eSBrooks Davis eui64_ntohost(char *hostname, size_t len, const struct eui64 *id) 2207387768eSBrooks Davis { 2217387768eSBrooks Davis FILE *fp; 2227387768eSBrooks Davis char buf[BUFSIZ + 2]; 2237387768eSBrooks Davis struct eui64 local_eui64; 2247387768eSBrooks Davis char local_host[MAXHOSTNAMELEN]; 2257387768eSBrooks Davis #ifdef YP 2267387768eSBrooks Davis char *result; 2277387768eSBrooks Davis int resultlen; 2287387768eSBrooks Davis char eui64_a[24]; 2297387768eSBrooks Davis char *yp_domain; 2307387768eSBrooks Davis #endif 231a93705b0SJilles Tjoelker if ((fp = fopen(_PATH_EUI64, "re")) == NULL) 2327387768eSBrooks Davis return (1); 2337387768eSBrooks Davis 2347387768eSBrooks Davis while (fgets(buf,BUFSIZ,fp)) { 2357387768eSBrooks Davis if (buf[0] == '#') 2367387768eSBrooks Davis continue; 2377387768eSBrooks Davis #ifdef YP 2387387768eSBrooks Davis if (buf[0] == '+') { 2397387768eSBrooks Davis if (yp_get_default_domain(&yp_domain)) 2407387768eSBrooks Davis continue; 2417387768eSBrooks Davis eui64_ntoa(id, eui64_a, sizeof(eui64_a)); 2427387768eSBrooks Davis if (yp_match(yp_domain, "eui64.byid", eui64_a, 2437387768eSBrooks Davis strlen(eui64_a), &result, &resultlen)) { 2447387768eSBrooks Davis continue; 2457387768eSBrooks Davis } 2467387768eSBrooks Davis strncpy(buf, result, resultlen); 2477387768eSBrooks Davis buf[resultlen] = '\0'; 2487387768eSBrooks Davis free(result); 2497387768eSBrooks Davis } 2507387768eSBrooks Davis #endif 2517387768eSBrooks Davis if (eui64_line(buf, &local_eui64, local_host, 2527387768eSBrooks Davis sizeof(local_host)) == 0) { 2537387768eSBrooks Davis if (bcmp(&local_eui64.octet[0], 2547387768eSBrooks Davis &id->octet[0], EUI64_LEN) == 0) { 2557387768eSBrooks Davis /* We have a match */ 2567387768eSBrooks Davis strcpy(hostname, local_host); 2577387768eSBrooks Davis fclose(fp); 2587387768eSBrooks Davis return(0); 2597387768eSBrooks Davis } 2607387768eSBrooks Davis } 2617387768eSBrooks Davis } 2627387768eSBrooks Davis fclose(fp); 2637387768eSBrooks Davis return (1); 2647387768eSBrooks Davis } 2657387768eSBrooks Davis 2667387768eSBrooks Davis /* 2677387768eSBrooks Davis * Map a hostname to an EUI-64 using /etc/eui64 or NIS/YP. 2687387768eSBrooks Davis */ 2697387768eSBrooks Davis int 2707387768eSBrooks Davis eui64_hostton(const char *hostname, struct eui64 *id) 2717387768eSBrooks Davis { 2727387768eSBrooks Davis FILE *fp; 2737387768eSBrooks Davis char buf[BUFSIZ + 2]; 2747387768eSBrooks Davis struct eui64 local_eui64; 2757387768eSBrooks Davis char local_host[MAXHOSTNAMELEN]; 2767387768eSBrooks Davis #ifdef YP 2777387768eSBrooks Davis char *result; 2787387768eSBrooks Davis int resultlen; 2797387768eSBrooks Davis char *yp_domain; 2807387768eSBrooks Davis #endif 281a93705b0SJilles Tjoelker if ((fp = fopen(_PATH_EUI64, "re")) == NULL) 2827387768eSBrooks Davis return (1); 2837387768eSBrooks Davis 2847387768eSBrooks Davis while (fgets(buf,BUFSIZ,fp)) { 2857387768eSBrooks Davis if (buf[0] == '#') 2867387768eSBrooks Davis continue; 2877387768eSBrooks Davis #ifdef YP 2887387768eSBrooks Davis if (buf[0] == '+') { 2897387768eSBrooks Davis if (yp_get_default_domain(&yp_domain)) 2907387768eSBrooks Davis continue; 2917387768eSBrooks Davis if (yp_match(yp_domain, "eui64.byname", hostname, 2927387768eSBrooks Davis strlen(hostname), &result, &resultlen)) { 2937387768eSBrooks Davis continue; 2947387768eSBrooks Davis } 2957387768eSBrooks Davis strncpy(buf, result, resultlen); 2967387768eSBrooks Davis buf[resultlen] = '\0'; 2977387768eSBrooks Davis free(result); 2987387768eSBrooks Davis } 2997387768eSBrooks Davis #endif 3007387768eSBrooks Davis if (eui64_line(buf, &local_eui64, local_host, 3017387768eSBrooks Davis sizeof(local_host)) == 0) { 3027387768eSBrooks Davis if (strcmp(hostname, local_host) == 0) { 3037387768eSBrooks Davis /* We have a match */ 3047387768eSBrooks Davis bcopy(&local_eui64, id, sizeof(struct eui64)); 3057387768eSBrooks Davis fclose(fp); 3067387768eSBrooks Davis return(0); 3077387768eSBrooks Davis } 3087387768eSBrooks Davis } 3097387768eSBrooks Davis } 3107387768eSBrooks Davis fclose(fp); 3117387768eSBrooks Davis return (1); 3127387768eSBrooks Davis } 313