mn.c File Reference

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include "agentapi.h"
#include "debug.h"
#include "util.h"
#include "dyn_ip.h"
#include "mn.h"
#include "monitor.h"
#include "fixed_fd_zero.h"

Include dependency graph for mn.c:

Go to the source code of this file.

Functions

int degrade_current_fa_priority (void)
void passive_find (void)
void find_agent (int entry)
 find_agent: - STATE_INIT to move to this state STATE_TIMEOUT to indicate timeout in this state, ie.
void request_tunnel (int entry, int forced, int check_timer)
 rqeuest_tunnel: : STATE_INIT to move to this state, STATE_TIMEOUT to indicate timeout in this state, i.e.
void connected (int type, __u16 lifetime)
void close_for_home (int entry)
void at_home (void)
void disconnect (void)
int main_vanha (int argc, char *argv[])

Variables

int real_tunnel_up
mn_data mn
mn_config config
timeval timers [TIMER_COUNT]
char * program_name


Function Documentation

void at_home ( void   ) 

Definition at line 730 of file mn.c.

References DEBUG(), DEBUG_INFO, DEBUG_STATES, DEBUG_TIMERS, mn, MN_AT_HOME, mn_remove_dynamic_home_addr(), send_gratuitous_arp(), mn_data::state, TIMER_GEN, and timers.

Referenced by close_for_home(), and main_vanha().

00731 {
00732         DEBUG(DEBUG_INFO, "at_home()\n");
00733         send_gratuitous_arp(config.ha_ip_addr, config.mn_home_ip_addr);
00734         mn.state = MN_AT_HOME;
00735         DEBUG(DEBUG_STATES, "State: At home\n");
00736         DEBUG(DEBUG_TIMERS, "Clearing TIMER_GEN\n");
00737         timerclear(&timers[TIMER_GEN]);
00738         mn_remove_dynamic_home_addr();
00739 }

Here is the call graph for this function:

void close_for_home ( int  entry  ) 

Definition at line 649 of file mn.c.

References agentadv_data::addr, at_home(), mn_data::co_addr, mn_data::current_adv, DEBUG(), DEBUG_INFO, DEBUG_MESSAGES, DEBUG_STATES, DEBUG_TIMERS, mn_data::fa_addr, mn_data::HA_reg_retry_time, mn_data::local_addr, LOG2, MAX_REGISTRATION_TIME, MIN_REGISTRATION_TIME, mn, MN_CLOSE_FOR_HOME, real_tunnel_up, REG_DISC, agentadv_data::reg_retry_time, send_gratuitous_arp(), send_registration(), mn_data::session_key, mn_data::session_key_len, mn_config::shared_secret_len, mn_data::state, STATE_INIT, stop_tunneling(), TIMER_GEN, and timers.

