xref: /mOS-networking-stack/core/src/mos_api.c (revision 861ea7df)
176404edcSAsim Jamshed #include <assert.h>
276404edcSAsim Jamshed #include <ctype.h>
376404edcSAsim Jamshed #include <string.h>
476404edcSAsim Jamshed #ifdef ENABLE_DEBUG_EVENT
576404edcSAsim Jamshed #include <stdarg.h>
676404edcSAsim Jamshed #endif
776404edcSAsim Jamshed 
876404edcSAsim Jamshed #include "mtcp.h"
976404edcSAsim Jamshed #include "mos_api.h"
1076404edcSAsim Jamshed #include "debug.h"
1176404edcSAsim Jamshed #include "config.h"
1276404edcSAsim Jamshed #include "ip_in.h"
1376404edcSAsim Jamshed #include "tcp_out.h"
1476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1576404edcSAsim Jamshed #define MAX(x, y) (((x) > (y)) ? (x) : (y))
1676404edcSAsim Jamshed #define MIN(x, y) (((x) < (y)) ? (x) : (y))
1776404edcSAsim Jamshed #define SKIP_SPACES(x) while (*x && isspace((int)*x)) x++;
1876404edcSAsim Jamshed #define SKIP_CHAR(x) while((*x) && !isspace(*x)) x++;
1976404edcSAsim Jamshed 
2076404edcSAsim Jamshed #define KW_AND       "and "
2176404edcSAsim Jamshed #define KW_OR        "or "
2276404edcSAsim Jamshed #define KW_NOT       "not "
2376404edcSAsim Jamshed #define KW_TCP       "tcp"
2476404edcSAsim Jamshed #define KW_NOT_TCP   "!tcp"
2576404edcSAsim Jamshed #define KW_NOT_TCP2  "not tcp"
2676404edcSAsim Jamshed #define KW_SRC       "src "
2776404edcSAsim Jamshed #define KW_DST       "dst "
2876404edcSAsim Jamshed #define KW_HOST      "host "
2976404edcSAsim Jamshed #define KW_NET       "net "
3076404edcSAsim Jamshed #define KW_MASK      "mask "
3176404edcSAsim Jamshed #define KW_PORT      "port "
3276404edcSAsim Jamshed #define KW_PORTRANGE "portrange "
3376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
3476404edcSAsim Jamshed int
3576404edcSAsim Jamshed IsValidFlowRule(char *cf)
3676404edcSAsim Jamshed {
3776404edcSAsim Jamshed 	char *word;
3876404edcSAsim Jamshed 	int skip_word = 0;
3976404edcSAsim Jamshed 
4076404edcSAsim Jamshed 	/* '!tcp' or 'not tcp' are also not supported in TCP flow filter */
4176404edcSAsim Jamshed 	if (strstr(cf, KW_NOT_TCP) || strstr(cf, KW_NOT_TCP2)) {
4276404edcSAsim Jamshed 		TRACE_ERROR("'!tcp' or 'not tcp' is not a valid rule for TCP flow monitor.\n");
4376404edcSAsim Jamshed 		return FALSE;
4476404edcSAsim Jamshed 	}
4576404edcSAsim Jamshed 
4676404edcSAsim Jamshed 	/* verify that the rule contains flow-related keywords only */
4776404edcSAsim Jamshed 	word = cf;
4876404edcSAsim Jamshed 	SKIP_SPACES(word);
4976404edcSAsim Jamshed 
5076404edcSAsim Jamshed 	/* while (browse the rule by words) */
5176404edcSAsim Jamshed 	while (*word) {
5276404edcSAsim Jamshed 		if (skip_word) {
5376404edcSAsim Jamshed 			skip_word = 0;
5476404edcSAsim Jamshed 			SKIP_CHAR(word);
5576404edcSAsim Jamshed 			SKIP_SPACES(word);
5676404edcSAsim Jamshed 			continue;
5776404edcSAsim Jamshed 		}
5876404edcSAsim Jamshed 		/* parse the keyword */
5976404edcSAsim Jamshed 		/* case "tcp" "src" "dst" "not' "and" "or" -> move to the next word */
6076404edcSAsim Jamshed 		if (!strncmp(word, KW_TCP, sizeof(KW_TCP) - 1) ||
6176404edcSAsim Jamshed 			!strncmp(word, KW_SRC, sizeof(KW_SRC) - 1) ||
6276404edcSAsim Jamshed 			!strncmp(word, KW_DST, sizeof(KW_DST) - 1) ||
6376404edcSAsim Jamshed 			!strncmp(word, KW_NOT, sizeof(KW_NOT) - 1) ||
6476404edcSAsim Jamshed 			!strncmp(word, KW_AND, sizeof(KW_AND) - 1) ||
6576404edcSAsim Jamshed 			!strncmp(word, KW_OR, sizeof(KW_OR) - 1)) {
6676404edcSAsim Jamshed 			skip_word = 0;
6776404edcSAsim Jamshed 		}
6876404edcSAsim Jamshed 		/* case "net" "mask" "port" "portrange" -> skip a word (= param) */
6976404edcSAsim Jamshed 		else if (!strncmp(word, KW_HOST, sizeof(KW_HOST) - 1) ||
7076404edcSAsim Jamshed 				 !strncmp(word, KW_NET, sizeof(KW_NET) - 1) ||
7176404edcSAsim Jamshed 				 !strncmp(word, KW_MASK, sizeof(KW_MASK) - 1) ||
7276404edcSAsim Jamshed 				 !strncmp(word, KW_PORT, sizeof(KW_PORT) - 1) ||
7376404edcSAsim Jamshed 				 !strncmp(word, KW_PORTRANGE, sizeof(KW_PORTRANGE) - 1)) {
7476404edcSAsim Jamshed 			skip_word = 1;
7576404edcSAsim Jamshed 		}
7676404edcSAsim Jamshed 		/* default (rule has any invalid keyword) -> return error */
7776404edcSAsim Jamshed 		else {
7876404edcSAsim Jamshed 			TRACE_ERROR("Invalid keyword in filter (%s)\n", word);
7976404edcSAsim Jamshed 			return FALSE;
8076404edcSAsim Jamshed 		}
8176404edcSAsim Jamshed 
8276404edcSAsim Jamshed 		SKIP_CHAR(word);
8376404edcSAsim Jamshed 		SKIP_SPACES(word);
8476404edcSAsim Jamshed 	}
8576404edcSAsim Jamshed 
8676404edcSAsim Jamshed 	return TRUE;
8776404edcSAsim Jamshed }
8876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
8976404edcSAsim Jamshed /* Assign an address range (specified by ft) to monitor via sock */
9076404edcSAsim Jamshed int
9176404edcSAsim Jamshed mtcp_bind_monitor_filter(mctx_t mctx, int sockid, monitor_filter_t ft)
9276404edcSAsim Jamshed {
9376404edcSAsim Jamshed 	socket_map_t sock;
9476404edcSAsim Jamshed 	mtcp_manager_t mtcp;
9576404edcSAsim Jamshed 
9676404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
9776404edcSAsim Jamshed 	if (!mtcp) {
9876404edcSAsim Jamshed 		errno = EACCES;
9976404edcSAsim Jamshed 		return -1;
10076404edcSAsim Jamshed 	}
10176404edcSAsim Jamshed 
10276404edcSAsim Jamshed 	/* if filter is not set, do nothing and return */
10376404edcSAsim Jamshed 	if (ft == NULL) {
10476404edcSAsim Jamshed 		TRACE_ERROR("filter not set!\n");
10576404edcSAsim Jamshed 		return 0;
10676404edcSAsim Jamshed 	}
10776404edcSAsim Jamshed 
10876404edcSAsim Jamshed 	/* retrieve the socket */
10976404edcSAsim Jamshed 	if (sockid < 0 || sockid >= g_config.mos->max_concurrency) {
11076404edcSAsim Jamshed 		errno = EBADF;
11176404edcSAsim Jamshed 		TRACE_ERROR("sockid is invalid!\n");
11276404edcSAsim Jamshed 		return -1;
11376404edcSAsim Jamshed 	}
11476404edcSAsim Jamshed 	sock = &mtcp->msmap[sockid];
11576404edcSAsim Jamshed 
11676404edcSAsim Jamshed 	/* check socket type */
11776404edcSAsim Jamshed 	switch (sock->socktype) {
11876404edcSAsim Jamshed 	case MOS_SOCK_MONITOR_RAW:
11976404edcSAsim Jamshed 		/* For MONITOR_RAW type, allow any bpf rule */
12076404edcSAsim Jamshed 		if (!ft->raw_pkt_filter) {
12176404edcSAsim Jamshed 			TRACE_ERROR("raw pkt filter is null");
12276404edcSAsim Jamshed 			return 0;
12376404edcSAsim Jamshed 		}
12476404edcSAsim Jamshed 		if (SET_BPFFILTER(&sock->monitor_listener->raw_pkt_fcode,
12576404edcSAsim Jamshed 						  ft->raw_pkt_filter) < 0) {
12676404edcSAsim Jamshed 			TRACE_ERROR("Invalid filter expression!\n");
12776404edcSAsim Jamshed 			errno = EINVAL;
12876404edcSAsim Jamshed 			return -1;
12976404edcSAsim Jamshed 		}
13076404edcSAsim Jamshed 		break;
13176404edcSAsim Jamshed 	case MOS_SOCK_MONITOR_STREAM:
13276404edcSAsim Jamshed 		/* For MONITOR_STREAM_PASSIVE type, restrict to flow-level keywords */
13376404edcSAsim Jamshed 		if (ft->stream_syn_filter) {
13476404edcSAsim Jamshed 			if (!IsValidFlowRule(ft->stream_syn_filter)) {
13576404edcSAsim Jamshed 				errno = EINVAL;
13676404edcSAsim Jamshed 				return -1;
13776404edcSAsim Jamshed 			}
13876404edcSAsim Jamshed 			if (SET_BPFFILTER(&sock->monitor_listener->stream_syn_fcode,
13976404edcSAsim Jamshed 							  ft->stream_syn_filter) < 0) {
14076404edcSAsim Jamshed 				TRACE_ERROR("Invalid filter expression!\n");
14176404edcSAsim Jamshed 				errno = EINVAL;
14276404edcSAsim Jamshed 				return -1;
14376404edcSAsim Jamshed 			}
14476404edcSAsim Jamshed 		}
14576404edcSAsim Jamshed 		if (ft->stream_orphan_filter) {
14676404edcSAsim Jamshed 			if (!IsValidFlowRule(ft->stream_orphan_filter)) {
14776404edcSAsim Jamshed 				errno = EINVAL;
14876404edcSAsim Jamshed 				return -1;
14976404edcSAsim Jamshed 			}
15076404edcSAsim Jamshed 			if (SET_BPFFILTER(&sock->monitor_listener->stream_orphan_fcode,
15176404edcSAsim Jamshed 							  ft->stream_orphan_filter) < 0) {
15276404edcSAsim Jamshed 				TRACE_ERROR("Invalid filter expression!\n");
15376404edcSAsim Jamshed 				errno = EINVAL;
15476404edcSAsim Jamshed 				return -1;
15576404edcSAsim Jamshed 			}
15676404edcSAsim Jamshed 		}
15776404edcSAsim Jamshed 		break;
15876404edcSAsim Jamshed 	default:
15976404edcSAsim Jamshed 		/* return error for other socket types */
16076404edcSAsim Jamshed 		errno = ENOPROTOOPT;
16176404edcSAsim Jamshed 		TRACE_ERROR("Invalid sock type!\n");
16276404edcSAsim Jamshed 		return -1;
16376404edcSAsim Jamshed 	}
16476404edcSAsim Jamshed 
16576404edcSAsim Jamshed 	return 0;
16676404edcSAsim Jamshed }
16776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
16876404edcSAsim Jamshed void
16976404edcSAsim Jamshed mtcp_app_join(mctx_t mctx)
17076404edcSAsim Jamshed {
17176404edcSAsim Jamshed 	mtcp_manager_t mtcp = GetMTCPManager(mctx);
17276404edcSAsim Jamshed 	if (!mtcp) return;
17376404edcSAsim Jamshed 
17476404edcSAsim Jamshed 	RunPassiveLoop(mtcp);
17576404edcSAsim Jamshed 	return;
17676404edcSAsim Jamshed }
17776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
17876404edcSAsim Jamshed /* Callback only functions */
17976404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
18076404edcSAsim Jamshed void
18176404edcSAsim Jamshed mtcp_set_uctx(mctx_t mctx, int msock, void *uctx)
18276404edcSAsim Jamshed {
18376404edcSAsim Jamshed 	mtcp_manager_t mtcp;
18476404edcSAsim Jamshed 
18576404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
18676404edcSAsim Jamshed 	if (!mtcp) {
18776404edcSAsim Jamshed 		return;
18876404edcSAsim Jamshed 	}
18976404edcSAsim Jamshed 
19076404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
19176404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self())
19276404edcSAsim Jamshed 		return;
19376404edcSAsim Jamshed 
19476404edcSAsim Jamshed 	if (msock < 0 || msock >= g_config.mos->max_concurrency) {
19576404edcSAsim Jamshed 		TRACE_API("Socket id %d out of range.\n", msock);
19676404edcSAsim Jamshed 		errno = EBADF;
19776404edcSAsim Jamshed 		return;
19876404edcSAsim Jamshed 	}
19976404edcSAsim Jamshed 
20076404edcSAsim Jamshed 	socket_map_t socket = &mtcp->msmap[msock];
20176404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE)
20276404edcSAsim Jamshed 		socket->monitor_stream->uctx = uctx;
20376404edcSAsim Jamshed 	else if (socket->socktype == MOS_SOCK_MONITOR_STREAM ||
20476404edcSAsim Jamshed 			 socket->socktype == MOS_SOCK_MONITOR_RAW)
20576404edcSAsim Jamshed 		socket->monitor_listener->uctx = uctx;
20676404edcSAsim Jamshed }
20776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
20876404edcSAsim Jamshed void *
20976404edcSAsim Jamshed mtcp_get_uctx(mctx_t mctx, int msock)
21076404edcSAsim Jamshed {
21176404edcSAsim Jamshed 	mtcp_manager_t mtcp;
21276404edcSAsim Jamshed 
21376404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
21476404edcSAsim Jamshed 	if (!mtcp) {
21576404edcSAsim Jamshed 		errno = EACCES;
21676404edcSAsim Jamshed 		return NULL;
21776404edcSAsim Jamshed 	}
21876404edcSAsim Jamshed 
21976404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
22076404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
22176404edcSAsim Jamshed 		errno = EPERM;
22276404edcSAsim Jamshed 		return NULL;
22376404edcSAsim Jamshed 	}
22476404edcSAsim Jamshed 
22576404edcSAsim Jamshed 	if (msock < 0 || msock >= g_config.mos->max_concurrency) {
22676404edcSAsim Jamshed 		TRACE_API("Socket id %d out of range.\n", msock);
22776404edcSAsim Jamshed 		errno = EBADF;
22876404edcSAsim Jamshed 		return NULL;
22976404edcSAsim Jamshed 	}
23076404edcSAsim Jamshed 
23176404edcSAsim Jamshed 	socket_map_t socket = &mtcp->msmap[msock];
23276404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE)
23376404edcSAsim Jamshed 		return socket->monitor_stream->uctx;
23476404edcSAsim Jamshed 	else if (socket->socktype == MOS_SOCK_MONITOR_STREAM ||
23576404edcSAsim Jamshed 			 socket->socktype == MOS_SOCK_MONITOR_RAW)
23676404edcSAsim Jamshed 		return socket->monitor_listener->uctx;
23776404edcSAsim Jamshed 	else
23876404edcSAsim Jamshed 		return NULL;
23976404edcSAsim Jamshed }
24076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
24176404edcSAsim Jamshed ssize_t
24276404edcSAsim Jamshed mtcp_peek(mctx_t mctx, int msock, int side, char *buf, size_t len)
24376404edcSAsim Jamshed {
24476404edcSAsim Jamshed 	int copylen, rc;
24576404edcSAsim Jamshed 	struct tcp_stream *cur_stream;
24676404edcSAsim Jamshed 	mtcp_manager_t mtcp;
24776404edcSAsim Jamshed 	socket_map_t sock;
24876404edcSAsim Jamshed 
24976404edcSAsim Jamshed 	copylen = rc = 0;
25076404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
25176404edcSAsim Jamshed 	if (!mtcp) {
25276404edcSAsim Jamshed 		errno = EACCES;
25376404edcSAsim Jamshed 		return -1;
25476404edcSAsim Jamshed 	}
25576404edcSAsim Jamshed 
25676404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
25776404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
25876404edcSAsim Jamshed 		errno = EPERM;
25976404edcSAsim Jamshed 		return -1;
26076404edcSAsim Jamshed 	}
26176404edcSAsim Jamshed 
26276404edcSAsim Jamshed 	/* check if the socket is monitor stream */
26376404edcSAsim Jamshed 	sock = &mtcp->msmap[msock];
26476404edcSAsim Jamshed 	if (sock->socktype != MOS_SOCK_MONITOR_STREAM_ACTIVE) {
26576404edcSAsim Jamshed 		TRACE_DBG("Invalid socket type!\n");
26676404edcSAsim Jamshed 		errno = EBADF;
26776404edcSAsim Jamshed 		return -1;
26876404edcSAsim Jamshed 	}
26976404edcSAsim Jamshed 
27076404edcSAsim Jamshed 	if (side != MOS_SIDE_CLI && side != MOS_SIDE_SVR) {
27176404edcSAsim Jamshed 		TRACE_ERROR("Invalid side requested!\n");
27276404edcSAsim Jamshed 		exit(EXIT_FAILURE);
27376404edcSAsim Jamshed 		return -1;
27476404edcSAsim Jamshed 	}
27576404edcSAsim Jamshed 
27676404edcSAsim Jamshed 	struct tcp_stream *mstrm = sock->monitor_stream->stream;
27776404edcSAsim Jamshed 	cur_stream = (side == mstrm->side) ? mstrm : mstrm->pair_stream;
27876404edcSAsim Jamshed 
27976404edcSAsim Jamshed 	if (!cur_stream || !cur_stream->buffer_mgmt) {
28076404edcSAsim Jamshed 		TRACE_DBG("Stream is NULL!! or buffer management is disabled\n");
28176404edcSAsim Jamshed 		errno = EINVAL;
28276404edcSAsim Jamshed 		return -1;
28376404edcSAsim Jamshed 	}
28476404edcSAsim Jamshed 
28576404edcSAsim Jamshed 	/* Check if the read was not just due to syn-ack recv */
28676404edcSAsim Jamshed 	if (cur_stream->rcvvar != NULL &&
28776404edcSAsim Jamshed 	    cur_stream->rcvvar->rcvbuf != NULL) {
28876404edcSAsim Jamshed 		tcprb_t *rcvbuf = cur_stream->rcvvar->rcvbuf;
28976404edcSAsim Jamshed 		loff_t *poff = &sock->monitor_stream->peek_offset[cur_stream->side];
29076404edcSAsim Jamshed 
29176404edcSAsim Jamshed 		rc = tcprb_ppeek(rcvbuf, (uint8_t *)buf, len, *poff);
29276404edcSAsim Jamshed 		if (rc < 0) {
29376404edcSAsim Jamshed 			errno = ENODATA;
29476404edcSAsim Jamshed 			return -1;
29576404edcSAsim Jamshed 		}
29676404edcSAsim Jamshed 
29776404edcSAsim Jamshed 		*poff += rc;
29876404edcSAsim Jamshed 		UNUSED(copylen);
29976404edcSAsim Jamshed 
30076404edcSAsim Jamshed 		return rc;
30176404edcSAsim Jamshed 	} else {
30276404edcSAsim Jamshed 		TRACE_DBG("Stream hasn't yet been initialized!\n");
30376404edcSAsim Jamshed 		rc = 0;
30476404edcSAsim Jamshed 	}
30576404edcSAsim Jamshed 
30676404edcSAsim Jamshed 	return rc;
30776404edcSAsim Jamshed }
30876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
30976404edcSAsim Jamshed /**
31076404edcSAsim Jamshed  * Copies from the frags.. returns no. of bytes copied to buf
31176404edcSAsim Jamshed  */
31276404edcSAsim Jamshed static inline int
31376404edcSAsim Jamshed ExtractPayloadFromFrags(struct tcp_ring_buffer *rcvbuf, char *buf,
31476404edcSAsim Jamshed 						size_t count, off_t seq_num)
31576404edcSAsim Jamshed {
31676404edcSAsim Jamshed 	int cpbytesleft;
31776404edcSAsim Jamshed 	struct fragment_ctx *it;
31876404edcSAsim Jamshed 
31976404edcSAsim Jamshed 	it = rcvbuf->fctx;
32076404edcSAsim Jamshed 	cpbytesleft = count;
32176404edcSAsim Jamshed 	/* go through each frag */
32276404edcSAsim Jamshed 	while (it) {
32376404edcSAsim Jamshed 		/* first check whether sequent number matches */
32476404edcSAsim Jamshed 		if (TCP_SEQ_BETWEEN(seq_num, it->seq, it->seq + it->len)) {
32576404edcSAsim Jamshed 			/* copy buf starting from seq# seq_num */
32676404edcSAsim Jamshed 			/* copy the MIN of seq-range and bytes to be copied */
32776404edcSAsim Jamshed 			memcpy(buf + count - cpbytesleft,
32876404edcSAsim Jamshed 			       rcvbuf->head + seq_num - rcvbuf->head_seq,
32976404edcSAsim Jamshed 			       MIN(it->len - (seq_num - it->seq), cpbytesleft));
33076404edcSAsim Jamshed 			/* update target seq num */
33176404edcSAsim Jamshed 			seq_num += it->len - (seq_num - it->seq);
33276404edcSAsim Jamshed 			/* update cpbytes left */
33376404edcSAsim Jamshed 			cpbytesleft -= it->len - (seq_num - it->seq);
33476404edcSAsim Jamshed 			if (cpbytesleft == 0)
33576404edcSAsim Jamshed 				break;
33676404edcSAsim Jamshed 		}
33776404edcSAsim Jamshed 		it = it->next;
33876404edcSAsim Jamshed 	}
33976404edcSAsim Jamshed 
34076404edcSAsim Jamshed 	count -= cpbytesleft;
34176404edcSAsim Jamshed 
34276404edcSAsim Jamshed 	/* return number of bytes copied */
34376404edcSAsim Jamshed 	return count;
34476404edcSAsim Jamshed }
34576404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
34676404edcSAsim Jamshed /* Please see in-code comments for description */
34776404edcSAsim Jamshed ssize_t
34876404edcSAsim Jamshed mtcp_ppeek(mctx_t mctx, int msock, int side,
34976404edcSAsim Jamshed 			  char *buf, size_t count, uint64_t off)
35076404edcSAsim Jamshed {
35176404edcSAsim Jamshed 	mtcp_manager_t mtcp;
35276404edcSAsim Jamshed 	struct tcp_stream *cur_stream;
35376404edcSAsim Jamshed 	int rc;
35476404edcSAsim Jamshed 	socket_map_t sock;
35576404edcSAsim Jamshed 
35676404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
35776404edcSAsim Jamshed 	if (!mtcp) {
35876404edcSAsim Jamshed 		errno = EACCES;
35976404edcSAsim Jamshed 		goto ppeek_error;
36076404edcSAsim Jamshed 	}
36176404edcSAsim Jamshed 
36276404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
36376404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
36476404edcSAsim Jamshed 		errno = EPERM;
36576404edcSAsim Jamshed 		goto ppeek_error;
36676404edcSAsim Jamshed 	}
36776404edcSAsim Jamshed 
36876404edcSAsim Jamshed 	/* check if the socket is monitor stream */
36976404edcSAsim Jamshed 	sock = &mtcp->msmap[msock];
37076404edcSAsim Jamshed 	if (sock->socktype != MOS_SOCK_MONITOR_STREAM_ACTIVE) {
37176404edcSAsim Jamshed 		TRACE_DBG("Invalid socket type!\n");
37276404edcSAsim Jamshed 		errno = ESOCKTNOSUPPORT;
37376404edcSAsim Jamshed 		goto ppeek_error;
37476404edcSAsim Jamshed 	}
37576404edcSAsim Jamshed 
37676404edcSAsim Jamshed 	if (side != MOS_SIDE_CLI && side != MOS_SIDE_SVR) {
37776404edcSAsim Jamshed 		TRACE_ERROR("Invalid side requested!\n");
37876404edcSAsim Jamshed 		exit(EXIT_FAILURE);
37976404edcSAsim Jamshed 		return -1;
38076404edcSAsim Jamshed 	}
38176404edcSAsim Jamshed 
38276404edcSAsim Jamshed 	struct tcp_stream *mstrm = sock->monitor_stream->stream;
38376404edcSAsim Jamshed 	cur_stream = (side == mstrm->side) ? mstrm : mstrm->pair_stream;
38476404edcSAsim Jamshed 
38576404edcSAsim Jamshed 	if (!cur_stream || !cur_stream->buffer_mgmt) {
38676404edcSAsim Jamshed 		TRACE_DBG("Stream is either NULL or ring buffer is not managed!!\n");
38776404edcSAsim Jamshed 		errno = EACCES;
38876404edcSAsim Jamshed 		goto ppeek_error;
38976404edcSAsim Jamshed 	}
39076404edcSAsim Jamshed 
39176404edcSAsim Jamshed 	rc = 0;
39276404edcSAsim Jamshed 	/* Check if the read was not just due to syn-ack recv */
39376404edcSAsim Jamshed 	if (cur_stream->rcvvar != NULL &&
39476404edcSAsim Jamshed 	    cur_stream->rcvvar->rcvbuf != NULL) {
39576404edcSAsim Jamshed 		tcprb_t *rcvbuf = cur_stream->rcvvar->rcvbuf;
39676404edcSAsim Jamshed 		return tcprb_ppeek(rcvbuf, (uint8_t *)buf, count, off);
39776404edcSAsim Jamshed 	} else {
39876404edcSAsim Jamshed 		errno = EPERM;
39976404edcSAsim Jamshed 		goto ppeek_error;
40076404edcSAsim Jamshed 	}
40176404edcSAsim Jamshed 
40276404edcSAsim Jamshed 	return rc;
40376404edcSAsim Jamshed 
40476404edcSAsim Jamshed  ppeek_error:
40576404edcSAsim Jamshed 	return -1;
40676404edcSAsim Jamshed }
40776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
40876404edcSAsim Jamshed #ifdef MTCP_CB_GETCURPKT_CREATE_COPY
40976404edcSAsim Jamshed static __thread unsigned char local_frame[ETHERNET_FRAME_LEN];
41076404edcSAsim Jamshed inline struct pkt_info *
411a14d6bd4SAsim Jamshed ClonePacketCtx(struct pkt_info *to, unsigned char *frame, struct pkt_info *from)
41276404edcSAsim Jamshed {
41376404edcSAsim Jamshed 	/* memcpy the entire ethernet frame */
41476404edcSAsim Jamshed 	assert(from);
415a14d6bd4SAsim Jamshed 	assert(from->eth_len > 0);
416a14d6bd4SAsim Jamshed 	assert(from->eth_len <= ETHERNET_FRAME_LEN);
417a14d6bd4SAsim Jamshed 	memcpy(frame, from->ethh, from->eth_len);
418a14d6bd4SAsim Jamshed 
419a14d6bd4SAsim Jamshed 	/* only memcpy till the last field before ethh */
420a14d6bd4SAsim Jamshed 	/* memcpy(to, from, PCTX_COPY_LEN); */
421a14d6bd4SAsim Jamshed 	memcpy(to, from, PKT_INFO_LEN);
42276404edcSAsim Jamshed 	/* set iph */
42376404edcSAsim Jamshed 	to->ethh = (struct ethhdr *)frame;
42476404edcSAsim Jamshed 	/* set iph */
425a14d6bd4SAsim Jamshed 	to->iph = from->iph ?
42676404edcSAsim Jamshed 		(struct iphdr *)((uint8_t *)(frame + ETHERNET_HEADER_LEN)) : NULL;
427ec2936c9SAsim Jamshed 	if (to->iph) {
42876404edcSAsim Jamshed 		/* set tcph */
429a14d6bd4SAsim Jamshed 		to->tcph = from->tcph ?
43076404edcSAsim Jamshed 			(struct tcphdr *)(((uint8_t *)(to->iph)) + (to->iph->ihl<<2)) : NULL;
431ec2936c9SAsim Jamshed 		if (to->tcph)
43276404edcSAsim Jamshed 			/* set payload */
433a14d6bd4SAsim Jamshed 			to->payload = from->tcph ?
43476404edcSAsim Jamshed 				((uint8_t *)(to->tcph) + (to->tcph->doff<<2)) : NULL;
435ec2936c9SAsim Jamshed 	}
43676404edcSAsim Jamshed 	return to;
43776404edcSAsim Jamshed }
43876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
43976404edcSAsim Jamshed int
44076404edcSAsim Jamshed mtcp_getlastpkt(mctx_t mctx, int sock, int side, struct pkt_info *pkt)
44176404edcSAsim Jamshed {
44276404edcSAsim Jamshed 	mtcp_manager_t mtcp;
44376404edcSAsim Jamshed 	socket_map_t socket;
44476404edcSAsim Jamshed 	struct pkt_ctx *cur_pkt_ctx;
44576404edcSAsim Jamshed 
44676404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
44776404edcSAsim Jamshed 	if (!mtcp) {
44876404edcSAsim Jamshed 		errno = EACCES;
44976404edcSAsim Jamshed 		return -1;
45076404edcSAsim Jamshed 	}
45176404edcSAsim Jamshed 
45276404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
45376404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
45476404edcSAsim Jamshed 		errno = EPERM;
45576404edcSAsim Jamshed 		return -1;
45676404edcSAsim Jamshed 	}
45776404edcSAsim Jamshed 
45876404edcSAsim Jamshed 	/* check if the socket is monitor stream */
45976404edcSAsim Jamshed 	socket = &mtcp->msmap[sock];
460a14d6bd4SAsim Jamshed #ifndef RECORDPKT_PER_STREAM
461a14d6bd4SAsim Jamshed 	switch (socket->socktype) {
462a14d6bd4SAsim Jamshed 	case MOS_SOCK_MONITOR_STREAM_ACTIVE:
463a14d6bd4SAsim Jamshed 	case MOS_SOCK_MONITOR_RAW:
464a14d6bd4SAsim Jamshed 	case MOS_SOCK_MONITOR_STREAM:
465a14d6bd4SAsim Jamshed 		if (mtcp->pctx == NULL) {
466a14d6bd4SAsim Jamshed 			errno = EACCES;
467a14d6bd4SAsim Jamshed 			return -1;
468a14d6bd4SAsim Jamshed 		}
469a14d6bd4SAsim Jamshed 		cur_pkt_ctx = mtcp->pctx;
470a14d6bd4SAsim Jamshed 		break;
471a14d6bd4SAsim Jamshed 	default:
472a14d6bd4SAsim Jamshed 		TRACE_DBG("Invalid socket type!\n");
473a14d6bd4SAsim Jamshed 		errno = EBADF;
474a14d6bd4SAsim Jamshed 		return -1;
475a14d6bd4SAsim Jamshed 	}
476a14d6bd4SAsim Jamshed #else /* RECORDPKT_PER_STREAM */
477a14d6bd4SAsim Jamshed 	struct tcp_stream *cur_stream;
47876404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE) {
47976404edcSAsim Jamshed 		if (side != MOS_SIDE_CLI && side != MOS_SIDE_SVR) {
48076404edcSAsim Jamshed 			TRACE_ERROR("Invalid side requested!\n");
48176404edcSAsim Jamshed 			exit(EXIT_FAILURE);
48276404edcSAsim Jamshed 			return -1;
48376404edcSAsim Jamshed 		}
48476404edcSAsim Jamshed 
48576404edcSAsim Jamshed 		struct tcp_stream *mstrm = socket->monitor_stream->stream;
48676404edcSAsim Jamshed 		cur_stream = (side == mstrm->side) ? mstrm : mstrm->pair_stream;
48776404edcSAsim Jamshed 
48876404edcSAsim Jamshed 		cur_pkt_ctx = &cur_stream->last_pctx;
48976404edcSAsim Jamshed 		if (!cur_pkt_ctx->p.ethh) {
49076404edcSAsim Jamshed 			errno = ENODATA;
49176404edcSAsim Jamshed 			return -1;
49276404edcSAsim Jamshed 		}
49376404edcSAsim Jamshed 	} else if (socket->socktype == MOS_SOCK_MONITOR_RAW) {
49476404edcSAsim Jamshed 		cur_pkt_ctx = mtcp->pctx;
49576404edcSAsim Jamshed 	} else if (socket->socktype == MOS_SOCK_MONITOR_STREAM) {
49676404edcSAsim Jamshed 		/*
49776404edcSAsim Jamshed 		 * if it is a monitor socket, then this means that
49876404edcSAsim Jamshed 		 * this is a request for an orphan tcp packet
49976404edcSAsim Jamshed 		 */
50076404edcSAsim Jamshed 		cur_pkt_ctx = mtcp->pctx;
50176404edcSAsim Jamshed 	} else {
50276404edcSAsim Jamshed 		TRACE_DBG("Invalid socket type!\n");
50376404edcSAsim Jamshed 		errno = EBADF;
50476404edcSAsim Jamshed 		return -1;
50576404edcSAsim Jamshed 	}
506a14d6bd4SAsim Jamshed #endif /* !RECORDPKT_PER_STREAM */
507a14d6bd4SAsim Jamshed 	ClonePacketCtx(pkt, local_frame, &(cur_pkt_ctx->p));
50876404edcSAsim Jamshed 	return 0;
50976404edcSAsim Jamshed }
51076404edcSAsim Jamshed #else
51176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
51276404edcSAsim Jamshed int
51376404edcSAsim Jamshed mtcp_getlastpkt(mctx_t mctx, int sock, int side, struct pkt_ctx **pctx)
51476404edcSAsim Jamshed {
51576404edcSAsim Jamshed 	mtcp_manager_t mtcp;
51676404edcSAsim Jamshed 
51776404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
51876404edcSAsim Jamshed 	if (!mtcp) {
51976404edcSAsim Jamshed 		errno = EACCES;
52076404edcSAsim Jamshed 		return -1;
52176404edcSAsim Jamshed 	}
52276404edcSAsim Jamshed 
52376404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
52476404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
52576404edcSAsim Jamshed 		errno = EPERM;
52676404edcSAsim Jamshed 		return -1;
52776404edcSAsim Jamshed 	}
52876404edcSAsim Jamshed 	/* just pass direct pointer */
52976404edcSAsim Jamshed 	*pctx = mtcp->pctx;
53076404edcSAsim Jamshed 
53176404edcSAsim Jamshed 	return 0;
53276404edcSAsim Jamshed }
53376404edcSAsim Jamshed #endif
53476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
53591df013fSAsim Jamshed int
53691df013fSAsim Jamshed mtcp_sendpkt(mctx_t mctx, int sock, const struct pkt_info *pkt)
53791df013fSAsim Jamshed {
53891df013fSAsim Jamshed 	mtcp_manager_t mtcp;
53991df013fSAsim Jamshed 	socket_map_t socket;
54091df013fSAsim Jamshed 
54191df013fSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
54291df013fSAsim Jamshed 	if (!mtcp || !pkt) {
54391df013fSAsim Jamshed 		errno = EACCES;
54491df013fSAsim Jamshed 		return -1;
54591df013fSAsim Jamshed 	}
54691df013fSAsim Jamshed 
54791df013fSAsim Jamshed 	/* check if the calling thread is in MOS context */
54891df013fSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
54991df013fSAsim Jamshed 		errno = EPERM;
55091df013fSAsim Jamshed 		return -1;
55191df013fSAsim Jamshed 	}
55291df013fSAsim Jamshed 
55391df013fSAsim Jamshed 	/* check if the socket is monitor stream */
55491df013fSAsim Jamshed 	socket = &mtcp->msmap[sock];
55591df013fSAsim Jamshed 
55691df013fSAsim Jamshed 	if (!(pkt->iph) || !(pkt->tcph)) {
55791df013fSAsim Jamshed 		errno = ENODATA;
55891df013fSAsim Jamshed 		TRACE_INFO("mtcp_sendpkt() only supports TCP packet for now.\n");
55991df013fSAsim Jamshed 		return -1;
56091df013fSAsim Jamshed 	}
56191df013fSAsim Jamshed 
56291df013fSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE) {
56391df013fSAsim Jamshed 		SendTCPPacketStandalone(mtcp,
56491df013fSAsim Jamshed 				   pkt->iph->saddr, pkt->tcph->source,
56591df013fSAsim Jamshed 				   pkt->iph->daddr, pkt->tcph->dest,
56691df013fSAsim Jamshed 				   htonl(pkt->tcph->seq), htonl(pkt->tcph->ack_seq),
56791df013fSAsim Jamshed 				   ntohs(pkt->tcph->window), TCP_FLAG_ACK,
56891df013fSAsim Jamshed 				   pkt->payload, pkt->payloadlen,
56991df013fSAsim Jamshed 				   socket->monitor_stream->stream->rcvvar->ts_recent,
57091df013fSAsim Jamshed 				   socket->monitor_stream->stream->rcvvar->ts_lastack_rcvd,
571a834ea89SAsim Jamshed 				   pkt->iph->id, pkt->in_ifidx);
57291df013fSAsim Jamshed 
57391df013fSAsim Jamshed 
57491df013fSAsim Jamshed 	}
57591df013fSAsim Jamshed 
57691df013fSAsim Jamshed 	return 0;
57791df013fSAsim Jamshed }
57891df013fSAsim Jamshed /*----------------------------------------------------------------------------*/
57976404edcSAsim Jamshed /** Disable events from the monitor stream socket
58076404edcSAsim Jamshed  * @param [in] mtcp: mtcp_manager
58176404edcSAsim Jamshed  * @param [in] sock: socket
58276404edcSAsim Jamshed  *
58376404edcSAsim Jamshed  * returns 0 on success, -1 on failure
58476404edcSAsim Jamshed  *
58576404edcSAsim Jamshed  * This is used for flow management based monitoring sockets
58676404edcSAsim Jamshed  */
58776404edcSAsim Jamshed int
58876404edcSAsim Jamshed RemoveMonitorEvents(mtcp_manager_t mtcp, socket_map_t socket, int side)
58976404edcSAsim Jamshed {
59076404edcSAsim Jamshed 	struct mon_stream *mstream;
59176404edcSAsim Jamshed 	struct mon_listener *mlistener;
59276404edcSAsim Jamshed 
59376404edcSAsim Jamshed 	if (mtcp == NULL) {
59476404edcSAsim Jamshed 		TRACE_DBG("mtcp is not defined!!!\n");
59576404edcSAsim Jamshed 		errno = EACCES;
59676404edcSAsim Jamshed 		return -1;
59776404edcSAsim Jamshed 	}
59876404edcSAsim Jamshed 
59976404edcSAsim Jamshed 	switch (socket->socktype) {
60076404edcSAsim Jamshed 	case MOS_SOCK_MONITOR_STREAM_ACTIVE:
60176404edcSAsim Jamshed 		mstream = socket->monitor_stream;
60276404edcSAsim Jamshed 		if (mstream == NULL) {
60376404edcSAsim Jamshed 			TRACE_ERROR("Mon Stream does not exist!\n");
60476404edcSAsim Jamshed 			/* exit(-1); */
60576404edcSAsim Jamshed 			errno = ENODATA;
60676404edcSAsim Jamshed 			return -1;
60776404edcSAsim Jamshed 		}
60876404edcSAsim Jamshed 
60976404edcSAsim Jamshed 		if (side == MOS_SIDE_SVR) mstream->server_mon = 0;
61076404edcSAsim Jamshed 		else if (side == MOS_SIDE_CLI) mstream->client_mon = 0;
61176404edcSAsim Jamshed 
61276404edcSAsim Jamshed 		if (mstream->server_mon == 0 && mstream->client_mon == 0) {
61376404edcSAsim Jamshed #ifdef NEWEV
61476404edcSAsim Jamshed 			/*
61576404edcSAsim Jamshed 			 * if stree_dontcare is NULL, then we know that all
61676404edcSAsim Jamshed 			 * events have already been disabled
61776404edcSAsim Jamshed 			 */
61876404edcSAsim Jamshed 			if (mstream->stree_pre_rcv != NULL) {
61976404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mstream->stree_dontcare);
62076404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mstream->stree_pre_rcv);
62176404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mstream->stree_post_snd);
62276404edcSAsim Jamshed 
62376404edcSAsim Jamshed 				mstream->stree_dontcare = NULL;
62476404edcSAsim Jamshed 				mstream->stree_pre_rcv = NULL;
62576404edcSAsim Jamshed 				mstream->stree_post_snd = NULL;
62676404edcSAsim Jamshed 			}
62776404edcSAsim Jamshed #else
62876404edcSAsim Jamshed 			/* no error checking over here..
62976404edcSAsim Jamshed 			 * but its okay.. this code is
63076404edcSAsim Jamshed 			 * deprecated
63176404edcSAsim Jamshed 			 */
63276404edcSAsim Jamshed 			CleanupEvP(&mstream->dontcare_evp);
63376404edcSAsim Jamshed 			CleanupEvP(&mstream->pre_tcp_evp);
63476404edcSAsim Jamshed 			CleanupEvP(&mstream->post_tcp_evp);
63576404edcSAsim Jamshed #endif
63676404edcSAsim Jamshed 		}
63776404edcSAsim Jamshed 		break;
63876404edcSAsim Jamshed 	case MOS_SOCK_MONITOR_STREAM:
63976404edcSAsim Jamshed 		mlistener = socket->monitor_listener;
64076404edcSAsim Jamshed 		if (mlistener == NULL) {
64176404edcSAsim Jamshed 			TRACE_ERROR("Mon listener does not exist!\n");
64276404edcSAsim Jamshed 			errno = ENODATA;
64376404edcSAsim Jamshed 			return -1;
64476404edcSAsim Jamshed 		}
64576404edcSAsim Jamshed 
64676404edcSAsim Jamshed 		if (side == MOS_SIDE_SVR) mlistener->server_mon = 0;
64776404edcSAsim Jamshed 		else if (side == MOS_SIDE_CLI) mlistener->client_mon = 0;
64876404edcSAsim Jamshed 
64976404edcSAsim Jamshed 		if (mlistener->server_mon == 0 && mlistener->client_mon == 0) {
65076404edcSAsim Jamshed #ifdef NEWEV
65176404edcSAsim Jamshed 			/*
65276404edcSAsim Jamshed 			 * if stree_dontcare is NULL, then we know that all
65376404edcSAsim Jamshed 			 * events have already been disabled
65476404edcSAsim Jamshed 			 */
65576404edcSAsim Jamshed 			if (mlistener->stree_pre_rcv != NULL) {
65676404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mlistener->stree_dontcare);
65776404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mlistener->stree_pre_rcv);
65876404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mlistener->stree_post_snd);
65976404edcSAsim Jamshed 
66076404edcSAsim Jamshed 				mlistener->stree_dontcare = NULL;
66176404edcSAsim Jamshed 				mlistener->stree_pre_rcv = NULL;
66276404edcSAsim Jamshed 				mlistener->stree_post_snd = NULL;
66376404edcSAsim Jamshed 			}
66476404edcSAsim Jamshed #else
66576404edcSAsim Jamshed 			/* no error checking over here..
66676404edcSAsim Jamshed 			 * but its okay.. this code is
66776404edcSAsim Jamshed 			 * deprecated
66876404edcSAsim Jamshed 			 */
66976404edcSAsim Jamshed 			CleanupEvB(mtcp, &mlistener->dontcare_evb);
67076404edcSAsim Jamshed 			CleanupEvB(mtcp, &mlistener->pre_tcp_evb);
67176404edcSAsim Jamshed 			CleanupEvB(mtcp, &mlistener->post_tcp_evb);
67276404edcSAsim Jamshed #endif
67376404edcSAsim Jamshed 		}
67476404edcSAsim Jamshed 		break;
67576404edcSAsim Jamshed 	default:
67676404edcSAsim Jamshed 		TRACE_ERROR("Invalid socket type!\n");
67776404edcSAsim Jamshed 	}
67876404edcSAsim Jamshed 
67976404edcSAsim Jamshed 	return 0;
68076404edcSAsim Jamshed }
68176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
68276404edcSAsim Jamshed /**
68376404edcSAsim Jamshed  * Disable monitoring based on side variable.
68476404edcSAsim Jamshed  */
68576404edcSAsim Jamshed int
68676404edcSAsim Jamshed mtcp_cb_stop(mctx_t mctx, int sock, int side)
68776404edcSAsim Jamshed {
68876404edcSAsim Jamshed 	mtcp_manager_t mtcp;
68976404edcSAsim Jamshed 	socket_map_t socket;
69076404edcSAsim Jamshed 	struct tcp_stream *stream;
69176404edcSAsim Jamshed 	struct socket_map *walk;
69276404edcSAsim Jamshed 	uint8_t mgmt;
69376404edcSAsim Jamshed 
69476404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
69576404edcSAsim Jamshed 	if (!mtcp) {
69676404edcSAsim Jamshed 		errno = EACCES;
69776404edcSAsim Jamshed 		return -1;
69876404edcSAsim Jamshed 	}
69976404edcSAsim Jamshed 
70076404edcSAsim Jamshed 	socket = &mtcp->msmap[sock];
70176404edcSAsim Jamshed 
70276404edcSAsim Jamshed 	/* works for both monitor listener and stream sockets */
70376404edcSAsim Jamshed 	RemoveMonitorEvents(mtcp, socket, side);
70476404edcSAsim Jamshed 
70576404edcSAsim Jamshed 	/* passive monitoring socket is not connected to any stream */
706*861ea7dfSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM) {
707*861ea7dfSAsim Jamshed 	  /* it should return an EPERM error instead of quitting silently */
708*861ea7dfSAsim Jamshed 	  errno = EPERM;
709*861ea7dfSAsim Jamshed 	  return -1;
710*861ea7dfSAsim Jamshed 	}
71176404edcSAsim Jamshed 
71276404edcSAsim Jamshed 	if (side == MOS_SIDE_CLI) {
71376404edcSAsim Jamshed 		/* see if the associated stream requires monitoring any more */
71476404edcSAsim Jamshed 		stream = (socket->monitor_stream->stream->side == MOS_SIDE_CLI) ?
71576404edcSAsim Jamshed 			socket->monitor_stream->stream :
71676404edcSAsim Jamshed 			socket->monitor_stream->stream->pair_stream;
71776404edcSAsim Jamshed 
71876404edcSAsim Jamshed 		mgmt = 0;
71976404edcSAsim Jamshed 		SOCKQ_FOREACH_START(walk, &stream->msocks) {
72076404edcSAsim Jamshed 			if (walk->monitor_stream->client_mon == 1) {
72176404edcSAsim Jamshed 				mgmt = 1;
72276404edcSAsim Jamshed 				break;
72376404edcSAsim Jamshed 			}
72476404edcSAsim Jamshed 		} SOCKQ_FOREACH_END;
72576404edcSAsim Jamshed 		/* if all streams have mgmt off, then tag the stream for destruction */
72676404edcSAsim Jamshed 		if (mgmt == 0) {
72776404edcSAsim Jamshed 			stream = (socket->monitor_stream->stream->side == MOS_SIDE_CLI) ?
72876404edcSAsim Jamshed 				socket->monitor_stream->stream :
72976404edcSAsim Jamshed 				socket->monitor_stream->stream->pair_stream;
73076404edcSAsim Jamshed 			stream->status_mgmt = 0;
73176404edcSAsim Jamshed 		}
73276404edcSAsim Jamshed 	}
73376404edcSAsim Jamshed 
73476404edcSAsim Jamshed 	if (side == MOS_SIDE_SVR) {
73576404edcSAsim Jamshed 		/* see if the associated stream requires monitoring any more */
73676404edcSAsim Jamshed 		stream = (socket->monitor_stream->stream->side == MOS_SIDE_SVR) ?
73776404edcSAsim Jamshed 			socket->monitor_stream->stream :
73876404edcSAsim Jamshed 			socket->monitor_stream->stream->pair_stream;
73976404edcSAsim Jamshed 		mgmt = 0;
74076404edcSAsim Jamshed 		SOCKQ_FOREACH_START(walk, &stream->msocks) {
74176404edcSAsim Jamshed 			if (walk->monitor_stream->server_mon == 1) {
74276404edcSAsim Jamshed 				mgmt = 1;
74376404edcSAsim Jamshed 				break;
74476404edcSAsim Jamshed 			}
74576404edcSAsim Jamshed 		} SOCKQ_FOREACH_END;
74676404edcSAsim Jamshed 		/* if all streams have mgmt off, then tag the stream for destruction */
74776404edcSAsim Jamshed 		if (mgmt == 0) {
74876404edcSAsim Jamshed 			stream = (socket->monitor_stream->stream->side == MOS_SIDE_SVR) ?
74976404edcSAsim Jamshed 				socket->monitor_stream->stream :
75076404edcSAsim Jamshed 				socket->monitor_stream->stream->pair_stream;
75176404edcSAsim Jamshed 			stream->status_mgmt = 0;
75276404edcSAsim Jamshed 		}
75376404edcSAsim Jamshed 	}
75476404edcSAsim Jamshed 
75576404edcSAsim Jamshed 	return 0;
75676404edcSAsim Jamshed }
75776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
75876404edcSAsim Jamshed /**
75976404edcSAsim Jamshed  * send a RST packet to the TCP stream (uni-directional)
76076404edcSAsim Jamshed  */
76176404edcSAsim Jamshed static inline void
76276404edcSAsim Jamshed SendRSTPacketStandalone(mtcp_manager_t mtcp, struct tcp_stream *stream) {
76376404edcSAsim Jamshed 	SendTCPPacketStandalone(mtcp,
76476404edcSAsim Jamshed 				stream->saddr, stream->sport, stream->daddr, stream->dport,
76576404edcSAsim Jamshed 				stream->snd_nxt, stream->rcv_nxt, 0, TCP_FLAG_RST | TCP_FLAG_ACK,
766a834ea89SAsim Jamshed 				NULL, 0, mtcp->cur_ts, 0, 0, -1);
76776404edcSAsim Jamshed }
76876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
76976404edcSAsim Jamshed /**
77076404edcSAsim Jamshed  * Reset the connection (send RST packets to both sides)
77176404edcSAsim Jamshed  */
77276404edcSAsim Jamshed int
77376404edcSAsim Jamshed mtcp_reset_conn(mctx_t mctx, int sock)
77476404edcSAsim Jamshed {
77576404edcSAsim Jamshed 	mtcp_manager_t mtcp;
77676404edcSAsim Jamshed 	socket_map_t socket;
77776404edcSAsim Jamshed 
77876404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
77976404edcSAsim Jamshed 	if (!mtcp) {
78076404edcSAsim Jamshed 		errno = EACCES;
78176404edcSAsim Jamshed 		return -1;
78276404edcSAsim Jamshed 	}
78376404edcSAsim Jamshed 
78476404edcSAsim Jamshed 	socket = &mtcp->msmap[sock];
78576404edcSAsim Jamshed 
78676404edcSAsim Jamshed 	/* passive monitoring socket is not connected to any stream */
78776404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM) {
78876404edcSAsim Jamshed 		errno = EINVAL;
78976404edcSAsim Jamshed 		return -1;
79076404edcSAsim Jamshed 	}
79176404edcSAsim Jamshed 
79276404edcSAsim Jamshed 	/* send RST packets to the both sides */
79376404edcSAsim Jamshed 	SendRSTPacketStandalone(mtcp, socket->monitor_stream->stream);
79476404edcSAsim Jamshed 	SendRSTPacketStandalone(mtcp, socket->monitor_stream->stream->pair_stream);
79576404edcSAsim Jamshed 
79676404edcSAsim Jamshed 	return 0;
79776404edcSAsim Jamshed }
79876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
79976404edcSAsim Jamshed uint32_t
80076404edcSAsim Jamshed mtcp_cb_get_ts(mctx_t mctx)
80176404edcSAsim Jamshed {
80276404edcSAsim Jamshed 	mtcp_manager_t mtcp;
80376404edcSAsim Jamshed 
80476404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
80576404edcSAsim Jamshed 	if (!mtcp) {
80676404edcSAsim Jamshed 		TRACE_DBG("Can't access MTCP manager!\n");
80776404edcSAsim Jamshed 		errno = EACCES;
80876404edcSAsim Jamshed 		return 0;
80976404edcSAsim Jamshed 	}
81076404edcSAsim Jamshed 
81176404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
81276404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
81376404edcSAsim Jamshed 		errno = EPERM;
81476404edcSAsim Jamshed 		return 0;
81576404edcSAsim Jamshed 	}
81676404edcSAsim Jamshed 
81776404edcSAsim Jamshed 	return TS_TO_USEC(mtcp->cur_ts);
81876404edcSAsim Jamshed }
81976404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
82076404edcSAsim Jamshed /* Macros related to getpeername */
82176404edcSAsim Jamshed #define TILL_SVRADDR		offsetof(struct sockaddr_in, sin_zero)
82276404edcSAsim Jamshed #define TILL_SVRPORT		offsetof(struct sockaddr_in, sin_addr)
82376404edcSAsim Jamshed #define TILL_SVRFAMILY		offsetof(struct sockaddr_in, sin_port)
82476404edcSAsim Jamshed #define TILL_CLIADDR		sizeof(struct sockaddr) + TILL_SVRADDR
82576404edcSAsim Jamshed #define TILL_CLIPORT		sizeof(struct sockaddr) + TILL_SVRPORT
82676404edcSAsim Jamshed #define TILL_CLIFAMILY		sizeof(struct sockaddr) + TILL_SVRFAMILY
82776404edcSAsim Jamshed 
82876404edcSAsim Jamshed int
82976404edcSAsim Jamshed mtcp_getpeername(mctx_t mctx, int sockfd, struct sockaddr *saddr,
83076404edcSAsim Jamshed 				 socklen_t *addrlen, int side)
83176404edcSAsim Jamshed {
83276404edcSAsim Jamshed 	mtcp_manager_t mtcp;
83376404edcSAsim Jamshed 	socket_map_t socket;
83476404edcSAsim Jamshed 	struct tcp_stream *stream;
83576404edcSAsim Jamshed 	struct sockaddr_in *sin;
83676404edcSAsim Jamshed 	int rc;
83776404edcSAsim Jamshed 
83876404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
83976404edcSAsim Jamshed 	if (!mtcp) {
84076404edcSAsim Jamshed 		TRACE_DBG("Can't access MTCP manager!\n");
84176404edcSAsim Jamshed 		errno = EACCES;
84276404edcSAsim Jamshed 		return -1;
84376404edcSAsim Jamshed 	}
84476404edcSAsim Jamshed 
845a5e1a556SAsim Jamshed 	/* check if sockfd is within limits */
846a5e1a556SAsim Jamshed 	if (sockfd < 0 || sockfd >= g_config.mos->max_concurrency) {
847a5e1a556SAsim Jamshed 		TRACE_API("Socket id %d out of range.\n", sockfd);
848a5e1a556SAsim Jamshed 		errno = EBADF;
849a5e1a556SAsim Jamshed 		return -1;
850a5e1a556SAsim Jamshed 	}
851a5e1a556SAsim Jamshed 
85276404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
85376404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
85476404edcSAsim Jamshed 		errno = EPERM;
85576404edcSAsim Jamshed 		return -1;
85676404edcSAsim Jamshed 	}
85776404edcSAsim Jamshed 
85876404edcSAsim Jamshed 	socket = &mtcp->msmap[sockfd];
85976404edcSAsim Jamshed 	sin = (struct sockaddr_in *)saddr;
86076404edcSAsim Jamshed 	rc = 0;
86176404edcSAsim Jamshed 
86276404edcSAsim Jamshed 	/* retrieve both streams */
86376404edcSAsim Jamshed 	stream = socket->monitor_stream->stream;
86476404edcSAsim Jamshed 
86576404edcSAsim Jamshed 	if (side != stream->side)
86676404edcSAsim Jamshed 		stream = stream->pair_stream;
86776404edcSAsim Jamshed 
868a5e1a556SAsim Jamshed 	if (stream == NULL) {
869a5e1a556SAsim Jamshed 		errno = ENOTCONN;
87076404edcSAsim Jamshed 		return -1;
871a5e1a556SAsim Jamshed 	}
87276404edcSAsim Jamshed 
87376404edcSAsim Jamshed 	/* reset to 2 * sizeof(struct sockaddr) if addrlen is too big */
87476404edcSAsim Jamshed 	if (*addrlen > 2 * sizeof(struct sockaddr))
87576404edcSAsim Jamshed 		*addrlen = 2 * sizeof(struct sockaddr);
87676404edcSAsim Jamshed 
87776404edcSAsim Jamshed 	/* according per manpage, address can be truncated */
87876404edcSAsim Jamshed 	switch (*addrlen) {
87976404edcSAsim Jamshed 	case (2 * sizeof(struct sockaddr)):
88076404edcSAsim Jamshed 	case TILL_CLIADDR:
88176404edcSAsim Jamshed 		sin[1].sin_addr.s_addr = stream->side == MOS_SIDE_SVR ?
88276404edcSAsim Jamshed 								 stream->daddr : stream->saddr;
88376404edcSAsim Jamshed 	case TILL_CLIPORT:
88476404edcSAsim Jamshed 		sin[1].sin_port = stream->side == MOS_SIDE_SVR ?
88576404edcSAsim Jamshed 						  stream->dport : stream->sport;
88676404edcSAsim Jamshed 	case TILL_CLIFAMILY:
88776404edcSAsim Jamshed 		sin[1].sin_family = AF_INET;
88876404edcSAsim Jamshed 	case (sizeof(struct sockaddr)):
88976404edcSAsim Jamshed 	case TILL_SVRADDR:
89076404edcSAsim Jamshed 		sin->sin_addr.s_addr = stream->side == MOS_SIDE_SVR ?
89176404edcSAsim Jamshed 							   stream->saddr : stream->daddr;
89276404edcSAsim Jamshed 	case TILL_SVRPORT:
89376404edcSAsim Jamshed 		sin->sin_port = stream->side == MOS_SIDE_SVR ?
89476404edcSAsim Jamshed 						stream->sport : stream->dport;
89576404edcSAsim Jamshed 	case TILL_SVRFAMILY:
89676404edcSAsim Jamshed 		sin->sin_family = AF_INET;
89776404edcSAsim Jamshed 		break;
89876404edcSAsim Jamshed 	default:
89976404edcSAsim Jamshed 		rc = -1;
90076404edcSAsim Jamshed 		*addrlen = 0xFFFF;
901a5e1a556SAsim Jamshed 		errno = EINVAL;
90276404edcSAsim Jamshed 	}
90376404edcSAsim Jamshed 
90476404edcSAsim Jamshed 	return rc;
90576404edcSAsim Jamshed }
90676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
90776404edcSAsim Jamshed int
90876404edcSAsim Jamshed mtcp_setlastpkt(mctx_t mctx, int sock, int side, off_t offset,
90976404edcSAsim Jamshed 		byte *data, uint16_t datalen, int option)
91076404edcSAsim Jamshed {
91176404edcSAsim Jamshed 	mtcp_manager_t mtcp;
91276404edcSAsim Jamshed 	struct pkt_ctx *cur_pkt_ctx;
91376404edcSAsim Jamshed 	struct ethhdr *ethh;
91476404edcSAsim Jamshed 	struct iphdr *iph;
91576404edcSAsim Jamshed 	struct tcphdr *tcph;
91676404edcSAsim Jamshed 	unsigned char *payload;
91776404edcSAsim Jamshed 
91876404edcSAsim Jamshed #if 0
91976404edcSAsim Jamshed 	socket_map_t socket;
92076404edcSAsim Jamshed 	struct tcp_stream *cur_stream;
92176404edcSAsim Jamshed #endif
92276404edcSAsim Jamshed 
92376404edcSAsim Jamshed 	/* checking if mtcp is valid */
92476404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
92576404edcSAsim Jamshed 	if (!mtcp) {
92676404edcSAsim Jamshed 		errno = EACCES;
92776404edcSAsim Jamshed 		TRACE_ERROR("Invalid mtcp!\n");
92876404edcSAsim Jamshed 		return -1;
92976404edcSAsim Jamshed 	}
93076404edcSAsim Jamshed 
93176404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
93276404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
93376404edcSAsim Jamshed 		errno = EPERM;
93476404edcSAsim Jamshed 		TRACE_ERROR("Invalid thread id!\n");
93576404edcSAsim Jamshed 		return -1;
93676404edcSAsim Jamshed 	}
93776404edcSAsim Jamshed 
93876404edcSAsim Jamshed #if 0
93976404edcSAsim Jamshed 	/* check if the socket is monitor stream */
94076404edcSAsim Jamshed 	socket = &mtcp->msmap[sock];
94176404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE) {
94276404edcSAsim Jamshed 		if (side != MOS_SIDE_CLI && side != MOS_SIDE_SVR) {
94376404edcSAsim Jamshed 			TRACE_ERROR("Invalid side requested!\n");
94476404edcSAsim Jamshed 			exit(EXIT_FAILURE);
94576404edcSAsim Jamshed 			return -1;
94676404edcSAsim Jamshed 		}
94776404edcSAsim Jamshed 
94876404edcSAsim Jamshed 		struct tcp_stream *mstrm = socket->monitor_stream->stream;
94976404edcSAsim Jamshed 		cur_stream = (side == mstrm->side) ? mstrm : mstrm->pair_stream;
95076404edcSAsim Jamshed 
95176404edcSAsim Jamshed 		if (!cur_stream->allow_pkt_modification)
95276404edcSAsim Jamshed 			return -1;
95376404edcSAsim Jamshed 	} else if (socket->socktype != MOS_SOCK_MONITOR_RAW) {
95476404edcSAsim Jamshed 		TRACE_ERROR("Invalid socket type!\n");
95576404edcSAsim Jamshed 		exit(EXIT_FAILURE);
95676404edcSAsim Jamshed 		return -1;
95776404edcSAsim Jamshed 	}
95876404edcSAsim Jamshed #endif
95976404edcSAsim Jamshed 
96076404edcSAsim Jamshed 	/* see if cur_pkt_ctx is valid */
96176404edcSAsim Jamshed 	cur_pkt_ctx = mtcp->pctx;
96276404edcSAsim Jamshed 	if (cur_pkt_ctx == NULL) {
96376404edcSAsim Jamshed 		TRACE_ERROR("pctx is NULL!\n");
96476404edcSAsim Jamshed 		errno = ENODATA;
96576404edcSAsim Jamshed 		return -1;
96676404edcSAsim Jamshed 	}
96776404edcSAsim Jamshed 
96876404edcSAsim Jamshed 	/* check if offset is valid */
96976404edcSAsim Jamshed 	if (offset < 0) {
97076404edcSAsim Jamshed 		TRACE_ERROR("Invalid offset position!\n");
97176404edcSAsim Jamshed 		errno = EINVAL;
97276404edcSAsim Jamshed 		return -1;
97376404edcSAsim Jamshed 	}
97476404edcSAsim Jamshed 
97576404edcSAsim Jamshed 	if (__builtin_popcount(option & (MOS_DROP | MOS_CHOMP |
97676404edcSAsim Jamshed 					 MOS_INSERT | MOS_OVERWRITE)) != 1) {
97776404edcSAsim Jamshed 		TRACE_ERROR("mtcp_setlastpkt() function only allows one of "
97876404edcSAsim Jamshed 			    "(MOS_DROP | MOS_CHOMP | MOS_INSERT | MOS_OVERWRITE) "
97976404edcSAsim Jamshed 			    "to be set at a time.\n");
98076404edcSAsim Jamshed 		errno = EAGAIN;
98176404edcSAsim Jamshed 		return -1;
98276404edcSAsim Jamshed 	}
98376404edcSAsim Jamshed 
98476404edcSAsim Jamshed 	/* drop pkt has the highest priority */
98576404edcSAsim Jamshed 	if (option & MOS_DROP) {
98676404edcSAsim Jamshed 		mtcp->pctx->forward = 0;
98776404edcSAsim Jamshed 		return 0;
98876404edcSAsim Jamshed 	} else if (option & MOS_ETH_HDR) {
98976404edcSAsim Jamshed 		/* validity test */
99076404edcSAsim Jamshed 		if ((ethh=cur_pkt_ctx->p.ethh) == NULL ||
99176404edcSAsim Jamshed 		    offset + datalen > sizeof(struct ethhdr)) {
99276404edcSAsim Jamshed 			TRACE_ERROR("Ethernet setting has gone out of bounds "
99376404edcSAsim Jamshed 				    "(offset: %ld, datalen: %d)\n",
99476404edcSAsim Jamshed 				    offset, datalen);
99576404edcSAsim Jamshed 			errno = EINVAL;
99676404edcSAsim Jamshed 			return -1;
99776404edcSAsim Jamshed 		}
99876404edcSAsim Jamshed 		if (option & MOS_CHOMP) {
99976404edcSAsim Jamshed 			TRACE_ERROR("Illegal call. "
100076404edcSAsim Jamshed 				    "Ethernet header can't be chopped down!\n");
100176404edcSAsim Jamshed 			errno = EACCES;
100276404edcSAsim Jamshed 			return -1;
100376404edcSAsim Jamshed 		} else if (option & MOS_INSERT) {
100476404edcSAsim Jamshed 			TRACE_ERROR("Illegal call. "
100576404edcSAsim Jamshed 				    "Ethernet header can't be extended!\n");
100676404edcSAsim Jamshed 			errno = EACCES;
100776404edcSAsim Jamshed 			return -1;
100876404edcSAsim Jamshed 		} else /* if (option & MOS_OVERWRITE) */ {
100976404edcSAsim Jamshed 			memcpy((uint8_t *)ethh + offset, data, datalen);
101076404edcSAsim Jamshed 		}
101176404edcSAsim Jamshed 		/* iph, tcph, and payload do not need to change */
101276404edcSAsim Jamshed 	} else if (option & MOS_IP_HDR) {
101376404edcSAsim Jamshed 		/* validity test */
101476404edcSAsim Jamshed 		if (cur_pkt_ctx->p.ethh == NULL ||
101576404edcSAsim Jamshed 		    cur_pkt_ctx->p.ethh->h_proto != ntohs(ETH_P_IP) ||
101676404edcSAsim Jamshed 		    (iph=(struct iphdr *)(cur_pkt_ctx->p.ethh + 1)) == NULL) {
101776404edcSAsim Jamshed 			TRACE_ERROR("ethh or iph are out of bounds\n");
101876404edcSAsim Jamshed 			errno = EACCES;
101976404edcSAsim Jamshed 			return -1;
102076404edcSAsim Jamshed 		}
102176404edcSAsim Jamshed 		if (option & MOS_OVERWRITE) {
102276404edcSAsim Jamshed 			if (offset + datalen > (iph->ihl<<2)) {
102376404edcSAsim Jamshed 				TRACE_ERROR("IP setting has gone out of bounds "
102476404edcSAsim Jamshed 					    "(offset: %ld, datalen: %d)\n",
102576404edcSAsim Jamshed 					    offset, datalen);
102676404edcSAsim Jamshed 				errno = EINVAL;
102776404edcSAsim Jamshed 				return -1;
102876404edcSAsim Jamshed 			}
102976404edcSAsim Jamshed 			memcpy((uint8_t *)iph + offset, data, datalen);
103076404edcSAsim Jamshed 		}
103176404edcSAsim Jamshed 		if (option & MOS_CHOMP) {
103276404edcSAsim Jamshed 			memmove((uint8_t *)iph + offset,
103376404edcSAsim Jamshed 				(uint8_t *)iph + offset + datalen,
103476404edcSAsim Jamshed 				cur_pkt_ctx->p.ip_len - offset - datalen);
103576404edcSAsim Jamshed 
103676404edcSAsim Jamshed 			/* iph does not need to change */
103776404edcSAsim Jamshed 			if (iph->protocol == IPPROTO_TCP) {
103876404edcSAsim Jamshed 				cur_pkt_ctx->p.tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2));
103976404edcSAsim Jamshed 				cur_pkt_ctx->p.payload = (uint8_t *)cur_pkt_ctx->p.tcph +
104076404edcSAsim Jamshed 					(cur_pkt_ctx->p.tcph->doff<<2);
104176404edcSAsim Jamshed 			} else {
104276404edcSAsim Jamshed 				/* reset tcph if iph does not have tcp proto */
104376404edcSAsim Jamshed 				cur_pkt_ctx->p.tcph = NULL;
104476404edcSAsim Jamshed 			}
104576404edcSAsim Jamshed 			/* update iph total length */
104676404edcSAsim Jamshed 			cur_pkt_ctx->p.ip_len = ntohs(iph->tot_len);
104776404edcSAsim Jamshed 			/* update eth frame length */
104876404edcSAsim Jamshed 			cur_pkt_ctx->p.eth_len = cur_pkt_ctx->p.ip_len + sizeof(struct ethhdr);
104976404edcSAsim Jamshed 		} else if (option & MOS_INSERT) {
105076404edcSAsim Jamshed 			memmove((uint8_t *)iph + offset + datalen,
105176404edcSAsim Jamshed 				(uint8_t *)iph + offset + 1,
105276404edcSAsim Jamshed 				cur_pkt_ctx->p.ip_len - offset);
105376404edcSAsim Jamshed 			memcpy((uint8_t *)iph + offset,
105476404edcSAsim Jamshed 			       data, datalen);
105576404edcSAsim Jamshed 
105676404edcSAsim Jamshed 			/* iph does not need to change */
105776404edcSAsim Jamshed 			if (iph->protocol == IPPROTO_TCP) {
105876404edcSAsim Jamshed 				cur_pkt_ctx->p.tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2));
105976404edcSAsim Jamshed 				cur_pkt_ctx->p.payload = (uint8_t *)cur_pkt_ctx->p.tcph +
106076404edcSAsim Jamshed 					(cur_pkt_ctx->p.tcph->doff<<2);
106176404edcSAsim Jamshed 			} else {
106276404edcSAsim Jamshed 				/* reset tcph if iph does not have tcp proto */
106376404edcSAsim Jamshed 				cur_pkt_ctx->p.tcph = NULL;
106476404edcSAsim Jamshed 			}
106576404edcSAsim Jamshed 			/* update iph total length */
106676404edcSAsim Jamshed 			cur_pkt_ctx->p.ip_len = ntohs(iph->tot_len);
106776404edcSAsim Jamshed 			/* update eth frame length */
106876404edcSAsim Jamshed 			cur_pkt_ctx->p.eth_len = cur_pkt_ctx->p.ip_len + sizeof(struct ethhdr);
106976404edcSAsim Jamshed 		}
107076404edcSAsim Jamshed 		/* can't update payloadlen because we don't know tcph->doff */
107176404edcSAsim Jamshed 	} else if (option & MOS_TCP_HDR) {
107276404edcSAsim Jamshed 		/* validity test */
107376404edcSAsim Jamshed 		iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1);
107476404edcSAsim Jamshed 		if (iph == NULL ||
107576404edcSAsim Jamshed 		    iph->protocol != IPPROTO_TCP ||
107676404edcSAsim Jamshed 		    (tcph=(struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2))) == NULL) {
107776404edcSAsim Jamshed 			TRACE_ERROR("TCP setting has gone out of bounds "
107876404edcSAsim Jamshed 				    "(offset: %ld, datalen: %d)\n",
107976404edcSAsim Jamshed 				    offset, datalen);
108076404edcSAsim Jamshed 			errno = EINVAL;
108176404edcSAsim Jamshed 			return -1;
108276404edcSAsim Jamshed 		}
108376404edcSAsim Jamshed 		if (option & MOS_OVERWRITE) {
108476404edcSAsim Jamshed 			if (offset + datalen > (tcph->doff<<2)) {
108576404edcSAsim Jamshed 				TRACE_ERROR("TCP setting has gone out of bounds "
108676404edcSAsim Jamshed 					    "(offset: %ld, datalen: %d)\n",
108776404edcSAsim Jamshed 					    offset, datalen);
108876404edcSAsim Jamshed 				errno = EINVAL;
108976404edcSAsim Jamshed 				return -1;
109076404edcSAsim Jamshed 			}
109176404edcSAsim Jamshed 			memcpy((uint8_t *)tcph + offset, data, datalen);
109276404edcSAsim Jamshed 			/* update tcp seq # */
109376404edcSAsim Jamshed 			cur_pkt_ctx->p.seq = ntohl(tcph->seq);
109476404edcSAsim Jamshed 			/* update tcp ack_seq # */
109576404edcSAsim Jamshed 			cur_pkt_ctx->p.ack_seq = ntohl(tcph->ack_seq);
109676404edcSAsim Jamshed 			/* update tcp window */
109776404edcSAsim Jamshed 			cur_pkt_ctx->p.window = ntohs(tcph->window);
109876404edcSAsim Jamshed 
109976404edcSAsim Jamshed 			/* 150422 dhkim TODO: seq and offset are two different form of same
110076404edcSAsim Jamshed 			 * variable. We also need to update the offset. */
110176404edcSAsim Jamshed 		}
110276404edcSAsim Jamshed 		if (option & MOS_CHOMP) {
110376404edcSAsim Jamshed 			memmove((uint8_t *)tcph + offset,
110476404edcSAsim Jamshed 				(uint8_t *)tcph + offset + datalen,
110576404edcSAsim Jamshed 				cur_pkt_ctx->p.payloadlen + (tcph->doff<<2)
110676404edcSAsim Jamshed 				- offset - datalen);
110776404edcSAsim Jamshed 			/* update payload ptr */
110876404edcSAsim Jamshed 			cur_pkt_ctx->p.payload = (uint8_t *)tcph + (tcph->doff<<2);
110976404edcSAsim Jamshed 		} else if (option & MOS_INSERT) {
111076404edcSAsim Jamshed 			memmove((uint8_t *)tcph + offset + datalen,
111176404edcSAsim Jamshed 				(uint8_t *)tcph + offset + 1,
111276404edcSAsim Jamshed 				cur_pkt_ctx->p.payloadlen + (tcph->doff<<2)
111376404edcSAsim Jamshed 				- offset);
111476404edcSAsim Jamshed 			memcpy((uint8_t *)tcph + offset, data, datalen);
111576404edcSAsim Jamshed 			/* update payload ptr */
111676404edcSAsim Jamshed 			cur_pkt_ctx->p.payload = (uint8_t *)tcph + (tcph->doff<<2);
111776404edcSAsim Jamshed 		}
111876404edcSAsim Jamshed 	} else if (option & MOS_TCP_PAYLOAD) {
111976404edcSAsim Jamshed 		iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1);
112076404edcSAsim Jamshed 		tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2));
112176404edcSAsim Jamshed 		payload = (uint8_t *)tcph + (tcph->doff<<2);
112276404edcSAsim Jamshed 		if (option & MOS_OVERWRITE) {
112376404edcSAsim Jamshed 			if (offset + datalen > ntohs(iph->tot_len) -
112476404edcSAsim Jamshed 			    (iph->ihl<<2) - (tcph->doff<<2)) {
112576404edcSAsim Jamshed 				TRACE_ERROR("Payload setting has gone out of bounds "
112676404edcSAsim Jamshed 					    "(offset: %ld, datalen: %d)\n",
112776404edcSAsim Jamshed 					    offset, datalen);
112876404edcSAsim Jamshed 				errno = EINVAL;
112976404edcSAsim Jamshed 				return -1;
113076404edcSAsim Jamshed 			}
113176404edcSAsim Jamshed 			memcpy(payload + offset, data, datalen);
113276404edcSAsim Jamshed 		}
113376404edcSAsim Jamshed 		if (option & MOS_CHOMP) {
113476404edcSAsim Jamshed 			memmove(payload + offset,
113576404edcSAsim Jamshed 				payload + offset + datalen,
113676404edcSAsim Jamshed 				(cur_pkt_ctx->p.payloadlen -
113776404edcSAsim Jamshed 				 offset - datalen));
113876404edcSAsim Jamshed 			/* update payload length */
113976404edcSAsim Jamshed 			cur_pkt_ctx->p.payloadlen = cur_pkt_ctx->p.ip_len -
114076404edcSAsim Jamshed 				(tcph->doff<<2) - (iph->ihl<<2);
114176404edcSAsim Jamshed 		} else if (option & MOS_INSERT) {
114276404edcSAsim Jamshed 			memmove(payload + offset + datalen,
114376404edcSAsim Jamshed 				payload + offset + 1,
114476404edcSAsim Jamshed 				cur_pkt_ctx->p.payloadlen - offset);
114576404edcSAsim Jamshed 			memcpy(payload + offset, data, datalen);
114676404edcSAsim Jamshed 			cur_pkt_ctx->p.payloadlen = cur_pkt_ctx->p.ip_len -
114776404edcSAsim Jamshed 				(tcph->doff<<2) - (iph->ihl<<2);
114876404edcSAsim Jamshed 		}
114976404edcSAsim Jamshed 	} else {
115076404edcSAsim Jamshed 		TRACE_ERROR("Invalid option!\n");
115176404edcSAsim Jamshed 		errno = EINVAL;
115276404edcSAsim Jamshed 		return -1;
115376404edcSAsim Jamshed 	}
115476404edcSAsim Jamshed 
115576404edcSAsim Jamshed 	/* update ip checksum */
115676404edcSAsim Jamshed 	if (option & MOS_UPDATE_IP_CHKSUM) {
115776404edcSAsim Jamshed 		iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1);
115876404edcSAsim Jamshed 		iph->check = 0;
115976404edcSAsim Jamshed 		iph->check = ip_fast_csum(iph, iph->ihl);
116076404edcSAsim Jamshed 	}
116176404edcSAsim Jamshed 
116276404edcSAsim Jamshed 	/* update tcp checksum */
116376404edcSAsim Jamshed 	if (option & MOS_UPDATE_TCP_CHKSUM) {
116476404edcSAsim Jamshed 		iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1);
116576404edcSAsim Jamshed 		tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2));
116676404edcSAsim Jamshed 		tcph->check = 0;
116776404edcSAsim Jamshed 		tcph->check = TCPCalcChecksum((uint16_t *)tcph,
116876404edcSAsim Jamshed 					      ntohs(iph->tot_len) - (iph->ihl<<2),
116976404edcSAsim Jamshed 					      iph->saddr, iph->daddr);
117076404edcSAsim Jamshed 	}
117176404edcSAsim Jamshed 	return 0;
117276404edcSAsim Jamshed }
117376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
117476404edcSAsim Jamshed #if 0
117576404edcSAsim Jamshed inline int
117676404edcSAsim Jamshed mtcp_cb_updatecurpkt(mctx_t mctx, off_t offset, unsigned char *data,
117776404edcSAsim Jamshed 		     uint16_t datalen, int option)
117876404edcSAsim Jamshed {
117976404edcSAsim Jamshed 	return mtcp_setlastpkt(mctx, sock, side, offset, data, datalen, option);
118076404edcSAsim Jamshed }
118176404edcSAsim Jamshed #endif
118276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
118376404edcSAsim Jamshed /**
118476404edcSAsim Jamshed  * THIS IS A DEPRECETED FUNCTION...
118576404edcSAsim Jamshed  */
118676404edcSAsim Jamshed int
118776404edcSAsim Jamshed mtcp_cb_dropcurpkt(mctx_t mctx)
118876404edcSAsim Jamshed {
118976404edcSAsim Jamshed 	mtcp_manager_t mtcp;
119076404edcSAsim Jamshed 
119176404edcSAsim Jamshed 	/* checking if mtcp is valid */
119276404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
119376404edcSAsim Jamshed 	if (!mtcp) {
119476404edcSAsim Jamshed 		TRACE_ERROR("Invalid mtcp!\n");
119576404edcSAsim Jamshed 		errno = EACCES;
119676404edcSAsim Jamshed 		return -1;
119776404edcSAsim Jamshed 	}
119876404edcSAsim Jamshed 
119976404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
120076404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
120176404edcSAsim Jamshed 		TRACE_ERROR("Invalid thread id!\n");
120276404edcSAsim Jamshed 		errno = EPERM;
120376404edcSAsim Jamshed 		return -1;
120476404edcSAsim Jamshed 	}
120576404edcSAsim Jamshed 
120676404edcSAsim Jamshed 	/* see if cur_pkt_ctx is valid */
120776404edcSAsim Jamshed 	if (mtcp->pctx == NULL) {
120876404edcSAsim Jamshed 		TRACE_ERROR("pctx is NULL!\n");
120976404edcSAsim Jamshed 		errno = ENODATA;
121076404edcSAsim Jamshed 		return -1;
121176404edcSAsim Jamshed 	}
121276404edcSAsim Jamshed 
121376404edcSAsim Jamshed 	mtcp->pctx->forward = 0;
121476404edcSAsim Jamshed 
121576404edcSAsim Jamshed 	return 0;
121676404edcSAsim Jamshed }
121776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
121876404edcSAsim Jamshed int
121976404edcSAsim Jamshed mtcp_set_debug_string(mtcp_manager_t mtcp, const char *fmt, ...)
122076404edcSAsim Jamshed {
122176404edcSAsim Jamshed #ifdef ENABLE_DEBUG_EVENT
122276404edcSAsim Jamshed 	va_list args;
122376404edcSAsim Jamshed 	int i;
122476404edcSAsim Jamshed 
122576404edcSAsim Jamshed 	assert(mtcp);
122676404edcSAsim Jamshed 
122776404edcSAsim Jamshed 	if (fmt == NULL) {
122876404edcSAsim Jamshed 		mtcp->dbg_buf[0] = '\0';
122976404edcSAsim Jamshed 		return 0;
123076404edcSAsim Jamshed 	}
123176404edcSAsim Jamshed 
123276404edcSAsim Jamshed 	va_start(args, fmt);
123376404edcSAsim Jamshed 	i = vsnprintf(mtcp->dbg_buf, DBG_BUF_LEN - 1, fmt, args);
123476404edcSAsim Jamshed 	va_end(args);
123576404edcSAsim Jamshed 
123676404edcSAsim Jamshed 	return i;
123776404edcSAsim Jamshed #else
123876404edcSAsim Jamshed 	return -1;
123976404edcSAsim Jamshed #endif /* ENABLE_DEBUG_EVENT */
124076404edcSAsim Jamshed }
124176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
124276404edcSAsim Jamshed int
124376404edcSAsim Jamshed mtcp_get_debug_string(mctx_t mctx, char *buf, int len)
124476404edcSAsim Jamshed {
124576404edcSAsim Jamshed #ifdef ENABLE_DEBUG_EVENT
124676404edcSAsim Jamshed 	mtcp_manager_t mtcp;
124776404edcSAsim Jamshed 	int copylen;
124876404edcSAsim Jamshed 
124976404edcSAsim Jamshed 	if (len < 0)
125076404edcSAsim Jamshed 		return -1;
125176404edcSAsim Jamshed 	else if (len == 0)
125276404edcSAsim Jamshed 		return 0;
125376404edcSAsim Jamshed 
125476404edcSAsim Jamshed 	if (!(mtcp = GetMTCPManager(mctx)))
125576404edcSAsim Jamshed 		return -1;
125676404edcSAsim Jamshed 
125776404edcSAsim Jamshed 	copylen = MIN(strlen(mtcp->dbg_buf), len);
125876404edcSAsim Jamshed 	strncpy(buf, mtcp->dbg_buf, copylen);
125976404edcSAsim Jamshed 
126076404edcSAsim Jamshed 	return copylen;
126176404edcSAsim Jamshed #else
126276404edcSAsim Jamshed 	return -1;
126376404edcSAsim Jamshed #endif /* ENABLE_DEBUG_EVENT */
126476404edcSAsim Jamshed }
126576404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1266