Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

pcap-snoop.c File Reference

#include <sys/param.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <net/raw.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pcap-int.h"

Include dependency graph for pcap-snoop.c:

Include dependency graph

Go to the source code of this file.

Functions

int pcap_read (pcap_t *p, int cnt, pcap_handler callback, u_char *user)
int pcap_stats (pcap_t *p, struct pcap_stat *ps)
pcap_tpcap_open_live (char *device, int snaplen, int promisc, int to_ms, char *ebuf)
int pcap_setfilter (pcap_t *p, struct bpf_program *fp)

Variables

const char rcsid []


Function Documentation

pcap_t* pcap_open_live char *  device,
int  snaplen,
int  promisc,
int  to_ms,
char *  ebuf
 

Definition at line 147 of file pcap-snoop.c.

References bind(), BIOCGBLEN, BIOCGDLT, BIOCIMMEDIATE, BIOCPROMISC, BIOCSBLEN, BIOCSETIF, BIOCSRTIMEOUT, BIOCVERSION, BPF_MAJOR_VERSION, BPF_MINOR_VERSION, bpf_open(), pcap::buffer, pcap::bufsize, bpf_version::bv_major, bpf_version::bv_minor, close(), DLT_CHDLC, DLT_EN10MB, DLT_FDDI, DLT_FRELAY, DLT_IEEE802, DLT_NULL, DLT_PPP, DLT_PPP_BSDOS, DLT_RAW, DLT_SLIP, DLT_SLIP_BSDOS, errno, pcap::fd, ioctl(), pcap::linktype, malloc(), pcap::offset, p, PCAP_ERRBUF_SIZE, pcap_strerror(), pcap_t, setsockopt(), snaplen, pcap::snapshot, snprintf(), and socket().

Referenced by add_or_find_if(), and PktInterfaceSrc::PktInterfaceSrc().

