/* This file is part of Kismet Kismet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Kismet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Kismet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include #include #include "prism2source.h" #ifdef HAVE_LINUX_NETLINK int Prism2Source::OpenSource() { channel = 0; paused = 0; int fds[2], r; fd = -1; struct sockaddr_nl addr; r = pipe(fds); if (r < 0) { snprintf(errstr, 1024, "Prism2 open pipe() failed. (%s)", strerror(errno)); return(-1); } read_sock = fds[0]; write_sock = fds[1]; fd = socket(PF_NETLINK, SOCK_RAW, MCAST_GRP_SNIFF); if (fd < 0) { snprintf(errstr, 1024, "Prism2 open socket() failed. (%s)", strerror(errno)); return(-1); } memset (&addr, 0, sizeof(addr)); addr.nl_family = PF_NETLINK; addr.nl_pid = getpid(); addr.nl_groups = MCAST_GRP_SNIFF; if (bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_nl)) < 0) { snprintf(errstr, 1024, "Prism2 open bind() failed. (%s)", strerror(errno)); return(-1); } num_packets = 0; return(1); } int Prism2Source::CloseSource() { close(fd); return 1; } int Prism2Source::FetchPacket(kis_packet *packet, uint8_t *data, uint8_t *moddata) { fd_set rs; int r; struct timeval tim; struct timeval *ptm; if (read_sock < 0 || fd < 0) { snprintf(errstr, 1024, "Prism2 fetch failed. (source not open)"); return(-1); } FD_ZERO(&rs); FD_SET(fd, &rs); FD_SET(read_sock, &rs); if (PRISM2_READ_TIMEOUT >= 0) { tim.tv_sec = PRISM2_READ_TIMEOUT / 1000; tim.tv_usec = (PRISM2_READ_TIMEOUT % 1000) * 1000; ptm = &tim; } else { ptm = NULL; } r = select((read_sock > fd) ? read_sock + 1 : fd + 1, &rs, NULL, NULL, ptm); if (r < 0) { snprintf(errstr, 1024, "Prism2 fetch select() failed. (%s)", strerror(errno)); return(-1); } if (r == 0) { if (PRISM2_READ_TIMEOUT >= 0) return(0); } if (FD_ISSET(read_sock, &rs)) { char a; if (read(read_sock, &a, 1)!=1) return -1; } // u_char buf[MAX_PACKET_LEN]; if (FD_ISSET(fd, &rs)) { r = recv(fd, buffer, MAX_PACKET_LEN, 0); if (r < 0) { // We ignore ENOBUFS since it seems to happen fairly often and is really // annoying. if (errno == ENOBUFS) return 0; snprintf(errstr, 1024, "Prism2 fetch recv() failed. (%s)", strerror(errno)); return -1; } } if (paused) return 0; Prism2Common(packet, data, moddata); num_packets++; snprintf(packet->sourcename, 32, "%s", name.c_str()); packet->parm = parameters; return(packet->caplen); } int Prism2Source::Prism2Common(kis_packet *packet, uint8_t *data, uint8_t *moddata) { memset(packet, 0, sizeof(kis_packet)); sniff_packet_t *sniff_info = (sniff_packet_t *) buffer; gettimeofday(&packet->ts, NULL); packet->data = data; packet->moddata = moddata; packet->modified = 0; if (gpsd != NULL) { gpsd->FetchLoc(&packet->gps_lat, &packet->gps_lon, &packet->gps_alt, &packet->gps_spd, &packet->gps_heading, &packet->gps_fix); } // Trim the FCS packet->caplen = kismin(sniff_info->frmlen.data - 4, (uint32_t) MAX_PACKET_LEN); packet->len = packet->caplen; // Copy the radio levels out packet->signal = sniff_info->signal.data; packet->noise = sniff_info->noise.data; int offset = sizeof(sniff_packet_t); memcpy(packet->data, &buffer[offset], packet->caplen); packet->carrier = carrier_80211b; return 1; } int Prism2Source::FetchChannel() { return 0; } // ---------------------------------------------------------------------------- // // Registrant and control functions outside of the class KisPacketSource *prism2source_registrant(string in_name, string in_device, char *in_err) { return new Prism2Source(in_name, in_device); } int monitor_wlanng_legacy(const char *in_dev, int initch, char *in_err, void **in_if, void *in_ext) { // I really didn't want to do this... char cmdline[2048]; // Bring the device up, zero its ip, and set promisc if (Ifconfig_Delta_Flags(in_dev, in_err, IFF_UP | IFF_RUNNING | IFF_PROMISC) < 0) return -1; // Enable the interface snprintf(cmdline, 2048, "wlanctl-ng %s lnxreq_wlansniff channel=%d enable=true", in_dev, initch); if (RunSysCmd(cmdline) < 0) { snprintf(in_err, 1024, "Unable to execute '%s'", cmdline); return -1; } return 0; } int chancontrol_wlanng_legacy(const char *in_dev, int initch, char *in_err, void *in_ext) { // I really didn't want to do this... char cmdline[2048]; // Set the channel snprintf(cmdline, 2048, "wlanctl-ng %s lnxreq_wlansniff channel=%d enable=true >/dev/null 2>/dev/null", in_dev, initch); if (RunSysCmd(cmdline) < 0) { snprintf(in_err, 1024, "Unable to execute '%s'", cmdline); return -1; } return 0; } #endif