From 48bc6c35b191857f39b628bd586bd94a03fd13d7 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Wed, 8 May 2013 13:06:27 -0700 Subject: [PATCH] Add an API to set "immediate mode". In "immediate mode", packets are delivered as soon as they arrive. --- Makefile.in | 1 + dlpisubs.c | 8 +- dlpisubs.h | 2 +- pcap-bpf.c | 168 ++++++++++++---------------------- pcap-dag.c | 17 +++- pcap-dlpi.c | 2 +- pcap-int.h | 5 +- pcap-libdlpi.c | 2 +- pcap-nit.c | 35 +++++-- pcap-pf.c | 4 +- pcap-snit.c | 35 +++++-- pcap-win32.c | 20 +++- pcap.c | 17 +++- pcap/pcap.h | 1 + pcap_set_immediate_mode.3pcap | 47 ++++++++++ 15 files changed, 212 insertions(+), 152 deletions(-) create mode 100644 pcap_set_immediate_mode.3pcap diff --git a/Makefile.in b/Makefile.in index 95d36e734a..636e7275af 100644 --- a/Makefile.in +++ b/Makefile.in @@ -199,6 +199,7 @@ MAN3PCAP_NOEXPAND = \ pcap_open_live.3pcap \ pcap_set_buffer_size.3pcap \ pcap_set_datalink.3pcap \ + pcap_set_immediate_mode.3pcap \ pcap_set_promisc.3pcap \ pcap_set_rfmon.3pcap \ pcap_set_snaplen.3pcap \ diff --git a/dlpisubs.c b/dlpisubs.c index 738f4b93bb..efeabdf73e 100644 --- a/dlpisubs.c +++ b/dlpisubs.c @@ -273,7 +273,7 @@ pcap_process_mactype(pcap_t *p, u_int mactype) * Push and configure the buffer module. Returns -1 for error, otherwise 0. */ int -pcap_conf_bufmod(pcap_t *p, int snaplen, int timeout) +pcap_conf_bufmod(pcap_t *p, int snaplen) { int retv = 0; @@ -293,11 +293,11 @@ pcap_conf_bufmod(pcap_t *p, int snaplen, int timeout) } /* Set up the bufmod timeout. */ - if (timeout != 0) { + if (!p->opt.immediate && p->opt.timeout != 0) { struct timeval to; - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout * 1000) % 1000000; + to.tv_sec = p->opt.timeout / 1000; + to.tv_usec = (p->opt.timeout * 1000) % 1000000; if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) { pcap_stream_err("SBIOCSTIME", errno, p->errbuf); retv = -1; diff --git a/dlpisubs.h b/dlpisubs.h index 8795af645e..858bca3c56 100644 --- a/dlpisubs.h +++ b/dlpisubs.h @@ -30,7 +30,7 @@ int pcap_stats_dlpi(pcap_t *, struct pcap_stat *); int pcap_process_pkts(pcap_t *, pcap_handler, u_char *, int, u_char *, int); int pcap_process_mactype(pcap_t *, u_int); #ifdef HAVE_SYS_BUFMOD_H -int pcap_conf_bufmod(pcap_t *, int, int); +int pcap_conf_bufmod(pcap_t *, int); #endif int pcap_alloc_databuf(pcap_t *); int strioctl(int, int, int, char *); diff --git a/pcap-bpf.c b/pcap-bpf.c index 10b902647f..25dd0a11d5 100644 --- a/pcap-bpf.c +++ b/pcap-bpf.c @@ -143,31 +143,31 @@ struct pcap_bpf { #endif #ifdef HAVE_ZEROCOPY_BPF - /* - * Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will - * alternative between these two actual mmap'd buffers as required. - * As there is a header on the front size of the mmap'd buffer, only - * some of the buffer is exposed to libpcap as a whole via bufsize; - * zbufsize is the true size. zbuffer tracks the current zbuf - * assocated with buffer so that it can be used to decide which the - * next buffer to read will be. - */ - u_char *zbuf1, *zbuf2, *zbuffer; - u_int zbufsize; - u_int zerocopy; - u_int interrupted; - struct timespec firstsel; - /* - * If there's currently a buffer being actively processed, then it is - * referenced here; 'buffer' is also pointed at it, but offset by the - * size of the header. - */ - struct bpf_zbuf_header *bzh; + /* + * Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will + * alternative between these two actual mmap'd buffers as required. + * As there is a header on the front size of the mmap'd buffer, only + * some of the buffer is exposed to libpcap as a whole via bufsize; + * zbufsize is the true size. zbuffer tracks the current zbuf + * assocated with buffer so that it can be used to decide which the + * next buffer to read will be. + */ + u_char *zbuf1, *zbuf2, *zbuffer; + u_int zbufsize; + u_int zerocopy; + u_int interrupted; + struct timespec firstsel; + /* + * If there's currently a buffer being actively processed, then it is + * referenced here; 'buffer' is also pointed at it, but offset by the + * size of the header. + */ + struct bpf_zbuf_header *bzh; + int nonblock; /* true if in nonblocking mode */ #endif /* HAVE_ZEROCOPY_BPF */ char *device; /* device name */ int filtering_in_kernel; /* using kernel filter */ - int timeout; /* timeout for buffering */ int must_do_on_close; /* stuff we must do when we close */ }; @@ -234,10 +234,8 @@ static int pcap_set_datalink_bpf(pcap_t *p, int dlt); /* * For zerocopy bpf, the setnonblock/getnonblock routines need to modify - * pb->timeout so we don't call select(2) if the pcap handle is in non- - * blocking mode. We preserve the timeout supplied by pcap_open functions - * to make sure it does not get clobbered if the pcap handle moves between - * blocking and non-blocking mode. + * pb->nonblock so we don't call select(2) if the pcap handle is in non- + * blocking mode. */ static int pcap_getnonblock_bpf(pcap_t *p, char *errbuf) @@ -245,13 +243,8 @@ pcap_getnonblock_bpf(pcap_t *p, char *errbuf) #ifdef HAVE_ZEROCOPY_BPF struct pcap_bpf *pb = p->private; - if (pb->zerocopy) { - /* - * Use a negative value for the timeout to represent that the - * pcap handle is in non-blocking mode. - */ - return (pb->timeout < 0); - } + if (pb->zerocopy) + return (pb->nonblock); #endif return (pcap_getnonblock_fd(p, errbuf)); } @@ -263,30 +256,7 @@ pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf) struct pcap_bpf *pb = p->private; if (pb->zerocopy) { - /* - * Map each value to their corresponding negation to - * preserve the timeout value provided with pcap_set_timeout. - * (from pcap-linux.c). - */ - if (nonblock) { - if (pb->timeout >= 0) { - /* - * Indicate that we're switching to - * non-blocking mode. - */ - pb->timeout = ~pb->timeout; - } - } else { - if (pb->timeout < 0) { - /* - * Timeout is negative, so we're currently - * in blocking mode; reverse the previous - * operation, to make the timeout non-negative - * again. - */ - pb->timeout = ~pb->timeout; - } - } + pb->nonblock = nonblock; return (0); } #endif @@ -368,11 +338,11 @@ pcap_next_zbuf(pcap_t *p, int *cc) * our timeout is less then or equal to zero, handle it like a * regular timeout. */ - tmout = pb->timeout; + tmout = p->opt.timeout; if (tmout) (void) clock_gettime(CLOCK_MONOTONIC, &cur); - if (pb->interrupted && pb->timeout) { - expire = TSTOMILLI(&pb->firstsel) + pb->timeout; + if (pb->interrupted && p->opt.timeout) { + expire = TSTOMILLI(&pb->firstsel) + p->opt.timeout; tmout = expire - TSTOMILLI(&cur); #undef TSTOMILLI if (tmout <= 0) { @@ -393,7 +363,7 @@ pcap_next_zbuf(pcap_t *p, int *cc) * the next timeout. Note that we only call select if the handle * is in blocking mode. */ - if (pb->timeout >= 0) { + if (!pb->nonblock) { FD_ZERO(&r_set); FD_SET(p->fd, &r_set); if (tmout != 0) { @@ -401,9 +371,9 @@ pcap_next_zbuf(pcap_t *p, int *cc) tv.tv_usec = (tmout * 1000) % 1000000; } r = select(p->fd + 1, &r_set, NULL, NULL, - pb->timeout != 0 ? &tv : NULL); + p->opt.timeout != 0 ? &tv : NULL); if (r < 0 && errno == EINTR) { - if (!pb->interrupted && pb->timeout) { + if (!pb->interrupted && p->opt.timeout) { pb->interrupted = 1; pb->firstsel = cur; } @@ -2090,11 +2060,15 @@ pcap_activate_bpf(pcap_t *p) } #endif /* set timeout */ - pb->timeout = p->opt.timeout; #ifdef HAVE_ZEROCOPY_BPF - if (pb->timeout != 0 && !pb->zerocopy) { + /* + * In zero-copy mode, we just use the timeout in select(). + * XXX - what if we're in non-blocking mode and the *application* + * is using select() or poll() or kqueues or....? + */ + if (p->opt.timeout && !pb->zerocopy) { #else - if (pb->timeout) { + if (p->opt.timeout) { #endif /* * XXX - is this seconds/nanoseconds in AIX? @@ -2118,8 +2092,8 @@ pcap_activate_bpf(pcap_t *p) struct BPF_TIMEVAL bpf_to; if (IOCPARM_LEN(BIOCSRTIMEOUT) != sizeof(struct timeval)) { - bpf_to.tv_sec = pb->timeout / 1000; - bpf_to.tv_usec = (pb->timeout * 1000) % 1000000; + bpf_to.tv_sec = p->opt.timeout / 1000; + bpf_to.tv_usec = (p->opt.timeout * 1000) % 1000000; if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); @@ -2128,8 +2102,8 @@ pcap_activate_bpf(pcap_t *p) } } else { #endif - to.tv_sec = pb->timeout / 1000; - to.tv_usec = (pb->timeout * 1000) % 1000000; + to.tv_sec = p->opt.timeout / 1000; + to.tv_usec = (p->opt.timeout * 1000) % 1000000; if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); @@ -2141,7 +2115,6 @@ pcap_activate_bpf(pcap_t *p) #endif } -#ifdef _AIX #ifdef BIOCIMMEDIATE /* * Darren Reed notes that @@ -2155,49 +2128,24 @@ pcap_activate_bpf(pcap_t *p) * * so we turn BIOCIMMEDIATE mode on if this is AIX. * - * We don't turn it on for other platforms, as that means we - * get woken up for every packet, which may not be what we want; - * in the Winter 1993 USENIX paper on BPF, they say: - * - * Since a process might want to look at every packet on a - * network and the time between packets can be only a few - * microseconds, it is not possible to do a read system call - * per packet and BPF must collect the data from several - * packets and return it as a unit when the monitoring - * application does a read. - * - * which I infer is the reason for the timeout - it means we - * wait that amount of time, in the hopes that more packets - * will arrive and we'll get them all with one read. - * - * Setting BIOCIMMEDIATE mode on FreeBSD (and probably other - * BSDs) causes the timeout to be ignored. - * - * On the other hand, some platforms (e.g., Linux) don't support - * timeouts, they just hand stuff to you as soon as it arrives; - * if that doesn't cause a problem on those platforms, it may - * be OK to have BIOCIMMEDIATE mode on BSD as well. - * - * (Note, though, that applications may depend on the read - * completing, even if no packets have arrived, when the timeout - * expires, e.g. GUI applications that have to check for input - * while waiting for packets to arrive; a non-zero timeout - * prevents "select()" from working right on FreeBSD and - * possibly other BSDs, as the timer doesn't start until a - * "read()" is done, so the timer isn't in effect if the - * application is blocked on a "select()", and the "select()" - * doesn't get woken up for a BPF device until the buffer - * fills up.) + * We don't, by default, turn it on for other platforms, as that + * means we get woken up for every packet, which may not be what + * we want; we only turn it on if requested. */ - v = 1; - if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s", - pcap_strerror(errno)); - status = PCAP_ERROR; - goto bad; +#ifndef _AIX + if (p->opt.immediate) { +#endif /* _AIX */ + v = 1; + if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "BIOCIMMEDIATE: %s", pcap_strerror(errno)); + status = PCAP_ERROR; + goto bad; + } +#ifndef _AIX } -#endif /* BIOCIMMEDIATE */ #endif /* _AIX */ +#endif /* BIOCIMMEDIATE */ if (p->opt.promisc) { /* set promiscuous mode, just warn if it fails */ diff --git a/pcap-dag.c b/pcap-dag.c index 1a1ed18ff5..f101c8bb4e 100644 --- a/pcap-dag.c +++ b/pcap-dag.c @@ -683,11 +683,18 @@ static int dag_activate(pcap_t* handle) goto faildetach; } - /* Amount of data to collect in Bytes before calling callbacks. - * Important for efficiency, but can introduce latency - * at low packet rates if to_ms not set! - */ - mindata = 65536; + if (handle->opt.immediate) { + /* Call callback immediately. + * XXX - is this the right way to handle this? + */ + mindata = 0; + } else { + /* Amount of data to collect in Bytes before calling callbacks. + * Important for efficiency, but can introduce latency + * at low packet rates if to_ms not set! + */ + mindata = 65536; + } /* Obey opt.timeout (was to_ms) if supplied. This is a good idea! * Recommend 10-100ms. Calls will time out even if no data arrived. diff --git a/pcap-dlpi.c b/pcap-dlpi.c index 323fbad94c..f11620a904 100644 --- a/pcap-dlpi.c +++ b/pcap-dlpi.c @@ -739,7 +739,7 @@ pcap_activate_dlpi(pcap_t *p) #endif /* Push and configure bufmod. */ - if (pcap_conf_bufmod(p, ss, p->opt.timeout) != 0) + if (pcap_conf_bufmod(p, ss) != 0) goto bad; #endif diff --git a/pcap-int.h b/pcap-int.h index 3527ca349a..56f7a37c60 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -85,11 +85,12 @@ extern CRITICAL_SECTION g_PcapCompileCriticalSection; #endif /* _MSC_VER */ struct pcap_opt { + char *source; int timeout; /* timeout for buffering */ int buffer_size; - char *source; int promisc; - int rfmon; + int rfmon; /* monitor mode */ + int immediate; /* immediate mode - deliver packets as soon as they arrive */ int tstamp_type; }; diff --git a/pcap-libdlpi.c b/pcap-libdlpi.c index 351e9846a5..e5da8c6bac 100644 --- a/pcap-libdlpi.c +++ b/pcap-libdlpi.c @@ -192,7 +192,7 @@ pcap_activate_libdlpi(pcap_t *p) p->fd = dlpi_fd(pd->dlpi_hd); /* Push and configure bufmod. */ - if (pcap_conf_bufmod(p, p->snapshot, p->opt.timeout) != 0) + if (pcap_conf_bufmod(p, p->snapshot) != 0) goto bad; /* diff --git a/pcap-nit.c b/pcap-nit.c index 8e3572116e..5610b2931b 100644 --- a/pcap-nit.c +++ b/pcap-nit.c @@ -218,28 +218,42 @@ pcap_inject_nit(pcap_t *p, const void *buf, size_t size) } static int -nit_setflags(int fd, int promisc, int to_ms, char *ebuf) +nit_setflags(pcap_t *p) { struct nit_ioc nioc; memset(&nioc, 0, sizeof(nioc)); - nioc.nioc_bufspace = BUFSPACE; - nioc.nioc_chunksize = CHUNKSIZE; nioc.nioc_typetomatch = NT_ALLTYPES; nioc.nioc_snaplen = p->snapshot; nioc.nioc_bufalign = sizeof(int); nioc.nioc_bufoffset = 0; - if (to_ms != 0) { + if (p->opt.buffer_size != 0) + nioc.nioc_bufspace = p->opt.buffer_size; + else { + /* Default buffer size */ + nioc.nioc_bufspace = BUFSPACE; + } + + if (p->opt.immediate) { + /* + * XXX - will this cause packets to be delivered immediately? + * XXX - given that this is for SunOS prior to 4.0, do + * we care? + */ + nioc.nioc_chunksize = 0; + } else + nioc.nioc_chunksize = CHUNKSIZE; + if (p->opt.timeout != 0) { nioc.nioc_flags |= NF_TIMEOUT; - nioc.nioc_timeout.tv_sec = to_ms / 1000; - nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000; + nioc.nioc_timeout.tv_sec = p->opt.timeout / 1000; + nioc.nioc_timeout.tv_usec = (p->opt.timeout * 1000) % 1000000; } - if (promisc) + if (p->opt.promisc) nioc.nioc_flags |= NF_PROMISC; - if (ioctl(fd, SIOCSNIT, &nioc) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s", + if (ioctl(p->fd, SIOCSNIT, &nioc) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s", pcap_strerror(errno)); return (-1); } @@ -282,7 +296,8 @@ pcap_activate_nit(pcap_t *p) "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno)); goto bad; } - nit_setflags(p->fd, p->opt.promisc, p->opt.timeout, p->errbuf); + if (nit_setflags(p) < 0) + goto bad; /* * NIT supports only ethernets. diff --git a/pcap-pf.c b/pcap-pf.c index eb06e7b5ba..5eb36087a3 100644 --- a/pcap-pf.c +++ b/pcap-pf.c @@ -337,7 +337,9 @@ your system may not be properly configured; see the packetfilter(4) man page\n", goto bad; } pf->OrigMissed = -1; - enmode = ENTSTAMP|ENBATCH|ENNONEXCL; + enmode = ENTSTAMP|ENNONEXCL; + if (!p->opt.immediate) + enmode |= ENBATCH; if (p->opt.promisc) enmode |= ENPROMISC; if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) { diff --git a/pcap-snit.c b/pcap-snit.c index c910c8b35a..7ff41599a1 100644 --- a/pcap-snit.c +++ b/pcap-snit.c @@ -236,33 +236,48 @@ pcap_inject_snit(pcap_t *p, const void *buf, size_t size) } static int -nit_setflags(int fd, int promisc, int to_ms, char *ebuf) +nit_setflags(pcap_t *p) { bpf_u_int32 flags; struct strioctl si; + u_int zero = 0; struct timeval timeout; + if (p->opt.immediate) { + /* + * Set the chunk size to zero, so that chunks get sent + * up immediately. + */ + si.ic_cmd = NIOCSCHUNK; + si.ic_len = sizeof(zero); + si.ic_dp = (char *)&zero; + if (ioctl(p->fd, I_STR, (char *)&si) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s", + pcap_strerror(errno)); + return (-1); + } + } si.ic_timout = INFTIM; - if (to_ms != 0) { - timeout.tv_sec = to_ms / 1000; - timeout.tv_usec = (to_ms * 1000) % 1000000; + if (p->opt.timeout != 0) { + timeout.tv_sec = p->opt.timeout / 1000; + timeout.tv_usec = (p->opt.timeout * 1000) % 1000000; si.ic_cmd = NIOCSTIME; si.ic_len = sizeof(timeout); si.ic_dp = (char *)&timeout; - if (ioctl(fd, I_STR, (char *)&si) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s", + if (ioctl(p->fd, I_STR, (char *)&si) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s", pcap_strerror(errno)); return (-1); } } flags = NI_TIMESTAMP | NI_LEN | NI_DROPS; - if (promisc) + if (p->opt.promisc) flags |= NI_PROMISC; si.ic_cmd = NIOCSFLAGS; si.ic_len = sizeof(flags); si.ic_dp = (char *)&flags; - if (ioctl(fd, I_STR, (char *)&si) < 0) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s", + if (ioctl(p->fd, I_STR, (char *)&si) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s", pcap_strerror(errno)); return (-1); } @@ -358,7 +373,7 @@ pcap_activate_snit(pcap_t *p) pcap_strerror(errno)); goto bad; } - if (nit_setflags(p->fd, p->opt.promisc, p->opt.timeout, p->errbuf) < 0) + if (nit_setflags(p) < 0) goto bad; (void)ioctl(fd, I_FLUSH, (char *)FLUSHR); diff --git a/pcap-win32.c b/pcap-win32.c index a490d0b24c..db0509564d 100644 --- a/pcap-win32.c +++ b/pcap-win32.c @@ -635,11 +635,23 @@ pcap_activate_win32(pcap_t *p) PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize); - /* tell the driver to copy the buffer only if it contains at least 16K */ - if(PacketSetMinToCopy(p->adapter,16000)==FALSE) + if (p-opt.immediate) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror()); - goto bad; + /* tell the driver to copy the buffer as soon as data arrives */ + if(PacketSetMinToCopy(p->adapter,0)==FALSE) + { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror()); + goto bad; + } + } + else + { + /* tell the driver to copy the buffer only if it contains at least 16K */ + if(PacketSetMinToCopy(p->adapter,16000)==FALSE) + { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror()); + goto bad; + } } } else diff --git a/pcap.c b/pcap.c index 1fc00bde80..2daa850dec 100644 --- a/pcap.c +++ b/pcap.c @@ -541,10 +541,12 @@ pcap_create_common(const char *source, char *ebuf, size_t size) initialize_ops(p); /* put in some defaults*/ - pcap_set_timeout(p, 0); - pcap_set_snaplen(p, 65535); /* max packet size */ + pcap_set_snaplen(p, 65535); /* max packet size */ + p->opt.timeout = 0; /* no timeout specified */ + p->opt.buffer_size = 0; /* use the platform's default */ p->opt.promisc = 0; - p->opt.buffer_size = 0; + p->opt.rfmon = 0; + p->opt.immediate = 0; p->opt.tstamp_type = -1; /* default to not setting time stamp type */ return (p); } @@ -631,6 +633,15 @@ pcap_set_tstamp_type(pcap_t *p, int tstamp_type) return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP); } +int +pcap_set_immediate_mode(pcap_t *p, int immediate) +{ + if (pcap_check_activated(p)) + return (PCAP_ERROR_ACTIVATED); + p->opt.immediate = immediate; + return (0); +} + int pcap_set_buffer_size(pcap_t *p, int buffer_size) { diff --git a/pcap/pcap.h b/pcap/pcap.h index d022cd3408..9124e3fc15 100644 --- a/pcap/pcap.h +++ b/pcap/pcap.h @@ -280,6 +280,7 @@ int pcap_can_set_rfmon(pcap_t *); int pcap_set_rfmon(pcap_t *, int); int pcap_set_timeout(pcap_t *, int); int pcap_set_tstamp_type(pcap_t *, int); +int pcap_set_immediate_mode(pcap_t *, int); int pcap_set_buffer_size(pcap_t *, int); int pcap_activate(pcap_t *); diff --git a/pcap_set_immediate_mode.3pcap b/pcap_set_immediate_mode.3pcap new file mode 100644 index 0000000000..fef5dcdf99 --- /dev/null +++ b/pcap_set_immediate_mode.3pcap @@ -0,0 +1,47 @@ +.\" +.\" Copyright (c) 1994, 1996, 1997 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that: (1) source code distributions +.\" retain the above copyright notice and this paragraph in its entirety, (2) +.\" distributions including binary code include the above copyright notice and +.\" this paragraph in its entirety in the documentation or other materials +.\" provided with the distribution, and (3) all advertising materials mentioning +.\" features or use of this software display the following acknowledgement: +.\" ``This product includes software developed by the University of California, +.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of +.\" the University nor the names of its contributors may be used to endorse +.\" or promote products derived from this software without specific prior +.\" written permission. +.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.TH PCAP_SET_IMMEDIATE_MODE 3PCAP "8 May 20013" +.SH NAME +pcap_set_immediate_mode \- set immediate mode for a not-yet-activated capture +handle +.SH SYNOPSIS +.nf +.ft B +#include +.LP +.ft B +int pcap_set_immediate_mode(pcap_t *p, int immediate_mode); +.ft +.fi +.SH DESCRIPTION +.B pcap_set_immediate_mode() +sets whether immediate mode should be set on a capture handle when +the handle is activated. +If +.I immediate_mode +is non-zero, immediate mode will be set, otherwise it will not be set. +.SH RETURN VALUE +.B pcap_set_immediate_mode() +returns 0 on success or +.B PCAP_ERROR_ACTIVATED +if called on a capture handle that has been activated. +.SH SEE ALSO +pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)