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 Interface::setdirection(pcap_direction_t d) { return pcap_setdirection(handle, d); }
/* The pcap capture routine. */ int pcap_capture(fko_srv_options_t *opts) { pcap_t *pcap; char errstr[PCAP_ERRBUF_SIZE] = {0}; struct bpf_program fp; int res; int pcap_errcnt = 0; int pending_break = 0; int promisc = 0; int set_direction = 1; int pcap_file_mode = 0; int status; int useconds; int pcap_dispatch_count; int max_sniff_bytes; int is_err; pid_t child_pid; #if FIREWALL_IPFW time_t now; #endif useconds = strtol_wrapper(opts->config[CONF_PCAP_LOOP_SLEEP], 0, RCHK_MAX_PCAP_LOOP_SLEEP, NO_EXIT_UPON_ERR, &is_err); if(is_err != FKO_SUCCESS) { log_msg(LOG_ERR, "[*] invalid PCAP_LOOP_SLEEP_value"); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } max_sniff_bytes = strtol_wrapper(opts->config[CONF_MAX_SNIFF_BYTES], 0, RCHK_MAX_SNIFF_BYTES, NO_EXIT_UPON_ERR, &is_err); if(is_err != FKO_SUCCESS) { log_msg(LOG_ERR, "[*] invalid MAX_SNIFF_BYTES"); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } /* Set promiscuous mode if ENABLE_PCAP_PROMISC is set to 'Y'. */ if(strncasecmp(opts->config[CONF_ENABLE_PCAP_PROMISC], "Y", 1) == 0) promisc = 1; if(opts->config[CONF_PCAP_FILE] != NULL && opts->config[CONF_PCAP_FILE][0] != '\0') pcap_file_mode = 1; if(pcap_file_mode == 1) { log_msg(LOG_INFO, "Reading pcap file: %s", opts->config[CONF_PCAP_FILE]); pcap = pcap_open_offline(opts->config[CONF_PCAP_FILE], errstr); if(pcap == NULL) { log_msg(LOG_ERR, "[*] pcap_open_offline() error: %s", errstr); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } } else { log_msg(LOG_INFO, "Sniffing interface: %s", opts->config[CONF_PCAP_INTF]); pcap = pcap_open_live(opts->config[CONF_PCAP_INTF], max_sniff_bytes, promisc, 100, errstr ); if(pcap == NULL) { log_msg(LOG_ERR, "[*] pcap_open_live() error: %s", errstr); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } } /* Set pcap filters, if any. */ if (opts->config[CONF_PCAP_FILTER][0] != '\0') { if(pcap_compile(pcap, &fp, opts->config[CONF_PCAP_FILTER], 1, 0) == -1) { log_msg(LOG_ERR, "[*] Error compiling pcap filter: %s", pcap_geterr(pcap) ); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } if(pcap_setfilter(pcap, &fp) == -1) { log_msg(LOG_ERR, "[*] Error setting pcap filter: %s", pcap_geterr(pcap) ); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } log_msg(LOG_INFO, "PCAP filter is: '%s'", opts->config[CONF_PCAP_FILTER]); pcap_freecode(&fp); } /* Determine and set the data link encapsulation offset. */ switch(pcap_datalink(pcap)) { case DLT_EN10MB: opts->data_link_offset = 14; break; #if defined(__linux__) case DLT_LINUX_SLL: opts->data_link_offset = 16; break; #elif defined(__OpenBSD__) case DLT_LOOP: set_direction = 0; opts->data_link_offset = 4; break; #endif case DLT_NULL: set_direction = 0; opts->data_link_offset = 4; break; default: opts->data_link_offset = 0; break; } /* We are only interested on seeing packets coming into the interface. */ if ((opts->pcap_any_direction == 0) && (set_direction == 1) && (pcap_file_mode == 0) && (pcap_setdirection(pcap, PCAP_D_IN) < 0)) if(opts->verbose) log_msg(LOG_WARNING, "[*] Warning: pcap error on setdirection: %s.", pcap_geterr(pcap)); /* Set our pcap handle nonblocking mode. * * NOTE: This is simply set to 0 for now until we find a need * to actually use this mode (which when set on a FreeBSD * system, it silently breaks the packet capture). */ if((pcap_file_mode == 0) && (pcap_setnonblock(pcap, DEF_PCAP_NONBLOCK, errstr)) == -1) { log_msg(LOG_ERR, "[*] Error setting pcap nonblocking to %i: %s", 0, errstr ); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } pcap_dispatch_count = strtol_wrapper(opts->config[CONF_PCAP_DISPATCH_COUNT], 0, RCHK_MAX_PCAP_DISPATCH_COUNT, NO_EXIT_UPON_ERR, &is_err); if(is_err != FKO_SUCCESS) { log_msg(LOG_ERR, "[*] invalid PCAP_DISPATCH_COUNT"); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } /* Initialize our signal handlers. You can check the return value for * the number of signals that were *not* set. Those that were not set * will be listed in the log/stderr output. */ if(set_sig_handlers() > 0) log_msg(LOG_ERR, "Errors encountered when setting signal handlers."); log_msg(LOG_INFO, "Starting fwknopd main event loop."); /* Jump into our home-grown packet cature loop. */ while(1) { /* If we got a SIGCHLD and it was the tcp server, then handle it here. */ if(got_sigchld) { if(opts->tcp_server_pid > 0) { child_pid = waitpid(0, &status, WNOHANG); if(child_pid == opts->tcp_server_pid) { if(WIFSIGNALED(status)) log_msg(LOG_WARNING, "TCP server got signal: %i", WTERMSIG(status)); log_msg(LOG_WARNING, "TCP server exited with status of %i. Attempting restart.", WEXITSTATUS(status) ); opts->tcp_server_pid = 0; /* Attempt to restart tcp server ? */ usleep(1000000); run_tcp_server(opts); } } got_sigchld = 0; } /* Any signal except USR1, USR2, and SIGCHLD mean break the loop. */ if(got_signal != 0) { if(got_sigint || got_sigterm || got_sighup) { pcap_breakloop(pcap); pending_break = 1; } else if(got_sigusr1 || got_sigusr2) { /* Not doing anything with these yet. */ got_sigusr1 = got_sigusr2 = 0; got_signal = 0; } else got_signal = 0; } res = pcap_dispatch(pcap, pcap_dispatch_count, (pcap_handler)&process_packet, (unsigned char *)opts); /* Count processed packets */ if(res > 0) { if(opts->foreground == 1 && opts->verbose > 2) log_msg(LOG_DEBUG, "pcap_dispatch() processed: %d packets", res); /* Count the set of processed packets (pcap_dispatch() return * value) - we use this as a comparison for --packet-limit regardless * of SPA packet validity at this point. */ opts->packet_ctr += res; if (opts->packet_ctr_limit && opts->packet_ctr >= opts->packet_ctr_limit) { log_msg(LOG_WARNING, "* Incoming packet count limit of %i reached", opts->packet_ctr_limit ); pcap_breakloop(pcap); pending_break = 1; } } /* If there was an error, complain and go on (to an extent before * giving up). */ else if(res == -1) { log_msg(LOG_ERR, "[*] Error from pcap_dispatch: %s", pcap_geterr(pcap) ); if(pcap_errcnt++ > MAX_PCAP_ERRORS_BEFORE_BAIL) { log_msg(LOG_ERR, "[*] %i consecutive pcap errors. Giving up", pcap_errcnt ); clean_exit(opts, FW_CLEANUP, EXIT_FAILURE); } } else if(pending_break == 1 || res == -2) { /* pcap_breakloop was called, so we bail. */ log_msg(LOG_INFO, "Gracefully leaving the fwknopd event loop."); break; } else pcap_errcnt = 0; /* Check for any expired firewall rules and deal with them. */ check_firewall_rules(opts); #if FIREWALL_IPFW /* Purge expired rules that no longer have any corresponding * dynamic rules. */ if(opts->fw_config->total_rules > 0) { time(&now); if(opts->fw_config->last_purge < (now - opts->fw_config->purge_interval)) { ipfw_purge_expired_rules(opts); opts->fw_config->last_purge = now; } } #endif usleep(useconds); } pcap_close(pcap); return(0); }
static void packet_socket_setup(struct packet_socket *psock) { int bpf_fd = -1, val = -1; DEBUGP("calling pcap_create() with %s\n", psock->name); psock->pcap_in = pcap_create(psock->name, psock->pcap_error); if (psock->pcap_in == NULL) die_pcap_perror(psock->pcap_in, "pcap_create"); psock->pcap_out = pcap_create(psock->name, psock->pcap_error); if (psock->pcap_out == NULL) die_pcap_perror(psock->pcap_out, "pcap_create"); if (pcap_set_snaplen(psock->pcap_in, PACKET_READ_BYTES) != 0) die_pcap_perror(psock->pcap_in, "pcap_set_snaplen"); if (pcap_set_snaplen(psock->pcap_out, PACKET_READ_BYTES) != 0) die_pcap_perror(psock->pcap_out, "pcap_set_snaplen"); if (pcap_activate(psock->pcap_in) != 0) die_pcap_perror(psock->pcap_in, "pcap_activate " "(OpenBSD: another process (tcpdump?) " "using bpf0?)"); if (pcap_activate(psock->pcap_out) != 0) die_pcap_perror(psock->pcap_out, "pcap_activate " "(OpenBSD: another process (tcpdump?) " "using bpf0?)"); if (pcap_setdirection(psock->pcap_in, PCAP_D_IN) != 0) die_pcap_perror(psock->pcap_in, "pcap_setdirection"); if (pcap_setdirection(psock->pcap_out, PCAP_D_OUT) != 0) die_pcap_perror(psock->pcap_out, "pcap_setdirection"); bpf_fd = pcap_get_selectable_fd(psock->pcap_in); if (bpf_fd < 0) die_pcap_perror(psock->pcap_in, "pcap_get_selectable_fd"); /* By default libpcap with BPF waits until a read buffer fills * up before returning any packets. We use BIOCIMMEDIATE to * force the BPF device to return the first packet * immediately. */ val = 1; if (ioctl(bpf_fd, BIOCIMMEDIATE, &val) < 0) die_perror("ioctl BIOCIMMEDIATE on bpf fd"); bpf_fd = pcap_get_selectable_fd(psock->pcap_out); if (bpf_fd < 0) die_pcap_perror(psock->pcap_out, "pcap_get_selectable_fd"); /* By default libpcap with BPF waits until a read buffer fills * up before returning any packets. We use BIOCIMMEDIATE to * force the BPF device to return the first packet * immediately. */ val = 1; if (ioctl(bpf_fd, BIOCIMMEDIATE, &val) < 0) die_perror("ioctl BIOCIMMEDIATE on bpf fd"); /* Find data link type. */ psock->data_link = pcap_datalink(psock->pcap_in); DEBUGP("data_link: %d\n", psock->data_link); /* Based on the data_link type, calculate the offset of the * packet data in the buffer. */ switch (psock->data_link) { case DLT_EN10MB: psock->pcap_offset = sizeof(struct ether_header); break; case DLT_LOOP: case DLT_NULL: psock->pcap_offset = sizeof(u32); break; default: die("Unknown data_link type %d\n", psock->data_link); break; } }
ochannel & ochannel::Open () { #if defined (__linux__) struct ifreq ifreq; struct sockaddr_ll sockaddr_ll = { PF_PACKET, 0x0000, 0x0000, ARPHRD_ETHER, PACKET_OTHERHOST, ETHER_ADDR_LEN, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; std::memset (& ifreq, 0, sizeof (ifreq)); std::memcpy (ifreq.ifr_name, ointerface::Name (), sizeof (ifreq.ifr_name)); if ((this->mfd = socket (sockaddr_ll.sll_family, SOCK_RAW, oethernet::Protocol ())) == -1) { oerror::error (1, errno, "%s", ointerface::Name ()); } if (bind (this->mfd, (struct sockaddr *) (& sockaddr_ll), sizeof (sockaddr_ll)) == -1) { oerror::error (1, errno, "Can't bind socket to %s", ifreq.ifr_name); } #if 1 if (ioctl (this->mfd, SIOCGIFFLAGS, & ifreq) == -1) { oerror::error (1, errno, "%s", ifreq.ifr_name); } ifreq.ifr_flags |= (IFF_UP | IFF_BROADCAST | IFF_MULTICAST); ifreq.ifr_flags &= ~IFF_ALLMULTI; if (ioctl (this->mfd, SIOCSIFFLAGS, & ifreq) == -1) { oerror::error (1, errno, "%s", ifreq.ifr_name); } #endif #elif defined (__APPLE__) struct ifreq ifreq; struct timeval timer = { 0, 0 }; static struct bpf_insn bpf_insn [] = { { BPF_LD+ BPF_H + BPF_ABS, 0, 0, 12 }, { BPF_JMP+ BPF_JEQ + BPF_K, 0, 13, ntohs (oCHANNEL_ETHERTYPE) }, { BPF_LD+ BPF_B+BPF_ABS, 0, 0, 0 }, { BPF_JMP+ BPF_JEQ+BPF_K, 0, 11, 0 }, { BPF_LD+ BPF_B+BPF_ABS, 0, 0, 1 }, { BPF_JMP+ BPF_JEQ+BPF_K, 0, 9, 0 }, { BPF_LD+ BPF_B+BPF_ABS, 0, 0, 2 }, { BPF_JMP+ BPF_JEQ+BPF_K, 0, 7, 0 }, { BPF_LD+ BPF_B+BPF_ABS, 0, 0, 3 }, { BPF_JMP+ BPF_JEQ+BPF_K, 0, 5, 0 }, { BPF_LD+ BPF_B+BPF_ABS, 0, 0, 4 }, { BPF_JMP+ BPF_JEQ+BPF_K, 0, 3, 0 }, { BPF_LD+ BPF_B+BPF_ABS, 0, 0, 5 }, { BPF_JMP+ BPF_JEQ+BPF_K, 0, 1, 0 }, { BPF_RET+ BPF_K, 0, 0, 4096 }, { BPF_RET+ BPF_K, 0, 0, 0 } }; struct bpf_program bpf_program; char filename [sizeof (oCHANNEL_BPFDEVICE)]; const uint8_t * hostaddr = ointerface::HostAddress (); unsigned count; unsigned state; for (count = 0; count < 100; count++) { std::snprintf (filename, sizeof (filename), oCHANNEL_BPFDEVICE, count); if ((this->mfd =::open (filename, O_RDWR)) != -1) { break; } } if (this->mfd == -1) { oerror::error (1, ECANCELED, "No bpf counts available"); } std::memcpy (ifreq.ifr_name, this->mname, sizeof (ifreq.ifr_name)); if (ioctl (this->mfd, BIOCSETIF, & ifreq) == -1) { oerror::error (1, errno, "%s", ifreq.ifr_name); } if (ioctl (this->mfd, BIOCGBLEN, & this->bpf_length) == -1) { oerror::error (1, errno, "Can't determine buffer length"); } state = true; if (ioctl (this->mfd, BIOCIMMEDIATE, & state) == -1) { oerror::error (1, errno, "Can't activate immediate mode"); } state = false; if (ioctl (this->mfd, BIOCSSEESENT, & state) == -1) { oerror::error (1, errno, "Can't hide outgoing frames"); } timer.tv_usec = this->mtimer * 1000; if (ioctl (this->mfd, BIOCSRTIMEOUT, & timer) == -1) { oerror::error (1, errno, "Can't set timeout"); } bpf_insn [3].k = hostaddr [0]; bpf_insn [5].k = hostaddr [1]; bpf_insn [7].k = hostaddr [2]; bpf_insn [9].k = hostaddr [3]; bpf_insn [11].k = hostaddr [4]; bpf_insn [13].k = hostaddr [5]; bpf_program.bf_len = sizeof (bpf_program)/sizeof (struct bpf_insn); bpf_program.bf_insns = bpf_insn; if (ioctl (this->mfd, BIOCSETF, & bpf_program) == -1) { oerror::error (1, errno, "Can't use filter program"); } #elif defined (__OpenBSD__) struct ifreq ifreq; std::memset (& ifreq, 0, sizeof (ifreq)); if ((this->mfd = std::socket (sockaddr->sdl_family, SOCK_RAW, oethernet::Protocol ())) == -1) { oerror::error (1, errno, "%s", ointerface::Name ()); } std::memcpy (ifreq.ifr_name, interface, sizeof (ifreq.ifr_name)); #if 0 if (ioctl (this->mfd, SIOCGIFINDEX, & ifreq) == -1) { oerror::error (1, errno, "%s", ifreq.ifr_name); } sockaddr->sdl_ifindex = ifreq.ifr_ifindex; if (ioctl (this->mfd, OSIOCGIFADDR, & ifreq) == -1) { oerror::error (1, errno, "%s", ifreq.ifr_name); } std::memcpy (sockaddr->sdl_data, ifreq.ifr_ifru.ifru_addr.sa_data, sizeof (sockaddr->sdl_data)); if (std::bind (this->mfd, (struct sockaddr *) (sockaddr), sizeof (struct sockaddr_dl)) == -1) { oerror::error (1, errno, "Can't bind socket to %s", interface); } #endif if (ioctl (this->mfd, SIOCGIFFLAGS, & ifreq) == -1) { oerror::error (1, errno, "Can't read state of %s", ifreq.ifr_name); } if (!(ifreq.ifr_flags & IFF_UP)) { ifreq.ifr_flags |= IFF_UP; ifreq.ifr_flags |= IFF_BROADCAST; ifreq.ifr_flags |= IFF_MULTICAST; ifreq.ifr_flags &= ~IFF_ALLMULTI; if (ioctl (this->mfd, SIOCSIFFLAGS, & ifreq) == -1) { oerror::error (1, errno, "Can't save state of %s", ifreq.ifr_name); } } #elif defined (WINPCAP) struct bpf_program bpf_program; this->msocket = pcap_open_live (ointerface::Name (), 65536, 0, this->mtimer, this->merrbuf); if (!this->msocket) { oerror::error (1, errno, "can't open adaptor: %s", ointerface::Name ()); } _snprintf (this->mfilter, sizeof (this->mfilter), "ether proto 0x%04x and not ether src %s", oethernet::Protocol (), ointerface::HardwareAddressString ()); if (pcap_compile (this->msocket, & bpf_program, this->mfilter, 1, 0xffffff) < 0) { oerror::error (1, errno, "Can't compile pcap filter: %s", ointerface::Name); } if (pcap_setfilter (this->msocket, & bpf_program) < 0) { oerror::error (1, errno, "Can't install pcap filter: %s", ointerface::Name ()); } if (pcap_setmintocopy (this->msocket, ETHER_MAX_LEN)) { oerror::error (1, errno, "Can't set minimum data: %s", ointerface::Name ()); } #if 0 if (pcap_setdirection (this->msocket, PCAP_D_IN)) { oerror::error (1, errno, "Can't set packet direction: %s", ointerface::Name ()); } #endif #else #error "Unknown Environment." #endif return (* this); }
void sniff(char *in_if, char *out_if, char *in_file, char *out_file, TableStateMachine *machine, int num_workers, int no_report, int batch) { pcap_t *hpcap[2]; char errbuf[PCAP_ERRBUF_SIZE]; char *device_in = NULL, *device_out = NULL; pcap_if_t *devices, *next_device; int res; struct bpf_program bpf; ProcessorData *processor; int linktype[2], linkHdrLen, i; char *mode; memset(errbuf, 0, PCAP_ERRBUF_SIZE); if (in_if || out_if) { // Find available interfaces if (pcap_findalldevs(&devices, errbuf)) { fprintf(stderr, "[Sniffer] ERROR: Cannot find network interface (pcap_findalldevs error: %s)\n", errbuf); exit(1); } // Find requested interface next_device = devices; while (next_device) { printf("[Sniffer] Found network interface: %s\n", next_device->name); if (in_if && (strcmp(in_if, next_device->name) == 0)) { device_in = in_if; } if (out_if && (strcmp(out_if, next_device->name) == 0)) { device_out = out_if; } next_device = next_device->next; } pcap_freealldevs(devices); if (in_if && (strcmp(in_if, STR_ANY) == 0)) { device_in = STR_ANY; } if (in_if && !device_in) { fprintf(stderr, "[Sniffer] ERROR: Cannot find input network interface\n"); exit(1); } if (out_if && !device_out) { fprintf(stderr, "[Sniffer] ERROR: Cannot find output network interface\n"); exit(1); } } if (in_if) { printf("[Sniffer] Sniffer is capturing from device: %s\n", device_in); } else { printf("[Sniffer] Sniffer is reading packets from file: %s\n", in_file); } if (out_if) { printf("[Sniffer] Packets are sent on device: %s\n", device_out); } else { printf("[Sniffer] Packets written to file: %s\n", out_file); } if (in_if) { hpcap[0] = pcap_create(device_in, errbuf); } else { hpcap[0] = pcap_open_offline(in_file, errbuf); } if (out_if) { hpcap[1] = pcap_create(device_out, errbuf); } else { //hpcap[1] = pcap_dump_fopen(out_file, errbuf); } for (i = 0; i < 2; i++) { mode = (i == 0) ? "input" : "output"; // Check pcap handle if (!hpcap[i]) { fprintf(stderr, "[Sniffer] ERROR: Cannot create %s pcap handle (pcap_create/pcap_open_offline error: %s)\n", mode ,errbuf); exit(1); } if (in_if && i == 0) { // Set promiscuous mode pcap_set_promisc(hpcap[0], 1); } // Activate PCAP if ((in_if && i == 0) || (out_if && i == 1)) { res = pcap_activate(hpcap[i]); switch (res) { case 0: // Success break; case PCAP_WARNING_PROMISC_NOTSUP: fprintf(stderr, "[Sniffer] WARNING: Promiscuous mode is not supported\n"); exit(1); break; case PCAP_WARNING: fprintf(stderr, "[Sniffer] WARNING: Unknown (%s)\n", pcap_geterr(hpcap[i])); exit(1); break; case PCAP_ERROR_NO_SUCH_DEVICE: fprintf(stderr, "[Sniffer] ERROR: Device not found\n"); exit(1); break; case PCAP_ERROR_PERM_DENIED: fprintf(stderr, "[Sniffer] ERROR: Permission denied\n"); exit(1); break; case PCAP_ERROR_PROMISC_PERM_DENIED: fprintf(stderr, "[Sniffer] ERROR: Permission denied for promiscuous mode\n"); exit(1); break; case PCAP_ERROR_RFMON_NOTSUP: fprintf(stderr, "[Sniffer] ERROR: Monitor mode is not supported\n"); exit(1); break; case PCAP_ERROR_IFACE_NOT_UP: fprintf(stderr, "[Sniffer] ERROR: Interface %s is not available\n", (i == 0) ? device_in : device_out); exit(1); break; default: fprintf(stderr, "[Sniffer] ERROR: Unknown (%s)\n", pcap_geterr(hpcap[i])); exit(1); break; } } if (i == 0) { if (in_if) { // Set capture direction (ingress only) res = pcap_setdirection(hpcap[0], PCAP_D_IN); if (res) { fprintf(stderr, "[Sniffer] ERROR: Cannot set capture direction (pcap_setdirection error: %s, return value: %d)\n", pcap_geterr(hpcap[0]), res); exit(1); } } // Compile PCAP filter (IP packets) res = pcap_compile(hpcap[0], &bpf, STR_FILTER, 0, PCAP_NETMASK_UNKNOWN); if (res) { fprintf(stderr, "[Sniffer] ERROR: Cannot compile packet filter (pcap_compile error: %s)\n", pcap_geterr(hpcap[0])); exit(1); } res = pcap_setfilter(hpcap[0], &bpf); if (res) { fprintf(stderr, "[Sniffer] ERROR: Cannot set packet filter (pcap_setfilter error: %s, return value: %d)\n", pcap_geterr(hpcap[0]), res); exit(1); } pcap_freecode(&bpf); } // Find data link type if ((linktype[i] = pcap_datalink(hpcap[i])) < 0) { fprintf(stderr, "[Sniffer] Cannot determine data link type (pcap_datalink error: %s)\n", pcap_geterr(hpcap[i])); exit(1); } if (i == 1 && linktype[0] != linktype[1]) { fprintf(stderr, "[Sniffer] Incompatible link types (input=%d, output=%d)\n", linktype[0], linktype[1]); exit(1); } } linkHdrLen = 0; switch (linktype[0]) { case DLT_NULL: linkHdrLen = 4; break; case DLT_EN10MB: linkHdrLen = 14; break; case DLT_SLIP: case DLT_PPP: linkHdrLen = 24; break; default: fprintf(stderr, "[Sniffer] Unsupported data link type: %d\n", linktype[0]); exit(1); } // Prepare processor processor = init_processor(machine, hpcap[0], hpcap[1], linkHdrLen, num_workers, no_report, batch); _global_processor = processor; // Set signal handler signal(SIGINT, stop); signal(SIGTERM, stop); signal(SIGQUIT, stop); // Run sniffer gettimeofday(&(processor->start), NULL); printf("[Sniffer] Sniffer is running (input: %s, outout: %s)...\n", in_if, out_if); res = pcap_loop(hpcap[0], -1, process_packet, (unsigned char *)(processor)); stop(res); }
bool BaseSniffer::set_direction(pcap_direction_t d) { bool result = pcap_setdirection(handle, d) != -1; return result; }
inline void set_capture_direction(pcap_t *source, const capture_direction &dir) { if (pcap_setdirection(source, static_cast<pcap_direction_t>(dir)) != 0) { throw error{"pcap_setdirection error\n" + error_string(source)}; } }
PcapPort::PortMonitor::PortMonitor(const char *device, Direction direction, AbstractPort::PortStats *stats) { int ret; char errbuf[PCAP_ERRBUF_SIZE] = ""; bool noLocalCapture; direction_ = direction; isDirectional_ = true; isPromisc_ = true; noLocalCapture = true; stats_ = stats; stop_ = false; _retry: #ifdef Q_OS_WIN32 int flags = 0; if (isPromisc_) flags |= PCAP_OPENFLAG_PROMISCUOUS; if (noLocalCapture) flags |= PCAP_OPENFLAG_NOCAPTURE_LOCAL; handle_ = pcap_open(device, 64 /* FIXME */, flags, 1000 /* ms */, NULL, errbuf); #else handle_ = pcap_open_live(device, 64 /* FIXME */, int(isPromisc_), 1000 /* ms */, errbuf); #endif if (handle_ == NULL) { if (isPromisc_ && QString(errbuf).contains("promiscuous")) { qDebug("Can't set promiscuous mode, trying non-promisc %s", device); isPromisc_ = false; goto _retry; } else if (noLocalCapture && QString(errbuf).contains("loopback")) { qDebug("Can't set no local capture mode %s", device); noLocalCapture = false; goto _retry; } else goto _open_error; } #ifdef Q_OS_WIN32 // pcap_setdirection() API is not supported in Windows. // NOTE: WinPcap 4.1.1 and above exports a dummy API that returns -1 // but since we would like to work with previous versions of WinPcap // also, we assume the API does not exist ret = -1; #else switch (direction_) { case kDirectionRx: ret = pcap_setdirection(handle_, PCAP_D_IN); break; case kDirectionTx: ret = pcap_setdirection(handle_, PCAP_D_OUT); break; default: ret = -1; // avoid 'may be used uninitialized' warning Q_ASSERT(false); } #endif if (ret < 0) goto _set_direction_error; return; _set_direction_error: qDebug("Error setting direction(%d) %s: %s\n", direction, device, pcap_geterr(handle_)); isDirectional_ = false; return; _open_error: qDebug("%s: Error opening port %s: %s\n", __FUNCTION__, device, errbuf); }
/** * 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); g_info("Compile of [%s] worked! Returning %p", expr, pcdescr); 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; }
void *sniffer_thread(void *params) { struct sniffer_thread_parameter *p = (struct sniffer_thread_parameter *) params; struct interface *sniff_interface = p->sniff_interface; //i/p interface struct route **routes = p->routes; //o/p interface char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */ pcap_t *handle; /* packet capture handle */ //char filter_exp[64]; /* filter expression [3] */ //strcpy(filter_exp,"ip"); // sprintf(filter_exp, "ip and ether dst %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", PRINT_MAC(sniff_interface->interface_macaddress)); // struct bpf_program fp; /* compiled filter program (expression) */ struct got_packet_parameter got_packet_param; struct sockaddr_ll sa_in, sa_out[3]; int i; /* open capture device */ handle = pcap_open_live(sniff_interface->interface_name, SNAP_LEN, 1, 1000, errbuf); if (handle == NULL) { fprintf(stderr, "Couldn't open device %s: %s\n", sniff_interface->interface_name, errbuf); exit(EXIT_FAILURE); } /* make sure we're capturing on an Ethernet device [2] */ if (pcap_datalink(handle) != DLT_EN10MB) { fprintf(stderr, "%s is not an Ethernet\n", sniff_interface->interface_name); exit(EXIT_FAILURE); } if (pcap_setdirection(handle,PCAP_D_IN)!=0) { fprintf(stderr, "error in setting direction for %s\n", sniff_interface->interface_name); exit(EXIT_FAILURE); } /* compile the filter expression */ /*if (pcap_compile(handle, &fp, filter_exp, 0, sniff_interface->interface_netaddress) == -1) { fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle)); exit(EXIT_FAILURE); }*/ /* apply the compiled filter */ /*if (pcap_setfilter(handle, &fp) == -1) { fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle)); exit(EXIT_FAILURE); }*/ // Open socket for sniffing interface sa_in.sll_family = PF_PACKET; sa_in.sll_ifindex = sniff_interface->interface_index; sa_in.sll_halen = ETHER_ADDR_LEN; sa_in.sll_protocol = htons(ETH_P_ALL); sa_in.sll_hatype = 0; sa_in.sll_pkttype = 0; memcpy(sa_in.sll_addr, sniff_interface->interface_macaddress, ETHER_ADDR_LEN); sniff_interface->sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); //printf(" sniff socket %d \n",sniff_interface->sockfd); if (sniff_interface->sockfd == -1) { fprintf(stderr, "Cannot create raw socket for sniffing interface in sniffer_thread\n"); fprintf(stderr, "%s\n", strerror(errno)); exit(-1); } else{ if (bind(sniff_interface->sockfd, (struct sockaddr *)&sa_in, sizeof(sa_in)) != 0){ //WARNING fprintf(stderr, "Cannot bind to raw socket for sniffing interface in sniffer_thread\n"); fprintf(stderr, "%s\n", strerror(errno)); } // Open socket for all output interface for (i=0; i<p->num_ifs; i++) { sa_out[i].sll_family = PF_PACKET; sa_out[i].sll_ifindex = (*routes)[i].interface.interface_index; //sa_out[i].sll_ifindex = 4; //printf(" opened socket ifindex %d \n",sa_out[i].sll_ifindex); sa_out[i].sll_halen = ETHER_ADDR_LEN; sa_out[i].sll_protocol = htons(ETH_P_ALL); sa_out[i].sll_hatype = 0; sa_out[i].sll_pkttype = 0; memcpy(sa_out[i].sll_addr, (*routes)[i].interface.interface_macaddress, ETHER_ADDR_LEN); //printf("opened socket ifname %s \n",(*routes)[i].interface.interface_name); (*routes)[i].interface.sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if ((*routes)[i].interface.sockfd == -1) { fprintf(stderr, "Cannot create raw socket for output interface in sniffer_thread\n"); fprintf(stderr, "%s\n", strerror(errno)); exit(-1); } else{ //printf("opened socket %d \n",(*routes)[i].interface.sockfd); if (bind((*routes)[i].interface.sockfd, (struct sockaddr *)&sa_out[i], sizeof(sa_out[i])) != 0){ //WARNING fprintf(stderr, "Cannot bind to raw socket for output interface in sniffer_thread\n"); } } } } // Parse information to got_packet handler got_packet_param.sniff_interface = sniff_interface; //got_packet_param.num_routes = num_routes; got_packet_param.routes = routes; got_packet_param.num_ifs = p->num_ifs; //got_packet_param.arp_table_root = arp_table_root; pcap_loop(handle, -1, got_packet, (u_char *) &got_packet_param); /* cleanup */ //pcap_freecode(&fp); pcap_close(handle); fprintf(stderr, "\nCapture complete.\n"); return 0; }
void recv_packet(void) { char errbuf[PCAP_ERRBUF_SIZE], *pfilter=NULL; struct bpf_program filter; bpf_u_int32 net, mask; int ac_s=0, ret=0, worktodo=1; uint8_t msg_type=0, status=0, *ptr=NULL; size_t msg_len=0; xpoll_t spdf[2]; union { recv_workunit_t *r; uint8_t *cr; uint32_t *magic; } wk_u; union { listener_info_t *l; uint8_t *ptr; } l_u; union { drone_version_t *v; uint8_t *ptr; } d_u; drone_version_t dv; struct pcap_stat pcs; r_queue=fifo_init(); close_output_modules(); close_report_modules(); close_payload_modules(); DBG(M_IPC, "creating server socket"); memset(s->ss, 0, sizeof(scan_settings_t)); memset(&dv, 0, sizeof(dv)); d_u.v=&dv; dv.magic=DRONE_MAGIC; dv.maj=DRONE_MAJ; dv.min=DRONE_MIN; recv_stats_t recv_stats; /* heh */ if ((ac_s=socktrans_bind(s->ipcuri)) < 0) { terminate("cant create listener socket"); } DBG(M_IPC, "waiting for main to connect"); parent_sync(); lc_s=socktrans_accept(ac_s, DEF_SOCK_TIMEOUT); if (lc_s < 0) { terminate("main didnt connect, exiting"); } DBG(M_IPC, "got connection"); if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) { terminate("unexpected sequence of messages from parent waiting for ident request, exiting"); } if (msg_type != MSG_IDENT || status != MSG_STATUS_OK) { ERR("got an unknown message type `%s' or bad status %d from parent, exiting", strmsgtype(msg_type), status); } if (send_message(lc_s, MSG_IDENTLISTENER, MSG_STATUS_OK, d_u.ptr, sizeof(drone_version_t)) < 0) { terminate("cant send back msgident to parent"); } if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) { terminate("cant read ident ack message from parent, exiting"); } if (msg_type != MSG_ACK || status != MSG_STATUS_OK) { ERR("got an unknown message type `%s' or bad status %d from parent, exiting", strmsgtype(msg_type), status); } DBG(M_IPC, "sending ready message to parent"); l_u.l=(listener_info_t *)xmalloc(sizeof(listener_info_t)); memcpy(&l_u.l->myaddr, &s->vi[0]->myaddr, sizeof(struct sockaddr_storage)); memcpy(&l_u.l->mymask, &s->vi[0]->mymask, sizeof(struct sockaddr_storage)); memcpy(l_u.l->hwaddr, s->vi[0]->hwaddr, THE_ONLY_SUPPORTED_HWADDR_LEN); l_u.l->mtu=s->vi[0]->mtu; assert(s->interface_str != NULL); if (pcap_lookupnet(s->interface_str, &net, &mask, errbuf) < 0) { ERR("pcap_lookupnet fails, ignoring: %s", errbuf); } if (s->pcap_readfile == NULL) { pdev=pcap_open_live(s->interface_str, /* XXX haha */ s->vi[0]->mtu + 64, (GET_PROMISC() ? 1 : 0), 0, errbuf); if (pdev == NULL) { ERR("pcap open live: %s", errbuf); DBG(M_IPC, "sending ready error message to parent"); if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) { terminate("cant send message ready error"); } terminate("informed parent, exiting"); } } else { pdev=pcap_open_offline(s->pcap_readfile, errbuf); if (pdev == NULL) { ERR("pcap open offline: %s", errbuf); DBG(M_IPC, "sending ready error message to parent"); if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) { terminate("cant send message ready error"); } terminate("informed parent, exiting"); } } ret=util_getheadersize(pdev, errbuf); if (ret < 0 || ret > 0xffff) { ERR("error getting link header size: %s", errbuf); DBG(M_IPC, "sending ready error message to parent"); if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) { terminate("cant send message ready error"); } terminate("informed parent, exiting"); } s->ss->header_len=(uint16_t)ret; if (s->pcap_dumpfile != NULL) { VRB(0, "opening `%s' for pcap log", s->pcap_dumpfile); pdump=pcap_dump_open(pdev, s->pcap_dumpfile); if (pdump == NULL) { ERR("cant log to pcap file `%s'", pcap_geterr(pdev)); DBG(M_IPC, "sending ready error message to parent"); if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) { terminate("cant send message ready error"); } terminate("informed parent, exiting"); } } else { DBG(M_CLD, "not logging to pcap file"); } if (util_preparepcap(pdev, errbuf) < 0) { ERR("cant setup pcap filedesc to immediate mode: %s", errbuf); DBG(M_IPC, "sending ready error message to parent"); if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) { terminate("cant send message ready error"); } terminate("informed parent, exiting"); } /* pcap_fd will be -1 for a pcap file */ pcap_fd=pcap_get_selectable_fd(pdev); if (pcap_fd < 0 && s->pcap_readfile == NULL) { ERR("cant get selectable fd from pcap device, exiting"); DBG(M_IPC, "sending ready error message to parent"); if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) { terminate("sant send message ready error"); } terminate("informed parent, exiting"); } #ifdef PCAP_D_IN if (pcap_setdirection(pdev, PCAP_D_IN) < 0) { ERR("cant set pcap direction to in, exiting"); DBG(M_IPC, "sending ready error message to parent"); if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) { terminate("sant send message ready error"); } terminate("informed parent, exiting"); } #endif DBG(M_CLD, "listener dropping privs"); if (drop_privs() < 0) { terminate("cant drop privs"); } if (send_message(lc_s, MSG_READY, MSG_STATUS_OK, l_u.ptr, sizeof(listener_info_t)) < 0) { terminate("cant send message ready"); } xfree(l_u.l); /* XXX */ s->ss->syn_key=0; do { if (get_singlemessage(lc_s, &msg_type, &status, &wk_u.cr, &msg_len) != 1) { terminate("unexpected sequence of messages from parent looking for a workunit"); } if (status != MSG_STATUS_OK) { terminate("bad message status %u", status); } if (msg_type == MSG_QUIT) { worktodo=0; break; } else if (msg_type == MSG_WORKUNIT) { ; } else { terminate("unexpected message, expecting workunit or quit message"); } if (msg_len < sizeof(uint32_t)) { terminate("bad message, too short [" STFMT "]", msg_len); } if (msg_len < sizeof(recv_workunit_t)) { terminate("short workunit"); } worktodo=1; DBG(M_WRK, "workunit `%s'", strworkunit(wk_u.cr, msg_len)); s->ss->recv_timeout=wk_u.r->recv_timeout; s->ss->ret_layers=wk_u.r->ret_layers; s->recv_opts=wk_u.r->recv_opts; s->ss->window_size=wk_u.r->window_size; s->ss->syn_key=wk_u.r->syn_key; if (wk_u.r->pcap_len) { if ((msg_len - sizeof(recv_workunit_t)) == wk_u.r->pcap_len) { extract_pcapfilter(wk_u.cr + sizeof(recv_workunit_t), wk_u.r->pcap_len); } else { terminate("pcap option length illegal"); } } switch (*wk_u.magic) { case UDP_RECV_MAGIC: s->ss->mode=MODE_UDPSCAN; break; case TCP_RECV_MAGIC: s->ss->mode=MODE_TCPSCAN; break; case ARP_RECV_MAGIC: s->ss->mode=MODE_ARPSCAN; break; default: terminate("unknown recv workunit type"); break; } DBG(M_IPC, "from ipc, got workunit: %s", strworkunit((const void *)wk_u.cr, msg_len)); if (s->ss->mode == MODE_ARPSCAN) { if (s->ss->header_len != 14) { DBG(M_IPC, "sending msg error"); if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) { terminate("cant send message ready"); } terminate("wrong linktype for arp scan"); } } if (s->ss->ret_layers > 0) { DBG(M_CLD, "setting up packet queue"); p_queue=fifo_init(); } pfilter=get_pcapfilterstr(); VRB(1, "using pcap filter: `%s'", pfilter); memset(&filter, 0, sizeof(filter)); if (pcap_compile(pdev, &filter, pfilter, 0, net) < 0) { ERR("error compiling filter: %s", pcap_geterr(pdev)); if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) { ERR("cant send message ready error"); } terminate("cant compile pcap filter"); } if (pcap_setfilter(pdev, &filter) < 0) { ERR("error setting compiled filter: %s", pcap_geterr(pdev)); if (send_message(lc_s, MSG_READY, MSG_STATUS_ERROR, NULL, 0) < 0) { ERR("cant send message ready error"); } terminate("cant set compiled pcap filter"); } pcap_freecode(&filter); if (s->ss->ret_layers > 0) { DBG(M_IPC, "returning whole packet via ipc"); } DBG(M_IPC, "sending ready message to parent"); if (pcap_setnonblock(pdev, 1, errbuf) < 0) { terminate("cant set pcap non-blocking mode"); } if (send_message(lc_s, MSG_READY, MSG_STATUS_OK, NULL, 0) < 0) { terminate("cant send message ready"); } while (1) { spdf[0].fd=lc_s; spdf[1].fd=pcap_fd; /* if pdev is a socket ( ! -1 ) */ if (xpoll(&spdf[0], 2, -1) < 0) { ERR("xpoll fails: %s", strerror(errno)); } if (spdf[1].rw & XPOLL_READABLE) { pcap_dispatch(pdev, 1, parse_packet, NULL); } /* no packets, better drain the queue */ drain_pqueue(); if (spdf[0].rw & XPOLL_READABLE) { if (get_singlemessage(lc_s, &msg_type, &status, &ptr, &msg_len) != 1) { ERR("unexpected sequence of messages from parent in main read loop, exiting"); worktodo=0; break; } if (msg_type == MSG_TERMINATE) { DBG(M_IPC, "parent wants me to stop listening, breaking"); break; } else if (msg_type == MSG_QUIT) { DBG(M_IPC, "Parent wants me to quit, breaking"); worktodo=0; break; } else { ERR("got strange message `%s' from parent, exiting", strmsgtype(msg_type)); worktodo=0; break; } } } memset(&recv_stats, 0, sizeof(recv_stats)); if (pcap_stats(pdev, &pcs) != -1) { recv_stats.packets_recv=pcs.ps_recv; recv_stats.packets_dropped=pcs.ps_drop; recv_stats.packets_dropped=pcs.ps_ifdrop; } if (send_message(lc_s, MSG_WORKDONE, MSG_STATUS_OK, (void *)&recv_stats, sizeof(recv_stats)) < 0) { terminate("cant send workdone message to parent, exiting"); } } while (worktodo); pcap_close(pdev); if (s->pcap_dumpfile) { pcap_dump_close(pdump); } DBG(M_CLD, "listener exiting"); shutdown(lc_s, SHUT_RDWR); close(lc_s); uexit(0); }
int main(int argc, char *argv[]) { signal (SIGINT, signal_handler); //printf("\033[?1049h\033[H"); clear_log(); my_log("Software switch starting..."); my_log(pcap_lib_version()); int option = 0, ret; char c; pthread_t config_thread; char errbuf[PCAP_ERRBUF_SIZE]; p1 = create_port_struct(1); p2 = create_port_struct(2); while ((option = getopt(argc, argv,"h l 1:2: m")) != -1) { switch (option) { case '1' : strcpy(p1->name, optarg); break; case '2' : strcpy(p2->name, optarg); break; case 'l': list_interfaces(); exit(0); case 'm': mock_rule(); break; case 'h': default: print_usage(); exit(EXIT_FAILURE); } } p1->handle = pcap_create(p1->name, errbuf); if ( (ret = pcap_setdirection(p1->handle, PCAP_D_IN)) != 0){ printf("pcap_setdirection returned %i\n", ret); my_log("pcap_setdirection failed"); pcap_perror(p1->handle, 0); //exit(-1); } if ( pcap_set_promisc(p1->handle, 1) != 0){ printf("pcap_set_promisc returned \n%s\n", pcap_geterr(p1->handle)); my_log("pcap_set_promisc failed"); pcap_perror(p1->handle, 0); exit(-1); } if ( pcap_set_immediate_mode(p1->handle, 1) != 0){ printf("pcap_set_immediate_mode returned \n%s\n", pcap_geterr(p1->handle)); my_log("pcap_set_immediate_mode failed"); pcap_perror(p1->handle, 0); exit(-1); } if ( pcap_activate(p1->handle)){ printf("Failed to open interface %s\n", pcap_geterr(p1->handle)); exit(-1); } else { sprintf(log_b, "Handle activated for %s", p1->name); my_log(log_b); } p2->handle = pcap_create(p2->name, errbuf); if ( pcap_setdirection(p2->handle, PCAP_D_OUT) != 0){ my_log("pcap_setdirection failed"); pcap_perror(p2->handle, 0); //exit(-1); } if ( pcap_set_promisc(p2->handle, 1) != 0){ my_log("pcap_set_promisc failed"); pcap_perror(p2->handle, 0); exit(-1); } if ( pcap_set_immediate_mode(p2->handle, 1) != 0){ my_log("pcap_set_immediate_mode failed"); pcap_perror(p2->handle, 0); exit(-1); } if ( pcap_activate(p2->handle)){ printf("Failed to open interface %s\n", pcap_geterr(p2->handle)); exit(-1); } else { sprintf(log_b, "Handle activated for %s", p2->name); my_log(log_b); } //exit(0); my_log("Deleting mac table.."); clear_mac(); sprintf(log_b, "Default action is %s", (DEFAULT_ACTION == R_ALLOW)? "R_ALLOW" : "R_DENY"); my_log(log_b); my_log("Creating threads..."); pthread_mutex_init(&mutex, NULL); if ( pthread_create(&(p1->thread), 0, port_listener, (void *)p1) ){ my_log("Error creating p1 thread"); exit(-1); } if ( pthread_create(&(p2->thread), 0, port_listener, (void *)p2) ){ my_log("Error creating p2 thread"); exit(-1); } pthread_create(&config_thread, 0, config, 0); while (1) { mac_delete_old_entries(5); if(pause_rendering == 1) continue; // render here system("clear"); print_mac(); print_rules(); print_stats_header(); print_stats(p1->in, "1 IN"); print_stats(p1->out, "1 OUT"); print_stats(p2->in, "2 IN"); print_stats(p2->out, "2 OUT"); printf("p1in: %i\tp1out: %i\tp2in: %i\tp2out: %i\n", p1in, p1out, p2in, p2out); sleep(1); } pthread_join(config_thread, 0); pthread_join(p1->thread, 0); pthread_join(p2->thread, 0); //printf("\033[?1049l"); // go back return 0; }
//------------------------------------------------------------------------------ tOplkError edrv_init(const tEdrvInitParam* pEdrvInitParam_p) { struct sched_param schedParam; // Check parameter validity ASSERT(pEdrvInitParam_p != NULL); // clear instance structure OPLK_MEMSET(&edrvInstance_l, 0, sizeof(edrvInstance_l)); if (pEdrvInitParam_p->pDevName == NULL) return kErrorEdrvInit; // save the init data edrvInstance_l.initParam = *pEdrvInitParam_p; /* if no MAC address was specified read MAC address of used * Ethernet interface */ if ((edrvInstance_l.initParam.aMacAddr[0] == 0) && (edrvInstance_l.initParam.aMacAddr[1] == 0) && (edrvInstance_l.initParam.aMacAddr[2] == 0) && (edrvInstance_l.initParam.aMacAddr[3] == 0) && (edrvInstance_l.initParam.aMacAddr[4] == 0) && (edrvInstance_l.initParam.aMacAddr[5] == 0)) { // read MAC address from controller getMacAdrs(edrvInstance_l.initParam.pDevName, edrvInstance_l.initParam.aMacAddr); } // Set up and activate the pcap live capture handle edrvInstance_l.pPcap = startPcap(); if (edrvInstance_l.pPcap == NULL) { return kErrorEdrvInit; } if (pcap_setdirection(edrvInstance_l.pPcap, PCAP_D_OUT) < 0) { DEBUG_LVL_ERROR_TRACE("%s() couldn't set PCAP direction\n", __func__); return kErrorEdrvInit; } if (pthread_mutex_init(&edrvInstance_l.mutex, NULL) != 0) { DEBUG_LVL_ERROR_TRACE("%s() couldn't init mutex\n", __func__); return kErrorEdrvInit; } if (sem_init(&edrvInstance_l.syncSem, 0, 0) != 0) { DEBUG_LVL_ERROR_TRACE("%s() couldn't init semaphore\n", __func__); return kErrorEdrvInit; } if (pthread_create(&edrvInstance_l.hThread, NULL, workerThread, &edrvInstance_l) != 0) { DEBUG_LVL_ERROR_TRACE("%s() Couldn't create worker thread!\n", __func__); return kErrorEdrvInit; } schedParam.sched_priority = CONFIG_THREAD_PRIORITY_MEDIUM; if (pthread_setschedparam(edrvInstance_l.hThread, SCHED_FIFO, &schedParam) != 0) { DEBUG_LVL_ERROR_TRACE("%s() couldn't set thread scheduling parameters!\n", __func__); } #if (defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 12)) pthread_setname_np(edrvInstance_l.hThread, "oplk-edrvpcap"); #endif /* wait until thread is started */ sem_wait(&edrvInstance_l.syncSem); return kErrorOk; }