00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00052 int intervals[5000];
00053
00054
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
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;
00103 int mobiles=0;
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
00118
00119
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
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
00158
00159
00160
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
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
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
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
00352
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
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
00368
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
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
00410
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
00424
00425
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
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
00448
00449
00450
00451
00452
00453
00454
00455
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
00486
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
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
00512
00513
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
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
00534
00535
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
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
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 int send_registration(int request_type)
00581 {
00582 char sendbuf[MAXMSG];
00583 char *pos;
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
00657
00658
00659 if (parse_msg(sendbuf, len, &ext) != 0) {
00660 DEBUG(DEBUG_INFO, "WARNING! Own registration request was not "
00661 "valid!\n");
00662 }
00663
00664
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
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
00701 memset(&addr, 0, sizeof(addr));
00702 addr.sin_family = AF_INET;
00703
00704
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
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
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
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
00818
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
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
00860
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
00874
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
00920
00921
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
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
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
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
00997 if (ext->mn_keyrep != NULL) {
00998 DEBUG(DEBUG_MESSAGES, "Registration reply from FA "
00999 "contained mn_keyrep extension - dropped it\n");
01000
01001
01002 ext->mn_keyrep = NULL;
01003 }
01004 } else if (ext->rep->code < 64 || ext->rep->code > 127) {
01005
01006
01007
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
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
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
01089 mobile_array[cur_mobile].mn.registration_id[1]++;
01090
01091 return 1;
01092 #endif
01093 }
01094
01095
01096
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
01102
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
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
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
01135 mobile_array[cur_mobile].mn.expire_check = 1;
01136
01137 if (mobile_array[cur_mobile].mn.current_adv != NULL) {
01138
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
01165
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
01206 static int handle_id_mismatch_ha(struct msg_extensions *ext)
01207 {
01208
01209
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
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
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
01284 static int handle_unknown_ha(struct msg_extensions *ext)
01285 {
01286 int retry_hadisc = 0;
01287
01288
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;
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;
01370
01371
01372
01373 case REGREP_MN_FAILED_AUTH_FA:
01374 if (mobile_array[cur_mobile].mn.try_to_fix_sec_assoc) {
01375
01376
01377
01378 return 1;
01379 }
01380
01381
01382
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
01392
01393 degrade_current_fa_priority();
01394 }
01395
01396 return 0;
01397 }
01398
01399
01400
01401
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);
01490 if((i+1)<mobiles)
01491 {
01492 if(interval=atoi(devices[i+1].timestart)-atoi(devices[i].timestart)<0) interval=3;
01493 else interval=atoi(devices[i+1].timestart)-atoi(devices[i].timestart);
01494 }
01495 else interval=3;
01496
01497
01498 if(mobile_array[cur_mobile].state==0)
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);
01503 sent_regs++;
01504 }
01505 else
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);
01510 sent_deregs++;
01511 }
01512 cur_mobile=cur_mobile+1;
01513
01514 sleep(interval);
01515 }
01516 cur_mobile=0;
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;
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();
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");
01617 }
01618
01619 parse_rows(rownumber);
01620 create_mobile();
01621 send_messages(3);
01622 printf("Sent %i REGISTER messages and %i DEREGISTER messages \n", sent_regs, sent_deregs);
01623
01624 return EXIT_SUCCESS;
01625 }