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