|
|
1.1 ! root 1: /* tcp_subr.c 6.1 83/07/29 */ ! 2: #include "tcp.h" ! 3: #if NTCP > 0 ! 4: ! 5: #include "../h/param.h" ! 6: #include "../h/systm.h" ! 7: #include "../h/stream.h" ! 8: #include "../h/inet/mbuf.h" ! 9: #include "../h/inet/in.h" ! 10: #include "../h/inet/ip.h" ! 11: #include "../h/inet/ip_var.h" ! 12: #include "../h/inet/tcp.h" ! 13: #include "../h/inet/tcp_fsm.h" ! 14: #include "../h/inet/tcp_seq.h" ! 15: #include "../h/inet/tcp_timer.h" ! 16: #include "../h/inet/tcp_var.h" ! 17: #include "../h/inet/tcpip.h" ! 18: #include "../h/inet/socket.h" ! 19: #include "../h/inet/tcpdebug.h" ! 20: ! 21: extern int tcp_maxseg; ! 22: ! 23: /* ! 24: * Create template to be used to send tcp packets on a connection. ! 25: * Call after host entry created, allocates an mbuf and fills ! 26: * in a skeletal tcp/ip header, minimizing the amount of work ! 27: * necessary when the connection is used. ! 28: */ ! 29: struct tcpiphdr * ! 30: tcp_template(tp) ! 31: struct tcpcb *tp; ! 32: { ! 33: register struct socket *so = tp->t_socket; ! 34: register struct mbuf *m; ! 35: register struct tcpiphdr *n; ! 36: ! 37: m = m_get(M_WAIT, MT_HEADER); ! 38: if (m == NULL) ! 39: return (0); ! 40: m->next = 0; ! 41: m->wptr += sizeof (struct tcpiphdr); ! 42: n = mtod(m, struct tcpiphdr *); ! 43: n->ti_next = n->ti_prev = 0; ! 44: n->ti_x1 = 0; ! 45: n->ti_pr = 6; /* tcp protocol number */ ! 46: n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); ! 47: n->ti_src = so->so_laddr; ! 48: n->ti_dst = so->so_faddr; ! 49: n->ti_sport = so->so_lport; ! 50: n->ti_dport = so->so_fport; ! 51: n->ti_seq = 0; ! 52: n->ti_ack = 0; ! 53: n->ti_x2 = 0; ! 54: n->ti_off = 5; ! 55: n->ti_flags = 0; ! 56: n->ti_win = 0; ! 57: n->ti_sum = 0; ! 58: n->ti_urp = 0; ! 59: return (n); ! 60: } ! 61: ! 62: /* ! 63: * Send a single message to the TCP at address specified by ! 64: * the given TCP/IP header. If flags==0, then we make a copy ! 65: * of the tcpiphdr at ti and send directly to the addressed host. ! 66: * This is used to force keep alive messages out using the TCP ! 67: * template for a connection tp->t_template. If flags are given ! 68: * then we send a message back to the TCP which originated the ! 69: * segment ti, and discard the mbuf containing it and any other ! 70: * attached mbufs. ! 71: * ! 72: * In any case the ack and sequence number of the transmitted ! 73: * segment are as specified by the parameters. ! 74: */ ! 75: tcp_respond(tp, ti, ack, seq, flags) ! 76: struct tcpcb *tp; ! 77: register struct tcpiphdr *ti; ! 78: tcp_seq ack, seq; ! 79: int flags; ! 80: { ! 81: struct mbuf *m; ! 82: int win = 0, tlen; ! 83: ! 84: if (tp) { ! 85: win = sbrcvspace(tp->t_socket); ! 86: } ! 87: if (flags == 0) { ! 88: m = m_get(M_DONTWAIT, MT_HEADER); ! 89: if (m == NULL) ! 90: return; ! 91: m->next = 0; ! 92: m->wptr += sizeof (struct tcpiphdr) + 1; ! 93: *mtod(m, struct tcpiphdr *) = *ti; ! 94: ti = mtod(m, struct tcpiphdr *); ! 95: flags = TH_ACK; ! 96: tlen = 1; ! 97: } else { ! 98: m = dtom(ti); ! 99: m_freem(m->m_next); ! 100: m->m_next = 0; ! 101: m->rptr = (u_char *)ti; ! 102: m->wptr = m->rptr + sizeof (struct tcpiphdr); ! 103: #define xchg(a,b,type) { type t; t=a; a=b; b=t; } ! 104: xchg(ti->ti_dst, ti->ti_src, u_long); ! 105: xchg(ti->ti_dport, ti->ti_sport, u_short); ! 106: #undef xchg ! 107: tlen = 0; ! 108: } ! 109: ti->ti_next = ti->ti_prev = 0; ! 110: ti->ti_x1 = 0; ! 111: ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen)); ! 112: ti->ti_seq = htonl(seq); ! 113: ti->ti_ack = htonl(ack); ! 114: ti->ti_x2 = 0; ! 115: ti->ti_off = sizeof (struct tcphdr) >> 2; ! 116: ti->ti_flags = flags; ! 117: ti->ti_win = htons((u_short)win); ! 118: ti->ti_urp = 0; ! 119: ti->ti_src = htonl(ti->ti_src); ! 120: ti->ti_dst = htonl(ti->ti_dst); ! 121: ti->ti_sport = htons(ti->ti_sport); ! 122: ti->ti_dport = htons(ti->ti_dport); ! 123: ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + tlen); ! 124: ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + tlen; ! 125: ((struct ip *)ti)->ip_ttl = TCP_TTL; ! 126: ! 127: ti->ti_dst = ntohl(ti->ti_dst); ! 128: ti->ti_src = ntohl(ti->ti_src); ! 129: tcp_debug(ti, 1); ! 130: tcp_ldout(m); ! 131: } ! 132: ! 133: /* ! 134: * Create a new TCP control block, making an ! 135: * empty reassembly queue and hooking it to the argument ! 136: * protocol control block. ! 137: */ ! 138: struct tcpcb * ! 139: tcp_newtcpcb(so) ! 140: struct socket *so; ! 141: { ! 142: register struct tcpcb *tp; ! 143: extern struct tcpcb tcpcb[]; ! 144: ! 145: tp = &tcpcb[so->so_dev]; ! 146: if(tp->t_template) ! 147: (void) m_free(dtom(tp->t_template)); ! 148: bzero(tp, sizeof(struct tcpcb)); ! 149: tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; ! 150: /* ! 151: * If the default maximum IP packet size is 576 bytes ! 152: * and a standard IP header is 20 bytes, with a TCP ! 153: * header of 20 bytes plus the options necessary to ! 154: * upgrade it to something higher, then initialize the ! 155: * maximum segment size to 576 - (20 + 20 + 8 + slop). ! 156: */ ! 157: tp->t_maxseg = tcp_maxseg; /* satisfy the rest of the world */ ! 158: tp->t_flags = 0; /* sends options! */ ! 159: tp->t_socket = so; ! 160: so->so_tcpcb = tp; ! 161: return (tp); ! 162: } ! 163: ! 164: /* ! 165: * Drop a TCP connection. ! 166: * If connection is synchronized, ! 167: * then send a RST to peer. ! 168: */ ! 169: struct tcpcb * ! 170: tcp_drop(tp) ! 171: register struct tcpcb *tp; ! 172: { ! 173: ! 174: if (TCPS_HAVERCVDSYN(tp->t_state)) { ! 175: tp->t_state = TCPS_CLOSED; ! 176: (void) tcp_output(tp); ! 177: } ! 178: return (tcp_close(tp)); ! 179: } ! 180: ! 181: /* ! 182: * Close a TCP control block: ! 183: * discard all space held by the tcp ! 184: * discard internet protocol block ! 185: * wake up any sleepers ! 186: */ ! 187: struct tcpcb * ! 188: tcp_close(tp) ! 189: register struct tcpcb *tp; ! 190: { ! 191: register struct tcpiphdr *t; ! 192: struct socket *so = tp->t_socket; ! 193: register struct mbuf *m; ! 194: ! 195: if(!tp) ! 196: panic("tcp_close"); ! 197: t = tp->seg_next; ! 198: while (t != (struct tcpiphdr *)tp) { ! 199: t = (struct tcpiphdr *)t->ti_next; ! 200: m = dtom(t->ti_prev); ! 201: remque(t->ti_prev); ! 202: m_freem(m); ! 203: } ! 204: if (tp->t_template) ! 205: (void) m_free(dtom(tp->t_template)); ! 206: tp->t_template = 0; ! 207: if (tp->t_tcpopt) ! 208: (void) m_free(dtom(tp->t_tcpopt)); ! 209: tp->t_tcpopt = 0; ! 210: if (tp->t_ipopt) ! 211: (void) m_free(dtom(tp->t_ipopt)); ! 212: tp->t_ipopt = 0; ! 213: so->so_tcpcb = 0; ! 214: soisdisconnected(so); ! 215: return ((struct tcpcb *)0); ! 216: } ! 217: ! 218: /* ! 219: * For debugging save time event occurred, the direction of the message, ! 220: * and the tcp header. Then increment the pointer to the tcp ! 221: * debug queue. ! 222: */ ! 223: int Nbugarr=SIZDEBUG; ! 224: struct tcpdebug bugarr[SIZDEBUG]; /* buffer to store the debug info in */ ! 225: int tcpdbg_ind=0; /* index into bugarr at last entry */ ! 226: ! 227: tcp_debug(ti, code) ! 228: struct tcpiphdr *ti; ! 229: { ! 230: bugarr[tcpdbg_ind].stamp = time; ! 231: bugarr[tcpdbg_ind].inout = code; ! 232: bugarr[tcpdbg_ind].savhdr = ti->ti_t; ! 233: tcpdbg_ind = (tcpdbg_ind + 1) % SIZDEBUG; ! 234: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.