xref: /freebsd/lib/libc/net/eui64.c (revision 726b99f9f95cb0622d9e7ece3ad828484c63ec9b)
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