117683Spst/* 217683Spst * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 317683Spst * The Regents of the University of California. All rights reserved. 417683Spst * 517683Spst * Redistribution and use in source and binary forms, with or without 617683Spst * modification, are permitted provided that: (1) source code distributions 717683Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817683Spst * distributions including binary code include the above copyright notice and 917683Spst * this paragraph in its entirety in the documentation or other materials 1017683Spst * provided with the distribution, and (3) all advertising materials mentioning 1117683Spst * features or use of this software display the following acknowledgement: 1217683Spst * ``This product includes software developed by the University of California, 1317683Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417683Spst * the University nor the names of its contributors may be used to endorse 1517683Spst * or promote products derived from this software without specific prior 1617683Spst * written permission. 1717683Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817683Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917683Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2017683Spst */ 2117683Spst#ifndef lint 22127664Sbmsstatic const char rcsid[] _U_ = 23214518Srpaulo "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.62 2008-04-14 20:40:58 guy Exp $ (LBL)"; 2417683Spst#endif 2517683Spst 2675107Sfenner#ifdef HAVE_CONFIG_H 2775107Sfenner#include "config.h" 2875107Sfenner#endif 2975107Sfenner 3017683Spst#include <sys/types.h> 3117683Spst#include <sys/time.h> 3217683Spst#include <sys/timeb.h> 3317683Spst#include <sys/file.h> 3417683Spst#include <sys/ioctl.h> 3517683Spst#include <sys/socket.h> 3617683Spst 3717683Spst#include <net/if.h> 3817683Spst#include <net/nit.h> 3917683Spst 4017683Spst#include <netinet/in.h> 4117683Spst#include <netinet/in_systm.h> 4217683Spst#include <netinet/ip.h> 4317683Spst#include <netinet/if_ether.h> 4417683Spst#include <netinet/ip_var.h> 4517683Spst#include <netinet/udp.h> 4617683Spst#include <netinet/udp_var.h> 4717683Spst#include <netinet/tcp.h> 4817683Spst#include <netinet/tcpip.h> 4917683Spst 5017683Spst#include <ctype.h> 5117683Spst#include <errno.h> 5217683Spst#include <stdio.h> 5317683Spst 5417683Spst#include "pcap-int.h" 5517683Spst 5617683Spst#ifdef HAVE_OS_PROTO_H 5717683Spst#include "os-proto.h" 5817683Spst#endif 5917683Spst 6017683Spst/* 6117683Spst * The chunk size for NIT. This is the amount of buffering 6217683Spst * done for read calls. 6317683Spst */ 6417683Spst#define CHUNKSIZE (2*1024) 6517683Spst 6617683Spst/* 6717683Spst * The total buffer space used by NIT. 6817683Spst */ 6917683Spst#define BUFSPACE (4*CHUNKSIZE) 7017683Spst 7117683Spst/* Forwards */ 7217683Spststatic int nit_setflags(int, int, int, char *); 7317683Spst 74127664Sbmsstatic int 75127664Sbmspcap_stats_nit(pcap_t *p, struct pcap_stat *ps) 7617683Spst{ 7717683Spst 7898530Sfenner /* 7998530Sfenner * "ps_recv" counts packets handed to the filter, not packets 8098530Sfenner * that passed the filter. As filtering is done in userland, 8198530Sfenner * this does not include packets dropped because we ran out 8298530Sfenner * of buffer space. 8398530Sfenner * 8498530Sfenner * "ps_drop" presumably counts packets dropped by the socket 8598530Sfenner * because of flow control requirements or resource exhaustion; 8698530Sfenner * it doesn't count packets dropped by the interface driver. 8798530Sfenner * As filtering is done in userland, it counts packets regardless 8898530Sfenner * of whether they would've passed the filter. 8998530Sfenner * 9098530Sfenner * These statistics don't include packets not yet read from the 9198530Sfenner * kernel by libpcap or packets not yet read from libpcap by the 9298530Sfenner * application. 9398530Sfenner */ 9417683Spst *ps = p->md.stat; 9517683Spst return (0); 9617683Spst} 9717683Spst 98127664Sbmsstatic int 99127664Sbmspcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 10017683Spst{ 10117683Spst register int cc, n; 10217683Spst register u_char *bp, *cp, *ep; 10317683Spst register struct nit_hdr *nh; 10417683Spst register int caplen; 10517683Spst 10617683Spst cc = p->cc; 10717683Spst if (cc == 0) { 10817683Spst cc = read(p->fd, (char *)p->buffer, p->bufsize); 10917683Spst if (cc < 0) { 11017683Spst if (errno == EWOULDBLOCK) 11117683Spst return (0); 11275107Sfenner snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s", 11317683Spst pcap_strerror(errno)); 11417683Spst return (-1); 11517683Spst } 11617683Spst bp = p->buffer; 11717683Spst } else 11817683Spst bp = p->bp; 11917683Spst 12017683Spst /* 12117683Spst * Loop through each packet. The increment expression 12217683Spst * rounds up to the next int boundary past the end of 12317683Spst * the previous packet. 12417683Spst */ 12517683Spst n = 0; 12617683Spst ep = bp + cc; 12717683Spst while (bp < ep) { 128127664Sbms /* 129127664Sbms * Has "pcap_breakloop()" been called? 130127664Sbms * If so, return immediately - if we haven't read any 131127664Sbms * packets, clear the flag and return -2 to indicate 132127664Sbms * that we were told to break out of the loop, otherwise 133127664Sbms * leave the flag set, so that the *next* call will break 134127664Sbms * out of the loop without having read any packets, and 135127664Sbms * return the number of packets we've processed so far. 136127664Sbms */ 137127664Sbms if (p->break_loop) { 138127664Sbms if (n == 0) { 139127664Sbms p->break_loop = 0; 140127664Sbms return (-2); 141127664Sbms } else { 142127664Sbms p->cc = ep - bp; 143127664Sbms p->bp = bp; 144127664Sbms return (n); 145127664Sbms } 146127664Sbms } 147127664Sbms 14817683Spst nh = (struct nit_hdr *)bp; 14917683Spst cp = bp + sizeof(*nh); 15017683Spst 15117683Spst switch (nh->nh_state) { 15217683Spst 15317683Spst case NIT_CATCH: 15417683Spst break; 15517683Spst 15617683Spst case NIT_NOMBUF: 15717683Spst case NIT_NOCLUSTER: 15817683Spst case NIT_NOSPACE: 15917683Spst p->md.stat.ps_drop = nh->nh_dropped; 16017683Spst continue; 16117683Spst 16217683Spst case NIT_SEQNO: 16317683Spst continue; 16417683Spst 16517683Spst default: 16675107Sfenner snprintf(p->errbuf, sizeof(p->errbuf), 16775107Sfenner "bad nit state %d", nh->nh_state); 16817683Spst return (-1); 16917683Spst } 17017683Spst ++p->md.stat.ps_recv; 17117683Spst bp += ((sizeof(struct nit_hdr) + nh->nh_datalen + 17217683Spst sizeof(int) - 1) & ~(sizeof(int) - 1)); 17317683Spst 17417683Spst caplen = nh->nh_wirelen; 17517683Spst if (caplen > p->snapshot) 17617683Spst caplen = p->snapshot; 177190225Srpaulo if (bpf_filter(p->fcode.bf_insns, cp, nh->nh_wirelen, caplen)) { 17817683Spst struct pcap_pkthdr h; 17917683Spst h.ts = nh->nh_timestamp; 18017683Spst h.len = nh->nh_wirelen; 18117683Spst h.caplen = caplen; 18217683Spst (*callback)(user, &h, cp); 183190225Srpaulo if (++n >= cnt && cnt > 0) { 18417683Spst p->cc = ep - bp; 18517683Spst p->bp = bp; 18617683Spst return (n); 18717683Spst } 18817683Spst } 18917683Spst } 19017683Spst p->cc = 0; 19117683Spst return (n); 19217683Spst} 19317683Spst 19417683Spststatic int 195146768Ssampcap_inject_nit(pcap_t *p, const void *buf, size_t size) 196146768Ssam{ 197146768Ssam struct sockaddr sa; 198146768Ssam int ret; 199146768Ssam 200146768Ssam memset(&sa, 0, sizeof(sa)); 201146768Ssam strncpy(sa.sa_data, device, sizeof(sa.sa_data)); 202146768Ssam ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa)); 203146768Ssam if (ret == -1) { 204146768Ssam snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", 205146768Ssam pcap_strerror(errno)); 206146768Ssam return (-1); 207146768Ssam } 208146768Ssam return (ret); 209146768Ssam} 210146768Ssam 211146768Ssamstatic int 21217683Spstnit_setflags(int fd, int promisc, int to_ms, char *ebuf) 21317683Spst{ 21417683Spst struct nit_ioc nioc; 21517683Spst 21675107Sfenner memset(&nioc, 0, sizeof(nioc)); 21717683Spst nioc.nioc_bufspace = BUFSPACE; 21817683Spst nioc.nioc_chunksize = CHUNKSIZE; 21917683Spst nioc.nioc_typetomatch = NT_ALLTYPES; 22017683Spst nioc.nioc_snaplen = p->snapshot; 22117683Spst nioc.nioc_bufalign = sizeof(int); 22217683Spst nioc.nioc_bufoffset = 0; 22317683Spst 22417683Spst if (to_ms != 0) { 22517683Spst nioc.nioc_flags |= NF_TIMEOUT; 22617683Spst nioc.nioc_timeout.tv_sec = to_ms / 1000; 22717683Spst nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000; 22817683Spst } 22917683Spst if (promisc) 23017683Spst nioc.nioc_flags |= NF_PROMISC; 23117683Spst 23217683Spst if (ioctl(fd, SIOCSNIT, &nioc) < 0) { 23375107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s", 23475107Sfenner pcap_strerror(errno)); 23517683Spst return (-1); 23617683Spst } 23717683Spst return (0); 23817683Spst} 23917683Spst 240190225Srpaulostatic int 241190225Srpaulopcap_activate_nit(pcap_t *p) 242127664Sbms{ 24317683Spst int fd; 24417683Spst struct sockaddr_nit snit; 24517683Spst 246190225Srpaulo if (p->opt.rfmon) { 247190225Srpaulo /* 248190225Srpaulo * No monitor mode on SunOS 3.x or earlier (no 249190225Srpaulo * Wi-Fi *devices* for the hardware that supported 250190225Srpaulo * them!). 251190225Srpaulo */ 252190225Srpaulo return (PCAP_ERROR_RFMON_NOTSUP); 25317683Spst } 25417683Spst 255190225Srpaulo if (p->snapshot < 96) 25617683Spst /* 25717683Spst * NIT requires a snapshot length of at least 96. 25817683Spst */ 259190225Srpaulo p->snapshot = 96; 26017683Spst 26175107Sfenner memset(p, 0, sizeof(*p)); 26217683Spst p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW); 26317683Spst if (fd < 0) { 264190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 26575107Sfenner "socket: %s", pcap_strerror(errno)); 26617683Spst goto bad; 26717683Spst } 26817683Spst snit.snit_family = AF_NIT; 269190225Srpaulo (void)strncpy(snit.snit_ifname, p->opt.source, NITIFSIZ); 27017683Spst 27117683Spst if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) { 272190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 27375107Sfenner "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno)); 27417683Spst goto bad; 27517683Spst } 276190225Srpaulo nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf); 27717683Spst 27817683Spst /* 27917683Spst * NIT supports only ethernets. 28017683Spst */ 28117683Spst p->linktype = DLT_EN10MB; 28217683Spst 28317683Spst p->bufsize = BUFSPACE; 28417683Spst p->buffer = (u_char *)malloc(p->bufsize); 28517683Spst if (p->buffer == NULL) { 286190225Srpaulo strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 28717683Spst goto bad; 28817683Spst } 289127664Sbms 290127664Sbms /* 291127664Sbms * "p->fd" is a socket, so "select()" should work on it. 292127664Sbms */ 293127664Sbms p->selectable_fd = p->fd; 294127664Sbms 295146768Ssam /* 296146768Ssam * This is (presumably) a real Ethernet capture; give it a 297146768Ssam * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so 298146768Ssam * that an application can let you choose it, in case you're 299146768Ssam * capturing DOCSIS traffic that a Cisco Cable Modem 300146768Ssam * Termination System is putting out onto an Ethernet (it 301146768Ssam * doesn't put an Ethernet header onto the wire, it puts raw 302146768Ssam * DOCSIS frames out on the wire inside the low-level 303146768Ssam * Ethernet framing). 304146768Ssam */ 305146768Ssam p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); 306146768Ssam /* 307146768Ssam * If that fails, just leave the list empty. 308146768Ssam */ 309146768Ssam if (p->dlt_list != NULL) { 310146768Ssam p->dlt_list[0] = DLT_EN10MB; 311146768Ssam p->dlt_list[1] = DLT_DOCSIS; 312146768Ssam p->dlt_count = 2; 313146768Ssam } 314146768Ssam 315127664Sbms p->read_op = pcap_read_nit; 316146768Ssam p->inject_op = pcap_inject_nit; 317127664Sbms p->setfilter_op = install_bpf_program; /* no kernel filtering */ 318147894Ssam p->setdirection_op = NULL; /* Not implemented. */ 319127664Sbms p->set_datalink_op = NULL; /* can't change data link type */ 320127664Sbms p->getnonblock_op = pcap_getnonblock_fd; 321127664Sbms p->setnonblock_op = pcap_setnonblock_fd; 322127664Sbms p->stats_op = pcap_stats_nit; 323127664Sbms 324190225Srpaulo return (0); 32517683Spst bad: 326214518Srpaulo pcap_cleanup_live_common(p); 327190225Srpaulo return (PCAP_ERROR); 32817683Spst} 32917683Spst 330190225Srpaulopcap_t * 331251129Sdelphijpcap_create_interface(const char *device, char *ebuf) 332190225Srpaulo{ 333190225Srpaulo pcap_t *p; 334190225Srpaulo 335190225Srpaulo p = pcap_create_common(device, ebuf); 336190225Srpaulo if (p == NULL) 337190225Srpaulo return (NULL); 338190225Srpaulo 339190225Srpaulo p->activate_op = pcap_activate_nit; 340190225Srpaulo return (p); 341190225Srpaulo} 342190225Srpaulo 34317683Spstint 344127664Sbmspcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 34517683Spst{ 34617683Spst return (0); 34717683Spst} 348