1 /* $KAME: mip6.c,v 1.20 2000/03/18 03:05:38 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, 1998, 1999 and 2000 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
33 * Copyright (c) 1999 and 2000 Ericsson Radio Systems AB
34 * All rights reserved.
36 * Author: Conny Larsson <conny.larsson@era.ericsson.se>
37 * Mattias Pettersson <mattias.pettersson@era.ericsson.se>
42 * TODO: nuke calls to in6_control, it is not supposed to be called from
46 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/malloc.h>
54 #include <sys/domain.h>
55 #include <sys/protosw.h>
56 #include <sys/socket.h>
57 #include <sys/errno.h>
59 #include <sys/kernel.h>
60 #include <sys/syslog.h>
61 #include <sys/ioccom.h>
64 #include <net/if_types.h>
65 #include <net/route.h>
66 #include <net/if_gif.h>
67 #include <net/if_dl.h>
68 #include <net/netisr.h>
70 #include <netinet/in.h>
71 #include <netinet/in_var.h>
72 #include <netinet/in.h>
73 #include <netinet/ip6.h>
74 #include <netinet/ip_encap.h>
75 #include <netinet/icmp6.h>
76 #include <netinet6/ip6_var.h>
77 #include <netinet6/ip6protosw.h>
79 #include <netinet6/mip6.h>
80 #include <netinet6/mip6_common.h>
83 #include <sys/param.h>
85 #include <sys/systm.h>
86 #include <machine/stdarg.h>
87 #include <sys/syslog.h>
90 #include <net/net_osdep.h>
92 int (*mip6_rec_ra_hook
)(struct mbuf
*, int) = 0;
94 struct in6_addr
* (*mip6_global_addr_hook
)(struct in6_addr
*) = 0;
95 struct mip6_subopt_hal
* (*mip6_hal_dynamic_hook
)(struct in6_addr
*) = 0;
96 int (*mip6_write_config_data_ha_hook
)(u_long
, void *) = 0;
97 int (*mip6_clear_config_data_ha_hook
)(u_long
, void *) = 0;
98 int (*mip6_enable_func_ha_hook
)(u_long
, caddr_t
) = 0;
100 int (*mip6_rec_ba_hook
)(struct mbuf
*, int) = 0;
101 int (*mip6_rec_br_hook
)(struct mbuf
*, int) = 0;
102 void (*mip6_stop_bu_hook
)(struct in6_addr
*) = 0;
103 int (*mip6_write_config_data_mn_hook
)(u_long
, void *) = 0;
104 int (*mip6_clear_config_data_mn_hook
)(u_long
, caddr_t
) = 0;
105 int (*mip6_enable_func_mn_hook
)(u_long
, caddr_t
) = 0;
109 int mip6_debug_is_enabled
= 0;
113 /* Declaration of Global variables. */
114 struct mip6_bc
*mip6_bcq
= NULL
; /* First entry in BC list */
115 struct mip6_na
*mip6_naq
= NULL
; /* First entry in NA retrans. list */
116 struct mip6_prefix
*mip6_pq
= NULL
; /* Ptr to prefix queue */
117 struct mip6_config mip6_config
; /* Config parameters for MIPv6 */
118 struct mip6_link_list
*mip6_llq
= NULL
; /* List of links receiving RA's */
121 #if 0 /* Phasing out MIP6_HA and MIP6_MN */
123 u_int8_t mip6_module
= MIP6_HA_MODULE
; /* Info about loaded modules (HA) */
124 #elif defined(MIP6_MN)
125 u_int8_t mip6_module
= MIP6_MN_MODULE
; /* Info about loaded modules (MN) */
127 u_int8_t mip6_module
= 0; /* Info about loaded modules (CN) */
130 u_int8_t mip6_module
= 0; /* Info about loaded modules (CN) */
133 extern struct ip6protosw mip6_tunnel_protosw
;
136 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
137 struct callout_handle mip6_timer_na_handle
;
138 struct callout_handle mip6_timer_bc_handle
;
139 struct callout_handle mip6_timer_prefix_handle
;
143 /* Definitions of some costant IP6 addresses. */
144 struct in6_addr in6addr_linklocal
;
145 struct in6_addr in6addr_sitelocal
;
146 struct in6_addr in6addr_aha_64
;
147 struct in6_addr in6addr_aha_nn
;
151 ##############################################################################
153 # INITIALIZATION AND EXIT FUNCTIONS
154 # These functions are executed when the MIPv6 code is activated and de-
155 # activated respectively.
157 ##############################################################################
161 ******************************************************************************
162 * Function: mip6_init
163 * Description: Initialization of MIPv6 variables that must be initialized
164 * before the code is executed.
165 ******************************************************************************
170 static int mip6_init_done
= 0;
175 /* Initialize global addresses. */
176 in6addr_linklocal
.s6_addr32
[0] = MIP6_ADDR_INT32_ULL
;
177 in6addr_linklocal
.s6_addr32
[1] = 0x00000000;
178 in6addr_linklocal
.s6_addr32
[2] = 0x00000000;
179 in6addr_linklocal
.s6_addr32
[3] = 0x00000000;
181 in6addr_sitelocal
.s6_addr32
[0] = MIP6_ADDR_INT32_USL
;
182 in6addr_sitelocal
.s6_addr32
[1] = 0x00000000;
183 in6addr_sitelocal
.s6_addr32
[2] = 0x00000000;
184 in6addr_sitelocal
.s6_addr32
[3] = 0x00000000;
186 in6addr_aha_64
.s6_addr32
[0] = 0x00000000;
187 in6addr_aha_64
.s6_addr32
[1] = 0xffffffff;
188 in6addr_aha_64
.s6_addr32
[2] = MIP6_ADDR_INT32_AHA2
;
189 in6addr_aha_64
.s6_addr32
[3] = MIP6_ADDR_INT32_AHA1
;
191 in6addr_aha_nn
.s6_addr32
[0] = 0x00000000;
192 in6addr_aha_nn
.s6_addr32
[1] = 0xffffffff;
193 in6addr_aha_nn
.s6_addr32
[2] = 0xffffffff;
194 in6addr_aha_nn
.s6_addr32
[3] = MIP6_ADDR_INT32_AHA1
;
196 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
197 /* Initialize handle for timer functions. */
198 callout_handle_init(&mip6_timer_na_handle
);
199 callout_handle_init(&mip6_timer_bc_handle
);
200 callout_handle_init(&mip6_timer_prefix_handle
);
203 /* Initialize global variable */
204 bzero(&mip6_config
, sizeof(struct mip6_config
));
206 /* Set default values for MIP6 configuration parameters. */
207 LIST_INIT(&mip6_config
.fna_list
);
209 mip6_config
.bu_lifetime
= 600;
210 mip6_config
.br_update
= 60;
211 mip6_config
.hr_lifetime
= 3600;
212 mip6_config
.enable_outq
= 1;
214 mip6_enable_hooks(MIP6_GENERIC_HOOKS
);
215 mip6_enable_hooks(MIP6_CONFIG_HOOKS
);
218 printf("%s: MIP6 initialized\n", __FUNCTION__
);
224 ******************************************************************************
225 * Function: mip6_exit
226 * Description: This function is called when the module is unloaded (relesed)
228 ******************************************************************************
233 struct mip6_na
*nap
, *nap_tmp
;
234 struct mip6_bc
*bcp
, *bcp_nxt
;
235 struct mip6_prefix
*prefix
;
238 /* Cancel outstanding timeout function calls. */
239 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
240 untimeout(mip6_timer_na
, (void *)NULL
, mip6_timer_na_handle
);
241 untimeout(mip6_timer_bc
, (void *)NULL
, mip6_timer_bc_handle
);
242 untimeout(mip6_timer_prefix
, (void *)NULL
, mip6_timer_prefix_handle
);
244 untimeout(mip6_timer_na
, (void *)NULL
);
245 untimeout(mip6_timer_bc
, (void *)NULL
);
246 untimeout(mip6_timer_prefix
, (void *)NULL
);
249 /* Remove each entry in every queue. */
251 for (nap
= mip6_naq
; nap
;) {
254 _FREE(nap_tmp
, M_TEMP
);
258 for (bcp
= mip6_bcq
; bcp
;) {
259 mip6_bc_delete(bcp
, &bcp_nxt
);
264 for (prefix
= mip6_pq
; prefix
;)
265 prefix
= mip6_prefix_delete(prefix
);
273 ##############################################################################
275 # RECEIVING FUNCTIONS
276 # These functions receives the incoming IPv6 packet and further processing of
277 # the packet depends on the content in the packet.
279 ##############################################################################
283 ******************************************************************************
284 * Function: mip6_rec_ctrl_sig
285 * Description: This function receives incoming signals and calls the approp-
286 * riate function for further processing of the destination
288 * Ret value: 0 Everything is OK.
289 * IPPROTO_DONE Error code used when something went wrong.
290 ******************************************************************************
293 mip6_rec_ctrl_sig(m_in
, off
)
294 struct mbuf
*m_in
; /* Mbuf containing the entire IPv6 packet */
295 int off
; /* Offset (bytes) from beginning of mbuf to start of
296 destination option */
298 register struct ip6_hdr
*ip6
; /* IPv6 header */
299 int res
; /* Result of function call */
302 static int count
= 0;
305 mip6_debug("\nMIPv6 Start processing a control signal (%d)\n", count
);
309 if (mip6_inp
== NULL
) {
310 log(LOG_ERR
, "%s: Variabel mip6_inp is NULL\n",
314 ip6
= mtod(m_in
, struct ip6_hdr
*);
316 /* Store necessary data from IPv6 header */
317 mip6_inp
->ip6_src
= ip6
->ip6_src
;
318 mip6_inp
->ip6_dst
= ip6
->ip6_dst
;
320 /* Process incoming signal (BU, BA, BR and/or Home Address option) */
321 if (mip6_inp
->optflag
& MIP6_DSTOPT_BU
) {
322 res
= mip6_rec_bu(m_in
, off
);
325 mip6_debug("\nMIPv6 Error processing control "
326 "signal BU (%d)\n", count
);
332 if (MIP6_IS_MN_ACTIVE
) {
333 if (mip6_inp
->optflag
& MIP6_DSTOPT_BA
) {
334 if (mip6_rec_ba_hook
)
335 res
= (*mip6_rec_ba_hook
)(m_in
, off
);
338 mip6_debug("\nMIPv6 Error processing control "
339 "signal BA (%d)\n", count
);
346 if (MIP6_IS_MN_ACTIVE
) {
347 if (mip6_inp
->optflag
& MIP6_DSTOPT_BR
) {
348 if (mip6_rec_br_hook
)
349 res
= (*mip6_rec_br_hook
)(m_in
, off
);
352 mip6_debug("\nMIPv6 Error processing control "
353 "signal BR (%d)\n", count
);
360 if (mip6_inp
->optflag
& MIP6_DSTOPT_HA
)
361 mip6_ha2srcaddr(m_in
);
364 mip6_debug("\nMIPv6 Finished processing a control signal (%d)\n",
373 ******************************************************************************
374 * Function: mip6_icmp6_input
375 * Description: Every ICMP6 message must be checked for errors. If a Router
376 * Advertisement is included the Home Agent List must be up-
378 * The check of the Router Advertisement can not be done in
379 * function nd6_ra_input since this function only deals with
380 * configuration issues.
381 * Ret value: 0 Everything is OK.
382 * IPPROTO_DONE Error code used when something went wrong.
383 ******************************************************************************
386 mip6_icmp6_input(m
, off
)
387 struct mbuf
*m
; /* Mbuf containing the entire IPv6 packet */
388 int off
; /* Offset from start of mbuf to icmp6 message */
390 struct ip6_hdr
*ip6
; /* IPv6 header */
391 struct ip6_hdr
*ip6_icmp
; /* IPv6 header in icmpv6 packet */
392 struct icmp6_hdr
*icmp6
; /* ICMP6 header */
393 struct mip6_bc
*bcp
; /* Binding Cache list entry */
394 struct mip6_bc
*bcp_nxt
; /* Binding Cache list entry */
395 struct nd_router_advert
*ra
; /* Router Advertisement */
396 u_int8_t
*err_ptr
; /* Octet offset for error */
397 int icmp6len
, err_off
, res
= 0;
399 ip6
= mtod(m
, struct ip6_hdr
*);
400 icmp6len
= m
->m_pkthdr
.len
- off
;
401 icmp6
= (struct icmp6_hdr
*)((caddr_t
)ip6
+ off
);
403 switch (icmp6
->icmp6_type
) {
404 case ICMP6_DST_UNREACH
:
405 /* First we have to find the destination address
406 from the original IPv6 packet. Make sure that
407 the IPv6 packet is included in the ICMPv6 packet. */
408 if ((off
+ sizeof(struct icmp6_hdr
) +
409 sizeof(struct ip6_hdr
)) >= m
->m_pkthdr
.len
)
412 ip6_icmp
= (struct ip6_hdr
*) ((caddr_t
)icmp6
+
413 sizeof(struct icmp6_hdr
));
415 /* Remove BC entry if present */
416 bcp
= mip6_bc_find(&ip6_icmp
->ip6_dst
);
417 if (bcp
&& !bcp
->hr_flag
)
418 mip6_bc_delete(bcp
, &bcp_nxt
);
421 case ICMP6_PARAM_PROB
:
422 if (icmp6
->icmp6_code
!= ICMP6_PARAMPROB_OPTION
)
425 /* First we have to find the destination address
426 from the original IPv6 packet. Make sure that
427 the ptr is within the ICMPv6 packet. */
428 err_off
= ntohl(icmp6
->icmp6_data32
[0]);
429 if ((off
+ sizeof(struct icmp6_hdr
) + err_off
) >=
433 ip6_icmp
= (struct ip6_hdr
*)((caddr_t
)icmp6
+
434 sizeof(struct icmp6_hdr
));
436 /* Check which option that failed */
437 err_ptr
= (u_int8_t
*) ((caddr_t
)icmp6
+
438 sizeof(struct icmp6_hdr
) +
441 if (MIP6_IS_MN_ACTIVE
&& (*err_ptr
== IP6OPT_BINDING_UPDATE
)) {
442 if (mip6_stop_bu_hook
)
443 (*mip6_stop_bu_hook
)(&ip6_icmp
->ip6_dst
);
446 if (*err_ptr
== IP6OPT_HOME_ADDRESS
) {
448 "Node %s does not recognize Home Address option\n",
449 ip6_sprintf(&ip6_icmp
->ip6_dst
));
450 /* The message is discarded by the icmp code. */
454 case ND_ROUTER_ADVERT
:
455 if (icmp6
->icmp6_code
!= 0)
457 if (icmp6len
< sizeof(struct nd_router_advert
))
460 ra
= (struct nd_router_advert
*)icmp6
;
461 if ((ra
->nd_ra_flags_reserved
& ND_RA_FLAG_HA
) == 0)
464 if (mip6_rec_ra_hook
) {
465 res
= mip6_rec_ra_hook(m
, off
);
476 ##############################################################################
478 # CONTROL SIGNAL FUNCTIONS
479 # Functions for processing of incoming control signals (Binding Update and
480 # Home Address option).
482 ##############################################################################
486 ******************************************************************************
487 * Function: mip6_rec_bu
488 * Description: Receive a Binding Update option and evaluate the contents.
489 * Ret value: 0 Everything is OK.
490 * IPPROTO_DONE Error code used when something went wrong.
491 ******************************************************************************
494 mip6_rec_bu(m_in
, off
)
495 struct mbuf
*m_in
; /* Mbuf containing the entire IPv6 packet */
496 int off
; /* Offset from start of mbuf to start of dest option */
498 struct in6_addr
*src_addr
; /* Src addr for HA sending BU */
499 struct mip6_subopt_hal
*hal
; /* Home Agents List sub-option */
500 struct mip6_bc
*bcp
; /* Binding Cache list entry */
501 struct mip6_bc
*bcp_nxt
;
502 struct in6_addr
*coa
; /* COA of the MN sending the BU */
503 struct mip6_subbuf
*subbuf
; /* Buffer containing sub-options */
504 struct in6_addr ll_allnode
; /* Link local all nodes address */
505 u_int32_t min_time
; /* Minimum lifetime to be sent in BA */
506 u_long na_flags
= 0; /* Flags for NA message */
507 int send_na
; /* If node becomes HA for MN, broadcast NA */
517 /* Find the care-of address used by the MN when sending the BU. */
519 coa
= &mip6_inp
->coa
->coa
;
521 coa
= &mip6_inp
->ip6_src
;
523 /* Make sure that the BU contains a valid AH or ESP header. */
526 if ( !((m_in
->m_flags
& M_AUTHIPHDR
&& m_in
->m_flags
& M_AUTHIPDGM
) ||
527 (m_in
->m_flags
& M_AUTHIPDGM
&& m_in
->m_flags
& M_DECRYPTED
))) {
528 ip6stat
.ip6s_badoptions
++;
530 "%s: No AH or ESP header in BU from host %s\n",
538 /* Make sure that the BU contains a valid Home Address option. */
539 if ((mip6_inp
->optflag
& MIP6_DSTOPT_HA
) == 0) {
540 ip6stat
.ip6s_badoptions
++;
542 "%s: No Home Address option included in BU from host %s\n",
543 __FUNCTION__
, ip6_sprintf(coa
));
547 /* Make sure that the length field in the BU is >= 8. */
548 if (mip6_inp
->bu_opt
->len
< IP6OPT_BULEN
) {
549 ip6stat
.ip6s_badoptions
++;
551 "%s: Length field to short (%d) in BU from host %s\n",
552 __FUNCTION__
, mip6_inp
->bu_opt
->len
, ip6_sprintf(coa
));
556 /* The sequence no in the BU must be greater than or equal to the
557 sequence number in the previous BU recieved (modulo 2^^16). */
559 bcp
= mip6_bc_find(&mip6_inp
->ha_opt
->home_addr
);
561 if (MIP6_LEQ(mip6_inp
->bu_opt
->seqno
, bcp
->seqno
)) {
562 ip6stat
.ip6s_badoptions
++;
564 "%s: Received sequence number (%d) <= "
565 "current (%d) in BU from host %s\n",
566 __FUNCTION__
, mip6_inp
->bu_opt
->seqno
,
567 bcp
->seqno
, ip6_sprintf(coa
));
576 mip6_debug("\nReceived Binding Update\n");
577 mip6_debug("IP Header Src: %s\n",
578 ip6_sprintf(&mip6_inp
->ip6_src
));
579 mip6_debug("IP Header Dst: %s\n",
580 ip6_sprintf(&mip6_inp
->ip6_dst
));
581 mip6_debug("Type/Length/Flags: %x / %u / ",
582 mip6_inp
->bu_opt
->type
, mip6_inp
->bu_opt
->len
);
583 if (mip6_inp
->bu_opt
->flags
& MIP6_BU_AFLAG
)
585 if (mip6_inp
->bu_opt
->flags
& MIP6_BU_HFLAG
)
587 if (mip6_inp
->bu_opt
->flags
& MIP6_BU_RFLAG
)
590 mip6_debug("Seq no/Life time: %u / %u\n",
591 mip6_inp
->bu_opt
->seqno
,
592 mip6_inp
->bu_opt
->lifetime
);
593 mip6_debug("Prefix length: %u\n",
594 mip6_inp
->bu_opt
->prefix_len
);
596 if (mip6_inp
->bu_opt
->len
> IP6OPT_BULEN
) {
597 offset
= mip6_opt_offset(m_in
, off
, IP6OPT_BINDING_UPDATE
);
598 if (offset
== 0) goto end_debug
;
600 mip6_debug("Sub-options present (TLV coded)\n");
601 for (ii
= IP6OPT_BULEN
; ii
< mip6_inp
->bu_opt
->len
; ii
++) {
602 if ((ii
- IP6OPT_BULEN
) % 16 == 0)
604 if ((ii
- IP6OPT_BULEN
) % 4 == 0)
606 m_copydata(m_in
, offset
+ 2 + ii
, sizeof(var
),
608 mip6_debug("%02x", var
);
609 if ((ii
- IP6OPT_BULEN
+ 1) % 16 == 0)
612 if ((ii
- IP6OPT_BULEN
) % 16)
618 /* Shall Dynamic Home Agent Address Discovery be performed? */
622 if (MIP6_IS_HA_ACTIVE
) {
623 if ((mip6_inp
->ip6_dst
.s6_addr8
[15] & 0x7f) ==
624 MIP6_ADDR_ANYCAST_HA
) {
625 if (mip6_global_addr_hook
)
626 src_addr
= (*mip6_global_addr_hook
)
627 (&mip6_inp
->ip6_dst
);
628 if (src_addr
== NULL
) {
630 "%s: No global source address found\n",
635 if (mip6_hal_dynamic_hook
)
636 hal
= (*mip6_hal_dynamic_hook
)(src_addr
);
637 if (mip6_store_subopt(&subbuf
, (caddr_t
)hal
)) {
638 if (subbuf
) _FREE(subbuf
, M_TEMP
);
641 error
= mip6_send_ba(src_addr
,
642 &mip6_inp
->ha_opt
->home_addr
,
643 coa
, subbuf
, MIP6_BA_STATUS_DHAAD
,
644 mip6_inp
->bu_opt
->seqno
, 0);
649 /* Check if BU includes Unique Identifier sub-option is present. */
650 /* XXX Code have to be added. */
652 /* Check if this is a request to cache a binding for the MN. */
653 if ((mip6_inp
->bu_opt
->lifetime
!= 0) &&
654 (! IN6_ARE_ADDR_EQUAL(&mip6_inp
->ha_opt
->home_addr
, coa
))) {
655 /* The request to cache the binding depends on if the H-bit
656 is set or not in the BU. */
658 if (mip6_inp
->bu_opt
->flags
& MIP6_BU_HFLAG
) {
659 /* The H-bit is set. Register the primary coa. Is the
660 node is a router implementing HA functionality */
661 if ((!ip6_forwarding
|| !MIP6_IS_HA_ACTIVE
) &&
662 (mip6_inp
->bu_opt
->flags
& MIP6_BU_AFLAG
)) {
663 error
= mip6_send_ba(
665 &mip6_inp
->ha_opt
->home_addr
,
666 coa
, NULL
, MIP6_BA_STATUS_HOMEREGNOSUP
,
667 mip6_inp
->bu_opt
->seqno
, 0);
671 /* Verify that the home address is an on-link IPv6
672 address and that the prefix length is correct. */
673 res
= mip6_addr_on_link(&mip6_inp
->ha_opt
->home_addr
,
674 mip6_inp
->bu_opt
->prefix_len
);
676 (mip6_inp
->bu_opt
->flags
& MIP6_BU_AFLAG
)) {
677 error
= mip6_send_ba(
679 &mip6_inp
->ha_opt
->home_addr
,
681 mip6_inp
->bu_opt
->seqno
, 0);
685 /* Other reject reasons may be added, e.g.
686 insufficient resources to serve a MN. */
687 /* XXX Code may be added. */
689 /* The BU is OK and this node becomes the HA for
690 the MN. Find out which lifetime to use in the BA */
691 min_time
= mip6_min_lifetime(
692 &mip6_inp
->ha_opt
->home_addr
,
693 mip6_inp
->bu_opt
->prefix_len
);
694 min_time
= min(min_time
,
695 mip6_inp
->bu_opt
->lifetime
);
697 /* Create a new or update an existing BC entry. */
698 rtr
= mip6_inp
->bu_opt
->flags
& MIP6_BU_RFLAG
;
699 bcp
= mip6_bc_find(&mip6_inp
->ha_opt
->home_addr
);
701 mip6_bc_update(bcp
, coa
, min_time
, 1, rtr
,
702 mip6_inp
->bu_opt
->prefix_len
,
703 mip6_inp
->bu_opt
->seqno
,
704 bcp
->info
, bcp
->lasttime
);
706 bcp
= mip6_bc_create(
707 &mip6_inp
->ha_opt
->home_addr
,
708 coa
, min_time
, 1, rtr
,
709 mip6_inp
->bu_opt
->prefix_len
,
710 mip6_inp
->bu_opt
->seqno
);
715 /* Send a BA to the mobile node if the A-bit is
717 if (mip6_inp
->bu_opt
->flags
& MIP6_BU_AFLAG
) {
718 error
= mip6_send_ba(&mip6_inp
->ip6_dst
,
722 MIP6_BA_STATUS_ACCEPT
,
729 /* The HA shall act as a proxy for the MN while it
730 is at a FN. Create a new or move an existing
732 error
= mip6_tunnel(&mip6_inp
->ip6_dst
,
734 MIP6_TUNNEL_MOVE
, MIP6_NODE_HA
,
738 error
= mip6_proxy(&bcp
->home_addr
,
739 &mip6_inp
->ip6_dst
, RTM_ADD
);
742 mip6_debug("%s: set proxy error = %d\n",
743 __FUNCTION__
, error
);
748 /* Create a NA for the MN if the HA did not already
749 have a BC entry for this MN marked as a "home
751 The first NA will be sent in the create function,
752 the remaining NAs are sent by the timer function. */
754 ll_allnode
= in6addr_linklocal_allnodes
;
755 na_flags
|= ND_NA_FLAG_OVERRIDE
;
756 if (mip6_inp
->bu_opt
->flags
& MIP6_BU_RFLAG
)
757 na_flags
|= ND_NA_FLAG_ROUTER
;
759 mip6_na_create(&mip6_inp
->ha_opt
->home_addr
,
761 &mip6_inp
->ha_opt
->home_addr
,
762 mip6_inp
->bu_opt
->prefix_len
,
766 /* The H-bit is NOT set. Request to cache a binding.
767 Create a new or update an existing BC entry. */
768 rtr
= mip6_inp
->bu_opt
->flags
& MIP6_BU_RFLAG
;
769 bcp
= mip6_bc_find(&mip6_inp
->ha_opt
->home_addr
);
771 mip6_bc_update(bcp
, coa
,
772 mip6_inp
->bu_opt
->lifetime
,
774 mip6_inp
->bu_opt
->prefix_len
,
775 mip6_inp
->bu_opt
->seqno
,
776 bcp
->info
, bcp
->lasttime
);
778 bcp
= mip6_bc_create(
779 &mip6_inp
->ha_opt
->home_addr
,
780 coa
, mip6_inp
->bu_opt
->lifetime
,
781 0, rtr
, mip6_inp
->bu_opt
->prefix_len
,
782 mip6_inp
->bu_opt
->seqno
);
787 /* Send a BA to the mobile node if the A-bit is
789 if (mip6_inp
->bu_opt
->flags
& MIP6_BU_AFLAG
) {
790 error
= mip6_send_ba(&mip6_inp
->ip6_dst
,
793 MIP6_BA_STATUS_ACCEPT
,
802 /* Check if this is a request to delete a binding for the MN. */
803 if ((mip6_inp
->bu_opt
->lifetime
== 0) ||
804 (IN6_ARE_ADDR_EQUAL(&mip6_inp
->ha_opt
->home_addr
, coa
))) {
805 /* The request to delete the binding depends on if the
806 H-bit is set or not in the BU. */
807 if (mip6_inp
->bu_opt
->flags
& MIP6_BU_HFLAG
) {
808 /* The H-bit is set. Make sure that there is an
809 entry in the BC marked as "home registration"
812 if (((bcp
== NULL
) || (bcp
->hr_flag
== 0)) &&
813 (mip6_inp
->bu_opt
->flags
& MIP6_BU_AFLAG
)) {
814 error
= mip6_send_ba(
816 &mip6_inp
->ha_opt
->home_addr
,
817 coa
, NULL
, MIP6_BA_STATUS_NOTHA
,
818 mip6_inp
->bu_opt
->seqno
, 0);
822 /* The HA should delete BC entry, remove tunnel and
823 stop acting as a proxy for the MN. */
824 error
= mip6_bc_delete(bcp
, &bcp_nxt
);
828 /* Send a BA to the MN if the A-bit is set. */
829 if (mip6_inp
->bu_opt
->flags
& MIP6_BU_AFLAG
) {
830 error
= mip6_send_ba(
832 &mip6_inp
->ha_opt
->home_addr
,
833 coa
, NULL
, MIP6_BA_STATUS_ACCEPT
,
834 mip6_inp
->bu_opt
->seqno
, 0);
839 /* The H-bit is NOT set. Request the CN to delete
842 error
= mip6_bc_delete(bcp
, &bcp_nxt
);
847 if (mip6_inp
->bu_opt
->flags
& MIP6_BU_AFLAG
) {
848 error
= mip6_send_ba(
850 &mip6_inp
->ha_opt
->home_addr
,
851 coa
, NULL
, MIP6_BA_STATUS_ACCEPT
,
852 mip6_inp
->bu_opt
->seqno
, 0);
865 ******************************************************************************
866 * Function: mip6_ha2srcaddr
867 * Description: Copy Home Address option to IPv6 header source address, i.e
868 * replacing the existing source address.
869 ******************************************************************************
873 struct mbuf
*m
; /* The entire IPv6 packet */
875 register struct ip6_hdr
*ip6
; /* IPv6 header */
878 mip6_debug("\nReceived Home Address Option\n");
879 mip6_debug("Type/Length: %x / %u\n", mip6_inp
->ha_opt
->type
,
880 mip6_inp
->ha_opt
->len
);
881 mip6_debug("Home Address: %s\n",
882 ip6_sprintf(&mip6_inp
->ha_opt
->home_addr
));
885 /* Copy the Home Address option address to the Source Address */
886 ip6
= mtod(m
, struct ip6_hdr
*);
887 ip6
->ip6_src
= mip6_inp
->ha_opt
->home_addr
;
893 ##############################################################################
896 # These functions are called when an IPv6 packet has been created internally
897 # by MIPv6 and shall be sent directly to its destination or when an option
898 # (BU, BA, BR) has been created and shall be stored in the mipv6 output queue
899 # for piggybacking on the first outgoing packet sent to the node.
901 ##############################################################################
905 ******************************************************************************
906 * Function: mip6_send_ba
907 * Description: Send a Binding Acknowledgement back to the Mobile Node. A new
908 * IPv6 packet is built including a IPv6 header, a Routing header
909 * and a Destination header (where the BA is stored).
911 * IPPROTO_DONE If anything goes wrong.
912 ******************************************************************************
915 mip6_send_ba(ip6_src
, ip6_dst
, coa
, subbuf
, status
, seqno
, lifetime
)
916 struct in6_addr
*ip6_src
; /* Source address for packet */
917 struct in6_addr
*ip6_dst
; /* Destination address for packet */
918 struct in6_addr
*coa
; /* Care-of address for MN */
919 struct mip6_subbuf
*subbuf
; /* Home Agents List sub-option */
920 u_int8_t status
; /* Result of the Binding Update request */
921 u_int16_t seqno
; /* Seq no in the BU being acknowledged */
922 u_int32_t lifetime
; /* Proposed lifetime in the BU */
924 struct mbuf
*m_ip6
; /* IPv6 header stored in a mbuf */
925 struct mip6_opt_ba
*ba_opt
; /* BA allocated in this function */
926 struct ip6_pktopts
*opt
; /* Options for IPv6 packet */
933 opt
= (struct ip6_pktopts
*)MALLOC ip6_pktopts
),
937 bzero(opt
, sizeof(struct ip6_pktopts
));
939 opt
->ip6po_hlim
= -1; /* -1 means to use default hop limit */
940 m_ip6
= mip6_create_ip6hdr(ip6_src
, ip6_dst
, IPPROTO_NONE
);
944 opt
->ip6po_rhinfo
.ip6po_rhi_rthdr
= mip6_create_rh(coa
,
946 if(opt
->ip6po_rhinfo
.ip6po_rhi_rthdr
== NULL
)
949 ba_opt
= mip6_create_ba(status
, seqno
, lifetime
);
953 opt
->ip6po_dest2
= mip6_create_dh((void *)ba_opt
, subbuf
,
955 if(opt
->ip6po_dest2
== NULL
)
958 mip6_config
.enable_outq
= 0;
959 error
= ip6_output(m_ip6
, opt
, NULL
, 0, NULL
, NULL
);
961 _FREE(opt
->ip6po_rhinfo
.ip6po_rhi_rthdr
, M_TEMP
);
962 _FREE(opt
->ip6po_dest2
, M_TEMP
);
963 _FREE(ba_opt
, M_TEMP
);
964 mip6_config
.enable_outq
= 1;
966 "%s: ip6_output function failed to send BA, error = %d\n",
967 __FUNCTION__
, error
);
970 mip6_config
.enable_outq
= 1;
973 mip6_debug("\nSent Binding Acknowledgement\n");
974 mip6_debug("IP Header Src: %s\n", ip6_sprintf(ip6_src
));
975 mip6_debug("IP Header Dst: %s\n", ip6_sprintf(ip6_dst
));
976 mip6_debug("Type/Length/Status: %x / %u / %u\n",
977 ba_opt
->type
, ba_opt
->len
, ba_opt
->status
);
978 mip6_debug("Seq no/Life time: %u / %u\n",
979 ba_opt
->seqno
, ba_opt
->lifetime
);
980 mip6_debug("Refresh time: %u\n", ba_opt
->refresh
);
983 mip6_debug("Sub-options present (TLV coded)\n");
984 for (ii
= 0; ii
< subbuf
->len
; ii
++) {
989 bcopy((caddr_t
)&subbuf
->buffer
[ii
], (caddr_t
)&var
, 1);
990 mip6_debug("%02x", var
);
991 if ((ii
+ 1) % 16 == 0)
999 _FREE(opt
->ip6po_rhinfo
.ip6po_rhi_rthdr
, M_TEMP
);
1000 _FREE(opt
->ip6po_dest2
, M_TEMP
);
1001 _FREE(ba_opt
, M_TEMP
);
1008 ******************************************************************************
1009 * Function: mip6_send_na
1010 * Description: Sends a Neighbor Advertisement for a specific prefix. If the
1011 * address is a aggregatable unicast address, i.e. prefix length
1012 * is 64, a NA is sent to the site local and link local addresse
1015 ******************************************************************************
1019 struct mip6_na
*nap
; /* Neighbor Advertisement sent */
1021 struct mip6_prefix
*pq
;
1022 struct nd_prefix
*pr
; /* Prefix list entry */
1023 struct in6_addr new_addr
; /* New constructed address */
1024 struct in6_addr sl_addr
; /* Site local address */
1029 mip6_debug("\nSent Neighbor Advertisement (0x%x)\n", nap
);
1032 /* Send NA for specified address if length equal to 0, otherwise for
1033 each prefix with the same length as the address.
1034 Different prefix list is used for HA and MN. */
1035 if (nap
->prefix_len
== 0) {
1036 nd6_na_output(nap
->ifp
, &nap
->dst_addr
, &nap
->target_addr
,
1037 nap
->flags
, nap
->use_link_opt
, NULL
);
1039 mip6_debug("Target Address: %s\n",
1040 ip6_sprintf(&nap
->target_addr
));
1044 if ((MIP6_IS_HA_ACTIVE
) && (nap
->prefix_len
!= 0)) {
1045 for (pq
= mip6_pq
; pq
; pq
= pq
->next
) {
1046 if ((nap
->prefix_len
== pq
->prefix_len
) &&
1047 in6_are_prefix_equal(&pq
->prefix
,
1050 mip6_build_in6addr(&new_addr
,
1054 nd6_na_output(nap
->ifp
, &nap
->dst_addr
,
1055 &new_addr
, nap
->flags
,
1056 nap
->use_link_opt
, NULL
);
1058 mip6_debug("Target Address: %s\n",
1059 ip6_sprintf(&new_addr
));
1064 if (nap
->prefix_len
== 64) {
1065 /* NA for the site-local address is
1066 only sent if length equals to 64. */
1067 bcopy((caddr_t
)&in6addr_sitelocal
,
1068 (caddr_t
)&sl_addr
, 6);
1069 bcopy((caddr_t
)&nap
->target_addr
+ 6,
1070 (caddr_t
)&sl_addr
+ 6, 2);
1071 mip6_build_in6addr(&new_addr
,
1075 nd6_na_output(nap
->ifp
,
1079 nap
->use_link_opt
, NULL
);
1081 mip6_debug("Target Address: %s\n",
1082 ip6_sprintf(&new_addr
));
1085 /* NA for the link-local address is
1086 only sent if length equals to 64. */
1087 mip6_build_in6addr(&new_addr
,
1091 nd6_na_output(nap
->ifp
,
1095 nap
->use_link_opt
, NULL
);
1097 mip6_debug("Target Address: %s\n",
1098 ip6_sprintf(&new_addr
));
1103 for (pr
= nd_prefix
.lh_first
; pr
; pr
= pr
->ndpr_next
) {
1104 if ((nap
->prefix_len
== pr
->ndpr_plen
) &&
1105 in6_are_prefix_equal(&nap
->target_addr
,
1111 &pr
->ndpr_prefix
.sin6_addr
,
1113 nd6_na_output(nap
->ifp
,
1117 nap
->use_link_opt
, NULL
);
1119 mip6_debug("Target Address: %s\n",
1120 ip6_sprintf(&new_addr
));
1125 if (nap
->prefix_len
== 64) {
1126 /* NA for the site-local address is
1127 only sent if length equals to 64. */
1128 bcopy((caddr_t
)&in6addr_sitelocal
,
1129 (caddr_t
)&sl_addr
, 6);
1130 bcopy((caddr_t
)&nap
->target_addr
+ 6,
1131 (caddr_t
)&sl_addr
+ 6, 2);
1132 mip6_build_in6addr(&new_addr
,
1136 nd6_na_output(nap
->ifp
,
1140 nap
->use_link_opt
, NULL
);
1142 mip6_debug("Target Address: %s\n",
1143 ip6_sprintf(&new_addr
));
1146 /* NA for the link-local address is
1147 only sent if length equals to 64. */
1148 mip6_build_in6addr(&new_addr
,
1152 nd6_na_output(nap
->ifp
,
1156 nap
->use_link_opt
, NULL
);
1158 mip6_debug("Target Address: %s\n",
1159 ip6_sprintf(&new_addr
));
1170 ##############################################################################
1173 # Miscellaneous functions needed for the internal processing of incoming and
1174 # outgoing control signals.
1176 ##############################################################################
1180 ******************************************************************************
1181 * Function: mip6_create_ip6hdr
1182 * Description: Create and fill in data for an IPv6 header to be used by
1183 * packets originating from MIPv6.
1184 * Ret value: NULL if a IPv6 header could not be created.
1185 * Otherwise, pointer to a mbuf including the IPv6 header.
1186 ******************************************************************************
1189 mip6_create_ip6hdr(ip6_src
, ip6_dst
, next
)
1190 struct in6_addr
*ip6_src
; /* Source address for packet */
1191 struct in6_addr
*ip6_dst
; /* Destination address for packet */
1192 u_int8_t next
; /* Next header following the IPv6 header */
1194 struct ip6_hdr
*ip6
; /* IPv6 header */
1195 struct mbuf
*m
; /* Ptr to mbuf allocated for output data */
1197 /* Allocate memory for the IPv6 header and fill it with data */
1198 ip6
= (struct ip6_hdr
*)MALLOC ip6_hdr
),
1202 bzero(ip6
, sizeof(struct ip6_hdr
));
1205 ip6
->ip6_vfc
&= ~IPV6_VERSION_MASK
;
1206 ip6
->ip6_vfc
|= IPV6_VERSION
;
1208 ip6
->ip6_nxt
= next
;
1209 ip6
->ip6_hlim
= IPV6_DEFHLIM
;
1211 ip6
->ip6_src
= *ip6_src
;
1212 ip6
->ip6_dst
= *ip6_dst
;
1214 /* Allocate memory for mbuf and copy IPv6 header to mbuf. */
1215 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
1220 m
->m_len
= sizeof(*ip6
);
1221 m
->m_pkthdr
.len
= m
->m_len
;
1222 m
->m_pkthdr
.rcvif
= NULL
;
1223 bcopy((caddr_t
)ip6
, mtod(m
, caddr_t
), sizeof(*ip6
));
1231 ******************************************************************************
1232 * Function: mip6_create_rh
1233 * Description: Create a routing header of type 0 and add the COA for the MN.
1234 * Ret value: A pointer to the ip6_rthdr structure if everything is OK.
1236 ******************************************************************************
1239 mip6_create_rh(coa
, next
)
1240 struct in6_addr
*coa
; /* Care-of address for the MN */
1241 u_int8_t next
; /* Next header following the routing header */
1243 struct ip6_rthdr0
*rthdr0
; /* Routing header type 0 */
1246 len
= sizeof(struct ip6_rthdr0
) + sizeof(struct in6_addr
);
1247 rthdr0
= (struct ip6_rthdr0
*)MALLOC M_TEMP
, M_WAITOK
);
1252 rthdr0
->ip6r0_nxt
= next
;
1253 rthdr0
->ip6r0_len
= 2;
1254 rthdr0
->ip6r0_type
= 0;
1255 rthdr0
->ip6r0_segleft
= 1;
1256 rthdr0
->ip6r0_reserved
= 0;
1257 bcopy((caddr_t
)coa
, (caddr_t
)rthdr0
+ sizeof(struct ip6_rthdr0
),
1258 sizeof(struct in6_addr
));
1259 return (struct ip6_rthdr
*)rthdr0
;
1265 ******************************************************************************
1266 * Function: mip6_create_ba
1267 * Description: Create a Binding Acknowledgement option for transmission.
1268 * Ret value: NULL if a BA option could not be created.
1269 * Otherwise, pointer to the BA option.
1270 ******************************************************************************
1272 struct mip6_opt_ba
*
1273 mip6_create_ba(status
, seqno
, lifetime
)
1274 u_int8_t status
; /* Result of the Binding Update request */
1275 u_int16_t seqno
; /* Sequence number in the BU being acknowledged */
1276 u_int32_t lifetime
; /* Proposed lifetime in the BU */
1278 struct mip6_opt_ba
*ba_opt
; /* BA allocated in this function */
1280 /* Allocate a Binding Aknowledgement option and set values */
1281 ba_opt
= (struct mip6_opt_ba
*)MALLOC mip6_opt_ba
),
1285 bzero(ba_opt
, sizeof(struct mip6_opt_ba
));
1287 ba_opt
->type
= IP6OPT_BINDING_ACK
;
1288 ba_opt
->len
= IP6OPT_BALEN
;
1289 ba_opt
->status
= status
;
1290 ba_opt
->seqno
= seqno
;
1291 ba_opt
->lifetime
= lifetime
;
1293 /* Calculate value for refresh time */
1294 if (MIP6_IS_HA_ACTIVE
)
1295 ba_opt
->refresh
= (ba_opt
->lifetime
* 8) / 10;
1297 ba_opt
->refresh
= ba_opt
->lifetime
;
1305 ******************************************************************************
1306 * Function: mip6_create_dh
1307 * Description: Create a destination header and add either a BA or BU option.
1308 * Ret value: A pointer to the ip6_dest structure if everything is OK.
1310 ******************************************************************************
1313 mip6_create_dh(arg_opt
, arg_sub
, next
)
1314 void *arg_opt
; /* BU or a BA option */
1315 struct mip6_subbuf
*arg_sub
; /* BU or BA sub-option (NULL if not present) */
1316 u_int8_t next
; /* Next header following the dest header */
1318 struct mip6_opt
*opt
; /* Destination option */
1319 struct ip6_dest
*dest
; /* Destination header */
1320 int off
; /* Offset from start of Dest Header (byte) */
1321 int error
; /* Error code from function call */
1323 opt
= (struct mip6_opt
*)arg_opt
;
1325 if (opt
->type
== IP6OPT_BINDING_ACK
) {
1327 error
= mip6_add_ba(&dest
, &off
,
1328 (struct mip6_opt_ba
*)opt
, arg_sub
);
1331 _FREE(dest
, M_TEMP
);
1334 dest
->ip6d_nxt
= next
;
1335 } else if (opt
->type
== IP6OPT_BINDING_UPDATE
) {
1337 error
= mip6_add_bu(&dest
, &off
,
1338 (struct mip6_opt_bu
*)opt
, arg_sub
);
1341 _FREE(dest
, M_TEMP
);
1344 dest
->ip6d_nxt
= next
;
1352 ******************************************************************************
1353 * Function: mip6_opt_offset
1354 * Description: Find offset for BU, BA or BR option in the Destination Header.
1355 * The option type is specified as input parameter and the offset
1356 * to start of the first option of the specified type is returned.
1357 * Ret value: Offset (bytes) to specified option from beginning of m_in.
1358 * If no option is found a length of 0 is returned indicating an
1360 ******************************************************************************
1363 mip6_opt_offset(m_in
, off
, type
)
1364 struct mbuf
*m_in
; /* Mbuf containing the entire IPv6 packet */
1365 int off
; /* Offset from start of mbuf to start of dest option */
1366 int type
; /* Type of option to look for */
1368 int ii
; /* Internal counter */
1369 u_int8_t opttype
; /* Option type found in Destination Header*/
1370 u_int8_t optlen
; /* Option length incl type and length */
1371 u_int32_t len
; /* Length of Destination Header in bytes */
1372 u_int8_t len8
; /* Length of Destination Header in bytes */
1373 u_int32_t offset
; /* Offset to BU option from beginning of m_in */
1375 m_copydata(m_in
, off
+ 1, sizeof(len8
), (caddr_t
)&len8
);
1376 len
= (len8
+ 1) << 3;
1379 for (ii
= 2; ii
< len
;) {
1380 m_copydata(m_in
, off
+ ii
, sizeof(opttype
), (caddr_t
)&opttype
);
1381 if (opttype
== type
) {
1384 } else if (opttype
== IP6OPT_PAD1
) {
1391 m_copydata(m_in
, off
+ ii
, sizeof(optlen
), (caddr_t
)&optlen
);
1400 ******************************************************************************
1401 * Function: mip6_addr_on_link
1402 * Description: Check if an address is an on-link IPv6 address with respect to
1403 * the home agent's current prefix list.
1405 * 133 = Not home subnet
1406 * 136 = Incorrect interface identifier length
1407 ******************************************************************************
1410 mip6_addr_on_link(addr
, prefix_len
)
1411 struct in6_addr
*addr
; /* IPv6 address to check */
1412 int prefix_len
; /* Prefix length for the address */
1414 struct mip6_prefix
*pr
; /* Pointer to entries in the prexix list */
1416 for (pr
= mip6_pq
; pr
; pr
= pr
->next
) {
1417 /* Check if the IPv6 prefixes are equal, i.e. of the same
1418 IPv6 type of address. */
1419 /* If they are, verify that the prefix length is correct. */
1420 if (in6_are_prefix_equal(addr
, &pr
->prefix
, pr
->prefix_len
)) {
1421 if (prefix_len
== 0)
1424 if (pr
->prefix_len
== prefix_len
)
1427 return MIP6_BA_STATUS_IFLEN
;
1430 return MIP6_BA_STATUS_SUBNET
;
1436 ******************************************************************************
1437 * Function: mip6_min_lifetime
1438 * Description: Decide the remaining valid lifetime for a home address. If the
1439 * prefix length is zero the lifetime is the lifetime of the
1440 * prefix list entry for this prefix.
1441 * If the prefix length is non-zero the lifetime is the minimum
1442 * remaining valid lifetime for all subnet prefixes on the mobile
1444 * Note: This function is only used by the Home Agent.
1445 * Ret value: Lifetime
1446 ******************************************************************************
1449 mip6_min_lifetime(addr
, prefix_len
)
1450 struct in6_addr
*addr
; /* IPv6 address to check */
1451 int prefix_len
; /* Prefix length for the address */
1453 struct mip6_prefix
*pr
; /* Ptr to entries in the prexix list */
1454 u_int32_t min_time
; /* Minimum life time */
1456 min_time
= 0xffffffff;
1458 for (pr
= mip6_pq
; pr
; pr
= pr
->next
) {
1459 /* Different handling depending on the prefix length. */
1460 if (prefix_len
== 0) {
1461 if (in6_are_prefix_equal(addr
, &pr
->prefix
,
1463 return pr
->valid_time
;
1466 min_time
= min(min_time
, pr
->valid_time
);
1474 ******************************************************************************
1475 * Function: mip6_build_in6addr
1476 * Description: Build an in6 address from a prefix and the interface id.
1477 * The length of the different parts is decided by prefix_len.
1479 ******************************************************************************
1482 mip6_build_in6addr(new_addr
, id
, prefix
, prefix_len
)
1483 struct in6_addr
*new_addr
; /* New address built in this function */
1484 struct in6_addr
*id
; /* Interface id part of the address */
1485 const struct in6_addr
*prefix
; /* Prefix part of the address */
1486 int prefix_len
; /* Prefix length (bits) */
1488 u_int8_t byte_pr
, byte_id
;
1491 for (ii
= 0; ii
< prefix_len
/ 8; ii
++)
1492 new_addr
->s6_addr8
[ii
] = prefix
->s6_addr8
[ii
];
1494 if (prefix_len
% 8) {
1495 /* Add the last bits of the prefix to the common byte. */
1496 byte_pr
= prefix
->s6_addr8
[ii
];
1497 byte_pr
= byte_pr
>> (8 - (prefix_len
% 8));
1498 byte_pr
= byte_pr
<< (8 - (prefix_len
% 8));
1500 /* Then, add the first bits of the interface id to the
1502 byte_id
= id
->s6_addr8
[ii
];
1503 byte_id
= byte_id
<< (prefix_len
% 8);
1504 byte_id
= byte_id
>> (prefix_len
% 8);
1505 new_addr
->s6_addr8
[ii
] = byte_pr
| byte_id
;
1509 for (jj
= ii
; jj
< 16; jj
++)
1510 new_addr
->s6_addr8
[jj
] = id
->s6_addr8
[jj
];
1516 ******************************************************************************
1517 * Function: mip6_build_ha_anycast
1518 * Description: Build an mobile IPv6 Home-Agents anycast address from a prefix
1519 * and the prefix length. The interface id is according to
1522 ******************************************************************************
1525 mip6_build_ha_anycast(new_addr
, prefix
, prefix_len
)
1526 struct in6_addr
*new_addr
; /* New address built in this function */
1527 const struct in6_addr
*prefix
; /* Prefix part of the address */
1528 int prefix_len
; /* Prefix length (bits) */
1530 struct in6_addr addr
;
1533 if (prefix
->s6_addr8
[0] == 0xff) {
1534 *new_addr
= in6addr_any
;
1538 if (((prefix
->s6_addr8
[0] & 0xe0) != 0) && (prefix_len
!= 64)) {
1539 *new_addr
= in6addr_any
;
1543 if (((prefix
->s6_addr8
[0] & 0xe0) != 0) && (prefix_len
== 64))
1544 addr
= in6addr_aha_64
;
1546 addr
= in6addr_aha_nn
;
1548 mip6_build_in6addr(new_addr
, &addr
, prefix
, prefix_len
);
1554 ******************************************************************************
1555 * Function: mip6_add_ifaddr
1556 * Description: Similar to "ifconfig <ifp> <addr> prefixlen <plen>".
1557 * Ret value: Standard error codes.
1558 ******************************************************************************
1561 mip6_add_ifaddr(struct in6_addr
*addr
,
1564 int flags
) /* Note: IN6_IFF_NODAD available flag */
1566 struct in6_aliasreq
*ifra
, dummy
;
1567 struct sockaddr_in6
*sa6
;
1568 struct sockaddr_in6 oldaddr
;
1569 struct in6_ifaddr
*ia
, *oia
;
1570 struct in6_addrlifetime
*lt
;
1571 int error
= 0, hostIsNew
, prefixIsNew
;
1573 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1576 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
1577 time_t time_second
= (time_t)time
.tv_sec
;
1580 bzero(&dummy
, sizeof(dummy
));
1583 ifra
->ifra_addr
.sin6_len
= sizeof(ifra
->ifra_addr
);
1584 ifra
->ifra_addr
.sin6_family
= AF_INET6
;
1585 ifra
->ifra_addr
.sin6_addr
= *addr
;
1588 ifra
->ifra_prefixmask
.sin6_len
=
1589 sizeof(ifra
->ifra_prefixmask
);
1590 ifra
->ifra_prefixmask
.sin6_family
= AF_INET6
;
1591 in6_prefixlen2mask(&ifra
->ifra_prefixmask
.sin6_addr
, plen
);
1592 /* XXXYYY Should the prefix also change its prefixmask? */
1595 ifra
->ifra_flags
= flags
;
1596 ifra
->ifra_lifetime
.ia6t_vltime
= ND6_INFINITE_LIFETIME
;
1597 ifra
->ifra_lifetime
.ia6t_pltime
= ND6_INFINITE_LIFETIME
;
1599 sa6
= &ifra
->ifra_addr
;
1601 /* "ifconfig ifp inet6 Home_Address prefixlen 64/128 (alias?)" */
1608 * Code recycled from in6_control().
1612 * Find address for this interface, if it exists.
1614 if (IN6_IS_ADDR_LINKLOCAL(&sa6
->sin6_addr
)) {
1615 if (sa6
->sin6_addr
.s6_addr16
[1] == 0) {
1616 /* interface ID is not embedded by the user */
1617 sa6
->sin6_addr
.s6_addr16
[1] =
1618 htons(ifp
->if_index
);
1620 else if (sa6
->sin6_addr
.s6_addr16
[1] !=
1621 htons(ifp
->if_index
)) {
1623 return(EINVAL
); /* ifid is contradict */
1625 if (sa6
->sin6_scope_id
) {
1626 if (sa6
->sin6_scope_id
!=
1627 (u_int32_t
)ifp
->if_index
) {
1631 sa6
->sin6_scope_id
= 0; /* XXX: good way? */
1634 ia
= in6ifa_ifpwithaddr(ifp
, &sa6
->sin6_addr
);
1637 ia
= (struct in6_ifaddr
*)
1638 MALLOC M_IFADDR
, M_WAITOK
);
1643 bzero((caddr_t
)ia
, sizeof(*ia
));
1644 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
1645 ia
->ia_ifa
.ifa_dstaddr
1646 = (struct sockaddr
*)&ia
->ia_dstaddr
;
1647 ia
->ia_ifa
.ifa_netmask
1648 = (struct sockaddr
*)&ia
->ia_prefixmask
;
1651 if ((oia
= in6_ifaddr
) != NULL
) {
1652 for ( ; oia
->ia_next
; oia
= oia
->ia_next
)
1657 ia
->ia_ifa
.ifa_refcnt
++;
1659 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1660 if ((ifa
= ifp
->if_addrlist
) != NULL
) {
1661 for ( ; ifa
->ifa_next
; ifa
= ifa
->ifa_next
)
1663 ifa
->ifa_next
= &ia
->ia_ifa
;
1665 ifp
->if_addrlist
= &ia
->ia_ifa
;
1667 TAILQ_INSERT_TAIL(&ifp
->if_addrlist
, &ia
->ia_ifa
,
1670 ia
->ia_ifa
.ifa_refcnt
++;
1673 /* sanity for overflow - beware unsigned */
1674 lt
= &ifra
->ifra_lifetime
;
1675 if (lt
->ia6t_vltime
!= ND6_INFINITE_LIFETIME
1676 && lt
->ia6t_vltime
+ time_second
< time_second
) {
1680 if (lt
->ia6t_pltime
!= ND6_INFINITE_LIFETIME
1681 && lt
->ia6t_pltime
+ time_second
< time_second
) {
1688 if (ifra
->ifra_addr
.sin6_len
== 0) {
1689 ifra
->ifra_addr
= ia
->ia_addr
;
1691 } else if (IN6_ARE_ADDR_EQUAL(&ifra
->ifra_addr
.sin6_addr
,
1692 &ia
->ia_addr
.sin6_addr
))
1695 if (ifra
->ifra_prefixmask
.sin6_len
) {
1696 in6_ifscrub(ifp
, ia
);
1697 ia
->ia_prefixmask
= ifra
->ifra_prefixmask
;
1700 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
1701 (ifra
->ifra_dstaddr
.sin6_family
== AF_INET6
)) {
1702 in6_ifscrub(ifp
, ia
);
1703 oldaddr
= ia
->ia_dstaddr
;
1704 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
1705 /* link-local index check: should be a separate function? */
1706 if (IN6_IS_ADDR_LINKLOCAL(&ia
->ia_dstaddr
.sin6_addr
)) {
1707 if (ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1] == 0) {
1709 * interface ID is not embedded by
1712 ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1]
1713 = htons(ifp
->if_index
);
1714 } else if (ia
->ia_dstaddr
.sin6_addr
.s6_addr16
[1] !=
1715 htons(ifp
->if_index
)) {
1716 ia
->ia_dstaddr
= oldaddr
;
1718 return(EINVAL
); /* ifid is contradict */
1721 prefixIsNew
= 1; /* We lie; but effect's the same */
1723 if (ifra
->ifra_addr
.sin6_family
== AF_INET6
&&
1724 (hostIsNew
|| prefixIsNew
))
1726 error
= in6_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
1728 if (ifra
->ifra_addr
.sin6_family
== AF_INET6
1729 && hostIsNew
&& (ifp
->if_flags
& IFF_MULTICAST
)) {
1730 int error_local
= 0;
1733 * join solicited multicast addr for new host id
1735 struct in6_addr llsol
;
1736 bzero(&llsol
, sizeof(struct in6_addr
));
1737 llsol
.s6_addr16
[0] = htons(0xff02);
1738 llsol
.s6_addr16
[1] = htons(ifp
->if_index
);
1739 llsol
.s6_addr32
[1] = 0;
1740 llsol
.s6_addr32
[2] = htonl(1);
1741 llsol
.s6_addr32
[3] =
1742 ifra
->ifra_addr
.sin6_addr
.s6_addr32
[3];
1743 llsol
.s6_addr8
[12] = 0xff;
1744 (void)in6_addmulti(&llsol
, ifp
, &error_local
);
1746 error
= error_local
;
1749 ia
->ia6_flags
= ifra
->ifra_flags
;
1750 ia
->ia6_flags
&= ~IN6_IFF_DUPLICATED
; /*safety*/
1751 ia
->ia6_flags
&= ~IN6_IFF_NODAD
; /* Mobile IPv6 */
1753 ia
->ia6_lifetime
= ifra
->ifra_lifetime
;
1755 if (ia
->ia6_lifetime
.ia6t_vltime
!= ND6_INFINITE_LIFETIME
) {
1756 ia
->ia6_lifetime
.ia6t_expire
=
1757 time_second
+ ia
->ia6_lifetime
.ia6t_vltime
;
1759 ia
->ia6_lifetime
.ia6t_expire
= 0;
1760 if (ia
->ia6_lifetime
.ia6t_pltime
!= ND6_INFINITE_LIFETIME
) {
1761 ia
->ia6_lifetime
.ia6t_preferred
=
1762 time_second
+ ia
->ia6_lifetime
.ia6t_pltime
;
1764 ia
->ia6_lifetime
.ia6t_preferred
= 0;
1767 * Perform DAD, if needed.
1768 * XXX It may be of use, if we can administratively
1771 switch (ifp
->if_type
) {
1780 /* Mobile IPv6 modification */
1781 if ((ifra
->ifra_flags
& IN6_IFF_NODAD
) == 0) {
1782 ia
->ia6_flags
|= IN6_IFF_TENTATIVE
;
1783 nd6_dad_start((struct ifaddr
*)ia
, NULL
);
1796 int error_local
= 0;
1798 iilen
= (sizeof(ia
->ia_prefixmask
.sin6_addr
) << 3) -
1799 in6_mask2len(&ia
->ia_prefixmask
.sin6_addr
);
1800 error_local
= in6_prefix_add_ifid(iilen
, ia
);
1802 error
= error_local
;
1814 ******************************************************************************
1815 * Function: mip6_tunnel_output
1816 * Description: Encapsulates packet in an outer header which is determined
1817 * of the Binding Cache entry provided. Note that packet is
1818 * (currently) not sent here, but should be sent by the caller.
1819 * Ret value: != 0 if failure. It's up to the caller to free the mbuf chain.
1820 ******************************************************************************
1823 mip6_tunnel_output(mp
, bc
)
1827 struct sockaddr_in6 dst
;
1828 const struct encaptab
*ep
= bc
->ep
;
1829 struct mbuf
*m
= *mp
;
1830 struct sockaddr_in6
*sin6_src
= (struct sockaddr_in6
*)&ep
->src
;
1831 struct sockaddr_in6
*sin6_dst
= (struct sockaddr_in6
*)&ep
->dst
;
1832 struct ip6_hdr
*ip6
;
1836 bzero(&dst
, sizeof(dst
));
1837 dst
.sin6_len
= sizeof(struct sockaddr_in6
);
1838 dst
.sin6_family
= AF_INET6
;
1839 dst
.sin6_addr
= bc
->coa
;
1841 if (ep
->af
!= AF_INET6
|| ep
->dst
.ss_len
!= dst
.sin6_len
||
1842 bcmp(&ep
->dst
, &dst
, dst
.sin6_len
) != 0 )
1845 /* Recursion problems? */
1847 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_src
->sin6_addr
)) {
1851 len
= m
->m_pkthdr
.len
;
1853 if (m
->m_len
< sizeof(*ip6
)) {
1854 m
= m_pullup(m
, sizeof(*ip6
));
1858 ip6
= mtod(m
, struct ip6_hdr
*);
1859 itos
= (ntohl(ip6
->ip6_flow
) >> 20) & 0xff;
1862 /* prepend new IP header */
1863 M_PREPEND(m
, sizeof(struct ip6_hdr
), M_DONTWAIT
);
1864 if (m
&& m
->m_len
< sizeof(struct ip6_hdr
))
1865 m
= m_pullup(m
, sizeof(struct ip6_hdr
));
1868 printf("ENOBUFS in mip6_tunnel_output %d\n", __LINE__
);
1873 ip6
= mtod(m
, struct ip6_hdr
*);
1875 ip6
->ip6_vfc
&= ~IPV6_VERSION_MASK
;
1876 ip6
->ip6_vfc
|= IPV6_VERSION
;
1877 ip6
->ip6_plen
= htons((u_short
)len
);
1878 ip6
->ip6_nxt
= IPPROTO_IPV6
;
1879 ip6
->ip6_hlim
= ip6_gif_hlim
; /* Same? */
1880 ip6
->ip6_src
= sin6_src
->sin6_addr
;
1882 /* bidirectional configured tunnel mode */
1883 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst
->sin6_addr
))
1884 ip6
->ip6_dst
= sin6_dst
->sin6_addr
;
1895 ******************************************************************************
1896 * Function: mip6_tunnel_input
1897 * Description: similar to gif_input() and in6_gif_input().
1898 * Ret value: standard error codes.
1899 ******************************************************************************
1902 mip6_tunnel_input(mp
, offp
, proto
)
1906 struct mbuf
*m
= *mp
;
1907 struct ip6_hdr
*ip6
;
1911 ip6
= mtod(m
, struct ip6_hdr
*);
1912 otos
= ip6
->ip6_flow
;
1918 struct ip6_hdr
*ip6
;
1920 if (m
->m_len
< sizeof(*ip6
)) {
1921 m
= m_pullup(m
, sizeof(*ip6
));
1923 return IPPROTO_DONE
;
1925 m
->m_flags
|= M_MIP6TUNNEL
; /* Tell MN that this packet
1927 ip6
= mtod(m
, struct ip6_hdr
*);
1930 if (IF_QFULL(&ip6intrq
)) {
1931 IF_DROP(&ip6intrq
); /* update statistics */
1934 return IPPROTO_DONE
;
1936 IF_ENQUEUE(&ip6intrq
, m
);
1938 /* we don't need it as we tunnel IPv6 in IPv6 only. */
1939 schednetisr(NETISR_IPV6
);
1946 mip6_debug("%s: protocol %d not supported.\n", __FUNCTION__
,
1950 return IPPROTO_DONE
;
1953 return IPPROTO_DONE
;
1959 ******************************************************************************
1960 * Function: mip6_tunnel
1961 * Description: Create, move or delete a tunnel from the Home Agent to the MN
1962 * or from the Mobile Node to the Home Agent.
1963 * Ret value: Standard error codes.
1964 ******************************************************************************
1967 mip6_tunnel(ip6_src
, ip6_dst
, action
, start
, entry
)
1968 struct in6_addr
*ip6_src
; /* Tunnel start point */
1969 struct in6_addr
*ip6_dst
; /* Tunnel end point */
1970 int action
; /* Action: MIP6_TUNNEL_{ADD,MOVE,DEL} */
1971 int start
; /* Either the Home Agent or the Mobile Node */
1972 void *entry
; /* BC or ESM depending on start variable */
1974 const struct encaptab
*ep
; /* Encapsulation entry */
1975 const struct encaptab
**ep_store
; /* Where to store encap reference */
1976 struct sockaddr_in6 src
, srcm
;
1977 struct sockaddr_in6 dst
, dstm
;
1978 struct in6_addr mask
;
1982 if ((start
== MIP6_NODE_MN
) && (entry
!= NULL
))
1983 ep_store
= &((struct mip6_esm
*)entry
)->ep
;
1984 else if ((start
== MIP6_NODE_HA
) && (entry
!= NULL
))
1985 ep_store
= &((struct mip6_bc
*)entry
)->ep
;
1988 printf("%s: Tunnel not modified\n", __FUNCTION__
);
1993 if (action
== MIP6_TUNNEL_DEL
) {
1994 /* Moving to Home network. Remove tunnel. */
1995 if (ep_store
&& *ep_store
) {
1996 encap_detach(*ep_store
);
2002 if ((action
== MIP6_TUNNEL_ADD
) || (action
== MIP6_TUNNEL_MOVE
)) {
2003 if (action
== MIP6_TUNNEL_MOVE
&& ep_store
&& *ep_store
) {
2004 /* Remove the old encapsulation entry first. */
2005 encap_detach(*ep_store
);
2009 bzero(&src
, sizeof(src
));
2010 src
.sin6_family
= AF_INET6
;
2011 src
.sin6_len
= sizeof(struct sockaddr_in6
);
2012 src
.sin6_addr
= *ip6_src
;
2014 in6_prefixlen2mask(&mask
, mask_len
);
2015 bzero(&srcm
, sizeof(srcm
));
2016 srcm
.sin6_family
= AF_INET6
;
2017 srcm
.sin6_len
= sizeof(struct sockaddr_in6
);
2018 srcm
.sin6_addr
= mask
;
2020 bzero(&dst
, sizeof(dst
));
2021 dst
.sin6_family
= AF_INET6
;
2022 dst
.sin6_len
= sizeof(struct sockaddr_in6
);
2023 dst
.sin6_addr
= *ip6_dst
;
2025 in6_prefixlen2mask(&mask
, mask_len
);
2026 bzero(&dstm
, sizeof(dstm
));
2027 dstm
.sin6_family
= AF_INET6
;
2028 dstm
.sin6_len
= sizeof(struct sockaddr_in6
);
2029 dstm
.sin6_addr
= mask
;
2031 ep
= encap_attach(AF_INET6
, -1,
2032 (struct sockaddr
*)&src
,
2033 (struct sockaddr
*)&srcm
,
2034 (struct sockaddr
*)&dst
,
2035 (struct sockaddr
*)&dstm
,
2036 (struct protosw
*)&mip6_tunnel_protosw
,
2049 ******************************************************************************
2050 * Function: mip6_proxy
2051 * Description: Set or delete address to act proxy for.
2052 * Ret value: Standard error codes.
2053 ******************************************************************************
2056 mip6_proxy(struct in6_addr
* addr
,
2057 struct in6_addr
* local
,
2060 struct sockaddr_in6 mask
/* = {sizeof(mask), AF_INET6 }*/;
2061 struct sockaddr_in6 sa6
;
2062 struct sockaddr_dl
*sdl
;
2066 struct rtentry
*nrt
;
2068 if (cmd
== RTM_DELETE
) {
2071 bzero(&sa6
, sizeof(sa6
));
2072 sa6
.sin6_family
= AF_INET6
;
2073 sa6
.sin6_len
= sizeof(sa6
);
2074 sa6
.sin6_addr
= *addr
;
2076 #ifdef __FreeBSD__ || defined (__APPLE__)
2077 rt
= rtalloc1((struct sockaddr
*)&sa6
, 1, 0UL);
2079 rt
= rtalloc1((struct sockaddr
*)&sa6
, 1);
2082 return EHOSTUNREACH
;
2084 error
= rtrequest(RTM_DELETE
, rt_key(rt
), (struct sockaddr
*)0,
2085 rt_mask(rt
), 0, (struct rtentry
**)0);
2092 bzero(&sa6
, sizeof(sa6
));
2093 sa6
.sin6_family
= AF_INET6
;
2094 sa6
.sin6_len
= sizeof(sa6
);
2095 sa6
.sin6_addr
= *local
;
2097 ifa
= ifa_ifwithaddr((struct sockaddr
*)&sa6
);
2101 sa6
.sin6_addr
= *addr
;
2106 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2107 for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
2109 for (ifa
= ifp
->if_addrlist
.tqh_first
; ifa
;
2110 ifa
= ifa
->ifa_list
.tqe_next
)
2112 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
2118 MALLOC(sdl
, struct sockaddr_dl
*, ifa
->ifa_addr
->sa_len
, M_IFMADDR
,
2120 bcopy((struct sockaddr_dl
*)ifa
->ifa_addr
, sdl
, ifa
->ifa_addr
->sa_len
);
2123 bzero(&mask
, sizeof(mask
));
2124 mask
.sin6_family
= AF_INET6
;
2125 mask
.sin6_len
= sizeof(mask
);
2127 in6_len2mask(&mask
.sin6_addr
, 128);
2129 flags
= (RTF_STATIC
| RTF_ANNOUNCE
| RTA_NETMASK
);
2131 error
= rtrequest(RTM_ADD
, (struct sockaddr
*)&sa6
,
2132 (struct sockaddr
*)sdl
,
2133 (struct sockaddr
*)&mask
, flags
, &nrt
);
2136 /* avoid expiration */
2138 nrt
->rt_rmx
.rmx_expire
= 0;
2139 nrt
->rt_genmask
= NULL
;
2145 _FREE(sdl
, M_IFMADDR
);
2152 ##############################################################################
2155 # The correspondent node maintains a Binding Cache list for each node from
2156 # which it has received a BU.
2157 # It also maintains a list of Neighbor Advertisements that shall be sent
2158 # either by the home agent when start acting as a proxy for the mobile node
2159 # or by the mobile node when returning to the home network.
2161 ##############################################################################
2165 ******************************************************************************
2166 * Function: mip6_bc_find
2167 * Description: Find an entry in the Binding Cache list.
2168 * Ret value: Pointer to Binding Cache entry or NULL if no entry found.
2169 ******************************************************************************
2172 mip6_bc_find(home_addr
)
2173 struct in6_addr
*home_addr
; /* Home Address of the MN for which the BC
2174 entry is searched */
2176 struct mip6_bc
*bcp
; /* Entry in the Binding Cache list */
2178 for (bcp
= mip6_bcq
; bcp
; bcp
= bcp
->next
) {
2179 if (IN6_ARE_ADDR_EQUAL(home_addr
, &bcp
->home_addr
))
2188 ******************************************************************************
2189 * Function: mip6_bc_create
2190 * Description: Create a new Binding Cache entry, add it first to the Binding
2191 * Cache list and set parameters for the entry.
2192 * Ret value: Pointer to the created BC entry or NULL.
2193 * Note 1: If the BC timeout function has not been started it is started.
2194 * The BC timeout function will be called once every second until
2195 * there are no more entries in the BC list.
2196 * Note 2: The gif i/f is created/updated in function mip6_tunnel and
2197 * should not be taken care of here.
2198 ******************************************************************************
2201 mip6_bc_create(home_addr
, coa
, lifetime
, hr
, rtr
, prefix_len
, seqno
)
2202 struct in6_addr
*home_addr
; /* Home Address for the mobile node */
2203 struct in6_addr
*coa
; /* COA for the mobile node */
2204 u_int32_t lifetime
; /* Remaining lifetime for this BC entry */
2205 u_int8_t hr
; /* Flag for home registration (0/1) */
2206 u_int8_t rtr
; /* MN is router (0/1) */
2207 u_int8_t prefix_len
; /* Prefix length for Home Address */
2208 u_int16_t seqno
; /* Sequence number in the received BU */
2210 struct mip6_bc
*bcp
; /* Created BC list entry*/
2213 bcp
= (struct mip6_bc
*)MALLOC mip6_bc
),
2217 bzero((caddr_t
)bcp
, sizeof(struct mip6_bc
));
2220 bcp
->home_addr
= *home_addr
;
2222 bcp
->lifetime
= lifetime
;
2224 bcp
->prefix_len
= prefix_len
;
2230 bcp
->rtr_flag
= rtr
;
2234 if (mip6_config
.br_update
> 60)
2235 bcp
->info
.br_interval
= 60;
2236 else if (mip6_config
.br_update
< 2)
2237 bcp
->info
.br_interval
= 2;
2239 bcp
->info
.br_interval
= mip6_config
.br_update
;
2242 /* Insert the entry as the first entry in the Binding Cache list. */
2244 if (mip6_bcq
== NULL
) {
2246 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2247 mip6_timer_bc_handle
=
2249 timeout(mip6_timer_bc
, (void *)0, hz
);
2251 bcp
->next
= mip6_bcq
;
2257 mip6_debug("\nBinding Cache Entry created (0x%x)\n", bcp
);
2258 mip6_debug("Home Addr/Prefix len: %s / %u\n",
2259 ip6_sprintf(&bcp
->home_addr
), bcp
->prefix_len
);
2260 mip6_debug("Care-of Address: %s\n", ip6_sprintf(&bcp
->coa
));
2261 mip6_debug("Remaining lifetime: %u\n", bcp
->lifetime
);
2262 mip6_debug("Sequence number: %u\n", bcp
->seqno
);
2263 mip6_debug("Home reg/Router: ");
2265 mip6_debug("TRUE / ");
2267 mip6_debug("FALSE / ");
2270 mip6_debug("TRUE\n");
2272 mip6_debug("FALSE\n");
2280 ******************************************************************************
2281 * Function: mip6_bc_update
2282 * Description: Update an existing Binding Cache entry
2284 * Note: The gif i/f is created/updated in function mip6_tunnel and
2285 * should not be taken care of here.
2286 ******************************************************************************
2289 mip6_bc_update(bcp
, coa
, lifetime
, hr
, rtr
, prefix_len
, seqno
, info
, lasttime
)
2290 struct mip6_bc
*bcp
; /* BC entry being allocated or updated */
2291 struct in6_addr
*coa
; /* COA for the mobile node */
2292 u_int32_t lifetime
; /* Remaining lifetime for this BC entry */
2293 u_int8_t hr
; /* Flag for home registration (0/1) */
2294 u_int8_t rtr
; /* MN is router (0/1) */
2295 u_int8_t prefix_len
; /* Prefix length for Home Address */
2296 u_int16_t seqno
; /* Sequence number in the received BU */
2297 struct bc_info info
; /* Usage info for cache replacement policy */
2298 time_t lasttime
; /* The time at which a BR was last sent */
2301 bcp
->lifetime
= lifetime
;
2303 bcp
->prefix_len
= prefix_len
;
2307 bcp
->rtr_flag
= rtr
;
2308 bzero((caddr_t
)&bcp
->info
, sizeof(struct bc_info
));
2312 if (info
.br_interval
> 60)
2313 bcp
->info
.br_interval
= 60;
2314 else if (info
.br_interval
< 2)
2315 bcp
->info
.br_interval
= 2;
2317 bcp
->info
.br_interval
= info
.br_interval
;
2319 bcp
->lasttime
= lasttime
;
2322 mip6_debug("\nBinding Cache Entry updated (0x%x)\n", bcp
);
2323 mip6_debug("Home Addr/Prefix len: %s / %u\n",
2324 ip6_sprintf(&bcp
->home_addr
), bcp
->prefix_len
);
2325 mip6_debug("Care-of Address: %s\n", ip6_sprintf(&bcp
->coa
));
2326 mip6_debug("Remaining lifetime: %u\n", bcp
->lifetime
);
2327 mip6_debug("Sequence number: %u\n", bcp
->seqno
);
2328 mip6_debug("Home reg/Router: ");
2330 mip6_debug("TRUE / ");
2332 mip6_debug("FALSE / ");
2335 mip6_debug("TRUE\n");
2337 mip6_debug("FALSE\n");
2345 ******************************************************************************
2346 * Function: mip6_bc_delete
2347 * Description: Delete an entry in the Binding Cache list.
2348 * Ret value: Error code
2349 * Pointer to next entry in list or NULL if last entry removed.
2350 ******************************************************************************
2353 mip6_bc_delete(bcp_del
, bcp_nxt
)
2354 struct mip6_bc
*bcp_del
; /* Pointer to BC entry to delete */
2355 struct mip6_bc
**bcp_nxt
; /* Returns next entry in the list */
2357 struct mip6_bc
*bcp
; /* Current entry in the BC list */
2358 struct mip6_bc
*bcp_prev
; /* Previous entry in the BC list */
2359 struct mip6_bc
*bcp_next
; /* Next entry in the BC list */
2365 for (bcp
= mip6_bcq
; bcp
; bcp
= bcp
->next
) {
2366 bcp_next
= bcp
->next
;
2367 if (bcp
!= bcp_del
) {
2372 /* Make sure that the list pointers are correct. */
2373 if (bcp_prev
== NULL
)
2374 mip6_bcq
= bcp
->next
;
2376 bcp_prev
->next
= bcp
->next
;
2379 /* The HA should stop acting as a proxy for the MN. */
2380 error
= mip6_proxy(&bcp
->home_addr
, NULL
, RTM_DELETE
);
2383 mip6_debug("%s: delete proxy error = %d\n",
2384 __FUNCTION__
, error
);
2386 *bcp_nxt
= bcp_next
;
2390 /* Delete the existing tunnel to the MN. */
2391 mip6_tunnel(NULL
, NULL
, MIP6_TUNNEL_DEL
, MIP6_NODE_HA
,
2396 mip6_debug("\nBinding Cache Entry deleted (0x%x)\n", bcp
);
2400 /* Remove the timer if the BC queue is empty */
2401 if (mip6_bcq
== NULL
) {
2402 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2403 untimeout(mip6_timer_bc
, (void *)NULL
,
2404 mip6_timer_bc_handle
);
2405 callout_handle_init(&mip6_timer_bc_handle
);
2407 untimeout(mip6_timer_bc
, (void *)NULL
);
2414 *bcp_nxt
= bcp_next
;
2421 ******************************************************************************
2422 * Function: mip6_na_create
2423 * Description: Create a NA entry and add it to the list of Neighbor Adver-
2424 * tisements. The NA will be repeateadly sent by either the
2425 * Mobile Node when returning to its home link or by the Home
2426 * Agent when acting as a proxy for a Mobile Node while away
2427 * from its home network.
2428 * Note: The first Neighbor Advertisement is sent by this function.
2429 * Ret value: Pointer to the created entry or NULL in case of error.
2430 ******************************************************************************
2433 mip6_na_create(home_addr
, dst_addr
, target_addr
, prefix_len
,
2434 flags
, use_link_opt
)
2435 struct in6_addr
*home_addr
; /* Home address of the mobile node */
2436 struct in6_addr
*dst_addr
; /* Destination address */
2437 struct in6_addr
*target_addr
; /* Target address */
2438 u_int8_t prefix_len
; /* Prefix length of the home address */
2439 u_long flags
; /* Flags for the NA message */
2440 int use_link_opt
; /* Include Target link layer address option or
2441 not (0 = Do not include, 1 = Include) */
2443 struct mip6_na
*nap
; /* Created NA message */
2444 struct mip6_link_list
*llp
; /* Link list entry */
2445 struct mip6_ha_list
*halp
; /* Home agent list entry */
2446 struct mip6_addr_list
*addrp
; /* Address list entry */
2447 struct nd_prefix
*pr
; /* Prefix list entry */
2448 int s
, start_timer
= 0;
2455 if (mip6_naq
== NULL
)
2458 nap
= (struct mip6_na
*)MALLOC mip6_na
),
2462 bzero(nap
, sizeof(struct mip6_na
));
2465 nap
->home_addr
= *home_addr
;
2466 nap
->dst_addr
= *dst_addr
;
2467 nap
->target_addr
= *target_addr
;
2468 nap
->prefix_len
= prefix_len
;
2470 nap
->use_link_opt
= use_link_opt
;
2471 nap
->no
= MIP6_MAX_ADVERT_REXMIT
;
2473 /* The interface that shall be used may not be assumed to be the
2474 interface of the incoming packet, but must be the interface stated
2475 in the prefix that matches the home address. */
2476 if (MIP6_IS_HA_ACTIVE
) {
2477 for (llp
= mip6_llq
; llp
; llp
= llp
->next
) {
2478 for (halp
= llp
->ha_list
; halp
; halp
= halp
->next
) {
2479 for (addrp
= halp
->addr_list
; addrp
;
2480 addrp
= addrp
->next
) {
2481 if (in6_are_prefix_equal(
2493 if (addrp
== NULL
) {
2495 "%s: No interface found for sending Neighbor "
2496 "Advertisements at\n", __FUNCTION__
);
2499 nap
->ifp
= llp
->ifp
;
2502 if (MIP6_IS_MN_ACTIVE
) {
2503 for (pr
= nd_prefix
.lh_first
; pr
; pr
= pr
->ndpr_next
) {
2504 if (!pr
->ndpr_stateflags
.onlink
)
2506 if (in6_are_prefix_equal(home_addr
,
2507 &pr
->ndpr_prefix
.sin6_addr
,
2513 "%s: No interface found for sending Neighbor "
2514 "Advertisements at\n", __FUNCTION__
);
2517 nap
->ifp
= pr
->ndpr_ifp
;
2520 /* Add the new na entry first to the list. */
2522 nap
->next
= mip6_naq
;
2527 mip6_debug("\nCreated Neighbor Advertisement List entry (0x%x)\n",
2529 mip6_debug("Interface being used: %s\n", if_name(nap
->ifp
));
2530 mip6_debug("Home Addr/Prefix len: %s / %d\n",
2531 ip6_sprintf(&nap
->home_addr
), nap
->prefix_len
);
2532 mip6_debug("Destination Address: %s\n", ip6_sprintf(&nap
->dst_addr
));
2533 mip6_debug("Target Address: %s\n",
2534 ip6_sprintf(&nap
->target_addr
));
2535 if (nap
->use_link_opt
)
2536 mip6_debug("Incl Target ll_addr : TRUE\n");
2538 mip6_debug("Incl Target ll_addr : FALSE\n");
2541 /* Send the Neighbor Advertisment entry to speed up cache changes. */
2545 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2546 mip6_timer_na_handle
=
2548 timeout(mip6_timer_na
, (void *)0, hz
);
2556 ******************************************************************************
2557 * Function: mip6_na_delete
2558 * Description: Delete an entry in the NA list.
2559 * Ret value: Pointer to next entry in list or NULL if last entry removed.
2560 ******************************************************************************
2563 mip6_na_delete(nap_del
)
2564 struct mip6_na
*nap_del
; /* Pointer to NA entry to delete */
2566 struct mip6_na
*nap
; /* Current entry in the NA list */
2567 struct mip6_na
*nap_prev
; /* Previous entry in the NA list */
2568 struct mip6_na
*nap_next
; /* Next entry in the NA list */
2574 for (nap
= mip6_naq
; nap
; nap
= nap
->next
) {
2575 nap_next
= nap
->next
;
2576 if (nap
== nap_del
) {
2577 if (nap_prev
== NULL
)
2578 mip6_naq
= nap
->next
;
2580 nap_prev
->next
= nap
->next
;
2583 mip6_debug("\nNeighbor Advertisement Entry "
2584 "deleted (0x%x)\n", nap
);
2588 /* Remove the timer if the NA queue is empty */
2589 if (mip6_naq
== NULL
) {
2590 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2591 untimeout(mip6_timer_na
, (void *)NULL
,
2592 mip6_timer_na_handle
);
2593 callout_handle_init(&mip6_timer_na_handle
);
2595 untimeout(mip6_timer_na
, (void *)NULL
);
2609 ******************************************************************************
2610 * Function: mip6_prefix_find
2611 * Description: Try to find an existing prefix entry in the prefix list.
2612 * Ret value: Pointer to found prefix list entry or NULL.
2613 ******************************************************************************
2615 struct mip6_prefix
*
2616 mip6_prefix_find(prefix
, prefix_len
)
2617 struct in6_addr
*prefix
; /* Prefix to search for */
2618 u_int8_t prefix_len
; /* Prefix length */
2620 struct mip6_prefix
*pq
;
2622 for (pq
= mip6_pq
; pq
; pq
= pq
->next
) {
2623 if (in6_are_prefix_equal(&pq
->prefix
, prefix
, prefix_len
))
2632 ******************************************************************************
2633 * Function: mip6_prefix_create
2634 * Description: Create a prefix and add it as the first entry in the list.
2635 * Start the timer if not started already.
2636 * Ret value: Pointer to created prefix list entry or NULL.
2637 ******************************************************************************
2639 struct mip6_prefix
*
2640 mip6_prefix_create(ifp
, prefix
, prefix_len
, valid_time
)
2641 struct ifnet
*ifp
; /* Outgoing interface */
2642 struct in6_addr
*prefix
; /* Prefix to search for */
2643 u_int8_t prefix_len
; /* Prefix length */
2644 u_int32_t valid_time
; /* Time (s) that the prefix is valid */
2646 struct mip6_prefix
*pq
;
2647 int s
, start_timer
= 0;
2649 if (mip6_pq
== NULL
)
2652 pq
= (struct mip6_prefix
*)MALLOC mip6_prefix
),
2656 bzero(pq
, sizeof(struct mip6_prefix
));
2661 pq
->prefix
= *prefix
;
2662 pq
->prefix_len
= prefix_len
;
2663 pq
->valid_time
= valid_time
;
2668 mip6_debug("\nInternal Prefix list entry created (0x%x)\n", pq
);
2669 mip6_debug("Interface: %s\n", if_name(ifp
));
2670 mip6_debug("Prefix: %s\n", ip6_sprintf(&pq
->prefix
));
2671 mip6_debug("Prefix len: %d\n", pq
->prefix_len
);
2672 mip6_debug("Life time: %d\n", htonl(pq
->valid_time
));
2676 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2677 mip6_timer_prefix_handle
=
2679 timeout(mip6_timer_prefix
, (void *)0, hz
);
2687 ******************************************************************************
2688 * Function: mip6_prefix_delete
2689 * Description: Delete the requested prefix list entry.
2690 * Ret value: Ptr to next entry in list or NULL if last entry removed.
2691 ******************************************************************************
2693 struct mip6_prefix
*
2694 mip6_prefix_delete(pre_del
)
2695 struct mip6_prefix
*pre_del
; /* Prefix list entry to be deleted */
2697 struct mip6_prefix
*pre
; /* Current entry in the list */
2698 struct mip6_prefix
*pre_prev
; /* Previous entry in the list */
2699 struct mip6_prefix
*pre_next
; /* Next entry in the list */
2702 /* Find the requested entry in the link list. */
2706 for (pre
= mip6_pq
; pre
; pre
= pre
->next
) {
2707 pre_next
= pre
->next
;
2708 if (pre
== pre_del
) {
2709 if (pre_prev
== NULL
)
2710 mip6_pq
= pre
->next
;
2712 pre_prev
->next
= pre
->next
;
2715 mip6_debug("\nMIPv6 prefix entry deleted (0x%x)\n", pre
);
2719 /* Remove the timer if the prefix queue is empty */
2720 if (mip6_pq
== NULL
) {
2721 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2722 untimeout(mip6_timer_prefix
, (void *)NULL
,
2723 mip6_timer_prefix_handle
);
2724 callout_handle_init(&mip6_timer_prefix_handle
);
2726 untimeout(mip6_timer_prefix
, (void *)NULL
);
2740 ##############################################################################
2743 # These functions are called at regular basis. They operate on the lists, e.g.
2744 # reducing timer counters and removing entries from the list if needed.
2746 ##############################################################################
2750 ******************************************************************************
2751 * Function: mip6_timer_na
2752 * Description: Called once every second. For each entry in the list a Neighbor
2753 * Advertisement is sent until the counter value reaches 0. Then
2754 * the entry is removed.
2756 ******************************************************************************
2760 void *arg
; /* Not used */
2762 struct mip6_na
*nap
; /* Neighbor Advertisement entry */
2765 boolean_t funnel_state
;
2766 funnel_state
= thread_set_funneled(TRUE
);
2769 /* Go through the entire list of Neighbor Advertisement entries. */
2771 for (nap
= mip6_naq
; nap
;) {
2774 nap
= mip6_na_delete(nap
);
2780 if (mip6_naq
!= NULL
) {
2781 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2782 mip6_timer_na_handle
=
2784 timeout(mip6_timer_na
, (void *)0, hz
);
2787 (void) thread_set_funneled(funnel_state
);
2794 ******************************************************************************
2795 * Function: mip6_timer_bc
2796 * Description: Called once every second. For each entry in the BC list, a
2797 * counter is reduced by 1 until it reaches the value of zero,
2798 * then the entry is removed.
2800 ******************************************************************************
2804 void *arg
; /* Not used */
2806 struct mip6_bc
*bcp
; /* Current entry in the BC list */
2807 struct mip6_bc
*bcp_nxt
; /* Next BC list entry */
2810 boolean_t funnel_state
;
2811 funnel_state
= thread_set_funneled(TRUE
);
2814 /* Go through the entire list of Binding Cache entries. */
2816 for (bcp
= mip6_bcq
; bcp
;) {
2818 if (bcp
->lifetime
== 0) {
2819 mip6_bc_delete(bcp
, &bcp_nxt
);
2827 /* Code have to be added to take care of bc_info.br_interval
2829 /* We have to send a BR when the mip6_bc.lifetime ==
2830 mip6_bc.bc_info.br_interval. */
2831 if (mip6_bcq
!= NULL
) {
2832 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2833 mip6_timer_bc_handle
=
2835 timeout(mip6_timer_bc
, (void *)0, hz
);
2838 (void) thread_set_funneled(funnel_state
);
2846 ******************************************************************************
2847 * Function: mip6_timer_prefix
2848 * Description: Called once every second. Search the list of prefixes and if
2849 * a prefix has timed out it is removed from the list.
2851 ******************************************************************************
2854 mip6_timer_prefix(arg
)
2855 void *arg
; /* Not used */
2857 struct mip6_prefix
*pq_entry
; /* Current entry in the prefix list */
2860 boolean_t funnel_state
;
2861 funnel_state
= thread_set_funneled(TRUE
);
2864 /* Go through the entire list of prefix entries. */
2866 for (pq_entry
= mip6_pq
; pq_entry
;) {
2867 pq_entry
->valid_time
-= 1;
2868 if (pq_entry
->valid_time
== 0)
2869 pq_entry
= mip6_prefix_delete(pq_entry
);
2871 pq_entry
= pq_entry
->next
;
2875 if (mip6_pq
!= NULL
) {
2876 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2877 mip6_timer_prefix_handle
=
2879 timeout(mip6_timer_prefix
, (void *)0, hz
);
2882 (void) thread_set_funneled(funnel_state
);
2890 ##############################################################################
2892 # IOCTL AND DEBUG FUNCTIONS
2894 ##############################################################################
2898 ******************************************************************************
2899 * Function: mip6_ioctl
2900 * Description: The ioctl handler for MIPv6. These are used by the
2901 * configuration program to set and get various parameters.
2902 * Ret value: 0 or error code
2903 ******************************************************************************
2906 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
2907 mip6_ioctl(so
, cmd
, data
, ifp
, p
)
2914 mip6_ioctl(so
, cmd
, data
, ifp
)
2923 /* Note: privileges already checked in in6_control(). */
2927 case SIOCSBCFLUSH_MIP6
:
2928 case SIOCSDEFCONFIG_MIP6
:
2929 res
= mip6_clear_config_data(cmd
, data
);
2932 case SIOCSBRUPDATE_MIP6
:
2933 res
= mip6_write_config_data(cmd
, data
);
2936 case SIOCSHAPREF_MIP6
:
2937 /* Note: this one can be run before attach. */
2938 if (mip6_write_config_data_ha_hook
)
2939 res
= (*mip6_write_config_data_ha_hook
)
2943 case SIOCACOADDR_MIP6
:
2944 case SIOCAHOMEADDR_MIP6
:
2945 case SIOCSBULIFETIME_MIP6
:
2946 case SIOCSHRLIFETIME_MIP6
:
2947 case SIOCDCOADDR_MIP6
:
2948 /* Note: these can be run before attach. */
2949 if (mip6_write_config_data_mn_hook
)
2950 res
= (*mip6_write_config_data_mn_hook
)
2954 case SIOCSDEBUG_MIP6
:
2955 case SIOCSENABLEBR_MIP6
:
2956 case SIOCSATTACH_MIP6
:
2957 res
= mip6_enable_func(cmd
, data
);
2960 case SIOCSFWDSLUNICAST_MIP6
:
2961 case SIOCSFWDSLMULTICAST_MIP6
:
2962 /* Note: these can be run before attach. */
2963 if (mip6_enable_func_ha_hook
)
2964 res
= (*mip6_enable_func_ha_hook
)(cmd
, data
);
2967 case SIOCSPROMMODE_MIP6
:
2968 case SIOCSBU2CN_MIP6
:
2969 case SIOCSREVTUNNEL_MIP6
:
2970 case SIOCSAUTOCONFIG_MIP6
:
2971 case SIOCSEAGERMD_MIP6
:
2972 /* Note: these can be run before attach. */
2973 if (mip6_enable_func_mn_hook
)
2974 res
= (*mip6_enable_func_mn_hook
)(cmd
, data
);
2977 case SIOCSRELEASE_MIP6
:
2986 if (MIP6_IS_HA_ACTIVE
) {
2989 case SIOCSHALISTFLUSH_MIP6
:
2990 if (mip6_clear_config_data_ha_hook
)
2991 res
= (*mip6_clear_config_data_ha_hook
)
3001 if (MIP6_IS_MN_ACTIVE
) {
3004 case SIOCSFORADDRFLUSH_MIP6
:
3005 case SIOCSHADDRFLUSH_MIP6
:
3006 case SIOCSBULISTFLUSH_MIP6
:
3007 if (mip6_clear_config_data_mn_hook
)
3008 res
= (*mip6_clear_config_data_mn_hook
)
3019 printf("%s: unknown command: %lu\n", __FUNCTION__
, (u_long
)cmd
);
3028 ******************************************************************************
3029 * Function: mip6_debug
3030 * Description: This function displays MIPv6 debug messages to the console
3031 * if activated with the configuration program. Note that this
3032 * is included only when "options MIP6_DEBUG" is defined.
3034 ******************************************************************************
3037 void mip6_debug(char *fmt
, ...)
3042 if (!mip6_debug_is_enabled
)
3054 mip6_enable_debug(int status
)
3056 mip6_debug_is_enabled
= status
;
3058 #endif /* MIP6_DEBUG */
3063 ******************************************************************************
3064 * Function: mip6_write_config_data
3065 * Description: This function is called to write certain config values for
3066 * MIPv6. The data is written into the global config structure.
3068 ******************************************************************************
3070 int mip6_write_config_data(u_long cmd
, caddr_t data
)
3075 case SIOCSBRUPDATE_MIP6
:
3076 mip6_config
.br_update
= *(u_int8_t
*)data
;
3085 ******************************************************************************
3086 * Function: mip6_clear_config_data
3087 * Description: This function is called to clear internal lists handled by
3090 ******************************************************************************
3092 int mip6_clear_config_data(u_long cmd
, caddr_t data
)
3095 struct mip6_bc
*bcp
, *bcp_nxt
;
3099 case SIOCSBCFLUSH_MIP6
:
3100 for (bcp
= mip6_bcq
; bcp
;) {
3102 mip6_bc_delete(bcp
, &bcp_nxt
);
3109 case SIOCSDEFCONFIG_MIP6
:
3110 mip6_config
.bu_lifetime
= 600;
3111 mip6_config
.br_update
= 60;
3112 mip6_config
.hr_lifetime
= 3600;
3113 mip6_config
.enable_outq
= 1;
3123 ******************************************************************************
3124 * Function: mip6_enable_func
3125 * Description: This function is called to enable or disable certain functions
3126 * in mip6. The data is written into the global config struct.
3128 ******************************************************************************
3130 int mip6_enable_func(u_long cmd
, caddr_t data
)
3135 enable
= ((struct mip6_input_data
*)data
)->value
;
3138 case SIOCSDEBUG_MIP6
:
3140 mip6_enable_debug(enable
);
3142 printf("No Mobile IPv6 debug information available!\n");
3146 case SIOCSENABLEBR_MIP6
:
3147 mip6_config
.enable_br
= enable
;
3150 case SIOCSATTACH_MIP6
:
3151 printf("%s: attach %d\n", __FUNCTION__
, enable
); /* RM */
3152 retval
= mip6_attach(enable
);