浅析rtnetlink接收wireless网卡信息的源码实例【转】
2008-10-31 12:35
686 查看
浅析rtnetlink接收wireless网卡信息的源码实例【转】
作者:飞镖 luther (gliethttp)
http://blog.chinaunix.net/u1/38994/showart_1353632.html[/code]
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <sys/socket.h>#include <linux/netlink.h>#include <linux/rtnetlink.h>#include <linux/if.h>#include <linux/if_ether.h>#include <linux/wireless.h>#include <linux/sockios.h>#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"#define luther_printf(msg...) printf("===luther:=== "msg)struct luther_context { int ioctl_sock; int event_sock; char ifname[IFNAMSIZ + 1]; int ifindex; int ifindex2; int has_capability; int we_version_compiled;} luther_context = { .ifname = "eth0", .ifindex = -1, .ifindex2 = -1, };static void luther_event_rtm_newlink(struct luther_context *ctx, struct nlmsghdr *h, size_t len);static void luther_event_rtm_dellink(struct luther_context *ctx, struct nlmsghdr *h, size_t len);static void luther_wext_event_wireless(struct luther_context *ctx, char *data, int len);static void luther_wext_event_link(struct luther_context *ctx, char *buf, size_t len, int del);static int luther_wext_get_range(struct luther_context *ctx);static unsigned int if_nametoindex(const char *ifname);int main(int argc, char *argv[]){ struct sockaddr_nl local; luther_context.ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); if (luther_context.ioctl_sock < 0) { perror("socket(PF_INET,SOCK_DGRAM)"); return 0; } luther_context.event_sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (luther_context.event_sock < 0) { perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); close(luther_context.ioctl_sock); return 0; } memset(&local, 0, sizeof(local)); local.nl_family = AF_NETLINK; local.nl_groups = RTMGRP_LINK; if (bind(luther_context.event_sock, (struct sockaddr *) &local, sizeof(local)) < 0) { perror("bind(netlink)"); close(luther_context.ioctl_sock); close(luther_context.event_sock); return 0; } if (argc == 2) { strcpy(luther_context.ifname, argv[1]); } if( luther_wext_get_range(&luther_context) < 0) { close(luther_context.ioctl_sock); close(luther_context.event_sock); return 0; } luther_context.ifindex = luther_context.ifname[0] ? if_nametoindex(luther_context.ifname) : -1; do { char buf[8192]; int left; struct sockaddr_nl from; socklen_t fromlen; struct nlmsghdr *h; int sock = luther_context.event_sock; struct luther_context *ctx = &luther_context; int max_events = 10;try_again: fromlen = sizeof(from); left = recvfrom(sock, buf, sizeof(buf), 0/* MSG_DONTWAIT */, (struct sockaddr *) &from, &fromlen); if (left < 0) { if (errno != EINTR && errno != EAGAIN) perror("recvfrom(netlink)"); return 0; } h = (struct nlmsghdr *) buf; while (left >= (int) sizeof(*h)) { int len, plen; len = h->nlmsg_len; plen = len - sizeof(*h); if (len > left || plen < 0) { luther_printf("Malformed netlink message: "rtnetlin
"len=%d left=%d plen=%d/n", len, left, plen); break; } switch (h->nlmsg_type) { case RTM_NEWLINK: luther_event_rtm_newlink(ctx, h, plen); break; case RTM_DELLINK: luther_event_rtm_dellink(ctx, h, plen); break; } len = NLMSG_ALIGN(len); left -= len; h = (struct nlmsghdr *) ((char *) h + len); } if (left > 0) { luther_printf("%d extra bytes in the end of netlink " "message/n", left); } if (--max_events > 0) { /* * Try to receive all events in one eloop call in order to * limit race condition on cases where AssocInfo event, Assoc * event, and EAPOL frames are received more or less at the * same time. We want to process the event messages first * before starting EAPOL processing. */ goto try_again; } goto try_again; } while (0) ;}static void luther_event_rtm_newlink(struct luther_context *ctx, struct nlmsghdr *h, size_t len){ struct ifinfomsg *ifi; int attrlen, nlmsg_len, rta_len; struct rtattr * attr; if (len < sizeof(*ifi)) return; ifi = NLMSG_DATA(h); if ((ctx->ifindex != ifi->ifi_index && ctx->ifindex2 != ifi->ifi_index) && (ctx->ifindex != -1)) { luther_printf("Ignore event for foreign ifindex %d/n", ifi->ifi_index); return; } /* luther_printf("RTM_NEWLINK: ifi_flags=0x%x " "(%s%s)/n", ifi->ifi_flags, (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : ""); */ nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); attrlen = h->nlmsg_len - nlmsg_len; if (attrlen < 0) return; attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); rta_len = RTA_ALIGN(sizeof(struct rtattr)); while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_WIRELESS) { luther_wext_event_wireless( ctx, ((char *) attr) + rta_len, attr->rta_len - rta_len); } else if (attr->rta_type == IFLA_IFNAME) { luther_wext_event_link(ctx, ((char *) attr) + rta_len, attr->rta_len - rta_len, 0); } attr = RTA_NEXT(attr, attrlen); }}static void luther_event_rtm_dellink(struct luther_context *ctx, struct nlmsghdr *h, size_t len){ struct ifinfomsg *ifi; int attrlen, nlmsg_len, rta_len; struct rtattr * attr; if (len < sizeof(*ifi)) return; ifi = NLMSG_DATA(h); nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); attrlen = h->nlmsg_len - nlmsg_len; if (attrlen < 0) return; attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); rta_len = RTA_ALIGN(sizeof(struct rtattr)); while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_IFNAME) { luther_wext_event_link(ctx, ((char *) attr) + rta_len, attr->rta_len - rta_len, 1); } attr = RTA_NEXT(attr, attrlen); }}static void luther_wext_event_wireless(struct luther_context *ctx, char *data, int len){ struct iw_event iwe_buf, *iwe = &iwe_buf; char *pos, *end, *custom, *buf; pos = data; end = data + len; while (pos + IW_EV_LCP_LEN <= end) { /* Event data may be unaligned, so make a local, aligned copy * before processing. */ memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); luther_printf("event: cmd=0x%x len=%d/n", iwe->cmd, iwe->len); if (iwe->len <= IW_EV_LCP_LEN) return; custom = pos + IW_EV_POINT_LEN; if (ctx->we_version_compiled > 18 && (iwe->cmd == IWEVMICHAELMICFAILURE || iwe->cmd == IWEVCUSTOM || iwe->cmd == IWEVASSOCREQIE || iwe->cmd == IWEVASSOCRESPIE || iwe->cmd == IWEVPMKIDCAND)) { /* WE-19 removed the pointer from struct iw_point */ char *dpos = (char *) &iwe_buf.u.data.length; int dlen = dpos - (char *) &iwe_buf; memcpy(dpos, pos + IW_EV_LCP_LEN, sizeof(struct iw_event) - dlen); } else { memcpy(&iwe_buf, pos, sizeof(struct iw_event)); custom += IW_EV_POINT_OFF; } switch (iwe->cmd) { case SIOCGIWAP: luther_printf("event: new AP: " MACSTR, MAC2STR((unsigned char *) iwe->u.ap_addr.sa_data)); if (memcmp(iwe->u.ap_addr.sa_data, "/x00/x00/x00/x00/x00/x00", ETH_ALEN) == 0 || memcmp(iwe->u.ap_addr.sa_data, "/x44/x44/x44/x44/x44/x44", ETH_ALEN) == 0) { luther_printf("event : Disconnect/n"); } else { luther_printf("event : Associated to a new BSS/n"); } break; case IWEVMICHAELMICFAILURE: luther_printf("event : Michael MIC failure wireless/n"); break; case IWEVCUSTOM: if (custom + iwe->u.data.length > end) return; buf = malloc(iwe->u.data.length + 1); if (buf == NULL) return; memcpy(buf, custom, iwe->u.data.length); buf[iwe->u.data.length] = '/0'; luther_printf("event : custom -> %s/n", buf); free(buf); break; case SIOCGIWSCAN: luther_printf("event : scan_results/n"); break; case IWEVASSOCREQIE: luther_printf("event : AssocReq IE wireless/n"); break; case IWEVASSOCRESPIE: luther_printf("event : AssocResp IE wireless/n"); break; case IWEVPMKIDCAND: luther_printf("event : PMKID candidate wireless/n"); break; } pos += iwe->len; }}static void luther_wext_event_link(struct luther_context *ctx, char *buf, size_t len, int del){ luther_printf("RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s/n", del ? "DEL" : "NEW", buf,rtnetlin
del ? "removed" : "added");}static int luther_wext_get_range(struct luther_context *ctx){ struct iw_range *range; struct iwreq iwr; int minlen; size_t buflen; /* * Use larger buffer than struct iw_range in order to allow the * structure to grow in the future. */ buflen = sizeof(struct iw_range) + 500; range = calloc(buflen, 1); if (range == NULL) return -1; memset(&iwr, 0, sizeof(iwr)); strncpy(iwr.ifr_name, ctx->ifname, IFNAMSIZ); iwr.u.data.pointer = (caddr_t) range; iwr.u.data.length = buflen; minlen = ((char *) &range->enc_capa) - (char *) range + sizeof(range->enc_capa); if (ioctl(ctx->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { perror("ioctl[SIOCGIWRANGE]"); free(range); return -1; } else if (iwr.u.data.length >= minlen && range->we_version_compiled >= 18) { /* luther_printf("SIOCGIWRANGE: WE(compiled)=%d " "WE(source)=%d enc_capa=0x%x/n", range->we_version_compiled, range->we_version_source, range->enc_capa); */ ctx->has_capability = 1; ctx->we_version_compiled = range->we_version_compiled; } else { luther_printf("SIOCGIWRANGE: too old (short) data - " "assuming WPA is not supported/n"); } free(range); return 0;}static unsigned int if_nametoindex(const char *ifname){ struct ifreq ifr; int fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) return 0; strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); ifr.ifr_ifindex = 0; if (ioctl (fd, SIOCGIFINDEX, &ifr) < 0) { return 0; } return ifr.ifr_ifindex;}
luther@gliethttp:~$ arm-linux-gcc -o rtnetlink rtnetlink.c ;arm-linux-strip -s rtnetlink/telephony/modules # tftp -r rtnetlink -g 192.168.100.1/telephony/modules # ./rtnetlink &===luther:=== event: cmd=0x8b06 len=8===luther:=== RTM_NEWLINK, IFLA_IFNAME: Interface 'eth0' added===luther:=== RTM_NEWLINK, IFLA_IFNAME: Interface 'eth0' added===luther:=== event: cmd=0x8b19 len=8===luther:=== event : scan_results===luther:=== event: cmd=0x8b06 len=8===luther:=== event: cmd=0x8b04 len=12===luther:=== event: cmd=0x8b15 len=20===luther:=== event: new AP: 00:1d:7e:a0:0e:81===luther:=== event : Associated to a new BSS===luther:=== event: cmd=0x8b1a len=22===luther:=== RTM_NEWLINK, IFLA_IFNAME: Interface 'eth0' added===luther:=== RTM_NEWLINK, IFLA_IFNAME: Interface 'eth0' added===luther:=== event: cmd=0x8b06 len=8===luther:=== RTM_NEWLINK, IFLA_IFNAME: Interface 'eth0' added===luther:=== RTM_NEWLINK, IFLA_IFNAME: Interface 'eth0' added===luther:=== event: cmd=0x8b19 len=8===luther:=== event : scan_results===luther:=== event: cmd=0x8b06 len=8===luther:=== event: cmd=0x8b04 len=12===luther:=== event: cmd=0x8b15 len=20===luther:=== event: new AP: 00:1d:7e:a0:0e:81===luther:=== event : Associated to a new BSS===luther:=== event: cmd=0x8b1a len=22===luther:=== RTM_NEWLINK, IFLA_IFNAME: Interface 'eth0' added===luther:=== RTM_NEWLINK, IFLA_IFNAME: Interface 'eth0' added===luther:=== event: cmd=0x8c02 len=28===luther:=== event : custom -> HS_DEACTIVATED===luther:=== event: cmd=0x8c02 len=26===luther:=== event : custom -> HS_ACTIVATED
相关文章推荐
- 超详细的php用户注册页面填写信息完整实例(附源码)
- Linux 查看网卡接收报文信息命令ethtool
- 超详细的php用户注册页面填写信息完整实例(附源码)
- 小白自学C#之《C#.net_经典编程例子400个》实例001带历史信息的菜单 附自学源码
- maven之构建jdbc连oracle的四种方式实例和注册驱动源码浅析
- Android编程实现QQ表情的发送和接收完整实例(附源码)
- Silverlight实用窍门系列:48.DataGrid行详细信息的绑定--DataGrid.RowDetailsTemplate【附带实例源码】
- wince中获取有线网卡和无线网卡ip信息的实例
- maven之构建jdbc连oracle的四种方式实例和注册驱动源码浅析
- Linux USB 驱动开发实例 (三)—— 基于USB总线的无线网卡浅析
- Hibernate加载基本的配置信息源码浅析
- OpenStack建立实例完整过程源码详细分析(14)----依据AMQP通信架构实现消息接收机制解析之一
- C语言解析pcap文件得到HTTP信息实例(原创,附源码)
- Linux USB 驱动开发实例 (三)—— 基于USB总线的无线网卡浅析
- Linux USB 驱动开发实例 (三)—— 基于USB总线的无线网卡浅析
- 基于rt-thread+lwip分析数据是怎么从网卡芯片接收数据到pbuf的(lwip源码解析一)
- 【PyQt4 实例18】获取网卡信息
- OpenStack建立实例完整过程源码详细分析(15)----依据AMQP通信架构实现消息接收机制解析之二
- C语言解析pcap文件得到HTTP信息实例(原创,附源码)
- C语言解析pcap文件得到HTTP信息实例(原创,附源码)