📄 pasn.cxx
字号:
/* * pasn.cxx * * ASN classes in support of the SNMP code. * * Portable Windows Library * * Copyright (c) 1993-1998 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Portions are Copyright (C) 1993 Free Software Foundation, Inc. * All Rights Reserved. * * Contributor(s): ______________________________________. * * $Log: pasn.cxx,v $ * Revision 1.14 2000/05/05 10:08:29 robertj * Fixed some GNU compiler warnings * * Revision 1.13 1999/05/01 11:29:20 robertj * Alpha linux port changes. * * Revision 1.12 1999/05/01 03:52:20 robertj * Fixed various egcs warnings. * * Revision 1.11 1999/03/02 01:53:38 craigs * Fixed problem with creating IpAddress objects * * Revision 1.10 1999/02/16 08:08:06 robertj * MSVC 6.0 compatibility changes. * * Revision 1.9 1998/11/30 04:52:04 robertj * New directory structure * * Revision 1.8 1998/10/13 14:06:31 robertj * Complete rewrite of memory leak detection code. * * Revision 1.7 1998/09/23 06:22:27 robertj * Added open source copyright license. * * Revision 1.6 1998/02/16 06:57:05 robertj * Moved pragma implemenetation in here so do not need upasn.cxx file. * * Revision 1.7 1998/01/26 02:49:21 robertj * GNU support. * * Revision 1.6 1998/01/26 01:45:36 robertj * Removed unused variable. * * Revision 1.5 1997/08/20 09:00:37 craigs * Fixed problems with decoding of PASNNull * * Revision 1.4 1997/07/20 08:34:37 craigs * Added ASN NULL type * * Revision 1.3 1997/07/16 05:52:48 craigs * Changed ASN constructors to store value length separately so * ASNString consctructor will worki correctly * * Revision 1.2 1996/11/04 03:58:34 robertj * Added ASN types to class. * * Revision 1.1 1996/09/14 13:02:18 robertj * Initial revision * */#ifdef __GNUC__#pragma implementation "pasn.h"#endif#include <ptlib.h>#include <ptclib/pasn.h>#define new PNEW#define ASN_BOOLEAN (0x01)#define ASN_INTEGER (0x02)#define ASN_BIT_STR (0x03)#define ASN_OCTET_STR (0x04)#define ASN_NULL (0x05)#define ASN_OBJECT_ID (0x06)#define ASN_SEQUENCE (0x10)#define ASN_SET (0x11)#define ASN_UNIVERSAL (0x00)#define ASN_APPLICATION (0x40)#define ASN_CONTEXT (0x80)#define ASN_PRIVATE (0xC0)#define ASN_PRIMITIVE (0x00)#define ASN_CONSTRUCTOR (0x20)#define ASN_LONG_LEN (0x80)#define ASN_EXTENSION_ID (0x1F)#define ASN_BIT8 (0x80)#define MAX_OID_LEN 64static char cannotPerformOnBaseTypeMsg[] = "Cannot perform operation on base type PASNObject";BYTE PASNObject::ASNTypeToType[] = { ASN_INTEGER | ASN_UNIVERSAL | ASN_PRIMITIVE, // Integer ASN_OCTET_STR | ASN_UNIVERSAL | ASN_PRIMITIVE, // String ASN_OBJECT_ID | ASN_UNIVERSAL | ASN_PRIMITIVE, // ObjectID ASN_CONSTRUCTOR | ASN_SEQUENCE, // Sequence ASN_CONSTRUCTOR | ASN_CONTEXT, // Choice ASN_APPLICATION | 0, // IPAddress ASN_APPLICATION | 1, // Counter32 ASN_APPLICATION | 2, // Gauge32 ASN_APPLICATION | 3, // TimeTicks// SNMP v2 types ASN_APPLICATION | 4, // Opaque ASN_APPLICATION | 5, // NsapAddress ASN_APPLICATION | 6, // Counter64 ASN_APPLICATION | 7, // UInteger32 // Oops - missed the Null type ASN_NULL | ASN_UNIVERSAL | ASN_PRIMITIVE, // Null 0, // Unknown};////////////////////////////////////////////////////////////////////////////// PASNObject// All ASN objects descend from this class. It is the primitive type// which can be put into the ASNSequence class//PASNObject::PASNObject(){}void PASNObject::PrintOn(ostream &) const{ PAssertAlways(cannotPerformOnBaseTypeMsg);}void PASNObject::Encode(PBYTEArray &) { PAssertAlways(cannotPerformOnBaseTypeMsg);}WORD PASNObject::GetEncodedLength() { PAssertAlways(cannotPerformOnBaseTypeMsg); return 0;}PASNObject::ASNType PASNObject::GetType() const{ PAssertAlways(cannotPerformOnBaseTypeMsg); return Unknown;}PString PASNObject::GetTypeAsString() const{ PAssertAlways(cannotPerformOnBaseTypeMsg); return PString();}PObject * PASNObject::Clone() const{ PAssertAlways(cannotPerformOnBaseTypeMsg); return NULL;}void PASNObject::EncodeASNLength (PBYTEArray & buffer, WORD length){ PINDEX offs = buffer.GetSize(); // handle lengths less then 128 if (length < 128) buffer[offs++] = (BYTE)length; // handle lengths less than 256 else if (length < 256) { buffer[offs++] = (BYTE)(0x01 | ASN_LONG_LEN); buffer[offs++] = (BYTE)length; } // handle lengths up to 0xffff else { buffer[offs++] = (u_char)(0x02 | ASN_LONG_LEN); buffer[offs++] = (u_char)((length >> 8) & 0xFF); buffer[offs++] = (u_char)(length & 0xFF); }}BOOL PASNObject::DecodeASNLength (const PBYTEArray & buffer, PINDEX & ptr, WORD & len){ PINDEX s = buffer.GetSize(); if (ptr >= s) return FALSE; BYTE ch = buffer[ptr++]; if ((ch & ASN_LONG_LEN) == 0) len = (WORD)ch; else if ((ch & ~ASN_LONG_LEN) == 0x01) { if (ptr >= s) return FALSE; len = (WORD)buffer[ptr++]; } else { if (ptr + 1 >= s) return FALSE; len = (WORD)((buffer[ptr] << 8) + buffer[ptr+1]); ptr += 2; } return TRUE;}WORD PASNObject::GetASNLengthLength (WORD length) { // handle lengths less then 128 if (length < 128) return 1; // handle lengths less than 256 else if (length < 256) return 2; // handle lengths up to 0xffff else return 3;}void PASNObject::EncodeASNSequenceStart(PBYTEArray & buffer, BYTE type, WORD length) { buffer[buffer.GetSize()] = type; EncodeASNLength(buffer, length);}WORD PASNObject::GetASNSequenceStartLength(WORD length) { return (WORD)(1 + GetASNLengthLength(length));}void PASNObject::EncodeASNHeader(PBYTEArray & buffer, PASNObject::ASNType type, WORD length){ buffer[buffer.GetSize()] = ASNTypeToType[type]; EncodeASNLength(buffer, length);}WORD PASNObject::GetASNHeaderLength(WORD length) { return (WORD)(1 + GetASNLengthLength(length));}void PASNObject::EncodeASNInteger (PBYTEArray & buffer, PASNInt data, PASNObject::ASNType type){ DWORD mask; WORD intsize = sizeof(data); // create a mask which is the top nine bits of a DWORD, or 0xFF800000 // on a big endian machine mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1); // remove all sequences of nine 0's or 1's at the start of the value while ((((data & mask) == 0) || ((data & mask) == mask)) && intsize > 1) { intsize--; data <<= 8; } // insert the header EncodeASNHeader(buffer, type, intsize); // insert the data PINDEX offs = buffer.GetSize(); mask = 0xFFL << (8 * (sizeof(DWORD) - 1)); while (intsize--) { buffer[offs++] = (u_char)((data & mask) >> (8 * (sizeof(DWORD) - 1))); data <<= 8; }}void PASNObject::EncodeASNUnsigned (PBYTEArray & buffer, PASNUnsigned data, PASNObject::ASNType type){ long mask; WORD intsize = sizeof(data); int add_null_byte = 0; mask = 0xFFL << (8 * (sizeof(long) - 1)); /* mask is 0xFF000000 on a big-endian machine */ if ((u_char)((data & mask) >> (8 * (sizeof(PASNUnsigned) - 1))) & 0x80){ /* if MSB is set */ add_null_byte = 1; intsize++; } // create a mask which is the top nine bits of a DWORD, or 0xFF800000 // on a big endian machine mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1); // remove all sequences of nine 0's or 1's at the start of the value while ((((data & mask) == 0) || (((long)data & mask) == mask)) && intsize > 1) { intsize--; data <<= 8; } // insert the header EncodeASNHeader(buffer, type, intsize); // insert the data PINDEX offs = buffer.GetSize(); mask = 0xFFL << (8 * (sizeof(DWORD) - 1)); while (intsize--) { buffer[offs++] = (u_char)((data & mask) >> (8 * (sizeof(DWORD) - 1))); data <<= 8; } if (add_null_byte == 1) buffer[offs++] = 0;}BOOL PASNObject::DecodeASNInteger(const PBYTEArray & buffer, PINDEX & ptr, PASNInt & value, PASNObject::ASNType theType){ if (buffer[ptr++] != ASNTypeToType[theType]) return FALSE; WORD len; if (!DecodeASNLength(buffer, ptr, len)) return FALSE; if (ptr + len > buffer.GetSize()) return FALSE; if (buffer[ptr] & 0x80) value = -1; /* integer is negative */ else value = 0; while (len--) value = (value << 8) | buffer[ptr++]; return TRUE;}BOOL PASNObject::DecodeASNUnsigned(const PBYTEArray & buffer, PINDEX & ptr, PASNUnsigned & value, PASNObject::ASNType theType){ if (buffer[ptr++] != ASNTypeToType[theType]) return FALSE; WORD len; if (!DecodeASNLength(buffer, ptr, len)) return FALSE; if (ptr + len > buffer.GetSize()) return FALSE;// if (buffer[ptr] & 0x80)// value = -1; /* integer is negative */ value = 0; while (len--) value = (value << 8) | buffer[ptr++]; return TRUE;}WORD PASNObject::GetASNIntegerLength(PASNInt data) { DWORD mask; WORD intsize = sizeof(data); // create a mask which is the top nine bits of a DWORD, or 0xFF800000 // on a big endian machine mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1); // remove all sequences of nine 0's or 1's at the start of the value while ((((data & mask) == 0) || ((data & mask) == mask)) && intsize > 1) { intsize--; data <<= 8; } // get the length of the header return (WORD)(intsize + GetASNHeaderLength(intsize));}WORD PASNObject::GetASNUnsignedLength (PASNUnsigned data){ long mask; WORD intsize = sizeof(data); int add_null_byte = 0; mask = 0xFFL << (8 * (sizeof(long) - 1)); /* mask is 0xFF000000 on a big-endian machine */ if ((u_char)((data & mask) >> (8 * (sizeof(PASNUnsigned) - 1))) & 0x80) { /* if MSB is set */ add_null_byte = 1; intsize++; } // create a mask which is the top nine bits of a DWORD, or 0xFF800000 // on a big endian machine mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1); // remove all sequences of nine 0's or 1's at the start of the value while ((((data & mask) == 0) || (((long)data & mask) == mask)) && intsize > 1) { intsize--; data <<= 8; } // insert the header return (WORD)(intsize + GetASNHeaderLength(intsize) + add_null_byte);}PASNInt PASNObject::GetInteger () const{ PAssertAlways("Cannot return ASN object as Integer"); return 0;}PString PASNObject::GetString () const{ PAssertAlways("Cannot return ASN object as String"); return PString();}PASNUnsigned PASNObject::GetUnsigned() const{ PAssertAlways("Cannot return ASN object as Unsigned"); return 0;}const PASNSequence & PASNObject::GetSequence() const{ PAssertAlways("Cannot return ASN object as Sequence"); PASNSequence * ptr = NULL; return (PASNSequence &)*ptr;}PIPSocket::Address PASNObject::GetIPAddress () const{ PAssertAlways("Cannot return ASN object as IP Address"); return PIPSocket::Address();}////////////////////////////////////////////////////////////////////////////// PASNInteger// A descendant of PASNObject which is a simple ASN integer type//PASNInteger::PASNInteger(PASNInt val){ value = val;}PASNInteger::PASNInteger(const PBYTEArray & buffer, PINDEX & ptr){ DecodeASNInteger(buffer, ptr, value, Integer);}void PASNInteger::PrintOn(ostream & strm) const{ strm << "Integer: " << value << endl;}void PASNInteger::Encode(PBYTEArray & buffer){ EncodeASNInteger(buffer, value, Integer);}WORD PASNInteger::GetEncodedLength(){ return GetASNIntegerLength(value);}PASNObject::ASNType PASNInteger::GetType() const{ return Integer;}PString PASNInteger::GetTypeAsString() const{ return PString("Integer");}PASNInt PASNInteger::GetInteger () const{ return value;}PString PASNInteger::GetString () const{ return PString(PString::Signed, (long)value);}PObject * PASNInteger::Clone() const{ return new PASNInteger(*this);}////////////////////////////////////////////////////////////////////////////// PASNString// A descendant of PASNObject which is a simple ASN OctetStr type//PASNString::PASNString(const PString & str){ value = str; valueLen = (WORD)str.GetLength();}PASNString::PASNString(const BYTE * ptr, int len){ value = PString((const char *)ptr, len); valueLen = (WORD)len;}PASNString::PASNString(const PBYTEArray & buffer, PASNObject::ASNType type){ PINDEX ptr = 0; Decode(buffer, ptr, type);}PASNString::PASNString(const PBYTEArray & buffer, PINDEX & ptr, PASNObject::ASNType type){ Decode(buffer, ptr, type);}BOOL PASNString::Decode(const PBYTEArray & buffer, PINDEX & ptr, PASNObject::ASNType type){ valueLen = 0; if (buffer[ptr++] != ASNTypeToType[type]) return FALSE; if (!DecodeASNLength(buffer, ptr, valueLen)) return FALSE; if (ptr + valueLen > buffer.GetSize()) return FALSE; value = PString(ptr + (const char *)(const BYTE *)buffer, valueLen); ptr += valueLen; return TRUE;}void PASNString::PrintOn(ostream & strm) const{ strm << GetTypeAsString() << ": " << value << endl; }void PASNString::Encode(PBYTEArray & buffer, PASNObject::ASNType type){ // insert the header EncodeASNHeader(buffer, type, valueLen); // add the string PINDEX offs = buffer.GetSize(); for (PINDEX i = 0; i < valueLen; i++) buffer[offs+i] = value[i];}WORD PASNString::GetEncodedLength(){ return (WORD)(GetASNHeaderLength(valueLen) + (int)valueLen);}PASNObject::ASNType PASNString::GetType() const{ return String;}PString PASNString::GetTypeAsString() const{ return PString("String");}PString PASNString::GetString () const{ return value;}PObject * PASNString::Clone() const{ return new PASNString(*this);}////////////////////////////////////////////////////////////////////////////// PASNUnsignedInteger// A descendant of PASNObject which is an unsigned integerBOOL PASNUnsignedInteger::Decode(const PBYTEArray & buffer, PINDEX & ptr, PASNObject::ASNType theType){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -