BBB File /usr/local/sbin/ipwatchd
From Wiki
				
				
				Jump to navigationJump to search
				
				WARNING: Not fully tested. This page is not complete.
The monitoring process consists of a small C daemon that uses netlink and rtnetlink interface to watch for address changes on any of the network interfaces.
When a change is detected, 'ipwatchd' runs the /usr/local/sbin/ifdisplay script. That script outputs the configuration of eth0 and wlan0 to 'lpr', which then spools it to a serially attached printer.
'ipwatchd' uses the Debian services framework for start/stop/restart control, PID file management, and any of the other stuff that an application shouldn't be responsible for. See /etc/init.d/ipwatchd for the source to the init.d file, and how to install it.
As root, compile with 'gcc -W -Wall ipwatchd.c -o /usr/local/sbin/ipwatchd'
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <syslog.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#define DAEMON_NAME "simpledaemon"
//
//
//
static void signal_handler (int sig)
{
  switch (sig)
  {
    case SIGHUP:
      syslog (LOG_WARNING, "Received SIGHUP signal.");
      break;
    case SIGINT:
    case SIGTERM:
      syslog (LOG_INFO, "Daemon exiting");
      exit (EXIT_SUCCESS);
      break;
    default:
      syslog (LOG_WARNING, "Unhandled signal %s", strsignal (sig));
      break;
  }
}
//
//
//
static void daemonize (char *rundir)
{
  int pid, sid, i;
  struct sigaction newSigAction;
  sigset_t newSigSet;
  if (getppid () == 1)
    return;
  //
  //  Set signal mask - signals we want to block
  //
  sigemptyset (&newSigSet);
  sigaddset (&newSigSet, SIGCHLD);            // ignore child - i.e. we don't need to wait for it
  sigaddset (&newSigSet, SIGTSTP);            // ignore Tty stop signals
  sigaddset (&newSigSet, SIGTTOU);            // ignore Tty background writes
  sigaddset (&newSigSet, SIGTTIN);            // ignore Tty background reads
  sigprocmask (SIG_BLOCK, &newSigSet, NULL);  // Block the above specified signals
  //
  //  Set up a signal handler
  //
  newSigAction.sa_handler = signal_handler;
  sigemptyset (&newSigAction.sa_mask);
  newSigAction.sa_flags = 0;
  //
  //  Signals to handle
  //
  sigaction (SIGHUP,  &newSigAction, NULL); // catch hangup signal
  sigaction (SIGTERM, &newSigAction, NULL); // catch term signal
  sigaction (SIGINT,  &newSigAction, NULL); // catch interrupt signal
  if ((pid = fork ()) < 0)
    exit (EXIT_FAILURE);
  if (pid > 0)
    exit (EXIT_SUCCESS);
  umask (027);
  if ((sid = setsid ()) < 0)
    exit (EXIT_FAILURE);
  //
  //  Close all descriptors
  //
  for (i = getdtablesize (); i >= 0; --i)
    close (i);
  //
  //  Set stdin, stdout, stderr to /dev/null
  //
  i = open ("/dev/null", O_RDWR);
  dup (i);
  dup (i);
  //
  //  Change directory we run from
  //
  chdir (rundir);
}
static void monitorNetlink (void)
{
  struct sockaddr_nl addr;
  int nls;
  unsigned int len;
  char buffer [4096];
  struct nlmsghdr *nlh;
  if ((nls = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
  {
    syslog (LOG_ERR, "socket() failed: %d/%s", errno, strerror (errno));
    exit (EXIT_FAILURE);
  }
  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)
  {
    syslog (LOG_ERR, "bind() failed: %d/%s", errno, strerror (errno));
    exit (EXIT_FAILURE);
  }
  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)
        system ("/root/bin/ifdisplay");
}
int main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
{
  setlogmask (LOG_UPTO (LOG_INFO));
  openlog (DAEMON_NAME, LOG_CONS | LOG_PERROR, LOG_USER);
  syslog (LOG_INFO, "ipwatch starting up");
  daemonize ("/tmp/");
  syslog (LOG_INFO, "ipwatch running");
  while (1)
    monitorNetlink ();
}
