GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libpcap/inet.c Lines: 0 66 0.0 %
Date: 2017-11-07 Branches: 0 34 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: inet.c,v 1.24 2015/12/22 19:51:04 mmcc Exp $	*/
2
3
/*
4
 * Copyright (c) 1994, 1995, 1996, 1997, 1998
5
 *	The Regents of the University of California.  All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 * 3. All advertising materials mentioning features or use of this software
16
 *    must display the following acknowledgement:
17
 *	This product includes software developed by the Computer Systems
18
 *	Engineering Group at Lawrence Berkeley Laboratory.
19
 * 4. Neither the name of the University nor of the Laboratory may be used
20
 *    to endorse or promote products derived from this software without
21
 *    specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 */
35
36
37
#include <sys/file.h>
38
#include <sys/ioctl.h>
39
#include <sys/socket.h>
40
#ifdef HAVE_SYS_SOCKIO_H
41
#include <sys/sockio.h>
42
#endif
43
#include <sys/time.h>				/* concession to AIX */
44
45
struct mbuf;
46
struct rtentry;
47
48
#include <net/if.h>
49
#include <netinet/in.h>
50
51
#include <ctype.h>
52
#include <errno.h>
53
#include <stdio.h>
54
#include <stdlib.h>
55
#include <string.h>
56
#include <unistd.h>
57
#ifdef HAVE_IFADDRS_H
58
#include <ifaddrs.h>
59
#endif
60
61
#include "pcap-int.h"
62
63
#ifdef HAVE_OS_PROTO_H
64
#include "os-proto.h"
65
#endif
66
67
/*
68
 * Free a list of interfaces.
69
 */
70
void
71
pcap_freealldevs(pcap_if_t *alldevs)
72
{
73
	pcap_if_t *curdev, *nextdev;
74
	pcap_addr_t *curaddr, *nextaddr;
75
76
	for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
77
		nextdev = curdev->next;
78
79
		/*
80
		 * Free all addresses.
81
		 */
82
		for (curaddr = curdev->addresses; curaddr != NULL;
83
		    curaddr = nextaddr) {
84
			nextaddr = curaddr->next;
85
			free(curaddr->addr);
86
			free(curaddr->netmask);
87
			free(curaddr->broadaddr);
88
			free(curaddr->dstaddr);
89
			free(curaddr);
90
		}
91
92
		/*
93
		 * Free the name string.
94
		 */
95
		free(curdev->name);
96
97
		/*
98
		 * Free the description string, if any.
99
		 */
100
		free(curdev->description);
101
102
		/*
103
		 * Free the interface.
104
		 */
105
		free(curdev);
106
	}
107
}
108
109
/*
110
 * Return the name of a network interface attached to the system, or NULL
111
 * if none can be found.  The interface must be configured up; the
112
 * lowest unit number is preferred; loopback is ignored.
113
 */
114
char *
115
pcap_lookupdev(errbuf)
116
	char *errbuf;
117
{
118
#ifdef HAVE_IFADDRS_H
119
	struct ifaddrs *ifap, *ifa, *mp;
120
	int n, minunit;
121
	char *cp;
122
	static char device[IF_NAMESIZE + 1];
123
124
	if (getifaddrs(&ifap) != 0) {
125
		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
126
		    "getifaddrs: %s", pcap_strerror(errno));
127
		return NULL;
128
	}
129
130
	mp = NULL;
131
	minunit = 666;
132
	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
133
		if ((ifa->ifa_flags & IFF_UP) == 0)
134
			continue;
135
		if (ISLOOPBACK(ifa->ifa_name, ifa->ifa_flags))
136
			continue;
137
		for (cp = ifa->ifa_name; !isdigit((unsigned char)*cp); ++cp)
138
			continue;
139
		n = atoi(cp);
140
		if (n < minunit) {
141
			minunit = n;
142
			mp = ifa;
143
		}
144
	}
145
	if (mp == NULL) {
146
		(void)strlcpy(errbuf, "no suitable device found",
147
		    PCAP_ERRBUF_SIZE);
148
		freeifaddrs(ifap);
149
		return (NULL);
150
	}
151
152
	(void)strlcpy(device, mp->ifa_name, sizeof(device));
153
	freeifaddrs(ifap);
154
	return (device);
155
#else
156
	int fd, minunit, n;
157
	char *cp;
158
	struct ifreq *ifrp, *ifend, *ifnext, *mp;
159
	struct ifconf ifc;
160
	struct ifreq ibuf[16], ifr;
161
	static char device[sizeof(ifrp->ifr_name) + 1];
