1*5075Swnj /* tcp_subr.c 4.2 81/11/25 */ 25068Swnj 35068Swnj #include "../h/param.h" 45068Swnj #include "../h/systm.h" 55068Swnj #include "../h/mbuf.h" 65068Swnj #include "../h/socket.h" 75068Swnj #include "../h/socketvar.h" 85068Swnj #include "../h/protosw.h" 95068Swnj #include "../net/inet.h" 105068Swnj #include "../net/inet_pcb.h" 115068Swnj #include "../net/inet_systm.h" 125068Swnj #include "../net/if.h" 135068Swnj #include "../net/imp.h" 145068Swnj #include "../net/ip.h" 155068Swnj #include "../net/ip_var.h" 165068Swnj #include "../net/tcp.h" 175068Swnj #define TCPFSTAB 185068Swnj #include "../net/tcp_fsm.h" 195068Swnj #include "../net/tcp_var.h" 205068Swnj #include "/usr/include/errno.h" 215068Swnj 225068Swnj /* 235068Swnj * Tcp initialization 245068Swnj */ 255068Swnj tcp_init() 265068Swnj { 275068Swnj 285068Swnj tcp_iss = 1; /* wrong */ 295068Swnj tcb.inp_next = tcb.inp_prev = &tcb; 305068Swnj } 315068Swnj 325068Swnj /* 335068Swnj * Create template to be used to send tcp packets on a connection. 345068Swnj * Call after host entry created, allocates an mbuf and fills 355068Swnj * in a skeletal tcp/ip header, minimizing the amount of work 365068Swnj * necessary when the connection is used. 375068Swnj */ 385068Swnj struct tcpiphdr * 395068Swnj tcp_template(tp) 405068Swnj struct tcpcb *tp; 415068Swnj { 425068Swnj register struct inpcb *inp = tp->t_inpcb; 435068Swnj register struct mbuf *m; 445068Swnj register struct tcpiphdr *n; 455068Swnj 465068Swnj COUNT(TCP_TEMPLATE); 475068Swnj m = m_get(1); 485068Swnj if (m == 0) 495068Swnj return (0); 505068Swnj m->m_off = MMAXOFF - sizeof (struct tcpiphdr); 515068Swnj m->m_len = sizeof (struct tcpiphdr); 525068Swnj n = mtod(m, struct tcpiphdr *); 535068Swnj n->ti_next = n->ti_prev = 0; 545068Swnj n->ti_x1 = 0; 555068Swnj n->ti_pr = IPPROTO_TCP; 565068Swnj n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); 575068Swnj n->ti_src = inp->inp_laddr; 585068Swnj n->ti_dst = inp->inp_faddr; 595068Swnj n->ti_sport = inp->inp_lport; 605068Swnj n->ti_dport = inp->inp_fport; 615068Swnj n->ti_seq = 0; 625068Swnj n->ti_ackno = 0; 635068Swnj n->ti_x2 = 0; 645068Swnj n->ti_off = 5; 655068Swnj n->ti_flags = 0; 665068Swnj n->ti_win = 0; 675068Swnj n->ti_sum = 0; 685068Swnj n->ti_urp = 0; 695068Swnj return (n); 705068Swnj } 715068Swnj 725068Swnj /* 735068Swnj * Reflect a control message back to sender of tcp segment ti, 745068Swnj * with ack, seq and flags fields as specified by parameters. 755068Swnj */ 765068Swnj tcp_reflect(ti, ack, seq, flags) 775068Swnj register struct tcpiphdr *ti; 785068Swnj tcpseq_t ack, seq; 795068Swnj int flags; 805068Swnj { 815068Swnj 825068Swnj m_freem(m->m_next); 835068Swnj m->m_next = 0; 845068Swnj m->m_len = sizeof(struct tcpiphdr); 855068Swnj #define xchg(a,b) j=a; a=b; b=j 865068Swnj xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr); 875068Swnj xchg(ti->ti_dport, ti->ti_sport); 885068Swnj #undef xchg 895068Swnj ti->ti_ack = htonl(ack); 905068Swnj ti->ti_seq = htonl(seq); 915068Swnj ti->ti_flags = flags; 925068Swnj 935068Swnj ti->ti_len = htons(sizeof (struct tcphdr)); 945068Swnj ti->ti_off = 5; 955068Swnj ti->ti_sum = inet_cksum(m, sizeof(struct tcpiphdr)); 965068Swnj ((struct ip *)ti)->ip_len = sizeof(struct tcpiphdr); 975068Swnj ((struct ip *)ti)->ip_ttl = MAXTTL; 985068Swnj ip_output(m); 995068Swnj } 100*5075Swnj 101*5075Swnj struct tcpcb * 102*5075Swnj tcp_newtcpcb(inp) 103*5075Swnj struct inpcb *inp; 104*5075Swnj { 105*5075Swnj struct mbuf *m = m_getclr(0); 106*5075Swnj register struct tcpcb *tp; 107*5075Swnj COUNT(TCP_NEWTCPCB); 108*5075Swnj 109*5075Swnj if (m == 0) 110*5075Swnj return (0); 111*5075Swnj tp = mtod(m, struct tcpcb *); 112*5075Swnj 113*5075Swnj /* 114*5075Swnj * Make empty reassembly queue. 115*5075Swnj */ 116*5075Swnj tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; 117*5075Swnj 118*5075Swnj /* 119*5075Swnj * Initialize sequence numbers and round trip retransmit timer. 120*5075Swnj */ 121*5075Swnj tp->t_xmtime = T_REXMT; 122*5075Swnj tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una = 123*5075Swnj tp->iss = tcp_iss; 124*5075Swnj tp->snd_off = tp->iss + 1; 125*5075Swnj tcp_iss += (ISSINCR >> 1) + 1; 126*5075Swnj 127*5075Swnj /* 128*5075Swnj * Hook to inpcb. 129*5075Swnj */ 130*5075Swnj tp->t_inpcb = inp; 131*5075Swnj inp->inp_ppcb = (caddr_t)tp; 132*5075Swnj return (tp); 133*5075Swnj } 134*5075Swnj 135*5075Swnj tcp_drop(tp, errno) 136*5075Swnj struct tcpcb *tp; 137*5075Swnj int errno; 138*5075Swnj { 139*5075Swnj struct socket *so = tp->t_inpcb->inp_socket; 140*5075Swnj 141*5075Swnj COUNT(TCP_DROP); 142*5075Swnj if (TCPS_HAVERCVDSYN(tp->t_state) && 143*5075Swnj TCPS_OURFINISACKED(tp->t_state) == 0) { 144*5075Swnj tp->t_state = TCPS_CLOSED; 145*5075Swnj tcp_output(tp); 146*5075Swnj } 147*5075Swnj so->so_error = errno; 148*5075Swnj socantrcvmore(so); 149*5075Swnj socantsndmore(so); 150*5075Swnj tcp_close(tp); 151*5075Swnj } 152*5075Swnj 153*5075Swnj tcp_close(tp) 154*5075Swnj register struct tcpcb *tp; 155*5075Swnj { 156*5075Swnj register struct tcpiphdr *t; 157*5075Swnj 158*5075Swnj COUNT(TCP_CLOSE); 159*5075Swnj tcp_canceltimers(tp); 160*5075Swnj t = tp->seg_next; 161*5075Swnj for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next) 162*5075Swnj m_freem(dtom(t)); 163*5075Swnj if (tp->t_template) { 164*5075Swnj (void) m_free(dtom(tp->t_template)); 165*5075Swnj tp->t_template = 0; 166*5075Swnj } 167*5075Swnj in_pcbfree(tp->t_inpcb); 168*5075Swnj (void) m_free(dtom(tp)); 169*5075Swnj } 170*5075Swnj 171*5075Swnj /*ARGSUSED*/ 172*5075Swnj tcp_sense(m) 173*5075Swnj struct mbuf *m; 174*5075Swnj { 175*5075Swnj 176*5075Swnj COUNT(TCP_SENSE); 177*5075Swnj return (EOPNOTSUPP); 178*5075Swnj } 179*5075Swnj 180*5075Swnj tcp_drain() 181*5075Swnj { 182*5075Swnj register struct inpcb *ip; 183*5075Swnj 184*5075Swnj COUNT(TCP_DRAIN); 185*5075Swnj } 186*5075Swnj 187*5075Swnj tcp_ctlinput(m) 188*5075Swnj struct mbuf *m; 189*5075Swnj { 190*5075Swnj 191*5075Swnj COUNT(TCP_CTLINPUT); 192*5075Swnj m_freem(m); 193*5075Swnj } 194