// SPDX-License-Identifier: GPL-2.0-or-later /****************************************************************************** * * (C)Copyright 1998,1999 SysKonnect, * a business unit of Schneider & Koch & Co. Datensysteme GmbH. * * See the file "skfddi.c" for further information. * * The information in this file is provided "AS IS" without warranty. *
******************************************************************************/
/* Parameter Management Frame processing for SMT 7.2
*/
sm = smtod(mb,struct smt_header *) ;
DB_SMT("SMT: processing PMF frame at %p len %d", sm, mb->sm_len); #ifdef DEBUG
dump_smt(smc,sm,"PMF Received") ; #endif /* * Start the watchdog: It may be a long, long packet and * maybe the watchdog occurs ...
*/
smt_start_watchdog(smc) ;
smt = smtod(mb, struct smt_header *) ;
smt->smt_dest = req->smt_source ; /* DA == source of request */
smt->smt_class = req->smt_class ; /* same class (GET/SET) */
smt->smt_type = SMT_REPLY ;
smt->smt_version = SMT_VID_2 ;
smt->smt_tid = req->smt_tid ; /* same TID */
smt->smt_pad = 0 ;
smt->smt_len = 0 ;
/* * setup parameter status
*/
pcon.pc_len = SMT_MAX_INFO_LEN ; /* max para length */
pcon.pc_err = 0 ; /* no error */
pcon.pc_badset = 0 ; /* no bad set count */
pcon.pc_p = (void *) (smt + 1) ; /* paras start here */
/* * check authoriziation and set count
*/
error = 0 ; if (set) { if (!local && smt_authorize(smc,req))
error = SMT_RDF_AUTHOR ; elseif (smt_check_set_count(smc,req))
pcon.pc_badset = SMT_RDF_BADSET ;
} /* * add reason code and all mandatory parameters
*/
res = (struct smt_p_reason *) pcon.pc_p ;
smt_add_para(smc,&pcon,(u_short) SMT_P_REASON,0,0) ;
smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ; /* update 1035 and 1036 later if set */
set_pcon = pcon ;
smt_add_para(smc,&pcon,(u_short) SMT_P1035,0,0) ;
smt_add_para(smc,&pcon,(u_short) SMT_P1036,0,0) ;
pcon.pc_err = error ;
len = req->smt_len ;
pa = (struct smt_para *) (req + 1) ; /* * process list of paras
*/ while (!pcon.pc_err && len > 0 ) { if (((u_short)len < pa->p_len + PARA_LEN) || (pa->p_len & 3)) {
pcon.pc_err = SMT_RDF_LENGTH ; break ;
}
if (((range = (pa->p_type & 0xf000)) == 0x2000) ||
range == 0x3000 || range == 0x4000) { /* * get index for PART,MAC ad PATH group
*/
index = *((u_char *)pa + PARA_LEN + 3) ;/* index */
idx_end = index ; if (!set && (pa->p_len != 4)) {
pcon.pc_err = SMT_RDF_LENGTH ; break ;
} if (!index && !set) { switch (range) { case 0x2000 :
index = INDEX_MAC ;
idx_end = index - 1 + NUMMACS ; break ; case 0x3000 :
index = INDEX_PATH ;
idx_end = index - 1 + NUMPATHS ; break ; case 0x4000 :
index = INDEX_PORT ;
idx_end = index - 1 + NUMPHYS ; #ifndef CONCENTRATOR if (smc->s.sas == SMT_SAS)
idx_end = INDEX_PORT ; #endif break ;
}
}
} else { /* * smt group has no index
*/ if (!set && (pa->p_len != 0)) {
pcon.pc_err = SMT_RDF_LENGTH ; break ;
}
index = 0 ;
idx_end = 0 ;
} while (index <= idx_end) { /* * if group * add all paras of group
*/
pt = smt_get_ptab(pa->p_type) ; if (pt && pt->p_access == AC_GROUP && !set) {
pt++ ; while (pt->p_access == AC_G ||
pt->p_access == AC_GR) {
smt_add_para(smc,&pcon,pt->p_num,
index,local);
pt++ ;
}
} /* * ignore * AUTHORIZATION in get/set * SET COUNT in set
*/ elseif (pa->p_type != SMT_P_AUTHOR &&
(!set || (pa->p_type != SMT_P1035))) { int st ; if (pcon.pc_badset) {
smt_add_para(smc,&pcon,pa->p_type,
index,local) ;
} elseif (set) {
st = smt_set_para(smc,pa,index,local,1); /* * return para even if error
*/
smt_add_para(smc,&pcon,pa->p_type,
index,local) ;
pcon.pc_err = st ;
} else { if (pt && pt->p_access == AC_S) {
pcon.pc_err =
SMT_RDF_ILLEGAL ;
}
smt_add_para(smc,&pcon,pa->p_type,
index,local) ;
}
} if (pcon.pc_err) break ;
index++ ;
}
len -= pa->p_len + PARA_LEN ;
pa = (struct smt_para *) ((char *)pa + pa->p_len + PARA_LEN) ;
}
smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
/* update reason code */
res->rdf_reason = pcon.pc_badset ? pcon.pc_badset :
pcon.pc_err ? pcon.pc_err : SMT_RDF_SUCCESS ; if (set && (res->rdf_reason == SMT_RDF_SUCCESS)) { /* * increment set count * set time stamp * store station id of last set
*/
smc->mib.fddiSMTSetCount.count++ ;
smt_set_timestamp(smc,smc->mib.fddiSMTSetCount.timestamp) ;
smc->mib.fddiSMTLastSetStationId = req->smt_sid ;
smt_add_para(smc,&set_pcon,(u_short) SMT_P1035,0,0) ;
smt_add_para(smc,&set_pcon,(u_short) SMT_P1036,0,0) ;
} return mb;
}
staticint smt_authorize(struct s_smc *smc, struct smt_header *sm)
{ struct smt_para *pa ; int i ; char *p ;
/* * check source station id if not zero
*/
p = (char *) &smc->mib.fddiPRPMFStation ; for (i = 0 ; i < 8 && !p[i] ; i++)
; if (i != 8) { if (memcmp((char *) &sm->smt_sid,
(char *) &smc->mib.fddiPRPMFStation,8)) return 1;
} /* * check authoriziation parameter if passwd not zero
*/
p = (char *) smc->mib.fddiPRPMFPasswd ; for (i = 0 ; i < 8 && !p[i] ; i++)
; if (i != 8) {
pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P_AUTHOR) ; if (!pa) return 1; if (pa->p_len != 8) return 1; if (memcmp((char *)(pa+1),(char *)smc->mib.fddiPRPMFPasswd,8)) return 1;
} return 0;
}
pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P1035) ; if (pa) {
sc = (struct smt_p_setcount *) pa ; if ((smc->mib.fddiSMTSetCount.count != sc->count) ||
memcmp((char *) smc->mib.fddiSMTSetCount.timestamp,
(char *)sc->timestamp,8)) return 1;
} return 0;
}
void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, int index, int local)
{ struct smt_para *pa ; conststruct s_p_tab *pt ; struct fddi_mib_m *mib_m = NULL; struct fddi_mib_p *mib_p = NULL; int len ; int plen ; char *from ; char *to ; constchar *swap ; char c ; int range ; char *mib_addr ; int mac ; int path ; int port ; int sp_len ;
/* * skip if error
*/ if (pcon->pc_err) return ;
/* * actions don't have a value
*/
pt = smt_get_ptab(para) ; if (pt && pt->p_access == AC_S) return ;
to = (char *) (pcon->pc_p) ; /* destination pointer */
len = pcon->pc_len ; /* free space */
plen = len ; /* remember start length */
pa = (struct smt_para *) to ; /* type/length pointer */
to += PARA_LEN ; /* skip smt_para */
len -= PARA_LEN ; /* * set index if required
*/ if (((range = (para & 0xf000)) == 0x2000) ||
range == 0x3000 || range == 0x4000) { if (len < 4) goto wrong_error ;
to[0] = 0 ;
to[1] = 0 ;
to[2] = 0 ;
to[3] = index ;
len -= 4 ;
to += 4 ;
}
mac = index - INDEX_MAC ;
path = index - INDEX_PATH ;
port = index - INDEX_PORT ; /* * get pointer to mib
*/ switch (range) { case 0x1000 : default :
mib_addr = (char *) (&smc->mib) ; break ; case 0x2000 : if (mac < 0 || mac >= NUMMACS) {
pcon->pc_err = SMT_RDF_NOPARAM ; return ;
}
mib_addr = (char *) (&smc->mib.m[mac]) ;
mib_m = (struct fddi_mib_m *) mib_addr ; break ; case 0x3000 : if (path < 0 || path >= NUMPATHS) {
pcon->pc_err = SMT_RDF_NOPARAM ; return ;
}
mib_addr = (char *) (&smc->mib.a[path]) ; break ; case 0x4000 : if (port < 0 || port >= smt_mib_phys(smc)) {
pcon->pc_err = SMT_RDF_NOPARAM ; return ;
}
mib_addr = (char *) (&smc->mib.p[port_to_mib(smc,port)]) ;
mib_p = (struct fddi_mib_p *) mib_addr ; break ;
} /* * check special paras
*/
swap = NULL; switch (para) { case SMT_P10F0 : case SMT_P10F1 : #ifdef ESS case SMT_P10F2 : case SMT_P10F3 : case SMT_P10F4 : case SMT_P10F5 : case SMT_P10F6 : case SMT_P10F7 : #endif #ifdef SBA case SMT_P10F8 : case SMT_P10F9 : #endif case SMT_P20F1 : if (!local) {
pcon->pc_err = SMT_RDF_NOPARAM ; return ;
} break ; case SMT_P2034 : case SMT_P2046 : case SMT_P2047 : case SMT_P204A : case SMT_P2051 : case SMT_P2052 :
mac_update_counter(smc) ; break ; case SMT_P4022:
mib_p->fddiPORTPC_LS = LS2MIB(
sm_pm_get_ls(smc,port_to_mib(smc,port))) ; break ; case SMT_P_REASON :
*(u32 *)to = 0 ;
sp_len = 4 ; goto sp_done ; case SMT_P1033 : /* time stamp */
smt_set_timestamp(smc,smc->mib.fddiSMTTimeStamp) ; break ;
done: /* * make it even (in case of 'I' encoding) * note: len is DECREMENTED
*/ if (len & 3) {
to[0] = 0 ;
to[1] = 0 ;
to += 4 - (len & 3 ) ;
len = len & ~ 3 ;
}
/* set type and length */
pa->p_type = para ;
pa->p_len = plen - len - PARA_LEN ; /* return values */
pcon->pc_p = (void *) to ;
pcon->pc_len = len ; return ;
sp_done:
len -= sp_len ;
to += sp_len ; goto done ;
len_error: /* parameter does not fit in frame */
pcon->pc_err = SMT_RDF_TOOLONG ; return ;
wrong_error:
pcon->pc_err = SMT_RDF_LENGTH ;
}
/* * set parameter
*/ staticint smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, int set)
{ #define IFSET(x) if (set) (x)
conststruct s_p_tab *pt ; int len ; char *from ; char *to ; constchar *swap ; char c ; char *mib_addr ; struct fddi_mib *mib ; struct fddi_mib_m *mib_m = NULL; struct fddi_mib_a *mib_a = NULL; struct fddi_mib_p *mib_p = NULL; int mac ; int path ; int port ;
SK_LOC_DECL(u_char,byte_val) ;
SK_LOC_DECL(u_short,word_val) ;
SK_LOC_DECL(u_long,long_val) ;
mac = index - INDEX_MAC ;
path = index - INDEX_PATH ;
port = index - INDEX_PORT ;
len = pa->p_len ;
from = (char *) (pa + 1 ) ;
mib = &smc->mib ; switch (pa->p_type & 0xf000) { case 0x1000 : default :
mib_addr = (char *) mib ; break ; case 0x2000 : if (mac < 0 || mac >= NUMMACS) { return SMT_RDF_NOPARAM;
}
mib_m = &smc->mib.m[mac] ;
mib_addr = (char *) mib_m ;
from += 4 ; /* skip index */
len -= 4 ; break ; case 0x3000 : if (path < 0 || path >= NUMPATHS) { return SMT_RDF_NOPARAM;
}
mib_a = &smc->mib.a[path] ;
mib_addr = (char *) mib_a ;
from += 4 ; /* skip index */
len -= 4 ; break ; case 0x4000 : if (port < 0 || port >= smt_mib_phys(smc)) { return SMT_RDF_NOPARAM;
}
mib_p = &smc->mib.p[port_to_mib(smc,port)] ;
mib_addr = (char *) mib_p ;
from += 4 ; /* skip index */
len -= 4 ; break ;
} switch (pa->p_type) { case SMT_P10F0 : case SMT_P10F1 : #ifdef ESS case SMT_P10F2 : case SMT_P10F3 : case SMT_P10F4 : case SMT_P10F5 : case SMT_P10F6 : case SMT_P10F7 : #endif #ifdef SBA case SMT_P10F8 : case SMT_P10F9 : #endif case SMT_P20F1 : if (!local) return SMT_RDF_NOPARAM; break ;
}
pt = smt_get_ptab(pa->p_type) ; if (!pt) return (pa->p_type & 0xff00) ? SMT_RDF_NOPARAM :
SMT_RDF_ILLEGAL; switch (pt->p_access) { case AC_GR : case AC_S : break ; default : return SMT_RDF_ILLEGAL;
}
to = mib_addr + pt->p_offset ;
swap = pt->p_swap ; /* pointer to swap string */
while (swap && (c = *swap++)) { switch(c) { case'b' :
to = (char *) &byte_val ; break ; case'w' :
to = (char *) &word_val ; break ; case'l' :
to = (char *) &long_val ; break ; case'S' : case'E' : case'R' : case'r' : if (len < 4) { goto len_error ;
} if (from[0] | from[1]) goto val_error ; #ifdef LITTLE_ENDIAN if (c == 'r') {
to[0] = from[2] ;
to[1] = from[3] ;
} else {
to[1] = from[2] ;
to[0] = from[3] ;
} #else
to[0] = from[2] ;
to[1] = from[3] ; #endif
from += 4 ;
to += 2 ;
len -= 4 ; break ; case'F' : case'B' : if (len < 4) { goto len_error ;
} if (from[0] | from[1] | from[2]) goto val_error ;
to[0] = from[3] ;
len -= 4 ;
from += 4 ;
to += 4 ; break ; case'C' : case'T' : case'L' : if (len < 4) { goto len_error ;
} #ifdef LITTLE_ENDIAN
to[3] = *from++ ;
to[2] = *from++ ;
to[1] = *from++ ;
to[0] = *from++ ; #else
to[0] = *from++ ;
to[1] = *from++ ;
to[2] = *from++ ;
to[3] = *from++ ; #endif
len -= 4 ;
to += 4 ; break ; case'A' : if (len < 8) goto len_error ; if (set)
memcpy(to,from+2,6) ;
to += 8 ;
from += 8 ;
len -= 8 ; break ; case'4' : if (len < 4) goto len_error ; if (set)
memcpy(to,from,4) ;
to += 4 ;
from += 4 ;
len -= 4 ; break ; case'8' : if (len < 8) goto len_error ; if (set)
memcpy(to,from,8) ;
to += 8 ;
from += 8 ;
len -= 8 ; break ; case'D' : if (len < 32) goto len_error ; if (set)
memcpy(to,from,32) ;
to += 32 ;
from += 32 ;
len -= 32 ; break ; case'P' : /* timestamp is NOT swapped */ if (set) {
to[0] = *from++ ;
to[1] = *from++ ;
to[2] = *from++ ;
to[3] = *from++ ;
to[4] = *from++ ;
to[5] = *from++ ;
to[6] = *from++ ;
to[7] = *from++ ;
}
to += 8 ;
len -= 8 ; break ; default :
SMT_PANIC(smc,SMT_E0120, SMT_E0120_MSG) ; return SMT_RDF_ILLEGAL;
}
} /* * actions and internal updates
*/ switch (pa->p_type) { case SMT_P101A: /* fddiSMTConfigPolicy */ if (word_val & ~1) goto val_error ;
IFSET(mib->fddiSMTConfigPolicy = word_val) ; break ; case SMT_P101B : /* fddiSMTConnectionPolicy */ if (!(word_val & POLICY_MM)) goto val_error ;
IFSET(mib->fddiSMTConnectionPolicy = word_val) ; break ; case SMT_P101D : /* fddiSMTTT_Notify */ if (word_val < 2 || word_val > 30) goto val_error ;
IFSET(mib->fddiSMTTT_Notify = word_val) ; break ; case SMT_P101E : /* fddiSMTStatRptPolicy */ if (byte_val & ~1) goto val_error ;
IFSET(mib->fddiSMTStatRptPolicy = byte_val) ; break ; case SMT_P101F : /* fddiSMTTrace_MaxExpiration */ /* * note: lower limit trace_max = 6.001773... s * NO upper limit
*/ if (long_val < (long)0x478bf51L) goto val_error ;
IFSET(mib->fddiSMTTrace_MaxExpiration = long_val) ; break ; #ifdef ESS case SMT_P10F2 : /* fddiESSPayload */ if (long_val > 1562) goto val_error ; if (set && smc->mib.fddiESSPayload != long_val) {
smc->ess.raf_act_timer_poll = TRUE ;
smc->mib.fddiESSPayload = long_val ;
} break ; case SMT_P10F3 : /* fddiESSOverhead */ if (long_val < 50 || long_val > 5000) goto val_error ; if (set && smc->mib.fddiESSPayload &&
smc->mib.fddiESSOverhead != long_val) {
smc->ess.raf_act_timer_poll = TRUE ;
smc->mib.fddiESSOverhead = long_val ;
} break ; case SMT_P10F4 : /* fddiESSMaxTNeg */ if (long_val > -MS2BCLK(5) || long_val < -MS2BCLK(165)) goto val_error ;
IFSET(mib->fddiESSMaxTNeg = long_val) ; break ; case SMT_P10F5 : /* fddiESSMinSegmentSize */ if (long_val < 1 || long_val > 4478) goto val_error ;
IFSET(mib->fddiESSMinSegmentSize = long_val) ; break ; case SMT_P10F6 : /* fddiESSCategory */ if ((long_val & 0xffff) != 1) goto val_error ;
IFSET(mib->fddiESSCategory = long_val) ; break ; case SMT_P10F7 : /* fddiESSSyncTxMode */ if (word_val > 1) goto val_error ;
IFSET(mib->fddiESSSynchTxMode = word_val) ; break ; #endif #ifdef SBA case SMT_P10F8 : /* fddiSBACommand */ if (byte_val != SB_STOP && byte_val != SB_START) goto val_error ;
IFSET(mib->fddiSBACommand = byte_val) ; break ; case SMT_P10F9 : /* fddiSBAAvailable */ if (byte_val > 100) goto val_error ;
IFSET(mib->fddiSBAAvailable = byte_val) ; break ; #endif case SMT_P2020 : /* fddiMACRequestedPaths */ if ((word_val & (MIB_P_PATH_PRIM_PREFER |
MIB_P_PATH_PRIM_ALTER)) == 0 ) goto val_error ;
IFSET(mib_m->fddiMACRequestedPaths = word_val) ; break ; case SMT_P205F : /* fddiMACFrameErrorThreshold */ /* 0 .. ffff acceptable */
IFSET(mib_m->fddiMACFrameErrorThreshold = word_val) ; break ; case SMT_P2067 : /* fddiMACNotCopiedThreshold */ /* 0 .. ffff acceptable */
IFSET(mib_m->fddiMACNotCopiedThreshold = word_val) ; break ; case SMT_P2076: /* fddiMACMA_UnitdataEnable */ if (byte_val & ~1) goto val_error ; if (set) {
mib_m->fddiMACMA_UnitdataEnable = byte_val ;
queue_event(smc,EVENT_RMT,RM_ENABLE_FLAG) ;
} break ; case SMT_P20F1 : /* fddiMACT_Min */
IFSET(mib_m->fddiMACT_Min = long_val) ; break ; case SMT_P320F : if (long_val > 1562) goto val_error ;
IFSET(mib_a->fddiPATHSbaPayload = long_val) ; #ifdef ESS if (set)
ess_para_change(smc) ; #endif break ; case SMT_P3210 : if (long_val > 5000) goto val_error ;
val_error: /* parameter value in frame is out of range */ return SMT_RDF_RANGE;
len_error: /* parameter value in frame is too short */ return SMT_RDF_LENGTH;
#if 0
no_author_error: /* parameter not setable, because the SBA is not active * Please note: we give the return code 'not authorizeed * because SBA denied is not a valid return code in the * PMF protocol.
*/ return SMT_RDF_AUTHOR; #endif
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.