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