xref: /netbsd-src/lib/libc/net/ethers.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
1 /*	$NetBSD: ethers.c,v 1.12 1997/11/12 05:49:24 mjacob Exp $	*/
2 
3 /*
4  * ethers(3N) a la Sun.
5  *
6  * Written by Roland McGrath <roland@frob.com> 10/14/93.
7  * Public domain.
8  */
9 
10 #include "namespace.h"
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <net/if.h>
14 #include <net/if_ether.h>
15 #include <netinet/in.h>
16 #include <sys/param.h>
17 #include <paths.h>
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #ifdef YP
23 #include <rpcsvc/ypclnt.h>
24 #endif
25 
26 #ifdef __weak_alias
27 __weak_alias(ether_aton,_ether_aton);
28 __weak_alias(ether_hostton,_ether_hostton);
29 __weak_alias(ether_line,_ether_line);
30 __weak_alias(ether_ntoa,_ether_ntoa);
31 __weak_alias(ether_ntohost,_ether_ntohost);
32 #endif
33 
34 #ifndef _PATH_ETHERS
35 #define _PATH_ETHERS "/etc/ethers"
36 #endif
37 
38 char *
39 ether_ntoa(e)
40 	struct ether_addr *e;
41 {
42 	static char a[] = "xx:xx:xx:xx:xx:xx";
43 
44 	snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
45 	    e->ether_addr_octet[0], e->ether_addr_octet[1],
46 	    e->ether_addr_octet[2], e->ether_addr_octet[3],
47 	    e->ether_addr_octet[4], e->ether_addr_octet[5]);
48 	return a;
49 }
50 
51 struct ether_addr *
52 ether_aton(s)
53 	const char *s;
54 {
55 	static struct ether_addr n;
56 	u_int i[6];
57 
58 	if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
59 	    &i[2], &i[3], &i[4], &i[5]) == 6) {
60 		n.ether_addr_octet[0] = (u_char)i[0];
61 		n.ether_addr_octet[1] = (u_char)i[1];
62 		n.ether_addr_octet[2] = (u_char)i[2];
63 		n.ether_addr_octet[3] = (u_char)i[3];
64 		n.ether_addr_octet[4] = (u_char)i[4];
65 		n.ether_addr_octet[5] = (u_char)i[5];
66 		return &n;
67 	}
68 	return NULL;
69 }
70 
71 int
72 ether_ntohost(hostname, e)
73 	char *hostname;
74 	struct ether_addr *e;
75 {
76 	FILE *f;
77 	char *p;
78 	size_t len;
79 	struct ether_addr try;
80 
81 #ifdef YP
82 	char trybuf[sizeof "xx:xx:xx:xx:xx:xx"];
83 	int trylen;
84 
85 	trylen = snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
86 	    e->ether_addr_octet[0], e->ether_addr_octet[1],
87 	    e->ether_addr_octet[2], e->ether_addr_octet[3],
88 	    e->ether_addr_octet[4], e->ether_addr_octet[5]);
89 #endif
90 
91 	f = fopen(_PATH_ETHERS, "r");
92 	if (f == NULL)
93 		return -1;
94 	while ((p = fgetln(f, &len)) != NULL) {
95 		if (p[len - 1] != '\n')
96 			continue;		/* skip lines w/o \n */
97 		p[--len] = '\0';
98 #ifdef YP
99 		/* A + in the file means try YP now.  */
100 		if (len == 1 && *p == '+') {
101 			char *ypbuf, *ypdom;
102 			int ypbuflen;
103 
104 			if (yp_get_default_domain(&ypdom))
105 				continue;
106 			if (yp_match(ypdom, "ethers.byaddr", trybuf,
107 			    trylen, &ypbuf, &ypbuflen))
108 				continue;
109 			if (ether_line(ypbuf, &try, hostname) == 0) {
110 				free(ypbuf);
111 				(void)fclose(f);
112 				return 0;
113 			}
114 			free(ypbuf);
115 			continue;
116 		}
117 #endif
118 		if (ether_line(p, &try, hostname) == 0 &&
119 		    memcmp((char *)&try, (char *)e, sizeof try) == 0) {
120 			(void)fclose(f);
121 			return 0;
122 		}
123 	}
124 	(void)fclose(f);
125 	errno = ENOENT;
126 	return -1;
127 }
128 
129 int
130 ether_hostton(hostname, e)
131 	const char *hostname;
132 	struct ether_addr *e;
133 {
134 	FILE *f;
135 	char *p;
136 	size_t len;
137 	char try[MAXHOSTNAMELEN + 1];
138 #ifdef YP
139 	int hostlen = strlen(hostname);
140 #endif
141 
142 	f = fopen(_PATH_ETHERS, "r");
143 	if (f==NULL)
144 		return -1;
145 
146 	while ((p = fgetln(f, &len)) != NULL) {
147 		if (p[len - 1] != '\n')
148 			continue;		/* skip lines w/o \n */
149 		p[--len] = '\0';
150 #ifdef YP
151 		/* A + in the file means try YP now.  */
152 		if (len == 1 && *p == '+') {
153 			char *ypbuf, *ypdom;
154 			int ypbuflen;
155 
156 			if (yp_get_default_domain(&ypdom))
157 				continue;
158 			if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
159 			    &ypbuf, &ypbuflen))
160 				continue;
161 			if (ether_line(ypbuf, e, try) == 0) {
162 				free(ypbuf);
163 				(void)fclose(f);
164 				return 0;
165 			}
166 			free(ypbuf);
167 			continue;
168 		}
169 #endif
170 		if (ether_line(p, e, try) == 0 && strcmp(hostname, try) == 0) {
171 			(void)fclose(f);
172 			return 0;
173 		}
174 	}
175 	(void)fclose(f);
176 	errno = ENOENT;
177 	return -1;
178 }
179 
180 int
181 ether_line(l, e, hostname)
182 	const char *l;
183 	struct ether_addr *e;
184 	char *hostname;
185 {
186 	u_int i[6];
187 	static char buf[sizeof " %x:%x:%x:%x:%x:%x %s\\n" + 21];
188 		/* XXX: 21 == strlen (ASCII representation of 2^64) */
189 
190 	if (! buf[0])
191 		snprintf(buf, sizeof buf, " %%x:%%x:%%x:%%x:%%x:%%x %%%ds\\n",
192 		    MAXHOSTNAMELEN);
193 	if (sscanf(l, buf,
194 	    &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], hostname) == 7) {
195 		e->ether_addr_octet[0] = (u_char)i[0];
196 		e->ether_addr_octet[1] = (u_char)i[1];
197 		e->ether_addr_octet[2] = (u_char)i[2];
198 		e->ether_addr_octet[3] = (u_char)i[3];
199 		e->ether_addr_octet[4] = (u_char)i[4];
200 		e->ether_addr_octet[5] = (u_char)i[5];
201 		return 0;
202 	}
203 	errno = EINVAL;
204 	return -1;
205 }
206