/* 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;
}