SNMP -- snmp协议报文说明

标签: C  snmp

1,snmp报文图片

snmpæ¥ææ ¼å¼PDU

2,snmp协议报文拆分说明

      1)前提: snmp数据报文格式均为: tpye - length - value 的方式

       2)snmp报文解析

        如上图蓝色所示,即为snmp报文内容:

2.1 SNMP头部

        # 30 27 : 0x30 type = snmp消息 | 0x27 length = 长度

        # 02 01 00 ... 00 05 00 为 value;

2.2 SNMP版本号(type - length - value)

        # 02 01 00 :02 类型 01为长度 00 为snmp版本
(02为数据类型integer|01为此段消息长度,00为snmp版本1|01为v2c | 02为snmpv2|03为snmpv3)

2.3 SNMP共同体

        # 04 06 70 75 62 6c 68 63 
(04 (octet string) + 数据长度 + 实际共同体字符)


2.4 SNMP PDU类型 (type - length - value)

       # a0 1a 02 02 0f ff ... 00 05 00

      a0 为 snmp pdu类型 ,具体见下

PDU类型

名称

a0

get-request

a1

get-next-request

a2

get-response

a3

set-request

a4

trap

2.5 SNMP Request ID

    #  02 02 0f ff 

    snmp request ID值是任意的,作用为,在get-response,snmp服务的回应对应数据时,需要使用一样的 Request ID(原因UDP协议是不可靠协议,加入request ID 作为数据返回的判断)


2.7 SNMP error-status | SNMP error-index

    # SNMP error-status  : 02 01 00 (值都为0)

    # SNMP error-index   : 02 01 00
error-status :0无错误|1toobig|2noSuchName|3badValue|4readonly|5genErr

     
0 no error   
1 too big  
2 no such name 没有此变量名称
3 bad value set操作下发了错误的值
4 read only set操作了只读节点
5 gen error 一般未知错误


2.7 ANS.1 SEQUENCE类型

    # 30 0e  0x30 为类型  0e为长度


2.8 Variable-bindings (此处下面可包含多个 OID-VALUE)

  # 30 0c   

      ASN.1 Object Identifier  -- OID的名称 (符合type-length-value)

      ASN.1 value (OID的值) 05 00 (get等操作下 填写null 就是05 00|在response下,就是type-length-value | 在 set操作下,下发的值就是放在此处)

3,SNMP 常用类型
ASN.1 类型ID:
integer  0x02
octet string 0x04
null 0x05
object identifier 0x06
sequence 0x30

snmp 应用类型ID:
ipAddress 0x40
counter 0x41
gauge 0x42
timeticks 0x43
opague 0x44

 

4,在编程中出现了 [Malformed Packet: SNMP]

错误原因是:snmp协议模式是:type - length - value的,其中一处的 length 错误,则wiresharke抓包就会提示这样的错误。

 

5,附 组合snmp 帧的简单代码

#include <stdio.h>
#include <sys/types.h>			/* See NOTES */
#include <sys/socket.h>
#include<netinet/in.h>
#include <string.h>

typedef char oid;
#define BUF_MAX 1024
#define _GET 0
#define _GET_NEXT 1
#define _GET_RESPONE 2
#define _SET 3
#define _TRAP 4

