📄 smt.c
字号:
#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 + -