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.c236
1 files changed, 236 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..e46dcd7006
--- /dev/null
+++ b/src/lib/libc/net/ethers.c
@@ -0,0 +1,236 @@
1/* $OpenBSD: ethers.c,v 1.19 2005/03/28 06:19:58 tedu 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.19 2005/03/28 06:19:58 tedu 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(const char *, struct ether_addr *);
50
51char *
52ether_ntoa(struct ether_addr *e)
53{
54 static char a[] = "xx:xx:xx:xx:xx:xx";
55
56 (void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
57 e->ether_addr_octet[0], e->ether_addr_octet[1],
58 e->ether_addr_octet[2], e->ether_addr_octet[3],
59 e->ether_addr_octet[4], e->ether_addr_octet[5]);
60
61 return (a);
62}
63
64static char *
65_ether_aton(const char *s, struct ether_addr *e)
66{
67 int i;
68 long l;
69 char *pp;
70
71 while (isspace(*s))
72 s++;
73
74 /* expect 6 hex octets separated by ':' or space/NUL if last octet */
75 for (i = 0; i < 6; i++) {
76 l = strtol(s, &pp, 16);
77 if (pp == s || l > 0xFF || l < 0)
78 return (NULL);
79 if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
80 return (NULL);
81 e->ether_addr_octet[i] = (u_char)l;
82 s = pp + 1;
83 }
84
85 /* return character after the octets ala strtol(3) */
86 return (pp);
87}
88
89struct ether_addr *
90ether_aton(const char *s)
91{
92 static struct ether_addr n;
93
94 return (_ether_aton(s, &n) ? &n : NULL);
95}
96
97int
98ether_ntohost(char *hostname, struct ether_addr *e)
99{
100 FILE *f;
101 char buf[BUFSIZ+1], *p;
102 size_t len;
103 struct ether_addr try;
104#ifdef YP
105 char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
106 int trylen;
107#endif
108
109#ifdef YP
110 snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
111 e->ether_addr_octet[0], e->ether_addr_octet[1],
112 e->ether_addr_octet[2], e->ether_addr_octet[3],
113 e->ether_addr_octet[4], e->ether_addr_octet[5]);
114 trylen = strlen(trybuf);
115#endif
116
117 f = fopen(_PATH_ETHERS, "r");
118 if (f == NULL)
119 return (-1);
120 while ((p = fgetln(f, &len)) != NULL) {
121 if (p[len-1] == '\n')
122 len--;
123 if (len > sizeof(buf) - 2)
124 continue;
125 (void)memcpy(buf, p, len);
126 buf[len] = '\n'; /* code assumes newlines later on */
127 buf[len+1] = '\0';
128#ifdef YP
129 /* A + in the file means try YP now. */
130 if (!strncmp(buf, "+\n", sizeof(buf))) {
131 char *ypbuf, *ypdom;
132 int ypbuflen;
133
134 if (yp_get_default_domain(&ypdom))
135 continue;
136 if (yp_match(ypdom, "ethers.byaddr", trybuf,
137 trylen, &ypbuf, &ypbuflen))
138 continue;
139 if (ether_line(ypbuf, &try, hostname) == 0) {
140 free(ypbuf);
141 (void)fclose(f);
142 return (0);
143 }
144 free(ypbuf);
145 continue;
146 }
147#endif
148 if (ether_line(buf, &try, hostname) == 0 &&
149 memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
150 (void)fclose(f);
151 return (0);
152 }
153 }
154 (void)fclose(f);
155 errno = ENOENT;
156 return (-1);
157}
158
159int
160ether_hostton(const char *hostname, struct ether_addr *e)
161{
162 FILE *f;
163 char buf[BUFSIZ+1], *p;
164 char try[MAXHOSTNAMELEN];
165 size_t len;
166#ifdef YP
167 int hostlen = strlen(hostname);
168#endif
169
170 f = fopen(_PATH_ETHERS, "r");
171 if (f==NULL)
172 return (-1);
173
174 while ((p = fgetln(f, &len)) != NULL) {
175 if (p[len-1] == '\n')
176 len--;
177 if (len > sizeof(buf) - 2)
178 continue;
179 memcpy(buf, p, len);
180 buf[len] = '\n'; /* code assumes newlines later on */
181 buf[len+1] = '\0';
182#ifdef YP
183 /* A + in the file means try YP now. */
184 if (!strncmp(buf, "+\n", sizeof(buf))) {
185 char *ypbuf, *ypdom;
186 int ypbuflen;
187
188 if (yp_get_default_domain(&ypdom))
189 continue;
190 if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
191 &ypbuf, &ypbuflen))
192 continue;
193 if (ether_line(ypbuf, e, try) == 0) {
194 free(ypbuf);
195 (void)fclose(f);
196 return (0);
197 }
198 free(ypbuf);
199 continue;
200 }
201#endif
202 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
203 (void)fclose(f);
204 return (0);
205 }
206 }
207 (void)fclose(f);
208 errno = ENOENT;
209 return (-1);
210}
211
212int
213ether_line(const char *line, struct ether_addr *e, char *hostname)
214{
215 char *p;
216 size_t n;
217
218 /* Parse "xx:xx:xx:xx:xx:xx" */
219 if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
220 goto bad;
221
222 /* Now get the hostname */
223 while (isspace(*p))
224 p++;
225 if (*p == '\0')
226 goto bad;
227 n = strcspn(p, " \t\n");
228 if (n >= MAXHOSTNAMELEN)
229 goto bad;
230 strlcpy(hostname, p, n + 1);
231 return (0);
232
233bad:
234 errno = EINVAL;
235 return (-1);
236}