Re: Way to monitor IP address change?...

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> >  Is there a way to monitor IP-address changes without using polling?

yes - you can use netlink route sockets for that.. you setup a socket
and then listen on the "RTMGRP_IPV4_IFADDR" multicast group.. the kernel
will broadcast address changes on that socket for you to absorb. (v6 has
its own group)

The netlink API is not one of the easier things to use that I have seen.
I was going to just leave my response at a ptr to netlink, but when it
was taking me 30 minutes to doublecheck my answer, I figured it was
worth cobbling together a fuller answer for posterity and posting a
sample here that deals with new addresses - removals of old addresses
are done in a very similar way.

The documentation always says to use libnetlink, which helps with some
of the overflow issues I have no doubt screwed up below. so buyer
beware.

/* Copyright mcmanus@xxxxxxxxxxxx 2008, Under terms of GPLv2 */

#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 nls,len,rtl;
    char buffer[4096];
    struct nlmsghdr *nlh;
    struct ifaddrmsg *ifa;
    struct rtattr *rth;
    
    if ((nls = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)   perror ("socket failure\n");
    
    memset (&addr,0,sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTMGRP_IPV4_IFADDR;
    
    if (bind(nls, (struct sockaddr *)&addr, sizeof(addr)) == -1)    perror ("bind failure\n");

    nlh = (struct nlmsghdr *)buffer;
    while ((len = recv (nls,nlh,4096,0)) > 0)
    {
        for (;(NLMSG_OK (nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE); nlh = NLMSG_NEXT(nlh, len))
        {
            if (nlh->nlmsg_type != RTM_NEWADDR) continue; /* some other kind of announcement */
            
            ifa = (struct ifaddrmsg *) NLMSG_DATA (nlh);
            
            rth = IFA_RTA (ifa);
            rtl = IFA_PAYLOAD (nlh);
            for (;rtl && RTA_OK (rth, rtl); rth = RTA_NEXT (rth,rtl))
            {
                char name[IFNAMSIZ];
                uint32_t ipaddr;
                
                if (rth->rta_type != IFA_LOCAL) continue;
                
                ipaddr = * ((uint32_t *)RTA_DATA(rth));
                ipaddr = htonl(ipaddr);
                
                fprintf (stdout,"%s is now %X\n",if_indextoname(ifa->ifa_index,name),ipaddr);
            }
        }
    }
}

    




--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux