Is there a way to detect IP address changes on the local machine in Linux programmatically using C++?
To determine when your IP address may change or if it already has, start by determining your current IP address. You can do this by searching “what is my IP address” or using free tools like WhatIsMyIP.com. Then, compare the returned address to the examples below.
Luckily for you, Linux has multiple ways of changing your IP address, whether you want it to be dynamic or static. You will see how it is possible to have multiple IP addresses for a single machine and how you can assign IP addresses to virtual network adapters.
There's no simple command that you can run to determine whether the IP address on a Linux system is assigned by DHCP or static. If it changes when the system restarts, it's clearly dynamically assigned, but even a dynamic address has some resistance to change. The best way is to look at the configuration file.
here you go.. this does it without polling.
it only listens for RTM_NEWADDR but it should be easy to change to support RTM_DELADDR if you need
#include <stdio.h> #include <string.h> #include <netinet/in.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #include <net/if.h> int main() { struct sockaddr_nl addr; int sock, len; char buffer[4096]; struct nlmsghdr *nlh; if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { perror("couldn't open NETLINK_ROUTE socket"); return 1; } memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_groups = RTMGRP_IPV4_IFADDR; if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("couldn't bind"); return 1; } nlh = (struct nlmsghdr *)buffer; while ((len = recv(sock, nlh, 4096, 0)) > 0) { while ((NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE)) { if (nlh->nlmsg_type == RTM_NEWADDR) { struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh); struct rtattr *rth = IFA_RTA(ifa); int rtl = IFA_PAYLOAD(nlh); while (rtl && RTA_OK(rth, rtl)) { if (rth->rta_type == IFA_LOCAL) { char name[IFNAMSIZ]; if_indextoname(ifa->ifa_index, name); char ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, RTA_DATA(rth), ip, sizeof(ip)); printf("interface %s ip: %s\n", name, ip); } rth = RTA_NEXT(rth, rtl); } } nlh = NLMSG_NEXT(nlh, len); } } return 0; }
In C, to get the current IP I use:
int s; struct ifreq ifr = {}; s = socket(PF_INET, SOCK_DGRAM, 0); strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name)); if (ioctl(s, SIOCGIFADDR, &ifr) >= 0) printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
Replace "eth0" with the interface you're looking at. All you now need to do is poll for a change.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With