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