NETWORK ATTACKS FRAMEWORK
1.0.0
A NETwork Attacks framework. Making network attacks impact evaluation easier!
|
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