xref: /mOS-networking-stack/core/src/mos_api.c (revision 76404edc)
1*76404edcSAsim Jamshed #include <assert.h>
2*76404edcSAsim Jamshed #include <ctype.h>
3*76404edcSAsim Jamshed #include <string.h>
4*76404edcSAsim Jamshed #ifdef ENABLE_DEBUG_EVENT
5*76404edcSAsim Jamshed #include <stdarg.h>
6*76404edcSAsim Jamshed #endif
7*76404edcSAsim Jamshed 
8*76404edcSAsim Jamshed #include "mtcp.h"
9*76404edcSAsim Jamshed #include "mos_api.h"
10*76404edcSAsim Jamshed #include "debug.h"
11*76404edcSAsim Jamshed #include "config.h"
12*76404edcSAsim Jamshed #include "ip_in.h"
13*76404edcSAsim Jamshed #include "tcp_out.h"
14*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
15*76404edcSAsim Jamshed #define MAX(x, y) (((x) > (y)) ? (x) : (y))
16*76404edcSAsim Jamshed #define MIN(x, y) (((x) < (y)) ? (x) : (y))
17*76404edcSAsim Jamshed #define SKIP_SPACES(x) while (*x && isspace((int)*x)) x++;
18*76404edcSAsim Jamshed #define SKIP_CHAR(x) while((*x) && !isspace(*x)) x++;
19*76404edcSAsim Jamshed 
20*76404edcSAsim Jamshed #define KW_AND       "and "
21*76404edcSAsim Jamshed #define KW_OR        "or "
22*76404edcSAsim Jamshed #define KW_NOT       "not "
23*76404edcSAsim Jamshed #define KW_TCP       "tcp"
24*76404edcSAsim Jamshed #define KW_NOT_TCP   "!tcp"
25*76404edcSAsim Jamshed #define KW_NOT_TCP2  "not tcp"
26*76404edcSAsim Jamshed #define KW_SRC       "src "
27*76404edcSAsim Jamshed #define KW_DST       "dst "
28*76404edcSAsim Jamshed #define KW_HOST      "host "
29*76404edcSAsim Jamshed #define KW_NET       "net "
30*76404edcSAsim Jamshed #define KW_MASK      "mask "
31*76404edcSAsim Jamshed #define KW_PORT      "port "
32*76404edcSAsim Jamshed #define KW_PORTRANGE "portrange "
33*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
34*76404edcSAsim Jamshed int
35*76404edcSAsim Jamshed IsValidFlowRule(char *cf)
36*76404edcSAsim Jamshed {
37*76404edcSAsim Jamshed 	char *word;
38*76404edcSAsim Jamshed 	int skip_word = 0;
39*76404edcSAsim Jamshed 
40*76404edcSAsim Jamshed 	/* '!tcp' or 'not tcp' are also not supported in TCP flow filter */
41*76404edcSAsim Jamshed 	if (strstr(cf, KW_NOT_TCP) || strstr(cf, KW_NOT_TCP2)) {
42*76404edcSAsim Jamshed 		TRACE_ERROR("'!tcp' or 'not tcp' is not a valid rule for TCP flow monitor.\n");
43*76404edcSAsim Jamshed 		return FALSE;
44*76404edcSAsim Jamshed 	}
45*76404edcSAsim Jamshed 
46*76404edcSAsim Jamshed 	/* verify that the rule contains flow-related keywords only */
47*76404edcSAsim Jamshed 	word = cf;
48*76404edcSAsim Jamshed 	SKIP_SPACES(word);
49*76404edcSAsim Jamshed 
50*76404edcSAsim Jamshed 	/* while (browse the rule by words) */
51*76404edcSAsim Jamshed 	while (*word) {
52*76404edcSAsim Jamshed 		if (skip_word) {
53*76404edcSAsim Jamshed 			skip_word = 0;
54*76404edcSAsim Jamshed 			SKIP_CHAR(word);
55*76404edcSAsim Jamshed 			SKIP_SPACES(word);
56*76404edcSAsim Jamshed 			continue;
57*76404edcSAsim Jamshed 		}
58*76404edcSAsim Jamshed 		/* parse the keyword */
59*76404edcSAsim Jamshed 		/* case "tcp" "src" "dst" "not' "and" "or" -> move to the next word */
60*76404edcSAsim Jamshed 		if (!strncmp(word, KW_TCP, sizeof(KW_TCP) - 1) ||
61*76404edcSAsim Jamshed 			!strncmp(word, KW_SRC, sizeof(KW_SRC) - 1) ||
62*76404edcSAsim Jamshed 			!strncmp(word, KW_DST, sizeof(KW_DST) - 1) ||
63*76404edcSAsim Jamshed 			!strncmp(word, KW_NOT, sizeof(KW_NOT) - 1) ||
64*76404edcSAsim Jamshed 			!strncmp(word, KW_AND, sizeof(KW_AND) - 1) ||
65*76404edcSAsim Jamshed 			!strncmp(word, KW_OR, sizeof(KW_OR) - 1)) {
66*76404edcSAsim Jamshed 			skip_word = 0;
67*76404edcSAsim Jamshed 		}
68*76404edcSAsim Jamshed 		/* case "net" "mask" "port" "portrange" -> skip a word (= param) */
69*76404edcSAsim Jamshed 		else if (!strncmp(word, KW_HOST, sizeof(KW_HOST) - 1) ||
70*76404edcSAsim Jamshed 				 !strncmp(word, KW_NET, sizeof(KW_NET) - 1) ||
71*76404edcSAsim Jamshed 				 !strncmp(word, KW_MASK, sizeof(KW_MASK) - 1) ||
72*76404edcSAsim Jamshed 				 !strncmp(word, KW_PORT, sizeof(KW_PORT) - 1) ||
73*76404edcSAsim Jamshed 				 !strncmp(word, KW_PORTRANGE, sizeof(KW_PORTRANGE) - 1)) {
74*76404edcSAsim Jamshed 			skip_word = 1;
75*76404edcSAsim Jamshed 		}
76*76404edcSAsim Jamshed 		/* default (rule has any invalid keyword) -> return error */
77*76404edcSAsim Jamshed 		else {
78*76404edcSAsim Jamshed 			TRACE_ERROR("Invalid keyword in filter (%s)\n", word);
79*76404edcSAsim Jamshed 			return FALSE;
80*76404edcSAsim Jamshed 		}
81*76404edcSAsim Jamshed 
82*76404edcSAsim Jamshed 		SKIP_CHAR(word);
83*76404edcSAsim Jamshed 		SKIP_SPACES(word);
84*76404edcSAsim Jamshed 	}
85*76404edcSAsim Jamshed 
86*76404edcSAsim Jamshed 	return TRUE;
87*76404edcSAsim Jamshed }
88*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
89*76404edcSAsim Jamshed /* Assign an address range (specified by ft) to monitor via sock */
90*76404edcSAsim Jamshed int
91*76404edcSAsim Jamshed mtcp_bind_monitor_filter(mctx_t mctx, int sockid, monitor_filter_t ft)
92*76404edcSAsim Jamshed {
93*76404edcSAsim Jamshed 	socket_map_t sock;
94*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
95*76404edcSAsim Jamshed 
96*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
97*76404edcSAsim Jamshed 	if (!mtcp) {
98*76404edcSAsim Jamshed 		errno = EACCES;
99*76404edcSAsim Jamshed 		return -1;
100*76404edcSAsim Jamshed 	}
101*76404edcSAsim Jamshed 
102*76404edcSAsim Jamshed 	/* if filter is not set, do nothing and return */
103*76404edcSAsim Jamshed 	if (ft == NULL) {
104*76404edcSAsim Jamshed 		TRACE_ERROR("filter not set!\n");
105*76404edcSAsim Jamshed 		return 0;
106*76404edcSAsim Jamshed 	}
107*76404edcSAsim Jamshed 
108*76404edcSAsim Jamshed 	/* retrieve the socket */
109*76404edcSAsim Jamshed 	if (sockid < 0 || sockid >= g_config.mos->max_concurrency) {
110*76404edcSAsim Jamshed 		errno = EBADF;
111*76404edcSAsim Jamshed 		TRACE_ERROR("sockid is invalid!\n");
112*76404edcSAsim Jamshed 		return -1;
113*76404edcSAsim Jamshed 	}
114*76404edcSAsim Jamshed 	sock = &mtcp->msmap[sockid];
115*76404edcSAsim Jamshed 
116*76404edcSAsim Jamshed 	/* check socket type */
117*76404edcSAsim Jamshed 	switch (sock->socktype) {
118*76404edcSAsim Jamshed 	case MOS_SOCK_MONITOR_RAW:
119*76404edcSAsim Jamshed 		/* For MONITOR_RAW type, allow any bpf rule */
120*76404edcSAsim Jamshed 		if (!ft->raw_pkt_filter) {
121*76404edcSAsim Jamshed 			TRACE_ERROR("raw pkt filter is null");
122*76404edcSAsim Jamshed 			return 0;
123*76404edcSAsim Jamshed 		}
124*76404edcSAsim Jamshed 		if (SET_BPFFILTER(&sock->monitor_listener->raw_pkt_fcode,
125*76404edcSAsim Jamshed 						  ft->raw_pkt_filter) < 0) {
126*76404edcSAsim Jamshed 			TRACE_ERROR("Invalid filter expression!\n");
127*76404edcSAsim Jamshed 			errno = EINVAL;
128*76404edcSAsim Jamshed 			return -1;
129*76404edcSAsim Jamshed 		}
130*76404edcSAsim Jamshed 		break;
131*76404edcSAsim Jamshed 	case MOS_SOCK_MONITOR_STREAM:
132*76404edcSAsim Jamshed 		/* For MONITOR_STREAM_PASSIVE type, restrict to flow-level keywords */
133*76404edcSAsim Jamshed 		if (ft->stream_syn_filter) {
134*76404edcSAsim Jamshed 			if (!IsValidFlowRule(ft->stream_syn_filter)) {
135*76404edcSAsim Jamshed 				errno = EINVAL;
136*76404edcSAsim Jamshed 				return -1;
137*76404edcSAsim Jamshed 			}
138*76404edcSAsim Jamshed 			if (SET_BPFFILTER(&sock->monitor_listener->stream_syn_fcode,
139*76404edcSAsim Jamshed 							  ft->stream_syn_filter) < 0) {
140*76404edcSAsim Jamshed 				TRACE_ERROR("Invalid filter expression!\n");
141*76404edcSAsim Jamshed 				errno = EINVAL;
142*76404edcSAsim Jamshed 				return -1;
143*76404edcSAsim Jamshed 			}
144*76404edcSAsim Jamshed 		}
145*76404edcSAsim Jamshed 		if (ft->stream_orphan_filter) {
146*76404edcSAsim Jamshed 			if (!IsValidFlowRule(ft->stream_orphan_filter)) {
147*76404edcSAsim Jamshed 				errno = EINVAL;
148*76404edcSAsim Jamshed 				return -1;
149*76404edcSAsim Jamshed 			}
150*76404edcSAsim Jamshed 			if (SET_BPFFILTER(&sock->monitor_listener->stream_orphan_fcode,
151*76404edcSAsim Jamshed 							  ft->stream_orphan_filter) < 0) {
152*76404edcSAsim Jamshed 				TRACE_ERROR("Invalid filter expression!\n");
153*76404edcSAsim Jamshed 				errno = EINVAL;
154*76404edcSAsim Jamshed 				return -1;
155*76404edcSAsim Jamshed 			}
156*76404edcSAsim Jamshed 		}
157*76404edcSAsim Jamshed 		break;
158*76404edcSAsim Jamshed 	default:
159*76404edcSAsim Jamshed 		/* return error for other socket types */
160*76404edcSAsim Jamshed 		errno = ENOPROTOOPT;
161*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid sock type!\n");
162*76404edcSAsim Jamshed 		return -1;
163*76404edcSAsim Jamshed 	}
164*76404edcSAsim Jamshed 
165*76404edcSAsim Jamshed 	return 0;
166*76404edcSAsim Jamshed }
167*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
168*76404edcSAsim Jamshed void
169*76404edcSAsim Jamshed mtcp_app_join(mctx_t mctx)
170*76404edcSAsim Jamshed {
171*76404edcSAsim Jamshed 	mtcp_manager_t mtcp = GetMTCPManager(mctx);
172*76404edcSAsim Jamshed 	if (!mtcp) return;
173*76404edcSAsim Jamshed 
174*76404edcSAsim Jamshed 	RunPassiveLoop(mtcp);
175*76404edcSAsim Jamshed 	return;
176*76404edcSAsim Jamshed }
177*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
178*76404edcSAsim Jamshed /* Callback only functions */
179*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
180*76404edcSAsim Jamshed void
181*76404edcSAsim Jamshed mtcp_set_uctx(mctx_t mctx, int msock, void *uctx)
182*76404edcSAsim Jamshed {
183*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
184*76404edcSAsim Jamshed 
185*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
186*76404edcSAsim Jamshed 	if (!mtcp) {
187*76404edcSAsim Jamshed 		return;
188*76404edcSAsim Jamshed 	}
189*76404edcSAsim Jamshed 
190*76404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
191*76404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self())
192*76404edcSAsim Jamshed 		return;
193*76404edcSAsim Jamshed 
194*76404edcSAsim Jamshed 	if (msock < 0 || msock >= g_config.mos->max_concurrency) {
195*76404edcSAsim Jamshed 		TRACE_API("Socket id %d out of range.\n", msock);
196*76404edcSAsim Jamshed 		errno = EBADF;
197*76404edcSAsim Jamshed 		return;
198*76404edcSAsim Jamshed 	}
199*76404edcSAsim Jamshed 
200*76404edcSAsim Jamshed 	socket_map_t socket = &mtcp->msmap[msock];
201*76404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE)
202*76404edcSAsim Jamshed 		socket->monitor_stream->uctx = uctx;
203*76404edcSAsim Jamshed 	else if (socket->socktype == MOS_SOCK_MONITOR_STREAM ||
204*76404edcSAsim Jamshed 			 socket->socktype == MOS_SOCK_MONITOR_RAW)
205*76404edcSAsim Jamshed 		socket->monitor_listener->uctx = uctx;
206*76404edcSAsim Jamshed }
207*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
208*76404edcSAsim Jamshed void *
209*76404edcSAsim Jamshed mtcp_get_uctx(mctx_t mctx, int msock)
210*76404edcSAsim Jamshed {
211*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
212*76404edcSAsim Jamshed 
213*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
214*76404edcSAsim Jamshed 	if (!mtcp) {
215*76404edcSAsim Jamshed 		errno = EACCES;
216*76404edcSAsim Jamshed 		return NULL;
217*76404edcSAsim Jamshed 	}
218*76404edcSAsim Jamshed 
219*76404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
220*76404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
221*76404edcSAsim Jamshed 		errno = EPERM;
222*76404edcSAsim Jamshed 		return NULL;
223*76404edcSAsim Jamshed 	}
224*76404edcSAsim Jamshed 
225*76404edcSAsim Jamshed 	if (msock < 0 || msock >= g_config.mos->max_concurrency) {
226*76404edcSAsim Jamshed 		TRACE_API("Socket id %d out of range.\n", msock);
227*76404edcSAsim Jamshed 		errno = EBADF;
228*76404edcSAsim Jamshed 		return NULL;
229*76404edcSAsim Jamshed 	}
230*76404edcSAsim Jamshed 
231*76404edcSAsim Jamshed 	socket_map_t socket = &mtcp->msmap[msock];
232*76404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE)
233*76404edcSAsim Jamshed 		return socket->monitor_stream->uctx;
234*76404edcSAsim Jamshed 	else if (socket->socktype == MOS_SOCK_MONITOR_STREAM ||
235*76404edcSAsim Jamshed 			 socket->socktype == MOS_SOCK_MONITOR_RAW)
236*76404edcSAsim Jamshed 		return socket->monitor_listener->uctx;
237*76404edcSAsim Jamshed 	else
238*76404edcSAsim Jamshed 		return NULL;
239*76404edcSAsim Jamshed }
240*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
241*76404edcSAsim Jamshed ssize_t
242*76404edcSAsim Jamshed mtcp_peek(mctx_t mctx, int msock, int side, char *buf, size_t len)
243*76404edcSAsim Jamshed {
244*76404edcSAsim Jamshed 	int copylen, rc;
245*76404edcSAsim Jamshed 	struct tcp_stream *cur_stream;
246*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
247*76404edcSAsim Jamshed 	socket_map_t sock;
248*76404edcSAsim Jamshed 
249*76404edcSAsim Jamshed 	copylen = rc = 0;
250*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
251*76404edcSAsim Jamshed 	if (!mtcp) {
252*76404edcSAsim Jamshed 		errno = EACCES;
253*76404edcSAsim Jamshed 		return -1;
254*76404edcSAsim Jamshed 	}
255*76404edcSAsim Jamshed 
256*76404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
257*76404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
258*76404edcSAsim Jamshed 		errno = EPERM;
259*76404edcSAsim Jamshed 		return -1;
260*76404edcSAsim Jamshed 	}
261*76404edcSAsim Jamshed 
262*76404edcSAsim Jamshed 	/* check if the socket is monitor stream */
263*76404edcSAsim Jamshed 	sock = &mtcp->msmap[msock];
264*76404edcSAsim Jamshed 	if (sock->socktype != MOS_SOCK_MONITOR_STREAM_ACTIVE) {
265*76404edcSAsim Jamshed 		TRACE_DBG("Invalid socket type!\n");
266*76404edcSAsim Jamshed 		errno = EBADF;
267*76404edcSAsim Jamshed 		return -1;
268*76404edcSAsim Jamshed 	}
269*76404edcSAsim Jamshed 
270*76404edcSAsim Jamshed 	if (side != MOS_SIDE_CLI && side != MOS_SIDE_SVR) {
271*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid side requested!\n");
272*76404edcSAsim Jamshed 		exit(EXIT_FAILURE);
273*76404edcSAsim Jamshed 		return -1;
274*76404edcSAsim Jamshed 	}
275*76404edcSAsim Jamshed 
276*76404edcSAsim Jamshed 	struct tcp_stream *mstrm = sock->monitor_stream->stream;
277*76404edcSAsim Jamshed 	cur_stream = (side == mstrm->side) ? mstrm : mstrm->pair_stream;
278*76404edcSAsim Jamshed 
279*76404edcSAsim Jamshed 	if (!cur_stream || !cur_stream->buffer_mgmt) {
280*76404edcSAsim Jamshed 		TRACE_DBG("Stream is NULL!! or buffer management is disabled\n");
281*76404edcSAsim Jamshed 		errno = EINVAL;
282*76404edcSAsim Jamshed 		return -1;
283*76404edcSAsim Jamshed 	}
284*76404edcSAsim Jamshed 
285*76404edcSAsim Jamshed 	/* Check if the read was not just due to syn-ack recv */
286*76404edcSAsim Jamshed 	if (cur_stream->rcvvar != NULL &&
287*76404edcSAsim Jamshed 	    cur_stream->rcvvar->rcvbuf != NULL) {
288*76404edcSAsim Jamshed #ifdef NEWRB
289*76404edcSAsim Jamshed 		tcprb_t *rcvbuf = cur_stream->rcvvar->rcvbuf;
290*76404edcSAsim Jamshed 		loff_t *poff = &sock->monitor_stream->peek_offset[cur_stream->side];
291*76404edcSAsim Jamshed 
292*76404edcSAsim Jamshed 		rc = tcprb_ppeek(rcvbuf, (uint8_t *)buf, len, *poff);
293*76404edcSAsim Jamshed 		if (rc < 0) {
294*76404edcSAsim Jamshed 			errno = ENODATA;
295*76404edcSAsim Jamshed 			return -1;
296*76404edcSAsim Jamshed 		}
297*76404edcSAsim Jamshed 
298*76404edcSAsim Jamshed 		*poff += rc;
299*76404edcSAsim Jamshed 		UNUSED(copylen);
300*76404edcSAsim Jamshed 
301*76404edcSAsim Jamshed 		return rc;
302*76404edcSAsim Jamshed #else
303*76404edcSAsim Jamshed 		struct tcp_ring_buffer *rcvbuf;
304*76404edcSAsim Jamshed 		uint32_t *monitor_read_head_offset_ptr;
305*76404edcSAsim Jamshed 		uint8_t *overlap_ptr;
306*76404edcSAsim Jamshed 		/* assign monitor-related ptrs */
307*76404edcSAsim Jamshed 		rcvbuf = cur_stream->rcvvar->rcvbuf;
308*76404edcSAsim Jamshed 		monitor_read_head_offset_ptr = &sock->monitor_stream->monitor_read.head_offset[cur_stream->side];
309*76404edcSAsim Jamshed 		overlap_ptr = &sock->monitor_stream->monitor_read.overlap[cur_stream->side];
310*76404edcSAsim Jamshed 
311*76404edcSAsim Jamshed 		/*
312*76404edcSAsim Jamshed 		 * if the head ptr is way back than monitor offset...
313*76404edcSAsim Jamshed 		 * then head ptr has looped around.. use m_tail_offset as
314*76404edcSAsim Jamshed 		 * reference
315*76404edcSAsim Jamshed 		 */
316*76404edcSAsim Jamshed 		if (rcvbuf->head_offset + rcvbuf->merged_len <
317*76404edcSAsim Jamshed 		    *monitor_read_head_offset_ptr)
318*76404edcSAsim Jamshed 			copylen = MIN(rcvbuf->monitor_read_tail_offset -
319*76404edcSAsim Jamshed 						  *monitor_read_head_offset_ptr,
320*76404edcSAsim Jamshed 						  len);
321*76404edcSAsim Jamshed 		/*
322*76404edcSAsim Jamshed 		 * if the head ptr is ahead of monitor offset...
323*76404edcSAsim Jamshed 		 * then read till head + merged length
324*76404edcSAsim Jamshed 		 */
325*76404edcSAsim Jamshed 		else
326*76404edcSAsim Jamshed 			copylen = MIN(rcvbuf->head_offset +
327*76404edcSAsim Jamshed 						  rcvbuf->merged_len -
328*76404edcSAsim Jamshed 						  *monitor_read_head_offset_ptr,
329*76404edcSAsim Jamshed 						  len);
330*76404edcSAsim Jamshed 		memcpy(buf, rcvbuf->data + *monitor_read_head_offset_ptr, copylen);
331*76404edcSAsim Jamshed 		*monitor_read_head_offset_ptr += copylen;
332*76404edcSAsim Jamshed 		rc = copylen;
333*76404edcSAsim Jamshed 		if (*overlap_ptr) {
334*76404edcSAsim Jamshed 			*overlap_ptr = 0;
335*76404edcSAsim Jamshed 			rc = -1;
336*76404edcSAsim Jamshed 		}
337*76404edcSAsim Jamshed #endif
338*76404edcSAsim Jamshed 	} else {
339*76404edcSAsim Jamshed 		TRACE_DBG("Stream hasn't yet been initialized!\n");
340*76404edcSAsim Jamshed 		rc = 0;
341*76404edcSAsim Jamshed 	}
342*76404edcSAsim Jamshed 
343*76404edcSAsim Jamshed 	return rc;
344*76404edcSAsim Jamshed }
345*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
346*76404edcSAsim Jamshed /**
347*76404edcSAsim Jamshed  * Copies from the frags.. returns no. of bytes copied to buf
348*76404edcSAsim Jamshed  */
349*76404edcSAsim Jamshed static inline int
350*76404edcSAsim Jamshed ExtractPayloadFromFrags(struct tcp_ring_buffer *rcvbuf, char *buf,
351*76404edcSAsim Jamshed 						size_t count, off_t seq_num)
352*76404edcSAsim Jamshed {
353*76404edcSAsim Jamshed 	int cpbytesleft;
354*76404edcSAsim Jamshed 	struct fragment_ctx *it;
355*76404edcSAsim Jamshed 
356*76404edcSAsim Jamshed 	it = rcvbuf->fctx;
357*76404edcSAsim Jamshed 	cpbytesleft = count;
358*76404edcSAsim Jamshed 	/* go through each frag */
359*76404edcSAsim Jamshed 	while (it) {
360*76404edcSAsim Jamshed 		/* first check whether sequent number matches */
361*76404edcSAsim Jamshed 		if (TCP_SEQ_BETWEEN(seq_num, it->seq, it->seq + it->len)) {
362*76404edcSAsim Jamshed 			/* copy buf starting from seq# seq_num */
363*76404edcSAsim Jamshed 			/* copy the MIN of seq-range and bytes to be copied */
364*76404edcSAsim Jamshed 			memcpy(buf + count - cpbytesleft,
365*76404edcSAsim Jamshed 			       rcvbuf->head + seq_num - rcvbuf->head_seq,
366*76404edcSAsim Jamshed 			       MIN(it->len - (seq_num - it->seq), cpbytesleft));
367*76404edcSAsim Jamshed 			/* update target seq num */
368*76404edcSAsim Jamshed 			seq_num += it->len - (seq_num - it->seq);
369*76404edcSAsim Jamshed 			/* update cpbytes left */
370*76404edcSAsim Jamshed 			cpbytesleft -= it->len - (seq_num - it->seq);
371*76404edcSAsim Jamshed 			if (cpbytesleft == 0)
372*76404edcSAsim Jamshed 				break;
373*76404edcSAsim Jamshed 		}
374*76404edcSAsim Jamshed 		it = it->next;
375*76404edcSAsim Jamshed 	}
376*76404edcSAsim Jamshed 
377*76404edcSAsim Jamshed 	count -= cpbytesleft;
378*76404edcSAsim Jamshed 
379*76404edcSAsim Jamshed 	/* return number of bytes copied */
380*76404edcSAsim Jamshed 	return count;
381*76404edcSAsim Jamshed }
382*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
383*76404edcSAsim Jamshed /* Please see in-code comments for description */
384*76404edcSAsim Jamshed ssize_t
385*76404edcSAsim Jamshed #ifdef NEWPPEEK
386*76404edcSAsim Jamshed mtcp_ppeek(mctx_t mctx, int msock, int side,
387*76404edcSAsim Jamshed 			  char *buf, size_t count, uint64_t off)
388*76404edcSAsim Jamshed #else
389*76404edcSAsim Jamshed mtcp_ppeek(mctx_t mctx, int msock, int side,
390*76404edcSAsim Jamshed 			  char *buf, size_t count, off_t seq_num)
391*76404edcSAsim Jamshed #endif
392*76404edcSAsim Jamshed {
393*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
394*76404edcSAsim Jamshed 	struct tcp_stream *cur_stream;
395*76404edcSAsim Jamshed 	int rc;
396*76404edcSAsim Jamshed 	socket_map_t sock;
397*76404edcSAsim Jamshed 
398*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
399*76404edcSAsim Jamshed 	if (!mtcp) {
400*76404edcSAsim Jamshed 		errno = EACCES;
401*76404edcSAsim Jamshed 		goto ppeek_error;
402*76404edcSAsim Jamshed 	}
403*76404edcSAsim Jamshed 
404*76404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
405*76404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
406*76404edcSAsim Jamshed 		errno = EPERM;
407*76404edcSAsim Jamshed 		goto ppeek_error;
408*76404edcSAsim Jamshed 	}
409*76404edcSAsim Jamshed 
410*76404edcSAsim Jamshed 	/* check if the socket is monitor stream */
411*76404edcSAsim Jamshed 	sock = &mtcp->msmap[msock];
412*76404edcSAsim Jamshed 	if (sock->socktype != MOS_SOCK_MONITOR_STREAM_ACTIVE) {
413*76404edcSAsim Jamshed 		TRACE_DBG("Invalid socket type!\n");
414*76404edcSAsim Jamshed 		errno = ESOCKTNOSUPPORT;
415*76404edcSAsim Jamshed 		goto ppeek_error;
416*76404edcSAsim Jamshed 	}
417*76404edcSAsim Jamshed 
418*76404edcSAsim Jamshed 	if (side != MOS_SIDE_CLI && side != MOS_SIDE_SVR) {
419*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid side requested!\n");
420*76404edcSAsim Jamshed 		exit(EXIT_FAILURE);
421*76404edcSAsim Jamshed 		return -1;
422*76404edcSAsim Jamshed 	}
423*76404edcSAsim Jamshed 
424*76404edcSAsim Jamshed 	struct tcp_stream *mstrm = sock->monitor_stream->stream;
425*76404edcSAsim Jamshed 	cur_stream = (side == mstrm->side) ? mstrm : mstrm->pair_stream;
426*76404edcSAsim Jamshed 
427*76404edcSAsim Jamshed 	if (!cur_stream || !cur_stream->buffer_mgmt) {
428*76404edcSAsim Jamshed 		TRACE_DBG("Stream is either NULL or ring buffer is not managed!!\n");
429*76404edcSAsim Jamshed 		errno = EACCES;
430*76404edcSAsim Jamshed 		goto ppeek_error;
431*76404edcSAsim Jamshed 	}
432*76404edcSAsim Jamshed 
433*76404edcSAsim Jamshed 	rc = 0;
434*76404edcSAsim Jamshed 	/* Check if the read was not just due to syn-ack recv */
435*76404edcSAsim Jamshed 	if (cur_stream->rcvvar != NULL &&
436*76404edcSAsim Jamshed 	    cur_stream->rcvvar->rcvbuf != NULL) {
437*76404edcSAsim Jamshed #ifdef NEWRB
438*76404edcSAsim Jamshed 		tcprb_t *rcvbuf = cur_stream->rcvvar->rcvbuf;
439*76404edcSAsim Jamshed #ifndef NEWPPEEK
440*76404edcSAsim Jamshed 		loff_t off = seq2loff(rcvbuf, seq_num, cur_stream->rcvvar->irs + 1);
441*76404edcSAsim Jamshed #endif
442*76404edcSAsim Jamshed 		return tcprb_ppeek(rcvbuf, (uint8_t *)buf, count, off);
443*76404edcSAsim Jamshed #else
444*76404edcSAsim Jamshed 		struct tcp_ring_buffer *rcvbuf = cur_stream->rcvvar->rcvbuf;
445*76404edcSAsim Jamshed 
446*76404edcSAsim Jamshed 		/* Next calculate the lowest sequence number in ring buffer */
447*76404edcSAsim Jamshed 		off_t lwst_seq_num = 0;
448*76404edcSAsim Jamshed 		if (rcvbuf->monitor_read_tail_offset == 0) {
449*76404edcSAsim Jamshed 			lwst_seq_num = rcvbuf->head_seq - rcvbuf->head_offset;
450*76404edcSAsim Jamshed 		}
451*76404edcSAsim Jamshed 		else {
452*76404edcSAsim Jamshed 			lwst_seq_num = rcvbuf->head_seq -
453*76404edcSAsim Jamshed 				(rcvbuf->head_offset +
454*76404edcSAsim Jamshed 				 rcvbuf->monitor_read_tail_offset -
455*76404edcSAsim Jamshed 				 rcvbuf->tail_offset);
456*76404edcSAsim Jamshed 		}
457*76404edcSAsim Jamshed 		/*
458*76404edcSAsim Jamshed 		 * if the requested payload is within the frags then
459*76404edcSAsim Jamshed 		 * copy the payload from frags (if possible)
460*76404edcSAsim Jamshed 		 */
461*76404edcSAsim Jamshed 		if (TCP_SEQ_BETWEEN(seq_num, rcvbuf->head_seq + rcvbuf->merged_len,
462*76404edcSAsim Jamshed 							rcvbuf->head_seq + rcvbuf->last_len)) {
463*76404edcSAsim Jamshed 			/* if no bytes copied... then return error */
464*76404edcSAsim Jamshed 			if ((rc=ExtractPayloadFromFrags(rcvbuf, buf, count, seq_num)) == 0) {
465*76404edcSAsim Jamshed 				errno = EAGAIN;
466*76404edcSAsim Jamshed 				goto ppeek_error;
467*76404edcSAsim Jamshed 			} else {
468*76404edcSAsim Jamshed 				/* set count to the number of bytes actually copied */
469*76404edcSAsim Jamshed 				count = rc;
470*76404edcSAsim Jamshed 				/* function was a success.. record it! */
471*76404edcSAsim Jamshed 				//rc = 0;
472*76404edcSAsim Jamshed 			}
473*76404edcSAsim Jamshed 		} else if (TCP_SEQ_BETWEEN(seq_num, lwst_seq_num, rcvbuf->head_seq + rcvbuf->merged_len)) {
474*76404edcSAsim Jamshed 			/*
475*76404edcSAsim Jamshed 			 * else if the requested payload is on or before
476*76404edcSAsim Jamshed 			 * the received data
477*76404edcSAsim Jamshed 			 */
478*76404edcSAsim Jamshed 
479*76404edcSAsim Jamshed 			/* first go back to the starting offset */
480*76404edcSAsim Jamshed 			int cpbytesleft;
481*76404edcSAsim Jamshed 			off_t start;
482*76404edcSAsim Jamshed 			int distance;
483*76404edcSAsim Jamshed 
484*76404edcSAsim Jamshed 			if (lwst_seq_num > seq_num) {
485*76404edcSAsim Jamshed 				errno = EAGAIN;
486*76404edcSAsim Jamshed 				goto ppeek_error;
487*76404edcSAsim Jamshed 			} else
488*76404edcSAsim Jamshed 				lwst_seq_num = seq_num;
489*76404edcSAsim Jamshed 
490*76404edcSAsim Jamshed 			start = 0;
491*76404edcSAsim Jamshed 			distance = rcvbuf->head_seq - lwst_seq_num;
492*76404edcSAsim Jamshed 			cpbytesleft = count;
493*76404edcSAsim Jamshed 
494*76404edcSAsim Jamshed 			/* if the distance is longer than the head_offset (needs a wrap-around) */
495*76404edcSAsim Jamshed 			if (distance > rcvbuf->head_offset) {
496*76404edcSAsim Jamshed 				/* first calculate the start offset */
497*76404edcSAsim Jamshed 				start = rcvbuf->monitor_read_tail_offset - (distance - rcvbuf->head_offset);
498*76404edcSAsim Jamshed 				/* get the bytes copy value for 1st part */
499*76404edcSAsim Jamshed 				cpbytesleft = count - MIN(rcvbuf->monitor_read_tail_offset - start, count);
500*76404edcSAsim Jamshed 				/* do the memcpy */
501*76404edcSAsim Jamshed 				memcpy(buf, rcvbuf->data + start,
502*76404edcSAsim Jamshed 				       MIN(rcvbuf->monitor_read_tail_offset - start, count));
503*76404edcSAsim Jamshed 				if (cpbytesleft == 0) {
504*76404edcSAsim Jamshed 					rc = 0;
505*76404edcSAsim Jamshed 				} else {
506*76404edcSAsim Jamshed 					/* do the 2nd memcpy */
507*76404edcSAsim Jamshed 					memcpy(buf + rcvbuf->monitor_read_tail_offset - start,
508*76404edcSAsim Jamshed 					       rcvbuf->data,
509*76404edcSAsim Jamshed 					       MIN(distance - (rcvbuf->monitor_read_tail_offset - start),
510*76404edcSAsim Jamshed 							   cpbytesleft));
511*76404edcSAsim Jamshed 					cpbytesleft = cpbytesleft -
512*76404edcSAsim Jamshed 						MIN(distance - (rcvbuf->monitor_read_tail_offset - start),
513*76404edcSAsim Jamshed 						    cpbytesleft);
514*76404edcSAsim Jamshed 					count = count - cpbytesleft;
515*76404edcSAsim Jamshed 				}
516*76404edcSAsim Jamshed 			} else { /* if the distance is shorter */
517*76404edcSAsim Jamshed 				start = rcvbuf->head_offset - distance;
518*76404edcSAsim Jamshed 				count = MIN(distance, count);
519*76404edcSAsim Jamshed 				memcpy(buf, rcvbuf->data + start, MIN(distance, count));
520*76404edcSAsim Jamshed 			}
521*76404edcSAsim Jamshed 			rc = count;
522*76404edcSAsim Jamshed 		} else {
523*76404edcSAsim Jamshed 			errno = ERANGE;
524*76404edcSAsim Jamshed 			goto ppeek_error;
525*76404edcSAsim Jamshed 		}
526*76404edcSAsim Jamshed #endif
527*76404edcSAsim Jamshed 	} else {
528*76404edcSAsim Jamshed 		errno = EPERM;
529*76404edcSAsim Jamshed 		goto ppeek_error;
530*76404edcSAsim Jamshed 	}
531*76404edcSAsim Jamshed 
532*76404edcSAsim Jamshed 	return rc;
533*76404edcSAsim Jamshed 
534*76404edcSAsim Jamshed  ppeek_error:
535*76404edcSAsim Jamshed 	return -1;
536*76404edcSAsim Jamshed }
537*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
538*76404edcSAsim Jamshed #ifdef MTCP_CB_GETCURPKT_CREATE_COPY
539*76404edcSAsim Jamshed static __thread unsigned char local_frame[ETHERNET_FRAME_LEN];
540*76404edcSAsim Jamshed inline struct pkt_info *
541*76404edcSAsim Jamshed ClonePacketCtx(struct pkt_info *to, unsigned char *frame, struct pkt_ctx *from)
542*76404edcSAsim Jamshed {
543*76404edcSAsim Jamshed 	/* only memcpy till the last field before ethh */
544*76404edcSAsim Jamshed 	/* memcpy(to, from, PCTX_COPY_LEN); */
545*76404edcSAsim Jamshed 	memcpy(to, &(from->p), PKT_INFO_LEN);
546*76404edcSAsim Jamshed 	/* memcpy the entire ethernet frame */
547*76404edcSAsim Jamshed 	assert(from);
548*76404edcSAsim Jamshed 	assert(from->p.eth_len > 0);
549*76404edcSAsim Jamshed 	assert(from->p.eth_len <= ETHERNET_FRAME_LEN);
550*76404edcSAsim Jamshed 	memcpy(frame, from->p.ethh, from->p.eth_len);
551*76404edcSAsim Jamshed 	/* set iph */
552*76404edcSAsim Jamshed 	to->ethh = (struct ethhdr *)frame;
553*76404edcSAsim Jamshed 	/* set iph */
554*76404edcSAsim Jamshed 	to->iph = from->p.iph ?
555*76404edcSAsim Jamshed 		(struct iphdr *)((uint8_t *)(frame + ETHERNET_HEADER_LEN)) : NULL;
556*76404edcSAsim Jamshed 	/* set tcph */
557*76404edcSAsim Jamshed 	to->tcph = from->p.tcph ?
558*76404edcSAsim Jamshed 		(struct tcphdr *)(((uint8_t *)(to->iph)) + (to->iph->ihl<<2)) : NULL;
559*76404edcSAsim Jamshed 	/* set payload */
560*76404edcSAsim Jamshed 	to->payload = from->p.tcph ?
561*76404edcSAsim Jamshed 		((uint8_t *)(to->tcph) + (to->tcph->doff<<2)) : NULL;
562*76404edcSAsim Jamshed 	return to;
563*76404edcSAsim Jamshed }
564*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
565*76404edcSAsim Jamshed int
566*76404edcSAsim Jamshed mtcp_getlastpkt(mctx_t mctx, int sock, int side, struct pkt_info *pkt)
567*76404edcSAsim Jamshed {
568*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
569*76404edcSAsim Jamshed 	socket_map_t socket;
570*76404edcSAsim Jamshed 	struct tcp_stream *cur_stream;
571*76404edcSAsim Jamshed 	struct pkt_ctx *cur_pkt_ctx;
572*76404edcSAsim Jamshed 
573*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
574*76404edcSAsim Jamshed 	if (!mtcp) {
575*76404edcSAsim Jamshed 		errno = EACCES;
576*76404edcSAsim Jamshed 		return -1;
577*76404edcSAsim Jamshed 	}
578*76404edcSAsim Jamshed 
579*76404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
580*76404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
581*76404edcSAsim Jamshed 		errno = EPERM;
582*76404edcSAsim Jamshed 		return -1;
583*76404edcSAsim Jamshed 	}
584*76404edcSAsim Jamshed 
585*76404edcSAsim Jamshed 	/* check if the socket is monitor stream */
586*76404edcSAsim Jamshed 	socket = &mtcp->msmap[sock];
587*76404edcSAsim Jamshed 
588*76404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE) {
589*76404edcSAsim Jamshed 		if (side != MOS_SIDE_CLI && side != MOS_SIDE_SVR) {
590*76404edcSAsim Jamshed 			TRACE_ERROR("Invalid side requested!\n");
591*76404edcSAsim Jamshed 			exit(EXIT_FAILURE);
592*76404edcSAsim Jamshed 			return -1;
593*76404edcSAsim Jamshed 		}
594*76404edcSAsim Jamshed 
595*76404edcSAsim Jamshed 		struct tcp_stream *mstrm = socket->monitor_stream->stream;
596*76404edcSAsim Jamshed 		cur_stream = (side == mstrm->side) ? mstrm : mstrm->pair_stream;
597*76404edcSAsim Jamshed 
598*76404edcSAsim Jamshed 		cur_pkt_ctx = &cur_stream->last_pctx;
599*76404edcSAsim Jamshed 		if (!cur_pkt_ctx->p.ethh) {
600*76404edcSAsim Jamshed 			errno = ENODATA;
601*76404edcSAsim Jamshed 			return -1;
602*76404edcSAsim Jamshed 		}
603*76404edcSAsim Jamshed 	} else if (socket->socktype == MOS_SOCK_MONITOR_RAW) {
604*76404edcSAsim Jamshed 		cur_pkt_ctx = mtcp->pctx;
605*76404edcSAsim Jamshed 	} else if (socket->socktype == MOS_SOCK_MONITOR_STREAM) {
606*76404edcSAsim Jamshed 		/*
607*76404edcSAsim Jamshed 		 * if it is a monitor socket, then this means that
608*76404edcSAsim Jamshed 		 * this is a request for an orphan tcp packet
609*76404edcSAsim Jamshed 		 */
610*76404edcSAsim Jamshed 		cur_pkt_ctx = mtcp->pctx;
611*76404edcSAsim Jamshed 	} else {
612*76404edcSAsim Jamshed 		TRACE_DBG("Invalid socket type!\n");
613*76404edcSAsim Jamshed 		errno = EBADF;
614*76404edcSAsim Jamshed 		return -1;
615*76404edcSAsim Jamshed 	}
616*76404edcSAsim Jamshed 
617*76404edcSAsim Jamshed 	ClonePacketCtx(pkt, local_frame, cur_pkt_ctx);
618*76404edcSAsim Jamshed 	return 0;
619*76404edcSAsim Jamshed }
620*76404edcSAsim Jamshed #else
621*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
622*76404edcSAsim Jamshed int
623*76404edcSAsim Jamshed mtcp_getlastpkt(mctx_t mctx, int sock, int side, struct pkt_ctx **pctx)
624*76404edcSAsim Jamshed {
625*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
626*76404edcSAsim Jamshed 
627*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
628*76404edcSAsim Jamshed 	if (!mtcp) {
629*76404edcSAsim Jamshed 		errno = EACCES;
630*76404edcSAsim Jamshed 		return -1;
631*76404edcSAsim Jamshed 	}
632*76404edcSAsim Jamshed 
633*76404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
634*76404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
635*76404edcSAsim Jamshed 		errno = EPERM;
636*76404edcSAsim Jamshed 		return -1;
637*76404edcSAsim Jamshed 	}
638*76404edcSAsim Jamshed 	/* just pass direct pointer */
639*76404edcSAsim Jamshed 	*pctx = mtcp->pctx;
640*76404edcSAsim Jamshed 
641*76404edcSAsim Jamshed 	return 0;
642*76404edcSAsim Jamshed }
643*76404edcSAsim Jamshed #endif
644*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
645*76404edcSAsim Jamshed /** Disable events from the monitor stream socket
646*76404edcSAsim Jamshed  * @param [in] mtcp: mtcp_manager
647*76404edcSAsim Jamshed  * @param [in] sock: socket
648*76404edcSAsim Jamshed  *
649*76404edcSAsim Jamshed  * returns 0 on success, -1 on failure
650*76404edcSAsim Jamshed  *
651*76404edcSAsim Jamshed  * This is used for flow management based monitoring sockets
652*76404edcSAsim Jamshed  */
653*76404edcSAsim Jamshed int
654*76404edcSAsim Jamshed RemoveMonitorEvents(mtcp_manager_t mtcp, socket_map_t socket, int side)
655*76404edcSAsim Jamshed {
656*76404edcSAsim Jamshed 	struct mon_stream *mstream;
657*76404edcSAsim Jamshed 	struct mon_listener *mlistener;
658*76404edcSAsim Jamshed 
659*76404edcSAsim Jamshed 	if (mtcp == NULL) {
660*76404edcSAsim Jamshed 		TRACE_DBG("mtcp is not defined!!!\n");
661*76404edcSAsim Jamshed 		errno = EACCES;
662*76404edcSAsim Jamshed 		return -1;
663*76404edcSAsim Jamshed 	}
664*76404edcSAsim Jamshed 
665*76404edcSAsim Jamshed 	switch (socket->socktype) {
666*76404edcSAsim Jamshed 	case MOS_SOCK_MONITOR_STREAM_ACTIVE:
667*76404edcSAsim Jamshed 		mstream = socket->monitor_stream;
668*76404edcSAsim Jamshed 		if (mstream == NULL) {
669*76404edcSAsim Jamshed 			TRACE_ERROR("Mon Stream does not exist!\n");
670*76404edcSAsim Jamshed 			/* exit(-1); */
671*76404edcSAsim Jamshed 			errno = ENODATA;
672*76404edcSAsim Jamshed 			return -1;
673*76404edcSAsim Jamshed 		}
674*76404edcSAsim Jamshed 
675*76404edcSAsim Jamshed 		if (side == MOS_SIDE_SVR) mstream->server_mon = 0;
676*76404edcSAsim Jamshed 		else if (side == MOS_SIDE_CLI) mstream->client_mon = 0;
677*76404edcSAsim Jamshed 
678*76404edcSAsim Jamshed 		if (mstream->server_mon == 0 && mstream->client_mon == 0) {
679*76404edcSAsim Jamshed #ifdef NEWEV
680*76404edcSAsim Jamshed 			/*
681*76404edcSAsim Jamshed 			 * if stree_dontcare is NULL, then we know that all
682*76404edcSAsim Jamshed 			 * events have already been disabled
683*76404edcSAsim Jamshed 			 */
684*76404edcSAsim Jamshed 			if (mstream->stree_pre_rcv != NULL) {
685*76404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mstream->stree_dontcare);
686*76404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mstream->stree_pre_rcv);
687*76404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mstream->stree_post_snd);
688*76404edcSAsim Jamshed 
689*76404edcSAsim Jamshed 				mstream->stree_dontcare = NULL;
690*76404edcSAsim Jamshed 				mstream->stree_pre_rcv = NULL;
691*76404edcSAsim Jamshed 				mstream->stree_post_snd = NULL;
692*76404edcSAsim Jamshed 			}
693*76404edcSAsim Jamshed #else
694*76404edcSAsim Jamshed 			/* no error checking over here..
695*76404edcSAsim Jamshed 			 * but its okay.. this code is
696*76404edcSAsim Jamshed 			 * deprecated
697*76404edcSAsim Jamshed 			 */
698*76404edcSAsim Jamshed 			CleanupEvP(&mstream->dontcare_evp);
699*76404edcSAsim Jamshed 			CleanupEvP(&mstream->pre_tcp_evp);
700*76404edcSAsim Jamshed 			CleanupEvP(&mstream->post_tcp_evp);
701*76404edcSAsim Jamshed #endif
702*76404edcSAsim Jamshed 		}
703*76404edcSAsim Jamshed 		break;
704*76404edcSAsim Jamshed 	case MOS_SOCK_MONITOR_STREAM:
705*76404edcSAsim Jamshed 		mlistener = socket->monitor_listener;
706*76404edcSAsim Jamshed 		if (mlistener == NULL) {
707*76404edcSAsim Jamshed 			TRACE_ERROR("Mon listener does not exist!\n");
708*76404edcSAsim Jamshed 			errno = ENODATA;
709*76404edcSAsim Jamshed 			return -1;
710*76404edcSAsim Jamshed 		}
711*76404edcSAsim Jamshed 
712*76404edcSAsim Jamshed 		if (side == MOS_SIDE_SVR) mlistener->server_mon = 0;
713*76404edcSAsim Jamshed 		else if (side == MOS_SIDE_CLI) mlistener->client_mon = 0;
714*76404edcSAsim Jamshed 
715*76404edcSAsim Jamshed 		if (mlistener->server_mon == 0 && mlistener->client_mon == 0) {
716*76404edcSAsim Jamshed #ifdef NEWEV
717*76404edcSAsim Jamshed 			/*
718*76404edcSAsim Jamshed 			 * if stree_dontcare is NULL, then we know that all
719*76404edcSAsim Jamshed 			 * events have already been disabled
720*76404edcSAsim Jamshed 			 */
721*76404edcSAsim Jamshed 			if (mlistener->stree_pre_rcv != NULL) {
722*76404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mlistener->stree_dontcare);
723*76404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mlistener->stree_pre_rcv);
724*76404edcSAsim Jamshed 				stree_dec_ref(mtcp->ev_store, mlistener->stree_post_snd);
725*76404edcSAsim Jamshed 
726*76404edcSAsim Jamshed 				mlistener->stree_dontcare = NULL;
727*76404edcSAsim Jamshed 				mlistener->stree_pre_rcv = NULL;
728*76404edcSAsim Jamshed 				mlistener->stree_post_snd = NULL;
729*76404edcSAsim Jamshed 			}
730*76404edcSAsim Jamshed #else
731*76404edcSAsim Jamshed 			/* no error checking over here..
732*76404edcSAsim Jamshed 			 * but its okay.. this code is
733*76404edcSAsim Jamshed 			 * deprecated
734*76404edcSAsim Jamshed 			 */
735*76404edcSAsim Jamshed 			CleanupEvB(mtcp, &mlistener->dontcare_evb);
736*76404edcSAsim Jamshed 			CleanupEvB(mtcp, &mlistener->pre_tcp_evb);
737*76404edcSAsim Jamshed 			CleanupEvB(mtcp, &mlistener->post_tcp_evb);
738*76404edcSAsim Jamshed #endif
739*76404edcSAsim Jamshed 		}
740*76404edcSAsim Jamshed 		break;
741*76404edcSAsim Jamshed 	default:
742*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid socket type!\n");
743*76404edcSAsim Jamshed 	}
744*76404edcSAsim Jamshed 
745*76404edcSAsim Jamshed 	return 0;
746*76404edcSAsim Jamshed }
747*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
748*76404edcSAsim Jamshed /**
749*76404edcSAsim Jamshed  * Disable monitoring based on side variable.
750*76404edcSAsim Jamshed  */
751*76404edcSAsim Jamshed int
752*76404edcSAsim Jamshed mtcp_cb_stop(mctx_t mctx, int sock, int side)
753*76404edcSAsim Jamshed {
754*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
755*76404edcSAsim Jamshed 	socket_map_t socket;
756*76404edcSAsim Jamshed 	struct tcp_stream *stream;
757*76404edcSAsim Jamshed 	struct socket_map *walk;
758*76404edcSAsim Jamshed 	uint8_t mgmt;
759*76404edcSAsim Jamshed 
760*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
761*76404edcSAsim Jamshed 	if (!mtcp) {
762*76404edcSAsim Jamshed 		errno = EACCES;
763*76404edcSAsim Jamshed 		return -1;
764*76404edcSAsim Jamshed 	}
765*76404edcSAsim Jamshed 
766*76404edcSAsim Jamshed 	socket = &mtcp->msmap[sock];
767*76404edcSAsim Jamshed 
768*76404edcSAsim Jamshed 	/* works for both monitor listener and stream sockets */
769*76404edcSAsim Jamshed 	RemoveMonitorEvents(mtcp, socket, side);
770*76404edcSAsim Jamshed 
771*76404edcSAsim Jamshed 	/* passive monitoring socket is not connected to any stream */
772*76404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM)
773*76404edcSAsim Jamshed 		return 0;
774*76404edcSAsim Jamshed 
775*76404edcSAsim Jamshed 	if (side == MOS_SIDE_CLI) {
776*76404edcSAsim Jamshed 		/* see if the associated stream requires monitoring any more */
777*76404edcSAsim Jamshed 		stream = (socket->monitor_stream->stream->side == MOS_SIDE_CLI) ?
778*76404edcSAsim Jamshed 			socket->monitor_stream->stream :
779*76404edcSAsim Jamshed 			socket->monitor_stream->stream->pair_stream;
780*76404edcSAsim Jamshed 
781*76404edcSAsim Jamshed 		mgmt = 0;
782*76404edcSAsim Jamshed 		SOCKQ_FOREACH_START(walk, &stream->msocks) {
783*76404edcSAsim Jamshed 			if (walk->monitor_stream->client_mon == 1) {
784*76404edcSAsim Jamshed 				mgmt = 1;
785*76404edcSAsim Jamshed 				break;
786*76404edcSAsim Jamshed 			}
787*76404edcSAsim Jamshed 		} SOCKQ_FOREACH_END;
788*76404edcSAsim Jamshed 		/* if all streams have mgmt off, then tag the stream for destruction */
789*76404edcSAsim Jamshed 		if (mgmt == 0) {
790*76404edcSAsim Jamshed 			stream = (socket->monitor_stream->stream->side == MOS_SIDE_CLI) ?
791*76404edcSAsim Jamshed 				socket->monitor_stream->stream :
792*76404edcSAsim Jamshed 				socket->monitor_stream->stream->pair_stream;
793*76404edcSAsim Jamshed 			stream->status_mgmt = 0;
794*76404edcSAsim Jamshed 		}
795*76404edcSAsim Jamshed 	}
796*76404edcSAsim Jamshed 
797*76404edcSAsim Jamshed 	if (side == MOS_SIDE_SVR) {
798*76404edcSAsim Jamshed 		/* see if the associated stream requires monitoring any more */
799*76404edcSAsim Jamshed 		stream = (socket->monitor_stream->stream->side == MOS_SIDE_SVR) ?
800*76404edcSAsim Jamshed 			socket->monitor_stream->stream :
801*76404edcSAsim Jamshed 			socket->monitor_stream->stream->pair_stream;
802*76404edcSAsim Jamshed 		mgmt = 0;
803*76404edcSAsim Jamshed 		SOCKQ_FOREACH_START(walk, &stream->msocks) {
804*76404edcSAsim Jamshed 			if (walk->monitor_stream->server_mon == 1) {
805*76404edcSAsim Jamshed 				mgmt = 1;
806*76404edcSAsim Jamshed 				break;
807*76404edcSAsim Jamshed 			}
808*76404edcSAsim Jamshed 		} SOCKQ_FOREACH_END;
809*76404edcSAsim Jamshed 		/* if all streams have mgmt off, then tag the stream for destruction */
810*76404edcSAsim Jamshed 		if (mgmt == 0) {
811*76404edcSAsim Jamshed 			stream = (socket->monitor_stream->stream->side == MOS_SIDE_SVR) ?
812*76404edcSAsim Jamshed 				socket->monitor_stream->stream :
813*76404edcSAsim Jamshed 				socket->monitor_stream->stream->pair_stream;
814*76404edcSAsim Jamshed 			stream->status_mgmt = 0;
815*76404edcSAsim Jamshed 		}
816*76404edcSAsim Jamshed 	}
817*76404edcSAsim Jamshed 
818*76404edcSAsim Jamshed 	return 0;
819*76404edcSAsim Jamshed }
820*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
821*76404edcSAsim Jamshed /**
822*76404edcSAsim Jamshed  * send a RST packet to the TCP stream (uni-directional)
823*76404edcSAsim Jamshed  */
824*76404edcSAsim Jamshed static inline void
825*76404edcSAsim Jamshed SendRSTPacketStandalone(mtcp_manager_t mtcp, struct tcp_stream *stream) {
826*76404edcSAsim Jamshed 	SendTCPPacketStandalone(mtcp,
827*76404edcSAsim Jamshed 				stream->saddr, stream->sport, stream->daddr, stream->dport,
828*76404edcSAsim Jamshed 				stream->snd_nxt, stream->rcv_nxt, 0, TCP_FLAG_RST | TCP_FLAG_ACK,
829*76404edcSAsim Jamshed 				NULL, 0, mtcp->cur_ts, 0);
830*76404edcSAsim Jamshed }
831*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
832*76404edcSAsim Jamshed /**
833*76404edcSAsim Jamshed  * Reset the connection (send RST packets to both sides)
834*76404edcSAsim Jamshed  */
835*76404edcSAsim Jamshed int
836*76404edcSAsim Jamshed mtcp_reset_conn(mctx_t mctx, int sock)
837*76404edcSAsim Jamshed {
838*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
839*76404edcSAsim Jamshed 	socket_map_t socket;
840*76404edcSAsim Jamshed 
841*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
842*76404edcSAsim Jamshed 	if (!mtcp) {
843*76404edcSAsim Jamshed 		errno = EACCES;
844*76404edcSAsim Jamshed 		return -1;
845*76404edcSAsim Jamshed 	}
846*76404edcSAsim Jamshed 
847*76404edcSAsim Jamshed 	socket = &mtcp->msmap[sock];
848*76404edcSAsim Jamshed 
849*76404edcSAsim Jamshed 	/* passive monitoring socket is not connected to any stream */
850*76404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM) {
851*76404edcSAsim Jamshed 		errno = EINVAL;
852*76404edcSAsim Jamshed 		return -1;
853*76404edcSAsim Jamshed 	}
854*76404edcSAsim Jamshed 
855*76404edcSAsim Jamshed 	/* send RST packets to the both sides */
856*76404edcSAsim Jamshed 	SendRSTPacketStandalone(mtcp, socket->monitor_stream->stream);
857*76404edcSAsim Jamshed 	SendRSTPacketStandalone(mtcp, socket->monitor_stream->stream->pair_stream);
858*76404edcSAsim Jamshed 
859*76404edcSAsim Jamshed 	return 0;
860*76404edcSAsim Jamshed }
861*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
862*76404edcSAsim Jamshed uint32_t
863*76404edcSAsim Jamshed mtcp_cb_get_ts(mctx_t mctx)
864*76404edcSAsim Jamshed {
865*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
866*76404edcSAsim Jamshed 
867*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
868*76404edcSAsim Jamshed 	if (!mtcp) {
869*76404edcSAsim Jamshed 		TRACE_DBG("Can't access MTCP manager!\n");
870*76404edcSAsim Jamshed 		errno = EACCES;
871*76404edcSAsim Jamshed 		return 0;
872*76404edcSAsim Jamshed 	}
873*76404edcSAsim Jamshed 
874*76404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
875*76404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
876*76404edcSAsim Jamshed 		errno = EPERM;
877*76404edcSAsim Jamshed 		return 0;
878*76404edcSAsim Jamshed 	}
879*76404edcSAsim Jamshed 
880*76404edcSAsim Jamshed 	return TS_TO_USEC(mtcp->cur_ts);
881*76404edcSAsim Jamshed }
882*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
883*76404edcSAsim Jamshed /* Macros related to getpeername */
884*76404edcSAsim Jamshed #define TILL_SVRADDR		offsetof(struct sockaddr_in, sin_zero)
885*76404edcSAsim Jamshed #define TILL_SVRPORT		offsetof(struct sockaddr_in, sin_addr)
886*76404edcSAsim Jamshed #define TILL_SVRFAMILY		offsetof(struct sockaddr_in, sin_port)
887*76404edcSAsim Jamshed #define TILL_CLIADDR		sizeof(struct sockaddr) + TILL_SVRADDR
888*76404edcSAsim Jamshed #define TILL_CLIPORT		sizeof(struct sockaddr) + TILL_SVRPORT
889*76404edcSAsim Jamshed #define TILL_CLIFAMILY		sizeof(struct sockaddr) + TILL_SVRFAMILY
890*76404edcSAsim Jamshed 
891*76404edcSAsim Jamshed int
892*76404edcSAsim Jamshed mtcp_getpeername(mctx_t mctx, int sockfd, struct sockaddr *saddr,
893*76404edcSAsim Jamshed 				 socklen_t *addrlen, int side)
894*76404edcSAsim Jamshed {
895*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
896*76404edcSAsim Jamshed 	socket_map_t socket;
897*76404edcSAsim Jamshed 	struct tcp_stream *stream;
898*76404edcSAsim Jamshed 	struct sockaddr_in *sin;
899*76404edcSAsim Jamshed 	int rc;
900*76404edcSAsim Jamshed 
901*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
902*76404edcSAsim Jamshed 	if (!mtcp) {
903*76404edcSAsim Jamshed 		TRACE_DBG("Can't access MTCP manager!\n");
904*76404edcSAsim Jamshed 		errno = EACCES;
905*76404edcSAsim Jamshed 		return -1;
906*76404edcSAsim Jamshed 	}
907*76404edcSAsim Jamshed 
908*76404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
909*76404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
910*76404edcSAsim Jamshed 		errno = EPERM;
911*76404edcSAsim Jamshed 		return -1;
912*76404edcSAsim Jamshed 	}
913*76404edcSAsim Jamshed 
914*76404edcSAsim Jamshed 	socket = &mtcp->msmap[sockfd];
915*76404edcSAsim Jamshed 	sin = (struct sockaddr_in *)saddr;
916*76404edcSAsim Jamshed 	rc = 0;
917*76404edcSAsim Jamshed 
918*76404edcSAsim Jamshed 	/* retrieve both streams */
919*76404edcSAsim Jamshed 	stream = socket->monitor_stream->stream;
920*76404edcSAsim Jamshed 
921*76404edcSAsim Jamshed 	if (side != stream->side)
922*76404edcSAsim Jamshed 		stream = stream->pair_stream;
923*76404edcSAsim Jamshed 
924*76404edcSAsim Jamshed 	if (stream == NULL)
925*76404edcSAsim Jamshed 		return -1;
926*76404edcSAsim Jamshed 
927*76404edcSAsim Jamshed 	/* reset to 2 * sizeof(struct sockaddr) if addrlen is too big */
928*76404edcSAsim Jamshed 	if (*addrlen > 2 * sizeof(struct sockaddr))
929*76404edcSAsim Jamshed 		*addrlen = 2 * sizeof(struct sockaddr);
930*76404edcSAsim Jamshed 
931*76404edcSAsim Jamshed 	/* according per manpage, address can be truncated */
932*76404edcSAsim Jamshed 	switch (*addrlen) {
933*76404edcSAsim Jamshed 	case (2 * sizeof(struct sockaddr)):
934*76404edcSAsim Jamshed 	case TILL_CLIADDR:
935*76404edcSAsim Jamshed 		sin[1].sin_addr.s_addr = stream->side == MOS_SIDE_SVR ?
936*76404edcSAsim Jamshed 								 stream->daddr : stream->saddr;
937*76404edcSAsim Jamshed 	case TILL_CLIPORT:
938*76404edcSAsim Jamshed 		sin[1].sin_port = stream->side == MOS_SIDE_SVR ?
939*76404edcSAsim Jamshed 						  stream->dport : stream->sport;
940*76404edcSAsim Jamshed 	case TILL_CLIFAMILY:
941*76404edcSAsim Jamshed 		sin[1].sin_family = AF_INET;
942*76404edcSAsim Jamshed 	case (sizeof(struct sockaddr)):
943*76404edcSAsim Jamshed 	case TILL_SVRADDR:
944*76404edcSAsim Jamshed 		sin->sin_addr.s_addr = stream->side == MOS_SIDE_SVR ?
945*76404edcSAsim Jamshed 							   stream->saddr : stream->daddr;
946*76404edcSAsim Jamshed 	case TILL_SVRPORT:
947*76404edcSAsim Jamshed 		sin->sin_port = stream->side == MOS_SIDE_SVR ?
948*76404edcSAsim Jamshed 						stream->sport : stream->dport;
949*76404edcSAsim Jamshed 	case TILL_SVRFAMILY:
950*76404edcSAsim Jamshed 		sin->sin_family = AF_INET;
951*76404edcSAsim Jamshed 		break;
952*76404edcSAsim Jamshed 	default:
953*76404edcSAsim Jamshed 		rc = -1;
954*76404edcSAsim Jamshed 		*addrlen = 0xFFFF;
955*76404edcSAsim Jamshed 	}
956*76404edcSAsim Jamshed 
957*76404edcSAsim Jamshed 	return rc;
958*76404edcSAsim Jamshed }
959*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
960*76404edcSAsim Jamshed int
961*76404edcSAsim Jamshed mtcp_setlastpkt(mctx_t mctx, int sock, int side, off_t offset,
962*76404edcSAsim Jamshed 		byte *data, uint16_t datalen, int option)
963*76404edcSAsim Jamshed {
964*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
965*76404edcSAsim Jamshed 	struct pkt_ctx *cur_pkt_ctx;
966*76404edcSAsim Jamshed 	struct ethhdr *ethh;
967*76404edcSAsim Jamshed 	struct iphdr *iph;
968*76404edcSAsim Jamshed 	struct tcphdr *tcph;
969*76404edcSAsim Jamshed 	unsigned char *payload;
970*76404edcSAsim Jamshed 
971*76404edcSAsim Jamshed #if 0
972*76404edcSAsim Jamshed 	socket_map_t socket;
973*76404edcSAsim Jamshed 	struct tcp_stream *cur_stream;
974*76404edcSAsim Jamshed #endif
975*76404edcSAsim Jamshed 
976*76404edcSAsim Jamshed 	/* checking if mtcp is valid */
977*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
978*76404edcSAsim Jamshed 	if (!mtcp) {
979*76404edcSAsim Jamshed 		errno = EACCES;
980*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid mtcp!\n");
981*76404edcSAsim Jamshed 		return -1;
982*76404edcSAsim Jamshed 	}
983*76404edcSAsim Jamshed 
984*76404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
985*76404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
986*76404edcSAsim Jamshed 		errno = EPERM;
987*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid thread id!\n");
988*76404edcSAsim Jamshed 		return -1;
989*76404edcSAsim Jamshed 	}
990*76404edcSAsim Jamshed 
991*76404edcSAsim Jamshed #if 0
992*76404edcSAsim Jamshed 	/* check if the socket is monitor stream */
993*76404edcSAsim Jamshed 	socket = &mtcp->msmap[sock];
994*76404edcSAsim Jamshed 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE) {
995*76404edcSAsim Jamshed 		if (side != MOS_SIDE_CLI && side != MOS_SIDE_SVR) {
996*76404edcSAsim Jamshed 			TRACE_ERROR("Invalid side requested!\n");
997*76404edcSAsim Jamshed 			exit(EXIT_FAILURE);
998*76404edcSAsim Jamshed 			return -1;
999*76404edcSAsim Jamshed 		}
1000*76404edcSAsim Jamshed 
1001*76404edcSAsim Jamshed 		struct tcp_stream *mstrm = socket->monitor_stream->stream;
1002*76404edcSAsim Jamshed 		cur_stream = (side == mstrm->side) ? mstrm : mstrm->pair_stream;
1003*76404edcSAsim Jamshed 
1004*76404edcSAsim Jamshed 		if (!cur_stream->allow_pkt_modification)
1005*76404edcSAsim Jamshed 			return -1;
1006*76404edcSAsim Jamshed 	} else if (socket->socktype != MOS_SOCK_MONITOR_RAW) {
1007*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid socket type!\n");
1008*76404edcSAsim Jamshed 		exit(EXIT_FAILURE);
1009*76404edcSAsim Jamshed 		return -1;
1010*76404edcSAsim Jamshed 	}
1011*76404edcSAsim Jamshed #endif
1012*76404edcSAsim Jamshed 
1013*76404edcSAsim Jamshed 	/* see if cur_pkt_ctx is valid */
1014*76404edcSAsim Jamshed 	cur_pkt_ctx = mtcp->pctx;
1015*76404edcSAsim Jamshed 	if (cur_pkt_ctx == NULL) {
1016*76404edcSAsim Jamshed 		TRACE_ERROR("pctx is NULL!\n");
1017*76404edcSAsim Jamshed 		errno = ENODATA;
1018*76404edcSAsim Jamshed 		return -1;
1019*76404edcSAsim Jamshed 	}
1020*76404edcSAsim Jamshed 
1021*76404edcSAsim Jamshed 	/* check if offset is valid */
1022*76404edcSAsim Jamshed 	if (offset < 0) {
1023*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid offset position!\n");
1024*76404edcSAsim Jamshed 		errno = EINVAL;
1025*76404edcSAsim Jamshed 		return -1;
1026*76404edcSAsim Jamshed 	}
1027*76404edcSAsim Jamshed 
1028*76404edcSAsim Jamshed 	if (__builtin_popcount(option & (MOS_DROP | MOS_CHOMP |
1029*76404edcSAsim Jamshed 					 MOS_INSERT | MOS_OVERWRITE)) != 1) {
1030*76404edcSAsim Jamshed 		TRACE_ERROR("mtcp_setlastpkt() function only allows one of "
1031*76404edcSAsim Jamshed 			    "(MOS_DROP | MOS_CHOMP | MOS_INSERT | MOS_OVERWRITE) "
1032*76404edcSAsim Jamshed 			    "to be set at a time.\n");
1033*76404edcSAsim Jamshed 		errno = EAGAIN;
1034*76404edcSAsim Jamshed 		return -1;
1035*76404edcSAsim Jamshed 	}
1036*76404edcSAsim Jamshed 
1037*76404edcSAsim Jamshed 	/* drop pkt has the highest priority */
1038*76404edcSAsim Jamshed 	if (option & MOS_DROP) {
1039*76404edcSAsim Jamshed 		mtcp->pctx->forward = 0;
1040*76404edcSAsim Jamshed 		return 0;
1041*76404edcSAsim Jamshed 	} else if (option & MOS_ETH_HDR) {
1042*76404edcSAsim Jamshed 		/* validity test */
1043*76404edcSAsim Jamshed 		if ((ethh=cur_pkt_ctx->p.ethh) == NULL ||
1044*76404edcSAsim Jamshed 		    offset + datalen > sizeof(struct ethhdr)) {
1045*76404edcSAsim Jamshed 			TRACE_ERROR("Ethernet setting has gone out of bounds "
1046*76404edcSAsim Jamshed 				    "(offset: %ld, datalen: %d)\n",
1047*76404edcSAsim Jamshed 				    offset, datalen);
1048*76404edcSAsim Jamshed 			errno = EINVAL;
1049*76404edcSAsim Jamshed 			return -1;
1050*76404edcSAsim Jamshed 		}
1051*76404edcSAsim Jamshed 		if (option & MOS_CHOMP) {
1052*76404edcSAsim Jamshed 			TRACE_ERROR("Illegal call. "
1053*76404edcSAsim Jamshed 				    "Ethernet header can't be chopped down!\n");
1054*76404edcSAsim Jamshed 			errno = EACCES;
1055*76404edcSAsim Jamshed 			return -1;
1056*76404edcSAsim Jamshed 		} else if (option & MOS_INSERT) {
1057*76404edcSAsim Jamshed 			TRACE_ERROR("Illegal call. "
1058*76404edcSAsim Jamshed 				    "Ethernet header can't be extended!\n");
1059*76404edcSAsim Jamshed 			errno = EACCES;
1060*76404edcSAsim Jamshed 			return -1;
1061*76404edcSAsim Jamshed 		} else /* if (option & MOS_OVERWRITE) */ {
1062*76404edcSAsim Jamshed 			memcpy((uint8_t *)ethh + offset, data, datalen);
1063*76404edcSAsim Jamshed 		}
1064*76404edcSAsim Jamshed 		/* iph, tcph, and payload do not need to change */
1065*76404edcSAsim Jamshed 	} else if (option & MOS_IP_HDR) {
1066*76404edcSAsim Jamshed 		/* validity test */
1067*76404edcSAsim Jamshed 		if (cur_pkt_ctx->p.ethh == NULL ||
1068*76404edcSAsim Jamshed 		    cur_pkt_ctx->p.ethh->h_proto != ntohs(ETH_P_IP) ||
1069*76404edcSAsim Jamshed 		    (iph=(struct iphdr *)(cur_pkt_ctx->p.ethh + 1)) == NULL) {
1070*76404edcSAsim Jamshed 			TRACE_ERROR("ethh or iph are out of bounds\n");
1071*76404edcSAsim Jamshed 			errno = EACCES;
1072*76404edcSAsim Jamshed 			return -1;
1073*76404edcSAsim Jamshed 		}
1074*76404edcSAsim Jamshed 		if (option & MOS_OVERWRITE) {
1075*76404edcSAsim Jamshed 			if (offset + datalen > (iph->ihl<<2)) {
1076*76404edcSAsim Jamshed 				TRACE_ERROR("IP setting has gone out of bounds "
1077*76404edcSAsim Jamshed 					    "(offset: %ld, datalen: %d)\n",
1078*76404edcSAsim Jamshed 					    offset, datalen);
1079*76404edcSAsim Jamshed 				errno = EINVAL;
1080*76404edcSAsim Jamshed 				return -1;
1081*76404edcSAsim Jamshed 			}
1082*76404edcSAsim Jamshed 			memcpy((uint8_t *)iph + offset, data, datalen);
1083*76404edcSAsim Jamshed 		}
1084*76404edcSAsim Jamshed 		if (option & MOS_CHOMP) {
1085*76404edcSAsim Jamshed 			memmove((uint8_t *)iph + offset,
1086*76404edcSAsim Jamshed 				(uint8_t *)iph + offset + datalen,
1087*76404edcSAsim Jamshed 				cur_pkt_ctx->p.ip_len - offset - datalen);
1088*76404edcSAsim Jamshed 
1089*76404edcSAsim Jamshed 			/* iph does not need to change */
1090*76404edcSAsim Jamshed 			if (iph->protocol == IPPROTO_TCP) {
1091*76404edcSAsim Jamshed 				cur_pkt_ctx->p.tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2));
1092*76404edcSAsim Jamshed 				cur_pkt_ctx->p.payload = (uint8_t *)cur_pkt_ctx->p.tcph +
1093*76404edcSAsim Jamshed 					(cur_pkt_ctx->p.tcph->doff<<2);
1094*76404edcSAsim Jamshed 			} else {
1095*76404edcSAsim Jamshed 				/* reset tcph if iph does not have tcp proto */
1096*76404edcSAsim Jamshed 				cur_pkt_ctx->p.tcph = NULL;
1097*76404edcSAsim Jamshed 			}
1098*76404edcSAsim Jamshed 			/* update iph total length */
1099*76404edcSAsim Jamshed 			cur_pkt_ctx->p.ip_len = ntohs(iph->tot_len);
1100*76404edcSAsim Jamshed 			/* update eth frame length */
1101*76404edcSAsim Jamshed 			cur_pkt_ctx->p.eth_len = cur_pkt_ctx->p.ip_len + sizeof(struct ethhdr);
1102*76404edcSAsim Jamshed 		} else if (option & MOS_INSERT) {
1103*76404edcSAsim Jamshed 			memmove((uint8_t *)iph + offset + datalen,
1104*76404edcSAsim Jamshed 				(uint8_t *)iph + offset + 1,
1105*76404edcSAsim Jamshed 				cur_pkt_ctx->p.ip_len - offset);
1106*76404edcSAsim Jamshed 			memcpy((uint8_t *)iph + offset,
1107*76404edcSAsim Jamshed 			       data, datalen);
1108*76404edcSAsim Jamshed 
1109*76404edcSAsim Jamshed 			/* iph does not need to change */
1110*76404edcSAsim Jamshed 			if (iph->protocol == IPPROTO_TCP) {
1111*76404edcSAsim Jamshed 				cur_pkt_ctx->p.tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2));
1112*76404edcSAsim Jamshed 				cur_pkt_ctx->p.payload = (uint8_t *)cur_pkt_ctx->p.tcph +
1113*76404edcSAsim Jamshed 					(cur_pkt_ctx->p.tcph->doff<<2);
1114*76404edcSAsim Jamshed 			} else {
1115*76404edcSAsim Jamshed 				/* reset tcph if iph does not have tcp proto */
1116*76404edcSAsim Jamshed 				cur_pkt_ctx->p.tcph = NULL;
1117*76404edcSAsim Jamshed 			}
1118*76404edcSAsim Jamshed 			/* update iph total length */
1119*76404edcSAsim Jamshed 			cur_pkt_ctx->p.ip_len = ntohs(iph->tot_len);
1120*76404edcSAsim Jamshed 			/* update eth frame length */
1121*76404edcSAsim Jamshed 			cur_pkt_ctx->p.eth_len = cur_pkt_ctx->p.ip_len + sizeof(struct ethhdr);
1122*76404edcSAsim Jamshed 		}
1123*76404edcSAsim Jamshed 		/* can't update payloadlen because we don't know tcph->doff */
1124*76404edcSAsim Jamshed 	} else if (option & MOS_TCP_HDR) {
1125*76404edcSAsim Jamshed 		/* validity test */
1126*76404edcSAsim Jamshed 		iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1);
1127*76404edcSAsim Jamshed 		if (iph == NULL ||
1128*76404edcSAsim Jamshed 		    iph->protocol != IPPROTO_TCP ||
1129*76404edcSAsim Jamshed 		    (tcph=(struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2))) == NULL) {
1130*76404edcSAsim Jamshed 			TRACE_ERROR("TCP setting has gone out of bounds "
1131*76404edcSAsim Jamshed 				    "(offset: %ld, datalen: %d)\n",
1132*76404edcSAsim Jamshed 				    offset, datalen);
1133*76404edcSAsim Jamshed 			errno = EINVAL;
1134*76404edcSAsim Jamshed 			return -1;
1135*76404edcSAsim Jamshed 		}
1136*76404edcSAsim Jamshed 		if (option & MOS_OVERWRITE) {
1137*76404edcSAsim Jamshed 			if (offset + datalen > (tcph->doff<<2)) {
1138*76404edcSAsim Jamshed 				TRACE_ERROR("TCP setting has gone out of bounds "
1139*76404edcSAsim Jamshed 					    "(offset: %ld, datalen: %d)\n",
1140*76404edcSAsim Jamshed 					    offset, datalen);
1141*76404edcSAsim Jamshed 				errno = EINVAL;
1142*76404edcSAsim Jamshed 				return -1;
1143*76404edcSAsim Jamshed 			}
1144*76404edcSAsim Jamshed 			memcpy((uint8_t *)tcph + offset, data, datalen);
1145*76404edcSAsim Jamshed 			/* update tcp seq # */
1146*76404edcSAsim Jamshed 			cur_pkt_ctx->p.seq = ntohl(tcph->seq);
1147*76404edcSAsim Jamshed 			/* update tcp ack_seq # */
1148*76404edcSAsim Jamshed 			cur_pkt_ctx->p.ack_seq = ntohl(tcph->ack_seq);
1149*76404edcSAsim Jamshed 			/* update tcp window */
1150*76404edcSAsim Jamshed 			cur_pkt_ctx->p.window = ntohs(tcph->window);
1151*76404edcSAsim Jamshed 
1152*76404edcSAsim Jamshed 			/* 150422 dhkim TODO: seq and offset are two different form of same
1153*76404edcSAsim Jamshed 			 * variable. We also need to update the offset. */
1154*76404edcSAsim Jamshed 		}
1155*76404edcSAsim Jamshed 		if (option & MOS_CHOMP) {
1156*76404edcSAsim Jamshed 			memmove((uint8_t *)tcph + offset,
1157*76404edcSAsim Jamshed 				(uint8_t *)tcph + offset + datalen,
1158*76404edcSAsim Jamshed 				cur_pkt_ctx->p.payloadlen + (tcph->doff<<2)
1159*76404edcSAsim Jamshed 				- offset - datalen);
1160*76404edcSAsim Jamshed 			/* update payload ptr */
1161*76404edcSAsim Jamshed 			cur_pkt_ctx->p.payload = (uint8_t *)tcph + (tcph->doff<<2);
1162*76404edcSAsim Jamshed 		} else if (option & MOS_INSERT) {
1163*76404edcSAsim Jamshed 			memmove((uint8_t *)tcph + offset + datalen,
1164*76404edcSAsim Jamshed 				(uint8_t *)tcph + offset + 1,
1165*76404edcSAsim Jamshed 				cur_pkt_ctx->p.payloadlen + (tcph->doff<<2)
1166*76404edcSAsim Jamshed 				- offset);
1167*76404edcSAsim Jamshed 			memcpy((uint8_t *)tcph + offset, data, datalen);
1168*76404edcSAsim Jamshed 			/* update payload ptr */
1169*76404edcSAsim Jamshed 			cur_pkt_ctx->p.payload = (uint8_t *)tcph + (tcph->doff<<2);
1170*76404edcSAsim Jamshed 		}
1171*76404edcSAsim Jamshed 	} else if (option & MOS_TCP_PAYLOAD) {
1172*76404edcSAsim Jamshed 		iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1);
1173*76404edcSAsim Jamshed 		tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2));
1174*76404edcSAsim Jamshed 		payload = (uint8_t *)tcph + (tcph->doff<<2);
1175*76404edcSAsim Jamshed 		if (option & MOS_OVERWRITE) {
1176*76404edcSAsim Jamshed 			if (offset + datalen > ntohs(iph->tot_len) -
1177*76404edcSAsim Jamshed 			    (iph->ihl<<2) - (tcph->doff<<2)) {
1178*76404edcSAsim Jamshed 				TRACE_ERROR("Payload setting has gone out of bounds "
1179*76404edcSAsim Jamshed 					    "(offset: %ld, datalen: %d)\n",
1180*76404edcSAsim Jamshed 					    offset, datalen);
1181*76404edcSAsim Jamshed 				errno = EINVAL;
1182*76404edcSAsim Jamshed 				return -1;
1183*76404edcSAsim Jamshed 			}
1184*76404edcSAsim Jamshed 			memcpy(payload + offset, data, datalen);
1185*76404edcSAsim Jamshed 		}
1186*76404edcSAsim Jamshed 		if (option & MOS_CHOMP) {
1187*76404edcSAsim Jamshed 			memmove(payload + offset,
1188*76404edcSAsim Jamshed 				payload + offset + datalen,
1189*76404edcSAsim Jamshed 				(cur_pkt_ctx->p.payloadlen -
1190*76404edcSAsim Jamshed 				 offset - datalen));
1191*76404edcSAsim Jamshed 			/* update payload length */
1192*76404edcSAsim Jamshed 			cur_pkt_ctx->p.payloadlen = cur_pkt_ctx->p.ip_len -
1193*76404edcSAsim Jamshed 				(tcph->doff<<2) - (iph->ihl<<2);
1194*76404edcSAsim Jamshed 		} else if (option & MOS_INSERT) {
1195*76404edcSAsim Jamshed 			memmove(payload + offset + datalen,
1196*76404edcSAsim Jamshed 				payload + offset + 1,
1197*76404edcSAsim Jamshed 				cur_pkt_ctx->p.payloadlen - offset);
1198*76404edcSAsim Jamshed 			memcpy(payload + offset, data, datalen);
1199*76404edcSAsim Jamshed 			cur_pkt_ctx->p.payloadlen = cur_pkt_ctx->p.ip_len -
1200*76404edcSAsim Jamshed 				(tcph->doff<<2) - (iph->ihl<<2);
1201*76404edcSAsim Jamshed 		}
1202*76404edcSAsim Jamshed 	} else {
1203*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid option!\n");
1204*76404edcSAsim Jamshed 		errno = EINVAL;
1205*76404edcSAsim Jamshed 		return -1;
1206*76404edcSAsim Jamshed 	}
1207*76404edcSAsim Jamshed 
1208*76404edcSAsim Jamshed 	/* update ip checksum */
1209*76404edcSAsim Jamshed 	if (option & MOS_UPDATE_IP_CHKSUM) {
1210*76404edcSAsim Jamshed 		iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1);
1211*76404edcSAsim Jamshed 		iph->check = 0;
1212*76404edcSAsim Jamshed 		iph->check = ip_fast_csum(iph, iph->ihl);
1213*76404edcSAsim Jamshed 	}
1214*76404edcSAsim Jamshed 
1215*76404edcSAsim Jamshed 	/* update tcp checksum */
1216*76404edcSAsim Jamshed 	if (option & MOS_UPDATE_TCP_CHKSUM) {
1217*76404edcSAsim Jamshed 		iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1);
1218*76404edcSAsim Jamshed 		tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2));
1219*76404edcSAsim Jamshed 		tcph->check = 0;
1220*76404edcSAsim Jamshed 		tcph->check = TCPCalcChecksum((uint16_t *)tcph,
1221*76404edcSAsim Jamshed 					      ntohs(iph->tot_len) - (iph->ihl<<2),
1222*76404edcSAsim Jamshed 					      iph->saddr, iph->daddr);
1223*76404edcSAsim Jamshed 	}
1224*76404edcSAsim Jamshed 	return 0;
1225*76404edcSAsim Jamshed }
1226*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1227*76404edcSAsim Jamshed #if 0
1228*76404edcSAsim Jamshed inline int
1229*76404edcSAsim Jamshed mtcp_cb_updatecurpkt(mctx_t mctx, off_t offset, unsigned char *data,
1230*76404edcSAsim Jamshed 		     uint16_t datalen, int option)
1231*76404edcSAsim Jamshed {
1232*76404edcSAsim Jamshed 	return mtcp_setlastpkt(mctx, sock, side, offset, data, datalen, option);
1233*76404edcSAsim Jamshed }
1234*76404edcSAsim Jamshed #endif
1235*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1236*76404edcSAsim Jamshed /**
1237*76404edcSAsim Jamshed  * THIS IS A DEPRECETED FUNCTION...
1238*76404edcSAsim Jamshed  */
1239*76404edcSAsim Jamshed int
1240*76404edcSAsim Jamshed mtcp_cb_dropcurpkt(mctx_t mctx)
1241*76404edcSAsim Jamshed {
1242*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
1243*76404edcSAsim Jamshed 
1244*76404edcSAsim Jamshed 	/* checking if mtcp is valid */
1245*76404edcSAsim Jamshed 	mtcp = GetMTCPManager(mctx);
1246*76404edcSAsim Jamshed 	if (!mtcp) {
1247*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid mtcp!\n");
1248*76404edcSAsim Jamshed 		errno = EACCES;
1249*76404edcSAsim Jamshed 		return -1;
1250*76404edcSAsim Jamshed 	}
1251*76404edcSAsim Jamshed 
1252*76404edcSAsim Jamshed 	/* check if the calling thread is in MOS context */
1253*76404edcSAsim Jamshed 	if (mtcp->ctx->thread != pthread_self()) {
1254*76404edcSAsim Jamshed 		TRACE_ERROR("Invalid thread id!\n");
1255*76404edcSAsim Jamshed 		errno = EPERM;
1256*76404edcSAsim Jamshed 		return -1;
1257*76404edcSAsim Jamshed 	}
1258*76404edcSAsim Jamshed 
1259*76404edcSAsim Jamshed 	/* see if cur_pkt_ctx is valid */
1260*76404edcSAsim Jamshed 	if (mtcp->pctx == NULL) {
1261*76404edcSAsim Jamshed 		TRACE_ERROR("pctx is NULL!\n");
1262*76404edcSAsim Jamshed 		errno = ENODATA;
1263*76404edcSAsim Jamshed 		return -1;
1264*76404edcSAsim Jamshed 	}
1265*76404edcSAsim Jamshed 
1266*76404edcSAsim Jamshed 	mtcp->pctx->forward = 0;
1267*76404edcSAsim Jamshed 
1268*76404edcSAsim Jamshed 	return 0;
1269*76404edcSAsim Jamshed }
1270*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1271*76404edcSAsim Jamshed int
1272*76404edcSAsim Jamshed mtcp_set_debug_string(mtcp_manager_t mtcp, const char *fmt, ...)
1273*76404edcSAsim Jamshed {
1274*76404edcSAsim Jamshed #ifdef ENABLE_DEBUG_EVENT
1275*76404edcSAsim Jamshed 	va_list args;
1276*76404edcSAsim Jamshed 	int i;
1277*76404edcSAsim Jamshed 
1278*76404edcSAsim Jamshed 	assert(mtcp);
1279*76404edcSAsim Jamshed 
1280*76404edcSAsim Jamshed 	if (fmt == NULL) {
1281*76404edcSAsim Jamshed 		mtcp->dbg_buf[0] = '\0';
1282*76404edcSAsim Jamshed 		return 0;
1283*76404edcSAsim Jamshed 	}
1284*76404edcSAsim Jamshed 
1285*76404edcSAsim Jamshed 	va_start(args, fmt);
1286*76404edcSAsim Jamshed 	i = vsnprintf(mtcp->dbg_buf, DBG_BUF_LEN - 1, fmt, args);
1287*76404edcSAsim Jamshed 	va_end(args);
1288*76404edcSAsim Jamshed 
1289*76404edcSAsim Jamshed 	return i;
1290*76404edcSAsim Jamshed #else
1291*76404edcSAsim Jamshed 	return -1;
1292*76404edcSAsim Jamshed #endif /* ENABLE_DEBUG_EVENT */
1293*76404edcSAsim Jamshed }
1294*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1295*76404edcSAsim Jamshed int
1296*76404edcSAsim Jamshed mtcp_get_debug_string(mctx_t mctx, char *buf, int len)
1297*76404edcSAsim Jamshed {
1298*76404edcSAsim Jamshed #ifdef ENABLE_DEBUG_EVENT
1299*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
1300*76404edcSAsim Jamshed 	int copylen;
1301*76404edcSAsim Jamshed 
1302*76404edcSAsim Jamshed 	if (len < 0)
1303*76404edcSAsim Jamshed 		return -1;
1304*76404edcSAsim Jamshed 	else if (len == 0)
1305*76404edcSAsim Jamshed 		return 0;
1306*76404edcSAsim Jamshed 
1307*76404edcSAsim Jamshed 	if (!(mtcp = GetMTCPManager(mctx)))
1308*76404edcSAsim Jamshed 		return -1;
1309*76404edcSAsim Jamshed 
1310*76404edcSAsim Jamshed 	copylen = MIN(strlen(mtcp->dbg_buf), len);
1311*76404edcSAsim Jamshed 	strncpy(buf, mtcp->dbg_buf, copylen);
1312*76404edcSAsim Jamshed 
1313*76404edcSAsim Jamshed 	return copylen;
1314*76404edcSAsim Jamshed #else
1315*76404edcSAsim Jamshed 	return -1;
1316*76404edcSAsim Jamshed #endif /* ENABLE_DEBUG_EVENT */
1317*76404edcSAsim Jamshed }
1318*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1319