]> git.saurik.com Git - apple/network_cmds.git/blob - pcap/inet.c
network_cmds-76.tar.gz
[apple/network_cmds.git] / pcap / inet.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /* $OpenBSD: inet.c,v 1.6 1997/01/24 19:17:25 deraadt Exp $ */
25
26 /*
27 * Copyright (c) 1994, 1995, 1996
28 * The Regents of the University of California. All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the Computer Systems
41 * Engineering Group at Lawrence Berkeley Laboratory.
42 * 4. Neither the name of the University nor of the Laboratory may be used
43 * to endorse or promote products derived from this software without
44 * specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 */
58
59 #ifndef lint
60 static char rcsid[] =
61 "@(#) Header: inet.c,v 1.16 96/06/23 14:28:22 leres Exp (LBL)";
62 #endif
63
64 #include <sys/param.h>
65 #include <sys/file.h>
66 #include <sys/ioctl.h>
67 #include <sys/socket.h>
68 #ifdef HAVE_SYS_SOCKIO_H
69 #include <sys/sockio.h>
70 #endif
71
72 #if __STDC__
73 struct mbuf;
74 struct rtentry;
75 #endif
76
77 #include <net/if.h>
78 #include <netinet/in.h>
79
80 #include <ctype.h>
81 #include <errno.h>
82 #include <memory.h>
83 #include <stdio.h>
84 #include <stdlib.h>
85 #include <string.h>
86 #include <unistd.h>
87 #include <pcap.h>
88
89 #ifdef HAVE_OS_PROTO_H
90 #include "os-proto.h"
91 #endif
92
93 #include "pcap-int.h"
94
95 /* Not all systems have IFF_LOOPBACK */
96 #ifdef IFF_LOOPBACK
97 #define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK)
98 #else
99 #define ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0)
100 #endif
101
102 /*
103 * Return the name of a network interface attached to the system, or NULL
104 * if none can be found. The interface must be configured up; the
105 * lowest unit number is preferred; loopback is ignored.
106 */
107 char *
108 pcap_lookupdev(errbuf)
109 register char *errbuf;
110 {
111 register int fd, minunit, n;
112 register char *cp, *ibuf = NULL;
113 register struct ifreq *ifrp, *ifend, *ifnext, *mp;
114 struct ifconf ifc;
115 struct ifreq ifr;
116 static char device[sizeof(ifrp->ifr_name) + 1];
117 int len = 8192;
118
119 fd = socket(AF_INET, SOCK_DGRAM, 0);
120 if (fd < 0) {
121 (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno));
122 return (NULL);
123 }
124 while (1) {
125 ifc.ifc_len = len;
126 ifc.ifc_buf = ibuf = realloc(ibuf, len);
127 if (ibuf == NULL) {
128 close(fd);
129 return (NULL);
130 }
131 if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) {
132 (void)close(fd);
133 free(ibuf);
134 return (NULL);
135 }
136 if (ifc.ifc_len + sizeof(ifr) < len)
137 break;
138 len *= 2;
139 }
140
141 ifrp = (struct ifreq *)ibuf;
142 ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
143
144 mp = NULL;
145 minunit = 666;
146 for (; ifrp < ifend; ifrp = ifnext) {
147 #if BSD - 0 >= 199006
148 n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
149 if (n < sizeof(*ifrp))
150 ifnext = ifrp + 1;
151 else
152 ifnext = (struct ifreq *)((char *)ifrp + n);
153 if (ifrp->ifr_addr.sa_family != AF_INET)
154 continue;
155 #else
156 ifnext = ifrp + 1;
157 #endif
158 /*
159 * Need a template to preserve address info that is
160 * used below to locate the next entry. (Otherwise,
161 * SIOCGIFFLAGS stomps over it because the requests
162 * are returned in a union.)
163 */
164 strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
165 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
166 (void)sprintf(errbuf, "SIOCGIFFLAGS: %s",
167 pcap_strerror(errno));
168 (void)close(fd);
169 free(ibuf);
170 return (NULL);
171 }
172
173 /* Must be up and not the loopback */
174 if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr))
175 continue;
176
177 for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
178 continue;
179 n = atoi(cp);
180 if (n < minunit) {
181 minunit = n;
182 mp = ifrp;
183 }
184 }
185 free(ibuf);
186 (void)close(fd);
187 if (mp == NULL) {
188 (void)strcpy(errbuf, "no suitable device found");
189 return (NULL);
190 }
191
192 (void)strncpy(device, mp->ifr_name, sizeof(device) - 1);
193 device[sizeof(device) - 1] = '\0';
194 return (device);
195 }
196
197 int
198 pcap_lookupnet(device, netp, maskp, errbuf)
199 register char *device;
200 register bpf_u_int32 *netp, *maskp;
201 register char *errbuf;
202 {
203 register int fd;
204 register struct sockaddr_in *sin;
205 struct ifreq ifr;
206
207 fd = socket(AF_INET, SOCK_DGRAM, 0);
208 if (fd < 0) {
209 (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno));
210 return (-1);
211 }
212 memset(&ifr, 0, sizeof(ifr));
213 #ifdef linux
214 /* XXX Work around Linux kernel bug */
215 ifr.ifr_addr.sa_family = AF_INET;
216 #endif
217 (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
218 if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
219 (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s",
220 device, pcap_strerror(errno));
221 (void)close(fd);
222 return (-1);
223 }
224 sin = (struct sockaddr_in *)&ifr.ifr_addr;
225 *netp = sin->sin_addr.s_addr;
226 if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
227 (void)sprintf(errbuf, "SIOCGIFNETMASK: %s: %s",
228 device, pcap_strerror(errno));
229 (void)close(fd);
230 return (-1);
231 }
232 (void)close(fd);
233 *maskp = sin->sin_addr.s_addr;
234 if (*maskp == 0) {
235 if (IN_CLASSA(*netp))
236 *maskp = IN_CLASSA_NET;
237 else if (IN_CLASSB(*netp))
238 *maskp = IN_CLASSB_NET;
239 else if (IN_CLASSC(*netp))
240 *maskp = IN_CLASSC_NET;
241 else {
242 (void)sprintf(errbuf, "inet class for 0x%x unknown",
243 *netp);
244 return (-1);
245 }
246 }
247 *netp &= *maskp;
248 return (0);
249 }