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