# #include "util.h" #include "pkts.h" #include "buf.h" #include /* tcp_snd send tcp pkt - Send sequence no's. seqno to seqno + nseq. Compute rcv window to advertise. It is current unused window until unused window is < 50% of max. window; then max. window is advertised. Update t_snxt if send new seqno's. Clr t_acktime to indicate that ACK is not due. */ tcp_snd(ptcb, seqno, nseq) register struct tcb *ptcb; long seqno; register int nseq; { register struct tcp_hdr *tcp; short dlen, maxsdata, uwnd; dlen = 0; tcp = &ptcb->t_tcp; tcp->tc_off = (TCPHSIZ << 2); if ((ptcb->t_state & (SYN_RCVD|FIN_RCVD)) == SYN_RCVD) { uwnd = ptcb->t_rlast - ptcb->t_rnxt; if (uwnd < (RWINDOW >> 1)) { ptcb->t_rwnd = RWINDOW; ptcb->t_rlast = ptcb->t_rnxt + RWINDOW; } else ptcb->t_rwnd = uwnd; } do { tcp->tc_flags &= (~(SYN|FIN|URG)); tcp->tc_flags |= PSH; if (nseq) { maxsdata = nseq <= ptcb->t_maxsdata ? nseq:ptcb->t_maxsdata; dlen = sb_pkt(ptcb, seqno, maxsdata); } tcp->tc_seqno = seqno; tcp->tc_ackno = ptcb->t_rnxt; tcp->tc_window = ptcb->t_rwnd; wr_tcp(ptcb, dlen); seqno += dlen; nseq -= dlen; if (tcp->tc_flags & SYN) { seqno++; nseq--; ptcb->t_state |= SYN_SENT; } if (tcp->tc_flags & FIN) { seqno++; nseq--; ptcb->t_state |= FIN_SENT; } } while (nseq > 0); if ((seqno - ptcb->t_snxt) > 0) ptcb->t_snxt = seqno; ptcb->t_acktime = 0; return(TRUE); } snd_reset(ptcb, ppkt) struct tcb *ptcb; struct rcvpkt *ppkt; { register struct tcp_hdr *tcp, *tcp2; register struct inet_hdr *inp; short iphlen, slen; char flags; short dskt; tcp2 = &ptcb->t_tcp; flags = tcp2->tc_flags; dskt = tcp2->tc_dskt; inp = &ppkt->rp_inet; iphlen = ((inp->ip_ihlver & 017) << 2); tcp = (char *) inp + iphlen; tcp2->tc_dskt = tcp->tc_sskt; tcp2->tc_off = (TCPHSIZ << 2); if (tcp->tc_flags & ACK) { tcp2->tc_flags = RST; tcp2->tc_seqno = tcp->tc_ackno; } else { tcp2->tc_flags = RST|ACK; tcp2->tc_seqno = 0; slen = inp->ip_len - (iphlen + ((tcp->tc_off & 0360) >> 2) ); if (tcp->tc_flags & SYN) slen++; if (tcp->tc_flags & FIN) slen++; tcp2->tc_ackno = tcp->tc_seqno + slen; } wr_tcp(ptcb, 0); tcp2->tc_flags = flags; tcp2->tc_dskt = dskt; return; } wr_tcp(ptcb, dlen) register struct tcb *ptcb; short dlen; { register struct tcp_hdr *tcp; register struct inet_hdr *inp; short tcplen, iplen, plen; tcp = &ptcb->t_tcp; tcplen = dlen + ((tcp->tc_off & 0360) >> 2); tcp->tc_cksum = 0; if (prflag & PF_SND) { dmp_state(); dmp_pkt("Packet sent\n", &ptcb->t_net, (tcplen + IPHSIZ)); } tcp_swab(tcp); ptcb->t_phdr.pt_len = swab(tcplen); tcp->tc_cksum = ~cksum_tcp(&ptcb->t_phdr, tcp, tcplen); inp = &ptcb->t_inet; iplen = tcplen + IPHSIZ; inp->ip_len = swab(iplen); inp->ip_id = 0; plen = iplen + NETHSIZ; if (!wr_pkt(&ptcb->t_net, plen)) return(FALSE); return(TRUE); }