NETWORK ATTACKS FRAMEWORK  1.0.0
A NETwork Attacks framework. Making network attacks impact evaluation easier!
NA_aodv_rrep.cc
Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * Copyright (C) 2001 Uppsala University & 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  * Authors: Erik Nordstr�m, <erik.nordstrom@it.uu.se>
00020  *
00021  *
00022  *****************************************************************************/
00023 #define NS_PORT
00024 #define OMNETPP
00025 
00026 #ifdef NS_PORT
00027 #ifndef OMNETPP
00028 #include "ns/aodv-uu.h"
00029 #else
00030 #include "../NA_aodv_uu_omnet.h"
00031 #include "compatibility.h"
00032 #endif
00033 #else
00034 #include <netinet/in.h>
00035 #include "NA_aodv_rrep.h"
00036 #include "NA_aodv_neighbor.h"
00037 #include "NA_aodv_hello.h"
00038 #include "NA_routing_table.h"
00039 #include "NA_aodv_timeout.h"
00040 #include "NA_timer_queue_aodv.h"
00041 #include "NA_aodv_socket.h"
00042 #include "NA_defs_aodv.h"
00043 #include "NA_debug_aodv.h"
00044 #include "NA_params.h"
00045 
00046 extern int unidir_hack, optimized_hellos, llfeedback;
00047 
00048 #endif
00049 
00050 
00051 RREP *NS_CLASS rrep_create(u_int8_t flags,
00052                            u_int8_t prefix,
00053                            u_int8_t hcnt,
00054                            struct in_addr dest_addr,
00055                            u_int32_t dest_seqno,
00056                            struct in_addr orig_addr, u_int32_t life)
00057 {
00058     RREP *rrep;
00059 #ifndef OMNETPP
00060     rrep = (RREP *) aodv_socket_new_msg();
00061 #else
00062     rrep =  new RREP("RouteReply");
00063     rrep->cost=0;
00064 #endif
00065     rrep->type = AODV_RREP;
00066     rrep->res1 = 0;
00067     rrep->res2 = 0;
00068     rrep->prefix = prefix;
00069     rrep->hcnt = hcnt;
00070     rrep->dest_addr = dest_addr.s_addr;
00071     rrep->dest_seqno = htonl(dest_seqno);
00072     rrep->orig_addr = orig_addr.s_addr;
00073     rrep->lifetime = htonl(life);
00074 
00075     if (flags & RREP_REPAIR)
00076         rrep->r = 1;
00077     if (flags & RREP_ACK)
00078         rrep->a = 1;
00079 
00080     /* Don't print information about hello messages... */
00081 #ifdef DEBUG_OUTPUT
00082     if (rrep->dest_addr != rrep->orig_addr)
00083     {
00084         DEBUG(LOG_DEBUG, 0, "Assembled RREP:");
00085         log_pkt_fields((AODV_msg *) rrep);
00086     }
00087 #endif
00088 
00089     return rrep;
00090 }
00091 
00092 RREP_ack *NS_CLASS rrep_ack_create()
00093 {
00094     RREP_ack *rrep_ack;
00095 #ifndef OMNETPP
00096     rrep_ack = (RREP_ack *) aodv_socket_new_msg();
00097 #else
00098     rrep_ack = new RREP_ack("RouteReplyAck");
00099 #endif
00100     rrep_ack->type = AODV_RREP_ACK;
00101 
00102     DEBUG(LOG_DEBUG, 0, "Assembled RREP_ack");
00103     return rrep_ack;
00104 }
00105 
00106 void NS_CLASS rrep_ack_process(RREP_ack * rrep_ack, int rrep_acklen,
00107                                struct in_addr ip_src, struct in_addr ip_dst)
00108 {
00109     rt_table_t *rt;
00110 
00111     rt = rt_table_find(ip_src);
00112 #ifdef OMNETPP
00113     totalRrepAckRec++;
00114 #endif
00115     if (rt == NULL)
00116     {
00117         DEBUG(LOG_WARNING, 0, "No RREP_ACK expected for %s", ip_to_str(ip_src));
00118 
00119         return;
00120     }
00121     DEBUG(LOG_DEBUG, 0, "Received RREP_ACK from %s", ip_to_str(ip_src));
00122 
00123     /* Remove unexpired timer for this RREP_ACK */
00124     timer_remove(&rt->ack_timer);
00125 }
00126 
00127 AODV_ext *NS_CLASS rrep_add_ext(RREP * rrep, int type, unsigned int offset,
00128                                 int len, char *data)
00129 {
00130     AODV_ext *ext = NULL;
00131 #ifndef OMNETPP
00132     if (offset < RREP_SIZE)
00133         return NULL;
00134 
00135     ext = (AODV_ext *) ((char *) rrep + offset);
00136 
00137     ext->type = type;
00138     ext->length = len;
00139 
00140     memcpy(AODV_EXT_DATA(ext), data, len);
00141 #else
00142     ext = rrep->addExtension(type,len,data);
00143 #endif
00144     return ext;
00145 }
00146 
00147 void NS_CLASS rrep_send(RREP * rrep, rt_table_t * rev_rt,
00148                         rt_table_t * fwd_rt, int size)
00149 {
00150     u_int8_t rrep_flags = 0;
00151     struct in_addr dest;
00152 
00153     if (!rev_rt)
00154     {
00155         DEBUG(LOG_WARNING, 0, "Can't send RREP, rev_rt = NULL!");
00156         return;
00157     }
00158 
00159     dest.s_addr = rrep->dest_addr;
00160 
00161     /* Check if we should request a RREP-ACK */
00162     if ((rev_rt->state == VALID && rev_rt->flags & RT_UNIDIR) ||
00163             (rev_rt->hcnt == 1 && unidir_hack))
00164     {
00165         rt_table_t *neighbor = rt_table_find(rev_rt->next_hop);
00166 
00167         if (neighbor && neighbor->state == VALID && !neighbor->ack_timer.used)
00168         {
00169             /* If the node we received a RREQ for is a neighbor we are
00170                probably facing a unidirectional link... Better request a
00171                RREP-ack */
00172             rrep_flags |= RREP_ACK;
00173             neighbor->flags |= RT_UNIDIR;
00174 
00175             /* Must remove any pending hello timeouts when we set the
00176                RT_UNIDIR flag, else the route may expire after we begin to
00177                ignore hellos... */
00178             timer_remove(&neighbor->hello_timer);
00179             neighbor_link_break(neighbor);
00180 
00181             DEBUG(LOG_DEBUG, 0, "Link to %s is unidirectional!",
00182                   ip_to_str(neighbor->dest_addr));
00183 
00184             timer_set_timeout(&neighbor->ack_timer, NEXT_HOP_WAIT);
00185         }
00186     }
00187 
00188     DEBUG(LOG_DEBUG, 0, "Sending RREP to next hop %s about %s->%s",
00189           ip_to_str(rev_rt->next_hop), ip_to_str(rev_rt->dest_addr),
00190           ip_to_str(dest));
00191 #ifdef OMNETPP
00192     if (!omnet_exist_rte (rev_rt->next_hop))
00193     {
00194         struct in_addr nm;
00195         nm.s_addr = ManetAddress(IPv4Address::ALLONES_ADDRESS);
00196         if (useIndex)
00197             omnet_chg_rte(rev_rt->next_hop,rev_rt->next_hop, nm, 1,false,rev_rt->ifindex);
00198         else
00199             omnet_chg_rte(rev_rt->next_hop,rev_rt->next_hop, nm, 1,false,DEV_NR(rev_rt->ifindex).ipaddr);
00200     }
00201     totalRrepSend++;
00202 #endif
00203     rrep->ttl=MAXTTL;
00204     aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, 1,
00205                      &DEV_IFINDEX(rev_rt->ifindex));
00206 
00207     /* Update precursor lists */
00208     if (fwd_rt)
00209     {
00210         precursor_add(fwd_rt, rev_rt->next_hop);
00211         precursor_add(rev_rt, fwd_rt->next_hop);
00212     }
00213 
00214     if (!llfeedback && optimized_hellos)
00215         hello_start();
00216 }
00217 
00218 void NS_CLASS rrep_forward(RREP * rrep, int size, rt_table_t * rev_rt,
00219                            rt_table_t * fwd_rt, int ttl)
00220 {
00221     /* Sanity checks... */
00222     if (!fwd_rt || !rev_rt)
00223     {
00224         DEBUG(LOG_WARNING, 0, "Could not forward RREP because of NULL route!");
00225         return;
00226     }
00227 
00228     if (!rrep)
00229     {
00230         DEBUG(LOG_WARNING, 0, "No RREP to forward!");
00231         return;
00232     }
00233 
00234     DEBUG(LOG_DEBUG, 0, "Forwarding RREP to %s", ip_to_str(rev_rt->next_hop));
00235 
00236     /* Here we should do a check if we should request a RREP_ACK,
00237        i.e we suspect a unidirectional link.. But how? */
00238     if (0)
00239     {
00240         rt_table_t *neighbor;
00241 
00242         /* If the source of the RREP is not a neighbor we must find the
00243            neighbor (link) entry which is the next hop towards the RREP
00244            source... */
00245         if (rev_rt->dest_addr.s_addr != rev_rt->next_hop.s_addr)
00246             neighbor = rt_table_find(rev_rt->next_hop);
00247         else
00248             neighbor = rev_rt;
00249 
00250         if (neighbor && !neighbor->ack_timer.used)
00251         {
00252             /* If the node we received a RREQ for is a neighbor we are
00253                probably facing a unidirectional link... Better request a
00254                RREP-ack */
00255             rrep->a = 1;
00256             neighbor->flags |= RT_UNIDIR;
00257 
00258             timer_set_timeout(&neighbor->ack_timer, NEXT_HOP_WAIT);
00259         }
00260     }
00261 #ifndef OMNETPP
00262     rrep = (RREP *) aodv_socket_queue_msg((AODV_msg *) rrep, size);
00263     rrep->hcnt = fwd_rt->hcnt;  /* Update the hopcount */
00264 
00265     aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, ttl,
00266                      &DEV_IFINDEX(rev_rt->ifindex));
00267 
00268 #else
00269     RREP * rrep_new = check_and_cast <RREP *> (rrep->dup());
00270     rrep_new->hcnt = fwd_rt->hcnt;
00271     rrep_new->hopfix = fwd_rt->hopfix;
00272     totalRrepSend++;
00273     rrep_new->ttl=ttl;
00274     aodv_socket_send((AODV_msg *) rrep_new, rev_rt->next_hop, size, 1,
00275                      &DEV_IFINDEX(rev_rt->ifindex));
00276 #endif
00277     precursor_add(fwd_rt, rev_rt->next_hop);
00278     precursor_add(rev_rt, fwd_rt->next_hop);
00279     rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT);
00280 }
00281 
00282 
00283 void NS_CLASS rrep_process(RREP * rrep, int rreplen, struct in_addr ip_src,
00284                            struct in_addr ip_dst, int ip_ttl,unsigned int ifindex)
00285 {
00286     u_int32_t rrep_lifetime, rrep_seqno, rrep_new_hcnt;
00287     u_int8_t pre_repair_hcnt = 0, pre_repair_flags = 0;
00288     rt_table_t *fwd_rt, *rev_rt;
00289     AODV_ext *ext;
00290     unsigned int extlen = 0;
00291     int rt_flags = 0;
00292     struct in_addr rrep_dest, rrep_orig;
00293     uint32_t cost;
00294     uint8_t  hopfix;
00295 #ifdef CONFIG_GATEWAY
00296     struct in_addr inet_dest_addr;
00297     int inet_rrep = 0;
00298 #endif
00299 
00300     /* Convert to correct byte order on affeected fields: */
00301     ManetAddress aux;
00302     if (getAp(rrep->dest_addr, aux))
00303     {
00304         rrep_dest.s_addr = aux;
00305     }
00306     else
00307         rrep_dest.s_addr = rrep->dest_addr;
00308 
00309     if (getAp(rrep->orig_addr, aux))
00310     {
00311         rrep_orig.s_addr = aux;
00312     }
00313     else
00314         rrep_orig.s_addr = rrep->orig_addr;
00315 
00316     rrep_seqno = ntohl(rrep->dest_seqno);
00317     rrep_lifetime = ntohl(rrep->lifetime);
00318     /* Increment RREP hop count to account for intermediate node... */
00319     rrep_new_hcnt = rrep->hcnt + 1;
00320     cost = rrep->cost;
00321     hopfix = rrep->hopfix;
00322     if (this->isStaticNode())
00323         hopfix++;
00324 
00325     if (rreplen < (int) RREP_SIZE)
00326     {
00327         alog(LOG_WARNING, 0, __FUNCTION__,
00328              "IP data field too short (%u bytes)"
00329              " from %s to %s", rreplen, ip_to_str(ip_src), ip_to_str(ip_dst));
00330         return;
00331     }
00332 
00333 
00334 
00335     /* Ignore messages which aim to a create a route to one self */
00336 
00337 #ifndef OMNETPP
00338     if (rrep_dest.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr)
00339         return;
00340 
00341     if (rrep_orig.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr)
00342         DEBUG(LOG_DEBUG, 0, "rrep for us");
00343 #else
00344 
00345 
00346     if (isLocalAddress (rrep_dest.s_addr))
00347         return;
00348     if (addressIsForUs(rrep_orig.s_addr))
00349         DEBUG(LOG_DEBUG, 0, "rrep for us");
00350 #endif
00351 
00352     DEBUG(LOG_DEBUG, 0, "from %s about %s->%s",
00353           ip_to_str(ip_src), ip_to_str(rrep_orig), ip_to_str(rrep_dest));
00354 #ifdef DEBUG_OUTPUT
00355     log_pkt_fields((AODV_msg *) rrep);
00356 #endif
00357 
00358     /* Determine whether there are any extensions */
00359 
00360 #ifndef OMNETPP
00361     ext = (AODV_ext *) ((char *) rrep + RREP_SIZE);
00362     while ((rreplen - extlen) > RREP_SIZE)
00363     {
00364 #else
00365     totalRrepRec++;
00366     ext = rrep->getFirstExtension();
00367     for (int i=0; i<rrep->getNumExtension (); i++)
00368     {
00369 #endif
00370         switch (ext->type)
00371         {
00372         case RREP_EXT:
00373             DEBUG(LOG_INFO, 0, "RREP include EXTENSION");
00374             /* Do something here */
00375             break;
00376 #ifdef CONFIG_GATEWAY
00377         case RREP_INET_DEST_EXT:
00378             if (ext->length == sizeof(u_int32_t))
00379             {
00380 
00381                 /* Destination address in RREP is the gateway address, while the
00382                  * extension holds the real destination */
00383                 memcpy(&inet_dest_addr, AODV_EXT_DATA(ext), ext->length);
00384                 DEBUG(LOG_DEBUG, 0, "RREP_INET_DEST_EXT: <%s>",
00385                       ip_to_str(inet_dest_addr));
00386                 /* This was a RREP from a gateway */
00387                 rt_flags |= RT_GATEWAY;
00388                 inet_rrep = 1;
00389                 break;
00390             }
00391 #endif
00392         default:
00393             alog(LOG_WARNING, 0, __FUNCTION__, "Unknown or bad extension %d",
00394                  ext->type);
00395             break;
00396         }
00397         extlen += AODV_EXT_SIZE(ext);
00398         ext = AODV_EXT_NEXT(ext);
00399     }
00400 
00401     /* ---------- CHECK IF WE SHOULD MAKE A FORWARD ROUTE ------------ */
00402 
00403     fwd_rt = rt_table_find(rrep_dest);
00404     rev_rt = rt_table_find(rrep_orig);
00405 
00406     if (!fwd_rt)
00407     {
00408         /* We didn't have an existing entry, so we insert a new one. */
00409         fwd_rt = rt_table_insert(rrep_dest, ip_src, rrep_new_hcnt, rrep_seqno,
00410                                  rrep_lifetime, VALID, rt_flags, ifindex, cost, hopfix);
00411     }
00412     else if (useHover && (fwd_rt->dest_seqno == 0 ||
00413              (int32_t) rrep_seqno > (int32_t) fwd_rt->dest_seqno ||
00414              (rrep_seqno == fwd_rt->dest_seqno &&
00415               (fwd_rt->state == INVALID || fwd_rt->flags & RT_UNIDIR ||
00416                cost < fwd_rt->cost))))
00417     {
00418         pre_repair_hcnt = fwd_rt->hcnt;
00419         pre_repair_flags = fwd_rt->flags;
00420 
00421         fwd_rt = rt_table_update(fwd_rt, ip_src, rrep_new_hcnt, rrep_seqno,
00422                                  rrep_lifetime, VALID,
00423                                  rt_flags | fwd_rt->flags, ifindex, cost, hopfix);
00424     }
00425     else if (!useHover && (fwd_rt->dest_seqno == 0 ||
00426              (int32_t) rrep_seqno > (int32_t) fwd_rt->dest_seqno ||
00427              (rrep_seqno == fwd_rt->dest_seqno &&
00428               (fwd_rt->state == INVALID || fwd_rt->flags & RT_UNIDIR ||
00429                rrep_new_hcnt < fwd_rt->hcnt))))
00430     {
00431         pre_repair_hcnt = fwd_rt->hcnt;
00432         pre_repair_flags = fwd_rt->flags;
00433 
00434         fwd_rt = rt_table_update(fwd_rt, ip_src, rrep_new_hcnt, rrep_seqno,
00435                                  rrep_lifetime, VALID,
00436                                  rt_flags | fwd_rt->flags, ifindex, cost, hopfix);
00437     }
00438     else
00439     {
00440         if (fwd_rt->hcnt > 1)
00441         {
00442             DEBUG(LOG_DEBUG, 0,
00443                   "Dropping RREP, fwd_rt->hcnt=%d fwd_rt->seqno=%ld",
00444                   fwd_rt->hcnt, fwd_rt->dest_seqno);
00445         }
00446         return;
00447     }
00448 
00449     /* If the RREP_ACK flag is set we must send a RREP
00450        acknowledgement to the destination that replied... */
00451     if (rrep->a)
00452     {
00453         RREP_ack *rrep_ack;
00454 
00455         rrep_ack = rrep_ack_create();
00456         totalRrepAckSend++;
00457         rrep_ack->ttl=MAXTTL;
00458         aodv_socket_send((AODV_msg *) rrep_ack, fwd_rt->next_hop,
00459                          NEXT_HOP_WAIT, 1, &DEV_IFINDEX(fwd_rt->ifindex));
00460         /* Remove RREP_ACK flag... */
00461         rrep->a = 0;
00462     }
00463 
00464     /* Check if this RREP was for us (i.e. we previously made a RREQ
00465        for this host). */
00466 #ifndef OMNETPP
00467     if (rrep_orig.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr)
00468     {
00469 #else
00470     if (isLocalAddress (rrep_orig.s_addr))
00471     {
00472 #endif
00473 
00474 #ifdef CONFIG_GATEWAY
00475         if (inet_rrep)
00476         {
00477             rt_table_t *inet_rt;
00478             inet_rt = rt_table_find(inet_dest_addr);
00479 
00480             /* Add a "fake" route indicating that this is an Internet
00481              * destination, thus should be encapsulated and routed through a
00482              * gateway... */
00483             if (!inet_rt)
00484                 rt_table_insert(inet_dest_addr, rrep_dest, rrep_new_hcnt, 0,
00485                                 rrep_lifetime, VALID, RT_INET_DEST, ifindex);
00486             else if (inet_rt->state == INVALID || rrep_new_hcnt < inet_rt->hcnt)
00487             {
00488                 rt_table_update(inet_rt, rrep_dest, rrep_new_hcnt, 0,
00489                                 rrep_lifetime, VALID, RT_INET_DEST |
00490                                 inet_rt->flags, ifindex);
00491             }
00492             else
00493             {
00494                 DEBUG(LOG_DEBUG, 0, "INET Response, but no update %s",
00495                       ip_to_str(inet_dest_addr));
00496             }
00497         }
00498 #endif              /* CONFIG_GATEWAY */
00499 
00500         /* If the route was previously in repair, a NO DELETE RERR should be
00501            sent to the source of the route, so that it may choose to reinitiate
00502            route discovery for the destination. Fixed a bug here that caused the
00503            repair flag to be unset and the RERR never being sent. Thanks to
00504            McWood <hjw_5@hotmail.com> for discovering this. */
00505         if (pre_repair_flags & RT_REPAIR)
00506         {
00507             if (fwd_rt->hcnt > pre_repair_hcnt)
00508             {
00509                 RERR *rerr;
00510                 u_int8_t rerr_flags = 0;
00511                 struct in_addr dest;
00512 
00513                 dest.s_addr = ManetAddress(IPv4Address(AODV_BROADCAST));
00514                 rerr_flags |= RERR_NODELETE;
00515 
00516 #ifdef OMNETPP
00517                 if (fwd_rt->nprec)
00518                 {
00519 #endif
00520                     rerr = rerr_create(rerr_flags, fwd_rt->dest_addr,
00521                                        fwd_rt->dest_seqno);
00522                     rerr->ttl=1;
00523                     if (fwd_rt->nprec)
00524                         aodv_socket_send((AODV_msg *) rerr, dest,
00525                                          RERR_CALC_SIZE(rerr), 1,
00526                                          &DEV_IFINDEX(fwd_rt->ifindex));
00527 #ifdef OMNETPP
00528                 }
00529 #endif
00530             }
00531         }
00532     }
00533     else
00534     {
00535         /* --- Here we FORWARD the RREP on the REVERSE route --- */
00536         if (rev_rt && rev_rt->state == VALID)
00537         {
00538 #ifndef OMNETPP
00539             rrep_forward(rrep, rreplen, rev_rt, fwd_rt, --ip_ttl);
00540 #else
00541             rrep_forward(rrep, rreplen, rev_rt, fwd_rt, ip_ttl); // the ttl is decremented for ip layer
00542 #endif
00543         }
00544         else
00545         {
00546             DEBUG(LOG_DEBUG, 0, "Could not forward RREP - NO ROUTE!!!");
00547         }
00548     }
00549 
00550     if (!llfeedback && optimized_hellos)
00551         hello_start();
00552 }
00553 
00554 /************************************************************************/
00555 
00556 /* Include a Hello Interval Extension on the RREP and return new offset */
00557 
00558 int rrep_add_hello_ext(RREP * rrep, int offset, u_int32_t interval)
00559 {
00560     AODV_ext *ext;
00561 #ifndef OMNETPP
00562     ext = (AODV_ext *) ((char *) rrep + RREP_SIZE + offset);
00563     ext->type = RREP_HELLO_INTERVAL_EXT;
00564     ext->length = sizeof(interval);
00565     memcpy(AODV_EXT_DATA(ext), &interval, sizeof(interval));
00566 #else
00567     ext = rrep->addExtension(RREP_HELLO_INTERVAL_EXT,sizeof(interval),(char*)&interval);
00568 #endif
00569     return (offset + AODV_EXT_SIZE(ext));
00570 }
00571 
 All Classes Files Functions Variables Typedefs Enumerator Defines