aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-03-22 13:22:25 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-23 16:52:26 -0400
commit52036a43055b3aae6659841c45a809af2ad4535e (patch)
treeaf400c0966ec6eda25fe182acb7f457d2c403be7 /net/dccp
parent85645bab57bfc6b0b43bb96a301c4ef83925c07d (diff)
ipv6: dccp: handle ICMP messages on DCCP_NEW_SYN_RECV request sockets
dccp_v6_err() can restrict lookups to ehash table, and not to listeners. Note this patch creates the infrastructure, but this means that ICMP messages for request sockets are ignored until complete conversion. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/ipv6.c41
1 files changed, 8 insertions, 33 deletions
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 69d8f13895ba..9d0551092c6c 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -85,11 +85,12 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
85 return; 85 return;
86 } 86 }
87 87
88 sk = inet6_lookup(net, &dccp_hashinfo, 88 sk = __inet6_lookup_established(net, &dccp_hashinfo,
89 &hdr->daddr, dh->dccph_dport, 89 &hdr->daddr, dh->dccph_dport,
90 &hdr->saddr, dh->dccph_sport, inet6_iif(skb)); 90 &hdr->saddr, ntohs(dh->dccph_sport),
91 inet6_iif(skb));
91 92
92 if (sk == NULL) { 93 if (!sk) {
93 ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), 94 ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
94 ICMP6_MIB_INERRORS); 95 ICMP6_MIB_INERRORS);
95 return; 96 return;
@@ -99,6 +100,9 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
99 inet_twsk_put(inet_twsk(sk)); 100 inet_twsk_put(inet_twsk(sk));
100 return; 101 return;
101 } 102 }
103 seq = dccp_hdr_seq(dh);
104 if (sk->sk_state == DCCP_NEW_SYN_RECV)
105 return dccp_req_err(sk, seq);
102 106
103 bh_lock_sock(sk); 107 bh_lock_sock(sk);
104 if (sock_owned_by_user(sk)) 108 if (sock_owned_by_user(sk))
@@ -108,7 +112,6 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
108 goto out; 112 goto out;
109 113
110 dp = dccp_sk(sk); 114 dp = dccp_sk(sk);
111 seq = dccp_hdr_seq(dh);
112 if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) && 115 if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
113 !between48(seq, dp->dccps_awl, dp->dccps_awh)) { 116 !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
114 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); 117 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
@@ -149,34 +152,6 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
149 152
150 /* Might be for an request_sock */ 153 /* Might be for an request_sock */
151 switch (sk->sk_state) { 154 switch (sk->sk_state) {
152 struct request_sock *req;
153 case DCCP_LISTEN:
154 if (sock_owned_by_user(sk))
155 goto out;
156
157 req = inet6_csk_search_req(sk, dh->dccph_dport,
158 &hdr->daddr, &hdr->saddr,
159 inet6_iif(skb));
160 if (!req)
161 goto out;
162
163 /*
164 * ICMPs are not backlogged, hence we cannot get an established
165 * socket here.
166 */
167 WARN_ON(req->sk != NULL);
168
169 if (!between48(seq, dccp_rsk(req)->dreq_iss,
170 dccp_rsk(req)->dreq_gss)) {
171 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
172 reqsk_put(req);
173 goto out;
174 }
175
176 inet_csk_reqsk_queue_drop(sk, req);
177 reqsk_put(req);
178 goto out;
179
180 case DCCP_REQUESTING: 155 case DCCP_REQUESTING:
181 case DCCP_RESPOND: /* Cannot happen. 156 case DCCP_RESPOND: /* Cannot happen.
182 It can, it SYNs are crossed. --ANK */ 157 It can, it SYNs are crossed. --ANK */