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