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