void reader_libpcapfile_opened() { int dlt_to_linktype(int dlt); pcapFileHeader.linktype = dlt_to_linktype(pcap_datalink(pcap)) | pcap_datalink_ext(pcap); pcapFileHeader.snaplen = pcap_snapshot(pcap); offlineFile = pcap_file(pcap); if (config.bpf) { struct bpf_program bpf; if (pcap_compile(pcap, &bpf, config.bpf, 1, PCAP_NETMASK_UNKNOWN) == -1) { LOG("ERROR - Couldn't compile filter: '%s' with %s", config.bpf, pcap_geterr(pcap)); exit(1); } if (pcap_setfilter(pcap, &bpf) == -1) { LOG("ERROR - Couldn't set filter: '%s' with %s", config.bpf, pcap_geterr(pcap)); exit(1); } } int t; for (t = 0; t < MOLOCH_FILTER_MAX; t++) { if (config.bpfsNum[t]) { int i; if (bpf_programs[t]) { for (i = 0; i < config.bpfsNum[t]; i++) { pcap_freecode(&bpf_programs[t][i]); } } else { bpf_programs[t] = malloc(config.bpfsNum[t]*sizeof(struct bpf_program)); } for (i = 0; i < config.bpfsNum[t]; i++) { if (pcap_compile(pcap, &bpf_programs[t][i], config.bpfs[t][i], 1, PCAP_NETMASK_UNKNOWN) == -1) { LOG("ERROR - Couldn't compile filter: '%s' with %s", config.bpfs[t][i], pcap_geterr(pcap)); exit(1); } } moloch_reader_should_filter = reader_libpcapfile_should_filter; } } if (config.flushBetween) moloch_session_flush(); offlinePcapName = strdup(offlinePcapFilename); int fd = pcap_fileno(pcap); if (fd == -1) { g_timeout_add(0, reader_libpcapfile_read, NULL); } else { moloch_watch_fd(fd, MOLOCH_GIO_READ_COND, reader_libpcapfile_read, NULL); } }
pcap_dumper_t * pcap_ng_dump_open(pcap_t *p, const char *fname) { FILE *f; int linktype; /* * If this pcap_t hasn't been activated, it doesn't have a * link-layer type, so we can't use it. */ if (!p->activated) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: not-yet-activated pcap_t passed to pcap_ng_dump_open", fname); return (NULL); } if (fname[0] == '-' && fname[1] == '\0') { f = stdout; fname = "standard output"; } else { f = fopen(fname, "wb"); if (f == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, pcap_strerror(errno)); return (NULL); } } /* * Make sure a section header will be added and that * any information to a previous section gets cleared. */ pcap_ng_init_section_info(p); /* * When using the block based API, the section header and * interface description blocks are given by the caller */ if (p->linktype != DLT_PKTAP && p->linktype != DLT_PCAPNG) { linktype = dlt_to_linktype(p->linktype); if (linktype == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: link-layer type %d isn't supported in savefiles", fname, p->linktype); if (f != stdout) fclose(f); return (NULL); } linktype |= p->linktype_ext; return (pcap_ng_setup_dump(p, linktype, f, fname)); } else { return ((pcap_dumper_t *)f); } }
void reader_libpcap_start() { int dlt_to_linktype(int dlt); //ALW - Bug: assumes all linktypes are the same pcapFileHeader.linktype = dlt_to_linktype(pcap_datalink(pcaps[0])) | pcap_datalink_ext(pcaps[0]); pcapFileHeader.snaplen = pcap_snapshot(pcaps[0]); pcap_t *dpcap = pcap_open_dead(pcapFileHeader.linktype, pcapFileHeader.snaplen); int t; for (t = 0; t < MOLOCH_FILTER_MAX; t++) { if (config.bpfsNum[t]) { int i; if (bpf_programs[t]) { for (i = 0; i < config.bpfsNum[t]; i++) { pcap_freecode(&bpf_programs[t][i]); } } else { bpf_programs[t] = malloc(config.bpfsNum[t]*sizeof(struct bpf_program)); } for (i = 0; i < config.bpfsNum[t]; i++) { if (pcap_compile(dpcap, &bpf_programs[t][i], config.bpfs[t][i], 1, PCAP_NETMASK_UNKNOWN) == -1) { LOG("ERROR - Couldn't compile filter: '%s' with %s", config.bpfs[t][i], pcap_geterr(dpcap)); exit(1); } } moloch_reader_should_filter = reader_libpcap_should_filter; } } int i; for (i = 0; i < MAX_INTERFACES && config.interface[i]; i++) { if (config.bpf) { struct bpf_program bpf; if (pcap_compile(pcaps[i], &bpf, config.bpf, 1, PCAP_NETMASK_UNKNOWN) == -1) { LOG("ERROR - Couldn't compile filter: '%s' with %s", config.bpf, pcap_geterr(pcaps[i])); exit(1); } if (pcap_setfilter(pcaps[i], &bpf) == -1) { LOG("ERROR - Couldn't set filter: '%s' with %s", config.bpf, pcap_geterr(pcaps[i])); exit(1); } } char name[100]; snprintf(name, sizeof(name), "moloch-pcap%d", i); g_thread_new(name, &reader_libpcap_thread, (gpointer)pcaps[i]); } }
/* * Initialize so that sf_write() will output to the given stream. */ pcap_dumper_t * pcap_dump_fopen(pcap_t *p, FILE *f) { int linktype; linktype = dlt_to_linktype(p->linktype); if (linktype == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "stream: link-layer type %d isn't supported in savefiles", p->linktype); return (NULL); } linktype |= p->linktype_ext; return (pcap_setup_dump(p, linktype, f, "stream")); }
/* * Initialize so that sf_write() will output to the file named 'fname'. */ pcap_dumper_t * pcap_dump_open(pcap_t *p, const char *fname) { FILE *f; int linktype; /* * If this pcap_t hasn't been activated, it doesn't have a * link-layer type, so we can't use it. */ if (!p->activated) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: not-yet-activated pcap_t passed to pcap_dump_open", fname); return (NULL); } linktype = dlt_to_linktype(p->linktype); if (linktype == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: link-layer type %d isn't supported in savefiles", fname, p->linktype); return (NULL); } linktype |= p->linktype_ext; if (fname[0] == '-' && fname[1] == '\0') { f = stdout; fname = "standard output"; } else { #if !defined(WIN32) && !defined(MSDOS) f = fopen(fname, "w"); #else f = fopen(fname, "wb"); #endif if (f == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, pcap_strerror(errno)); return (NULL); } } return (pcap_setup_dump(p, linktype, f, fname)); }
pcap_dumper_t * pcap_dump_open_append(pcap_t *p, const char *fname) { FILE *f; int linktype; int amt_read; struct pcap_file_header ph; linktype = dlt_to_linktype(p->linktype); if (linktype == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: link-layer type %d isn't supported in savefiles", fname, linktype); return (NULL); } if (fname[0] == '-' && fname[1] == '\0') return (pcap_setup_dump(p, linktype, stdout, "standard output")); #if !defined(_WIN32) && !defined(MSDOS) f = fopen(fname, "r+"); #else f = fopen(fname, "rb+"); #endif if (f == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, pcap_strerror(errno)); return (NULL); } /* * Try to read a pcap header. */ amt_read = fread(&ph, 1, sizeof (ph), f); if (amt_read != sizeof (ph)) { if (ferror(f)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, pcap_strerror(errno)); fclose(f); return (NULL); } else if (feof(f) && amt_read > 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: truncated pcap file header", fname); fclose(f); return (NULL); } } #if defined(_WIN32) || defined(MSDOS) /* * We turn off buffering. * XXX - why? And why not on the standard output? */ setbuf(f, NULL); #endif /* * If a header is already present and: * * it's not for a pcap file of the appropriate resolution * and the right byte order for this machine; * * the link-layer header types don't match; * * the snapshot lengths don't match; * * return an error. */ if (amt_read > 0) { /* * A header is already present. * Do the checks. */ switch (ph.magic) { case TCPDUMP_MAGIC: if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: different time stamp precision, cannot append to file", fname); fclose(f); return (NULL); } break; case NSEC_TCPDUMP_MAGIC: if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: different time stamp precision, cannot append to file", fname); fclose(f); return (NULL); } break; case SWAPLONG(TCPDUMP_MAGIC): case SWAPLONG(NSEC_TCPDUMP_MAGIC): snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: different byte order, cannot append to file", fname); fclose(f); return (NULL); case KUZNETZOV_TCPDUMP_MAGIC: case SWAPLONG(KUZNETZOV_TCPDUMP_MAGIC): case NAVTEL_TCPDUMP_MAGIC: case SWAPLONG(NAVTEL_TCPDUMP_MAGIC): snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: not a pcap file to which we can append", fname); fclose(f); return (NULL); default: snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: not a pcap file", fname); fclose(f); return (NULL); } /* * Good version? */ if (ph.version_major != PCAP_VERSION_MAJOR || ph.version_minor != PCAP_VERSION_MINOR) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: version is %u.%u, cannot append to file", fname, ph.version_major, ph.version_minor); fclose(f); return (NULL); } if (linktype != ph.linktype) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: different linktype, cannot append to file", fname); fclose(f); return (NULL); } if (p->snapshot != ph.snaplen) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: different snaplen, cannot append to file", fname); fclose(f); return (NULL); } } else { /* * A header isn't present; attempt to write it. */ if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s", fname, pcap_strerror(errno)); (void)fclose(f); return (NULL); } } /* * Start writing at the end of the file. */ if (fseek(f, 0, SEEK_END) == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't seek to end of %s: %s", fname, pcap_strerror(errno)); (void)fclose(f); return (NULL); } return ((pcap_dumper_t *)f); }
LOCAL void reader_libpcapfile_opened() { int dlt_to_linktype(int dlt); if (config.flushBetween) moloch_session_flush(); moloch_packet_set_linksnap(dlt_to_linktype(pcap_datalink(pcap)) | pcap_datalink_ext(pcap), pcap_snapshot(pcap)); offlineFile = pcap_file(pcap); if (config.bpf && pcapFileHeader.linktype != 239) { struct bpf_program bpf; if (pcap_compile(pcap, &bpf, config.bpf, 1, PCAP_NETMASK_UNKNOWN) == -1) { LOGEXIT("ERROR - Couldn't compile filter: '%s' with %s", config.bpf, pcap_geterr(pcap)); } if (pcap_setfilter(pcap, &bpf) == -1) { LOGEXIT("ERROR - Couldn't set filter: '%s' with %s", config.bpf, pcap_geterr(pcap)); } } readerPos++; if (readerFileName[readerPos]) moloch_free_later(readerFileName[readerPos], g_free); readerFileName[readerPos] = g_strdup(offlinePcapFilename); int fd = pcap_fileno(pcap); if (fd == -1) { g_timeout_add(0, reader_libpcapfile_read, NULL); } else { moloch_watch_fd(fd, MOLOCH_GIO_READ_COND, reader_libpcapfile_read, NULL); } if (filenameOpsNum > 0) { // Free any previously allocated if (readerFieldOps[readerPos].size > 0) moloch_field_ops_free(&readerFieldOps[readerPos]); moloch_field_ops_init(&readerFieldOps[readerPos], filenameOpsNum, MOLOCH_FIELD_OPS_FLAGS_COPY); // Go thru all the filename ops looking for matches and then expand the value string int i; for (i = 0; i < filenameOpsNum; i++) { GMatchInfo *match_info = 0; g_regex_match(filenameOps[i].regex, offlinePcapFilename, 0, &match_info); if (g_match_info_matches(match_info)) { GError *error = 0; char *expand = g_match_info_expand_references(match_info, filenameOps[i].expand, &error); if (error) { LOG("Error expanding '%s' with '%s' - %s", offlinePcapFilename, filenameOps[i].expand, error->message); g_error_free(error); } if (expand) { moloch_field_ops_add(&readerFieldOps[readerPos], filenameOps[i].field, expand, -1); g_free(expand); } } g_match_info_free(match_info); } } }
DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid; unsigned int maxp; CaptureJob *j; DWORD result; HANDLE ifh; #ifndef _WIN32 char errbuf[PCAP_ERRBUF_SIZE+4]; char *name; #endif check_pssdk(); dprintf("sniffer>> start_capture()"); ifid = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_INTERFACE_ID); maxp = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_PACKET_COUNT); maxp = min(maxp, SNIFFER_MAX_QUEUE); maxp = max(maxp, 1); result = ERROR_SUCCESS; do { // the interface is invalid if (ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { result = ERROR_INVALID_PARAMETER; break; } #ifdef _WIN32 ifh = pktsdk_interface_by_index(ifid); if (ifh == NULL) { result = ERROR_INVALID_PARAMETER; break; } #else ifh = ifid; #endif j = &open_captures[ifid]; // the interface is already being captured if (j->active) { result = ERROR_INVALID_PARAMETER; break; } #ifdef _WIN32 j->adp = AdpCreate(); dprintf("sniffer>> capture_start() AdpCreate: 0x%.8x", j->adp); AdpSetConfig(j->adp, ifh); hErr = AdpOpenAdapter(j->adp); dprintf("sniffer>> capture_start() AdpOpenAdapter: 0x%.8x", hErr); if (hErr != HNERR_OK) { AdpDestroy(j->adp); result = hErr; break; } j->capture_linktype = 1; // LINKTYPE_ETHERNET forced on windows #else name = get_interface_name_by_index(ifh); if(!name) { result = ERROR_INVALID_PARAMETER; break; } j->pcap = pcap_open_live(name, 65535, 1, 1000, errbuf); if(!j->pcap) { result = EACCES; break; } j->capture_linktype = dlt_to_linktype(pcap_datalink(j->pcap)); // get the datalink associated with the capture, needed when saving pcap file if (-1 == j->capture_linktype) { j->capture_linktype = 1; // force to LINKTYPE_ETHERNET in case of error } if(packet_filter) { struct bpf_program bpf; char *add_filter; char *real_filter = NULL; int rc; dprintf("handling packet_filter"); add_filter = packet_get_tlv_value_string(packet, TLV_TYPE_SNIFFER_ADDITIONAL_FILTER); dprintf("add_filter = %p (%s)", add_filter, add_filter ? add_filter : ""); if(add_filter) { asprintf(&real_filter, "%s and (%s)", packet_filter, add_filter); } else { real_filter = strdup(packet_filter); } dprintf("the real filter string we'll be using is '%s'", real_filter); rc = pcap_compile(j->pcap, &bpf, real_filter, 1, 0); free(real_filter); if(rc == -1) { dprintf("pcap compile reckons '%s' is a failure because of '%s'", real_filter, pcap_geterr(j->pcap)); result = ERROR_INVALID_PARAMETER; break; } dprintf("compiled filter, now setfilter()'ing"); rc = pcap_setfilter(j->pcap, &bpf); pcap_freecode(&bpf); if(rc == -1) { dprintf("can't set filter because '%s'", pcap_geterr(j->pcap)); result = ERROR_INVALID_PARAMETER; break; } dprintf("filter applied successfully"); } j->thread = thread_create((THREADFUNK) sniffer_thread, j, NULL, NULL); if(! j->thread) { pcap_close(j->pcap); break; } #endif j->pkts = calloc(maxp, sizeof(*(j->pkts))); if (j->pkts == NULL) { #ifdef _WIN32 AdpCloseAdapter(j->adp); AdpDestroy(j->adp); #else pcap_close(j->pcap); #endif result = ERROR_ACCESS_DENIED; break; } j->active = 1; j->intf = ifid; j->max_pkts = maxp; j->cur_pkts = 0; j->mtu = AdpCfgGetMaxPacketSize(AdpGetConfig(j->adp)); #ifdef _WIN32 AdpSetOnPacketRecv(j->adp, (FARPROC)sniffer_receive, (DWORD_PTR)j); AdpSetMacFilter(j->adp, mfAll); #else thread_run(j->thread); #endif } while (0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }