CaptureReader::CaptureReader(const Params& params) : BaseReader{params.interface} { char errbuf[PCAP_ERRBUF_SIZE]; // storage of error description const char* device {source.c_str()}; handle = pcap_create(device, errbuf); if(!handle) { throw PcapError("pcap_create", errbuf); } if(int status {pcap_set_snaplen(handle, params.snaplen)}) { throw PcapError("pcap_set_snaplen", pcap_statustostr(status)); } if(int status {pcap_set_promisc(handle, params.promisc ? 1 : 0)}) { throw PcapError("pcap_set_promisc", pcap_statustostr(status)); } if(int status {pcap_set_timeout(handle, params.timeout_ms)}) { throw PcapError("pcap_set_timeout", pcap_statustostr(status)); } if(int status {pcap_set_buffer_size(handle, params.buffer_size)}) { throw PcapError("pcap_set_buffer_size", pcap_statustostr(status)); } if(int status {pcap_activate(handle)}) { throw PcapError("pcap_activate", pcap_statustostr(status)); } pcap_direction_t direction {PCAP_D_INOUT}; switch(params.direction) { using Direction = CaptureReader::Direction; case Direction::IN : direction = PCAP_D_IN; break; case Direction::OUT : direction = PCAP_D_OUT; break; case Direction::INOUT: direction = PCAP_D_INOUT; break; } if(int status {pcap_setdirection(handle, direction)}) { throw PcapError("pcap_setdirection", pcap_statustostr(status)); } bpf_u_int32 localnet, netmask; if(pcap_lookupnet(device, &localnet, &netmask, errbuf) < 0) { throw PcapError("pcap_lookupnet", errbuf); } BPF bpf(handle, params.filter.c_str(), netmask); if(pcap_setfilter(handle, bpf) < 0) { throw PcapError("pcap_setfiltration", pcap_geterr(handle)); } }
int main(int argc, char **argv) { char errbuf[PCAP_ERRBUF_SIZE]; struct pcap_pkthdr *pkthdr; const u_char *pkt_data; Options options; parse_args(argc, argv, &options); if(options.list_devices) { show_devices(); exit(0); } // Create Handles for in and out pcap_t *in_handle = pcap_create(argv[1], errbuf); pcap_t *out_handle = pcap_create(argv[1], errbuf); if(!in_handle | !out_handle ) exit_error(errbuf, -1); int result = 0; // Set timeout result = pcap_set_timeout(in_handle, 1); // Header size up to window size result = pcap_set_timeout(out_handle, 1); // Header size up to window size handle_pcap_errors(in_handle, result, "set_timeout"); handle_pcap_errors(out_handle, result, "set_timeout"); // Activate! result = pcap_activate(out_handle); result = pcap_activate(in_handle); handle_pcap_errors(out_handle, result, "pcap_activate"); handle_pcap_errors(in_handle, result, "pcap_activate"); // Set Filter filter_on_port(out_handle, "src port ", options.port_str); filter_on_port(in_handle, "dst port ", options.port_str); // Count packet lenghts on port int out_byte_count = 0; int in_byte_count = 0; for(int i = 0; i < 100; i++) { pcap_next_ex(out_handle, &pkthdr, &pkt_data); out_byte_count += pkthdr->len; pcap_next_ex(in_handle, &pkthdr, &pkt_data); in_byte_count += pkthdr->len; } printf("In Bytes: %d\n", in_byte_count); printf("Out Bytes: %d\n", out_byte_count); return 0; }
static pcap_t* open_pcap_dev(const char* ifname, int frameSize, char* errbuf) { pcap_t* handle = pcap_create(ifname, errbuf); if (handle) { int err; err = pcap_set_snaplen(handle, frameSize); if (err) AVB_LOGF_WARNING("Cannot set snap len %d", err); err = pcap_set_promisc(handle, 1); if (err) AVB_LOGF_WARNING("Cannot set promisc %d", err); err = pcap_set_immediate_mode(handle, 1); if (err) AVB_LOGF_WARNING("Cannot set immediate mode %d", err); // we need timeout (here 100ms) otherwise we could block for ever err = pcap_set_timeout(handle, 100); if (err) AVB_LOGF_WARNING("Cannot set timeout %d", err); err = pcap_set_tstamp_precision(handle, PCAP_TSTAMP_PRECISION_NANO); if (err) AVB_LOGF_WARNING("Cannot set tstamp nano precision %d", err); err = pcap_set_tstamp_type(handle, PCAP_TSTAMP_ADAPTER_UNSYNCED); if (err) AVB_LOGF_WARNING("Cannot set tstamp adapter unsynced %d", err); err = pcap_activate(handle); if (err) AVB_LOGF_WARNING("Cannot activate pcap %d", err); } return handle; }
void capture(char *dev) { pcap_t *pcap; char errbuf[PCAP_ERRBUF_SIZE]; struct pcap_pkthdr header; /* The header that pcap gives us */ const u_char *packet; /* The actual packet */ if(NULL == dev) { dev = pcap_lookupdev(errbuf); if (dev == NULL) { fprintf(stderr, "Couldn't find default device: %s\n", errbuf); exit(1); } } pcap = pcap_create(dev, errbuf); pcap_set_rfmon(pcap, 1); pcap_set_promisc(pcap, 1); pcap_set_buffer_size(pcap, 1 * 1024 * 1024); pcap_set_timeout(pcap, 1); pcap_set_snaplen(pcap, 16384); pcap_activate(pcap); if(DLT_IEEE802_11_RADIO == pcap_datalink(pcap)) { pcap_loop(pcap, 0, got_packet, 0); } else { fprintf(stderr, "Could not initialize a IEEE802_11_RADIO packet capture for interface %s\n", dev); } }
pcap_t * pcap_open_live_extended(const char *source, int snaplen, int promisc, int to_ms, int rfmon, char *errbuf) { pcap_t *p; int status; p = pcap_create(source, errbuf); if (p == NULL) return (NULL); status = pcap_set_snaplen(p, snaplen); if (status < 0) goto fail; status = pcap_set_promisc(p, promisc); if (status < 0) goto fail; status = pcap_set_timeout(p, to_ms); if (status < 0) goto fail; if(pcap_can_set_rfmon(p) == 1) { status = pcap_set_rfmon(p, rfmon); if (status < 0) goto fail; } status = pcap_activate(p); if (status < 0) goto fail; return (p); fail: snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, pcap_geterr(p)); pcap_close(p); return (NULL); }
/* Initializes pcap capture settings and returns a pcap handle on success, NULL on error */ pcap_t *capture_init(char *capture_source) { pcap_t *handle = NULL; char errbuf[PCAP_ERRBUF_SIZE] = {0}; #ifdef __APPLE__ // must disassociate from any current AP. This is the only way. pid_t pid = fork(); if (!pid) { char* argv[] = {"/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport", "-z", NULL}; execve("/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport", argv, NULL); } int status; waitpid(pid, &status, 0); handle = pcap_create(capture_source, errbuf); if (handle) { pcap_set_snaplen(handle, BUFSIZ); pcap_set_timeout(handle, 50); pcap_set_rfmon(handle, 1); pcap_set_promisc(handle, 1); int status = pcap_activate(handle); if (status) cprintf(CRITICAL, "pcap_activate status %d\n", status); } #else handle = pcap_open_live(capture_source, BUFSIZ, 1, 0, errbuf); #endif if (!handle) { handle = pcap_open_offline(capture_source, errbuf); } return handle; }
/* * Class: disy_jnipcap_Pcap * Method: setTimeout * Signature: (JI)I */ JNIEXPORT jint JNICALL Java_disy_jnipcap_Pcap_setTimeout (JNIEnv *env, jclass jcls, jlong jptr, jint jtoms) { pcap_t *p = (pcap_t *) jptr; if (p == NULL) return -1; return (jint) pcap_set_timeout (p, (int) jtoms); }
pcap_t * pcap_create(const char *device, char *ebuf) { pcap_t *p; p = calloc(1, sizeof(*p)); if (p == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (NULL); } p->fd = -1; /* not opened yet */ p->opt.source = strdup(device); if (p->opt.source == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); free(p); return (NULL); } /* put in some defaults*/ pcap_set_timeout(p, 0); pcap_set_snaplen(p, 65535); /* max packet size */ p->opt.promisc = 0; p->opt.buffer_size = 0; return (p); }
static int tc_pcap_open(pcap_t **pd, char *device, int snap_len, int buf_size) { int status; char ebuf[PCAP_ERRBUF_SIZE]; *ebuf = '\0'; *pd = pcap_create(device, ebuf); if (*pd == NULL) { tc_log_info(LOG_ERR, 0, "pcap create error:%s", ebuf); return TC_ERROR; } status = pcap_set_snaplen(*pd, snap_len); if (status != 0) { tc_log_info(LOG_ERR, 0, "pcap_set_snaplen error:%s", pcap_statustostr(status)); return TC_ERROR; } status = pcap_set_promisc(*pd, 0); if (status != 0) { tc_log_info(LOG_ERR, 0, "pcap_set_promisc error:%s", pcap_statustostr(status)); return TC_ERROR; } status = pcap_set_timeout(*pd, 1000); if (status != 0) { tc_log_info(LOG_ERR, 0, "pcap_set_timeout error:%s", pcap_statustostr(status)); return TC_ERROR; } status = pcap_set_buffer_size(*pd, buf_size); if (status != 0) { tc_log_info(LOG_ERR, 0, "pcap_set_buffer_size error:%s", pcap_statustostr(status)); return TC_ERROR; } tc_log_info(LOG_NOTICE, 0, "pcap_set_buffer_size:%d", buf_size); status = pcap_activate(*pd); if (status < 0) { tc_log_info(LOG_ERR, 0, "pcap_activate error:%s", pcap_statustostr(status)); return TC_ERROR; } else if (status > 0) { tc_log_info(LOG_WARN, 0, "pcap activate warn:%s", pcap_statustostr(status)); } return TC_OK; }
NAPCapHandle * na_pcap_open (const char *iface, GError **error) { char errbuf[PCAP_ERRBUF_SIZE]; pcap_t *pcap_handle = pcap_create (iface, errbuf); if (pcap_handle == NULL) { g_set_error (error, NA_PCAP_ERROR, NA_PCAP_ERROR_OPEN, "pcap failed to create handle for iface: %s", errbuf); return NULL; } pcap_set_snaplen (pcap_handle, PCAP_SNAPLEN); pcap_set_timeout (pcap_handle, 100); if (pcap_activate (pcap_handle) != 0) { g_set_error (error, NA_PCAP_ERROR, NA_PCAP_ERROR_OPEN, "pcap failed to activate handle for iface"); return NULL; } NAPCapHandle *handle = g_new0 (NAPCapHandle, 1); handle->pcap_handle = pcap_handle; handle->iface = iface; handle->linktype = pcap_datalink (pcap_handle); switch (handle->linktype) { case (DLT_EN10MB): g_debug ("Ethernet link detected"); break; case (DLT_PPP): g_debug ("PPP link detected"); break; case (DLT_LINUX_SLL): g_debug ("Linux Cooked Socket link detected"); break; default: g_debug ("No PPP or Ethernet link: %d", handle->linktype); break; } return handle; }
static void prep_pcap_handle(pcap_t *handle) { int err; err = pcap_set_rfmon(handle, options.rfmon); if(err) die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__); err = pcap_set_promisc(handle, options.promisc); if(err) die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__); err = pcap_set_snaplen(handle, options.snaplen); if(err) die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__); err = pcap_set_timeout(handle, options.read_timeout); if(err) die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__); if(options.buffer_size > 0) { err = pcap_set_buffer_size(handle, options.buffer_size); if(err) die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__); } if(options.tstamp_type != PCAP_ERROR) { err = pcap_set_tstamp_type(handle, options.tstamp_type); if(err == PCAP_ERROR_ACTIVATED) die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__); else if(err == PCAP_ERROR_CANTSET_TSTAMP_TYPE) die(0, "pcap_set_tstamp_type(): Device does not support setting the timestamp"); else if(err == PCAP_WARNING_TSTAMP_TYPE_NOTSUP) plog(0, "pcap_set_tstamp_type(): Device does not support specified tstamp type"); } if(options.tstamp_nano) { err = pcap_set_tstamp_precision(handle, PCAP_TSTAMP_PRECISION_NANO); if(err == PCAP_ERROR_ACTIVATED) die(0, "DEBUG: pcap handle should not be activated at %s:%d", __FILE__, __LINE__); else if(err == PCAP_ERROR_TSTAMP_PRECISION_NOTSUP) die(0, "pcap_set_tstamp_precision(): Device does not support nanosecond precision"); } if(options.linktype != PCAP_ERROR) { err = pcap_set_datalink(handle, options.linktype); if(err) die(0, "pcap_set_datalink(): %s", pcap_geterr(handle)); } }
pcap_t * pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf) { pcap_t *p; int status; p = pcap_create(source, errbuf); if (p == NULL) return (NULL); status = pcap_set_snaplen(p, snaplen); if (status < 0) goto fail; status = pcap_set_promisc(p, promisc); if (status < 0) goto fail; status = pcap_set_timeout(p, to_ms); if (status < 0) goto fail; /* * Mark this as opened with pcap_open_live(), so that, for * example, we show the full list of DLT_ values, rather * than just the ones that are compatible with capturing * when not in monitor mode. That allows existing applications * to work the way they used to work, but allows new applications * that know about the new open API to, for example, find out the * DLT_ values that they can select without changing whether * the adapter is in monitor mode or not. */ p->oldstyle = 1; status = pcap_activate(p); if (status < 0) goto fail; return (p); fail: if (status == PCAP_ERROR) snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, p->errbuf); else if (status == PCAP_ERROR_NO_SUCH_DEVICE || status == PCAP_ERROR_PERM_DENIED || status == PCAP_ERROR_PROMISC_PERM_DENIED) snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source, pcap_statustostr(status), p->errbuf); else snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, pcap_statustostr(status)); pcap_close(p); return (NULL); }
static int epcap_open(EPCAP_STATE *ep) { char errbuf[PCAP_ERRBUF_SIZE]; if (ep->file) { PCAP_ERRBUF(ep->p = pcap_open_offline(ep->file, errbuf)); } else { if (ep->dev == NULL) PCAP_ERRBUF(ep->dev = pcap_lookupdev(errbuf)); #ifdef HAVE_PCAP_CREATE PCAP_ERRBUF(ep->p = pcap_create(ep->dev, errbuf)); (void)pcap_set_snaplen(ep->p, ep->snaplen); (void)pcap_set_promisc(ep->p, ep->opt & EPCAP_OPT_PROMISC); (void)pcap_set_timeout(ep->p, ep->timeout); if (ep->bufsz > 0) (void)pcap_set_buffer_size(ep->p, ep->bufsz); switch (pcap_activate(ep->p)) { case 0: break; case PCAP_WARNING: case PCAP_ERROR: case PCAP_WARNING_PROMISC_NOTSUP: case PCAP_ERROR_NO_SUCH_DEVICE: case PCAP_ERROR_PERM_DENIED: pcap_perror(ep->p, "pcap_activate: "); exit(EXIT_FAILURE); default: exit(EXIT_FAILURE); } #else PCAP_ERRBUF(ep->p = pcap_open_live(ep->dev, ep->snaplen, ep->opt & EPCAP_OPT_PROMISC, ep->timeout, errbuf)); #endif /* monitor mode */ #ifdef PCAP_ERROR_RFMON_NOTSUP if (pcap_can_set_rfmon(ep->p) == 1) (void)pcap_set_rfmon(ep->p, ep->opt & EPCAP_OPT_RFMON); #endif } ep->datalink = pcap_datalink(ep->p); return 0; }
static void tcpeek_init_pcap(void) { char *ifname, errmsg[PCAP_ERRBUF_SIZE], expression[] = "tcp or icmp"; struct bpf_program bpf; if(strisempty(g.option.ifname)) { ifname = pcap_lookupdev(errmsg); if(!ifname) { error_abort("%s", errmsg); } strncpy(g.option.ifname, ifname, sizeof(g.option.ifname) - 1); } g.pcap.pcap = pcap_create(g.option.ifname, errmsg); if(!g.pcap.pcap) { error_abort("%s", errmsg); } if(pcap_set_buffer_size(g.pcap.pcap, g.option.buffer * 1024 * 1024) != 0) { error_abort("%s", "can not set buffer size"); } if(pcap_set_snaplen(g.pcap.pcap, DEFAULT_PCAP_SNAPLEN) != 0) { error_abort("%s", "can not set snaplen"); } if(pcap_set_promisc(g.pcap.pcap, g.option.promisc) != 0) { error_abort("%s", "can not set promiscuous mode"); } if(pcap_set_timeout(g.pcap.pcap, 1) != 0) { error_abort("%s", "can not set timeout"); } if(pcap_activate(g.pcap.pcap) != 0) { error_abort("%s", pcap_geterr(g.pcap.pcap)); } if(pcap_compile(g.pcap.pcap, &bpf, expression, 0, 0) == -1) { error_abort("%s '%s'", pcap_geterr(g.pcap.pcap), expression); } if(pcap_setfilter(g.pcap.pcap, &bpf) == -1){ error_abort("%s", pcap_geterr(g.pcap.pcap)); } pcap_freecode(&bpf); g.pcap.snapshot = pcap_snapshot(g.pcap.pcap); g.pcap.datalink = pcap_datalink(g.pcap.pcap); if(g.pcap.datalink != DLT_EN10MB && g.pcap.datalink != DLT_LINUX_SLL) { error_abort("not support datalink %s (%s)", pcap_datalink_val_to_name(g.pcap.datalink), pcap_datalink_val_to_description(g.pcap.datalink) ); } }
pcap_t * reader_libpcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf) { pcap_t *p; int status; p = pcap_create(source, errbuf); if (p == NULL) return (NULL); status = pcap_set_snaplen(p, snaplen); if (status < 0) goto fail; status = pcap_set_promisc(p, promisc); if (status < 0) goto fail; status = pcap_set_timeout(p, to_ms); if (status < 0) goto fail; status = pcap_set_buffer_size(p, config.pcapBufferSize); if (status < 0) goto fail; status = pcap_activate(p); if (status < 0) goto fail; status = pcap_setnonblock(p, TRUE, errbuf); if (status < 0) { pcap_close(p); return (NULL); } return (p); fail: if (status == PCAP_ERROR) snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, pcap_geterr(p)); else if (status == PCAP_ERROR_NO_SUCH_DEVICE || status == PCAP_ERROR_PERM_DENIED) snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source, pcap_statustostr(status), pcap_geterr(p)); else snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, pcap_statustostr(status)); pcap_close(p); return (NULL); }
static PyObject *ppcap_set_timeout(ppcap *self, PyObject *args) { int to_ms; int retval; if (!PyArg_ParseTuple(args, "i", &to_ms)) return NULL; if (!ppcap_isset_handle(self->handle)) { PyErr_SetString(PyExc_Ppcap, "pcap handle is not created"); return NULL; } retval = pcap_set_timeout(self->handle, to_ms); if (retval == PCAP_ERROR_ACTIVATED) { PyErr_Format(PyExc_Ppcap, "%s", pcap_geterr(self->handle)); return NULL; } Py_RETURN_NONE; }
void pcaplistener::initInterface() { char errbuf[PCAP_ERRBUF_SIZE]; if(pcap_lookupnet(listenInterface.c_str(), &net, &mask, errbuf)) { fprintf(stderr, "Failed to look up netmask: %s", errbuf); exit(0); } if(!(pcap = pcap_create(listenInterface.c_str(), errbuf))) { fprintf(stderr, "Failed to create interface source: %s", errbuf); exit(0); } if(pcap_set_snaplen(pcap, SNAPLEN)) { fprintf(stderr, "Failed to set pcap snapshot length: %s", errbuf); exit(0); } if(pcap_set_promisc(pcap, 1)) { fprintf(stderr, "Failed to set interface to promiscuous mode: %s", errbuf); exit(0); } if(pcap_set_timeout(pcap, READ_TIMEOUT_MS)) { fprintf(stderr, "Failed to set pcap timeout: %s", errbuf); exit(0); } if(pcap_activate(pcap)) { fprintf(stderr, "Failed to activate pcap: %s", errbuf); exit(0); } fexpr = "(host 0.0.0.1)"; }
bool PcapActivity::openLive() { Poco::Buffer<char> errBuff(PCAP_ERRBUF_SIZE); _pcap = pcap_create(_device.c_str(), errBuff.begin()); if (_pcap == nullptr) { _logger.warning("Couldn't open device %s: %s", _device, std::string(errBuff.begin())); return false; } int status = pcap_set_snaplen(_pcap, 1500); if (status < 0) { _logger.warning("Can't set pcap snaplen: %s", std::string(pcap_strerror(status))); } status = pcap_set_promisc(_pcap, 1); if (status < 0) { _logger.warning("Can't set pcap promiscuous mode: %s", std::string(pcap_strerror(status))); } status = pcap_set_timeout(_pcap, 2500); if (status < 0) { _logger.warning("Can't set pcap timeout: %s", std::string(pcap_strerror(status))); } #ifdef POCO_OS_FAMILY_UNIX status = pcap_set_buffer_size(_pcap, 2097152); //2MB #else status = pcap_setbuff(_pcap, 2097152); //2MB #endif if (status < 0) { _logger.warning("Can't set pcap buffer size: %s", std::string(pcap_strerror(status))); } status = pcap_activate(_pcap); if (status < 0) { _logger.warning("Couldn't activate device %s: %s", _device, std::string(pcap_strerror(status))); return false; } return true; }
int main(int argc, char **argv) { register int op; register char *cp, *cmdbuf, *device; long longarg; char *p; int timeout = 1000; int immediate = 0; int nonblock = 0; bpf_u_int32 localnet, netmask; struct bpf_program fcode; char ebuf[PCAP_ERRBUF_SIZE]; int status; int packet_count; device = NULL; if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else program_name = argv[0]; opterr = 0; while ((op = getopt(argc, argv, "i:mnt:")) != -1) { switch (op) { case 'i': device = optarg; break; case 'm': immediate = 1; break; case 'n': nonblock = 1; break; case 't': longarg = strtol(optarg, &p, 10); if (p == optarg || *p != '\0') { error("Timeout value \"%s\" is not a number", optarg); /* NOTREACHED */ } if (longarg < 0) { error("Timeout value %ld is negative", longarg); /* NOTREACHED */ } if (longarg > INT_MAX) { error("Timeout value %ld is too large (> %d)", longarg, INT_MAX); /* NOTREACHED */ } timeout = (int)longarg; break; default: usage(); /* NOTREACHED */ } } if (device == NULL) { device = pcap_lookupdev(ebuf); if (device == NULL) error("%s", ebuf); } *ebuf = '\0'; pd = pcap_create(device, ebuf); if (pd == NULL) error("%s", ebuf); status = pcap_set_snaplen(pd, 65535); if (status != 0) error("%s: pcap_set_snaplen failed: %s", device, pcap_statustostr(status)); if (immediate) { status = pcap_set_immediate_mode(pd, 1); if (status != 0) error("%s: pcap_set_immediate_mode failed: %s", device, pcap_statustostr(status)); } status = pcap_set_timeout(pd, timeout); if (status != 0) error("%s: pcap_set_timeout failed: %s", device, pcap_statustostr(status)); status = pcap_activate(pd); if (status < 0) { /* * pcap_activate() failed. */ error("%s: %s\n(%s)", device, pcap_statustostr(status), pcap_geterr(pd)); } else if (status > 0) { /* * pcap_activate() succeeded, but it's warning us * of a problem it had. */ warning("%s: %s\n(%s)", device, pcap_statustostr(status), pcap_geterr(pd)); } if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { localnet = 0; netmask = 0; warning("%s", ebuf); } cmdbuf = copy_argv(&argv[optind]); if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0) error("%s", pcap_geterr(pd)); if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); if (pcap_setnonblock(pd, nonblock, ebuf) == -1) error("pcap_setnonblock failed: %s", ebuf); printf("Listening on %s\n", device); for (;;) { packet_count = 0; status = pcap_dispatch(pd, -1, countme, (u_char *)&packet_count); if (status < 0) break; if (status != 0) { printf("%d packets seen, %d packets counted after pcap_dispatch returns\n", status, packet_count); } } if (status == -2) { /* * We got interrupted, so perhaps we didn't * manage to finish a line we were printing. * Print an extra newline, just in case. */ putchar('\n'); } (void)fflush(stdout); if (status == -1) { /* * Error. Report it. */ (void)fprintf(stderr, "%s: pcap_loop: %s\n", program_name, pcap_geterr(pd)); } pcap_close(pd); exit(status == -1 ? 1 : 0); }
struct if_pcap_host_context * if_pcap_create_handle(const char *ifname, unsigned int isfile, if_pcap_handler handler, void *handlerarg) { struct if_pcap_host_context *ctx; int dlt; ctx = calloc(1, sizeof(*ctx)); if (NULL == ctx) goto fail; ctx->isfile = isfile; ctx->pkthandler = handler; ctx->pkthandlerarg = handlerarg; if (ctx->isfile) { ctx->p = pcap_open_offline(ifname, ctx->errbuf); if (NULL == ctx->p) goto fail; } else { ctx->p = pcap_create(ifname, ctx->errbuf); if (NULL == ctx->p) goto fail; if (-1 == pcap_setdirection(ctx->p, PCAP_D_IN)) { printf("Could not restrict pcap capture to input on %s\n", ifname); goto fail; } pcap_set_timeout(ctx->p, 1); pcap_set_snaplen(ctx->p, 65535); pcap_set_promisc(ctx->p, 1); switch (pcap_activate(ctx->p)) { case 0: break; case PCAP_WARNING_PROMISC_NOTSUP: printf("Promiscuous mode not supported on %s: %s\n", ifname, pcap_geterr(ctx->p)); break; case PCAP_WARNING: printf("Warning while activating pcap capture on %s: %s\n", ifname, pcap_geterr(ctx->p)); break; case PCAP_ERROR_NO_SUCH_DEVICE: case PCAP_ERROR_PERM_DENIED: printf("Error activating pcap capture on %s: %s\n", ifname, pcap_geterr(ctx->p)); /* FALLTHOUGH */ default: goto fail; break; } dlt = pcap_datalink(ctx->p); if (DLT_EN10MB != dlt) { printf("Data link type on %s is %d, only %d supported\n", ifname, dlt, DLT_EN10MB); goto fail; } } return (ctx); fail: if (ctx) free(ctx); return (NULL); }
/** Open a PCAP handle abstraction * * This opens interfaces for capture or injection, or files/streams for reading/writing. * @param pcap created with fr_pcap_init. * @return 0 on success, -1 on error. */ int fr_pcap_open(fr_pcap_t *pcap) { switch (pcap->type) { case PCAP_INTERFACE_OUT: case PCAP_INTERFACE_IN: { #if defined(HAVE_PCAP_CREATE) && defined(HAVE_PCAP_ACTIVATE) pcap->handle = pcap_create(pcap->name, pcap->errbuf); if (!pcap->handle) { fr_strerror_printf("%s", pcap->errbuf); return -1; } if (pcap_set_snaplen(pcap->handle, SNAPLEN) != 0) { create_error: fr_strerror_printf("%s", pcap_geterr(pcap->handle)); pcap_close(pcap->handle); pcap->handle = NULL; return -1; } if (pcap_set_timeout(pcap->handle, PCAP_NONBLOCK_TIMEOUT) != 0) { goto create_error; } if (pcap_set_promisc(pcap->handle, pcap->promiscuous) != 0) { goto create_error; } if (pcap_set_buffer_size(pcap->handle, SNAPLEN * (pcap->buffer_pkts ? pcap->buffer_pkts : PCAP_BUFFER_DEFAULT)) != 0) { goto create_error; } if (pcap_activate(pcap->handle) != 0) { goto create_error; } #else /* * Alternative functions for libpcap < 1.0 */ pcap->handle = pcap_open_live(pcap->name, SNAPLEN, pcap->promiscuous, PCAP_NONBLOCK_TIMEOUT, pcap->errbuf); if (!pcap->handle) { fr_strerror_printf("%s", pcap->errbuf); return -1; } #endif /* * Despite accepting an errbuff, pcap_setnonblock doesn't seem to write * error message there in newer versions. */ if (pcap_setnonblock(pcap->handle, true, pcap->errbuf) != 0) { fr_strerror_printf("%s", *pcap->errbuf != '\0' ? pcap->errbuf : pcap_geterr(pcap->handle)); pcap_close(pcap->handle); pcap->handle = NULL; return -1; } pcap->fd = pcap_get_selectable_fd(pcap->handle); pcap->link_layer = pcap_datalink(pcap->handle); #ifndef __linux__ { int value = 1; if (ioctl(pcap->fd, BIOCIMMEDIATE, &value) < 0) { fr_strerror_printf("Failed setting BIOCIMMEDIATE: %s", fr_syserror(errno)); } } #endif } break; case PCAP_FILE_IN: pcap->handle = pcap_open_offline(pcap->name, pcap->errbuf); if (!pcap->handle) { fr_strerror_printf("%s", pcap->errbuf); return -1; } pcap->fd = pcap_get_selectable_fd(pcap->handle); pcap->link_layer = pcap_datalink(pcap->handle); break; case PCAP_FILE_OUT: if (pcap->link_layer < 0) { pcap->link_layer = DLT_EN10MB; } pcap->handle = pcap_open_dead(pcap->link_layer, SNAPLEN); if (!pcap->handle) { fr_strerror_printf("Unknown error occurred opening dead PCAP handle"); return -1; } pcap->dumper = pcap_dump_open(pcap->handle, pcap->name); if (!pcap->dumper) { fr_strerror_printf("%s", pcap_geterr(pcap->handle)); return -1; } break; #ifdef HAVE_PCAP_FOPEN_OFFLINE case PCAP_STDIO_IN: pcap->handle = pcap_fopen_offline(stdin, pcap->errbuf); if (!pcap->handle) { fr_strerror_printf("%s", pcap->errbuf); return -1; } pcap->fd = pcap_get_selectable_fd(pcap->handle); pcap->link_layer = pcap_datalink(pcap->handle); break; #else case PCAP_STDIO_IN: fr_strerror_printf("This version of libpcap does not support reading pcap data from streams"); return -1; #endif #ifdef HAVE_PCAP_DUMP_FOPEN case PCAP_STDIO_OUT: pcap->handle = pcap_open_dead(DLT_EN10MB, SNAPLEN); pcap->dumper = pcap_dump_fopen(pcap->handle, stdout); if (!pcap->dumper) { fr_strerror_printf("%s", pcap_geterr(pcap->handle)); return -1; } break; #else case PCAP_STDIO_OUT: fr_strerror_printf("This version of libpcap does not support writing pcap data to streams"); return -1; #endif case PCAP_INVALID: default: fr_assert(0); fr_strerror_printf("Bad handle type (%i)", pcap->type); return -1; } return 0; }
/** * Set up pcap listener for the given interfaces and protocols. * @return a properly configured pcap_t* object for listening for the given protocols - NULL on error * @see pcap_protocols */ pcap_t* create_pcap_listener(const char * dev ///<[in] Device name to listen on , gboolean blocking ///<[in] TRUE if this is a blocking connection , unsigned listenmask ///<[in] Bit mask of protocols to listen for ///< (see @ref pcap_protocols "list of valid bits") , struct bpf_program*prog) ///<[out] Compiled PCAP program { pcap_t* pcdescr = NULL; bpf_u_int32 maskp = 0; bpf_u_int32 netp = 0; char errbuf[PCAP_ERRBUF_SIZE]; char * expr = NULL; int filterlen = 1; unsigned j; int cnt=0; int rc; const char ORWORD [] = " or "; gboolean need_promisc = FALSE; BINDDEBUG(pcap_t); // setbuf(stdout, NULL); setvbuf(stdout, NULL, _IONBF, 0); errbuf[0] = '\0'; // Search the list of valid bits so we can construct the libpcap filter // for the given set of protocols on the fly... // On this pass we just compute the amount of memory we'll need... for (j = 0, cnt = 0; j < DIMOF(filterinfo); ++j) { if (listenmask & filterinfo[j].filterbit) { ++cnt; if (cnt > 1) { filterlen += sizeof(ORWORD); } filterlen += strlen(filterinfo[j].filter); } } if (filterlen < 2) { g_warning("Constructed filter is too short - invalid mask argument."); return NULL; } if (NULL == (expr = malloc(filterlen))) { g_error("Out of memory!"); return NULL; } // Same song, different verse... // This time around, we construct the filter expr[0] = '\0'; for (j = 0, cnt = 0; j < DIMOF(filterinfo); ++j) { if (listenmask & filterinfo[j].filterbit) { ++cnt; if (cnt > 1) { g_strlcat(expr, ORWORD, filterlen); } g_strlcat(expr, filterinfo[j].filter, filterlen); } } if (pcap_lookupnet(dev, &netp, &maskp, errbuf) != 0) { // This is not a problem for non-IPv4 protocols... // It just looks up the ipv4 address - which we mostly don't care about. g_info("%s.%d: pcap_lookupnet(\"%s\") failed: [%s]" , __FUNCTION__, __LINE__, dev, errbuf); } if (NULL == (pcdescr = pcap_create(dev, errbuf))) { g_warning("pcap_create failed: [%s]", errbuf); goto oopsie; } //pcap_set_promisc(pcdescr, FALSE); for (j = 0; j < DIMOF(filterinfo); ++j) { if (listenmask & filterinfo[j].filterbit) { const char * addrstring = filterinfo[j].mcastaddr; if (addrstring && !_enable_mcast_address(addrstring, dev, TRUE)) { need_promisc = TRUE; } } } pcap_set_promisc(pcdescr, need_promisc); #ifdef HAVE_PCAP_SET_RFMON pcap_set_rfmon(pcdescr, FALSE); #endif pcap_setdirection(pcdescr, PCAP_D_IN); // Weird bug - returns -3 and doesn't show an error message... // And pcap_getnonblock also returns -3... Neither should happen AFAIK... errbuf[0] = '\0'; if ((rc = pcap_setnonblock(pcdescr, !blocking, errbuf)) < 0 && errbuf[0] != '\0') { g_warning("pcap_setnonblock(%d) failed: [%s] [rc=%d]", !blocking, errbuf, rc); g_warning("Have no idea why this happens - current blocking state is: %d." , pcap_getnonblock(pcdescr, errbuf)); } pcap_set_snaplen(pcdescr, 1500); /// @todo deal with pcap_set_timeout() call here. if (blocking) { pcap_set_timeout(pcdescr, 240*1000); } else { pcap_set_timeout(pcdescr, 1); } //pcap_set_buffer_size(pcdescr, 1500); if (pcap_activate(pcdescr) != 0) { g_warning("pcap_activate failed: [%s]", pcap_geterr(pcdescr)); goto oopsie; } if (pcap_compile(pcdescr, prog, expr, FALSE, maskp) < 0) { g_warning("pcap_compile of [%s] failed: [%s]", expr, pcap_geterr(pcdescr)); goto oopsie; } if (pcap_setfilter(pcdescr, prog) < 0) { g_warning("pcap_setfilter on [%s] failed: [%s]", expr, pcap_geterr(pcdescr)); goto oopsie; } DEBUGMSG1("Compile of [%s] worked!", expr); free(expr); expr = NULL; return(pcdescr); oopsie: // Some kind of failure - free things up and return NULL g_warning("%s.%d: Could not set up PCAP on %s" , __FUNCTION__, __LINE__, dev); if (expr) { free(expr); expr = NULL; } if (pcdescr) { close_pcap_listener(pcdescr, dev, listenmask); pcdescr = NULL; } return NULL; }
int main(int argc, char **argv) { char *cp, *device; int op; int dorfmon, useactivate; char ebuf[PCAP_ERRBUF_SIZE]; char *infile; char *cmdbuf; pcap_t *pd; int status = 0; int pcap_fd; #if defined(USE_BPF) struct bpf_program bad_fcode; struct bpf_insn uninitialized[INSN_COUNT]; #elif defined(USE_SOCKET_FILTERS) struct sock_fprog bad_fcode; struct sock_filter uninitialized[INSN_COUNT]; #endif struct bpf_program fcode; device = NULL; dorfmon = 0; useactivate = 0; infile = NULL; if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else program_name = argv[0]; opterr = 0; while ((op = getopt(argc, argv, "aF:i:I")) != -1) { switch (op) { case 'a': useactivate = 1; break; case 'F': infile = optarg; break; case 'i': device = optarg; break; case 'I': dorfmon = 1; useactivate = 1; /* required for rfmon */ break; default: usage(); /* NOTREACHED */ } } if (device == NULL) { /* * No interface specified; get whatever pcap_lookupdev() * finds. */ device = pcap_lookupdev(ebuf); if (device == NULL) { error("couldn't find interface to use: %s", ebuf); } } if (infile != NULL) { /* * Filter specified with "-F" and a file containing * a filter. */ cmdbuf = read_infile(infile); } else { if (optind < argc) { /* * Filter specified with arguments on the * command line. */ cmdbuf = copy_argv(&argv[optind+1]); } else { /* * No filter specified; use an empty string, which * compiles to an "accept all" filter. */ cmdbuf = ""; } } if (useactivate) { pd = pcap_create(device, ebuf); if (pd == NULL) error("%s: pcap_create() failed: %s", device, ebuf); status = pcap_set_snaplen(pd, 65535); if (status != 0) error("%s: pcap_set_snaplen failed: %s", device, pcap_statustostr(status)); status = pcap_set_promisc(pd, 1); if (status != 0) error("%s: pcap_set_promisc failed: %s", device, pcap_statustostr(status)); if (dorfmon) { status = pcap_set_rfmon(pd, 1); if (status != 0) error("%s: pcap_set_rfmon failed: %s", device, pcap_statustostr(status)); } status = pcap_set_timeout(pd, 1000); if (status != 0) error("%s: pcap_set_timeout failed: %s", device, pcap_statustostr(status)); status = pcap_activate(pd); if (status < 0) { /* * pcap_activate() failed. */ error("%s: %s\n(%s)", device, pcap_statustostr(status), pcap_geterr(pd)); } else if (status > 0) { /* * pcap_activate() succeeded, but it's warning us * of a problem it had. */ warning("%s: %s\n(%s)", device, pcap_statustostr(status), pcap_geterr(pd)); } } else { *ebuf = '\0'; pd = pcap_open_live(device, 65535, 1, 1000, ebuf); if (pd == NULL) error("%s", ebuf); else if (*ebuf) warning("%s", ebuf); } pcap_fd = pcap_fileno(pd); /* * Try setting a filter with an uninitialized bpf_program * structure. This should cause valgrind to report a * problem. * * We don't check for errors, because it could get an * error due to a bad pointer or count. */ #if defined(USE_BPF) ioctl(pcap_fd, BIOCSETF, &bad_fcode); #elif defined(USE_SOCKET_FILTERS) setsockopt(pcap_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bad_fcode, sizeof(bad_fcode)); #endif /* * Try setting a filter with an initialized bpf_program * structure that points to an uninitialized program. * That should also cause valgrind to report a problem. * * We don't check for errors, because it could get an * error due to a bad pointer or count. */ #if defined(USE_BPF) bad_fcode.bf_len = INSN_COUNT; bad_fcode.bf_insns = uninitialized; ioctl(pcap_fd, BIOCSETF, &bad_fcode); #elif defined(USE_SOCKET_FILTERS) bad_fcode.len = INSN_COUNT; bad_fcode.filter = uninitialized; setsockopt(pcap_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bad_fcode, sizeof(bad_fcode)); #endif /* * Now compile a filter and set the filter with that. * That should *not* cause valgrind to report a * problem. */ if (pcap_compile(pd, &fcode, cmdbuf, 1, 0) < 0) error("can't compile filter: %s", pcap_geterr(pd)); if (pcap_setfilter(pd, &fcode) < 0) error("can't set filter: %s", pcap_geterr(pd)); pcap_close(pd); exit(status < 0 ? 1 : 0); }
int main(int argc, char **argv) { register int op; register char *cp, *device; int dorfmon, dopromisc, snaplen, useactivate, bufsize; char ebuf[PCAP_ERRBUF_SIZE]; pcap_t *pd; int status = 0; device = NULL; dorfmon = 0; dopromisc = 0; snaplen = MAXIMUM_SNAPLEN; bufsize = 0; useactivate = 0; if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else program_name = argv[0]; opterr = 0; while ((op = getopt(argc, argv, "i:Ips:aB:")) != -1) { switch (op) { case 'i': device = optarg; break; case 'I': dorfmon = 1; useactivate = 1; /* required for rfmon */ break; case 'p': dopromisc = 1; break; case 's': { char *end; snaplen = strtol(optarg, &end, 0); if (optarg == end || *end != '\0' || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN) error("invalid snaplen %s", optarg); else if (snaplen == 0) snaplen = MAXIMUM_SNAPLEN; break; } case 'B': bufsize = atoi(optarg)*1024; if (bufsize <= 0) error("invalid packet buffer size %s", optarg); useactivate = 1; /* required for bufsize */ break; case 'a': useactivate = 1; break; default: usage(); /* NOTREACHED */ } } if (useactivate) { pd = pcap_create(device, ebuf); if (pd == NULL) error("%s", ebuf); status = pcap_set_snaplen(pd, snaplen); if (status != 0) error("%s: pcap_set_snaplen failed: %s", device, pcap_statustostr(status)); if (dopromisc) { status = pcap_set_promisc(pd, 1); if (status != 0) error("%s: pcap_set_promisc failed: %s", device, pcap_statustostr(status)); } if (dorfmon) { status = pcap_set_rfmon(pd, 1); if (status != 0) error("%s: pcap_set_rfmon failed: %s", device, pcap_statustostr(status)); } status = pcap_set_timeout(pd, 1000); if (status != 0) error("%s: pcap_set_timeout failed: %s", device, pcap_statustostr(status)); if (bufsize != 0) { status = pcap_set_buffer_size(pd, bufsize); if (status != 0) error("%s: pcap_set_buffer_size failed: %s", device, pcap_statustostr(status)); } status = pcap_activate(pd); if (status < 0) { /* * pcap_activate() failed. */ error("%s: %s\n(%s)", device, pcap_statustostr(status), pcap_geterr(pd)); } else if (status > 0) { /* * pcap_activate() succeeded, but it's warning us * of a problem it had. */ warning("%s: %s\n(%s)", device, pcap_statustostr(status), pcap_geterr(pd)); } } else { *ebuf = '\0'; pd = pcap_open_live(device, 65535, 0, 1000, ebuf); if (pd == NULL) error("%s", ebuf); else if (*ebuf) warning("%s", ebuf); } pcap_close(pd); exit(status < 0 ? 1 : 0); }
static ulink_recv_t *ulink_recv_open(const char *netdev) { int err; ulink_recv_t *t = NULL; if (getenv("debug") != NULL) { debug = 1; } t = (ulink_recv_t *)malloc(sizeof(ulink_recv_t)); memset(t, 0, sizeof(ulink_recv_t)); /* init the pcap */ { char errbuf[PCAP_ERRBUF_SIZE]; t->pcap_handle = pcap_create(netdev, errbuf); if (NULL == t->pcap_handle) { LOG_("pcap_open_live failed. %s", errbuf); free(t); return NULL; } err = pcap_set_snaplen(t->pcap_handle, 128); if (err) { LOG_("pcap_set_snaplen failed: %s", pcap_statustostr(err)); pcap_close(t->pcap_handle); free(t); return NULL; } err = pcap_set_rfmon(t->pcap_handle, 1); if (err) { LOG_("pcap_set_rfmon failed: %s", pcap_statustostr(err)); pcap_close(t->pcap_handle); free(t); return NULL; } err = pcap_set_timeout(t->pcap_handle, CHANNEL_SCAN_TIME); if (err) { LOG_("pcap_set_timeout failed: %s", pcap_statustostr(err)); pcap_close(t->pcap_handle); free(t); return NULL; } err = pcap_activate(t->pcap_handle); if (err) { LOG_("pcap_activate failed: %s", pcap_statustostr(err)); pcap_close(t->pcap_handle); free(t); return NULL; } /* filter */ err = pcap_compile(t->pcap_handle, &t->bpf, "ether multicast and type data subtype qos-data or subtype data", 1, 0); if (err) { LOG_("pcap_compile failed: %s", pcap_geterr(t->pcap_handle)); pcap_close(t->pcap_handle); free(t); return NULL; } err = pcap_setfilter(t->pcap_handle, &t->bpf); if (err) { LOG_("pcap_setfilter failed: %s", pcap_statustostr(err)); pcap_freecode(&t->bpf); pcap_close(t->pcap_handle); free(t); return NULL; } } return t; }
static ERL_NIF_TERM nif_pcap_open_live(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary device = {0}; int snaplen = 0; int promisc = 0; int to_ms = 0; int buffer_size = 0; int rfmon = 0; char errbuf[PCAP_ERRBUF_SIZE] = {0}; EWPCAP_STATE *ep = NULL; ERL_NIF_TERM res = {0}; ERL_NIF_TERM ref = {0}; if (!enif_inspect_iolist_as_binary(env, argv[0], &device)) return enif_make_badarg(env); if (!enif_get_int(env, argv[1], &snaplen)) return enif_make_badarg(env); if (!enif_get_int(env, argv[2], &promisc)) return enif_make_badarg(env); if (!enif_get_int(env, argv[3], &to_ms)) return enif_make_badarg(env); if (!enif_get_int(env, argv[4], &buffer_size)) return enif_make_badarg(env); if (!enif_get_int(env, argv[5], &rfmon)) return enif_make_badarg(env); /* NULL terminate the device name */ if (device.size > 0) { if (!enif_realloc_binary(&device, device.size+1)) return enif_make_tuple2(env, atom_error, atom_enomem); device.data[device.size-1] = '\0'; } ep = enif_alloc_resource(EWPCAP_RESOURCE, sizeof(EWPCAP_STATE)); if (ep == NULL) return enif_make_tuple2(env, atom_error, atom_enomem); /* "any" is a Linux only virtual dev */ ep->p = pcap_create((device.size == 0 ? "any" : (char *)device.data), errbuf); if (ep->p == NULL) return enif_make_tuple2(env, atom_error, enif_make_string(env, errbuf, ERL_NIF_LATIN1)); /* Set the snaplen */ (void)pcap_set_snaplen(ep->p, snaplen); /* Set promiscuous mode */ (void)pcap_set_promisc(ep->p, promisc); /* Set timeout */ (void)pcap_set_timeout(ep->p, to_ms); /* Set buffer size */ if (buffer_size > 0) (void)pcap_set_buffer_size(ep->p, buffer_size); /* Set monitor mode */ if (pcap_can_set_rfmon(ep->p) == 1) (void)pcap_set_rfmon(ep->p, rfmon); /* Return failure on error and warnings */ if (pcap_activate(ep->p) != 0) { pcap_close(ep->p); return enif_make_tuple2(env, atom_error, enif_make_string(env, pcap_geterr(ep->p), ERL_NIF_LATIN1)); } ep->datalink = pcap_datalink(ep->p); (void)enif_self(env, &ep->pid); ep->term_env = enif_alloc_env(); if (ep->term_env == NULL) { pcap_close(ep->p); return enif_make_tuple2(env, atom_error, atom_enomem); } ep->ref = enif_make_ref(ep->term_env); ref = enif_make_copy(env, ep->ref); res = enif_make_resource(env, ep); enif_release_resource(ep); return enif_make_tuple2(env, atom_ok, enif_make_tuple3(env, atom_ewpcap_resource, ref, res)); }
int main(int argc, char** argv) { int ret = 0; int hadBadPacket = 0; int inum; int port; int saveFile = 0; int i = 0; int frame = ETHER_IF_FRAME_LEN; char err[PCAP_ERRBUF_SIZE]; char filter[32]; const char *server = NULL; struct bpf_program fp; pcap_if_t *d; pcap_addr_t *a; signal(SIGINT, sig_handler); #ifndef _WIN32 ssl_InitSniffer(); /* dll load on Windows */ #endif ssl_Trace("./tracefile.txt", err); if (argc == 1) { /* normal case, user chooses device and port */ if (pcap_findalldevs(&alldevs, err) == -1) err_sys("Error in pcap_findalldevs"); for (d = alldevs; d; d=d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)\n", d->description); else printf(" (No description available)\n"); } if (i == 0) err_sys("No interfaces found! Make sure pcap or WinPcap is" " installed correctly and you have sufficient permissions"); printf("Enter the interface number (1-%d): ", i); ret = scanf("%d", &inum); if (ret != 1) printf("scanf port failed\n"); if (inum < 1 || inum > i) err_sys("Interface number out of range"); /* Jump to the selected adapter */ for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++); pcap = pcap_create(d->name, err); if (pcap == NULL) printf("pcap_create failed %s\n", err); /* get an IPv4 address */ for (a = d->addresses; a; a = a->next) { switch(a->addr->sa_family) { case AF_INET: server = iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr); printf("server = %s\n", server); break; default: break; } } if (server == NULL) err_sys("Unable to get device IPv4 address"); ret = pcap_set_snaplen(pcap, 65536); if (ret != 0) printf("pcap_set_snaplen failed %s\n", pcap_geterr(pcap)); ret = pcap_set_timeout(pcap, 1000); if (ret != 0) printf("pcap_set_timeout failed %s\n", pcap_geterr(pcap)); ret = pcap_set_buffer_size(pcap, 1000000); if (ret != 0) printf("pcap_set_buffer_size failed %s\n", pcap_geterr(pcap)); ret = pcap_set_promisc(pcap, 1); if (ret != 0) printf("pcap_set_promisc failed %s\n", pcap_geterr(pcap)); ret = pcap_activate(pcap); if (ret != 0) printf("pcap_activate failed %s\n", pcap_geterr(pcap)); printf("Enter the port to scan: "); ret = scanf("%d", &port); if (ret != 1) printf("scanf port failed\n"); SNPRINTF(filter, sizeof(filter), "tcp and port %d", port); ret = pcap_compile(pcap, &fp, filter, 0, 0); if (ret != 0) printf("pcap_compile failed %s\n", pcap_geterr(pcap)); ret = pcap_setfilter(pcap, &fp); if (ret != 0) printf("pcap_setfilter failed %s\n", pcap_geterr(pcap)); ret = ssl_SetPrivateKey(server, port, "../../certs/server-key.pem", FILETYPE_PEM, NULL, err); if (ret != 0) { printf("Please run directly from sslSniffer/sslSnifferTest dir\n"); } #ifdef HAVE_SNI { char altName[128]; printf("Enter alternate SNI: "); ret = scanf("%s", altName); if (strnlen(altName, 128) > 0) { ret = ssl_SetNamedPrivateKey(altName, server, port, "../../certs/server-key.pem", FILETYPE_PEM, NULL, err); if (ret != 0) { printf("Please run directly from " "sslSniffer/sslSnifferTest dir\n"); } } } #endif } else if (argc >= 3) { saveFile = 1; pcap = pcap_open_offline(argv[1], err); if (pcap == NULL) { printf("pcap_open_offline failed %s\n", err); ret = -1; } else { const char* passwd = NULL; /* defaults for server and port */ port = 443; server = "127.0.0.1"; if (argc >= 4) server = argv[3]; if (argc >= 5) port = atoi(argv[4]); if (argc >= 6) passwd = argv[5]; ret = ssl_SetPrivateKey(server, port, argv[2], FILETYPE_PEM, passwd, err); } } else { /* usage error */ printf( "usage: ./snifftest or ./snifftest dump pemKey" " [server] [port] [password]\n"); exit(EXIT_FAILURE); } if (ret != 0) err_sys(err); if (pcap_datalink(pcap) == DLT_NULL) frame = NULL_IF_FRAME_LEN; while (1) { static int packetNumber = 0; struct pcap_pkthdr header; const unsigned char* packet = pcap_next(pcap, &header); packetNumber++; if (packet) { byte data[65535+16384]; /* may have a partial 16k record cached */ if (header.caplen > 40) { /* min ip(20) + min tcp(20) */ packet += frame; header.caplen -= frame; } else continue; ret = ssl_DecodePacket(packet, header.caplen, data, err); if (ret < 0) { printf("ssl_Decode ret = %d, %s\n", ret, err); hadBadPacket = 1; } if (ret > 0) { data[ret] = 0; printf("SSL App Data(%d:%d):%s\n", packetNumber, ret, data); } } else if (saveFile) break; /* we're done reading file */ } FreeAll(); return hadBadPacket ? EXIT_FAILURE : EXIT_SUCCESS; }
/** * \brief Init function for ReceivePcap. * * This is a setup function for recieving packets * via libpcap. There are two versions of this function * depending on the major version of libpcap used. * For versions prior to 1.x we use open_pcap_live, * for versions 1.x and greater we use pcap_create + pcap_activate. * * \param tv pointer to ThreadVars * \param initdata pointer to the interface passed from the user * \param data pointer gets populated with PcapThreadVars * * \todo Create a general pcap setup function. */ TmEcode ReceivePcapThreadInit(ThreadVars *tv, const void *initdata, void **data) { SCEnter(); PcapIfaceConfig *pcapconfig = (PcapIfaceConfig *)initdata; if (initdata == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL"); SCReturnInt(TM_ECODE_FAILED); } PcapThreadVars *ptv = SCMalloc(sizeof(PcapThreadVars)); if (unlikely(ptv == NULL)) { pcapconfig->DerefFunc(pcapconfig); SCReturnInt(TM_ECODE_FAILED); } memset(ptv, 0, sizeof(PcapThreadVars)); ptv->tv = tv; ptv->livedev = LiveGetDevice(pcapconfig->iface); if (ptv->livedev == NULL) { SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); SCFree(ptv); SCReturnInt(TM_ECODE_FAILED); } SCLogInfo("using interface %s", (char *)pcapconfig->iface); if (LiveGetOffload() == 0) { (void)GetIfaceOffloading((char *)pcapconfig->iface, 1, 1); } else { DisableIfaceOffloading(ptv->livedev, 1, 1); } ptv->checksum_mode = pcapconfig->checksum_mode; if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) { SCLogInfo("Running in 'auto' checksum mode. Detection of interface state will require " xstr(CHECKSUM_SAMPLE_COUNT) " packets."); } /* XXX create a general pcap setup function */ char errbuf[PCAP_ERRBUF_SIZE]; ptv->pcap_handle = pcap_create((char *)pcapconfig->iface, errbuf); if (ptv->pcap_handle == NULL) { if (strlen(errbuf)) { SCLogError(SC_ERR_PCAP_CREATE, "Couldn't create a new pcap handler for %s, error %s", (char *)pcapconfig->iface, errbuf); } else { SCLogError(SC_ERR_PCAP_CREATE, "Couldn't create a new pcap handler for %s", (char *)pcapconfig->iface); } SCFree(ptv); pcapconfig->DerefFunc(pcapconfig); SCReturnInt(TM_ECODE_FAILED); } if (pcapconfig->snaplen == 0) { /* We set snaplen if we can get the MTU */ ptv->pcap_snaplen = GetIfaceMaxPacketSize(pcapconfig->iface); } else { ptv->pcap_snaplen = pcapconfig->snaplen; } if (ptv->pcap_snaplen > 0) { /* set Snaplen. Must be called before pcap_activate */ int pcap_set_snaplen_r = pcap_set_snaplen(ptv->pcap_handle, ptv->pcap_snaplen); if (pcap_set_snaplen_r != 0) { SCLogError(SC_ERR_PCAP_SET_SNAPLEN, "Couldn't set snaplen, error: %s", pcap_geterr(ptv->pcap_handle)); SCFree(ptv); pcapconfig->DerefFunc(pcapconfig); SCReturnInt(TM_ECODE_FAILED); } SCLogInfo("Set snaplen to %d for '%s'", ptv->pcap_snaplen, pcapconfig->iface); } /* set Promisc, and Timeout. Must be called before pcap_activate */ int pcap_set_promisc_r = pcap_set_promisc(ptv->pcap_handle, pcapconfig->promisc); //printf("ReceivePcapThreadInit: pcap_set_promisc(%p) returned %" PRId32 "\n", ptv->pcap_handle, pcap_set_promisc_r); if (pcap_set_promisc_r != 0) { SCLogError(SC_ERR_PCAP_SET_PROMISC, "Couldn't set promisc mode, error %s", pcap_geterr(ptv->pcap_handle)); SCFree(ptv); pcapconfig->DerefFunc(pcapconfig); SCReturnInt(TM_ECODE_FAILED); } int pcap_set_timeout_r = pcap_set_timeout(ptv->pcap_handle,LIBPCAP_COPYWAIT); //printf("ReceivePcapThreadInit: pcap_set_timeout(%p) returned %" PRId32 "\n", ptv->pcap_handle, pcap_set_timeout_r); if (pcap_set_timeout_r != 0) { SCLogError(SC_ERR_PCAP_SET_TIMEOUT, "Problems setting timeout, error %s", pcap_geterr(ptv->pcap_handle)); SCFree(ptv); pcapconfig->DerefFunc(pcapconfig); SCReturnInt(TM_ECODE_FAILED); } #ifdef HAVE_PCAP_SET_BUFF ptv->pcap_buffer_size = pcapconfig->buffer_size; if (ptv->pcap_buffer_size >= 0 && ptv->pcap_buffer_size <= INT_MAX) { if (ptv->pcap_buffer_size > 0) SCLogInfo("Going to use pcap buffer size of %" PRId32 "", ptv->pcap_buffer_size); int pcap_set_buffer_size_r = pcap_set_buffer_size(ptv->pcap_handle,ptv->pcap_buffer_size); //printf("ReceivePcapThreadInit: pcap_set_timeout(%p) returned %" PRId32 "\n", ptv->pcap_handle, pcap_set_buffer_size_r); if (pcap_set_buffer_size_r != 0) { SCLogError(SC_ERR_PCAP_SET_BUFF_SIZE, "Problems setting pcap buffer size, error %s", pcap_geterr(ptv->pcap_handle)); SCFree(ptv); pcapconfig->DerefFunc(pcapconfig); SCReturnInt(TM_ECODE_FAILED); } } #endif /* HAVE_PCAP_SET_BUFF */ /* activate the handle */ int pcap_activate_r = pcap_activate(ptv->pcap_handle); //printf("ReceivePcapThreadInit: pcap_activate(%p) returned %" PRId32 "\n", ptv->pcap_handle, pcap_activate_r); if (pcap_activate_r != 0) { SCLogError(SC_ERR_PCAP_ACTIVATE_HANDLE, "Couldn't activate the pcap handler, error %s", pcap_geterr(ptv->pcap_handle)); SCFree(ptv); pcapconfig->DerefFunc(pcapconfig); SCReturnInt(TM_ECODE_FAILED); } else { ptv->pcap_state = PCAP_STATE_UP; } /* set bpf filter if we have one */ if (pcapconfig->bpf_filter) { SCMutexLock(&pcap_bpf_compile_lock); ptv->bpf_filter = pcapconfig->bpf_filter; if (pcap_compile(ptv->pcap_handle,&ptv->filter,(char *)ptv->bpf_filter,1,0) < 0) { SCLogError(SC_ERR_BPF, "bpf compilation error %s", pcap_geterr(ptv->pcap_handle)); SCMutexUnlock(&pcap_bpf_compile_lock); SCFree(ptv); pcapconfig->DerefFunc(pcapconfig); return TM_ECODE_FAILED; } if (pcap_setfilter(ptv->pcap_handle,&ptv->filter) < 0) { SCLogError(SC_ERR_BPF, "could not set bpf filter %s", pcap_geterr(ptv->pcap_handle)); SCMutexUnlock(&pcap_bpf_compile_lock); SCFree(ptv); pcapconfig->DerefFunc(pcapconfig); return TM_ECODE_FAILED; } SCMutexUnlock(&pcap_bpf_compile_lock); } /* no offloading supported at all */ (void)GetIfaceOffloading(pcapconfig->iface, 1, 1); ptv->datalink = pcap_datalink(ptv->pcap_handle); pcapconfig->DerefFunc(pcapconfig); ptv->capture_kernel_packets = StatsRegisterCounter("capture.kernel_packets", ptv->tv); ptv->capture_kernel_drops = StatsRegisterCounter("capture.kernel_drops", ptv->tv); ptv->capture_kernel_ifdrops = StatsRegisterCounter("capture.kernel_ifdrops", ptv->tv); *data = (void *)ptv; SCReturnInt(TM_ECODE_OK); }
void BaseSniffer::set_timeout(int ms) { pcap_set_timeout(handle, ms); }
int main (int argc, char *argv[]) { struct pollfd *poll_fd; struct config etherpoke_conf; struct config_filter *filter_iter; struct session_data *pcap_session; struct option_data opt; char conf_errbuff[CONF_ERRBUF_SIZE]; char pcap_errbuff[PCAP_ERRBUF_SIZE]; struct pathname path_config; struct sigaction sa; #ifdef DBG_AVG_LOOP_SPEED clock_t clock_start; double clock_avg; #endif pid_t pid; int i, c, j, rval, syslog_flags, opt_index, filter_cnt, sock, poll_len; struct option opt_long[] = { { "", no_argument, NULL, '4' }, { "", no_argument, NULL, '6' }, { "hostname", required_argument, NULL, 't' }, { "daemon", no_argument, NULL, 'd' }, { "accept-max", required_argument, NULL, 'm' }, { "verbose", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { NULL, 0, NULL, 0 } }; sock = -1; poll_fd = NULL; pcap_session = NULL; exitno = EXIT_SUCCESS; syslog_flags = LOG_PID | LOG_PERROR; #ifdef DBG_AVG_LOOP_SPEED clock_avg = 0; #endif memset (&opt, 0, sizeof (struct option_data)); opt.accept_max = ACCEPT_MAX; opt.ip_version = AF_UNSPEC; memset (&path_config, 0, sizeof (struct pathname)); memset (ðerpoke_conf, 0, sizeof (struct config)); while ( (c = getopt_long (argc, argv, "46t:dm:Vhv", opt_long, &opt_index)) != -1 ){ switch ( c ){ case 'd': opt.daemon = 1; break; case 't': rval = hostformat_parse (optarg, opt.hostname, opt.port); if ( rval == -1 || strlen (opt.hostname) == 0 || strlen (opt.port) == 0 ){ fprintf (stderr, "%s: invalid hostname format (expects HOSTNAME:PORT)\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } opt.tcp_event = 1; break; case '4': opt.ip_version = AF_INET; break; case '6': opt.ip_version = AF_INET6; break; case 'm': rval = sscanf (optarg, "%u", &(opt.accept_max)); if ( rval < 1 || opt.accept_max == 0 ){ fprintf (stderr, "%s: invalid number for maximum connections\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } break; case 'V': opt.verbose = 1; break; case 'h': etherpoke_help (argv[0]); exitno = EXIT_SUCCESS; goto cleanup; case 'v': etherpoke_version (argv[0]); exitno = EXIT_SUCCESS; goto cleanup; default: etherpoke_help (argv[0]); exitno = EXIT_FAILURE; goto cleanup; } } // Check if there are some non-option arguments, these are treated as paths // to configuration files. if ( (argc - optind) == 0 ){ fprintf (stderr, "%s: configuration file not specified. Use '--help' to see usage information.\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } // Change working directory to match the dirname of the config file. rval = path_split (argv[optind], &path_config); if ( rval != 0 ){ fprintf (stderr, "%s: cannot split path to configuration file.\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } rval = chdir (path_config.dir); if ( rval == -1 ){ fprintf (stderr, "%s: cannot set working directory to '%s': %s\n", argv[0], path_config.dir, strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } // // Load configuration file // filter_cnt = config_load (ðerpoke_conf, path_config.base, conf_errbuff); if ( filter_cnt == -1 ){ fprintf (stderr, "%s: cannot load configuration file '%s': %s\n", argv[0], argv[optind], conf_errbuff); exitno = EXIT_FAILURE; goto cleanup; } else if ( filter_cnt == 0 ){ fprintf (stderr, "%s: nothing to do, no filters defined.\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } // Allocate enough memory for filters (+1 means that we are also allocating // space for listening socket). // NOTE: always allocate space for listening socket here, to move this // allocation inside the block below (where listening socket is actually // allocated) is not a good idea as more complex condition would have to be // used inside the main loop. poll_len = filter_cnt + 1; if ( opt.tcp_event ){ struct addrinfo *host_addr, addr_hint; int opt_val; // Increase poll size to accommodate socket descriptors for clients. poll_len += opt.accept_max; host_addr = NULL; memset (&addr_hint, 0, sizeof (struct addrinfo)); // Setup addrinfo hints addr_hint.ai_family = opt.ip_version; addr_hint.ai_socktype = SOCK_STREAM; addr_hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; rval = getaddrinfo (opt.hostname, opt.port, &addr_hint, &host_addr); if ( rval != 0 ){ fprintf (stderr, "%s: hostname resolve failed: %s\n", argv[0], gai_strerror (rval)); exitno = EXIT_FAILURE; goto cleanup; } sock = socket (host_addr->ai_family, host_addr->ai_socktype | SOCK_NONBLOCK, host_addr->ai_protocol); if ( sock == -1 ){ freeaddrinfo (host_addr); fprintf (stderr, "%s: cannot create socket: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } opt_val = 1; if ( setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof (opt_val)) == -1 ){ freeaddrinfo (host_addr); fprintf (stderr, "%s: cannot set socket options: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } rval = bind (sock, (struct sockaddr*) host_addr->ai_addr, host_addr->ai_addrlen); if ( rval == -1 ){ freeaddrinfo (host_addr); fprintf (stderr, "%s: cannot bind to address: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } rval = listen (sock, LISTEN_QUEUE_LEN); if ( rval == -1 ){ freeaddrinfo (host_addr); fprintf (stderr, "%s: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } freeaddrinfo (host_addr); } pcap_session = (struct session_data*) calloc (filter_cnt, sizeof (struct session_data)); if ( pcap_session == NULL ){ fprintf (stderr, "%s: cannot allocate memory: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } for ( i = 0, filter_iter = etherpoke_conf.head; filter_iter != NULL; i++, filter_iter = filter_iter->next ){ int link_type; session_data_init (&(pcap_session[i])); pcap_session[i].timeout = filter_iter->session_timeout; pcap_session[i].evt_mask = filter_iter->notify; pcap_session[i].filter_name = strdup (filter_iter->name); if ( pcap_session[i].filter_name == NULL ){ fprintf (stderr, "%s: cannot allocate memory: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } if ( filter_iter->notify & NOTIFY_EXEC ){ if ( filter_iter->session_begin != NULL ){ rval = wordexp (filter_iter->session_begin, &(pcap_session[i].evt_cmd_beg), WORDEXP_FLAGS); if ( rval != 0 ) goto filter_error; } if ( filter_iter->session_error != NULL ){ rval = wordexp (filter_iter->session_error, &(pcap_session[i].evt_cmd_err), WORDEXP_FLAGS); if ( rval != 0 ) goto filter_error; } if ( filter_iter->session_end != NULL ){ rval = wordexp (filter_iter->session_end, &(pcap_session[i].evt_cmd_end), WORDEXP_FLAGS); if ( rval != 0 ) goto filter_error; } filter_error: switch ( rval ){ case WRDE_SYNTAX: fprintf (stderr, "%s: invalid event hook in '%s': syntax error\n", argv[0], filter_iter->name); exitno = EXIT_FAILURE; goto cleanup; case WRDE_BADCHAR: fprintf (stderr, "%s: invalid event hook in '%s': bad character\n", argv[0], filter_iter->name); exitno = EXIT_FAILURE; goto cleanup; case WRDE_BADVAL: fprintf (stderr, "%s: invalid event hook in '%s': referencing undefined variable\n", argv[0], filter_iter->name); exitno = EXIT_FAILURE; goto cleanup; case WRDE_NOSPACE: fprintf (stderr, "%s: cannot expand event hook string in '%s': out of memory\n", argv[0], filter_iter->name); exitno = EXIT_FAILURE; goto cleanup; } } pcap_session[i].handle = pcap_create (filter_iter->interface, pcap_errbuff); if ( pcap_session[i].handle == NULL ){ fprintf (stderr, "%s: cannot start packet capture: %s\n", argv[0], pcap_errbuff); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_set_rfmon (pcap_session[i].handle, filter_iter->rfmon); if ( rval != 0 ){ fprintf (stderr, "%s: cannot enable monitor mode on interface '%s': %s\n", argv[0], filter_iter->interface, pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_set_promisc (pcap_session[i].handle, !(filter_iter->rfmon)); if ( rval != 0 ){ fprintf (stderr, "%s: cannot enable promiscuous mode on interface '%s'\n", argv[0], filter_iter->interface); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_set_timeout (pcap_session[i].handle, SELECT_TIMEOUT_MS); if ( rval != 0 ){ fprintf (stderr, "%s: cannot set read timeout on interface '%s': %s\n", argv[0], filter_iter->interface, pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_setnonblock (pcap_session[i].handle, 1, pcap_errbuff); if ( rval == -1 ){ fprintf (stderr, "%s: cannot set nonblock mode on packet capture resource: %s\n", argv[0], pcap_errbuff); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_activate (pcap_session[i].handle); if ( rval != 0 ){ fprintf (stderr, "%s: cannot activate packet capture on interface '%s': %s\n", argv[0], filter_iter->interface, pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } // Set link-layer type from configuration file. if ( filter_iter->link_type != NULL ){ link_type = pcap_datalink_name_to_val (filter_iter->link_type); if ( link_type == -1 ){ fprintf (stderr, "%s: cannot convert link-layer type '%s': unknown link-layer type name\n", argv[0], filter_iter->link_type); exitno = EXIT_FAILURE; goto cleanup; } } else { // If no link-layer type is specified in the configuration file, // use default value. At this point I am sticking with DLTs used by // wireshark on hardware I have available. Different values may // apply to different hardware/driver, therefore more research time // should be put into finding 'best' values. // More information: http://www.tcpdump.org/linktypes.html if ( filter_iter->rfmon ){ link_type = DLT_IEEE802_11_RADIO; } else { link_type = DLT_EN10MB; } } rval = pcap_set_datalink (pcap_session[i].handle, link_type); if ( rval == -1 ){ fprintf (stderr, "%s: cannot set data-link type: %s\n", argv[0], pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } if ( filter_iter->match != NULL ){ struct bpf_program bpf_prog; rval = pcap_compile (pcap_session[i].handle, &bpf_prog, filter_iter->match, 0, PCAP_NETMASK_UNKNOWN); if ( rval == -1 ){ fprintf (stderr, "%s: cannot compile the filter '%s' match rule: %s\n", argv[0], filter_iter->name, pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } rval = pcap_setfilter (pcap_session[i].handle, &bpf_prog); if ( rval == -1 ){ fprintf (stderr, "%s: cannot apply the filter '%s' on interface '%s': %s\n", argv[0], filter_iter->name, filter_iter->interface, pcap_geterr (pcap_session[i].handle)); exitno = EXIT_FAILURE; goto cleanup; } pcap_freecode (&bpf_prog); } pcap_session[i].fd = pcap_get_selectable_fd (pcap_session[i].handle); if ( pcap_session[i].fd == -1 ){ fprintf (stderr, "%s: cannot obtain file descriptor for packet capture interface '%s'\n", argv[0], filter_iter->interface); exitno = EXIT_FAILURE; goto cleanup; } } // We no longer need data stored in config structure. All neccessary data // were moved into session_data structure. config_unload (ðerpoke_conf); poll_fd = (struct pollfd*) malloc (sizeof (struct pollfd) * poll_len); if ( poll_fd == NULL ){ fprintf (stderr, "%s: cannot allocate memory: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } // Populate poll structure... for ( i = 0; i < poll_len; i++ ){ // ... with pcap file descriptors... if ( i < filter_cnt ) poll_fd[i].fd = pcap_session[i].fd; // ... listening socket... else if ( i == filter_cnt ) poll_fd[i].fd = sock; // ... invalid file descriptors (will be ignored by poll(2)), in space reserved for client sockets... else poll_fd[i].fd = -1; poll_fd[i].events = POLLIN | POLLERR; poll_fd[i].revents = 0; } // // Setup signal handler // sa.sa_handler = etherpoke_sigdie; sigemptyset (&(sa.sa_mask)); sa.sa_flags = 0; rval = 0; rval &= sigaction (SIGINT, &sa, NULL); rval &= sigaction (SIGQUIT, &sa, NULL); rval &= sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigemptyset (&(sa.sa_mask)); sa.sa_flags = 0; rval &= sigaction (SIGCHLD, &sa, NULL); if ( rval != 0 ){ fprintf (stderr, "%s: cannot setup signal handler: %s\n", argv[0], strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } // // Daemonize the process if the flag was set // if ( opt.daemon == 1 ){ pid = fork (); if ( pid > 0 ){ exitno = EXIT_SUCCESS; goto cleanup; } else if ( pid == -1 ){ fprintf (stderr, "%s: cannot daemonize the process (fork failed).\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } if ( setsid () == -1 ){ fprintf (stderr, "%s: cannot daemonize the process (setsid failed).\n", argv[0]); exitno = EXIT_FAILURE; goto cleanup; } umask (0); freopen ("/dev/null", "r", stdin); freopen ("/dev/null", "w", stdout); freopen ("/dev/null", "w", stderr); syslog_flags = LOG_PID; } openlog ("etherpoke", syslog_flags, LOG_DAEMON); syslog (LOG_INFO, "Etherpoke started (loaded filters: %u)", filter_cnt); if ( opt.tcp_event ) syslog (LOG_INFO, "Event notifications available via %s:%s (ACCEPT_MAX: %u)", opt.hostname, opt.port, opt.accept_max); // // Main loop // main_loop = 1; while ( main_loop ){ const u_char *pkt_data; struct pcap_pkthdr *pkt_header; time_t current_time; errno = 0; rval = poll (poll_fd, poll_len, SELECT_TIMEOUT_MS); if ( rval == -1 ){ if ( errno == EINTR ) continue; syslog (LOG_ERR, "poll(2) failed: %s", strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } #ifdef DBG_AVG_LOOP_SPEED clock_start = clock (); #endif // Accept incoming connection if ( poll_fd[filter_cnt].revents & POLLIN ){ int sock_new; sock_new = accept (sock, NULL, NULL); if ( sock_new == -1 ){ syslog (LOG_ERR, "cannot accept new connection: %s", strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } // Find unused place in the poll array for ( j = (filter_cnt + 1); j < poll_len; j++ ){ if ( poll_fd[j].fd == -1 ){ poll_fd[j].fd = sock_new; sock_new = -1; break; } } if ( sock_new != -1 ){ if ( opt.verbose ) syslog (LOG_INFO, "Client refused: too many concurrent connections"); close (sock_new); } else { if ( opt.verbose ) syslog (LOG_INFO, "Client connected..."); } } // Take care of incoming client data. At this point only shutdown and // close is handled, no other input is expected from the clients. for ( i = (filter_cnt + 1); i < poll_len; i++ ){ if ( poll_fd[i].revents & POLLIN ){ char nok[128]; errno = 0; rval = recv (poll_fd[i].fd, nok, sizeof (nok), MSG_DONTWAIT); if ( rval <= 0 && (errno != EAGAIN && errno != EWOULDBLOCK) ){ if ( opt.verbose ) syslog (LOG_INFO, "Client disconnected..."); close (poll_fd[i].fd); poll_fd[i].fd = -1; } } } time (¤t_time); // Handle changes on pcap file descriptors for ( i = 0; i < filter_cnt; i++ ){ wordexp_t *cmd_exp; const char *evt_str; // Handle incoming packet if ( (poll_fd[i].revents & POLLIN) || (poll_fd[i].revents & POLLERR) ){ rval = pcap_next_ex (pcap_session[i].handle, &pkt_header, &pkt_data); if ( rval == 1 ){ if ( pcap_session[i].evt.ts == 0 ) pcap_session[i].evt.type = SE_BEG; pcap_session[i].evt.ts = pkt_header->ts.tv_sec; } else if ( rval < 0 ){ pcap_session[i].evt.type = SE_ERR; } } if ( (pcap_session[i].evt.ts > 0) && (difftime (current_time, pcap_session[i].evt.ts) >= pcap_session[i].timeout) ){ pcap_session[i].evt.type = SE_END; } switch ( pcap_session[i].evt.type ){ case SE_NUL: // There was no change on this file descriptor, skip to // another one. 'continue' may seem a bit confusing here, // but it applies to a loop above. Not sure how other // compilers will behave (other than gcc). continue; case SE_BEG: evt_str = "BEG"; cmd_exp = &(pcap_session[i].evt_cmd_beg); pcap_session[i].evt.type = SE_NUL; break; case SE_END: cmd_exp = &(pcap_session[i].evt_cmd_end); evt_str = "END"; pcap_session[i].evt.type = SE_NUL; pcap_session[i].evt.ts = 0; break; case SE_ERR: evt_str = "ERR"; cmd_exp = &(pcap_session[i].evt_cmd_err); pcap_session[i].evt.type = SE_NUL; pcap_session[i].evt.ts = 0; break; default: // Undefined state... What to do, other than die? syslog (LOG_ERR, "undefined event type"); exitno = EXIT_FAILURE; goto cleanup; } if ( opt.verbose ) syslog (LOG_INFO, "%s:%s", pcap_session[i].filter_name, evt_str); // Send socket notification if ( pcap_session[i].evt_mask & NOTIFY_SOCK ){ char msg[CONF_FILTER_NAME_MAXLEN + 5]; snprintf (msg, sizeof (msg), "%s:%s", pcap_session[i].filter_name, evt_str); for ( j = (filter_cnt + 1); j < poll_len; j++ ){ if ( poll_fd[j].fd == -1 ) continue; errno = 0; rval = send (poll_fd[j].fd, msg, strlen (msg) + 1, MSG_NOSIGNAL | MSG_DONTWAIT); if ( rval == -1 && (errno != EAGAIN && errno != EWOULDBLOCK) ){ syslog (LOG_WARNING, "failed to send notification: %s", strerror (errno)); close (poll_fd[j].fd); poll_fd[j].fd = -1; } } } // Execute an event hook if ( pcap_session[i].evt_mask & NOTIFY_EXEC ){ // Expansion was not made... if ( cmd_exp->we_wordc == 0 ) continue; pid = fork (); if ( pid == -1 ){ syslog (LOG_ERR, "cannot fork the process: %s", strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } // Parent process, carry on... if ( pid > 0 ) continue; errno = 0; execv (cmd_exp->we_wordv[0], cmd_exp->we_wordv); // This code gets executed only if execv(3) fails. Wrapping // this code in a condition is unneccessary. syslog (LOG_WARNING, "cannot execute event hook in '%s': %s", pcap_session[i].filter_name, strerror (errno)); exitno = EXIT_FAILURE; goto cleanup; } } #ifdef DBG_AVG_LOOP_SPEED clock_avg = (clock_avg + (clock () - clock_start)) / 2; syslog (LOG_DEBUG, "Average loop speed: %lf", (double) (clock_avg / CLOCKS_PER_SEC)); #endif } syslog (LOG_INFO, "Etherpoke shutdown (signal %u)", exitno); cleanup: closelog (); if ( pcap_session != NULL ){ for ( i = 0; i < filter_cnt; i++ ) session_data_free (&(pcap_session[i])); free (pcap_session); } if ( poll_fd != NULL ) free (poll_fd); if ( sock != -1 ) close (sock); config_unload (ðerpoke_conf); path_free (&path_config); return exitno; }