00650 {
00651         int retry_time;
00652 
00653         DEBUG(DEBUG_INFO, "close_for_home(%i)\n", entry);
00654 
00655         if (mn.current_adv == NULL) {
00656                 LOG2(LOG_ALERT, "close_for_home - current_adv == NULL\n");
00657         }
00658         if (entry == STATE_INIT) {
00659                 mn.state = MN_CLOSE_FOR_HOME;
00660                 if (real_tunnel_up)
00661                         stop_tunneling();
00662                 else if (config.shared_secret_len < 0 ||
00663                          config.mn_home_ip_addr.s_addr == 0) {
00664                         DEBUG(DEBUG_INFO,
00665                               "close_for_home - not registered; going directly"
00666                               " to home\n");
00667                         at_home();
00668                         return;
00669                 } else {
00670                         DEBUG(DEBUG_INFO,
00671                               "close_for_home - not registered, but trying to "
00672                               "deregister possible old bindings at HA\n");
00673                         if (mn.co_addr.s_addr == 0)
00674                                 mn.co_addr.s_addr = mn.local_addr.s_addr;
00675                 }
00676                 if (mn.current_adv != NULL) {
00677                         DEBUG(DEBUG_TIMERS, "FA[%s] reg_retry_time: "
00678                               "%i => %i (close_for_home)\n",
00679                               inet_ntoa(mn.current_adv->addr),
00680                               mn.current_adv->reg_retry_time,
00681                               MIN_REGISTRATION_TIME);
00682                         mn.current_adv->reg_retry_time = MIN_REGISTRATION_TIME;
00683                 } else
00684                         mn.HA_reg_retry_time = MIN_REGISTRATION_TIME;
00685 
00686                 /* drop the previous session key so that locupd to FA with the
00687                  * old binding goes to the HA */
00688                 if (mn.session_key != NULL)
00689                         free(mn.session_key);
00690                 mn.session_key = NULL;
00691                 mn.session_key_len = 0;
00692         } else if (mn.current_adv == NULL ||
00693                    mn.current_adv->reg_retry_time >= MAX_REGISTRATION_TIME) {
00694                 DEBUG(DEBUG_MESSAGES,
00695                       "Could not get reply from HA - assuming deregistration "
00696                       "worked\n");
00697                 at_home();
00698                 return;
00699         } else if (mn.current_adv != NULL) {
00700                 DEBUG(DEBUG_TIMERS, "FA[%s] reg_retry_time: %i => ",
00701                       inet_ntoa(mn.current_adv->addr),
00702                       mn.current_adv->reg_retry_time);
00703                 if (mn.current_adv->reg_retry_time == 0)
00704                         mn.current_adv->reg_retry_time = 1;
00705                 else
00706                         mn.current_adv->reg_retry_time *= 2;
00707                 DEBUG(DEBUG_TIMERS, "%i\n", mn.current_adv->reg_retry_time);
00708         }
00709 
00710         send_gratuitous_arp(config.ha_ip_addr, config.mn_home_ip_addr);
00711 
00712         /* send deregistration message to HA */
00713         mn.fa_addr = config.ha_ip_addr;
00714         send_registration(REG_DISC);
00715 
00716         /* at least full retry time should be waited */
00717         gettimeofday(&timers[TIMER_GEN], NULL);
00718         retry_time = mn.current_adv ? mn.current_adv->reg_retry_time :
00719                 mn.HA_reg_retry_time;
00720         DEBUG(DEBUG_TIMERS, "close_for_home - TIMER_GEN: set now+%i sec\n",
00721               retry_time);
00722         timers[TIMER_GEN].tv_sec += retry_time;
00723 
00724         DEBUG(DEBUG_STATES, "State: Close for home\n");
00725 }

Here is the call graph for this function:

void connected ( int  type,
__u16  lifetime 
)

Definition at line 513 of file mn.c.

References agentadv_data::addr, ASSERT, CON_HA, mn_data::current_adv, DEBUG(), DEBUG_INFO, DEBUG_STATES, DEBUG_TIMERS, mn_config::enable_fa_decapsulation, mn_data::fa_addr, agentadv_data::in_use, mn_data::info_str, LOG2, mn, MN_CONNECTED, mn_config::mn_default_tunnel_lifetime, agentadv_data::prio_degrade_percent, real_tunnel_up, remove_fa_host_routes(), restart_tunneling(), start_tunneling(), mn_data::state, TIMER_GEN, TIMER_LIFETIME, TIMER_REQUEST, TIMER_REREG, timers, mn_data::tunnel_addr, mn_data::tunnel_up, and mn_data::warn_str.

