port l2tpd fixes from changeset:2696 to trunk.
authorNicolas Thill <nico@openwrt.org>
Fri, 16 Dec 2005 12:00:19 +0000 (12:00 +0000)
committerNicolas Thill <nico@openwrt.org>
Fri, 16 Dec 2005 12:00:19 +0000 (12:00 +0000)
SVN-Revision: 2697

openwrt/package/l2tpd/Makefile
openwrt/package/l2tpd/files/l2tpd.conf [new file with mode: 0644]
openwrt/package/l2tpd/files/l2tpd.init [new file with mode: 0644]
openwrt/package/l2tpd/files/options.l2tpd [new file with mode: 0644]
openwrt/package/l2tpd/ipkg/l2tpd.conffiles [new file with mode: 0644]
openwrt/package/l2tpd/patches/01-debian-2.patch [new file with mode: 0644]
openwrt/package/l2tpd/patches/02-debian-2-pty-rev.patch [new file with mode: 0644]
openwrt/package/l2tpd/patches/03-jacco-pty.patch [new file with mode: 0644]
openwrt/package/l2tpd/patches/debian-2.patch [deleted file]

index ac80e0b09f4bcc809b022ab78db497f0fe73084c..0af0c09f452ba6ca7ffc5cc16597b64faf86eb80 100644 (file)
@@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk
 PKG_NAME:=l2tpd
 PKG_VERSION:=0.70pre
 PKG_UPSTREAM_VERSION:=0.70-pre20031121
-PKG_RELEASE:=1
+PKG_RELEASE:=2.1
 PKG_MD5SUM:=3f2707b6e16a8cb72e7bf64f574202fa
 
 PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/l/l2tpd
@@ -30,6 +30,12 @@ $(PKG_BUILD_DIR)/.built:
        touch $@
 
 $(IPKG_L2TPD):
+       install -d -m0755 $(IDIR_L2TPD)/etc/l2tpd
+       install -m0644 ./files/l2tpd.conf $(IDIR_L2TPD)/etc/l2tpd/
+       install -d -m0755 $(IDIR_L2TPD)/etc/ppp
+       install -m0644 ./files/options.l2tpd $(IDIR_L2TPD)/etc/ppp/
+       install -d -m0755 $(IDIR_L2TPD)/etc/init.d
+       install -m0755 ./files/l2tpd.init $(IDIR_L2TPD)/etc/init.d/l2tpd
        install -d -m0755 $(IDIR_L2TPD)/usr/sbin
        install -m0755 $(PKG_BUILD_DIR)/$(PKG_NAME) $(IDIR_L2TPD)/usr/sbin/
        $(RSTRIP) $(IDIR_L2TPD)
