Drop main() prototype. Syncs with NetBSD-8
[minix.git] / external / bsd / libpcap / dist / fad-glifc.c
blob1d436dba23484b03b33762ab7e5c33f40080c5ee
1 /* $NetBSD: fad-glifc.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */
3 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
4 /*
5 * Copyright (c) 1994, 1995, 1996, 1997, 1998
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the Computer Systems
19 * Engineering Group at Lawrence Berkeley Laboratory.
20 * 4. Neither the name of the University nor of the Laboratory may be used
21 * to endorse or promote products derived from this software without
22 * specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
37 #include <sys/cdefs.h>
38 __RCSID("$NetBSD: fad-glifc.c,v 1.2 2014/11/19 19:33:30 christos Exp $");
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
44 #include <sys/param.h>
45 #include <sys/file.h>
46 #include <sys/ioctl.h>
47 #include <sys/socket.h>
48 #ifdef HAVE_SYS_SOCKIO_H
49 #include <sys/sockio.h>
50 #endif
51 #include <sys/time.h> /* concession to AIX */
53 struct mbuf; /* Squelch compiler warnings on some platforms for */
54 struct rtentry; /* declarations in <net/if.h> */
55 #include <net/if.h>
56 #include <netinet/in.h>
58 #include <ctype.h>
59 #include <errno.h>
60 #include <memory.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <unistd.h>
66 #include "pcap-int.h"
68 #ifdef HAVE_OS_PROTO_H
69 #include "os-proto.h"
70 #endif
73 * Get a list of all interfaces that are up and that we can open.
74 * Returns -1 on error, 0 otherwise.
75 * The list, as returned through "alldevsp", may be null if no interfaces
76 * were up and could be opened.
78 * This is the implementation used on platforms that have SIOCGLIFCONF
79 * but don't have "getifaddrs()". (Solaris 8 and later; we use
80 * SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
82 int
83 pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
85 pcap_if_t *devlist = NULL;
86 register int fd4, fd6, fd;
87 register struct lifreq *ifrp, *ifend;
88 struct lifnum ifn;
89 struct lifconf ifc;
90 char *buf = NULL;
91 unsigned buf_size;
92 #ifdef HAVE_SOLARIS
93 char *p, *q;
94 #endif
95 struct lifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
96 struct sockaddr *netmask, *broadaddr, *dstaddr;
97 int ret = 0;
100 * Create a socket from which to fetch the list of interfaces,
101 * and from which to fetch IPv4 information.
103 fd4 = socket(AF_INET, SOCK_DGRAM, 0);
104 if (fd4 < 0) {
105 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
106 "socket: %s", pcap_strerror(errno));
107 return (-1);
111 * Create a socket from which to fetch IPv6 information.
113 fd6 = socket(AF_INET6, SOCK_DGRAM, 0);
114 if (fd6 < 0) {
115 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
116 "socket: %s", pcap_strerror(errno));
117 (void)close(fd4);
118 return (-1);
122 * How many entries will SIOCGLIFCONF return?
124 ifn.lifn_family = AF_UNSPEC;
125 ifn.lifn_flags = 0;
126 ifn.lifn_count = 0;
127 if (ioctl(fd4, SIOCGLIFNUM, (char *)&ifn) < 0) {
128 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
129 "SIOCGLIFNUM: %s", pcap_strerror(errno));
130 (void)close(fd6);
131 (void)close(fd4);
132 return (-1);
136 * Allocate a buffer for those entries.
138 buf_size = ifn.lifn_count * sizeof (struct lifreq);
139 buf = malloc(buf_size);
140 if (buf == NULL) {
141 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
142 "malloc: %s", pcap_strerror(errno));
143 (void)close(fd6);
144 (void)close(fd4);
145 return (-1);
149 * Get the entries.
151 ifc.lifc_len = buf_size;
152 ifc.lifc_buf = buf;
153 ifc.lifc_family = AF_UNSPEC;
154 ifc.lifc_flags = 0;
155 memset(buf, 0, buf_size);
156 if (ioctl(fd4, SIOCGLIFCONF, (char *)&ifc) < 0) {
157 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
158 "SIOCGLIFCONF: %s", pcap_strerror(errno));
159 (void)close(fd6);
160 (void)close(fd4);
161 free(buf);
162 return (-1);
166 * Loop over the entries.
168 ifrp = (struct lifreq *)buf;
169 ifend = (struct lifreq *)(buf + ifc.lifc_len);
171 for (; ifrp < ifend; ifrp++) {
173 * IPv6 or not?
175 if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6)
176 fd = fd6;
177 else
178 fd = fd4;
181 * Skip entries that begin with "dummy".
182 * XXX - what are these? Is this Linux-specific?
183 * Are there platforms on which we shouldn't do this?
185 if (strncmp(ifrp->lifr_name, "dummy", 5) == 0)
186 continue;
188 #ifdef HAVE_SOLARIS
190 * Skip entries that have a ":" followed by a number
191 * at the end - those are Solaris virtual interfaces
192 * on which you can't capture.
194 p = strchr(ifrp->lifr_name, ':');
195 if (p != NULL) {
197 * We have a ":"; is it followed by a number?
199 while (isdigit((unsigned char)*p))
200 p++;
201 if (*p == '\0') {
203 * All digits after the ":" until the end.
205 continue;
208 #endif
211 * Get the flags for this interface.
213 strncpy(ifrflags.lifr_name, ifrp->lifr_name,
214 sizeof(ifrflags.lifr_name));
215 if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) {
216 if (errno == ENXIO)
217 continue;
218 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
219 "SIOCGLIFFLAGS: %.*s: %s",
220 (int)sizeof(ifrflags.lifr_name),
221 ifrflags.lifr_name,
222 pcap_strerror(errno));
223 ret = -1;
224 break;
228 * Get the netmask for this address on this interface.
230 strncpy(ifrnetmask.lifr_name, ifrp->lifr_name,
231 sizeof(ifrnetmask.lifr_name));
232 memcpy(&ifrnetmask.lifr_addr, &ifrp->lifr_addr,
233 sizeof(ifrnetmask.lifr_addr));
234 if (ioctl(fd, SIOCGLIFNETMASK, (char *)&ifrnetmask) < 0) {
235 if (errno == EADDRNOTAVAIL) {
237 * Not available.
239 netmask = NULL;
240 } else {
241 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
242 "SIOCGLIFNETMASK: %.*s: %s",
243 (int)sizeof(ifrnetmask.lifr_name),
244 ifrnetmask.lifr_name,
245 pcap_strerror(errno));
246 ret = -1;
247 break;
249 } else
250 netmask = (struct sockaddr *)&ifrnetmask.lifr_addr;
253 * Get the broadcast address for this address on this
254 * interface (if any).
256 if (ifrflags.lifr_flags & IFF_BROADCAST) {
257 strncpy(ifrbroadaddr.lifr_name, ifrp->lifr_name,
258 sizeof(ifrbroadaddr.lifr_name));
259 memcpy(&ifrbroadaddr.lifr_addr, &ifrp->lifr_addr,
260 sizeof(ifrbroadaddr.lifr_addr));
261 if (ioctl(fd, SIOCGLIFBRDADDR,
262 (char *)&ifrbroadaddr) < 0) {
263 if (errno == EADDRNOTAVAIL) {
265 * Not available.
267 broadaddr = NULL;
268 } else {
269 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
270 "SIOCGLIFBRDADDR: %.*s: %s",
271 (int)sizeof(ifrbroadaddr.lifr_name),
272 ifrbroadaddr.lifr_name,
273 pcap_strerror(errno));
274 ret = -1;
275 break;
277 } else
278 broadaddr = (struct sockaddr *)&ifrbroadaddr.lifr_broadaddr;
279 } else {
281 * Not a broadcast interface, so no broadcast
282 * address.
284 broadaddr = NULL;
288 * Get the destination address for this address on this
289 * interface (if any).
291 if (ifrflags.lifr_flags & IFF_POINTOPOINT) {
292 strncpy(ifrdstaddr.lifr_name, ifrp->lifr_name,
293 sizeof(ifrdstaddr.lifr_name));
294 memcpy(&ifrdstaddr.lifr_addr, &ifrp->lifr_addr,
295 sizeof(ifrdstaddr.lifr_addr));
296 if (ioctl(fd, SIOCGLIFDSTADDR,
297 (char *)&ifrdstaddr) < 0) {
298 if (errno == EADDRNOTAVAIL) {
300 * Not available.
302 dstaddr = NULL;
303 } else {
304 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
305 "SIOCGLIFDSTADDR: %.*s: %s",
306 (int)sizeof(ifrdstaddr.lifr_name),
307 ifrdstaddr.lifr_name,
308 pcap_strerror(errno));
309 ret = -1;
310 break;
312 } else
313 dstaddr = (struct sockaddr *)&ifrdstaddr.lifr_dstaddr;
314 } else
315 dstaddr = NULL;
317 #ifdef HAVE_SOLARIS
319 * If this entry has a colon followed by a number at
320 * the end, it's a logical interface. Those are just
321 * the way you assign multiple IP addresses to a real
322 * interface, so an entry for a logical interface should
323 * be treated like the entry for the real interface;
324 * we do that by stripping off the ":" and the number.
326 p = strchr(ifrp->lifr_name, ':');
327 if (p != NULL) {
329 * We have a ":"; is it followed by a number?
331 q = p + 1;
332 while (isdigit((unsigned char)*q))
333 q++;
334 if (*q == '\0') {
336 * All digits after the ":" until the end.
337 * Strip off the ":" and everything after
338 * it.
340 *p = '\0';
343 #endif
346 * Add information for this address to the list.
348 if (add_addr_to_iflist(&devlist, ifrp->lifr_name,
349 ifrflags.lifr_flags, (struct sockaddr *)&ifrp->lifr_addr,
350 sizeof (struct sockaddr_storage),
351 netmask, sizeof (struct sockaddr_storage),
352 broadaddr, sizeof (struct sockaddr_storage),
353 dstaddr, sizeof (struct sockaddr_storage), errbuf) < 0) {
354 ret = -1;
355 break;
358 free(buf);
359 (void)close(fd6);
360 (void)close(fd4);
362 if (ret == -1) {
364 * We had an error; free the list we've been constructing.
366 if (devlist != NULL) {
367 pcap_freealldevs(devlist);
368 devlist = NULL;
372 *alldevsp = devlist;
373 return (ret);