00514 {
00515         DEBUG(DEBUG_INFO, "connected(%i, %i)\n", type, lifetime);
00516         ASSERT(lifetime > 0);
00517 
00518         if (mn.current_adv != NULL) {
00519                 if (mn.current_adv->addr.s_addr != mn.fa_addr.s_addr) {
00520                         DEBUG(DEBUG_INFO, "fa_addr=%s != ",
00521                               inet_ntoa(mn.fa_addr));
00522                         DEBUG(DEBUG_INFO, "current_adv->addr=%s\n",
00523                               inet_ntoa(mn.current_adv->addr));
00524                 }
00525                 mn.current_adv->in_use = 1;
00526                 /* This FA works, so don't degrade priority: */
00527                 mn.current_adv->prio_degrade_percent = 0; 
00528         } else {
00529                 LOG2(LOG_WARNING, "connected - current_adv == NULL\n");
00530                 mn.warn_str = "connected - current_adv == NULL";
00531         }
00532 
00533         /* HA MUST NOT use larger lifetime and the FAs cannot change the
00534          * requested lifetime - force the lifetime to be at maximum the
00535          * configured time */
00536         if (lifetime > config.mn_default_tunnel_lifetime) {
00537                 LOG2(LOG_WARNING, "Lifetime in the reply (%i sec) larger than "
00538                      "expected (%i sec) - lowering it\n", lifetime,
00539                      config.mn_default_tunnel_lifetime);
00540                 mn.warn_str = "lifetime in the reply larger than expected";
00541                 lifetime = config.mn_default_tunnel_lifetime;
00542         }
00543 
00544         if (config.enable_fa_decapsulation &&
00545             mn.fa_addr.s_addr != mn.tunnel_addr.s_addr &&
00546             mn.tunnel_addr.s_addr != 0 &&
00547             mn.current_adv != NULL)
00548                 remove_fa_host_routes(0);
00549 
00550         /* if tunnel endpoint has changed, or tunnel is down, create tunnel to
00551          * FA */
00552         if (mn.fa_addr.s_addr != mn.tunnel_addr.s_addr || !real_tunnel_up) {
00553                 if (real_tunnel_up) {
00554                         DEBUG(DEBUG_STATES, "Restart tunneling\n");
00555                         restart_tunneling();
00556                 } else {
00557                         DEBUG(DEBUG_STATES, "Start tunneling\n");
00558                         start_tunneling();
00559                 }
00560         }
00561 
00562         /* set lifetime timer */
00563         timers[TIMER_LIFETIME].tv_sec = timers[TIMER_REQUEST].tv_sec +
00564                 lifetime;
00565         timers[TIMER_LIFETIME].tv_usec = timers[TIMER_REQUEST].tv_usec;
00566 
00567           /* If connection was approved by HA,
00568            * reset timer for reregistering the tunnel */
00569         if (type == CON_HA) {
00570                 set_reregistration_time(lifetime);
00571         }
00572         if (mn.state != MN_CONNECTED && type == CON_HA) {
00573                 LOG2(LOG_INFO, "Connection established.\n");
00574                 mn.info_str = "connection established";
00575         }
00576 
00577         DEBUG(DEBUG_TIMERS, "setting TIMER_GEN = TIMER_REREG %li.%06li (in %li"
00578               " sec)\n",
00579               timers[TIMER_REREG].tv_sec, timers[TIMER_REREG].tv_usec,
00580               timers[TIMER_REREG].tv_sec - time(NULL));
00581         timers[TIMER_GEN] = timers[TIMER_REREG];
00582         mn.state = MN_CONNECTED;
00583         mn.tunnel_up = 1;
00584         DEBUG(DEBUG_STATES, "State: Connected\n");
00585 }

Here is the call graph for this function:

int degrade_current_fa_priority ( void   ) 

Definition at line 80 of file mn.c.

References mn_data::current_adv, DEBUG(), DEBUG_INFO, DEFAULT_PRIO_DEGRADE_FACTOR, DEFAULT_PRIO_DEGRADE_INITIAL, mn, and agentadv_data::prio_degrade_percent.

Referenced by request_tunnel().

00081 {
00082         if (mn.current_adv == NULL)
00083                 return 1;
00084 
00085         if (mn.current_adv->prio_degrade_percent == 0) {
00086                 mn.current_adv->prio_degrade_percent = 
00087                         DEFAULT_PRIO_DEGRADE_INITIAL;
00088         } else {
00089                 mn.current_adv->prio_degrade_percent *= 
00090                         DEFAULT_PRIO_DEGRADE_FACTOR;
00091         }
00092 
00093         if (mn.current_adv->prio_degrade_percent > 100) {
00094                 mn.current_adv->prio_degrade_percent = 100;
00095         }
00096 
00097         DEBUG(DEBUG_INFO, "degrade_current_fa_priority: %d\n",
00098               mn.current_adv->prio_degrade_percent);
00099         
00100         return 0;
00101 }

