- Replace flags used for LCP/IPCP with state machine.
authorBrendan O'Dea <bod@optus.net>
Sun, 31 Jul 2005 10:04:09 +0000 (10:04 +0000)
committerBrendan O'Dea <bod@optus.net>
Sun, 31 Jul 2005 10:04:09 +0000 (10:04 +0000)
- Use openssl MD5, fix DAE vector (Alex Kiernan).

27 files changed:
Changes
Docs/manual.html
Docs/startup-config.5
Makefile
THANKS
arp.c
bgp.c
cli.c
cluster.c
cluster.h
constants.c
constants.h
control.c
control.h
icmp.c
l2tpns.c
l2tpns.h
l2tpns.spec
md5.c [deleted file]
md5.h [deleted file]
nsctl.c
plugin.h
ppp.c
radius.c
tbf.c
tbf.h
test/radius.c

diff --git a/Changes b/Changes
index 452407b..e579e70 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,10 +1,10 @@
-* Wed Jun 29 2005 Brendan O'Dea <bod@c47.org> 2.1.2
-- Don't resend IPCP while still in progress.
-- Ignore duplicate ACKs for IPCP.
-- Clear RADIUSIPCP for walled garden sessions on ACK.
+* Sun Jul 31 2005 Brendan O'Dea <bod@> 2.1.2
 - Clear cluster_master on election so that slaves will accept a new master.
 - Provide more comments/defaults in etc/startup-config.default.
 - Add DAE support (PoD/CoA) from Vladislav Bjelic.
 - Clear cluster_master on election so that slaves will accept a new master.
 - Provide more comments/defaults in etc/startup-config.default.
 - Add DAE support (PoD/CoA) from Vladislav Bjelic.
+- Clean up new warnings from gcc 4.0.
+- Replace flags used for LCP/IPCP with state machine.
+- Use openssl MD5, fix DAE vector (Alex Kiernan).
 
 * Tue Jun 14 2005 Brendan O'Dea <bod@optusnet.com.au> 2.1.1
 - Add missing newline to backtrace macro.
 
 * Tue Jun 14 2005 Brendan O'Dea <bod@optusnet.com.au> 2.1.1
 - Add missing newline to backtrace macro.
index 2458391..1fe4694 100644 (file)
@@ -185,6 +185,13 @@ the same as the LAC, or authentication will fail.  Only actually be
 used if the LAC requests authentication.
 </LI>
 
 used if the LAC requests authentication.
 </LI>
 
+<LI><B>ppp_restart_time</B> (int)<BR>
+<B>ppp_max_configure</B> (int)<BR>
+<B>ppp_max_failure</B> (int)<BR>
+PPP counters and timers values, as described in &sect;4.1 of
+<a href="ftp://ftp.rfc-editor.org/in-notes/rfc1661.txt">RFC1661</a>.
+</LI>
+
 <LI><B>primary_dns</B> (ip address)
 <LI><B>secondary_dns</B> (ip address)<BR>
 Whenever a PPP connection is established, DNS servers will be sent to the
 <LI><B>primary_dns</B> (ip address)
 <LI><B>secondary_dns</B> (ip address)<BR>
 Whenever a PPP connection is established, DNS servers will be sent to the
index 7170dbe..c403de1 100644 (file)
@@ -2,7 +2,7 @@
 .de Id
 .ds Dt \\$4 \\$5
 ..
 .de Id
 .ds Dt \\$4 \\$5
 ..
-.Id $Id: startup-config.5,v 1.11 2005-06-28 14:48:31 bodea Exp $
+.Id $Id: startup-config.5,v 1.12 2005-07-31 10:04:14 bodea Exp $
 .TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions"
 .SH NAME
 startup\-config \- configuration file for l2tpns
 .TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions"
 .SH NAME
 startup\-config \- configuration file for l2tpns
@@ -63,6 +63,16 @@ for authenticating tunnel request.  Must be the same as the LAC, or
 authentication will fail.  Only actually be used if the LAC requests
 authentication.
 .TP
 authentication will fail.  Only actually be used if the LAC requests
 authentication.
 .TP
+.B ppp_restart_time
+Restart timer for PPP protocol negotiation in seconds (default: 3).
+.TP
+.B ppp_max_configure
+Number of configure requests to send before giving up (default: 10).
+.TP
+.B ppp_max_failure
+Number of Configure-Nak requests to send before sending a
+Configure-Reject (default: 5).
+.TP
 .BR primary_dns , " secondary_dns"
 Whenever a PPP connection is established, DNS servers will be sent to the
 user, both a primary and a secondary.  If either is set to 0.0.0.0, then that
 .BR primary_dns , " secondary_dns"
 Whenever a PPP connection is established, DNS servers will be sent to the
 user, both a primary and a secondary.  If either is set to 0.0.0.0, then that
index 156ff39..de2755f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -23,10 +23,10 @@ LDFLAGS =
 LDLIBS =
 INSTALL = install -c -D -o root -g root
 
 LDLIBS =
 INSTALL = install -c -D -o root -g root
 
-l2tpns.LIBS = -lm -lcli -ldl
+l2tpns.LIBS = -lcrypto -lm -lcli -ldl
 
 OBJS = arp.o cli.o cluster.o constants.o control.o icmp.o l2tpns.o \
 
 OBJS = arp.o cli.o cluster.o constants.o control.o icmp.o l2tpns.o \
-    ll.o md5.o ppp.o radius.o tbf.o util.o
+    ll.o ppp.o radius.o tbf.o util.o
 
 PROGRAMS = l2tpns nsctl
 PLUGINS = autosnoop.so autothrottle.so garden.so sessionctl.so \
 
 PROGRAMS = l2tpns nsctl
 PLUGINS = autosnoop.so autothrottle.so garden.so sessionctl.so \
@@ -109,20 +109,19 @@ install: all
 
 ## Dependencies: (autogenerated) ##
 arp.o: arp.c l2tpns.h
 
 ## Dependencies: (autogenerated) ##
 arp.o: arp.c l2tpns.h
-cli.o: cli.c l2tpns.h util.h cluster.h tbf.h ll.h bgp.h
+cli.o: cli.c l2tpns.h constants.h util.h cluster.h tbf.h ll.h bgp.h
 cluster.o: cluster.c l2tpns.h cluster.h util.h tbf.h bgp.h
 constants.o: constants.c constants.h
 control.o: control.c l2tpns.h control.h
 icmp.o: icmp.c l2tpns.h
 cluster.o: cluster.c l2tpns.h cluster.h util.h tbf.h bgp.h
 constants.o: constants.c constants.h
 control.o: control.c l2tpns.h control.h
 icmp.o: icmp.c l2tpns.h
-l2tpns.o: l2tpns.c md5.h l2tpns.h cluster.h plugin.h ll.h constants.h \
-  control.h util.h tbf.h bgp.h
+l2tpns.o: l2tpns.c l2tpns.h cluster.h plugin.h ll.h constants.h control.h \
+  util.h tbf.h bgp.h fake_epoll.h
 ll.o: ll.c ll.h
 ll.o: ll.c ll.h
-md5.o: md5.c md5.h
 ppp.o: ppp.c l2tpns.h constants.h plugin.h util.h tbf.h cluster.h
 ppp.o: ppp.c l2tpns.h constants.h plugin.h util.h tbf.h cluster.h
-radius.o: radius.c md5.h constants.h l2tpns.h plugin.h util.h
+radius.o: radius.c constants.h l2tpns.h plugin.h util.h cluster.h
 tbf.o: tbf.c l2tpns.h util.h tbf.h
 util.o: util.c l2tpns.h bgp.h
 tbf.o: tbf.c l2tpns.h util.h tbf.h
 util.o: util.c l2tpns.h bgp.h
-bgp.o: bgp.c l2tpns.h bgp.h util.h
+bgp.o: bgp.c l2tpns.h bgp.h util.h fake_epoll.h
 autosnoop.so: autosnoop.c l2tpns.h plugin.h
 autothrottle.so: autothrottle.c l2tpns.h plugin.h
 garden.so: garden.c l2tpns.h plugin.h control.h
 autosnoop.so: autosnoop.c l2tpns.h plugin.h
 autothrottle.so: autothrottle.c l2tpns.h plugin.h
 garden.so: garden.c l2tpns.h plugin.h control.h
diff --git a/THANKS b/THANKS
index 07d9619..3262976 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -16,3 +16,4 @@ Bj
 Roberto Chostakovis        <rchostakovis@users.sourceforge.net>
 Jordan Hrycaj              <jordan@mjh.teddy-net.com>
 Vladislav Bjelic           <vladislav@gmail.com>
 Roberto Chostakovis        <rchostakovis@users.sourceforge.net>
 Jordan Hrycaj              <jordan@mjh.teddy-net.com>
 Vladislav Bjelic           <vladislav@gmail.com>
+Alex Kiernan               <alex.kiernan@gmail.com>
diff --git a/arp.c b/arp.c
index 1c2faa1..5fad15d 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -1,6 +1,6 @@
 // L2TPNS: arp
 
 // L2TPNS: arp
 
-char const *cvs_id_arp = "$Id: arp.c,v 1.6 2005-01-07 07:14:14 bodea Exp $";
+char const *cvs_id_arp = "$Id: arp.c,v 1.7 2005-07-31 10:04:09 bodea Exp $";
 
 #include <string.h>
 #include <unistd.h>
 
 #include <string.h>
 #include <unistd.h>
@@ -55,7 +55,7 @@ void sendarp(int ifr_idx, const unsigned char* mac, in_addr_t ip)
 
        memset(&sll, 0, sizeof(sll));
        sll.sll_family = AF_PACKET;
 
        memset(&sll, 0, sizeof(sll));
        sll.sll_family = AF_PACKET;
-       strncpy(sll.sll_addr, mac, sizeof(sll.sll_addr) - 1);
+       memcpy(sll.sll_addr, mac, sizeof(sll.sll_addr) - 1);
        sll.sll_halen = ETH_ALEN;
        sll.sll_ifindex = ifr_idx;
 
        sll.sll_halen = ETH_ALEN;
        sll.sll_ifindex = ifr_idx;
 
diff --git a/bgp.c b/bgp.c
index 96e2868..bfb8de9 100644 (file)
--- a/bgp.c
+++ b/bgp.c
@@ -10,7 +10,7 @@
  *   nor RFC2385 (which requires a kernel patch on 2.4 kernels).
  */
 
  *   nor RFC2385 (which requires a kernel patch on 2.4 kernels).
  */
 
