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

📄 smt.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
#if	0		/* for DUP recognition, do NOT filter them */	/* ignore loop back packets */	if (is_my_addr(smc,&sm->smt_source) && !local) {		smt_free_mbuf(smc,mb) ;		return ;	}#endif	smt_swap_para(sm,(int) mb->sm_len,1) ;	DB_SMT("SMT : received packet [%s] at 0x%x\n",		smt_type_name[m_fc(mb) & 0xf],sm) ;	DB_SMT("SMT : version %d, class %s\n",sm->smt_version,		smt_class_name[(sm->smt_class>LAST_CLASS)?0 : sm->smt_class]) ;#ifdef	SBA	/*	 * check if NSA frame	 */	if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF &&		(sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) {			smc->sba.sm = sm ;			sba(smc,NIF) ;	}#endif	/*	 * ignore any packet with NSA and A-indicator set	 */	if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) {		DB_SMT("SMT : ignoring NSA with A-indicator set from %s\n",			addr_to_string(&sm->smt_source),0) ;		smt_free_mbuf(smc,mb) ;		return ;	}	/*	 * ignore frames with illegal length	 */	if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) ||	    ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) {		smt_free_mbuf(smc,mb) ;		return ;	}	/*	 * check SMT version	 */	switch (sm->smt_class) {	case SMT_NIF :	case SMT_SIF_CONFIG :	case SMT_SIF_OPER :	case SMT_ECF :		if (sm->smt_version != SMT_VID)			illegal = 1;		break ;	default :		if (sm->smt_version != SMT_VID_2)			illegal = 1;		break ;	}	if (illegal) {		DB_SMT("SMT : version = %d, dest = %s\n",			sm->smt_version,addr_to_string(&sm->smt_source)) ;		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_VERSION,local) ;		smt_free_mbuf(smc,mb) ;		return ;	}	if ((sm->smt_len > mb->sm_len - sizeof(struct smt_header)) ||	    ((sm->smt_len & 3) && (sm->smt_class != SMT_ECF))) {		DB_SMT("SMT: info length error, len = %d\n",sm->smt_len,0) ;		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,local) ;		smt_free_mbuf(smc,mb) ;		return ;	}	switch (sm->smt_class) {	case SMT_NIF :		if (smt_check_para(smc,sm,plist_nif)) {			DB_SMT("SMT: NIF with para problem, ignoring\n",0,0) ;			break ;		} ;		switch (sm->smt_type) {		case SMT_ANNOUNCE :		case SMT_REQUEST :			if (!(fs & C_INDICATOR) && m_fc(mb) == FC_SMT_NSA				&& is_broadcast(&sm->smt_dest)) {				struct smt_p_state	*st ;				/* set my UNA */				if (!is_equal(					&smc->mib.m[MAC0].fddiMACUpstreamNbr,					&sm->smt_source)) {					DB_SMT("SMT : updated my UNA = %s\n",					addr_to_string(&sm->smt_source),0) ;					if (!is_equal(&smc->mib.m[MAC0].					    fddiMACUpstreamNbr,&SMT_Unknown)){					 /* Do not update unknown address */					 smc->mib.m[MAC0].fddiMACOldUpstreamNbr=					 smc->mib.m[MAC0].fddiMACUpstreamNbr ;					}					smc->mib.m[MAC0].fddiMACUpstreamNbr =						sm->smt_source ;					smt_srf_event(smc,						SMT_EVENT_MAC_NEIGHBOR_CHANGE,						INDEX_MAC,0) ;					smt_echo_test(smc,0) ;				}				smc->sm.smt_tvu = smt_get_time() ;				st = (struct smt_p_state *)					sm_to_para(smc,sm,SMT_P_STATE) ;				if (st) {					smc->mib.m[MAC0].fddiMACUNDA_Flag =					(st->st_dupl_addr & SMT_ST_MY_DUPA) ?					TRUE : FALSE ;					update_dac(smc,1) ;				}			}			if ((sm->smt_type == SMT_REQUEST) &&			    is_individual(&sm->smt_source) &&			    ((!(fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) ||			     (m_fc(mb) != FC_SMT_NSA))) {				DB_SMT("SMT : replying to NIF request %s\n",					addr_to_string(&sm->smt_source),0) ;				smt_send_nif(smc,&sm->smt_source,					FC_SMT_INFO,					sm->smt_tid,					SMT_REPLY,local) ;			}			break ;		case SMT_REPLY :			DB_SMT("SMT : received NIF response from %s\n",				addr_to_string(&sm->smt_source),0) ;			if (fs & A_INDICATOR) {				smc->sm.pend[SMT_TID_NIF] = 0 ;				DB_SMT("SMT : duplicate address\n",0,0) ;				smc->mib.m[MAC0].fddiMACDupAddressTest =					DA_FAILED ;				smc->r.dup_addr_test = DA_FAILED ;				queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;				smc->mib.m[MAC0].fddiMACDA_Flag = TRUE ;				update_dac(smc,1) ;				break ;			}			if (sm->smt_tid == smc->sm.pend[SMT_TID_NIF]) {				smc->sm.pend[SMT_TID_NIF] = 0 ;				/* set my DNA */				if (!is_equal(					&smc->mib.m[MAC0].fddiMACDownstreamNbr,					&sm->smt_source)) {					DB_SMT("SMT : updated my DNA\n",0,0) ;					if (!is_equal(&smc->mib.m[MAC0].					 fddiMACDownstreamNbr, &SMT_Unknown)){					 /* Do not update unknown address */				smc->mib.m[MAC0].fddiMACOldDownstreamNbr =					 smc->mib.m[MAC0].fddiMACDownstreamNbr ;					}					smc->mib.m[MAC0].fddiMACDownstreamNbr =						sm->smt_source ;					smt_srf_event(smc,						SMT_EVENT_MAC_NEIGHBOR_CHANGE,						INDEX_MAC,0) ;					smt_echo_test(smc,1) ;				}				smc->mib.m[MAC0].fddiMACDA_Flag = FALSE ;				update_dac(smc,1) ;				smc->sm.smt_tvd = smt_get_time() ;				smc->mib.m[MAC0].fddiMACDupAddressTest =					DA_PASSED ;				if (smc->r.dup_addr_test != DA_PASSED) {					smc->r.dup_addr_test = DA_PASSED ;					queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;				}			}			else if (sm->smt_tid ==				smc->sm.pend[SMT_TID_NIF_TEST]) {				DB_SMT("SMT : NIF test TID ok\n",0,0) ;			}			else {				DB_SMT("SMT : expected TID %lx, got %lx\n",				smc->sm.pend[SMT_TID_NIF],sm->smt_tid) ;			}			break ;		default :			illegal = 2 ;			break ;		}		break ;	case SMT_SIF_CONFIG :	/* station information */		if (sm->smt_type != SMT_REQUEST)			break ;		DB_SMT("SMT : replying to SIF Config request from %s\n",			addr_to_string(&sm->smt_source),0) ;		smt_send_sif_config(smc,&sm->smt_source,sm->smt_tid,local) ;		break ;	case SMT_SIF_OPER :	/* station information */		if (sm->smt_type != SMT_REQUEST)			break ;		DB_SMT("SMT : replying to SIF Operation request from %s\n",			addr_to_string(&sm->smt_source),0) ;		smt_send_sif_operation(smc,&sm->smt_source,sm->smt_tid,local) ;		break ;	case SMT_ECF :		/* echo frame */		switch (sm->smt_type) {		case SMT_REPLY :			smc->mib.priv.fddiPRIVECF_Reply_Rx++ ;			DB_SMT("SMT: received ECF reply from %s\n",				addr_to_string(&sm->smt_source),0) ;			if (sm_to_para(smc,sm,SMT_P_ECHODATA) == 0) {				DB_SMT("SMT: ECHODATA missing\n",0,0) ;				break ;			}			if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF]) {				DB_SMT("SMT : ECF test TID ok\n",0,0) ;			}			else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_UNA]) {				DB_SMT("SMT : ECF test UNA ok\n",0,0) ;			}			else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_DNA]) {				DB_SMT("SMT : ECF test DNA ok\n",0,0) ;			}			else {				DB_SMT("SMT : expected TID %lx, got %lx\n",					smc->sm.pend[SMT_TID_ECF],					sm->smt_tid) ;			}			break ;		case SMT_REQUEST :			smc->mib.priv.fddiPRIVECF_Req_Rx++ ;			{			if (sm->smt_len && !sm_to_para(smc,sm,SMT_P_ECHODATA)) {			DB_SMT("SMT: ECF with para problem,sending RDF\n",0,0) ;				smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,					local) ;				break ;			}			DB_SMT("SMT - sending ECF reply to %s\n",				addr_to_string(&sm->smt_source),0) ;			/* set destination addr.  & reply */			sm->smt_dest = sm->smt_source ;			sm->smt_type = SMT_REPLY ;			dump_smt(smc,sm,"ECF REPLY") ;			smc->mib.priv.fddiPRIVECF_Reply_Tx++ ;			smt_send_frame(smc,mb,FC_SMT_INFO,local) ;			return ;		/* DON'T free mbuf */			}		default :			illegal = 1 ;			break ;		}		break ;#ifndef	BOOT	case SMT_RAF :		/* resource allocation */#ifdef	ESS		DB_ESSN(2,"ESS: RAF frame received\n",0,0) ;		fs = ess_raf_received_pack(smc,mb,sm,fs) ;#endif#ifdef	SBA		DB_SBAN(2,"SBA: RAF frame received\n",0,0) ;		sba_raf_received_pack(smc,sm,fs) ;#endif		break ;	case SMT_RDF :		/* request denied */		smc->mib.priv.fddiPRIVRDF_Rx++ ;		break ;	case SMT_ESF :		/* extended service - not supported */		if (sm->smt_type == SMT_REQUEST) {			DB_SMT("SMT - received ESF, sending RDF\n",0,0) ;			smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;		}		break ;	case SMT_PMF_GET :	case SMT_PMF_SET :		if (sm->smt_type != SMT_REQUEST)			break ;		/* update statistics */		if (sm->smt_class == SMT_PMF_GET)			smc->mib.priv.fddiPRIVPMF_Get_Rx++ ;		else			smc->mib.priv.fddiPRIVPMF_Set_Rx++ ;		/*		 * ignore PMF SET with I/G set		 */		if ((sm->smt_class == SMT_PMF_SET) &&			!is_individual(&sm->smt_dest)) {			DB_SMT("SMT: ignoring PMF-SET with I/G set\n",0,0) ;			break ;		}		smt_pmf_received_pack(smc,mb, local) ;		break ;	case SMT_SRF :		dump_smt(smc,sm,"SRF received") ;		break ;	default :		if (sm->smt_type != SMT_REQUEST)			break ;		/*		 * For frames with unknown class:		 * we need to send a RDF frame according to 8.1.3.1.1,		 * only if it is a REQUEST.		 */		DB_SMT("SMT : class = %d, send RDF to %s\n",			sm->smt_class, addr_to_string(&sm->smt_source)) ;		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;		break ;#endif	}	if (illegal) {		DB_SMT("SMT: discarding invalid frame, reason = %d\n",			illegal,0) ;	}	smt_free_mbuf(smc,mb) ;}static void update_dac(struct s_smc *smc, int report){	int	cond ;	cond = ( smc->mib.m[MAC0].fddiMACUNDA_Flag |		smc->mib.m[MAC0].fddiMACDA_Flag) != 0 ;	if (report && (cond != smc->mib.m[MAC0].fddiMACDuplicateAddressCond))		smt_srf_event(smc, SMT_COND_MAC_DUP_ADDR,INDEX_MAC,cond) ;	else		smc->mib.m[MAC0].fddiMACDuplicateAddressCond = cond ;}/* * send SMT frame *	set source address *	set station ID *	send frame */void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local)/* SMbuf *mb;	buffer to send *//* int fc;	FC value */{	struct smt_header	*sm ;	if (!smc->r.sm_ma_avail && !local) {		smt_free_mbuf(smc,mb) ;		return ;	}	sm = smtod(mb,struct smt_header *) ;	sm->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;	sm->smt_sid = smc->mib.fddiSMTStationId ;	smt_swap_para(sm,(int) mb->sm_len,0) ;		/* swap para & header */	hwm_conv_can(smc,(char *)sm,12) ;		/* convert SA and DA */	smc->mib.m[MAC0].fddiMACSMTTransmit_Ct++ ;	smt_send_mbuf(smc,mb,local ? FC_SMT_LOC : fc) ;}/* * generate and send RDF */static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,			 int local)/* SMbuf *rej;	mbuf of offending frame *//* int fc;	FC of denied frame *//* int reason;	reason code */{	SMbuf	*mb ;	struct smt_header	*sm ;	/* header of offending frame */	struct smt_rdf	*rdf ;	int		len ;	int		frame_len ;	sm = smtod(rej,struct smt_header *) ;	if (sm->smt_type != SMT_REQUEST)		return ;	DB_SMT("SMT: sending RDF to %s,reason = 0x%x\n",		addr_to_string(&sm->smt_source),reason) ;	/*	 * note: get framelength from MAC length, NOT from SMT header	 * smt header length is included in sm_len	 */	frame_len = rej->sm_len ;	if (!(mb=smt_build_frame(smc,SMT_RDF,SMT_REPLY,sizeof(struct smt_rdf))))		return ;	rdf = smtod(mb,struct smt_rdf *) ;	rdf->smt.smt_tid = sm->smt_tid ;		/* use TID from sm */	rdf->smt.smt_dest = sm->smt_source ;		/* set dest = source */	/* set P12 */	rdf->reason.para.p_type = SMT_P_REASON ;	rdf->reason.para.p_len = sizeof(struct smt_p_reason) - PARA_LEN ;	rdf->reason.rdf_reason = reason ;	/* set P14 */	rdf->version.para.p_type = SMT_P_VERSION ;	rdf->version.para.p_len = sizeof(struct smt_p_version) - PARA_LEN ;	rdf->version.v_pad = 0 ;	rdf->version.v_n = 1 ;	rdf->version.v_index = 1 ;	rdf->version.v_version[0] = SMT_VID_2 ;	rdf->version.v_pad2 = 0 ;	/* set P13 */	if ((unsigned) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) +		2*sizeof(struct smt_header))		len = frame_len ;	else		len = SMT_MAX_INFO_LEN - sizeof(*rdf) +			2*sizeof(struct smt_header) ;	/* make length multiple of 4 */	len &= ~3 ;	rdf->refused.para.p_type = SMT_P_REFUSED ;	/* length of para is smt_frame + ref_fc */	rdf->refused.para.p_len = len + 4 ;	rdf->refused.ref_fc = fc ;	/* swap it back */	smt_swap_para(sm,frame_len,0) ;	memcpy((char *) &rdf->refused.ref_header,(char *) sm,len) ;	len -= sizeof(struct smt_header) ;	mb->sm_len += len ;	rdf->smt.smt_len += len ;	dump_smt(smc,(struct smt_header *)rdf,"RDF") ;	smc->mib.priv.fddiPRIVRDF_Tx++ ;	smt_send_frame(smc,mb,FC_SMT_INFO,local) ;}/* * generate and send NIF */static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 			 int fc, u_long tid, int type, int local)/* struct fddi_addr *dest;	dest address *//* int fc;			frame control *//* u_long tid;			transaction id *//* int type;			frame type */{	struct smt_nif	*nif ;	SMbuf		*mb ;	if (!(mb = smt_build_frame(smc,SMT_NIF,type,sizeof(struct smt_nif))))		return ;	nif = smtod(mb, struct smt_nif *) ;	smt_fill_una(smc,&nif->una) ;	/* set UNA */	smt_fill_sde(smc,&nif->sde) ;	/* set station descriptor */	smt_fill_state(smc,&nif->state) ;	/* set state information */#ifdef	SMT6_10	smt_fill_fsc(smc,&nif->fsc) ;	/* set frame status cap. */#endif	nif->smt.smt_dest = *dest ;	/* destination address */	nif->smt.smt_tid = tid ;	/* transaction ID */	dump_smt(smc,(struct smt_header *)nif,"NIF") ;	smt_send_frame(smc,mb,fc,local) ;}#ifdef	DEBUG/* * send NIF request (test purpose) */static void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest){	smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ;	smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST],		SMT_REQUEST,0) ;}/* * send ECF request (test purpose) */static void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest,				 int len){	smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ;	smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF],		SMT_REQUEST,len) ;}#endif/* * echo test */static void smt_echo_test(struct s_smc *smc, int dna){	u_long	tid ;	smc->sm.pend[dna ? SMT_TID_ECF_DNA : SMT_TID_ECF_UNA] =		tid = smt_get_tid(smc) ;	smt_send_ecf(smc, dna ?		&smc->mib.m[MAC0].fddiMACDownstreamNbr :		&smc->mib.m[MAC0].fddiMACUpstreamNbr,		FC_SMT_INFO,tid, SMT_REQUEST, (SMT_TEST_ECHO_LEN & ~3)-8) ;}/* * generate and send ECF */static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,			 u_long tid, int type, int len)/* struct fddi_addr *dest;	dest address *//* int fc;			frame control *//* u_long tid;			transaction id *//* int type;			frame type *//* int len;			frame length */{	struct smt_ecf	*ecf ;	SMbuf		*mb ;	if (!(mb = smt_build_frame(smc,SMT_ECF,type,SMT_ECF_LEN + len)))		return ;	ecf = smtod(mb, struct smt_ecf *) ;	smt_fill_echo(smc,&ecf->ec_echo,tid,len) ;	/* set ECHO */	ecf->smt.smt_dest = *dest ;	/* destination address */	ecf->smt.smt_tid = tid ;	/* transaction ID */	smc->mib.priv.fddiPRIVECF_Req_Tx++ ;	smt_send_frame(smc,mb,fc,0) ;}/* * generate and send SIF config response

⌨️ 快捷键说明

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