xref: /mOS-networking-stack/core/src/tcp.c (revision 05e3289c)
176404edcSAsim Jamshed #include <assert.h>
276404edcSAsim Jamshed #include <string.h>
376404edcSAsim Jamshed 
476404edcSAsim Jamshed #include "mtcp.h"
576404edcSAsim Jamshed #include "arp.h"
676404edcSAsim Jamshed #include "socket.h"
776404edcSAsim Jamshed #include "eth_out.h"
876404edcSAsim Jamshed #include "ip_out.h"
976404edcSAsim Jamshed #include "mos_api.h"
1076404edcSAsim Jamshed #include "tcp_util.h"
1176404edcSAsim Jamshed #include "tcp_in.h"
1276404edcSAsim Jamshed #include "tcp_out.h"
1376404edcSAsim Jamshed #include "tcp_ring_buffer.h"
1476404edcSAsim Jamshed #include "eventpoll.h"
1576404edcSAsim Jamshed #include "debug.h"
1676404edcSAsim Jamshed #include "timer.h"
1776404edcSAsim Jamshed #include "ip_in.h"
1876404edcSAsim Jamshed #include "config.h"
1976404edcSAsim Jamshed 
2076404edcSAsim Jamshed extern struct pkt_info *
21a14d6bd4SAsim Jamshed ClonePacketCtx(struct pkt_info *to, unsigned char *frame, struct pkt_info *from);
2276404edcSAsim Jamshed 
2376404edcSAsim Jamshed #define VERIFY_RX_CHECKSUM	TRUE
2476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
2576404edcSAsim Jamshed static inline uint32_t
DetectStreamType(mtcp_manager_t mtcp,struct pkt_ctx * pctx,uint32_t ip,uint16_t port)2676404edcSAsim Jamshed DetectStreamType(mtcp_manager_t mtcp, struct pkt_ctx *pctx,
2776404edcSAsim Jamshed 				 uint32_t ip, uint16_t port)
2876404edcSAsim Jamshed {
2976404edcSAsim Jamshed 	/* To Do: We will extend this filter to check listeners for proxy as well */
3076404edcSAsim Jamshed 	struct sockaddr_in *addr;
3176404edcSAsim Jamshed 	int rc, cnt_match, socktype;
3276404edcSAsim Jamshed 	struct mon_listener *walk;
3376404edcSAsim Jamshed 	struct sfbpf_program fcode;
3476404edcSAsim Jamshed 
3576404edcSAsim Jamshed 	cnt_match = 0;
3676404edcSAsim Jamshed 	rc = 0;
3776404edcSAsim Jamshed 
3876404edcSAsim Jamshed 	if (mtcp->num_msp > 0) {
3976404edcSAsim Jamshed 		/* mtcp_bind_monitor_filter()
4076404edcSAsim Jamshed 		 * - create MonitorTCPStream only when the filter of any of the existing
4176404edcSAsim Jamshed 		 *   passive sockets match the incoming flow */
4276404edcSAsim Jamshed 		TAILQ_FOREACH(walk, &mtcp->monitors, link) {
4376404edcSAsim Jamshed 			/* For every passive monitor sockets, */
4476404edcSAsim Jamshed 			socktype = walk->socket->socktype;
4576404edcSAsim Jamshed 			if (socktype != MOS_SOCK_MONITOR_STREAM)
4676404edcSAsim Jamshed 				continue; // XXX: can this happen??
4776404edcSAsim Jamshed 
4876404edcSAsim Jamshed 			/* if pctx hits the filter rule, handle the passive monitor socket */
4976404edcSAsim Jamshed 			fcode = walk->stream_syn_fcode;
5076404edcSAsim Jamshed 			if (!(ISSET_BPFFILTER(fcode) && pctx &&
5176404edcSAsim Jamshed 				EVAL_BPFFILTER(fcode, (uint8_t *)pctx->p.iph - sizeof(struct ethhdr),
5276404edcSAsim Jamshed 							   pctx->p.ip_len + sizeof(struct ethhdr)) == 0)) {
5376404edcSAsim Jamshed 				walk->is_stream_syn_filter_hit = 1;// set the 'filter hit' flag to 1
5476404edcSAsim Jamshed 				cnt_match++; // count the number of matched sockets
5576404edcSAsim Jamshed 			}
5676404edcSAsim Jamshed 		}
5776404edcSAsim Jamshed 
5876404edcSAsim Jamshed 		/* if there's any passive monitoring socket whose filter is hit,
5976404edcSAsim Jamshed 		   we should create monitor stream */
6076404edcSAsim Jamshed 		if (cnt_match > 0)
6176404edcSAsim Jamshed 			rc = STREAM_TYPE(MOS_SOCK_MONITOR_STREAM_ACTIVE);
6276404edcSAsim Jamshed 	}
6376404edcSAsim Jamshed 
6476404edcSAsim Jamshed 	if (mtcp->listener) {
6576404edcSAsim Jamshed 		/* Detect end TCP stack mode */
6676404edcSAsim Jamshed 		addr = &mtcp->listener->socket->saddr;
6776404edcSAsim Jamshed 		if (addr->sin_port == port) {
6876404edcSAsim Jamshed 			if (addr->sin_addr.s_addr != INADDR_ANY) {
6976404edcSAsim Jamshed 				if (ip == addr->sin_addr.s_addr) {
7076404edcSAsim Jamshed 					rc |= STREAM_TYPE(MOS_SOCK_STREAM);
7176404edcSAsim Jamshed 				}
7276404edcSAsim Jamshed 			} else {
7376404edcSAsim Jamshed 				int i;
7476404edcSAsim Jamshed 
7576404edcSAsim Jamshed 				for (i = 0; i < g_config.mos->netdev_table->num; i++) {
7676404edcSAsim Jamshed 					if (ip == g_config.mos->netdev_table->ent[i]->ip_addr) {
7776404edcSAsim Jamshed 						rc |= STREAM_TYPE(MOS_SOCK_STREAM);
7876404edcSAsim Jamshed 					}
7976404edcSAsim Jamshed 				}
8076404edcSAsim Jamshed 			}
8176404edcSAsim Jamshed 		}
8276404edcSAsim Jamshed 	}
8376404edcSAsim Jamshed 
8476404edcSAsim Jamshed 	return rc;
8576404edcSAsim Jamshed }
8676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
8776404edcSAsim Jamshed static inline tcp_stream *
CreateServerStream(mtcp_manager_t mtcp,int type,struct pkt_ctx * pctx)8876404edcSAsim Jamshed CreateServerStream(mtcp_manager_t mtcp, int type, struct pkt_ctx *pctx)
8976404edcSAsim Jamshed {
9076404edcSAsim Jamshed 	tcp_stream *cur_stream = NULL;
9176404edcSAsim Jamshed 
9276404edcSAsim Jamshed 	/* create new stream and add to flow hash table */
9376404edcSAsim Jamshed 	cur_stream = CreateTCPStream(mtcp, NULL, type,
9476404edcSAsim Jamshed 			pctx->p.iph->daddr, pctx->p.tcph->dest,
9576404edcSAsim Jamshed 			pctx->p.iph->saddr, pctx->p.tcph->source, NULL);
9676404edcSAsim Jamshed 	if (!cur_stream) {
9776404edcSAsim Jamshed 		TRACE_ERROR("INFO: Could not allocate tcp_stream!\n");
9876404edcSAsim Jamshed 		return FALSE;
9976404edcSAsim Jamshed 	}
10076404edcSAsim Jamshed 
10176404edcSAsim Jamshed 	cur_stream->rcvvar->irs = pctx->p.seq;
10276404edcSAsim Jamshed 	cur_stream->sndvar->peer_wnd = pctx->p.window;
10376404edcSAsim Jamshed 	cur_stream->rcv_nxt = cur_stream->rcvvar->irs;
10476404edcSAsim Jamshed 	cur_stream->sndvar->cwnd = 1;
10576404edcSAsim Jamshed 	ParseTCPOptions(cur_stream, pctx->p.cur_ts, (uint8_t *)pctx->p.tcph +
10676404edcSAsim Jamshed 			TCP_HEADER_LEN, (pctx->p.tcph->doff << 2) - TCP_HEADER_LEN);
10776404edcSAsim Jamshed 
10876404edcSAsim Jamshed 	return cur_stream;
10976404edcSAsim Jamshed }
11076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
11176404edcSAsim Jamshed static inline tcp_stream *
CreateMonitorStream(mtcp_manager_t mtcp,struct pkt_ctx * pctx,uint32_t stream_type,unsigned int * hash)11276404edcSAsim Jamshed CreateMonitorStream(mtcp_manager_t mtcp, struct pkt_ctx* pctx,
11376404edcSAsim Jamshed 		    uint32_t stream_type, unsigned int *hash)
11476404edcSAsim Jamshed {
11576404edcSAsim Jamshed 	tcp_stream *stream = NULL;
11676404edcSAsim Jamshed 	struct socket_map *walk;
11776404edcSAsim Jamshed 	/* create a client stream context */
11876404edcSAsim Jamshed 	stream = CreateDualTCPStream(mtcp, NULL, stream_type, pctx->p.iph->daddr,
11976404edcSAsim Jamshed 				     pctx->p.tcph->dest, pctx->p.iph->saddr,
12076404edcSAsim Jamshed 				     pctx->p.tcph->source, NULL);
12176404edcSAsim Jamshed 	if (!stream)
12276404edcSAsim Jamshed 		return FALSE;
12376404edcSAsim Jamshed 
12476404edcSAsim Jamshed 	stream->side = MOS_SIDE_CLI;
12576404edcSAsim Jamshed 	stream->pair_stream->side = MOS_SIDE_SVR;
12676404edcSAsim Jamshed 	/* update recv context */
12776404edcSAsim Jamshed 	stream->rcvvar->irs = pctx->p.seq;
12876404edcSAsim Jamshed 	stream->sndvar->peer_wnd = pctx->p.window;
12976404edcSAsim Jamshed 	stream->rcv_nxt = stream->rcvvar->irs + 1;
13076404edcSAsim Jamshed 	stream->sndvar->cwnd = 1;
13176404edcSAsim Jamshed 
13276404edcSAsim Jamshed 	/*
13376404edcSAsim Jamshed 	 * if buffer management is off, then disable
13476404edcSAsim Jamshed 	 * monitoring tcp ring of either streams (only if stream
13576404edcSAsim Jamshed 	 * is just monitor stream active)
13676404edcSAsim Jamshed 	 */
13776404edcSAsim Jamshed 	if (IS_STREAM_TYPE(stream, MOS_SOCK_MONITOR_STREAM_ACTIVE)) {
13876404edcSAsim Jamshed 		assert(IS_STREAM_TYPE(stream->pair_stream,
13976404edcSAsim Jamshed 				      MOS_SOCK_MONITOR_STREAM_ACTIVE));
14076404edcSAsim Jamshed 
14176404edcSAsim Jamshed 		stream->buffer_mgmt = FALSE;
14276404edcSAsim Jamshed 		stream->pair_stream->buffer_mgmt = FALSE;
14376404edcSAsim Jamshed 
14476404edcSAsim Jamshed 		/*
14576404edcSAsim Jamshed 		 * if there is even a single monitor asking for
14676404edcSAsim Jamshed 		 * buffer management, enable it (that's why the
14776404edcSAsim Jamshed 		 * need for the loop)
14876404edcSAsim Jamshed 		 */
14976404edcSAsim Jamshed 		uint8_t bm;
15076404edcSAsim Jamshed 		stream->status_mgmt = 0;
15176404edcSAsim Jamshed 		SOCKQ_FOREACH_START(walk, &stream->msocks) {
15276404edcSAsim Jamshed 			bm = walk->monitor_stream->monitor_listener->server_buf_mgmt;
15376404edcSAsim Jamshed 			if (bm > stream->buffer_mgmt) {
15476404edcSAsim Jamshed 				stream->buffer_mgmt = bm;
15576404edcSAsim Jamshed 			}
15676404edcSAsim Jamshed 			if (walk->monitor_stream->monitor_listener->server_mon == 1) {
15776404edcSAsim Jamshed 				stream->status_mgmt = 1;
15876404edcSAsim Jamshed 			}
15976404edcSAsim Jamshed 		} SOCKQ_FOREACH_END;
16076404edcSAsim Jamshed 
16176404edcSAsim Jamshed 		stream->pair_stream->status_mgmt = 0;
16276404edcSAsim Jamshed 		SOCKQ_FOREACH_START(walk, &stream->pair_stream->msocks) {
16376404edcSAsim Jamshed 			bm = walk->monitor_stream->monitor_listener->client_buf_mgmt;
16476404edcSAsim Jamshed 			if (bm > stream->pair_stream->buffer_mgmt) {
16576404edcSAsim Jamshed 				stream->pair_stream->buffer_mgmt = bm;
16676404edcSAsim Jamshed 			}
16776404edcSAsim Jamshed 			if (walk->monitor_stream->monitor_listener->client_mon == 1) {
16876404edcSAsim Jamshed 				stream->pair_stream->status_mgmt = 1;
16976404edcSAsim Jamshed 			}
17076404edcSAsim Jamshed 		} SOCKQ_FOREACH_END;
17176404edcSAsim Jamshed 	}
17276404edcSAsim Jamshed 
17376404edcSAsim Jamshed 	ParseTCPOptions(stream, pctx->p.cur_ts,
17476404edcSAsim Jamshed 			(uint8_t *)pctx->p.tcph + TCP_HEADER_LEN,
17576404edcSAsim Jamshed 			(pctx->p.tcph->doff << 2) - TCP_HEADER_LEN);
17676404edcSAsim Jamshed 
17776404edcSAsim Jamshed 	return stream;
17876404edcSAsim Jamshed }
17976404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
18076404edcSAsim Jamshed static inline struct tcp_stream *
FindStream(mtcp_manager_t mtcp,struct pkt_ctx * pctx,unsigned int * hash)18176404edcSAsim Jamshed FindStream(mtcp_manager_t mtcp, struct pkt_ctx *pctx, unsigned int *hash)
18276404edcSAsim Jamshed {
18376404edcSAsim Jamshed 	struct tcp_stream temp_stream;
18476404edcSAsim Jamshed 
18576404edcSAsim Jamshed 	temp_stream.saddr = pctx->p.iph->daddr;
18676404edcSAsim Jamshed 	temp_stream.sport = pctx->p.tcph->dest;
18776404edcSAsim Jamshed 	temp_stream.daddr = pctx->p.iph->saddr;
18876404edcSAsim Jamshed 	temp_stream.dport = pctx->p.tcph->source;
18976404edcSAsim Jamshed 
19076404edcSAsim Jamshed 	return HTSearch(mtcp->tcp_flow_table, &temp_stream, hash);
19176404edcSAsim Jamshed }
19276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
19376404edcSAsim Jamshed /* Create new flow for new packet or return NULL */
19476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
19576404edcSAsim Jamshed static inline struct tcp_stream *
CreateStream(mtcp_manager_t mtcp,struct pkt_ctx * pctx,unsigned int * hash)19676404edcSAsim Jamshed CreateStream(mtcp_manager_t mtcp, struct pkt_ctx *pctx, unsigned int *hash)
19776404edcSAsim Jamshed {
19876404edcSAsim Jamshed 	tcp_stream *cur_stream = NULL;
19976404edcSAsim Jamshed 	uint32_t stream_type;
20076404edcSAsim Jamshed 	const struct iphdr *iph = pctx->p.iph;
20176404edcSAsim Jamshed 	const struct tcphdr* tcph = pctx->p.tcph;
20276404edcSAsim Jamshed 
20376404edcSAsim Jamshed 	if (tcph->syn && !tcph->ack) {
20476404edcSAsim Jamshed 		/* handle the SYN */
20576404edcSAsim Jamshed 
20676404edcSAsim Jamshed 		stream_type = DetectStreamType(mtcp, pctx, iph->daddr, tcph->dest);
20776404edcSAsim Jamshed 		if (!stream_type) {
20876404edcSAsim Jamshed 			TRACE_DBG("Refusing SYN packet.\n");
20976404edcSAsim Jamshed #ifdef DBGMSG
21076404edcSAsim Jamshed 			DumpIPPacket(mtcp, iph, pctx->p.ip_len);
21176404edcSAsim Jamshed #endif
21276404edcSAsim Jamshed 			return NULL;
21376404edcSAsim Jamshed 		}
21476404edcSAsim Jamshed 
21576404edcSAsim Jamshed 		/* if it is accepting connections only */
21676404edcSAsim Jamshed 		if (stream_type == STREAM_TYPE(MOS_SOCK_STREAM)) {
21776404edcSAsim Jamshed 			cur_stream = CreateServerStream(mtcp, stream_type, pctx);
21876404edcSAsim Jamshed 			if (!cur_stream) {
21976404edcSAsim Jamshed 				TRACE_DBG("No available space in flow pool.\n");
22076404edcSAsim Jamshed #ifdef DBGMSG
22176404edcSAsim Jamshed 				DumpIPPacket(mtcp, iph, pctx->p.ip_len);
22276404edcSAsim Jamshed #endif
22376404edcSAsim Jamshed 			}
22476404edcSAsim Jamshed 		} else if (stream_type & STREAM_TYPE(MOS_SOCK_MONITOR_STREAM_ACTIVE)) {
22576404edcSAsim Jamshed 			/*
22676404edcSAsim Jamshed 			 * create both monitoring streams, and accept
22776404edcSAsim Jamshed 			 * connection if it is set in embedded environment
22876404edcSAsim Jamshed 			 */
22976404edcSAsim Jamshed #if 1
23076404edcSAsim Jamshed 			cur_stream = CreateClientTCPStream(mtcp, NULL, stream_type,
23176404edcSAsim Jamshed 									pctx->p.iph->saddr, pctx->p.tcph->source,
23276404edcSAsim Jamshed 									pctx->p.iph->daddr, pctx->p.tcph->dest,
23376404edcSAsim Jamshed 									hash);
23476404edcSAsim Jamshed #else
23576404edcSAsim Jamshed 			cur_stream = CreateMonitorStream(mtcp, pctx, stream_type, hash);
23676404edcSAsim Jamshed #endif
23776404edcSAsim Jamshed 			if (!cur_stream) {
23876404edcSAsim Jamshed 				TRACE_DBG("No available space in flow pool.\n");
23976404edcSAsim Jamshed #ifdef DBGMSG
24076404edcSAsim Jamshed 				DumpIPPacket(mtcp, iph, pctx->p.ip_len);
24176404edcSAsim Jamshed #endif
24276404edcSAsim Jamshed 			}
24376404edcSAsim Jamshed 		}  else {
24476404edcSAsim Jamshed 			/* invalid stream type! */
24576404edcSAsim Jamshed 		}
24676404edcSAsim Jamshed 
24776404edcSAsim Jamshed 		return cur_stream;
24876404edcSAsim Jamshed 
24976404edcSAsim Jamshed 	} else {
25076404edcSAsim Jamshed 		TRACE_DBG("Weird packet comes.\n");
25176404edcSAsim Jamshed #ifdef DBGMSG
25276404edcSAsim Jamshed 		DumpIPPacket(mtcp, iph, pctx->p.ip_len);
25376404edcSAsim Jamshed #endif
25476404edcSAsim Jamshed 		return NULL;
25576404edcSAsim Jamshed 	}
25676404edcSAsim Jamshed }
25776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
25876404edcSAsim Jamshed inline void
FillPacketContextTCPInfo(struct pkt_ctx * pctx,struct tcphdr * tcph)25976404edcSAsim Jamshed FillPacketContextTCPInfo(struct pkt_ctx *pctx, struct tcphdr * tcph)
26076404edcSAsim Jamshed {
26176404edcSAsim Jamshed 	pctx->p.tcph = tcph;
26276404edcSAsim Jamshed 	pctx->p.payload    = (uint8_t *)tcph + (tcph->doff << 2);
26376404edcSAsim Jamshed 	pctx->p.payloadlen = pctx->p.ip_len - (pctx->p.payload - (u_char *)pctx->p.iph);
26476404edcSAsim Jamshed 	pctx->p.seq = ntohl(tcph->seq);
26576404edcSAsim Jamshed 	pctx->p.ack_seq = ntohl(tcph->ack_seq);
26676404edcSAsim Jamshed 	pctx->p.window = ntohs(tcph->window);
26776404edcSAsim Jamshed 	pctx->p.offset = 0;
26876404edcSAsim Jamshed 
26976404edcSAsim Jamshed 	return ;
27076404edcSAsim Jamshed }
27176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
27276404edcSAsim Jamshed /**
27376404edcSAsim Jamshed  * Called for every incoming packet from the NIC (when monitoring is disabled)
27476404edcSAsim Jamshed  */
27576404edcSAsim Jamshed static void
HandleSockStream(mtcp_manager_t mtcp,struct tcp_stream * cur_stream,struct pkt_ctx * pctx)27676404edcSAsim Jamshed HandleSockStream(mtcp_manager_t mtcp, struct tcp_stream *cur_stream,
27776404edcSAsim Jamshed 				struct pkt_ctx *pctx)
27876404edcSAsim Jamshed {
27976404edcSAsim Jamshed 	UpdateRecvTCPContext(mtcp, cur_stream, pctx);
28076404edcSAsim Jamshed 	DoActionEndTCPPacket(mtcp, cur_stream, pctx);
28176404edcSAsim Jamshed }
28276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
28376404edcSAsim Jamshed void
UpdateMonitor(mtcp_manager_t mtcp,struct tcp_stream * sendside_stream,struct tcp_stream * recvside_stream,struct pkt_ctx * pctx,bool is_pkt_reception)28476404edcSAsim Jamshed UpdateMonitor(mtcp_manager_t mtcp, struct tcp_stream *sendside_stream,
28576404edcSAsim Jamshed 			struct tcp_stream *recvside_stream, struct pkt_ctx *pctx,
28676404edcSAsim Jamshed 			bool is_pkt_reception)
28776404edcSAsim Jamshed {
28876404edcSAsim Jamshed 	struct socket_map *walk;
28976404edcSAsim Jamshed 
29076404edcSAsim Jamshed 	assert(pctx);
29176404edcSAsim Jamshed 
292a14d6bd4SAsim Jamshed #ifdef RECORDPKT_PER_STREAM
29376404edcSAsim Jamshed 	/* clone sendside_stream even if sender is disabled */
29476404edcSAsim Jamshed 	ClonePacketCtx(&sendside_stream->last_pctx.p,
295a14d6bd4SAsim Jamshed 		       sendside_stream->last_pkt_data, &(pctx.p));
296a14d6bd4SAsim Jamshed #endif
297*05e3289cSYoungGyoun 
29876404edcSAsim Jamshed 	/* update send stream context first */
29976404edcSAsim Jamshed 	if (sendside_stream->status_mgmt) {
30076404edcSAsim Jamshed 		sendside_stream->cb_events = MOS_ON_PKT_IN;
30176404edcSAsim Jamshed 
30276404edcSAsim Jamshed 		if (is_pkt_reception)
30376404edcSAsim Jamshed 			UpdatePassiveSendTCPContext(mtcp, sendside_stream, pctx);
30476404edcSAsim Jamshed 
30576404edcSAsim Jamshed 		sendside_stream->allow_pkt_modification = true;
30676404edcSAsim Jamshed 		/* POST hook of sender */
307*05e3289cSYoungGyoun 		if (sendside_stream->side == MOS_SIDE_CLI) {
30876404edcSAsim Jamshed 			SOCKQ_FOREACH_START(walk, &sendside_stream->msocks) {
30976404edcSAsim Jamshed 				HandleCallback(mtcp, MOS_HK_SND, walk, sendside_stream->side,
31076404edcSAsim Jamshed 					       pctx, sendside_stream->cb_events);
31176404edcSAsim Jamshed 			} SOCKQ_FOREACH_END;
312*05e3289cSYoungGyoun 		} else { /* sendside_stream->side == MOS_SIDE_SVR */
313*05e3289cSYoungGyoun 			SOCKQ_FOREACH_REVERSE(walk, &sendside_stream->msocks) {
314*05e3289cSYoungGyoun 				HandleCallback(mtcp, MOS_HK_SND, walk, sendside_stream->side,
315*05e3289cSYoungGyoun 					       pctx, sendside_stream->cb_events);
316*05e3289cSYoungGyoun 			} SOCKQ_FOREACH_END;
317*05e3289cSYoungGyoun 		}
31876404edcSAsim Jamshed 		sendside_stream->allow_pkt_modification = false;
31976404edcSAsim Jamshed 	}
32076404edcSAsim Jamshed 
32176404edcSAsim Jamshed 	/* Attach Server-side stream */
32276404edcSAsim Jamshed 	if (recvside_stream == NULL) {
32376404edcSAsim Jamshed 		assert(sendside_stream->side == MOS_SIDE_CLI);
32476404edcSAsim Jamshed 		if ((recvside_stream = AttachServerTCPStream(mtcp, sendside_stream, 0,
32576404edcSAsim Jamshed 				pctx->p.iph->saddr, pctx->p.tcph->source,
32676404edcSAsim Jamshed 				pctx->p.iph->daddr, pctx->p.tcph->dest)) == NULL) {
32776404edcSAsim Jamshed 			DestroyTCPStream(mtcp, sendside_stream);
32876404edcSAsim Jamshed 			return;
32976404edcSAsim Jamshed 		}
33076404edcSAsim Jamshed 		/* update recv context */
33176404edcSAsim Jamshed 		recvside_stream->rcvvar->irs = pctx->p.seq;
33276404edcSAsim Jamshed 		recvside_stream->sndvar->peer_wnd = pctx->p.window;
33376404edcSAsim Jamshed 		recvside_stream->rcv_nxt = recvside_stream->rcvvar->irs + 1;
33476404edcSAsim Jamshed 		recvside_stream->sndvar->cwnd = 1;
33576404edcSAsim Jamshed 
33676404edcSAsim Jamshed 		ParseTCPOptions(recvside_stream, pctx->p.cur_ts,
33776404edcSAsim Jamshed 				(uint8_t *)pctx->p.tcph + TCP_HEADER_LEN,
33876404edcSAsim Jamshed 				(pctx->p.tcph->doff << 2) - TCP_HEADER_LEN);
33976404edcSAsim Jamshed 	}
34076404edcSAsim Jamshed 
34176404edcSAsim Jamshed 	/* Perform post-send tcp activities */
34276404edcSAsim Jamshed 	PostSendTCPAction(mtcp, pctx, recvside_stream, sendside_stream);
34376404edcSAsim Jamshed 
34476404edcSAsim Jamshed 	if (/*1*/recvside_stream->status_mgmt) {
34576404edcSAsim Jamshed 		recvside_stream->cb_events = MOS_ON_PKT_IN;
34676404edcSAsim Jamshed 
34776404edcSAsim Jamshed 		/* Predict events which may be raised prior to performing TCP processing */
34876404edcSAsim Jamshed 		PreRecvTCPEventPrediction(mtcp, pctx, recvside_stream);
34976404edcSAsim Jamshed 
35076404edcSAsim Jamshed 		/* retransmitted packet should avoid event simulation */
35176404edcSAsim Jamshed 		//if ((recvside_stream->cb_events & MOS_ON_REXMIT) == 0)
35276404edcSAsim Jamshed 			/* update receive stream context (recv_side stream) */
35376404edcSAsim Jamshed 		if (is_pkt_reception)
35476404edcSAsim Jamshed 			UpdateRecvTCPContext(mtcp, recvside_stream, pctx);
35576404edcSAsim Jamshed 		else
35676404edcSAsim Jamshed 			UpdatePassiveRecvTCPContext(mtcp, recvside_stream, pctx);
35776404edcSAsim Jamshed 
35876404edcSAsim Jamshed 		/* POST hook of receiver */
359*05e3289cSYoungGyoun 		if (recvside_stream->side == MOS_SIDE_CLI) {
360*05e3289cSYoungGyoun 			SOCKQ_FOREACH_REVERSE(walk, &recvside_stream->msocks) {
361*05e3289cSYoungGyoun 				HandleCallback(mtcp, MOS_HK_RCV, walk, recvside_stream->side,
362*05e3289cSYoungGyoun 					       pctx, recvside_stream->cb_events);
363*05e3289cSYoungGyoun 			} SOCKQ_FOREACH_END;
364*05e3289cSYoungGyoun 		} else { /* recvside_stream->side == MOS_SIDE_SVR */
36576404edcSAsim Jamshed 			SOCKQ_FOREACH_START(walk, &recvside_stream->msocks) {
36676404edcSAsim Jamshed 				HandleCallback(mtcp, MOS_HK_RCV, walk, recvside_stream->side,
36776404edcSAsim Jamshed 					       pctx, recvside_stream->cb_events);
36876404edcSAsim Jamshed 			} SOCKQ_FOREACH_END;
36976404edcSAsim Jamshed 		}
370*05e3289cSYoungGyoun 	}
37176404edcSAsim Jamshed 
37276404edcSAsim Jamshed 	/* reset callback events counter */
37376404edcSAsim Jamshed 	recvside_stream->cb_events = 0;
37476404edcSAsim Jamshed 	sendside_stream->cb_events = 0;
37576404edcSAsim Jamshed }
37676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
37776404edcSAsim Jamshed static void
HandleMonitorStream(mtcp_manager_t mtcp,struct tcp_stream * sendside_stream,struct tcp_stream * recvside_stream,struct pkt_ctx * pctx)37876404edcSAsim Jamshed HandleMonitorStream(mtcp_manager_t mtcp, struct tcp_stream *sendside_stream,
37976404edcSAsim Jamshed 			struct tcp_stream *recvside_stream, struct pkt_ctx *pctx)
38076404edcSAsim Jamshed {
38176404edcSAsim Jamshed 	UpdateMonitor(mtcp, sendside_stream, recvside_stream, pctx, true);
38276404edcSAsim Jamshed 
38376404edcSAsim Jamshed 	recvside_stream = sendside_stream->pair_stream;
38476404edcSAsim Jamshed 
38576404edcSAsim Jamshed 	if (HAS_STREAM_TYPE(recvside_stream, MOS_SOCK_STREAM)) {
38676404edcSAsim Jamshed 		DoActionEndTCPPacket(mtcp, recvside_stream, pctx);
38776404edcSAsim Jamshed 	} else {
38876404edcSAsim Jamshed 		/* forward packets */
38976404edcSAsim Jamshed 		if (pctx->forward)
39076404edcSAsim Jamshed 			ForwardIPPacket(mtcp, pctx);
39176404edcSAsim Jamshed 
39276404edcSAsim Jamshed 		if (recvside_stream->stream_type == sendside_stream->stream_type &&
39376404edcSAsim Jamshed 		    IS_STREAM_TYPE(recvside_stream, MOS_SOCK_MONITOR_STREAM_ACTIVE)) {
39476404edcSAsim Jamshed 			if (((recvside_stream->state == TCP_ST_TIME_WAIT &&
39576404edcSAsim Jamshed 				  g_config.mos->tcp_tw_interval == 0) ||
39676404edcSAsim Jamshed 			     recvside_stream->state == TCP_ST_CLOSED_RSVD ||
39776404edcSAsim Jamshed 			     !recvside_stream->status_mgmt) &&
39876404edcSAsim Jamshed 			    ((sendside_stream->state == TCP_ST_TIME_WAIT &&
39976404edcSAsim Jamshed 				  g_config.mos->tcp_tw_interval == 0) ||
40076404edcSAsim Jamshed 			     sendside_stream->state == TCP_ST_CLOSED_RSVD ||
40176404edcSAsim Jamshed 			     !sendside_stream->status_mgmt))
40276404edcSAsim Jamshed 
40376404edcSAsim Jamshed 				DestroyTCPStream(mtcp, recvside_stream);
40476404edcSAsim Jamshed 		}
40576404edcSAsim Jamshed 	}
40676404edcSAsim Jamshed }
40776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
40876404edcSAsim Jamshed int
ProcessInTCPPacket(mtcp_manager_t mtcp,struct pkt_ctx * pctx)40976404edcSAsim Jamshed ProcessInTCPPacket(mtcp_manager_t mtcp, struct pkt_ctx *pctx)
41076404edcSAsim Jamshed {
41176404edcSAsim Jamshed 	uint64_t events = 0;
41276404edcSAsim Jamshed 	struct tcp_stream *cur_stream;
41376404edcSAsim Jamshed 	struct iphdr* iph;
41476404edcSAsim Jamshed 	struct tcphdr* tcph;
41576404edcSAsim Jamshed 	struct mon_listener *walk;
41676404edcSAsim Jamshed 	unsigned int hash = 0;
41776404edcSAsim Jamshed 
41876404edcSAsim Jamshed 	iph = pctx->p.iph;
41976404edcSAsim Jamshed 	tcph = (struct tcphdr *)((u_char *)pctx->p.iph + (pctx->p.iph->ihl << 2));
42076404edcSAsim Jamshed 
42176404edcSAsim Jamshed 	FillPacketContextTCPInfo(pctx, tcph);
42276404edcSAsim Jamshed 
42376404edcSAsim Jamshed 	/* callback for monitor raw socket */
42476404edcSAsim Jamshed 	TAILQ_FOREACH(walk, &mtcp->monitors, link)
42576404edcSAsim Jamshed 		if (walk->socket->socktype == MOS_SOCK_MONITOR_RAW)
42676404edcSAsim Jamshed 			HandleCallback(mtcp, MOS_NULL, walk->socket, MOS_SIDE_BOTH,
42776404edcSAsim Jamshed 				       pctx, MOS_ON_PKT_IN);
42876404edcSAsim Jamshed 
42976404edcSAsim Jamshed 	if (pctx->p.ip_len < ((iph->ihl + tcph->doff) << 2))
43076404edcSAsim Jamshed 		return ERROR;
43176404edcSAsim Jamshed 
43276404edcSAsim Jamshed #if VERIFY_RX_CHECKSUM
43376404edcSAsim Jamshed 	if (TCPCalcChecksum((uint16_t *)pctx->p.tcph,
43476404edcSAsim Jamshed 						(tcph->doff << 2) + pctx->p.payloadlen,
43576404edcSAsim Jamshed 						iph->saddr, pctx->p.iph->daddr)) {
43676404edcSAsim Jamshed 		TRACE_DBG("Checksum Error: Original: 0x%04x, calculated: 0x%04x\n",
43776404edcSAsim Jamshed 				tcph->check, TCPCalcChecksum((uint16_t *)tcph,
438cafe7743SAsim Jamshed 				(tcph->doff << 2) + pctx->p.payloadlen,
43976404edcSAsim Jamshed 				iph->saddr, iph->daddr));
44076404edcSAsim Jamshed 		if (pctx->forward && mtcp->num_msp)
44176404edcSAsim Jamshed 			ForwardIPPacket(mtcp, pctx);
44276404edcSAsim Jamshed 		return ERROR;
44376404edcSAsim Jamshed 	}
44476404edcSAsim Jamshed #endif
44576404edcSAsim Jamshed 	events |= MOS_ON_PKT_IN;
44676404edcSAsim Jamshed 
44776404edcSAsim Jamshed 	/* Check whether a packet is belong to any stream */
44876404edcSAsim Jamshed 	cur_stream = FindStream(mtcp, pctx, &hash);
44976404edcSAsim Jamshed 	if (!cur_stream) {
45076404edcSAsim Jamshed 		/*
45176404edcSAsim Jamshed 		 * No need to create stream for monitor.
45276404edcSAsim Jamshed 		 *  But do create 1 for client case!
45376404edcSAsim Jamshed 		 */
45476404edcSAsim Jamshed 		if (mtcp->listener == NULL && mtcp->num_msp == 0) {
45576404edcSAsim Jamshed 			//if (pctx->forward)
45676404edcSAsim Jamshed 			//	ForwardIPPacket(mtcp, pctx);
45776404edcSAsim Jamshed 			return TRUE;
45876404edcSAsim Jamshed 		}
45976404edcSAsim Jamshed 		/* Create new flow for new packet or return NULL */
46076404edcSAsim Jamshed 		cur_stream = CreateStream(mtcp, pctx, &hash);
46176404edcSAsim Jamshed 		if (!cur_stream)
46276404edcSAsim Jamshed 			events = MOS_ON_ORPHAN;
46376404edcSAsim Jamshed 	}
46476404edcSAsim Jamshed 
46576404edcSAsim Jamshed 	if (cur_stream) {
46676404edcSAsim Jamshed 		cur_stream->cb_events = events;
46776404edcSAsim Jamshed 
46876404edcSAsim Jamshed 		if (cur_stream->rcvvar && cur_stream->rcvvar->rcvbuf)
46976404edcSAsim Jamshed 			pctx->p.offset = (uint64_t)seq2loff(cur_stream->rcvvar->rcvbuf,
47076404edcSAsim Jamshed 					pctx->p.seq, cur_stream->rcvvar->irs + 1);
47176404edcSAsim Jamshed 
47276404edcSAsim Jamshed 		if (IS_STREAM_TYPE(cur_stream, MOS_SOCK_STREAM))
47376404edcSAsim Jamshed 			HandleSockStream(mtcp, cur_stream, pctx);
47476404edcSAsim Jamshed 
47576404edcSAsim Jamshed 		else if (HAS_STREAM_TYPE(cur_stream, MOS_SOCK_MONITOR_STREAM_ACTIVE))
47676404edcSAsim Jamshed 			HandleMonitorStream(mtcp, cur_stream, cur_stream->pair_stream, pctx);
47776404edcSAsim Jamshed 		else
47876404edcSAsim Jamshed 			assert(0);
47976404edcSAsim Jamshed 	} else {
48076404edcSAsim Jamshed 		struct mon_listener *walk;
48176404edcSAsim Jamshed 		struct sfbpf_program fcode;
48276404edcSAsim Jamshed 		/*
48376404edcSAsim Jamshed 		 * event callback for pkt_no_conn; MOS_SIDE_BOTH
48476404edcSAsim Jamshed 		 * means that we can't judge sides here
48576404edcSAsim Jamshed 		 */
48676404edcSAsim Jamshed 		TAILQ_FOREACH(walk, &mtcp->monitors, link) {
48776404edcSAsim Jamshed 			/* mtcp_bind_monitor_filter()
48876404edcSAsim Jamshed 			 * - apply stream orphan filter to every pkt before raising ORPHAN event */
48976404edcSAsim Jamshed 			fcode = walk->stream_orphan_fcode;
49076404edcSAsim Jamshed 			if (!(ISSET_BPFFILTER(fcode) && pctx &&
49176404edcSAsim Jamshed 				EVAL_BPFFILTER(fcode, (uint8_t *)pctx->p.iph - sizeof(struct ethhdr),
49276404edcSAsim Jamshed 							   pctx->p.ip_len + sizeof(struct ethhdr)) == 0)) {
49376404edcSAsim Jamshed 				HandleCallback(mtcp, MOS_NULL, walk->socket, MOS_SIDE_BOTH,
49476404edcSAsim Jamshed 					       pctx, events);
49576404edcSAsim Jamshed 			}
49676404edcSAsim Jamshed 		}
49776404edcSAsim Jamshed 		if (mtcp->listener) {
498af399fe0SAsim Jamshed 			/* RFC 793 (page 65) says
499af399fe0SAsim Jamshed 			   "An incoming segment containing a RST is discarded."
500af399fe0SAsim Jamshed 			   if the TCP state is CLOSED (= TCP stream does not exist). */
501af399fe0SAsim Jamshed 			if (!tcph->rst)
50276404edcSAsim Jamshed 				/* Send RST if it is run as EndTCP only mode */
50376404edcSAsim Jamshed 				SendTCPPacketStandalone(mtcp,
50476404edcSAsim Jamshed 							iph->daddr, tcph->dest, iph->saddr, tcph->source,
505*05e3289cSYoungGyoun 							0, pctx->p.seq + pctx->p.payloadlen + 1, 0,
506*05e3289cSYoungGyoun 							TCP_FLAG_RST | TCP_FLAG_ACK,
507a834ea89SAsim Jamshed 							NULL, 0, pctx->p.cur_ts, 0, 0, -1);
50876404edcSAsim Jamshed 		} else if (pctx->forward) {
50976404edcSAsim Jamshed 			/* Do forward or drop if it run as Monitor only mode */
51076404edcSAsim Jamshed 			ForwardIPPacket(mtcp, pctx);
51176404edcSAsim Jamshed 		}
51276404edcSAsim Jamshed 	}
51376404edcSAsim Jamshed 
51476404edcSAsim Jamshed 	return TRUE;
51576404edcSAsim Jamshed }
51676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
517