static void dag_platform_cleanup(pcap_t *p) { struct pcap_dag *pd; if (p != NULL) { pd = p->priv; #ifdef HAVE_DAG_STREAMS_API if(dag_stop_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); if(dag_detach_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); #else if(dag_stop(p->fd) < 0) fprintf(stderr,"dag_stop: %s\n", strerror(errno)); #endif /* HAVE_DAG_STREAMS_API */ if(p->fd != -1) { if(dag_close(p->fd) < 0) fprintf(stderr,"dag_close: %s\n", strerror(errno)); p->fd = -1; } delete_pcap_dag(p); pcap_cleanup_live_common(p); } /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */ }
static void TcCleanup(pcap_t *p) { if (p->TcPacketsBuffer != NULL) { g_TcFunctions.PacketsBufferDestroy(p->TcPacketsBuffer); p->TcPacketsBuffer = NULL; } if (p->TcInstance != NULL) { /* * here we do not check for the error values */ g_TcFunctions.InstanceClose(p->TcInstance); p->TcInstance = NULL; } if (p->PpiPacket != NULL) { free(p->PpiPacket); p->PpiPacket = NULL; } pcap_cleanup_live_common(p); }
static void usb_cleanup_linux_mmap(pcap_t* handle) { /* buffer must not be freed because it's memory mapped */ /* XXX - does it need to be unmapped? */ handle->buffer = NULL; pcap_cleanup_live_common(handle); }
static void dbus_cleanup(pcap_t *handle) { struct pcap_dbus *handlep = handle->priv; dbus_connection_unref(handlep->conn); pcap_cleanup_live_common(handle); }
static void snf_platform_cleanup(pcap_t *p) { if (p == NULL) return; snf_ring_close(p->md.snf_ring); snf_close(p->md.snf_handle); pcap_cleanup_live_common(p); }
/* * Close dlpi handle. */ static void pcap_cleanup_libdlpi(pcap_t *p) { if (p->dlpi_hd != NULL) { dlpi_close(p->dlpi_hd); p->dlpi_hd = NULL; p->fd = -1; } pcap_cleanup_live_common(p); }
static void usb_cleanup_linux_mmap(pcap_t* handle) { /* if we have a memory-mapped buffer, unmap it */ if (handle->md.mmapbuf != NULL) { munmap(handle->md.mmapbuf, handle->md.mmapbuflen); handle->md.mmapbuf = NULL; } pcap_cleanup_live_common(handle); }
static void pcap_cleanup_acn(pcap_t *handle) { int chassis, geoslot; unit_t *u; if (find_unit_by_fd(handle->fd, &chassis, &geoslot, &u) == 0) return; close_with_IOP(chassis, geoslot, LIVE); if (u) u->first_time = 0; pcap_cleanup_live_common(handle); }
static void usb_cleanup_linux_mmap(pcap_t* handle) { struct pcap_usb_linux *handlep = handle->private; /* if we have a memory-mapped buffer, unmap it */ if (handlep->mmapbuf != NULL) { munmap(handlep->mmapbuf, handlep->mmapbuflen); handlep->mmapbuf = NULL; } pcap_cleanup_live_common(handle); }
/* * Close dlpi handle. */ static void pcap_cleanup_libdlpi(pcap_t *p) { struct pcap_dlpi *pd = p->priv; if (pd->dlpi_hd != NULL) { dlpi_close(pd->dlpi_hd); pd->dlpi_hd = NULL; p->fd = -1; } pcap_cleanup_live_common(p); }
static void snf_platform_cleanup(pcap_t *p) { struct pcap_snf *ps = p->priv; #ifdef SNF_HAVE_INJECT_API if (ps->snf_inj) snf_inject_close(ps->snf_inj); #endif snf_ring_close(ps->snf_ring); snf_close(ps->snf_handle); pcap_cleanup_live_common(p); }
static void snf_platform_cleanup(pcap_t *p) { struct pcap_snf *ps; if (p == NULL) return; ps = p->priv; snf_ring_close(ps->snf_ring); snf_close(ps->snf_handle); pcap_cleanup_live_common(p); }
static void pcap_cleanup_dlpi(pcap_t *p) { #ifdef DL_HP_RAWDLS struct pcap_dlpi *pd = p->priv; if (pd->send_fd >= 0) { close(pd->send_fd); pd->send_fd = -1; } #endif pcap_cleanup_live_common(p); }
static void rdmasniff_cleanup(pcap_t *handle) { struct pcap_rdmasniff *priv = handle->priv; ibv_dereg_mr(priv->mr); ibv_destroy_flow(priv->flow); ibv_destroy_qp(priv->qp); ibv_destroy_cq(priv->cq); ibv_dealloc_pd(priv->pd); ibv_destroy_comp_channel(priv->channel); ibv_close_device(priv->context); free(priv->oneshot_buffer); pcap_cleanup_live_common(handle); }
static void dag_platform_cleanup(pcap_t *p) { struct pcap_dag *pd = p->priv; if(dag_stop_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); if(dag_detach_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); if(pd->dag_ref != NULL) { dag_config_dispose(pd->dag_ref); p->fd = -1; pd->dag_ref = NULL; } delete_pcap_dag(p); pcap_cleanup_live_common(p); /* Note: don't need to call close(p->fd) or dag_close(p->fd) as dag_config_dispose(pd->dag_ref) does this. */ }
static void dag_platform_cleanup(pcap_t *p) { struct pcap_dag *pd = p->priv; if(dag_stop_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); if(dag_detach_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); if(p->fd != -1) { if(dag_close(p->fd) < 0) fprintf(stderr,"dag_close: %s\n", strerror(errno)); p->fd = -1; } delete_pcap_dag(p); pcap_cleanup_live_common(p); /* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */ }
static int pcap_activate_nit(pcap_t *p) { int fd; struct sockaddr_nit snit; if (p->opt.rfmon) { /* * No monitor mode on SunOS 3.x or earlier (no * Wi-Fi *devices* for the hardware that supported * them!). */ return (PCAP_ERROR_RFMON_NOTSUP); } /* * Turn a negative snapshot value (invalid), a snapshot value of * 0 (unspecified), or a value bigger than the normal maximum * value, into the maximum allowed value. * * If some application really *needs* a bigger snapshot * length, we should just increase MAXIMUM_SNAPLEN. */ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN) p->snapshot = MAXIMUM_SNAPLEN; if (p->snapshot < 96) /* * NIT requires a snapshot length of at least 96. */ p->snapshot = 96; memset(p, 0, sizeof(*p)); p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW); if (fd < 0) { pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "socket"); goto bad; } snit.snit_family = AF_NIT; (void)strncpy(snit.snit_ifname, p->opt.device, NITIFSIZ); if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) { /* * XXX - there's probably a particular bind error that * means "there's no such device" and a particular bind * error that means "that device doesn't support NIT"; * they might be the same error, if they both end up * meaning "NIT doesn't know about that device". */ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "bind: %s", snit.snit_ifname); goto bad; } if (nit_setflags(p) < 0) goto bad; /* * NIT supports only ethernets. */ p->linktype = DLT_EN10MB; p->bufsize = BUFSPACE; p->buffer = malloc(p->bufsize); if (p->buffer == NULL) { pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "malloc"); goto bad; } /* * "p->fd" is a socket, so "select()" should work on it. */ p->selectable_fd = p->fd; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } p->read_op = pcap_read_nit; p->inject_op = pcap_inject_nit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_nit; return (0); bad: pcap_cleanup_live_common(p); return (PCAP_ERROR); }
static int pcap_netmap_dispatch(pcap_t *p, int cnt, pcap_handler cb, u_char *user) { int ret; struct pcap_netmap *pn = NM_PRIV(p); struct nm_desc *d = pn->d; struct pollfd pfd = { .fd = p->fd, .events = POLLIN, .revents = 0 }; pn->cb = cb; pn->cb_arg = user; for (;;) { if (p->break_loop) { p->break_loop = 0; return PCAP_ERROR_BREAK; } /* nm_dispatch won't run forever */ ret = nm_dispatch((void *)d, cnt, (void *)pcap_netmap_filter, (void *)p); if (ret != 0) break; errno = 0; ret = poll(&pfd, 1, p->the_timeout); } return ret; } /* XXX need to check the NIOCTXSYNC/poll */ static int pcap_netmap_inject(pcap_t *p, const void *buf, size_t size) { struct nm_desc *d = NM_PRIV(p)->d; return nm_inject(d, buf, size); } static int pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags) { struct pcap_netmap *pn = NM_PRIV(p); struct nm_desc *d = pn->d; struct ifreq ifr; int error, fd = d->fd; #ifdef linux fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { fprintf(stderr, "Error: cannot get device control socket.\n"); return -1; } #endif /* linux */ bzero(&ifr, sizeof(ifr)); strncpy(ifr.ifr_name, d->req.nr_name, sizeof(ifr.ifr_name)); switch (what) { case SIOCSIFFLAGS: ifr.ifr_flags = *if_flags; #ifdef __FreeBSD__ ifr.ifr_flagshigh = *if_flags >> 16; #endif /* __FreeBSD__ */ break; } error = ioctl(fd, what, &ifr); if (!error) { switch (what) { case SIOCGIFFLAGS: *if_flags = ifr.ifr_flags; #ifdef __FreeBSD__ *if_flags |= (ifr.ifr_flagshigh << 16); #endif /* __FreeBSD__ */ } } #ifdef linux close(fd); #endif /* linux */ return error ? -1 : 0; } static void pcap_netmap_close(pcap_t *p) { struct pcap_netmap *pn = NM_PRIV(p); struct nm_desc *d = pn->d; uint32_t if_flags = 0; if (pn->must_clear_promisc) { pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */ if (if_flags & IFF_PPROMISC) { if_flags &= ~IFF_PPROMISC; pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags); } } nm_close(d); #ifdef HAVE_NO_PRIV free(pn); SET_PRIV(p, NULL); // unnecessary #endif pcap_cleanup_live_common(p); } static int pcap_netmap_activate(pcap_t *p) { struct pcap_netmap *pn = NM_PRIV(p); struct nm_desc *d = nm_open(p->opt.source, NULL, 0, NULL); uint32_t if_flags = 0; if (d == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "netmap open: cannot access %s: %s\n", p->opt.source, pcap_strerror(errno)); #ifdef HAVE_NO_PRIV free(pn); SET_PRIV(p, NULL); // unnecessary #endif pcap_cleanup_live_common(p); return (PCAP_ERROR); } if (0) fprintf(stderr, "%s device %s priv %p fd %d ports %d..%d\n", __FUNCTION__, p->opt.source, d, d->fd, d->first_rx_ring, d->last_rx_ring); pn->d = d; p->fd = d->fd; if (p->opt.promisc && !(d->req.nr_ringid & NETMAP_SW_RING)) { pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */ if (!(if_flags & IFF_PPROMISC)) { pn->must_clear_promisc = 1; if_flags |= IFF_PPROMISC; pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags); } } p->linktype = DLT_EN10MB; p->selectable_fd = p->fd; p->read_op = pcap_netmap_dispatch; p->inject_op = pcap_netmap_inject, p->setfilter_op = install_bpf_program; p->setdirection_op = NULL; p->set_datalink_op = NULL; p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_netmap_stats; p->cleanup_op = pcap_netmap_close; return (0); } pcap_t * pcap_netmap_create(const char *device, char *ebuf, int *is_ours) { pcap_t *p; *is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4)); if (! *is_ours) return NULL; #ifdef HAVE_NO_PRIV { void *pn = calloc(1, sizeof(struct pcap_netmap)); if (pn == NULL) return NULL; p = pcap_create_common(device, ebuf); if (p == NULL) { free(pn); return NULL; } SET_PRIV(p, pn); } #else p = pcap_create_common(device, ebuf, sizeof (struct pcap_netmap)); if (p == NULL) return (NULL); #endif p->activate_op = pcap_netmap_activate; return (p); }
static int pcap_activate_nit(pcap_t *p) { int fd; struct sockaddr_nit snit; if (p->opt.rfmon) { /* * No monitor mode on SunOS 3.x or earlier (no * Wi-Fi *devices* for the hardware that supported * them!). */ return (PCAP_ERROR_RFMON_NOTSUP); } if (p->snapshot < 96) /* * NIT requires a snapshot length of at least 96. */ p->snapshot = 96; memset(p, 0, sizeof(*p)); p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW); if (fd < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); goto bad; } snit.snit_family = AF_NIT; (void)strncpy(snit.snit_ifname, p->opt.source, NITIFSIZ); if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno)); goto bad; } if (nit_setflags(p) < 0) goto bad; /* * NIT supports only ethernets. */ p->linktype = DLT_EN10MB; p->bufsize = BUFSPACE; p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } /* * "p->fd" is a socket, so "select()" should work on it. */ p->selectable_fd = p->fd; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } p->read_op = pcap_read_nit; p->inject_op = pcap_inject_nit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_nit; return (0); bad: pcap_cleanup_live_common(p); return (PCAP_ERROR); }
static int bt_activate(pcap_t* handle) { struct pcap_bt *handlep = handle->priv; struct sockaddr_hci addr; int opt; int dev_id; struct hci_filter flt; int err = PCAP_ERROR; /* get bt interface id */ if (sscanf(handle->opt.source, BT_IFACE"%d", &dev_id) != 1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get Bluetooth device index from %s", handle->opt.source); return PCAP_ERROR; } /* Initialize some components of the pcap structure. */ handle->bufsize = handle->snapshot+BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header); handle->offset = BT_CTRL_SIZE; handle->linktype = DLT_BLUETOOTH_HCI_H4_WITH_PHDR; handle->read_op = bt_read_linux; handle->inject_op = bt_inject_linux; handle->setfilter_op = install_bpf_program; /* no kernel filtering */ handle->setdirection_op = bt_setdirection_linux; handle->set_datalink_op = NULL; /* can't change data link type */ handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = bt_stats_linux; handlep->dev_id = dev_id; /* Create HCI socket */ handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (handle->fd < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket: %s", strerror(errno)); return PCAP_ERROR; } handle->buffer = malloc(handle->bufsize); if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno)); goto close_fail; } opt = 1; if (setsockopt(handle->fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't enable data direction info: %s", strerror(errno)); goto close_fail; } opt = 1; if (setsockopt(handle->fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't enable time stamp: %s", strerror(errno)); goto close_fail; } /* Setup filter, do not call hci function to avoid dependence on * external libs */ memset(&flt, 0, sizeof(flt)); memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask)); memset((void *) &flt.event_mask, 0xff, sizeof(flt.event_mask)); if (setsockopt(handle->fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't set filter: %s", strerror(errno)); goto close_fail; } /* Bind socket to the HCI device */ addr.hci_family = AF_BLUETOOTH; addr.hci_dev = handlep->dev_id; #ifdef SOCKADDR_HCI_HAS_HCI_CHANNEL addr.hci_channel = HCI_CHANNEL_RAW; #endif if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d: %s", handlep->dev_id, strerror(errno)); goto close_fail; } if (handle->opt.rfmon) { /* * Monitor mode doesn't apply to Bluetooth devices. */ err = PCAP_ERROR_RFMON_NOTSUP; goto close_fail; } if (handle->opt.buffer_size != 0) { /* * Set the socket buffer size to the specified value. */ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno)); goto close_fail; } } handle->selectable_fd = handle->fd; return 0; close_fail: pcap_cleanup_live_common(handle); return err; }
static int bt_activate(pcap_t* handle) { struct pcap_bt *handlep = handle->priv; struct sockaddr_hci addr; int opt; int dev_id; struct hci_filter flt; int err = PCAP_ERROR; /* get bt interface id */ if (sscanf(handle->opt.device, BT_IFACE"%d", &dev_id) != 1) { pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get Bluetooth device index from %s", handle->opt.device); return PCAP_ERROR; } /* * Turn a negative snapshot value (invalid), a snapshot value of * 0 (unspecified), or a value bigger than the normal maximum * value, into the maximum allowed value. * * If some application really *needs* a bigger snapshot * length, we should just increase MAXIMUM_SNAPLEN. */ if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN) handle->snapshot = MAXIMUM_SNAPLEN; /* Initialize some components of the pcap structure. */ handle->bufsize = BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header)+handle->snapshot; handle->linktype = DLT_BLUETOOTH_HCI_H4_WITH_PHDR; handle->read_op = bt_read_linux; handle->inject_op = bt_inject_linux; handle->setfilter_op = install_bpf_program; /* no kernel filtering */ handle->setdirection_op = bt_setdirection_linux; handle->set_datalink_op = NULL; /* can't change data link type */ handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = bt_stats_linux; handlep->dev_id = dev_id; /* Create HCI socket */ handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (handle->fd < 0) { pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "Can't create raw socket"); return PCAP_ERROR; } handle->buffer = malloc(handle->bufsize); if (!handle->buffer) { pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "Can't allocate dump buffer"); goto close_fail; } opt = 1; if (setsockopt(handle->fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) { pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "Can't enable data direction info"); goto close_fail; } opt = 1; if (setsockopt(handle->fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) { pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "Can't enable time stamp"); goto close_fail; } /* Setup filter, do not call hci function to avoid dependence on * external libs */ memset(&flt, 0, sizeof(flt)); memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask)); memset((void *) &flt.event_mask, 0xff, sizeof(flt.event_mask)); if (setsockopt(handle->fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "Can't set filter"); goto close_fail; } /* Bind socket to the HCI device */ addr.hci_family = AF_BLUETOOTH; addr.hci_dev = handlep->dev_id; #ifdef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL addr.hci_channel = HCI_CHANNEL_RAW; #endif if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, errno, "Can't attach to device %d", handlep->dev_id); goto close_fail; } if (handle->opt.rfmon) { /* * Monitor mode doesn't apply to Bluetooth devices. */ err = PCAP_ERROR_RFMON_NOTSUP; goto close_fail; } if (handle->opt.buffer_size != 0) { /* * Set the socket buffer size to the specified value. */ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) { pcap_fmt_errmsg_for_errno(handle->errbuf, errno, PCAP_ERRBUF_SIZE, "SO_RCVBUF"); goto close_fail; } } handle->selectable_fd = handle->fd; return 0; close_fail: pcap_cleanup_live_common(handle); return err; }
static int pcap_netmap_dispatch(pcap_t *p, int cnt, pcap_handler cb, u_char *user) { int ret; struct pcap_netmap *pn = p->priv; struct nm_desc *d = pn->d; struct pollfd pfd = { .fd = p->fd, .events = POLLIN, .revents = 0 }; pn->cb = cb; pn->cb_arg = user; for (;;) { if (p->break_loop) { p->break_loop = 0; return PCAP_ERROR_BREAK; } /* nm_dispatch won't run forever */ ret = nm_dispatch((void *)d, cnt, (void *)pcap_netmap_filter, (void *)p); if (ret != 0) break; errno = 0; ret = poll(&pfd, 1, p->opt.timeout); } return ret; } /* XXX need to check the NIOCTXSYNC/poll */ static int pcap_netmap_inject(pcap_t *p, const void *buf, size_t size) { struct pcap_netmap *pn = p->priv; struct nm_desc *d = pn->d; return nm_inject(d, buf, size); } static int pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags) { struct pcap_netmap *pn = p->priv; struct nm_desc *d = pn->d; struct ifreq ifr; int error, fd = d->fd; #ifdef linux fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { fprintf(stderr, "Error: cannot get device control socket.\n"); return -1; } #endif /* linux */ bzero(&ifr, sizeof(ifr)); strncpy(ifr.ifr_name, d->req.nr_name, sizeof(ifr.ifr_name)); switch (what) { case SIOCSIFFLAGS: /* * The flags we pass in are 32-bit and unsigned. * * On most if not all UN*Xes, ifr_flags is 16-bit and * signed, and the result of assigning a longer * unsigned value to a shorter signed value is * implementation-defined (even if, in practice, it'll * do what's intended on all platforms we support * result of assigning a 32-bit unsigned value). * So we mask out the upper 16 bits. */ ifr.ifr_flags = *if_flags & 0xffff; #ifdef __FreeBSD__ /* * In FreeBSD, we need to set the high-order flags, * as we're using IFF_PPROMISC, which is in those bits. * * XXX - DragonFly BSD? */ ifr.ifr_flagshigh = *if_flags >> 16; #endif /* __FreeBSD__ */ break; } error = ioctl(fd, what, &ifr); if (!error) { switch (what) { case SIOCGIFFLAGS: /* * The flags we return are 32-bit. * * On most if not all UN*Xes, ifr_flags is * 16-bit and signed, and will get sign- * extended, so that the upper 16 bits of * those flags will be forced on. So we * mask out the upper 16 bits of the * sign-extended value. */ *if_flags = ifr.ifr_flags & 0xffff; #ifdef __FreeBSD__ /* * In FreeBSD, we need to return the * high-order flags, as we're using * IFF_PPROMISC, which is in those bits. * * XXX - DragonFly BSD? */ *if_flags |= (ifr.ifr_flagshigh << 16); #endif /* __FreeBSD__ */ } } #ifdef linux close(fd); #endif /* linux */ return error ? -1 : 0; } static void pcap_netmap_close(pcap_t *p) { struct pcap_netmap *pn = p->priv; struct nm_desc *d = pn->d; uint32_t if_flags = 0; if (pn->must_clear_promisc) { pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */ if (if_flags & IFF_PPROMISC) { if_flags &= ~IFF_PPROMISC; pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags); } } nm_close(d); pcap_cleanup_live_common(p); } static int pcap_netmap_activate(pcap_t *p) { struct pcap_netmap *pn = p->priv; struct nm_desc *d; uint32_t if_flags = 0; d = nm_open(p->opt.device, NULL, 0, NULL); if (d == NULL) { pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "netmap open: cannot access %s", p->opt.device); pcap_cleanup_live_common(p); return (PCAP_ERROR); } if (0) fprintf(stderr, "%s device %s priv %p fd %d ports %d..%d\n", __FUNCTION__, p->opt.device, d, d->fd, d->first_rx_ring, d->last_rx_ring); pn->d = d; p->fd = d->fd; /* * Turn a negative snapshot value (invalid), a snapshot value of * 0 (unspecified), or a value bigger than the normal maximum * value, into the maximum allowed value. * * If some application really *needs* a bigger snapshot * length, we should just increase MAXIMUM_SNAPLEN. */ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN) p->snapshot = MAXIMUM_SNAPLEN; if (p->opt.promisc && !(d->req.nr_ringid & NETMAP_SW_RING)) { pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */ if (!(if_flags & IFF_PPROMISC)) { pn->must_clear_promisc = 1; if_flags |= IFF_PPROMISC; pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags); } } p->linktype = DLT_EN10MB; p->selectable_fd = p->fd; p->read_op = pcap_netmap_dispatch; p->inject_op = pcap_netmap_inject, p->setfilter_op = install_bpf_program; p->setdirection_op = NULL; p->set_datalink_op = NULL; p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_netmap_stats; p->cleanup_op = pcap_netmap_close; return (0); } pcap_t * pcap_netmap_create(const char *device, char *ebuf, int *is_ours) { pcap_t *p; *is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4)); if (! *is_ours) return NULL; p = pcap_create_common(ebuf, sizeof (struct pcap_netmap)); if (p == NULL) return (NULL); p->activate_op = pcap_netmap_activate; return (p); }
static int can_activate(pcap_t* handle) { struct pcap_can *handlep = handle->priv; struct sockaddr_can addr; struct ifreq ifr; /* Initialize some components of the pcap structure. */ handle->bufsize = CAN_CONTROL_SIZE + 16; handle->linktype = DLT_CAN_SOCKETCAN; handle->read_op = can_read_linux; handle->inject_op = can_inject_linux; handle->setfilter_op = can_setfilter_linux; handle->setdirection_op = can_setdirection_linux; handle->set_datalink_op = NULL; handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = can_stats_linux; /* Create socket */ handle->fd = socket(PF_CAN, SOCK_RAW, CAN_RAW); if (handle->fd < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s", errno, strerror(errno)); return PCAP_ERROR; } /* get interface index */ memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFINDEX, &ifr) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Unable to get interface index: %s", pcap_strerror(errno)); pcap_cleanup_live_common(handle); return PCAP_ERROR; } handlep->ifindex = ifr.ifr_ifindex; /* allocate butter */ handle->buffer = malloc(handle->bufsize); if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s", pcap_strerror(errno)); pcap_cleanup_live_common(handle); return PCAP_ERROR; } /* Bind to the socket */ addr.can_family = AF_CAN; addr.can_ifindex = handlep->ifindex; if( bind( handle->fd, (struct sockaddr*)&addr, sizeof(addr) ) < 0 ) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s", handlep->ifindex, errno, strerror(errno)); pcap_cleanup_live_common(handle); return PCAP_ERROR; } if (handle->opt.rfmon) { /* Monitor mode doesn't apply to CAN devices. */ pcap_cleanup_live_common(handle); return PCAP_ERROR_RFMON_NOTSUP; } handle->selectable_fd = handle->fd; return 0; }
static int pcap_activate_snit(pcap_t *p) { struct strioctl si; /* struct for ioctl() */ struct ifreq ifr; /* interface request struct */ int chunksize = CHUNKSIZE; int fd; static char dev[] = "/dev/nit"; if (p->opt.rfmon) { /* * No monitor mode on SunOS 4.x (no Wi-Fi devices on * hardware supported by SunOS 4.x). */ return (PCAP_ERROR_RFMON_NOTSUP); } if (p->snapshot < 96) /* * NIT requires a snapshot length of at least 96. */ p->snapshot = 96; /* * Initially try a read/write open (to allow the inject * method to work). If that fails due to permission * issues, fall back to read-only. This allows a * non-root user to be granted specific access to pcap * capabilities via file permissions. * * XXX - we should have an API that has a flag that * controls whether to open read-only or read-write, * so that denial of permission to send (or inability * to send, if sending packets isn't supported on * the device in question) can be indicated at open * time. */ p->fd = fd = open(dev, O_RDWR); if (fd < 0 && errno == EACCES) p->fd = fd = open(dev, O_RDONLY); if (fd < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev, pcap_strerror(errno)); goto bad; } /* arrange to get discrete messages from the STREAM and use NIT_BUF */ if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s", pcap_strerror(errno)); goto bad; } if (ioctl(fd, I_PUSH, "nbuf") < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s", pcap_strerror(errno)); goto bad; } /* set the chunksize */ si.ic_cmd = NIOCSCHUNK; si.ic_timout = INFTIM; si.ic_len = sizeof(chunksize); si.ic_dp = (char *)&chunksize; if (ioctl(fd, I_STR, (char *)&si) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s", pcap_strerror(errno)); goto bad; } /* request the interface */ strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; si.ic_cmd = NIOCBIND; si.ic_len = sizeof(ifr); si.ic_dp = (char *)𝔦 if (ioctl(fd, I_STR, (char *)&si) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s", ifr.ifr_name, pcap_strerror(errno)); goto bad; } /* set the snapshot length */ si.ic_cmd = NIOCSSNAP; si.ic_len = sizeof(p->snapshot); si.ic_dp = (char *)&p->snapshot; if (ioctl(fd, I_STR, (char *)&si) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s", pcap_strerror(errno)); goto bad; } if (nit_setflags(p) < 0) goto bad; (void)ioctl(fd, I_FLUSH, (char *)FLUSHR); /* * NIT supports only ethernets. */ p->linktype = DLT_EN10MB; p->bufsize = BUFSPACE; p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); goto bad; } /* * "p->fd" is an FD for a STREAMS device, so "select()" and * "poll()" should work on it. */ p->selectable_fd = p->fd; /* * This is (presumably) a real Ethernet capture; give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem * Termination System is putting out onto an Ethernet (it * doesn't put an Ethernet header onto the wire, it puts raw * DOCSIS frames out on the wire inside the low-level * Ethernet framing). */ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); /* * If that fails, just leave the list empty. */ if (p->dlt_list != NULL) { p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2; } p->read_op = pcap_read_snit; p->inject_op = pcap_inject_snit; p->setfilter_op = install_bpf_program; /* no kernel filtering */ p->setdirection_op = NULL; /* Not implemented. */ p->set_datalink_op = NULL; /* can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_snit; return (0); bad: pcap_cleanup_live_common(p); return (PCAP_ERROR); }