1 /* $NetBSD: ethers.c,v 1.25 2014/09/18 13:58:20 christos 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 <sys/cdefs.h>
11 #if defined(LIBC_SCCS) && !defined(lint)
12 __RCSID("$NetBSD: ethers.c,v 1.25 2014/09/18 13:58:20 christos Exp $");
13 #endif /* LIBC_SCCS and not lint */
14
15 #include "namespace.h"
16 #include <sys/param.h>
17 #include <sys/socket.h>
18
19 #include <net/if.h>
20 #include <net/if_ether.h>
21 #include <netinet/in.h>
22
23 #include <assert.h>
24 #include <errno.h>
25 #include <paths.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #ifdef YP
31 #include <rpcsvc/ypclnt.h>
32 #endif
33
34 #ifdef __weak_alias
__weak_alias(ether_aton,_ether_aton)35 __weak_alias(ether_aton,_ether_aton)
36 __weak_alias(ether_hostton,_ether_hostton)
37 __weak_alias(ether_line,_ether_line)
38 __weak_alias(ether_ntoa,_ether_ntoa)
39 __weak_alias(ether_ntohost,_ether_ntohost)
40 #endif
41
42 #ifndef _PATH_ETHERS
43 #define _PATH_ETHERS "/etc/ethers"
44 #endif
45
46 char *
47 ether_ntoa(const struct ether_addr *e)
48 {
49 static char a[18];
50
51 _DIAGASSERT(e != NULL);
52
53 (void) snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
54 e->ether_addr_octet[0], e->ether_addr_octet[1],
55 e->ether_addr_octet[2], e->ether_addr_octet[3],
56 e->ether_addr_octet[4], e->ether_addr_octet[5]);
57 return a;
58 }
59
60 struct ether_addr *
ether_aton(const char * s)61 ether_aton(const char *s)
62 {
63 static struct ether_addr n;
64 u_int i[6];
65
66 _DIAGASSERT(s != NULL);
67
68 if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
69 &i[2], &i[3], &i[4], &i[5]) == 6) {
70 n.ether_addr_octet[0] = (u_char)i[0];
71 n.ether_addr_octet[1] = (u_char)i[1];
72 n.ether_addr_octet[2] = (u_char)i[2];
73 n.ether_addr_octet[3] = (u_char)i[3];
74 n.ether_addr_octet[4] = (u_char)i[4];
75 n.ether_addr_octet[5] = (u_char)i[5];
76 return &n;
77 }
78 return NULL;
79 }
80
81 int
ether_ntohost(char * hostname,const struct ether_addr * e)82 ether_ntohost(char *hostname, const struct ether_addr *e)
83 {
84 FILE *f;
85 char *p;
86 struct ether_addr try;
87
88 _DIAGASSERT(hostname != NULL);
89 _DIAGASSERT(e != NULL);
90
91 #ifdef YP
92 char trybuf[sizeof "xx:xx:xx:xx:xx:xx"];
93 int trylen;
94 trylen = snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
95 e->ether_addr_octet[0], e->ether_addr_octet[1],
96 e->ether_addr_octet[2], e->ether_addr_octet[3],
97 e->ether_addr_octet[4], e->ether_addr_octet[5]);
98 #endif
99
100 f = fopen(_PATH_ETHERS, "re");
101 if (f == NULL)
102 return -1;
103 for (p = NULL;;) {
104 free(p);
105 p = fparseln(f, NULL, NULL, NULL, FPARSELN_UNESCALL);
106 if (p == NULL)
107 break;
108 #ifdef YP
109 /* A + in the file means try YP now. */
110 if (strcmp(p, "+") == 0) {
111 char *ypbuf, *ypdom;
112 int ypbuflen;
113
114 if (yp_get_default_domain(&ypdom))
115 continue;
116 if (yp_match(ypdom, "ethers.byaddr", trybuf,
117 trylen, &ypbuf, &ypbuflen))
118 continue;
119 ypbuflen = ether_line(ypbuf, &try, hostname);
120 free(ypbuf);
121 if (ypbuflen == 0)
122 goto done;
123 continue;
124 }
125 #endif
126 if (ether_line(p, &try, hostname) == 0 &&
127 memcmp(&try, e, sizeof try) == 0)
128 goto done;
129 }
130 free(p);
131 (void)fclose(f);
132 errno = ENOENT;
133 return -1;
134 done:
135 free(p);
136 (void)fclose(f);
137 return 0;
138 }
139
140 int
ether_hostton(const char * hostname,struct ether_addr * e)141 ether_hostton(const char *hostname, struct ether_addr *e)
142 {
143 FILE *f;
144 char *p;
145 char try[MAXHOSTNAMELEN + 1];
146 #ifdef YP
147 int hostlen = (int)strlen(hostname);
148 #endif
149
150 _DIAGASSERT(hostname != NULL);
151 _DIAGASSERT(e != NULL);
152
153 f = fopen(_PATH_ETHERS, "re");
154 if (f == NULL)
155 return -1;
156
157 for (p = NULL;;) {
158 free(p);
159 p = fparseln(f, NULL, NULL, NULL, FPARSELN_UNESCALL);
160 if (p == NULL)
161 break;
162 #ifdef YP
163 /* A + in the file means try YP now. */
164 if (strcmp(p, "+") == 0) {
165 char *ypbuf, *ypdom;
166 int ypbuflen;
167
168 if (yp_get_default_domain(&ypdom))
169 continue;
170 if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
171 &ypbuf, &ypbuflen))
172 continue;
173 ypbuflen = ether_line(ypbuf, e, try);
174 free(ypbuf);
175 if (ypbuflen == 0)
176 goto done;
177 continue;
178 }
179 #endif
180 if (ether_line(p, e, try) == 0 && strcmp(hostname, try) == 0)
181 goto done;
182 }
183 free(p);
184 (void)fclose(f);
185 errno = ENOENT;
186 return -1;
187 done:
188 free(p);
189 (void)fclose(f);
190 return 0;
191 }
192
193 int
ether_line(const char * l,struct ether_addr * e,char * hostname)194 ether_line(const char *l, struct ether_addr *e, char *hostname)
195 {
196 u_int i[6];
197
198 #define S2(arg) #arg
199 #define S1(arg) S2(arg)
200 static const char fmt[] = " %x:%x:%x:%x:%x:%x"
201 " %" S1(MAXHOSTNAMELEN) "s\n";
202 #undef S2
203 #undef S1
204
205 _DIAGASSERT(l != NULL);
206 _DIAGASSERT(e != NULL);
207 _DIAGASSERT(hostname != NULL);
208
209 if (sscanf(l, fmt,
210 &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], hostname) == 7) {
211 e->ether_addr_octet[0] = (u_char)i[0];
212 e->ether_addr_octet[1] = (u_char)i[1];
213 e->ether_addr_octet[2] = (u_char)i[2];
214 e->ether_addr_octet[3] = (u_char)i[3];
215 e->ether_addr_octet[4] = (u_char)i[4];
216 e->ether_addr_octet[5] = (u_char)i[5];
217 return 0;
218 }
219 errno = EINVAL;
220 return -1;
221 }
222