NETWORK ATTACKS FRAMEWORK
1.0.0
A NETwork Attacks framework. Making network attacks impact evaluation easier!
|
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, ð); 00248 00249 if (memcmp(ð, 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 }