📄 tcp.c
字号:
break;
case SR_CANCEL_READ:
assert (tcp_fd->tf_flags & TFF_READ_IP);
tcp_fd->tf_flags &= ~TFF_READ_IP;
if (tcp_conn->tc_readuser == tcp_fd)
{
tcp_conn->tc_readuser= 0;
tcp_restart_fd_read (tcp_conn);
}
if (tcp_fd->tf_read_count)
reply_thr_put (tcp_fd, tcp_fd->tf_read_count, FALSE);
else
reply_thr_put (tcp_fd, EINTR, FALSE);
break;
case SR_CANCEL_IOCTL:
assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
type= tcp_fd->tf_ioreq & IOCTYPE_MASK;
switch (type)
{
case NWIOGTCPCONF & IOCTYPE_MASK:
reply_thr_put (tcp_fd, EINTR, TRUE);
break;
case NWIOSTCPCONF & IOCTYPE_MASK:
case NWIOTCPSHUTDOWN & IOCTYPE_MASK:
case NWIOTCPATTACH & IOCTYPE_MASK:
reply_thr_get (tcp_fd, EINTR, TRUE);
break;
case NWIOTCPCONN & IOCTYPE_MASK:
case NWIOTCPLISTEN & IOCTYPE_MASK:
assert (tcp_conn->tc_connuser == tcp_fd);
tcp_conn->tc_connuser= 0;
tcp_conn->tc_mainuser= 0;
tcp_close_connection(tcp_conn, ENOCONN);
reply_thr_get (tcp_fd, EINTR, TRUE);
break;
default:
ip_warning(( "unknown ioctl inprogress: 0x%x",
tcp_fd->tf_ioreq ));
reply_thr_get (tcp_fd, EINTR, TRUE);
break;
}
break;
default:
ip_panic(( "unknown cancel request" ));
break;
}
return NW_OK;
}
/*
tcp_connect
*/
PRIVATE int tcp_connect(tcp_fd)
tcp_fd_t *tcp_fd;
{
tcp_conn_t *tcp_conn;
int state;
if (!(tcp_fd->tf_flags & TFF_OPTSET))
{
#if DEBUG
{ where(); }
#endif
tcp_reply_ioctl(tcp_fd, EBADMODE);
return NW_OK;
}
if (tcp_fd->tf_flags & TFF_CONNECT)
{
tcp_reply_ioctl(tcp_fd, EISCONN);
return NW_OK;
}
if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
!= (NWTC_SET_RA|NWTC_SET_RP))
{
#if DEBUG
{ where(); printf("tcp_fd_table[%d].tf_tcpconf.nwtc_flags= 0x%x\n",
tcp_fd-tcp_fd_table, tcp_fd->tf_tcpconf.nwtc_flags); }
#endif
tcp_reply_ioctl(tcp_fd, EBADMODE);
return NW_OK;
}
assert(!tcp_fd->tf_conn);
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_mainuser)
{
tcp_reply_ioctl(tcp_fd, EADDRINUSE);
return NW_OK;
}
}
else
{
tcp_conn= find_empty_conn();
if (!tcp_conn)
{
tcp_reply_ioctl(tcp_fd, EAGAIN);
return NW_OK;
}
}
tcp_fd->tf_conn= tcp_conn;
return tcp_su4connect(tcp_fd);
}
/*
tcp_su4connect
*/
PRIVATE int tcp_su4connect(tcp_fd)
tcp_fd_t *tcp_fd;
{
tcp_conn_t *tcp_conn;
acc_t *tmp_acc;
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_conn->tc_mainuser= tcp_fd;
tcp_setup_conn(tcp_conn);
tcp_conn->tc_port= tcp_fd->tf_port;
tcp_conn->tc_connuser= tcp_fd;
#if DEBUG & 256
{ where(); printf("tcp_conn_table[%d].tc_connuser= 0x%x\n", tcp_conn-
tcp_conn_table, tcp_conn->tc_connuser); }
#endif
tcp_conn->tc_orglisten= FALSE;
tcp_conn->tc_state= TCS_SYN_SENT;
#if DEBUG & 16
{ where(); tcp_write_state(tcp_conn); }
#endif
tcp_restart_write (tcp_conn);
if (tcp_conn->tc_connuser)
return NW_SUSPEND;
else
return NW_OK;
}
PRIVATE void close_mainuser(tcp_conn, tcp_fd)
tcp_conn_t *tcp_conn;
tcp_fd_t *tcp_fd;
{
int i;
if (tcp_conn->tc_mainuser != tcp_fd)
return;
tcp_conn->tc_mainuser= 0;
assert (tcp_conn->tc_writeuser != tcp_fd);
assert (tcp_conn->tc_readuser != tcp_fd);
assert (tcp_conn->tc_connuser != tcp_fd);
for (i= 0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++, tcp_fd++)
{
if (!(tcp_fd->tf_flags & TFF_INUSE))
continue;
if (tcp_fd->tf_conn != tcp_conn)
continue;
tcp_conn->tc_mainuser= tcp_fd;
return;
}
}
PRIVATE int conn_right4fd(tcp_conn, tcp_fd)
tcp_fd_t *tcp_fd;
tcp_conn_t *tcp_conn;
{
unsigned long flags;
flags= tcp_fd->tf_tcpconf.nwtc_flags;
if (tcp_fd->tf_tcpconf.nwtc_locport != tcp_conn->tc_locport)
return FALSE;
if ((flags & NWTC_SET_RA) && tcp_fd->tf_tcpconf.nwtc_remaddr !=
tcp_conn->tc_remaddr)
return FALSE;
if ((flags & NWTC_SET_RP) && tcp_fd->tf_tcpconf.nwtc_remport !=
tcp_conn->tc_remport)
return FALSE;
if (tcp_fd->tf_port != tcp_conn->tc_port)
return FALSE;
return TRUE;
}
PRIVATE int tcp_attache(tcp_fd)
tcp_fd_t *tcp_fd;
{
tcp_conn_t *tcp_conn;
int state;
if (!(tcp_fd->tf_flags & TFF_OPTSET))
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EBADMODE, TRUE);
return NW_OK;
}
if (tcp_fd->tf_flags & TFF_CONNECT)
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EISCONN, TRUE);
return NW_OK;
}
if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
!= (NWTC_SET_RA|NWTC_SET_RP))
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EBADMODE, TRUE);
return NW_OK;
}
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 DEBUG
{ where(); printf("conn_entry not found\n"); }
#endif
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get (tcp_fd, ENOCONN, TRUE);
return NW_OK;
}
assert (tcp_conn->tc_flags & TCF_INUSE);
state= tcp_conn->tc_state;
if (state == TCS_CLOSED || state == TCS_LISTEN || state ==
TCS_SYN_SENT || state == TCS_SYN_RECEIVED)
{
#if DEBUG
{ where(); printf("conn_entry in wrong state: ");
tcp_write_state(tcp_conn); printf("\n"); }
#endif
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get (tcp_fd, ENOCONN, TRUE);
return NW_OK;
}
tcp_fd->tf_conn= tcp_conn;
tcp_fd->tf_flags |= TFF_CONNECTED;
tcp_fd->tf_flags |= TFF_PUSH_DATA; /* XXX */
return NW_OK;
}
/*
tcp_listen
*/
PRIVATE int tcp_listen(tcp_fd)
tcp_fd_t *tcp_fd;
{
tcp_conn_t *tcp_conn;
int state;
#if DEBUG & 256
{ where(); printf("tcp_listen(&tcp_fd_table[%d]) called\n", tcp_fd-
tcp_fd_table); }
#endif
if (!(tcp_fd->tf_flags & TFF_OPTSET))
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EBADMODE, TRUE);
return NW_OK;
}
if (tcp_fd->tf_flags & TFF_CONNECT)
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EISCONN, TRUE);
return NW_OK;
}
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_mainuser)
{
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= 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;
#if DEBUG & 256
{ where(); printf("tcp_conn_table[%d].tc_connuser= 0x%x\n", tcp_conn-
tcp_conn_table, tcp_conn->tc_connuser); }
#endif
return tcp_su4listen(tcp_fd);
}
PRIVATE void tcp_buffree (priority, reqsize)
int priority;
size_t reqsize;
{
int i;
tcp_conn_t *tcp_conn;
if (priority <TCP_PRI_FRAG2SEND)
return;
#if DEBUG & 256
{ where(); printf("tcp_buffree called\n"); }
#endif
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;
bf_afree(tcp_conn->tc_frag2send);
tcp_conn->tc_frag2send= 0;
if (bf_free_buffsize >= reqsize)
return;
}
if (priority <TCP_PRI_CONNwoUSER)
return;
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_mainuser)
continue;
if (tcp_conn->tc_state == TCS_CLOSED)
continue;
#if DEBUG
{ where(); printf("calling tcp_close_connection (out of memory)\n"); }
#endif
tcp_close_connection (tcp_conn, EOUTOFBUFS);
if (bf_free_buffsize >= reqsize)
return;
}
if (priority <TCP_PRI_CONN_INUSE)
return;
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_state == TCS_CLOSED)
continue;
#if DEBUG
{ where(); printf("calling tcp_close_connection (out of memory)\n"); }
#endif
tcp_close_connection (tcp_conn, EOUTOFBUFS);
if (bf_free_buffsize >= reqsize)
return;
}
}
PRIVATE void tcp_notreach(pack)
acc_t *pack;
{
acc_t *tcp_pack;
ip_hdr_t *ip_hdr;
tcp_hdr_t *tcp_hdr;
tcp_conn_t *tcp_conn;
int ip_hdr_size;
int new_ttl;
pack->acc_linkC++;
pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
ip_hdr_size= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
tcp_pack= bf_cut(pack, ip_hdr_size, TCP_MIN_HDR_SIZE);
tcp_pack= bf_packIffLess(tcp_pack, TCP_MIN_HDR_SIZE);
tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack);
tcp_conn= find_conn_entry( tcp_hdr->th_srcport, ip_hdr->ih_src,
tcp_hdr->th_dstport, ip_hdr->ih_dst);
if (tcp_conn)
{
new_ttl= tcp_conn->tc_ttl;
if (new_ttl == IP_MAX_TTL)
{
#if DEBUG
{ where(); printf("calling tcp_close_connection\n"); }
#endif
tcp_close_connection(tcp_conn, EDSTNOTRCH);
bf_afree(pack);
bf_afree(tcp_pack);
return;
}
new_ttl *= 2;
if (new_ttl> IP_MAX_TTL)
new_ttl= IP_MAX_TTL;
tcp_conn->tc_ttl= new_ttl;
tcp_conn->tc_no_retrans= 0;
}
else
{
#if DEBUG
{ where(); printf("got a EDSTNOTRCH for non existing connection\n"); }
#endif
}
bf_afree(pack);
bf_afree(tcp_pack);
}
/*
tcp_setup_conn
*/
PRIVATE void tcp_setup_conn(tcp_conn)
tcp_conn_t *tcp_conn;
{
assert(!tcp_conn->tc_readuser);
assert(!tcp_conn->tc_writeuser);
assert(!tcp_conn->tc_connuser);
if (tcp_conn->tc_flags & TCF_INUSE)
{
assert (tcp_conn->tc_state == TCS_CLOSED ||
tcp_conn->tc_state == TCS_TIME_WAIT);
assert (!tcp_conn->tc_send_data);
if (tcp_conn->tc_senddis < get_time())
tcp_conn->tc_ISS= 0;
}
else
{
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_WND_SIZE;
tcp_conn->tc_urg_wnd= TCP_DEF_URG_WND;
}
if (!tcp_conn->tc_ISS)
{
tcp_conn->tc_ISS= (get_time()/HZ)*ISS_INC_FREQ;
}
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;
tcp_conn->tc_SND_WL2= tcp_conn->tc_ISS;
tcp_conn->tc_IRS= 0;
tcp_conn->tc_SND_WL1= tcp_conn->tc_IRS;
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;
tcp_conn->tc_rcvd_data= 0;
tcp_conn->tc_rcv_queue= 0;
tcp_conn->tc_send_data= 0;
tcp_conn->tc_remipopt= 0;
tcp_conn->tc_remtcpopt= 0;
tcp_conn->tc_frag2send= 0;
tcp_conn->tc_no_retrans= 0;
tcp_conn->tc_max_no_retrans= TCP_DEF_MAX_NO_RETRANS;
tcp_conn->tc_0wnd_to= 0;
tcp_conn->tc_rtt= TCP_DEF_RTT;
tcp_conn->tc_ett= 0;
tcp_conn->tc_mss= TCP_DEF_MSS;
tcp_conn->tc_error= NW_OK;
tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + tcp_conn->tc_mss;
tcp_conn->tc_snd_cthresh= TCP_MAX_WND_SIZE;
tcp_conn->tc_snd_cinc= 0;
tcp_conn->tc_snd_wnd= TCP_MAX_WND_SIZE;
tcp_conn->tc_flags= TCF_INUSE;
#if DEBUG & 256
{ where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n",
tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -