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_ctx *from) 412 { 413 /* only memcpy till the last field before ethh */ 414 /* memcpy(to, from, PCTX_COPY_LEN); */ 415 memcpy(to, &(from->p), PKT_INFO_LEN); 416 /* memcpy the entire ethernet frame */ 417 assert(from); 418 assert(from->p.eth_len > 0); 419 assert(from->p.eth_len <= ETHERNET_FRAME_LEN); 420 memcpy(frame, from->p.ethh, from->p.eth_len); 421 /* set iph */ 422 to->ethh = (struct ethhdr *)frame; 423 /* set iph */ 424 to->iph = from->p.iph ? 425 (struct iphdr *)((uint8_t *)(frame + ETHERNET_HEADER_LEN)) : NULL; 426 /* set tcph */ 427 to->tcph = from->p.tcph ? 428 (struct tcphdr *)(((uint8_t *)(to->iph)) + (to->iph->ihl<<2)) : NULL; 429 /* set payload */ 430 to->payload = from->p.tcph ? 431 ((uint8_t *)(to->tcph) + (to->tcph->doff<<2)) : NULL; 432 return to; 433 } 434 /*----------------------------------------------------------------------------*/ 435 int 436 mtcp_getlastpkt(mctx_t mctx, int sock, int side, struct pkt_info *pkt) 437 { 438 mtcp_manager_t mtcp; 439 socket_map_t socket; 440 struct tcp_stream *cur_stream; 441 struct pkt_ctx *cur_pkt_ctx; 442 443 mtcp = GetMTCPManager(mctx); 444 if (!mtcp) { 445 errno = EACCES; 446 return -1; 447 } 448 449 /* check if the calling thread is in MOS context */ 450 if (mtcp->ctx->thread != pthread_self()) { 451 errno = EPERM; 452 return -1; 453 } 454 455 /* check if the socket is monitor stream */ 456 socket = &mtcp->msmap[sock]; 457 458 if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE) { 459 if (side != MOS_SIDE_CLI && side != MOS_SIDE_SVR) { 460 TRACE_ERROR("Invalid side requested!\n"); 461 exit(EXIT_FAILURE); 462 return -1; 463 } 464 465 struct tcp_stream *mstrm = socket->monitor_stream->stream; 466 cur_stream = (side == mstrm->side) ? mstrm : mstrm->pair_stream; 467 468 cur_pkt_ctx = &cur_stream->last_pctx; 469 if (!cur_pkt_ctx->p.ethh) { 470 errno = ENODATA; 471 return -1; 472 } 473 } else if (socket->socktype == MOS_SOCK_MONITOR_RAW) { 474 cur_pkt_ctx = mtcp->pctx; 475 } else if (socket->socktype == MOS_SOCK_MONITOR_STREAM) { 476 /* 477 * if it is a monitor socket, then this means that 478 * this is a request for an orphan tcp packet 479 */ 480 cur_pkt_ctx = mtcp->pctx; 481 } else { 482 TRACE_DBG("Invalid socket type!\n"); 483 errno = EBADF; 484 return -1; 485 } 486 487 ClonePacketCtx(pkt, local_frame, cur_pkt_ctx); 488 return 0; 489 } 490 #else 491 /*----------------------------------------------------------------------------*/ 492 int 493 mtcp_getlastpkt(mctx_t mctx, int sock, int side, struct pkt_ctx **pctx) 494 { 495 mtcp_manager_t mtcp; 496 497 mtcp = GetMTCPManager(mctx); 498 if (!mtcp) { 499 errno = EACCES; 500 return -1; 501 } 502 503 /* check if the calling thread is in MOS context */ 504 if (mtcp->ctx->thread != pthread_self()) { 505 errno = EPERM; 506 return -1; 507 } 508 /* just pass direct pointer */ 509 *pctx = mtcp->pctx; 510 511 return 0; 512 } 513 #endif 514 /*----------------------------------------------------------------------------*/ 515 int 516 mtcp_sendpkt(mctx_t mctx, int sock, const struct pkt_info *pkt) 517 { 518 mtcp_manager_t mtcp; 519 socket_map_t socket; 520 521 mtcp = GetMTCPManager(mctx); 522 if (!mtcp || !pkt) { 523 errno = EACCES; 524 return -1; 525 } 526 527 /* check if the calling thread is in MOS context */ 528 if (mtcp->ctx->thread != pthread_self()) { 529 errno = EPERM; 530 return -1; 531 } 532 533 /* check if the socket is monitor stream */ 534 socket = &mtcp->msmap[sock]; 535 536 if (!(pkt->iph) || !(pkt->tcph)) { 537 errno = ENODATA; 538 TRACE_INFO("mtcp_sendpkt() only supports TCP packet for now.\n"); 539 return -1; 540 } 541 542 if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE) { 543 SendTCPPacketStandalone(mtcp, 544 pkt->iph->saddr, pkt->tcph->source, 545 pkt->iph->daddr, pkt->tcph->dest, 546 htonl(pkt->tcph->seq), htonl(pkt->tcph->ack_seq), 547 ntohs(pkt->tcph->window), TCP_FLAG_ACK, 548 pkt->payload, pkt->payloadlen, 549 socket->monitor_stream->stream->rcvvar->ts_recent, 550 socket->monitor_stream->stream->rcvvar->ts_lastack_rcvd, 551 pkt->iph->id); 552 553 554 } 555 556 return 0; 557 } 558 /*----------------------------------------------------------------------------*/ 559 /** Disable events from the monitor stream socket 560 * @param [in] mtcp: mtcp_manager 561 * @param [in] sock: socket 562 * 563 * returns 0 on success, -1 on failure 564 * 565 * This is used for flow management based monitoring sockets 566 */ 567 int 568 RemoveMonitorEvents(mtcp_manager_t mtcp, socket_map_t socket, int side) 569 { 570 struct mon_stream *mstream; 571 struct mon_listener *mlistener; 572 573 if (mtcp == NULL) { 574 TRACE_DBG("mtcp is not defined!!!\n"); 575 errno = EACCES; 576 return -1; 577 } 578 579 switch (socket->socktype) { 580 case MOS_SOCK_MONITOR_STREAM_ACTIVE: 581 mstream = socket->monitor_stream; 582 if (mstream == NULL) { 583 TRACE_ERROR("Mon Stream does not exist!\n"); 584 /* exit(-1); */ 585 errno = ENODATA; 586 return -1; 587 } 588 589 if (side == MOS_SIDE_SVR) mstream->server_mon = 0; 590 else if (side == MOS_SIDE_CLI) mstream->client_mon = 0; 591 592 if (mstream->server_mon == 0 && mstream->client_mon == 0) { 593 #ifdef NEWEV 594 /* 595 * if stree_dontcare is NULL, then we know that all 596 * events have already been disabled 597 */ 598 if (mstream->stree_pre_rcv != NULL) { 599 stree_dec_ref(mtcp->ev_store, mstream->stree_dontcare); 600 stree_dec_ref(mtcp->ev_store, mstream->stree_pre_rcv); 601 stree_dec_ref(mtcp->ev_store, mstream->stree_post_snd); 602 603 mstream->stree_dontcare = NULL; 604 mstream->stree_pre_rcv = NULL; 605 mstream->stree_post_snd = NULL; 606 } 607 #else 608 /* no error checking over here.. 609 * but its okay.. this code is 610 * deprecated 611 */ 612 CleanupEvP(&mstream->dontcare_evp); 613 CleanupEvP(&mstream->pre_tcp_evp); 614 CleanupEvP(&mstream->post_tcp_evp); 615 #endif 616 } 617 break; 618 case MOS_SOCK_MONITOR_STREAM: 619 mlistener = socket->monitor_listener; 620 if (mlistener == NULL) { 621 TRACE_ERROR("Mon listener does not exist!\n"); 622 errno = ENODATA; 623 return -1; 624 } 625 626 if (side == MOS_SIDE_SVR) mlistener->server_mon = 0; 627 else if (side == MOS_SIDE_CLI) mlistener->client_mon = 0; 628 629 if (mlistener->server_mon == 0 && mlistener->client_mon == 0) { 630 #ifdef NEWEV 631 /* 632 * if stree_dontcare is NULL, then we know that all 633 * events have already been disabled 634 */ 635 if (mlistener->stree_pre_rcv != NULL) { 636 stree_dec_ref(mtcp->ev_store, mlistener->stree_dontcare); 637 stree_dec_ref(mtcp->ev_store, mlistener->stree_pre_rcv); 638 stree_dec_ref(mtcp->ev_store, mlistener->stree_post_snd); 639 640 mlistener->stree_dontcare = NULL; 641 mlistener->stree_pre_rcv = NULL; 642 mlistener->stree_post_snd = NULL; 643 } 644 #else 645 /* no error checking over here.. 646 * but its okay.. this code is 647 * deprecated 648 */ 649 CleanupEvB(mtcp, &mlistener->dontcare_evb); 650 CleanupEvB(mtcp, &mlistener->pre_tcp_evb); 651 CleanupEvB(mtcp, &mlistener->post_tcp_evb); 652 #endif 653 } 654 break; 655 default: 656 TRACE_ERROR("Invalid socket type!\n"); 657 } 658 659 return 0; 660 } 661 /*----------------------------------------------------------------------------*/ 662 /** 663 * Disable monitoring based on side variable. 664 */ 665 int 666 mtcp_cb_stop(mctx_t mctx, int sock, int side) 667 { 668 mtcp_manager_t mtcp; 669 socket_map_t socket; 670 struct tcp_stream *stream; 671 struct socket_map *walk; 672 uint8_t mgmt; 673 674 mtcp = GetMTCPManager(mctx); 675 if (!mtcp) { 676 errno = EACCES; 677 return -1; 678 } 679 680 socket = &mtcp->msmap[sock]; 681 682 /* works for both monitor listener and stream sockets */ 683 RemoveMonitorEvents(mtcp, socket, side); 684 685 /* passive monitoring socket is not connected to any stream */ 686 if (socket->socktype == MOS_SOCK_MONITOR_STREAM) 687 return 0; 688 689 if (side == MOS_SIDE_CLI) { 690 /* see if the associated stream requires monitoring any more */ 691 stream = (socket->monitor_stream->stream->side == MOS_SIDE_CLI) ? 692 socket->monitor_stream->stream : 693 socket->monitor_stream->stream->pair_stream; 694 695 mgmt = 0; 696 SOCKQ_FOREACH_START(walk, &stream->msocks) { 697 if (walk->monitor_stream->client_mon == 1) { 698 mgmt = 1; 699 break; 700 } 701 } SOCKQ_FOREACH_END; 702 /* if all streams have mgmt off, then tag the stream for destruction */ 703 if (mgmt == 0) { 704 stream = (socket->monitor_stream->stream->side == MOS_SIDE_CLI) ? 705 socket->monitor_stream->stream : 706 socket->monitor_stream->stream->pair_stream; 707 stream->status_mgmt = 0; 708 } 709 } 710 711 if (side == MOS_SIDE_SVR) { 712 /* see if the associated stream requires monitoring any more */ 713 stream = (socket->monitor_stream->stream->side == MOS_SIDE_SVR) ? 714 socket->monitor_stream->stream : 715 socket->monitor_stream->stream->pair_stream; 716 mgmt = 0; 717 SOCKQ_FOREACH_START(walk, &stream->msocks) { 718 if (walk->monitor_stream->server_mon == 1) { 719 mgmt = 1; 720 break; 721 } 722 } SOCKQ_FOREACH_END; 723 /* if all streams have mgmt off, then tag the stream for destruction */ 724 if (mgmt == 0) { 725 stream = (socket->monitor_stream->stream->side == MOS_SIDE_SVR) ? 726 socket->monitor_stream->stream : 727 socket->monitor_stream->stream->pair_stream; 728 stream->status_mgmt = 0; 729 } 730 } 731 732 return 0; 733 } 734 /*----------------------------------------------------------------------------*/ 735 /** 736 * send a RST packet to the TCP stream (uni-directional) 737 */ 738 static inline void 739 SendRSTPacketStandalone(mtcp_manager_t mtcp, struct tcp_stream *stream) { 740 SendTCPPacketStandalone(mtcp, 741 stream->saddr, stream->sport, stream->daddr, stream->dport, 742 stream->snd_nxt, stream->rcv_nxt, 0, TCP_FLAG_RST | TCP_FLAG_ACK, 743 NULL, 0, mtcp->cur_ts, 0, 0); 744 } 745 /*----------------------------------------------------------------------------*/ 746 /** 747 * Reset the connection (send RST packets to both sides) 748 */ 749 int 750 mtcp_reset_conn(mctx_t mctx, int sock) 751 { 752 mtcp_manager_t mtcp; 753 socket_map_t socket; 754 755 mtcp = GetMTCPManager(mctx); 756 if (!mtcp) { 757 errno = EACCES; 758 return -1; 759 } 760 761 socket = &mtcp->msmap[sock]; 762 763 /* passive monitoring socket is not connected to any stream */ 764 if (socket->socktype == MOS_SOCK_MONITOR_STREAM) { 765 errno = EINVAL; 766 return -1; 767 } 768 769 /* send RST packets to the both sides */ 770 SendRSTPacketStandalone(mtcp, socket->monitor_stream->stream); 771 SendRSTPacketStandalone(mtcp, socket->monitor_stream->stream->pair_stream); 772 773 return 0; 774 } 775 /*----------------------------------------------------------------------------*/ 776 uint32_t 777 mtcp_cb_get_ts(mctx_t mctx) 778 { 779 mtcp_manager_t mtcp; 780 781 mtcp = GetMTCPManager(mctx); 782 if (!mtcp) { 783 TRACE_DBG("Can't access MTCP manager!\n"); 784 errno = EACCES; 785 return 0; 786 } 787 788 /* check if the calling thread is in MOS context */ 789 if (mtcp->ctx->thread != pthread_self()) { 790 errno = EPERM; 791 return 0; 792 } 793 794 return TS_TO_USEC(mtcp->cur_ts); 795 } 796 /*----------------------------------------------------------------------------*/ 797 /* Macros related to getpeername */ 798 #define TILL_SVRADDR offsetof(struct sockaddr_in, sin_zero) 799 #define TILL_SVRPORT offsetof(struct sockaddr_in, sin_addr) 800 #define TILL_SVRFAMILY offsetof(struct sockaddr_in, sin_port) 801 #define TILL_CLIADDR sizeof(struct sockaddr) + TILL_SVRADDR 802 #define TILL_CLIPORT sizeof(struct sockaddr) + TILL_SVRPORT 803 #define TILL_CLIFAMILY sizeof(struct sockaddr) + TILL_SVRFAMILY 804 805 int 806 mtcp_getpeername(mctx_t mctx, int sockfd, struct sockaddr *saddr, 807 socklen_t *addrlen, int side) 808 { 809 mtcp_manager_t mtcp; 810 socket_map_t socket; 811 struct tcp_stream *stream; 812 struct sockaddr_in *sin; 813 int rc; 814 815 mtcp = GetMTCPManager(mctx); 816 if (!mtcp) { 817 TRACE_DBG("Can't access MTCP manager!\n"); 818 errno = EACCES; 819 return -1; 820 } 821 822 /* check if sockfd is within limits */ 823 if (sockfd < 0 || sockfd >= g_config.mos->max_concurrency) { 824 TRACE_API("Socket id %d out of range.\n", sockfd); 825 errno = EBADF; 826 return -1; 827 } 828 829 /* check if the calling thread is in MOS context */ 830 if (mtcp->ctx->thread != pthread_self()) { 831 errno = EPERM; 832 return -1; 833 } 834 835 socket = &mtcp->msmap[sockfd]; 836 sin = (struct sockaddr_in *)saddr; 837 rc = 0; 838 839 /* retrieve both streams */ 840 stream = socket->monitor_stream->stream; 841 842 if (side != stream->side) 843 stream = stream->pair_stream; 844 845 if (stream == NULL) { 846 errno = ENOTCONN; 847 return -1; 848 } 849 850 /* reset to 2 * sizeof(struct sockaddr) if addrlen is too big */ 851 if (*addrlen > 2 * sizeof(struct sockaddr)) 852 *addrlen = 2 * sizeof(struct sockaddr); 853 854 /* according per manpage, address can be truncated */ 855 switch (*addrlen) { 856 case (2 * sizeof(struct sockaddr)): 857 case TILL_CLIADDR: 858 sin[1].sin_addr.s_addr = stream->side == MOS_SIDE_SVR ? 859 stream->daddr : stream->saddr; 860 case TILL_CLIPORT: 861 sin[1].sin_port = stream->side == MOS_SIDE_SVR ? 862 stream->dport : stream->sport; 863 case TILL_CLIFAMILY: 864 sin[1].sin_family = AF_INET; 865 case (sizeof(struct sockaddr)): 866 case TILL_SVRADDR: 867 sin->sin_addr.s_addr = stream->side == MOS_SIDE_SVR ? 868 stream->saddr : stream->daddr; 869 case TILL_SVRPORT: 870 sin->sin_port = stream->side == MOS_SIDE_SVR ? 871 stream->sport : stream->dport; 872 case TILL_SVRFAMILY: 873 sin->sin_family = AF_INET; 874 break; 875 default: 876 rc = -1; 877 *addrlen = 0xFFFF; 878 errno = EINVAL; 879 } 880 881 return rc; 882 } 883 /*----------------------------------------------------------------------------*/ 884 int 885 mtcp_setlastpkt(mctx_t mctx, int sock, int side, off_t offset, 886 byte *data, uint16_t datalen, int option) 887 { 888 mtcp_manager_t mtcp; 889 struct pkt_ctx *cur_pkt_ctx; 890 struct ethhdr *ethh; 891 struct iphdr *iph; 892 struct tcphdr *tcph; 893 unsigned char *payload; 894 895 #if 0 896 socket_map_t socket; 897 struct tcp_stream *cur_stream; 898 #endif 899 900 /* checking if mtcp is valid */ 901 mtcp = GetMTCPManager(mctx); 902 if (!mtcp) { 903 errno = EACCES; 904 TRACE_ERROR("Invalid mtcp!\n"); 905 return -1; 906 } 907 908 /* check if the calling thread is in MOS context */ 909 if (mtcp->ctx->thread != pthread_self()) { 910 errno = EPERM; 911 TRACE_ERROR("Invalid thread id!\n"); 912 return -1; 913 } 914 915 #if 0 916 /* check if the socket is monitor stream */ 917 socket = &mtcp->msmap[sock]; 918 if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE) { 919 if (side != MOS_SIDE_CLI && side != MOS_SIDE_SVR) { 920 TRACE_ERROR("Invalid side requested!\n"); 921 exit(EXIT_FAILURE); 922 return -1; 923 } 924 925 struct tcp_stream *mstrm = socket->monitor_stream->stream; 926 cur_stream = (side == mstrm->side) ? mstrm : mstrm->pair_stream; 927 928 if (!cur_stream->allow_pkt_modification) 929 return -1; 930 } else if (socket->socktype != MOS_SOCK_MONITOR_RAW) { 931 TRACE_ERROR("Invalid socket type!\n"); 932 exit(EXIT_FAILURE); 933 return -1; 934 } 935 #endif 936 937 /* see if cur_pkt_ctx is valid */ 938 cur_pkt_ctx = mtcp->pctx; 939 if (cur_pkt_ctx == NULL) { 940 TRACE_ERROR("pctx is NULL!\n"); 941 errno = ENODATA; 942 return -1; 943 } 944 945 /* check if offset is valid */ 946 if (offset < 0) { 947 TRACE_ERROR("Invalid offset position!\n"); 948 errno = EINVAL; 949 return -1; 950 } 951 952 if (__builtin_popcount(option & (MOS_DROP | MOS_CHOMP | 953 MOS_INSERT | MOS_OVERWRITE)) != 1) { 954 TRACE_ERROR("mtcp_setlastpkt() function only allows one of " 955 "(MOS_DROP | MOS_CHOMP | MOS_INSERT | MOS_OVERWRITE) " 956 "to be set at a time.\n"); 957 errno = EAGAIN; 958 return -1; 959 } 960 961 /* drop pkt has the highest priority */ 962 if (option & MOS_DROP) { 963 mtcp->pctx->forward = 0; 964 return 0; 965 } else if (option & MOS_ETH_HDR) { 966 /* validity test */ 967 if ((ethh=cur_pkt_ctx->p.ethh) == NULL || 968 offset + datalen > sizeof(struct ethhdr)) { 969 TRACE_ERROR("Ethernet setting has gone out of bounds " 970 "(offset: %ld, datalen: %d)\n", 971 offset, datalen); 972 errno = EINVAL; 973 return -1; 974 } 975 if (option & MOS_CHOMP) { 976 TRACE_ERROR("Illegal call. " 977 "Ethernet header can't be chopped down!\n"); 978 errno = EACCES; 979 return -1; 980 } else if (option & MOS_INSERT) { 981 TRACE_ERROR("Illegal call. " 982 "Ethernet header can't be extended!\n"); 983 errno = EACCES; 984 return -1; 985 } else /* if (option & MOS_OVERWRITE) */ { 986 memcpy((uint8_t *)ethh + offset, data, datalen); 987 } 988 /* iph, tcph, and payload do not need to change */ 989 } else if (option & MOS_IP_HDR) { 990 /* validity test */ 991 if (cur_pkt_ctx->p.ethh == NULL || 992 cur_pkt_ctx->p.ethh->h_proto != ntohs(ETH_P_IP) || 993 (iph=(struct iphdr *)(cur_pkt_ctx->p.ethh + 1)) == NULL) { 994 TRACE_ERROR("ethh or iph are out of bounds\n"); 995 errno = EACCES; 996 return -1; 997 } 998 if (option & MOS_OVERWRITE) { 999 if (offset + datalen > (iph->ihl<<2)) { 1000 TRACE_ERROR("IP setting has gone out of bounds " 1001 "(offset: %ld, datalen: %d)\n", 1002 offset, datalen); 1003 errno = EINVAL; 1004 return -1; 1005 } 1006 memcpy((uint8_t *)iph + offset, data, datalen); 1007 } 1008 if (option & MOS_CHOMP) { 1009 memmove((uint8_t *)iph + offset, 1010 (uint8_t *)iph + offset + datalen, 1011 cur_pkt_ctx->p.ip_len - offset - datalen); 1012 1013 /* iph does not need to change */ 1014 if (iph->protocol == IPPROTO_TCP) { 1015 cur_pkt_ctx->p.tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2)); 1016 cur_pkt_ctx->p.payload = (uint8_t *)cur_pkt_ctx->p.tcph + 1017 (cur_pkt_ctx->p.tcph->doff<<2); 1018 } else { 1019 /* reset tcph if iph does not have tcp proto */ 1020 cur_pkt_ctx->p.tcph = NULL; 1021 } 1022 /* update iph total length */ 1023 cur_pkt_ctx->p.ip_len = ntohs(iph->tot_len); 1024 /* update eth frame length */ 1025 cur_pkt_ctx->p.eth_len = cur_pkt_ctx->p.ip_len + sizeof(struct ethhdr); 1026 } else if (option & MOS_INSERT) { 1027 memmove((uint8_t *)iph + offset + datalen, 1028 (uint8_t *)iph + offset + 1, 1029 cur_pkt_ctx->p.ip_len - offset); 1030 memcpy((uint8_t *)iph + offset, 1031 data, datalen); 1032 1033 /* iph does not need to change */ 1034 if (iph->protocol == IPPROTO_TCP) { 1035 cur_pkt_ctx->p.tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2)); 1036 cur_pkt_ctx->p.payload = (uint8_t *)cur_pkt_ctx->p.tcph + 1037 (cur_pkt_ctx->p.tcph->doff<<2); 1038 } else { 1039 /* reset tcph if iph does not have tcp proto */ 1040 cur_pkt_ctx->p.tcph = NULL; 1041 } 1042 /* update iph total length */ 1043 cur_pkt_ctx->p.ip_len = ntohs(iph->tot_len); 1044 /* update eth frame length */ 1045 cur_pkt_ctx->p.eth_len = cur_pkt_ctx->p.ip_len + sizeof(struct ethhdr); 1046 } 1047 /* can't update payloadlen because we don't know tcph->doff */ 1048 } else if (option & MOS_TCP_HDR) { 1049 /* validity test */ 1050 iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1); 1051 if (iph == NULL || 1052 iph->protocol != IPPROTO_TCP || 1053 (tcph=(struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2))) == NULL) { 1054 TRACE_ERROR("TCP setting has gone out of bounds " 1055 "(offset: %ld, datalen: %d)\n", 1056 offset, datalen); 1057 errno = EINVAL; 1058 return -1; 1059 } 1060 if (option & MOS_OVERWRITE) { 1061 if (offset + datalen > (tcph->doff<<2)) { 1062 TRACE_ERROR("TCP setting has gone out of bounds " 1063 "(offset: %ld, datalen: %d)\n", 1064 offset, datalen); 1065 errno = EINVAL; 1066 return -1; 1067 } 1068 memcpy((uint8_t *)tcph + offset, data, datalen); 1069 /* update tcp seq # */ 1070 cur_pkt_ctx->p.seq = ntohl(tcph->seq); 1071 /* update tcp ack_seq # */ 1072 cur_pkt_ctx->p.ack_seq = ntohl(tcph->ack_seq); 1073 /* update tcp window */ 1074 cur_pkt_ctx->p.window = ntohs(tcph->window); 1075 1076 /* 150422 dhkim TODO: seq and offset are two different form of same 1077 * variable. We also need to update the offset. */ 1078 } 1079 if (option & MOS_CHOMP) { 1080 memmove((uint8_t *)tcph + offset, 1081 (uint8_t *)tcph + offset + datalen, 1082 cur_pkt_ctx->p.payloadlen + (tcph->doff<<2) 1083 - offset - datalen); 1084 /* update payload ptr */ 1085 cur_pkt_ctx->p.payload = (uint8_t *)tcph + (tcph->doff<<2); 1086 } else if (option & MOS_INSERT) { 1087 memmove((uint8_t *)tcph + offset + datalen, 1088 (uint8_t *)tcph + offset + 1, 1089 cur_pkt_ctx->p.payloadlen + (tcph->doff<<2) 1090 - offset); 1091 memcpy((uint8_t *)tcph + offset, data, datalen); 1092 /* update payload ptr */ 1093 cur_pkt_ctx->p.payload = (uint8_t *)tcph + (tcph->doff<<2); 1094 } 1095 } else if (option & MOS_TCP_PAYLOAD) { 1096 iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1); 1097 tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2)); 1098 payload = (uint8_t *)tcph + (tcph->doff<<2); 1099 if (option & MOS_OVERWRITE) { 1100 if (offset + datalen > ntohs(iph->tot_len) - 1101 (iph->ihl<<2) - (tcph->doff<<2)) { 1102 TRACE_ERROR("Payload setting has gone out of bounds " 1103 "(offset: %ld, datalen: %d)\n", 1104 offset, datalen); 1105 errno = EINVAL; 1106 return -1; 1107 } 1108 memcpy(payload + offset, data, datalen); 1109 } 1110 if (option & MOS_CHOMP) { 1111 memmove(payload + offset, 1112 payload + offset + datalen, 1113 (cur_pkt_ctx->p.payloadlen - 1114 offset - datalen)); 1115 /* update payload length */ 1116 cur_pkt_ctx->p.payloadlen = cur_pkt_ctx->p.ip_len - 1117 (tcph->doff<<2) - (iph->ihl<<2); 1118 } else if (option & MOS_INSERT) { 1119 memmove(payload + offset + datalen, 1120 payload + offset + 1, 1121 cur_pkt_ctx->p.payloadlen - offset); 1122 memcpy(payload + offset, data, datalen); 1123 cur_pkt_ctx->p.payloadlen = cur_pkt_ctx->p.ip_len - 1124 (tcph->doff<<2) - (iph->ihl<<2); 1125 } 1126 } else { 1127 TRACE_ERROR("Invalid option!\n"); 1128 errno = EINVAL; 1129 return -1; 1130 } 1131 1132 /* update ip checksum */ 1133 if (option & MOS_UPDATE_IP_CHKSUM) { 1134 iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1); 1135 iph->check = 0; 1136 iph->check = ip_fast_csum(iph, iph->ihl); 1137 } 1138 1139 /* update tcp checksum */ 1140 if (option & MOS_UPDATE_TCP_CHKSUM) { 1141 iph = (struct iphdr *)(cur_pkt_ctx->p.ethh + 1); 1142 tcph = (struct tcphdr *)((uint8_t *)iph + (iph->ihl<<2)); 1143 tcph->check = 0; 1144 tcph->check = TCPCalcChecksum((uint16_t *)tcph, 1145 ntohs(iph->tot_len) - (iph->ihl<<2), 1146 iph->saddr, iph->daddr); 1147 } 1148 return 0; 1149 } 1150 /*----------------------------------------------------------------------------*/ 1151 #if 0 1152 inline int 1153 mtcp_cb_updatecurpkt(mctx_t mctx, off_t offset, unsigned char *data, 1154 uint16_t datalen, int option) 1155 { 1156 return mtcp_setlastpkt(mctx, sock, side, offset, data, datalen, option); 1157 } 1158 #endif 1159 /*----------------------------------------------------------------------------*/ 1160 /** 1161 * THIS IS A DEPRECETED FUNCTION... 1162 */ 1163 int 1164 mtcp_cb_dropcurpkt(mctx_t mctx) 1165 { 1166 mtcp_manager_t mtcp; 1167 1168 /* checking if mtcp is valid */ 1169 mtcp = GetMTCPManager(mctx); 1170 if (!mtcp) { 1171 TRACE_ERROR("Invalid mtcp!\n"); 1172 errno = EACCES; 1173 return -1; 1174 } 1175 1176 /* check if the calling thread is in MOS context */ 1177 if (mtcp->ctx->thread != pthread_self()) { 1178 TRACE_ERROR("Invalid thread id!\n"); 1179 errno = EPERM; 1180 return -1; 1181 } 1182 1183 /* see if cur_pkt_ctx is valid */ 1184 if (mtcp->pctx == NULL) { 1185 TRACE_ERROR("pctx is NULL!\n"); 1186 errno = ENODATA; 1187 return -1; 1188 } 1189 1190 mtcp->pctx->forward = 0; 1191 1192 return 0; 1193 } 1194 /*----------------------------------------------------------------------------*/ 1195 int 1196 mtcp_set_debug_string(mtcp_manager_t mtcp, const char *fmt, ...) 1197 { 1198 #ifdef ENABLE_DEBUG_EVENT 1199 va_list args; 1200 int i; 1201 1202 assert(mtcp); 1203 1204 if (fmt == NULL) { 1205 mtcp->dbg_buf[0] = '\0'; 1206 return 0; 1207 } 1208 1209 va_start(args, fmt); 1210 i = vsnprintf(mtcp->dbg_buf, DBG_BUF_LEN - 1, fmt, args); 1211 va_end(args); 1212 1213 return i; 1214 #else 1215 return -1; 1216 #endif /* ENABLE_DEBUG_EVENT */ 1217 } 1218 /*----------------------------------------------------------------------------*/ 1219 int 1220 mtcp_get_debug_string(mctx_t mctx, char *buf, int len) 1221 { 1222 #ifdef ENABLE_DEBUG_EVENT 1223 mtcp_manager_t mtcp; 1224 int copylen; 1225 1226 if (len < 0) 1227 return -1; 1228 else if (len == 0) 1229 return 0; 1230 1231 if (!(mtcp = GetMTCPManager(mctx))) 1232 return -1; 1233 1234 copylen = MIN(strlen(mtcp->dbg_buf), len); 1235 strncpy(buf, mtcp->dbg_buf, copylen); 1236 1237 return copylen; 1238 #else 1239 return -1; 1240 #endif /* ENABLE_DEBUG_EVENT */ 1241 } 1242 /*----------------------------------------------------------------------------*/ 1243