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

📄 tp_pcb.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
tp_freeref(n)RefNum n;{	register struct tp_ref *r = tp_ref + n;	register struct tp_pcb *tpcb;	tpcb = r->tpr_pcb;	IFDEBUG(D_TIMER)		printf("tp_freeref called for ref %d pcb %x maxrefopen %d\n", 		n, tpcb, tp_refinfo.tpr_maxopen);	ENDDEBUG	IFTRACE(D_TIMER)		tptrace(TPPTmisc, "tp_freeref ref maxrefopen pcb",		n, tp_refinfo.tpr_maxopen, tpcb, 0);	ENDTRACE	if (tpcb == 0)		return;	IFDEBUG(D_CONN)		printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", tpcb);	ENDDEBUG	r->tpr_pcb = (struct tp_pcb *)0;	tpcb->tp_refstate = REF_FREE;	for (r = tp_ref + tp_refinfo.tpr_maxopen; r > tp_ref; r--)		if (r->tpr_pcb)			break;	tp_refinfo.tpr_maxopen = r - tp_ref;	tp_refinfo.tpr_numopen--;	IFDEBUG(D_TIMER)		printf("tp_freeref ends w/ maxrefopen %d\n", tp_refinfo.tpr_maxopen);	ENDDEBUG}/* * NAME:  tp_getref() * * CALLED FROM: *  tp_attach() * * FUNCTION and ARGUMENTS: *  obtains the next free reference and allocates the appropriate *  ref structure, links that structure to (tpcb)  * * RETURN VALUE: *	a reference number *  or TP_ENOREF * * SIDE EFFECTS: * * NOTES: */u_longtp_getref(tpcb) 	register struct tp_pcb *tpcb;{	register struct tp_ref	*r, *rlim;	register int 			i;	caddr_t obase;	unsigned size;	if (++tp_refinfo.tpr_numopen < tp_refinfo.tpr_size)		for (r = tp_refinfo.tpr_base, rlim = r + tp_refinfo.tpr_size;								++r < rlim; ) 	/* tp_ref[0] is never used */			if (r->tpr_pcb == 0)				goto got_one;	/* else have to allocate more space */	obase = (caddr_t)tp_refinfo.tpr_base;	size = tp_refinfo.tpr_size * sizeof(struct tp_ref);	r = (struct tp_ref *) malloc(size + size, M_PCB, M_NOWAIT);	if (r == 0)		return (--tp_refinfo.tpr_numopen, TP_ENOREF);	tp_refinfo.tpr_base = tp_ref = r;	tp_refinfo.tpr_size *= 2;	bcopy(obase, (caddr_t)r, size);	free(obase, M_PCB);	r = (struct tp_ref *)(size + (caddr_t)r);	bzero((caddr_t)r, size);got_one:	r->tpr_pcb = tpcb;	tpcb->tp_refstate = REF_OPENING;	i = r - tp_refinfo.tpr_base;	if (tp_refinfo.tpr_maxopen < i) 		tp_refinfo.tpr_maxopen = i;	return (u_long)i;}/* * NAME: tp_set_npcb() * * CALLED FROM: *	tp_attach(), tp_route_to() * * FUNCTION and ARGUMENTS: *  given a tpcb, allocate an appropriate lower-lever npcb, freeing *  any old ones that might need re-assigning. */tp_set_npcb(tpcb)register struct tp_pcb *tpcb;{	register struct socket *so = tpcb->tp_sock;	int error;	if (tpcb->tp_nlproto && tpcb->tp_npcb) {		short so_state = so->so_state;		so->so_state &= ~SS_NOFDREF;		tpcb->tp_nlproto->nlp_pcbdetach(tpcb->tp_npcb);		so->so_state = so_state;	}	tpcb->tp_nlproto = &nl_protosw[tpcb->tp_netservice];	/* xx_pcballoc sets so_pcb */	error = tpcb->tp_nlproto->nlp_pcballoc(so, tpcb->tp_nlproto->nlp_pcblist);	tpcb->tp_npcb = so->so_pcb;	so->so_pcb = (caddr_t)tpcb;	return (error);}/* * NAME: tp_attach() * * CALLED FROM: *	tp_usrreq, PRU_ATTACH * * FUNCTION and ARGUMENTS: *  given a socket (so) and a protocol family (dom), allocate a tpcb *  and ref structure, initialize everything in the structures that *  needs to be initialized. * * RETURN VALUE: *  0 ok *  EINVAL if DEBUG(X) in is on and a disaster has occurred *  ENOPROTOOPT if TP hasn't been configured or if the *   socket wasn't created with tp as its protocol *  EISCONN if this socket is already part of a connection *  ETOOMANYREFS if ran out of tp reference numbers. *  E* whatever error is returned from soreserve() *    for from the network-layer pcb allocation routine * * SIDE EFFECTS: * * NOTES: */tp_attach(so, protocol)	struct socket 			*so;	int 					protocol;{	register struct tp_pcb	*tpcb;	int 					error = 0;	int 					dom = so->so_proto->pr_domain->dom_family;	u_long					lref;	extern struct tp_conn_param tp_conn_param[];	IFDEBUG(D_CONN)		printf("tp_attach:dom 0x%x so 0x%x ", dom, so);	ENDDEBUG	IFTRACE(D_CONN)		tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0);	ENDTRACE	if (so->so_pcb != NULL) { 		return EISCONN;	/* socket already part of a connection*/	}	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0)		error = soreserve(so, tp_sendspace, tp_recvspace);		/* later an ioctl will allow reallocation IF still in closed state */	if (error)		goto bad2;	MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT);	if (tpcb == NULL) {		error = ENOBUFS;		goto bad2;	}	bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) );	if ( ((lref = tp_getref(tpcb)) &  TP_ENOREF) != 0 ) { 		error = ETOOMANYREFS; 		goto bad3;	}	tpcb->tp_lref = lref;	tpcb->tp_sock =  so;	tpcb->tp_domain = dom;	tpcb->tp_rhiwat = so->so_rcv.sb_hiwat;	/* tpcb->tp_proto = protocol; someday maybe? */	if (protocol && protocol<ISOPROTO_TP4) {		tpcb->tp_netservice = ISO_CONS;		tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC								 * will generate correct fake-ack values								 */	} else {		tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS;		/* the default */	}	tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice];	tpcb->tp_state = TP_CLOSED;	tpcb->tp_vers  = TP_VERSION;	tpcb->tp_notdetached = 1;		   /* Spec says default is 128 octets,			* that is, if the tpdusize argument never appears, use 128.			* As the initiator, we will always "propose" the 2048			* size, that is, we will put this argument in the CR 			* always, but accept what the other side sends on the CC.			* If the initiator sends us something larger on a CR,			* we'll respond w/ this.			* Our maximum is 4096.  See tp_chksum.c comments.			*/	tpcb->tp_cong_win = 		tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize;	tpcb->tp_seqmask  = TP_NML_FMT_MASK;	tpcb->tp_seqbit  =  TP_NML_FMT_BIT;	tpcb->tp_seqhalf  =  tpcb->tp_seqbit >> 1;	/* attach to a network-layer protoswitch */	if ( error =  tp_set_npcb(tpcb))		goto bad4;	ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain);	/* nothing to do for iso case */	if( dom == AF_INET )		sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb;	return 0;bad4:	IFDEBUG(D_CONN)		printf("BAD4 in tp_attach, so 0x%x\n", so);	ENDDEBUG	tp_freeref(tpcb->tp_lref);bad3:	IFDEBUG(D_CONN)		printf("BAD3 in tp_attach, so 0x%x\n", so);	ENDDEBUG	free((caddr_t)tpcb, M_PCB); /* never a cluster  */bad2:	IFDEBUG(D_CONN)		printf("BAD2 in tp_attach, so 0x%x\n", so);	ENDDEBUG	so->so_pcb = 0;/*bad:*/	IFDEBUG(D_CONN)		printf("BAD in tp_attach, so 0x%x\n", so);	ENDDEBUG	return error;}/* * NAME:  tp_detach() * * CALLED FROM: *	tp.trans, on behalf of a user close request *  and when the reference timer goes off * (if the disconnect  was initiated by the protocol entity  * rather than by the user) * * FUNCTION and ARGUMENTS: *  remove the tpcb structure from the list of active or *  partially active connections, recycle all the mbufs *  associated with the pcb, ref structure, sockbufs, etc. *  Only free the ref structure if you know that a ref timer *  wasn't set for this tpcb. * * RETURNS:  Nada * * SIDE EFFECTS: * * NOTES: *  tp_soisdisconnected() was already when this is called */voidtp_detach(tpcb)	register struct tp_pcb 	*tpcb;{	void					tp_freeref(), tp_rsyflush();	register struct socket	 *so = tpcb->tp_sock;	IFDEBUG(D_CONN)		printf("tp_detach(tpcb 0x%x, so 0x%x)\n",			tpcb,so);	ENDDEBUG	IFTRACE(D_CONN)		tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx", 			tpcb, so, *(u_short *)(tpcb->tp_lsuffix), 0);	ENDTRACE	IFDEBUG(D_CONN)		printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv);		dump_mbuf(so->so_snd.sb_mb, "so_snd at detach ");		printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n",				tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach);	ENDDEBUG	if (tpcb->tp_Xsnd.sb_mb) {		printf("Unsent Xdata on detach; would panic");		sbflush(&tpcb->tp_Xsnd);	}	if (tpcb->tp_ucddata)		m_freem(tpcb->tp_ucddata);	IFDEBUG(D_CONN)		printf("reassembly info cnt %d rsyq 0x%x\n",		    tpcb->tp_rsycnt, tpcb->tp_rsyq);	ENDDEBUG	if (tpcb->tp_rsyq)		tp_rsyflush(tpcb);	if (tpcb->tp_next) {		remque(tpcb);		tpcb->tp_next = tpcb->tp_prev = 0;	}	tpcb->tp_notdetached = 0;	IFDEBUG(D_CONN)		printf("calling (...nlproto->...)(0x%x, so 0x%x)\n", 			tpcb->tp_npcb, so);		printf("so 0x%x so_head 0x%x,  qlen %d q0len %d qlimit %d\n", 		so,  so->so_head,		so->so_q0len, so->so_qlen, so->so_qlimit);	ENDDEBUG	(tpcb->tp_nlproto->nlp_pcbdetach)(tpcb->tp_npcb);				/* does an so->so_pcb = 0; sofree(so) */	IFDEBUG(D_CONN)		printf("after xxx_pcbdetach\n");	ENDDEBUG	if (tpcb->tp_state == TP_LISTENING) {		register struct tp_pcb **tt;		for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten))			if (*tt == tpcb)				break;		if (*tt)			*tt = tpcb->tp_nextlisten;		else			printf("tp_detach from listen: should panic\n");	}	if (tpcb->tp_refstate == REF_OPENING ) {		/* no connection existed here so no reference timer will be called */		IFDEBUG(D_CONN)			printf("SETTING ref %d to REF_FREE\n", tpcb->tp_lref);		ENDDEBUG		tp_freeref(tpcb->tp_lref);	}#ifdef TP_PERF_MEAS	/* 	 * Get rid of the cluster mbuf allocated for performance measurements, if	 * there is one.  Note that tpcb->tp_perf_on says nothing about whether or 	 * not a cluster mbuf was allocated, so you have to check for a pointer 	 * to one (that is, we need the TP_PERF_MEASs around the following section 	 * of code, not the IFPERFs)	 */	if (tpcb->tp_p_mbuf) {		register struct mbuf *m = tpcb->tp_p_mbuf;		struct mbuf *n;		IFDEBUG(D_PERF_MEAS)			printf("freeing tp_p_meas 0x%x  ", tpcb->tp_p_meas);		ENDDEBUG		do {		    MFREE(m, n);		    m = n;		} while (n);		tpcb->tp_p_meas = 0;		tpcb->tp_p_mbuf = 0;	}#endif /* TP_PERF_MEAS */	IFDEBUG(D_CONN)		printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb);	ENDDEBUG	/* free((caddr_t)tpcb, M_PCB); WHere to put this ? */}struct que {	struct tp_pcb *next;	struct tp_pcb *prev;} tp_bound_pcbs ={(struct tp_pcb *)&tp_bound_pcbs, (struct tp_pcb *)&tp_bound_pcbs};u_short tp_unique;tp_tselinuse(tlen, tsel, siso, reuseaddr)caddr_t tsel;register struct sockaddr_iso *siso;{	struct tp_pcb *b = tp_bound_pcbs.next, *l = tp_listeners;	register struct tp_pcb *t;	for (;;) {		if (b != (struct tp_pcb *)&tp_bound_pcbs) {			t = b; b = t->tp_next;		} else if (l) {			t = l; l = t->tp_nextlisten;		} else			break;		if (tlen == t->tp_lsuffixlen && bcmp(tsel, t->tp_lsuffix, tlen) == 0) {			if (t->tp_flags & TPF_GENERAL_ADDR) {				if (siso == 0 || reuseaddr == 0)					return 1;			} else if (siso) {				if (siso->siso_family == t->tp_domain &&					t->tp_nlproto->nlp_cmpnetaddr(t->tp_npcb, siso, TP_LOCAL))						return 1;			} else if (reuseaddr == 0)						return 1;		}	}	return 0;}tp_pcbbind(tpcb, nam)register struct tp_pcb *tpcb;register struct mbuf *nam;{	register struct sockaddr_iso *siso = 0;	int tlen = 0, wrapped = 0;	caddr_t tsel;	u_short tutil;	if (tpcb->tp_state != TP_CLOSED)		return (EINVAL);	if (nam) {		siso = mtod(nam, struct sockaddr_iso *);		switch (siso->siso_family) {		default:			return (EAFNOSUPPORT);#ifdef ISO		case AF_ISO:			tlen = siso->siso_tlen;			tsel = TSEL(siso);			if (siso->siso_nlen == 0)				siso = 0;			break;#endif#ifdef INET		case AF_INET:			tsel = (caddr_t)&tutil;			if (tutil =  ((struct sockaddr_in *)siso)->sin_port) {				tlen = 2;			}			if (((struct sockaddr_in *)siso)->sin_addr.s_addr == 0)				siso = 0;		}#endif	}	if (tpcb->tp_lsuffixlen == 0) {		if (tlen) {			if (tp_tselinuse(tlen, tsel, siso,								tpcb->tp_sock->so_options & SO_REUSEADDR))				return (EINVAL);		} else {			for (tsel = (caddr_t)&tutil, tlen = 2;;){				if (tp_unique++ < ISO_PORT_RESERVED ||					tp_unique > ISO_PORT_USERRESERVED) {						if (wrapped++)							return ESRCH;						tp_unique = ISO_PORT_RESERVED;				}				tutil = htons(tp_unique);				if (tp_tselinuse(tlen, tsel, siso, 0) == 0)					break;			}			if (siso) switch (siso->siso_family) {#ifdef ISO				case AF_ISO:					bcopy(tsel, TSEL(siso), tlen);					siso->siso_tlen = tlen;					break;#endif#ifdef INET				case AF_INET:					((struct sockaddr_in *)siso)->sin_port = tutil;#endif				}		}		bcopy(tsel, tpcb->tp_lsuffix, (tpcb->tp_lsuffixlen = tlen));		insque(tpcb, &tp_bound_pcbs);	} else {		if (tlen || siso == 0)			return (EINVAL);	}	if (siso == 0) {		tpcb->tp_flags |= TPF_GENERAL_ADDR;		return (0);	}	return tpcb->tp_nlproto->nlp_pcbbind(tpcb->tp_npcb, nam);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -