NETWORK ATTACKS FRAMEWORK  1.0.0
A NETwork Attacks framework. Making network attacks impact evaluation easier!
NA_nl.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 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <sys/time.h>
00026 #include <unistd.h>
00027 #include <errno.h>
00028 #include <sys/types.h>
00029 #include <sys/socket.h>
00030 #include <asm/types.h>
00031 #include <linux/netlink.h>
00032 #include <sys/select.h>
00033 #include <netinet/in.h>
00034 #include <arpa/inet.h>
00035 #include <linux/rtnetlink.h>
00036 
00037 #include "defs.h"
00038 #include "lnx/kaodv-netlink.h"
00039 #include "debug.h"
00040 #include "NA_aodv_rreq.h"
00041 #include "NA_aodv_timeout.h"
00042 #include "NA_routing_table.h"
00043 #include "NA_aodv_hello.h"
00044 #include "NA_params.h"
00045 #include "NA_aodv_socket.h"
00046 #include "NA_aodv_rerr.h"
00047 
00048 /* Implements a Netlink socket communication channel to the kernel. Route
00049  * information and refresh messages are passed. */
00050 
00051 struct nlsock {
00052         int sock;
00053         int seq;
00054         struct sockaddr_nl local;
00055 };
00056 
00057 struct sockaddr_nl peer = { AF_NETLINK, 0, 0, 0 };
00058 
00059 struct nlsock aodvnl;
00060 struct nlsock rtnl;
00061 
00062 static void nl_kaodv_callback(int sock);
00063 static void nl_rt_callback(int sock);
00064 
00065 extern int llfeedback, active_route_timeout, qual_threshold, internet_gw_mode,
00066     wait_on_reboot;
00067 extern struct timer worb_timer;
00068 
00069 #define BUFLEN 256
00070 
00071 /* #define DEBUG_NETLINK */
00072 
00073 void nl_init(void)
00074 {
00075         int status;
00076         unsigned int addrlen;
00077 
00078         memset(&peer, 0, sizeof(struct sockaddr_nl));
00079         peer.nl_family = AF_NETLINK;
00080         peer.nl_pid = 0;
00081         peer.nl_groups = 0;
00082 
00083         memset(&aodvnl, 0, sizeof(struct nlsock));
00084         aodvnl.seq = 0;
00085         aodvnl.local.nl_family = AF_NETLINK;
00086         aodvnl.local.nl_groups = AODVGRP_NOTIFY;
00087         aodvnl.local.nl_pid = getpid();
00088 
00089         /* This is the AODV specific socket to communicate with the
00090            AODV kernel module */
00091         aodvnl.sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_AODV);
00092 
00093         if (aodvnl.sock < 0) {
00094                 perror("Unable to create AODV netlink socket");
00095                 exit(-1);
00096         }
00097 
00098 
00099         status = bind(aodvnl.sock, (struct sockaddr *) &aodvnl.local,
00100                       sizeof(aodvnl.local));
00101 
00102         if (status == -1) {
00103                 perror("Bind for AODV netlink socket failed");
00104                 exit(-1);
00105         }
00106 
00107         addrlen = sizeof(aodvnl.local);
00108 
00109         if (getsockname
00110             (aodvnl.sock, (struct sockaddr *) &aodvnl.local, &addrlen) < 0) {
00111                 perror("Getsockname failed ");
00112                 exit(-1);
00113         }
00114 
00115         if (attach_callback_func(aodvnl.sock, nl_kaodv_callback) < 0) {
00116                 alog(LOG_ERR, 0, __FUNCTION__, "Could not attach callback.");
00117         }
00118         /* This socket is the generic routing socket for adding and
00119            removing kernel routing table entries */
00120 
00121         memset(&rtnl, 0, sizeof(struct nlsock));
00122         rtnl.seq = 0;
00123         rtnl.local.nl_family = AF_NETLINK;
00124         rtnl.local.nl_groups =
00125             RTMGRP_NOTIFY | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
00126         rtnl.local.nl_pid = getpid();
00127 
00128         rtnl.sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
00129 
00130         if (rtnl.sock < 0) {
00131                 perror("Unable to create RT netlink socket");
00132                 exit(-1);
00133         }
00134 
00135         addrlen = sizeof(rtnl.local);
00136 
00137         status = bind(rtnl.sock, (struct sockaddr *) &rtnl.local, addrlen);
00138 
00139         if (status == -1) {
00140                 perror("Bind for RT netlink socket failed");
00141                 exit(-1);
00142         }
00143 
00144         if (getsockname(rtnl.sock, (struct sockaddr *) &rtnl.local, &addrlen) <
00145             0) {
00146                 perror("Getsockname failed ");
00147                 exit(-1);
00148         }
00149 
00150         if (attach_callback_func(rtnl.sock, nl_rt_callback) < 0) {
00151                 alog(LOG_ERR, 0, __FUNCTION__, "Could not attach callback.");
00152         }
00153 }
00154 
00155 void nl_cleanup(void)
00156 {
00157         close(aodvnl.sock);
00158         close(rtnl.sock);
00159 }
00160 
00161 
00162 static void nl_kaodv_callback(int sock)
00163 {
00164         int len;
00165         socklen_t addrlen;
00166         struct nlmsghdr *nlm;
00167         struct nlmsgerr *nlmerr;
00168         char buf[BUFLEN];
00169         struct in_addr dest_addr, src_addr;
00170         kaodv_rt_msg_t *m;
00171         rt_table_t *rt, *fwd_rt, *rev_rt = NULL;
00172 
00173         addrlen = sizeof(struct sockaddr_nl);
00174 
00175 
00176         len =
00177             recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &peer, &addrlen);
00178 
00179         if (len <= 0)
00180                 return;
00181 
00182         nlm = (struct nlmsghdr *) buf;
00183 
00184         switch (nlm->nlmsg_type) {
00185         case NLMSG_ERROR:
00186                 nlmerr = NLMSG_DATA(nlm);
00187                 if (nlmerr->error == 0) {
00188                 /*      DEBUG(LOG_DEBUG, 0, "NLMSG_ACK"); */
00189                 } else {
00190                         DEBUG(LOG_DEBUG, 0, "NLMSG_ERROR, error=%d type=%s",
00191                               nlmerr->error, 
00192                               kaodv_msg_type_to_str(nlmerr->msg.nlmsg_type));
00193                 }
00194                 break;
00195 
00196         case KAODVM_DEBUG:
00197                 DEBUG(LOG_DEBUG, 0, "kaodv: %s", NLMSG_DATA(nlm));
00198                 break;
00199         case KAODVM_TIMEOUT:
00200                 m = NLMSG_DATA(nlm);
00201                 dest_addr.s_addr = m->dst;
00202 
00203                 DEBUG(LOG_DEBUG, 0,
00204                       "Got TIMEOUT msg from kernel for %s",
00205                       ip_to_str(dest_addr));
00206 
00207                 rt = rt_table_find(dest_addr);
00208 
00209                 if (rt && rt->state == VALID)
00210                         route_expire_timeout(rt);
00211                 else
00212                         DEBUG(LOG_DEBUG, 0,
00213                               "Got rt timeoute event but there is no route");
00214                 break;
00215         case KAODVM_ROUTE_REQ:
00216                 m = NLMSG_DATA(nlm);
00217                 dest_addr.s_addr = m->dst;
00218 
00219                 DEBUG(LOG_DEBUG, 0, "Got ROUTE_REQ: %s from kernel",
00220                       ip_to_str(dest_addr));
00221 
00222                 rreq_route_discovery(dest_addr, 0, NULL);
00223                 break;
00224         case KAODVM_REPAIR:
00225                 m = NLMSG_DATA(nlm);
00226                 dest_addr.s_addr = m->dst;
00227                 src_addr.s_addr = m->src;
00228 
00229                 DEBUG(LOG_DEBUG, 0, "Got REPAIR from kernel for %s",
00230                       ip_to_str(dest_addr));
00231 
00232                 fwd_rt = rt_table_find(dest_addr);
00233 
00234                 if (fwd_rt)
00235                         rreq_local_repair(fwd_rt, src_addr, NULL);
00236 
00237                 break;
00238         case KAODVM_ROUTE_UPDATE:
00239                 m = NLMSG_DATA(nlm);
00240 
00241                 
00242                 dest_addr.s_addr = m->dst;
00243                 src_addr.s_addr = m->src;
00244 
00245                 //      DEBUG(LOG_DEBUG, 0, "ROute update s=%s d=%s", ip_to_str(src_addr), ip_to_str(dest_addr));
00246                 if (dest_addr.s_addr == AODV_BROADCAST ||
00247                     dest_addr.s_addr ==
00248                     DEV_IFINDEX(m->ifindex).broadcast.s_addr)
00249                         return;
00250 
00251                 fwd_rt = rt_table_find(dest_addr);
00252                 rev_rt = rt_table_find(src_addr);
00253 
00254                 rt_table_update_route_timeouts(fwd_rt, rev_rt);
00255 
00256                 break;
00257         case KAODVM_SEND_RERR:
00258                 m = NLMSG_DATA(nlm);
00259                 dest_addr.s_addr = m->dst;
00260                 src_addr.s_addr = m->src;
00261 
00262                 if (dest_addr.s_addr == AODV_BROADCAST ||
00263                     dest_addr.s_addr ==
00264                     DEV_IFINDEX(m->ifindex).broadcast.s_addr)
00265                         return;
00266 
00267                 fwd_rt = rt_table_find(dest_addr);
00268                 rev_rt = rt_table_find(src_addr);
00269 
00270                 do {
00271                         struct in_addr rerr_dest;
00272                         RERR *rerr;
00273 
00274                         DEBUG(LOG_DEBUG, 0,
00275                               "Sending RERR for unsolicited message from %s to dest %s",
00276                               ip_to_str(src_addr), ip_to_str(dest_addr));
00277 
00278                         if (fwd_rt) {
00279                                 rerr = rerr_create(0, fwd_rt->dest_addr,
00280                                                    fwd_rt->dest_seqno);
00281 
00282                                 rt_table_update_timeout(fwd_rt, DELETE_PERIOD);
00283                         } else
00284                                 rerr = rerr_create(0, dest_addr, 0);
00285 
00286                         /* Unicast the RERR to the source of the data transmission
00287                          * if possible, otherwise we broadcast it. */
00288 
00289                         if (rev_rt && rev_rt->state == VALID)
00290                                 rerr_dest = rev_rt->next_hop;
00291                         else
00292                                 rerr_dest.s_addr = AODV_BROADCAST;
00293 
00294                         aodv_socket_send((AODV_msg *) rerr, rerr_dest,
00295                                          RERR_CALC_SIZE(rerr), 1,
00296                                          &DEV_IFINDEX(m->ifindex));
00297 
00298                         if (wait_on_reboot) {
00299                                 DEBUG(LOG_DEBUG, 0,
00300                                       "Wait on reboot timer reset.");
00301                                 timer_set_timeout(&worb_timer, DELETE_PERIOD);
00302                         }
00303                 } while (0);
00304                 break;
00305         default:
00306                 DEBUG(LOG_DEBUG, 0, "Got mesg type=%d\n", nlm->nlmsg_type);
00307         }
00308 
00309 }
00310 static void nl_rt_callback(int sock)
00311 {
00312         int len, attrlen;
00313         socklen_t addrlen;
00314         struct nlmsghdr *nlm;
00315         struct nlmsgerr *nlmerr;
00316         char buf[BUFLEN];
00317         struct ifaddrmsg *ifm;
00318         struct rtattr *rta;
00319 
00320         addrlen = sizeof(struct sockaddr_nl);
00321 
00322         len =
00323             recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &peer, &addrlen);
00324 
00325         if (len <= 0)
00326                 return;
00327 
00328         nlm = (struct nlmsghdr *) buf;
00329 
00330         switch (nlm->nlmsg_type) {
00331         case NLMSG_ERROR:
00332                 nlmerr = NLMSG_DATA(nlm);
00333                 if (nlmerr->error == 0) {
00334                 /*      DEBUG(LOG_DEBUG, 0, "NLMSG_ACK"); */
00335                 } else {
00336                         DEBUG(LOG_DEBUG, 0, "NLMSG_ERROR, error=%d type=%d",
00337                               nlmerr->error, nlmerr->msg.nlmsg_type);
00338                 }
00339                 break;
00340         case RTM_NEWLINK:
00341                 DEBUG(LOG_DEBUG, 0, "RTM_NEWADDR");
00342                 break;
00343         case RTM_NEWADDR:
00344                 ifm = NLMSG_DATA(nlm);
00345 
00346                 rta = (struct rtattr *) ((char *) ifm + sizeof(ifm));
00347 
00348                 attrlen = nlm->nlmsg_len -
00349                     sizeof(struct nlmsghdr) - sizeof(struct ifaddrmsg);
00350 
00351                 for (; RTA_OK(rta, attrlen); rta = RTA_NEXT(rta, attrlen)) {
00352 
00353                         if (rta->rta_type == IFA_ADDRESS) {
00354                                 struct in_addr ifaddr;
00355 
00356                                 memcpy(&ifaddr, RTA_DATA(rta),
00357                                        RTA_PAYLOAD(rta));
00358 
00359                                 DEBUG(LOG_DEBUG, 0,
00360                                       "Interface index %d changed address to %s",
00361                                       ifm->ifa_index, ip_to_str(ifaddr));
00362                         }
00363                 }
00364                 break;
00365         case RTM_NEWROUTE:
00366                 /* DEBUG(LOG_DEBUG, 0, "RTM_NEWROUTE"); */
00367                 break;
00368         }
00369         return;
00370 }
00371 
00372 int prefix_length(int family, void *nm)
00373 {
00374         int prefix = 0;
00375 
00376         if (family == AF_INET) {
00377                 unsigned int tmp;
00378                 memcpy(&tmp, nm, sizeof(unsigned int));
00379 
00380                 while (tmp) {
00381                         tmp = tmp << 1;
00382                         prefix++;
00383                 }
00384                 return prefix;
00385 
00386         } else {
00387                 DEBUG(LOG_DEBUG, 0, "Unsupported address family");
00388         }
00389 
00390         return 0;
00391 }
00392 
00393 /* Utility function  comes from IPv4Route2. 
00394    Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
00395 int addattr(struct nlmsghdr *n, int type, void *data, int alen)
00396 {
00397         struct rtattr *attr;
00398         int len = RTA_LENGTH(alen);
00399 
00400         attr = (struct rtattr *) (((char *) n) + NLMSG_ALIGN(n->nlmsg_len));
00401         attr->rta_type = type;
00402         attr->rta_len = len;
00403         memcpy(RTA_DATA(attr), data, alen);
00404         n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
00405 
00406         return 0;
00407 }
00408 
00409 
00410 #define ATTR_BUFLEN 512
00411 
00412 int nl_send(struct nlsock *nl, struct nlmsghdr *n)
00413 {
00414         int res;
00415         struct iovec iov = { (void *) n, n->nlmsg_len };
00416         struct msghdr msg =
00417             { (void *) &peer, sizeof(peer), &iov, 1, NULL, 0, 0 };
00418         // int flags = 0;
00419 
00420         if (!nl)
00421                 return -1;
00422 
00423         n->nlmsg_seq = ++nl->seq;
00424         n->nlmsg_pid = nl->local.nl_pid;
00425 
00426         /* Request an acknowledgement by setting NLM_F_ACK */
00427         n->nlmsg_flags |= NLM_F_ACK;
00428 
00429         /* Send message to netlink interface. */
00430         res = sendmsg(nl->sock, &msg, 0);
00431 
00432         if (res < 0) {
00433                 fprintf(stderr, "error: %s\n", strerror(errno));
00434                 return -1;
00435         }
00436         return 0;
00437 }
00438 
00439 /* Function to add, remove and update entries in the kernel routing
00440  * table */
00441 int nl_kern_route(int action, int flags, int family,
00442                   int index, struct in_addr *dst, struct in_addr *gw,
00443                   struct in_addr *nm, int metric)
00444 {
00445         struct {
00446                 struct nlmsghdr nlh;
00447                 struct rtmsg rtm;
00448                 char attrbuf[1024];
00449         } req;
00450 
00451         if (!dst || !gw)
00452                 return -1;
00453 
00454         req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
00455         req.nlh.nlmsg_type = action;
00456         req.nlh.nlmsg_flags = NLM_F_REQUEST | flags;
00457         req.nlh.nlmsg_pid = 0;
00458 
00459         req.rtm.rtm_family = family;
00460 
00461         if (!nm)
00462                 req.rtm.rtm_dst_len = sizeof(struct in_addr) * 8;
00463         else
00464                 req.rtm.rtm_dst_len = prefix_length(AF_INET, nm);
00465 
00466         req.rtm.rtm_src_len = 0;
00467         req.rtm.rtm_tos = 0;
00468         req.rtm.rtm_table = RT_TABLE_MAIN;
00469         req.rtm.rtm_protocol = 100;
00470         req.rtm.rtm_scope = RT_SCOPE_LINK;
00471         req.rtm.rtm_type = RTN_UNICAST;
00472         req.rtm.rtm_flags = 0;
00473 
00474         addattr(&req.nlh, RTA_DST, dst, sizeof(struct in_addr));
00475 
00476         if (memcmp(dst, gw, sizeof(struct in_addr)) != 0) {
00477                 req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
00478                 addattr(&req.nlh, RTA_GATEWAY, gw, sizeof(struct in_addr));
00479         }
00480 
00481         if (index > 0)
00482                 addattr(&req.nlh, RTA_OIF, &index, sizeof(index));
00483 
00484         addattr(&req.nlh, RTA_PRIORITY, &metric, sizeof(metric));
00485 
00486         return nl_send(&rtnl, &req.nlh);
00487 }
00488 
00489 int nl_send_add_route_msg(struct in_addr dest, struct in_addr next_hop,
00490                           int metric, u_int32_t lifetime, int rt_flags,
00491                           int ifindex)
00492 {
00493         struct {
00494                 struct nlmsghdr n;
00495                 struct kaodv_rt_msg m;
00496         } areq;
00497 
00498         DEBUG(LOG_DEBUG, 0, "ADD/UPDATE: %s:%s ifindex=%d",
00499               ip_to_str(dest), ip_to_str(next_hop), ifindex);
00500 
00501         memset(&areq, 0, sizeof(areq));
00502 
00503         areq.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct kaodv_rt_msg));
00504         areq.n.nlmsg_type = KAODVM_ADDROUTE;
00505         areq.n.nlmsg_flags = NLM_F_REQUEST;
00506 
00507         areq.m.dst = dest.s_addr;
00508         areq.m.nhop = next_hop.s_addr;
00509         areq.m.time = lifetime;
00510         areq.m.ifindex = ifindex;
00511 
00512         if (rt_flags & RT_INET_DEST) {
00513                 areq.m.flags |= KAODV_RT_GW_ENCAP;
00514         }
00515 
00516         if (rt_flags & RT_REPAIR)
00517                 areq.m.flags |= KAODV_RT_REPAIR;
00518 
00519         if (nl_send(&aodvnl, &areq.n) < 0) {
00520                 DEBUG(LOG_DEBUG, 0, "Failed to send netlink message");
00521                 return -1;
00522         }
00523 #ifdef DEBUG_NETLINK
00524         DEBUG(LOG_DEBUG, 0, "Sending add route");
00525 #endif
00526         return nl_kern_route(RTM_NEWROUTE, NLM_F_CREATE,
00527                              AF_INET, ifindex, &dest, &next_hop, NULL, metric);
00528 }
00529 
00530 int nl_send_no_route_found_msg(struct in_addr dest)
00531 {
00532         struct {
00533                 struct nlmsghdr n;
00534                 kaodv_rt_msg_t m;
00535         } areq;
00536 
00537         memset(&areq, 0, sizeof(areq));
00538 
00539         areq.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct kaodv_rt_msg));
00540         areq.n.nlmsg_type = KAODVM_NOROUTE_FOUND;
00541         areq.n.nlmsg_flags = NLM_F_REQUEST;
00542 
00543         areq.m.dst = dest.s_addr;
00544 
00545         DEBUG(LOG_DEBUG, 0, "Send NOROUTE_FOUND to kernel: %s",
00546               ip_to_str(dest));
00547 
00548         return nl_send(&aodvnl, &areq.n);
00549 }
00550 
00551 int nl_send_del_route_msg(struct in_addr dest, struct in_addr next_hop, int metric)
00552 {
00553         int index = -1;
00554         struct {
00555                 struct nlmsghdr n;
00556                 struct kaodv_rt_msg m;
00557         } areq;
00558 
00559         DEBUG(LOG_DEBUG, 0, "Send DEL_ROUTE to kernel: %s", ip_to_str(dest));
00560 
00561         memset(&areq, 0, sizeof(areq));
00562 
00563         areq.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct kaodv_rt_msg));
00564         areq.n.nlmsg_type = KAODVM_DELROUTE;
00565         areq.n.nlmsg_flags = NLM_F_REQUEST;
00566 
00567         areq.m.dst = dest.s_addr;
00568         areq.m.nhop = next_hop.s_addr;
00569         areq.m.time = 0;
00570         areq.m.flags = 0;
00571 
00572         if (nl_send(&aodvnl, &areq.n) < 0) {
00573                 DEBUG(LOG_DEBUG, 0, "Failed to send netlink message");
00574                 return -1;
00575         }
00576 #ifdef DEBUG_NETLINK
00577         DEBUG(LOG_DEBUG, 0, "Sending del route");
00578 #endif
00579         return nl_kern_route(RTM_DELROUTE, 0, AF_INET, index, &dest, &next_hop,
00580                              NULL, metric);
00581 }
00582 
00583 int nl_send_conf_msg(void)
00584 {
00585         struct {
00586                 struct nlmsghdr n;
00587                 kaodv_conf_msg_t cm;
00588         } areq;
00589 
00590         memset(&areq, 0, sizeof(areq));
00591 
00592         areq.n.nlmsg_len = NLMSG_LENGTH(sizeof(kaodv_conf_msg_t));
00593         areq.n.nlmsg_type = KAODVM_CONFIG;
00594         areq.n.nlmsg_flags = NLM_F_REQUEST;
00595 
00596         areq.cm.qual_th = qual_threshold;
00597         areq.cm.active_route_timeout = active_route_timeout;
00598         areq.cm.is_gateway = internet_gw_mode;
00599 
00600 #ifdef DEBUG_NETLINK
00601         DEBUG(LOG_DEBUG, 0, "Sending aodv conf msg");
00602 #endif
00603         return nl_send(&aodvnl, &areq.n);
00604 }
 All Classes Files Functions Variables Typedefs Enumerator Defines