ipchange.c
8. Juni 2015 16:15
                    /* ipchange.c
 *
 *  Netlink based IP monitor on specific interface.
 *  Executes command on new IPv4 address.
 *
 *  Sebastian Kricner
 *  tuxwave.net
 *  June 2014
 *
*/

#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/msg.h>
#include <netlink/errno.h>
#include <netlink/route/link.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <syslog.h>
#include <sys/types.h>
#include <string.h>

/*
gcc ipchange.c -o ipchange $(pkg-config --cflags --libs libnl-3.0 libnl-route-3.0)
*/

static char *interface;
static char *cmd;

static void parse_notification(struct nl_object *obj, void *arg)
{
    struct rtnl_addr *addr;
    char s_addr[128];

    int flags;
    char s_flags[128];

    unsigned int ifindex;
    char s_ifname[16];

    addr = (struct rtnl_addr *) obj;
    flags = rtnl_addr_get_flags(addr);
    ifindex = rtnl_addr_get_ifindex(addr);
    if(if_indextoname(ifindex, s_ifname))
    {
        nl_addr2str(rtnl_addr_get_local(addr), s_addr, sizeof(s_addr));
        rtnl_addr_flags2str(flags, s_flags, sizeof(s_flags));

        setenv("S_INTERFACE", s_ifname, 0);
        setenv("S_ADDRESS", s_addr, 0);
        setenv("S_FLAGS", s_flags, 0);

        if(strcmp(s_ifname, interface) == 0)
        {
            system(cmd);
            syslog(LOG_NOTICE, "command executed");
        }
    }
    return;
}

static int process_notification(struct nl_msg *msg, void *arg)
{
    struct nlmsghdr *msghdr = nlmsg_hdr(msg);
    if(msghdr->nlmsg_type == RTM_NEWADDR)
        nl_msg_parse(msg, &parse_notification, arg);
    return NL_OK;
}

static int start_monitor(char *interface, char *cmd)
{
    struct nl_sock *sk;
    int err;
    sk = nl_socket_alloc();
    if(!sk)
    {
        fprintf(stderr, "Could not allocate netlink socket.\n");
        exit(ENOMEM);
    }
    nl_socket_disable_seq_check(sk);
    nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, process_notification, NULL);
    if(err = nl_connect(sk, NETLINK_ROUTE))
    {
        fprintf(stderr, "netlink error: %s\n", nl_geterror(err));
        nl_socket_free(sk);
        sk = NULL;
        exit(err);
    }
    nl_socket_add_memberships(sk, RTNLGRP_IPV4_IFADDR, 0);
    while (1)
        nl_recvmsgs_default(sk);
    return 0;
}

static void daemonize(void)
{
    int pid;

    if(pid = fork())
    {
        exit(EXIT_SUCCESS);
    }
    else if(pid == 0)
    {
        close(0);
        close(1);
        close(2);
        setsid();
        syslog(LOG_NOTICE, "Daemonized");
        FILE *pidfile = fopen("/var/run/ipchange.pid", "w");
        fprintf(pidfile, "%d", getpid());
        fclose(pidfile);
    }
    else
    {
        perror("daemonize");
        exit(errno);
    }
    return;
}

int main(int argc, char **argv, char **envp)
{
    interface = "eth0";
    cmd = "foo";
    daemonize();
    start_monitor(interface, cmd);
    return(EXIT_SUCCESS);
}

                    
        
Download