1 | /*
|
---|
2 | tcp.c
|
---|
3 |
|
---|
4 | Copyright 1995 Philip Homburg
|
---|
5 | */
|
---|
6 |
|
---|
7 | #include "inet.h"
|
---|
8 | #include "buf.h"
|
---|
9 | #include "clock.h"
|
---|
10 | #include "event.h"
|
---|
11 | #include "type.h"
|
---|
12 |
|
---|
13 | #include "io.h"
|
---|
14 | #include "ip.h"
|
---|
15 | #include "sr.h"
|
---|
16 | #include "assert.h"
|
---|
17 | #include "rand256.h"
|
---|
18 | #include "tcp.h"
|
---|
19 | #include "tcp_int.h"
|
---|
20 |
|
---|
21 | THIS_FILE
|
---|
22 |
|
---|
23 | #define NOT_IMPLEMENTED 0
|
---|
24 |
|
---|
25 | PUBLIC tcp_port_t *tcp_port_table;
|
---|
26 | PUBLIC tcp_fd_t tcp_fd_table[TCP_FD_NR];
|
---|
27 | PUBLIC tcp_conn_t tcp_conn_table[TCP_CONN_NR];
|
---|
28 | PUBLIC sr_cancel_t tcp_cancel_f;
|
---|
29 |
|
---|
30 | FORWARD void tcp_main ARGS(( tcp_port_t *port ));
|
---|
31 | FORWARD int tcp_select ARGS(( int fd, unsigned operations ));
|
---|
32 | FORWARD acc_t *tcp_get_data ARGS(( int fd, size_t offset,
|
---|
33 | size_t count, int for_ioctl ));
|
---|
34 | FORWARD int tcp_put_data ARGS(( int fd, size_t offset,
|
---|
35 | acc_t *data, int for_ioctl ));
|
---|
36 | FORWARD void tcp_put_pkt ARGS(( int fd, acc_t *data, size_t datalen ));
|
---|
37 | FORWARD void read_ip_packets ARGS(( tcp_port_t *port ));
|
---|
38 | FORWARD int tcp_setconf ARGS(( tcp_fd_t *tcp_fd ));
|
---|
39 | FORWARD int tcp_setopt ARGS(( tcp_fd_t *tcp_fd ));
|
---|
40 | FORWARD int tcp_connect ARGS(( tcp_fd_t *tcp_fd ));
|
---|
41 | FORWARD int tcp_listen ARGS(( tcp_fd_t *tcp_fd, int do_listenq ));
|
---|
42 | FORWARD int tcp_acceptto ARGS(( tcp_fd_t *tcp_fd ));
|
---|
43 | FORWARD tcpport_t find_unused_port ARGS(( int fd ));
|
---|
44 | FORWARD int is_unused_port ARGS(( Tcpport_t port ));
|
---|
45 | FORWARD int reply_thr_put ARGS(( tcp_fd_t *tcp_fd, int reply,
|
---|
46 | int for_ioctl ));
|
---|
47 | FORWARD void reply_thr_get ARGS(( tcp_fd_t *tcp_fd, int reply,
|
---|
48 | int for_ioctl ));
|
---|
49 | FORWARD tcp_conn_t *find_conn_entry ARGS(( Tcpport_t locport,
|
---|
50 | ipaddr_t locaddr, Tcpport_t remport, ipaddr_t readaddr ));
|
---|
51 | FORWARD tcp_conn_t *find_empty_conn ARGS(( void ));
|
---|
52 | FORWARD tcp_conn_t *find_best_conn ARGS(( ip_hdr_t *ip_hdr,
|
---|
53 | tcp_hdr_t *tcp_hdr ));
|
---|
54 | FORWARD tcp_conn_t *new_conn_for_queue ARGS(( tcp_fd_t *tcp_fd ));
|
---|
55 | FORWARD int maybe_listen ARGS(( ipaddr_t locaddr, Tcpport_t locport,
|
---|
56 | ipaddr_t remaddr, Tcpport_t remport ));
|
---|
57 | FORWARD int tcp_su4connect ARGS(( tcp_fd_t *tcp_fd ));
|
---|
58 | FORWARD void tcp_buffree ARGS(( int priority ));
|
---|
59 | #ifdef BUF_CONSISTENCY_CHECK
|
---|
60 | FORWARD void tcp_bufcheck ARGS(( void ));
|
---|
61 | #endif
|
---|
62 | FORWARD void tcp_setup_conn ARGS(( tcp_port_t *tcp_port,
|
---|
63 | tcp_conn_t *tcp_conn ));
|
---|
64 | FORWARD u32_t tcp_rand32 ARGS(( void ));
|
---|
65 |
|
---|
66 | PUBLIC void tcp_prep()
|
---|
67 | {
|
---|
68 | tcp_port_table= alloc(tcp_conf_nr * sizeof(tcp_port_table[0]));
|
---|
69 | }
|
---|
70 |
|
---|
71 | PUBLIC void tcp_init()
|
---|
72 | {
|
---|
73 | int i, j, k, ifno;
|
---|
74 | tcp_fd_t *tcp_fd;
|
---|
75 | tcp_port_t *tcp_port;
|
---|
76 | tcp_conn_t *tcp_conn;
|
---|
77 |
|
---|
78 | assert (BUF_S >= sizeof(struct nwio_ipopt));
|
---|
79 | assert (BUF_S >= sizeof(struct nwio_ipconf));
|
---|
80 | assert (BUF_S >= sizeof(struct nwio_tcpconf));
|
---|
81 | assert (BUF_S >= IP_MAX_HDR_SIZE + TCP_MAX_HDR_SIZE);
|
---|
82 |
|
---|
83 | for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++, tcp_fd++)
|
---|
84 | {
|
---|
85 | tcp_fd->tf_flags= TFF_EMPTY;
|
---|
86 | }
|
---|
87 |
|
---|
88 | for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
|
---|
89 | tcp_fd++)
|
---|
90 | {
|
---|
91 | tcp_conn->tc_flags= TCF_EMPTY;
|
---|
92 | tcp_conn->tc_busy= 0;
|
---|
93 | }
|
---|
94 |
|
---|
95 | #ifndef BUF_CONSISTENCY_CHECK
|
---|
96 | bf_logon(tcp_buffree);
|
---|
97 | #else
|
---|
98 | bf_logon(tcp_buffree, tcp_bufcheck);
|
---|
99 | #endif
|
---|
100 |
|
---|
101 | for (i=0, tcp_port= tcp_port_table; i<tcp_conf_nr; i++, tcp_port++)
|
---|
102 | {
|
---|
103 | tcp_port->tp_ipdev= tcp_conf[i].tc_port;
|
---|
104 |
|
---|
105 | tcp_port->tp_flags= TPF_EMPTY;
|
---|
106 | tcp_port->tp_state= TPS_EMPTY;
|
---|
107 | tcp_port->tp_snd_head= NULL;
|
---|
108 | tcp_port->tp_snd_tail= NULL;
|
---|
109 | ev_init(&tcp_port->tp_snd_event);
|
---|
110 | for (j= 0; j<TCP_CONN_HASH_NR; j++)
|
---|
111 | {
|
---|
112 | for (k= 0; k<4; k++)
|
---|
113 | {
|
---|
114 | tcp_port->tp_conn_hash[j][k]=
|
---|
115 | &tcp_conn_table[0];
|
---|
116 | }
|
---|
117 | }
|
---|
118 |
|
---|
119 | ifno= ip_conf[tcp_port->tp_ipdev].ic_ifno;
|
---|
120 | sr_add_minor(if2minor(ifno, TCP_DEV_OFF),
|
---|
121 | i, tcp_open, tcp_close, tcp_read,
|
---|
122 | tcp_write, tcp_ioctl, tcp_cancel, tcp_select);
|
---|
123 |
|
---|
124 | tcp_main(tcp_port);
|
---|
125 | }
|
---|
126 | tcp_cancel_f= tcp_cancel;
|
---|
127 | }
|
---|
128 |
|
---|
129 | PRIVATE void tcp_main(tcp_port)
|
---|
130 | tcp_port_t *tcp_port;
|
---|
131 | {
|
---|
132 | int result, i;
|
---|
133 | tcp_conn_t *tcp_conn;
|
---|
134 | tcp_fd_t *tcp_fd;
|
---|
135 |
|
---|
136 | switch (tcp_port->tp_state)
|
---|
137 | {
|
---|
138 | case TPS_EMPTY:
|
---|
139 | tcp_port->tp_state= TPS_SETPROTO;
|
---|
140 | tcp_port->tp_ipfd= ip_open(tcp_port->tp_ipdev,
|
---|
141 | tcp_port->tp_ipdev, tcp_get_data,
|
---|
142 | tcp_put_data, tcp_put_pkt, 0 /* no select_res */);
|
---|
143 | if (tcp_port->tp_ipfd < 0)
|
---|
144 | {
|
---|
145 | tcp_port->tp_state= TPS_ERROR;
|
---|
146 | DBLOCK(1, printf("%s, %d: unable to open ip port\n",
|
---|
147 | __FILE__, __LINE__));
|
---|
148 | return;
|
---|
149 | }
|
---|
150 |
|
---|
151 | result= ip_ioctl(tcp_port->tp_ipfd, NWIOSIPOPT);
|
---|
152 | if (result == NW_SUSPEND)
|
---|
153 | tcp_port->tp_flags |= TPF_SUSPEND;
|
---|
154 | if (result < 0)
|
---|
155 | {
|
---|
156 | return;
|
---|
157 | }
|
---|
158 | if (tcp_port->tp_state != TPS_GETCONF)
|
---|
159 | return;
|
---|
160 | /* drops through */
|
---|
161 | case TPS_GETCONF:
|
---|
162 | tcp_port->tp_flags &= ~TPF_SUSPEND;
|
---|
163 |
|
---|
164 | result= ip_ioctl(tcp_port->tp_ipfd, NWIOGIPCONF);
|
---|
165 | if (result == NW_SUSPEND)
|
---|
166 | tcp_port->tp_flags |= TPF_SUSPEND;
|
---|
167 | if (result < 0)
|
---|
168 | {
|
---|
169 | return;
|
---|
170 | }
|
---|
171 | if (tcp_port->tp_state != TPS_MAIN)
|
---|
172 | return;
|
---|
173 | /* drops through */
|
---|
174 | case TPS_MAIN:
|
---|
175 | tcp_port->tp_flags &= ~TPF_SUSPEND;
|
---|
176 | tcp_port->tp_pack= 0;
|
---|
177 |
|
---|
178 | tcp_conn= &tcp_conn_table[tcp_port->tp_ipdev];
|
---|
179 | tcp_conn->tc_flags= TCF_INUSE;
|
---|
180 | assert(!tcp_conn->tc_busy);
|
---|
181 | tcp_conn->tc_locport= 0;
|
---|
182 | tcp_conn->tc_locaddr= tcp_port->tp_ipaddr;
|
---|
183 | tcp_conn->tc_remport= 0;
|
---|
184 | tcp_conn->tc_remaddr= 0;
|
---|
185 | tcp_conn->tc_state= TCS_CLOSED;
|
---|
186 | tcp_conn->tc_fd= 0;
|
---|
187 | tcp_conn->tc_connInprogress= 0;
|
---|
188 | tcp_conn->tc_orglisten= FALSE;
|
---|
189 | tcp_conn->tc_senddis= 0;
|
---|
190 | tcp_conn->tc_ISS= 0;
|
---|
191 | tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
|
---|
192 | tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
|
---|
193 | tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS;
|
---|
194 | tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;
|
---|
195 | tcp_conn->tc_IRS= 0;
|
---|
196 | tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS;
|
---|
197 | tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS;
|
---|
198 | tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS;
|
---|
199 | tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
|
---|
200 | tcp_conn->tc_port= tcp_port;
|
---|
201 | tcp_conn->tc_rcvd_data= NULL;
|
---|
202 | tcp_conn->tc_adv_data= NULL;
|
---|
203 | tcp_conn->tc_send_data= 0;
|
---|
204 | tcp_conn->tc_remipopt= NULL;
|
---|
205 | tcp_conn->tc_tcpopt= NULL;
|
---|
206 | tcp_conn->tc_frag2send= 0;
|
---|
207 | tcp_conn->tc_tos= TCP_DEF_TOS;
|
---|
208 | tcp_conn->tc_ttl= IP_MAX_TTL;
|
---|
209 | tcp_conn->tc_rcv_wnd= TCP_MAX_RCV_WND_SIZE;
|
---|
210 | tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
|
---|
211 | tcp_conn->tc_stt= 0;
|
---|
212 | tcp_conn->tc_0wnd_to= 0;
|
---|
213 | tcp_conn->tc_artt= TCP_DEF_RTT*TCP_RTT_SCALE;
|
---|
214 | tcp_conn->tc_drtt= 0;
|
---|
215 | tcp_conn->tc_rtt= TCP_DEF_RTT;
|
---|
216 | tcp_conn->tc_max_mtu= tcp_port->tp_mtu;
|
---|
217 | tcp_conn->tc_mtu= tcp_conn->tc_max_mtu;
|
---|
218 | tcp_conn->tc_mtutim= 0;
|
---|
219 | tcp_conn->tc_error= NW_OK;
|
---|
220 | tcp_conn->tc_snd_wnd= TCP_MAX_SND_WND_SIZE;
|
---|
221 | tcp_conn->tc_snd_cinc=
|
---|
222 | (long)TCP_DEF_MSS*TCP_DEF_MSS/TCP_MAX_SND_WND_SIZE+1;
|
---|
223 |
|
---|
224 | tcp_conn->tc_rt_time= 0;
|
---|
225 | tcp_conn->tc_rt_seq= 0;
|
---|
226 | tcp_conn->tc_rt_threshold= tcp_conn->tc_ISS;
|
---|
227 |
|
---|
228 | for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++,
|
---|
229 | tcp_fd++)
|
---|
230 | {
|
---|
231 | if (!(tcp_fd->tf_flags & TFF_INUSE))
|
---|
232 | continue;
|
---|
233 | if (tcp_fd->tf_port != tcp_port)
|
---|
234 | continue;
|
---|
235 | if (tcp_fd->tf_flags & TFF_IOC_INIT_SP)
|
---|
236 | {
|
---|
237 | tcp_fd->tf_flags &= ~TFF_IOC_INIT_SP;
|
---|
238 | tcp_ioctl(i, tcp_fd->tf_ioreq);
|
---|
239 | }
|
---|
240 | }
|
---|
241 | read_ip_packets(tcp_port);
|
---|
242 | return;
|
---|
243 |
|
---|
244 | default:
|
---|
245 | ip_panic(( "unknown state" ));
|
---|
246 | break;
|
---|
247 | }
|
---|
248 | }
|
---|
249 |
|
---|
250 | PRIVATE int tcp_select(fd, operations)
|
---|
251 | int fd;
|
---|
252 | unsigned operations;
|
---|
253 | {
|
---|
254 | int i;
|
---|
255 | unsigned resops;
|
---|
256 | tcp_fd_t *tcp_fd;
|
---|
257 | tcp_conn_t *tcp_conn;
|
---|
258 |
|
---|
259 | tcp_fd= &tcp_fd_table[fd];
|
---|
260 | assert (tcp_fd->tf_flags & TFF_INUSE);
|
---|
261 |
|
---|
262 | resops= 0;
|
---|
263 | if (tcp_fd->tf_flags & TFF_LISTENQ)
|
---|
264 | {
|
---|
265 | /* Special case for LISTENQ */
|
---|
266 | if (operations & SR_SELECT_READ)
|
---|
267 | {
|
---|
268 | for (i= 0; i<TFL_LISTEN_MAX; i++)
|
---|
269 | {
|
---|
270 | if (tcp_fd->tf_listenq[i] == NULL)
|
---|
271 | continue;
|
---|
272 | if (tcp_fd->tf_listenq[i]->tc_connInprogress
|
---|
273 | == 0)
|
---|
274 | {
|
---|
275 | break;
|
---|
276 | }
|
---|
277 | }
|
---|
278 | if (i >= TFL_LISTEN_MAX)
|
---|
279 | tcp_fd->tf_flags |= TFF_SEL_READ;
|
---|
280 | else
|
---|
281 | resops |= SR_SELECT_READ;
|
---|
282 | }
|
---|
283 | if (operations & SR_SELECT_WRITE)
|
---|
284 | {
|
---|
285 | /* We can't handles writes. Just return the error
|
---|
286 | * when the user tries to write.
|
---|
287 | */
|
---|
288 | resops |= SR_SELECT_WRITE;
|
---|
289 | }
|
---|
290 | return resops;
|
---|
291 | }
|
---|
292 | if (tcp_fd->tf_flags & TFF_CONNECTING)
|
---|
293 | {
|
---|
294 | /* Special case for CONNECTING */
|
---|
295 | if (operations & SR_SELECT_WRITE)
|
---|
296 | tcp_fd->tf_flags |= TFF_SEL_WRITE;
|
---|
297 | return 0;
|
---|
298 | }
|
---|
299 | if (operations & SR_SELECT_READ)
|
---|
300 | {
|
---|
301 | tcp_conn= tcp_fd->tf_conn;
|
---|
302 |
|
---|
303 | if (!(tcp_fd->tf_flags & TFF_CONNECTED))
|
---|
304 | {
|
---|
305 | /* We can't handle reads until a connection has been
|
---|
306 | * established. Return the error when the user tries
|
---|
307 | * to read.
|
---|
308 | */
|
---|
309 | resops |= SR_SELECT_READ;
|
---|
310 | }
|
---|
311 | else if (tcp_conn->tc_state == TCS_CLOSED ||
|
---|
312 | tcp_sel_read(tcp_conn))
|
---|
313 | {
|
---|
314 | resops |= SR_SELECT_READ;
|
---|
315 | }
|
---|
316 | else if (!(operations & SR_SELECT_POLL))
|
---|
317 | tcp_fd->tf_flags |= TFF_SEL_READ;
|
---|
318 | }
|
---|
319 | if (operations & SR_SELECT_WRITE)
|
---|
320 | {
|
---|
321 | tcp_conn= tcp_fd->tf_conn;
|
---|
322 | if (!(tcp_fd->tf_flags & TFF_CONNECTED))
|
---|
323 | {
|
---|
324 | /* We can't handle writes until a connection has been
|
---|
325 | * established. Return the error when the user tries
|
---|
326 | * to write.
|
---|
327 | */
|
---|
328 | resops |= SR_SELECT_WRITE;
|
---|
329 | }
|
---|
330 | else if (tcp_conn->tc_state == TCS_CLOSED ||
|
---|
331 | tcp_conn->tc_flags & TCF_FIN_SENT ||
|
---|
332 | tcp_sel_write(tcp_conn))
|
---|
333 | {
|
---|
334 | resops |= SR_SELECT_WRITE;
|
---|
335 | }
|
---|
336 | else if (!(operations & SR_SELECT_POLL))
|
---|
337 | tcp_fd->tf_flags |= TFF_SEL_WRITE;
|
---|
338 | }
|
---|
339 | if (operations & SR_SELECT_EXCEPTION)
|
---|
340 | {
|
---|
341 | /* Should add code for exceptions */
|
---|
342 | }
|
---|
343 | return resops;
|
---|
344 | }
|
---|
345 |
|
---|
346 | PRIVATE acc_t *tcp_get_data (port, offset, count, for_ioctl)
|
---|
347 | int port;
|
---|
348 | size_t offset;
|
---|
349 | size_t count;
|
---|
350 | int for_ioctl;
|
---|
351 | {
|
---|
352 | tcp_port_t *tcp_port;
|
---|
353 | int result;
|
---|
354 |
|
---|
355 | tcp_port= &tcp_port_table[port];
|
---|
356 |
|
---|
357 | switch (tcp_port->tp_state)
|
---|
358 | {
|
---|
359 | case TPS_SETPROTO:
|
---|
360 | if (!count)
|
---|
361 | {
|
---|
362 | result= (int)offset;
|
---|
363 | if (result<0)
|
---|
364 | {
|
---|
365 | tcp_port->tp_state= TPS_ERROR;
|
---|
366 | break;
|
---|
367 | }
|
---|
368 | tcp_port->tp_state= TPS_GETCONF;
|
---|
369 | if (tcp_port->tp_flags & TPF_SUSPEND)
|
---|
370 | tcp_main(tcp_port);
|
---|
371 | return NW_OK;
|
---|
372 | }
|
---|
373 | assert (!offset);
|
---|
374 | assert (count == sizeof(struct nwio_ipopt));
|
---|
375 | {
|
---|
376 | struct nwio_ipopt *ipopt;
|
---|
377 | acc_t *acc;
|
---|
378 |
|
---|
379 | acc= bf_memreq(sizeof(*ipopt));
|
---|
380 | ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);
|
---|
381 | ipopt->nwio_flags= NWIO_COPY |
|
---|
382 | NWIO_EN_LOC | NWIO_DI_BROAD |
|
---|
383 | NWIO_REMANY | NWIO_PROTOSPEC |
|
---|
384 | NWIO_HDR_O_ANY | NWIO_RWDATALL;
|
---|
385 | ipopt->nwio_proto= IPPROTO_TCP;
|
---|
386 | return acc;
|
---|
387 | }
|
---|
388 | case TPS_MAIN:
|
---|
389 | assert(tcp_port->tp_flags & TPF_WRITE_IP);
|
---|
390 | if (!count)
|
---|
391 | {
|
---|
392 | result= (int)offset;
|
---|
393 | if (result<0)
|
---|
394 | {
|
---|
395 | if (result == EDSTNOTRCH)
|
---|
396 | {
|
---|
397 | if (tcp_port->tp_snd_head)
|
---|
398 | {
|
---|
399 | tcp_notreach(tcp_port->
|
---|
400 | tp_snd_head);
|
---|
401 | }
|
---|
402 | }
|
---|
403 | else
|
---|
404 | {
|
---|
405 | ip_warning((
|
---|
406 | "ip_write failed with error: %d\n",
|
---|
407 | result ));
|
---|
408 | }
|
---|
409 | }
|
---|
410 | assert (tcp_port->tp_pack);
|
---|
411 | bf_afree (tcp_port->tp_pack);
|
---|
412 | tcp_port->tp_pack= 0;
|
---|
413 |
|
---|
414 | if (tcp_port->tp_flags & TPF_WRITE_SP)
|
---|
415 | {
|
---|
416 | tcp_port->tp_flags &= ~(TPF_WRITE_SP|
|
---|
417 | TPF_WRITE_IP);
|
---|
418 | if (tcp_port->tp_snd_head)
|
---|
419 | tcp_port_write(tcp_port);
|
---|
420 | }
|
---|
421 | else
|
---|
422 | tcp_port->tp_flags &= ~TPF_WRITE_IP;
|
---|
423 | }
|
---|
424 | else
|
---|
425 | {
|
---|
426 | return bf_cut (tcp_port->tp_pack, offset,
|
---|
427 | count);
|
---|
428 | }
|
---|
429 | break;
|
---|
430 | default:
|
---|
431 | printf("tcp_get_data(%d, 0x%x, 0x%x) called but tp_state= 0x%x\n",
|
---|
432 | port, offset, count, tcp_port->tp_state);
|
---|
433 | break;
|
---|
434 | }
|
---|
435 | return NW_OK;
|
---|
436 | }
|
---|
437 |
|
---|
438 | PRIVATE int tcp_put_data (fd, offset, data, for_ioctl)
|
---|
439 | int fd;
|
---|
440 | size_t offset;
|
---|
441 | acc_t *data;
|
---|
442 | int for_ioctl;
|
---|
443 | {
|
---|
444 | tcp_port_t *tcp_port;
|
---|
445 | int result;
|
---|
446 |
|
---|
447 | tcp_port= &tcp_port_table[fd];
|
---|
448 |
|
---|
449 | switch (tcp_port->tp_state)
|
---|
450 | {
|
---|
451 | case TPS_GETCONF:
|
---|
452 | if (!data)
|
---|
453 | {
|
---|
454 | result= (int)offset;
|
---|
455 | if (result<0)
|
---|
456 | {
|
---|
457 | tcp_port->tp_state= TPS_ERROR;
|
---|
458 | return NW_OK;
|
---|
459 | }
|
---|
460 | tcp_port->tp_state= TPS_MAIN;
|
---|
461 | if (tcp_port->tp_flags & TPF_SUSPEND)
|
---|
462 | tcp_main(tcp_port);
|
---|
463 | }
|
---|
464 | else
|
---|
465 | {
|
---|
466 | struct nwio_ipconf *ipconf;
|
---|
467 |
|
---|
468 | data= bf_packIffLess(data, sizeof(*ipconf));
|
---|
469 | ipconf= (struct nwio_ipconf *)ptr2acc_data(data);
|
---|
470 | assert (ipconf->nwic_flags & NWIC_IPADDR_SET);
|
---|
471 | tcp_port->tp_ipaddr= ipconf->nwic_ipaddr;
|
---|
472 | tcp_port->tp_subnetmask= ipconf->nwic_netmask;
|
---|
473 | tcp_port->tp_mtu= ipconf->nwic_mtu;
|
---|
474 | bf_afree(data);
|
---|
475 | }
|
---|
476 | break;
|
---|
477 | case TPS_MAIN:
|
---|
478 | assert(tcp_port->tp_flags & TPF_READ_IP);
|
---|
479 | if (!data)
|
---|
480 | {
|
---|
481 | result= (int)offset;
|
---|
482 | if (result<0)
|
---|
483 | ip_panic(( "ip_read() failed" ));
|
---|
484 |
|
---|
485 | if (tcp_port->tp_flags & TPF_READ_SP)
|
---|
486 | {
|
---|
487 | tcp_port->tp_flags &= ~(TPF_READ_SP|
|
---|
488 | TPF_READ_IP);
|
---|
489 | read_ip_packets(tcp_port);
|
---|
490 | }
|
---|
491 | else
|
---|
492 | tcp_port->tp_flags &= ~TPF_READ_IP;
|
---|
493 | }
|
---|
494 | else
|
---|
495 | {
|
---|
496 | assert(!offset);
|
---|
497 | /* this is an invalid assertion but ip sends
|
---|
498 | * only whole datagrams up */
|
---|
499 | tcp_put_pkt(fd, data, bf_bufsize(data));
|
---|
500 | }
|
---|
501 | break;
|
---|
502 | default:
|
---|
503 | printf(
|
---|
504 | "tcp_put_data(%d, 0x%x, %p) called but tp_state= 0x%x\n",
|
---|
505 | fd, offset, data, tcp_port->tp_state);
|
---|
506 | break;
|
---|
507 | }
|
---|
508 | return NW_OK;
|
---|
509 | }
|
---|
510 |
|
---|
511 | /*
|
---|
512 | tcp_put_pkt
|
---|
513 | */
|
---|
514 |
|
---|
515 | PRIVATE void tcp_put_pkt(fd, data, datalen)
|
---|
516 | int fd;
|
---|
517 | acc_t *data;
|
---|
518 | size_t datalen;
|
---|
519 | {
|
---|
520 | tcp_port_t *tcp_port;
|
---|
521 | tcp_conn_t *tcp_conn, **conn_p;
|
---|
522 | ip_hdr_t *ip_hdr;
|
---|
523 | tcp_hdr_t *tcp_hdr;
|
---|
524 | acc_t *ip_pack, *tcp_pack;
|
---|
525 | size_t ip_datalen, tcp_datalen, ip_hdr_len, tcp_hdr_len;
|
---|
526 | u16_t sum, mtu;
|
---|
527 | u32_t bits;
|
---|
528 | int i, hash;
|
---|
529 | ipaddr_t srcaddr, dstaddr, ipaddr, mask;
|
---|
530 | tcpport_t srcport, dstport;
|
---|
531 |
|
---|
532 | tcp_port= &tcp_port_table[fd];
|
---|
533 |
|
---|
534 | /* Extract the IP header. */
|
---|
535 | ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
|
---|
536 | ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
|
---|
537 | ip_datalen= datalen - ip_hdr_len;
|
---|
538 | if (ip_datalen == 0)
|
---|
539 | {
|
---|
540 | if (ip_hdr->ih_proto == 0)
|
---|
541 | {
|
---|
542 | /* IP layer reports new IP address */
|
---|
543 | ipaddr= ip_hdr->ih_src;
|
---|
544 | mask= ip_hdr->ih_dst;
|
---|
545 | mtu= ntohs(ip_hdr->ih_length);
|
---|
546 | tcp_port->tp_ipaddr= ipaddr;
|
---|
547 | tcp_port->tp_subnetmask= mask;
|
---|
548 | tcp_port->tp_mtu= mtu;
|
---|
549 | DBLOCK(1, printf("tcp_put_pkt: using address ");
|
---|
550 | writeIpAddr(ipaddr);
|
---|
551 | printf(", netmask ");
|
---|
552 | writeIpAddr(mask);
|
---|
553 | printf(", mtu %u\n", mtu));
|
---|
554 | for (i= 0, tcp_conn= tcp_conn_table+i;
|
---|
555 | i<TCP_CONN_NR; i++, tcp_conn++)
|
---|
556 | {
|
---|
557 | if (!(tcp_conn->tc_flags & TCF_INUSE))
|
---|
558 | continue;
|
---|
559 | if (tcp_conn->tc_port != tcp_port)
|
---|
560 | continue;
|
---|
561 | tcp_conn->tc_locaddr= ipaddr;
|
---|
562 | }
|
---|
563 | }
|
---|
564 | else
|
---|
565 | DBLOCK(1, printf("tcp_put_pkt: no TCP header\n"));
|
---|
566 | bf_afree(data);
|
---|
567 | return;
|
---|
568 | }
|
---|
569 | data->acc_linkC++;
|
---|
570 | ip_pack= data;
|
---|
571 | ip_pack= bf_align(ip_pack, ip_hdr_len, 4);
|
---|
572 | ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);
|
---|
573 | data= bf_delhead(data, ip_hdr_len);
|
---|
574 |
|
---|
575 | /* Compute the checksum */
|
---|
576 | sum= tcp_pack_oneCsum(ip_hdr, data);
|
---|
577 |
|
---|
578 | /* Extract the TCP header */
|
---|
579 | if (ip_datalen < TCP_MIN_HDR_SIZE)
|
---|
580 | {
|
---|
581 | DBLOCK(1, printf("truncated TCP header\n"));
|
---|
582 | bf_afree(ip_pack);
|
---|
583 | bf_afree(data);
|
---|
584 | return;
|
---|
585 | }
|
---|
586 | data= bf_packIffLess(data, TCP_MIN_HDR_SIZE);
|
---|
587 | tcp_hdr= (tcp_hdr_t *)ptr2acc_data(data);
|
---|
588 | tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
|
---|
589 | /* actualy (>> 4) << 2 */
|
---|
590 | if (ip_datalen < tcp_hdr_len || tcp_hdr_len < TCP_MIN_HDR_SIZE)
|
---|
591 | {
|
---|
592 | if (tcp_hdr_len < TCP_MIN_HDR_SIZE)
|
---|
593 | {
|
---|
594 | DBLOCK(1, printf("strange tcp header length %d\n",
|
---|
595 | tcp_hdr_len));
|
---|
596 | }
|
---|
597 | else
|
---|
598 | {
|
---|
599 | DBLOCK(1, printf("truncated TCP header\n"));
|
---|
600 | }
|
---|
601 | bf_afree(ip_pack);
|
---|
602 | bf_afree(data);
|
---|
603 | return;
|
---|
604 | }
|
---|
605 | data->acc_linkC++;
|
---|
606 | tcp_pack= data;
|
---|
607 | tcp_pack= bf_align(tcp_pack, tcp_hdr_len, 4);
|
---|
608 | tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack);
|
---|
609 | if (ip_datalen == tcp_hdr_len)
|
---|
610 | {
|
---|
611 | bf_afree(data);
|
---|
612 | data= NULL;
|
---|
613 | }
|
---|
614 | else
|
---|
615 | data= bf_delhead(data, tcp_hdr_len);
|
---|
616 | tcp_datalen= ip_datalen-tcp_hdr_len;
|
---|
617 |
|
---|
618 | if ((u16_t)~sum)
|
---|
619 | {
|
---|
620 | DBLOCK(1, printf("checksum error in tcp packet\n");
|
---|
621 | printf("tcp_pack_oneCsum(...)= 0x%x length= %d\n",
|
---|
622 | (u16_t)~sum, tcp_datalen);
|
---|
623 | printf("src ip_addr= "); writeIpAddr(ip_hdr->ih_src);
|
---|
624 | printf("\n"));
|
---|
625 | bf_afree(ip_pack);
|
---|
626 | bf_afree(tcp_pack);
|
---|
627 | bf_afree(data);
|
---|
628 | return;
|
---|
629 | }
|
---|
630 |
|
---|
631 | srcaddr= ip_hdr->ih_src;
|
---|
632 | dstaddr= ip_hdr->ih_dst;
|
---|
633 | srcport= tcp_hdr->th_srcport;
|
---|
634 | dstport= tcp_hdr->th_dstport;
|
---|
635 | bits= srcaddr ^ dstaddr ^ srcport ^ dstport;
|
---|
636 | bits= (bits >> 16) ^ bits;
|
---|
637 | bits= (bits >> 8) ^ bits;
|
---|
638 | hash= ((bits >> TCP_CONN_HASH_SHIFT) ^ bits) & (TCP_CONN_HASH_NR-1);
|
---|
639 | conn_p= tcp_port->tp_conn_hash[hash];
|
---|
640 | if (conn_p[0]->tc_locport == dstport &&
|
---|
641 | conn_p[0]->tc_remport == srcport &&
|
---|
642 | conn_p[0]->tc_remaddr == srcaddr &&
|
---|
643 | conn_p[0]->tc_locaddr == dstaddr)
|
---|
644 | {
|
---|
645 | tcp_conn= conn_p[0];
|
---|
646 | }
|
---|
647 | else if (conn_p[1]->tc_locport == dstport &&
|
---|
648 | conn_p[1]->tc_remport == srcport &&
|
---|
649 | conn_p[1]->tc_remaddr == srcaddr &&
|
---|
650 | conn_p[1]->tc_locaddr == dstaddr)
|
---|
651 | {
|
---|
652 | tcp_conn= conn_p[1];
|
---|
653 | conn_p[1]= conn_p[0];
|
---|
654 | conn_p[0]= tcp_conn;
|
---|
655 | }
|
---|
656 | else if (conn_p[2]->tc_locport == dstport &&
|
---|
657 | conn_p[2]->tc_remport == srcport &&
|
---|
658 | conn_p[2]->tc_remaddr == srcaddr &&
|
---|
659 | conn_p[2]->tc_locaddr == dstaddr)
|
---|
660 | {
|
---|
661 | tcp_conn= conn_p[2];
|
---|
662 | conn_p[2]= conn_p[1];
|
---|
663 | conn_p[1]= conn_p[0];
|
---|
664 | conn_p[0]= tcp_conn;
|
---|
665 | }
|
---|
666 | else if (conn_p[3]->tc_locport == dstport &&
|
---|
667 | conn_p[3]->tc_remport == srcport &&
|
---|
668 | conn_p[3]->tc_remaddr == srcaddr &&
|
---|
669 | conn_p[3]->tc_locaddr == dstaddr)
|
---|
670 | {
|
---|
671 | tcp_conn= conn_p[3];
|
---|
672 | conn_p[3]= conn_p[2];
|
---|
673 | conn_p[2]= conn_p[1];
|
---|
674 | conn_p[1]= conn_p[0];
|
---|
675 | conn_p[0]= tcp_conn;
|
---|
676 | }
|
---|
677 | else
|
---|
678 | tcp_conn= NULL;
|
---|
679 | if ((tcp_conn != NULL && tcp_conn->tc_state == TCS_CLOSED) ||
|
---|
680 | (tcp_hdr->th_flags & THF_SYN))
|
---|
681 | {
|
---|
682 | tcp_conn= NULL;
|
---|
683 | }
|
---|
684 |
|
---|
685 | if (tcp_conn == NULL)
|
---|
686 | {
|
---|
687 | tcp_conn= find_best_conn(ip_hdr, tcp_hdr);
|
---|
688 | if (!tcp_conn)
|
---|
689 | {
|
---|
690 | /* listen backlog hack */
|
---|
691 | bf_afree(ip_pack);
|
---|
692 | bf_afree(tcp_pack);
|
---|
693 | bf_afree(data);
|
---|
694 | return;
|
---|
695 | }
|
---|
696 | if (tcp_conn->tc_state != TCS_CLOSED)
|
---|
697 | {
|
---|
698 | conn_p[3]= conn_p[2];
|
---|
699 | conn_p[2]= conn_p[1];
|
---|
700 | conn_p[1]= conn_p[0];
|
---|
701 | conn_p[0]= tcp_conn;
|
---|
702 | }
|
---|
703 | }
|
---|
704 | assert(tcp_conn->tc_busy == 0);
|
---|
705 | tcp_conn->tc_busy++;
|
---|
706 | tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, data, tcp_datalen);
|
---|
707 | tcp_conn->tc_busy--;
|
---|
708 | bf_afree(ip_pack);
|
---|
709 | bf_afree(tcp_pack);
|
---|
710 | }
|
---|
711 |
|
---|
712 |
|
---|
713 | PUBLIC int tcp_open (port, srfd, get_userdata, put_userdata, put_pkt,
|
---|
714 | select_res)
|
---|
715 | int port;
|
---|
716 | int srfd;
|
---|
717 | get_userdata_t get_userdata;
|
---|
718 | put_userdata_t put_userdata;
|
---|
719 | put_pkt_t put_pkt;
|
---|
720 | select_res_t select_res;
|
---|
721 | {
|
---|
722 | int i, j;
|
---|
723 |
|
---|
724 | tcp_fd_t *tcp_fd;
|
---|
725 |
|
---|
726 | for (i=0; i<TCP_FD_NR && (tcp_fd_table[i].tf_flags & TFF_INUSE);
|
---|
727 | i++);
|
---|
728 | if (i>=TCP_FD_NR)
|
---|
729 | {
|
---|
730 | return EAGAIN;
|
---|
731 | }
|
---|
732 |
|
---|
733 | tcp_fd= &tcp_fd_table[i];
|
---|
734 |
|
---|
735 | tcp_fd->tf_flags= TFF_INUSE;
|
---|
736 | tcp_fd->tf_flags |= TFF_PUSH_DATA;
|
---|
737 |
|
---|
738 | tcp_fd->tf_port= &tcp_port_table[port];
|
---|
739 | tcp_fd->tf_srfd= srfd;
|
---|
740 | tcp_fd->tf_tcpconf.nwtc_flags= TCP_DEF_CONF;
|
---|
741 | tcp_fd->tf_tcpconf.nwtc_remaddr= 0;
|
---|
742 | tcp_fd->tf_tcpconf.nwtc_remport= 0;
|
---|
743 | tcp_fd->tf_tcpopt.nwto_flags= TCP_DEF_OPT;
|
---|
744 | tcp_fd->tf_get_userdata= get_userdata;
|
---|
745 | tcp_fd->tf_put_userdata= put_userdata;
|
---|
746 | tcp_fd->tf_select_res= select_res;
|
---|
747 | tcp_fd->tf_conn= 0;
|
---|
748 | tcp_fd->tf_error= 0;
|
---|
749 | for (j= 0; j<TFL_LISTEN_MAX; j++)
|
---|
750 | tcp_fd->tf_listenq[j]= NULL;
|
---|
751 | return i;
|
---|
752 | }
|
---|
753 |
|
---|
754 | /*
|
---|
755 | tcp_ioctl
|
---|
756 | */
|
---|
757 | PUBLIC int tcp_ioctl (fd, req)
|
---|
758 | int fd;
|
---|
759 | ioreq_t req;
|
---|
760 | {
|
---|
761 | tcp_fd_t *tcp_fd;
|
---|
762 | tcp_port_t *tcp_port;
|
---|
763 | tcp_conn_t *tcp_conn;
|
---|
764 | nwio_tcpconf_t *tcp_conf;
|
---|
765 | nwio_tcpopt_t *tcp_opt;
|
---|
766 | tcp_cookie_t *cookiep;
|
---|
767 | acc_t *acc, *conf_acc, *opt_acc;
|
---|
768 | int result, *bytesp;
|
---|
769 | u8_t rndbits[RAND256_BUFSIZE];
|
---|
770 |
|
---|
771 | tcp_fd= &tcp_fd_table[fd];
|
---|
772 |
|
---|
773 | assert (tcp_fd->tf_flags & TFF_INUSE);
|
---|
774 |
|
---|
775 | tcp_port= tcp_fd->tf_port;
|
---|
776 | tcp_fd->tf_flags |= TFF_IOCTL_IP;
|
---|
777 | tcp_fd->tf_ioreq= req;
|
---|
778 |
|
---|
779 | if (tcp_port->tp_state != TPS_MAIN)
|
---|
780 | {
|
---|
781 | tcp_fd->tf_flags |= TFF_IOC_INIT_SP;
|
---|
782 | return NW_SUSPEND;
|
---|
783 | }
|
---|
784 |
|
---|
785 | switch (req)
|
---|
786 | {
|
---|
787 | case NWIOSTCPCONF:
|
---|
788 | if ((tcp_fd->tf_flags & TFF_CONNECTED) ||
|
---|
789 | (tcp_fd->tf_flags & TFF_CONNECTING) ||
|
---|
790 | (tcp_fd->tf_flags & TFF_LISTENQ))
|
---|
791 | {
|
---|
792 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
793 | reply_thr_get (tcp_fd, EISCONN, TRUE);
|
---|
794 | result= NW_OK;
|
---|
795 | break;
|
---|
796 | }
|
---|
797 | result= tcp_setconf(tcp_fd);
|
---|
798 | break;
|
---|
799 | case NWIOGTCPCONF:
|
---|
800 | conf_acc= bf_memreq(sizeof(*tcp_conf));
|
---|
801 | assert (conf_acc->acc_length == sizeof(*tcp_conf));
|
---|
802 | tcp_conf= (nwio_tcpconf_t *)ptr2acc_data(conf_acc);
|
---|
803 |
|
---|
804 | *tcp_conf= tcp_fd->tf_tcpconf;
|
---|
805 | if (tcp_fd->tf_flags & TFF_CONNECTED)
|
---|
806 | {
|
---|
807 | tcp_conn= tcp_fd->tf_conn;
|
---|
808 | tcp_conf->nwtc_locport= tcp_conn->tc_locport;
|
---|
809 | tcp_conf->nwtc_remaddr= tcp_conn->tc_remaddr;
|
---|
810 | tcp_conf->nwtc_remport= tcp_conn->tc_remport;
|
---|
811 | }
|
---|
812 | tcp_conf->nwtc_locaddr= tcp_fd->tf_port->tp_ipaddr;
|
---|
813 | result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
|
---|
814 | 0, conf_acc, TRUE);
|
---|
815 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
816 | reply_thr_put(tcp_fd, result, TRUE);
|
---|
817 | result= NW_OK;
|
---|
818 | break;
|
---|
819 | case NWIOSTCPOPT:
|
---|
820 | result= tcp_setopt(tcp_fd);
|
---|
821 | break;
|
---|
822 | case NWIOGTCPOPT:
|
---|
823 | opt_acc= bf_memreq(sizeof(*tcp_opt));
|
---|
824 | assert (opt_acc->acc_length == sizeof(*tcp_opt));
|
---|
825 | tcp_opt= (nwio_tcpopt_t *)ptr2acc_data(opt_acc);
|
---|
826 |
|
---|
827 | *tcp_opt= tcp_fd->tf_tcpopt;
|
---|
828 | result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
|
---|
829 | 0, opt_acc, TRUE);
|
---|
830 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
831 | reply_thr_put(tcp_fd, result, TRUE);
|
---|
832 | result= NW_OK;
|
---|
833 | break;
|
---|
834 | case NWIOTCPCONN:
|
---|
835 | if (tcp_fd->tf_flags & TFF_CONNECTING)
|
---|
836 | {
|
---|
837 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
838 | reply_thr_get (tcp_fd, EALREADY, TRUE);
|
---|
839 | result= NW_OK;
|
---|
840 | break;
|
---|
841 | }
|
---|
842 | if (tcp_fd->tf_flags & TFF_CONNECTED)
|
---|
843 | {
|
---|
844 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
845 | reply_thr_get (tcp_fd, EISCONN, TRUE);
|
---|
846 | result= NW_OK;
|
---|
847 | break;
|
---|
848 | }
|
---|
849 | result= tcp_connect(tcp_fd);
|
---|
850 | if (result == NW_OK)
|
---|
851 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
852 | break;
|
---|
853 | case NWIOTCPLISTEN:
|
---|
854 | case NWIOTCPLISTENQ:
|
---|
855 | if ((tcp_fd->tf_flags & TFF_CONNECTED) ||
|
---|
856 | (tcp_fd->tf_flags & TFF_LISTENQ) ||
|
---|
857 | (tcp_fd->tf_flags & TFF_CONNECTING))
|
---|
858 | {
|
---|
859 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
860 | reply_thr_get (tcp_fd, EISCONN, TRUE);
|
---|
861 | result= NW_OK;
|
---|
862 | break;
|
---|
863 | }
|
---|
864 | result= tcp_listen(tcp_fd, (req == NWIOTCPLISTENQ));
|
---|
865 | break;
|
---|
866 | case NWIOTCPSHUTDOWN:
|
---|
867 | if (!(tcp_fd->tf_flags & TFF_CONNECTED))
|
---|
868 | {
|
---|
869 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
870 | reply_thr_get (tcp_fd, ENOTCONN, TRUE);
|
---|
871 | result= NW_OK;
|
---|
872 | break;
|
---|
873 | }
|
---|
874 | tcp_fd->tf_flags |= TFF_IOCTL_IP;
|
---|
875 | tcp_fd->tf_ioreq= req;
|
---|
876 | tcp_conn= tcp_fd->tf_conn;
|
---|
877 |
|
---|
878 | tcp_conn->tc_busy++;
|
---|
879 | tcp_fd_write(tcp_conn);
|
---|
880 | tcp_conn->tc_busy--;
|
---|
881 | tcp_conn_write(tcp_conn, 0);
|
---|
882 | if (!(tcp_fd->tf_flags & TFF_IOCTL_IP))
|
---|
883 | result= NW_OK;
|
---|
884 | else
|
---|
885 | result= NW_SUSPEND;
|
---|
886 | break;
|
---|
887 | case NWIOTCPPUSH:
|
---|
888 | if (!(tcp_fd->tf_flags & TFF_CONNECTED))
|
---|
889 | {
|
---|
890 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
891 | reply_thr_get (tcp_fd, ENOTCONN, TRUE);
|
---|
892 | result= NW_OK;
|
---|
893 | break;
|
---|
894 | }
|
---|
895 | tcp_conn= tcp_fd->tf_conn;
|
---|
896 | tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;
|
---|
897 | tcp_conn->tc_flags &= ~TCF_NO_PUSH;
|
---|
898 | tcp_conn->tc_flags |= TCF_PUSH_NOW;
|
---|
899 |
|
---|
900 | /* Start the timer (if necessary) */
|
---|
901 | if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_UNA)
|
---|
902 | tcp_set_send_timer(tcp_conn);
|
---|
903 |
|
---|
904 | tcp_conn_write(tcp_conn, 0);
|
---|
905 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
906 | reply_thr_get (tcp_fd, NW_OK, TRUE);
|
---|
907 | result= NW_OK;
|
---|
908 | break;
|
---|
909 | case NWIOGTCPCOOKIE:
|
---|
910 | if (!(tcp_fd->tf_flags & TFF_COOKIE))
|
---|
911 | {
|
---|
912 | tcp_fd->tf_cookie.tc_ref= fd;
|
---|
913 | rand256(rndbits);
|
---|
914 | assert(sizeof(tcp_fd->tf_cookie.tc_secret) <=
|
---|
915 | RAND256_BUFSIZE);
|
---|
916 | memcpy(tcp_fd->tf_cookie.tc_secret,
|
---|
917 | rndbits, sizeof(tcp_fd->tf_cookie.tc_secret));
|
---|
918 | tcp_fd->tf_flags |= TFF_COOKIE;
|
---|
919 | }
|
---|
920 | acc= bf_memreq(sizeof(*cookiep));
|
---|
921 | cookiep= (tcp_cookie_t *)ptr2acc_data(acc);
|
---|
922 |
|
---|
923 | *cookiep= tcp_fd->tf_cookie;
|
---|
924 | result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
|
---|
925 | 0, acc, TRUE);
|
---|
926 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
927 | reply_thr_put(tcp_fd, result, TRUE);
|
---|
928 | result= NW_OK;
|
---|
929 | break;
|
---|
930 | case NWIOTCPACCEPTTO:
|
---|
931 | result= tcp_acceptto(tcp_fd);
|
---|
932 | break;
|
---|
933 | case FIONREAD:
|
---|
934 | acc= bf_memreq(sizeof(*bytesp));
|
---|
935 | bytesp= (int *)ptr2acc_data(acc);
|
---|
936 | tcp_bytesavailable(tcp_fd, bytesp);
|
---|
937 | result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
|
---|
938 | 0, acc, TRUE);
|
---|
939 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
940 | reply_thr_put(tcp_fd, result, TRUE);
|
---|
941 | result= NW_OK;
|
---|
942 | break;
|
---|
943 |
|
---|
944 | case NWIOTCPGERROR:
|
---|
945 | acc= bf_memreq(sizeof(*bytesp));
|
---|
946 | bytesp= (int *)ptr2acc_data(acc);
|
---|
947 | *bytesp= -tcp_fd->tf_error; /* Errors are positive in
|
---|
948 | * user space.
|
---|
949 | */
|
---|
950 | tcp_fd->tf_error= 0;
|
---|
951 | result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
|
---|
952 | 0, acc, TRUE);
|
---|
953 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
954 | reply_thr_put(tcp_fd, result, TRUE);
|
---|
955 | result= NW_OK;
|
---|
956 | break;
|
---|
957 |
|
---|
958 | default:
|
---|
959 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
960 | reply_thr_get(tcp_fd, EBADIOCTL, TRUE);
|
---|
961 | result= NW_OK;
|
---|
962 | break;
|
---|
963 | }
|
---|
964 | return result;
|
---|
965 | }
|
---|
966 |
|
---|
967 |
|
---|
968 | /*
|
---|
969 | tcp_setconf
|
---|
970 | */
|
---|
971 |
|
---|
972 | PRIVATE int tcp_setconf(tcp_fd)
|
---|
973 | tcp_fd_t *tcp_fd;
|
---|
974 | {
|
---|
975 | nwio_tcpconf_t *tcpconf;
|
---|
976 | nwio_tcpconf_t oldconf, newconf;
|
---|
977 | acc_t *data;
|
---|
978 | tcp_fd_t *fd_ptr;
|
---|
979 | unsigned int new_en_flags, new_di_flags,
|
---|
980 | old_en_flags, old_di_flags, all_flags, flags;
|
---|
981 | int i;
|
---|
982 |
|
---|
983 | data= (*tcp_fd->tf_get_userdata)
|
---|
984 | (tcp_fd->tf_srfd, 0,
|
---|
985 | sizeof(nwio_tcpconf_t), TRUE);
|
---|
986 |
|
---|
987 | if (!data)
|
---|
988 | return EFAULT;
|
---|
989 |
|
---|
990 | data= bf_packIffLess(data, sizeof(nwio_tcpconf_t));
|
---|
991 | assert (data->acc_length == sizeof(nwio_tcpconf_t));
|
---|
992 |
|
---|
993 | tcpconf= (nwio_tcpconf_t *)ptr2acc_data(data);
|
---|
994 | oldconf= tcp_fd->tf_tcpconf;
|
---|
995 | newconf= *tcpconf;
|
---|
996 |
|
---|
997 | old_en_flags= oldconf.nwtc_flags & 0xffff;
|
---|
998 | old_di_flags= (oldconf.nwtc_flags >> 16) &
|
---|
999 | 0xffff;
|
---|
1000 | new_en_flags= newconf.nwtc_flags & 0xffff;
|
---|
1001 | new_di_flags= (newconf.nwtc_flags >> 16) &
|
---|
1002 | 0xffff;
|
---|
1003 | if (new_en_flags & new_di_flags)
|
---|
1004 | {
|
---|
1005 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1006 | reply_thr_get(tcp_fd, EBADMODE, TRUE);
|
---|
1007 | bf_afree(data);
|
---|
1008 | return NW_OK;
|
---|
1009 | }
|
---|
1010 |
|
---|
1011 | /* NWTC_ACC_MASK */
|
---|
1012 | if (new_di_flags & NWTC_ACC_MASK)
|
---|
1013 | {
|
---|
1014 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1015 | reply_thr_get(tcp_fd, EBADMODE, TRUE);
|
---|
1016 | bf_afree(data);
|
---|
1017 | return NW_OK;
|
---|
1018 | /* access modes can't be disabled */
|
---|
1019 | }
|
---|
1020 |
|
---|
1021 | if (!(new_en_flags & NWTC_ACC_MASK))
|
---|
1022 | new_en_flags |= (old_en_flags & NWTC_ACC_MASK);
|
---|
1023 |
|
---|
1024 | /* NWTC_LOCPORT_MASK */
|
---|
1025 | if (new_di_flags & NWTC_LOCPORT_MASK)
|
---|
1026 | {
|
---|
1027 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1028 | reply_thr_get(tcp_fd, EBADMODE, TRUE);
|
---|
1029 | bf_afree(data);
|
---|
1030 | return NW_OK;
|
---|
1031 | /* the loc ports can't be disabled */
|
---|
1032 | }
|
---|
1033 | if (!(new_en_flags & NWTC_LOCPORT_MASK))
|
---|
1034 | {
|
---|
1035 | new_en_flags |= (old_en_flags &
|
---|
1036 | NWTC_LOCPORT_MASK);
|
---|
1037 | newconf.nwtc_locport= oldconf.nwtc_locport;
|
---|
1038 | }
|
---|
1039 | else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL)
|
---|
1040 | {
|
---|
1041 | newconf.nwtc_locport= find_unused_port(tcp_fd-
|
---|
1042 | tcp_fd_table);
|
---|
1043 | }
|
---|
1044 | else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET)
|
---|
1045 | {
|
---|
1046 | if (!newconf.nwtc_locport)
|
---|
1047 | {
|
---|
1048 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1049 | reply_thr_get(tcp_fd, EBADMODE, TRUE);
|
---|
1050 | bf_afree(data);
|
---|
1051 | return NW_OK;
|
---|
1052 | }
|
---|
1053 | }
|
---|
1054 |
|
---|
1055 | /* NWTC_REMADDR_MASK */
|
---|
1056 | if (!((new_en_flags | new_di_flags) &
|
---|
1057 | NWTC_REMADDR_MASK))
|
---|
1058 | {
|
---|
1059 | new_en_flags |= (old_en_flags &
|
---|
1060 | NWTC_REMADDR_MASK);
|
---|
1061 | new_di_flags |= (old_di_flags &
|
---|
1062 | NWTC_REMADDR_MASK);
|
---|
1063 | newconf.nwtc_remaddr= oldconf.nwtc_remaddr;
|
---|
1064 | }
|
---|
1065 | else if (new_en_flags & NWTC_SET_RA)
|
---|
1066 | {
|
---|
1067 | if (!newconf.nwtc_remaddr)
|
---|
1068 | {
|
---|
1069 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1070 | reply_thr_get(tcp_fd, EBADMODE, TRUE);
|
---|
1071 | bf_afree(data);
|
---|
1072 | return NW_OK;
|
---|
1073 | }
|
---|
1074 | }
|
---|
1075 | else
|
---|
1076 | {
|
---|
1077 | assert (new_di_flags & NWTC_REMADDR_MASK);
|
---|
1078 | newconf.nwtc_remaddr= 0;
|
---|
1079 | }
|
---|
1080 |
|
---|
1081 | /* NWTC_REMPORT_MASK */
|
---|
1082 | if (!((new_en_flags | new_di_flags) & NWTC_REMPORT_MASK))
|
---|
1083 | {
|
---|
1084 | new_en_flags |= (old_en_flags &
|
---|
1085 | NWTC_REMPORT_MASK);
|
---|
1086 | new_di_flags |= (old_di_flags &
|
---|
1087 | NWTC_REMPORT_MASK);
|
---|
1088 | newconf.nwtc_remport=
|
---|
1089 | oldconf.nwtc_remport;
|
---|
1090 | }
|
---|
1091 | else if (new_en_flags & NWTC_SET_RP)
|
---|
1092 | {
|
---|
1093 | if (!newconf.nwtc_remport)
|
---|
1094 | {
|
---|
1095 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1096 | reply_thr_get(tcp_fd, EBADMODE, TRUE);
|
---|
1097 | bf_afree(data);
|
---|
1098 | return NW_OK;
|
---|
1099 | }
|
---|
1100 | }
|
---|
1101 | else
|
---|
1102 | {
|
---|
1103 | assert (new_di_flags & NWTC_REMPORT_MASK);
|
---|
1104 | newconf.nwtc_remport= 0;
|
---|
1105 | }
|
---|
1106 |
|
---|
1107 | newconf.nwtc_flags= ((unsigned long)new_di_flags
|
---|
1108 | << 16) | new_en_flags;
|
---|
1109 | all_flags= new_en_flags | new_di_flags;
|
---|
1110 |
|
---|
1111 | /* check the access modes */
|
---|
1112 | if ((all_flags & NWTC_LOCPORT_MASK) != NWTC_LP_UNSET)
|
---|
1113 | {
|
---|
1114 | for (i=0, fd_ptr= tcp_fd_table; i<TCP_FD_NR; i++, fd_ptr++)
|
---|
1115 | {
|
---|
1116 | if (fd_ptr == tcp_fd)
|
---|
1117 | continue;
|
---|
1118 | if (!(fd_ptr->tf_flags & TFF_INUSE))
|
---|
1119 | continue;
|
---|
1120 | if (fd_ptr->tf_port != tcp_fd->tf_port)
|
---|
1121 | continue;
|
---|
1122 | flags= fd_ptr->tf_tcpconf.nwtc_flags;
|
---|
1123 | if ((flags & NWTC_LOCPORT_MASK) == NWTC_LP_UNSET)
|
---|
1124 | continue;
|
---|
1125 | if (fd_ptr->tf_tcpconf.nwtc_locport !=
|
---|
1126 | newconf.nwtc_locport)
|
---|
1127 | continue;
|
---|
1128 | if ((flags & NWTC_ACC_MASK) != (all_flags &
|
---|
1129 | NWTC_ACC_MASK) ||
|
---|
1130 | (all_flags & NWTC_ACC_MASK) == NWTC_EXCL)
|
---|
1131 | {
|
---|
1132 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1133 | reply_thr_get(tcp_fd, EADDRINUSE, TRUE);
|
---|
1134 | bf_afree(data);
|
---|
1135 | return NW_OK;
|
---|
1136 | }
|
---|
1137 | }
|
---|
1138 | }
|
---|
1139 |
|
---|
1140 | tcp_fd->tf_tcpconf= newconf;
|
---|
1141 |
|
---|
1142 | if ((all_flags & NWTC_ACC_MASK) &&
|
---|
1143 | ((all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET ||
|
---|
1144 | (all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL) &&
|
---|
1145 | (all_flags & NWTC_REMADDR_MASK) &&
|
---|
1146 | (all_flags & NWTC_REMPORT_MASK))
|
---|
1147 | tcp_fd->tf_flags |= TFF_CONF_SET;
|
---|
1148 | else
|
---|
1149 | {
|
---|
1150 | tcp_fd->tf_flags &= ~TFF_CONF_SET;
|
---|
1151 | }
|
---|
1152 | bf_afree(data);
|
---|
1153 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1154 | reply_thr_get(tcp_fd, NW_OK, TRUE);
|
---|
1155 | return NW_OK;
|
---|
1156 | }
|
---|
1157 |
|
---|
1158 |
|
---|
1159 | /*
|
---|
1160 | tcp_setopt
|
---|
1161 | */
|
---|
1162 |
|
---|
1163 | PRIVATE int tcp_setopt(tcp_fd)
|
---|
1164 | tcp_fd_t *tcp_fd;
|
---|
1165 | {
|
---|
1166 | nwio_tcpopt_t *tcpopt;
|
---|
1167 | nwio_tcpopt_t oldopt, newopt;
|
---|
1168 | acc_t *data;
|
---|
1169 | unsigned int new_en_flags, new_di_flags,
|
---|
1170 | old_en_flags, old_di_flags;
|
---|
1171 |
|
---|
1172 | data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
|
---|
1173 | sizeof(nwio_tcpopt_t), TRUE);
|
---|
1174 |
|
---|
1175 | if (!data)
|
---|
1176 | return EFAULT;
|
---|
1177 |
|
---|
1178 | data= bf_packIffLess(data, sizeof(nwio_tcpopt_t));
|
---|
1179 | assert (data->acc_length == sizeof(nwio_tcpopt_t));
|
---|
1180 |
|
---|
1181 | tcpopt= (nwio_tcpopt_t *)ptr2acc_data(data);
|
---|
1182 | oldopt= tcp_fd->tf_tcpopt;
|
---|
1183 | newopt= *tcpopt;
|
---|
1184 |
|
---|
1185 | old_en_flags= oldopt.nwto_flags & 0xffff;
|
---|
1186 | old_di_flags= (oldopt.nwto_flags >> 16) & 0xffff;
|
---|
1187 | new_en_flags= newopt.nwto_flags & 0xffff;
|
---|
1188 | new_di_flags= (newopt.nwto_flags >> 16) & 0xffff;
|
---|
1189 | if (new_en_flags & new_di_flags)
|
---|
1190 | {
|
---|
1191 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1192 | reply_thr_get(tcp_fd, EBADMODE, TRUE);
|
---|
1193 | return NW_OK;
|
---|
1194 | }
|
---|
1195 |
|
---|
1196 | /* NWTO_SND_URG_MASK */
|
---|
1197 | if (!((new_en_flags | new_di_flags) & NWTO_SND_URG_MASK))
|
---|
1198 | {
|
---|
1199 | new_en_flags |= (old_en_flags & NWTO_SND_URG_MASK);
|
---|
1200 | new_di_flags |= (old_di_flags & NWTO_SND_URG_MASK);
|
---|
1201 | }
|
---|
1202 |
|
---|
1203 | /* NWTO_RCV_URG_MASK */
|
---|
1204 | if (!((new_en_flags | new_di_flags) & NWTO_RCV_URG_MASK))
|
---|
1205 | {
|
---|
1206 | new_en_flags |= (old_en_flags & NWTO_RCV_URG_MASK);
|
---|
1207 | new_di_flags |= (old_di_flags & NWTO_RCV_URG_MASK);
|
---|
1208 | }
|
---|
1209 |
|
---|
1210 | /* NWTO_BSD_URG_MASK */
|
---|
1211 | if (!((new_en_flags | new_di_flags) & NWTO_BSD_URG_MASK))
|
---|
1212 | {
|
---|
1213 | new_en_flags |= (old_en_flags & NWTO_BSD_URG_MASK);
|
---|
1214 | new_di_flags |= (old_di_flags & NWTO_BSD_URG_MASK);
|
---|
1215 | }
|
---|
1216 | else
|
---|
1217 | {
|
---|
1218 | if (tcp_fd->tf_conn == NULL)
|
---|
1219 | {
|
---|
1220 | bf_afree(data);
|
---|
1221 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1222 | reply_thr_get(tcp_fd, EINVAL, TRUE);
|
---|
1223 | return NW_OK;
|
---|
1224 | }
|
---|
1225 | }
|
---|
1226 |
|
---|
1227 | /* NWTO_DEL_RST_MASK */
|
---|
1228 | if (!((new_en_flags | new_di_flags) & NWTO_DEL_RST_MASK))
|
---|
1229 | {
|
---|
1230 | new_en_flags |= (old_en_flags & NWTO_DEL_RST_MASK);
|
---|
1231 | new_di_flags |= (old_di_flags & NWTO_DEL_RST_MASK);
|
---|
1232 | }
|
---|
1233 |
|
---|
1234 | /* NWTO_BULK_MASK */
|
---|
1235 | if (!((new_en_flags | new_di_flags) & NWTO_BULK_MASK))
|
---|
1236 | {
|
---|
1237 | new_en_flags |= (old_en_flags & NWTO_BULK_MASK);
|
---|
1238 | new_di_flags |= (old_di_flags & NWTO_BULK_MASK);
|
---|
1239 | }
|
---|
1240 |
|
---|
1241 | newopt.nwto_flags= ((unsigned long)new_di_flags << 16) |
|
---|
1242 | new_en_flags;
|
---|
1243 | tcp_fd->tf_tcpopt= newopt;
|
---|
1244 | if (newopt.nwto_flags & NWTO_SND_URG)
|
---|
1245 | tcp_fd->tf_flags |= TFF_WR_URG;
|
---|
1246 | else
|
---|
1247 | tcp_fd->tf_flags &= ~TFF_WR_URG;
|
---|
1248 |
|
---|
1249 | if (newopt.nwto_flags & NWTO_RCV_URG)
|
---|
1250 | tcp_fd->tf_flags |= TFF_RECV_URG;
|
---|
1251 | else
|
---|
1252 | tcp_fd->tf_flags &= ~TFF_RECV_URG;
|
---|
1253 |
|
---|
1254 | if (tcp_fd->tf_conn)
|
---|
1255 | {
|
---|
1256 | if (newopt.nwto_flags & NWTO_BSD_URG)
|
---|
1257 | tcp_fd->tf_conn->tc_flags |= TCF_BSD_URG;
|
---|
1258 | else
|
---|
1259 | tcp_fd->tf_conn->tc_flags &= ~TCF_BSD_URG;
|
---|
1260 | }
|
---|
1261 |
|
---|
1262 | if (newopt.nwto_flags & NWTO_DEL_RST)
|
---|
1263 | tcp_fd->tf_flags |= TFF_DEL_RST;
|
---|
1264 | else
|
---|
1265 | tcp_fd->tf_flags &= ~TFF_DEL_RST;
|
---|
1266 |
|
---|
1267 | if (newopt.nwto_flags & NWTO_BULK)
|
---|
1268 | tcp_fd->tf_flags &= ~TFF_PUSH_DATA;
|
---|
1269 | else
|
---|
1270 | tcp_fd->tf_flags |= TFF_PUSH_DATA;
|
---|
1271 |
|
---|
1272 | bf_afree(data);
|
---|
1273 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1274 | reply_thr_get(tcp_fd, NW_OK, TRUE);
|
---|
1275 | return NW_OK;
|
---|
1276 | }
|
---|
1277 |
|
---|
1278 |
|
---|
1279 | PRIVATE tcpport_t find_unused_port(fd)
|
---|
1280 | int fd;
|
---|
1281 | {
|
---|
1282 | tcpport_t port, nw_port;
|
---|
1283 |
|
---|
1284 | for (port= 0x8000+fd; port < 0xffff-TCP_FD_NR; port+= TCP_FD_NR)
|
---|
1285 | {
|
---|
1286 | nw_port= htons(port);
|
---|
1287 | if (is_unused_port(nw_port))
|
---|
1288 | return nw_port;
|
---|
1289 | }
|
---|
1290 | for (port= 0x8000; port < 0xffff; port++)
|
---|
1291 | {
|
---|
1292 | nw_port= htons(port);
|
---|
1293 | if (is_unused_port(nw_port))
|
---|
1294 | return nw_port;
|
---|
1295 | }
|
---|
1296 | ip_panic(( "unable to find unused port (shouldn't occur)" ));
|
---|
1297 | return 0;
|
---|
1298 | }
|
---|
1299 |
|
---|
1300 | PRIVATE int is_unused_port(port)
|
---|
1301 | tcpport_t port;
|
---|
1302 | {
|
---|
1303 | int i;
|
---|
1304 | tcp_fd_t *tcp_fd;
|
---|
1305 | tcp_conn_t *tcp_conn;
|
---|
1306 |
|
---|
1307 | for (i= 0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++,
|
---|
1308 | tcp_fd++)
|
---|
1309 | {
|
---|
1310 | if (!(tcp_fd->tf_flags & TFF_CONF_SET))
|
---|
1311 | continue;
|
---|
1312 | if (tcp_fd->tf_tcpconf.nwtc_locport == port)
|
---|
1313 | return FALSE;
|
---|
1314 | }
|
---|
1315 | for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
|
---|
1316 | i<TCP_CONN_NR; i++, tcp_conn++)
|
---|
1317 | /* the first tcp_conf_nr ports are special */
|
---|
1318 | {
|
---|
1319 | if (!(tcp_conn->tc_flags & TCF_INUSE))
|
---|
1320 | continue;
|
---|
1321 | if (tcp_conn->tc_locport == port)
|
---|
1322 | return FALSE;
|
---|
1323 | }
|
---|
1324 | return TRUE;
|
---|
1325 | }
|
---|
1326 |
|
---|
1327 | PRIVATE int reply_thr_put(tcp_fd, reply, for_ioctl)
|
---|
1328 | tcp_fd_t *tcp_fd;
|
---|
1329 | int reply;
|
---|
1330 | int for_ioctl;
|
---|
1331 | {
|
---|
1332 | assert (tcp_fd);
|
---|
1333 |
|
---|
1334 | return (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd, reply,
|
---|
1335 | (acc_t *)0, for_ioctl);
|
---|
1336 | }
|
---|
1337 |
|
---|
1338 | PRIVATE void reply_thr_get(tcp_fd, reply, for_ioctl)
|
---|
1339 | tcp_fd_t *tcp_fd;
|
---|
1340 | int reply;
|
---|
1341 | int for_ioctl;
|
---|
1342 | {
|
---|
1343 | acc_t *result;
|
---|
1344 |
|
---|
1345 | result= (*tcp_fd->tf_get_userdata)(tcp_fd->tf_srfd, reply,
|
---|
1346 | (size_t)0, for_ioctl);
|
---|
1347 | assert (!result);
|
---|
1348 | }
|
---|
1349 |
|
---|
1350 | PUBLIC int tcp_su4listen(tcp_fd, tcp_conn, do_listenq)
|
---|
1351 | tcp_fd_t *tcp_fd;
|
---|
1352 | tcp_conn_t *tcp_conn;
|
---|
1353 | int do_listenq;
|
---|
1354 | {
|
---|
1355 | tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport;
|
---|
1356 | tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr;
|
---|
1357 | if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP)
|
---|
1358 | tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;
|
---|
1359 | else
|
---|
1360 | tcp_conn->tc_remport= 0;
|
---|
1361 | if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA)
|
---|
1362 | tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;
|
---|
1363 | else
|
---|
1364 | tcp_conn->tc_remaddr= 0;
|
---|
1365 |
|
---|
1366 | tcp_setup_conn(tcp_fd->tf_port, tcp_conn);
|
---|
1367 | tcp_conn->tc_fd= tcp_fd;
|
---|
1368 | tcp_conn->tc_connInprogress= 1;
|
---|
1369 | tcp_conn->tc_orglisten= TRUE;
|
---|
1370 | tcp_conn->tc_state= TCS_LISTEN;
|
---|
1371 | tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_LISTEN;
|
---|
1372 | if (do_listenq)
|
---|
1373 | {
|
---|
1374 | tcp_fd->tf_flags |= TFF_LISTENQ;
|
---|
1375 | tcp_reply_ioctl(tcp_fd, NW_OK);
|
---|
1376 | return NW_OK;
|
---|
1377 | }
|
---|
1378 | return NW_SUSPEND;
|
---|
1379 | }
|
---|
1380 |
|
---|
1381 | /*
|
---|
1382 | find_empty_conn
|
---|
1383 |
|
---|
1384 | This function returns a connection that is not inuse.
|
---|
1385 | This includes connections that are never used, and connections without a
|
---|
1386 | user that are not used for a while.
|
---|
1387 | */
|
---|
1388 |
|
---|
1389 | PRIVATE tcp_conn_t *find_empty_conn()
|
---|
1390 | {
|
---|
1391 | int i;
|
---|
1392 | tcp_conn_t *tcp_conn;
|
---|
1393 |
|
---|
1394 | for (i=tcp_conf_nr, tcp_conn= tcp_conn_table+i;
|
---|
1395 | i<TCP_CONN_NR; i++, tcp_conn++)
|
---|
1396 | /* the first tcp_conf_nr connections are reserved for
|
---|
1397 | * RSTs
|
---|
1398 | */
|
---|
1399 | {
|
---|
1400 | if (tcp_conn->tc_flags == TCF_EMPTY)
|
---|
1401 | {
|
---|
1402 | tcp_conn->tc_connInprogress= 0;
|
---|
1403 | tcp_conn->tc_fd= NULL;
|
---|
1404 | return tcp_conn;
|
---|
1405 | }
|
---|
1406 | if (tcp_conn->tc_fd)
|
---|
1407 | continue;
|
---|
1408 | if (tcp_conn->tc_senddis > get_time())
|
---|
1409 | continue;
|
---|
1410 | if (tcp_conn->tc_state != TCS_CLOSED)
|
---|
1411 | {
|
---|
1412 | tcp_close_connection (tcp_conn, ENOCONN);
|
---|
1413 | }
|
---|
1414 | tcp_conn->tc_flags= 0;
|
---|
1415 | return tcp_conn;
|
---|
1416 | }
|
---|
1417 | return NULL;
|
---|
1418 | }
|
---|
1419 |
|
---|
1420 |
|
---|
1421 | /*
|
---|
1422 | find_conn_entry
|
---|
1423 |
|
---|
1424 | This function return a connection matching locport, locaddr, remport, remaddr.
|
---|
1425 | If no such connection exists NULL is returned.
|
---|
1426 | If a connection exists without mainuser it is closed.
|
---|
1427 | */
|
---|
1428 |
|
---|
1429 | PRIVATE tcp_conn_t *find_conn_entry(locport, locaddr, remport, remaddr)
|
---|
1430 | tcpport_t locport;
|
---|
1431 | ipaddr_t locaddr;
|
---|
1432 | tcpport_t remport;
|
---|
1433 | ipaddr_t remaddr;
|
---|
1434 | {
|
---|
1435 | tcp_conn_t *tcp_conn;
|
---|
1436 | int i, state;
|
---|
1437 |
|
---|
1438 | assert(remport);
|
---|
1439 | assert(remaddr);
|
---|
1440 | for (i=tcp_conf_nr, tcp_conn= tcp_conn_table+i; i<TCP_CONN_NR;
|
---|
1441 | i++, tcp_conn++)
|
---|
1442 | /* the first tcp_conf_nr connections are reserved for
|
---|
1443 | RSTs */
|
---|
1444 | {
|
---|
1445 | if (tcp_conn->tc_flags == TCF_EMPTY)
|
---|
1446 | continue;
|
---|
1447 | if (tcp_conn->tc_locport != locport ||
|
---|
1448 | tcp_conn->tc_locaddr != locaddr ||
|
---|
1449 | tcp_conn->tc_remport != remport ||
|
---|
1450 | tcp_conn->tc_remaddr != remaddr)
|
---|
1451 | continue;
|
---|
1452 | if (tcp_conn->tc_fd)
|
---|
1453 | return tcp_conn;
|
---|
1454 | state= tcp_conn->tc_state;
|
---|
1455 | if (state != TCS_CLOSED)
|
---|
1456 | {
|
---|
1457 | tcp_close_connection(tcp_conn, ENOCONN);
|
---|
1458 | }
|
---|
1459 | return tcp_conn;
|
---|
1460 | }
|
---|
1461 | return NULL;
|
---|
1462 | }
|
---|
1463 |
|
---|
1464 | PRIVATE void read_ip_packets(tcp_port)
|
---|
1465 | tcp_port_t *tcp_port;
|
---|
1466 | {
|
---|
1467 | int result;
|
---|
1468 |
|
---|
1469 | do
|
---|
1470 | {
|
---|
1471 | tcp_port->tp_flags |= TPF_READ_IP;
|
---|
1472 | result= ip_read(tcp_port->tp_ipfd, TCP_MAX_DATAGRAM);
|
---|
1473 | if (result == NW_SUSPEND)
|
---|
1474 | {
|
---|
1475 | tcp_port->tp_flags |= TPF_READ_SP;
|
---|
1476 | return;
|
---|
1477 | }
|
---|
1478 | assert(result == NW_OK);
|
---|
1479 | tcp_port->tp_flags &= ~TPF_READ_IP;
|
---|
1480 | } while(!(tcp_port->tp_flags & TPF_READ_IP));
|
---|
1481 | }
|
---|
1482 |
|
---|
1483 | /*
|
---|
1484 | find_best_conn
|
---|
1485 | */
|
---|
1486 |
|
---|
1487 | PRIVATE tcp_conn_t *find_best_conn(ip_hdr, tcp_hdr)
|
---|
1488 | ip_hdr_t *ip_hdr;
|
---|
1489 | tcp_hdr_t *tcp_hdr;
|
---|
1490 | {
|
---|
1491 |
|
---|
1492 | int best_level, new_level;
|
---|
1493 | tcp_conn_t *best_conn, *listen_conn, *tcp_conn;
|
---|
1494 | tcp_fd_t *tcp_fd;
|
---|
1495 | int i;
|
---|
1496 | ipaddr_t locaddr;
|
---|
1497 | ipaddr_t remaddr;
|
---|
1498 | tcpport_t locport;
|
---|
1499 | tcpport_t remport;
|
---|
1500 |
|
---|
1501 | locaddr= ip_hdr->ih_dst;
|
---|
1502 | remaddr= ip_hdr->ih_src;
|
---|
1503 | locport= tcp_hdr->th_dstport;
|
---|
1504 | remport= tcp_hdr->th_srcport;
|
---|
1505 | if (!remport) /* This can interfere with a listen, so we reject it
|
---|
1506 | * by clearing the requested port
|
---|
1507 | */
|
---|
1508 | locport= 0;
|
---|
1509 |
|
---|
1510 | best_level= 0;
|
---|
1511 | best_conn= NULL;
|
---|
1512 | listen_conn= NULL;
|
---|
1513 | for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
|
---|
1514 | i<TCP_CONN_NR; i++, tcp_conn++)
|
---|
1515 | /* the first tcp_conf_nr connections are reserved for
|
---|
1516 | RSTs */
|
---|
1517 | {
|
---|
1518 | if (!(tcp_conn->tc_flags & TCF_INUSE))
|
---|
1519 | continue;
|
---|
1520 | /* First fast check for open connections. */
|
---|
1521 | if (tcp_conn->tc_locaddr == locaddr &&
|
---|
1522 | tcp_conn->tc_locport == locport &&
|
---|
1523 | tcp_conn->tc_remport == remport &&
|
---|
1524 | tcp_conn->tc_remaddr == remaddr &&
|
---|
1525 | tcp_conn->tc_fd)
|
---|
1526 | {
|
---|
1527 | return tcp_conn;
|
---|
1528 | }
|
---|
1529 |
|
---|
1530 | /* Now check for listens and abandoned connections. */
|
---|
1531 | if (tcp_conn->tc_locaddr != locaddr)
|
---|
1532 | {
|
---|
1533 | continue;
|
---|
1534 | }
|
---|
1535 | new_level= 0;
|
---|
1536 | if (tcp_conn->tc_locport)
|
---|
1537 | {
|
---|
1538 | if (tcp_conn->tc_locport != locport)
|
---|
1539 | {
|
---|
1540 | continue;
|
---|
1541 | }
|
---|
1542 | new_level += 4;
|
---|
1543 | }
|
---|
1544 | if (tcp_conn->tc_remport)
|
---|
1545 | {
|
---|
1546 | if (tcp_conn->tc_remport != remport)
|
---|
1547 | {
|
---|
1548 | continue;
|
---|
1549 | }
|
---|
1550 | new_level += 1;
|
---|
1551 | }
|
---|
1552 | if (tcp_conn->tc_remaddr)
|
---|
1553 | {
|
---|
1554 | if (tcp_conn->tc_remaddr != remaddr)
|
---|
1555 | {
|
---|
1556 | continue;
|
---|
1557 | }
|
---|
1558 | new_level += 2;
|
---|
1559 | }
|
---|
1560 | if (new_level<best_level)
|
---|
1561 | continue;
|
---|
1562 | if (new_level != 7 && tcp_conn->tc_state != TCS_LISTEN)
|
---|
1563 | continue;
|
---|
1564 | if (new_level == 7)
|
---|
1565 | /* We found an abandoned connection */
|
---|
1566 | {
|
---|
1567 | assert(!tcp_conn->tc_fd);
|
---|
1568 | if (best_conn && tcp_Lmod4G(tcp_conn->tc_ISS,
|
---|
1569 | best_conn->tc_ISS))
|
---|
1570 | {
|
---|
1571 | continue;
|
---|
1572 | }
|
---|
1573 | best_conn= tcp_conn;
|
---|
1574 | continue;
|
---|
1575 | }
|
---|
1576 | if (!(tcp_hdr->th_flags & THF_SYN))
|
---|
1577 | continue;
|
---|
1578 | best_level= new_level;
|
---|
1579 | listen_conn= tcp_conn;
|
---|
1580 | assert(listen_conn->tc_fd != NULL);
|
---|
1581 | }
|
---|
1582 |
|
---|
1583 | if (listen_conn && listen_conn->tc_fd->tf_flags & TFF_LISTENQ &&
|
---|
1584 | listen_conn->tc_fd->tf_conn == listen_conn)
|
---|
1585 | {
|
---|
1586 | /* Special processing for listen queues. Only accept the
|
---|
1587 | * connection if there is empty space in the queue and
|
---|
1588 | * there are empty connections as well.
|
---|
1589 | */
|
---|
1590 | listen_conn= new_conn_for_queue(listen_conn->tc_fd);
|
---|
1591 | }
|
---|
1592 |
|
---|
1593 | if (!best_conn && !listen_conn)
|
---|
1594 | {
|
---|
1595 | if ((tcp_hdr->th_flags & THF_SYN) &&
|
---|
1596 | maybe_listen(locaddr, locport, remaddr, remport))
|
---|
1597 | {
|
---|
1598 | /* Quick hack to implement listen back logs:
|
---|
1599 | * if a SYN arrives and there is no listen waiting
|
---|
1600 | * for that packet, then no reply is sent.
|
---|
1601 | */
|
---|
1602 | return NULL;
|
---|
1603 | }
|
---|
1604 |
|
---|
1605 | for (i=0, tcp_conn= tcp_conn_table; i<tcp_conf_nr;
|
---|
1606 | i++, tcp_conn++)
|
---|
1607 | {
|
---|
1608 | /* find valid port to send RST */
|
---|
1609 | if ((tcp_conn->tc_flags & TCF_INUSE) &&
|
---|
1610 | tcp_conn->tc_locaddr==locaddr)
|
---|
1611 | {
|
---|
1612 | break;
|
---|
1613 | }
|
---|
1614 | }
|
---|
1615 | assert (tcp_conn);
|
---|
1616 | assert (tcp_conn->tc_state == TCS_CLOSED);
|
---|
1617 |
|
---|
1618 | tcp_conn->tc_locport= locport;
|
---|
1619 | tcp_conn->tc_locaddr= locaddr;
|
---|
1620 | tcp_conn->tc_remport= remport;
|
---|
1621 | tcp_conn->tc_remaddr= remaddr;
|
---|
1622 | assert (!tcp_conn->tc_fd);
|
---|
1623 | return tcp_conn;
|
---|
1624 | }
|
---|
1625 |
|
---|
1626 | if (best_conn)
|
---|
1627 | {
|
---|
1628 | if (!listen_conn)
|
---|
1629 | {
|
---|
1630 | assert(!best_conn->tc_fd);
|
---|
1631 | return best_conn;
|
---|
1632 | }
|
---|
1633 |
|
---|
1634 | assert(listen_conn->tc_connInprogress);
|
---|
1635 | tcp_fd= listen_conn->tc_fd;
|
---|
1636 | assert(tcp_fd);
|
---|
1637 | assert((tcp_fd->tf_flags & TFF_LISTENQ) ||
|
---|
1638 | tcp_fd->tf_conn == listen_conn);
|
---|
1639 |
|
---|
1640 | if (best_conn->tc_state != TCS_CLOSED)
|
---|
1641 | tcp_close_connection(best_conn, ENOCONN);
|
---|
1642 |
|
---|
1643 | listen_conn->tc_ISS= best_conn->tc_ISS;
|
---|
1644 | if (best_conn->tc_senddis > listen_conn->tc_senddis)
|
---|
1645 | listen_conn->tc_senddis= best_conn->tc_senddis;
|
---|
1646 | return listen_conn;
|
---|
1647 | }
|
---|
1648 | assert (listen_conn);
|
---|
1649 | return listen_conn;
|
---|
1650 | }
|
---|
1651 |
|
---|
1652 | /*
|
---|
1653 | new_conn_for_queue
|
---|
1654 | */
|
---|
1655 | PRIVATE tcp_conn_t *new_conn_for_queue(tcp_fd)
|
---|
1656 | tcp_fd_t *tcp_fd;
|
---|
1657 | {
|
---|
1658 | int i;
|
---|
1659 | tcp_conn_t *tcp_conn;
|
---|
1660 |
|
---|
1661 | assert(tcp_fd->tf_flags & TFF_LISTENQ);
|
---|
1662 |
|
---|
1663 | for (i= 0; i<TFL_LISTEN_MAX; i++)
|
---|
1664 | {
|
---|
1665 | if (tcp_fd->tf_listenq[i] == NULL)
|
---|
1666 | break;
|
---|
1667 | }
|
---|
1668 | if (i >= TFL_LISTEN_MAX)
|
---|
1669 | return NULL;
|
---|
1670 |
|
---|
1671 | tcp_conn= find_empty_conn();
|
---|
1672 | if (!tcp_conn)
|
---|
1673 | return NULL;
|
---|
1674 | tcp_fd->tf_listenq[i]= tcp_conn;
|
---|
1675 | (void)tcp_su4listen(tcp_fd, tcp_conn, 0 /* !do_listenq */);
|
---|
1676 | return tcp_conn;
|
---|
1677 | }
|
---|
1678 |
|
---|
1679 | /*
|
---|
1680 | maybe_listen
|
---|
1681 | */
|
---|
1682 | PRIVATE int maybe_listen(locaddr, locport, remaddr, remport)
|
---|
1683 | ipaddr_t locaddr;
|
---|
1684 | tcpport_t locport;
|
---|
1685 | ipaddr_t remaddr;
|
---|
1686 | tcpport_t remport;
|
---|
1687 | {
|
---|
1688 | int i;
|
---|
1689 | tcp_conn_t *tcp_conn;
|
---|
1690 | tcp_fd_t *fd;
|
---|
1691 |
|
---|
1692 | for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
|
---|
1693 | i<TCP_CONN_NR; i++, tcp_conn++)
|
---|
1694 | {
|
---|
1695 | if (!(tcp_conn->tc_flags & TCF_INUSE))
|
---|
1696 | continue;
|
---|
1697 |
|
---|
1698 | if (tcp_conn->tc_locaddr != locaddr)
|
---|
1699 | {
|
---|
1700 | continue;
|
---|
1701 | }
|
---|
1702 | if (tcp_conn->tc_locport != locport )
|
---|
1703 | {
|
---|
1704 | continue;
|
---|
1705 | }
|
---|
1706 | if (!tcp_conn->tc_orglisten)
|
---|
1707 | continue;
|
---|
1708 | fd= tcp_conn->tc_fd;
|
---|
1709 | if (!fd)
|
---|
1710 | continue;
|
---|
1711 | if ((fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP) &&
|
---|
1712 | tcp_conn->tc_remport != remport)
|
---|
1713 | {
|
---|
1714 | continue;
|
---|
1715 | }
|
---|
1716 | if ((fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA) &&
|
---|
1717 | tcp_conn->tc_remaddr != remaddr)
|
---|
1718 | {
|
---|
1719 | continue;
|
---|
1720 | }
|
---|
1721 | if (!(fd->tf_flags & TFF_DEL_RST))
|
---|
1722 | continue;
|
---|
1723 | return 1;
|
---|
1724 |
|
---|
1725 | }
|
---|
1726 | return 0;
|
---|
1727 | }
|
---|
1728 |
|
---|
1729 |
|
---|
1730 | PUBLIC void tcp_reply_ioctl(tcp_fd, reply)
|
---|
1731 | tcp_fd_t *tcp_fd;
|
---|
1732 | int reply;
|
---|
1733 | {
|
---|
1734 | assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
|
---|
1735 | assert (tcp_fd->tf_ioreq == NWIOTCPSHUTDOWN ||
|
---|
1736 | tcp_fd->tf_ioreq == NWIOTCPLISTEN ||
|
---|
1737 | tcp_fd->tf_ioreq == NWIOTCPLISTENQ ||
|
---|
1738 | tcp_fd->tf_ioreq == NWIOTCPACCEPTTO ||
|
---|
1739 | tcp_fd->tf_ioreq == NWIOTCPCONN);
|
---|
1740 |
|
---|
1741 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
1742 | reply_thr_get (tcp_fd, reply, TRUE);
|
---|
1743 | }
|
---|
1744 |
|
---|
1745 | PUBLIC void tcp_reply_write(tcp_fd, reply)
|
---|
1746 | tcp_fd_t *tcp_fd;
|
---|
1747 | size_t reply;
|
---|
1748 | {
|
---|
1749 | assert (tcp_fd->tf_flags & TFF_WRITE_IP);
|
---|
1750 |
|
---|
1751 | tcp_fd->tf_flags &= ~TFF_WRITE_IP;
|
---|
1752 | reply_thr_get (tcp_fd, reply, FALSE);
|
---|
1753 | }
|
---|
1754 |
|
---|
1755 | PUBLIC void tcp_reply_read(tcp_fd, reply)
|
---|
1756 | tcp_fd_t *tcp_fd;
|
---|
1757 | size_t reply;
|
---|
1758 | {
|
---|
1759 | assert (tcp_fd->tf_flags & TFF_READ_IP);
|
---|
1760 |
|
---|
1761 | tcp_fd->tf_flags &= ~TFF_READ_IP;
|
---|
1762 | reply_thr_put (tcp_fd, reply, FALSE);
|
---|
1763 | }
|
---|
1764 |
|
---|
1765 | PUBLIC int tcp_write(fd, count)
|
---|
1766 | int fd;
|
---|
1767 | size_t count;
|
---|
1768 | {
|
---|
1769 | tcp_fd_t *tcp_fd;
|
---|
1770 | tcp_conn_t *tcp_conn;
|
---|
1771 |
|
---|
1772 | tcp_fd= &tcp_fd_table[fd];
|
---|
1773 |
|
---|
1774 | assert (tcp_fd->tf_flags & TFF_INUSE);
|
---|
1775 |
|
---|
1776 | if (!(tcp_fd->tf_flags & TFF_CONNECTED))
|
---|
1777 | {
|
---|
1778 | reply_thr_get (tcp_fd, ENOTCONN, FALSE);
|
---|
1779 | return NW_OK;
|
---|
1780 | }
|
---|
1781 | tcp_conn= tcp_fd->tf_conn;
|
---|
1782 | if (tcp_conn->tc_state == TCS_CLOSED)
|
---|
1783 | {
|
---|
1784 | reply_thr_get(tcp_fd, tcp_conn->tc_error, FALSE);
|
---|
1785 | return NW_OK;
|
---|
1786 | }
|
---|
1787 | if (tcp_conn->tc_flags & TCF_FIN_SENT)
|
---|
1788 | {
|
---|
1789 | reply_thr_get (tcp_fd, ESHUTDOWN, FALSE);
|
---|
1790 | return NW_OK;
|
---|
1791 | }
|
---|
1792 |
|
---|
1793 | tcp_fd->tf_flags |= TFF_WRITE_IP;
|
---|
1794 | tcp_fd->tf_write_offset= 0;
|
---|
1795 | tcp_fd->tf_write_count= count;
|
---|
1796 |
|
---|
1797 | /* New data may cause a segment to be sent. Clear PUSH_NOW
|
---|
1798 | * from last NWIOTCPPUSH ioctl.
|
---|
1799 | */
|
---|
1800 | tcp_conn->tc_flags &= ~(TCF_NO_PUSH|TCF_PUSH_NOW);
|
---|
1801 |
|
---|
1802 | /* Start the timer (if necessary) */
|
---|
1803 | if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_UNA)
|
---|
1804 | tcp_set_send_timer(tcp_conn);
|
---|
1805 |
|
---|
1806 | assert(tcp_conn->tc_busy == 0);
|
---|
1807 | tcp_conn->tc_busy++;
|
---|
1808 | tcp_fd_write(tcp_conn);
|
---|
1809 | tcp_conn->tc_busy--;
|
---|
1810 | tcp_conn_write(tcp_conn, 0);
|
---|
1811 |
|
---|
1812 | if (!(tcp_fd->tf_flags & TFF_WRITE_IP))
|
---|
1813 | return NW_OK;
|
---|
1814 | else
|
---|
1815 | return NW_SUSPEND;
|
---|
1816 | }
|
---|
1817 |
|
---|
1818 | PUBLIC int
|
---|
1819 | tcp_read(fd, count)
|
---|
1820 | int fd;
|
---|
1821 | size_t count;
|
---|
1822 | {
|
---|
1823 | tcp_fd_t *tcp_fd;
|
---|
1824 | tcp_conn_t *tcp_conn;
|
---|
1825 |
|
---|
1826 | tcp_fd= &tcp_fd_table[fd];
|
---|
1827 |
|
---|
1828 | assert (tcp_fd->tf_flags & TFF_INUSE);
|
---|
1829 |
|
---|
1830 | if (!(tcp_fd->tf_flags & TFF_CONNECTED))
|
---|
1831 | {
|
---|
1832 | reply_thr_put (tcp_fd, ENOTCONN, FALSE);
|
---|
1833 | return NW_OK;
|
---|
1834 | }
|
---|
1835 | tcp_conn= tcp_fd->tf_conn;
|
---|
1836 |
|
---|
1837 | tcp_fd->tf_flags |= TFF_READ_IP;
|
---|
1838 | tcp_fd->tf_read_offset= 0;
|
---|
1839 | tcp_fd->tf_read_count= count;
|
---|
1840 |
|
---|
1841 | assert(tcp_conn->tc_busy == 0);
|
---|
1842 | tcp_conn->tc_busy++;
|
---|
1843 | tcp_fd_read(tcp_conn, 0);
|
---|
1844 | tcp_conn->tc_busy--;
|
---|
1845 | if (!(tcp_fd->tf_flags & TFF_READ_IP))
|
---|
1846 | return NW_OK;
|
---|
1847 | else
|
---|
1848 | return NW_SUSPEND;
|
---|
1849 | }
|
---|
1850 |
|
---|
1851 | /*
|
---|
1852 | tcp_restart_connect
|
---|
1853 |
|
---|
1854 | reply the success or failure of a connect to the user.
|
---|
1855 | */
|
---|
1856 |
|
---|
1857 |
|
---|
1858 | PUBLIC void tcp_restart_connect(tcp_conn)
|
---|
1859 | tcp_conn_t *tcp_conn;
|
---|
1860 | {
|
---|
1861 | tcp_fd_t *tcp_fd;
|
---|
1862 | int reply;
|
---|
1863 |
|
---|
1864 | assert(tcp_conn->tc_connInprogress);
|
---|
1865 | tcp_conn->tc_connInprogress= 0;
|
---|
1866 |
|
---|
1867 | tcp_fd= tcp_conn->tc_fd;
|
---|
1868 | assert(tcp_fd);
|
---|
1869 | if (tcp_fd->tf_flags & TFF_LISTENQ)
|
---|
1870 | {
|
---|
1871 | /* Special code for listen queues */
|
---|
1872 | assert(tcp_conn->tc_state != TCS_CLOSED);
|
---|
1873 |
|
---|
1874 | /* Reply for select */
|
---|
1875 | if ((tcp_fd->tf_flags & TFF_SEL_READ) &&
|
---|
1876 | tcp_fd->tf_select_res)
|
---|
1877 | {
|
---|
1878 | tcp_fd->tf_flags &= ~TFF_SEL_READ;
|
---|
1879 | tcp_fd->tf_select_res(tcp_fd->tf_srfd,
|
---|
1880 | SR_SELECT_READ);
|
---|
1881 | }
|
---|
1882 |
|
---|
1883 | /* Reply for acceptto */
|
---|
1884 | if (tcp_fd->tf_flags & TFF_IOCTL_IP)
|
---|
1885 | (void) tcp_acceptto(tcp_fd);
|
---|
1886 |
|
---|
1887 | return;
|
---|
1888 | }
|
---|
1889 |
|
---|
1890 | if (tcp_conn->tc_state == TCS_CLOSED)
|
---|
1891 | {
|
---|
1892 | reply= tcp_conn->tc_error;
|
---|
1893 | assert(tcp_conn->tc_fd == tcp_fd);
|
---|
1894 | tcp_fd->tf_conn= NULL;
|
---|
1895 | tcp_conn->tc_fd= NULL;
|
---|
1896 | tcp_fd->tf_error= reply;
|
---|
1897 | }
|
---|
1898 | else
|
---|
1899 | {
|
---|
1900 | tcp_fd->tf_flags |= TFF_CONNECTED;
|
---|
1901 | reply= NW_OK;
|
---|
1902 | }
|
---|
1903 |
|
---|
1904 | if (tcp_fd->tf_flags & TFF_CONNECTING)
|
---|
1905 | {
|
---|
1906 | /* Special code for asynchronous connects */
|
---|
1907 | tcp_fd->tf_flags &= ~TFF_CONNECTING;
|
---|
1908 |
|
---|
1909 | /* Reply for select */
|
---|
1910 | if ((tcp_fd->tf_flags & TFF_SEL_WRITE) &&
|
---|
1911 | tcp_fd->tf_select_res)
|
---|
1912 | {
|
---|
1913 | tcp_fd->tf_flags &= ~TFF_SEL_WRITE;
|
---|
1914 | tcp_fd->tf_select_res(tcp_fd->tf_srfd,
|
---|
1915 | SR_SELECT_WRITE);
|
---|
1916 | }
|
---|
1917 |
|
---|
1918 | return;
|
---|
1919 | }
|
---|
1920 |
|
---|
1921 | assert(tcp_fd->tf_flags & TFF_IOCTL_IP);
|
---|
1922 | assert(tcp_fd->tf_ioreq == NWIOTCPLISTEN ||
|
---|
1923 | tcp_fd->tf_ioreq == NWIOTCPCONN);
|
---|
1924 |
|
---|
1925 | tcp_reply_ioctl (tcp_fd, reply);
|
---|
1926 | }
|
---|
1927 |
|
---|
1928 | /*
|
---|
1929 | tcp_close
|
---|
1930 | */
|
---|
1931 |
|
---|
1932 | PUBLIC void tcp_close(fd)
|
---|
1933 | int fd;
|
---|
1934 | {
|
---|
1935 | int i;
|
---|
1936 | tcp_fd_t *tcp_fd;
|
---|
1937 | tcp_conn_t *tcp_conn;
|
---|
1938 |
|
---|
1939 | tcp_fd= &tcp_fd_table[fd];
|
---|
1940 |
|
---|
1941 | assert (tcp_fd->tf_flags & TFF_INUSE);
|
---|
1942 | assert (!(tcp_fd->tf_flags &
|
---|
1943 | (TFF_IOCTL_IP|TFF_READ_IP|TFF_WRITE_IP)));
|
---|
1944 |
|
---|
1945 | if (tcp_fd->tf_flags & TFF_LISTENQ)
|
---|
1946 | {
|
---|
1947 | /* Special code for listen queues */
|
---|
1948 | for (i= 0; i<TFL_LISTEN_MAX; i++)
|
---|
1949 | {
|
---|
1950 | tcp_conn= tcp_fd->tf_listenq[i];
|
---|
1951 | if (!tcp_conn)
|
---|
1952 | continue;
|
---|
1953 |
|
---|
1954 | tcp_fd->tf_listenq[i]= NULL;
|
---|
1955 | assert(tcp_conn->tc_fd == tcp_fd);
|
---|
1956 | tcp_conn->tc_fd= NULL;
|
---|
1957 |
|
---|
1958 | if (tcp_conn->tc_connInprogress)
|
---|
1959 | {
|
---|
1960 | tcp_conn->tc_connInprogress= 0;
|
---|
1961 | tcp_close_connection(tcp_conn, ENOCONN);
|
---|
1962 | continue;
|
---|
1963 | }
|
---|
1964 |
|
---|
1965 | tcp_shutdown (tcp_conn);
|
---|
1966 | if (tcp_conn->tc_state == TCS_ESTABLISHED)
|
---|
1967 | tcp_conn->tc_state= TCS_CLOSING;
|
---|
1968 |
|
---|
1969 | /* Set the retransmission timeout a bit smaller. */
|
---|
1970 | tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CLOSING;
|
---|
1971 |
|
---|
1972 | /* If all data has been acknowledged, close the connection. */
|
---|
1973 | if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
|
---|
1974 | tcp_close_connection(tcp_conn, ENOTCONN);
|
---|
1975 | }
|
---|
1976 |
|
---|
1977 | tcp_conn= tcp_fd->tf_conn;
|
---|
1978 | assert(tcp_conn->tc_fd == tcp_fd);
|
---|
1979 | assert (tcp_conn->tc_connInprogress);
|
---|
1980 | tcp_conn->tc_connInprogress= 0;
|
---|
1981 | tcp_conn->tc_fd= NULL;
|
---|
1982 | tcp_fd->tf_conn= NULL;
|
---|
1983 | tcp_close_connection(tcp_conn, ENOCONN);
|
---|
1984 | }
|
---|
1985 | for (i= 0; i<TFL_LISTEN_MAX; i++)
|
---|
1986 | {
|
---|
1987 | assert(tcp_fd->tf_listenq[i] == NULL);
|
---|
1988 | }
|
---|
1989 |
|
---|
1990 | if (tcp_fd->tf_flags & TFF_CONNECTING)
|
---|
1991 | {
|
---|
1992 | tcp_conn= tcp_fd->tf_conn;
|
---|
1993 | assert(tcp_conn != NULL);
|
---|
1994 |
|
---|
1995 | assert (tcp_conn->tc_connInprogress);
|
---|
1996 | tcp_conn->tc_connInprogress= 0;
|
---|
1997 | tcp_conn->tc_fd= NULL;
|
---|
1998 | tcp_fd->tf_conn= NULL;
|
---|
1999 | tcp_close_connection(tcp_conn, ENOCONN);
|
---|
2000 |
|
---|
2001 | tcp_fd->tf_flags &= ~TFF_CONNECTING;
|
---|
2002 | }
|
---|
2003 |
|
---|
2004 | tcp_fd->tf_flags &= ~TFF_INUSE;
|
---|
2005 | if (!tcp_fd->tf_conn)
|
---|
2006 | return;
|
---|
2007 |
|
---|
2008 |
|
---|
2009 | tcp_conn= tcp_fd->tf_conn;
|
---|
2010 | assert(tcp_conn->tc_fd == tcp_fd);
|
---|
2011 | tcp_conn->tc_fd= NULL;
|
---|
2012 |
|
---|
2013 | assert (!tcp_conn->tc_connInprogress);
|
---|
2014 |
|
---|
2015 | tcp_shutdown (tcp_conn);
|
---|
2016 | if (tcp_conn->tc_state == TCS_ESTABLISHED)
|
---|
2017 | {
|
---|
2018 | tcp_conn->tc_state= TCS_CLOSING;
|
---|
2019 | }
|
---|
2020 |
|
---|
2021 | /* Set the retransmission timeout a bit smaller. */
|
---|
2022 | tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CLOSING;
|
---|
2023 |
|
---|
2024 | /* If all data has been acknowledged, close the connection. */
|
---|
2025 | if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
|
---|
2026 | tcp_close_connection(tcp_conn, ENOTCONN);
|
---|
2027 | }
|
---|
2028 |
|
---|
2029 | PUBLIC int tcp_cancel(fd, which_operation)
|
---|
2030 | int fd;
|
---|
2031 | int which_operation;
|
---|
2032 | {
|
---|
2033 | tcp_fd_t *tcp_fd;
|
---|
2034 | tcp_conn_t *tcp_conn;
|
---|
2035 |
|
---|
2036 | tcp_fd= &tcp_fd_table[fd];
|
---|
2037 |
|
---|
2038 | assert (tcp_fd->tf_flags & TFF_INUSE);
|
---|
2039 |
|
---|
2040 | tcp_conn= tcp_fd->tf_conn;
|
---|
2041 |
|
---|
2042 | switch (which_operation)
|
---|
2043 | {
|
---|
2044 | case SR_CANCEL_WRITE:
|
---|
2045 | assert (tcp_fd->tf_flags & TFF_WRITE_IP);
|
---|
2046 | tcp_fd->tf_flags &= ~TFF_WRITE_IP;
|
---|
2047 |
|
---|
2048 | if (tcp_fd->tf_write_offset)
|
---|
2049 | reply_thr_get (tcp_fd, tcp_fd->tf_write_offset, FALSE);
|
---|
2050 | else
|
---|
2051 | reply_thr_get (tcp_fd, EINTR, FALSE);
|
---|
2052 | break;
|
---|
2053 | case SR_CANCEL_READ:
|
---|
2054 | assert (tcp_fd->tf_flags & TFF_READ_IP);
|
---|
2055 | tcp_fd->tf_flags &= ~TFF_READ_IP;
|
---|
2056 | if (tcp_fd->tf_read_offset)
|
---|
2057 | reply_thr_put (tcp_fd, tcp_fd->tf_read_offset, FALSE);
|
---|
2058 | else
|
---|
2059 | reply_thr_put (tcp_fd, EINTR, FALSE);
|
---|
2060 | break;
|
---|
2061 | case SR_CANCEL_IOCTL:
|
---|
2062 | assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
|
---|
2063 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
2064 |
|
---|
2065 | if (tcp_fd->tf_flags & TFF_IOC_INIT_SP)
|
---|
2066 | {
|
---|
2067 | tcp_fd->tf_flags &= ~TFF_IOC_INIT_SP;
|
---|
2068 | reply_thr_put (tcp_fd, EINTR, TRUE);
|
---|
2069 | break;
|
---|
2070 | }
|
---|
2071 |
|
---|
2072 | switch (tcp_fd->tf_ioreq)
|
---|
2073 | {
|
---|
2074 | case NWIOGTCPCONF:
|
---|
2075 | reply_thr_put (tcp_fd, EINTR, TRUE);
|
---|
2076 | break;
|
---|
2077 | case NWIOSTCPCONF:
|
---|
2078 | case NWIOTCPSHUTDOWN:
|
---|
2079 | reply_thr_get (tcp_fd, EINTR, TRUE);
|
---|
2080 | break;
|
---|
2081 | case NWIOTCPCONN:
|
---|
2082 | case NWIOTCPLISTEN:
|
---|
2083 | assert (tcp_conn->tc_connInprogress);
|
---|
2084 | tcp_conn->tc_connInprogress= 0;
|
---|
2085 | tcp_conn->tc_fd= NULL;
|
---|
2086 | tcp_fd->tf_conn= NULL;
|
---|
2087 | tcp_close_connection(tcp_conn, ENOCONN);
|
---|
2088 | reply_thr_get (tcp_fd, EINTR, TRUE);
|
---|
2089 | break;
|
---|
2090 | default:
|
---|
2091 | ip_warning(( "unknown ioctl inprogress: 0x%x",
|
---|
2092 | tcp_fd->tf_ioreq ));
|
---|
2093 | reply_thr_get (tcp_fd, EINTR, TRUE);
|
---|
2094 | break;
|
---|
2095 | }
|
---|
2096 | break;
|
---|
2097 | default:
|
---|
2098 | ip_panic(( "unknown cancel request" ));
|
---|
2099 | break;
|
---|
2100 | }
|
---|
2101 | return NW_OK;
|
---|
2102 | }
|
---|
2103 |
|
---|
2104 | /*
|
---|
2105 | tcp_connect
|
---|
2106 | */
|
---|
2107 |
|
---|
2108 | PRIVATE int tcp_connect(tcp_fd)
|
---|
2109 | tcp_fd_t *tcp_fd;
|
---|
2110 | {
|
---|
2111 | tcp_conn_t *tcp_conn;
|
---|
2112 | nwio_tcpcl_t *tcpcl;
|
---|
2113 | long nwtcl_flags;
|
---|
2114 | int r, do_asynch;
|
---|
2115 | acc_t *data;
|
---|
2116 |
|
---|
2117 | if (!(tcp_fd->tf_flags & TFF_CONF_SET))
|
---|
2118 | {
|
---|
2119 | tcp_reply_ioctl(tcp_fd, EBADMODE);
|
---|
2120 | return NW_OK;
|
---|
2121 | }
|
---|
2122 | assert (!(tcp_fd->tf_flags & TFF_CONNECTED) &&
|
---|
2123 | !(tcp_fd->tf_flags & TFF_CONNECTING) &&
|
---|
2124 | !(tcp_fd->tf_flags & TFF_LISTENQ));
|
---|
2125 | if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
|
---|
2126 | != (NWTC_SET_RA|NWTC_SET_RP))
|
---|
2127 | {
|
---|
2128 | tcp_reply_ioctl(tcp_fd, EBADMODE);
|
---|
2129 | return NW_OK;
|
---|
2130 | }
|
---|
2131 |
|
---|
2132 | data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
|
---|
2133 | sizeof(*tcpcl), TRUE);
|
---|
2134 | if (!data)
|
---|
2135 | return EFAULT;
|
---|
2136 |
|
---|
2137 | data= bf_packIffLess(data, sizeof(*tcpcl));
|
---|
2138 | assert (data->acc_length == sizeof(*tcpcl));
|
---|
2139 | tcpcl= (nwio_tcpcl_t *)ptr2acc_data(data);
|
---|
2140 |
|
---|
2141 | nwtcl_flags= tcpcl->nwtcl_flags;
|
---|
2142 | bf_afree(data); data= NULL; tcpcl= NULL;
|
---|
2143 |
|
---|
2144 | if (nwtcl_flags == TCF_ASYNCH)
|
---|
2145 | do_asynch= 1;
|
---|
2146 | else if (nwtcl_flags == TCF_DEFAULT)
|
---|
2147 | do_asynch= 0;
|
---|
2148 | else
|
---|
2149 | {
|
---|
2150 | tcp_reply_ioctl(tcp_fd, EINVAL);
|
---|
2151 | return NW_OK;
|
---|
2152 | }
|
---|
2153 |
|
---|
2154 | assert(!tcp_fd->tf_conn);
|
---|
2155 | tcp_conn= find_conn_entry(tcp_fd->tf_tcpconf.nwtc_locport,
|
---|
2156 | tcp_fd->tf_port->tp_ipaddr,
|
---|
2157 | tcp_fd->tf_tcpconf.nwtc_remport,
|
---|
2158 | tcp_fd->tf_tcpconf.nwtc_remaddr);
|
---|
2159 | if (tcp_conn)
|
---|
2160 | {
|
---|
2161 | if (tcp_conn->tc_fd)
|
---|
2162 | {
|
---|
2163 | tcp_reply_ioctl(tcp_fd, EADDRINUSE);
|
---|
2164 | return NW_OK;
|
---|
2165 | }
|
---|
2166 | }
|
---|
2167 | else
|
---|
2168 | {
|
---|
2169 | tcp_conn= find_empty_conn();
|
---|
2170 | if (!tcp_conn)
|
---|
2171 | {
|
---|
2172 | tcp_reply_ioctl(tcp_fd, EAGAIN);
|
---|
2173 | return NW_OK;
|
---|
2174 | }
|
---|
2175 | }
|
---|
2176 | tcp_fd->tf_conn= tcp_conn;
|
---|
2177 |
|
---|
2178 | r= tcp_su4connect(tcp_fd);
|
---|
2179 | if (r == NW_SUSPEND && do_asynch)
|
---|
2180 | {
|
---|
2181 | tcp_fd->tf_flags |= TFF_CONNECTING;
|
---|
2182 | tcp_reply_ioctl(tcp_fd, EINPROGRESS);
|
---|
2183 | r= NW_OK;
|
---|
2184 | }
|
---|
2185 | return r;
|
---|
2186 | }
|
---|
2187 |
|
---|
2188 | /*
|
---|
2189 | tcp_su4connect
|
---|
2190 | */
|
---|
2191 |
|
---|
2192 | PRIVATE int tcp_su4connect(tcp_fd)
|
---|
2193 | tcp_fd_t *tcp_fd;
|
---|
2194 | {
|
---|
2195 | tcp_conn_t *tcp_conn;
|
---|
2196 |
|
---|
2197 | tcp_conn= tcp_fd->tf_conn;
|
---|
2198 |
|
---|
2199 | tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport;
|
---|
2200 | tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr;
|
---|
2201 |
|
---|
2202 | assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP);
|
---|
2203 | assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA);
|
---|
2204 | tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;
|
---|
2205 | tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;
|
---|
2206 |
|
---|
2207 | tcp_setup_conn(tcp_fd->tf_port, tcp_conn);
|
---|
2208 |
|
---|
2209 | tcp_conn->tc_fd= tcp_fd;
|
---|
2210 | tcp_conn->tc_connInprogress= 1;
|
---|
2211 | tcp_conn->tc_orglisten= FALSE;
|
---|
2212 | tcp_conn->tc_state= TCS_SYN_SENT;
|
---|
2213 | tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CONNECT;
|
---|
2214 |
|
---|
2215 | /* Start the timer (if necessary) */
|
---|
2216 | tcp_set_send_timer(tcp_conn);
|
---|
2217 |
|
---|
2218 | tcp_conn_write(tcp_conn, 0);
|
---|
2219 |
|
---|
2220 | if (tcp_conn->tc_connInprogress)
|
---|
2221 | return NW_SUSPEND;
|
---|
2222 | else
|
---|
2223 | return NW_OK;
|
---|
2224 | }
|
---|
2225 |
|
---|
2226 |
|
---|
2227 | /*
|
---|
2228 | tcp_listen
|
---|
2229 | */
|
---|
2230 |
|
---|
2231 | PRIVATE int tcp_listen(tcp_fd, do_listenq)
|
---|
2232 | tcp_fd_t *tcp_fd;
|
---|
2233 | int do_listenq;
|
---|
2234 | {
|
---|
2235 | tcp_conn_t *tcp_conn;
|
---|
2236 |
|
---|
2237 | if (!(tcp_fd->tf_flags & TFF_CONF_SET))
|
---|
2238 | {
|
---|
2239 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
2240 | reply_thr_get(tcp_fd, EBADMODE, TRUE);
|
---|
2241 | return NW_OK;
|
---|
2242 | }
|
---|
2243 | assert (!(tcp_fd->tf_flags & TFF_CONNECTED) &&
|
---|
2244 | !(tcp_fd->tf_flags & TFF_CONNECTING) &&
|
---|
2245 | !(tcp_fd->tf_flags & TFF_LISTENQ));
|
---|
2246 | tcp_conn= tcp_fd->tf_conn;
|
---|
2247 | assert(!tcp_conn);
|
---|
2248 |
|
---|
2249 | if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
|
---|
2250 | == (NWTC_SET_RA|NWTC_SET_RP))
|
---|
2251 | {
|
---|
2252 | tcp_conn= find_conn_entry(
|
---|
2253 | tcp_fd->tf_tcpconf.nwtc_locport,
|
---|
2254 | tcp_fd->tf_port->tp_ipaddr,
|
---|
2255 | tcp_fd->tf_tcpconf.nwtc_remport,
|
---|
2256 | tcp_fd->tf_tcpconf.nwtc_remaddr);
|
---|
2257 | if (tcp_conn)
|
---|
2258 | {
|
---|
2259 | if (tcp_conn->tc_fd)
|
---|
2260 | {
|
---|
2261 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
2262 | reply_thr_get (tcp_fd, EADDRINUSE, TRUE);
|
---|
2263 | return NW_OK;
|
---|
2264 | }
|
---|
2265 | tcp_fd->tf_conn= tcp_conn;
|
---|
2266 | return tcp_su4listen(tcp_fd, tcp_conn, do_listenq);
|
---|
2267 | }
|
---|
2268 | }
|
---|
2269 | tcp_conn= find_empty_conn();
|
---|
2270 | if (!tcp_conn)
|
---|
2271 | {
|
---|
2272 | tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
|
---|
2273 | reply_thr_get (tcp_fd, EAGAIN, TRUE);
|
---|
2274 | return NW_OK;
|
---|
2275 | }
|
---|
2276 | tcp_fd->tf_conn= tcp_conn;
|
---|
2277 | return tcp_su4listen(tcp_fd, tcp_conn, do_listenq);
|
---|
2278 | }
|
---|
2279 |
|
---|
2280 | /*
|
---|
2281 | tcp_acceptto
|
---|
2282 | */
|
---|
2283 |
|
---|
2284 | PRIVATE int tcp_acceptto(tcp_fd)
|
---|
2285 | tcp_fd_t *tcp_fd;
|
---|
2286 | {
|
---|
2287 | int i, dst_nr;
|
---|
2288 | tcp_fd_t *dst_fd;
|
---|
2289 | tcp_conn_t *tcp_conn;
|
---|
2290 | tcp_cookie_t *cookiep;
|
---|
2291 | acc_t *data;
|
---|
2292 | tcp_cookie_t cookie;
|
---|
2293 |
|
---|
2294 | if (!(tcp_fd->tf_flags & TFF_LISTENQ))
|
---|
2295 | {
|
---|
2296 | tcp_reply_ioctl(tcp_fd, EINVAL);
|
---|
2297 | return NW_OK;
|
---|
2298 | }
|
---|
2299 | for (i= 0; i<TFL_LISTEN_MAX; i++)
|
---|
2300 | {
|
---|
2301 | tcp_conn= tcp_fd->tf_listenq[i];
|
---|
2302 | if (tcp_conn && !tcp_conn->tc_connInprogress)
|
---|
2303 | break;
|
---|
2304 | }
|
---|
2305 | if (i >= TFL_LISTEN_MAX)
|
---|
2306 | {
|
---|
2307 | /* Nothing, suspend caller */
|
---|
2308 | return NW_SUSPEND;
|
---|
2309 | }
|
---|
2310 |
|
---|
2311 | data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
|
---|
2312 | sizeof(*cookiep), TRUE);
|
---|
2313 | if (!data)
|
---|
2314 | return EFAULT;
|
---|
2315 |
|
---|
2316 | data= bf_packIffLess(data, sizeof(*cookiep));
|
---|
2317 | cookiep= (tcp_cookie_t *)ptr2acc_data(data);
|
---|
2318 | cookie= *cookiep;
|
---|
2319 |
|
---|
2320 | bf_afree(data); data= NULL;
|
---|
2321 |
|
---|
2322 | dst_nr= cookie.tc_ref;
|
---|
2323 | if (dst_nr < 0 || dst_nr >= TCP_FD_NR)
|
---|
2324 | {
|
---|
2325 | printf("tcp_acceptto: bad fd %d\n", dst_nr);
|
---|
2326 | tcp_reply_ioctl(tcp_fd, EINVAL);
|
---|
2327 | return NW_OK;
|
---|
2328 | }
|
---|
2329 | dst_fd= &tcp_fd_table[dst_nr];
|
---|
2330 | if (!(dst_fd->tf_flags & TFF_INUSE) ||
|
---|
2331 | (dst_fd->tf_flags & (TFF_READ_IP|TFF_WRITE_IP|TFF_IOCTL_IP)) ||
|
---|
2332 | dst_fd->tf_conn != NULL ||
|
---|
2333 | !(dst_fd->tf_flags & TFF_COOKIE))
|
---|
2334 | {
|
---|
2335 | printf("tcp_acceptto: bad flags 0x%x or conn %p for fd %d\n",
|
---|
2336 | dst_fd->tf_flags, dst_fd->tf_conn, dst_nr);
|
---|
2337 | tcp_reply_ioctl(tcp_fd, EINVAL);
|
---|
2338 | return NW_OK;
|
---|
2339 | }
|
---|
2340 | if (memcmp(&cookie, &dst_fd->tf_cookie, sizeof(cookie)) != 0)
|
---|
2341 | {
|
---|
2342 | printf("tcp_acceptto: bad cookie\n");
|
---|
2343 | return NW_OK;
|
---|
2344 | }
|
---|
2345 |
|
---|
2346 | /* Move connection */
|
---|
2347 | tcp_fd->tf_listenq[i]= NULL;
|
---|
2348 | tcp_conn->tc_fd= dst_fd;
|
---|
2349 | dst_fd->tf_conn= tcp_conn;
|
---|
2350 | dst_fd->tf_flags |= TFF_CONNECTED;
|
---|
2351 |
|
---|
2352 | tcp_reply_ioctl(tcp_fd, NW_OK);
|
---|
2353 | return NW_OK;
|
---|
2354 | }
|
---|
2355 |
|
---|
2356 |
|
---|
2357 | PRIVATE void tcp_buffree (priority)
|
---|
2358 | int priority;
|
---|
2359 | {
|
---|
2360 | int i;
|
---|
2361 | tcp_conn_t *tcp_conn;
|
---|
2362 |
|
---|
2363 | if (priority == TCP_PRI_FRAG2SEND)
|
---|
2364 | {
|
---|
2365 | for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
|
---|
2366 | tcp_conn++)
|
---|
2367 | {
|
---|
2368 | if (!(tcp_conn->tc_flags & TCF_INUSE))
|
---|
2369 | continue;
|
---|
2370 | if (!tcp_conn->tc_frag2send)
|
---|
2371 | continue;
|
---|
2372 | if (tcp_conn->tc_busy)
|
---|
2373 | continue;
|
---|
2374 | bf_afree(tcp_conn->tc_frag2send);
|
---|
2375 | tcp_conn->tc_frag2send= 0;
|
---|
2376 | }
|
---|
2377 | }
|
---|
2378 |
|
---|
2379 | if (priority == TCP_PRI_CONN_EXTRA)
|
---|
2380 | {
|
---|
2381 | for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
|
---|
2382 | tcp_conn++)
|
---|
2383 | {
|
---|
2384 | if (!(tcp_conn->tc_flags & TCF_INUSE))
|
---|
2385 | continue;
|
---|
2386 | if (tcp_conn->tc_busy)
|
---|
2387 | continue;
|
---|
2388 | if (tcp_conn->tc_adv_data)
|
---|
2389 | {
|
---|
2390 | bf_afree(tcp_conn->tc_adv_data);
|
---|
2391 | tcp_conn->tc_adv_data= NULL;
|
---|
2392 | }
|
---|
2393 | }
|
---|
2394 | }
|
---|
2395 |
|
---|
2396 | if (priority == TCP_PRI_CONNwoUSER)
|
---|
2397 | {
|
---|
2398 | for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
|
---|
2399 | tcp_conn++)
|
---|
2400 | {
|
---|
2401 | if (!(tcp_conn->tc_flags & TCF_INUSE))
|
---|
2402 | continue;
|
---|
2403 | if (tcp_conn->tc_busy)
|
---|
2404 | continue;
|
---|
2405 | if (tcp_conn->tc_fd)
|
---|
2406 | continue;
|
---|
2407 | if (tcp_conn->tc_state == TCS_CLOSED)
|
---|
2408 | continue;
|
---|
2409 | if (tcp_conn->tc_rcvd_data == NULL &&
|
---|
2410 | tcp_conn->tc_send_data == NULL)
|
---|
2411 | {
|
---|
2412 | continue;
|
---|
2413 | }
|
---|
2414 | tcp_close_connection (tcp_conn, EOUTOFBUFS);
|
---|
2415 | }
|
---|
2416 | }
|
---|
2417 |
|
---|
2418 | if (priority == TCP_PRI_CONN_INUSE)
|
---|
2419 | {
|
---|
2420 | for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
|
---|
2421 | tcp_conn++)
|
---|
2422 | {
|
---|
2423 | if (!(tcp_conn->tc_flags & TCF_INUSE))
|
---|
2424 | continue;
|
---|
2425 | if (tcp_conn->tc_busy)
|
---|
2426 | continue;
|
---|
2427 | if (tcp_conn->tc_state == TCS_CLOSED)
|
---|
2428 | continue;
|
---|
2429 | if (tcp_conn->tc_rcvd_data == NULL &&
|
---|
2430 | tcp_conn->tc_send_data == NULL)
|
---|
2431 | {
|
---|
2432 | continue;
|
---|
2433 | }
|
---|
2434 | tcp_close_connection (tcp_conn, EOUTOFBUFS);
|
---|
2435 | }
|
---|
2436 | }
|
---|
2437 | }
|
---|
2438 |
|
---|
2439 | #ifdef BUF_CONSISTENCY_CHECK
|
---|
2440 | PRIVATE void tcp_bufcheck()
|
---|
2441 | {
|
---|
2442 | int i;
|
---|
2443 | tcp_conn_t *tcp_conn;
|
---|
2444 | tcp_port_t *tcp_port;
|
---|
2445 |
|
---|
2446 | for (i= 0, tcp_port= tcp_port_table; i<tcp_conf_nr; i++, tcp_port++)
|
---|
2447 | {
|
---|
2448 | if (tcp_port->tp_pack)
|
---|
2449 | bf_check_acc(tcp_port->tp_pack);
|
---|
2450 | }
|
---|
2451 | for (i= 0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++, tcp_conn++)
|
---|
2452 | {
|
---|
2453 | assert(!tcp_conn->tc_busy);
|
---|
2454 | if (tcp_conn->tc_rcvd_data)
|
---|
2455 | bf_check_acc(tcp_conn->tc_rcvd_data);
|
---|
2456 | if (tcp_conn->tc_adv_data)
|
---|
2457 | bf_check_acc(tcp_conn->tc_adv_data);
|
---|
2458 | if (tcp_conn->tc_send_data)
|
---|
2459 | bf_check_acc(tcp_conn->tc_send_data);
|
---|
2460 | if (tcp_conn->tc_remipopt)
|
---|
2461 | bf_check_acc(tcp_conn->tc_remipopt);
|
---|
2462 | if (tcp_conn->tc_tcpopt)
|
---|
2463 | bf_check_acc(tcp_conn->tc_tcpopt);
|
---|
2464 | if (tcp_conn->tc_frag2send)
|
---|
2465 | bf_check_acc(tcp_conn->tc_frag2send);
|
---|
2466 | }
|
---|
2467 | }
|
---|
2468 | #endif
|
---|
2469 |
|
---|
2470 | PUBLIC void tcp_notreach(tcp_conn)
|
---|
2471 | tcp_conn_t *tcp_conn;
|
---|
2472 | {
|
---|
2473 | int new_ttl;
|
---|
2474 |
|
---|
2475 | new_ttl= tcp_conn->tc_ttl;
|
---|
2476 | if (new_ttl == IP_MAX_TTL)
|
---|
2477 | {
|
---|
2478 | if (tcp_conn->tc_state == TCS_SYN_SENT)
|
---|
2479 | tcp_close_connection(tcp_conn, EDSTNOTRCH);
|
---|
2480 | return;
|
---|
2481 | }
|
---|
2482 | else if (new_ttl < TCP_DEF_TTL_NEXT)
|
---|
2483 | new_ttl= TCP_DEF_TTL_NEXT;
|
---|
2484 | else
|
---|
2485 | {
|
---|
2486 | new_ttl *= 2;
|
---|
2487 | if (new_ttl> IP_MAX_TTL)
|
---|
2488 | new_ttl= IP_MAX_TTL;
|
---|
2489 | }
|
---|
2490 | tcp_conn->tc_ttl= new_ttl;
|
---|
2491 | tcp_conn->tc_stt= 0;
|
---|
2492 | tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
|
---|
2493 | tcp_conn_write(tcp_conn, 1);
|
---|
2494 | }
|
---|
2495 |
|
---|
2496 | FORWARD u32_t mtu_table[]=
|
---|
2497 | { /* From RFC-1191 */
|
---|
2498 | /* Plateau MTU Comments Reference */
|
---|
2499 | /* ------ --- -------- --------- */
|
---|
2500 | /* 65535 Official maximum MTU RFC 791 */
|
---|
2501 | /* 65535 Hyperchannel RFC 1044 */
|
---|
2502 | 65535,
|
---|
2503 | 32000, /* Just in case */
|
---|
2504 | /* 17914 16Mb IBM Token Ring ref. [6] */
|
---|
2505 | 17914,
|
---|
2506 | /* 8166 IEEE 802.4 RFC 1042 */
|
---|
2507 | 8166,
|
---|
2508 | /* 4464 IEEE 802.5 (4Mb max) RFC 1042 */
|
---|
2509 | /* 4352 FDDI (Revised) RFC 1188 */
|
---|
2510 | 4352, /* (1%) */
|
---|
2511 | /* 2048 Wideband Network RFC 907 */
|
---|
2512 | /* 2002 IEEE 802.5 (4Mb recommended) RFC 1042 */
|
---|
2513 | 2002, /* (2%) */
|
---|
2514 | /* 1536 Exp. Ethernet Nets RFC 895 */
|
---|
2515 | /* 1500 Ethernet Networks RFC 894 */
|
---|
2516 | /* 1500 Point-to-Point (default) RFC 1134 */
|
---|
2517 | /* 1492 IEEE 802.3 RFC 1042 */
|
---|
2518 | 1492, /* (3%) */
|
---|
2519 | /* 1006 SLIP RFC 1055 */
|
---|
2520 | /* 1006 ARPANET BBN 1822 */
|
---|
2521 | 1006,
|
---|
2522 | /* 576 X.25 Networks RFC 877 */
|
---|
2523 | /* 544 DEC IP Portal ref. [10] */
|
---|
2524 | /* 512 NETBIOS RFC 1088 */
|
---|
2525 | /* 508 IEEE 802/Source-Rt Bridge RFC 1042 */
|
---|
2526 | /* 508 ARCNET RFC 1051 */
|
---|
2527 | 508, /* (13%) */
|
---|
2528 | /* 296 Point-to-Point (low delay) RFC 1144 */
|
---|
2529 | 296,
|
---|
2530 | 68, /* Official minimum MTU RFC 791 */
|
---|
2531 | 0, /* End of list */
|
---|
2532 | };
|
---|
2533 |
|
---|
2534 | PUBLIC void tcp_mtu_exceeded(tcp_conn)
|
---|
2535 | tcp_conn_t *tcp_conn;
|
---|
2536 | {
|
---|
2537 | u16_t mtu;
|
---|
2538 | int i;
|
---|
2539 | clock_t curr_time;
|
---|
2540 |
|
---|
2541 | if (!(tcp_conn->tc_flags & TCF_PMTU))
|
---|
2542 | {
|
---|
2543 | /* Strange, got MTU exceeded but DF is not set. Ignore
|
---|
2544 | * the error. If the problem persists, the connection will
|
---|
2545 | * time-out.
|
---|
2546 | */
|
---|
2547 | return;
|
---|
2548 | }
|
---|
2549 | curr_time= get_time();
|
---|
2550 |
|
---|
2551 | /* We get here in cases. Either were are trying to find an MTU
|
---|
2552 | * that works at all, or we are trying see how far we can increase
|
---|
2553 | * the current MTU. If the last change to the MTU was a long time
|
---|
2554 | * ago, we assume the second case.
|
---|
2555 | */
|
---|
2556 | if (curr_time >= tcp_conn->tc_mtutim + TCP_PMTU_INCR_IV)
|
---|
2557 | {
|
---|
2558 | mtu= tcp_conn->tc_mtu;
|
---|
2559 | mtu -= mtu/TCP_PMTU_INCR_FRAC;
|
---|
2560 | tcp_conn->tc_mtu= mtu;
|
---|
2561 | tcp_conn->tc_mtutim= curr_time;
|
---|
2562 | DBLOCK(1, printf(
|
---|
2563 | "tcp_mtu_exceeded: new (lowered) mtu %d for conn %d\n",
|
---|
2564 | mtu, tcp_conn-tcp_conn_table));
|
---|
2565 | tcp_conn->tc_stt= 0;
|
---|
2566 | tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
|
---|
2567 | tcp_conn_write(tcp_conn, 1);
|
---|
2568 | return;
|
---|
2569 | }
|
---|
2570 |
|
---|
2571 | tcp_conn->tc_mtutim= curr_time;
|
---|
2572 | mtu= tcp_conn->tc_mtu;
|
---|
2573 | for (i= 0; mtu_table[i] >= mtu; i++)
|
---|
2574 | ; /* Nothing to do */
|
---|
2575 | mtu= mtu_table[i];
|
---|
2576 | if (mtu >= TCP_MIN_PATH_MTU)
|
---|
2577 | {
|
---|
2578 | tcp_conn->tc_mtu= mtu;
|
---|
2579 | }
|
---|
2580 | else
|
---|
2581 | {
|
---|
2582 | /* Small MTUs can be used for denial-of-service attacks.
|
---|
2583 | * Switch-off PMTU if the MTU becomes too small.
|
---|
2584 | */
|
---|
2585 | tcp_conn->tc_flags &= ~TCF_PMTU;
|
---|
2586 | tcp_conn->tc_mtu= TCP_MIN_PATH_MTU;
|
---|
2587 | DBLOCK(1, printf(
|
---|
2588 | "tcp_mtu_exceeded: clearing TCF_PMTU for conn %d\n",
|
---|
2589 | tcp_conn-tcp_conn_table););
|
---|
2590 |
|
---|
2591 | }
|
---|
2592 | DBLOCK(1, printf("tcp_mtu_exceeded: new mtu %d for conn %d\n",
|
---|
2593 | mtu, tcp_conn-tcp_conn_table););
|
---|
2594 | tcp_conn->tc_stt= 0;
|
---|
2595 | tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
|
---|
2596 | tcp_conn_write(tcp_conn, 1);
|
---|
2597 | }
|
---|
2598 |
|
---|
2599 | PUBLIC void tcp_mtu_incr(tcp_conn)
|
---|
2600 | tcp_conn_t *tcp_conn;
|
---|
2601 | {
|
---|
2602 | clock_t curr_time;
|
---|
2603 | u32_t mtu;
|
---|
2604 |
|
---|
2605 | assert(tcp_conn->tc_mtu < tcp_conn->tc_max_mtu);
|
---|
2606 | if (!(tcp_conn->tc_flags & TCF_PMTU))
|
---|
2607 | {
|
---|
2608 | /* Use a much longer time-out for retrying PMTU discovery
|
---|
2609 | * after is has been disabled. Note that PMTU discovery
|
---|
2610 | * can be disabled during a short loss of connectivity.
|
---|
2611 | */
|
---|
2612 | curr_time= get_time();
|
---|
2613 | if (curr_time > tcp_conn->tc_mtutim+TCP_PMTU_EN_IV)
|
---|
2614 | {
|
---|
2615 | tcp_conn->tc_flags |= TCF_PMTU;
|
---|
2616 | DBLOCK(1, printf(
|
---|
2617 | "tcp_mtu_incr: setting TCF_PMTU for conn %d\n",
|
---|
2618 | tcp_conn-tcp_conn_table););
|
---|
2619 | }
|
---|
2620 | return;
|
---|
2621 | }
|
---|
2622 |
|
---|
2623 | mtu= tcp_conn->tc_mtu;
|
---|
2624 | mtu += mtu/TCP_PMTU_INCR_FRAC;
|
---|
2625 | if (mtu > tcp_conn->tc_max_mtu)
|
---|
2626 | mtu= tcp_conn->tc_max_mtu;
|
---|
2627 | tcp_conn->tc_mtu= mtu;
|
---|
2628 | DBLOCK(0x1, printf("tcp_mtu_incr: new mtu %ld for conn %d\n",
|
---|
2629 | mtu, tcp_conn-tcp_conn_table););
|
---|
2630 | }
|
---|
2631 |
|
---|
2632 | /*
|
---|
2633 | tcp_setup_conn
|
---|
2634 | */
|
---|
2635 |
|
---|
2636 | PRIVATE void tcp_setup_conn(tcp_port, tcp_conn)
|
---|
2637 | tcp_port_t *tcp_port;
|
---|
2638 | tcp_conn_t *tcp_conn;
|
---|
2639 | {
|
---|
2640 | u16_t mss;
|
---|
2641 |
|
---|
2642 | assert(!tcp_conn->tc_connInprogress);
|
---|
2643 | tcp_conn->tc_port= tcp_port;
|
---|
2644 | if (tcp_conn->tc_flags & TCF_INUSE)
|
---|
2645 | {
|
---|
2646 | assert (tcp_conn->tc_state == TCS_CLOSED);
|
---|
2647 | assert (!tcp_conn->tc_send_data);
|
---|
2648 | if (tcp_conn->tc_senddis < get_time())
|
---|
2649 | tcp_conn->tc_ISS= 0;
|
---|
2650 | }
|
---|
2651 | else
|
---|
2652 | {
|
---|
2653 | assert(!tcp_conn->tc_busy);
|
---|
2654 | tcp_conn->tc_senddis= 0;
|
---|
2655 | tcp_conn->tc_ISS= 0;
|
---|
2656 | tcp_conn->tc_tos= TCP_DEF_TOS;
|
---|
2657 | tcp_conn->tc_ttl= TCP_DEF_TTL;
|
---|
2658 | tcp_conn->tc_rcv_wnd= TCP_MAX_RCV_WND_SIZE;
|
---|
2659 | tcp_conn->tc_fd= NULL;
|
---|
2660 | }
|
---|
2661 | if (!tcp_conn->tc_ISS)
|
---|
2662 | {
|
---|
2663 | tcp_conn->tc_ISS= tcp_rand32();
|
---|
2664 | }
|
---|
2665 | tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
|
---|
2666 | tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
|
---|
2667 | tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS+1;
|
---|
2668 | tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;
|
---|
2669 | tcp_conn->tc_SND_PSH= tcp_conn->tc_ISS+1;
|
---|
2670 | tcp_conn->tc_IRS= 0;
|
---|
2671 | tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS;
|
---|
2672 | tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS;
|
---|
2673 | tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS;
|
---|
2674 | tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
|
---|
2675 |
|
---|
2676 | assert(tcp_conn->tc_rcvd_data == NULL);
|
---|
2677 | assert(tcp_conn->tc_adv_data == NULL);
|
---|
2678 | assert(tcp_conn->tc_send_data == NULL);
|
---|
2679 |
|
---|
2680 | tcp_conn->tc_ka_time= TCP_DEF_KEEPALIVE;
|
---|
2681 |
|
---|
2682 | tcp_conn->tc_remipopt= NULL;
|
---|
2683 | tcp_conn->tc_tcpopt= NULL;
|
---|
2684 |
|
---|
2685 | assert(tcp_conn->tc_frag2send == NULL);
|
---|
2686 |
|
---|
2687 | tcp_conn->tc_stt= 0;
|
---|
2688 | tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
|
---|
2689 | tcp_conn->tc_0wnd_to= 0;
|
---|
2690 | tcp_conn->tc_artt= TCP_DEF_RTT*TCP_RTT_SCALE;
|
---|
2691 | tcp_conn->tc_drtt= 0;
|
---|
2692 | tcp_conn->tc_rtt= TCP_DEF_RTT;
|
---|
2693 | tcp_conn->tc_max_mtu= tcp_conn->tc_port->tp_mtu;
|
---|
2694 | tcp_conn->tc_mtu= tcp_conn->tc_max_mtu;
|
---|
2695 | tcp_conn->tc_mtutim= 0;
|
---|
2696 | tcp_conn->tc_error= NW_OK;
|
---|
2697 | mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
|
---|
2698 | tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + 2*mss;
|
---|
2699 | tcp_conn->tc_snd_cthresh= TCP_MAX_SND_WND_SIZE;
|
---|
2700 | tcp_conn->tc_snd_cinc=
|
---|
2701 | (long)TCP_DEF_MSS*TCP_DEF_MSS/TCP_MAX_SND_WND_SIZE+1;
|
---|
2702 | tcp_conn->tc_snd_wnd= TCP_MAX_SND_WND_SIZE;
|
---|
2703 | tcp_conn->tc_rt_time= 0;
|
---|
2704 | tcp_conn->tc_rt_seq= 0;
|
---|
2705 | tcp_conn->tc_rt_threshold= tcp_conn->tc_ISS;
|
---|
2706 | tcp_conn->tc_flags= TCF_INUSE;
|
---|
2707 | tcp_conn->tc_flags |= TCF_PMTU;
|
---|
2708 |
|
---|
2709 | clck_untimer(&tcp_conn->tc_transmit_timer);
|
---|
2710 | tcp_conn->tc_transmit_seq= 0;
|
---|
2711 | }
|
---|
2712 |
|
---|
2713 | PRIVATE u32_t tcp_rand32()
|
---|
2714 | {
|
---|
2715 | u8_t bits[RAND256_BUFSIZE];
|
---|
2716 |
|
---|
2717 | rand256(bits);
|
---|
2718 | return bits[0] | (bits[1] << 8) | (bits[2] << 16) | (bits[3] << 24);
|
---|
2719 | }
|
---|
2720 |
|
---|
2721 | /*
|
---|
2722 | * $PchId: tcp.c,v 1.34 2005/06/28 14:20:27 philip Exp $
|
---|
2723 | */
|
---|