-char const *cvs_id_bgp = "$Id: bgp.c,v 1.10 2005-06-04 15:42:35 bodea Exp $";
+char const *cvs_id_bgp = "$Id: bgp.c,v 1.11 2005-07-31 10:04:09 bodea Exp $";
 
 #include <stdlib.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -767,7 +767,7 @@ static int bgp_connect(struct bgp_peer *peer)
 static int bgp_handle_connect(struct bgp_peer *peer)
 {
     int err = 0;
 static int bgp_handle_connect(struct bgp_peer *peer)
 {
     int err = 0;
-    int len = sizeof(int);
+    socklen_t len = sizeof(int);
     getsockopt(peer->sock, SOL_SOCKET, SO_ERROR, &err, &len);
     if (err)
     {
     getsockopt(peer->sock, SOL_SOCKET, SO_ERROR, &err, &len);
     if (err)
     {
diff --git a/cli.c b/cli.c
index d0f9a8a..e017ff5 100644 (file)
--- a/cli.c
+++ b/cli.c
@@ -2,7 +2,7 @@
 // vim: sw=8 ts=8
 
 char const *cvs_name = "$Name:  $";
 // vim: sw=8 ts=8
 
 char const *cvs_name = "$Name:  $";
-char const *cvs_id_cli = "$Id: cli.c,v 1.63 2005-06-28 14:48:17 bodea Exp $";
+char const *cvs_id_cli = "$Id: cli.c,v 1.64 2005-07-31 10:04:09 bodea Exp $";
 
 #include <stdio.h>
 #include <stdarg.h>
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -25,6 +25,7 @@ char const *cvs_id_cli = "$Id: cli.c,v 1.63 2005-06-28 14:48:17 bodea Exp $";
 #include <libcli.h>
 
 #include "l2tpns.h"
 #include <libcli.h>
 
 #include "l2tpns.h"
+#include "constants.h"
 #include "util.h"
 #include "cluster.h"
 #include "tbf.h"
 #include "util.h"
 #include "cluster.h"
 #include "tbf.h"
@@ -289,10 +290,10 @@ void cli_do(int sockfd)
 {
        int require_auth = 1;
        struct sockaddr_in addr;
 {
        int require_auth = 1;
        struct sockaddr_in addr;
-       int l = sizeof(addr);
+       socklen_t l = sizeof(addr);
 
        if (fork_and_close()) return;
 
        if (fork_and_close()) return;
-       if (getpeername(sockfd, (struct sockaddr *)&addr, &l) == 0)
+       if (getpeername(sockfd, (struct sockaddr *) &addr, &l) == 0)
        {
                require_auth = addr.sin_addr.s_addr != inet_addr("127.0.0.1");
                LOG(require_auth ? 3 : 4, 0, 0, "Accepted connection to CLI from %s\n",
        {
                require_auth = addr.sin_addr.s_addr != inet_addr("127.0.0.1");
                LOG(require_auth ? 3 : 4, 0, 0, "Accepted connection to CLI from %s\n",
@@ -407,6 +408,19 @@ static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int
                        cli_print(cli, "\tCalling Num:\t%s", session[s].calling);
                        cli_print(cli, "\tCalled Num:\t%s", session[s].called);
                        cli_print(cli, "\tTunnel ID:\t%d", session[s].tunnel);
                        cli_print(cli, "\tCalling Num:\t%s", session[s].calling);
                        cli_print(cli, "\tCalled Num:\t%s", session[s].called);
                        cli_print(cli, "\tTunnel ID:\t%d", session[s].tunnel);
+                       cli_print(cli, "\tPPP Phase:\t%s", ppp_phase(session[s].ppp.phase));
+                       switch (session[s].ppp.phase)
+                       {
+                       case Establish:
+                               cli_print(cli, "\tLCP state:\t%s", ppp_state(session[s].ppp.lcp));
+                               break;
+
+                       case Authenticate:
+                       case Network:
+                               cli_print(cli, "\t IPCP state:\t%s", ppp_state(session[s].ppp.ipcp));
+                               cli_print(cli, "\t IPV6CP state:\t%s", ppp_state(session[s].ppp.ipv6cp));
+                               cli_print(cli, "\t CCP state:\t%s", ppp_state(session[s].ppp.ccp));
+                       }
                        cli_print(cli, "\tIP address:\t%s", fmtaddr(htonl(session[s].ip), 0));
                        cli_print(cli, "\tUnique SID:\t%u", session[s].unique_id);
                        cli_print(cli, "\tOpened:\t\t%u seconds", session[s].opened ? abs(time_now - session[s].opened) : 0);
                        cli_print(cli, "\tIP address:\t%s", fmtaddr(htonl(session[s].ip), 0));
                        cli_print(cli, "\tUnique SID:\t%u", session[s].unique_id);
                        cli_print(cli, "\tOpened:\t\t%u seconds", session[s].opened ? abs(time_now - session[s].opened) : 0);
@@ -507,7 +521,7 @@ static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int
                                (session[i].snoop_ip && session[i].snoop_port) ? "Y" : "N",
                                (session[i].throttle_in || session[i].throttle_out) ? "Y" : "N",
                                (session[i].walled_garden) ? "Y" : "N",
                                (session[i].snoop_ip && session[i].snoop_port) ? "Y" : "N",
                                (session[i].throttle_in || session[i].throttle_out) ? "Y" : "N",
                                (session[i].walled_garden) ? "Y" : "N",
-                               (session[i].flags & SF_IPV6CP_ACKED) ? "Y" : "N",
+                               (session[i].ppp.ipv6cp == Opened) ? "Y" : "N",
                                abs(time_now - (unsigned long)session[i].opened),
                                (unsigned long)session[i].cout,
                                (unsigned long)session[i].cin,
                                abs(time_now - (unsigned long)session[i].opened),
                                (unsigned long)session[i].cout,
                                (unsigned long)session[i].cin,
@@ -816,7 +830,6 @@ static int cmd_show_version(struct cli_def *cli, char *command, char **argv, int
                cli_print(cli, "  %s", cvs_id_icmp);
                cli_print(cli, "  %s", cvs_id_l2tpns);
                cli_print(cli, "  %s", cvs_id_ll);
                cli_print(cli, "  %s", cvs_id_icmp);
                cli_print(cli, "  %s", cvs_id_l2tpns);
                cli_print(cli, "  %s", cvs_id_ll);
-               cli_print(cli, "  %s", cvs_id_md5);
                cli_print(cli, "  %s", cvs_id_ppp);
                cli_print(cli, "  %s", cvs_id_radius);
                cli_print(cli, "  %s", cvs_id_tbf);
                cli_print(cli, "  %s", cvs_id_ppp);
                cli_print(cli, "  %s", cvs_id_radius);
                cli_print(cli, "  %s", cvs_id_tbf);
index ad41e46..2370eaf 100644 (file)
--- a/cluster.c
+++ b/cluster.c
@@ -1,6 +1,6 @@
 // L2TPNS Clustering Stuff
 
 // L2TPNS Clustering Stuff
 
-char const *cvs_id_cluster = "$Id: cluster.c,v 1.44 2005-06-28 14:48:19 bodea Exp $";
+char const *cvs_id_cluster = "$Id: cluster.c,v 1.45 2005-07-31 10:04:09 bodea Exp $";
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -56,7 +56,7 @@ static struct {
 static struct {
        int seq;
        int size;
 static struct {
        int seq;
        int size;
-       char data[MAX_HEART_SIZE];
+       uint8_t data[MAX_HEART_SIZE];
 } past_hearts[HB_HISTORY_SIZE];        // Ring buffer of heartbeats that we've recently sent out. Needed so
                                // we can re-transmit if needed.
 
 } past_hearts[HB_HISTORY_SIZE];        // Ring buffer of heartbeats that we've recently sent out. Needed so
                                // we can re-transmit if needed.
 
@@ -178,7 +178,7 @@ static int cluster_send_data(void *data, int datalen)
 // Maintains the format. Assumes that the caller
 // has passed in a big enough buffer!
 //
 // Maintains the format. Assumes that the caller
 // has passed in a big enough buffer!
 //
-static void add_type(char **p, int type, int more, char *data, int size)
+static void add_type(uint8_t **p, int type, int more, uint8_t *data, int size)
 {
        *((uint32_t *) (*p)) = type;
        *p += sizeof(uint32_t);
 {
        *((uint32_t *) (*p)) = type;
        *p += sizeof(uint32_t);
@@ -231,7 +231,7 @@ static void cluster_uptodate(void)
 // Send a unicast UDP packet to a peer with 'data' as the
 // contents.
 //
 // Send a unicast UDP packet to a peer with 'data' as the
 // contents.
 //
-static int peer_send_data(in_addr_t peer, char *data, int size)
+static int peer_send_data(in_addr_t peer, uint8_t *data, int size)
 {
        struct sockaddr_in addr = {0};
 
 {
        struct sockaddr_in addr = {0};
 
@@ -259,10 +259,10 @@ static int peer_send_data(in_addr_t peer, char *data, int size)
 //
 // Send a structured message to a peer with a single element of type 'type'.
 //
 //
 // Send a structured message to a peer with a single element of type 'type'.
 //
-static int peer_send_message(in_addr_t peer, int type, int more, char *data, int size)
+static int peer_send_message(in_addr_t peer, int type, int more, uint8_t *data, int size)
 {
 {
-       char buf[65536];        // Vast overkill.
-       char *p = buf;
+       uint8_t buf[65536];     // Vast overkill.
+       uint8_t *p = buf;
 
        LOG(4, 0, 0, "Sending message to peer (type %d, more %d, size %d)\n", type, more, size);
        add_type(&p, type, more, data, size);
 
        LOG(4, 0, 0, "Sending message to peer (type %d, more %d, size %d)\n", type, more, size);
        add_type(&p, type, more, data, size);
@@ -271,10 +271,10 @@ static int peer_send_message(in_addr_t peer, int type, int more, char *data, int
 }
 
 // send a packet to the master
 }
 
 // send a packet to the master
-static int _forward_packet(char *data, int size, in_addr_t addr, int port, int type)
+static int _forward_packet(uint8_t *data, int size, in_addr_t addr, int port, int type)
 {
 {
-       char buf[65536];        // Vast overkill.
-       char *p = buf;
+       uint8_t buf[65536];     // Vast overkill.
+       uint8_t *p = buf;
 
        if (!config->cluster_master_address) // No election has been held yet. Just skip it.
                return -1;
 
        if (!config->cluster_master_address) // No election has been held yet. Just skip it.
                return -1;
@@ -282,7 +282,7 @@ static int _forward_packet(char *data, int size, in_addr_t addr, int port, int t
        LOG(4, 0, 0, "Forwarding packet from %s to master (size %d)\n", fmtaddr(addr, 0), size);
 
        STAT(c_forwarded);
        LOG(4, 0, 0, "Forwarding packet from %s to master (size %d)\n", fmtaddr(addr, 0), size);
 
        STAT(c_forwarded);
-       add_type(&p, type, addr, (char *) &port, sizeof(port)); // ick. should be uint16_t
+       add_type(&p, type, addr, (uint8_t *) &port, sizeof(port)); // ick. should be uint16_t
        memcpy(p, data, size);
        p += size;
 
        memcpy(p, data, size);
        p += size;
 
@@ -295,13 +295,13 @@ static int _forward_packet(char *data, int size, in_addr_t addr, int port, int t
 // The master just processes the payload as if it had
 // received it off the tun device.
 //
 // The master just processes the payload as if it had
 // received it off the tun device.
 //
-int master_forward_packet(char *data, int size, in_addr_t addr, int port)
+int master_forward_packet(uint8_t *data, int size, in_addr_t addr, int port)
 {
        return _forward_packet(data, size, addr, port, C_FORWARD);
 }
 
 // Forward a DAE RADIUS packet to the master.
 {
        return _forward_packet(data, size, addr, port, C_FORWARD);
 }
 
 // Forward a DAE RADIUS packet to the master.
-int master_forward_dae_packet(char *data, int size, in_addr_t addr, int port)
+int master_forward_dae_packet(uint8_t *data, int size, in_addr_t addr, int port)
 {
        return _forward_packet(data, size, addr, port, C_FORWARD_DAE);
 }
 {
        return _forward_packet(data, size, addr, port, C_FORWARD_DAE);
 }
@@ -313,10 +313,10 @@ int master_forward_dae_packet(char *data, int size, in_addr_t addr, int port)
 // token bucket queue, and lets normal processing take care
 // of it.
 //
 // token bucket queue, and lets normal processing take care
 // of it.
 //
-int master_throttle_packet(int tbfid, char *data, int size)
+int master_throttle_packet(int tbfid, uint8_t *data, int size)
 {
 {
-       char buf[65536];        // Vast overkill.
-       char *p = buf;
+       uint8_t buf[65536];     // Vast overkill.
+       uint8_t *p = buf;
 
        if (!config->cluster_master_address) // No election has been held yet. Just skip it.
                return -1;
 
        if (!config->cluster_master_address) // No election has been held yet. Just skip it.
                return -1;
@@ -338,10 +338,10 @@ int master_throttle_packet(int tbfid, char *data, int size)
 //
 // (Note that this must be called with the tun header
 // as the start of the data).
 //
 // (Note that this must be called with the tun header
 // as the start of the data).
-int master_garden_packet(sessionidt s, char *data, int size)
+int master_garden_packet(sessionidt s, uint8_t *data, int size)
 {
 {
-       char buf[65536];        // Vast overkill.
-       char *p = buf;
+       uint8_t buf[65536];     // Vast overkill.
+       uint8_t *p = buf;
 
        if (!config->cluster_master_address) // No election has been held yet. Just skip it.
                return -1;
 
        if (!config->cluster_master_address) // No election has been held yet. Just skip it.
                return -1;
@@ -358,7 +358,7 @@ int master_garden_packet(sessionidt s, char *data, int size)
 // Send a chunk of data as a heartbeat..
 // We save it in the history buffer as we do so.
 //
 // Send a chunk of data as a heartbeat..
 // We save it in the history buffer as we do so.
 //
-static void send_heartbeat(int seq, char *data, int size)
+static void send_heartbeat(int seq, uint8_t *data, int size)
 {
        int i;
 
 {
        int i;
 
@@ -380,8 +380,8 @@ static void send_heartbeat(int seq, char *data, int size)
 //
 void cluster_send_ping(time_t basetime)
 {
 //
 void cluster_send_ping(time_t basetime)
 {
-       char buff[100 + sizeof(pingt)];
-       char *p = buff;
+       uint8_t buff[100 + sizeof(pingt)];
+       uint8_t *p = buff;
        pingt x;
 
        if (config->cluster_iam_master && basetime)             // We're heartbeating so no need to ping.
        pingt x;
 
        if (config->cluster_iam_master && basetime)             // We're heartbeating so no need to ping.
@@ -394,7 +394,7 @@ void cluster_send_ping(time_t basetime)
        x.undef = config->cluster_undefined_sessions + config->cluster_undefined_tunnels;
        x.basetime = basetime;
 
        x.undef = config->cluster_undefined_sessions + config->cluster_undefined_tunnels;
        x.basetime = basetime;
 
-       add_type(&p, C_PING, basetime, (char *) &x, sizeof(x));
+       add_type(&p, C_PING, basetime, (uint8_t *) &x, sizeof(x));
        cluster_send_data(buff, (p-buff) );
 }
 
        cluster_send_data(buff, (p-buff) );
 }
 
@@ -456,7 +456,7 @@ void master_update_counts(void)
 
                        // Forward the data to the master.
        LOG(4, 0, 0, "Sending byte counters to master (%d elements)\n", c);
 
                        // Forward the data to the master.
        LOG(4, 0, 0, "Sending byte counters to master (%d elements)\n", c);
-       peer_send_message(config->cluster_master_address, C_BYTES, c, (char *) &b, sizeof(b[0]) * c);
+       peer_send_message(config->cluster_master_address, C_BYTES, c, (uint8_t *) &b, sizeof(b[0]) * c);
        return;
 }
 
        return;
 }
 
@@ -738,7 +738,7 @@ static void cluster_check_sessions(int highsession, int freesession_ptr, int hig
                cluster_uptodate();
 }
 
                cluster_uptodate();
 }
 
-static int hb_add_type(char **p, int type, int id)
+static int hb_add_type(uint8_t **p, int type, int id)
 {
        switch (type) {
                case C_CSESSION: { // Compressed C_SESSION.
 {
        switch (type) {
                case C_CSESSION: { // Compressed C_SESSION.
@@ -752,13 +752,13 @@ static int hb_add_type(char **p, int type, int id)
                                // Did we compress the full structure, and is the size actually
                                // reduced??
                        if ( (d - orig) == sizeof(sessiont) && size < sizeof(sessiont) ) {
                                // Did we compress the full structure, and is the size actually
                                // reduced??
                        if ( (d - orig) == sizeof(sessiont) && size < sizeof(sessiont) ) {
-                               add_type(p, C_CSESSION, id, (char *) c, size);
+                               add_type(p, C_CSESSION, id, c, size);
                                break;
                        }
                        // Failed to compress : Fall through.
                }
                                break;
                        }
                        // Failed to compress : Fall through.
                }
-               case C_SESSION: add_type(p, C_SESSION, id,
-                       (char *) &session[id], sizeof(sessiont));
+               case C_SESSION:
+                       add_type(p, C_SESSION, id, (uint8_t *) &session[id], sizeof(sessiont));
                        break;
 
                case C_CTUNNEL: { // Compressed C_TUNNEL
                        break;
 
                case C_CTUNNEL: { // Compressed C_TUNNEL
@@ -777,8 +777,8 @@ static int hb_add_type(char **p, int type, int id)
                        }
                        // Failed to compress : Fall through.
                }
                        }
                        // Failed to compress : Fall through.
                }
-               case C_TUNNEL: add_type(p, C_TUNNEL, id,
-                       (char *) &tunnel[id], sizeof(tunnelt));
+               case C_TUNNEL:
+                       add_type(p, C_TUNNEL, id, (uint8_t *) &tunnel[id], sizeof(tunnelt));
                        break;
                default:
                        LOG(0, 0, 0, "Found an invalid type in heart queue! (%d)\n", type);
                        break;
                default:
                        LOG(0, 0, 0, "Found an invalid type in heart queue! (%d)\n", type);
@@ -794,9 +794,9 @@ static int hb_add_type(char **p, int type, int id)
 void cluster_heartbeat()
 {
        int i, count = 0, tcount = 0;
 void cluster_heartbeat()
 {
        int i, count = 0, tcount = 0;
-       char buff[MAX_HEART_SIZE + sizeof(heartt) + sizeof(int) ];
+       uint8_t buff[MAX_HEART_SIZE + sizeof(heartt) + sizeof(int) ];
        heartt h;
        heartt h;
-       char *p = buff;
+       uint8_t *p = buff;
 
        if (!config->cluster_iam_master)        // Only the master does this.
                return;
 
        if (!config->cluster_iam_master)        // Only the master does this.
                return;
@@ -820,7 +820,7 @@ void cluster_heartbeat()
        h.timeout  = config->cluster_hb_timeout;
        h.table_version = config->cluster_table_version;
 
        h.timeout  = config->cluster_hb_timeout;
        h.table_version = config->cluster_table_version;
 
-       add_type(&p, C_HEARTBEAT, HB_VERSION, (char *) &h, sizeof(h));
+       add_type(&p, C_HEARTBEAT, HB_VERSION, (uint8_t *) &h, sizeof(h));
 
        for (i = 0; i < config->cluster_num_changes; ++i) {
                hb_add_type(&p, cluster_changes[i].type, cluster_changes[i].id);
 
        for (i = 0; i < config->cluster_num_changes; ++i) {
                hb_add_type(&p, cluster_changes[i].type, cluster_changes[i].id);
@@ -1099,7 +1099,7 @@ static int cluster_set_master(in_addr_t peer, in_addr_t master)
 // Note that we don't mark the session as dirty; We rely on
 // the slow table walk to propogate this back out to the slaves.
 //
 // Note that we don't mark the session as dirty; We rely on
 // the slow table walk to propogate this back out to the slaves.
 //
-static int cluster_handle_bytes(char *data, int size)
+static int cluster_handle_bytes(uint8_t *data, int size)
 {
        bytest *b;
 
 {
        bytest *b;
 
@@ -1238,6 +1238,9 @@ struct oldsession {
        uint32_t tx_connect_speed;
        uint32_t rx_connect_speed;
        uint32_t flags;
        uint32_t tx_connect_speed;
        uint32_t rx_connect_speed;
        uint32_t flags;
+#define SF_IPCP_ACKED  1       // Has this session seen an IPCP Ack?
+#define SF_LCP_ACKED   2       // LCP negotiated
+#define SF_CCP_ACKED   4       // CCP negotiated
        in_addr_t snoop_ip;
        uint16_t snoop_port;
        uint16_t sid;
        in_addr_t snoop_ip;
        uint16_t snoop_port;
        uint16_t sid;
@@ -1257,7 +1260,6 @@ static uint8_t *convert_session(struct oldsession *old)
        new.far = old->far;
        new.tunnel = old->tunnel;
        new.l2tp_flags = old->l2tp_flags;
        new.far = old->far;
        new.tunnel = old->tunnel;
        new.l2tp_flags = old->l2tp_flags;
-       new.flags = old->flags;
        new.ip = old->ip;
        new.ip_pool_index = old->ip_pool_index;
        new.unique_id = old->unique_id;
        new.ip = old->ip;
        new.ip_pool_index = old->ip_pool_index;
        new.unique_id = old->unique_id;
@@ -1297,6 +1299,21 @@ static uint8_t *convert_session(struct oldsession *old)
        for (i = 0; i < MAXROUTE; i++)
                memcpy(&new.route[i], &old->route[i], sizeof(new.route[i]));
 
        for (i = 0; i < MAXROUTE; i++)
                memcpy(&new.route[i], &old->route[i], sizeof(new.route[i]));
 
+       if (new.opened)
+       {
+               new.ppp.phase = Establish;
+               if (old->flags & (SF_IPCP_ACKED|SF_LCP_ACKED))
+               {
+                       new.ppp.phase = Network;
+                       new.ppp.lcp   = Opened;
+                       new.ppp.ipcp  = (old->flags & SF_IPCP_ACKED) ? Opened : Starting;
+                       new.ppp.ccp   = (old->flags & SF_CCP_ACKED)  ? Opened : Stopped;
+               }
+
+               // no PPPv6 in old session
+               new.ppp.ipv6cp = Stopped;
+       }
+
        return (uint8_t *) &new;
 }
 
        return (uint8_t *) &new;
 }
 
@@ -1572,10 +1589,10 @@ shortpacket:
 // We got a packet on the cluster port!
 // Handle pings, lastseens, and heartbeats!
 //
 // We got a packet on the cluster port!
 // Handle pings, lastseens, and heartbeats!
 //
-int processcluster(char *data, int size, in_addr_t addr)
+int processcluster(uint8_t *data, int size, in_addr_t addr)
 {
        int type, more;
 {
        int type, more;
-       char *p = data;
+       uint8_t *p = data;
        int s = size;
 
        if (addr == my_address)
        int s = size;
 
        if (addr == my_address)
@@ -1814,7 +1831,7 @@ static int rle_decompress(uint8_t **src_p, int ssize, uint8_t *dst, int dsize)
 {
        int count;
        int orig_dsize = dsize;
 {
        int count;
        int orig_dsize = dsize;
-       char *src = *src_p;
+       uint8_t *src = *src_p;
 
        while (ssize >0 && dsize > 0) { // While there's more to decompress, and there's room in the decompress buffer...
                count = *src++; --ssize;  // get the count byte from the source.
 
        while (ssize >0 && dsize > 0) { // While there's more to decompress, and there's room in the decompress buffer...
                count = *src++; --ssize;  // get the count byte from the source.
index 931c007..4fe7ad0 100644 (file)
--- a/cluster.h
+++ b/cluster.h
@@ -1,5 +1,5 @@
 // L2TPNS Clustering Stuff
 // L2TPNS Clustering Stuff
-// $Id: cluster.h,v 1.13 2005-06-28 14:48:19 bodea Exp $
+// $Id: cluster.h,v 1.14 2005-07-31 10:04:10 bodea Exp $
 
 #ifndef __CLUSTER_H__
 #define __CLUSTER_H__
 
 #ifndef __CLUSTER_H__
 #define __CLUSTER_H__
@@ -72,13 +72,13 @@ typedef struct {
 } pingt;
 
 int cluster_init(void);
 } pingt;
 
 int cluster_init(void);
-int processcluster(char *buf, int size, in_addr_t addr);
+int processcluster(uint8_t *buf, int size, in_addr_t addr);
 int cluster_send_session(int sid);
 int cluster_send_tunnel(int tid);
 int cluster_send_session(int sid);
 int cluster_send_tunnel(int tid);
-int master_forward_packet(char *data, int size, in_addr_t addr, int port);
-int master_forward_dae_packet(char *data, int size, in_addr_t addr, int port);
-int master_throttle_packet(int tid, char *data, int size);
-int master_garden_packet(sessionidt s, char *data, int size);
+int master_forward_packet(uint8_t *data, int size, in_addr_t addr, int port);
+int master_forward_dae_packet(uint8_t *data, int size, in_addr_t addr, int port);
+int master_throttle_packet(int tid, uint8_t *data, int size);
+int master_garden_packet(sessionidt s, uint8_t *data, int size);
 void master_update_counts(void);
 void cluster_send_ping(time_t basetime);
 void cluster_heartbeat(void);
 void master_update_counts(void);
 void cluster_send_ping(time_t basetime);
 void cluster_heartbeat(void);
index f9e3fa1..48e7d59 100644 (file)
@@ -1,6 +1,6 @@
 // L2TPNS: constants
 
 // L2TPNS: constants
 
-char const *cvs_id_constants = "$Id: constants.c,v 1.6 2005-06-28 14:48:20 bodea Exp $";
+char const *cvs_id_constants = "$Id: constants.c,v 1.7 2005-07-31 10:04:10 bodea Exp $";
 
 #include <stdio.h>
 #include "constants.h"
 
 #include <stdio.h>
 #include "constants.h"
@@ -19,19 +19,27 @@ char const *cvs_id_constants = "$Id: constants.c,v 1.6 2005-06-28 14:48:20 bodea
        return n; \
     }
 
        return n; \
     }
 
-CONSTANT(lcp_type,
+CONSTANT(l2tp_code,
     0,                                                 // 0
     0,                                                 // 0
-    "Maximum-Receive-Unit",                            // 1
-    "Async-Control-Map",                               // 2
-    "Authentication-Protocol",                         // 3
-    "Quality-Protocol",                                        // 4
-    "Magic-Number",                                    // 5
-    0,                                                 // 6
-    "Protocol-Field-Compression",                      // 7
-    "Address-and-Control-Field-Compression"            // 8
+    "SCCRQ",                                           // 1
+    "SCCRP",                                           // 2
+    "SCCCN",                                           // 3
+    "StopCCN",                                         // 4
+    0,                                                 // 5
+    "HELLO",                                           // 6
+    "OCRQ",                                            // 7
+    "OCRP",                                            // 8
+    "OCCN",                                            // 9
+    "ICRQ",                                            // 10
+    "ICRP",                                            // 11
+    "ICCN",                                            // 12
+    0,                                                 // 13
+    "CDN",                                             // 14
+    "WEN",                                             // 15
+    "SLI"                                              // 16
 )
 
 )
 
-CONSTANT(avp_name,
+CONSTANT(l2tp_avp_name,
     "Message Type",                                    // 0
     "Result Code",                                     // 1
     "Protocol Version",                                        // 2
     "Message Type",                                    // 0
     "Result Code",                                     // 1
     "Protocol Version",                                        // 2
@@ -74,7 +82,7 @@ CONSTANT(avp_name,
     "Sequencing Required"                              // 39
 )
 
     "Sequencing Required"                              // 39
 )
 
-CONSTANT(stopccn_result_code,
+CONSTANT(l2tp_stopccn_result_code,
     0,                                                 // 0
     "General request to clear control connection",     // 1
     "General error--Error Code indicates the problem", // 2
     0,                                                 // 0
     "General request to clear control connection",     // 1
     "General error--Error Code indicates the problem", // 2
@@ -87,7 +95,7 @@ CONSTANT(stopccn_result_code,
     "Finite State Machine error"                       // 7
 )
 
     "Finite State Machine error"                       // 7
 )
 
-CONSTANT(cdn_result_code,
+CONSTANT(l2tp_cdn_result_code,
     0,                                                 // 0
     "Call disconnected due to loss of carrier",                // 1
     "Call disconnected for the reason indicated in"
     0,                                                 // 0
     "Call disconnected due to loss of carrier",                // 1
     "Call disconnected for the reason indicated in"
@@ -107,7 +115,7 @@ CONSTANT(cdn_result_code,
        " detected"                                     // 11
 )
 
        " detected"                                     // 11
 )
 
-CONSTANT(error_code,
+CONSTANT(l2tp_error_code,
     "No general error",                                        // 0
     "No control connection exists yet for this LAC-LNS"
        " pair",                                        // 1
     "No general error",                                        // 0
     "No control connection exists yet for this LAC-LNS"
        " pair",                                        // 1
@@ -124,7 +132,28 @@ CONSTANT(error_code,
        " an unknown AVP with the M-bit set"            // 8
 )
 
        " an unknown AVP with the M-bit set"            // 8
 )
 
-CONSTANT(auth_type,
+CONSTANT(ppp_phase,
+    "Dead",                                            // 0
+    "Establish",                                       // 1
+    "Authenticate",                                    // 2
+    "Network",                                         // 3
+    "Terminate",                                       // 4
+)
+
+CONSTANT(ppp_state,
+    "Initial",                                         // 0
+    "Starting",                                                // 1
+    "Closed",                                          // 2
+    "Stopped",                                         // 3
+    "Closing",                                         // 4
+    "Stopping",                                                // 5
+    "Request-Sent",                                    // 6
+    "Ack-Received",                                    // 7
+    "Ack-Sent",                                                // 8
+    "Opened"                                           // 9
+)
+
+CONSTANT(ppp_auth_type,
     0,                                                 // 0
     "Textual username/password exchange",              // 1
     "PPP CHAP",                                                // 2
     0,                                                 // 0
     "Textual username/password exchange",              // 1
     "PPP CHAP",                                                // 2
@@ -133,7 +162,7 @@ CONSTANT(auth_type,
     "Microsoft CHAP Version 1 (MSCHAPv1)"              // 5
 )
 
     "Microsoft CHAP Version 1 (MSCHAPv1)"              // 5
 )
 
-CONSTANT(ppp_lcp_type,
+CONSTANT(ppp_code,
     0,                                                 // 0
     "ConfigReq",                                       // 1
     "ConfigAck",                                       // 2
     0,                                                 // 0
     "ConfigReq",                                       // 1
     "ConfigAck",                                       // 2
@@ -149,15 +178,26 @@ CONSTANT(ppp_lcp_type,
     "IdentRequest"                                     // 12
 )
 
     "IdentRequest"                                     // 12
 )
 
+CONSTANT(ppp_lcp_option,
+    0,                                                 // 0
+    "Maximum-Receive-Unit",                            // 1
+    "Async-Control-Map",                               // 2
+    "Authentication-Protocol",                         // 3
+    "Quality-Protocol",                                        // 4
+    "Magic-Number",                                    // 5
+    0,                                                 // 6
+    "Protocol-Field-Compression",                      // 7
+    "Address-and-Control-Field-Compression"            // 8
+)
+
 CONSTANT(radius_state,
     "RADIUSNULL",                                      // 0
     "RADIUSCHAP",                                      // 1
     "RADIUSAUTH",                                      // 2
 CONSTANT(radius_state,
     "RADIUSNULL",                                      // 0
     "RADIUSCHAP",                                      // 1
     "RADIUSAUTH",                                      // 2
-    "RADIUSIPCP",                                      // 3
-    "RADIUSSTART",                                     // 4
-    "RADIUSSTOP",                                      // 5
-    "RADIUSINTERIM",                                   // 6
-    "RADIUSWAIT"                                       // 7
+    "RADIUSSTART",                                     // 3
+    "RADIUSSTOP",                                      // 4
+    "RADIUSINTERIM",                                   // 5
+    "RADIUSWAIT"                                       // 6
 )
 
 CONSTANT(radius_code,
 )
 
 CONSTANT(radius_code,
@@ -185,23 +225,3 @@ CONSTANT(radius_code,
     "CoA-ACK",                                         // 44
     "CoA-NAK"                                          // 45
 )
     "CoA-ACK",                                         // 44
     "CoA-NAK"                                          // 45
 )
-
-CONSTANT(l2tp_message_type,
-    0,                                                 // 0
-    "SCCRQ",                                           // 1
-    "SCCRP",                                           // 2
-    "SCCCN",                                           // 3
-    "StopCCN",                                         // 4
-    0,                                                 // 5
-    "HELLO",                                           // 6
-    "OCRQ",                                            // 7
-    "OCRP",                                            // 8
-    "OCCN",                                            // 9
-    "ICRQ",                                            // 10
-    "ICRP",                                            // 11
-    "ICCN",                                            // 12
-    0,                                                 // 13
-    "CDN",                                             // 14
-    "WEN",                                             // 15
-    "SLI"                                              // 16
-)
index a27ce79..a9693c3 100644 (file)
@@ -1,15 +1,17 @@
 #ifndef __CONSTANTS_H__
 #define __CONSTANTS_H__
 
 #ifndef __CONSTANTS_H__
 #define __CONSTANTS_H__
 
-char const *lcp_type(int type);
-char const *avp_name(int avp);
-char const *stopccn_result_code(int code);
-char const *cdn_result_code(int code);
-char const *error_code(int code);
-char const *auth_type(int type);
-char const *ppp_lcp_type(int type);
+char const *l2tp_code(int type);
+char const *l2tp_avp_name(int avp);
+char const *l2tp_stopccn_result_code(int code);
+char const *l2tp_cdn_result_code(int code);
+char const *l2tp_error_code(int code);
+char const *ppp_phase(int code);
+char const *ppp_state(int code);
+char const *ppp_auth_type(int type);
+char const *ppp_code(int type);
+char const *ppp_lcp_option(int type);
 char const *radius_state(int state);
 char const *radius_code(int code);
 char const *radius_state(int state);
 char const *radius_code(int code);
-char const *l2tp_message_type(int type);
 
 #endif /* __CONSTANTS_H__ */
 
 #endif /* __CONSTANTS_H__ */
index bd65de5..805a90b 100644 (file)
--- a/control.c
+++ b/control.c
@@ -1,12 +1,12 @@
 // L2TPNS: control
 
 // L2TPNS: control
 
-char const *cvs_id_control = "$Id: control.c,v 1.4 2004-12-16 08:49:53 bodea Exp $";
+char const *cvs_id_control = "$Id: control.c,v 1.5 2005-07-31 10:04:10 bodea Exp $";
 
 #include <string.h>
 #include "l2tpns.h"
 #include "control.h"
 
 
 #include <string.h>
 #include "l2tpns.h"
 #include "control.h"
 
-int pack_control(char *data, int len, uint8_t type, int argc, char *argv[])
+int pack_control(uint8_t *data, int len, uint8_t type, int argc, char *argv[])
 {
     struct nsctl_packet pkt;
     struct nsctl_args arg;
 {
     struct nsctl_packet pkt;
     struct nsctl_args arg;
@@ -62,7 +62,7 @@ int pack_control(char *data, int len, uint8_t type, int argc, char *argv[])
     return sz;
 }
 
     return sz;
 }
 
-int unpack_control(struct nsctl *control, char *data, int len)
+int unpack_control(struct nsctl *control, uint8_t *data, int len)
 {
     struct nsctl_packet pkt;
     char *p = pkt.argv;
 {
     struct nsctl_packet pkt;
     char *p = pkt.argv;
index ee7ed7d..e1f7d54 100644 (file)
--- a/control.h
+++ b/control.h
@@ -47,8 +47,8 @@ struct nsctl {
     char *argv[0xff];
 };
 
     char *argv[0xff];
 };
 
-int pack_control(char *data, int len, uint8_t type, int argc, char *argv[]);
-int unpack_control(struct nsctl *packet, char *data, int len);
+int pack_control(uint8_t *data, int len, uint8_t type, int argc, char *argv[]);
+int unpack_control(struct nsctl *packet, uint8_t *data, int len);
 void dump_control(struct nsctl *control, FILE *stream);
 
 #endif /* __CONTROL_H__ */
 void dump_control(struct nsctl *control, FILE *stream);
 
 #endif /* __CONTROL_H__ */
diff --git a/icmp.c b/icmp.c
index da04c38..93d00c1 100644 (file)
--- a/icmp.c
+++ b/icmp.c
@@ -1,6 +1,6 @@
 // L2TPNS: icmp
 
 // L2TPNS: icmp
 
-char const *cvs_id_icmp = "$Id: icmp.c,v 1.8 2005-06-04 15:42:06 bodea Exp $";
+char const *cvs_id_icmp = "$Id: icmp.c,v 1.9 2005-07-31 10:04:10 bodea Exp $";
 
 #include <arpa/inet.h>
 #include <netdb.h>
 
 #include <arpa/inet.h>
 #include <netdb.h>
@@ -18,7 +18,7 @@ char const *cvs_id_icmp = "$Id: icmp.c,v 1.8 2005-06-04 15:42:06 bodea Exp $";
 
 #include "l2tpns.h"
 
 
 #include "l2tpns.h"
 
-static uint16_t _checksum(unsigned char *addr, int count);
+static uint16_t _checksum(uint8_t *addr, int count);
 
 struct ipv6_pseudo_hdr {
        struct in6_addr src;
 
 struct ipv6_pseudo_hdr {
        struct in6_addr src;
@@ -28,7 +28,7 @@ struct ipv6_pseudo_hdr {
        uint32_t nexthdr :  8;
 };
 
        uint32_t nexthdr :  8;
 };
 
-void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, char *packet, int packet_len)
+void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, uint8_t *packet, int packet_len)
 {
        char buf[128] = {0};
        struct iphdr *iph;
 {
        char buf[128] = {0};
        struct iphdr *iph;
@@ -72,15 +72,15 @@ void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, char
 
        icmp->type = ICMP_DEST_UNREACH;
        icmp->code = ICMP_HOST_UNREACH;
 
        icmp->type = ICMP_DEST_UNREACH;
        icmp->code = ICMP_HOST_UNREACH;
-       icmp->checksum = _checksum((char *) icmp, sizeof(struct icmphdr) + packet_len);
+       icmp->checksum = _checksum((uint8_t *) icmp, sizeof(struct icmphdr) + packet_len);
 
 
-       iph->check = _checksum((char *) iph, sizeof(struct iphdr));
+       iph->check = _checksum((uint8_t *) iph, sizeof(struct iphdr));
 
 
-       sendto(icmp_socket, (char *)buf, len, 0, (struct sockaddr *)&whereto, sizeof(struct sockaddr));
+       sendto(icmp_socket, buf, len, 0, (struct sockaddr *)&whereto, sizeof(struct sockaddr));
        close(icmp_socket);
 }
 
        close(icmp_socket);
 }
 
-static uint16_t _checksum(unsigned char *addr, int count)
+static uint16_t _checksum(uint8_t *addr, int count)
 {
        register long sum = 0;
 
 {
        register long sum = 0;
 
index a729992..8204503 100644 (file)
--- a/l2tpns.c
+++ b/l2tpns.c
@@ -4,7 +4,7 @@
 // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
 // vim: sw=8 ts=8
 
 // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
 // vim: sw=8 ts=8
 
-char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.114 2005-07-04 05:49:46 bodea Exp $";
+char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.115 2005-07-31 10:04:10 bodea Exp $";
 
 #include <arpa/inet.h>
 #include <assert.h>
 
 #include <arpa/inet.h>
 #include <assert.h>
@@ -38,9 +38,9 @@ char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.114 2005-07-04 05:49:46 bodea Exp
 #include <unistd.h>
 #include <sched.h>
 #include <sys/sysinfo.h>
 #include <unistd.h>
 #include <sched.h>
 #include <sys/sysinfo.h>
+#include <openssl/md5.h>
 #include <libcli.h>
 
 #include <libcli.h>
 
-#include "md5.h"
 #include "l2tpns.h"
 #include "cluster.h"
 #include "plugin.h"
 #include "l2tpns.h"
 #include "cluster.h"
 #include "plugin.h"
@@ -105,6 +105,9 @@ config_descriptt config_values[] = {
        CONFIG("pid_file", pid_file, STRING),
        CONFIG("random_device", random_device, STRING),
        CONFIG("l2tp_secret", l2tpsecret, STRING),
        CONFIG("pid_file", pid_file, STRING),
        CONFIG("random_device", random_device, STRING),
        CONFIG("l2tp_secret", l2tpsecret, STRING),
+       CONFIG("ppp_restart_time", ppp_restart_time, INT),
+       CONFIG("ppp_max_configure", ppp_max_configure, INT),
+       CONFIG("ppp_max_failure", ppp_max_failure, INT),
        CONFIG("primary_dns", default_dns1, IPv4),
        CONFIG("secondary_dns", default_dns2, IPv4),
        CONFIG("primary_radius", radiusserver[0], IPv4),
        CONFIG("primary_dns", default_dns1, IPv4),
        CONFIG("secondary_dns", default_dns2, IPv4),
        CONFIG("primary_radius", radiusserver[0], IPv4),
@@ -182,7 +185,7 @@ static void sighup_handler(int sig);
 static void sigalrm_handler(int sig);
 static void shutdown_handler(int sig);
 static void sigchild_handler(int sig);
 static void sigalrm_handler(int sig);
 static void shutdown_handler(int sig);
 static void sigchild_handler(int sig);
-static void build_chap_response(char *challenge, uint8_t id, uint16_t challenge_length, char **challenge_response);
+static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challenge_length, uint8_t **challenge_response);
 static void update_config(void);
 static void read_config_file(void);
 static void initplugins(void);
 static void update_config(void);
 static void read_config_file(void);
 static void initplugins(void);
@@ -258,10 +261,10 @@ void _log(int level, sessionidt s, tunnelidt t, const char *format, ...)
        va_end(ap);
 }
 
        va_end(ap);
 }
 
-void _log_hex(int level, const char *title, const char *data, int maxsize)
+void _log_hex(int level, const char *title, const uint8_t *data, int maxsize)
 {
        int i, j;
 {
        int i, j;
-       const uint8_t *d = (const uint8_t *) data;
+       const uint8_t *d = data;
 
        if (config->debug < level) return;
 
 
        if (config->debug < level) return;
 
@@ -551,7 +554,7 @@ static void inittun(void)
        tunidx = ifr.ifr_ifindex;
 
        // Only setup IPv6 on the tun device if we have a configured prefix
        tunidx = ifr.ifr_ifindex;
 
        // Only setup IPv6 on the tun device if we have a configured prefix
-       if (config->ipv6_prefix.s6_addr[0] > 0) {
+       if (config->ipv6_prefix.s6_addr[0]) {
                ifr6fd = socket(PF_INET6, SOCK_DGRAM, 0);
 
                // Link local address is FE80::1
                ifr6fd = socket(PF_INET6, SOCK_DGRAM, 0);
 
                // Link local address is FE80::1
@@ -702,8 +705,11 @@ sessionidt sessionbyipv6(struct in6_addr ip)
        CSTAT(sessionbyipv6);
 
        if (!memcmp(&config->ipv6_prefix, &ip, 8) ||
        CSTAT(sessionbyipv6);
 
        if (!memcmp(&config->ipv6_prefix, &ip, 8) ||
-               (ip.s6_addr[0] == 0xFE && ip.s6_addr[1] == 0x80 &&
-                (ip.s6_addr16[1] == ip.s6_addr16[2] == ip.s6_addr16[3] == 0))) {
+               (ip.s6_addr[0] == 0xFE &&
+                ip.s6_addr[1] == 0x80 &&
+                ip.s6_addr16[1] == 0 &&
+                ip.s6_addr16[2] == 0 &&
+                ip.s6_addr16[3] == 0)) {
                s = lookup_ipmap(*(in_addr_t *) &ip.s6_addr[8]);
        } else {
                s = lookup_ipv6map(ip);
                s = lookup_ipmap(*(in_addr_t *) &ip.s6_addr[8]);
        } else {
                s = lookup_ipv6map(ip);
@@ -973,14 +979,14 @@ int tun_write(uint8_t * data, int size)
 
 // process outgoing (to tunnel) IP
 //
 
 // process outgoing (to tunnel) IP
 //
-static void processipout(uint8_t * buf, int len)
+static void processipout(uint8_t *buf, int len)
 {
        sessionidt s;
        sessiont *sp;
        tunnelidt t;
        in_addr_t ip;
 
 {
        sessionidt s;
        sessiont *sp;
        tunnelidt t;
        in_addr_t ip;
 
-       char *data = buf;       // Keep a copy of the originals.
+       uint8_t *data = buf;    // Keep a copy of the originals.
        int size = len;
 
        uint8_t b[MAXETHER + 20];
        int size = len;
 
        uint8_t b[MAXETHER + 20];
@@ -1126,7 +1132,7 @@ static void processipv6out(uint8_t * buf, int len)
        in_addr_t ip;
        struct in6_addr ip6;
 
        in_addr_t ip;
        struct in6_addr ip6;
 
-       char *data = buf;       // Keep a copy of the originals.
+       uint8_t *data = buf;    // Keep a copy of the originals.
        int size = len;
 
        uint8_t b[MAXETHER + 20];
        int size = len;
 
        uint8_t b[MAXETHER + 20];
@@ -1313,7 +1319,7 @@ static void controls(controlt * c, uint16_t avp, char *val, uint8_t m)
 }
 
 // add a binary AVP
 }
 
 // add a binary AVP
-static void controlb(controlt * c, uint16_t avp, char *val, unsigned int len, uint8_t m)
+static void controlb(controlt * c, uint16_t avp, uint8_t *val, unsigned int len, uint8_t m)
 {
        uint16_t l = ((m ? 0x8000 : 0) + len + 6);
        *(uint16_t *) (c->buf + c->length + 0) = htons(l);
 {
        uint16_t l = ((m ? 0x8000 : 0) + len + 6);
        *(uint16_t *) (c->buf + c->length + 0) = htons(l);
@@ -1493,10 +1499,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
        if (session[s].ip && !walled_garden && !session[s].die)
        {
                // RADIUS Stop message
        if (session[s].ip && !walled_garden && !session[s].die)
        {
                // RADIUS Stop message
-               uint16_t r = sess_local[s].radius;
-               if (!r)
-                       r = radiusnew(s);
-
+               uint16_t r = radiusnew(s);
                if (r)
                {
                        // stop, if not already trying
                if (r)
                {
                        // stop, if not already trying
@@ -1534,7 +1537,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
                        free_ip_address(s);
 
                // unroute IPv6, if setup
                        free_ip_address(s);
 
                // unroute IPv6, if setup
-               if (session[s].flags & SF_IPV6_ROUTED)
+               if (session[s].ppp.ipv6cp == Opened && session[s].ipv6prefixlen)
                        route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0);
        }
 
                        route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0);
        }
 
@@ -1546,7 +1549,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
                controlt *c = controlnew(14); // sending CDN
                if (error)
                {
                controlt *c = controlnew(14); // sending CDN
                if (error)
                {
-                       char buf[4];
+                       uint8_t buf[4];
                        *(uint16_t *) buf     = htons(result);
                        *(uint16_t *) (buf+2) = htons(error);
                        controlb(c, 1, buf, 4, 1);
                        *(uint16_t *) buf     = htons(result);
                        *(uint16_t *) (buf+2) = htons(error);
                        controlb(c, 1, buf, 4, 1);
@@ -1565,78 +1568,66 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
        if (session[s].filter_in) ip_filters[session[s].filter_in - 1].used--;
        if (session[s].filter_out) ip_filters[session[s].filter_out - 1].used--;
 
        if (session[s].filter_in) ip_filters[session[s].filter_in - 1].used--;
        if (session[s].filter_out) ip_filters[session[s].filter_out - 1].used--;
 
+       // clear PPP state
+       memset(&session[s].ppp, 0, sizeof(session[s].ppp));
+       sess_local[s].lcp.restart = 0;
+       sess_local[s].ipcp.restart = 0;
+       sess_local[s].ipv6cp.restart = 0;
+       sess_local[s].ccp.restart = 0;
+
        cluster_send_session(s);
 }
 
 void sendipcp(tunnelidt t, sessionidt s)
 {
        uint8_t buf[MAXCONTROL];
        cluster_send_session(s);
 }
 
 void sendipcp(tunnelidt t, sessionidt s)
 {
        uint8_t buf[MAXCONTROL];
-       uint16_t r = sess_local[s].radius;
        uint8_t *q;
 
        CSTAT(sendipcp);
 
        uint8_t *q;
 
        CSTAT(sendipcp);
 
-       if (!r)
-               r = radiusnew(s);
-
-       if (!r)
-       {
-               sessionshutdown(s, "No free RADIUS sessions for IPCP", 3, 0);
-               return;
-       }
-
-       if (radius[r].state != RADIUSIPCP)
-       {
-               radius[r].state = RADIUSIPCP;
-               radius[r].try = 0;
-       }
-
-       radius[r].retry = backoff(radius[r].try++);
-       if (radius[r].try > 10)
+       if (!session[s].unique_id)
        {
        {
-               radiusclear(r, s);      // Clear radius session.
-               sessionshutdown(s, "No reply to IPCP.", 3, 0);
-               return;
+               if (!++last_id) ++last_id; // skip zero
+               session[s].unique_id = last_id;
        }
 
        q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPCP);
        if (!q) return;
 
        *q = ConfigReq;
        }
 
        q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPCP);
        if (!q) return;
 
        *q = ConfigReq;
-       q[1] = r >> RADIUS_SHIFT;                    // ID, dont care, we only send one type of request
-       *(uint16_t *) (q + 2) = htons(10);
-       q[4] = 3;
-       q[5] = 6;
+       q[1] = session[s].unique_id & 0xf;      // ID, dont care, we only send one type of request
+       *(uint16_t *) (q + 2) = htons(10);      // packet length
+       q[4] = 3;                               // ip address option
+       q[5] = 6;                               // option length
        *(in_addr_t *) (q + 6) = config->peer_address ? config->peer_address :
                                 config->bind_address ? config->bind_address :
                                 my_address; // send my IP
 
        tunnelsend(buf, 10 + (q - buf), t); // send it
        *(in_addr_t *) (q + 6) = config->peer_address ? config->peer_address :
                                 config->bind_address ? config->bind_address :
                                 my_address; // send my IP
 
        tunnelsend(buf, 10 + (q - buf), t); // send it
-       session[s].flags &= ~SF_IPCP_ACKED;     // Clear flag.
-
-       // If we have an IPv6 prefix length configured, assume we should
-       // try to negotiate an IPv6 session as well. Unless we've had a
-       // (N)ACK for IPV6CP.
-       if (config->ipv6_prefix.s6_addr[0] > 0 && 
-                       !(session[s].flags & SF_IPV6CP_ACKED) &&
-                       !(session[s].flags & SF_IPV6_NACKED))
-       {
-               q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPV6CP);
-               if (!q) return;
-
-               *q = ConfigReq;
-               q[1] = r >> RADIUS_SHIFT;               // ID, don't care, we
-                                                       // only send one type
-                                                       // of request
-               *(uint16_t *) (q + 2) = htons(14);
-               q[4] = 1;
-               q[5] = 10;
-               *(uint32_t *) (q + 6) = 0;              // We'll be prefix::1
-               *(uint32_t *) (q + 10) = 0;
-               q[13] = 1;
-
-               tunnelsend(buf, 14 + (q - buf), t);     // send it
-       }
+}
+
+void sendipv6cp(tunnelidt t, sessionidt s)
+{
+       uint8_t buf[MAXCONTROL];
+       uint8_t *q;
+
+       CSTAT(sendipv6cp);
+
+       q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPV6CP);
+       if (!q) return;
+
+       *q = ConfigReq;
+       q[1] = session[s].unique_id & 0xf;      // ID, don't care, we
+                                               // only send one type
+                                               // of request
+       *(uint16_t *) (q + 2) = htons(14);
+       q[4] = 1;                               // interface identifier option
+       q[5] = 10;                              // option length
+       *(uint32_t *) (q + 6) = 0;              // We'll be prefix::1
+       *(uint32_t *) (q + 10) = 0;
+       q[13] = 1;
+
+       tunnelsend(buf, 14 + (q - buf), t);     // send it
 }
 
 static void sessionclear(sessionidt s)
 }
 
 static void sessionclear(sessionidt s)
@@ -1742,7 +1733,7 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha
                controlt *c = controlnew(4);    // sending StopCCN
                if (error)
                {
                controlt *c = controlnew(4);    // sending StopCCN
                if (error)
                {
-                       char buf[64];
+                       uint8_t buf[64];
                        int l = 4;
                        *(uint16_t *) buf     = htons(result);
                        *(uint16_t *) (buf+2) = htons(error);
                        int l = 4;
                        *(uint16_t *) buf     = htons(result);
                        *(uint16_t *) (buf+2) = htons(error);
@@ -1767,9 +1758,9 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha
 }
 
 // read and process packet on tunnel (UDP)
 }
 
 // read and process packet on tunnel (UDP)
-void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
+void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
 {
 {
-       char *chapresponse = NULL;
+       uint8_t *chapresponse = NULL;
        uint16_t l = len, t = 0, s = 0, ns = 0, nr = 0;
        uint8_t *p = buf + 2;
 
        uint16_t l = len, t = 0, s = 0, ns = 0, nr = 0;
        uint8_t *p = buf + 2;
 
@@ -2061,7 +2052,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                        n = orig_len;
                                }
 
                                        n = orig_len;
                                }
 
-                               LOG(4, s, t, "   AVP %d (%s) len %d%s%s\n", mtype, avp_name(mtype), n,
+                               LOG(4, s, t, "   AVP %d (%s) len %d%s%s\n", mtype, l2tp_avp_name(mtype), n,
                                        flags & 0x40 ? ", hidden" : "", flags & 0x80 ? ", mandatory" : "");
 
                                switch (mtype)
                                        flags & 0x40 ? ", hidden" : "", flags & 0x80 ? ", mandatory" : "");
 
                                switch (mtype)
@@ -2069,7 +2060,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                case 0:     // message type
                                        message = ntohs(*(uint16_t *) b);
                                        mandatory = flags & 0x80;
                                case 0:     // message type
                                        message = ntohs(*(uint16_t *) b);
                                        mandatory = flags & 0x80;
-                                       LOG(4, s, t, "   Message type = %d (%s)\n", *b, l2tp_message_type(message));
+                                       LOG(4, s, t, "   Message type = %d (%s)\n", *b, l2tp_code(message));
                                        break;
                                case 1:     // result code
                                        {
                                        break;
                                case 1:     // result code
                                        {
@@ -2077,18 +2068,18 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                                const char* resdesc = "(unknown)";
                                                if (message == 4)
                                                { /* StopCCN */
                                                const char* resdesc = "(unknown)";
                                                if (message == 4)
                                                { /* StopCCN */
-                                                       resdesc = stopccn_result_code(rescode);
+                                                       resdesc = l2tp_stopccn_result_code(rescode);
                                                }
                                                else if (message == 14)
                                                { /* CDN */
                                                }
                                                else if (message == 14)
                                                { /* CDN */
-                                                       resdesc = cdn_result_code(rescode);
+                                                       resdesc = l2tp_cdn_result_code(rescode);
                                                }
 
                                                LOG(4, s, t, "   Result Code %d: %s\n", rescode, resdesc);
                                                if (n >= 4)
                                                {
                                                        uint16_t errcode = ntohs(*(uint16_t *)(b + 2));
                                                }
 
                                                LOG(4, s, t, "   Result Code %d: %s\n", rescode, resdesc);
                                                if (n >= 4)
                                                {
                                                        uint16_t errcode = ntohs(*(uint16_t *)(b + 2));
-                                                       LOG(4, s, t, "   Error Code %d: %s\n", errcode, error_code(errcode));
+                                                       LOG(4, s, t, "   Error Code %d: %s\n", errcode, l2tp_error_code(errcode));
                                                }
                                                if (n > 4)
                                                        LOG(4, s, t, "   Error String: %.*s\n", n-4, b+4);
                                                }
                                                if (n > 4)
                                                        LOG(4, s, t, "   Error String: %.*s\n", n-4, b+4);
@@ -2222,7 +2213,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                case 29:    // Proxy Authentication Type
                                        {
                                                uint16_t atype = ntohs(*(uint16_t *)b);
                                case 29:    // Proxy Authentication Type
                                        {
                                                uint16_t atype = ntohs(*(uint16_t *)b);
-                                               LOG(4, s, t, "   Proxy Auth Type %d (%s)\n", atype, auth_type(atype));
+                                               LOG(4, s, t, "   Proxy Auth Type %d (%s)\n", atype, ppp_auth_type(atype));
                                                if (atype == 2)
                                                        authtype = AUTHCHAP;
                                                else if (atype == 3)
                                                if (atype == 2)
                                                        authtype = AUTHCHAP;
                                                else if (atype == 3)
@@ -2351,7 +2342,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                case 10:      // ICRQ
                                        if (sessionfree && main_quit != QUIT_SHUTDOWN)
                                        {
                                case 10:      // ICRQ
                                        if (sessionfree && main_quit != QUIT_SHUTDOWN)
                                        {
-                                               uint16_t r;
+                                               controlt *c = controlnew(11); // ICRP
 
                                                s = sessionfree;
                                                sessionfree = session[s].next;
 
                                                s = sessionfree;
                                                sessionfree = session[s].next;
@@ -2360,41 +2351,34 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                                if (s > config->cluster_highest_sessionid)
                                                        config->cluster_highest_sessionid = s;
 
                                                if (s > config->cluster_highest_sessionid)
                                                        config->cluster_highest_sessionid = s;
 
-                                               // make a RADIUS session
-                                               if ((r = radiusnew(s)))
-                                               {
-                                                       controlt *c = controlnew(11); // sending ICRP
-                                                       session[s].opened = time_now;
-                                                       session[s].tunnel = t;
-                                                       session[s].far = asession;
-                                                       session[s].last_packet = time_now;
-                                                       LOG(3, s, t, "New session (%d/%d)\n", tunnel[t].far, session[s].far);
-                                                       control16(c, 14, s, 1); // assigned session
-                                                       controladd(c, t, asession); // send the reply
-
-                                                       strncpy(radius[r].calling, calling, sizeof(radius[r].calling) - 1);
-                                                       strncpy(session[s].called, called, sizeof(session[s].called) - 1);
-                                                       strncpy(session[s].calling, calling, sizeof(session[s].calling) - 1);
-                                                       STAT(session_created);
-                                                       break;
-                                               }
+                                               session[s].opened = time_now;
+                                               session[s].tunnel = t;
+                                               session[s].far = asession;
+                                               session[s].last_packet = time_now;
+                                               LOG(3, s, t, "New session (%d/%d)\n", tunnel[t].far, session[s].far);
+                                               control16(c, 14, s, 1); // assigned session
+                                               controladd(c, t, asession); // send the reply
 
 
+                                               strncpy(session[s].called, called, sizeof(session[s].called) - 1);
+                                               strncpy(session[s].calling, calling, sizeof(session[s].calling) - 1);
 
 
-                                               LOG(1, s, t, "No free RADIUS sessions for ICRQ\n");
-                                               sessionclear(s);
-                                       }
-                                       else
-                                       {
-                                               STAT(session_overflow);
-                                               LOG(1, 0, t, "No free sessions\n");
+                                               session[s].ppp.phase = Establish;
+                                               session[s].ppp.lcp = Starting;
+
+                                               STAT(session_created);
+                                               break;
                                        }
 
                                        {
                                                controlt *c = controlnew(14); // CDN
                                        }
 
                                        {
                                                controlt *c = controlnew(14); // CDN
-                                               if (main_quit == QUIT_SHUTDOWN)
-                                                       control16(c, 1, 2, 7); // try another
-                                               else
+                                               if (!sessionfree)
+                                               {
+                                                       STAT(session_overflow);
+                                                       LOG(1, 0, t, "No free sessions\n");
                                                        control16(c, 1, 4, 0); // temporary lack of resources
                                                        control16(c, 1, 4, 0); // temporary lack of resources
+                                               }
+                                               else
+                                                       control16(c, 1, 2, 7); // shutting down, try another
 
                                                controladd(c, t, asession); // send the message
                                        }
 
                                                controladd(c, t, asession); // send the message
                                        }
@@ -2408,12 +2392,19 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                        session[s].l2tp_flags = aflags; // set flags received
                                        LOG(3, s, t, "Magic %X Flags %X\n", amagic, aflags);
                                        controlnull(t); // ack
                                        session[s].l2tp_flags = aflags; // set flags received
                                        LOG(3, s, t, "Magic %X Flags %X\n", amagic, aflags);
                                        controlnull(t); // ack
+
                                        // proxy authentication type is not supported
                                        if (!(config->radius_authtypes & authtype))
                                                authtype = config->radius_authprefer;
 
                                        // start LCP
                                        sendlcp(t, s, authtype);
                                        // proxy authentication type is not supported
                                        if (!(config->radius_authtypes & authtype))
                                                authtype = config->radius_authprefer;
 
                                        // start LCP
                                        sendlcp(t, s, authtype);
+                                       sess_local[s].lcp.restart = time_now + config->ppp_restart_time;
+                                       sess_local[s].lcp.conf_sent = 1;
+                                       sess_local[s].lcp.nak_sent = 0;
+                                       sess_local[s].lcp_authtype = authtype;
+                                       session[s].ppp.lcp = RequestSent;
+
                                        break;
                                case 14:      // CDN
                                        controlnull(t); // ack
                                        break;
                                case 14:      // CDN
                                        controlnull(t); // ack
@@ -2507,16 +2498,9 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                }
                else if (prot == PPPIPV6CP)
                {
                }
                else if (prot == PPPIPV6CP)
                {
-                       if (config->ipv6_prefix.s6_addr[0] > 0)
-                       {
-                               session[s].last_packet = time_now;
-                               if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; }
-                               processipv6cp(t, s, p, l);
-                       }
-                       else
-                       {
-                               LOG(1, s, t, "IPv6 not configured; ignoring IPv6CP\n");
-                       }
+                       session[s].last_packet = time_now;
+                       if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; }
+                       processipv6cp(t, s, p, l);
                }
                else if (prot == PPPCCP)
                {
                }
                else if (prot == PPPCCP)
                {
@@ -2543,7 +2527,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                }
                else if (prot == PPPIPV6)
                {
                }
                else if (prot == PPPIPV6)
                {
-                       if (!config->ipv6_prefix.s6_addr[0] > 0)
+                       if (!config->ipv6_prefix.s6_addr[0])
                        {
                                LOG(1, s, t, "IPv6 not configured; yet received IPv6 packet. Ignoring.\n");
                                return;
                        {
                                LOG(1, s, t, "IPv6 not configured; yet received IPv6 packet. Ignoring.\n");
                                return;
@@ -2592,7 +2576,7 @@ static void processtun(uint8_t * buf, int len)
        if (*(uint16_t *) (buf + 2) == htons(PKTIP)) // IPv4
                processipout(buf, len);
        else if (*(uint16_t *) (buf + 2) == htons(PKTIPV6) // IPV6
        if (*(uint16_t *) (buf + 2) == htons(PKTIP)) // IPv4
                processipout(buf, len);
        else if (*(uint16_t *) (buf + 2) == htons(PKTIPV6) // IPV6
-           && config->ipv6_prefix.s6_addr[0] > 0)
+           && config->ipv6_prefix.s6_addr[0])
                processipv6out(buf, len);
 
        // Else discard.
                processipv6out(buf, len);
 
        // Else discard.
@@ -2734,13 +2718,123 @@ static void regular_cleanups(double period)
                        continue;
                }
 
                        continue;
                }
 
-               if (session[s].ip && !(session[s].flags & SF_IPCP_ACKED)
-                   && !(sess_local[s].radius && radius[sess_local[s].radius].state == RADIUSIPCP))
+               // PPP timeouts
+               if (sess_local[s].lcp.restart >= time_now)
                {
                {
-                       // IPCP has not completed yet. Resend
-                       LOG(3, s, session[s].tunnel, "No ACK for initial IPCP ConfigReq... resending\n");
-                       sendipcp(session[s].tunnel, s);
-                       s_actions++;
+                       int next_state = session[s].ppp.lcp;
+                       switch (session[s].ppp.lcp)
+                       {
+                       case RequestSent:
+                       case AckReceived:
+                               next_state = RequestSent;
+
+                       case AckSent:
+                               if (sess_local[s].lcp.conf_sent < config->ppp_max_configure)
+                               {
+                                       LOG(3, s, session[s].tunnel, "No ACK for LCP ConfigReq... resending\n");
+                                       sess_local[s].lcp.restart = time_now + config->ppp_restart_time;
+                                       sess_local[s].lcp.conf_sent++;
+                                       sendlcp(t, s, sess_local[s].lcp_authtype);
+                                       change_state(s, lcp, next_state);
+                               }
+                               else
+                               {
+                                       sessionshutdown(s, "No response to LCP ConfigReq.", 3, 0);
+                                       STAT(session_timeout);
+                               }
+
+                               s_actions++;
+                       }
+
+                       if (session[s].die)
+                               continue;
+               }
+
+               if (sess_local[s].ipcp.restart >= time_now)
+               {
+                       int next_state = session[s].ppp.ipcp;
+                       switch (session[s].ppp.ipcp)
+                       {
+                       case RequestSent:
+                       case AckReceived:
+                               next_state = RequestSent;
+
+                       case AckSent:
+                               if (sess_local[s].ipcp.conf_sent < config->ppp_max_configure)
+                               {
+                                       LOG(3, s, session[s].tunnel, "No ACK for IPCP ConfigReq... resending\n");
+                                       sess_local[s].ipcp.restart = time_now + config->ppp_restart_time;
+                                       sess_local[s].ipcp.conf_sent++;
+                                       sendipcp(t, s);
+                                       change_state(s, ipcp, next_state);
+                               }
+                               else
+                               {
+                                       sessionshutdown(s, "No response to IPCP ConfigReq.", 3, 0);
+                                       STAT(session_timeout);
+                               }
+
+                               s_actions++;
+                       }
+
+                       if (session[s].die)
+                               continue;
+               }
+
+               if (sess_local[s].ipv6cp.restart >= time_now)
+               {
+                       int next_state = session[s].ppp.ipv6cp;
+                       switch (session[s].ppp.ipv6cp)
+                       {
+                       case RequestSent:
+                       case AckReceived:
+                               next_state = RequestSent;
+
+                       case AckSent:
+                               if (sess_local[s].ipv6cp.conf_sent < config->ppp_max_configure)
+                               {
+                                       LOG(3, s, session[s].tunnel, "No ACK for IPV6CP ConfigReq... resending\n");
+                                       sess_local[s].ipv6cp.restart = time_now + config->ppp_restart_time;
+                                       sess_local[s].ipv6cp.conf_sent++;
+                                       sendipv6cp(t, s);
+                                       change_state(s, ipv6cp, next_state);
+                               }
+                               else
+                               {
+                                       LOG(3, s, session[s].tunnel, "No ACK for IPV6CP ConfigReq\n");
+                                       change_state(s, ipv6cp, Stopped);
+                               }
+
+                               s_actions++;
+                       }
+               }
+
+               if (sess_local[s].ccp.restart >= time_now)
+               {
+                       int next_state = session[s].ppp.ccp;
+                       switch (session[s].ppp.ccp)
+                       {
+                       case RequestSent:
+                       case AckReceived:
+                               next_state = RequestSent;
+
+                       case AckSent:
+                               if (sess_local[s].ccp.conf_sent < config->ppp_max_configure)
+                               {
+                                       LOG(3, s, session[s].tunnel, "No ACK for CCP ConfigReq... resending\n");
+                                       sess_local[s].ccp.restart = time_now + config->ppp_restart_time;
+                                       sess_local[s].ccp.conf_sent++;
+                                       sendccp(t, s);
+                                       change_state(s, ccp, next_state);
+                               }
+                               else
+                               {
+                                       LOG(3, s, session[s].tunnel, "No ACK for CCP ConfigReq\n");
+                                       change_state(s, ccp, Stopped);
+                               }
+
+                               s_actions++;
+                       }
                }
 
                // Drop sessions who have not responded within IDLE_TIMEOUT seconds
                }
 
                // Drop sessions who have not responded within IDLE_TIMEOUT seconds
@@ -2753,7 +2847,7 @@ static void regular_cleanups(double period)
                }
 
                // No data in ECHO_TIMEOUT seconds, send LCP ECHO
                }
 
                // No data in ECHO_TIMEOUT seconds, send LCP ECHO
-               if (session[s].user[0] && (time_now - session[s].last_packet >= ECHO_TIMEOUT))
+               if (session[s].ppp.phase >= Establish && (time_now - session[s].last_packet >= ECHO_TIMEOUT))
                {
                        uint8_t b[MAXCONTROL] = {0};
 
                {
                        uint8_t b[MAXCONTROL] = {0};
 
@@ -3084,7 +3178,8 @@ static void mainloop(void)
                if (n)
                {
                        struct sockaddr_in addr;
                if (n)
                {
                        struct sockaddr_in addr;
-                       int alen, c, s;
+                       socklen_t alen;
+                       int c, s;
                        int udp_ready = 0;
                        int tun_ready = 0;
                        int cluster_ready = 0;
                        int udp_ready = 0;
                        int tun_ready = 0;
                        int cluster_ready = 0;
@@ -3391,6 +3486,9 @@ static void initdata(int optdebug, char *optconfig)
        config->num_tbfs = MAXTBFS;
        config->rl_rate = 28; // 28kbps
        config->cluster_master_min_adv = 1;
        config->num_tbfs = MAXTBFS;
        config->rl_rate = 28; // 28kbps
        config->cluster_master_min_adv = 1;
+       config->ppp_restart_time = 3;
+       config->ppp_max_configure = 10;
+       config->ppp_max_failure = 5;
        strcpy(config->random_device, RANDOMDEVICE);
 
        log_stream = stderr;
        strcpy(config->random_device, RANDOMDEVICE);
 
        log_stream = stderr;
@@ -3758,7 +3856,7 @@ static void initippool()
        LOG(1, 0, 0, "IP address pool is %d addresses\n", ip_pool_size - 1);
 }
 
        LOG(1, 0, 0, "IP address pool is %d addresses\n", ip_pool_size - 1);
 }
 
-void snoop_send_packet(char *packet, uint16_t size, in_addr_t destination, uint16_t port)
+void snoop_send_packet(uint8_t *packet, uint16_t size, in_addr_t destination, uint16_t port)
 {
        struct sockaddr_in snoop_addr = {0};
        if (!destination || !port || snoopfd <= 0 || size <= 0 || !packet)
 {
        struct sockaddr_in snoop_addr = {0};
        if (!destination || !port || snoopfd <= 0 || size <= 0 || !packet)
@@ -4055,7 +4153,7 @@ static void sigchild_handler(int sig)
            ;
 }
 
            ;
 }
 
-static void build_chap_response(char *challenge, uint8_t id, uint16_t challenge_length, char **challenge_response)
+static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challenge_length, uint8_t **challenge_response)
 {
        MD5_CTX ctx;
        *challenge_response = NULL;
 {
        MD5_CTX ctx;
        *challenge_response = NULL;
@@ -4068,13 +4166,13 @@ static void build_chap_response(char *challenge, uint8_t id, uint16_t challenge_
 
        LOG(4, 0, 0, "   Building challenge response for CHAP request\n");
 
 
        LOG(4, 0, 0, "   Building challenge response for CHAP request\n");
 
-       *challenge_response = (char *)calloc(17, 1);
+       *challenge_response = calloc(17, 1);
 
 
-       MD5Init(&ctx);
-       MD5Update(&ctx, &id, 1);
-       MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
-       MD5Update(&ctx, challenge, challenge_length);
-       MD5Final(*challenge_response, &ctx);
+       MD5_Init(&ctx);
+       MD5_Update(&ctx, &id, 1);
+       MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
+       MD5_Update(&ctx, challenge, challenge_length);
+       MD5_Final(*challenge_response, &ctx);
 
        return;
 }
 
        return;
 }
@@ -4384,13 +4482,8 @@ int sessionsetup(tunnelidt t, sessionidt s)
                        cache_ipmap(session[s].ip, s);
        }
 
                        cache_ipmap(session[s].ip, s);
        }
 
-       if (!session[s].unique_id)
-       {
-               // did this session just finish radius?
-               LOG(3, s, t, "Sending initial IPCP to client\n");
-               sendipcp(t, s);
-               session[s].unique_id = ++last_id;
-       }
+       sess_local[s].lcp_authtype = 0; // RADIUS authentication complete
+       lcp_open(t, s); // transition to Network phase and send initial IPCP
 
        // Run the plugin's against this new session.
        {
 
        // Run the plugin's against this new session.
        {
@@ -4499,7 +4592,7 @@ int load_session(sessionidt s, sessiont *new)
        }
 
        // check v6 routing
        }
 
        // check v6 routing
-       if (new->flags & SF_IPV6_ROUTED && !(session[s].flags & SF_IPV6_ROUTED))
+       if (new->ipv6prefixlen && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened)
                    route6set(s, new->ipv6route, new->ipv6prefixlen, 1);
 
        // check filters
                    route6set(s, new->ipv6route, new->ipv6prefixlen, 1);
 
        // check filters
@@ -4716,7 +4809,7 @@ static void plugins_done()
                run_plugin_done(p);
 }
 
                run_plugin_done(p);
 }
 
-static void processcontrol(uint8_t * buf, int len, struct sockaddr_in *addr, int alen)
+static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
 {
        struct nsctl request;
        struct nsctl response;
 {
        struct nsctl request;
        struct nsctl response;
@@ -5040,11 +5133,11 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec
        uint16_t m = htons(type);
 
        // Compute initial pad
        uint16_t m = htons(type);
 
        // Compute initial pad
-       MD5Init(&ctx);
-       MD5Update(&ctx, (unsigned char *) &m, 2);
-       MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
-       MD5Update(&ctx, vector, vec_len);
-       MD5Final(digest, &ctx);
+       MD5_Init(&ctx);
+       MD5_Update(&ctx, (unsigned char *) &m, 2);
+       MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
+       MD5_Update(&ctx, vector, vec_len);
+       MD5_Final(digest, &ctx);
 
        // pointer to last decoded 16 octets
        last = value;
 
        // pointer to last decoded 16 octets
        last = value;
@@ -5054,10 +5147,10 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec
                // calculate a new pad based on the last decoded block
                if (d >= sizeof(digest))
                {
                // calculate a new pad based on the last decoded block
                if (d >= sizeof(digest))
                {
-                       MD5Init(&ctx);
-                       MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
-                       MD5Update(&ctx, last, sizeof(digest));
-                       MD5Final(digest, &ctx);
+                       MD5_Init(&ctx);
+                       MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
+                       MD5_Update(&ctx, last, sizeof(digest));
+                       MD5_Final(digest, &ctx);
 
                        d = 0;
                        last = value;
 
                        d = 0;
                        last = value;
index a8e2d9a..2bf86bf 100644 (file)
--- a/l2tpns.h
+++ b/l2tpns.h
@@ -1,5 +1,5 @@
 // L2TPNS Global Stuff
 // L2TPNS Global Stuff
-// $Id: l2tpns.h,v 1.80 2005-06-28 14:48:27 bodea Exp $
+// $Id: l2tpns.h,v 1.81 2005-07-31 10:04:10 bodea Exp $
 
 #ifndef __L2TPNS_H__
 #define __L2TPNS_H__
 
 #ifndef __L2TPNS_H__
 #define __L2TPNS_H__
 #define CONFIGFILE     FLASHDIR "/startup-config"      // Configuration file
 #define CLIUSERS       FLASHDIR "/users"               // CLI Users file
 #define IPPOOLFILE     FLASHDIR "/ip_pool"             // Address pool configuration
 #define CONFIGFILE     FLASHDIR "/startup-config"      // Configuration file
 #define CLIUSERS       FLASHDIR "/users"               // CLI Users file
 #define IPPOOLFILE     FLASHDIR "/ip_pool"             // Address pool configuration
-#define ACCT_TIME      3000            // 5 minute accounting interval
-#define ACCT_SHUT_TIME 600             // 1 minute for counters of shutdown sessions
-#define        L2TPPORT        1701            // L2TP port
-#define RADPORT                1645            // old radius port...
-#define DAEPORT                3799            // DAE port
-#define        PKTARP          0x0806          // ARP packet type
-#define        PKTIP           0x0800          // IPv4 packet type
-#define        PKTIPV6         0x86DD          // IPv6 packet type
+#define ACCT_TIME      3000                            // 5 minute accounting interval
+#define ACCT_SHUT_TIME 600                             // 1 minute for counters of shutdown sessions
+#define        L2TPPORT        1701                            // L2TP port
+#define RADPORT                1645                            // old radius port...
+#define DAEPORT                3799                            // DAE port
+#define        PKTARP          0x0806                          // ARP packet type
+#define        PKTIP           0x0800                          // IPv4 packet type
+#define        PKTIPV6         0x86DD                          // IPv6 packet type
 #define        PPPPAP          0xC023
 #define        PPPCHAP         0xC223
 #define        PPPLCP          0xC021
 #define        PPPPAP          0xC023
 #define        PPPCHAP         0xC223
 #define        PPPLCP          0xC021
@@ -121,6 +121,52 @@ enum {
        CoANAK
 };
 
        CoANAK
 };
 
+// PPP phases
+enum {
+       Dead,
+       Establish,
+       Authenticate,
+       Network,
+       Terminate
+};
+
+// PPP states
+enum {
+       Initial,
+       Starting,
+       Closed,
+       Stopped,
+       Closing,
+       Stopping,
+       RequestSent,
+       AckReceived,
+       AckSent,
+       Opened
+};
+
+// reset state machine counters
+#define initialise_restart_count(_s, _fsm)                     \
+       sess_local[_s]._fsm.conf_sent = sess_local[_s]._fsm.nak_sent
+
+// stop timer on change to state where timer does not run
+#define change_state(_s, _fsm, _new) ({                                \
+       if (_new != session[_s].ppp._fsm)                       \
+       {                                                       \
+               switch (_new)                                   \
+               {                                               \
+               case Initial:                                   \
+               case Starting:                                  \
+               case Closed:                                    \
+               case Stopped:                                   \
+               case Opened:                                    \
+                       sess_local[_s]._fsm.restart = 0;        \
+                       initialise_restart_count(_s, _fsm);     \
+               }                                               \
+               session[_s].ppp._fsm = _new;                    \
+               cluster_send_session(_s);                       \
+       }                                                       \
+})
+
 // Types
 typedef uint16_t sessionidt;
 typedef uint16_t tunnelidt;
 // Types
 typedef uint16_t sessionidt;
 typedef uint16_t tunnelidt;
@@ -174,7 +220,14 @@ typedef struct
        sessionidt far;                 // far end session ID
        tunnelidt tunnel;               // near end tunnel ID
        uint8_t l2tp_flags;             // various bit flags from the ICCN on the l2tp tunnel.
        sessionidt far;                 // far end session ID
        tunnelidt tunnel;               // near end tunnel ID
        uint8_t l2tp_flags;             // various bit flags from the ICCN on the l2tp tunnel.
-       uint8_t flags;                  // Various session flags.
+       struct {
+               uint8_t phase;          // PPP phase
+               uint8_t lcp:4;          //   LCP    state
+               uint8_t ipcp:4;         //   IPCP   state
+               uint8_t ipv6cp:4;       //   IPV6CP state
+               uint8_t ccp:4;          //   CCP    state
+               uint8_t pad;            // unused
+       } ppp;
        in_addr_t ip;                   // IP of session set by RADIUS response (host byte order).
        int ip_pool_index;              // index to IP pool
        uint32_t unique_id;             // unique session id
        in_addr_t ip;                   // IP of session set by RADIUS response (host byte order).
        int ip_pool_index;              // index to IP pool
        uint32_t unique_id;             // unique session id
@@ -198,7 +251,7 @@ typedef struct
        uint16_t tbf_in;                // filter bucket for throttling in from the user.
        uint16_t tbf_out;               // filter bucket for throttling out to the user.
        int random_vector_length;
        uint16_t tbf_in;                // filter bucket for throttling in from the user.
        uint16_t tbf_out;               // filter bucket for throttling out to the user.
        int random_vector_length;
-       char random_vector[MAXTEL];
+       uint8_t random_vector[MAXTEL];
        char user[MAXUSER];             // user (needed in seesion for radius stop messages)
        char called[MAXTEL];            // called number
        char calling[MAXTEL];           // calling number
        char user[MAXUSER];             // user (needed in seesion for radius stop messages)
        char called[MAXTEL];            // called number
        char calling[MAXTEL];           // calling number
@@ -209,17 +262,10 @@ typedef struct
        uint8_t walled_garden;          // is this session gardened?
        uint8_t ipv6prefixlen;          // IPv6 route prefix length
        struct in6_addr ipv6route;      // Static IPv6 route
        uint8_t walled_garden;          // is this session gardened?
        uint8_t ipv6prefixlen;          // IPv6 route prefix length
        struct in6_addr ipv6route;      // Static IPv6 route
-       char reserved[16];              // Space to expand structure without changing HB_VERSION
+       char reserved[11];              // Space to expand structure without changing HB_VERSION
 }
 sessiont;
 
 }
 sessiont;
 
-#define SF_IPCP_ACKED  1       // Has this session seen an IPCP Ack?
-#define SF_LCP_ACKED   2       // LCP negotiated
-#define SF_CCP_ACKED   4       // CCP negotiated
-#define SF_IPV6CP_ACKED        8       // IPv6 negotiated
-#define SF_IPV6_NACKED 16      // IPv6 rejected
-#define SF_IPV6_ROUTED 32      // advertised v6 route
-
 #define AUTHPAP                1       // allow PAP
 #define AUTHCHAP       2       // allow CHAP
 
 #define AUTHPAP                1       // allow PAP
 #define AUTHCHAP       2       // allow CHAP
 
@@ -233,6 +279,16 @@ typedef struct
        uint32_t cin;
        uint32_t cout;
 
        uint32_t cin;
        uint32_t cout;
 
+       // PPP restart timer/counters
+       struct {
+               time_t restart;
+               int conf_sent;
+               int nak_sent;
+       } lcp, ipcp, ipv6cp, ccp;
+
+       // authentication to use
+       int lcp_authtype;
+
        // DoS prevention
        clockt last_packet_out;
        uint32_t packets_out;
        // DoS prevention
        clockt last_packet_out;
        uint32_t packets_out;
@@ -271,13 +327,12 @@ typedef struct
 }
 tunnelt;
 
 }
 tunnelt;
 
-// 180 bytes per radius session
+// 160 bytes per radius session
 typedef struct                 // outstanding RADIUS requests
 {
        sessionidt session;     // which session this applies to
        hasht auth;             // request authenticator
        clockt retry;           // when to try next
 typedef struct                 // outstanding RADIUS requests
 {
        sessionidt session;     // which session this applies to
        hasht auth;             // request authenticator
        clockt retry;           // when to try next
-       char calling[MAXTEL];   // calling number
        char pass[129];         // password
        uint8_t id;             // ID for PPP response
        uint8_t try;            // which try we are on
        char pass[129];         // password
        uint8_t id;             // ID for PPP response
        uint8_t try;            // which try we are on
@@ -328,7 +383,6 @@ enum
        RADIUSNULL,             // Not in use
        RADIUSCHAP,             // sending CHAP down PPP
        RADIUSAUTH,             // sending auth to RADIUS server
        RADIUSNULL,             // Not in use
        RADIUSCHAP,             // sending CHAP down PPP
        RADIUSAUTH,             // sending auth to RADIUS server
-       RADIUSIPCP,             // sending IPCP to end user
        RADIUSSTART,            // sending start accounting to RADIUS server
        RADIUSSTOP,             // sending stop accounting to RADIUS server
        RADIUSINTERIM,          // sending interim accounting to RADIUS server
        RADIUSSTART,            // sending start accounting to RADIUS server
        RADIUSSTOP,             // sending stop accounting to RADIUS server
        RADIUSINTERIM,          // sending interim accounting to RADIUS server
@@ -391,6 +445,7 @@ struct Tstats
     uint32_t   call_sessionbyuser;
     uint32_t   call_sendarp;
     uint32_t   call_sendipcp;
     uint32_t   call_sessionbyuser;
     uint32_t   call_sendarp;
     uint32_t   call_sendipcp;
+    uint32_t   call_sendipv6cp;
     uint32_t   call_processipv6cp;
     uint32_t   call_tunnelsend;
     uint32_t   call_sessionkill;
     uint32_t   call_processipv6cp;
     uint32_t   call_tunnelsend;
     uint32_t   call_sessionkill;
@@ -457,6 +512,10 @@ typedef struct
 
        char            random_device[256];             // random device path, defaults to RANDOMDEVICE
 
 
        char            random_device[256];             // random device path, defaults to RANDOMDEVICE
 
+       int             ppp_restart_time;               // timeout for PPP restart
+       int             ppp_max_configure;              // max lcp configure requests to send
+       int             ppp_max_failure;                // max lcp configure naks to send
+
        char            radiussecret[64];
        int             radius_accounting;
        int             radius_interim;
        char            radiussecret[64];
        int             radius_accounting;
        int             radius_interim;
@@ -601,6 +660,7 @@ void sendarp(int ifr_idx, const unsigned char* mac, in_addr_t ip);
 // ppp.c
 void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
 void processchap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
 // ppp.c
 void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
 void processchap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
+void lcp_open(tunnelidt t, sessionidt s);
 void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
 void processipcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
 void processipv6cp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
 void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
 void processipcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
 void processipv6cp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
@@ -611,6 +671,7 @@ void sendchap(tunnelidt t, sessionidt s);
 uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, tunnelidt t, sessionidt s, uint16_t mtype);
 void sendlcp(tunnelidt t, sessionidt s, int authtype);
 void send_ipin(sessionidt s, uint8_t *buf, int len);
 uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, tunnelidt t, sessionidt s, uint16_t mtype);
 void sendlcp(tunnelidt t, sessionidt s, int authtype);
 void send_ipin(sessionidt s, uint8_t *buf, int len);
+void sendccp(tunnelidt t, sessionidt s);
 
 
 // radius.c
 
 
 // radius.c
@@ -638,8 +699,9 @@ void filter_session(sessionidt s, int filter_in, int filter_out);
 void send_garp(in_addr_t ip);
 void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t);
 void sendipcp(tunnelidt t, sessionidt s);
 void send_garp(in_addr_t ip);
 void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t);
 void sendipcp(tunnelidt t, sessionidt s);
+void sendipv6cp(tunnelidt t, sessionidt s);
 void processudp(uint8_t *buf, int len, struct sockaddr_in *addr);
 void processudp(uint8_t *buf, int len, struct sockaddr_in *addr);
-void snoop_send_packet(char *packet, uint16_t size, in_addr_t destination, uint16_t port);
+void snoop_send_packet(uint8_t *packet, uint16_t size, in_addr_t destination, uint16_t port);
 int find_filter(char const *name, size_t len);
 int ip_filter(uint8_t *buf, int len, uint8_t filter);
 int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc);
 int find_filter(char const *name, size_t len);
 int ip_filter(uint8_t *buf, int len, uint8_t filter);
 int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc);
@@ -652,7 +714,7 @@ int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc
 #define LOG_HEX(D, t, d, s)    ({ if (D <= config->debug) _log_hex(D, t, d, s); })
 
 void _log(int level, sessionidt s, tunnelidt t, const char *format, ...) __attribute__((format (printf, 4, 5)));
 #define LOG_HEX(D, t, d, s)    ({ if (D <= config->debug) _log_hex(D, t, d, s); })
 
 void _log(int level, sessionidt s, tunnelidt t, const char *format, ...) __attribute__((format (printf, 4, 5)));
-void _log_hex(int level, const char *title, const char *data, int maxsize);
+void _log_hex(int level, const char *title, const uint8_t *data, int maxsize);
 
 int sessionsetup(tunnelidt t, sessionidt s);
 int run_plugins(int plugin_type, void *data);
 
 int sessionsetup(tunnelidt t, sessionidt s);
 int run_plugins(int plugin_type, void *data);
@@ -670,7 +732,7 @@ int cli_arg_help(struct cli_def *cli, int cr_ok, char *entry, ...);
 
 
 // icmp.c
 
 
 // icmp.c
-void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, char *packet, int packet_len);
+void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, uint8_t *packet, int packet_len);
 
 
 extern tunnelt *tunnel;
 
 
 extern tunnelt *tunnel;
index 6b760a1..c3d63ca 100644 (file)
@@ -8,8 +8,8 @@ Source: http://optusnet.dl.sourceforge.net/sourceforge/l2tpns/l2tpns-%{version}.
 URL: http://sourceforge.net/projects/l2tpns
 BuildRoot: %{_tmppath}/%{name}-%{version}-root
 Prereq: /sbin/chkconfig
 URL: http://sourceforge.net/projects/l2tpns
 BuildRoot: %{_tmppath}/%{name}-%{version}-root
 Prereq: /sbin/chkconfig
-BuildRequires: libcli >= 1.8.5
-Requires: libcli >= 1.8.5
+BuildRequires: libcli >= 1.8.5, openssl-devel
+Requires: libcli >= 1.8.5, openssl
 
 %description
 l2tpns is a layer 2 tunneling protocol network server (LNS).  It
 
 %description
 l2tpns is a layer 2 tunneling protocol network server (LNS).  It
@@ -43,5 +43,5 @@ rm -rf %{buildroot}
 %attr(644,root,root) /usr/share/man/man[58]/*
 
 %changelog
 %attr(644,root,root) /usr/share/man/man[58]/*
 
 %changelog
-* Wed Jun 29 2005 Brendan O'Dea <bod@c47.org> 2.1.2-1
+* Sun Jul 31 2005 Brendan O'Dea <bod@> 2.1.2-1
 - 2.1.2 release, see /usr/share/doc/l2tpns-2.1.2/Changes
 - 2.1.2 release, see /usr/share/doc/l2tpns-2.1.2/Changes
diff --git a/md5.c b/md5.c
deleted file mode 100644 (file)
index 59c87be..0000000
--- a/md5.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
- */
-
-char const *cvs_id_md5 = "$Id: md5.c,v 1.3 2004-08-13 00:02:50 fred_nerk Exp $";
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-#include <string.h>
-#include "md5.h"
-
-/* Constants for MD5Transform routine.
- */
-
-#define S11 7
-#define S12 12
-#define S13 17
-#define S14 22
-#define S21 5
-#define S22 9
-#define S23 14
-#define S24 20
-#define S31 4
-#define S32 11
-#define S33 16
-#define S34 23
-#define S41 6
-#define S42 10
-#define S43 15
-#define S44 21
-
-static void MD5Transform PROTO_LIST((UINT4[4], unsigned char[64]));
-static void Encode PROTO_LIST((unsigned char *, UINT4 *, unsigned int));
-static void Decode PROTO_LIST((UINT4 *, unsigned char *, unsigned int));
-
-static unsigned char PADDING[64] = {
-       0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions.
- */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | (~z)))
-
-/* ROTATE_LEFT rotates x left n bits.
- */
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-Rotation is separate from addition to prevent recomputation.
- */
-#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-
-/* MD5 initialization. Begins an MD5 operation, writing a new context.
- */
-void MD5Init(MD5_CTX *context)
-{
-       context->count[0] = context->count[1] = 0;
-       // Load magic initialization constants.
-       context->state[0] = 0x67452301;
-       context->state[1] = 0xefcdab89;
-       context->state[2] = 0x98badcfe;
-       context->state[3] = 0x10325476;
-}
-
-/* MD5 block update operation. Continues an MD5 message-digest
-  operation, processing another message block, and updating the
-  context.
- */
-void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputLen)
-
-{
-       unsigned int i,
-       index,
-       partLen;
-
-       /* Compute number of bytes mod 64 */
-       index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
-
-       /* Update number of bits */
-       if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3))
-               context->count[1]++;
-       context->count[1] += ((UINT4) inputLen >> 29);
-
-       partLen = 64 - index;
-
-       /* Transform as many times as possible.
-        */
-       if (inputLen >= partLen)
-       {
-               memcpy(&context->buffer[index], input, partLen);
-               MD5Transform(context->state, context->buffer);
-
-               for (i = partLen; i + 63 < inputLen; i += 64)
-                       MD5Transform(context->state, &input[i]);
-
-               index = 0;
-       }
-       else
-               i = 0;
-
-       /* Buffer remaining input */
-       memcpy(&context->buffer[index], &input[i], inputLen - i);
-}
-
-/* MD5 finalization. Ends an MD5 message-digest operation, writing the
-  the message digest and zeroizing the context.
- */
-void MD5Final(unsigned char digest[16], MD5_CTX *context)
-{
-       unsigned char bits[8];
-       unsigned int index, padLen;
-
-       /* Save number of bits */
-       Encode(bits, context->count, 8);
-
-       /* Pad out to 56 mod 64.
-        */
-       index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
-       padLen = (index < 56) ? (56 - index) : (120 - index);
-       MD5Update(context, PADDING, padLen);
-
-       /* Append length (before padding) */
-       MD5Update(context, bits, 8);
-
-       /* Store state in digest */
-       Encode(digest, context->state, 16);
-
-       /* Zeroize sensitive information.
-        */
-       memset(context, 0, sizeof(*context));
-}
-
-/* MD5 basic transformation. Transforms state based on block.
- */
-static void MD5Transform(UINT4 state[4], unsigned char block[64])
-{
-       UINT4 a = state[0],
-                 b = state[1],
-                     c = state[2],
-                         d = state[3],
-                             x[16];
-
-       Decode(x, block, 64);
-
-       /* Round 1 */
-       FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
-       FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
-       FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
-       FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
-       FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
-       FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
-       FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
-       FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
-       FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
-       FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
-       FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
-       FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
-       FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
-       FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
-       FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
-       FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
-       /* Round 2 */
-       GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
-       GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
-       GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
-       GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
-       GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
-       GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
-       GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
-       GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
-       GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
-       GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
-       GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
-
-       GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
-       GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
-       GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
-       GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
-       GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
-       /* Round 3 */
-       HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
-       HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
-       HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
-       HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
-       HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
-       HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
-       HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
-       HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
-       HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
-       HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
-       HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
-       HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
-       HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
-       HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
-       HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
-       HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
-
-       /* Round 4 */
-       II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
-       II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
-       II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
-       II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
-       II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
-       II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
-       II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
-       II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
-       II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
-       II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
-       II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
-       II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
-       II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
-       II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
-       II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
-       II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
-
-       state[0] += a;
-       state[1] += b;
-       state[2] += c;
-       state[3] += d;
-
-       // Zeroize sensitive information.
-       memset(x, 0, sizeof(x));
-}
-
-/* Encodes input (UINT4) into output (unsigned char). Assumes len is
-  a multiple of 4.
- */
-static void Encode(unsigned char *output, UINT4 *input, unsigned int len)
-{
-       unsigned int i, j;
-
-       for (i = 0, j = 0; j < len; i++, j += 4)
-       {
-               output[j] = (unsigned char) (input[i] & 0xff);
-               output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
-               output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
-               output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
-       }
-}
-
-/* Decodes input (unsigned char) into output (UINT4). Assumes len is
-  a multiple of 4.
- */
-static void Decode(UINT4 *output, unsigned char *input, unsigned int len)
-{
-       unsigned int i, j;
-
-       for (i = 0, j = 0; j < len; i++, j += 4)
-               output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
-}
-
diff --git a/md5.h b/md5.h
deleted file mode 100644 (file)
index 5685fdb..0000000
--- a/md5.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* RSAREF types and constants
- */
-
-#ifndef __MD5_H__
-#define __MD5_H__
-
-/* PROTOTYPES should be set to one if and only if the compiler supports
-  function argument prototyping.
-The following makes PROTOTYPES default to 0 if it has not already
-
-  been defined with C compiler flags.
- */
-#ifndef PROTOTYPES
-#define PROTOTYPES 0
-#endif
-
-/* POINTER defines a generic pointer type */
-typedef unsigned char *POINTER;
-
-/* UINT2 defines a two byte word */
-typedef unsigned short int UINT2;
-
-/* UINT4 defines a four byte word */
-typedef unsigned long int UINT4;
-
-/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
-If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
-  returns an empty list.
- */
-#if PROTOTYPES
-#define PROTO_LIST(list) list
-#else
-#define PROTO_LIST(list) ()
-#endif
-
-
-/* MD5.H - header file for MD5C.C
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-/* MD5 context. */
-typedef struct {
-  UINT4 state[4];                                   /* state (ABCD) */
-  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
-  unsigned char buffer[64];                         /* input buffer */
-} MD5_CTX;
-
-void MD5Init PROTO_LIST ((MD5_CTX *));
-void MD5Update PROTO_LIST
-  ((MD5_CTX *, unsigned char *, unsigned int));
-void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
-
-#endif /* __MD5_H__ */
diff --git a/nsctl.c b/nsctl.c
index 057edfa..59ad0c6 100644 (file)
--- a/nsctl.c
+++ b/nsctl.c
@@ -141,7 +141,7 @@ static struct nsctl *request(char *host, int port, int type, int argc, char *arg
     socklen_t len = sizeof(peer);
     struct hostent *h = gethostbyname(host);
     int fd;
     socklen_t len = sizeof(peer);
     struct hostent *h = gethostbyname(host);
     int fd;
-    char buf[NSCTL_MAX_PKT_SZ];
+    uint8_t buf[NSCTL_MAX_PKT_SZ];
     int sz;
     char *err;
 
     int sz;
     char *err;
 
index 6619ad3..faf3a5e 100644 (file)
--- a/plugin.h
+++ b/plugin.h
@@ -28,7 +28,7 @@ enum
 struct pluginfuncs
 {
        void (*log)(int level, sessionidt s, tunnelidt t, const char *format, ...);
 struct pluginfuncs
 {
        void (*log)(int level, sessionidt s, tunnelidt t, const char *format, ...);
-       void (*log_hex)(int level, const char *title, const char *data, int maxsize);
+       void (*log_hex)(int level, const char *title, const uint8_t *data, int maxsize);
        char *(*fmtaddr)(in_addr_t addr, int n);
        sessionidt (*get_session_by_username)(char *username);
        sessiont *(*get_session_by_id)(sessionidt s);
        char *(*fmtaddr)(in_addr_t addr, int n);
        sessionidt (*get_session_by_username)(char *username);
        sessiont *(*get_session_by_id)(sessionidt s);
diff --git a/ppp.c b/ppp.c
index 0d3b168..a604755 100644 (file)
--- a/ppp.c
+++ b/ppp.c
@@ -1,6 +1,6 @@
 // L2TPNS PPP Stuff
 
 // L2TPNS PPP Stuff
 
-char const *cvs_id_ppp = "$Id: ppp.c,v 1.64 2005-06-24 08:34:53 bodea Exp $";
+char const *cvs_id_ppp = "$Id: ppp.c,v 1.65 2005-07-31 10:04:10 bodea Exp $";
 
 #include <stdio.h>
 #include <string.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -23,8 +23,7 @@ extern uint32_t eth_tx;
 extern time_t time_now;
 extern configt *config;
 
 extern time_t time_now;
 extern configt *config;
 
-static void initccp(tunnelidt t, sessionidt s);
-static uint8_t *add_lcp_auth(uint8_t *b, int size, int authtype);
+static int add_lcp_auth(uint8_t *b, int size, int authtype);
 
 // Process PAP messages
 void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
 
 // Process PAP messages
 void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
@@ -32,6 +31,7 @@ void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
        char user[MAXUSER];
        char pass[MAXPASS];
        uint16_t hl;
        char user[MAXUSER];
        char pass[MAXPASS];
        uint16_t hl;
+       uint16_t r;
 
        CSTAT(processpap);
 
 
        CSTAT(processpap);
 
@@ -61,6 +61,12 @@ void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                return;
        }
 
                return;
        }
 
+       if (session[s].ppp.phase != Authenticate)
+       {
+               LOG(2, s, t, "PAP ignored in %s phase\n", ppp_phase(session[s].ppp.phase));
+               return;
+       }
+
        {
                uint8_t *b = p;
                b += 4;
        {
                uint8_t *b = p;
                b += 4;
@@ -78,7 +84,9 @@ void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                }
                LOG(3, s, t, "PAP login %s/%s\n", user, pass);
        }
                }
                LOG(3, s, t, "PAP login %s/%s\n", user, pass);
        }
-       if (session[s].ip || !sess_local[s].radius)
+
+       r = radiusnew(s);
+       if (session[s].ip || !r)
        {
                // respond now, either no RADIUS available or already authenticated
                uint8_t b[MAXCONTROL];
        {
                // respond now, either no RADIUS available or already authenticated
                uint8_t b[MAXCONTROL];
@@ -93,26 +101,21 @@ void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                p[1] = id;
                *(uint16_t *) (p + 2) = htons(5);       // length
                p[4] = 0;                               // no message
                p[1] = id;
                *(uint16_t *) (p + 2) = htons(5);       // length
                p[4] = 0;                               // no message
+               tunnelsend(b, 5 + (p - b), t);          // send it
+
                if (session[s].ip)
                {
                        LOG(3, s, t, "Already an IP allocated: %s (%d)\n",
                                fmtaddr(htonl(session[s].ip), 0), session[s].ip_pool_index);
                if (session[s].ip)
                {
                        LOG(3, s, t, "Already an IP allocated: %s (%d)\n",
                                fmtaddr(htonl(session[s].ip), 0), session[s].ip_pool_index);
-
-                       session[s].flags &= ~SF_IPCP_ACKED;
                }
                else
                {
                }
                else
                {
-                       LOG(1, s, t, "No radius session available to authenticate session...\n");
+                       LOG(1, s, t, "No RADIUS session available to authenticate session...\n");
+                       sessionshutdown(s, "No free RADIUS sessions.", 4, 0);
                }
                }
-               LOG(3, s, t, "Fallback response to PAP (%s)\n", (session[s].ip) ? "ACK" : "NAK");
-               tunnelsend(b, 5 + (p - b), t); // send it
-               sessionshutdown(s, "PAP authentication failed.", 3, 0);
        }
        else
        {
        }
        else
        {
-               // set up RADIUS request
-               uint16_t r = sess_local[s].radius;
-
                // Run PRE_AUTH plugins
                struct param_pre_auth packet = { &tunnel[t], &session[s], strdup(user), strdup(pass), PPPPAP, 1 };
                run_plugins(PLUGIN_PRE_AUTH, &packet);
                // Run PRE_AUTH plugins
                struct param_pre_auth packet = { &tunnel[t], &session[s], strdup(user), strdup(pass), PPPPAP, 1 };
                run_plugins(PLUGIN_PRE_AUTH, &packet);
@@ -177,6 +180,13 @@ void processchap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                sessionshutdown(s, "CHAP length mismatch.", 3, 0);
                return;
        }
                sessionshutdown(s, "CHAP length mismatch.", 3, 0);
                return;
        }
+
+       if (session[s].ppp.phase != Authenticate)
+       {
+               LOG(2, s, t, "CHAP ignored in %s phase\n", ppp_phase(session[s].ppp.phase));
+               return;
+       }
+
        if (p[1] != radius[r].id)
        {
                LOG(1, s, t, "Wrong CHAP response ID %d (should be %d) (%d)\n", p[1], radius[r].id, r);
        if (p[1] != radius[r].id)
        {
                LOG(1, s, t, "Wrong CHAP response ID %d (should be %d) (%d)\n", p[1], radius[r].id, r);
@@ -243,7 +253,7 @@ static void dumplcp(uint8_t *p, int l)
        uint8_t *o = (p + 4);
 
        LOG_HEX(5, "PPP LCP Packet", p, l);
        uint8_t *o = (p + 4);
 
        LOG_HEX(5, "PPP LCP Packet", p, l);
-       LOG(4, 0, 0, "PPP LCP Packet type %d (%s len %d)\n", *p, ppp_lcp_type((int)*p), ntohs( ((uint16_t *) p)[1]) );
+       LOG(4, 0, 0, "PPP LCP Packet type %d (%s len %d)\n", *p, ppp_code((int)*p), ntohs( ((uint16_t *) p)[1]) );
        LOG(4, 0, 0, "Length: %d\n", l);
        if (*p != ConfigReq && *p != ConfigRej && *p != ConfigAck)
                return;
        LOG(4, 0, 0, "Length: %d\n", l);
        if (*p != ConfigReq && *p != ConfigRej && *p != ConfigAck)
                return;
@@ -268,54 +278,54 @@ static void dumplcp(uint8_t *p, int l)
                {
                        case 1: // Maximum-Receive-Unit
                                if (length == 4)
                {
                        case 1: // Maximum-Receive-Unit
                                if (length == 4)
-                                       LOG(4, 0, 0, "    %s %d\n", lcp_type(type), ntohs(*(uint16_t *)(o + 2)));
+                                       LOG(4, 0, 0, "    %s %d\n", ppp_lcp_option(type), ntohs(*(uint16_t *)(o + 2)));
                                else
                                else
-                                       LOG(4, 0, 0, "    %s odd length %d\n", lcp_type(type), length);
+                                       LOG(4, 0, 0, "    %s odd length %d\n", ppp_lcp_option(type), length);
                                break;
                        case 2: // Async-Control-Character-Map
                                if (length == 6)
                                {
                                        uint32_t asyncmap = ntohl(*(uint32_t *)(o + 2));
                                break;
                        case 2: // Async-Control-Character-Map
                                if (length == 6)
                                {
                                        uint32_t asyncmap = ntohl(*(uint32_t *)(o + 2));
-                                       LOG(4, 0, 0, "    %s %x\n", lcp_type(type), asyncmap);
+                                       LOG(4, 0, 0, "    %s %x\n", ppp_lcp_option(type), asyncmap);
                                }
                                else
                                }
                                else
-                                       LOG(4, 0, 0, "   %s odd length %d\n", lcp_type(type), length);
+                                       LOG(4, 0, 0, "   %s odd length %d\n", ppp_lcp_option(type), length);
                                break;
                        case 3: // Authentication-Protocol
                                if (length == 4)
                                {
                                        int proto = ntohs(*(uint16_t *)(o + 2));
                                break;
                        case 3: // Authentication-Protocol
                                if (length == 4)
                                {
                                        int proto = ntohs(*(uint16_t *)(o + 2));
-                                       LOG(4, 0, 0, "   %s 0x%x (%s)\n", lcp_type(type), proto,
+                                       LOG(4, 0, 0, "   %s 0x%x (%s)\n", ppp_lcp_option(type), proto,
                                                proto == PPPPAP  ? "PAP"  : "UNSUPPORTED");
                                }
                                else if (length == 5)
                                {
                                        int proto = ntohs(*(uint16_t *)(o + 2));
                                        int algo = *(uint8_t *)(o + 4);
                                                proto == PPPPAP  ? "PAP"  : "UNSUPPORTED");
                                }
                                else if (length == 5)
                                {
                                        int proto = ntohs(*(uint16_t *)(o + 2));
                                        int algo = *(uint8_t *)(o + 4);
-                                       LOG(4, 0, 0, "   %s 0x%x 0x%x (%s)\n", lcp_type(type), proto, algo,
+                                       LOG(4, 0, 0, "   %s 0x%x 0x%x (%s)\n", ppp_lcp_option(type), proto, algo,
                                                (proto == PPPCHAP && algo == 5) ? "CHAP MD5"  : "UNSUPPORTED");
                                }
                                else
                                                (proto == PPPCHAP && algo == 5) ? "CHAP MD5"  : "UNSUPPORTED");
                                }
                                else
-                                       LOG(4, 0, 0, "   %s odd length %d\n", lcp_type(type), length);
+                                       LOG(4, 0, 0, "   %s odd length %d\n", ppp_lcp_option(type), length);
                                break;
                        case 4: // Quality-Protocol
                                {
                                        uint32_t qp = ntohl(*(uint32_t *)(o + 2));
                                break;
                        case 4: // Quality-Protocol
                                {
                                        uint32_t qp = ntohl(*(uint32_t *)(o + 2));
-                                       LOG(4, 0, 0, "    %s %x\n", lcp_type(type), qp);
+                                       LOG(4, 0, 0, "    %s %x\n", ppp_lcp_option(type), qp);
                                }
                                break;
                        case 5: // Magic-Number
                                if (length == 6)
                                {
                                        uint32_t magicno = ntohl(*(uint32_t *)(o + 2));
                                }
                                break;
                        case 5: // Magic-Number
                                if (length == 6)
                                {
                                        uint32_t magicno = ntohl(*(uint32_t *)(o + 2));
-                                       LOG(4, 0, 0, "    %s %x\n", lcp_type(type), magicno);
+                                       LOG(4, 0, 0, "    %s %x\n", ppp_lcp_option(type), magicno);
                                }
                                else
                                }
                                else
-                                       LOG(4, 0, 0, "   %s odd length %d\n", lcp_type(type), length);
+                                       LOG(4, 0, 0, "   %s odd length %d\n", ppp_lcp_option(type), length);
                                break;
                        case 7: // Protocol-Field-Compression
                        case 8: // Address-And-Control-Field-Compression
                                break;
                        case 7: // Protocol-Field-Compression
                        case 8: // Address-And-Control-Field-Compression
-                               LOG(4, 0, 0, "    %s\n", lcp_type(type));
+                               LOG(4, 0, 0, "    %s\n", ppp_lcp_option(type));
                                break;
                        default:
                                LOG(2, 0, 0, "    Unknown PPP LCP Option type %d\n", type);
                                break;
                        default:
                                LOG(2, 0, 0, "    Unknown PPP LCP Option type %d\n", type);
@@ -326,6 +336,113 @@ static void dumplcp(uint8_t *p, int l)
        }
 }
 
        }
 }
 
+void lcp_open(tunnelidt t, sessionidt s)
+{
+       // transition to Authentication or Network phase: 
+       session[s].ppp.phase = sess_local[s].lcp_authtype ? Authenticate : Network;
+
+       // LCP now Opened
+       change_state(s, lcp, Opened);
+
+       if (session[s].ppp.phase == Authenticate)
+       {
+               if (sess_local[s].lcp_authtype == AUTHCHAP)
+                       sendchap(t, s);
+       }
+       else
+       {
+               // This-Layer-Up
+               sendipcp(t, s);
+               change_state(s, ipcp, RequestSent);
+               // move to passive state for IPv6 (if configured), CCP
+               if (config->ipv6_prefix.s6_addr[0])
+                       change_state(s, ipv6cp, Stopped);
+               else
+                       change_state(s, ipv6cp, Closed);
+
+               change_state(s, ccp, Stopped);
+       }
+}
+
+static void lcp_restart(sessionidt s)
+{
+       session[s].ppp.phase = Establish;
+       // This-Layer-Down
+       change_state(s, ipcp, Dead);
+       change_state(s, ipv6cp, Dead);
+       change_state(s, ccp, Dead);
+}
+
+static uint8_t *ppp_rej(sessionidt s, uint8_t *buf, size_t blen, uint16_t mtype,
+       uint8_t **response, uint8_t *queued, uint8_t *packet, uint8_t *option)
+{
+       if (!*response || **response != ConfigRej)
+       {
+               queued = *response = makeppp(buf, blen, packet, 2, session[s].tunnel, s, mtype);
+               if (!queued)
+                       return 0;
+
+               *queued = ConfigRej;
+               queued += 4;
+       }
+
+       if ((queued - buf + option[1]) > blen)
+       {
+               LOG(2, s, session[s].tunnel, "PPP overflow for ConfigRej (proto %u, option %u).\n", mtype, *option);
+               return 0;
+       }
+
+       memcpy(queued, option, option[1]);
+       return queued + option[1];
+}
+
+static uint8_t *ppp_nak(sessionidt s, uint8_t *buf, size_t blen, uint16_t mtype,
+       uint8_t **response, uint8_t *queued, uint8_t *packet, uint8_t *option,
+       uint8_t *value, size_t vlen)
+{
+       int *nak_sent;
+       switch (mtype)
+       {
+       case PPPLCP:    nak_sent = &sess_local[s].lcp.nak_sent;    break;
+       case PPPIPCP:   nak_sent = &sess_local[s].ipcp.nak_sent;   break;
+       case PPPIPV6CP: nak_sent = &sess_local[s].ipv6cp.nak_sent; break;
+       default:        return 0; // ?
+       }
+
+       if (*response && **response != ConfigNak)
+       {
+               if (*nak_sent < config->ppp_max_failure) // reject queued
+                       return queued;
+
+               return ppp_rej(s, buf, blen, mtype, response, 0, packet, option);
+       }
+
+       if (!*response)
+       {
+               if (*nak_sent >= config->ppp_max_failure)
+                       return ppp_rej(s, buf, blen, mtype, response, 0, packet, option);
+
+               queued = *response = makeppp(buf, blen, packet, 2, session[s].tunnel, s, mtype);
+               if (!queued)
+                       return 0;
+
+               *nak_sent++;
+               *queued = ConfigNak;
+               queued += 4;
+       }
+
+       if ((queued - buf + vlen + 2) > blen)
+       {
+               LOG(2, s, session[s].tunnel, "PPP overflow for ConfigNak (proto %u, option %u).\n", mtype, *option);
+               return 0;
+       }
+
+       *queued++ = *option;
+       *queued++ = vlen + 2;
+       memcpy(queued, value, vlen);
+       return queued + vlen;
+}
+
 // Process LCP messages
 void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
 {
 // Process LCP messages
 void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
 {
@@ -352,10 +469,14 @@ void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
        }
        l = hl;
 
        }
        l = hl;
 
+       if (session[s].die) // going down...
+               return;
+
        if (*p == ConfigAck)
        {
                int x = l - 4;
                uint8_t *o = (p + 4);
        if (*p == ConfigAck)
        {
                int x = l - 4;
                uint8_t *o = (p + 4);
+               int authtype = 0;
 
                LOG(3, s, t, "LCP: ConfigAck (%d bytes)...\n", l);
                if (config->debug > 3) dumplcp(p, l);
 
                LOG(3, s, t, "LCP: ConfigAck (%d bytes)...\n", l);
                if (config->debug > 3) dumplcp(p, l);
@@ -371,8 +492,10 @@ void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                                case 3: // Authentication-Protocol
                                        {
                                                int proto = ntohs(*(uint16_t *)(o + 2));
                                case 3: // Authentication-Protocol
                                        {
                                                int proto = ntohs(*(uint16_t *)(o + 2));
-                                               if (proto == PPPCHAP && *(o + 4) == 5)
-                                                       sendchap(t, s);
+                                               if (proto == PPPPAP)
+                                                       authtype = AUTHPAP;
+                                               else if (proto == PPPCHAP && *(o + 4) == 5)
+                                                       authtype = AUTHCHAP;
                                        }
 
                                        break;
                                        }
 
                                        break;
@@ -381,13 +504,41 @@ void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                        o += length;
                }
 
                        o += length;
                }
 
-               session[s].flags |= SF_LCP_ACKED;
+               if (!session[s].ip && authtype)
+                       sess_local[s].lcp_authtype = authtype;
+
+               switch (session[s].ppp.lcp)
+               {
+               case RequestSent:
+                       initialise_restart_count(s, lcp);
+                       change_state(s, lcp, AckReceived);
+                       break;
+
+               case AckReceived:
+               case Opened:
+                       LOG(3, s, t, "LCP: ConfigAck in state %s?  Sending ConfigReq\n", ppp_state(session[s].ppp.lcp));
+                       if (session[s].ppp.lcp == Opened)
+                               lcp_restart(s);
+
+                       sendlcp(s, t, sess_local[s].lcp_authtype);
+                       change_state(s, lcp, RequestSent);
+                       break;
+
+               case AckSent:
+                       lcp_open(t, s);
+                       break;
+
+               default:
+                       LOG(3, s, t, "LCP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.lcp));
+               }
        }
        else if (*p == ConfigReq)
        {
                int x = l - 4;
                uint8_t *o = (p + 4);
                uint8_t *response = 0;
        }
        else if (*p == ConfigReq)
        {
                int x = l - 4;
                uint8_t *o = (p + 4);
                uint8_t *response = 0;
+               static uint8_t asyncmap[4] = { 0, 0, 0, 0 }; // all zero
+               static uint8_t authproto[5];
 
                LOG(3, s, t, "LCP: ConfigReq (%d bytes)...\n", l);
                if (config->debug > 3) dumplcp(p, l);
 
                LOG(3, s, t, "LCP: ConfigReq (%d bytes)...\n", l);
                if (config->debug > 3) dumplcp(p, l);
@@ -408,40 +559,23 @@ void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                                        if (!ntohl(*(uint32_t *)(o + 2))) // all bits zero is OK
                                                break;
 
                                        if (!ntohl(*(uint32_t *)(o + 2))) // all bits zero is OK
                                                break;
 
-                                       if (response && *response != ConfigNak) // rej already queued
-                                               break;
-
                                        LOG(2, s, t, "    Remote requesting asyncmap.  Rejecting.\n");
                                        LOG(2, s, t, "    Remote requesting asyncmap.  Rejecting.\n");
-                                       if (!response)
-                                       {
-                                               q = response = makeppp(b, sizeof(b), p, 2, t, s, PPPLCP);
-                                               if (!q) break;
-                                               *q = ConfigNak;
-                                               q += 4;
-                                       }
-
-                                       if ((q - b + 11) > sizeof(b))
-                                       {
-                                               LOG(2, s, t, "LCP overflow for asyncmap ConfigNak.\n");
-                                               break;
-                                       }
-
-                                       *q++ = type;
-                                       *q++ = 6;
-                                       memset(q, 0, 4); // asyncmap 0
-                                       q += 4;
+                                       q = ppp_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, asyncmap, sizeof(asyncmap));
                                        break;
 
                                case 3: // Authentication-Protocol
                                        {
                                                int proto = ntohs(*(uint16_t *)(o + 2));
                                                char proto_name[] = "0x0000";
                                        break;
 
                                case 3: // Authentication-Protocol
                                        {
                                                int proto = ntohs(*(uint16_t *)(o + 2));
                                                char proto_name[] = "0x0000";
-                                               uint8_t *a;
+                                               int alen;
 
                                                if (proto == PPPPAP)
                                                {
                                                        if (config->radius_authtypes & AUTHPAP)
 
                                                if (proto == PPPPAP)
                                                {
                                                        if (config->radius_authtypes & AUTHPAP)
+                                                       {
+                                                               sess_local[s].lcp_authtype = AUTHPAP;
                                                                break;
                                                                break;
+                                                       }
 
                                                        strcpy(proto_name, "PAP");
                                                }
 
                                                        strcpy(proto_name, "PAP");
                                                }
@@ -449,45 +583,29 @@ void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                                                {
                                                        if (config->radius_authtypes & AUTHCHAP
                                                            && *(o + 4) == 5) // MD5
                                                {
                                                        if (config->radius_authtypes & AUTHCHAP
                                                            && *(o + 4) == 5) // MD5
+                                                       {
+                                                               sess_local[s].lcp_authtype = AUTHCHAP;
                                                                break;
                                                                break;
+                                                       }
 
                                                        strcpy(proto_name, "CHAP");
                                                }
                                                else
                                                        sprintf(proto_name, "%#4.4x", proto);
 
 
                                                        strcpy(proto_name, "CHAP");
                                                }
                                                else
                                                        sprintf(proto_name, "%#4.4x", proto);
 
-                                               if (response && *response != ConfigNak) // rej already queued
-                                                       break;
-
                                                LOG(2, s, t, "    Remote requesting %s authentication.  Rejecting.\n", proto_name);
 
                                                LOG(2, s, t, "    Remote requesting %s authentication.  Rejecting.\n", proto_name);
 
-                                               if (!response)
-                                               {
-                                                       q = response = makeppp(b, sizeof(b), p, 2, t, s, PPPLCP);
-                                                       if (!q) break;
-                                                       *q = ConfigNak;
-                                                       q += 4;
-                                               }
-
-                                               a = add_lcp_auth(q, sizeof(b) - (q - b), config->radius_authprefer);
-                                               if (!a)
-                                               {
-                                                       LOG(2, s, t, "LCP overflow for %s ConfigNak.\n", proto_name);
-                                                       break;
-                                               }
-
-                                               q = a;
+                                               alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authprefer);
+                                               if (alen < 2) break; // paranoia
 
 
-                                               if (config->radius_authtypes != config->radius_authprefer)
+                                               q = ppp_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, authproto + 2, alen - 2);
+                                               if (q && *response == ConfigNak &&
+                                                       config->radius_authtypes != config->radius_authprefer)
                                                {
                                                {
-                                                       a = add_lcp_auth(q, sizeof(b) - (q - b), config->radius_authtypes & ~config->radius_authprefer);
-                                                       if (!a)
-                                                       {
-                                                               LOG(2, s, t, "LCP overflow for %s ConfigNak.\n", proto_name);
-                                                               break;
-                                                       }
-
-                                                       q = a;
+                                                       // alternate type
+                                                       alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authtypes & ~config->radius_authprefer);
+                                                       if (alen < 2) break;
+                                                       q = ppp_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, authproto + 2, alen - 2);
                                                }
 
                                                break;
                                                }
 
                                                break;
@@ -505,22 +623,7 @@ void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
 
                                default: // Reject any unknown options
                                        LOG(2, s, t, "    Rejecting PPP LCP Option type %d\n", type);
 
                                default: // Reject any unknown options
                                        LOG(2, s, t, "    Rejecting PPP LCP Option type %d\n", type);
-                                       if (!response || *response != ConfigRej) // drop nak in favour of rej
-                                       {
-                                               q = response = makeppp(b, sizeof(b), p, 2, t, s, PPPLCP);
-                                               if (!q) break;
-                                               *q = ConfigRej;
-                                               q += 4;
-                                       }
-
-                                       if ((q - b + length) > sizeof(b))
-                                       {
-                                               LOG(2, s, t, "LCP overflow for ConfigRej (type=%d).\n", type);
-                                               break;
-                                       }
-
-                                       memcpy(q, o, length);
-                                       q += length;
+                                       q = ppp_rej(s, b, sizeof(b), PPPLCP, &response, q, p, o);
                        }
                        x -= length;
                        o += length;
                        }
                        x -= length;
                        o += length;
@@ -539,11 +642,57 @@ void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                        *response = ConfigAck;
                }
 
                        *response = ConfigAck;
                }
 
-               LOG(3, s, t, "Sending %s\n", ppp_lcp_type(*response));
-               tunnelsend(b, l + response - b, t);
+               switch (session[s].ppp.lcp)
+               {
+               case Closed:
+                       response = makeppp(b, sizeof(b), p, 2, t, s, PPPLCP);
+                       if (!response) return;
+                       *response = TerminateAck;
+                       *((uint16_t *) (response + 2)) = htons(l = 4);
+                       break;
+
+               case Stopped:
+                       initialise_restart_count(s, lcp);
+                       sendlcp(s, t, sess_local[s].lcp_authtype);
+                       if (*response == ConfigAck)
+                               change_state(s, lcp, AckSent);
+                       else
+                               change_state(s, lcp, RequestSent);
+
+                       break;
+
+               case RequestSent:
+                       if (*response == ConfigAck)
+                               change_state(s, lcp, AckSent);
+
+                       break;
+
+               case AckReceived:
+                       if (*response == ConfigAck)
+                               lcp_open(t, s);
+
+                       break;
+
+               case Opened:
+                       lcp_restart(s);
+                       sendlcp(s, t, sess_local[s].lcp_authtype);
+                       /* fallthrough */
+
+               case AckSent:
+                       if (*response == ConfigAck)
+                               change_state(s, lcp, AckSent);
+                       else
+                               change_state(s, lcp, RequestSent);
 
 
-               if (!(session[s].flags & SF_LCP_ACKED))
-                       sendlcp(t, s, config->radius_authprefer);
+                       break;
+
+               default:
+                       LOG(3, s, t, "LCP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.lcp));
+                       return;
+               }
+
+               LOG(3, s, t, "LCP: Sending %s\n", ppp_code(*response));
+               tunnelsend(b, l + (response - b), t);
        }
        else if (*p == ConfigNak)
        {
        }
        else if (*p == ConfigNak)
        {
@@ -608,10 +757,42 @@ void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                        return;
                }
 
                        return;
                }
 
-               if (authtype == -1)
-                       authtype = config->radius_authprefer;
+               if (authtype > 0)
+                       sess_local[s].lcp_authtype = authtype;
+
+               switch (session[s].ppp.lcp)
+               {
+               case Closed:
+               case Stopped:
+                       {
+                               uint8_t *response = makeppp(b, sizeof(b), p, 2, t, s, PPPLCP);
+                               if (!response) return;
+                               *response = TerminateAck;
+                               *((uint16_t *) (response + 2)) = htons(l = 4);
+                               tunnelsend(b, l + (response - b), t);
+                       }
+                       break;
+
+               case RequestSent:
+               case AckSent:
+                       initialise_restart_count(s, lcp);
+                       sendlcp(s, t, sess_local[s].lcp_authtype);
+                       break;
+
+               case AckReceived:
+                       LOG(3, s, t, "LCP: ConfigNak in state %s?  Sending ConfigReq\n", ppp_state(session[s].ppp.lcp));
+                       sendlcp(s, t, sess_local[s].lcp_authtype);
+                       break;
+
+               case Opened:
+                       lcp_restart(s);
+                       sendlcp(s, t, sess_local[s].lcp_authtype);
+                       break;
 
 
-               sendlcp(t, s, authtype);
+               default:
+                       LOG(3, s, t, "LCP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.lcp));
+                       return;
+               }
        }
        else if (*p == TerminateReq)
        {
        }
        else if (*p == TerminateReq)
        {
@@ -631,7 +812,7 @@ void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                if (*(uint16_t *) (p+4) == htons(PPPIPV6CP))
                {
                        LOG(3, s, t, "IPv6 rejected\n");
                if (*(uint16_t *) (p+4) == htons(PPPIPV6CP))
                {
                        LOG(3, s, t, "IPv6 rejected\n");
-                       session[s].flags |= SF_IPV6_NACKED;
+                       change_state(s, ipv6cp, Closed);
                }
                else
                {
                }
                else
                {
@@ -653,49 +834,50 @@ void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
        {
                // Ignore it, last_packet time is set earlier than this.
        }
        {
                // Ignore it, last_packet time is set earlier than this.
        }
-       else if (*p == IdentRequest)
+       else
        {
        {
+               int code = *p;
+               int mru = session[s].mru;
+               if (!mru)
+                       mru = DEFAULT_MRU;
+
+               if (l > mru) l = mru;
+
                *p = CodeRej;
                *p = CodeRej;
-               if (l > MAXCONTROL)
-               {
-                       LOG(1, s, t, "Truncated Ident Packet (length=%d) to 1400 bytes\n", l);
-                       l = 1400;
-               }
                q = makeppp(b, sizeof(b), p, l, t, s, PPPLCP);
                if (!q) return;
                q = makeppp(b, sizeof(b), p, l, t, s, PPPLCP);
                if (!q) return;
-               LOG_HEX(5, "LCPIdentRej", q, l + 4);
-               tunnelsend(b, 12 + 4 + l, t);
-       }
-       else
-       {
-               LOG(1, s, t, "Unexpected LCP code %d\n", *p);
-               STAT(tunnel_rx_errors);
+
+               LOG(3, s, t, "Unexpected LCP code %s\n", ppp_code(code));
+               tunnelsend(b, l + (q - b), t);
        }
 }
 
        }
 }
 
-// find a PPP option, returns point to option, or 0 if not found
-static uint8_t *findppp(uint8_t *b, uint8_t mtype)
+static void ipcp_open(tunnelidt t, sessionidt s)
 {
 {
-       uint16_t l = ntohs(*(uint16_t *) (b + 2));
-       if (l < 4)
-               return 0;
-       b += 4;
-       l -= 4;
-       while (l)
+       LOG(3, s, t, "IPCP Acked, session is now active\n");
+
+       change_state(s, ipcp, Opened);
+
+       if (!session[s].walled_garden)
        {
        {
-               if (l < b[1] || !b[1])
-                       return 0;               // faulty
-               if (*b == mtype)
-                       return b;
-               l -= b[1];
-               b += b[1];
+               uint16_t r = radiusnew(s);
+               if (r)
+                       radiussend(r, RADIUSSTART); // send radius start
+       }
+
+       // start IPv6 if configured and still in passive state
+       if (session[s].ppp.ipv6cp == Stopped)
+       {
+               sendipv6cp(t, s);
+               change_state(s, ipv6cp, RequestSent);
        }
        }
-       return 0;
 }
 
 // Process IPCP messages
 void processipcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
 {
 }
 
 // Process IPCP messages
 void processipcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
 {
+       uint8_t b[MAXCONTROL];
+       uint8_t *q = 0;
        uint16_t hl;
 
        CSTAT(processipcp);
        uint16_t hl;
 
        CSTAT(processipcp);
@@ -716,135 +898,217 @@ void processipcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
        }
        l = hl;
 
        }
        l = hl;
 
+       if (session[s].ppp.phase < Network)
+       {
+               LOG(2, s, t, "IPCP %s ignored in %s phase\n", ppp_code(*p), ppp_phase(session[s].ppp.phase));
+               return;
+       }
+
        if (*p == ConfigAck)
        {
        if (*p == ConfigAck)
        {
-               uint16_t r = sess_local[s].radius;
+               switch (session[s].ppp.ipcp)
+               {
+               case RequestSent:
+                       initialise_restart_count(s, ipcp);
+                       change_state(s, ipcp, AckReceived);
+                       break;
 
 
-               // ignore duplicate ACKs
-               if (session[s].flags & SF_IPCP_ACKED)
-                       return;
+               case AckReceived:
+               case Opened:
+                       LOG(3, s, t, "IPCP: ConfigAck in state %s?  Sending ConfigReq\n", ppp_state(session[s].ppp.ipcp));
+                       sendipcp(s, t);
+                       change_state(s, ipcp, RequestSent);
+                       break;
 
 
-               // happy with our IPCP
-               session[s].flags |= SF_IPCP_ACKED;
+               case AckSent:
+                       ipcp_open(t, s);
+                       break;
 
 
-               LOG(3, s, t, "IPCP Acked, session is now active\n");
+               default:
+                       LOG(3, s, t, "IPCP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.ipcp));
+               }
+       }
+       else if (*p == ConfigReq)
+       {
+               uint8_t *response = 0;
+               uint8_t *o = p + 4;
+               int length = l - 4;
+               int gotip = 0;
+               in_addr_t addr;
 
 
-               // clear LCP_ACKED/CCP_ACKED flag for possible fast renegotiation for routers
-               session[s].flags &= ~(SF_LCP_ACKED|SF_CCP_ACKED);
+               LOG(4, s, t, "IPCP ConfigReq received\n");
 
 
-               if (r && session[s].walled_garden)
+               while (length > 2)
                {
                {
-                       radiusclear(r, s);
-                       return;
-               }
+                       switch (*o)
+                       {
+                       case 3: // ip address
+                               gotip++; // seen address
+                               if (o[1] != 6 || o[1] > length) return;
 
 
-               if (!r)
-                       r = radiusnew(s);
+                               addr = htonl(session[s].ip);
+                               if (memcmp(o + 2, &addr, (sizeof addr)))
+                               {
+                                       q = ppp_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
+                                       if (!q || *response == ConfigRej)
+                                       {
+                                               sessionshutdown(s, "Can't negotiate IPCP.", 3, 0);
+                                               return;
+                                       }
+                               }
 
 
-               if (r)
-                       radiussend(r, RADIUSSTART); // send radius start, having got IPCP at last
+                               break;
 
 
-               return;
-       }
-       if (*p != ConfigReq)
-       {
-               LOG(1, s, t, "Unexpected IPCP code %d\n", *p);
-               STAT(tunnel_rx_errors);
-               return ;
-       }
-       LOG(4, s, t, "IPCP ConfigReq received\n");
+                       case 129: // primary DNS
+                               if (o[1] != 6 || o[1] > length) return;
 
 
-       if (!session[s].ip)
-       {
-               LOG(3, s, t, "Waiting on radius reply\n");
-               return;                 // have to wait on RADIUS reply
-       }
-       // form a config reply quoting the IP in the session
-       {
-               uint8_t b[MAXCONTROL];
-               uint8_t *i, *q;
+                               addr = htonl(session[s].dns1);
+                               if (memcmp(o + 2, &addr, (sizeof addr)))
+                               {
+                                       q = ppp_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
+                                       if (!q) return;
+                               }
 
 
-               q = p + 4;
-               i = p + l;
-               while (q < i && q[1])
-               {
-                       if (*q != 0x81 && *q != 0x83 && *q != 3)
                                break;
                                break;
-                       q += q[1];
-               }
-               if (q < i)
-               {
-                       // reject
-                       uint16_t n = 4;
-                       i = p + l;
-                       if (!(q = makeppp(b, sizeof(b), p, l, t, s, PPPIPCP)))
-                               return;
-
-                       *q = ConfigRej;
-                       p += 4;
-                       while (p < i && p[1])
-                       {
-                               if (*p != 0x81 && *p != 0x83 && *p != 3)
+
+                       case 131: // secondary DNS
+                               if (o[1] != 6 || o[1] > length) return;
+
+                               addr = htonl(session[s].dns1);
+                               if (memcmp(o + 2, &addr, sizeof(addr)))
                                {
                                {
-                                       LOG(2, s, t, "IPCP reject %d\n", *p);
-                                       memcpy(q + n, p, p[1]);
-                                       n += p[1];
+                                       q = ppp_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
+                                       if (!q) return;
                                }
                                }
-                               p += p[1];
+
+                               break;
+
+                       default:
+                               LOG(2, s, t, "    Rejecting PPP IPCP Option type %d\n", *o);
+                               q = ppp_rej(s, b, sizeof(b), PPPIPCP, &response, q, p, o);
+                               if (!q) return;
                        }
                        }
-                       *(uint16_t *) (q + 2) = htons(n);
-                       LOG(4, s, t, "Sending ConfigRej\n");
-                       tunnelsend(b, n + (q - b), t); // send it
+
+                       length -= o[1];
+                       o += o[1];
+               }
+
+               if (response)
+               {
+                       l = q - response; // IPCP packet length
+                       *((uint16_t *) (response + 2)) = htons(l); // update header
+               }
+               else if (gotip)
+               {
+                       // Send packet back as ConfigAck
+                       response = makeppp(b, sizeof(b), p, l, t, s, PPPIPCP);
+                       if (!response) return;
+                       *response = ConfigAck;
                }
                else
                {
                }
                else
                {
-                       LOG(4, s, t, "Sending ConfigAck\n");
-                       *p = ConfigAck;
-                       if ((i = findppp(p, 0x81))) // Primary DNS address
-                       {
-                               if (*(uint32_t *) (i + 2) != htonl(session[s].dns1))
-                               {
-                                       *(uint32_t *) (i + 2) = htonl(session[s].dns1);
-                                       *p = ConfigNak;
-                                       LOG(5, s, t, "   DNS1 = %s\n",
-                                               fmtaddr(htonl(session[s].dns1), 0));
-                               }
-                       }
-                       if ((i = findppp(p, 0x83))) // Secondary DNS address (TBA, is it)
-                       {
-                               if (*(uint32_t *) (i + 2) != htonl(session[s].dns2))
-                               {
-                                       *(uint32_t *) (i + 2) = htonl(session[s].dns2);
-                                       *p = ConfigNak;
-                                       LOG(5, s, t, "   DNS2 = %s\n",
-                                               fmtaddr(htonl(session[s].dns2), 0));
-                               }
-                       }
-                       i = findppp(p, 3);              // IP address
-                       if (!i || i[1] != 6)
-                       {
-                               LOG(1, s, t, "No IP in IPCP request\n");
-                               STAT(tunnel_rx_errors);
-                               return ;
-                       }
-                       if (*(uint32_t *) (i + 2) != htonl(session[s].ip))
-                       {
-                               *(uint32_t *) (i + 2) = htonl(session[s].ip);
-                               *p = ConfigNak;
-                               LOG(4, s, t, " No, a ConfigNak, client is requesting IP - sending %s\n",
-                                               fmtaddr(htonl(session[s].ip), 0));
-                       }
-                       if (!(q = makeppp(b, sizeof(b), p, l, t, s, PPPIPCP)))
-                               return;
+                       LOG(1, s, t, "No IP in IPCP request\n");
+                       STAT(tunnel_rx_errors);
+                       return;
+               }
+
+               switch (session[s].ppp.ipcp)
+               {
+               case Closed:
+                       response = makeppp(b, sizeof(b), p, 2, t, s, PPPIPCP);
+                       if (!response) return;
+                       *response = TerminateAck;
+                       *((uint16_t *) (response + 2)) = htons(l = 4);
+                       break;
+
+               case Stopped:
+                       initialise_restart_count(s, ipcp);
+                       sendipcp(s, t);
+                       if (*response == ConfigAck)
+                               change_state(s, ipcp, AckSent);
+                       else
+                               change_state(s, ipcp, RequestSent);
+
+                       break;
 
 
-                       tunnelsend(b, l + (q - b), t); // send it
+               case RequestSent:
+                       if (*response == ConfigAck)
+                               change_state(s, ipcp, AckSent);
+
+                       break;
+
+               case AckReceived:
+                       if (*response == ConfigAck)
+                               ipcp_open(t, s);
+
+                       break;
+
+               case Opened:
+                       initialise_restart_count(s, ipcp);
+                       sendipcp(s, t);
+                       /* fallthrough */
+
+               case AckSent:
+                       if (*response == ConfigAck)
+                               change_state(s, ipcp, AckSent);
+                       else
+                               change_state(s, ipcp, RequestSent);
+
+                       break;
+
+               default:
+                       LOG(3, s, t, "IPCP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.ipcp));
+                       return;
                }
                }
+
+               LOG(3, s, t, "IPCP: Sending %s\n", ppp_code(*response));
+               tunnelsend(b, l + (response - b), t);
+       }
+       else if (*p == TerminateReq)
+       {
+               LOG(3, s, t, "IPCP: Received TerminateReq.  Sending TerminateAck\n");
+               *p = TerminateAck;
+               q = makeppp(b, sizeof(b),  p, l, t, s, PPPIPCP);
+               if (!q) return;
+               tunnelsend(b, l + (q - b), t);
+               change_state(s, ipcp, Stopped);
        }
        }
+       else
+       {
+               int code = *p;
+               int mru = session[s].mru;
+               if (!mru)
+                       mru = DEFAULT_MRU;
+
+               if (l > mru) l = mru;
+
+               *p = CodeRej;
+               q = makeppp(b, sizeof(b), p, l, t, s, PPPIPCP);
+               if (!q) return;
+
+               LOG(3, s, t, "Unexpected IPCP code %s\n", ppp_code(code));
+               tunnelsend(b, l + (q - b), t);
+       }
+}
+
+static void ipv6cp_open(tunnelidt t, sessionidt s)
+{
+       LOG(3, s, t, "IPV6CP Acked\n");
+
+       change_state(s, ipv6cp, Opened);
+       if (session[s].ipv6prefixlen)
+               route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 1);
+
+       // Send an initial RA (TODO: Should we send these regularly?)
+       send_ipv6_ra(t, s, NULL);
 }
 
 // Process IPV6CP messages
 void processipv6cp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
 {
 }
 
 // Process IPV6CP messages
 void processipv6cp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
 {
+       uint8_t b[MAXCONTROL];
+       uint8_t *q = 0;
+       uint16_t hl;
 
        CSTAT(processipv6cp);
 
 
        CSTAT(processipv6cp);
 
@@ -855,112 +1119,195 @@ void processipv6cp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                STAT(tunnel_rx_errors);
                return ;
        }
                STAT(tunnel_rx_errors);
                return ;
        }
-       if (*p == ConfigAck)
-       {
-               // happy with our IPV6CP
-               session[s].flags |= SF_IPV6CP_ACKED;
 
 
-               LOG(3, s, t, "IPV6CP Acked, IPv6 is now active\n");
-               // Add a routed block if configured.
-               if (session[s].ipv6prefixlen)
-               {
-                       route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 1);
-                       session[s].flags |= SF_IPV6_ROUTED;
-               }
-
-               // Send an initial RA (TODO: Should we send these regularly?)
-               send_ipv6_ra(t, s, NULL);
-               return;
-       }
-       if (*p != ConfigReq)
+       if ((hl = ntohs(*(uint16_t *) (p + 2))) > l)
        {
        {
-               LOG(1, s, t, "Unexpected IPV6CP code %d\n", *p);
+               LOG(1, s, t, "Length mismatch IPV6CP %u/%u\n", hl, l);
                STAT(tunnel_rx_errors);
                STAT(tunnel_rx_errors);
+               return ;
+       }
+       l = hl;
+
+       if (session[s].ppp.phase < Network)
+       {
+               LOG(2, s, t, "IPV6CP %s ignored in %s phase\n", ppp_code(*p), ppp_phase(session[s].ppp.phase));
                return;
        }
 
                return;
        }
 
-       LOG(4, s, t, "IPV6CP ConfigReq received\n");
-       if (ntohs(*(uint16_t *) (p + 2)) > l)
+       if (!config->ipv6_prefix.s6_addr[0])
        {
        {
-               LOG(1, s, t, "Length mismatch IPV6CP %d/%d\n", ntohs(*(uint16_t *) (p + 2)), l);
-               STAT(tunnel_rx_errors);
-               return ;
+               LOG(2, s, t, "IPV6CP %s rejected (not configured)\n", ppp_code(*p));
+               *p = ProtocolRej;
+               q = makeppp(b, sizeof(b),  p, l, t, s, PPPIPV6CP);
+               if (!q) return;
+               tunnelsend(b, l + (q - b), t);
+               return;
        }
        }
+
        if (!session[s].ip)
        {
        if (!session[s].ip)
        {
-               LOG(3, s, t, "Waiting on radius reply\n");
-               return;                 // have to wait on RADIUS reply
+               LOG(3, s, t, "IPV6CP: no IPv4 address (IPCP in state %s)\n", ppp_state(session[s].ppp.ipcp));
+               return; // need IPCP to complete...
        }
        }
-       // form a config reply quoting the IP in the session
-       {
-               uint8_t b[MAXCONTROL];
-               uint8_t *i,
-               *q;
 
 
-               l = ntohs(*(uint16_t *) (p + 2)); // We must use length from IPV6CP len field
-               q = p + 4;
-               i = p + l;
-               while (q < i && q[1])
+       if (*p == ConfigAck)
+       {
+               switch (session[s].ppp.ipv6cp)
                {
                {
-                       if (*q != 1)
-                               break;
-                       q += q[1];
+               case RequestSent:
+                       initialise_restart_count(s, ipv6cp);
+                       change_state(s, ipv6cp, AckReceived);
+                       break;
+
+               case AckReceived:
+               case Opened:
+                       LOG(3, s, t, "IPV6CP: ConfigAck in state %s?  Sending ConfigReq\n", ppp_state(session[s].ppp.ipv6cp));
+                       sendipv6cp(s, t);
+                       change_state(s, ipv6cp, RequestSent);
+                       break;
+
+               case AckSent:
+                       ipv6cp_open(t, s);
+                       break;
+
+               default:
+                       LOG(3, s, t, "IPV6CP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.ipv6cp));
                }
                }
-               if (q < i)
+       }
+       else if (*p == ConfigReq)
+       {
+               uint8_t *response = 0;
+               uint8_t *o = p + 4;
+               int length = l - 4;
+               int gotip = 0;
+               uint8_t ident[8];
+
+               LOG(4, s, t, "IPV6CP ConfigReq received\n");
+
+               while (length > 2)
                {
                {
-                       // reject
-                       uint16_t n = 4;
-                       i = p + l;
-                       if (!(q = makeppp(b, sizeof(b), p, l, t, s, PPPIPV6CP)))
-                       {
-                               LOG(2, s, t, "Failed to send IPV6CP ConfigRej\n");
-                               return;
-                       }
-                       *q = ConfigRej;
-                       p += 4;
-                       while (p < i && p[1])
+                       switch (*o)
                        {
                        {
-                               if (*p != 1)
+                       case 1: // interface identifier
+                               gotip++; // seen address
+                               if (o[1] != 10 || o[1] > length) return;
+
+                               *(uint32_t *) ident = htonl(session[s].ip);
+                               *(uint32_t *) (ident + 4) = 0;
+
+                               if (memcmp(o + 2, ident, sizeof(ident)))
                                {
                                {
-                                       LOG(2, s, t, "IPV6CP reject %d\n", *p);
-                                       memcpy(q + n, p, p[1]);
-                                       n += p[1];
+                                       q = ppp_nak(s, b, sizeof(b), PPPIPV6CP, &response, q, p, o, ident, sizeof(ident));
+                                       if (!q) return;
                                }
                                }
-                               p += p[1];
+
+                               break;
+
+                       default:
+                               LOG(2, s, t, "    Rejecting PPP IPV6CP Option type %d\n", *o);
+                               q = ppp_rej(s, b, sizeof(b), PPPIPV6CP, &response, q, p, o);
+                               if (!q) return;
                        }
                        }
-                       *(uint16_t *) (q + 2) = htons(n);
-                       LOG(4, s, t, "Sending ConfigRej\n");
-                       tunnelsend(b, n + (q - b), t); // send it
+
+                       length -= o[1];
+                       o += o[1];
+               }
+
+               if (response)
+               {
+                       l = q - response; // IPV6CP packet length
+                       *((uint16_t *) (response + 2)) = htons(l); // update header
+               }
+               else if (gotip)
+               {
+                       // Send packet back as ConfigAck
+                       response = makeppp(b, sizeof(b), p, l, t, s, PPPIPV6CP);
+                       if (!response) return;
+                       *response = ConfigAck;
                }
                else
                {
                }
                else
                {
-                       LOG(4, s, t, "Sending ConfigAck\n");
-                       *p = ConfigAck;
-                       i = findppp(p, 1);              // IP address
-                       if (!i || i[1] != 10)
-                       {
-                               LOG(1, s, t, "No IP in IPV6CP request\n");
-                               STAT(tunnel_rx_errors);
-                               return ;
-                       }
-                       if ((*(uint32_t *) (i + 2) != htonl(session[s].ip)) || 
-                                       (*(uint32_t *) (i + 6) != 0))
-                       {
-                               *(uint32_t *) (i + 2) = htonl(session[s].ip);
-                               *(uint32_t *) (i + 6) = 0;
-                               *p = ConfigNak;
-                               LOG(4, s, t,
-                                       " No, a ConfigNak, client is "
-                                       "requesting IP - sending %s\n",
-                                       fmtaddr(htonl(session[s].ip), 0));
-                       }
-                       if (!(q = makeppp(b, sizeof(b), p, l, t, s, PPPIPV6CP)))
-                       {
-                               LOG(2, s, t, " Failed to send IPV6CP packet.\n");
-                               return;
-                       }
-                       tunnelsend(b, l + (q - b), t); // send it
+                       LOG(1, s, t, "No interface identifier in IPV6CP request\n");
+                       STAT(tunnel_rx_errors);
+                       return;
+               }
+
+               switch (session[s].ppp.ipv6cp)
+               {
+               case Closed:
+                       response = makeppp(b, sizeof(b), p, 2, t, s, PPPIPV6CP);
+                       if (!response) return;
+                       *response = TerminateAck;
+                       *((uint16_t *) (response + 2)) = htons(l = 4);
+                       break;
+
+               case Stopped:
+                       initialise_restart_count(s, ipv6cp);
+                       sendipv6cp(s, t);
+                       if (*response == ConfigAck)
+                               change_state(s, ipv6cp, AckSent);
+                       else
+                               change_state(s, ipv6cp, RequestSent);
+
+                       break;
+
+               case RequestSent:
+                       if (*response == ConfigAck)
+                               change_state(s, ipv6cp, AckSent);
+
+                       break;
+
+               case AckReceived:
+                       if (*response == ConfigAck)
+                               ipv6cp_open(t, s);
+
+                       break;
+
+               case Opened:
+                       initialise_restart_count(s, ipv6cp);
+                       sendipv6cp(s, t);
+                       /* fallthrough */
+
+               case AckSent:
+                       if (*response == ConfigAck)
+                               change_state(s, ipv6cp, AckSent);
+                       else
+                               change_state(s, ipv6cp, RequestSent);
+
+                       break;
+
+               default:
+                       LOG(3, s, t, "IPV6CP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.ipv6cp));
+                       return;
                }
                }
+
+               LOG(3, s, t, "IPV6CP: Sending %s\n", ppp_code(*response));
+               tunnelsend(b, l + (response - b), t);
+       }
+       else if (*p == TerminateReq)
+       {
+               LOG(3, s, t, "IPV6CP: Received TerminateReq.  Sending TerminateAck\n");
+               *p = TerminateAck;
+               q = makeppp(b, sizeof(b),  p, l, t, s, PPPIPV6CP);
+               if (!q) return;
+               tunnelsend(b, l + (q - b), t);
+               change_state(s, ipv6cp, Stopped);
+       }
+       else
+       {
+               int code = *p;
+               int mru = session[s].mru;
+               if (!mru)
+                       mru = DEFAULT_MRU;
+
+               if (l > mru) l = mru;
+
+               *p = CodeRej;
+               q = makeppp(b, sizeof(b), p, l, t, s, PPPIPV6CP);
+               if (!q) return;
+
+               LOG(3, s, t, "Unexpected IPV6CP code %s\n", ppp_code(code));
+               tunnelsend(b, l + (q - b), t);
        }
 }
 
        }
 }
 
@@ -985,6 +1332,9 @@ void processipin(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                return ;
        }
 
                return ;
        }
 
+       if (session[s].ppp.phase != Network || session[s].ppp.ipcp != Opened)
+               return;
+
        // no spoof (do sessionbyip to handled statically routed subnets)
        if (ip != session[s].ip && sessionbyip(htonl(ip)) != s)
        {
        // no spoof (do sessionbyip to handled statically routed subnets)
        if (ip != session[s].ip && sessionbyip(htonl(ip)) != s)
        {
@@ -1070,6 +1420,9 @@ void processipv6in(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
                return ;
        }
 
                return ;
        }
 
+       if (session[s].ppp.phase != Network || session[s].ppp.ipv6cp != Opened)
+               return;
+
        // no spoof
        if (ipv4 != session[s].ip && memcmp(&config->ipv6_prefix, &ip, 8) && sessionbyipv6(ip) != s)
        {
        // no spoof
        if (ipv4 != session[s].ip && memcmp(&config->ipv6_prefix, &ip, 8) && sessionbyipv6(ip) != s)
        {
@@ -1190,46 +1543,131 @@ void processccp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l)
        CSTAT(processccp);
 
        LOG_HEX(5, "CCP", p, l);
        CSTAT(processccp);
 
        LOG_HEX(5, "CCP", p, l);
-       switch (l > 1 ? *p : 0)
+
+       if (session[s].ppp.phase < Network)
        {
        {
-       case ConfigAck:
-               session[s].flags |= SF_CCP_ACKED;
+               LOG(2, s, t, "CCP %s ignored in %s phase\n", ppp_code(*p), ppp_phase(session[s].ppp.phase));
                return;
                return;
+       }
 
 
-       case ConfigReq:
-               if (l < 6) // accept no compression
+       if (l < 1)
+       {
+               LOG(1, s, t, "Short CCP packet\n");
+               STAT(tunnel_rx_errors);
+       }
+
+       if (*p == ConfigAck)
+       {
+               switch (session[s].ppp.ccp)
                {
                {
-                       *p = ConfigAck;
+               case RequestSent:
+                       initialise_restart_count(s, ccp);
+                       change_state(s, ccp, AckReceived);
+                       break;
+
+               case AckReceived:
+               case Opened:
+                       LOG(3, s, t, "CCP: ConfigAck in state %s?  Sending ConfigReq\n", ppp_state(session[s].ppp.ccp));
+                       sendccp(s, t);
+                       change_state(s, ccp, RequestSent);
                        break;
                        break;
+
+               case AckSent:
+                       LOG(3, s, t, "CCP Acked\n");
+                       change_state(s, ccp, Opened);
+                       break;
+
+               default:
+                       LOG(3, s, t, "CCP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.ccp));
                }
                }
+       }
+       else if (*p == ConfigReq)
+       {
+               if (l < 6) // accept no compression
+                       *p = ConfigAck;
+               else // compression requested--reject
+                       *p = ConfigRej;
 
 
-               // compression requested--reject
-               *p = ConfigRej;
+               q = makeppp(b, sizeof(b), p, l, t, s, PPPCCP);
+               if (!q) return;
 
 
-               // send CCP request for no compression for our end if not negotiated
-               if (!(session[s].flags & SF_CCP_ACKED))
-                       initccp(t, s);
+               switch (session[s].ppp.ccp)
+               {
+               case Closed:
+                       q = makeppp(b, sizeof(b), p, 2, t, s, PPPCCP);
+                       if (!q) return;
+                       *q = TerminateAck;
+                       *((uint16_t *) (q + 2)) = htons(l = 4);
+                       break;
 
 
-               break;
+               case Stopped:
+                       initialise_restart_count(s, ccp);
+                       sendccp(s, t);
+                       if (*q == ConfigAck)
+                               change_state(s, ccp, AckSent);
+                       else
+                               change_state(s, ccp, RequestSent);
 
 
-       case TerminateReq:
-               *p = TerminateAck;
-               break;
+                       break;
 
 
-       default:
-               if (l > 1)
-                       LOG(1, s, t, "Unexpected CCP request code %d\n", *p);
-               else
-                       LOG(1, s, t, "Short CCP packet\n");
+               case RequestSent:
+                       if (*q == ConfigAck)
+                               change_state(s, ccp, AckSent);
 
 
-               STAT(tunnel_rx_errors);
-               return;
+                       break;
+
+               case AckReceived:
+                       if (*q == ConfigAck)
+                               change_state(s, ccp, Opened);
+
+                       break;
+
+               case Opened:
+                       initialise_restart_count(s, ccp);
+                       sendccp(s, t);
+                       /* fallthrough */
+
+               case AckSent:
+                       if (*q == ConfigAck)
+                               change_state(s, ccp, AckSent);
+                       else
+                               change_state(s, ccp, RequestSent);
+
+                       break;
+
+               default:
+                       LOG(3, s, t, "CCP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.ccp));
+                       return;
+               }
+
+               LOG(3, s, t, "CCP: Sending %s\n", ppp_code(*q));
+               tunnelsend(b, l + (q - b), t);
        }
        }
+       else if (*p == TerminateReq)
+       {
+               LOG(3, s, t, "CCP: Received TerminateReq.  Sending TerminateAck\n");
+               *p = TerminateAck;
+               q = makeppp(b, sizeof(b),  p, l, t, s, PPPCCP);
+               if (!q) return;
+               tunnelsend(b, l + (q - b), t);
+               change_state(s, ccp, Stopped);
+       }
+       else
+       {
+               int code = *p;
+               int mru = session[s].mru;
+               if (!mru)
+                       mru = DEFAULT_MRU;
 
 
-       if (!(q = makeppp(b, sizeof(b), p, l, t, s, PPPCCP)))
-               return;
+               if (l > mru) l = mru;
+
+               *p = CodeRej;
+               q = makeppp(b, sizeof(b), p, l, t, s, PPPCCP);
+               if (!q) return;
 
 
-       tunnelsend(b, l + (q - b), t); // send it
+               LOG(3, s, t, "Unexpected CCP code %s\n", ppp_code(code));
+               tunnelsend(b, l + (q - b), t);
+       }
 }
 
 // send a CHAP challenge
 }
 
 // send a CHAP challenge
@@ -1270,7 +1708,7 @@ void sendchap(tunnelidt t, sessionidt s)
        q[1] = radius[r].id;                    // ID
        q[4] = 16;                              // value size (size of challenge)
        memcpy(q + 5, radius[r].auth, 16);      // challenge
        q[1] = radius[r].id;                    // ID
        q[4] = 16;                              // value size (size of challenge)
        memcpy(q + 5, radius[r].auth, 16);      // challenge
-       strcpy(q + 21, hostname);               // our name
+       strcpy((char *) q + 21, hostname);      // our name
        *(uint16_t *) (q + 2) = htons(strlen(hostname) + 21); // length
        tunnelsend(b, strlen(hostname) + 21 + (q - b), t); // send it
 }
        *(uint16_t *) (q + 2) = htons(strlen(hostname) + 21); // length
        tunnelsend(b, strlen(hostname) + 21 + (q - b), t); // send it
 }
@@ -1319,21 +1757,22 @@ uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, tunnelidt t, sessionid
        return b;
 }
 
        return b;
 }
 
-static uint8_t *add_lcp_auth(uint8_t *b, int size, int authtype)
+static int add_lcp_auth(uint8_t *b, int size, int authtype)
 {
 {
+       int len = 0;
        if ((authtype == AUTHCHAP && size < 5) || size < 4)
                return 0;
 
        *b++ = 3; // Authentication-Protocol
        if (authtype == AUTHCHAP)
        {
        if ((authtype == AUTHCHAP && size < 5) || size < 4)
                return 0;
 
        *b++ = 3; // Authentication-Protocol
        if (authtype == AUTHCHAP)
        {
-               *b++ = 5; // length
+               len = *b++ = 5; // length
                *(uint16_t *) b = htons(PPPCHAP); b += 2;
                *b++ = 5; // MD5
        }
        else if (authtype == AUTHPAP)
        {
                *(uint16_t *) b = htons(PPPCHAP); b += 2;
                *b++ = 5; // MD5
        }
        else if (authtype == AUTHPAP)
        {
-               *b++ = 4; // length
+               len = *b++ = 4; // length
                *(uint16_t *) b = htons(PPPPAP); b += 2;
        }
        else
                *(uint16_t *) b = htons(PPPPAP); b += 2;
        }
        else
@@ -1341,19 +1780,20 @@ static uint8_t *add_lcp_auth(uint8_t *b, int size, int authtype)
                LOG(0, 0, 0, "add_lcp_auth called with unsupported auth type %d\n", authtype);
        }
 
                LOG(0, 0, 0, "add_lcp_auth called with unsupported auth type %d\n", authtype);
        }
 
-       return b;
+       return len;
 }
 
 // Send initial LCP ConfigReq for MRU, authentication type and magic no
 void sendlcp(tunnelidt t, sessionidt s, int authtype)
 {
 }
 
 // Send initial LCP ConfigReq for MRU, authentication type and magic no
 void sendlcp(tunnelidt t, sessionidt s, int authtype)
 {
-       char b[500], *q, *l;
+       uint8_t b[500], *q, *l;
 
        if (!(q = makeppp(b, sizeof(b), NULL, 0, t, s, PPPLCP)))
                return;
 
 
        if (!(q = makeppp(b, sizeof(b), NULL, 0, t, s, PPPLCP)))
                return;
 
-       LOG(4, s, t, "Sending LCP ConfigReq for %s\n",
-           authtype == AUTHCHAP ? "CHAP" : "PAP");
+       LOG(4, s, t, "Sending LCP ConfigReq%s%s\n",
+           authtype ? " for " : "",
+           authtype ? (authtype == AUTHCHAP ? "CHAP" : "PAP") : "");
 
        if (!session[s].mru)
                session[s].mru = DEFAULT_MRU;
 
        if (!session[s].mru)
                session[s].mru = DEFAULT_MRU;
@@ -1367,7 +1807,8 @@ void sendlcp(tunnelidt t, sessionidt s, int authtype)
        *l++ = 1; *l++ = 4; // Maximum-Receive-Unit (length 4)
        *(uint16_t *) l = htons(session[s].mru); l += 2;
 
        *l++ = 1; *l++ = 4; // Maximum-Receive-Unit (length 4)
        *(uint16_t *) l = htons(session[s].mru); l += 2;
 
-       l = add_lcp_auth(l, sizeof(b) - (l - b), authtype);
+       if (authtype)
+               l += add_lcp_auth(l, sizeof(b) - (l - b), authtype);
 
        *l++ = 5; *l++ = 6; // Magic-Number (length 6)
        *(uint32_t *) l = htonl(session[s].magic);
 
        *l++ = 5; *l++ = 6; // Magic-Number (length 6)
        *(uint32_t *) l = htonl(session[s].magic);
@@ -1380,9 +1821,9 @@ void sendlcp(tunnelidt t, sessionidt s, int authtype)
 }
 
 // Send CCP request for no compression
 }
 
 // Send CCP request for no compression
-static void initccp(tunnelidt t, sessionidt s)
+void sendccp(tunnelidt t, sessionidt s)
 {
 {
-       char b[500], *q;
+       uint8_t b[500], *q;
 
        if (!(q = makeppp(b, sizeof(b), NULL, 0, t, s, PPPCCP)))
                return;
 
        if (!(q = makeppp(b, sizeof(b), NULL, 0, t, s, PPPCCP)))
                return;
index 690380f..b31c6f0 100644 (file)
--- a/radius.c
+++ b/radius.c
@@ -1,6 +1,6 @@
 // L2TPNS Radius Stuff
 
 // L2TPNS Radius Stuff
 
-char const *cvs_id_radius = "$Id: radius.c,v 1.36 2005-06-30 14:31:26 bodea Exp $";
+char const *cvs_id_radius = "$Id: radius.c,v 1.37 2005-07-31 10:04:10 bodea Exp $";
 
 #include <time.h>
 #include <stdio.h>
 
 #include <time.h>
 #include <stdio.h>
@@ -13,7 +13,7 @@ char const *cvs_id_radius = "$Id: radius.c,v 1.36 2005-06-30 14:31:26 bodea Exp
 #include <ctype.h>
 #include <netinet/in.h>
 #include <errno.h>
 #include <ctype.h>
 #include <netinet/in.h>
 #include <errno.h>
-#include "md5.h"
+#include <openssl/md5.h>
 #include "constants.h"
 #include "l2tpns.h"
 #include "plugin.h"
 #include "constants.h"
 #include "l2tpns.h"
 #include "plugin.h"
@@ -182,7 +182,7 @@ void radiussend(uint16_t r, uint8_t state)
        {
                *p = 1;                 // user name
                p[1] = strlen(session[s].user) + 2;
        {
                *p = 1;                 // user name
                p[1] = strlen(session[s].user) + 2;
-               strcpy(p + 2, session[s].user);
+               strcpy((char *) p + 2, session[s].user);
                p += p[1];
        }
        if (state == RADIUSAUTH)
                p += p[1];
        }
        if (state == RADIUSAUTH)
@@ -212,13 +212,13 @@ void radiussend(uint16_t r, uint8_t state)
                                while (p < pl)
                                {
                                        MD5_CTX ctx;
                                while (p < pl)
                                {
                                        MD5_CTX ctx;
-                                       MD5Init(&ctx);
-                                       MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret));
+                                       MD5_Init(&ctx);
+                                       MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret));
                                        if (p)
                                        if (p)
-                                               MD5Update(&ctx, pass + p - 16, 16);
+                                               MD5_Update(&ctx, pass + p - 16, 16);
                                        else
                                        else
-                                               MD5Update(&ctx, radius[r].auth, 16);
-                                       MD5Final(hash, &ctx);
+                                               MD5_Update(&ctx, radius[r].auth, 16);
+                                       MD5_Final(hash, &ctx);
                                        do
                                        {
                                                pass[p] ^= hash[p & 15];
                                        do
                                        {
                                                pass[p] ^= hash[p & 15];
@@ -244,7 +244,7 @@ void radiussend(uint16_t r, uint8_t state)
                {
                        *p = 44;        // session ID
                        p[1] = 18;
                {
                        *p = 44;        // session ID
                        p[1] = 18;
-                       sprintf(p + 2, "%08X%08X", session[s].unique_id, session[s].opened);
+                       sprintf((char *) p + 2, "%08X%08X", session[s].unique_id, session[s].opened);
                        p += p[1];
                        if (state == RADIUSSTART)
                        {                       // start
                        p += p[1];
                        if (state == RADIUSSTART)
                        {                       // start
@@ -299,7 +299,7 @@ void radiussend(uint16_t r, uint8_t state)
                                *p = 26;                                // vendor-specific
                                *(uint32_t *) (p + 2) = htonl(9);       // Cisco
                                p[6] = 1;                               // Cisco-AVPair
                                *p = 26;                                // vendor-specific
                                *(uint32_t *) (p + 2) = htonl(9);       // Cisco
                                p[6] = 1;                               // Cisco-AVPair
-                               p[7] = 2 + sprintf(p + 8, "intercept=%s:%d",
+                               p[7] = 2 + sprintf((char *) p + 8, "intercept=%s:%d",
                                        fmtaddr(session[s].snoop_ip, 0), session[s].snoop_port);
 
                                p[1] = p[7] + 6;
                                        fmtaddr(session[s].snoop_ip, 0), session[s].snoop_port);
 
                                p[1] = p[7] + 6;
@@ -325,21 +325,14 @@ void radiussend(uint16_t r, uint8_t state)
        {
                *p = 30;                // called
                p[1] = strlen(session[s].called) + 2;
        {
                *p = 30;                // called
                p[1] = strlen(session[s].called) + 2;
-               strcpy(p + 2, session[s].called);
-               p += p[1];
-       }
-       if (*radius[r].calling)
-       {
-               *p = 31;                // calling
-               p[1] = strlen(radius[r].calling) + 2;
-               strcpy(p + 2, radius[r].calling);
+               strcpy((char *) p + 2, session[s].called);
                p += p[1];
        }
        else if (*session[s].calling)
        {
                *p = 31;                // calling
                p[1] = strlen(session[s].calling) + 2;
                p += p[1];
        }
        else if (*session[s].calling)
        {
                *p = 31;                // calling
                p[1] = strlen(session[s].calling) + 2;
-               strcpy(p + 2, session[s].calling);
+               strcpy((char *) p + 2, session[s].calling);
                p += p[1];
        }
        // NAS-IP-Address
                p += p[1];
        }
        // NAS-IP-Address
@@ -353,15 +346,15 @@ void radiussend(uint16_t r, uint8_t state)
        if (state != RADIUSAUTH)
        {
            // Build auth for accounting packet
        if (state != RADIUSAUTH)
        {
            // Build auth for accounting packet
-           char z[16] = {0};
-           char hash[16] = {0};
+           uint8_t z[16] = {0};
+           uint8_t hash[16] = {0};
            MD5_CTX ctx;
            MD5_CTX ctx;
-           MD5Init(&ctx);
-           MD5Update(&ctx, b, 4);
-           MD5Update(&ctx, z, 16);
-           MD5Update(&ctx, b + 20, (p - b) - 20);
-           MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret));
-           MD5Final(hash, &ctx);
+           MD5_Init(&ctx);
+           MD5_Update(&ctx, b, 4);
+           MD5_Update(&ctx, z, 16);
+           MD5_Update(&ctx, b + 20, (p - b) - 20);
+           MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret));
+           MD5_Final(hash, &ctx);
            memcpy(b + 4, hash, 16);
            memcpy(radius[r].auth, hash, 16);
        }
            memcpy(b + 4, hash, 16);
            memcpy(radius[r].auth, hash, 16);
        }
@@ -381,9 +374,9 @@ void radiussend(uint16_t r, uint8_t state)
 
 static void handle_avpair(sessionidt s, uint8_t *avp, int len)
 {
 
 static void handle_avpair(sessionidt s, uint8_t *avp, int len)
 {
-       char *key = avp;
-       char *value = memchr(avp, '=', len);
-       char tmp[2048] = "";
+       uint8_t *key = avp;
+       uint8_t *value = memchr(avp, '=', len);
+       uint8_t tmp[2048] = "";
 
        if (value)
        {
 
        if (value)
        {
@@ -415,7 +408,7 @@ static void handle_avpair(sessionidt s, uint8_t *avp, int len)
        
        // Run hooks
        {
        
        // Run hooks
        {
-               struct param_radius_response p = { &tunnel[session[s].tunnel], &session[s], key, value };
+               struct param_radius_response p = { &tunnel[session[s].tunnel], &session[s], (char *) key, (char *) value };
                run_plugins(PLUGIN_RADIUS_RESPONSE, &p);
        }
 }
                run_plugins(PLUGIN_RADIUS_RESPONSE, &p);
        }
 }
@@ -463,12 +456,12 @@ void processrad(uint8_t *buf, int len, char socket_index)
                return;
        }
        t = session[s].tunnel;
                return;
        }
        t = session[s].tunnel;
-       MD5Init(&ctx);
-       MD5Update(&ctx, buf, 4);
-       MD5Update(&ctx, radius[r].auth, 16);
-       MD5Update(&ctx, buf + 20, len - 20);
-       MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret));
-       MD5Final(hash, &ctx);
+       MD5_Init(&ctx);
+       MD5_Update(&ctx, buf, 4);
+       MD5_Update(&ctx, radius[r].auth, 16);
+       MD5_Update(&ctx, buf + 20, len - 20);
+       MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret));
+       MD5_Final(hash, &ctx);
        do {
                if (memcmp(hash, buf + 4, 16))
                {
        do {
                if (memcmp(hash, buf + 4, 16))
                {
@@ -617,7 +610,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
                                        else if (*p == 11)
                                        {
                                                // Filter-Id
                                        else if (*p == 11)
                                        {
                                                // Filter-Id
-                                               char *filter = p + 2;
+                                               char *filter = (char *) p + 2;
                                                int l = p[1] - 2;
                                                char *suffix;
                                                int f;
                                                int l = p[1] - 2;
                                                char *suffix;
                                                int f;
@@ -680,10 +673,10 @@ void processrad(uint8_t *buf, int len, char socket_index)
                                                int prefixlen;
                                                uint8_t *n = p + 2;
                                                uint8_t *e = p + p[1];
                                                int prefixlen;
                                                uint8_t *n = p + 2;
                                                uint8_t *e = p + p[1];
-                                               uint8_t *m = strchr(n, '/');
+                                               uint8_t *m = memchr(n, '/', e - p);
 
                                                *m++ = 0;
 
                                                *m++ = 0;
-                                               inet_pton(AF_INET6, n, &r6);
+                                               inet_pton(AF_INET6, (char *) n, &r6);
 
                                                prefixlen = 0;
                                                while (m < e && isdigit(*m)) {
 
                                                prefixlen = 0;
                                                while (m < e && isdigit(*m)) {
@@ -710,12 +703,12 @@ void processrad(uint8_t *buf, int len, char socket_index)
 
                        if (!session[s].dns1 && config->default_dns1)
                        {
 
                        if (!session[s].dns1 && config->default_dns1)
                        {
-                               session[s].dns1 = htonl(config->default_dns1);
+                               session[s].dns1 = ntohl(config->default_dns1);
                                LOG(3, s, t, "   Sending dns1 = %s\n", fmtaddr(config->default_dns1, 0));
                        }
                        if (!session[s].dns2 && config->default_dns2)
                        {
                                LOG(3, s, t, "   Sending dns1 = %s\n", fmtaddr(config->default_dns1, 0));
                        }
                        if (!session[s].dns2 && config->default_dns2)
                        {
-                               session[s].dns2 = htonl(config->default_dns2);
+                               session[s].dns2 = ntohl(config->default_dns2);
                                LOG(3, s, t, "   Sending dns2 = %s\n", fmtaddr(config->default_dns2, 0));
                        }
 
                                LOG(3, s, t, "   Sending dns2 = %s\n", fmtaddr(config->default_dns2, 0));
                        }
 
@@ -750,20 +743,11 @@ void radiusretry(uint16_t r)
                case RADIUSCHAP:        // sending CHAP down PPP
                        sendchap(t, s);
                        break;
                case RADIUSCHAP:        // sending CHAP down PPP
                        sendchap(t, s);
                        break;
-               case RADIUSIPCP:
-                       sendipcp(t, s); // send IPCP
-                       break;
                case RADIUSAUTH:        // sending auth to RADIUS server
                case RADIUSAUTH:        // sending auth to RADIUS server
-                       radiussend(r, RADIUSAUTH);
-                       break;
                case RADIUSSTART:       // sending start accounting to RADIUS server
                case RADIUSSTART:       // sending start accounting to RADIUS server
-                       radiussend(r, RADIUSSTART);
-                       break;
                case RADIUSSTOP:        // sending stop accounting to RADIUS server
                case RADIUSSTOP:        // sending stop accounting to RADIUS server
-                       radiussend(r, RADIUSSTOP);
-                       break;
                case RADIUSINTERIM:     // sending interim accounting to RADIUS server
                case RADIUSINTERIM:     // sending interim accounting to RADIUS server
-                       radiussend(r, RADIUSINTERIM);
+                       radiussend(r, radius[r].state);
                        break;
                default:
                case RADIUSNULL:        // Not in use
                        break;
                default:
                case RADIUSNULL:        // Not in use
@@ -832,10 +816,10 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
        i = strlen(config->radiussecret);
        if (i > 16) i = 16;
 
        i = strlen(config->radiussecret);
        if (i > 16) i = 16;
 
-       MD5Init(&ctx);
-       MD5Update(&ctx, buf, len);
-       MD5Update(&ctx, buf, config->radiussecret, i);
-       MD5Final(hash, &ctx);
+       MD5_Init(&ctx);
+       MD5_Update(&ctx, buf, len);
+       MD5_Update(&ctx, config->radiussecret, i);
+       MD5_Final(hash, &ctx);
        if (memcmp(hash, vector, 16) != 0)
        {
                LOG(1, 0, 0, "Incorrect vector in DAE request (wrong secret in radius config?)\n");
        if (memcmp(hash, vector, 16) != 0)
        {
                LOG(1, 0, 0, "Incorrect vector in DAE request (wrong secret in radius config?)\n");
@@ -903,7 +887,7 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
                        }
 
                        len = p - packet;
                        }
 
                        len = p - packet;
-                       i = find_filter(packet, len);
+                       i = find_filter((char *) packet, len);
                        if (i < 0 || !*ip_filters[i].name)
                        {
                                error = 404;
                        if (i < 0 || !*ip_filters[i].name)
                        {
                                error = 404;
@@ -1063,10 +1047,10 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
        i = strlen(config->radiussecret);
        if (i > 16) i = 16;
 
        i = strlen(config->radiussecret);
        if (i > 16) i = 16;
 
-       MD5Init(&ctx);
-       MD5Update(&ctx, buf, len);
-       MD5Update(&ctx, config->radiussecret, i);
-       MD5Final(hash, &ctx);
+       MD5_Init(&ctx);
+       MD5_Update(&ctx, buf, len);
+       MD5_Update(&ctx, config->radiussecret, i);
+       MD5_Final(hash, &ctx);
        memcpy(buf + 4, hash, 16);
 
        LOG(3, 0, 0, "Sending DAE %s, id=%d\n", radius_code(r_code), r_id);
        memcpy(buf + 4, hash, 16);
 
        LOG(3, 0, 0, "Sending DAE %s, id=%d\n", radius_code(r_code), r_id);
diff --git a/tbf.c b/tbf.c
index 091e52d..9b4993d 100644 (file)
--- a/tbf.c
+++ b/tbf.c
@@ -1,6 +1,6 @@
 // L2TPNS: token bucket filters
 
 // L2TPNS: token bucket filters
 
-char const *cvs_id_tbf = "$Id: tbf.c,v 1.12 2005-05-02 09:55:04 bodea Exp $";
+char const *cvs_id_tbf = "$Id: tbf.c,v 1.13 2005-07-31 10:04:10 bodea Exp $";
 
 #include <string.h>
 #include "l2tpns.h"
 
 #include <string.h>
 #include "l2tpns.h"
@@ -159,10 +159,10 @@ void fsck_tbfs(void)
 // If we can send it right away, we do. Else we
 // try and queue it to send later. Else we drop it.
 //
 // If we can send it right away, we do. Else we
 // try and queue it to send later. Else we drop it.
 //
-int tbf_queue_packet(int tbf_id, char * data, int size)
+int tbf_queue_packet(int tbf_id, uint8_t *data, int size)
 {
        int i;
 {
        int i;
-       tbft * f;
+       tbft *f;
 
        if (!filter_list)
                return -1;
 
        if (!filter_list)
                return -1;
diff --git a/tbf.h b/tbf.h
index 5c85c39..925e4f7 100644 (file)
--- a/tbf.h
+++ b/tbf.h
@@ -30,12 +30,12 @@ typedef struct {
        uint32_t        p_delayed;      // Total packets not sent immediately.
 
        int             sizes[TBF_MAX_QUEUE];
        uint32_t        p_delayed;      // Total packets not sent immediately.
 
        int             sizes[TBF_MAX_QUEUE];
-       char            packets[TBF_MAX_QUEUE][TBF_MAX_SIZE];
+       uint8_t         packets[TBF_MAX_QUEUE][TBF_MAX_SIZE];
 } tbft;
 
 void init_tbf(int num_tbfs);
 int tbf_run_timer(void);
 } tbft;
 
 void init_tbf(int num_tbfs);
 int tbf_run_timer(void);
-int tbf_queue_packet(int tbf_id, char * data, int size);
+int tbf_queue_packet(int tbf_id, uint8_t * data, int size);
 int new_tbf(int sid, int max_credit, int rate, void (*f)(sessionidt, uint8_t *, int));
 int free_tbf(int tid);
 void fsck_tbfs(void);
 int new_tbf(int sid, int max_credit, int rate, void (*f)(sessionidt, uint8_t *, int));
 int free_tbf(int tid);
 void fsck_tbfs(void);
index cc42db5..d0a8dc4 100644 (file)
@@ -19,7 +19,7 @@
 #include <fcntl.h>
 #include <sys/select.h>
 #include <signal.h>
 #include <fcntl.h>
 #include <sys/select.h>
 #include <signal.h>
-#include "../md5.h"
+#include <openssl/md5.h>
 
 extern char *optarg;
 extern int optind;
 
 extern char *optarg;
 extern int optind;
@@ -394,16 +394,16 @@ int main(int argc, char *argv[])
            for (int j = 0; j < pw_len; j += 16)
            {
                MD5_CTX ctx;
            for (int j = 0; j < pw_len; j += 16)
            {
                MD5_CTX ctx;
-               MD5Init(&ctx);
-               MD5Update(&ctx, secret, strlen(secret));
+               MD5_Init(&ctx);
+               MD5_Update(&ctx, secret, strlen(secret));
                if (j)
                if (j)
-                   MD5Update(&ctx, pass + j - 16, 16);
+                   MD5_Update(&ctx, pass + j - 16, 16);
                else
                    /* authenticator */
                else
                    /* authenticator */
-                   MD5Update(&ctx, u->request + 4, 16);
+                   MD5_Update(&ctx, u->request + 4, 16);
 
 
-               char digest[16];
-               MD5Final(digest, &ctx);
+               uint8_t digest[16];
+               MD5_Final(digest, &ctx);
 
                for (int k = 0; k < 16; k++)
                    pass[j + k] ^= digest[k];
 
                for (int k = 0; k < 16; k++)
                    pass[j + k] ^= digest[k];