* NOTE!!! the new tcp-reassembly code *must not* use * m_adj() with a negative index. That alters the chain * of mbufs (by possibly chopping trailing mbufs). At * the front of tcp_reass we count the mbuf overhead * and setup the tail pointer. If we use m_adj(m, -5) * we could corrupt the tail pointer. Currently the * code only uses m_adj(m, postive-num). If this * changes appropriate change
| 523 | * be needed. |
| 524 | */ |
| 525 | int |
| 526 | tcp_reass(struct tcpcb *tp, struct tcphdr *th, tcp_seq *seq_start, |
| 527 | int *tlenp, struct mbuf *m) |
| 528 | { |
| 529 | struct tseg_qent *q, *last, *first; |
| 530 | struct tseg_qent *p = NULL; |
| 531 | struct tseg_qent *nq = NULL; |
| 532 | struct tseg_qent *te = NULL; |
| 533 | struct mbuf *mlast = NULL; |
| 534 | struct sockbuf *sb; |
| 535 | struct socket *so = tp->t_inpcb->inp_socket; |
| 536 | char *s = NULL; |
| 537 | int flags, i, lenofoh; |
| 538 | |
| 539 | INP_WLOCK_ASSERT(tp->t_inpcb); |
| 540 | /* |
| 541 | * XXX: tcp_reass() is rather inefficient with its data structures |
| 542 | * and should be rewritten (see NetBSD for optimizations). |
| 543 | */ |
| 544 | |
| 545 | KASSERT(th == NULL || (seq_start != NULL && tlenp != NULL), |
| 546 | ("tcp_reass called with illegal parameter combination " |
| 547 | "(tp=%p, th=%p, seq_start=%p, tlenp=%p, m=%p)", |
| 548 | tp, th, seq_start, tlenp, m)); |
| 549 | /* |
| 550 | * Call with th==NULL after become established to |
| 551 | * force pre-ESTABLISHED data up to user socket. |
| 552 | */ |
| 553 | if (th == NULL) |
| 554 | goto present; |
| 555 | KASSERT(SEQ_GEQ(th->th_seq, tp->rcv_nxt), |
| 556 | ("Attempt to add old entry to reassembly queue (th=%p, tp=%p)", |
| 557 | th, tp)); |
| 558 | #ifdef TCP_REASS_LOGGING |
| 559 | tcp_reass_log_new_in(tp, th->th_seq, *tlenp, m, TCP_R_LOG_ADD, NULL); |
| 560 | #endif |
| 561 | #ifdef TCP_REASS_COUNTERS |
| 562 | counter_u64_add(reass_entry, 1); |
| 563 | #endif |
| 564 | /* |
| 565 | * Check for zero length data. |
| 566 | */ |
| 567 | if ((*tlenp == 0) && ((th->th_flags & TH_FIN) == 0)) { |
| 568 | /* |
| 569 | * A zero length segment does no |
| 570 | * one any good. We could check |
| 571 | * the rcv_nxt <-> rcv_wnd but thats |
| 572 | * already done for us by the caller. |
| 573 | */ |
| 574 | #ifdef TCP_REASS_COUNTERS |
| 575 | counter_u64_add(tcp_zero_input, 1); |
| 576 | #endif |
| 577 | m_freem(m); |
| 578 | #ifdef TCP_REASS_LOGGING |
| 579 | tcp_reass_log_dump(tp); |
| 580 | #endif |
| 581 | return (0); |
| 582 | } |
no test coverage detected