00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "wifiscan.h"
00020
00021 struct wireless_scan * WifiScan::iw_process_scanning_token(
00022 struct iw_event * event, struct wireless_scan * wscan)
00023 {
00024 struct wireless_scan * oldwscan;
00025
00026
00027 switch (event->cmd)
00028 {
00029 case SIOCGIWAP:
00030
00031 oldwscan = wscan;
00032 wscan = (struct wireless_scan *)malloc(sizeof(struct wireless_scan));
00033 if (wscan == NULL)
00034 return (wscan);
00035
00036 if (oldwscan != NULL)
00037 oldwscan->next = wscan;
00038
00039
00040 bzero(wscan, sizeof(struct wireless_scan));
00041
00042
00043 wscan->has_ap_addr = 1;
00044 memcpy(&(wscan->ap_addr), &(event->u.ap_addr), sizeof(sockaddr));
00045 break;
00046 case SIOCGIWNWID:
00047 wscan->b.has_nwid = 1;
00048 memcpy(&(wscan->b.nwid), &(event->u.nwid), sizeof(iwparam));
00049 break;
00050 case SIOCGIWFREQ:
00051 wscan->b.has_freq = 1;
00052 wscan->b.freq = iw_freq2float(&(event->u.freq));
00053 wscan->b.freq_flags = event->u.freq.flags;
00054 break;
00055 case SIOCGIWMODE:
00056 wscan->b.mode = event->u.mode;
00057 if ((wscan->b.mode < IW_NUM_OPER_MODE) && (wscan->b.mode >= 0))
00058 wscan->b.has_mode = 1;
00059 break;
00060 case SIOCGIWESSID:
00061 wscan->b.has_essid = 1;
00062 wscan->b.essid_on = event->u.data.flags;
00063 memset(wscan->b.essid, '\0', IW_ESSID_MAX_SIZE + 1);
00064 if ((event->u.essid.pointer) && (event->u.essid.length))
00065 memcpy(wscan->b.essid, event->u.essid.pointer, event->u.essid.length);
00066 break;
00067 case SIOCGIWENCODE:
00068 wscan->b.has_key = 1;
00069 wscan->b.key_size = event->u.data.length;
00070 wscan->b.key_flags = event->u.data.flags;
00071 if (event->u.data.pointer)
00072 memcpy(wscan->b.key, event->u.essid.pointer, event->u.data.length);
00073 else
00074 wscan->b.key_flags |= IW_ENCODE_NOKEY;
00075 break;
00076 case IWEVQUAL:
00077
00078 wscan->has_stats = 1;
00079 memcpy(&wscan->stats.qual, &event->u.qual, sizeof(struct iw_quality));
00080 break;
00081 case SIOCGIWRATE:
00082
00083
00084 if ((!wscan->has_maxbitrate) ||
00085 (event->u.bitrate.value > wscan->maxbitrate.value))
00086 {
00087 wscan->has_maxbitrate = 1;
00088 memcpy(&(wscan->maxbitrate), &(event->u.bitrate), sizeof(iwparam));
00089 }
00090 case IWEVCUSTOM:
00091
00092 default:
00093 break;
00094 }
00095
00096 return (wscan);
00097 }
00098
00099 int WifiScan::scan_channels(wireless_scan_head * context)
00100 {
00101 struct iwreq wrq;
00102 struct iw_scan_req scanopt;
00103 int scanflags = 0;
00104 unsigned char * buffer = NULL;
00105 int buflen = IW_SCAN_MAX_DATA;
00106 struct iw_range range;
00107 int has_range;
00108 struct timeval tv;
00109 int timeout = 15000000;
00110
00111
00112
00113
00114
00115
00116
00117 has_range = (iw_get_range_info(socket_, interface_, &range) >= 0);
00118 if ((!has_range) || (range.we_version_compiled < 14))
00119 {
00120 std::cerr << interface_ << "does not support scanning." << std::endl;
00121 return SCAN_CHANNELS_NO_SCAN_SUPPORT;
00122 }
00123
00124
00125
00126
00127 tv.tv_sec = 0;
00128 tv.tv_usec = 250000;
00129
00130
00131 memset(&scanopt, 0, sizeof(scanopt));
00132
00133
00134 double channel_to_freq;
00135 iw_freq freq;
00136 for (int i = 0; i < channels_.size(); i++)
00137 {
00138 iw_channel_to_freq(channels_[i], &channel_to_freq, &range);
00139 iw_float2freq(channel_to_freq, &freq);
00140 scanopt.channel_list[i] = freq;
00141 }
00142 scanopt.num_channels = channels_.size();
00143
00144 wrq.u.data.pointer = (caddr_t)&scanopt;
00145 wrq.u.data.length = sizeof(scanopt);
00146 wrq.u.data.flags = scanflags;
00147
00148
00149 if (iw_set_ext(socket_, interface_, SIOCSIWSCAN, &wrq) < 0)
00150 {
00151 if ((errno != EPERM) || (scanflags != 0))
00152 {
00153 std::cerr << interface_ << "does not support scanning: "
00154 << strerror(errno) << std::endl;
00155 return SCAN_CHANNELS_NO_SCAN_SUPPORT;
00156 }
00157 tv.tv_usec = 0;
00158 }
00159 usleep(tv.tv_usec);
00160 timeout -= tv.tv_usec;
00161
00162 while (true)
00163 {
00164 fd_set rfds;
00165 int last_fd;
00166 int ret;
00167
00168 FD_ZERO(&rfds);
00169 last_fd = -1;
00170
00171 ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
00172 if (ret < 0)
00173 {
00174 if (errno == EAGAIN || errno == EINTR)
00175 continue;
00176 std::cerr << "Unhandled signal, exiting..." << std::endl;
00177 return SCAN_CHANNELS_UNHANDLED_SIGNAL;
00178 }
00179
00180 if (ret == 0)
00181 {
00182 unsigned char * newbuf;
00183
00184 realloc:
00185
00186 newbuf = (unsigned char *)realloc(buffer, buflen);
00187 if (newbuf == NULL)
00188 {
00189 if (buffer)
00190 free(buffer);
00191 std::cerr << "Allocation failed." << std::endl;
00192 return SCAN_CHANNELS_ALLOCATION_FAILED;
00193 }
00194 buffer = newbuf;
00195
00196
00197 wrq.u.data.pointer = buffer;
00198 wrq.u.data.flags = 0;
00199 wrq.u.data.length = buflen;
00200 if (iw_get_ext(socket_, interface_, SIOCGIWSCAN, &wrq) < 0)
00201 {
00202
00203 if ((errno == E2BIG) && (range.we_version_compiled > 16)
00204 && (buflen < 0xFFFF))
00205 {
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 if (wrq.u.data.length > buflen)
00216 buflen = wrq.u.data.length;
00217 else
00218 buflen *= 2;
00219
00220
00221 if (buflen > 0xFFFF)
00222 buflen = 0xFFFF;
00223
00224
00225 goto realloc;
00226 }
00227
00228
00229 if (errno == EAGAIN)
00230 {
00231
00232 tv.tv_sec = 0;
00233 tv.tv_usec = 100000;
00234 timeout -= tv.tv_usec;
00235 if (timeout > 0)
00236 {
00237 usleep(tv.tv_usec);
00238 continue;
00239 }
00240 }
00241
00242
00243 free(buffer);
00244 std::cerr << interface_ << ": failed to read scan data: "
00245 << strerror(errno) << std::endl;
00246 return SCAN_CHANNELS_FAILED_TO_READ;
00247 }
00248 else
00249 break;
00250 }
00251 }
00252
00253 if (wrq.u.data.length)
00254 {
00255 struct iw_event iwe;
00256 struct stream_descr stream;
00257 struct wireless_scan * wscan = NULL;
00258 struct iwscan_state state = { 1, 0};
00259 int ret;
00260
00261 iw_init_event_stream(&stream, (char *)buffer, wrq.u.data.length);
00262
00263 context->result = NULL;
00264
00265
00266 do
00267 {
00268
00269 ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled);
00270 if (ret > 0)
00271 {
00272
00273 wscan = iw_process_scanning_token(&iwe, wscan);
00274
00275 if (wscan == NULL)
00276 {
00277 free(buffer);
00278 errno = ENOMEM;
00279 return SCAN_CHANNELS_PROBLEMS_PROCESSING;
00280 }
00281
00282 if (context->result == NULL)
00283 context->result = wscan;
00284 }
00285 } while (ret > 0);
00286
00287 std::cout << interface_ << ": scan completed" << std::endl;
00288 }
00289 else
00290 std::cout << interface_ << ": no scan results" << std::endl;
00291
00292 free(buffer);
00293 return 0;
00294 }
00295
00296 bool WifiScan::DeviceAddressCompare::operator ()(const std::string &lhs,
00297 const std::string &rhs) const
00298 {
00299 return lhs.substr(0, 10) < rhs.substr(0, 10);
00300 }
00301
00302 double WifiScan::MeanRSSI(const std::vector<double> &RSSIValues)
00303 {
00304 double total = 0.0;
00305 for (std::vector<double>::const_iterator it = RSSIValues.begin();
00306 it != RSSIValues.end(); it++)
00307 {
00308 total += *it;
00309 }
00310 return total / RSSIValues.size();
00311 }
00312
00313 WifiScan::WifiScan(std::vector<int> channels, std::string interface)
00314 {
00315 interface_ = new char[interface.length() + 1];
00316 std::strcpy(interface_, interface.c_str());
00317 channels_ = channels;
00318
00319 if ((socket_ = iw_sockets_open()) < 0)
00320 throw WIFISCAN_ERROR_OPENING_IOCTL_SOCKET;
00321 kernel_version_ = iw_get_kernel_we_version();
00322 if (iw_get_range_info(socket_, interface_, &range_) < 0)
00323 throw WIFISCAN_ERROR_GETTING_RANGE_INFO;
00324 }
00325
00326 WifiScan::~WifiScan()
00327 {
00328 iw_sockets_close(socket_);
00329 }
00330
00331 void WifiScan::createFingerprint(ros::Publisher *pub)
00332 {
00333 wireless_scan_head scan_context;
00334
00335 if (geteuid() != 0)
00336 ROS_FATAL_STREAM("uid: " << geteuid());
00337
00338 if (scan_channels(&scan_context) < 0)
00339 throw WIFISCAN_ERROR_IN_IW_SCAN;
00340 if (scan_context.result != 0)
00341 ROS_DEBUG_STREAM("Fingerprint collected, publishing...");
00342
00343
00344 std::map<std::string, double, DeviceAddressCompare> fingerprint;
00345 std::map<std::string, std::vector<double> > devicesWithMoreSSIDs;
00346 for (wireless_scan *i = scan_context.result; i != 0; i = i->next)
00347 {
00348
00349 char address[128];
00350 snprintf(address, 128, "%02X%02X%02X%02X%02X%02X",
00351 (unsigned char)i->ap_addr.sa_data[0],
00352 (unsigned char)i->ap_addr.sa_data[1],
00353 (unsigned char)i->ap_addr.sa_data[2],
00354 (unsigned char)i->ap_addr.sa_data[3],
00355 (unsigned char)i->ap_addr.sa_data[4],
00356 (unsigned char)i->ap_addr.sa_data[5]);
00357
00358
00359 double dBm;
00360 if (i->stats.qual.updated & IW_QUAL_DBM)
00361 {
00362 dBm = i->stats.qual.level;
00363 if (i->stats.qual.level >= 64)
00364 dBm -= 0x100;
00365 }
00366 else if (i->stats.qual.updated & IW_QUAL_RCPI)
00367 {
00368 dBm = (i->stats.qual.level / 2.0) - 110.0;
00369 }
00370
00371
00372 std::pair<std::map<std::string, double>::iterator, bool> ret;
00373 ret = fingerprint.insert(
00374 std::pair<std::string, double>(std::string(address), dBm));
00375 if (ret.second == false)
00376 {
00377 std::vector<double> RSSIValues;
00378 std::string newSSID = std::string(address);
00379 std::map<std::string, std::vector<double> >::iterator deviceWithMoreSSIDs;
00380 deviceWithMoreSSIDs = devicesWithMoreSSIDs.find(newSSID.substr(0, 10));
00381
00382 if (deviceWithMoreSSIDs == devicesWithMoreSSIDs.end())
00383 {
00384 if (ret.first->first.substr(11, 2) == newSSID.substr(11, 2))
00385 {
00386 ROS_WARN_STREAM("Address not unique.");
00387 }
00388 else
00389 {
00390 RSSIValues.push_back(dBm);
00391 RSSIValues.push_back(ret.first->second);
00392 newSSID = newSSID.substr(0, 10);
00393 devicesWithMoreSSIDs.insert(
00394 std::pair<std::string, std::vector<double> >(newSSID,
00395 RSSIValues));
00396 dBm = MeanRSSI(RSSIValues);
00397 fingerprint.erase(ret.first);
00398 fingerprint.insert(
00399 std::pair<std::string, double>(newSSID + "**", dBm));
00400 }
00401 }
00402 else
00403 {
00404 RSSIValues = deviceWithMoreSSIDs->second;
00405 RSSIValues.push_back(dBm);
00406 deviceWithMoreSSIDs->second = RSSIValues;
00407 dBm = MeanRSSI(RSSIValues);
00408 ret.first->second = dBm;
00409 }
00410 }
00411 }
00412
00413
00414 wifi_scan::Fingerprint fingerprint_message;
00415 fingerprint_message.list.clear();
00416 for (std::map<std::string, double>::iterator it = fingerprint.begin();
00417 it != fingerprint.end();
00418 it++)
00419 {
00420 wifi_scan::AddressRSSI address_rssi;
00421 address_rssi.address = it->first;
00422 address_rssi.rssi = it->second;
00423 ROS_DEBUG_STREAM(it->first << ", " << it->second);
00424 fingerprint_message.list.push_back(address_rssi);
00425 }
00426 fingerprint_message.header.stamp = ros::Time::now();
00427 pub->publish(fingerprint_message);
00428 }
00429