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