PageRenderTime 54ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/src/mn.c

https://github.com/shtrom/umip
C | 2649 lines | 2182 code | 345 blank | 122 comment | 516 complexity | d53d9b9e2d849b5d827e37d7ec49d9e6 MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * $Id: mn.c 1.380 06/05/15 18:34:56+03:00 vnuorval@tcs.hut.fi $
  3. *
  4. * This file is part of the MIPL Mobile IPv6 for Linux.
  5. *
  6. * Authors:
  7. * Ville Nuorvala <vnuorval@tcs.hut.fi>
  8. * Antti Tuominen <anttit@tcs.hut.fi>
  9. * Henrik Petander <petander@tcs.hut.fi>
  10. *
  11. * Copyright 2003-2005 Go-Core Project
  12. * Copyright 2003-2006 Helsinki University of Technology
  13. *
  14. * MIPL Mobile IPv6 for Linux is free software; you can redistribute
  15. * it and/or modify it under the terms of the GNU General Public
  16. * License as published by the Free Software Foundation; version 2 of
  17. * the License.
  18. *
  19. * MIPL Mobile IPv6 for Linux is distributed in the hope that it will
  20. * be useful, but WITHOUT ANY WARRANTY; without even the implied
  21. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  22. * See the GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with MIPL Mobile IPv6 for Linux; if not, write to the Free
  26. * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  27. * 02111-1307 USA.
  28. */
  29. #ifdef HAVE_CONFIG_H
  30. #include <config.h>
  31. #endif
  32. #include <pthread.h>
  33. #include <syslog.h>
  34. #include <errno.h>
  35. #include <time.h>
  36. #include <unistd.h>
  37. #include <netinet/icmp6.h>
  38. #include <netinet/ip6mh.h>
  39. #include <netinet/in.h>
  40. #include <netinet/ip6.h>
  41. #include <linux/fib_rules.h>
  42. #include "debug.h"
  43. #include "mipv6.h"
  44. #include "icmp6.h"
  45. #include "ndisc.h"
  46. #include "mpdisc_mn.h"
  47. #include "mh.h"
  48. #include "mn.h"
  49. #include "cn.h"
  50. #include "movement.h"
  51. #include "util.h"
  52. #include "list.h"
  53. #include "bul.h"
  54. #include "xfrm.h"
  55. #include "tunnelctl.h"
  56. #include "rtnl.h"
  57. #include "conf.h"
  58. #include "prefix.h"
  59. #include "retrout.h"
  60. #include "keygen.h"
  61. #include "dhaad_mn.h"
  62. #include "ipsec.h"
  63. #define MN_DEBUG_LEVEL 1
  64. #if MN_DEBUG_LEVEL >= 1
  65. #define MDBG dbg
  66. #else
  67. #define MDBG(...)
  68. #endif
  69. #if MN_DEBUG_LEVEL >= 2
  70. #define MDBG2 dbg
  71. #else
  72. #define MDBG2(...)
  73. #endif
  74. #ifndef FIB_RULE_FIND_SADDR
  75. #define FIB_RULE_FIND_SADDR 0
  76. #endif
  77. LIST_HEAD(home_addr_list);
  78. pthread_rwlock_t mn_lock;
  79. const struct timespec dereg_bu_lifetime_ts =
  80. { DEREG_BU_LIFETIME, 0 };
  81. const struct timespec non_mip_cn_ltime_ts =
  82. { NON_MIP_CN_LTIME, 0 };
  83. const struct timespec min_valid_bu_lifetime_ts =
  84. { MIN_VALID_BU_LIFETIME, 0 };
  85. static int pending_bas = 0;
  86. static void mn_send_home_bu(struct home_addr_info *hai);
  87. static int mn_ext_tunnel_ops(int request, int old_if, int new_if, void *data);
  88. static int mn_block_rule_del(struct home_addr_info *hai)
  89. {
  90. int ret = -1;
  91. if (!(hai->home_block & HOME_ADDR_RULE_BLOCK)) {
  92. MDBG("blackhole is not set.\n");
  93. return ret;
  94. }
  95. if ((ret = rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK, RTN_BLACKHOLE,
  96. &hai->hoa.addr, 128, &in6addr_any, 0,
  97. FIB_RULE_FIND_SADDR)) < 0)
  98. MDBG("failed to delete blackhole rule.\n");
  99. else
  100. hai->home_block &= ~HOME_ADDR_RULE_BLOCK;
  101. return ret;
  102. }
  103. static int mn_block_rule_add(struct home_addr_info *hai)
  104. {
  105. int ret = -1;
  106. if (hai->home_block & HOME_ADDR_RULE_BLOCK) {
  107. MDBG("blackhole is already set.\n");
  108. return ret;
  109. }
  110. if ((ret = rule_add(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK, RTN_BLACKHOLE,
  111. &hai->hoa.addr, 128, &in6addr_any, 0,
  112. FIB_RULE_FIND_SADDR)) < 0)
  113. MDBG("failed to add blackhole rule.\n");
  114. else
  115. hai->home_block |= HOME_ADDR_RULE_BLOCK;
  116. return ret;
  117. }
  118. static void bul_expire(struct tq_elem *tqe)
  119. {
  120. pthread_rwlock_wrlock(&mn_lock);
  121. if (!task_interrupted()) {
  122. struct bulentry *bule = tq_data(tqe, struct bulentry, tqe);
  123. /* Set lifetime to 0 to help bul_delete */
  124. tsclear(bule->lifetime);
  125. MDBG("Bul expire type %d", bule->type);
  126. bul_delete(bule);
  127. }
  128. pthread_rwlock_unlock(&mn_lock);
  129. }
  130. static void bule_invalidate(struct bulentry *e,
  131. struct timespec *timestamp,
  132. int block)
  133. {
  134. struct home_addr_info *hai = e->home;
  135. struct in6_addr hoa, peer_addr;
  136. int type = e->type;
  137. uint16_t flags = e->flags;
  138. if (type != BUL_ENTRY)
  139. return;
  140. MDBG("%s unable to handle binding, changing BUL entry to %s\n",
  141. (e->flags & IP6_MH_BU_HOME ? "HA" : "CN"),
  142. (block ? "NON_MIP_CN_ENTRY" : "UNREACH_ENTRY"));
  143. hoa = e->hoa;
  144. peer_addr = e->peer_addr;
  145. bul_delete(e);
  146. if (hai->at_home)
  147. return;
  148. e = create_bule(&hoa, &peer_addr);
  149. if (e == NULL)
  150. return;
  151. e->type = block ? NON_MIP_CN_ENTRY : UNREACH_ENTRY;
  152. e->flags = flags;
  153. e->home = hai;
  154. e->lastsent = *timestamp;
  155. e->lifetime = NON_MIP_CN_LTIME_TS;
  156. e->delay = NON_MIP_CN_LTIME_TS;
  157. e->callback = bul_expire;
  158. if (bul_add(e) < 0)
  159. bul_delete(e);
  160. }
  161. static void mn_reset_ro_bule(struct bulentry *e)
  162. {
  163. e->callback = bul_expire;
  164. e->lifetime = MAX_TOKEN_LIFETIME_TS;
  165. e->delay = MAX_TOKEN_LIFETIME_TS;
  166. e->do_send_bu = 1;
  167. }
  168. static void mn_rr_check_entry(struct tq_elem *tqe)
  169. {
  170. struct bulentry *bule;
  171. struct timespec now;
  172. long last_used;
  173. pthread_rwlock_wrlock(&mn_lock);
  174. if (task_interrupted()) {
  175. pthread_rwlock_unlock(&mn_lock);
  176. return;
  177. }
  178. bule = tq_data(tqe, struct bulentry, tqe);
  179. clock_gettime(CLOCK_REALTIME, &now);
  180. last_used = mn_bule_xfrm_last_used(&bule->peer_addr, &bule->hoa, &now);
  181. if (last_used >= 0 && last_used < MN_RO_RESTART_THRESHOLD) {
  182. bule->lastsent = now;
  183. mn_reset_ro_bule(bule);
  184. pre_bu_bul_update(bule);
  185. mn_rr_refresh(bule);
  186. if (bule->rr.state == RR_READY)
  187. mn_send_cn_bu(bule);
  188. else {
  189. bul_update_expire(bule);
  190. bul_update_timer(bule);
  191. }
  192. pthread_rwlock_unlock(&mn_lock);
  193. return;
  194. }
  195. bul_delete(bule);
  196. pthread_rwlock_unlock(&mn_lock);
  197. }
  198. static void mn_recv_param_prob(const struct icmp6_hdr *ih, ssize_t len,
  199. __attribute__ ((unused)) const struct in6_addr *src,
  200. const struct in6_addr *dst,
  201. __attribute__ ((unused)) int iif,
  202. __attribute__ ((unused)) int hoplimit)
  203. {
  204. struct ip6_hdr *ip6h = (struct ip6_hdr *)(ih + 1);
  205. int optlen = len - sizeof(struct icmp6_hdr);
  206. uint32_t errptr;
  207. uint8_t *off_octet;
  208. struct bulentry *e = NULL;
  209. struct in6_addr *laddr = &ip6h->ip6_src;
  210. struct in6_addr *raddr = &ip6h->ip6_dst;
  211. struct in6_addr addr;
  212. /* We only handle code 1 & 2 messages. */
  213. if (ih->icmp6_code != ICMP6_PARAMPROB_NEXTHEADER &&
  214. ih->icmp6_code != ICMP6_PARAMPROB_OPTION)
  215. return;
  216. /* Find offending octet in the original packet. */
  217. errptr = ntohl(ih->icmp6_pptr);
  218. /* Validity checks */
  219. if (len < 0 ||
  220. (uint32_t)len <= errptr || !IN6_ARE_ADDR_EQUAL(laddr, dst) ||
  221. icmp6_parse_data(ip6h, optlen, &laddr, &raddr) < 0)
  222. return;
  223. off_octet = ((uint8_t *) ip6h + errptr);
  224. MDBG("Parameter problem: offending octet %d [0x%2x]\n",
  225. errptr, *off_octet);
  226. /* If CN did not understand Mobility Header, set BUL entry to
  227. * ACK_ERROR so no further BUs are sumbitted to this CN. */
  228. if (ih->icmp6_code == ICMP6_PARAMPROB_NEXTHEADER &&
  229. *off_octet == IPPROTO_MH) {
  230. MDBG("CN doesn't implement MH handling.\n");
  231. } else if (ih->icmp6_code == ICMP6_PARAMPROB_OPTION &&
  232. *off_octet == IP6OPT_HOME_ADDRESS) {
  233. MDBG("CN doesn't implement Home Address Option processing\n");
  234. } else {
  235. MDBG("Got ICMPv6 paramprob not resulting from HAO or MH\n");
  236. return;
  237. }
  238. pthread_rwlock_wrlock(&mn_lock);
  239. if (mn_rr_error_check(laddr, raddr, &addr))
  240. laddr = &addr;
  241. e = bul_get(NULL, laddr, raddr);
  242. if (e != NULL) {
  243. if (e->flags & IP6_MH_BU_HOME) {
  244. if (!conf.UseMnHaIPsec &&
  245. !conf.MnDiscardHaParamProb) {
  246. clock_gettime(CLOCK_REALTIME, &e->lastsent);
  247. bule_invalidate(e, &e->lastsent, 1);
  248. }
  249. } else if (ih->icmp6_code == ICMP6_PARAMPROB_OPTION) {
  250. syslog(LOG_ERR,
  251. "CN participated in RO but can't handle HAO\n");
  252. } else {
  253. clock_gettime(CLOCK_REALTIME, &e->lastsent);
  254. bule_invalidate(e, &e->lastsent, 1);
  255. }
  256. }
  257. pthread_rwlock_unlock(&mn_lock);
  258. }
  259. static struct icmp6_handler mn_param_prob_handler = {
  260. .recv = mn_recv_param_prob,
  261. };
  262. static int mn_send_bu_msg(struct bulentry *bule)
  263. {
  264. struct ip6_mh_binding_update *bu;
  265. struct iovec iov[IP6_MHOPT_MAX+1];
  266. int iov_ind = 0;
  267. int ret = -ENOMEM;
  268. uint8_t *bind_key = NULL;
  269. struct in6_addr_bundle addrs;
  270. memset(iov, 0, IP6_MHOPT_MAX+1);
  271. bu = mh_create(&iov[iov_ind++], IP6_MH_TYPE_BU);
  272. if (!bu)
  273. return -ENOMEM;
  274. bu->ip6mhbu_seqno = htons(bule->seq);
  275. bu->ip6mhbu_flags = bule->flags;
  276. bu->ip6mhbu_lifetime = htons(bule->lifetime.tv_sec >> 2);
  277. if (bule->use_alt_coa &&
  278. mh_create_opt_altcoa(&iov[iov_ind++], &bule->coa)) {
  279. free_iov_data(iov, iov_ind);
  280. return -ENOMEM;
  281. }
  282. if (bule->flags & IP6_MH_BU_HOME) {
  283. struct home_addr_info *hai = bule->home;
  284. if (bule->flags & IP6_MH_BU_MR && bu->ip6mhbu_lifetime &&
  285. bule->home->mnp_count > 0 && conf.MobRtrUseExplicitMode &&
  286. mh_create_opt_mob_net_prefix(&iov[iov_ind++],
  287. hai->mnp_count,
  288. &hai->mob_net_prefixes) < 0) {
  289. free_iov_data(iov, iov_ind);
  290. return -ENOMEM;
  291. }
  292. } else {
  293. if (mh_create_opt_nonce_index(&iov[iov_ind++], bule->rr.ho_ni,
  294. bule->rr.co_ni) ||
  295. mh_create_opt_auth_data(&iov[iov_ind++])) {
  296. free_iov_data(iov, iov_ind);
  297. return -ENOMEM;
  298. }
  299. bind_key = bule->Kbm;
  300. }
  301. if (bule->flags & IP6_MH_BU_ACK)
  302. bule->wait_ack = 1;
  303. addrs.src = &bule->hoa;
  304. addrs.dst = &bule->peer_addr;
  305. addrs.local_coa = &bule->coa;
  306. addrs.remote_coa = NULL;
  307. addrs.bind_coa = &bule->coa;
  308. ret = mh_send(&addrs, iov, iov_ind, bind_key, bule->if_coa);
  309. if (ret <= 0)
  310. MDBG("mh_send failed ret: %d\n", ret);
  311. free_iov_data(iov, iov_ind);
  312. return ret;
  313. }
  314. static int mn_get_home_lifetime(struct home_addr_info *hai,
  315. struct timespec *lifetime, int dereg)
  316. {
  317. if (!hai->at_home && !dereg) {
  318. struct mn_addr *coa = &hai->primary_coa;
  319. struct timespec now;
  320. unsigned long coa_lft;
  321. unsigned long hoa_lft;
  322. clock_gettime(CLOCK_REALTIME, &now);
  323. coa_lft = mpd_curr_lft(&now, &coa->timestamp,
  324. coa->valid_time.tv_sec);
  325. hoa_lft = mpd_curr_lft(&now, &hai->hoa.timestamp,
  326. hai->hoa.valid_time.tv_sec);
  327. tssetsec(*lifetime, umin(umin(coa_lft, hoa_lft),
  328. conf.MnMaxHaBindingLife));
  329. mpd_sanitize_lft(lifetime);
  330. MDBG("CoA lifetime %u s, HoA lifetime %u s, BU lifetime %u s\n",
  331. coa_lft, hoa_lft, lifetime->tv_sec);
  332. return 0;
  333. } else {
  334. tsclear(*lifetime);
  335. MDBG("BU lifetime %u s\n", lifetime->tv_sec);
  336. return 1;
  337. }
  338. }
  339. static int mn_get_ro_lifetime(struct home_addr_info *hai,
  340. struct timespec *lifetime, int dereg)
  341. {
  342. tsclear(*lifetime);
  343. if (!hai->at_home && !dereg) {
  344. struct bulentry *e;
  345. e = bul_get(hai, NULL, &hai->ha_addr);
  346. if (e == NULL || !(e->flags & IP6_MH_BU_HOME)) {
  347. MDBG("No valid home registration");
  348. } else {
  349. struct timespec now;
  350. struct mn_addr *coa = &hai->primary_coa;
  351. unsigned long coa_lft;
  352. unsigned long home_lft;
  353. clock_gettime(CLOCK_REALTIME, &now);
  354. coa_lft = mpd_curr_lft(&now, &coa->timestamp,
  355. coa->valid_time.tv_sec);
  356. home_lft = mpd_curr_lft(&now, &e->lastsent,
  357. e->lifetime.tv_sec);
  358. tssetsec(*lifetime, umin(umin(coa_lft, home_lft),
  359. conf.MnMaxCnBindingLife));
  360. mpd_sanitize_lft(lifetime);
  361. }
  362. return 0;
  363. }
  364. MDBG("BU lifetime %u s\n", lifetime->tv_sec);
  365. return 1;
  366. }
  367. static int mn_dereg(void *vbule, __attribute__ ((unused)) void *arg)
  368. {
  369. struct bulentry *bule = vbule;
  370. if (bule->type == BUL_ENTRY) {
  371. if (!(bule->flags & IP6_MH_BU_HOME)) {
  372. bule->dereg = 1;
  373. mn_rr_refresh(bule);
  374. if (bule->rr.state != RR_READY)
  375. return 0;
  376. }
  377. bule->seq++;
  378. tsclear(bule->lifetime);
  379. mn_send_bu_msg(bule);
  380. }
  381. bul_delete(bule);
  382. return 0;
  383. }
  384. #define FLUSH_ALL 0
  385. #define FLUSH_VALID 1
  386. #define FLUSH_FAILED 2
  387. static int _bul_flush(void *vbule, void *arg)
  388. {
  389. struct bulentry *bule = vbule;
  390. int *type = arg;
  391. if (*type == FLUSH_ALL ||
  392. (*type == FLUSH_VALID && bule->type == BUL_ENTRY) ||
  393. (*type == FLUSH_FAILED && bule->type != BUL_ENTRY))
  394. bul_delete(bule);
  395. return 0;
  396. }
  397. static void mn_change_ha(struct home_addr_info *hai)
  398. {
  399. int dhaad = dhaad_home_reg_failed(hai);
  400. int type = FLUSH_VALID;
  401. if (hai->home_reg_status != HOME_REG_NONE)
  402. bul_iterate(&hai->bul, _bul_flush, &type);
  403. syslog(LOG_ERR,
  404. "Home registration failed with HA, trying next one\n");
  405. if (!dhaad && !hai->at_home)
  406. mn_send_home_bu(hai);
  407. }
  408. static int bu_lft_check(struct bulentry *bule)
  409. {
  410. if (!tsisset(bule->lifetime))
  411. return 0;
  412. int dereg;
  413. if (bule->flags & IP6_MH_BU_HOME)
  414. dereg = mn_get_home_lifetime(bule->home, &bule->lifetime, 0);
  415. else
  416. dereg = mn_get_ro_lifetime(bule->home, &bule->lifetime,
  417. bule->dereg);
  418. return !dereg && !tsisset(bule->lifetime);
  419. }
  420. /*
  421. * bu_resend - resend a binding update
  422. */
  423. static void bu_resend(struct tq_elem *tqe)
  424. {
  425. pthread_rwlock_wrlock(&mn_lock);
  426. if (!task_interrupted()) {
  427. struct bulentry *bule = tq_data(tqe, struct bulentry, tqe);
  428. struct home_addr_info *hai = bule->home;
  429. int expired;
  430. MDBG("Bul resend [%p] type %d\n", bule, bule->type);
  431. clock_gettime(CLOCK_REALTIME, &bule->lastsent);
  432. tsadd(bule->delay, bule->delay, bule->delay);
  433. bule->delay = tsmin(bule->delay, MAX_BINDACK_TIMEOUT_TS);
  434. bule->consecutive_resends++;
  435. expired = bu_lft_check(bule);
  436. bule->seq++;
  437. if (bule->flags & IP6_MH_BU_HOME &&
  438. hai->use_dhaad &&
  439. bule->consecutive_resends > MAX_CONSECUTIVE_RESENDS) {
  440. struct timespec now;
  441. clock_gettime(CLOCK_REALTIME, &now);
  442. bule_invalidate(bule, &now, 0);
  443. mn_change_ha(hai);
  444. pthread_rwlock_unlock(&mn_lock);
  445. return;
  446. }
  447. mn_send_bu_msg(bule);
  448. if (expired)
  449. bul_delete(bule);
  450. else {
  451. bul_update_expire(bule);
  452. bul_update_timer(bule);
  453. }
  454. }
  455. pthread_rwlock_unlock(&mn_lock);
  456. }
  457. static void bu_refresh(struct tq_elem *tqe)
  458. {
  459. pthread_rwlock_wrlock(&mn_lock);
  460. if (!task_interrupted()) {
  461. struct bulentry *bule = tq_data(tqe, struct bulentry, tqe);
  462. int expired;
  463. MDBG("Bul refresh type: %d\n", bule->type);
  464. clock_gettime(CLOCK_REALTIME, &bule->lastsent);
  465. bule->delay = conf.InitialBindackTimeoutReReg_ts;
  466. expired = bu_lft_check(bule);
  467. bule->seq++;
  468. bule->callback = bu_resend;
  469. pre_bu_bul_update(bule);
  470. mn_send_bu_msg(bule);
  471. if (expired)
  472. bul_delete(bule);
  473. else {
  474. bul_update_expire(bule);
  475. bul_update_timer(bule);
  476. if (conf.OptimisticHandoff)
  477. post_ba_bul_update(bule);
  478. }
  479. }
  480. pthread_rwlock_unlock(&mn_lock);
  481. }
  482. static void mn_update_hoa_lifetime(struct mn_addr *mn_hoa,
  483. struct timespec *timestamp,
  484. uint32_t valid_time,
  485. uint32_t preferred_time)
  486. {
  487. mn_hoa->timestamp = *timestamp;
  488. tssetsec(mn_hoa->valid_time, valid_time);
  489. tssetsec(mn_hoa->preferred_time, preferred_time);
  490. MDBG2("updated HoA lifetimes: preferred %u s and valid %u s\n",
  491. mn_hoa->preferred_time.tv_sec, mn_hoa->valid_time.tv_sec);
  492. }
  493. struct mv_hoa_args {
  494. struct home_addr_info *target;
  495. int if_next;
  496. };
  497. /*
  498. * Move home address between
  499. */
  500. static int mv_hoa(struct ifaddrmsg *ifa, struct rtattr *rta_tb[], void *arg)
  501. {
  502. struct mv_hoa_args *mha = arg;
  503. struct home_addr_info *hai = mha->target;
  504. struct mn_addr *hoa = &hai->hoa;
  505. int err;
  506. struct timespec now;
  507. uint32_t preferred = PREFIX_LIFETIME_INFINITE;
  508. uint32_t valid = PREFIX_LIFETIME_INFINITE;
  509. int plen = (mha->if_next == hai->if_tunnel ? 128 : hai->plen);
  510. clock_gettime(CLOCK_REALTIME, &now);
  511. if (hai->lladdr_comp && rta_tb[IFA_CACHEINFO] != NULL) {
  512. struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
  513. mn_update_hoa_lifetime(hoa, &now,
  514. ci->ifa_valid, ci->ifa_prefered);
  515. valid = ci->ifa_valid;
  516. preferred = ci->ifa_prefered;
  517. }
  518. if (mha->if_next >= 0 && (unsigned int)mha->if_next == ifa->ifa_index)
  519. return 0;
  520. MDBG("move HoA %x:%x:%x:%x:%x:%x:%x:%x/%d from iface %d to %d\n",
  521. NIP6ADDR(&hoa->addr), plen, ifa->ifa_index, mha->if_next);
  522. err = addr_add(&hoa->addr, plen,
  523. ifa->ifa_flags|IFA_F_HOMEADDRESS_NODAD,
  524. ifa->ifa_scope, mha->if_next, preferred, valid);
  525. if (err < 0)
  526. return err;
  527. hoa->iif = mha->if_next;
  528. addr_del(&hoa->addr, ifa->ifa_prefixlen, ifa->ifa_index);
  529. return 0;
  530. }
  531. int nemo_mr_tnl_routes_add(struct home_addr_info *hai, int ifindex)
  532. {
  533. struct list_head *l;
  534. struct prefix_list_entry *pe;
  535. list_for_each(l, &hai->mob_net_prefixes) {
  536. struct prefix_list_entry *p;
  537. p = list_entry(l, struct prefix_list_entry, list);
  538. if (route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP,
  539. 0, IP6_RT_PRIO_MIP6_FWD,
  540. &p->ple_prefix, p->ple_plen,
  541. &in6addr_any, 0, NULL) < 0) {
  542. pe = p;
  543. goto undo;
  544. }
  545. }
  546. return 0;
  547. undo:
  548. list_for_each(l, &hai->mob_net_prefixes) {
  549. struct prefix_list_entry *p;
  550. p = list_entry(l, struct prefix_list_entry, list);
  551. route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
  552. &p->ple_prefix, p->ple_plen, &in6addr_any, 0, NULL);
  553. if (p == pe)
  554. break;
  555. }
  556. return -1;
  557. }
  558. static int mn_tnl_state_add(struct home_addr_info *hai, int ifindex, int all)
  559. {
  560. int err = 0;
  561. if (hai->home_reg_status != HOME_REG_NONE) {
  562. if ((err = mn_ro_pol_add(hai, ifindex, all)) < 0)
  563. return err;
  564. if ((err = route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP, 0,
  565. IP6_RT_PRIO_MIP6_OUT, &in6addr_any, 0,
  566. &in6addr_any, 0, NULL)) < 0) {
  567. mn_ro_pol_del(hai, ifindex, all);
  568. }
  569. }
  570. if (hai->mob_rtr &&
  571. (err = nemo_mr_tnl_routes_add(hai, ifindex)) < 0) {
  572. route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT,
  573. &hai->hoa.addr, 128, &in6addr_any, 0, NULL);
  574. mn_ro_pol_del(hai, ifindex, all);
  575. }
  576. return err;
  577. }
  578. static void nemo_mr_tnl_routes_del(struct home_addr_info *hai, int ifindex)
  579. {
  580. struct list_head *l;
  581. list_for_each(l, &hai->mob_net_prefixes) {
  582. struct prefix_list_entry *p;
  583. p = list_entry(l, struct prefix_list_entry, list);
  584. route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
  585. &p->ple_prefix, p->ple_plen, &in6addr_any, 0, NULL);
  586. }
  587. }
  588. static void mn_tnl_state_del(struct home_addr_info *hai, int ifindex, int all)
  589. {
  590. if (hai->home_reg_status != HOME_REG_NONE) {
  591. if (hai->mob_rtr)
  592. nemo_mr_tnl_routes_del(hai, ifindex);
  593. route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT,
  594. &hai->hoa.addr, 128, &in6addr_any, 0, NULL);
  595. mn_ro_pol_del(hai, ifindex, all);
  596. }
  597. }
  598. static void mn_home_ext_cleanup(struct bulentry *bule)
  599. {
  600. struct home_addr_info *hai = bule->home;
  601. hai->home_reg_status = HOME_REG_NONE;
  602. if (hai->pend_ba) {
  603. hai->pend_ba = 0;
  604. pending_bas--;
  605. }
  606. bule->ext_cleanup = NULL;
  607. }
  608. /* Clean up policy route for HoA when bulentry is deleted. */
  609. static void mn_pol_ext_cleanup(struct bulentry *bule)
  610. {
  611. MDBG("\n");
  612. mpd_cancel_mps(&bule->hoa, &bule->peer_addr);
  613. mn_tnl_state_del(bule->home, bule->home->if_tunnel, 0);
  614. if (conf.UseMnHaIPsec) {
  615. mn_ipsec_tnl_update(&bule->peer_addr, &bule->hoa, bule);
  616. mn_ipsec_tnl_pol_del(&bule->peer_addr, &bule->hoa, bule);
  617. }
  618. bule->ext_cleanup = mn_home_ext_cleanup;
  619. }
  620. static int process_first_home_bu(struct bulentry *bule,
  621. struct home_addr_info *hai,
  622. struct timespec *lifetime)
  623. {
  624. int err = 0;
  625. bule->type = BUL_ENTRY;
  626. bule->flags = (IP6_MH_BU_HOME | IP6_MH_BU_ACK |
  627. hai->lladdr_comp | hai->mob_rtr);
  628. if (conf.UseMnHaIPsec && conf.KeyMngMobCapability)
  629. bule->flags |= IP6_MH_BU_KEYM;
  630. bule->coa_changed = -1;
  631. bule->coa = hai->primary_coa.addr;
  632. bule->if_coa = hai->primary_coa.iif;
  633. bule->lifetime = *lifetime;
  634. bule->delay = conf.InitialBindackTimeoutFirstReg_ts;
  635. bule->callback = bu_resend;
  636. /* Use alt. coa with IPsec */
  637. bule->use_alt_coa = 1;
  638. bule->ext_cleanup = mn_pol_ext_cleanup;
  639. bule->home = hai;
  640. bule->consecutive_resends = 0;
  641. hai->home_reg_status = HOME_REG_UNCERTAIN;
  642. if ((err = mn_tnl_state_add(hai, hai->if_tunnel, 0)) < 0)
  643. MDBG("Failed to initialize new bule for HA\n");
  644. else
  645. MDBG("New bule for HA\n");
  646. return err;
  647. }
  648. static int mn_do_dad(struct home_addr_info *hai, int dereg);
  649. static void mn_send_home_na(struct home_addr_info *hai);
  650. static int mn_bu_ratelimit(struct bulentry *e)
  651. {
  652. if (IN6_ARE_ADDR_EQUAL(&e->coa, &e->last_coa)) {
  653. if (e->wait_ack) {
  654. MDBG("Rate limit BU\n");
  655. return 1;
  656. }
  657. } else {
  658. e->wait_ack = 0;
  659. e->consecutive_resends = 0;
  660. e->coa_changed = 1;
  661. }
  662. return 0;
  663. }
  664. static void mn_send_home_bu(struct home_addr_info *hai)
  665. {
  666. struct bulentry *bule = NULL;
  667. struct timespec lifetime;
  668. int homereg_expired = 0;
  669. movement_t type_movement = MIP6_TYPE_MOVEMENT_UNKNOWN;
  670. TRACE;
  671. if (IN6_IS_ADDR_UNSPECIFIED(&hai->ha_addr)) {
  672. MDBG("HA not set for home link\n");
  673. return;
  674. }
  675. mn_get_home_lifetime(hai, &lifetime, 0);
  676. if ((bule = bul_get(hai, NULL, &hai->ha_addr)) == NULL) {
  677. assert(!hai->at_home);
  678. /* Create new bul entry for HA */
  679. if (!tsisset(lifetime)) {
  680. dbg("HoA or CoA expired, unable to create binding.\n");
  681. return;
  682. }
  683. if (conf.UseMnHaIPsec &&
  684. !ipsec_policy_entry_check(&hai->ha_addr, &hai->hoa.addr,
  685. IPSEC_F_MH_BUBA)) {
  686. syslog(LOG_ERR,
  687. "MN lacks the necessary IPsec policies for "
  688. "protecting the home registration to HA "
  689. "%x:%x:%x:%x:%x:%x:%x:%x\n",
  690. NIP6ADDR(&hai->ha_addr));
  691. if (hai->use_dhaad)
  692. mn_change_ha(hai);
  693. return;
  694. }
  695. bule = create_bule(&hai->hoa.addr, &hai->ha_addr);
  696. if (bule == NULL)
  697. return;
  698. if (process_first_home_bu(bule, hai, &lifetime) < 0 ||
  699. bul_add(bule) < 0) {
  700. bul_delete(bule);
  701. return;
  702. }
  703. type_movement = MIP6_TYPE_MOVEMENT_HL2FL;
  704. MDBG("New bule for HA\n");
  705. } else if (bule->type == BUL_ENTRY) {
  706. /* Update bule */
  707. clock_gettime(CLOCK_REALTIME, &bule->lastsent);
  708. if (IN6_ARE_ADDR_EQUAL(&bule->hoa, &bule->coa)) {
  709. if (process_first_home_bu(bule,
  710. hai, &lifetime) < 0) {
  711. bul_delete(bule);
  712. return;
  713. }
  714. type_movement = MIP6_TYPE_MOVEMENT_HL2FL;
  715. } else {
  716. bule->coa = hai->primary_coa.addr;
  717. bule->if_coa = hai->primary_coa.iif;
  718. /* Rate limiting home registration binding updates
  719. is necessary for multihomed MNs */
  720. if (mn_bu_ratelimit(bule))
  721. return;
  722. if (!hai->at_home) {
  723. MDBG("Moved to foreign network\n");
  724. bule->lifetime = lifetime;
  725. type_movement = MIP6_TYPE_MOVEMENT_FL2FL;
  726. bul_iterate(&hai->bul, mn_bule_ro_pol_del, NULL);
  727. } else {
  728. MDBG("Moved to home network\n");
  729. type_movement = MIP6_TYPE_MOVEMENT_FL2HL;
  730. tsclear(bule->lifetime);
  731. mn_pol_ext_cleanup(bule);
  732. }
  733. bule->delay = conf.InitialBindackTimeoutReReg_ts;
  734. bule->callback = bu_resend;
  735. }
  736. bule->seq++;
  737. pre_bu_bul_update(bule);
  738. MDBG("Bule for HA exists. Updating it.\n");
  739. } else {
  740. MDBG("HA doesn't accept BU\n");
  741. return;
  742. }
  743. if (type_movement == MIP6_TYPE_MOVEMENT_FL2HL) {
  744. if (tsisset(bule->hard_expire) &&
  745. tsafter(bule->hard_expire, bule->lastsent)) {
  746. /* If MN returns to home link after the expiration of
  747. * home registration, MN does not send de-reg BU to HA
  748. */
  749. homereg_expired = 1;
  750. }
  751. }
  752. if (!homereg_expired) {
  753. bule->do_send_bu = 1;
  754. mn_send_bu_msg(bule);
  755. bul_update_timer(bule);
  756. if (conf.OptimisticHandoff)
  757. post_ba_bul_update(bule);
  758. }
  759. if (conf.UseMnHaIPsec) {
  760. /* create SP entry for protecting RR signals */
  761. if (type_movement == MIP6_TYPE_MOVEMENT_HL2FL) {
  762. mn_ipsec_tnl_pol_add(&bule->home->ha_addr,
  763. &bule->hoa, bule);
  764. }
  765. /* migrate tunnel endpoint */
  766. if (bule->coa_changed &&
  767. type_movement != MIP6_TYPE_MOVEMENT_FL2HL) {
  768. mn_ipsec_tnl_update(&bule->home->ha_addr,
  769. &bule->hoa, bule);
  770. }
  771. }
  772. /* Before bul_iterate, tunnel modification should be done. */
  773. tunnel_mod(hai->if_tunnel, &hai->primary_coa.addr, &hai->ha_addr,
  774. hai->primary_coa.iif, mn_ext_tunnel_ops, hai);
  775. bule->last_coa = bule->coa;
  776. bule->coa_changed = 0;
  777. if (homereg_expired) {
  778. bul_delete(bule);
  779. mn_do_dad(hai, 1);
  780. }
  781. }
  782. void mn_send_cn_bu(struct bulentry *bule)
  783. {
  784. /* Rate limiting CN registration binding updates
  785. is necessary for multihomed MNs */
  786. if (mn_bu_ratelimit(bule))
  787. return;
  788. mn_get_ro_lifetime(bule->home, &bule->lifetime, bule->dereg);
  789. bule->seq++;
  790. clock_gettime(CLOCK_REALTIME, &bule->lastsent);
  791. pre_bu_bul_update(bule);
  792. mn_send_bu_msg(bule);
  793. bule->last_coa = bule->coa;
  794. bule->coa_changed = 0;
  795. if (bule->flags & IP6_MH_BU_ACK) {
  796. bule->callback = bu_resend;
  797. bule->delay = conf.InitialBindackTimeoutReReg_ts;
  798. } else {
  799. if (bule->dereg) {
  800. bul_delete(bule);
  801. return;
  802. }
  803. bule->callback = mn_rr_check_entry;
  804. bule->delay = bule->lifetime;
  805. tsadd(bule->lastsent, bule->lifetime, bule->hard_expire);
  806. bule->do_send_bu = 0;
  807. post_ba_bul_update(bule);
  808. }
  809. bul_update_expire(bule);
  810. bul_update_timer(bule);
  811. }
  812. /* Sets lifetime and expire of bulentry based on lifetime of received BA
  813. * @bule: corresponding bul entry
  814. * @ba_lifetime: lifetime from BA
  815. * @bu_resend: refresh in seconds
  816. */
  817. static inline int set_bule_lifetime(struct bulentry *bule,
  818. struct timespec *ba_lifetime,
  819. struct timespec *br_advice)
  820. {
  821. assert(bule->type == BUL_ENTRY);
  822. bule->lifetime = tsmin(bule->lifetime, *ba_lifetime);
  823. if (bule->flags & IP6_MH_BU_HOME) {
  824. tssetsec(bule->delay, bule->lifetime.tv_sec * BU_REFRESH_DELAY);
  825. if (tsbefore(bule->delay, *br_advice))
  826. bule->delay = *br_advice;
  827. } else {
  828. tssetsec(bule->delay, max(ba_lifetime->tv_sec, 0));
  829. }
  830. dbg("Set bule lifetime to %ld (s) and resend to bule->delay %d (s)\n",
  831. bule->lifetime.tv_sec, bule->delay.tv_sec);
  832. return 0;
  833. }
  834. static void mn_send_home_na(struct home_addr_info *hai)
  835. {
  836. uint32_t na_flags = ND_NA_FLAG_OVERRIDE;
  837. ndisc_send_na(hai->hoa.iif, &hai->hoa.addr,
  838. &in6addr_all_nodes_mc, &hai->hoa.addr, na_flags);
  839. if (hai->lladdr_comp && hai->home_reg_status != HOME_REG_NONE) {
  840. struct in6_addr lladdr;
  841. ipv6_addr_llocal(&hai->hoa.addr, &lladdr);
  842. ndisc_send_na(hai->hoa.iif, &lladdr,
  843. &in6addr_all_nodes_mc,
  844. &lladdr, na_flags);
  845. }
  846. }
  847. /* Returns number of pending BAs, when it is 0, MN can start registering the
  848. addresses on the link as CoAs
  849. */
  850. static int mn_dereg_home(struct home_addr_info *hai)
  851. {
  852. if (hai->pend_ba) {
  853. hai->pend_ba = 0;
  854. pending_bas--;
  855. if (hai->at_home)
  856. mn_send_home_na(hai);
  857. }
  858. return 0;
  859. }
  860. static int mn_chk_bauth(struct ip6_mh_binding_ack *ba, ssize_t len,
  861. const struct mh_options *mh_opts,
  862. struct bulentry *e)
  863. {
  864. struct ip6_mh_opt_auth_data *bauth;
  865. uint8_t status = ba->ip6mhba_status;
  866. if ((bauth = mh_opt(&ba->ip6mhba_hdr, mh_opts, IP6_MHOPT_BAUTH))) {
  867. /* Authenticator is calculated with MH checksum set to 0 */
  868. ba->ip6mhba_hdr.ip6mh_cksum = 0;
  869. return mh_verify_auth_data(ba, len, bauth,
  870. &e->coa, &e->peer_addr, e->Kbm);
  871. }
  872. if (e->seq == ntohs(ba->ip6mhba_seqno)) {
  873. if (status == IP6_MH_BAS_HOME_NI_EXPIRED) {
  874. /* resend Hoti */
  875. e->rr.state = RR_H_EXPIRED;
  876. } else if (status == IP6_MH_BAS_COA_NI_EXPIRED) {
  877. /* resend CoTi */
  878. e->rr.state = RR_C_EXPIRED;
  879. } else if (status == IP6_MH_BAS_NI_EXPIRED){
  880. e->rr.state = RR_EXPIRED;
  881. }
  882. mn_rr_force_refresh(e);
  883. mn_reset_ro_bule(e);
  884. pre_bu_bul_update(e);
  885. }
  886. return -1;
  887. }
  888. static void mn_recv_ba(const struct ip6_mh *mh, ssize_t len,
  889. const struct in6_addr_bundle *in,
  890. __attribute__ ((unused)) int iif)
  891. {
  892. struct ip6_mh_binding_ack *ba;
  893. struct mh_options mh_opts;
  894. struct bulentry *bule;
  895. struct timespec now, ba_lifetime, br_adv, mps_delay;
  896. uint16_t seqno;
  897. TRACE;
  898. if (len < 0 || (size_t)len < sizeof(struct ip6_mh_binding_ack) ||
  899. mh_opt_parse(mh, len,
  900. sizeof(struct ip6_mh_binding_ack), &mh_opts) < 0)
  901. return;
  902. ba = (struct ip6_mh_binding_ack *)mh;
  903. pthread_rwlock_wrlock(&mn_lock);
  904. bule = bul_get(NULL, in->dst, in->src);
  905. if (!bule || bule->type != BUL_ENTRY) {
  906. MDBG("Got BA without corresponding BUL entry "
  907. "from %x:%x:%x:%x:%x:%x:%x:%x "
  908. "to home address %x:%x:%x:%x:%x:%x:%x:%x "
  909. "with coa %x:%x:%x:%x:%x:%x:%x:%x\n",
  910. NIP6ADDR(in->src),
  911. NIP6ADDR(in->dst),
  912. NIP6ADDR(in->local_coa != NULL ?
  913. in->local_coa : &in6addr_any));
  914. pthread_rwlock_unlock(&mn_lock);
  915. return;
  916. }
  917. dbg("Got BA from %x:%x:%x:%x:%x:%x:%x:%x "
  918. "to home address %x:%x:%x:%x:%x:%x:%x:%x "
  919. "with coa %x:%x:%x:%x:%x:%x:%x:%x and status %d\n",
  920. NIP6ADDR(in->src), NIP6ADDR(in->dst),
  921. NIP6ADDR(in->local_coa != NULL ? in->local_coa : &in6addr_any),
  922. ba->ip6mhba_status);
  923. dbg("Dumping corresponding BULE\n");
  924. dbg_func(bule, dump_bule);
  925. /* First check authenticator */
  926. if (!(bule->flags & IP6_MH_BU_HOME) &&
  927. mn_chk_bauth(ba, len, &mh_opts, bule)) {
  928. pthread_rwlock_unlock(&mn_lock);
  929. return;
  930. }
  931. /* Then sequence number */
  932. seqno = ntohs(ba->ip6mhba_seqno);
  933. if (bule->seq != seqno) {
  934. if (ba->ip6mhba_status != IP6_MH_BAS_SEQNO_BAD) {
  935. /*
  936. * In this case, ignore BA and resends BU.
  937. */
  938. MDBG("Got BA with incorrect sequence number %d, "
  939. "the one sent in BU was %d\n", seqno, bule->seq);
  940. pthread_rwlock_unlock(&mn_lock);
  941. return;
  942. }
  943. }
  944. bule->do_send_bu = 0;
  945. bule->consecutive_resends = 0;
  946. clock_gettime(CLOCK_REALTIME, &now);
  947. if (ba->ip6mhba_status >= IP6_MH_BAS_UNSPECIFIED) {
  948. if (ba->ip6mhba_status == IP6_MH_BAS_SEQNO_BAD) {
  949. MDBG("out of sync seq nr\n");
  950. clock_gettime(CLOCK_REALTIME, &bule->lastsent);
  951. bule->seq = seqno + 1;
  952. if (bule->flags & IP6_MH_BU_HOME)
  953. mn_get_home_lifetime(bule->home,
  954. &bule->lifetime, 0);
  955. else
  956. mn_get_ro_lifetime(bule->home,
  957. &bule->lifetime, 0);
  958. bule->callback = bu_resend;
  959. pre_bu_bul_update(bule);
  960. mn_send_bu_msg(bule);
  961. bule->delay = conf.InitialBindackTimeoutReReg_ts;
  962. bul_update_timer(bule);
  963. if (bule->flags & IP6_MH_BU_HOME &&
  964. conf.OptimisticHandoff) {
  965. post_ba_bul_update(bule);
  966. }
  967. pthread_rwlock_unlock(&mn_lock);
  968. return;
  969. }
  970. if (bule->flags & IP6_MH_BU_HOME) {
  971. struct home_addr_info *hai = bule->home;
  972. char err_str[MAX_BA_STATUS_STR_LEN];
  973. if (hai->at_home) {
  974. bul_delete(bule);
  975. mn_do_dad(hai, 1);
  976. pthread_rwlock_unlock(&mn_lock);
  977. return;
  978. }
  979. mh_ba_status_to_str(ba->ip6mhba_status, err_str);
  980. syslog(LOG_ERR, "Received BA with error status %s. "
  981. "Unable to register with HA. Deleting entry\n",
  982. err_str);
  983. if (hai->use_dhaad) {
  984. bule_invalidate(bule, &now, 0);
  985. mn_change_ha(hai);
  986. } else {
  987. bule_invalidate(bule, &now, 1);
  988. }
  989. pthread_rwlock_unlock(&mn_lock);
  990. return;
  991. } else {
  992. /* Don't resend BUs to this CN */
  993. bule_invalidate(bule, &now, 1);
  994. pthread_rwlock_unlock(&mn_lock);
  995. return;
  996. }
  997. }
  998. if (bule->wait_ack)
  999. bule->wait_ack = 0;
  1000. else {
  1001. MDBG("unexpected BA, ignoring\n");
  1002. pthread_rwlock_unlock(&mn_lock);
  1003. return;
  1004. }
  1005. tssetsec(ba_lifetime, ntohs(ba->ip6mhba_lifetime) << 2);
  1006. br_adv = ba_lifetime;
  1007. tsadd(bule->lastsent, ba_lifetime, bule->hard_expire);
  1008. if (!(bule->flags & IP6_MH_BU_HOME) || !conf.OptimisticHandoff)
  1009. post_ba_bul_update(bule);
  1010. if (bule->flags & IP6_MH_BU_HOME) {
  1011. struct home_addr_info *hai = bule->home;
  1012. struct ip6_mh_opt_refresh_advice *bra;
  1013. if (bule->flags & IP6_MH_BU_MR &&
  1014. !(ba->ip6mhba_flags & IP6_MH_BA_MR)) {
  1015. if (hai->use_dhaad) {
  1016. mn_change_ha(hai);
  1017. } else {
  1018. int one = 1;
  1019. bul_iterate(&hai->bul, mn_dereg, &one);
  1020. }
  1021. pthread_rwlock_unlock(&mn_lock);
  1022. return;
  1023. }
  1024. if (!tsisset(ba_lifetime)) {
  1025. int type = FLUSH_FAILED;
  1026. mn_dereg_home(hai);
  1027. bul_delete(bule);
  1028. /* If BA was for home registration & succesful
  1029. * Send RO BUs to CNs for this home address.
  1030. */
  1031. bul_iterate(&hai->bul, _bul_flush, &type);
  1032. bul_iterate(&hai->bul, mn_rr_start_handoff, NULL);
  1033. pthread_rwlock_unlock(&mn_lock);
  1034. mn_movement_event(NULL);
  1035. mn_block_rule_del(hai);
  1036. return;
  1037. }
  1038. /* If status of BA is 0 or 1, Binding Update is accepted. */
  1039. if (ba->ip6mhba_status == IP6_MH_BAS_PRFX_DISCOV){
  1040. mpd_trigger_mps(&bule->hoa, &bule->peer_addr);
  1041. }else if( hai->home_reg_status == HOME_REG_UNCERTAIN && tsisset(ba_lifetime)){
  1042. if(tsisset(hai->hoa.timestamp)){
  1043. mps_delay = tsmin(hai->hoa.valid_time, ba_lifetime);
  1044. mpd_schedule_first_mps(&bule->hoa, &bule->peer_addr, &mps_delay);
  1045. }else
  1046. mpd_trigger_mps(&bule->hoa, &bule->peer_addr);
  1047. }
  1048. /* If BA was for home registration & succesful
  1049. * Send RO BUs to CNs for this home address.
  1050. */
  1051. hai->home_reg_status = HOME_REG_VALID;
  1052. bul_iterate(&hai->bul, mn_rr_start_handoff, NULL);
  1053. /* IP6_MH_BA_KEYM */
  1054. if (bule->flags & IP6_MH_BU_KEYM) {
  1055. if (ba->ip6mhba_flags & IP6_MH_BA_KEYM) {
  1056. /* Inform IKE to send readdress msg */
  1057. } else {
  1058. /* Inform IKE to renegotiate SAs */
  1059. /* Remove the flag from this bule */
  1060. bule->flags &= ~IP6_MH_BU_KEYM;
  1061. /* Issue a warning */
  1062. syslog(LOG_ERR,
  1063. "HA does not support IKE session surviving, "
  1064. "traffic may be interrupted after movements.\n"
  1065. );
  1066. }
  1067. }
  1068. bra = mh_opt(&ba->ip6mhba_hdr, &mh_opts, IP6_MHOPT_BREFRESH);
  1069. if (bra)
  1070. tssetsec(br_adv, ntohs(bra->ip6mora_interval) << 2);
  1071. }
  1072. if (!tsisset(ba_lifetime)) {
  1073. dbg("Deleting bul entry\n");
  1074. bul_delete(bule);
  1075. } else {
  1076. set_bule_lifetime(bule, &ba_lifetime, &br_adv);
  1077. if (bule->flags & IP6_MH_BU_HOME) {
  1078. dbg("Callback to bu_refresh after %d seconds\n",
  1079. bule->delay.tv_sec);
  1080. bule->callback = bu_refresh;
  1081. } else {
  1082. dbg("Callback to mn_rr_check_entry after %d seconds\n",
  1083. bule->delay.tv_sec);
  1084. bule->callback = mn_rr_check_entry;
  1085. }
  1086. bul_update_expire(bule);
  1087. bul_update_timer(bule);
  1088. }
  1089. pthread_rwlock_unlock(&mn_lock);
  1090. }
  1091. static struct mh_handler mn_ba_handler = {
  1092. .recv = mn_recv_ba,
  1093. };
  1094. static int do_handoff(struct home_addr_info *hai)
  1095. {
  1096. if (!IN6_IS_ADDR_UNSPECIFIED(&hai->ha_addr)) {
  1097. if (hai->pend_ba)
  1098. mn_send_home_bu(hai);
  1099. else if (!pending_bas) {
  1100. if (!hai->at_home ||
  1101. hai->home_reg_status != HOME_REG_NONE)
  1102. mn_send_home_bu(hai);
  1103. bul_iterate(&hai->bul, mn_rr_start_handoff, NULL);
  1104. hai->verdict = MN_HO_NONE;
  1105. }
  1106. } else if (!pending_bas) {
  1107. if (hai->at_home)
  1108. dhaad_stop(hai);
  1109. else
  1110. dhaad_start(hai);
  1111. }
  1112. return 0;
  1113. }
  1114. struct home_addr_info *mn_get_home_addr(const struct in6_addr *hoa)
  1115. {
  1116. struct list_head *l;
  1117. list_for_each(l, &home_addr_list) {
  1118. struct home_addr_info *hai;
  1119. hai = list_entry(l, struct home_addr_info, list);
  1120. if (IN6_ARE_ADDR_EQUAL(hoa, &hai->hoa.addr))
  1121. return hai;
  1122. }
  1123. return NULL;
  1124. }
  1125. struct home_addr_info *mn_get_home_addr_by_dhaadid(uint16_t dhaad_id)
  1126. {
  1127. struct list_head *lh;
  1128. list_for_each(lh, &home_addr_list) {
  1129. struct home_addr_info *hai;
  1130. hai = list_entry(lh, struct home_addr_info, list);
  1131. pthread_mutex_lock(&hai->ha_list.c_lock);
  1132. if (hai->ha_list.dhaad_id == dhaad_id) {
  1133. pthread_mutex_unlock(&hai->ha_list.c_lock);
  1134. return hai;
  1135. }
  1136. pthread_mutex_unlock(&hai->ha_list.c_lock);
  1137. }
  1138. return NULL;
  1139. }
  1140. struct flag_hoa_args {
  1141. struct home_addr_info *target;
  1142. int flag;
  1143. };
  1144. static int flag_hoa(struct ifaddrmsg *ifa, struct rtattr *rta_tb[], void *arg)
  1145. {
  1146. /*
  1147. * To do: also call this function for addresses learned through MPD
  1148. */
  1149. struct flag_hoa_args *fhoa = arg;
  1150. struct home_addr_info *hai = fhoa->target;
  1151. struct mn_addr *hoa = &hai->hoa;
  1152. struct in6_addr *addr = RTA_DATA(rta_tb[IFA_ADDRESS]);
  1153. struct timespec now;
  1154. uint32_t preferred;
  1155. uint32_t valid;
  1156. int err, plen;
  1157. if (hai->if_tunnel >= 0 && ifa->ifa_index == (uint32_t)hai->if_tunnel)
  1158. plen = 128;
  1159. else
  1160. plen = hai->plen;
  1161. clock_gettime(CLOCK_REALTIME, &now);
  1162. if (rta_tb[IFA_CACHEINFO] != NULL) {
  1163. struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
  1164. mn_update_hoa_lifetime(hoa, &now,
  1165. ci->ifa_valid, ci->ifa_prefered);
  1166. valid = ci->ifa_valid;
  1167. preferred = ci->ifa_prefered;
  1168. } else {
  1169. preferred = mpd_curr_lft(&now,
  1170. &hoa->timestamp,
  1171. hoa->preferred_time.tv_sec);
  1172. valid = mpd_curr_lft(&now,
  1173. &hoa->timestamp,
  1174. hoa->valid_time.tv_sec);
  1175. }
  1176. if (fhoa->flag)
  1177. ifa->ifa_flags |= IFA_F_HOMEADDRESS_NODAD;
  1178. else
  1179. ifa->ifa_flags &= ~IFA_F_HOMEADDRESS_NODAD;
  1180. MDBG("set HoA %x:%x:%x:%x:%x:%x:%x:%x/%d iif %d flags %x preferred_time %u valid_time %u\n",
  1181. NIP6ADDR(addr), plen, ifa->ifa_index, ifa->ifa_flags, preferred, valid);
  1182. if ((err = addr_add(addr, plen,
  1183. ifa->ifa_flags, ifa->ifa_scope, ifa->ifa_index,
  1184. preferred, valid)) < 0) {
  1185. MDBG("failed with %d\n", err);
  1186. return err;
  1187. }
  1188. hoa->iif = ifa->ifa_index;
  1189. return 0;
  1190. }
  1191. static void nemo_mr_rules_del(struct home_addr_info *hinfo)
  1192. {
  1193. struct list_head *l;
  1194. list_for_each(l, &hinfo->mob_net_prefixes) {
  1195. struct prefix_list_entry *p = NULL;
  1196. p = list_entry(l, struct prefix_list_entry, list);
  1197. rule_del(NULL, RT6_TABLE_MIP6,
  1198. IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
  1199. &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0);
  1200. rule_del(NULL, RT6_TABLE_MAIN,
  1201. IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
  1202. &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
  1203. }
  1204. }
  1205. static int nemo_mr_rules_add(struct home_addr_info *hinfo)
  1206. {
  1207. struct prefix_list_entry *pe = NULL;
  1208. struct list_head *l;
  1209. list_for_each(l, &hinfo->mob_net_prefixes) {
  1210. struct prefix_list_entry *p = NULL;
  1211. p = list_entry(l, struct prefix_list_entry, list);
  1212. if (rule_add(NULL, RT6_TABLE_MAIN,
  1213. IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
  1214. &in6addr_any, 0,
  1215. &p->ple_prefix, p->ple_plen, 0) < 0) {
  1216. pe = p;
  1217. goto undo;
  1218. }
  1219. if (rule_add(NULL, RT6_TABLE_MIP6,
  1220. IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
  1221. &p->ple_prefix, p->ple_plen,
  1222. &in6addr_any, 0, 0) < 0) {
  1223. rule_del(NULL, RT6_TABLE_MAIN,
  1224. IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
  1225. &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
  1226. pe = p;
  1227. goto undo;
  1228. }
  1229. }
  1230. return 0;
  1231. undo:
  1232. list_for_each(l, &hinfo->mob_net_prefixes) {
  1233. struct prefix_list_entry *p = NULL;
  1234. p = list_entry(l, struct prefix_list_entry, list);
  1235. rule_del(NULL, RT6_TABLE_MIP6,
  1236. IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
  1237. &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0);
  1238. rule_del(NULL, RT6_TABLE_MAIN,
  1239. IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
  1240. &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
  1241. if (p == pe)
  1242. break;
  1243. }
  1244. return -1;
  1245. }
  1246. static void clean_home_addr_info(struct home_addr_info *hai)
  1247. {
  1248. struct flag_hoa_args arg;
  1249. int plen = (hai->hoa.iif == hai->if_tunnel ? 128 : hai->plen);
  1250. list_del(&hai->list);
  1251. if (hai->mob_rtr)
  1252. nemo_mr_rules_del(hai);
  1253. arg.target = hai;
  1254. arg.flag = 0;
  1255. addr_do(&hai->hoa.addr, plen,
  1256. hai->hoa.iif, &arg, flag_hoa);
  1257. bul_iterate(&hai->bul, mn_dereg, NULL);
  1258. bul_home_cleanup(&hai->bul);
  1259. mn_block_rule_del(hai);
  1260. rule_del(NULL, RT6_TABLE_MIP6,
  1261. IP6_RULE_PRIO_MIP6_HOA_OUT, RTN_UNICAST,
  1262. &hai->hoa.addr, 128, &in6addr_any, 0, FIB_RULE_FIND_SADDR);
  1263. tunnel_del(hai->if_tunnel, NULL, NULL);
  1264. dhaad_stop(hai);
  1265. free(hai);
  1266. }
  1267. static int rpl_copy(const struct list_head *rpl1, struct list_head *rpl2)
  1268. {
  1269. struct list_head *l, *n;
  1270. struct xfrm_ro_pol *rp1, *rp2;
  1271. list_for_each(l, rpl1) {
  1272. rp1 = list_entry(l, struct xfrm_ro_pol, list);
  1273. rp2 = malloc(sizeof(struct xfrm_ro_pol));
  1274. if (rp2 == NULL)
  1275. goto undo;
  1276. memcpy(rp2, rp1, sizeof(struct xfrm_ro_pol));
  1277. list_add_tail(&rp2->list, rpl2);
  1278. }
  1279. return 0;
  1280. undo:
  1281. list_for_each_safe(l, n, rpl2) {
  1282. list_del(l);
  1283. rp2 = list_entry(l, struct xfrm_ro_pol, list);
  1284. free(rp2);
  1285. }
  1286. return -1;
  1287. }
  1288. static struct home_addr_info *hai_copy(struct home_addr_info *conf_hai)
  1289. {
  1290. struct home_addr_info *hai = malloc(sizeof(struct home_addr_info));
  1291. if (hai != NULL) {
  1292. pthread_mutexattr_t mattrs;
  1293. pthread_mutexattr_init(&mattrs);
  1294. pthread_mutexattr_settype(&mattrs, PTHREAD_MUTEX_FAST_NP);
  1295. memcpy(hai, conf_hai, sizeof(struct home_addr_info));
  1296. if (pthread_mutex_init(&hai->ha_list.c_lock, NULL))
  1297. goto undo;
  1298. INIT_LIST_HEAD(&hai->mob_net_prefixes);
  1299. if (hai->mob_rtr &&
  1300. prefix_list_copy(&conf_hai->mob_net_prefixes,
  1301. &hai->mob_net_prefixes) < 0)
  1302. goto mutex_undo;
  1303. INIT_LIST_HEAD(&hai->ro_policies);
  1304. if (rpl_copy(&conf_hai->ro_policies, &hai->ro_policies) < 0)
  1305. goto mnp_undo;
  1306. INIT_LIST_HEAD(&hai->ha_list.tqe.list);
  1307. INIT_LIST_HEAD(&hai->ha_list.home_agents);
  1308. }
  1309. return hai;
  1310. mnp_undo:
  1311. prefix_list_free(&hai->mob_net_prefixes);
  1312. mutex_undo:
  1313. pthread_mutex_destroy(&hai->ha_list.c_lock);
  1314. undo:
  1315. free(hai);
  1316. return NULL;
  1317. }
  1318. static int conf_home_addr_info(struct home_addr_info *conf_hai)
  1319. {
  1320. struct list_head *list, *n;
  1321. struct timespec init = { 0, 0 };
  1322. struct flag_hoa_args arg;
  1323. struct home_addr_info *hai;
  1324. MDBG("HoA address %x:%x:%x:%x:%x:%x:%x:%x\n",
  1325. NIP6ADDR(&conf_hai->hoa.addr));
  1326. if ((hai = hai_copy(conf_hai)) == NULL)
  1327. goto err;
  1328. if (hai->mob_rtr) {
  1329. MDBG("is Mobile Router\n");
  1330. list_for_each(list, &hai->mob_net_prefixes) {
  1331. struct prefix_list_entry *p;
  1332. p = list_entry(list, struct prefix_list_entry, list);
  1333. MDBG("Mobile Network Prefix %x:%x:%x:%x:%x:%x:%x:%x/%d\n",
  1334. NIP6ADDR(&p->ple_prefix), p->ple_plen);
  1335. }
  1336. }
  1337. if (IN6_IS_ADDR_UNSPECIFIED(&hai->ha_addr)) {
  1338. hai->use_dhaad = 1;
  1339. } else {
  1340. MDBG("HA address %x:%x:%x:%x:%x:%x:%x:%x\n",
  1341. NIP6ADDR(&hai->ha_addr));
  1342. }
  1343. hai->if_tunnel = tunnel_add(&hai->hoa.addr, &hai->ha_addr,
  1344. hai->if_home, NULL, NULL);
  1345. if (hai->if_tunnel <= 0) {
  1346. MDBG("failed to create MN-HA tunnel\n");
  1347. goto clean_err;
  1348. }
  1349. if (rule_add(NULL, RT6_TABLE_MIP6,
  1350. IP6_RULE_PRIO_MIP6_HOA_OUT, RTN_UNICAST,
  1351. &hai->hoa.addr, 128, &in6addr_any, 0, FIB_RULE_FIND_SADDR) < 0) {
  1352. goto clean_err;
  1353. }
  1354. if (mn_block_rule_add(hai) < 0)
  1355. goto clean_err;
  1356. if(bul_home_init(hai)) {
  1357. goto clean_err;
  1358. }
  1359. MDBG("Home address %x:%x:%x:%x:%x:%x:%x:%x\n",
  1360. NIP6ADDR(&hai->hoa.addr));
  1361. hai->home_reg_status = HOME_REG_NONE;
  1362. hai->verdict = MN_HO_NONE;
  1363. mn_update_hoa_lifetime(&hai->hoa, &init,
  1364. PREFIX_LIFETIME_INFINITE,
  1365. PREFIX_LIFETIME_INFINITE);
  1366. arg.target = hai;
  1367. arg.flag = 1;
  1368. if (addr_do(&hai->hoa.addr, 128,
  1369. hai->if_tunnel, &arg, flag_hoa) < 0) {
  1370. goto clean_err;
  1371. }
  1372. if (hai->mob_rtr && nemo_mr_rules_add(hai) < 0) {
  1373. goto clean_err;
  1374. }
  1375. hai->at_home = hai->hoa.iif == hai->if_home;
  1376. pthread_rwlock_wrlock(&mn_lock);
  1377. list_add(&hai->list, &home_addr_list);
  1378. pthread_rwlock_unlock(&mn_lock);
  1379. MDBG("Added new home_addr_info successfully\n");
  1380. return 0;
  1381. clean_err:
  1382. clean_home_addr_info(hai);
  1383. err:
  1384. list_for_each_safe(list, n, &home_addr_list) {
  1385. hai = list_entry(list, struct home_addr_info, list);
  1386. clean_home_addr_info(hai);
  1387. }
  1388. return -1;
  1389. }
  1390. static int mn_home_reg_addr_expires(struct bulentry *e, struct mn_addr *addr)
  1391. {
  1392. struct timespec next_bu, addr_expires;
  1393. if (prefix_lft_infinite(addr->valid_time.tv_sec))
  1394. return 0;
  1395. tsadd(e->lastsent, e->delay, next_bu);
  1396. tsadd(addr->timestamp, addr->valid_time, addr_expires);
  1397. if (!tsbefore(next_bu, addr_expires))
  1398. return 0;
  1399. e->consecutive_resends = 0;
  1400. return 1;
  1401. }
  1402. static int update_hoa(struct ifaddrmsg *ifa,
  1403. __attribute__ ((unused)) struct rtattr *rta_tb[],
  1404. void *arg)
  1405. {
  1406. struct home_addr_info *hai = arg;
  1407. return addr_add(&hai->hoa.addr, 128, ifa->ifa_flags,
  1408. ifa->ifa_scope, hai->hoa.iif,
  1409. hai->hoa.preferred_time.tv_sec,
  1410. hai->hoa.valid_time.tv_sec);
  1411. }
  1412. int mn_update_home_prefix(struct home_addr_info *hai,
  1413. const struct timespec *timestamp,
  1414. const struct nd_opt_prefix_info *pinfo)
  1415. {
  1416. struct timespec now;
  1417. struct nd_opt_prefix_info p;
  1418. uint32_t valid_time;
  1419. if (hai->plen != pinfo->nd_opt_pi_prefix_len ||
  1420. ipv6_pfx_cmp(&pinfo->nd_opt_pi_prefix, &hai->hoa.addr, hai->plen))
  1421. return 0;
  1422. clock_gettime(CLOCK_REALTIME, &now);
  1423. memcpy(&p, pinfo, sizeof(struct nd_opt_prefix_info));
  1424. p.nd_opt_pi_valid_time = mpd_curr_lft(&now,
  1425. timestamp,
  1426. p.nd_opt_pi_valid_time);
  1427. p.nd_opt_pi_preferred_time = mpd_curr_lft(&now,
  1428. timestamp,
  1429. p.nd_opt_pi_preferred_time);
  1430. /* todo: also add new HoAs */
  1431. MDBG2("preferred_life %u valid_life %u\n",
  1432. p.nd_opt_pi_preferred_time, p.nd_opt_pi_valid_time);
  1433. valid_time = mpd_curr_lft(&now, &hai->hoa.timestamp,
  1434. hai->hoa.valid_time.tv_sec);
  1435. mn_update_hoa_lifetime(&hai->hoa, &now, p.nd_opt_pi_valid_time,
  1436. p.nd_opt_pi_preferred_time);
  1437. if (hai->home_reg_status == HOME_REG_NONE) {
  1438. int plen = (hai->hoa.iif == hai->if_tunnel ? 128 : hai->plen);
  1439. /* check if HoA has expired and reinsert it */
  1440. if (valid_time == 0 && hai->hoa.valid_time.tv_sec) {
  1441. struct flag_hoa_args arg;
  1442. arg.target = hai;
  1443. arg.flag = 1;
  1444. addr_do(&hai->hoa.addr, plen,
  1445. hai->hoa.iif, &arg, flag_hoa);
  1446. }
  1447. } else if (hai->home_reg_status != HOME_REG_VALID) {
  1448. if (hai->hoa.valid_time.tv_sec) {
  1449. addr_do(&hai->hoa.addr, 128, hai->hoa.iif,
  1450. hai, update_hoa);
  1451. } else
  1452. addr_del(&hai->hoa.addr, 128, hai->hoa.iif);
  1453. }
  1454. if (!hai->at_home) {
  1455. struct bulentry *e;
  1456. e = bul_get(hai, NULL, &hai->ha_addr);
  1457. if (e == NULL || !(e->flags & IP6_MH_BU_HOME))
  1458. return -ENOENT;
  1459. /* check if new HoA lifetime is smaller than current
  1460. home registration lifetime */
  1461. MDBG2("preferred_time %u valid_life %u\n",
  1462. p.nd_opt_pi_preferred_time, p.nd_opt_pi_valid_time);
  1463. if (mn_home_reg_addr_expires(e, &hai->hoa)) {
  1464. MDBG("HoA expires before next BU, do_handoff()\n");
  1465. do_handoff(hai);
  1466. } else
  1467. hai->verdict = MN_HO_NONE;
  1468. if (p.nd_opt_pi_valid_time &&
  1469. !prefix_lft_infinite(p.nd_opt_pi_valid_time))
  1470. mpd_schedule_first_mps(&e->hoa, &e->peer_addr,
  1471. &hai->hoa.valid_time);
  1472. }
  1473. return 0;
  1474. }
  1475. /* Decide which CoA should be used for RO. Policy Manager is asked
  1476. * first. If it does not provide a hint, primary CoA is used. The
  1477. * function returns the ifindex of the interface the CoA is associated
  1478. * with and copies the CoA to 'coa'.
  1479. */
  1480. static int mn_get_ro_coa(const struct in6_addr *cn,
  1481. const struct home_addr_info *hai,
  1482. struct in6_addr *coa)
  1483. {
  1484. int ret = conf.pmgr.best_ro_coa(&hai->hoa.addr, cn, coa);
  1485. if (ret <= 0) { /* Policy manager remained silent, let's use hai */
  1486. *coa = hai->primary_coa.addr;
  1487. ret = hai->primary_coa.iif;
  1488. }
  1489. return ret;
  1490. }
  1491. static struct in6_addr linklocal_prefix = { { { 0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
  1492. static inline void linklocal_rt_rules_del(void)
  1493. {
  1494. rule_del(NULL, RT6_TABLE_MAIN,
  1495. IP6_RULE_PRIO_MIP6_COA_OUT, RTN_UNICAST,
  1496. &linklocal_prefix, 64, &in6addr_any, 0, 0);
  1497. }
  1498. static inline int linklocal_rt_rules_add(void)
  1499. {
  1500. return rule_add(NULL, RT6_TABLE_MAIN,
  1501. IP6_RULE_PRIO_MIP6_COA_OUT, RTN_UNICAST,
  1502. &linklocal_prefix, 64, &in6addr_any, 0, 0);
  1503. }
  1504. static int mn_ext_tunnel_ops(__attribute__ ((unused)) int request,
  1505. int old_if, int new_if, void *data)
  1506. {
  1507. struct home_addr_info *hai = data;
  1508. struct mv_hoa_args mha;
  1509. if (old_if == new_if)
  1510. return 0;
  1511. mha.if_next = new_if;
  1512. mha.target = hai;
  1513. if (hai->hoa.iif == old_if &&
  1514. (mn_tnl_state_add(hai, new_if, 1) ||
  1515. addr_do(&hai->hoa.addr, 128, old_if, &mha, mv_hoa) < 0))
  1516. goto undo;
  1517. mn_tnl_state_del(hai, old_if, 1);
  1518. hai->if_tunnel = new_if;
  1519. return 0;
  1520. undo:
  1521. mha.if_next = old_if;
  1522. if (hai->hoa.iif == new_if)
  1523. addr_do(&hai->hoa.addr, 128, new_if, &mha, mv_hoa);
  1524. mn_tnl_state_del(hai, new_if, 1);
  1525. return -1;
  1526. }
  1527. static int mn_move(struct home_addr_info *hai)
  1528. {
  1529. struct mv_hoa_args mha;
  1530. mha.target = hai;
  1531. TRACE;
  1532. if (hai->at_home) {
  1533. int plen = (hai->hoa.iif == hai->if_tunnel ? 128 : hai->plen);
  1534. struct bulentry *e;
  1535. MDBG("in home net\n");
  1536. if (hai->home_reg_status == HOME_REG_NONE &&
  1537. (e = bul_get(hai, NULL, &hai->ha_addr)) != NULL &&
  1538. e->flags & IP6_MH_BU_HOME && e->type != BUL_ENTRY)
  1539. bul_delete(e);
  1540. if (hai->hoa.iif != hai->primary_coa.iif) {
  1541. mha.if_next = hai->primary_coa.iif;
  1542. addr_do(&hai->hoa.addr, plen,
  1543. hai->hoa.iif, &mha, mv_hoa);
  1544. if (hai->home_reg_status == HOME_REG_NONE) {
  1545. mn_send_home_na(hai);
  1546. do_handoff(hai);
  1547. return 0;
  1548. }
  1549. }
  1550. if (hai->home_reg_status != HOME_REG_NONE && !hai->pend_ba) {
  1551. pending_bas++;
  1552. hai->pend_ba = 1;
  1553. do_handoff(hai);
  1554. }
  1555. } else {
  1556. MDBG("in foreign net\n");
  1557. mn_block_rule_add(hai);
  1558. if (hai->pend_ba) {
  1559. hai->pend_ba = 0;
  1560. pending_bas--;
  1561. }
  1562. if (hai->hoa.iif != hai->if_tunnel) {
  1563. mha.if_next = hai->if_tunnel;
  1564. addr_do(&hai->hoa.addr, hai->plen,
  1565. hai->hoa.iif, &mha, mv_hoa);
  1566. }
  1567. do_handoff(hai);
  1568. }
  1569. return 0;
  1570. }
  1571. static int mn_recv_na(int fd, struct home_addr_info *hai,
  1572. struct in6_addr *addr, int ifindex, int has_home_reg)
  1573. {
  1574. unsigned char msg[MAX_PKT_LEN];
  1575. struct sockaddr_in6 saddr;
  1576. struct in6_addr *daddr;
  1577. struct in6_pktinfo pkt_info;
  1578. int len, iif, hoplimit;
  1579. struct nd_neighbor_advert *na;
  1580. uint8_t *hwa = NULL;
  1581. int ret, hwalen = 0;
  1582. len = icmp6_recv(fd, msg, sizeof(msg), &saddr, &pkt_info, &hoplimit);
  1583. if (len < 0)
  1584. return 0;
  1585. daddr = &pkt_info.ipi6_addr;
  1586. iif = pkt_info.ipi6_ifindex;
  1587. na = (struct nd_neighbor_advert *)msg;
  1588. if (iif != ifindex || hoplimit < 255 || (size_t)len < sizeof(*na) ||
  1589. na->nd_na_code != 0 || IN6_IS_ADDR_MULTICAST(&na->nd_na_target) ||
  1590. (na->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED &&
  1591. IN6_IS_ADDR_MULTICAST(daddr)))
  1592. return 0;
  1593. if (hai != NULL) {
  1594. int optlen = len - sizeof(struct nd_neighbor_advert);
  1595. uint8_t *opt = (uint8_t *)(na + 1);
  1596. while (optlen > 1) {
  1597. int olen = opt[1] << 3;
  1598. if (olen > optlen || olen == 0)
  1599. return 0;
  1600. switch (opt[0]) {
  1601. case ND_OPT_TARGET_LINKADDR:
  1602. hwa = &opt[2];
  1603. hwalen = opt[1] * 8 - 2;
  1604. break;
  1605. }
  1606. optlen -= olen;
  1607. opt += olen;
  1608. }
  1609. }
  1610. if (IN6_ARE_ADDR_EQUAL(addr, &na->nd_na_target)) {
  1611. if (has_home_reg && hwa != NULL) {
  1612. ret = neigh_add(iif, NUD_STALE, NTF_ROUTER,
  1613. &hai->ha_addr, hwa, hwalen, 1);
  1614. dbg("ret %d\n", ret);
  1615. }
  1616. return 1;
  1617. }
  1618. return 0;
  1619. }
  1620. int mn_lladdr_dad(struct ifaddrmsg *ifa, struct rtattr *rta_tb[],
  1621. __attribute__ ((unused)) void *arg)
  1622. {
  1623. struct in6_addr *lladdr = RTA_DATA(rta_tb[IFA_ADDRESS]);
  1624. addr_del(lladdr, ifa->ifa_prefixlen, ifa->ifa_index);
  1625. return addr_add(lladdr, ifa->ifa_prefixlen, ifa->ifa_flags,
  1626. ifa->ifa_scope, ifa->ifa_index, 0, 0);
  1627. }
  1628. static int mn_dad_probe(struct in6_addr *addr, int plen, int ifindex)
  1629. {
  1630. int deleted;
  1631. if (IN6_IS_ADDR_LINKLOCAL(addr))
  1632. return addr_do(addr, plen, ifindex, NULL, mn_lladdr_dad);
  1633. /* make sure address isn't configured on interface before
  1634. DAD probe or MN will receive reply from itself */
  1635. deleted = !addr_del(addr, plen, ifindex);
  1636. ndisc_send_ns(ifindex, addr);
  1637. return deleted;
  1638. }
  1639. static int mn_hoa_add(struct home_addr_info *hai,
  1640. struct in6_addr *addr, int plen, int ifindex)
  1641. {
  1642. int scope;
  1643. int flag;
  1644. uint32_t preferred;
  1645. uint32_t valid;
  1646. if (hai == NULL) {
  1647. scope = RT_SCOPE_LINK;
  1648. preferred = 0;
  1649. valid = 0;
  1650. flag = 0;
  1651. } els

Large files files are truncated, but you can click here to view the full file