xref: /netbsd/usr.sbin/fwctl/eui64.c (revision f108f421)
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@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@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
eui64_line(const char * l,struct eui64 * e,char * hostname,size_t len)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
eui64_aton(const char * a,struct eui64 * e)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
eui64_ntoa(const struct eui64 * id,char * a,size_t len)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
eui64_ntohost(char * hostname,size_t len,const struct eui64 * id)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
eui64_hostton(const char * hostname,struct eui64 * id)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