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