Here is the call graph for this function:

void disconnect ( void   ) 

Definition at line 744 of file mn.c.

References mn_data::cur_route_info, DEBUG(), DEBUG_INFO, DEBUG_MESSAGES, DEBUG_STATES, DEBUG_TIMERS, mn, MN_CONNECTED, MN_DISCONNECTED, mn_remove_dynamic_home_addr(), real_tunnel_up, REG_DISC, send_registration(), mn_data::session_key, mn_data::session_key_len, mn_data::state, stop_tunneling(), TIMER_GEN, and timers.

Referenced by handle_api().

00745 {
00746         DEBUG(DEBUG_INFO, "disconnect()\n");
00747 
00748         mn.cur_route_info.known = 0;
00749 
00750         /* if we are connected, we'd better throw out a
00751          * deregistration message */
00752         if (mn.state == MN_CONNECTED) {
00753                 send_registration(REG_DISC);
00754                 DEBUG(DEBUG_MESSAGES, "Deregistration message sent\n");
00755         }
00756         if (real_tunnel_up) stop_tunneling();
00757 
00758         /* free session key */
00759         if (mn.session_key) {
00760                 free(mn.session_key);
00761                 mn.session_key = NULL;
00762                 mn.session_key_len = 0;
00763         }
00764 
00765         DEBUG(DEBUG_TIMERS, "Clearing TIMER_GEN\n");
00766         timerclear(&timers[TIMER_GEN]);
00767         mn.state = MN_DISCONNECTED;
00768         DEBUG(DEBUG_STATES, "State: Disconnected\n");
00769         syslog(LOG_INFO, "Disconnected.");
00770         mn_remove_dynamic_home_addr();
00771 }

Here is the call graph for this function:

void find_agent ( int  entry  ) 

find_agent: - STATE_INIT to move to this state STATE_TIMEOUT to indicate timeout in this state, ie.

we haven't received an agent adv to our last sent solicitation

Enter find agent state

Definition at line 308 of file mn.c.

References mn_data::co_addr, mn_data::current_adv, DEBUG(), DEBUG_INFO, DEBUG_STATES, DEBUG_TIMERS, mn_data::device_count, mn_data::fa_addr, FA_GET_NO, get_fa(), mn_config::home_net_addr_plen, mn_config::home_net_subnet_bc, agentadv_data::in_use, mn_data::local_addr, MAX_RANDOM_SOLICITATION_DELAY, mn, mn_config::mn_default_tunnel_lifetime, MN_FIND_AGENT, passive_find(), mn_data::req_lifetime, request_tunnel(), mn_data::state, STATE_INIT, TIMER_GEN, timers, mn_data::tunnel_mode, and mn_data::tunnel_up.

Referenced by handle_api(), main_vanha(), and request_tunnel().

