421c4604f386259afa97b2ce078185f215ca33af
[linux-flexiantxendom0-3.2.10.git] / net / ipv6 / mobile_ip6 / mobhdr_common.c
1 /*
2  *      Mobile IPv6 Mobility Header Common Functions
3  *
4  *      Authors:
5  *      Antti Tuominen <ajtuomin@tml.hut.fi>
6  *
7  *      $Id: s.mh_recv.c 1.159 02/10/16 15:01:29+03:00 antti@traci.mipl.mediapoli.com $
8  *
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.
13  *
14  */
15
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>
22 #include <net/ipv6.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>
30
31 #include "stats.h"
32 #include "debug.h"
33 #include "mobhdr.h"
34 #include "bcache.h"
35 #include "rr_crypto.h"
36 #include "exthdrs.h"
37 #include "config.h"
38
39 #define MIPV6_MH_MAX MIPV6_MH_BE
40 struct mh_proto {
41         int     (*func) (struct in6_addr *, struct in6_addr *, 
42                          struct in6_addr *, struct in6_addr *, 
43                          struct mipv6_mh *);
44 };
45
46 static struct mh_proto mh_rcv[MIPV6_MH_MAX];
47
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 *))
51 {
52         if (mh_rcv[type].func != NULL)
53                 return -1;
54
55         mh_rcv[type].func = func;
56
57         return 0;
58 }
59
60 void mipv6_mh_unregister(int type)
61 {
62         if (type < 0 || type > MIPV6_MH_MAX)
63                 return;
64
65         mh_rcv[type].func = NULL;
66 }
67
68 struct socket *mipv6_mh_socket = NULL;
69
70 #if 1
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)
75 {
76         memcpy(buff, data + offset, len);
77         return 0;
78 }
79 #else
80 static int dstopts_getfrag(
81         void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
82 {
83 }
84 #endif
85
86 struct mipv6_mh_opt *alloc_mh_opts(int totlen)
87 {
88         struct mipv6_mh_opt *ops;
89
90         ops = kmalloc(sizeof(*ops) + totlen, GFP_ATOMIC);
91         if (ops == NULL)
92                 return NULL;
93
94         memset(ops, 0, sizeof(*ops));
95         ops->next_free = ops->data;
96         ops->freelen = totlen;
97
98         return ops;
99 }
100
101 int append_mh_opt(struct mipv6_mh_opt *ops, u8 type, u8 len, void *data)
102 {
103         struct mipv6_mo *mo;
104
105         if (ops->next_free == NULL) {
106                 DEBUG(DBG_ERROR, "No free room for option");
107                 return -ENOMEM;
108         }
109         if (ops->freelen < len + 2) {
110                 DEBUG(DBG_ERROR, "No free room for option");
111                 return -ENOMEM;
112         }
113         else {
114                 ops->freelen -= (len + 2);
115                 ops->totlen += (len + 2);
116         }
117
118         mo = (struct mipv6_mo *)ops->next_free;
119         mo->type = type;
120         mo->length = len;
121
122         switch (type) {
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);
126                 break;
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);
132                 break;
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;
136                 break;
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);
140                 break;
141         default:
142                 DEBUG(DBG_ERROR, "Unknow option type");
143                 break;
144         }
145
146         if (ops->freelen == 0)
147                 ops->next_free = NULL;
148         else
149                 ops->next_free += (len + 2);
150
151         return 0;
152 }
153
154 /*
155  * Calculates required padding with xn + y requirement with offset
156  */
157 static inline int optpad(int xn, int y, int offset)
158 {
159         return ((y - offset) & (xn - 1));
160 }
161
162 static int option_pad(int type, int offset)
163 {
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 */
169         return 0;
170 }
171
172 /*
173  * Add Pad1 or PadN option to data
174  */
175 int mipv6_add_pad(u8 *data, int n)
176 {
177         struct mipv6_mo_padn *padn;
178
179         if (n <= 0) return 0;
180         if (n == 1) {
181                 *data = MIPV6_OPT_PAD1;
182                 return 1;
183         }
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);
188         return n;
189 }
190
191 /*
192  * Write options to mobility header buffer
193  */
194 static int prepare_mh_opts(u8 *optdata, int off, struct mipv6_mh_opt *ops)
195 {
196         u8 *nextopt = optdata;
197         int offset = off, pad = 0;
198
199         if (ops == NULL) {
200                 nextopt = NULL;
201                 return -1;
202         }
203
204         if (ops->alt_coa) {
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);
210         }
211
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);
218         }
219
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);
226         }
227
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
231                  * if necessary. */
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;
236         }
237         nextopt = NULL;
238
239         return 0;
240 }
241
242 static int calculate_mh_opts(struct mipv6_mh_opt *ops, int mh_len)
243 {
244         int offset = mh_len;
245
246         if (ops == NULL)
247                 return 0;
248
249         if (ops->alt_coa)
250                 offset += sizeof(struct mipv6_mo_alt_coa)
251                         + option_pad(MIPV6_OPT_ALTERNATE_COA, offset);
252
253         if (ops->br_advice)
254                 offset += sizeof(struct mipv6_mo_br_advice)
255                         + option_pad(MIPV6_OPT_BIND_REFRESH_ADVICE, offset);
256
257         if (ops->nonce_indices)
258                 offset += sizeof(struct mipv6_mo_nonce_indices)
259                         + option_pad(MIPV6_OPT_NONCE_INDICES, offset);
260
261         if (ops->auth_data) /* no alignment */
262                 offset += ops->auth_data->length + 2;
263
264         return offset - mh_len;
265 }
266
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);
270
271 /*
272  *
273  * Mobility Header Message send functions
274  *
275  */
276
277 /**
278  * send_mh - builds and sends a MH msg
279  *
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
288  * @parm: auth data
289  *
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
293  * otherwise.
294  **/
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)
302 {
303         struct flowi fl;
304         struct mipv6_mh *mh; 
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;
309
310         DEBUG_FUNC();
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);
315
316         mh = sock_kmalloc(sk, padded_len, GFP_ATOMIC);
317         if (!mh) {
318                 DEBUG(DBG_ERROR, "memory allocation failed");
319                 return -ENOMEM;
320         }
321
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;
328
329         if (hao_addr || rth_addr) {
330                 __u8 *opt_ptr;
331
332                 if (hao_addr)
333                         txopt_len += sizeof(struct mipv6_dstopt_homeaddr) + 6;
334                 if (rth_addr)
335                         txopt_len += sizeof(struct rt2_hdr);
336
337                 txopt_len += sizeof(*txopt);
338                 txopt = sock_kmalloc(sk, txopt_len, GFP_ATOMIC);
339                 if (txopt == NULL) {
340                         DEBUG(DBG_ERROR, "No socket space left");
341                         sock_kfree_s(sk, mh, padded_len);
342                         return -ENOMEM;
343                 }
344                 memset(txopt, 0, txopt_len);
345                 txopt->tot_len = txopt_len;
346                 opt_ptr = (__u8 *) (txopt + 1);
347                 if (hao_addr) {
348                         int holen = sizeof(struct mipv6_dstopt_homeaddr) + 6;
349                         txopt->dst1opt = (struct ipv6_opt_hdr *) opt_ptr;
350                         txopt->opt_flen += holen;
351                         opt_ptr += holen;
352                         mipv6_append_dst1opts(txopt->dst1opt, saddr, 
353                                               NULL, holen);
354                         txopt->mipv6_flags = MIPV6_SND_HAO;
355                 }
356                 if (rth_addr) {
357                         int rtlen = sizeof(struct rt2_hdr);
358                         txopt->srcrt2 = (struct ipv6_rt_hdr *) opt_ptr;
359                         txopt->opt_nflen += rtlen;
360                         opt_ptr += rtlen;
361                         mipv6_append_rt2hdr(txopt->srcrt2, rth_addr);
362                 }
363         }
364
365         /* Fill in the fields of MH */
366         mh->payload = NEXTHDR_NONE;
367         mh->length = (padded_len >> 3) - 1;     /* Units of 8 octets - 1 */
368         mh->type = msg_type;
369         mh->reserved = 0;
370         mh->checksum = 0;
371
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);
376         
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);
381         }
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));
386
387         ip6_build_xmit(sk, dstopts_getfrag, mh, &fl, padded_len, txopt, 255,
388                         MSG_DONTWAIT);
389         /* dst cache must be cleared so RR messages can be routed through
390            different interfaces */
391         sk_dst_reset(sk);
392
393         if (txopt_len)
394                 sock_kfree_s(sk, txopt, txopt_len);
395         sock_kfree_s(sk, mh, padded_len);
396         return 0;
397 }
398
399 /**
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
404  *
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
407  * failure.
408  **/
409 int mipv6_send_brr(struct in6_addr *saddr, struct in6_addr *daddr,
410                    struct mipv6_mh_opt *ops)
411 {
412         struct mipv6_mh_brr br;
413
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 
417          */
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);
421 }
422
423 /**
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
432  *
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
435  * failure.
436  **/
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)
440 {
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;
445
446         memset(&ba, 0, sizeof(ba));
447         
448         ba.status = status;
449         ba.sequence = htons(sequence);
450         ba.lifetime = htons(lifetime >> 2);
451         
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);
458
459         memset(&parm, 0, sizeof(parm));
460         parm.coa = coaddr;
461         parm.cn_addr = saddr;
462
463         if (k_bu) {
464                 ops_len += sizeof(struct mipv6_mo_bauth_data) + 
465                         MIPV6_RR_MAC_LENGTH;
466                 parm.k_bu = k_bu;
467         }
468
469         if (mip6node_cnf.binding_refresh_advice) {
470                 ops_len += sizeof(struct mipv6_mo_br_advice);
471         }
472         if (ops_len) {
473                 ops = alloc_mh_opts(ops_len);
474                 if (ops == NULL) {
475                         DEBUG(DBG_WARNING, "Out of memory");
476                         return -ENOMEM;
477                 }
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");
482                                 if (ops)
483                                         kfree(ops);
484                                 return -ENOMEM;
485                         }
486                 }
487                 if (k_bu) {
488                         if (append_mh_opt(ops, MIPV6_OPT_AUTH_DATA,
489                                           MIPV6_RR_MAC_LENGTH, NULL) < 0) {
490                                 DEBUG(DBG_WARNING, "Adding BAD failed");
491                                 if (ops)
492                                         kfree(ops);
493                                 return -ENOMEM;
494                         }
495                 }
496         }
497
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);
501         else
502                 ret = send_mh(daddr, saddr, MIPV6_MH_BA, sizeof(ba), (u8 *)&ba,
503                               NULL, coaddr, ops, &parm);
504
505         if (ret == 0) {
506                 if (status < 128) {
507                         MIPV6_INC_STATS(n_ba_sent);
508                 } else {
509                         MIPV6_INC_STATS(n_ban_sent);
510                 }
511         }
512
513         if (ops)
514                 kfree(ops);
515
516         return 0;
517 }
518
519 /**
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)
524  *
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
527  * failure.
528  **/
529 int mipv6_send_be(struct in6_addr *saddr, struct in6_addr *daddr, 
530                   struct in6_addr *home, __u8 status)
531 {
532         struct mipv6_mh_be be;
533         int ret = 0;
534
535         memset(&be, 0, sizeof(be));
536         be.status = status;
537         if (home)
538                 ipv6_addr_copy(&be.home_addr, home);
539
540         ret = send_mh(daddr, saddr, MIPV6_MH_BE, sizeof(be), (u8 *)&be,
541                       NULL, NULL, NULL, NULL);
542         if (ret == 0)
543                 MIPV6_INC_STATS(n_be_sent);
544
545         return ret;
546 }
547
548 /**
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
554  *
555  * Send a reply to HoTI or CoTI message. 
556  **/
557 static int mipv6_send_addr_test(struct in6_addr *saddr,
558                                 struct in6_addr *daddr,
559                                 int msg_type,
560                                 struct mipv6_mh_addr_ti *init)
561 {
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;
566         int ret = 0;
567
568         DEBUG_FUNC();
569
570         if ((nonce = mipv6_rr_get_new_nonce())== NULL) {
571                 DEBUG(DBG_WARNING, "Nonce creation failed");
572                 return 0;
573         } 
574         if (mipv6_rr_cookie_create(daddr, &kgen_token, nonce->index)) {
575                 DEBUG(DBG_WARNING, "No cookie");
576                 return 0;
577         }
578
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);
584
585         /* No options defined */
586         ret = send_mh(daddr, saddr, msg_type, sizeof(addr_test),
587                       (u8 *)&addr_test, NULL, NULL, ops, NULL);
588
589         if (ret == 0) {
590                 if (msg_type == MIPV6_MH_HOT) {
591                         MIPV6_INC_STATS(n_hot_sent);
592                 } else {
593                         MIPV6_INC_STATS(n_cot_sent);
594                 }
595         }
596
597         return 0;
598 }
599
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)
604 {
605         __u8 ba_status = SUCCESS;
606
607         if (lifetime >  MAX_RR_BINDING_LIFE)
608                 lifetime = MAX_RR_BINDING_LIFE;
609
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;
614         } 
615
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,
619                               lifetime, k_bu);
620         }
621 }
622
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)
627 {
628 #if 0
629         mipv6_send_ba(daddr, haddr, coa, HOME_REGISTRATION_NOT_SUPPORTED,
630                       sequence, lifetime, k_bu);
631 #endif
632 }
633
634 static void bc_cache_delete(struct in6_addr *daddr, struct in6_addr *haddr, 
635                             struct in6_addr *coa, __u16 sequence, __u8 flags,
636                             __u8 *k_bu)
637 {
638         __u8 status = SUCCESS;
639
640         /* Cached Care-of Address Deregistration */
641         if (mipv6_bcache_exists(haddr, daddr) == CACHE_ENTRY) {
642                 mipv6_bcache_delete(haddr, daddr, CACHE_ENTRY);
643         } else {
644                 DEBUG(DBG_INFO, "entry is not in cache");
645                 status = REASON_UNSPECIFIED;
646         }
647         if (flags & MIPV6_BU_F_ACK) {
648                 mipv6_send_ba(daddr, haddr, coa, status, sequence, 
649                               0, k_bu);
650         }
651 }
652
653 static void bc_cn_home_delete(struct in6_addr *daddr, struct in6_addr *haddr, 
654                               struct in6_addr *coa, __u16 sequence, __u8 flags,
655                               __u8 *k_bu)
656 {
657 #if 0
658         mipv6_send_ba(daddr, haddr, coa, HOME_REGISTRATION_NOT_SUPPORTED, 
659                       sequence, 0, k_bu);
660 #endif
661 }
662
663 /**
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
668  *
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
672  * skipped.
673  **/
674 int parse_mo_tlv(void *mos, int len, struct mobopt *opts)
675 {
676         struct mipv6_mo *curr = (struct mipv6_mo *)mos;
677         int left = len;
678
679         while (left > 0) {
680                 int optlen = 0;
681                 if (curr->type == MIPV6_OPT_PAD1)
682                         optlen = 1;
683                 else
684                         optlen = 2 + curr->length;
685
686                 if (optlen > left)
687                         goto bad;
688
689                 switch (curr->type) {
690                 case MIPV6_OPT_PAD1:
691                         DEBUG(DBG_DATADUMP, "MIPV6_OPT_PAD1 at %x", curr);
692                         break;
693                 case MIPV6_OPT_PADN:
694                         DEBUG(DBG_DATADUMP, "MIPV6_OPT_PADN at %x", curr);
695                         break;
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;
699                         break;
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;
704                         break;
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;
708                         break;
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;
712                         break;
713                 default:
714                         DEBUG(DBG_INFO, "MO Unknown option type %d at %x, ignoring.",
715                                curr->type, curr);
716                         /* unknown mobility option, ignore and skip */
717                 }
718
719                 (u8 *)curr += optlen;
720                 left -= optlen;
721         }
722
723         if (left == 0)
724                 return 0;
725  bad:
726         return -1;
727 }
728
729 /*
730  *
731  * Mobility Header Message handlers
732  *
733  */
734
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,
739                                     struct mipv6_mh *mh)
740 {
741         struct mipv6_mh_addr_ti *ti = (struct mipv6_mh_addr_ti *)mh->data;
742         
743         DEBUG_FUNC();
744         if (!mip6node_cnf.accept_ret_rout) {
745                 DEBUG(DBG_INFO, "Return routability administratively disabled");
746                 return -1;
747         }
748         if (mh->length < 1) {
749                 DEBUG(DBG_INFO, "Mobility Header length less than H/C TestInit");
750                 return -1;
751         }
752
753         if (hao) {
754                 DEBUG(DBG_INFO, "H/C TestInit has HAO, dropped.");
755                 return -1;
756         }
757
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);
764         } else 
765                 return -1; /* Impossible to get here */
766 }
767
768 /**
769  * mipv6_handle_mh_bu - Binding Update handler
770  * @src: care-of address of sender
771  * @dst: our address
772  * @haddr: home address of sender
773  * @mh: pointer to the beginning of the Mobility Header
774  *
775  * Handles Binding Update. Packet and offset to option are passed.
776  * Returns 0 on success, otherwise negative.
777  **/
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,
782                               struct mipv6_mh *mh)
783 {
784         struct mipv6_mh_bu *bu = (struct mipv6_mh_bu *)mh->data;
785         int msg_len = (mh->length << 3) + 2;
786         int auth = 0;
787         int dereg; /* Is this deregistration? */ 
788
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;
793         __u16 sequence;
794         __u32 lifetime;
795         
796         if (msg_len < (sizeof(*bu))) {
797                 DEBUG(DBG_INFO, "Mobility Header length less than BU");
798                 MIPV6_INC_STATS(n_bu_drop.invalid);
799                 return -1;
800         }
801
802         /* If HAO not present, CoA == HAddr */
803         if (coaddr == NULL)
804                 coa = haddr;
805         else
806                 coa = coaddr;
807
808         sequence = ntohs(bu->sequence);
809         if (bu->lifetime == 0xffff)
810                 lifetime = 0xffffffff;
811         else
812                 lifetime = ntohs(bu->lifetime) << 2;
813
814         dereg = (ipv6_addr_cmp(haddr, coa) == 0 || lifetime == 0);
815
816         if (msg_len > sizeof(*bu)) {
817                 struct mobopt opts;
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);
821                         return -1;
822                 }
823                 /*
824                  * MIPV6_OPT_AUTH_DATA, MIPV6_OPT_NONCE_INDICES, 
825                  * MIPV6_OPT_ALT_COA
826                  */
827                 if (opts.alt_coa) {
828                         coa = &opts.alt_coa->addr;
829                         dereg = (ipv6_addr_cmp(haddr, coa) == 0 || lifetime == 0);
830                 }
831                 if (!(flags & MIPV6_BU_F_HOME)) { 
832                         u8 ba_status = 0;
833                         u8 *h_ckie  = NULL, *c_ckie = NULL; /* Home and care-of cookies */
834
835                         /* BUs to CN MUST include authorization data and nonce indices options */
836                         if (!opts.auth_data || !opts.nonce_indices) {
837                                 DEBUG(DBG_WARNING,
838                                       "Route optimization BU without authorization material, aborting processing");
839                                 return MH_AUTH_FAILED;
840                         }
841                         if (mipv6_rr_cookie_create(
842                                     haddr, &h_ckie, opts.nonce_indices->home_nonce_i) < 0) {
843                                 DEBUG(DBG_WARNING,
844                                       "mipv6_rr_cookie_create failed for home cookie");
845                                 ba_status = EXPIRED_HOME_NONCE_INDEX;
846                         }
847                         /* Don't create the care-of cookie, if MN deregisters */
848                         if (!dereg && mipv6_rr_cookie_create(
849                                     coa, &c_ckie,
850                                     opts.nonce_indices->careof_nonce_i) < 0) {
851                                 DEBUG(DBG_WARNING,
852                                       "mipv6_rr_cookie_create failed for coa cookie");
853                                 if (ba_status == 0)
854                                         ba_status = EXPIRED_CAREOF_NONCE_INDEX;
855                                 else
856                                         ba_status = EXPIRED_NONCES;
857                         }
858                         if (ba_status == 0) {
859                                 if (dereg)
860                                         key_bu = mipv6_rr_key_calc(h_ckie, NULL);
861                                 else
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");
867                                         auth = 1;
868                                 } else {
869                                         DEBUG(DBG_WARNING, 
870                                               "BU Authentication failed");
871                                 }
872                         }
873                         if (h_ckie)
874                                 kfree(h_ckie);
875                         if (c_ckie)
876                                 kfree(c_ckie);
877                         if (ba_status != 0) {
878                                 MIPV6_INC_STATS(n_bu_drop.auth);
879                                 mipv6_send_ba(dst, haddr, coa, ba_status,
880                                               sequence, 0, NULL);
881                                 goto out;
882                         }
883                 }
884
885         }
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);
889                 if (key_bu)
890                         kfree(key_bu);
891                 return MH_AUTH_FAILED;
892         }
893
894
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");
899                         goto out;
900                 }
901                 if ((bc_entry.flags & MIPV6_BU_F_HOME) != (flags & MIPV6_BU_F_HOME)) {
902                         DEBUG(DBG_INFO,
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);
906                         goto out;
907                 }
908                 if (!MIPV6_SEQ_GT(sequence, bc_entry.seq)) {
909                         DEBUG(DBG_INFO,
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);
913                         goto out;
914                 }
915         }
916
917         if (!dereg) {
918                 int ifindex;
919                 struct rt6_info *rt;
920
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);
925                 } else {
926                         /*
927                          * Can't process the BU since the right interface is 
928                          * not found.
929                          */
930                         DEBUG(DBG_WARNING, "No route entry found for handling "
931                               "a BU request, (using 0 as index)");
932                         ifindex = 0;
933                 }
934                 if (flags & MIPV6_BU_F_HOME)
935                         mip6_fn.bce_home_add(ifindex, haddr, dst, haddr, 
936                                              coa, lifetime, sequence, flags, 
937                                              key_bu);
938                 else
939                         mip6_fn.bce_cache_add(ifindex, haddr, dst, haddr, 
940                                               coa, lifetime, sequence, flags, 
941                                               key_bu);
942         } else {
943                 DEBUG(DBG_INFO, "calling BCE delete.");
944
945                 if (flags & MIPV6_BU_F_HOME)
946                         mip6_fn.bce_home_del(dst, haddr, coa, sequence, 
947                                              flags, key_bu);
948                 else
949                         mip6_fn.bce_cache_del(dst, haddr, coa, sequence, 
950                                               flags, key_bu);
951         }
952  out:
953         MIPV6_INC_STATS(n_bu_rcvd);
954         if (key_bu)
955                 kfree(key_bu);
956         return 0;
957 }
958
959 int mipv6_mh_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
960 {
961         struct sk_buff *skb = *skbp;
962         struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
963         struct mipv6_mh *mh;
964         struct in6_addr *lhome, *fhome, *lcoa = NULL, *fcoa = NULL;
965         int len = ((skb->h.raw[1] + 1)<<3);
966         int ret = 0;
967
968         fhome = &skb->nh.ipv6h->saddr;
969         lhome = &skb->nh.ipv6h->daddr;
970
971         if (opt->hao != 0) {
972                 fcoa = (struct in6_addr *)((u8 *)skb->nh.raw + opt->hao);
973         }
974
975         if (opt->srcrt2 != 0) {
976                 struct rt2_hdr *rt2;
977                 rt2 = (struct rt2_hdr *)((u8 *)skb->nh.raw + opt->srcrt2);
978                 lcoa = &rt2->addr;
979         }
980
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,
985                                     skb->csum)) {
986                         if (net_ratelimit())
987                                 printk(KERN_WARNING "MIPv6 MH hw checksum failed\n");
988                         skb->ip_summed = CHECKSUM_NONE;
989                 }
990         }
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");
995                         goto bad;
996                 }
997         }
998
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");
1002                 kfree_skb(skb);
1003                 return 0;
1004         }
1005
1006         mh = (struct mipv6_mh *) skb->h.raw;
1007
1008         /* Verify there are no more headers after the MH */
1009         if (mh->payload != NEXTHDR_NONE) {
1010                 DEBUG(DBG_INFO, "MIPv6 MH error");
1011                 goto bad;
1012         }
1013
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);
1019                 goto bad;
1020         }
1021         if (mh_rcv[mh->type].func != NULL) {
1022                 ret = mh_rcv[mh->type].func(lhome, lcoa, fhome, fcoa, mh);
1023         } else {
1024                 DEBUG(DBG_INFO, "No handler for MH Type %d", mh->type);
1025                 goto bad;
1026         }
1027
1028         ASSERT(len == (mh->length + 1) << 3);
1029
1030         skb->h.raw += (mh->length + 1) << 3;
1031         *nhoffp = (u8*)mh - skb->nh.raw;
1032         return 1;
1033
1034 bad:
1035         MIPV6_INC_STATS(n_mh_in_error);
1036         kfree_skb(skb);
1037         return 0;
1038
1039 }
1040
1041 #if LINUX_VERSION_CODE >= 0
1042 //0x2052a
1043 struct inet6_protocol mipv6_mh_protocol =
1044 {
1045         mipv6_mh_rcv,           /* handler              */
1046         NULL,                   /* error control        */
1047         IPPROTO_MOBILITY,       /* protocol ID          */
1048 };
1049 #else
1050 struct inet6_protocol mipv6_mh_protocol = 
1051 {
1052         mipv6_mh_rcv,           /* handler              */
1053         NULL,                   /* error control        */
1054         IPPROTO_MOBILITY,       /* protocol ID          */
1055 };
1056 #endif
1057
1058 /*
1059  *
1060  * Code module init/exit functions
1061  *
1062  */
1063
1064 int __init mipv6_mh_common_init(void)
1065 {
1066         struct sock *sk;
1067         int err;
1068
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;
1073
1074         mipv6_mh_socket = sock_alloc();
1075         if (mipv6_mh_socket == NULL) {
1076                 printk(KERN_ERR
1077                        "Failed to create the MIP6 MH control socket.\n");
1078                 return -1;
1079         }
1080         mipv6_mh_socket->type = SOCK_RAW;
1081
1082         if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_MOBILITY, 
1083                                &mipv6_mh_socket)) < 0) {
1084                 printk(KERN_ERR
1085                        "Failed to initialize the MIP6 MH control socket (err %d).\n",
1086                        err);
1087                 sock_release(mipv6_mh_socket);
1088                 mipv6_mh_socket = NULL; /* for safety */
1089                 return err;
1090         }
1091
1092         sk = mipv6_mh_socket->sk;
1093         sk->sk_allocation = GFP_ATOMIC;
1094         sk->sk_sndbuf = 65536;
1095         sk->sk_prot->unhash(sk);
1096
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;
1101
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;
1107                 return -EAGAIN;
1108         }
1109 #else
1110         inet6_add_protocol(&mipv6_mh_protocol);
1111 #endif
1112         /* To disable the use of dst_cache, 
1113          *  which slows down the sending of BUs ??
1114          */
1115         sk->sk_dst_cache=NULL; 
1116
1117         return 0;
1118 }
1119
1120 void __exit mipv6_mh_common_exit(void)
1121 {
1122         if (mipv6_mh_socket) sock_release(mipv6_mh_socket);
1123         mipv6_mh_socket = NULL; /* For safety. */
1124
1125 #if LINUX_VERSION_CODE >= 0
1126         inet6_del_protocol(&mipv6_mh_protocol, IPPROTO_MOBILITY);
1127 #else
1128         inet6_del_protocol(&mipv6_mh_protocol);
1129 #endif
1130         memset(&mh_rcv, 0, sizeof(mh_rcv));
1131 }
1132
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);
1140