This patch fixes the link statistics for connections that
go through multiple IPCP up-down cycles. Such connections
happen typically in a setup where pppd is used as a back-end
by a L2TP daemon, in case the PPP session at the other side
of the L2TP tunnel reconnects, but the L2TP daemon at that
side just reuses the old L2TP tunnel instead of creating a
new one.
The patch is most important when RADIUS accounting is in use:
Each IPCP-down initiates a RADIUS-Accounting-Stop packet, which
indicates the end of a session. Without this patch, the
accounting information in each subsequent RADIUS-Accounting-Stop
packet of the very same connection would contain cumulative
data since the connection start, but not the data of the last
"sub-session"; in other words, the accounting data sent to
the RADIUS server would indicate that the client had used much
more session time and transfered much more data.
NOTE: The problem fixed by this patch exists even when the
radius plugin is not in use; when extracting accounting data
from the syslog, you can work around the bug, because you
can see there that the same instance of pppd had multiple
sessions; you cannot see this in the RADIUS accounting data.
Furthermore, this patch suppresses duplicate printing/syslogging
of identical data.
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define RCSID "$Id: ipcp.c,v 1.65 2004/01/13 03:59:06 paulus Exp $"
+#define RCSID "$Id: ipcp.c,v 1.66 2004/10/28 00:32:32 paulus Exp $"
notice("secondary DNS address %I", go->dnsaddr[1]);
}
notice("secondary DNS address %I", go->dnsaddr[1]);
}
+ reset_link_stats(f->unit);
+
np_up(f->unit, PPP_IP);
ipcp_is_up = 1;
np_up(f->unit, PPP_IP);
ipcp_is_up = 1;
IPCPDEBUG(("ipcp: down"));
/* XXX a bit IPv4-centric here, we only need to get the stats
* before the interface is marked down. */
IPCPDEBUG(("ipcp: down"));
/* XXX a bit IPv4-centric here, we only need to get the stats
* before the interface is marked down. */
+ /* XXX more correct: we must get the stats before running the notifiers,
+ * at least for the radius plugin */
update_link_stats(f->unit);
notify(ip_down_notifier, 0);
if (ip_down_hook)
update_link_stats(f->unit);
notify(ip_down_notifier, 0);
if (ip_down_hook)
}
sifvjcomp(f->unit, 0, 0, 0);
}
sifvjcomp(f->unit, 0, 0, 0);
+ print_link_stats(); /* _after_ running the notifiers and ip_down_hook(),
+ * because print_link_stats() sets link_stats_valid
+ * to 0 (zero) */
+
/*
* If we are doing dial-on-demand, set the interface
* to queue up outgoing packets (for now).
/*
* If we are doing dial-on-demand, set the interface
* to queue up outgoing packets (for now).
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define RCSID "$Id: main.c,v 1.137 2004/10/24 23:13:16 paulus Exp $"
+#define RCSID "$Id: main.c,v 1.138 2004/10/28 00:32:32 paulus Exp $"
#include <stdio.h>
#include <ctype.h>
#include <stdio.h>
#include <ctype.h>
static struct timeval start_time; /* Time when link was started. */
static struct timeval start_time; /* Time when link was started. */
+static struct pppd_stats old_link_stats;
struct pppd_stats link_stats;
unsigned link_connect_time;
int link_stats_valid;
struct pppd_stats link_stats;
unsigned link_connect_time;
int link_stats_valid;
#endif
static void handle_events __P((void));
#endif
static void handle_events __P((void));
-static void print_link_stats __P((void));
+void print_link_stats __P((void));
extern char *ttyname __P((int));
extern char *getlogin __P((void));
extern char *ttyname __P((int));
extern char *getlogin __P((void));
die(status)
int status;
{
die(status)
int status;
{
cleanup();
notify(exitnotify, status);
syslog(LOG_INFO, "Exit.");
cleanup();
notify(exitnotify, status);
syslog(LOG_INFO, "Exit.");
+/*
+ * reset_link_stats - "reset" stats when link goes up.
+ */
+void
+reset_link_stats(u)
+ int u;
+{
+ if (!get_ppp_stats(u, &old_link_stats))
+ return;
+ gettimeofday(&start_time, NULL);
+}
+
/*
* update_link_stats - get stats at link termination.
*/
/*
* update_link_stats - get stats at link termination.
*/
link_connect_time = now.tv_sec - start_time.tv_sec;
link_stats_valid = 1;
link_connect_time = now.tv_sec - start_time.tv_sec;
link_stats_valid = 1;
+ link_stats.bytes_in -= old_link_stats.bytes_in;
+ link_stats.bytes_out -= old_link_stats.bytes_out;
+ link_stats.pkts_in -= old_link_stats.pkts_in;
+ link_stats.pkts_out -= old_link_stats.pkts_out;
+
slprintf(numbuf, sizeof(numbuf), "%u", link_connect_time);
script_setenv("CONNECT_TIME", numbuf, 0);
slprintf(numbuf, sizeof(numbuf), "%u", link_stats.bytes_out);
slprintf(numbuf, sizeof(numbuf), "%u", link_connect_time);
script_setenv("CONNECT_TIME", numbuf, 0);
slprintf(numbuf, sizeof(numbuf), "%u", link_stats.bytes_out);
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: pppd.h,v 1.82 2003/04/07 00:01:46 paulus Exp $
+ * $Id: pppd.h,v 1.83 2004/10/28 00:32:32 paulus Exp $
void (*done)(void *), void *arg));
/* Run program prog with args in child */
void reopen_log __P((void)); /* (re)open the connection to syslog */
void (*done)(void *), void *arg));
/* Run program prog with args in child */
void reopen_log __P((void)); /* (re)open the connection to syslog */
+void print_link_stats __P((void)); /* Print stats, if available */
+void reset_link_stats __P((int)); /* Reset (init) stats when link goes up */
void update_link_stats __P((int)); /* Get stats at link termination */
void script_setenv __P((char *, char *, int)); /* set script env var */
void script_unsetenv __P((char *)); /* unset script env var */
void update_link_stats __P((int)); /* Get stats at link termination */
void script_setenv __P((char *, char *, int)); /* set script env var */
void script_unsetenv __P((char *)); /* unset script env var */