static char *snmp_frame = NULL;
/*完成snmp整个帧的填充,并拷贝到指针*/
int snmp_head( char *buf, int len ) {
	int n = 0;
	char tmp[BUF_MAX] = {0};
	tmp[n++] = 0x30;
	tmp[n++] = len;
	memcpy(&tmp[n],buf,len);
	n += len;
	snmp_frame = (char *)malloc( n + 1);
	if( snmp_frame == NULL ) {
		perror("frame error:");
	} else {
		memcpy(snmp_frame,tmp,n);
	}
	return n;
	
}
/*填充snmp 版本信息 及 共同体*/
int version_public(char *data,int len) {
	int n = 0;
	const char *communit = "public";
	int nlen = strlen(communit);
	char tmp[BUF_MAX] = {0};
	tmp[n++] = 0x02;
	tmp[n++] = 0x01;
	tmp[n++] = 0x00;
	tmp[n++] = 0x04;
	tmp[n++] = nlen;
	memcpy(&tmp[n],communit,nlen);
	n += nlen;
	memcpy(&tmp[n],data,len);
	n += len;
	n = snmp_head(tmp,n);
	return n;
}
/*组合snmp data 的头部信息 : 类型 长度 值*/
int snmp_data(int stype, char *error_bindings , int len ) {
	int n = 0;
	char tmp[BUF_MAX] = {0};
	tmp[n++] = 0xa0 + stype;
	tmp[n++] = len;
	memcpy(&tmp[n],error_bindings,len);
	n += len;
	n = version_public(tmp,n);
	return n;
}
/*组合snmp request-id 和 error-status error-index*/
int error_info(int stype,char *bindings,int len) {
	int n = 0;
	int id = time(NULL);
	char tmp[BUF_MAX] = {0};
	tmp[n++] = 0x02;
	tmp[n++] = sizeof(id);
	memcpy(&tmp[n],&id,sizeof(id));
	n += sizeof(id);
	tmp[n++] = 0x02;
	tmp[n++] = 0x01;
	tmp[n++] = 0x00;
	tmp[n++] = 0x02;
	tmp[n++] = 0x01;
	tmp[n++] = 0x00;
	memcpy(&tmp[n],bindings,len);
	n += len;
	n = snmp_data(stype,tmp,n);
	return n;
}
/*组合variable-bindings 的头部信息*/
int variable_bindings(int stype, char *item, int len ) {
	int n = 0;
	char tmp[BUF_MAX] = {0};
	tmp[n++] = 0x30;
	tmp[n++] = len + 2;
	tmp[n++] = 0x30;
	tmp[n++] = len;
	memcpy(&tmp[n],item,len);
	n += len;
	n = error_info(stype,tmp,n);
	return n;
}
/*先组合OID和OID对应的值*/
int build_snmp_frame( int stype, oid *targoid, int olen, int vtype,const char *value,int vlen ) {
	int rlen = 0;
	char tmp[BUF_MAX] = {0};
	tmp[rlen++] = 0x06; 
	tmp[rlen++] = olen;
	memcpy(&tmp[rlen],targoid,olen);
	rlen += olen;
	switch( stype ) {
		case 3 :
			if( value == NULL ) {
				return -1;
			} else {
				tmp[rlen++] = vtype;
				tmp[rlen++] = vlen;
				memcpy(&tmp[rlen],value,vlen);
				rlen += vlen;
			}
		break;
		default :
			tmp[rlen++] = 0x05;
			tmp[rlen++] = 0x00;
		break;
	}
	rlen = variable_bindings(stype,tmp,rlen);
	return rlen;
}
int main(void) {
	int sock = 0;
	char buff[2048] = {0};
	oid tmp[12] = {0x2b,0x6,0x1,0x2,0x1,0x1,0x4,0x0};
	int n = 0;
	const char *setv = "111111111";
	n = build_snmp_frame(0,tmp,8,4,setv,strlen(setv));
	#if 1
	sock = socket(AF_INET,SOCK_DGRAM,0);
	if( sock < 0 ) perror("upd:");
	struct sockaddr_in svr = {0};
	svr.sin_family = AF_INET;
	inet_pton(AF_INET,"172.16.200.107",&svr.sin_addr);
	svr.sin_port = htons(161);
	if ( snmp_frame ) {
		sendto(sock,snmp_frame,n ,0,(struct sockaddr *)&svr,sizeof(svr));
		free(snmp_frame);
	}
	#endif
	
	return 0;
}

 

版权声明:本文为u013625451原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u013625451/article/details/105049388

智能推荐

RIP/DHCP/ACL综合实验

