Re: from pppoe(8) to pppoe(4) - how to run a script on IP address change?

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Matthew Dempsky
Date: Saturday, July 10, 2010 - 6:19 am

On Fri, 9 Jul 2010 23:23:52 -0700, patrick keshishian <pkeshish@gmail.com> wrote:

Sigh, yeah... I meant to handle that, but then got side tracked and
forgot to fix it when I came back to send the email.

Oh well, updated zombie-proof version below.


#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <net/if.h>
#include <net/route.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <err.h>

void
usage(void)
{
	extern char *__progname;

	fprintf(stderr, "usage: %s [-i interface] command ...\n", __progname);
	exit(1);
}

int
main(int argc, char *argv[])
{
	char msg[2048];
	int fd;
	ssize_t n;
	pid_t pid;
	struct rt_msghdr *rtm;
	struct ifa_msghdr *ifam;
	unsigned int rtfilter;
	unsigned int ifindex = 0;
	int ch;

	while ((ch = getopt(argc, argv, "i:")) != -1) {
		switch (ch) {
		case 'i':
			ifindex = if_nametoindex(optarg);
			if (ifindex == 0)
				errx(1, "no interface: %s", optarg);
			break;

		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (argv[0] == NULL)
		usage();

	fd = socket(PF_ROUTE, SOCK_RAW, 0);
	if (fd == -1)
		err(1, "unable to open route socket");

	rtfilter = ROUTE_FILTER(RTM_NEWADDR) | ROUTE_FILTER(RTM_DELADDR);
	if (setsockopt(fd, PF_ROUTE, ROUTE_MSGFILTER, &rtfilter,
	    sizeof(rtfilter)) == -1)
		err(1, "unable to set route message filter");

	for (;;) {
		n = read(fd, msg, sizeof(msg));
		if (n == -1)
			err(1, "unable to read from route socket");
		if (n == 0)
			errx(1, "eof on route socket");

		rtm = (struct rt_msghdr *)msg;
		if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) {
			warnx("route message truncated");
			continue;
		}
		if (rtm->rtm_version != RTM_VERSION) {
			warnx("bad route message version");
			continue;
		}

		if (rtm->rtm_type != RTM_NEWADDR &&
		    rtm->rtm_type != RTM_DELADDR) {
			warnx("unexpected route message");
			continue;
		}

		ifam = (struct ifa_msghdr *)rtm;
		if (ifindex != 0 && ifam->ifam_index != ifindex)
			continue;

		pid = rfork(RFFDG | RFPROC | RFNOWAIT);
		if (pid == -1) {
			warnx("unable to fork child");
			continue;
		}
		if (pid == 0) {
			execvp(argv[0], argv);
			err(1, "unable to exec command");
		}
	}

	/* NOTREACHED */
}
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
Re: from pppoe(8) to pppoe(4) - how to run a script on IP ..., Matthew Dempsky, (Sat Jul 10, 6:19 am)