pcap-nit.c revision 146768
1169689Skan/* 2169689Skan * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 3169689Skan * The Regents of the University of California. All rights reserved. 4169689Skan * 5169689Skan * Redistribution and use in source and binary forms, with or without 6169689Skan * modification, are permitted provided that: (1) source code distributions 7169689Skan * retain the above copyright notice and this paragraph in its entirety, (2) 8169689Skan * distributions including binary code include the above copyright notice and 9169689Skan * this paragraph in its entirety in the documentation or other materials 10169689Skan * provided with the distribution, and (3) all advertising materials mentioning 11169689Skan * features or use of this software display the following acknowledgement: 12169689Skan * ``This product includes software developed by the University of California, 13169689Skan * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14169689Skan * the University nor the names of its contributors may be used to endorse 15169689Skan * or promote products derived from this software without specific prior 16169689Skan * written permission. 17169689Skan * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18169689Skan * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19169689Skan * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20169689Skan */ 21169689Skan#ifndef lint 22169689Skanstatic const char rcsid[] _U_ = 23169689Skan "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.57 2004/10/19 07:06:13 guy Exp $ (LBL)"; 24169689Skan#endif 25169689Skan 26169689Skan#ifdef HAVE_CONFIG_H 27169689Skan#include "config.h" 28169689Skan#endif 29169689Skan 30169689Skan#include <sys/types.h> 31169689Skan#include <sys/time.h> 32169689Skan#include <sys/timeb.h> 33169689Skan#include <sys/file.h> 34169689Skan#include <sys/ioctl.h> 35169689Skan#include <sys/socket.h> 36169689Skan 37169689Skan#include <net/if.h> 38169689Skan#include <net/nit.h> 39169689Skan 40169689Skan#include <netinet/in.h> 41169689Skan#include <netinet/in_systm.h> 42169689Skan#include <netinet/ip.h> 43169689Skan#include <netinet/if_ether.h> 44169689Skan#include <netinet/ip_var.h> 45169689Skan#include <netinet/udp.h> 46169689Skan#include <netinet/udp_var.h> 47169689Skan#include <netinet/tcp.h> 48169689Skan#include <netinet/tcpip.h> 49169689Skan 50169689Skan#include <ctype.h> 51169689Skan#include <errno.h> 52169689Skan#include <stdio.h> 53169689Skan 54169689Skan#include "pcap-int.h" 55169689Skan 56169689Skan#ifdef HAVE_OS_PROTO_H 57169689Skan#include "os-proto.h" 58169689Skan#endif 59169689Skan 60169689Skan/* 61169689Skan * The chunk size for NIT. This is the amount of buffering 62169689Skan * done for read calls. 63169689Skan */ 64169689Skan#define CHUNKSIZE (2*1024) 65169689Skan 66169689Skan/* 67169689Skan * The total buffer space used by NIT. 68169689Skan */ 69169689Skan#define BUFSPACE (4*CHUNKSIZE) 70169689Skan 71169689Skan/* Forwards */ 72169689Skanstatic int nit_setflags(int, int, int, char *); 73169689Skan 74169689Skanstatic int 75169689Skanpcap_stats_nit(pcap_t *p, struct pcap_stat *ps) 76169689Skan{ 77169689Skan 78169689Skan /* 79169689Skan * "ps_recv" counts packets handed to the filter, not packets 80169689Skan * that passed the filter. As filtering is done in userland, 81169689Skan * this does not include packets dropped because we ran out 82169689Skan * of buffer space. 83169689Skan * 84169689Skan * "ps_drop" presumably counts packets dropped by the socket 85169689Skan * because of flow control requirements or resource exhaustion; 86169689Skan * it doesn't count packets dropped by the interface driver. 87169689Skan * As filtering is done in userland, it counts packets regardless 88169689Skan * of whether they would've passed the filter. 89169689Skan * 90169689Skan * These statistics don't include packets not yet read from the 91169689Skan * kernel by libpcap or packets not yet read from libpcap by the 92169689Skan * application. 93169689Skan */ 94169689Skan *ps = p->md.stat; 95169689Skan return (0); 96169689Skan} 97169689Skan 98169689Skanstatic int 99169689Skanpcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 100169689Skan{ 101169689Skan register int cc, n; 102169689Skan register struct bpf_insn *fcode = p->fcode.bf_insns; 103169689Skan register u_char *bp, *cp, *ep; 104169689Skan register struct nit_hdr *nh; 105169689Skan register int caplen; 106169689Skan 107169689Skan cc = p->cc; 108169689Skan if (cc == 0) { 109169689Skan cc = read(p->fd, (char *)p->buffer, p->bufsize); 110169689Skan if (cc < 0) { 111169689Skan if (errno == EWOULDBLOCK) 112169689Skan return (0); 113169689Skan snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s", 114169689Skan pcap_strerror(errno)); 115169689Skan return (-1); 116169689Skan } 117169689Skan bp = p->buffer; 118169689Skan } else 119169689Skan bp = p->bp; 120169689Skan 121169689Skan /* 122169689Skan * Loop through each packet. The increment expression 123169689Skan * rounds up to the next int boundary past the end of 124169689Skan * the previous packet. 125169689Skan */ 126169689Skan n = 0; 127169689Skan ep = bp + cc; 128169689Skan while (bp < ep) { 129169689Skan /* 130169689Skan * Has "pcap_breakloop()" been called? 131169689Skan * If so, return immediately - if we haven't read any 132169689Skan * packets, clear the flag and return -2 to indicate 133169689Skan * that we were told to break out of the loop, otherwise 134169689Skan * leave the flag set, so that the *next* call will break 135169689Skan * out of the loop without having read any packets, and 136169689Skan * return the number of packets we've processed so far. 137169689Skan */ 138169689Skan if (p->break_loop) { 139169689Skan if (n == 0) { 140169689Skan p->break_loop = 0; 141169689Skan return (-2); 142169689Skan } else { 143169689Skan p->cc = ep - bp; 144169689Skan p->bp = bp; 145169689Skan return (n); 146169689Skan } 147169689Skan } 148169689Skan 149169689Skan nh = (struct nit_hdr *)bp; 150169689Skan cp = bp + sizeof(*nh); 151169689Skan 152169689Skan switch (nh->nh_state) { 153169689Skan 154169689Skan case NIT_CATCH: 155169689Skan break; 156169689Skan 157169689Skan case NIT_NOMBUF: 158169689Skan case NIT_NOCLUSTER: 159169689Skan case NIT_NOSPACE: 160169689Skan p->md.stat.ps_drop = nh->nh_dropped; 161169689Skan continue; 162169689Skan 163169689Skan case NIT_SEQNO: 164169689Skan continue; 165169689Skan 166169689Skan default: 167169689Skan snprintf(p->errbuf, sizeof(p->errbuf), 168169689Skan "bad nit state %d", nh->nh_state); 169169689Skan return (-1); 170169689Skan } 171169689Skan ++p->md.stat.ps_recv; 172169689Skan bp += ((sizeof(struct nit_hdr) + nh->nh_datalen + 173169689Skan sizeof(int) - 1) & ~(sizeof(int) - 1)); 174169689Skan 175169689Skan caplen = nh->nh_wirelen; 176169689Skan if (caplen > p->snapshot) 177169689Skan caplen = p->snapshot; 178169689Skan if (bpf_filter(fcode, cp, nh->nh_wirelen, caplen)) { 179169689Skan struct pcap_pkthdr h; 180169689Skan h.ts = nh->nh_timestamp; 181169689Skan h.len = nh->nh_wirelen; 182169689Skan h.caplen = caplen; 183169689Skan (*callback)(user, &h, cp); 184169689Skan if (++n >= cnt && cnt >= 0) { 185169689Skan p->cc = ep - bp; 186169689Skan p->bp = bp; 187169689Skan return (n); 188169689Skan } 189169689Skan } 190169689Skan } 191169689Skan p->cc = 0; 192169689Skan return (n); 193169689Skan} 194169689Skan 195169689Skanstatic int 196169689Skanpcap_inject_nit(pcap_t *p, const void *buf, size_t size) 197169689Skan{ 198169689Skan struct sockaddr sa; 199169689Skan int ret; 200169689Skan 201169689Skan memset(&sa, 0, sizeof(sa)); 202169689Skan strncpy(sa.sa_data, device, sizeof(sa.sa_data)); 203169689Skan ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa)); 204169689Skan if (ret == -1) { 205169689Skan snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", 206169689Skan pcap_strerror(errno)); 207169689Skan return (-1); 208169689Skan } 209169689Skan return (ret); 210169689Skan} 211169689Skan 212169689Skanstatic int 213169689Skannit_setflags(int fd, int promisc, int to_ms, char *ebuf) 214169689Skan{ 215169689Skan struct nit_ioc nioc; 216169689Skan 217169689Skan memset(&nioc, 0, sizeof(nioc)); 218169689Skan nioc.nioc_bufspace = BUFSPACE; 219169689Skan nioc.nioc_chunksize = CHUNKSIZE; 220169689Skan nioc.nioc_typetomatch = NT_ALLTYPES; 221169689Skan nioc.nioc_snaplen = p->snapshot; 222169689Skan nioc.nioc_bufalign = sizeof(int); 223169689Skan nioc.nioc_bufoffset = 0; 224169689Skan 225169689Skan if (to_ms != 0) { 226169689Skan nioc.nioc_flags |= NF_TIMEOUT; 227169689Skan nioc.nioc_timeout.tv_sec = to_ms / 1000; 228169689Skan nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000; 229169689Skan } 230169689Skan if (promisc) 231169689Skan nioc.nioc_flags |= NF_PROMISC; 232169689Skan 233169689Skan if (ioctl(fd, SIOCSNIT, &nioc) < 0) { 234169689Skan snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s", 235169689Skan pcap_strerror(errno)); 236169689Skan return (-1); 237169689Skan } 238169689Skan return (0); 239169689Skan} 240169689Skan 241169689Skanstatic void 242169689Skanpcap_close_nit(pcap_t *p) 243169689Skan{ 244169689Skan pcap_close_common(p); 245169689Skan if (p->device != NULL) 246169689Skan free(p->device); 247169689Skan} 248169689Skan 249169689Skanpcap_t * 250169689Skanpcap_open_live(const char *device, int snaplen, int promisc, int to_ms, 251169689Skan char *ebuf) 252169689Skan{ 253169689Skan int fd; 254169689Skan struct sockaddr_nit snit; 255169689Skan register pcap_t *p; 256169689Skan 257169689Skan p = (pcap_t *)malloc(sizeof(*p)); 258169689Skan if (p == NULL) { 259169689Skan strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 260169689Skan return (NULL); 261169689Skan } 262169689Skan 263169689Skan if (snaplen < 96) 264169689Skan /* 265169689Skan * NIT requires a snapshot length of at least 96. 266169689Skan */ 267169689Skan snaplen = 96; 268169689Skan 269169689Skan memset(p, 0, sizeof(*p)); 270169689Skan p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW); 271169689Skan if (fd < 0) { 272169689Skan snprintf(ebuf, PCAP_ERRBUF_SIZE, 273169689Skan "socket: %s", pcap_strerror(errno)); 274169689Skan goto bad; 275169689Skan } 276169689Skan snit.snit_family = AF_NIT; 277169689Skan (void)strncpy(snit.snit_ifname, device, NITIFSIZ); 278169689Skan 279169689Skan if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) { 280169689Skan snprintf(ebuf, PCAP_ERRBUF_SIZE, 281169689Skan "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno)); 282169689Skan goto bad; 283169689Skan } 284169689Skan p->snapshot = snaplen; 285169689Skan nit_setflags(p->fd, promisc, to_ms, ebuf); 286169689Skan 287169689Skan /* 288169689Skan * NIT supports only ethernets. 289169689Skan */ 290169689Skan p->linktype = DLT_EN10MB; 291169689Skan 292169689Skan p->bufsize = BUFSPACE; 293169689Skan p->buffer = (u_char *)malloc(p->bufsize); 294169689Skan if (p->buffer == NULL) { 295169689Skan strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 296169689Skan goto bad; 297169689Skan } 298169689Skan 299169689Skan /* 300169689Skan * We need the device name in order to send packets. 301169689Skan */ 302169689Skan p->device = strdup(device); 303169689Skan if (p->device == NULL) { 304169689Skan strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 305169689Skan free(p->buffer); 306169689Skan goto bad; 307169689Skan } 308169689Skan 309169689Skan /* 310169689Skan * "p->fd" is a socket, so "select()" should work on it. 311169689Skan */ 312169689Skan p->selectable_fd = p->fd; 313169689Skan 314169689Skan /* 315169689Skan * This is (presumably) a real Ethernet capture; give it a 316169689Skan * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so 317169689Skan * that an application can let you choose it, in case you're 318169689Skan * capturing DOCSIS traffic that a Cisco Cable Modem 319169689Skan * Termination System is putting out onto an Ethernet (it 320169689Skan * doesn't put an Ethernet header onto the wire, it puts raw 321169689Skan * DOCSIS frames out on the wire inside the low-level 322169689Skan * Ethernet framing). 323169689Skan */ 324169689Skan p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); 325169689Skan /* 326169689Skan * If that fails, just leave the list empty. 327169689Skan */ 328169689Skan if (p->dlt_list != NULL) { 329169689Skan p->dlt_list[0] = DLT_EN10MB; 330169689Skan p->dlt_list[1] = DLT_DOCSIS; 331169689Skan p->dlt_count = 2; 332169689Skan } 333169689Skan 334169689Skan p->read_op = pcap_read_nit; 335169689Skan p->inject_op = pcap_inject_nit; 336169689Skan p->setfilter_op = install_bpf_program; /* no kernel filtering */ 337169689Skan p->set_datalink_op = NULL; /* can't change data link type */ 338169689Skan p->getnonblock_op = pcap_getnonblock_fd; 339169689Skan p->setnonblock_op = pcap_setnonblock_fd; 340169689Skan p->stats_op = pcap_stats_nit; 341169689Skan p->close_op = pcap_close_nit; 342169689Skan 343169689Skan return (p); 344169689Skan bad: 345169689Skan if (fd >= 0) 346169689Skan close(fd); 347169689Skan free(p); 348169689Skan return (NULL); 349169689Skan} 350169689Skan 351169689Skanint 352169689Skanpcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 353169689Skan{ 354169689Skan return (0); 355169689Skan} 356169689Skan