⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp_usrreq.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -