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