Sync with FreeBSD. This adds read-only support for zip and ISO9660.
[dragonfly.git] / contrib / libpcap-0.8.3 / inet.c
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.
5  *
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.
21  *
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.
33  */
34
35 #ifndef lint
36 static const char rcsid[] _U_ =
37     "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.58.2.1 2003/11/15 23:26:41 guy Exp $ (LBL)";
38 #endif
39
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43
44 #ifdef WIN32
45 #include <pcap-stdinc.h>
46 #else /* WIN32 */
47
48 #include <sys/param.h>
49 #include <sys/file.h>
50 #include <sys/ioctl.h>
51 #include <sys/socket.h>
52 #ifdef HAVE_SYS_SOCKIO_H
53 #include <sys/sockio.h>
54 #endif
55 #include <sys/time.h>                           /* concession to AIX */
56
57 struct mbuf;            /* Squelch compiler warnings on some platforms for */
58 struct rtentry;         /* declarations in <net/if.h> */
59 #include <net/if.h>
60 #include <netinet/in.h>
61 #endif /* WIN32 */
62
63 #include <ctype.h>
64 #include <errno.h>
65 #include <memory.h>
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #ifndef WIN32
70 #include <unistd.h>
71 #endif /* WIN32 */
72 #ifdef HAVE_LIMITS_H
73 #include <limits.h>
74 #else
75 #define INT_MAX         2147483647
76 #endif
77 #ifdef HAVE_IFADDRS_H
78 #include <ifaddrs.h>
79 #endif
80
81 #include "pcap-int.h"
82
83 #ifdef HAVE_OS_PROTO_H
84 #include "os-proto.h"
85 #endif
86
87 /* Not all systems have IFF_LOOPBACK */
88 #ifdef IFF_LOOPBACK
89 #define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
90 #else
91 #define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
92     (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
93 #endif
94
95 struct sockaddr *
96 dup_sockaddr(struct sockaddr *sa, size_t sa_length)
97 {
98         struct sockaddr *newsa;
99
100         if ((newsa = malloc(sa_length)) == NULL)
101                 return (NULL);
102         return (memcpy(newsa, sa, sa_length));
103 }
104
105 static int
106 get_instance(const char *name)
107 {
108         const char *cp, *endcp;
109         int n;
110
111         if (strcmp(name, "any") == 0) {
112                 /*
113                  * Give the "any" device an artificially high instance
114                  * number, so it shows up after all other non-loopback
115                  * interfaces.
116                  */
117                 return INT_MAX;
118         }
119
120         endcp = name + strlen(name);
121         for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
122                 continue;
123
124         if (isdigit((unsigned char)*cp))
125                 n = atoi(cp);
126         else
127                 n = 0;
128         return (n);
129 }
130
131 int
132 add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
133     u_int flags, const char *description, char *errbuf)
134 {
135         pcap_if_t *curdev, *prevdev, *nextdev;
136         int this_instance;
137
138         /*
139          * Is there already an entry in the list for this interface?
140          */
141         for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
142                 if (strcmp(name, curdev->name) == 0)
143                         break;  /* yes, we found it */
144         }
145         if (curdev == NULL) {
146                 /*
147                  * No, we didn't find it.
148                  * Allocate a new entry.
149                  */
150                 curdev = malloc(sizeof(pcap_if_t));
151                 if (curdev == NULL) {
152                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
153                             "malloc: %s", pcap_strerror(errno));
154                         return (-1);
155                 }
156
157                 /*
158                  * Fill in the entry.
159                  */
160                 curdev->next = NULL;
161                 curdev->name = malloc(strlen(name) + 1);
162                 strcpy(curdev->name, name);
163                 if (description != NULL) {
164                         /*
165                          * We have a description for this interface.
166                          */
167                         curdev->description = malloc(strlen(description) + 1);
168                         strcpy(curdev->description, description);
169                 } else {
170                         /*
171                          * We don't.
172                          */
173                         curdev->description = NULL;
174                 }
175                 curdev->addresses = NULL;       /* list starts out as empty */
176                 curdev->flags = 0;
177                 if (ISLOOPBACK(name, flags))
178                         curdev->flags |= PCAP_IF_LOOPBACK;
179
180                 /*
181                  * Add it to the list, in the appropriate location.
182                  * First, get the instance number of this interface.
183                  */
184                 this_instance = get_instance(name);
185
186                 /*
187                  * Now look for the last interface with an instance number
188                  * less than or equal to the new interface's instance
189                  * number - except that non-loopback interfaces are
190                  * arbitrarily treated as having interface numbers less
191                  * than those of loopback interfaces, so the loopback
192                  * interfaces are put at the end of the list.
193                  *
194                  * We start with "prevdev" being NULL, meaning we're before
195                  * the first element in the list.
196                  */
197                 prevdev = NULL;
198                 for (;;) {
199                         /*
200                          * Get the interface after this one.
201                          */
202                         if (prevdev == NULL) {
203                                 /*
204                                  * The next element is the first element.
205                                  */
206                                 nextdev = *alldevs;
207                         } else
208                                 nextdev = prevdev->next;
209
210                         /*
211                          * Are we at the end of the list?
212                          */
213                         if (nextdev == NULL) {
214                                 /*
215                                  * Yes - we have to put the new entry
216                                  * after "prevdev".
217                                  */
218                                 break;
219                         }
220
221                         /*
222                          * Is the new interface a non-loopback interface
223                          * and the next interface a loopback interface?
224                          */
225                         if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
226                             (nextdev->flags & PCAP_IF_LOOPBACK)) {
227                                 /*
228                                  * Yes, we should put the new entry
229                                  * before "nextdev", i.e. after "prevdev".
230                                  */
231                                 break;
232                         }
233
234                         /*
235                          * Is the new interface's instance number less
236                          * than the next interface's instance number,
237                          * and is it the case that the new interface is a
238                          * non-loopback interface or the next interface is
239                          * a loopback interface?
240                          *
241                          * (The goal of both loopback tests is to make
242                          * sure that we never put a loopback interface
243                          * before any non-loopback interface and that we
244                          * always put a non-loopback interface before all
245                          * loopback interfaces.)
246                          */
247                         if (this_instance < get_instance(nextdev->name) &&
248                             (!(curdev->flags & PCAP_IF_LOOPBACK) ||
249                                (nextdev->flags & PCAP_IF_LOOPBACK))) {
250                                 /*
251                                  * Yes - we should put the new entry
252                                  * before "nextdev", i.e. after "prevdev".
253                                  */
254                                 break;
255                         }
256
257                         prevdev = nextdev;
258                 }
259
260                 /*
261                  * Insert before "nextdev".
262                  */
263                 curdev->next = nextdev;
264
265                 /*
266                  * Insert after "prevdev" - unless "prevdev" is null,
267                  * in which case this is the first interface.
268                  */
269                 if (prevdev == NULL) {
270                         /*
271                          * This is the first interface.  Pass back a
272                          * pointer to it, and put "curdev" before
273                          * "nextdev".
274                          */
275                         *alldevs = curdev;
276                 } else
277                         prevdev->next = curdev;
278         }
279
280         *curdev_ret = curdev;
281         return (0);
282 }
283
284 int
285 add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags,
286     struct sockaddr *addr, size_t addr_size,
287     struct sockaddr *netmask, size_t netmask_size,
288     struct sockaddr *broadaddr, size_t broadaddr_size,
289     struct sockaddr *dstaddr, size_t dstaddr_size,
290     char *errbuf)
291 {
292         pcap_if_t *curdev;
293         pcap_addr_t *curaddr, *prevaddr, *nextaddr;
294
295         if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
296                 /*
297                  * Error - give up.
298                  */
299                 return (-1);
300         }
301         if (curdev == NULL) {
302                 /*
303                  * Device wasn't added because it can't be opened.
304                  * Not a fatal error.
305                  */
306                 return (0);
307         }
308
309         /*
310          * "curdev" is an entry for this interface; add an entry for this
311          * address to its list of addresses.
312          *
313          * Allocate the new entry and fill it in.
314          */
315         curaddr = malloc(sizeof(pcap_addr_t));
316         if (curaddr == NULL) {
317                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
318                     "malloc: %s", pcap_strerror(errno));
319                 return (-1);
320         }
321
322         curaddr->next = NULL;
323         if (addr != NULL) {
324                 curaddr->addr = dup_sockaddr(addr, addr_size);
325                 if (curaddr->addr == NULL) {
326                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
327                             "malloc: %s", pcap_strerror(errno));
328                         free(curaddr);
329                         return (-1);
330                 }
331         } else
332                 curaddr->addr = NULL;
333
334         if (netmask != NULL) {
335                 curaddr->netmask = dup_sockaddr(netmask, netmask_size);
336                 if (curaddr->netmask == NULL) {
337                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
338                             "malloc: %s", pcap_strerror(errno));
339                         free(curaddr);
340                         return (-1);
341                 }
342         } else
343                 curaddr->netmask = NULL;
344
345         if (broadaddr != NULL) {
346                 curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
347                 if (curaddr->broadaddr == NULL) {
348                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
349                             "malloc: %s", pcap_strerror(errno));
350                         free(curaddr);
351                         return (-1);
352                 }
353         } else
354                 curaddr->broadaddr = NULL;
355
356         if (dstaddr != NULL) {
357                 curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
358                 if (curaddr->dstaddr == NULL) {
359                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
360                             "malloc: %s", pcap_strerror(errno));
361                         free(curaddr);
362                         return (-1);
363                 }
364         } else
365                 curaddr->dstaddr = NULL;
366
367         /*
368          * Find the end of the list of addresses.
369          */
370         for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
371                 nextaddr = prevaddr->next;
372                 if (nextaddr == NULL) {
373                         /*
374                          * This is the end of the list.
375                          */
376                         break;
377                 }
378         }
379
380         if (prevaddr == NULL) {
381                 /*
382                  * The list was empty; this is the first member.
383                  */
384                 curdev->addresses = curaddr;
385         } else {
386                 /*
387                  * "prevaddr" is the last member of the list; append
388                  * this member to it.
389                  */
390                 prevaddr->next = curaddr;
391         }
392
393         return (0);
394 }
395
396 int
397 pcap_add_if(pcap_if_t **devlist, char *name, u_int flags,
398     const char *description, char *errbuf)
399 {
400         pcap_if_t *curdev;
401
402         return (add_or_find_if(&curdev, devlist, name, flags, description,
403             errbuf));
404 }
405
406
407 /*
408  * Free a list of interfaces.
409  */
410 void
411 pcap_freealldevs(pcap_if_t *alldevs)
412 {
413         pcap_if_t *curdev, *nextdev;
414         pcap_addr_t *curaddr, *nextaddr;
415
416         for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
417                 nextdev = curdev->next;
418
419                 /*
420                  * Free all addresses.
421                  */
422                 for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
423                         nextaddr = curaddr->next;
424                         if (curaddr->addr)
425                                 free(curaddr->addr);
426                         if (curaddr->netmask)
427                                 free(curaddr->netmask);
428                         if (curaddr->broadaddr)
429                                 free(curaddr->broadaddr);
430                         if (curaddr->dstaddr)
431                                 free(curaddr->dstaddr);
432                         free(curaddr);
433                 }
434
435                 /*
436                  * Free the name string.
437                  */
438                 free(curdev->name);
439
440                 /*
441                  * Free the description string, if any.
442                  */
443                 if (curdev->description != NULL)
444                         free(curdev->description);
445
446                 /*
447                  * Free the interface.
448                  */
449                 free(curdev);
450         }
451 }
452
453 #ifndef WIN32
454
455 /*
456  * Return the name of a network interface attached to the system, or NULL
457  * if none can be found.  The interface must be configured up; the
458  * lowest unit number is preferred; loopback is ignored.
459  */
460 char *
461 pcap_lookupdev(errbuf)
462         register char *errbuf;
463 {
464         pcap_if_t *alldevs;
465 /* for old BSD systems, including bsdi3 */
466 #ifndef IF_NAMESIZE
467 #define IF_NAMESIZE IFNAMSIZ
468 #endif
469         static char device[IF_NAMESIZE + 1];
470         char *ret;
471
472         if (pcap_findalldevs(&alldevs, errbuf) == -1)
473                 return (NULL);
474
475         if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
476                 /*
477                  * There are no devices on the list, or the first device
478                  * on the list is a loopback device, which means there
479                  * are no non-loopback devices on the list.  This means
480                  * we can't return any device.
481                  *
482                  * XXX - why not return a loopback device?  If we can't
483                  * capture on it, it won't be on the list, and if it's
484                  * on the list, there aren't any non-loopback devices,
485                  * so why not just supply it as the default device?
486                  */
487                 (void)strlcpy(errbuf, "no suitable device found",
488                     PCAP_ERRBUF_SIZE);
489                 ret = NULL;
490         } else {
491                 /*
492                  * Return the name of the first device on the list.
493                  */
494                 (void)strlcpy(device, alldevs->name, sizeof(device));
495                 ret = device;
496         }
497
498         pcap_freealldevs(alldevs);
499         return (ret);
500 }
501
502 int
503 pcap_lookupnet(device, netp, maskp, errbuf)
504         register const char *device;
505         register bpf_u_int32 *netp, *maskp;
506         register char *errbuf;
507 {
508         register int fd;
509         register struct sockaddr_in *sin;
510         struct ifreq ifr;
511
512         /*
513          * The pseudo-device "any" listens on all interfaces and therefore
514          * has the network address and -mask "0.0.0.0" therefore catching
515          * all traffic. Using NULL for the interface is the same as "any".
516          */
517         if (!device || strcmp(device, "any") == 0
518 #ifdef HAVE_DAG_API
519             || strstr(device, "dag") != NULL
520 #endif
521             ) {
522                 *netp = *maskp = 0;
523                 return 0;
524         }
525
526         fd = socket(AF_INET, SOCK_DGRAM, 0);
527         if (fd < 0) {
528                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
529                     pcap_strerror(errno));
530                 return (-1);
531         }
532         memset(&ifr, 0, sizeof(ifr));
533 #ifdef linux
534         /* XXX Work around Linux kernel bug */
535         ifr.ifr_addr.sa_family = AF_INET;
536 #endif
537         (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
538         if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
539                 if (errno == EADDRNOTAVAIL) {
540                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
541                             "%s: no IPv4 address assigned", device);
542                 } else {
543                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
544                             "SIOCGIFADDR: %s: %s",
545                             device, pcap_strerror(errno));
546                 }
547                 (void)close(fd);
548                 return (-1);
549         }
550         sin = (struct sockaddr_in *)&ifr.ifr_addr;
551         *netp = sin->sin_addr.s_addr;
552         if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
553                 (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
554                     "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno));
555                 (void)close(fd);
556                 return (-1);
557         }
558         (void)close(fd);
559         *maskp = sin->sin_addr.s_addr;
560         if (*maskp == 0) {
561                 if (IN_CLASSA(*netp))
562                         *maskp = IN_CLASSA_NET;
563                 else if (IN_CLASSB(*netp))
564                         *maskp = IN_CLASSB_NET;
565                 else if (IN_CLASSC(*netp))
566                         *maskp = IN_CLASSC_NET;
567                 else {
568                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
569                             "inet class for 0x%x unknown", *netp);
570                         return (-1);
571                 }
572         }
573         *netp &= *maskp;
574         return (0);
575 }
576
577 #else /* WIN32 */
578
579 /*
580  * Return the name of a network interface attached to the system, or NULL
581  * if none can be found.  The interface must be configured up; the
582  * lowest unit number is preferred; loopback is ignored.
583  */
584 char *
585 pcap_lookupdev(errbuf)
586         register char *errbuf;
587 {
588         DWORD dwVersion;
589         DWORD dwWindowsMajorVersion;
590         dwVersion = GetVersion();       /* get the OS version */
591         dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
592         
593         if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
594                 /*
595                  * Windows 95, 98, ME.
596                  */
597                 ULONG NameLength = 8192;
598                 static char AdaptersName[8192];
599                 
600                 PacketGetAdapterNames(AdaptersName,&NameLength);
601                 
602                 return (AdaptersName);
603         } else {
604                 /*
605                  * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
606                  */
607                 ULONG NameLength = 8192;
608                 static WCHAR AdaptersName[8192];
609                 char *tAstr;
610                 WCHAR *tUstr;
611                 WCHAR *TAdaptersName = (WCHAR*)malloc(8192 * sizeof(WCHAR));
612                 int NAdapts = 0;
613
614                 if(TAdaptersName == NULL)
615                 {
616                         (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
617                         return NULL;
618                 }
619
620                 PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength);
621
622                 tAstr = (char*)TAdaptersName;
623                 tUstr = (WCHAR*)AdaptersName;
624
625                 /*
626                  * Convert and copy the device names
627                  */
628                 while(sscanf(tAstr, "%S", tUstr) > 0)
629                 {
630                         tAstr += strlen(tAstr) + 1;
631                         tUstr += wcslen(tUstr) + 1;
632                         NAdapts ++;
633                 }
634
635                 tAstr++;
636                 *tUstr = 0;
637                 tUstr++;
638
639                 /*
640                  * Copy the descriptions
641                  */
642                 while(NAdapts--)
643                 {
644                         strcpy((char*)tUstr, tAstr);
645                         (char*)tUstr += strlen(tAstr) + 1;;
646                         tAstr += strlen(tAstr) + 1;
647                 }
648
649                 return (char *)(AdaptersName);
650         }       
651 }
652
653
654 int
655 pcap_lookupnet(device, netp, maskp, errbuf)
656         const register char *device;
657         register bpf_u_int32 *netp, *maskp;
658         register char *errbuf;
659 {
660         /* 
661          * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
662          * in order to skip non IPv4 (i.e. IPv6 addresses)
663          */
664         npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
665         LONG if_addr_size = 1;
666         struct sockaddr_in *t_addr;
667         unsigned int i;
668
669         if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
670                 *netp = *maskp = 0;
671                 return (0);
672         }
673
674         for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
675         {
676                 if(if_addrs[i].IPAddress.ss_family == AF_INET)
677                 {
678                         t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
679                         *netp = t_addr->sin_addr.S_un.S_addr;
680                         t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
681                         *maskp = t_addr->sin_addr.S_un.S_addr;
682
683                         *netp &= *maskp;
684                         return (0);
685                 }
686                                 
687         }
688
689         *netp = *maskp = 0;
690         return (0);
691 }
692
693 #endif /* WIN32 */