pcap.c revision 241231
184865Sobrien/* 2218822Sdim * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998 3130561Sobrien * The Regents of the University of California. All rights reserved. 484865Sobrien * 584865Sobrien * Redistribution and use in source and binary forms, with or without 6130561Sobrien * modification, are permitted provided that the following conditions 784865Sobrien * are met: 8130561Sobrien * 1. Redistributions of source code must retain the above copyright 9130561Sobrien * notice, this list of conditions and the following disclaimer. 10130561Sobrien * 2. Redistributions in binary form must reproduce the above copyright 11130561Sobrien * notice, this list of conditions and the following disclaimer in the 1284865Sobrien * documentation and/or other materials provided with the distribution. 13130561Sobrien * 3. All advertising materials mentioning features or use of this software 14130561Sobrien * must display the following acknowledgement: 15130561Sobrien * This product includes software developed by the Computer Systems 16130561Sobrien * Engineering Group at Lawrence Berkeley Laboratory. 1784865Sobrien * 4. Neither the name of the University nor of the Laboratory may be used 18130561Sobrien * to endorse or promote products derived from this software without 19130561Sobrien * specific prior written permission. 20218822Sdim * 2184865Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22218822Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2384865Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2484865Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2584865Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2684865Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2784865Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28130561Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29130561Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3084865Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31218822Sdim * SUCH DAMAGE. 32218822Sdim */ 33218822Sdim 34218822Sdim#ifndef lint 35218822Sdimstatic const char rcsid[] _U_ = 36218822Sdim "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.128 2008-12-23 20:13:29 guy Exp $ (LBL)"; 37218822Sdim#endif 38218822Sdim 39218822Sdim#ifdef HAVE_CONFIG_H 40218822Sdim#include "config.h" 41130561Sobrien#endif 4284865Sobrien 43130561Sobrien#ifdef WIN32 44130561Sobrien#include <pcap-stdinc.h> 45130561Sobrien#else /* WIN32 */ 46130561Sobrien#if HAVE_INTTYPES_H 4784865Sobrien#include <inttypes.h> 48130561Sobrien#elif HAVE_STDINT_H 49130561Sobrien#include <stdint.h> 50130561Sobrien#endif 51130561Sobrien#ifdef HAVE_SYS_BITYPES_H 52130561Sobrien#include <sys/bitypes.h> 53130561Sobrien#endif 54130561Sobrien#include <sys/types.h> 55130561Sobrien#include <sys/mman.h> 56130561Sobrien#endif /* WIN32 */ 57130561Sobrien 58130561Sobrien#include <stdio.h> 59130561Sobrien#include <stdlib.h> 60130561Sobrien#include <string.h> 61130561Sobrien#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__) 62130561Sobrien#include <unistd.h> 63130561Sobrien#endif 64130561Sobrien#include <fcntl.h> 65130561Sobrien#include <errno.h> 66130561Sobrien 67130561Sobrien#ifdef HAVE_OS_PROTO_H 68130561Sobrien#include "os-proto.h" 6984865Sobrien#endif 7084865Sobrien 7184865Sobrien#ifdef MSDOS 7284865Sobrien#include "pcap-dos.h" 7384865Sobrien#endif 7484865Sobrien 7584865Sobrien#include "pcap-int.h" 7684865Sobrien 7784865Sobrien#ifdef HAVE_DAG_API 7884865Sobrien#include <dagnew.h> 7984865Sobrien#include <dagapi.h> 8084865Sobrien#endif 8184865Sobrien 8284865Sobrienint 8384865Sobrienpcap_not_initialized(pcap_t *pcap) 8484865Sobrien{ 8584865Sobrien /* this means 'not initialized' */ 8684865Sobrien return (PCAP_ERROR_NOT_ACTIVATED); 8784865Sobrien} 88104834Sobrien 89104834Sobrien/* 90104834Sobrien * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't, 9184865Sobrien * a PCAP_ERROR value on an error. 92130561Sobrien */ 9384865Sobrienint 9484865Sobrienpcap_can_set_rfmon(pcap_t *p) 9584865Sobrien{ 9684865Sobrien return (p->can_set_rfmon_op(p)); 9784865Sobrien} 9884865Sobrien 9984865Sobrien/* 10084865Sobrien * For systems where rfmon mode is never supported. 10184865Sobrien */ 10284865Sobrienstatic int 103130561Sobrienpcap_cant_set_rfmon(pcap_t *p _U_) 104130561Sobrien{ 105130561Sobrien return (0); 10684865Sobrien} 10784865Sobrien 108130561Sobrien/* 10984865Sobrien * Sets *tstamp_typesp to point to an array 1 or more supported time stamp 11084865Sobrien * types; the return value is the number of supported time stamp types. 11184865Sobrien * The list should be freed by a call to pcap_free_tstamp_types() when 112104834Sobrien * you're done with it. 113104834Sobrien * 114104834Sobrien * A return value of 0 means "you don't get a choice of time stamp type", 11584865Sobrien * in which case *tstamp_typesp is set to null. 116130561Sobrien * 11784865Sobrien * PCAP_ERROR is returned on error. 118130561Sobrien */ 11984865Sobrienint 12084865Sobrienpcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp) 12184865Sobrien{ 12284865Sobrien if (p->tstamp_type_count == 0) { 12384865Sobrien /* 124104834Sobrien * We don't support multiple time stamp types. 125104834Sobrien */ 126104834Sobrien *tstamp_typesp = NULL; 12784865Sobrien } else { 12884865Sobrien *tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp), 12984865Sobrien p->tstamp_type_count); 13084865Sobrien if (*tstamp_typesp == NULL) { 131130561Sobrien (void)snprintf(p->errbuf, sizeof(p->errbuf), 132130561Sobrien "malloc: %s", pcap_strerror(errno)); 133218822Sdim return (PCAP_ERROR); 134218822Sdim } 135218822Sdim (void)memcpy(*tstamp_typesp, p->tstamp_type_list, 136218822Sdim sizeof(**tstamp_typesp) * p->tstamp_type_count); 137218822Sdim } 138218822Sdim return (p->tstamp_type_count); 139218822Sdim} 14084865Sobrien 14189857Sobrien/* 142130561Sobrien * In Windows, you might have a library built with one version of the 14389857Sobrien * C runtime library and an application built with another version of 14489857Sobrien * the C runtime library, which means that the library might use one 14584865Sobrien * version of malloc() and free() and the application might use another 14684865Sobrien * version of malloc() and free(). If so, that means something 14784865Sobrien * allocated by the library cannot be freed by the application, so we 14884865Sobrien * need to have a pcap_free_tstamp_types() routine to free up the list 14984865Sobrien * allocated by pcap_list_tstamp_types(), even though it's just a wrapper 150218822Sdim * around free(). 151218822Sdim */ 152218822Sdimvoid 153218822Sdimpcap_free_tstamp_types(int *tstamp_type_list) 154218822Sdim{ 155218822Sdim free(tstamp_type_list); 156218822Sdim} 15784865Sobrien 15884865Sobrien/* 15984865Sobrien * Default one-shot callback; overridden for capture types where the 16084865Sobrien * packet data cannot be guaranteed to be available after the callback 16184865Sobrien * returns, so that a copy must be made. 162130561Sobrien */ 16384865Sobrienstatic void 16484865Sobrienpcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt) 16584865Sobrien{ 16684865Sobrien struct oneshot_userdata *sp = (struct oneshot_userdata *)user; 16784865Sobrien 168130561Sobrien *sp->hdr = *h; 16984865Sobrien *sp->pkt = pkt; 17084865Sobrien} 17184865Sobrien 17284865Sobrienconst u_char * 17384865Sobrienpcap_next(pcap_t *p, struct pcap_pkthdr *h) 17489857Sobrien{ 175130561Sobrien struct oneshot_userdata s; 176130561Sobrien const u_char *pkt; 17784865Sobrien 178130561Sobrien s.hdr = h; 179130561Sobrien s.pkt = &pkt; 18084865Sobrien s.pd = p; 18184865Sobrien if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0) 182130561Sobrien return (0); 183130561Sobrien return (pkt); 184130561Sobrien} 185130561Sobrien 186218822Sdimint 187130561Sobrienpcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, 188130561Sobrien const u_char **pkt_data) 18984865Sobrien{ 19084865Sobrien struct oneshot_userdata s; 19184865Sobrien 19284865Sobrien s.hdr = &p->pcap_header; 19384865Sobrien s.pkt = pkt_data; 19484865Sobrien s.pd = p; 19584865Sobrien 19684865Sobrien /* Saves a pointer to the packet headers */ 19784865Sobrien *pkt_header= &p->pcap_header; 19884865Sobrien 19984865Sobrien if (p->sf.rfile != NULL) { 200130561Sobrien int status; 201130561Sobrien 20284865Sobrien /* We are on an offline capture */ 203130561Sobrien status = pcap_offline_read(p, 1, p->oneshot_callback, 204130561Sobrien (u_char *)&s); 205218822Sdim 206130561Sobrien /* 20789857Sobrien * Return codes for pcap_offline_read() are: 208130561Sobrien * - 0: EOF 209218822Sdim * - -1: error 210130561Sobrien * - >1: OK 211130561Sobrien * The first one ('0') conflicts with the return code of 21284865Sobrien * 0 from pcap_read() meaning "no packets arrived before 213130561Sobrien * the timeout expired", so we map it to -2 so you can 214130561Sobrien * distinguish between an EOF from a savefile and a 215130561Sobrien * "no packets arrived before the timeout expired, try 21684865Sobrien * again" from a live capture. 21784865Sobrien */ 218130561Sobrien if (status == 0) 21984865Sobrien return (-2); 220130561Sobrien else 221130561Sobrien return (status); 22284865Sobrien } 22384865Sobrien 22484865Sobrien /* 22589857Sobrien * Return codes for pcap_read() are: 226218822Sdim * - 0: timeout 227104834Sobrien * - -1: error 22889857Sobrien * - -2: loop was broken out of with pcap_breakloop() 229130561Sobrien * - >1: OK 230130561Sobrien * The first one ('0') conflicts with the return code of 0 from 231130561Sobrien * pcap_offline_read() meaning "end of file". 232130561Sobrien */ 23384865Sobrien return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s)); 23484865Sobrien} 235130561Sobrien 236130561Sobrienstatic void 237130561Sobrieninitialize_ops(pcap_t *p) 23889857Sobrien{ 239130561Sobrien /* 240130561Sobrien * Set operation pointers for operations that only work on 24184865Sobrien * an activated pcap_t to point to a routine that returns 24284865Sobrien * a "this isn't activated" error. 243130561Sobrien */ 24484865Sobrien p->read_op = (read_op_t)pcap_not_initialized; 245130561Sobrien p->inject_op = (inject_op_t)pcap_not_initialized; 24684865Sobrien p->setfilter_op = (setfilter_op_t)pcap_not_initialized; 24789857Sobrien p->setdirection_op = (setdirection_op_t)pcap_not_initialized; 24889857Sobrien p->set_datalink_op = (set_datalink_op_t)pcap_not_initialized; 249130561Sobrien p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized; 25084865Sobrien p->setnonblock_op = (setnonblock_op_t)pcap_not_initialized; 25184865Sobrien p->stats_op = (stats_op_t)pcap_not_initialized; 25284865Sobrien#ifdef WIN32 253130561Sobrien p->setbuff_op = (setbuff_op_t)pcap_not_initialized; 25484865Sobrien p->setmode_op = (setmode_op_t)pcap_not_initialized; 25584865Sobrien p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized; 25684865Sobrien#endif 25784865Sobrien 25884865Sobrien /* 25984865Sobrien * Default cleanup operation - implementations can override 26084865Sobrien * this, but should call pcap_cleanup_live_common() after 26184865Sobrien * doing their own additional cleanup. 26284865Sobrien */ 26384865Sobrien p->cleanup_op = pcap_cleanup_live_common; 26484865Sobrien 265130561Sobrien /* 266130561Sobrien * In most cases, the standard one-short callback can 26784865Sobrien * be used for pcap_next()/pcap_next_ex(). 26884865Sobrien */ 269130561Sobrien p->oneshot_callback = pcap_oneshot; 27084865Sobrien} 27189857Sobrien 27284865Sobrienpcap_t * 273130561Sobrienpcap_create_common(const char *source, char *ebuf) 27484865Sobrien{ 275130561Sobrien pcap_t *p; 27684865Sobrien 277130561Sobrien p = malloc(sizeof(*p)); 27884865Sobrien if (p == NULL) { 279130561Sobrien snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", 28084865Sobrien pcap_strerror(errno)); 281130561Sobrien return (NULL); 28284865Sobrien } 283130561Sobrien memset(p, 0, sizeof(*p)); 28484865Sobrien#ifndef WIN32 285130561Sobrien p->fd = -1; /* not opened yet */ 28684865Sobrien p->selectable_fd = -1; 287130561Sobrien p->send_fd = -1; 28884865Sobrien#endif 289130561Sobrien 29084865Sobrien p->opt.source = strdup(source); 29184865Sobrien if (p->opt.source == NULL) { 292218822Sdim snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", 29384865Sobrien pcap_strerror(errno)); 29484865Sobrien free(p); 29584865Sobrien return (NULL); 29684865Sobrien } 29784865Sobrien 29884865Sobrien /* 29984865Sobrien * Default to "can't set rfmon mode"; if it's supported by 30084865Sobrien * a platform, the create routine that called us can set 30184865Sobrien * the op to its routine to check whether a particular 30284865Sobrien * device supports it. 30384865Sobrien */ 30484865Sobrien p->can_set_rfmon_op = pcap_cant_set_rfmon; 30584865Sobrien 30684865Sobrien initialize_ops(p); 30784865Sobrien 308130561Sobrien /* put in some defaults*/ 309104834Sobrien pcap_set_timeout(p, 0); 310104834Sobrien pcap_set_snaplen(p, 65535); /* max packet size */ 311104834Sobrien p->opt.promisc = 0; 312104834Sobrien p->opt.buffer_size = 0; 31389857Sobrien p->opt.tstamp_type = -1; /* default to not setting time stamp type */ 31489857Sobrien return (p); 315130561Sobrien} 31684865Sobrien 317130561Sobrienint 318130561Sobrienpcap_check_activated(pcap_t *p) 319130561Sobrien{ 32084865Sobrien if (p->activated) { 32184865Sobrien snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform " 32284865Sobrien " operation on activated capture"); 32384865Sobrien return (-1); 324130561Sobrien } 32584865Sobrien return (0); 32684865Sobrien} 327130561Sobrien 32884865Sobrienint 329130561Sobrienpcap_set_snaplen(pcap_t *p, int snaplen) 33084865Sobrien{ 331130561Sobrien if (pcap_check_activated(p)) 33284865Sobrien return (PCAP_ERROR_ACTIVATED); 333130561Sobrien p->snapshot = snaplen; 33484865Sobrien return (0); 33589857Sobrien} 33689857Sobrien 337130561Sobrienint 33889857Sobrienpcap_set_promisc(pcap_t *p, int promisc) 33989857Sobrien{ 34089857Sobrien if (pcap_check_activated(p)) 341130561Sobrien return (PCAP_ERROR_ACTIVATED); 34289857Sobrien p->opt.promisc = promisc; 34384865Sobrien return (0); 344130561Sobrien} 34584865Sobrien 34684865Sobrienint 34784865Sobrienpcap_set_rfmon(pcap_t *p, int rfmon) 34884865Sobrien{ 34984865Sobrien if (pcap_check_activated(p)) 35084865Sobrien return (PCAP_ERROR_ACTIVATED); 35184865Sobrien p->opt.rfmon = rfmon; 35284865Sobrien return (0); 35384865Sobrien} 35484865Sobrien 35584865Sobrienint 35684865Sobrienpcap_set_timeout(pcap_t *p, int timeout_ms) 35784865Sobrien{ 35884865Sobrien if (pcap_check_activated(p)) 35984865Sobrien return (PCAP_ERROR_ACTIVATED); 36084865Sobrien p->md.timeout = timeout_ms; 36184865Sobrien return (0); 36284865Sobrien} 36384865Sobrien 364130561Sobrienint 365130561Sobrienpcap_set_tstamp_type(pcap_t *p, int tstamp_type) 366130561Sobrien{ 367130561Sobrien int i; 36884865Sobrien 36984865Sobrien if (pcap_check_activated(p)) 37084865Sobrien return (PCAP_ERROR_ACTIVATED); 37184865Sobrien 37284865Sobrien /* 37384865Sobrien * If p->tstamp_type_count is 0, we don't support setting 374130561Sobrien * the time stamp type at all. 37584865Sobrien */ 37684865Sobrien if (p->tstamp_type_count == 0) 37784865Sobrien return (PCAP_ERROR_CANTSET_TSTAMP_TYPE); 37884865Sobrien 37984865Sobrien /* 380130561Sobrien * Check whether we claim to support this type of time stamp. 38184865Sobrien */ 382130561Sobrien for (i = 0; i < p->tstamp_type_count; i++) { 383130561Sobrien if (p->tstamp_type_list[i] == tstamp_type) { 384130561Sobrien /* 385130561Sobrien * Yes. 386130561Sobrien */ 387130561Sobrien p->opt.tstamp_type = tstamp_type; 388130561Sobrien return (0); 38984865Sobrien } 390130561Sobrien } 391130561Sobrien 392130561Sobrien /* 393130561Sobrien * No. We support setting the time stamp type, but not to this 394130561Sobrien * particular value. 395130561Sobrien */ 39684865Sobrien return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP); 397130561Sobrien} 398130561Sobrien 39984865Sobrienint 400130561Sobrienpcap_set_buffer_size(pcap_t *p, int buffer_size) 401130561Sobrien{ 402130561Sobrien if (pcap_check_activated(p)) 403130561Sobrien return (PCAP_ERROR_ACTIVATED); 40484865Sobrien p->opt.buffer_size = buffer_size; 405130561Sobrien return (0); 406130561Sobrien} 407130561Sobrien 408130561Sobrienint 409130561Sobrienpcap_activate(pcap_t *p) 41084865Sobrien{ 411130561Sobrien int status; 412130561Sobrien 413130561Sobrien /* 414130561Sobrien * Catch attempts to re-activate an already-activated 415130561Sobrien * pcap_t; this should, for example, catch code that 416130561Sobrien * calls pcap_open_live() followed by pcap_activate(), 417130561Sobrien * as some code that showed up in a Stack Exchange 418130561Sobrien * question did. 41984865Sobrien */ 420130561Sobrien if (pcap_check_activated(p)) 421130561Sobrien return (PCAP_ERROR_ACTIVATED); 422130561Sobrien status = p->activate_op(p); 423130561Sobrien if (status >= 0) 424130561Sobrien p->activated = 1; 425130561Sobrien else { 42684865Sobrien if (p->errbuf[0] == '\0') { 427130561Sobrien /* 428130561Sobrien * No error message supplied by the activate routine; 429130561Sobrien * for the benefit of programs that don't specially 430130561Sobrien * handle errors other than PCAP_ERROR, return the 43184865Sobrien * error message corresponding to the status. 432130561Sobrien */ 433130561Sobrien snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s", 434130561Sobrien pcap_statustostr(status)); 435130561Sobrien } 43684865Sobrien 437130561Sobrien /* 438130561Sobrien * Undo any operation pointer setting, etc. done by 439130561Sobrien * the activate operation. 440130561Sobrien */ 44184865Sobrien initialize_ops(p); 442130561Sobrien } 443130561Sobrien return (status); 444130561Sobrien} 445130561Sobrien 44684865Sobrienpcap_t * 447130561Sobrienpcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf) 448130561Sobrien{ 449130561Sobrien pcap_t *p; 45084865Sobrien int status; 451130561Sobrien 452130561Sobrien p = pcap_create(source, errbuf); 453130561Sobrien if (p == NULL) 454130561Sobrien return (NULL); 455130561Sobrien status = pcap_set_snaplen(p, snaplen); 45684865Sobrien if (status < 0) 457130561Sobrien goto fail; 458130561Sobrien status = pcap_set_promisc(p, promisc); 459130561Sobrien if (status < 0) 460130561Sobrien goto fail; 461130561Sobrien status = pcap_set_timeout(p, to_ms); 462130561Sobrien if (status < 0) 463104834Sobrien goto fail; 464218822Sdim /* 465218822Sdim * Mark this as opened with pcap_open_live(), so that, for 466130561Sobrien * example, we show the full list of DLT_ values, rather 467104834Sobrien * than just the ones that are compatible with capturing 468130561Sobrien * when not in monitor mode. That allows existing applications 469130561Sobrien * to work the way they used to work, but allows new applications 470130561Sobrien * that know about the new open API to, for example, find out the 471130561Sobrien * DLT_ values that they can select without changing whether 472130561Sobrien * the adapter is in monitor mode or not. 473130561Sobrien */ 474130561Sobrien p->oldstyle = 1; 475130561Sobrien status = pcap_activate(p); 47684865Sobrien if (status < 0) 47784865Sobrien goto fail; 47884865Sobrien return (p); 47984865Sobrienfail: 48084865Sobrien if (status == PCAP_ERROR) 48184865Sobrien snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, 482130561Sobrien p->errbuf); 48384865Sobrien else if (status == PCAP_ERROR_NO_SUCH_DEVICE || 48484865Sobrien status == PCAP_ERROR_PERM_DENIED || 48584865Sobrien status == PCAP_ERROR_PROMISC_PERM_DENIED) 48684865Sobrien snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source, 48784865Sobrien pcap_statustostr(status), p->errbuf); 48884865Sobrien else 48984865Sobrien snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, 49084865Sobrien pcap_statustostr(status)); 49184865Sobrien pcap_close(p); 49284865Sobrien return (NULL); 49384865Sobrien} 49484865Sobrien 49584865Sobrienint 49684865Sobrienpcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 49784865Sobrien{ 498218822Sdim return (p->read_op(p, cnt, callback, user)); 499218822Sdim} 50084865Sobrien 50184865Sobrien/* 50284865Sobrien * XXX - is this necessary? 50384865Sobrien */ 50484865Sobrienint 50584865Sobrienpcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 50684865Sobrien{ 50784865Sobrien 50884865Sobrien return (p->read_op(p, cnt, callback, user)); 50984865Sobrien} 51084865Sobrien 51184865Sobrienint 51284865Sobrienpcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 51384865Sobrien{ 51484865Sobrien register int n; 51584865Sobrien 51684865Sobrien for (;;) { 51784865Sobrien if (p->sf.rfile != NULL) { 51884865Sobrien /* 51984865Sobrien * 0 means EOF, so don't loop if we get 0. 52084865Sobrien */ 52184865Sobrien n = pcap_offline_read(p, cnt, callback, user); 52284865Sobrien } else { 52384865Sobrien /* 52484865Sobrien * XXX keep reading until we get something 52584865Sobrien * (or an error occurs) 52684865Sobrien */ 52784865Sobrien do { 52884865Sobrien n = p->read_op(p, cnt, callback, user); 52984865Sobrien } while (n == 0); 53084865Sobrien } 53184865Sobrien if (n <= 0) 53284865Sobrien return (n); 53384865Sobrien if (cnt > 0) { 53484865Sobrien cnt -= n; 53584865Sobrien if (cnt <= 0) 53684865Sobrien return (0); 53784865Sobrien } 53884865Sobrien } 53984865Sobrien} 54084865Sobrien 54184865Sobrien/* 54284865Sobrien * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate. 54384865Sobrien */ 54484865Sobrienvoid 54584865Sobrienpcap_breakloop(pcap_t *p) 54684865Sobrien{ 54784865Sobrien p->break_loop = 1; 54884865Sobrien} 54984865Sobrien 55084865Sobrienint 55184865Sobrienpcap_datalink(pcap_t *p) 55284865Sobrien{ 55384865Sobrien return (p->linktype); 55484865Sobrien} 55584865Sobrien 55684865Sobrienint 55784865Sobrienpcap_datalink_ext(pcap_t *p) 55884865Sobrien{ 55984865Sobrien return (p->linktype_ext); 56089857Sobrien} 56189857Sobrien 56284865Sobrienint 56384865Sobrienpcap_list_datalinks(pcap_t *p, int **dlt_buffer) 56484865Sobrien{ 56584865Sobrien if (p->dlt_count == 0) { 56684865Sobrien /* 56784865Sobrien * We couldn't fetch the list of DLTs, which means 56884865Sobrien * this platform doesn't support changing the 56984865Sobrien * DLT for an interface. Return a list of DLTs 57084865Sobrien * containing only the DLT this device supports. 57184865Sobrien */ 57284865Sobrien *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer)); 57384865Sobrien if (*dlt_buffer == NULL) { 57484865Sobrien (void)snprintf(p->errbuf, sizeof(p->errbuf), 57584865Sobrien "malloc: %s", pcap_strerror(errno)); 57684865Sobrien return (-1); 57784865Sobrien } 57884865Sobrien **dlt_buffer = p->linktype; 57984865Sobrien return (1); 58084865Sobrien } else { 58184865Sobrien *dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count); 58284865Sobrien if (*dlt_buffer == NULL) { 58384865Sobrien (void)snprintf(p->errbuf, sizeof(p->errbuf), 58484865Sobrien "malloc: %s", pcap_strerror(errno)); 58584865Sobrien return (-1); 58684865Sobrien } 58784865Sobrien (void)memcpy(*dlt_buffer, p->dlt_list, 58884865Sobrien sizeof(**dlt_buffer) * p->dlt_count); 58984865Sobrien return (p->dlt_count); 59084865Sobrien } 591104834Sobrien} 59284865Sobrien 593104834Sobrien/* 59484865Sobrien * In Windows, you might have a library built with one version of the 59584865Sobrien * C runtime library and an application built with another version of 596104834Sobrien * the C runtime library, which means that the library might use one 59784865Sobrien * version of malloc() and free() and the application might use another 598104834Sobrien * version of malloc() and free(). If so, that means something 599104834Sobrien * allocated by the library cannot be freed by the application, so we 600104834Sobrien * need to have a pcap_free_datalinks() routine to free up the list 601104834Sobrien * allocated by pcap_list_datalinks(), even though it's just a wrapper 602104834Sobrien * around free(). 603104834Sobrien */ 604104834Sobrienvoid 605104834Sobrienpcap_free_datalinks(int *dlt_list) 606104834Sobrien{ 607104834Sobrien free(dlt_list); 608104834Sobrien} 609104834Sobrien 610104834Sobrienint 61184865Sobrienpcap_set_datalink(pcap_t *p, int dlt) 61284865Sobrien{ 61384865Sobrien int i; 61484865Sobrien const char *dlt_name; 61584865Sobrien 616218822Sdim if (p->dlt_count == 0 || p->set_datalink_op == NULL) { 617218822Sdim /* 618218822Sdim * We couldn't fetch the list of DLTs, or we don't 619218822Sdim * have a "set datalink" operation, which means 620218822Sdim * this platform doesn't support changing the 621218822Sdim * DLT for an interface. Check whether the new 622218822Sdim * DLT is the one this interface supports. 623218822Sdim */ 624218822Sdim if (p->linktype != dlt) 625218822Sdim goto unsupported; 626218822Sdim 627218822Sdim /* 628218822Sdim * It is, so there's nothing we need to do here. 629218822Sdim */ 630218822Sdim return (0); 631218822Sdim } 63284865Sobrien for (i = 0; i < p->dlt_count; i++) 63384865Sobrien if (p->dlt_list[i] == dlt) 63484865Sobrien break; 63584865Sobrien if (i >= p->dlt_count) 63684865Sobrien goto unsupported; 63784865Sobrien if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB && 638130561Sobrien dlt == DLT_DOCSIS) { 63984865Sobrien /* 64089857Sobrien * This is presumably an Ethernet device, as the first 64189857Sobrien * link-layer type it offers is DLT_EN10MB, and the only 64284865Sobrien * other type it offers is DLT_DOCSIS. That means that 64384865Sobrien * we can't tell the driver to supply DOCSIS link-layer 64484865Sobrien * headers - we're just pretending that's what we're 64584865Sobrien * getting, as, presumably, we're capturing on a dedicated 64684865Sobrien * link to a Cisco Cable Modem Termination System, and 64784865Sobrien * it's putting raw DOCSIS frames on the wire inside low-level 64884865Sobrien * Ethernet framing. 64984865Sobrien */ 65084865Sobrien p->linktype = dlt; 65184865Sobrien return (0); 65284865Sobrien } 65384865Sobrien if (p->set_datalink_op(p, dlt) == -1) 65484865Sobrien return (-1); 65584865Sobrien p->linktype = dlt; 65684865Sobrien return (0); 65784865Sobrien 65884865Sobrienunsupported: 65984865Sobrien dlt_name = pcap_datalink_val_to_name(dlt); 66084865Sobrien if (dlt_name != NULL) { 66184865Sobrien (void) snprintf(p->errbuf, sizeof(p->errbuf), 66284865Sobrien "%s is not one of the DLTs supported by this device", 66384865Sobrien dlt_name); 66484865Sobrien } else { 66584865Sobrien (void) snprintf(p->errbuf, sizeof(p->errbuf), 66684865Sobrien "DLT %d is not one of the DLTs supported by this device", 66784865Sobrien dlt); 66884865Sobrien } 66984865Sobrien return (-1); 67084865Sobrien} 67184865Sobrien 672130561Sobrien/* 67384865Sobrien * This array is designed for mapping upper and lower case letter 67484865Sobrien * together for a case independent comparison. The mappings are 67584865Sobrien * based upon ascii character sequences. 67684865Sobrien */ 67784865Sobrienstatic const u_char charmap[] = { 67884865Sobrien (u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003', 67984865Sobrien (u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007', 68084865Sobrien (u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013', 68184865Sobrien (u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017', 68284865Sobrien (u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023', 68384865Sobrien (u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027', 68484865Sobrien (u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033', 68584865Sobrien (u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037', 68684865Sobrien (u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043', 687130561Sobrien (u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047', 68884865Sobrien (u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053', 68984865Sobrien (u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057', 69084865Sobrien (u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063', 69184865Sobrien (u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067', 69284865Sobrien (u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073', 69384865Sobrien (u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077', 69484865Sobrien (u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143', 69584865Sobrien (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147', 69684865Sobrien (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153', 69784865Sobrien (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157', 69884865Sobrien (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163', 69984865Sobrien (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167', 700130561Sobrien (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133', 701130561Sobrien (u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137', 702130561Sobrien (u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143', 703130561Sobrien (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147', 704130561Sobrien (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153', 705130561Sobrien (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157', 706130561Sobrien (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163', 707130561Sobrien (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167', 708130561Sobrien (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173', 709218822Sdim (u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177', 710218822Sdim (u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203', 711218822Sdim (u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207', 712218822Sdim (u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213', 713218822Sdim (u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217', 714218822Sdim (u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223', 715218822Sdim (u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227', 716218822Sdim (u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233', 717218822Sdim (u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237', 718218822Sdim (u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243', 719218822Sdim (u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247', 720218822Sdim (u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253', 721218822Sdim (u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257', 722218822Sdim (u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263', 723218822Sdim (u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267', 724218822Sdim (u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273', 725218822Sdim (u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277', 726218822Sdim (u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343', 727218822Sdim (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347', 728218822Sdim (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353', 729218822Sdim (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357', 730218822Sdim (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363', 731218822Sdim (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367', 732218822Sdim (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333', 733218822Sdim (u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337', 734218822Sdim (u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343', 735218822Sdim (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347', 736218822Sdim (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353', 737218822Sdim (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357', 738218822Sdim (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363', 739218822Sdim (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367', 740218822Sdim (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373', 741218822Sdim (u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377', 742218822Sdim}; 743218822Sdim 744218822Sdimint 745218822Sdimpcap_strcasecmp(const char *s1, const char *s2) 746218822Sdim{ 747218822Sdim register const u_char *cm = charmap, 748218822Sdim *us1 = (const u_char *)s1, 749218822Sdim *us2 = (const u_char *)s2; 750218822Sdim 751218822Sdim while (cm[*us1] == cm[*us2++]) 752218822Sdim if (*us1++ == '\0') 753218822Sdim return(0); 754218822Sdim return (cm[*us1] - cm[*--us2]); 755218822Sdim} 756218822Sdim 757218822Sdimstruct dlt_choice { 758218822Sdim const char *name; 759218822Sdim const char *description; 760218822Sdim int dlt; 761218822Sdim}; 762218822Sdim 763218822Sdim#define DLT_CHOICE(code, description) { #code, description, code } 764218822Sdim#define DLT_CHOICE_SENTINEL { NULL, NULL, 0 } 765218822Sdim 766218822Sdimstatic struct dlt_choice dlt_choices[] = { 767218822Sdim DLT_CHOICE(DLT_NULL, "BSD loopback"), 768218822Sdim DLT_CHOICE(DLT_EN10MB, "Ethernet"), 769218822Sdim DLT_CHOICE(DLT_IEEE802, "Token ring"), 770218822Sdim DLT_CHOICE(DLT_ARCNET, "BSD ARCNET"), 771218822Sdim DLT_CHOICE(DLT_SLIP, "SLIP"), 772218822Sdim DLT_CHOICE(DLT_PPP, "PPP"), 773218822Sdim DLT_CHOICE(DLT_FDDI, "FDDI"), 774218822Sdim DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"), 775218822Sdim DLT_CHOICE(DLT_RAW, "Raw IP"), 776218822Sdim DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"), 777218822Sdim DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"), 778218822Sdim DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"), 779218822Sdim DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"), 780218822Sdim DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"), 781218822Sdim DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"), 782218822Sdim DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"), 783218822Sdim DLT_CHOICE(DLT_IEEE802_11, "802.11"), 784218822Sdim DLT_CHOICE(DLT_FRELAY, "Frame Relay"), 785218822Sdim DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"), 786218822Sdim DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"), 787218822Sdim DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"), 788218822Sdim DLT_CHOICE(DLT_LTALK, "Localtalk"), 789218822Sdim DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"), 790218822Sdim DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"), 791218822Sdim DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"), 792218822Sdim DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"), 793218822Sdim DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"), 794218822Sdim DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radiotap header"), 795218822Sdim DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"), 796218822Sdim DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"), 797218822Sdim DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"), 798218822Sdim DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"), 799218822Sdim DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"), 800218822Sdim DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"), 801218822Sdim DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"), 802218822Sdim DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"), 803218822Sdim DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"), 804218822Sdim DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"), 805218822Sdim DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"), 806218822Sdim DLT_CHOICE(DLT_MTP2, "SS7 MTP2"), 807218822Sdim DLT_CHOICE(DLT_MTP3, "SS7 MTP3"), 808218822Sdim DLT_CHOICE(DLT_SCCP, "SS7 SCCP"), 809218822Sdim DLT_CHOICE(DLT_DOCSIS, "DOCSIS"), 810218822Sdim DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"), 811218822Sdim DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"), 812218822Sdim DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"), 813218822Sdim DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"), 814218822Sdim DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"), 815218822Sdim DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"), 816218822Sdim DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"), 817218822Sdim DLT_CHOICE(DLT_GPF_T, "GPF-T"), 818218822Sdim DLT_CHOICE(DLT_GPF_F, "GPF-F"), 819218822Sdim DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"), 820218822Sdim DLT_CHOICE(DLT_ERF_ETH, "Ethernet with Endace ERF header"), 821218822Sdim DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"), 822218822Sdim DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"), 823218822Sdim DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"), 824218822Sdim DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"), 825218822Sdim DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"), 826218822Sdim DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"), 827218822Sdim DLT_CHOICE(DLT_MFR, "FRF.16 Frame Relay"), 828218822Sdim DLT_CHOICE(DLT_JUNIPER_VP, "Juniper Voice PIC"), 829218822Sdim DLT_CHOICE(DLT_A429, "Arinc 429"), 830218822Sdim DLT_CHOICE(DLT_A653_ICM, "Arinc 653 Interpartition Communication"), 831218822Sdim DLT_CHOICE(DLT_USB, "USB"), 832218822Sdim DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"), 833218822Sdim DLT_CHOICE(DLT_IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"), 834218822Sdim DLT_CHOICE(DLT_USB_LINUX, "USB with Linux header"), 835218822Sdim DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"), 836218822Sdim DLT_CHOICE(DLT_IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"), 837218822Sdim DLT_CHOICE(DLT_PPI, "Per-Packet Information"), 838218822Sdim DLT_CHOICE(DLT_IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"), 839218822Sdim DLT_CHOICE(DLT_JUNIPER_ISM, "Juniper Integrated Service Module"), 840218822Sdim DLT_CHOICE(DLT_IEEE802_15_4, "IEEE 802.15.4 with FCS"), 841218822Sdim DLT_CHOICE(DLT_SITA, "SITA pseudo-header"), 842218822Sdim DLT_CHOICE(DLT_ERF, "Endace ERF header"), 843218822Sdim DLT_CHOICE(DLT_RAIF1, "Ethernet with u10 Networks pseudo-header"), 844218822Sdim DLT_CHOICE(DLT_IPMB, "IPMB"), 845218822Sdim DLT_CHOICE(DLT_JUNIPER_ST, "Juniper Secure Tunnel"), 846218822Sdim DLT_CHOICE(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"), 847130561Sobrien DLT_CHOICE(DLT_AX25_KISS, "AX.25 with KISS header"), 848218822Sdim DLT_CHOICE(DLT_IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"), 849130561Sobrien DLT_CHOICE(DLT_MPLS, "MPLS with label as link-layer header"), 850130561Sobrien DLT_CHOICE(DLT_USB_LINUX_MMAPPED, "USB with padded Linux header"), 851130561Sobrien DLT_CHOICE(DLT_DECT, "DECT"), 852130561Sobrien DLT_CHOICE(DLT_AOS, "AOS Space Data Link protocol"), 853130561Sobrien DLT_CHOICE(DLT_WIHART, "Wireless HART"), 854130561Sobrien DLT_CHOICE(DLT_FC_2, "Fibre Channel FC-2"), 855130561Sobrien DLT_CHOICE(DLT_FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"), 856218822Sdim DLT_CHOICE(DLT_IPNET, "Solaris ipnet"), 857218822Sdim DLT_CHOICE(DLT_CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"), 858130561Sobrien DLT_CHOICE(DLT_IPV4, "Raw IPv4"), 859130561Sobrien DLT_CHOICE(DLT_IPV6, "Raw IPv6"), 860130561Sobrien DLT_CHOICE(DLT_IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"), 861130561Sobrien DLT_CHOICE(DLT_JUNIPER_VS, "Juniper Virtual Server"), 862130561Sobrien DLT_CHOICE(DLT_JUNIPER_SRX_E2E, "Juniper SRX E2E"), 863130561Sobrien DLT_CHOICE(DLT_JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"), 864130561Sobrien DLT_CHOICE(DLT_DVB_CI, "DVB-CI"), 865130561Sobrien DLT_CHOICE(DLT_JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"), 866130561Sobrien DLT_CHOICE(DLT_NFLOG, "Linux netfilter log messages"), 867130561Sobrien DLT_CHOICE(DLT_NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"), 868218822Sdim DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"), 869218822Sdim DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"), 870218822Sdim DLT_CHOICE_SENTINEL 871218822Sdim}; 872130561Sobrien 873130561Sobrienint 874130561Sobrienpcap_datalink_name_to_val(const char *name) 875218822Sdim{ 876218822Sdim int i; 877130561Sobrien 878218822Sdim for (i = 0; dlt_choices[i].name != NULL; i++) { 879218822Sdim if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1, 880218822Sdim name) == 0) 881218822Sdim return (dlt_choices[i].dlt); 882218822Sdim } 883218822Sdim return (-1); 88484865Sobrien} 885130561Sobrien 88684865Sobrienconst char * 887130561Sobrienpcap_datalink_val_to_name(int dlt) 88884865Sobrien{ 88984865Sobrien int i; 89084865Sobrien 89184865Sobrien for (i = 0; dlt_choices[i].name != NULL; i++) { 892130561Sobrien if (dlt_choices[i].dlt == dlt) 89384865Sobrien return (dlt_choices[i].name + sizeof("DLT_") - 1); 89484865Sobrien } 89584865Sobrien return (NULL); 89684865Sobrien} 89784865Sobrien 89884865Sobrienconst char * 89984865Sobrienpcap_datalink_val_to_description(int dlt) 90084865Sobrien{ 90184865Sobrien int i; 90284865Sobrien 90384865Sobrien for (i = 0; dlt_choices[i].name != NULL; i++) { 90484865Sobrien if (dlt_choices[i].dlt == dlt) 90584865Sobrien return (dlt_choices[i].description); 906104834Sobrien } 90784865Sobrien return (NULL); 90884865Sobrien} 909130561Sobrien 910130561Sobrienstruct tstamp_type_choice { 911130561Sobrien const char *name; 912218822Sdim const char *description; 913218822Sdim int type; 914130561Sobrien}; 91584865Sobrien 91684865Sobrienstatic struct tstamp_type_choice tstamp_type_choices[] = { 91784865Sobrien { "host", "Host", PCAP_TSTAMP_HOST }, 918130561Sobrien { "host_lowprec", "Host, low precision", PCAP_TSTAMP_HOST_LOWPREC }, 91984865Sobrien { "host_hiprec", "Host, high precision", PCAP_TSTAMP_HOST_HIPREC }, 920130561Sobrien { "adapter", "Adapter", PCAP_TSTAMP_ADAPTER }, 921130561Sobrien { "adapter_unsynced", "Adapter, not synced with system time", PCAP_TSTAMP_ADAPTER_UNSYNCED }, 922130561Sobrien { NULL, NULL, 0 } 923130561Sobrien}; 924130561Sobrien 925218822Sdimint 92684865Sobrienpcap_tstamp_type_name_to_val(const char *name) 927130561Sobrien{ 928218822Sdim int i; 929218822Sdim 930130561Sobrien for (i = 0; tstamp_type_choices[i].name != NULL; i++) { 93184865Sobrien if (pcap_strcasecmp(tstamp_type_choices[i].name, name) == 0) 93284865Sobrien return (tstamp_type_choices[i].type); 93384865Sobrien } 93484865Sobrien return (PCAP_ERROR); 935130561Sobrien} 93684865Sobrien 93784865Sobrienconst char * 93884865Sobrienpcap_tstamp_type_val_to_name(int tstamp_type) 939130561Sobrien{ 94084865Sobrien int i; 94184865Sobrien 94284865Sobrien for (i = 0; tstamp_type_choices[i].name != NULL; i++) { 94384865Sobrien if (tstamp_type_choices[i].type == tstamp_type) 94484865Sobrien return (tstamp_type_choices[i].name); 94584865Sobrien } 94684865Sobrien return (NULL); 94784865Sobrien} 94884865Sobrien 949218822Sdimconst char * 95084865Sobrienpcap_tstamp_type_val_to_description(int tstamp_type) 95184865Sobrien{ 95284865Sobrien int i; 953130561Sobrien 95484865Sobrien for (i = 0; tstamp_type_choices[i].name != NULL; i++) { 955130561Sobrien if (tstamp_type_choices[i].type == tstamp_type) 95684865Sobrien return (tstamp_type_choices[i].description); 95784865Sobrien } 95884865Sobrien return (NULL); 95989857Sobrien} 960130561Sobrien 961130561Sobrienint 962218822Sdimpcap_snapshot(pcap_t *p) 96384865Sobrien{ 964130561Sobrien return (p->snapshot); 965130561Sobrien} 966130561Sobrien 967130561Sobrienint 968130561Sobrienpcap_is_swapped(pcap_t *p) 969130561Sobrien{ 970218822Sdim return (p->sf.swapped); 971218822Sdim} 972130561Sobrien 973218822Sdimint 974130561Sobrienpcap_major_version(pcap_t *p) 975130561Sobrien{ 97684865Sobrien return (p->sf.version_major); 977130561Sobrien} 978218822Sdim 979218822Sdimint 980218822Sdimpcap_minor_version(pcap_t *p) 981130561Sobrien{ 982218822Sdim return (p->sf.version_minor); 983130561Sobrien} 984130561Sobrien 985130561SobrienFILE * 986130561Sobrienpcap_file(pcap_t *p) 987130561Sobrien{ 988130561Sobrien return (p->sf.rfile); 989130561Sobrien} 990218822Sdim 991218822Sdimint 992218822Sdimpcap_fileno(pcap_t *p) 993130561Sobrien{ 994218822Sdim#ifndef WIN32 995130561Sobrien return (p->fd); 996130561Sobrien#else 997130561Sobrien if (p->adapter != NULL) 998130561Sobrien return ((int)(DWORD)p->adapter->hFile); 999130561Sobrien else 1000130561Sobrien return (-1); 1001130561Sobrien#endif 1002130561Sobrien} 1003130561Sobrien 100484865Sobrien#if !defined(WIN32) && !defined(MSDOS) 100584865Sobrienint 100684865Sobrienpcap_get_selectable_fd(pcap_t *p) 1007104834Sobrien{ 1008104834Sobrien return (p->selectable_fd); 100989857Sobrien} 1010104834Sobrien#endif 1011104834Sobrien 1012104834Sobrienvoid 1013104834Sobrienpcap_perror(pcap_t *p, char *prefix) 1014104834Sobrien{ 1015104834Sobrien fprintf(stderr, "%s: %s\n", prefix, p->errbuf); 1016104834Sobrien} 1017104834Sobrien 1018104834Sobrienchar * 1019104834Sobrienpcap_geterr(pcap_t *p) 1020104834Sobrien{ 1021104834Sobrien return (p->errbuf); 1022130561Sobrien} 1023104834Sobrien 1024130561Sobrienint 1025104834Sobrienpcap_getnonblock(pcap_t *p, char *errbuf) 102684865Sobrien{ 1027104834Sobrien return (p->getnonblock_op(p, errbuf)); 102884865Sobrien} 1029104834Sobrien 103089857Sobrien/* 103189857Sobrien * Get the current non-blocking mode setting, under the assumption that 1032104834Sobrien * it's just the standard POSIX non-blocking flag. 103384865Sobrien * 1034104834Sobrien * We don't look at "p->nonblock", in case somebody tweaked the FD 1035130561Sobrien * directly. 1036218822Sdim */ 103784865Sobrien#if !defined(WIN32) && !defined(MSDOS) 103884865Sobrienint 103984865Sobrienpcap_getnonblock_fd(pcap_t *p, char *errbuf) 104084865Sobrien{ 104184865Sobrien int fdflags; 104284865Sobrien 104384865Sobrien fdflags = fcntl(p->fd, F_GETFL, 0); 104484865Sobrien if (fdflags == -1) { 104584865Sobrien snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", 104684865Sobrien pcap_strerror(errno)); 104784865Sobrien return (-1); 104884865Sobrien } 104984865Sobrien if (fdflags & O_NONBLOCK) 105084865Sobrien return (1); 1051130561Sobrien else 105284865Sobrien return (0); 105384865Sobrien} 105484865Sobrien#endif 1055130561Sobrien 105684865Sobrienint 1057130561Sobrienpcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) 1058130561Sobrien{ 1059130561Sobrien return (p->setnonblock_op(p, nonblock, errbuf)); 1060130561Sobrien} 1061130561Sobrien 106284865Sobrien#if !defined(WIN32) && !defined(MSDOS) 106384865Sobrien/* 1064130561Sobrien * Set non-blocking mode, under the assumption that it's just the 106584865Sobrien * standard POSIX non-blocking flag. (This can be called by the 1066130561Sobrien * per-platform non-blocking-mode routine if that routine also 1067130561Sobrien * needs to do some additional work.) 1068130561Sobrien */ 1069130561Sobrienint 1070130561Sobrienpcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf) 107184865Sobrien{ 107284865Sobrien int fdflags; 1073130561Sobrien 107484865Sobrien fdflags = fcntl(p->fd, F_GETFL, 0); 107584865Sobrien if (fdflags == -1) { 107684865Sobrien snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", 107784865Sobrien pcap_strerror(errno)); 107884865Sobrien return (-1); 107984865Sobrien } 108084865Sobrien if (nonblock) 1081218822Sdim fdflags |= O_NONBLOCK; 1082218822Sdim else 108384865Sobrien fdflags &= ~O_NONBLOCK; 108484865Sobrien if (fcntl(p->fd, F_SETFL, fdflags) == -1) { 1085130561Sobrien snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", 1086218822Sdim pcap_strerror(errno)); 1087218822Sdim return (-1); 1088218822Sdim } 1089218822Sdim return (0); 1090218822Sdim} 1091218822Sdim#endif 1092218822Sdim 1093218822Sdim#ifdef WIN32 1094218822Sdim/* 1095218822Sdim * Generate a string for the last Win32-specific error (i.e. an error generated when 1096218822Sdim * calling a Win32 API). 1097218822Sdim * For errors occurred during standard C calls, we still use pcap_strerror() 1098218822Sdim */ 1099218822Sdimchar * 1100218822Sdimpcap_win32strerror(void) 1101218822Sdim{ 1102218822Sdim DWORD error; 1103218822Sdim static char errbuf[PCAP_ERRBUF_SIZE+1]; 1104218822Sdim int errlen; 1105218822Sdim char *p; 1106218822Sdim 1107218822Sdim error = GetLastError(); 1108218822Sdim FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf, 1109218822Sdim PCAP_ERRBUF_SIZE, NULL); 1110218822Sdim 1111218822Sdim /* 1112218822Sdim * "FormatMessage()" "helpfully" sticks CR/LF at the end of the 1113130561Sobrien * message. Get rid of it. 1114130561Sobrien */ 111584865Sobrien errlen = strlen(errbuf); 1116130561Sobrien if (errlen >= 2) { 1117130561Sobrien errbuf[errlen - 1] = '\0'; 111884865Sobrien errbuf[errlen - 2] = '\0'; 111984865Sobrien } 1120130561Sobrien p = strchr(errbuf, '\0'); 1121130561Sobrien snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error); 1122130561Sobrien return (errbuf); 112384865Sobrien} 1124130561Sobrien#endif 1125130561Sobrien 1126130561Sobrien/* 112784865Sobrien * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values. 1128130561Sobrien */ 1129130561Sobrienconst char * 1130130561Sobrienpcap_statustostr(int errnum) 1131130561Sobrien{ 1132130561Sobrien static char ebuf[15+10+1]; 1133130561Sobrien 1134130561Sobrien switch (errnum) { 1135218822Sdim 113684865Sobrien case PCAP_WARNING: 1137130561Sobrien return("Generic warning"); 1138218822Sdim 1139130561Sobrien case PCAP_WARNING_TSTAMP_TYPE_NOTSUP: 114084865Sobrien return ("That type of time stamp is not supported by that device"); 1141130561Sobrien 1142130561Sobrien case PCAP_WARNING_PROMISC_NOTSUP: 1143130561Sobrien return ("That device doesn't support promiscuous mode"); 1144130561Sobrien 1145130561Sobrien case PCAP_ERROR: 114684865Sobrien return("Generic error"); 1147130561Sobrien 114884865Sobrien case PCAP_ERROR_BREAK: 1149130561Sobrien return("Loop terminated by pcap_breakloop"); 1150130561Sobrien 1151218822Sdim case PCAP_ERROR_NOT_ACTIVATED: 1152218822Sdim return("The pcap_t has not been activated"); 1153218822Sdim 1154218822Sdim case PCAP_ERROR_ACTIVATED: 1155218822Sdim return ("The setting can't be changed after the pcap_t is activated"); 115684865Sobrien 1157218822Sdim case PCAP_ERROR_NO_SUCH_DEVICE: 1158218822Sdim return ("No such device exists"); 1159218822Sdim 1160218822Sdim case PCAP_ERROR_RFMON_NOTSUP: 1161218822Sdim return ("That device doesn't support monitor mode"); 1162218822Sdim 1163218822Sdim case PCAP_ERROR_NOT_RFMON: 1164218822Sdim return ("That operation is supported only in monitor mode"); 1165218822Sdim 1166218822Sdim case PCAP_ERROR_PERM_DENIED: 1167218822Sdim return ("You don't have permission to capture on that device"); 1168218822Sdim 1169218822Sdim case PCAP_ERROR_IFACE_NOT_UP: 1170218822Sdim return ("That device is not up"); 1171218822Sdim 1172218822Sdim case PCAP_ERROR_CANTSET_TSTAMP_TYPE: 1173218822Sdim return ("That device doesn't support setting the time stamp type"); 1174130561Sobrien 1175218822Sdim case PCAP_ERROR_PROMISC_PERM_DENIED: 1176218822Sdim return ("You don't have permission to capture in promiscuous mode on that device"); 1177218822Sdim } 1178218822Sdim (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); 1179130561Sobrien return(ebuf); 118084865Sobrien} 1181130561Sobrien 1182130561Sobrien/* 1183130561Sobrien * Not all systems have strerror(). 1184130561Sobrien */ 1185130561Sobrienconst char * 1186130561Sobrienpcap_strerror(int errnum) 118784865Sobrien{ 1188130561Sobrien#ifdef HAVE_STRERROR 1189130561Sobrien return (strerror(errnum)); 1190130561Sobrien#else 119184865Sobrien extern int sys_nerr; 1192130561Sobrien extern const char *const sys_errlist[]; 1193130561Sobrien static char ebuf[15+10+1]; 1194130561Sobrien 1195130561Sobrien if ((unsigned int)errnum < sys_nerr) 1196130561Sobrien return ((char *)sys_errlist[errnum]); 1197130561Sobrien (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); 1198130561Sobrien return(ebuf); 1199130561Sobrien#endif 1200218822Sdim} 1201130561Sobrien 1202130561Sobrienint 1203130561Sobrienpcap_setfilter(pcap_t *p, struct bpf_program *fp) 1204130561Sobrien{ 1205130561Sobrien return (p->setfilter_op(p, fp)); 1206130561Sobrien} 1207130561Sobrien 1208130561Sobrien/* 1209130561Sobrien * Set direction flag, which controls whether we accept only incoming 1210130561Sobrien * packets, only outgoing packets, or both. 1211130561Sobrien * Note that, depending on the platform, some or all direction arguments 1212218822Sdim * might not be supported. 1213130561Sobrien */ 1214130561Sobrienint 1215130561Sobrienpcap_setdirection(pcap_t *p, pcap_direction_t d) 1216130561Sobrien{ 1217130561Sobrien if (p->setdirection_op == NULL) { 1218130561Sobrien snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1219130561Sobrien "Setting direction is not implemented on this platform"); 1220130561Sobrien return (-1); 1221130561Sobrien } else 1222130561Sobrien return (p->setdirection_op(p, d)); 1223130561Sobrien} 1224130561Sobrien 1225130561Sobrienint 1226130561Sobrienpcap_stats(pcap_t *p, struct pcap_stat *ps) 1227130561Sobrien{ 1228130561Sobrien return (p->stats_op(p, ps)); 1229130561Sobrien} 1230130561Sobrien 1231130561Sobrienstatic int 1232130561Sobrienpcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_) 1233130561Sobrien{ 1234130561Sobrien snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1235130561Sobrien "Statistics aren't available from a pcap_open_dead pcap_t"); 1236130561Sobrien return (-1); 1237130561Sobrien} 1238130561Sobrien 1239130561Sobrien#ifdef WIN32 1240130561Sobrienint 1241130561Sobrienpcap_setbuff(pcap_t *p, int dim) 1242130561Sobrien{ 1243130561Sobrien return (p->setbuff_op(p, dim)); 1244130561Sobrien} 1245130561Sobrien 1246130561Sobrienstatic int 1247130561Sobrienpcap_setbuff_dead(pcap_t *p, int dim) 1248130561Sobrien{ 1249130561Sobrien snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1250130561Sobrien "The kernel buffer size cannot be set on a pcap_open_dead pcap_t"); 125184865Sobrien return (-1); 125284865Sobrien} 125384865Sobrien 1254130561Sobrienint 1255130561Sobrienpcap_setmode(pcap_t *p, int mode) 1256130561Sobrien{ 1257130561Sobrien return (p->setmode_op(p, mode)); 1258130561Sobrien} 1259130561Sobrien 1260130561Sobrienstatic int 1261130561Sobrienpcap_setmode_dead(pcap_t *p, int mode) 126284865Sobrien{ 126384865Sobrien snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1264130561Sobrien "impossible to set mode on a pcap_open_dead pcap_t"); 1265218822Sdim return (-1); 1266218822Sdim} 1267130561Sobrien 1268130561Sobrienint 1269130561Sobrienpcap_setmintocopy(pcap_t *p, int size) 1270130561Sobrien{ 127184865Sobrien return (p->setmintocopy_op(p, size)); 127284865Sobrien} 127384865Sobrien 1274130561Sobrienstatic int 1275130561Sobrienpcap_setmintocopy_dead(pcap_t *p, int size) 1276130561Sobrien{ 1277130561Sobrien snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1278130561Sobrien "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t"); 1279130561Sobrien return (-1); 1280130561Sobrien} 1281130561Sobrien#endif 1282130561Sobrien 1283130561Sobrien/* 1284130561Sobrien * On some platforms, we need to clean up promiscuous or monitor mode 1285130561Sobrien * when we close a device - and we want that to happen even if the 128684865Sobrien * application just exits without explicitl closing devices. 1287130561Sobrien * On those platforms, we need to register a "close all the pcaps" 1288130561Sobrien * routine to be called when we exit, and need to maintain a list of 1289130561Sobrien * pcaps that need to be closed to clean up modes. 1290130561Sobrien * 129184865Sobrien * XXX - not thread-safe. 1292130561Sobrien */ 1293130561Sobrien 1294130561Sobrien/* 1295130561Sobrien * List of pcaps on which we've done something that needs to be 1296130561Sobrien * cleaned up. 1297130561Sobrien * If there are any such pcaps, we arrange to call "pcap_close_all()" 1298130561Sobrien * when we exit, and have it close all of them. 1299130561Sobrien */ 1300130561Sobrienstatic struct pcap *pcaps_to_close; 1301130561Sobrien 1302130561Sobrien/* 1303130561Sobrien * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to 1304130561Sobrien * be called on exit. 1305218822Sdim */ 1306130561Sobrienstatic int did_atexit; 1307130561Sobrien 1308130561Sobrienstatic void 1309130561Sobrienpcap_close_all(void) 1310130561Sobrien{ 131184865Sobrien struct pcap *handle; 131284865Sobrien 1313130561Sobrien while ((handle = pcaps_to_close) != NULL) 1314130561Sobrien pcap_close(handle); 1315130561Sobrien} 1316130561Sobrien 1317218822Sdimint 131884865Sobrienpcap_do_addexit(pcap_t *p) 131984865Sobrien{ 132084865Sobrien /* 132184865Sobrien * If we haven't already done so, arrange to have 132284865Sobrien * "pcap_close_all()" called when we exit. 132384865Sobrien */ 132484865Sobrien if (!did_atexit) { 132584865Sobrien if (atexit(pcap_close_all) == -1) { 1326104834Sobrien /* 1327104834Sobrien * "atexit()" failed; let our caller know. 132884865Sobrien */ 132984865Sobrien strncpy(p->errbuf, "atexit failed", 1330104834Sobrien PCAP_ERRBUF_SIZE); 133184865Sobrien return (0); 133284865Sobrien } 1333104834Sobrien did_atexit = 1; 1334104834Sobrien } 133584865Sobrien return (1); 133684865Sobrien} 133784865Sobrien 1338104834Sobrienvoid 1339104834Sobrienpcap_add_to_pcaps_to_close(pcap_t *p) 134084865Sobrien{ 1341104834Sobrien p->md.next = pcaps_to_close; 1342104834Sobrien pcaps_to_close = p; 134384865Sobrien} 134484865Sobrien 1345104834Sobrienvoid 1346104834Sobrienpcap_remove_from_pcaps_to_close(pcap_t *p) 134784865Sobrien{ 134884865Sobrien pcap_t *pc, *prevpc; 134984865Sobrien 1350104834Sobrien for (pc = pcaps_to_close, prevpc = NULL; pc != NULL; 1351104834Sobrien prevpc = pc, pc = pc->md.next) { 1352104834Sobrien if (pc == p) { 1353104834Sobrien /* 1354104834Sobrien * Found it. Remove it from the list. 1355104834Sobrien */ 1356104834Sobrien if (prevpc == NULL) { 1357104834Sobrien /* 1358130561Sobrien * It was at the head of the list. 1359130561Sobrien */ 1360130561Sobrien pcaps_to_close = pc->md.next; 1361130561Sobrien } else { 1362130561Sobrien /* 1363130561Sobrien * It was in the middle of the list. 1364130561Sobrien */ 1365130561Sobrien prevpc->md.next = pc->md.next; 1366130561Sobrien } 1367130561Sobrien break; 1368218822Sdim } 1369130561Sobrien } 1370218822Sdim} 1371218822Sdim 1372218822Sdimvoid 1373218822Sdimpcap_cleanup_live_common(pcap_t *p) 1374218822Sdim{ 1375218822Sdim if (p->buffer != NULL) { 1376218822Sdim free(p->buffer); 1377218822Sdim p->buffer = NULL; 1378218822Sdim } 1379218822Sdim if (p->dlt_list != NULL) { 1380218822Sdim free(p->dlt_list); 1381218822Sdim p->dlt_list = NULL; 1382130561Sobrien p->dlt_count = 0; 1383130561Sobrien } 1384218822Sdim if (p->tstamp_type_list != NULL) { 1385218822Sdim free(p->tstamp_type_list); 1386218822Sdim p->tstamp_type_list = NULL; 1387218822Sdim p->tstamp_type_count = 0; 1388218822Sdim } 1389218822Sdim pcap_freecode(&p->fcode); 1390130561Sobrien#if !defined(WIN32) && !defined(MSDOS) 139184865Sobrien if (p->fd >= 0) { 1392130561Sobrien close(p->fd); 139384865Sobrien p->fd = -1; 139484865Sobrien } 1395104834Sobrien p->selectable_fd = -1; 1396104834Sobrien p->send_fd = -1; 1397104834Sobrien#endif 1398104834Sobrien} 1399104834Sobrien 1400104834Sobrienstatic void 1401104834Sobrienpcap_cleanup_dead(pcap_t *p _U_) 1402104834Sobrien{ 1403130561Sobrien /* Nothing to do. */ 140484865Sobrien} 1405218822Sdim 1406218822Sdimpcap_t * 1407130561Sobrienpcap_open_dead(int linktype, int snaplen) 1408130561Sobrien{ 1409218822Sdim pcap_t *p; 1410130561Sobrien 1411130561Sobrien p = malloc(sizeof(*p)); 1412130561Sobrien if (p == NULL) 1413130561Sobrien return NULL; 1414130561Sobrien memset (p, 0, sizeof(*p)); 1415130561Sobrien p->snapshot = snaplen; 1416130561Sobrien p->linktype = linktype; 1417130561Sobrien p->stats_op = pcap_stats_dead; 1418130561Sobrien#ifdef WIN32 1419130561Sobrien p->setbuff_op = pcap_setbuff_dead; 1420130561Sobrien p->setmode_op = pcap_setmode_dead; 1421130561Sobrien p->setmintocopy_op = pcap_setmintocopy_dead; 1422130561Sobrien#endif 1423130561Sobrien p->cleanup_op = pcap_cleanup_dead; 1424130561Sobrien p->activated = 1; 1425218822Sdim return (p); 1426130561Sobrien} 1427130561Sobrien 1428130561Sobrien/* 1429130561Sobrien * API compatible with WinPcap's "send a packet" routine - returns -1 1430130561Sobrien * on error, 0 otherwise. 1431130561Sobrien * 1432130561Sobrien * XXX - what if we get a short write? 1433130561Sobrien */ 1434130561Sobrienint 1435130561Sobrienpcap_sendpacket(pcap_t *p, const u_char *buf, int size) 1436130561Sobrien{ 1437218822Sdim if (p->inject_op(p, buf, size) == -1) 1438130561Sobrien return (-1); 143984865Sobrien return (0); 1440130561Sobrien} 144184865Sobrien 1442130561Sobrien/* 1443218822Sdim * API compatible with OpenBSD's "send a packet" routine - returns -1 on 144484865Sobrien * error, number of bytes written otherwise. 144589857Sobrien */ 144689857Sobrienint 1447130561Sobrienpcap_inject(pcap_t *p, const void *buf, size_t size) 144889857Sobrien{ 1449218822Sdim return (p->inject_op(p, buf, size)); 1450218822Sdim} 1451218822Sdim 145284865Sobrienvoid 145384865Sobrienpcap_close(pcap_t *p) 145484865Sobrien{ 1455218822Sdim if (p->opt.source != NULL) 1456218822Sdim free(p->opt.source); 145784865Sobrien p->cleanup_op(p); 1458130561Sobrien free(p); 1459218822Sdim} 1460218822Sdim 1461218822Sdim/* 1462218822Sdim * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw 146384865Sobrien * data for the packet, check whether the packet passes the filter. 146484865Sobrien * Returns the return value of the filter program, which will be zero if 146584865Sobrien * the packet doesn't pass and non-zero if the packet does pass. 146684865Sobrien */ 146784865Sobrienint 146884865Sobrienpcap_offline_filter(struct bpf_program *fp, const struct pcap_pkthdr *h, 146984865Sobrien const u_char *pkt) 147084865Sobrien{ 147184865Sobrien struct bpf_insn *fcode = fp->bf_insns; 147284865Sobrien 147384865Sobrien if (fcode != NULL) 147489857Sobrien return (bpf_filter(fcode, pkt, h->len, h->caplen)); 147584865Sobrien else 147684865Sobrien return (0); 147784865Sobrien} 147884865Sobrien 1479130561Sobrien/* 148084865Sobrien * We make the version string static, and return a pointer to it, rather 148184865Sobrien * than exporting the version string directly. On at least some UNIXes, 148284865Sobrien * if you import data from a shared library into an program, the data is 1483130561Sobrien * bound into the program binary, so if the string in the version of the 148484865Sobrien * library with which the program was linked isn't the same as the 148584865Sobrien * string in the version of the library with which the program is being 1486218822Sdim * run, various undesirable things may happen (warnings, the string 1487130561Sobrien * being the one from the version of the library with which the program 148884865Sobrien * was linked, or even weirder things, such as the string being the one 148984865Sobrien * from the library but being truncated). 1490130561Sobrien */ 149184865Sobrien#ifdef HAVE_VERSION_H 149284865Sobrien#include "version.h" 149384865Sobrien#else 149484865Sobrienstatic const char pcap_version_string[] = "libpcap version 1.x.y"; 149584865Sobrien#endif 149684865Sobrien 149784865Sobrien#ifdef WIN32 1498130561Sobrien/* 149984865Sobrien * XXX - it'd be nice if we could somehow generate the WinPcap and libpcap 150084865Sobrien * version numbers when building WinPcap. (It'd be nice to do so for 1501218822Sdim * the packet.dll version number as well.) 150284865Sobrien */ 150384865Sobrienstatic const char wpcap_version_string[] = "4.0"; 150484865Sobrienstatic const char pcap_version_string_fmt[] = 150584865Sobrien "WinPcap version %s, based on %s"; 1506130561Sobrienstatic const char pcap_version_string_packet_dll_fmt[] = 150784865Sobrien "WinPcap version %s (packet.dll version %s), based on %s"; 150884865Sobrienstatic char *full_pcap_version_string; 150984865Sobrien 151084865Sobrienconst char * 151184865Sobrienpcap_lib_version(void) 1512130561Sobrien{ 151384865Sobrien char *packet_version_string; 151484865Sobrien size_t full_pcap_version_string_len; 1515130561Sobrien 151684865Sobrien if (full_pcap_version_string == NULL) { 151784865Sobrien /* 151884865Sobrien * Generate the version string. 151984865Sobrien */ 152084865Sobrien packet_version_string = PacketGetVersion(); 152184865Sobrien if (strcmp(wpcap_version_string, packet_version_string) == 0) { 152289857Sobrien /* 152384865Sobrien * WinPcap version string and packet.dll version 152484865Sobrien * string are the same; just report the WinPcap 152584865Sobrien * version. 152684865Sobrien */ 152784865Sobrien full_pcap_version_string_len = 152884865Sobrien (sizeof pcap_version_string_fmt - 4) + 152984865Sobrien strlen(wpcap_version_string) + 153084865Sobrien strlen(pcap_version_string); 153189857Sobrien full_pcap_version_string = 153289857Sobrien malloc(full_pcap_version_string_len); 153384865Sobrien sprintf(full_pcap_version_string, 1534130561Sobrien pcap_version_string_fmt, wpcap_version_string, 1535130561Sobrien pcap_version_string); 1536130561Sobrien } else { 1537130561Sobrien /* 1538130561Sobrien * WinPcap version string and packet.dll version 1539130561Sobrien * string are different; that shouldn't be the 1540130561Sobrien * case (the two libraries should come from the 1541130561Sobrien * same version of WinPcap), so we report both 1542130561Sobrien * versions. 1543130561Sobrien */ 1544130561Sobrien full_pcap_version_string_len = 1545130561Sobrien (sizeof pcap_version_string_packet_dll_fmt - 6) + 1546130561Sobrien strlen(wpcap_version_string) + 1547130561Sobrien strlen(packet_version_string) + 1548130561Sobrien strlen(pcap_version_string); 1549130561Sobrien full_pcap_version_string = malloc(full_pcap_version_string_len); 155084865Sobrien 155184865Sobrien sprintf(full_pcap_version_string, 155284865Sobrien pcap_version_string_packet_dll_fmt, 155384865Sobrien wpcap_version_string, packet_version_string, 155484865Sobrien pcap_version_string); 1555218822Sdim } 1556218822Sdim } 1557218822Sdim return (full_pcap_version_string); 1558218822Sdim} 1559218822Sdim 1560130561Sobrien#elif defined(MSDOS) 156184865Sobrien 156284865Sobrienstatic char *full_pcap_version_string; 156384865Sobrien 156484865Sobrienconst char * 156584865Sobrienpcap_lib_version (void) 156684865Sobrien{ 156784865Sobrien char *packet_version_string; 156884865Sobrien size_t full_pcap_version_string_len; 1569130561Sobrien static char dospfx[] = "DOS-"; 157084865Sobrien 157184865Sobrien if (full_pcap_version_string == NULL) { 1572218822Sdim /* 157384865Sobrien * Generate the version string. 157484865Sobrien */ 157584865Sobrien full_pcap_version_string_len = 157684865Sobrien sizeof dospfx + strlen(pcap_version_string); 157784865Sobrien full_pcap_version_string = 157884865Sobrien malloc(full_pcap_version_string_len); 157984865Sobrien strcpy(full_pcap_version_string, dospfx); 1580218822Sdim strcat(full_pcap_version_string, pcap_version_string); 1581218822Sdim } 1582218822Sdim return (full_pcap_version_string); 1583218822Sdim} 1584218822Sdim 158584865Sobrien#else /* UN*X */ 158684865Sobrien 158784865Sobrienconst char * 1588130561Sobrienpcap_lib_version(void) 1589130561Sobrien{ 1590130561Sobrien return (pcap_version_string); 1591130561Sobrien} 1592130561Sobrien#endif 1593130561Sobrien