📄 tcp.c
字号:
/*tcp_su4connect*/PRIVATE int tcp_su4connect(tcp_fd)tcp_fd_t *tcp_fd;{ tcp_conn_t *tcp_conn; tcp_conn= tcp_fd->tf_conn; tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport; tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr; assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP); assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA); tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport; tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr; tcp_setup_conn(tcp_fd->tf_port, tcp_conn); tcp_conn->tc_fd= tcp_fd; tcp_conn->tc_connInprogress= 1; tcp_conn->tc_orglisten= FALSE; tcp_conn->tc_state= TCS_SYN_SENT; tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CONNECT; /* Start the timer (if necessary) */ tcp_set_send_timer(tcp_conn); tcp_conn_write(tcp_conn, 0); if (tcp_conn->tc_connInprogress) return NW_SUSPEND; else return NW_OK;}/*tcp_listen*/PRIVATE int tcp_listen(tcp_fd, do_listenq)tcp_fd_t *tcp_fd;int do_listenq;{ tcp_conn_t *tcp_conn; if (!(tcp_fd->tf_flags & TFF_CONF_SET)) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get(tcp_fd, EBADMODE, TRUE); return NW_OK; } assert (!(tcp_fd->tf_flags & TFF_CONNECTEDx) && !(tcp_fd->tf_flags & TFF_CONNECTING) && !(tcp_fd->tf_flags & TFF_LISTENQ)); tcp_conn= tcp_fd->tf_conn; assert(!tcp_conn); if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP)) == (NWTC_SET_RA|NWTC_SET_RP)) { tcp_conn= find_conn_entry( tcp_fd->tf_tcpconf.nwtc_locport, tcp_fd->tf_port->tp_ipaddr, tcp_fd->tf_tcpconf.nwtc_remport, tcp_fd->tf_tcpconf.nwtc_remaddr); if (tcp_conn) { if (tcp_conn->tc_fd) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, EADDRINUSE, TRUE); return NW_OK; } tcp_fd->tf_conn= tcp_conn; return tcp_su4listen(tcp_fd, tcp_conn, do_listenq); } } tcp_conn= find_empty_conn(); if (!tcp_conn) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, EAGAIN, TRUE); return NW_OK; } tcp_fd->tf_conn= tcp_conn; return tcp_su4listen(tcp_fd, tcp_conn, do_listenq);}/*tcp_acceptto*/PRIVATE int tcp_acceptto(tcp_fd)tcp_fd_t *tcp_fd;{ int i, dst_nr; tcp_fd_t *dst_fd; tcp_conn_t *tcp_conn; tcp_cookie_t *cookiep; acc_t *data; if (!(tcp_fd->tf_flags & TFF_LISTENQ)) { tcp_reply_ioctl(tcp_fd, EINVAL); return NW_OK; } for (i= 0; i<TFL_LISTEN_MAX; i++) { tcp_conn= tcp_fd->tf_listenq[i]; if (tcp_conn && !tcp_conn->tc_connInprogress) break; } if (i >= TFL_LISTEN_MAX) { /* Nothing, suspend caller */ return NW_SUSPEND; } data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0, sizeof(*cookiep), TRUE); if (!data) return EFAULT; data= bf_packIffLess(data, sizeof(*cookiep)); cookiep= (tcp_cookie_t *)ptr2acc_data(data); dst_nr= cookiep->tc_ref; if (dst_nr < 0 || dst_nr >= TCP_FD_NR) { printf("tcp_acceptto: bad fd %d\n", dst_nr); tcp_reply_ioctl(tcp_fd, EINVAL); return NW_OK; } dst_fd= &tcp_fd_table[dst_nr]; if (!(dst_fd->tf_flags & TFF_INUSE) || (dst_fd->tf_flags & (TFF_READ_IP|TFF_WRITE_IP|TFF_IOCTL_IP)) || dst_fd->tf_conn != NULL || !(dst_fd->tf_flags & TFF_COOKIE)) { printf("tcp_acceptto: bad flags 0x%x or conn %p for fd %d\n", dst_fd->tf_flags, dst_fd->tf_conn, dst_nr); tcp_reply_ioctl(tcp_fd, EINVAL); return NW_OK; } if (memcmp(cookiep, &dst_fd->tf_cookie, sizeof(*cookiep)) != 0) { printf("tcp_acceptto: bad cookie\n"); return NW_OK; } /* Move connection */ tcp_fd->tf_listenq[i]= NULL; tcp_conn->tc_fd= dst_fd; dst_fd->tf_conn= tcp_conn; dst_fd->tf_flags |= TFF_CONNECTEDx; tcp_reply_ioctl(tcp_fd, NW_OK); return NW_OK;}PRIVATE void tcp_buffree (priority)int priority;{ int i; tcp_conn_t *tcp_conn; if (priority == TCP_PRI_FRAG2SEND) { for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++, tcp_conn++) { if (!(tcp_conn->tc_flags & TCF_INUSE)) continue; if (!tcp_conn->tc_frag2send) continue; if (tcp_conn->tc_busy) continue; bf_afree(tcp_conn->tc_frag2send); tcp_conn->tc_frag2send= 0; } } if (priority == TCP_PRI_CONN_EXTRA) { for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++, tcp_conn++) { if (!(tcp_conn->tc_flags & TCF_INUSE)) continue; if (tcp_conn->tc_busy) continue; if (tcp_conn->tc_adv_data) { bf_afree(tcp_conn->tc_adv_data); tcp_conn->tc_adv_data= NULL; } } } if (priority == TCP_PRI_CONNwoUSER) { for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++, tcp_conn++) { if (!(tcp_conn->tc_flags & TCF_INUSE)) continue; if (tcp_conn->tc_busy) continue; if (tcp_conn->tc_fd) continue; if (tcp_conn->tc_state == TCS_CLOSED) continue; if (tcp_conn->tc_rcvd_data == NULL && tcp_conn->tc_send_data == NULL) { continue; } tcp_close_connection (tcp_conn, EOUTOFBUFS); } } if (priority == TCP_PRI_CONN_INUSE) { for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++, tcp_conn++) { if (!(tcp_conn->tc_flags & TCF_INUSE)) continue; if (tcp_conn->tc_busy) continue; if (tcp_conn->tc_state == TCS_CLOSED) continue; if (tcp_conn->tc_rcvd_data == NULL && tcp_conn->tc_send_data == NULL) { continue; } tcp_close_connection (tcp_conn, EOUTOFBUFS); } }}#ifdef BUF_CONSISTENCY_CHECKPRIVATE void tcp_bufcheck(){ int i; tcp_conn_t *tcp_conn; tcp_port_t *tcp_port; for (i= 0, tcp_port= tcp_port_table; i<tcp_conf_nr; i++, tcp_port++) { if (tcp_port->tp_pack) bf_check_acc(tcp_port->tp_pack); } for (i= 0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++, tcp_conn++) { assert(!tcp_conn->tc_busy); if (tcp_conn->tc_rcvd_data) bf_check_acc(tcp_conn->tc_rcvd_data); if (tcp_conn->tc_adv_data) bf_check_acc(tcp_conn->tc_adv_data); if (tcp_conn->tc_send_data) bf_check_acc(tcp_conn->tc_send_data); if (tcp_conn->tc_remipopt) bf_check_acc(tcp_conn->tc_remipopt); if (tcp_conn->tc_tcpopt) bf_check_acc(tcp_conn->tc_tcpopt); if (tcp_conn->tc_frag2send) bf_check_acc(tcp_conn->tc_frag2send); }}#endifPUBLIC void tcp_notreach(tcp_conn)tcp_conn_t *tcp_conn;{ int new_ttl; new_ttl= tcp_conn->tc_ttl; if (new_ttl == IP_MAX_TTL) { if (tcp_conn->tc_state == TCS_SYN_SENT) tcp_close_connection(tcp_conn, EDSTNOTRCH); return; } else if (new_ttl < TCP_DEF_TTL_NEXT) new_ttl= TCP_DEF_TTL_NEXT; else { new_ttl *= 2; if (new_ttl> IP_MAX_TTL) new_ttl= IP_MAX_TTL; } tcp_conn->tc_ttl= new_ttl; tcp_conn->tc_stt= 0; tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA; tcp_conn_write(tcp_conn, 1);}FORWARD u32_t mtu_table[]={ /* From RFC-1191 *//* Plateau MTU Comments Reference *//* ------ --- -------- --------- *//* 65535 Official maximum MTU RFC 791 *//* 65535 Hyperchannel RFC 1044 */ 65535, 32000, /* Just in case *//* 17914 16Mb IBM Token Ring ref. [6] */ 17914,/* 8166 IEEE 802.4 RFC 1042 */ 8166,/* 4464 IEEE 802.5 (4Mb max) RFC 1042 *//* 4352 FDDI (Revised) RFC 1188 */ 4352, /* (1%) *//* 2048 Wideband Network RFC 907 *//* 2002 IEEE 802.5 (4Mb recommended) RFC 1042 */ 2002, /* (2%) *//* 1536 Exp. Ethernet Nets RFC 895 *//* 1500 Ethernet Networks RFC 894 *//* 1500 Point-to-Point (default) RFC 1134 *//* 1492 IEEE 802.3 RFC 1042 */ 1492, /* (3%) *//* 1006 SLIP RFC 1055 *//* 1006 ARPANET BBN 1822 */ 1006,/* 576 X.25 Networks RFC 877 *//* 544 DEC IP Portal ref. [10] *//* 512 NETBIOS RFC 1088 *//* 508 IEEE 802/Source-Rt Bridge RFC 1042 *//* 508 ARCNET RFC 1051 */ 508, /* (13%) *//* 296 Point-to-Point (low delay) RFC 1144 */ 296, 68, /* Official minimum MTU RFC 791 */ 0, /* End of list */};PUBLIC void tcp_mtu_exceeded(tcp_conn)tcp_conn_t *tcp_conn;{ u16_t mtu; int i; clock_t curr_time; if (!(tcp_conn->tc_flags & TCF_PMTU)) { /* Strange, got MTU exceeded but DF is not set. Ignore * the error. If the problem persists, the connection will * time-out. */ return; } curr_time= get_time(); /* We get here in cases. Either were are trying to find an MTU * that works at all, or we are trying see how far we can increase * the current MTU. If the last change to the MTU was a long time * ago, we assume the second case. */ if (curr_time >= tcp_conn->tc_mtutim + TCP_PMTU_INCR_IV) { mtu= tcp_conn->tc_mtu; mtu -= mtu/TCP_PMTU_INCR_FRAC; tcp_conn->tc_mtu= mtu; tcp_conn->tc_mtutim= curr_time; DBLOCK(1, printf( "tcp_mtu_exceeded: new (lowered) mtu %d for conn %d\n", mtu, tcp_conn-tcp_conn_table)); tcp_conn->tc_stt= 0; tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA; tcp_conn_write(tcp_conn, 1); return; } tcp_conn->tc_mtutim= curr_time; mtu= tcp_conn->tc_mtu; for (i= 0; mtu_table[i] >= mtu; i++) ; /* Nothing to do */ mtu= mtu_table[i]; if (mtu >= TCP_MIN_PATH_MTU) { tcp_conn->tc_mtu= mtu; } else { /* Small MTUs can be used for denial-of-service attacks. * Switch-off PMTU if the MTU becomes too small. */ tcp_conn->tc_flags &= ~TCF_PMTU; tcp_conn->tc_mtu= TCP_MIN_PATH_MTU; DBLOCK(1, printf( "tcp_mtu_exceeded: clearing TCF_PMTU for conn %d\n", tcp_conn-tcp_conn_table);); } DBLOCK(1, printf("tcp_mtu_exceeded: new mtu %d for conn %d\n", mtu, tcp_conn-tcp_conn_table);); tcp_conn->tc_stt= 0; tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA; tcp_conn_write(tcp_conn, 1);}PUBLIC void tcp_mtu_incr(tcp_conn)tcp_conn_t *tcp_conn;{ clock_t curr_time; u32_t mtu; assert(tcp_conn->tc_mtu < tcp_conn->tc_max_mtu); if (!(tcp_conn->tc_flags & TCF_PMTU)) { /* Use a much longer time-out for retrying PMTU discovery * after is has been disabled. Note that PMTU discovery * can be disabled during a short loss of connectivity. */ curr_time= get_time(); if (curr_time > tcp_conn->tc_mtutim+TCP_PMTU_EN_IV) { tcp_conn->tc_flags |= TCF_PMTU; DBLOCK(1, printf( "tcp_mtu_incr: setting TCF_PMTU for conn %d\n", tcp_conn-tcp_conn_table);); } return; } mtu= tcp_conn->tc_mtu; mtu += mtu/TCP_PMTU_INCR_FRAC; if (mtu > tcp_conn->tc_max_mtu) mtu= tcp_conn->tc_max_mtu; tcp_conn->tc_mtu= mtu; DBLOCK(0x1, printf("tcp_mtu_incr: new mtu %ld for conn %d\n", mtu, tcp_conn-tcp_conn_table););}/*tcp_setup_conn*/PRIVATE void tcp_setup_conn(tcp_port, tcp_conn)tcp_port_t *tcp_port;tcp_conn_t *tcp_conn;{ u16_t mss; assert(!tcp_conn->tc_connInprogress); tcp_conn->tc_port= tcp_port; if (tcp_conn->tc_flags & TCF_INUSE) { assert (tcp_conn->tc_state == TCS_CLOSED); assert (!tcp_conn->tc_send_data); if (tcp_conn->tc_senddis < get_time()) tcp_conn->tc_ISS= 0; } else { assert(!tcp_conn->tc_busy); tcp_conn->tc_senddis= 0; tcp_conn->tc_ISS= 0; tcp_conn->tc_tos= TCP_DEF_TOS; tcp_conn->tc_ttl= TCP_DEF_TTL; tcp_conn->tc_rcv_wnd= TCP_MAX_RCV_WND_SIZE; tcp_conn->tc_fd= NULL; } if (!tcp_conn->tc_ISS) { tcp_conn->tc_ISS= tcp_rand32(); } tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS; tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS; tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS+1; tcp_conn->tc_SND_UP= tcp_conn->tc_ISS; tcp_conn->tc_SND_PSH= tcp_conn->tc_ISS+1; tcp_conn->tc_IRS= 0; tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS; tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS; tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS; tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS; assert(tcp_conn->tc_rcvd_data == NULL); assert(tcp_conn->tc_adv_data == NULL); assert(tcp_conn->tc_send_data == NULL); tcp_conn->tc_ka_time= TCP_DEF_KEEPALIVE; tcp_conn->tc_remipopt= NULL; tcp_conn->tc_tcpopt= NULL; assert(tcp_conn->tc_frag2send == NULL); tcp_conn->tc_stt= 0; tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD; tcp_conn->tc_0wnd_to= 0; tcp_conn->tc_artt= TCP_DEF_RTT*TCP_RTT_SCALE; tcp_conn->tc_drtt= 0; tcp_conn->tc_rtt= TCP_DEF_RTT; tcp_conn->tc_max_mtu= tcp_conn->tc_port->tp_mtu; tcp_conn->tc_mtu= tcp_conn->tc_max_mtu; tcp_conn->tc_mtutim= 0; tcp_conn->tc_error= NW_OK; mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE; tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + 2*mss; tcp_conn->tc_snd_cthresh= TCP_MAX_SND_WND_SIZE; tcp_conn->tc_snd_cinc= (long)TCP_DEF_MSS*TCP_DEF_MSS/TCP_MAX_SND_WND_SIZE+1; tcp_conn->tc_snd_wnd= TCP_MAX_SND_WND_SIZE; tcp_conn->tc_rt_time= 0; tcp_conn->tc_rt_seq= 0; tcp_conn->tc_rt_threshold= tcp_conn->tc_ISS; tcp_conn->tc_flags= TCF_INUSE; tcp_conn->tc_flags |= TCF_PMTU; clck_untimer(&tcp_conn->tc_transmit_timer); tcp_conn->tc_transmit_seq= 0;}PRIVATE u32_t tcp_rand32(){ u8_t bits[RAND256_BUFSIZE]; rand256(bits); return bits[0] | (bits[1] << 8) | (bits[2] << 16) | (bits[3] << 24);}/* * $PchId: tcp.c,v 1.34 2005/06/28 14:20:27 philip Exp $ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -