📄 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); }#endifassert (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_connThis function returns a connection that is not inuse.This includes connections that are never used, and connection without auser 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_entryThis 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 + -