ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/package/kernel/realtek-wl/src/Users/wireless_tools.25/iwevent.c b/package/kernel/realtek-wl/src/Users/wireless_tools.25/iwevent.c
new file mode 100644
index 0000000..efe96f5
--- /dev/null
+++ b/package/kernel/realtek-wl/src/Users/wireless_tools.25/iwevent.c
@@ -0,0 +1,571 @@
+/*
+ *	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>
+//#define MSG_DONTWAIT	0x40
+/************************ 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)
+{
+	socklen_t 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 int
+print_event_token(struct iw_event *	event,	/* Extracted token */
+		  struct iw_range *	iwrange,	/* Range info */
+		  int			has_range)
+{
+  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("   Encryption mode:restricted");
+	    if(event->u.data.flags & IW_ENCODE_OPEN)
+	      printf("   Encryption 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, (unsigned char *)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, (unsigned char *)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, (unsigned char *)event->u.addr.sa_data));
+      break;
+    case IWEVEXPIRED:
+      printf("Expired node:%s\n",
+	     iw_pr_ether(buffer, (unsigned char *)event->u.addr.sa_data));
+      break;
+#endif /* WIRELESS_EXT > 14 */
+      /* ----- 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 IWEVQUAL:
+      {
+	event->u.qual.updated = 0x0;	/* Not that reliable, disable */
+	iw_print_stats(buffer, &event->u.qual, iwrange, has_range);
+	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 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);
+}
+#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 int
+index2name(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 int
+LinkCatcher(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 void
+handle_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 int
+wait_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 void
+iw_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
+ */
+int
+main(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);
+}