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 <stdio.h>
717387768eSBrooks Davis #include <paths.h>
72*2cf5e936SAndriy Voskoboinyk #include <sys/param.h>
737387768eSBrooks Davis #include <sys/eui64.h>
747387768eSBrooks Davis #include <string.h>
757387768eSBrooks Davis #include <stdlib.h>
767387768eSBrooks Davis #ifdef YP
777387768eSBrooks Davis #include <rpc/rpc.h>
787387768eSBrooks Davis #include <rpcsvc/yp_prot.h>
797387768eSBrooks Davis #include <rpcsvc/ypclnt.h>
807387768eSBrooks Davis #endif
817387768eSBrooks Davis
827387768eSBrooks Davis #ifndef _PATH_EUI64
837387768eSBrooks Davis #define _PATH_EUI64 "/etc/eui64"
847387768eSBrooks Davis #endif
857387768eSBrooks Davis
867387768eSBrooks Davis static int eui64_line(const char *l, struct eui64 *e, char *hostname,
877387768eSBrooks Davis size_t len);
887387768eSBrooks Davis
897387768eSBrooks Davis /*
907387768eSBrooks Davis * Parse a string of text containing an EUI-64 and hostname
917387768eSBrooks Davis * and separate it into its component parts.
927387768eSBrooks Davis */
937387768eSBrooks Davis static int
eui64_line(const char * l,struct eui64 * e,char * hostname,size_t len)947387768eSBrooks Davis eui64_line(const char *l, struct eui64 *e, char *hostname, size_t len)
957387768eSBrooks Davis {
967387768eSBrooks Davis char *line, *linehead, *cur;
977387768eSBrooks Davis
987387768eSBrooks Davis linehead = strdup(l);
997387768eSBrooks Davis if (linehead == NULL)
1007387768eSBrooks Davis return (-1);
1017387768eSBrooks Davis line = linehead;
1027387768eSBrooks Davis
1037387768eSBrooks Davis /* Find and parse the EUI64 */
1047387768eSBrooks Davis while ((cur = strsep(&line, " \t\r\n")) != NULL) {
1057387768eSBrooks Davis if (*cur != '\0') {
1067387768eSBrooks Davis if (eui64_aton(cur, e) == 0)
1077387768eSBrooks Davis break;
1087387768eSBrooks Davis else
1097387768eSBrooks Davis goto bad;
1107387768eSBrooks Davis }
1117387768eSBrooks Davis }
1127387768eSBrooks Davis
1137387768eSBrooks Davis /* Find the hostname */
1147387768eSBrooks Davis while ((cur = strsep(&line, " \t\r\n")) != NULL) {
1157387768eSBrooks Davis if (*cur != '\0') {
1167387768eSBrooks Davis if (strlcpy(hostname, cur, len) <= len)
1177387768eSBrooks Davis break;
1187387768eSBrooks Davis else
1197387768eSBrooks Davis goto bad;
1207387768eSBrooks Davis }
1217387768eSBrooks Davis }
1227387768eSBrooks Davis
1237387768eSBrooks Davis /* Make sure what remains is either whitespace or a comment */
1247387768eSBrooks Davis while ((cur = strsep(&line, " \t\r\n")) != NULL) {
1257387768eSBrooks Davis if (*cur == '#')
1267387768eSBrooks Davis break;
1277387768eSBrooks Davis if (*cur != '\0')
1287387768eSBrooks Davis goto bad;
1297387768eSBrooks Davis }
1307387768eSBrooks Davis
131726b99f9SPedro F. Giffuni free(linehead);
1327387768eSBrooks Davis return (0);
1337387768eSBrooks Davis
1347387768eSBrooks Davis bad:
1357387768eSBrooks Davis free(linehead);
1367387768eSBrooks Davis return (-1);
1377387768eSBrooks Davis }
1387387768eSBrooks Davis
1397387768eSBrooks Davis /*
1407387768eSBrooks Davis * Convert an ASCII representation of an EUI-64 to binary form.
1417387768eSBrooks Davis */
1427387768eSBrooks Davis int
eui64_aton(const char * a,struct eui64 * e)1437387768eSBrooks Davis eui64_aton(const char *a, struct eui64 *e)
1447387768eSBrooks Davis {
1457387768eSBrooks Davis int i;
1467387768eSBrooks Davis unsigned int o0, o1, o2, o3, o4, o5, o6, o7;
1477387768eSBrooks Davis
1487387768eSBrooks Davis /* canonical form */
1497387768eSBrooks Davis i = sscanf(a, "%x-%x-%x-%x-%x-%x-%x-%x",
1507387768eSBrooks Davis &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7);
1517387768eSBrooks Davis if (i == EUI64_LEN)
1527387768eSBrooks Davis goto good;
1537387768eSBrooks Davis /* ethernet form */
1547387768eSBrooks Davis i = sscanf(a, "%x:%x:%x:%x:%x:%x:%x:%x",
1557387768eSBrooks Davis &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7);
1567387768eSBrooks Davis if (i == EUI64_LEN)
1577387768eSBrooks Davis goto good;
1587387768eSBrooks Davis /* classic fwcontrol/dconschat form */
1597387768eSBrooks Davis i = sscanf(a, "0x%2x%2x%2x%2x%2x%2x%2x%2x",
1607387768eSBrooks Davis &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7);
1617387768eSBrooks Davis if (i == EUI64_LEN)
1627387768eSBrooks Davis goto good;
1637387768eSBrooks Davis /* MAC format (-) */
1647387768eSBrooks Davis i = sscanf(a, "%x-%x-%x-%x-%x-%x",
1657387768eSBrooks Davis &o0, &o1, &o2, &o5, &o6, &o7);
1667387768eSBrooks Davis if (i == 6) {
1677387768eSBrooks Davis o3 = 0xff;
1687387768eSBrooks Davis o4 = 0xfe;
1697387768eSBrooks Davis goto good;
1707387768eSBrooks Davis }
1717387768eSBrooks Davis /* MAC format (:) */
1727387768eSBrooks Davis i = sscanf(a, "%x:%x:%x:%x:%x:%x",
1737387768eSBrooks Davis &o0, &o1, &o2, &o5, &o6, &o7);
1747387768eSBrooks Davis if (i == 6) {
1757387768eSBrooks Davis o3 = 0xff;
1767387768eSBrooks Davis o4 = 0xfe;
1777387768eSBrooks Davis goto good;
1787387768eSBrooks Davis }
1797387768eSBrooks Davis
1807387768eSBrooks Davis return (-1);
1817387768eSBrooks Davis
1827387768eSBrooks Davis good:
1837387768eSBrooks Davis e->octet[0]=o0;
1847387768eSBrooks Davis e->octet[1]=o1;
1857387768eSBrooks Davis e->octet[2]=o2;
1867387768eSBrooks Davis e->octet[3]=o3;
1877387768eSBrooks Davis e->octet[4]=o4;
1887387768eSBrooks Davis e->octet[5]=o5;
1897387768eSBrooks Davis e->octet[6]=o6;
1907387768eSBrooks Davis e->octet[7]=o7;
1917387768eSBrooks Davis
1927387768eSBrooks Davis return (0);
1937387768eSBrooks Davis }
1947387768eSBrooks Davis
1957387768eSBrooks Davis /*
1967387768eSBrooks Davis * Convert a binary representation of an EUI-64 to an ASCII string.
1977387768eSBrooks Davis */
1987387768eSBrooks Davis int
eui64_ntoa(const struct eui64 * id,char * a,size_t len)1997387768eSBrooks Davis eui64_ntoa(const struct eui64 *id, char *a, size_t len)
2007387768eSBrooks Davis {
2017387768eSBrooks Davis int i;
2027387768eSBrooks Davis
2037387768eSBrooks Davis i = snprintf(a, len, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
2047387768eSBrooks Davis id->octet[0], id->octet[1], id->octet[2], id->octet[3],
2057387768eSBrooks Davis id->octet[4], id->octet[5], id->octet[6], id->octet[7]);
2067387768eSBrooks Davis if (i < 23 || i >= len)
2077387768eSBrooks Davis return (-1);
2087387768eSBrooks Davis return (0);
2097387768eSBrooks Davis }
2107387768eSBrooks Davis
2117387768eSBrooks Davis /*
2127387768eSBrooks Davis * Map an EUI-64 to a hostname. Use either /etc/eui64 or NIS/YP.
2137387768eSBrooks Davis */
2147387768eSBrooks Davis int
eui64_ntohost(char * hostname,size_t len,const struct eui64 * id)2157387768eSBrooks Davis eui64_ntohost(char *hostname, size_t len, const struct eui64 *id)
2167387768eSBrooks Davis {
2177387768eSBrooks Davis FILE *fp;
2187387768eSBrooks Davis char buf[BUFSIZ + 2];
2197387768eSBrooks Davis struct eui64 local_eui64;
2207387768eSBrooks Davis char local_host[MAXHOSTNAMELEN];
2217387768eSBrooks Davis #ifdef YP
2227387768eSBrooks Davis char *result;
2237387768eSBrooks Davis int resultlen;
2247387768eSBrooks Davis char eui64_a[24];
2257387768eSBrooks Davis char *yp_domain;
2267387768eSBrooks Davis #endif
227a93705b0SJilles Tjoelker if ((fp = fopen(_PATH_EUI64, "re")) == NULL)
2287387768eSBrooks Davis return (1);
2297387768eSBrooks Davis
2307387768eSBrooks Davis while (fgets(buf,BUFSIZ,fp)) {
2317387768eSBrooks Davis if (buf[0] == '#')
2327387768eSBrooks Davis continue;
2337387768eSBrooks Davis #ifdef YP
2347387768eSBrooks Davis if (buf[0] == '+') {
2357387768eSBrooks Davis if (yp_get_default_domain(&yp_domain))
2367387768eSBrooks Davis continue;
2377387768eSBrooks Davis eui64_ntoa(id, eui64_a, sizeof(eui64_a));
2387387768eSBrooks Davis if (yp_match(yp_domain, "eui64.byid", eui64_a,
2397387768eSBrooks Davis strlen(eui64_a), &result, &resultlen)) {
2407387768eSBrooks Davis continue;
2417387768eSBrooks Davis }
2427387768eSBrooks Davis strncpy(buf, result, resultlen);
2437387768eSBrooks Davis buf[resultlen] = '\0';
2447387768eSBrooks Davis free(result);
2457387768eSBrooks Davis }
2467387768eSBrooks Davis #endif
2477387768eSBrooks Davis if (eui64_line(buf, &local_eui64, local_host,
2487387768eSBrooks Davis sizeof(local_host)) == 0) {
2497387768eSBrooks Davis if (bcmp(&local_eui64.octet[0],
2507387768eSBrooks Davis &id->octet[0], EUI64_LEN) == 0) {
2517387768eSBrooks Davis /* We have a match */
2527387768eSBrooks Davis strcpy(hostname, local_host);
2537387768eSBrooks Davis fclose(fp);
2547387768eSBrooks Davis return(0);
2557387768eSBrooks Davis }
2567387768eSBrooks Davis }
2577387768eSBrooks Davis }
2587387768eSBrooks Davis fclose(fp);
2597387768eSBrooks Davis return (1);
2607387768eSBrooks Davis }
2617387768eSBrooks Davis
2627387768eSBrooks Davis /*
2637387768eSBrooks Davis * Map a hostname to an EUI-64 using /etc/eui64 or NIS/YP.
2647387768eSBrooks Davis */
2657387768eSBrooks Davis int
eui64_hostton(const char * hostname,struct eui64 * id)2667387768eSBrooks Davis eui64_hostton(const char *hostname, struct eui64 *id)
2677387768eSBrooks Davis {
2687387768eSBrooks Davis FILE *fp;
2697387768eSBrooks Davis char buf[BUFSIZ + 2];
2707387768eSBrooks Davis struct eui64 local_eui64;
2717387768eSBrooks Davis char local_host[MAXHOSTNAMELEN];
2727387768eSBrooks Davis #ifdef YP
2737387768eSBrooks Davis char *result;
2747387768eSBrooks Davis int resultlen;
2757387768eSBrooks Davis char *yp_domain;
2767387768eSBrooks Davis #endif
277a93705b0SJilles Tjoelker if ((fp = fopen(_PATH_EUI64, "re")) == NULL)
2787387768eSBrooks Davis return (1);
2797387768eSBrooks Davis
2807387768eSBrooks Davis while (fgets(buf,BUFSIZ,fp)) {
2817387768eSBrooks Davis if (buf[0] == '#')
2827387768eSBrooks Davis continue;
2837387768eSBrooks Davis #ifdef YP
2847387768eSBrooks Davis if (buf[0] == '+') {
2857387768eSBrooks Davis if (yp_get_default_domain(&yp_domain))
2867387768eSBrooks Davis continue;
2877387768eSBrooks Davis if (yp_match(yp_domain, "eui64.byname", hostname,
2887387768eSBrooks Davis strlen(hostname), &result, &resultlen)) {
2897387768eSBrooks Davis continue;
2907387768eSBrooks Davis }
2917387768eSBrooks Davis strncpy(buf, result, resultlen);
2927387768eSBrooks Davis buf[resultlen] = '\0';
2937387768eSBrooks Davis free(result);
2947387768eSBrooks Davis }
2957387768eSBrooks Davis #endif
2967387768eSBrooks Davis if (eui64_line(buf, &local_eui64, local_host,
2977387768eSBrooks Davis sizeof(local_host)) == 0) {
2987387768eSBrooks Davis if (strcmp(hostname, local_host) == 0) {
2997387768eSBrooks Davis /* We have a match */
3007387768eSBrooks Davis bcopy(&local_eui64, id, sizeof(struct eui64));
3017387768eSBrooks Davis fclose(fp);
3027387768eSBrooks Davis return(0);
3037387768eSBrooks Davis }
3047387768eSBrooks Davis }
3057387768eSBrooks Davis }
3067387768eSBrooks Davis fclose(fp);
3077387768eSBrooks Davis return (1);
3087387768eSBrooks Davis }
309