aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/dccp/input.c48
1 files changed, 39 insertions, 9 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 3560a2a875a0..1ce101062824 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -58,6 +58,42 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb)
58 dccp_send_close(sk, 0); 58 dccp_send_close(sk, 0);
59} 59}
60 60
61static u8 dccp_reset_code_convert(const u8 code)
62{
63 const u8 error_code[] = {
64 [DCCP_RESET_CODE_CLOSED] = 0, /* normal termination */
65 [DCCP_RESET_CODE_UNSPECIFIED] = 0, /* nothing known */
66 [DCCP_RESET_CODE_ABORTED] = ECONNRESET,
67
68 [DCCP_RESET_CODE_NO_CONNECTION] = ECONNREFUSED,
69 [DCCP_RESET_CODE_CONNECTION_REFUSED] = ECONNREFUSED,
70 [DCCP_RESET_CODE_TOO_BUSY] = EUSERS,
71 [DCCP_RESET_CODE_AGGRESSION_PENALTY] = EDQUOT,
72
73 [DCCP_RESET_CODE_PACKET_ERROR] = ENOMSG,
74 [DCCP_RESET_CODE_BAD_INIT_COOKIE] = EBADR,
75 [DCCP_RESET_CODE_BAD_SERVICE_CODE] = EBADRQC,
76 [DCCP_RESET_CODE_OPTION_ERROR] = EILSEQ,
77 [DCCP_RESET_CODE_MANDATORY_ERROR] = EOPNOTSUPP,
78 };
79
80 return code >= DCCP_MAX_RESET_CODES ? 0 : error_code[code];
81}
82
83static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb)
84{
85 u8 err = dccp_reset_code_convert(dccp_hdr_reset(skb)->dccph_reset_code);
86
87 sk->sk_err = err;
88
89 /* Queue the equivalent of TCP fin so that dccp_recvmsg exits the loop */
90 dccp_fin(sk, skb);
91
92 if (err && !sock_flag(sk, SOCK_DEAD))
93 sk_wake_async(sk, 0, POLL_ERR);
94 dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
95}
96
61static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) 97static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
62{ 98{
63 struct dccp_sock *dp = dccp_sk(sk); 99 struct dccp_sock *dp = dccp_sk(sk);
@@ -191,9 +227,8 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
191 * S.state := TIMEWAIT 227 * S.state := TIMEWAIT
192 * Set TIMEWAIT timer 228 * Set TIMEWAIT timer
193 * Drop packet and return 229 * Drop packet and return
194 */ 230 */
195 dccp_fin(sk, skb); 231 dccp_rcv_reset(sk, skb);
196 dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
197 return 0; 232 return 0;
198 case DCCP_PKT_CLOSEREQ: 233 case DCCP_PKT_CLOSEREQ:
199 dccp_rcv_closereq(sk, skb); 234 dccp_rcv_closereq(sk, skb);
@@ -521,12 +556,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
521 * Drop packet and return 556 * Drop packet and return
522 */ 557 */
523 if (dh->dccph_type == DCCP_PKT_RESET) { 558 if (dh->dccph_type == DCCP_PKT_RESET) {
524 /* 559 dccp_rcv_reset(sk, skb);
525 * Queue the equivalent of TCP fin so that dccp_recvmsg
526 * exits the loop
527 */
528 dccp_fin(sk, skb);
529 dccp_time_wait(sk, DCCP_TIME_WAIT, 0);
530 return 0; 560 return 0;
531 /* 561 /*
532 * Step 7: Check for unexpected packet types 562 * Step 7: Check for unexpected packet types