summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/ethers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/ethers.c')
-rw-r--r--src/lib/libc/net/ethers.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/src/lib/libc/net/ethers.c b/src/lib/libc/net/ethers.c
new file mode 100644
index 0000000000..899022a622
--- /dev/null
+++ b/src/lib/libc/net/ethers.c
@@ -0,0 +1,261 @@
1/* $OpenBSD: ethers.c,v 1.16 2003/06/17 21:56:24 millert Exp $ */
2
3/*
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * ethers(3) a la Sun.
21 * Originally Written by Roland McGrath <roland@frob.com> 10/14/93.
22 * Substantially modified by Todd C. Miller <Todd.Miller@courtesan.com>
23 */
24
25#if defined(LIBC_SCCS) && !defined(lint)
26static char rcsid[] = "$OpenBSD: ethers.c,v 1.16 2003/06/17 21:56:24 millert Exp $";
27#endif /* LIBC_SCCS and not lint */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <netinet/in.h>
33#include <netinet/if_ether.h>
34#include <sys/param.h>
35#include <paths.h>
36#include <errno.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <ctype.h>
41#ifdef YP
42#include <rpcsvc/ypclnt.h>
43#endif
44
45#ifndef _PATH_ETHERS
46#define _PATH_ETHERS "/etc/ethers"
47#endif
48
49static char * _ether_aton(char *, struct ether_addr *);
50
51char *
52ether_ntoa(e)
53 struct ether_addr *e;
54{
55 static char a[] = "xx:xx:xx:xx:xx:xx";
56
57 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
58 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
59 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
60 errno = EINVAL;
61 return (NULL);
62 }
63
64 (void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
65 e->ether_addr_octet[0], e->ether_addr_octet[1],
66 e->ether_addr_octet[2], e->ether_addr_octet[3],
67 e->ether_addr_octet[4], e->ether_addr_octet[5]);
68
69 return (a);
70}
71
72static char *
73_ether_aton(s, e)
74 char *s;
75 struct ether_addr *e;
76{
77 int i;
78 long l;
79 char *pp;
80
81 while (isspace(*s))
82 s++;
83
84 /* expect 6 hex octets separated by ':' or space/NUL if last octet */
85 for (i = 0; i < 6; i++) {
86 l = strtol(s, &pp, 16);
87 if (pp == s || l > 0xFF || l < 0)
88 return (NULL);
89 if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
90 return (NULL);
91 e->ether_addr_octet[i] = (u_char)l;
92 s = pp + 1;
93 }
94
95 /* return character after the octets ala strtol(3) */
96 return (pp);
97}
98
99struct ether_addr *
100ether_aton(s)
101 char *s;
102{
103 static struct ether_addr n;
104
105 return (_ether_aton(s, &n) ? &n : NULL);
106}
107
108int
109ether_ntohost(hostname, e)
110 char *hostname;
111 struct ether_addr *e;
112{
113 FILE *f;
114 char buf[BUFSIZ+1], *p;
115 size_t len;
116 struct ether_addr try;
117#ifdef YP
118 char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
119 int trylen;
120#endif
121
122 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
123 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
124 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
125 errno = EINVAL;
126 return (-1);
127 }
128
129#ifdef YP
130 snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
131 e->ether_addr_octet[0], e->ether_addr_octet[1],
132 e->ether_addr_octet[2], e->ether_addr_octet[3],
133 e->ether_addr_octet[4], e->ether_addr_octet[5]);
134 trylen = strlen(trybuf);
135#endif
136
137 f = fopen(_PATH_ETHERS, "r");
138 if (f == NULL)
139 return (-1);
140 while ((p = fgetln(f, &len)) != NULL) {
141 if (p[len-1] == '\n')
142 len--;
143 if (len > sizeof(buf) - 2)
144 continue;
145 (void)memcpy(buf, p, len);
146 buf[len] = '\n'; /* code assumes newlines later on */
147 buf[len+1] = '\0';
148#ifdef YP
149 /* A + in the file means try YP now. */
150 if (!strncmp(buf, "+\n", sizeof(buf))) {
151 char *ypbuf, *ypdom;
152 int ypbuflen;
153
154 if (yp_get_default_domain(&ypdom))
155 continue;
156 if (yp_match(ypdom, "ethers.byaddr", trybuf,
157 trylen, &ypbuf, &ypbuflen))
158 continue;
159 if (ether_line(ypbuf, &try, hostname) == 0) {
160 free(ypbuf);
161 (void)fclose(f);
162 return (0);
163 }
164 free(ypbuf);
165 continue;
166 }
167#endif
168 if (ether_line(buf, &try, hostname) == 0 &&
169 memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
170 (void)fclose(f);
171 return (0);
172 }
173 }
174 (void)fclose(f);
175 errno = ENOENT;
176 return (-1);
177}
178
179int
180ether_hostton(hostname, e)
181 char *hostname;
182 struct ether_addr *e;
183{
184 FILE *f;
185 char buf[BUFSIZ+1], *p;
186 char try[MAXHOSTNAMELEN];
187 size_t len;
188#ifdef YP
189 int hostlen = strlen(hostname);
190#endif
191
192 f = fopen(_PATH_ETHERS, "r");
193 if (f==NULL)
194 return (-1);
195
196 while ((p = fgetln(f, &len)) != NULL) {
197 if (p[len-1] == '\n')
198 len--;
199 if (len > sizeof(buf) - 2)
200 continue;
201 memcpy(buf, p, len);
202 buf[len] = '\n'; /* code assumes newlines later on */
203 buf[len+1] = '\0';
204#ifdef YP
205 /* A + in the file means try YP now. */
206 if (!strncmp(buf, "+\n", sizeof(buf))) {
207 char *ypbuf, *ypdom;
208 int ypbuflen;
209
210 if (yp_get_default_domain(&ypdom))
211 continue;
212 if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
213 &ypbuf, &ypbuflen))
214 continue;
215 if (ether_line(ypbuf, e, try) == 0) {
216 free(ypbuf);
217 (void)fclose(f);
218 return (0);
219 }
220 free(ypbuf);
221 continue;
222 }
223#endif
224 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
225 (void)fclose(f);
226 return (0);
227 }
228 }
229 (void)fclose(f);
230 errno = ENOENT;
231 return (-1);
232}
233
234int
235ether_line(line, e, hostname)
236 char *line;
237 struct ether_addr *e;
238 char *hostname;
239{
240 char *p;
241 size_t n;
242
243 /* Parse "xx:xx:xx:xx:xx:xx" */
244 if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
245 goto bad;
246
247 /* Now get the hostname */
248 while (isspace(*p))
249 p++;
250 if (*p == '\0')
251 goto bad;
252 n = strcspn(p, " \t\n");
253 if (n >= MAXHOSTNAMELEN)
254 goto bad;
255 strlcpy(hostname, p, n + 1);
256 return (0);
257
258bad:
259 errno = EINVAL;
260 return (-1);
261}