1 /* $KAME: mip6_hooks.c,v 1.8 2000/03/25 07:23:51 sumikawa 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: Mattias Pettersson <mattias.pettersson@era.ericsson.se>
37 * Hesham Soliman <hesham.soliman@ericsson.com.au>
38 * Martti Kuparinen <martti.kuparinen@ericsson.com>
41 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/malloc.h>
50 #include <sys/types.h>
51 #include <sys/socket.h>
52 #include <sys/kernel.h>
54 #include <net/if_types.h>
55 #include <netinet/in.h>
56 #include <netinet/in_var.h>
57 #include <netinet/ip6.h>
58 #include <netinet6/ip6_var.h>
59 #include <netinet6/nd6.h>
60 #include <netinet6/mip6.h>
61 #include <netinet6/mip6_common.h>
64 * These are defined in sys/netinet6/
66 extern int (*mip6_store_dstopt_pre_hook
)(struct mbuf
*, u_int8_t
*,
68 extern int (*mip6_rec_ctrl_sig_hook
)(struct mbuf
*, int);
69 extern int (*mip6_new_packet_hook
)(struct mbuf
*);
70 extern int (*mip6_icmp6_input_hook
)(struct mbuf
*, int);
71 extern int (*mip6_output_hook
)(struct mbuf
*, struct ip6_pktopts
**);
72 extern int (*mip6_rec_ra_hook
)(struct mbuf
*, int);
74 /* Home Agent-specific hooks */
75 extern struct in6_addr
* (*mip6_global_addr_hook
)(struct in6_addr
*);
76 extern struct mip6_subopt_hal
* (*mip6_hal_dynamic_hook
)(struct in6_addr
*);
77 extern int (*mip6_write_config_data_ha_hook
)(u_long
, void *);
78 extern int (*mip6_clear_config_data_ha_hook
)(u_long
, void *);
79 extern int (*mip6_enable_func_ha_hook
)(u_long
, caddr_t
);
80 extern void (*mip6_icmp6_output_hook
)(struct mbuf
*);
82 /* Mobile Node-specific hooks */
83 extern int (*mip6_route_optimize_hook
)(struct mbuf
*);
84 extern void (*mip6_select_defrtr_hook
)(void);
85 extern struct nd_prefix
* (*mip6_get_home_prefix_hook
)(void);
86 extern void (*mip6_prelist_update_hook
)(struct nd_prefix
*,
87 struct nd_defrouter
*);
88 extern void (*mip6_expired_defrouter_hook
)(struct nd_defrouter
*);
89 extern void (*mip6_probe_pfxrtrs_hook
)(void);
90 extern void (*mip6_store_advint_hook
)(struct nd_opt_advint
*,
91 struct nd_defrouter
*);
92 extern int (*mip6_get_md_state_hook
)(void);
93 extern int (*mip6_rec_ba_hook
)(struct mbuf
*, int);
94 extern int (*mip6_rec_br_hook
)(struct mbuf
*, int);
95 extern void (*mip6_stop_bu_hook
)(struct in6_addr
*);
96 extern int (*mip6_write_config_data_mn_hook
)(u_long
, void *);
97 extern int (*mip6_clear_config_data_mn_hook
)(u_long
, caddr_t
);
98 extern int (*mip6_enable_func_mn_hook
)(u_long
, caddr_t
);
99 extern void (*mip6_minus_a_case_hook
)(struct nd_prefix
*);
100 extern struct mip6_esm
* (*mip6_esm_find_hook
)(struct in6_addr
*);
104 mip6_minus_a_case(struct nd_prefix
*pr
)
106 struct in6_addr addr
;
108 if (IN6_IS_ADDR_UNSPECIFIED(&pr
->ndpr_addr
) ||
109 IN6_IS_ADDR_MULTICAST(&pr
->ndpr_addr
) ||
110 IN6_IS_ADDR_LINKLOCAL(&pr
->ndpr_addr
)) {
115 mip6_esm_create(pr
->ndpr_ifp
, NULL
, &addr
, &pr
->ndpr_addr
,
116 pr
->ndpr_plen
, MIP6_STATE_UNDEF
, PERMANENT
, 0xFFFF);
118 mip6_debug("Late Home Address %s found for autoconfig'd case. Starting"
119 " Mobile IPv6.\n", ip6_sprintf(&pr
->ndpr_addr
));
121 mip6_minus_a_case_hook
= 0;
122 mip6_enable_hooks(MIP6_SPECIFIC_HOOKS
);
127 mip6_find_auto_home_addr(void)
129 struct nd_prefix
*pr
;
131 struct in6_ifaddr
*ia6
;
134 for (pr
= nd_prefix
.lh_first
; pr
; pr
= pr
->ndpr_next
) {
136 mip6_debug("%s: scanning prefix %s (pr = %p)\n", __FUNCTION__
,
137 ip6_sprintf(&pr
->ndpr_prefix
.sin6_addr
), pr
);
139 if (IN6_IS_ADDR_UNSPECIFIED(&pr
->ndpr_addr
) ||
140 IN6_IS_ADDR_MULTICAST(&pr
->ndpr_addr
) ||
141 IN6_IS_ADDR_LINKLOCAL(&pr
->ndpr_addr
)) {
145 ia6
= in6ifa_ifpwithaddr(pr
->ndpr_ifp
, &pr
->ndpr_addr
);
146 if (ia6
&& (ia6
->ia6_flags
| IN6_IFF_DETACHED
))
149 break; /* XXXYYY Remove in v2.0. */
152 mip6_debug("%s: skipping detached test on prefix %s "
153 "(pr = %p)\n", __FUNCTION__
,
154 ip6_sprintf(&pr
->ndpr_prefix
.sin6_addr
), pr
);
158 #if 0 /* XXXYYY Add in v2.0 */
159 for (pfxrtr
= pr
->ndpr_advrtrs
.lh_first
; pfxrtr
;
160 pfxrtr
= pfxrtr
->pfr_next
) {
161 if ((pfxrtr
->router
->flags
& ND_RA_FLAG_HA
)
169 mip6_debug("Found an autoconfigured home address "
170 "immediately: %s\n", ip6_sprintf(&pr
->ndpr_addr
));
175 mip6_debug("Couldn't find an autoconfigured home address "
184 mip6_enable_hooks(int scope
)
189 * Activate the hook functions. After this some packets might come
191 * Note: mip6_minus_a_case_hook() is an exception and is not handled
195 if (scope
== MIP6_GENERIC_HOOKS
) {
196 mip6_store_dstopt_pre_hook
= mip6_store_dstopt_pre
;
197 mip6_rec_ctrl_sig_hook
= mip6_rec_ctrl_sig
;
198 mip6_new_packet_hook
= mip6_new_packet
;
199 mip6_icmp6_input_hook
= mip6_icmp6_input
;
200 mip6_output_hook
= mip6_output
;
203 if (scope
== MIP6_CONFIG_HOOKS
) {
204 /* Activate Home Agent-specific hooks */
205 mip6_write_config_data_ha_hook
= mip6_write_config_data_ha
;
206 mip6_clear_config_data_ha_hook
= mip6_clear_config_data_ha
;
207 mip6_enable_func_ha_hook
= mip6_enable_func_ha
;
209 /* Activate Mobile Node-specific hooks */
210 mip6_write_config_data_mn_hook
= mip6_write_config_data_mn
;
211 mip6_clear_config_data_mn_hook
= mip6_clear_config_data_mn
;
212 mip6_enable_func_mn_hook
= mip6_enable_func_mn
;
215 if (scope
== MIP6_SPECIFIC_HOOKS
) {
216 /* Activate Home Agent-specific hooks */
217 if (MIP6_IS_HA_ACTIVE
) {
218 mip6_rec_ra_hook
= mip6_rec_raha
;
219 mip6_global_addr_hook
= mip6_global_addr
;
220 mip6_hal_dynamic_hook
= mip6_hal_dynamic
;
221 mip6_icmp6_output_hook
= mip6_icmp6_output
;
224 /* Activate Mobile Node-specific hooks */
225 if (MIP6_IS_MN_ACTIVE
) {
226 mip6_route_optimize_hook
= mip6_route_optimize
;
227 mip6_rec_ra_hook
= mip6_rec_ramn
;
228 mip6_select_defrtr_hook
= mip6_select_defrtr
;
229 mip6_get_home_prefix_hook
= mip6_get_home_prefix
;
230 mip6_prelist_update_hook
= mip6_prelist_update
;
231 mip6_expired_defrouter_hook
= mip6_expired_defrouter
;
232 mip6_probe_pfxrtrs_hook
= mip6_probe_pfxrtrs
;
233 mip6_store_advint_hook
= mip6_store_advint
;
234 mip6_get_md_state_hook
= mip6_get_md_state
;
235 mip6_rec_ba_hook
= mip6_rec_ba
;
236 mip6_rec_br_hook
= mip6_rec_bu
;
237 mip6_stop_bu_hook
= mip6_stop_bu
;
238 mip6_esm_find_hook
= mip6_esm_find
;
247 mip6_disable_hooks(int scope
)
252 * Deactivate the hook functions. After this some packets might not
253 * come to the module...
257 if (scope
== MIP6_GENERIC_HOOKS
) {
258 mip6_store_dstopt_pre_hook
= 0;
259 mip6_rec_ctrl_sig_hook
= 0;
260 mip6_new_packet_hook
= 0;
261 mip6_icmp6_input_hook
= 0;
262 mip6_output_hook
= 0;
265 if (scope
== MIP6_SPECIFIC_HOOKS
) {
267 /* De-activate Home Agent-specific hooks */
268 if (MIP6_IS_HA_ACTIVE
) {
269 mip6_rec_ra_hook
= 0;
270 mip6_global_addr_hook
= 0;
271 mip6_hal_dynamic_hook
= 0;
272 mip6_write_config_data_ha_hook
= 0;
273 mip6_clear_config_data_ha_hook
= 0;
274 mip6_enable_func_ha_hook
= 0;
277 /* De-activate Mobile Node-specific hooks */
278 if (MIP6_IS_MN_ACTIVE
) {
279 mip6_route_optimize_hook
= 0;
280 mip6_rec_ra_hook
= 0;
281 mip6_select_defrtr_hook
= 0;
282 mip6_get_home_prefix_hook
= 0;
283 mip6_prelist_update_hook
= 0;
284 mip6_expired_defrouter_hook
= 0;
285 mip6_probe_pfxrtrs_hook
= 0;
286 mip6_store_advint_hook
= 0;
287 mip6_get_md_state_hook
= 0;
288 mip6_rec_ba_hook
= 0;
289 mip6_rec_br_hook
= 0;
290 mip6_stop_bu_hook
= 0;
291 mip6_write_config_data_mn_hook
= 0;
292 mip6_clear_config_data_mn_hook
= 0;
293 mip6_enable_func_mn_hook
= 0;
294 mip6_esm_find_hook
= 0;
295 mip6_minus_a_case_hook
= 0;
304 mip6_attach(int module)
307 * Important that necessary settings have been done _before_ calling
308 * mip6_attach(), e.g. home address specified or autoconfig set.
309 * mip6config program sees to that.
313 No support for modules here yet. XXXYYY
315 Old check (not valid any longer):
316 #if (defined(MIP6_MN) || defined (MIP6_HA) || defined(MIP6_MODULES))
320 char *old
= "?", *new = "?";
321 if (mip6_module
== MIP6_HA_MODULE
)
322 strcpy(old
, "Home Agent");
323 if (mip6_module
== MIP6_MN_MODULE
)
324 strcpy(old
, "Mobile Node");
325 if (module == MIP6_HA_MODULE
)
326 strcpy(new, "Home Agent");
327 if (module == MIP6_MN_MODULE
)
328 strcpy(new, "Mobile Node");
330 mip6_debug("Can't switch operation mode from %s to %s \n"
331 "- please deactivate first (\"mip6config -x\")\n",
339 printf("%s: attach ha\n", __FUNCTION__
); /* RM */
340 mip6_module
= module;
345 printf("%s: attach mn\n", __FUNCTION__
); /* RM */
346 mip6_module
= module;
352 mip6_debug("%s: illegal attach (module = %d)\n", __FUNCTION__
,
358 if (MIP6_IS_MN_ACTIVE
) {
359 if(mip6_get_home_prefix_hook
) /* Test arbitrary hook */
363 * If autoconfig state: find a global address to use as Home
365 * - Take first available on any interface, else if no found:
366 * - Enable hook to wait for a Router Advertisement to give
369 if (mip6_config
.autoconfig
) {
370 struct nd_prefix
*pr
;
371 struct in6_addr addr
;
374 if ((pr
= mip6_find_auto_home_addr()) != NULL
) {
375 mip6_esm_create(pr
->ndpr_ifp
, &addr
, &addr
,
376 &pr
->ndpr_addr
,pr
->ndpr_plen
,
377 MIP6_STATE_UNDEF
, PERMANENT
,
379 mip6_enable_hooks(MIP6_SPECIFIC_HOOKS
);
384 mip6_debug("Waiting for Router Advertisement "
385 "to give me an address.\n");
387 mip6_minus_a_case_hook
= mip6_minus_a_case
;
392 mip6_enable_hooks(MIP6_SPECIFIC_HOOKS
);
397 if (MIP6_IS_HA_ACTIVE
) {
398 /* XXXYYY Build anycast or is it done? */
399 mip6_enable_hooks(MIP6_SPECIFIC_HOOKS
);
408 /* Disable the hooks */
409 mip6_disable_hooks(MIP6_SPECIFIC_HOOKS
);
411 if (MIP6_IS_MN_ACTIVE
) {
416 if (MIP6_IS_HA_ACTIVE
)
420 Correspondent Node functionality is never terminated.
421 mip6_disable_hooks(MIP6_GENERIC_HOOKS);
425 mip6_module
= 0; /* Make HA or MN inactive */