PageRenderTime 68ms CodeModel.GetById 21ms 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
  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. } else {
  1652. struct mn_addr *hoa = &hai->hoa;
  1653. struct timespec now;
  1654. scope = RT_SCOPE_UNIVERSE;
  1655. clock_gettime(CLOCK_REALTIME, &now);
  1656. preferred = mpd_curr_lft(&now, &hoa->timestamp,
  1657. hoa->preferred_time.tv_sec);
  1658. valid = mpd_curr_lft(&now, &hoa->timestamp,
  1659. hoa->valid_time.tv_sec);
  1660. flag = IFA_F_HOMEADDRESS_NODAD;
  1661. }
  1662. return addr_add(addr, plen, flag, scope, ifindex, preferred, valid);
  1663. }
  1664. static int mn_addr_do_dad(int fd, struct home_addr_info *hai,
  1665. struct in6_addr *addr, int plen,
  1666. int ifindex, int has_home_reg)
  1667. {
  1668. fd_set rset;
  1669. struct timeval tv;
  1670. int add = (mn_dad_probe(addr, plen, ifindex) || hai == NULL);
  1671. FD_ZERO(&rset);
  1672. FD_SET(fd, &rset);
  1673. tv.tv_sec = DAD_TIMEOUT;
  1674. tv.tv_usec = 0;
  1675. for (;;) {
  1676. int ret;
  1677. /* Note on portability: we assume that tv is modified to show
  1678. the time left which is AFAIK true only in Linux
  1679. timeout
  1680. */
  1681. ret = select(fd+1, &rset, NULL, NULL, &tv);
  1682. if (ret < 0)
  1683. return -1;
  1684. if (ret == 0) {
  1685. if (add)
  1686. mn_hoa_add(hai, addr, plen, ifindex);
  1687. if (has_home_reg) {
  1688. MDBG("HA didn't answer DAD probe!\n");
  1689. return -1;
  1690. } else {
  1691. MDBG("DAD succeeded!\n");
  1692. MDBG("address = %x:%x:%x:%x:%x:%x:%x:%x\n",
  1693. NIP6ADDR(addr));
  1694. if (!IN6_IS_ADDR_LINKLOCAL(addr) && hai)
  1695. mn_block_rule_del(hai);
  1696. return 0;
  1697. }
  1698. } else {
  1699. if (!mn_recv_na(fd, hai, addr, ifindex, has_home_reg))
  1700. continue;
  1701. if (has_home_reg) {
  1702. MDBG("HA answered DAD probe!\n");
  1703. if (add)
  1704. mn_hoa_add(hai, addr, plen, ifindex);
  1705. return 0;
  1706. } else {
  1707. MDBG("DAD failed!\n");
  1708. return -1;
  1709. }
  1710. }
  1711. }
  1712. }
  1713. static int mn_do_dad(struct home_addr_info *hai, int dereg)
  1714. {
  1715. int sock, ret = -1, val = 1;
  1716. struct icmp6_filter filter;
  1717. struct in6_addr solicit;
  1718. int type = FLUSH_ALL;
  1719. if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
  1720. return ret;
  1721. ICMP6_FILTER_SETBLOCKALL(&filter);
  1722. ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);
  1723. setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val));
  1724. setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val));
  1725. setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
  1726. sizeof(struct icmp6_filter));
  1727. ipv6_addr_solict_mult(&hai->hoa.addr, &solicit);
  1728. if_mc_group(sock, hai->primary_coa.iif, &in6addr_all_nodes_mc,
  1729. IPV6_JOIN_GROUP);
  1730. if_mc_group(sock, hai->primary_coa.iif, &solicit, IPV6_JOIN_GROUP);
  1731. if (hai->home_reg_status == HOME_REG_NONE) {
  1732. if (hai->lladdr_comp) {
  1733. struct in6_addr lladdr;
  1734. ipv6_addr_llocal(&hai->hoa.addr, &lladdr);
  1735. if (mn_addr_do_dad(sock, NULL, &lladdr, 64,
  1736. hai->primary_coa.iif, 0) < 0) {
  1737. MDBG("Link-local DAD failed!\n");
  1738. goto err;
  1739. }
  1740. }
  1741. if (mn_addr_do_dad(sock, hai, &hai->hoa.addr, hai->plen,
  1742. hai->primary_coa.iif, 0) < 0) {
  1743. MDBG("HoA DAD failed!\n");
  1744. goto err;
  1745. }
  1746. if (dereg)
  1747. mn_send_home_na(hai);
  1748. ret = mn_move(hai);
  1749. } else if (!mn_addr_do_dad(sock, hai, &hai->hoa.addr,
  1750. hai->plen, hai->primary_coa.iif, 1)) {
  1751. ret = mn_move(hai);
  1752. }
  1753. out:
  1754. close(sock);
  1755. return ret;
  1756. err:
  1757. bul_iterate(&hai->bul, _bul_flush, &type);
  1758. goto out;
  1759. }
  1760. static inline void mn_update_coa_lifetime(struct mn_addr *mn_coa,
  1761. struct md_coa *md_coa)
  1762. {
  1763. mn_coa->timestamp = md_coa->timestamp;
  1764. mn_coa->valid_time = md_coa->valid_time;
  1765. mn_coa->preferred_time = md_coa->preferred_time;
  1766. MDBG2("updated CoA lifetimes: preferred %u s and valid %u s\n",
  1767. mn_coa->preferred_time.tv_sec, mn_coa->valid_time.tv_sec);
  1768. }
  1769. static void mn_coa_updated(struct home_addr_info *hai)
  1770. {
  1771. if (!hai->at_home) {
  1772. struct bulentry *e;
  1773. struct mn_addr *coa;
  1774. e = bul_get(hai, NULL, &hai->ha_addr);
  1775. if (e == NULL || !(e->flags & IP6_MH_BU_HOME))
  1776. return;
  1777. coa = &hai->primary_coa;
  1778. MDBG2("preferred_time %u valid_life %u\n",
  1779. coa->preferred_time.tv_sec,
  1780. coa->valid_time.tv_sec);
  1781. /* check if new CoA lifetime is smaller than current
  1782. home registration lifetime */
  1783. if (mn_home_reg_addr_expires(e, coa)) {
  1784. MDBG("CoA expires before next BU, do_handoff()\n");
  1785. do_handoff(hai);
  1786. } else
  1787. hai->verdict = MN_HO_NONE;
  1788. }
  1789. }
  1790. static int mn_home_rtr_chk(struct home_addr_info *hai, struct md_router *rtr)
  1791. {
  1792. int at_home;
  1793. struct list_head *lrp;
  1794. if (hai->verdict != MN_HO_RETURN_HOME) {
  1795. hai->at_home = 0;
  1796. return 0;
  1797. }
  1798. at_home = hai->at_home;
  1799. hai->at_home = 1;
  1800. list_for_each(lrp, &rtr->prefixes) {
  1801. struct prefix_list_entry *p;
  1802. p = list_entry(lrp, struct prefix_list_entry, list);
  1803. mn_update_home_prefix(hai, &p->timestamp, &p->pinfo);
  1804. }
  1805. return !at_home;
  1806. }
  1807. static inline int mn_verify_iface(const struct md_inet6_iface *iface)
  1808. {
  1809. return !list_empty(&iface->coas) && !list_empty(&iface->default_rtr);
  1810. }
  1811. static struct md_inet6_iface *mn_get_iface(const struct home_addr_info *hai,
  1812. int pref_iif,
  1813. struct list_head *iface_list)
  1814. {
  1815. int iif;
  1816. struct md_inet6_iface *best_iface;
  1817. struct list_head *l;
  1818. if ((iif = conf.pmgr.best_iface(&hai->hoa.addr,
  1819. &hai->ha_addr, pref_iif)) > 0 &&
  1820. (best_iface = md_get_inet6_iface(iface_list, iif)) != NULL &&
  1821. mn_verify_iface(best_iface))
  1822. return best_iface;
  1823. best_iface = NULL;
  1824. list_for_each(l, iface_list) {
  1825. struct md_inet6_iface *iface;
  1826. iface = list_entry(l, struct md_inet6_iface, list);
  1827. if (mn_verify_iface(iface) &&
  1828. (best_iface == NULL ||
  1829. (best_iface)->preference > iface->preference ||
  1830. (best_iface->preference == iface->preference &&
  1831. iface->ifindex == pref_iif))) {
  1832. best_iface = iface;
  1833. }
  1834. }
  1835. return best_iface;
  1836. }
  1837. static struct md_coa *mn_get_coa(const struct home_addr_info *hai, int iif,
  1838. const struct in6_addr *pref_coa,
  1839. struct list_head *coa_list)
  1840. {
  1841. struct in6_addr coa = in6addr_any;
  1842. int coa_iif;
  1843. struct md_coa *best_coa;
  1844. struct list_head *l;
  1845. coa_iif = conf.pmgr.best_coa(&hai->hoa.addr, &hai->ha_addr,
  1846. iif, pref_coa, &coa);
  1847. if (coa_iif == iif &&
  1848. (best_coa = md_get_coa(coa_list, &coa)) != NULL &&
  1849. tsisset(best_coa->valid_time))
  1850. return best_coa;
  1851. if ((best_coa = md_get_coa(coa_list, pref_coa)) != NULL) {
  1852. if (!tsisset(best_coa->valid_time))
  1853. best_coa = NULL;
  1854. else if (tsisset(best_coa->preferred_time))
  1855. return best_coa;
  1856. }
  1857. list_for_each(l, coa_list) {
  1858. struct md_coa *test_coa = list_entry(l, struct md_coa, list);
  1859. if (tsisset(test_coa->valid_time)) {
  1860. if (tsisset(test_coa->preferred_time))
  1861. return test_coa;
  1862. if (best_coa == NULL)
  1863. best_coa = test_coa;
  1864. }
  1865. }
  1866. return best_coa;
  1867. }
  1868. static int mn_make_ho_verdict(const struct movement_event *me,
  1869. const struct home_addr_info *hai,
  1870. struct md_router **next_rtr,
  1871. struct md_coa **next_coa)
  1872. {
  1873. struct md_inet6_iface *old_iface = NULL, *new_iface = NULL;
  1874. struct md_router *rtr;
  1875. struct md_coa *coa = NULL;
  1876. int pref_iif = hai->primary_coa.iif; /* prefer current CoA interface */
  1877. int force = 0;
  1878. if (me->iface != NULL &&
  1879. (rtr = md_get_first_router(&me->iface->default_rtr)) != NULL &&
  1880. mn_is_at_home(&rtr->prefixes, &hai->home_prefix, hai->home_plen)) {
  1881. *next_rtr = rtr;
  1882. *next_coa = NULL;
  1883. return MN_HO_RETURN_HOME;
  1884. }
  1885. if (pref_iif > 0) {
  1886. old_iface = md_get_inet6_iface(me->iface_list, pref_iif);
  1887. if (old_iface == NULL)
  1888. pref_iif = 0;
  1889. }
  1890. switch (me->event_type) {
  1891. case ME_DHAAD:
  1892. force = 1;
  1893. break;
  1894. case ME_IFACE_DOWN:
  1895. case ME_LINK_DOWN:
  1896. case ME_RTR_EXPIRED:
  1897. assert(me->iface != NULL);
  1898. if (old_iface != NULL && old_iface != me->iface)
  1899. return MN_HO_IGNORE;
  1900. break;
  1901. case ME_RTR_NEW:
  1902. assert(!list_empty(&me->iface->default_rtr));
  1903. case ME_LINK_UP:
  1904. assert(me->iface != NULL);
  1905. break;
  1906. case ME_RTR_BACK:
  1907. case ME_RTR_UPDATED:
  1908. assert(me->iface != NULL);
  1909. assert(!list_empty(&me->iface->default_rtr));
  1910. if (old_iface == NULL)
  1911. break;
  1912. if (old_iface != me->iface)
  1913. return MN_HO_IGNORE;
  1914. *next_coa = md_get_coa(&old_iface->coas,
  1915. &hai->primary_coa.addr);
  1916. if (*next_coa == NULL)
  1917. break;
  1918. *next_rtr = md_get_first_router(&old_iface->default_rtr);
  1919. return MN_HO_REESTABLISH;
  1920. case ME_COA_NEW:
  1921. assert(me->iface != NULL);
  1922. assert(me->coa != NULL);
  1923. assert(me->iface->ifindex == me->coa->ifindex);
  1924. break;
  1925. case ME_COA_EXPIRED:
  1926. assert(me->iface != NULL);
  1927. assert(me->coa != NULL);
  1928. assert(me->iface->ifindex == me->coa->ifindex);
  1929. if (old_iface == NULL ||
  1930. (old_iface == me->iface &&
  1931. IN6_ARE_ADDR_EQUAL(&hai->primary_coa.addr,
  1932. &me->coa->addr)))
  1933. break;
  1934. return MN_HO_IGNORE;
  1935. case ME_COA_LFT_DEC:
  1936. case ME_COA_LFT_INC:
  1937. assert(me->iface != NULL);
  1938. assert(me->coa != NULL);
  1939. assert(me->iface->ifindex == me->coa->ifindex);
  1940. if (old_iface == NULL)
  1941. break;
  1942. if (old_iface != me->iface ||
  1943. !IN6_ARE_ADDR_EQUAL(&hai->primary_coa.addr,
  1944. &me->coa->addr))
  1945. return MN_HO_IGNORE;
  1946. *next_coa = me->coa;
  1947. return MN_HO_CHECK_LIFETIME;
  1948. default:
  1949. return MN_HO_IGNORE;
  1950. }
  1951. new_iface = mn_get_iface(hai, pref_iif, me->iface_list);
  1952. if (new_iface == NULL)
  1953. return MN_HO_INVALIDATE;
  1954. coa = mn_get_coa(hai, new_iface->ifindex,
  1955. &hai->primary_coa.addr, &new_iface->coas);
  1956. if (coa == NULL)
  1957. return MN_HO_INVALIDATE;
  1958. if (!force && new_iface == old_iface &&
  1959. IN6_ARE_ADDR_EQUAL(&coa->addr, &hai->primary_coa.addr))
  1960. return MN_HO_IGNORE;
  1961. if (list_empty(&new_iface->default_rtr))
  1962. return MN_HO_IGNORE;
  1963. *next_rtr = md_get_first_router(&new_iface->default_rtr);
  1964. *next_coa = coa;
  1965. return MN_HO_PROCEED;
  1966. }
  1967. static void mn_chk_ho_verdict(struct home_addr_info *hai,
  1968. const struct movement_event *event)
  1969. {
  1970. struct md_router *rtr = NULL;
  1971. struct md_coa *coa = NULL;
  1972. int move_home = 0;
  1973. if (event->event_type == ME_COA_EXPIRED &&
  1974. IN6_ARE_ADDR_EQUAL(&event->coa->addr, &hai->hoa.addr))
  1975. return;
  1976. hai->verdict = mn_make_ho_verdict(event, hai, &rtr, &coa);
  1977. if (hai->verdict == MN_HO_IGNORE)
  1978. return;
  1979. if (hai->verdict == MN_HO_INVALIDATE) {
  1980. hai->primary_coa.iif = 0;
  1981. return;
  1982. }
  1983. if (rtr != NULL)
  1984. move_home = mn_home_rtr_chk(hai, rtr);
  1985. if (hai->verdict == MN_HO_CHECK_LIFETIME) {
  1986. mn_update_coa_lifetime(&hai->primary_coa, coa);
  1987. mn_coa_updated(hai);
  1988. } else if (hai->verdict == MN_HO_REESTABLISH) {
  1989. hai->primary_coa.iif = coa->ifindex;
  1990. mn_update_coa_lifetime(&hai->primary_coa, coa);
  1991. mn_coa_updated(hai);
  1992. } else {
  1993. switch (hai->verdict) {
  1994. case MN_HO_PROCEED:
  1995. hai->primary_coa.iif = coa->ifindex;
  1996. hai->primary_coa.addr = coa->addr;
  1997. mn_update_coa_lifetime(&hai->primary_coa, coa);
  1998. break;
  1999. case MN_HO_RETURN_HOME:
  2000. hai->primary_coa.iif = rtr->ifindex;
  2001. hai->primary_coa.addr = hai->hoa.addr;
  2002. break;
  2003. default:
  2004. return;
  2005. }
  2006. if (hai->at_home && !hai->pend_ba) {
  2007. /* check if router is HA */
  2008. if (hai->home_reg_status != HOME_REG_NONE &&
  2009. rtr_addr_chk(rtr, &hai->ha_addr)) {
  2010. mn_move(hai);
  2011. } else if (hai->home_reg_status != HOME_REG_NONE ||
  2012. move_home) {
  2013. int type = FLUSH_FAILED;
  2014. mn_do_dad(hai, 0);
  2015. if (hai->home_reg_status == HOME_REG_NONE)
  2016. bul_iterate(&hai->bul,
  2017. _bul_flush, &type);
  2018. }
  2019. }
  2020. }
  2021. }
  2022. int mn_movement_event(struct movement_event *event)
  2023. {
  2024. struct list_head *lh;
  2025. struct home_addr_info *hai;
  2026. /* First de-registration */
  2027. pthread_rwlock_wrlock(&mn_lock);
  2028. if (event != NULL) {
  2029. if (event->event_type == ME_DHAAD) {
  2030. hai = mn_get_home_addr_by_dhaadid(event->data);
  2031. if (hai == NULL) {
  2032. pthread_rwlock_unlock(&mn_lock);
  2033. return 0;
  2034. }
  2035. dhaad_stop(hai);
  2036. mn_chk_ho_verdict(hai, event);
  2037. } else {
  2038. if (event->event_type == ME_COA_EXPIRED)
  2039. mn_rr_delete_co(&event->coa->addr);
  2040. list_for_each(lh, &home_addr_list) {
  2041. hai = list_entry(lh,
  2042. struct home_addr_info, list);
  2043. mn_chk_ho_verdict(hai, event);
  2044. }
  2045. }
  2046. }
  2047. /* Then registration if we are not at home,
  2048. otherwise we need to wait for BA to avoid forwarding loops */
  2049. if (!pending_bas) {
  2050. list_for_each(lh, &home_addr_list) {
  2051. hai = list_entry(lh, struct home_addr_info, list);
  2052. if (!hai->at_home &&
  2053. positive_ho_verdict(hai->verdict)) {
  2054. mn_move(hai);
  2055. }
  2056. }
  2057. }
  2058. pthread_rwlock_unlock(&mn_lock);
  2059. return 0;
  2060. }
  2061. /**
  2062. * mn_rr_start_handoff - start RR procedure after changing CoA
  2063. * vbule: bulentry
  2064. *
  2065. * Triggers RR with CN if necessary, else sends BU to CN.
  2066. **/
  2067. int mn_rr_start_handoff(void *vbule, __attribute__ ((unused)) void *dummy)
  2068. {
  2069. struct bulentry *bule = vbule;
  2070. if (bule->type != BUL_ENTRY || bule->flags & IP6_MH_BU_HOME)
  2071. return 0;
  2072. if (bule->home->at_home) {
  2073. MDBG("Returning home, no need for Care-of keygen token\n");
  2074. bule->dereg = 1;
  2075. tsclear(bule->lifetime);
  2076. }
  2077. bule->if_coa = mn_get_ro_coa(&bule->peer_addr, bule->home, &bule->coa);
  2078. if (bule->if_coa < 0)
  2079. goto delete_entry;
  2080. bule->do_send_bu = 1;
  2081. mn_rr_refresh(bule);
  2082. if (bule->rr.state == RR_READY)
  2083. mn_send_cn_bu(bule);
  2084. return 0;
  2085. delete_entry:
  2086. bul_delete(bule);
  2087. return 0;
  2088. }
  2089. /* mn_start_ro - start RO, triggered by tunneled packet */
  2090. void mn_start_ro(struct in6_addr *cn, struct in6_addr *hoa)
  2091. {
  2092. struct bulentry *bule;
  2093. struct home_addr_info *hai;
  2094. struct in6_addr coa;
  2095. int if_coa;
  2096. pthread_rwlock_wrlock(&mn_lock);
  2097. hai = mn_get_home_addr(hoa);
  2098. if (!hai || hai->at_home) {
  2099. pthread_rwlock_unlock(&mn_lock);
  2100. return;
  2101. }
  2102. if_coa = mn_get_ro_coa(cn, hai, &coa);
  2103. if (if_coa > 0) {
  2104. MDBG("MN: Start RO to %x:%x:%x:%x:%x:%x:%x:%x, "
  2105. "from %x:%x:%x:%x:%x:%x:%x:%x\n",
  2106. NIP6ADDR(cn), NIP6ADDR(hoa));
  2107. bule = bul_get(NULL, hoa, cn);
  2108. if (bule) {
  2109. /* If BUL entry exists, RR is done or in progress */
  2110. pthread_rwlock_unlock(&mn_lock);
  2111. return;
  2112. }
  2113. bule = create_bule(hoa, cn);
  2114. if (!bule) {
  2115. MDBG("Malloc failed at starting of RO\n");
  2116. pthread_rwlock_unlock(&mn_lock);
  2117. return;
  2118. }
  2119. bule->type = BUL_ENTRY;
  2120. bule->flags = conf.CnBuAck;
  2121. bule->coa = coa;
  2122. bule->if_coa = if_coa;
  2123. bule->coa_changed = -1;
  2124. bule->home = hai;
  2125. bule->rr.state = RR_NOT_STARTED;
  2126. mn_reset_ro_bule(bule);
  2127. if (bul_add(bule) < 0) {
  2128. bul_delete(bule);
  2129. pthread_rwlock_unlock(&mn_lock);
  2130. return;
  2131. }
  2132. mn_rr_refresh(bule);
  2133. if (bule->rr.state == RR_NOT_STARTED)
  2134. bul_delete(bule);
  2135. }
  2136. pthread_rwlock_unlock(&mn_lock);
  2137. }
  2138. static void mn_recv_brr(__attribute__ ((unused)) const struct ip6_mh *mh,
  2139. ssize_t len, const struct in6_addr_bundle *in,
  2140. __attribute__ ((unused)) int iif)
  2141. {
  2142. struct bulentry *e;
  2143. struct in6_addr *cn, *hoa;
  2144. struct timespec now;
  2145. long last_used;
  2146. if (len < 0 || (size_t)len < sizeof(struct ip6_mh_binding_request))
  2147. return;
  2148. cn = in->src;
  2149. hoa = in->dst;
  2150. pthread_rwlock_wrlock(&mn_lock);
  2151. /* Do we have BUL entry for cn? If not, drop. */
  2152. if ((e = bul_get(NULL, hoa, cn)) == NULL) {
  2153. pthread_rwlock_unlock(&mn_lock);
  2154. return;
  2155. }
  2156. dbg("Received BRR\n");
  2157. dbg_func(e, dump_bule);
  2158. clock_gettime(CLOCK_REALTIME, &now);
  2159. /* Do we need a binding? */
  2160. last_used = xfrm_last_used(cn, hoa, IPPROTO_DSTOPTS, &now);
  2161. if (last_used >= 0 && last_used < MN_RO_RESTART_THRESHOLD)
  2162. mn_rr_start_handoff(e, NULL);
  2163. pthread_rwlock_unlock(&mn_lock);
  2164. }
  2165. static struct mh_handler mn_brr_handler = {
  2166. .recv = mn_recv_brr,
  2167. };
  2168. static void mn_recv_be(const struct ip6_mh *mh, ssize_t len,
  2169. const struct in6_addr_bundle *in,
  2170. __attribute__ ((unused)) int iif)
  2171. {
  2172. struct ip6_mh_binding_error *berr;
  2173. struct bulentry *e;
  2174. struct in6_addr *cn, *hoa;
  2175. struct timespec now;
  2176. struct in6_addr addr;
  2177. if (len < 0 || (size_t)len < sizeof(struct ip6_mh_binding_error))
  2178. return;
  2179. berr = (struct ip6_mh_binding_error *)mh;
  2180. cn = in->src;
  2181. pthread_rwlock_wrlock(&mn_lock);
  2182. if (!IN6_IS_ADDR_UNSPECIFIED(&berr->ip6mhbe_homeaddr))
  2183. hoa = &berr->ip6mhbe_homeaddr;
  2184. else if (mn_rr_error_check(in->dst, in->src, &addr))
  2185. hoa = &addr;
  2186. else
  2187. hoa = in->dst;
  2188. /* Do we have BUL entry for cn? If not, drop. */
  2189. if ((e = bul_get(NULL, hoa, cn)) == NULL || e->type != BUL_ENTRY)
  2190. goto out;
  2191. clock_gettime(CLOCK_REALTIME, &now);
  2192. /* Invalidate old entry, if it is not home entry */
  2193. if (e->flags & IP6_MH_BU_HOME) {
  2194. MDBG("Got BE from HA, it does not understand us ?\n");
  2195. bule_invalidate(e, &now, 1);
  2196. goto out;
  2197. }
  2198. if (berr->ip6mhbe_status == IP6_MH_BES_UNKNOWN_HAO) {
  2199. bul_delete(e);
  2200. } else if (berr->ip6mhbe_status == IP6_MH_BES_UNKNOWN_MH) {
  2201. /* if no ack expected, ignore */
  2202. /* if extension in use, stop using it */
  2203. /* if no extensions, stop route optimization */
  2204. if (!e->do_send_bu)
  2205. goto out;
  2206. if (hoa == &berr->ip6mhbe_homeaddr && e->rr.state != RR_READY)
  2207. goto out;
  2208. if (e->rr.state != RR_READY || e->wait_ack)
  2209. bule_invalidate(e, &now, 1);
  2210. }
  2211. out:
  2212. pthread_rwlock_unlock(&mn_lock);
  2213. }
  2214. static struct mh_handler mn_be_handler = {
  2215. .recv = mn_recv_be,
  2216. };
  2217. int mn_init(void)
  2218. {
  2219. struct list_head *l, *n;
  2220. if (conf.DoRouteOptimizationMN &&
  2221. ipsec_policy_entry_check(NULL, NULL, IPSEC_F_TNL_ANY)) {
  2222. syslog(LOG_ERR,
  2223. "MN can't use both DoRouteOptimizationMN and TunnelPayload IPsecPolicy");
  2224. return -1;
  2225. }
  2226. if (pthread_rwlock_init(&mn_lock, NULL))
  2227. return -1;
  2228. if (md_init() < 0)
  2229. return -1;
  2230. if (bul_init() < 0)
  2231. goto err_bul;
  2232. dhaad_mn_init();
  2233. if (mpd_mn_init() < 0)
  2234. goto err_mpd;
  2235. if (rr_init() < 0)
  2236. goto err_rr;
  2237. list_for_each(l, &conf.home_addrs) {
  2238. struct home_addr_info *hai;
  2239. hai = list_entry(l, struct home_addr_info, list);
  2240. if (conf_home_addr_info(hai) < 0)
  2241. goto err_hoa;
  2242. }
  2243. if_mc_group(ICMP6_MAIN_SOCK, 0, &in6addr_all_nodes_mc,
  2244. IPV6_JOIN_GROUP);
  2245. if (linklocal_rt_rules_add() < 0)
  2246. goto err_rule;
  2247. icmp6_handler_reg(ICMP6_PARAM_PROB, &mn_param_prob_handler);
  2248. mh_handler_reg(IP6_MH_TYPE_BERROR, &mn_be_handler);
  2249. mh_handler_reg(IP6_MH_TYPE_BACK, &mn_ba_handler);
  2250. mh_handler_reg(IP6_MH_TYPE_BRR, &mn_brr_handler);
  2251. if (md_start() < 0)
  2252. goto err_md;
  2253. return 0;
  2254. err_md:
  2255. mh_handler_dereg(IP6_MH_TYPE_BRR, &mn_brr_handler);
  2256. mh_handler_dereg(IP6_MH_TYPE_BACK, &mn_ba_handler);
  2257. mh_handler_dereg(IP6_MH_TYPE_BERROR, &mn_be_handler);
  2258. icmp6_handler_dereg(ICMP6_PARAM_PROB, &mn_param_prob_handler);
  2259. linklocal_rt_rules_del();
  2260. err_rule:
  2261. pthread_rwlock_wrlock(&mn_lock);
  2262. list_for_each_safe(l, n, &home_addr_list) {
  2263. struct home_addr_info *hai;
  2264. hai = list_entry(l, struct home_addr_info, list);
  2265. clean_home_addr_info(hai);
  2266. }
  2267. pthread_rwlock_unlock(&mn_lock);
  2268. err_hoa:
  2269. pthread_rwlock_wrlock(&mn_lock);
  2270. bul_flush();
  2271. pthread_rwlock_unlock(&mn_lock);
  2272. rr_cleanup();
  2273. err_rr:
  2274. mpd_mn_cleanup();
  2275. err_mpd:
  2276. dhaad_mn_cleanup();
  2277. bul_cleanup();
  2278. err_bul:
  2279. md_cleanup();
  2280. return -1;
  2281. }
  2282. void mn_cleanup()
  2283. {
  2284. struct list_head *l, *n;
  2285. md_stop();
  2286. mh_handler_dereg(IP6_MH_TYPE_BRR, &mn_brr_handler);
  2287. mh_handler_dereg(IP6_MH_TYPE_BACK, &mn_ba_handler);
  2288. mh_handler_dereg(IP6_MH_TYPE_BERROR, &mn_be_handler);
  2289. icmp6_handler_dereg(ICMP6_PARAM_PROB, &mn_param_prob_handler);
  2290. linklocal_rt_rules_del();
  2291. pthread_rwlock_wrlock(&mn_lock);
  2292. list_for_each_safe(l, n, &home_addr_list) {
  2293. struct home_addr_info *hai;
  2294. hai = list_entry(l, struct home_addr_info, list);
  2295. clean_home_addr_info(hai);
  2296. }
  2297. bul_flush();
  2298. pthread_rwlock_unlock(&mn_lock);
  2299. rr_cleanup();
  2300. mpd_mn_cleanup();
  2301. dhaad_mn_cleanup();
  2302. bul_cleanup();
  2303. md_cleanup();
  2304. }