00148 {
00149         int fd;
00150         struct sockaddr_raw sr;
00151         struct snoopfilter sf;
00152         u_int v;
00153         int ll_hdrlen;
00154         int snooplen;
00155         pcap_t *p;
00156         struct ifreq ifr;
00157 
00158         p = (pcap_t *)malloc(sizeof(*p));
00159         if (p == NULL) {
00160                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
00161                     pcap_strerror(errno));
00162                 return (NULL);
00163         }
00164         memset(p, 0, sizeof(*p));
00165         fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
00166         if (fd < 0) {
00167                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
00168                     pcap_strerror(errno));
00169                 goto bad;
00170         }
00171         p->fd = fd;
00172         memset(&sr, 0, sizeof(sr));
00173         sr.sr_family = AF_RAW;
00174         (void)strncpy(sr.sr_ifname, device, sizeof(sr.sr_ifname));
00175         if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
00176                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
00177                     pcap_strerror(errno));
00178                 goto bad;
00179         }
00180         memset(&sf, 0, sizeof(sf));
00181         if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
00182                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
00183                     pcap_strerror(errno));
00184                 goto bad;
00185         }
00186         v = 64 * 1024;
00187         (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v));
00188         /*
00189          * XXX hack - map device name to link layer type
00190          */
00191         if (strncmp("et", device, 2) == 0 ||    /* Challenge 10 Mbit */
00192             strncmp("ec", device, 2) == 0 ||    /* Indigo/Indy 10 Mbit,
00193                                                    O2 10/100 */
00194             strncmp("ef", device, 2) == 0 ||    /* O200/2000 10/100 Mbit */
00195             strncmp("eg", device, 2) == 0 ||    /* Octane/O2xxx/O3xxx Gigabit */
00196             strncmp("gfe", device, 3) == 0 ||   /* GIO 100 Mbit */
00197             strncmp("fxp", device, 3) == 0 ||   /* Challenge VME Enet */
00198             strncmp("ep", device, 2) == 0 ||    /* Challenge 8x10 Mbit EPLEX */
00199             strncmp("vfe", device, 3) == 0 ||   /* Challenge VME 100Mbit */
00200             strncmp("fa", device, 2) == 0 ||
00201             strncmp("qaa", device, 3) == 0 ||
00202             strncmp("cip", device, 3) == 0 ||
00203             strncmp("el", device, 2) == 0) {
00204                 p->linktype = DLT_EN10MB;
00205                 p->offset = RAW_HDRPAD(sizeof(struct ether_header));
00206                 ll_hdrlen = sizeof(struct ether_header);
00207         } else if (strncmp("ipg", device, 3) == 0 ||
00208                    strncmp("rns", device, 3) == 0 ||    /* O2/200/2000 FDDI */
00209                    strncmp("xpi", device, 3) == 0) {
00210                 p->linktype = DLT_FDDI;
00211                 p->offset = 3;                          /* XXX yeah? */
00212                 ll_hdrlen = 13;
00213         } else if (strncmp("ppp", device, 3) == 0) {
00214                 p->linktype = DLT_RAW;
00215                 ll_hdrlen = 0;  /* DLT_RAW meaning "no PPP header, just the IP packet"? */
00216         } else if (strncmp("lo", device, 2) == 0) {
00217                 p->linktype = DLT_NULL;
00218                 ll_hdrlen = 4;  /* is this just like BSD's loopback device? */
00219         } else {
00220                 snprintf(ebuf, PCAP_ERRBUF_SIZE,
00221                     "snoop: unknown physical layer type");
00222                 goto bad;
00223         }
00224 #ifdef SIOCGIFMTU
00225         /*
00226          * XXX - IRIX appears to give you an error if you try to set the
00227          * capture length to be greater than the MTU, so let's try to get
00228          * the MTU first and, if that succeeds, trim the snap length
00229          * to be no greater than the MTU.
00230          */
00231         (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
00232         if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) {
00233                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
00234                     pcap_strerror(errno));
00235                 goto bad;
00236         }
00237         /*
00238          * OK, we got it.
00239          *
00240          * XXX - some versions of IRIX 6.5 define "ifr_mtu" and have an
00241          * "ifru_metric" member of the "ifr_ifru" union in an "ifreq"
00242          * structure, others don't.
00243          *
00244          * I've no idea what's going on, so, if "ifr_mtu" isn't defined,
00245          * we define it as "ifr_metric", as using that field appears to
00246          * work on the versions that lack "ifr_mtu" (and, on those that
00247          * don't lack it, "ifru_metric" and "ifru_mtu" are both "int"
00248          * members of the "ifr_ifru" union, which suggests that they
00249          * may be interchangeable in this case).
00250          */
00251 #ifndef ifr_mtu
00252 #define ifr_mtu ifr_metric
00253 #endif
00254         if (snaplen > ifr.ifr_mtu + ll_hdrlen)
00255                 snaplen = ifr.ifr_mtu + ll_hdrlen;
00256 #endif
00257 
00258         /*
00259          * The argument to SIOCSNOOPLEN is the number of link-layer
00260          * payload bytes to capture - it doesn't count link-layer
00261          * header bytes.
00262          */
00263         snooplen = snaplen - ll_hdrlen;
00264         if (snooplen < 0)
00265                 snooplen = 0;
00266         if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) {
00267                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
00268                     pcap_strerror(errno));
00269                 goto bad;
00270         }
00271         p->snapshot = snaplen;
00272         v = 1;
00273         if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
00274                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
00275                     pcap_strerror(errno));
00276                 goto bad;
00277         }
00278 
00279         p->bufsize = 4096;                              /* XXX */
00280         p->buffer = (u_char *)malloc(p->bufsize);
00281         if (p->buffer == NULL) {
00282                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
00283                     pcap_strerror(errno));
00284                 goto bad;
00285         }
00286 
00287         return (p);
00288  bad:
00289         (void)close(fd);
00290         free(p);
00291         return (NULL);
00292 }

int pcap_read pcap_t p,
int  cnt,
pcap_handler  callback,
u_char *  user
 

Definition at line 62 of file pcap-snoop.c.

References bpf_program::bf_insns, bhp, pcap::bp, bpf_filter(), BPF_WORDALIGN, pcap::buffer, pcap::bufsize, pcap_pkthdr::caplen, pcap::cc, ep, pcap::errbuf, errno, pcap::fcode, pcap::fd, pcap_pkthdr::len, lseek(), pcap::md, pcap::offset, p, PCAP_ERRBUF_SIZE, pcap_handler, pcap_strerror(), pcap_t, pcap_stat::ps_recv, read(), pcap::snapshot, snprintf(), pcap_md::stat, and pcap_pkthdr::ts.