162
163
	fd = socket(AF_INET, SOCK_DGRAM, 0);
164
	if (fd < 0) {
165
		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
166
		    pcap_strerror(errno));
167
		return (NULL);
168
	}
169
	ifc.ifc_len = sizeof ibuf;
170
	ifc.ifc_buf = (caddr_t)ibuf;
171
172
	memset((char *)ibuf, 0, sizeof(ibuf));
173
	if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
174
	    ifc.ifc_len < sizeof(struct ifreq)) {
175
		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFCONF: %s",
176
		    pcap_strerror(errno));
177
		(void)close(fd);
178
		return (NULL);
179
	}
180
	ifrp = ibuf;
181
	ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
182
183
	mp = NULL;
184
	minunit = 666;
185
	for (; ifrp < ifend; ifrp = ifnext) {
186
#ifdef HAVE_SOCKADDR_SA_LEN
187
		n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
188
		if (n < sizeof(*ifrp))
189
			ifnext = ifrp + 1;
190
		else
191
			ifnext = (struct ifreq *)((char *)ifrp + n);
192
		if (ifrp->ifr_addr.sa_family != AF_INET)
193
			continue;
194
#else
195
		ifnext = ifrp + 1;
196
#endif
197
		/*
198
		 * Need a template to preserve address info that is
199
		 * used below to locate the next entry.  (Otherwise,
200
		 * SIOCGIFFLAGS stomps over it because the requests
201
		 * are returned in a union.)
202
		 */
203
		(void)strlcpy(ifr.ifr_name, ifrp->ifr_name,
204
		    sizeof(ifr.ifr_name));
205
		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
206
			if (errno == ENXIO)
207
				continue;
208
			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
209
			    "SIOCGIFFLAGS: %.*s: %s",
210
			    (int)sizeof(ifr.ifr_name), ifr.ifr_name,
211
			    pcap_strerror(errno));
212
			(void)close(fd);
213
			return (NULL);
214
		}
215
216
		/* Must be up and not the loopback */
217
		if ((ifr.ifr_flags & IFF_UP) == 0 ||
218
		    ISLOOPBACK(ifr.ifr_name, ifr.ifr_flags))
219
			continue;
220
221
		for (cp = ifrp->ifr_name; !isdigit((unsigned char)*cp); ++cp)
222
			continue;
223
		n = atoi(cp);
224
		if (n < minunit) {
225
			minunit = n;
226
			mp = ifrp;
227
		}
228
	}
229
	(void)close(fd);
230
	if (mp == NULL) {
231
		(void)strlcpy(errbuf, "no suitable device found",
232
		    PCAP_ERRBUF_SIZE);
233
		return (NULL);
234
	}
235
236
	(void)strlcpy(device, mp->ifr_name, sizeof(device));
237
	return (device);
238
#endif
239
}
240
241
int
242
pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp,
243
    char *errbuf)
244
{
245
	int fd;
246
	struct sockaddr_in *sin;
247
	struct ifreq ifr;
248
249
	fd = socket(AF_INET, SOCK_DGRAM, 0);
250
	if (fd < 0) {
251
		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
252
		    pcap_strerror(errno));
253
		return (-1);
254
	}
255
	memset(&ifr, 0, sizeof(ifr));
256
#ifdef linux
257
	/* XXX Work around Linux kernel bug */
258
	ifr.ifr_addr.sa_family = AF_INET;
259
#endif
260
	(void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
261
	if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
262
		if (errno == EADDRNOTAVAIL) {
263
			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
264
			    "%s: no IPv4 address assigned", device);
265
		} else {
266
			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
267
			    "SIOCGIFADDR: %s: %s",
268
			    device, pcap_strerror(errno));
269
		}
270
		(void)close(fd);
271
		return (-1);
272
	}
273
	sin = (struct sockaddr_in *)&ifr.ifr_addr;
274
	*netp = sin->sin_addr.s_addr;
275
	if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
276
		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
277
		    "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
278
		(void)close(fd);
279
		return (-1);
280
	}
281
	(void)close(fd);
282
	*maskp = sin->sin_addr.s_addr;
283
	if (*maskp == 0) {
284
		if (IN_CLASSA(*netp))
285
			*maskp = IN_CLASSA_NET;
286
		else if (IN_CLASSB(*netp))
287
			*maskp = IN_CLASSB_NET;
288
		else if (IN_CLASSC(*netp))
289
			*maskp = IN_CLASSC_NET;
290
		else {
291
			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
292
			    "inet class for 0x%x unknown", *netp);
293
			return (-1);
294
		}
295
	}
296
	*netp &= *maskp;
297
	return (0);
298
}