1 /** $MirOS: src/lib/libc/net/ethers.c,v 1.4 2005/09/22 20:40:02 tg Exp $ */
2 /* $OpenBSD: ethers.c,v 1.20 2005/08/06 20:30:03 espie Exp $ */
3
4 /*
5 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*
21 * ethers(3) a la Sun.
22 * Originally Written by Roland McGrath <roland@frob.com> 10/14/93.
23 * Substantially modified by Todd C. Miller <Todd.Miller@courtesan.com>
24 */
25
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <net/if.h>
29 #include <netinet/in.h>
30 #include <netinet/if_ether.h>
31 #include <sys/param.h>
32 #include <paths.h>
33 #include <errno.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38
39 __RCSID("$MirOS: src/lib/libc/net/ethers.c,v 1.4 2005/09/22 20:40:02 tg Exp $");
40
41 #ifndef _PATH_ETHERS
42 #define _PATH_ETHERS "/etc/ethers"
43 #endif
44
45 static char * _ether_aton(const char *, struct ether_addr *);
46
47 char *
ether_ntoa(struct ether_addr * e)48 ether_ntoa(struct ether_addr *e)
49 {
50 static char a[] = "xx:xx:xx:xx:xx:xx";
51
52 (void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
53 e->ether_addr_octet[0], e->ether_addr_octet[1],
54 e->ether_addr_octet[2], e->ether_addr_octet[3],
55 e->ether_addr_octet[4], e->ether_addr_octet[5]);
56
57 return (a);
58 }
59
60 static char *
_ether_aton(const char * s,struct ether_addr * e)61 _ether_aton(const char *s, struct ether_addr *e)
62 {
63 int i;
64 long l;
65 char *pp;
66
67 while (isspace(*s))
68 s++;
69
70 /* expect 6 hex octets separated by ':' or space/NUL if last octet */
71 for (i = 0; i < 6; i++) {
72 l = strtol(s, &pp, 16);
73 if (pp == s || l > 0xFF || l < 0)
74 return (NULL);
75 if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
76 return (NULL);
77 e->ether_addr_octet[i] = (u_char)l;
78 s = pp + 1;
79 }
80
81 /* return character after the octets ala strtol(3) */
82 return (pp);
83 }
84
85 struct ether_addr *
ether_aton(const char * s)86 ether_aton(const char *s)
87 {
88 static struct ether_addr n;
89
90 return (_ether_aton(s, &n) ? &n : NULL);
91 }
92
93 int
ether_ntohost(char * hostname,struct ether_addr * e)94 ether_ntohost(char *hostname, struct ether_addr *e)
95 {
96 FILE *f;
97 char buf[BUFSIZ+1], *p;
98 size_t len;
99 struct ether_addr try;
100
101 f = fopen(_PATH_ETHERS, "r");
102 if (f == NULL)
103 return (-1);
104 while ((p = fgetln(f, &len)) != NULL) {
105 if (p[len-1] == '\n')
106 len--;
107 if (len > sizeof(buf) - 2)
108 continue;
109 (void)memcpy(buf, p, len);
110 buf[len] = '\n'; /* code assumes newlines later on */
111 buf[len+1] = '\0';
112 if (ether_line(buf, &try, hostname) == 0 &&
113 memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
114 (void)fclose(f);
115 return (0);
116 }
117 }
118 (void)fclose(f);
119 errno = ENOENT;
120 return (-1);
121 }
122
123 int
ether_hostton(const char * hostname,struct ether_addr * e)124 ether_hostton(const char *hostname, struct ether_addr *e)
125 {
126 FILE *f;
127 char buf[BUFSIZ+1], *p;
128 char try[MAXHOSTNAMELEN];
129 size_t len;
130
131 f = fopen(_PATH_ETHERS, "r");
132 if (f==NULL)
133 return (-1);
134
135 while ((p = fgetln(f, &len)) != NULL) {
136 if (p[len-1] == '\n')
137 len--;
138 if (len > sizeof(buf) - 2)
139 continue;
140 memcpy(buf, p, len);
141 buf[len] = '\n'; /* code assumes newlines later on */
142 buf[len+1] = '\0';
143 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
144 (void)fclose(f);
145 return (0);
146 }
147 }
148 (void)fclose(f);
149 errno = ENOENT;
150 return (-1);
151 }
152
153 int
ether_line(const char * line,struct ether_addr * e,char * hostname)154 ether_line(const char *line, struct ether_addr *e, char *hostname)
155 {
156 char *p;
157 size_t n;
158
159 /* Parse "xx:xx:xx:xx:xx:xx" */
160 if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
161 goto bad;
162
163 /* Now get the hostname */
164 while (isspace(*p))
165 p++;
166 if (*p == '\0')
167 goto bad;
168 n = strcspn(p, " \t\n");
169 if (n >= MAXHOSTNAMELEN)
170 goto bad;
171 strlcpy(hostname, p, n + 1);
172 return (0);
173
174 bad:
175 errno = EINVAL;
176 return (-1);
177 }
178