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