1 /* NetBSD: status.c,v 1.3 2008/05/04 13:30:54 martin Exp */ 2 3 /* 4 * status.c - pppd plugin to implement an `lcpstatus' option. 5 * This is intended as more of an example than perfected feature, 6 * but this code has been in use on my local network for a year and 7 * is quite useful as is (with a bit of external help, at any rate). 8 * 9 * Written January 2003 by John F. Woods, jfw@funhouse.com 10 */ 11 12 /* 13 * Copyright (c) 2004 The NetBSD Foundation, Inc. 14 * All rights reserved. 15 * 16 * This code is derived from software contributed to The NetBSD Foundation 17 * by John F. Woods, jfw@funhouse.com. 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 1. Redistributions of source code must retain the above copyright 23 * notice, this list of conditions and the following disclaimer. 24 * 2. Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in the 26 * documentation and/or other materials provided with the distribution. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 #include <stddef.h> 41 #include <time.h> 42 #include <stdio.h> 43 #include "pppd.h" 44 45 /* this version string will be checked against pppd's version string when 46 * this plugin is loaded. 47 */ 48 char pppd_version[] = VERSION; 49 50 /* 51 * Usage: to use this status plug as-is, add the lines: 52 plugin status 53 lcpstatus /var/run/ppp0.status 54 * to your PPP options file (or add the appropriate options to your 55 * pppd command line), where /var/run/ppp0.status can vary to taste. 56 * This plugin will then proceed to create the lcp status file and 57 * write one of four strings to the file based on the most recent LCP 58 * event: "up", "down", "?", or "!", representing LCP up, LCP down, 59 * LCP echo not received, and received-our-own-LCP-echo (probably 60 * indicating a loopback or a disconnected modem echoing back characters). 61 * On my system, I have a separate program which reads that file every 62 * second and sends a UDP broadcast packet on my ethernet with the contents 63 * of the file; each of the other computers on my ethernet (all Macs) have 64 * a tiny little program which listens for that UDP broadcast packet and 65 * updates a menubar status indicator; the end result is that when PPP 66 * shuts down, users on my LAN immediately know without having to go look 67 * at the modem. (Or without demanding that *I* go look at the modem...) 68 * 69 * If you want to modify this plugin, other ways you could use and display 70 * the data generated by the transitions would include: 71 * + directly broadcasting the results from inside the pppd task (rather 72 * than having a separate process do it) 73 * + store the ppp state in an SNMP database so it could be displayed with 74 * a standard form of client rather than a goofy little Mac OS X menubar 75 * widget. 76 */ 77 78 static char *statusfilename = 0; 79 static char *laststatus = 0; 80 static char UP[] = "up"; 81 static char DOWN[] = "down"; 82 static char MISS[] = "?"; 83 static char MINE[] = "!"; 84 85 static option_t status_options[] = { 86 { "lcpstatus", o_string, &statusfilename, 87 "Name of file to which LCP status string will be written" }, 88 { NULL } 89 }; 90 91 /* status should be one of the canned constants above. */ 92 static void writestatus(char *status) 93 { 94 FILE *statusfile; 95 if (status == laststatus) return; /* we knew that already */ 96 statusfile = fopen(statusfilename, "w"); 97 if (!statusfile) { 98 warn("can't write %s to log LCP status", statusfilename); 99 free(statusfilename); 100 statusfilename = 0; 101 return; 102 } 103 fprintf(statusfile, "%s\n", status); 104 fclose(statusfile); 105 laststatus = status; 106 } 107 108 static void status_lcp_up(void) 109 { 110 if (!statusfilename) return; /* not enabled */ 111 writestatus(UP); 112 } 113 114 static void status_lcp_down(void) 115 { 116 if (!statusfilename) return; /* not enabled */ 117 writestatus(DOWN); 118 } 119 120 static void status_lcp_echo(int pending) 121 { 122 if (!statusfilename) return; /* not enabled */ 123 if (pending == 0) 124 writestatus(UP); 125 else if (laststatus != MINE) 126 writestatus(MISS); 127 } 128 129 static void status_lcp_echoreply(int mine) 130 { 131 if (!statusfilename) return; /* not enabled */ 132 if (mine == 0) 133 writestatus(UP); 134 else 135 writestatus(MINE); 136 } 137 138 void plugin_init(void) 139 { 140 info("Initialize PPP status plugin."); 141 add_options(status_options); 142 lcp_up_hook = status_lcp_up; 143 lcp_down_hook = status_lcp_down; 144 lcp_echo_hook = status_lcp_echo; 145 lcp_echoreply_hook = status_lcp_echoreply; 146 } 147