Exemple #1
0
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);
}
Exemple #2
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(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);
}
Exemple #4
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;
}
Exemple #5
0
/* ---------------------------------------------------------------------- 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;
}
Exemple #6
0
//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;
	}
}
Exemple #7
0
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);
    }
}
Exemple #8
0
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;
}
Exemple #9
0
/*
 * 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);
}