组播: 加入组的组成员才会接受到消息,只需要将流量发送一次到组播地址 减少控制面流量,减少头部复制, RIP1  广播   有类  不支持认证 RIP2  组播   无类  (支持VLAN)、支持认证 所有距离矢量路由协议:具有距离矢量特征的协议,都会在边界自动汇总 控制平面  路由的产生是控制平面的流量 数据平面  ...

【Sublime】使用 Sublime 工具时运行python文件

使用 Sublime 工具时报Decode error - output not utf-8解决办法   在菜单中tools中第四项编译系统 内最后一项增添新的编译系统 自动新建 Python.sublime-build文件,并添加"encoding":"cp936"这一行,保存即可 使用python2 则注释encoding改为utf-8 ctr...

java乐观锁和悲观锁最底层的实现

1. CAS实现的乐观锁 CAS(Compare And Swap 比较并且替换)是乐观锁的一种实现方式,是一种轻量级锁,JUC 中很多工具类的实现就是基于 CAS 的,也可以理解为自旋锁 JUC是指import java.util.concurrent下面的包, 比如:import java.util.concurrent.atomic.AtomicInteger; 最终实现是汇编指令:lock...

Python 中各种imread函数的区别与联系

  原博客:https://blog.csdn.net/renelian1572/article/details/78761278 最近一直在用python做图像处理相关的东西,被各种imread函数搞得很头疼,因此今天决定将这些imread总结一下,以免以后因此犯些愚蠢的错误。如果你正好也对此感到困惑可以看下这篇总结。当然,要了解具体的细节,还是应该 read the fuc...

用栈判断一个字符串是否平衡

注: (1)本文定义:左符号:‘(’、‘[’、‘{’…… 右符号:‘)’、‘]’、‘}’……. (2)所谓的字符串的符号平衡,是指字符串中的左符号与右符号对应且相等,如字符串中的如‘(&r...

猜你喜欢

JAVA环境变量配置

位置 计算机->属性->高级系统设置->环境变量 方式一 用户变量新建path 系统变量新建classpath 方式二 系统变量 新建JAVA_HOME,值为JDK路径 编辑path,前加 方式三 用户变量新建JAVA_HOME 此路径含lib、bin、jre等文件夹。后运行tomcat,eclipse等需此变量,故最好设。 用户变量编辑Path,前加 系统可在任何路径识别jav...

常用的伪类选择器

CSS选择器众多 CSS选择器及权重计算 最常用的莫过于类选择器,其它的相对用的就不会那么多了,当然属性选择器和为类选择器用的也会比较多,这里我们就常用的伪类选择器来讲一讲。 什么是伪类选择器? CSS伪类是用来添加一些选择器的特殊效果。 常用的为类选择器 状态伪类 我们中最常见的为类选择器就是a标签(链接)上的为类选择器。 当我们使用它们的时候,需要遵循一定的顺序问题,否则将可能出现bug 注意...

ButterKnife的使用介绍及原理探究(六)

前面分析了ButterKnife的源码,了解其实现原理,那么就将原理运用于实践吧。 github地址:       点击打开链接 一、自定义注解 这里为了便于理解,只提供BindView注解。 二、添加注解处理器 添加ViewInjectProcessor注解处理器,看代码, 这里分别实现了init、getSupportedAnnotationTypes、g...

1.写一个程序,提示输入两个字符串,然后进行比较,输出较小的字符串。考试复习题库1|要求:只能使用单字符比较操作。

1.写一个程序,提示输入两个字符串,然后进行比较,输出较小的字符串。 要求只能使用单字符比较操作。 参考代码: 实验结果截图:...

小demo:slideDown()实现二级菜单栏下拉效果

效果如下,鼠标经过显示隐藏的二级菜单栏 但是这样的时候会存在一个问题,就是鼠标快速不停移入移出会导致二级菜单栏闪屏现象,一般需要使用stop()来清除事件  ...