home *** CD-ROM | disk | FTP | other *** search
/ Steganos Hacker Tools / SHT151.iso / programme / scanner / nmapNTsp1 / Win_2000.exe / nmapNT-src / libpcap-possiblymodified / pcap-linux.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-05  |  8.5 KB  |  355 lines

  1. /*
  2.  * Copyright (c) 1996, 1997
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. static const char rcsid[] =
  23.     "@(#) $Header: /archive/CVS/nmap/libpcap-possiblymodified/pcap-linux.c,v 1.2 1998/12/05 20:17:28 fyodor Exp $ (LBL)";
  24. #endif
  25.  
  26. #include <sys/param.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/socket.h>
  29. #include <sys/time.h>
  30.  
  31. #include <net/if.h>
  32. #ifdef HAVE_NET_IF_ARP_H
  33. #include <net/if_arp.h>
  34. #else
  35. #include <linux/if_arp.h>
  36. #endif
  37. #include <linux/if_ether.h>
  38.  
  39. #include <netinet/in.h>
  40.  
  41. #include <errno.h>
  42. #include <malloc.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <unistd.h>
  47.  
  48. static struct ifreq saved_ifr;
  49.  
  50. #include "pcap-int.h"
  51.  
  52. #include "gnuc.h"
  53. #ifdef HAVE_OS_PROTO_H
  54. #include "os-proto.h"
  55. #endif
  56.  
  57. #define TIMEVAL_SUBTRACT(a,b)  ((a.tv_sec - b.tv_sec) * 1000000 + a.tv_usec - b.tv_usec)
  58.  
  59. static int timeout;
  60.  
  61. void linux_restore_ifr(void);
  62.  
  63.  
  64. int
  65. pcap_stats(pcap_t *p, struct pcap_stat *ps)
  66. {
  67.  
  68.     *ps = p->md.stat;
  69.     return (0);
  70. }
  71.  
  72. int
  73. pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  74. {
  75.     register int cc;
  76.     register int bufsize;
  77.     register int caplen;
  78.     register u_char *bp;
  79.     struct sockaddr from;
  80.     int fromlen;
  81.     fd_set fd_r;
  82.     struct timeval select_time, start, now, tmp;
  83.     int res;
  84.     fromlen = sizeof(from);
  85.  
  86.     select_time.tv_sec = timeout / 1000;
  87.     select_time.tv_usec = (timeout % 1000) * 1000;
  88.     gettimeofday(&start, NULL);
  89.  
  90.  
  91.     do {
  92.  
  93.       FD_ZERO(&fd_r);
  94.       FD_SET(p->fd, &fd_r );
  95.  
  96.       bp = p->buffer + p->offset;
  97.       bufsize = p->bufsize - p->offset;
  98.       if (p->md.pad > 0) {
  99.         memset(bp, 0, p->md.pad);
  100.         bp += p->md.pad;
  101.         bufsize -= p->md.pad;
  102.       }
  103.  
  104.       tmp = select_time; /* Because linux mucks with the timeout in select() */
  105.       res = select(p->fd+1, &fd_r, NULL, NULL, &tmp);
  106.       if (res < 0) {
  107.         sprintf(p->errbuf, "select: %s", pcap_strerror(errno));
  108.         return (-1);
  109.       } else if (res > 0) {
  110.         fromlen = sizeof(from);
  111.         while ((cc = recvfrom(p->fd, bp, bufsize, 0, &from, &fromlen)) < 0) {
  112.           /* Don't choke when we get ptraced */
  113.           if (errno != EINTR && errno != EAGAIN) {
  114.         sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
  115.         return (-1);
  116.           }
  117.         }
  118.         
  119.         if (!strcmp(p->md.device, from.sa_data)) {
  120.           /* If we need have leading zero bytes, adjust count */
  121.           cc += p->md.pad;
  122.           bp = p->buffer + p->offset;
  123.           
  124.           /* If we need to step over leading junk, adjust count and pointer */
  125.           cc -= p->md.skip;
  126.           bp += p->md.skip;
  127.           
  128.           /* Captured length can't exceed our read buffer size */
  129.         caplen = cc;
  130.         if (caplen > bufsize)
  131.           caplen = bufsize;
  132.         
  133.         /* Captured length can't exceed the snapshot length */
  134.         if (caplen > p->snapshot)
  135.           caplen = p->snapshot;
  136.         
  137.         if (p->fcode.bf_insns == NULL ||
  138.             bpf_filter(p->fcode.bf_insns, bp, cc, caplen)) {
  139.           struct pcap_pkthdr h;
  140.           
  141.           ++p->md.stat.ps_recv;
  142.           /* Get timestamp */
  143.           if (ioctl(p->fd, SIOCGSTAMP, &h.ts) < 0) {
  144.             sprintf(p->errbuf, "SIOCGSTAMP: %s",
  145.                             pcap_strerror(errno));
  146.             return (-1);
  147.           }
  148.           h.len = cc;
  149.           h.caplen = caplen;
  150.           (*callback)(user, &h, bp);
  151.           return (1);
  152.         }
  153.           }
  154.         }
  155.       gettimeofday(&now, NULL);
  156.     } while((timeout == 0 && res) || (TIMEVAL_SUBTRACT(now,start) < timeout * 1000));
  157.  
  158.     return 0;
  159. }
  160.  
  161. pcap_t *
  162. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  163. {
  164.     register int fd, broadcast;
  165.     register pcap_t *p;
  166.     struct ifreq ifr;
  167.     struct sockaddr sa;
  168.  
  169.     timeout = to_ms;
  170.  
  171.     p = (pcap_t *)malloc(sizeof(*p));
  172.     if (p == NULL) {
  173.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  174.         return (NULL);
  175.     }
  176.     memset(p, 0, sizeof(*p));
  177.     fd = -1;
  178.  
  179.     fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
  180.     if (fd < 0) {
  181.         sprintf(ebuf, "socket: %s", pcap_strerror(errno));
  182.         goto bad;
  183.     }
  184.     p->fd = fd;
  185.  
  186.     /* Bind to the interface name */
  187.     memset(&sa, 0, sizeof(sa));
  188.     sa.sa_family = AF_INET;
  189.     (void)strncpy(sa.sa_data, device, sizeof(sa.sa_data));
  190.     if (bind(p->fd, &sa, sizeof(sa))) {
  191.         sprintf(ebuf, "bind: %s: %s", device, pcap_strerror(errno));
  192.         goto bad;
  193.     }
  194.  
  195.     memset(&ifr, 0, sizeof(ifr));
  196.     strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  197.     if (ioctl(p->fd, SIOCGIFHWADDR, &ifr) < 0 ) {
  198.         sprintf(ebuf, "SIOCGIFHWADDR: %s", pcap_strerror(errno));
  199.         goto bad;
  200.     }
  201.     broadcast = 0;
  202.     switch (ifr.ifr_hwaddr.sa_family) {
  203.  
  204.     case ARPHRD_ETHER:
  205.     case ARPHRD_METRICOM:
  206.         p->linktype = DLT_EN10MB;
  207.         p->offset = 2;
  208.         ++broadcast;
  209.         break;
  210.  
  211.     case ARPHRD_EETHER:
  212.         p->linktype = DLT_EN3MB;
  213.         ++broadcast;
  214.         break;
  215.  
  216.     case ARPHRD_AX25:
  217.         p->linktype = DLT_AX25;
  218.         ++broadcast;
  219.         break;
  220.  
  221.     case ARPHRD_PRONET:
  222.         p->linktype = DLT_PRONET;
  223.         break;
  224.  
  225.     case ARPHRD_CHAOS:
  226.         p->linktype = DLT_CHAOS;
  227.         break;
  228.  
  229.     case ARPHRD_IEEE802:
  230.         p->linktype = DLT_IEEE802;
  231.         ++broadcast;
  232.         break;
  233.  
  234.     case ARPHRD_ARCNET:
  235.         p->linktype = DLT_ARCNET;
  236.         ++broadcast;
  237.         break;
  238.  
  239.     case ARPHRD_SLIP:
  240.     case ARPHRD_CSLIP:
  241.     case ARPHRD_SLIP6:
  242.     case ARPHRD_CSLIP6:
  243.     case ARPHRD_PPP:
  244.         p->linktype = DLT_RAW;
  245.         break;
  246.  
  247.     case ARPHRD_LOOPBACK:
  248.         p->linktype = DLT_NULL;
  249.         p->md.pad = 2;
  250.         p->md.skip = 12;
  251.         break;
  252.  
  253. #ifdef ARPHRD_FDDI
  254.     /* Not all versions of the kernel has this define */
  255.     case ARPHRD_FDDI:
  256.         p->linktype = DLT_FDDI;
  257.         ++broadcast;
  258.         break;
  259. #endif
  260.  
  261. #ifdef notdef
  262.     case ARPHRD_LOCALTLK:
  263.     case ARPHRD_NETROM:
  264.     case ARPHRD_APPLETLK:
  265.     case ARPHRD_DLCI:
  266.     case ARPHRD_RSRVD:
  267.     case ARPHRD_ADAPT:
  268.     case ARPHRD_TUNNEL:
  269.     case ARPHRD_TUNNEL6:
  270.     case ARPHRD_FRAD:
  271.     case ARPHRD_SKIP:
  272.         /* XXX currently do not know what to do with these... */
  273.         abort();
  274. #endif
  275.  
  276.     default:
  277.         sprintf(ebuf, "unknown physical layer type 0x%x",
  278.             ifr.ifr_hwaddr.sa_family);
  279.         goto bad;
  280.     }
  281.  
  282.     /* Base the buffer size on the interface MTU */
  283.     memset(&ifr, 0, sizeof(ifr));
  284.     strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  285.     if (ioctl(p->fd, SIOCGIFMTU, &ifr) < 0 ) {
  286.         sprintf(ebuf, "SIOCGIFMTU: %s", pcap_strerror(errno));
  287.         goto bad;
  288.     }
  289.  
  290.     /* Leave room for link header (which is never large under linux...) */
  291.     p->bufsize = ifr.ifr_mtu + 64;
  292.  
  293.     p->buffer = (u_char *)malloc(p->bufsize + p->offset);
  294.     if (p->buffer == NULL) {
  295.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  296.         goto bad;
  297.     }
  298.  
  299.     /* XXX */
  300.     if (promisc && broadcast) {
  301.         memset(&ifr, 0, sizeof(ifr));
  302.         strcpy(ifr.ifr_name, device);
  303.         if (ioctl(p->fd, SIOCGIFFLAGS, &ifr) < 0 ) {
  304.             sprintf(ebuf, "SIOCGIFFLAGS: %s", pcap_strerror(errno));
  305.             goto bad;
  306.         }
  307.         saved_ifr = ifr;
  308.         ifr.ifr_flags |= IFF_PROMISC;
  309.         if (ioctl(p->fd, SIOCSIFFLAGS, &ifr) < 0 ) {
  310.             sprintf(ebuf, "SIOCSIFFLAGS: %s", pcap_strerror(errno));
  311.             goto bad;
  312.         }
  313.         ifr.ifr_flags &= ~IFF_PROMISC;
  314.         atexit(linux_restore_ifr);
  315.     }
  316.  
  317.     p->md.device = strdup(device);
  318.     if (p->md.device == NULL) {
  319.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  320.         goto bad;
  321.     }
  322.     p->snapshot = snaplen;
  323.  
  324.     return (p);
  325. bad:
  326.     if (fd >= 0)
  327.         (void)close(fd);
  328.     if (p->buffer != NULL)
  329.         free(p->buffer);
  330.     if (p->md.device != NULL)
  331.         free(p->md.device);
  332.     free(p);
  333.     return (NULL);
  334. }
  335.  
  336. int
  337. pcap_setfilter(pcap_t *p, struct bpf_program *fp)
  338. {
  339.  
  340.     p->fcode = *fp;
  341.     return (0);
  342. }
  343.  
  344. void
  345. linux_restore_ifr(void)
  346. {
  347.     register int fd;
  348.  
  349.     fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
  350.     if (fd < 0)
  351.         fprintf(stderr, "linux socket: %s", pcap_strerror(errno));
  352.     else if (ioctl(fd, SIOCSIFFLAGS, &saved_ifr) < 0)
  353.         fprintf(stderr, "linux SIOCSIFFLAGS: %s", pcap_strerror(errno));
  354. }
  355.