00001
00002
00003
00004
00005
00006
00007 #include "inet.h"
00008 #include "buf.h"
00009 #include "clock.h"
00010 #include "event.h"
00011 #include "type.h"
00012
00013 #include "io.h"
00014 #include "ip.h"
00015 #include "sr.h"
00016 #include "assert.h"
00017 #include "rand256.h"
00018 #include "tcp.h"
00019 #include "tcp_int.h"
00020
00021 THIS_FILE
00022
00023 #define NOT_IMPLEMENTED 0
00024
00025 PUBLIC tcp_port_t *tcp_port_table;
00026 PUBLIC tcp_fd_t tcp_fd_table[TCP_FD_NR];
00027 PUBLIC tcp_conn_t tcp_conn_table[TCP_CONN_NR];
00028 PUBLIC sr_cancel_t tcp_cancel_f;
00029
00030 FORWARD void tcp_main ARGS(( tcp_port_t *port ));
00031 FORWARD int tcp_select ARGS(( int fd, unsigned operations ));
00032 FORWARD acc_t *tcp_get_data ARGS(( int fd, size_t offset,
00033 size_t count, int for_ioctl ));
00034 FORWARD int tcp_put_data ARGS(( int fd, size_t offset,
00035 acc_t *data, int for_ioctl ));
00036 FORWARD void tcp_put_pkt ARGS(( int fd, acc_t *data, size_t datalen ));
00037 FORWARD void read_ip_packets ARGS(( tcp_port_t *port ));
00038 FORWARD int tcp_setconf ARGS(( tcp_fd_t *tcp_fd ));
00039 FORWARD int tcp_setopt ARGS(( tcp_fd_t *tcp_fd ));
00040 FORWARD int tcp_connect ARGS(( tcp_fd_t *tcp_fd ));
00041 FORWARD int tcp_listen ARGS(( tcp_fd_t *tcp_fd, int do_listenq ));
00042 FORWARD int tcp_acceptto ARGS(( tcp_fd_t *tcp_fd ));
00043 FORWARD tcpport_t find_unused_port ARGS(( int fd ));
00044 FORWARD int is_unused_port ARGS(( Tcpport_t port ));
00045 FORWARD int reply_thr_put ARGS(( tcp_fd_t *tcp_fd, int reply,
00046 int for_ioctl ));
00047 FORWARD void reply_thr_get ARGS(( tcp_fd_t *tcp_fd, int reply,
00048 int for_ioctl ));
00049 FORWARD tcp_conn_t *find_conn_entry ARGS(( Tcpport_t locport,
00050 ipaddr_t locaddr, Tcpport_t remport, ipaddr_t readaddr ));
00051 FORWARD tcp_conn_t *find_empty_conn ARGS(( void ));
00052 FORWARD tcp_conn_t *find_best_conn ARGS(( ip_hdr_t *ip_hdr,
00053 tcp_hdr_t *tcp_hdr ));
00054 FORWARD tcp_conn_t *new_conn_for_queue ARGS(( tcp_fd_t *tcp_fd ));
00055 FORWARD int maybe_listen ARGS(( ipaddr_t locaddr, Tcpport_t locport,
00056 ipaddr_t remaddr, Tcpport_t remport ));
00057 FORWARD int tcp_su4connect ARGS(( tcp_fd_t *tcp_fd ));
00058 FORWARD void tcp_buffree ARGS(( int priority ));
00059 #ifdef BUF_CONSISTENCY_CHECK
00060 FORWARD void tcp_bufcheck ARGS(( void ));
00061 #endif
00062 FORWARD void tcp_setup_conn ARGS(( tcp_port_t *tcp_port,
00063 tcp_conn_t *tcp_conn ));
00064 FORWARD u32_t tcp_rand32 ARGS(( void ));
00065
00066 PUBLIC void tcp_prep()
00067 {
00068 tcp_port_table= alloc(tcp_conf_nr * sizeof(tcp_port_table[0]));
00069 }
00070
00071 PUBLIC void tcp_init()
00072 {
00073 int i, j, k, ifno;
00074 tcp_fd_t *tcp_fd;
00075 tcp_port_t *tcp_port;
00076 tcp_conn_t *tcp_conn;
00077
00078 assert (BUF_S >= sizeof(struct nwio_ipopt));
00079 assert (BUF_S >= sizeof(struct nwio_ipconf));
00080 assert (BUF_S >= sizeof(struct nwio_tcpconf));
00081 assert (BUF_S >= IP_MAX_HDR_SIZE + TCP_MAX_HDR_SIZE);
00082
00083 for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++, tcp_fd++)
00084 {
00085 tcp_fd->tf_flags= TFF_EMPTY;
00086 }
00087
00088 for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
00089 tcp_fd++)
00090 {
00091 tcp_conn->tc_flags= TCF_EMPTY;
00092 tcp_conn->tc_busy= 0;
00093 }
00094
00095 #ifndef BUF_CONSISTENCY_CHECK
00096 bf_logon(tcp_buffree);
00097 #else
00098 bf_logon(tcp_buffree, tcp_bufcheck);
00099 #endif
00100
00101 for (i=0, tcp_port= tcp_port_table; i<tcp_conf_nr; i++, tcp_port++)
00102 {
00103 tcp_port->tp_ipdev= tcp_conf[i].tc_port;
00104
00105 tcp_port->tp_flags= TPF_EMPTY;
00106 tcp_port->tp_state= TPS_EMPTY;
00107 tcp_port->tp_snd_head= NULL;
00108 tcp_port->tp_snd_tail= NULL;
00109 ev_init(&tcp_port->tp_snd_event);
00110 for (j= 0; j<TCP_CONN_HASH_NR; j++)
00111 {
00112 for (k= 0; k<4; k++)
00113 {
00114 tcp_port->tp_conn_hash[j][k]=
00115 &tcp_conn_table[0];
00116 }
00117 }
00118
00119 ifno= ip_conf[tcp_port->tp_ipdev].ic_ifno;
00120 sr_add_minor(if2minor(ifno, TCP_DEV_OFF),
00121 i, tcp_open, tcp_close, tcp_read,
00122 tcp_write, tcp_ioctl, tcp_cancel, tcp_select);
00123
00124 tcp_main(tcp_port);
00125 }
00126 tcp_cancel_f= tcp_cancel;
00127 }
00128
00129 PRIVATE void tcp_main(tcp_port)
00130 tcp_port_t *tcp_port;
00131 {
00132 int result, i;
00133 tcp_conn_t *tcp_conn;
00134 tcp_fd_t *tcp_fd;
00135
00136 switch (tcp_port->tp_state)
00137 {
00138 case TPS_EMPTY:
00139 tcp_port->tp_state= TPS_SETPROTO;
00140 tcp_port->tp_ipfd= ip_open(tcp_port->tp_ipdev,
00141 tcp_port->tp_ipdev, tcp_get_data,
00142 tcp_put_data, tcp_put_pkt, 0 );
00143 if (tcp_port->tp_ipfd < 0)
00144 {
00145 tcp_port->tp_state= TPS_ERROR;
00146 DBLOCK(1, printf("%s, %d: unable to open ip port\n",
00147 __FILE__, __LINE__));
00148 return;
00149 }
00150
00151 result= ip_ioctl(tcp_port->tp_ipfd, NWIOSIPOPT);
00152 if (result == NW_SUSPEND)
00153 tcp_port->tp_flags |= TPF_SUSPEND;
00154 if (result < 0)
00155 {
00156 return;
00157 }
00158 if (tcp_port->tp_state != TPS_GETCONF)
00159 return;
00160
00161 case TPS_GETCONF:
00162 tcp_port->tp_flags &= ~TPF_SUSPEND;
00163
00164 result= ip_ioctl(tcp_port->tp_ipfd, NWIOGIPCONF);
00165 if (result == NW_SUSPEND)
00166 tcp_port->tp_flags |= TPF_SUSPEND;
00167 if (result < 0)
00168 {
00169 return;
00170 }
00171 if (tcp_port->tp_state != TPS_MAIN)
00172 return;
00173
00174 case TPS_MAIN:
00175 tcp_port->tp_flags &= ~TPF_SUSPEND;
00176 tcp_port->tp_pack= 0;
00177
00178 tcp_conn= &tcp_conn_table[tcp_port->tp_ipdev];
00179 tcp_conn->tc_flags= TCF_INUSE;
00180 assert(!tcp_conn->tc_busy);
00181 tcp_conn->tc_locport= 0;
00182 tcp_conn->tc_locaddr= tcp_port->tp_ipaddr;
00183 tcp_conn->tc_remport= 0;
00184 tcp_conn->tc_remaddr= 0;
00185 tcp_conn->tc_state= TCS_CLOSED;
00186 tcp_conn->tc_fd= 0;
00187 tcp_conn->tc_connInprogress= 0;
00188 tcp_conn->tc_orglisten= FALSE;
00189 tcp_conn->tc_senddis= 0;
00190 tcp_conn->tc_ISS= 0;
00191 tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
00192 tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
00193 tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS;
00194 tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;
00195 tcp_conn->tc_IRS= 0;
00196 tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS;
00197 tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS;
00198 tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS;
00199 tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
00200 tcp_conn->tc_port= tcp_port;
00201 tcp_conn->tc_rcvd_data= NULL;
00202 tcp_conn->tc_adv_data= NULL;
00203 tcp_conn->tc_send_data= 0;
00204 tcp_conn->tc_remipopt= NULL;
00205 tcp_conn->tc_tcpopt= NULL;
00206 tcp_conn->tc_frag2send= 0;
00207 tcp_conn->tc_tos= TCP_DEF_TOS;
00208 tcp_conn->tc_ttl= IP_MAX_TTL;
00209 tcp_conn->tc_rcv_wnd= TCP_MAX_RCV_WND_SIZE;
00210 tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
00211 tcp_conn->tc_stt= 0;
00212 tcp_conn->tc_0wnd_to= 0;
00213 tcp_conn->tc_artt= TCP_DEF_RTT*TCP_RTT_SCALE;
00214 tcp_conn->tc_drtt= 0;
00215 tcp_conn->tc_rtt= TCP_DEF_RTT;
00216 tcp_conn->tc_max_mtu= tcp_port->tp_mtu;
00217 tcp_conn->tc_mtu= tcp_conn->tc_max_mtu;
00218 tcp_conn->tc_mtutim= 0;
00219 tcp_conn->tc_error= NW_OK;
00220 tcp_conn->tc_snd_wnd= TCP_MAX_SND_WND_SIZE;
00221 tcp_conn->tc_snd_cinc=
00222 (long)TCP_DEF_MSS*TCP_DEF_MSS/TCP_MAX_SND_WND_SIZE+1;
00223
00224 tcp_conn->tc_rt_time= 0;
00225 tcp_conn->tc_rt_seq= 0;
00226 tcp_conn->tc_rt_threshold= tcp_conn->tc_ISS;
00227
00228 for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++,
00229 tcp_fd++)
00230 {
00231 if (!(tcp_fd->tf_flags & TFF_INUSE))
00232 continue;
00233 if (tcp_fd->tf_port != tcp_port)
00234 continue;
00235 if (tcp_fd->tf_flags & TFF_IOC_INIT_SP)
00236 {
00237 tcp_fd->tf_flags &= ~TFF_IOC_INIT_SP;
00238 tcp_ioctl(i, tcp_fd->tf_ioreq);
00239 }
00240 }
00241 read_ip_packets(tcp_port);
00242 return;
00243
00244 default:
00245 ip_panic(( "unknown state" ));
00246 break;
00247 }
00248 }
00249
00250 PRIVATE int tcp_select(fd, operations)
00251 int fd;
00252 unsigned operations;
00253 {
00254 int i;
00255 unsigned resops;
00256 tcp_fd_t *tcp_fd;
00257 tcp_conn_t *tcp_conn;
00258
00259 tcp_fd= &tcp_fd_table[fd];
00260 assert (tcp_fd->tf_flags & TFF_INUSE);
00261
00262 resops= 0;
00263 if (tcp_fd->tf_flags & TFF_LISTENQ)
00264 {
00265
00266 if (operations & SR_SELECT_READ)
00267 {
00268 for (i= 0; i<TFL_LISTEN_MAX; i++)
00269 {
00270 if (tcp_fd->tf_listenq[i] == NULL)
00271 continue;
00272 if (tcp_fd->tf_listenq[i]->tc_connInprogress
00273 == 0)
00274 {
00275 break;
00276 }
00277 }
00278 if (i >= TFL_LISTEN_MAX)
00279 tcp_fd->tf_flags |= TFF_SEL_READ;
00280 else
00281 resops |= SR_SELECT_READ;
00282 }
00283 if (operations & SR_SELECT_WRITE)
00284 {
00285
00286
00287
00288 resops |= SR_SELECT_WRITE;
00289 }
00290 return resops;
00291 }
00292 if (tcp_fd->tf_flags & TFF_CONNECTING)
00293 {
00294
00295 if (operations & SR_SELECT_WRITE)
00296 tcp_fd->tf_flags |= TFF_SEL_WRITE;
00297 return 0;
00298 }
00299 if (operations & SR_SELECT_READ)
00300 {
00301 tcp_conn= tcp_fd->tf_conn;
00302
00303 if (!(tcp_fd->tf_flags & TFF_CONNECTED))
00304 {
00305
00306
00307
00308
00309 resops |= SR_SELECT_READ;
00310 }
00311 else if (tcp_conn->tc_state == TCS_CLOSED ||
00312 tcp_sel_read(tcp_conn))
00313 {
00314 resops |= SR_SELECT_READ;
00315 }
00316 else if (!(operations & SR_SELECT_POLL))
00317 tcp_fd->tf_flags |= TFF_SEL_READ;
00318 }
00319 if (operations & SR_SELECT_WRITE)
00320 {
00321 tcp_conn= tcp_fd->tf_conn;
00322 if (!(tcp_fd->tf_flags & TFF_CONNECTED))
00323 {
00324
00325
00326
00327
00328 resops |= SR_SELECT_WRITE;
00329 }
00330 else if (tcp_conn->tc_state == TCS_CLOSED ||
00331 tcp_conn->tc_flags & TCF_FIN_SENT ||
00332 tcp_sel_write(tcp_conn))
00333 {
00334 resops |= SR_SELECT_WRITE;
00335 }
00336 else if (!(operations & SR_SELECT_POLL))
00337 tcp_fd->tf_flags |= TFF_SEL_WRITE;
00338 }
00339 if (operations & SR_SELECT_EXCEPTION)
00340 {
00341
00342 }
00343 return resops;
00344 }
00345
00346 PRIVATE acc_t *tcp_get_data (port, offset, count, for_ioctl)
00347 int port;
00348 size_t offset;
00349 size_t count;
00350 int for_ioctl;
00351 {
00352 tcp_port_t *tcp_port;
00353 int result;
00354
00355 tcp_port= &tcp_port_table[port];
00356
00357 switch (tcp_port->tp_state)
00358 {
00359 case TPS_SETPROTO:
00360 if (!count)
00361 {
00362 result= (int)offset;
00363 if (result<0)
00364 {
00365 tcp_port->tp_state= TPS_ERROR;
00366 break;
00367 }
00368 tcp_port->tp_state= TPS_GETCONF;
00369 if (tcp_port->tp_flags & TPF_SUSPEND)
00370 tcp_main(tcp_port);
00371 return NW_OK;
00372 }
00373 assert (!offset);
00374 assert (count == sizeof(struct nwio_ipopt));
00375 {
00376 struct nwio_ipopt *ipopt;
00377 acc_t *acc;
00378
00379 acc= bf_memreq(sizeof(*ipopt));
00380 ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);
00381 ipopt->nwio_flags= NWIO_COPY |
00382 NWIO_EN_LOC | NWIO_DI_BROAD |
00383 NWIO_REMANY | NWIO_PROTOSPEC |
00384 NWIO_HDR_O_ANY | NWIO_RWDATALL;
00385 ipopt->nwio_proto= IPPROTO_TCP;
00386 return acc;
00387 }
00388 case TPS_MAIN:
00389 assert(tcp_port->tp_flags & TPF_WRITE_IP);
00390 if (!count)
00391 {
00392 result= (int)offset;
00393 if (result<0)
00394 {
00395 if (result == EDSTNOTRCH)
00396 {
00397 if (tcp_port->tp_snd_head)
00398 {
00399 tcp_notreach(tcp_port->
00400 tp_snd_head);
00401 }
00402 }
00403 else
00404 {
00405 ip_warning((
00406 "ip_write failed with error: %d\n",
00407 result ));
00408 }
00409 }
00410 assert (tcp_port->tp_pack);
00411 bf_afree (tcp_port->tp_pack);
00412 tcp_port->tp_pack= 0;
00413
00414 if (tcp_port->tp_flags & TPF_WRITE_SP)
00415 {
00416 tcp_port->tp_flags &= ~(TPF_WRITE_SP|
00417 TPF_WRITE_IP);
00418 if (tcp_port->tp_snd_head)
00419 tcp_port_write(tcp_port);
00420 }
00421 else
00422 tcp_port->tp_flags &= ~TPF_WRITE_IP;
00423 }
00424 else
00425 {
00426 return bf_cut (tcp_port->tp_pack, offset,
00427 count);
00428 }
00429 break;
00430 default:
00431 printf("tcp_get_data(%d, 0x%x, 0x%x) called but tp_state= 0x%x\n",
00432 port, offset, count, tcp_port->tp_state);
00433 break;
00434 }
00435 return NW_OK;
00436 }
00437
00438 PRIVATE int tcp_put_data (fd, offset, data, for_ioctl)
00439 int fd;
00440 size_t offset;
00441 acc_t *data;
00442 int for_ioctl;
00443 {
00444 tcp_port_t *tcp_port;
00445 int result;
00446
00447 tcp_port= &tcp_port_table[fd];
00448
00449 switch (tcp_port->tp_state)
00450 {
00451 case TPS_GETCONF:
00452 if (!data)
00453 {
00454 result= (int)offset;
00455 if (result<0)
00456 {
00457 tcp_port->tp_state= TPS_ERROR;
00458 return NW_OK;
00459 }
00460 tcp_port->tp_state= TPS_MAIN;
00461 if (tcp_port->tp_flags & TPF_SUSPEND)
00462 tcp_main(tcp_port);
00463 }
00464 else
00465 {
00466 struct nwio_ipconf *ipconf;
00467
00468 data= bf_packIffLess(data, sizeof(*ipconf));
00469 ipconf= (struct nwio_ipconf *)ptr2acc_data(data);
00470 assert (ipconf->nwic_flags & NWIC_IPADDR_SET);
00471 tcp_port->tp_ipaddr= ipconf->nwic_ipaddr;
00472 tcp_port->tp_subnetmask= ipconf->nwic_netmask;
00473 tcp_port->tp_mtu= ipconf->nwic_mtu;
00474 bf_afree(data);
00475 }
00476 break;
00477 case TPS_MAIN:
00478 assert(tcp_port->tp_flags & TPF_READ_IP);
00479 if (!data)
00480 {
00481 result= (int)offset;
00482 if (result<0)
00483 ip_panic(( "ip_read() failed" ));
00484
00485 if (tcp_port->tp_flags & TPF_READ_SP)
00486 {
00487 tcp_port->tp_flags &= ~(TPF_READ_SP|
00488 TPF_READ_IP);
00489 read_ip_packets(tcp_port);
00490 }
00491 else
00492 tcp_port->tp_flags &= ~TPF_READ_IP;
00493 }
00494 else
00495 {
00496 assert(!offset);
00497
00498
00499 tcp_put_pkt(fd, data, bf_bufsize(data));
00500 }
00501 break;
00502 default:
00503 printf(
00504 "tcp_put_data(%d, 0x%x, %p) called but tp_state= 0x%x\n",
00505 fd, offset, data, tcp_port->tp_state);
00506 break;
00507 }
00508 return NW_OK;
00509 }
00510
00511
00512
00513
00514
00515 PRIVATE void tcp_put_pkt(fd, data, datalen)
00516 int fd;
00517 acc_t *data;
00518 size_t datalen;
00519 {
00520 tcp_port_t *tcp_port;
00521 tcp_conn_t *tcp_conn, **conn_p;
00522 ip_hdr_t *ip_hdr;
00523 tcp_hdr_t *tcp_hdr;
00524 acc_t *ip_pack, *tcp_pack;
00525 size_t ip_datalen, tcp_datalen, ip_hdr_len, tcp_hdr_len;
00526 u16_t sum, mtu;
00527 u32_t bits;
00528 int i, hash;
00529 ipaddr_t srcaddr, dstaddr, ipaddr, mask;
00530 tcpport_t srcport, dstport;
00531
00532 tcp_port= &tcp_port_table[fd];
00533
00534
00535 ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
00536 ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
00537 ip_datalen= datalen - ip_hdr_len;
00538 if (ip_datalen == 0)
00539 {
00540 if (ip_hdr->ih_proto == 0)
00541 {
00542
00543 ipaddr= ip_hdr->ih_src;
00544 mask= ip_hdr->ih_dst;
00545 mtu= ntohs(ip_hdr->ih_length);
00546 tcp_port->tp_ipaddr= ipaddr;
00547 tcp_port->tp_subnetmask= mask;
00548 tcp_port->tp_mtu= mtu;
00549 DBLOCK(1, printf("tcp_put_pkt: using address ");
00550 writeIpAddr(ipaddr);
00551 printf(", netmask ");
00552 writeIpAddr(mask);
00553 printf(", mtu %u\n", mtu));
00554 for (i= 0, tcp_conn= tcp_conn_table+i;
00555 i<TCP_CONN_NR; i++, tcp_conn++)
00556 {
00557 if (!(tcp_conn->tc_flags & TCF_INUSE))
00558 continue;
00559 if (tcp_conn->tc_port != tcp_port)
00560 continue;
00561 tcp_conn->tc_locaddr= ipaddr;
00562 }
00563 }
00564 else
00565 DBLOCK(1, printf("tcp_put_pkt: no TCP header\n"));
00566 bf_afree(data);
00567 return;
00568 }
00569 data->acc_linkC++;
00570 ip_pack= data;
00571 ip_pack= bf_align(ip_pack, ip_hdr_len, 4);
00572 ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);
00573 data= bf_delhead(data, ip_hdr_len);
00574
00575
00576 sum= tcp_pack_oneCsum(ip_hdr, data);
00577
00578
00579 if (ip_datalen < TCP_MIN_HDR_SIZE)
00580 {
00581 DBLOCK(1, printf("truncated TCP header\n"));
00582 bf_afree(ip_pack);
00583 bf_afree(data);
00584 return;
00585 }
00586 data= bf_packIffLess(data, TCP_MIN_HDR_SIZE);
00587 tcp_hdr= (tcp_hdr_t *)ptr2acc_data(data);
00588 tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;
00589
00590 if (ip_datalen < tcp_hdr_len || tcp_hdr_len < TCP_MIN_HDR_SIZE)
00591 {
00592 if (tcp_hdr_len < TCP_MIN_HDR_SIZE)
00593 {
00594 DBLOCK(1, printf("strange tcp header length %d\n",
00595 tcp_hdr_len));
00596 }
00597 else
00598 {
00599 DBLOCK(1, printf("truncated TCP header\n"));
00600 }
00601 bf_afree(ip_pack);
00602 bf_afree(data);
00603 return;
00604 }
00605 data->acc_linkC++;
00606 tcp_pack= data;
00607 tcp_pack= bf_align(tcp_pack, tcp_hdr_len, 4);
00608 tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack);
00609 if (ip_datalen == tcp_hdr_len)
00610 {
00611 bf_afree(data);
00612 data= NULL;
00613 }
00614 else
00615 data= bf_delhead(data, tcp_hdr_len);
00616 tcp_datalen= ip_datalen-tcp_hdr_len;
00617
00618 if ((u16_t)~sum)
00619 {
00620 DBLOCK(1, printf("checksum error in tcp packet\n");
00621 printf("tcp_pack_oneCsum(...)= 0x%x length= %d\n",
00622 (u16_t)~sum, tcp_datalen);
00623 printf("src ip_addr= "); writeIpAddr(ip_hdr->ih_src);
00624 printf("\n"));
00625 bf_afree(ip_pack);
00626 bf_afree(tcp_pack);
00627 bf_afree(data);
00628 return;
00629 }
00630
00631 srcaddr= ip_hdr->ih_src;
00632 dstaddr= ip_hdr->ih_dst;
00633 srcport= tcp_hdr->th_srcport;
00634 dstport= tcp_hdr->th_dstport;
00635 bits= srcaddr ^ dstaddr ^ srcport ^ dstport;
00636 bits= (bits >> 16) ^ bits;
00637 bits= (bits >> 8) ^ bits;
00638 hash= ((bits >> TCP_CONN_HASH_SHIFT) ^ bits) & (TCP_CONN_HASH_NR-1);
00639 conn_p= tcp_port->tp_conn_hash[hash];
00640 if (conn_p[0]->tc_locport == dstport &&
00641 conn_p[0]->tc_remport == srcport &&
00642 conn_p[0]->tc_remaddr == srcaddr &&
00643 conn_p[0]->tc_locaddr == dstaddr)
00644 {
00645 tcp_conn= conn_p[0];
00646 }
00647 else if (conn_p[1]->tc_locport == dstport &&
00648 conn_p[1]->tc_remport == srcport &&
00649 conn_p[1]->tc_remaddr == srcaddr &&
00650 conn_p[1]->tc_locaddr == dstaddr)
00651 {
00652 tcp_conn= conn_p[1];
00653 conn_p[1]= conn_p[0];
00654 conn_p[0]= tcp_conn;
00655 }
00656 else if (conn_p[2]->tc_locport == dstport &&
00657 conn_p[2]->tc_remport == srcport &&
00658 conn_p[2]->tc_remaddr == srcaddr &&
00659 conn_p[2]->tc_locaddr == dstaddr)
00660 {
00661 tcp_conn= conn_p[2];
00662 conn_p[2]= conn_p[1];
00663 conn_p[1]= conn_p[0];
00664 conn_p[0]= tcp_conn;
00665 }
00666 else if (conn_p[3]->tc_locport == dstport &&
00667 conn_p[3]->tc_remport == srcport &&
00668 conn_p[3]->tc_remaddr == srcaddr &&
00669 conn_p[3]->tc_locaddr == dstaddr)
00670 {
00671 tcp_conn= conn_p[3];
00672 conn_p[3]= conn_p[2];
00673 conn_p[2]= conn_p[1];
00674 conn_p[1]= conn_p[0];
00675 conn_p[0]= tcp_conn;
00676 }
00677 else
00678 tcp_conn= NULL;
00679 if ((tcp_conn != NULL && tcp_conn->tc_state == TCS_CLOSED) ||
00680 (tcp_hdr->th_flags & THF_SYN))
00681 {
00682 tcp_conn= NULL;
00683 }
00684
00685 if (tcp_conn == NULL)
00686 {
00687 tcp_conn= find_best_conn(ip_hdr, tcp_hdr);
00688 if (!tcp_conn)
00689 {
00690
00691 bf_afree(ip_pack);
00692 bf_afree(tcp_pack);
00693 bf_afree(data);
00694 return;
00695 }
00696 if (tcp_conn->tc_state != TCS_CLOSED)
00697 {
00698 conn_p[3]= conn_p[2];
00699 conn_p[2]= conn_p[1];
00700 conn_p[1]= conn_p[0];
00701 conn_p[0]= tcp_conn;
00702 }
00703 }
00704 assert(tcp_conn->tc_busy == 0);
00705 tcp_conn->tc_busy++;
00706 tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, data, tcp_datalen);
00707 tcp_conn->tc_busy--;
00708 bf_afree(ip_pack);
00709 bf_afree(tcp_pack);
00710 }
00711
00712
00713 PUBLIC int tcp_open (port, srfd, get_userdata, put_userdata, put_pkt,
00714 select_res)
00715 int port;
00716 int srfd;
00717 get_userdata_t get_userdata;
00718 put_userdata_t put_userdata;
00719 put_pkt_t put_pkt;
00720 select_res_t select_res;
00721 {
00722 int i, j;
00723
00724 tcp_fd_t *tcp_fd;
00725
00726 for (i=0; i<TCP_FD_NR && (tcp_fd_table[i].tf_flags & TFF_INUSE);
00727 i++);
00728 if (i>=TCP_FD_NR)
00729 {
00730 return EAGAIN;
00731 }
00732
00733 tcp_fd= &tcp_fd_table[i];
00734
00735 tcp_fd->tf_flags= TFF_INUSE;
00736 tcp_fd->tf_flags |= TFF_PUSH_DATA;
00737
00738 tcp_fd->tf_port= &tcp_port_table[port];
00739 tcp_fd->tf_srfd= srfd;
00740 tcp_fd->tf_tcpconf.nwtc_flags= TCP_DEF_CONF;
00741 tcp_fd->tf_tcpconf.nwtc_remaddr= 0;
00742 tcp_fd->tf_tcpconf.nwtc_remport= 0;
00743 tcp_fd->tf_tcpopt.nwto_flags= TCP_DEF_OPT;
00744 tcp_fd->tf_get_userdata= get_userdata;
00745 tcp_fd->tf_put_userdata= put_userdata;
00746 tcp_fd->tf_select_res= select_res;
00747 tcp_fd->tf_conn= 0;
00748 tcp_fd->tf_error= 0;
00749 for (j= 0; j<TFL_LISTEN_MAX; j++)
00750 tcp_fd->tf_listenq[j]= NULL;
00751 return i;
00752 }
00753
00754
00755
00756
00757 PUBLIC int tcp_ioctl (fd, req)
00758 int fd;
00759 ioreq_t req;
00760 {
00761 tcp_fd_t *tcp_fd;
00762 tcp_port_t *tcp_port;
00763 tcp_conn_t *tcp_conn;
00764 nwio_tcpconf_t *tcp_conf;
00765 nwio_tcpopt_t *tcp_opt;
00766 tcp_cookie_t *cookiep;
00767 acc_t *acc, *conf_acc, *opt_acc;
00768 int result, *bytesp;
00769 u8_t rndbits[RAND256_BUFSIZE];
00770
00771 tcp_fd= &tcp_fd_table[fd];
00772
00773 assert (tcp_fd->tf_flags & TFF_INUSE);
00774
00775 tcp_port= tcp_fd->tf_port;
00776 tcp_fd->tf_flags |= TFF_IOCTL_IP;
00777 tcp_fd->tf_ioreq= req;
00778
00779 if (tcp_port->tp_state != TPS_MAIN)
00780 {
00781 tcp_fd->tf_flags |= TFF_IOC_INIT_SP;
00782 return NW_SUSPEND;
00783 }
00784
00785 switch (req)
00786 {
00787 case NWIOSTCPCONF:
00788 if ((tcp_fd->tf_flags & TFF_CONNECTED) ||
00789 (tcp_fd->tf_flags & TFF_CONNECTING) ||
00790 (tcp_fd->tf_flags & TFF_LISTENQ))
00791 {
00792 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00793 reply_thr_get (tcp_fd, EISCONN, TRUE);
00794 result= NW_OK;
00795 break;
00796 }
00797 result= tcp_setconf(tcp_fd);
00798 break;
00799 case NWIOGTCPCONF:
00800 conf_acc= bf_memreq(sizeof(*tcp_conf));
00801 assert (conf_acc->acc_length == sizeof(*tcp_conf));
00802 tcp_conf= (nwio_tcpconf_t *)ptr2acc_data(conf_acc);
00803
00804 *tcp_conf= tcp_fd->tf_tcpconf;
00805 if (tcp_fd->tf_flags & TFF_CONNECTED)
00806 {
00807 tcp_conn= tcp_fd->tf_conn;
00808 tcp_conf->nwtc_locport= tcp_conn->tc_locport;
00809 tcp_conf->nwtc_remaddr= tcp_conn->tc_remaddr;
00810 tcp_conf->nwtc_remport= tcp_conn->tc_remport;
00811 }
00812 tcp_conf->nwtc_locaddr= tcp_fd->tf_port->tp_ipaddr;
00813 result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
00814 0, conf_acc, TRUE);
00815 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00816 reply_thr_put(tcp_fd, result, TRUE);
00817 result= NW_OK;
00818 break;
00819 case NWIOSTCPOPT:
00820 result= tcp_setopt(tcp_fd);
00821 break;
00822 case NWIOGTCPOPT:
00823 opt_acc= bf_memreq(sizeof(*tcp_opt));
00824 assert (opt_acc->acc_length == sizeof(*tcp_opt));
00825 tcp_opt= (nwio_tcpopt_t *)ptr2acc_data(opt_acc);
00826
00827 *tcp_opt= tcp_fd->tf_tcpopt;
00828 result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
00829 0, opt_acc, TRUE);
00830 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00831 reply_thr_put(tcp_fd, result, TRUE);
00832 result= NW_OK;
00833 break;
00834 case NWIOTCPCONN:
00835 if (tcp_fd->tf_flags & TFF_CONNECTING)
00836 {
00837 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00838 reply_thr_get (tcp_fd, EALREADY, TRUE);
00839 result= NW_OK;
00840 break;
00841 }
00842 if (tcp_fd->tf_flags & TFF_CONNECTED)
00843 {
00844 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00845 reply_thr_get (tcp_fd, EISCONN, TRUE);
00846 result= NW_OK;
00847 break;
00848 }
00849 result= tcp_connect(tcp_fd);
00850 if (result == NW_OK)
00851 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00852 break;
00853 case NWIOTCPLISTEN:
00854 case NWIOTCPLISTENQ:
00855 if ((tcp_fd->tf_flags & TFF_CONNECTED) ||
00856 (tcp_fd->tf_flags & TFF_LISTENQ) ||
00857 (tcp_fd->tf_flags & TFF_CONNECTING))
00858 {
00859 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00860 reply_thr_get (tcp_fd, EISCONN, TRUE);
00861 result= NW_OK;
00862 break;
00863 }
00864 result= tcp_listen(tcp_fd, (req == NWIOTCPLISTENQ));
00865 break;
00866 case NWIOTCPSHUTDOWN:
00867 if (!(tcp_fd->tf_flags & TFF_CONNECTED))
00868 {
00869 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00870 reply_thr_get (tcp_fd, ENOTCONN, TRUE);
00871 result= NW_OK;
00872 break;
00873 }
00874 tcp_fd->tf_flags |= TFF_IOCTL_IP;
00875 tcp_fd->tf_ioreq= req;
00876 tcp_conn= tcp_fd->tf_conn;
00877
00878 tcp_conn->tc_busy++;
00879 tcp_fd_write(tcp_conn);
00880 tcp_conn->tc_busy--;
00881 tcp_conn_write(tcp_conn, 0);
00882 if (!(tcp_fd->tf_flags & TFF_IOCTL_IP))
00883 result= NW_OK;
00884 else
00885 result= NW_SUSPEND;
00886 break;
00887 case NWIOTCPPUSH:
00888 if (!(tcp_fd->tf_flags & TFF_CONNECTED))
00889 {
00890 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00891 reply_thr_get (tcp_fd, ENOTCONN, TRUE);
00892 result= NW_OK;
00893 break;
00894 }
00895 tcp_conn= tcp_fd->tf_conn;
00896 tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;
00897 tcp_conn->tc_flags &= ~TCF_NO_PUSH;
00898 tcp_conn->tc_flags |= TCF_PUSH_NOW;
00899
00900
00901 if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_UNA)
00902 tcp_set_send_timer(tcp_conn);
00903
00904 tcp_conn_write(tcp_conn, 0);
00905 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00906 reply_thr_get (tcp_fd, NW_OK, TRUE);
00907 result= NW_OK;
00908 break;
00909 case NWIOGTCPCOOKIE:
00910 if (!(tcp_fd->tf_flags & TFF_COOKIE))
00911 {
00912 tcp_fd->tf_cookie.tc_ref= fd;
00913 rand256(rndbits);
00914 assert(sizeof(tcp_fd->tf_cookie.tc_secret) <=
00915 RAND256_BUFSIZE);
00916 memcpy(tcp_fd->tf_cookie.tc_secret,
00917 rndbits, sizeof(tcp_fd->tf_cookie.tc_secret));
00918 tcp_fd->tf_flags |= TFF_COOKIE;
00919 }
00920 acc= bf_memreq(sizeof(*cookiep));
00921 cookiep= (tcp_cookie_t *)ptr2acc_data(acc);
00922
00923 *cookiep= tcp_fd->tf_cookie;
00924 result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
00925 0, acc, TRUE);
00926 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00927 reply_thr_put(tcp_fd, result, TRUE);
00928 result= NW_OK;
00929 break;
00930 case NWIOTCPACCEPTTO:
00931 result= tcp_acceptto(tcp_fd);
00932 break;
00933 case FIONREAD:
00934 acc= bf_memreq(sizeof(*bytesp));
00935 bytesp= (int *)ptr2acc_data(acc);
00936 tcp_bytesavailable(tcp_fd, bytesp);
00937 result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
00938 0, acc, TRUE);
00939 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00940 reply_thr_put(tcp_fd, result, TRUE);
00941 result= NW_OK;
00942 break;
00943
00944 case NWIOTCPGERROR:
00945 acc= bf_memreq(sizeof(*bytesp));
00946 bytesp= (int *)ptr2acc_data(acc);
00947 *bytesp= -tcp_fd->tf_error;
00948
00949
00950 tcp_fd->tf_error= 0;
00951 result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
00952 0, acc, TRUE);
00953 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00954 reply_thr_put(tcp_fd, result, TRUE);
00955 result= NW_OK;
00956 break;
00957
00958 default:
00959 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
00960 reply_thr_get(tcp_fd, EBADIOCTL, TRUE);
00961 result= NW_OK;
00962 break;
00963 }
00964 return result;
00965 }
00966
00967
00968
00969
00970
00971
00972 PRIVATE int tcp_setconf(tcp_fd)
00973 tcp_fd_t *tcp_fd;
00974 {
00975 nwio_tcpconf_t *tcpconf;
00976 nwio_tcpconf_t oldconf, newconf;
00977 acc_t *data;
00978 tcp_fd_t *fd_ptr;
00979 unsigned int new_en_flags, new_di_flags,
00980 old_en_flags, old_di_flags, all_flags, flags;
00981 int i;
00982
00983 data= (*tcp_fd->tf_get_userdata)
00984 (tcp_fd->tf_srfd, 0,
00985 sizeof(nwio_tcpconf_t), TRUE);
00986
00987 if (!data)
00988 return EFAULT;
00989
00990 data= bf_packIffLess(data, sizeof(nwio_tcpconf_t));
00991 assert (data->acc_length == sizeof(nwio_tcpconf_t));
00992
00993 tcpconf= (nwio_tcpconf_t *)ptr2acc_data(data);
00994 oldconf= tcp_fd->tf_tcpconf;
00995 newconf= *tcpconf;
00996
00997 old_en_flags= oldconf.nwtc_flags & 0xffff;
00998 old_di_flags= (oldconf.nwtc_flags >> 16) &
00999 0xffff;
01000 new_en_flags= newconf.nwtc_flags & 0xffff;
01001 new_di_flags= (newconf.nwtc_flags >> 16) &
01002 0xffff;
01003 if (new_en_flags & new_di_flags)
01004 {
01005 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01006 reply_thr_get(tcp_fd, EBADMODE, TRUE);
01007 bf_afree(data);
01008 return NW_OK;
01009 }
01010
01011
01012 if (new_di_flags & NWTC_ACC_MASK)
01013 {
01014 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01015 reply_thr_get(tcp_fd, EBADMODE, TRUE);
01016 bf_afree(data);
01017 return NW_OK;
01018
01019 }
01020
01021 if (!(new_en_flags & NWTC_ACC_MASK))
01022 new_en_flags |= (old_en_flags & NWTC_ACC_MASK);
01023
01024
01025 if (new_di_flags & NWTC_LOCPORT_MASK)
01026 {
01027 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01028 reply_thr_get(tcp_fd, EBADMODE, TRUE);
01029 bf_afree(data);
01030 return NW_OK;
01031
01032 }
01033 if (!(new_en_flags & NWTC_LOCPORT_MASK))
01034 {
01035 new_en_flags |= (old_en_flags &
01036 NWTC_LOCPORT_MASK);
01037 newconf.nwtc_locport= oldconf.nwtc_locport;
01038 }
01039 else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL)
01040 {
01041 newconf.nwtc_locport= find_unused_port(tcp_fd-
01042 tcp_fd_table);
01043 }
01044 else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET)
01045 {
01046 if (!newconf.nwtc_locport)
01047 {
01048 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01049 reply_thr_get(tcp_fd, EBADMODE, TRUE);
01050 bf_afree(data);
01051 return NW_OK;
01052 }
01053 }
01054
01055
01056 if (!((new_en_flags | new_di_flags) &
01057 NWTC_REMADDR_MASK))
01058 {
01059 new_en_flags |= (old_en_flags &
01060 NWTC_REMADDR_MASK);
01061 new_di_flags |= (old_di_flags &
01062 NWTC_REMADDR_MASK);
01063 newconf.nwtc_remaddr= oldconf.nwtc_remaddr;
01064 }
01065 else if (new_en_flags & NWTC_SET_RA)
01066 {
01067 if (!newconf.nwtc_remaddr)
01068 {
01069 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01070 reply_thr_get(tcp_fd, EBADMODE, TRUE);
01071 bf_afree(data);
01072 return NW_OK;
01073 }
01074 }
01075 else
01076 {
01077 assert (new_di_flags & NWTC_REMADDR_MASK);
01078 newconf.nwtc_remaddr= 0;
01079 }
01080
01081
01082 if (!((new_en_flags | new_di_flags) & NWTC_REMPORT_MASK))
01083 {
01084 new_en_flags |= (old_en_flags &
01085 NWTC_REMPORT_MASK);
01086 new_di_flags |= (old_di_flags &
01087 NWTC_REMPORT_MASK);
01088 newconf.nwtc_remport=
01089 oldconf.nwtc_remport;
01090 }
01091 else if (new_en_flags & NWTC_SET_RP)
01092 {
01093 if (!newconf.nwtc_remport)
01094 {
01095 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01096 reply_thr_get(tcp_fd, EBADMODE, TRUE);
01097 bf_afree(data);
01098 return NW_OK;
01099 }
01100 }
01101 else
01102 {
01103 assert (new_di_flags & NWTC_REMPORT_MASK);
01104 newconf.nwtc_remport= 0;
01105 }
01106
01107 newconf.nwtc_flags= ((unsigned long)new_di_flags
01108 << 16) | new_en_flags;
01109 all_flags= new_en_flags | new_di_flags;
01110
01111
01112 if ((all_flags & NWTC_LOCPORT_MASK) != NWTC_LP_UNSET)
01113 {
01114 for (i=0, fd_ptr= tcp_fd_table; i<TCP_FD_NR; i++, fd_ptr++)
01115 {
01116 if (fd_ptr == tcp_fd)
01117 continue;
01118 if (!(fd_ptr->tf_flags & TFF_INUSE))
01119 continue;
01120 if (fd_ptr->tf_port != tcp_fd->tf_port)
01121 continue;
01122 flags= fd_ptr->tf_tcpconf.nwtc_flags;
01123 if ((flags & NWTC_LOCPORT_MASK) == NWTC_LP_UNSET)
01124 continue;
01125 if (fd_ptr->tf_tcpconf.nwtc_locport !=
01126 newconf.nwtc_locport)
01127 continue;
01128 if ((flags & NWTC_ACC_MASK) != (all_flags &
01129 NWTC_ACC_MASK) ||
01130 (all_flags & NWTC_ACC_MASK) == NWTC_EXCL)
01131 {
01132 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01133 reply_thr_get(tcp_fd, EADDRINUSE, TRUE);
01134 bf_afree(data);
01135 return NW_OK;
01136 }
01137 }
01138 }
01139
01140 tcp_fd->tf_tcpconf= newconf;
01141
01142 if ((all_flags & NWTC_ACC_MASK) &&
01143 ((all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET ||
01144 (all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL) &&
01145 (all_flags & NWTC_REMADDR_MASK) &&
01146 (all_flags & NWTC_REMPORT_MASK))
01147 tcp_fd->tf_flags |= TFF_CONF_SET;
01148 else
01149 {
01150 tcp_fd->tf_flags &= ~TFF_CONF_SET;
01151 }
01152 bf_afree(data);
01153 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01154 reply_thr_get(tcp_fd, NW_OK, TRUE);
01155 return NW_OK;
01156 }
01157
01158
01159
01160
01161
01162
01163 PRIVATE int tcp_setopt(tcp_fd)
01164 tcp_fd_t *tcp_fd;
01165 {
01166 nwio_tcpopt_t *tcpopt;
01167 nwio_tcpopt_t oldopt, newopt;
01168 acc_t *data;
01169 unsigned int new_en_flags, new_di_flags,
01170 old_en_flags, old_di_flags;
01171
01172 data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
01173 sizeof(nwio_tcpopt_t), TRUE);
01174
01175 if (!data)
01176 return EFAULT;
01177
01178 data= bf_packIffLess(data, sizeof(nwio_tcpopt_t));
01179 assert (data->acc_length == sizeof(nwio_tcpopt_t));
01180
01181 tcpopt= (nwio_tcpopt_t *)ptr2acc_data(data);
01182 oldopt= tcp_fd->tf_tcpopt;
01183 newopt= *tcpopt;
01184
01185 old_en_flags= oldopt.nwto_flags & 0xffff;
01186 old_di_flags= (oldopt.nwto_flags >> 16) & 0xffff;
01187 new_en_flags= newopt.nwto_flags & 0xffff;
01188 new_di_flags= (newopt.nwto_flags >> 16) & 0xffff;
01189 if (new_en_flags & new_di_flags)
01190 {
01191 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01192 reply_thr_get(tcp_fd, EBADMODE, TRUE);
01193 return NW_OK;
01194 }
01195
01196
01197 if (!((new_en_flags | new_di_flags) & NWTO_SND_URG_MASK))
01198 {
01199 new_en_flags |= (old_en_flags & NWTO_SND_URG_MASK);
01200 new_di_flags |= (old_di_flags & NWTO_SND_URG_MASK);
01201 }
01202
01203
01204 if (!((new_en_flags | new_di_flags) & NWTO_RCV_URG_MASK))
01205 {
01206 new_en_flags |= (old_en_flags & NWTO_RCV_URG_MASK);
01207 new_di_flags |= (old_di_flags & NWTO_RCV_URG_MASK);
01208 }
01209
01210
01211 if (!((new_en_flags | new_di_flags) & NWTO_BSD_URG_MASK))
01212 {
01213 new_en_flags |= (old_en_flags & NWTO_BSD_URG_MASK);
01214 new_di_flags |= (old_di_flags & NWTO_BSD_URG_MASK);
01215 }
01216 else
01217 {
01218 if (tcp_fd->tf_conn == NULL)
01219 {
01220 bf_afree(data);
01221 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01222 reply_thr_get(tcp_fd, EINVAL, TRUE);
01223 return NW_OK;
01224 }
01225 }
01226
01227
01228 if (!((new_en_flags | new_di_flags) & NWTO_DEL_RST_MASK))
01229 {
01230 new_en_flags |= (old_en_flags & NWTO_DEL_RST_MASK);
01231 new_di_flags |= (old_di_flags & NWTO_DEL_RST_MASK);
01232 }
01233
01234
01235 if (!((new_en_flags | new_di_flags) & NWTO_BULK_MASK))
01236 {
01237 new_en_flags |= (old_en_flags & NWTO_BULK_MASK);
01238 new_di_flags |= (old_di_flags & NWTO_BULK_MASK);
01239 }
01240
01241 newopt.nwto_flags= ((unsigned long)new_di_flags << 16) |
01242 new_en_flags;
01243 tcp_fd->tf_tcpopt= newopt;
01244 if (newopt.nwto_flags & NWTO_SND_URG)
01245 tcp_fd->tf_flags |= TFF_WR_URG;
01246 else
01247 tcp_fd->tf_flags &= ~TFF_WR_URG;
01248
01249 if (newopt.nwto_flags & NWTO_RCV_URG)
01250 tcp_fd->tf_flags |= TFF_RECV_URG;
01251 else
01252 tcp_fd->tf_flags &= ~TFF_RECV_URG;
01253
01254 if (tcp_fd->tf_conn)
01255 {
01256 if (newopt.nwto_flags & NWTO_BSD_URG)
01257 tcp_fd->tf_conn->tc_flags |= TCF_BSD_URG;
01258 else
01259 tcp_fd->tf_conn->tc_flags &= ~TCF_BSD_URG;
01260 }
01261
01262 if (newopt.nwto_flags & NWTO_DEL_RST)
01263 tcp_fd->tf_flags |= TFF_DEL_RST;
01264 else
01265 tcp_fd->tf_flags &= ~TFF_DEL_RST;
01266
01267 if (newopt.nwto_flags & NWTO_BULK)
01268 tcp_fd->tf_flags &= ~TFF_PUSH_DATA;
01269 else
01270 tcp_fd->tf_flags |= TFF_PUSH_DATA;
01271
01272 bf_afree(data);
01273 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01274 reply_thr_get(tcp_fd, NW_OK, TRUE);
01275 return NW_OK;
01276 }
01277
01278
01279 PRIVATE tcpport_t find_unused_port(fd)
01280 int fd;
01281 {
01282 tcpport_t port, nw_port;
01283
01284 for (port= 0x8000+fd; port < 0xffff-TCP_FD_NR; port+= TCP_FD_NR)
01285 {
01286 nw_port= htons(port);
01287 if (is_unused_port(nw_port))
01288 return nw_port;
01289 }
01290 for (port= 0x8000; port < 0xffff; port++)
01291 {
01292 nw_port= htons(port);
01293 if (is_unused_port(nw_port))
01294 return nw_port;
01295 }
01296 ip_panic(( "unable to find unused port (shouldn't occur)" ));
01297 return 0;
01298 }
01299
01300 PRIVATE int is_unused_port(port)
01301 tcpport_t port;
01302 {
01303 int i;
01304 tcp_fd_t *tcp_fd;
01305 tcp_conn_t *tcp_conn;
01306
01307 for (i= 0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++,
01308 tcp_fd++)
01309 {
01310 if (!(tcp_fd->tf_flags & TFF_CONF_SET))
01311 continue;
01312 if (tcp_fd->tf_tcpconf.nwtc_locport == port)
01313 return FALSE;
01314 }
01315 for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
01316 i<TCP_CONN_NR; i++, tcp_conn++)
01317
01318 {
01319 if (!(tcp_conn->tc_flags & TCF_INUSE))
01320 continue;
01321 if (tcp_conn->tc_locport == port)
01322 return FALSE;
01323 }
01324 return TRUE;
01325 }
01326
01327 PRIVATE int reply_thr_put(tcp_fd, reply, for_ioctl)
01328 tcp_fd_t *tcp_fd;
01329 int reply;
01330 int for_ioctl;
01331 {
01332 assert (tcp_fd);
01333
01334 return (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd, reply,
01335 (acc_t *)0, for_ioctl);
01336 }
01337
01338 PRIVATE void reply_thr_get(tcp_fd, reply, for_ioctl)
01339 tcp_fd_t *tcp_fd;
01340 int reply;
01341 int for_ioctl;
01342 {
01343 acc_t *result;
01344
01345 result= (*tcp_fd->tf_get_userdata)(tcp_fd->tf_srfd, reply,
01346 (size_t)0, for_ioctl);
01347 assert (!result);
01348 }
01349
01350 PUBLIC int tcp_su4listen(tcp_fd, tcp_conn, do_listenq)
01351 tcp_fd_t *tcp_fd;
01352 tcp_conn_t *tcp_conn;
01353 int do_listenq;
01354 {
01355 tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport;
01356 tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr;
01357 if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP)
01358 tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;
01359 else
01360 tcp_conn->tc_remport= 0;
01361 if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA)
01362 tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;
01363 else
01364 tcp_conn->tc_remaddr= 0;
01365
01366 tcp_setup_conn(tcp_fd->tf_port, tcp_conn);
01367 tcp_conn->tc_fd= tcp_fd;
01368 tcp_conn->tc_connInprogress= 1;
01369 tcp_conn->tc_orglisten= TRUE;
01370 tcp_conn->tc_state= TCS_LISTEN;
01371 tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_LISTEN;
01372 if (do_listenq)
01373 {
01374 tcp_fd->tf_flags |= TFF_LISTENQ;
01375 tcp_reply_ioctl(tcp_fd, NW_OK);
01376 return NW_OK;
01377 }
01378 return NW_SUSPEND;
01379 }
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389 PRIVATE tcp_conn_t *find_empty_conn()
01390 {
01391 int i;
01392 tcp_conn_t *tcp_conn;
01393
01394 for (i=tcp_conf_nr, tcp_conn= tcp_conn_table+i;
01395 i<TCP_CONN_NR; i++, tcp_conn++)
01396
01397
01398
01399 {
01400 if (tcp_conn->tc_flags == TCF_EMPTY)
01401 {
01402 tcp_conn->tc_connInprogress= 0;
01403 tcp_conn->tc_fd= NULL;
01404 return tcp_conn;
01405 }
01406 if (tcp_conn->tc_fd)
01407 continue;
01408 if (tcp_conn->tc_senddis > get_time())
01409 continue;
01410 if (tcp_conn->tc_state != TCS_CLOSED)
01411 {
01412 tcp_close_connection (tcp_conn, ENOCONN);
01413 }
01414 tcp_conn->tc_flags= 0;
01415 return tcp_conn;
01416 }
01417 return NULL;
01418 }
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429 PRIVATE tcp_conn_t *find_conn_entry(locport, locaddr, remport, remaddr)
01430 tcpport_t locport;
01431 ipaddr_t locaddr;
01432 tcpport_t remport;
01433 ipaddr_t remaddr;
01434 {
01435 tcp_conn_t *tcp_conn;
01436 int i, state;
01437
01438 assert(remport);
01439 assert(remaddr);
01440 for (i=tcp_conf_nr, tcp_conn= tcp_conn_table+i; i<TCP_CONN_NR;
01441 i++, tcp_conn++)
01442
01443
01444 {
01445 if (tcp_conn->tc_flags == TCF_EMPTY)
01446 continue;
01447 if (tcp_conn->tc_locport != locport ||
01448 tcp_conn->tc_locaddr != locaddr ||
01449 tcp_conn->tc_remport != remport ||
01450 tcp_conn->tc_remaddr != remaddr)
01451 continue;
01452 if (tcp_conn->tc_fd)
01453 return tcp_conn;
01454 state= tcp_conn->tc_state;
01455 if (state != TCS_CLOSED)
01456 {
01457 tcp_close_connection(tcp_conn, ENOCONN);
01458 }
01459 return tcp_conn;
01460 }
01461 return NULL;
01462 }
01463
01464 PRIVATE void read_ip_packets(tcp_port)
01465 tcp_port_t *tcp_port;
01466 {
01467 int result;
01468
01469 do
01470 {
01471 tcp_port->tp_flags |= TPF_READ_IP;
01472 result= ip_read(tcp_port->tp_ipfd, TCP_MAX_DATAGRAM);
01473 if (result == NW_SUSPEND)
01474 {
01475 tcp_port->tp_flags |= TPF_READ_SP;
01476 return;
01477 }
01478 assert(result == NW_OK);
01479 tcp_port->tp_flags &= ~TPF_READ_IP;
01480 } while(!(tcp_port->tp_flags & TPF_READ_IP));
01481 }
01482
01483
01484
01485
01486
01487 PRIVATE tcp_conn_t *find_best_conn(ip_hdr, tcp_hdr)
01488 ip_hdr_t *ip_hdr;
01489 tcp_hdr_t *tcp_hdr;
01490 {
01491
01492 int best_level, new_level;
01493 tcp_conn_t *best_conn, *listen_conn, *tcp_conn;
01494 tcp_fd_t *tcp_fd;
01495 int i;
01496 ipaddr_t locaddr;
01497 ipaddr_t remaddr;
01498 tcpport_t locport;
01499 tcpport_t remport;
01500
01501 locaddr= ip_hdr->ih_dst;
01502 remaddr= ip_hdr->ih_src;
01503 locport= tcp_hdr->th_dstport;
01504 remport= tcp_hdr->th_srcport;
01505 if (!remport)
01506
01507
01508 locport= 0;
01509
01510 best_level= 0;
01511 best_conn= NULL;
01512 listen_conn= NULL;
01513 for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
01514 i<TCP_CONN_NR; i++, tcp_conn++)
01515
01516
01517 {
01518 if (!(tcp_conn->tc_flags & TCF_INUSE))
01519 continue;
01520
01521 if (tcp_conn->tc_locaddr == locaddr &&
01522 tcp_conn->tc_locport == locport &&
01523 tcp_conn->tc_remport == remport &&
01524 tcp_conn->tc_remaddr == remaddr &&
01525 tcp_conn->tc_fd)
01526 {
01527 return tcp_conn;
01528 }
01529
01530
01531 if (tcp_conn->tc_locaddr != locaddr)
01532 {
01533 continue;
01534 }
01535 new_level= 0;
01536 if (tcp_conn->tc_locport)
01537 {
01538 if (tcp_conn->tc_locport != locport)
01539 {
01540 continue;
01541 }
01542 new_level += 4;
01543 }
01544 if (tcp_conn->tc_remport)
01545 {
01546 if (tcp_conn->tc_remport != remport)
01547 {
01548 continue;
01549 }
01550 new_level += 1;
01551 }
01552 if (tcp_conn->tc_remaddr)
01553 {
01554 if (tcp_conn->tc_remaddr != remaddr)
01555 {
01556 continue;
01557 }
01558 new_level += 2;
01559 }
01560 if (new_level<best_level)
01561 continue;
01562 if (new_level != 7 && tcp_conn->tc_state != TCS_LISTEN)
01563 continue;
01564 if (new_level == 7)
01565
01566 {
01567 assert(!tcp_conn->tc_fd);
01568 if (best_conn && tcp_Lmod4G(tcp_conn->tc_ISS,
01569 best_conn->tc_ISS))
01570 {
01571 continue;
01572 }
01573 best_conn= tcp_conn;
01574 continue;
01575 }
01576 if (!(tcp_hdr->th_flags & THF_SYN))
01577 continue;
01578 best_level= new_level;
01579 listen_conn= tcp_conn;
01580 assert(listen_conn->tc_fd != NULL);
01581 }
01582
01583 if (listen_conn && listen_conn->tc_fd->tf_flags & TFF_LISTENQ &&
01584 listen_conn->tc_fd->tf_conn == listen_conn)
01585 {
01586
01587
01588
01589
01590 listen_conn= new_conn_for_queue(listen_conn->tc_fd);
01591 }
01592
01593 if (!best_conn && !listen_conn)
01594 {
01595 if ((tcp_hdr->th_flags & THF_SYN) &&
01596 maybe_listen(locaddr, locport, remaddr, remport))
01597 {
01598
01599
01600
01601
01602 return NULL;
01603 }
01604
01605 for (i=0, tcp_conn= tcp_conn_table; i<tcp_conf_nr;
01606 i++, tcp_conn++)
01607 {
01608
01609 if ((tcp_conn->tc_flags & TCF_INUSE) &&
01610 tcp_conn->tc_locaddr==locaddr)
01611 {
01612 break;
01613 }
01614 }
01615 assert (tcp_conn);
01616 assert (tcp_conn->tc_state == TCS_CLOSED);
01617
01618 tcp_conn->tc_locport= locport;
01619 tcp_conn->tc_locaddr= locaddr;
01620 tcp_conn->tc_remport= remport;
01621 tcp_conn->tc_remaddr= remaddr;
01622 assert (!tcp_conn->tc_fd);
01623 return tcp_conn;
01624 }
01625
01626 if (best_conn)
01627 {
01628 if (!listen_conn)
01629 {
01630 assert(!best_conn->tc_fd);
01631 return best_conn;
01632 }
01633
01634 assert(listen_conn->tc_connInprogress);
01635 tcp_fd= listen_conn->tc_fd;
01636 assert(tcp_fd);
01637 assert((tcp_fd->tf_flags & TFF_LISTENQ) ||
01638 tcp_fd->tf_conn == listen_conn);
01639
01640 if (best_conn->tc_state != TCS_CLOSED)
01641 tcp_close_connection(best_conn, ENOCONN);
01642
01643 listen_conn->tc_ISS= best_conn->tc_ISS;
01644 if (best_conn->tc_senddis > listen_conn->tc_senddis)
01645 listen_conn->tc_senddis= best_conn->tc_senddis;
01646 return listen_conn;
01647 }
01648 assert (listen_conn);
01649 return listen_conn;
01650 }
01651
01652
01653
01654
01655 PRIVATE tcp_conn_t *new_conn_for_queue(tcp_fd)
01656 tcp_fd_t *tcp_fd;
01657 {
01658 int i;
01659 tcp_conn_t *tcp_conn;
01660
01661 assert(tcp_fd->tf_flags & TFF_LISTENQ);
01662
01663 for (i= 0; i<TFL_LISTEN_MAX; i++)
01664 {
01665 if (tcp_fd->tf_listenq[i] == NULL)
01666 break;
01667 }
01668 if (i >= TFL_LISTEN_MAX)
01669 return NULL;
01670
01671 tcp_conn= find_empty_conn();
01672 if (!tcp_conn)
01673 return NULL;
01674 tcp_fd->tf_listenq[i]= tcp_conn;
01675 (void)tcp_su4listen(tcp_fd, tcp_conn, 0 );
01676 return tcp_conn;
01677 }
01678
01679
01680
01681
01682 PRIVATE int maybe_listen(locaddr, locport, remaddr, remport)
01683 ipaddr_t locaddr;
01684 tcpport_t locport;
01685 ipaddr_t remaddr;
01686 tcpport_t remport;
01687 {
01688 int i;
01689 tcp_conn_t *tcp_conn;
01690 tcp_fd_t *fd;
01691
01692 for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i;
01693 i<TCP_CONN_NR; i++, tcp_conn++)
01694 {
01695 if (!(tcp_conn->tc_flags & TCF_INUSE))
01696 continue;
01697
01698 if (tcp_conn->tc_locaddr != locaddr)
01699 {
01700 continue;
01701 }
01702 if (tcp_conn->tc_locport != locport )
01703 {
01704 continue;
01705 }
01706 if (!tcp_conn->tc_orglisten)
01707 continue;
01708 fd= tcp_conn->tc_fd;
01709 if (!fd)
01710 continue;
01711 if ((fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP) &&
01712 tcp_conn->tc_remport != remport)
01713 {
01714 continue;
01715 }
01716 if ((fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA) &&
01717 tcp_conn->tc_remaddr != remaddr)
01718 {
01719 continue;
01720 }
01721 if (!(fd->tf_flags & TFF_DEL_RST))
01722 continue;
01723 return 1;
01724
01725 }
01726 return 0;
01727 }
01728
01729
01730 PUBLIC void tcp_reply_ioctl(tcp_fd, reply)
01731 tcp_fd_t *tcp_fd;
01732 int reply;
01733 {
01734 assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
01735 assert (tcp_fd->tf_ioreq == NWIOTCPSHUTDOWN ||
01736 tcp_fd->tf_ioreq == NWIOTCPLISTEN ||
01737 tcp_fd->tf_ioreq == NWIOTCPLISTENQ ||
01738 tcp_fd->tf_ioreq == NWIOTCPACCEPTTO ||
01739 tcp_fd->tf_ioreq == NWIOTCPCONN);
01740
01741 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
01742 reply_thr_get (tcp_fd, reply, TRUE);
01743 }
01744
01745 PUBLIC void tcp_reply_write(tcp_fd, reply)
01746 tcp_fd_t *tcp_fd;
01747 size_t reply;
01748 {
01749 assert (tcp_fd->tf_flags & TFF_WRITE_IP);
01750
01751 tcp_fd->tf_flags &= ~TFF_WRITE_IP;
01752 reply_thr_get (tcp_fd, reply, FALSE);
01753 }
01754
01755 PUBLIC void tcp_reply_read(tcp_fd, reply)
01756 tcp_fd_t *tcp_fd;
01757 size_t reply;
01758 {
01759 assert (tcp_fd->tf_flags & TFF_READ_IP);
01760
01761 tcp_fd->tf_flags &= ~TFF_READ_IP;
01762 reply_thr_put (tcp_fd, reply, FALSE);
01763 }
01764
01765 PUBLIC int tcp_write(fd, count)
01766 int fd;
01767 size_t count;
01768 {
01769 tcp_fd_t *tcp_fd;
01770 tcp_conn_t *tcp_conn;
01771
01772 tcp_fd= &tcp_fd_table[fd];
01773
01774 assert (tcp_fd->tf_flags & TFF_INUSE);
01775
01776 if (!(tcp_fd->tf_flags & TFF_CONNECTED))
01777 {
01778 reply_thr_get (tcp_fd, ENOTCONN, FALSE);
01779 return NW_OK;
01780 }
01781 tcp_conn= tcp_fd->tf_conn;
01782 if (tcp_conn->tc_state == TCS_CLOSED)
01783 {
01784 reply_thr_get(tcp_fd, tcp_conn->tc_error, FALSE);
01785 return NW_OK;
01786 }
01787 if (tcp_conn->tc_flags & TCF_FIN_SENT)
01788 {
01789 reply_thr_get (tcp_fd, ESHUTDOWN, FALSE);
01790 return NW_OK;
01791 }
01792
01793 tcp_fd->tf_flags |= TFF_WRITE_IP;
01794 tcp_fd->tf_write_offset= 0;
01795 tcp_fd->tf_write_count= count;
01796
01797
01798
01799
01800 tcp_conn->tc_flags &= ~(TCF_NO_PUSH|TCF_PUSH_NOW);
01801
01802
01803 if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_UNA)
01804 tcp_set_send_timer(tcp_conn);
01805
01806 assert(tcp_conn->tc_busy == 0);
01807 tcp_conn->tc_busy++;
01808 tcp_fd_write(tcp_conn);
01809 tcp_conn->tc_busy--;
01810 tcp_conn_write(tcp_conn, 0);
01811
01812 if (!(tcp_fd->tf_flags & TFF_WRITE_IP))
01813 return NW_OK;
01814 else
01815 return NW_SUSPEND;
01816 }
01817
01818 PUBLIC int
01819 tcp_read(fd, count)
01820 int fd;
01821 size_t count;
01822 {
01823 tcp_fd_t *tcp_fd;
01824 tcp_conn_t *tcp_conn;
01825
01826 tcp_fd= &tcp_fd_table[fd];
01827
01828 assert (tcp_fd->tf_flags & TFF_INUSE);
01829
01830 if (!(tcp_fd->tf_flags & TFF_CONNECTED))
01831 {
01832 reply_thr_put (tcp_fd, ENOTCONN, FALSE);
01833 return NW_OK;
01834 }
01835 tcp_conn= tcp_fd->tf_conn;
01836
01837 tcp_fd->tf_flags |= TFF_READ_IP;
01838 tcp_fd->tf_read_offset= 0;
01839 tcp_fd->tf_read_count= count;
01840
01841 assert(tcp_conn->tc_busy == 0);
01842 tcp_conn->tc_busy++;
01843 tcp_fd_read(tcp_conn, 0);
01844 tcp_conn->tc_busy--;
01845 if (!(tcp_fd->tf_flags & TFF_READ_IP))
01846 return NW_OK;
01847 else
01848 return NW_SUSPEND;
01849 }
01850
01851
01852
01853
01854
01855
01856
01857
01858 PUBLIC void tcp_restart_connect(tcp_conn)
01859 tcp_conn_t *tcp_conn;
01860 {
01861 tcp_fd_t *tcp_fd;
01862 int reply;
01863
01864 assert(tcp_conn->tc_connInprogress);
01865 tcp_conn->tc_connInprogress= 0;
01866
01867 tcp_fd= tcp_conn->tc_fd;
01868 assert(tcp_fd);
01869 if (tcp_fd->tf_flags & TFF_LISTENQ)
01870 {
01871
01872 assert(tcp_conn->tc_state != TCS_CLOSED);
01873
01874
01875 if ((tcp_fd->tf_flags & TFF_SEL_READ) &&
01876 tcp_fd->tf_select_res)
01877 {
01878 tcp_fd->tf_flags &= ~TFF_SEL_READ;
01879 tcp_fd->tf_select_res(tcp_fd->tf_srfd,
01880 SR_SELECT_READ);
01881 }
01882
01883
01884 if (tcp_fd->tf_flags & TFF_IOCTL_IP)
01885 (void) tcp_acceptto(tcp_fd);
01886
01887 return;
01888 }
01889
01890 if (tcp_conn->tc_state == TCS_CLOSED)
01891 {
01892 reply= tcp_conn->tc_error;
01893 assert(tcp_conn->tc_fd == tcp_fd);
01894 tcp_fd->tf_conn= NULL;
01895 tcp_conn->tc_fd= NULL;
01896 tcp_fd->tf_error= reply;
01897 }
01898 else
01899 {
01900 tcp_fd->tf_flags |= TFF_CONNECTED;
01901 reply= NW_OK;
01902 }
01903
01904 if (tcp_fd->tf_flags & TFF_CONNECTING)
01905 {
01906
01907 tcp_fd->tf_flags &= ~TFF_CONNECTING;
01908
01909
01910 if ((tcp_fd->tf_flags & TFF_SEL_WRITE) &&
01911 tcp_fd->tf_select_res)
01912 {
01913 tcp_fd->tf_flags &= ~TFF_SEL_WRITE;
01914 tcp_fd->tf_select_res(tcp_fd->tf_srfd,
01915 SR_SELECT_WRITE);
01916 }
01917
01918 return;
01919 }
01920
01921 assert(tcp_fd->tf_flags & TFF_IOCTL_IP);
01922 assert(tcp_fd->tf_ioreq == NWIOTCPLISTEN ||
01923 tcp_fd->tf_ioreq == NWIOTCPCONN);
01924
01925 tcp_reply_ioctl (tcp_fd, reply);
01926 }
01927
01928
01929
01930
01931
01932 PUBLIC void tcp_close(fd)
01933 int fd;
01934 {
01935 int i;
01936 tcp_fd_t *tcp_fd;
01937 tcp_conn_t *tcp_conn;
01938
01939 tcp_fd= &tcp_fd_table[fd];
01940
01941 assert (tcp_fd->tf_flags & TFF_INUSE);
01942 assert (!(tcp_fd->tf_flags &
01943 (TFF_IOCTL_IP|TFF_READ_IP|TFF_WRITE_IP)));
01944
01945 if (tcp_fd->tf_flags & TFF_LISTENQ)
01946 {
01947
01948 for (i= 0; i<TFL_LISTEN_MAX; i++)
01949 {
01950 tcp_conn= tcp_fd->tf_listenq[i];
01951 if (!tcp_conn)
01952 continue;
01953
01954 tcp_fd->tf_listenq[i]= NULL;
01955 assert(tcp_conn->tc_fd == tcp_fd);
01956 tcp_conn->tc_fd= NULL;
01957
01958 if (tcp_conn->tc_connInprogress)
01959 {
01960 tcp_conn->tc_connInprogress= 0;
01961 tcp_close_connection(tcp_conn, ENOCONN);
01962 continue;
01963 }
01964
01965 tcp_shutdown (tcp_conn);
01966 if (tcp_conn->tc_state == TCS_ESTABLISHED)
01967 tcp_conn->tc_state= TCS_CLOSING;
01968
01969
01970 tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CLOSING;
01971
01972
01973 if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
01974 tcp_close_connection(tcp_conn, ENOTCONN);
01975 }
01976
01977 tcp_conn= tcp_fd->tf_conn;
01978 assert(tcp_conn->tc_fd == tcp_fd);
01979 assert (tcp_conn->tc_connInprogress);
01980 tcp_conn->tc_connInprogress= 0;
01981 tcp_conn->tc_fd= NULL;
01982 tcp_fd->tf_conn= NULL;
01983 tcp_close_connection(tcp_conn, ENOCONN);
01984 }
01985 for (i= 0; i<TFL_LISTEN_MAX; i++)
01986 {
01987 assert(tcp_fd->tf_listenq[i] == NULL);
01988 }
01989
01990 if (tcp_fd->tf_flags & TFF_CONNECTING)
01991 {
01992 tcp_conn= tcp_fd->tf_conn;
01993 assert(tcp_conn != NULL);
01994
01995 assert (tcp_conn->tc_connInprogress);
01996 tcp_conn->tc_connInprogress= 0;
01997 tcp_conn->tc_fd= NULL;
01998 tcp_fd->tf_conn= NULL;
01999 tcp_close_connection(tcp_conn, ENOCONN);
02000
02001 tcp_fd->tf_flags &= ~TFF_CONNECTING;
02002 }
02003
02004 tcp_fd->tf_flags &= ~TFF_INUSE;
02005 if (!tcp_fd->tf_conn)
02006 return;
02007
02008
02009 tcp_conn= tcp_fd->tf_conn;
02010 assert(tcp_conn->tc_fd == tcp_fd);
02011 tcp_conn->tc_fd= NULL;
02012
02013 assert (!tcp_conn->tc_connInprogress);
02014
02015 tcp_shutdown (tcp_conn);
02016 if (tcp_conn->tc_state == TCS_ESTABLISHED)
02017 {
02018 tcp_conn->tc_state= TCS_CLOSING;
02019 }
02020
02021
02022 tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CLOSING;
02023
02024
02025 if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
02026 tcp_close_connection(tcp_conn, ENOTCONN);
02027 }
02028
02029 PUBLIC int tcp_cancel(fd, which_operation)
02030 int fd;
02031 int which_operation;
02032 {
02033 tcp_fd_t *tcp_fd;
02034 tcp_conn_t *tcp_conn;
02035
02036 tcp_fd= &tcp_fd_table[fd];
02037
02038 assert (tcp_fd->tf_flags & TFF_INUSE);
02039
02040 tcp_conn= tcp_fd->tf_conn;
02041
02042 switch (which_operation)
02043 {
02044 case SR_CANCEL_WRITE:
02045 assert (tcp_fd->tf_flags & TFF_WRITE_IP);
02046 tcp_fd->tf_flags &= ~TFF_WRITE_IP;
02047
02048 if (tcp_fd->tf_write_offset)
02049 reply_thr_get (tcp_fd, tcp_fd->tf_write_offset, FALSE);
02050 else
02051 reply_thr_get (tcp_fd, EINTR, FALSE);
02052 break;
02053 case SR_CANCEL_READ:
02054 assert (tcp_fd->tf_flags & TFF_READ_IP);
02055 tcp_fd->tf_flags &= ~TFF_READ_IP;
02056 if (tcp_fd->tf_read_offset)
02057 reply_thr_put (tcp_fd, tcp_fd->tf_read_offset, FALSE);
02058 else
02059 reply_thr_put (tcp_fd, EINTR, FALSE);
02060 break;
02061 case SR_CANCEL_IOCTL:
02062 assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
02063 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
02064
02065 if (tcp_fd->tf_flags & TFF_IOC_INIT_SP)
02066 {
02067 tcp_fd->tf_flags &= ~TFF_IOC_INIT_SP;
02068 reply_thr_put (tcp_fd, EINTR, TRUE);
02069 break;
02070 }
02071
02072 switch (tcp_fd->tf_ioreq)
02073 {
02074 case NWIOGTCPCONF:
02075 reply_thr_put (tcp_fd, EINTR, TRUE);
02076 break;
02077 case NWIOSTCPCONF:
02078 case NWIOTCPSHUTDOWN:
02079 reply_thr_get (tcp_fd, EINTR, TRUE);
02080 break;
02081 case NWIOTCPCONN:
02082 case NWIOTCPLISTEN:
02083 assert (tcp_conn->tc_connInprogress);
02084 tcp_conn->tc_connInprogress= 0;
02085 tcp_conn->tc_fd= NULL;
02086 tcp_fd->tf_conn= NULL;
02087 tcp_close_connection(tcp_conn, ENOCONN);
02088 reply_thr_get (tcp_fd, EINTR, TRUE);
02089 break;
02090 default:
02091 ip_warning(( "unknown ioctl inprogress: 0x%x",
02092 tcp_fd->tf_ioreq ));
02093 reply_thr_get (tcp_fd, EINTR, TRUE);
02094 break;
02095 }
02096 break;
02097 default:
02098 ip_panic(( "unknown cancel request" ));
02099 break;
02100 }
02101 return NW_OK;
02102 }
02103
02104
02105
02106
02107
02108 PRIVATE int tcp_connect(tcp_fd)
02109 tcp_fd_t *tcp_fd;
02110 {
02111 tcp_conn_t *tcp_conn;
02112 nwio_tcpcl_t *tcpcl;
02113 long nwtcl_flags;
02114 int r, do_asynch;
02115 acc_t *data;
02116
02117 if (!(tcp_fd->tf_flags & TFF_CONF_SET))
02118 {
02119 tcp_reply_ioctl(tcp_fd, EBADMODE);
02120 return NW_OK;
02121 }
02122 assert (!(tcp_fd->tf_flags & TFF_CONNECTED) &&
02123 !(tcp_fd->tf_flags & TFF_CONNECTING) &&
02124 !(tcp_fd->tf_flags & TFF_LISTENQ));
02125 if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
02126 != (NWTC_SET_RA|NWTC_SET_RP))
02127 {
02128 tcp_reply_ioctl(tcp_fd, EBADMODE);
02129 return NW_OK;
02130 }
02131
02132 data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
02133 sizeof(*tcpcl), TRUE);
02134 if (!data)
02135 return EFAULT;
02136
02137 data= bf_packIffLess(data, sizeof(*tcpcl));
02138 assert (data->acc_length == sizeof(*tcpcl));
02139 tcpcl= (nwio_tcpcl_t *)ptr2acc_data(data);
02140
02141 nwtcl_flags= tcpcl->nwtcl_flags;
02142 bf_afree(data); data= NULL; tcpcl= NULL;
02143
02144 if (nwtcl_flags == TCF_ASYNCH)
02145 do_asynch= 1;
02146 else if (nwtcl_flags == TCF_DEFAULT)
02147 do_asynch= 0;
02148 else
02149 {
02150 tcp_reply_ioctl(tcp_fd, EINVAL);
02151 return NW_OK;
02152 }
02153
02154 assert(!tcp_fd->tf_conn);
02155 tcp_conn= find_conn_entry(tcp_fd->tf_tcpconf.nwtc_locport,
02156 tcp_fd->tf_port->tp_ipaddr,
02157 tcp_fd->tf_tcpconf.nwtc_remport,
02158 tcp_fd->tf_tcpconf.nwtc_remaddr);
02159 if (tcp_conn)
02160 {
02161 if (tcp_conn->tc_fd)
02162 {
02163 tcp_reply_ioctl(tcp_fd, EADDRINUSE);
02164 return NW_OK;
02165 }
02166 }
02167 else
02168 {
02169 tcp_conn= find_empty_conn();
02170 if (!tcp_conn)
02171 {
02172 tcp_reply_ioctl(tcp_fd, EAGAIN);
02173 return NW_OK;
02174 }
02175 }
02176 tcp_fd->tf_conn= tcp_conn;
02177
02178 r= tcp_su4connect(tcp_fd);
02179 if (r == NW_SUSPEND && do_asynch)
02180 {
02181 tcp_fd->tf_flags |= TFF_CONNECTING;
02182 tcp_reply_ioctl(tcp_fd, EINPROGRESS);
02183 r= NW_OK;
02184 }
02185 return r;
02186 }
02187
02188
02189
02190
02191
02192 PRIVATE int tcp_su4connect(tcp_fd)
02193 tcp_fd_t *tcp_fd;
02194 {
02195 tcp_conn_t *tcp_conn;
02196
02197 tcp_conn= tcp_fd->tf_conn;
02198
02199 tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport;
02200 tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr;
02201
02202 assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP);
02203 assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA);
02204 tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;
02205 tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;
02206
02207 tcp_setup_conn(tcp_fd->tf_port, tcp_conn);
02208
02209 tcp_conn->tc_fd= tcp_fd;
02210 tcp_conn->tc_connInprogress= 1;
02211 tcp_conn->tc_orglisten= FALSE;
02212 tcp_conn->tc_state= TCS_SYN_SENT;
02213 tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CONNECT;
02214
02215
02216 tcp_set_send_timer(tcp_conn);
02217
02218 tcp_conn_write(tcp_conn, 0);
02219
02220 if (tcp_conn->tc_connInprogress)
02221 return NW_SUSPEND;
02222 else
02223 return NW_OK;
02224 }
02225
02226
02227
02228
02229
02230
02231 PRIVATE int tcp_listen(tcp_fd, do_listenq)
02232 tcp_fd_t *tcp_fd;
02233 int do_listenq;
02234 {
02235 tcp_conn_t *tcp_conn;
02236
02237 if (!(tcp_fd->tf_flags & TFF_CONF_SET))
02238 {
02239 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
02240 reply_thr_get(tcp_fd, EBADMODE, TRUE);
02241 return NW_OK;
02242 }
02243 assert (!(tcp_fd->tf_flags & TFF_CONNECTED) &&
02244 !(tcp_fd->tf_flags & TFF_CONNECTING) &&
02245 !(tcp_fd->tf_flags & TFF_LISTENQ));
02246 tcp_conn= tcp_fd->tf_conn;
02247 assert(!tcp_conn);
02248
02249 if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
02250 == (NWTC_SET_RA|NWTC_SET_RP))
02251 {
02252 tcp_conn= find_conn_entry(
02253 tcp_fd->tf_tcpconf.nwtc_locport,
02254 tcp_fd->tf_port->tp_ipaddr,
02255 tcp_fd->tf_tcpconf.nwtc_remport,
02256 tcp_fd->tf_tcpconf.nwtc_remaddr);
02257 if (tcp_conn)
02258 {
02259 if (tcp_conn->tc_fd)
02260 {
02261 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
02262 reply_thr_get (tcp_fd, EADDRINUSE, TRUE);
02263 return NW_OK;
02264 }
02265 tcp_fd->tf_conn= tcp_conn;
02266 return tcp_su4listen(tcp_fd, tcp_conn, do_listenq);
02267 }
02268 }
02269 tcp_conn= find_empty_conn();
02270 if (!tcp_conn)
02271 {
02272 tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
02273 reply_thr_get (tcp_fd, EAGAIN, TRUE);
02274 return NW_OK;
02275 }
02276 tcp_fd->tf_conn= tcp_conn;
02277 return tcp_su4listen(tcp_fd, tcp_conn, do_listenq);
02278 }
02279
02280
02281
02282
02283
02284 PRIVATE int tcp_acceptto(tcp_fd)
02285 tcp_fd_t *tcp_fd;
02286 {
02287 int i, dst_nr;
02288 tcp_fd_t *dst_fd;
02289 tcp_conn_t *tcp_conn;
02290 tcp_cookie_t *cookiep;
02291 acc_t *data;
02292 tcp_cookie_t cookie;
02293
02294 if (!(tcp_fd->tf_flags & TFF_LISTENQ))
02295 {
02296 tcp_reply_ioctl(tcp_fd, EINVAL);
02297 return NW_OK;
02298 }
02299 for (i= 0; i<TFL_LISTEN_MAX; i++)
02300 {
02301 tcp_conn= tcp_fd->tf_listenq[i];
02302 if (tcp_conn && !tcp_conn->tc_connInprogress)
02303 break;
02304 }
02305 if (i >= TFL_LISTEN_MAX)
02306 {
02307
02308 return NW_SUSPEND;
02309 }
02310
02311 data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0,
02312 sizeof(*cookiep), TRUE);
02313 if (!data)
02314 return EFAULT;
02315
02316 data= bf_packIffLess(data, sizeof(*cookiep));
02317 cookiep= (tcp_cookie_t *)ptr2acc_data(data);
02318 cookie= *cookiep;
02319
02320 bf_afree(data); data= NULL;
02321
02322 dst_nr= cookie.tc_ref;
02323 if (dst_nr < 0 || dst_nr >= TCP_FD_NR)
02324 {
02325 printf("tcp_acceptto: bad fd %d\n", dst_nr);
02326 tcp_reply_ioctl(tcp_fd, EINVAL);
02327 return NW_OK;
02328 }
02329 dst_fd= &tcp_fd_table[dst_nr];
02330 if (!(dst_fd->tf_flags & TFF_INUSE) ||
02331 (dst_fd->tf_flags & (TFF_READ_IP|TFF_WRITE_IP|TFF_IOCTL_IP)) ||
02332 dst_fd->tf_conn != NULL ||
02333 !(dst_fd->tf_flags & TFF_COOKIE))
02334 {
02335 printf("tcp_acceptto: bad flags 0x%x or conn %p for fd %d\n",
02336 dst_fd->tf_flags, dst_fd->tf_conn, dst_nr);
02337 tcp_reply_ioctl(tcp_fd, EINVAL);
02338 return NW_OK;
02339 }
02340 if (memcmp(&cookie, &dst_fd->tf_cookie, sizeof(cookie)) != 0)
02341 {
02342 printf("tcp_acceptto: bad cookie\n");
02343 return NW_OK;
02344 }
02345
02346
02347 tcp_fd->tf_listenq[i]= NULL;
02348 tcp_conn->tc_fd= dst_fd;
02349 dst_fd->tf_conn= tcp_conn;
02350 dst_fd->tf_flags |= TFF_CONNECTED;
02351
02352 tcp_reply_ioctl(tcp_fd, NW_OK);
02353 return NW_OK;
02354 }
02355
02356
02357 PRIVATE void tcp_buffree (priority)
02358 int priority;
02359 {
02360 int i;
02361 tcp_conn_t *tcp_conn;
02362
02363 if (priority == TCP_PRI_FRAG2SEND)
02364 {
02365 for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
02366 tcp_conn++)
02367 {
02368 if (!(tcp_conn->tc_flags & TCF_INUSE))
02369 continue;
02370 if (!tcp_conn->tc_frag2send)
02371 continue;
02372 if (tcp_conn->tc_busy)
02373 continue;
02374 bf_afree(tcp_conn->tc_frag2send);
02375 tcp_conn->tc_frag2send= 0;
02376 }
02377 }
02378
02379 if (priority == TCP_PRI_CONN_EXTRA)
02380 {
02381 for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
02382 tcp_conn++)
02383 {
02384 if (!(tcp_conn->tc_flags & TCF_INUSE))
02385 continue;
02386 if (tcp_conn->tc_busy)
02387 continue;
02388 if (tcp_conn->tc_adv_data)
02389 {
02390 bf_afree(tcp_conn->tc_adv_data);
02391 tcp_conn->tc_adv_data= NULL;
02392 }
02393 }
02394 }
02395
02396 if (priority == TCP_PRI_CONNwoUSER)
02397 {
02398 for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
02399 tcp_conn++)
02400 {
02401 if (!(tcp_conn->tc_flags & TCF_INUSE))
02402 continue;
02403 if (tcp_conn->tc_busy)
02404 continue;
02405 if (tcp_conn->tc_fd)
02406 continue;
02407 if (tcp_conn->tc_state == TCS_CLOSED)
02408 continue;
02409 if (tcp_conn->tc_rcvd_data == NULL &&
02410 tcp_conn->tc_send_data == NULL)
02411 {
02412 continue;
02413 }
02414 tcp_close_connection (tcp_conn, EOUTOFBUFS);
02415 }
02416 }
02417
02418 if (priority == TCP_PRI_CONN_INUSE)
02419 {
02420 for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
02421 tcp_conn++)
02422 {
02423 if (!(tcp_conn->tc_flags & TCF_INUSE))
02424 continue;
02425 if (tcp_conn->tc_busy)
02426 continue;
02427 if (tcp_conn->tc_state == TCS_CLOSED)
02428 continue;
02429 if (tcp_conn->tc_rcvd_data == NULL &&
02430 tcp_conn->tc_send_data == NULL)
02431 {
02432 continue;
02433 }
02434 tcp_close_connection (tcp_conn, EOUTOFBUFS);
02435 }
02436 }
02437 }
02438
02439 #ifdef BUF_CONSISTENCY_CHECK
02440 PRIVATE void tcp_bufcheck()
02441 {
02442 int i;
02443 tcp_conn_t *tcp_conn;
02444 tcp_port_t *tcp_port;
02445
02446 for (i= 0, tcp_port= tcp_port_table; i<tcp_conf_nr; i++, tcp_port++)
02447 {
02448 if (tcp_port->tp_pack)
02449 bf_check_acc(tcp_port->tp_pack);
02450 }
02451 for (i= 0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++, tcp_conn++)
02452 {
02453 assert(!tcp_conn->tc_busy);
02454 if (tcp_conn->tc_rcvd_data)
02455 bf_check_acc(tcp_conn->tc_rcvd_data);
02456 if (tcp_conn->tc_adv_data)
02457 bf_check_acc(tcp_conn->tc_adv_data);
02458 if (tcp_conn->tc_send_data)
02459 bf_check_acc(tcp_conn->tc_send_data);
02460 if (tcp_conn->tc_remipopt)
02461 bf_check_acc(tcp_conn->tc_remipopt);
02462 if (tcp_conn->tc_tcpopt)
02463 bf_check_acc(tcp_conn->tc_tcpopt);
02464 if (tcp_conn->tc_frag2send)
02465 bf_check_acc(tcp_conn->tc_frag2send);
02466 }
02467 }
02468 #endif
02469
02470 PUBLIC void tcp_notreach(tcp_conn)
02471 tcp_conn_t *tcp_conn;
02472 {
02473 int new_ttl;
02474
02475 new_ttl= tcp_conn->tc_ttl;
02476 if (new_ttl == IP_MAX_TTL)
02477 {
02478 if (tcp_conn->tc_state == TCS_SYN_SENT)
02479 tcp_close_connection(tcp_conn, EDSTNOTRCH);
02480 return;
02481 }
02482 else if (new_ttl < TCP_DEF_TTL_NEXT)
02483 new_ttl= TCP_DEF_TTL_NEXT;
02484 else
02485 {
02486 new_ttl *= 2;
02487 if (new_ttl> IP_MAX_TTL)
02488 new_ttl= IP_MAX_TTL;
02489 }
02490 tcp_conn->tc_ttl= new_ttl;
02491 tcp_conn->tc_stt= 0;
02492 tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
02493 tcp_conn_write(tcp_conn, 1);
02494 }
02495
02496 FORWARD u32_t mtu_table[]=
02497 {
02498
02499
02500
02501
02502 65535,
02503 32000,
02504
02505 17914,
02506
02507 8166,
02508
02509
02510 4352,
02511
02512
02513 2002,
02514
02515
02516
02517
02518 1492,
02519
02520
02521 1006,
02522
02523
02524
02525
02526
02527 508,
02528
02529 296,
02530 68,
02531 0,
02532 };
02533
02534 PUBLIC void tcp_mtu_exceeded(tcp_conn)
02535 tcp_conn_t *tcp_conn;
02536 {
02537 u16_t mtu;
02538 int i;
02539 clock_t curr_time;
02540
02541 if (!(tcp_conn->tc_flags & TCF_PMTU))
02542 {
02543
02544
02545
02546
02547 return;
02548 }
02549 curr_time= get_time();
02550
02551
02552
02553
02554
02555
02556 if (curr_time >= tcp_conn->tc_mtutim + TCP_PMTU_INCR_IV)
02557 {
02558 mtu= tcp_conn->tc_mtu;
02559 mtu -= mtu/TCP_PMTU_INCR_FRAC;
02560 tcp_conn->tc_mtu= mtu;
02561 tcp_conn->tc_mtutim= curr_time;
02562 DBLOCK(1, printf(
02563 "tcp_mtu_exceeded: new (lowered) mtu %d for conn %d\n",
02564 mtu, tcp_conn-tcp_conn_table));
02565 tcp_conn->tc_stt= 0;
02566 tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
02567 tcp_conn_write(tcp_conn, 1);
02568 return;
02569 }
02570
02571 tcp_conn->tc_mtutim= curr_time;
02572 mtu= tcp_conn->tc_mtu;
02573 for (i= 0; mtu_table[i] >= mtu; i++)
02574 ;
02575 mtu= mtu_table[i];
02576 if (mtu >= TCP_MIN_PATH_MTU)
02577 {
02578 tcp_conn->tc_mtu= mtu;
02579 }
02580 else
02581 {
02582
02583
02584
02585 tcp_conn->tc_flags &= ~TCF_PMTU;
02586 tcp_conn->tc_mtu= TCP_MIN_PATH_MTU;
02587 DBLOCK(1, printf(
02588 "tcp_mtu_exceeded: clearing TCF_PMTU for conn %d\n",
02589 tcp_conn-tcp_conn_table););
02590
02591 }
02592 DBLOCK(1, printf("tcp_mtu_exceeded: new mtu %d for conn %d\n",
02593 mtu, tcp_conn-tcp_conn_table););
02594 tcp_conn->tc_stt= 0;
02595 tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA;
02596 tcp_conn_write(tcp_conn, 1);
02597 }
02598
02599 PUBLIC void tcp_mtu_incr(tcp_conn)
02600 tcp_conn_t *tcp_conn;
02601 {
02602 clock_t curr_time;
02603 u32_t mtu;
02604
02605 assert(tcp_conn->tc_mtu < tcp_conn->tc_max_mtu);
02606 if (!(tcp_conn->tc_flags & TCF_PMTU))
02607 {
02608
02609
02610
02611
02612 curr_time= get_time();
02613 if (curr_time > tcp_conn->tc_mtutim+TCP_PMTU_EN_IV)
02614 {
02615 tcp_conn->tc_flags |= TCF_PMTU;
02616 DBLOCK(1, printf(
02617 "tcp_mtu_incr: setting TCF_PMTU for conn %d\n",
02618 tcp_conn-tcp_conn_table););
02619 }
02620 return;
02621 }
02622
02623 mtu= tcp_conn->tc_mtu;
02624 mtu += mtu/TCP_PMTU_INCR_FRAC;
02625 if (mtu > tcp_conn->tc_max_mtu)
02626 mtu= tcp_conn->tc_max_mtu;
02627 tcp_conn->tc_mtu= mtu;
02628 DBLOCK(0x1, printf("tcp_mtu_incr: new mtu %ld for conn %d\n",
02629 mtu, tcp_conn-tcp_conn_table););
02630 }
02631
02632
02633
02634
02635
02636 PRIVATE void tcp_setup_conn(tcp_port, tcp_conn)
02637 tcp_port_t *tcp_port;
02638 tcp_conn_t *tcp_conn;
02639 {
02640 u16_t mss;
02641
02642 assert(!tcp_conn->tc_connInprogress);
02643 tcp_conn->tc_port= tcp_port;
02644 if (tcp_conn->tc_flags & TCF_INUSE)
02645 {
02646 assert (tcp_conn->tc_state == TCS_CLOSED);
02647 assert (!tcp_conn->tc_send_data);
02648 if (tcp_conn->tc_senddis < get_time())
02649 tcp_conn->tc_ISS= 0;
02650 }
02651 else
02652 {
02653 assert(!tcp_conn->tc_busy);
02654 tcp_conn->tc_senddis= 0;
02655 tcp_conn->tc_ISS= 0;
02656 tcp_conn->tc_tos= TCP_DEF_TOS;
02657 tcp_conn->tc_ttl= TCP_DEF_TTL;
02658 tcp_conn->tc_rcv_wnd= TCP_MAX_RCV_WND_SIZE;
02659 tcp_conn->tc_fd= NULL;
02660 }
02661 if (!tcp_conn->tc_ISS)
02662 {
02663 tcp_conn->tc_ISS= tcp_rand32();
02664 }
02665 tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;
02666 tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;
02667 tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS+1;
02668 tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;
02669 tcp_conn->tc_SND_PSH= tcp_conn->tc_ISS+1;
02670 tcp_conn->tc_IRS= 0;
02671 tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS;
02672 tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS;
02673 tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS;
02674 tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
02675
02676 assert(tcp_conn->tc_rcvd_data == NULL);
02677 assert(tcp_conn->tc_adv_data == NULL);
02678 assert(tcp_conn->tc_send_data == NULL);
02679
02680 tcp_conn->tc_ka_time= TCP_DEF_KEEPALIVE;
02681
02682 tcp_conn->tc_remipopt= NULL;
02683 tcp_conn->tc_tcpopt= NULL;
02684
02685 assert(tcp_conn->tc_frag2send == NULL);
02686
02687 tcp_conn->tc_stt= 0;
02688 tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;
02689 tcp_conn->tc_0wnd_to= 0;
02690 tcp_conn->tc_artt= TCP_DEF_RTT*TCP_RTT_SCALE;
02691 tcp_conn->tc_drtt= 0;
02692 tcp_conn->tc_rtt= TCP_DEF_RTT;
02693 tcp_conn->tc_max_mtu= tcp_conn->tc_port->tp_mtu;
02694 tcp_conn->tc_mtu= tcp_conn->tc_max_mtu;
02695 tcp_conn->tc_mtutim= 0;
02696 tcp_conn->tc_error= NW_OK;
02697 mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;
02698 tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + 2*mss;
02699 tcp_conn->tc_snd_cthresh= TCP_MAX_SND_WND_SIZE;
02700 tcp_conn->tc_snd_cinc=
02701 (long)TCP_DEF_MSS*TCP_DEF_MSS/TCP_MAX_SND_WND_SIZE+1;
02702 tcp_conn->tc_snd_wnd= TCP_MAX_SND_WND_SIZE;
02703 tcp_conn->tc_rt_time= 0;
02704 tcp_conn->tc_rt_seq= 0;
02705 tcp_conn->tc_rt_threshold= tcp_conn->tc_ISS;
02706 tcp_conn->tc_flags= TCF_INUSE;
02707 tcp_conn->tc_flags |= TCF_PMTU;
02708
02709 clck_untimer(&tcp_conn->tc_transmit_timer);
02710 tcp_conn->tc_transmit_seq= 0;
02711 }
02712
02713 PRIVATE u32_t tcp_rand32()
02714 {
02715 u8_t bits[RAND256_BUFSIZE];
02716
02717 rand256(bits);
02718 return bits[0] | (bits[1] << 8) | (bits[2] << 16) | (bits[3] << 24);
02719 }
02720
02721
02722
02723