00309 {
00310         int t, chg;
00311         static int retry_time = 0; /* time in seconds between retries of agent
00312                                     * solicitations */
00313 
00314         DEBUG(DEBUG_INFO, "find_agent(%i)\n", entry);
00315 
00316         mn.tunnel_up = 0;
00317 
00318         if (mn.device_count == 0) {
00319                 passive_find();
00320                 return;
00321         }
00322 
00323         if (mn.tunnel_mode == API_TUNNEL_FULL_HA) {
00324                 DEBUG(DEBUG_INFO,
00325                       "find_agent: trying to register directly to HA\n");
00326                 if (config.ha_ip_addr.s_addr == 0 &&
00327                     config.home_net_addr_plen > -1) {
00328                         /* dynamic HA address resolution */
00329                         mn.fa_addr.s_addr = config.home_net_subnet_bc.s_addr;
00330                 } else
00331                         mn.fa_addr.s_addr = config.ha_ip_addr.s_addr;
00332                 mn.co_addr.s_addr = mn.local_addr.s_addr;
00333                 if (mn.current_adv != NULL) {
00334                         mn.current_adv->in_use = 0;
00335                         mn.current_adv = NULL;
00336                 }
00337                 request_tunnel(STATE_INIT, 0, 0);
00338                 return;
00339         }
00340 
00341         /* try to find the best FA from the previously received agentadvs;
00342          * if a valid entry is found, use it; otherwise send agent
00343          * solicitation */
00344         chg = get_fa(NULL);
00345         if (chg != FA_GET_NO) {
00346                 DEBUG(DEBUG_INFO, "find_agent: found FA from stored agentadv "
00347                       "data - FA=%s, HFA=", inet_ntoa(mn.fa_addr));
00348                 DEBUG(DEBUG_INFO, "%s\n", inet_ntoa(mn.co_addr));
00349                 request_tunnel(STATE_INIT, 0, 0);
00350                 return;
00351         }
00352 
00353         if (entry == STATE_INIT) {
00354                 mn.state = MN_FIND_AGENT;
00355                 retry_time = 0;
00356                 mn.req_lifetime = config.mn_default_tunnel_lifetime;
00357         }
00358 
00359         t = get_solicitation_interval(&retry_time);
00360         if (t == 0) {
00361                 passive_find();
00362                 return;
00363         }
00364 
00365         /* send agent solicitation to all the active interfaces */
00366         send_solicitations(&mn);
00367 
00368         DEBUG(DEBUG_TIMERS, "find_agent - TIMER_GEN: set now+%i sec\n", t);
00369         gettimeofday(&timers[TIMER_GEN], NULL);
00370         timers[TIMER_GEN].tv_sec += t;
00371         add_usecs(&timers[TIMER_GEN],
00372                   get_rand32() % MAX_RANDOM_SOLICITATION_DELAY);
00373 
00374         DEBUG(DEBUG_STATES, "State: Find agent\n");
00375 }

Here is the call graph for this function:

int main_vanha ( int  argc,
char *  argv[] 
)

Definition at line 910 of file mn.c.

References at_home(), check_expired_agent_advs(), check_interfaces(), check_old_tunnel_expiration(), mn_config::enable_fa_decapsulation, mn_config::enforce_routes, find_agent(), handle_api(), handle_icmp(), handle_registration(), is_coloc_addr_foreign(), LOG2, mn, MN_DISCONNECTED, mn_init(), mn_parse_command_line(), MN_STOP, program_name, and STATE_INIT.

