$OpenBSD: patch-pcapsource_cc,v 1.2 2006/11/01 21:13:20 kili Exp $ # Partially from upstream SVN (pcap stuff and some bugfixes). # Additionally, remove outdated stuff like ancontrol, fix some use after # close(2). --- pcapsource.cc.orig Sun Apr 2 17:13:00 2006 +++ pcapsource.cc Fri Oct 20 13:42:27 2006 @@ -124,17 +124,17 @@ int PcapSource::OpenSource() { pd = pcap_open_live(unconst, MAX_PACKET_LEN, 1, 1000, errstr); + free(unconst); + + if (strlen(errstr) > 0) + return -1; // Error is already in errstr + #if defined (SYS_OPENBSD) || defined(SYS_NETBSD) && defined(HAVE_RADIOTAP) /* Request desired DLT on multi-DLT systems that default to EN10MB. We do this later anyway but doing it here ensures we have the desired DLT from the get go. */ pcap_set_datalink(pd, DLT_IEEE802_11_RADIO); #endif - free(unconst); - - if (strlen(errstr) > 0) - return -1; // Error is already in errstr - paused = 0; errstr[0] = '\0'; @@ -146,7 +146,7 @@ int PcapSource::OpenSource() { #ifdef HAVE_PCAP_NONBLOCK pcap_setnonblock(pd, 1, errstr); -#elif !defined(SYS_OPENBSD) +#elif !defined(SYS_OPENBSD) && defined(HAVE_PCAP_GETSELFD) // do something clever (Thanks to Guy Harris for suggesting this). int save_mode = fcntl(pcap_get_selectable_fd(pd), F_GETFL, 0); if (fcntl(pcap_get_selectable_fd(pd), F_SETFL, save_mode | O_NONBLOCK) < 0) { @@ -180,6 +180,20 @@ int PcapSource::FetchSignalLevels(int *i return 0; } +void PcapSource::SetSmartCRC(int in_smart) { + if (in_smart && crc32_table == NULL) { + crc32_table = new unsigned int[256]; + crc32_init_table_80211(crc32_table); + } + + if (in_smart == 0 && crc32_table != NULL) { + delete[] crc32_table; + crc32_table = NULL; + } + + decode_fcs = in_smart; +} + // Errorcheck the datalink type int PcapSource::DatalinkType() { datalink_type = pcap_datalink(pd); @@ -233,7 +247,13 @@ int PcapSource::CloseSource() { } int PcapSource::FetchDescriptor() { +#ifdef HAVE_PCAP_GETSELFD return pcap_get_selectable_fd(pd); +#elif defined(HAVE_PCAP_GETEVENT) + return pcap_event(pd); +#else + return -1; +#endif } void PcapSource::Callback(u_char *bp, const struct pcap_pkthdr *header, @@ -291,7 +311,8 @@ int PcapSource::ManglePacket(kis_packet int ret = 0; memset(packet, 0, sizeof(kis_packet)); - packet->ts = callback_header.ts; + packet->ts.tv_sec = callback_header.ts.tv_sec; + packet->ts.tv_usec = callback_header.ts.tv_usec; packet->data = data; packet->moddata = moddata; packet->modified = 0; @@ -310,9 +331,35 @@ int PcapSource::ManglePacket(kis_packet ret = Radiotap2KisPack(packet, data, moddata); #endif } else { - packet->caplen = kismin(callback_header.caplen, (uint32_t) MAX_PACKET_LEN); + unsigned int fcs = FCSBytes(); + if (callback_header.caplen <= fcs) { + packet->error = 1; + packet->caplen = 0; + packet->len = 0; + return 0; + } + + packet->caplen = kismin(callback_header.caplen - fcs, + (uint32_t) MAX_PACKET_LEN); packet->len = packet->caplen; memcpy(packet->data, callback_data, packet->caplen); + + // If we're going to validate fcs, check it here */ + if (fcs && decode_fcs) { + uint32_t *frame_crc = + (uint32_t *) &(callback_data[callback_header.caplen - 4]); + uint32_t calc_crc = + crc32_le_80211(crc32_table, packet->data, packet->caplen); + + if (memcmp(frame_crc, &calc_crc, 4)) { + packet->error = 1; + // printf("debug - crc corrupt, got %08x expected %08x\n", calc_crc, *frame_crc); + return 1; + } + + // printf("debug - good - got crc %08x, expected %08x\n", calc_crc, *frame_crc); + } + ret = 1; } @@ -2054,7 +2101,10 @@ int monitor_ipwlivetap(const char *in_de return -1; } - fgets(dynif, 32, sysf); + if (fgets(dynif, 32, sysf) == NULL) { + fclose(sysf); + return -1; + } // We're done with the RO fclose(sysf); @@ -2084,7 +2134,10 @@ int monitor_ipwlivetap(const char *in_de return -1; } - fgets(dynif, 32, sysf); + if (fgets(dynif, 32, sysf) == NULL) { + fclose(sysf); + return -1; + } fclose(sysf); @@ -2353,38 +2406,10 @@ int monitor_wrt54g(const char *in_dev, i #endif #ifdef SYS_OPENBSD -// This should be done programattically... int monitor_openbsd_cisco(const char *in_dev, int initch, char *in_err, void **in_if, void *in_ext) { - char cmdline[2048]; - - // Sanitize the device just to be safe. The ifconfig should fail if - // the device is invalid, but why take risks - for (unsigned int x = 0; x < strlen(in_dev); x++) { - if (!isalnum(in_dev[x])) { - snprintf(in_err, STATUS_MAX, "Invalid device '%s'", in_dev); - return -1; - } - } - - snprintf(cmdline, 2048, "ancontrol -i %s -o 1", in_dev); - if (RunSysCmd(cmdline) < 0) { - snprintf(in_err, 1024, "Unable to execute '%s'", cmdline); - return -1; - } - - snprintf(cmdline, 2048, "ancontrol -i %s -p 1", in_dev); - if (RunSysCmd(cmdline) < 0) { - snprintf(in_err, 1024, "Unable to execute '%s'", cmdline); - return -1; - } - - snprintf(cmdline, 2048, "ancontrol -i %s -M 7", in_dev); - if (RunSysCmd(cmdline) < 0) { - snprintf(in_err, 1024, "Unable to execute '%s'", cmdline); - return -1; - } - - return 0; + // Lost cause. Since Feb '06 an(4) can do radiotap_bsd_b. + snprintf(in_err, STATUS_MAX, "cisco_openbsd is deprecated. Try radiotap_bsd_b."); + return -1; } int monitor_openbsd_prism2(const char *in_dev, int initch, char *in_err, void **in_if, void *in_ext) { @@ -2436,30 +2461,6 @@ int monitor_openbsd_prism2(const char *i return -1; } - // Disable power managment - bzero((char *)&wreq, sizeof(wreq)); - wreq.wi_len = WI_MAX_DATALEN; - wreq.wi_type = WI_RID_PM_ENABLED; - wreq.wi_val[0] = 0; - - if (ioctl(s, SIOCSWAVELAN, &ifr) < 0) { - close(s); - snprintf(in_err, 1024, "Power management ioctl failed: %s", - strerror(errno)); - } - - // Lower AP density, better radio threshold settings? - bzero((char *)&wreq, sizeof(wreq)); - wreq.wi_len = WI_MAX_DATALEN; - wreq.wi_type = WI_RID_SYSTEM_SCALE; - wreq.wi_val[0] = 1; - - if (ioctl(s, SIOCSWAVELAN, &ifr) < 0) { - close(s); - snprintf(in_err, 1024, "AP Density ioctl failed: %s", - strerror(errno)); - } - // Enable driver processing of 802.11b frames bzero((char *)&wreq, sizeof(wreq)); wreq.wi_len = WI_MAX_DATALEN; @@ -2473,14 +2474,17 @@ int monitor_openbsd_prism2(const char *i return -1; } - // Disable roaming, we don't want the card to probe + /* + * Disable roaming, we don't want the card to probe + * If this fails, don't consider it fatal. + */ + bzero((char *)&wreq, sizeof(wreq)); wreq.wi_len = WI_MAX_DATALEN; wreq.wi_type = WI_RID_ROAMING_MODE; wreq.wi_val[0] = 3; if (ioctl(s, SIOCSWAVELAN, &ifr) < 0) { - close(s); snprintf(in_err, 1024, "Roaming disable ioctl failed: %s", strerror(errno)); } @@ -2750,7 +2754,7 @@ bool RadiotapBSD::getmediaopt(int& optio return false; memset(&ifmr, 0, sizeof(ifmr)); - strncpy(ifmr.ifm_name, ifname.c_str(), sizeof(ifmr.ifm_name)); + strncpy(ifmr.ifm_name, ifname.c_str(), sizeof(ifmr.ifm_name)-1); /* * We must go through the motions of reading all @@ -2775,7 +2779,7 @@ bool RadiotapBSD::setmediaopt(int option return false; memset(&ifmr, 0, sizeof(ifmr)); - strncpy(ifmr.ifm_name, ifname.c_str(), sizeof(ifmr.ifm_name)); + strncpy(ifmr.ifm_name, ifname.c_str(), sizeof(ifmr.ifm_name)-1); /* * We must go through the motions of reading all @@ -2803,7 +2807,7 @@ bool RadiotapBSD::setmediaopt(int option delete mwords; memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, ifname.c_str(), sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name, ifname.c_str(), sizeof(ifr.ifr_name)-1); ifr.ifr_media = (ifmr.ifm_current &~ IFM_OMASK) | options; ifr.ifr_media = (ifr.ifr_media &~ IFM_MMASK) | IFM_MAKEMODE(mode); @@ -2857,7 +2861,7 @@ bool RadiotapBSD::get80211(int type, int if (!checksocket()) return false; memset(&ireq, 0, sizeof(ireq)); - strncpy(ireq.i_name, ifname.c_str(), sizeof(ireq.i_name)); + strncpy(ireq.i_name, ifname.c_str(), sizeof(ireq.i_name)-1); ireq.i_type = type; ireq.i_len = len; ireq.i_data = data; @@ -2875,7 +2879,7 @@ bool RadiotapBSD::set80211(int type, int if (!checksocket()) return false; memset(&ireq, 0, sizeof(ireq)); - strncpy(ireq.i_name, ifname.c_str(), sizeof(ireq.i_name)); + strncpy(ireq.i_name, ifname.c_str(), sizeof(ireq.i_name)-1); ireq.i_type = type; ireq.i_val = val; ireq.i_len = len; @@ -2892,6 +2896,7 @@ bool RadiotapBSD::getifflags(int& flags) return false; strncpy(ifr.ifr_name, ifname.c_str(), sizeof (ifr.ifr_name)); + ifr.ifr_name[sizeof (ifr.ifr_name)-1] = '\0'; if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { perror("SIOCGIFFLAGS ioctl failed"); return false;