作者:张华 发表于: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;
}