📄 tcp.c
字号:
break;
}
result= tcp_setconf(tcp_fd);
break;
case NWIOGTCPCONF & IOCTYPE_MASK:
if (req != NWIOGTCPCONF)
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_put (tcp_fd, EBADIOCTL, TRUE);
result= NW_OK;
break;
}
conf_acc= bf_memreq(sizeof(*tcp_conf));
assert (conf_acc->acc_length == sizeof(*tcp_conf));
tcp_conf= (nwio_tcpconf_t *)ptr2acc_data(conf_acc);
*tcp_conf= tcp_fd->tf_tcpconf;
if (tcp_fd->tf_flags & TFF_CONNECTED)
{
tcp_conn= tcp_fd->tf_conn;
tcp_conf->nwtc_locport= tcp_conn->tc_locport;
tcp_conf->nwtc_remaddr= tcp_conn->tc_remaddr;
tcp_conf->nwtc_remport= tcp_conn->tc_remport;
}
tcp_conf->nwtc_locaddr= tcp_fd->tf_port->tp_ipaddr;
result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd,
0, conf_acc, TRUE);
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_put(tcp_fd, result, TRUE);
result= NW_OK;
break;
case NWIOTCPCONN & IOCTYPE_MASK:
if (req != NWIOTCPCONN)
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get (tcp_fd, EBADIOCTL, TRUE);
result= NW_OK;
break;
}
if (tcp_fd->tf_flags & TFF_CONNECTED)
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get (tcp_fd, EISCONN, TRUE);
result= NW_OK;
break;
}
result= tcp_connect(tcp_fd);
break;
case NWIOTCPLISTEN & IOCTYPE_MASK:
if (req != NWIOTCPLISTEN)
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get (tcp_fd, EBADIOCTL, TRUE);
result= NW_OK;
break;
}
if (tcp_fd->tf_flags & TFF_CONNECTED)
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get (tcp_fd, EISCONN, TRUE);
result= NW_OK;
break;
}
result= tcp_listen(tcp_fd);
#if DEBUG & 256
{ where(); printf("tcp_listen= %d\n", result); }
#endif
break;
#if 0
case NWIOTCPATTACH & IOCTYPE_MASK:
if (req != NWIOTCPATTACH)
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get (tcp_fd, EBADIOCTL, TRUE);
result= NW_OK;
break;
}
if (tcp_fd->tf_flags & TFF_CONNECTED)
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get (tcp_fd, EISCONN, TRUE);
result= NW_OK;
break;
}
result= tcp_attache(tcp_fd);
break;
#endif
case NWIOTCPSHUTDOWN & IOCTYPE_MASK:
if (req != NWIOTCPSHUTDOWN)
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get (tcp_fd, EBADIOCTL, TRUE);
result= NW_OK;
break;
}
if (!(tcp_fd->tf_flags & TFF_CONNECTED))
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get (tcp_fd, ENOTCONN, TRUE);
result= NW_OK;
break;
}
tcp_fd->tf_flags |= TFF_IOCTL_IP;
tcp_fd->tf_ioreq= req;
tcp_conn= tcp_fd->tf_conn;
if (tcp_conn->tc_writeuser)
return NW_SUSPEND;
tcp_conn->tc_writeuser= tcp_fd;
tcp_restart_fd_write (tcp_conn);
if (!(tcp_fd->tf_flags & TFF_IOCTL_IP))
return NW_OK;
else
return NW_SUSPEND;
break;
default:
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EBADIOCTL, TRUE);
result= NW_OK;
break;
}
return result;
}
PRIVATE int tcp_setconf(tcp_fd)
tcp_fd_t *tcp_fd;
{
nwio_tcpconf_t *tcpconf;
nwio_tcpconf_t oldconf, newconf;
acc_t *data;
int result;
tcpport_t port;
tcp_fd_t *fd_ptr;
unsigned int new_en_flags, new_di_flags,
old_en_flags, old_di_flags, all_flags, flags;
int i;
data= (*tcp_fd->tf_get_userdata)
(tcp_fd->tf_srfd, 0,
sizeof(nwio_tcpconf_t), TRUE);
if (!data)
return EFAULT;
data= bf_packIffLess(data, sizeof(nwio_tcpconf_t));
assert (data->acc_length == sizeof(nwio_tcpconf_t));
tcpconf= (nwio_tcpconf_t *)ptr2acc_data(data);
oldconf= tcp_fd->tf_tcpconf;
newconf= *tcpconf;
old_en_flags= oldconf.nwtc_flags & 0xffff;
old_di_flags= (oldconf.nwtc_flags >> 16) &
0xffff;
new_en_flags= newconf.nwtc_flags & 0xffff;
new_di_flags= (newconf.nwtc_flags >> 16) &
0xffff;
if (new_en_flags & new_di_flags)
{
#if DEBUG
{ where(); printf("bad ioctl\n"); }
#endif
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EBADMODE, TRUE);
return NW_OK;
}
/* NWTC_ACC_MASK */
if (new_di_flags & NWTC_ACC_MASK)
{
#if DEBUG
{ where(); printf("bad ioctl\n"); }
#endif
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EBADMODE, TRUE);
return NW_OK;
/* access modes can't be disabled */
}
if (!(new_en_flags & NWTC_ACC_MASK))
new_en_flags |= (old_en_flags & NWTC_ACC_MASK);
/* NWTC_LOCPORT_MASK */
if (new_di_flags & NWTC_LOCPORT_MASK)
{
#if DEBUG
{ where(); printf("bad ioctl\n"); }
#endif
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EBADMODE, TRUE);
return NW_OK;
/* the loc ports can't be disabled */
}
if (!(new_en_flags & NWTC_LOCPORT_MASK))
{
new_en_flags |= (old_en_flags &
NWTC_LOCPORT_MASK);
#if DEBUG
{ where(); printf("locport= old locport (=%u)\n",
ntohs(newconf.nwtc_locport)); }
#endif
newconf.nwtc_locport= oldconf.nwtc_locport;
}
else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL)
{
newconf.nwtc_locport= find_unused_port(tcp_fd-
tcp_fd_table);
#if DEBUG & 256
{ where(); printf("locport selected (=%u)\n",
ntohs(newconf.nwtc_locport)); }
#endif
}
else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET)
{
#if DEBUG & 256
{ where(); printf("locport set (=%u)\n",
ntohs(newconf.nwtc_locport)); }
#endif
if (!newconf.nwtc_locport)
{
#if DEBUG
{ where(); printf("bad ioctl\n"); }
#endif
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EBADMODE, TRUE);
return NW_OK;
}
}
/* NWTC_REMADDR_MASK */
if (!((new_en_flags | new_di_flags) &
NWTC_REMADDR_MASK))
{
new_en_flags |= (old_en_flags &
NWTC_REMADDR_MASK);
new_di_flags |= (old_di_flags &
NWTC_REMADDR_MASK);
newconf.nwtc_remaddr= oldconf.nwtc_remaddr;
}
else if (new_en_flags & NWTC_SET_RA)
{
if (!newconf.nwtc_remaddr)
{
#if DEBUG
{ where(); printf("bad ioctl\n"); }
#endif
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EBADMODE, TRUE);
return NW_OK;
}
}
else
{
assert (new_di_flags & NWTC_REMADDR_MASK);
newconf.nwtc_remaddr= 0;
}
/* NWTC_REMPORT_MASK */
if (!((new_en_flags | new_di_flags) & NWTC_REMPORT_MASK))
{
new_en_flags |= (old_en_flags &
NWTC_REMPORT_MASK);
new_di_flags |= (old_di_flags &
NWTC_REMPORT_MASK);
newconf.nwtc_remport=
oldconf.nwtc_remport;
}
else if (new_en_flags & NWTC_SET_RP)
{
if (!newconf.nwtc_remport)
{
#if DEBUG
{ where(); printf("bad ioctl\n"); }
#endif
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EBADMODE, TRUE);
return NW_OK;
}
}
else
{
assert (new_di_flags & NWTC_REMPORT_MASK);
newconf.nwtc_remport= 0;
}
newconf.nwtc_flags= ((unsigned long)new_di_flags
<< 16) | new_en_flags;
all_flags= new_en_flags | new_di_flags;
/* Let's check the access modes */
if ((all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL ||
(all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET)
{
for (i=0, fd_ptr= tcp_fd_table; i<TCP_FD_NR; i++, fd_ptr++)
{
if (fd_ptr == tcp_fd)
continue;
if (!(fd_ptr->tf_flags & TFF_INUSE))
continue;
flags= fd_ptr->tf_tcpconf.nwtc_flags;
if ((flags & NWTC_LOCPORT_MASK) != NWTC_LP_SEL &&
(flags & NWTC_LOCPORT_MASK) != NWTC_LP_SET)
continue;
if (fd_ptr->tf_tcpconf.nwtc_locport !=
newconf.nwtc_locport)
continue;
if ((flags & NWTC_ACC_MASK) != (all_flags &
NWTC_ACC_MASK))
{
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, EADDRINUSE, TRUE);
return NW_OK;
}
}
}
tcp_fd->tf_tcpconf= newconf;
if ((all_flags & NWTC_ACC_MASK) &&
((all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET ||
(all_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SEL) &&
(all_flags & NWTC_REMADDR_MASK) &&
(all_flags & NWTC_REMPORT_MASK))
tcp_fd->tf_flags |= TFF_OPTSET;
else
{
#if DEBUG
{ where();
if (!(all_flags & NWTC_ACC_MASK)) printf("NWTC_ACC_MASK not set ");
if (!(all_flags & (NWTC_LP_SET|NWTC_LP_SEL)))
printf("local port not set ");
if (!(all_flags & NWTC_REMADDR_MASK))
printf("NWTC_REMADDR_MASK not set ");
if (!(all_flags & NWTC_REMPORT_MASK))
printf("NWTC_REMPORT_MASK not set "); }
#endif
tcp_fd->tf_flags &= ~TFF_OPTSET;
}
bf_afree(data);
tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
reply_thr_get(tcp_fd, NW_OK, TRUE);
return NW_OK;
}
PRIVATE tcpport_t find_unused_port(fd)
int fd;
{
tcpport_t port, nw_port;
for (port= 0x8000; port < 0xffff-TCP_FD_NR; port+= TCP_FD_NR)
{
nw_port= htons(port);
if (is_unused_port(nw_port))
return nw_port;
}
for (port= 0x8000; port < 0xffff; port++)
{
nw_port= htons(port);
if (is_unused_port(nw_port))
return nw_port;
}
ip_panic(( "unable to find unused port (shouldn't occur)" ));
return 0;
}
PRIVATE int is_unused_port(port)
tcpport_t port;
{
int i;
tcp_fd_t *tcp_fd;
tcp_conn_t *tcp_conn;
for (i= 0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++,
tcp_fd++)
{
if (!(tcp_fd->tf_flags & TFF_OPTSET))
continue;
if (tcp_fd->tf_tcpconf.nwtc_locport == port)
return FALSE;
}
for (i= TCP_PORT_NR, tcp_conn= tcp_conn_table+i;
i<TCP_CONN_NR; i++, tcp_conn++)
/* the first TCP_PORT_NR ports are special */
{
if (!(tcp_conn->tc_flags & TCF_INUSE))
continue;
if (tcp_conn->tc_locport == port)
return FALSE;
}
return TRUE;
}
PRIVATE int reply_thr_put(tcp_fd, reply, for_ioctl)
tcp_fd_t *tcp_fd;
int reply;
int for_ioctl;
{
#if DEBUG & 256
{ where(); printf("reply_thr_put(..) called\n"); }
#endif
#if DEBUG & 256
{ where(); printf("calling 0x%x\n", tcp_fd->tf_put_userdata); }
#endif
assert (tcp_fd);
return (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd, reply,
(acc_t *)0, for_ioctl);
}
PRIVATE void reply_thr_get(tcp_fd, reply, for_ioctl)
tcp_fd_t *tcp_fd;
int reply;
int for_ioctl;
{
acc_t *result;
#if DEBUG & 256
{ where(); printf("reply_thr_get(..) called\n"); }
#endif
result= (*tcp_fd->tf_get_userdata)(tcp_fd->tf_srfd, reply,
(size_t)0, for_ioctl);
assert (!result);
}
PUBLIC int tcp_su4listen(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;
if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP)
tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;
else
tcp_conn->tc_remport= 0;
if (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA)
tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;
else
tcp_conn->tc_remaddr= 0;
tcp_setup_conn(tcp_conn);
tcp_conn->tc_port= tcp_fd->tf_port;
tcp_conn->tc_mainuser= tcp_fd;
tcp_conn->tc_connuser= tcp_fd;
tcp_conn->tc_orglisten= TRUE;
tcp_conn->tc_state= TCS_LISTEN;
#if DEBUG & 2
{ where(); tcp_write_state(tcp_conn); }
#endif
return NW_SUSPEND;
}
/*
find_empty_conn
This function returns a connection that is not inuse.
This includes connections that are never used, and connection without a
user that are not used for a while.
*/
PRIVATE tcp_conn_t *find_empty_conn()
{
int i;
tcp_conn_t *tcp_conn;
int state;
for (i=TCP_PORT_NR, tcp_conn= tcp_conn_table+i;
i<TCP_CONN_NR; i++, tcp_conn++)
/* the first TCP_PORT_NR connection are reserved for
RSTs */
{
if (tcp_conn->tc_flags == TCF_EMPTY)
{
tcp_conn->tc_connuser= NULL;
tcp_conn->tc_mainuser= NULL;
return tcp_conn;
}
if (tcp_conn->tc_mainuser)
continue;
if (tcp_conn->tc_senddis > get_time())
continue;
if (tcp_conn->tc_state != TCS_CLOSED)
{
#if DEBUG
{ where(); printf("calling tcp_close_connection\n"); }
#endif
tcp_close_connection (tcp_conn, ENOCONN);
}
return tcp_conn;
}
return NULL;
}
/*
find_conn_entry
This function return a connection matching locport, locaddr, remport, remaddr.
If no such connection exists NULL is returned.
If a connection exists without mainuser it is closed.
*/
PRIVATE tcp_conn_t *find_conn_entry(locport, locaddr, remport, remaddr)
tcpport_t locport;
ipaddr_t locaddr;
tcpport_t remport;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -