]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - net/ipv6/mip6.c
[IPSEC]: Set skb->data to payload in x->mode->output
[linux-2.6-omap-h63xx.git] / net / ipv6 / mip6.c
1 /*
2  * Copyright (C)2003-2006 Helsinki University of Technology
3  * Copyright (C)2003-2006 USAGI/WIDE Project
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 /*
20  * Authors:
21  *      Noriaki TAKAMIYA @USAGI
22  *      Masahide NAKAMURA @USAGI
23  */
24
25 #include <linux/module.h>
26 #include <linux/skbuff.h>
27 #include <linux/time.h>
28 #include <linux/ipv6.h>
29 #include <linux/icmpv6.h>
30 #include <net/sock.h>
31 #include <net/ipv6.h>
32 #include <net/ip6_checksum.h>
33 #include <net/rawv6.h>
34 #include <net/xfrm.h>
35 #include <net/mip6.h>
36
37 static xfrm_address_t *mip6_xfrm_addr(struct xfrm_state *x, xfrm_address_t *addr)
38 {
39         return x->coaddr;
40 }
41
42 static inline unsigned int calc_padlen(unsigned int len, unsigned int n)
43 {
44         return (n - len + 16) & 0x7;
45 }
46
47 static inline void *mip6_padn(__u8 *data, __u8 padlen)
48 {
49         if (!data)
50                 return NULL;
51         if (padlen == 1) {
52                 data[0] = MIP6_OPT_PAD_1;
53         } else if (padlen > 1) {
54                 data[0] = MIP6_OPT_PAD_N;
55                 data[1] = padlen - 2;
56                 if (padlen > 2)
57                         memset(data+2, 0, data[1]);
58         }
59         return data + padlen;
60 }
61
62 static inline void mip6_param_prob(struct sk_buff *skb, int code, int pos)
63 {
64         icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev);
65 }
66
67 static int mip6_mh_len(int type)
68 {
69         int len = 0;
70
71         switch (type) {
72         case IP6_MH_TYPE_BRR:
73                 len = 0;
74                 break;
75         case IP6_MH_TYPE_HOTI:
76         case IP6_MH_TYPE_COTI:
77         case IP6_MH_TYPE_BU:
78         case IP6_MH_TYPE_BACK:
79                 len = 1;
80                 break;
81         case IP6_MH_TYPE_HOT:
82         case IP6_MH_TYPE_COT:
83         case IP6_MH_TYPE_BERROR:
84                 len = 2;
85                 break;
86         }
87         return len;
88 }
89
90 static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
91 {
92         struct ip6_mh *mh;
93
94         if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) ||
95             !pskb_may_pull(skb, (skb_transport_offset(skb) +
96                                  ((skb_transport_header(skb)[1] + 1) << 3))))
97                 return -1;
98
99         mh = (struct ip6_mh *)skb_transport_header(skb);
100
101         if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {
102                 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",
103                                mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type));
104                 mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) -
105                                          skb_network_header(skb)));
106                 return -1;
107         }
108
109         if (mh->ip6mh_proto != IPPROTO_NONE) {
110                 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
111                                mh->ip6mh_proto);
112                 mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) -
113                                          skb_network_header(skb)));
114                 return -1;
115         }
116
117         return 0;
118 }
119
120 struct mip6_report_rate_limiter {
121         spinlock_t lock;
122         struct timeval stamp;
123         int iif;
124         struct in6_addr src;
125         struct in6_addr dst;
126 };
127
128 static struct mip6_report_rate_limiter mip6_report_rl = {
129         .lock = __SPIN_LOCK_UNLOCKED(mip6_report_rl.lock)
130 };
131
132 static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb)
133 {
134         struct ipv6hdr *iph = ipv6_hdr(skb);
135         struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data;
136
137         if (!ipv6_addr_equal(&iph->saddr, (struct in6_addr *)x->coaddr) &&
138             !ipv6_addr_any((struct in6_addr *)x->coaddr))
139                 return -ENOENT;
140
141         return destopt->nexthdr;
142 }
143
144 /* Destination Option Header is inserted.
145  * IP Header's src address is replaced with Home Address Option in
146  * Destination Option Header.
147  */
148 static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb)
149 {
150         struct ipv6hdr *iph;
151         struct ipv6_destopt_hdr *dstopt;
152         struct ipv6_destopt_hao *hao;
153         u8 nexthdr;
154         int len;
155
156         skb_push(skb, -skb_network_offset(skb));
157         iph = ipv6_hdr(skb);
158         iph->payload_len = htons(skb->len - sizeof(*iph));
159
160         nexthdr = *skb_mac_header(skb);
161         *skb_mac_header(skb) = IPPROTO_DSTOPTS;
162
163         dstopt = (struct ipv6_destopt_hdr *)skb_transport_header(skb);
164         dstopt->nexthdr = nexthdr;
165
166         hao = mip6_padn((char *)(dstopt + 1),
167                         calc_padlen(sizeof(*dstopt), 6));
168
169         hao->type = IPV6_TLV_HAO;
170         hao->length = sizeof(*hao) - 2;
171         BUG_TRAP(hao->length == 16);
172
173         len = ((char *)hao - (char *)dstopt) + sizeof(*hao);
174
175         memcpy(&hao->addr, &iph->saddr, sizeof(hao->addr));
176         spin_lock_bh(&x->lock);
177         memcpy(&iph->saddr, x->coaddr, sizeof(iph->saddr));
178         spin_unlock_bh(&x->lock);
179
180         BUG_TRAP(len == x->props.header_len);
181         dstopt->hdrlen = (x->props.header_len >> 3) - 1;
182
183         return 0;
184 }
185
186 static inline int mip6_report_rl_allow(struct timeval *stamp,
187                                        struct in6_addr *dst,
188                                        struct in6_addr *src, int iif)
189 {
190         int allow = 0;
191
192         spin_lock_bh(&mip6_report_rl.lock);
193         if (mip6_report_rl.stamp.tv_sec != stamp->tv_sec ||
194             mip6_report_rl.stamp.tv_usec != stamp->tv_usec ||
195             mip6_report_rl.iif != iif ||
196             !ipv6_addr_equal(&mip6_report_rl.src, src) ||
197             !ipv6_addr_equal(&mip6_report_rl.dst, dst)) {
198                 mip6_report_rl.stamp.tv_sec = stamp->tv_sec;
199                 mip6_report_rl.stamp.tv_usec = stamp->tv_usec;
200                 mip6_report_rl.iif = iif;
201                 ipv6_addr_copy(&mip6_report_rl.src, src);
202                 ipv6_addr_copy(&mip6_report_rl.dst, dst);
203                 allow = 1;
204         }
205         spin_unlock_bh(&mip6_report_rl.lock);
206         return allow;
207 }
208
209 static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct flowi *fl)
210 {
211         struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
212         struct ipv6_destopt_hao *hao = NULL;
213         struct xfrm_selector sel;
214         int offset;
215         struct timeval stamp;
216         int err = 0;
217
218         if (unlikely(fl->proto == IPPROTO_MH &&
219                      fl->fl_mh_type <= IP6_MH_TYPE_MAX))
220                 goto out;
221
222         if (likely(opt->dsthao)) {
223                 offset = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO);
224                 if (likely(offset >= 0))
225                         hao = (struct ipv6_destopt_hao *)
226                                         (skb_network_header(skb) + offset);
227         }
228
229         skb_get_timestamp(skb, &stamp);
230
231         if (!mip6_report_rl_allow(&stamp, &ipv6_hdr(skb)->daddr,
232                                   hao ? &hao->addr : &ipv6_hdr(skb)->saddr,
233                                   opt->iif))
234                 goto out;
235
236         memset(&sel, 0, sizeof(sel));
237         memcpy(&sel.daddr, (xfrm_address_t *)&ipv6_hdr(skb)->daddr,
238                sizeof(sel.daddr));
239         sel.prefixlen_d = 128;
240         memcpy(&sel.saddr, (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
241                sizeof(sel.saddr));
242         sel.prefixlen_s = 128;
243         sel.family = AF_INET6;
244         sel.proto = fl->proto;
245         sel.dport = xfrm_flowi_dport(fl);
246         if (sel.dport)
247                 sel.dport_mask = htons(~0);
248         sel.sport = xfrm_flowi_sport(fl);
249         if (sel.sport)
250                 sel.sport_mask = htons(~0);
251         sel.ifindex = fl->oif;
252
253         err = km_report(IPPROTO_DSTOPTS, &sel,
254                         (hao ? (xfrm_address_t *)&hao->addr : NULL));
255
256  out:
257         return err;
258 }
259
260 static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
261                                u8 **nexthdr)
262 {
263         u16 offset = sizeof(struct ipv6hdr);
264         struct ipv6_opt_hdr *exthdr =
265                                    (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
266         const unsigned char *nh = skb_network_header(skb);
267         unsigned int packet_len = skb->tail - skb->network_header;
268         int found_rhdr = 0;
269
270         *nexthdr = &ipv6_hdr(skb)->nexthdr;
271
272         while (offset + 1 <= packet_len) {
273
274                 switch (**nexthdr) {
275                 case NEXTHDR_HOP:
276                         break;
277                 case NEXTHDR_ROUTING:
278                         found_rhdr = 1;
279                         break;
280                 case NEXTHDR_DEST:
281                         /*
282                          * HAO MUST NOT appear more than once.
283                          * XXX: It is better to try to find by the end of
284                          * XXX: packet if HAO exists.
285                          */
286                         if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) {
287                                 LIMIT_NETDEBUG(KERN_WARNING "mip6: hao exists already, override\n");
288                                 return offset;
289                         }
290
291                         if (found_rhdr)
292                                 return offset;
293
294                         break;
295                 default:
296                         return offset;
297                 }
298
299                 offset += ipv6_optlen(exthdr);
300                 *nexthdr = &exthdr->nexthdr;
301                 exthdr = (struct ipv6_opt_hdr *)(nh + offset);
302         }
303
304         return offset;
305 }
306
307 static int mip6_destopt_init_state(struct xfrm_state *x)
308 {
309         if (x->id.spi) {
310                 printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
311                        x->id.spi);
312                 return -EINVAL;
313         }
314         if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
315                 printk(KERN_INFO "%s: state's mode is not %u: %u\n",
316                        __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
317                 return -EINVAL;
318         }
319
320         x->props.header_len = sizeof(struct ipv6_destopt_hdr) +
321                 calc_padlen(sizeof(struct ipv6_destopt_hdr), 6) +
322                 sizeof(struct ipv6_destopt_hao);
323         BUG_TRAP(x->props.header_len == 24);
324
325         return 0;
326 }
327
328 /*
329  * Do nothing about destroying since it has no specific operation for
330  * destination options header unlike IPsec protocols.
331  */
332 static void mip6_destopt_destroy(struct xfrm_state *x)
333 {
334 }
335
336 static struct xfrm_type mip6_destopt_type =
337 {
338         .description    = "MIP6DESTOPT",
339         .owner          = THIS_MODULE,
340         .proto          = IPPROTO_DSTOPTS,
341         .flags          = XFRM_TYPE_NON_FRAGMENT,
342         .init_state     = mip6_destopt_init_state,
343         .destructor     = mip6_destopt_destroy,
344         .input          = mip6_destopt_input,
345         .output         = mip6_destopt_output,
346         .reject         = mip6_destopt_reject,
347         .hdr_offset     = mip6_destopt_offset,
348         .local_addr     = mip6_xfrm_addr,
349 };
350
351 static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb)
352 {
353         struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data;
354
355         if (!ipv6_addr_equal(&rt2->addr, (struct in6_addr *)x->coaddr) &&
356             !ipv6_addr_any((struct in6_addr *)x->coaddr))
357                 return -ENOENT;
358
359         return rt2->rt_hdr.nexthdr;
360 }
361
362 /* Routing Header type 2 is inserted.
363  * IP Header's dst address is replaced with Routing Header's Home Address.
364  */
365 static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb)
366 {
367         struct ipv6hdr *iph;
368         struct rt2_hdr *rt2;
369         u8 nexthdr;
370
371         skb_push(skb, -skb_network_offset(skb));
372         iph = ipv6_hdr(skb);
373         iph->payload_len = htons(skb->len - sizeof(*iph));
374
375         nexthdr = *skb_mac_header(skb);
376         *skb_mac_header(skb) = IPPROTO_ROUTING;
377
378         rt2 = (struct rt2_hdr *)skb_transport_header(skb);
379         rt2->rt_hdr.nexthdr = nexthdr;
380         rt2->rt_hdr.hdrlen = (x->props.header_len >> 3) - 1;
381         rt2->rt_hdr.type = IPV6_SRCRT_TYPE_2;
382         rt2->rt_hdr.segments_left = 1;
383         memset(&rt2->reserved, 0, sizeof(rt2->reserved));
384
385         BUG_TRAP(rt2->rt_hdr.hdrlen == 2);
386
387         memcpy(&rt2->addr, &iph->daddr, sizeof(rt2->addr));
388         spin_lock_bh(&x->lock);
389         memcpy(&iph->daddr, x->coaddr, sizeof(iph->daddr));
390         spin_unlock_bh(&x->lock);
391
392         return 0;
393 }
394
395 static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
396                              u8 **nexthdr)
397 {
398         u16 offset = sizeof(struct ipv6hdr);
399         struct ipv6_opt_hdr *exthdr =
400                                    (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
401         const unsigned char *nh = skb_network_header(skb);
402         unsigned int packet_len = skb->tail - skb->network_header;
403         int found_rhdr = 0;
404
405         *nexthdr = &ipv6_hdr(skb)->nexthdr;
406
407         while (offset + 1 <= packet_len) {
408
409                 switch (**nexthdr) {
410                 case NEXTHDR_HOP:
411                         break;
412                 case NEXTHDR_ROUTING:
413                         if (offset + 3 <= packet_len) {
414                                 struct ipv6_rt_hdr *rt;
415                                 rt = (struct ipv6_rt_hdr *)(nh + offset);
416                                 if (rt->type != 0)
417                                         return offset;
418                         }
419                         found_rhdr = 1;
420                         break;
421                 case NEXTHDR_DEST:
422                         if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
423                                 return offset;
424
425                         if (found_rhdr)
426                                 return offset;
427
428                         break;
429                 default:
430                         return offset;
431                 }
432
433                 offset += ipv6_optlen(exthdr);
434                 *nexthdr = &exthdr->nexthdr;
435                 exthdr = (struct ipv6_opt_hdr *)(nh + offset);
436         }
437
438         return offset;
439 }
440
441 static int mip6_rthdr_init_state(struct xfrm_state *x)
442 {
443         if (x->id.spi) {
444                 printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
445                        x->id.spi);
446                 return -EINVAL;
447         }
448         if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
449                 printk(KERN_INFO "%s: state's mode is not %u: %u\n",
450                        __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
451                 return -EINVAL;
452         }
453
454         x->props.header_len = sizeof(struct rt2_hdr);
455
456         return 0;
457 }
458
459 /*
460  * Do nothing about destroying since it has no specific operation for routing
461  * header type 2 unlike IPsec protocols.
462  */
463 static void mip6_rthdr_destroy(struct xfrm_state *x)
464 {
465 }
466
467 static struct xfrm_type mip6_rthdr_type =
468 {
469         .description    = "MIP6RT",
470         .owner          = THIS_MODULE,
471         .proto          = IPPROTO_ROUTING,
472         .flags          = XFRM_TYPE_NON_FRAGMENT,
473         .init_state     = mip6_rthdr_init_state,
474         .destructor     = mip6_rthdr_destroy,
475         .input          = mip6_rthdr_input,
476         .output         = mip6_rthdr_output,
477         .hdr_offset     = mip6_rthdr_offset,
478         .remote_addr    = mip6_xfrm_addr,
479 };
480
481 static int __init mip6_init(void)
482 {
483         printk(KERN_INFO "Mobile IPv6\n");
484
485         if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) {
486                 printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __FUNCTION__);
487                 goto mip6_destopt_xfrm_fail;
488         }
489         if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) {
490                 printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
491                 goto mip6_rthdr_xfrm_fail;
492         }
493         if (rawv6_mh_filter_register(mip6_mh_filter) < 0) {
494                 printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__);
495                 goto mip6_rawv6_mh_fail;
496         }
497
498
499         return 0;
500
501  mip6_rawv6_mh_fail:
502         xfrm_unregister_type(&mip6_rthdr_type, AF_INET6);
503  mip6_rthdr_xfrm_fail:
504         xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
505  mip6_destopt_xfrm_fail:
506         return -EAGAIN;
507 }
508
509 static void __exit mip6_fini(void)
510 {
511         if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0)
512                 printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__);
513         if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
514                 printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
515         if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
516                 printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
517 }
518
519 module_init(mip6_init);
520 module_exit(mip6_fini);
521
522 MODULE_LICENSE("GPL");
523 MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_DSTOPTS);
524 MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ROUTING);