1616#include <linux/random.h>
1717#include <linux/slab.h>
1818#include <linux/xfrm.h>
19+ #include <linux/string.h>
1920
2021#include <net/addrconf.h>
2122#include <net/inet_common.h>
3031#include <net/ip6_checksum.h>
3132#include <net/xfrm.h>
3233#include <net/secure_seq.h>
34+ #include <net/sock.h>
3335
3436#include "dccp.h"
3537#include "ipv6.h"
@@ -597,19 +599,13 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
597599 --ANK (980728)
598600 */
599601 if (np -> rxopt .all )
600- /*
601- * FIXME: Add handling of IPV6_PKTOPTIONS skb. See the comments below
602- * (wrt ipv6_pktopions) and net/ipv6/tcp_ipv6.c for an example.
603- */
604602 opt_skb = skb_clone (skb , GFP_ATOMIC );
605603
606604 if (sk -> sk_state == DCCP_OPEN ) { /* Fast path */
607605 if (dccp_rcv_established (sk , skb , dccp_hdr (skb ), skb -> len ))
608606 goto reset ;
609- if (opt_skb ) {
610- /* XXX This is where we would goto ipv6_pktoptions. */
611- __kfree_skb (opt_skb );
612- }
607+ if (opt_skb )
608+ goto ipv6_pktoptions ;
613609 return 0 ;
614610 }
615611
@@ -640,10 +636,8 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
640636
641637 if (dccp_rcv_state_process (sk , skb , dccp_hdr (skb ), skb -> len ))
642638 goto reset ;
643- if (opt_skb ) {
644- /* XXX This is where we would goto ipv6_pktoptions. */
645- __kfree_skb (opt_skb );
646- }
639+ if (opt_skb )
640+ goto ipv6_pktoptions ;
647641 return 0 ;
648642
649643reset :
@@ -653,6 +647,35 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
653647 __kfree_skb (opt_skb );
654648 kfree_skb (skb );
655649 return 0 ;
650+
651+ /* Handling IPV6_PKTOPTIONS skb the similar
652+ * way it's done for net/ipv6/tcp_ipv6.c
653+ */
654+ ipv6_pktoptions :
655+ if (!((1 << sk -> sk_state ) & (DCCPF_CLOSED | DCCPF_LISTEN ))) {
656+ if (np -> rxopt .bits .rxinfo || np -> rxopt .bits .rxoinfo )
657+ np -> mcast_oif = inet6_iif (opt_skb );
658+ if (np -> rxopt .bits .rxhlim || np -> rxopt .bits .rxohlim )
659+ np -> mcast_hops = ipv6_hdr (opt_skb )-> hop_limit ;
660+ if (np -> rxopt .bits .rxflow || np -> rxopt .bits .rxtclass )
661+ np -> rcv_flowinfo = ip6_flowinfo (ipv6_hdr (opt_skb ));
662+ if (np -> repflow )
663+ np -> flow_label = ip6_flowlabel (ipv6_hdr (opt_skb ));
664+ if (ipv6_opt_accepted (sk , opt_skb ,
665+ & DCCP_SKB_CB (opt_skb )-> header .h6 )) {
666+ skb_set_owner_r (opt_skb , sk );
667+ memmove (IP6CB (opt_skb ),
668+ & DCCP_SKB_CB (opt_skb )-> header .h6 ,
669+ sizeof (struct inet6_skb_parm ));
670+ opt_skb = xchg (& np -> pktoptions , opt_skb );
671+ } else {
672+ __kfree_skb (opt_skb );
673+ opt_skb = xchg (& np -> pktoptions , NULL );
674+ }
675+ }
676+
677+ kfree_skb (opt_skb );
678+ return 0 ;
656679}
657680
658681static int dccp_v6_rcv (struct sk_buff * skb )
0 commit comments