Skip to content

Instantly share code, notes, and snippets.

@pandax381
Created May 17, 2019 09:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pandax381/d19cad747e777de15b48b4b5663c106c to your computer and use it in GitHub Desktop.
Save pandax381/d19cad747e777de15b48b4b5663c106c to your computer and use it in GitHub Desktop.
Detect add/delete IP address to interface on Linux
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/rtnetlink.h>
#include <linux/if.h>
static volatile sig_atomic_t terminate;
static int
process_rtm_addr (struct nlmsghdr *hdr) {
struct ifaddrmsg *msg;
size_t n;
struct rtattr *rta;
char local[INET6_ADDRSTRLEN] = {0}, *label = NULL, *dir;
msg = NLMSG_DATA(hdr);
n = hdr->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
for (rta = IFA_RTA(msg); RTA_OK(rta, n); rta = RTA_NEXT(rta, n)) {
switch (rta->rta_type) {
case IFA_LOCAL:
inet_ntop(msg->ifa_family, RTA_DATA(rta), local, sizeof(local));
break;
case IFA_LABEL:
label = (char *)RTA_DATA(rta);
break;
}
}
dir = (hdr->nlmsg_type == RTM_NEWADDR) ? "add" : "del";
if (label) {
fprintf(stderr, "%s: %s %s/%u\n", label, dir, local, msg->ifa_prefixlen);
} else {
fprintf(stderr, "(%d): %s %s/%u\n", msg->ifa_index, dir, local, msg->ifa_prefixlen);
}
return 0;
}
static void
on_signal (int signum) {
(void)signum;
terminate = 1;
}
int
main (int argc, char *argv[]) {
struct sigaction sig;
int soc;
struct sockaddr_nl sa;
char buf[4096];
ssize_t n;
struct nlmsghdr *hdr;
(void)argc, (void)argv;
memset(&sig, 0, sizeof(sig));
sig.sa_handler = on_signal;
if (sigaction(SIGINT, &sig, NULL) == -1) {
perror("sigaction");
return -1;
}
if (sigaction(SIGTERM, &sig, NULL) == -1) {
perror("sigaction");
return -1;
}
soc = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
if (soc == -1) {
perror("socket");
return -1;
}
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_pid = 0;
sa.nl_groups = RTMGRP_IPV4_IFADDR;
if (bind(soc, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
perror("bind");
close(soc);
return -1;
}
while (!terminate) {
n = recv(soc, buf, sizeof(buf), 0);
if (n == -1) {
if (errno == EINTR) {
continue;
}
perror("recv");
close(soc);
return -1;
}
if (!n) {
fprintf(stderr, "EOF\n");
break;
}
for (hdr = (struct nlmsghdr *)buf; NLMSG_OK(hdr, n); hdr = NLMSG_NEXT(hdr, n)) {
switch (hdr->nlmsg_type) {
case RTM_NEWADDR:
case RTM_DELADDR:
process_rtm_addr(hdr);
break;
default:
fprintf(stderr, "Unknown Type (%u)\n", hdr->nlmsg_type);
break;
}
}
}
close(soc);
return 0;
}
@pandax381
Copy link
Author

$ gcc -W -Wall -o ipmond ipmond.c
$ ./ipmond
enp4s0f0: del 10.15.2.165/24
enp4s0f0: add 10.15.2.165/24

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment