]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - net/ipv6/exthdrs.c
a7cac228f5b51ebcc1cc095a1d839a99c8a907d3
[karo-tx-linux.git] / net / ipv6 / exthdrs.c
1 /*
2  *      Extension Header handling for IPv6
3  *      Linux INET6 implementation
4  *
5  *      Authors:
6  *      Pedro Roque             <roque@di.fc.ul.pt>
7  *      Andi Kleen              <ak@muc.de>
8  *      Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
9  *
10  *      $Id: exthdrs.c,v 1.13 2001/06/19 15:58:56 davem Exp $
11  *
12  *      This program is free software; you can redistribute it and/or
13  *      modify it under the terms of the GNU General Public License
14  *      as published by the Free Software Foundation; either version
15  *      2 of the License, or (at your option) any later version.
16  */
17
18 /* Changes:
19  *      yoshfuji                : ensure not to overrun while parsing 
20  *                                tlv options.
21  *      Mitsuru KANDA @USAGI and: Remove ipv6_parse_exthdrs().
22  *      YOSHIFUJI Hideaki @USAGI  Register inbound extension header
23  *                                handlers as inet6_protocol{}.
24  */
25
26 #include <linux/errno.h>
27 #include <linux/types.h>
28 #include <linux/socket.h>
29 #include <linux/sockios.h>
30 #include <linux/sched.h>
31 #include <linux/net.h>
32 #include <linux/netdevice.h>
33 #include <linux/in6.h>
34 #include <linux/icmpv6.h>
35
36 #include <net/sock.h>
37 #include <net/snmp.h>
38
39 #include <net/ipv6.h>
40 #include <net/protocol.h>
41 #include <net/transp_v6.h>
42 #include <net/rawv6.h>
43 #include <net/ndisc.h>
44 #include <net/ip6_route.h>
45 #include <net/addrconf.h>
46
47 #include <asm/uaccess.h>
48
49 /*
50  *      Parsing tlv encoded headers.
51  *
52  *      Parsing function "func" returns 1, if parsing succeed
53  *      and 0, if it failed.
54  *      It MUST NOT touch skb->h.
55  */
56
57 struct tlvtype_proc {
58         int     type;
59         int     (*func)(struct sk_buff *skb, int offset);
60 };
61
62 /*********************
63   Generic functions
64  *********************/
65
66 /* An unknown option is detected, decide what to do */
67
68 static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
69 {
70         switch ((skb->nh.raw[optoff] & 0xC0) >> 6) {
71         case 0: /* ignore */
72                 return 1;
73
74         case 1: /* drop packet */
75                 break;
76
77         case 3: /* Send ICMP if not a multicast address and drop packet */
78                 /* Actually, it is redundant check. icmp_send
79                    will recheck in any case.
80                  */
81                 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
82                         break;
83         case 2: /* send ICMP PARM PROB regardless and drop packet */
84                 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
85                 return 0;
86         };
87
88         kfree_skb(skb);
89         return 0;
90 }
91
92 /* Parse tlv encoded option header (hop-by-hop or destination) */
93
94 static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
95 {
96         struct tlvtype_proc *curr;
97         int off = skb->h.raw - skb->nh.raw;
98         int len = ((skb->h.raw[1]+1)<<3);
99
100         if ((skb->h.raw + len) - skb->data > skb_headlen(skb))
101                 goto bad;
102
103         off += 2;
104         len -= 2;
105
106         while (len > 0) {
107                 int optlen = skb->nh.raw[off+1]+2;
108
109                 switch (skb->nh.raw[off]) {
110                 case IPV6_TLV_PAD0:
111                         optlen = 1;
112                         break;
113
114                 case IPV6_TLV_PADN:
115                         break;
116
117                 default: /* Other TLV code so scan list */
118                         if (optlen > len)
119                                 goto bad;
120                         for (curr=procs; curr->type >= 0; curr++) {
121                                 if (curr->type == skb->nh.raw[off]) {
122                                         /* type specific length/alignment 
123                                            checks will be performed in the 
124                                            func(). */
125                                         if (curr->func(skb, off) == 0)
126                                                 return 0;
127                                         break;
128                                 }
129                         }
130                         if (curr->type < 0) {
131                                 if (ip6_tlvopt_unknown(skb, off) == 0)
132                                         return 0;
133                         }
134                         break;
135                 }
136                 off += optlen;
137                 len -= optlen;
138         }
139         if (len == 0)
140                 return 1;
141 bad:
142         kfree_skb(skb);
143         return 0;
144 }
145
146 /*****************************
147   Destination options header.
148  *****************************/
149
150 static struct tlvtype_proc tlvprocdestopt_lst[] = {
151         /* No destination options are defined now */
152         {-1,                    NULL}
153 };
154
155 static int ipv6_destopt_rcv(struct sk_buff **skbp)
156 {
157         struct sk_buff *skb = *skbp;
158         struct inet6_skb_parm *opt = IP6CB(skb);
159
160         if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
161             !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
162                 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
163                 kfree_skb(skb);
164                 return -1;
165         }
166
167         opt->lastopt = skb->h.raw - skb->nh.raw;
168         opt->dst1 = skb->h.raw - skb->nh.raw;
169
170         if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
171                 skb->h.raw += ((skb->h.raw[1]+1)<<3);
172                 opt->nhoff = opt->dst1;
173                 return 1;
174         }
175
176         IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
177         return -1;
178 }
179
180 static struct inet6_protocol destopt_protocol = {
181         .handler        =       ipv6_destopt_rcv,
182         .flags          =       INET6_PROTO_NOPOLICY,
183 };
184
185 void __init ipv6_destopt_init(void)
186 {
187         if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
188                 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
189 }
190
191 /********************************
192   NONE header. No data in packet.
193  ********************************/
194
195 static int ipv6_nodata_rcv(struct sk_buff **skbp)
196 {
197         struct sk_buff *skb = *skbp;
198
199         kfree_skb(skb);
200         return 0;
201 }
202
203 static struct inet6_protocol nodata_protocol = {
204         .handler        =       ipv6_nodata_rcv,
205         .flags          =       INET6_PROTO_NOPOLICY,
206 };
207
208 void __init ipv6_nodata_init(void)
209 {
210         if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
211                 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
212 }
213
214 /********************************
215   Routing header.
216  ********************************/
217
218 static int ipv6_rthdr_rcv(struct sk_buff **skbp)
219 {
220         struct sk_buff *skb = *skbp;
221         struct inet6_skb_parm *opt = IP6CB(skb);
222         struct in6_addr *addr;
223         struct in6_addr daddr;
224         struct inet6_dev *idev;
225         int n, i;
226         struct ipv6_rt_hdr *hdr;
227         struct rt0_hdr *rthdr;
228         int accept_source_route = ipv6_devconf.accept_source_route;
229
230         if (accept_source_route < 0 ||
231             ((idev = in6_dev_get(skb->dev)) == NULL)) {
232                 kfree_skb(skb);
233                 return -1;
234         }
235         if (idev->cnf.accept_source_route < 0) {
236                 in6_dev_put(idev);
237                 kfree_skb(skb);
238                 return -1;
239         }
240
241         if (accept_source_route > idev->cnf.accept_source_route)
242                 accept_source_route = idev->cnf.accept_source_route;
243
244         in6_dev_put(idev);
245
246         if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
247             !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
248                 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
249                 kfree_skb(skb);
250                 return -1;
251         }
252
253         hdr = (struct ipv6_rt_hdr *) skb->h.raw;
254
255         switch (hdr->type) {
256         case IPV6_SRCRT_TYPE_0:
257                 if (accept_source_route > 0)
258                         break;
259                 kfree_skb(skb);
260                 return -1;
261         default:
262                 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
263                 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
264                 return -1;
265         }
266
267         if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
268             skb->pkt_type != PACKET_HOST) {
269                 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
270                 kfree_skb(skb);
271                 return -1;
272         }
273
274 looped_back:
275         if (hdr->segments_left == 0) {
276                 opt->lastopt = skb->h.raw - skb->nh.raw;
277                 opt->srcrt = skb->h.raw - skb->nh.raw;
278                 skb->h.raw += (hdr->hdrlen + 1) << 3;
279                 opt->dst0 = opt->dst1;
280                 opt->dst1 = 0;
281                 opt->nhoff = (&hdr->nexthdr) - skb->nh.raw;
282                 return 1;
283         }
284
285         if (hdr->hdrlen & 0x01) {
286                 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
287                 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
288                 return -1;
289         }
290
291         /*
292          *      This is the routing header forwarding algorithm from
293          *      RFC 2460, page 16.
294          */
295
296         n = hdr->hdrlen >> 1;
297
298         if (hdr->segments_left > n) {
299                 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
300                 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
301                 return -1;
302         }
303
304         /* We are about to mangle packet header. Be careful!
305            Do not damage packets queued somewhere.
306          */
307         if (skb_cloned(skb)) {
308                 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
309                 kfree_skb(skb);
310                 /* the copy is a forwarded packet */
311                 if (skb2 == NULL) {
312                         IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS);      
313                         return -1;
314                 }
315                 *skbp = skb = skb2;
316                 opt = IP6CB(skb2);
317                 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
318         }
319
320         if (skb->ip_summed == CHECKSUM_HW)
321                 skb->ip_summed = CHECKSUM_NONE;
322
323         i = n - --hdr->segments_left;
324
325         rthdr = (struct rt0_hdr *) hdr;
326         addr = rthdr->addr;
327         addr += i - 1;
328
329         if (ipv6_addr_is_multicast(addr)) {
330                 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
331                 kfree_skb(skb);
332                 return -1;
333         }
334
335         ipv6_addr_copy(&daddr, addr);
336         ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr);
337         ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr);
338
339         dst_release(xchg(&skb->dst, NULL));
340         ip6_route_input(skb);
341         if (skb->dst->error) {
342                 skb_push(skb, skb->data - skb->nh.raw);
343                 dst_input(skb);
344                 return -1;
345         }
346
347         if (skb->dst->dev->flags&IFF_LOOPBACK) {
348                 if (skb->nh.ipv6h->hop_limit <= 1) {
349                         IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
350                         icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
351                                     0, skb->dev);
352                         kfree_skb(skb);
353                         return -1;
354                 }
355                 skb->nh.ipv6h->hop_limit--;
356                 goto looped_back;
357         }
358
359         skb_push(skb, skb->data - skb->nh.raw);
360         dst_input(skb);
361         return -1;
362 }
363
364 static struct inet6_protocol rthdr_protocol = {
365         .handler        =       ipv6_rthdr_rcv,
366         .flags          =       INET6_PROTO_NOPOLICY,
367 };
368
369 void __init ipv6_rthdr_init(void)
370 {
371         if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
372                 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
373 };
374
375 /*
376    This function inverts received rthdr.
377    NOTE: specs allow to make it automatically only if
378    packet authenticated.
379
380    I will not discuss it here (though, I am really pissed off at
381    this stupid requirement making rthdr idea useless)
382
383    Actually, it creates severe problems  for us.
384    Embryonic requests has no associated sockets,
385    so that user have no control over it and
386    cannot not only to set reply options, but
387    even to know, that someone wants to connect
388    without success. :-(
389
390    For now we need to test the engine, so that I created
391    temporary (or permanent) backdoor.
392    If listening socket set IPV6_RTHDR to 2, then we invert header.
393                                                    --ANK (980729)
394  */
395
396 struct ipv6_txoptions *
397 ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
398 {
399         /* Received rthdr:
400
401            [ H1 -> H2 -> ... H_prev ]  daddr=ME
402
403            Inverted result:
404            [ H_prev -> ... -> H1 ] daddr =sender
405
406            Note, that IP output engine will rewrite this rthdr
407            by rotating it left by one addr.
408          */
409
410         int n, i;
411         struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
412         struct rt0_hdr *irthdr;
413         struct ipv6_txoptions *opt;
414         int hdrlen = ipv6_optlen(hdr);
415
416         if (hdr->segments_left ||
417             hdr->type != IPV6_SRCRT_TYPE_0 ||
418             hdr->hdrlen & 0x01)
419                 return NULL;
420
421         n = hdr->hdrlen >> 1;
422         opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
423         if (opt == NULL)
424                 return NULL;
425         memset(opt, 0, sizeof(*opt));
426         opt->tot_len = sizeof(*opt) + hdrlen;
427         opt->srcrt = (void*)(opt+1);
428         opt->opt_nflen = hdrlen;
429
430         memcpy(opt->srcrt, hdr, sizeof(*hdr));
431         irthdr = (struct rt0_hdr*)opt->srcrt;
432         irthdr->reserved = 0;
433         opt->srcrt->segments_left = n;
434         for (i=0; i<n; i++)
435                 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
436         return opt;
437 }
438
439 EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
440
441 /**********************************
442   Hop-by-hop options.
443  **********************************/
444
445 /* Router Alert as of RFC 2711 */
446
447 static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
448 {
449         if (skb->nh.raw[optoff+1] == 2) {
450                 IP6CB(skb)->ra = optoff;
451                 return 1;
452         }
453         LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
454                        skb->nh.raw[optoff+1]);
455         kfree_skb(skb);
456         return 0;
457 }
458
459 /* Jumbo payload */
460
461 static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
462 {
463         u32 pkt_len;
464
465         if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
466                 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
467                                skb->nh.raw[optoff+1]);
468                 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
469                 goto drop;
470         }
471
472         pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));
473         if (pkt_len <= IPV6_MAXPLEN) {
474                 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
475                 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
476                 return 0;
477         }
478         if (skb->nh.ipv6h->payload_len) {
479                 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
480                 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
481                 return 0;
482         }
483
484         if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
485                 IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS);
486                 goto drop;
487         }
488
489         if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
490                 goto drop;
491
492         return 1;
493
494 drop:
495         kfree_skb(skb);
496         return 0;
497 }
498
499 static struct tlvtype_proc tlvprochopopt_lst[] = {
500         {
501                 .type   = IPV6_TLV_ROUTERALERT,
502                 .func   = ipv6_hop_ra,
503         },
504         {
505                 .type   = IPV6_TLV_JUMBO,
506                 .func   = ipv6_hop_jumbo,
507         },
508         { -1, }
509 };
510
511 int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
512 {
513         struct inet6_skb_parm *opt = IP6CB(skb);
514
515         /*
516          * skb->nh.raw is equal to skb->data, and
517          * skb->h.raw - skb->nh.raw is always equal to
518          * sizeof(struct ipv6hdr) by definition of
519          * hop-by-hop options.
520          */
521         if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
522             !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
523                 kfree_skb(skb);
524                 return -1;
525         }
526
527         opt->hop = sizeof(struct ipv6hdr);
528         if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
529                 skb->h.raw += (skb->h.raw[1]+1)<<3;
530                 opt->nhoff = sizeof(struct ipv6hdr);
531                 return sizeof(struct ipv6hdr);
532         }
533         return -1;
534 }
535
536 /*
537  *      Creating outbound headers.
538  *
539  *      "build" functions work when skb is filled from head to tail (datagram)
540  *      "push"  functions work when headers are added from tail to head (tcp)
541  *
542  *      In both cases we assume, that caller reserved enough room
543  *      for headers.
544  */
545
546 static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
547                             struct ipv6_rt_hdr *opt,
548                             struct in6_addr **addr_p)
549 {
550         struct rt0_hdr *phdr, *ihdr;
551         int hops;
552
553         ihdr = (struct rt0_hdr *) opt;
554         
555         phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
556         memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
557
558         hops = ihdr->rt_hdr.hdrlen >> 1;
559
560         if (hops > 1)
561                 memcpy(phdr->addr, ihdr->addr + 1,
562                        (hops - 1) * sizeof(struct in6_addr));
563
564         ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
565         *addr_p = ihdr->addr;
566
567         phdr->rt_hdr.nexthdr = *proto;
568         *proto = NEXTHDR_ROUTING;
569 }
570
571 static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
572 {
573         struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
574
575         memcpy(h, opt, ipv6_optlen(opt));
576         h->nexthdr = *proto;
577         *proto = type;
578 }
579
580 void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
581                           u8 *proto,
582                           struct in6_addr **daddr)
583 {
584         if (opt->srcrt) {
585                 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
586                 /*
587                  * IPV6_RTHDRDSTOPTS is ignored
588                  * unless IPV6_RTHDR is set (RFC3542).
589                  */
590                 if (opt->dst0opt)
591                         ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
592         }
593         if (opt->hopopt)
594                 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
595 }
596
597 void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
598 {
599         if (opt->dst1opt)
600                 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
601 }
602
603 struct ipv6_txoptions *
604 ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
605 {
606         struct ipv6_txoptions *opt2;
607
608         opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
609         if (opt2) {
610                 long dif = (char*)opt2 - (char*)opt;
611                 memcpy(opt2, opt, opt->tot_len);
612                 if (opt2->hopopt)
613                         *((char**)&opt2->hopopt) += dif;
614                 if (opt2->dst0opt)
615                         *((char**)&opt2->dst0opt) += dif;
616                 if (opt2->dst1opt)
617                         *((char**)&opt2->dst1opt) += dif;
618                 if (opt2->srcrt)
619                         *((char**)&opt2->srcrt) += dif;
620         }
621         return opt2;
622 }
623
624 EXPORT_SYMBOL_GPL(ipv6_dup_options);
625
626 static int ipv6_renew_option(void *ohdr,
627                              struct ipv6_opt_hdr __user *newopt, int newoptlen,
628                              int inherit,
629                              struct ipv6_opt_hdr **hdr,
630                              char **p)
631 {
632         if (inherit) {
633                 if (ohdr) {
634                         memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
635                         *hdr = (struct ipv6_opt_hdr *)*p;
636                         *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
637                 }
638         } else {
639                 if (newopt) {
640                         if (copy_from_user(*p, newopt, newoptlen))
641                                 return -EFAULT;
642                         *hdr = (struct ipv6_opt_hdr *)*p;
643                         if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
644                                 return -EINVAL;
645                         *p += CMSG_ALIGN(newoptlen);
646                 }
647         }
648         return 0;
649 }
650
651 struct ipv6_txoptions *
652 ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
653                    int newtype,
654                    struct ipv6_opt_hdr __user *newopt, int newoptlen)
655 {
656         int tot_len = 0;
657         char *p;
658         struct ipv6_txoptions *opt2;
659         int err;
660
661         if (opt) {
662                 if (newtype != IPV6_HOPOPTS && opt->hopopt)
663                         tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
664                 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
665                         tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
666                 if (newtype != IPV6_RTHDR && opt->srcrt)
667                         tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
668                 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
669                         tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
670         }
671
672         if (newopt && newoptlen)
673                 tot_len += CMSG_ALIGN(newoptlen);
674
675         if (!tot_len)
676                 return NULL;
677
678         tot_len += sizeof(*opt2);
679         opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
680         if (!opt2)
681                 return ERR_PTR(-ENOBUFS);
682
683         memset(opt2, 0, tot_len);
684
685         opt2->tot_len = tot_len;
686         p = (char *)(opt2 + 1);
687
688         err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
689                                 newtype != IPV6_HOPOPTS,
690                                 &opt2->hopopt, &p);
691         if (err)
692                 goto out;
693
694         err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
695                                 newtype != IPV6_RTHDRDSTOPTS,
696                                 &opt2->dst0opt, &p);
697         if (err)
698                 goto out;
699
700         err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
701                                 newtype != IPV6_RTHDR,
702                                 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
703         if (err)
704                 goto out;
705
706         err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
707                                 newtype != IPV6_DSTOPTS,
708                                 &opt2->dst1opt, &p);
709         if (err)
710                 goto out;
711
712         opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
713                           (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
714                           (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
715         opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
716
717         return opt2;
718 out:
719         sock_kfree_s(sk, opt2, opt2->tot_len);
720         return ERR_PTR(err);
721 }
722
723 struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
724                                           struct ipv6_txoptions *opt)
725 {
726         /*
727          * ignore the dest before srcrt unless srcrt is being included.
728          * --yoshfuji
729          */
730         if (opt && opt->dst0opt && !opt->srcrt) {
731                 if (opt_space != opt) {
732                         memcpy(opt_space, opt, sizeof(*opt_space));
733                         opt = opt_space;
734                 }
735                 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
736                 opt->dst0opt = NULL;
737         }
738
739         return opt;
740 }
741