Back to home page

LXR

 
 

    


0001 /******************************************************************************
0002  *
0003  *  (C)Copyright 1998,1999 SysKonnect,
0004  *  a business unit of Schneider & Koch & Co. Datensysteme GmbH.
0005  *
0006  *  See the file "skfddi.c" for further information.
0007  *
0008  *  This program is free software; you can redistribute it and/or modify
0009  *  it under the terms of the GNU General Public License as published by
0010  *  the Free Software Foundation; either version 2 of the License, or
0011  *  (at your option) any later version.
0012  *
0013  *  The information in this file is provided "AS IS" without warranty.
0014  *
0015  ******************************************************************************/
0016 
0017 /*
0018     Parameter Management Frame processing for SMT 7.2
0019 */
0020 
0021 #include "h/types.h"
0022 #include "h/fddi.h"
0023 #include "h/smc.h"
0024 #include "h/smt_p.h"
0025 
0026 #define KERNEL
0027 #include "h/smtstate.h"
0028 
0029 #ifndef SLIM_SMT
0030 
0031 #ifndef lint
0032 static const char ID_sccs[] = "@(#)pmf.c    1.37 97/08/04 (C) SK " ;
0033 #endif
0034 
0035 static int smt_authorize(struct s_smc *smc, struct smt_header *sm);
0036 static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm);
0037 static const struct s_p_tab* smt_get_ptab(u_short para);
0038 static int smt_mib_phys(struct s_smc *smc);
0039 static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
0040             int local, int set);
0041 void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
0042           int index, int local);
0043 static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
0044                      int set, int local);
0045 static int port_to_mib(struct s_smc *smc, int p);
0046 
0047 #define MOFFSS(e)   offsetof(struct fddi_mib, e)
0048 #define MOFFMS(e)   offsetof(struct fddi_mib_m, e)
0049 #define MOFFAS(e)   offsetof(struct fddi_mib_a, e)
0050 #define MOFFPS(e)   offsetof(struct fddi_mib_p, e)
0051 
0052 
0053 #define AC_G    0x01        /* Get */
0054 #define AC_GR   0x02        /* Get/Set */
0055 #define AC_S    0x04        /* Set */
0056 #define AC_NA   0x08
0057 #define AC_GROUP    0x10        /* Group */
0058 #define MS2BCLK(x)  ((x)*12500L)
0059 /*
0060     F   LFag (byte)
0061     B   byte
0062     S   u_short 16 bit
0063     C   Counter 32 bit
0064     L   Long 32 bit
0065     T   Timer_2 32 bit
0066     P   TimeStamp ;
0067     A   LongAddress (6 byte)
0068     E   Enum 16 bit
0069     R   ResId 16 Bit
0070 */
0071 static const struct s_p_tab {
0072     u_short p_num ;     /* parameter code */
0073     u_char  p_access ;  /* access rights */
0074     u_short p_offset ;  /* offset in mib */
0075     char    p_swap[3] ; /* format string */
0076 } p_tab[] = {
0077     /* StationIdGrp */
0078     { SMT_P100A,AC_GROUP    } ,
0079     { SMT_P100B,AC_G,   MOFFSS(fddiSMTStationId),   "8" } ,
0080     { SMT_P100D,AC_G,   MOFFSS(fddiSMTOpVersionId), "S" } ,
0081     { SMT_P100E,AC_G,   MOFFSS(fddiSMTHiVersionId), "S" } ,
0082     { SMT_P100F,AC_G,   MOFFSS(fddiSMTLoVersionId), "S" } ,
0083     { SMT_P1010,AC_G,   MOFFSS(fddiSMTManufacturerData), "D" } ,
0084     { SMT_P1011,AC_GR,  MOFFSS(fddiSMTUserData),    "D" } ,
0085     { SMT_P1012,AC_G,   MOFFSS(fddiSMTMIBVersionId),    "S" } ,
0086 
0087     /* StationConfigGrp */
0088     { SMT_P1014,AC_GROUP    } ,
0089     { SMT_P1015,AC_G,   MOFFSS(fddiSMTMac_Ct),      "B" } ,
0090     { SMT_P1016,AC_G,   MOFFSS(fddiSMTNonMaster_Ct),    "B" } ,
0091     { SMT_P1017,AC_G,   MOFFSS(fddiSMTMaster_Ct),   "B" } ,
0092     { SMT_P1018,AC_G,   MOFFSS(fddiSMTAvailablePaths),  "B" } ,
0093     { SMT_P1019,AC_G,   MOFFSS(fddiSMTConfigCapabilities),"S"   } ,
0094     { SMT_P101A,AC_GR,  MOFFSS(fddiSMTConfigPolicy),    "wS"    } ,
0095     { SMT_P101B,AC_GR,  MOFFSS(fddiSMTConnectionPolicy),"wS"    } ,
0096     { SMT_P101D,AC_GR,  MOFFSS(fddiSMTTT_Notify),   "wS"    } ,
0097     { SMT_P101E,AC_GR,  MOFFSS(fddiSMTStatRptPolicy),   "bB"    } ,
0098     { SMT_P101F,AC_GR,  MOFFSS(fddiSMTTrace_MaxExpiration),"lL" } ,
0099     { SMT_P1020,AC_G,   MOFFSS(fddiSMTPORTIndexes), "II"    } ,
0100     { SMT_P1021,AC_G,   MOFFSS(fddiSMTMACIndexes),  "I" } ,
0101     { SMT_P1022,AC_G,   MOFFSS(fddiSMTBypassPresent),   "F" } ,
0102 
0103     /* StatusGrp */
0104     { SMT_P1028,AC_GROUP    } ,
0105     { SMT_P1029,AC_G,   MOFFSS(fddiSMTECMState),    "E" } ,
0106     { SMT_P102A,AC_G,   MOFFSS(fddiSMTCF_State),    "E" } ,
0107     { SMT_P102C,AC_G,   MOFFSS(fddiSMTRemoteDisconnectFlag),"F" } ,
0108     { SMT_P102D,AC_G,   MOFFSS(fddiSMTStationStatus),   "E" } ,
0109     { SMT_P102E,AC_G,   MOFFSS(fddiSMTPeerWrapFlag),    "F" } ,
0110 
0111     /* MIBOperationGrp */
0112     { SMT_P1032,AC_GROUP    } ,
0113     { SMT_P1033,AC_G,   MOFFSS(fddiSMTTimeStamp),"P"        } ,
0114     { SMT_P1034,AC_G,   MOFFSS(fddiSMTTransitionTimeStamp),"P"  } ,
0115     /* NOTE : SMT_P1035 is already swapped ! SMT_P_SETCOUNT */
0116     { SMT_P1035,AC_G,   MOFFSS(fddiSMTSetCount),"4P"        } ,
0117     { SMT_P1036,AC_G,   MOFFSS(fddiSMTLastSetStationId),"8" } ,
0118 
0119     { SMT_P103C,AC_S,   0,              "wS"    } ,
0120 
0121     /*
0122      * PRIVATE EXTENSIONS
0123      * only accessible locally to get/set passwd
0124      */
0125     { SMT_P10F0,AC_GR,  MOFFSS(fddiPRPMFPasswd),    "8" } ,
0126     { SMT_P10F1,AC_GR,  MOFFSS(fddiPRPMFStation),   "8" } ,
0127 #ifdef  ESS
0128     { SMT_P10F2,AC_GR,  MOFFSS(fddiESSPayload),     "lL"    } ,
0129     { SMT_P10F3,AC_GR,  MOFFSS(fddiESSOverhead),    "lL"    } ,
0130     { SMT_P10F4,AC_GR,  MOFFSS(fddiESSMaxTNeg),     "lL"    } ,
0131     { SMT_P10F5,AC_GR,  MOFFSS(fddiESSMinSegmentSize),  "lL"    } ,
0132     { SMT_P10F6,AC_GR,  MOFFSS(fddiESSCategory),    "lL"    } ,
0133     { SMT_P10F7,AC_GR,  MOFFSS(fddiESSSynchTxMode), "wS"    } ,
0134 #endif
0135 #ifdef  SBA
0136     { SMT_P10F8,AC_GR,  MOFFSS(fddiSBACommand),     "bF"    } ,
0137     { SMT_P10F9,AC_GR,  MOFFSS(fddiSBAAvailable),   "bF"    } ,
0138 #endif
0139     /* MAC Attributes */
0140     { SMT_P200A,AC_GROUP    } ,
0141     { SMT_P200B,AC_G,   MOFFMS(fddiMACFrameStatusFunctions),"S" } ,
0142     { SMT_P200D,AC_G,   MOFFMS(fddiMACT_MaxCapabilitiy),"T" } ,
0143     { SMT_P200E,AC_G,   MOFFMS(fddiMACTVXCapabilitiy),"T"   } ,
0144 
0145     /* ConfigGrp */
0146     { SMT_P2014,AC_GROUP    } ,
0147     { SMT_P2016,AC_G,   MOFFMS(fddiMACAvailablePaths),  "B" } ,
0148     { SMT_P2017,AC_G,   MOFFMS(fddiMACCurrentPath), "S" } ,
0149     { SMT_P2018,AC_G,   MOFFMS(fddiMACUpstreamNbr), "A" } ,
0150     { SMT_P2019,AC_G,   MOFFMS(fddiMACDownstreamNbr),   "A" } ,
0151     { SMT_P201A,AC_G,   MOFFMS(fddiMACOldUpstreamNbr),  "A" } ,
0152     { SMT_P201B,AC_G,   MOFFMS(fddiMACOldDownstreamNbr),"A" } ,
0153     { SMT_P201D,AC_G,   MOFFMS(fddiMACDupAddressTest),  "E" } ,
0154     { SMT_P2020,AC_GR,  MOFFMS(fddiMACRequestedPaths),  "wS"    } ,
0155     { SMT_P2021,AC_G,   MOFFMS(fddiMACDownstreamPORTType),"E"   } ,
0156     { SMT_P2022,AC_G,   MOFFMS(fddiMACIndex),       "S" } ,
0157 
0158     /* AddressGrp */
0159     { SMT_P2028,AC_GROUP    } ,
0160     { SMT_P2029,AC_G,   MOFFMS(fddiMACSMTAddress),  "A" } ,
0161 
0162     /* OperationGrp */
0163     { SMT_P2032,AC_GROUP    } ,
0164     { SMT_P2033,AC_G,   MOFFMS(fddiMACT_Req),       "T" } ,
0165     { SMT_P2034,AC_G,   MOFFMS(fddiMACT_Neg),       "T" } ,
0166     { SMT_P2035,AC_G,   MOFFMS(fddiMACT_Max),       "T" } ,
0167     { SMT_P2036,AC_G,   MOFFMS(fddiMACTvxValue),    "T" } ,
0168     { SMT_P2038,AC_G,   MOFFMS(fddiMACT_Pri0),      "T" } ,
0169     { SMT_P2039,AC_G,   MOFFMS(fddiMACT_Pri1),      "T" } ,
0170     { SMT_P203A,AC_G,   MOFFMS(fddiMACT_Pri2),      "T" } ,
0171     { SMT_P203B,AC_G,   MOFFMS(fddiMACT_Pri3),      "T" } ,
0172     { SMT_P203C,AC_G,   MOFFMS(fddiMACT_Pri4),      "T" } ,
0173     { SMT_P203D,AC_G,   MOFFMS(fddiMACT_Pri5),      "T" } ,
0174     { SMT_P203E,AC_G,   MOFFMS(fddiMACT_Pri6),      "T" } ,
0175 
0176 
0177     /* CountersGrp */
0178     { SMT_P2046,AC_GROUP    } ,
0179     { SMT_P2047,AC_G,   MOFFMS(fddiMACFrame_Ct),    "C" } ,
0180     { SMT_P2048,AC_G,   MOFFMS(fddiMACCopied_Ct),   "C" } ,
0181     { SMT_P2049,AC_G,   MOFFMS(fddiMACTransmit_Ct), "C" } ,
0182     { SMT_P204A,AC_G,   MOFFMS(fddiMACToken_Ct),    "C" } ,
0183     { SMT_P2051,AC_G,   MOFFMS(fddiMACError_Ct),    "C" } ,
0184     { SMT_P2052,AC_G,   MOFFMS(fddiMACLost_Ct),     "C" } ,
0185     { SMT_P2053,AC_G,   MOFFMS(fddiMACTvxExpired_Ct),   "C" } ,
0186     { SMT_P2054,AC_G,   MOFFMS(fddiMACNotCopied_Ct),    "C" } ,
0187     { SMT_P2056,AC_G,   MOFFMS(fddiMACRingOp_Ct),   "C" } ,
0188 
0189     /* FrameErrorConditionGrp */
0190     { SMT_P205A,AC_GROUP    } ,
0191     { SMT_P205F,AC_GR,  MOFFMS(fddiMACFrameErrorThreshold),"wS" } ,
0192     { SMT_P2060,AC_G,   MOFFMS(fddiMACFrameErrorRatio), "S" } ,
0193 
0194     /* NotCopiedConditionGrp */
0195     { SMT_P2064,AC_GROUP    } ,
0196     { SMT_P2067,AC_GR,  MOFFMS(fddiMACNotCopiedThreshold),"wS"  } ,
0197     { SMT_P2069,AC_G,   MOFFMS(fddiMACNotCopiedRatio),  "S" } ,
0198 
0199     /* StatusGrp */
0200     { SMT_P206E,AC_GROUP    } ,
0201     { SMT_P206F,AC_G,   MOFFMS(fddiMACRMTState),    "S" } ,
0202     { SMT_P2070,AC_G,   MOFFMS(fddiMACDA_Flag), "F" } ,
0203     { SMT_P2071,AC_G,   MOFFMS(fddiMACUNDA_Flag),   "F" } ,
0204     { SMT_P2072,AC_G,   MOFFMS(fddiMACFrameErrorFlag),  "F" } ,
0205     { SMT_P2073,AC_G,   MOFFMS(fddiMACNotCopiedFlag),   "F" } ,
0206     { SMT_P2074,AC_G,   MOFFMS(fddiMACMA_UnitdataAvailable),"F" } ,
0207     { SMT_P2075,AC_G,   MOFFMS(fddiMACHardwarePresent), "F" } ,
0208     { SMT_P2076,AC_GR,  MOFFMS(fddiMACMA_UnitdataEnable),"bF"   } ,
0209 
0210     /*
0211      * PRIVATE EXTENSIONS
0212      * only accessible locally to get/set TMIN
0213      */
0214     { SMT_P20F0,AC_NA                       } ,
0215     { SMT_P20F1,AC_GR,  MOFFMS(fddiMACT_Min),       "lT"    } ,
0216 
0217     /* Path Attributes */
0218     /*
0219      * DON't swap 320B,320F,3210: they are already swapped in swap_para()
0220      */
0221     { SMT_P320A,AC_GROUP    } ,
0222     { SMT_P320B,AC_G,   MOFFAS(fddiPATHIndex),      "r" } ,
0223     { SMT_P320F,AC_GR,  MOFFAS(fddiPATHSbaPayload), "l4"    } ,
0224     { SMT_P3210,AC_GR,  MOFFAS(fddiPATHSbaOverhead),    "l4"    } ,
0225     /* fddiPATHConfiguration */
0226     { SMT_P3212,AC_G,   0,              ""  } ,
0227     { SMT_P3213,AC_GR,  MOFFAS(fddiPATHT_Rmode),    "lT"    } ,
0228     { SMT_P3214,AC_GR,  MOFFAS(fddiPATHSbaAvailable),   "lL"    } ,
0229     { SMT_P3215,AC_GR,  MOFFAS(fddiPATHTVXLowerBound),  "lT"    } ,
0230     { SMT_P3216,AC_GR,  MOFFAS(fddiPATHT_MaxLowerBound),"lT"    } ,
0231     { SMT_P3217,AC_GR,  MOFFAS(fddiPATHMaxT_Req),   "lT"    } ,
0232 
0233     /* Port Attributes */
0234     /* ConfigGrp */
0235     { SMT_P400A,AC_GROUP    } ,
0236     { SMT_P400C,AC_G,   MOFFPS(fddiPORTMy_Type),    "E" } ,
0237     { SMT_P400D,AC_G,   MOFFPS(fddiPORTNeighborType),   "E" } ,
0238     { SMT_P400E,AC_GR,  MOFFPS(fddiPORTConnectionPolicies),"bB" } ,
0239     { SMT_P400F,AC_G,   MOFFPS(fddiPORTMacIndicated),   "2" } ,
0240     { SMT_P4010,AC_G,   MOFFPS(fddiPORTCurrentPath),    "E" } ,
0241     { SMT_P4011,AC_GR,  MOFFPS(fddiPORTRequestedPaths), "l4"    } ,
0242     { SMT_P4012,AC_G,   MOFFPS(fddiPORTMACPlacement),   "S" } ,
0243     { SMT_P4013,AC_G,   MOFFPS(fddiPORTAvailablePaths), "B" } ,
0244     { SMT_P4016,AC_G,   MOFFPS(fddiPORTPMDClass),   "E" } ,
0245     { SMT_P4017,AC_G,   MOFFPS(fddiPORTConnectionCapabilities), "B"} ,
0246     { SMT_P401D,AC_G,   MOFFPS(fddiPORTIndex),      "R" } ,
0247 
0248     /* OperationGrp */
0249     { SMT_P401E,AC_GROUP    } ,
0250     { SMT_P401F,AC_GR,  MOFFPS(fddiPORTMaint_LS),   "wE"    } ,
0251     { SMT_P4021,AC_G,   MOFFPS(fddiPORTBS_Flag),    "F" } ,
0252     { SMT_P4022,AC_G,   MOFFPS(fddiPORTPC_LS),      "E" } ,
0253 
0254     /* ErrorCtrsGrp */
0255     { SMT_P4028,AC_GROUP    } ,
0256     { SMT_P4029,AC_G,   MOFFPS(fddiPORTEBError_Ct), "C" } ,
0257     { SMT_P402A,AC_G,   MOFFPS(fddiPORTLCTFail_Ct), "C" } ,
0258 
0259     /* LerGrp */
0260     { SMT_P4032,AC_GROUP    } ,
0261     { SMT_P4033,AC_G,   MOFFPS(fddiPORTLer_Estimate),   "F" } ,
0262     { SMT_P4034,AC_G,   MOFFPS(fddiPORTLem_Reject_Ct),  "C" } ,
0263     { SMT_P4035,AC_G,   MOFFPS(fddiPORTLem_Ct),     "C" } ,
0264     { SMT_P403A,AC_GR,  MOFFPS(fddiPORTLer_Cutoff), "bB"    } ,
0265     { SMT_P403B,AC_GR,  MOFFPS(fddiPORTLer_Alarm),  "bB"    } ,
0266 
0267     /* StatusGrp */
0268     { SMT_P403C,AC_GROUP    } ,
0269     { SMT_P403D,AC_G,   MOFFPS(fddiPORTConnectState),   "E" } ,
0270     { SMT_P403E,AC_G,   MOFFPS(fddiPORTPCMStateX),  "E" } ,
0271     { SMT_P403F,AC_G,   MOFFPS(fddiPORTPC_Withhold),    "E" } ,
0272     { SMT_P4040,AC_G,   MOFFPS(fddiPORTLerFlag),    "F" } ,
0273     { SMT_P4041,AC_G,   MOFFPS(fddiPORTHardwarePresent),"F" } ,
0274 
0275     { SMT_P4046,AC_S,   0,              "wS"    } ,
0276 
0277     { 0,    AC_GROUP    } ,
0278     { 0 }
0279 } ;
0280 
0281 void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local)
0282 {
0283     struct smt_header   *sm ;
0284     SMbuf       *reply ;
0285 
0286     sm = smtod(mb,struct smt_header *) ;
0287     DB_SMT("SMT: processing PMF frame at %p len %d\n",sm,mb->sm_len) ;
0288 #ifdef  DEBUG
0289     dump_smt(smc,sm,"PMF Received") ;
0290 #endif
0291     /*
0292      * Start the watchdog: It may be a long, long packet and
0293      * maybe the watchdog occurs ...
0294      */
0295     smt_start_watchdog(smc) ;
0296 
0297     if (sm->smt_class == SMT_PMF_GET ||
0298         sm->smt_class == SMT_PMF_SET) {
0299         reply = smt_build_pmf_response(smc,sm,
0300             sm->smt_class == SMT_PMF_SET,local) ;
0301         if (reply) {
0302             sm = smtod(reply,struct smt_header *) ;
0303 #ifdef  DEBUG
0304             dump_smt(smc,sm,"PMF Reply") ;
0305 #endif
0306             smt_send_frame(smc,reply,FC_SMT_INFO,local) ;
0307         }
0308     }
0309 }
0310 
0311 static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
0312                      int set, int local)
0313 {
0314     SMbuf           *mb ;
0315     struct smt_header   *smt ;
0316     struct smt_para     *pa ;
0317     struct smt_p_reason *res ;
0318     const struct s_p_tab    *pt ;
0319     int         len ;
0320     int         index ;
0321     int         idx_end ;
0322     int         error ;
0323     int         range ;
0324     SK_LOC_DECL(struct s_pcon,pcon) ;
0325     SK_LOC_DECL(struct s_pcon,set_pcon) ;
0326 
0327     /*
0328      * build SMT header
0329      */
0330     if (!(mb = smt_get_mbuf(smc)))
0331         return mb;
0332 
0333     smt = smtod(mb, struct smt_header *) ;
0334     smt->smt_dest = req->smt_source ;   /* DA == source of request */
0335     smt->smt_class = req->smt_class ;   /* same class (GET/SET) */
0336     smt->smt_type = SMT_REPLY ;
0337     smt->smt_version = SMT_VID_2 ;
0338     smt->smt_tid = req->smt_tid ;       /* same TID */
0339     smt->smt_pad = 0 ;
0340     smt->smt_len = 0 ;
0341 
0342     /*
0343      * setup parameter status
0344      */
0345     pcon.pc_len = SMT_MAX_INFO_LEN ;    /* max para length */
0346     pcon.pc_err = 0 ;           /* no error */
0347     pcon.pc_badset = 0 ;            /* no bad set count */
0348     pcon.pc_p = (void *) (smt + 1) ;    /* paras start here */
0349 
0350     /*
0351      * check authoriziation and set count
0352      */
0353     error = 0 ;
0354     if (set) {
0355         if (!local && smt_authorize(smc,req))
0356             error = SMT_RDF_AUTHOR ;
0357         else if (smt_check_set_count(smc,req))
0358             pcon.pc_badset = SMT_RDF_BADSET ;
0359     }
0360     /*
0361      * add reason code and all mandatory parameters
0362      */
0363     res = (struct smt_p_reason *) pcon.pc_p ;
0364     smt_add_para(smc,&pcon,(u_short) SMT_P_REASON,0,0) ;
0365     smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
0366     /* update 1035 and 1036 later if set */
0367     set_pcon = pcon ;
0368     smt_add_para(smc,&pcon,(u_short) SMT_P1035,0,0) ;
0369     smt_add_para(smc,&pcon,(u_short) SMT_P1036,0,0) ;
0370 
0371     pcon.pc_err = error ;
0372     len = req->smt_len ;
0373     pa = (struct smt_para *) (req + 1) ;
0374     /*
0375      * process list of paras
0376      */
0377     while (!pcon.pc_err && len > 0 ) {
0378         if (((u_short)len < pa->p_len + PARA_LEN) || (pa->p_len & 3)) {
0379             pcon.pc_err = SMT_RDF_LENGTH ;
0380             break ;
0381         }
0382 
0383         if (((range = (pa->p_type & 0xf000)) == 0x2000) ||
0384             range == 0x3000 || range == 0x4000) {
0385             /*
0386              * get index for PART,MAC ad PATH group
0387              */
0388             index = *((u_char *)pa + PARA_LEN + 3) ;/* index */
0389             idx_end = index ;
0390             if (!set && (pa->p_len != 4)) {
0391                 pcon.pc_err = SMT_RDF_LENGTH ;
0392                 break ;
0393             }
0394             if (!index && !set) {
0395                 switch (range) {
0396                 case 0x2000 :
0397                     index = INDEX_MAC ;
0398                     idx_end = index - 1 + NUMMACS ;
0399                     break ;
0400                 case 0x3000 :
0401                     index = INDEX_PATH ;
0402                     idx_end = index - 1 + NUMPATHS ;
0403                     break ;
0404                 case 0x4000 :
0405                     index = INDEX_PORT ;
0406                     idx_end = index - 1 + NUMPHYS ;
0407 #ifndef CONCENTRATOR
0408                     if (smc->s.sas == SMT_SAS)
0409                         idx_end = INDEX_PORT ;
0410 #endif
0411                     break ;
0412                 }
0413             }
0414         }
0415         else {
0416             /*
0417              * smt group has no index
0418              */
0419             if (!set && (pa->p_len != 0)) {
0420                 pcon.pc_err = SMT_RDF_LENGTH ;
0421                 break ;
0422             }
0423             index = 0 ;
0424             idx_end = 0 ;
0425         }
0426         while (index <= idx_end) {
0427             /*
0428              * if group
0429              *  add all paras of group
0430              */
0431             pt = smt_get_ptab(pa->p_type) ;
0432             if (pt && pt->p_access == AC_GROUP && !set) {
0433                 pt++ ;
0434                 while (pt->p_access == AC_G ||
0435                     pt->p_access == AC_GR) {
0436                     smt_add_para(smc,&pcon,pt->p_num,
0437                         index,local);
0438                     pt++ ;
0439                 }
0440             }
0441             /*
0442              * ignore
0443              *  AUTHORIZATION in get/set
0444              *  SET COUNT in set
0445              */
0446             else if (pa->p_type != SMT_P_AUTHOR &&
0447                  (!set || (pa->p_type != SMT_P1035))) {
0448                 int st ;
0449                 if (pcon.pc_badset) {
0450                     smt_add_para(smc,&pcon,pa->p_type,
0451                         index,local) ;
0452                 }
0453                 else if (set) {
0454                     st = smt_set_para(smc,pa,index,local,1);
0455                     /*
0456                      * return para even if error
0457                      */
0458                     smt_add_para(smc,&pcon,pa->p_type,
0459                         index,local) ;
0460                     pcon.pc_err = st ;
0461                 }
0462                 else {
0463                     if (pt && pt->p_access == AC_S) {
0464                         pcon.pc_err =
0465                             SMT_RDF_ILLEGAL ;
0466                     }
0467                     smt_add_para(smc,&pcon,pa->p_type,
0468                         index,local) ;
0469                 }
0470             }
0471             if (pcon.pc_err)
0472                 break ;
0473             index++ ;
0474         }
0475         len -= pa->p_len + PARA_LEN ;
0476         pa = (struct smt_para *) ((char *)pa + pa->p_len + PARA_LEN) ;
0477     }
0478     smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
0479     mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
0480 
0481     /* update reason code */
0482     res->rdf_reason = pcon.pc_badset ? pcon.pc_badset :
0483             pcon.pc_err ? pcon.pc_err : SMT_RDF_SUCCESS ;
0484     if (set && (res->rdf_reason == SMT_RDF_SUCCESS)) {
0485         /*
0486          * increment set count
0487          * set time stamp
0488          * store station id of last set
0489          */
0490         smc->mib.fddiSMTSetCount.count++ ;
0491         smt_set_timestamp(smc,smc->mib.fddiSMTSetCount.timestamp) ;
0492         smc->mib.fddiSMTLastSetStationId = req->smt_sid ;
0493         smt_add_para(smc,&set_pcon,(u_short) SMT_P1035,0,0) ;
0494         smt_add_para(smc,&set_pcon,(u_short) SMT_P1036,0,0) ;
0495     }
0496     return mb;
0497 }
0498 
0499 static int smt_authorize(struct s_smc *smc, struct smt_header *sm)
0500 {
0501     struct smt_para *pa ;
0502     int     i ;
0503     char        *p ;
0504 
0505     /*
0506      * check source station id if not zero
0507      */
0508     p = (char *) &smc->mib.fddiPRPMFStation ;
0509     for (i = 0 ; i < 8 && !p[i] ; i++)
0510         ;
0511     if (i != 8) {
0512         if (memcmp((char *) &sm->smt_sid,
0513             (char *) &smc->mib.fddiPRPMFStation,8))
0514             return 1;
0515     }
0516     /*
0517      * check authoriziation parameter if passwd not zero
0518      */
0519     p = (char *) smc->mib.fddiPRPMFPasswd ;
0520     for (i = 0 ; i < 8 && !p[i] ; i++)
0521         ;
0522     if (i != 8) {
0523         pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P_AUTHOR) ;
0524         if (!pa)
0525             return 1;
0526         if (pa->p_len != 8)
0527             return 1;
0528         if (memcmp((char *)(pa+1),(char *)smc->mib.fddiPRPMFPasswd,8))
0529             return 1;
0530     }
0531     return 0;
0532 }
0533 
0534 static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm)
0535 {
0536     struct smt_para *pa ;
0537     struct smt_p_setcount   *sc ;
0538 
0539     pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P1035) ;
0540     if (pa) {
0541         sc = (struct smt_p_setcount *) pa ;
0542         if ((smc->mib.fddiSMTSetCount.count != sc->count) ||
0543             memcmp((char *) smc->mib.fddiSMTSetCount.timestamp,
0544             (char *)sc->timestamp,8))
0545             return 1;
0546     }
0547     return 0;
0548 }
0549 
0550 void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
0551           int index, int local)
0552 {
0553     struct smt_para *pa ;
0554     const struct s_p_tab    *pt ;
0555     struct fddi_mib_m *mib_m = NULL;
0556     struct fddi_mib_p *mib_p = NULL;
0557     int     len ;
0558     int     plen ;
0559     char        *from ;
0560     char        *to ;
0561     const char  *swap ;
0562     char        c ;
0563     int     range ;
0564     char        *mib_addr ;
0565     int     mac ;
0566     int     path ;
0567     int     port ;
0568     int     sp_len ;
0569 
0570     /*
0571      * skip if error
0572      */
0573     if (pcon->pc_err)
0574         return ;
0575 
0576     /*
0577      * actions don't have a value
0578      */
0579     pt = smt_get_ptab(para) ;
0580     if (pt && pt->p_access == AC_S)
0581         return ;
0582 
0583     to = (char *) (pcon->pc_p) ;    /* destination pointer */
0584     len = pcon->pc_len ;        /* free space */
0585     plen = len ;            /* remember start length */
0586     pa = (struct smt_para *) to ;   /* type/length pointer */
0587     to += PARA_LEN ;        /* skip smt_para */
0588     len -= PARA_LEN ;
0589     /*
0590      * set index if required
0591      */
0592     if (((range = (para & 0xf000)) == 0x2000) ||
0593         range == 0x3000 || range == 0x4000) {
0594         if (len < 4)
0595             goto wrong_error ;
0596         to[0] = 0 ;
0597         to[1] = 0 ;
0598         to[2] = 0 ;
0599         to[3] = index ;
0600         len -= 4 ;
0601         to += 4 ;
0602     }
0603     mac = index - INDEX_MAC ;
0604     path = index - INDEX_PATH ;
0605     port = index - INDEX_PORT ;
0606     /*
0607      * get pointer to mib
0608      */
0609     switch (range) {
0610     case 0x1000 :
0611     default :
0612         mib_addr = (char *) (&smc->mib) ;
0613         break ;
0614     case 0x2000 :
0615         if (mac < 0 || mac >= NUMMACS) {
0616             pcon->pc_err = SMT_RDF_NOPARAM ;
0617             return ;
0618         }
0619         mib_addr = (char *) (&smc->mib.m[mac]) ;
0620         mib_m = (struct fddi_mib_m *) mib_addr ;
0621         break ;
0622     case 0x3000 :
0623         if (path < 0 || path >= NUMPATHS) {
0624             pcon->pc_err = SMT_RDF_NOPARAM ;
0625             return ;
0626         }
0627         mib_addr = (char *) (&smc->mib.a[path]) ;
0628         break ;
0629     case 0x4000 :
0630         if (port < 0 || port >= smt_mib_phys(smc)) {
0631             pcon->pc_err = SMT_RDF_NOPARAM ;
0632             return ;
0633         }
0634         mib_addr = (char *) (&smc->mib.p[port_to_mib(smc,port)]) ;
0635         mib_p = (struct fddi_mib_p *) mib_addr ;
0636         break ;
0637     }
0638     /*
0639      * check special paras
0640      */
0641     swap = NULL;
0642     switch (para) {
0643     case SMT_P10F0 :
0644     case SMT_P10F1 :
0645 #ifdef  ESS
0646     case SMT_P10F2 :
0647     case SMT_P10F3 :
0648     case SMT_P10F4 :
0649     case SMT_P10F5 :
0650     case SMT_P10F6 :
0651     case SMT_P10F7 :
0652 #endif
0653 #ifdef  SBA
0654     case SMT_P10F8 :
0655     case SMT_P10F9 :
0656 #endif
0657     case SMT_P20F1 :
0658         if (!local) {
0659             pcon->pc_err = SMT_RDF_NOPARAM ;
0660             return ;
0661         }
0662         break ;
0663     case SMT_P2034 :
0664     case SMT_P2046 :
0665     case SMT_P2047 :
0666     case SMT_P204A :
0667     case SMT_P2051 :
0668     case SMT_P2052 :
0669         mac_update_counter(smc) ;
0670         break ;
0671     case SMT_P4022:
0672         mib_p->fddiPORTPC_LS = LS2MIB(
0673             sm_pm_get_ls(smc,port_to_mib(smc,port))) ;
0674         break ;
0675     case SMT_P_REASON :
0676         *(u32 *)to = 0 ;
0677         sp_len = 4 ;
0678         goto sp_done ;
0679     case SMT_P1033 :            /* time stamp */
0680         smt_set_timestamp(smc,smc->mib.fddiSMTTimeStamp) ;
0681         break ;
0682 
0683     case SMT_P1020:             /* port indexes */
0684 #if NUMPHYS == 12
0685         swap = "IIIIIIIIIIII" ;
0686 #else
0687 #if NUMPHYS == 2
0688         if (smc->s.sas == SMT_SAS)
0689             swap = "I" ;
0690         else
0691             swap = "II" ;
0692 #else
0693 #if NUMPHYS == 24
0694         swap = "IIIIIIIIIIIIIIIIIIIIIIII" ;
0695 #else
0696     ????
0697 #endif
0698 #endif
0699 #endif
0700         break ;
0701     case SMT_P3212 :
0702         {
0703             sp_len = cem_build_path(smc,to,path) ;
0704             goto sp_done ;
0705         }
0706     case SMT_P1048 :        /* peer wrap condition */
0707         {
0708             struct smt_p_1048   *sp ;
0709             sp = (struct smt_p_1048 *) to ;
0710             sp->p1048_flag = smc->mib.fddiSMTPeerWrapFlag ;
0711             sp->p1048_cf_state = smc->mib.fddiSMTCF_State ;
0712             sp_len = sizeof(struct smt_p_1048) ;
0713             goto sp_done ;
0714         }
0715     case SMT_P208C :
0716         {
0717             struct smt_p_208c   *sp ;
0718             sp = (struct smt_p_208c *) to ;
0719             sp->p208c_flag =
0720                 smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
0721             sp->p208c_dupcondition =
0722                 (mib_m->fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0) |
0723                 (mib_m->fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0);
0724             sp->p208c_fddilong =
0725                 mib_m->fddiMACSMTAddress ;
0726             sp->p208c_fddiunalong =
0727                 mib_m->fddiMACUpstreamNbr ;
0728             sp->p208c_pad = 0 ;
0729             sp_len = sizeof(struct smt_p_208c) ;
0730             goto sp_done ;
0731         }
0732     case SMT_P208D :        /* frame error condition */
0733         {
0734             struct smt_p_208d   *sp ;
0735             sp = (struct smt_p_208d *) to ;
0736             sp->p208d_flag =
0737                 mib_m->fddiMACFrameErrorFlag ;
0738             sp->p208d_frame_ct =
0739                 mib_m->fddiMACFrame_Ct ;
0740             sp->p208d_error_ct =
0741                 mib_m->fddiMACError_Ct ;
0742             sp->p208d_lost_ct =
0743                 mib_m->fddiMACLost_Ct ;
0744             sp->p208d_ratio =
0745                 mib_m->fddiMACFrameErrorRatio ;
0746             sp_len = sizeof(struct smt_p_208d) ;
0747             goto sp_done ;
0748         }
0749     case SMT_P208E :        /* not copied condition */
0750         {
0751             struct smt_p_208e   *sp ;
0752             sp = (struct smt_p_208e *) to ;
0753             sp->p208e_flag =
0754                 mib_m->fddiMACNotCopiedFlag ;
0755             sp->p208e_not_copied =
0756                 mib_m->fddiMACNotCopied_Ct ;
0757             sp->p208e_copied =
0758                 mib_m->fddiMACCopied_Ct ;
0759             sp->p208e_not_copied_ratio =
0760                 mib_m->fddiMACNotCopiedRatio ;
0761             sp_len = sizeof(struct smt_p_208e) ;
0762             goto sp_done ;
0763         }
0764     case SMT_P208F :    /* neighbor change event */
0765         {
0766             struct smt_p_208f   *sp ;
0767             sp = (struct smt_p_208f *) to ;
0768             sp->p208f_multiple =
0769                 mib_m->fddiMACMultiple_N ;
0770             sp->p208f_nacondition =
0771                 mib_m->fddiMACDuplicateAddressCond ;
0772             sp->p208f_old_una =
0773                 mib_m->fddiMACOldUpstreamNbr ;
0774             sp->p208f_new_una =
0775                 mib_m->fddiMACUpstreamNbr ;
0776             sp->p208f_old_dna =
0777                 mib_m->fddiMACOldDownstreamNbr ;
0778             sp->p208f_new_dna =
0779                 mib_m->fddiMACDownstreamNbr ;
0780             sp->p208f_curren_path =
0781                 mib_m->fddiMACCurrentPath ;
0782             sp->p208f_smt_address =
0783                 mib_m->fddiMACSMTAddress ;
0784             sp_len = sizeof(struct smt_p_208f) ;
0785             goto sp_done ;
0786         }
0787     case SMT_P2090 :
0788         {
0789             struct smt_p_2090   *sp ;
0790             sp = (struct smt_p_2090 *) to ;
0791             sp->p2090_multiple =
0792                 mib_m->fddiMACMultiple_P ;
0793             sp->p2090_availablepaths =
0794                 mib_m->fddiMACAvailablePaths ;
0795             sp->p2090_currentpath =
0796                 mib_m->fddiMACCurrentPath ;
0797             sp->p2090_requestedpaths =
0798                 mib_m->fddiMACRequestedPaths ;
0799             sp_len = sizeof(struct smt_p_2090) ;
0800             goto sp_done ;
0801         }
0802     case SMT_P4050 :
0803         {
0804             struct smt_p_4050   *sp ;
0805             sp = (struct smt_p_4050 *) to ;
0806             sp->p4050_flag =
0807                 mib_p->fddiPORTLerFlag ;
0808             sp->p4050_pad = 0 ;
0809             sp->p4050_cutoff =
0810                 mib_p->fddiPORTLer_Cutoff ;
0811             sp->p4050_alarm =
0812                 mib_p->fddiPORTLer_Alarm ;
0813             sp->p4050_estimate =
0814                 mib_p->fddiPORTLer_Estimate ;
0815             sp->p4050_reject_ct =
0816                 mib_p->fddiPORTLem_Reject_Ct ;
0817             sp->p4050_ct =
0818                 mib_p->fddiPORTLem_Ct ;
0819             sp_len = sizeof(struct smt_p_4050) ;
0820             goto sp_done ;
0821         }
0822 
0823     case SMT_P4051 :
0824         {
0825             struct smt_p_4051   *sp ;
0826             sp = (struct smt_p_4051 *) to ;
0827             sp->p4051_multiple =
0828                 mib_p->fddiPORTMultiple_U ;
0829             sp->p4051_porttype =
0830                 mib_p->fddiPORTMy_Type ;
0831             sp->p4051_connectstate =
0832                 mib_p->fddiPORTConnectState ;
0833             sp->p4051_pc_neighbor =
0834                 mib_p->fddiPORTNeighborType ;
0835             sp->p4051_pc_withhold =
0836                 mib_p->fddiPORTPC_Withhold ;
0837             sp_len = sizeof(struct smt_p_4051) ;
0838             goto sp_done ;
0839         }
0840     case SMT_P4052 :
0841         {
0842             struct smt_p_4052   *sp ;
0843             sp = (struct smt_p_4052 *) to ;
0844             sp->p4052_flag =
0845                 mib_p->fddiPORTEB_Condition ;
0846             sp->p4052_eberrorcount =
0847                 mib_p->fddiPORTEBError_Ct ;
0848             sp_len = sizeof(struct smt_p_4052) ;
0849             goto sp_done ;
0850         }
0851     case SMT_P4053 :
0852         {
0853             struct smt_p_4053   *sp ;
0854             sp = (struct smt_p_4053 *) to ;
0855             sp->p4053_multiple =
0856                 mib_p->fddiPORTMultiple_P ;
0857             sp->p4053_availablepaths =
0858                 mib_p->fddiPORTAvailablePaths ;
0859             sp->p4053_currentpath =
0860                 mib_p->fddiPORTCurrentPath ;
0861             memcpy( (char *) &sp->p4053_requestedpaths,
0862                 (char *) mib_p->fddiPORTRequestedPaths,4) ;
0863             sp->p4053_mytype =
0864                 mib_p->fddiPORTMy_Type ;
0865             sp->p4053_neighbortype =
0866                 mib_p->fddiPORTNeighborType ;
0867             sp_len = sizeof(struct smt_p_4053) ;
0868             goto sp_done ;
0869         }
0870     default :
0871         break ;
0872     }
0873     /*
0874      * in table ?
0875      */
0876     if (!pt) {
0877         pcon->pc_err = (para & 0xff00) ? SMT_RDF_NOPARAM :
0878                         SMT_RDF_ILLEGAL ;
0879         return ;
0880     }
0881     /*
0882      * check access rights
0883      */
0884     switch (pt->p_access) {
0885     case AC_G :
0886     case AC_GR :
0887         break ;
0888     default :
0889         pcon->pc_err = SMT_RDF_ILLEGAL ;
0890         return ;
0891     }
0892     from = mib_addr + pt->p_offset ;
0893     if (!swap)
0894         swap = pt->p_swap ;     /* pointer to swap string */
0895 
0896     /*
0897      * copy values
0898      */
0899     while ((c = *swap++)) {
0900         switch(c) {
0901         case 'b' :
0902         case 'w' :
0903         case 'l' :
0904             break ;
0905         case 'S' :
0906         case 'E' :
0907         case 'R' :
0908         case 'r' :
0909             if (len < 4)
0910                 goto len_error ;
0911             to[0] = 0 ;
0912             to[1] = 0 ;
0913 #ifdef  LITTLE_ENDIAN
0914             if (c == 'r') {
0915                 to[2] = *from++ ;
0916                 to[3] = *from++ ;
0917             }
0918             else {
0919                 to[3] = *from++ ;
0920                 to[2] = *from++ ;
0921             }
0922 #else
0923             to[2] = *from++ ;
0924             to[3] = *from++ ;
0925 #endif
0926             to += 4 ;
0927             len -= 4 ;
0928             break ;
0929         case 'I' :      /* for SET of port indexes */
0930             if (len < 2)
0931                 goto len_error ;
0932 #ifdef  LITTLE_ENDIAN
0933             to[1] = *from++ ;
0934             to[0] = *from++ ;
0935 #else
0936             to[0] = *from++ ;
0937             to[1] = *from++ ;
0938 #endif
0939             to += 2 ;
0940             len -= 2 ;
0941             break ;
0942         case 'F' :
0943         case 'B' :
0944             if (len < 4)
0945                 goto len_error ;
0946             len -= 4 ;
0947             to[0] = 0 ;
0948             to[1] = 0 ;
0949             to[2] = 0 ;
0950             to[3] = *from++ ;
0951             to += 4 ;
0952             break ;
0953         case 'C' :
0954         case 'T' :
0955         case 'L' :
0956             if (len < 4)
0957                 goto len_error ;
0958 #ifdef  LITTLE_ENDIAN
0959             to[3] = *from++ ;
0960             to[2] = *from++ ;
0961             to[1] = *from++ ;
0962             to[0] = *from++ ;
0963 #else
0964             to[0] = *from++ ;
0965             to[1] = *from++ ;
0966             to[2] = *from++ ;
0967             to[3] = *from++ ;
0968 #endif
0969             len -= 4 ;
0970             to += 4 ;
0971             break ;
0972         case '2' :      /* PortMacIndicated */
0973             if (len < 4)
0974                 goto len_error ;
0975             to[0] = 0 ;
0976             to[1] = 0 ;
0977             to[2] = *from++ ;
0978             to[3] = *from++ ;
0979             len -= 4 ;
0980             to += 4 ;
0981             break ;
0982         case '4' :
0983             if (len < 4)
0984                 goto len_error ;
0985             to[0] = *from++ ;
0986             to[1] = *from++ ;
0987             to[2] = *from++ ;
0988             to[3] = *from++ ;
0989             len -= 4 ;
0990             to += 4 ;
0991             break ;
0992         case 'A' :
0993             if (len < 8)
0994                 goto len_error ;
0995             to[0] = 0 ;
0996             to[1] = 0 ;
0997             memcpy((char *) to+2,(char *) from,6) ;
0998             to += 8 ;
0999             from += 8 ;
1000             len -= 8 ;
1001             break ;
1002         case '8' :
1003             if (len < 8)
1004                 goto len_error ;
1005             memcpy((char *) to,(char *) from,8) ;
1006             to += 8 ;
1007             from += 8 ;
1008             len -= 8 ;
1009             break ;
1010         case 'D' :
1011             if (len < 32)
1012                 goto len_error ;
1013             memcpy((char *) to,(char *) from,32) ;
1014             to += 32 ;
1015             from += 32 ;
1016             len -= 32 ;
1017             break ;
1018         case 'P' :      /* timestamp is NOT swapped */
1019             if (len < 8)
1020                 goto len_error ;
1021             to[0] = *from++ ;
1022             to[1] = *from++ ;
1023             to[2] = *from++ ;
1024             to[3] = *from++ ;
1025             to[4] = *from++ ;
1026             to[5] = *from++ ;
1027             to[6] = *from++ ;
1028             to[7] = *from++ ;
1029             to += 8 ;
1030             len -= 8 ;
1031             break ;
1032         default :
1033             SMT_PANIC(smc,SMT_E0119, SMT_E0119_MSG) ;
1034             break ;
1035         }
1036     }
1037 
1038 done:
1039     /*
1040      * make it even (in case of 'I' encoding)
1041      * note: len is DECREMENTED
1042      */
1043     if (len & 3) {
1044         to[0] = 0 ;
1045         to[1] = 0 ;
1046         to += 4 - (len & 3 ) ;
1047         len = len & ~ 3 ;
1048     }
1049 
1050     /* set type and length */
1051     pa->p_type = para ;
1052     pa->p_len = plen - len - PARA_LEN ;
1053     /* return values */
1054     pcon->pc_p = (void *) to ;
1055     pcon->pc_len = len ;
1056     return ;
1057 
1058 sp_done:
1059     len -= sp_len ;
1060     to += sp_len ;
1061     goto done ;
1062 
1063 len_error:
1064     /* parameter does not fit in frame */
1065     pcon->pc_err = SMT_RDF_TOOLONG ;
1066     return ;
1067 
1068 wrong_error:
1069     pcon->pc_err = SMT_RDF_LENGTH ;
1070 }
1071 
1072 /*
1073  * set parameter
1074  */
1075 static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
1076             int local, int set)
1077 {
1078 #define IFSET(x)    if (set) (x)
1079 
1080     const struct s_p_tab    *pt ;
1081     int     len ;
1082     char        *from ;
1083     char        *to ;
1084     const char  *swap ;
1085     char        c ;
1086     char        *mib_addr ;
1087     struct fddi_mib *mib ;
1088     struct fddi_mib_m   *mib_m = NULL;
1089     struct fddi_mib_a   *mib_a = NULL;
1090     struct fddi_mib_p   *mib_p = NULL;
1091     int     mac ;
1092     int     path ;
1093     int     port ;
1094     SK_LOC_DECL(u_char,byte_val) ;
1095     SK_LOC_DECL(u_short,word_val) ;
1096     SK_LOC_DECL(u_long,long_val) ;
1097 
1098     mac = index - INDEX_MAC ;
1099     path = index - INDEX_PATH ;
1100     port = index - INDEX_PORT ;
1101     len = pa->p_len ;
1102     from = (char *) (pa + 1 ) ;
1103 
1104     mib = &smc->mib ;
1105     switch (pa->p_type & 0xf000) {
1106     case 0x1000 :
1107     default :
1108         mib_addr = (char *) mib ;
1109         break ;
1110     case 0x2000 :
1111         if (mac < 0 || mac >= NUMMACS) {
1112             return SMT_RDF_NOPARAM;
1113         }
1114         mib_m = &smc->mib.m[mac] ;
1115         mib_addr = (char *) mib_m ;
1116         from += 4 ;     /* skip index */
1117         len -= 4 ;
1118         break ;
1119     case 0x3000 :
1120         if (path < 0 || path >= NUMPATHS) {
1121             return SMT_RDF_NOPARAM;
1122         }
1123         mib_a = &smc->mib.a[path] ;
1124         mib_addr = (char *) mib_a ;
1125         from += 4 ;     /* skip index */
1126         len -= 4 ;
1127         break ;
1128     case 0x4000 :
1129         if (port < 0 || port >= smt_mib_phys(smc)) {
1130             return SMT_RDF_NOPARAM;
1131         }
1132         mib_p = &smc->mib.p[port_to_mib(smc,port)] ;
1133         mib_addr = (char *) mib_p ;
1134         from += 4 ;     /* skip index */
1135         len -= 4 ;
1136         break ;
1137     }
1138     switch (pa->p_type) {
1139     case SMT_P10F0 :
1140     case SMT_P10F1 :
1141 #ifdef  ESS
1142     case SMT_P10F2 :
1143     case SMT_P10F3 :
1144     case SMT_P10F4 :
1145     case SMT_P10F5 :
1146     case SMT_P10F6 :
1147     case SMT_P10F7 :
1148 #endif
1149 #ifdef  SBA
1150     case SMT_P10F8 :
1151     case SMT_P10F9 :
1152 #endif
1153     case SMT_P20F1 :
1154         if (!local)
1155             return SMT_RDF_NOPARAM;
1156         break ;
1157     }
1158     pt = smt_get_ptab(pa->p_type) ;
1159     if (!pt)
1160         return (pa->p_type & 0xff00) ? SMT_RDF_NOPARAM :
1161                            SMT_RDF_ILLEGAL;
1162     switch (pt->p_access) {
1163     case AC_GR :
1164     case AC_S :
1165         break ;
1166     default :
1167         return SMT_RDF_ILLEGAL;
1168     }
1169     to = mib_addr + pt->p_offset ;
1170     swap = pt->p_swap ;     /* pointer to swap string */
1171 
1172     while (swap && (c = *swap++)) {
1173         switch(c) {
1174         case 'b' :
1175             to = (char *) &byte_val ;
1176             break ;
1177         case 'w' :
1178             to = (char *) &word_val ;
1179             break ;
1180         case 'l' :
1181             to = (char *) &long_val ;
1182             break ;
1183         case 'S' :
1184         case 'E' :
1185         case 'R' :
1186         case 'r' :
1187             if (len < 4) {
1188                 goto len_error ;
1189             }
1190             if (from[0] | from[1])
1191                 goto val_error ;
1192 #ifdef  LITTLE_ENDIAN
1193             if (c == 'r') {
1194                 to[0] = from[2] ;
1195                 to[1] = from[3] ;
1196             }
1197             else {
1198                 to[1] = from[2] ;
1199                 to[0] = from[3] ;
1200             }
1201 #else
1202             to[0] = from[2] ;
1203             to[1] = from[3] ;
1204 #endif
1205             from += 4 ;
1206             to += 2 ;
1207             len -= 4 ;
1208             break ;
1209         case 'F' :
1210         case 'B' :
1211             if (len < 4) {
1212                 goto len_error ;
1213             }
1214             if (from[0] | from[1] | from[2])
1215                 goto val_error ;
1216             to[0] = from[3] ;
1217             len -= 4 ;
1218             from += 4 ;
1219             to += 4 ;
1220             break ;
1221         case 'C' :
1222         case 'T' :
1223         case 'L' :
1224             if (len < 4) {
1225                 goto len_error ;
1226             }
1227 #ifdef  LITTLE_ENDIAN
1228             to[3] = *from++ ;
1229             to[2] = *from++ ;
1230             to[1] = *from++ ;
1231             to[0] = *from++ ;
1232 #else
1233             to[0] = *from++ ;
1234             to[1] = *from++ ;
1235             to[2] = *from++ ;
1236             to[3] = *from++ ;
1237 #endif
1238             len -= 4 ;
1239             to += 4 ;
1240             break ;
1241         case 'A' :
1242             if (len < 8)
1243                 goto len_error ;
1244             if (set)
1245                 memcpy(to,from+2,6) ;
1246             to += 8 ;
1247             from += 8 ;
1248             len -= 8 ;
1249             break ;
1250         case '4' :
1251             if (len < 4)
1252                 goto len_error ;
1253             if (set)
1254                 memcpy(to,from,4) ;
1255             to += 4 ;
1256             from += 4 ;
1257             len -= 4 ;
1258             break ;
1259         case '8' :
1260             if (len < 8)
1261                 goto len_error ;
1262             if (set)
1263                 memcpy(to,from,8) ;
1264             to += 8 ;
1265             from += 8 ;
1266             len -= 8 ;
1267             break ;
1268         case 'D' :
1269             if (len < 32)
1270                 goto len_error ;
1271             if (set)
1272                 memcpy(to,from,32) ;
1273             to += 32 ;
1274             from += 32 ;
1275             len -= 32 ;
1276             break ;
1277         case 'P' :      /* timestamp is NOT swapped */
1278             if (set) {
1279                 to[0] = *from++ ;
1280                 to[1] = *from++ ;
1281                 to[2] = *from++ ;
1282                 to[3] = *from++ ;
1283                 to[4] = *from++ ;
1284                 to[5] = *from++ ;
1285                 to[6] = *from++ ;
1286                 to[7] = *from++ ;
1287             }
1288             to += 8 ;
1289             len -= 8 ;
1290             break ;
1291         default :
1292             SMT_PANIC(smc,SMT_E0120, SMT_E0120_MSG) ;
1293             return SMT_RDF_ILLEGAL;
1294         }
1295     }
1296     /*
1297      * actions and internal updates
1298      */
1299     switch (pa->p_type) {
1300     case SMT_P101A:         /* fddiSMTConfigPolicy */
1301         if (word_val & ~1)
1302             goto val_error ;
1303         IFSET(mib->fddiSMTConfigPolicy = word_val) ;
1304         break ;
1305     case SMT_P101B :        /* fddiSMTConnectionPolicy */
1306         if (!(word_val & POLICY_MM))
1307             goto val_error ;
1308         IFSET(mib->fddiSMTConnectionPolicy = word_val) ;
1309         break ;
1310     case SMT_P101D :        /* fddiSMTTT_Notify */
1311         if (word_val < 2 || word_val > 30)
1312             goto val_error ;
1313         IFSET(mib->fddiSMTTT_Notify = word_val) ;
1314         break ;
1315     case SMT_P101E :        /* fddiSMTStatRptPolicy */
1316         if (byte_val & ~1)
1317             goto val_error ;
1318         IFSET(mib->fddiSMTStatRptPolicy = byte_val) ;
1319         break ;
1320     case SMT_P101F :        /* fddiSMTTrace_MaxExpiration */
1321         /*
1322          * note: lower limit trace_max = 6.001773... s
1323          * NO upper limit
1324          */
1325         if (long_val < (long)0x478bf51L)
1326             goto val_error ;
1327         IFSET(mib->fddiSMTTrace_MaxExpiration = long_val) ;
1328         break ;
1329 #ifdef  ESS
1330     case SMT_P10F2 :        /* fddiESSPayload */
1331         if (long_val > 1562)
1332             goto val_error ;
1333         if (set && smc->mib.fddiESSPayload != long_val) {
1334             smc->ess.raf_act_timer_poll = TRUE ;
1335             smc->mib.fddiESSPayload = long_val ;
1336         }
1337         break ;
1338     case SMT_P10F3 :        /* fddiESSOverhead */
1339         if (long_val < 50 || long_val > 5000)
1340             goto val_error ;
1341         if (set && smc->mib.fddiESSPayload &&
1342             smc->mib.fddiESSOverhead != long_val) {
1343             smc->ess.raf_act_timer_poll = TRUE ;
1344             smc->mib.fddiESSOverhead = long_val ;
1345         }
1346         break ;
1347     case SMT_P10F4 :        /* fddiESSMaxTNeg */
1348         if (long_val > -MS2BCLK(5) || long_val < -MS2BCLK(165))
1349             goto val_error ;
1350         IFSET(mib->fddiESSMaxTNeg = long_val) ;
1351         break ;
1352     case SMT_P10F5 :        /* fddiESSMinSegmentSize */
1353         if (long_val < 1 || long_val > 4478)
1354             goto val_error ;
1355         IFSET(mib->fddiESSMinSegmentSize = long_val) ;
1356         break ;
1357     case SMT_P10F6 :        /* fddiESSCategory */
1358         if ((long_val & 0xffff) != 1)
1359             goto val_error ;
1360         IFSET(mib->fddiESSCategory = long_val) ;
1361         break ;
1362     case SMT_P10F7 :        /* fddiESSSyncTxMode */
1363         if (word_val > 1)
1364             goto val_error ;
1365         IFSET(mib->fddiESSSynchTxMode = word_val) ;
1366         break ;
1367 #endif
1368 #ifdef  SBA
1369     case SMT_P10F8 :        /* fddiSBACommand */
1370         if (byte_val != SB_STOP && byte_val != SB_START)
1371             goto val_error ;
1372         IFSET(mib->fddiSBACommand = byte_val) ;
1373         break ;
1374     case SMT_P10F9 :        /* fddiSBAAvailable */
1375         if (byte_val > 100)
1376             goto val_error ;
1377         IFSET(mib->fddiSBAAvailable = byte_val) ;
1378         break ;
1379 #endif
1380     case SMT_P2020 :        /* fddiMACRequestedPaths */
1381         if ((word_val & (MIB_P_PATH_PRIM_PREFER |
1382             MIB_P_PATH_PRIM_ALTER)) == 0 )
1383             goto val_error ;
1384         IFSET(mib_m->fddiMACRequestedPaths = word_val) ;
1385         break ;
1386     case SMT_P205F :        /* fddiMACFrameErrorThreshold */
1387         /* 0 .. ffff acceptable */
1388         IFSET(mib_m->fddiMACFrameErrorThreshold = word_val) ;
1389         break ;
1390     case SMT_P2067 :        /* fddiMACNotCopiedThreshold */
1391         /* 0 .. ffff acceptable */
1392         IFSET(mib_m->fddiMACNotCopiedThreshold = word_val) ;
1393         break ;
1394     case SMT_P2076:         /* fddiMACMA_UnitdataEnable */
1395         if (byte_val & ~1)
1396             goto val_error ;
1397         if (set) {
1398             mib_m->fddiMACMA_UnitdataEnable = byte_val ;
1399             queue_event(smc,EVENT_RMT,RM_ENABLE_FLAG) ;
1400         }
1401         break ;
1402     case SMT_P20F1 :        /* fddiMACT_Min */
1403         IFSET(mib_m->fddiMACT_Min = long_val) ;
1404         break ;
1405     case SMT_P320F :
1406         if (long_val > 1562)
1407             goto val_error ;
1408         IFSET(mib_a->fddiPATHSbaPayload = long_val) ;
1409 #ifdef  ESS
1410         if (set)
1411             ess_para_change(smc) ;
1412 #endif
1413         break ;
1414     case SMT_P3210 :
1415         if (long_val > 5000)
1416             goto val_error ;
1417         
1418         if (long_val != 0 && mib_a->fddiPATHSbaPayload == 0)
1419             goto val_error ;
1420 
1421         IFSET(mib_a->fddiPATHSbaOverhead = long_val) ;
1422 #ifdef  ESS
1423         if (set)
1424             ess_para_change(smc) ;
1425 #endif
1426         break ;
1427     case SMT_P3213:         /* fddiPATHT_Rmode */
1428         /* no limit :
1429          * 0 .. 343.597 => 0 .. 2e32 * 80nS
1430          */
1431         if (set) {
1432             mib_a->fddiPATHT_Rmode = long_val ;
1433             rtm_set_timer(smc) ;
1434         }
1435         break ;
1436     case SMT_P3214 :        /* fddiPATHSbaAvailable */
1437         if (long_val > 0x00BEBC20L)
1438             goto val_error ;
1439 #ifdef SBA 
1440         if (set && mib->fddiSBACommand == SB_STOP)
1441             goto val_error ;
1442 #endif
1443         IFSET(mib_a->fddiPATHSbaAvailable = long_val) ;
1444         break ;
1445     case SMT_P3215 :        /* fddiPATHTVXLowerBound */
1446         IFSET(mib_a->fddiPATHTVXLowerBound = long_val) ;
1447         goto change_mac_para ;
1448     case SMT_P3216 :        /* fddiPATHT_MaxLowerBound */
1449         IFSET(mib_a->fddiPATHT_MaxLowerBound = long_val) ;
1450         goto change_mac_para ;
1451     case SMT_P3217 :        /* fddiPATHMaxT_Req */
1452         IFSET(mib_a->fddiPATHMaxT_Req = long_val) ;
1453 
1454 change_mac_para:
1455         if (set && smt_set_mac_opvalues(smc)) {
1456             RS_SET(smc,RS_EVENT) ;
1457             smc->sm.please_reconnect = 1 ;
1458             queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
1459         }
1460         break ;
1461     case SMT_P400E :        /* fddiPORTConnectionPolicies */
1462         if (byte_val > 1)
1463             goto val_error ;
1464         IFSET(mib_p->fddiPORTConnectionPolicies = byte_val) ;
1465         break ;
1466     case SMT_P4011 :        /* fddiPORTRequestedPaths */
1467         /* all 3*8 bits allowed */
1468         IFSET(memcpy((char *)mib_p->fddiPORTRequestedPaths,
1469             (char *)&long_val,4)) ;
1470         break ;
1471     case SMT_P401F:         /* fddiPORTMaint_LS */
1472         if (word_val > 4)
1473             goto val_error ;
1474         IFSET(mib_p->fddiPORTMaint_LS = word_val) ;
1475         break ;
1476     case SMT_P403A :        /* fddiPORTLer_Cutoff */
1477         if (byte_val < 4 || byte_val > 15)
1478             goto val_error ;
1479         IFSET(mib_p->fddiPORTLer_Cutoff = byte_val) ;
1480         break ;
1481     case SMT_P403B :        /* fddiPORTLer_Alarm */
1482         if (byte_val < 4 || byte_val > 15)
1483             goto val_error ;
1484         IFSET(mib_p->fddiPORTLer_Alarm = byte_val) ;
1485         break ;
1486 
1487     /*
1488      * Actions
1489      */
1490     case SMT_P103C :        /* fddiSMTStationAction */
1491         if (smt_action(smc,SMT_STATION_ACTION, (int) word_val, 0))
1492             goto val_error ;
1493         break ;
1494     case SMT_P4046:         /* fddiPORTAction */
1495         if (smt_action(smc,SMT_PORT_ACTION, (int) word_val,
1496             port_to_mib(smc,port)))
1497             goto val_error ;
1498         break ;
1499     default :
1500         break ;
1501     }
1502     return 0;
1503 
1504 val_error:
1505     /* parameter value in frame is out of range */
1506     return SMT_RDF_RANGE;
1507 
1508 len_error:
1509     /* parameter value in frame is too short */
1510     return SMT_RDF_LENGTH;
1511 
1512 #if 0
1513 no_author_error:
1514     /* parameter not setable, because the SBA is not active
1515      * Please note: we give the return code 'not authorizeed
1516      *  because SBA denied is not a valid return code in the
1517      * PMF protocol.
1518      */
1519     return SMT_RDF_AUTHOR;
1520 #endif
1521 }
1522 
1523 static const struct s_p_tab *smt_get_ptab(u_short para)
1524 {
1525     const struct s_p_tab    *pt ;
1526     for (pt = p_tab ; pt->p_num && pt->p_num != para ; pt++)
1527         ;
1528     return pt->p_num ? pt : NULL;
1529 }
1530 
1531 static int smt_mib_phys(struct s_smc *smc)
1532 {
1533 #ifdef  CONCENTRATOR
1534     SK_UNUSED(smc) ;
1535 
1536     return NUMPHYS;
1537 #else
1538     if (smc->s.sas == SMT_SAS)
1539         return 1;
1540     return NUMPHYS;
1541 #endif
1542 }
1543 
1544 static int port_to_mib(struct s_smc *smc, int p)
1545 {
1546 #ifdef  CONCENTRATOR
1547     SK_UNUSED(smc) ;
1548 
1549     return p;
1550 #else
1551     if (smc->s.sas == SMT_SAS)
1552         return PS;
1553     return p;
1554 #endif
1555 }
1556 
1557 
1558 #ifdef  DEBUG
1559 #ifndef BOOT
1560 void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text)
1561 {
1562     int len ;
1563     struct smt_para *pa ;
1564     char    *c ;
1565     int n ;
1566     int nn ;
1567 #ifdef  LITTLE_ENDIAN
1568     int smtlen ;
1569 #endif
1570 
1571     SK_UNUSED(smc) ;
1572 
1573 #ifdef  DEBUG_BRD
1574     if (smc->debug.d_smtf < 2)
1575 #else
1576     if (debug.d_smtf < 2)
1577 #endif
1578         return ;
1579 #ifdef  LITTLE_ENDIAN
1580     smtlen = sm->smt_len + sizeof(struct smt_header) ;
1581 #endif
1582     printf("SMT Frame [%s]:\nDA  ",text) ;
1583     dump_hex((char *) &sm->smt_dest,6) ;
1584     printf("\tSA ") ;
1585     dump_hex((char *) &sm->smt_source,6) ;
1586     printf(" Class %x Type %x Version %x\n",
1587         sm->smt_class,sm->smt_type,sm->smt_version)  ;
1588     printf("TID %lx\t\tSID ",sm->smt_tid) ;
1589     dump_hex((char *) &sm->smt_sid,8) ;
1590     printf(" LEN %x\n",sm->smt_len) ;
1591 
1592     len = sm->smt_len ;
1593     pa = (struct smt_para *) (sm + 1) ;
1594     while (len > 0 ) {
1595         int plen ;
1596 #ifdef UNIX
1597         printf("TYPE %x LEN %x VALUE\t",pa->p_type,pa->p_len) ;
1598 #else
1599         printf("TYPE %04x LEN %2x VALUE\t",pa->p_type,pa->p_len) ;
1600 #endif
1601         n = pa->p_len ;
1602         if ( (n < 0 ) || (n > (int)(len - PARA_LEN))) {
1603             n = len - PARA_LEN ;
1604             printf(" BAD LENGTH\n") ;
1605             break ;
1606         }
1607 #ifdef  LITTLE_ENDIAN
1608         smt_swap_para(sm,smtlen,0) ;
1609 #endif
1610         if (n < 24) {
1611             dump_hex((char *)(pa+1),(int) n) ;
1612             printf("\n") ;
1613         }
1614         else {
1615             int first = 0 ;
1616             c = (char *)(pa+1) ;
1617             dump_hex(c,16) ;
1618             printf("\n") ;
1619             n -= 16 ;
1620             c += 16 ;
1621             while (n > 0) {
1622                 nn = (n > 16) ? 16 : n ;
1623                 if (n > 64) {
1624                     if (first == 0)
1625                         printf("\t\t\t...\n") ;
1626                     first = 1 ;
1627                 }
1628                 else {
1629                     printf("\t\t\t") ;
1630                     dump_hex(c,nn) ;
1631                     printf("\n") ;
1632                 }
1633                 n -= nn ;
1634                 c += 16 ;
1635             }
1636         }
1637 #ifdef  LITTLE_ENDIAN
1638         smt_swap_para(sm,smtlen,1) ;
1639 #endif
1640         plen = (pa->p_len + PARA_LEN + 3) & ~3 ;
1641         len -= plen ;
1642         pa = (struct smt_para *)((char *)pa + plen) ;
1643     }
1644     printf("-------------------------------------------------\n\n") ;
1645 }
1646 
1647 void dump_hex(char *p, int len)
1648 {
1649     int n = 0 ;
1650     while (len--) {
1651         n++ ;
1652 #ifdef UNIX
1653         printf("%x%s",*p++ & 0xff,len ? ( (n & 7) ? " " : "-") : "") ;
1654 #else
1655         printf("%02x%s",*p++ & 0xff,len ? ( (n & 7) ? " " : "-") : "") ;
1656 #endif
1657     }
1658 }
1659 #endif  /* no BOOT */
1660 #endif  /* DEBUG */
1661 
1662 
1663 #endif  /* no SLIM_SMT */