diff --git a/openwrt/package/l2tpd/files/l2tpd.conf b/openwrt/package/l2tpd/files/l2tpd.conf
new file mode 100644 (file)
index 0000000..2a9ba1c
--- /dev/null
@@ -0,0 +1,29 @@
+;
+; This is a minimal sample l2tpd configuration file for use
+; with L2TP over IPsec.
+;
+; The idea is to provide an L2TP daemon to which remote Windows L2TP/IPsec
+; clients connect. In this example, the internal (protected) network 
+; is 192.168.1.0/24.  A special IP range within this network is reserved
+; for the remote clients: 192.168.1.128/25
+; (i.e. 192.168.1.128 ... 192.168.1.254)
+;
+; The listen-addr parameter can be used if you want to bind the L2TP daemon
+; to a specific IP address instead of to all interfaces. For instance,
+; you could bind it to the interface of the internal LAN (e.g. 192.168.1.98
+; in the example below). Yet another IP address (local ip, e.g. 192.168.1.99)
+; will be used by l2tpd as its address on pppX interfaces.
+
+[global]
+; listen-addr = 192.168.1.98
+
+[lns default]
+ip range = 192.168.1.128-192.168.1.254
+local ip = 192.168.1.99
+require chap = yes
+refuse pap = yes
+require authentication = yes
+name = LinuxVPNserver
+ppp debug = yes
+pppoptfile = /etc/ppp/options.l2tpd
+length bit = yes
diff --git a/openwrt/package/l2tpd/files/l2tpd.init b/openwrt/package/l2tpd/files/l2tpd.init
new file mode 100644 (file)
index 0000000..f531757
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+BIN=l2tpd
+DEFAULT=/etc/default/$BIN
+RUN_D=/var/run
+PID_F=$RUN_D/$BIN.pid
+[ -f $DEFAULT ] && . $DEFAULT
+
+case $1 in
+ start)
+  $BIN $OPTIONS
+  ;;
+ stop)
+  [ -f $PID_F ] && kill $(cat $PID_F)
+  ;;
+ *)
+  echo "usage: $0 (start|stop)"
+  exit 1
+esac
+
+exit $?
diff --git a/openwrt/package/l2tpd/files/options.l2tpd b/openwrt/package/l2tpd/files/options.l2tpd
new file mode 100644 (file)
index 0000000..425a56e
--- /dev/null
@@ -0,0 +1,17 @@
+ipcp-accept-local
+ipcp-accept-remote
+ms-dns  192.168.1.1
+ms-dns  192.168.1.3
+ms-wins 192.168.1.2
+ms-wins 192.168.1.4
+noccp
+auth
+crtscts
+idle 1800
+mtu 1410
+mru 1410
+nodefaultroute
+debug
+lock
+proxyarp
+connect-delay 5000
diff --git a/openwrt/package/l2tpd/ipkg/l2tpd.conffiles b/openwrt/package/l2tpd/ipkg/l2tpd.conffiles
new file mode 100644 (file)
index 0000000..1607479
--- /dev/null
@@ -0,0 +1,2 @@
+/etc/l2tpd/l2tpd.conf
+/etc/ppp/options.l2tpd
diff --git a/openwrt/package/l2tpd/patches/01-debian-2.patch b/openwrt/package/l2tpd/patches/01-debian-2.patch
new file mode 100644 (file)
index 0000000..8a6e204
--- /dev/null
@@ -0,0 +1,3394 @@
+--- l2tpd-0.70-pre20031121.orig/Makefile
++++ l2tpd-0.70-pre20031121/Makefile
+@@ -28,7 +28,8 @@
+ # become runtime options) debugging flags
+ #
+ #DFLAGS= -g -O2 -DDEBUG_PPPD
+-DFLAGS= -g -O2 -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY
++#DFLAGS= -g -O2 -Wall -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY
++DFLAGS= -ggdb -Wall -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY
+ #
+ # Uncomment the next line for Linux
+ #
+@@ -58,7 +59,7 @@
+ FFLAGS= -DIP_ALLOCATION 
+-CFLAGS= $(DFLAGS) -Wall -DSANITY $(OSFLAGS) $(FFLAGS)
++CFLAGS= $(DFLAGS) -Wall -DSANITY $(OSFLAGS) $(FFLAGS) 
+ HDRS=l2tp.h avp.h misc.h control.h call.h scheduler.h file.h aaa.h md5.h
+ OBJS=l2tpd.o pty.o misc.o control.o avp.o call.o network.o avpsend.o scheduler.o file.o aaa.o md5.o
+ LIBS= $(OSLIB) # -lefence # efence for malloc checking
+--- l2tpd-0.70-pre20031121.orig/control.c
++++ l2tpd-0.70-pre20031121/control.c
+@@ -227,7 +227,7 @@
+             add_bearer_caps_avp (buf, t->ourbc);
+             /* FIXME:  Tie breaker */
+             add_firmware_avp (buf);
+-            add_hostname_avp (buf);
++            add_hostname_avp (buf, t);
+             add_vendor_avp (buf);
+             add_tunnelid_avp (buf, t->ourtid);
+             if (t->ourrws >= 0)
+@@ -346,7 +346,6 @@
+                      "%s: Peer did not specify assigned tunnel ID.  Closing.\n",
+                      __FUNCTION__);
+             set_error (c, VENDOR_ERROR, "Specify your assigned tunnel ID");
+-            c->needclose = -1;
+             return -EINVAL;
+         }
+         if (!(t->lns = get_lns (t)))
+@@ -356,7 +355,6 @@
+                      "%s: Denied connection to unauthorized peer %s\n",
+                      __FUNCTION__, IPADDY (t->peer.sin_addr));
+             set_error (c, VENDOR_ERROR, "No Authorization");
+-            c->needclose = -1;
+             return -EINVAL;
+         }
+         t->ourrws = t->lns->tun_rws;
+@@ -368,7 +366,6 @@
+                      "%s: Peer did not specify framing capability.  Closing.\n",
+                      __FUNCTION__);
+             set_error (c, VENDOR_ERROR, "Specify framing capability");
+-            c->needclose = -1;
+             return -EINVAL;
+         }
+         /* FIXME: Do we need to be sure they specified a version number?
+@@ -380,7 +377,6 @@
+          if (DEBUG) log(LOG_DEBUG,
+          "%s: Peer did not specify bearer capability.  Closing.\n",__FUNCTION__);
+          set_error(c, VENDOR_ERROR, "Specify bearer capability");
+-         c->needclose = -1;
+          return -EINVAL;
+          }  */
+         if ((!strlen (t->hostname)) && ((t->chal_us.state) || ((t->lns->challenge))))
+@@ -390,7 +386,6 @@
+                      "%s: Peer did not specify hostname.  Closing.\n",
+                      __FUNCTION__);
+             set_error (c, VENDOR_ERROR, "Specify your hostname");
+-            c->needclose = -1;
+             return -EINVAL;
+         }
+         y = tunnels.head;
+@@ -427,7 +422,7 @@
+         add_frame_caps_avp (buf, t->ourfc);
+         add_bearer_caps_avp (buf, t->ourbc);
+         add_firmware_avp (buf);
+-        add_hostname_avp (buf);
++        add_hostname_avp (buf, t);
+         add_vendor_avp (buf);
+         add_tunnelid_avp (buf, t->ourtid);
+         if (t->ourrws >= 0)
+@@ -481,7 +476,6 @@
+                      "%s: Peer did not specify framing capability.  Closing.\n",
+                      __FUNCTION__);
+             set_error (c, VENDOR_ERROR, "Specify framing capability");
+-            c->needclose = -1;
+             return -EINVAL;
+         }
+         /* FIXME: Do we need to be sure they specified a version number?
+@@ -493,7 +487,6 @@
+          if (DEBUG) log(LOG_DEBUG,
+          "%s: Peer did not specify bearer capability.  Closing.\n",__FUNCTION__);
+          set_error(c, VENDOR_ERROR, "Specify bearer capability");
+-         c->needclose = -1;
+          return -EINVAL;
+          } */
+         if ((!strlen (t->hostname)) && ((t->chal_them.state) || ((t->chal_us.state))))
+@@ -503,7 +496,6 @@
+                      "%s: Peer did not specify hostname.  Closing.\n",
+                      __FUNCTION__);
+             set_error (c, VENDOR_ERROR, "Specify your hostname");
+-            c->needclose = -1;
+             return -EINVAL;
+         }
+         if (t->tid <= 0)
+@@ -513,7 +505,6 @@
+                      "%s: Peer did not specify assigned tunnel ID.  Closing.\n",
+                      __FUNCTION__);
+             set_error (c, VENDOR_ERROR, "Specify your assigned tunnel ID");
+-            c->needclose = -1;
+             return -EINVAL;
+         }
+         if (t->chal_them.state)
+@@ -524,7 +515,6 @@
+                 set_error (c, VENDOR_ERROR, "No secret key on our side");
+                 log (LOG_WARN, "%s: No secret key for authenticating '%s'\n",
+                      __FUNCTION__, t->hostname);
+-                c->needclose = -1;
+                 return -EINVAL;
+             }
+             if (memcmp
+@@ -534,7 +524,6 @@
+                            "Invalid challenge authentication");
+                 log (LOG_DEBUG, "%s: Invalid authentication for host '%s'\n",
+                      __FUNCTION__, t->hostname);
+-                c->needclose = -1;
+                 return -EINVAL;
+             }
+         }
+@@ -546,7 +535,6 @@
+                 log (LOG_WARN, "%s: No secret for authenticating to '%s'\n",
+                      __FUNCTION__, t->hostname);
+                 set_error (c, VENDOR_ERROR, "No secret key on our end");
+-                c->needclose = -1;
+                 return -EINVAL;
+             };
+         }
+@@ -606,7 +594,6 @@
+                            "Invalid challenge authentication");
+                 log (LOG_DEBUG, "%s: Invalid authentication for host '%s'\n",
+                      __FUNCTION__, t->hostname);
+-                c->needclose = -1;
+                 return -EINVAL;
+             }
+         }
+@@ -1584,6 +1571,14 @@
+     wbuf[pos++] = e;
+     for (x = 0; x < buf->len; x++)
+     {
++              // we must at least still have 4 bytes left in the worst case scenario:
++              // 1 for a possible escape, 1 for the value and 1 to end the PPP stream.
++              if(pos >= (sizeof(wbuf) - 4)) {
++                      if(DEBUG)
++                              log(LOG_CRIT, "%s: rx packet is too big after PPP encoding (size %u, max is %u)\n", 
++                                                      __FUNCTION__, buf->len, MAX_RECV_SIZE);
++                      return -EINVAL;
++              }
+         e = *((char *) buf->start + x);
+         if ((e < 0x20) || (e == PPP_ESCAPE) || (e == PPP_FLAG))
+         {
+@@ -1592,7 +1587,6 @@
+             wbuf[pos++] = PPP_ESCAPE;
+         }
+         wbuf[pos++] = e;
+-
+     }
+     wbuf[pos++] = PPP_FLAG;
+     x = write (c->fd, wbuf, pos);
+--- l2tpd-0.70-pre20031121.orig/misc.h
++++ l2tpd-0.70-pre20031121/misc.h
+@@ -80,4 +80,11 @@
+ extern void safe_copy (char *, char *, int);
+ extern void opt_destroy (struct ppp_opts *);
+ extern struct ppp_opts *add_opt (struct ppp_opts *, char *, ...);
++extern u_int16_t get16(u_int8_t *);
++extern u_int32_t get32(u_int8_t *);
++extern u_int64_t get64(u_int8_t *);
++extern void set16(u_int8_t *, u_int16_t);
++extern void set32(u_int8_t *, u_int32_t);
++extern void set64(u_int8_t *, u_int64_t);
++
+ #endif
+--- l2tpd-0.70-pre20031121.orig/avp.h
++++ l2tpd-0.70-pre20031121/avp.h
+@@ -19,22 +19,35 @@
+ struct avp_hdr
+ {
+-    _u16 length;
+-    _u16 vendorid;
+-    _u16 attr;
++    u_int16_t length;
++    u_int16_t vendorid;
++    u_int16_t attr;
+ };
++#define AVP_F_MANDATORY       0x1
++#define AVP_F_FIXLEN  0x2
++#define AVP_F_ASCII           0x4
++
+ struct avp
+ {
+-    int num;                    /* Number of AVP */
+-    int m;                      /* Set M? */
+-    int (*handler) (struct tunnel *, struct call *, void *, int);
+-    /* This should handle the AVP
+-       taking a tunnel, call, the data,
+-       and the length of the AVP as
+-       parameters.  Should return 0
+-       upon success */
+-    char *description;          /* A name, for debugging */
++    u_int32_t         num;                            /* Number of AVP */
++    u_int32_t flags;
++      u_int32_t       sz;                                     /* expected avp payload size as
++                                                                       * (AVP_F_FIXLEN) ? (==) : (!>=)
++                                                                       * note: size checked is performed 
++                                                                       * after unhiding */
++      u_int8_t        allowed_states[8];      /* List of allowed message types for
++                                                                       * a particular avp. Fixed len for
++                                                                       * alignement issues. */
++
++    /* This should handle the AVP taking a tunnel, call, 
++       * the data, and the length of the AVP as parameters.  
++       * Should return 0 upon success */
++    int (*handle) (struct tunnel *, struct call *, void *, int);
++
++      /* This should handle avp specifics sanity checks */
++      int (*validate) (int, struct tunnel *, struct call *, void *, int);
++    char *description;                /* A name, for debugging */
+ };
+ extern int handle_avps (struct buffer *buf, struct tunnel *t, struct call *c);
+@@ -84,8 +97,56 @@
+ #define RESULT_CLEAR 1
+ #define RESULT_ERROR 2
+ #define RESULT_EXISTS 3
++
++/* avp id's */
++#define       MESSAGE_TYPE_AVP                0
++#define RESULT_CODE_AVP                       1
++#define PROTOCOL_VERSION_AVP  2
++#define       FRAMING_CAP_AVP                 3
++#define       BEARER_CAP_AVP                  4
++#define TIE_BREAKER_AVP                       5
++#define       FIRMWARE_REV_AVP                6
++#define       HOSTNAME_AVP                    7
++#define VENDOR_NAME_AVP                       8
++#define ASSIGNED_TUN_ID_AVP           9
++#define       RX_WIN_SIZE_AVP                 10
++#define       CHALLENGE_AVP                   11
++#define       CHALLENGE_RESP_AVP              12
++#define       CAUSE_ERROR_AVP                 13
++#define       ASSIGNED_SES_ID_AVP             14
++#define       SERIAL_NUMBER_AVP               15
++#define       MIN_BPS_AVP                             16
++#define       MAX_BPS_AVP                             17
++#define       BEARER_TYPE_AVP                 18
++#define       FRAMING_TYPE_AVP                19
++#define       PACKET_DELAY_AVP                20
++#define       CALLED_NUMBER_AVP               21
++#define CALLING_NUMBER_AVP            22
++#define       SUB_ADDRESS_AVP                 23
++#define       TX_CONNECT_SPEED_AVP    24
++#define       PHYS_CHAN_ID_AVP                25
++#define       INIT_RX_LCP_AVP                 26
++#define       LAST_TX_LCP_AVP                 27
++#define       LAST_RX_LCP_AVP                 28
++#define       PROXY_AUTH_TYPE_AVP             29
++#define       PROXY_AUTH_NAME_AVP             30
++#define       PROXY_AUTH_CHAL_AVP             31
++#define       PROXY_AUTH_ID_AVP               32
++#define       PROXY_AUTH_CHAL_RESP_AVP        33
++#define CALL_ERROR_AVP                        34
++#define       ACCM_AVP                                35
++#define RANDOM_VECTOR_AVP             36
++#define       PRIV_GROUP_ID_AVP               37
++#define       RX_CONNECT_SPEED_AVP    38
++#define       SEQ_REQUIRED_AVP                39
++#define AVP_MAX                               SEQ_REQUIRED_AVP
++
++extern int validate_msgtype_avp(int, struct tunnel *, struct call *, void *, int);
++extern int validate_gen_avp(int, struct tunnel *, struct call *, void *, int);
++
+ extern void encrypt_avp (struct buffer *, _u16, struct tunnel *);
+ extern int decrypt_avp (char *, struct tunnel *);
++
+ extern int message_type_avp (struct tunnel *, struct call *, void *, int);
+ extern int protocol_version_avp (struct tunnel *, struct call *, void *, int);
+ extern int framing_caps_avp (struct tunnel *, struct call *, void *, int);
+@@ -97,12 +158,12 @@
+ extern int receive_window_size_avp (struct tunnel *, struct call *, void *,
+                                     int);
+ extern int result_code_avp (struct tunnel *, struct call *, void *, int);
+-extern int assigned_call_avp (struct tunnel *, struct call *, void *, int);
++extern int assigned_session_avp (struct tunnel *, struct call *, void *, int);
+ extern int call_serno_avp (struct tunnel *, struct call *, void *, int);
+ extern int bearer_type_avp (struct tunnel *, struct call *, void *, int);
+ extern int call_physchan_avp (struct tunnel *, struct call *, void *, int);
+-extern int dialed_number_avp (struct tunnel *, struct call *, void *, int);
+-extern int dialing_number_avp (struct tunnel *, struct call *, void *, int);
++extern int called_number_avp (struct tunnel *, struct call *, void *, int);
++extern int calling_number_avp (struct tunnel *, struct call *, void *, int);
+ extern int sub_address_avp (struct tunnel *, struct call *, void *, int);
+ extern int frame_type_avp (struct tunnel *, struct call *, void *, int);
+ extern int rx_speed_avp (struct tunnel *, struct call *, void *, int);
+@@ -118,7 +179,7 @@
+ extern int add_avp_rws (struct buffer *, _u16);
+ extern int add_tunnelid_avp (struct buffer *, _u16);
+ extern int add_vendor_avp (struct buffer *);
+-extern int add_hostname_avp (struct buffer *);
++extern int add_hostname_avp (struct buffer *, struct tunnel*);
+ extern int add_firmware_avp (struct buffer *);
+ extern int add_bearer_caps_avp (struct buffer *buf, _u16 caps);
+ extern int add_frame_caps_avp (struct buffer *buf, _u16 caps);
+--- l2tpd-0.70-pre20031121.orig/network.c
++++ l2tpd-0.70-pre20031121/network.c
+@@ -214,6 +214,8 @@
+                 t->self->needclose = -1;
+             }
+         }
++              free(buf->rstart);
++              free(buf);
+     }
+     else
+     {
+@@ -371,7 +373,9 @@
+                 if (debug_network)
+                 {
+                     log (LOG_DEBUG, "%s: recv packet from %s, size = %d," \
+-"tunnel = %d, call = %d\n", __FUNCTION__, inet_ntoa (from.sin_addr), recvsize, tunnel, call);
++                                                                      "tunnel = %d, call = %d\n", __func__, 
++                                                                      inet_ntoa (from.sin_addr), recvsize, 
++                                                                      tunnel, call);
+                 }
+                 if (packet_dump)
+                 {
+--- l2tpd-0.70-pre20031121.orig/aaa.c
++++ l2tpd-0.70-pre20031121/aaa.c
+@@ -209,9 +209,11 @@
+                  __FUNCTION__, u, t, s);
+ #endif
+             strncpy (secret, s, size);
++                      fclose(f);
+             return -1;
+         }
+     }
++      fclose(f);
+     return 0;
+ }
+--- l2tpd-0.70-pre20031121.orig/l2tpd.c
++++ l2tpd-0.70-pre20031121/l2tpd.c
+@@ -266,6 +266,9 @@
+     /* erase pid file */
+       unlink (gconfig.pidfile);
++      /* erase control pipe */
++      unlink(CONTROL_PIPE);
++
+     exit (1);
+ }
+@@ -333,13 +336,17 @@
+         tcgetattr (c->fd, &ptyconf);
+         *(c->oldptyconf) = ptyconf;
+         ptyconf.c_cflag &= ~(ICANON | ECHO);
+-        ptyconf.c_lflag &= ~ECHO;
++              ptyconf.c_lflag &= ~ECHO;
+         tcsetattr (c->fd, TCSANOW, &ptyconf);
+         snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b);
+         fd2 = open (tty, O_RDWR);
+-      stropt[pos++] = strdup(tty);
+-      stropt[pos] = NULL;
++              if(!fd2)
++                      log(LOG_WARN, "unable to open tty %s", tty);
++
++              /* XXX JEF: CHECK ME */
++              stropt[pos++] = strdup(tty);
++              stropt[pos] = NULL;
+ #ifdef USE_KERNEL
+     }
+@@ -623,7 +630,13 @@
+ {
+     struct lac *lac;
+     lac = (struct lac *) data;
+-    if (!lac->active)
++
++    if (!lac)
++    {
++        log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__);
++        return;
++    }
++      if (!lac->active)
+     {
+         log (LOG_DEBUG, "%s: LAC %s not active", __FUNCTION__, lac->entname);
+         return;
+@@ -635,11 +648,6 @@
+         log (LOG_LOG, "%s: maximum retries exceeded.\n", __FUNCTION__);
+         return;
+     }
+-    if (!lac)
+-    {
+-        log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__);
+-        return;
+-    }
+     if (!lac->t)
+     {
+ #ifdef DEGUG_MAGIC
+@@ -774,12 +782,7 @@
+ void do_control ()
+ {
+     char buf[1024];
+-    char *host;
+-    char *tunstr;
+-    char *callstr;
+-
+-    char *sub_str;              /* jz: use by the strtok function */
+-    char *tmp_ptr;              /* jz: use by the strtok function */
++    char *host, *tunstr, *callstr, *tmpstr;
+     struct lac *lac;
+     int call;
+     int tunl;
+@@ -792,24 +795,39 @@
+             if (buf[cnt - 1] == '\n')
+                 buf[--cnt] = 0;
+ #ifdef DEBUG_CONTROL
+-            log (LOG_DEBUG, "%s: Got message %s (%d bytes long)\n",
++            log (LOG_DEBUG, "%s: Got message \"%s\" (%d bytes long)\n",
+                  __FUNCTION__, buf, cnt);
+ #endif
+             switch (buf[0])
+             {
+             case 't':
+-                host = strchr (buf, ' ') + 1;
++                host = strchr (buf, ' ');
++                              if(!host)
++                                      goto out;
++                              host++;
+ #ifdef DEBUG_CONTROL
+                 log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n",
+                      __FUNCTION__, host);
+ #endif
+                 l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL);
+                 break;
+-            case 'c':
+-
+-                switch_io = 1;  /* jz: Switch for Incoming - Outgoing Calls */
+-
+-                tunstr = strchr (buf, ' ') + 1;
++            case 'c':            /* option 'c' for incoming call */
++            case 'o':          /* option 'o' for outgoing call */
++                              tunstr = strchr (buf, ' ');
++                              if(!tunstr)
++                                      goto out;
++                              tunstr++;
++
++                              if(buf[0] == 'c')
++                      switch_io = 1;  /* Switch for Incoming Calls */
++                              else {
++                      switch_io = 0;  /* Switch for Outgoing Calls */
++                                      tmpstr = strchr(tunstr, ' ');
++                                      if(!tmpstr)
++                                              goto out;
++                                      strncpy(dial_no_tmp,tmpstr, sizeof(*dial_no_tmp));
++                              }
++                
+                 lac = laclist;
+                 while (lac)
+                 {
+@@ -842,52 +860,12 @@
+ #endif
+                 lac_call (tunl, NULL, NULL);
+                 break;
+-
+-            case 'o':          /* jz: option 'o' for doing a outgoing call */
+-
+-                switch_io = 0;  /* jz: Switch for incoming - outgoing Calls */
+-
+-                sub_str = strchr (buf, ' ') + 1;
+-
+-                tunstr = strtok (sub_str, " "); /* jz: using strtok function to get */
+-                tmp_ptr = strtok (NULL, " ");   /*     params out of the pipe       */
+-                strcpy (dial_no_tmp, tmp_ptr);
+-
+-                lac = laclist;
+-                while (lac)
+-                {
+-                    if (!strcasecmp (lac->entname, tunstr))
+-                    {
+-                        lac->active = -1;
+-                        lac->rtries = 0;
+-                        if (!lac->c)
+-                            magic_lac_dial (lac);
+-                        else
+-                            log (LOG_DEBUG,
+-                                 "%s: Session '%s' already active!\n",
+-                                 __FUNCTION__, lac->entname);
+-                        break;
+-                    }
+-                    lac = lac->next;
+-                }
+-                if (lac)
+-                    break;
+-                tunl = atoi (tunstr);
+-                if (!tunl)
+-                {
+-                    log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
+-                         tunstr);
+-                    break;
+-                }
+-#ifdef DEBUG_CONTROL
+-                log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
+-                     __FUNCTION__, tunl);
+-#endif
+-                lac_call (tunl, NULL, NULL);
+-                break;
+-
+             case 'h':
+-                callstr = strchr (buf, ' ') + 1;
++                callstr = strchr (buf, ' ');
++                if(!callstr)
++                                      goto out;
++                              callstr++;
++
+                 call = atoi (callstr);
+ #ifdef DEBUG_CONTROL
+                 log (LOG_DEBUG, "%s: Attempting to call %d\n", __FUNCTION__,
+@@ -896,7 +874,11 @@
+                 lac_hangup (call);
+                 break;
+             case 'd':
+-                tunstr = strchr (buf, ' ') + 1;
++                tunstr = strchr (buf, ' ');
++                if(!tunstr)
++                                      goto out;
++                              tunstr++;
++
+                 lac = laclist;
+                 while (lac)
+                 {
+@@ -937,6 +919,8 @@
+             }
+         }
+     }
++
++out:
+     /* Otherwise select goes nuts */
+     close (control_fd);
+     control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600);
+@@ -1002,7 +986,6 @@
+     int pid=0;
+     int i,l;
+     char buf[STRLEN];
+-    int pidfilewritten=0;
+     if((pid = fork()) < 0) {
+         log(LOG_LOG, "%s: Unable to fork ()\n",__FUNCTION__);
+@@ -1012,56 +995,52 @@
+     else if (pid)
+         exit(0);
+-    close(0);
+-    close(1);
+-    close(2);
++
++      close(0);
++      close(1);
++      close(2);
++      dup2(open("/dev/null", O_RDONLY), 0);
++      dup2(open("/dev/null", O_RDONLY), 1);
++      dup2(open("/dev/null", O_RDONLY), 2);
+     /* Read previous pid file. */
+-    if ((i = open(gconfig.pidfile,O_RDONLY)) > 0) {
+-        l=read(i,buf,sizeof(buf)-1);
+-        if (i < 0) {
+-            log(LOG_LOG, "%s: Unable to read pid file [%s]\n",
+-                    __FUNCTION__, gconfig.pidfile);
+-        }
+-        buf[i] = '\0';
+-        pid = atoi(buf);
+-
+-        /* If the previous server process is not still running,
+-           write a new pid file immediately. */
+-        if (pid && (pid == getpid () || kill (pid, 0) < 0)) {
+-            unlink (gconfig.pidfile);
+-            if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0640)) >= 0)
+-            {
+-                snprintf (buf, sizeof(buf), "%d\n", (int)getpid());
+-                write (i, buf, strlen(buf));
+-                close (i);
+-                pidfilewritten = 1;
+-            }
++    if((i = open(gconfig.pidfile,O_RDONLY)) > 0) {
++              l=read(i,buf,sizeof(buf)-1);                                                             
++        if (l >= 0) {
++              buf[l] = '\0';                                                                       
++              pid = atoi(buf);                                                                     
+         }
+-        else
+-        {
++              close(i);
++
++              /* if pid is read and process exist exit */
++        if(pid && !kill(pid, 0)) {
+             log(LOG_LOG, "%s: There's already a l2tpd server running.\n",
+                     __FUNCTION__);
+             close(server_socket);
+             exit(1);
+         }
++
++              /* remove stalled pid file */
++              unlink(gconfig.pidfile);
+     }
+     pid = setsid();
+-    if(! pidfilewritten) {
+-        unlink(gconfig.pidfile);
+-        if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0640)) >= 0) {
+-            snprintf (buf, strlen(buf), "%d\n", (int)getpid());
+-            write (i, buf, strlen(buf));
+-            close (i);
+-            pidfilewritten = 1;
+-        }
+-    }
++      /* create new pid file */
++      if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0644)) >= 0) {
++              snprintf (buf, sizeof(buf), "%d", (int)getpid());
++              write (i, buf, strlen(buf));
++              close (i);
++      }
++      else {
++              log(LOG_LOG, "%s: could not write pid file %s error %d",
++                              __FUNCTION__, gconfig.pidfile, i);
++              close(server_socket);
++              exit(1);
++      }
+ }
+-
+ void init (int argc,char *argv[])
+ {
+     struct lac *lac;
+@@ -1103,10 +1082,6 @@
+     }
+     log (LOG_LOG, "l2tpd version " SERVER_VERSION " started on %s PID:%d\n",
+          hostname, getpid ());
+-    log (LOG_LOG,
+-         "Written by Mark Spencer, Copyright (C) 1998, Adtran, Inc.\n");
+-    log (LOG_LOG, "Forked by Scott Balmos and David Stipp, (C) 2001\n");
+-    log (LOG_LOG, "Inherited by Jeff McAdams, (C) 2002\n");
+     listenaddr.s_addr = gconfig.listenaddr;
+     log (LOG_LOG, "%s version %s on a %s, listening on IP address %s, port %d\n", uts.sysname,
+        uts.release, uts.machine, inet_ntoa(listenaddr), gconfig.port);
+--- l2tpd-0.70-pre20031121.orig/misc.c
++++ l2tpd-0.70-pre20031121/misc.c
+@@ -301,3 +301,42 @@
+         return -1;
+     }
+ }
++
++u_int16_t get16(u_int8_t *p) {
++      return p[0] << 8 | p[1];
++}
++
++u_int32_t get32(u_int8_t *p) {
++      return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
++}
++
++u_int64_t get64(u_int8_t *p) {
++      return (u_int64_t)p[0] << 56 | (u_int64_t)p[1] << 48 |
++             (u_int64_t)p[2] << 40 | (u_int64_t)p[3] << 32 |
++             (u_int64_t)p[4] << 24 | (u_int64_t)p[5] << 16 | 
++                 (u_int64_t)p[6] << 8  | (u_int64_t)p[7];
++}
++
++void set16(u_int8_t *cp, u_int16_t x) {
++      *cp++ = x >> 8;
++    *cp = x & 0xff;
++} 
++
++void set32(u_int8_t *cp, u_int32_t x) {
++      *cp++ = x >> 24;
++    *cp++ = (x >> 16) & 0xff;
++      *cp++ = (x >> 8) & 0xff;
++      *cp = x & 0xff;
++}
++
++void set64(u_int8_t *cp, u_int64_t x) {   
++      *cp++ = x >> 56;
++      *cp++ = (x >> 48) & 0xff;
++      *cp++ = (x >> 40) & 0xff;
++      *cp++ = (x >> 32) & 0xff;
++      *cp++ = (x >> 24) & 0xff;
++      *cp++ = (x >> 16) & 0xff;
++      *cp++ = (x >> 8) & 0xff;
++      *cp = x & 0xff;
++}
++
+--- l2tpd-0.70-pre20031121.orig/avp.c
++++ l2tpd-0.70-pre20031121/avp.c
+@@ -4,9 +4,12 @@
+  * Layer Two Tunnelling Protocol Daemon
+  * Copyright (C) 1998 Adtran, Inc.
+  * Copyright (C) 2002 Jeff McAdams
++ * Copyright (C) 2003 Jean-Francois Dive
+  *
+  * Mark Spencer
+  *
++ * 12/2003    parsing sanitization, Jean-Francois Dive
++ *
+  * This software is distributed under the terms
+  * of the GPL, which you should have received
+  * along with this source.
+@@ -20,50 +23,53 @@
+ #include <netinet/in.h>
+ #include "l2tp.h"
+-#define AVP_MAX 39
++/* TODO: 
++ * - Tie breaker.
++ * - Clean Proxy Authentication solution.
++ */
++/*****************************************************************************/
+ struct avp avps[] = {
+-
+-    {0, 1, &message_type_avp, "Message Type"},
+-    {1, 1, &result_code_avp, "Result Code"},
+-    {2, 1, &protocol_version_avp, "Protocol Version"},
+-    {3, 1, &framing_caps_avp, "Framing Capabilities"},
+-    {4, 1, &bearer_caps_avp, "Bearer Capabilities"},
+-    {5, 0, NULL, "Tie Breaker"},
+-    {6, 0, &firmware_rev_avp, "Firmware Revision"},
+-    {7, 0, &hostname_avp, "Host Name"},
+-    {8, 1, &vendor_avp, "Vendor Name"},
+-    {9, 1, &assigned_tunnel_avp, "Assigned Tunnel ID"},
+-    {10, 1, &receive_window_size_avp, "Receive Window Size"},
+-    {11, 1, &challenge_avp, "Challenge"},
+-    {12, 0, NULL, "Q.931 Cause Code"},
+-    {13, 1, &chalresp_avp, "Challenge Response"},
+-    {14, 1, &assigned_call_avp, "Assigned Call ID"},
+-    {15, 1, &call_serno_avp, "Call Serial Number"},
+-    {16, 1, NULL, "Minimum BPS"},
+-    {17, 1, NULL, "Maximum BPS"},
+-    {18, 1, &bearer_type_avp, "Bearer Type"},
+-    {19, 1, &frame_type_avp, "Framing Type"},
+-    {20, 1, &packet_delay_avp, "Packet Processing Delay"},
+-    {21, 1, &dialed_number_avp, "Dialed Number"},
+-    {22, 1, &dialing_number_avp, "Dialing Number"},
+-    {23, 1, &sub_address_avp, "Sub-Address"},
+-    {24, 1, &tx_speed_avp, "Transmit Connect Speed"},
+-    {25, 1, &call_physchan_avp, "Physical channel ID"},
+-    {26, 0, NULL, "Initial Received LCP Confreq"},
+-    {27, 0, NULL, "Last Sent LCP Confreq"},
+-    {28, 0, NULL, "Last Received LCP Confreq"},
+-    {29, 1, &ignore_avp, "Proxy Authen Type"},
+-    {30, 0, &ignore_avp, "Proxy Authen Name"},
+-    {31, 0, &ignore_avp, "Proxy Authen Challenge"},
+-    {32, 0, &ignore_avp, "Proxy Authen ID"},
+-    {33, 1, &ignore_avp, "Proxy Authen Response"},
+-    {34, 1, NULL, "Call Errors"},
+-    {35, 1, &ignore_avp, "ACCM"},
+-    {36, 1, &rand_vector_avp, "Random Vector"},
+-    {37, 1, NULL, "Private Group ID"},
+-    {38, 0, &rx_speed_avp, "Receive Connect Speed"},
+-    {39, 1, &seq_reqd_avp, "Sequencing Required"}
++    {0, AVP_F_MANDATORY|AVP_F_FIXLEN, 2, {0}, &message_type_avp, &validate_msgtype_avp, "Message Type"},
++    {1, AVP_F_MANDATORY, MAXSTRLEN, {CDN, StopCCN}, &result_code_avp, &validate_gen_avp, "Result Code"},
++    {2, AVP_F_MANDATORY|AVP_F_FIXLEN, 2, {SCCRP, SCCRQ}, &protocol_version_avp, &validate_gen_avp, "Protocol Version"},
++    {3, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {SCCRP, SCCRQ}, &framing_caps_avp, &validate_gen_avp, "Framing Capabilities"},
++    {4, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {SCCRP, SCCRQ}, &bearer_caps_avp, &validate_gen_avp, "Bearer Capabilities"},
++    {5, 0, 0, {0}, NULL, NULL, "Tie Breaker"},
++    {6, AVP_F_FIXLEN, 2, {SCCRP, SCCRQ}, &firmware_rev_avp, &validate_gen_avp, "Firmware Revision"},
++    {7, AVP_F_ASCII, MAXSTRLEN, {SCCRP, SCCRQ}, &hostname_avp, &validate_gen_avp, "Host Name"},
++    {8, AVP_F_MANDATORY|AVP_F_ASCII, MAXSTRLEN, {SCCRP, SCCRQ}, &vendor_avp, &validate_gen_avp, "Vendor Name"},
++    {9, AVP_F_MANDATORY|AVP_F_FIXLEN, 2, {SCCRP, SCCRQ, StopCCN}, &assigned_tunnel_avp, &validate_gen_avp, "Assigned Tunnel ID"},
++    {10, AVP_F_MANDATORY|AVP_F_FIXLEN, 2,{SCCRP, SCCRQ, OCRP, OCCN, StopCCN}, &receive_window_size_avp, &validate_gen_avp, "Receive Window Size"},
++    {11, AVP_F_MANDATORY, 128, {SCCRP, SCCRQ}, &challenge_avp, &validate_gen_avp, "Challenge"},
++    {12, 0, 0, {0}, NULL, NULL, "Q.931 Cause Code"},
++    {13, AVP_F_MANDATORY, MD_SIG_SIZE, {SCCRP, SCCCN}, &chalresp_avp, &validate_gen_avp, "Challenge Response"},
++    {14, AVP_F_MANDATORY|AVP_F_FIXLEN, 2, {CDN, ICRP, ICRQ, OCRP, OCRQ}, &assigned_session_avp, &validate_gen_avp, "Assigned Session ID"},
++    {15, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {ICRQ, OCRQ}, &call_serno_avp, &validate_gen_avp, "Call Serial Number"},
++    {16, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {0}, NULL, NULL, "Minimum BPS"},
++    {17, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {0}, NULL, NULL, "Maximum BPS"},
++    {18, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {ICRQ, OCRQ}, &bearer_type_avp, &validate_gen_avp, "Bearer Type"},
++    {19, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {ICCN, OCRQ, OCCN}, &frame_type_avp, &validate_gen_avp, "Framing Type"},
++    {20, AVP_F_MANDATORY|AVP_F_FIXLEN, 2, {ICRP, OCRQ, ICCN, OCRP, OCCN}, &packet_delay_avp, &validate_gen_avp, "Packet Processing Delay"},
++    {21, AVP_F_MANDATORY|AVP_F_ASCII, MAXSTRLEN, {ICRQ, OCRQ}, &called_number_avp, &validate_gen_avp, "Called Number"},
++    {22, AVP_F_MANDATORY|AVP_F_ASCII, MAXSTRLEN, {ICRQ}, &calling_number_avp, &validate_gen_avp, "Calling Number"},
++    {23, AVP_F_MANDATORY|AVP_F_ASCII, MAXSTRLEN, {OCRP, ICRQ}, &sub_address_avp, &validate_gen_avp, "Sub-Address"},
++    {24, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {ICCN, OCCN, OCRP}, &tx_speed_avp, &validate_gen_avp, "Transmit Connect Speed"},
++    {25, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {ICRQ, OCRQ, OCRP, OCCN}, &call_physchan_avp, &validate_gen_avp, "Physical channel ID"},
++    {26, 0, 0, {0}, NULL, NULL, "Initial Received LCP Confreq"},
++    {27, 0, 0, {0}, NULL, NULL, "Last Sent LCP Confreq"},
++    {28, 0, 0, {0}, NULL, NULL, "Last Received LCP Confreq"},
++    {29, AVP_F_MANDATORY, 0, {0}, &ignore_avp, NULL, "Proxy Authen Type"},
++    {30, 0, 0, {0}, &ignore_avp, NULL, "Proxy Authen Name"},
++    {31, 0, 0, {0}, &ignore_avp, NULL, "Proxy Authen Challenge"},
++    {32, 0, 0, {0}, &ignore_avp, NULL, "Proxy Authen ID"},
++    {33, AVP_F_MANDATORY, 0, {0}, &ignore_avp, NULL, "Proxy Authen Response"},
++    {34, AVP_F_MANDATORY|AVP_F_FIXLEN, 26, {0}, NULL, NULL, "Call Errors"},
++    {35, AVP_F_MANDATORY|AVP_F_FIXLEN, 10, {0}, &ignore_avp, NULL, "ACCM"},
++    {36, AVP_F_MANDATORY, 1024, {0}, &rand_vector_avp, &validate_gen_avp, "Random Vector"},
++    {37, AVP_F_MANDATORY, 0, {0}, NULL, NULL, "Private Group ID"},
++    {38, AVP_F_FIXLEN, 4, {ICCN, OCCN, OCRP}, &rx_speed_avp, &validate_gen_avp, "Receive Connect Speed"},
++    {39, AVP_F_MANDATORY, 0, {ICCN, OCCN, OCRP}, &seq_reqd_avp, &validate_gen_avp, "Sequencing Required"}
+ };
+ char *msgtypes[] = {
+@@ -111,6 +117,7 @@
+     "Call was connected but no appropriate framing was detect"
+ };
++/*****************************************************************************/
+ void wrong_length (struct call *c, char *field, int expected, int found,
+                    int min)
+ {
+@@ -126,12 +133,9 @@
+     c->needclose = -1;
+ }
+-/*
+- * t, c, data, and datalen may be assumed to be defined for all avp's
+- */
+-
+-int message_type_avp (struct tunnel *t, struct call *c, void *data,
+-                      int datalen)
++/*****************************************************************************/
++int validate_msgtype_avp(int attr,  struct tunnel *t, struct call *c, 
++                                               void *data, int datalen)
+ {
+     /*
+      * This will be with every control message.  It is critical that this
+@@ -139,28 +143,9 @@
+      * (assuming sanity check)
+      */
+-    _u16 *raw = data;
+-    c->msgtype = ntohs (raw[3]);
+-    if (datalen != 8)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG, "%s: wrong size (%d != 8)\n", __FUNCTION__,
+-                 datalen);
+-        wrong_length (c, "Message Type", 8, datalen, 0);
+-        return -EINVAL;
+-    }
+-    if ((c->msgtype > MAX_MSG) || (!msgtypes[c->msgtype]))
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG, "%s: unknown message type %d\n", __FUNCTION__,
+-                 c->msgtype);
+-        return -EINVAL;
+-    }
+-    if (debug_avp)
+-        if (DEBUG)
+-            log (LOG_DEBUG, "%s: message type %d (%s)\n", __FUNCTION__,
+-                 c->msgtype, msgtypes[c->msgtype]);
+-#ifdef SANITY
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      c->msgtype = get16(p);
++
+     if (t->sanity)
+     {
+         /*
+@@ -172,11 +157,11 @@
+             if (DEBUG)
+                 log (LOG_DEBUG,
+                      "%s: attempting to negotiate tunnel inside a call!\n",
+-                     __FUNCTION__);
++                     __func__);
+             return -EINVAL;
+         }
+-        switch (c->msgtype)
++        switch (get16(p))
+         {
+         case SCCRQ:
+             if ((t->state != 0) && (t->state != SCCRQ))
+@@ -189,7 +174,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate SCCRQ with state != 0\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             break;
+@@ -199,7 +184,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate SCCRP with state != SCCRQ!\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             break;
+@@ -209,7 +194,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate SCCCN with state != SCCRP!\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             break;
+@@ -219,7 +204,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate ICRQ when state != SCCCN\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             if (c != t->self)
+@@ -227,7 +212,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate ICRQ on a call!\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             break;
+@@ -237,7 +222,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate ICRP on tunnel!=SCCCN\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             if (c->state != ICRQ)
+@@ -245,7 +230,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate ICRP when state != ICRQ\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             break;
+@@ -255,7 +240,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate ICCN when state != ICRP\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             break;
+@@ -265,7 +250,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate SLI when state != ICCN\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             break;
+@@ -275,7 +260,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate OCRP on tunnel!=SCCCN\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             if (c->state != OCRQ)
+@@ -283,7 +268,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate OCRP when state != OCRQ\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             break;
+@@ -294,7 +279,7 @@
+                 if (DEBUG)
+                     log (LOG_DEBUG,
+                          "%s: attempting to negotiate OCCN when state != OCRQ\n",
+-                         __FUNCTION__);
++                         __func__);
+                 return -EINVAL;
+             }
+             break;
+@@ -303,72 +288,33 @@
+         case Hello:
+             break;
+         default:
+-            log (LOG_WARN, "%s: i don't know how to handle %s messages\n",
+-                 __FUNCTION__, msgtypes[c->msgtype]);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    if (c->msgtype == ICRQ)
+-    {
+-        struct call *tmp;
+-        if (debug_avp)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG, "%s: new incoming call\n", __FUNCTION__);
+-        }
+-        tmp = new_call (t);
+-        if (!tmp)
+-        {
+-            log (LOG_WARN, "%s: unable to create new call\n", __FUNCTION__);
++            log (LOG_WARN, "%s: unknown messages type %d\n",
++                 __func__, get16(p));
+             return -EINVAL;
+         }
+-        tmp->next = t->call_head;
+-        t->call_head = tmp;
+-        t->count++;
+-        /*
+-           * Is this still safe to assume that the head will always
+-           * be the most recent call being negotiated?
+-           * Probably...  FIXME anyway...
+-         */
+-
+     }
+-    return 0;
++      return 0;
+ }
+-int rand_vector_avp (struct tunnel *t, struct call *c, void *data,
+-                     int datalen)
+-{
+-    int size;
+-    _u16 *raw = (_u16 *) data;
+-    size = (raw[0] & 0x0FFF) - 6;
+-    if (t->sanity)
+-    {
+-        if (size < 0)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG, "%s: Random vector too small (%d < 0)\n",
+-                     __FUNCTION__, size);
+-            wrong_length (c, "Random Vector", 6, datalen, 1);
+-            return -EINVAL;
+-        }
+-        if (size > MAX_VECTOR_SIZE)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG, "%s: Random vector too large (%d > %d)\n",
+-                     __FUNCTION__, datalen, MAX_VECTOR_SIZE);
+-            wrong_length (c, "Random Vector", 6, datalen, 1);
+-            return -EINVAL;
+-        }
+-    }
+-    if (debug_avp)
+-        log (LOG_DEBUG, "%s: Random Vector of %d octets\n", __FUNCTION__,
+-             size);
+-    t->chal_us.vector = (unsigned char *) &raw[3];
+-    t->chal_us.vector_len = size;
+-    return 0;
++/*****************************************************************************/
++int validate_gen_avp(int attr,  struct tunnel *t, struct call *c, 
++                                       void *data, int datalen) {
++      (void)data; (void)datalen;
++      int i = 0, found = 0;
++
++    if(t->sanity) {
++              for(i = 0; i < 8; i++) {
++                      if(c->msgtype == avps[attr].allowed_states[i])
++                              found++;
++              }
++              if(!found) 
++                      return -EINVAL;
++      }
++      return 0;
+ }
++/* t, c, data, and datalen may be assumed to be defined for all avp's        */
++/*****************************************************************************/
+ int ignore_avp (struct tunnel *t, struct call *c, void *data, int datalen)
+ {
+     /*
+@@ -383,94 +329,88 @@
+      *
+      */
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG, "%s : Ignoring AVP\n", __FUNCTION__);
+-    }
++      log (LOG_DEBUG, "%s : Ignoring AVP\n", __func__);
+     return 0;
+ }
+-int seq_reqd_avp (struct tunnel *t, struct call *c, void *data, int datalen)
++/*****************************************************************************/
++int message_type_avp (struct tunnel *t, struct call *c, void *data,
++                      int avplen)
+ {
+-#ifdef SANITY
+-    if (t->sanity)
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      
++      if(!c->msgtype)
++              c->msgtype = get16(p);
++
++    if ((c->msgtype > MAX_MSG) || (!msgtypes[c->msgtype]))
+     {
+-        if (datalen != 6)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is incorrect size.  %d != 6\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Sequencing Required", 6, datalen, 1);
+-            return -EINVAL;
+-        }
+-        switch (c->msgtype)
++        log (LOG_DEBUG, "%s: unknown message type %d\n", __func__,
++             c->msgtype);
++        return -EINVAL;
++    }
++    if (debug_avp)
++        log (LOG_DEBUG, "%s: message type %d (%s)\n", __func__,
++             c->msgtype, msgtypes[c->msgtype]);
++    if (c->msgtype == ICRQ)
++    {
++        struct call *tmp;
++        if (debug_avp)
++              log (LOG_DEBUG, "%s: new incoming call\n", __func__);
++        tmp = new_call (t);
++        if (!tmp)
+         {
+-        case ICCN:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: sequencing required not appropriate for %s!\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
++            log (LOG_WARN, "%s: unable to create new call\n", __func__);
+             return -EINVAL;
+         }
++        tmp->next = t->call_head;
++        t->call_head = tmp;
++        t->count++;
++        /*
++         * Is this still safe to assume that the head will always
++         * be the most recent call being negotiated?
++         * Probably...  FIXME anyway...
++         */
+     }
+-#endif
++    return 0;
++}
++
++/*****************************************************************************/
++int rand_vector_avp (struct tunnel *t, struct call *c, void *data,
++                     int avplen)
++{
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      int datalen = avplen - sizeof(struct avp_hdr);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG, "%s: peer requires sequencing.\n", __FUNCTION__);
+-    }
++        log (LOG_DEBUG, "%s: random vector len %d\n", __func__, datalen);
++    t->chal_us.vector = (unsigned char *)p;
++    t->chal_us.vector_len = datalen;
++    return 0;
++}
++
++/*****************************************************************************/
++int seq_reqd_avp (struct tunnel *t, struct call *c, void *data, int datalen)
++{
++    if (debug_avp)
++      log (LOG_DEBUG, "%s: peer requires sequencing.\n", __func__);
+     c->seq_reqd = -1;
+     return 0;
+ }
++/*****************************************************************************/
+ int result_code_avp (struct tunnel *t, struct call *c, void *data,
+-                     int datalen)
++                     int avplen)
+ {
+-    /*
+-     * Find out what version of l2tp the other side is using.
+-     * I'm not sure what we're supposed to do with this but whatever..
+-     */
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      int datalen = avplen - sizeof(struct avp_hdr);
++    u_int16_t result = get16(p);
++    u_int16_t error = get16(p + 2);
+-    int error;
+-    int result;
+-    _u16 *raw = data;
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        if (datalen < 10)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is incorrect size.  %d < 10\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Result Code", 10, datalen, 1);
+-            return -EINVAL;
+-        }
+-        switch (c->msgtype)
+-        {
+-        case CDN:
+-        case StopCCN:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: result code not appropriate for %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-    }
+-#endif
+-    result = ntohs (raw[3]);
+-    error = ntohs (raw[4]);
+     if ((c->msgtype == StopCCN) && ((result > 7) || (result < 1)))
+     {
+         if (DEBUG)
+             log (LOG_DEBUG,
+-                 "%s: result code out of range (%d %d %d).  Ignoring.\n",
+-                 __FUNCTION__, result, error, datalen);
++                 "%s: (StopCCN) result code out of range ! (1 < %d < 7)\n",
++                 __func__, result);
+         return 0;
+     }
+@@ -478,1112 +418,348 @@
+     {
+         if (DEBUG)
+             log (LOG_DEBUG,
+-                 "%s: result code out of range (%d %d %d).  Ignoring.\n",
+-                 __FUNCTION__, result, error, datalen);
++                 "%s: (CDN) result code out of range !(1 < %d < 11)\n",
++                 __func__, result);
+         return 0;
+     }
+     c->error = error;
+     c->result = result;
+-    safe_copy (c->errormsg, (char *) &raw[5], datalen - 10);
++      memcpy(c->errormsg, (char*)p + 4, datalen - 4);
++      c->errormsg[datalen - 4] = '\0';
++
+     if (debug_avp)
+     {
+-        if (DEBUG && (c->msgtype == StopCCN))
++        if(c->msgtype == StopCCN)
+         {
+             log (LOG_DEBUG,
+                  "%s: peer closing for reason %d (%s), error = %d (%s)\n",
+-                 __FUNCTION__, result, stopccn_result_codes[result], error,
++                 __func__, result, stopccn_result_codes[result], error,
+                  c->errormsg);
+         }
+         else
+         {
+             log (LOG_DEBUG,
+                  "%s: peer closing for reason %d (%s), error = %d (%s)\n",
+-                 __FUNCTION__, result, cdn_result_codes[result], error,
++                 __func__, result, cdn_result_codes[result], error,
+                  c->errormsg);
+         }
+     }
+     return 0;
+ }
++/*****************************************************************************/
+ int protocol_version_avp (struct tunnel *t, struct call *c, void *data,
+-                          int datalen)
++                          int avplen)
+ {
+-    /*
+-     * Find out what version of l2tp the other side is using.
+-     * I'm not sure what we're supposed to do with this but whatever..
+-     */
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-    int ver;
+-    _u16 *raw = data;
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        if (datalen != 8)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is incorrect size.  %d != 8\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Protocol Version", 8, datalen, 1);
+-            return -EINVAL;
+-        }
+-        switch (c->msgtype)
+-        {
+-        case SCCRP:
+-        case SCCRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: protocol version not appropriate for %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-    }
+-#endif
+-    ver = ntohs (raw[3]);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer is using version %d, revision %d.\n", __FUNCTION__,
+-                 (ver >> 8), ver & 0xFF);
+-    }
++      log (LOG_DEBUG, "%s: peer is using version %d, revision %d.\n", 
++                       __func__,*p, *(p+1));
+     return 0;
+ }
++/*****************************************************************************/
+ int framing_caps_avp (struct tunnel *t, struct call *c, void *data,
+-                      int datalen)
++                      int avplen)
+ {
+-    /*
+-     * Retrieve the framing capabilities
+-     * from the peer
+-     */
+-
+-    int caps;
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++    u_int16_t caps = get16(p + 2);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case SCCRP:
+-        case SCCRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: framing capabilities not appropriate for %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 10)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is incorrect size.  %d != 10\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Framming Capabilities", 10, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    caps = ntohs (raw[4]);
+     if (debug_avp)
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: supported peer frames:%s%s\n", __FUNCTION__,
+-                 caps & ASYNC_FRAMING ? " async" : "",
+-                 caps & SYNC_FRAMING ? " sync" : "");
++      log (LOG_DEBUG, "%s: supported peer frames:%s %s\n", __func__,
++             caps & ASYNC_FRAMING ? "async" : "",
++             caps & SYNC_FRAMING ? "sync" : "");
++
+     t->fc = caps & (ASYNC_FRAMING | SYNC_FRAMING);
+     return 0;
+ }
++/*****************************************************************************/
+ int bearer_caps_avp (struct tunnel *t, struct call *c, void *data,
+-                     int datalen)
++                     int avplen)
+ {
+-    /*
+-     * What kind of bearer channels does our peer support?
+-     */
+-    int caps;
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++    u_int16_t caps = get16(p + 2);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case SCCRP:
+-        case SCCRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: bearer capabilities not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 10)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is incorrect size.  %d != 10\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Bearer Capabilities", 10, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    caps = ntohs (raw[4]);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-        {
+-            log (LOG_DEBUG,
+-                 "%s: supported peer bearers:%s%s\n",
+-                 __FUNCTION__,
+-                 caps & ANALOG_BEARER ? " analog" : "",
+-                 caps & DIGITAL_BEARER ? " digital" : "");
+-        }
++      log (LOG_DEBUG, "%s: supported peer bearers:%s %s\n",
++              __func__,
++              caps & ANALOG_BEARER ? "analog" : "",
++              caps & DIGITAL_BEARER ? "digital" : "");
+-    }
+     t->bc = caps & (ANALOG_BEARER | DIGITAL_BEARER);
+     return 0;
+ }
+-
+-/* FIXME: I need to handle tie breakers eventually */
+-
++/*****************************************************************************/
+ int firmware_rev_avp (struct tunnel *t, struct call *c, void *data,
+-                      int datalen)
++                      int avplen)
+ {
+-    /*
+-     * Report and record remote firmware version
+-     */
+-    int ver;
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case SCCRP:
+-        case SCCRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: firmware revision not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 8)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is incorrect size.  %d != 8\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Firmware Revision", 8, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    ver = ntohs (raw[3]);
++    t->firmware = get16(p);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer reports firmware version %d (0x%.4x)\n",
+-                 __FUNCTION__, ver, ver);
+-    }
+-    t->firmware = ver;
++      log (LOG_DEBUG, "%s: peer reports firmware version %d (0x%.4X)\n",
++              __func__, t->firmware, t->firmware);
+     return 0;
+ }
++/*****************************************************************************/
+ int bearer_type_avp (struct tunnel *t, struct call *c, void *data,
+-                     int datalen)
++                     int avplen)
+ {
+-    /*
+-     * What kind of bearer channel is the call on?
+-     */
+-    int b;
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case ICRQ:
+-        case OCRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: bearer type not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 10)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is incorrect size.  %d != 10\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Bearer Type", 10, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    b = ntohs (raw[4]);
++      t->call_head->bearer = get16(p + 2);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer bears:%s\n", __FUNCTION__,
+-                 b & ANALOG_BEARER ? " analog" : "digital");
+-    }
+-    t->call_head->bearer = b;
++      log (LOG_DEBUG, "%s: peer bears: %s\n", __func__,
++             (t->call_head->bearer & ANALOG_BEARER) ? "analog" : "digital");
+     return 0;
+ }
+-int frame_type_avp (struct tunnel *t, struct call *c, void *data, int datalen)
++/*****************************************************************************/
++int frame_type_avp (struct tunnel *t, struct call *c, void *data, int avplen)
+ {
+-    /*
+-     * What kind of frame channel is the call on?
+-     */
+-    int b;
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case ICCN:
+-        case OCRQ:
+-        case OCCN:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: frame type not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 10)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is incorrect size.  %d != 10\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Frame Type", 10, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    b = ntohs (raw[4]);
++      c->frame = get16(p + 2);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer uses:%s frames\n", __FUNCTION__,
+-                 b & ASYNC_FRAMING ? " async" : "sync");
+-    }
+-    c->frame = b;
++      log (LOG_DEBUG, "%s: peer uses:%s frames\n", __func__,
++             (c->frame & ASYNC_FRAMING) ? "async" : "sync");
+     return 0;
+ }
+-int hostname_avp (struct tunnel *t, struct call *c, void *data, int datalen)
++/*****************************************************************************/
++int hostname_avp (struct tunnel *t, struct call *c, void *data, int avplen)
+ {
+-    /*
+-     * What is the peer's name?
+-     */
+-    int size;
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      int datalen = avplen - sizeof(struct avp_hdr);
++
++    memcpy(t->hostname, p, datalen);
++      t->hostname[datalen] = '\0';
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case SCCRP:
+-        case SCCRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: hostname not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen < 6)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Hostname", 6, datalen, 1);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    size = raw[0] & 0x0FFF;
+-    if (size > MAXSTRLEN - 1)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG, "%s: truncating reported hostname (size is %d)\n",
+-                 __FUNCTION__, size);
+-        size = MAXSTRLEN - 1;
+-    }
+-    safe_copy (t->hostname, (char *) &raw[3], size - 6);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer reports hostname '%s'\n", __FUNCTION__,
+-                 t->hostname);
+-    }
++      log (LOG_DEBUG, "%s: peer reports hostname '%s'\n", __func__,
++             t->hostname);
++
+     return 0;
+ }
+-int dialing_number_avp (struct tunnel *t, struct call *c, void *data,
+-                        int datalen)
++/*****************************************************************************/
++int calling_number_avp (struct tunnel *t, struct call *c, void *data,
++                        int avplen)
+ {
+-    /*
+-     * What is the peer's name?
+-     */
+-    int size;
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      int datalen = avplen - sizeof(struct avp_hdr);
++
++    memcpy(t->call_head->dialing, p, datalen);
++      t->call_head->dialing[datalen] = '\0';
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case ICRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: dialing number not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen < 6)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Dialing Number", 6, datalen, 1);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    size = raw[0] & 0x0FFF;
+-    if (size > MAXSTRLEN - 1)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: truncating reported dialing number (size is %d)\n",
+-                 __FUNCTION__, size);
+-        size = MAXSTRLEN - 1;
+-    }
+-    safe_copy (t->call_head->dialing, (char *) &raw[3], size);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer reports dialing number '%s'\n", __FUNCTION__,
+-                 t->call_head->dialing);
+-    }
++      log (LOG_DEBUG, "%s: peer reports dialing number '%s'\n", __func__,
++             t->call_head->dialing);
++
+     return 0;
+ }
+-int dialed_number_avp (struct tunnel *t, struct call *c, void *data,
+-                       int datalen)
++/*****************************************************************************/
++int called_number_avp (struct tunnel *t, struct call *c, void *data,
++                       int avplen)
+ {
+-    /*
+-     * What is the peer's name?
+-     */
+-    int size;
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      int datalen = avplen - sizeof(struct avp_hdr);
++
++    memcpy(t->call_head->dialed, p, datalen);
++      t->call_head->dialed[datalen] = '\0';
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case OCRQ:
+-        case ICRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: dialed number not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen < 6)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Dialed Number", 6, datalen, 1);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    size = raw[0] & 0x0FFF;
+-    if (size > MAXSTRLEN - 1)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: truncating reported dialed number (size is %d)\n",
+-                 __FUNCTION__, size);
+-        size = MAXSTRLEN - 1;
+-    }
+-    safe_copy (t->call_head->dialed, (char *) &raw[3], size);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer reports dialed number '%s'\n", __FUNCTION__,
+-                 t->call_head->dialed);
+-    }
++      log (LOG_DEBUG, "%s: peer reports dialed number '%s'\n", __func__,
++             t->call_head->dialed);
++
+     return 0;
+ }
++/*****************************************************************************/
+ int sub_address_avp (struct tunnel *t, struct call *c, void *data,
+-                     int datalen)
++                     int avplen)
+ {
+-    /*
+-     * What is the peer's name?
+-     */
+-    int size;
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      int datalen = avplen - sizeof(struct avp_hdr);
++
++      memcpy(t->call_head->subaddy, p, datalen);
++      t->call_head->subaddy[datalen] = '\0';
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case OCRP:
+-        case ICRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: sub_address not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen < 6)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Sub-address", 6, datalen, 1);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    size = raw[0] & 0x0FFF;
+-    if (size > MAXSTRLEN - 1)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: truncating reported sub address (size is %d)\n",
+-                 __FUNCTION__, size);
+-        size = MAXSTRLEN - 1;
+-    }
+-    safe_copy (t->call_head->subaddy, (char *) &raw[3], size);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer reports subaddress '%s'\n", __FUNCTION__,
+-                 t->call_head->subaddy);
+-    }
++      log (LOG_DEBUG, "%s: peer reports subaddress '%s'\n", __func__,
++             t->call_head->subaddy);
+     return 0;
+ }
+-int vendor_avp (struct tunnel *t, struct call *c, void *data, int datalen)
++/*****************************************************************************/
++int vendor_avp (struct tunnel *t, struct call *c, void *data, int avplen)
+ {
+-    /*
+-     * What vendor makes the other end?
+-     */
+-    int size;
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      int datalen = avplen - sizeof(struct avp_hdr);
++
++      memcpy(t->vendor, p, datalen);
++      t->vendor[datalen] = '\0';
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case SCCRP:
+-        case SCCRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: vendor not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen < 6)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Vendor", 6, datalen, 1);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    size = raw[0] & 0x0FFF;
+-    if (size > MAXSTRLEN - 1)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG, "%s: truncating reported vendor (size is %d)\n",
+-                 __FUNCTION__, size);
+-        size = MAXSTRLEN - 1;
+-    }
+-    safe_copy (t->vendor, (char *) &raw[3], size);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer reports vendor '%s'\n", __FUNCTION__, t->vendor);
+-    }
++      log (LOG_DEBUG, "%s: peer reports vendor '%s'\n", __func__, t->vendor);
+     return 0;
+ }
+-int challenge_avp (struct tunnel *t, struct call *c, void *data, int datalen)
++/*****************************************************************************/
++int challenge_avp (struct tunnel *t, struct call *c, void *data, int avplen)
+ {
+-    /*
+-     * We are sent a challenge
+-     */
+-    _u16 *raw = data;
+-    int size;
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case SCCRP:
+-        case SCCRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: challenge not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen < 6)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "challenge", 6, datalen, 1);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    /* size = raw[0] & 0x0FFF; */
+-    /* length field of AVP's is only 10 bits long, not 12 */
+-    size = raw[0] & 0x03FF;
+-    size -= sizeof (struct avp_hdr);
+-    /* if (size != MD_SIG_SIZE)
+-    {
+-        log (LOG_DEBUG, "%s: Challenge is not the right length (%d != %d)\n",
+-             __FUNCTION__, size, MD_SIG_SIZE);
+-        return -EINVAL;
+-    } */
+-    t->chal_us.challenge = malloc(size+1);
+-    if (t->chal_us.challenge == NULL)
+-    {
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      int datalen = avplen - sizeof(struct avp_hdr);
++
++    t->chal_us.challenge = calloc(datalen, 1);
++    if (!t->chal_us.challenge)
+         return -ENOMEM;
+-    }
+-    memset(t->chal_us.challenge, 0, size+1);
+-    bcopy (&raw[3], (t->chal_us.challenge), size);
++    memcpy(t->chal_us.challenge, p, datalen);
+     t->chal_us.state = STATE_CHALLENGED;
++
+     if (debug_avp)
+-    {
+-        log (LOG_DEBUG, "%s: challenge avp found\n", __FUNCTION__);
+-    }
++      log (LOG_DEBUG, "%s: challenge avp found\n", __func__);
++
+     return 0;
+ }
+-int chalresp_avp (struct tunnel *t, struct call *c, void *data, int datalen)
++/*****************************************************************************/
++int chalresp_avp (struct tunnel *t, struct call *c, void *data, int avplen)
+ {
+-    /*
+-     * We are sent a challenge
+-     */
+-    _u16 *raw = data;
+-    int size;
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case SCCRP:
+-        case SCCCN:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: challenge response not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen < 6)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "challenge", 6, datalen, 1);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    size = raw[0] & 0x0FFF;
+-    size -= sizeof (struct avp_hdr);
+-    if (size != MD_SIG_SIZE)
+-    {
+-        log (LOG_DEBUG, "%s: Challenge is not the right length (%d != %d)\n",
+-             __FUNCTION__, size, MD_SIG_SIZE);
+-        return -EINVAL;
+-    }
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-    bcopy (&raw[3], t->chal_them.reply, MD_SIG_SIZE);
+-    if (debug_avp)
+-    {
+-        log (LOG_DEBUG, "%s: Challenge reply found\n", __FUNCTION__);
+-    }
++    memcpy(t->chal_them.reply, p, MD_SIG_SIZE);
++    if(debug_avp)
++      log(LOG_DEBUG, "%s: Challenge reply found\n", __func__);
+     return 0;
+ }
++/*****************************************************************************/
+ int assigned_tunnel_avp (struct tunnel *t, struct call *c, void *data,
+-                         int datalen)
++                         int avplen)
+ {
+-    /*
+-     * What is their TID that we must use from now on?
+-     */
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      u_int16_t id = get16(p);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case SCCRP:
+-        case SCCRQ:
+-        case StopCCN:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: tunnel ID not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 8)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is wrong size.  %d != 8\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Assigned Tunnel ID", 8, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+     if (c->msgtype == StopCCN)
+-    {
+-        t->qtid = ntohs (raw[3]);
+-    }
++        t->qtid = id;
+     else
+-    {
+-        t->tid = ntohs (raw[3]);
+-    }
++        t->tid = id;
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: using peer's tunnel %d\n", __FUNCTION__,
+-                 ntohs (raw[3]));
+-    }
++      log (LOG_DEBUG, "%s: using peer's tunnel %d\n", __func__, id);
+     return 0;
+ }
+-int assigned_call_avp (struct tunnel *t, struct call *c, void *data,
+-                       int datalen)
++/*****************************************************************************/
++int assigned_session_avp (struct tunnel *t, struct call *c, void *data,
++                       int avplen)
+ {
+-    /*
+-     * What is their CID that we must use from now on?
+-     */
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
++      u_int16_t id = get16(p);
++
++      switch(c->msgtype) {
++              case CDN:
++              case ICRP:
++              case OCRP:
++                      c->cid = id;
++                      break;
++              case ICRQ:
++                      t->call_head->cid = id;
++                      break;
++      };
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case CDN:
+-        case ICRP:
+-        case ICRQ:
+-        case OCRP:             /* jz: deleting the debug message */
+-            break;
+-        case OCRQ:
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: call ID not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 8)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is wrong size.  %d != 8\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Assigned Call ID", 8, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    if (c->msgtype == CDN)
+-    {
+-        c->qcid = ntohs (raw[3]);
+-    }
+-    else if (c->msgtype == ICRQ)
+-    {
+-        t->call_head->cid = ntohs (raw[3]);
+-    }
+-    else if (c->msgtype == ICRP)
+-    {
+-        c->cid = ntohs (raw[3]);
+-    }
+-    else if (c->msgtype == OCRP)
+-    {                           /* jz: copy callid to c->cid */
+-        c->cid = ntohs (raw[3]);
+-    }
+-    else
+-    {
+-        log (LOG_DEBUG, "%s:  Dunno what to do when it's state %s!\n",
+-             __FUNCTION__, msgtypes[c->msgtype]);
+-    }
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: using peer's call %d\n", __FUNCTION__, ntohs (raw[3]));
+-    }
++      log (LOG_DEBUG, "%s: assigned session id: %d\n", __func__, id);
+     return 0;
+ }
++/*****************************************************************************/
+ int packet_delay_avp (struct tunnel *t, struct call *c, void *data,
+-                      int datalen)
++                      int avplen)
+ {
+-    /*
+-     * What is their CID that we must use from now on?
+-     */
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case ICRP:
+-        case OCRQ:
+-        case ICCN:
+-        case OCRP:
+-        case OCCN:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: packet delay not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 8)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is wrong size.  %d != 8\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Assigned Call ID", 8, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    c->ppd = ntohs (raw[3]);
++    c->ppd = get16(p);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer's delay is %d 1/10's of a second\n", __FUNCTION__,
+-                 ntohs (raw[3]));
+-    }
++      log (LOG_DEBUG, "%s: peer's delay is %d 1/10's of a second\n", __func__,
++             c->ppd);
+     return 0;
+ }
+-int call_serno_avp (struct tunnel *t, struct call *c, void *data, int datalen)
++/*****************************************************************************/
++int call_serno_avp (struct tunnel *t, struct call *c, void *data, int avplen)
+ {
+     /*
+      * What is the serial number of the call?
+      */
+-    _u16 *raw = data;
+-
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case ICRQ:
+-        case OCRQ:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: call ID not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 10)
+-        {
+-#ifdef STRICT
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is wrong size.  %d != 10\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Serial Number", 10, datalen, 0);
+-            return -EINVAL;
+-#else
+-            log (LOG_DEBUG,
+-                 "%s: peer is using old style serial number.  Will be invalid.\n",
+-                 __FUNCTION__);
+-#endif
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-        }
+-    }
+-#endif
+-    t->call_head->serno = (((unsigned int) ntohs (raw[3])) << 16) |
+-        ((unsigned int) ntohs (raw[4]));
++    t->call_head->serno = get32(p);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: serial number is %d\n", __FUNCTION__,
+-                 t->call_head->serno);
+-    }
++      log (LOG_DEBUG, "%s: serial number is %d\n", __func__, 
++                       t->call_head->serno);
+     return 0;
+ }
+-int rx_speed_avp (struct tunnel *t, struct call *c, void *data, int datalen)
++/*****************************************************************************/
++int rx_speed_avp (struct tunnel *t, struct call *c, void *data, int avplen)
+ {
+-    /*
+-     * What is the received baud rate of the call?
+-     */
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case ICCN:
+-        case OCCN:
+-        case OCRP:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: rx connect speed not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 10)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is wrong size.  %d != 10\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Connect Speed (RX)", 10, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    c->rxspeed = (((unsigned int) ntohs (raw[3])) << 16) |
+-        ((unsigned int) ntohs (raw[4]));
+-    if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: receive baud rate is %d\n", __FUNCTION__, c->rxspeed);
+-    }
++    c->rxspeed = get32(p);
++    if(debug_avp)
++      log(LOG_DEBUG, "%s: receive baud rate is %d\n", __func__, c->rxspeed);
+     return 0;
+ }
+-int tx_speed_avp (struct tunnel *t, struct call *c, void *data, int datalen)
++/*****************************************************************************/
++int tx_speed_avp (struct tunnel *t, struct call *c, void *data, int avplen)
+ {
+-    /*
+-     * What is the tranmsit baud rate of the call?
+-     */
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case ICCN:
+-        case OCCN:
+-        case OCRP:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: tx connect speed not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 10)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is wrong size.  %d != 10\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Connect Speed (tx)", 10, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    c->txspeed = (((unsigned int) ntohs (raw[3])) << 16) |
+-        ((unsigned int) ntohs (raw[4]));
++    c->txspeed = get32(p);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: transmit baud rate is %d\n", __FUNCTION__, c->txspeed);
+-    }
++      log (LOG_DEBUG, "%s: transmit baud rate is %d\n", 
++                       __func__, c->txspeed);
+     return 0;
+ }
++
++/*****************************************************************************/
+ int call_physchan_avp (struct tunnel *t, struct call *c, void *data,
+-                       int datalen)
++                       int avplen)
+ {
+-    /*
+-     * What is the physical channel?
+-     */
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case ICRQ:
+-        case OCRQ:
+-        case OCRP:
+-        case OCCN:
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: physical channel not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 10)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is wrong size.  %d != 10\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Physical Channel", 10, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    t->call_head->physchan = (((unsigned int) ntohs (raw[3])) << 16) |
+-        ((unsigned int) ntohs (raw[4]));
++    t->call_head->physchan = get32(p);
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: physical channel is %d\n", __FUNCTION__,
+-                 t->call_head->physchan);
+-    }
++      log(LOG_DEBUG, "%s: physical channel is %d\n", __func__,
++                      t->call_head->physchan);
+     return 0;
+ }
++/*****************************************************************************/
+ int receive_window_size_avp (struct tunnel *t, struct call *c, void *data,
+-                             int datalen)
++                             int avplen)
+ {
+-    /*
+-     * What is their RWS?
+-     */
+-    _u16 *raw = data;
++      u_int8_t *p = data + sizeof(struct avp_hdr);
+-#ifdef SANITY
+-    if (t->sanity)
+-    {
+-        switch (c->msgtype)
+-        {
+-        case SCCRP:
+-        case SCCRQ:
+-        case OCRP:             /* jz */
+-        case OCCN:             /* jz */
+-        case StopCCN:
+-/*            case ICRP:
+-              case ICCN: */
+-            break;
+-        default:
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: RWS not appropriate for message %s.  Ignoring.\n",
+-                     __FUNCTION__, msgtypes[c->msgtype]);
+-            return 0;
+-        }
+-        if (datalen != 8)
+-        {
+-            if (DEBUG)
+-                log (LOG_DEBUG,
+-                     "%s: avp is wrong size.  %d != 8\n", __FUNCTION__,
+-                     datalen);
+-            wrong_length (c, "Receive Window Size", 8, datalen, 0);
+-            return -EINVAL;
+-        }
+-    }
+-#endif
+-    t->rws = ntohs (raw[3]);
++    t->rws = get16(p);
+ /*    if (c->rws >= 0)
+               c->fbit = FBIT; */
+     if (debug_avp)
+-    {
+-        if (DEBUG)
+-            log (LOG_DEBUG,
+-                 "%s: peer wants RWS of %d.  Will use flow control.\n",
+-                 __FUNCTION__, t->rws);
+-    }
++              log (LOG_DEBUG, "%s: peer wants RWS of %d.  Will use flow control.\n",
++             __func__, t->rws);
+     return 0;
+ }
++/*****************************************************************************/
+ int handle_avps (struct buffer *buf, struct tunnel *t, struct call *c)
+ {
+     /*
+@@ -1594,82 +770,100 @@
+     struct avp_hdr *avp;
+     int len = buf->len - sizeof (struct control_hdr);
++      u_int16_t rlen = 0;
++      u_int16_t attr = 0;
+     int firstavp = -1;
+-    int hidlen;
++    int hidlen = 0;
+     char *data = buf->start + sizeof (struct control_hdr);
+     avp = (struct avp_hdr *) data;
++
+     if (debug_avp)
+         log (LOG_DEBUG, "%s: handling avp's for tunnel %d, call %d\n",
+-             __FUNCTION__, t->ourtid, c->ourcid);
++             __func__, t->ourtid, c->ourcid);
++
++      if(len < 6) {
++      log (LOG_WARN, "%s: packet too small\n", __func__);
++        set_error(c, ERROR_LENGTH, "Invalid message length");
++        return -EINVAL;
++      }
++
+     while (len > 0)
+     {
+-        /* Go ahead and byte-swap the header */
+-        swaps (avp, sizeof (struct avp_hdr));
+-        if (avp->attr > AVP_MAX)
++              rlen = get16((u_int8_t*)&avp->length);
++              attr = get16((u_int8_t*)&avp->attr);
++
++              /* AVP header checks */
++        if (attr > AVP_MAX)
+         {
+-            if (AMBIT (avp->length))
++            if (AMBIT(rlen))
+             {
+                 log (LOG_WARN,
+-                     "%s:  dont know how to handle mandatory attribute %d.  Closing %s.\n"
+-                     __FUNCTION__, avp->attr,
+-                     (c != t->self) ? "call" : "tunnel");
+-                set_error (c, VENDOR_ERROR,
+-                           "mandatory attribute %d cannot be handled",
+-                           avp->attr);
+-                c->needclose = -1;
++                     "%s:  unhandeled mandatory attribute %d.  Closing %s.\n", 
++                     __func__, attr, (c != t->self) ? "call" : "tunnel");
++                set_error (c, VENDOR_ERROR, 
++                                                 "mandatory attribute %d cannot be handled", attr);
+                 return -EINVAL;
+             }
+             else
+             {
+                 if (DEBUG)
+                     log (LOG_WARN,
+-                         "%s:  dont know how to handle atribute %d.\n",
+-                         __FUNCTION__, avp->attr);
++                         "%s: handeled attribute %d.\n",
++                         __func__, attr);
+                 goto next;
+             }
+         }
+-        if (ALENGTH (avp->length) > len)
++        if (ALENGTH (rlen) > len)
+         {
+             log (LOG_WARN,
+-                 "%s: AVP received with length > remaining packet length!\n",
+-                 __FUNCTION__);
++                 "%s: AVP reported length > remaining packet length\n",
++                 __func__);
+             set_error (c, ERROR_LENGTH, "Invalid AVP length");
+-            c->needclose = -1;
+             return -EINVAL;
+         }
+-        if (avp->attr && firstavp)
++              if (ALENGTH (rlen) < sizeof (struct avp_hdr))
+         {
+-            log (LOG_WARN, "%s: First AVP was not message type.\n",
+-                 __FUNCTION__);
+-            set_error (c, VENDOR_ERROR, "First AVP must be message type");
+-            c->needclose = -1;
++            log (LOG_WARN, "%s: AVP reported length too small (%d).\n",
++                 __func__, ALENGTH (rlen));
++            set_error (c, ERROR_LENGTH, "AVP too small");
+             return -EINVAL;
+         }
+-        if (ALENGTH (avp->length) < sizeof (struct avp_hdr))
++              if (avps[attr].sz) {
++                      if((avps[attr].flags & AVP_F_FIXLEN) ?  
++                         (ALENGTH(rlen) - sizeof(struct avp_hdr)) != avps[attr].sz :
++                         (ALENGTH(rlen) - sizeof(struct avp_hdr)) > avps[attr].sz) {
++                              log (LOG_DEBUG, "%s: %s avp size mismatch  (%d %s %d)\n", 
++                                      __func__,
++                                      avps[attr].description, 
++                                      (avps[attr].flags & AVP_F_FIXLEN) ? "!=" : "<", 
++                                      ALENGTH(rlen), avps[attr].sz);
++                              set_error (c, ERROR_LENGTH, "AVP size check failed");
++                              return -EINVAL;
++                      }
++              }
++        if (attr && firstavp)
+         {
+-            log (LOG_WARN, "%s: AVP with too small of size (%d).\n",
+-                 __FUNCTION__, ALENGTH (avp->length));
+-            set_error (c, ERROR_LENGTH, "AVP too small");
+-            c->needclose = -1;
++            log (LOG_WARN, "%s: First AVP was not message type.\n",
++                 __func__);
++            set_error (c, VENDOR_ERROR, "First AVP must be message type");
+             return -EINVAL;
+         }
+-        if (AZBITS (avp->length))
++        if (AZBITS (rlen))
+         {
+-            log (LOG_WARN, "%s: %sAVP has reserved bits set.\n", __FUNCTION__,
+-                 AMBIT (avp->length) ? "Mandatory " : "");
+-            if (AMBIT (avp->length))
++            log (LOG_WARN, "%s: %sAVP has reserved bits set.\n", __func__,
++                 AMBIT (rlen) ? "Mandatory " : "");
++            if (AMBIT (rlen))
+             {
+                 set_error (c, ERROR_RESERVED, "reserved bits set in AVP");
+-                c->needclose = -1;
+                 return -EINVAL;
+             }
+             goto next;
+         }
+-        if (AHBIT (avp->length))
++
++              /* decryption */
++        if (AHBIT (rlen))
+         {
+-#ifdef DEBUG_HIDDEN
+-            log (LOG_DEBUG, "%s: Hidden bit set on AVP.\n", __FUNCTION__);
+-#endif
++            log (LOG_DEBUG, "%s: Hidden bit set on AVP.\n", __func__);
+             /* We want to rewrite the AVP as an unhidden AVP
+                and then pass it along as normal.  Remeber how
+                long the AVP was in the first place though! */
+@@ -1678,12 +872,11 @@
+             {
+                 if (debug_avp)
+                     log (LOG_WARN, "%s: Unable to handle hidden %sAVP\n:",
+-                         __FUNCTION__,
+-                         (AMBIT (avp->length) ? "mandatory " : ""));
+-                if (AMBIT (avp->length))
++                         __func__,
++                         (AMBIT (rlen) ? "mandatory " : ""));
++                if (AMBIT (rlen))
+                 {
+                     set_error (c, VENDOR_ERROR, "Invalid Hidden AVP");
+-                    c->needclose = -1;
+                     return -EINVAL;
+                 }
+                 goto next;
+@@ -1696,17 +889,43 @@
+         }
+         else
+             hidlen = 0;
+-        if (avps[avp->attr].handler)
++
++              /* validate */
++              if (avps[attr].validate) 
++              {
++                      if(avps[attr].validate(attr, t, c, avp, ALENGTH (rlen))) {
++                               if (AMBIT (rlen))
++                {
++                    log (LOG_WARN,
++                         "%s: verification of AVP %d (%s) failed.\n",
++                         __func__, attr,
++                         avps[attr].description);
++                                      set_error (c, VENDOR_ERROR, "processing failed on mandatory AVP");
++                    return -EINVAL;
++                }
++                else
++                {
++                    if (DEBUG)
++                        log (LOG_DEBUG,
++                             "%s: Bad exit status handling attribute %d (%s).\n",
++                             __func__, attr,
++                             avps[attr].description);
++                }
++                      }
++              }
++
++              /* handling */
++        if (avps[attr].handle)
+         {
+-            if (avps[avp->attr].handler (t, c, avp, ALENGTH (avp->length)))
++            if (avps[attr].handle(t, c, avp, ALENGTH (rlen)))
+             {
+-                if (AMBIT (avp->length))
++                if (AMBIT (rlen))
+                 {
+                     log (LOG_WARN,
+-                         "%s: Bad exit status handling attribute %d (%s) on mandatory packet.\n",
+-                         __FUNCTION__, avp->attr,
+-                         avps[avp->attr].description);
+-                    c->needclose = -1;
++                         "%s: Bad exit status handling mandatory attribute %d (%s).\n",
++                         __func__, attr,
++                         avps[attr].description);
++                                      set_error (c, VENDOR_ERROR, "processing failed on mandatory AVP");
+                     return -EINVAL;
+                 }
+                 else
+@@ -1714,29 +933,31 @@
+                     if (DEBUG)
+                         log (LOG_DEBUG,
+                              "%s: Bad exit status handling attribute %d (%s).\n",
+-                             __FUNCTION__, avp->attr,
+-                             avps[avp->attr].description);
++                             __func__, attr,
++                             avps[attr].description);
+                 }
+             }
+         }
+         else
+         {
+-            if (AMBIT (avp->length))
++            if (AMBIT (rlen))
+             {
+                 log (LOG_WARN,
+                      "%s:  No handler for mandatory attribute %d (%s).  Closing %s.\n",
+-                     __FUNCTION__, avp->attr, avps[avp->attr].description,
++                     __func__, attr, 
++                                       avps[attr].description,
+                      (c != t->self) ? "call" : "tunnel");
+                 set_error (c, VENDOR_ERROR, "No handler for attr %d (%s)\n",
+-                           avp->attr, avps[avp->attr].description);
++                           attr, 
++                                                 avps[attr].description);
+                 return -EINVAL;
+             }
+             else
+             {
+                 if (DEBUG)
+                     log (LOG_WARN, "%s:  no handler for atribute %d (%s).\n",
+-                         __FUNCTION__, avp->attr,
+-                         avps[avp->attr].description);
++                         __func__, attr,
++                         avps[attr].description);
+             }
+         }
+       next:
+@@ -1748,16 +969,17 @@
+         }
+         else
+         {
+-            len -= ALENGTH (avp->length);
+-            data += ALENGTH (avp->length);      /* Next AVP, please */
++            len -= ALENGTH (rlen);
++            data += ALENGTH (rlen);      /* Next AVP, please */
+         }
+         avp = (struct avp_hdr *) data;
+         firstavp = 0;
+     }
+     if (len != 0)
+     {
+-        log (LOG_WARN, "%s: negative overall packet length\n", __FUNCTION__);
++        log (LOG_WARN, "%s: negative overall packet length\n", __func__);
+         return -EINVAL;
+     }
++
+     return 0;
+ }
+--- l2tpd-0.70-pre20031121.orig/avpsend.c
++++ l2tpd-0.70-pre20031121/avpsend.c
+@@ -1,11 +1,5 @@
+ /*
+- * $Id$
+- *
+- * Layer Two Tunnelling Protocol Daemon
+- * Copyright (C) 1998 Adtran, Inc.
+- * Copyright (C) 2002 Jeff McAdams
+- *
+- * Mark Spencer
++ * Copyright (C) 2004 Jean-Francois Dive
+  *
+  * This software is distributed under the terms
+  * of the GPL, which you should have received
+@@ -14,337 +8,288 @@
+  * Attribute Value Pair creating routines
+  */
++/* TODO: Handle Tie break */
++/* TODO: Get real hostname / config */
++/* TODO: There should be an overflow check on
++ *             the buffer size. (safe for now as 
++ *             packet size = 4k
++ */
++
+ #include <stdlib.h>
+ #include <string.h>
+-#include <netinet/in.h>
++#include <unistd.h>
+ #include "l2tp.h"
+-/* 
+- * These routines should add avp's to a buffer
+- * to be sent
+- */
++extern struct avp avps[];
++/* We could add here padding support which would allow
++ * to keep alignemnt straight <jdive> */
++static int add_avp(struct buffer *buf, u_int32_t avpid, unsigned char *v, 
++                             u_int32_t sz, u_int8_t setpayload) {
++      u_int8_t *p = buf->start + buf->len;
++
++      if(avpid > AVP_MAX  || !avps[avpid].flags) {
++              log(LOG_DEBUG, "%s: invalid avp id %d\n", __func__, avpid);
++              return 1;
++      }
++
++      set16(p, (sz + 6) | (avps[avpid].flags & AVP_F_MANDATORY ? MBIT : 0));
++      set16(p + 2, VENDOR_ID);
++      set16(p + 4, avpid);
++      if(setpayload) 
++              memcpy(p + 6, v, sz);
+-/* FIXME:  If SANITY is on, we should check for buffer overruns */
++      buf->len += (sz + 6);
++      return 0;
++}
+-/* FIXME: Can't this be condensed alot? */
++/*****************************************************************************/
++int add_message_type_avp(struct buffer *buf, _u16 type) {
++      u_int8_t t[2];
++      set16(t, type);
++      if(add_avp(buf, MESSAGE_TYPE_AVP, t, 2, 1))
++              return 1;
++    return 0;
++}
+-int add_message_type_avp (struct buffer *buf, _u16 type)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0x8 | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = 0;
+-    raw[3] = htons (type);
+-    buf->len += 8;
++/*****************************************************************************/
++int add_protocol_avp(struct buffer *buf) {
++      u_int8_t t[2];
++      set16(t, OUR_L2TP_VERSION);
++      if(add_avp(buf, PROTOCOL_VERSION_AVP, t, 2, 1))
++              return 1;
+     return 0;
+ }
+-int add_protocol_avp (struct buffer *buf)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0x8 | MBIT);        /* Length and M bit */
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x2);       /* Value of our AVP */
+-    raw[3] = htons (OUR_L2TP_VERSION);
+-    buf->len += 8;
++/*****************************************************************************/
++int add_frame_caps_avp(struct buffer *buf, _u16 caps) {
++      u_int8_t t[4];
++      t[0] = 0; 
++      t[1] = 0;
++      set16(&t[2], caps);
++      if(add_avp(buf, FRAMING_CAP_AVP, t, 4, 1))
++              return 1;
+     return 0;
+ }
+-int add_frame_caps_avp (struct buffer *buf, _u16 caps)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0xA | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x3);
+-    raw[3] = 0;
+-    raw[4] = htons (caps);
+-    buf->len += 10;
++/*****************************************************************************/
++int add_bearer_caps_avp(struct buffer *buf, _u16 caps) {
++      u_int8_t t[4];
++      t[0] = 0; 
++      t[1] = 0;
++      set16(&t[2], caps);
++      if(add_avp(buf, BEARER_CAP_AVP, t, 4, 1))
++              return 1;
+     return 0;
+ }
+-int add_bearer_caps_avp (struct buffer *buf, _u16 caps)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0xA | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x4);
+-    raw[3] = 0;
+-    raw[4] = htons (caps);
+-    buf->len += 10;
++/*****************************************************************************/
++int add_firmware_avp(struct buffer *buf) {
++      u_int8_t t[2];
++      set16(t, OUR_L2TP_VERSION);
++      if(add_avp(buf, FIRMWARE_REV_AVP, t, 2, 1))
++              return 1;
+     return 0;
+ }
+-/* FIXME: I need to send tie breaker AVP's */
+-
+-int add_firmware_avp (struct buffer *buf)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0x8);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x6);
+-    raw[3] = htons (FIRMWARE_REV);
+-    buf->len += 8;
++/*****************************************************************************/
++int add_hostname_avp(struct buffer *buf, struct tunnel *t) {
++      char n[STRLEN];
++      int sz = 0;
++      if(t->lac && t->lac->hostname[0]) {
++              strncpy(n,t->lac->hostname, sizeof(n));
++              sz = strnlen(t->lac->hostname, sizeof(t->lac->hostname));
++      }
++      else if(t->lns && t->lns->hostname[0]) {
++              strncpy(n,t->lns->hostname, sizeof(n));
++              sz = strnlen(t->lns->hostname, sizeof(t->lns->hostname));
++      }
++      else {
++              if(gethostname(n, STRLEN)) {
++                      strcpy(n,"eriwan");
++                      sz = 6;
++              }
++              else
++                      sz = strnlen(n, sizeof(n));
++      }
++      if(add_avp(buf, HOSTNAME_AVP, n, sz, 1))
++              return 1;
+     return 0;
+ }
+-/*
+-int add_hostname_avp(struct buffer *buf) {
+-      _u16 *raw = (_u16 *)(buf->start + buf->len);
+-      raw[0] = htons((0x6 + strlen(hostname)) | MBIT);
+-      raw[1] = htons(VENDOR_ID);
+-      raw[2] = htons(0x7);
+-      strcpy((char *)(&raw[3]), hostname);
+-      buf->len += 6 + strlen(hostname);
+-      return 0;
++/*****************************************************************************/
++int add_vendor_avp(struct buffer *buf) {
++      if(add_avp(buf, VENDOR_NAME_AVP, VENDOR_NAME, strlen(VENDOR_NAME), 1))
++              return 1;
++    return 0;
+ }
+-*/
+-int add_hostname_avp (struct buffer *buf)
+-{
+-    char names[6] = "eriwan";
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0xC | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x7);
+-    strcpy ((char *) (&raw[3]), names);
+-    buf->len += 12;
+-    return 0;
+-}
+-
+-int add_vendor_avp (struct buffer *buf)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0x6 + strlen (VENDOR_NAME));
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x8);
+-    strcpy ((char *) (&raw[3]), VENDOR_NAME);
+-    buf->len += 6 + strlen (VENDOR_NAME);
+-    return 0;
+-}
+-
+-int add_tunnelid_avp (struct buffer *buf, _u16 tid)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0x8 | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x9);
+-    raw[3] = htons (tid);
+-    buf->len += 8;
+-    return 0;
+-}
+-
+-int add_avp_rws (struct buffer *buf, _u16 rws)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0x8 | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0xA);
+-    raw[3] = htons (rws);
+-    buf->len += 8;
+-    return 0;
+-}
+-
+-int add_challenge_avp (struct buffer *buf, char *c, int len)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons ((0x6 + len) | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0xB);
+-    bcopy (c, (char *) (&raw[3]), len);
+-    buf->len += 6 + len;
+-    return 0;
+-}
+-
+-int add_chalresp_avp (struct buffer *buf, char *c, int len)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons ((0x6 + len) | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0xD);
+-    bcopy (c, (char *) (&raw[3]), len);
+-    buf->len += 6 + len;
+-    return 0;
+-}
+-
+-int add_randvect_avp (struct buffer *buf, char *c, int len)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons ((0x6 + len) | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x24);
+-    bcopy (c, (char *) (&raw[3]), len);
+-    buf->len += 6 + len;
+-    return 0;
+-}
+-
+-int add_result_code_avp (struct buffer *buf, _u16 result, _u16 error,
+-                         char *msg, int len)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons ((0xA + len) | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x1);
+-    raw[3] = htons (result);
+-    raw[4] = htons (error);
+-    bcopy (msg, (char *) &raw[5], len);
+-    buf->len += (10 + len);
++/*****************************************************************************/
++int add_tunnelid_avp(struct buffer *buf, _u16 tid) {
++      u_int8_t t[2];
++      set16(t, tid);
++      if(add_avp(buf, ASSIGNED_TUN_ID_AVP, t, 2, 1))
++              return 1;
+     return 0;
+ }
++/*****************************************************************************/
++int add_avp_rws(struct buffer *buf, _u16 rws) {
++      u_int8_t t[2];
++      set16(t, rws);
++      if(add_avp(buf, RX_WIN_SIZE_AVP, t, 2, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_challenge_avp(struct buffer *buf, char *c, int len) {
++      if(add_avp(buf, CHALLENGE_AVP, c, len, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_chalresp_avp(struct buffer *buf, char *c, int len) {
++      if(add_avp(buf, CHALLENGE_RESP_AVP, c, len, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_randvect_avp(struct buffer *buf, char *c, int len) {
++      if(add_avp(buf, RANDOM_VECTOR_AVP, c, len, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_result_code_avp(struct buffer *buf, _u16 result, _u16 error,
++                        char *msg, int len) {
++      u_int8_t t[4];
++      set16(t, result);
++      set16(&t[2], error);
++      memcpy((u_int8_t*)(buf->start + buf->len + 10), msg, len);
++      memcpy((u_int8_t*)(buf->start + buf->len + 6), t, 4);
++      if(add_avp(buf, RESULT_CODE_AVP, 0, 4 + len, 0))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
+ #ifdef TEST_HIDDEN
+-int add_callid_avp (struct buffer *buf, _u16 callid, struct tunnel *t)
+-{
+-#else
+-int add_callid_avp (struct buffer *buf, _u16 callid)
+-{
+-#endif
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-#ifdef TEST_HIDDEN
++int add_callid_avp(struct buffer *buf, _u16 callid, struct tunnel *t) {
++      u_int8_t t[2];
+     if (t->hbit)
+         raw++;
+-#endif
+-    raw[0] = htons (0x8 | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0xE);
+-    raw[3] = htons (callid);
+-    buf->len += 8;
+-#ifdef TEST_HIDDEN
++      set16(t, callid);
++      if(add_avp(buf, ASSIGNED_SES_ID_AVP, t, 2, 1))
++              return 1;
+     if (t->hbit)
+         encrypt_avp (buf, 8, t);
++    return 0;
++}
++#else
++int add_callid_avp(struct buffer *buf, _u16 callid) {
++      u_int8_t t[2];
++      set16(t, callid);
++      if(add_avp(buf, ASSIGNED_SES_ID_AVP, t, 2, 1))
++              return 1;
++    return 0;
++}
+ #endif
++
++/*****************************************************************************/
++int add_serno_avp(struct buffer *buf, unsigned int serno) {
++      u_int8_t t[4];
++      set32(t, serno);
++      if(add_avp(buf, SERIAL_NUMBER_AVP, t, 4, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_bearer_avp(struct buffer *buf, int bearer) {
++      u_int8_t t[4];
++      set32(t, bearer);
++      if(add_avp(buf, BEARER_TYPE_AVP, t, 4, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_frame_avp(struct buffer *buf, int frame) {
++      u_int8_t t[4];
++      set32(t, frame);
++      if(add_avp(buf, FRAMING_TYPE_AVP, t, 4, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_txspeed_avp(struct buffer *buf, int speed) {
++      u_int8_t t[4];
++      set32(t, speed);
++      if(add_avp(buf, TX_CONNECT_SPEED_AVP, t, 4, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_rxspeed_avp(struct buffer *buf, int speed) {
++      u_int8_t t[4];
++      set32(t, speed);
++      if(add_avp(buf, RX_CONNECT_SPEED_AVP, t, 4, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_physchan_avp(struct buffer *buf, unsigned int physchan) {
++      u_int8_t t[4];
++      set32(t, physchan);
++      if(add_avp(buf, PHYS_CHAN_ID_AVP, t, 4, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_ppd_avp(struct buffer *buf, _u16 ppd) {
++      u_int8_t t[2];
++      set16(t, ppd);
++      if(add_avp(buf, PACKET_DELAY_AVP, t, 2, 1))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_seqreqd_avp(struct buffer *buf) {
++      if(add_avp(buf, SEQ_REQUIRED_AVP, 0, 0, 0))
++              return 1;
++    return 0;
++}
++
++/*****************************************************************************/
++int add_minbps_avp(struct buffer *buf, int speed) {
++      u_int8_t t[4];
++      set32(t, speed);
++      if(add_avp(buf, MIN_BPS_AVP, t, 4, 1))
++              return 1;
+     return 0;
+ }
+-int add_serno_avp (struct buffer *buf, unsigned int serno)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0xA | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0xF);
+-    raw[3] = htons ((serno >> 16) & 0xFFFF);
+-    raw[4] = htons (serno & 0xFFFF);
+-    buf->len += 10;
+-    return 0;
+-}
+-
+-int add_bearer_avp (struct buffer *buf, int bearer)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0xA | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x12);
+-    raw[3] = htons ((bearer >> 16) & 0xFFFF);
+-    raw[4] = htons (bearer & 0xFFFF);
+-    buf->len += 10;
+-    return 0;
+-}
+-
+-int add_frame_avp (struct buffer *buf, int frame)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0xA | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x13);
+-    raw[3] = htons ((frame >> 16) & 0xFFFF);
+-    raw[4] = htons (frame & 0xFFFF);
+-    buf->len += 10;
+-    return 0;
+-}
+-
+-int add_txspeed_avp (struct buffer *buf, int speed)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0xA | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x18);
+-    raw[3] = htons ((speed >> 16) & 0xFFFF);
+-    raw[4] = htons (speed & 0xFFFF);
+-    buf->len += 10;
+-    return 0;
+-}
+-
+-int add_rxspeed_avp (struct buffer *buf, int speed)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0xA | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x26);
+-    raw[3] = htons ((speed >> 16) & 0xFFFF);
+-    raw[4] = htons (speed & 0xFFFF);
+-    buf->len += 10;
+-    return 0;
+-}
+-
+-int add_physchan_avp (struct buffer *buf, unsigned int physchan)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0x8 | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x19);
+-    raw[3] = htons ((physchan >> 16) & 0xFFFF);
+-    raw[4] = htons (physchan & 0xFFFF);
+-    buf->len += 10;
+-    return 0;
+-}
+-
+-int add_ppd_avp (struct buffer *buf, _u16 ppd)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0x8 | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x14);
+-    raw[3] = htons (ppd);
+-    buf->len += 8;
+-    return 0;
+-}
+-
+-int add_seqreqd_avp (struct buffer *buf)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0x6 | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x27);
+-    buf->len += 6;
+-    return 0;
+-}
+-
+-/* jz: options dor the outgoing call */
+-
+-/* jz: Minimum BPS - 16 */
+-int add_minbps_avp (struct buffer *buf, int speed)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0xA | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x10);
+-    raw[3] = htons ((speed >> 16) & 0xFFFF);
+-    raw[4] = htons (speed & 0xFFFF);
+-    buf->len += 10;
+-    return 0;
+-}
+-
+-/* jz: Maximum BPS - 17 */
+-int add_maxbps_avp (struct buffer *buf, int speed)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons (0xA | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x11);
+-    raw[3] = htons ((speed >> 16) & 0xFFFF);
+-    raw[4] = htons (speed & 0xFFFF);
+-    buf->len += 10;
+-    return 0;
+-}
+-
+-/* jz: Dialed Number 21 */
+-int add_number_avp (struct buffer *buf, char *no)
+-{
+-    _u16 *raw = (_u16 *) (buf->start + buf->len);
+-    raw[0] = htons ((0x6 + strlen (no)) | MBIT);
+-    raw[1] = htons (VENDOR_ID);
+-    raw[2] = htons (0x15);
+-    strncpy ((char *) (&(raw[3])), no, strlen (no));
+-    buf->len += 6 + strlen (no);
++/*****************************************************************************/
++int add_maxbps_avp(struct buffer *buf, int speed) {
++      u_int8_t t[4];
++      set32(t, speed);
++      if(add_avp(buf, MAX_BPS_AVP, t, 4, 1))
++              return 1;
+     return 0;
+ }
++
++/*****************************************************************************/
++int add_number_avp(struct buffer *buf, char *no) {
++      if(add_avp(buf, CALLED_NUMBER_AVP, no, strlen(no), 1))
++              return 1;
++      return 0;
++}
diff --git a/openwrt/package/l2tpd/patches/02-debian-2-pty-rev.patch b/openwrt/package/l2tpd/patches/02-debian-2-pty-rev.patch
new file mode 100644 (file)
index 0000000..135e17e
--- /dev/null
@@ -0,0 +1,21 @@
+diff -ruN l2tpd-0.70pre-old/l2tpd.c l2tpd-0.70pre-new/l2tpd.c
+--- l2tpd-0.70pre-old/l2tpd.c  2005-12-16 12:02:02.000000000 +0100
++++ l2tpd-0.70pre-new/l2tpd.c  2005-12-16 12:14:24.000000000 +0100
+@@ -336,17 +336,10 @@
+         tcgetattr (c->fd, &ptyconf);
+         *(c->oldptyconf) = ptyconf;
+         ptyconf.c_cflag &= ~(ICANON | ECHO);
+-              ptyconf.c_lflag &= ~ECHO;
+         tcsetattr (c->fd, TCSANOW, &ptyconf);
+         snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b);
+         fd2 = open (tty, O_RDWR);
+-              if(!fd2)
+-                      log(LOG_WARN, "unable to open tty %s", tty);
+-
+-              /* XXX JEF: CHECK ME */
+-              stropt[pos++] = strdup(tty);
+-              stropt[pos] = NULL;
+ #ifdef USE_KERNEL
+     }
diff --git a/openwrt/package/l2tpd/patches/03-jacco-pty.patch b/openwrt/package/l2tpd/patches/03-jacco-pty.patch
new file mode 100644 (file)
index 0000000..67169b8
--- /dev/null
@@ -0,0 +1,1194 @@
+diff -ruN l2tpd-0.70pre-old/l2tpd.c l2tpd-0.70pre-new/l2tpd.c
+--- l2tpd-0.70pre-old/l2tpd.c  2005-12-16 12:34:12.000000000 +0100
++++ l2tpd-0.70pre-new/l2tpd.c  2005-12-16 12:34:54.000000000 +0100
+@@ -16,6 +16,7 @@
+  */
+ #include <stdlib.h>
++#include <sys/types.h>
+ #include <sys/utsname.h>
+ #include <sys/stat.h>
+ #include <sys/wait.h>
+@@ -274,8 +275,8 @@
+ int start_pppd (struct call *c, struct ppp_opts *opts)
+ {
+-    char a, b;
+-    char tty[80];
++    /* char a, b; */
++    char *tty;
+     char *stropt[80];
+     struct ppp_opts *p;
+ #ifdef USE_KERNEL
+@@ -324,12 +325,45 @@
+     else
+     {
+ #endif
+-        if ((c->fd = getPtyMaster (&a, &b)) < 0)
++      c->fd = open("/dev/ptmx", O_RDWR);
++      if (c->fd == -1)
++      {
++              log (LOG_WARN, "%s: unable to open /dev/ptmx to allocate pty\n",
++                              __FUNCTION__);
++              return -EINVAL;
++      } else
++      {
++          if (grantpt(c->fd))
++          {
++              log (LOG_WARN, "%s: unable to grantpt() on pty\n",
++                              __FUNCTION__);
++              close(c->fd);
++              return -EINVAL;
++          }
++          if (unlockpt(c->fd))
++          {
++              log (LOG_WARN, "%s: unable to unlockpt() on pty\n",
++                      __FUNCTION__);
++              close(c->fd);
++              return -EINVAL;
++          }
++          tty = ptsname(c->fd);
++          if (tty == NULL)
++          {
++              log (LOG_WARN, "%s: unable to obtain name of slave tty\n",
++                      __FUNCTION__);
++              close(c->fd);
++              return -EINVAL;
++          }
++      }
++      
++      
++ /*   if ((c->fd = getPtyMaster (&a, &b)) < 0)
+         {
+             log (LOG_WARN, "%s: unable to allocate pty, abandoning!\n",
+                  __FUNCTION__);
+             return -EINVAL;
+-        }
++        } */
+         /* set fd opened above to not echo so we don't see read our own packets
+            back of the file descriptor that we just wrote them to */
+@@ -338,8 +372,14 @@
+         ptyconf.c_cflag &= ~(ICANON | ECHO);
+         tcsetattr (c->fd, TCSANOW, &ptyconf);
+-        snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b);
++/*        snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b); */
+         fd2 = open (tty, O_RDWR);
++      if (fd2 == -1)
++      {
++              log (LOG_WARN, "%s: unable to open slave tty %s\n", __FUNCTION__, tty);
++              close(c->fd);
++              return -EINVAL;
++      }
+ #ifdef USE_KERNEL
+     }
+diff -ruN l2tpd-0.70pre-old/l2tpd.c.orig l2tpd-0.70pre-new/l2tpd.c.orig
+--- l2tpd-0.70pre-old/l2tpd.c.orig     1970-01-01 01:00:00.000000000 +0100
++++ l2tpd-0.70pre-new/l2tpd.c.orig     2005-12-16 12:14:24.000000000 +0100
+@@ -0,0 +1,1104 @@
++/*
++ * $Id$
++ *
++ * Layer Two Tunnelling Protocol Daemon
++ * Copyright (C) 1998 Adtran, Inc.
++ * Copyright (C) 2002 Jeff McAdams
++ *
++ * Mark Spencer
++ *
++ * This software is distributed under the terms
++ * of the GPL, which you should have received
++ * along with this source.
++ *
++ * Main Daemon source.
++ *
++ */
++
++#include <stdlib.h>
++#include <sys/utsname.h>
++#include <sys/stat.h>
++#include <sys/wait.h>
++#include <stdio.h>
++#include <errno.h>
++#include <unistd.h>
++#include <time.h>
++#if (__GLIBC__ < 2)
++# if defined(FREEBSD)
++#  include <sys/signal.h>
++# elif defined(LINUX)
++#  include <bsd/signal.h>
++# elif defined(SOLARIS)
++#  include <signal.h>
++# endif
++#else
++# include <signal.h>
++#endif
++#include <netdb.h>
++#include <string.h>
++#include <fcntl.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#ifdef USE_KERNEL
++#include <sys/ioctl.h>
++#endif
++#include "l2tp.h"
++
++struct tunnel_list tunnels;
++int max_tunnels = DEF_MAX_TUNNELS;
++struct utsname uts;
++int ppd = 1;                    /* Packet processing delay */
++int control_fd;                 /* descriptor of control area */
++char *args;
++
++char *dial_no_tmp;              /* jz: Dialnumber for Outgoing Call */
++int switch_io = 0;              /* jz: Switch for Incoming or Outgoing Call */
++
++void init_tunnel_list (struct tunnel_list *t)
++{
++    t->head = NULL;
++    t->count = 0;
++    t->calls = 0;
++}
++
++/* Now sends to syslog instead - MvO */
++void show_status (void)
++{
++    struct schedule_entry *se;
++    struct tunnel *t;
++    struct call *c;
++    struct lns *tlns;
++    struct lac *tlac;
++    struct host *h;
++    int s = 0;
++    log (LOG_WARN, "====== l2tpd statistics ========\n");
++    log (LOG_WARN, " Scheduler entries:\n");
++    se = events;
++    while (se)
++    {
++        s++;
++        t = (struct tunnel *) se->data;
++        tlac = (struct lac *) se->data;
++        c = (struct call *) se->data;
++        if (se->func == &hello)
++        {
++            log (LOG_WARN, "%d: HELLO to %d\n", s, t->tid);
++        }
++        else if (se->func == &magic_lac_dial)
++        {
++            log (LOG_WARN, "%d: Magic dial on %s\n", s, tlac->entname);
++        }
++        else if (se->func == &send_zlb)
++        {
++            log (LOG_WARN, "%d: Send payload ZLB on call %d:%d\n", s,
++                     c->container->tid, c->cid);
++        }
++        else if (se->func == &dethrottle)
++        {
++            log (LOG_WARN, "%d: Dethrottle call %d:%d\n", s, c->container->tid,
++                     c->cid);
++        }
++        else
++            log (LOG_WARN, "%d: Unknown event\n", s);
++        se = se->next;
++    };
++    log (LOG_WARN, "Total Events scheduled: %d\n", s);
++    log (LOG_WARN, "Number of tunnels open: %d\n", tunnels.count);
++    t = tunnels.head;
++    while (t)
++    {
++        log (LOG_WARN, "Tunnel %s, ID = %d (local), %d (remote) to %s:%d\n"
++                 "   control_seq_num = %d, control_rec_seq_num = %d,\n"
++                 "   cLr = %d\n",
++                 (t->lac ? t->lac->entname : (t->lns ? t->lns->entname : "")),
++                 t->ourtid, t->tid, IPADDY (t->peer.sin_addr),
++                 ntohs (t->peer.sin_port), t->control_seq_num,
++                 t->control_rec_seq_num, t->cLr);
++        c = t->call_head;
++        while (c)
++        {
++            log (LOG_WARN, 
++                     "Call %s, ID = %d (local), %d (remote), serno = %u,\n"
++                     "      data_seq_num = %d, data_rec_seq_num = %d,\n"
++                     "      pLr = %d, tx = %u bytes (%u), rx= %u bytes (%u)\n",
++                     (c->lac ? c->lac->
++                      entname : (c->lns ? c->lns->entname : "")), c->ourcid,
++                     c->cid, c->serno, c->data_seq_num, c->data_rec_seq_num,
++                     c->pLr, c->tx_bytes, c->tx_pkts, c->rx_bytes, c->rx_pkts);
++            c = c->next;
++        }
++        t = t->next;
++    }
++    log (LOG_WARN, "==========Config File===========\n");
++    tlns = lnslist;
++    while (tlns)
++    {
++        log (LOG_WARN, "LNS entry %s\n",
++                 tlns->entname[0] ? tlns->entname : "(unnamed)");
++        tlns = tlns->next;
++    };
++    tlac = laclist;
++    while (tlac)
++    {
++        log (LOG_WARN, "LAC entry %s, LNS is/are:",
++                 tlac->entname[0] ? tlac->entname : "(unnamed)");
++        h = tlac->lns;
++        if (h)
++        {
++            while (h)
++            {
++                log (LOG_WARN, " %s", h->hostname);
++                h = h->next;
++            }
++        }
++        else
++            log (LOG_WARN, " [none]");
++        log (LOG_WARN, "\n");
++        tlac = tlac->next;
++    };
++    log (LOG_WARN, "================================\n");
++}
++
++void null_handler(int sig)
++{
++       /* FIXME 
++        * A sighup is received when a call is terminated, unknown origine .. 
++        * I catch it and ll looks good, but .. 
++      */
++}
++
++void status_handler (int sig)
++{
++    show_status ();
++}
++
++void child_handler (int signal)
++{
++    /*
++     * Oops, somebody we launched was killed.
++     * It's time to reap them and close that call.
++     * But first, we have to find out what PID died.
++     * unfortunately, pppd will 
++     */
++    struct tunnel *t;
++    struct call *c;
++    pid_t pid;
++    int status;
++    t = tunnels.head;
++    /* Keep looping until all are cleared */
++    for(;;)
++    {
++        pid = waitpid (-1, &status, WNOHANG);
++        if (pid < 1)
++        {
++            /*
++             * Oh well, nobody there.  Maybe we reaped it
++             * somewhere else already
++             */
++            return;
++        }
++        while (t)
++        {
++            c = t->call_head;
++            while (c)
++            {
++                if (c->pppd == pid)
++                {
++                    if ( WIFEXITED( status ) )
++                    {
++                        log (LOG_DEBUG, "%s : pppd exited for call %d with code %d\n", __FUNCTION__,
++                         c->cid, WEXITSTATUS( status ) );
++                    }
++                    else if( WIFSIGNALED( status ) )
++                    {
++                        log (LOG_DEBUG, "%s : pppd terminated for call %d by signal %d\n", __FUNCTION__,
++                         c->cid, WTERMSIG( status ) );
++                    }
++                    else
++                    {
++                        log (LOG_DEBUG, "%s : pppd exited for call %d for unknown reason\n", __FUNCTION__,
++                         c->cid );
++                    }
++                    c->needclose = -1;
++                    /* 
++                     * OK...pppd died, we can go ahead and close the pty for
++                     * it
++                     */
++                    close (c->fd);
++                    c->fd = -1;
++                    return;
++                }
++                c = c->next;
++            }
++            t = t->next;
++        }
++    }
++}
++
++void death_handler (int signal)
++{
++    /*
++       * If we get here, somebody terminated us with a kill or a control-c.
++       * we call call_close on each tunnel twice to get a StopCCN out
++       * for each one (we can't pause to make sure it's received.
++       * Then we close the connections
++     */
++    struct tunnel *st, *st2;
++    int sec;
++    log (LOG_CRIT, "%s: Fatal signal %d received\n", __FUNCTION__, signal);
++    st = tunnels.head;
++    while (st)
++    {
++        st2 = st->next;
++        strcpy (st->self->errormsg, "Server closing");
++        sec = st->self->closing;
++        if (st->lac)
++            st->lac->redial = 0;
++        call_close (st->self);
++        if (!sec)
++        {
++            st->self->closing = -1;
++            call_close (st->self);
++        }
++        st = st2;
++    }
++
++    /* erase pid file */
++      unlink (gconfig.pidfile);
++
++      /* erase control pipe */
++      unlink(CONTROL_PIPE);
++
++    exit (1);
++}
++
++int start_pppd (struct call *c, struct ppp_opts *opts)
++{
++    char a, b;
++    char tty[80];
++    char *stropt[80];
++    struct ppp_opts *p;
++#ifdef USE_KERNEL
++    struct l2tp_call_opts co;
++#endif
++    int pos = 1;
++    int fd2;
++#ifdef DEBUG_PPPD
++    int x;
++#endif
++    struct termios ptyconf;
++    char *str;
++    p = opts;
++    stropt[0] = strdup (PPPD);
++    while (p)
++    {
++        stropt[pos] = (char *) malloc (strlen (p->option) + 1);
++        strncpy (stropt[pos], p->option, strlen (p->option) + 1);
++        pos++;
++        p = p->next;
++    }
++    stropt[pos] = NULL;
++    if (c->pppd > 0)
++    {
++        log (LOG_WARN, "%s: PPP already started on call!\n", __FUNCTION__);
++        return -EINVAL;
++    }
++    if (c->fd > -1)
++    {
++        log (LOG_WARN, "%s: file descriptor already assigned!\n",
++             __FUNCTION__);
++        return -EINVAL;
++    }
++#ifdef USE_KERNEL
++    if (kernel_support)
++    {
++        co.ourtid = c->container->ourtid;
++        co.ourcid = c->ourcid;
++        ioctl (server_socket, L2TPIOCGETCALLOPTS, &co);
++        stropt[pos++] = strdup ("channel");
++        stropt[pos] = (char *) malloc (10);
++        snprintf (stropt[pos], 10, "%d", co.id);
++        pos++;
++        stropt[pos] = NULL;
++    }
++    else
++    {
++#endif
++        if ((c->fd = getPtyMaster (&a, &b)) < 0)
++        {
++            log (LOG_WARN, "%s: unable to allocate pty, abandoning!\n",
++                 __FUNCTION__);
++            return -EINVAL;
++        }
++
++        /* set fd opened above to not echo so we don't see read our own packets
++           back of the file descriptor that we just wrote them to */
++        tcgetattr (c->fd, &ptyconf);
++        *(c->oldptyconf) = ptyconf;
++        ptyconf.c_cflag &= ~(ICANON | ECHO);
++        tcsetattr (c->fd, TCSANOW, &ptyconf);
++
++        snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b);
++        fd2 = open (tty, O_RDWR);
++
++#ifdef USE_KERNEL
++    }
++#endif
++    str = stropt[0];
++#ifdef DEBUG_PPPD
++    log (LOG_DEBUG, "%s: I'm running:  ", __FUNCTION__);
++    for (x = 0; stropt[x]; x++)
++    {
++        log (LOG_DEBUG, "\"%s\" ", stropt[x]);
++    };
++    log (LOG_DEBUG, "\n");
++#endif
++    c->pppd = fork ();
++    if (c->pppd < 0)
++    {
++        log (LOG_WARN, "%s: unable to fork(), abandoning!\n", __FUNCTION__);
++        return -EINVAL;
++    }
++    else if (!c->pppd)
++    {
++        struct call *sc;
++        struct tunnel *st;
++
++        close (0);
++        close (1);
++        close (2);
++#ifdef USE_KERNEL
++        if (!kernel_support && (fd2 < 0))
++#else
++        if (fd2 < 0)
++#endif
++        {
++            log (LOG_WARN, "%s: Unable to open %s to launch pppd!\n",
++                 __FUNCTION__, tty);
++            exit (1);
++        }
++        dup2 (fd2, 0);
++        dup2 (fd2, 1);
++
++
++        /* close all the calls pty fds */
++        st = tunnels.head;
++        while (st)
++        {
++            sc = st->call_head;
++            while (sc)
++            {
++                close (sc->fd);
++                sc = sc->next;
++            }
++            st = st->next;
++        }
++
++        /* close the UDP socket fd */
++        close (server_socket);
++
++        /* close the control pipe fd */
++        close (control_fd);
++
++        if( c->dialing[0] )
++        {
++            setenv( "CALLER_ID", c->dialing, 1 );
++        }
++        execv (PPPD, stropt);
++        log (LOG_WARN, "%s: Exec of %s failed!\n", __FUNCTION__, PPPD);
++        exit (1);
++    };
++    close (fd2);
++    pos = 0;
++    while (stropt[pos])
++    {
++        free (stropt[pos]);
++        pos++;
++    };
++    return 0;
++}
++
++void destroy_tunnel (struct tunnel *t)
++{
++    /*
++     * Immediately destroy a tunnel (and all its calls)
++     * and free its resources.  This may be called
++     * by the tunnel itself,so it needs to be
++     * "suicide safe"
++     */
++
++    struct call *c, *me;
++    struct tunnel *p;
++    struct timeval tv;
++    if (!t)
++        return;
++
++    /*
++     * Save ourselves until the very
++     * end, since we might be calling this ourselves.
++     * We must divorce ourself from the tunnel
++     * structure, however, to avoid recursion
++     * because of the logic of the destroy_call
++     */
++    me = t->self;
++
++    /*
++     * Destroy all the member calls
++     */
++    c = t->call_head;
++    while (c)
++    {
++        destroy_call (c);
++        c = c->next;
++    };
++    /*
++     * Remove ourselves from the list of tunnels
++     */
++
++    if (tunnels.head == t)
++    {
++        tunnels.head = t->next;
++        tunnels.count--;
++    }
++    else
++    {
++        p = tunnels.head;
++        if (p)
++        {
++            while (p->next && (p->next != t))
++                p = p->next;
++            if (p->next)
++            {
++                p->next = t->next;
++                tunnels.count--;
++            }
++            else
++            {
++                log (LOG_WARN,
++                     "%s: unable to locate tunnel in tunnel list\n",
++                     __FUNCTION__);
++            }
++        }
++        else
++        {
++            log (LOG_WARN, "%s: tunnel list is empty!\n", __FUNCTION__);
++        }
++    }
++    if (t->lac)
++    {
++        t->lac->t = NULL;
++        if (t->lac->redial && (t->lac->rtimeout > 0) && !t->lac->rsched &&
++            t->lac->active)
++        {
++            log (LOG_LOG, "%s: Will redial in %d seconds\n", __FUNCTION__,
++                 t->lac->rtimeout);
++            tv.tv_sec = t->lac->rtimeout;
++            tv.tv_usec = 0;
++            t->lac->rsched = schedule (tv, magic_lac_dial, t->lac);
++        }
++    }
++    /* XXX L2TP/IPSec: remove relevant SAs here?  NTB 20011010
++     * XXX But what if another tunnel is using same SA?
++     */
++    if (t->lns)
++        t->lns->t = NULL;
++    free (t);
++    free (me);
++}
++
++struct tunnel *l2tp_call (char *host, int port, struct lac *lac,
++                          struct lns *lns)
++{
++    /*
++     * Establish a tunnel from us to host
++     * on port port
++     */
++    struct call *tmp = NULL;
++    struct hostent *hp;
++    unsigned int addr;
++    port = htons (port);
++    hp = gethostbyname (host);
++    if (!hp)
++    {
++        log (LOG_WARN, "%s: gethostbyname() failed for %s.\n", __FUNCTION__,
++             host);
++        return NULL;
++    }
++    bcopy (hp->h_addr, &addr, hp->h_length);
++    /* Force creation of a new tunnel
++       and set it's tid to 0 to cause
++       negotiation to occur */
++    /* XXX L2TP/IPSec: Set up SA to addr:port here?  NTB 20011010
++     */
++    tmp = get_call (0, 0, addr, port);
++    if (!tmp)
++    {
++        log (LOG_WARN, "%s: Unable to create tunnel to %s.\n", __FUNCTION__,
++             host);
++        return NULL;
++    }
++    tmp->container->tid = 0;
++    tmp->container->lac = lac;
++    tmp->container->lns = lns;
++    tmp->lac = lac;
++    tmp->lns = lns;
++    if (lac)
++        lac->t = tmp->container;
++    if (lns)
++        lns->t = tmp->container;
++    /*
++     * Since our state is 0, we will establish a tunnel now
++     */
++    log (LOG_LOG, "%s:Connecting to host %s, port %d\n", __FUNCTION__, host,
++         ntohs (port));
++    control_finish (tmp->container, tmp);
++    return tmp->container;
++}
++
++void magic_lac_tunnel (void *data)
++{
++    struct lac *lac;
++    lac = (struct lac *) data;
++    if (!lac)
++    {
++        log (LOG_WARN, "%s: magic_lac_tunnel: called on NULL lac!\n",
++             __FUNCTION__);
++        return;
++    }
++    if (lac->lns)
++    {
++        /* FIXME: I should try different LNS's if I get failures */
++        l2tp_call (lac->lns->hostname, lac->lns->port, lac, NULL);
++        return;
++    }
++    else if (deflac && deflac->lns)
++    {
++        l2tp_call (deflac->lns->hostname, deflac->lns->port, lac, NULL);
++        return;
++    }
++    else
++    {
++        log (LOG_WARN, "%s: Unable to find hostname to dial for '%s'\n",
++             __FUNCTION__, lac->entname);
++        return;
++    }
++}
++
++struct call *lac_call (int tid, struct lac *lac, struct lns *lns)
++{
++    struct tunnel *t = tunnels.head;
++    struct call *tmp;
++    while (t)
++    {
++        if (t->ourtid == tid)
++        {
++            tmp = new_call (t);
++            if (!tmp)
++            {
++                log (LOG_WARN, "%s: unable to create new call\n",
++                     __FUNCTION__);
++                return NULL;
++            }
++            tmp->next = t->call_head;
++            t->call_head = tmp;
++            t->count++;
++            tmp->cid = 0;
++            tmp->lac = lac;
++            tmp->lns = lns;
++            if (lac)
++                lac->c = tmp;
++            log (LOG_LOG, "%s: Calling on tunnel %d\n", __FUNCTION__, tid);
++            strcpy (tmp->dial_no, dial_no_tmp); /*  jz: copy dialnumber to tmp->dial_no  */
++            control_finish (t, tmp);
++            return tmp;
++        }
++        t = t->next;
++    };
++    log (LOG_DEBUG, "%s: No such tunnel %d to generate call.\n", __FUNCTION__,
++         tid);
++    return NULL;
++}
++
++void magic_lac_dial (void *data)
++{
++    struct lac *lac;
++    lac = (struct lac *) data;
++
++    if (!lac)
++    {
++        log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__);
++        return;
++    }
++      if (!lac->active)
++    {
++        log (LOG_DEBUG, "%s: LAC %s not active", __FUNCTION__, lac->entname);
++        return;
++    }
++    lac->rsched = NULL;
++    lac->rtries++;
++    if (lac->rmax && (lac->rtries > lac->rmax))
++    {
++        log (LOG_LOG, "%s: maximum retries exceeded.\n", __FUNCTION__);
++        return;
++    }
++    if (!lac->t)
++    {
++#ifdef DEGUG_MAGIC
++        log (LOG_DEBUG, "%s : tunnel not up!  Connecting!\n", __FUNCTION__);
++#endif
++        magic_lac_tunnel (lac);
++        return;
++    }
++    lac_call (lac->t->ourtid, lac, NULL);
++}
++
++void lac_hangup (int cid)
++{
++    struct tunnel *t = tunnels.head;
++    struct call *tmp;
++    while (t)
++    {
++        tmp = t->call_head;
++        while (tmp)
++        {
++            if (tmp->ourcid == cid)
++            {
++                log (LOG_LOG,
++                     "%s :Hanging up call %d, Local: %d, Remote: %d\n",
++                     __FUNCTION__, tmp->serno, tmp->ourcid, tmp->cid);
++                strcpy (tmp->errormsg, "Goodbye!");
++/*                            tmp->needclose = -1; */
++                kill (tmp->pppd, SIGTERM);
++                return;
++            }
++            tmp = tmp->next;
++        }
++        t = t->next;
++    };
++    log (LOG_DEBUG, "%s : No such call %d to hang up.\n", __FUNCTION__, cid);
++    return;
++}
++
++void lac_disconnect (int tid)
++{
++    struct tunnel *t = tunnels.head;
++    while (t)
++    {
++        if (t->ourtid == tid)
++        {
++            log (LOG_LOG,
++                 "%s: Disconnecting from %s, Local: %d, Remote: %d\n",
++                 __FUNCTION__, IPADDY (t->peer.sin_addr), t->ourtid, t->tid);
++            t->self->needclose = -1;
++            strcpy (t->self->errormsg, "Goodbye!");
++            call_close (t->self);
++            return;
++        }
++        t = t->next;
++    };
++    log (LOG_DEBUG, "%s: No such tunnel %d to hang up.\n", __FUNCTION__, tid);
++    return;
++}
++
++struct tunnel *new_tunnel ()
++{
++    struct tunnel *tmp = malloc (sizeof (struct tunnel));
++    char entropy_buf[2] = "\0";
++    if (!tmp)
++        return NULL;
++    tmp->control_seq_num = 0;
++    tmp->control_rec_seq_num = 0;
++    tmp->cLr = 0;
++    tmp->call_head = NULL;
++    tmp->next = NULL;
++    tmp->debug = -1;
++    tmp->tid = -1;
++    tmp->hello = NULL;
++#ifndef TESTING
++/*    while(get_call((tmp->ourtid = rand() & 0xFFFF),0,0,0)); */
++#ifdef USE_KERNEL
++    if (kernel_support)
++        tmp->ourtid = ioctl (server_socket, L2TPIOCADDTUNNEL, 0);
++    else
++#endif
++/*        tmp->ourtid = rand () & 0xFFFF; */
++        /* get_entropy((char *)&tmp->ourtid, 2); */
++        get_entropy(entropy_buf, 2);
++        {
++            int *temp;
++            temp = (int *)entropy_buf;
++            tmp->ourtid = *temp & 0xFFFF;
++#ifdef DEBUG_ENTROPY
++            log(LOG_DEBUG, "ourtid = %u, entropy_buf = %hx\n", tmp->ourtid, *temp);
++#endif
++        }
++#else
++    tmp->ourtid = 0x6227;
++#endif
++    tmp->nego = 0;
++    tmp->count = 0;
++    tmp->state = 0;             /* Nothing */
++    tmp->peer.sin_family = AF_INET;
++    tmp->peer.sin_port = 0;
++    bzero (&(tmp->peer.sin_addr), sizeof (tmp->peer.sin_addr));
++    tmp->sanity = -1;
++    tmp->qtid = -1;
++    tmp->ourfc = ASYNC_FRAMING | SYNC_FRAMING;
++    tmp->ourbc = 0;
++    tmp->ourtb = (((_u64) rand ()) << 32) | ((_u64) rand ());
++    tmp->fc = -1;               /* These really need to be specified by the peer */
++    tmp->bc = -1;               /* And we want to know if they forgot */
++    tmp->hostname[0] = 0;
++    tmp->vendor[0] = 0;
++    tmp->secret[0] = 0;
++    if (!(tmp->self = new_call (tmp)))
++    {
++        free (tmp);
++        return NULL;
++    };
++    tmp->ourrws = DEFAULT_RWS_SIZE;
++    tmp->self->ourfbit = FBIT;
++    tmp->lac = NULL;
++    tmp->lns = NULL;
++    tmp->chal_us.state = 0;
++    tmp->chal_us.secret[0] = 0;
++    memset (tmp->chal_us.reply, 0, MD_SIG_SIZE);
++    tmp->chal_them.state = 0;
++    tmp->chal_them.secret[0] = 0;
++    memset (tmp->chal_them.reply, 0, MD_SIG_SIZE);
++    tmp->chal_them.vector = (unsigned char *) malloc (VECTOR_SIZE);
++    tmp->chal_us.vector = NULL;
++    tmp->hbit = 0;
++    return tmp;
++}
++
++void do_control ()
++{
++    char buf[1024];
++    char *host, *tunstr, *callstr, *tmpstr;
++    struct lac *lac;
++    int call;
++    int tunl;
++    int cnt = -1;
++    while (cnt)
++    {
++        cnt = read (control_fd, buf, sizeof (buf));
++        if (cnt > 0)
++        {
++            if (buf[cnt - 1] == '\n')
++                buf[--cnt] = 0;
++#ifdef DEBUG_CONTROL
++            log (LOG_DEBUG, "%s: Got message \"%s\" (%d bytes long)\n",
++                 __FUNCTION__, buf, cnt);
++#endif
++            switch (buf[0])
++            {
++            case 't':
++                host = strchr (buf, ' ');
++                              if(!host)
++                                      goto out;
++                              host++;
++#ifdef DEBUG_CONTROL
++                log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n",
++                     __FUNCTION__, host);
++#endif
++                l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL);
++                break;
++            case 'c':            /* option 'c' for incoming call */
++            case 'o':          /* option 'o' for outgoing call */
++                              tunstr = strchr (buf, ' ');
++                              if(!tunstr)
++                                      goto out;
++                              tunstr++;
++
++                              if(buf[0] == 'c')
++                      switch_io = 1;  /* Switch for Incoming Calls */
++                              else {
++                      switch_io = 0;  /* Switch for Outgoing Calls */
++                                      tmpstr = strchr(tunstr, ' ');
++                                      if(!tmpstr)
++                                              goto out;
++                                      strncpy(dial_no_tmp,tmpstr, sizeof(*dial_no_tmp));
++                              }
++                
++                lac = laclist;
++                while (lac)
++                {
++                    if (!strcasecmp (lac->entname, tunstr))
++                    {
++                        lac->active = -1;
++                        lac->rtries = 0;
++                        if (!lac->c)
++                            magic_lac_dial (lac);
++                        else
++                            log (LOG_DEBUG,
++                                 "%s: Session '%s' already active!\n",
++                                 __FUNCTION__, lac->entname);
++                        break;
++                    }
++                    lac = lac->next;
++                }
++                if (lac)
++                    break;
++                tunl = atoi (tunstr);
++                if (!tunl)
++                {
++                    log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
++                         tunstr);
++                    break;
++                }
++#ifdef DEBUG_CONTROL
++                log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
++                     __FUNCTION__, tunl);
++#endif
++                lac_call (tunl, NULL, NULL);
++                break;
++            case 'h':
++                callstr = strchr (buf, ' ');
++                if(!callstr)
++                                      goto out;
++                              callstr++;
++
++                call = atoi (callstr);
++#ifdef DEBUG_CONTROL
++                log (LOG_DEBUG, "%s: Attempting to call %d\n", __FUNCTION__,
++                     call);
++#endif
++                lac_hangup (call);
++                break;
++            case 'd':
++                tunstr = strchr (buf, ' ');
++                if(!tunstr)
++                                      goto out;
++                              tunstr++;
++
++                lac = laclist;
++                while (lac)
++                {
++                    if (!strcasecmp (lac->entname, tunstr))
++                    {
++                        lac->active = 0;
++                        lac->rtries = 0;
++                        if (lac->t)
++                            lac_disconnect (lac->t->ourtid);
++                        else
++                            log (LOG_DEBUG, "%s: Session '%s' not up\n",
++                                 __FUNCTION__, lac->entname);
++                        break;
++                    }
++                    lac = lac->next;
++                }
++                if (lac)
++                    break;
++                tunl = atoi (tunstr);
++                if (!tunl)
++                {
++                    log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
++                         tunstr);
++                    break;
++                }
++#ifdef DEBUG_CONTROL
++                log (LOG_DEBUG, "%s: Attempting to disconnect tunnel %d\n",
++                     __FUNCTION__, tunl);
++#endif
++                lac_disconnect (tunl);
++                break;
++            case 's':
++                show_status ();
++                break;
++            default:
++                log (LOG_DEBUG, "%s: Unknown command %c\n", __FUNCTION__,
++                     buf[0]);
++            }
++        }
++    }
++
++out:
++    /* Otherwise select goes nuts */
++    close (control_fd);
++    control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600);
++}
++
++void usage(void) {
++    printf("Usage: l2tpd -D -c [config file] -s [secret file] -p [pid file]\n");
++    printf("\n");
++    exit(1);
++}
++
++void init_args(int argc, char *argv[]) {
++    int i=0;
++    gconfig.daemon=1;
++    memset(gconfig.altauthfile,0,STRLEN);
++    memset(gconfig.altconfigfile,0,STRLEN);
++    memset(gconfig.authfile,0,STRLEN);
++    memset(gconfig.configfile,0,STRLEN);
++    memset(gconfig.pidfile,0,STRLEN);
++    strncpy(gconfig.altauthfile,ALT_DEFAULT_AUTH_FILE,
++            sizeof(gconfig.altauthfile) - 1);
++    strncpy(gconfig.altconfigfile,ALT_DEFAULT_CONFIG_FILE,
++            sizeof(gconfig.altconfigfile) - 1);
++    strncpy(gconfig.authfile,DEFAULT_AUTH_FILE,
++            sizeof(gconfig.authfile) - 1);
++    strncpy(gconfig.configfile,DEFAULT_CONFIG_FILE,
++            sizeof(gconfig.configfile) - 1);
++    strncpy(gconfig.pidfile,DEFAULT_PID_FILE,
++            sizeof(gconfig.pidfile) - 1);
++    for (i = 1; i < argc; i++) {
++        if(! strncmp(argv[i],"-c",2)) {
++            if(++i == argc)
++                usage();
++            else
++                strncpy(gconfig.configfile,argv[i],
++                        sizeof(gconfig.configfile) - 1);
++        }
++        else if (! strncmp(argv[i],"-D",2)) {
++            gconfig.daemon=0;
++        }
++        else if (! strncmp(argv[i],"-s",2)) {
++            if(++i == argc)
++                usage();
++            else
++                strncpy(gconfig.authfile,argv[i],
++                        sizeof(gconfig.authfile) - 1);
++        }
++        else if (! strncmp(argv[i],"-p",2)) {
++            if(++i == argc)
++                usage();
++            else
++                strncpy(gconfig.pidfile,argv[i],
++                        sizeof(gconfig.pidfile) - 1);
++        }
++        else {
++            usage();
++        }
++    }
++}
++
++
++void daemonize() {
++    int pid=0;
++    int i,l;
++    char buf[STRLEN];
++
++    if((pid = fork()) < 0) {
++        log(LOG_LOG, "%s: Unable to fork ()\n",__FUNCTION__);
++        close(server_socket);
++        exit(1);
++    }
++    else if (pid)
++        exit(0);
++
++
++      close(0);
++      close(1);
++      close(2);
++      dup2(open("/dev/null", O_RDONLY), 0);
++      dup2(open("/dev/null", O_RDONLY), 1);
++      dup2(open("/dev/null", O_RDONLY), 2);
++
++    /* Read previous pid file. */
++    if((i = open(gconfig.pidfile,O_RDONLY)) > 0) {
++              l=read(i,buf,sizeof(buf)-1);                                                             
++        if (l >= 0) {
++              buf[l] = '\0';                                                                       
++              pid = atoi(buf);                                                                     
++        }
++              close(i);
++
++              /* if pid is read and process exist exit */
++        if(pid && !kill(pid, 0)) {
++            log(LOG_LOG, "%s: There's already a l2tpd server running.\n",
++                    __FUNCTION__);
++            close(server_socket);
++            exit(1);
++        }
++
++              /* remove stalled pid file */
++              unlink(gconfig.pidfile);
++    }
++
++    pid = setsid();
++
++      /* create new pid file */
++      if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0644)) >= 0) {
++              snprintf (buf, sizeof(buf), "%d", (int)getpid());
++              write (i, buf, strlen(buf));
++              close (i);
++      }
++      else {
++              log(LOG_LOG, "%s: could not write pid file %s error %d",
++                              __FUNCTION__, gconfig.pidfile, i);
++              close(server_socket);
++              exit(1);
++      }
++}
++
++
++void init (int argc,char *argv[])
++{
++    struct lac *lac;
++    struct in_addr listenaddr;
++
++    init_args (argc,argv);
++    srand( time(NULL) );
++    rand_source = 0;
++    init_addr ();
++    if (init_config ())
++    {
++        log (LOG_CRIT, "%s: Unable to load config file\n", __FUNCTION__);
++        exit (1);
++    }
++    if (uname (&uts))
++    {
++        log (LOG_CRIT, "%s : Unable to determine host system\n",
++             __FUNCTION__);
++        exit (1);
++    }
++    init_tunnel_list (&tunnels);
++    if (init_network ())
++        exit (1);
++    if (gconfig.daemon)
++      daemonize ();
++    signal (SIGTERM, &death_handler);
++    signal (SIGINT, &death_handler);
++    signal (SIGCHLD, &child_handler);
++    signal (SIGUSR1, &status_handler);
++    signal (SIGHUP, &null_handler);
++    init_scheduler ();
++    mkfifo (CONTROL_PIPE, 0600);
++    control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600);
++    if (control_fd < 0)
++    {
++        log (LOG_CRIT, "%s: Unable to open " CONTROL_PIPE " for reading.",
++             __FUNCTION__);
++        exit (1);
++    }
++    log (LOG_LOG, "l2tpd version " SERVER_VERSION " started on %s PID:%d\n",
++         hostname, getpid ());
++    listenaddr.s_addr = gconfig.listenaddr;
++    log (LOG_LOG, "%s version %s on a %s, listening on IP address %s, port %d\n", uts.sysname,
++       uts.release, uts.machine, inet_ntoa(listenaddr), gconfig.port);
++    lac = laclist;
++    while (lac)
++    {
++        if (lac->autodial)
++        {
++#ifdef DEBUG_MAGIC
++            log (LOG_DEBUG, "%s: Autodialing '%s'\n", __FUNCTION__,
++                 lac->entname[0] ? lac->entname : "(unnamed)");
++#endif
++            lac->active = -1;
++            switch_io = 1;      /* If we're a LAC, autodials will be ICRQ's */
++            magic_lac_dial (lac);
++        }
++        lac = lac->next;
++    }
++}
++
++int main (int argc, char *argv[])
++{
++    init(argc,argv);
++    dial_no_tmp = calloc (128, sizeof (char));
++    network_thread ();
++    return 0;
++}
diff --git a/openwrt/package/l2tpd/patches/debian-2.patch b/openwrt/package/l2tpd/patches/debian-2.patch
deleted file mode 100644 (file)
index 8a6e204..0000000
+++ /dev/null
@@ -1,3394 +0,0 @@
---- l2tpd-0.70-pre20031121.orig/Makefile
-+++ l2tpd-0.70-pre20031121/Makefile
-@@ -28,7 +28,8 @@
- # become runtime options) debugging flags
- #
- #DFLAGS= -g -O2 -DDEBUG_PPPD
--DFLAGS= -g -O2 -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY
-+#DFLAGS= -g -O2 -Wall -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY
-+DFLAGS= -ggdb -Wall -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY
- #
- # Uncomment the next line for Linux
- #
-@@ -58,7 +59,7 @@
- FFLAGS= -DIP_ALLOCATION 
--CFLAGS= $(DFLAGS) -Wall -DSANITY $(OSFLAGS) $(FFLAGS)
-+CFLAGS= $(DFLAGS) -Wall -DSANITY $(OSFLAGS) $(FFLAGS) 
- HDRS=l2tp.h avp.h misc.h control.h call.h scheduler.h file.h aaa.h md5.h
- OBJS=l2tpd.o pty.o misc.o control.o avp.o call.o network.o avpsend.o scheduler.o file.o aaa.o md5.o
- LIBS= $(OSLIB) # -lefence # efence for malloc checking
---- l2tpd-0.70-pre20031121.orig/control.c
-+++ l2tpd-0.70-pre20031121/control.c
-@@ -227,7 +227,7 @@
-             add_bearer_caps_avp (buf, t->ourbc);
-             /* FIXME:  Tie breaker */
-             add_firmware_avp (buf);
--            add_hostname_avp (buf);
-+            add_hostname_avp (buf, t);
-             add_vendor_avp (buf);
-             add_tunnelid_avp (buf, t->ourtid);
-             if (t->ourrws >= 0)
-@@ -346,7 +346,6 @@
-                      "%s: Peer did not specify assigned tunnel ID.  Closing.\n",
-                      __FUNCTION__);
-             set_error (c, VENDOR_ERROR, "Specify your assigned tunnel ID");
--            c->needclose = -1;
-             return -EINVAL;
-         }
-         if (!(t->lns = get_lns (t)))
-@@ -356,7 +355,6 @@
-                      "%s: Denied connection to unauthorized peer %s\n",
-                      __FUNCTION__, IPADDY (t->peer.sin_addr));
-             set_error (c, VENDOR_ERROR, "No Authorization");
--            c->needclose = -1;
-             return -EINVAL;
-         }
-         t->ourrws = t->lns->tun_rws;
-@@ -368,7 +366,6 @@
-                      "%s: Peer did not specify framing capability.  Closing.\n",
-                      __FUNCTION__);
-             set_error (c, VENDOR_ERROR, "Specify framing capability");
--            c->needclose = -1;
-             return -EINVAL;
-         }
-         /* FIXME: Do we need to be sure they specified a version number?
-@@ -380,7 +377,6 @@
-          if (DEBUG) log(LOG_DEBUG,
-          "%s: Peer did not specify bearer capability.  Closing.\n",__FUNCTION__);
-          set_error(c, VENDOR_ERROR, "Specify bearer capability");
--         c->needclose = -1;
-          return -EINVAL;
-          }  */
-         if ((!strlen (t->hostname)) && ((t->chal_us.state) || ((t->lns->challenge))))
-@@ -390,7 +386,6 @@
-                      "%s: Peer did not specify hostname.  Closing.\n",
-                      __FUNCTION__);
-             set_error (c, VENDOR_ERROR, "Specify your hostname");
--            c->needclose = -1;
-             return -EINVAL;
-         }
-         y = tunnels.head;
-@@ -427,7 +422,7 @@
-         add_frame_caps_avp (buf, t->ourfc);
-         add_bearer_caps_avp (buf, t->ourbc);
-         add_firmware_avp (buf);
--        add_hostname_avp (buf);
-+        add_hostname_avp (buf, t);
-         add_vendor_avp (buf);
-         add_tunnelid_avp (buf, t->ourtid);
-         if (t->ourrws >= 0)
-@@ -481,7 +476,6 @@
-                      "%s: Peer did not specify framing capability.  Closing.\n",
-                      __FUNCTION__);
-             set_error (c, VENDOR_ERROR, "Specify framing capability");
--            c->needclose = -1;
-             return -EINVAL;
-         }
-         /* FIXME: Do we need to be sure they specified a version number?
-@@ -493,7 +487,6 @@
-          if (DEBUG) log(LOG_DEBUG,
-          "%s: Peer did not specify bearer capability.  Closing.\n",__FUNCTION__);
-          set_error(c, VENDOR_ERROR, "Specify bearer capability");
--         c->needclose = -1;
-          return -EINVAL;
-          } */
-         if ((!strlen (t->hostname)) && ((t->chal_them.state) || ((t->chal_us.state))))
-@@ -503,7 +496,6 @@
-                      "%s: Peer did not specify hostname.  Closing.\n",
-                      __FUNCTION__);
-             set_error (c, VENDOR_ERROR, "Specify your hostname");
--            c->needclose = -1;
-             return -EINVAL;
-         }
-         if (t->tid <= 0)
-@@ -513,7 +505,6 @@
-                      "%s: Peer did not specify assigned tunnel ID.  Closing.\n",
-                      __FUNCTION__);
-             set_error (c, VENDOR_ERROR, "Specify your assigned tunnel ID");
--            c->needclose = -1;
-             return -EINVAL;
-         }
-         if (t->chal_them.state)
-@@ -524,7 +515,6 @@
-                 set_error (c, VENDOR_ERROR, "No secret key on our side");
-                 log (LOG_WARN, "%s: No secret key for authenticating '%s'\n",
-                      __FUNCTION__, t->hostname);
--                c->needclose = -1;
-                 return -EINVAL;
-             }
-             if (memcmp
-@@ -534,7 +524,6 @@
-                            "Invalid challenge authentication");
-                 log (LOG_DEBUG, "%s: Invalid authentication for host '%s'\n",
-                      __FUNCTION__, t->hostname);
--                c->needclose = -1;
-                 return -EINVAL;
-             }
-         }
-@@ -546,7 +535,6 @@
-                 log (LOG_WARN, "%s: No secret for authenticating to '%s'\n",
-                      __FUNCTION__, t->hostname);
-                 set_error (c, VENDOR_ERROR, "No secret key on our end");
--                c->needclose = -1;
-                 return -EINVAL;
-             };
-         }
-@@ -606,7 +594,6 @@
-                            "Invalid challenge authentication");
-                 log (LOG_DEBUG, "%s: Invalid authentication for host '%s'\n",
-                      __FUNCTION__, t->hostname);
--                c->needclose = -1;
-                 return -EINVAL;
-             }
-         }
-@@ -1584,6 +1571,14 @@
-     wbuf[pos++] = e;
-     for (x = 0; x < buf->len; x++)
-     {
-+              // we must at least still have 4 bytes left in the worst case scenario:
-+              // 1 for a possible escape, 1 for the value and 1 to end the PPP stream.
-+              if(pos >= (sizeof(wbuf) - 4)) {
-+                      if(DEBUG)
-+                              log(LOG_CRIT, "%s: rx packet is too big after PPP encoding (size %u, max is %u)\n", 
-+                                                      __FUNCTION__, buf->len, MAX_RECV_SIZE);
-+                      return -EINVAL;
-+              }
-         e = *((char *) buf->start + x);
-         if ((e < 0x20) || (e == PPP_ESCAPE) || (e == PPP_FLAG))
-         {
-@@ -1592,7 +1587,6 @@
-             wbuf[pos++] = PPP_ESCAPE;
-         }
-         wbuf[pos++] = e;
--
-     }
-     wbuf[pos++] = PPP_FLAG;
-     x = write (c->fd, wbuf, pos);
---- l2tpd-0.70-pre20031121.orig/misc.h
-+++ l2tpd-0.70-pre20031121/misc.h
-@@ -80,4 +80,11 @@
- extern void safe_copy (char *, char *, int);
- extern void opt_destroy (struct ppp_opts *);
- extern struct ppp_opts *add_opt (struct ppp_opts *, char *, ...);
-+extern u_int16_t get16(u_int8_t *);
-+extern u_int32_t get32(u_int8_t *);
-+extern u_int64_t get64(u_int8_t *);
-+extern void set16(u_int8_t *, u_int16_t);
-+extern void set32(u_int8_t *, u_int32_t);
-+extern void set64(u_int8_t *, u_int64_t);
-+
- #endif
---- l2tpd-0.70-pre20031121.orig/avp.h
-+++ l2tpd-0.70-pre20031121/avp.h
-@@ -19,22 +19,35 @@
- struct avp_hdr
- {
--    _u16 length;
--    _u16 vendorid;
--    _u16 attr;
-+    u_int16_t length;
-+    u_int16_t vendorid;
-+    u_int16_t attr;
- };
-+#define AVP_F_MANDATORY       0x1
-+#define AVP_F_FIXLEN  0x2
-+#define AVP_F_ASCII           0x4
-+
- struct avp
- {
--    int num;                    /* Number of AVP */
--    int m;                      /* Set M? */
--    int (*handler) (struct tunnel *, struct call *, void *, int);
--    /* This should handle the AVP
--       taking a tunnel, call, the data,
--       and the length of the AVP as
--       parameters.  Should return 0
--       upon success */
--    char *description;          /* A name, for debugging */
-+    u_int32_t         num;                            /* Number of AVP */
-+    u_int32_t flags;
-+      u_int32_t       sz;                                     /* expected avp payload size as
-+                                                                       * (AVP_F_FIXLEN) ? (==) : (!>=)
-+                                                                       * note: size checked is performed 
-+                                                                       * after unhiding */
-+      u_int8_t        allowed_states[8];      /* List of allowed message types for
-+                                                                       * a particular avp. Fixed len for
-+                                                                       * alignement issues. */
-+
-+    /* This should handle the AVP taking a tunnel, call, 
-+       * the data, and the length of the AVP as parameters.  
-+       * Should return 0 upon success */
-+    int (*handle) (struct tunnel *, struct call *, void *, int);
-+
-+      /* This should handle avp specifics sanity checks */
-+      int (*validate) (int, struct tunnel *, struct call *, void *, int);
-+    char *description;                /* A name, for debugging */
- };
- extern int handle_avps (struct buffer *buf, struct tunnel *t, struct call *c);
-@@ -84,8 +97,56 @@
- #define RESULT_CLEAR 1
- #define RESULT_ERROR 2
- #define RESULT_EXISTS 3
-+
-+/* avp id's */
-+#define       MESSAGE_TYPE_AVP                0
-+#define RESULT_CODE_AVP                       1
-+#define PROTOCOL_VERSION_AVP  2
-+#define       FRAMING_CAP_AVP                 3
-+#define       BEARER_CAP_AVP                  4
-+#define TIE_BREAKER_AVP                       5
-+#define       FIRMWARE_REV_AVP                6
-+#define       HOSTNAME_AVP                    7
-+#define VENDOR_NAME_AVP                       8
-+#define ASSIGNED_TUN_ID_AVP           9
-+#define       RX_WIN_SIZE_AVP                 10
-+#define       CHALLENGE_AVP                   11
-+#define       CHALLENGE_RESP_AVP              12
-+#define       CAUSE_ERROR_AVP                 13
-+#define       ASSIGNED_SES_ID_AVP             14
-+#define       SERIAL_NUMBER_AVP               15
-+#define       MIN_BPS_AVP                             16
-+#define       MAX_BPS_AVP                             17
-+#define       BEARER_TYPE_AVP                 18
-+#define       FRAMING_TYPE_AVP                19
-+#define       PACKET_DELAY_AVP                20
-+#define       CALLED_NUMBER_AVP               21
-+#define CALLING_NUMBER_AVP            22
-+#define       SUB_ADDRESS_AVP                 23
-+#define       TX_CONNECT_SPEED_AVP    24
-+#define       PHYS_CHAN_ID_AVP                25
-+#define       INIT_RX_LCP_AVP                 26
-+#define       LAST_TX_LCP_AVP                 27
-+#define       LAST_RX_LCP_AVP                 28
-+#define       PROXY_AUTH_TYPE_AVP             29
-+#define       PROXY_AUTH_NAME_AVP             30
-+#define       PROXY_AUTH_CHAL_AVP             31
-+#define       PROXY_AUTH_ID_AVP               32
-+#define       PROXY_AUTH_CHAL_RESP_AVP        33
-+#define CALL_ERROR_AVP                        34
-+#define       ACCM_AVP                                35
-+#define RANDOM_VECTOR_AVP             36
-+#define       PRIV_GROUP_ID_AVP               37
-+#define       RX_CONNECT_SPEED_AVP    38
-+#define       SEQ_REQUIRED_AVP                39
-+#define AVP_MAX                               SEQ_REQUIRED_AVP
-+
-+extern int validate_msgtype_avp(int, struct tunnel *, struct call *, void *, int);
-+extern int validate_gen_avp(int, struct tunnel *, struct call *, void *, int);
-+
- extern void encrypt_avp (struct buffer *, _u16, struct tunnel *);
- extern int decrypt_avp (char *, struct tunnel *);
-+
- extern int message_type_avp (struct tunnel *, struct call *, void *, int);
- extern int protocol_version_avp (struct tunnel *, struct call *, void *, int);
- extern int framing_caps_avp (struct tunnel *, struct call *, void *, int);
-@@ -97,12 +158,12 @@
- extern int receive_window_size_avp (struct tunnel *, struct call *, void *,
-                                     int);
- extern int result_code_avp (struct tunnel *, struct call *, void *, int);
--extern int assigned_call_avp (struct tunnel *, struct call *, void *, int);
-+extern int assigned_session_avp (struct tunnel *, struct call *, void *, int);
- extern int call_serno_avp (struct tunnel *, struct call *, void *, int);
- extern int bearer_type_avp (struct tunnel *, struct call *, void *, int);
- extern int call_physchan_avp (struct tunnel *, struct call *, void *, int);
--extern int dialed_number_avp (struct tunnel *, struct call *, void *, int);
--extern int dialing_number_avp (struct tunnel *, struct call *, void *, int);
-+extern int called_number_avp (struct tunnel *, struct call *, void *, int);
-+extern int calling_number_avp (struct tunnel *, struct call *, void *, int);
- extern int sub_address_avp (struct tunnel *, struct call *, void *, int);
- extern int frame_type_avp (struct tunnel *, struct call *, void *, int);
- extern int rx_speed_avp (struct tunnel *, struct call *, void *, int);
-@@ -118,7 +179,7 @@
- extern int add_avp_rws (struct buffer *, _u16);
- extern int add_tunnelid_avp (struct buffer *, _u16);
- extern int add_vendor_avp (struct buffer *);
--extern int add_hostname_avp (struct buffer *);
-+extern int add_hostname_avp (struct buffer *, struct tunnel*);
- extern int add_firmware_avp (struct buffer *);
- extern int add_bearer_caps_avp (struct buffer *buf, _u16 caps);
- extern int add_frame_caps_avp (struct buffer *buf, _u16 caps);
---- l2tpd-0.70-pre20031121.orig/network.c
-+++ l2tpd-0.70-pre20031121/network.c
-@@ -214,6 +214,8 @@
-                 t->self->needclose = -1;
-             }
-         }
-+              free(buf->rstart);
-+              free(buf);
-     }
-     else
-     {
-@@ -371,7 +373,9 @@
-                 if (debug_network)
-                 {
-                     log (LOG_DEBUG, "%s: recv packet from %s, size = %d," \
--"tunnel = %d, call = %d\n", __FUNCTION__, inet_ntoa (from.sin_addr), recvsize, tunnel, call);
-+                                                                      "tunnel = %d, call = %d\n", __func__, 
-+                                                                      inet_ntoa (from.sin_addr), recvsize, 
-+                                                                      tunnel, call);
-                 }
-                 if (packet_dump)
-                 {
---- l2tpd-0.70-pre20031121.orig/aaa.c
-+++ l2tpd-0.70-pre20031121/aaa.c
-@@ -209,9 +209,11 @@
-                  __FUNCTION__, u, t, s);
- #endif
-             strncpy (secret, s, size);
-+                      fclose(f);
-             return -1;
-         }
-     }
-+      fclose(f);
-     return 0;
- }
---- l2tpd-0.70-pre20031121.orig/l2tpd.c
-+++ l2tpd-0.70-pre20031121/l2tpd.c
-@@ -266,6 +266,9 @@
-     /* erase pid file */
-       unlink (gconfig.pidfile);
-+      /* erase control pipe */
-+      unlink(CONTROL_PIPE);
-+
-     exit (1);
- }
-@@ -333,13 +336,17 @@
-         tcgetattr (c->fd, &ptyconf);
-         *(c->oldptyconf) = ptyconf;
-         ptyconf.c_cflag &= ~(ICANON | ECHO);
--        ptyconf.c_lflag &= ~ECHO;
-+              ptyconf.c_lflag &= ~ECHO;
-         tcsetattr (c->fd, TCSANOW, &ptyconf);
-         snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b);
-         fd2 = open (tty, O_RDWR);
--      stropt[pos++] = strdup(tty);
--      stropt[pos] = NULL;
-+              if(!fd2)
-+                      log(LOG_WARN, "unable to open tty %s", tty);
-+
-+              /* XXX JEF: CHECK ME */
-+              stropt[pos++] = strdup(tty);
-+              stropt[pos] = NULL;
- #ifdef USE_KERNEL
-     }
-@@ -623,7 +630,13 @@
- {
-     struct lac *lac;
-     lac = (struct lac *) data;
--    if (!lac->active)
-+
-+    if (!lac)
-+    {
-+        log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__);
-+        return;
-+    }
-+      if (!lac->active)
-     {
-         log (LOG_DEBUG, "%s: LAC %s not active", __FUNCTION__, lac->entname);
-         return;
-@@ -635,11 +648,6 @@
-         log (LOG_LOG, "%s: maximum retries exceeded.\n", __FUNCTION__);
-         return;
-     }
--    if (!lac)
--    {
--        log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__);
--        return;
--    }
-     if (!lac->t)
-     {
- #ifdef DEGUG_MAGIC
-@@ -774,12 +782,7 @@
- void do_control ()
- {
-     char buf[1024];
--    char *host;
--    char *tunstr;
--    char *callstr;
--
--    char *sub_str;              /* jz: use by the strtok function */
--    char *tmp_ptr;              /* jz: use by the strtok function */
-+    char *host, *tunstr, *callstr, *tmpstr;
-     struct lac *lac;
-     int call;
-     int tunl;
-@@ -792,24 +795,39 @@
-             if (buf[cnt - 1] == '\n')
-                 buf[--cnt] = 0;
- #ifdef DEBUG_CONTROL
--            log (LOG_DEBUG, "%s: Got message %s (%d bytes long)\n",
-+            log (LOG_DEBUG, "%s: Got message \"%s\" (%d bytes long)\n",
-                  __FUNCTION__, buf, cnt);
- #endif
-             switch (buf[0])
-             {
-             case 't':
--                host = strchr (buf, ' ') + 1;
-+                host = strchr (buf, ' ');
-+                              if(!host)
-+                                      goto out;
-+                              host++;
- #ifdef DEBUG_CONTROL
-                 log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n",
-                      __FUNCTION__, host);
- #endif
-                 l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL);
-                 break;
--            case 'c':
--
--                switch_io = 1;  /* jz: Switch for Incoming - Outgoing Calls */
--
--                tunstr = strchr (buf, ' ') + 1;
-+            case 'c':            /* option 'c' for incoming call */
-+            case 'o':          /* option 'o' for outgoing call */
-+                              tunstr = strchr (buf, ' ');
-+                              if(!tunstr)
-+                                      goto out;
-+                              tunstr++;
-+
-+                              if(buf[0] == 'c')
-+                      switch_io = 1;  /* Switch for Incoming Calls */
-+                              else {
-+                      switch_io = 0;  /* Switch for Outgoing Calls */
-+                                      tmpstr = strchr(tunstr, ' ');
-+                                      if(!tmpstr)
-+                                              goto out;
-+                                      strncpy(dial_no_tmp,tmpstr, sizeof(*dial_no_tmp));
-+                              }
-+                
-                 lac = laclist;
-                 while (lac)
-                 {
-@@ -842,52 +860,12 @@
- #endif
-                 lac_call (tunl, NULL, NULL);
-                 break;
--
--            case 'o':          /* jz: option 'o' for doing a outgoing call */
--
--                switch_io = 0;  /* jz: Switch for incoming - outgoing Calls */
--
--                sub_str = strchr (buf, ' ') + 1;
--
--                tunstr = strtok (sub_str, " "); /* jz: using strtok function to get */
--                tmp_ptr = strtok (NULL, " ");   /*     params out of the pipe       */
--                strcpy (dial_no_tmp, tmp_ptr);
--
--                lac = laclist;
--                while (lac)
--                {
--                    if (!strcasecmp (lac->entname, tunstr))
--                    {
--                        lac->active = -1;
--                        lac->rtries = 0;
--                        if (!lac->c)
--                            magic_lac_dial (lac);
--                        else
--                            log (LOG_DEBUG,
--                                 "%s: Session '%s' already active!\n",
--                                 __FUNCTION__, lac->entname);
--                        break;
--                    }
--                    lac = lac->next;
--                }
--                if (lac)
--                    break;
--                tunl = atoi (tunstr);
--                if (!tunl)
--                {
--                    log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
--                         tunstr);
--                    break;
--                }
--#ifdef DEBUG_CONTROL
--                log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
--                     __FUNCTION__, tunl);
--#endif
--                lac_call (tunl, NULL, NULL);
--                break;
--
-             case 'h':
--                callstr = strchr (buf, ' ') + 1;
-+                callstr = strchr (buf, ' ');
-+                if(!callstr)
-+                                      goto out;
-+                              callstr++;
-+
-                 call = atoi (callstr);
- #ifdef DEBUG_CONTROL
-                 log (LOG_DEBUG, "%s: Attempting to call %d\n", __FUNCTION__,
-@@ -896,7 +874,11 @@
-                 lac_hangup (call);
-                 break;
-             case 'd':
--                tunstr = strchr (buf, ' ') + 1;
-+                tunstr = strchr (buf, ' ');
-+                if(!tunstr)
-+                                      goto out;
-+                              tunstr++;
-+
-                 lac = laclist;
-                 while (lac)
-                 {
-@@ -937,6 +919,8 @@
-             }
-         }
-     }
-+
-+out:
-     /* Otherwise select goes nuts */
-     close (control_fd);
-     control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600);
-@@ -1002,7 +986,6 @@
-     int pid=0;
-     int i,l;
-     char buf[STRLEN];
--    int pidfilewritten=0;
-     if((pid = fork()) < 0) {
-         log(LOG_LOG, "%s: Unable to fork ()\n",__FUNCTION__);
-@@ -1012,56 +995,52 @@
-     else if (pid)
-         exit(0);
--    close(0);
--    close(1);
--    close(2);
-+
-+      close(0);
-+      close(1);
-+      close(2);
-+      dup2(open("/dev/null", O_RDONLY), 0);
-+      dup2(open("/dev/null", O_RDONLY), 1);
-+      dup2(open("/dev/null", O_RDONLY), 2);
-     /* Read previous pid file. */
--    if ((i = open(gconfig.pidfile,O_RDONLY)) > 0) {
--        l=read(i,buf,sizeof(buf)-1);
--        if (i < 0) {
--            log(LOG_LOG, "%s: Unable to read pid file [%s]\n",
--                    __FUNCTION__, gconfig.pidfile);
--        }
--        buf[i] = '\0';
--        pid = atoi(buf);
--
--        /* If the previous server process is not still running,
--           write a new pid file immediately. */
--        if (pid && (pid == getpid () || kill (pid, 0) < 0)) {
--            unlink (gconfig.pidfile);
--            if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0640)) >= 0)
--            {
--                snprintf (buf, sizeof(buf), "%d\n", (int)getpid());
--                write (i, buf, strlen(buf));
--                close (i);
--                pidfilewritten = 1;
--            }
-+    if((i = open(gconfig.pidfile,O_RDONLY)) > 0) {
-+              l=read(i,buf,sizeof(buf)-1);                                                             
-+        if (l >= 0) {
-+              buf[l] = '\0';                                                                       
-+              pid = atoi(buf);                                                                     
-         }
--        else
--        {
-+              close(i);
-+
-+              /* if pid is read and process exist exit */
-+        if(pid && !kill(pid, 0)) {
-             log(LOG_LOG, "%s: There's already a l2tpd server running.\n",
-                     __FUNCTION__);
-             close(server_socket);
-             exit(1);
-         }
-+
-+              /* remove stalled pid file */
-+              unlink(gconfig.pidfile);
-     }
-     pid = setsid();
--    if(! pidfilewritten) {
--        unlink(gconfig.pidfile);
--        if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0640)) >= 0) {
--            snprintf (buf, strlen(buf), "%d\n", (int)getpid());
--            write (i, buf, strlen(buf));
--            close (i);
--            pidfilewritten = 1;
--        }
--    }
-+      /* create new pid file */
-+      if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0644)) >= 0) {
-+              snprintf (buf, sizeof(buf), "%d", (int)getpid());
-+              write (i, buf, strlen(buf));
-+              close (i);
-+      }
-+      else {
-+              log(LOG_LOG, "%s: could not write pid file %s error %d",
-+                              __FUNCTION__, gconfig.pidfile, i);
-+              close(server_socket);
-+              exit(1);
-+      }
- }
--
- void init (int argc,char *argv[])
- {
-     struct lac *lac;
-@@ -1103,10 +1082,6 @@
-     }
-     log (LOG_LOG, "l2tpd version " SERVER_VERSION " started on %s PID:%d\n",
-          hostname, getpid ());
--    log (LOG_LOG,
--         "Written by Mark Spencer, Copyright (C) 1998, Adtran, Inc.\n");
--    log (LOG_LOG, "Forked by Scott Balmos and David Stipp, (C) 2001\n");
--    log (LOG_LOG, "Inherited by Jeff McAdams, (C) 2002\n");
-     listenaddr.s_addr = gconfig.listenaddr;
-     log (LOG_LOG, "%s version %s on a %s, listening on IP address %s, port %d\n", uts.sysname,
-        uts.release, uts.machine, inet_ntoa(listenaddr), gconfig.port);
---- l2tpd-0.70-pre20031121.orig/misc.c
-+++ l2tpd-0.70-pre20031121/misc.c
-@@ -301,3 +301,42 @@
-         return -1;
-     }
- }
-+
-+u_int16_t get16(u_int8_t *p) {
-+      return p[0] << 8 | p[1];
-+}
-+
-+u_int32_t get32(u_int8_t *p) {
-+      return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
-+}
-+
-+u_int64_t get64(u_int8_t *p) {
-+      return (u_int64_t)p[0] << 56 | (u_int64_t)p[1] << 48 |
-+             (u_int64_t)p[2] << 40 | (u_int64_t)p[3] << 32 |
-+             (u_int64_t)p[4] << 24 | (u_int64_t)p[5] << 16 | 
-+                 (u_int64_t)p[6] << 8  | (u_int64_t)p[7];
-+}
-+
-+void set16(u_int8_t *cp, u_int16_t x) {
-+      *cp++ = x >> 8;
-+    *cp = x & 0xff;
-+} 
-+
-+void set32(u_int8_t *cp, u_int32_t x) {
-+      *cp++ = x >> 24;
-+    *cp++ = (x >> 16) & 0xff;
-+      *cp++ = (x >> 8) & 0xff;
-+      *cp = x & 0xff;
-+}
-+
-+void set64(u_int8_t *cp, u_int64_t x) {   
-+      *cp++ = x >> 56;
-+      *cp++ = (x >> 48) & 0xff;
-+      *cp++ = (x >> 40) & 0xff;
-+      *cp++ = (x >> 32) & 0xff;
-+      *cp++ = (x >> 24) & 0xff;
-+      *cp++ = (x >> 16) & 0xff;
-+      *cp++ = (x >> 8) & 0xff;
-+      *cp = x & 0xff;
-+}
-+
---- l2tpd-0.70-pre20031121.orig/avp.c
-+++ l2tpd-0.70-pre20031121/avp.c
-@@ -4,9 +4,12 @@
-  * Layer Two Tunnelling Protocol Daemon
-  * Copyright (C) 1998 Adtran, Inc.
-  * Copyright (C) 2002 Jeff McAdams
-+ * Copyright (C) 2003 Jean-Francois Dive
-  *
-  * Mark Spencer
-  *
-+ * 12/2003    parsing sanitization, Jean-Francois Dive
-+ *
-  * This software is distributed under the terms
-  * of the GPL, which you should have received
-  * along with this source.
-@@ -20,50 +23,53 @@
- #include <netinet/in.h>
- #include "l2tp.h"
--#define AVP_MAX 39
-+/* TODO: 
-+ * - Tie breaker.
-+ * - Clean Proxy Authentication solution.
-+ */
-+/*****************************************************************************/
- struct avp avps[] = {
--
--    {0, 1, &message_type_avp, "Message Type"},
--    {1, 1, &result_code_avp, "Result Code"},
--    {2, 1, &protocol_version_avp, "Protocol Version"},
--    {3, 1, &framing_caps_avp, "Framing Capabilities"},
--    {4, 1, &bearer_caps_avp, "Bearer Capabilities"},
--    {5, 0, NULL, "Tie Breaker"},
--    {6, 0, &firmware_rev_avp, "Firmware Revision"},
--    {7, 0, &hostname_avp, "Host Name"},
--    {8, 1, &vendor_avp, "Vendor Name"},
--    {9, 1, &assigned_tunnel_avp, "Assigned Tunnel ID"},
--    {10, 1, &receive_window_size_avp, "Receive Window Size"},
--    {11, 1, &challenge_avp, "Challenge"},
--    {12, 0, NULL, "Q.931 Cause Code"},
--    {13, 1, &chalresp_avp, "Challenge Response"},
--    {14, 1, &assigned_call_avp, "Assigned Call ID"},
--    {15, 1, &call_serno_avp, "Call Serial Number"},
--    {16, 1, NULL, "Minimum BPS"},
--    {17, 1, NULL, "Maximum BPS"},
--    {18, 1, &bearer_type_avp, "Bearer Type"},
--    {19, 1, &frame_type_avp, "Framing Type"},
--    {20, 1, &packet_delay_avp, "Packet Processing Delay"},
--    {21, 1, &dialed_number_avp, "Dialed Number"},
--    {22, 1, &dialing_number_avp, "Dialing Number"},
--    {23, 1, &sub_address_avp, "Sub-Address"},
--    {24, 1, &tx_speed_avp, "Transmit Connect Speed"},
--    {25, 1, &call_physchan_avp, "Physical channel ID"},
--    {26, 0, NULL, "Initial Received LCP Confreq"},
--    {27, 0, NULL, "Last Sent LCP Confreq"},
--    {28, 0, NULL, "Last Received LCP Confreq"},
--    {29, 1, &ignore_avp, "Proxy Authen Type"},
--    {30, 0, &ignore_avp, "Proxy Authen Name"},
--    {31, 0, &ignore_avp, "Proxy Authen Challenge"},
--    {32, 0, &ignore_avp, "Proxy Authen ID"},
--    {33, 1, &ignore_avp, "Proxy Authen Response"},
--    {34, 1, NULL, "Call Errors"},
--    {35, 1, &ignore_avp, "ACCM"},
--    {36, 1, &rand_vector_avp, "Random Vector"},
--    {37, 1, NULL, "Private Group ID"},
--    {38, 0, &rx_speed_avp, "Receive Connect Speed"},
--    {39, 1, &seq_reqd_avp, "Sequencing Required"}
-+    {0, AVP_F_MANDATORY|AVP_F_FIXLEN, 2, {0}, &message_type_avp, &validate_msgtype_avp, "Message Type"},
-+    {1, AVP_F_MANDATORY, MAXSTRLEN, {CDN, StopCCN}, &result_code_avp, &validate_gen_avp, "Result Code"},
-+    {2, AVP_F_MANDATORY|AVP_F_FIXLEN, 2, {SCCRP, SCCRQ}, &protocol_version_avp, &validate_gen_avp, "Protocol Version"},
-+    {3, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {SCCRP, SCCRQ}, &framing_caps_avp, &validate_gen_avp, "Framing Capabilities"},
-+    {4, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {SCCRP, SCCRQ}, &bearer_caps_avp, &validate_gen_avp, "Bearer Capabilities"},
-+    {5, 0, 0, {0}, NULL, NULL, "Tie Breaker"},
-+    {6, AVP_F_FIXLEN, 2, {SCCRP, SCCRQ}, &firmware_rev_avp, &validate_gen_avp, "Firmware Revision"},
-+    {7, AVP_F_ASCII, MAXSTRLEN, {SCCRP, SCCRQ}, &hostname_avp, &validate_gen_avp, "Host Name"},
-+    {8, AVP_F_MANDATORY|AVP_F_ASCII, MAXSTRLEN, {SCCRP, SCCRQ}, &vendor_avp, &validate_gen_avp, "Vendor Name"},
-+    {9, AVP_F_MANDATORY|AVP_F_FIXLEN, 2, {SCCRP, SCCRQ, StopCCN}, &assigned_tunnel_avp, &validate_gen_avp, "Assigned Tunnel ID"},
-+    {10, AVP_F_MANDATORY|AVP_F_FIXLEN, 2,{SCCRP, SCCRQ, OCRP, OCCN, StopCCN}, &receive_window_size_avp, &validate_gen_avp, "Receive Window Size"},
-+    {11, AVP_F_MANDATORY, 128, {SCCRP, SCCRQ}, &challenge_avp, &validate_gen_avp, "Challenge"},
-+    {12, 0, 0, {0}, NULL, NULL, "Q.931 Cause Code"},
-+    {13, AVP_F_MANDATORY, MD_SIG_SIZE, {SCCRP, SCCCN}, &chalresp_avp, &validate_gen_avp, "Challenge Response"},
-+    {14, AVP_F_MANDATORY|AVP_F_FIXLEN, 2, {CDN, ICRP, ICRQ, OCRP, OCRQ}, &assigned_session_avp, &validate_gen_avp, "Assigned Session ID"},
-+    {15, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {ICRQ, OCRQ}, &call_serno_avp, &validate_gen_avp, "Call Serial Number"},
-+    {16, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {0}, NULL, NULL, "Minimum BPS"},
-+    {17, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {0}, NULL, NULL, "Maximum BPS"},
-+    {18, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {ICRQ, OCRQ}, &bearer_type_avp, &validate_gen_avp, "Bearer Type"},
-+    {19, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {ICCN, OCRQ, OCCN}, &frame_type_avp, &validate_gen_avp, "Framing Type"},
-+    {20, AVP_F_MANDATORY|AVP_F_FIXLEN, 2, {ICRP, OCRQ, ICCN, OCRP, OCCN}, &packet_delay_avp, &validate_gen_avp, "Packet Processing Delay"},
-+    {21, AVP_F_MANDATORY|AVP_F_ASCII, MAXSTRLEN, {ICRQ, OCRQ}, &called_number_avp, &validate_gen_avp, "Called Number"},
-+    {22, AVP_F_MANDATORY|AVP_F_ASCII, MAXSTRLEN, {ICRQ}, &calling_number_avp, &validate_gen_avp, "Calling Number"},
-+    {23, AVP_F_MANDATORY|AVP_F_ASCII, MAXSTRLEN, {OCRP, ICRQ}, &sub_address_avp, &validate_gen_avp, "Sub-Address"},
-+    {24, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {ICCN, OCCN, OCRP}, &tx_speed_avp, &validate_gen_avp, "Transmit Connect Speed"},
-+    {25, AVP_F_MANDATORY|AVP_F_FIXLEN, 4, {ICRQ, OCRQ, OCRP, OCCN}, &call_physchan_avp, &validate_gen_avp, "Physical channel ID"},
-+    {26, 0, 0, {0}, NULL, NULL, "Initial Received LCP Confreq"},
-+    {27, 0, 0, {0}, NULL, NULL, "Last Sent LCP Confreq"},
-+    {28, 0, 0, {0}, NULL, NULL, "Last Received LCP Confreq"},
-+    {29, AVP_F_MANDATORY, 0, {0}, &ignore_avp, NULL, "Proxy Authen Type"},
-+    {30, 0, 0, {0}, &ignore_avp, NULL, "Proxy Authen Name"},
-+    {31, 0, 0, {0}, &ignore_avp, NULL, "Proxy Authen Challenge"},
-+    {32, 0, 0, {0}, &ignore_avp, NULL, "Proxy Authen ID"},
-+    {33, AVP_F_MANDATORY, 0, {0}, &ignore_avp, NULL, "Proxy Authen Response"},
-+    {34, AVP_F_MANDATORY|AVP_F_FIXLEN, 26, {0}, NULL, NULL, "Call Errors"},
-+    {35, AVP_F_MANDATORY|AVP_F_FIXLEN, 10, {0}, &ignore_avp, NULL, "ACCM"},
-+    {36, AVP_F_MANDATORY, 1024, {0}, &rand_vector_avp, &validate_gen_avp, "Random Vector"},
-+    {37, AVP_F_MANDATORY, 0, {0}, NULL, NULL, "Private Group ID"},
-+    {38, AVP_F_FIXLEN, 4, {ICCN, OCCN, OCRP}, &rx_speed_avp, &validate_gen_avp, "Receive Connect Speed"},
-+    {39, AVP_F_MANDATORY, 0, {ICCN, OCCN, OCRP}, &seq_reqd_avp, &validate_gen_avp, "Sequencing Required"}
- };
- char *msgtypes[] = {
-@@ -111,6 +117,7 @@
-     "Call was connected but no appropriate framing was detect"
- };
-+/*****************************************************************************/
- void wrong_length (struct call *c, char *field, int expected, int found,
-                    int min)
- {
-@@ -126,12 +133,9 @@
-     c->needclose = -1;
- }
--/*
-- * t, c, data, and datalen may be assumed to be defined for all avp's
-- */
--
--int message_type_avp (struct tunnel *t, struct call *c, void *data,
--                      int datalen)
-+/*****************************************************************************/
-+int validate_msgtype_avp(int attr,  struct tunnel *t, struct call *c, 
-+                                               void *data, int datalen)
- {
-     /*
-      * This will be with every control message.  It is critical that this
-@@ -139,28 +143,9 @@
-      * (assuming sanity check)
-      */
--    _u16 *raw = data;
--    c->msgtype = ntohs (raw[3]);
--    if (datalen != 8)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG, "%s: wrong size (%d != 8)\n", __FUNCTION__,
--                 datalen);
--        wrong_length (c, "Message Type", 8, datalen, 0);
--        return -EINVAL;
--    }
--    if ((c->msgtype > MAX_MSG) || (!msgtypes[c->msgtype]))
--    {
--        if (DEBUG)
--            log (LOG_DEBUG, "%s: unknown message type %d\n", __FUNCTION__,
--                 c->msgtype);
--        return -EINVAL;
--    }
--    if (debug_avp)
--        if (DEBUG)
--            log (LOG_DEBUG, "%s: message type %d (%s)\n", __FUNCTION__,
--                 c->msgtype, msgtypes[c->msgtype]);
--#ifdef SANITY
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      c->msgtype = get16(p);
-+
-     if (t->sanity)
-     {
-         /*
-@@ -172,11 +157,11 @@
-             if (DEBUG)
-                 log (LOG_DEBUG,
-                      "%s: attempting to negotiate tunnel inside a call!\n",
--                     __FUNCTION__);
-+                     __func__);
-             return -EINVAL;
-         }
--        switch (c->msgtype)
-+        switch (get16(p))
-         {
-         case SCCRQ:
-             if ((t->state != 0) && (t->state != SCCRQ))
-@@ -189,7 +174,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate SCCRQ with state != 0\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             break;
-@@ -199,7 +184,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate SCCRP with state != SCCRQ!\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             break;
-@@ -209,7 +194,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate SCCCN with state != SCCRP!\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             break;
-@@ -219,7 +204,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate ICRQ when state != SCCCN\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             if (c != t->self)
-@@ -227,7 +212,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate ICRQ on a call!\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             break;
-@@ -237,7 +222,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate ICRP on tunnel!=SCCCN\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             if (c->state != ICRQ)
-@@ -245,7 +230,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate ICRP when state != ICRQ\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             break;
-@@ -255,7 +240,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate ICCN when state != ICRP\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             break;
-@@ -265,7 +250,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate SLI when state != ICCN\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             break;
-@@ -275,7 +260,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate OCRP on tunnel!=SCCCN\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             if (c->state != OCRQ)
-@@ -283,7 +268,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate OCRP when state != OCRQ\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             break;
-@@ -294,7 +279,7 @@
-                 if (DEBUG)
-                     log (LOG_DEBUG,
-                          "%s: attempting to negotiate OCCN when state != OCRQ\n",
--                         __FUNCTION__);
-+                         __func__);
-                 return -EINVAL;
-             }
-             break;
-@@ -303,72 +288,33 @@
-         case Hello:
-             break;
-         default:
--            log (LOG_WARN, "%s: i don't know how to handle %s messages\n",
--                 __FUNCTION__, msgtypes[c->msgtype]);
--            return -EINVAL;
--        }
--    }
--#endif
--    if (c->msgtype == ICRQ)
--    {
--        struct call *tmp;
--        if (debug_avp)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG, "%s: new incoming call\n", __FUNCTION__);
--        }
--        tmp = new_call (t);
--        if (!tmp)
--        {
--            log (LOG_WARN, "%s: unable to create new call\n", __FUNCTION__);
-+            log (LOG_WARN, "%s: unknown messages type %d\n",
-+                 __func__, get16(p));
-             return -EINVAL;
-         }
--        tmp->next = t->call_head;
--        t->call_head = tmp;
--        t->count++;
--        /*
--           * Is this still safe to assume that the head will always
--           * be the most recent call being negotiated?
--           * Probably...  FIXME anyway...
--         */
--
-     }
--    return 0;
-+      return 0;
- }
--int rand_vector_avp (struct tunnel *t, struct call *c, void *data,
--                     int datalen)
--{
--    int size;
--    _u16 *raw = (_u16 *) data;
--    size = (raw[0] & 0x0FFF) - 6;
--    if (t->sanity)
--    {
--        if (size < 0)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG, "%s: Random vector too small (%d < 0)\n",
--                     __FUNCTION__, size);
--            wrong_length (c, "Random Vector", 6, datalen, 1);
--            return -EINVAL;
--        }
--        if (size > MAX_VECTOR_SIZE)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG, "%s: Random vector too large (%d > %d)\n",
--                     __FUNCTION__, datalen, MAX_VECTOR_SIZE);
--            wrong_length (c, "Random Vector", 6, datalen, 1);
--            return -EINVAL;
--        }
--    }
--    if (debug_avp)
--        log (LOG_DEBUG, "%s: Random Vector of %d octets\n", __FUNCTION__,
--             size);
--    t->chal_us.vector = (unsigned char *) &raw[3];
--    t->chal_us.vector_len = size;
--    return 0;
-+/*****************************************************************************/
-+int validate_gen_avp(int attr,  struct tunnel *t, struct call *c, 
-+                                       void *data, int datalen) {
-+      (void)data; (void)datalen;
-+      int i = 0, found = 0;
-+
-+    if(t->sanity) {
-+              for(i = 0; i < 8; i++) {
-+                      if(c->msgtype == avps[attr].allowed_states[i])
-+                              found++;
-+              }
-+              if(!found) 
-+                      return -EINVAL;
-+      }
-+      return 0;
- }
-+/* t, c, data, and datalen may be assumed to be defined for all avp's        */
-+/*****************************************************************************/
- int ignore_avp (struct tunnel *t, struct call *c, void *data, int datalen)
- {
-     /*
-@@ -383,94 +329,88 @@
-      *
-      */
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG, "%s : Ignoring AVP\n", __FUNCTION__);
--    }
-+      log (LOG_DEBUG, "%s : Ignoring AVP\n", __func__);
-     return 0;
- }
--int seq_reqd_avp (struct tunnel *t, struct call *c, void *data, int datalen)
-+/*****************************************************************************/
-+int message_type_avp (struct tunnel *t, struct call *c, void *data,
-+                      int avplen)
- {
--#ifdef SANITY
--    if (t->sanity)
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      
-+      if(!c->msgtype)
-+              c->msgtype = get16(p);
-+
-+    if ((c->msgtype > MAX_MSG) || (!msgtypes[c->msgtype]))
-     {
--        if (datalen != 6)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is incorrect size.  %d != 6\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Sequencing Required", 6, datalen, 1);
--            return -EINVAL;
--        }
--        switch (c->msgtype)
-+        log (LOG_DEBUG, "%s: unknown message type %d\n", __func__,
-+             c->msgtype);
-+        return -EINVAL;
-+    }
-+    if (debug_avp)
-+        log (LOG_DEBUG, "%s: message type %d (%s)\n", __func__,
-+             c->msgtype, msgtypes[c->msgtype]);
-+    if (c->msgtype == ICRQ)
-+    {
-+        struct call *tmp;
-+        if (debug_avp)
-+              log (LOG_DEBUG, "%s: new incoming call\n", __func__);
-+        tmp = new_call (t);
-+        if (!tmp)
-         {
--        case ICCN:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: sequencing required not appropriate for %s!\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
-+            log (LOG_WARN, "%s: unable to create new call\n", __func__);
-             return -EINVAL;
-         }
-+        tmp->next = t->call_head;
-+        t->call_head = tmp;
-+        t->count++;
-+        /*
-+         * Is this still safe to assume that the head will always
-+         * be the most recent call being negotiated?
-+         * Probably...  FIXME anyway...
-+         */
-     }
--#endif
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int rand_vector_avp (struct tunnel *t, struct call *c, void *data,
-+                     int avplen)
-+{
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      int datalen = avplen - sizeof(struct avp_hdr);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG, "%s: peer requires sequencing.\n", __FUNCTION__);
--    }
-+        log (LOG_DEBUG, "%s: random vector len %d\n", __func__, datalen);
-+    t->chal_us.vector = (unsigned char *)p;
-+    t->chal_us.vector_len = datalen;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int seq_reqd_avp (struct tunnel *t, struct call *c, void *data, int datalen)
-+{
-+    if (debug_avp)
-+      log (LOG_DEBUG, "%s: peer requires sequencing.\n", __func__);
-     c->seq_reqd = -1;
-     return 0;
- }
-+/*****************************************************************************/
- int result_code_avp (struct tunnel *t, struct call *c, void *data,
--                     int datalen)
-+                     int avplen)
- {
--    /*
--     * Find out what version of l2tp the other side is using.
--     * I'm not sure what we're supposed to do with this but whatever..
--     */
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      int datalen = avplen - sizeof(struct avp_hdr);
-+    u_int16_t result = get16(p);
-+    u_int16_t error = get16(p + 2);
--    int error;
--    int result;
--    _u16 *raw = data;
--#ifdef SANITY
--    if (t->sanity)
--    {
--        if (datalen < 10)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is incorrect size.  %d < 10\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Result Code", 10, datalen, 1);
--            return -EINVAL;
--        }
--        switch (c->msgtype)
--        {
--        case CDN:
--        case StopCCN:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: result code not appropriate for %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--    }
--#endif
--    result = ntohs (raw[3]);
--    error = ntohs (raw[4]);
-     if ((c->msgtype == StopCCN) && ((result > 7) || (result < 1)))
-     {
-         if (DEBUG)
-             log (LOG_DEBUG,
--                 "%s: result code out of range (%d %d %d).  Ignoring.\n",
--                 __FUNCTION__, result, error, datalen);
-+                 "%s: (StopCCN) result code out of range ! (1 < %d < 7)\n",
-+                 __func__, result);
-         return 0;
-     }
-@@ -478,1112 +418,348 @@
-     {
-         if (DEBUG)
-             log (LOG_DEBUG,
--                 "%s: result code out of range (%d %d %d).  Ignoring.\n",
--                 __FUNCTION__, result, error, datalen);
-+                 "%s: (CDN) result code out of range !(1 < %d < 11)\n",
-+                 __func__, result);
-         return 0;
-     }
-     c->error = error;
-     c->result = result;
--    safe_copy (c->errormsg, (char *) &raw[5], datalen - 10);
-+      memcpy(c->errormsg, (char*)p + 4, datalen - 4);
-+      c->errormsg[datalen - 4] = '\0';
-+
-     if (debug_avp)
-     {
--        if (DEBUG && (c->msgtype == StopCCN))
-+        if(c->msgtype == StopCCN)
-         {
-             log (LOG_DEBUG,
-                  "%s: peer closing for reason %d (%s), error = %d (%s)\n",
--                 __FUNCTION__, result, stopccn_result_codes[result], error,
-+                 __func__, result, stopccn_result_codes[result], error,
-                  c->errormsg);
-         }
-         else
-         {
-             log (LOG_DEBUG,
-                  "%s: peer closing for reason %d (%s), error = %d (%s)\n",
--                 __FUNCTION__, result, cdn_result_codes[result], error,
-+                 __func__, result, cdn_result_codes[result], error,
-                  c->errormsg);
-         }
-     }
-     return 0;
- }
-+/*****************************************************************************/
- int protocol_version_avp (struct tunnel *t, struct call *c, void *data,
--                          int datalen)
-+                          int avplen)
- {
--    /*
--     * Find out what version of l2tp the other side is using.
--     * I'm not sure what we're supposed to do with this but whatever..
--     */
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--    int ver;
--    _u16 *raw = data;
--#ifdef SANITY
--    if (t->sanity)
--    {
--        if (datalen != 8)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is incorrect size.  %d != 8\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Protocol Version", 8, datalen, 1);
--            return -EINVAL;
--        }
--        switch (c->msgtype)
--        {
--        case SCCRP:
--        case SCCRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: protocol version not appropriate for %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--    }
--#endif
--    ver = ntohs (raw[3]);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer is using version %d, revision %d.\n", __FUNCTION__,
--                 (ver >> 8), ver & 0xFF);
--    }
-+      log (LOG_DEBUG, "%s: peer is using version %d, revision %d.\n", 
-+                       __func__,*p, *(p+1));
-     return 0;
- }
-+/*****************************************************************************/
- int framing_caps_avp (struct tunnel *t, struct call *c, void *data,
--                      int datalen)
-+                      int avplen)
- {
--    /*
--     * Retrieve the framing capabilities
--     * from the peer
--     */
--
--    int caps;
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+    u_int16_t caps = get16(p + 2);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case SCCRP:
--        case SCCRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: framing capabilities not appropriate for %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 10)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is incorrect size.  %d != 10\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Framming Capabilities", 10, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    caps = ntohs (raw[4]);
-     if (debug_avp)
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: supported peer frames:%s%s\n", __FUNCTION__,
--                 caps & ASYNC_FRAMING ? " async" : "",
--                 caps & SYNC_FRAMING ? " sync" : "");
-+      log (LOG_DEBUG, "%s: supported peer frames:%s %s\n", __func__,
-+             caps & ASYNC_FRAMING ? "async" : "",
-+             caps & SYNC_FRAMING ? "sync" : "");
-+
-     t->fc = caps & (ASYNC_FRAMING | SYNC_FRAMING);
-     return 0;
- }
-+/*****************************************************************************/
- int bearer_caps_avp (struct tunnel *t, struct call *c, void *data,
--                     int datalen)
-+                     int avplen)
- {
--    /*
--     * What kind of bearer channels does our peer support?
--     */
--    int caps;
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+    u_int16_t caps = get16(p + 2);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case SCCRP:
--        case SCCRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: bearer capabilities not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 10)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is incorrect size.  %d != 10\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Bearer Capabilities", 10, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    caps = ntohs (raw[4]);
-     if (debug_avp)
--    {
--        if (DEBUG)
--        {
--            log (LOG_DEBUG,
--                 "%s: supported peer bearers:%s%s\n",
--                 __FUNCTION__,
--                 caps & ANALOG_BEARER ? " analog" : "",
--                 caps & DIGITAL_BEARER ? " digital" : "");
--        }
-+      log (LOG_DEBUG, "%s: supported peer bearers:%s %s\n",
-+              __func__,
-+              caps & ANALOG_BEARER ? "analog" : "",
-+              caps & DIGITAL_BEARER ? "digital" : "");
--    }
-     t->bc = caps & (ANALOG_BEARER | DIGITAL_BEARER);
-     return 0;
- }
--
--/* FIXME: I need to handle tie breakers eventually */
--
-+/*****************************************************************************/
- int firmware_rev_avp (struct tunnel *t, struct call *c, void *data,
--                      int datalen)
-+                      int avplen)
- {
--    /*
--     * Report and record remote firmware version
--     */
--    int ver;
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case SCCRP:
--        case SCCRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: firmware revision not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 8)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is incorrect size.  %d != 8\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Firmware Revision", 8, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    ver = ntohs (raw[3]);
-+    t->firmware = get16(p);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer reports firmware version %d (0x%.4x)\n",
--                 __FUNCTION__, ver, ver);
--    }
--    t->firmware = ver;
-+      log (LOG_DEBUG, "%s: peer reports firmware version %d (0x%.4X)\n",
-+              __func__, t->firmware, t->firmware);
-     return 0;
- }
-+/*****************************************************************************/
- int bearer_type_avp (struct tunnel *t, struct call *c, void *data,
--                     int datalen)
-+                     int avplen)
- {
--    /*
--     * What kind of bearer channel is the call on?
--     */
--    int b;
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case ICRQ:
--        case OCRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: bearer type not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 10)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is incorrect size.  %d != 10\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Bearer Type", 10, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    b = ntohs (raw[4]);
-+      t->call_head->bearer = get16(p + 2);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer bears:%s\n", __FUNCTION__,
--                 b & ANALOG_BEARER ? " analog" : "digital");
--    }
--    t->call_head->bearer = b;
-+      log (LOG_DEBUG, "%s: peer bears: %s\n", __func__,
-+             (t->call_head->bearer & ANALOG_BEARER) ? "analog" : "digital");
-     return 0;
- }
--int frame_type_avp (struct tunnel *t, struct call *c, void *data, int datalen)
-+/*****************************************************************************/
-+int frame_type_avp (struct tunnel *t, struct call *c, void *data, int avplen)
- {
--    /*
--     * What kind of frame channel is the call on?
--     */
--    int b;
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case ICCN:
--        case OCRQ:
--        case OCCN:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: frame type not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 10)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is incorrect size.  %d != 10\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Frame Type", 10, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    b = ntohs (raw[4]);
-+      c->frame = get16(p + 2);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer uses:%s frames\n", __FUNCTION__,
--                 b & ASYNC_FRAMING ? " async" : "sync");
--    }
--    c->frame = b;
-+      log (LOG_DEBUG, "%s: peer uses:%s frames\n", __func__,
-+             (c->frame & ASYNC_FRAMING) ? "async" : "sync");
-     return 0;
- }
--int hostname_avp (struct tunnel *t, struct call *c, void *data, int datalen)
-+/*****************************************************************************/
-+int hostname_avp (struct tunnel *t, struct call *c, void *data, int avplen)
- {
--    /*
--     * What is the peer's name?
--     */
--    int size;
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      int datalen = avplen - sizeof(struct avp_hdr);
-+
-+    memcpy(t->hostname, p, datalen);
-+      t->hostname[datalen] = '\0';
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case SCCRP:
--        case SCCRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: hostname not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen < 6)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Hostname", 6, datalen, 1);
--            return -EINVAL;
--        }
--    }
--#endif
--    size = raw[0] & 0x0FFF;
--    if (size > MAXSTRLEN - 1)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG, "%s: truncating reported hostname (size is %d)\n",
--                 __FUNCTION__, size);
--        size = MAXSTRLEN - 1;
--    }
--    safe_copy (t->hostname, (char *) &raw[3], size - 6);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer reports hostname '%s'\n", __FUNCTION__,
--                 t->hostname);
--    }
-+      log (LOG_DEBUG, "%s: peer reports hostname '%s'\n", __func__,
-+             t->hostname);
-+
-     return 0;
- }
--int dialing_number_avp (struct tunnel *t, struct call *c, void *data,
--                        int datalen)
-+/*****************************************************************************/
-+int calling_number_avp (struct tunnel *t, struct call *c, void *data,
-+                        int avplen)
- {
--    /*
--     * What is the peer's name?
--     */
--    int size;
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      int datalen = avplen - sizeof(struct avp_hdr);
-+
-+    memcpy(t->call_head->dialing, p, datalen);
-+      t->call_head->dialing[datalen] = '\0';
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case ICRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: dialing number not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen < 6)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Dialing Number", 6, datalen, 1);
--            return -EINVAL;
--        }
--    }
--#endif
--    size = raw[0] & 0x0FFF;
--    if (size > MAXSTRLEN - 1)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: truncating reported dialing number (size is %d)\n",
--                 __FUNCTION__, size);
--        size = MAXSTRLEN - 1;
--    }
--    safe_copy (t->call_head->dialing, (char *) &raw[3], size);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer reports dialing number '%s'\n", __FUNCTION__,
--                 t->call_head->dialing);
--    }
-+      log (LOG_DEBUG, "%s: peer reports dialing number '%s'\n", __func__,
-+             t->call_head->dialing);
-+
-     return 0;
- }
--int dialed_number_avp (struct tunnel *t, struct call *c, void *data,
--                       int datalen)
-+/*****************************************************************************/
-+int called_number_avp (struct tunnel *t, struct call *c, void *data,
-+                       int avplen)
- {
--    /*
--     * What is the peer's name?
--     */
--    int size;
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      int datalen = avplen - sizeof(struct avp_hdr);
-+
-+    memcpy(t->call_head->dialed, p, datalen);
-+      t->call_head->dialed[datalen] = '\0';
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case OCRQ:
--        case ICRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: dialed number not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen < 6)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Dialed Number", 6, datalen, 1);
--            return -EINVAL;
--        }
--    }
--#endif
--    size = raw[0] & 0x0FFF;
--    if (size > MAXSTRLEN - 1)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: truncating reported dialed number (size is %d)\n",
--                 __FUNCTION__, size);
--        size = MAXSTRLEN - 1;
--    }
--    safe_copy (t->call_head->dialed, (char *) &raw[3], size);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer reports dialed number '%s'\n", __FUNCTION__,
--                 t->call_head->dialed);
--    }
-+      log (LOG_DEBUG, "%s: peer reports dialed number '%s'\n", __func__,
-+             t->call_head->dialed);
-+
-     return 0;
- }
-+/*****************************************************************************/
- int sub_address_avp (struct tunnel *t, struct call *c, void *data,
--                     int datalen)
-+                     int avplen)
- {
--    /*
--     * What is the peer's name?
--     */
--    int size;
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      int datalen = avplen - sizeof(struct avp_hdr);
-+
-+      memcpy(t->call_head->subaddy, p, datalen);
-+      t->call_head->subaddy[datalen] = '\0';
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case OCRP:
--        case ICRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: sub_address not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen < 6)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Sub-address", 6, datalen, 1);
--            return -EINVAL;
--        }
--    }
--#endif
--    size = raw[0] & 0x0FFF;
--    if (size > MAXSTRLEN - 1)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: truncating reported sub address (size is %d)\n",
--                 __FUNCTION__, size);
--        size = MAXSTRLEN - 1;
--    }
--    safe_copy (t->call_head->subaddy, (char *) &raw[3], size);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer reports subaddress '%s'\n", __FUNCTION__,
--                 t->call_head->subaddy);
--    }
-+      log (LOG_DEBUG, "%s: peer reports subaddress '%s'\n", __func__,
-+             t->call_head->subaddy);
-     return 0;
- }
--int vendor_avp (struct tunnel *t, struct call *c, void *data, int datalen)
-+/*****************************************************************************/
-+int vendor_avp (struct tunnel *t, struct call *c, void *data, int avplen)
- {
--    /*
--     * What vendor makes the other end?
--     */
--    int size;
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      int datalen = avplen - sizeof(struct avp_hdr);
-+
-+      memcpy(t->vendor, p, datalen);
-+      t->vendor[datalen] = '\0';
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case SCCRP:
--        case SCCRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: vendor not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen < 6)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Vendor", 6, datalen, 1);
--            return -EINVAL;
--        }
--    }
--#endif
--    size = raw[0] & 0x0FFF;
--    if (size > MAXSTRLEN - 1)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG, "%s: truncating reported vendor (size is %d)\n",
--                 __FUNCTION__, size);
--        size = MAXSTRLEN - 1;
--    }
--    safe_copy (t->vendor, (char *) &raw[3], size);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer reports vendor '%s'\n", __FUNCTION__, t->vendor);
--    }
-+      log (LOG_DEBUG, "%s: peer reports vendor '%s'\n", __func__, t->vendor);
-     return 0;
- }
--int challenge_avp (struct tunnel *t, struct call *c, void *data, int datalen)
-+/*****************************************************************************/
-+int challenge_avp (struct tunnel *t, struct call *c, void *data, int avplen)
- {
--    /*
--     * We are sent a challenge
--     */
--    _u16 *raw = data;
--    int size;
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case SCCRP:
--        case SCCRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: challenge not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen < 6)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "challenge", 6, datalen, 1);
--            return -EINVAL;
--        }
--    }
--#endif
--    /* size = raw[0] & 0x0FFF; */
--    /* length field of AVP's is only 10 bits long, not 12 */
--    size = raw[0] & 0x03FF;
--    size -= sizeof (struct avp_hdr);
--    /* if (size != MD_SIG_SIZE)
--    {
--        log (LOG_DEBUG, "%s: Challenge is not the right length (%d != %d)\n",
--             __FUNCTION__, size, MD_SIG_SIZE);
--        return -EINVAL;
--    } */
--    t->chal_us.challenge = malloc(size+1);
--    if (t->chal_us.challenge == NULL)
--    {
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      int datalen = avplen - sizeof(struct avp_hdr);
-+
-+    t->chal_us.challenge = calloc(datalen, 1);
-+    if (!t->chal_us.challenge)
-         return -ENOMEM;
--    }
--    memset(t->chal_us.challenge, 0, size+1);
--    bcopy (&raw[3], (t->chal_us.challenge), size);
-+    memcpy(t->chal_us.challenge, p, datalen);
-     t->chal_us.state = STATE_CHALLENGED;
-+
-     if (debug_avp)
--    {
--        log (LOG_DEBUG, "%s: challenge avp found\n", __FUNCTION__);
--    }
-+      log (LOG_DEBUG, "%s: challenge avp found\n", __func__);
-+
-     return 0;
- }
--int chalresp_avp (struct tunnel *t, struct call *c, void *data, int datalen)
-+/*****************************************************************************/
-+int chalresp_avp (struct tunnel *t, struct call *c, void *data, int avplen)
- {
--    /*
--     * We are sent a challenge
--     */
--    _u16 *raw = data;
--    int size;
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case SCCRP:
--        case SCCCN:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: challenge response not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen < 6)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is too small.  %d < 6\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "challenge", 6, datalen, 1);
--            return -EINVAL;
--        }
--    }
--#endif
--    size = raw[0] & 0x0FFF;
--    size -= sizeof (struct avp_hdr);
--    if (size != MD_SIG_SIZE)
--    {
--        log (LOG_DEBUG, "%s: Challenge is not the right length (%d != %d)\n",
--             __FUNCTION__, size, MD_SIG_SIZE);
--        return -EINVAL;
--    }
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--    bcopy (&raw[3], t->chal_them.reply, MD_SIG_SIZE);
--    if (debug_avp)
--    {
--        log (LOG_DEBUG, "%s: Challenge reply found\n", __FUNCTION__);
--    }
-+    memcpy(t->chal_them.reply, p, MD_SIG_SIZE);
-+    if(debug_avp)
-+      log(LOG_DEBUG, "%s: Challenge reply found\n", __func__);
-     return 0;
- }
-+/*****************************************************************************/
- int assigned_tunnel_avp (struct tunnel *t, struct call *c, void *data,
--                         int datalen)
-+                         int avplen)
- {
--    /*
--     * What is their TID that we must use from now on?
--     */
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      u_int16_t id = get16(p);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case SCCRP:
--        case SCCRQ:
--        case StopCCN:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: tunnel ID not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 8)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is wrong size.  %d != 8\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Assigned Tunnel ID", 8, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
-     if (c->msgtype == StopCCN)
--    {
--        t->qtid = ntohs (raw[3]);
--    }
-+        t->qtid = id;
-     else
--    {
--        t->tid = ntohs (raw[3]);
--    }
-+        t->tid = id;
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: using peer's tunnel %d\n", __FUNCTION__,
--                 ntohs (raw[3]));
--    }
-+      log (LOG_DEBUG, "%s: using peer's tunnel %d\n", __func__, id);
-     return 0;
- }
--int assigned_call_avp (struct tunnel *t, struct call *c, void *data,
--                       int datalen)
-+/*****************************************************************************/
-+int assigned_session_avp (struct tunnel *t, struct call *c, void *data,
-+                       int avplen)
- {
--    /*
--     * What is their CID that we must use from now on?
--     */
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
-+      u_int16_t id = get16(p);
-+
-+      switch(c->msgtype) {
-+              case CDN:
-+              case ICRP:
-+              case OCRP:
-+                      c->cid = id;
-+                      break;
-+              case ICRQ:
-+                      t->call_head->cid = id;
-+                      break;
-+      };
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case CDN:
--        case ICRP:
--        case ICRQ:
--        case OCRP:             /* jz: deleting the debug message */
--            break;
--        case OCRQ:
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: call ID not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 8)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is wrong size.  %d != 8\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Assigned Call ID", 8, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    if (c->msgtype == CDN)
--    {
--        c->qcid = ntohs (raw[3]);
--    }
--    else if (c->msgtype == ICRQ)
--    {
--        t->call_head->cid = ntohs (raw[3]);
--    }
--    else if (c->msgtype == ICRP)
--    {
--        c->cid = ntohs (raw[3]);
--    }
--    else if (c->msgtype == OCRP)
--    {                           /* jz: copy callid to c->cid */
--        c->cid = ntohs (raw[3]);
--    }
--    else
--    {
--        log (LOG_DEBUG, "%s:  Dunno what to do when it's state %s!\n",
--             __FUNCTION__, msgtypes[c->msgtype]);
--    }
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: using peer's call %d\n", __FUNCTION__, ntohs (raw[3]));
--    }
-+      log (LOG_DEBUG, "%s: assigned session id: %d\n", __func__, id);
-     return 0;
- }
-+/*****************************************************************************/
- int packet_delay_avp (struct tunnel *t, struct call *c, void *data,
--                      int datalen)
-+                      int avplen)
- {
--    /*
--     * What is their CID that we must use from now on?
--     */
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case ICRP:
--        case OCRQ:
--        case ICCN:
--        case OCRP:
--        case OCCN:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: packet delay not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 8)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is wrong size.  %d != 8\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Assigned Call ID", 8, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    c->ppd = ntohs (raw[3]);
-+    c->ppd = get16(p);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer's delay is %d 1/10's of a second\n", __FUNCTION__,
--                 ntohs (raw[3]));
--    }
-+      log (LOG_DEBUG, "%s: peer's delay is %d 1/10's of a second\n", __func__,
-+             c->ppd);
-     return 0;
- }
--int call_serno_avp (struct tunnel *t, struct call *c, void *data, int datalen)
-+/*****************************************************************************/
-+int call_serno_avp (struct tunnel *t, struct call *c, void *data, int avplen)
- {
-     /*
-      * What is the serial number of the call?
-      */
--    _u16 *raw = data;
--
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case ICRQ:
--        case OCRQ:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: call ID not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 10)
--        {
--#ifdef STRICT
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is wrong size.  %d != 10\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Serial Number", 10, datalen, 0);
--            return -EINVAL;
--#else
--            log (LOG_DEBUG,
--                 "%s: peer is using old style serial number.  Will be invalid.\n",
--                 __FUNCTION__);
--#endif
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--        }
--    }
--#endif
--    t->call_head->serno = (((unsigned int) ntohs (raw[3])) << 16) |
--        ((unsigned int) ntohs (raw[4]));
-+    t->call_head->serno = get32(p);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: serial number is %d\n", __FUNCTION__,
--                 t->call_head->serno);
--    }
-+      log (LOG_DEBUG, "%s: serial number is %d\n", __func__, 
-+                       t->call_head->serno);
-     return 0;
- }
--int rx_speed_avp (struct tunnel *t, struct call *c, void *data, int datalen)
-+/*****************************************************************************/
-+int rx_speed_avp (struct tunnel *t, struct call *c, void *data, int avplen)
- {
--    /*
--     * What is the received baud rate of the call?
--     */
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case ICCN:
--        case OCCN:
--        case OCRP:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: rx connect speed not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 10)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is wrong size.  %d != 10\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Connect Speed (RX)", 10, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    c->rxspeed = (((unsigned int) ntohs (raw[3])) << 16) |
--        ((unsigned int) ntohs (raw[4]));
--    if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: receive baud rate is %d\n", __FUNCTION__, c->rxspeed);
--    }
-+    c->rxspeed = get32(p);
-+    if(debug_avp)
-+      log(LOG_DEBUG, "%s: receive baud rate is %d\n", __func__, c->rxspeed);
-     return 0;
- }
--int tx_speed_avp (struct tunnel *t, struct call *c, void *data, int datalen)
-+/*****************************************************************************/
-+int tx_speed_avp (struct tunnel *t, struct call *c, void *data, int avplen)
- {
--    /*
--     * What is the tranmsit baud rate of the call?
--     */
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case ICCN:
--        case OCCN:
--        case OCRP:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: tx connect speed not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 10)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is wrong size.  %d != 10\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Connect Speed (tx)", 10, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    c->txspeed = (((unsigned int) ntohs (raw[3])) << 16) |
--        ((unsigned int) ntohs (raw[4]));
-+    c->txspeed = get32(p);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: transmit baud rate is %d\n", __FUNCTION__, c->txspeed);
--    }
-+      log (LOG_DEBUG, "%s: transmit baud rate is %d\n", 
-+                       __func__, c->txspeed);
-     return 0;
- }
-+
-+/*****************************************************************************/
- int call_physchan_avp (struct tunnel *t, struct call *c, void *data,
--                       int datalen)
-+                       int avplen)
- {
--    /*
--     * What is the physical channel?
--     */
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case ICRQ:
--        case OCRQ:
--        case OCRP:
--        case OCCN:
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: physical channel not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 10)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is wrong size.  %d != 10\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Physical Channel", 10, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    t->call_head->physchan = (((unsigned int) ntohs (raw[3])) << 16) |
--        ((unsigned int) ntohs (raw[4]));
-+    t->call_head->physchan = get32(p);
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: physical channel is %d\n", __FUNCTION__,
--                 t->call_head->physchan);
--    }
-+      log(LOG_DEBUG, "%s: physical channel is %d\n", __func__,
-+                      t->call_head->physchan);
-     return 0;
- }
-+/*****************************************************************************/
- int receive_window_size_avp (struct tunnel *t, struct call *c, void *data,
--                             int datalen)
-+                             int avplen)
- {
--    /*
--     * What is their RWS?
--     */
--    _u16 *raw = data;
-+      u_int8_t *p = data + sizeof(struct avp_hdr);
--#ifdef SANITY
--    if (t->sanity)
--    {
--        switch (c->msgtype)
--        {
--        case SCCRP:
--        case SCCRQ:
--        case OCRP:             /* jz */
--        case OCCN:             /* jz */
--        case StopCCN:
--/*            case ICRP:
--              case ICCN: */
--            break;
--        default:
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: RWS not appropriate for message %s.  Ignoring.\n",
--                     __FUNCTION__, msgtypes[c->msgtype]);
--            return 0;
--        }
--        if (datalen != 8)
--        {
--            if (DEBUG)
--                log (LOG_DEBUG,
--                     "%s: avp is wrong size.  %d != 8\n", __FUNCTION__,
--                     datalen);
--            wrong_length (c, "Receive Window Size", 8, datalen, 0);
--            return -EINVAL;
--        }
--    }
--#endif
--    t->rws = ntohs (raw[3]);
-+    t->rws = get16(p);
- /*    if (c->rws >= 0)
-               c->fbit = FBIT; */
-     if (debug_avp)
--    {
--        if (DEBUG)
--            log (LOG_DEBUG,
--                 "%s: peer wants RWS of %d.  Will use flow control.\n",
--                 __FUNCTION__, t->rws);
--    }
-+              log (LOG_DEBUG, "%s: peer wants RWS of %d.  Will use flow control.\n",
-+             __func__, t->rws);
-     return 0;
- }
-+/*****************************************************************************/
- int handle_avps (struct buffer *buf, struct tunnel *t, struct call *c)
- {
-     /*
-@@ -1594,82 +770,100 @@
-     struct avp_hdr *avp;
-     int len = buf->len - sizeof (struct control_hdr);
-+      u_int16_t rlen = 0;
-+      u_int16_t attr = 0;
-     int firstavp = -1;
--    int hidlen;
-+    int hidlen = 0;
-     char *data = buf->start + sizeof (struct control_hdr);
-     avp = (struct avp_hdr *) data;
-+
-     if (debug_avp)
-         log (LOG_DEBUG, "%s: handling avp's for tunnel %d, call %d\n",
--             __FUNCTION__, t->ourtid, c->ourcid);
-+             __func__, t->ourtid, c->ourcid);
-+
-+      if(len < 6) {
-+      log (LOG_WARN, "%s: packet too small\n", __func__);
-+        set_error(c, ERROR_LENGTH, "Invalid message length");
-+        return -EINVAL;
-+      }
-+
-     while (len > 0)
-     {
--        /* Go ahead and byte-swap the header */
--        swaps (avp, sizeof (struct avp_hdr));
--        if (avp->attr > AVP_MAX)
-+              rlen = get16((u_int8_t*)&avp->length);
-+              attr = get16((u_int8_t*)&avp->attr);
-+
-+              /* AVP header checks */
-+        if (attr > AVP_MAX)
-         {
--            if (AMBIT (avp->length))
-+            if (AMBIT(rlen))
-             {
-                 log (LOG_WARN,
--                     "%s:  dont know how to handle mandatory attribute %d.  Closing %s.\n"
--                     __FUNCTION__, avp->attr,
--                     (c != t->self) ? "call" : "tunnel");
--                set_error (c, VENDOR_ERROR,
--                           "mandatory attribute %d cannot be handled",
--                           avp->attr);
--                c->needclose = -1;
-+                     "%s:  unhandeled mandatory attribute %d.  Closing %s.\n", 
-+                     __func__, attr, (c != t->self) ? "call" : "tunnel");
-+                set_error (c, VENDOR_ERROR, 
-+                                                 "mandatory attribute %d cannot be handled", attr);
-                 return -EINVAL;
-             }
-             else
-             {
-                 if (DEBUG)
-                     log (LOG_WARN,
--                         "%s:  dont know how to handle atribute %d.\n",
--                         __FUNCTION__, avp->attr);
-+                         "%s: handeled attribute %d.\n",
-+                         __func__, attr);
-                 goto next;
-             }
-         }
--        if (ALENGTH (avp->length) > len)
-+        if (ALENGTH (rlen) > len)
-         {
-             log (LOG_WARN,
--                 "%s: AVP received with length > remaining packet length!\n",
--                 __FUNCTION__);
-+                 "%s: AVP reported length > remaining packet length\n",
-+                 __func__);
-             set_error (c, ERROR_LENGTH, "Invalid AVP length");
--            c->needclose = -1;
-             return -EINVAL;
-         }
--        if (avp->attr && firstavp)
-+              if (ALENGTH (rlen) < sizeof (struct avp_hdr))
-         {
--            log (LOG_WARN, "%s: First AVP was not message type.\n",
--                 __FUNCTION__);
--            set_error (c, VENDOR_ERROR, "First AVP must be message type");
--            c->needclose = -1;
-+            log (LOG_WARN, "%s: AVP reported length too small (%d).\n",
-+                 __func__, ALENGTH (rlen));
-+            set_error (c, ERROR_LENGTH, "AVP too small");
-             return -EINVAL;
-         }
--        if (ALENGTH (avp->length) < sizeof (struct avp_hdr))
-+              if (avps[attr].sz) {
-+                      if((avps[attr].flags & AVP_F_FIXLEN) ?  
-+                         (ALENGTH(rlen) - sizeof(struct avp_hdr)) != avps[attr].sz :
-+                         (ALENGTH(rlen) - sizeof(struct avp_hdr)) > avps[attr].sz) {
-+                              log (LOG_DEBUG, "%s: %s avp size mismatch  (%d %s %d)\n", 
-+                                      __func__,
-+                                      avps[attr].description, 
-+                                      (avps[attr].flags & AVP_F_FIXLEN) ? "!=" : "<", 
-+                                      ALENGTH(rlen), avps[attr].sz);
-+                              set_error (c, ERROR_LENGTH, "AVP size check failed");
-+                              return -EINVAL;
-+                      }
-+              }
-+        if (attr && firstavp)
-         {
--            log (LOG_WARN, "%s: AVP with too small of size (%d).\n",
--                 __FUNCTION__, ALENGTH (avp->length));
--            set_error (c, ERROR_LENGTH, "AVP too small");
--            c->needclose = -1;
-+            log (LOG_WARN, "%s: First AVP was not message type.\n",
-+                 __func__);
-+            set_error (c, VENDOR_ERROR, "First AVP must be message type");
-             return -EINVAL;
-         }
--        if (AZBITS (avp->length))
-+        if (AZBITS (rlen))
-         {
--            log (LOG_WARN, "%s: %sAVP has reserved bits set.\n", __FUNCTION__,
--                 AMBIT (avp->length) ? "Mandatory " : "");
--            if (AMBIT (avp->length))
-+            log (LOG_WARN, "%s: %sAVP has reserved bits set.\n", __func__,
-+                 AMBIT (rlen) ? "Mandatory " : "");
-+            if (AMBIT (rlen))
-             {
-                 set_error (c, ERROR_RESERVED, "reserved bits set in AVP");
--                c->needclose = -1;
-                 return -EINVAL;
-             }
-             goto next;
-         }
--        if (AHBIT (avp->length))
-+
-+              /* decryption */
-+        if (AHBIT (rlen))
-         {
--#ifdef DEBUG_HIDDEN
--            log (LOG_DEBUG, "%s: Hidden bit set on AVP.\n", __FUNCTION__);
--#endif
-+            log (LOG_DEBUG, "%s: Hidden bit set on AVP.\n", __func__);
-             /* We want to rewrite the AVP as an unhidden AVP
-                and then pass it along as normal.  Remeber how
-                long the AVP was in the first place though! */
-@@ -1678,12 +872,11 @@
-             {
-                 if (debug_avp)
-                     log (LOG_WARN, "%s: Unable to handle hidden %sAVP\n:",
--                         __FUNCTION__,
--                         (AMBIT (avp->length) ? "mandatory " : ""));
--                if (AMBIT (avp->length))
-+                         __func__,
-+                         (AMBIT (rlen) ? "mandatory " : ""));
-+                if (AMBIT (rlen))
-                 {
-                     set_error (c, VENDOR_ERROR, "Invalid Hidden AVP");
--                    c->needclose = -1;
-                     return -EINVAL;
-                 }
-                 goto next;
-@@ -1696,17 +889,43 @@
-         }
-         else
-             hidlen = 0;
--        if (avps[avp->attr].handler)
-+
-+              /* validate */
-+              if (avps[attr].validate) 
-+              {
-+                      if(avps[attr].validate(attr, t, c, avp, ALENGTH (rlen))) {
-+                               if (AMBIT (rlen))
-+                {
-+                    log (LOG_WARN,
-+                         "%s: verification of AVP %d (%s) failed.\n",
-+                         __func__, attr,
-+                         avps[attr].description);
-+                                      set_error (c, VENDOR_ERROR, "processing failed on mandatory AVP");
-+                    return -EINVAL;
-+                }
-+                else
-+                {
-+                    if (DEBUG)
-+                        log (LOG_DEBUG,
-+                             "%s: Bad exit status handling attribute %d (%s).\n",
-+                             __func__, attr,
-+                             avps[attr].description);
-+                }
-+                      }
-+              }
-+
-+              /* handling */
-+        if (avps[attr].handle)
-         {
--            if (avps[avp->attr].handler (t, c, avp, ALENGTH (avp->length)))
-+            if (avps[attr].handle(t, c, avp, ALENGTH (rlen)))
-             {
--                if (AMBIT (avp->length))
-+                if (AMBIT (rlen))
-                 {
-                     log (LOG_WARN,
--                         "%s: Bad exit status handling attribute %d (%s) on mandatory packet.\n",
--                         __FUNCTION__, avp->attr,
--                         avps[avp->attr].description);
--                    c->needclose = -1;
-+                         "%s: Bad exit status handling mandatory attribute %d (%s).\n",
-+                         __func__, attr,
-+                         avps[attr].description);
-+                                      set_error (c, VENDOR_ERROR, "processing failed on mandatory AVP");
-                     return -EINVAL;
-                 }
-                 else
-@@ -1714,29 +933,31 @@
-                     if (DEBUG)
-                         log (LOG_DEBUG,
-                              "%s: Bad exit status handling attribute %d (%s).\n",
--                             __FUNCTION__, avp->attr,
--                             avps[avp->attr].description);
-+                             __func__, attr,
-+                             avps[attr].description);
-                 }
-             }
-         }
-         else
-         {
--            if (AMBIT (avp->length))
-+            if (AMBIT (rlen))
-             {
-                 log (LOG_WARN,
-                      "%s:  No handler for mandatory attribute %d (%s).  Closing %s.\n",
--                     __FUNCTION__, avp->attr, avps[avp->attr].description,
-+                     __func__, attr, 
-+                                       avps[attr].description,
-                      (c != t->self) ? "call" : "tunnel");
-                 set_error (c, VENDOR_ERROR, "No handler for attr %d (%s)\n",
--                           avp->attr, avps[avp->attr].description);
-+                           attr, 
-+                                                 avps[attr].description);
-                 return -EINVAL;
-             }
-             else
-             {
-                 if (DEBUG)
-                     log (LOG_WARN, "%s:  no handler for atribute %d (%s).\n",
--                         __FUNCTION__, avp->attr,
--                         avps[avp->attr].description);
-+                         __func__, attr,
-+                         avps[attr].description);
-             }
-         }
-       next:
-@@ -1748,16 +969,17 @@
-         }
-         else
-         {
--            len -= ALENGTH (avp->length);
--            data += ALENGTH (avp->length);      /* Next AVP, please */
-+            len -= ALENGTH (rlen);
-+            data += ALENGTH (rlen);      /* Next AVP, please */
-         }
-         avp = (struct avp_hdr *) data;
-         firstavp = 0;
-     }
-     if (len != 0)
-     {
--        log (LOG_WARN, "%s: negative overall packet length\n", __FUNCTION__);
-+        log (LOG_WARN, "%s: negative overall packet length\n", __func__);
-         return -EINVAL;
-     }
-+
-     return 0;
- }
---- l2tpd-0.70-pre20031121.orig/avpsend.c
-+++ l2tpd-0.70-pre20031121/avpsend.c
-@@ -1,11 +1,5 @@
- /*
-- * $Id$
-- *
-- * Layer Two Tunnelling Protocol Daemon
-- * Copyright (C) 1998 Adtran, Inc.
-- * Copyright (C) 2002 Jeff McAdams
-- *
-- * Mark Spencer
-+ * Copyright (C) 2004 Jean-Francois Dive
-  *
-  * This software is distributed under the terms
-  * of the GPL, which you should have received
-@@ -14,337 +8,288 @@
-  * Attribute Value Pair creating routines
-  */
-+/* TODO: Handle Tie break */
-+/* TODO: Get real hostname / config */
-+/* TODO: There should be an overflow check on
-+ *             the buffer size. (safe for now as 
-+ *             packet size = 4k
-+ */
-+
- #include <stdlib.h>
- #include <string.h>
--#include <netinet/in.h>
-+#include <unistd.h>
- #include "l2tp.h"
--/* 
-- * These routines should add avp's to a buffer
-- * to be sent
-- */
-+extern struct avp avps[];
-+/* We could add here padding support which would allow
-+ * to keep alignemnt straight <jdive> */
-+static int add_avp(struct buffer *buf, u_int32_t avpid, unsigned char *v, 
-+                             u_int32_t sz, u_int8_t setpayload) {
-+      u_int8_t *p = buf->start + buf->len;
-+
-+      if(avpid > AVP_MAX  || !avps[avpid].flags) {
-+              log(LOG_DEBUG, "%s: invalid avp id %d\n", __func__, avpid);
-+              return 1;
-+      }
-+
-+      set16(p, (sz + 6) | (avps[avpid].flags & AVP_F_MANDATORY ? MBIT : 0));
-+      set16(p + 2, VENDOR_ID);
-+      set16(p + 4, avpid);
-+      if(setpayload) 
-+              memcpy(p + 6, v, sz);
--/* FIXME:  If SANITY is on, we should check for buffer overruns */
-+      buf->len += (sz + 6);
-+      return 0;
-+}
--/* FIXME: Can't this be condensed alot? */
-+/*****************************************************************************/
-+int add_message_type_avp(struct buffer *buf, _u16 type) {
-+      u_int8_t t[2];
-+      set16(t, type);
-+      if(add_avp(buf, MESSAGE_TYPE_AVP, t, 2, 1))
-+              return 1;
-+    return 0;
-+}
--int add_message_type_avp (struct buffer *buf, _u16 type)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0x8 | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = 0;
--    raw[3] = htons (type);
--    buf->len += 8;
-+/*****************************************************************************/
-+int add_protocol_avp(struct buffer *buf) {
-+      u_int8_t t[2];
-+      set16(t, OUR_L2TP_VERSION);
-+      if(add_avp(buf, PROTOCOL_VERSION_AVP, t, 2, 1))
-+              return 1;
-     return 0;
- }
--int add_protocol_avp (struct buffer *buf)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0x8 | MBIT);        /* Length and M bit */
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x2);       /* Value of our AVP */
--    raw[3] = htons (OUR_L2TP_VERSION);
--    buf->len += 8;
-+/*****************************************************************************/
-+int add_frame_caps_avp(struct buffer *buf, _u16 caps) {
-+      u_int8_t t[4];
-+      t[0] = 0; 
-+      t[1] = 0;
-+      set16(&t[2], caps);
-+      if(add_avp(buf, FRAMING_CAP_AVP, t, 4, 1))
-+              return 1;
-     return 0;
- }
--int add_frame_caps_avp (struct buffer *buf, _u16 caps)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0xA | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x3);
--    raw[3] = 0;
--    raw[4] = htons (caps);
--    buf->len += 10;
-+/*****************************************************************************/
-+int add_bearer_caps_avp(struct buffer *buf, _u16 caps) {
-+      u_int8_t t[4];
-+      t[0] = 0; 
-+      t[1] = 0;
-+      set16(&t[2], caps);
-+      if(add_avp(buf, BEARER_CAP_AVP, t, 4, 1))
-+              return 1;
-     return 0;
- }
--int add_bearer_caps_avp (struct buffer *buf, _u16 caps)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0xA | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x4);
--    raw[3] = 0;
--    raw[4] = htons (caps);
--    buf->len += 10;
-+/*****************************************************************************/
-+int add_firmware_avp(struct buffer *buf) {
-+      u_int8_t t[2];
-+      set16(t, OUR_L2TP_VERSION);
-+      if(add_avp(buf, FIRMWARE_REV_AVP, t, 2, 1))
-+              return 1;
-     return 0;
- }
--/* FIXME: I need to send tie breaker AVP's */
--
--int add_firmware_avp (struct buffer *buf)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0x8);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x6);
--    raw[3] = htons (FIRMWARE_REV);
--    buf->len += 8;
-+/*****************************************************************************/
-+int add_hostname_avp(struct buffer *buf, struct tunnel *t) {
-+      char n[STRLEN];
-+      int sz = 0;
-+      if(t->lac && t->lac->hostname[0]) {
-+              strncpy(n,t->lac->hostname, sizeof(n));
-+              sz = strnlen(t->lac->hostname, sizeof(t->lac->hostname));
-+      }
-+      else if(t->lns && t->lns->hostname[0]) {
-+              strncpy(n,t->lns->hostname, sizeof(n));
-+              sz = strnlen(t->lns->hostname, sizeof(t->lns->hostname));
-+      }
-+      else {
-+              if(gethostname(n, STRLEN)) {
-+                      strcpy(n,"eriwan");
-+                      sz = 6;
-+              }
-+              else
-+                      sz = strnlen(n, sizeof(n));
-+      }
-+      if(add_avp(buf, HOSTNAME_AVP, n, sz, 1))
-+              return 1;
-     return 0;
- }
--/*
--int add_hostname_avp(struct buffer *buf) {
--      _u16 *raw = (_u16 *)(buf->start + buf->len);
--      raw[0] = htons((0x6 + strlen(hostname)) | MBIT);
--      raw[1] = htons(VENDOR_ID);
--      raw[2] = htons(0x7);
--      strcpy((char *)(&raw[3]), hostname);
--      buf->len += 6 + strlen(hostname);
--      return 0;
-+/*****************************************************************************/
-+int add_vendor_avp(struct buffer *buf) {
-+      if(add_avp(buf, VENDOR_NAME_AVP, VENDOR_NAME, strlen(VENDOR_NAME), 1))
-+              return 1;
-+    return 0;
- }
--*/
--int add_hostname_avp (struct buffer *buf)
--{
--    char names[6] = "eriwan";
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0xC | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x7);
--    strcpy ((char *) (&raw[3]), names);
--    buf->len += 12;
--    return 0;
--}
--
--int add_vendor_avp (struct buffer *buf)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0x6 + strlen (VENDOR_NAME));
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x8);
--    strcpy ((char *) (&raw[3]), VENDOR_NAME);
--    buf->len += 6 + strlen (VENDOR_NAME);
--    return 0;
--}
--
--int add_tunnelid_avp (struct buffer *buf, _u16 tid)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0x8 | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x9);
--    raw[3] = htons (tid);
--    buf->len += 8;
--    return 0;
--}
--
--int add_avp_rws (struct buffer *buf, _u16 rws)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0x8 | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0xA);
--    raw[3] = htons (rws);
--    buf->len += 8;
--    return 0;
--}
--
--int add_challenge_avp (struct buffer *buf, char *c, int len)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons ((0x6 + len) | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0xB);
--    bcopy (c, (char *) (&raw[3]), len);
--    buf->len += 6 + len;
--    return 0;
--}
--
--int add_chalresp_avp (struct buffer *buf, char *c, int len)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons ((0x6 + len) | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0xD);
--    bcopy (c, (char *) (&raw[3]), len);
--    buf->len += 6 + len;
--    return 0;
--}
--
--int add_randvect_avp (struct buffer *buf, char *c, int len)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons ((0x6 + len) | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x24);
--    bcopy (c, (char *) (&raw[3]), len);
--    buf->len += 6 + len;
--    return 0;
--}
--
--int add_result_code_avp (struct buffer *buf, _u16 result, _u16 error,
--                         char *msg, int len)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons ((0xA + len) | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x1);
--    raw[3] = htons (result);
--    raw[4] = htons (error);
--    bcopy (msg, (char *) &raw[5], len);
--    buf->len += (10 + len);
-+/*****************************************************************************/
-+int add_tunnelid_avp(struct buffer *buf, _u16 tid) {
-+      u_int8_t t[2];
-+      set16(t, tid);
-+      if(add_avp(buf, ASSIGNED_TUN_ID_AVP, t, 2, 1))
-+              return 1;
-     return 0;
- }
-+/*****************************************************************************/
-+int add_avp_rws(struct buffer *buf, _u16 rws) {
-+      u_int8_t t[2];
-+      set16(t, rws);
-+      if(add_avp(buf, RX_WIN_SIZE_AVP, t, 2, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_challenge_avp(struct buffer *buf, char *c, int len) {
-+      if(add_avp(buf, CHALLENGE_AVP, c, len, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_chalresp_avp(struct buffer *buf, char *c, int len) {
-+      if(add_avp(buf, CHALLENGE_RESP_AVP, c, len, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_randvect_avp(struct buffer *buf, char *c, int len) {
-+      if(add_avp(buf, RANDOM_VECTOR_AVP, c, len, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_result_code_avp(struct buffer *buf, _u16 result, _u16 error,
-+                        char *msg, int len) {
-+      u_int8_t t[4];
-+      set16(t, result);
-+      set16(&t[2], error);
-+      memcpy((u_int8_t*)(buf->start + buf->len + 10), msg, len);
-+      memcpy((u_int8_t*)(buf->start + buf->len + 6), t, 4);
-+      if(add_avp(buf, RESULT_CODE_AVP, 0, 4 + len, 0))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
- #ifdef TEST_HIDDEN
--int add_callid_avp (struct buffer *buf, _u16 callid, struct tunnel *t)
--{
--#else
--int add_callid_avp (struct buffer *buf, _u16 callid)
--{
--#endif
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--#ifdef TEST_HIDDEN
-+int add_callid_avp(struct buffer *buf, _u16 callid, struct tunnel *t) {
-+      u_int8_t t[2];
-     if (t->hbit)
-         raw++;
--#endif
--    raw[0] = htons (0x8 | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0xE);
--    raw[3] = htons (callid);
--    buf->len += 8;
--#ifdef TEST_HIDDEN
-+      set16(t, callid);
-+      if(add_avp(buf, ASSIGNED_SES_ID_AVP, t, 2, 1))
-+              return 1;
-     if (t->hbit)
-         encrypt_avp (buf, 8, t);
-+    return 0;
-+}
-+#else
-+int add_callid_avp(struct buffer *buf, _u16 callid) {
-+      u_int8_t t[2];
-+      set16(t, callid);
-+      if(add_avp(buf, ASSIGNED_SES_ID_AVP, t, 2, 1))
-+              return 1;
-+    return 0;
-+}
- #endif
-+
-+/*****************************************************************************/
-+int add_serno_avp(struct buffer *buf, unsigned int serno) {
-+      u_int8_t t[4];
-+      set32(t, serno);
-+      if(add_avp(buf, SERIAL_NUMBER_AVP, t, 4, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_bearer_avp(struct buffer *buf, int bearer) {
-+      u_int8_t t[4];
-+      set32(t, bearer);
-+      if(add_avp(buf, BEARER_TYPE_AVP, t, 4, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_frame_avp(struct buffer *buf, int frame) {
-+      u_int8_t t[4];
-+      set32(t, frame);
-+      if(add_avp(buf, FRAMING_TYPE_AVP, t, 4, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_txspeed_avp(struct buffer *buf, int speed) {
-+      u_int8_t t[4];
-+      set32(t, speed);
-+      if(add_avp(buf, TX_CONNECT_SPEED_AVP, t, 4, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_rxspeed_avp(struct buffer *buf, int speed) {
-+      u_int8_t t[4];
-+      set32(t, speed);
-+      if(add_avp(buf, RX_CONNECT_SPEED_AVP, t, 4, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_physchan_avp(struct buffer *buf, unsigned int physchan) {
-+      u_int8_t t[4];
-+      set32(t, physchan);
-+      if(add_avp(buf, PHYS_CHAN_ID_AVP, t, 4, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_ppd_avp(struct buffer *buf, _u16 ppd) {
-+      u_int8_t t[2];
-+      set16(t, ppd);
-+      if(add_avp(buf, PACKET_DELAY_AVP, t, 2, 1))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_seqreqd_avp(struct buffer *buf) {
-+      if(add_avp(buf, SEQ_REQUIRED_AVP, 0, 0, 0))
-+              return 1;
-+    return 0;
-+}
-+
-+/*****************************************************************************/
-+int add_minbps_avp(struct buffer *buf, int speed) {
-+      u_int8_t t[4];
-+      set32(t, speed);
-+      if(add_avp(buf, MIN_BPS_AVP, t, 4, 1))
-+              return 1;
-     return 0;
- }
--int add_serno_avp (struct buffer *buf, unsigned int serno)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0xA | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0xF);
--    raw[3] = htons ((serno >> 16) & 0xFFFF);
--    raw[4] = htons (serno & 0xFFFF);
--    buf->len += 10;
--    return 0;
--}
--
--int add_bearer_avp (struct buffer *buf, int bearer)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0xA | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x12);
--    raw[3] = htons ((bearer >> 16) & 0xFFFF);
--    raw[4] = htons (bearer & 0xFFFF);
--    buf->len += 10;
--    return 0;
--}
--
--int add_frame_avp (struct buffer *buf, int frame)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0xA | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x13);
--    raw[3] = htons ((frame >> 16) & 0xFFFF);
--    raw[4] = htons (frame & 0xFFFF);
--    buf->len += 10;
--    return 0;
--}
--
--int add_txspeed_avp (struct buffer *buf, int speed)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0xA | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x18);
--    raw[3] = htons ((speed >> 16) & 0xFFFF);
--    raw[4] = htons (speed & 0xFFFF);
--    buf->len += 10;
--    return 0;
--}
--
--int add_rxspeed_avp (struct buffer *buf, int speed)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0xA | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x26);
--    raw[3] = htons ((speed >> 16) & 0xFFFF);
--    raw[4] = htons (speed & 0xFFFF);
--    buf->len += 10;
--    return 0;
--}
--
--int add_physchan_avp (struct buffer *buf, unsigned int physchan)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0x8 | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x19);
--    raw[3] = htons ((physchan >> 16) & 0xFFFF);
--    raw[4] = htons (physchan & 0xFFFF);
--    buf->len += 10;
--    return 0;
--}
--
--int add_ppd_avp (struct buffer *buf, _u16 ppd)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0x8 | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x14);
--    raw[3] = htons (ppd);
--    buf->len += 8;
--    return 0;
--}
--
--int add_seqreqd_avp (struct buffer *buf)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0x6 | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x27);
--    buf->len += 6;
--    return 0;
--}
--
--/* jz: options dor the outgoing call */
--
--/* jz: Minimum BPS - 16 */
--int add_minbps_avp (struct buffer *buf, int speed)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0xA | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x10);
--    raw[3] = htons ((speed >> 16) & 0xFFFF);
--    raw[4] = htons (speed & 0xFFFF);
--    buf->len += 10;
--    return 0;
--}
--
--/* jz: Maximum BPS - 17 */
--int add_maxbps_avp (struct buffer *buf, int speed)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons (0xA | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x11);
--    raw[3] = htons ((speed >> 16) & 0xFFFF);
--    raw[4] = htons (speed & 0xFFFF);
--    buf->len += 10;
--    return 0;
--}
--
--/* jz: Dialed Number 21 */
--int add_number_avp (struct buffer *buf, char *no)
--{
--    _u16 *raw = (_u16 *) (buf->start + buf->len);
--    raw[0] = htons ((0x6 + strlen (no)) | MBIT);
--    raw[1] = htons (VENDOR_ID);
--    raw[2] = htons (0x15);
--    strncpy ((char *) (&(raw[3])), no, strlen (no));
--    buf->len += 6 + strlen (no);
-+/*****************************************************************************/
-+int add_maxbps_avp(struct buffer *buf, int speed) {
-+      u_int8_t t[4];
-+      set32(t, speed);
-+      if(add_avp(buf, MAX_BPS_AVP, t, 4, 1))
-+              return 1;
-     return 0;
- }
-+
-+/*****************************************************************************/
-+int add_number_avp(struct buffer *buf, char *no) {
-+      if(add_avp(buf, CALLED_NUMBER_AVP, no, strlen(no), 1))
-+              return 1;
-+      return 0;
-+}