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

📄 tp_input.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
 * * NOTE: *  The initial value of acktime is 2 so that we will never *  have a 0 value for tp_peer_acktime.  It gets used in the *  computation of the retransmission timer value, and so it *  mustn't be zero. *  2 seems like a reasonable minimum. */ProtoHooktp_input(m, faddr, laddr, cons_channel, dgout_routine, ce_bit)	register	struct mbuf 	*m;	struct sockaddr 			*faddr, *laddr; /* NSAP addresses */	caddr_t						cons_channel;	int 						(*dgout_routine)();	int							ce_bit;{	register struct tp_pcb 	*tpcb;	register struct tpdu 	*hdr;	struct socket 			*so;	struct tp_event 		e;	int 					error;	unsigned 				dutype;	u_short 				dref, sref, acktime, subseq;	u_char 					preferred_class, class_to_use, pdusize;	u_char					opt, dusize, addlopt, version;#ifdef TP_PERF_MEAS	u_char					perf_meas;#endif /* TP_PERF_MEAS */	u_char					fsufxlen, lsufxlen;	caddr_t					fsufxloc, lsufxloc;	int						tpdu_len;	u_int 					takes_data;	u_int					fcc_present; 	int						errlen;	struct tp_conn_param 	tpp;	int						tpcons_output();again:	hdr = mtod(m, struct tpdu *);	tpcb = 0;	error = errlen = tpdu_len = 0;	takes_data = fcc_present = FALSE;	acktime = 2; sref = subseq = 0;	fsufxloc = lsufxloc = NULL;	fsufxlen = lsufxlen =		preferred_class = class_to_use = pdusize = addlopt = 0;	dusize = TP_DFL_TPDUSIZE;#ifdef TP_PERF_MEAS	GET_CUR_TIME( &e.e_time ); perf_meas = 0;#endif /* TP_PERF_MEAS */		IFDEBUG(D_TPINPUT)		printf("tp_input(0x%x, ... 0x%x)\n", m, cons_channel);	ENDDEBUG	/* 	 * get the actual tpdu length - necessary for monitoring	 * and for checksumming	 * 	 * Also, maybe measure the mbuf chain lengths and sizes.	 */	{ 	register struct mbuf *n=m;#	ifdef ARGO_DEBUG		int chain_length = 0;#	endif ARGO_DEBUG		for(;;) {			tpdu_len += n->m_len;			IFDEBUG(D_MBUF_MEAS)				if( n->m_flags & M_EXT) {					IncStat(ts_mb_cluster);				} else {					IncStat(ts_mb_small);				}				chain_length ++;			ENDDEBUG			if (n->m_next == MNULL ) {				break;			}			n = n->m_next;		}		IFDEBUG(D_MBUF_MEAS)			if(chain_length > 16)				chain_length = 0; /* zero used for anything > 16 */			tp_stat.ts_mb_len_distr[chain_length] ++;		ENDDEBUG	}	IFTRACE(D_TPINPUT)		tptraceTPCB(TPPTtpduin, hdr->tpdu_type, hdr, hdr->tpdu_li+1, tpdu_len, 			0);	ENDTRACE	dref = ntohs((short)hdr->tpdu_dref);	sref = ntohs((short)hdr->tpdu_sref);	dutype = (int)hdr->tpdu_type;	IFDEBUG(D_TPINPUT)		printf("input: dutype 0x%x cons_channel 0x%x dref 0x%x\n", dutype,			cons_channel, dref);		printf("input: dref 0x%x sref 0x%x\n", dref, sref);	ENDDEBUG	IFTRACE(D_TPINPUT)		tptrace(TPPTmisc, "channel dutype dref ", 			cons_channel, dutype, dref, 0);	ENDTRACE#ifdef ARGO_DEBUG	if( (dutype < TP_MIN_TPDUTYPE) || (dutype > TP_MAX_TPDUTYPE)) {		printf("BAD dutype! 0x%x, channel 0x%x dref 0x%x\n",			dutype, cons_channel, dref);		dump_buf (m, sizeof( struct mbuf ));		IncStat(ts_inv_dutype);		goto discard;	}#endif /* ARGO_DEBUG */	CHECK( (dutype < TP_MIN_TPDUTYPE || dutype > TP_MAX_TPDUTYPE),		E_TP_INV_TPDU, ts_inv_dutype, respond, 		2 );		/* unfortunately we can't take the address of the tpdu_type field,		 * since it's a bit field - so we just use the constant offset 2		 */	/* Now this isn't very neat but since you locate a pcb one way	 * at the beginning of connection establishment, and by	 * the dref for each tpdu after that, we have to treat CRs differently	 */	if ( dutype == CR_TPDU_type ) {		u_char alt_classes = 0;		preferred_class = 1 << hdr->tpdu_CRclass;		opt = hdr->tpdu_CRoptions;		WHILE_OPTIONS(P, hdr, 1 ) /* { */			switch( vbptr(P)->tpv_code ) {			case	TPP_tpdu_size: 						vb_getval(P, u_char, dusize);				IFDEBUG(D_TPINPUT)					printf("CR dusize 0x%x\n", dusize);				ENDDEBUG				/* COS tests: NBS IA (Dec. 1987) Sec. 4.5.2.1 */				if (dusize < TP_MIN_TPDUSIZE || dusize > TP_MAX_TPDUSIZE)						dusize = TP_DFL_TPDUSIZE;				break;			case	TPP_ptpdu_size:				switch (vbptr(P)->tpv_len) {				case 1: pdusize = vbval(P, u_char); break;				case 2: pdusize = ntohs(vbval(P, u_short)); break;				default: ;				IFDEBUG(D_TPINPUT)					printf("malformed prefered TPDU option\n");				ENDDEBUG				}				break;			case	TPP_addl_opt:				vb_getval(P, u_char, addlopt);				break;			case	TPP_calling_sufx:				/* could use vb_getval, but we want to save the loc & len				 * for later use				 */				fsufxloc = (caddr_t) &vbptr(P)->tpv_val;				fsufxlen = vbptr(P)->tpv_len;				IFDEBUG(D_TPINPUT)					printf("CR fsufx:");					{ register int j;						for(j=0; j<fsufxlen; j++ ) {							printf(" 0x%x. ", *((caddr_t)(fsufxloc+j)) );						}						printf("\n");					}				ENDDEBUG				break;			case	TPP_called_sufx:				/* could use vb_getval, but we want to save the loc & len				 * for later use				 */				lsufxloc = (caddr_t) &vbptr(P)->tpv_val;				lsufxlen = vbptr(P)->tpv_len;				IFDEBUG(D_TPINPUT)					printf("CR lsufx:");					{ register int j;						for(j=0; j<lsufxlen; j++ ) {							printf(" 0x%x. ", *((u_char *)(lsufxloc+j)) );						}						printf("\n");					}				ENDDEBUG				break;#ifdef TP_PERF_MEAS			case	TPP_perf_meas:				vb_getval(P, u_char, perf_meas);				break;#endif /* TP_PERF_MEAS */			case	TPP_vers:				/* not in class 0; 1 octet; in CR_TPDU only */				/* COS tests says if version wrong, use default version!?XXX */				CHECK( (vbval(P, u_char) != TP_VERSION ), 					E_TP_INV_PVAL, ts_inv_pval, setversion,					(1 + (caddr_t)&vbptr(P)->tpv_val - (caddr_t)hdr) );			setversion:				version = vbval(P, u_char);				break;			case	TPP_acktime:				vb_getval(P, u_short, acktime);				acktime = ntohs(acktime);				acktime = acktime/500; /* convert to slowtimo ticks */				if((short)acktime <=0 )					acktime = 2; /* don't allow a bad peer to screw us up */				IFDEBUG(D_TPINPUT)					printf("CR acktime 0x%x\n", acktime);				ENDDEBUG				break;			case	TPP_alt_class:				{					u_char *aclass = 0;					register int i;					static u_char bad_alt_classes[5] =						{ ~0, ~3, ~5, ~0xf, ~0x1f};					aclass = 						(u_char *) &(((struct tp_vbp *)P)->tpv_val);					for (i = ((struct tp_vbp *)P)->tpv_len; i>0; i--) {						alt_classes |= (1<<((*aclass++)>>4));					}					CHECK( (bad_alt_classes[hdr->tpdu_CRclass] & alt_classes),						E_TP_INV_PVAL, ts_inv_aclass, respond,						((caddr_t)aclass) - (caddr_t)hdr);					IFDEBUG(D_TPINPUT)						printf("alt_classes 0x%x\n", alt_classes);					ENDDEBUG				}				break;			case	TPP_security:			case	TPP_residER:			case	TPP_priority:			case	TPP_transdelay:			case	TPP_throughput: 			case	TPP_addl_info: 			case	TPP_subseq:			default:				IFDEBUG(D_TPINPUT)					printf("param ignored CR_TPDU code= 0x%x\n",						 vbptr(P)->tpv_code);				ENDDEBUG				IncStat(ts_param_ignored);				break;			case	TPP_checksum:						IFDEBUG(D_TPINPUT)					printf("CR before cksum\n");				ENDDEBUG				CHECK( iso_check_csum(m, tpdu_len), 					E_TP_INV_PVAL, ts_bad_csum, discard, 0)				IFDEBUG(D_TPINPUT)					printf("CR before cksum\n");				ENDDEBUG				break;			}		/* } */ END_WHILE_OPTIONS(P)		if (lsufxlen == 0) {			/* can't look for a tpcb w/o any called sufx */			error =  E_TP_LENGTH_INVAL;			IncStat(ts_inv_sufx);			goto respond;		} else {			register struct tp_pcb *t;			/*			 * The intention here is to trap all CR requests			 * to a given nsap, for constructing transport			 * service bridges at user level; so these			 * intercepts should precede the normal listens.			 * Phrasing the logic in this way also allows for			 * mop-up listeners, which we don't currently implement.			 * We also wish to have a single socket be able to			 * listen over any network service provider,			 * (cons or clns or ip).			 */			for (t = tp_listeners; t ; t = t->tp_nextlisten)				if ((t->tp_lsuffixlen == 0 ||					 (lsufxlen == t->tp_lsuffixlen &&					  bcmp(lsufxloc, t->tp_lsuffix, lsufxlen) == 0)) &&					((t->tp_flags & TPF_GENERAL_ADDR) ||					 (laddr->sa_family == t->tp_domain &&					  (*t->tp_nlproto->nlp_cmpnetaddr)								(t->tp_npcb, laddr, TP_LOCAL))))					break;			CHECK(t == 0, E_TP_NO_SESSION, ts_inv_sufx, respond,				(1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))				/* _tpduf is the fixed part; add 2 to get the dref bits of 				 * the fixed part (can't take the address of a bit field) 				 */			IFDEBUG(D_TPINPUT)				printf("checking if dup CR\n");			ENDDEBUG			tpcb = t;			for (t = tpcb->tp_next; t != tpcb; t = t->tp_next) {				if (sref != t->tp_fref)					continue;				if ((*tpcb->tp_nlproto->nlp_cmpnetaddr)(						t->tp_npcb, faddr, TP_FOREIGN)) {					IFDEBUG(D_TPINPUT)						printf("duplicate CR discarded\n");					ENDDEBUG					goto discard;				}			}			IFTRACE(D_TPINPUT)				tptrace(TPPTmisc, "tp_input: tpcb *lsufxloc tpstate", 					tpcb, *lsufxloc, tpcb->tp_state, 0);			ENDTRACE		}		/* 		 * WE HAVE A TPCB 		 * already know that the classes in the CR match at least		 * one class implemented, but we don't know yet if they		 * include any classes permitted by this server.		 */		IFDEBUG(D_TPINPUT)			printf("HAVE A TPCB 1: 0x%x\n", tpcb);		ENDDEBUG		IFDEBUG(D_CONN)			printf("CR: bef CHKS: flags 0x%x class_to_use 0x%x alt 0x%x opt 0x%x tp_class 0x%x\n", 				tpcb->tp_flags, class_to_use, alt_classes, opt, tpcb->tp_class);		ENDDEBUG		/* tpcb->tp_class doesn't include any classes not implemented  */		class_to_use = (preferred_class & tpcb->tp_class);		if( (class_to_use = preferred_class & tpcb->tp_class) == 0 )			class_to_use = alt_classes & tpcb->tp_class;		class_to_use = 1 << tp_mask_to_num(class_to_use);		{			tpp = tpcb->_tp_param;			tpp.p_class = class_to_use;			tpp.p_tpdusize = dusize;			tpp.p_ptpdusize = pdusize;			tpp.p_xtd_format = (opt & TPO_XTD_FMT) == TPO_XTD_FMT;			tpp.p_xpd_service = (addlopt & TPAO_USE_TXPD) == TPAO_USE_TXPD;			tpp.p_use_checksum = (tpp.p_class == TP_CLASS_0)?0:				(addlopt & TPAO_NO_CSUM) == 0;			tpp.p_version = version;#ifdef notdef			tpp.p_use_efc = (opt & TPO_USE_EFC) == TPO_USE_EFC;			tpp.p_use_nxpd = (addlopt & TPAO_USE_NXPD) == TPAO_USE_NXPD;			tpp.p_use_rcc = (addlopt & TPAO_USE_RCC) == TPAO_USE_RCC;#endif /* notdef */		CHECK(			tp_consistency(tpcb, 0 /* not force or strict */, &tpp) != 0, 			E_TP_NEGOT_FAILED, ts_negotfailed, clear_parent_tcb,			(1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr) 				/* ^ more or less the location of class */			)		}		IFTRACE(D_CONN)			tptrace(TPPTmisc, 				"after 1 consist class_to_use class, out, tpconsout",				class_to_use, 				tpcb->tp_class, dgout_routine, tpcons_output				);		ENDTRACE		CHECK(			((class_to_use == TP_CLASS_0)&&(dgout_routine != tpcons_output)),			E_TP_NEGOT_FAILED, ts_negotfailed, clear_parent_tcb,			(1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr) 				/* ^ more or less the location of class */			)		IFDEBUG(D_CONN)			printf("CR: after CRCCCHECKS: tpcb 0x%x, flags 0x%x\n", 				tpcb, tpcb->tp_flags);		ENDDEBUG		takes_data = TRUE;		e.ATTR(CR_TPDU).e_cdt  =  hdr->tpdu_CRcdt;		e.ev_number = CR_TPDU;		so = tpcb->tp_sock;		if (so->so_options & SO_ACCEPTCONN) {			struct tp_pcb *parent_tpcb = tpcb;			/* 			 * Create a socket, tpcb, ll pcb, etc. 			 * for this newborn connection, and fill in all the values. 			 */			IFDEBUG(D_CONN)				printf("abt to call tp_newsocket(0x%x, 0x%x, 0x%x, 0x%x)\n",					so, laddr, faddr, cons_channel);			ENDDEBUG			if( (so = 

⌨️ 快捷键说明

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