static struct wif *fbsd_open(char *iface) { struct wif *wi; struct priv_fbsd *pf; int fd; /* setup wi struct */ wi = wi_alloc(sizeof(*pf)); if (!wi) return NULL; wi->wi_read = fbsd_read; wi->wi_write = fbsd_write; wi->wi_set_channel = fbsd_set_channel; wi->wi_get_channel = fbsd_get_channel; wi->wi_close = fbsd_close; wi->wi_fd = fbsd_fd; wi->wi_get_mac = fbsd_get_mac; wi->wi_set_mac = fbsd_set_mac; wi->wi_get_rate = fbsd_get_rate; wi->wi_set_rate = fbsd_set_rate; wi->wi_get_monitor = fbsd_get_monitor; wi->wi_get_mtu = fbsd_get_mtu; wi->wi_set_mtu = fbsd_set_mtu; /* setup iface */ fd = do_fbsd_open(wi, iface); if (fd == -1) { do_free(wi); return NULL; } /* setup private state */ pf = wi_priv(wi); pf->pf_fd = fd; pf->pf_txparams.ibp_vers = IEEE80211_BPF_VERSION; pf->pf_txparams.ibp_len = sizeof(struct ieee80211_bpf_params) - 6; pf->pf_txparams.ibp_rate0 = 2; /* 1 MB/s XXX */ pf->pf_txparams.ibp_try0 = 1; /* no retransmits */ pf->pf_txparams.ibp_rate1 = 2; /* 1 MB/s XXX */ pf->pf_txparams.ibp_try1 = 1; /* no retransmits */ pf->pf_txparams.ibp_flags = IEEE80211_BPF_NOACK; pf->pf_txparams.ibp_power = 100; /* nominal max */ pf->pf_txparams.ibp_pri = WME_AC_VO; /* high priority */ return wi; }
static int net_read(struct wif *wi, unsigned char *h80211, int len, struct rx_info *ri) { struct priv_net *pn = wi_priv(wi); uint32_t buf[512]; // 512 * 4 = 2048 unsigned char *bufc = (unsigned char*)buf; int cmd; int sz = sizeof(*ri); int l; int ret; /* try queue */ l = queue_get(pn, buf, sizeof(buf)); if (!l) { /* try reading form net */ l = sizeof(buf); cmd = net_get(pn->pn_s, buf, &l); if (cmd == -1) return -1; if (cmd == NET_RC) { ret = ntohl((buf[0])); return ret; } assert(cmd == NET_PACKET); } /* XXX */ if (ri) { // re-assemble 64-bit integer ri->ri_mactime = __be64_to_cpu(((uint64_t)buf[0] << 32 || buf[1] )); ri->ri_power = __be32_to_cpu(buf[2]); ri->ri_noise = __be32_to_cpu(buf[3]); ri->ri_channel = __be32_to_cpu(buf[4]); ri->ri_rate = __be32_to_cpu(buf[5]); ri->ri_antenna = __be32_to_cpu(buf[6]); } l -= sz; assert(l > 0); if (l > len) l = len; memcpy(h80211, &bufc[sz], l); return l; }
static struct wif *cygwin_open(char *iface) { struct wif *wi; struct priv_cygwin *priv; /* setup wi struct */ wi = wi_alloc(sizeof(*priv)); if (!wi) return NULL; wi->wi_read = cygwin_read; wi->wi_write = cygwin_write; wi->wi_set_channel = cygwin_set_channel; wi->wi_get_channel = cygwin_get_channel; wi->wi_close = cygwin_close; wi->wi_fd = cygwin_fd; wi->wi_get_mac = cygwin_get_mac; wi->wi_set_mac = cygwin_set_mac; wi->wi_get_rate = cygwin_get_rate; wi->wi_set_rate = cygwin_set_rate; wi->wi_get_monitor = cygwin_get_monitor; /* setup iface */ if (do_cygwin_open(wi, iface) == -1) goto err; /* setup private state */ priv = wi_priv(wi); priv->pc_wi = wi; /* setup reader */ if (pipe(priv->pc_pipe) == -1) goto err; priv->pc_running = 2; if (pthread_create(&priv->pc_reader, NULL, cygwin_reader, priv)) goto err; priv->pc_running = 1; return wi; err: do_free(wi); return NULL; }
static int net_write(struct wif *wi, unsigned char *h80211, int len, struct tx_info *ti) { struct priv_net *pn = wi_priv(wi); int sz = sizeof(*ti); unsigned char buf[2048]; unsigned char *ptr = buf; /* XXX */ if (ti) memcpy(ptr, ti, sz); else memset(ptr, 0, sizeof(*ti)); ptr += sz; memcpy(ptr, h80211, len); sz += len; return net_cmd(pn, NET_WRITE, buf, sz); }
static int net_get_mac(struct wif *wi, unsigned char *mac) { struct priv_net *pn = wi_priv(wi); uint32_t buf[2]; // only need 6 bytes, this provides 8 int cmd; int sz = 6; if (net_send(pn->pn_s, NET_GET_MAC, NULL, 0) == -1) return -1; cmd = net_get_nopacket(pn, buf, &sz); if (cmd == -1) return -1; if (cmd == NET_RC) return ntohl(buf[0]); assert(cmd == NET_MAC); assert(sz == 6); memcpy(mac, buf, 6); return 0; }
static int cygwin_read(struct wif * wi, unsigned char * h80211, int len, struct rx_info * ri) { struct priv_cygwin * pc = wi_priv(wi); struct rx_info tmp; int plen; if (pc->pc_running == -1) return -1; if (!ri) ri = &tmp; /* length */ if (net_read_exact(pc->pc_pipe[0], &plen, sizeof(plen)) == -1) return -1; /* ri */ if (net_read_exact(pc->pc_pipe[0], ri, sizeof(*ri)) == -1) return -1; plen -= sizeof(*ri); assert(plen > 0); return cygwin_read_reader(pc->pc_pipe[0], plen, h80211, len); }
struct wif *net_open(char *iface) { struct wif *wi; struct priv_net *pn; int s; /* setup wi struct */ wi = wi_alloc(sizeof(*pn)); if (!wi) return NULL; wi->wi_read = net_read; wi->wi_write = net_write; wi->wi_set_channel = net_set_channel; wi->wi_get_channel = net_get_channel; wi->wi_set_rate = net_set_rate; wi->wi_get_rate = net_get_rate; wi->wi_close = net_close; wi->wi_fd = net_fd; wi->wi_get_mac = net_get_mac; wi->wi_get_monitor = net_get_monitor; /* setup iface */ s = do_net_open(iface); if (s == -1) { do_net_free(wi); return NULL; } /* setup private state */ pn = wi_priv(wi); pn->pn_s = s; pn->pn_queue.q_next = pn->pn_queue.q_prev = &pn->pn_queue; pn->pn_queue_free.q_next = pn->pn_queue_free.q_prev = &pn->pn_queue_free; return wi; }
static int fbsd_write(struct wif *wi, unsigned char *h80211, int len, struct tx_info *ti) { struct iovec iov[2]; struct priv_fbsd *pf = wi_priv(wi); int rc; /* XXX make use of ti */ if (ti) {} iov[0].iov_base = &pf->pf_txparams; iov[0].iov_len = pf->pf_txparams.ibp_len; iov[1].iov_base = h80211; iov[1].iov_len = len; rc = writev(pf->pf_fd, iov, 2); if (rc == -1) return rc; if (rc < (int) iov[0].iov_len) return 0; return rc - iov[0].iov_len; }
static int net_get_monitor(struct wif *wi) { return net_cmd(wi_priv(wi), NET_GET_MONITOR, NULL, 0); }
static int net_get_rate(struct wif *wi) { struct priv_net *pn = wi_priv(wi); return net_cmd(pn, NET_GET_RATE, NULL, 0); }
static int net_set_rate(struct wif *wi, int rate) { uint32_t c = htonl(rate); return net_cmd(wi_priv(wi), NET_SET_RATE, &c, sizeof(c)); }
static int net_get_channel(struct wif *wi) { struct priv_net *pn = wi_priv(wi); return net_cmd(pn, NET_GET_CHAN, NULL, 0); }
static int net_set_channel(struct wif *wi, int chan) { uint32_t c = htonl(chan); return net_cmd(wi_priv(wi), NET_SET_CHAN, &c, sizeof(c)); }
static int do_fbsd_open(struct wif *wi, char *iface) { int i; char buf[64]; int fd = -1; struct ifreq ifr; unsigned int dlt = DLT_IEEE802_11_RADIO; int s; unsigned int flags; struct ifmediareq ifmr; int *mwords; struct priv_fbsd *pf = wi_priv(wi); /* basic sanity check */ if (strlen(iface) >= sizeof(ifr.ifr_name)) return -1; /* open wifi */ s = socket(PF_INET, SOCK_DGRAM, 0); if (s == -1) return -1; pf->pf_s = s; /* set iface up and promisc */ memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, iface); if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) goto close_sock; flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); flags |= IFF_UP | IFF_PPROMISC; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, iface); ifr.ifr_flags = flags & 0xffff; ifr.ifr_flagshigh = flags >> 16; if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1) goto close_sock; /* monitor mode */ memset(&ifmr, 0, sizeof(ifmr)); strcpy(ifmr.ifm_name, iface); if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) goto close_sock; assert(ifmr.ifm_count != 0); mwords = (int *)malloc(ifmr.ifm_count * sizeof(int)); if (!mwords) goto close_sock; ifmr.ifm_ulist = mwords; if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) { free(mwords); goto close_sock; } free(mwords); memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, iface); ifr.ifr_media = ifmr.ifm_current; if (ioctl(s, SIOCSIFMEDIA, &ifr) == -1) goto close_sock; /* setup ifreq for chan that may be used in future */ strcpy(pf->pf_ireq.i_name, iface); pf->pf_ireq.i_type = IEEE80211_IOC_CHANNEL; /* same for ifreq [mac addr] */ strcpy(pf->pf_ifr.ifr_name, iface); /* open bpf */ for(i = 0; i < 256; i++) { sprintf(buf, "/dev/bpf%d", i); fd = open(buf, O_RDWR); if(fd < 0) { if(errno != EBUSY) return -1; continue; } else break; } if(fd < 0) goto close_sock; strcpy(ifr.ifr_name, iface); if(ioctl(fd, BIOCSETIF, &ifr) < 0) goto close_bpf; if (ioctl(fd, BIOCSDLT, &dlt) < 0) goto close_bpf; dlt = 1; if (ioctl(fd, BIOCIMMEDIATE, &dlt) == -1) goto close_bpf; return fd; close_sock: close(s); return -1; close_bpf: close(fd); goto close_sock; }
static int file_fd(struct wif *wi) { struct priv_file *pf = wi_priv(wi); return pf->pf_fd; }
static int file_read(struct wif *wi, unsigned char *h80211, int len, struct rx_info *ri) { struct priv_file *pf = wi_priv(wi); struct pcap_pkthdr pkh; int rc; unsigned char buf[4096]; int off = 0; struct ieee80211_radiotap_header *rh; struct ieee80211_radiotap_iterator iter; rc = read(pf->pf_fd, &pkh, sizeof(pkh)); if (rc != sizeof(pkh)) return -1; if (pkh.caplen > sizeof(buf)) { printf("Bad caplen %d\n", pkh.caplen); return 0; } assert(pkh.caplen <= sizeof(buf)); rc = read(pf->pf_fd, buf, pkh.caplen); if (rc != (int) pkh.caplen) return -1; if (ri) memset(ri, 0, sizeof(*ri)); switch (pf->pf_dtl) { case LINKTYPE_IEEE802_11: off = 0; break; case LINKTYPE_RADIOTAP_HDR: rh = (struct ieee80211_radiotap_header*) buf; off = le16_to_cpu(rh->it_len); if (ieee80211_radiotap_iterator_init(&iter, rh, rc) < 0) return -1; while (ieee80211_radiotap_iterator_next(&iter) >= 0) { switch (iter.this_arg_index) { case IEEE80211_RADIOTAP_FLAGS: if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS) rc -= 4; break; } } break; case LINKTYPE_PRISM_HEADER: if (buf[7] == 0x40) off = 0x40; else off = *((int *)(buf + 4)); rc -= 4; break; case LINKTYPE_PPI_HDR: off = le16_to_cpu(*(unsigned short *)(buf + 2)); /* for a while Kismet logged broken PPI headers */ if (off == 24 && le16_to_cpu(*(unsigned short *)(buf + 8)) == 2 ) off = 32; break; case LINKTYPE_ETHERNET: printf("Ethernet packets\n"); return 0; default: errx(1, "Unknown DTL %d", pf->pf_dtl); break; } rc -= off; assert(rc >= 0); if (rc > len) rc = len; memcpy(h80211, &buf[off], rc); return rc; }
static int cygwin_get_freq(struct wif * wi) { struct priv_cygwin * pc = wi_priv(wi); return pc->pc_frequency; }
static int file_get_rate(struct wif *wi) { struct priv_file *pf = wi_priv(wi); return pf->pf_rate; }
static int net_fd(struct wif *wi) { struct priv_net *pn = wi_priv(wi); return pn->pn_s; }
static int fbsd_fd(struct wif *wi) { struct priv_fbsd *pf = wi_priv(wi); return pf->pf_fd; }
/** * Set MAC Address of the device * @param mac MAC Address * @return 0 if successful */ static int cygwin_set_mac(struct wif *wi, unsigned char *mac) { struct priv_cygwin *pc = wi_priv(wi); return pc->pc_set_mac(mac); }
/** * Get device channel * @return channel */ static int cygwin_get_channel(struct wif *wi) { struct priv_cygwin *pc = wi_priv(wi); return pc->pc_channel; }
/** * Get the different functions for to interact with the device: * - setting monitor mode * - changing channel * - capturing data * - injecting packets * @param iface The interface name */ static int do_cygwin_open(struct wif *wi, char *iface) { struct priv_cygwin *priv = wi_priv(wi); void *lib; char *file; char *parm; int rc = -1; int tempret = 0; if (!iface) return -1; if (strlen(iface) == 0) return -1; priv->useDll = 0; if (stristr(iface, DLL_EXTENSION)) priv->useDll = 1; if (priv->useDll) { file = strdup(iface); if (!file) return -1; parm = strchr(file, '|'); if (parm) *parm++ = 0; /* load lib */ lib = dlopen(file, RTLD_LAZY); if (!lib) goto errdll; priv->pc_init = dlsym(lib, xstr(CYGWIN_DLL_INIT)); priv->pc_set_chan = dlsym(lib, xstr(CYGWIN_DLL_SET_CHAN)); priv->pc_get_mac = dlsym(lib, xstr(CYGWIN_DLL_GET_MAC)); priv->pc_set_mac = dlsym(lib, xstr(CYGWIN_DLL_SET_MAC)); priv->pc_close = dlsym(lib, xstr(CYGWIN_DLL_CLOSE)); priv->pc_inject = dlsym(lib, xstr(CYGWIN_DLL_INJECT)); priv->pc_sniff = dlsym(lib, xstr(CYGWIN_DLL_SNIFF)); if (!(priv->pc_init && priv->pc_set_chan && priv->pc_get_mac && priv->pc_inject && priv->pc_sniff && priv->pc_close)) goto errdll; /* init lib */ if ((rc = priv->pc_init(parm))) goto errdll; priv->pc_did_init = 1; rc = 0; errdll: free(file); } else { #ifdef HAVE_AIRPCAP // Check if it's an Airpcap device priv->isAirpcap = isAirpcapDevice(iface); if (priv->isAirpcap) { // Get functions priv->pc_init = airpcap_init; priv->pc_set_chan = airpcap_set_chan; priv->pc_get_mac = airpcap_get_mac; priv->pc_set_mac = airpcap_set_mac; priv->pc_close = airpcap_close; priv->pc_inject = airpcap_inject; priv->pc_sniff = airpcap_sniff; rc = 0; } #endif } if (rc == 0) { // Don't forget to initialize if (! priv->useDll) { rc = priv->pc_init(iface); if (rc == 0) priv->pc_did_init = 1; else fprintf(stderr,"Error initializing <%s>\n", iface); } /* set initial chan */ tempret = wi_set_channel(wi, 1); if (tempret) rc = tempret; } else { // Show an error message if the adapter is not supported fprintf(stderr, "Adapter <%s> not supported\n", iface); } return rc; }
static int file_get_channel(struct wif *wi) { struct priv_file *pf = wi_priv(wi); return pf->pf_chan; }
static int obsd_fd(struct wif *wi) { struct priv_obsd *po = wi_priv(wi); return po->po_fd; }