#include #include #include #include #include #include #if DBG UINT BaudBitField = 0; #ifdef UNDER_CE // WARNING, this really doesn't work with UNICODE #define isprint(c) (((c) >= TEXT(' ')) && ((c) <= 0x7f)) #else #define wsprintf sprintf #endif int vDispMode; UINT vDecodeLayer; int vSlotTable[] = { 1, 6, 8, 16 }; int IasRequest; TCHAR *vLM_PDU_DscReason[] = { TEXT(""), TEXT("User Request"), TEXT("Unexpected IrLAP Disconnect"), TEXT("Failed to establish IrLAP connection"), TEXT("IrLAP reset"), TEXT("Link management initiated disconnect"), TEXT("data sent to disconnected LSAP"), TEXT("Non responsive LM-MUX client"), TEXT("No available LM-MUX client"), TEXT("Unspecified") }; /* ** Negotiation Parameter Value (PV) tables */ TCHAR *vBaud[] = { TEXT("2400"), TEXT("9600"), TEXT("19200"), TEXT("38400"), TEXT("57600"), TEXT("115200"), TEXT("576000"), TEXT("1152000"), TEXT("4000000") }; TCHAR *vMaxTAT[] = /* Turn Around Time */ { TEXT("500"), TEXT("250"), TEXT("100"), TEXT("50"), TEXT("25"), TEXT("10"), TEXT("5"), TEXT("reserved") }; TCHAR *vMinTAT[] = { TEXT("10"), TEXT("5"), TEXT("1"), TEXT("0.5"), TEXT("0.1"), TEXT("0.05"), TEXT("0.01"), TEXT("0") }; TCHAR *vDataSize[] = { TEXT("64"), TEXT("128"), TEXT("256"), TEXT("512"), TEXT("1024"), TEXT("2048"), TEXT("reserved"), TEXT("reserved") }; TCHAR *vWinSize[] = { TEXT("1"), TEXT("2"), TEXT("3"), TEXT("4"), TEXT("5"), TEXT("6"), TEXT("7"), TEXT("reserved") }; TCHAR *vNumBofs[] = { TEXT("48"), TEXT("24"), TEXT("12"), TEXT("5"), TEXT("3"), TEXT("2"), TEXT("1"), TEXT("0") }; TCHAR *vDiscThresh[] = { TEXT("3"), TEXT("8"), TEXT("12"), TEXT("16"), TEXT("20"), TEXT("25"), TEXT("30"), TEXT("40") }; /*---------------------------------------------------------------------------*/ void RawDump(UCHAR *pFrameBuf, UCHAR *pEndBuf, TCHAR **ppOutStr) { BOOLEAN First = TRUE; UCHAR *pBufPtr = pFrameBuf; if (!vDecodeLayer) return; if (vDispMode == DISP_ASCII || vDispMode == DISP_BOTH) { while (pBufPtr <= pEndBuf) { if (First) { First = FALSE; *(*ppOutStr)++ = TEXT('['); } *(*ppOutStr)++ = isprint(*pBufPtr) ? *pBufPtr : '.'; pBufPtr++; } if (!First) // meaning, close [ *(*ppOutStr)++ = ']'; } First = TRUE; pBufPtr = pFrameBuf; if (vDispMode == DISP_HEX || vDispMode == DISP_BOTH) { while (pBufPtr <= pEndBuf) { if (First) { First = FALSE; *(*ppOutStr)++ = TEXT('['); } *ppOutStr += wsprintf(*ppOutStr, TEXT("%02X "), *pBufPtr); pBufPtr++; } if (!First) // meaning, close [ *(*ppOutStr)++ = ']'; } } /*---------------------------------------------------------------------------*/ TCHAR * GetStatusStr(UCHAR status) { switch (status) { case LM_PDU_SUCCESS: return (TEXT("SUCCESS")); case LM_PDU_FAILURE: return (TEXT("FAILURE")); case LM_PDU_UNSUPPORTED: return (TEXT("UNSUPPORTED")); default: return (TEXT("BAD STATUS!")); } } void DecodeIas(UCHAR *pFrameBuf, UCHAR *pEndBuf, TCHAR **ppOutStr) { /* IAS_CNTL_HEADER *pCntlHeader = (IAS_CNTL_HEADER *) pFrameBuf; int NameLen; WCHAR NameBuffer[128]; *ppOutStr += wsprintf(*ppOutStr, TEXT("lst:%d ack:%d opcode:%d "), pCntlHeader->Last, pCntlHeader->Ack, pCntlHeader->OpCode); switch (pCntlHeader->OpCode) { case LM_GETVALUEBYCLASS: *ppOutStr += wsprintf(*ppOutStr, TEXT("GetValueByClass")); break; default: *ppOutStr += wsprintf(*ppOutStr, TEXT("I DON'T DECODE THIS OPCODE!")); return; } pFrameBuf++; IasRequest = !IasRequest; // This can get out of sync, then we're f'd if (IasRequest) { *ppOutStr += wsprintf(*ppOutStr, TEXT("Req ")); // Class name NameLen = (int) *pFrameBuf++; MultiByteToWideChar( CP_ACP, 0, pFrameBuf, NameLen, NameBuffer, 128); NameBuffer[NameLen] = TEXT('\0'); *ppOutStr += wsprintf(*ppOutStr, TEXT("class:%ws "), NameBuffer); pFrameBuf += NameLen; // Attribute name NameLen = (int) *pFrameBuf++; MultiByteToWideChar( CP_ACP, 0, pFrameBuf, NameLen, NameBuffer, 128); NameBuffer[NameLen] = TEXT('\0'); *ppOutStr += wsprintf(*ppOutStr, TEXT("attrib:%ws "), NameBuffer); } else { *ppOutStr += wsprintf(*ppOutStr, TEXT("Resp ")); switch (*pFrameBuf) { case 0: *ppOutStr += wsprintf(*ppOutStr, TEXT("attrib:%ws "), NameBuffer); break; case 1: *ppOutStr += wsprintf(*ppOutStr, TEXT("No such class ")); break; case 2: *ppOutStr += wsprintf(*ppOutStr, TEXT("No such attribute ")); break; } } */ return; } /*---------------------------------------------------------------------------*/ void DecodeIFrm(UCHAR *pFrameBuf, UCHAR *pEndBuf, TCHAR **ppOutStr) { LM_HEADER *pLMHeader = (LM_HEADER *) pFrameBuf; LM_CNTL_FORMAT *pCFormat = (LM_CNTL_FORMAT *)(pFrameBuf + sizeof(LM_HEADER)); UCHAR *pLMParm1 = ((UCHAR *) pCFormat + sizeof(LM_CNTL_FORMAT)); UCHAR *pLMParm2 = ((UCHAR *) pCFormat + sizeof(LM_CNTL_FORMAT) + 1); TTP_CONN_HEADER *pTTPConnHeader = (TTP_CONN_HEADER *) pLMParm2; TTP_DATA_HEADER *pTTPDataHeader = (TTP_DATA_HEADER *) (pFrameBuf + sizeof(LM_HEADER)); TCHAR RCStr[] = TEXT(" "); BOOLEAN IasFrame = FALSE; if (2 == vDecodeLayer) // LAP only { RawDump(pFrameBuf, pEndBuf, ppOutStr); return; } // Ensure the LMP header is there if (((UCHAR *)pLMHeader + sizeof(LM_HEADER) > pEndBuf+1)) { *ppOutStr += wsprintf(*ppOutStr, TEXT("!-MISSING LMP HEADER-!")); return; } *ppOutStr += wsprintf(*ppOutStr, TEXT("sls:%02X dls:%02X "), pLMHeader->SLSAP_SEL, pLMHeader->DLSAP_SEL); if (pLMHeader->SLSAP_SEL == IAS_SEL || pLMHeader->DLSAP_SEL == IAS_SEL) { IasFrame = TRUE; *ppOutStr += wsprintf(*ppOutStr, TEXT("*IAS*")); } switch (pLMHeader->CntlBit) { case LM_PDU_CNTL_FRAME: _tcscpy(RCStr, pCFormat->ABit == LM_PDU_REQUEST ? TEXT("req") : TEXT("conf")); if (((UCHAR *)pCFormat + sizeof(LM_CNTL_FORMAT)) > pEndBuf+1) { *ppOutStr += wsprintf(*ppOutStr, TEXT("!-MISSING LMP-CNTL HEADER-!")); return; } else { if (pLMParm1 > pEndBuf) { pLMParm1 = NULL; pLMParm2 = NULL; pTTPConnHeader = NULL; } else { if (pLMParm2 > pEndBuf) { pLMParm2 = NULL; pTTPConnHeader = NULL; } else { if (((UCHAR *)pTTPConnHeader+sizeof(TTP_CONN_HEADER)) > pEndBuf+1) { pTTPConnHeader = NULL; } } } } switch (pCFormat->OpCode) { case LM_PDU_CONNECT: *ppOutStr += wsprintf(*ppOutStr, TEXT("LM-Connect.%s "), RCStr); if (pLMParm1 != NULL) { *ppOutStr += wsprintf(*ppOutStr, TEXT("rsvd:%02X "), *pLMParm1); } if (3 == vDecodeLayer) // LMP only { if (pLMParm2 != NULL) { // This is user data RawDump(pLMParm2, pEndBuf, ppOutStr); } } else { // TTP if (pTTPConnHeader == NULL) { *ppOutStr += wsprintf(*ppOutStr, TEXT("!-MISSING TTP CONNECT HEADER-!")); } else { *ppOutStr += wsprintf(*ppOutStr, TEXT("pf:%d ic:%d "), pTTPConnHeader->ParmFlag, pTTPConnHeader->InitialCredit); // This is user data RawDump(((UCHAR *) pTTPConnHeader + sizeof(TTP_CONN_HEADER)), pEndBuf, ppOutStr); } } break; case LM_PDU_DISCONNECT: *ppOutStr += wsprintf(*ppOutStr, TEXT("LM-Disconnect.%s"), RCStr); if (pLMParm1 == NULL) { *ppOutStr += wsprintf(*ppOutStr, TEXT("!-MISSING REASON CODE-!")); return; } else { if ((*pLMParm1 > LM_PDU_MAX_DSC_REASON || *pLMParm1 == 0) && *pLMParm1 != 0xFF) { *ppOutStr += wsprintf(*ppOutStr, TEXT(" BAD REASON CODE:%02X "), *pLMParm1); } else { if (*pLMParm1 == 0xFF) { *pLMParm1 = 0x09; // KLUDGE HERE !! } *ppOutStr += wsprintf(*ppOutStr, TEXT("(%02X:%s) "), *pLMParm1, vLM_PDU_DscReason[*pLMParm1]); } if (pLMParm2 != NULL) { RawDump(pLMParm2, pEndBuf, ppOutStr); } } break; case LM_PDU_ACCESSMODE: *ppOutStr += wsprintf(*ppOutStr, TEXT("LM-AccessMode.%s "), RCStr); if (pLMParm1 == NULL || pLMParm2 == NULL) { *ppOutStr += wsprintf(*ppOutStr, TEXT("!-MISSING PARAMETER-!")); } else { if (pCFormat->ABit == LM_PDU_REQUEST) { *ppOutStr += wsprintf(*ppOutStr, TEXT("rsvd:%02X "), *pLMParm1); } else { *ppOutStr += wsprintf(*ppOutStr, TEXT("status:%s "), GetStatusStr(*pLMParm1)); } *ppOutStr += wsprintf(*ppOutStr, TEXT("mode:%s "), *pLMParm2 == LM_PDU_EXCLUSIVE ? TEXT("Exclusive") : TEXT("Multiplexed")); } break; default: *ppOutStr += wsprintf(*ppOutStr, TEXT("Bad opcode: ")); RawDump((UCHAR *) pCFormat, pEndBuf, ppOutStr); } break; case LM_PDU_DATA_FRAME: if (IasFrame) { DecodeIas((UCHAR *) pCFormat, pEndBuf, ppOutStr); break; } if (3 == vDecodeLayer) { RawDump((UCHAR *) pCFormat, pEndBuf, ppOutStr); } else { // TTP if ((UCHAR *) (pTTPDataHeader + 1) > pEndBuf + 1) { *ppOutStr += wsprintf(*ppOutStr, TEXT("!-MISSING TTP DATA HEADER-!")); } else { *ppOutStr += wsprintf(*ppOutStr, TEXT("mb:%d nc:%d "), pTTPDataHeader->MoreBit, pTTPDataHeader->AdditionalCredit); // This is user data RawDump(((UCHAR *) pTTPDataHeader + sizeof(TTP_DATA_HEADER)), pEndBuf, ppOutStr); } } break; default: *ppOutStr += wsprintf(*ppOutStr, TEXT("Bad LM-PDU type: ")); RawDump((UCHAR *) pLMHeader, pEndBuf, ppOutStr); } } /*---------------------------------------------------------------------------*/ UCHAR * DumpPv(TCHAR *PVTable[], UCHAR *pQosUChar, TCHAR **ppOutStr, UINT *pBitField) { int Pl = (int) *pQosUChar++; int i; BOOLEAN First = TRUE; UCHAR Mask = 1; *pBitField = 0; if (Pl == 1) { *pBitField = (UINT) *pQosUChar; } else { *pBitField = ((UINT) *(pQosUChar+1))<<8; *pBitField |= (UINT) *(pQosUChar); } for (i = 0; i <= 8; i++) { if (*pBitField & (Mask)) { if (First) { *ppOutStr += wsprintf(*ppOutStr, PVTable[i]); First = FALSE; } else *ppOutStr += wsprintf(*ppOutStr, TEXT(",%s"), PVTable[i]); } Mask *= 2; } *(*ppOutStr)++ = '>'; return pQosUChar + Pl; } /*---------------------------------------------------------------------------*/ void DecodeNegParms(UCHAR *pCurPos, UCHAR *pEndBuf, TCHAR **ppOutStr) { UINT BitField; while (pCurPos+2 <= pEndBuf) /* need at least 3 bytes */ /* to define a parm */ { switch (*pCurPos) { case NEG_PI_BAUD: *ppOutStr += wsprintf(*ppOutStr, TEXT("GenNewAddr) *ppOutStr += wsprintf(*ppOutStr, TEXT("new addr ")); *ppOutStr += wsprintf(*ppOutStr, TEXT("sa:%02X%02X%02X%02X "), DiscvFormat->SrcAddr[0], DiscvFormat->SrcAddr[1], DiscvFormat->SrcAddr[2], DiscvFormat->SrcAddr[3]); *ppOutStr += wsprintf(*ppOutStr, TEXT("da:%02X%02X%02X%02X "), DiscvFormat->DestAddr[0], DiscvFormat->DestAddr[1], DiscvFormat->DestAddr[2], DiscvFormat->DestAddr[3]); *ppOutStr += wsprintf(*ppOutStr, TEXT("Slot:%02X/%X "), DiscvFormat->SlotNo, vSlotTable[DiscvFormat->NoOfSlots]); RawDump(DiscvInfo, pEndBuf, ppOutStr); break; case XID_NEGPARMS_FORMAT_ID: *ppOutStr += wsprintf(*ppOutStr, TEXT("Neg Parms ")); DecodeNegParms(NegParms, pEndBuf, ppOutStr); break; } } /*---------------------------------------------------------------------------*/ void BadFrame(UCHAR *pFrameBuf, UCHAR *pEndBuf, TCHAR **ppOutStr) { *ppOutStr += wsprintf(*ppOutStr, TEXT("Undefined Frame: ")); RawDump(pFrameBuf, pEndBuf, ppOutStr); } /*---------------------------------------------------------------------------*/ TCHAR *DecodeIRDA(int *pFrameType,// returned frame type (-1=bad frame) UCHAR *pFrameBuf, // pointer to buffer containing IRLAP frame UINT FrameLen, // length of buffer TCHAR *pOutStr, // string where decoded packet is placed UINT DecodeLayer,// 0, hdronly, 1,LAP only, 2 LAP/LMP, 3, LAP/LMP/TTP int fNoConnAddr,// TRUE->Don't show connection address in str int DispMode ) { UINT CRBit; UINT PFBit; UCHAR *Addr = pFrameBuf; UCHAR *Cntl = pFrameBuf + 1; TCHAR CRStr[] = TEXT(" "); TCHAR PFChar = TEXT(' '); SNRM_FORMAT *SNRMFormat = (SNRM_FORMAT *) ((UCHAR *) pFrameBuf + 2); UA_FORMAT *UAFormat = (UA_FORMAT *) ((UCHAR *) pFrameBuf + 2); UINT Nr = IRLAP_GET_NR(*Cntl); UINT Ns = IRLAP_GET_NS(*Cntl); UCHAR *pEndBuf = pFrameBuf + FrameLen - 1; TCHAR *First = pOutStr; vDispMode = DispMode; vDecodeLayer = DecodeLayer; if ( !fNoConnAddr) pOutStr += wsprintf(pOutStr, TEXT("ca:%02X "), IRLAP_GET_ADDR(*Addr)); CRBit = IRLAP_GET_CRBIT(*Addr); _tcscpy(CRStr, CRBit == _IRLAP_CMD ? TEXT("cmd"):TEXT("rsp")); PFBit = IRLAP_GET_PFBIT(*Cntl); if (1 == PFBit) { if (CRBit == _IRLAP_CMD) PFChar = 'P'; else PFChar ='F'; } *pFrameType = IRLAP_FRAME_TYPE(*Cntl); switch (IRLAP_FRAME_TYPE(*Cntl)) { case IRLAP_I_FRM: pOutStr += wsprintf(pOutStr, TEXT("I %s %c ns:%01d nr:%01d "), CRStr, PFChar, Ns, Nr); if (DecodeLayer) DecodeIFrm(pFrameBuf + 2, pEndBuf, &pOutStr); break; case IRLAP_S_FRM: *pFrameType = IRLAP_GET_SCNTL(*Cntl); switch (IRLAP_GET_SCNTL(*Cntl)) { case IRLAP_RR: pOutStr += wsprintf(pOutStr, TEXT("RR %s %c nr:%01d"), CRStr, PFChar, Nr); break; case IRLAP_RNR: pOutStr += wsprintf(pOutStr, TEXT("RNR %s %c nr:%01d"), CRStr, PFChar, Nr); break; case IRLAP_REJ: pOutStr += wsprintf(pOutStr, TEXT("REJ %s %c nr:%01d"), CRStr, PFChar, Nr); break; case IRLAP_SREJ: pOutStr += wsprintf(pOutStr, TEXT("SREJ %s %c nr:%01d"), CRStr, PFChar, Nr); break; default: BadFrame(pFrameBuf, pEndBuf, &pOutStr); } break; case IRLAP_U_FRM: *pFrameType = IRLAP_GET_UCNTL(*Cntl); switch (IRLAP_GET_UCNTL(*Cntl)) { case IRLAP_UI: pOutStr += wsprintf(pOutStr,TEXT("UI %s %c "), CRStr, PFChar); RawDump(pFrameBuf + 2, pEndBuf, &pOutStr); break; case IRLAP_XID_CMD: case IRLAP_XID_RSP: pOutStr += wsprintf(pOutStr,TEXT("XID %s %c "), CRStr, PFChar); if (DecodeLayer) DecodeXID(pFrameBuf + 2, pEndBuf, &pOutStr); break; case IRLAP_TEST: pOutStr += wsprintf(pOutStr, TEXT("TEST %s %c "), CRStr, PFChar); pOutStr += wsprintf(pOutStr, TEXT("sa:%02X%02X%02X%02X da:%02X%02X%02X%02X "), UAFormat->SrcAddr[0], UAFormat->SrcAddr[1], UAFormat->SrcAddr[2], UAFormat->SrcAddr[3], UAFormat->DestAddr[0], UAFormat->DestAddr[1], UAFormat->DestAddr[2], UAFormat->DestAddr[3]); RawDump(pFrameBuf + 1 + sizeof(UA_FORMAT), pEndBuf, &pOutStr); break; case IRLAP_SNRM: if (CRBit == _IRLAP_CMD) { pOutStr += wsprintf(pOutStr,TEXT("SNRM %s %c "), CRStr,PFChar); if ((UCHAR *) SNRMFormat < pEndBuf) { pOutStr += wsprintf(pOutStr, TEXT("sa:%02X%02X%02X%02X da:%02X%02X%02X%02X ca:%02X "), SNRMFormat->SrcAddr[0], SNRMFormat->SrcAddr[1], SNRMFormat->SrcAddr[2], SNRMFormat->SrcAddr[3], SNRMFormat->DestAddr[0], SNRMFormat->DestAddr[1], SNRMFormat->DestAddr[2], SNRMFormat->DestAddr[3], // CRBit stored in conn addr // according to spec... (SNRMFormat->ConnAddr) >>1); if (DecodeLayer) DecodeNegParms(&(SNRMFormat->FirstPI), pEndBuf, &pOutStr); } } else pOutStr += wsprintf(pOutStr, TEXT("RNRM %s %c "),CRStr,PFChar); break; case IRLAP_DISC: if (CRBit == _IRLAP_CMD) pOutStr += wsprintf(pOutStr, TEXT("DISC %s %c "), CRStr, PFChar); else pOutStr += wsprintf(pOutStr, TEXT("RD %s %c "), CRStr, PFChar); break; case IRLAP_UA: pOutStr += wsprintf(pOutStr, TEXT("UA %s %c "),CRStr,PFChar); if ((UCHAR *) UAFormat < pEndBuf) { pOutStr += wsprintf(pOutStr, TEXT("sa:%02X%02X%02X%02X da:%02X%02X%02X%02X "), UAFormat->SrcAddr[0], UAFormat->SrcAddr[1], UAFormat->SrcAddr[2], UAFormat->SrcAddr[3], UAFormat->DestAddr[0], UAFormat->DestAddr[1], UAFormat->DestAddr[2], UAFormat->DestAddr[3]); if (DecodeLayer) DecodeNegParms(&(UAFormat->FirstPI), pEndBuf, &pOutStr); } break; case IRLAP_FRMR: pOutStr += wsprintf(pOutStr, TEXT("FRMR %s %c "), CRStr, PFChar); RawDump(pFrameBuf + 2, pEndBuf, &pOutStr); break; case IRLAP_DM: pOutStr += wsprintf(pOutStr, TEXT("DM %s %c "), CRStr, PFChar); break; default: BadFrame(pFrameBuf, pEndBuf, &pOutStr); } break; default: *pFrameType = -1; BadFrame(pFrameBuf, pEndBuf, &pOutStr); } *pOutStr = 0; return (First); } #endif