]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/dccp/ipv4.c
[NET_SCHED]: Propagate nla_parse return value
[karo-tx-linux.git] / net / dccp / ipv4.c
index 58a79c2ae55cc3fab1104da5f2e8b91291d52ae2..9e38b0d6195ce637355762471cb988e8ea4527fa 100644 (file)
@@ -241,8 +241,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
                goto out;
 
        dp = dccp_sk(sk);
-       seq = dccp_hdr_seq(skb);
-       if (sk->sk_state != DCCP_LISTEN &&
+       seq = dccp_hdr_seq(dh);
+       if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
            !between48(seq, dp->dccps_swl, dp->dccps_swh)) {
                NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
                goto out;
@@ -408,7 +408,7 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
 
        dccp_sync_mss(newsk, dst_mtu(dst));
 
-       __inet_hash(&dccp_hashinfo, newsk, 0);
+       __inet_hash_nolisten(&dccp_hashinfo, newsk);
        __inet_inherit_port(&dccp_hashinfo, sk, newsk);
 
        return newsk;
@@ -469,7 +469,7 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
                          };
 
        security_skb_classify_flow(skb, &fl);
-       if (ip_route_output_flow(&rt, &fl, sk, 0)) {
+       if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0)) {
                IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
                return NULL;
        }
@@ -510,17 +510,12 @@ out:
 static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
 {
        int err;
-       struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
        const struct iphdr *rxiph;
-       const int dccp_hdr_reset_len = sizeof(struct dccp_hdr) +
-                                      sizeof(struct dccp_hdr_ext) +
-                                      sizeof(struct dccp_hdr_reset);
        struct sk_buff *skb;
        struct dst_entry *dst;
-       u64 seqno = 0;
 
        /* Never send a reset in response to a reset. */
-       if (rxdh->dccph_type == DCCP_PKT_RESET)
+       if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
                return;
 
        if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
@@ -530,37 +525,14 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
        if (dst == NULL)
                return;
 
-       skb = alloc_skb(dccp_v4_ctl_socket->sk->sk_prot->max_header,
-                       GFP_ATOMIC);
+       skb = dccp_ctl_make_reset(dccp_v4_ctl_socket, rxskb);
        if (skb == NULL)
                goto out;
 
-       /* Reserve space for headers. */
-       skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header);
-       skb->dst = dst_clone(dst);
-
-       dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len);
-
-       /* Build DCCP header and checksum it. */
-       dh->dccph_type     = DCCP_PKT_RESET;
-       dh->dccph_sport    = rxdh->dccph_dport;
-       dh->dccph_dport    = rxdh->dccph_sport;
-       dh->dccph_doff     = dccp_hdr_reset_len / 4;
-       dh->dccph_x        = 1;
-       dccp_hdr_reset(skb)->dccph_reset_code =
-                               DCCP_SKB_CB(rxskb)->dccpd_reset_code;
-
-       /* See "8.3.1. Abnormal Termination" in RFC 4340 */
-       if (DCCP_SKB_CB(rxskb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
-               seqno = ADD48(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_csum_outgoing(skb);
        rxiph = ip_hdr(rxskb);
-       dh->dccph_checksum = dccp_v4_csum_finish(skb, rxiph->saddr,
-                                                rxiph->daddr);
+       dccp_hdr(skb)->dccph_checksum = dccp_v4_csum_finish(skb, rxiph->saddr,
+                                                                rxiph->daddr);
+       skb->dst = dst_clone(dst);
 
        bh_lock_sock(dccp_v4_ctl_socket->sk);
        err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
@@ -596,17 +568,14 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        struct dccp_request_sock *dreq;
        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;
 
        /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
        if (((struct rtable *)skb->dst)->rt_flags &
-           (RTCF_BROADCAST | RTCF_MULTICAST)) {
-               reset_code = DCCP_RESET_CODE_NO_CONNECTION;
-               goto drop;
-       }
+           (RTCF_BROADCAST | RTCF_MULTICAST))
+               return 0;       /* discard, don't send a reset here */
 
        if (dccp_bad_service_code(sk, service)) {
-               reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
+               dcb->dccpd_reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
                goto drop;
        }
        /*
@@ -614,6 +583,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
         * limitations, they conserve resources and peer is
         * evidently real one.
         */
+       dcb->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
        if (inet_csk_reqsk_queue_is_full(sk))
                goto drop;
 
@@ -630,11 +600,12 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        if (req == NULL)
                goto drop;
 
-       if (dccp_parse_options(sk, skb))
-               goto drop_and_free;
-
        dccp_reqsk_init(req, skb);
 
+       dreq = dccp_rsk(req);
+       if (dccp_parse_options(sk, dreq, skb))
+               goto drop_and_free;
+
        if (security_inet_conn_request(sk, skb, req))
                goto drop_and_free;
 
@@ -651,7 +622,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
         * In fact we defer setting S.GSR, S.SWL, S.SWH to
         * dccp_create_openreq_child.
         */
-       dreq = dccp_rsk(req);
        dreq->dreq_isr     = dcb->dccpd_seq;
        dreq->dreq_iss     = dccp_v4_init_sequence(skb);
        dreq->dreq_service = service;
@@ -666,7 +636,6 @@ drop_and_free:
        reqsk_free(req);
 drop:
        DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
-       dcb->dccpd_reset_code = reset_code;
        return -1;
 }
 
@@ -826,7 +795,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
 
        dh = dccp_hdr(skb);
 
-       DCCP_SKB_CB(skb)->dccpd_seq  = dccp_hdr_seq(skb);
+       DCCP_SKB_CB(skb)->dccpd_seq  = dccp_hdr_seq(dh);
        DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
 
        dccp_pr_debug("%8.8s "
@@ -953,6 +922,8 @@ static struct timewait_sock_ops dccp_timewait_sock_ops = {
        .twsk_obj_size  = sizeof(struct inet_timewait_sock),
 };
 
+DEFINE_PROTO_INUSE(dccp_v4)
+
 static struct proto dccp_v4_prot = {
        .name                   = "DCCP",
        .owner                  = THIS_MODULE,
@@ -981,6 +952,7 @@ static struct proto dccp_v4_prot = {
        .compat_setsockopt      = compat_dccp_setsockopt,
        .compat_getsockopt      = compat_dccp_getsockopt,
 #endif
+       REF_PROTO_INUSE(dccp_v4)
 };
 
 static struct net_protocol dccp_v4_protocol = {
@@ -1068,8 +1040,8 @@ module_exit(dccp_v4_exit);
  * values directly, Also cover the case where the protocol is not specified,
  * i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP
  */
-MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-33-type-6");
-MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-0-type-6");
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 33, 6);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 0, 6);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
 MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol");