static int iw_event_stream_pop( struct iw_event_stream *stream, struct iw_event *iwe, int we_version) { return iw_extract_event_stream( (struct stream_descr *) stream, iwe, we_version); }
/* * Print out all Wireless Events part of the RTNetlink message * Most often, there will be only one event per message, but * just make sure we read everything... */ static inline int print_event_stream(int ifindex, char * data, int len) { struct iw_event iwe; struct stream_descr stream; int i = 0; int ret; char buffer[64]; struct timeval recv_time; struct timezone tz; struct wireless_iface * wireless_data; /* Get data from cache */ wireless_data = iw_get_interface_data(ifindex); if(wireless_data == NULL) return(-1); /* Print received time in readable form */ gettimeofday(&recv_time, &tz); iw_print_timeval(buffer, sizeof(buffer), &recv_time, &tz); iw_init_event_stream(&stream, data, len); do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, wireless_data->range.we_version_compiled); if(ret != 0) { if(i++ == 0) printf("%s %-8.16s ", buffer, wireless_data->ifname); else printf(" "); if(ret > 0) print_event_token(&iwe, &wireless_data->range, wireless_data->has_range); else printf("(Invalid event)\n"); /* Push data out *now*, in case we are redirected to a pipe */ fflush(stdout); } } while(ret > 0); return(0); }
/* * Print out all Wireless Events part of the RTNetlink message * Most often, there will be only one event per message, but * just make sure we read everything... */ static inline int print_event_stream(char * ifname, char * data, int len) { struct iw_event iwe; struct stream_descr stream; int i = 0; int ret; char buffer[64]; struct timeval recv_time; #if 0 struct iw_range range; int has_range; #endif #if 0 has_range = (iw_get_range_info(skfd, ifname, &range) < 0); #endif /* In readable form */ gettimeofday(&recv_time, NULL); iw_print_timeval(buffer, &recv_time); iw_init_event_stream(&stream, data, len); do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe); if(ret != 0) { if(i++ == 0) printf("%s %-8.8s ", buffer, ifname); else printf(" "); if(ret > 0) print_event_token(&iwe, NULL, 0); else printf("(Invalid event)\n"); } } while(ret > 0); return(0); }
APLIST *wireless_scanning(int iwsockfd, const char *ifname) { APLIST *ap = NULL; APLIST *newap; struct iwreq wrq; int scanflags = 0; /* Flags for scan */ unsigned char * buffer = NULL; /* Results */ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE < 17 */ struct iw_range range; int has_range; struct timeval tv; /* select timeout */ int timeout = 15000000; /* 15s */ /* Get range stuff */ has_range = (iw_get_range_info(iwsockfd, ifname, &range) >= 0); /* Check if the interface could support scanning. */ if ((!has_range) || (range.we_version_compiled < 14)) { fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n", ifname); return NULL; } /* Init timeout value -> 250ms between set and first get */ tv.tv_sec = 0; tv.tv_usec = 250000; wrq.u.data.pointer = NULL; wrq.u.data.flags = 0; wrq.u.data.length = 0; /* Initiate Scanning */ if (iw_set_ext(iwsockfd, ifname, SIOCSIWSCAN, &wrq) < 0) { if ((errno != EPERM) || (scanflags != 0)) { fprintf(stderr, "%-8.16s Interface doesn't support " "scanning : %s\n\n", ifname, strerror(errno)); return NULL; } tv.tv_usec = 0; } timeout -= tv.tv_usec; /* Forever */ while (1) { fd_set rfds; /* File descriptors for select */ int last_fd; /* Last fd */ int ret; /* Guess what ? We must re-generate rfds each time */ FD_ZERO(&rfds); last_fd = -1; /* In here, add the rtnetlink fd in the list */ /* Wait until something happens */ ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); /* Check if there was an error */ if (ret < 0) { if (errno == EAGAIN || errno == EINTR) continue; fprintf(stderr, "Unhandled signal - exiting...\n"); return NULL; } /* Check if there was a timeout */ if (ret == 0) { unsigned char *newbuf; realloc: /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ newbuf = realloc(buffer, buflen); if (newbuf == NULL) { if (buffer) free(buffer); fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__); return NULL; } buffer = newbuf; /* Try to read the results */ wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; if (iw_get_ext(iwsockfd, ifname, SIOCGIWSCAN, &wrq) < 0) { /* Check if buffer was too small (WE-17 only) */ if ((errno == E2BIG) && (range.we_version_compiled > 16)) { /* Check if the driver gave us any hints. */ if (wrq.u.data.length > buflen) buflen = wrq.u.data.length; else buflen *= 2; /* Try again */ goto realloc; } /* Check if results not available yet */ if(errno == EAGAIN) { /* Restart timer for only 100ms*/ tv.tv_sec = 0; tv.tv_usec = 100000; timeout -= tv.tv_usec; if (timeout > 0) continue; /* Try again later */ } /* Bad error */ free(buffer); fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n", ifname, strerror(errno)); return NULL; } else /* We have the results, go to process them */ break; } /* In here, check if event and event type * if scan event, read results. All errors bad & no reset timeout */ } if(wrq.u.data.length) { struct iw_event iwe; struct stream_descr stream; int ret; iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); if (iwe.cmd==SIOCGIWAP) { newap = malloc(sizeof(APLIST)); newap->info = NULL; newap->next = ap; ap = newap; } ap->info = wireless_parse_scanning_event(&iwe, ap->info); } while (ret > 0); printf("\n"); } else printf("%-8.16s No scan results\n\n", ifname); free(buffer); return ap; }
/* ---------------------------------------------------------------------- WirelessInterface_Scan */ static PyObject* WirelessInterface_Scan(wiface* self) { iwreq wrq; unsigned char* buffer = NULL; int buflen = IW_SCAN_MAX_DATA; iwrange range; int has_range; timeval tv; int timeout = 15000000; PyObject* scan_list = NULL; has_range = (iw_get_range_info(self->sock, self->ifname, &range) >= 0); tv.tv_sec = 0; tv.tv_usec = 250000; wrq.u.data.pointer = NULL; wrq.u.data.flags = 0; wrq.u.data.length = 0; if (iw_set_ext(self->sock, self->ifname, SIOCSIWSCAN, &wrq) < 0) { if (errno != EPERM) { PyErr_SetString(IwScanError, "Interface doesn't support scanning"); return NULL; } tv.tv_usec = 0; } timeout -= tv.tv_usec; while (1) { fd_set rfds; int last_fd; int ret; FD_ZERO(&rfds); last_fd = -1; ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); if (ret < 0) { if (errno == EAGAIN || errno == EINTR) continue; else { PyErr_SetString(IwScanError, "Unknown scanning error"); return NULL; } } if (!ret) { unsigned char* newbuf; realloc: newbuf = realloc(buffer, buflen); if (!newbuf) { if (buffer) free(buffer); PyErr_SetString(IwScanError, "Memory allocation failure in scan"); return NULL; } buffer = newbuf; wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; if (iw_get_ext(self->sock, self->ifname, SIOCGIWSCAN, &wrq) < 0) { if ((errno == E2BIG)) { if (wrq.u.data.length > buflen) buflen = wrq.u.data.length; else buflen *= 2; goto realloc; } if (errno == EAGAIN) { tv.tv_sec = 0; tv.tv_usec = 100000; timeout -= tv.tv_usec; if (timeout > 0) continue; } free(buffer); PyErr_SetString(IwScanError, "Unable to read scan data"); return NULL; } else break; } } if (wrq.u.data.length) { iwevent iwe; stream_descr stream; int ret; PyObject* scan_dict = NULL; scan_list = PyList_New(0); iw_init_event_stream(&stream, (char*)(buffer), wrq.u.data.length); do { ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); if (ret > 0) { wifacesd sd; int sr = WirelessInterface_ScanItem(&sd, &iwe, &range, has_range); if (sr) { int i; if (scan_dict) { PyList_Append(scan_list, scan_dict); Py_DECREF(scan_dict); } scan_dict = PyDict_New(); for (i = 0; i < IWSCAN_INTERFACE_KEYS; i++) { PyMapping_SetItemString(scan_dict, WirelessInterfaceKeys[i], Py_BuildValue("")); } } if (sd.num) { int i; for (i = 0; i < sd.num; i++) { PyMapping_SetItemString(scan_dict, WirelessInterfaceKeys[sd.keys[i]], sd.objs[i]); Py_DECREF(sd.objs[i]); } } } } while (ret > 0); PyList_Append(scan_list, scan_dict); Py_XDECREF(scan_dict); } else return Py_BuildValue("[]"); free(buffer); return scan_list; }
//noise levels, returned by this functions, are invalid, don't use them void CWextHW::readScanResults() { if (m_wextFd == -1) { return; } //Kill Timer: if (m_scTimerId != -1) { killTimer(m_scPollrate); m_scTimerId = -1; } else { //This is not a timer call; this should not happen qWarning() << tr("Warning, no timer present while trying to get scan results"); return; } struct iwreq wrq; memset(&wrq,0,sizeof(struct iwreq)); unsigned char * buffer = NULL; /* Results */ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */ struct iw_range range; memset(&range,0,sizeof(struct iw_range)); int has_range; QList<WextRawScan> res = QList<WextRawScan>(); WextRawScan singleres; singleres.bssid = libnutcommon::MacAddress(); singleres.group = GCI_UNDEFINED; singleres.pairwise = PCI_UNDEFINED; singleres.protocols = PROTO_UNDEFINED; singleres.keyManagement = KM_UNDEFINED; /* workaround */ struct wireless_config wifiConfig; memset(&wifiConfig,0,sizeof(struct wireless_config)); /* Get basic information */ if(iw_get_basic_config(m_wextFd, m_ifname.toAscii().constData(), &wifiConfig) < 0) { /* If no wireless name : no wireless extensions */ /* But let's check if the interface exists at all */ struct ifreq ifr; memset(&ifr,0,sizeof(struct ifreq)); strncpy(ifr.ifr_name, m_ifname.toAscii().data(), IFNAMSIZ); if(ioctl(m_wextFd, SIOCGIFFLAGS, &ifr) < 0) qWarning() << tr("(Wireless Extension) No device present"); else qWarning() << tr("(Wireless Extension) Device not supported"); return; } qDebug() << "Fetched basic config."; /* Get AP address */ if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWAP, &wrq) >= 0) { qDebug() << "Got AP"; } /* Get bit rate */ if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWRATE, &wrq) >= 0) { qDebug() << "Got bit rate"; } /* Get Power Management settings */ wrq.u.power.flags = 0; if(iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWPOWER, &wrq) >= 0) { qDebug() << "Got power"; } /* workaround */ /* Get range stuff */ /* Get range stuff */ qDebug() << QString("Getting range stuff for %1").arg(m_ifname.toAscii().data()); if (iw_get_range_info(m_wextFd, m_ifname.toAscii().data(), &range) >= 0) { has_range = 1; qDebug() << "Success readWirelessInfo getrange" << strerror(errno); } else { //This is VERY strange: we always get the "operation not permitted" error, although iw_get_range() worked qDebug() << QString("Error \"hasRange == 0\" (%1)").arg(strerror(errno)); } singleres.hasRange = has_range; //If we get a timeout for more than 5 times, stop polling. if (errno == EAGAIN) { qDebug() << "Scan results not available yet"; m_scTimeOutCount++; if (m_scTimeOutCount == 5) { return; } m_scTimerId = startTimer(m_scPollrate); return; } qDebug() << "Got range stuff"; if (has_range) { singleres.maxquality.level = (quint8) range.max_qual.level; singleres.maxquality.qual = (quint8) range.max_qual.qual; singleres.maxquality.noise = (quint8) range.max_qual.noise; singleres.maxquality.updated = (quint8) range.max_qual.updated; qDebug() << "RANGE (scanresults): " << singleres.maxquality.level << singleres.maxquality.qual << singleres.maxquality.noise << singleres.maxquality.updated; } else { singleres.maxquality.level = 0; singleres.maxquality.qual = 0; singleres.maxquality.noise = 0; singleres.maxquality.updated = 0; qWarning() << tr("Range information are not available"); } unsigned char * newbuf; for (int i=0; i <= 16; i++) { //realloc (don't do this forever) //Allocate newbuffer newbuf = (uchar*) realloc(buffer, buflen); if(newbuf == NULL) { if (buffer) { free(buffer); buffer = NULL; } qDebug() << "Allocating buffer for Wext failed"; return; } buffer = newbuf; //Set Request variables: wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; //Get the data: if (iw_get_ext(m_wextFd, m_ifname.toAscii().data(), SIOCGIWSCAN, &wrq) < 0) { //Buffer is too small if((errno == E2BIG) && (range.we_version_compiled > 16)) { //check if driver gives any hints about scan length: if (wrq.u.data.length > buflen) { buflen = wrq.u.data.length; } else { //If not, double the length buflen *= 2; } //Start from the beginning: qDebug() << "Buffer was too small"; continue; } //No range error occured or kernel has wireless extension < 16 if (errno == EAGAIN) { qDebug() << "Scan results not available yet"; m_scTimerId = startTimer(m_scPollrate); return; } //Bad error occured if (buffer) { free(buffer); buffer = NULL; } qWarning() << tr("(%1) Failed to read scan data : %2").arg(m_ifname, QString(strerror(errno))); } else { //Results are there break; } } //Now read the data: if (wrq.u.data.length) { struct iw_event iwe; memset(&iwe,0,sizeof(struct iw_event)); struct stream_descr stream; memset(&stream,0,sizeof(struct stream_descr)); int ret; //Init event stream // char buffer2[128]; libnutcommon::MacAddress tmpMac; iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); do { /* Extract an event and parse it*/ memset(&iwe,0,sizeof(struct iw_event)); //valgrind complains about it? ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); if(ret > 0) { //Now parse our scan event: switch(iwe.cmd) { case SIOCGIWAP: //ap_addr has type socketaddr //Workaround for macaddress // iw_saether_ntop(&(iwe.u.ap_addr), buffer2); // tmpMac = libnutcommon::MacAddress(QString::fromAscii(buffer2,128)); tmpMac = libnutcommon::MacAddress( (ether_addr*) iwe.u.ap_addr.sa_data); if (singleres.bssid.zero()) { //First bssid singleres.bssid = tmpMac; qDebug() << "Start parsing one network" << singleres.bssid.toString(); } // if our last bssid is different from the actual one, then we have to append it to our scanlist if ( (singleres.bssid != tmpMac) ) { res.append(singleres); qDebug() << "End parsing one network" << singleres.bssid.toString(); //reset singleres singleres.ssid = QString(); singleres.bssid.clear(); singleres.quality = WextRawSignal(); singleres.freq = -1; singleres.group = GCI_UNDEFINED; singleres.pairwise = PCI_UNDEFINED; singleres.keyManagement = KM_UNDEFINED; singleres.protocols = PROTO_UNDEFINED; singleres.opmode = OPM_AUTO; singleres.bssid = tmpMac; qDebug() << "Start parsing one network" << singleres.bssid.toString(); } qDebug() << "BSSID" << singleres.bssid.toString(); break; case IWEVQUAL: //Quality event: qDebug() << "Quality" << singleres.bssid.toString(); singleres.quality.qual = (quint8) iwe.u.qual.qual; singleres.quality.level = (quint8) iwe.u.qual.level; singleres.quality.noise = (quint8) iwe.u.qual.noise; singleres.quality.updated = (quint8) iwe.u.qual.updated; qDebug() << "STATS (scanresults): " << singleres.quality.level << singleres.quality.qual << singleres.quality.noise << singleres.quality.updated; break; case SIOCGIWFREQ: qDebug() << "Frequency" << singleres.bssid.toString(); { double freq; freq = iw_freq2float(&(iwe.u.freq)); //Hopefully in hz if ( ( (freq/1e9) < 10.0 ) && ( (freq/1e9) > 0.0 ) ) { singleres.freq = (int) (freq/1e6); qDebug() << "Channel for" << singleres.ssid << "is " << freq << singleres.freq; } else { singleres.freq = -1; } } break; case SIOCGIWMODE: qDebug() << "Mode:" << singleres.bssid.toString(); if(iwe.u.mode >= IW_NUM_OPER_MODE) { iwe.u.mode = IW_NUM_OPER_MODE; } singleres.opmode = (OPMODE) iwe.u.mode; break; case SIOCGIWESSID: qDebug() << "ESSID:" << singleres.bssid.toString(); if (iwe.u.essid.flags) { /* Does it have an ESSID index ? */ if ( iwe.u.essid.pointer && iwe.u.essid.length ) { if ( (iwe.u.essid.flags & IW_ENCODE_INDEX) > 1) { singleres.ssid = QString("%1 [%2]").arg(QString::fromAscii((char*) iwe.u.essid.pointer,iwe.u.essid.length), QString::number(iwe.u.essid.flags & IW_ENCODE_INDEX)); } else { singleres.ssid = QString("%1").arg(QString::fromAscii((char*) iwe.u.essid.pointer,iwe.u.essid.length)); } } else { singleres.ssid = QString("N/A"); } } else { //Hidden essid or broken driver singleres.ssid = QString(); } break; case SIOCGIWENCODE: //Get encrytion stuff: (just the key) qDebug() << "Encode" << singleres.bssid.toString(); if (! iwe.u.data.pointer) { iwe.u.data.flags |= IW_ENCODE_NOKEY; } if(iwe.u.data.flags & IW_ENCODE_DISABLED) { //Encryption is disabled singleres.keyManagement = KM_NONE; qDebug() << "PARING ENCODE-Information: NO KEY"; } else { //Extract key information: (See iwlib.c line 1500) //keyflags: iwe.u.data.flags //keysize = iwe.u.data.length // //Do we have a key if (iwe.u.data.flags & IW_ENCODE_NOKEY) { //no key if (iwe.u.data.length <= 0) { //Encryption is on, but group is unknown singleres.keyManagement = KM_NONE; qDebug() << "PARSING ENCODE-INFORMATION: WEP KEY"; } } //else: we have a, key but check type later } break; case SIOCGIWRATE: singleres.bitrates.append((qint32) iwe.u.bitrate.value); qDebug() << "Adding Bitrate: " << (qint32) iwe.u.bitrate.value; break; case IWEVGENIE: //group/pairwsie ciphers etc. //buffer = iwe.u.data.pointer //bufflen = iwe.u.data.length qDebug() << "IE_START" << singleres.bssid.toString(); { int offset = 0; /* Loop on each IE, each IE is minimum 2 bytes */ while(offset <= (iwe.u.data.length - 2)) { /* Check IE type */ if (0xdd == ((uchar *) iwe.u.data.pointer)[offset] || (0x30 == ((uchar *) iwe.u.data.pointer)[offset]) ) { // WPA1/2 parseWextIeWpa(((uchar *) iwe.u.data.pointer) + offset, iwe.u.data.length, &singleres); qDebug() << "Parsed IE-Information of " << singleres.ssid << singleres.bssid.toString(); qDebug() << toString(singleres.group) << toString(singleres.pairwise) << toString(singleres.keyManagement); } /* Skip over this IE to the next one in the list. */ offset += buffer[offset+1] + 2; } } qDebug() << "IE_END" << singleres.bssid.toString(); break; default: //Ignore all other event types. Maybe we need them later? break; } } else { //Append last scan: if (!singleres.bssid.zero()) { res.append(singleres); qDebug() << "End parsing one network" << singleres.bssid.toString(); } } } while(ret > 0); //Delete buffer if (buffer) { free(buffer); buffer = NULL; } //We have the data, now construct complete ScanResult setScanResults(res); } else { qWarning() << tr("No Scanresults available"); setScanResults(QList<WextRawScan>()); } if (buffer) { free(buffer); buffer = NULL; } }
static inline void llf_handle_netlink_events(struct rtnl_handle *rth) { while (1) { struct sockaddr_nl sanl; socklen_t sanllen; struct nlmsghdr *h; struct ifinfomsg *ifi; int amt; char buf[8192]; amt = recvfrom(rth->fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *) &sanl, &sanllen); if (amt < 0) { if (errno != EINTR && errno != EAGAIN) { fprintf(stderr, "%s: error reading netlink: %s.\n", __PRETTY_FUNCTION__, strerror(errno)); } return; } if (amt == 0) { fprintf(stderr, "%s: EOF on netlink??\n", __PRETTY_FUNCTION__); return; } h = (struct nlmsghdr *) buf; while (amt >= (int) sizeof(*h)) { int len = h->nlmsg_len; int l = len - sizeof(*h); if (l < 0 || len > amt) { fprintf(stderr, "%s: malformed netlink message: len=%d\n", __PRETTY_FUNCTION__, len); break; } switch (h->nlmsg_type) { case RTM_NEWLINK: // LinkCatcher(h); if (h->nlmsg_type != RTM_NEWLINK) return; ifi = NLMSG_DATA(h); /* Check for attributes */ if (h->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) { int attrlen = h->nlmsg_len - NLMSG_ALIGN(sizeof(struct ifinfomsg)); struct rtattr *attr = (void *) ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg)); while (RTA_OK(attr, attrlen)) { /* Check if the Wireless kind */ if (attr->rta_type == IFLA_WIRELESS) { struct iw_event iwe; struct stream_descr stream; int ret; #if WE_VERSION >= 17 struct wireless_iface *wireless_data; /* Get data from cache */ wireless_data = iw_get_interface_data(ifi->ifi_index); if (wireless_data == NULL) return; #endif /* Go to display it */ iw_init_event_stream(&stream, (void *) attr + RTA_ALIGN(sizeof (struct rtattr)), attr->rta_len - RTA_ALIGN(sizeof (struct rtattr))); do { /* Extract an event and print it */ #if WE_VERSION >= 17 ret = iw_extract_event_stream(&stream, &iwe, wireless_data-> range. we_version_compiled); #else ret = iw_extract_event_stream(&stream, &iwe); #endif if (ret != 0) { if (ret > 0) llf_print_event(&iwe, NULL, 0); else DEBUG(LOG_WARNING, 0, "Invalid iw event"); } } while (ret > 0); } attr = RTA_NEXT(attr, attrlen); } } break; default: #if 0 fprintf(stderr, "%s: got nlmsg of type %#x.\n", __PRETTY_FUNCTION__, h->nlmsg_type); #endif break; } len = NLMSG_ALIGN(len); amt -= len; h = (struct nlmsghdr *) ((char *) h + len); } if (amt > 0) fprintf(stderr, "%s: remnant of size %d on netlink\n", __PRETTY_FUNCTION__, amt); } }
bool WifiStumbler::stumble() { int pid; pid = getpid(); struct iwreq w_request; w_request.u.data.pointer = (caddr_t)&pid; w_request.u.data.length = 0; if (iw_set_ext(wlan_sock_, wlan_if_.c_str(), SIOCSIWSCAN, &w_request) < 0) { ROS_ERROR("Couldn't start stumbler."); return false; } timeval time; time.tv_sec = 0; time.tv_usec = 200000; uint8_t *p_buff = NULL; int buff_size = IW_SCAN_MAX_DATA; bool is_end = false; while(!is_end) { fd_set fds; int ret; FD_ZERO(&fds); ret = select(0, &fds, NULL, NULL, &time); if (ret == 0) { uint8_t *p_buff2; while (!is_end) { p_buff2 = (uint8_t *)realloc(p_buff, buff_size); p_buff = p_buff2; w_request.u.data.pointer = p_buff; w_request.u.data.flags = 0; w_request.u.data.length = buff_size; if (iw_get_ext(wlan_sock_, wlan_if_.c_str(), SIOCGIWSCAN, &w_request) < 0) { if (errno == E2BIG && range_.we_version_compiled > 16) { if (w_request.u.data.length > buff_size) buff_size = w_request.u.data.length; else buff_size *= 2; continue; } else if (errno == EAGAIN) { time.tv_sec = 0; time.tv_usec = 200000; break; } } else is_end = true; } } } // Put wifi data into ROS message wifi_tools::AccessPoint ap; iw_event event; stream_descr stream; wifi_stumble_.data.clear(); wifi_stumble_.header.stamp = ros::Time::now(); iw_init_event_stream(&stream, (char *)p_buff, w_request.u.data.length); is_end = false; int value = 0; while(!is_end) { value = iw_extract_event_stream(&stream, &event, range_.we_version_compiled); if(!(value>0)) { is_end = true; } else { if(event.cmd == IWEVQUAL) { // quality part of statistics //ROS_INFO("command=IWEVQUAL"); if (event.u.qual.level != 0 || (event.u.qual.updated & (IW_QUAL_DBM | IW_QUAL_RCPI))) { ap.noise = event.u.qual.noise; ap.ss = event.u.qual.level; } } else if(event.cmd == SIOCGIWAP) { // get access point MAC addresses //ROS_INFO("command=SIOCGIWAP"); char mac_buff[1024]; iw_ether_ntop((const struct ether_addr *)&event.u.ap_addr.sa_data,mac_buff); ap.mac_address = std::string(mac_buff); ROS_INFO("mac_addr=%s",mac_buff); } else if(event.cmd == SIOCGIWESSID) { // get ESSID //ROS_INFO("command=SIOCGIWESSID"); wifi_stumble_.data.push_back(ap); } else if(event.cmd == SIOCGIWENCODE) { // get encoding token & mode //ROS_INFO("command=SIOCGIWENCODE"); } else if(event.cmd == SIOCGIWFREQ) { // get channel/frequency (Hz) //ROS_INFO("command=SIOCGIWFREQ"); } else if(event.cmd == SIOCGIWRATE) { // get default bit rate (bps) //ROS_INFO("command=SIOCGIWRATE"); } else if(event.cmd == SIOCGIWMODE) { // get operation mode //ROS_INFO("command=SIOCGIWMODE"); } else if(event.cmd == IWEVCUSTOM) { // Driver specific ascii string //ROS_INFO("command=IWEVCUSTOM"); } else if(event.cmd == IWEVGENIE) { // Generic IE (WPA, RSN, WMM, ..) //ROS_INFO("command=IWEVGENIE"); } else { // another command //ROS_INFO("another command"); } } } checkDuplication(); return true; }
/* * Perform a scanning on one device */ static int print_scanning_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; unsigned char * buffer = NULL; /* Results */ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */ struct iw_range range; int has_range; struct timeval tv; /* Select timeout */ int timeout = 15000000; /* 15s */ /* Avoid "Unused parameter" warning */ args = args; count = count; /* Get range stuff */ has_range = (iw_get_range_info(skfd, ifname, &range) >= 0); /* Check if the interface could support scanning. */ if((!has_range) || (range.we_version_compiled < 14)) { fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n", ifname); return(-1); } /* Init timeout value -> 250ms*/ tv.tv_sec = 0; tv.tv_usec = 250000; /* * Here we should look at the command line args and set the IW_SCAN_ flags * properly */ wrq.u.data.pointer = NULL; /* Later */ wrq.u.data.flags = 0; wrq.u.data.length = 0; /* Initiate Scanning */ if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0) { if(errno != EPERM) { fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n", ifname, strerror(errno)); return(-1); } /* If we don't have the permission to initiate the scan, we may * still have permission to read left-over results. * But, don't wait !!! */ #if 0 /* Not cool, it display for non wireless interfaces... */ fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname); #endif tv.tv_usec = 0; } timeout -= tv.tv_usec; /* Forever */ while(1) { fd_set rfds; /* File descriptors for select */ int last_fd; /* Last fd */ int ret; /* Guess what ? We must re-generate rfds each time */ FD_ZERO(&rfds); last_fd = -1; /* In here, add the rtnetlink fd in the list */ /* Wait until something happens */ ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); /* Check if there was an error */ if(ret < 0) { if(errno == EAGAIN || errno == EINTR) continue; fprintf(stderr, "Unhandled signal - exiting...\n"); return(-1); } /* Check if there was a timeout */ if(ret == 0) { unsigned char * newbuf; realloc: /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ newbuf = realloc(buffer, buflen); if(newbuf == NULL) { if(buffer) free(buffer); fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__); return(-1); } buffer = newbuf; /* Try to read the results */ wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0) { /* Check if buffer was too small (WE-17 only) */ if((errno == E2BIG) && (range.we_version_compiled > 16)) { /* Some driver may return very large scan results, either * because there are many cells, or because they have many * large elements in cells (like IWEVCUSTOM). Most will * only need the regular sized buffer. We now use a dynamic * allocation of the buffer to satisfy everybody. Of course, * as we don't know in advance the size of the array, we try * various increasing sizes. Jean II */ /* Check if the driver gave us any hints. */ if(wrq.u.data.length > buflen) buflen = wrq.u.data.length; else buflen *= 2; /* Try again */ goto realloc; } /* Check if results not available yet */ if(errno == EAGAIN) { /* Restart timer for only 100ms*/ tv.tv_sec = 0; tv.tv_usec = 100000; timeout -= tv.tv_usec; if(timeout > 0) continue; /* Try again later */ } /* Bad error */ free(buffer); fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n", ifname, strerror(errno)); return(-2); } else /* We have the results, go to process them */ break; } /* In here, check if event and event type * if scan event, read results. All errors bad & no reset timeout */ } if(wrq.u.data.length) { struct iw_event iwe; struct stream_descr stream; struct iwscan_state state = { .ap_num = 1, .val_index = 0 }; int ret; #if 0 /* Debugging code. In theory useless, because it's debugged ;-) */ int i; printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]); for(i = 1; i < wrq.u.data.length; i++) printf(":%02X", buffer[i]); printf("]\n"); #endif printf("%-8.16s Scan completed :\n", ifname); iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); if(ret > 0) print_scanning_token(&stream, &iwe, &state, &range, has_range); } while(ret > 0); printf("\n"); } else printf("%-8.16s No scan results\n", ifname); free(buffer); return(0); }