NETWORK ATTACKS FRAMEWORK  1.0.0
A NETwork Attacks framework. Making network attacks impact evaluation easier!
NA_llf.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * Copyright (C) 2001 Uppsala University and Ericsson AB.
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  *
00019  * Author: Erik Nordstr�m, <erik.nordstrom@it.uu.se>
00020  *
00021  *****************************************************************************/
00022 
00023 #include "NA_defs.h"
00024 #include "NA_debug.h"
00025 
00026 #include <sys/types.h>
00027 #include <sys/ioctl.h>
00028 #include <sys/uio.h>
00029 #include <asm/types.h>
00030 #include <ctype.h>
00031 #include <time.h>
00032 #include <sys/time.h>
00033 #include <net/ethernet.h>       /* struct ether_addr */
00034 #include <linux/netlink.h>
00035 #include <linux/rtnetlink.h>
00036 #include <linux/wireless.h>
00037 #include <iwlib.h>
00038 
00039 #include "NA_aodv_neighbor.h"
00040 #include "NA_routing_table.h"
00041 /* The netlink socket code is taken from the wireless tools by Jean Tourrilhes
00042  * <jt@hpl.hp.com>, who in turn took code from libnetlink.c RTnetlink service
00043  * routines, by Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>. All GPL code. */
00044 
00045 struct rtnl_handle {
00046     int fd;
00047     struct sockaddr_nl local;
00048     struct sockaddr_nl peer;
00049     u_int32_t seq;
00050     u_int32_t dump;
00051 };
00052 
00053 static inline int llf_rtnl_open(struct rtnl_handle *rth,
00054                                 unsigned subscriptions);
00055 static inline void llf_handle_netlink_events(struct rtnl_handle *rth);
00056 
00057 static struct rtnl_handle rth;
00058 
00059 static void llf_callback(int fd)
00060 {
00061 
00062     llf_handle_netlink_events(&rth);
00063 }
00064 
00065 void llf_init()
00066 {
00067 
00068     if (llf_rtnl_open(&rth, RTMGRP_LINK) < 0) {
00069         DEBUG(LOG_ERR, 0, "Can't initialize rtnetlink socket");
00070         return;
00071     }
00072     if (attach_callback_func(rth.fd, llf_callback) < 0) {
00073         alog(LOG_ERR, 0, __FUNCTION__, "Could not attach callback");
00074         return;
00075     }
00076 }
00077 
00078 
00079 void llf_cleanup()
00080 {
00081     close(rth.fd);
00082 }
00083 
00084 
00085 
00086 static inline int llf_rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
00087 {
00088     int addr_len;
00089 
00090     memset(rth, 0, sizeof(rth));
00091 
00092     rth->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
00093     if (rth->fd < 0) {
00094         perror("Cannot open netlink socket");
00095         return -1;
00096     }
00097 
00098     memset(&rth->local, 0, sizeof(rth->local));
00099     rth->local.nl_family = AF_NETLINK;
00100     rth->local.nl_groups = subscriptions;
00101 
00102     if (bind(rth->fd, (struct sockaddr *) &rth->local, sizeof(rth->local)) < 0) {
00103         perror("Cannot bind netlink socket");
00104         return -1;
00105     }
00106     addr_len = sizeof(rth->local);
00107     if (getsockname(rth->fd, (struct sockaddr *) &rth->local, &addr_len) < 0) {
00108         perror("Cannot getsockname");
00109         return -1;
00110     }
00111     if (addr_len != sizeof(rth->local)) {
00112         fprintf(stderr, "Wrong address length %d\n", addr_len);
00113         return -1;
00114     }
00115     if (rth->local.nl_family != AF_NETLINK) {
00116         fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family);
00117         return -1;
00118     }
00119     rth->seq = time(NULL);
00120     return 0;
00121 }
00122 
00123 
00124 /*
00125  * Static information about wireless interface.
00126  * We cache this info for performance reason.
00127  */
00128 typedef struct wireless_iface {
00129     /* Linked list */
00130     struct wireless_iface *next;
00131 
00132     /* Interface identification */
00133     int ifindex;                /* Interface index == black magic */
00134 
00135     /* Interface data */
00136     char ifname[IFNAMSIZ + 1];  /* Interface name */
00137     struct iw_range range;      /* Wireless static data */
00138     int has_range;
00139 } wireless_iface;
00140 
00141 /**************************** VARIABLES ****************************/
00142 
00143 /* Cache of wireless interfaces */
00144 struct wireless_iface *interface_cache = NULL;
00145 
00146 /*
00147  * Get name of interface based on interface index...
00148  */
00149 static inline int index2name(int skfd, int ifindex, char *name)
00150 {
00151     struct ifreq irq;
00152     int ret = 0;
00153 
00154     memset(name, 0, IFNAMSIZ + 1);
00155 
00156     /* Get interface name */
00157     irq.ifr_ifindex = ifindex;
00158     if (ioctl(skfd, SIOCGIFNAME, &irq) < 0)
00159         ret = -1;
00160     else
00161         strncpy(name, irq.ifr_name, IFNAMSIZ);
00162 
00163     return (ret);
00164 }
00165 
00166 static struct wireless_iface *iw_get_interface_data(int ifindex)
00167 {
00168     struct wireless_iface *curr;
00169     int skfd = -1;              /* ioctl socket */
00170 
00171     /* Search for it in the database */
00172     curr = interface_cache;
00173     while (curr != NULL) {
00174         /* Match ? */
00175         if (curr->ifindex == ifindex) {
00176             //printf("Cache : found %d-%s\n", curr->ifindex, curr->ifname);
00177 
00178             /* Return */
00179             return (curr);
00180         }
00181         /* Next entry */
00182         curr = curr->next;
00183     }
00184 
00185     /* Create a channel to the NET kernel. Doesn't happen too often, so
00186      * socket creation overhead is minimal... */
00187     if ((skfd = iw_sockets_open()) < 0) {
00188         perror("iw_sockets_open");
00189         return (NULL);
00190     }
00191 
00192     /* Create new entry, zero, init */
00193     curr = calloc(1, sizeof(struct wireless_iface));
00194     if (!curr) {
00195         fprintf(stderr, "Malloc failed\n");
00196         return (NULL);
00197     }
00198     curr->ifindex = ifindex;
00199 
00200     /* Extract static data */
00201     if (index2name(skfd, ifindex, curr->ifname) < 0) {
00202         perror("index2name");
00203         free(curr);
00204         return (NULL);
00205     }
00206     curr->has_range =
00207         (iw_get_range_info(skfd, curr->ifname, &curr->range) >= 0);
00208     //printf("Cache : create %d-%s\n", curr->ifindex, curr->ifname);
00209 
00210     /* Done */
00211     iw_sockets_close(skfd);
00212 
00213     /* Link it */
00214     curr->next = interface_cache;
00215     interface_cache = curr;
00216 
00217     return (curr);
00218 }
00219 
00220 /* Ugly, ugly way to get ip from eth address */
00221 int mac_to_ip(struct sockaddr *hwaddr, struct in_addr *ip_addr, char *ifname)
00222 {
00223     FILE *fp;
00224     char ip[100];
00225     char hwa[100];
00226     char mask[100];
00227     char line[200];
00228     char dev[100];
00229     int type, flags, num;
00230     struct ether_addr eth;
00231 
00232     if ((fp = fopen("/proc/net/arp", "r")) == NULL) {
00233         perror("/proc/net/arp");
00234         return (-1);
00235     }
00236     /* Bypass header -- read until newline */
00237     if (fgets(line, sizeof(line), fp) != (char *) NULL) {
00238         strcpy(mask, "-");
00239         strcpy(dev, "-");
00240         /* Read the ARP cache entries. */
00241         for (; fgets(line, sizeof(line), fp);) {
00242             num = sscanf(line, "%s 0x%x 0x%x %100s %100s %100s\n",
00243                          ip, &type, &flags, hwa, mask, dev);
00244             if (num < 4)
00245                 break;
00246 
00247             iw_ether_aton(hwa, &eth);
00248 
00249             if (memcmp(&eth, hwaddr->sa_data, ETH_ALEN) == 0) {
00250 
00251                 inet_aton(ip, ip_addr);
00252 
00253                 fclose(fp);
00254                 return 0;
00255             }
00256         }
00257     }
00258     fclose(fp);
00259     return -1;
00260 }
00261 
00262 static inline int llf_print_event(struct iw_event *event,
00263                                   struct iw_range *iwrange, int has_iwrange)
00264 {
00265     char buffer[128];
00266     struct in_addr ip;
00267     rt_table_t *rt;
00268 
00269     /* Now, let's decode the event */
00270     switch (event->cmd) {
00271 
00272     case IWEVTXDROP:
00273         DEBUG(LOG_DEBUG, 0, "Tx packet dropped:%s",
00274               iw_pr_ether(buffer, event->u.addr.sa_data));
00275 
00276 
00277         if (mac_to_ip(&event->u.addr, &ip, this_host.devs[0].ifname) != 0) {
00278             DEBUG(LOG_DEBUG, 0, "failed mac_to_ip");
00279             return 0;
00280         }
00281         //printf("IP=%s\n", ip_to_str(ip));
00282 
00283         rt = rt_table_find(ip);
00284 
00285         if (rt)
00286             neighbor_link_break(rt);
00287         else
00288             DEBUG(LOG_DEBUG, 0, "no route for ip=%s", ip_to_str(ip));
00289         break;
00290 
00291     default:
00292         DEBUG(LOG_DEBUG, 0, "(Unknown Wireless event 0x%04X)", event->cmd);
00293     }
00294 
00295     return 0;
00296 }
00297 
00298 static inline void llf_handle_netlink_events(struct rtnl_handle *rth)
00299 {
00300     while (1) {
00301         struct sockaddr_nl sanl;
00302         socklen_t sanllen;
00303         struct nlmsghdr *h;
00304         struct ifinfomsg *ifi;
00305         int amt;
00306         char buf[8192];
00307 
00308         amt =
00309             recvfrom(rth->fd, buf, sizeof(buf), MSG_DONTWAIT,
00310                      (struct sockaddr *) &sanl, &sanllen);
00311         if (amt < 0) {
00312             if (errno != EINTR && errno != EAGAIN) {
00313                 fprintf(stderr, "%s: error reading netlink: %s.\n",
00314                         __PRETTY_FUNCTION__, strerror(errno));
00315             }
00316             return;
00317         }
00318 
00319         if (amt == 0) {
00320             fprintf(stderr, "%s: EOF on netlink??\n", __PRETTY_FUNCTION__);
00321             return;
00322         }
00323 
00324         h = (struct nlmsghdr *) buf;
00325         while (amt >= (int) sizeof(*h)) {
00326             int len = h->nlmsg_len;
00327             int l = len - sizeof(*h);
00328 
00329             if (l < 0 || len > amt) {
00330                 fprintf(stderr, "%s: malformed netlink message: len=%d\n",
00331                         __PRETTY_FUNCTION__, len);
00332                 break;
00333             }
00334 
00335             switch (h->nlmsg_type) {
00336             case RTM_NEWLINK:
00337 //              LinkCatcher(h);
00338                 if (h->nlmsg_type != RTM_NEWLINK)
00339                     return;
00340 
00341                 ifi = NLMSG_DATA(h);
00342 
00343                 /* Check for attributes */
00344                 if (h->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) {
00345                     int attrlen =
00346                         h->nlmsg_len - NLMSG_ALIGN(sizeof(struct ifinfomsg));
00347                     struct rtattr *attr =
00348                         (void *) ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg));
00349 
00350                     while (RTA_OK(attr, attrlen)) {
00351                         /* Check if the Wireless kind */
00352                         if (attr->rta_type == IFLA_WIRELESS) {
00353                             struct iw_event iwe;
00354                             struct stream_descr stream;
00355                             int ret;
00356 #if WE_VERSION >= 17
00357 
00358                             struct wireless_iface *wireless_data;
00359 
00360                             /* Get data from cache */
00361                             wireless_data =
00362                                 iw_get_interface_data(ifi->ifi_index);
00363 
00364                             if (wireless_data == NULL)
00365                                 return;
00366 #endif
00367 
00368                             /* Go to display it */
00369 
00370                             iw_init_event_stream(&stream,
00371                                                  (void *) attr +
00372                                                  RTA_ALIGN(sizeof
00373                                                            (struct rtattr)),
00374                                                  attr->rta_len -
00375                                                  RTA_ALIGN(sizeof
00376                                                            (struct rtattr)));
00377                             do {
00378                                 /* Extract an event and print it */
00379 #if WE_VERSION >= 17
00380                                 ret =
00381                                     iw_extract_event_stream(&stream, &iwe,
00382                                                             wireless_data->
00383                                                             range.
00384                                                             we_version_compiled);
00385 #else
00386                                 ret = iw_extract_event_stream(&stream, &iwe);
00387 #endif
00388                                 if (ret != 0) {
00389                                     if (ret > 0)
00390                                         llf_print_event(&iwe, NULL, 0);
00391                                     else
00392                                         DEBUG(LOG_WARNING, 0,
00393                                               "Invalid iw event");
00394                                 }
00395                             } while (ret > 0);
00396 
00397                         }
00398                         attr = RTA_NEXT(attr, attrlen);
00399                     }
00400                 }
00401 
00402                 break;
00403             default:
00404 #if 0
00405                 fprintf(stderr, "%s: got nlmsg of type %#x.\n",
00406                         __PRETTY_FUNCTION__, h->nlmsg_type);
00407 #endif
00408                 break;
00409             }
00410 
00411             len = NLMSG_ALIGN(len);
00412             amt -= len;
00413             h = (struct nlmsghdr *) ((char *) h + len);
00414         }
00415 
00416         if (amt > 0)
00417             fprintf(stderr, "%s: remnant of size %d on netlink\n",
00418                     __PRETTY_FUNCTION__, amt);
00419     }
00420 }
 All Classes Files Functions Variables Typedefs Enumerator Defines