📄 tcp.c
字号:
i<TCP_CONN_NR; i++, tcp_conn++) { if (!(tcp_conn->tc_flags & TCF_INUSE)) continue; if (tcp_conn->tc_port != tcp_port) continue; tcp_conn->tc_locaddr= ipaddr; } } else DBLOCK(1, printf("tcp_put_pkt: no TCP header\n")); bf_afree(data); return; } data->acc_linkC++; ip_pack= data; ip_pack= bf_align(ip_pack, ip_hdr_len, 4); ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack); data= bf_delhead(data, ip_hdr_len); /* Compute the checksum */ sum= tcp_pack_oneCsum(ip_hdr, data); /* Extract the TCP header */ if (ip_datalen < TCP_MIN_HDR_SIZE) { DBLOCK(1, printf("truncated TCP header\n")); bf_afree(ip_pack); bf_afree(data); return; } data= bf_packIffLess(data, TCP_MIN_HDR_SIZE); tcp_hdr= (tcp_hdr_t *)ptr2acc_data(data); tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2; /* actualy (>> 4) << 2 */ if (ip_datalen < tcp_hdr_len || tcp_hdr_len < TCP_MIN_HDR_SIZE) { if (tcp_hdr_len < TCP_MIN_HDR_SIZE) { DBLOCK(1, printf("strange tcp header length %d\n", tcp_hdr_len)); } else { DBLOCK(1, printf("truncated TCP header\n")); } bf_afree(ip_pack); bf_afree(data); return; } data->acc_linkC++; tcp_pack= data; tcp_pack= bf_align(tcp_pack, tcp_hdr_len, 4); tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack); if (ip_datalen == tcp_hdr_len) { bf_afree(data); data= NULL; } else data= bf_delhead(data, tcp_hdr_len); tcp_datalen= ip_datalen-tcp_hdr_len; if ((u16_t)~sum) { DBLOCK(1, printf("checksum error in tcp packet\n"); printf("tcp_pack_oneCsum(...)= 0x%x length= %d\n", (u16_t)~sum, tcp_datalen); printf("src ip_addr= "); writeIpAddr(ip_hdr->ih_src); printf("\n")); bf_afree(ip_pack); bf_afree(tcp_pack); bf_afree(data); return; } srcaddr= ip_hdr->ih_src; dstaddr= ip_hdr->ih_dst; srcport= tcp_hdr->th_srcport; dstport= tcp_hdr->th_dstport; bits= srcaddr ^ dstaddr ^ srcport ^ dstport; bits= (bits >> 16) ^ bits; bits= (bits >> 8) ^ bits; hash= ((bits >> TCP_CONN_HASH_SHIFT) ^ bits) & (TCP_CONN_HASH_NR-1); conn_p= tcp_port->tp_conn_hash[hash]; if (conn_p[0]->tc_locport == dstport && conn_p[0]->tc_remport == srcport && conn_p[0]->tc_remaddr == srcaddr && conn_p[0]->tc_locaddr == dstaddr) { tcp_conn= conn_p[0]; } else if (conn_p[1]->tc_locport == dstport && conn_p[1]->tc_remport == srcport && conn_p[1]->tc_remaddr == srcaddr && conn_p[1]->tc_locaddr == dstaddr) { tcp_conn= conn_p[1]; conn_p[1]= conn_p[0]; conn_p[0]= tcp_conn; } else if (conn_p[2]->tc_locport == dstport && conn_p[2]->tc_remport == srcport && conn_p[2]->tc_remaddr == srcaddr && conn_p[2]->tc_locaddr == dstaddr) { tcp_conn= conn_p[2]; conn_p[2]= conn_p[1]; conn_p[1]= conn_p[0]; conn_p[0]= tcp_conn; } else if (conn_p[3]->tc_locport == dstport && conn_p[3]->tc_remport == srcport && conn_p[3]->tc_remaddr == srcaddr && conn_p[3]->tc_locaddr == dstaddr) { tcp_conn= conn_p[3]; conn_p[3]= conn_p[2]; conn_p[2]= conn_p[1]; conn_p[1]= conn_p[0]; conn_p[0]= tcp_conn; } else tcp_conn= NULL; if ((tcp_conn != NULL && tcp_conn->tc_state == TCS_CLOSED) || (tcp_hdr->th_flags & THF_SYN)) { tcp_conn= NULL; } if (tcp_conn == NULL) { tcp_conn= find_best_conn(ip_hdr, tcp_hdr); if (!tcp_conn) { /* listen backlog hack */ bf_afree(ip_pack); bf_afree(tcp_pack); bf_afree(data); return; } if (tcp_conn->tc_state != TCS_CLOSED) { conn_p[3]= conn_p[2]; conn_p[2]= conn_p[1]; conn_p[1]= conn_p[0]; conn_p[0]= tcp_conn; } } assert(tcp_conn->tc_busy == 0); tcp_conn->tc_busy++; tcp_frag2conn(tcp_conn, ip_hdr, tcp_hdr, data, tcp_datalen); tcp_conn->tc_busy--; bf_afree(ip_pack); bf_afree(tcp_pack);}PUBLIC int tcp_open (port, srfd, get_userdata, put_userdata, put_pkt, select_res)int port;int srfd;get_userdata_t get_userdata;put_userdata_t put_userdata;put_pkt_t put_pkt;select_res_t select_res;{ int i, j; tcp_fd_t *tcp_fd; for (i=0; i<TCP_FD_NR && (tcp_fd_table[i].tf_flags & TFF_INUSE); i++); if (i>=TCP_FD_NR) { return EAGAIN; } tcp_fd= &tcp_fd_table[i]; tcp_fd->tf_flags= TFF_INUSE; tcp_fd->tf_flags |= TFF_PUSH_DATA; tcp_fd->tf_port= &tcp_port_table[port]; tcp_fd->tf_srfd= srfd; tcp_fd->tf_tcpconf.nwtc_flags= TCP_DEF_CONF; tcp_fd->tf_tcpconf.nwtc_remaddr= 0; tcp_fd->tf_tcpconf.nwtc_remport= 0; tcp_fd->tf_tcpopt.nwto_flags= TCP_DEF_OPT; tcp_fd->tf_get_userdata= get_userdata; tcp_fd->tf_put_userdata= put_userdata; tcp_fd->tf_select_res= select_res; tcp_fd->tf_conn= 0; for (j= 0; j<TFL_LISTEN_MAX; j++) tcp_fd->tf_listenq[j]= NULL; return i;}/*tcp_ioctl*/PUBLIC int tcp_ioctl (fd, req)int fd;ioreq_t req;{ tcp_fd_t *tcp_fd; tcp_port_t *tcp_port; tcp_conn_t *tcp_conn; nwio_tcpconf_t *tcp_conf; nwio_tcpopt_t *tcp_opt; tcp_cookie_t *cookiep; acc_t *acc, *conf_acc, *opt_acc; int result, *bytesp; u8_t rndbits[RAND256_BUFSIZE]; tcp_fd= &tcp_fd_table[fd]; assert (tcp_fd->tf_flags & TFF_INUSE); tcp_port= tcp_fd->tf_port; tcp_fd->tf_flags |= TFF_IOCTL_IP; tcp_fd->tf_ioreq= req; if (tcp_port->tp_state != TPS_MAIN) { tcp_fd->tf_flags |= TFF_IOC_INIT_SP; return NW_SUSPEND; } switch (req) { case NWIOSTCPCONF: if ((tcp_fd->tf_flags & TFF_CONNECTEDx) || (tcp_fd->tf_flags & TFF_CONNECTING) || (tcp_fd->tf_flags & TFF_LISTENQ)) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, EISCONN, TRUE); result= NW_OK; break; } result= tcp_setconf(tcp_fd); break; case NWIOGTCPCONF: 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_CONNECTEDx) { 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 NWIOSTCPOPT: result= tcp_setopt(tcp_fd); break; case NWIOGTCPOPT: opt_acc= bf_memreq(sizeof(*tcp_opt)); assert (opt_acc->acc_length == sizeof(*tcp_opt)); tcp_opt= (nwio_tcpopt_t *)ptr2acc_data(opt_acc); *tcp_opt= tcp_fd->tf_tcpopt; result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd, 0, opt_acc, TRUE); tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_put(tcp_fd, result, TRUE); result= NW_OK; break; case NWIOTCPCONN: if (tcp_fd->tf_flags & TFF_CONNECTING) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, EALREADY, TRUE); result= NW_OK; break; } if (tcp_fd->tf_flags & TFF_CONNECTEDx) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, EISCONN, TRUE); result= NW_OK; break; } result= tcp_connect(tcp_fd); if (result == NW_OK) tcp_fd->tf_flags &= ~TFF_IOCTL_IP; break; case NWIOTCPLISTEN: case NWIOTCPLISTENQ: if ((tcp_fd->tf_flags & TFF_CONNECTEDx) || (tcp_fd->tf_flags & TFF_LISTENQ) || (tcp_fd->tf_flags & TFF_CONNECTING)) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, EISCONN, TRUE); result= NW_OK; break; } result= tcp_listen(tcp_fd, (req == NWIOTCPLISTENQ)); break; case NWIOTCPSHUTDOWN: if (!(tcp_fd->tf_flags & TFF_CONNECTEDx)) { 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; tcp_conn->tc_busy++; tcp_fd_write(tcp_conn); tcp_conn->tc_busy--; tcp_conn_write(tcp_conn, 0); if (!(tcp_fd->tf_flags & TFF_IOCTL_IP)) result= NW_OK; else result= NW_SUSPEND; break; case NWIOTCPPUSH: if (!(tcp_fd->tf_flags & TFF_CONNECTEDx)) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, ENOTCONN, TRUE); result= NW_OK; break; } tcp_conn= tcp_fd->tf_conn; tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT; tcp_conn->tc_flags &= ~TCF_NO_PUSH; tcp_conn->tc_flags |= TCF_PUSH_NOW; /* Start the timer (if necessary) */ if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_UNA) tcp_set_send_timer(tcp_conn); tcp_conn_write(tcp_conn, 0); tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, NW_OK, TRUE); result= NW_OK; break; case NWIOGTCPCOOKIE: if (!(tcp_fd->tf_flags & TFF_COOKIE)) { tcp_fd->tf_cookie.tc_ref= fd; rand256(rndbits); assert(sizeof(tcp_fd->tf_cookie.tc_secret) <= RAND256_BUFSIZE); memcpy(tcp_fd->tf_cookie.tc_secret, rndbits, sizeof(tcp_fd->tf_cookie.tc_secret)); tcp_fd->tf_flags |= TFF_COOKIE; } acc= bf_memreq(sizeof(*cookiep)); cookiep= (tcp_cookie_t *)ptr2acc_data(acc); *cookiep= tcp_fd->tf_cookie; result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd, 0, acc, TRUE); tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_put(tcp_fd, result, TRUE); result= NW_OK; break; case NWIOTCPACCEPTTO: result= tcp_acceptto(tcp_fd); break; case FIONREAD: acc= bf_memreq(sizeof(*bytesp)); bytesp= (int *)ptr2acc_data(acc); tcp_bytesavailable(tcp_fd, bytesp); result= (*tcp_fd->tf_put_userdata)(tcp_fd->tf_srfd, 0, acc, TRUE); tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_put(tcp_fd, result, TRUE); result= NW_OK; break; default: tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get(tcp_fd, EBADIOCTL, TRUE); result= NW_OK; break; } return result;}/*tcp_setconf*/PRIVATE int tcp_setconf(tcp_fd)tcp_fd_t *tcp_fd;{ nwio_tcpconf_t *tcpconf; nwio_tcpconf_t oldconf, newconf; acc_t *data; 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) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get(tcp_fd, EBADMODE, TRUE); bf_afree(data); return NW_OK; } /* NWTC_ACC_MASK */ if (new_di_flags & NWTC_ACC_MASK) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get(tcp_fd, EBADMODE, TRUE); bf_afree(data); 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) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get(tcp_fd, EBADMODE, TRUE); bf_afree(data); 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); 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); } else if ((new_en_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET) { if (!newconf.nwtc_locport) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get(tcp_fd, EBADMODE, TRUE); bf_afree(data); 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) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get(tcp_fd, EBADMODE, TRUE); bf_afree(data); 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) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get(tcp_fd, EBADMODE, TRUE); bf_afree(data); return NW_OK; } } else {assert (new_di_flags & NWTC_REMPORT_MASK); newconf.nwtc_remport= 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -