• nodejs实现接收Snmp的Trap消息


    var assert = require('assert');
    
    var ASN1 = {
    	EOC: 0,
    	Boolean: 1,
    	Integer: 2,
    	BitString: 3,
    	OctetString: 4,
    	Null: 5,
    	OID: 6,
    	ObjectDescriptor: 7,
    	External: 8,
    	Real: 9, // float
    	Enumeration: 10,
    	PDV: 11,
    	Utf8String: 12,
    	RelativeOID: 13,
    	Sequence: 16,
    	Set: 17,
    	NumericString: 18,
    	PrintableString: 19,
    	T61String: 20,
    	VideotexString: 21,
    	IA5String: 22,
    	UTCTime: 23,
    	GeneralizedTime: 24,
    	GraphicString: 25,
    	VisibleString: 26,
    	GeneralString: 28,
    	UniversalString: 29,
    	CharacterString: 30,
    	BMPString: 31,
    	Constructor: 32,
    	Context: 128,
    
    	TypeError: function(msg) {
    		var e = new Error();
    		e.name = 'InvalidAsn1Error';
    		e.message = msg || '';
    		return e;
    	}
    };
    
    function Reader(data) {
    	if (!data || !Buffer.isBuffer(data))
    	throw new TypeError('data must be a node Buffer');
    
    	this._buf = data;
    	this._size = data.length;
    
    	// These hold the "current" state
    	this._len = 0;
    	this._offset = 0;
    
    	var self = this;
    	this.__defineGetter__('length', function() { return self._len; });
    	this.__defineGetter__('offset', function() { return self._offset; });
    	this.__defineGetter__('remain', function() {
    	return self._size - self._offset;
    	});
    	this.__defineGetter__('buffer', function() {
    	return self._buf.slice(self._offset);
    	});
    }
    
    
    /**
     * Reads a single byte and advances offset; you can pass in `true` to make this
     * a "peek" operation (i.e., get the byte, but don't advance the offset).
     *
     * @param {Boolean} peek true means don't move offset.
     * @return {Number} the next byte, null if not enough data.
     */
    Reader.prototype.readByte = function(peek) {
    	if (this._size - this._offset < 1)
    	return null;
    
    	var b = this._buf[this._offset] & 0xff;
    
    	if (!peek)
    	this._offset += 1;
    
    	return b;
    };
    
    
    Reader.prototype.peek = function() {
    	return this.readByte(true);
    };
    
    
    /**
     * Reads a (potentially) variable length off the BER buffer.  This call is
     * not really meant to be called directly, as callers have to manipulate
     * the internal buffer afterwards.
     *
     * As a result of this call, you can call `Reader.length`, until the
     * next thing called that does a readLength.
     *
     * @return {Number} the amount of offset to advance the buffer.
     * @throws {InvalidAsn1Error} on bad ASN.1
     */
    Reader.prototype.readLength = function(offset) {
    	if (offset === undefined)
    	offset = this._offset;
    
    	if (offset >= this._size)
    	return null;
    
    	var lenB = this._buf[offset++] & 0xff;
    	if (lenB === null)
    	return null;
    
    	if ((lenB & 0x80) == 0x80) {
    	lenB &= 0x7f;
    
    	if (lenB == 0)
    	  throw ASN1.TypeError('Indefinite length not supported');
    
    	if (lenB > 4)
    	  throw ASN1.TypeError('encoding too long');
    
    	if (this._size - offset < lenB)
    	  return null;
    
    	this._len = 0;
    	for (var i = 0; i < lenB; i++)
    	  this._len = (this._len << 8) + (this._buf[offset++] & 0xff);
    
    	} else {
    	// Wasn't a variable length
    	this._len = lenB;
    	}
    
    	return offset;
    };
    
    
    /**
     * Parses the next sequence in this BER buffer.
     *
     * To get the length of the sequence, call `Reader.length`.
     *
     * @return {Number} the sequence's tag.
     */
    Reader.prototype.readSequence = function(tag) {
      var seq = this.peek();
      if (seq === null)
    	return null;
      if (tag !== undefined && tag !== seq)
    	throw ASN1.TypeError('Expected 0x' + tag.toString(16) + ': got 0x' + seq.toString(16));
    
      var o = this.readLength(this._offset + 1); // stored in `length`
      if (o === null)
    	return null;
    
      this._offset = o;
      return seq;
    };
    
    
    Reader.prototype.readInt = function() {
      return this.readTag(ASN1.Integer);
    };
    
    
    Reader.prototype.readBoolean = function() {
      return (this.readTag(ASN1.Boolean) === 0 ? false : true);
    };
    
    
    Reader.prototype.readEnumeration = function() {
      return this.readTag(ASN1.Enumeration);
    };
    
    
    Reader.prototype.readString = function(tag, retbuf) {
      if (!tag)
    	tag = ASN1.OctetString;
    
      var b = this.peek();
      if (b === null)
    	return null;
    
      if (b !== tag)
    	throw ASN1.TypeError('Expected 0x' + tag.toString(16) + ': got 0x' + b.toString(16));
    
      var o = this.readLength(this._offset + 1); // stored in `length`
    
      if (o === null)
    	return null;
    
      if (this.length > this._size - o)
    	return null;
    
      this._offset = o;
    
      if (this.length === 0)
    	return retbuf ? new Buffer(0) : '';
    
      var str = this._buf.slice(this._offset, this._offset + this.length);
      this._offset += this.length;
    
      return retbuf ? str : str.toString('utf8');
    };
    
    Reader.prototype.readOID = function(tag) {
      if (!tag)
    	tag = ASN1.OID;
    
      var b = this.readString(tag, true);
      if (b === null)
    	return null;
    
      var values = [];
      var value = 0;
    
      for (var i = 0; i < b.length; i++) {
    	var byte = b[i] & 0xff;
    
    	value <<= 7;
    	value += byte & 0x7f;
    	if ((byte & 0x80) == 0) {
    	  values.push(value);
    	  value = 0;
    	}
      }
    
      value = values.shift();
      values.unshift(value % 40);
      values.unshift((value / 40) >> 0);
    
      return values.join('.');
    };
    
    
    Reader.prototype.readTag = function(tag) {
      assert.ok(tag !== undefined);
    
      var b = this.peek();
    
      if (b === null)
    	return null;
    
      if (b !== tag)
    	throw ASN1.TypeError('Expected 0x' + tag.toString(16) + ': got 0x' + b.toString(16));
    
      var o = this.readLength(this._offset + 1); // stored in `length`
      if (o === null)
    	return null;
    
      if (this.length > 4)
    	throw ASN1.TypeError('Integer too long: ' + this.length);
    
      if (this.length > this._size - o)
    	return null;
      this._offset = o;
    
      var fb = this._buf[this._offset];
      var value = 0;
    
      for (var i = 0; i < this.length; i++) {
    	value <<= 8;
    	value |= (this._buf[this._offset++] & 0xff);
      }
    
      if ((fb & 0x80) == 0x80 && i !== 4)
    	value -= (1 << (i * 8));
    
      return value >> 0;
    };
    
    
    var dgram = require("dgram");
    function parseTrapPacket(buffer){
    	var pkt = {};
    	var reader = new Reader(buffer);
    	reader.readSequence();
    	pkt.version = reader.readInt();//02 01 00
    	pkt.community = reader.readString();//04 06 70 75 62 6c 69 63
    	pkt.type = reader.readSequence();//a4
    	pkt.enterprise = reader.readOID()//0x06, 0x0c, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x91, 0x28, 0x02, 0x02, 0x47, 0x64
    	var bytes = reader.readString(64, true);//0x40, 0x04, 0xc0, 0xa8, 0x17, 0x0a,
    	pkt.agentAddr = bytes[0] + "." + bytes[1] + "." + bytes[2] + "." + bytes[3];
    	pkt.specific = reader.readInt();// 0x02, 0x01, 0x06,
    	pkt.generic = reader.readInt();//0x02, 0x01, 0x0a
    	pkt.upTime = reader.readTag(67);//
    	pkt.varbinds = readVarbinds(reader);
    	return pkt;
    };
    function readVarbinds (reader) {
    	var vbs = [];
    	reader.readSequence ();
    	while (1) {
    		reader.readSequence();
    		var oid = reader.readOID (), type = reader.peek (), value = '';
    		if (type == null) break;
    
    		switch(type){
    			case 1:
    				value = reader.readBoolean();
    			break;
    			case 2:
    			case 65:
    			case 66:
    			case 67:
    				value = reader.readTag(2);
    			break;
    			case 4:
    				value = reader.readString (null);
    			break;
    			case 5:
    			case 128:
    			case 129:
    			case 130:
    				reader.readByte ();
    				reader.readByte ();
    				value = null;
    			break;
    			case 6:
    				value = reader.readOID();
    			break;
    			case 64:
    				var bytes = reader.readString(64, true);
    				value = bytes.length == 4 ? bytes[0] + '.' + bytes[1] + '.' + bytes[2] + '.' + bytes[3] : '';
    			break;
    			case 68:
    			case 70:
    				value = reader.readString(type, true);
    			break;
    		}
    		vbs.push ({
    			oid: oid,
    			type: type,
    			value: value
    		});
    	}
    	return vbs;
    }
    function Receiver(port, onTrap, onError, onStart){
    	this.port = port;
    	this.socket = null;
    	this.isRunning = false;
    	this.onTrap = onTrap;
    	this.onError = onError;
    	this.onStart = onStart;
    };
    Receiver.prototype.start = function(){
    	var self = this;
    	if(self.isRunning) return;
    	var socket = self.socket =  dgram.createSocket('udp4');
    	socket.on('error', function(err){
    		socket.close();
    		self.isRunning = false;
    		if(self.onError){
    			self.onError(err);
    		}
    	});
    	socket.on('message', function(msg, remote){
    		if(self.onTrap){
    			var pkt = parseTrapPacket(msg);
    			self.onTrap(remote, pkt);
    		}
    	});
    	socket.on('listening', function(){
    		self.isRunning = true;
    		if(self.onStart){
    			self.onStart(self.port);
    		}
    	});
    	socket.bind(self.port);
    };
    Receiver.prototype.stop = function(){
    	var self = this;
    	if(self.isRunning){
    		if(self.socket){
    			self.socket.close();
    			self.isRunning = false;
    		}
    	}
    };
    
    var trap = new Receiver(162, function(remote, pkt){
    	console.log(JSON.stringify(remote), JSON.stringify(pkt));
    }, '', function(port){
    	console.log('begin listen on ' + port);
    });
    trap.start();
    
    module.exports.TrapReceiver = Receiver;
    

      

  • 相关阅读:
    餐巾计划问题 zwk费用流解法
    Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵
    smarty之缓存机制
    mysql中 where in 用法详解
    sql语句中left join、inner join中的on与where的区别
    PHP表单数组的具体使用方法介绍
    document.body.scrollTop值为0的解决方法[转]
    left join on and和left join on where条件的困惑[转]
    Uedit32_17.00 修改某一语言背景色-修改后续名后语法着色及某语言的大括号{}对齐
    CSS 针对谷歌浏览器(Chrome) safari的webkit核心浏览器CSS hack
  • 原文地址:https://www.cnblogs.com/zh33gl/p/4763197.html
Copyright © 2020-2023  润新知