GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/net/ethers.c Lines: 18 101 17.8 %
Date: 2017-11-07 Branches: 9 70 12.9 %

Line Branch Exec Source
1
/*	$OpenBSD: ethers.c,v 1.25 2016/09/21 04:38:56 guenther 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
#include <sys/types.h>
26
#include <sys/socket.h>
27
#include <net/if.h>
28
#include <netinet/in.h>
29
#include <netinet/if_ether.h>
30
#include <paths.h>
31
#include <errno.h>
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <ctype.h>
36
#include <limits.h>
37
#ifdef YP
38
#include <rpcsvc/ypclnt.h>
39
#endif
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 *
48
ether_ntoa(struct ether_addr *e)
49
{
50
	static char a[] = "xx:xx:xx:xx:xx:xx";
51
52
178
	(void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
53
356
	    e->ether_addr_octet[0], e->ether_addr_octet[1],
54
178
	    e->ether_addr_octet[2], e->ether_addr_octet[3],
55
178
	    e->ether_addr_octet[4], e->ether_addr_octet[5]);
56
57
178
	return (a);
58
}
59
60
static char *
61
_ether_aton(const char *s, struct ether_addr *e)
62
{
63
	int i;
64
	long l;
65
30
	char *pp;
66
67
30
	while (isspace((unsigned char)*s))
68
		s++;
69
70
	/* expect 6 hex octets separated by ':' or space/NUL if last octet */
71
210
	for (i = 0; i < 6; i++) {
72
90
		l = strtol(s, &pp, 16);
73
90
		if (pp == s || l > 0xFF || l < 0)
74
			return (NULL);
75

105
		if (!(*pp == ':' ||
76

30
		    (i == 5 && (isspace((unsigned char)*pp) ||
77
15
		    *pp == '\0'))))
78
			return (NULL);
79
90
		e->ether_addr_octet[i] = (u_char)l;
80
90
		s = pp + 1;
81
	}
82
83
	/* return character after the octets ala strtol(3) */
84
15
	return (pp);
85
15
}
86
87
struct ether_addr *
88
ether_aton(const char *s)
89
{
90
	static struct ether_addr n;
91
92
30
	return (_ether_aton(s, &n) ? &n : NULL);
93
}
94
95
int
96
ether_ntohost(char *hostname, struct ether_addr *e)
97
{
98
	FILE *f;
99
	char buf[BUFSIZ+1], *p;
100
	size_t len;
101
	struct ether_addr try;
102
#ifdef YP
103
	char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
104
	int trylen;
105
#endif
106
107
#ifdef YP
108
	snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
109
	    e->ether_addr_octet[0], e->ether_addr_octet[1],
110
	    e->ether_addr_octet[2], e->ether_addr_octet[3],
111
	    e->ether_addr_octet[4], e->ether_addr_octet[5]);
112
	trylen = strlen(trybuf);
113
#endif
114
115
	f = fopen(_PATH_ETHERS, "re");
116
	if (f == NULL)
117
		return (-1);
118
	while ((p = fgetln(f, &len)) != NULL) {
119
		if (p[len-1] == '\n')
120
			len--;
121
		if (len > sizeof(buf) - 2)
122
			continue;
123
		(void)memcpy(buf, p, len);
124
		buf[len] = '\n';	/* code assumes newlines later on */
125
		buf[len+1] = '\0';
126
#ifdef YP
127
		/* A + in the file means try YP now.  */
128
		if (!strncmp(buf, "+\n", sizeof(buf))) {
129
			char *ypbuf, *ypdom;
130
			int ypbuflen;
131
132
			if (yp_get_default_domain(&ypdom))
133
				continue;
134
			if (yp_match(ypdom, "ethers.byaddr", trybuf,
135
			    trylen, &ypbuf, &ypbuflen))
136
				continue;
137
			if (ether_line(ypbuf, &try, hostname) == 0) {
138
				free(ypbuf);
139
				(void)fclose(f);
140
				return (0);
141
			}
142
			free(ypbuf);
143
			continue;
144
		}
145
#endif
146
		if (ether_line(buf, &try, hostname) == 0 &&
147
		    memcmp(&try, e, sizeof(try)) == 0) {
148
			(void)fclose(f);
149
			return (0);
150
		}
151
	}
152
	(void)fclose(f);
153
	errno = ENOENT;
154
	return (-1);
155
}
156
157
int
158
ether_hostton(const char *hostname, struct ether_addr *e)
159
{
160
	FILE *f;
161
	char buf[BUFSIZ+1], *p;
162
	char try[HOST_NAME_MAX+1];
163
	size_t len;
164
#ifdef YP
165
	int hostlen = strlen(hostname);
166
#endif
167
168
	f = fopen(_PATH_ETHERS, "re");
169
	if (f==NULL)
170
		return (-1);
171
172
	while ((p = fgetln(f, &len)) != NULL) {
173
		if (p[len-1] == '\n')
174
			len--;
175
		if (len > sizeof(buf) - 2)
176
			continue;
177
		memcpy(buf, p, len);
178
		buf[len] = '\n';	/* code assumes newlines later on */
179
		buf[len+1] = '\0';
180
#ifdef YP
181
		/* A + in the file means try YP now.  */
182
		if (!strncmp(buf, "+\n", sizeof(buf))) {
183
			char *ypbuf, *ypdom;
184
			int ypbuflen;
185
186
			if (yp_get_default_domain(&ypdom))
187
				continue;
188
			if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
189
			    &ypbuf, &ypbuflen))
190
				continue;
191
			if (ether_line(ypbuf, e, try) == 0) {
192
				free(ypbuf);
193
				(void)fclose(f);
194
				return (0);
195
			}
196
			free(ypbuf);
197
			continue;
198
		}
199
#endif
200
		if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
201
			(void)fclose(f);
202
			return (0);
203
		}
204
	}
205
	(void)fclose(f);
206
	errno = ENOENT;
207
	return (-1);
208
}
209
210
int
211
ether_line(const char *line, struct ether_addr *e, char *hostname)
212
{
213
	char *p;
214
	size_t n;
215
216
	/* Parse "xx:xx:xx:xx:xx:xx" */
217
	if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
218
		goto bad;
219
220
	/* Now get the hostname */
221
	while (isspace((unsigned char)*p))
222
		p++;
223
	if (*p == '\0')
224
		goto bad;
225
	n = strcspn(p, " \t\n");
226
	if (n >= HOST_NAME_MAX+1)
227
		goto bad;
228
	strlcpy(hostname, p, n + 1);
229
	return (0);
230
231
bad:
232
	errno = EINVAL;
233
	return (-1);
234
}
235
DEF_WEAK(ether_line);