Referenced by pcap_dispatch(), and pcap_loop().

00063 {
00064         int cc;
00065         register struct snoopheader *sh;
00066         register int datalen;
00067         register int caplen;
00068         register u_char *cp;
00069 
00070 again:
00071         cc = read(p->fd, (char *)p->buffer, p->bufsize);
00072         if (cc < 0) {
00073                 /* Don't choke when we get ptraced */
00074                 switch (errno) {
00075 
00076                 case EINTR:
00077                                 goto again;
00078 
00079                 case EWOULDBLOCK:
00080                         return (0);                     /* XXX */
00081                 }
00082                 snprintf(p->errbuf, sizeof(p->errbuf),
00083                     "read: %s", pcap_strerror(errno));
00084                 return (-1);
00085         }
00086         sh = (struct snoopheader *)p->buffer;
00087         datalen = sh->snoop_packetlen;
00088         caplen = (datalen < p->snapshot) ? datalen : p->snapshot;
00089         cp = (u_char *)(sh + 1) + p->offset;            /* XXX */
00090 
00091         if (p->fcode.bf_insns == NULL ||
00092             bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
00093                 struct pcap_pkthdr h;
00094                 ++p->md.stat.ps_recv;
00095                 h.ts.tv_sec = sh->snoop_timestamp.tv_sec;
00096                 h.ts.tv_usec = sh->snoop_timestamp.tv_usec;
00097                 h.len = datalen;
00098                 h.caplen = caplen;
00099                 (*callback)(user, &h, cp);
00100                 return (1);
00101         }
00102         return (0);
00103 }

int pcap_setfilter pcap_t p,
struct bpf_program fp
 

Definition at line 295 of file pcap-snoop.c.

References BIOCSETF, pcap::errbuf, errno, pcap::fd, install_bpf_program(), ioctl(), no_optimize, p, PCAP_ERRBUF_SIZE, pcap_strerror(), pcap_t, pcap_sf::rfile, pcap::sf, and snprintf().

Referenced by PktSrc::SetFilter().

00296 {
00297 
00298         if (install_bpf_program(p, fp) < 0)
00299                 return (-1);
00300         return (0);
00301 }

int pcap_stats pcap_t p,
struct pcap_stat ps
 

Definition at line 106 of file pcap-snoop.c.

References BIOCGSTATS, bpf_stat::bs_drop, bpf_stat::bs_recv, pcap::errbuf, errno, pcap::fd, ioctl(), pcap::md, p, PCAP_ERRBUF_SIZE, pcap_strerror(), pcap_t, pcap_stat::ps_drop, pcap_stat::ps_recv, snprintf(), and pcap_md::stat.

Referenced by PktSrc::Statistics().

00107 {
00108         register struct rawstats *rs;
00109         struct rawstats rawstats;
00110 
00111         rs = &rawstats;
00112         memset(rs, 0, sizeof(*rs));
00113         if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) {
00114                 snprintf(p->errbuf, sizeof(p->errbuf),
00115                     "SIOCRAWSTATS: %s", pcap_strerror(errno));
00116                 return (-1);
00117         }
00118 
00119         /*
00120          * "ifdrops" are those dropped by the network interface
00121          * due to resource shortages or hardware errors.
00122          *
00123          * "sbdrops" are those dropped due to socket buffer limits.
00124          *
00125          * As filter is done in userland, "sbdrops" counts packets
00126          * regardless of whether they would've passed the filter.
00127          *
00128          * XXX - does this count *all* Snoop or Drain sockets,
00129          * rather than just this socket?  If not, why does it have
00130          * both Snoop and Drain statistics?
00131          */
00132         p->md.stat.ps_drop =
00133             rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops +
00134             rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops;
00135 
00136         /*
00137          * "ps_recv" counts only packets that passed the filter.
00138          * As filtering is done in userland, this does not include
00139          * packets dropped because we ran out of buffer space.
00140          */
00141         *ps = p->md.stat;
00142         return (0);
00143 }


Variable Documentation

const char rcsid[] [static]
 

Initial value:

    "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.33.2.3 2002/07/30 07:48:48 guy Exp $ (LBL)"

Definition at line 22 of file pcap-snoop.c.


Generated on Wed Sep 14 03:03:02 2005 for bro_docs by doxygen 1.3.5