⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iwevent.c

📁 iwconfig iwlist iwpriv
💻 C
字号:
/* *	Wireless Tools * *		Jean II - HPL 99->01 * * Main code for "iwevent". This listent for wireless events on rtnetlink. * You need to link this code against "iwcommon.c" and "-lm". * * Part of this code is from Alexey Kuznetsov, part is from Casey Carter, * I've just put the pieces together... * By the way, if you know a way to remove the root restrictions, tell me * about it... * * This file is released under the GPL license. *     Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com> *//***************************** INCLUDES *****************************/#include "iwlib.h"		/* Header */#include <linux/netlink.h>#include <linux/rtnetlink.h>#include <getopt.h>#include <time.h>#include <sys/time.h>/* Ugly backward compatibility :-( */#ifndef IFLA_WIRELESS#define IFLA_WIRELESS	(IFLA_MASTER + 1)#endif /* IFLA_WIRELESS *//************************ RTNETLINK HELPERS ************************//* * The following code is extracted from : * ---------------------------------------------- * libnetlink.c	RTnetlink service routines. * *		This program 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. * * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> * ----------------------------------------------- */struct rtnl_handle{	int			fd;	struct sockaddr_nl	local;	struct sockaddr_nl	peer;	__u32			seq;	__u32			dump;};static inline void rtnl_close(struct rtnl_handle *rth){	close(rth->fd);}static inline int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions){	int addr_len;	memset(rth, 0, sizeof(rth));	rth->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);	if (rth->fd < 0) {		perror("Cannot open netlink socket");		return -1;	}	memset(&rth->local, 0, sizeof(rth->local));	rth->local.nl_family = AF_NETLINK;	rth->local.nl_groups = subscriptions;	if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {		perror("Cannot bind netlink socket");		return -1;	}	addr_len = sizeof(rth->local);	if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {		perror("Cannot getsockname");		return -1;	}	if (addr_len != sizeof(rth->local)) {		fprintf(stderr, "Wrong address length %d\n", addr_len);		return -1;	}	if (rth->local.nl_family != AF_NETLINK) {		fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family);		return -1;	}	rth->seq = time(NULL);	return 0;}/********************* WIRELESS EVENT DECODING *********************//* * This is the bit I wrote... */#if WIRELESS_EXT > 13/*------------------------------------------------------------------*//* * Print one element from the scanning results */static inline intprint_event_token(struct iw_event *	event,	/* Extracted token */		  char *		ifname,		  struct iw_range *	iwrange,	/* Range info */		  int			has_iwrange){  char		buffer[128];	/* Temporary buffer */  /* Now, let's decode the event */  switch(event->cmd)    {      /* ----- set events ----- */      /* Events that result from a "SET XXX" operation by the user */    case SIOCSIWNWID:      if(event->u.nwid.disabled)	printf("NWID:off/any\n");      else	printf("NWID:%X\n", event->u.nwid.value);      break;    case SIOCSIWFREQ:      {	float		freq;			/* Frequency/channel */	freq = iw_freq2float(&(event->u.freq));	iw_print_freq(buffer, freq);	printf("%s\n", buffer);      }      break;    case SIOCSIWMODE:      printf("Mode:%s\n",	     iw_operation_mode[event->u.mode]);      break;    case SIOCSIWESSID:      {	char essid[IW_ESSID_MAX_SIZE+1];	if((event->u.essid.pointer) && (event->u.essid.length))	  memcpy(essid, event->u.essid.pointer, event->u.essid.length);	essid[event->u.essid.length] = '\0';	if(event->u.essid.flags)	  {	    /* Does it have an ESSID index ? */	    if((event->u.essid.flags & IW_ENCODE_INDEX) > 1)	      printf("ESSID:\"%s\" [%d]\n", essid,		     (event->u.essid.flags & IW_ENCODE_INDEX));	    else	      printf("ESSID:\"%s\"\n", essid);	  }	else	  printf("ESSID:off/any\n");      }      break;    case SIOCSIWENCODE:      {	unsigned char	key[IW_ENCODING_TOKEN_MAX];	if(event->u.data.pointer)	  memcpy(key, event->u.essid.pointer, event->u.data.length);	else	  event->u.data.flags |= IW_ENCODE_NOKEY;	printf("Encryption key:");	if(event->u.data.flags & IW_ENCODE_DISABLED)	  printf("off\n");	else	  {	    /* Display the key */	    iw_print_key(buffer, key, event->u.data.length,			 event->u.data.flags);	    printf("%s", buffer);	    /* Other info... */	    if((event->u.data.flags & IW_ENCODE_INDEX) > 1)	      printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX);	    if(event->u.data.flags & IW_ENCODE_RESTRICTED)	      printf("   Security mode:restricted");	    if(event->u.data.flags & IW_ENCODE_OPEN)	      printf("   Security mode:open");	    printf("\n");	  }      }      break;      /* ----- driver events ----- */      /* Events generated by the driver when something important happens */    case SIOCGIWAP:      printf("New Access Point/Cell address:%s\n",	     iw_pr_ether(buffer, event->u.ap_addr.sa_data));      break;    case SIOCGIWSCAN:      printf("Scan request completed\n");      break;    case IWEVTXDROP:      printf("Tx packet dropped:%s\n",	     iw_pr_ether(buffer, event->u.addr.sa_data));      break;#if WIRELESS_EXT > 14    case IWEVCUSTOM:      {	char custom[IW_CUSTOM_MAX+1];	if((event->u.data.pointer) && (event->u.data.length))	  memcpy(custom, event->u.data.pointer, event->u.data.length);	custom[event->u.data.length] = '\0';	printf("Custom driver event:%s\n", custom);      }      break;    case IWEVREGISTERED:      printf("Registered node:%s\n",	     iw_pr_ether(buffer, event->u.addr.sa_data));      break;    case IWEVEXPIRED:      printf("Expired node:%s\n",	     iw_pr_ether(buffer, event->u.addr.sa_data));      break;#endif /* WIRELESS_EXT > 14 */#if WIRELESS_EXT > 15    case SIOCGIWTHRSPY:      {	struct iw_thrspy	threshold;	int			skfd;	struct iw_range		range;	int			has_range = 0;	if((event->u.data.pointer) && (event->u.data.length))	  {	    memcpy(&threshold, event->u.data.pointer,		   sizeof(struct iw_thrspy));	    if((skfd = iw_sockets_open()) >= 0)	      {		has_range = (iw_get_range_info(skfd, ifname, &range) >= 0);		close(skfd);	      }	    printf("Spy threshold crossed on address:%s\n",		   iw_pr_ether(buffer, threshold.addr.sa_data));	    threshold.qual.updated = 0x0;	/* Not that reliable, disable */	    iw_print_stats(buffer, &threshold.qual, &range, has_range);	    printf("                            Link %s\n", buffer);	  }	else	  printf("Invalid Spy Threshold event\n");      }      break;#else      /* Avoid "Unused parameter" warning */      ifname = ifname;#endif /* WIRELESS_EXT > 15 */      /* ----- junk ----- */      /* other junk not currently in use */    case SIOCGIWRATE:      iw_print_bitrate(buffer, event->u.bitrate.value);      printf("Bit Rate:%s\n", buffer);      break;    case SIOCGIWNAME:      printf("Protocol:%-1.16s\n", event->u.name);      break;    case IWEVQUAL:      {	event->u.qual.updated = 0x0;	/* Not that reliable, disable */	iw_print_stats(buffer, &event->u.qual, iwrange, has_iwrange);	printf("Link %s\n", buffer);	break;      }    default:      printf("(Unknown Wireless event 0x%04X)\n", event->cmd);    }	/* switch(event->cmd) */  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 intprint_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, ifname, NULL, 0);	  else	    printf("(Invalid event)\n");	}    }  while(ret > 0);  return(0);}#endif	/* WIRELESS_EXT > 13 *//*********************** RTNETLINK EVENT DUMP***********************//* * Dump the events we receive from rtnetlink * This code is mostly from Casey *//*------------------------------------------------------------------*//* * Respond to a single RTM_NEWLINK event from the rtnetlink socket. */static inline intindex2name(int	index, char *name){  int		skfd = -1;	/* generic raw socket desc.	*/  struct ifreq	irq;  int		ret = 0;  memset(name, 0, IFNAMSIZ + 1);  /* Create a channel to the NET kernel. */  if((skfd = iw_sockets_open()) < 0)    {      perror("socket");      exit(-1);    }  /* Get interface name */  irq.ifr_ifindex = index;  if(ioctl(skfd, SIOCGIFNAME, &irq) < 0)    ret = -1;  else    strncpy(name, irq.ifr_name, IFNAMSIZ);  close(skfd);  return(ret);}/*------------------------------------------------------------------*//* * Respond to a single RTM_NEWLINK event from the rtnetlink socket. */static intLinkCatcher(struct nlmsghdr *nlh){  struct ifinfomsg* ifi;  char ifname[IFNAMSIZ + 1];#if 0  fprintf(stderr, "nlmsg_type = %d.\n", nlh->nlmsg_type);#endif  if(nlh->nlmsg_type != RTM_NEWLINK)    return 0;  ifi = NLMSG_DATA(nlh);  /* Get a name... */  index2name(ifi->ifi_index, ifname);#if WIRELESS_EXT > 13  /* Code is ugly, but sort of works - Jean II */  /* Check for attributes */  if (nlh->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) {      int attrlen = nlh->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) {	  /* Go to display it */	  print_event_stream(ifname,			     (void *)attr + RTA_ALIGN(sizeof(struct rtattr)),			     attr->rta_len - RTA_ALIGN(sizeof(struct rtattr)));	}	attr = RTA_NEXT(attr, attrlen);      }  }#endif	/* WIRELESS_EXT > 13 */  return 0;}/* ---------------------------------------------------------------- *//* * We must watch the rtnelink socket for events. * This routine handles those events (i.e., call this when rth.fd * is ready to read). */static inline voidhandle_netlink_events(struct rtnl_handle *	rth){  while(1)    {      struct sockaddr_nl sanl;      socklen_t sanllen;      struct nlmsghdr *h;      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);	      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);    }}/**************************** MAIN LOOP ****************************//* ---------------------------------------------------------------- *//* * Wait until we get an event */static inline intwait_for_event(struct rtnl_handle *	rth){#if 0  struct timeval	tv;	/* Select timeout */#endif  /* 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);      FD_SET(rth->fd, &rfds);      last_fd = rth->fd;      /* Wait until something happens */      ret = select(last_fd + 1, &rfds, NULL, NULL, NULL);      /* Check if there was an error */      if(ret < 0)	{	  if(errno == EAGAIN || errno == EINTR)	    continue;	  fprintf(stderr, "Unhandled signal - exiting...\n");	  break;	}      /* Check if there was a timeout */      if(ret == 0)	{	  continue;	}      /* Check for interface discovery events. */      if(FD_ISSET(rth->fd, &rfds))	handle_netlink_events(rth);    }  return(0);}/******************************* MAIN *******************************//* ---------------------------------------------------------------- *//* * helper ;-) */static voidiw_usage(int status){  fputs("Usage: iwevent [OPTIONS]\n"	"   Monitors and displays Wireless Events.\n"	"   Options are:\n"	"     -h,--help     Print this message.\n"	"     -v,--version  Show version of this program.\n",	status ? stderr : stdout);  exit(status);}/* Command line options */static const struct option long_opts[] = {  { "help", no_argument, NULL, 'h' },  { "version", no_argument, NULL, 'v' },  { NULL, 0, NULL, 0 }};/* ---------------------------------------------------------------- *//* * main body of the program */intmain(int	argc,     char *	argv[]){  struct rtnl_handle	rth;  int opt;  /* Check command line options */  while((opt = getopt_long(argc, argv, "hv", long_opts, NULL)) > 0)    {      switch(opt)	{	case 'h':	  iw_usage(0);	  break;	case 'v':	  return(iw_print_version_info("iwevent"));	  break;	default:	  iw_usage(1);	  break;	}    }  if(optind < argc)    {      fputs("Too many arguments.\n", stderr);      iw_usage(1);    }  /* Open netlink channel */  if(rtnl_open(&rth, RTMGRP_LINK) < 0)    {      perror("Can't initialize rtnetlink socket");      return(1);    }#if WIRELESS_EXT > 13  fprintf(stderr, "Waiting for Wireless Events...\n");#else	/* WIRELESS_EXT > 13 */  fprintf(stderr, "Unsupported in Wireless Extensions <= 14 :-(\n");  return(-1);#endif	/* WIRELESS_EXT > 13 */  /* Do what we have to do */  wait_for_event(&rth);  /* Cleanup - only if you are pedantic */  rtnl_close(&rth);  return(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -