18cf6c252SPaul Traina /* 28cf6c252SPaul Traina * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 38cf6c252SPaul Traina * The Regents of the University of California. All rights reserved. 48cf6c252SPaul Traina * 58cf6c252SPaul Traina * Redistribution and use in source and binary forms, with or without 68cf6c252SPaul Traina * modification, are permitted provided that: (1) source code distributions 78cf6c252SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 88cf6c252SPaul Traina * distributions including binary code include the above copyright notice and 98cf6c252SPaul Traina * this paragraph in its entirety in the documentation or other materials 108cf6c252SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 118cf6c252SPaul Traina * features or use of this software display the following acknowledgement: 128cf6c252SPaul Traina * ``This product includes software developed by the University of California, 138cf6c252SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 148cf6c252SPaul Traina * the University nor the names of its contributors may be used to endorse 158cf6c252SPaul Traina * or promote products derived from this software without specific prior 168cf6c252SPaul Traina * written permission. 178cf6c252SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 188cf6c252SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 198cf6c252SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 203052b236SBill Fenner * 218cf6c252SPaul Traina * Modifications made to accommodate the new SunOS4.0 NIT facility by 228cf6c252SPaul Traina * Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989. 238cf6c252SPaul Traina * This module now handles the STREAMS based NIT. 248cf6c252SPaul Traina */ 258cf6c252SPaul Traina 263052b236SBill Fenner #ifndef lint 27feb4ecdbSBruce M Simpson static const char rcsid[] _U_ = 28a8e07101SRui Paulo "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.73.2.4 2008-04-14 20:41:52 guy Exp $ (LBL)"; 29dc2c7305SBill Fenner #endif 30dc2c7305SBill Fenner 31dc2c7305SBill Fenner #ifdef HAVE_CONFIG_H 32dc2c7305SBill Fenner #include "config.h" 333052b236SBill Fenner #endif 343052b236SBill Fenner 358cf6c252SPaul Traina #include <sys/types.h> 368cf6c252SPaul Traina #include <sys/time.h> 378cf6c252SPaul Traina #include <sys/timeb.h> 388cf6c252SPaul Traina #include <sys/dir.h> 398cf6c252SPaul Traina #include <sys/fcntlcom.h> 408cf6c252SPaul Traina #include <sys/file.h> 418cf6c252SPaul Traina #include <sys/ioctl.h> 428cf6c252SPaul Traina #include <sys/socket.h> 438cf6c252SPaul Traina #include <sys/stropts.h> 448cf6c252SPaul Traina 458cf6c252SPaul Traina #include <net/if.h> 468cf6c252SPaul Traina #include <net/nit.h> 478cf6c252SPaul Traina #include <net/nit_if.h> 488cf6c252SPaul Traina #include <net/nit_pf.h> 498cf6c252SPaul Traina #include <net/nit_buf.h> 508cf6c252SPaul Traina 518cf6c252SPaul Traina #include <netinet/in.h> 528cf6c252SPaul Traina #include <netinet/in_systm.h> 538cf6c252SPaul Traina #include <netinet/ip.h> 548cf6c252SPaul Traina #include <netinet/if_ether.h> 558cf6c252SPaul Traina #include <netinet/ip_var.h> 568cf6c252SPaul Traina #include <netinet/udp.h> 578cf6c252SPaul Traina #include <netinet/udp_var.h> 588cf6c252SPaul Traina #include <netinet/tcp.h> 598cf6c252SPaul Traina #include <netinet/tcpip.h> 608cf6c252SPaul Traina 618cf6c252SPaul Traina #include <ctype.h> 628cf6c252SPaul Traina #include <errno.h> 638cf6c252SPaul Traina #include <stdio.h> 648cf6c252SPaul Traina #include <string.h> 658cf6c252SPaul Traina #include <unistd.h> 668cf6c252SPaul Traina 678cf6c252SPaul Traina #include "pcap-int.h" 688cf6c252SPaul Traina 698cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H 708cf6c252SPaul Traina #include "os-proto.h" 718cf6c252SPaul Traina #endif 728cf6c252SPaul Traina 738cf6c252SPaul Traina /* 748cf6c252SPaul Traina * The chunk size for NIT. This is the amount of buffering 758cf6c252SPaul Traina * done for read calls. 768cf6c252SPaul Traina */ 778cf6c252SPaul Traina #define CHUNKSIZE (2*1024) 788cf6c252SPaul Traina 798cf6c252SPaul Traina /* 808cf6c252SPaul Traina * The total buffer space used by NIT. 818cf6c252SPaul Traina */ 828cf6c252SPaul Traina #define BUFSPACE (4*CHUNKSIZE) 838cf6c252SPaul Traina 848cf6c252SPaul Traina /* Forwards */ 858cf6c252SPaul Traina static int nit_setflags(int, int, int, char *); 868cf6c252SPaul Traina 87feb4ecdbSBruce M Simpson static int 88feb4ecdbSBruce M Simpson pcap_stats_snit(pcap_t *p, struct pcap_stat *ps) 898cf6c252SPaul Traina { 908cf6c252SPaul Traina 910a94d38fSBill Fenner /* 920a94d38fSBill Fenner * "ps_recv" counts packets handed to the filter, not packets 930a94d38fSBill Fenner * that passed the filter. As filtering is done in userland, 940a94d38fSBill Fenner * this does not include packets dropped because we ran out 950a94d38fSBill Fenner * of buffer space. 960a94d38fSBill Fenner * 970a94d38fSBill Fenner * "ps_drop" counts packets dropped inside the "/dev/nit" 980a94d38fSBill Fenner * device because of flow control requirements or resource 990a94d38fSBill Fenner * exhaustion; it doesn't count packets dropped by the 1000a94d38fSBill Fenner * interface driver, or packets dropped upstream. As filtering 1010a94d38fSBill Fenner * is done in userland, it counts packets regardless of whether 1020a94d38fSBill Fenner * they would've passed the filter. 1030a94d38fSBill Fenner * 1040a94d38fSBill Fenner * These statistics don't include packets not yet read from the 1050a94d38fSBill Fenner * kernel by libpcap or packets not yet read from libpcap by the 1060a94d38fSBill Fenner * application. 1070a94d38fSBill Fenner */ 1088cf6c252SPaul Traina *ps = p->md.stat; 1098cf6c252SPaul Traina return (0); 1108cf6c252SPaul Traina } 1118cf6c252SPaul Traina 112feb4ecdbSBruce M Simpson static int 113feb4ecdbSBruce M Simpson pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 1148cf6c252SPaul Traina { 1158cf6c252SPaul Traina register int cc, n; 1168cf6c252SPaul Traina register u_char *bp, *cp, *ep; 1178cf6c252SPaul Traina register struct nit_bufhdr *hdrp; 1188cf6c252SPaul Traina register struct nit_iftime *ntp; 1198cf6c252SPaul Traina register struct nit_iflen *nlp; 1208cf6c252SPaul Traina register struct nit_ifdrops *ndp; 1218cf6c252SPaul Traina register int caplen; 1228cf6c252SPaul Traina 1238cf6c252SPaul Traina cc = p->cc; 1248cf6c252SPaul Traina if (cc == 0) { 1258cf6c252SPaul Traina cc = read(p->fd, (char *)p->buffer, p->bufsize); 1268cf6c252SPaul Traina if (cc < 0) { 1278cf6c252SPaul Traina if (errno == EWOULDBLOCK) 1288cf6c252SPaul Traina return (0); 129dc2c7305SBill Fenner snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s", 1308cf6c252SPaul Traina pcap_strerror(errno)); 1318cf6c252SPaul Traina return (-1); 1328cf6c252SPaul Traina } 1338cf6c252SPaul Traina bp = p->buffer; 1348cf6c252SPaul Traina } else 1358cf6c252SPaul Traina bp = p->bp; 1368cf6c252SPaul Traina 1378cf6c252SPaul Traina /* 1388cf6c252SPaul Traina * loop through each snapshot in the chunk 1398cf6c252SPaul Traina */ 1408cf6c252SPaul Traina n = 0; 1418cf6c252SPaul Traina ep = bp + cc; 1428cf6c252SPaul Traina while (bp < ep) { 143feb4ecdbSBruce M Simpson /* 144feb4ecdbSBruce M Simpson * Has "pcap_breakloop()" been called? 145feb4ecdbSBruce M Simpson * If so, return immediately - if we haven't read any 146feb4ecdbSBruce M Simpson * packets, clear the flag and return -2 to indicate 147feb4ecdbSBruce M Simpson * that we were told to break out of the loop, otherwise 148feb4ecdbSBruce M Simpson * leave the flag set, so that the *next* call will break 149feb4ecdbSBruce M Simpson * out of the loop without having read any packets, and 150feb4ecdbSBruce M Simpson * return the number of packets we've processed so far. 151feb4ecdbSBruce M Simpson */ 152feb4ecdbSBruce M Simpson if (p->break_loop) { 153feb4ecdbSBruce M Simpson if (n == 0) { 154feb4ecdbSBruce M Simpson p->break_loop = 0; 155feb4ecdbSBruce M Simpson return (-2); 156feb4ecdbSBruce M Simpson } else { 157feb4ecdbSBruce M Simpson p->bp = bp; 158feb4ecdbSBruce M Simpson p->cc = ep - bp; 159feb4ecdbSBruce M Simpson return (n); 160feb4ecdbSBruce M Simpson } 161feb4ecdbSBruce M Simpson } 162feb4ecdbSBruce M Simpson 1638cf6c252SPaul Traina ++p->md.stat.ps_recv; 1648cf6c252SPaul Traina cp = bp; 1658cf6c252SPaul Traina 1668cf6c252SPaul Traina /* get past NIT buffer */ 1678cf6c252SPaul Traina hdrp = (struct nit_bufhdr *)cp; 1688cf6c252SPaul Traina cp += sizeof(*hdrp); 1698cf6c252SPaul Traina 1708cf6c252SPaul Traina /* get past NIT timer */ 1718cf6c252SPaul Traina ntp = (struct nit_iftime *)cp; 1728cf6c252SPaul Traina cp += sizeof(*ntp); 1738cf6c252SPaul Traina 1748cf6c252SPaul Traina ndp = (struct nit_ifdrops *)cp; 1758cf6c252SPaul Traina p->md.stat.ps_drop = ndp->nh_drops; 1768cf6c252SPaul Traina cp += sizeof *ndp; 1778cf6c252SPaul Traina 1788cf6c252SPaul Traina /* get past packet len */ 1798cf6c252SPaul Traina nlp = (struct nit_iflen *)cp; 1808cf6c252SPaul Traina cp += sizeof(*nlp); 1818cf6c252SPaul Traina 1828cf6c252SPaul Traina /* next snapshot */ 1838cf6c252SPaul Traina bp += hdrp->nhb_totlen; 1848cf6c252SPaul Traina 1858cf6c252SPaul Traina caplen = nlp->nh_pktlen; 1868cf6c252SPaul Traina if (caplen > p->snapshot) 1878cf6c252SPaul Traina caplen = p->snapshot; 1888cf6c252SPaul Traina 189a8e07101SRui Paulo if (bpf_filter(p->fcode.bf_insns, cp, nlp->nh_pktlen, caplen)) { 1908cf6c252SPaul Traina struct pcap_pkthdr h; 1918cf6c252SPaul Traina h.ts = ntp->nh_timestamp; 1928cf6c252SPaul Traina h.len = nlp->nh_pktlen; 1938cf6c252SPaul Traina h.caplen = caplen; 1948cf6c252SPaul Traina (*callback)(user, &h, cp); 195a8e07101SRui Paulo if (++n >= cnt && cnt > 0) { 1968cf6c252SPaul Traina p->cc = ep - bp; 1978cf6c252SPaul Traina p->bp = bp; 1988cf6c252SPaul Traina return (n); 1998cf6c252SPaul Traina } 2008cf6c252SPaul Traina } 2018cf6c252SPaul Traina } 2028cf6c252SPaul Traina p->cc = 0; 2038cf6c252SPaul Traina return (n); 2048cf6c252SPaul Traina } 2058cf6c252SPaul Traina 2068cf6c252SPaul Traina static int 20704fb2745SSam Leffler pcap_inject_snit(pcap_t *p, const void *buf, size_t size) 20804fb2745SSam Leffler { 20904fb2745SSam Leffler struct strbuf ctl, data; 21004fb2745SSam Leffler 21104fb2745SSam Leffler /* 21204fb2745SSam Leffler * XXX - can we just do 21304fb2745SSam Leffler * 21404fb2745SSam Leffler ret = write(pd->f, buf, size); 21504fb2745SSam Leffler */ 21604fb2745SSam Leffler ctl.len = sizeof(*sa); /* XXX - what was this? */ 21704fb2745SSam Leffler ctl.buf = (char *)sa; 21804fb2745SSam Leffler data.buf = buf; 21904fb2745SSam Leffler data.len = size; 22004fb2745SSam Leffler ret = putmsg(p->fd, &ctl, &data); 22104fb2745SSam Leffler if (ret == -1) { 22204fb2745SSam Leffler snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", 22304fb2745SSam Leffler pcap_strerror(errno)); 22404fb2745SSam Leffler return (-1); 22504fb2745SSam Leffler } 22604fb2745SSam Leffler return (ret); 22704fb2745SSam Leffler } 22804fb2745SSam Leffler 22904fb2745SSam Leffler static int 2308cf6c252SPaul Traina nit_setflags(int fd, int promisc, int to_ms, char *ebuf) 2318cf6c252SPaul Traina { 2328cf6c252SPaul Traina bpf_u_int32 flags; 2338cf6c252SPaul Traina struct strioctl si; 2348cf6c252SPaul Traina struct timeval timeout; 2358cf6c252SPaul Traina 2368cf6c252SPaul Traina si.ic_timout = INFTIM; 2378cf6c252SPaul Traina if (to_ms != 0) { 2388cf6c252SPaul Traina timeout.tv_sec = to_ms / 1000; 2398cf6c252SPaul Traina timeout.tv_usec = (to_ms * 1000) % 1000000; 2408cf6c252SPaul Traina si.ic_cmd = NIOCSTIME; 2418cf6c252SPaul Traina si.ic_len = sizeof(timeout); 2428cf6c252SPaul Traina si.ic_dp = (char *)&timeout; 2438cf6c252SPaul Traina if (ioctl(fd, I_STR, (char *)&si) < 0) { 244dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s", 245dc2c7305SBill Fenner pcap_strerror(errno)); 2468cf6c252SPaul Traina return (-1); 2478cf6c252SPaul Traina } 2488cf6c252SPaul Traina } 2498cf6c252SPaul Traina flags = NI_TIMESTAMP | NI_LEN | NI_DROPS; 2508cf6c252SPaul Traina if (promisc) 2518cf6c252SPaul Traina flags |= NI_PROMISC; 2528cf6c252SPaul Traina si.ic_cmd = NIOCSFLAGS; 2538cf6c252SPaul Traina si.ic_len = sizeof(flags); 2548cf6c252SPaul Traina si.ic_dp = (char *)&flags; 2558cf6c252SPaul Traina if (ioctl(fd, I_STR, (char *)&si) < 0) { 256dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s", 257dc2c7305SBill Fenner pcap_strerror(errno)); 2588cf6c252SPaul Traina return (-1); 2598cf6c252SPaul Traina } 2608cf6c252SPaul Traina return (0); 2618cf6c252SPaul Traina } 2628cf6c252SPaul Traina 263a8e07101SRui Paulo static int 264a8e07101SRui Paulo pcap_activate_snit(pcap_t *p) 2658cf6c252SPaul Traina { 2668cf6c252SPaul Traina struct strioctl si; /* struct for ioctl() */ 2678cf6c252SPaul Traina struct ifreq ifr; /* interface request struct */ 2688cf6c252SPaul Traina int chunksize = CHUNKSIZE; 2698cf6c252SPaul Traina int fd; 2708cf6c252SPaul Traina static char dev[] = "/dev/nit"; 2718cf6c252SPaul Traina 272a8e07101SRui Paulo if (p->opt.rfmon) { 273a8e07101SRui Paulo /* 274a8e07101SRui Paulo * No monitor mode on SunOS 4.x (no Wi-Fi devices on 275a8e07101SRui Paulo * hardware supported by SunOS 4.x). 276a8e07101SRui Paulo */ 277a8e07101SRui Paulo return (PCAP_ERROR_RFMON_NOTSUP); 2788cf6c252SPaul Traina } 2798cf6c252SPaul Traina 280a8e07101SRui Paulo if (p->snapshot < 96) 2818cf6c252SPaul Traina /* 2828cf6c252SPaul Traina * NIT requires a snapshot length of at least 96. 2838cf6c252SPaul Traina */ 284a8e07101SRui Paulo p->snapshot = 96; 2858cf6c252SPaul Traina 28604fb2745SSam Leffler /* 28704fb2745SSam Leffler * Initially try a read/write open (to allow the inject 28804fb2745SSam Leffler * method to work). If that fails due to permission 28904fb2745SSam Leffler * issues, fall back to read-only. This allows a 29004fb2745SSam Leffler * non-root user to be granted specific access to pcap 29104fb2745SSam Leffler * capabilities via file permissions. 29204fb2745SSam Leffler * 29304fb2745SSam Leffler * XXX - we should have an API that has a flag that 29404fb2745SSam Leffler * controls whether to open read-only or read-write, 29504fb2745SSam Leffler * so that denial of permission to send (or inability 29604fb2745SSam Leffler * to send, if sending packets isn't supported on 29704fb2745SSam Leffler * the device in question) can be indicated at open 29804fb2745SSam Leffler * time. 29904fb2745SSam Leffler */ 30004fb2745SSam Leffler p->fd = fd = open(dev, O_RDWR); 30104fb2745SSam Leffler if (fd < 0 && errno == EACCES) 3028cf6c252SPaul Traina p->fd = fd = open(dev, O_RDONLY); 3038cf6c252SPaul Traina if (fd < 0) { 304a8e07101SRui Paulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev, 305dc2c7305SBill Fenner pcap_strerror(errno)); 3068cf6c252SPaul Traina goto bad; 3078cf6c252SPaul Traina } 3088cf6c252SPaul Traina 3098cf6c252SPaul Traina /* arrange to get discrete messages from the STREAM and use NIT_BUF */ 3108cf6c252SPaul Traina if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) { 311a8e07101SRui Paulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s", 312dc2c7305SBill Fenner pcap_strerror(errno)); 3138cf6c252SPaul Traina goto bad; 3148cf6c252SPaul Traina } 3158cf6c252SPaul Traina if (ioctl(fd, I_PUSH, "nbuf") < 0) { 316a8e07101SRui Paulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s", 317dc2c7305SBill Fenner pcap_strerror(errno)); 3188cf6c252SPaul Traina goto bad; 3198cf6c252SPaul Traina } 3208cf6c252SPaul Traina /* set the chunksize */ 3218cf6c252SPaul Traina si.ic_cmd = NIOCSCHUNK; 3228cf6c252SPaul Traina si.ic_timout = INFTIM; 3238cf6c252SPaul Traina si.ic_len = sizeof(chunksize); 3248cf6c252SPaul Traina si.ic_dp = (char *)&chunksize; 3258cf6c252SPaul Traina if (ioctl(fd, I_STR, (char *)&si) < 0) { 326a8e07101SRui Paulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s", 327dc2c7305SBill Fenner pcap_strerror(errno)); 3288cf6c252SPaul Traina goto bad; 3298cf6c252SPaul Traina } 3308cf6c252SPaul Traina 3318cf6c252SPaul Traina /* request the interface */ 332a8e07101SRui Paulo strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); 333feb4ecdbSBruce M Simpson ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; 3348cf6c252SPaul Traina si.ic_cmd = NIOCBIND; 3358cf6c252SPaul Traina si.ic_len = sizeof(ifr); 3368cf6c252SPaul Traina si.ic_dp = (char *)𝔦 3378cf6c252SPaul Traina if (ioctl(fd, I_STR, (char *)&si) < 0) { 338a8e07101SRui Paulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s", 3398cf6c252SPaul Traina ifr.ifr_name, pcap_strerror(errno)); 3408cf6c252SPaul Traina goto bad; 3418cf6c252SPaul Traina } 3428cf6c252SPaul Traina 3438cf6c252SPaul Traina /* set the snapshot length */ 3448cf6c252SPaul Traina si.ic_cmd = NIOCSSNAP; 345a8e07101SRui Paulo si.ic_len = sizeof(p->snapshot); 346a8e07101SRui Paulo si.ic_dp = (char *)&p->snapshot; 3478cf6c252SPaul Traina if (ioctl(fd, I_STR, (char *)&si) < 0) { 348a8e07101SRui Paulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s", 349dc2c7305SBill Fenner pcap_strerror(errno)); 3508cf6c252SPaul Traina goto bad; 3518cf6c252SPaul Traina } 352a8e07101SRui Paulo if (nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf) < 0) 3538cf6c252SPaul Traina goto bad; 3548cf6c252SPaul Traina 3558cf6c252SPaul Traina (void)ioctl(fd, I_FLUSH, (char *)FLUSHR); 3568cf6c252SPaul Traina /* 3578cf6c252SPaul Traina * NIT supports only ethernets. 3588cf6c252SPaul Traina */ 3598cf6c252SPaul Traina p->linktype = DLT_EN10MB; 3608cf6c252SPaul Traina 3618cf6c252SPaul Traina p->bufsize = BUFSPACE; 3628cf6c252SPaul Traina p->buffer = (u_char *)malloc(p->bufsize); 3638cf6c252SPaul Traina if (p->buffer == NULL) { 364a8e07101SRui Paulo strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 3658cf6c252SPaul Traina goto bad; 3668cf6c252SPaul Traina } 367feb4ecdbSBruce M Simpson 368feb4ecdbSBruce M Simpson /* 369feb4ecdbSBruce M Simpson * "p->fd" is an FD for a STREAMS device, so "select()" and 370feb4ecdbSBruce M Simpson * "poll()" should work on it. 371feb4ecdbSBruce M Simpson */ 372feb4ecdbSBruce M Simpson p->selectable_fd = p->fd; 373feb4ecdbSBruce M Simpson 37404fb2745SSam Leffler /* 37504fb2745SSam Leffler * This is (presumably) a real Ethernet capture; give it a 37604fb2745SSam Leffler * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so 37704fb2745SSam Leffler * that an application can let you choose it, in case you're 37804fb2745SSam Leffler * capturing DOCSIS traffic that a Cisco Cable Modem 37904fb2745SSam Leffler * Termination System is putting out onto an Ethernet (it 38004fb2745SSam Leffler * doesn't put an Ethernet header onto the wire, it puts raw 38104fb2745SSam Leffler * DOCSIS frames out on the wire inside the low-level 38204fb2745SSam Leffler * Ethernet framing). 38304fb2745SSam Leffler */ 38404fb2745SSam Leffler p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); 38504fb2745SSam Leffler /* 38604fb2745SSam Leffler * If that fails, just leave the list empty. 38704fb2745SSam Leffler */ 38804fb2745SSam Leffler if (p->dlt_list != NULL) { 38904fb2745SSam Leffler p->dlt_list[0] = DLT_EN10MB; 39004fb2745SSam Leffler p->dlt_list[1] = DLT_DOCSIS; 39104fb2745SSam Leffler p->dlt_count = 2; 39204fb2745SSam Leffler } 39304fb2745SSam Leffler 394feb4ecdbSBruce M Simpson p->read_op = pcap_read_snit; 39504fb2745SSam Leffler p->inject_op = pcap_inject_snit; 396feb4ecdbSBruce M Simpson p->setfilter_op = install_bpf_program; /* no kernel filtering */ 397ee2dd488SSam Leffler p->setdirection_op = NULL; /* Not implemented. */ 398feb4ecdbSBruce M Simpson p->set_datalink_op = NULL; /* can't change data link type */ 399feb4ecdbSBruce M Simpson p->getnonblock_op = pcap_getnonblock_fd; 400feb4ecdbSBruce M Simpson p->setnonblock_op = pcap_setnonblock_fd; 401feb4ecdbSBruce M Simpson p->stats_op = pcap_stats_snit; 402feb4ecdbSBruce M Simpson 403a8e07101SRui Paulo return (0); 4048cf6c252SPaul Traina bad: 405a8e07101SRui Paulo return (PCAP_ERROR); 406a8e07101SRui Paulo } 407a8e07101SRui Paulo 408a8e07101SRui Paulo pcap_t * 409a8e07101SRui Paulo pcap_create(const char *device, char *ebuf) 410a8e07101SRui Paulo { 411a8e07101SRui Paulo pcap_t *p; 412a8e07101SRui Paulo 413a8e07101SRui Paulo p = pcap_create_common(device, ebuf); 414a8e07101SRui Paulo if (p == NULL) 4158cf6c252SPaul Traina return (NULL); 416a8e07101SRui Paulo 417a8e07101SRui Paulo p->activate_op = pcap_activate_snit; 418a8e07101SRui Paulo return (p); 4198cf6c252SPaul Traina } 4208cf6c252SPaul Traina 4218cf6c252SPaul Traina int 422feb4ecdbSBruce M Simpson pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 4238cf6c252SPaul Traina { 4248cf6c252SPaul Traina return (0); 4258cf6c252SPaul Traina } 426