|
|
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.