18cf6c252SPaul Traina /* 2a4b5b39fSBill Fenner * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998 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 the following conditions 78cf6c252SPaul Traina * are met: 88cf6c252SPaul Traina * 1. Redistributions of source code must retain the above copyright 98cf6c252SPaul Traina * notice, this list of conditions and the following disclaimer. 108cf6c252SPaul Traina * 2. Redistributions in binary form must reproduce the above copyright 118cf6c252SPaul Traina * notice, this list of conditions and the following disclaimer in the 128cf6c252SPaul Traina * documentation and/or other materials provided with the distribution. 138cf6c252SPaul Traina * 3. All advertising materials mentioning features or use of this software 148cf6c252SPaul Traina * must display the following acknowledgement: 158cf6c252SPaul Traina * This product includes software developed by the Computer Systems 168cf6c252SPaul Traina * Engineering Group at Lawrence Berkeley Laboratory. 178cf6c252SPaul Traina * 4. Neither the name of the University nor of the Laboratory may be used 188cf6c252SPaul Traina * to endorse or promote products derived from this software without 198cf6c252SPaul Traina * specific prior written permission. 208cf6c252SPaul Traina * 218cf6c252SPaul Traina * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 228cf6c252SPaul Traina * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 238cf6c252SPaul Traina * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 248cf6c252SPaul Traina * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 258cf6c252SPaul Traina * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 268cf6c252SPaul Traina * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 278cf6c252SPaul Traina * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 288cf6c252SPaul Traina * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 298cf6c252SPaul Traina * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 308cf6c252SPaul Traina * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 318cf6c252SPaul Traina * SUCH DAMAGE. 328cf6c252SPaul Traina */ 338cf6c252SPaul Traina 348cf6c252SPaul Traina #ifndef lint 35feb4ecdbSBruce M Simpson static const char rcsid[] _U_ = 365d18909fSSam Leffler "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.88.2.8 2005/08/13 22:29:46 hannes Exp $ (LBL)"; 37dc2c7305SBill Fenner #endif 38dc2c7305SBill Fenner 39dc2c7305SBill Fenner #ifdef HAVE_CONFIG_H 40dc2c7305SBill Fenner #include "config.h" 418cf6c252SPaul Traina #endif 428cf6c252SPaul Traina 43feb4ecdbSBruce M Simpson #ifdef WIN32 44feb4ecdbSBruce M Simpson #include <pcap-stdinc.h> 45feb4ecdbSBruce M Simpson #else /* WIN32 */ 468cf6c252SPaul Traina #include <sys/types.h> 47feb4ecdbSBruce M Simpson #endif /* WIN32 */ 488cf6c252SPaul Traina 498cf6c252SPaul Traina #include <stdio.h> 508cf6c252SPaul Traina #include <stdlib.h> 518cf6c252SPaul Traina #include <string.h> 5204fb2745SSam Leffler #if !defined(_MSC_VER) && !defined(__BORLANDC__) 538cf6c252SPaul Traina #include <unistd.h> 54feb4ecdbSBruce M Simpson #endif 550a94d38fSBill Fenner #include <fcntl.h> 560a94d38fSBill Fenner #include <errno.h> 578cf6c252SPaul Traina 588cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H 598cf6c252SPaul Traina #include "os-proto.h" 608cf6c252SPaul Traina #endif 618cf6c252SPaul Traina 6204fb2745SSam Leffler #ifdef MSDOS 6304fb2745SSam Leffler #include "pcap-dos.h" 6404fb2745SSam Leffler #endif 6504fb2745SSam Leffler 668cf6c252SPaul Traina #include "pcap-int.h" 678cf6c252SPaul Traina 68feb4ecdbSBruce M Simpson #ifdef HAVE_DAG_API 69feb4ecdbSBruce M Simpson #include <dagnew.h> 70feb4ecdbSBruce M Simpson #include <dagapi.h> 71feb4ecdbSBruce M Simpson #endif 72feb4ecdbSBruce M Simpson 738cf6c252SPaul Traina int 748cf6c252SPaul Traina pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 758cf6c252SPaul Traina { 768cf6c252SPaul Traina 77feb4ecdbSBruce M Simpson return p->read_op(p, cnt, callback, user); 78feb4ecdbSBruce M Simpson } 79feb4ecdbSBruce M Simpson 80feb4ecdbSBruce M Simpson /* 81feb4ecdbSBruce M Simpson * XXX - is this necessary? 82feb4ecdbSBruce M Simpson */ 83feb4ecdbSBruce M Simpson int 84feb4ecdbSBruce M Simpson pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 85feb4ecdbSBruce M Simpson { 86feb4ecdbSBruce M Simpson 87feb4ecdbSBruce M Simpson return p->read_op(p, cnt, callback, user); 888cf6c252SPaul Traina } 898cf6c252SPaul Traina 908cf6c252SPaul Traina int 918cf6c252SPaul Traina pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 928cf6c252SPaul Traina { 93a4b5b39fSBill Fenner register int n; 94a4b5b39fSBill Fenner 958cf6c252SPaul Traina for (;;) { 96feb4ecdbSBruce M Simpson if (p->sf.rfile != NULL) { 97feb4ecdbSBruce M Simpson /* 98feb4ecdbSBruce M Simpson * 0 means EOF, so don't loop if we get 0. 99feb4ecdbSBruce M Simpson */ 100a4b5b39fSBill Fenner n = pcap_offline_read(p, cnt, callback, user); 101feb4ecdbSBruce M Simpson } else { 102a4b5b39fSBill Fenner /* 103a4b5b39fSBill Fenner * XXX keep reading until we get something 104a4b5b39fSBill Fenner * (or an error occurs) 105a4b5b39fSBill Fenner */ 106a4b5b39fSBill Fenner do { 107feb4ecdbSBruce M Simpson n = p->read_op(p, cnt, callback, user); 108a4b5b39fSBill Fenner } while (n == 0); 109a4b5b39fSBill Fenner } 1108cf6c252SPaul Traina if (n <= 0) 1118cf6c252SPaul Traina return (n); 1128cf6c252SPaul Traina if (cnt > 0) { 1138cf6c252SPaul Traina cnt -= n; 1148cf6c252SPaul Traina if (cnt <= 0) 1158cf6c252SPaul Traina return (0); 1168cf6c252SPaul Traina } 1178cf6c252SPaul Traina } 1188cf6c252SPaul Traina } 1198cf6c252SPaul Traina 1208cf6c252SPaul Traina struct singleton { 1218cf6c252SPaul Traina struct pcap_pkthdr *hdr; 1228cf6c252SPaul Traina const u_char *pkt; 1238cf6c252SPaul Traina }; 1248cf6c252SPaul Traina 1258cf6c252SPaul Traina 1268cf6c252SPaul Traina static void 1278cf6c252SPaul Traina pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt) 1288cf6c252SPaul Traina { 1298cf6c252SPaul Traina struct singleton *sp = (struct singleton *)userData; 1308cf6c252SPaul Traina *sp->hdr = *h; 1318cf6c252SPaul Traina sp->pkt = pkt; 1328cf6c252SPaul Traina } 1338cf6c252SPaul Traina 1348cf6c252SPaul Traina const u_char * 1358cf6c252SPaul Traina pcap_next(pcap_t *p, struct pcap_pkthdr *h) 1368cf6c252SPaul Traina { 1378cf6c252SPaul Traina struct singleton s; 1388cf6c252SPaul Traina 1398cf6c252SPaul Traina s.hdr = h; 1408cf6c252SPaul Traina if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0) 1418cf6c252SPaul Traina return (0); 1428cf6c252SPaul Traina return (s.pkt); 1438cf6c252SPaul Traina } 1448cf6c252SPaul Traina 145feb4ecdbSBruce M Simpson struct pkt_for_fakecallback { 146feb4ecdbSBruce M Simpson struct pcap_pkthdr *hdr; 147feb4ecdbSBruce M Simpson const u_char **pkt; 148feb4ecdbSBruce M Simpson }; 149feb4ecdbSBruce M Simpson 150feb4ecdbSBruce M Simpson static void 151feb4ecdbSBruce M Simpson pcap_fakecallback(u_char *userData, const struct pcap_pkthdr *h, 152feb4ecdbSBruce M Simpson const u_char *pkt) 153feb4ecdbSBruce M Simpson { 154feb4ecdbSBruce M Simpson struct pkt_for_fakecallback *sp = (struct pkt_for_fakecallback *)userData; 155feb4ecdbSBruce M Simpson 156feb4ecdbSBruce M Simpson *sp->hdr = *h; 157feb4ecdbSBruce M Simpson *sp->pkt = pkt; 158feb4ecdbSBruce M Simpson } 159feb4ecdbSBruce M Simpson 160feb4ecdbSBruce M Simpson int 161feb4ecdbSBruce M Simpson pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, 162feb4ecdbSBruce M Simpson const u_char **pkt_data) 163feb4ecdbSBruce M Simpson { 164feb4ecdbSBruce M Simpson struct pkt_for_fakecallback s; 165feb4ecdbSBruce M Simpson 166feb4ecdbSBruce M Simpson s.hdr = &p->pcap_header; 167feb4ecdbSBruce M Simpson s.pkt = pkt_data; 168feb4ecdbSBruce M Simpson 169feb4ecdbSBruce M Simpson /* Saves a pointer to the packet headers */ 170feb4ecdbSBruce M Simpson *pkt_header= &p->pcap_header; 171feb4ecdbSBruce M Simpson 172feb4ecdbSBruce M Simpson if (p->sf.rfile != NULL) { 173feb4ecdbSBruce M Simpson int status; 174feb4ecdbSBruce M Simpson 175feb4ecdbSBruce M Simpson /* We are on an offline capture */ 176feb4ecdbSBruce M Simpson status = pcap_offline_read(p, 1, pcap_fakecallback, 177feb4ecdbSBruce M Simpson (u_char *)&s); 178feb4ecdbSBruce M Simpson 179feb4ecdbSBruce M Simpson /* 180feb4ecdbSBruce M Simpson * Return codes for pcap_offline_read() are: 181feb4ecdbSBruce M Simpson * - 0: EOF 182feb4ecdbSBruce M Simpson * - -1: error 183feb4ecdbSBruce M Simpson * - >1: OK 184feb4ecdbSBruce M Simpson * The first one ('0') conflicts with the return code of 185feb4ecdbSBruce M Simpson * 0 from pcap_read() meaning "no packets arrived before 186feb4ecdbSBruce M Simpson * the timeout expired", so we map it to -2 so you can 187feb4ecdbSBruce M Simpson * distinguish between an EOF from a savefile and a 188feb4ecdbSBruce M Simpson * "no packets arrived before the timeout expired, try 189feb4ecdbSBruce M Simpson * again" from a live capture. 190feb4ecdbSBruce M Simpson */ 191feb4ecdbSBruce M Simpson if (status == 0) 192feb4ecdbSBruce M Simpson return (-2); 193feb4ecdbSBruce M Simpson else 194feb4ecdbSBruce M Simpson return (status); 195feb4ecdbSBruce M Simpson } 196feb4ecdbSBruce M Simpson 197feb4ecdbSBruce M Simpson /* 198feb4ecdbSBruce M Simpson * Return codes for pcap_read() are: 199feb4ecdbSBruce M Simpson * - 0: timeout 200feb4ecdbSBruce M Simpson * - -1: error 201feb4ecdbSBruce M Simpson * - -2: loop was broken out of with pcap_breakloop() 202feb4ecdbSBruce M Simpson * - >1: OK 203feb4ecdbSBruce M Simpson * The first one ('0') conflicts with the return code of 0 from 204feb4ecdbSBruce M Simpson * pcap_offline_read() meaning "end of file". 205feb4ecdbSBruce M Simpson */ 206feb4ecdbSBruce M Simpson return (p->read_op(p, 1, pcap_fakecallback, (u_char *)&s)); 207feb4ecdbSBruce M Simpson } 208feb4ecdbSBruce M Simpson 209feb4ecdbSBruce M Simpson /* 210feb4ecdbSBruce M Simpson * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate. 211feb4ecdbSBruce M Simpson */ 212feb4ecdbSBruce M Simpson void 213feb4ecdbSBruce M Simpson pcap_breakloop(pcap_t *p) 214feb4ecdbSBruce M Simpson { 215feb4ecdbSBruce M Simpson p->break_loop = 1; 216feb4ecdbSBruce M Simpson } 217feb4ecdbSBruce M Simpson 2188cf6c252SPaul Traina int 2198cf6c252SPaul Traina pcap_datalink(pcap_t *p) 2208cf6c252SPaul Traina { 2218cf6c252SPaul Traina return (p->linktype); 2228cf6c252SPaul Traina } 2238cf6c252SPaul Traina 2248cf6c252SPaul Traina int 22509f33d61SBill Fenner pcap_list_datalinks(pcap_t *p, int **dlt_buffer) 22609f33d61SBill Fenner { 227feb4ecdbSBruce M Simpson if (p->dlt_count == 0) { 228feb4ecdbSBruce M Simpson /* 229feb4ecdbSBruce M Simpson * We couldn't fetch the list of DLTs, which means 230feb4ecdbSBruce M Simpson * this platform doesn't support changing the 231feb4ecdbSBruce M Simpson * DLT for an interface. Return a list of DLTs 232feb4ecdbSBruce M Simpson * containing only the DLT this device supports. 233feb4ecdbSBruce M Simpson */ 234feb4ecdbSBruce M Simpson *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer)); 235feb4ecdbSBruce M Simpson if (*dlt_buffer == NULL) { 236feb4ecdbSBruce M Simpson (void)snprintf(p->errbuf, sizeof(p->errbuf), 237feb4ecdbSBruce M Simpson "malloc: %s", pcap_strerror(errno)); 238feb4ecdbSBruce M Simpson return (-1); 23909f33d61SBill Fenner } 240feb4ecdbSBruce M Simpson **dlt_buffer = p->linktype; 241feb4ecdbSBruce M Simpson return (1); 242feb4ecdbSBruce M Simpson } else { 24309f33d61SBill Fenner *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer) * p->dlt_count); 24409f33d61SBill Fenner if (*dlt_buffer == NULL) { 245feb4ecdbSBruce M Simpson (void)snprintf(p->errbuf, sizeof(p->errbuf), 246feb4ecdbSBruce M Simpson "malloc: %s", pcap_strerror(errno)); 247feb4ecdbSBruce M Simpson return (-1); 24809f33d61SBill Fenner } 24909f33d61SBill Fenner (void)memcpy(*dlt_buffer, p->dlt_list, 25009f33d61SBill Fenner sizeof(**dlt_buffer) * p->dlt_count); 25109f33d61SBill Fenner return (p->dlt_count); 25209f33d61SBill Fenner } 253feb4ecdbSBruce M Simpson } 254feb4ecdbSBruce M Simpson 255feb4ecdbSBruce M Simpson int 256feb4ecdbSBruce M Simpson pcap_set_datalink(pcap_t *p, int dlt) 257feb4ecdbSBruce M Simpson { 258feb4ecdbSBruce M Simpson int i; 259feb4ecdbSBruce M Simpson const char *dlt_name; 260feb4ecdbSBruce M Simpson 261feb4ecdbSBruce M Simpson if (p->dlt_count == 0 || p->set_datalink_op == NULL) { 262feb4ecdbSBruce M Simpson /* 263feb4ecdbSBruce M Simpson * We couldn't fetch the list of DLTs, or we don't 264feb4ecdbSBruce M Simpson * have a "set datalink" operation, which means 265feb4ecdbSBruce M Simpson * this platform doesn't support changing the 266feb4ecdbSBruce M Simpson * DLT for an interface. Check whether the new 267feb4ecdbSBruce M Simpson * DLT is the one this interface supports. 268feb4ecdbSBruce M Simpson */ 269feb4ecdbSBruce M Simpson if (p->linktype != dlt) 270feb4ecdbSBruce M Simpson goto unsupported; 271feb4ecdbSBruce M Simpson 272feb4ecdbSBruce M Simpson /* 273feb4ecdbSBruce M Simpson * It is, so there's nothing we need to do here. 274feb4ecdbSBruce M Simpson */ 275feb4ecdbSBruce M Simpson return (0); 276feb4ecdbSBruce M Simpson } 277feb4ecdbSBruce M Simpson for (i = 0; i < p->dlt_count; i++) 278feb4ecdbSBruce M Simpson if (p->dlt_list[i] == dlt) 279feb4ecdbSBruce M Simpson break; 280feb4ecdbSBruce M Simpson if (i >= p->dlt_count) 281feb4ecdbSBruce M Simpson goto unsupported; 28204fb2745SSam Leffler if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB && 28304fb2745SSam Leffler dlt == DLT_DOCSIS) { 28404fb2745SSam Leffler /* 28504fb2745SSam Leffler * This is presumably an Ethernet device, as the first 28604fb2745SSam Leffler * link-layer type it offers is DLT_EN10MB, and the only 28704fb2745SSam Leffler * other type it offers is DLT_DOCSIS. That means that 28804fb2745SSam Leffler * we can't tell the driver to supply DOCSIS link-layer 28904fb2745SSam Leffler * headers - we're just pretending that's what we're 29004fb2745SSam Leffler * getting, as, presumably, we're capturing on a dedicated 29104fb2745SSam Leffler * link to a Cisco Cable Modem Termination System, and 29204fb2745SSam Leffler * it's putting raw DOCSIS frames on the wire inside low-level 29304fb2745SSam Leffler * Ethernet framing. 29404fb2745SSam Leffler */ 29504fb2745SSam Leffler p->linktype = dlt; 29604fb2745SSam Leffler return (0); 29704fb2745SSam Leffler } 298feb4ecdbSBruce M Simpson if (p->set_datalink_op(p, dlt) == -1) 299feb4ecdbSBruce M Simpson return (-1); 300feb4ecdbSBruce M Simpson p->linktype = dlt; 301feb4ecdbSBruce M Simpson return (0); 302feb4ecdbSBruce M Simpson 303feb4ecdbSBruce M Simpson unsupported: 304feb4ecdbSBruce M Simpson dlt_name = pcap_datalink_val_to_name(dlt); 305feb4ecdbSBruce M Simpson if (dlt_name != NULL) { 306feb4ecdbSBruce M Simpson (void) snprintf(p->errbuf, sizeof(p->errbuf), 307feb4ecdbSBruce M Simpson "%s is not one of the DLTs supported by this device", 308feb4ecdbSBruce M Simpson dlt_name); 309feb4ecdbSBruce M Simpson } else { 310feb4ecdbSBruce M Simpson (void) snprintf(p->errbuf, sizeof(p->errbuf), 311feb4ecdbSBruce M Simpson "DLT %d is not one of the DLTs supported by this device", 312feb4ecdbSBruce M Simpson dlt); 313feb4ecdbSBruce M Simpson } 314feb4ecdbSBruce M Simpson return (-1); 315feb4ecdbSBruce M Simpson } 316feb4ecdbSBruce M Simpson 317feb4ecdbSBruce M Simpson struct dlt_choice { 318feb4ecdbSBruce M Simpson const char *name; 319feb4ecdbSBruce M Simpson const char *description; 320feb4ecdbSBruce M Simpson int dlt; 321feb4ecdbSBruce M Simpson }; 322feb4ecdbSBruce M Simpson 323feb4ecdbSBruce M Simpson #define DLT_CHOICE(code, description) { #code, description, code } 324feb4ecdbSBruce M Simpson #define DLT_CHOICE_SENTINEL { NULL, NULL, 0 } 325feb4ecdbSBruce M Simpson 326feb4ecdbSBruce M Simpson static struct dlt_choice dlt_choices[] = { 327feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_NULL, "BSD loopback"), 328feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_EN10MB, "Ethernet"), 329feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_IEEE802, "Token ring"), 330feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_ARCNET, "ARCNET"), 331feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_SLIP, "SLIP"), 332feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_PPP, "PPP"), 333feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_FDDI, "FDDI"), 334ee2dd488SSam Leffler DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"), 335feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_RAW, "Raw IP"), 336feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"), 337feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"), 338feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"), 339feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"), 340feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"), 341feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"), 342feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_IEEE802_11, "802.11"), 343feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_FRELAY, "Frame Relay"), 344feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"), 345feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"), 346feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"), 347feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_LTALK, "Localtalk"), 348feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"), 349feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"), 350feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"), 351feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"), 352feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus BSD radio information header"), 353feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"), 354feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"), 35504fb2745SSam Leffler DLT_CHOICE(DLT_DOCSIS, "DOCSIS"), 356feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"), 357feb4ecdbSBruce M Simpson DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"), 35804fb2745SSam Leffler DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"), 35904fb2745SSam Leffler DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"), 36004fb2745SSam Leffler DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"), 36104fb2745SSam Leffler DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"), 36204fb2745SSam Leffler DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"), 36304fb2745SSam Leffler DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"), 36404fb2745SSam Leffler DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"), 36504fb2745SSam Leffler DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"), 36604fb2745SSam Leffler DLT_CHOICE(DLT_GPF_T, "GPF-T"), 36704fb2745SSam Leffler DLT_CHOICE(DLT_GPF_F, "GPF-F"), 36804fb2745SSam Leffler DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"), 36904fb2745SSam Leffler DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"), 37004fb2745SSam Leffler DLT_CHOICE(DLT_ERF_ETH, "Ethernet with Endace ERF header"), 37104fb2745SSam Leffler DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"), 372ee2dd488SSam Leffler DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"), 373ee2dd488SSam Leffler DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"), 374ee2dd488SSam Leffler DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"), 375ee2dd488SSam Leffler DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"), 3765d18909fSSam Leffler DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"), 3775d18909fSSam Leffler DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"), 3785d18909fSSam Leffler DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"), 3795d18909fSSam Leffler DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"), 3805d18909fSSam Leffler DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"), 381feb4ecdbSBruce M Simpson DLT_CHOICE_SENTINEL 382feb4ecdbSBruce M Simpson }; 383feb4ecdbSBruce M Simpson 384feb4ecdbSBruce M Simpson /* 385feb4ecdbSBruce M Simpson * This array is designed for mapping upper and lower case letter 386feb4ecdbSBruce M Simpson * together for a case independent comparison. The mappings are 387feb4ecdbSBruce M Simpson * based upon ascii character sequences. 388feb4ecdbSBruce M Simpson */ 389feb4ecdbSBruce M Simpson static const u_char charmap[] = { 390feb4ecdbSBruce M Simpson (u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003', 391feb4ecdbSBruce M Simpson (u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007', 392feb4ecdbSBruce M Simpson (u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013', 393feb4ecdbSBruce M Simpson (u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017', 394feb4ecdbSBruce M Simpson (u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023', 395feb4ecdbSBruce M Simpson (u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027', 396feb4ecdbSBruce M Simpson (u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033', 397feb4ecdbSBruce M Simpson (u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037', 398feb4ecdbSBruce M Simpson (u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043', 399feb4ecdbSBruce M Simpson (u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047', 400feb4ecdbSBruce M Simpson (u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053', 401feb4ecdbSBruce M Simpson (u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057', 402feb4ecdbSBruce M Simpson (u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063', 403feb4ecdbSBruce M Simpson (u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067', 404feb4ecdbSBruce M Simpson (u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073', 405feb4ecdbSBruce M Simpson (u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077', 406feb4ecdbSBruce M Simpson (u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143', 407feb4ecdbSBruce M Simpson (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147', 408feb4ecdbSBruce M Simpson (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153', 409feb4ecdbSBruce M Simpson (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157', 410feb4ecdbSBruce M Simpson (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163', 411feb4ecdbSBruce M Simpson (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167', 412feb4ecdbSBruce M Simpson (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133', 413feb4ecdbSBruce M Simpson (u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137', 414feb4ecdbSBruce M Simpson (u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143', 415feb4ecdbSBruce M Simpson (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147', 416feb4ecdbSBruce M Simpson (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153', 417feb4ecdbSBruce M Simpson (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157', 418feb4ecdbSBruce M Simpson (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163', 419feb4ecdbSBruce M Simpson (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167', 420feb4ecdbSBruce M Simpson (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173', 421feb4ecdbSBruce M Simpson (u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177', 422feb4ecdbSBruce M Simpson (u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203', 423feb4ecdbSBruce M Simpson (u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207', 424feb4ecdbSBruce M Simpson (u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213', 425feb4ecdbSBruce M Simpson (u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217', 426feb4ecdbSBruce M Simpson (u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223', 427feb4ecdbSBruce M Simpson (u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227', 428feb4ecdbSBruce M Simpson (u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233', 429feb4ecdbSBruce M Simpson (u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237', 430feb4ecdbSBruce M Simpson (u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243', 431feb4ecdbSBruce M Simpson (u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247', 432feb4ecdbSBruce M Simpson (u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253', 433feb4ecdbSBruce M Simpson (u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257', 434feb4ecdbSBruce M Simpson (u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263', 435feb4ecdbSBruce M Simpson (u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267', 436feb4ecdbSBruce M Simpson (u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273', 437feb4ecdbSBruce M Simpson (u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277', 438feb4ecdbSBruce M Simpson (u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343', 439feb4ecdbSBruce M Simpson (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347', 440feb4ecdbSBruce M Simpson (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353', 441feb4ecdbSBruce M Simpson (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357', 442feb4ecdbSBruce M Simpson (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363', 443feb4ecdbSBruce M Simpson (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367', 444feb4ecdbSBruce M Simpson (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333', 445feb4ecdbSBruce M Simpson (u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337', 446feb4ecdbSBruce M Simpson (u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343', 447feb4ecdbSBruce M Simpson (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347', 448feb4ecdbSBruce M Simpson (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353', 449feb4ecdbSBruce M Simpson (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357', 450feb4ecdbSBruce M Simpson (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363', 451feb4ecdbSBruce M Simpson (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367', 452feb4ecdbSBruce M Simpson (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373', 453feb4ecdbSBruce M Simpson (u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377', 454feb4ecdbSBruce M Simpson }; 455feb4ecdbSBruce M Simpson 456feb4ecdbSBruce M Simpson int 457feb4ecdbSBruce M Simpson pcap_strcasecmp(const char *s1, const char *s2) 458feb4ecdbSBruce M Simpson { 459feb4ecdbSBruce M Simpson register const u_char *cm = charmap, 460feb4ecdbSBruce M Simpson *us1 = (u_char *)s1, 461feb4ecdbSBruce M Simpson *us2 = (u_char *)s2; 462feb4ecdbSBruce M Simpson 463feb4ecdbSBruce M Simpson while (cm[*us1] == cm[*us2++]) 464feb4ecdbSBruce M Simpson if (*us1++ == '\0') 465feb4ecdbSBruce M Simpson return(0); 466feb4ecdbSBruce M Simpson return (cm[*us1] - cm[*--us2]); 467feb4ecdbSBruce M Simpson } 468feb4ecdbSBruce M Simpson 469feb4ecdbSBruce M Simpson int 470feb4ecdbSBruce M Simpson pcap_datalink_name_to_val(const char *name) 471feb4ecdbSBruce M Simpson { 472feb4ecdbSBruce M Simpson int i; 473feb4ecdbSBruce M Simpson 474feb4ecdbSBruce M Simpson for (i = 0; dlt_choices[i].name != NULL; i++) { 475feb4ecdbSBruce M Simpson if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1, 476feb4ecdbSBruce M Simpson name) == 0) 477feb4ecdbSBruce M Simpson return (dlt_choices[i].dlt); 478feb4ecdbSBruce M Simpson } 479feb4ecdbSBruce M Simpson return (-1); 480feb4ecdbSBruce M Simpson } 481feb4ecdbSBruce M Simpson 482feb4ecdbSBruce M Simpson const char * 483feb4ecdbSBruce M Simpson pcap_datalink_val_to_name(int dlt) 484feb4ecdbSBruce M Simpson { 485feb4ecdbSBruce M Simpson int i; 486feb4ecdbSBruce M Simpson 487feb4ecdbSBruce M Simpson for (i = 0; dlt_choices[i].name != NULL; i++) { 488feb4ecdbSBruce M Simpson if (dlt_choices[i].dlt == dlt) 489feb4ecdbSBruce M Simpson return (dlt_choices[i].name + sizeof("DLT_") - 1); 490feb4ecdbSBruce M Simpson } 491feb4ecdbSBruce M Simpson return (NULL); 492feb4ecdbSBruce M Simpson } 493feb4ecdbSBruce M Simpson 494feb4ecdbSBruce M Simpson const char * 495feb4ecdbSBruce M Simpson pcap_datalink_val_to_description(int dlt) 496feb4ecdbSBruce M Simpson { 497feb4ecdbSBruce M Simpson int i; 498feb4ecdbSBruce M Simpson 499feb4ecdbSBruce M Simpson for (i = 0; dlt_choices[i].name != NULL; i++) { 500feb4ecdbSBruce M Simpson if (dlt_choices[i].dlt == dlt) 501feb4ecdbSBruce M Simpson return (dlt_choices[i].description); 502feb4ecdbSBruce M Simpson } 503feb4ecdbSBruce M Simpson return (NULL); 504feb4ecdbSBruce M Simpson } 50509f33d61SBill Fenner 50609f33d61SBill Fenner int 5078cf6c252SPaul Traina pcap_snapshot(pcap_t *p) 5088cf6c252SPaul Traina { 5098cf6c252SPaul Traina return (p->snapshot); 5108cf6c252SPaul Traina } 5118cf6c252SPaul Traina 5128cf6c252SPaul Traina int 5138cf6c252SPaul Traina pcap_is_swapped(pcap_t *p) 5148cf6c252SPaul Traina { 5158cf6c252SPaul Traina return (p->sf.swapped); 5168cf6c252SPaul Traina } 5178cf6c252SPaul Traina 5188cf6c252SPaul Traina int 5198cf6c252SPaul Traina pcap_major_version(pcap_t *p) 5208cf6c252SPaul Traina { 5218cf6c252SPaul Traina return (p->sf.version_major); 5228cf6c252SPaul Traina } 5238cf6c252SPaul Traina 5248cf6c252SPaul Traina int 5258cf6c252SPaul Traina pcap_minor_version(pcap_t *p) 5268cf6c252SPaul Traina { 5278cf6c252SPaul Traina return (p->sf.version_minor); 5288cf6c252SPaul Traina } 5298cf6c252SPaul Traina 5308cf6c252SPaul Traina FILE * 5318cf6c252SPaul Traina pcap_file(pcap_t *p) 5328cf6c252SPaul Traina { 5338cf6c252SPaul Traina return (p->sf.rfile); 5348cf6c252SPaul Traina } 5358cf6c252SPaul Traina 5368cf6c252SPaul Traina int 5378cf6c252SPaul Traina pcap_fileno(pcap_t *p) 5388cf6c252SPaul Traina { 539feb4ecdbSBruce M Simpson #ifndef WIN32 5408cf6c252SPaul Traina return (p->fd); 541feb4ecdbSBruce M Simpson #else 542feb4ecdbSBruce M Simpson if (p->adapter != NULL) 543feb4ecdbSBruce M Simpson return ((int)(DWORD)p->adapter->hFile); 544feb4ecdbSBruce M Simpson else 545feb4ecdbSBruce M Simpson return (-1); 546feb4ecdbSBruce M Simpson #endif 5478cf6c252SPaul Traina } 5488cf6c252SPaul Traina 54904fb2745SSam Leffler #if !defined(WIN32) && !defined(MSDOS) 550feb4ecdbSBruce M Simpson int 551feb4ecdbSBruce M Simpson pcap_get_selectable_fd(pcap_t *p) 552feb4ecdbSBruce M Simpson { 553feb4ecdbSBruce M Simpson return (p->selectable_fd); 554feb4ecdbSBruce M Simpson } 555feb4ecdbSBruce M Simpson #endif 556feb4ecdbSBruce M Simpson 5578cf6c252SPaul Traina void 5588cf6c252SPaul Traina pcap_perror(pcap_t *p, char *prefix) 5598cf6c252SPaul Traina { 5608cf6c252SPaul Traina fprintf(stderr, "%s: %s\n", prefix, p->errbuf); 5618cf6c252SPaul Traina } 5628cf6c252SPaul Traina 5638cf6c252SPaul Traina char * 5648cf6c252SPaul Traina pcap_geterr(pcap_t *p) 5658cf6c252SPaul Traina { 5668cf6c252SPaul Traina return (p->errbuf); 5678cf6c252SPaul Traina } 5688cf6c252SPaul Traina 5690a94d38fSBill Fenner int 5700a94d38fSBill Fenner pcap_getnonblock(pcap_t *p, char *errbuf) 5710a94d38fSBill Fenner { 572feb4ecdbSBruce M Simpson return p->getnonblock_op(p, errbuf); 573feb4ecdbSBruce M Simpson } 574feb4ecdbSBruce M Simpson 575feb4ecdbSBruce M Simpson /* 576feb4ecdbSBruce M Simpson * Get the current non-blocking mode setting, under the assumption that 577feb4ecdbSBruce M Simpson * it's just the standard POSIX non-blocking flag. 578feb4ecdbSBruce M Simpson * 579feb4ecdbSBruce M Simpson * We don't look at "p->nonblock", in case somebody tweaked the FD 580feb4ecdbSBruce M Simpson * directly. 581feb4ecdbSBruce M Simpson */ 58204fb2745SSam Leffler #if !defined(WIN32) && !defined(MSDOS) 583feb4ecdbSBruce M Simpson int 584feb4ecdbSBruce M Simpson pcap_getnonblock_fd(pcap_t *p, char *errbuf) 585feb4ecdbSBruce M Simpson { 5860a94d38fSBill Fenner int fdflags; 5870a94d38fSBill Fenner 5880a94d38fSBill Fenner fdflags = fcntl(p->fd, F_GETFL, 0); 5890a94d38fSBill Fenner if (fdflags == -1) { 5900a94d38fSBill Fenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", 5910a94d38fSBill Fenner pcap_strerror(errno)); 5920a94d38fSBill Fenner return (-1); 5930a94d38fSBill Fenner } 5940a94d38fSBill Fenner if (fdflags & O_NONBLOCK) 5950a94d38fSBill Fenner return (1); 5960a94d38fSBill Fenner else 5970a94d38fSBill Fenner return (0); 5980a94d38fSBill Fenner } 599feb4ecdbSBruce M Simpson #endif 6000a94d38fSBill Fenner 6010a94d38fSBill Fenner int 6020a94d38fSBill Fenner pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) 6030a94d38fSBill Fenner { 604feb4ecdbSBruce M Simpson return p->setnonblock_op(p, nonblock, errbuf); 605feb4ecdbSBruce M Simpson } 606feb4ecdbSBruce M Simpson 60704fb2745SSam Leffler #if !defined(WIN32) && !defined(MSDOS) 608feb4ecdbSBruce M Simpson /* 609feb4ecdbSBruce M Simpson * Set non-blocking mode, under the assumption that it's just the 610feb4ecdbSBruce M Simpson * standard POSIX non-blocking flag. (This can be called by the 611feb4ecdbSBruce M Simpson * per-platform non-blocking-mode routine if that routine also 612feb4ecdbSBruce M Simpson * needs to do some additional work.) 613feb4ecdbSBruce M Simpson */ 614feb4ecdbSBruce M Simpson int 615feb4ecdbSBruce M Simpson pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf) 616feb4ecdbSBruce M Simpson { 6170a94d38fSBill Fenner int fdflags; 6180a94d38fSBill Fenner 6190a94d38fSBill Fenner fdflags = fcntl(p->fd, F_GETFL, 0); 6200a94d38fSBill Fenner if (fdflags == -1) { 6210a94d38fSBill Fenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", 6220a94d38fSBill Fenner pcap_strerror(errno)); 6230a94d38fSBill Fenner return (-1); 6240a94d38fSBill Fenner } 6250a94d38fSBill Fenner if (nonblock) 6260a94d38fSBill Fenner fdflags |= O_NONBLOCK; 6270a94d38fSBill Fenner else 6280a94d38fSBill Fenner fdflags &= ~O_NONBLOCK; 6290a94d38fSBill Fenner if (fcntl(p->fd, F_SETFL, fdflags) == -1) { 6300a94d38fSBill Fenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", 6310a94d38fSBill Fenner pcap_strerror(errno)); 6320a94d38fSBill Fenner return (-1); 6330a94d38fSBill Fenner } 6340a94d38fSBill Fenner return (0); 6350a94d38fSBill Fenner } 636feb4ecdbSBruce M Simpson #endif 637feb4ecdbSBruce M Simpson 638feb4ecdbSBruce M Simpson #ifdef WIN32 639feb4ecdbSBruce M Simpson /* 640feb4ecdbSBruce M Simpson * Generate a string for the last Win32-specific error (i.e. an error generated when 641feb4ecdbSBruce M Simpson * calling a Win32 API). 642feb4ecdbSBruce M Simpson * For errors occurred during standard C calls, we still use pcap_strerror() 643feb4ecdbSBruce M Simpson */ 644feb4ecdbSBruce M Simpson char * 645feb4ecdbSBruce M Simpson pcap_win32strerror(void) 646feb4ecdbSBruce M Simpson { 647feb4ecdbSBruce M Simpson DWORD error; 648feb4ecdbSBruce M Simpson static char errbuf[PCAP_ERRBUF_SIZE+1]; 649feb4ecdbSBruce M Simpson int errlen; 65004fb2745SSam Leffler char *p; 651feb4ecdbSBruce M Simpson 652feb4ecdbSBruce M Simpson error = GetLastError(); 653feb4ecdbSBruce M Simpson FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf, 654feb4ecdbSBruce M Simpson PCAP_ERRBUF_SIZE, NULL); 655feb4ecdbSBruce M Simpson 656feb4ecdbSBruce M Simpson /* 657feb4ecdbSBruce M Simpson * "FormatMessage()" "helpfully" sticks CR/LF at the end of the 658feb4ecdbSBruce M Simpson * message. Get rid of it. 659feb4ecdbSBruce M Simpson */ 660feb4ecdbSBruce M Simpson errlen = strlen(errbuf); 661feb4ecdbSBruce M Simpson if (errlen >= 2) { 662feb4ecdbSBruce M Simpson errbuf[errlen - 1] = '\0'; 663feb4ecdbSBruce M Simpson errbuf[errlen - 2] = '\0'; 664feb4ecdbSBruce M Simpson } 66504fb2745SSam Leffler p = strchr(errbuf, '\0'); 66604fb2745SSam Leffler snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error); 667feb4ecdbSBruce M Simpson return (errbuf); 668feb4ecdbSBruce M Simpson } 669feb4ecdbSBruce M Simpson #endif 6700a94d38fSBill Fenner 6710a94d38fSBill Fenner /* 6728cf6c252SPaul Traina * Not all systems have strerror(). 6738cf6c252SPaul Traina */ 6748cf6c252SPaul Traina char * 6758cf6c252SPaul Traina pcap_strerror(int errnum) 6768cf6c252SPaul Traina { 6778cf6c252SPaul Traina #ifdef HAVE_STRERROR 6788cf6c252SPaul Traina return (strerror(errnum)); 6798cf6c252SPaul Traina #else 6808cf6c252SPaul Traina extern int sys_nerr; 6818cf6c252SPaul Traina extern const char *const sys_errlist[]; 6828cf6c252SPaul Traina static char ebuf[20]; 6838cf6c252SPaul Traina 6848cf6c252SPaul Traina if ((unsigned int)errnum < sys_nerr) 6858cf6c252SPaul Traina return ((char *)sys_errlist[errnum]); 686dc2c7305SBill Fenner (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); 6878cf6c252SPaul Traina return(ebuf); 6888cf6c252SPaul Traina #endif 6898cf6c252SPaul Traina } 6908cf6c252SPaul Traina 691feb4ecdbSBruce M Simpson int 692feb4ecdbSBruce M Simpson pcap_setfilter(pcap_t *p, struct bpf_program *fp) 693feb4ecdbSBruce M Simpson { 694feb4ecdbSBruce M Simpson return p->setfilter_op(p, fp); 695feb4ecdbSBruce M Simpson } 696feb4ecdbSBruce M Simpson 697ee2dd488SSam Leffler /* 698ee2dd488SSam Leffler * Set direction flag, which controls whether we accept only incoming 699ee2dd488SSam Leffler * packets, only outgoing packets, or both. 700ee2dd488SSam Leffler * Note that, depending on the platform, some or all direction arguments 701ee2dd488SSam Leffler * might not be supported. 702ee2dd488SSam Leffler */ 703ee2dd488SSam Leffler int 7045d18909fSSam Leffler pcap_setdirection(pcap_t *p, pcap_direction_t d) 705ee2dd488SSam Leffler { 706ee2dd488SSam Leffler if (p->setdirection_op == NULL) { 707ee2dd488SSam Leffler snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 708ee2dd488SSam Leffler "Setting direction is not implemented on this platform"); 709ee2dd488SSam Leffler return -1; 710ee2dd488SSam Leffler } else 711ee2dd488SSam Leffler return p->setdirection_op(p, d); 712ee2dd488SSam Leffler } 713ee2dd488SSam Leffler 714feb4ecdbSBruce M Simpson int 715feb4ecdbSBruce M Simpson pcap_stats(pcap_t *p, struct pcap_stat *ps) 716feb4ecdbSBruce M Simpson { 717feb4ecdbSBruce M Simpson return p->stats_op(p, ps); 718feb4ecdbSBruce M Simpson } 719feb4ecdbSBruce M Simpson 720feb4ecdbSBruce M Simpson static int 72104fb2745SSam Leffler pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_) 722feb4ecdbSBruce M Simpson { 723feb4ecdbSBruce M Simpson snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 724feb4ecdbSBruce M Simpson "Statistics aren't available from a pcap_open_dead pcap_t"); 725feb4ecdbSBruce M Simpson return (-1); 726feb4ecdbSBruce M Simpson } 727feb4ecdbSBruce M Simpson 72804fb2745SSam Leffler void 72904fb2745SSam Leffler pcap_close_common(pcap_t *p) 73004fb2745SSam Leffler { 73104fb2745SSam Leffler if (p->buffer != NULL) 73204fb2745SSam Leffler free(p->buffer); 73304fb2745SSam Leffler #if !defined(WIN32) && !defined(MSDOS) 73404fb2745SSam Leffler if (p->fd >= 0) 73504fb2745SSam Leffler close(p->fd); 73604fb2745SSam Leffler #endif 73704fb2745SSam Leffler } 73804fb2745SSam Leffler 739feb4ecdbSBruce M Simpson static void 74004fb2745SSam Leffler pcap_close_dead(pcap_t *p _U_) 741feb4ecdbSBruce M Simpson { 742feb4ecdbSBruce M Simpson /* Nothing to do. */ 743feb4ecdbSBruce M Simpson } 744feb4ecdbSBruce M Simpson 745dc2c7305SBill Fenner pcap_t * 746dc2c7305SBill Fenner pcap_open_dead(int linktype, int snaplen) 747dc2c7305SBill Fenner { 748dc2c7305SBill Fenner pcap_t *p; 749dc2c7305SBill Fenner 750dc2c7305SBill Fenner p = malloc(sizeof(*p)); 751dc2c7305SBill Fenner if (p == NULL) 752dc2c7305SBill Fenner return NULL; 753dc2c7305SBill Fenner memset (p, 0, sizeof(*p)); 754dc2c7305SBill Fenner p->snapshot = snaplen; 755dc2c7305SBill Fenner p->linktype = linktype; 756feb4ecdbSBruce M Simpson p->stats_op = pcap_stats_dead; 757feb4ecdbSBruce M Simpson p->close_op = pcap_close_dead; 758dc2c7305SBill Fenner return p; 759dc2c7305SBill Fenner } 760dc2c7305SBill Fenner 76104fb2745SSam Leffler /* 76204fb2745SSam Leffler * API compatible with WinPcap's "send a packet" routine - returns -1 76304fb2745SSam Leffler * on error, 0 otherwise. 76404fb2745SSam Leffler * 76504fb2745SSam Leffler * XXX - what if we get a short write? 76604fb2745SSam Leffler */ 76704fb2745SSam Leffler int 76804fb2745SSam Leffler pcap_sendpacket(pcap_t *p, const u_char *buf, int size) 76904fb2745SSam Leffler { 77004fb2745SSam Leffler if (p->inject_op(p, buf, size) == -1) 77104fb2745SSam Leffler return (-1); 77204fb2745SSam Leffler return (0); 77304fb2745SSam Leffler } 77404fb2745SSam Leffler 77504fb2745SSam Leffler /* 77604fb2745SSam Leffler * API compatible with OpenBSD's "send a packet" routine - returns -1 on 77704fb2745SSam Leffler * error, number of bytes written otherwise. 77804fb2745SSam Leffler */ 77904fb2745SSam Leffler int 78004fb2745SSam Leffler pcap_inject(pcap_t *p, const void *buf, size_t size) 78104fb2745SSam Leffler { 78204fb2745SSam Leffler return (p->inject_op(p, buf, size)); 78304fb2745SSam Leffler } 78404fb2745SSam Leffler 7858cf6c252SPaul Traina void 7868cf6c252SPaul Traina pcap_close(pcap_t *p) 7878cf6c252SPaul Traina { 788feb4ecdbSBruce M Simpson p->close_op(p); 78909f33d61SBill Fenner if (p->dlt_list != NULL) 79009f33d61SBill Fenner free(p->dlt_list); 791dc2c7305SBill Fenner pcap_freecode(&p->fcode); 7928cf6c252SPaul Traina free(p); 7938cf6c252SPaul Traina } 794feb4ecdbSBruce M Simpson 795feb4ecdbSBruce M Simpson /* 796feb4ecdbSBruce M Simpson * We make the version string static, and return a pointer to it, rather 797feb4ecdbSBruce M Simpson * than exporting the version string directly. On at least some UNIXes, 798feb4ecdbSBruce M Simpson * if you import data from a shared library into an program, the data is 799feb4ecdbSBruce M Simpson * bound into the program binary, so if the string in the version of the 800feb4ecdbSBruce M Simpson * library with which the program was linked isn't the same as the 801feb4ecdbSBruce M Simpson * string in the version of the library with which the program is being 802feb4ecdbSBruce M Simpson * run, various undesirable things may happen (warnings, the string 803feb4ecdbSBruce M Simpson * being the one from the version of the library with which the program 804feb4ecdbSBruce M Simpson * was linked, or even weirder things, such as the string being the one 805feb4ecdbSBruce M Simpson * from the library but being truncated). 806feb4ecdbSBruce M Simpson */ 80704fb2745SSam Leffler #ifdef HAVE_VERSION_H 80804fb2745SSam Leffler #include "version.h" 80904fb2745SSam Leffler #else 81004fb2745SSam Leffler static const char pcap_version_string[] = "libpcap version 0.9[.x]"; 81104fb2745SSam Leffler #endif 81204fb2745SSam Leffler 813feb4ecdbSBruce M Simpson #ifdef WIN32 814feb4ecdbSBruce M Simpson /* 815feb4ecdbSBruce M Simpson * XXX - it'd be nice if we could somehow generate the WinPcap and libpcap 816feb4ecdbSBruce M Simpson * version numbers when building WinPcap. (It'd be nice to do so for 817feb4ecdbSBruce M Simpson * the packet.dll version number as well.) 818feb4ecdbSBruce M Simpson */ 81904fb2745SSam Leffler static const char wpcap_version_string[] = "3.1"; 820feb4ecdbSBruce M Simpson static const char pcap_version_string_fmt[] = 82104fb2745SSam Leffler "WinPcap version %s, based on %s"; 822feb4ecdbSBruce M Simpson static const char pcap_version_string_packet_dll_fmt[] = 82304fb2745SSam Leffler "WinPcap version %s (packet.dll version %s), based on %s"; 82404fb2745SSam Leffler static char *full_pcap_version_string; 825feb4ecdbSBruce M Simpson 826feb4ecdbSBruce M Simpson const char * 827feb4ecdbSBruce M Simpson pcap_lib_version(void) 828feb4ecdbSBruce M Simpson { 829feb4ecdbSBruce M Simpson char *packet_version_string; 83004fb2745SSam Leffler size_t full_pcap_version_string_len; 831feb4ecdbSBruce M Simpson 83204fb2745SSam Leffler if (full_pcap_version_string == NULL) { 833feb4ecdbSBruce M Simpson /* 834feb4ecdbSBruce M Simpson * Generate the version string. 835feb4ecdbSBruce M Simpson */ 836feb4ecdbSBruce M Simpson packet_version_string = PacketGetVersion(); 837feb4ecdbSBruce M Simpson if (strcmp(wpcap_version_string, packet_version_string) == 0) { 838feb4ecdbSBruce M Simpson /* 839feb4ecdbSBruce M Simpson * WinPcap version string and packet.dll version 840feb4ecdbSBruce M Simpson * string are the same; just report the WinPcap 841feb4ecdbSBruce M Simpson * version. 842feb4ecdbSBruce M Simpson */ 84304fb2745SSam Leffler full_pcap_version_string_len = 84404fb2745SSam Leffler (sizeof pcap_version_string_fmt - 4) + 84504fb2745SSam Leffler strlen(wpcap_version_string) + 84604fb2745SSam Leffler strlen(pcap_version_string); 84704fb2745SSam Leffler full_pcap_version_string = 84804fb2745SSam Leffler malloc(full_pcap_version_string_len); 84904fb2745SSam Leffler sprintf(full_pcap_version_string, 85004fb2745SSam Leffler pcap_version_string_fmt, wpcap_version_string, 85104fb2745SSam Leffler pcap_version_string); 852feb4ecdbSBruce M Simpson } else { 853feb4ecdbSBruce M Simpson /* 854feb4ecdbSBruce M Simpson * WinPcap version string and packet.dll version 855feb4ecdbSBruce M Simpson * string are different; that shouldn't be the 856feb4ecdbSBruce M Simpson * case (the two libraries should come from the 857feb4ecdbSBruce M Simpson * same version of WinPcap), so we report both 858feb4ecdbSBruce M Simpson * versions. 859feb4ecdbSBruce M Simpson */ 86004fb2745SSam Leffler full_pcap_version_string_len = 86104fb2745SSam Leffler (sizeof pcap_version_string_packet_dll_fmt - 6) + 862feb4ecdbSBruce M Simpson strlen(wpcap_version_string) + 86304fb2745SSam Leffler strlen(packet_version_string) + 86404fb2745SSam Leffler strlen(pcap_version_string); 86504fb2745SSam Leffler full_pcap_version_string = malloc(full_pcap_version_string_len); 86604fb2745SSam Leffler 86704fb2745SSam Leffler sprintf(full_pcap_version_string, 868feb4ecdbSBruce M Simpson pcap_version_string_packet_dll_fmt, 86904fb2745SSam Leffler wpcap_version_string, packet_version_string, 87004fb2745SSam Leffler pcap_version_string); 871feb4ecdbSBruce M Simpson } 872feb4ecdbSBruce M Simpson } 87304fb2745SSam Leffler return (full_pcap_version_string); 874feb4ecdbSBruce M Simpson } 87504fb2745SSam Leffler 87604fb2745SSam Leffler #elif defined(MSDOS) 87704fb2745SSam Leffler 87804fb2745SSam Leffler static char *full_pcap_version_string; 87904fb2745SSam Leffler 88004fb2745SSam Leffler const char * 88104fb2745SSam Leffler pcap_lib_version (void) 88204fb2745SSam Leffler { 88304fb2745SSam Leffler char *packet_version_string; 88404fb2745SSam Leffler size_t full_pcap_version_string_len; 88504fb2745SSam Leffler static char dospfx[] = "DOS-"; 88604fb2745SSam Leffler 88704fb2745SSam Leffler if (full_pcap_version_string == NULL) { 88804fb2745SSam Leffler /* 88904fb2745SSam Leffler * Generate the version string. 89004fb2745SSam Leffler */ 89104fb2745SSam Leffler full_pcap_version_string_len = 89204fb2745SSam Leffler sizeof dospfx + strlen(pcap_version_string); 89304fb2745SSam Leffler full_pcap_version_string = 89404fb2745SSam Leffler malloc(full_pcap_version_string_len); 89504fb2745SSam Leffler strcpy(full_pcap_version_string, dospfx); 89604fb2745SSam Leffler strcat(full_pcap_version_string, pcap_version_string); 89704fb2745SSam Leffler } 89804fb2745SSam Leffler return (full_pcap_version_string); 89904fb2745SSam Leffler } 90004fb2745SSam Leffler 90104fb2745SSam Leffler #else /* UN*X */ 902feb4ecdbSBruce M Simpson 903feb4ecdbSBruce M Simpson const char * 904feb4ecdbSBruce M Simpson pcap_lib_version(void) 905feb4ecdbSBruce M Simpson { 906feb4ecdbSBruce M Simpson return (pcap_version_string); 907feb4ecdbSBruce M Simpson } 908feb4ecdbSBruce M Simpson #endif 909