17c657876SArnaldo Carvalho de Melo /* 27c657876SArnaldo Carvalho de Melo * net/dccp/input.c 37c657876SArnaldo Carvalho de Melo * 47c657876SArnaldo Carvalho de Melo * An implementation of the DCCP protocol 57c657876SArnaldo Carvalho de Melo * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 67c657876SArnaldo Carvalho de Melo * 77c657876SArnaldo Carvalho de Melo * This program is free software; you can redistribute it and/or 87c657876SArnaldo Carvalho de Melo * modify it under the terms of the GNU General Public License 97c657876SArnaldo Carvalho de Melo * as published by the Free Software Foundation; either version 107c657876SArnaldo Carvalho de Melo * 2 of the License, or (at your option) any later version. 117c657876SArnaldo Carvalho de Melo */ 127c657876SArnaldo Carvalho de Melo 137c657876SArnaldo Carvalho de Melo #include <linux/config.h> 147c657876SArnaldo Carvalho de Melo #include <linux/dccp.h> 157c657876SArnaldo Carvalho de Melo #include <linux/skbuff.h> 167c657876SArnaldo Carvalho de Melo 177c657876SArnaldo Carvalho de Melo #include <net/sock.h> 187c657876SArnaldo Carvalho de Melo 197c657876SArnaldo Carvalho de Melo #include "ccid.h" 207c657876SArnaldo Carvalho de Melo #include "dccp.h" 217c657876SArnaldo Carvalho de Melo 227c657876SArnaldo Carvalho de Melo static void dccp_fin(struct sock *sk, struct sk_buff *skb) 237c657876SArnaldo Carvalho de Melo { 247c657876SArnaldo Carvalho de Melo sk->sk_shutdown |= RCV_SHUTDOWN; 257c657876SArnaldo Carvalho de Melo sock_set_flag(sk, SOCK_DONE); 267c657876SArnaldo Carvalho de Melo __skb_pull(skb, dccp_hdr(skb)->dccph_doff * 4); 277c657876SArnaldo Carvalho de Melo __skb_queue_tail(&sk->sk_receive_queue, skb); 287c657876SArnaldo Carvalho de Melo skb_set_owner_r(skb, sk); 297c657876SArnaldo Carvalho de Melo sk->sk_data_ready(sk, 0); 307c657876SArnaldo Carvalho de Melo } 317c657876SArnaldo Carvalho de Melo 327c657876SArnaldo Carvalho de Melo static void dccp_rcv_close(struct sock *sk, struct sk_buff *skb) 337c657876SArnaldo Carvalho de Melo { 347c657876SArnaldo Carvalho de Melo switch (sk->sk_state) { 357c657876SArnaldo Carvalho de Melo case DCCP_PARTOPEN: 367c657876SArnaldo Carvalho de Melo case DCCP_OPEN: 377c657876SArnaldo Carvalho de Melo dccp_v4_send_reset(sk, DCCP_RESET_CODE_CLOSED); 387c657876SArnaldo Carvalho de Melo dccp_fin(sk, skb); 397c657876SArnaldo Carvalho de Melo dccp_set_state(sk, DCCP_CLOSED); 407c657876SArnaldo Carvalho de Melo break; 417c657876SArnaldo Carvalho de Melo } 427c657876SArnaldo Carvalho de Melo } 437c657876SArnaldo Carvalho de Melo 447c657876SArnaldo Carvalho de Melo static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb) 457c657876SArnaldo Carvalho de Melo { 467c657876SArnaldo Carvalho de Melo /* 477c657876SArnaldo Carvalho de Melo * Step 7: Check for unexpected packet types 487c657876SArnaldo Carvalho de Melo * If (S.is_server and P.type == CloseReq) 497c657876SArnaldo Carvalho de Melo * Send Sync packet acknowledging P.seqno 507c657876SArnaldo Carvalho de Melo * Drop packet and return 517c657876SArnaldo Carvalho de Melo */ 527c657876SArnaldo Carvalho de Melo if (dccp_sk(sk)->dccps_role != DCCP_ROLE_CLIENT) { 53e92ae93aSArnaldo Carvalho de Melo dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC); 547c657876SArnaldo Carvalho de Melo return; 557c657876SArnaldo Carvalho de Melo } 567c657876SArnaldo Carvalho de Melo 577c657876SArnaldo Carvalho de Melo switch (sk->sk_state) { 587c657876SArnaldo Carvalho de Melo case DCCP_PARTOPEN: 597c657876SArnaldo Carvalho de Melo case DCCP_OPEN: 607c657876SArnaldo Carvalho de Melo dccp_set_state(sk, DCCP_CLOSING); 617c657876SArnaldo Carvalho de Melo dccp_send_close(sk); 627c657876SArnaldo Carvalho de Melo break; 637c657876SArnaldo Carvalho de Melo } 647c657876SArnaldo Carvalho de Melo } 657c657876SArnaldo Carvalho de Melo 667c657876SArnaldo Carvalho de Melo static inline void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) 677c657876SArnaldo Carvalho de Melo { 687c657876SArnaldo Carvalho de Melo struct dccp_sock *dp = dccp_sk(sk); 697c657876SArnaldo Carvalho de Melo 707c657876SArnaldo Carvalho de Melo if (dp->dccps_options.dccpo_send_ack_vector) 717c657876SArnaldo Carvalho de Melo dccp_ackpkts_check_rcv_ackno(dp->dccps_hc_rx_ackpkts, sk, 727c657876SArnaldo Carvalho de Melo DCCP_SKB_CB(skb)->dccpd_ack_seq); 737c657876SArnaldo Carvalho de Melo } 747c657876SArnaldo Carvalho de Melo 757c657876SArnaldo Carvalho de Melo static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) 767c657876SArnaldo Carvalho de Melo { 777c657876SArnaldo Carvalho de Melo const struct dccp_hdr *dh = dccp_hdr(skb); 787c657876SArnaldo Carvalho de Melo struct dccp_sock *dp = dccp_sk(sk); 79e92ae93aSArnaldo Carvalho de Melo u64 lswl, lawl; 807c657876SArnaldo Carvalho de Melo 817c657876SArnaldo Carvalho de Melo /* 827c657876SArnaldo Carvalho de Melo * Step 5: Prepare sequence numbers for Sync 837c657876SArnaldo Carvalho de Melo * If P.type == Sync or P.type == SyncAck, 847c657876SArnaldo Carvalho de Melo * If S.AWL <= P.ackno <= S.AWH and P.seqno >= S.SWL, 857c657876SArnaldo Carvalho de Melo * / * P is valid, so update sequence number variables 867c657876SArnaldo Carvalho de Melo * accordingly. After this update, P will pass the tests 877c657876SArnaldo Carvalho de Melo * in Step 6. A SyncAck is generated if necessary in 887c657876SArnaldo Carvalho de Melo * Step 15 * / 897c657876SArnaldo Carvalho de Melo * Update S.GSR, S.SWL, S.SWH 907c657876SArnaldo Carvalho de Melo * Otherwise, 917c657876SArnaldo Carvalho de Melo * Drop packet and return 927c657876SArnaldo Carvalho de Melo */ 937c657876SArnaldo Carvalho de Melo if (dh->dccph_type == DCCP_PKT_SYNC || 947c657876SArnaldo Carvalho de Melo dh->dccph_type == DCCP_PKT_SYNCACK) { 957690af3fSArnaldo Carvalho de Melo if (between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, 967690af3fSArnaldo Carvalho de Melo dp->dccps_awl, dp->dccps_awh) && 977c657876SArnaldo Carvalho de Melo !before48(DCCP_SKB_CB(skb)->dccpd_seq, dp->dccps_swl)) 987c657876SArnaldo Carvalho de Melo dccp_update_gsr(sk, DCCP_SKB_CB(skb)->dccpd_seq); 997c657876SArnaldo Carvalho de Melo else 1007c657876SArnaldo Carvalho de Melo return -1; 101e92ae93aSArnaldo Carvalho de Melo } 102e92ae93aSArnaldo Carvalho de Melo 1037c657876SArnaldo Carvalho de Melo /* 1047c657876SArnaldo Carvalho de Melo * Step 6: Check sequence numbers 1057c657876SArnaldo Carvalho de Melo * Let LSWL = S.SWL and LAWL = S.AWL 1067c657876SArnaldo Carvalho de Melo * If P.type == CloseReq or P.type == Close or P.type == Reset, 1077c657876SArnaldo Carvalho de Melo * LSWL := S.GSR + 1, LAWL := S.GAR 1087c657876SArnaldo Carvalho de Melo * If LSWL <= P.seqno <= S.SWH 1097c657876SArnaldo Carvalho de Melo * and (P.ackno does not exist or LAWL <= P.ackno <= S.AWH), 1107c657876SArnaldo Carvalho de Melo * Update S.GSR, S.SWL, S.SWH 1117c657876SArnaldo Carvalho de Melo * If P.type != Sync, 1127c657876SArnaldo Carvalho de Melo * Update S.GAR 1137c657876SArnaldo Carvalho de Melo * Otherwise, 1147c657876SArnaldo Carvalho de Melo * Send Sync packet acknowledging P.seqno 1157c657876SArnaldo Carvalho de Melo * Drop packet and return 1167c657876SArnaldo Carvalho de Melo */ 117e92ae93aSArnaldo Carvalho de Melo lswl = dp->dccps_swl; 118e92ae93aSArnaldo Carvalho de Melo lawl = dp->dccps_awl; 119e92ae93aSArnaldo Carvalho de Melo 120e92ae93aSArnaldo Carvalho de Melo if (dh->dccph_type == DCCP_PKT_CLOSEREQ || 1217c657876SArnaldo Carvalho de Melo dh->dccph_type == DCCP_PKT_CLOSE || 1227c657876SArnaldo Carvalho de Melo dh->dccph_type == DCCP_PKT_RESET) { 1237c657876SArnaldo Carvalho de Melo lswl = dp->dccps_gsr; 1247c657876SArnaldo Carvalho de Melo dccp_inc_seqno(&lswl); 1257c657876SArnaldo Carvalho de Melo lawl = dp->dccps_gar; 1267c657876SArnaldo Carvalho de Melo } 1277c657876SArnaldo Carvalho de Melo 1287c657876SArnaldo Carvalho de Melo if (between48(DCCP_SKB_CB(skb)->dccpd_seq, lswl, dp->dccps_swh) && 1297c657876SArnaldo Carvalho de Melo (DCCP_SKB_CB(skb)->dccpd_ack_seq == DCCP_PKT_WITHOUT_ACK_SEQ || 1307690af3fSArnaldo Carvalho de Melo between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, 1317690af3fSArnaldo Carvalho de Melo lawl, dp->dccps_awh))) { 1327c657876SArnaldo Carvalho de Melo dccp_update_gsr(sk, DCCP_SKB_CB(skb)->dccpd_seq); 1337c657876SArnaldo Carvalho de Melo 1347c657876SArnaldo Carvalho de Melo if (dh->dccph_type != DCCP_PKT_SYNC && 1357690af3fSArnaldo Carvalho de Melo (DCCP_SKB_CB(skb)->dccpd_ack_seq != 1367690af3fSArnaldo Carvalho de Melo DCCP_PKT_WITHOUT_ACK_SEQ)) 1377c657876SArnaldo Carvalho de Melo dp->dccps_gar = DCCP_SKB_CB(skb)->dccpd_ack_seq; 1387c657876SArnaldo Carvalho de Melo } else { 139a3054d48SArnaldo Carvalho de Melo LIMIT_NETDEBUG(KERN_WARNING "DCCP: Step 6 failed for %s packet, " 140a3054d48SArnaldo Carvalho de Melo "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and " 141a3054d48SArnaldo Carvalho de Melo "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), " 142a3054d48SArnaldo Carvalho de Melo "sending SYNC...\n", 143a3054d48SArnaldo Carvalho de Melo dccp_packet_name(dh->dccph_type), 144*58e45131SDavid S. Miller (unsigned long long) lswl, 145*58e45131SDavid S. Miller (unsigned long long) 146*58e45131SDavid S. Miller DCCP_SKB_CB(skb)->dccpd_seq, 147*58e45131SDavid S. Miller (unsigned long long) dp->dccps_swh, 148a3054d48SArnaldo Carvalho de Melo (DCCP_SKB_CB(skb)->dccpd_ack_seq == 149a3054d48SArnaldo Carvalho de Melo DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" : "exists", 150*58e45131SDavid S. Miller (unsigned long long) lawl, 151*58e45131SDavid S. Miller (unsigned long long) 152*58e45131SDavid S. Miller DCCP_SKB_CB(skb)->dccpd_ack_seq, 153*58e45131SDavid S. Miller (unsigned long long) dp->dccps_awh); 154e92ae93aSArnaldo Carvalho de Melo dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC); 1557c657876SArnaldo Carvalho de Melo return -1; 1567c657876SArnaldo Carvalho de Melo } 1577c657876SArnaldo Carvalho de Melo 1587c657876SArnaldo Carvalho de Melo return 0; 1597c657876SArnaldo Carvalho de Melo } 1607c657876SArnaldo Carvalho de Melo 1617c657876SArnaldo Carvalho de Melo int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, 1627c657876SArnaldo Carvalho de Melo const struct dccp_hdr *dh, const unsigned len) 1637c657876SArnaldo Carvalho de Melo { 1647c657876SArnaldo Carvalho de Melo struct dccp_sock *dp = dccp_sk(sk); 1657c657876SArnaldo Carvalho de Melo 1667c657876SArnaldo Carvalho de Melo if (dccp_check_seqno(sk, skb)) 1677c657876SArnaldo Carvalho de Melo goto discard; 1687c657876SArnaldo Carvalho de Melo 1697c657876SArnaldo Carvalho de Melo if (dccp_parse_options(sk, skb)) 1707c657876SArnaldo Carvalho de Melo goto discard; 1717c657876SArnaldo Carvalho de Melo 1727c657876SArnaldo Carvalho de Melo if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) 1737c657876SArnaldo Carvalho de Melo dccp_event_ack_recv(sk, skb); 1747c657876SArnaldo Carvalho de Melo 1757c657876SArnaldo Carvalho de Melo /* 1767c657876SArnaldo Carvalho de Melo * FIXME: check ECN to see if we should use 1777c657876SArnaldo Carvalho de Melo * DCCP_ACKPKTS_STATE_ECN_MARKED 1787c657876SArnaldo Carvalho de Melo */ 1797c657876SArnaldo Carvalho de Melo if (dp->dccps_options.dccpo_send_ack_vector) { 1807c657876SArnaldo Carvalho de Melo struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; 1817c657876SArnaldo Carvalho de Melo 1827c657876SArnaldo Carvalho de Melo if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, 1837c657876SArnaldo Carvalho de Melo DCCP_SKB_CB(skb)->dccpd_seq, 1847c657876SArnaldo Carvalho de Melo DCCP_ACKPKTS_STATE_RECEIVED)) { 185c59eab46SArnaldo Carvalho de Melo LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable " 1867690af3fSArnaldo Carvalho de Melo "packets buffer full!\n"); 1877c657876SArnaldo Carvalho de Melo ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; 1887c657876SArnaldo Carvalho de Melo inet_csk_schedule_ack(sk); 1897690af3fSArnaldo Carvalho de Melo inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 1907690af3fSArnaldo Carvalho de Melo TCP_DELACK_MIN, 1917690af3fSArnaldo Carvalho de Melo DCCP_RTO_MAX); 1927c657876SArnaldo Carvalho de Melo goto discard; 1937c657876SArnaldo Carvalho de Melo } 1947c657876SArnaldo Carvalho de Melo 1957c657876SArnaldo Carvalho de Melo /* 1967c657876SArnaldo Carvalho de Melo * FIXME: this activation is probably wrong, have to study more 1977c657876SArnaldo Carvalho de Melo * TCP delack machinery and how it fits into DCCP draft, but 1987c657876SArnaldo Carvalho de Melo * for now it kinda "works" 8) 1997c657876SArnaldo Carvalho de Melo */ 2007c657876SArnaldo Carvalho de Melo if (!inet_csk_ack_scheduled(sk)) { 2017c657876SArnaldo Carvalho de Melo inet_csk_schedule_ack(sk); 2027690af3fSArnaldo Carvalho de Melo inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 5 * HZ, 2037690af3fSArnaldo Carvalho de Melo DCCP_RTO_MAX); 2047c657876SArnaldo Carvalho de Melo } 2057c657876SArnaldo Carvalho de Melo } 2067c657876SArnaldo Carvalho de Melo 2077c657876SArnaldo Carvalho de Melo ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); 2087c657876SArnaldo Carvalho de Melo ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); 2097c657876SArnaldo Carvalho de Melo 2107c657876SArnaldo Carvalho de Melo switch (dccp_hdr(skb)->dccph_type) { 2117c657876SArnaldo Carvalho de Melo case DCCP_PKT_DATAACK: 2127c657876SArnaldo Carvalho de Melo case DCCP_PKT_DATA: 2137c657876SArnaldo Carvalho de Melo /* 2147690af3fSArnaldo Carvalho de Melo * FIXME: check if sk_receive_queue is full, schedule DATA_DROPPED 2157690af3fSArnaldo Carvalho de Melo * option if it is. 2167c657876SArnaldo Carvalho de Melo */ 2177c657876SArnaldo Carvalho de Melo __skb_pull(skb, dh->dccph_doff * 4); 2187c657876SArnaldo Carvalho de Melo __skb_queue_tail(&sk->sk_receive_queue, skb); 2197c657876SArnaldo Carvalho de Melo skb_set_owner_r(skb, sk); 2207c657876SArnaldo Carvalho de Melo sk->sk_data_ready(sk, 0); 2217c657876SArnaldo Carvalho de Melo return 0; 2227c657876SArnaldo Carvalho de Melo case DCCP_PKT_ACK: 2237c657876SArnaldo Carvalho de Melo goto discard; 2247c657876SArnaldo Carvalho de Melo case DCCP_PKT_RESET: 2257c657876SArnaldo Carvalho de Melo /* 2267c657876SArnaldo Carvalho de Melo * Step 9: Process Reset 2277c657876SArnaldo Carvalho de Melo * If P.type == Reset, 2287c657876SArnaldo Carvalho de Melo * Tear down connection 2297c657876SArnaldo Carvalho de Melo * S.state := TIMEWAIT 2307c657876SArnaldo Carvalho de Melo * Set TIMEWAIT timer 2317c657876SArnaldo Carvalho de Melo * Drop packet and return 2327c657876SArnaldo Carvalho de Melo */ 2337c657876SArnaldo Carvalho de Melo dccp_fin(sk, skb); 2347c657876SArnaldo Carvalho de Melo dccp_time_wait(sk, DCCP_TIME_WAIT, 0); 2357c657876SArnaldo Carvalho de Melo return 0; 2367c657876SArnaldo Carvalho de Melo case DCCP_PKT_CLOSEREQ: 2377c657876SArnaldo Carvalho de Melo dccp_rcv_closereq(sk, skb); 2387c657876SArnaldo Carvalho de Melo goto discard; 2397c657876SArnaldo Carvalho de Melo case DCCP_PKT_CLOSE: 2407c657876SArnaldo Carvalho de Melo dccp_rcv_close(sk, skb); 2417c657876SArnaldo Carvalho de Melo return 0; 2427c657876SArnaldo Carvalho de Melo case DCCP_PKT_REQUEST: 2437c657876SArnaldo Carvalho de Melo /* Step 7 2447c657876SArnaldo Carvalho de Melo * or (S.is_server and P.type == Response) 2457c657876SArnaldo Carvalho de Melo * or (S.is_client and P.type == Request) 2467c657876SArnaldo Carvalho de Melo * or (S.state >= OPEN and P.type == Request 2477c657876SArnaldo Carvalho de Melo * and P.seqno >= S.OSR) 2487c657876SArnaldo Carvalho de Melo * or (S.state >= OPEN and P.type == Response 2497c657876SArnaldo Carvalho de Melo * and P.seqno >= S.OSR) 2507c657876SArnaldo Carvalho de Melo * or (S.state == RESPOND and P.type == Data), 2517c657876SArnaldo Carvalho de Melo * Send Sync packet acknowledging P.seqno 2527c657876SArnaldo Carvalho de Melo * Drop packet and return 2537c657876SArnaldo Carvalho de Melo */ 2547c657876SArnaldo Carvalho de Melo if (dp->dccps_role != DCCP_ROLE_LISTEN) 2557c657876SArnaldo Carvalho de Melo goto send_sync; 2567c657876SArnaldo Carvalho de Melo goto check_seq; 2577c657876SArnaldo Carvalho de Melo case DCCP_PKT_RESPONSE: 2587c657876SArnaldo Carvalho de Melo if (dp->dccps_role != DCCP_ROLE_CLIENT) 2597c657876SArnaldo Carvalho de Melo goto send_sync; 2607c657876SArnaldo Carvalho de Melo check_seq: 2617c657876SArnaldo Carvalho de Melo if (!before48(DCCP_SKB_CB(skb)->dccpd_seq, dp->dccps_osr)) { 2627c657876SArnaldo Carvalho de Melo send_sync: 263e92ae93aSArnaldo Carvalho de Melo dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, 264e92ae93aSArnaldo Carvalho de Melo DCCP_PKT_SYNC); 2657c657876SArnaldo Carvalho de Melo } 2667c657876SArnaldo Carvalho de Melo break; 267e92ae93aSArnaldo Carvalho de Melo case DCCP_PKT_SYNC: 268e92ae93aSArnaldo Carvalho de Melo dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, 269e92ae93aSArnaldo Carvalho de Melo DCCP_PKT_SYNCACK); 270e92ae93aSArnaldo Carvalho de Melo /* 271e92ae93aSArnaldo Carvalho de Melo * From the draft: 272e92ae93aSArnaldo Carvalho de Melo * 273e92ae93aSArnaldo Carvalho de Melo * As with DCCP-Ack packets, DCCP-Sync and DCCP-SyncAck packets 274e92ae93aSArnaldo Carvalho de Melo * MAY have non-zero-length application data areas, whose 275e92ae93aSArnaldo Carvalho de Melo * contents * receivers MUST ignore. 276e92ae93aSArnaldo Carvalho de Melo */ 277e92ae93aSArnaldo Carvalho de Melo goto discard; 2787c657876SArnaldo Carvalho de Melo } 2797c657876SArnaldo Carvalho de Melo 2807c657876SArnaldo Carvalho de Melo DCCP_INC_STATS_BH(DCCP_MIB_INERRS); 2817c657876SArnaldo Carvalho de Melo discard: 2827c657876SArnaldo Carvalho de Melo __kfree_skb(skb); 2837c657876SArnaldo Carvalho de Melo return 0; 2847c657876SArnaldo Carvalho de Melo } 2857c657876SArnaldo Carvalho de Melo 2867c657876SArnaldo Carvalho de Melo static int dccp_rcv_request_sent_state_process(struct sock *sk, 2877c657876SArnaldo Carvalho de Melo struct sk_buff *skb, 2887c657876SArnaldo Carvalho de Melo const struct dccp_hdr *dh, 2897c657876SArnaldo Carvalho de Melo const unsigned len) 2907c657876SArnaldo Carvalho de Melo { 2917c657876SArnaldo Carvalho de Melo /* 2927c657876SArnaldo Carvalho de Melo * Step 4: Prepare sequence numbers in REQUEST 2937c657876SArnaldo Carvalho de Melo * If S.state == REQUEST, 2947c657876SArnaldo Carvalho de Melo * If (P.type == Response or P.type == Reset) 2957c657876SArnaldo Carvalho de Melo * and S.AWL <= P.ackno <= S.AWH, 2967c657876SArnaldo Carvalho de Melo * / * Set sequence number variables corresponding to the 2977c657876SArnaldo Carvalho de Melo * other endpoint, so P will pass the tests in Step 6 * / 2987c657876SArnaldo Carvalho de Melo * Set S.GSR, S.ISR, S.SWL, S.SWH 2997c657876SArnaldo Carvalho de Melo * / * Response processing continues in Step 10; Reset 3007c657876SArnaldo Carvalho de Melo * processing continues in Step 9 * / 3017c657876SArnaldo Carvalho de Melo */ 3027c657876SArnaldo Carvalho de Melo if (dh->dccph_type == DCCP_PKT_RESPONSE) { 3037c657876SArnaldo Carvalho de Melo const struct inet_connection_sock *icsk = inet_csk(sk); 3047c657876SArnaldo Carvalho de Melo struct dccp_sock *dp = dccp_sk(sk); 3057c657876SArnaldo Carvalho de Melo 3067c657876SArnaldo Carvalho de Melo /* Stop the REQUEST timer */ 3077c657876SArnaldo Carvalho de Melo inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); 3087c657876SArnaldo Carvalho de Melo BUG_TRAP(sk->sk_send_head != NULL); 3097c657876SArnaldo Carvalho de Melo __kfree_skb(sk->sk_send_head); 3107c657876SArnaldo Carvalho de Melo sk->sk_send_head = NULL; 3117c657876SArnaldo Carvalho de Melo 3127690af3fSArnaldo Carvalho de Melo if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, 3137690af3fSArnaldo Carvalho de Melo dp->dccps_awl, dp->dccps_awh)) { 3147690af3fSArnaldo Carvalho de Melo dccp_pr_debug("invalid ackno: S.AWL=%llu, " 3157690af3fSArnaldo Carvalho de Melo "P.ackno=%llu, S.AWH=%llu \n", 316f6ccf554SDavid S. Miller (unsigned long long)dp->dccps_awl, 317f6ccf554SDavid S. Miller (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, 318f6ccf554SDavid S. Miller (unsigned long long)dp->dccps_awh); 3197c657876SArnaldo Carvalho de Melo goto out_invalid_packet; 3207c657876SArnaldo Carvalho de Melo } 3217c657876SArnaldo Carvalho de Melo 3227c657876SArnaldo Carvalho de Melo dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq; 32303ace394SArnaldo Carvalho de Melo dccp_update_gsr(sk, dp->dccps_isr); 32403ace394SArnaldo Carvalho de Melo /* 32503ace394SArnaldo Carvalho de Melo * SWL and AWL are initially adjusted so that they are not less than 32603ace394SArnaldo Carvalho de Melo * the initial Sequence Numbers received and sent, respectively: 32703ace394SArnaldo Carvalho de Melo * SWL := max(GSR + 1 - floor(W/4), ISR), 32803ace394SArnaldo Carvalho de Melo * AWL := max(GSS - W' + 1, ISS). 32903ace394SArnaldo Carvalho de Melo * These adjustments MUST be applied only at the beginning of the 33003ace394SArnaldo Carvalho de Melo * connection. 33103ace394SArnaldo Carvalho de Melo * 33203ace394SArnaldo Carvalho de Melo * AWL was adjusted in dccp_v4_connect -acme 33303ace394SArnaldo Carvalho de Melo */ 33403ace394SArnaldo Carvalho de Melo dccp_set_seqno(&dp->dccps_swl, 33503ace394SArnaldo Carvalho de Melo max48(dp->dccps_swl, dp->dccps_isr)); 3367c657876SArnaldo Carvalho de Melo 3377c657876SArnaldo Carvalho de Melo if (ccid_hc_rx_init(dp->dccps_hc_rx_ccid, sk) != 0 || 3387c657876SArnaldo Carvalho de Melo ccid_hc_tx_init(dp->dccps_hc_tx_ccid, sk) != 0) { 3397c657876SArnaldo Carvalho de Melo ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); 3407c657876SArnaldo Carvalho de Melo ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); 3417c657876SArnaldo Carvalho de Melo /* FIXME: send appropriate RESET code */ 3427c657876SArnaldo Carvalho de Melo goto out_invalid_packet; 3437c657876SArnaldo Carvalho de Melo } 3447c657876SArnaldo Carvalho de Melo 3457c657876SArnaldo Carvalho de Melo dccp_sync_mss(sk, dp->dccps_pmtu_cookie); 3467c657876SArnaldo Carvalho de Melo 3477c657876SArnaldo Carvalho de Melo /* 3487c657876SArnaldo Carvalho de Melo * Step 10: Process REQUEST state (second part) 3497c657876SArnaldo Carvalho de Melo * If S.state == REQUEST, 3507690af3fSArnaldo Carvalho de Melo * / * If we get here, P is a valid Response from the 3517690af3fSArnaldo Carvalho de Melo * server (see Step 4), and we should move to 3527690af3fSArnaldo Carvalho de Melo * PARTOPEN state. PARTOPEN means send an Ack, 3537690af3fSArnaldo Carvalho de Melo * don't send Data packets, retransmit Acks 3547690af3fSArnaldo Carvalho de Melo * periodically, and always include any Init Cookie 3557690af3fSArnaldo Carvalho de Melo * from the Response * / 3567c657876SArnaldo Carvalho de Melo * S.state := PARTOPEN 3577c657876SArnaldo Carvalho de Melo * Set PARTOPEN timer 3587c657876SArnaldo Carvalho de Melo * Continue with S.state == PARTOPEN 3597690af3fSArnaldo Carvalho de Melo * / * Step 12 will send the Ack completing the 3607690af3fSArnaldo Carvalho de Melo * three-way handshake * / 3617c657876SArnaldo Carvalho de Melo */ 3627c657876SArnaldo Carvalho de Melo dccp_set_state(sk, DCCP_PARTOPEN); 3637c657876SArnaldo Carvalho de Melo 3647c657876SArnaldo Carvalho de Melo /* Make sure socket is routed, for correct metrics. */ 3657c657876SArnaldo Carvalho de Melo inet_sk_rebuild_header(sk); 3667c657876SArnaldo Carvalho de Melo 3677c657876SArnaldo Carvalho de Melo if (!sock_flag(sk, SOCK_DEAD)) { 3687c657876SArnaldo Carvalho de Melo sk->sk_state_change(sk); 3697c657876SArnaldo Carvalho de Melo sk_wake_async(sk, 0, POLL_OUT); 3707c657876SArnaldo Carvalho de Melo } 3717c657876SArnaldo Carvalho de Melo 3727c657876SArnaldo Carvalho de Melo if (sk->sk_write_pending || icsk->icsk_ack.pingpong || 3737c657876SArnaldo Carvalho de Melo icsk->icsk_accept_queue.rskq_defer_accept) { 3747c657876SArnaldo Carvalho de Melo /* Save one ACK. Data will be ready after 3757c657876SArnaldo Carvalho de Melo * several ticks, if write_pending is set. 3767c657876SArnaldo Carvalho de Melo * 3777c657876SArnaldo Carvalho de Melo * It may be deleted, but with this feature tcpdumps 3787c657876SArnaldo Carvalho de Melo * look so _wonderfully_ clever, that I was not able 3797c657876SArnaldo Carvalho de Melo * to stand against the temptation 8) --ANK 3807c657876SArnaldo Carvalho de Melo */ 3817c657876SArnaldo Carvalho de Melo /* 3827c657876SArnaldo Carvalho de Melo * OK, in DCCP we can as well do a similar trick, its 3837c657876SArnaldo Carvalho de Melo * even in the draft, but there is no need for us to 3847c657876SArnaldo Carvalho de Melo * schedule an ack here, as dccp_sendmsg does this for 3857c657876SArnaldo Carvalho de Melo * us, also stated in the draft. -acme 3867c657876SArnaldo Carvalho de Melo */ 3877c657876SArnaldo Carvalho de Melo __kfree_skb(skb); 3887c657876SArnaldo Carvalho de Melo return 0; 3897c657876SArnaldo Carvalho de Melo } 3907c657876SArnaldo Carvalho de Melo dccp_send_ack(sk); 3917c657876SArnaldo Carvalho de Melo return -1; 3927c657876SArnaldo Carvalho de Melo } 3937c657876SArnaldo Carvalho de Melo 3947c657876SArnaldo Carvalho de Melo out_invalid_packet: 3957c657876SArnaldo Carvalho de Melo return 1; /* dccp_v4_do_rcv will send a reset, but... 3967690af3fSArnaldo Carvalho de Melo FIXME: the reset code should be 3977690af3fSArnaldo Carvalho de Melo DCCP_RESET_CODE_PACKET_ERROR */ 3987c657876SArnaldo Carvalho de Melo } 3997c657876SArnaldo Carvalho de Melo 4007c657876SArnaldo Carvalho de Melo static int dccp_rcv_respond_partopen_state_process(struct sock *sk, 4017c657876SArnaldo Carvalho de Melo struct sk_buff *skb, 4027c657876SArnaldo Carvalho de Melo const struct dccp_hdr *dh, 4037c657876SArnaldo Carvalho de Melo const unsigned len) 4047c657876SArnaldo Carvalho de Melo { 4057c657876SArnaldo Carvalho de Melo int queued = 0; 4067c657876SArnaldo Carvalho de Melo 4077c657876SArnaldo Carvalho de Melo switch (dh->dccph_type) { 4087c657876SArnaldo Carvalho de Melo case DCCP_PKT_RESET: 4097c657876SArnaldo Carvalho de Melo inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); 4107c657876SArnaldo Carvalho de Melo break; 4117c657876SArnaldo Carvalho de Melo case DCCP_PKT_DATAACK: 4127c657876SArnaldo Carvalho de Melo case DCCP_PKT_ACK: 4137c657876SArnaldo Carvalho de Melo /* 4147690af3fSArnaldo Carvalho de Melo * FIXME: we should be reseting the PARTOPEN (DELACK) timer 4157690af3fSArnaldo Carvalho de Melo * here but only if we haven't used the DELACK timer for 4167690af3fSArnaldo Carvalho de Melo * something else, like sending a delayed ack for a TIMESTAMP 4177690af3fSArnaldo Carvalho de Melo * echo, etc, for now were not clearing it, sending an extra 4187690af3fSArnaldo Carvalho de Melo * ACK when there is nothing else to do in DELACK is not a big 4197690af3fSArnaldo Carvalho de Melo * deal after all. 4207c657876SArnaldo Carvalho de Melo */ 4217c657876SArnaldo Carvalho de Melo 4227c657876SArnaldo Carvalho de Melo /* Stop the PARTOPEN timer */ 4237c657876SArnaldo Carvalho de Melo if (sk->sk_state == DCCP_PARTOPEN) 4247c657876SArnaldo Carvalho de Melo inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); 4257c657876SArnaldo Carvalho de Melo 4267c657876SArnaldo Carvalho de Melo dccp_sk(sk)->dccps_osr = DCCP_SKB_CB(skb)->dccpd_seq; 4277c657876SArnaldo Carvalho de Melo dccp_set_state(sk, DCCP_OPEN); 4287c657876SArnaldo Carvalho de Melo 4297c657876SArnaldo Carvalho de Melo if (dh->dccph_type == DCCP_PKT_DATAACK) { 4307c657876SArnaldo Carvalho de Melo dccp_rcv_established(sk, skb, dh, len); 4317690af3fSArnaldo Carvalho de Melo queued = 1; /* packet was queued 4327690af3fSArnaldo Carvalho de Melo (by dccp_rcv_established) */ 4337c657876SArnaldo Carvalho de Melo } 4347c657876SArnaldo Carvalho de Melo break; 4357c657876SArnaldo Carvalho de Melo } 4367c657876SArnaldo Carvalho de Melo 4377c657876SArnaldo Carvalho de Melo return queued; 4387c657876SArnaldo Carvalho de Melo } 4397c657876SArnaldo Carvalho de Melo 4407c657876SArnaldo Carvalho de Melo int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, 4417c657876SArnaldo Carvalho de Melo struct dccp_hdr *dh, unsigned len) 4427c657876SArnaldo Carvalho de Melo { 4437c657876SArnaldo Carvalho de Melo struct dccp_sock *dp = dccp_sk(sk); 4447c657876SArnaldo Carvalho de Melo const int old_state = sk->sk_state; 4457c657876SArnaldo Carvalho de Melo int queued = 0; 4467c657876SArnaldo Carvalho de Melo 4478649b0d4SArnaldo Carvalho de Melo /* 4488649b0d4SArnaldo Carvalho de Melo * Step 3: Process LISTEN state 4498649b0d4SArnaldo Carvalho de Melo * (Continuing from dccp_v4_do_rcv and dccp_v6_do_rcv) 4508649b0d4SArnaldo Carvalho de Melo * 4518649b0d4SArnaldo Carvalho de Melo * If S.state == LISTEN, 4528649b0d4SArnaldo Carvalho de Melo * If P.type == Request or P contains a valid Init Cookie 4538649b0d4SArnaldo Carvalho de Melo * option, 4548649b0d4SArnaldo Carvalho de Melo * * Must scan the packet's options to check for an Init 4558649b0d4SArnaldo Carvalho de Melo * Cookie. Only the Init Cookie is processed here, 4568649b0d4SArnaldo Carvalho de Melo * however; other options are processed in Step 8. This 4578649b0d4SArnaldo Carvalho de Melo * scan need only be performed if the endpoint uses Init 4588649b0d4SArnaldo Carvalho de Melo * Cookies * 4598649b0d4SArnaldo Carvalho de Melo * * Generate a new socket and switch to that socket * 4608649b0d4SArnaldo Carvalho de Melo * Set S := new socket for this port pair 4618649b0d4SArnaldo Carvalho de Melo * S.state = RESPOND 4628649b0d4SArnaldo Carvalho de Melo * Choose S.ISS (initial seqno) or set from Init Cookie 4638649b0d4SArnaldo Carvalho de Melo * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie 4648649b0d4SArnaldo Carvalho de Melo * Continue with S.state == RESPOND 4658649b0d4SArnaldo Carvalho de Melo * * A Response packet will be generated in Step 11 * 4668649b0d4SArnaldo Carvalho de Melo * Otherwise, 4678649b0d4SArnaldo Carvalho de Melo * Generate Reset(No Connection) unless P.type == Reset 4688649b0d4SArnaldo Carvalho de Melo * Drop packet and return 4698649b0d4SArnaldo Carvalho de Melo * 4708649b0d4SArnaldo Carvalho de Melo * NOTE: the check for the packet types is done in 4718649b0d4SArnaldo Carvalho de Melo * dccp_rcv_state_process 4728649b0d4SArnaldo Carvalho de Melo */ 4738649b0d4SArnaldo Carvalho de Melo if (sk->sk_state == DCCP_LISTEN) { 4748649b0d4SArnaldo Carvalho de Melo if (dh->dccph_type == DCCP_PKT_REQUEST) { 4758649b0d4SArnaldo Carvalho de Melo if (dccp_v4_conn_request(sk, skb) < 0) 4768649b0d4SArnaldo Carvalho de Melo return 1; 4778649b0d4SArnaldo Carvalho de Melo 4788649b0d4SArnaldo Carvalho de Melo /* FIXME: do congestion control initialization */ 4798649b0d4SArnaldo Carvalho de Melo goto discard; 4808649b0d4SArnaldo Carvalho de Melo } 4818649b0d4SArnaldo Carvalho de Melo if (dh->dccph_type == DCCP_PKT_RESET) 4828649b0d4SArnaldo Carvalho de Melo goto discard; 4838649b0d4SArnaldo Carvalho de Melo 4848649b0d4SArnaldo Carvalho de Melo /* Caller (dccp_v4_do_rcv) will send Reset(No Connection)*/ 4858649b0d4SArnaldo Carvalho de Melo return 1; 4868649b0d4SArnaldo Carvalho de Melo } 4878649b0d4SArnaldo Carvalho de Melo 4888649b0d4SArnaldo Carvalho de Melo if (sk->sk_state != DCCP_REQUESTING) { 4897c657876SArnaldo Carvalho de Melo if (dccp_check_seqno(sk, skb)) 4907c657876SArnaldo Carvalho de Melo goto discard; 4917c657876SArnaldo Carvalho de Melo 4927c657876SArnaldo Carvalho de Melo /* 4937c657876SArnaldo Carvalho de Melo * Step 8: Process options and mark acknowledgeable 4947c657876SArnaldo Carvalho de Melo */ 4957c657876SArnaldo Carvalho de Melo if (dccp_parse_options(sk, skb)) 4967c657876SArnaldo Carvalho de Melo goto discard; 4977c657876SArnaldo Carvalho de Melo 4987690af3fSArnaldo Carvalho de Melo if (DCCP_SKB_CB(skb)->dccpd_ack_seq != 4997690af3fSArnaldo Carvalho de Melo DCCP_PKT_WITHOUT_ACK_SEQ) 5007c657876SArnaldo Carvalho de Melo dccp_event_ack_recv(sk, skb); 5017c657876SArnaldo Carvalho de Melo 5027c657876SArnaldo Carvalho de Melo ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); 5037c657876SArnaldo Carvalho de Melo ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); 5047c657876SArnaldo Carvalho de Melo 5057c657876SArnaldo Carvalho de Melo /* 5067c657876SArnaldo Carvalho de Melo * FIXME: check ECN to see if we should use 5077c657876SArnaldo Carvalho de Melo * DCCP_ACKPKTS_STATE_ECN_MARKED 5087c657876SArnaldo Carvalho de Melo */ 5097c657876SArnaldo Carvalho de Melo if (dp->dccps_options.dccpo_send_ack_vector) { 5107c657876SArnaldo Carvalho de Melo if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, 5117c657876SArnaldo Carvalho de Melo DCCP_SKB_CB(skb)->dccpd_seq, 5127c657876SArnaldo Carvalho de Melo DCCP_ACKPKTS_STATE_RECEIVED)) 5137c657876SArnaldo Carvalho de Melo goto discard; 5147c657876SArnaldo Carvalho de Melo /* 5157690af3fSArnaldo Carvalho de Melo * FIXME: this activation is probably wrong, have to 5167690af3fSArnaldo Carvalho de Melo * study more TCP delack machinery and how it fits into 5177690af3fSArnaldo Carvalho de Melo * DCCP draft, but for now it kinda "works" 8) 5187c657876SArnaldo Carvalho de Melo */ 5197690af3fSArnaldo Carvalho de Melo if ((dp->dccps_hc_rx_ackpkts->dccpap_ack_seqno == 5207690af3fSArnaldo Carvalho de Melo DCCP_MAX_SEQNO + 1) && 5217c657876SArnaldo Carvalho de Melo !inet_csk_ack_scheduled(sk)) { 5227c657876SArnaldo Carvalho de Melo inet_csk_schedule_ack(sk); 5237690af3fSArnaldo Carvalho de Melo inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 5247690af3fSArnaldo Carvalho de Melo TCP_DELACK_MIN, 5257690af3fSArnaldo Carvalho de Melo DCCP_RTO_MAX); 5267c657876SArnaldo Carvalho de Melo } 5277c657876SArnaldo Carvalho de Melo } 5287c657876SArnaldo Carvalho de Melo } 5297c657876SArnaldo Carvalho de Melo 5307c657876SArnaldo Carvalho de Melo /* 5317c657876SArnaldo Carvalho de Melo * Step 9: Process Reset 5327c657876SArnaldo Carvalho de Melo * If P.type == Reset, 5337c657876SArnaldo Carvalho de Melo * Tear down connection 5347c657876SArnaldo Carvalho de Melo * S.state := TIMEWAIT 5357c657876SArnaldo Carvalho de Melo * Set TIMEWAIT timer 5367c657876SArnaldo Carvalho de Melo * Drop packet and return 5377c657876SArnaldo Carvalho de Melo */ 5387c657876SArnaldo Carvalho de Melo if (dh->dccph_type == DCCP_PKT_RESET) { 5397690af3fSArnaldo Carvalho de Melo /* 5407690af3fSArnaldo Carvalho de Melo * Queue the equivalent of TCP fin so that dccp_recvmsg 5417690af3fSArnaldo Carvalho de Melo * exits the loop 5427690af3fSArnaldo Carvalho de Melo */ 5437c657876SArnaldo Carvalho de Melo dccp_fin(sk, skb); 5447c657876SArnaldo Carvalho de Melo dccp_time_wait(sk, DCCP_TIME_WAIT, 0); 5457c657876SArnaldo Carvalho de Melo return 0; 5467c657876SArnaldo Carvalho de Melo /* 5477c657876SArnaldo Carvalho de Melo * Step 7: Check for unexpected packet types 5487c657876SArnaldo Carvalho de Melo * If (S.is_server and P.type == CloseReq) 5497c657876SArnaldo Carvalho de Melo * or (S.is_server and P.type == Response) 5507c657876SArnaldo Carvalho de Melo * or (S.is_client and P.type == Request) 5517c657876SArnaldo Carvalho de Melo * or (S.state == RESPOND and P.type == Data), 5527c657876SArnaldo Carvalho de Melo * Send Sync packet acknowledging P.seqno 5537c657876SArnaldo Carvalho de Melo * Drop packet and return 5547c657876SArnaldo Carvalho de Melo */ 5557c657876SArnaldo Carvalho de Melo } else if ((dp->dccps_role != DCCP_ROLE_CLIENT && 5567690af3fSArnaldo Carvalho de Melo (dh->dccph_type == DCCP_PKT_RESPONSE || 5577690af3fSArnaldo Carvalho de Melo dh->dccph_type == DCCP_PKT_CLOSEREQ)) || 5587c657876SArnaldo Carvalho de Melo (dp->dccps_role == DCCP_ROLE_CLIENT && 5597c657876SArnaldo Carvalho de Melo dh->dccph_type == DCCP_PKT_REQUEST) || 5607690af3fSArnaldo Carvalho de Melo (sk->sk_state == DCCP_RESPOND && 5617690af3fSArnaldo Carvalho de Melo dh->dccph_type == DCCP_PKT_DATA)) { 562e92ae93aSArnaldo Carvalho de Melo dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, 563e92ae93aSArnaldo Carvalho de Melo DCCP_PKT_SYNC); 5647c657876SArnaldo Carvalho de Melo goto discard; 5657c657876SArnaldo Carvalho de Melo } 5667c657876SArnaldo Carvalho de Melo 5677c657876SArnaldo Carvalho de Melo switch (sk->sk_state) { 5687c657876SArnaldo Carvalho de Melo case DCCP_CLOSED: 5697c657876SArnaldo Carvalho de Melo return 1; 5707c657876SArnaldo Carvalho de Melo 5717c657876SArnaldo Carvalho de Melo case DCCP_REQUESTING: 5727c657876SArnaldo Carvalho de Melo /* FIXME: do congestion control initialization */ 5737c657876SArnaldo Carvalho de Melo 5747c657876SArnaldo Carvalho de Melo queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len); 5757c657876SArnaldo Carvalho de Melo if (queued >= 0) 5767c657876SArnaldo Carvalho de Melo return queued; 5777c657876SArnaldo Carvalho de Melo 5787c657876SArnaldo Carvalho de Melo __kfree_skb(skb); 5797c657876SArnaldo Carvalho de Melo return 0; 5807c657876SArnaldo Carvalho de Melo 5817c657876SArnaldo Carvalho de Melo case DCCP_RESPOND: 5827c657876SArnaldo Carvalho de Melo case DCCP_PARTOPEN: 5837690af3fSArnaldo Carvalho de Melo queued = dccp_rcv_respond_partopen_state_process(sk, skb, 5847690af3fSArnaldo Carvalho de Melo dh, len); 5857c657876SArnaldo Carvalho de Melo break; 5867c657876SArnaldo Carvalho de Melo } 5877c657876SArnaldo Carvalho de Melo 5887690af3fSArnaldo Carvalho de Melo if (dh->dccph_type == DCCP_PKT_ACK || 5897690af3fSArnaldo Carvalho de Melo dh->dccph_type == DCCP_PKT_DATAACK) { 5907c657876SArnaldo Carvalho de Melo switch (old_state) { 5917c657876SArnaldo Carvalho de Melo case DCCP_PARTOPEN: 5927c657876SArnaldo Carvalho de Melo sk->sk_state_change(sk); 5937c657876SArnaldo Carvalho de Melo sk_wake_async(sk, 0, POLL_OUT); 5947c657876SArnaldo Carvalho de Melo break; 5957c657876SArnaldo Carvalho de Melo } 5967c657876SArnaldo Carvalho de Melo } 5977c657876SArnaldo Carvalho de Melo 5987c657876SArnaldo Carvalho de Melo if (!queued) { 5997c657876SArnaldo Carvalho de Melo discard: 6007c657876SArnaldo Carvalho de Melo __kfree_skb(skb); 6017c657876SArnaldo Carvalho de Melo } 6027c657876SArnaldo Carvalho de Melo return 0; 6037c657876SArnaldo Carvalho de Melo } 604