您的位置:首页 > 其它

浅析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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