📄 iwevent.c
字号:
/* * Wireless Tools * * Jean II - HPL 99->04 * * 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-2004 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 *//****************************** TYPES ******************************//* * Static information about wireless interface. * We cache this info for performance reason. */typedef struct wireless_iface{ /* Linked list */ struct wireless_iface * next; /* Interface identification */ int ifindex; /* Interface index == black magic */ /* Interface data */ char ifname[IFNAMSIZ + 1]; /* Interface name */ struct iw_range range; /* Wireless static data */ int has_range;} wireless_iface;/**************************** VARIABLES ****************************//* Cache of wireless interfaces */struct wireless_iface * interface_cache = NULL;/************************ 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, (socklen_t *) &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 INTERFACE DATABASE *******************//* * We keep a few information about each wireless interface on the * system. This avoid to query this info at each event, therefore * reducing overhead. * * Each interface is indexed by the 'ifindex'. As opposed to interface * names, 'ifindex' are never reused (even if you reactivate the same * hardware), so the data we cache will never apply to the wrong * interface. * Because of that, we are pretty lazy when it come to purging the * cache... *//*------------------------------------------------------------------*//* * Get name of interface based on interface index... */static inline intindex2name(int skfd, int ifindex, char * name){ struct ifreq irq; int ret = 0; memset(name, 0, IFNAMSIZ + 1); /* Get interface name */ irq.ifr_ifindex = ifindex; if(ioctl(skfd, SIOCGIFNAME, &irq) < 0) ret = -1; else strncpy(name, irq.ifr_name, IFNAMSIZ); return(ret);}/*------------------------------------------------------------------*//* * Get interface data from cache or live interface */static struct wireless_iface *iw_get_interface_data(int ifindex){ struct wireless_iface * curr; int skfd = -1; /* ioctl socket */ /* Search for it in the database */ curr = interface_cache; while(curr != NULL) { /* Match ? */ if(curr->ifindex == ifindex) { //printf("Cache : found %d-%s\n", curr->ifindex, curr->ifname); /* Return */ return(curr); } /* Next entry */ curr = curr->next; } /* Create a channel to the NET kernel. Doesn't happen too often, so * socket creation overhead is minimal... */ if((skfd = iw_sockets_open()) < 0) { perror("iw_sockets_open"); return(NULL); } /* Create new entry, zero, init */ curr = calloc(1, sizeof(struct wireless_iface)); if(!curr) { fprintf(stderr, "Malloc failed\n"); return(NULL); } curr->ifindex = ifindex; /* Extract static data */ if(index2name(skfd, ifindex, curr->ifname) < 0) { perror("index2name"); free(curr); return(NULL); } curr->has_range = (iw_get_range_info(skfd, curr->ifname, &curr->range) >= 0); //printf("Cache : create %d-%s\n", curr->ifindex, curr->ifname); /* Done */ iw_sockets_close(skfd); /* Link it */ curr->next = interface_cache; interface_cache = curr; return(curr);}/*------------------------------------------------------------------*//* * Remove interface data from cache (if it exist) */static voidiw_del_interface_data(int ifindex){ struct wireless_iface * curr; struct wireless_iface * prev = NULL; struct wireless_iface * next; /* Go through the list, find the interface, kills it */ curr = interface_cache; while(curr) { next = curr->next; /* Got a match ? */ if(curr->ifindex == ifindex) { /* Unlink. Root ? */ if(!prev) interface_cache = next; else prev->next = next; //printf("Cache : purge %d-%s\n", curr->ifindex, curr->ifname); /* Destroy */ free(curr); } else { /* Keep as previous */ prev = curr; } /* Next entry */ curr = next; }}/********************* WIRELESS EVENT DECODING *********************//* * Parse the Wireless Event and print it out *//*------------------------------------------------------------------*//* * Dump a buffer as a serie of hex * Maybe should go in iwlib... * Maybe we should have better formatting like iw_print_key... */static char *iw_hexdump(char * buf, size_t buflen, const unsigned char *data, size_t datalen){ size_t i; char * pos = buf; for(i = 0; i < datalen; i++) pos += snprintf(pos, buf + buflen - pos, "%02X", data[i]); return buf;}/*------------------------------------------------------------------*//* * Print one element from the scanning results */static inline intprint_event_token(struct iw_event * event, /* Extracted token */ struct iw_range * iw_range, /* Range info */ int has_range){ char buffer[128]; /* Temporary buffer */ char buffer2[30]; /* Temporary buffer */ char * prefix = (IW_IS_GET(event->cmd) ? "New" : "Set"); /* 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("Set NWID:off/any\n"); else printf("Set NWID:%X\n", event->u.nwid.value); break; case SIOCSIWFREQ: case SIOCGIWFREQ: { double freq; /* Frequency/channel */ int channel = -1; /* Converted to channel */ freq = iw_freq2float(&(event->u.freq)); if(has_range) { if(freq < KILO) /* Convert channel to frequency if possible */ channel = iw_channel_to_freq((int) freq, &freq, iw_range); else /* Convert frequency to channel if possible */ channel = iw_freq_to_channel(freq, iw_range); } iw_print_freq(buffer, sizeof(buffer), freq, channel, event->u.freq.flags); printf("%s %s\n", prefix, buffer); } break; case SIOCSIWMODE: printf("Set Mode:%s\n", iw_operation_mode[event->u.mode]); break; case SIOCSIWESSID: case SIOCGIWESSID: { char essid[IW_ESSID_MAX_SIZE+1]; memset(essid, '\0', sizeof(essid)); if((event->u.essid.pointer) && (event->u.essid.length)) memcpy(essid, event->u.essid.pointer, event->u.essid.length); if(event->u.essid.flags) { /* Does it have an ESSID index ? */ if((event->u.essid.flags & IW_ENCODE_INDEX) > 1) printf("%s ESSID:\"%s\" [%d]\n", prefix, essid, (event->u.essid.flags & IW_ENCODE_INDEX)); else printf("%s ESSID:\"%s\"\n", prefix, essid); } else printf("%s ESSID:off/any\n", prefix); } break; case SIOCSIWENCODE: { unsigned char key[IW_ENCODING_TOKEN_MAX]; if(event->u.data.pointer) memcpy(key, event->u.data.pointer, event->u.data.length); else event->u.data.flags |= IW_ENCODE_NOKEY; printf("Set Encryption key:"); if(event->u.data.flags & IW_ENCODE_DISABLED) printf("off\n"); else { /* Display the key */ iw_print_key(buffer, sizeof(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_sawap_ntop(&event->u.ap_addr, buffer)); break; case SIOCGIWSCAN: printf("Scan request completed\n"); break; case IWEVTXDROP: printf("Tx packet dropped:%s\n", iw_saether_ntop(&event->u.addr, buffer)); break; case IWEVCUSTOM: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -