mn_agentadv.c File Reference

#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_dataadv_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 Documentation

#define UPDATE_OFFSET (  ) 

Value:

adv->adv.n = ext.n ? \
(typeof(ext.n)) (((char *) ext.n) - ext.start + adv->adv.start) : NULL

Referenced by handle_icmp().


Function Documentation

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:


Variable Documentation

struct mn_config config

Definition at line 45 of file mn.c.

struct mn_data mn

Definition at line 44 of file mn.c.

int real_tunnel_up

Definition at line 30 of file mn_tunnel.c.

struct timeval timers[TIMER_COUNT]

Definition at line 47 of file mn.c.


Generated on Tue Jan 15 08:50:50 2008 for Virtual foreign agent generator version 0.1 by  doxygen 1.5.1