NetBSD-5.0.2/usr.sbin/pppd/plugins/status/status.c

Compare this file to the similar file:
Show the results in this format:

/*	$NetBSD: status.c,v 1.3 2008/05/04 13:30:54 martin Exp $	*/

/*
 * status.c - pppd plugin to implement an `lcpstatus' option.
 * This is intended as more of an example than perfected feature,
 * but this code has been in use on my local network for a year and
 * is quite useful as is (with a bit of external help, at any rate).
 *
 * Written January 2003 by John F. Woods, jfw@funhouse.com
 */

/*
 * Copyright (c) 2004 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by John F. Woods, jfw@funhouse.com.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#include <stddef.h>
#include <time.h>
#include <stdio.h>
#include "pppd.h"

/* this version string will be checked against pppd's version string when
 * this plugin is loaded.
*/
char pppd_version[] = VERSION;

/*
 * Usage: to use this status plug as-is, add the lines:
plugin status
lcpstatus /var/run/ppp0.status
 * to your PPP options file (or add the appropriate options to your
 * pppd command line), where /var/run/ppp0.status can vary to taste.
 * This plugin will then proceed to create the lcp status file and
 * write one of four strings to the file based on the most recent LCP
 * event:  "up", "down", "?", or "!", representing LCP up, LCP down,
 * LCP echo not received, and received-our-own-LCP-echo (probably
 * indicating a loopback or a disconnected modem echoing back characters).
 * On my system, I have a separate program which reads that file every
 * second and sends a UDP broadcast packet on my ethernet with the contents
 * of the file; each of the other computers on my ethernet (all Macs) have
 * a tiny little program which listens for that UDP broadcast packet and
 * updates a menubar status indicator; the end result is that when PPP
 * shuts down, users on my LAN immediately know without having to go look
 * at the modem.  (Or without demanding that *I* go look at the modem...)
 *
 * If you want to modify this plugin, other ways you could use and display
 * the data generated by the transitions would include:
 * + directly broadcasting the results from inside the pppd task (rather
 *   than having a separate process do it)
 * + store the ppp state in an SNMP database so it could be displayed with
 *   a standard form of client rather than a goofy little Mac OS X menubar
 *   widget.
 */

static char *statusfilename = 0;
static char *laststatus = 0;
static char UP[] = "up";
static char DOWN[] = "down";
static char MISS[] = "?";
static char MINE[] = "!";

static option_t status_options[] = {
	{ "lcpstatus", o_string, &statusfilename,
	  "Name of file to which LCP status string will be written" },
	{ NULL }
};

/* status should be one of the canned constants above. */
static void writestatus(char *status)
{
        FILE *statusfile;
	if (status == laststatus) return;  /* we knew that already */
	statusfile = fopen(statusfilename, "w");
	if (!statusfile) {
                warn("can't write %s to log LCP status", statusfilename);
		free(statusfilename);
		statusfilename = 0;
		return;
	}
	fprintf(statusfile, "%s\n", status);
	fclose(statusfile);
	laststatus = status;
}

static void status_lcp_up(void)
{
        if (!statusfilename) return; /* not enabled */
	writestatus(UP);
}

static void status_lcp_down(void)
{
        if (!statusfilename) return; /* not enabled */
	writestatus(DOWN);
}

static void status_lcp_echo(int pending)
{
        if (!statusfilename) return; /* not enabled */
	if (pending == 0)
                writestatus(UP);
	else if (laststatus != MINE)
                writestatus(MISS);
}

static void status_lcp_echoreply(int mine)
{
        if (!statusfilename) return; /* not enabled */
	if (mine == 0)
                writestatus(UP);
	else
                writestatus(MINE);
}

void plugin_init(void)
{
	info("Initialize PPP status plugin.");
	add_options(status_options);
	lcp_up_hook = status_lcp_up;
	lcp_down_hook = status_lcp_down;
	lcp_echo_hook = status_lcp_echo;
	lcp_echoreply_hook = status_lcp_echoreply;
}