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