]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/mip6_mn.c
dde4bf5158f4ccb6ea9a0488af798bab0edc417e
[apple/xnu.git] / bsd / netinet6 / mip6_mn.c
1 /* $KAME: mip6_mn.c,v 1.11 2000/03/18 03:05:42 itojun Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, 1998, 1999 and 2000 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1999 and 2000 Ericsson Radio Systems AB
34 * All rights reserved.
35 *
36 * Author: Conny Larsson <conny.larsson@era.ericsson.se>
37 *
38 */
39
40 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
41 #include "opt_inet.h"
42 #endif
43
44 /*
45 * Mobile IPv6 Mobile Nodes
46 */
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/malloc.h>
50 #include <sys/mbuf.h>
51 #include <sys/domain.h>
52 #include <sys/protosw.h>
53 #include <sys/socket.h>
54 #include <sys/errno.h>
55 #include <sys/time.h>
56 #include <sys/kernel.h>
57 #include <sys/syslog.h>
58 #include <sys/ioccom.h>
59 #include <net/if.h>
60 #include <net/if_types.h>
61 #include <net/route.h>
62 #include <netinet/in.h>
63 #include <netinet/in_var.h>
64 #include <netinet6/in6_var.h>
65 #include <netinet/ip6.h>
66 #include <netinet6/ip6_var.h>
67 #include <netinet/icmp6.h>
68 #include <netinet6/nd6.h>
69 #include <netinet6/mip6.h>
70 #include <netinet6/mip6_common.h>
71
72 /* Declaration of Global variables. */
73 struct mip6_bul *mip6_bulq = NULL; /* First entry in Binding Update list */
74 struct mip6_esm *mip6_esmq = NULL; /* List of event-state machines */
75
76 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
77 struct callout_handle mip6_timer_outqueue_handle;
78 struct callout_handle mip6_timer_bul_handle;
79 struct callout_handle mip6_timer_esm_handle;
80 #endif
81
82
83 /*
84 ##############################################################################
85 #
86 # INITIALIZATION AND EXIT FUNCTIONS
87 # These functions are executed when the MIPv6 code is activated and de-
88 # activated respectively.
89 #
90 ##############################################################################
91 */
92
93 /*
94 ******************************************************************************
95 * Function: mip6_mn_init
96 * Description: Initialization of MIPv6 variables that must be initialized
97 * before the MN code is executed.
98 ******************************************************************************
99 */
100 void
101 mip6_mn_init(void)
102 {
103 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
104 /* Initialize handle for timer functions. */
105 callout_handle_init(&mip6_timer_outqueue_handle);
106 callout_handle_init(&mip6_timer_bul_handle);
107 callout_handle_init(&mip6_timer_esm_handle);
108 #endif
109
110 printf("%s: MIP6 Mobile Node initialized\n", __FUNCTION__);
111 }
112
113
114
115 /*
116 ******************************************************************************
117 * Function: mip6_mn_exit
118 * Description: This function is called when the MN module is unloaded
119 * (relesed) from the kernel.
120 ******************************************************************************
121 */
122 void
123 mip6_mn_exit()
124 {
125 struct mip6_output *outp, *outp_tmp;
126 struct mip6_bul *bulp;
127 struct mip6_esm *esp;
128 int s;
129
130 /* Cancel outstanding timeout function calls. */
131 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
132 untimeout(mip6_timer_outqueue, (void *)NULL,
133 mip6_timer_outqueue_handle);
134 untimeout(mip6_timer_bul, (void *)NULL, mip6_timer_bul_handle);
135 untimeout(mip6_timer_esm, (void *)NULL, mip6_timer_esm_handle);
136 #else
137 untimeout(mip6_timer_outqueue, (void *)NULL);
138 untimeout(mip6_timer_bul, (void *)NULL);
139 untimeout(mip6_timer_esm, (void *)NULL);
140 #endif
141
142 /* Remove each entry in every queue. */
143 s = splnet();
144 for (outp = mip6_outq; outp;) {
145 outp_tmp = outp;
146 outp = outp->next;
147 if (outp_tmp->opt)
148 _FREE(outp_tmp->opt, M_TEMP);
149 if (outp_tmp->subopt)
150 _FREE(outp_tmp->subopt, M_TEMP);
151 _FREE(outp_tmp, M_TEMP);
152 }
153 mip6_outq = NULL;
154
155 for (bulp = mip6_bulq; bulp;)
156 bulp = mip6_bul_delete(bulp);
157 mip6_bulq = NULL;
158
159 for (esp = mip6_esmq; esp;)
160 esp = mip6_esm_delete(esp);
161 mip6_esmq = NULL;
162 splx(s);
163 }
164
165
166
167 /*
168 ##############################################################################
169 #
170 # RECEIVING FUNCTIONS
171 # These functions receives the incoming IPv6 packet and further processing of
172 # the packet depends on the content in the packet.
173 #
174 ##############################################################################
175 */
176
177 /*
178 ******************************************************************************
179 * Function: mip6_new_defrtr
180 * Description: Called from the move detection algorithm when it has decided
181 * to change default router, i.e the network that we were
182 * connected to has changed.
183 * Ret value: -
184 ******************************************************************************
185 */
186 void
187 mip6_new_defrtr(state, home_prefix, prim_prefix, def_router)
188 int state; /* State from move detection algorithm */
189 struct nd_prefix *home_prefix; /* Prefix for Home Address */
190 struct nd_prefix *prim_prefix; /* Prefix for primary care-of address */
191 struct nd_defrouter *def_router; /* New default router being used */
192 {
193 struct in6_addr *home_addr; /* Home Address for Mobile Node */
194 struct in6_addr *prim_addr; /* Primary Care-of Adress for MN */
195 struct mip6_esm *esp; /* Home address entry */
196 struct mip6_bul *bulp; /* Entry in the BU list */
197 struct ifaddr *if_addr; /* Interface address */
198 struct mip6_bu_data bu_data; /* Data used when a BU is created */
199 struct in6_addr ll_all_addr; /* Link local all nodes address */
200 struct in6_addr old_coa;
201 struct sockaddr_in6 sin6;
202 u_int32_t lifetime; /* Lifetime used in BU */
203 u_long na_flags; /* Flags for NA message */
204
205 /* Check incoming parameters */
206 if (home_prefix != NULL)
207 home_addr = &home_prefix->ndpr_addr;
208 else {
209 log(LOG_ERR, "%s: No home address configured\n", __FUNCTION__);
210 return;
211 }
212
213 esp = mip6_esm_find(home_addr);
214 if (esp == NULL) {
215 log(LOG_ERR,
216 "%s: No event-state machine found\n", __FUNCTION__);
217 return;
218 }
219
220 if (prim_prefix != NULL)
221 prim_addr = &prim_prefix->ndpr_addr;
222 else
223 prim_addr = NULL;
224
225 /* Decide how the mobile node has moved. */
226 if ((prim_prefix == NULL) && (state == MIP6_MD_UNDEFINED)) {
227 /* The Mobile Node is not connected to a network */
228 esp->state = MIP6_STATE_UNDEF;
229 esp->coa = in6addr_any;
230 if (esp->ha_fn != NULL) {
231 _FREE(esp->ha_fn, M_TEMP);
232 esp->ha_fn = NULL;
233 }
234 if (mip6_tunnel(NULL, NULL, MIP6_TUNNEL_DEL, MIP6_NODE_MN,
235 (void *)esp))
236 return;
237 } else if ((prim_prefix == NULL) && (state == MIP6_MD_HOME)) {
238 /* The Mobile Node is returning to the home link. Change the
239 parameters for the event-state machine. */
240 esp->state = MIP6_STATE_DEREG;
241 old_coa = esp->coa;
242 esp->coa = esp->home_addr;
243
244 /* Send a BU de-registration to the Home Agent. */
245 bulp = mip6_bul_find(NULL, home_addr);
246 if (bulp == NULL) {
247 /* The event-state machine was in state undefined. */
248 esp->state = MIP6_STATE_HOME;
249
250 /* When returning home and no home registration exist
251 we can not assume the home address to be unique.
252 Perform DAD, but find the i/f address first. */
253 bzero(&sin6, sizeof(struct sockaddr_in6));
254 sin6.sin6_len = sizeof(struct sockaddr_in6);
255 sin6.sin6_family = AF_INET6;
256 sin6.sin6_addr = esp->home_addr;
257
258 if_addr = ifa_ifwithaddr((struct sockaddr *)&sin6);
259 if (if_addr == NULL)
260 return;
261
262 ((struct in6_ifaddr *)if_addr)->ia6_flags |=
263 IN6_IFF_TENTATIVE;
264 nd6_dad_start(if_addr, NULL);
265 return;
266 }
267
268 bulp->lifetime = mip6_config.hr_lifetime;
269 bulp->refreshtime = bulp->lifetime;
270 bulp->coa = bulp->bind_addr;
271
272 bu_data.prefix_len = esp->prefix_len;
273 bu_data.ack = 1;
274
275 if (mip6_send_bu(bulp, &bu_data, NULL) != 0)
276 return;
277
278 /* Send a BU to the previous foreign network. */
279 if ( !IN6_IS_ADDR_UNSPECIFIED(&old_coa) &&
280 (esp->ha_fn != NULL)) {
281 /* Find lifetime used for the BU to the def router. */
282 lifetime = mip6_prefix_lifetime(&old_coa);
283 lifetime = min(lifetime, MIP6_BU_LIFETIME_DEFRTR);
284
285 /* Create a tunnel used by the MN to receive
286 incoming tunneled packets. */
287 if (mip6_tunnel(home_addr, &esp->ha_fn->addr,
288 MIP6_TUNNEL_ADD,
289 MIP6_NODE_MN, (void *)esp))
290 return;
291
292 mip6_send_bu2fn(&old_coa, esp->ha_fn, home_addr,
293 esp->ifp, lifetime);
294 _FREE(esp->ha_fn, M_TEMP);
295 esp->ha_fn = NULL;
296 }
297
298 /* The Mobile Node must send a Neighbor Advertisement to inform
299 other nodes that it has arrived back to its home network.
300 The first NA will be sent in the create function, the
301 remaining NAs are sent by the timer function. */
302 ll_all_addr = in6addr_linklocal_allnodes;
303 na_flags = ND_NA_FLAG_OVERRIDE;
304 mip6_na_create(home_addr, &ll_all_addr, home_addr,
305 esp->prefix_len, na_flags, 1);
306 } else if ((prim_prefix != NULL) && (state == MIP6_MD_FOREIGN)) {
307 /* If no Home Agent Address exist. Build an anycast address */
308 if (IN6_IS_ADDR_UNSPECIFIED(&esp->ha_hn)) {
309 mip6_build_ha_anycast(&esp->ha_hn, &esp->home_addr,
310 esp->prefix_len);
311 if (IN6_IS_ADDR_UNSPECIFIED(&esp->ha_hn)) {
312 log(LOG_ERR,
313 "%s: Could not create anycast address "
314 "for Mobile Node, wrong prefix length\n",
315 __FUNCTION__);
316 return;
317 }
318 }
319
320 if ((esp->state == MIP6_STATE_UNDEF) ||
321 (esp->state == MIP6_STATE_HOME) ||
322 (esp->state == MIP6_STATE_DEREG)) {
323 /* Home Network --> Foreign Network */
324 /* Update state information for the home address. */
325 esp->state = MIP6_STATE_NOTREG;
326 esp->coa = *prim_addr;
327 if (esp->ha_fn != NULL) {
328 _FREE(esp->ha_fn, M_TEMP);
329 esp->ha_fn = NULL;
330 }
331
332 /* Find an existing or create a new BUL entry. */
333 bulp = mip6_bul_find(NULL, &esp->home_addr);
334 if (bulp == NULL) {
335 bulp = mip6_bul_create(&esp->ha_hn,
336 &esp->home_addr,
337 prim_addr,
338 mip6_config.hr_lifetime,
339 1);
340 if (bulp == NULL)
341 return;
342 } else {
343 bulp->coa = *prim_addr;
344 bulp->lifetime = mip6_config.hr_lifetime;
345 bulp->refreshtime = bulp->lifetime;
346 }
347
348 /* Send a BU registration to the Home Agent. */
349 bulp->coa = *prim_addr;
350 bulp->lifetime = mip6_config.hr_lifetime;
351 bulp->refreshtime = mip6_config.hr_lifetime;
352
353 bu_data.prefix_len = esp->prefix_len;
354 bu_data.ack = 1;
355
356 if (mip6_send_bu(bulp, &bu_data, NULL) != 0)
357 return;
358 } else if (esp->state == MIP6_STATE_REG ||
359 esp->state == MIP6_STATE_REREG ||
360 esp->state == MIP6_STATE_REGNEWCOA ||
361 esp->state == MIP6_STATE_NOTREG) {
362 /* Foreign Network --> New Foreign Network */
363 /* Update state information for the home address. */
364 esp->state = MIP6_STATE_REGNEWCOA;
365 old_coa = esp->coa;
366 esp->coa = *prim_addr;
367
368 /* Find an existing or create a new BUL entry. */
369 bulp = mip6_bul_find(NULL, &esp->home_addr);
370 if (bulp == NULL) {
371 bulp = mip6_bul_create(&esp->ha_hn,
372 &esp->home_addr,
373 prim_addr,
374 mip6_config.hr_lifetime,
375 1);
376 if (bulp == NULL)
377 return;
378 }
379
380 /* Send a BU registration to the Home Agent. */
381 bulp->coa = *prim_addr;
382 bulp->lifetime = mip6_config.hr_lifetime;
383 bulp->refreshtime = mip6_config.hr_lifetime;
384 bulp->no_of_sent_bu = 0;
385
386 bu_data.prefix_len = esp->prefix_len;
387 bu_data.ack = 1;
388
389 if (mip6_send_bu(bulp, &bu_data, NULL) != 0)
390 return;
391
392 /* Send a BU registration to the previous default
393 router. */
394 if ( !IN6_IS_ADDR_UNSPECIFIED(&old_coa) &&
395 (esp->ha_fn)) {
396 /* Find lifetime to be used for the BU to
397 the def router. */
398 lifetime = mip6_prefix_lifetime(&old_coa);
399 lifetime = min(lifetime,
400 MIP6_BU_LIFETIME_DEFRTR);
401
402 /* Create a tunnel used by the MN to receive
403 incoming tunneled packets. */
404 if (mip6_tunnel(prim_addr, &esp->ha_fn->addr,
405 MIP6_TUNNEL_MOVE,
406 MIP6_NODE_MN, (void *)esp))
407 return;
408
409 mip6_send_bu2fn(&old_coa, esp->ha_fn,
410 prim_addr,
411 esp->ifp, lifetime);
412 _FREE(esp->ha_fn, M_TEMP);
413 esp->ha_fn = NULL;
414 }
415 }
416 } else
417 esp->state = MIP6_STATE_UNDEF;
418 }
419
420
421
422 /*
423 ##############################################################################
424 #
425 # CONTROL SIGNAL FUNCTIONS
426 # Functions for processing of incoming control signals (Binding Acknowledge-
427 # ment and Binding Request option) and sub-options (Home Agents list).
428 #
429 ##############################################################################
430 */
431
432 /*
433 ******************************************************************************
434 * Function: mip6_rec_ba
435 * Description: Receive a BA option and evaluate the contents.
436 * Ret value: 0 Everything is OK.
437 * IPPROTO_DONE Error code used when something went wrong.
438 ******************************************************************************
439 */
440 int
441 mip6_rec_ba(m_in, off)
442 struct mbuf *m_in; /* Mbuf containing the entire IPv6 packet */
443 int off; /* Offset from start of mbuf to start of dest option */
444 {
445 struct mip6_esm *esp; /* Home address entry */
446 struct mip6_bul *bulp; /* Entry in the Binding Update list */
447 struct in6_addr *from_src; /* Source address in received packet */
448 struct in6_addr bind_addr; /* Binding addr in BU causing this BA */
449 u_int8_t hr_flag;
450 int error;
451 #if MIP6_DEBUG
452 u_int8_t var;
453 int ii, offset;
454 #endif
455
456 /* Make sure that the BA contains a valid AH or ESP header. */
457 #if IPSEC
458 #ifndef __OpenBSD__
459 if ( !((m_in->m_flags & M_AUTHIPHDR && m_in->m_flags & M_AUTHIPDGM) ||
460 (m_in->m_flags & M_AUTHIPDGM && m_in->m_flags & M_DECRYPTED))) {
461 ip6stat.ip6s_badoptions++;
462 log(LOG_ERR, "%s: No AH or ESP included in BA\n",
463 __FUNCTION__);
464 return IPPROTO_DONE;
465 }
466 #endif
467 #endif
468
469 /* Make sure that the length field in the BA is >= 11. */
470 if (mip6_inp->ba_opt->len < IP6OPT_BALEN) {
471 ip6stat.ip6s_badoptions++;
472 log(LOG_ERR, "%s: Length field in BA < 11\n", __FUNCTION__);
473 return IPPROTO_DONE;
474 }
475
476 /* Make sure that the sent BU sequence number == received BA sequence
477 number. But first, find the source address for the incoming packet
478 (it may include a home address option). */
479 if (mip6_inp->optflag & MIP6_DSTOPT_HA)
480 from_src = &mip6_inp->ha_opt->home_addr;
481 else
482 from_src = &mip6_inp->ip6_src;
483
484 bulp = mip6_bul_find(from_src, &mip6_inp->ip6_dst);
485 if (bulp == NULL) {
486 log(LOG_ERR, "%s: No Binding Update List entry found\n",
487 __FUNCTION__);
488 return IPPROTO_DONE;
489 }
490
491 if (mip6_inp->ba_opt->seqno != bulp->seqno) {
492 ip6stat.ip6s_badoptions++;
493 log(LOG_ERR,
494 "%s: Received sequence number not equal to sent\n",
495 __FUNCTION__);
496 return IPPROTO_DONE;
497 }
498
499 #if MIP6_DEBUG
500 mip6_debug("\nReceived Binding Acknowledgement\n");
501 mip6_debug("IP Header Src: %s\n", ip6_sprintf(from_src));
502 mip6_debug("IP Header Dst: %s\n",
503 ip6_sprintf(&mip6_inp->ip6_dst));
504 mip6_debug("Type/Length/Status: %x / %u / %u\n",
505 mip6_inp->ba_opt->type,
506 mip6_inp->ba_opt->len, mip6_inp->ba_opt->status);
507 mip6_debug("Seq no/Life time: %u / %u\n", mip6_inp->ba_opt->seqno,
508 mip6_inp->ba_opt->lifetime);
509 mip6_debug("Refresh time: %u\n", mip6_inp->ba_opt->refresh);
510
511 if (mip6_inp->ba_opt->len > IP6OPT_BALEN) {
512 offset = mip6_opt_offset(m_in, off, IP6OPT_BINDING_ACK);
513 if (offset == 0)
514 goto end_debug;
515
516 mip6_debug("Sub-options present (TLV coded)\n");
517 for (ii = IP6OPT_BALEN; ii < mip6_inp->ba_opt->len; ii++) {
518 if ((ii - IP6OPT_BALEN) % 16 == 0)
519 mip6_debug("\t0x:");
520 if ((ii - IP6OPT_BALEN) % 4 == 0)
521 mip6_debug(" ");
522 m_copydata(m_in, offset + 2 + ii, sizeof(var),
523 (caddr_t)&var);
524 mip6_debug("%02x", var);
525 if ((ii - IP6OPT_BALEN + 1) % 16 == 0)
526 mip6_debug("\n");
527 }
528 if ((ii - IP6OPT_BALEN) % 16)
529 mip6_debug("\n");
530 }
531 end_debug:
532 #endif
533
534 /* Check the status field in the BA. */
535 if (mip6_inp->ba_opt->status >= 128) {
536 /* Remove the BUL entry and process the error
537 (order is important). */
538 bind_addr = bulp->bind_addr;
539 hr_flag = bulp->hr_flag;
540 mip6_bul_delete(bulp);
541
542 error = mip6_ba_error(from_src, &mip6_inp->ip6_dst,
543 &bind_addr, hr_flag);
544 return error;
545 }
546
547 /* BA was accepted. Update corresponding entry in the BUL.
548 Stop retransmitting the BU. */
549 bulp->no_of_sent_bu = 0;
550 bulp->update_rate = MIP6_MAX_UPDATE_RATE;
551 mip6_clear_retrans(bulp);
552
553 /* If the BA was received from the Home Agent the state
554 of the event state machine shall be updated. */
555 if (bulp->hr_flag) {
556 esp = mip6_esm_find(&bulp->bind_addr);
557 if (esp == NULL) {
558 log(LOG_ERR, "%s: No event-state machine found\n",
559 __FUNCTION__);
560 return IPPROTO_DONE;
561 }
562
563 /* If Dynamic Home Agent Address Discovery, change
564 HA address and remove esp->dad entry. */
565 if (esp->dad) {
566 esp->ha_hn = *from_src;
567 bulp->dst_addr = *from_src;
568 if (esp->dad->hal)
569 _FREE(esp->dad->hal, M_TEMP);
570 _FREE(esp->dad, M_TEMP);
571 esp->dad = NULL;
572 }
573
574 /* Update the state for the home address. */
575 if (esp->state == MIP6_STATE_DEREG) {
576 mip6_bul_delete(bulp);
577
578 /* Remove the tunnel for the MN */
579 mip6_tunnel(NULL, NULL, MIP6_TUNNEL_DEL,
580 MIP6_NODE_MN, (void *)esp);
581
582 /* Send BU to each CN in the BUL to remove its
583 BC entry. */
584 mip6_update_cns(&esp->home_addr,
585 &esp->home_addr, 0, 0);
586 mip6_outq_flush();
587
588 /* Don't set the state until BUs have been sent to
589 all CNs, otherwise the Home Address option will
590 not be added for the outgoing packet. */
591 esp->state = MIP6_STATE_HOME;
592 esp->coa = in6addr_any;
593 } else {
594 esp->state = MIP6_STATE_REG;
595
596 /* Create or modify a tunnel used by the MN to
597 receive incoming tunneled packets. */
598 if (mip6_tunnel(&esp->coa, &esp->ha_hn,
599 MIP6_TUNNEL_MOVE, MIP6_NODE_MN,
600 (void *)esp))
601 return IPPROTO_DONE;
602
603 /* Send BU to each CN in the BUL to update BC entry. */
604 bulp->lifetime = mip6_inp->ba_opt->lifetime;
605 bulp->refreshtime = mip6_inp->ba_opt->refresh;
606 mip6_update_cns(&esp->home_addr, &esp->coa, 0,
607 bulp->lifetime);
608 }
609 }
610 return 0;
611 }
612
613
614
615 /*
616 ******************************************************************************
617 * Function: mip6_rec_br
618 * Description: Receive a Binding Request option and evaluate the contents.
619 * Ret value: 0 Everything is OK.
620 * IPPROTO_DONE Error code used when something went wrong.
621 ******************************************************************************
622 */
623 int
624 mip6_rec_br(m_in, off)
625 struct mbuf *m_in; /* Mbuf containing the entire IPv6 packet */
626 int off; /* Offset from start of mbuf to start of dest option */
627 {
628 struct mip6_opt_bu *bu_opt; /* BU allocated in function */
629 struct in6_addr *from_src; /* Src address in rec packet */
630 struct mip6_esm *esp; /* Home address entry */
631 struct mip6_bul *bulp_cn; /* CN entry in the BU list */
632 struct mip6_bul *bulp_ha; /* HA entry in the BU list */
633 struct mip6_subbuf *subbuf = NULL; /* Sub-options for an option */
634 struct mip6_subopt_coa altcoa; /* Alternate care-of address */
635 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
636 long time_second = time.tv_sec;
637 #endif
638 #if MIP6_DEBUG
639 const struct mbuf *m = (const struct mbuf *)m_in;
640 u_int8_t var;
641 int ii, offset;
642 #endif
643
644 /* Make sure that the BA contains a valid AH or ESP header. */
645 if (mip6_inp->br_opt->type != IP6OPT_BINDING_REQ) {
646 ip6stat.ip6s_badoptions++;
647 return IPPROTO_DONE;
648 }
649
650 #if MIP6_DEBUG
651 mip6_debug("\nReceived Binding Request\n");
652 mip6_debug("Type/Length: %x / %u\n", mip6_inp->br_opt->type,
653 mip6_inp->br_opt->len);
654
655 if (mip6_inp->br_opt->len > IP6OPT_BRLEN) {
656 offset = mip6_opt_offset(m_in, off, IP6OPT_BINDING_REQ);
657 if (offset == 0)
658 goto end_debug;
659
660 mip6_debug("Sub-options present (TLV coded)\n");
661 for (ii = IP6OPT_BRLEN; ii < mip6_inp->br_opt->len; ii++) {
662 if (m->m_len < offset + 2 + ii + 1)
663 break;
664 if ((ii - IP6OPT_BRLEN) % 16 == 0)
665 mip6_debug("\t0x:");
666 if ((ii - IP6OPT_BRLEN) % 4 == 0)
667 mip6_debug(" ");
668 m_copydata(m_in, offset + 2 + ii, sizeof(var),
669 (caddr_t)&var);
670 mip6_debug("%02x", var);
671 if ((ii - IP6OPT_BRLEN + 1) % 16 == 0)
672 mip6_debug("\n");
673 }
674 if ((ii - IP6OPT_BRLEN) % 16)
675 mip6_debug("\n");
676 }
677 end_debug:
678 #endif
679
680 /* Check if the BR includes a Unique Identifier sub-option. */
681 if (mip6_inp->br_opt->len > IP6OPT_BRLEN) {
682 /* Received tunneled Router Advertisement when the MN's home
683 subnet is renumbered while the MN is away from home. */
684 /* XXX Code have to be added. */
685 } else {
686 /* A CN is requesting the MN to send a BU to update its BC. */
687 /* Find the source address for the incoming packet (it may
688 include a home address option). */
689 if (mip6_inp->optflag & MIP6_DSTOPT_HA)
690 from_src = &mip6_inp->ha_opt->home_addr;
691 else
692 from_src = &mip6_inp->ip6_src;
693
694 /* Find out which lifetime to use in the BU */
695 bulp_cn = mip6_bul_find(from_src, &mip6_inp->ip6_dst);
696 if (bulp_cn == NULL)
697 return IPPROTO_DONE;
698
699 esp = mip6_esm_find(&mip6_inp->ip6_dst);
700 if (esp == NULL) {
701 log(LOG_ERR, "%s: no event-state machine found\n",
702 __FUNCTION__);
703 return IPPROTO_DONE;
704 }
705
706 bulp_ha = mip6_bul_find(&esp->ha_hn, &mip6_inp->ip6_dst);
707 if (bulp_ha == NULL)
708 return IPPROTO_DONE;
709
710 if (bulp_ha->lifetime > bulp_cn->lifetime) {
711 /* Send a BU to the previous default router. */
712 bulp_cn->seqno += 1;
713 bu_opt = mip6_create_bu(0, 0, 0, bulp_cn->seqno,
714 bulp_ha->lifetime);
715 if (bu_opt == NULL)
716 return IPPROTO_DONE;
717
718 altcoa.type = IP6SUBOPT_ALTCOA;
719 altcoa.len = IP6OPT_COALEN;
720 altcoa.coa = bulp_cn->coa;
721 if (mip6_store_subopt(&subbuf, (caddr_t)&altcoa)
722 != 0) {
723 if (subbuf)
724 _FREE(subbuf, M_TEMP);
725 return IPPROTO_DONE;
726 }
727
728 mip6_outq_create(bu_opt, subbuf, &esp->home_addr,
729 from_src, NOT_SENT);
730
731 bulp_cn->lifetime = bulp_ha->lifetime;
732 bulp_cn->refreshtime = bulp_ha->lifetime;
733 bulp_cn->lasttime = time_second;
734 bulp_cn->no_of_sent_bu = 0;
735 bulp_cn->update_rate = MIP6_MAX_UPDATE_RATE;
736 mip6_clear_retrans(bulp_cn);
737 }
738 }
739 return 0;
740 }
741
742
743
744 /*
745 ******************************************************************************
746 * Function: mip6_rec_hal
747 * Description: Performs Dynamic Home Agent Address Discovery. Called when a
748 * list of global home agent addresses is received. Checks if the
749 * received packets source address is in the list. If not it shall
750 * be added as the first entry in the list.
751 * Save the home agent address list in the event-state machine
752 * and send a BU to the first address in the list.
753 * Note: The timeout used in the BU is a trade off between how long
754 * time it shall wait before the next entry in the list is picked
755 * and, if successful first registration, the time to perform
756 * next registration. I believe 16 - 32 seconds will be fine.
757 * Ret value: 0 Everything is OK.
758 * IPPROTO_DONE Error code used when something went wrong.
759 ******************************************************************************
760 */
761 int
762 mip6_rec_hal(src, dst, hal)
763 struct in6_addr *src; /* Incoming packet source address */
764 struct in6_addr *dst; /* Incoming packet destination address */
765 struct mip6_subopt_hal *hal; /* List of HA's on the home link */
766 {
767 struct mip6_esm *esp; /* Event-state machine */
768 struct mip6_bul *bulp; /* Entry in the Binding Update list */
769 struct mip6_subbuf *subbuf; /* Buffer containing sub-options */
770 struct mip6_bu_data bu_data; /* Data used when a BU is created */
771 int found, ii, new_len, index;
772
773 subbuf = NULL;
774
775 /* Find the event-state machine */
776 esp = mip6_esm_find(dst);
777 if (esp == NULL) {
778 log(LOG_ERR,
779 "%s: Couldn't find an event-state machine for "
780 "home address %s\n",
781 __FUNCTION__, ip6_sprintf(dst));
782 return IPPROTO_DONE;
783 }
784
785 /* If the incoming source address is not in the list of home
786 agents it is treated as the HA with highest preference.
787 Otherwise, the HA's are tried in the listed order. */
788 found = 0;
789 if (hal == NULL)
790 new_len = IP6OPT_HALEN;
791 else {
792 index = hal->len / IP6OPT_HALEN;
793 for (ii = 0; ii < index; ii++) {
794 if (IN6_ARE_ADDR_EQUAL(&hal->halist[ii], src)) {
795 found = 1;
796 break;
797 }
798 }
799 if (found)
800 new_len = hal->len;
801 else
802 new_len = hal->len + IP6OPT_HALEN;
803 }
804
805 /* Store the home agents list in the event-state machine. Add the
806 incoming packets source address if necessary. */
807 esp->dad = (struct mip6_dad *)MALLOC(sizeof(struct mip6_dad),
808 M_TEMP, M_WAITOK);
809 if (esp->dad == NULL)
810 return IPPROTO_DONE;
811 bzero(esp->dad, sizeof(struct mip6_dad));
812
813 index = new_len / IP6OPT_HALEN;
814 esp->dad->hal = (struct mip6_subopt_hal *)
815 MALLOC(sizeof(struct mip6_subopt_hal) +
816 ((index - 1) * sizeof(struct in6_addr)),
817 M_TEMP, M_WAITOK);
818 if (esp->dad->hal == NULL)
819 return IPPROTO_DONE;
820
821 esp->dad->hal->type = IP6SUBOPT_HALIST;
822 esp->dad->hal->len = new_len;
823 if (found) {
824 for (ii = 0; ii < index; ii++) {
825 bcopy(&hal->halist[ii], &esp->dad->hal->halist[ii],
826 sizeof(struct in6_addr));
827 }
828 } else {
829 bcopy(src, &esp->dad->hal->halist[0], sizeof(struct in6_addr));
830 for (ii = 0; ii < index - 1; ii++) {
831 bcopy(&hal->halist[ii], &esp->dad->hal->halist[ii+1],
832 sizeof(struct in6_addr));
833 }
834 }
835
836 /* Create a BUL entry. If there exist one already something is
837 wrong and an error message is sent to the console. */
838 bulp = mip6_bul_find(src, dst);
839 if (bulp != NULL) {
840 log(LOG_ERR,
841 "%s: A BUL entry found but it shouldn't have been. "
842 "Internal error that must be looked into\n", __FUNCTION__);
843 return IPPROTO_DONE;
844 }
845
846 bulp = mip6_bul_create(&esp->dad->hal->halist[0], &esp->home_addr,
847 &esp->coa, MIP6_BU_LIFETIME_DHAAD, 1);
848 if (bulp == NULL)
849 return IPPROTO_DONE;
850
851 /* Send a BU registration to the Home Agent with highest preference. */
852 bu_data.prefix_len = esp->prefix_len;
853 bu_data.ack = 1;
854
855 if (mip6_send_bu(bulp, &bu_data, subbuf) != 0)
856 return IPPROTO_DONE;
857
858 /* Set index to next entry to be used in the list.
859 Starts at 0 (which has been sent in this function) */
860 if ((esp->dad->hal->len / IP6OPT_HALEN) == 1)
861 esp->dad->index = 0;
862 else
863 esp->dad->index = 1;
864
865 return 0;
866 };
867
868
869
870 /*
871 ******************************************************************************
872 * Function: mip6_rec_ramn
873 * Description: Processed by a Mobile Node. Includes a Router Advertisement
874 * with a H-bit set in the flags variable (checked by the calling
875 * function).
876 * The global unicast address for the home agent with the highest
877 * preference and the time when it expires are stored.
878 * Ret value: 0 Everything is OK. Otherwise appropriate error code.
879 ******************************************************************************
880 */
881 int
882 mip6_rec_ramn(m, off)
883 struct mbuf *m; /* Mbuf containing the entire IPv6 packet */
884 int off; /* Offset from start of mbuf to start of RA */
885 {
886 struct ip6_hdr *ip6; /* IPv6 header */
887 struct nd_router_advert *ra; /* Router Advertisement */
888 struct mip6_esm *esp; /* Event-state machine */
889 struct nd_opt_hai *hai; /* Home Agent information option */
890 struct nd_opt_prefix_info *pi; /* Ptr to prefix information */
891 u_int8_t *opt_ptr; /* Ptr to current option in RA */
892 int cur_off; /* Cur offset from start of RA */
893 caddr_t icmp6msg; /* Copy of mbuf (consequtively) */
894 int16_t tmp_pref;
895 time_t tmp_lifetime;
896 int icmp6len;
897 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
898 long time_second = time.tv_sec;
899 #endif
900
901 /* Find out if the RA can be processed */
902 ip6 = mtod(m, struct ip6_hdr *);
903 if (ip6->ip6_hlim != 255) {
904 log(LOG_INFO,
905 "%s: Invalid hlim %d in Router Advertisement\n",
906 __FUNCTION__,
907 ip6->ip6_hlim);
908 return 0;
909 }
910
911 if (!IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) {
912 log(LOG_INFO,
913 "%s: Source address %s is not link-local\n", __FUNCTION__,
914 ip6_sprintf(&ip6->ip6_src));
915 return 0;
916 }
917
918 /* The mbuf data must be stored consequtively to be able to
919 cast data from it. */
920 icmp6len = m->m_pkthdr.len - off;
921 icmp6msg = (caddr_t)MALLOC(icmp6len, M_TEMP, M_WAITOK);
922 if (icmp6msg == NULL)
923 return IPPROTO_DONE;
924
925 m_copydata(m, off, icmp6len, icmp6msg);
926 ra = (struct nd_router_advert *)icmp6msg;
927
928 /* First, if a Home Agent Information option is present then the Home
929 Agent preference and lifetime is taken from the option. */
930 cur_off = sizeof(struct nd_router_advert);
931 tmp_lifetime = ntohl(ra->nd_ra_router_lifetime);
932 tmp_pref = 0;
933
934 while (cur_off < icmp6len) {
935 opt_ptr = ((caddr_t)icmp6msg + cur_off);
936 if (*opt_ptr == ND_OPT_HA_INFORMATION) {
937 /* Check the home agent information option */
938 hai = (struct nd_opt_hai *)opt_ptr;
939 if (hai->nd_opt_hai_len != 1) {
940 ip6stat.ip6s_badoptions++;
941 return IPPROTO_DONE;
942 }
943
944 tmp_pref = ntohs(hai->nd_opt_hai_pref);
945 tmp_lifetime = ntohs(hai->nd_opt_hai_lifetime);
946 cur_off += 8;
947 continue;
948 } else {
949 if (*(opt_ptr + 1) == 0) {
950 ip6stat.ip6s_badoptions++;
951 return IPPROTO_DONE;
952 }
953 cur_off += *(opt_ptr + 1) * 8;
954 }
955 }
956
957 /* Go through all prefixes and store global address for the Home
958 Agent with the highest preference. */
959 cur_off = sizeof(struct nd_router_advert);
960 while (cur_off < icmp6len) {
961 opt_ptr = ((caddr_t)icmp6msg + cur_off);
962 if (*opt_ptr == ND_OPT_PREFIX_INFORMATION) {
963 /* Check the prefix information option */
964 pi = (struct nd_opt_prefix_info *)opt_ptr;
965 if (pi->nd_opt_pi_len != 4) {
966 ip6stat.ip6s_badoptions++;
967 return IPPROTO_DONE;
968 }
969
970 if (!(pi->nd_opt_pi_flags_reserved &
971 ND_OPT_PI_FLAG_RTADDR)) {
972 cur_off += 4 * 8;
973 continue;
974 }
975
976 if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix) ||
977 IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
978 cur_off += 4 * 8;
979 continue;
980 }
981
982 /* Aggregatable unicast address, rfc2374 */
983 if (((pi->nd_opt_pi_prefix.s6_addr8[0] & 0xe0) >
984 0x10) && (pi->nd_opt_pi_prefix_len != 64)) {
985 cur_off += 4 * 8;
986 continue;
987 }
988
989 /* Only save the address if it's equal to the coa. */
990 for (esp = mip6_esmq; esp; esp = esp->next) {
991 if (in6_are_prefix_equal(
992 &pi->nd_opt_pi_prefix,
993 &esp->coa,
994 pi->nd_opt_pi_prefix_len)) {
995 if (esp->ha_fn == NULL) {
996 esp->ha_fn = (struct mip6_hafn *)
997 MALLOC(sizeof(struct mip6_hafn), M_TEMP, M_WAITOK);
998 if (esp->ha_fn == NULL)
999 return ENOBUFS;
1000 bzero(esp->ha_fn, sizeof(struct mip6_hafn));
1001
1002 esp->ha_fn->addr = pi->nd_opt_pi_prefix;
1003 esp->ha_fn->prefix_len = pi->nd_opt_pi_prefix_len;
1004 esp->ha_fn->pref = tmp_pref;
1005 esp->ha_fn->time = time_second + tmp_lifetime;
1006 } else {
1007 if (tmp_pref > esp->ha_fn->pref) {
1008 esp->ha_fn->addr = pi->nd_opt_pi_prefix;
1009 esp->ha_fn->prefix_len = pi->nd_opt_pi_prefix_len;
1010 esp->ha_fn->pref = tmp_pref;
1011 esp->ha_fn->time = time_second + tmp_lifetime;
1012 } else
1013 esp->ha_fn->time = time_second + tmp_lifetime;
1014 }
1015 }
1016 }
1017
1018 cur_off += 4 * 8;
1019 continue;
1020 } else {
1021 if (*(opt_ptr + 1) == 0) {
1022 ip6stat.ip6s_badoptions++;
1023 return IPPROTO_DONE;
1024 }
1025 cur_off += *(opt_ptr + 1) * 8;
1026 }
1027 }
1028 return 0;
1029 }
1030
1031
1032 /*
1033 ******************************************************************************
1034 * Function: mip6_route_optimize
1035 * Description: When a tunneled packet is received a BU shall be sent to the
1036 * CN if no Binding Update List entry exist or if the rate limit
1037 * for sending BUs for an existing BUL entry is not exceded.
1038 * Ret value: 0 Everything is OK.
1039 * IPPROTO_DONE Error code used when something went wrong.
1040 ******************************************************************************
1041 */
1042 int
1043 mip6_route_optimize(m)
1044 struct mbuf *m; /* Mbuf containing the entire IPv6 packet */
1045 {
1046 struct ip6_hdr *ip6;
1047 struct mip6_esm *esp;
1048 struct mip6_bul *bulp, *bulp_hr;
1049 struct mip6_subbuf *subbuf; /* Buffer containing sub-options */
1050 struct mip6_bu_data bu_data; /* Data used when a BU is created */
1051 struct mip6_subopt_coa altcoa; /* Alternate care-of address */
1052 time_t t;
1053 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
1054 long time_second = time.tv_sec;
1055 #endif
1056
1057 /* Make sure that all requirements are meet for sending a BU to
1058 the original sender of the packet. */
1059 if (!(m->m_flags & M_MIP6TUNNEL))
1060 return 0;
1061
1062 ip6 = mtod(m, struct ip6_hdr *);
1063 esp = mip6_esm_find(&ip6->ip6_dst);
1064 if (esp == NULL)
1065 return 0;
1066
1067 /* Try to find an existing BUL entry. */
1068 bulp = mip6_bul_find(&ip6->ip6_src, &esp->home_addr);
1069 if (bulp == NULL) {
1070 /* Some information needed from the BU home registration */
1071 bulp_hr = mip6_bul_find(NULL, &esp->home_addr);
1072 if (bulp_hr == NULL)
1073 return 0;
1074 bulp = mip6_bul_create(&ip6->ip6_src, &esp->home_addr,
1075 &esp->coa, bulp_hr->lifetime, 0);
1076 if (bulp == NULL)
1077 return IPPROTO_DONE;
1078 } else {
1079 /* If the existing BUL entry is waiting for an ack or
1080 has disabled sending BU, no BU shall be sent. */
1081 if ((bulp->state) || (bulp->bu_flag == 0))
1082 return 0;
1083
1084 /* Check the rate limiting for sending Binding Updates */
1085 t = (time_t)time_second;
1086 #if MIP6_DEBUG
1087 mip6_debug("%s: Rate limiting for sending BU\n", __FUNCTION__);
1088 mip6_debug("(time - bulp->lasttime) < bulp->update_rate\n");
1089 mip6_debug("time = %lu\n", (u_long)t);
1090 mip6_debug("bulp->lasttimetime = %lu\n", bulp->lasttime);
1091 mip6_debug("bulp->update_rate = %d\n", bulp->update_rate);
1092 #endif
1093 if ((t - bulp->lasttime) < bulp->update_rate)
1094 return 0;
1095 }
1096
1097 /* OK we have to send a BU. */
1098 subbuf = NULL;
1099 bu_data.prefix_len = esp->prefix_len;
1100 bu_data.ack = 0;
1101
1102 altcoa.type = IP6SUBOPT_ALTCOA;
1103 altcoa.len = IP6OPT_COALEN;
1104 altcoa.coa = bulp->coa;
1105 if (mip6_store_subopt(&subbuf, (caddr_t)&altcoa)) {
1106 if (subbuf) _FREE(subbuf, M_TEMP);
1107 return IPPROTO_DONE;
1108 }
1109
1110 if (mip6_send_bu(bulp, &bu_data, subbuf) != 0)
1111 return IPPROTO_DONE;
1112 return 0;
1113 }
1114
1115
1116
1117 /*
1118 ##############################################################################
1119 #
1120 # SENDING FUNCTIONS
1121 # These functions are called when an IPv6 packet has been created internally
1122 # by MIPv6 and shall be sent directly to its destination or when an option
1123 # (BU, BA, BR) has been created and shall be stored in the mipv6 output queue
1124 # for piggybacking on the first outgoing packet sent to the node.
1125 #
1126 ##############################################################################
1127 */
1128
1129 /*
1130 ******************************************************************************
1131 * Function: mip6_send_bu
1132 * Description: Send a Binding Update option to a node (CN, HA or MN). A new
1133 * IPv6 packet is built including an IPv6 header and a Destination
1134 * header (where the BU is stored).
1135 * Arguments: bulp - BUL entry for which the BU is sent.
1136 * data - BU data needed when the BU option is created. NULL
1137 * if the BU option stored in the BUL entry is used.
1138 * subopt - Sub-options for the BU. NULL if the BU sub-options
1139 * stored in the BUL entry is used.
1140 * Note: The following combinations of indata are possible:
1141 * data == NULL && subbuf == NULL Use existing data, i.e used for
1142 * retransmission
1143 * data != NULL && subbuf == NULL Clear existing data and send a
1144 * new BU without sub-options
1145 * data != NULL && subbuf != NULL Clear existing data and send a
1146 * new BU with new sub-options
1147 * Ret value: 0 if everything OK. Otherwise appropriate error code.
1148 ******************************************************************************
1149 */
1150 int
1151 mip6_send_bu(bulp, data, subbuf)
1152 struct mip6_bul *bulp;
1153 struct mip6_bu_data *data;
1154 struct mip6_subbuf *subbuf;
1155 {
1156 struct mbuf *m_ip6; /* IPv6 header stored in a mbuf */
1157 struct ip6_pktopts *pktopt; /* Options for IPv6 packet */
1158 struct mip6_opt_bu *bu_opt; /* Binding Update option */
1159 struct mip6_subbuf *bu_subopt; /* Binding Update sub-options */
1160 struct mip6_esm *esp; /* Home address entry */
1161 int error;
1162 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
1163 long time_second = time.tv_sec;
1164 #endif
1165 #if MIP6_DEBUG
1166 int ii;
1167 u_int8_t var;
1168 #endif
1169
1170 /* Make sure that it's allowed to send a BU */
1171 if (bulp == NULL)
1172 return 0;
1173
1174 if (!bulp->bu_flag) {
1175 log(LOG_INFO,
1176 "%s: BU not sent to host %s due to an ICMP Parameter "
1177 "Problem, Code 2, when a BU was sent previously\n",
1178 __FUNCTION__, ip6_sprintf(&bulp->dst_addr));
1179 return 0;
1180 }
1181
1182 /* Only send BU if we are not in state UNDEFINED */
1183 esp = mip6_esm_find(&bulp->bind_addr);
1184 if (esp == NULL) {
1185 log(LOG_ERR, "%s: We should never come here\n", __FUNCTION__);
1186 return 0;
1187 } else if (esp->state == MIP6_STATE_UNDEF) {
1188 log(LOG_INFO,
1189 "%s: Mobile Node with home address %s not connected to "
1190 "any network. Binding Update could not be sent.\n",
1191 __FUNCTION__, ip6_sprintf(&bulp->bind_addr));
1192 return 0;
1193 }
1194
1195 /* Evaluate parameters according to the note in the function header */
1196 if ((data == NULL) && (subbuf == NULL)) {
1197 if ((bulp->state == NULL) || (bulp->state->bu_opt == NULL)) {
1198 log(LOG_ERR,
1199 "%s: No existing BU option to send\n",
1200 __FUNCTION__);
1201 return 0;
1202 }
1203 bulp->seqno += 1;
1204 bu_opt = bulp->state->bu_opt;
1205 bu_opt->seqno = bulp->seqno;
1206 bu_subopt = bulp->state->bu_subopt;
1207 } else if (data != NULL) {
1208 mip6_clear_retrans(bulp);
1209 if (data->ack) {
1210 bulp->state = mip6_create_retrans(bulp);
1211 if (bulp->state == NULL)
1212 return ENOBUFS;
1213 }
1214
1215 bulp->seqno += 1;
1216 bu_opt = mip6_create_bu(data->prefix_len, data->ack,
1217 bulp->hr_flag,
1218 bulp->seqno, bulp->lifetime);
1219 if (bu_opt == NULL) {
1220 mip6_clear_retrans(bulp);
1221 bulp->seqno -= 1;
1222 return ENOBUFS;
1223 }
1224
1225 if (data->ack) {
1226 bulp->state->bu_opt = bu_opt;
1227 bulp->state->bu_subopt = subbuf;
1228 bu_subopt = bulp->state->bu_subopt;
1229 } else
1230 bu_subopt = subbuf;
1231 } else {
1232 log(LOG_ERR,
1233 "%s: Function parameter error. We should not come here\n",
1234 __FUNCTION__);
1235 return 0;
1236 }
1237
1238 /* Allocate necessary memory and send the BU */
1239 pktopt = (struct ip6_pktopts *)MALLOC(sizeof(struct ip6_pktopts),
1240 M_TEMP, M_NOWAIT);
1241 if (pktopt == NULL)
1242 return ENOBUFS;
1243 bzero(pktopt, sizeof(struct ip6_pktopts));
1244
1245 pktopt->ip6po_hlim = -1; /* -1 means to use default hop limit */
1246 m_ip6 = mip6_create_ip6hdr(&bulp->bind_addr, &bulp->dst_addr,
1247 IPPROTO_NONE);
1248 if(m_ip6 == NULL) {
1249 _FREE(pktopt, M_TEMP);
1250 return ENOBUFS;
1251 }
1252
1253 pktopt->ip6po_dest2 = mip6_create_dh((void *)bu_opt, bu_subopt,
1254 IPPROTO_NONE);
1255 if(pktopt->ip6po_dest2 == NULL) {
1256 _FREE(pktopt, M_TEMP);
1257 _FREE(m_ip6, M_TEMP);
1258 return ENOBUFS;
1259 }
1260
1261 mip6_config.enable_outq = 0;
1262 error = ip6_output(m_ip6, pktopt, NULL, 0, NULL, NULL);
1263 if (error) {
1264 _FREE(pktopt->ip6po_dest2, M_TEMP);
1265 _FREE(pktopt, M_TEMP);
1266 mip6_config.enable_outq = 1;
1267 log(LOG_ERR,
1268 "%s: ip6_output function failed to send BU, error = %d\n",
1269 __FUNCTION__, error);
1270 return error;
1271 }
1272 mip6_config.enable_outq = 1;
1273
1274 /* Update Binding Update List variables. */
1275 bulp->lasttime = time_second;
1276 bulp->no_of_sent_bu += 1;
1277
1278 if ( !(bu_opt->flags & MIP6_BU_AFLAG)) {
1279 if (bulp->no_of_sent_bu >= MIP6_MAX_FAST_UPDATES)
1280 bulp->update_rate = MIP6_SLOW_UPDATE_RATE;
1281 }
1282
1283 #if MIP6_DEBUG
1284 mip6_debug("\nSent Binding Update option (0x%x)\n", bu_opt);
1285 mip6_debug("IP Header Src: %s\n", ip6_sprintf(&bulp->bind_addr));
1286 mip6_debug("IP Header Dst: %s\n", ip6_sprintf(&bulp->dst_addr));
1287 mip6_debug("Type/Length/Flags: %x / %u / ", bu_opt->type, bu_opt->len);
1288 if (bu_opt->flags & MIP6_BU_AFLAG)
1289 mip6_debug("A ");
1290 if (bu_opt->flags & MIP6_BU_HFLAG)
1291 mip6_debug("H ");
1292 if (bu_opt->flags & MIP6_BU_RFLAG)
1293 mip6_debug("R ");
1294 mip6_debug("\n");
1295 mip6_debug("Seq no/Life time: %u / %u\n", bu_opt->seqno,
1296 bu_opt->lifetime);
1297 mip6_debug("Prefix length: %u\n", bu_opt->prefix_len);
1298
1299 if (bu_subopt) {
1300 mip6_debug("Sub-options present (TLV coded)\n");
1301 for (ii = 0; ii < bu_subopt->len; ii++) {
1302 if (ii % 16 == 0)
1303 mip6_debug("\t0x:");
1304 if (ii % 4 == 0)
1305 mip6_debug(" ");
1306 bcopy((caddr_t)&bu_subopt->buffer[ii],
1307 (caddr_t)&var, 1);
1308 mip6_debug("%02x", var);
1309 if ((ii + 1) % 16 == 0)
1310 mip6_debug("\n");
1311 }
1312 if (ii % 16)
1313 mip6_debug("\n");
1314 }
1315 #endif
1316
1317 _FREE(pktopt->ip6po_dest2, M_TEMP);
1318 _FREE(pktopt, M_TEMP);
1319 return 0;
1320 }
1321
1322
1323
1324 /*
1325 ******************************************************************************
1326 * Function: mip6_send_bu2fn
1327 * Description: Create a new or modify an existing Binding Update List entry,
1328 * create a Bindig Update option and a new temporary event-state
1329 * machine and send the Binding Update option to a Home Agent at
1330 * the previous foreign network.
1331 * Ret value: -
1332 ******************************************************************************
1333 */
1334 void
1335 mip6_send_bu2fn(old_coa, old_ha, coa, esm_ifp, lifetime)
1336 struct in6_addr *old_coa; /* Previous care-of address */
1337 struct mip6_hafn *old_ha; /* Previous Home Agent address */
1338 struct in6_addr *coa; /* Current coa or home address */
1339 struct ifnet *esm_ifp; /* Physical i/f used by event-state machine */
1340 u_int32_t lifetime; /* Lifetime for BU */
1341 {
1342 struct mip6_esm *esp; /* ESM for prev COA */
1343 struct mip6_bul *bulp; /* BU list entry*/
1344 struct mip6_subbuf *subbuf; /* Buffer containing sub-options */
1345 struct mip6_bu_data bu_data; /* Data used when a BU is created */
1346 struct mip6_subopt_coa altcoa; /* Alternate care-of address */
1347 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
1348 long time_second = time.tv_sec;
1349 #endif
1350
1351 /* Make sure that the Home Agent at the previous network exist and
1352 that it's still valid. */
1353 if (old_ha == NULL)
1354 return;
1355 else {
1356 if (time_second > old_ha->time) {
1357 log(LOG_INFO,
1358 "%s: Timer had expired for Home Agent on "
1359 "previous network. No BU sent\n",
1360 __FUNCTION__);
1361 return;
1362 }
1363 }
1364
1365 /* Find an existing or create a new BUL entry. */
1366 bulp = mip6_bul_find(NULL, old_coa);
1367 if (bulp == NULL) {
1368 bulp = mip6_bul_create(&old_ha->addr, old_coa, coa,
1369 lifetime, 1);
1370 if (bulp == NULL)
1371 return;
1372 } else {
1373 bulp->dst_addr = old_ha->addr;
1374 bulp->coa = *coa;
1375 bulp->lifetime = lifetime;
1376 bulp->refreshtime = lifetime;
1377 mip6_clear_retrans(bulp);
1378 }
1379
1380 /* Create an event-state machine to be used when the home address
1381 option is created for outgoing packets. The event-state machine
1382 must be removed when the BUL entry is removed. */
1383 esp = mip6_esm_create(esm_ifp, &old_ha->addr, coa, old_coa, 0,
1384 MIP6_STATE_NOTREG, TEMPORARY,
1385 MIP6_BU_LIFETIME_DEFRTR);
1386 if (esp == NULL)
1387 return;
1388
1389 /* Send the Binding Update option */
1390 subbuf = NULL;
1391
1392 bu_data.prefix_len = 0;
1393 bu_data.ack = 0;
1394
1395 altcoa.type = IP6SUBOPT_ALTCOA;
1396 altcoa.len = IP6OPT_COALEN;
1397 altcoa.coa = *coa;
1398 if (mip6_store_subopt(&subbuf, (caddr_t)&altcoa)) {
1399 if (subbuf)
1400 _FREE(subbuf, M_TEMP);
1401 return;
1402 }
1403
1404 if (mip6_send_bu(bulp, &bu_data, subbuf) != 0)
1405 return;
1406 }
1407
1408
1409
1410 /*
1411 ******************************************************************************
1412 * Function: mip6_update_cns
1413 * Description: Search the BUL for each entry with a matching home address for
1414 * which no Binding Update has been sent for the new COA.
1415 * Call a function for queueing the BU.
1416 * Note: Since this BU is stored in the MN for a couple of seconds
1417 * before it is piggybacked or flashed from the queue it may
1418 * not have the ack-bit set.
1419 * Ret value: -
1420 ******************************************************************************
1421 */
1422 void
1423 mip6_update_cns(home_addr, coa, prefix_len, lifetime)
1424 struct in6_addr *home_addr; /* Home Address for MN */
1425 struct in6_addr *coa; /* New Primary COA for MN */
1426 u_int8_t prefix_len; /* Prefix length for Home Address */
1427 u_int32_t lifetime; /* Lifetime for BU registration */
1428 {
1429 struct mip6_bul *bulp; /* Entry in the Binding Update List */
1430
1431 /* Try to find existing entry in the BUL. Home address must match. */
1432 for (bulp = mip6_bulq; bulp;) {
1433 if (IN6_ARE_ADDR_EQUAL(home_addr, &bulp->bind_addr) &&
1434 !IN6_ARE_ADDR_EQUAL(coa, &bulp->coa)) {
1435 /* Queue a BU for transmission to the node. */
1436 mip6_queue_bu(bulp, home_addr, coa,
1437 prefix_len, lifetime);
1438
1439 /* Remove BUL entry if it's a de-registration. */
1440 if (IN6_ARE_ADDR_EQUAL(home_addr, coa) ||
1441 (lifetime == 0))
1442 bulp = mip6_bul_delete(bulp);
1443 else
1444 bulp = bulp->next;
1445 } else
1446 bulp = bulp->next;
1447 }
1448 }
1449
1450
1451
1452 /*
1453 ******************************************************************************
1454 * Function: mip6_queue_bu
1455 * Description: Create a BU and a sub-option (alternate care-of address).
1456 * Update the BUL entry and store it in the output queue for
1457 * piggy-backing.
1458 * Note: Since this BU is stored in the MN for a couple of seconds
1459 * before it is piggybacked or flashed from the queue it may
1460 * not have the ack-bit set.
1461 * Ret value: -
1462 ******************************************************************************
1463 */
1464 void
1465 mip6_queue_bu(bulp, home_addr, coa, prefix_len, lifetime)
1466 struct mip6_bul *bulp; /* Entry in the Binding Update List */
1467 struct in6_addr *home_addr; /* Home Address for MN */
1468 struct in6_addr *coa; /* New Primary COA for MN */
1469 u_int8_t prefix_len; /* Prefix length for Home Address */
1470 u_int32_t lifetime; /* Lifetime for BU registration */
1471 {
1472 struct mip6_opt_bu *bu_opt; /* BU allocated in this function */
1473 struct mip6_subbuf *subbuf; /* Buffer containing sub-options */
1474 struct mip6_subopt_coa altcoa; /* Alternate care-of address */
1475 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
1476 long time_second = time.tv_sec;
1477 #endif
1478
1479 /* Check if it's allowed to send a BU to this node. */
1480 if ((coa == NULL) || (bulp == NULL))
1481 return;
1482
1483 if (bulp->bu_flag == 0) {
1484 log(LOG_INFO,
1485 "%s: BU not sent to host %s due to an ICMP Parameter "
1486 "Problem, Code 2, when a BU was sent previously\n",
1487 __FUNCTION__, ip6_sprintf(&bulp->dst_addr));
1488 return;
1489 }
1490
1491 /* Create the sub-option */
1492 subbuf = NULL;
1493 altcoa.type = IP6SUBOPT_ALTCOA;
1494 altcoa.len = IP6OPT_COALEN;
1495 altcoa.coa = *coa;
1496 if (mip6_store_subopt(&subbuf, (caddr_t)&altcoa)) {
1497 if (subbuf)
1498 _FREE(subbuf, M_TEMP);
1499 return;
1500 }
1501
1502 /* Create a BU. */
1503 bulp->seqno += 1;
1504 bu_opt = mip6_create_bu(prefix_len, 0, 0, bulp->seqno, lifetime);
1505 if (bu_opt == NULL) {
1506 log(LOG_ERR, "%s: Could not create a BU\n", __FUNCTION__);
1507 return;
1508 }
1509
1510 /* Update BUL entry */
1511 bulp->coa = *coa;
1512 bulp->lifetime = lifetime;
1513 bulp->refreshtime = lifetime;
1514 bulp->lasttime = time_second;
1515 bulp->no_of_sent_bu += 1;
1516 mip6_clear_retrans(bulp);
1517
1518 /* Add entry to the output queue for transmission to the CN. */
1519 mip6_outq_create(bu_opt, subbuf, home_addr, &bulp->dst_addr, NOT_SENT);
1520 }
1521
1522
1523
1524 /*
1525 ##############################################################################
1526 #
1527 # UTILITY FUNCTIONS
1528 # Miscellaneous functions needed for processing of incoming control signals
1529 # or events originated from the move detection algorithm.
1530 #
1531 ##############################################################################
1532 */
1533
1534 /*
1535 ******************************************************************************
1536 * Function: mip6_create_bu
1537 * Description: Create a Binding Update option for transmission.
1538 * Ret value: Pointer to the BU option or NULL.
1539 * Note: Variable seqno and lifetime set in function
1540 * mip6_update_bul_entry.
1541 ******************************************************************************
1542 */
1543 struct mip6_opt_bu *
1544 mip6_create_bu(prefix_len, ack, hr, seqno, lifetime)
1545 u_int8_t prefix_len; /* Prefix length for Home Address */
1546 int ack; /* Ack required (0 = FALSE otherwise TRUE) */
1547 int hr; /* Home Registration (0 = FALSE otherwise TRUE) */
1548 u_int16_t seqno; /* Sequence number */
1549 u_int32_t lifetime; /* Suggested lifetime for the BU registration */
1550 {
1551 struct mip6_opt_bu *bu_opt; /* BU allocated in this function */
1552
1553 /* Allocate and store Binding Update option data */
1554 bu_opt = (struct mip6_opt_bu *)MALLOC(sizeof(struct mip6_opt_bu),
1555 M_TEMP, M_WAITOK);
1556 if (bu_opt == NULL)
1557 return NULL;
1558 bzero(bu_opt, sizeof(struct mip6_opt_bu));
1559
1560 bu_opt->type = IP6OPT_BINDING_UPDATE;
1561 bu_opt->len = IP6OPT_BULEN;
1562 bu_opt->seqno = seqno;
1563 bu_opt->lifetime = lifetime;
1564
1565 /* The prefix length field is valid only for "home registration" BU. */
1566 if (hr) {
1567 bu_opt->flags |= MIP6_BU_HFLAG;
1568 bu_opt->prefix_len = prefix_len;
1569 if (ip6_forwarding)
1570 bu_opt->flags |= MIP6_BU_RFLAG;
1571 } else
1572 bu_opt->prefix_len = 0;
1573
1574 if (ack)
1575 bu_opt->flags |= MIP6_BU_AFLAG;
1576
1577 #if MIP6_DEBUG
1578 mip6_debug("\nBinding Update option created (0x%x)\n", bu_opt);
1579 #endif
1580 return bu_opt;
1581 }
1582
1583
1584
1585 /*
1586 ******************************************************************************
1587 * Function: mip6_stop_bu
1588 * Description: Stop sending a Binding Update to the host that has generated
1589 * the icmp error message.
1590 * Ret value: -
1591 ******************************************************************************
1592 */
1593 void
1594 mip6_stop_bu(ip6_dst)
1595 struct in6_addr *ip6_dst; /* Host that generated ICMP error message */
1596 {
1597 struct mip6_bul *bulp; /* Entry in the BU list */
1598
1599 /* No future BU shall be sent to this destination. */
1600 for (bulp = mip6_bulq; bulp; bulp = bulp->next) {
1601 if (IN6_ARE_ADDR_EQUAL(ip6_dst, &bulp->dst_addr))
1602 bulp->bu_flag = 0;
1603 }
1604 }
1605
1606
1607
1608 /*
1609 ******************************************************************************
1610 * Function: mip6_ba_error
1611 * Description: Each incoming BA error is taken care of by this function.
1612 * If a registration to the Home Agent failed then dynamic home
1613 * agent address discovery shall be performed. If a de-regi-
1614 * stration failed then perform the same actions as when a
1615 * BA with status equals to 0 is received.
1616 * If a registration or de-registration to the CN failed then
1617 * the error is logged, no further action is taken.
1618 * If dynamic home agent address discovery already has been
1619 * done then take the next entry in the list. If its just one
1620 * entry in the list discard it and send a BU with destination
1621 * address equals to Home Agents anycast address.
1622 * Ret value: 0 Everything is OK.
1623 * IPPROTO_DONE Error code used when something went wrong.
1624 ******************************************************************************
1625 */
1626 int
1627 mip6_ba_error(src, dst, bind_addr, hr_flag)
1628 struct in6_addr *src; /* Src address for received BA option */
1629 struct in6_addr *dst; /* Dst address for received BA option */
1630 struct in6_addr *bind_addr; /* Binding addr in BU causing this error */
1631 u_int8_t hr_flag; /* Home reg flag in BU causing this error */
1632 {
1633 struct mip6_bul *bulp; /* New BUL entry*/
1634 struct mip6_esm *esp; /* Home address entry */
1635 struct in6_addr *dst_addr;
1636 struct mip6_bu_data bu_data; /* Data used when a BU is created */
1637 u_int32_t lifetime;
1638 int error, max_index;
1639
1640 if (mip6_inp->ba_opt->status == MIP6_BA_STATUS_UNSPEC) {
1641 /* Reason unspecified
1642 Received when either a Home Agent or Correspondent Node
1643 was not able to process the BU. */
1644 log(LOG_INFO,
1645 "\nBinding Acknowledgement error = %d "
1646 "(Reason unspecified) from host %s\n",
1647 mip6_inp->ba_opt->status, ip6_sprintf(src));
1648 } else if (mip6_inp->ba_opt->status == MIP6_BA_STATUS_PROHIBIT) {
1649 /* Administratively prohibited */
1650 log(LOG_INFO,
1651 "\nBinding Acknowledgement error = %d "
1652 "(Administratively prohibited) from host %s\n",
1653 mip6_inp->ba_opt->status, ip6_sprintf(src));
1654 log(LOG_INFO, "Contact your system administrator\n");
1655 } else if (mip6_inp->ba_opt->status == MIP6_BA_STATUS_RESOURCE) {
1656 /* Insufficient resources
1657 Received when a Home Agent receives a BU with the H-bit
1658 set and insufficient space exist or can be reclaimed
1659 (sec. 8.7). */
1660 log(LOG_INFO,
1661 "\nBinding Acknowledgement error = %d "
1662 "(Insufficient resources) from host %s\n",
1663 mip6_inp->ba_opt->status, ip6_sprintf(src));
1664 } else if (mip6_inp->ba_opt->status == MIP6_BA_STATUS_HOMEREGNOSUP) {
1665 /* Home registration not supported
1666 Received when a primary care-of address registration
1667 (sec. 9.3) is done and the node is not a router
1668 implementing Home Agent functionality. */
1669 log(LOG_INFO,
1670 "\nBinding Acknowledgement error = %d "
1671 "(Home registration not supported) from host %s\n",
1672 mip6_inp->ba_opt->status, ip6_sprintf(src));
1673 } else if (mip6_inp->ba_opt->status == MIP6_BA_STATUS_SUBNET) {
1674 /* Not home subnet
1675 Received when a primary care-of address registration
1676 (sec. 9.3) is done and the home address for the binding
1677 is not an on-link IPv6 address with respect to the Home
1678 Agent's current prefix list. */
1679 log(LOG_INFO,
1680 "\nBinding Acknowledgement error = %d "
1681 "(Not home subnet) from host %s\n",
1682 mip6_inp->ba_opt->status, ip6_sprintf(src));
1683 } else if (mip6_inp->ba_opt->status == MIP6_BA_STATUS_DHAAD) {
1684 /* Dynamic Home Agent Address Discovery
1685 Received when a Mobile Node is trying to find out the
1686 global address of the home agents on its home subnetwork
1687 (sec 9.2). */
1688 error = mip6_rec_hal(src, dst, mip6_inp->hal);
1689 return error;
1690 } else if (mip6_inp->ba_opt->status == MIP6_BA_STATUS_IFLEN) {
1691 /* Incorrect subnet prefix length
1692 Received when a primary care-of address registration
1693 (sec. 9.3) is done and the prefix length in the BU
1694 differs from the length of the home agent's own knowledge
1695 of the subnet prefix length on the home link. */
1696 log(LOG_INFO,
1697 "\nBinding Acknowledgement error = %d "
1698 "(Incorrect subnet prefix length) from host %s\n",
1699 mip6_inp->ba_opt->status, ip6_sprintf(src));
1700 } else if (mip6_inp->ba_opt->status == MIP6_BA_STATUS_NOTHA) {
1701 /* Not Home Agent for this Mobile Node
1702 Received when a primary care-of address de-registration
1703 (sec. 9.4) is done and the Home Agent has no entry for
1704 this mobil node marked as "home registration" in its
1705 Binding Cache. */
1706 log(LOG_INFO,
1707 "\nBinding Acknowledgement error = %d "
1708 "(Not Home Agent for this Mobile Node) from host %s\n",
1709 mip6_inp->ba_opt->status, ip6_sprintf(src));
1710 } else {
1711 log(LOG_INFO,
1712 "\nBinding Acknowledgement error = %d (Unknown) "
1713 "from host %s\n",
1714 mip6_inp->ba_opt->status, ip6_sprintf(src));
1715 }
1716
1717 /* Furthr processing according to the desription in the header. */
1718 if (hr_flag) {
1719 esp = mip6_esm_find(bind_addr);
1720 if (esp == NULL) {
1721 log(LOG_ERR,
1722 "%s: No event-state machine found\n",
1723 __FUNCTION__);
1724 return IPPROTO_DONE;
1725 }
1726
1727 /* If it's a de-registration, clear up the ESM. */
1728 if (esp->state == MIP6_STATE_DEREG) {
1729 /* Remove the tunnel for the MN */
1730 mip6_tunnel(NULL, NULL, MIP6_TUNNEL_DEL,
1731 MIP6_NODE_MN, (void *)esp);
1732
1733 /* Send BU to each entry (CN) in the BUL to remove
1734 the BC entry. */
1735 mip6_update_cns(&esp->home_addr, &esp->home_addr,
1736 0, 0);
1737 mip6_outq_flush();
1738
1739 /* Don't set the state until BUs have been sent
1740 to all CNs, otherwise the Home Address option
1741 will not be added for the outgoing packet. */
1742 esp->state = MIP6_STATE_HOME;
1743 esp->coa = in6addr_any;
1744 return 0;
1745 }
1746
1747 /* If it's a registration, perform dynamic home agent address
1748 discovery or use the existing. */
1749 if (esp->dad) {
1750 if (esp->dad->hal->len == IP6OPT_HALEN) {
1751 if (esp->dad->hal)
1752 _FREE(esp->dad->hal, M_TEMP);
1753 _FREE(esp->dad, M_TEMP);
1754
1755 /* Build an anycast address */
1756 mip6_build_ha_anycast(&esp->ha_hn,
1757 &esp->home_addr,
1758 esp->prefix_len);
1759 if (IN6_IS_ADDR_UNSPECIFIED(&esp->ha_hn)) {
1760 log(LOG_ERR,
1761 "%s: Could not create anycast "
1762 "address for Mobile Node, "
1763 "wrong prefix length\n",
1764 __FUNCTION__);
1765 return IPPROTO_DONE;
1766 }
1767 dst_addr = &esp->ha_hn;
1768 lifetime = mip6_config.hr_lifetime;
1769 } else {
1770 dst_addr = &esp->dad->hal->halist[esp->dad->index];
1771 max_index = (esp->dad->hal->len / IP6OPT_HALEN) - 1;
1772 if (esp->dad->index == max_index)
1773 esp->dad->index = 0;
1774 else
1775 esp->dad->index += 1;
1776 lifetime = MIP6_BU_LIFETIME_DHAAD;
1777 }
1778 } else {
1779 /* Build an anycast address */
1780 mip6_build_ha_anycast(&esp->ha_hn, &esp->home_addr,
1781 esp->prefix_len);
1782 if (IN6_IS_ADDR_UNSPECIFIED(&esp->ha_hn)) {
1783 log(LOG_ERR,
1784 "%s: Could not create anycast address for Mobile "
1785 "Node, wrong prefix length\n", __FUNCTION__);
1786 return IPPROTO_DONE;
1787 }
1788 dst_addr = &esp->ha_hn;
1789 lifetime = mip6_config.hr_lifetime;
1790 }
1791
1792 /* Create a new BUL entry and send a BU to the Home Agent */
1793 bulp = mip6_bul_create(dst_addr, &esp->home_addr, &esp->coa,
1794 lifetime, 1);
1795 if (bulp == NULL)
1796 return IPPROTO_DONE;
1797
1798 bu_data.prefix_len = esp->prefix_len;
1799 bu_data.ack = 1;
1800
1801 if (mip6_send_bu(bulp, &bu_data, NULL) != 0)
1802 return IPPROTO_DONE;
1803 }
1804 return 0;
1805 }
1806
1807
1808
1809 /*
1810 ******************************************************************************
1811 * Function: mip6_prefix_lifetime
1812 * Description: Decide the remaining valid lifetime for a home address. Search
1813 * the prefix list for a match and use this lifetime value.
1814 * Note: This function is used by the MN since no test of the on-link
1815 * flag is done.
1816 * Ret value: Lifetime
1817 ******************************************************************************
1818 */
1819 u_int32_t
1820 mip6_prefix_lifetime(addr)
1821 struct in6_addr *addr; /* IPv6 address to check */
1822 {
1823 struct nd_prefix *pr; /* Entries in the prexix list */
1824 u_int32_t min_time; /* Minimum life time */
1825
1826 min_time = 0xffffffff;
1827 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1828 if (in6_are_prefix_equal(addr, &pr->ndpr_prefix.sin6_addr,
1829 pr->ndpr_plen)) {
1830 return pr->ndpr_vltime;
1831 }
1832 }
1833 return min_time;
1834 }
1835
1836
1837
1838 /*
1839 ******************************************************************************
1840 * Function: mip6_create_retrans
1841 * Description: Removes the current content of the bulp->state variable and
1842 * allocates new memory.
1843 * Ret value: Pointer to the allocated memory or NULL.
1844 ******************************************************************************
1845 */
1846 struct mip6_retrans *
1847 mip6_create_retrans(bulp)
1848 struct mip6_bul *bulp;
1849 {
1850 if (bulp == NULL)
1851 return NULL;
1852
1853 mip6_clear_retrans(bulp);
1854 bulp->state = (struct mip6_retrans *)MALLOC(
1855 sizeof(struct mip6_retrans),
1856 M_TEMP, M_WAITOK);
1857 if (bulp->state == NULL)
1858 return NULL;
1859 bzero(bulp->state, sizeof(struct mip6_retrans));
1860
1861 bulp->state->bu_opt = NULL;
1862 bulp->state->bu_subopt = NULL;
1863 bulp->state->ba_timeout = 2;
1864 bulp->state->time_left = 2;
1865 return bulp->state;
1866 }
1867
1868
1869
1870 /*
1871 ******************************************************************************
1872 * Function: mip6_clear_retrans
1873 * Description: Removes the current content of the bulp->state variable and
1874 * sets it to NULL.
1875 * Ret value: -
1876 ******************************************************************************
1877 */
1878 void
1879 mip6_clear_retrans(bulp)
1880 struct mip6_bul *bulp;
1881 {
1882 if (bulp == NULL)
1883 return;
1884
1885 if (bulp->state) {
1886 if (bulp->state->bu_opt)
1887 _FREE(bulp->state->bu_opt, M_TEMP);
1888 if (bulp->state->bu_subopt)
1889 _FREE(bulp->state->bu_subopt, M_TEMP);
1890 _FREE(bulp->state, M_TEMP);
1891 bulp->state = NULL;
1892 }
1893 return;
1894 }
1895
1896
1897
1898 /*
1899 ##############################################################################
1900 #
1901 # LIST FUNCTIONS
1902 # The Mobile Node maintains a Bindig Update List (BUL) for each node to which
1903 # a BU has been sent.
1904 # Besides from this a list of event-state machines, one for each home address
1905 # is handled by the Mobile Node and the Correspondent Node since it may
1906 # become mobile at any time.
1907 # An output queue for piggybacking of options (BU, BA, BR) on the first
1908 # outgoing packet sent to the node is also maintained. If the option has not
1909 # been sent with a packet within MIP6_OUTQ_LIFETIME it will be sent in a
1910 # separate packet.
1911 #
1912 ##############################################################################
1913 */
1914
1915 /*
1916 ******************************************************************************
1917 * Function: mip6_bul_find
1918 * Description: Find a Binding Update List entry for which a matching can be
1919 * found for both the destination and binding address.
1920 * If variable dst_addr is NULL an entry for home registration
1921 * will be searched for.
1922 * Ret value: Pointer to Binding Update List entry or NULL
1923 ******************************************************************************
1924 */
1925 struct mip6_bul *
1926 mip6_bul_find(dst_addr, bind_addr)
1927 struct in6_addr *dst_addr; /* Destination Address for Binding Update */
1928 struct in6_addr *bind_addr; /* Home Address for MN or previous COA */
1929 {
1930 struct mip6_bul *bulp; /* Entry in the Binding Update list */
1931
1932 if (dst_addr == NULL) {
1933 for (bulp = mip6_bulq; bulp; bulp = bulp->next) {
1934 if (IN6_ARE_ADDR_EQUAL(bind_addr, &bulp->bind_addr) &&
1935 (bulp->hr_flag))
1936 break;
1937 }
1938 } else {
1939 for (bulp = mip6_bulq; bulp; bulp = bulp->next) {
1940 if (IN6_ARE_ADDR_EQUAL(dst_addr, &bulp->dst_addr) &&
1941 IN6_ARE_ADDR_EQUAL(bind_addr, &bulp->bind_addr))
1942 break;
1943 }
1944 if (bulp != NULL)
1945 return bulp;
1946
1947 /* It might be that the dest address for the BU was the Home
1948 Agent anycast address and in that case we try to find it. */
1949 for (bulp = mip6_bulq; bulp; bulp = bulp->next) {
1950 if ((bulp->dst_addr.s6_addr8[15] & 0x7f) ==
1951 MIP6_ADDR_ANYCAST_HA &&
1952 IN6_ARE_ADDR_EQUAL(bind_addr, &bulp->bind_addr)) {
1953 break;
1954 }
1955 }
1956 }
1957 return bulp;
1958 }
1959
1960
1961
1962
1963 /*
1964 ******************************************************************************
1965 * Function: mip6_bul_create
1966 * Description: Create a new Binding Update List entry and insert it as the
1967 * first entry in the list.
1968 * Ret value: Pointer to Binding Update List entry or NULL.
1969 * Note: If the BUL timeout function has not been started it is started.
1970 * The BUL timeout function will be called once every second until
1971 * there are no more entries in the BUL.
1972 ******************************************************************************
1973 */
1974 struct mip6_bul *
1975 mip6_bul_create(dst_addr, bind_addr, coa, lifetime, hr)
1976 struct in6_addr *dst_addr; /* Dst address for Binding Update */
1977 struct in6_addr *bind_addr; /* Home Address for MN or previous COA */
1978 struct in6_addr *coa; /* Primary COA for MN */
1979 u_int32_t lifetime; /* Lifetime for BU */
1980 u_int8_t hr; /* Home registration flag */
1981 {
1982 struct mip6_bul *bulp; /* New Binding Update list entry */
1983 int s;
1984
1985 bulp = (struct mip6_bul *)MALLOC(sizeof(struct mip6_bul),
1986 M_TEMP, M_WAITOK);
1987 if (bulp == NULL)
1988 return NULL;
1989 bzero(bulp, sizeof(struct mip6_bul));
1990
1991 bulp->next = NULL;
1992 bulp->dst_addr = *dst_addr;
1993 bulp->bind_addr = *bind_addr;
1994 bulp->coa = *coa;
1995 bulp->lifetime = lifetime;
1996 bulp->refreshtime = lifetime;
1997 bulp->seqno = 0;
1998 bulp->lasttime = 0;
1999 bulp->no_of_sent_bu = 0;
2000 bulp->state = NULL;
2001 bulp->bu_flag = 1;
2002 bulp->hr_flag = hr;
2003 bulp->update_rate = MIP6_MAX_UPDATE_RATE;
2004
2005 /* Insert the entry as the first entry in the BUL. */
2006 s = splnet();
2007 if (mip6_bulq == NULL) {
2008 mip6_bulq = bulp;
2009 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2010 mip6_timer_bul_handle =
2011 #endif
2012 timeout(mip6_timer_bul, (void *)0, hz);
2013 } else {
2014 bulp->next = mip6_bulq;
2015 mip6_bulq = bulp;
2016 }
2017 splx(s);
2018
2019 #if MIP6_DEBUG
2020 mip6_debug("\nBinding Update List Entry created (0x%x)\n", bulp);
2021 mip6_debug("Destination Address: %s\n", ip6_sprintf(&bulp->dst_addr));
2022 mip6_debug("Binding Address: %s\n", ip6_sprintf(&bulp->bind_addr));
2023 mip6_debug("Care-of Address: %s\n", ip6_sprintf(&bulp->coa));
2024 mip6_debug("Life/Refresh time: %u / %u\n", bulp->lifetime,
2025 bulp->refreshtime);
2026 mip6_debug("Seq no/Home reg: %u / ", bulp->seqno);
2027 if (bulp->hr_flag)
2028 mip6_debug("TRUE\n");
2029 else
2030 mip6_debug("FALSE\n");
2031 #endif
2032 return bulp;
2033 }
2034
2035
2036
2037 /*
2038 ******************************************************************************
2039 * Function: mip6_bul_delete
2040 * Description: Delete the requested Binding Update list entry.
2041 * Ret value: Ptr to next entry in list or NULL if last entry removed.
2042 ******************************************************************************
2043 */
2044 struct mip6_bul *
2045 mip6_bul_delete(bul_remove)
2046 struct mip6_bul *bul_remove; /* BUL entry to be deleted */
2047 {
2048 struct mip6_bul *bulp; /* Current entry in the BU list */
2049 struct mip6_bul *bulp_prev; /* Previous entry in the BU list */
2050 struct mip6_bul *bulp_next; /* Next entry in the BU list */
2051 int s;
2052
2053 /* Find the requested entry in the BUL. */
2054 s = splnet();
2055 bulp_next = NULL;
2056 bulp_prev = NULL;
2057 for (bulp = mip6_bulq; bulp; bulp = bulp->next) {
2058 bulp_next = bulp->next;
2059 if (bulp == bul_remove) {
2060 if (bulp_prev == NULL)
2061 mip6_bulq = bulp->next;
2062 else
2063 bulp_prev->next = bulp->next;
2064 #if MIP6_DEBUG
2065 mip6_debug("\nBU List Entry deleted (0x%x)\n", bulp);
2066 #endif
2067 mip6_clear_retrans(bulp);
2068 _FREE(bulp, M_TEMP);
2069
2070 /* Remove the timer if the BUL queue is empty */
2071 if (mip6_bulq == NULL) {
2072 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2073 untimeout(mip6_timer_bul, (void *)NULL,
2074 mip6_timer_bul_handle);
2075 callout_handle_init(&mip6_timer_bul_handle);
2076 #else
2077 untimeout(mip6_timer_bul, (void *)NULL);
2078 #endif
2079 }
2080 break;
2081 }
2082 bulp_prev = bulp;
2083 }
2084 splx(s);
2085 return bulp_next;
2086 }
2087
2088
2089
2090 /*
2091 ******************************************************************************
2092 * Function: mip6_esm_find
2093 * Description: Find an event-state machine for which the Mobile Nodes home
2094 * address matches and the type is correct.
2095 * Ret value: Pointer to event-state machine entry or NULL
2096 ******************************************************************************
2097 */
2098 struct mip6_esm *
2099 mip6_esm_find(home_addr)
2100 struct in6_addr *home_addr; /* MNs home address */
2101 {
2102 struct mip6_esm *esp;
2103
2104 for (esp = mip6_esmq; esp; esp = esp->next) {
2105 if (IN6_ARE_ADDR_EQUAL(home_addr, &esp->home_addr))
2106 return esp;
2107 }
2108 return NULL;
2109 }
2110
2111
2112
2113 /*
2114 ******************************************************************************
2115 * Function: mip6_esm_create
2116 * Description: Create an event-state machine entry and add it first to the
2117 * list. If type is PERMANENT the lifetime will be set to 0xFFFF,
2118 * otherwise it will be set to the specified lifetime. If type is
2119 * TEMPORARY the timer will be started if not already started.
2120 * Ret value: Pointer to an event-state machine or NULL.
2121 ******************************************************************************
2122 */
2123 struct mip6_esm *
2124 mip6_esm_create(ifp, ha_hn, coa, home_addr, prefix_len, state,
2125 type, lifetime)
2126 struct ifnet *ifp; /* Physical i/f used by this home address */
2127 struct in6_addr *ha_hn; /* Home agent address (home network) */
2128 struct in6_addr *coa; /* Current care-of address */
2129 struct in6_addr *home_addr; /* Home address */
2130 u_int8_t prefix_len; /* Prefix length for the home address */
2131 int state; /* State of the home address */
2132 enum esm_type type; /* Permanent or Temporary esm */
2133 u_int16_t lifetime; /* Lifetime for event-state machine */
2134 {
2135 struct mip6_esm *esp, *esp_tmp;
2136 int start_timer, s;
2137
2138 esp = (struct mip6_esm *)MALLOC(sizeof(struct mip6_esm),
2139 M_TEMP, M_WAITOK);
2140 if (esp == NULL) {
2141 log(LOG_ERR,
2142 "%s: Could not create an event-state machine\n",
2143 __FUNCTION__);
2144 return NULL;
2145 }
2146 bzero(esp, sizeof(struct mip6_esm));
2147
2148 esp->next = NULL;
2149 esp->ifp = ifp;
2150 esp->ep = NULL;
2151 esp->state = state;
2152 esp->type = type;
2153 esp->home_addr = *home_addr;
2154 esp->prefix_len = prefix_len;
2155 esp->ha_hn = *ha_hn;
2156 esp->coa = *coa;
2157 esp->ha_fn = NULL;
2158 esp->dad = NULL;
2159
2160 if (type == PERMANENT) {
2161 esp->lifetime = 0xFFFF;
2162 start_timer = 0;
2163 } else {
2164 esp->lifetime = lifetime;
2165 start_timer = 1;
2166 }
2167
2168 /* If no TEMPORARY already exist and the new is TEMPORARY, start
2169 the timer. */
2170 for (esp_tmp = mip6_esmq; esp_tmp; esp_tmp = esp_tmp->next) {
2171 if (esp_tmp->type == TEMPORARY)
2172 start_timer = 0;
2173 }
2174
2175 /* Insert entry as the first entry in the event-state machine list */
2176 s = splnet();
2177 if (mip6_esmq == NULL)
2178 mip6_esmq = esp;
2179 else {
2180 esp->next = mip6_esmq;
2181 mip6_esmq = esp;
2182 }
2183 splx(s);
2184
2185 if (start_timer) {
2186 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2187 mip6_timer_esm_handle =
2188 #endif
2189 timeout(mip6_timer_esm, (void *)0, hz);
2190 }
2191 return esp;
2192 }
2193
2194
2195
2196 /*
2197 ******************************************************************************
2198 * Function: mip6_esm_delete
2199 * Description: Delete the requested event-state machine.
2200 * Ret value: Ptr to next entry in list or NULL if last entry removed.
2201 ******************************************************************************
2202 */
2203 struct mip6_esm *
2204 mip6_esm_delete(esm_remove)
2205 struct mip6_esm *esm_remove; /* Event-state machine to be deleted */
2206 {
2207 struct mip6_esm *esp; /* Current entry in event-state list */
2208 struct mip6_esm *esp_prev; /* Previous entry in event-state list */
2209 struct mip6_esm *esp_next; /* Next entry in the event-state list */
2210 int s;
2211
2212 /* Find the requested entry in the event-state list. */
2213 s = splnet();
2214 esp_next = NULL;
2215 esp_prev = NULL;
2216 for (esp = mip6_esmq; esp; esp = esp->next) {
2217 esp_next = esp->next;
2218 if (esp == esm_remove) {
2219 if (esp_prev == NULL)
2220 mip6_esmq = esp->next;
2221 else
2222 esp_prev->next = esp->next;
2223
2224 mip6_tunnel(NULL, NULL, MIP6_TUNNEL_DEL, MIP6_NODE_MN,
2225 (void *)esp);
2226
2227 if (esp->dad) {
2228 if (esp->dad->hal)
2229 _FREE(esp->dad->hal, M_TEMP);
2230 _FREE(esp->dad, M_TEMP);
2231 }
2232
2233 if (esp->ha_fn) {
2234 _FREE(esp->ha_fn, M_TEMP);
2235 esp->ha_fn = NULL;
2236 }
2237
2238 #if MIP6_DEBUG
2239 mip6_debug("\nEvent-state machine deleted (0x%x)\n",
2240 esp);
2241 #endif
2242 _FREE(esp, M_TEMP);
2243
2244 /* Remove the timer if the ESM queue is empty */
2245 if (mip6_esmq == NULL) {
2246 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2247 untimeout(mip6_timer_esm, (void *)NULL,
2248 mip6_timer_esm_handle);
2249 callout_handle_init(&mip6_timer_esm_handle);
2250 #else
2251 untimeout(mip6_timer_esm, (void *)NULL);
2252 #endif
2253 }
2254 break;
2255 }
2256 esp_prev = esp;
2257 }
2258 splx(s);
2259 return esp_next;
2260 }
2261
2262
2263
2264 /*
2265 ******************************************************************************
2266 * Function: mip6_outq_create
2267 * Description: Add an entry to the output queue and store the destination
2268 * option and the sub-option (if present) to this entry.
2269 * Ret value: 0 Everything is OK
2270 * Otherwise appropriate error code
2271 * Note: If the outqueue timeout function has not been started it is
2272 * started. The outqueue timeout function will be called once
2273 * every MIP6_OUTQ_INTERVAL second until there are no more entries
2274 * in the list.
2275 ******************************************************************************
2276 */
2277 int
2278 mip6_outq_create(opt, subbuf, src_addr, dst_addr, flag)
2279 void *opt; /* Destination option (BU, BR or BA) */
2280 struct mip6_subbuf *subbuf; /* Buffer containing destination sub-options */
2281 struct in6_addr *src_addr; /* Source address for the option */
2282 struct in6_addr *dst_addr; /* Destination address for the option */
2283 enum send_state flag; /* Flag indicating the state of the entry */
2284 {
2285 struct mip6_output *outp; /* Pointer to output list entry */
2286 int s;
2287
2288 outp = (struct mip6_output *)MALLOC(sizeof(struct mip6_output),
2289 M_TEMP, M_WAITOK);
2290 if (outp == NULL)
2291 return ENOBUFS;
2292 bzero(outp, sizeof(struct mip6_output));
2293
2294 outp->next = NULL;
2295 outp->opt = opt;
2296 outp->subopt = subbuf;
2297 outp->ip6_dst = *dst_addr;
2298 outp->ip6_src = *src_addr;
2299 outp->flag = flag;
2300 outp->lifetime = MIP6_OUTQ_LIFETIME;
2301
2302 s = splnet();
2303 if (mip6_outq == NULL) {
2304 mip6_outq = outp;
2305 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2306 mip6_timer_outqueue_handle =
2307 #endif
2308 timeout(mip6_timer_outqueue, (void *)0,
2309 hz * (MIP6_OUTQ_INTERVAL/10));
2310 } else {
2311 /* Add this entry as the first entry in the queue. */
2312 outp->next = mip6_outq;
2313 mip6_outq = outp;
2314 }
2315 splx(s);
2316 return 0;
2317 }
2318
2319
2320
2321 /*
2322 ******************************************************************************
2323 * Function: mip6_outq_delete
2324 * Description: Delete the requested output queue entry.
2325 * Ret value: Ptr to next entry in list or NULL if last entry removed.
2326 ******************************************************************************
2327 */
2328 struct mip6_output *
2329 mip6_outq_delete(oqp_remove)
2330 struct mip6_output *oqp_remove; /* Output queue entry to be deleted */
2331 {
2332 struct mip6_output *oqp; /* Current entry in output queue */
2333 struct mip6_output *oqp_prev; /* Previous entry in output queue */
2334 struct mip6_output *oqp_next; /* Next entry in the output queue */
2335 int s;
2336
2337 /* Find the requested entry in the output queue. */
2338 s = splnet();
2339 oqp_next = NULL;
2340 oqp_prev = NULL;
2341 for (oqp = mip6_outq; oqp; oqp = oqp->next) {
2342 oqp_next = oqp->next;
2343 if (oqp == oqp_remove) {
2344 if (oqp_prev == NULL)
2345 mip6_outq = oqp->next;
2346 else
2347 oqp_prev->next = oqp->next;
2348
2349 if (oqp->opt)
2350 _FREE(oqp->opt, M_TEMP);
2351
2352 if (oqp->subopt)
2353 _FREE(oqp->subopt, M_TEMP);
2354
2355 #if MIP6_DEBUG
2356 mip6_debug("\nOutput Queue entry deleted (0x%x)\n",
2357 oqp);
2358 #endif
2359 _FREE(oqp, M_TEMP);
2360
2361 /* Remove the timer if the output queue is empty */
2362 if (mip6_outq == NULL) {
2363 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2364 untimeout(mip6_timer_outqueue, (void *)NULL,
2365 mip6_timer_outqueue_handle);
2366 callout_handle_init(
2367 &mip6_timer_outqueue_handle);
2368 #else
2369 untimeout(mip6_timer_outqueue, (void *)NULL);
2370 #endif
2371 }
2372 break;
2373 }
2374 oqp_prev = oqp;
2375 }
2376 splx(s);
2377 return oqp_next;
2378 }
2379
2380
2381
2382 /*
2383 ******************************************************************************
2384 * Function: mip6_outq_flush
2385 * Description: All entries in the output queue that have not been sent are
2386 * sent and then removed. No consideration of the time left for
2387 * the entry is taken.
2388 * Ret value: -
2389 * XXX The code is almost the same as in mip6_timer_outqueue
2390 ******************************************************************************
2391 */
2392 void
2393 mip6_outq_flush()
2394 {
2395 struct mip6_output *outp; /* Ptr to current mip6 output element */
2396 struct ip6_pktopts *pktopt; /* Packet Ext headers, options and data */
2397 struct mip6_opt *opt; /* Destination option */
2398 struct mbuf *m_ip6; /* IPv6 header stored in a mbuf */
2399 int error; /* Error code from function call */
2400 int off; /* Offset from start of DH (byte) */
2401 int s;
2402
2403 /* Go through the entire output queue and send all packets that
2404 have not been sent. */
2405 s = splnet();
2406 for (outp = mip6_outq; outp;) {
2407 if (outp->flag == NOT_SENT) {
2408 m_ip6 = mip6_create_ip6hdr(&outp->ip6_src,
2409 &outp->ip6_dst,
2410 IPPROTO_NONE);
2411 if (m_ip6 == NULL) {
2412 outp = outp->next;
2413 continue;
2414 }
2415
2416 /* Allocate packet extension header. */
2417 pktopt = (struct ip6_pktopts *)
2418 MALLOC(sizeof(struct ip6_pktopts),
2419 M_TEMP, M_WAITOK);
2420 if (pktopt == NULL) {
2421 _FREE(m_ip6, M_TEMP);
2422 outp = outp->next;
2423 continue;
2424 }
2425 bzero(pktopt, sizeof(struct ip6_pktopts));
2426 pktopt->ip6po_hlim = -1; /* -1 use def hop limit */
2427
2428 opt = (struct mip6_opt *)outp->opt;
2429 off = 2;
2430 if (opt->type == IP6OPT_BINDING_UPDATE) {
2431 /* Add my BU option to the Dest Header */
2432 error = mip6_add_bu(&pktopt->ip6po_dest2,
2433 &off,
2434 (struct mip6_opt_bu *)
2435 outp->opt,
2436 outp->subopt);
2437 if (error) {
2438 _FREE(m_ip6, M_TEMP);
2439 _FREE(pktopt, M_TEMP);
2440 outp = outp->next;
2441 continue;
2442 }
2443 } else if (opt->type == IP6OPT_BINDING_ACK) {
2444 /* Add my BA option to the Dest Header */
2445 error = mip6_add_ba(&pktopt->ip6po_dest2,
2446 &off,
2447 (struct mip6_opt_ba *)
2448 outp->opt,
2449 outp->subopt);
2450 if (error) {
2451 _FREE(m_ip6, M_TEMP);
2452 _FREE(pktopt, M_TEMP);
2453 outp = outp->next;
2454 continue;
2455 }
2456 } else if (opt->type == IP6OPT_BINDING_REQ) {
2457 /* Add my BR option to the Dest Header */
2458 error = mip6_add_br(&pktopt->ip6po_dest2,
2459 &off,
2460 (struct mip6_opt_br *)
2461 outp->opt,
2462 outp->subopt);
2463 if (error) {
2464 _FREE(m_ip6, M_TEMP);
2465 _FREE(pktopt, M_TEMP);
2466 outp = outp->next;
2467 continue;
2468 }
2469 }
2470
2471 /* Disable the search of the output queue to make
2472 sure that we not end up in an infinite loop. */
2473 mip6_config.enable_outq = 0;
2474 error = ip6_output(m_ip6, pktopt, NULL, 0, NULL, NULL);
2475 if (error) {
2476 _FREE(m_ip6, M_TEMP);
2477 _FREE(pktopt, M_TEMP);
2478 mip6_config.enable_outq = 1;
2479 outp = outp->next;
2480 log(LOG_ERR,
2481 "%s: ip6_output function failed, "
2482 "error = %d\n", __FUNCTION__, error);
2483 continue;
2484 }
2485 mip6_config.enable_outq = 1;
2486 outp->flag = SENT;
2487 #if MIP6_DEBUG
2488 mip6_debug("\nEntry from Output Queue sent\n");
2489 #endif
2490 }
2491
2492 /* Remove entry from the queue that has been sent. */
2493 if (outp->flag == SENT)
2494 outp = mip6_outq_delete(outp);
2495 else
2496 outp = outp->next;
2497
2498 /* Remove the timer if the output queue is empty */
2499 if (mip6_outq == NULL) {
2500 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2501 untimeout(mip6_timer_outqueue, (void *)NULL,
2502 mip6_timer_outqueue_handle);
2503 callout_handle_init(&mip6_timer_outqueue_handle);
2504 #else
2505 untimeout(mip6_timer_outqueue, (void *)NULL);
2506 #endif
2507 }
2508 }
2509 splx(s);
2510 }
2511
2512
2513
2514 /*
2515 ##############################################################################
2516 #
2517 # TIMER FUNCTIONS
2518 # These functions are called at regular basis. They operate on the lists, e.g.
2519 # reducing timer counters and removing entries from the list if needed.
2520 #
2521 ##############################################################################
2522 */
2523
2524 /*
2525 ******************************************************************************
2526 * Function: mip6_timer_outqueue
2527 * Description: Search the outqueue for entries that have not been sent yet and
2528 * for which the lifetime has expired.
2529 * If there are more entries left in the output queue, call this
2530 * fuction again every MIP6_OUTQ_INTERVAL until the queue is
2531 * empty.
2532 * Ret value: -
2533 ******************************************************************************
2534 */
2535 void
2536 mip6_timer_outqueue(arg)
2537 void *arg; /* Not used */
2538 {
2539 struct mip6_output *outp; /* Ptr to current mip6 output element */
2540 struct ip6_pktopts *pktopt; /* Packet Ext headers, options and data */
2541 struct mip6_opt *opt; /* Destination option */
2542 struct mbuf *m_ip6; /* IPv6 header stored in a mbuf */
2543 int error; /* Error code from function call */
2544 int off; /* Offset from start of DH (byte) */
2545
2546 #ifdef __APPLE__
2547 boolean_t funnel_state;
2548 funnel_state = thread_funnel_set(network_flock, TRUE);
2549 #endif
2550 /* Go through the entire output queue and send all packets that
2551 have not been sent. */
2552 for (outp = mip6_outq; outp;) {
2553 if (outp->flag == NOT_SENT)
2554 outp->lifetime -= MIP6_OUTQ_INTERVAL;
2555
2556 if ((outp->flag == NOT_SENT) && (outp->lifetime <= 0)) {
2557 m_ip6 = mip6_create_ip6hdr(&outp->ip6_src,
2558 &outp->ip6_dst,
2559 IPPROTO_NONE);
2560 if (m_ip6 == NULL) {
2561 outp = outp->next;
2562 continue;
2563 }
2564
2565 /* Allocate packet extension header. */
2566 pktopt = (struct ip6_pktopts *)
2567 MALLOC(sizeof(struct ip6_pktopts),
2568 M_TEMP, M_WAITOK);
2569 if (pktopt == NULL) {
2570 _FREE(m_ip6, M_TEMP);
2571 outp = outp->next;
2572 continue;
2573 }
2574 bzero(pktopt, sizeof(struct ip6_pktopts));
2575 pktopt->ip6po_hlim = -1; /* -1 default hop limit */
2576
2577 opt = (struct mip6_opt *)outp->opt;
2578 off = 2;
2579 if (opt->type == IP6OPT_BINDING_UPDATE) {
2580 /* Add my BU option to the Dest Header */
2581 error = mip6_add_bu(&pktopt->ip6po_dest2,
2582 &off,
2583 (struct mip6_opt_bu *)
2584 outp->opt,
2585 outp->subopt);
2586 if (error) {
2587 _FREE(m_ip6, M_TEMP);
2588 _FREE(pktopt, M_TEMP);
2589 outp = outp->next;
2590 continue;
2591 }
2592 } else if (opt->type == IP6OPT_BINDING_ACK) {
2593 /* Add my BA option to the Dest Header */
2594 error = mip6_add_ba(&pktopt->ip6po_dest2,
2595 &off,
2596 (struct mip6_opt_ba *)
2597 outp->opt,
2598 outp->subopt);
2599 if (error) {
2600 _FREE(m_ip6, M_TEMP);
2601 _FREE(pktopt, M_TEMP);
2602 outp = outp->next;
2603 continue;
2604 }
2605 } else if (opt->type == IP6OPT_BINDING_REQ) {
2606 /* Add my BR option to the Dest Header */
2607 error = mip6_add_br(&pktopt->ip6po_dest2,
2608 &off,
2609 (struct mip6_opt_br *)
2610 outp->opt,
2611 outp->subopt);
2612 if (error) {
2613 _FREE(m_ip6, M_TEMP);
2614 _FREE(pktopt, M_TEMP);
2615 outp = outp->next;
2616 continue;
2617 }
2618 }
2619
2620 /* Disable the search of the output queue to make
2621 sure that we not end up in an infinite loop. */
2622 mip6_config.enable_outq = 0;
2623 error = ip6_output(m_ip6, pktopt, NULL, 0, NULL, NULL);
2624 if (error) {
2625 _FREE(m_ip6, M_TEMP);
2626 _FREE(pktopt, M_TEMP);
2627 mip6_config.enable_outq = 1;
2628 outp = outp->next;
2629 log(LOG_ERR,
2630 "%s: ip6_output function failed, "
2631 "error = %d\n", __FUNCTION__, error);
2632 continue;
2633 }
2634 mip6_config.enable_outq = 1;
2635 outp->flag = SENT;
2636 #if MIP6_DEBUG
2637 mip6_debug("\nEntry from Output Queue sent\n");
2638 #endif
2639 }
2640
2641 /* Remove entry from the queue that has been sent. */
2642 if (outp->flag == SENT)
2643 outp = mip6_outq_delete(outp);
2644 else
2645 outp = outp->next;
2646 }
2647
2648 if (mip6_outq != NULL) {
2649 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2650 mip6_timer_outqueue_handle =
2651 #endif
2652 timeout(mip6_timer_outqueue, (void *)0,
2653 hz * (MIP6_OUTQ_INTERVAL/10));
2654 }
2655 #ifdef __APPLE__
2656 (void) thread_funnel_set(network_flock, FALSE);
2657 #endif
2658 }
2659
2660
2661
2662 /*
2663 ******************************************************************************
2664 * Function: mip6_timer_bul
2665 * Description: Search the Binding Update list for entries for which the life-
2666 * time or refresh time has expired.
2667 * If there are more entries left in the output queue, call this
2668 * fuction again once every second until the queue is empty.
2669 * Ret value: -
2670 ******************************************************************************
2671 */
2672 void
2673 mip6_timer_bul(arg)
2674 void *arg; /* Not used */
2675 {
2676 struct mip6_bul *bulp; /* Ptr to current BUL element */
2677 struct mip6_bul *new_bulp; /* Pointer to new BUL entry */
2678 struct mip6_esm *esp; /* Home address entry */
2679 struct mip6_opt_bu *bu_opt; /* BU option to be sent */
2680 struct in6_addr *dst_addr; /* Destination address for BU */
2681 struct mip6_subbuf *subbuf; /* Buffer containing sub-options */
2682 struct mip6_bu_data bu_data; /* Data used when a BU is created */
2683 struct mip6_subopt_coa altcoa; /* Alternate care-of address */
2684 u_int32_t lifetime;
2685 int max_index, s;
2686 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
2687 long time_second = time.tv_sec;
2688 #endif
2689 #ifdef __APPLE__
2690 boolean_t funnel_state;
2691 funnel_state = thread_funnel_set(network_flock, TRUE);
2692 #endif
2693
2694 /* Go through the entire BUL and check if any BU have to be sent. */
2695 subbuf = NULL;
2696 s = splnet();
2697 for (bulp = mip6_bulq; bulp;) {
2698 /* Find the correct event-state machine */
2699 esp = mip6_esm_find(&bulp->bind_addr);
2700 if (esp == NULL) {
2701 bulp = bulp->next;
2702 continue;
2703 }
2704
2705 /* If infinity lifetime, don't decrement it. */
2706 if (bulp->lifetime == 0xffffffff) {
2707 bulp = bulp->next;
2708 continue;
2709 }
2710
2711 bulp->lifetime -= 1;
2712 if (bulp->lifetime == 0) {
2713 if ((bulp->hr_flag) && (esp->type == PERMANENT)) {
2714 /* If this BUL entry is for the Home Agent
2715 a new one must be created before the old
2716 is deleted. The new entry shall try to
2717 register the MN again.
2718 This is not done for the previous default
2719 router. */
2720 if ((esp->state == MIP6_STATE_REG) ||
2721 (esp->state == MIP6_STATE_REREG) ||
2722 (esp->state == MIP6_STATE_REGNEWCOA) ||
2723 (esp->state == MIP6_STATE_NOTREG))
2724 esp->state = MIP6_STATE_NOTREG;
2725 else if ((esp->state == MIP6_STATE_HOME) ||
2726 (esp->state == MIP6_STATE_DEREG))
2727 esp->state = MIP6_STATE_DEREG;
2728 else
2729 esp->state = MIP6_STATE_UNDEF;
2730
2731 /* If Dynamic Home Agent Address Discovery,
2732 pick the dst address from the esp->dad list
2733 and set index. */
2734 if (esp->dad) {
2735 dst_addr = &esp->dad->hal->
2736 halist[esp->dad->index];
2737 max_index = (esp->dad->hal->len /
2738 IP6OPT_HALEN) - 1;
2739 if (esp->dad->index == max_index)
2740 esp->dad->index = 0;
2741 else
2742 esp->dad->index += 1;
2743 lifetime = MIP6_BU_LIFETIME_DHAAD;
2744 } else {
2745 dst_addr = &esp->ha_hn;
2746 lifetime = mip6_config.hr_lifetime;
2747 }
2748
2749 /* Send BU to the decided destination */
2750 new_bulp = mip6_bul_create(dst_addr,
2751 &esp->home_addr,
2752 &bulp->coa,
2753 lifetime, 1);
2754 if (new_bulp == NULL)
2755 break;
2756
2757 bu_data.prefix_len = esp->prefix_len;
2758 bu_data.ack = 1;
2759
2760 if (mip6_send_bu(new_bulp, &bu_data, NULL)
2761 != 0)
2762 break;
2763 }
2764
2765 /* The BUL entry must be deleted. */
2766 bulp = mip6_bul_delete(bulp);
2767 continue;
2768 }
2769
2770 if (bulp->refreshtime > 0)
2771 bulp->refreshtime -= 1;
2772
2773 /* Skip the bul entry if its not allowed to send any further
2774 BUs to the host. */
2775 if (bulp->bu_flag == 0) {
2776 bulp = bulp->next;
2777 continue;
2778 }
2779
2780 /* Check if a BU has already been sent to the destination. */
2781 if (bulp->state != NULL) {
2782 bulp->state->time_left -= 1;
2783 if (bulp->state->time_left == 0) {
2784 if (bulp->hr_flag) {
2785 /* This is a BUL entry for the HA */
2786 bulp->state->bu_opt->lifetime =
2787 bulp->lifetime;
2788 bulp->state->bu_opt->seqno++;
2789 if (mip6_send_bu(bulp, NULL, NULL)
2790 != 0)
2791 break;
2792
2793 if (bulp->state->ba_timeout <
2794 MIP6_MAX_BINDACK_TIMEOUT)
2795 bulp->state->ba_timeout =
2796 2 * bulp->state->
2797 ba_timeout;
2798 else
2799 bulp->state->ba_timeout =
2800 (u_int8_t)MIP6_MAX_BINDACK_TIMEOUT;
2801
2802 bulp->state->time_left = bulp->state->ba_timeout;
2803 } else {
2804 /* This is a BUL entry for a Correspondent Node */
2805 if (bulp->state->ba_timeout >= MIP6_MAX_BINDACK_TIMEOUT) {
2806 /* Do NOT continue to retransmit the BU */
2807 bulp->no_of_sent_bu = 0;
2808 mip6_clear_retrans(bulp);
2809 } else {
2810 bulp->state->bu_opt->lifetime = bulp->lifetime;
2811 bulp->state->bu_opt->seqno++;
2812 if (mip6_send_bu(bulp, NULL, NULL) != 0)
2813 break;
2814
2815 bulp->state->ba_timeout = 2 * bulp->state->ba_timeout;
2816 bulp->state->time_left = bulp->state->ba_timeout;
2817 }
2818 }
2819 }
2820 bulp = bulp->next;
2821 continue;
2822 }
2823
2824 /* Refreshtime has expired and no BU has been sent to the HA
2825 so far. Then we do it. */
2826 if (bulp->refreshtime == 0) {
2827 /* Store sub-option for BU option. */
2828 altcoa.type = IP6SUBOPT_ALTCOA;
2829 altcoa.len = IP6OPT_COALEN;
2830 altcoa.coa = bulp->coa;
2831 if (mip6_store_subopt(&subbuf, (caddr_t)&altcoa)) {
2832 if (subbuf)
2833 _FREE(subbuf, M_TEMP);
2834 break;
2835 }
2836
2837 if (bulp->hr_flag) {
2838 /* Since this is an entry for the Home Agent a new BU
2839 is being sent for which we require the receiver to
2840 respond with a BA. */
2841 bu_data.prefix_len = esp->prefix_len;
2842 bu_data.ack = 1;
2843
2844 bulp->lifetime = mip6_config.hr_lifetime;
2845 if (mip6_send_bu(bulp, &bu_data, subbuf) != 0)
2846 break;
2847 } else {
2848 /* This is an entry for a CN that has requested a BU to be
2849 sent when the refreshtime expires. We will NOT require
2850 this BU to be acknowledged. */
2851 bulp->seqno += 1;
2852 bu_opt = mip6_create_bu(0, 0, 0, bulp->seqno,
2853 mip6_config.hr_lifetime);
2854 if (bu_opt == NULL)
2855 break;
2856
2857 bulp->lasttime = time_second;
2858 mip6_outq_create(bu_opt, subbuf, &bulp->bind_addr,
2859 &bulp->dst_addr, NOT_SENT);
2860 }
2861 bulp = bulp->next;
2862 continue;
2863 }
2864 bulp = bulp->next;
2865 }
2866
2867 if (mip6_bulq != NULL) {
2868 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2869 mip6_timer_bul_handle =
2870 #endif
2871 timeout(mip6_timer_bul, (void *)0, hz);
2872 }
2873 splx(s);
2874 #ifdef __APPLE__
2875 (void) thread_funnel_set(network_flock, FALSE);
2876 #endif
2877 }
2878
2879
2880
2881 /*
2882 ******************************************************************************
2883 * Function: mip6_timer_esm
2884 * Description: This function is called when an event-state machine has been
2885 * created for sending a BU to the previous default router. The
2886 * event-state machine entry is needed for the correct addition
2887 * of the home address option for outgoing packets.
2888 * When the life time for the BU expires the event-state machine
2889 * is removed as well.
2890 * Ret value: -
2891 ******************************************************************************
2892 */
2893 void
2894 mip6_timer_esm(arg)
2895 void *arg; /* Not used */
2896 {
2897 struct mip6_esm *esp; /* Current event-state machine entry */
2898 int s, start_timer;
2899 #ifdef __APPLE__
2900 boolean_t funnel_state;
2901 funnel_state = thread_funnel_set(network_flock, TRUE);
2902 #endif
2903
2904 /* Go through the entire list of event-state machines. */
2905 s = splnet();
2906 for (esp = mip6_esmq; esp;) {
2907 if (esp->type == TEMPORARY) {
2908 esp->lifetime -= 1;
2909
2910 if (esp->lifetime == 0)
2911 esp = mip6_esm_delete(esp);
2912 else
2913 esp = esp->next;
2914 continue;
2915 }
2916 esp = esp->next;
2917 }
2918
2919 /* Only start the timer if there is a TEMPORARY machine in the list. */
2920 start_timer = 0;
2921 for (esp = mip6_esmq; esp; esp = esp->next) {
2922 if (esp->type == TEMPORARY) {
2923 start_timer = 1;
2924 break;
2925 }
2926 }
2927
2928 if (start_timer) {
2929 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2930 mip6_timer_esm_handle =
2931 #endif
2932 timeout(mip6_timer_esm, (void *)0, hz);
2933 }
2934 splx(s);
2935 #ifdef __APPLE__
2936 (void) thread_funnel_set(network_flock, FALSE);
2937 #endif
2938 }
2939
2940
2941
2942 /*
2943 ##############################################################################
2944 #
2945 # IOCTL FUNCTIONS
2946 # These functions are called from mip6_ioctl.
2947 #
2948 ##############################################################################
2949 */
2950
2951 /*
2952 ******************************************************************************
2953 * Function: mip6_write_config_data_mn
2954 * Description: This function is called to write certain config values for
2955 * MIPv6. The data is written into the global config structure.
2956 * Ret value: -
2957 ******************************************************************************
2958 */
2959 int mip6_write_config_data_mn(u_long cmd, void *arg)
2960 {
2961 struct mip6_esm *p;
2962 struct ifnet *ifp;
2963 struct mip6_input_data *input;
2964 struct mip6_static_addr *np;
2965 char ifn[10];
2966 int retval = 0;
2967 struct in6_addr any = in6addr_any;
2968
2969 switch (cmd) {
2970 case SIOCACOADDR_MIP6:
2971 input = (struct mip6_input_data *) arg;
2972 np = (struct mip6_static_addr *)
2973 MALLOC(sizeof(struct mip6_static_addr),
2974 M_TEMP, M_WAITOK);
2975 if (np == NULL)
2976 return ENOBUFS;
2977
2978 np->ip6_addr = input->ip6_addr;
2979 np->prefix_len = input->prefix_len;
2980 np->ifp = ifunit(input->if_name);
2981 if (np->ifp == NULL) {
2982 strncpy(ifn, input->if_name, sizeof(ifn));
2983 return EINVAL;
2984 }
2985 LIST_INSERT_HEAD(&mip6_config.fna_list, np, addr_entry);
2986 break;
2987
2988 case SIOCAHOMEADDR_MIP6:
2989 input = (struct mip6_input_data *) arg;
2990 ifp = ifunit(input->if_name);
2991 if (ifp == NULL)
2992 return EINVAL;
2993
2994 p = mip6_esm_create(ifp, &input->ha_addr, &any,
2995 &input->ip6_addr, input->prefix_len,
2996 MIP6_STATE_UNDEF, PERMANENT, 0xFFFF);
2997 if (p == NULL)
2998 return EINVAL; /*XXX*/
2999
3000 break;
3001
3002 case SIOCSBULIFETIME_MIP6:
3003 mip6_config.bu_lifetime = ((struct mip6_input_data *)arg)->value;
3004 break;
3005
3006 case SIOCSHRLIFETIME_MIP6:
3007 mip6_config.hr_lifetime = ((struct mip6_input_data *)arg)->value;
3008 break;
3009
3010 case SIOCDCOADDR_MIP6:
3011 input = (struct mip6_input_data *) arg;
3012 for (np = mip6_config.fna_list.lh_first; np != NULL;
3013 np = np->addr_entry.le_next){
3014 if (IN6_ARE_ADDR_EQUAL(&input->ip6_addr, &np->ip6_addr))
3015 break;
3016 }
3017 if (np == NULL){
3018 retval = EADDRNOTAVAIL;
3019 return retval;
3020 }
3021 LIST_REMOVE(np, addr_entry);
3022 break;
3023 }
3024 return retval;
3025 }
3026
3027
3028
3029 /*
3030 ******************************************************************************
3031 * Function: mip6_clear_config_data_mn
3032 * Description: This function is called to clear internal lists handled by
3033 * MIPv6.
3034 * Ret value: -
3035 ******************************************************************************
3036 */
3037 int mip6_clear_config_data_mn(u_long cmd, caddr_t data)
3038 {
3039 int retval = 0;
3040 int s;
3041
3042 struct mip6_static_addr *np;
3043 struct mip6_bul *bulp;
3044
3045 s = splnet();
3046 switch (cmd) {
3047 case SIOCSFORADDRFLUSH_MIP6:
3048 for (np = LIST_FIRST(&mip6_config.fna_list); np;
3049 np = LIST_NEXT(np, addr_entry)) {
3050 LIST_REMOVE(np, addr_entry);
3051 }
3052 break;
3053
3054 case SIOCSHADDRFLUSH_MIP6:
3055 retval = EINVAL;
3056 break;
3057
3058 case SIOCSBULISTFLUSH_MIP6:
3059 for (bulp = mip6_bulq; bulp;)
3060 bulp = mip6_bul_delete(bulp);
3061 break;
3062 }
3063 splx(s);
3064 return retval;
3065 }
3066
3067
3068
3069 /*
3070 ******************************************************************************
3071 * Function: mip6_enable_func_mn
3072 * Description: This function is called to enable or disable certain functions
3073 * in mip6. The data is written into the global config struct.
3074 * Ret value: -
3075 ******************************************************************************
3076 */
3077 int mip6_enable_func_mn(u_long cmd, caddr_t data)
3078 {
3079 int enable;
3080 int retval = 0;
3081
3082 enable = ((struct mip6_input_data *)data)->value;
3083
3084 switch (cmd) {
3085 case SIOCSPROMMODE_MIP6:
3086 mip6_config.enable_prom_mode = enable;
3087 break;
3088
3089 case SIOCSBU2CN_MIP6:
3090 mip6_config.enable_bu_to_cn = enable;
3091 break;
3092
3093 case SIOCSREVTUNNEL_MIP6:
3094 mip6_config.enable_rev_tunnel = enable;
3095 break;
3096
3097 case SIOCSAUTOCONFIG_MIP6:
3098 mip6_config.autoconfig = enable;
3099 break;
3100
3101 case SIOCSEAGERMD_MIP6:
3102 mip6_eager_md(enable);
3103 break;
3104 }
3105 return retval;
3106 }