Subject: pppd status, part 2
To: None <current-users@netbsd.org>
From: John F. Woods <jfw@jfwhome.funhouse.com>
List: current-users
Date: 01/19/2003 12:57:12
OK, I have implemented a scheme for making pppd's LCP status visible, and
I wanted to let people take a look at it. I've done it as a pppd plugin
(and therefore I've gotten pppd plugins working, as if that was a tremendous
amount of work), so it will be easy to expand or replace the status-reporting
mechanism (currently a file, but I'm going to toy with SNMP next).
The status plugin should be built as a shared library, copied to
/usr/lib/pppd/2.4.1/libstatus.so.0.0 (or whatever directory would be
appropriate), and loaded with a pppd option of "plugin libstatus.so.0.0"
(actually, I made a symbolic link "status" in that directory and just use
"plugin status"). My status plugin then takes a pppd option "lcpstatus"
whose argument is the pathname into which a status word is to be written.
("cvs diff" claims that I am out of date on lcp.c, even though I did a
"cvs update" this morning.)
Index: Makefile
===================================================================
RCS file: /cvsroot/src/usr.sbin/pppd/pppd/Makefile,v
retrieving revision 1.30
diff -u -d -b -w -r1.30 Makefile
--- Makefile 2002/09/18 03:54:35 1.30
+++ Makefile 2003/01/19 16:54:24
@@ -14,9 +14,9 @@
BINMODE=4555
BINOWN= root
-LDADD= -lpcap -lcrypt -lutil
+LDADD= -lpcap -lcrypt -lutil -Wl,--export-dynamic
DPADD= ${LIBPCAP} ${LIBCRYPT} ${LIBUTIL}
-CPPFLAGS+= -I. -DHAVE_PATHS_H -DSUPPORT_UTMP -DSUPPORT_UTMPX
+CPPFLAGS+= -I. -DHAVE_PATHS_H -DSUPPORT_UTMP -DSUPPORT_UTMPX -DPLUGIN
CPPFLAGS+= -I${PCAPDIR} -DPPP_FILTER
CPPFLAGS+= -DCBCP_SUPPORT -DCHAPMS -DUSE_CRYPT -DMSLANMAN
CPPFLAGS+= -DINET6
Index: pppd.h
===================================================================
RCS file: /cvsroot/src/usr.sbin/pppd/pppd/pppd.h,v
retrieving revision 1.23
diff -u -d -b -w -r1.23 pppd.h
--- pppd.h 2002/07/01 22:19:40 1.23
+++ pppd.h 2003/01/19 16:54:08
@@ -1,4 +1,4 @@
-/* $NetBSD: pppd.h,v 1.23 2002/07/01 22:19:40 itojun Exp $ */
+/* $NetBSD: pppd.h,v 1.22 2002/05/29 19:06:33 christos Exp $ */
/*
* pppd.h - PPP daemon global declarations.
@@ -638,6 +638,10 @@
extern void (*ip_up_hook) __P((void));
extern void (*ip_down_hook) __P((void));
extern void (*ip_choose_hook) __P((u_int32_t *));
+void (*lcp_up_hook) __P((void));
+void (*lcp_down_hook) __P((void));
+void (*lcp_echo_hook) __P((int));
+void (*lcp_echoreply_hook) __P((int));
/*
* Inline versions of get/put char/short/long.
Index: lcp.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/pppd/pppd/lcp.c,v
retrieving revision 1.24
diff -u -d -b -w -r1.24 lcp.c
--- lcp.c 2002/07/01 22:19:35 1.24
+++ lcp.c 2003/01/19 16:54:39
@@ -1,4 +1,4 @@
-/* $NetBSD: lcp.c,v 1.24 2002/07/01 22:19:35 itojun Exp $ */
+/* $NetBSD: lcp.c,v 1.23 2002/05/29 19:06:32 christos Exp $ */
/*
* lcp.c - PPP Link Control Protocol.
@@ -47,7 +47,7 @@
#if 0
#define RCSID "Id: lcp.c,v 1.57 2001/03/08 05:11:14 paulus Exp "
#else
-__RCSID("$NetBSD: lcp.c,v 1.24 2002/07/01 22:19:35 itojun Exp $");
+__RCSID("$NetBSD: lcp.c,v 1.23 2002/05/29 19:06:32 christos Exp $");
#endif
#endif
@@ -204,6 +204,18 @@
lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
+/* Hook for LCP up */
+void (*lcp_up_hook) __P((void)) = NULL;
+
+/* Hook for LCP down */
+void (*lcp_down_hook) __P((void)) = NULL;
+
+/* Hook for sending an LCP echo request, argument is pending count */
+void (*lcp_echo_hook) __P((int)) = NULL;
+
+/* Hook for receiving an LCP echo reply, argument is whether it's ours */
+void (*lcp_echoreply_hook) __P((int)) = NULL;
+
static int lcp_echos_pending = 0; /* Number of outstanding echo msgs */
static int lcp_echo_number = 0; /* ID number of next echo frame */
static int lcp_echo_timer_running = 0; /* set if a timer is running */
@@ -1836,6 +1848,8 @@
if (ho->neg_mru)
peer_mru[f->unit] = ho->mru;
+ if (lcp_up_hook) (*lcp_up_hook)();
+
lcp_echo_lowerup(f->unit); /* Enable echo messages */
link_established(f->unit);
@@ -1857,6 +1871,8 @@
link_down(f->unit);
+ if (lcp_down_hook) (*lcp_down_hook)();
+
ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0);
ppp_recv_config(f->unit, PPP_MRU,
(go->neg_asyncmap? go->asyncmap: 0xffffffff),
@@ -2181,8 +2197,10 @@
if (lcp_gotoptions[f->unit].neg_magicnumber
&& magic == lcp_gotoptions[f->unit].magicnumber) {
warn("appear to have received our own echo-reply!");
+ if (lcp_echoreply_hook) (*lcp_echoreply_hook)(1);
return;
}
+ if (lcp_echoreply_hook) (*lcp_echoreply_hook)(0);
/* Reset the number of outstanding echo frames */
lcp_echos_pending = 0;
@@ -2213,6 +2231,7 @@
* Make and send the echo request frame.
*/
if (f->state == OPENED) {
+ if (*lcp_echo_hook) (*lcp_echo_hook)(lcp_echos_pending);
lcp_magic = lcp_gotoptions[f->unit].magicnumber;
pktp = pkt;
PUTLONG(lcp_magic, pktp);
And finally, status.c itself (copy into the plugins directory alongside
minconn, and build it manually):
/*
* status.c - pppd plugin to implement an `lcpstatus' option.
*
* Copyright 2003 John Woods;
* based on minconn.c, Copyright 1999 Paul Mackerras.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms. The name of the author
* may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stddef.h>
#include <time.h>
#include <stdio.h>
#include "pppd.h"
char pppd_version[] = VERSION;
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 my_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 my_lcp_up(void)
{
if (!statusfilename) return; /* not enabled */
writestatus(UP);
}
static void my_lcp_down(void)
{
if (!statusfilename) return; /* not enabled */
writestatus(DOWN);
}
static void my_lcp_echo(int pending)
{
if (!statusfilename) return; /* not enabled */
if (pending == 0)
writestatus(UP);
else if (laststatus != MINE)
writestatus(MISS);
}
static void my_lcp_echoreply(int mine)
{
if (!statusfilename) return; /* not enabled */
if (mine == 0)
writestatus(UP);
else
writestatus(MINE);
}
void plugin_init(void)
{
info("plugin_init");
add_options(my_options);
lcp_up_hook = my_lcp_up;
lcp_down_hook = my_lcp_down;
lcp_echo_hook = my_lcp_echo;
lcp_echoreply_hook = my_lcp_echoreply;
}