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