Merge git://oss.sgi.com:8090/xfs/xfs-2.6
[linux-drm-fsl-dcu.git] / net / dccp / ipv6.c
index 193b946fd039587d936da2c4bb45feb43d0f6f38..7f51e8db3967280e7698fb1c916a64c6c4a5b24c 100644 (file)
@@ -59,7 +59,7 @@ static void dccp_v6_hash(struct sock *sk)
 }
 
 /* add pseudo-header to DCCP checksum stored in skb->csum */
-static inline u16 dccp_v6_csum_finish(struct sk_buff *skb,
+static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb,
                                      struct in6_addr *saddr,
                                      struct in6_addr *daddr)
 {
@@ -76,20 +76,19 @@ static inline void dccp_v6_send_check(struct sock *sk, int unused_value,
        dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr);
 }
 
-static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
+static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+                                                 __be16 sport, __be16 dport   )
 {
-       const struct dccp_hdr *dh = dccp_hdr(skb);
+       return secure_tcpv6_sequence_number(saddr, daddr, sport, dport);
+}
 
-       if (skb->protocol == htons(ETH_P_IPV6))
-               return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
-                                                   skb->nh.ipv6h->saddr.s6_addr32,
-                                                   dh->dccph_dport,
-                                                   dh->dccph_sport);
+static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb)
+{
+       return secure_dccpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
+                                            skb->nh.ipv6h->saddr.s6_addr32,
+                                            dccp_hdr(skb)->dccph_dport,
+                                            dccp_hdr(skb)->dccph_sport     );
 
-       return secure_dccp_sequence_number(skb->nh.iph->daddr,
-                                          skb->nh.iph->saddr,
-                                          dh->dccph_dport,
-                                          dh->dccph_sport);
 }
 
 static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -295,8 +294,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
                                                         &ireq6->rmt_addr);
                ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
                err = ip6_xmit(sk, skb, &fl, opt, 0);
-               if (err == NET_XMIT_CN)
-                       err = 0;
+               err = net_xmit_eval(err);
        }
 
 done:
@@ -312,7 +310,7 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req)
                kfree_skb(inet6_rsk(req)->pktopts);
 }
 
-static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
+static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
 {
        struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
        const u32 dccp_hdr_reset_len = sizeof(struct dccp_hdr) +
@@ -320,7 +318,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
                                       sizeof(struct dccp_hdr_reset);
        struct sk_buff *skb;
        struct flowi fl;
-       u64 seqno;
+       u64 seqno = 0;
 
        if (rxdh->dccph_type == DCCP_PKT_RESET)
                return;
@@ -331,7 +329,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
        skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header,
                        GFP_ATOMIC);
        if (skb == NULL)
-               return;
+               return;
 
        skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header);
 
@@ -347,17 +345,15 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
                                DCCP_SKB_CB(rxskb)->dccpd_reset_code;
 
        /* See "8.3.1. Abnormal Termination" in RFC 4340 */
-       seqno = 0;
        if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
                dccp_set_seqno(&seqno, DCCP_SKB_CB(rxskb)->dccpd_ack_seq + 1);
 
        dccp_hdr_set_seq(dh, seqno);
-       dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
-                        DCCP_SKB_CB(rxskb)->dccpd_seq);
+       dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq);
 
        dccp_csum_outgoing(skb);
        dh->dccph_checksum = dccp_v6_csum_finish(skb, &rxskb->nh.ipv6h->saddr,
-                                                     &rxskb->nh.ipv6h->daddr);
+                                                     &rxskb->nh.ipv6h->daddr);
 
        memset(&fl, 0, sizeof(fl));
        ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
@@ -428,7 +424,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        struct dccp_request_sock *dreq;
        struct inet6_request_sock *ireq6;
        struct ipv6_pinfo *np = inet6_sk(sk);
-       const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
+       const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
        struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
        __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
 
@@ -441,7 +437,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        if (dccp_bad_service_code(sk, service)) {
                reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
                goto drop;
-       }
+       }
        /*
         * There are no SYN attacks on IPv6, yet...
         */
@@ -491,7 +487,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
         */
        dreq = dccp_rsk(req);
        dreq->dreq_isr     = dcb->dccpd_seq;
-       dreq->dreq_iss     = dccp_v6_init_sequence(sk, skb);
+       dreq->dreq_iss     = dccp_v6_init_sequence(skb);
        dreq->dreq_service = service;
 
        if (dccp_v6_send_response(sk, req, NULL))