00911 {
00912         int n, i;
00913         fd_set set;
00914         struct timeval tv;
00915 
00916         memset(&mn, 0, sizeof(mn));
00917         mn.info_str = "initialization in progress";
00918 
00919         program_name = parse_long_options(argc, argv, "mobile node",
00920                                              PACKAGE, VERSION, dynamics_usage);
00921 
00922         mn_parse_command_line(argc, argv);
00923 
00924         if (!mn_init()) {
00925                 fprintf(stderr, "Initialization failed.\n");
00926                 exit(0);
00927         }
00928 
00929         if (mn.opt_connect) {
00930                 /* try to connect to a FA if MN is using FA decapsulation (i.e.
00931                  * its own home IP addr also in the foreign network) or if the
00932                  * home address is not assigned to a local interface with MN
00933                  * decapsulation */
00934                 mn.info_str = "trying to connect";
00935                 if (config.enable_fa_decapsulation || is_coloc_addr_foreign())
00936                 {
00937                         mn.tunnel_mode = API_TUNNEL_FULL;
00938                         find_agent(STATE_INIT);
00939                 } else at_home();
00940         }
00941 
00942         /* MN main loop */
00943         while (mn.state != MN_STOP) {
00944                 check_old_tunnel_expiration();
00945 
00946                 FD_ZERO(&set);
00947                 FD_SET(mn.registration_socket, &set);
00948                 for (i = 0; i < MAX_INTERFACES; i++) {
00949                         if (mn.iface[i].s_adv > -1)
00950                                 FD_SET(mn.iface[i].s_adv, &set);
00951                 }
00952                 if (mn.api_rw_socket > -1)
00953                         FD_SET(mn.api_rw_socket, &set);
00954                 if (mn.api_ro_socket > -1)
00955                         FD_SET(mn.api_ro_socket, &set);
00956 #ifdef INCLUDE_IPAY
00957                 FD_SET(mn.ipay_sock, &set);
00958                 FD_SET(mn.ipay_sock_fa, &set);
00959 #endif
00960                 if (mn.rtnetlink_socket > -1)
00961                         FD_SET(mn.rtnetlink_socket, &set);
00962 
00963                 if (get_next_timeout(&tv))
00964                         n = select(FD_SETSIZE, &set, NULL, NULL, &tv);
00965                 else n = select(FD_SETSIZE, &set, NULL, NULL, NULL);
00966                 if (n == 0) {
00967                         handle_timeout();
00968                         continue;
00969                 } else if (n == -1) {
00970                         switch (errno) {
00971                         case EINTR:
00972                                 break;
00973                         default:
00974                                 LOG2(LOG_ERR, "main - select: %s\n",
00975                                      strerror(errno));
00976                                 /* this used to exit dynmnd with
00977                                  * mn.state = MN_STOP;
00978                                  * but this might be a temporary problem, so
00979                                  * try agains; use a small delay to prevent
00980                                  * hogging all the CPU in case of select()
00981                                  * returning error all the time */
00982                                 sleep(1);
00983                         }
00984                         continue;
00985                 }
00986 
00987                 if (FD_ISSET(mn.registration_socket, &set) &&
00988                     handle_registration(mn.registration_socket)) {
00989                         /* try to reregister */
00990                         reinitiate_state();
00991                 }
00992 
00993                 for (i = 0; i < MAX_INTERFACES; i++) {
00994                         if (mn.iface[i].s_adv > -1 &&
00995                             FD_ISSET(mn.iface[i].s_adv, &set))
00996                                 handle_icmp(&mn.iface[i]);
00997                 }
00998 
00999                 if (mn.rtnetlink_socket > -1 &&
01000                     FD_ISSET(mn.rtnetlink_socket, &set)) {
01001                         int res = dyn_ip_monitor_get(
01002                                 mn.rtnetlink_socket,
01003                                 (config.enforce_routes &&
01004                                  mn.state != MN_DISCONNECTED) ?
01005                                 &mn.cur_route_info : NULL);
01006                         if (res == 1 || res == 2)
01007                                 check_interfaces(mn.iface, MAX_INTERFACES);
01008                 }
01009 
01010                 if (mn.api_rw_socket > -1 && FD_ISSET(mn.api_rw_socket, &set))
01011                         handle_api(mn.api_rw_socket, 1);
01012 
01013                 if (mn.api_ro_socket > -1 && FD_ISSET(mn.api_ro_socket, &set))
01014                         handle_api(mn.api_ro_socket, 0);
01015 
01016 #ifdef INCLUDE_IPAY
01017                 if (FD_ISSET(mn.ipay_sock, &set))
01018                         handle_ipay(mn.ipay_sock);
01019                 if (FD_ISSET(mn.ipay_sock_fa, &set))
01020                         handle_ipay(mn.ipay_sock_fa);
01021 #endif
01022 
01023                 /* check expired agent advs. If current FA's agent
01024                    adv. has expired move to FIND_AGENT state */
01025                 if (check_expired_agent_advs())
01026                         find_agent(STATE_INIT);
01027         }
01028 
01029         clean_up(0);
01030         return 0;
01031 }

Here is the call graph for this function:

void passive_find ( void   ) 

Definition at line 268 of file mn.c.

References DEBUG(), DEBUG_STATES, mn, MN_PASSIVE_FIND, and mn_data::state.

Referenced by find_agent().

00269 {
00270         mn.state = MN_PASSIVE_FIND;
00271         DEBUG(DEBUG_STATES, "State: Passive find\n");
00272 }

Here is the call graph for this function:

void request_tunnel ( int  entry,
int  forced,
int  check_timer 
)

rqeuest_tunnel: : STATE_INIT to move to this state, STATE_TIMEOUT to indicate timeout in this state, i.e.

