]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/mip6.c
xnu-201.42.3.tar.gz
[apple/xnu.git] / bsd / netinet6 / mip6.c
1 /* $KAME: mip6.c,v 1.20 2000/03/18 03:05:38 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 * Mattias Pettersson <mattias.pettersson@era.ericsson.se>
38 *
39 */
40
41 /*
42 * TODO: nuke calls to in6_control, it is not supposed to be called from
43 * softintr
44 */
45
46 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
47 #include "opt_inet.h"
48 #endif
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/malloc.h>
53 #include <sys/mbuf.h>
54 #include <sys/domain.h>
55 #include <sys/protosw.h>
56 #include <sys/socket.h>
57 #include <sys/errno.h>
58 #include <sys/time.h>
59 #include <sys/kernel.h>
60 #include <sys/syslog.h>
61 #include <sys/ioccom.h>
62
63 #include <net/if.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>
69
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>
78
79 #include <netinet6/mip6.h>
80 #include <netinet6/mip6_common.h>
81
82 #if MIP6_DEBUG
83 #include <sys/param.h>
84 #include <sys/proc.h>
85 #include <sys/systm.h>
86 #include <machine/stdarg.h>
87 #include <sys/syslog.h>
88 #endif
89
90 #include <net/net_osdep.h>
91
92 int (*mip6_rec_ra_hook)(struct mbuf *, int) = 0;
93
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;
99
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;
106
107
108 #if MIP6_DEBUG
109 int mip6_debug_is_enabled = 0;
110 #endif
111
112
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 */
119
120
121 #if 0 /* Phasing out MIP6_HA and MIP6_MN */
122 #if MIP6_HA
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) */
126 #else
127 u_int8_t mip6_module = 0; /* Info about loaded modules (CN) */
128 #endif
129 #else /* 0 */
130 u_int8_t mip6_module = 0; /* Info about loaded modules (CN) */
131 #endif /* 0 */
132
133 extern struct ip6protosw mip6_tunnel_protosw;
134
135
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;
140 #endif
141
142
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;
148
149
150 /*
151 ##############################################################################
152 #
153 # INITIALIZATION AND EXIT FUNCTIONS
154 # These functions are executed when the MIPv6 code is activated and de-
155 # activated respectively.
156 #
157 ##############################################################################
158 */
159
160 /*
161 ******************************************************************************
162 * Function: mip6_init
163 * Description: Initialization of MIPv6 variables that must be initialized
164 * before the code is executed.
165 ******************************************************************************
166 */
167 void
168 mip6_init(void)
169 {
170 static int mip6_init_done = 0;
171
172 if (mip6_init_done)
173 return;
174
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;
180
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;
185
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;
190
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;
195
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);
201 #endif
202
203 /* Initialize global variable */
204 bzero(&mip6_config, sizeof(struct mip6_config));
205
206 /* Set default values for MIP6 configuration parameters. */
207 LIST_INIT(&mip6_config.fna_list);
208
209 mip6_config.bu_lifetime = 600;
210 mip6_config.br_update = 60;
211 mip6_config.hr_lifetime = 3600;
212 mip6_config.enable_outq = 1;
213
214 mip6_enable_hooks(MIP6_GENERIC_HOOKS);
215 mip6_enable_hooks(MIP6_CONFIG_HOOKS);
216
217 mip6_init_done = 1;
218 printf("%s: MIP6 initialized\n", __FUNCTION__);
219 }
220
221
222
223 /*
224 ******************************************************************************
225 * Function: mip6_exit
226 * Description: This function is called when the module is unloaded (relesed)
227 * from the kernel.
228 ******************************************************************************
229 */
230 void
231 mip6_exit()
232 {
233 struct mip6_na *nap, *nap_tmp;
234 struct mip6_bc *bcp, *bcp_nxt;
235 struct mip6_prefix *prefix;
236 int s;
237
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);
243 #else
244 untimeout(mip6_timer_na, (void *)NULL);
245 untimeout(mip6_timer_bc, (void *)NULL);
246 untimeout(mip6_timer_prefix, (void *)NULL);
247 #endif
248
249 /* Remove each entry in every queue. */
250 s = splnet();
251 for (nap = mip6_naq; nap;) {
252 nap_tmp = nap;
253 nap = nap->next;
254 _FREE(nap_tmp, M_TEMP);
255 }
256 mip6_naq = NULL;
257
258 for (bcp = mip6_bcq; bcp;) {
259 mip6_bc_delete(bcp, &bcp_nxt);
260 bcp = bcp_nxt;
261 }
262 mip6_bcq = NULL;
263
264 for (prefix = mip6_pq; prefix;)
265 prefix = mip6_prefix_delete(prefix);
266 mip6_pq = NULL;
267 splx(s);
268 }
269
270
271
272 /*
273 ##############################################################################
274 #
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.
278 #
279 ##############################################################################
280 */
281
282 /*
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
287 * option.
288 * Ret value: 0 Everything is OK.
289 * IPPROTO_DONE Error code used when something went wrong.
290 ******************************************************************************
291 */
292 int
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 */
297 {
298 register struct ip6_hdr *ip6; /* IPv6 header */
299 int res; /* Result of function call */
300
301 #if MIP6_DEBUG
302 static int count = 0;
303
304 count += 1;
305 mip6_debug("\nMIPv6 Start processing a control signal (%d)\n", count);
306 #endif
307
308 res = 0;
309 if (mip6_inp == NULL) {
310 log(LOG_ERR, "%s: Variabel mip6_inp is NULL\n",
311 __FUNCTION__);
312 return IPPROTO_DONE;
313 }
314 ip6 = mtod(m_in, struct ip6_hdr *);
315
316 /* Store necessary data from IPv6 header */
317 mip6_inp->ip6_src = ip6->ip6_src;
318 mip6_inp->ip6_dst = ip6->ip6_dst;
319
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);
323 if (res != 0) {
324 #if MIP6_DEBUG
325 mip6_debug("\nMIPv6 Error processing control "
326 "signal BU (%d)\n", count);
327 #endif
328 return res;
329 }
330 }
331
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);
336 if (res != 0) {
337 #if MIP6_DEBUG
338 mip6_debug("\nMIPv6 Error processing control "
339 "signal BA (%d)\n", count);
340 #endif
341 return res;
342 }
343 }
344 }
345
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);
350 if (res != 0) {
351 #if MIP6_DEBUG
352 mip6_debug("\nMIPv6 Error processing control "
353 "signal BR (%d)\n", count);
354 #endif
355 return res;
356 }
357 }
358 }
359
360 if (mip6_inp->optflag & MIP6_DSTOPT_HA)
361 mip6_ha2srcaddr(m_in);
362
363 #if MIP6_DEBUG
364 mip6_debug("\nMIPv6 Finished processing a control signal (%d)\n",
365 count);
366 #endif
367 return 0;
368 }
369
370
371
372 /*
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-
377 * dated.
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 ******************************************************************************
384 */
385 int
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 */
389 {
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;
398
399 ip6 = mtod(m, struct ip6_hdr *);
400 icmp6len = m->m_pkthdr.len - off;
401 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
402
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)
410 return 0;
411
412 ip6_icmp = (struct ip6_hdr *) ((caddr_t)icmp6 +
413 sizeof(struct icmp6_hdr));
414
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);
419 break;
420
421 case ICMP6_PARAM_PROB:
422 if (icmp6->icmp6_code != ICMP6_PARAMPROB_OPTION)
423 break;
424
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) >=
430 m->m_pkthdr.len)
431 return 0;
432
433 ip6_icmp = (struct ip6_hdr *)((caddr_t)icmp6 +
434 sizeof(struct icmp6_hdr));
435
436 /* Check which option that failed */
437 err_ptr = (u_int8_t *) ((caddr_t)icmp6 +
438 sizeof(struct icmp6_hdr) +
439 err_off);
440
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);
444 }
445
446 if (*err_ptr == IP6OPT_HOME_ADDRESS) {
447 log(LOG_ERR,
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. */
451 }
452 break;
453
454 case ND_ROUTER_ADVERT:
455 if (icmp6->icmp6_code != 0)
456 break;
457 if (icmp6len < sizeof(struct nd_router_advert))
458 break;
459
460 ra = (struct nd_router_advert *)icmp6;
461 if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_HA) == 0)
462 break;
463
464 if (mip6_rec_ra_hook) {
465 res = mip6_rec_ra_hook(m, off);
466 if (res) return res;
467 break;
468 }
469 }
470 return 0;
471 }
472
473
474
475 /*
476 ##############################################################################
477 #
478 # CONTROL SIGNAL FUNCTIONS
479 # Functions for processing of incoming control signals (Binding Update and
480 # Home Address option).
481 #
482 ##############################################################################
483 */
484
485 /*
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 ******************************************************************************
492 */
493 int
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 */
497 {
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 */
508 int res, error;
509 u_int8_t rtr;
510 #if MIP6_DEBUG
511 u_int8_t var;
512 int offset, ii;
513 #endif
514
515 subbuf = NULL;
516
517 /* Find the care-of address used by the MN when sending the BU. */
518 if (mip6_inp->coa)
519 coa = &mip6_inp->coa->coa;
520 else
521 coa = &mip6_inp->ip6_src;
522
523 /* Make sure that the BU contains a valid AH or ESP header. */
524 #if IPSEC
525 #ifndef __OpenBSD__
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++;
529 log(LOG_INFO,
530 "%s: No AH or ESP header in BU from host %s\n",
531 __FUNCTION__,
532 ip6_sprintf(coa));
533 return IPPROTO_DONE;
534 }
535 #endif
536 #endif
537
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++;
541 log(LOG_INFO,
542 "%s: No Home Address option included in BU from host %s\n",
543 __FUNCTION__, ip6_sprintf(coa));
544 return IPPROTO_DONE;
545 }
546
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++;
550 log(LOG_INFO,
551 "%s: Length field to short (%d) in BU from host %s\n",
552 __FUNCTION__, mip6_inp->bu_opt->len, ip6_sprintf(coa));
553 return IPPROTO_DONE;
554 }
555
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). */
558 send_na = 0;
559 bcp = mip6_bc_find(&mip6_inp->ha_opt->home_addr);
560 if (bcp != NULL) {
561 if (MIP6_LEQ(mip6_inp->bu_opt->seqno, bcp->seqno)) {
562 ip6stat.ip6s_badoptions++;
563 log(LOG_INFO,
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));
568 return IPPROTO_DONE;
569 }
570 if (!bcp->hr_flag)
571 send_na = 1;
572 } else
573 send_na = 1;
574
575 #if MIP6_DEBUG
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)
584 mip6_debug("A ");
585 if (mip6_inp->bu_opt->flags & MIP6_BU_HFLAG)
586 mip6_debug("H ");
587 if (mip6_inp->bu_opt->flags & MIP6_BU_RFLAG)
588 mip6_debug("R ");
589 mip6_debug("\n");
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);
595
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;
599
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)
603 mip6_debug("\t0x:");
604 if ((ii - IP6OPT_BULEN) % 4 == 0)
605 mip6_debug(" ");
606 m_copydata(m_in, offset + 2 + ii, sizeof(var),
607 (caddr_t)&var);
608 mip6_debug("%02x", var);
609 if ((ii - IP6OPT_BULEN + 1) % 16 == 0)
610 mip6_debug("\n");
611 }
612 if ((ii - IP6OPT_BULEN) % 16)
613 mip6_debug("\n");
614 }
615 end_debug:
616 #endif
617
618 /* Shall Dynamic Home Agent Address Discovery be performed? */
619 src_addr = NULL;
620 hal = NULL;
621
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) {
629 log(LOG_ERR,
630 "%s: No global source address found\n",
631 __FUNCTION__);
632 return IPPROTO_DONE;
633 }
634
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);
639 return IPPROTO_DONE;
640 }
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);
645 return error;
646 }
647 }
648
649 /* Check if BU includes Unique Identifier sub-option is present. */
650 /* XXX Code have to be added. */
651
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. */
657 error = 0;
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(
664 &mip6_inp->ip6_dst,
665 &mip6_inp->ha_opt->home_addr,
666 coa, NULL, MIP6_BA_STATUS_HOMEREGNOSUP,
667 mip6_inp->bu_opt->seqno, 0);
668 return error;
669 }
670
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);
675 if ((res != 0) &&
676 (mip6_inp->bu_opt->flags & MIP6_BU_AFLAG)) {
677 error = mip6_send_ba(
678 &mip6_inp->ip6_dst,
679 &mip6_inp->ha_opt->home_addr,
680 coa, NULL, res,
681 mip6_inp->bu_opt->seqno, 0);
682 return error;
683 }
684
685 /* Other reject reasons may be added, e.g.
686 insufficient resources to serve a MN. */
687 /* XXX Code may be added. */
688
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);
696
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);
700 if (bcp)
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);
705 else {
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);
711 if (bcp == NULL)
712 return IPPROTO_DONE;
713 }
714
715 /* Send a BA to the mobile node if the A-bit is
716 set in the BU. */
717 if (mip6_inp->bu_opt->flags & MIP6_BU_AFLAG) {
718 error = mip6_send_ba(&mip6_inp->ip6_dst,
719 &bcp->home_addr,
720 &bcp->coa,
721 NULL,
722 MIP6_BA_STATUS_ACCEPT,
723 bcp->seqno,
724 bcp->lifetime);
725 if (error)
726 return error;
727 }
728
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
731 tunnel to the MN. */
732 error = mip6_tunnel(&mip6_inp->ip6_dst,
733 &bcp->coa,
734 MIP6_TUNNEL_MOVE, MIP6_NODE_HA,
735 (void *)bcp);
736 if (error)
737 return IPPROTO_DONE;
738 error = mip6_proxy(&bcp->home_addr,
739 &mip6_inp->ip6_dst, RTM_ADD);
740 if (error) {
741 #if MIP6_DEBUG
742 mip6_debug("%s: set proxy error = %d\n",
743 __FUNCTION__, error);
744 #endif
745 return IPPROTO_DONE;
746 }
747
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
750 registration".
751 The first NA will be sent in the create function,
752 the remaining NAs are sent by the timer function. */
753 if (send_na) {
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;
758
759 mip6_na_create(&mip6_inp->ha_opt->home_addr,
760 &ll_allnode,
761 &mip6_inp->ha_opt->home_addr,
762 mip6_inp->bu_opt->prefix_len,
763 na_flags, 1);
764 }
765 } else {
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);
770 if (bcp)
771 mip6_bc_update(bcp, coa,
772 mip6_inp->bu_opt->lifetime,
773 0, rtr,
774 mip6_inp->bu_opt->prefix_len,
775 mip6_inp->bu_opt->seqno,
776 bcp->info, bcp->lasttime);
777 else {
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);
783 if (bcp == NULL)
784 return IPPROTO_DONE;
785 }
786
787 /* Send a BA to the mobile node if the A-bit is
788 set in the BU. */
789 if (mip6_inp->bu_opt->flags & MIP6_BU_AFLAG) {
790 error = mip6_send_ba(&mip6_inp->ip6_dst,
791 &bcp->home_addr,
792 &bcp->coa, NULL,
793 MIP6_BA_STATUS_ACCEPT,
794 bcp->seqno,
795 bcp->lifetime);
796 return error;
797 }
798 }
799 return 0;
800 }
801
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"
810 for this MN. */
811 error = 0;
812 if (((bcp == NULL) || (bcp->hr_flag == 0)) &&
813 (mip6_inp->bu_opt->flags & MIP6_BU_AFLAG)) {
814 error = mip6_send_ba(
815 &mip6_inp->ip6_dst,
816 &mip6_inp->ha_opt->home_addr,
817 coa, NULL, MIP6_BA_STATUS_NOTHA,
818 mip6_inp->bu_opt->seqno, 0);
819 return error;
820 }
821
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);
825 if (error)
826 return IPPROTO_DONE;
827
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(
831 &mip6_inp->ip6_dst,
832 &mip6_inp->ha_opt->home_addr,
833 coa, NULL, MIP6_BA_STATUS_ACCEPT,
834 mip6_inp->bu_opt->seqno, 0);
835 if (error)
836 return error;
837 }
838 } else {
839 /* The H-bit is NOT set. Request the CN to delete
840 the binding. */
841 if (bcp != NULL) {
842 error = mip6_bc_delete(bcp, &bcp_nxt);
843 if (error)
844 return IPPROTO_DONE;
845 }
846
847 if (mip6_inp->bu_opt->flags & MIP6_BU_AFLAG) {
848 error = mip6_send_ba(
849 &mip6_inp->ip6_dst,
850 &mip6_inp->ha_opt->home_addr,
851 coa, NULL, MIP6_BA_STATUS_ACCEPT,
852 mip6_inp->bu_opt->seqno, 0);
853 if (error)
854 return error;
855 }
856 }
857 return 0;
858 }
859 return 0;
860 }
861
862
863
864 /*
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 ******************************************************************************
870 */
871 void
872 mip6_ha2srcaddr(m)
873 struct mbuf *m; /* The entire IPv6 packet */
874 {
875 register struct ip6_hdr *ip6; /* IPv6 header */
876
877 #if MIP6_DEBUG
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));
883 #endif
884
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;
888 }
889
890
891
892 /*
893 ##############################################################################
894 #
895 # SENDING FUNCTIONS
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.
900 #
901 ##############################################################################
902 */
903
904 /*
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).
910 * Ret value: 0 OK
911 * IPPROTO_DONE If anything goes wrong.
912 ******************************************************************************
913 */
914 int
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 */
923 {
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 */
927 int error;
928 #if MIP6_DEBUG
929 u_int8_t var;
930 int ii;
931 #endif
932
933 opt = (struct ip6_pktopts *)MALLOC ip6_pktopts),
934 M_TEMP, M_WAITOK);
935 if (opt == NULL)
936 return IPPROTO_DONE;
937 bzero(opt, sizeof(struct ip6_pktopts));
938
939 opt->ip6po_hlim = -1; /* -1 means to use default hop limit */
940 m_ip6 = mip6_create_ip6hdr(ip6_src, ip6_dst, IPPROTO_NONE);
941 if(m_ip6 == NULL)
942 return IPPROTO_DONE;
943
944 opt->ip6po_rhinfo.ip6po_rhi_rthdr = mip6_create_rh(coa,
945 IPPROTO_DSTOPTS);
946 if(opt->ip6po_rhinfo.ip6po_rhi_rthdr == NULL)
947 return IPPROTO_DONE;
948
949 ba_opt = mip6_create_ba(status, seqno, lifetime);
950 if (ba_opt == NULL)
951 return IPPROTO_DONE;
952
953 opt->ip6po_dest2 = mip6_create_dh((void *)ba_opt, subbuf,
954 IPPROTO_NONE);
955 if(opt->ip6po_dest2 == NULL)
956 return IPPROTO_DONE;
957
958 mip6_config.enable_outq = 0;
959 error = ip6_output(m_ip6, opt, NULL, 0, NULL, NULL);
960 if (error) {
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;
965 log(LOG_ERR,
966 "%s: ip6_output function failed to send BA, error = %d\n",
967 __FUNCTION__, error);
968 return error;
969 }
970 mip6_config.enable_outq = 1;
971
972 #if MIP6_DEBUG
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);
981
982 if (subbuf) {
983 mip6_debug("Sub-options present (TLV coded)\n");
984 for (ii = 0; ii < subbuf->len; ii++) {
985 if (ii % 16 == 0)
986 mip6_debug("\t0x:");
987 if (ii % 4 == 0)
988 mip6_debug(" ");
989 bcopy((caddr_t)&subbuf->buffer[ii], (caddr_t)&var, 1);
990 mip6_debug("%02x", var);
991 if ((ii + 1) % 16 == 0)
992 mip6_debug("\n");
993 }
994 if (ii % 16)
995 mip6_debug("\n");
996 }
997 #endif
998
999 _FREE(opt->ip6po_rhinfo.ip6po_rhi_rthdr, M_TEMP);
1000 _FREE(opt->ip6po_dest2, M_TEMP);
1001 _FREE(ba_opt, M_TEMP);
1002 return 0;
1003 }
1004
1005
1006
1007 /*
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
1013 * as well.
1014 * Ret value: -
1015 ******************************************************************************
1016 */
1017 void
1018 mip6_send_na(nap)
1019 struct mip6_na *nap; /* Neighbor Advertisement sent */
1020 {
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 */
1025
1026 nap->no -= 1;
1027
1028 #if MIP6_DEBUG
1029 mip6_debug("\nSent Neighbor Advertisement (0x%x)\n", nap);
1030 #endif
1031
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);
1038 #if MIP6_DEBUG
1039 mip6_debug("Target Address: %s\n",
1040 ip6_sprintf(&nap->target_addr));
1041 #endif
1042 }
1043
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,
1048 &nap->target_addr,
1049 pq->prefix_len)) {
1050 mip6_build_in6addr(&new_addr,
1051 &nap->target_addr,
1052 &pq->prefix,
1053 pq->prefix_len);
1054 nd6_na_output(nap->ifp, &nap->dst_addr,
1055 &new_addr, nap->flags,
1056 nap->use_link_opt, NULL);
1057 #if MIP6_DEBUG
1058 mip6_debug("Target Address: %s\n",
1059 ip6_sprintf(&new_addr));
1060 #endif
1061 } else
1062 continue;
1063
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,
1072 &nap->target_addr,
1073 &sl_addr,
1074 nap->prefix_len);
1075 nd6_na_output(nap->ifp,
1076 &nap->dst_addr,
1077 &new_addr,
1078 nap->flags,
1079 nap->use_link_opt, NULL);
1080 #if MIP6_DEBUG
1081 mip6_debug("Target Address: %s\n",
1082 ip6_sprintf(&new_addr));
1083 #endif
1084
1085 /* NA for the link-local address is
1086 only sent if length equals to 64. */
1087 mip6_build_in6addr(&new_addr,
1088 &nap->target_addr,
1089 &in6addr_linklocal,
1090 nap->prefix_len);
1091 nd6_na_output(nap->ifp,
1092 &nap->dst_addr,
1093 &new_addr,
1094 nap->flags,
1095 nap->use_link_opt, NULL);
1096 #if MIP6_DEBUG
1097 mip6_debug("Target Address: %s\n",
1098 ip6_sprintf(&new_addr));
1099 #endif
1100 }
1101 }
1102 } else {
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,
1106 &pr->ndpr_addr,
1107 pr->ndpr_plen)) {
1108 mip6_build_in6addr(
1109 &new_addr,
1110 &nap->target_addr,
1111 &pr->ndpr_prefix.sin6_addr,
1112 pr->ndpr_plen);
1113 nd6_na_output(nap->ifp,
1114 &nap->dst_addr,
1115 &new_addr,
1116 nap->flags,
1117 nap->use_link_opt, NULL);
1118 #if MIP6_DEBUG
1119 mip6_debug("Target Address: %s\n",
1120 ip6_sprintf(&new_addr));
1121 #endif
1122 } else
1123 continue;
1124
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,
1133 &nap->target_addr,
1134 &sl_addr,
1135 nap->prefix_len);
1136 nd6_na_output(nap->ifp,
1137 &nap->dst_addr,
1138 &new_addr,
1139 nap->flags,
1140 nap->use_link_opt, NULL);
1141 #if MIP6_DEBUG
1142 mip6_debug("Target Address: %s\n",
1143 ip6_sprintf(&new_addr));
1144 #endif
1145
1146 /* NA for the link-local address is
1147 only sent if length equals to 64. */
1148 mip6_build_in6addr(&new_addr,
1149 &nap->target_addr,
1150 &in6addr_linklocal,
1151 nap->prefix_len);
1152 nd6_na_output(nap->ifp,
1153 &nap->dst_addr,
1154 &new_addr,
1155 nap->flags,
1156 nap->use_link_opt, NULL);
1157 #if MIP6_DEBUG
1158 mip6_debug("Target Address: %s\n",
1159 ip6_sprintf(&new_addr));
1160 #endif
1161 }
1162 }
1163 }
1164 return;
1165 }
1166
1167
1168
1169 /*
1170 ##############################################################################
1171 #
1172 # UTILITY FUNCTIONS
1173 # Miscellaneous functions needed for the internal processing of incoming and
1174 # outgoing control signals.
1175 #
1176 ##############################################################################
1177 */
1178
1179 /*
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 ******************************************************************************
1187 */
1188 struct mbuf *
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 */
1193 {
1194 struct ip6_hdr *ip6; /* IPv6 header */
1195 struct mbuf *m; /* Ptr to mbuf allocated for output data */
1196
1197 /* Allocate memory for the IPv6 header and fill it with data */
1198 ip6 = (struct ip6_hdr *)MALLOC ip6_hdr),
1199 M_TEMP, M_WAITOK);
1200 if (ip6 == NULL)
1201 return NULL;
1202 bzero(ip6, sizeof(struct ip6_hdr));
1203
1204 ip6->ip6_flow = 0;
1205 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1206 ip6->ip6_vfc |= IPV6_VERSION;
1207 ip6->ip6_plen = 0;
1208 ip6->ip6_nxt = next;
1209 ip6->ip6_hlim = IPV6_DEFHLIM;
1210
1211 ip6->ip6_src = *ip6_src;
1212 ip6->ip6_dst = *ip6_dst;
1213
1214 /* Allocate memory for mbuf and copy IPv6 header to mbuf. */
1215 MGETHDR(m, M_DONTWAIT, MT_DATA);
1216 if (m == NULL) {
1217 return NULL;
1218 }
1219
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));
1224 _FREE(ip6, M_TEMP);
1225 return m;
1226 }
1227
1228
1229
1230 /*
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.
1235 * Otherwise NULL.
1236 ******************************************************************************
1237 */
1238 struct ip6_rthdr *
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 */
1242 {
1243 struct ip6_rthdr0 *rthdr0; /* Routing header type 0 */
1244 int len;
1245
1246 len = sizeof(struct ip6_rthdr0) + sizeof(struct in6_addr);
1247 rthdr0 = (struct ip6_rthdr0 *)MALLOC M_TEMP, M_WAITOK);
1248 if (rthdr0 == NULL)
1249 return NULL;
1250 bzero(rthdr0, len);
1251
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;
1260 }
1261
1262
1263
1264 /*
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 ******************************************************************************
1271 */
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 */
1277 {
1278 struct mip6_opt_ba *ba_opt; /* BA allocated in this function */
1279
1280 /* Allocate a Binding Aknowledgement option and set values */
1281 ba_opt = (struct mip6_opt_ba *)MALLOC mip6_opt_ba),
1282 M_TEMP, M_WAITOK);
1283 if (ba_opt == NULL)
1284 return NULL;
1285 bzero(ba_opt, sizeof(struct mip6_opt_ba));
1286
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;
1292
1293 /* Calculate value for refresh time */
1294 if (MIP6_IS_HA_ACTIVE)
1295 ba_opt->refresh = (ba_opt->lifetime * 8) / 10;
1296 else
1297 ba_opt->refresh = ba_opt->lifetime;
1298
1299 return ba_opt;
1300 }
1301
1302
1303
1304 /*
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.
1309 * Otherwise NULL.
1310 ******************************************************************************
1311 */
1312 struct ip6_dest *
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 */
1317 {
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 */
1322
1323 opt = (struct mip6_opt *)arg_opt;
1324 dest = NULL;
1325 if (opt->type == IP6OPT_BINDING_ACK) {
1326 off = 3;
1327 error = mip6_add_ba(&dest, &off,
1328 (struct mip6_opt_ba *)opt, arg_sub);
1329 if (error) {
1330 if (dest != NULL)
1331 _FREE(dest, M_TEMP);
1332 return NULL;
1333 }
1334 dest->ip6d_nxt = next;
1335 } else if (opt->type == IP6OPT_BINDING_UPDATE) {
1336 off = 2;
1337 error = mip6_add_bu(&dest, &off,
1338 (struct mip6_opt_bu *)opt, arg_sub);
1339 if (error) {
1340 if (dest != NULL)
1341 _FREE(dest, M_TEMP);
1342 return NULL;
1343 }
1344 dest->ip6d_nxt = next;
1345 }
1346 return dest;
1347 }
1348
1349
1350
1351 /*
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
1359 * error.
1360 ******************************************************************************
1361 */
1362 int
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 */
1367 {
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 */
1374
1375 m_copydata(m_in, off + 1, sizeof(len8), (caddr_t)&len8);
1376 len = (len8 + 1) << 3;
1377
1378 offset = 0;
1379 for (ii = 2; ii < len;) {
1380 m_copydata(m_in, off + ii, sizeof(opttype), (caddr_t)&opttype);
1381 if (opttype == type) {
1382 offset = off + ii;
1383 break;
1384 } else if (opttype == IP6OPT_PAD1) {
1385 ii += 1;
1386 continue;
1387 } else {
1388 ii += 1;
1389 }
1390
1391 m_copydata(m_in, off + ii, sizeof(optlen), (caddr_t)&optlen);
1392 ii += 1 + optlen;
1393 }
1394 return offset;
1395 }
1396
1397
1398
1399 /*
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.
1404 * Ret value: 0 = OK
1405 * 133 = Not home subnet
1406 * 136 = Incorrect interface identifier length
1407 ******************************************************************************
1408 */
1409 int
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 */
1413 {
1414 struct mip6_prefix *pr; /* Pointer to entries in the prexix list */
1415
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)
1422 return 0;
1423
1424 if (pr->prefix_len == prefix_len)
1425 return 0;
1426 else
1427 return MIP6_BA_STATUS_IFLEN;
1428 }
1429 }
1430 return MIP6_BA_STATUS_SUBNET;
1431 }
1432
1433
1434
1435 /*
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
1443 * node's home link.
1444 * Note: This function is only used by the Home Agent.
1445 * Ret value: Lifetime
1446 ******************************************************************************
1447 */
1448 u_int32_t
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 */
1452 {
1453 struct mip6_prefix *pr; /* Ptr to entries in the prexix list */
1454 u_int32_t min_time; /* Minimum life time */
1455
1456 min_time = 0xffffffff;
1457
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,
1462 pr->prefix_len)) {
1463 return pr->valid_time;
1464 }
1465 } else
1466 min_time = min(min_time, pr->valid_time);
1467 }
1468 return min_time;
1469 }
1470
1471
1472
1473 /*
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.
1478 * Ret value: -
1479 ******************************************************************************
1480 */
1481 void
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) */
1487 {
1488 u_int8_t byte_pr, byte_id;
1489 int ii, jj;
1490
1491 for (ii = 0; ii < prefix_len / 8; ii++)
1492 new_addr->s6_addr8[ii] = prefix->s6_addr8[ii];
1493
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));
1499
1500 /* Then, add the first bits of the interface id to the
1501 common byte. */
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;
1506 ii += 1;
1507 }
1508
1509 for (jj = ii; jj < 16; jj++)
1510 new_addr->s6_addr8[jj] = id->s6_addr8[jj];
1511 }
1512
1513
1514
1515 /*
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
1520 * RFC2526.
1521 * Ret value: -
1522 ******************************************************************************
1523 */
1524 void
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) */
1529 {
1530 struct in6_addr addr;
1531
1532
1533 if (prefix->s6_addr8[0] == 0xff) {
1534 *new_addr = in6addr_any;
1535 return;
1536 }
1537
1538 if (((prefix->s6_addr8[0] & 0xe0) != 0) && (prefix_len != 64)) {
1539 *new_addr = in6addr_any;
1540 return;
1541 }
1542
1543 if (((prefix->s6_addr8[0] & 0xe0) != 0) && (prefix_len == 64))
1544 addr = in6addr_aha_64;
1545 else
1546 addr = in6addr_aha_nn;
1547
1548 mip6_build_in6addr(new_addr, &addr, prefix, prefix_len);
1549 }
1550
1551
1552
1553 /*
1554 ******************************************************************************
1555 * Function: mip6_add_ifaddr
1556 * Description: Similar to "ifconfig <ifp> <addr> prefixlen <plen>".
1557 * Ret value: Standard error codes.
1558 ******************************************************************************
1559 */
1560 int
1561 mip6_add_ifaddr(struct in6_addr *addr,
1562 struct ifnet *ifp,
1563 int plen,
1564 int flags) /* Note: IN6_IFF_NODAD available flag */
1565 {
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;
1572 int s;
1573 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1574 struct ifaddr *ifa;
1575 #endif
1576 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
1577 time_t time_second = (time_t)time.tv_sec;
1578 #endif
1579
1580 bzero(&dummy, sizeof(dummy));
1581 ifra = &dummy;
1582
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;
1586
1587 if (plen != 0) {
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? */
1593 }
1594
1595 ifra->ifra_flags = flags;
1596 ifra->ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
1597 ifra->ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
1598
1599 sa6 = &ifra->ifra_addr;
1600
1601 /* "ifconfig ifp inet6 Home_Address prefixlen 64/128 (alias?)" */
1602 if (ifp == 0)
1603 return EOPNOTSUPP;
1604
1605 s = splnet();
1606
1607 /*
1608 * Code recycled from in6_control().
1609 */
1610
1611 /*
1612 * Find address for this interface, if it exists.
1613 */
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);
1619 }
1620 else if (sa6->sin6_addr.s6_addr16[1] !=
1621 htons(ifp->if_index)) {
1622 splx(s);
1623 return(EINVAL); /* ifid is contradict */
1624 }
1625 if (sa6->sin6_scope_id) {
1626 if (sa6->sin6_scope_id !=
1627 (u_int32_t)ifp->if_index) {
1628 splx(s);
1629 return(EINVAL);
1630 }
1631 sa6->sin6_scope_id = 0; /* XXX: good way? */
1632 }
1633 }
1634 ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
1635
1636 if (ia == 0) {
1637 ia = (struct in6_ifaddr *)
1638 MALLOC M_IFADDR, M_WAITOK);
1639 if (ia == NULL) {
1640 splx(s);
1641 return (ENOBUFS);
1642 }
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;
1649
1650 ia->ia_ifp = ifp;
1651 if ((oia = in6_ifaddr) != NULL) {
1652 for ( ; oia->ia_next; oia = oia->ia_next)
1653 continue;
1654 oia->ia_next = ia;
1655 } else
1656 in6_ifaddr = ia;
1657 ia->ia_ifa.ifa_refcnt++;
1658
1659 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1660 if ((ifa = ifp->if_addrlist) != NULL) {
1661 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
1662 continue;
1663 ifa->ifa_next = &ia->ia_ifa;
1664 } else
1665 ifp->if_addrlist = &ia->ia_ifa;
1666 #else
1667 TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa,
1668 ifa_list);
1669 #endif
1670 ia->ia_ifa.ifa_refcnt++;
1671 }
1672
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) {
1677 splx(s);
1678 return EINVAL;
1679 }
1680 if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
1681 && lt->ia6t_pltime + time_second < time_second) {
1682 splx(s);
1683 return EINVAL;
1684 }
1685 prefixIsNew = 0;
1686 hostIsNew = 1;
1687
1688 if (ifra->ifra_addr.sin6_len == 0) {
1689 ifra->ifra_addr = ia->ia_addr;
1690 hostIsNew = 0;
1691 } else if (IN6_ARE_ADDR_EQUAL(&ifra->ifra_addr.sin6_addr,
1692 &ia->ia_addr.sin6_addr))
1693 hostIsNew = 0;
1694
1695 if (ifra->ifra_prefixmask.sin6_len) {
1696 in6_ifscrub(ifp, ia);
1697 ia->ia_prefixmask = ifra->ifra_prefixmask;
1698 prefixIsNew = 1;
1699 }
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) {
1708 /*
1709 * interface ID is not embedded by
1710 * the user
1711 */
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;
1717 splx(s);
1718 return(EINVAL); /* ifid is contradict */
1719 }
1720 }
1721 prefixIsNew = 1; /* We lie; but effect's the same */
1722 }
1723 if (ifra->ifra_addr.sin6_family == AF_INET6 &&
1724 (hostIsNew || prefixIsNew))
1725 {
1726 error = in6_ifinit(ifp, ia, &ifra->ifra_addr, 0);
1727 }
1728 if (ifra->ifra_addr.sin6_family == AF_INET6
1729 && hostIsNew && (ifp->if_flags & IFF_MULTICAST)) {
1730 int error_local = 0;
1731
1732 /*
1733 * join solicited multicast addr for new host id
1734 */
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);
1745 if (error == 0)
1746 error = error_local;
1747 }
1748
1749 ia->ia6_flags = ifra->ifra_flags;
1750 ia->ia6_flags &= ~IN6_IFF_DUPLICATED; /*safety*/
1751 ia->ia6_flags &= ~IN6_IFF_NODAD; /* Mobile IPv6 */
1752
1753 ia->ia6_lifetime = ifra->ifra_lifetime;
1754 /* for sanity */
1755 if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
1756 ia->ia6_lifetime.ia6t_expire =
1757 time_second + ia->ia6_lifetime.ia6t_vltime;
1758 } else
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;
1763 } else
1764 ia->ia6_lifetime.ia6t_preferred = 0;
1765
1766 /*
1767 * Perform DAD, if needed.
1768 * XXX It may be of use, if we can administratively
1769 * disable DAD.
1770 */
1771 switch (ifp->if_type) {
1772 case IFT_ARCNET:
1773 case IFT_ETHER:
1774 case IFT_FDDI:
1775 #if 0
1776 case IFT_ATM:
1777 case IFT_SLIP:
1778 case IFT_PPP:
1779 #endif
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);
1784 }
1785 break;
1786 case IFT_DUMMY:
1787 case IFT_FAITH:
1788 case IFT_GIF:
1789 case IFT_LOOP:
1790 default:
1791 break;
1792 }
1793
1794 if (hostIsNew) {
1795 int iilen;
1796 int error_local = 0;
1797
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);
1801 if (error == 0)
1802 error = error_local;
1803 }
1804
1805 splx(s);
1806 return error;
1807
1808
1809 }
1810
1811
1812
1813 /*
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 ******************************************************************************
1821 */
1822 int
1823 mip6_tunnel_output(mp, bc)
1824 struct mbuf **mp;
1825 struct mip6_bc *bc;
1826 {
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;
1833 u_int8_t itos;
1834 int len;
1835
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;
1840
1841 if (ep->af != AF_INET6 || ep->dst.ss_len != dst.sin6_len ||
1842 bcmp(&ep->dst, &dst, dst.sin6_len) != 0 )
1843 return EFAULT;
1844
1845 /* Recursion problems? */
1846
1847 if (IN6_IS_ADDR_UNSPECIFIED(&sin6_src->sin6_addr)) {
1848 return EFAULT;
1849 }
1850
1851 len = m->m_pkthdr.len;
1852
1853 if (m->m_len < sizeof(*ip6)) {
1854 m = m_pullup(m, sizeof(*ip6));
1855 if (!m)
1856 return ENOBUFS;
1857 }
1858 ip6 = mtod(m, struct ip6_hdr *);
1859 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
1860
1861
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));
1866 if (m == NULL) {
1867 #if MIP6_DEBUG
1868 printf("ENOBUFS in mip6_tunnel_output %d\n", __LINE__);
1869 #endif
1870 return ENOBUFS;
1871 }
1872
1873 ip6 = mtod(m, struct ip6_hdr *);
1874 ip6->ip6_flow = 0;
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;
1881
1882 /* bidirectional configured tunnel mode */
1883 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
1884 ip6->ip6_dst = sin6_dst->sin6_addr;
1885 else
1886 return ENETUNREACH;
1887
1888 *mp = m;
1889 return 0;
1890 }
1891
1892
1893
1894 /*
1895 ******************************************************************************
1896 * Function: mip6_tunnel_input
1897 * Description: similar to gif_input() and in6_gif_input().
1898 * Ret value: standard error codes.
1899 ******************************************************************************
1900 */
1901 int
1902 mip6_tunnel_input(mp, offp, proto)
1903 struct mbuf **mp;
1904 int *offp, proto;
1905 {
1906 struct mbuf *m = *mp;
1907 struct ip6_hdr *ip6;
1908 int s, af = 0;
1909 u_int32_t otos;
1910
1911 ip6 = mtod(m, struct ip6_hdr *);
1912 otos = ip6->ip6_flow;
1913 m_adj(m, *offp);
1914
1915 switch (proto) {
1916 case IPPROTO_IPV6:
1917 {
1918 struct ip6_hdr *ip6;
1919 af = AF_INET6;
1920 if (m->m_len < sizeof(*ip6)) {
1921 m = m_pullup(m, sizeof(*ip6));
1922 if (!m)
1923 return IPPROTO_DONE;
1924 }
1925 m->m_flags |= M_MIP6TUNNEL; /* Tell MN that this packet
1926 was tunnelled. */
1927 ip6 = mtod(m, struct ip6_hdr *);
1928
1929 s = splimp();
1930 if (IF_QFULL(&ip6intrq)) {
1931 IF_DROP(&ip6intrq); /* update statistics */
1932 m_freem(m);
1933 splx(s);
1934 return IPPROTO_DONE;
1935 }
1936 IF_ENQUEUE(&ip6intrq, m);
1937 #if 0
1938 /* we don't need it as we tunnel IPv6 in IPv6 only. */
1939 schednetisr(NETISR_IPV6);
1940 #endif
1941 splx(s);
1942 break;
1943 }
1944 default:
1945 #if MIP6_DEBUG
1946 mip6_debug("%s: protocol %d not supported.\n", __FUNCTION__,
1947 proto);
1948 #endif
1949 m_freem(m);
1950 return IPPROTO_DONE;
1951 }
1952
1953 return IPPROTO_DONE;
1954 }
1955
1956
1957
1958 /*
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 ******************************************************************************
1965 */
1966 int
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 */
1973 {
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;
1979 int mask_len = 128;
1980
1981 ep_store = NULL;
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;
1986 else {
1987 #if MIP6_DEBUG
1988 printf("%s: Tunnel not modified\n", __FUNCTION__);
1989 #endif
1990 return 0;
1991 }
1992
1993 if (action == MIP6_TUNNEL_DEL) {
1994 /* Moving to Home network. Remove tunnel. */
1995 if (ep_store && *ep_store) {
1996 encap_detach(*ep_store);
1997 *ep_store = NULL;
1998 }
1999 return 0;
2000 }
2001
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);
2006 *ep_store = NULL;
2007 }
2008
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;
2013
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;
2019
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;
2024
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;
2030
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,
2037 NULL);
2038 if (ep == NULL)
2039 return EINVAL;
2040 *ep_store = ep;
2041 return 0;
2042 }
2043 return EINVAL;
2044 }
2045
2046
2047
2048 /*
2049 ******************************************************************************
2050 * Function: mip6_proxy
2051 * Description: Set or delete address to act proxy for.
2052 * Ret value: Standard error codes.
2053 ******************************************************************************
2054 */
2055 int
2056 mip6_proxy(struct in6_addr* addr,
2057 struct in6_addr* local,
2058 int cmd)
2059 {
2060 struct sockaddr_in6 mask /* = {sizeof(mask), AF_INET6 }*/;
2061 struct sockaddr_in6 sa6;
2062 struct sockaddr_dl *sdl;
2063 struct ifaddr *ifa;
2064 struct ifnet *ifp;
2065 int flags, error;
2066 struct rtentry *nrt;
2067
2068 if (cmd == RTM_DELETE) {
2069 struct rtentry *rt;
2070
2071 bzero(&sa6, sizeof(sa6));
2072 sa6.sin6_family = AF_INET6;
2073 sa6.sin6_len = sizeof(sa6);
2074 sa6.sin6_addr = *addr;
2075
2076 #ifdef __FreeBSD__ || defined (__APPLE__)
2077 rt = rtalloc1((struct sockaddr *)&sa6, 1, 0UL);
2078 #else
2079 rt = rtalloc1((struct sockaddr *)&sa6, 1);
2080 #endif
2081 if (rt == NULL)
2082 return EHOSTUNREACH;
2083
2084 error = rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
2085 rt_mask(rt), 0, (struct rtentry **)0);
2086 rt->rt_refcnt--;
2087 rt = NULL;
2088 return error;
2089 }
2090
2091 /* Create sa6 */
2092 bzero(&sa6, sizeof(sa6));
2093 sa6.sin6_family = AF_INET6;
2094 sa6.sin6_len = sizeof(sa6);
2095 sa6.sin6_addr = *local;
2096
2097 ifa = ifa_ifwithaddr((struct sockaddr *)&sa6);
2098 if (ifa == NULL)
2099 return EINVAL;
2100
2101 sa6.sin6_addr = *addr;
2102
2103 /* Create sdl */
2104 ifp = ifa->ifa_ifp;
2105
2106 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
2107 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
2108 #else
2109 for (ifa = ifp->if_addrlist.tqh_first; ifa;
2110 ifa = ifa->ifa_list.tqe_next)
2111 #endif
2112 if (ifa->ifa_addr->sa_family == AF_LINK)
2113 break;
2114
2115 if (!ifa)
2116 return EINVAL;
2117
2118 MALLOC(sdl, struct sockaddr_dl *, ifa->ifa_addr->sa_len, M_IFMADDR,
2119 M_WAITOK);
2120 bcopy((struct sockaddr_dl *)ifa->ifa_addr, sdl, ifa->ifa_addr->sa_len);
2121
2122 /* Create mask */
2123 bzero(&mask, sizeof(mask));
2124 mask.sin6_family = AF_INET6;
2125 mask.sin6_len = sizeof(mask);
2126
2127 in6_len2mask(&mask.sin6_addr, 128);
2128
2129 flags = (RTF_STATIC | RTF_ANNOUNCE | RTA_NETMASK);
2130
2131 error = rtrequest(RTM_ADD, (struct sockaddr *)&sa6,
2132 (struct sockaddr *)sdl,
2133 (struct sockaddr *)&mask, flags, &nrt);
2134
2135 if (error == 0) {
2136 /* avoid expiration */
2137 if (nrt) {
2138 nrt->rt_rmx.rmx_expire = 0;
2139 nrt->rt_genmask = NULL;
2140 nrt->rt_refcnt--;
2141 }
2142 else
2143 error = EINVAL;
2144 }
2145 _FREE(sdl, M_IFMADDR);
2146 return error;
2147 }
2148
2149
2150
2151 /*
2152 ##############################################################################
2153 #
2154 # LIST FUNCTIONS
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.
2160 #
2161 ##############################################################################
2162 */
2163
2164 /*
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 ******************************************************************************
2170 */
2171 struct mip6_bc *
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 */
2175 {
2176 struct mip6_bc *bcp; /* Entry in the Binding Cache list */
2177
2178 for (bcp = mip6_bcq; bcp; bcp = bcp->next) {
2179 if (IN6_ARE_ADDR_EQUAL(home_addr, &bcp->home_addr))
2180 return bcp;
2181 }
2182 return NULL;
2183 }
2184
2185
2186
2187 /*
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 ******************************************************************************
2199 */
2200 struct mip6_bc *
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 */
2209 {
2210 struct mip6_bc *bcp; /* Created BC list entry*/
2211 int s;
2212
2213 bcp = (struct mip6_bc *)MALLOC mip6_bc),
2214 M_TEMP, M_WAITOK);
2215 if (bcp == NULL)
2216 return NULL;
2217 bzero((caddr_t)bcp, sizeof(struct mip6_bc));
2218
2219 bcp->next = NULL;
2220 bcp->home_addr = *home_addr;
2221 bcp->coa = *coa;
2222 bcp->lifetime = lifetime;
2223 bcp->hr_flag = hr;
2224 bcp->prefix_len = prefix_len;
2225 bcp->seqno = seqno;
2226 bcp->lasttime = 0;
2227 bcp->ep = NULL;
2228
2229 if (bcp->hr_flag)
2230 bcp->rtr_flag = rtr;
2231 else {
2232 bcp->rtr_flag = 0;
2233
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;
2238 else
2239 bcp->info.br_interval = mip6_config.br_update;
2240 }
2241
2242 /* Insert the entry as the first entry in the Binding Cache list. */
2243 s = splnet();
2244 if (mip6_bcq == NULL) {
2245 mip6_bcq = bcp;
2246 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2247 mip6_timer_bc_handle =
2248 #endif
2249 timeout(mip6_timer_bc, (void *)0, hz);
2250 } else {
2251 bcp->next = mip6_bcq;
2252 mip6_bcq = bcp;
2253 }
2254 splx(s);
2255
2256 #if MIP6_DEBUG
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: ");
2264 if (bcp->hr_flag)
2265 mip6_debug("TRUE / ");
2266 else
2267 mip6_debug("FALSE / ");
2268
2269 if (bcp->rtr_flag)
2270 mip6_debug("TRUE\n");
2271 else
2272 mip6_debug("FALSE\n");
2273 #endif
2274 return bcp;
2275 }
2276
2277
2278
2279 /*
2280 ******************************************************************************
2281 * Function: mip6_bc_update
2282 * Description: Update an existing Binding Cache entry
2283 * Ret value: -
2284 * Note: The gif i/f is created/updated in function mip6_tunnel and
2285 * should not be taken care of here.
2286 ******************************************************************************
2287 */
2288 void
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 */
2299 {
2300 bcp->coa = *coa;
2301 bcp->lifetime = lifetime;
2302 bcp->hr_flag = hr;
2303 bcp->prefix_len = prefix_len;
2304 bcp->seqno = seqno;
2305
2306 if (bcp->hr_flag) {
2307 bcp->rtr_flag = rtr;
2308 bzero((caddr_t)&bcp->info, sizeof(struct bc_info));
2309 } else {
2310 bcp->rtr_flag = 0;
2311
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;
2316 else
2317 bcp->info.br_interval = info.br_interval;
2318 }
2319 bcp->lasttime = lasttime;
2320
2321 #if MIP6_DEBUG
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: ");
2329 if (bcp->hr_flag)
2330 mip6_debug("TRUE / ");
2331 else
2332 mip6_debug("FALSE / ");
2333
2334 if (bcp->rtr_flag)
2335 mip6_debug("TRUE\n");
2336 else
2337 mip6_debug("FALSE\n");
2338 #endif
2339 return;
2340 }
2341
2342
2343
2344 /*
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 ******************************************************************************
2351 */
2352 int
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 */
2356 {
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 */
2360 int s, error = 0;
2361
2362 s = splnet();
2363 bcp_prev = NULL;
2364 bcp_next = NULL;
2365 for (bcp = mip6_bcq; bcp; bcp = bcp->next) {
2366 bcp_next = bcp->next;
2367 if (bcp != bcp_del) {
2368 bcp_prev = bcp;
2369 continue;
2370 }
2371
2372 /* Make sure that the list pointers are correct. */
2373 if (bcp_prev == NULL)
2374 mip6_bcq = bcp->next;
2375 else
2376 bcp_prev->next = bcp->next;
2377
2378 if (bcp->hr_flag) {
2379 /* The HA should stop acting as a proxy for the MN. */
2380 error = mip6_proxy(&bcp->home_addr, NULL, RTM_DELETE);
2381 if (error) {
2382 #if MIP6_DEBUG
2383 mip6_debug("%s: delete proxy error = %d\n",
2384 __FUNCTION__, error);
2385 #endif
2386 *bcp_nxt = bcp_next;
2387 return error;
2388 }
2389
2390 /* Delete the existing tunnel to the MN. */
2391 mip6_tunnel(NULL, NULL, MIP6_TUNNEL_DEL, MIP6_NODE_HA,
2392 (void *)bcp);
2393 }
2394
2395 #if MIP6_DEBUG
2396 mip6_debug("\nBinding Cache Entry deleted (0x%x)\n", bcp);
2397 #endif
2398 _FREE(bcp, M_TEMP);
2399
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);
2406 #else
2407 untimeout(mip6_timer_bc, (void *)NULL);
2408 #endif
2409 }
2410 break;
2411 }
2412 splx(s);
2413
2414 *bcp_nxt = bcp_next;
2415 return error;
2416 }
2417
2418
2419
2420 /*
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 ******************************************************************************
2431 */
2432 struct mip6_na *
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) */
2442 {
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;
2449
2450 llp = NULL;
2451 halp = NULL;
2452 addrp = NULL;
2453 pr = NULL;
2454
2455 if (mip6_naq == NULL)
2456 start_timer = 1;
2457
2458 nap = (struct mip6_na *)MALLOC mip6_na),
2459 M_TEMP, M_WAITOK);
2460 if (nap == NULL)
2461 return NULL;
2462 bzero(nap, sizeof(struct mip6_na));
2463
2464 nap->next = NULL;
2465 nap->home_addr = *home_addr;
2466 nap->dst_addr = *dst_addr;
2467 nap->target_addr = *target_addr;
2468 nap->prefix_len = prefix_len;
2469 nap->flags = flags;
2470 nap->use_link_opt = use_link_opt;
2471 nap->no = MIP6_MAX_ADVERT_REXMIT;
2472
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(
2482 home_addr,
2483 &addrp->ip6_addr,
2484 addrp->prefix_len))
2485 break;
2486 }
2487 if (addrp != NULL)
2488 break;
2489 }
2490 if (addrp != NULL)
2491 break;
2492 }
2493 if (addrp == NULL) {
2494 log(LOG_ERR,
2495 "%s: No interface found for sending Neighbor "
2496 "Advertisements at\n", __FUNCTION__);
2497 return NULL;
2498 }
2499 nap->ifp = llp->ifp;
2500 }
2501
2502 if (MIP6_IS_MN_ACTIVE) {
2503 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
2504 if (!pr->ndpr_stateflags.onlink)
2505 continue;
2506 if (in6_are_prefix_equal(home_addr,
2507 &pr->ndpr_prefix.sin6_addr,
2508 pr->ndpr_plen))
2509 break;
2510 }
2511 if (pr == NULL) {
2512 log(LOG_ERR,
2513 "%s: No interface found for sending Neighbor "
2514 "Advertisements at\n", __FUNCTION__);
2515 return NULL;
2516 }
2517 nap->ifp = pr->ndpr_ifp;
2518 }
2519
2520 /* Add the new na entry first to the list. */
2521 s = splnet();
2522 nap->next = mip6_naq;
2523 mip6_naq = nap;
2524 splx(s);
2525
2526 #if MIP6_DEBUG
2527 mip6_debug("\nCreated Neighbor Advertisement List entry (0x%x)\n",
2528 nap);
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");
2537 else
2538 mip6_debug("Incl Target ll_addr : FALSE\n");
2539 #endif
2540
2541 /* Send the Neighbor Advertisment entry to speed up cache changes. */
2542 mip6_send_na(nap);
2543
2544 if (start_timer) {
2545 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2546 mip6_timer_na_handle =
2547 #endif
2548 timeout(mip6_timer_na, (void *)0, hz);
2549 }
2550 return nap;
2551 }
2552
2553
2554
2555 /*
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 ******************************************************************************
2561 */
2562 struct mip6_na *
2563 mip6_na_delete(nap_del)
2564 struct mip6_na *nap_del; /* Pointer to NA entry to delete */
2565 {
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 */
2569 int s;
2570
2571 s = splnet();
2572 nap_prev = NULL;
2573 nap_next = NULL;
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;
2579 else
2580 nap_prev->next = nap->next;
2581
2582 #if MIP6_DEBUG
2583 mip6_debug("\nNeighbor Advertisement Entry "
2584 "deleted (0x%x)\n", nap);
2585 #endif
2586 _FREE(nap, M_TEMP);
2587
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);
2594 #else
2595 untimeout(mip6_timer_na, (void *)NULL);
2596 #endif
2597 }
2598 break;
2599 }
2600 nap_prev = nap;
2601 }
2602 splx(s);
2603 return nap_next;
2604 }
2605
2606
2607
2608 /*
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 ******************************************************************************
2614 */
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 */
2619 {
2620 struct mip6_prefix *pq;
2621
2622 for (pq = mip6_pq; pq; pq = pq->next) {
2623 if (in6_are_prefix_equal(&pq->prefix, prefix, prefix_len))
2624 return pq;
2625 }
2626 return NULL;
2627 }
2628
2629
2630
2631 /*
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 ******************************************************************************
2638 */
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 */
2645 {
2646 struct mip6_prefix *pq;
2647 int s, start_timer = 0;
2648
2649 if (mip6_pq == NULL)
2650 start_timer = 1;
2651
2652 pq = (struct mip6_prefix *)MALLOC mip6_prefix),
2653 M_TEMP, M_WAITOK);
2654 if (pq == NULL)
2655 return NULL;
2656 bzero(pq, sizeof(struct mip6_prefix));
2657
2658 s = splnet();
2659 pq->next = mip6_pq;
2660 pq->ifp = ifp;
2661 pq->prefix = *prefix;
2662 pq->prefix_len = prefix_len;
2663 pq->valid_time = valid_time;
2664 mip6_pq = pq;
2665 splx(s);
2666
2667 #if MIP6_DEBUG
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));
2673 #endif
2674
2675 if (start_timer) {
2676 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2677 mip6_timer_prefix_handle =
2678 #endif
2679 timeout(mip6_timer_prefix, (void *)0, hz);
2680 }
2681 return pq;
2682 }
2683
2684
2685
2686 /*
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 ******************************************************************************
2692 */
2693 struct mip6_prefix *
2694 mip6_prefix_delete(pre_del)
2695 struct mip6_prefix *pre_del; /* Prefix list entry to be deleted */
2696 {
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 */
2700 int s;
2701
2702 /* Find the requested entry in the link list. */
2703 s = splnet();
2704 pre_next = NULL;
2705 pre_prev = NULL;
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;
2711 else
2712 pre_prev->next = pre->next;
2713
2714 #if MIP6_DEBUG
2715 mip6_debug("\nMIPv6 prefix entry deleted (0x%x)\n", pre);
2716 #endif
2717 _FREE(pre, M_TEMP);
2718
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);
2725 #else
2726 untimeout(mip6_timer_prefix, (void *)NULL);
2727 #endif
2728 }
2729 break;
2730 }
2731 pre_prev = pre;
2732 }
2733 splx(s);
2734 return pre_next;
2735 }
2736
2737
2738
2739 /*
2740 ##############################################################################
2741 #
2742 # TIMER FUNCTIONS
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.
2745 #
2746 ##############################################################################
2747 */
2748
2749 /*
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.
2755 * Ret value: -
2756 ******************************************************************************
2757 */
2758 void
2759 mip6_timer_na(arg)
2760 void *arg; /* Not used */
2761 {
2762 struct mip6_na *nap; /* Neighbor Advertisement entry */
2763 int s;
2764 #ifdef __APPLE__
2765 boolean_t funnel_state;
2766 funnel_state = thread_funnel_set(network_flock, TRUE);
2767 #endif
2768
2769 /* Go through the entire list of Neighbor Advertisement entries. */
2770 s = splnet();
2771 for (nap = mip6_naq; nap;) {
2772 mip6_send_na(nap);
2773 if (nap->no <= 0)
2774 nap = mip6_na_delete(nap);
2775 else
2776 nap = nap->next;
2777 }
2778 splx(s);
2779
2780 if (mip6_naq != NULL) {
2781 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2782 mip6_timer_na_handle =
2783 #endif
2784 timeout(mip6_timer_na, (void *)0, hz);
2785 }
2786 #ifdef __APPLE__
2787 (void) thread_funnel_set(network_flock, FALSE);
2788 #endif
2789 }
2790
2791
2792
2793 /*
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.
2799 * Ret value: -
2800 ******************************************************************************
2801 */
2802 void
2803 mip6_timer_bc(arg)
2804 void *arg; /* Not used */
2805 {
2806 struct mip6_bc *bcp; /* Current entry in the BC list */
2807 struct mip6_bc *bcp_nxt; /* Next BC list entry */
2808 int s;
2809 #ifdef __APPLE__
2810 boolean_t funnel_state;
2811 funnel_state = thread_funnel_set(network_flock, TRUE);
2812 #endif
2813
2814 /* Go through the entire list of Binding Cache entries. */
2815 s = splnet();
2816 for (bcp = mip6_bcq; bcp;) {
2817 bcp->lifetime -= 1;
2818 if (bcp->lifetime == 0) {
2819 mip6_bc_delete(bcp, &bcp_nxt);
2820 bcp = bcp_nxt;
2821 } else
2822 bcp = bcp->next;
2823 }
2824 splx(s);
2825
2826 /* XXX */
2827 /* Code have to be added to take care of bc_info.br_interval
2828 variable. */
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 =
2834 #endif
2835 timeout(mip6_timer_bc, (void *)0, hz);
2836 }
2837 #ifdef __APPLE__
2838 (void) thread_funnel_set(network_flock, FALSE);
2839 #endif
2840 return;
2841 }
2842
2843
2844
2845 /*
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.
2850 * Ret value: -
2851 ******************************************************************************
2852 */
2853
2854 void
2855 mip6_timer_prefix_funneled(arg)
2856 void *arg; /* Not used */
2857 {
2858 #ifdef __APPLE__
2859 boolean_t funnel_state;
2860 funnel_state = thread_funnel_set(network_flock, TRUE);
2861 #endif
2862 mip6_timer_prefix(arg);
2863 #ifdef __APPLE__
2864 (void) thread_funnel_set(network_flock, FALSE);
2865 #endif
2866 }
2867
2868 void
2869 mip6_timer_prefix(arg)
2870 void *arg; /* Not used */
2871 {
2872 struct mip6_prefix *pq_entry; /* Current entry in the prefix list */
2873 int s;
2874
2875 /* Go through the entire list of prefix entries. */
2876 s = splnet();
2877 for (pq_entry = mip6_pq; pq_entry;) {
2878 pq_entry->valid_time -= 1;
2879 if (pq_entry->valid_time == 0)
2880 pq_entry = mip6_prefix_delete(pq_entry);
2881 else
2882 pq_entry = pq_entry->next;
2883 }
2884 splx(s);
2885
2886 if (mip6_pq != NULL) {
2887 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
2888 mip6_timer_prefix_handle =
2889 #endif
2890 timeout(mip6_timer_prefix, (void *)0, hz);
2891 }
2892 return;
2893 }
2894
2895
2896
2897 /*
2898 ##############################################################################
2899 #
2900 # IOCTL AND DEBUG FUNCTIONS
2901 #
2902 ##############################################################################
2903 */
2904
2905 /*
2906 ******************************************************************************
2907 * Function: mip6_ioctl
2908 * Description: The ioctl handler for MIPv6. These are used by the
2909 * configuration program to set and get various parameters.
2910 * Ret value: 0 or error code
2911 ******************************************************************************
2912 */
2913 int
2914 #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
2915 mip6_ioctl(so, cmd, data, ifp, p)
2916 struct socket *so;
2917 u_long cmd;
2918 caddr_t data;
2919 struct ifnet *ifp;
2920 struct proc *p;
2921 #else
2922 mip6_ioctl(so, cmd, data, ifp)
2923 struct socket *so;
2924 u_long cmd;
2925 caddr_t data;
2926 struct ifnet *ifp;
2927 #endif
2928 {
2929 int res;
2930
2931 /* Note: privileges already checked in in6_control(). */
2932
2933 res = 0;
2934 switch (cmd) {
2935 case SIOCSBCFLUSH_MIP6:
2936 case SIOCSDEFCONFIG_MIP6:
2937 res = mip6_clear_config_data(cmd, data);
2938 return res;
2939
2940 case SIOCSBRUPDATE_MIP6:
2941 res = mip6_write_config_data(cmd, data);
2942 return res;
2943
2944 case SIOCSHAPREF_MIP6:
2945 /* Note: this one can be run before attach. */
2946 if (mip6_write_config_data_ha_hook)
2947 res = (*mip6_write_config_data_ha_hook)
2948 (cmd, data);
2949 break;
2950
2951 case SIOCACOADDR_MIP6:
2952 case SIOCAHOMEADDR_MIP6:
2953 case SIOCSBULIFETIME_MIP6:
2954 case SIOCSHRLIFETIME_MIP6:
2955 case SIOCDCOADDR_MIP6:
2956 /* Note: these can be run before attach. */
2957 if (mip6_write_config_data_mn_hook)
2958 res = (*mip6_write_config_data_mn_hook)
2959 (cmd, data);
2960 break;
2961
2962 case SIOCSDEBUG_MIP6:
2963 case SIOCSENABLEBR_MIP6:
2964 case SIOCSATTACH_MIP6:
2965 res = mip6_enable_func(cmd, data);
2966 return res;
2967
2968 case SIOCSFWDSLUNICAST_MIP6:
2969 case SIOCSFWDSLMULTICAST_MIP6:
2970 /* Note: these can be run before attach. */
2971 if (mip6_enable_func_ha_hook)
2972 res = (*mip6_enable_func_ha_hook)(cmd, data);
2973 break;
2974
2975 case SIOCSPROMMODE_MIP6:
2976 case SIOCSBU2CN_MIP6:
2977 case SIOCSREVTUNNEL_MIP6:
2978 case SIOCSAUTOCONFIG_MIP6:
2979 case SIOCSEAGERMD_MIP6:
2980 /* Note: these can be run before attach. */
2981 if (mip6_enable_func_mn_hook)
2982 res = (*mip6_enable_func_mn_hook)(cmd, data);
2983 break;
2984
2985 case SIOCSRELEASE_MIP6:
2986 mip6_release();
2987 return res;
2988
2989 default:
2990 res = EOPNOTSUPP;
2991 break;
2992 }
2993
2994 if (MIP6_IS_HA_ACTIVE) {
2995 res = 0;
2996 switch (cmd) {
2997 case SIOCSHALISTFLUSH_MIP6:
2998 if (mip6_clear_config_data_ha_hook)
2999 res = (*mip6_clear_config_data_ha_hook)
3000 (cmd, data);
3001 break;
3002
3003 default:
3004 res = EOPNOTSUPP;
3005 break;
3006 }
3007 }
3008
3009 if (MIP6_IS_MN_ACTIVE) {
3010 res = 0;
3011 switch (cmd) {
3012 case SIOCSFORADDRFLUSH_MIP6:
3013 case SIOCSHADDRFLUSH_MIP6:
3014 case SIOCSBULISTFLUSH_MIP6:
3015 if (mip6_clear_config_data_mn_hook)
3016 res = (*mip6_clear_config_data_mn_hook)
3017 (cmd, data);
3018 break;
3019
3020 default:
3021 res = EOPNOTSUPP;
3022 break;
3023 }
3024 }
3025 if (res) {
3026 #if MIP6_DEBUG
3027 printf("%s: unknown command: %lu\n", __FUNCTION__, (u_long)cmd);
3028 #endif
3029 }
3030 return res;
3031 }
3032
3033
3034
3035 /*
3036 ******************************************************************************
3037 * Function: mip6_debug
3038 * Description: This function displays MIPv6 debug messages to the console
3039 * if activated with the configuration program. Note that this
3040 * is included only when "options MIP6_DEBUG" is defined.
3041 * Ret value: -
3042 ******************************************************************************
3043 */
3044 #if MIP6_DEBUG
3045 void mip6_debug(char *fmt, ...)
3046 {
3047 #ifndef __bsdi__
3048 va_list ap;
3049
3050 if (!mip6_debug_is_enabled)
3051 return;
3052
3053 va_start(ap, fmt);
3054 vprintf(fmt, ap);
3055 va_end(ap);
3056 #endif
3057 }
3058
3059
3060
3061 void
3062 mip6_enable_debug(int status)
3063 {
3064 mip6_debug_is_enabled = status;
3065 }
3066 #endif /* MIP6_DEBUG */
3067
3068
3069
3070 /*
3071 ******************************************************************************
3072 * Function: mip6_write_config_data
3073 * Description: This function is called to write certain config values for
3074 * MIPv6. The data is written into the global config structure.
3075 * Ret value: -
3076 ******************************************************************************
3077 */
3078 int mip6_write_config_data(u_long cmd, caddr_t data)
3079 {
3080 int retval = 0;
3081
3082 switch (cmd) {
3083 case SIOCSBRUPDATE_MIP6:
3084 mip6_config.br_update = *(u_int8_t *)data;
3085 break;
3086 }
3087 return retval;
3088 }
3089
3090
3091
3092 /*
3093 ******************************************************************************
3094 * Function: mip6_clear_config_data
3095 * Description: This function is called to clear internal lists handled by
3096 * MIPv6.
3097 * Ret value: -
3098 ******************************************************************************
3099 */
3100 int mip6_clear_config_data(u_long cmd, caddr_t data)
3101 {
3102 int s, retval = 0;
3103 struct mip6_bc *bcp, *bcp_nxt;
3104
3105 s = splnet();
3106 switch (cmd) {
3107 case SIOCSBCFLUSH_MIP6:
3108 for (bcp = mip6_bcq; bcp;) {
3109 if(!bcp->hr_flag) {
3110 mip6_bc_delete(bcp, &bcp_nxt);
3111 bcp = bcp_nxt;
3112 } else
3113 bcp = bcp->next;
3114 }
3115 break;
3116
3117 case SIOCSDEFCONFIG_MIP6:
3118 mip6_config.bu_lifetime = 600;
3119 mip6_config.br_update = 60;
3120 mip6_config.hr_lifetime = 3600;
3121 mip6_config.enable_outq = 1;
3122 break;
3123 }
3124 splx(s);
3125 return retval;
3126 }
3127
3128
3129
3130 /*
3131 ******************************************************************************
3132 * Function: mip6_enable_func
3133 * Description: This function is called to enable or disable certain functions
3134 * in mip6. The data is written into the global config struct.
3135 * Ret value: -
3136 ******************************************************************************
3137 */
3138 int mip6_enable_func(u_long cmd, caddr_t data)
3139 {
3140 int enable;
3141 int retval = 0;
3142
3143 enable = ((struct mip6_input_data *)data)->value;
3144
3145 switch (cmd) {
3146 case SIOCSDEBUG_MIP6:
3147 #if MIP6_DEBUG
3148 mip6_enable_debug(enable);
3149 #else
3150 printf("No Mobile IPv6 debug information available!\n");
3151 #endif
3152 break;
3153
3154 case SIOCSENABLEBR_MIP6:
3155 mip6_config.enable_br = enable;
3156 break;
3157
3158 case SIOCSATTACH_MIP6:
3159 printf("%s: attach %d\n", __FUNCTION__, enable); /* RM */
3160 retval = mip6_attach(enable);
3161 break;
3162 }
3163 return retval;
3164 }