Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / libpcap / fad-glifc.c
blob99ca820a4d9fdaa911c6dd988f5f854097b0f466
1 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
2 /*
3 * Copyright (c) 1994, 1995, 1996, 1997, 1998
4 * The Regents of the University of California. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the Computer Systems
17 * Engineering Group at Lawrence Berkeley Laboratory.
18 * 4. Neither the name of the University nor of the Laboratory may be used
19 * to endorse or promote products derived from this software without
20 * specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
35 #ifndef lint
36 static const char rcsid[] _U_ =
37 "@(#) $Header: /pub/NetBSD/misc/repositories/cvsroot/src/dist/libpcap/fad-glifc.c,v 1.1.1.1 2006/02/27 15:45:44 drochner Exp $ (LBL)";
38 #endif
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 SIOCLGIFCONF
79 * but don't have "getifaddrs()". (Solaris 8 and later; we use
80 * SIOCLGIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
82 int
83 pcap_findalldevs(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, and skip it if it's
212 * not up.
214 strncpy(ifrflags.lifr_name, ifrp->lifr_name,
215 sizeof(ifrflags.lifr_name));
216 if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) {
217 if (errno == ENXIO)
218 continue;
219 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
220 "SIOCGLIFFLAGS: %.*s: %s",
221 (int)sizeof(ifrflags.lifr_name),
222 ifrflags.lifr_name,
223 pcap_strerror(errno));
224 ret = -1;
225 break;
227 if (!(ifrflags.lifr_flags & IFF_UP))
228 continue;
231 * Get the netmask for this address on this interface.
233 strncpy(ifrnetmask.lifr_name, ifrp->lifr_name,
234 sizeof(ifrnetmask.lifr_name));
235 memcpy(&ifrnetmask.lifr_addr, &ifrp->lifr_addr,
236 sizeof(ifrnetmask.lifr_addr));
237 if (ioctl(fd, SIOCGLIFNETMASK, (char *)&ifrnetmask) < 0) {
238 if (errno == EADDRNOTAVAIL) {
240 * Not available.
242 netmask = NULL;
243 } else {
244 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
245 "SIOCGLIFNETMASK: %.*s: %s",
246 (int)sizeof(ifrnetmask.lifr_name),
247 ifrnetmask.lifr_name,
248 pcap_strerror(errno));
249 ret = -1;
250 break;
252 } else
253 netmask = (struct sockaddr *)&ifrnetmask.lifr_addr;
256 * Get the broadcast address for this address on this
257 * interface (if any).
259 if (ifrflags.lifr_flags & IFF_BROADCAST) {
260 strncpy(ifrbroadaddr.lifr_name, ifrp->lifr_name,
261 sizeof(ifrbroadaddr.lifr_name));
262 memcpy(&ifrbroadaddr.lifr_addr, &ifrp->lifr_addr,
263 sizeof(ifrbroadaddr.lifr_addr));
264 if (ioctl(fd, SIOCGLIFBRDADDR,
265 (char *)&ifrbroadaddr) < 0) {
266 if (errno == EADDRNOTAVAIL) {
268 * Not available.
270 broadaddr = NULL;
271 } else {
272 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
273 "SIOCGLIFBRDADDR: %.*s: %s",
274 (int)sizeof(ifrbroadaddr.lifr_name),
275 ifrbroadaddr.lifr_name,
276 pcap_strerror(errno));
277 ret = -1;
278 break;
280 } else
281 broadaddr = (struct sockaddr *)&ifrbroadaddr.lifr_broadaddr;
282 } else {
284 * Not a broadcast interface, so no broadcast
285 * address.
287 broadaddr = NULL;
291 * Get the destination address for this address on this
292 * interface (if any).
294 if (ifrflags.lifr_flags & IFF_POINTOPOINT) {
295 strncpy(ifrdstaddr.lifr_name, ifrp->lifr_name,
296 sizeof(ifrdstaddr.lifr_name));
297 memcpy(&ifrdstaddr.lifr_addr, &ifrp->lifr_addr,
298 sizeof(ifrdstaddr.lifr_addr));
299 if (ioctl(fd, SIOCGLIFDSTADDR,
300 (char *)&ifrdstaddr) < 0) {
301 if (errno == EADDRNOTAVAIL) {
303 * Not available.
305 dstaddr = NULL;
306 } else {
307 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
308 "SIOCGLIFDSTADDR: %.*s: %s",
309 (int)sizeof(ifrdstaddr.lifr_name),
310 ifrdstaddr.lifr_name,
311 pcap_strerror(errno));
312 ret = -1;
313 break;
315 } else
316 dstaddr = (struct sockaddr *)&ifrdstaddr.lifr_dstaddr;
317 } else
318 dstaddr = NULL;
320 #ifdef HAVE_SOLARIS
322 * If this entry has a colon followed by a number at
323 * the end, it's a logical interface. Those are just
324 * the way you assign multiple IP addresses to a real
325 * interface, so an entry for a logical interface should
326 * be treated like the entry for the real interface;
327 * we do that by stripping off the ":" and the number.
329 p = strchr(ifrp->lifr_name, ':');
330 if (p != NULL) {
332 * We have a ":"; is it followed by a number?
334 q = p + 1;
335 while (isdigit((unsigned char)*q))
336 q++;
337 if (*q == '\0') {
339 * All digits after the ":" until the end.
340 * Strip off the ":" and everything after
341 * it.
343 *p = '\0';
346 #endif
349 * Add information for this address to the list.
351 if (add_addr_to_iflist(&devlist, ifrp->lifr_name,
352 ifrflags.lifr_flags, (struct sockaddr *)&ifrp->lifr_addr,
353 sizeof (struct sockaddr_storage),
354 netmask, sizeof (struct sockaddr_storage),
355 broadaddr, sizeof (struct sockaddr_storage),
356 dstaddr, sizeof (struct sockaddr_storage), errbuf) < 0) {
357 ret = -1;
358 break;
361 free(buf);
362 (void)close(fd6);
363 (void)close(fd4);
365 if (ret != -1) {
367 * We haven't had any errors yet; do any platform-specific
368 * operations to add devices.
370 if (pcap_platform_finddevs(&devlist, errbuf) < 0)
371 ret = -1;
374 if (ret == -1) {
376 * We had an error; free the list we've been constructing.
378 if (devlist != NULL) {
379 pcap_freealldevs(devlist);
380 devlist = NULL;
384 *alldevsp = devlist;
385 return (ret);