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
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)
--- /dev/null
+;
+; 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
--- /dev/null
+#!/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 $?
--- /dev/null
+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
--- /dev/null
+/etc/l2tpd/l2tpd.conf
+/etc/ppp/options.l2tpd
--- /dev/null
+--- 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;
++}
--- /dev/null
+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
+ }
--- /dev/null
+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;
++}
+++ /dev/null
---- 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;
-+}