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