snmp and netlink (by quqi99)

作者:张华 发表于:2020-03-11
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明

set up snmp env

#https://blog.csdn.net/xpleaf/article/details/51100725
sudo apt install snmpd snmp snmp-mibs-downloader libssl-dev libsnmp-dev -y
sudo download-mibs && ls /usr/share/snmp/mibs
sudo cp /etc/snmp/snmpd.conf /etc/snmp/snmpd.conf_bak

sudo bash -c 'cat >/etc/snmp/snmpd.conf' <<EOF
agentaddress udp:161
rocommunity public
EOF
sudo bash -c 'cat > /etc/snmp/snmp.conf' <<EOF
#mibs :
EOF

#or modify existing snmpd.conf directly
sudo vim /etc/snmp/snmpd.conf
#agentAddress  udp:127.0.0.1:161
agentAddress  udp:161
#view   systemonly  included   .1.3.6.1.2.1.1
#view   systemonly  included   .1.3.6.1.2.1.25.1
view   systemonly  included   .1
sudo vim /etc/snmp/snmp.conf
#mibs :

#sudo snmpd -Ls d -q -V -f
sudo systemctl restart snmpd
sudo journalctl -u snmpd -f
#https://blog.51cto.com/xpleaf/1757162
snmpwalk -v 2c -c public localhost sysUpTime
snmpwalk -v 2c -c public localhost 1.3.6.1.2.1.1.3

simulate netlink RTM_NEWNEIGH package

https://sourceforge.net/p/net-snmp/patches/1324/
https://github.com/torvalds/linux/blob/v4.15/net/bridge/br_fdb.c#L532

sudo ip link add test type bridge
sudo strace -s 100 -f -o up.txt -x ip link set test up
sudo ip tuntap add tap1 mode tap
sudo ip link set tap1 up
sudo brctl addif test tap1
sudo ifconfig test 10.122.1.1/24
sudo ifconfig tap1 10.122.1.3/24
bridge fdb show br test
sudo bridge fdb del 46:83:81:56:fa:fc dev tap1 dst 10.122.1.3
sudo strace -s 100 -f -o out -x  bridge fdb add 46:83:81:56:fa:fc dev tap1 dst 10.122.1.3
arp -i tap1 -s 10.122.1.1 02:00:5e:10:de:14
$ grep -r 'RTM_NEWNEIGH' out
30093 sendmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=48, type=RTM_NEWNEIGH, flags=NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE, seq=1583902245, pid=0}, {ndm_family=AF_BRIDGE, ndm_ifindex=if_nametoindex("tap1"), ndm_state=NUD_NOARP|NUD_PERMANENT, ndm_flags=NTF_SELF, ndm_type=RTN_UNSPEC}, [{{nla_len=10, nla_type=NDA_LLADDR}, "\x46\x83\x81\x56\xfa\xfc"}, {{nla_len=8, nla_type=NDA_DST}, "\x0a\x7a\x01\x03"}]}, iov_len=48}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 48
30093 recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=36, type=NLMSG_ERROR, flags=NLM_F_CAPPED, seq=1583902245, pid=30093}, {error=0, msg={len=48, type=RTM_NEWNEIGH, flags=NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE, seq=1583902245, pid=0}}}, iov_len=36}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 36

use snmp to get arp table

snmpwalk -v 2c -c public localhost ipNetToMediaTable

use snmp to delete arp item

$ snmpwalk -v 2c -c public localhost .1.3.6.1.2.1.4.22.1.4 |grep 20
IP-MIB::ipNetToMediaType.19.192.168.122.20 = INTEGER: dynamic(3)

$ snmpset -v 2c -c public localhost ipNetToMediaType.19.192.168.122.20 i 2
Error in packet.
Reason: noAccess
Failed object: IP-MIB::ipNetToMediaType.19.192.168.122.20

ok, need to configure rwcommunity rather than only rocommunity, but how to configure ?

libnl usage

wget https://raw.githubusercontent.com/thom311/libnl/master/src/nl-monitor.c
sudo apt-cache search libnl |grep libnl
sudo apt install libnl-3-200 libnl-3-dev libnl-genl-3-200 libnl-genl-3-dev libnl-route-3-200 libnl-route-3-dev -y
gcc arp-monitor.c -o arp-monitor $(pkg-config --cflags --libs libnl-3.0 libnl-genl-3.0 libnl-route-3.0)
gcc arp-monitor.c -o arp-monitor -I/usr/include/libnl3 -lnl-genl-3 -lnl-route-3 -lnl-3

