SNMP源码分析

news2024/12/28 10:52:45

源码下载

http://www.net-snmp.org/download.html

源码目录结构

在这里插入图片描述

net-snmp程序逻辑

(1)main主函数

#ifdef WIN32SERVICE  //windows系统下使用snmp
static int
SnmpDaemonMain(int argc, TCHAR * argv[])
#else	//linux系统
int
main(int argc, char *argv[])  //主函数
#endif
{
    static const char options[] = "aAc:CdD::fhHI:l:L:m:M:n:p:P:qrsS:UvV-:Y:"  //支持的一些参数,比如snmpd -v
    
    /*下面是一些switch-case,根据输入参数返回不同的内容。比如输入snmpd -v,走到 case 'v':
            version();
            exit_code = 0;
            goto out;
	  调用version()函数<见下文>,返回
	  $:snmpd -v
		NET-SNMP version:  5.8
		Web:               http://www.net-snmp.org/
		Email:             net-snmp-coders@lists.sourceforge.net
	*/

业务逻辑代码分析见下文:
static void
version(void)
{
    printf("\nNET-SNMP version:  %s\n"
           "Web:               http://www.net-snmp.org/\n"
           "Email:             net-snmp-coders@lists.sourceforge.net\n\n",
           netsnmp_get_version());
}

搜了两篇不错的源码分析:
篇一:
snmpd代理(main主函数位于:net-snmp-5.9.3\agent\snmpd.c)完成两个功能:
1、接收网管发过来的snmp包,并对接收到的snmp包进行解析,校验后,找到并调用相应的处理函数进行处理。
2、调用注册了的告警函数,向网管发送告警信息。
Net-snmp代码流程图:(https://blog.csdn.net/jiangxin04211/category_9271012.html)
在这里插入图片描述
篇二:
在这里插入图片描述
来源:https://blog.csdn.net/fuyuande/article/details/83047765
以上两篇梳理的已经非常详细,不再赘述。

(2)整体框架

一般的网络框架处理流程如下(net-snmp也类似):

 - 使用IO多路复用(linux下的select, poll, epoll)分离网络IO。
 - 对分离出来的网络IO进行操作,分为socket句柄可读、可写和出错三种情况。
 - 定时器事件,即检测一个定时器事件列表,如果有定时器到期,则执行该定时器事件。
while (netsnmp_running) 
{
    //更新配置文件
    update_config();
    
    //IO multiplexing
    count = netsnmp_large_fd_set_select(numfds, &readfds, &writefds, &exceptfds, tvp);
    if(count)
    {
        snmp_read2(&readfds);
    }
    
    /*
     * 如果更新配置之后,要先保存配置,防止之后崩溃
     */
     snmp_store_if_needed();

     /*
      * 处理定时器事件
      */
      run_alarms();

     netsnmp_check_outstanding_agent_requests();
}

run_alarms()函数:处理定时器事件。即遍历一个升序定时器列表,将定时器对象与当前时间(t_now)做比较,如果当前时间已经大于或等于定时器设置的时间,则表明定时器时间已经到了,执行定时器对应的回调函数。

void
snmp_read2(netsnmp_large_fd_set * fdset) --> snmp_sess_read2 --> _sess_read函数:

int
_sess_read(void *sessp, netsnmp_large_fd_set * fdset)
{
    if (transport->flags & NETSNMP_TRANSPORT_FLAG_LISTEN) 
    {
        int             data_sock = transport->f_accept(transport);
        return 0;
    }
    length = netsnmp_transport_recv(transport, rxbuf, rxbuf_len, &opaque,
                                    &olength);
     _sess_process_packet(sessp, sp, isp, transport,
                                           ocopy, ocopy?olength:0, pptr,
                                           pdulen)
}

_sess_read()函数根据状态标识transport->flags确定一个socket是侦听的socket还是普通与客户端连接的socket,如果是侦听sokcet则f_accept接收客户端的连接;如果是与客户端连接的socket,则先检测socket上有多少字节可读,如果没有字节可读或者检测字节数时出错,则关闭socket,反之调用处理函数。

snmpd程序使用一个session_list链表来管理所有的socket。

struct session_list *Sessions = NULL;   /* MT_LIB_SESSION */
netsnmp_session *
snmp_open(netsnmp_session *session)
{
    struct session_list *slp;
    slp = (struct session_list *) snmp_sess_open(session);
    if (!slp) {
        return NULL;
    }

    snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
    slp->next = Sessions;
    Sessions = slp;
    snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);

    return (slp->session);
}

int
snmp_close(netsnmp_session * session)
{
    struct session_list *slp = NULL, *oslp = NULL;

    {                           /*MTCRITICAL_RESOURCE */
        snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
        if (Sessions && Sessions->session == session) { /* If first entry */
            slp = Sessions;
            S

来源链接:https://www.jianshu.com/p/4998161c6c6f

(3)网络模块初始化

snmpd进程可以根据用户的配置来决定使用哪种协议来创建server,以某个协议为例子查看到接口注册流程如下:

init_snmp
    _init_snmp
        netsnmp_tdomain_init
            snmp_transport_inits.h
                netsnmp_tdomain_register(add domain_list(核心数据结构)//snmp_transport_inits.h
//使用宏来区分使用udp还是tcp协议,如下:
#ifdef NETSNMP_TRANSPORT_UDP_DOMAIN //为1
netsnmp_udp_ctor();
#endif
#ifdef NETSNMP_TRANSPORT_TCP_DOMAIN //为1
netsnmp_tcp_ctor();
#endif
#ifdef NETSNMP_TRANSPORT_ALIAS_DOMAIN
netsnmp_alias_ctor();
#endif
#ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
netsnmp_udpipv6_ctor();
#endif
#ifdef NETSNMP_TRANSPORT_TCPIPV6_DOMAIN
netsnmp_tcpipv6_ctor();
#endif

根据用户配置进行初始化流程如下:

init_master_agent
    netsnmp_tdomain_transport_full
        match = find_tdomain(mystring);//mystring即为用户的配置
            match->f_create_from_tstring_new(执行注册好的回调函数创建server)

调用过程可以使用如此命令进行查看,程序执行过程中会将相应的token打印在终端上,方便梳理逻辑:

snmpd  -Lo -f -Dsnmp_agent -Dread_config -Dtdomain

关键数据结构与接口:

typedef struct netsnmp_tdomain_s {
    const oid      *name;
    size_t          name_length;
    const char    **prefix;

    /*
     * The f_create_from_tstring field is deprecated, please do not use it
     * for new code and try to migrate old code away from using it.
     */
    netsnmp_transport *(*f_create_from_tstring) (const char *, int);

    netsnmp_transport *(*f_create_from_ostring) (const u_char *, size_t, int);

    struct netsnmp_tdomain_s *next;

    netsnmp_transport *(*f_create_from_tstring_new) (const char *, int,
                             const char*);

} netsnmp_tdomain;

/*
 * Our list of supported transport domains.  
 */

static netsnmp_tdomain *domain_list = NULL;

int             netsnmp_tdomain_register(netsnmp_tdomain *domain);
    
int             netsnmp_tdomain_unregister(netsnmp_tdomain *domain);

static netsnmp_tdomain *find_tdomain(const char* spec)

实现原理
将底层的tcp与udp处理数据的接口封装好,在上层创建一个中间层transport来隐藏底层的具体实现,使用一个链表来将具体的实现作为子节点连接起来,利用反射的方式根据用户的配置去找到对应的接口,去创建server,这是一个需要学习的思路。
来源链接:https://www.jianshu.com/p/6ec214aae144

梳理思路:

1、snmp基础概念:
https://www.jianshu.com/p/6a9e83aa41c0 (图-可参考)
https://blog.csdn.net/JIANGXIN04211/article/details/78444747 (内容-可参考)
以上图+内容两者结合理解。

2、https://blog.csdn.net/JIANGXIN04211/article/details/78444821 源码下载及编译安装
https://blog.csdn.net/JIANGXIN04211/article/details/78475155 扩展get
https://blog.csdn.net/JIANGXIN04211/article/details/78477890 扩展set
https://blog.csdn.net/JIANGXIN04211/article/details/78478429 扩展trap
以上扩展方式需要重新编译安装snmpd源码及重启程序,属于静态扩展方式,需要总结其他动态方式扩展。

3、源代码main-receive函数分析:
https://www.jianshu.com/p/4998161c6c6f

4、新增mib库转.c核心代码分析:(涉及如何修改适配应用这一块)
https://blog.csdn.net/JIANGXIN04211/article/details/78478581

5、梳理 项目 是如何动态扩展mib库的。

知识的搬运工,站在巨人肩膀上…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/195793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

吊打面试官,四面拿到阿里、字节 offer 后我还是选择了美团

祸兮福之所倚福兮祸之所伏 上学的时候对这句话不以为然&#xff0c;但是在社会上走的时间越长越觉得有道理 前不久好兄弟和领导闹矛盾裸辞了&#xff0c;身为好兄弟的我总不能干看着吧&#xff0c;总要帮他找工作的。(你们应该不会想我和他一起裸辞吧) 大学的师兄有好几个在大…

西门子200smart与组态王之间无线Profinet通信实例

在实际系统中&#xff0c;车间里分布多台PLC&#xff0c;需要用上位机软件集中控制。通常所有设备距离在几十米到上百米不等。在有通讯需求的时候&#xff0c;如果布线的话&#xff0c;工程量较大且不美观&#xff0c;这种情况下比较适合采用无线通信方式。本方案以组态王和2台…

19 | Rancher 使用介绍(管理 K8s 平台)

目录1 Rancher简介2 Rancher 安装2.1查看k8s的版本2.2 通过 Docker 来进行安装2.3 在 Rancher 的界面上绑定 K8s2.3.1 配置 Kubernetes 集群2.3.2 导入集群2.3.3 集群列表3 Rancher 上部署应用1 Rancher简介 Rancher 提供的功能&#xff1a; 支持 K8s 集群的身份验证和基于角色…

pod内时间时区与宿主机不一致

原因&#xff1a;pod内默认时区是UTC&#xff0c;宿主机时区是CST解决方式&#xff1a;一&#xff0c;如果仅仅是运行一个jar文件&#xff0c;可以使用如下命令&#xff1a;java -jar -Duser.timezoneGMT08 xxx.jar在k8s的Deployment文件中&#xff0c;加入上述JVM启动参数&…

一文读懂I/O模型

什么是IO呢&#xff1f;什么是阻塞非阻塞IO&#xff1f;什么是同步异步IO&#xff1f;什么是IO多路复用&#xff1f;select/epoll跟IO模型有什么关系&#xff1f;有几种经典IO模型呢&#xff1f;BIO、NIO、AIO到底有什么区别的&#xff1f; 如果这些问题&#xff0c;你都能很好…

hjr-微服务(六):如何保障服务稳定性

服务稳定是一个特别大的话题&#xff0c;一般我们用SLA描述服务的质量 SLA一般有99.9 &#xff0c;99.99&#xff0c;就是我们常说的三个9&#xff0c;四个9 有两个纬度衡量 时间纬度 请求纬度 请求的成功率计算方式&#xff1a;SL A 成功请求/&#xff08;成功请求请求失败…

【计算机网络】IP协议

网络层 在复杂的网络环境中寻找一条合适的路径传输数据 IP协议 IP指网际互连协议&#xff0c;Internet Protocol的缩写&#xff0c;是TCP/IP体系中的网络层协议。设计IP的目的是提高网络的可扩展性&#xff1a;一是解决互联网问题&#xff0c;实现大规模、异构网络的互联互通…

【先进设备】仅3mm!超薄款,足底压力步态测量分析系统

产品介绍足底压力步态测量分析系统是一套可用于采集人体足底压力的装置系统&#xff0c;其采用了高密度薄膜压力传感器矩阵&#xff0c;实现足底压力分布数据自动采集和分析&#xff0c;兼具大量程、高采集频率、高精度、高可靠性等特点&#xff0c;可以采集不同疾病的步态及足…

表白生日祝福和3D表白相册

作者&#xff1a;BSXY_19计科_陈永跃BSXY_信息学院注&#xff1a;未经允许禁止转发任何内容表白生日祝福和3D表白相册1、效果与展示2、资源下载3、PC版本生日祝福4、手机版本生日祝福5、动态相册6、如何给别人看1、效果与展示 好友给了我一个链接&#xff0c;我点看一看原来都…

【操作系统】2、进程管理

文章目录二、进程管理2.1 进程、线程的基本概念2.1.1 进程的组成和特性2.1.2 进程的状态和转换2.1.3 进程控制(理解)2.1.4 线程的概念2.1.5 线程的实现方式2.1.5.1 用户级线程2.1.5.2 内核级线程2.1.5.3 多线程模式2.1 6 线程的状态与转换2.2 进程同步2.2.1 概念2.2.2 进程互斥…

gitee通过idea上传新的项目流程

gitee通过idea上传新的项目流程今天开始分享 一、gitee服务端处理 1、登录gitee 服务端&#xff0c;创建仓库 2、点击创建 点击创建 3、创建完成 4、点击复制此仓库的地址&#xff1a;https://gitee.com/nandao1/demo2.git 下面idea会用到 二、idea客户端处理 1、创建demo…

物流行业有什么重要的指标,如何进行数据分析?

大数据是信息时代的典型特征&#xff0c;即通过收集、输入、储存、管理、分析对传统数据进行整合&#xff0c;在互联网的发展中其重要作用。目前大数据已经应用在很多领域中&#xff0c;并影响着各行各业&#xff0c;也有越来越多的行业开始关注大数据&#xff0c;例如“菜鸟网…

C语言数组指针(指向数组的指针)详解

数组&#xff08;Array&#xff09;是一系列具有相同类型的数据的集合&#xff0c;每一份数据叫做一个数组元素&#xff08;Element&#xff09;。数组中的所有元素在内存中是连续排列的&#xff0c;整个数组占用的是一块内存。以int arr[] { 99, 15, 100, 888, 252 };为例&am…

Homekit智能家居DIY-智能触摸面板开关

触摸开关&#xff0c;即通过触摸方式控制的墙壁开关&#xff0c;其感官场景如同我们的触屏手机&#xff0c;只需手指轻轻一点即可达到控制电器的目的&#xff0c;随着人们生活品质的提高&#xff0c;触摸开关将逐渐将换代传统机械按键开关。 触摸开关控制原理 触摸开关我们把…

VL6 多功能数据处理器

一、题目根据指示信号select的不同&#xff0c;对输入信号a,b实现不同的运算。输入信号a,b为8bit有符号数&#xff0c;当select信号为0&#xff0c;输出a&#xff1b;当select信号为1&#xff0c;输出b&#xff1b;当select信号为2&#xff0c;输出ab&#xff1b;当select信号为…

5、排序与分页

文章目录1 排序数据1.1 排序规则1.2 单列排序1.3 多列排序2 分页2.1 背景2.2 实现规则2.3 拓展尚硅谷MySQL数据库教程-讲师&#xff1a;宋红康 我们缺乏的不是知识&#xff0c;而是学而不厌的态度 1 排序数据 1.1 排序规则 使用 ORDER BY 子句排序 ASC&#xff08;ascend&…

MySQL安装教程(windows 64位)详细教程

1.确保电脑为64位系统 2.国外官网下载地址&#xff1a;MySQL : Download MySQL Community Server 2.1.点击下载之后&#xff0c;可以选择注册Oracle账号&#xff0c;也可以跳过直接下载 2.2.国内下载网址&#xff1a;Index of /mysql/MySQL-8.0/ 2.3.下载完成后解压到某一个文…

Qt 播放音频文件的几种方式

文章目录摘要1 QMediaPlayer1.1 播放音频文件1.2 播放视频文件1.3 我遇到的问题2 QSound3 QSoundEffect4 QAudioOutput关键字&#xff1a; Qt、 QSound、 QSoundEffect、 QMediaPlayer、 multimedia摘要 这篇文章至少拖了有一两个月了&#xff0c;这不阳了&#xff0c;在家实…

Linux的tree命令原来用处那么大,涨知识了!

大家应该熟悉或了解 Linux 中的目录结果&#xff0c;它就像树的根。这正是 tree 命令的概念。它以树状方式显示当前目录及其子目录的内容。 在使用 tree 命令之前&#xff0c;需要首先安装。 安装 tree 大多数 Linux 发行版中都没有预安装 tree 命令&#xff0c;但是可以在官…

XSS Game通关教程

12.XSS Game通关教程 1、Ma Spaghet! 审查源码 一个不安全的方式&#xff0c;直接get传输somebody 输入123看看位置 ?somebody123 如下 用下input标签即可 <input onmouseoveralert(1)>当鼠标移动到输入框时触发弹窗 2、Jefff 传入的jeff在eval里&#xff0c;那就…