X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fdccp%2Fipv6.c;fp=net%2Fdccp%2Fipv6.c;h=d75639abca02227b22b05e7838e3ca121d5d580e;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=3744c246c42e857f27476b3a865fc3db1d7e3c60;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 3744c246c..d75639abc 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1,6 +1,6 @@ /* * DCCP over IPv6 - * Linux INET6 implementation + * Linux INET6 implementation * * Based on net/dccp6/ipv6.c * @@ -12,6 +12,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include @@ -31,10 +32,6 @@ #include "dccp.h" #include "ipv6.h" -#include "feat.h" - -/* Socket used for sending RSTs and ACKs */ -static struct socket *dccp_v6_ctl_socket; static void dccp_v6_ctl_send_reset(struct sk_buff *skb); static void dccp_v6_reqsk_send_ack(struct sk_buff *skb, @@ -56,7 +53,7 @@ static void dccp_v6_hash(struct sock *sk) { if (sk->sk_state != DCCP_CLOSED) { if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) { - dccp_hash(sk); + dccp_prot.hash(sk); return; } local_bh_disable(); @@ -66,8 +63,8 @@ static void dccp_v6_hash(struct sock *sk) } static inline u16 dccp_v6_check(struct dccp_hdr *dh, int len, - struct in6_addr *saddr, - struct in6_addr *daddr, + struct in6_addr *saddr, + struct in6_addr *daddr, unsigned long base) { return csum_ipv6_magic(saddr, daddr, len, IPPROTO_DCCP, base); @@ -82,17 +79,17 @@ static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) skb->nh.ipv6h->saddr.s6_addr32, dh->dccph_dport, dh->dccph_sport); - - return secure_dccp_sequence_number(skb->nh.iph->daddr, - skb->nh.iph->saddr, - dh->dccph_dport, - dh->dccph_sport); + else + return secure_dccp_sequence_number(skb->nh.iph->daddr, + skb->nh.iph->saddr, + dh->dccph_dport, + dh->dccph_sport); } -static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, +static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { - struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr; + struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; struct inet_connection_sock *icsk = inet_csk(sk); struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); @@ -105,10 +102,10 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, dp->dccps_role = DCCP_ROLE_CLIENT; - if (addr_len < SIN6_LEN_RFC2133) + if (addr_len < SIN6_LEN_RFC2133) return -EINVAL; - if (usin->sin6_family != AF_INET6) + if (usin->sin6_family != AF_INET6) return -EAFNOSUPPORT; memset(&fl, 0, sizeof(fl)); @@ -125,15 +122,17 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl6_sock_release(flowlabel); } } + /* - * connect() to INADDR_ANY means loopback (BSD'ism). - */ - if (ipv6_addr_any(&usin->sin6_addr)) - usin->sin6_addr.s6_addr[15] = 1; + * connect() to INADDR_ANY means loopback (BSD'ism). + */ + + if (ipv6_addr_any(&usin->sin6_addr)) + usin->sin6_addr.s6_addr[15] = 0x1; addr_type = ipv6_addr_type(&usin->sin6_addr); - if (addr_type & IPV6_ADDR_MULTICAST) + if(addr_type & IPV6_ADDR_MULTICAST) return -ENETUNREACH; if (addr_type & IPV6_ADDR_LINKLOCAL) { @@ -158,8 +157,9 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, np->flow_label = fl.fl6_flowlabel; /* - * DCCP over IPv4 + * DCCP over IPv4 */ + if (addr_type == IPV6_ADDR_MAPPED) { u32 exthdrlen = icsk->icsk_ext_hdr_len; struct sockaddr_in sin; @@ -177,6 +177,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, sk->sk_backlog_rcv = dccp_v4_do_rcv; err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin)); + if (err) { icsk->icsk_ext_hdr_len = exthdrlen; icsk->icsk_af_ops = &dccp_ipv6_af_ops; @@ -202,9 +203,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl.fl_ip_dport = usin->sin6_port; fl.fl_ip_sport = inet->sport; - if (np->opt != NULL && np->opt->srcrt != NULL) { - const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; - + if (np->opt && np->opt->srcrt) { + struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; ipv6_addr_copy(&final, &fl.fl6_dst); ipv6_addr_copy(&fl.fl6_dst, rt0->addr); final_p = &final; @@ -213,12 +213,10 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, err = ip6_dst_lookup(sk, &dst, &fl); if (err) goto failure; - if (final_p) ipv6_addr_copy(&fl.fl6_dst, final_p); - err = xfrm_lookup(&dst, &fl, sk, 0); - if (err < 0) + if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) goto failure; if (saddr == NULL) { @@ -230,10 +228,10 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, ipv6_addr_copy(&np->saddr, saddr); inet->rcv_saddr = LOOPBACK4_IPV6; - __ip6_dst_store(sk, dst, NULL); + ip6_dst_store(sk, dst, NULL); icsk->icsk_ext_hdr_len = 0; - if (np->opt != NULL) + if (np->opt) icsk->icsk_ext_hdr_len = (np->opt->opt_flen + np->opt->opt_nflen); @@ -266,7 +264,7 @@ failure: } static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) + int type, int code, int offset, __u32 info) { struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data; const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); @@ -307,6 +305,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, /* icmp should have updated the destination cache entry */ dst = __sk_dst_check(sk, np->dst_cookie); + if (dst == NULL) { struct inet_sock *inet = inet_sk(sk); struct flowi fl; @@ -323,17 +322,16 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, fl.fl_ip_dport = inet->dport; fl.fl_ip_sport = inet->sport; - err = ip6_dst_lookup(sk, &dst, &fl); - if (err) { + if ((err = ip6_dst_lookup(sk, &dst, &fl))) { sk->sk_err_soft = -err; goto out; } - err = xfrm_lookup(&dst, &fl, sk, 0); - if (err < 0) { + if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { sk->sk_err_soft = -err; goto out; } + } else dst_hold(dst); @@ -357,12 +355,11 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, req = inet6_csk_search_req(sk, &prev, dh->dccph_dport, &hdr->daddr, &hdr->saddr, inet6_iif(skb)); - if (req == NULL) + if (!req) goto out; - /* - * ICMPs are not backlogged, hence we cannot get an established - * socket here. + /* ICMPs are not backlogged, hence we cannot get + * an established socket here. */ BUG_TRAP(req->sk == NULL); @@ -376,7 +373,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, case DCCP_REQUESTING: case DCCP_RESPOND: /* Cannot happen. - It can, it SYNs are crossed. --ANK */ + It can, it SYNs are crossed. --ANK */ if (!sock_owned_by_user(sk)) { DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); sk->sk_err = err; @@ -385,6 +382,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, * (see connect in sock.c) */ sk->sk_error_report(sk); + dccp_done(sk); } else sk->sk_err_soft = err; @@ -430,16 +428,14 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, ireq6->pktopts) { struct sk_buff *pktopts = ireq6->pktopts; struct inet6_skb_parm *rxopt = IP6CB(pktopts); - if (rxopt->srcrt) opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr *)(pktopts->nh.raw + rxopt->srcrt)); } - if (opt != NULL && opt->srcrt != NULL) { - const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; - + if (opt && opt->srcrt) { + struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; ipv6_addr_copy(&final, &fl.fl6_dst); ipv6_addr_copy(&fl.fl6_dst, rt0->addr); final_p = &final; @@ -448,19 +444,15 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, err = ip6_dst_lookup(sk, &dst, &fl); if (err) goto done; - if (final_p) ipv6_addr_copy(&fl.fl6_dst, final_p); - - err = xfrm_lookup(&dst, &fl, sk, 0); - if (err < 0) + if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) goto done; } skb = dccp_make_response(sk, dst, req); if (skb != NULL) { struct dccp_hdr *dh = dccp_hdr(skb); - dh->dccph_checksum = dccp_v6_check(dh, skb->len, &ireq6->loc_addr, &ireq6->rmt_addr, @@ -474,7 +466,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, } done: - if (opt != NULL && opt != np->opt) + if (opt && opt != np->opt) sock_kfree_s(sk, opt, opt->tot_len); dst_release(dst); return err; @@ -505,7 +497,7 @@ static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) struct dccp_hdr *dh = dccp_hdr(skb); dh->dccph_checksum = csum_ipv6_magic(&np->saddr, &np->daddr, - len, IPPROTO_DCCP, + len, IPPROTO_DCCP, csum_partial((char *)dh, dh->dccph_doff << 2, skb->csum)); @@ -513,8 +505,8 @@ static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) { - struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; - const u32 dccp_hdr_reset_len = sizeof(struct dccp_hdr) + + struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; + const int dccp_hdr_reset_len = sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_reset); struct sk_buff *skb; @@ -525,14 +517,20 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) return; if (!ipv6_unicast_destination(rxskb)) - return; + return; - skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header, - GFP_ATOMIC); - if (skb == NULL) + /* + * We need to grab some memory, and put together an RST, + * and then put it into the queue to be sent. + */ + + skb = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + + dccp_hdr_reset_len, GFP_ATOMIC); + if (skb == NULL) return; - skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header); + skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr) + + dccp_hdr_reset_len); skb->h.raw = skb_push(skb, dccp_hdr_reset_len); dh = dccp_hdr(skb); @@ -570,7 +568,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) /* sk = NULL, but it is safe for now. RST socket required. */ if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { - ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0); + ip6_xmit(NULL, skb, &fl, NULL, 0); DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); return; @@ -580,22 +578,22 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) kfree_skb(skb); } -static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb, - struct request_sock *req) +static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb) { struct flowi fl; struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; - const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) + + const int dccp_hdr_ack_len = sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits); struct sk_buff *skb; - skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header, - GFP_ATOMIC); + skb = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + + dccp_hdr_ack_len, GFP_ATOMIC); if (skb == NULL) return; - skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header); + skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr) + + dccp_hdr_ack_len); skb->h.raw = skb_push(skb, dccp_hdr_ack_len); dh = dccp_hdr(skb); @@ -607,7 +605,7 @@ static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb, dh->dccph_dport = rxdh->dccph_sport; dh->dccph_doff = dccp_hdr_ack_len / 4; dh->dccph_x = 1; - + dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq); dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq); @@ -625,7 +623,7 @@ static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb, if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { - ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0); + ip6_xmit(NULL, skb, &fl, NULL, 0); DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); return; } @@ -634,6 +632,12 @@ static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb, kfree_skb(skb); } +static void dccp_v6_reqsk_send_ack(struct sk_buff *skb, + struct request_sock *req) +{ + dccp_v6_ctl_send_ack(skb); +} + static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) { const struct dccp_hdr *dh = dccp_hdr(skb); @@ -653,6 +657,7 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) &iph->saddr, dh->dccph_sport, &iph->daddr, ntohs(dh->dccph_dport), inet6_iif(skb)); + if (nsk != NULL) { if (nsk->sk_state != DCCP_TIME_WAIT) { bh_lock_sock(nsk); @@ -673,7 +678,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 __u32 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; @@ -681,17 +686,17 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) return dccp_v4_conn_request(sk, skb); if (!ipv6_unicast_destination(skb)) - goto drop; + goto drop; 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... + * There are no SYN attacks on IPv6, yet... */ if (inet_csk_reqsk_queue_is_full(sk)) - goto drop; + goto drop; if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) goto drop; @@ -708,7 +713,8 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) ireq = inet_rsk(req); ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr); ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr); - req->rcv_wnd = dccp_feat_default_sequence_window; + req->rcv_wnd = 100; /* Fake, option parsing will get the + right value */ ireq6->pktopts = NULL; if (ipv6_opt_accepted(sk, skb) || @@ -724,7 +730,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL) ireq6->iif = inet6_iif(skb); - /* + /* * Step 3: Process LISTEN state * * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie @@ -768,8 +774,9 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, /* * v6 mapped */ + newsk = dccp_v4_request_recv_sock(sk, skb, req, dst); - if (newsk == NULL) + if (newsk == NULL) return NULL; newdp6 = (struct dccp6_sock *)newsk; @@ -815,9 +822,9 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, if (sk_acceptq_is_full(sk)) goto out_overflow; - if (np->rxopt.bits.osrcrt == 2 && opt == NULL && ireq6->pktopts) { - const struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts); - + if (np->rxopt.bits.osrcrt == 2 && + opt == NULL && ireq6->pktopts) { + struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts); if (rxopt->srcrt) opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr *)(ireq6->pktopts->nh.raw + @@ -831,9 +838,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, memset(&fl, 0, sizeof(fl)); fl.proto = IPPROTO_DCCP; ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); - if (opt != NULL && opt->srcrt != NULL) { - const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; - + if (opt && opt->srcrt) { + struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; ipv6_addr_copy(&final, &fl.fl6_dst); ipv6_addr_copy(&fl.fl6_dst, rt0->addr); final_p = &final; @@ -851,7 +857,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0) goto out; - } + } newsk = dccp_create_openreq_child(sk, req, skb); if (newsk == NULL) @@ -863,9 +869,10 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, * comment in that function for the gory details. -acme */ - __ip6_dst_store(newsk, dst, NULL); - newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM | - NETIF_F_TSO); + ip6_dst_store(newsk, dst, NULL); + newsk->sk_route_caps = dst->dev->features & + ~(NETIF_F_IP_CSUM | NETIF_F_TSO); + newdp6 = (struct dccp6_sock *)newsk; newinet = inet_sk(newsk); newinet->pinet6 = &newdp6->inet6; @@ -879,7 +886,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, ipv6_addr_copy(&newnp->rcv_saddr, &ireq6->loc_addr); newsk->sk_bound_dev_if = ireq6->iif; - /* Now IPv6 options... + /* Now IPv6 options... First: no IPv4 options. */ @@ -901,20 +908,20 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, newnp->mcast_oif = inet6_iif(skb); newnp->mcast_hops = skb->nh.ipv6h->hop_limit; - /* - * Clone native IPv6 options from listening socket (if any) - * - * Yes, keeping reference count would be much more clever, but we make - * one more one thing there: reattach optmem to newsk. + /* Clone native IPv6 options from listening socket (if any) + + Yes, keeping reference count would be much more clever, + but we make one more one thing there: reattach optmem + to newsk. */ - if (opt != NULL) { + if (opt) { newnp->opt = ipv6_dup_options(newsk, opt); if (opt != np->opt) sock_kfree_s(sk, opt, opt->tot_len); } inet_csk(newsk)->icsk_ext_hdr_len = 0; - if (newnp->opt != NULL) + if (newnp->opt) inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + newnp->opt->opt_flen); @@ -931,7 +938,7 @@ out_overflow: NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS); out: NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS); - if (opt != NULL && opt != np->opt) + if (opt && opt != np->opt) sock_kfree_s(sk, opt, opt->tot_len); dst_release(dst); return NULL; @@ -965,8 +972,8 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) goto discard; /* - * socket locking is here for SMP purposes as backlog rcv is currently - * called with bh processing disabled. + * socket locking is here for SMP purposes as backlog rcv + * is currently called with bh processing disabled. */ /* Do Stevens' IPV6_PKTOPTIONS. @@ -991,20 +998,20 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; } - if (sk->sk_state == DCCP_LISTEN) { + if (sk->sk_state == DCCP_LISTEN) { struct sock *nsk = dccp_v6_hnd_req(sk, skb); - - if (nsk == NULL) + if (!nsk) goto discard; + /* * Queue it on the new socket if the new socket is active, * 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) + if (opt_skb) __kfree_skb(opt_skb); return 0; } @@ -1017,7 +1024,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) reset: dccp_v6_ctl_send_reset(skb); discard: - if (opt_skb != NULL) + if (opt_skb) __kfree_skb(opt_skb); kfree_skb(skb); return 0; @@ -1050,7 +1057,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb) dh->dccph_sport, &skb->nh.ipv6h->daddr, ntohs(dh->dccph_dport), inet6_iif(skb)); - /* + /* * Step 2: * If no socket ... * Generate Reset(No Connection) unless P.type == Reset @@ -1059,14 +1066,15 @@ static int dccp_v6_rcv(struct sk_buff **pskb) if (sk == NULL) goto no_dccp_socket; - /* + /* * Step 2: * ... or S.state == TIMEWAIT, * Generate Reset(No Connection) unless P.type == Reset * Drop packet and return */ + if (sk->sk_state == DCCP_TIME_WAIT) - goto do_time_wait; + goto do_time_wait; if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; @@ -1105,40 +1113,32 @@ do_time_wait: } static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = { - .queue_xmit = inet6_csk_xmit, - .send_check = dccp_v6_send_check, - .rebuild_header = inet6_sk_rebuild_header, - .conn_request = dccp_v6_conn_request, - .syn_recv_sock = dccp_v6_request_recv_sock, - .net_header_len = sizeof(struct ipv6hdr), - .setsockopt = ipv6_setsockopt, - .getsockopt = ipv6_getsockopt, - .addr2sockaddr = inet6_csk_addr2sockaddr, - .sockaddr_len = sizeof(struct sockaddr_in6), -#ifdef CONFIG_COMPAT - .compat_setsockopt = compat_ipv6_setsockopt, - .compat_getsockopt = compat_ipv6_getsockopt, -#endif + .queue_xmit = inet6_csk_xmit, + .send_check = dccp_v6_send_check, + .rebuild_header = inet6_sk_rebuild_header, + .conn_request = dccp_v6_conn_request, + .syn_recv_sock = dccp_v6_request_recv_sock, + .net_header_len = sizeof(struct ipv6hdr), + .setsockopt = ipv6_setsockopt, + .getsockopt = ipv6_getsockopt, + .addr2sockaddr = inet6_csk_addr2sockaddr, + .sockaddr_len = sizeof(struct sockaddr_in6) }; /* * DCCP over IPv4 via INET6 API */ static struct inet_connection_sock_af_ops dccp_ipv6_mapped = { - .queue_xmit = ip_queue_xmit, - .send_check = dccp_v4_send_check, - .rebuild_header = inet_sk_rebuild_header, - .conn_request = dccp_v6_conn_request, - .syn_recv_sock = dccp_v6_request_recv_sock, - .net_header_len = sizeof(struct iphdr), - .setsockopt = ipv6_setsockopt, - .getsockopt = ipv6_getsockopt, - .addr2sockaddr = inet6_csk_addr2sockaddr, - .sockaddr_len = sizeof(struct sockaddr_in6), -#ifdef CONFIG_COMPAT - .compat_setsockopt = compat_ipv6_setsockopt, - .compat_getsockopt = compat_ipv6_getsockopt, -#endif + .queue_xmit = ip_queue_xmit, + .send_check = dccp_v4_send_check, + .rebuild_header = inet_sk_rebuild_header, + .conn_request = dccp_v6_conn_request, + .syn_recv_sock = dccp_v6_request_recv_sock, + .net_header_len = sizeof(struct iphdr), + .setsockopt = ipv6_setsockopt, + .getsockopt = ipv6_getsockopt, + .addr2sockaddr = inet6_csk_addr2sockaddr, + .sockaddr_len = sizeof(struct sockaddr_in6) }; /* NOTE: A lot of things set to zero explicitly by call to @@ -1146,83 +1146,71 @@ static struct inet_connection_sock_af_ops dccp_ipv6_mapped = { */ static int dccp_v6_init_sock(struct sock *sk) { - static __u8 dccp_v6_ctl_sock_initialized; - int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized); + int err = dccp_v4_init_sock(sk); - if (err == 0) { - if (unlikely(!dccp_v6_ctl_sock_initialized)) - dccp_v6_ctl_sock_initialized = 1; + if (err == 0) inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops; - } return err; } static int dccp_v6_destroy_sock(struct sock *sk) { - dccp_destroy_sock(sk); + dccp_v4_destroy_sock(sk); return inet6_destroy_sock(sk); } static struct proto dccp_v6_prot = { - .name = "DCCPv6", - .owner = THIS_MODULE, - .close = dccp_close, - .connect = dccp_v6_connect, - .disconnect = dccp_disconnect, - .ioctl = dccp_ioctl, - .init = dccp_v6_init_sock, - .setsockopt = dccp_setsockopt, - .getsockopt = dccp_getsockopt, - .sendmsg = dccp_sendmsg, - .recvmsg = dccp_recvmsg, - .backlog_rcv = dccp_v6_do_rcv, - .hash = dccp_v6_hash, - .unhash = dccp_unhash, - .accept = inet_csk_accept, - .get_port = dccp_v6_get_port, - .shutdown = dccp_shutdown, - .destroy = dccp_v6_destroy_sock, - .orphan_count = &dccp_orphan_count, - .max_header = MAX_DCCP_HEADER, - .obj_size = sizeof(struct dccp6_sock), - .rsk_prot = &dccp6_request_sock_ops, - .twsk_prot = &dccp6_timewait_sock_ops, -#ifdef CONFIG_COMPAT - .compat_setsockopt = compat_dccp_setsockopt, - .compat_getsockopt = compat_dccp_getsockopt, -#endif + .name = "DCCPv6", + .owner = THIS_MODULE, + .close = dccp_close, + .connect = dccp_v6_connect, + .disconnect = dccp_disconnect, + .ioctl = dccp_ioctl, + .init = dccp_v6_init_sock, + .setsockopt = dccp_setsockopt, + .getsockopt = dccp_getsockopt, + .sendmsg = dccp_sendmsg, + .recvmsg = dccp_recvmsg, + .backlog_rcv = dccp_v6_do_rcv, + .hash = dccp_v6_hash, + .unhash = dccp_unhash, + .accept = inet_csk_accept, + .get_port = dccp_v6_get_port, + .shutdown = dccp_shutdown, + .destroy = dccp_v6_destroy_sock, + .orphan_count = &dccp_orphan_count, + .max_header = MAX_DCCP_HEADER, + .obj_size = sizeof(struct dccp6_sock), + .rsk_prot = &dccp6_request_sock_ops, + .twsk_prot = &dccp6_timewait_sock_ops, }; static struct inet6_protocol dccp_v6_protocol = { - .handler = dccp_v6_rcv, - .err_handler = dccp_v6_err, - .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL, + .handler = dccp_v6_rcv, + .err_handler = dccp_v6_err, + .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL, }; static struct proto_ops inet6_dccp_ops = { - .family = PF_INET6, - .owner = THIS_MODULE, - .release = inet6_release, - .bind = inet6_bind, - .connect = inet_stream_connect, - .socketpair = sock_no_socketpair, - .accept = inet_accept, - .getname = inet6_getname, - .poll = dccp_poll, - .ioctl = inet6_ioctl, - .listen = inet_dccp_listen, - .shutdown = inet_shutdown, - .setsockopt = sock_common_setsockopt, - .getsockopt = sock_common_getsockopt, - .sendmsg = inet_sendmsg, - .recvmsg = sock_common_recvmsg, - .mmap = sock_no_mmap, - .sendpage = sock_no_sendpage, -#ifdef CONFIG_COMPAT - .compat_setsockopt = compat_sock_common_setsockopt, - .compat_getsockopt = compat_sock_common_getsockopt, -#endif + .family = PF_INET6, + .owner = THIS_MODULE, + .release = inet6_release, + .bind = inet6_bind, + .connect = inet_stream_connect, + .socketpair = sock_no_socketpair, + .accept = inet_accept, + .getname = inet6_getname, + .poll = dccp_poll, + .ioctl = inet6_ioctl, + .listen = inet_dccp_listen, + .shutdown = inet_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, + .sendmsg = inet_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, }; static struct inet_protosw dccp_v6_protosw = { @@ -1246,16 +1234,8 @@ static int __init dccp_v6_init(void) goto out_unregister_proto; inet6_register_protosw(&dccp_v6_protosw); - - err = inet_csk_ctl_sock_create(&dccp_v6_ctl_socket, PF_INET6, - SOCK_DCCP, IPPROTO_DCCP); - if (err != 0) - goto out_unregister_protosw; out: return err; -out_unregister_protosw: - inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP); - inet6_unregister_protosw(&dccp_v6_protosw); out_unregister_proto: proto_unregister(&dccp_v6_prot); goto out;