162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * net/dccp/input.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * An implementation of the DCCP protocol 662306a36Sopenharmony_ci * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/dccp.h> 1062306a36Sopenharmony_ci#include <linux/skbuff.h> 1162306a36Sopenharmony_ci#include <linux/slab.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <net/sock.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "ackvec.h" 1662306a36Sopenharmony_ci#include "ccid.h" 1762306a36Sopenharmony_ci#include "dccp.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */ 2062306a36Sopenharmony_ciint sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic void dccp_enqueue_skb(struct sock *sk, struct sk_buff *skb) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci __skb_pull(skb, dccp_hdr(skb)->dccph_doff * 4); 2562306a36Sopenharmony_ci __skb_queue_tail(&sk->sk_receive_queue, skb); 2662306a36Sopenharmony_ci skb_set_owner_r(skb, sk); 2762306a36Sopenharmony_ci sk->sk_data_ready(sk); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic void dccp_fin(struct sock *sk, struct sk_buff *skb) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci /* 3362306a36Sopenharmony_ci * On receiving Close/CloseReq, both RD/WR shutdown are performed. 3462306a36Sopenharmony_ci * RFC 4340, 8.3 says that we MAY send further Data/DataAcks after 3562306a36Sopenharmony_ci * receiving the closing segment, but there is no guarantee that such 3662306a36Sopenharmony_ci * data will be processed at all. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci sk->sk_shutdown = SHUTDOWN_MASK; 3962306a36Sopenharmony_ci sock_set_flag(sk, SOCK_DONE); 4062306a36Sopenharmony_ci dccp_enqueue_skb(sk, skb); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic int dccp_rcv_close(struct sock *sk, struct sk_buff *skb) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci int queued = 0; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci switch (sk->sk_state) { 4862306a36Sopenharmony_ci /* 4962306a36Sopenharmony_ci * We ignore Close when received in one of the following states: 5062306a36Sopenharmony_ci * - CLOSED (may be a late or duplicate packet) 5162306a36Sopenharmony_ci * - PASSIVE_CLOSEREQ (the peer has sent a CloseReq earlier) 5262306a36Sopenharmony_ci * - RESPOND (already handled by dccp_check_req) 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_ci case DCCP_CLOSING: 5562306a36Sopenharmony_ci /* 5662306a36Sopenharmony_ci * Simultaneous-close: receiving a Close after sending one. This 5762306a36Sopenharmony_ci * can happen if both client and server perform active-close and 5862306a36Sopenharmony_ci * will result in an endless ping-pong of crossing and retrans- 5962306a36Sopenharmony_ci * mitted Close packets, which only terminates when one of the 6062306a36Sopenharmony_ci * nodes times out (min. 64 seconds). Quicker convergence can be 6162306a36Sopenharmony_ci * achieved when one of the nodes acts as tie-breaker. 6262306a36Sopenharmony_ci * This is ok as both ends are done with data transfer and each 6362306a36Sopenharmony_ci * end is just waiting for the other to acknowledge termination. 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci if (dccp_sk(sk)->dccps_role != DCCP_ROLE_CLIENT) 6662306a36Sopenharmony_ci break; 6762306a36Sopenharmony_ci fallthrough; 6862306a36Sopenharmony_ci case DCCP_REQUESTING: 6962306a36Sopenharmony_ci case DCCP_ACTIVE_CLOSEREQ: 7062306a36Sopenharmony_ci dccp_send_reset(sk, DCCP_RESET_CODE_CLOSED); 7162306a36Sopenharmony_ci dccp_done(sk); 7262306a36Sopenharmony_ci break; 7362306a36Sopenharmony_ci case DCCP_OPEN: 7462306a36Sopenharmony_ci case DCCP_PARTOPEN: 7562306a36Sopenharmony_ci /* Give waiting application a chance to read pending data */ 7662306a36Sopenharmony_ci queued = 1; 7762306a36Sopenharmony_ci dccp_fin(sk, skb); 7862306a36Sopenharmony_ci dccp_set_state(sk, DCCP_PASSIVE_CLOSE); 7962306a36Sopenharmony_ci fallthrough; 8062306a36Sopenharmony_ci case DCCP_PASSIVE_CLOSE: 8162306a36Sopenharmony_ci /* 8262306a36Sopenharmony_ci * Retransmitted Close: we have already enqueued the first one. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ci sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_HUP); 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci return queued; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic int dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci int queued = 0; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci /* 9462306a36Sopenharmony_ci * Step 7: Check for unexpected packet types 9562306a36Sopenharmony_ci * If (S.is_server and P.type == CloseReq) 9662306a36Sopenharmony_ci * Send Sync packet acknowledging P.seqno 9762306a36Sopenharmony_ci * Drop packet and return 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_ci if (dccp_sk(sk)->dccps_role != DCCP_ROLE_CLIENT) { 10062306a36Sopenharmony_ci dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC); 10162306a36Sopenharmony_ci return queued; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* Step 13: process relevant Client states < CLOSEREQ */ 10562306a36Sopenharmony_ci switch (sk->sk_state) { 10662306a36Sopenharmony_ci case DCCP_REQUESTING: 10762306a36Sopenharmony_ci dccp_send_close(sk, 0); 10862306a36Sopenharmony_ci dccp_set_state(sk, DCCP_CLOSING); 10962306a36Sopenharmony_ci break; 11062306a36Sopenharmony_ci case DCCP_OPEN: 11162306a36Sopenharmony_ci case DCCP_PARTOPEN: 11262306a36Sopenharmony_ci /* Give waiting application a chance to read pending data */ 11362306a36Sopenharmony_ci queued = 1; 11462306a36Sopenharmony_ci dccp_fin(sk, skb); 11562306a36Sopenharmony_ci dccp_set_state(sk, DCCP_PASSIVE_CLOSEREQ); 11662306a36Sopenharmony_ci fallthrough; 11762306a36Sopenharmony_ci case DCCP_PASSIVE_CLOSEREQ: 11862306a36Sopenharmony_ci sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_HUP); 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci return queued; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic u16 dccp_reset_code_convert(const u8 code) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci static const u16 error_code[] = { 12662306a36Sopenharmony_ci [DCCP_RESET_CODE_CLOSED] = 0, /* normal termination */ 12762306a36Sopenharmony_ci [DCCP_RESET_CODE_UNSPECIFIED] = 0, /* nothing known */ 12862306a36Sopenharmony_ci [DCCP_RESET_CODE_ABORTED] = ECONNRESET, 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci [DCCP_RESET_CODE_NO_CONNECTION] = ECONNREFUSED, 13162306a36Sopenharmony_ci [DCCP_RESET_CODE_CONNECTION_REFUSED] = ECONNREFUSED, 13262306a36Sopenharmony_ci [DCCP_RESET_CODE_TOO_BUSY] = EUSERS, 13362306a36Sopenharmony_ci [DCCP_RESET_CODE_AGGRESSION_PENALTY] = EDQUOT, 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci [DCCP_RESET_CODE_PACKET_ERROR] = ENOMSG, 13662306a36Sopenharmony_ci [DCCP_RESET_CODE_BAD_INIT_COOKIE] = EBADR, 13762306a36Sopenharmony_ci [DCCP_RESET_CODE_BAD_SERVICE_CODE] = EBADRQC, 13862306a36Sopenharmony_ci [DCCP_RESET_CODE_OPTION_ERROR] = EILSEQ, 13962306a36Sopenharmony_ci [DCCP_RESET_CODE_MANDATORY_ERROR] = EOPNOTSUPP, 14062306a36Sopenharmony_ci }; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return code >= DCCP_MAX_RESET_CODES ? 0 : error_code[code]; 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci u16 err = dccp_reset_code_convert(dccp_hdr_reset(skb)->dccph_reset_code); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci sk->sk_err = err; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* Queue the equivalent of TCP fin so that dccp_recvmsg exits the loop */ 15262306a36Sopenharmony_ci dccp_fin(sk, skb); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if (err && !sock_flag(sk, SOCK_DEAD)) 15562306a36Sopenharmony_ci sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); 15662306a36Sopenharmony_ci dccp_time_wait(sk, DCCP_TIME_WAIT, 0); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic void dccp_handle_ackvec_processing(struct sock *sk, struct sk_buff *skb) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci struct dccp_ackvec *av = dccp_sk(sk)->dccps_hc_rx_ackvec; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci if (av == NULL) 16462306a36Sopenharmony_ci return; 16562306a36Sopenharmony_ci if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) 16662306a36Sopenharmony_ci dccp_ackvec_clear_state(av, DCCP_SKB_CB(skb)->dccpd_ack_seq); 16762306a36Sopenharmony_ci dccp_ackvec_input(av, skb); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic void dccp_deliver_input_to_ccids(struct sock *sk, struct sk_buff *skb) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci const struct dccp_sock *dp = dccp_sk(sk); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* Don't deliver to RX CCID when node has shut down read end. */ 17562306a36Sopenharmony_ci if (!(sk->sk_shutdown & RCV_SHUTDOWN)) 17662306a36Sopenharmony_ci ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); 17762306a36Sopenharmony_ci /* 17862306a36Sopenharmony_ci * Until the TX queue has been drained, we can not honour SHUT_WR, since 17962306a36Sopenharmony_ci * we need received feedback as input to adjust congestion control. 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ci if (sk->sk_write_queue.qlen > 0 || !(sk->sk_shutdown & SEND_SHUTDOWN)) 18262306a36Sopenharmony_ci ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci const struct dccp_hdr *dh = dccp_hdr(skb); 18862306a36Sopenharmony_ci struct dccp_sock *dp = dccp_sk(sk); 18962306a36Sopenharmony_ci u64 lswl, lawl, seqno = DCCP_SKB_CB(skb)->dccpd_seq, 19062306a36Sopenharmony_ci ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci /* 19362306a36Sopenharmony_ci * Step 5: Prepare sequence numbers for Sync 19462306a36Sopenharmony_ci * If P.type == Sync or P.type == SyncAck, 19562306a36Sopenharmony_ci * If S.AWL <= P.ackno <= S.AWH and P.seqno >= S.SWL, 19662306a36Sopenharmony_ci * / * P is valid, so update sequence number variables 19762306a36Sopenharmony_ci * accordingly. After this update, P will pass the tests 19862306a36Sopenharmony_ci * in Step 6. A SyncAck is generated if necessary in 19962306a36Sopenharmony_ci * Step 15 * / 20062306a36Sopenharmony_ci * Update S.GSR, S.SWL, S.SWH 20162306a36Sopenharmony_ci * Otherwise, 20262306a36Sopenharmony_ci * Drop packet and return 20362306a36Sopenharmony_ci */ 20462306a36Sopenharmony_ci if (dh->dccph_type == DCCP_PKT_SYNC || 20562306a36Sopenharmony_ci dh->dccph_type == DCCP_PKT_SYNCACK) { 20662306a36Sopenharmony_ci if (between48(ackno, dp->dccps_awl, dp->dccps_awh) && 20762306a36Sopenharmony_ci dccp_delta_seqno(dp->dccps_swl, seqno) >= 0) 20862306a36Sopenharmony_ci dccp_update_gsr(sk, seqno); 20962306a36Sopenharmony_ci else 21062306a36Sopenharmony_ci return -1; 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /* 21462306a36Sopenharmony_ci * Step 6: Check sequence numbers 21562306a36Sopenharmony_ci * Let LSWL = S.SWL and LAWL = S.AWL 21662306a36Sopenharmony_ci * If P.type == CloseReq or P.type == Close or P.type == Reset, 21762306a36Sopenharmony_ci * LSWL := S.GSR + 1, LAWL := S.GAR 21862306a36Sopenharmony_ci * If LSWL <= P.seqno <= S.SWH 21962306a36Sopenharmony_ci * and (P.ackno does not exist or LAWL <= P.ackno <= S.AWH), 22062306a36Sopenharmony_ci * Update S.GSR, S.SWL, S.SWH 22162306a36Sopenharmony_ci * If P.type != Sync, 22262306a36Sopenharmony_ci * Update S.GAR 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_ci lswl = dp->dccps_swl; 22562306a36Sopenharmony_ci lawl = dp->dccps_awl; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (dh->dccph_type == DCCP_PKT_CLOSEREQ || 22862306a36Sopenharmony_ci dh->dccph_type == DCCP_PKT_CLOSE || 22962306a36Sopenharmony_ci dh->dccph_type == DCCP_PKT_RESET) { 23062306a36Sopenharmony_ci lswl = ADD48(dp->dccps_gsr, 1); 23162306a36Sopenharmony_ci lawl = dp->dccps_gar; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (between48(seqno, lswl, dp->dccps_swh) && 23562306a36Sopenharmony_ci (ackno == DCCP_PKT_WITHOUT_ACK_SEQ || 23662306a36Sopenharmony_ci between48(ackno, lawl, dp->dccps_awh))) { 23762306a36Sopenharmony_ci dccp_update_gsr(sk, seqno); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (dh->dccph_type != DCCP_PKT_SYNC && 24062306a36Sopenharmony_ci ackno != DCCP_PKT_WITHOUT_ACK_SEQ && 24162306a36Sopenharmony_ci after48(ackno, dp->dccps_gar)) 24262306a36Sopenharmony_ci dp->dccps_gar = ackno; 24362306a36Sopenharmony_ci } else { 24462306a36Sopenharmony_ci unsigned long now = jiffies; 24562306a36Sopenharmony_ci /* 24662306a36Sopenharmony_ci * Step 6: Check sequence numbers 24762306a36Sopenharmony_ci * Otherwise, 24862306a36Sopenharmony_ci * If P.type == Reset, 24962306a36Sopenharmony_ci * Send Sync packet acknowledging S.GSR 25062306a36Sopenharmony_ci * Otherwise, 25162306a36Sopenharmony_ci * Send Sync packet acknowledging P.seqno 25262306a36Sopenharmony_ci * Drop packet and return 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * These Syncs are rate-limited as per RFC 4340, 7.5.4: 25562306a36Sopenharmony_ci * at most 1 / (dccp_sync_rate_limit * HZ) Syncs per second. 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ci if (time_before(now, (dp->dccps_rate_last + 25862306a36Sopenharmony_ci sysctl_dccp_sync_ratelimit))) 25962306a36Sopenharmony_ci return -1; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci DCCP_WARN("Step 6 failed for %s packet, " 26262306a36Sopenharmony_ci "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and " 26362306a36Sopenharmony_ci "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), " 26462306a36Sopenharmony_ci "sending SYNC...\n", dccp_packet_name(dh->dccph_type), 26562306a36Sopenharmony_ci (unsigned long long) lswl, (unsigned long long) seqno, 26662306a36Sopenharmony_ci (unsigned long long) dp->dccps_swh, 26762306a36Sopenharmony_ci (ackno == DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" 26862306a36Sopenharmony_ci : "exists", 26962306a36Sopenharmony_ci (unsigned long long) lawl, (unsigned long long) ackno, 27062306a36Sopenharmony_ci (unsigned long long) dp->dccps_awh); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci dp->dccps_rate_last = now; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci if (dh->dccph_type == DCCP_PKT_RESET) 27562306a36Sopenharmony_ci seqno = dp->dccps_gsr; 27662306a36Sopenharmony_ci dccp_send_sync(sk, seqno, DCCP_PKT_SYNC); 27762306a36Sopenharmony_ci return -1; 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci return 0; 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, 28462306a36Sopenharmony_ci const struct dccp_hdr *dh, const unsigned int len) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci struct dccp_sock *dp = dccp_sk(sk); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci switch (dccp_hdr(skb)->dccph_type) { 28962306a36Sopenharmony_ci case DCCP_PKT_DATAACK: 29062306a36Sopenharmony_ci case DCCP_PKT_DATA: 29162306a36Sopenharmony_ci /* 29262306a36Sopenharmony_ci * FIXME: schedule DATA_DROPPED (RFC 4340, 11.7.2) if and when 29362306a36Sopenharmony_ci * - sk_shutdown == RCV_SHUTDOWN, use Code 1, "Not Listening" 29462306a36Sopenharmony_ci * - sk_receive_queue is full, use Code 2, "Receive Buffer" 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_ci dccp_enqueue_skb(sk, skb); 29762306a36Sopenharmony_ci return 0; 29862306a36Sopenharmony_ci case DCCP_PKT_ACK: 29962306a36Sopenharmony_ci goto discard; 30062306a36Sopenharmony_ci case DCCP_PKT_RESET: 30162306a36Sopenharmony_ci /* 30262306a36Sopenharmony_ci * Step 9: Process Reset 30362306a36Sopenharmony_ci * If P.type == Reset, 30462306a36Sopenharmony_ci * Tear down connection 30562306a36Sopenharmony_ci * S.state := TIMEWAIT 30662306a36Sopenharmony_ci * Set TIMEWAIT timer 30762306a36Sopenharmony_ci * Drop packet and return 30862306a36Sopenharmony_ci */ 30962306a36Sopenharmony_ci dccp_rcv_reset(sk, skb); 31062306a36Sopenharmony_ci return 0; 31162306a36Sopenharmony_ci case DCCP_PKT_CLOSEREQ: 31262306a36Sopenharmony_ci if (dccp_rcv_closereq(sk, skb)) 31362306a36Sopenharmony_ci return 0; 31462306a36Sopenharmony_ci goto discard; 31562306a36Sopenharmony_ci case DCCP_PKT_CLOSE: 31662306a36Sopenharmony_ci if (dccp_rcv_close(sk, skb)) 31762306a36Sopenharmony_ci return 0; 31862306a36Sopenharmony_ci goto discard; 31962306a36Sopenharmony_ci case DCCP_PKT_REQUEST: 32062306a36Sopenharmony_ci /* Step 7 32162306a36Sopenharmony_ci * or (S.is_server and P.type == Response) 32262306a36Sopenharmony_ci * or (S.is_client and P.type == Request) 32362306a36Sopenharmony_ci * or (S.state >= OPEN and P.type == Request 32462306a36Sopenharmony_ci * and P.seqno >= S.OSR) 32562306a36Sopenharmony_ci * or (S.state >= OPEN and P.type == Response 32662306a36Sopenharmony_ci * and P.seqno >= S.OSR) 32762306a36Sopenharmony_ci * or (S.state == RESPOND and P.type == Data), 32862306a36Sopenharmony_ci * Send Sync packet acknowledging P.seqno 32962306a36Sopenharmony_ci * Drop packet and return 33062306a36Sopenharmony_ci */ 33162306a36Sopenharmony_ci if (dp->dccps_role != DCCP_ROLE_LISTEN) 33262306a36Sopenharmony_ci goto send_sync; 33362306a36Sopenharmony_ci goto check_seq; 33462306a36Sopenharmony_ci case DCCP_PKT_RESPONSE: 33562306a36Sopenharmony_ci if (dp->dccps_role != DCCP_ROLE_CLIENT) 33662306a36Sopenharmony_ci goto send_sync; 33762306a36Sopenharmony_cicheck_seq: 33862306a36Sopenharmony_ci if (dccp_delta_seqno(dp->dccps_osr, 33962306a36Sopenharmony_ci DCCP_SKB_CB(skb)->dccpd_seq) >= 0) { 34062306a36Sopenharmony_cisend_sync: 34162306a36Sopenharmony_ci dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, 34262306a36Sopenharmony_ci DCCP_PKT_SYNC); 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci break; 34562306a36Sopenharmony_ci case DCCP_PKT_SYNC: 34662306a36Sopenharmony_ci dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, 34762306a36Sopenharmony_ci DCCP_PKT_SYNCACK); 34862306a36Sopenharmony_ci /* 34962306a36Sopenharmony_ci * From RFC 4340, sec. 5.7 35062306a36Sopenharmony_ci * 35162306a36Sopenharmony_ci * As with DCCP-Ack packets, DCCP-Sync and DCCP-SyncAck packets 35262306a36Sopenharmony_ci * MAY have non-zero-length application data areas, whose 35362306a36Sopenharmony_ci * contents receivers MUST ignore. 35462306a36Sopenharmony_ci */ 35562306a36Sopenharmony_ci goto discard; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci DCCP_INC_STATS(DCCP_MIB_INERRS); 35962306a36Sopenharmony_cidiscard: 36062306a36Sopenharmony_ci __kfree_skb(skb); 36162306a36Sopenharmony_ci return 0; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ciint dccp_rcv_established(struct sock *sk, struct sk_buff *skb, 36562306a36Sopenharmony_ci const struct dccp_hdr *dh, const unsigned int len) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci if (dccp_check_seqno(sk, skb)) 36862306a36Sopenharmony_ci goto discard; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci if (dccp_parse_options(sk, NULL, skb)) 37162306a36Sopenharmony_ci return 1; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci dccp_handle_ackvec_processing(sk, skb); 37462306a36Sopenharmony_ci dccp_deliver_input_to_ccids(sk, skb); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci return __dccp_rcv_established(sk, skb, dh, len); 37762306a36Sopenharmony_cidiscard: 37862306a36Sopenharmony_ci __kfree_skb(skb); 37962306a36Sopenharmony_ci return 0; 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(dccp_rcv_established); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic int dccp_rcv_request_sent_state_process(struct sock *sk, 38562306a36Sopenharmony_ci struct sk_buff *skb, 38662306a36Sopenharmony_ci const struct dccp_hdr *dh, 38762306a36Sopenharmony_ci const unsigned int len) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci /* 39062306a36Sopenharmony_ci * Step 4: Prepare sequence numbers in REQUEST 39162306a36Sopenharmony_ci * If S.state == REQUEST, 39262306a36Sopenharmony_ci * If (P.type == Response or P.type == Reset) 39362306a36Sopenharmony_ci * and S.AWL <= P.ackno <= S.AWH, 39462306a36Sopenharmony_ci * / * Set sequence number variables corresponding to the 39562306a36Sopenharmony_ci * other endpoint, so P will pass the tests in Step 6 * / 39662306a36Sopenharmony_ci * Set S.GSR, S.ISR, S.SWL, S.SWH 39762306a36Sopenharmony_ci * / * Response processing continues in Step 10; Reset 39862306a36Sopenharmony_ci * processing continues in Step 9 * / 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_ci if (dh->dccph_type == DCCP_PKT_RESPONSE) { 40162306a36Sopenharmony_ci const struct inet_connection_sock *icsk = inet_csk(sk); 40262306a36Sopenharmony_ci struct dccp_sock *dp = dccp_sk(sk); 40362306a36Sopenharmony_ci long tstamp = dccp_timestamp(); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, 40662306a36Sopenharmony_ci dp->dccps_awl, dp->dccps_awh)) { 40762306a36Sopenharmony_ci dccp_pr_debug("invalid ackno: S.AWL=%llu, " 40862306a36Sopenharmony_ci "P.ackno=%llu, S.AWH=%llu\n", 40962306a36Sopenharmony_ci (unsigned long long)dp->dccps_awl, 41062306a36Sopenharmony_ci (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, 41162306a36Sopenharmony_ci (unsigned long long)dp->dccps_awh); 41262306a36Sopenharmony_ci goto out_invalid_packet; 41362306a36Sopenharmony_ci } 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci /* 41662306a36Sopenharmony_ci * If option processing (Step 8) failed, return 1 here so that 41762306a36Sopenharmony_ci * dccp_v4_do_rcv() sends a Reset. The Reset code depends on 41862306a36Sopenharmony_ci * the option type and is set in dccp_parse_options(). 41962306a36Sopenharmony_ci */ 42062306a36Sopenharmony_ci if (dccp_parse_options(sk, NULL, skb)) 42162306a36Sopenharmony_ci return 1; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci /* Obtain usec RTT sample from SYN exchange (used by TFRC). */ 42462306a36Sopenharmony_ci if (likely(dp->dccps_options_received.dccpor_timestamp_echo)) 42562306a36Sopenharmony_ci dp->dccps_syn_rtt = dccp_sample_rtt(sk, 10 * (tstamp - 42662306a36Sopenharmony_ci dp->dccps_options_received.dccpor_timestamp_echo)); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci /* Stop the REQUEST timer */ 42962306a36Sopenharmony_ci inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); 43062306a36Sopenharmony_ci WARN_ON(sk->sk_send_head == NULL); 43162306a36Sopenharmony_ci kfree_skb(sk->sk_send_head); 43262306a36Sopenharmony_ci sk->sk_send_head = NULL; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci /* 43562306a36Sopenharmony_ci * Set ISR, GSR from packet. ISS was set in dccp_v{4,6}_connect 43662306a36Sopenharmony_ci * and GSS in dccp_transmit_skb(). Setting AWL/AWH and SWL/SWH 43762306a36Sopenharmony_ci * is done as part of activating the feature values below, since 43862306a36Sopenharmony_ci * these settings depend on the local/remote Sequence Window 43962306a36Sopenharmony_ci * features, which were undefined or not confirmed until now. 44062306a36Sopenharmony_ci */ 44162306a36Sopenharmony_ci dp->dccps_gsr = dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci dccp_sync_mss(sk, icsk->icsk_pmtu_cookie); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci /* 44662306a36Sopenharmony_ci * Step 10: Process REQUEST state (second part) 44762306a36Sopenharmony_ci * If S.state == REQUEST, 44862306a36Sopenharmony_ci * / * If we get here, P is a valid Response from the 44962306a36Sopenharmony_ci * server (see Step 4), and we should move to 45062306a36Sopenharmony_ci * PARTOPEN state. PARTOPEN means send an Ack, 45162306a36Sopenharmony_ci * don't send Data packets, retransmit Acks 45262306a36Sopenharmony_ci * periodically, and always include any Init Cookie 45362306a36Sopenharmony_ci * from the Response * / 45462306a36Sopenharmony_ci * S.state := PARTOPEN 45562306a36Sopenharmony_ci * Set PARTOPEN timer 45662306a36Sopenharmony_ci * Continue with S.state == PARTOPEN 45762306a36Sopenharmony_ci * / * Step 12 will send the Ack completing the 45862306a36Sopenharmony_ci * three-way handshake * / 45962306a36Sopenharmony_ci */ 46062306a36Sopenharmony_ci dccp_set_state(sk, DCCP_PARTOPEN); 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci /* 46362306a36Sopenharmony_ci * If feature negotiation was successful, activate features now; 46462306a36Sopenharmony_ci * an activation failure means that this host could not activate 46562306a36Sopenharmony_ci * one ore more features (e.g. insufficient memory), which would 46662306a36Sopenharmony_ci * leave at least one feature in an undefined state. 46762306a36Sopenharmony_ci */ 46862306a36Sopenharmony_ci if (dccp_feat_activate_values(sk, &dp->dccps_featneg)) 46962306a36Sopenharmony_ci goto unable_to_proceed; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci /* Make sure socket is routed, for correct metrics. */ 47262306a36Sopenharmony_ci icsk->icsk_af_ops->rebuild_header(sk); 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci if (!sock_flag(sk, SOCK_DEAD)) { 47562306a36Sopenharmony_ci sk->sk_state_change(sk); 47662306a36Sopenharmony_ci sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT); 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (sk->sk_write_pending || inet_csk_in_pingpong_mode(sk) || 48062306a36Sopenharmony_ci icsk->icsk_accept_queue.rskq_defer_accept) { 48162306a36Sopenharmony_ci /* Save one ACK. Data will be ready after 48262306a36Sopenharmony_ci * several ticks, if write_pending is set. 48362306a36Sopenharmony_ci * 48462306a36Sopenharmony_ci * It may be deleted, but with this feature tcpdumps 48562306a36Sopenharmony_ci * look so _wonderfully_ clever, that I was not able 48662306a36Sopenharmony_ci * to stand against the temptation 8) --ANK 48762306a36Sopenharmony_ci */ 48862306a36Sopenharmony_ci /* 48962306a36Sopenharmony_ci * OK, in DCCP we can as well do a similar trick, its 49062306a36Sopenharmony_ci * even in the draft, but there is no need for us to 49162306a36Sopenharmony_ci * schedule an ack here, as dccp_sendmsg does this for 49262306a36Sopenharmony_ci * us, also stated in the draft. -acme 49362306a36Sopenharmony_ci */ 49462306a36Sopenharmony_ci __kfree_skb(skb); 49562306a36Sopenharmony_ci return 0; 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci dccp_send_ack(sk); 49862306a36Sopenharmony_ci return -1; 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ciout_invalid_packet: 50262306a36Sopenharmony_ci /* dccp_v4_do_rcv will send a reset */ 50362306a36Sopenharmony_ci DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; 50462306a36Sopenharmony_ci return 1; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ciunable_to_proceed: 50762306a36Sopenharmony_ci DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_ABORTED; 50862306a36Sopenharmony_ci /* 50962306a36Sopenharmony_ci * We mark this socket as no longer usable, so that the loop in 51062306a36Sopenharmony_ci * dccp_sendmsg() terminates and the application gets notified. 51162306a36Sopenharmony_ci */ 51262306a36Sopenharmony_ci dccp_set_state(sk, DCCP_CLOSED); 51362306a36Sopenharmony_ci sk->sk_err = ECOMM; 51462306a36Sopenharmony_ci return 1; 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic int dccp_rcv_respond_partopen_state_process(struct sock *sk, 51862306a36Sopenharmony_ci struct sk_buff *skb, 51962306a36Sopenharmony_ci const struct dccp_hdr *dh, 52062306a36Sopenharmony_ci const unsigned int len) 52162306a36Sopenharmony_ci{ 52262306a36Sopenharmony_ci struct dccp_sock *dp = dccp_sk(sk); 52362306a36Sopenharmony_ci u32 sample = dp->dccps_options_received.dccpor_timestamp_echo; 52462306a36Sopenharmony_ci int queued = 0; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci switch (dh->dccph_type) { 52762306a36Sopenharmony_ci case DCCP_PKT_RESET: 52862306a36Sopenharmony_ci inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); 52962306a36Sopenharmony_ci break; 53062306a36Sopenharmony_ci case DCCP_PKT_DATA: 53162306a36Sopenharmony_ci if (sk->sk_state == DCCP_RESPOND) 53262306a36Sopenharmony_ci break; 53362306a36Sopenharmony_ci fallthrough; 53462306a36Sopenharmony_ci case DCCP_PKT_DATAACK: 53562306a36Sopenharmony_ci case DCCP_PKT_ACK: 53662306a36Sopenharmony_ci /* 53762306a36Sopenharmony_ci * FIXME: we should be resetting the PARTOPEN (DELACK) timer 53862306a36Sopenharmony_ci * here but only if we haven't used the DELACK timer for 53962306a36Sopenharmony_ci * something else, like sending a delayed ack for a TIMESTAMP 54062306a36Sopenharmony_ci * echo, etc, for now were not clearing it, sending an extra 54162306a36Sopenharmony_ci * ACK when there is nothing else to do in DELACK is not a big 54262306a36Sopenharmony_ci * deal after all. 54362306a36Sopenharmony_ci */ 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci /* Stop the PARTOPEN timer */ 54662306a36Sopenharmony_ci if (sk->sk_state == DCCP_PARTOPEN) 54762306a36Sopenharmony_ci inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci /* Obtain usec RTT sample from SYN exchange (used by TFRC). */ 55062306a36Sopenharmony_ci if (likely(sample)) { 55162306a36Sopenharmony_ci long delta = dccp_timestamp() - sample; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci dp->dccps_syn_rtt = dccp_sample_rtt(sk, 10 * delta); 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci dp->dccps_osr = DCCP_SKB_CB(skb)->dccpd_seq; 55762306a36Sopenharmony_ci dccp_set_state(sk, DCCP_OPEN); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci if (dh->dccph_type == DCCP_PKT_DATAACK || 56062306a36Sopenharmony_ci dh->dccph_type == DCCP_PKT_DATA) { 56162306a36Sopenharmony_ci __dccp_rcv_established(sk, skb, dh, len); 56262306a36Sopenharmony_ci queued = 1; /* packet was queued 56362306a36Sopenharmony_ci (by __dccp_rcv_established) */ 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci break; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci return queued; 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ciint dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, 57262306a36Sopenharmony_ci struct dccp_hdr *dh, unsigned int len) 57362306a36Sopenharmony_ci{ 57462306a36Sopenharmony_ci struct dccp_sock *dp = dccp_sk(sk); 57562306a36Sopenharmony_ci struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); 57662306a36Sopenharmony_ci const int old_state = sk->sk_state; 57762306a36Sopenharmony_ci bool acceptable; 57862306a36Sopenharmony_ci int queued = 0; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci /* 58162306a36Sopenharmony_ci * Step 3: Process LISTEN state 58262306a36Sopenharmony_ci * 58362306a36Sopenharmony_ci * If S.state == LISTEN, 58462306a36Sopenharmony_ci * If P.type == Request or P contains a valid Init Cookie option, 58562306a36Sopenharmony_ci * (* Must scan the packet's options to check for Init 58662306a36Sopenharmony_ci * Cookies. Only Init Cookies are processed here, 58762306a36Sopenharmony_ci * however; other options are processed in Step 8. This 58862306a36Sopenharmony_ci * scan need only be performed if the endpoint uses Init 58962306a36Sopenharmony_ci * Cookies *) 59062306a36Sopenharmony_ci * (* Generate a new socket and switch to that socket *) 59162306a36Sopenharmony_ci * Set S := new socket for this port pair 59262306a36Sopenharmony_ci * S.state = RESPOND 59362306a36Sopenharmony_ci * Choose S.ISS (initial seqno) or set from Init Cookies 59462306a36Sopenharmony_ci * Initialize S.GAR := S.ISS 59562306a36Sopenharmony_ci * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init 59662306a36Sopenharmony_ci * Cookies Continue with S.state == RESPOND 59762306a36Sopenharmony_ci * (* A Response packet will be generated in Step 11 *) 59862306a36Sopenharmony_ci * Otherwise, 59962306a36Sopenharmony_ci * Generate Reset(No Connection) unless P.type == Reset 60062306a36Sopenharmony_ci * Drop packet and return 60162306a36Sopenharmony_ci */ 60262306a36Sopenharmony_ci if (sk->sk_state == DCCP_LISTEN) { 60362306a36Sopenharmony_ci if (dh->dccph_type == DCCP_PKT_REQUEST) { 60462306a36Sopenharmony_ci /* It is possible that we process SYN packets from backlog, 60562306a36Sopenharmony_ci * so we need to make sure to disable BH and RCU right there. 60662306a36Sopenharmony_ci */ 60762306a36Sopenharmony_ci rcu_read_lock(); 60862306a36Sopenharmony_ci local_bh_disable(); 60962306a36Sopenharmony_ci acceptable = inet_csk(sk)->icsk_af_ops->conn_request(sk, skb) >= 0; 61062306a36Sopenharmony_ci local_bh_enable(); 61162306a36Sopenharmony_ci rcu_read_unlock(); 61262306a36Sopenharmony_ci if (!acceptable) 61362306a36Sopenharmony_ci return 1; 61462306a36Sopenharmony_ci consume_skb(skb); 61562306a36Sopenharmony_ci return 0; 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci if (dh->dccph_type == DCCP_PKT_RESET) 61862306a36Sopenharmony_ci goto discard; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci /* Caller (dccp_v4_do_rcv) will send Reset */ 62162306a36Sopenharmony_ci dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; 62262306a36Sopenharmony_ci return 1; 62362306a36Sopenharmony_ci } else if (sk->sk_state == DCCP_CLOSED) { 62462306a36Sopenharmony_ci dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; 62562306a36Sopenharmony_ci return 1; 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci /* Step 6: Check sequence numbers (omitted in LISTEN/REQUEST state) */ 62962306a36Sopenharmony_ci if (sk->sk_state != DCCP_REQUESTING && dccp_check_seqno(sk, skb)) 63062306a36Sopenharmony_ci goto discard; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci /* 63362306a36Sopenharmony_ci * Step 7: Check for unexpected packet types 63462306a36Sopenharmony_ci * If (S.is_server and P.type == Response) 63562306a36Sopenharmony_ci * or (S.is_client and P.type == Request) 63662306a36Sopenharmony_ci * or (S.state == RESPOND and P.type == Data), 63762306a36Sopenharmony_ci * Send Sync packet acknowledging P.seqno 63862306a36Sopenharmony_ci * Drop packet and return 63962306a36Sopenharmony_ci */ 64062306a36Sopenharmony_ci if ((dp->dccps_role != DCCP_ROLE_CLIENT && 64162306a36Sopenharmony_ci dh->dccph_type == DCCP_PKT_RESPONSE) || 64262306a36Sopenharmony_ci (dp->dccps_role == DCCP_ROLE_CLIENT && 64362306a36Sopenharmony_ci dh->dccph_type == DCCP_PKT_REQUEST) || 64462306a36Sopenharmony_ci (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) { 64562306a36Sopenharmony_ci dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC); 64662306a36Sopenharmony_ci goto discard; 64762306a36Sopenharmony_ci } 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci /* Step 8: Process options */ 65062306a36Sopenharmony_ci if (dccp_parse_options(sk, NULL, skb)) 65162306a36Sopenharmony_ci return 1; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci /* 65462306a36Sopenharmony_ci * Step 9: Process Reset 65562306a36Sopenharmony_ci * If P.type == Reset, 65662306a36Sopenharmony_ci * Tear down connection 65762306a36Sopenharmony_ci * S.state := TIMEWAIT 65862306a36Sopenharmony_ci * Set TIMEWAIT timer 65962306a36Sopenharmony_ci * Drop packet and return 66062306a36Sopenharmony_ci */ 66162306a36Sopenharmony_ci if (dh->dccph_type == DCCP_PKT_RESET) { 66262306a36Sopenharmony_ci dccp_rcv_reset(sk, skb); 66362306a36Sopenharmony_ci return 0; 66462306a36Sopenharmony_ci } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { /* Step 13 */ 66562306a36Sopenharmony_ci if (dccp_rcv_closereq(sk, skb)) 66662306a36Sopenharmony_ci return 0; 66762306a36Sopenharmony_ci goto discard; 66862306a36Sopenharmony_ci } else if (dh->dccph_type == DCCP_PKT_CLOSE) { /* Step 14 */ 66962306a36Sopenharmony_ci if (dccp_rcv_close(sk, skb)) 67062306a36Sopenharmony_ci return 0; 67162306a36Sopenharmony_ci goto discard; 67262306a36Sopenharmony_ci } 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci switch (sk->sk_state) { 67562306a36Sopenharmony_ci case DCCP_REQUESTING: 67662306a36Sopenharmony_ci queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len); 67762306a36Sopenharmony_ci if (queued >= 0) 67862306a36Sopenharmony_ci return queued; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci __kfree_skb(skb); 68162306a36Sopenharmony_ci return 0; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci case DCCP_PARTOPEN: 68462306a36Sopenharmony_ci /* Step 8: if using Ack Vectors, mark packet acknowledgeable */ 68562306a36Sopenharmony_ci dccp_handle_ackvec_processing(sk, skb); 68662306a36Sopenharmony_ci dccp_deliver_input_to_ccids(sk, skb); 68762306a36Sopenharmony_ci fallthrough; 68862306a36Sopenharmony_ci case DCCP_RESPOND: 68962306a36Sopenharmony_ci queued = dccp_rcv_respond_partopen_state_process(sk, skb, 69062306a36Sopenharmony_ci dh, len); 69162306a36Sopenharmony_ci break; 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci if (dh->dccph_type == DCCP_PKT_ACK || 69562306a36Sopenharmony_ci dh->dccph_type == DCCP_PKT_DATAACK) { 69662306a36Sopenharmony_ci switch (old_state) { 69762306a36Sopenharmony_ci case DCCP_PARTOPEN: 69862306a36Sopenharmony_ci sk->sk_state_change(sk); 69962306a36Sopenharmony_ci sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT); 70062306a36Sopenharmony_ci break; 70162306a36Sopenharmony_ci } 70262306a36Sopenharmony_ci } else if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) { 70362306a36Sopenharmony_ci dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNCACK); 70462306a36Sopenharmony_ci goto discard; 70562306a36Sopenharmony_ci } 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci if (!queued) { 70862306a36Sopenharmony_cidiscard: 70962306a36Sopenharmony_ci __kfree_skb(skb); 71062306a36Sopenharmony_ci } 71162306a36Sopenharmony_ci return 0; 71262306a36Sopenharmony_ci} 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(dccp_rcv_state_process); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci/** 71762306a36Sopenharmony_ci * dccp_sample_rtt - Validate and finalise computation of RTT sample 71862306a36Sopenharmony_ci * @sk: socket structure 71962306a36Sopenharmony_ci * @delta: number of microseconds between packet and acknowledgment 72062306a36Sopenharmony_ci * 72162306a36Sopenharmony_ci * The routine is kept generic to work in different contexts. It should be 72262306a36Sopenharmony_ci * called immediately when the ACK used for the RTT sample arrives. 72362306a36Sopenharmony_ci */ 72462306a36Sopenharmony_ciu32 dccp_sample_rtt(struct sock *sk, long delta) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci /* dccpor_elapsed_time is either zeroed out or set and > 0 */ 72762306a36Sopenharmony_ci delta -= dccp_sk(sk)->dccps_options_received.dccpor_elapsed_time * 10; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci if (unlikely(delta <= 0)) { 73062306a36Sopenharmony_ci DCCP_WARN("unusable RTT sample %ld, using min\n", delta); 73162306a36Sopenharmony_ci return DCCP_SANE_RTT_MIN; 73262306a36Sopenharmony_ci } 73362306a36Sopenharmony_ci if (unlikely(delta > DCCP_SANE_RTT_MAX)) { 73462306a36Sopenharmony_ci DCCP_WARN("RTT sample %ld too large, using max\n", delta); 73562306a36Sopenharmony_ci return DCCP_SANE_RTT_MAX; 73662306a36Sopenharmony_ci } 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci return delta; 73962306a36Sopenharmony_ci} 740