/* * Copyright 2011 Range Networks, Inc. * All Rights Reserved. * * This software is distributed under multiple licenses; * see the COPYING file in the main directory for licensing * information for this specific distribuion. * * This use of this software may be subject to additional restrictions. * See the LEGAL file in the main directory for details. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include "BSSG.h" #include "BSSGMessages.h" #include "GPRSInternal.h" #include "Globals.h" #include "LLC.h" #define CASENAME(x) case x: return #x; namespace BSSG { const char *BSPDUType::name(int val) { switch ((type)val) { CASENAME(DL_UNITDATA) CASENAME(UL_UNITDATA) CASENAME(RA_CAPABILITY) CASENAME(PTM_UNITDATA) CASENAME(PAGING_PS) CASENAME(PAGING_CS) CASENAME(RA_CAPABILITY_UPDATE) CASENAME(RA_CAPABILITY_UPDATE_ACK) CASENAME(RADIO_STATUS) CASENAME(SUSPEND) CASENAME(SUSPEND_ACK) CASENAME(SUSPEND_NACK) CASENAME(RESUME) CASENAME(RESUME_ACK) CASENAME(RESUME_NACK) CASENAME(BVC_BLOCK) CASENAME(BVC_BLOCK_ACK) CASENAME(BVC_RESET) CASENAME(BVC_RESET_ACK) CASENAME(BVC_UNBLOCK) CASENAME(BVC_UNBLOCK_ACK) CASENAME(FLOW_CONTROL_BVC) CASENAME(FLOW_CONTROL_BVC_ACK) CASENAME(FLOW_CONTROL_MS) CASENAME(FLOW_CONTROL_MS_ACK) CASENAME(FLUSH_LL) CASENAME(FLUSH_LL_ACK) CASENAME(LLC_DISCARDED) CASENAME(SGSN_INVOKE_TRACE) CASENAME(STATUS) CASENAME(DOWNLOAD_BSS_PFC) CASENAME(CREATE_BSS_PFC) CASENAME(CREATE_BSS_PFC_ACK) CASENAME(CREATE_BSS_PFC_NACK) CASENAME(MODIFY_BSS_PFC) CASENAME(MODIFY_BSS_PFC_ACK) CASENAME(DELETE_BSS_PFC) CASENAME(DELETE_BSS_PFC_ACK) } return "unrecognized PDU"; } std::ostream& operator<<(std::ostream& os, const BSPDUType::type val) { os << "PDU_Type=" <<(int)val <<"=" <appendByte(((mMCC[1]-'0')<<4) | (mMCC[0]-'0')); // MCC digit 2, MCC digit 1 vec->appendByte(((mMNC[2]-'0')<<4) | (mMCC[2]-'0')); // MNC digit 3, MCC digit 3 vec->appendByte(((mMNC[1]-'0')<<4) | (mMNC[0]-'0')); // MNC digit 2, MNC digit 1 vec->appendUInt16(mLAC); vec->appendByte(mRAC); // Add Routing Area Identification IE from GSM 04.08 10.5.5.15, excluding IEI type and length bytes. // Add Cell Identity IE GSM 04.08 10.5.1.1, excluding IEI type unsigned mCI = gConfig.getNum("GSM.Identity.CI"); vec->appendUInt16(mCI); } // GSM 08.18 sec 10 describes the PDU messages that the SGSN can send to the BSS. // Cause values: 08.18 sec 11.3.8 BSSGUplinkMsg *BVCFactory(BSPDUType::type bstype, int arg1) // For reset, the bvci to reset; for others may be cause or tag . { BSSGUplinkMsg *vec = new BSSGUplinkMsg(80); // Big enough for any message. BVCI::type bvci; vec->setAppendP(0); // Setup vec for appending. // Add the NS header. vec->appendByte(NSPDUType::NS_UNITDATA); vec->appendByte(0); // unused byte. vec->appendUInt16(gBSSG.mbsNSEI); // Add the BSSG message type vec->appendByte((ByteType)bstype); switch (bstype) { case BSPDUType::BVC_RESET: // See GSM 08.18 sec 8.4: BVC-RESET procedure; and 10.4.12: BVC-RESET message. bvci = (BVCI::type) arg1; vec->appendByte(IEIType::BVCI); vec->appendLI(2); vec->appendUInt16(bvci); BVCAddCause(vec,0x8); // Cause 8: O&M Intervention if (bvci != BVCI::SIGNALLING) { BVCAddCellIdentifier(vec); } // We dont use the feature bitmap. break; case BSPDUType::BVC_RESET_ACK: BVCAddBVCI(vec,bstype); // There could be a cell identifier // There coulde be a feature bitmap. break; case BSPDUType::BVC_BLOCK: BVCAddBVCI(vec,bstype); BVCAddCause(vec,arg1); break; case BSPDUType::BVC_BLOCK_ACK: // fall through case BSPDUType::BVC_UNBLOCK: // fall through case BSPDUType::BVC_UNBLOCK_ACK: BVCAddBVCI(vec,bstype); break; case BSPDUType::FLOW_CONTROL_BVC_ACK: BVCAddTag(vec,arg1); break; default: assert(0); } return vec; } // Length Indicator GSM 08.16 10.1.2 // And I quote: // "The BSS or SGSN shall not consider the presence of octet 2a in a received IE // as an error when the IE is short enough for the length to be coded // in octet 2 only." // (pat) If the length is longer than 127, it is written simply // as a 16 bit number in network order, which is high byte first, // so the upper most bit is 0 if the value is <= 32767 static unsigned IEILength(unsigned int len) { if (len < 127) return 0x80 + len; assert(0); } void NSMsg::textNSHeader(std::ostream&os) const { int nstype = (int)getNSPDUType(); if (nstype == NSPDUType::NS_UNITDATA) { os <<"NSPDUType="<(this)); os << " LLC UL payload="<