@@ -738,7 +734,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
           looks not very well thought. For now we latch
           options, received in the last packet, enqueued
           by tcp. Feel free to propose better solution.
-                                              --ANK (980728)
+                                              --ANK (980728)
         */
        if (np->rxopt.all)
        /*
@@ -791,7 +787,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                 * otherwise we just shortcircuit this and continue with
                 * the new socket..
                 */
-               if (nsk != sk) {
+               if (nsk != sk) {
                        if (dccp_child_process(sk, nsk, skb))
                                goto reset;
                        if (opt_skb != NULL)
@@ -809,7 +805,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
        return 0;
 
 reset:
-       dccp_v6_ctl_send_reset(skb);
+       dccp_v6_ctl_send_reset(sk, skb);
 discard:
        if (opt_skb != NULL)
                __kfree_skb(opt_skb);
@@ -832,9 +828,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
        /* Step 1: If header checksum is incorrect, drop packet and return. */
        if (dccp_v6_csum_finish(skb, &skb->nh.ipv6h->saddr,
                                     &skb->nh.ipv6h->daddr)) {
-               LIMIT_NETDEBUG(KERN_WARNING
-                              "%s: dropped packet with invalid checksum\n",
-                              __FUNCTION__);
+               DCCP_WARN("dropped packet with invalid checksum\n");
                goto discard_it;
        }
 
@@ -849,14 +843,14 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
                DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
 
        /* Step 2:
-        *      Look up flow ID in table and get corresponding socket */
+        *      Look up flow ID in table and get corresponding socket */
        sk = __inet6_lookup(&dccp_hashinfo, &skb->nh.ipv6h->saddr,
                            dh->dccph_sport,
                            &skb->nh.ipv6h->daddr, ntohs(dh->dccph_dport),
                            inet6_iif(skb));
        /*
         * Step 2:
-        *      If no socket ...
+        *      If no socket ...
         */
        if (sk == NULL) {
                dccp_pr_debug("failed to look up flow ID in table and "
@@ -866,7 +860,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
 
        /*
         * Step 2:
-        *      ... or S.state == TIMEWAIT,
+        *      ... or S.state == TIMEWAIT,
         *              Generate Reset(No Connection) unless P.type == Reset
         *              Drop packet and return
         */
@@ -878,8 +872,8 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
 
        /*
         * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
-        *      o if MinCsCov = 0, only packets with CsCov = 0 are accepted
-        *      o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
+        *      o if MinCsCov = 0, only packets with CsCov = 0 are accepted
+        *      o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
         */
        min_cov = dccp_sk(sk)->dccps_pcrlen;
        if (dh->dccph_cscov  &&  (min_cov == 0 || dh->dccph_cscov < min_cov))  {
@@ -892,21 +886,21 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
                goto discard_and_relse;
 
-       return sk_receive_skb(sk, skb) ? -1 : 0;
+       return sk_receive_skb(sk, skb, 1) ? -1 : 0;
 
 no_dccp_socket:
        if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
                goto discard_it;
        /*
         * Step 2:
-        *      If no socket ...
+        *      If no socket ...
         *              Generate Reset(No Connection) unless P.type == Reset
         *              Drop packet and return
         */
        if (dh->dccph_type != DCCP_PKT_RESET) {
                DCCP_SKB_CB(skb)->dccpd_reset_code =
                                        DCCP_RESET_CODE_NO_CONNECTION;
-               dccp_v6_ctl_send_reset(skb);
+               dccp_v6_ctl_send_reset(sk, skb);
        }
 
 discard_it:
@@ -1047,7 +1041,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        if (final_p)
                ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-       err = xfrm_lookup(&dst, &fl, sk, 0);
+       err = xfrm_lookup(&dst, &fl, sk, 1);
        if (err < 0)
                goto failure;
 
@@ -1073,13 +1067,10 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        err = inet6_hash_connect(&dccp_death_row, sk);
        if (err)
                goto late_failure;
-       /* FIXME */
-#if 0
-       dp->dccps_gar = secure_dccp_v6_sequence_number(np->saddr.s6_addr32,
-                                                      np->daddr.s6_addr32,
-                                                      inet->sport,
-                                                      inet->dport);
-#endif
+
+       dp->dccps_iss = secure_dccpv6_sequence_number(np->saddr.s6_addr32,
+                                                     np->daddr.s6_addr32,
+                                                     inet->sport, inet->dport);
        err = dccp_connect(sk);
        if (err)
                goto late_failure;