Home | History | Annotate | Line # | Download | only in fwctl
      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 (at) 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 (at) 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