1*5089Swnj /* tcp_subr.c 4.3 81/11/26 */ 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" 9*5089Swnj #include "../net/in.h" 10*5089Swnj #include "../net/in_pcb.h" 11*5089Swnj #include "../net/in_systm.h" 125068Swnj #include "../net/if.h" 135068Swnj #include "../net/ip.h" 145068Swnj #include "../net/ip_var.h" 155068Swnj #include "../net/tcp.h" 165068Swnj #define TCPFSTAB 175068Swnj #include "../net/tcp_fsm.h" 18*5089Swnj #include "../net/tcp_seq.h" 19*5089Swnj #include "../net/tcp_timer.h" 205068Swnj #include "../net/tcp_var.h" 21*5089Swnj #include "../net/tcpip.h" 225068Swnj #include "/usr/include/errno.h" 235068Swnj 245068Swnj /* 255068Swnj * Tcp initialization 265068Swnj */ 275068Swnj tcp_init() 285068Swnj { 295068Swnj 30*5089Swnj COUNT(TCP_INIT); 315068Swnj tcp_iss = 1; /* wrong */ 325068Swnj tcb.inp_next = tcb.inp_prev = &tcb; 335068Swnj } 345068Swnj 355068Swnj /* 365068Swnj * Create template to be used to send tcp packets on a connection. 375068Swnj * Call after host entry created, allocates an mbuf and fills 385068Swnj * in a skeletal tcp/ip header, minimizing the amount of work 395068Swnj * necessary when the connection is used. 405068Swnj */ 415068Swnj struct tcpiphdr * 425068Swnj tcp_template(tp) 435068Swnj struct tcpcb *tp; 445068Swnj { 455068Swnj register struct inpcb *inp = tp->t_inpcb; 465068Swnj register struct mbuf *m; 475068Swnj register struct tcpiphdr *n; 485068Swnj 495068Swnj COUNT(TCP_TEMPLATE); 505068Swnj m = m_get(1); 515068Swnj if (m == 0) 525068Swnj return (0); 535068Swnj m->m_off = MMAXOFF - sizeof (struct tcpiphdr); 545068Swnj m->m_len = sizeof (struct tcpiphdr); 555068Swnj n = mtod(m, struct tcpiphdr *); 565068Swnj n->ti_next = n->ti_prev = 0; 575068Swnj n->ti_x1 = 0; 585068Swnj n->ti_pr = IPPROTO_TCP; 595068Swnj n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); 605068Swnj n->ti_src = inp->inp_laddr; 615068Swnj n->ti_dst = inp->inp_faddr; 625068Swnj n->ti_sport = inp->inp_lport; 635068Swnj n->ti_dport = inp->inp_fport; 645068Swnj n->ti_seq = 0; 65*5089Swnj n->ti_ack = 0; 665068Swnj n->ti_x2 = 0; 675068Swnj n->ti_off = 5; 685068Swnj n->ti_flags = 0; 695068Swnj n->ti_win = 0; 705068Swnj n->ti_sum = 0; 715068Swnj n->ti_urp = 0; 725068Swnj return (n); 735068Swnj } 745068Swnj 755068Swnj /* 76*5089Swnj * Send a reset message back to send of TCP segment ti, 775068Swnj * with ack, seq and flags fields as specified by parameters. 785068Swnj */ 79*5089Swnj tcp_respond(ti, ack, seq, flags) 805068Swnj register struct tcpiphdr *ti; 81*5089Swnj tcp_seq ack, seq; 825068Swnj int flags; 835068Swnj { 84*5089Swnj struct mbuf *m = dtom(ti); 855068Swnj 86*5089Swnj COUNT(TCP_RESPOND); 875068Swnj m_freem(m->m_next); 885068Swnj m->m_next = 0; 895068Swnj m->m_len = sizeof(struct tcpiphdr); 90*5089Swnj #define xchg(a,b,type) { type t; t=a; a=b; b=t; } 91*5089Swnj xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long); 92*5089Swnj xchg(ti->ti_dport, ti->ti_sport, u_short); 935068Swnj #undef xchg 94*5089Swnj ti->ti_next = ti->ti_prev = 0; 95*5089Swnj ti->ti_x1 = 0; 96*5089Swnj ti->ti_len = htons(sizeof (struct tcphdr)); 97*5089Swnj ti->ti_seq = htonl(seq); 985068Swnj ti->ti_ack = htonl(ack); 99*5089Swnj ti->ti_x2 = 0; 100*5089Swnj ti->ti_off = sizeof (struct tcphdr) >> 2; 1015068Swnj ti->ti_flags = flags; 102*5089Swnj ti->ti_win = ti->ti_urp = 0; 103*5089Swnj ti->ti_sum = in_cksum(m, sizeof(struct tcpiphdr)); 1045068Swnj ((struct ip *)ti)->ip_len = sizeof(struct tcpiphdr); 105*5089Swnj ((struct ip *)ti)->ip_ttl = TCP_TTL; 106*5089Swnj ip_output(m, (struct mbuf *)0); 1075068Swnj } 1085075Swnj 109*5089Swnj /* 110*5089Swnj * Create a new TCP control block, making an 111*5089Swnj * empty reassembly queue and hooking it to the argument 112*5089Swnj * protocol control block. 113*5089Swnj */ 1145075Swnj struct tcpcb * 1155075Swnj tcp_newtcpcb(inp) 1165075Swnj struct inpcb *inp; 1175075Swnj { 1185075Swnj struct mbuf *m = m_getclr(0); 1195075Swnj register struct tcpcb *tp; 1205075Swnj COUNT(TCP_NEWTCPCB); 1215075Swnj 1225075Swnj if (m == 0) 1235075Swnj return (0); 1245075Swnj tp = mtod(m, struct tcpcb *); 1255075Swnj tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; 126*5089Swnj tp->t_maxseg = 1024; 1275075Swnj tp->t_inpcb = inp; 1285075Swnj inp->inp_ppcb = (caddr_t)tp; 1295075Swnj return (tp); 1305075Swnj } 1315075Swnj 132*5089Swnj /* 133*5089Swnj * Drop a TCP connection, reporting 134*5089Swnj * the specified error. If connection is synchronized, 135*5089Swnj * then send a RST to peer. 136*5089Swnj */ 1375075Swnj tcp_drop(tp, errno) 1385075Swnj struct tcpcb *tp; 1395075Swnj int errno; 1405075Swnj { 1415075Swnj struct socket *so = tp->t_inpcb->inp_socket; 1425075Swnj 1435075Swnj COUNT(TCP_DROP); 1445075Swnj if (TCPS_HAVERCVDSYN(tp->t_state) && 145*5089Swnj TCPS_OURFINNOTACKED(tp->t_state)) { 1465075Swnj tp->t_state = TCPS_CLOSED; 1475075Swnj tcp_output(tp); 1485075Swnj } 1495075Swnj so->so_error = errno; 1505075Swnj tcp_close(tp); 1515075Swnj } 1525075Swnj 153*5089Swnj /* 154*5089Swnj * Close a TCP control block: 155*5089Swnj * discard all space held by the tcp 156*5089Swnj * discard internet protocol block 157*5089Swnj * wake up any sleepers 158*5089Swnj */ 1595075Swnj tcp_close(tp) 1605075Swnj register struct tcpcb *tp; 1615075Swnj { 1625075Swnj register struct tcpiphdr *t; 163*5089Swnj struct socket *so = tp->t_inpcb->inp_socket; 1645075Swnj 1655075Swnj COUNT(TCP_CLOSE); 1665075Swnj t = tp->seg_next; 1675075Swnj for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next) 1685075Swnj m_freem(dtom(t)); 169*5089Swnj if (tp->t_template) 1705075Swnj (void) m_free(dtom(tp->t_template)); 171*5089Swnj if (tp->t_tcpopt) 172*5089Swnj (void) m_free(dtom(tp->t_tcpopt)); 173*5089Swnj if (tp->t_ipopt) 174*5089Swnj (void) m_free(dtom(tp->t_ipopt)); 1755075Swnj in_pcbfree(tp->t_inpcb); 1765075Swnj (void) m_free(dtom(tp)); 177*5089Swnj socantrcvmore(so); 178*5089Swnj socantsendmore(so); 1795075Swnj } 1805075Swnj 1815075Swnj /*ARGSUSED*/ 1825075Swnj tcp_sense(m) 1835075Swnj struct mbuf *m; 1845075Swnj { 1855075Swnj 1865075Swnj COUNT(TCP_SENSE); 1875075Swnj return (EOPNOTSUPP); 1885075Swnj } 1895075Swnj 1905075Swnj tcp_drain() 1915075Swnj { 1925075Swnj register struct inpcb *ip; 1935075Swnj 1945075Swnj COUNT(TCP_DRAIN); 1955075Swnj } 1965075Swnj 1975075Swnj tcp_ctlinput(m) 1985075Swnj struct mbuf *m; 1995075Swnj { 2005075Swnj 2015075Swnj COUNT(TCP_CTLINPUT); 2025075Swnj m_freem(m); 2035075Swnj } 204