hua@t440p:/bak/work/c/netlink$ cat arp-monitor.c 
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <asm/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/route.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <libconfig.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/sockios.h>

#define BIT_IP(x)    ((unsigned char*)&(x))
#define STR_IP(x)    BIT_IP(x)[0], BIT_IP(x)[1], BIT_IP(x)[2], BIT_IP(x)[3]
#define STR_IPH(x)    BIT_IP(x)[3], BIT_IP(x)[2], BIT_IP(x)[1], BIT_IP(x)[0]
#define FMT_IP        "%d.%d.%d.%d"

#ifndef NDA_RTA
#define NDA_RTA(r) \
    ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
#endif
#ifndef NDA_PAYLOAD
#define NDA_PAYLOAD(n)    NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
#endif

void arp_parse_rattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
{
    memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
    while (RTA_OK(rta, len)) {
        if ((rta->rta_type <= max) && (!tb[rta->rta_type]))
            tb[rta->rta_type] = rta;
        rta = RTA_NEXT(rta,len);
    }
    if (len)
        fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
    
    return;
}

const char *addr_to_mac(unsigned char *addr, int alen, char *buf, ssize_t blen)
{
    int i;
    int l;

    l = 0;
    for (i = 0; i < alen; i++) {
        if (i==0) {
            snprintf(buf+l, blen, "%02x", addr[i]);
            blen -= 2;
            l += 2;
        } else {
            snprintf(buf+l, blen, ":%02x", addr[i]);
            blen -= 3;
            l += 3;
        }
    }
    return buf;
}

static void read_netlink_message(int fd)
{
    char buff[128 * 1024] = {0};
    char *buf[1024] = {0};
    struct nlmsghdr *nh;
    struct ndmsg *ndmsg;
    int read_size;
    int len = 0;    
    struct rtattr *tb[NDA_MAX + 1];
                
    read_size = read(fd, buff, sizeof(buff));
    if (read_size < 0) {
        return;
    }                    
        
    for (nh = (struct nlmsghdr*)buff; NLMSG_OK(nh, read_size);
        nh = NLMSG_NEXT(nh, read_size)) {
        switch (nh->nlmsg_type) {
        case RTM_NEWNEIGH:
            printf("add new arp cache\n");
            ndmsg = NLMSG_DATA(nh);
            if (ndmsg->ndm_family == AF_INET) {
                len = nh->nlmsg_len - NLMSG_SPACE(sizeof(struct ndmsg));
                arp_parse_rattr(tb, NDA_MAX, NDA_RTA(ndmsg), len);
                    if (tb[NDA_DST]) {
                        printf(""FMT_IP" %d\n", STR_IP(*(RTA_DATA(tb[NDA_DST]))), RTA_PAYLOAD(tb[NDA_DST]));
                    }
                    if (tb[NDA_LLADDR]) {
                        printf("%s %d\n", addr_to_mac(RTA_DATA(tb[NDA_LLADDR]),
                            RTA_PAYLOAD(tb[NDA_LLADDR]), buf, sizeof(buf)), RTA_PAYLOAD(tb[NDA_LLADDR]));
                    }
            }
            break;
        default:
            break;
        }
    }
    
    return;    
}

int main(void)
{
    int fd;
    struct sockaddr_nl sa;
    fd_set rd_set;
    int ret;
    
    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    
    bzero(&sa, sizeof(sa));
    
    sa.nl_family = AF_NETLINK;
    sa.nl_groups = RTM_NEWNEIGH | RTM_DELNEIGH;
    
    if ((bind(fd, (struct sockaddr *)&sa, sizeof(sa))) != 0) {
        perror("bind");
        return -1;
    }
    
    while (1) {
        FD_ZERO(&rd_set);
        FD_SET(fd, &rd_set);
        ret = select(fd + 1, &rd_set, NULL, NULL, NULL);
        if (ret < 0) {
            printf("select error\n");
            break;
        } else if (ret > 0) {
            if (FD_ISSET(fd, &rd_set)) {
                read_netlink_message(fd);
            }
        }
    }
    
    close(fd);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

quqi99

你的鼓励就是我创造的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值