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