no reply for last request within retry time

Enter request tunnel state

Definition at line 386 of file mn.c.

References add_fa_host_route(), agentadv_data::addr, mn_data::agentadv, mn_data::current_adv, DEBUG(), DEBUG_INFO, DEBUG_STATES, DEBUG_TIMERS, degrade_current_fa_priority(), mn_config::enable_fa_decapsulation, mn_data::fa_addr, find_agent(), mn_data::HA_reg_retry_time, agentadv_data::ifindex, agentadv_data::ifname, mn_data::info_str, mn_data::last_reg_send_time, MAX_REGISTRATION_TIME, MIN_REGISTRATION_DELAY, MIN_REGISTRATION_TIME, mn, MN_REQUEST_TUNNEL, REG_CONNECT, REG_REREG, agentadv_data::reg_retry_time, reply_waiting_api(), send_registration(), mn_data::state, STATE_INIT, TIMER_GEN, timers, mn_data::tunnel_up, mn_config::use_hadisc, and mn_data::warn_str.

Referenced by find_agent(), and handle_api().

00387 {
00388         int retry_time;
00389 
00390         DEBUG(DEBUG_INFO, "request_tunnel(%i, %i, %i)\n", entry, forced,
00391               check_timer);
00392 
00393         if (mn.current_adv == NULL) {
00394                 retry_time = mn.HA_reg_retry_time;
00395                 DEBUG(DEBUG_INFO, "No current agent advertisement " 
00396                       "when requesting tunnel (direct tunnel to HA?)\n");
00397         } else
00398                 retry_time = mn.current_adv->reg_retry_time;
00399 
00400         if (check_timer && retry_time > 1) {
00401                 struct timeval now;
00402                 gettimeofday(&now, NULL);
00403                 if (timerisset(&timers[TIMER_GEN]) &&
00404                     cmp_timeval(&now, &timers[TIMER_GEN]) < 0) {
00405                         DEBUG(DEBUG_TIMERS, "request_tunnel: TIMER_GEN not "
00406                               "yet reached\n");
00407                         return;
00408                 }
00409         }
00410 
00411         if (config.enable_fa_decapsulation && mn.current_adv != NULL)
00412                 add_fa_host_route(mn.current_adv->ifname, mn.agentadv,
00413                                   mn.current_adv->ifindex, mn.fa_addr);
00414 
00415         if (entry == STATE_INIT) {
00416                 mn.state = MN_REQUEST_TUNNEL;
00417                 if (!forced)
00418                         mn.tunnel_up = 0;
00419 
00420                 /* if last registration was sent less than a second ago,
00421                    wait a second before sending the request */
00422                 if (usec_passed(&mn.last_reg_send_time, NULL) <
00423                     MIN_REGISTRATION_DELAY) {
00424                         DEBUG(DEBUG_INFO, "Too frequent registration request "
00425                               "- delaying\n");
00426                         DEBUG(DEBUG_TIMERS, "request_tunnel: TIMER_GEN: set "
00427                               "now+1 sec (too freq.)\n");
00428                         gettimeofday(&timers[TIMER_GEN], NULL);
00429                         timers[TIMER_GEN].tv_sec++;
00430                         return;
00431                 }
00432         } else if (retry_time > MAX_REGISTRATION_TIME) {
00433                 /* STATE_TIMEOUT */
00434                 if (config.use_hadisc) {
00435                         DEBUG(DEBUG_INFO, "HA does not reply - try to discover"
00436                               " another HA\n");
00437                         mn.info_str = "restarting HA discovery";
00438                         config.ha_ip_addr.s_addr = 0;
00439                         if (mn.current_adv != NULL)
00440                                 mn.current_adv->reg_retry_time =
00441                                         MIN_REGISTRATION_TIME;
00442                         else
00443                                 mn.HA_reg_retry_time =
00444                                         MIN_REGISTRATION_TIME;
00445                 } else {
00446                         /* give up, switch to find agent */
00447                         if (forced) {
00448                                 DEBUG(DEBUG_INFO,
00449                                       "Could not confirm tunnel.\n");
00450                                 reply_waiting_api(API_FAILED, NULL, 0);
00451                         } else {
00452                                 DEBUG(DEBUG_INFO, "Could not register.\n");
00453                         }
00454                         find_agent(STATE_INIT);
00455                         return;
00456                 }
00457         } else if (mn.current_adv != NULL) {
00458                 /* STATE_TIMEOUT */
00459 #ifndef NO_PRIO_DEGRADE
00460                 /* degrade the FA priority */
00461                 degrade_current_fa_priority();
00462 #endif /* NO_PRIO_DEGRADE */
00463                 DEBUG(DEBUG_TIMERS, "FA[%s] reg_retry_time: %i => ",
00464                       inet_ntoa(mn.current_adv->addr),
00465                       mn.current_adv->reg_retry_time);
00466                 if (mn.current_adv->reg_retry_time == 0)
00467                         mn.current_adv->reg_retry_time = MIN_REGISTRATION_TIME;
00468                 else
00469                         mn.current_adv->reg_retry_time *= 2;
00470                 DEBUG(DEBUG_TIMERS, "%i\n", mn.current_adv->reg_retry_time);
00471         } else {
00472                 if (mn.HA_reg_retry_time == 0)
00473                         mn.HA_reg_retry_time = MIN_REGISTRATION_TIME;
00474                 else
00475                         mn.HA_reg_retry_time *= 2;
00476         }
00477 
00478         if (send_registration(forced ? REG_REREG : REG_CONNECT) < 0) {
00479                 DEBUG(DEBUG_INFO, "Registration failed for this FA - trying to"
00480                       " find a new one\n");
00481                 mn.warn_str = "Registration failed for this FA, trying to find"
00482                         " a new one";
00483                 find_agent(STATE_INIT);
00484                 return;
00485         }
00486 
00487         gettimeofday(&timers[TIMER_GEN], NULL);
00488         if (mn.current_adv != NULL) {
00489                 if (mn.current_adv->reg_retry_time < MIN_REGISTRATION_TIME)
00490                         mn.current_adv->reg_retry_time = MIN_REGISTRATION_TIME;
00491                 retry_time = mn.current_adv->reg_retry_time;
00492         } else {
00493                 if (mn.HA_reg_retry_time < MIN_REGISTRATION_TIME)
00494                         mn.HA_reg_retry_time = MIN_REGISTRATION_TIME;
00495                 retry_time = mn.HA_reg_retry_time;
00496         }
00497         DEBUG(DEBUG_TIMERS, "request_tunnel - TIMER_GEN: set now+%i sec\n",
00498               retry_time);
00499         timers[TIMER_GEN].tv_sec += retry_time;
00500 
00501         DEBUG(DEBUG_STATES, "State: Request tunnel%s\n",
00502               forced ? " (forced)" : "");
00503 }

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.

Referenced by adv_ok_fa(), at_home(), check_expired_agent_advs(), clean_agentadv(), clean_up(), close_for_home(), connected(), create_mobile(), degrade_current_fa_priority(), device_up(), disconnect(), find_agent(), get_fa(), handle_api(), handle_icmp(), handle_registration(), load_mn(), main_vanha(), mn_init(), mn_parse_command_line(), mn_remove_dynamic_home_addr(), monitor_poll_ap_addresses(), passive_find(), remove_fa_host_routes(), reply_waiting_api(), request_tunnel(), restart_tunneling(), send_registration(), start_tunneling(), stop_tunneling(), and update_fa_decaps_routes().

char* program_name

Definition at line 48 of file mn.c.

Referenced by main_vanha(), and mn_init().

int real_tunnel_up

Definition at line 30 of file mn_tunnel.c.

Referenced by close_for_home(), close_tunneling(), connected(), disconnect(), init_tunneling(), restart_tunneling(), start_tunneling(), and stop_tunneling().

struct timeval timers[TIMER_COUNT]

Definition at line 47 of file mn.c.

Referenced by at_home(), close_for_home(), connected(), disconnect(), find_agent(), mn_init(), request_tunnel(), and send_registration().


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