xref: /openbmc/linux/net/dccp/input.c (revision 58e45131dc269eff0983c6d44494f9e687686900)
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