2 * Mobile IPv6 Mobility Header Common Functions
5 * Antti Tuominen <ajtuomin@tml.hut.fi>
7 * $Id: s.mh_recv.c 1.159 02/10/16 15:01:29+03:00 antti@traci.mipl.mediapoli.com $
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
16 #include <linux/autoconf.h>
17 #include <linux/types.h>
18 #include <linux/in6.h>
19 #include <linux/skbuff.h>
20 #include <linux/ipsec.h>
21 #include <linux/init.h>
23 #include <net/ip6_route.h>
24 #include <net/ip6_checksum.h>
25 #include <net/addrconf.h>
26 #include <net/mipv6.h>
27 #include <net/checksum.h>
28 #include <net/protocol.h>
29 #include <linux/module.h>
35 #include "rr_crypto.h"
39 #define MIPV6_MH_MAX MIPV6_MH_BE
41 int (*func) (struct in6_addr *, struct in6_addr *,
42 struct in6_addr *, struct in6_addr *,
46 static struct mh_proto mh_rcv[MIPV6_MH_MAX];
48 int mipv6_mh_register(int type, int (*func)(
49 struct in6_addr *, struct in6_addr *,
50 struct in6_addr *, struct in6_addr *, struct mipv6_mh *))
52 if (mh_rcv[type].func != NULL)
55 mh_rcv[type].func = func;
60 void mipv6_mh_unregister(int type)
62 if (type < 0 || type > MIPV6_MH_MAX)
65 mh_rcv[type].func = NULL;
68 struct socket *mipv6_mh_socket = NULL;
71 /* TODO: Fix fragmentation */
72 static int dstopts_getfrag(
73 const void *data, struct in6_addr *addr,
74 char *buff, unsigned int offset, unsigned int len)
76 memcpy(buff, data + offset, len);
80 static int dstopts_getfrag(
81 void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
86 struct mipv6_mh_opt *alloc_mh_opts(int totlen)
88 struct mipv6_mh_opt *ops;
90 ops = kmalloc(sizeof(*ops) + totlen, GFP_ATOMIC);
94 memset(ops, 0, sizeof(*ops));
95 ops->next_free = ops->data;
96 ops->freelen = totlen;
101 int append_mh_opt(struct mipv6_mh_opt *ops, u8 type, u8 len, void *data)
105 if (ops->next_free == NULL) {
106 DEBUG(DBG_ERROR, "No free room for option");
109 if (ops->freelen < len + 2) {
110 DEBUG(DBG_ERROR, "No free room for option");
114 ops->freelen -= (len + 2);
115 ops->totlen += (len + 2);
118 mo = (struct mipv6_mo *)ops->next_free;
123 case MIPV6_OPT_ALTERNATE_COA:
124 ops->alt_coa = (struct mipv6_mo_alt_coa *)mo;
125 ipv6_addr_copy(&ops->alt_coa->addr, (struct in6_addr *)data);
127 case MIPV6_OPT_NONCE_INDICES:
128 DEBUG(DBG_INFO, "Added nonce indices pointer");
129 ops->nonce_indices = (struct mipv6_mo_nonce_indices *)mo;
130 ops->nonce_indices->home_nonce_i = *(__u16 *)data;
131 ops->nonce_indices->careof_nonce_i = *((__u16 *)data + 1);
133 case MIPV6_OPT_AUTH_DATA:
134 DEBUG(DBG_INFO, "Added opt auth_data pointer");
135 ops->auth_data = (struct mipv6_mo_bauth_data *)mo;
137 case MIPV6_OPT_BIND_REFRESH_ADVICE:
138 ops->br_advice = (struct mipv6_mo_br_advice *)mo;
139 ops->br_advice->refresh_interval = htons(*(u16 *)data);
142 DEBUG(DBG_ERROR, "Unknow option type");
146 if (ops->freelen == 0)
147 ops->next_free = NULL;
149 ops->next_free += (len + 2);
155 * Calculates required padding with xn + y requirement with offset
157 static inline int optpad(int xn, int y, int offset)
159 return ((y - offset) & (xn - 1));
162 static int option_pad(int type, int offset)
164 if (type == MIPV6_OPT_ALTERNATE_COA)
165 return optpad(8, 6, offset); /* 8n + 6 */
166 if (type == MIPV6_OPT_BIND_REFRESH_ADVICE ||
167 type == MIPV6_OPT_NONCE_INDICES)
168 return optpad(2, 0, offset); /* 2n */
173 * Add Pad1 or PadN option to data
175 int mipv6_add_pad(u8 *data, int n)
177 struct mipv6_mo_padn *padn;
179 if (n <= 0) return 0;
181 *data = MIPV6_OPT_PAD1;
184 padn = (struct mipv6_mo_padn *)data;
185 padn->type = MIPV6_OPT_PADN;
186 padn->length = n - 2;
187 memset(padn->data, 0, n - 2);
192 * Write options to mobility header buffer
194 static int prepare_mh_opts(u8 *optdata, int off, struct mipv6_mh_opt *ops)
196 u8 *nextopt = optdata;
197 int offset = off, pad = 0;
205 pad = option_pad(MIPV6_OPT_ALTERNATE_COA, offset);
206 nextopt += mipv6_add_pad(nextopt, pad);
207 memcpy(nextopt, ops->alt_coa, sizeof(struct mipv6_mo_alt_coa));
208 nextopt += sizeof(struct mipv6_mo_alt_coa);
209 offset += pad + sizeof(struct mipv6_mo_alt_coa);
212 if (ops->br_advice) {
213 pad = option_pad(MIPV6_OPT_BIND_REFRESH_ADVICE, offset);
214 nextopt += mipv6_add_pad(nextopt, pad);
215 memcpy(nextopt, ops->br_advice, sizeof(struct mipv6_mo_br_advice));
216 nextopt += sizeof(struct mipv6_mo_br_advice);
217 offset += pad + sizeof(struct mipv6_mo_br_advice);
220 if (ops->nonce_indices) {
221 pad = option_pad(MIPV6_OPT_NONCE_INDICES, offset);
222 nextopt += mipv6_add_pad(nextopt, pad);
223 memcpy(nextopt, ops->nonce_indices, sizeof(struct mipv6_mo_nonce_indices));
224 nextopt += sizeof(struct mipv6_mo_nonce_indices);
225 offset += pad + sizeof(struct mipv6_mo_nonce_indices);
228 if (ops->auth_data) {
229 /* This option should always be the last. Header
230 * length must be a multiple of 8 octects, so we pad
232 pad = optpad(8, 0, offset + ops->auth_data->length + 2);
233 nextopt += mipv6_add_pad(nextopt, pad);
234 memcpy(nextopt, ops->auth_data, ops->auth_data->length + 2);
235 nextopt += ops->auth_data->length + 2;
242 static int calculate_mh_opts(struct mipv6_mh_opt *ops, int mh_len)
250 offset += sizeof(struct mipv6_mo_alt_coa)
251 + option_pad(MIPV6_OPT_ALTERNATE_COA, offset);
254 offset += sizeof(struct mipv6_mo_br_advice)
255 + option_pad(MIPV6_OPT_BIND_REFRESH_ADVICE, offset);
257 if (ops->nonce_indices)
258 offset += sizeof(struct mipv6_mo_nonce_indices)
259 + option_pad(MIPV6_OPT_NONCE_INDICES, offset);
261 if (ops->auth_data) /* no alignment */
262 offset += ops->auth_data->length + 2;
264 return offset - mh_len;
267 extern int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag,
268 const void *data, struct flowi *fl, unsigned length,
269 struct ipv6_txoptions *opt, int hlimit, int flags);
273 * Mobility Header Message send functions
278 * send_mh - builds and sends a MH msg
280 * @daddr: destination address for packet
281 * @saddr: source address for packet
282 * @msg_type: type of MH
283 * @msg_len: message length
284 * @msg: MH type specific data
285 * @hao_addr: home address for home address option
286 * @rth_addr: routing header address
287 * @ops: mobility options
290 * Builds MH, appends the type specific msg data to the header and
291 * sends the packet with a home address option, if a home address was
292 * given. Returns 0, if everything succeeded and a negative error code
295 int send_mh(struct in6_addr *daddr,
296 struct in6_addr *saddr,
297 u8 msg_type, u8 msg_len, u8 *msg,
298 struct in6_addr *hao_addr,
299 struct in6_addr *rth_addr,
300 struct mipv6_mh_opt *ops,
301 struct mipv6_auth_parm *parm)
305 struct sock *sk = mipv6_mh_socket->sk;
306 struct ipv6_txoptions *txopt = NULL;
307 int tot_len = sizeof(struct mipv6_mh) + msg_len;
308 int padded_len = 0, txopt_len = 0;
311 /* Add length of options */
312 tot_len += calculate_mh_opts(ops, tot_len);
313 /* Needs to be a multiple of 8 octets */
314 padded_len = tot_len + optpad(8, 0, tot_len);
316 mh = sock_kmalloc(sk, padded_len, GFP_ATOMIC);
318 DEBUG(DBG_ERROR, "memory allocation failed");
322 memset(&fl, 0, sizeof(fl));
323 fl.proto = IPPROTO_MOBILITY;
324 ipv6_addr_copy(&fl.fl6_dst, daddr);
325 ipv6_addr_copy(&fl.fl6_src, saddr);
326 fl.fl6_flowlabel = 0;
327 fl.oif = sk->sk_bound_dev_if;
329 if (hao_addr || rth_addr) {
333 txopt_len += sizeof(struct mipv6_dstopt_homeaddr) + 6;
335 txopt_len += sizeof(struct rt2_hdr);
337 txopt_len += sizeof(*txopt);
338 txopt = sock_kmalloc(sk, txopt_len, GFP_ATOMIC);
340 DEBUG(DBG_ERROR, "No socket space left");
341 sock_kfree_s(sk, mh, padded_len);
344 memset(txopt, 0, txopt_len);
345 txopt->tot_len = txopt_len;
346 opt_ptr = (__u8 *) (txopt + 1);
348 int holen = sizeof(struct mipv6_dstopt_homeaddr) + 6;
349 txopt->dst1opt = (struct ipv6_opt_hdr *) opt_ptr;
350 txopt->opt_flen += holen;
352 mipv6_append_dst1opts(txopt->dst1opt, saddr,
354 txopt->mipv6_flags = MIPV6_SND_HAO;
357 int rtlen = sizeof(struct rt2_hdr);
358 txopt->srcrt2 = (struct ipv6_rt_hdr *) opt_ptr;
359 txopt->opt_nflen += rtlen;
361 mipv6_append_rt2hdr(txopt->srcrt2, rth_addr);
365 /* Fill in the fields of MH */
366 mh->payload = NEXTHDR_NONE;
367 mh->length = (padded_len >> 3) - 1; /* Units of 8 octets - 1 */
372 memcpy(mh->data, msg, msg_len);
373 prepare_mh_opts(mh->data + msg_len, msg_len + sizeof(*mh), ops);
374 /* If BAD is present, this is already done. */
375 mipv6_add_pad((u8 *)mh + tot_len, padded_len - tot_len);
377 if (parm && parm->k_bu && ops && ops->auth_data) {
378 /* Calculate the position of the authorization data before adding checksum*/
379 mipv6_auth_build(parm->cn_addr, parm->coa, (__u8 *)mh,
380 (__u8 *)mh + padded_len - MIPV6_RR_MAC_LENGTH, parm->k_bu);
382 /* Calculate the MH checksum */
383 mh->checksum = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
384 padded_len, IPPROTO_MOBILITY,
385 csum_partial((char *)mh, padded_len, 0));
387 ip6_build_xmit(sk, dstopts_getfrag, mh, &fl, padded_len, txopt, 255,
389 /* dst cache must be cleared so RR messages can be routed through
390 different interfaces */
394 sock_kfree_s(sk, txopt, txopt_len);
395 sock_kfree_s(sk, mh, padded_len);
400 * mipv6_send_brr - send a Binding Refresh Request
401 * @saddr: source address for BRR
402 * @daddr: destination address for BRR
403 * @ops: mobility options
405 * Sends a binding request. On a mobile node, use the mobile node's
406 * home address for @saddr. Returns 0 on success, negative on
409 int mipv6_send_brr(struct in6_addr *saddr, struct in6_addr *daddr,
410 struct mipv6_mh_opt *ops)
412 struct mipv6_mh_brr br;
414 memset(&br, 0, sizeof(br));
415 /* We don't need to explicitly add a RH to brr, since it will be
416 * included automatically, if a BCE exists
418 MIPV6_INC_STATS(n_brr_sent);
419 return send_mh(daddr, saddr, MIPV6_MH_BRR, sizeof(br), (u8 *)&br,
420 NULL, NULL, ops, NULL);
424 * mipv6_send_ba - send a Binding Acknowledgement
425 * @saddr: source address for BA
426 * @daddr: destination address for BA
427 * @coaddr: care-of address of MN
428 * @status: status field value
429 * @sequence: sequence number from BU
430 * @lifetime: granted lifetime for binding in seconds
431 * @ops: mobility options
433 * Send a binding acknowledgement. On a mobile node, use the mobile
434 * node's home address for saddr. Returns 0 on success, non-zero on
437 int mipv6_send_ba(struct in6_addr *saddr, struct in6_addr *daddr,
438 struct in6_addr *coaddr, u8 status, u16 sequence,
439 u32 lifetime, u8 *k_bu)
441 struct mipv6_mh_ba ba;
442 struct mipv6_auth_parm parm;
443 struct mipv6_mh_opt *ops = NULL;
444 int ops_len = 0, ret = 0;
446 memset(&ba, 0, sizeof(ba));
449 ba.sequence = htons(sequence);
450 ba.lifetime = htons(lifetime >> 2);
452 DEBUG(DBG_INFO, "sending a status %d BA %s authenticator to MN \n"
453 "%x:%x:%x:%x:%x:%x:%x:%x at care of address \n"
454 "%x:%x:%x:%x:%x:%x:%x:%x : with lifetime %d and \n"
455 " sequence number %d",
456 status, k_bu ? "with" : "without",
457 NIPV6ADDR(daddr), NIPV6ADDR(coaddr), lifetime, sequence);
459 memset(&parm, 0, sizeof(parm));
461 parm.cn_addr = saddr;
464 ops_len += sizeof(struct mipv6_mo_bauth_data) +
469 if (mip6node_cnf.binding_refresh_advice) {
470 ops_len += sizeof(struct mipv6_mo_br_advice);
473 ops = alloc_mh_opts(ops_len);
475 DEBUG(DBG_WARNING, "Out of memory");
478 if (mip6node_cnf.binding_refresh_advice > 0) {
479 if (append_mh_opt(ops, MIPV6_OPT_BIND_REFRESH_ADVICE, 2,
480 &mip6node_cnf.binding_refresh_advice) < 0) {
481 DEBUG(DBG_WARNING, "Adding BRA failed");
488 if (append_mh_opt(ops, MIPV6_OPT_AUTH_DATA,
489 MIPV6_RR_MAC_LENGTH, NULL) < 0) {
490 DEBUG(DBG_WARNING, "Adding BAD failed");
498 if (!ipv6_addr_cmp(coaddr, daddr))
499 ret = send_mh(daddr, saddr, MIPV6_MH_BA, sizeof(ba), (u8 *)&ba,
500 NULL, NULL, ops, &parm);
502 ret = send_mh(daddr, saddr, MIPV6_MH_BA, sizeof(ba), (u8 *)&ba,
503 NULL, coaddr, ops, &parm);
507 MIPV6_INC_STATS(n_ba_sent);
509 MIPV6_INC_STATS(n_ban_sent);
520 * mipv6_send_be - send a Binding Error message
521 * @saddr: source address for BE
522 * @daddr: destination address for BE
523 * @home: Home Address in offending packet (if any)
525 * Sends a binding error. On a mobile node, use the mobile node's
526 * home address for @saddr. Returns 0 on success, negative on
529 int mipv6_send_be(struct in6_addr *saddr, struct in6_addr *daddr,
530 struct in6_addr *home, __u8 status)
532 struct mipv6_mh_be be;
535 memset(&be, 0, sizeof(be));
538 ipv6_addr_copy(&be.home_addr, home);
540 ret = send_mh(daddr, saddr, MIPV6_MH_BE, sizeof(be), (u8 *)&be,
541 NULL, NULL, NULL, NULL);
543 MIPV6_INC_STATS(n_be_sent);
549 * mipv6_send_addr_test - send a HoT or CoT message
550 * @saddr: source address
551 * @daddr: destination address
552 * @msg_type: HoT or CoT message
553 * @init: HoTI or CoTI message
555 * Send a reply to HoTI or CoTI message.
557 static int mipv6_send_addr_test(struct in6_addr *saddr,
558 struct in6_addr *daddr,
560 struct mipv6_mh_addr_ti *init)
562 u_int8_t *kgen_token = NULL;
563 struct mipv6_mh_addr_test addr_test;
564 struct mipv6_rr_nonce *nonce;
565 struct mipv6_mh_opt *ops = NULL;
570 if ((nonce = mipv6_rr_get_new_nonce())== NULL) {
571 DEBUG(DBG_WARNING, "Nonce creation failed");
574 if (mipv6_rr_cookie_create(daddr, &kgen_token, nonce->index)) {
575 DEBUG(DBG_WARNING, "No cookie");
579 addr_test.nonce_index = nonce->index;
580 memcpy(addr_test.init_cookie, init->init_cookie,
581 MIPV6_RR_COOKIE_LENGTH);
582 memcpy(addr_test.kgen_token, kgen_token,
583 MIPV6_RR_COOKIE_LENGTH);
585 /* No options defined */
586 ret = send_mh(daddr, saddr, msg_type, sizeof(addr_test),
587 (u8 *)&addr_test, NULL, NULL, ops, NULL);
590 if (msg_type == MIPV6_MH_HOT) {
591 MIPV6_INC_STATS(n_hot_sent);
593 MIPV6_INC_STATS(n_cot_sent);
600 static void bc_cache_add(int ifindex, struct in6_addr *saddr,
601 struct in6_addr *daddr, struct in6_addr *haddr,
602 struct in6_addr *coa, __u32 lifetime, __u16 sequence,
603 __u8 flags, __u8 *k_bu)
605 __u8 ba_status = SUCCESS;
607 if (lifetime > MAX_RR_BINDING_LIFE)
608 lifetime = MAX_RR_BINDING_LIFE;
610 if (mipv6_bcache_add(ifindex, daddr, haddr, coa, lifetime,
611 sequence, flags, CACHE_ENTRY) != 0) {
612 DEBUG(DBG_ERROR, "binding failed.");
613 ba_status = INSUFFICIENT_RESOURCES;
616 if (flags & MIPV6_BU_F_ACK) {
617 DEBUG(DBG_INFO, "sending ack (code=%d)", ba_status);
618 mipv6_send_ba(daddr, haddr, coa, ba_status, sequence,
623 static void bc_cn_home_add(
624 int ifindex, struct in6_addr *saddr, struct in6_addr *daddr,
625 struct in6_addr *haddr, struct in6_addr *coa, __u32 lifetime,
626 __u16 sequence, __u8 flags, __u8 *k_bu)
629 mipv6_send_ba(daddr, haddr, coa, HOME_REGISTRATION_NOT_SUPPORTED,
630 sequence, lifetime, k_bu);
634 static void bc_cache_delete(struct in6_addr *daddr, struct in6_addr *haddr,
635 struct in6_addr *coa, __u16 sequence, __u8 flags,
638 __u8 status = SUCCESS;
640 /* Cached Care-of Address Deregistration */
641 if (mipv6_bcache_exists(haddr, daddr) == CACHE_ENTRY) {
642 mipv6_bcache_delete(haddr, daddr, CACHE_ENTRY);
644 DEBUG(DBG_INFO, "entry is not in cache");
645 status = REASON_UNSPECIFIED;
647 if (flags & MIPV6_BU_F_ACK) {
648 mipv6_send_ba(daddr, haddr, coa, status, sequence,
653 static void bc_cn_home_delete(struct in6_addr *daddr, struct in6_addr *haddr,
654 struct in6_addr *coa, __u16 sequence, __u8 flags,
658 mipv6_send_ba(daddr, haddr, coa, HOME_REGISTRATION_NOT_SUPPORTED,
664 * parse_mo_tlv - Parse TLV-encoded Mobility Options
665 * @mos: pointer to Mobility Options
666 * @len: total length of options
667 * @opts: structure to store option pointers
669 * Parses Mobility Options passed in @mos. Stores pointers in @opts
670 * to all valid mobility options found in @mos. Unknown options and
671 * padding (%MIPV6_OPT_PAD1 and %MIPV6_OPT_PADN) is ignored and
674 int parse_mo_tlv(void *mos, int len, struct mobopt *opts)
676 struct mipv6_mo *curr = (struct mipv6_mo *)mos;
681 if (curr->type == MIPV6_OPT_PAD1)
684 optlen = 2 + curr->length;
689 switch (curr->type) {
691 DEBUG(DBG_DATADUMP, "MIPV6_OPT_PAD1 at %x", curr);
694 DEBUG(DBG_DATADUMP, "MIPV6_OPT_PADN at %x", curr);
696 case MIPV6_OPT_ALTERNATE_COA:
697 DEBUG(DBG_DATADUMP, "MIPV6_OPT_ACOA at %x", curr);
698 opts->alt_coa = (struct mipv6_mo_alt_coa *)curr;
700 case MIPV6_OPT_NONCE_INDICES:
701 DEBUG(DBG_DATADUMP, "MIPV6_OPT_NONCE_INDICES at %x", curr);
702 opts->nonce_indices =
703 (struct mipv6_mo_nonce_indices *)curr;
705 case MIPV6_OPT_AUTH_DATA:
706 DEBUG(DBG_DATADUMP, "MIPV6_OPT_AUTH_DATA at %x", curr);
707 opts->auth_data = (struct mipv6_mo_bauth_data *)curr;
709 case MIPV6_OPT_BIND_REFRESH_ADVICE:
710 DEBUG(DBG_DATADUMP, "MIPV6_OPT_BIND_REFRESH_ADVICE at %x", curr);
711 opts->br_advice = (struct mipv6_mo_br_advice *)curr;
714 DEBUG(DBG_INFO, "MO Unknown option type %d at %x, ignoring.",
716 /* unknown mobility option, ignore and skip */
719 (u8 *)curr += optlen;
731 * Mobility Header Message handlers
735 static int mipv6_handle_mh_testinit(struct in6_addr *cn,
736 struct in6_addr *unused,
737 struct in6_addr *saddr,
738 struct in6_addr *hao,
741 struct mipv6_mh_addr_ti *ti = (struct mipv6_mh_addr_ti *)mh->data;
744 if (!mip6node_cnf.accept_ret_rout) {
745 DEBUG(DBG_INFO, "Return routability administratively disabled");
748 if (mh->length < 1) {
749 DEBUG(DBG_INFO, "Mobility Header length less than H/C TestInit");
754 DEBUG(DBG_INFO, "H/C TestInit has HAO, dropped.");
758 if (mh->type == MIPV6_MH_HOTI) {
759 MIPV6_INC_STATS(n_hoti_rcvd);
760 return mipv6_send_addr_test(cn, saddr, MIPV6_MH_HOT, ti);
761 } else if (mh->type == MIPV6_MH_COTI) {
762 MIPV6_INC_STATS(n_coti_rcvd);
763 return mipv6_send_addr_test(cn, saddr, MIPV6_MH_COT, ti);
765 return -1; /* Impossible to get here */
769 * mipv6_handle_mh_bu - Binding Update handler
770 * @src: care-of address of sender
772 * @haddr: home address of sender
773 * @mh: pointer to the beginning of the Mobility Header
775 * Handles Binding Update. Packet and offset to option are passed.
776 * Returns 0 on success, otherwise negative.
778 static int mipv6_handle_mh_bu(struct in6_addr *dst,
779 struct in6_addr *unused,
780 struct in6_addr *haddr,
781 struct in6_addr *coaddr,
784 struct mipv6_mh_bu *bu = (struct mipv6_mh_bu *)mh->data;
785 int msg_len = (mh->length << 3) + 2;
787 int dereg; /* Is this deregistration? */
789 struct mipv6_bce bc_entry;
790 struct in6_addr *coa;
791 __u8 *key_bu = NULL; /* RR BU authentication key */
792 __u8 flags = bu->flags;
796 if (msg_len < (sizeof(*bu))) {
797 DEBUG(DBG_INFO, "Mobility Header length less than BU");
798 MIPV6_INC_STATS(n_bu_drop.invalid);
802 /* If HAO not present, CoA == HAddr */
808 sequence = ntohs(bu->sequence);
809 if (bu->lifetime == 0xffff)
810 lifetime = 0xffffffff;
812 lifetime = ntohs(bu->lifetime) << 2;
814 dereg = (ipv6_addr_cmp(haddr, coa) == 0 || lifetime == 0);
816 if (msg_len > sizeof(*bu)) {
818 memset(&opts, 0, sizeof(opts));
819 if (parse_mo_tlv(bu + 1, msg_len - sizeof(*bu), &opts) < 0) {
820 MIPV6_INC_STATS(n_bu_drop.invalid);
824 * MIPV6_OPT_AUTH_DATA, MIPV6_OPT_NONCE_INDICES,
828 coa = &opts.alt_coa->addr;
829 dereg = (ipv6_addr_cmp(haddr, coa) == 0 || lifetime == 0);
831 if (!(flags & MIPV6_BU_F_HOME)) {
833 u8 *h_ckie = NULL, *c_ckie = NULL; /* Home and care-of cookies */
835 /* BUs to CN MUST include authorization data and nonce indices options */
836 if (!opts.auth_data || !opts.nonce_indices) {
838 "Route optimization BU without authorization material, aborting processing");
839 return MH_AUTH_FAILED;
841 if (mipv6_rr_cookie_create(
842 haddr, &h_ckie, opts.nonce_indices->home_nonce_i) < 0) {
844 "mipv6_rr_cookie_create failed for home cookie");
845 ba_status = EXPIRED_HOME_NONCE_INDEX;
847 /* Don't create the care-of cookie, if MN deregisters */
848 if (!dereg && mipv6_rr_cookie_create(
850 opts.nonce_indices->careof_nonce_i) < 0) {
852 "mipv6_rr_cookie_create failed for coa cookie");
854 ba_status = EXPIRED_CAREOF_NONCE_INDEX;
856 ba_status = EXPIRED_NONCES;
858 if (ba_status == 0) {
860 key_bu = mipv6_rr_key_calc(h_ckie, NULL);
862 key_bu = mipv6_rr_key_calc(h_ckie, c_ckie);
863 mh->checksum = 0;/* TODO: Don't mangle the packet */
864 if (key_bu && mipv6_auth_check(
865 dst, coa, (__u8 *)mh, msg_len + sizeof(*mh), opts.auth_data, key_bu) == 0) {
866 DEBUG(DBG_INFO, "mipv6_auth_check OK for BU");
870 "BU Authentication failed");
877 if (ba_status != 0) {
878 MIPV6_INC_STATS(n_bu_drop.auth);
879 mipv6_send_ba(dst, haddr, coa, ba_status,
886 /* Require authorization option for RO, home reg is protected by IPsec */
887 if (!(flags & MIPV6_BU_F_HOME) && !auth) {
888 MIPV6_INC_STATS(n_bu_drop.auth);
891 return MH_AUTH_FAILED;
895 if (mipv6_bcache_get(haddr, dst, &bc_entry) == 0) {
896 /* Avoid looping binding cache entries */
897 if (!ipv6_addr_cmp(&bc_entry.coa, haddr) && !ipv6_addr_cmp(&bc_entry.home_addr, coa)) {
898 DEBUG(DBG_WARNING, "Looped BU, dropping the packet");
901 if ((bc_entry.flags & MIPV6_BU_F_HOME) != (flags & MIPV6_BU_F_HOME)) {
903 "Registration type change. Sending BA REG_TYPE_CHANGE_FORBIDDEN");
904 mipv6_send_ba(dst, haddr, coa, REG_TYPE_CHANGE_FORBIDDEN,
905 sequence, lifetime, key_bu);
908 if (!MIPV6_SEQ_GT(sequence, bc_entry.seq)) {
910 "Sequence number mismatch. Sending BA SEQUENCE_NUMBER_OUT_OF_WINDOW");
911 mipv6_send_ba(dst, haddr, coa, SEQUENCE_NUMBER_OUT_OF_WINDOW,
912 bc_entry.seq, lifetime, key_bu);
921 DEBUG(DBG_INFO, "calling bu_add.");
922 if ((rt = rt6_lookup(haddr, dst, 0, 0)) != NULL) {
923 ifindex = rt->rt6i_dev->ifindex;
924 dst_release(&rt->u.dst);
927 * Can't process the BU since the right interface is
930 DEBUG(DBG_WARNING, "No route entry found for handling "
931 "a BU request, (using 0 as index)");
934 if (flags & MIPV6_BU_F_HOME)
935 mip6_fn.bce_home_add(ifindex, haddr, dst, haddr,
936 coa, lifetime, sequence, flags,
939 mip6_fn.bce_cache_add(ifindex, haddr, dst, haddr,
940 coa, lifetime, sequence, flags,
943 DEBUG(DBG_INFO, "calling BCE delete.");
945 if (flags & MIPV6_BU_F_HOME)
946 mip6_fn.bce_home_del(dst, haddr, coa, sequence,
949 mip6_fn.bce_cache_del(dst, haddr, coa, sequence,
953 MIPV6_INC_STATS(n_bu_rcvd);
959 int mipv6_mh_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
961 struct sk_buff *skb = *skbp;
962 struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
964 struct in6_addr *lhome, *fhome, *lcoa = NULL, *fcoa = NULL;
965 int len = ((skb->h.raw[1] + 1)<<3);
968 fhome = &skb->nh.ipv6h->saddr;
969 lhome = &skb->nh.ipv6h->daddr;
972 fcoa = (struct in6_addr *)((u8 *)skb->nh.raw + opt->hao);
975 if (opt->srcrt2 != 0) {
977 rt2 = (struct rt2_hdr *)((u8 *)skb->nh.raw + opt->srcrt2);
981 /* Verify checksum is correct */
982 if (skb->ip_summed == CHECKSUM_HW) {
983 skb->ip_summed = CHECKSUM_UNNECESSARY;
984 if (csum_ipv6_magic(fhome, lhome, skb->len, IPPROTO_MOBILITY,
987 printk(KERN_WARNING "MIPv6 MH hw checksum failed\n");
988 skb->ip_summed = CHECKSUM_NONE;
991 if (skb->ip_summed == CHECKSUM_NONE) {
992 if (csum_ipv6_magic(fhome, lhome, skb->len, IPPROTO_MOBILITY,
993 skb_checksum(skb, 0, skb->len, 0))) {
994 printk(KERN_WARNING "MIPv6 MH checksum failed\n");
999 if (!pskb_may_pull(skb, (skb->h.raw-skb->data) + sizeof(*mh)) ||
1000 !pskb_may_pull(skb, (skb->h.raw-skb->data) + len)) {
1001 DEBUG(DBG_INFO, "MIPv6 MH invalid length");
1006 mh = (struct mipv6_mh *) skb->h.raw;
1008 /* Verify there are no more headers after the MH */
1009 if (mh->payload != NEXTHDR_NONE) {
1010 DEBUG(DBG_INFO, "MIPv6 MH error");
1014 if (mh->type > MIPV6_MH_MAX) {
1015 /* send binding error */
1016 printk("Invalid mobility header type (%d)\n", mh->type);
1017 mipv6_send_be(lhome, fcoa ? fcoa : fhome, fcoa ? fhome : NULL,
1018 MIPV6_BE_UNKNOWN_MH_TYPE);
1021 if (mh_rcv[mh->type].func != NULL) {
1022 ret = mh_rcv[mh->type].func(lhome, lcoa, fhome, fcoa, mh);
1024 DEBUG(DBG_INFO, "No handler for MH Type %d", mh->type);
1028 ASSERT(len == (mh->length + 1) << 3);
1030 skb->h.raw += (mh->length + 1) << 3;
1031 *nhoffp = (u8*)mh - skb->nh.raw;
1035 MIPV6_INC_STATS(n_mh_in_error);
1041 #if LINUX_VERSION_CODE >= 0
1043 struct inet6_protocol mipv6_mh_protocol =
1045 mipv6_mh_rcv, /* handler */
1046 NULL, /* error control */
1047 IPPROTO_MOBILITY, /* protocol ID */
1050 struct inet6_protocol mipv6_mh_protocol =
1052 mipv6_mh_rcv, /* handler */
1053 NULL, /* error control */
1054 IPPROTO_MOBILITY, /* protocol ID */
1060 * Code module init/exit functions
1064 int __init mipv6_mh_common_init(void)
1069 mip6_fn.bce_home_add = bc_cn_home_add;
1070 mip6_fn.bce_cache_add = bc_cache_add;
1071 mip6_fn.bce_home_del = bc_cn_home_delete;
1072 mip6_fn.bce_cache_del = bc_cache_delete;
1074 mipv6_mh_socket = sock_alloc();
1075 if (mipv6_mh_socket == NULL) {
1077 "Failed to create the MIP6 MH control socket.\n");
1080 mipv6_mh_socket->type = SOCK_RAW;
1082 if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_MOBILITY,
1083 &mipv6_mh_socket)) < 0) {
1085 "Failed to initialize the MIP6 MH control socket (err %d).\n",
1087 sock_release(mipv6_mh_socket);
1088 mipv6_mh_socket = NULL; /* for safety */
1092 sk = mipv6_mh_socket->sk;
1093 sk->sk_allocation = GFP_ATOMIC;
1094 sk->sk_sndbuf = 65536;
1095 sk->sk_prot->unhash(sk);
1097 memset(&mh_rcv, 0, sizeof(mh_rcv));
1098 mh_rcv[MIPV6_MH_HOTI].func = mipv6_handle_mh_testinit;
1099 mh_rcv[MIPV6_MH_COTI].func = mipv6_handle_mh_testinit;
1100 mh_rcv[MIPV6_MH_BU].func = mipv6_handle_mh_bu;
1102 #if LINUX_VERSION_CODE >= 0
1103 if (inet6_add_protocol(&mipv6_mh_protocol, IPPROTO_MOBILITY) < 0) {
1104 printk(KERN_ERR "Failed to register MOBILITY protocol\n");
1105 sock_release(mipv6_mh_socket);
1106 mipv6_mh_socket = NULL;
1110 inet6_add_protocol(&mipv6_mh_protocol);
1112 /* To disable the use of dst_cache,
1113 * which slows down the sending of BUs ??
1115 sk->sk_dst_cache=NULL;
1120 void __exit mipv6_mh_common_exit(void)
1122 if (mipv6_mh_socket) sock_release(mipv6_mh_socket);
1123 mipv6_mh_socket = NULL; /* For safety. */
1125 #if LINUX_VERSION_CODE >= 0
1126 inet6_del_protocol(&mipv6_mh_protocol, IPPROTO_MOBILITY);
1128 inet6_del_protocol(&mipv6_mh_protocol);
1130 memset(&mh_rcv, 0, sizeof(mh_rcv));
1133 EXPORT_SYMBOL(send_mh);
1134 EXPORT_SYMBOL(parse_mo_tlv);
1135 EXPORT_SYMBOL(mipv6_send_ba);
1136 EXPORT_SYMBOL(mipv6_mh_register);
1137 EXPORT_SYMBOL(mipv6_mh_unregister);
1138 EXPORT_SYMBOL(alloc_mh_opts);
1139 EXPORT_SYMBOL(append_mh_opt);