mn_reg.c

Go to the documentation of this file.
00001 /* $Id: mn_reg.c,v 1.64 2001/09/29 14:56:23 jm Exp $
00002  * Mobile Node - registration
00003  *
00004  * Dynamic hierarchial IP tunnel
00005  *
00006  * Copyright (C) 1998-2001, Dynamics group, Tero Hätinen,
00007  * Joni Purojärvi and Antti Pyykkönen (Dynamo group)
00008  *
00009  * Modified by Tero Hätinen, Joni Purojärvi and Antti Pyykkönen
00010  * Used as a testing tool for home agent.
00011  * "Virtual foreign agent"
00012  * Generates registeration messages to the home agent
00013  *
00014  * This program is free software; you can redistribute it and/or modify
00015  * it under the terms of the GNU General Public License version 2 as
00016  * published by the Free Software Foundation. See README and COPYING for
00017  * more details.
00018  */
00019 
00020 #include "config.h"
00021 #include <stdlib.h>
00022 #include <stdio.h>
00023 #include <assert.h>
00024 #include <sys/socket.h>
00025 #include <netinet/in.h>
00026 #include <arpa/inet.h>
00027 #include <errno.h>
00028 #ifdef DYN_TARGET_LINUX
00029 #include <net/if_arp.h>
00030 #endif
00031 #include <string.h>
00032 #include <time.h>
00033 
00034 #include "agentapi.h"
00035 #include "auth.h"
00036 #include "debug.h"
00037 #include "msgparser.h"
00038 #include "proxyarp.h"
00039 #include "util.h"
00040 #include "mn.h"
00041 
00042 #include "fileio.h"
00043 #ifdef INCLUDE_IPAY
00044 #include "mn_ipay.h"
00045 #endif
00046 
00047 extern struct mn_data mn;
00048 extern struct mn_config config;
00049 extern struct timeval timers[TIMER_COUNT];
00050 
00051 /*Fileio stuff */
00052 int intervals[5000];
00053 
00054 //#define NUM_DEVICES 5000;
00055 int rownumber=0;
00056 typedef struct device DEVICE;
00057 typedef struct rowdata ROWDATA;
00058 
00059 
00060 
00061 
00062 
00063 struct rowdata { 
00064   char row[BUFSIZ];
00065 };
00066 
00067 
00068 struct device { 
00069   char ip_home[17]; 
00070   char ip_homeagent[17];
00071   char ip_careoff[17];
00072   char nai[32];
00073   char timestart[3];;
00074   char state[2];
00075 
00076 };
00077 
00078 
00079 
00080 
00081 DEVICE devices[5000];
00082 ROWDATA rows[5000];
00083 
00084 int sent_regs;
00085 int sent_deregs;
00086 
00087 struct tm *tmptr;
00088 time_t tm;      
00089 char timestr[60];
00090 
00091 
00092 /* "Virtual mobile" */
00093 struct mobile
00094 {
00095         struct mn_data mn;
00096         struct mn_config config;
00097         int state;
00098 
00099 };
00100 
00101 struct mobile mobile_array[20];
00102 int cur_mobile=0; //place of the virtual mobile in array
00103 int mobiles=0; //how many mobiles are in array
00104 
00105 static int fill_req_header(char *pos, int request_type, int use_reverse)
00106 {
00107         struct reg_req *req;
00108         int new_reg_time;
00109         unsigned int new_reg_rand;
00110         static int last_reg_time = 0;
00111         static unsigned int last_reg_rand = 0;
00112         struct timeval tv;
00113 
00114         req = (struct reg_req *) pos;
00115         req->type = REG_REQ;
00116         req->opts = 0;
00117         /* Note: the agent adv should be checked for allowed tunneling modes
00118          * and req->opts should be adjusted with that information if needed
00119          * (i.e. do not request unsupported mode) */
00120         if (!mobile_array[cur_mobile].config.enable_fa_decapsulation)
00121                 req->opts |= REGREQ_MN_DECAPS;
00122         if (use_reverse)
00123                 req->opts |= REGREQ_REVERSE_TUNNEL;
00124         if (request_type != REG_DISC) {
00125                 if (mobile_array[cur_mobile].mn.tunnel_mode == API_TUNNEL_FULL_HA)
00126                         req->lifetime =
00127                                 htons(mobile_array[cur_mobile].config.mn_default_tunnel_lifetime);
00128                 else
00129                         req->lifetime =
00130                                 htons(MIN(mobile_array[cur_mobile].mn.req_lifetime,
00131                                           mobile_array[cur_mobile].config.mn_default_tunnel_lifetime));
00132                 if (ntohs(req->lifetime) == 0) {
00133                         LOG2(LOG_INFO, "send_registration - trying to register"
00134                              ", but lifetime=0 - aborting\n");
00135                         return -1;
00136                 }
00137         } else req->lifetime = 0;
00138         req->home_addr.s_addr = mobile_array[cur_mobile].config.mn_home_ip_addr.s_addr;
00139         if (mobile_array[cur_mobile].config.ha_ip_addr.s_addr == 0 && mobile_array[cur_mobile].config.use_aaa) {
00140                 req->ha_addr.s_addr = mobile_array[cur_mobile].config.allow_home_addr_from_foreign_net ?
00141                         0 : -1;
00142         } else if (mobile_array[cur_mobile].config.ha_ip_addr.s_addr == 0 &&
00143                    mobile_array[cur_mobile].config.home_net_addr_plen > -1) {
00144                 /* dynamic HA address resolution */
00145                 req->ha_addr.s_addr = mobile_array[cur_mobile].config.home_net_subnet_bc.s_addr;
00146         } else
00147                 req->ha_addr.s_addr = mobile_array[cur_mobile].config.ha_ip_addr.s_addr;
00148         req->co_addr.s_addr = mobile_array[cur_mobile].mn.co_addr.s_addr;
00149 
00150         switch (mobile_array[cur_mobile].config.replay_meth) {
00151         case REPLAY_PROTECTION_NONE:
00152                 req->id[0] = 0;
00153                 req->id[1] = get_rand32();
00154                 break;
00155 
00156         case REPLAY_PROTECTION_TIMESTAMP:
00157                 /* set the timestamp according to RFC 2002, 5.6.1 (NTP format):
00158                  * high-order 32 bits: time in seconds from year 1900,
00159                  * low-order 32 bits: fractional seconds (1/256 sec resolution,
00160                  * i.e., 8 bits, used) and the last bits random */
00161                 gettimeofday(&tv, NULL);
00162                 new_reg_time = tv.tv_sec + mobile_array[cur_mobile].mn.clock_correction;
00163                 new_reg_rand = ((tv.tv_usec * 256 / 1000000) << 24) |
00164                         (get_rand32() & 0xffffff);
00165                 if (new_reg_time == last_reg_time &&
00166                     new_reg_rand <= last_reg_rand) {
00167                         /* id must always increase - forcing a larger id */
00168                         new_reg_rand = last_reg_rand + 1;
00169                 }
00170                 req->id[0] = htonl(new_reg_time + UNIX_NTP_DIFF);
00171                 req->id[1] = htonl(new_reg_rand);
00172                 last_reg_time = new_reg_time;
00173                 last_reg_rand = new_reg_rand;
00174                 break;
00175 
00176         case REPLAY_PROTECTION_NONCE:
00177                 req->id[0] = mobile_array[cur_mobile].mn.last_nonce;
00178                 req->id[1] = get_rand32();
00179                 break;
00180         }
00181 
00182         return sizeof(struct reg_req);
00183 }
00184 
00185 
00186 static int nai_equal(struct fa_nai_ext *nai1, struct fa_nai_ext *nai2)
00187 {
00188         int len = GET_NAI_LEN(nai1);
00189         if (nai2 == NULL || GET_NAI_LEN(nai2) != len)
00190                 return 0;
00191         if (memcmp(MSG_NAI_DATA(nai1), MSG_NAI_DATA(nai2), len) == 0)
00192                 return 1;
00193         return 0;
00194 }
00195 
00196 
00197 static int add_localized_reg_extensions(char *pos, int left, char *start)
00198 {
00199         static int last_req_seq_num = 0;
00200         struct registration_ext_dynamics *dyn_ext;
00201         int n, added = 0, add_auth = 1;
00202 
00203         if (mobile_array[cur_mobile].mn.current_adv == NULL || mobile_array[cur_mobile].mn.current_adv->adv.fa_nai == NULL ||
00204             mobile_array[cur_mobile].mn.last_req_FA_NAI->type == 0 ||
00205             (!mobile_array[cur_mobile].mn.prev_req_replied &&
00206              !nai_equal(mobile_array[cur_mobile].mn.last_req_FA_NAI, mobile_array[cur_mobile].mn.current_adv->adv.fa_nai))) {
00207                 if (mobile_array[cur_mobile].mn.current_adv == NULL)
00208                         DEBUG(DEBUG_INFO, "\tmobile_array[cur_mobile].mn.current_adv == NULL\n");
00209                 if (mobile_array[cur_mobile].mn.current_adv != NULL &&
00210                     mobile_array[cur_mobile].mn.current_adv->adv.fa_nai == NULL)
00211                         DEBUG(DEBUG_INFO,
00212                               "\tcurrent_adv->fa_nai == NULL\n");
00213                 if (mobile_array[cur_mobile].mn.last_req_FA_NAI->type == 0)
00214                         DEBUG(DEBUG_INFO, "\tlast_req_FA_NAI->type == 0\n");
00215                 if (!mobile_array[cur_mobile].mn.prev_req_replied)
00216                         DEBUG(DEBUG_INFO, "\t!mobile_array[cur_mobile].mn.prev_req_replied\n");
00217                 if (mobile_array[cur_mobile].mn.current_adv != NULL &&
00218                     !nai_equal(mobile_array[cur_mobile].mn.last_req_FA_NAI, mobile_array[cur_mobile].mn.current_adv->adv.fa_nai))
00219                         DEBUG(DEBUG_INFO, "\t!nai_equal()\n");
00220 
00221                 if (mobile_array[cur_mobile].mn.current_adv == NULL ||
00222                     mobile_array[cur_mobile].mn.current_adv->adv.fa_nai != NULL) {
00223                         DEBUG(DEBUG_INFO, "Not adding SK auth because "
00224                               "current_adv == NULL or FA NAI advertised and "
00225                               "forcing req. to HA\n");
00226                         add_auth = 0;
00227                 }
00228 
00229                 DEBUG(DEBUG_INFO, "Excluding previous FA NAI extension "
00230                       "(forcing request to HA)\n");
00231                 mobile_array[cur_mobile].mn.last_req_FA_NAI->type = 0;
00232         }
00233 
00234         if (left < sizeof(struct registration_ext_dynamics))
00235                 return -1;
00236 
00237         DEBUG(DEBUG_MESSAGES, " * ext_dynamics\n");
00238         dyn_ext = (struct registration_ext_dynamics *) pos;
00239         dyn_ext->type = VENDOR_EXT_TYPE2;
00240         dyn_ext->length = sizeof(struct registration_ext_dynamics) - 2;
00241         dyn_ext->reserved = 0;
00242         dyn_ext->vendor_id = htonl(VENDOR_ID_DYNAMICS);
00243         dyn_ext->sub_type = htons(VENDOR_EXT_DYNAMICS_OPTIONS);
00244         dyn_ext->version = VENDOR_EXT_VERSION;
00245         dyn_ext->opts = 0;
00246         dyn_ext->seq = htonl(++last_req_seq_num);
00247         added += sizeof(struct registration_ext_dynamics);
00248         left -= sizeof(struct registration_ext_dynamics);
00249 
00250         if (mobile_array[cur_mobile].mn.current_adv != NULL && mobile_array[cur_mobile].mn.current_adv->adv.fa_nai != NULL) {
00251                 /* previous FA NAI ext. */
00252                 if (mobile_array[cur_mobile].mn.prev_req_replied && mobile_array[cur_mobile].mn.last_req_FA_NAI->type != 0) {
00253                         n = GET_NAI_EXT_LEN(mobile_array[cur_mobile].mn.last_req_FA_NAI);
00254                         if (left < n)
00255                                 return -1;
00256                         mobile_array[cur_mobile].mn.last_req_FA_NAI->sub_type =
00257                                 htons(VENDOR_EXT_DYNAMICS_PREVIOUS_FA_NAI);
00258                         memcpy(pos + added, mobile_array[cur_mobile].mn.last_req_FA_NAI, n);
00259                         added += n;
00260                         left -= n;
00261                         DEBUG(DEBUG_MESSAGES, " * previous FA NAI (len=%i)\n",
00262                               n);
00263                 }
00264 
00265                 /* current FA NAI ext. */
00266                 n = GET_NAI_EXT_LEN(mobile_array[cur_mobile].mn.current_adv->adv.fa_nai);
00267                 memcpy(mobile_array[cur_mobile].mn.last_req_FA_NAI, mobile_array[cur_mobile].mn.current_adv->adv.fa_nai, n);
00268                 if (left < n)
00269                         return -1;
00270                 memcpy(pos + added, mobile_array[cur_mobile].mn.last_req_FA_NAI, n);
00271                 added += n;
00272                 left -= n;
00273                 DEBUG(DEBUG_MESSAGES, " * current FA NAI (len=%i)\n", n);
00274         }
00275 
00276         if (add_auth) {
00277                 if (left < sizeof(struct vendor_msg_auth) + MAX_SK_LEN)
00278                         return -1;
00279                 DEBUG(DEBUG_MESSAGES, " * sk_auth\n");
00280                 n = auth_add_vendor(
00281                         mobile_array[cur_mobile].config.auth_alg, mobile_array[cur_mobile].mn.session_key, mobile_array[cur_mobile].mn.session_key_len,
00282                         (unsigned char *) start,
00283                         (struct vendor_msg_auth *) (pos + added),
00284                         VENDOR_EXT_DYNAMICS_SK_AUTH, htonl(mobile_array[cur_mobile].config.spi));
00285                 added += n;
00286                 left -= n;
00287         }
00288 
00289         return added;
00290 }
00291 
00292 
00293 static int add_req_extensions(char *pos, int left, char *start,
00294                               int request_type, int use_reverse)
00295 {
00296         int use_dynamics_ext, n;
00297         struct fa_spi_entry *fa_spi = NULL;
00298         struct msg_key *mn_keyreq;
00299         struct challenge_ext *challenge = NULL;
00300         char *orig = pos;
00301         int add_mn_aaa_auth_ext = 0;
00302         int send_to_ha = 0;
00303 
00304         if (request_type == REG_DISC &&
00305             mobile_array[cur_mobile].mn.fa_addr.s_addr == mobile_array[cur_mobile].config.ha_ip_addr.s_addr)
00306                 send_to_ha = 1;
00307 
00308         if (mobile_array[cur_mobile].config.priv_ha > 0) {
00309                 struct priv_ha_ext *priv = (struct priv_ha_ext *) pos;
00310                 if (left < sizeof(struct priv_ha_ext))
00311                         return -1;
00312                 memset(priv, 0, sizeof(struct priv_ha_ext));
00313                 priv->type = VENDOR_EXT_TYPE2;
00314                 priv->length = sizeof(struct priv_ha_ext) - 2;
00315                 priv->vendor_id = htonl(VENDOR_ID_DYNAMICS);
00316                 priv->sub_type = htons(VENDOR_EXT_DYNAMICS_PRIV_HA);
00317                 priv->priv_ha = htonl(mobile_array[cur_mobile].config.priv_ha);
00318                 pos += GET_PRIV_HA_EXT_LEN(priv);
00319                 left -= GET_PRIV_HA_EXT_LEN(priv);
00320                 DEBUG(DEBUG_MESSAGES, " * priv_ha\n");
00321         }
00322 
00323         if (mobile_array[cur_mobile].config.mn_nai_len > 0) {
00324                 struct mn_nai_ext *nai;
00325                 if (left < sizeof(struct mn_nai_ext) + mobile_array[cur_mobile].config.mn_nai_len)
00326                         return -1;
00327                 nai = (struct mn_nai_ext *) pos;
00328                 nai->type = MN_NAI_EXT;
00329                 nai->length = mobile_array[cur_mobile].config.mn_nai_len;
00330                 memcpy(nai + 1, mobile_array[cur_mobile].config.mn_nai, mobile_array[cur_mobile].config.mn_nai_len);
00331                 pos += GET_MN_NAI_EXT_LEN(nai);
00332                 left -= GET_MN_NAI_EXT_LEN(nai);
00333                 DEBUG(DEBUG_MESSAGES, " * mn_nai\n");
00334         }
00335 
00336 #ifdef INCLUDE_IPAY
00337         if (mobile_array[cur_mobile].config.mn_nai_len == 0 && mobile_array[cur_mobile].mn.nai.nai != NULL) {
00338                 struct mn_nai_ext *nai;
00339                 if (left < sizeof(struct mn_nai_ext) + mobile_array[cur_mobile].mn.nai.len)
00340                         return -1;
00341                 nai = (struct mn_nai_ext *) pos;
00342                 nai->type = MN_NAI_EXT;
00343                 nai->length = mobile_array[cur_mobile].mn.nai.len;
00344                 memcpy(nai + 1, mobile_array[cur_mobile].mn.nai.nai, mobile_array[cur_mobile].mn.nai.len);
00345                 pos += GET_MN_NAI_EXT_LEN(nai);
00346                 left -= GET_MN_NAI_EXT_LEN(nai);
00347                 DEBUG(DEBUG_MESSAGES, " * mn_nai (Ipay)\n");
00348         }
00349 #endif
00350 
00351         /* add Dynamics extensions if the Foreign Agent advertised support for
00352          * them or if the registration is made directly to the Home Agent */
00353         use_dynamics_ext = mobile_array[cur_mobile].mn.fa_dynamics_ext.type != 0 ||
00354                 mobile_array[cur_mobile].mn.tunnel_mode == API_TUNNEL_FULL_HA;
00355 
00356         if (use_dynamics_ext) {
00357                 /* add mn_keyreq extension */
00358                 if (left < MIN_KEY_EXT_LEN)
00359                         return -1;
00360                 DEBUG(DEBUG_MESSAGES, " * mn_keyreq\n");
00361                 mn_keyreq = (struct msg_key *) pos;
00362                 init_key_extension(mn_keyreq, VENDOR_EXT_DYNAMICS_MN_KEYREQ,
00363                                    htonl(mobile_array[cur_mobile].config.spi), 0);
00364                 pos += GET_KEY_EXT_LEN(mn_keyreq);
00365                 left -= GET_KEY_EXT_LEN(mn_keyreq);
00366 
00367                 /* add HFA public key hash extension if the hash is available
00368                  * from the agent advertisement */
00369                 if (mobile_array[cur_mobile].mn.current_adv != NULL) {
00370                         struct msg_key *hashext =
00371                                 mobile_array[cur_mobile].mn.current_adv->adv.pubkey_hash;
00372                         if (hashext != NULL && hashext->type != 0) {
00373                                 if (left < GET_KEY_EXT_LEN(hashext))
00374                                         return -1;
00375                                 DEBUG(DEBUG_MESSAGES, " * pubkey_hash\n");
00376                                 memcpy(pos, hashext, GET_KEY_EXT_LEN(hashext));
00377                                 pos += GET_KEY_EXT_LEN(hashext);
00378                                 left -= GET_KEY_EXT_LEN(hashext);
00379                         }
00380                 }
00381         } else {
00382                 DEBUG(DEBUG_INFO, "FA did not advertise support for Dynamics "
00383                       "extensions - not using them\n");
00384         }
00385 
00386         if (mobile_array[cur_mobile].config.use_aaa &&
00387             mobile_array[cur_mobile].config.mn_ha_key_timestamp != 0 &&
00388             mobile_array[cur_mobile].config.mn_ha_key_lifetime != 0 &&
00389             mobile_array[cur_mobile].config.mn_ha_key_timestamp + mobile_array[cur_mobile].config.mn_ha_key_lifetime <
00390             time(NULL)) {
00391                 DEBUG(DEBUG_INFO, "Dynamic MN-HA security association (from "
00392                       "AAA) expired\n");
00393                 mobile_array[cur_mobile].config.shared_secret_len = -1;
00394         }
00395 
00396         if (mobile_array[cur_mobile].config.shared_secret_len >= 0) {
00397                 /* add MN->HA authentication extension */
00398                 if (left < sizeof(struct msg_auth) + MAX_SK_LEN)
00399                         return -1;
00400                 DEBUG(DEBUG_MESSAGES, " * mh_auth\n");
00401                 n = auth_add(mobile_array[cur_mobile].mn.use_auth_alg, mobile_array[cur_mobile].config.shared_secret,
00402                              mobile_array[cur_mobile].config.shared_secret_len, (unsigned char *) start,
00403                              (struct msg_auth *) pos, MH_AUTH,
00404                              htonl(mobile_array[cur_mobile].config.spi));
00405                 pos += n;
00406                 left -= n;
00407         }
00408 
00409         /* Add encapsulating delivery extension if MN decaps and reverse
00410          * tunnel is in use [RFC 2344, Chap. 3.3] */
00411         if (!mobile_array[cur_mobile].config.enable_fa_decapsulation && use_reverse) {
00412                 struct encaps_delivery_ext *edel =
00413                         (struct encaps_delivery_ext *) pos;
00414                 if (left < sizeof(struct encaps_delivery_ext))
00415                         return -1;
00416                 DEBUG(DEBUG_MESSAGES, " * encaps_delivery\n");
00417                 edel->type = ENCAPS_DELIVERY_EXT;
00418                 edel->length = 0;
00419                 pos += sizeof(struct encaps_delivery_ext);
00420                 left -= sizeof(struct encaps_delivery_ext);
00421         }
00422 
00423         /* add FA NAI extensions and session key based MN->FA authentication
00424          * if Dynamics extensions are used and the session key is available
00425          * and this is not a reregistration */
00426         if (use_dynamics_ext && mobile_array[cur_mobile].mn.session_key != NULL &&
00427             request_type != REG_REREG) {
00428                 n = add_localized_reg_extensions(pos, left, start);
00429                 if (n < 0)
00430                         return -1;
00431                 pos += n;
00432                 left -= n;
00433         } else if (mobile_array[cur_mobile].mn.current_adv != NULL &&
00434                    mobile_array[cur_mobile].mn.current_adv->adv.fa_nai != NULL) {
00435                 /* current FA NAI ext. */
00436                 memcpy(mobile_array[cur_mobile].mn.last_req_FA_NAI, mobile_array[cur_mobile].mn.current_adv->adv.fa_nai,
00437                        MAX_FA_NAI_LEN);
00438                 n = GET_NAI_EXT_LEN(mobile_array[cur_mobile].mn.last_req_FA_NAI);
00439                 if (left < n)
00440                         return -1;
00441                 memcpy(pos, mobile_array[cur_mobile].mn.last_req_FA_NAI, n);
00442                 pos += n;
00443                 left -= n;
00444                 DEBUG(DEBUG_MESSAGES, " * current FA NAI (len=%i)\n", n);
00445         }
00446 
00447         /* if the agent advertisement from the FA has a Challenge extension,
00448          * copy it to the registration request or if the previous registration
00449          * reply had a more recent Challenge ext, use it */
00450         /* FIX: MN must not use the same challenge again, so if no new
00451          * challenge is available, it is no use sending this registration
00452          * without first acquiring a new challenge fron an agent advertisement.
00453          * MN could send an agent soliciation in that case. Now the request
00454          * will be denied by FA and MN might get a new challenge from that
00455          * denial reply. */
00456         if (mobile_array[cur_mobile].mn.last_challenge_ext != NULL &&
00457             (mobile_array[cur_mobile].mn.current_adv == NULL ||
00458              cmp_timeval(&mobile_array[cur_mobile].mn.current_adv->last, &mobile_array[cur_mobile].mn.last_challenge_time) < 0))
00459         {
00460                 DEBUG(DEBUG_INFO, "Using challenge from last reg. reply\n");
00461                 challenge = mobile_array[cur_mobile].mn.last_challenge_ext;
00462         } else if (mobile_array[cur_mobile].mn.current_adv != NULL &&
00463                    mobile_array[cur_mobile].mn.current_adv->adv.challenge != NULL) {
00464                 DEBUG(DEBUG_INFO, "Using challenge from last agentadv\n");
00465                 challenge = mobile_array[cur_mobile].mn.current_adv->adv.challenge;
00466         } else
00467                 challenge = NULL;
00468 
00469         if (!send_to_ha)
00470                 fa_spi = get_fa_spi(0, mobile_array[cur_mobile].mn.fa_addr);
00471 
00472         if (challenge != NULL && (fa_spi != NULL || mobile_array[cur_mobile].config.use_aaa)) {
00473                 n = GET_CHALLENGE_EXT_LEN(challenge);
00474                 DEBUG(DEBUG_MESSAGES, " * challenge (len=%i)\n", n);
00475                 if (left < n)
00476                         return -1;
00477                 memcpy(pos, challenge, n);
00478                 challenge = (struct challenge_ext *) pos;
00479                 challenge->type = MN_FA_CHALLENGE_EXT;
00480                 pos += n;
00481                 left -= n;
00482                 add_mn_aaa_auth_ext = 1;
00483         }
00484 
00485         /* add shared secret based MN->FA authentication if the security
00486          * association is configured */
00487         if (!send_to_ha && fa_spi != NULL && !mobile_array[cur_mobile].mn.aaa_rekey) {
00488                 if (left < sizeof(struct msg_auth) + MAX_SK_LEN)
00489                         return -1;
00490                 DEBUG(DEBUG_MESSAGES, " * mf_auth\n");
00491                 n = auth_add(fa_spi->alg, fa_spi->shared_secret,
00492                              fa_spi->shared_secret_len,
00493                              (unsigned char *) start, (struct msg_auth *) pos,
00494                              MF_AUTH, htonl(fa_spi->spi));
00495                 pos += n;
00496                 left -= n;
00497                 add_mn_aaa_auth_ext = 0;
00498         } else if (!send_to_ha && mobile_array[cur_mobile].config.use_aaa) {
00499                 struct generalized_mn_fa_key_req_ext *keyreq;
00500 
00501                 add_mn_aaa_auth_ext = 1;
00502 
00503                 /* add MN-FA key req. from AAA */
00504                 keyreq = (struct generalized_mn_fa_key_req_ext *) pos;
00505                 if (left < sizeof(*keyreq))
00506                         return -1;
00507                 DEBUG(DEBUG_MESSAGES, " * MN-FA Key Req from AAA\n");
00508                 keyreq->type = GENERALIZED_MN_FA_KEY_REQ_EXT;
00509                 keyreq->subtype = GEN_MN_FA_KEY_REQ_FROM_AAA;
00510                 keyreq->length = htons(4);
00511                 /* FIX: mn_spi is the SPI that MN will assign for the security
00512                  * association; this may need to be uniquely selected for some
00513                  * cases(?) */
00514                 keyreq->mn_spi = htonl(1000);
00515                 pos += GET_GEN_MN_FA_KEY_REQ_EXT_LEN(keyreq);
00516                 left -= GET_GEN_MN_FA_KEY_REQ_EXT_LEN(keyreq);
00517         }
00518 
00519         if ((mobile_array[cur_mobile].config.shared_secret_len < 0 || mobile_array[cur_mobile].mn.aaa_rekey) &&
00520             mobile_array[cur_mobile].config.use_aaa) {
00521                 struct generalized_mn_ha_key_req_ext *keyreq;
00522 
00523                 add_mn_aaa_auth_ext = 1;
00524 
00525                 /* add MN-HA key req. from AAA */
00526                 keyreq = (struct generalized_mn_ha_key_req_ext *) pos;
00527                 if (left < sizeof(*keyreq))
00528                         return -1;
00529                 DEBUG(DEBUG_MESSAGES, " * MN-HA Key Req from AAA\n");
00530                 keyreq->type = GENERALIZED_MN_HA_KEY_REQ_EXT;
00531                 keyreq->subtype = GEN_MN_HA_KEY_REQ_FROM_AAA;
00532                 keyreq->length = htons(4);
00533                 /* FIX: mn_spi is the SPI that MN will assign for the security
00534                  * association; this may need to be uniquely selected for some
00535                  * cases(?) */
00536                 keyreq->mn_spi = htonl(1000);
00537                 pos += GET_GEN_MN_FA_KEY_REQ_EXT_LEN(keyreq);
00538                 left -= GET_GEN_MN_FA_KEY_REQ_EXT_LEN(keyreq);
00539         }
00540 
00541         if (add_mn_aaa_auth_ext && mobile_array[cur_mobile].config.use_aaa) {
00542                 /* add MN-AAA authentication extension */
00543                 if (left < sizeof(struct generalized_auth_ext) + MAX_SK_LEN)
00544                         return -1;
00545                 DEBUG(DEBUG_MESSAGES, " * gen_auth_ext(MN-AAA)\n");
00546                 n = auth_add_gen(mobile_array[cur_mobile].config.mn_aaa_auth_alg,
00547                                  mobile_array[cur_mobile].config.mn_aaa_shared_secret,
00548                                  mobile_array[cur_mobile].config.mn_aaa_shared_secret_len,
00549                                  (unsigned char *) start,
00550                                  challenge != NULL ?
00551                                  MSG_CHALLENGE_EXT_DATA(challenge) : NULL,
00552                                  challenge != NULL ?
00553                                  GET_CHALLENGE_LEN(challenge) : 0,
00554                                  (struct generalized_auth_ext *) pos,
00555                                  GENERALIZED_AUTH_MN_AAA,
00556                                  htonl(mobile_array[cur_mobile].config.mn_aaa_spi));
00557                 pos += n;
00558                 left -= n;
00559         }
00560 
00561 
00562         mobile_array[cur_mobile].mn.prev_req_replied = 0;
00563 
00564         return (int) (pos - orig);
00565 }
00566 
00567 /* send_registration:
00568  * @request_type: 
00569  *    REG_DISC    - deregistration
00570  *    REG_CONNECT - normal connection request
00571  *    REG_REREG   - reregistration (do not send sk_auth extension
00572  *                  and ask full time)
00573  *
00574  * 
00575  *
00576  * Send registration message.
00577  * 
00578  * Returns: 0 on success, -1 on error.
00579  */
00580 int send_registration(int request_type)
00581 {
00582         char sendbuf[MAXMSG];
00583         char *pos; /* pointer to next byte to write in sendbuf */
00584         int n, len;
00585         struct sockaddr_in addr;
00586         int use_reverse;
00587         struct msg_extensions ext;
00588 
00589         if (MAXMSG < (sizeof(struct reg_req) +
00590                       2 * (sizeof(struct msg_auth) + 16))) {
00591                 DEBUG(DEBUG_INFO, "MN: send_reg: too small send buffer!");
00592 
00593                 return -1;
00594         }
00595 
00596         use_reverse = mobile_array[cur_mobile].config.tunneling_mode == TUNMODE_AUTO_REVERSE ||
00597                 mobile_array[cur_mobile].config.tunneling_mode == TUNMODE_REVERSE;
00598 
00599         if (mobile_array[cur_mobile].mn.current_adv != NULL) {
00600                 if (mobile_array[cur_mobile].mn.current_adv->addr.s_addr != mobile_array[cur_mobile].mn.fa_addr.s_addr) {
00601                         DEBUG(DEBUG_INFO, "fa_addr=%s != ",
00602                               inet_ntoa(mobile_array[cur_mobile].mn.fa_addr));
00603                         DEBUG(DEBUG_INFO, "current_adv->addr=%s\n",
00604                               inet_ntoa(mobile_array[cur_mobile].mn.current_adv->addr));
00605                 }
00606 
00607                 DEBUG(DEBUG_INFO, "Setting in_use=%i for FA %s (send reg)\n",
00608                       request_type == REG_DISC ? 0 : 1,
00609                       inet_ntoa(mobile_array[cur_mobile].mn.current_adv->addr));
00610                 mobile_array[cur_mobile].mn.current_adv->in_use = request_type == REG_DISC ? 0 : 1;
00611                 if (mobile_array[cur_mobile].config.tunneling_mode == TUNMODE_AUTO_REVERSE &&
00612                     (ntohs(mobile_array[cur_mobile].mn.current_adv->adv.ext->opts) &
00613                      AGENT_ADV_BIDIR_TUNNELING) == 0)
00614                         use_reverse = 0;
00615                 if (mobile_array[cur_mobile].config.tunneling_mode == TUNMODE_AUTO_TRIANGLE &&
00616                     mobile_array[cur_mobile].mn.current_adv->adv.own_ext != NULL &&
00617                     (mobile_array[cur_mobile].mn.current_adv->adv.own_ext->opts &
00618                      AGENT_ADV_OWN_TRIANGLE_TUNNELING) == 0)
00619                         use_reverse = 1;
00620         } else {
00621                 DEBUG(DEBUG_INFO,
00622                       "send_registration: current_adv == NULL!?\n");
00623         }
00624 
00625         if ((use_reverse && mobile_array[cur_mobile].config.tunneling_mode == TUNMODE_TRIANGLE) ||
00626             (!use_reverse && mobile_array[cur_mobile].config.tunneling_mode == TUNMODE_REVERSE)) {
00627                 DEBUG(DEBUG_INFO, "FA does not support wanted tunneling mode -"
00628                       " aborting registration\n");
00629                 if (mobile_array[cur_mobile].mn.current_adv != NULL)
00630                         mobile_array[cur_mobile].mn.current_adv->reg_failed = 1;
00631                 return -1;
00632         }
00633 
00634         if (use_reverse)
00635                 DEBUG(DEBUG_MESSAGES, "Requesting reverse tunneling\n");
00636 
00637         pos = sendbuf;
00638 
00639         DEBUG(DEBUG_MESSAGES, "Sending registration message:\n * header\n");
00640         n = fill_req_header(pos, request_type, use_reverse);
00641         if (n < 0) return -1;
00642         pos += n;
00643 
00644         n = add_req_extensions(pos, MAXMSG - n, sendbuf, request_type,
00645                                use_reverse);
00646         if (n < 0) {
00647                 LOG2(LOG_ERR, "Registration request buffer overflow - unable"
00648                      " to send the request\n");
00649                 return -1;
00650         }
00651         pos += n;
00652 
00653         len = (int) (pos - sendbuf);
00654         assert(len <= MAXMSG);
00655 
00656         /* call parse_msg() to parse the message in order to get the details
00657          * of the sent message into debug output; in addition, this validates
00658          * the format of the request */
00659         if (parse_msg(sendbuf, len, &ext) != 0) {
00660                 DEBUG(DEBUG_INFO, "WARNING! Own registration request was not "
00661                       "valid!\n");
00662         }
00663 
00664         /* add ARP entry, if not already added */
00665         if (mobile_array[cur_mobile].mn.current_adv != NULL &&
00666             mobile_array[cur_mobile].mn.current_adv->adv_type == MN_ADV_TYPE_FA &&
00667             !mobile_array[cur_mobile].mn.current_adv->arpentry) {
00668                 struct sockaddr hwaddr;
00669                 DEBUG(DEBUG_INFO, "Adding ARP entry for FA\n");
00670                 memset(&hwaddr, 0, sizeof(hwaddr));
00671                 hwaddr.sa_family = ARPHRD_ETHER;
00672 #ifdef DYN_TARGET_LINUX
00673                 memcpy(hwaddr.sa_data, mobile_array[cur_mobile].mn.current_adv->adv.from.sll_addr,
00674                        mobile_array[cur_mobile].mn.current_adv->adv.from.sll_halen);
00675 #else
00676                 memcpy(hwaddr.sa_data, mobile_array[cur_mobile].mn.current_adv->adv.eth->h_source,
00677                        ETH_ALEN);
00678 #endif
00679                 if (arp_add_permanent_item(mobile_array[cur_mobile].mn.current_adv->addr,
00680                                            mobile_array[cur_mobile].mn.current_adv->ifname,
00681                                            &hwaddr) < 0) {
00682                         LOG2(LOG_WARNING, "arp_add_permanent_item(%s, %s, %s) "
00683                              "failed\n", inet_ntoa(mobile_array[cur_mobile].mn.current_adv->addr),
00684                              mobile_array[cur_mobile].mn.current_adv->ifname,
00685                              ether_hwtoa((unsigned char *)hwaddr.sa_data));
00686                 }
00687                 mobile_array[cur_mobile].mn.current_adv->arpentry = 1;
00688         }
00689 
00690         /* add host route to FA, if not already added */
00691         if (mobile_array[cur_mobile].config.enable_fa_decapsulation &&
00692             mobile_array[cur_mobile].mn.current_adv != NULL &&
00693             mobile_array[cur_mobile].mn.current_adv->adv_type == MN_ADV_TYPE_FA &&
00694             !mobile_array[cur_mobile].mn.current_adv->routeentry) {
00695                 DEBUG(DEBUG_INFO, "Adding routing entry for FA\n");
00696                 add_fa_host_route(mobile_array[cur_mobile].mn.current_adv->ifname, mobile_array[cur_mobile].mn.agentadv,
00697                                   mobile_array[cur_mobile].mn.current_adv->ifindex, mobile_array[cur_mobile].mn.fa_addr);
00698         }
00699 
00700         /* send the message */
00701         memset(&addr, 0, sizeof(addr));
00702         addr.sin_family = AF_INET;
00703        // addr.sin_addr.s_addr = mobile_array[cur_mobile].mn.fa_addr.s_addr;
00704          //addr.sin_addr.s_addr = inet_addr("172.16.0.2");
00705         addr.sin_addr.s_addr=mobile_array[cur_mobile].config.ha_ip_addr.s_addr;
00706         addr.sin_port = htons(mobile_array[cur_mobile].config.udp_port);
00707         DEBUG(DEBUG_MESSAGES, "sending registration request to %s:%i, "
00708               "type=%i\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port),
00709               request_type);
00710 
00711         gettimeofday(&mobile_array[cur_mobile].mn.last_reg_send_time, NULL);
00712         DEBUG(DEBUG_TIMERS, "last_reg_send_time=%li.%06li (FA=%s)\n",
00713               mobile_array[cur_mobile].mn.last_reg_send_time.tv_sec,
00714               mobile_array[cur_mobile].mn.last_reg_send_time.tv_usec,
00715               inet_ntoa(addr.sin_addr));
00716 
00717         
00718 
00719 
00720         n = sendto(mobile_array[cur_mobile].mn.registration_socket, sendbuf, len, 0,
00721                    (struct sockaddr *) &addr, sizeof(addr));
00722         if (n == len) {
00723                 /* store id for reply */
00724                 mobile_array[cur_mobile].mn.registration_id[0] =
00725                         ntohl(((struct reg_req *)sendbuf)->id[0]);
00726                 mobile_array[cur_mobile].mn.registration_id[1] =
00727                         ntohl(((struct reg_req *)sendbuf)->id[1]);
00728                 /* set registration time */
00729                 gettimeofday(&timers[TIMER_REQUEST], NULL);
00730                 mobile_array[cur_mobile].mn.last_request_sent = timers[TIMER_REQUEST].tv_sec;
00731                 return 0;
00732         } else {
00733                 LOG2(LOG_ERR, "send_reg - sendto: %s\n", strerror(errno));
00734                 return -1;
00735         }
00736 }
00737 
00738 
00739 static void show_key_dump(const char *title, const unsigned char *key,
00740                           int keylen)
00741 {
00742         int i;
00743 
00744         DEBUG(DEBUG_INFO, "%s: ", title);
00745         for (i = 0; i < keylen; i++)
00746                 DEBUG(DEBUG_INFO, "%02x", key[i]);
00747         DEBUG(DEBUG_INFO, "\n");
00748 }
00749 
00759 static int handle_reply_aaa(struct msg_extensions *ext, struct in_addr addr)
00760 {
00761         unsigned char *nodeaddr;
00762         unsigned int nodeaddrlen;
00763         unsigned char fa_secret[MAXSHAREDSECRETLEN];
00764         int fa_secret_len;
00765         unsigned char ha_secret[MAXSHAREDSECRETLEN];
00766         int ha_secret_len;
00767         struct mn_fa_key_material_from_aaa *fa_key = NULL;
00768         struct mn_ha_key_material_from_aaa *ha_key = NULL;
00769 
00770         if (mobile_array[cur_mobile].config.mn_home_ip_addr.s_addr == 0 &&
00771             mobile_array[cur_mobile].config.mn_nai_len > 0) {
00772                 nodeaddr = mobile_array[cur_mobile].config.mn_nai;
00773                 nodeaddrlen = mobile_array[cur_mobile].config.mn_nai_len;
00774         } else {
00775                 nodeaddr = (unsigned char *) &mobile_array[cur_mobile].config.mn_home_ip_addr;
00776                 nodeaddrlen = 4;
00777         }
00778 
00779         if (!mobile_array[cur_mobile].config.use_aaa) {
00780                 DEBUG(DEBUG_INFO, "Registration reply has key material from "
00781                       "AAA, but AAA is not configured; ignoring extension\n");
00782                 ext->mn_fa_key_material_aaa = NULL;
00783                 ext->mn_ha_key_material_aaa = NULL;
00784                 return 1;
00785         }
00786 
00787         if (ext->mn_fa_key_material_aaa) {
00788                 fa_key = (struct mn_fa_key_material_from_aaa *)
00789                         (ext->mn_fa_key_material_aaa + 1);
00790 
00791                 if (ext->mf_auth == NULL ||
00792                     !auth_is_protected(ext->mn_fa_key_material_aaa,
00793                                        ext->mf_auth)) {
00794                         LOG2(LOG_ALERT, "MN-FA auth. ext. does not protect "
00795                              "MN-FA key material from AAA\n");
00796                         return 0;
00797                 }
00798 
00799                 /* generate MN-FA key from key material */
00800                 fa_secret_len = MAXSHAREDSECRETLEN;
00801                 if (auth_generate_key(
00802                             mobile_array[cur_mobile].config.mn_aaa_keygen_alg,
00803                             mobile_array[cur_mobile].config.mn_aaa_shared_secret,
00804                             mobile_array[cur_mobile].config.mn_aaa_shared_secret_len,
00805                             (unsigned char *) (fa_key + 1),
00806                             GET_GEN_MN_FA_KEY_REP_LEN(
00807                                     ext->mn_fa_key_material_aaa) -
00808                             sizeof(struct mn_fa_key_material_from_aaa),
00809                             nodeaddr, nodeaddrlen,
00810                             fa_secret, &fa_secret_len)) {
00811                         LOG2(LOG_ALERT, "MN-FA key generation with material "
00812                              "from AAA failed\n");
00813                         return 0;
00814                 }
00815                 show_key_dump("MN-FA key", fa_secret, fa_secret_len);
00816 
00817                 /* check that MN-FA auth ext is valid before accepting the
00818                  * key */
00819                 if (!auth_check(auth_aaa_key_alg_id_to_dynamics(ntohs(
00820                         fa_key->alg_id)),
00821                                 fa_secret, fa_secret_len,
00822                                 (unsigned char *) ext->rep, ext->mf_auth)) {
00823                         LOG2(LOG_ALERT, "MN-FA key from AAA does not match "
00824                              "with MN-FA auth. ext.\n");
00825                         return 0;
00826                 }
00827         }
00828 
00829         if (ext->mn_ha_key_material_aaa) {
00830                 ha_key = (struct mn_ha_key_material_from_aaa *)
00831                         (ext->mn_ha_key_material_aaa + 1);
00832 
00833                 if (ext->mh_auth == NULL ||
00834                     !auth_is_protected(ext->mn_ha_key_material_aaa,
00835                                        ext->mh_auth)) {
00836                         LOG2(LOG_ALERT, "MN-HA auth. ext. does not protect "
00837                              "MN-HA key material from AAA\n");
00838                         return 0;
00839                 }
00840 
00841                 /* generate MN-HA key from key material */
00842                 ha_secret_len = MAXSHAREDSECRETLEN;
00843                 if (auth_generate_key(
00844                             mobile_array[cur_mobile].config.mn_aaa_keygen_alg,
00845                             mobile_array[cur_mobile].config.mn_aaa_shared_secret,
00846                             mobile_array[cur_mobile].config.mn_aaa_shared_secret_len,
00847                             (unsigned char *) (ha_key + 1),
00848                             GET_GEN_MN_HA_KEY_REP_LEN(
00849                                     ext->mn_ha_key_material_aaa) -
00850                             sizeof(struct mn_ha_key_material_from_aaa),
00851                             nodeaddr, nodeaddrlen,
00852                             ha_secret, &ha_secret_len)) {
00853                         LOG2(LOG_ALERT, "MN-HA key generation with material "
00854                              "from AAA failed\n");
00855                         return 0;
00856                 }
00857                 show_key_dump("MN-HA key", ha_secret, ha_secret_len);
00858 
00859                 /* check that MN-HA auth ext is valid before accepting the
00860                  * key */
00861                 if (!auth_check(auth_aaa_key_alg_id_to_dynamics(
00862                         ntohs(ha_key->alg_id)),
00863                                 ha_secret, ha_secret_len,
00864                                 (unsigned char *) ext->rep, ext->mh_auth)) {
00865                         LOG2(LOG_ALERT, "MN-HA key from AAA does not match "
00866                              "with MN-HA auth. ext.\n");
00867                         return 0;
00868                 }
00869         }
00870 
00871 
00872 
00873         /* Generated keys matched with authentication extensions - add new
00874          * dynamic security associations */
00875 
00876         if (ext->mn_fa_key_material_aaa) {
00877                 struct fa_spi_entry *spi;
00878 
00879                 spi = malloc(sizeof(struct fa_spi_entry));
00880                 if (spi == NULL) {
00881                         DEBUG(DEBUG_INFO, "Could not allocate memory for new "
00882                               "FA security association\n");
00883                         return 0;
00884                 }
00885                 memset(spi, 0, sizeof(struct fa_spi_entry));
00886                 list_init_node(&spi->node);
00887 
00888                 spi->spi = ntohl(fa_key->fa_spi);
00889                 spi->addr.s_addr = addr.s_addr;
00890                 spi->alg =
00891                         auth_aaa_key_alg_id_to_dynamics(ntohs(fa_key->alg_id));
00892                 time(&spi->created);
00893                 spi->lifetime = ntohl(fa_key->lifetime);
00894                 memcpy(spi->shared_secret, fa_secret, sizeof(fa_secret));
00895                 spi->shared_secret_len = fa_secret_len;
00896                 add_fa_spi(spi, 1);
00897         }
00898 
00899         if (ext->mn_ha_key_material_aaa) {
00900                 mobile_array[cur_mobile].config.spi = ntohl(ha_key->ha_spi);
00901                 mobile_array[cur_mobile].mn.use_auth_alg = mobile_array[cur_mobile].config.auth_alg =
00902                         auth_aaa_key_alg_id_to_dynamics(ntohs(ha_key->alg_id));
00903                 mobile_array[cur_mobile].config.replay_meth = auth_aaa_key_replay_to_dynamics(
00904                         ntohs(ha_key->replay_method));
00905                 memcpy(mobile_array[cur_mobile].config.shared_secret, ha_secret, sizeof(ha_secret));
00906                 mobile_array[cur_mobile].config.shared_secret_len = ha_secret_len;
00907                 time(&mobile_array[cur_mobile].config.mn_ha_key_timestamp);
00908                 mobile_array[cur_mobile].config.mn_ha_key_lifetime =
00909                         ntohl(ext->mn_ha_key_material_aaa->lifetime);
00910         }
00911 
00912         mobile_array[cur_mobile].mn.aaa_rekey = 0;
00913 
00914         return 1;
00915 }
00916 
00917 
00918 /*
00919  * Check if ext contains valid registration reply.
00920  * correct reply should have id[1] same as in request.
00921  * Return nonzero if it's valid, zero otherwise.
00922  */
00923 static int is_valid_reply(struct msg_extensions *ext, struct sockaddr_in addr)
00924 {
00925         int auth_alg;
00926         struct fa_spi_entry *fa_spi;
00927 
00928         ASSERT(ext != NULL);
00929 
00930         /* verify fields */
00931         if (ext->rep == NULL || ext->rep->type != REG_REP) {
00932                 LOG2(LOG_WARNING, "Received message from %s:%i was not a "
00933                      "registration reply\n",
00934                      inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
00935                 return 0;
00936         }
00937 
00938 #ifndef MN_ENABLE_VALIDATION
00939         DEBUG(DEBUG_INFO, "MN - no message validation in use\n");
00940         return 1;
00941 #else
00942 
00943         if ((ext->mn_fa_key_material_aaa != NULL ||
00944              ext->mn_ha_key_material_aaa != NULL) &&
00945             handle_reply_aaa(ext, addr.sin_addr) != 1) {
00946                 LOG2(LOG_ALERT, "Registration reply validation failed for AAA "
00947                         "related data - dropping reply\n");
00948                 return 0;
00949         }
00950 
00951         /* verify mac */
00952         if (ext->mh_auth != NULL) {
00953                 if (mobile_array[cur_mobile].config.shared_secret_len < 0) {
00954                         LOG2(LOG_ALERT, "MN-HA in reply, but security "
00955                              "association does not exists yet\n");
00956                         return 0;
00957                 }
00958                 if (!auth_check(mobile_array[cur_mobile].mn.use_auth_alg, mobile_array[cur_mobile].config.shared_secret,
00959                                 mobile_array[cur_mobile].config.shared_secret_len,
00960                                 (unsigned char *) ext->rep, ext->mh_auth)) {
00961                         if (mobile_array[cur_mobile].mn.use_auth_alg == AUTH_ALG_MD5)
00962                                 auth_alg = AUTH_ALG_MD5_RFC2002;
00963                         else if (mobile_array[cur_mobile].mn.use_auth_alg == AUTH_ALG_MD5_RFC2002)
00964                                 auth_alg = AUTH_ALG_MD5;
00965                         else
00966                                 auth_alg = 0;
00967                         if (auth_alg == 0 ||
00968                             !auth_check(auth_alg, mobile_array[cur_mobile].config.shared_secret,
00969                                         mobile_array[cur_mobile].config.shared_secret_len,
00970                                         (unsigned char *) ext->rep,
00971                                         ext->mh_auth)) {
00972                                 LOG2(LOG_ALERT,
00973                                      "Incorrect HA->MN authentication "
00974                                      "extension received in the reply\n");
00975                                 if (mobile_array[cur_mobile].config.use_aaa)
00976                                         mobile_array[cur_mobile].mn.aaa_rekey = 1;
00977                                 return 0;
00978                         } else {
00979                                 /* non-standard authentication method used */
00980                                 DEBUG(DEBUG_MESSAGES,
00981                                       "Non-standard MAC calculation detected "
00982                                       "- trying to use the same method\n");
00983                                 mobile_array[cur_mobile].mn.use_auth_alg = auth_alg;
00984                                 return 0;
00985                         }
00986                 }
00987         } else if (ext->sk_auth != NULL && mobile_array[cur_mobile].mn.session_key_len > 0) {
00988                 if (!auth_check_vendor(mobile_array[cur_mobile].config.auth_alg, mobile_array[cur_mobile].mn.session_key,
00989                                        mobile_array[cur_mobile].mn.session_key_len,
00990                                        (unsigned char *) ext->rep,
00991                                        ext->sk_auth)) {
00992                         LOG2(LOG_ALERT, "Incorrect session key based "
00993                              "authentication extension in the reply.\n");
00994                         return 0;
00995                 }
00996                 /* FAs cannot send session_keys */
00997                 if (ext->mn_keyrep != NULL) {
00998                         DEBUG(DEBUG_MESSAGES, "Registration reply from FA "
00999                               "contained mn_keyrep extension - dropped it\n");
01000                         /* Just clear the session key to prevent FAs from
01001                          * sending them us. */
01002                         ext->mn_keyrep = NULL;
01003                 }
01004         } else if (ext->rep->code < 64 || ext->rep->code > 127) {
01005                 /* codes 64 .. 127 are for Foreign Agent denial; only require
01006                  * authentication extension in messages that are from the
01007                  * Home Agent */
01008                 LOG2(LOG_ALERT, "No authentication in the reply\n");
01009                 if (mobile_array[cur_mobile].config.use_aaa)
01010                         mobile_array[cur_mobile].mn.aaa_rekey = 1;
01011                 return 0;
01012         }
01013 
01014         /* check the possible mf_auth */
01015         fa_spi = get_fa_spi(0, addr.sin_addr);
01016         if (ext->rep->code == REGREP_MN_FAILED_AUTH_FA && mobile_array[cur_mobile].config.use_aaa &&
01017             fa_spi != NULL && fa_spi->created != 0) {
01018                 DEBUG(DEBUG_INFO, "FA reported incorrect authentication - "
01019                       "trying to create a new security association\n");
01020                 remove_fa_spi(fa_spi);
01021                 free(fa_spi);
01022                 fa_spi = NULL;
01023                 mobile_array[cur_mobile].mn.try_to_fix_sec_assoc = 1;
01024         }
01025 
01026         if (fa_spi != NULL) {
01027                 if (ext->mf_auth == NULL) {
01028                         LOG2(LOG_ALERT, "No mf_auth in the reply even though "
01029                              "there is a security association with the FA.\n");
01030                         return 0;
01031                 } else if (!auth_check(fa_spi->alg, fa_spi->shared_secret,
01032                                        fa_spi->shared_secret_len,
01033                                        (unsigned char *) ext->rep,
01034                                        ext->mf_auth)) {
01035                         LOG2(LOG_ALERT, "Incorrect FA->MN authentication "
01036                              "extension received the reply\n");
01037                         return 0;
01038                 }
01039         } else if (ext->mf_auth != NULL && !mobile_array[cur_mobile].mn.try_to_fix_sec_assoc) {
01040                 LOG2(LOG_ALERT, "Reply has an MN-FA auth. ext., but there is "
01041                      "no security association with the FA.\n");
01042                 return 0;
01043         }
01044 
01045         /* verify id */
01046         if (ntohl(ext->rep->id[1]) != mobile_array[cur_mobile].mn.registration_id[1]) {
01047                 LOG2(LOG_ALERT,
01048                      "Wrong id field in the reply (was %08x, "
01049                      "expected %08x)\n",
01050                      ext->rep->id[1], (u32) htonl(mobile_array[cur_mobile].mn.registration_id[1]));
01051                 return 0;
01052         }
01053 
01054 
01055         if (ntohs(ext->rep->lifetime) > 0 &&
01056             IS_REGREP_ACCEPTED(ext->rep->code) &&
01057             mobile_array[cur_mobile].config.ha_ip_addr.s_addr == 0) {
01058                 DEBUG(DEBUG_INFO, "Discovered HA address from reply: %s\n",
01059                       inet_ntoa(ext->rep->ha_addr));
01060                 mobile_array[cur_mobile].config.ha_ip_addr.s_addr = ext->rep->ha_addr.s_addr;
01061         }
01062 
01063         if (ntohs(ext->rep->lifetime) > 0 &&
01064             IS_REGREP_ACCEPTED(ext->rep->code) &&
01065             mobile_array[cur_mobile].config.mn_home_ip_addr.s_addr == 0) {
01066                 DEBUG(DEBUG_INFO, "Discovered MN home address from "
01067                       "reply: %s\n", inet_ntoa(ext->rep->home_addr));
01068                 mobile_array[cur_mobile].mn.local_addr.s_addr =
01069                         mobile_array[cur_mobile].config.mn_home_ip_addr.s_addr =
01070                         ext->rep->home_addr.s_addr;
01071                 if (mobile_array[cur_mobile].mn.current_adv != NULL &&
01072                     dyn_ip_iface_address(mobile_array[cur_mobile].mn.current_adv->ifindex,
01073                                          &mobile_array[cur_mobile].config.mn_home_ip_addr) != 1) {
01074                         DEBUG(DEBUG_INFO, "Adding assigned home address to the"
01075                               " interface\n");
01076                         if (dyn_ip_addr_add(mobile_array[cur_mobile].mn.current_adv->ifname,
01077                                             mobile_array[cur_mobile].config.mn_home_ip_addr) == 0) {
01078                                 mobile_array[cur_mobile].mn.dynamic_home_addr.s_addr =
01079                                         mobile_array[cur_mobile].config.mn_home_ip_addr.s_addr;
01080                                 memcpy(mobile_array[cur_mobile].mn.dynamic_home_addr_dev,
01081                                        mobile_array[cur_mobile].mn.current_adv->ifname, IFNAMSIZ);
01082                         } else
01083                                 DEBUG(DEBUG_INFO, "dyn_ip_addr_add failed\n");
01084                 }
01085         }
01086 
01087 
01088         /* don't accept any further messages with same id */
01089         mobile_array[cur_mobile].mn.registration_id[1]++;
01090 
01091         return 1;
01092 #endif
01093 }
01094 
01095 
01096 /* Handle session key extension. Decrypt and copy to session_key */
01097 static void handle_key_ext(struct reg_rep *rep, struct msg_key *key)
01098 {
01099         ASSERT(rep != NULL && key != NULL);
01100         DEBUG(DEBUG_MESSAGES, "mobile-home key extension received\n");
01101         /* If SPIs are different, something went wrong and we should
01102          * send another registration request to obtain session key. */
01103 
01104         if (ntohl(key->spi) != mobile_array[cur_mobile].config.spi) {
01105                 LOG2(LOG_WARNING, "Wrong SPI in the key reply extension.\n");
01106                 return;
01107         }
01108 
01109         /* Extract new session key */
01110         if (mobile_array[cur_mobile].mn.session_key) free(mobile_array[cur_mobile].mn.session_key);
01111         mobile_array[cur_mobile].mn.session_key = auth_decrypt(mobile_array[cur_mobile].config.auth_alg, mobile_array[cur_mobile].config.shared_secret,
01112                                    mobile_array[cur_mobile].config.shared_secret_len, key, rep,
01113                                    (int *) &mobile_array[cur_mobile].mn.session_key_len);
01114         if (mobile_array[cur_mobile].mn.session_key == NULL) {
01115                 LOG2(LOG_ERR,
01116                        "handle_key_ext: session key decryption failed\n");
01117                 mobile_array[cur_mobile].mn.session_key_len = 0;
01118                 return;
01119         }
01120 
01121         show_key_dump("Session key", mobile_array[cur_mobile].mn.session_key, mobile_array[cur_mobile].mn.session_key_len);
01122 }
01123 
01124 
01125 /* Handle registration accepting registration reply */
01126 static void handle_reg_accept(struct msg_extensions *ext)
01127 {
01128 #ifdef MN_LOCUPD_PROFILER
01129         char tmp[30];
01130 #endif
01131 
01132         ASSERT(ext != NULL && ext->rep != NULL);
01133 
01134         /* Connection succeeded. It's ok to monitor agent adv. expiring */
01135         mobile_array[cur_mobile].mn.expire_check = 1;
01136 
01137         if (mobile_array[cur_mobile].mn.current_adv != NULL) {
01138                 /* reset retry wait time for next registration */
01139                 DEBUG(DEBUG_TIMERS, "FA[%s] reg_retry_time: "
01140                       "%i => %i (reg. reply ok)\n",
01141                       inet_ntoa(mobile_array[cur_mobile].mn.current_adv->addr),
01142                       mobile_array[cur_mobile].mn.current_adv->reg_retry_time,
01143                       MIN_REGISTRATION_TIME);
01144                 mobile_array[cur_mobile].mn.current_adv->reg_retry_time = MIN_REGISTRATION_TIME;
01145         } else
01146                 mobile_array[cur_mobile].mn.HA_reg_retry_time = MIN_REGISTRATION_TIME;
01147 
01148         if (ntohs(ext->rep->lifetime) > 0) {
01149                 DEBUG(DEBUG_INFO, "Registration accepted\n");
01150 #ifdef INCLUDE_IPAY
01151                 if (mobile_array[cur_mobile].mn.current_adv != NULL)
01152                         ipay_new_fa(mobile_array[cur_mobile].mn.current_adv);
01153 #endif
01154         } else DEBUG(DEBUG_INFO, "Deregistration accepted\n");
01155 
01156         switch (mobile_array[cur_mobile].mn.state) {
01157         case MN_CLOSE_FOR_HOME:
01158                 mobile_array[cur_mobile].mn.ha_error_count = 0;
01159                 if (ntohs(ext->rep->lifetime) == 0)
01160                         at_home();
01161                 break;
01162         case MN_FIND_AGENT:
01163         case MN_PASSIVE_FIND:
01164                 /* The answer is coming later than expected,
01165                  * so we just skip it. */
01166                 DEBUG(DEBUG_MESSAGES, "handle_reg_accept - in find agent or "
01167                       "passive find state - skipping reg. reply\n");
01168                 break;
01169         case MN_REQUEST_TUNNEL:
01170         case MN_CONNECTED:
01171                 mobile_array[cur_mobile].mn.ha_error_count = 0;
01172                 if (ext->mn_keyrep != NULL)
01173                         handle_key_ext(ext->rep, ext->mn_keyrep);
01174                 if (ext->rep->lifetime == 0) {
01175                         LOG2(LOG_INFO, "Got registration accepted reply with "
01176                              "zero lifetime - aborting registration and going "
01177                              "to passive find state\n");
01178                         reply_waiting_api(API_FAILED, NULL, 0);
01179                         passive_find();
01180                         return;
01181                 } else {
01182                         connected((ext->mh_auth) ? CON_HA : CON_FA,
01183                                   ntohs(ext->rep->lifetime));
01184 #ifdef MN_LOCUPD_PROFILER
01185                         snprintf(tmp, sizeof(tmp), "CON %s",
01186                                  inet_ntoa(mobile_array[cur_mobile].mn.fa_addr));
01187                         write_profiler(tmp);
01188 #endif
01189                         reply_waiting_api(API_SUCCESS, NULL, 0);
01190                 }
01191                 break;
01192 
01193         case MN_DISCONNECTED:
01194 #ifdef MN_LOCUPD_PROFILER
01195                 write_profiler("DIS");
01196 #endif
01197                 break;
01198 
01199         default:
01200                 break;
01201         }
01202 }
01203 
01204 
01205 /* returns: 1 = try again, 0 = give up */
01206 static int handle_id_mismatch_ha(struct msg_extensions *ext)
01207 {
01208         /* If reply code is 133, id failed and we should resynchronize
01209          * clock/nonce and try again */
01210 #ifdef MN_LOCUPD_PROFILER
01211         write_profiler("DENY_ID");
01212 #endif
01213         switch (mobile_array[cur_mobile].config.replay_meth) {
01214         case REPLAY_PROTECTION_NONE:
01215                 LOG2(LOG_INFO, "ID mismatch from HA even with "
01216                      "disabled replay protection\n");
01217                 reply_waiting_api(API_FAILED, &ext->rep->code, 1);
01218                 disconnect();
01219                 break;
01220 
01221         case REPLAY_PROTECTION_TIMESTAMP:
01222                 mobile_array[cur_mobile].mn.clock_correction = ntohl(ext->rep->id[0]) -
01223                         UNIX_NTP_DIFF - time(NULL);
01224                 if (mobile_array[cur_mobile].mn.ha_error_count++ < MAX_HA_ERRORS) {
01225                         LOG2(LOG_INFO, "Clock synchronization %d seconds\n",
01226                              mobile_array[cur_mobile].mn.clock_correction);
01227                         return 1;
01228                 } else {
01229                         LOG2(LOG_INFO,
01230                              "Clock resynchronization failed. "
01231                              "Disconnecting.\n");
01232                         reply_waiting_api(API_FAILED, &ext->rep->code, 1);
01233                         disconnect();
01234                 }
01235                 break;
01236 
01237         case REPLAY_PROTECTION_NONCE:
01238                 if (mobile_array[cur_mobile].mn.ha_error_count++ < MAX_HA_ERRORS) {
01239                         LOG2(LOG_INFO, "Nonce mismatch - syncronizing\n");
01240                         return 1;
01241                 } else {
01242                         LOG2(LOG_INFO, "Nonce mismatch - "
01243                              "syncronization failed\n");
01244                         reply_waiting_api(API_FAILED, &ext->rep->code, 1);
01245                         disconnect();
01246                 }
01247                 break;
01248         }
01249 
01250         return 0;
01251 }
01252 
01253 
01254 /* returns: 1 = try again, 0 = give up */
01255 static int handle_long_lifetime(struct msg_extensions *ext)
01256 {
01257 #ifdef MN_LOCUPD_PROFILER
01258         write_profiler("LIFETIME_FA");
01259 #endif
01260         if (mobile_array[cur_mobile].mn.req_lifetime > ntohs(ext->rep->lifetime) &&
01261                 ntohs(ext->rep->lifetime) >= MIN_ALLOWED_LIFETIME) {
01262                 LOG2(LOG_INFO, "FA (closest FA %s), "
01263                      "requests smaller lifetime (%d) - retrying\n",
01264                      inet_ntoa(mobile_array[cur_mobile].mn.fa_addr), ntohs(ext->rep->lifetime));
01265                 mobile_array[cur_mobile].mn.req_lifetime = ntohs(ext->rep->lifetime);
01266                 return 1;
01267         }
01268 
01269         /* this FA failed - try to find another one */
01270         LOG2(LOG_INFO, "FA %s denies requested lifetime %d s with bad "
01271              "suggestion %d s - changing FA\n",
01272              inet_ntoa(mobile_array[cur_mobile].mn.fa_addr), mobile_array[cur_mobile].mn.req_lifetime,
01273              ntohs(ext->rep->lifetime));
01274         if (mobile_array[cur_mobile].mn.current_adv != NULL)
01275                 mobile_array[cur_mobile].mn.current_adv->reg_failed = 1;
01276         else
01277                 LOG2(LOG_INFO, "handle_long_lifetime - current_adv == NULL\n");
01278         find_agent(STATE_INIT);
01279         return 0;
01280 }
01281 
01282 
01283 /* returns: 1 = try again, 0 = give up */
01284 static int handle_unknown_ha(struct msg_extensions *ext)
01285 {
01286         int retry_hadisc = 0;
01287 
01288         /* dynamic home agent address resolution */
01289 
01290         if (mobile_array[cur_mobile].config.ha_ip_addr.s_addr != 0 || mobile_array[cur_mobile].config.home_net_addr_plen < 0) {
01291                 LOG2(LOG_INFO, "HA did not accept HA address %s\n",
01292                      inet_ntoa(mobile_array[cur_mobile].config.ha_ip_addr));
01293                 retry_hadisc = 1;
01294         }
01295 
01296         if (ext->rep->ha_addr.s_addr ==
01297             mobile_array[cur_mobile].config.home_net_subnet_bc.s_addr) {
01298                 LOG2(LOG_INFO, "HA returned same subnet-directed broadcast "
01299                      "address in dynamic address resolution\n");
01300                 retry_hadisc = 1;
01301         }
01302 
01303         if (retry_hadisc) {
01304                 if (mobile_array[cur_mobile].config.use_hadisc) {
01305                         DEBUG(DEBUG_MESSAGES, "Try to discover another HA\n");
01306                         mobile_array[cur_mobile].mn.info_str = "restarting HA discovery";
01307                         mobile_array[cur_mobile].config.ha_ip_addr.s_addr = 0;
01308                         return 1;
01309                 }
01310                 return 0;
01311         }
01312 
01313         LOG2(LOG_INFO, "Learned HA address (%s) with dynamic address "
01314              "resolution\n", inet_ntoa(ext->rep->ha_addr));
01315         mobile_array[cur_mobile].mn.info_str = "HA discovery completed successfully";
01316         mobile_array[cur_mobile].config.ha_ip_addr.s_addr = ext->rep->ha_addr.s_addr;
01317         return 1; /* try to register with the new HA address */
01318 }
01319 
01320 
01330 static int handle_reg_denied(struct msg_extensions *ext)
01331 {
01332         ASSERT(ext != NULL && ext->rep != NULL);
01333 
01334         if (mobile_array[cur_mobile].mn.state != MN_REQUEST_TUNNEL &&
01335             mobile_array[cur_mobile].mn.state != MN_CLOSE_FOR_HOME &&
01336             mobile_array[cur_mobile].mn.state != MN_CONNECTED) {
01337                 DEBUG(DEBUG_MESSAGES, "handle_reg_denied - received denial "
01338                       "reply while not trying to register\n");
01339                 return 0;
01340         }
01341 
01342         DEBUG(DEBUG_MESSAGES, "Registration denied, code = %d (%s)\n",
01343                      ext->rep->code, reply_code_str(ext->rep->code));
01344 
01345         switch (ext->rep->code) {
01346         case REGREP_ID_MISMATCH_HA:
01347                 return handle_id_mismatch_ha(ext);
01348 
01349         case REGREP_LONG_LIFETIME_FA:
01350                 return handle_long_lifetime(ext);
01351 
01352         case REGREP_UNKNOWN_HA_HA:
01353                 return handle_unknown_ha(ext);
01354 
01355         case REGREP_HA_HOST_UNCREACHABLE_FA:
01356         case REGREP_HA_PORT_UNCREACHABLE_FA:
01357         case REGREP_HA_UNREACHABLE_FA:
01358                 if (mobile_array[cur_mobile].config.use_hadisc && mobile_array[cur_mobile].config.ha_ip_addr.s_addr != 0) {
01359                         DEBUG(DEBUG_MESSAGES, "HA unreachable => try to "
01360                               "discover another HA\n");
01361                         mobile_array[cur_mobile].mn.info_str = "restarting HA discovery";
01362                         mobile_array[cur_mobile].config.ha_ip_addr.s_addr = 0;
01363                         return 1;
01364                 }
01365                 return 0;
01366 
01367         case REGREP_UNKNOWN_CHALLENGE_FA:
01368         case REGREP_STALE_CHALLENGE_FA:
01369                 return 1; /* try to reregister; FIX: should get a new challenge
01370                            * value, if no new agent advertisement has been
01371                            * received */
01372 
01373         case REGREP_MN_FAILED_AUTH_FA:
01374                 if (mobile_array[cur_mobile].mn.try_to_fix_sec_assoc) {
01375                         /* dynamic security association was removed in
01376                          * is_valid_reply() so try to reregister and create a
01377                          * new security association with the FA */
01378                         return 1;
01379                 }
01380 
01381                 /* no method for fixing the security association, so just fall
01382                  * through to the default case */
01383 
01384         default:
01385 #ifdef MN_LOCUPD_PROFILER
01386                 write_profiler("DENY");
01387 #endif
01388                 LOG2(LOG_INFO, "Registration denied, code = %d (%s)\n",
01389                      ext->rep->code, reply_code_str(ext->rep->code));
01390                 reply_waiting_api(API_FAILED, &ext->rep->code, 1);
01391                 /* Try to change the FA by degrading the priority of the "
01392                    "current FA. */
01393                 degrade_current_fa_priority();
01394         }
01395 
01396         return 0;
01397 }
01398 
01399 
01400 /* Handle registration message from socket s.
01401  * Returns 1 if registration should be re-tried */
01402 int handle_registration(int s)
01403 {
01404         char msg[MAXMSG];
01405         unsigned int len;
01406         struct sockaddr_in addr;
01407         int n, res;
01408         struct msg_extensions ext;
01409 
01410         len = sizeof(addr);
01411 
01412         n = recvfrom(s, msg, MAXMSG, 0, (struct sockaddr*) &addr, &len);
01413         if (n < 0) {
01414                 LOG2(LOG_ERR, "registration recv: %s\n", strerror(errno));
01415                 return 0;
01416         }
01417         DEBUG(DEBUG_MESSAGES, "Received %d bytes from %s:%d\n", n,
01418                inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
01419 
01420         res = parse_msg(msg, n, &ext);
01421         if (res != 0 || ext.double_auth_ext != 0) {
01422                 char *reason = "N/A";
01423                 DEBUG(DEBUG_MESSAGES, "Dropping invalid message\n");
01424                 mobile_array[cur_mobile].mn.discarded_msgs++;
01425                 if (res == -1)
01426                         reason = "unknown extension";
01427                 else if (res == -2)
01428                         reason = "malformed message";
01429                 else if (res == -3 || res == -4 || res == -5)
01430                         reason = "unknown vendor extension";
01431                 else if (ext.double_auth_ext != 0)
01432                         reason = "double authentication extension";
01433                 report_discarded_msg(msg, n, &addr, reason);
01434                 return 0;
01435         }
01436 
01437         mobile_array[cur_mobile].mn.try_to_fix_sec_assoc = 0;
01438         if (is_valid_reply(&ext, addr)) {
01439                 mobile_array[cur_mobile].mn.prev_req_replied = 1;
01440                 time(&mobile_array[cur_mobile].mn.last_reply_rcvd);
01441                 mobile_array[cur_mobile].mn.last_reply_code = ext.rep->code;
01442                 mobile_array[cur_mobile].mn.last_nonce = ext.rep->id[0];
01443                 if (ext.challenge != NULL) {
01444                         int len;
01445                         gettimeofday(&mobile_array[cur_mobile].mn.last_challenge_time, NULL);
01446                         len = GET_CHALLENGE_EXT_LEN(ext.challenge);
01447                         if (mobile_array[cur_mobile].mn.last_challenge_ext == NULL ||
01448                             GET_CHALLENGE_EXT_LEN(mobile_array[cur_mobile].mn.last_challenge_ext) !=
01449                             len) {
01450                                 if (mobile_array[cur_mobile].mn.last_challenge_ext != NULL)
01451                                         free(mobile_array[cur_mobile].mn.last_challenge_ext);
01452                                 mobile_array[cur_mobile].mn.last_challenge_ext =
01453                                         (struct challenge_ext *) malloc(len);
01454                         }
01455 
01456                         if (mobile_array[cur_mobile].mn.last_challenge_ext != NULL)
01457                                 memcpy(mobile_array[cur_mobile].mn.last_challenge_ext, ext.challenge,
01458                                        len);
01459                         else
01460                                 DEBUG(DEBUG_INFO, "Could not malloc() memory "
01461                                       "for challenge extension\n");
01462                 }
01463                 if (IS_REGREP_ACCEPTED(ext.rep->code))
01464                         handle_reg_accept(&ext);
01465                 else
01466                         return handle_reg_denied(&ext);
01467         } else {
01468                 report_discarded_msg(msg, n, &addr, "invalid reply");
01469                 mobile_array[cur_mobile].mn.discarded_msgs++;
01470         }
01471 
01472         return 0;
01473 }
01474 
01475 
01483 int send_messages(int interval)
01484 {
01485 int i=0;
01486         for(i;i<mobiles-1;i++){
01487                 tm=time(NULL);
01488                 tmptr =localtime(&tm);
01489                 strftime(timestr,100, " %X",tmptr); //get time 
01490                 if((i+1)<mobiles) //check that we're not trying to go out of array 
01491                 {
01492                 if(interval=atoi(devices[i+1].timestart)-atoi(devices[i].timestart)<0) interval=3; //timeline fuxxored, no negative times->use default 3 seconds TODO: read from given interval
01493                 else interval=atoi(devices[i+1].timestart)-atoi(devices[i].timestart); //given wait ok
01494                 }
01495                 else interval=3; //wait 3 seconds after quit TODO read from given interval
01496 
01497                 
01498                 if(mobile_array[cur_mobile].state==0) //joint
01499                 {
01500                         mobile_array[cur_mobile].mn.req_lifetime = 600;
01501                         printf("%s REGISTERATION message with home address: %s , NAI: %s and interval: %i \n" , timestr, inet_ntoa(mobile_array[cur_mobile].config.mn_home_ip_addr),mobile_array[cur_mobile].config.mn_nai, interval);
01502                         send_registration(REG_CONNECT); //send reg
01503                         sent_regs++;
01504                 }
01505                 else //leave TODO if state==1 and if state==2 !!
01506          {
01507                         printf("%s DEREGISTERATION message with home address: %s and NAI: %s and interval %i \n", timestr, inet_ntoa(mobile_array[cur_mobile].config.mn_home_ip_addr), mobile_array[cur_mobile].config.mn_nai, interval);
01508                         mobile_array[cur_mobile].mn.req_lifetime = 0;
01509                         send_registration(REG_DISC); //send dereg
01510                         sent_deregs++;
01511                 }
01512                 cur_mobile=cur_mobile+1; //next mobile
01513                 
01514                 sleep(interval);
01515         }
01516         cur_mobile=0; //back to start, just in case
01517 
01518 return 1;
01519 }
01520 
01528 int create_mobile()
01529 {
01530 int i =0;
01531 
01532         for(i=0;i<rownumber-1;i++)
01533         {
01534                 if(devices[i].ip_home==NULL) return -1;//file read but it was empty, quit!
01535                 mobile_array[i].mn=mn;
01536                 mobile_array[i].config=config;
01537                 mobile_array[i].config.mn_home_ip_addr.s_addr=inet_addr(devices[i].ip_home);
01538                 mobile_array[i].config.mn_home_ip_addr_orig.s_addr=inet_addr(devices[i].ip_home);
01539                 mobile_array[i].config.ha_ip_addr.s_addr=inet_addr(devices[i].ip_homeagent);
01540                 mobile_array[i].config.ha_ip_addr_orig.s_addr=inet_addr(devices[i].ip_homeagent);
01541                 mobile_array[i].config.mn_nai_len=sizeof(devices[i].nai);
01542                 memcpy(mobile_array[i].config.mn_nai, devices[i].nai,sizeof(devices[i].nai));
01543                 mobile_array[i].mn.co_addr.s_addr=inet_addr(devices[i].ip_careoff);
01544                 mobile_array[i].state=atoi(devices[i].state);
01545                 mobiles=mobiles+1;
01546         }
01547 
01548 }
01549 
01550 
01560 int readfile(char file[]){
01561 
01562  FILE *fileo;
01563  
01564  fileo = fopen(file,"r"); 
01565 
01566   if(file==NULL) {
01567     printf("Do not Open.\n");
01568     return 1;
01569   }
01570 
01571 int i=0;
01572 
01573 while (!feof(fileo))
01574 {
01575         fgets(rows[i].row, sizeof(rows[i].row), fileo);    
01576   i=i+1;
01577   rownumber=rownumber+1;
01578 }
01579 
01580 
01581 return 1;
01582 }
01583 
01592 int parse_rows(int i) {
01593 
01594 int j;
01595 
01596 for (j=0; j<i; j++)
01597  {
01598         sscanf (rows[j].row,"%s %s %s %s %s %s ",devices[j].timestart,devices[j].state,devices[j].ip_home,devices[j].ip_homeagent,devices[j].ip_careoff,devices[j].nai,);
01599 
01600         }
01601 
01602 return 1;
01603 }
01604 
01605 
01606 
01607 int main(int argc, char *argv[])
01608 
01609 {
01610         printf("Virtual foreign agent v0.1. \n Sending registeration messages with interval: %i \n", 3);
01611         mn_init(); //read dynmnd.conf to make "meta mobile node"
01612         if(argc==2) readfile(argv[1]); 
01613         else
01614         {
01615                 printf("No filename given - using default /home/dynamo/mobiles.txt \n");
01616                 readfile("/home/dynamo/mobiles.txt"); //read cfg
01617         }
01618 
01619   parse_rows(rownumber); //parse lines
01620         create_mobile(); //creates virtual mobile nodes into array
01621         send_messages(3); //sends register messages with given interval
01622         printf("Sent %i REGISTER messages and %i DEREGISTER messages \n", sent_regs, sent_deregs);
01623         
01624   return EXIT_SUCCESS;
01625 }

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