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 |
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 * |
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 |
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 |
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 |
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 | |