📄 tcp_usrreq.c
字号:
register struct mbuf *m; int s; inp = sotoinpcb(so); if (inp == NULL) { if (so->so_error) error = so->so_error; else error = ENOPROTOOPT; m = *mp; /* get ready to free it */ goto badcb; } tp = intotcpcb(inp); if (tp == NULL) { if (so->so_error) error = so->so_error; else error = ENOPROTOOPT; m = *mp; /* get ready to free it */ goto badcb; }#else int error = 0; struct inpcb *inp = sotoinpcb(so); register struct tcpcb *tp = intotcpcb(inp); register struct mbuf *m;#endif XTI if (level != IPPROTO_TCP) return (ip_ctloutput(op, so, level, optname, mp)); switch (op) { case PRCO_SETOPT: m = *mp; switch (optname) { case TCP_NODELAY: if (m == NULL || m->m_len < sizeof (int)) error = EINVAL; else if (*mtod(m, int *)) tp->t_flags |= TF_NODELAY; else tp->t_flags &= ~TF_NODELAY; break; case TCP_MAXSEG: /* not yet */ error = EINVAL; break;#ifdef XTI case TCP_CONOPT: { int tmp_var; char *src_ptr; char *dst_ptr; unsigned short calculate_mss; if (m == NULL || m->m_len < sizeof(struct tcp_options)) { error = EINVAL; break; } calculate_mss = MIN(so->so_rcv.sb_hiwat / 2, tcp_mss(tp)); PRINTXTID(64, ("calmss=%d\n",calculate_mss)); src_ptr = (char *) (mtod(m, struct tcp_options *)); dst_ptr = (char *) &tp->xti_neg_qos; /* * Only allow maximum segment size to be changed */ if (((struct tcp_options *)src_ptr)->max_seg_size <= calculate_mss) { tp->xti_neg_qos.max_seg_size = ((struct tcp_options *)src_ptr)->max_seg_size; }#ifdef undef tmp_var = bcmp((char *)(mtod(m, struct tcp_options *)), (char *) &tp->xti_neg_qos, sizeof(struct tcp_options));#endif tmp_var = cmp_xti_tcpopts( (char *)(mtod(m, struct tcp_options *)), (char *) &tp->xti_neg_qos); PRINTXTID(64, ("qos:prec,timeout,max_seg,sec,com,hand,ttc=%x %x %d %x %x % %x\n", tp->xti_neg_qos.precedence, tp->xti_neg_qos.timeout, tp->xti_neg_qos.max_seg_size, tp->xti_neg_qos.secopt.security, tp->xti_neg_qos.secopt.compartment, tp->xti_neg_qos.secopt.handling, tp->xti_neg_qos.secopt.tcc)); PRINTXTID(64, ("tqos:prec,timeout,max_seg,sec,com,hand,ttc=%x %x %d %x %x %x %x\n", ((struct tcp_options *)src_ptr)->precedence, ((struct tcp_options *)src_ptr)->timeout, ((struct tcp_options *)src_ptr)->max_seg_size, ((struct tcp_options *)src_ptr)->secopt.security, ((struct tcp_options *)src_ptr)->secopt.compartment, ((struct tcp_options *)src_ptr)->secopt.handling, ((struct tcp_options *)src_ptr)->secopt.tcc)); if (tmp_var) { error = EOPNOTSUPP; break; } break; } case TCP_NEGQOS: if (m == NULL || m->m_len < sizeof(struct tcp_options)) { error = EOPNOTSUPP; break; } tp->xti_tmpneg_qos = (*mtod(m, struct tcp_options *)); break; case TCP_CHKQOS: { int tmp_var; char *src_ptr; char *dst_ptr; if (m == NULL || m->m_len < sizeof(struct tcp_options)) { error = EINVAL; break; } src_ptr = (char *) (mtod(m, struct tcp_options *)); dst_ptr = (char *) &tp->xti_neg_qos;#ifdef undef tmp_var = bcmp((char *)(mtod(m, struct tcp_options *)), (char *) &tp->xti_neg_qos, sizeof(struct tcp_options));#endif tmp_var = cmp_xti_tcpopts( (char *)(mtod(m, struct tcp_options *)), (char *) &tp->xti_neg_qos); PRINTXTID(64, ("tmp_var = %d\n",tmp_var)); PRINTXTID(64, ("src = %x, dst = %x, size = %d\n", (char *)(mtod(m,struct tcp_options *)), (char *) &tp->xti_neg_qos, sizeof(struct tcp_options))); if (tmp_var) { error = EOPNOTSUPP; break; } break; } case TCP_CONACCEPT: tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); break; case TCP_ACCEPTMODE: /* enable/disable accept mode */ if (m == NULL || m->m_len < sizeof (int)) error = EINVAL; else tp->t_acceptmode = (*mtod(m, int *)); break; #endif XTI default: error = EINVAL; break; }#ifdef XTIbadcb:#endif XTI if(m) (void) m_free(m); break; case PRCO_GETOPT: *mp = m = m_get(M_DONTWAIT, MT_SOOPTS); /* SMP */ if (m == NULL) return(ENOBUFS); m->m_len = sizeof(int); switch (optname) { case TCP_NODELAY: *mtod(m, int *) = tp->t_flags & TF_NODELAY; break; case TCP_MAXSEG: *mtod(m, int *) = tp->t_maxseg; break;#ifdef XTI case TCP_CONOPT: m->m_len = sizeof(struct tcp_options); (*mtod(m, struct tcp_options *)) = tp->xti_inbound_qos; break; case TCP_NEGQOS: /* NEGOTIATION WOULD GO HERE.... * Currently only support * default values */ m->m_len = sizeof(struct tcp_options); (*mtod(m, struct tcp_options *)) = tp->xti_neg_qos; break; case TCP_DFLTQOS: m->m_len = sizeof(struct tcp_options); (*mtod(m, struct tcp_options *)) = tp->xti_tcp_defqos; break;#endif XTI default: error = EINVAL; break; } break;#ifdef XTI case PRCO_XTIMAPSTATE: so->so_xticb.xti_states = tcp_to_xtistate(so); break; case PRCO_XTIMAPINFO: so->so_xticb.xti_tpinfo = &xti_tcpinfo; /* info is per provider */ break; case PRCO_XTICHKADDR: { struct xti_accept_check { int resfd; /* resfd of t_accept */ int seqnum; /* sequence number of t_accept */ union { struct sockaddr generic; /* address info from t_accept */ } addr; } tmp_accept; struct sockaddr_in tmp_addr; struct inpcb *inp; struct sockaddr_in *adeb; m = *mp; /* get mbuf pointer */ tmp_accept = *mtod(m, struct xti_accept_check *); inp = sotoinpcb(so); tmp_addr.sin_family = so->so_proto->pr_domain->dom_family; tmp_addr.sin_port = inp->inp_fport; tmp_addr.sin_addr = inp->inp_faddr; bzero((char *) &tmp_addr.sin_zero[0], 8); /* char sin_zero[8] */ adeb = (struct sockaddr_in *) &tmp_accept.addr.generic; bzero((char *) &adeb->sin_zero[0], 8); /* char sin_zero[8] */ if (bcmp((char *)&tmp_accept.addr.generic, (char *)&tmp_addr, sizeof(struct sockaddr_in))) { return(EADDRNOTAVAIL); } break; } case PRCO_XTIREJECT: { tp = tcp_drop(tp, ECONNABORTED); break; } break; case PRCO_XTICOPYTP: { struct socket *new = 0; m = *mp; new = *mtod(m, struct socket **); sototcpcb(new)->t_acceptmode = sototcpcb(so)->t_acceptmode; sototcpcb(new)->xti_neg_qos = sototcpcb(so)->xti_neg_qos; sototcpcb(new)->xti_tmpneg_qos = sototcpcb(so)->xti_tmpneg_qos; sototcpcb(new)->xti_tcp_defqos = sototcpcb(so)->xti_tcp_defqos; break; } case PRCO_XTIUNBIND: { xtiin_pcbunbind(so->so_pcb); if (((struct inpcb *)(so->so_pcb))->inp_ppcb) tcp_closekeepinp(((struct inpcb *) (so->so_pcb))->inp_ppcb); tp = tcp_newtcpcb(inp); if (tp == 0) { int nofd = so->so_state & SS_NOFDREF; /* XXX */ so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ smp_lock(&lk_tcb, LK_RETRY); in_pcbdetach(inp); smp_unlock(&lk_tcb); so->so_state |= nofd; error = ENOBUFS; } break; }#endif XTI } return (error);}/* * Allow buffering of 16K of data. This trades off memory for fewer * acks by tcp. - lp */int tcp_sendspace = 1024*16;int tcp_recvspace = 1024*16;#ifdef XTIint tcp_exrecvspace = 16*1;#endif XTI/* * Attach TCP protocol to socket, allocating * internet protocol control block, tcp control block, * bufer space, and entering LISTEN state if to accept connections. * * SMP: Lock set coming in. 4.14.87.us */tcp_attach(so) struct socket *so;{ register struct tcpcb *tp; struct inpcb *inp; int error; int owner = 0; /* SMP */ error = soreserve(so, tcp_sendspace, tcp_recvspace); if (error) return (error);#ifdef XTI so->so_options |= SO_BUFFOOB; error = soexreserve(so, 0, tcp_exrecvspace); if (error) return (error);#endif XTI /* SMP: Lock queue going into in_pcballoc because can be * used for different queues. Bug fix 6.3.87.us */ /* SMP: Bug fix. 3.22.89.us. * The situation here is that tcp_attach can be called with one * socket locked (as in from socket()) OR with two sockets * locked (as in from sonewconn). Since the bug fix here * is to exchange the heirarchial positions of the lk_socket * and lk_tcb, we must unlock socket(s) before locking * lk_tcb. Therefore, we have the check to see if we * have only one or two sockets locked. */ if((smp) && (so->so_head) && (smp_owner(&so->so_head->lk_socket) == 1)){ owner = 1; so->so_head->ref = 29; smp_unlock(&so->so_head->lk_socket); } if (smp){ so->ref = 14; smp_unlock(&so->lk_socket); smp_lock(&lk_tcb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; if (owner){ smp_lock(&so->so_head->lk_socket, LK_RETRY); owner = 0; so->so_head->ref = 0; } error = in_pcballoc(so, &tcb); smp_unlock(&lk_tcb); }else error = in_pcballoc(so, &tcb); if (error) return (error); inp = sotoinpcb(so); tp = tcp_newtcpcb(inp); if (tp == 0) { int nofd = so->so_state & SS_NOFDREF; /* XXX */ so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ if (smp){ so->ref = 14; smp_unlock(&so->lk_socket); smp_lock(&lk_tcb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; in_pcbdetach(inp); smp_unlock(&lk_tcb); so->so_state |= nofd; }else in_pcbdetach(inp); return (ENOBUFS); } tp->t_state = TCPS_CLOSED; return (0);}/* * Initiate (or continue) disconnect. * If embryonic state, just send reset (once). * If in ``let data drain'' option and linger null, just drop. * Otherwise (hard), mark socket disconnecting and drop * current input data; switch states based on user close, and * send segment to peer (with FIN). */struct tcpcb *tcp_disconnect(tp) register struct tcpcb *tp;{ struct socket *so = tp->t_inpcb->inp_socket; if (smp_debug){ if (smp_owner(&so->lk_socket) == 0) panic ("tcp_disconnect not lock owner"); } if (tp->t_state < TCPS_ESTABLISHED) tp = tcp_close(tp); else if ((so->so_options & SO_LINGER) && so->so_linger == 0) tp = tcp_drop(tp, 0); else { soisdisconnecting(so); sbflush(&so->so_rcv);#ifdef XTI sbflush(&so->so_exrcv);#endif XTI tp = tcp_usrclosed(tp); if (tp) (void) tcp_output(tp); } return (tp);}/* * User issued close, and wish to trail through shutdown states: * if never received SYN, just forget it. If got a SYN from peer, * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. * If already got a FIN from peer, then almost done; go to LAST_ACK * state. In all other cases, have already sent FIN to peer (e.g. * after PRU_SHUTDOWN), and just have to play tedious game waiting * for peer to send FIN or not respond to keep-alives, etc. * We can let the user exit from the close as soon as the FIN is acked. */struct tcpcb *tcp_usrclosed(tp) register struct tcpcb *tp;{ switch (tp->t_state) { case TCPS_CLOSED: case TCPS_LISTEN: case TCPS_SYN_SENT: tp->t_state = TCPS_CLOSED; tp = tcp_close(tp); break; case TCPS_SYN_RECEIVED: case TCPS_ESTABLISHED: tp->t_state = TCPS_FIN_WAIT_1; break; case TCPS_CLOSE_WAIT: tp->t_state = TCPS_LAST_ACK; break; } if (tp && tp->t_state >= TCPS_FIN_WAIT_2) soisdisconnected(tp->t_inpcb->inp_socket); return (tp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -