|
@@ -195,6 +195,32 @@ static void dccp_do_redirect(struct sk_buff *skb, struct sock *sk)
|
|
dst->ops->redirect(dst, sk, skb);
|
|
dst->ops->redirect(dst, sk, skb);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void dccp_req_err(struct sock *sk, u64 seq)
|
|
|
|
+ {
|
|
|
|
+ struct request_sock *req = inet_reqsk(sk);
|
|
|
|
+ struct net *net = sock_net(sk);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * ICMPs are not backlogged, hence we cannot get an established
|
|
|
|
+ * socket here.
|
|
|
|
+ */
|
|
|
|
+ WARN_ON(req->sk);
|
|
|
|
+
|
|
|
|
+ if (!between48(seq, dccp_rsk(req)->dreq_iss, dccp_rsk(req)->dreq_gss)) {
|
|
|
|
+ NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
|
|
|
|
+ } else {
|
|
|
|
+ /*
|
|
|
|
+ * Still in RESPOND, just remove it silently.
|
|
|
|
+ * There is no good way to pass the error to the newly
|
|
|
|
+ * created socket, and POSIX does not want network
|
|
|
|
+ * errors returned from accept().
|
|
|
|
+ */
|
|
|
|
+ inet_csk_reqsk_queue_drop(req->rsk_listener, req);
|
|
|
|
+ }
|
|
|
|
+ reqsk_put(req);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(dccp_req_err);
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* This routine is called by the ICMP module when it gets some sort of error
|
|
* This routine is called by the ICMP module when it gets some sort of error
|
|
* condition. If err < 0 then the socket should be closed and the error
|
|
* condition. If err < 0 then the socket should be closed and the error
|
|
@@ -227,10 +253,11 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- sk = inet_lookup(net, &dccp_hashinfo,
|
|
|
|
- iph->daddr, dh->dccph_dport,
|
|
|
|
- iph->saddr, dh->dccph_sport, inet_iif(skb));
|
|
|
|
- if (sk == NULL) {
|
|
|
|
|
|
+ sk = __inet_lookup_established(net, &dccp_hashinfo,
|
|
|
|
+ iph->daddr, dh->dccph_dport,
|
|
|
|
+ iph->saddr, ntohs(dh->dccph_sport),
|
|
|
|
+ inet_iif(skb));
|
|
|
|
+ if (!sk) {
|
|
ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
|
|
ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -239,6 +266,9 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
|
|
inet_twsk_put(inet_twsk(sk));
|
|
inet_twsk_put(inet_twsk(sk));
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+ seq = dccp_hdr_seq(dh);
|
|
|
|
+ if (sk->sk_state == DCCP_NEW_SYN_RECV)
|
|
|
|
+ return dccp_req_err(sk, seq);
|
|
|
|
|
|
bh_lock_sock(sk);
|
|
bh_lock_sock(sk);
|
|
/* If too many ICMPs get dropped on busy
|
|
/* If too many ICMPs get dropped on busy
|
|
@@ -251,7 +281,6 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
dp = dccp_sk(sk);
|
|
dp = dccp_sk(sk);
|
|
- seq = dccp_hdr_seq(dh);
|
|
|
|
if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
|
|
if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
|
|
!between48(seq, dp->dccps_awl, dp->dccps_awh)) {
|
|
!between48(seq, dp->dccps_awl, dp->dccps_awh)) {
|
|
NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
|
|
NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
|
|
@@ -288,37 +317,6 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
|
|
}
|
|
}
|
|
|
|
|
|
switch (sk->sk_state) {
|
|
switch (sk->sk_state) {
|
|
- struct request_sock *req;
|
|
|
|
- case DCCP_LISTEN:
|
|
|
|
- if (sock_owned_by_user(sk))
|
|
|
|
- goto out;
|
|
|
|
- req = inet_csk_search_req(sk, dh->dccph_dport,
|
|
|
|
- iph->daddr, iph->saddr);
|
|
|
|
- if (!req)
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * ICMPs are not backlogged, hence we cannot get an established
|
|
|
|
- * socket here.
|
|
|
|
- */
|
|
|
|
- WARN_ON(req->sk);
|
|
|
|
-
|
|
|
|
- if (!between48(seq, dccp_rsk(req)->dreq_iss,
|
|
|
|
- dccp_rsk(req)->dreq_gss)) {
|
|
|
|
- NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
|
|
|
|
- reqsk_put(req);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
- /*
|
|
|
|
- * Still in RESPOND, just remove it silently.
|
|
|
|
- * There is no good way to pass the error to the newly
|
|
|
|
- * created socket, and POSIX does not want network
|
|
|
|
- * errors returned from accept().
|
|
|
|
- */
|
|
|
|
- inet_csk_reqsk_queue_drop(sk, req);
|
|
|
|
- reqsk_put(req);
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
case DCCP_REQUESTING:
|
|
case DCCP_REQUESTING:
|
|
case DCCP_RESPOND:
|
|
case DCCP_RESPOND:
|
|
if (!sock_owned_by_user(sk)) {
|
|
if (!sock_owned_by_user(sk)) {
|