简介
略
SNMP v3 设备端开源代码
到达官网 https://sourceforge.net/projects/net-snmp/
官方目录:code下载源码
SNMP v3代码初始化的总结口
函数:SnmpDaemonMain()
Linux os设备常用初始化方法:
通过task进行初始化:TaskID = taskSpawn(“task name”, pri, opt, stacksize, (FUNCPTR)SnmpDaemonMain, 0, 0, 0, 0, 0);
设备端端口更改
SNMPv3默认端口为161,也可以进行更改
已端口161 更改为1025 为例:
更改接口位置:
SnmpDaemonMain -> init_snmp -> _init_snmp() ->
snmp mib 位置:
netsnmp_register_default_target(“snmp”, “udp”, “:161”)
更改为
netsnmp_register_default_target(“snmp”, “udp”, “:1025”)
snmp trap 位置:
netsnmp_register_default_target(“snmptrap”, “udp”, “:162”)
VPN绑定
SNMPv3开源代码是没有将vpn代码绑定功能加进来的,但是别人是把架子搭好了
代码调用的位置:
-
SnmpDaemonMain -> init_master_agent -> netsnmp_agent_listen_on -> netsmp_transport_open_server(“snmp”, port) -> netsnmp_tdomain_transport_full(application, str, local, NULL, NULL)
-
SnmpDaemonMain -> real_init_master -> netsmp_transport_open_server(“agentx”, sess.peername) -> netsnmp_tdomain_transport_full(application, str, local, NULL, NULL)
可以观察到 1 和 2 的调用都指向函数 netsnmp_tdomain_transport_full(application, str, local, NULL, NULL)
函数 netsnmp_tdomain_transport_full
第五个入参 const char *default_target 为设置vpn参数
入参个格式:
@: 例子:1.1.1.1@iface161代码绑定套接字:
代码位置:
netsnmp_tdomain_transport_full -> netsnmp_tdomain_transport_tspec(&tspec) ->
– match -> f_create_from_tspec
– match -> f_create_from_tstring
– match -> f_create_from_tstring_new
注册函数:
netsnmp_aal5pvc_ctor
netsnmp_alias_ctor
netsnmp_dtlsudp_ctor
netsnm_ipx_ctor
netsnmp_std_ctor
netsnmp_tcp_ctor
netsnmp_tcpipv6_ctor
netsnmp_udp_ctor
netsnmp_udpipv6_ctor
netsnmp_udpshared_ctor
netsnmp_unix_ctor
使用方法:
1.在函数netsmp_transport_open_server内部需要给netsnmp_tdomain_transport_full的第五个入参传值
2.需要注册相应业务函数,例如udp绑定vpn业务,需要调用netsnmp_udp_ctor函数注册回调函数,若不注册将无法执行
– match -> f_create_from_tspec
– match -> f_create_from_tstring
– match -> f_create_from_tstring_new
加入VPNid,为啥在走UDPv6绑定会出现错误?
tspec->target (str) = udp6:[::1]:161 (前缀prefix udp6 指向注册函数 netsnmp_udpipv6_ctor)
注册的函数:netsnmp_udpipv6_ctor
错误路径:SnmpDaemonMain -> init_master_agent -> netsnmp_agent_listen_on -> netsmp_transport_open_server(“snmp”, port) -> netsnmp_tdomain_transport_full(application, str, local, NULL, NULL) -> match -> f_create_from_tspec ->此时进入回调函数,在注册函数netsnmp_udpipv6_ctor里查找,这也是C语言中大多项目在运用的编码模式 -> netsnmp_udpipv6base_tspec_transport -> netsnmp_udp6_transport_with_source -> netsnmp_udp6_transport_bind -> bind(出错点)
netsnmp_udp6_transport_bind函数内部参数信息:
t->sock = 161
ep->iface == “vrf2”
addr->sin6_addr.s6_addr32[0] = 0
addr->sin6_addr.s6_addr32[1] = 0
addr->sin6_addr.s6_addr32[2] = 0
addr->sin6_addr.s6_addr32[3] = 10000000
绑定失败造成的致命错误:task未正常起来,导致MIBrowser get不到任何信息,并且shark抓包有接收信号,但包里没有数据
规避方案:
方案一
在开启vpnid绑定的时候(绑定方法参考《使用方法》),删除设备下/etc/snmp/snmpd.conf文本中的 udp6:[::1]:161
这样做的后果:不会走udp6的注册函数netsnmp_udpipv6_ctor,导致udpv6绑定失效,从而不支持udpv6功能。
方案二
直接不开启vpnid绑定
这样做的后果:vpn功能失效。
方案一,方案二都没有解决根本性问题,只是规避致命错误的方案。
最终解决方案是融合两者,也就是在加入了vpnid,为什么在走udpv6的时候,bind会出现错误
最终解决方案已找到:
错误地方:在初始化函数 SnmpDaemonMain()生成的配置文件 udp6:[::1]:161 中的 [::1] = 0.0.0.1 该地址是无效地址,从而导致绑定失败。
修改方案:在初始化写文本文档的时候,把udp6:[::1]:161 改为 udp6:[::]:161
修改原因:0.0.0.0和0.0.0.1都是IP地址,但是它们有着不同的含义。
0.0.0.0通常表示“任意地址”,用于表示当前主机上所有网络接口的地址,即所有可用的IP地址。在路由表中,当需要匹配目标IP地址时,如果路由表中某条路由的目标地址为0.0.0.0,则说明该路由适用于所有目标地址。
而0.0.0.1是一个具体的IP地址,它表示的是一个非法的地址,因为在IPv4地址中,每个分组只能取值为0~255。因此,使用0.0.0.1作为有效的IP地址是不合法的。
已经为大家踩过很多坑,记得收藏起来后面用得着。
****后续随缘更新,仅个人笔记慎重参考