#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <features.h>
#include <unistd.h>
#include "hashtable.h"
#include "debug.h"
#include "fileio.h"
#include "proxyarp.h"
#include "dyn_ip.h"
#include "agentapi.h"
#include "util.h"
#include "mn_agentadv.h"
#include "mn_handler.h"
#include "mn.h"
Include dependency graph for mn_agentadv.c:
Go to the source code of this file.
Defines | |
#define | UPDATE_OFFSET(n) |
Functions | |
int | adv_ok_fa (struct agentadv_data *adv) |
agentadv_data * | adv_fetch (struct hashtable *adv_hash, struct in_addr *addr, int ifindex) |
adv_fetch: : hash of agent advertisements : address of agent : 0 to accept any interface, or index of a given interface | |
int | clean_agentadv (struct node *node, void *data) |
int | get_fa (struct agentadv_data *adv) |
int | check_expired_agent_advs (void) |
int | handle_icmp (struct interface_data *iface) |
Variables | |
mn_data | mn |
mn_config | config |
timeval | timers [TIMER_COUNT] |
int | real_tunnel_up |
#define UPDATE_OFFSET | ( | n | ) |
Value:
adv->adv.n = ext.n ? \
(typeof(ext.n)) (((char *) ext.n) - ext.start + adv->adv.start) : NULL
Referenced by handle_icmp().
struct agentadv_data* adv_fetch | ( | struct hashtable * | adv_hash, | |
struct in_addr * | addr, | |||
int | ifindex | |||
) |
adv_fetch: : hash of agent advertisements : address of agent : 0 to accept any interface, or index of a given interface
fetch an agent advertisement from the . addr: the source IP address of the agent advertisment packet
Returns: the matching advertisement
Definition at line 124 of file mn_agentadv.c.
References agentadv_key::addr, agentadv_data::adv, and agentadv_key::ifindex.
Referenced by add_fa_host_route().
00125 { 00126 struct agentadv_data *adv; 00127 struct agentadv_key key; 00128 key.addr.s_addr = addr->s_addr; 00129 key.ifindex = ifindex; 00130 00131 adv = (struct agentadv_data *) 00132 hashtable_fetch(adv_hash, addr_hash, &key, addr_cmp); 00133 return (adv); 00134 }
int adv_ok_fa | ( | struct agentadv_data * | adv | ) |
Definition at line 61 of file mn_agentadv.c.
References agentadv_data::addr, agentadv_data::adv, mn_data::force_fa_addr, mn, TUNMODE_REVERSE, TUNMODE_TRIANGLE, and mn_config::tunneling_mode.
00062 { 00063 int opts; 00064 00065 if (mn.force_fa_addr.s_addr != 0 && 00066 mn.force_fa_addr.s_addr != adv->addr.s_addr) 00067 return 0; 00068 00069 if (adv->adv.ext == NULL) 00070 return 0; 00071 00072 opts = ntohs(adv->adv.ext->opts); 00073 if ((opts & AGENT_ADV_BUSY) || !(opts & AGENT_ADV_FOREIGN_AGENT)) 00074 return 0; 00075 00076 if (config.tunneling_mode == TUNMODE_REVERSE && 00077 !(opts & AGENT_ADV_BIDIR_TUNNELING)) 00078 return 0; 00079 00080 if (config.tunneling_mode == TUNMODE_TRIANGLE && 00081 adv->adv.own_ext != NULL && 00082 !(adv->adv.own_ext->opts & AGENT_ADV_OWN_TRIANGLE_TUNNELING)) 00083 return 0; 00084 00085 return 1; 00086 }
int check_expired_agent_advs | ( | void | ) |
Definition at line 508 of file mn_agentadv.c.
References ADV_CLEANUP_FREQ, ADV_EXTRA_TIME, mn_data::agentadv, clean_agentadv(), DEBUG(), FALSE, and mn.
Referenced by main_vanha().
00509 { 00510 static time_t prev_check = 0; 00511 struct timeval now; 00512 struct timeval tmp; 00513 00514 gettimeofday(&now, NULL); 00515 00516 if (prev_check <= now.tv_sec && 00517 now.tv_sec < prev_check + ADV_CLEANUP_FREQ) 00518 return 0; 00519 00520 prev_check = now.tv_sec; 00521 current_agent_expired = FALSE; 00522 00523 tmp.tv_sec = now.tv_sec - ADV_EXTRA_TIME; 00524 tmp.tv_usec = now.tv_usec; 00525 DEBUG(DEBUG_AGENTADV, 00526 "\tchecking for expired agentadv data\n"); 00527 hashtable_iterator(mn.agentadv, clean_agentadv, &tmp); 00528 00529 if (current_agent_expired) { 00530 DEBUG(DEBUG_AGENTADV, "Current agent's adv. expired - try to " 00531 "find new FA\n"); 00532 return 1; 00533 } 00534 00535 return 0; 00536 }
Here is the call graph for this function:
int clean_agentadv | ( | struct node * | node, | |
void * | data | |||
) |
Definition at line 141 of file mn_agentadv.c.
References agentadv_data::adv, event_FA::adv, mn_data::agentadv, mn_data::current_adv, DEBUG(), DEBUG_AGENTADV, DEBUG_INFO, device_up(), FA_ADV_EXPIRE, handler_call_all(), event_FA::hash, LOG2, mn, and TRUE.
Referenced by check_expired_agent_advs(), and clean_up().
00142 { 00143 struct agentadv_data *adv; 00144 struct timeval *tval; 00145 struct event_FA dat; 00146 00147 adv = (struct agentadv_data *) node; 00148 tval = (struct timeval *) data; 00149 00150 if (tval != NULL && cmp_timeval(tval, &adv->expire) < 0) 00151 return TRUE; /* not expired */ 00152 00153 if (tval != NULL && adv->in_use) { 00154 /* in use and removal not forced */ 00155 current_agent_expired = TRUE; 00156 return TRUE; 00157 } 00158 00159 DEBUG(DEBUG_AGENTADV, "clean_agentadv: removing %s\n", 00160 inet_ntoa(adv->addr)); 00161 00162 /* call handlers registered for FA_ADV_EXPIRE event */ 00163 dat.adv = adv; 00164 dat.hash = mn.agentadv; 00165 handler_call_all(FA_ADV_EXPIRE, &dat); 00166 00167 /* remove the possible ARP entries etc. */ 00168 if (adv->arpentry == 1 && 00169 arp_del_permanent_item(adv->addr, adv->ifname) < 0) { 00170 if (device_up(adv->ifindex)) { 00171 LOG2(LOG_WARNING, 00172 "arp_del_permanent_item(%s, %s) failed\n", 00173 inet_ntoa(adv->addr), adv->ifname); 00174 } else { 00175 DEBUG(DEBUG_INFO, "arp_del_permanent_item(%s, %s) " 00176 "failed (device down)\n", 00177 inet_ntoa(adv->addr), adv->ifname); 00178 } 00179 } 00180 00181 /* remove the possible host route to FA */ 00182 if (adv->routeentry == 1) { 00183 DEBUG(DEBUG_INFO, "Removing FA route (%s,%s)\n", 00184 inet_ntoa(adv->addr), adv->ifname); 00185 if (dyn_ip_route_del(adv->addr, adv->ifname) != 0) 00186 DEBUG(DEBUG_INFO, "FA route removing failed\n"); 00187 } 00188 00189 if (mn.current_adv == adv) { 00190 DEBUG(DEBUG_AGENTADV, "clean_agentadv: removed current_adv\n"); 00191 mn.current_adv = NULL; 00192 } 00193 00194 hashtable_remove(node); 00195 free(adv); 00196 00197 return TRUE; 00198 }
Here is the call graph for this function:
int get_fa | ( | struct agentadv_data * | adv | ) |
Definition at line 415 of file mn_agentadv.c.
References event_FA::adv, mn_data::agentadv, FA_GET, handler_call_all(), event_FA::hash, and mn.
Referenced by find_agent().
00416 { 00417 struct event_FA data; 00418 00419 data.adv = adv; 00420 data.hash = mn.agentadv; 00421 handler_call_all(FA_GET, &data); 00422 return update_fa_decision(adv); 00423 }
Here is the call graph for this function:
int handle_icmp | ( | struct interface_data * | iface | ) |
Definition at line 543 of file mn_agentadv.c.
References agentadv_key::addr, agentadv_data::adv, mn_data::agentadv, check_interfaces(), DEBUG(), DEFAULT_PRIO_DEGRADE_DEGRADE, interface_data::device, mn_data::force_fa_addr, mn_data::iface, agentadv_key::ifindex, interface_data::index, MAX_INTERFACES, MIN_ALLOWED_LIFETIME, mn, MN_ADV_TYPE_FA, MN_ADV_TYPE_HA, MN_ADV_TYPE_OWN_HA, interface_data::s_adv, and UPDATE_OFFSET.
Referenced by main_vanha().
00544 { 00545 char buf[MAX_ADV_MSG]; 00546 struct adv_extensions ext; 00547 struct agentadv_key key; 00548 struct agentadv_data *adv; 00549 int res; 00550 00551 /* return, if message was not for us */ 00552 res = handle_icmp_adv(iface->s_adv, buf, MAX_ADV_MSG, &ext); 00553 if (res == -1) { 00554 /* network is down - rescan interfaces */ 00555 check_interfaces(mn.iface, MAX_INTERFACES); 00556 } 00557 00558 if (res != 1) 00559 return 0; 00560 00561 UNALIGNED_(&key.addr.s_addr, &ext.ip->saddr); 00562 00563 #ifndef MN_FA_FORCE_AFTER_AGENTADV_UPDATE 00564 if (mn.force_fa_addr.s_addr != 0 && 00565 mn.force_fa_addr.s_addr != key.addr.s_addr) { 00566 DEBUG(DEBUG_AGENTADV, 00567 "handle_icmp: force_fa set to %s - ignoring this FA(1)", 00568 inet_ntoa(mn.force_fa_addr)); 00569 DEBUG(DEBUG_AGENTADV, " (%s)\n", inet_ntoa(key.addr)); 00570 return 0; 00571 } 00572 #endif /* MN_FA_FORCE_AFTER_AGENTADV_UPDATE */ 00573 00574 key.ifindex = iface->index; 00575 00576 if (ntohs(ext.ext->reg_lifetime) < MIN_ALLOWED_LIFETIME) { 00577 DEBUG(DEBUG_AGENTADV, 00578 "handle_icmp: too small lifetime advertised (%d) " 00579 "- ignoring this FA (%s)\n", 00580 ntohs(ext.ext->reg_lifetime), inet_ntoa(key.addr)); 00581 return 0; 00582 } 00583 00584 /* save the last agentadv */ 00585 adv = (struct agentadv_data *) 00586 hashtable_fetch(mn.agentadv, addr_hash, &key, addr_cmp); 00587 if (adv == NULL) { 00588 /* we have no previous information on this mobility agent */ 00589 adv = (struct agentadv_data *) 00590 malloc(sizeof(struct agentadv_data)); 00591 if (adv == NULL) { 00592 DEBUG(DEBUG_AGENTADV, 00593 "handle_icmp: no memory for agentadv data\n"); 00594 return 0; 00595 } 00596 DEBUG(DEBUG_AGENTADV, "Added new agentadv entry for %s\n", 00597 inet_ntoa(key.addr)); 00598 memset(adv, 0, sizeof(struct agentadv_data)); 00599 list_init_node(&adv->node); 00600 UNALIGNED_(&adv->addr.s_addr, &ext.ip->saddr); 00601 adv->counter = 1; 00602 adv->prio_degrade_percent = 0; /* don't degrade new FAs! */ 00603 if (!hashtable_add(mn.agentadv, addr_hash, &key.addr, 00604 &adv->node)) { 00605 DEBUG(DEBUG_AGENTADV, 00606 "handle_icmp: hashtable_add failed\n"); 00607 free(adv); 00608 return 0; 00609 } 00610 } else { 00611 /* updating information for previously heard mobility agent */ 00612 DEBUG(DEBUG_AGENTADV, "Used old agentadv entry for %s\n", 00613 inet_ntoa(key.addr)); 00614 adv->counter++; 00615 /* Let FA become slowly "available" again */ 00616 if (adv->prio_degrade_percent > 0) 00617 adv->prio_degrade_percent = (int) 00618 (adv->prio_degrade_percent* 00619 DEFAULT_PRIO_DEGRADE_DEGRADE); 00620 /* remove the reg_failed flag if the adv. opts has changed */ 00621 if (adv->reg_failed && ext.ext->opts != adv->adv.ext->opts) { 00622 DEBUG(DEBUG_AGENTADV, 00623 "Reseting reg_failed for this FA\n"); 00624 adv->reg_failed = 0; 00625 } 00626 } 00627 00628 adv->ifindex = iface->index; 00629 dynamics_strlcpy(adv->ifname, iface->device, sizeof(adv->ifname)); 00630 gettimeofday(&adv->last, NULL); 00631 adv->expire.tv_sec = adv->last.tv_sec + ntohs(ext.radv->lifetime) + 1; 00632 adv->expire.tv_usec = adv->last.tv_usec; 00633 DEBUG(DEBUG_AGENTADV, "\tnow=%li.%li, expire=%li.%li\n", 00634 adv->last.tv_sec, adv->last.tv_usec, 00635 adv->expire.tv_sec, adv->expire.tv_usec); 00636 00637 memcpy(adv->buf, buf, MAX_ADV_MSG); 00638 memcpy(&adv->adv, &ext, sizeof(struct adv_extensions)); 00639 adv->adv.start = adv->buf; 00640 adv->adv.len = ext.len; 00641 adv->adv.coaddrs = ext.coaddrs; 00642 memcpy(&adv->adv.from, &ext.from, sizeof(ext.from)); 00643 #define UPDATE_OFFSET(n) adv->adv.n = ext.n ? \ 00644 (typeof(ext.n)) (((char *) ext.n) - ext.start + adv->adv.start) : NULL 00645 #ifndef DYN_TARGET_LINUX 00646 UPDATE_OFFSET(eth); 00647 #endif 00648 UPDATE_OFFSET(ip); 00649 UPDATE_OFFSET(radv); 00650 UPDATE_OFFSET(ext); 00651 UPDATE_OFFSET(prefix); 00652 UPDATE_OFFSET(own_ext); 00653 UPDATE_OFFSET(pubkey_hash); 00654 UPDATE_OFFSET(fa_nai); 00655 UPDATE_OFFSET(challenge); 00656 00657 #ifdef MN_FA_FORCE_AFTER_AGENTADV_UPDATE 00658 if (mn.force_fa_addr.s_addr != 0 && 00659 mn.force_fa_addr.s_addr != key.addr.s_addr) { 00660 DEBUG(DEBUG_AGENTADV, 00661 "handle_icmp: force_fa set to %s - ignoring this FA(2)", 00662 inet_ntoa(mn.force_fa_addr)); 00663 DEBUG(DEBUG_AGENTADV, " (%s)\n", inet_ntoa(key.addr)); 00664 return 0; 00665 } 00666 #endif /* MN_FA_FORCE_AFTER_AGENTADV_UPDATE */ 00667 00668 if (ntohs(ext.ext->opts) & AGENT_ADV_HOME_AGENT) { 00669 adv->adv_type = MN_ADV_TYPE_HA; 00670 handle_home_adv(adv); 00671 } 00672 if (ntohs(ext.ext->opts) & AGENT_ADV_FOREIGN_AGENT) { 00673 if (adv->adv_type != MN_ADV_TYPE_OWN_HA) 00674 adv->adv_type = MN_ADV_TYPE_FA; 00675 if (ext.coaddrs <= 0) 00676 DEBUG(DEBUG_AGENTADV, 00677 "handle_icmp: FA adv with no COAs - ignoring\n"); 00678 else 00679 handle_fa_adv(adv); 00680 } 00681 00682 return 0; 00683 }
Here is the call graph for this function:
int real_tunnel_up |
Definition at line 30 of file mn_tunnel.c.