home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / E-zine / Magazines / crh / freebsd / rootkit / sniffit.0.3.5 / libpcap-0.3 / pcap-linux.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-05-27  |  5.6 KB  |  240 lines

  1. /*
  2.  * Copyright (c) 1996
  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: pcap-linux.c,v 1.4 96/12/10 23:15:00 leres 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.  
  33. #include <netinet/in.h>
  34.  
  35. #include <errno.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <unistd.h>
  40.  
  41. static struct ifreq saved_ifr;
  42.  
  43. #include "pcap-int.h"
  44.  
  45. #include "gnuc.h"
  46. #ifdef HAVE_OS_PROTO_H
  47. #include "os-proto.h"
  48. #endif
  49.  
  50. void linux_restore_ifr(void);
  51.  
  52. int
  53. pcap_stats(pcap_t *p, struct pcap_stat *ps)
  54. {
  55.  
  56.     *ps = p->md.stat;
  57.     return (0);
  58. }
  59.  
  60. int
  61. pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  62. {
  63.     register int cc;
  64.     register int bufsize;
  65.     register int caplen;
  66.     register u_char *bp;
  67.     struct sockaddr from;
  68.     int fromlen;
  69.  
  70.     bp = (char *)p->buffer;
  71.     bufsize = p->bufsize;
  72.     if (p->md.pad > 0) {
  73.         bp += p->md.pad;
  74.         bufsize -= p->md.pad;
  75.         memset(p->buffer, 0, p->md.pad);
  76.     }
  77.  
  78. again:
  79.     do {
  80.         fromlen = sizeof(from);
  81.         cc = recvfrom(p->fd, bp, bufsize, 0, &from, &fromlen);
  82.         if (cc < 0) {
  83.             /* Don't choke when we get ptraced */
  84.             switch (errno) {
  85.  
  86.             case EINTR:
  87.                     goto again;
  88.  
  89.             case EWOULDBLOCK:
  90.                 return (0);        /* XXX */
  91.             }
  92.             sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
  93.             return (-1);
  94.         }
  95.     } while (strcmp(p->md.device, from.sa_data));
  96.  
  97.     /* If we need have leading zero bytes, adjust count */
  98.     cc += p->md.pad;
  99.     bp = p->buffer;
  100.  
  101.     /* If we need to step over leading junk, adjust count and pointer */
  102.     cc -= p->md.skip;
  103.     bp += p->md.skip;
  104.  
  105.     /* Captured length can't exceed our read buffer size */
  106.     caplen = cc;
  107.     if (caplen > bufsize)
  108.         caplen = bufsize;
  109.  
  110.     /* Captured length can't exceed the snapshot length */
  111.     if (caplen > p->snapshot)
  112.         caplen = p->snapshot;
  113.  
  114.     if (p->fcode.bf_insns == NULL ||
  115.         bpf_filter(p->fcode.bf_insns, bp, cc, caplen)) {
  116.         struct pcap_pkthdr h;
  117.  
  118.         ++p->md.stat.ps_recv;
  119.         /* Get timestamp */
  120.         if (ioctl(p->fd, SIOCGSTAMP, &h.ts) < 0) {
  121.             sprintf(p->errbuf, "SIOCGSTAMP: %s",
  122.                 pcap_strerror(errno));
  123.             return (-1);
  124.         }
  125.         h.len = cc;
  126.         h.caplen = caplen;
  127.         (*callback)(user, &h, bp);
  128.         return (1);
  129.     }
  130.     return (0);
  131. }
  132.  
  133. pcap_t *
  134. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  135. {
  136.     register int fd, broadcast;
  137.     register pcap_t *p;
  138.     struct ifreq ifr;
  139.  
  140.     p = (pcap_t *)malloc(sizeof(*p));
  141.     if (p == NULL) {
  142.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  143.         return (NULL);
  144.     }
  145.     memset((char *)p, 0, sizeof(*p));
  146.     fd = -1;
  147.  
  148.     /* XXX hack - map device name to link layer type */
  149.     broadcast = 0;
  150.     if (strncmp("eth", device, 3) == 0) {
  151.         p->linktype = DLT_EN10MB;
  152.         ++broadcast;
  153.     } else if (strncmp("sl", device, 2) == 0) {
  154.         p->linktype = DLT_SLIP;
  155.         p->md.pad = 16;
  156.     } else if (strncmp("ppp", device, 3) == 0) {
  157.         p->linktype = DLT_PPP;
  158.         p->md.pad = 4;
  159.     } else if (strncmp("lo", device, 2) == 0) {
  160.         p->linktype = DLT_NULL;
  161.         p->md.pad = 2;
  162.         p->md.skip = 12;
  163.     } else {
  164.         sprintf(ebuf, "linux: unknown physical layer type");
  165.         goto bad;
  166.     }
  167.  
  168.     /* Linux is full of magic numbers */
  169.     fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
  170.     if (fd < 0) {
  171.         sprintf(ebuf, "linux socket: %s", pcap_strerror(errno));
  172.         goto bad;
  173.     }
  174.     p->fd = fd;
  175.  
  176.  
  177.     p->bufsize = 4096;                /* XXX */
  178.     p->buffer = (u_char *)malloc(p->bufsize);
  179.     if (p->buffer == NULL) {
  180.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  181.         goto bad;
  182.     }
  183.  
  184.     /* XXX */
  185.     if (promisc && broadcast) {
  186.         memset(&ifr, 0, sizeof(ifr));
  187.         strcpy(ifr.ifr_name, device);
  188.         if (ioctl(p->fd, SIOCGIFFLAGS, &ifr) < 0 ) {
  189.             sprintf(ebuf, "SIOCGIFFLAGS: %s", pcap_strerror(errno));
  190.             goto bad;
  191.         }
  192.         saved_ifr = ifr;
  193.         ifr.ifr_flags |= IFF_PROMISC;
  194.         if (ioctl(p->fd, SIOCSIFFLAGS, &ifr) < 0 ) {
  195.             sprintf(ebuf, "SIOCSIFFLAGS: %s", pcap_strerror(errno));
  196.             goto bad;
  197.         }
  198.         ifr.ifr_flags &= ~IFF_PROMISC;
  199.         atexit(linux_restore_ifr);
  200.     }
  201.  
  202.     p->md.device = strdup(device);
  203.     if (p->md.device == NULL) {
  204.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  205.         goto bad;
  206.     }
  207.     p->snapshot = snaplen;
  208.  
  209.     return (p);
  210. bad:
  211.     if (fd >= 0)
  212.         (void)close(fd);
  213.     if (p->buffer != NULL)
  214.         free(p->buffer);
  215.     if (p->md.device != NULL)
  216.         free(p->md.device);
  217.     free(p);
  218.     return (NULL);
  219. }
  220.  
  221. int
  222. pcap_setfilter(pcap_t *p, struct bpf_program *fp)
  223. {
  224.  
  225.     p->fcode = *fp;
  226.     return (0);
  227. }
  228.  
  229. void
  230. linux_restore_ifr(void)
  231. {
  232.     register int fd;
  233.  
  234.     fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
  235.     if (fd < 0)
  236.         fprintf(stderr, "linux socket: %s", pcap_strerror(errno));
  237.     else if (ioctl(fd, SIOCSIFFLAGS, &saved_ifr) < 0)
  238.         fprintf(stderr, "linux SIOCSIFFLAGS: %s", pcap_strerror(errno));
  239. }
  240.