From: nico Date: Fri, 16 Dec 2005 12:00:19 +0000 (+0000) Subject: port l2tpd fixes from changeset:2696 to trunk. X-Git-Url: https://git.rohieb.name/openwrt.git/commitdiff_plain/6f35f0363b0500981f09ea008859259815005f5c port l2tpd fixes from changeset:2696 to trunk. git-svn-id: svn://svn.openwrt.org/openwrt/trunk/openwrt@2697 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- diff --git a/package/l2tpd/Makefile b/package/l2tpd/Makefile index ac80e0b09..0af0c09f4 100644 --- a/package/l2tpd/Makefile +++ b/package/l2tpd/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=l2tpd PKG_VERSION:=0.70pre PKG_UPSTREAM_VERSION:=0.70-pre20031121 -PKG_RELEASE:=1 +PKG_RELEASE:=2.1 PKG_MD5SUM:=3f2707b6e16a8cb72e7bf64f574202fa PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/l/l2tpd @@ -30,6 +30,12 @@ $(PKG_BUILD_DIR)/.built: touch $@ $(IPKG_L2TPD): + install -d -m0755 $(IDIR_L2TPD)/etc/l2tpd + install -m0644 ./files/l2tpd.conf $(IDIR_L2TPD)/etc/l2tpd/ + install -d -m0755 $(IDIR_L2TPD)/etc/ppp + install -m0644 ./files/options.l2tpd $(IDIR_L2TPD)/etc/ppp/ + install -d -m0755 $(IDIR_L2TPD)/etc/init.d + install -m0755 ./files/l2tpd.init $(IDIR_L2TPD)/etc/init.d/l2tpd install -d -m0755 $(IDIR_L2TPD)/usr/sbin install -m0755 $(PKG_BUILD_DIR)/$(PKG_NAME) $(IDIR_L2TPD)/usr/sbin/ $(RSTRIP) $(IDIR_L2TPD) diff --git a/package/l2tpd/files/l2tpd.conf b/package/l2tpd/files/l2tpd.conf new file mode 100644 index 000000000..2a9ba1cc6 --- /dev/null +++ b/package/l2tpd/files/l2tpd.conf @@ -0,0 +1,29 @@ +; +; This is a minimal sample l2tpd configuration file for use +; with L2TP over IPsec. +; +; The idea is to provide an L2TP daemon to which remote Windows L2TP/IPsec +; clients connect. In this example, the internal (protected) network +; is 192.168.1.0/24. A special IP range within this network is reserved +; for the remote clients: 192.168.1.128/25 +; (i.e. 192.168.1.128 ... 192.168.1.254) +; +; The listen-addr parameter can be used if you want to bind the L2TP daemon +; to a specific IP address instead of to all interfaces. For instance, +; you could bind it to the interface of the internal LAN (e.g. 192.168.1.98 +; in the example below). Yet another IP address (local ip, e.g. 192.168.1.99) +; will be used by l2tpd as its address on pppX interfaces. + +[global] +; listen-addr = 192.168.1.98 + +[lns default] +ip range = 192.168.1.128-192.168.1.254 +local ip = 192.168.1.99 +require chap = yes +refuse pap = yes +require authentication = yes +name = LinuxVPNserver +ppp debug = yes +pppoptfile = /etc/ppp/options.l2tpd +length bit = yes diff --git a/package/l2tpd/files/l2tpd.init b/package/l2tpd/files/l2tpd.init new file mode 100644 index 000000000..f53175799 --- /dev/null +++ b/package/l2tpd/files/l2tpd.init @@ -0,0 +1,21 @@ +#!/bin/sh + +BIN=l2tpd +DEFAULT=/etc/default/$BIN +RUN_D=/var/run +PID_F=$RUN_D/$BIN.pid +[ -f $DEFAULT ] && . $DEFAULT + +case $1 in + start) + $BIN $OPTIONS + ;; + stop) + [ -f $PID_F ] && kill $(cat $PID_F) + ;; + *) + echo "usage: $0 (start|stop)" + exit 1 +esac + +exit $? diff --git a/package/l2tpd/files/options.l2tpd b/package/l2tpd/files/options.l2tpd new file mode 100644 index 000000000..425a56e08 --- /dev/null +++ b/package/l2tpd/files/options.l2tpd @@ -0,0 +1,17 @@ +ipcp-accept-local +ipcp-accept-remote +ms-dns 192.168.1.1 +ms-dns 192.168.1.3 +ms-wins 192.168.1.2 +ms-wins 192.168.1.4 +noccp +auth +crtscts +idle 1800 +mtu 1410 +mru 1410 +nodefaultroute +debug +lock +proxyarp +connect-delay 5000 diff --git a/package/l2tpd/ipkg/l2tpd.conffiles b/package/l2tpd/ipkg/l2tpd.conffiles new file mode 100644 index 000000000..1607479cb --- /dev/null +++ b/package/l2tpd/ipkg/l2tpd.conffiles @@ -0,0 +1,2 @@ +/etc/l2tpd/l2tpd.conf +/etc/ppp/options.l2tpd diff --git a/package/l2tpd/patches/01-debian-2.patch b/package/l2tpd/patches/01-debian-2.patch new file mode 100644 index 000000000..8a6e204c4 --- /dev/null +++ b/package/l2tpd/patches/01-debian-2.patch @@ -0,0 +1,3394 @@ +--- l2tpd-0.70-pre20031121.orig/Makefile ++++ l2tpd-0.70-pre20031121/Makefile +@@ -28,7 +28,8 @@ + # become runtime options) debugging flags + # + #DFLAGS= -g -O2 -DDEBUG_PPPD +-DFLAGS= -g -O2 -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY ++#DFLAGS= -g -O2 -Wall -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY ++DFLAGS= -ggdb -Wall -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY + # + # Uncomment the next line for Linux + # +@@ -58,7 +59,7 @@ + + FFLAGS= -DIP_ALLOCATION + +-CFLAGS= $(DFLAGS) -Wall -DSANITY $(OSFLAGS) $(FFLAGS) ++CFLAGS= $(DFLAGS) -Wall -DSANITY $(OSFLAGS) $(FFLAGS) + HDRS=l2tp.h avp.h misc.h control.h call.h scheduler.h file.h aaa.h md5.h + OBJS=l2tpd.o pty.o misc.o control.o avp.o call.o network.o avpsend.o scheduler.o file.o aaa.o md5.o + LIBS= $(OSLIB) # -lefence # efence for malloc checking +--- l2tpd-0.70-pre20031121.orig/control.c ++++ l2tpd-0.70-pre20031121/control.c +@@ -227,7 +227,7 @@ + add_bearer_caps_avp (buf, t->ourbc); + /* FIXME: Tie breaker */ + add_firmware_avp (buf); +- add_hostname_avp (buf); ++ add_hostname_avp (buf, t); + add_vendor_avp (buf); + add_tunnelid_avp (buf, t->ourtid); + if (t->ourrws >= 0) +@@ -346,7 +346,6 @@ + "%s: Peer did not specify assigned tunnel ID. Closing.\n", + __FUNCTION__); + set_error (c, VENDOR_ERROR, "Specify your assigned tunnel ID"); +- c->needclose = -1; + return -EINVAL; + } + if (!(t->lns = get_lns (t))) +@@ -356,7 +355,6 @@ + "%s: Denied connection to unauthorized peer %s\n", + __FUNCTION__, IPADDY (t->peer.sin_addr)); + set_error (c, VENDOR_ERROR, "No Authorization"); +- c->needclose = -1; + return -EINVAL; + } + t->ourrws = t->lns->tun_rws; +@@ -368,7 +366,6 @@ + "%s: Peer did not specify framing capability. Closing.\n", + __FUNCTION__); + set_error (c, VENDOR_ERROR, "Specify framing capability"); +- c->needclose = -1; + return -EINVAL; + } + /* FIXME: Do we need to be sure they specified a version number? +@@ -380,7 +377,6 @@ + if (DEBUG) log(LOG_DEBUG, + "%s: Peer did not specify bearer capability. Closing.\n",__FUNCTION__); + set_error(c, VENDOR_ERROR, "Specify bearer capability"); +- c->needclose = -1; + return -EINVAL; + } */ + if ((!strlen (t->hostname)) && ((t->chal_us.state) || ((t->lns->challenge)))) +@@ -390,7 +386,6 @@ + "%s: Peer did not specify hostname. Closing.\n", + __FUNCTION__); + set_error (c, VENDOR_ERROR, "Specify your hostname"); +- c->needclose = -1; + return -EINVAL; + } + y = tunnels.head; +@@ -427,7 +422,7 @@ + add_frame_caps_avp (buf, t->ourfc); + add_bearer_caps_avp (buf, t->ourbc); + add_firmware_avp (buf); +- add_hostname_avp (buf); ++ add_hostname_avp (buf, t); + add_vendor_avp (buf); + add_tunnelid_avp (buf, t->ourtid); + if (t->ourrws >= 0) +@@ -481,7 +476,6 @@ + "%s: Peer did not specify framing capability. Closing.\n", + __FUNCTION__); + set_error (c, VENDOR_ERROR, "Specify framing capability"); +- c->needclose = -1; + return -EINVAL; + } + /* FIXME: Do we need to be sure they specified a version number? +@@ -493,7 +487,6 @@ + if (DEBUG) log(LOG_DEBUG, + "%s: Peer did not specify bearer capability. Closing.\n",__FUNCTION__); + set_error(c, VENDOR_ERROR, "Specify bearer capability"); +- c->needclose = -1; + return -EINVAL; + } */ + if ((!strlen (t->hostname)) && ((t->chal_them.state) || ((t->chal_us.state)))) +@@ -503,7 +496,6 @@ + "%s: Peer did not specify hostname. Closing.\n", + __FUNCTION__); + set_error (c, VENDOR_ERROR, "Specify your hostname"); +- c->needclose = -1; + return -EINVAL; + } + if (t->tid <= 0) +@@ -513,7 +505,6 @@ + "%s: Peer did not specify assigned tunnel ID. Closing.\n", + __FUNCTION__); + set_error (c, VENDOR_ERROR, "Specify your assigned tunnel ID"); +- c->needclose = -1; + return -EINVAL; + } + if (t->chal_them.state) +@@ -524,7 +515,6 @@ + set_error (c, VENDOR_ERROR, "No secret key on our side"); + log (LOG_WARN, "%s: No secret key for authenticating '%s'\n", + __FUNCTION__, t->hostname); +- c->needclose = -1; + return -EINVAL; + } + if (memcmp +@@ -534,7 +524,6 @@ + "Invalid challenge authentication"); + log (LOG_DEBUG, "%s: Invalid authentication for host '%s'\n", + __FUNCTION__, t->hostname); +- c->needclose = -1; + return -EINVAL; + } + } +@@ -546,7 +535,6 @@ + log (LOG_WARN, "%s: No secret for authenticating to '%s'\n", + __FUNCTION__, t->hostname); + set_error (c, VENDOR_ERROR, "No secret key on our end"); +- c->needclose = -1; + return -EINVAL; + }; + } +@@ -606,7 +594,6 @@ + "Invalid challenge authentication"); + log (LOG_DEBUG, "%s: Invalid authentication for host '%s'\n", + __FUNCTION__, t->hostname); +- c->needclose = -1; + return -EINVAL; + } + } +@@ -1584,6 +1571,14 @@ + wbuf[pos++] = e; + for (x = 0; x < buf->len; x++) + { ++ // we must at least still have 4 bytes left in the worst case scenario: ++ // 1 for a possible escape, 1 for the value and 1 to end the PPP stream. ++ if(pos >= (sizeof(wbuf) - 4)) { ++ if(DEBUG) ++ log(LOG_CRIT, "%s: rx packet is too big after PPP encoding (size %u, max is %u)\n", ++ __FUNCTION__, buf->len, MAX_RECV_SIZE); ++ return -EINVAL; ++ } + e = *((char *) buf->start + x); + if ((e < 0x20) || (e == PPP_ESCAPE) || (e == PPP_FLAG)) + { +@@ -1592,7 +1587,6 @@ + wbuf[pos++] = PPP_ESCAPE; + } + wbuf[pos++] = e; +- + } + wbuf[pos++] = PPP_FLAG; + x = write (c->fd, wbuf, pos); +--- l2tpd-0.70-pre20031121.orig/misc.h ++++ l2tpd-0.70-pre20031121/misc.h +@@ -80,4 +80,11 @@ + extern void safe_copy (char *, char *, int); + extern void opt_destroy (struct ppp_opts *); + extern struct ppp_opts *add_opt (struct ppp_opts *, char *, ...); ++extern u_int16_t get16(u_int8_t *); ++extern u_int32_t get32(u_int8_t *); ++extern u_int64_t get64(u_int8_t *); ++extern void set16(u_int8_t *, u_int16_t); ++extern void set32(u_int8_t *, u_int32_t); ++extern void set64(u_int8_t *, u_int64_t); ++ + #endif +--- l2tpd-0.70-pre20031121.orig/avp.h ++++ l2tpd-0.70-pre20031121/avp.h +@@ -19,22 +19,35 @@ + + struct avp_hdr + { +- _u16 length; +- _u16 vendorid; +- _u16 attr; ++ u_int16_t length; ++ u_int16_t vendorid; ++ u_int16_t attr; + }; + ++#define AVP_F_MANDATORY 0x1 ++#define AVP_F_FIXLEN 0x2 ++#define AVP_F_ASCII 0x4 ++ + struct avp + { +- int num; /* Number of AVP */ +- int m; /* Set M? */ +- int (*handler) (struct tunnel *, struct call *, void *, int); +- /* This should handle the AVP +- taking a tunnel, call, the data, +- and the length of the AVP as +- parameters. Should return 0 +- upon success */ +- char *description; /* A name, for debugging */ ++ u_int32_t num; /* Number of AVP */ ++ u_int32_t flags; ++ u_int32_t sz; /* expected avp payload size as ++ * (AVP_F_FIXLEN) ? (==) : (!>=) ++ * note: size checked is performed ++ * after unhiding */ ++ u_int8_t allowed_states[8]; /* List of allowed message types for ++ * a particular avp. Fixed len for ++ * alignement issues. */ ++ ++ /* This should handle the AVP taking a tunnel, call, ++ * the data, and the length of the AVP as parameters. ++ * Should return 0 upon success */ ++ int (*handle) (struct tunnel *, struct call *, void *, int); ++ ++ /* This should handle avp specifics sanity checks */ ++ int (*validate) (int, struct tunnel *, struct call *, void *, int); ++ char *description; /* A name, for debugging */ + }; + + extern int handle_avps (struct buffer *buf, struct tunnel *t, struct call *c); +@@ -84,8 +97,56 @@ + #define RESULT_CLEAR 1 + #define RESULT_ERROR 2 + #define RESULT_EXISTS 3 ++ ++/* avp id's */ ++#define MESSAGE_TYPE_AVP 0 ++#define RESULT_CODE_AVP 1 ++#define PROTOCOL_VERSION_AVP 2 ++#define FRAMING_CAP_AVP 3 ++#define BEARER_CAP_AVP 4 ++#define TIE_BREAKER_AVP 5 ++#define FIRMWARE_REV_AVP 6 ++#define HOSTNAME_AVP 7 ++#define VENDOR_NAME_AVP 8 ++#define ASSIGNED_TUN_ID_AVP 9 ++#define RX_WIN_SIZE_AVP 10 ++#define CHALLENGE_AVP 11 ++#define CHALLENGE_RESP_AVP 12 ++#define CAUSE_ERROR_AVP 13 ++#define ASSIGNED_SES_ID_AVP 14 ++#define SERIAL_NUMBER_AVP 15 ++#define MIN_BPS_AVP 16 ++#define MAX_BPS_AVP 17 ++#define BEARER_TYPE_AVP 18 ++#define FRAMING_TYPE_AVP 19 ++#define PACKET_DELAY_AVP 20 ++#define CALLED_NUMBER_AVP 21 ++#define CALLING_NUMBER_AVP 22 ++#define SUB_ADDRESS_AVP 23 ++#define TX_CONNECT_SPEED_AVP 24 ++#define PHYS_CHAN_ID_AVP 25 ++#define INIT_RX_LCP_AVP 26 ++#define LAST_TX_LCP_AVP 27 ++#define LAST_RX_LCP_AVP 28 ++#define PROXY_AUTH_TYPE_AVP 29 ++#define PROXY_AUTH_NAME_AVP 30 ++#define PROXY_AUTH_CHAL_AVP 31 ++#define PROXY_AUTH_ID_AVP 32 ++#define PROXY_AUTH_CHAL_RESP_AVP 33 ++#define CALL_ERROR_AVP 34 ++#define ACCM_AVP 35 ++#define RANDOM_VECTOR_AVP 36 ++#define PRIV_GROUP_ID_AVP 37 ++#define RX_CONNECT_SPEED_AVP 38 ++#define SEQ_REQUIRED_AVP 39 ++#define AVP_MAX SEQ_REQUIRED_AVP ++ ++extern int validate_msgtype_avp(int, struct tunnel *, struct call *, void *, int); ++extern int validate_gen_avp(int, struct tunnel *, struct call *, void *, int); ++ + extern void encrypt_avp (struct buffer *, _u16, struct tunnel *); + extern int decrypt_avp (char *, struct tunnel *); ++ + extern int message_type_avp (struct tunnel *, struct call *, void *, int); + extern int protocol_version_avp (struct tunnel *, struct call *, void *, int); + extern int framing_caps_avp (struct tunnel *, struct call *, void *, int); +@@ -97,12 +158,12 @@ + extern int receive_window_size_avp (struct tunnel *, struct call *, void *, + int); + extern int result_code_avp (struct tunnel *, struct call *, void *, int); +-extern int assigned_call_avp (struct tunnel *, struct call *, void *, int); ++extern int assigned_session_avp (struct tunnel *, struct call *, void *, int); + extern int call_serno_avp (struct tunnel *, struct call *, void *, int); + extern int bearer_type_avp (struct tunnel *, struct call *, void *, int); + extern int call_physchan_avp (struct tunnel *, struct call *, void *, int); +-extern int dialed_number_avp (struct tunnel *, struct call *, void *, int); +-extern int dialing_number_avp (struct tunnel *, struct call *, void *, int); ++extern int called_number_avp (struct tunnel *, struct call *, void *, int); ++extern int calling_number_avp (struct tunnel *, struct call *, void *, int); + extern int sub_address_avp (struct tunnel *, struct call *, void *, int); + extern int frame_type_avp (struct tunnel *, struct call *, void *, int); + extern int rx_speed_avp (struct tunnel *, struct call *, void *, int); +@@ -118,7 +179,7 @@ + extern int add_avp_rws (struct buffer *, _u16); + extern int add_tunnelid_avp (struct buffer *, _u16); + extern int add_vendor_avp (struct buffer *); +-extern int add_hostname_avp (struct buffer *); ++extern int add_hostname_avp (struct buffer *, struct tunnel*); + extern int add_firmware_avp (struct buffer *); + extern int add_bearer_caps_avp (struct buffer *buf, _u16 caps); + extern int add_frame_caps_avp (struct buffer *buf, _u16 caps); +--- l2tpd-0.70-pre20031121.orig/network.c ++++ l2tpd-0.70-pre20031121/network.c +@@ -214,6 +214,8 @@ + t->self->needclose = -1; + } + } ++ free(buf->rstart); ++ free(buf); + } + else + { +@@ -371,7 +373,9 @@ + if (debug_network) + { + log (LOG_DEBUG, "%s: recv packet from %s, size = %d," \ +-"tunnel = %d, call = %d\n", __FUNCTION__, inet_ntoa (from.sin_addr), recvsize, tunnel, call); ++ "tunnel = %d, call = %d\n", __func__, ++ inet_ntoa (from.sin_addr), recvsize, ++ tunnel, call); + } + if (packet_dump) + { +--- l2tpd-0.70-pre20031121.orig/aaa.c ++++ l2tpd-0.70-pre20031121/aaa.c +@@ -209,9 +209,11 @@ + __FUNCTION__, u, t, s); + #endif + strncpy (secret, s, size); ++ fclose(f); + return -1; + } + } ++ fclose(f); + return 0; + } + +--- l2tpd-0.70-pre20031121.orig/l2tpd.c ++++ l2tpd-0.70-pre20031121/l2tpd.c +@@ -266,6 +266,9 @@ + /* erase pid file */ + unlink (gconfig.pidfile); + ++ /* erase control pipe */ ++ unlink(CONTROL_PIPE); ++ + exit (1); + } + +@@ -333,13 +336,17 @@ + tcgetattr (c->fd, &ptyconf); + *(c->oldptyconf) = ptyconf; + ptyconf.c_cflag &= ~(ICANON | ECHO); +- ptyconf.c_lflag &= ~ECHO; ++ ptyconf.c_lflag &= ~ECHO; + tcsetattr (c->fd, TCSANOW, &ptyconf); + + snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b); + fd2 = open (tty, O_RDWR); +- stropt[pos++] = strdup(tty); +- stropt[pos] = NULL; ++ if(!fd2) ++ log(LOG_WARN, "unable to open tty %s", tty); ++ ++ /* XXX JEF: CHECK ME */ ++ stropt[pos++] = strdup(tty); ++ stropt[pos] = NULL; + + #ifdef USE_KERNEL + } +@@ -623,7 +630,13 @@ + { + struct lac *lac; + lac = (struct lac *) data; +- if (!lac->active) ++ ++ if (!lac) ++ { ++ log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__); ++ return; ++ } ++ if (!lac->active) + { + log (LOG_DEBUG, "%s: LAC %s not active", __FUNCTION__, lac->entname); + return; +@@ -635,11 +648,6 @@ + log (LOG_LOG, "%s: maximum retries exceeded.\n", __FUNCTION__); + return; + } +- if (!lac) +- { +- log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__); +- return; +- } + if (!lac->t) + { + #ifdef DEGUG_MAGIC +@@ -774,12 +782,7 @@ + void do_control () + { + char buf[1024]; +- char *host; +- char *tunstr; +- char *callstr; +- +- char *sub_str; /* jz: use by the strtok function */ +- char *tmp_ptr; /* jz: use by the strtok function */ ++ char *host, *tunstr, *callstr, *tmpstr; + struct lac *lac; + int call; + int tunl; +@@ -792,24 +795,39 @@ + if (buf[cnt - 1] == '\n') + buf[--cnt] = 0; + #ifdef DEBUG_CONTROL +- log (LOG_DEBUG, "%s: Got message %s (%d bytes long)\n", ++ log (LOG_DEBUG, "%s: Got message \"%s\" (%d bytes long)\n", + __FUNCTION__, buf, cnt); + #endif + switch (buf[0]) + { + case 't': +- host = strchr (buf, ' ') + 1; ++ host = strchr (buf, ' '); ++ if(!host) ++ goto out; ++ host++; + #ifdef DEBUG_CONTROL + log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n", + __FUNCTION__, host); + #endif + l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL); + break; +- case 'c': +- +- switch_io = 1; /* jz: Switch for Incoming - Outgoing Calls */ +- +- tunstr = strchr (buf, ' ') + 1; ++ case 'c': /* option 'c' for incoming call */ ++ case 'o': /* option 'o' for outgoing call */ ++ tunstr = strchr (buf, ' '); ++ if(!tunstr) ++ goto out; ++ tunstr++; ++ ++ if(buf[0] == 'c') ++ switch_io = 1; /* Switch for Incoming Calls */ ++ else { ++ switch_io = 0; /* Switch for Outgoing Calls */ ++ tmpstr = strchr(tunstr, ' '); ++ if(!tmpstr) ++ goto out; ++ strncpy(dial_no_tmp,tmpstr, sizeof(*dial_no_tmp)); ++ } ++ + lac = laclist; + while (lac) + { +@@ -842,52 +860,12 @@ + #endif + lac_call (tunl, NULL, NULL); + break; +- +- case 'o': /* jz: option 'o' for doing a outgoing call */ +- +- switch_io = 0; /* jz: Switch for incoming - outgoing Calls */ +- +- sub_str = strchr (buf, ' ') + 1; +- +- tunstr = strtok (sub_str, " "); /* jz: using strtok function to get */ +- tmp_ptr = strtok (NULL, " "); /* params out of the pipe */ +- strcpy (dial_no_tmp, tmp_ptr); +- +- lac = laclist; +- while (lac) +- { +- if (!strcasecmp (lac->entname, tunstr)) +- { +- lac->active = -1; +- lac->rtries = 0; +- if (!lac->c) +- magic_lac_dial (lac); +- else +- log (LOG_DEBUG, +- "%s: Session '%s' already active!\n", +- __FUNCTION__, lac->entname); +- break; +- } +- lac = lac->next; +- } +- if (lac) +- break; +- tunl = atoi (tunstr); +- if (!tunl) +- { +- log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__, +- tunstr); +- break; +- } +-#ifdef DEBUG_CONTROL +- log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n", +- __FUNCTION__, tunl); +-#endif +- lac_call (tunl, NULL, NULL); +- break; +- + case 'h': +- callstr = strchr (buf, ' ') + 1; ++ callstr = strchr (buf, ' '); ++ if(!callstr) ++ goto out; ++ callstr++; ++ + call = atoi (callstr); + #ifdef DEBUG_CONTROL + log (LOG_DEBUG, "%s: Attempting to call %d\n", __FUNCTION__, +@@ -896,7 +874,11 @@ + lac_hangup (call); + break; + case 'd': +- tunstr = strchr (buf, ' ') + 1; ++ tunstr = strchr (buf, ' '); ++ if(!tunstr) ++ goto out; ++ tunstr++; ++ + lac = laclist; + while (lac) + { +@@ -937,6 +919,8 @@ + } + } + } ++ ++out: + /* Otherwise select goes nuts */ + close (control_fd); + control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600); +@@ -1002,7 +986,6 @@ + int pid=0; + int i,l; + char buf[STRLEN]; +- int pidfilewritten=0; + + if((pid = fork()) < 0) { + log(LOG_LOG, "%s: Unable to fork ()\n",__FUNCTION__); +@@ -1012,56 +995,52 @@ + else if (pid) + exit(0); + +- close(0); +- close(1); +- close(2); ++ ++ close(0); ++ close(1); ++ close(2); ++ dup2(open("/dev/null", O_RDONLY), 0); ++ dup2(open("/dev/null", O_RDONLY), 1); ++ dup2(open("/dev/null", O_RDONLY), 2); + + /* Read previous pid file. */ +- if ((i = open(gconfig.pidfile,O_RDONLY)) > 0) { +- l=read(i,buf,sizeof(buf)-1); +- if (i < 0) { +- log(LOG_LOG, "%s: Unable to read pid file [%s]\n", +- __FUNCTION__, gconfig.pidfile); +- } +- buf[i] = '\0'; +- pid = atoi(buf); +- +- /* If the previous server process is not still running, +- write a new pid file immediately. */ +- if (pid && (pid == getpid () || kill (pid, 0) < 0)) { +- unlink (gconfig.pidfile); +- if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0640)) >= 0) +- { +- snprintf (buf, sizeof(buf), "%d\n", (int)getpid()); +- write (i, buf, strlen(buf)); +- close (i); +- pidfilewritten = 1; +- } ++ if((i = open(gconfig.pidfile,O_RDONLY)) > 0) { ++ l=read(i,buf,sizeof(buf)-1); ++ if (l >= 0) { ++ buf[l] = '\0'; ++ pid = atoi(buf); + } +- else +- { ++ close(i); ++ ++ /* if pid is read and process exist exit */ ++ if(pid && !kill(pid, 0)) { + log(LOG_LOG, "%s: There's already a l2tpd server running.\n", + __FUNCTION__); + close(server_socket); + exit(1); + } ++ ++ /* remove stalled pid file */ ++ unlink(gconfig.pidfile); + } + + pid = setsid(); + +- if(! pidfilewritten) { +- unlink(gconfig.pidfile); +- if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0640)) >= 0) { +- snprintf (buf, strlen(buf), "%d\n", (int)getpid()); +- write (i, buf, strlen(buf)); +- close (i); +- pidfilewritten = 1; +- } +- } ++ /* create new pid file */ ++ if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0644)) >= 0) { ++ snprintf (buf, sizeof(buf), "%d", (int)getpid()); ++ write (i, buf, strlen(buf)); ++ close (i); ++ } ++ else { ++ log(LOG_LOG, "%s: could not write pid file %s error %d", ++ __FUNCTION__, gconfig.pidfile, i); ++ close(server_socket); ++ exit(1); ++ } + } + + +- + void init (int argc,char *argv[]) + { + struct lac *lac; +@@ -1103,10 +1082,6 @@ + } + log (LOG_LOG, "l2tpd version " SERVER_VERSION " started on %s PID:%d\n", + hostname, getpid ()); +- log (LOG_LOG, +- "Written by Mark Spencer, Copyright (C) 1998, Adtran, Inc.\n"); +- log (LOG_LOG, "Forked by Scott Balmos and David Stipp, (C) 2001\n"); +- log (LOG_LOG, "Inherited by Jeff McAdams, (C) 2002\n"); + listenaddr.s_addr = gconfig.listenaddr; + log (LOG_LOG, "%s version %s on a %s, listening on IP address %s, port %d\n", uts.sysname, + uts.release, uts.machine, inet_ntoa(listenaddr), gconfig.port); +--- l2tpd-0.70-pre20031121.orig/misc.c ++++ l2tpd-0.70-pre20031121/misc.c +@@ -301,3 +301,42 @@ + return -1; + } + } ++ ++u_int16_t get16(u_int8_t *p) { ++ return p[0] << 8 | p[1]; ++} ++ ++u_int32_t get32(u_int8_t *p) { ++ return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; ++} ++ ++u_int64_t get64(u_int8_t *p) { ++ return (u_int64_t)p[0] << 56 | (u_int64_t)p[1] << 48 | ++ (u_int64_t)p[2] << 40 | (u_int64_t)p[3] << 32 | ++ (u_int64_t)p[4] << 24 | (u_int64_t)p[5] << 16 | ++ (u_int64_t)p[6] << 8 | (u_int64_t)p[7]; ++} ++ ++void set16(u_int8_t *cp, u_int16_t x) { ++ *cp++ = x >> 8; ++ *cp = x & 0xff; ++} ++ ++void set32(u_int8_t *cp, u_int32_t x) { ++ *cp++ = x >> 24; ++ *cp++ = (x >> 16) & 0xff; ++ *cp++ = (x >> 8) & 0xff; ++ *cp = x & 0xff; ++} ++ ++void set64(u_int8_t *cp, u_int64_t x) { ++ *cp++ = x >> 56; ++ *cp++ = (x >> 48) & 0xff; ++ *cp++ = (x >> 40) & 0xff; ++ *cp++ = (x >> 32) & 0xff; ++ *cp++ = (x >> 24) & 0xff; ++ *cp++ = (x >> 16) & 0xff; ++ *cp++ = (x >> 8) & 0xff; ++ *cp = x & 0xff; ++} ++ +--- l2tpd-0.70-pre20031121.orig/avp.c ++++ l2tpd-0.70-pre20031121/avp.c +@@ -4,9 +4,12 @@ + * Layer Two Tunnelling Protocol Daemon + * Copyright (C) 1998 Adtran, Inc. + * Copyright (C) 2002 Jeff McAdams ++ * Copyright (C) 2003 Jean-Francois Dive + * + * Mark Spencer + * ++ * 12/2003 parsing sanitization, Jean-Francois Dive ++ * + * This software is distributed under the terms + * of the GPL, which you should have received + * along with this source. +@@ -20,50 +23,53 @@ + #include + #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 + #include +-#include ++#include + #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 */ ++static int add_avp(struct buffer *buf, u_int32_t avpid, unsigned char *v, ++ u_int32_t sz, u_int8_t setpayload) { ++ u_int8_t *p = buf->start + buf->len; ++ ++ if(avpid > AVP_MAX || !avps[avpid].flags) { ++ log(LOG_DEBUG, "%s: invalid avp id %d\n", __func__, avpid); ++ return 1; ++ } ++ ++ set16(p, (sz + 6) | (avps[avpid].flags & AVP_F_MANDATORY ? MBIT : 0)); ++ set16(p + 2, VENDOR_ID); ++ set16(p + 4, avpid); ++ if(setpayload) ++ memcpy(p + 6, v, sz); + +-/* FIXME: If SANITY is on, we should check for buffer overruns */ ++ buf->len += (sz + 6); ++ return 0; ++} + +-/* FIXME: Can't this be condensed alot? */ ++/*****************************************************************************/ ++int add_message_type_avp(struct buffer *buf, _u16 type) { ++ u_int8_t t[2]; ++ set16(t, type); ++ if(add_avp(buf, MESSAGE_TYPE_AVP, t, 2, 1)) ++ return 1; ++ return 0; ++} + +-int add_message_type_avp (struct buffer *buf, _u16 type) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0x8 | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = 0; +- raw[3] = htons (type); +- buf->len += 8; ++/*****************************************************************************/ ++int add_protocol_avp(struct buffer *buf) { ++ u_int8_t t[2]; ++ set16(t, OUR_L2TP_VERSION); ++ if(add_avp(buf, PROTOCOL_VERSION_AVP, t, 2, 1)) ++ return 1; + return 0; + } + +-int add_protocol_avp (struct buffer *buf) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0x8 | MBIT); /* Length and M bit */ +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x2); /* Value of our AVP */ +- raw[3] = htons (OUR_L2TP_VERSION); +- buf->len += 8; ++/*****************************************************************************/ ++int add_frame_caps_avp(struct buffer *buf, _u16 caps) { ++ u_int8_t t[4]; ++ t[0] = 0; ++ t[1] = 0; ++ set16(&t[2], caps); ++ if(add_avp(buf, FRAMING_CAP_AVP, t, 4, 1)) ++ return 1; + return 0; + } + +-int add_frame_caps_avp (struct buffer *buf, _u16 caps) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0xA | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x3); +- raw[3] = 0; +- raw[4] = htons (caps); +- buf->len += 10; ++/*****************************************************************************/ ++int add_bearer_caps_avp(struct buffer *buf, _u16 caps) { ++ u_int8_t t[4]; ++ t[0] = 0; ++ t[1] = 0; ++ set16(&t[2], caps); ++ if(add_avp(buf, BEARER_CAP_AVP, t, 4, 1)) ++ return 1; + return 0; + } + +-int add_bearer_caps_avp (struct buffer *buf, _u16 caps) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0xA | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x4); +- raw[3] = 0; +- raw[4] = htons (caps); +- buf->len += 10; ++/*****************************************************************************/ ++int add_firmware_avp(struct buffer *buf) { ++ u_int8_t t[2]; ++ set16(t, OUR_L2TP_VERSION); ++ if(add_avp(buf, FIRMWARE_REV_AVP, t, 2, 1)) ++ return 1; + return 0; + } + +-/* FIXME: I need to send tie breaker AVP's */ +- +-int add_firmware_avp (struct buffer *buf) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0x8); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x6); +- raw[3] = htons (FIRMWARE_REV); +- buf->len += 8; ++/*****************************************************************************/ ++int add_hostname_avp(struct buffer *buf, struct tunnel *t) { ++ char n[STRLEN]; ++ int sz = 0; ++ if(t->lac && t->lac->hostname[0]) { ++ strncpy(n,t->lac->hostname, sizeof(n)); ++ sz = strnlen(t->lac->hostname, sizeof(t->lac->hostname)); ++ } ++ else if(t->lns && t->lns->hostname[0]) { ++ strncpy(n,t->lns->hostname, sizeof(n)); ++ sz = strnlen(t->lns->hostname, sizeof(t->lns->hostname)); ++ } ++ else { ++ if(gethostname(n, STRLEN)) { ++ strcpy(n,"eriwan"); ++ sz = 6; ++ } ++ else ++ sz = strnlen(n, sizeof(n)); ++ } ++ if(add_avp(buf, HOSTNAME_AVP, n, sz, 1)) ++ return 1; + return 0; + } + +-/* +-int add_hostname_avp(struct buffer *buf) { +- _u16 *raw = (_u16 *)(buf->start + buf->len); +- raw[0] = htons((0x6 + strlen(hostname)) | MBIT); +- raw[1] = htons(VENDOR_ID); +- raw[2] = htons(0x7); +- strcpy((char *)(&raw[3]), hostname); +- buf->len += 6 + strlen(hostname); +- return 0; ++/*****************************************************************************/ ++int add_vendor_avp(struct buffer *buf) { ++ if(add_avp(buf, VENDOR_NAME_AVP, VENDOR_NAME, strlen(VENDOR_NAME), 1)) ++ return 1; ++ return 0; + } +-*/ + +-int add_hostname_avp (struct buffer *buf) +-{ +- char names[6] = "eriwan"; +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0xC | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x7); +- strcpy ((char *) (&raw[3]), names); +- buf->len += 12; +- return 0; +-} +- +-int add_vendor_avp (struct buffer *buf) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0x6 + strlen (VENDOR_NAME)); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x8); +- strcpy ((char *) (&raw[3]), VENDOR_NAME); +- buf->len += 6 + strlen (VENDOR_NAME); +- return 0; +-} +- +-int add_tunnelid_avp (struct buffer *buf, _u16 tid) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0x8 | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x9); +- raw[3] = htons (tid); +- buf->len += 8; +- return 0; +-} +- +-int add_avp_rws (struct buffer *buf, _u16 rws) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0x8 | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0xA); +- raw[3] = htons (rws); +- buf->len += 8; +- return 0; +-} +- +-int add_challenge_avp (struct buffer *buf, char *c, int len) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons ((0x6 + len) | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0xB); +- bcopy (c, (char *) (&raw[3]), len); +- buf->len += 6 + len; +- return 0; +-} +- +-int add_chalresp_avp (struct buffer *buf, char *c, int len) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons ((0x6 + len) | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0xD); +- bcopy (c, (char *) (&raw[3]), len); +- buf->len += 6 + len; +- return 0; +-} +- +-int add_randvect_avp (struct buffer *buf, char *c, int len) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons ((0x6 + len) | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x24); +- bcopy (c, (char *) (&raw[3]), len); +- buf->len += 6 + len; +- return 0; +-} +- +-int add_result_code_avp (struct buffer *buf, _u16 result, _u16 error, +- char *msg, int len) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons ((0xA + len) | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x1); +- raw[3] = htons (result); +- raw[4] = htons (error); +- bcopy (msg, (char *) &raw[5], len); +- buf->len += (10 + len); ++/*****************************************************************************/ ++int add_tunnelid_avp(struct buffer *buf, _u16 tid) { ++ u_int8_t t[2]; ++ set16(t, tid); ++ if(add_avp(buf, ASSIGNED_TUN_ID_AVP, t, 2, 1)) ++ return 1; + return 0; + } + ++/*****************************************************************************/ ++int add_avp_rws(struct buffer *buf, _u16 rws) { ++ u_int8_t t[2]; ++ set16(t, rws); ++ if(add_avp(buf, RX_WIN_SIZE_AVP, t, 2, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_challenge_avp(struct buffer *buf, char *c, int len) { ++ if(add_avp(buf, CHALLENGE_AVP, c, len, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_chalresp_avp(struct buffer *buf, char *c, int len) { ++ if(add_avp(buf, CHALLENGE_RESP_AVP, c, len, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_randvect_avp(struct buffer *buf, char *c, int len) { ++ if(add_avp(buf, RANDOM_VECTOR_AVP, c, len, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_result_code_avp(struct buffer *buf, _u16 result, _u16 error, ++ char *msg, int len) { ++ u_int8_t t[4]; ++ set16(t, result); ++ set16(&t[2], error); ++ memcpy((u_int8_t*)(buf->start + buf->len + 10), msg, len); ++ memcpy((u_int8_t*)(buf->start + buf->len + 6), t, 4); ++ if(add_avp(buf, RESULT_CODE_AVP, 0, 4 + len, 0)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ + #ifdef TEST_HIDDEN +-int add_callid_avp (struct buffer *buf, _u16 callid, struct tunnel *t) +-{ +-#else +-int add_callid_avp (struct buffer *buf, _u16 callid) +-{ +-#endif +- _u16 *raw = (_u16 *) (buf->start + buf->len); +-#ifdef TEST_HIDDEN ++int add_callid_avp(struct buffer *buf, _u16 callid, struct tunnel *t) { ++ u_int8_t t[2]; + if (t->hbit) + raw++; +-#endif +- raw[0] = htons (0x8 | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0xE); +- raw[3] = htons (callid); +- buf->len += 8; +-#ifdef TEST_HIDDEN ++ set16(t, callid); ++ if(add_avp(buf, ASSIGNED_SES_ID_AVP, t, 2, 1)) ++ return 1; + if (t->hbit) + encrypt_avp (buf, 8, t); ++ return 0; ++} ++#else ++int add_callid_avp(struct buffer *buf, _u16 callid) { ++ u_int8_t t[2]; ++ set16(t, callid); ++ if(add_avp(buf, ASSIGNED_SES_ID_AVP, t, 2, 1)) ++ return 1; ++ return 0; ++} + #endif ++ ++/*****************************************************************************/ ++int add_serno_avp(struct buffer *buf, unsigned int serno) { ++ u_int8_t t[4]; ++ set32(t, serno); ++ if(add_avp(buf, SERIAL_NUMBER_AVP, t, 4, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_bearer_avp(struct buffer *buf, int bearer) { ++ u_int8_t t[4]; ++ set32(t, bearer); ++ if(add_avp(buf, BEARER_TYPE_AVP, t, 4, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_frame_avp(struct buffer *buf, int frame) { ++ u_int8_t t[4]; ++ set32(t, frame); ++ if(add_avp(buf, FRAMING_TYPE_AVP, t, 4, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_txspeed_avp(struct buffer *buf, int speed) { ++ u_int8_t t[4]; ++ set32(t, speed); ++ if(add_avp(buf, TX_CONNECT_SPEED_AVP, t, 4, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_rxspeed_avp(struct buffer *buf, int speed) { ++ u_int8_t t[4]; ++ set32(t, speed); ++ if(add_avp(buf, RX_CONNECT_SPEED_AVP, t, 4, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_physchan_avp(struct buffer *buf, unsigned int physchan) { ++ u_int8_t t[4]; ++ set32(t, physchan); ++ if(add_avp(buf, PHYS_CHAN_ID_AVP, t, 4, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_ppd_avp(struct buffer *buf, _u16 ppd) { ++ u_int8_t t[2]; ++ set16(t, ppd); ++ if(add_avp(buf, PACKET_DELAY_AVP, t, 2, 1)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_seqreqd_avp(struct buffer *buf) { ++ if(add_avp(buf, SEQ_REQUIRED_AVP, 0, 0, 0)) ++ return 1; ++ return 0; ++} ++ ++/*****************************************************************************/ ++int add_minbps_avp(struct buffer *buf, int speed) { ++ u_int8_t t[4]; ++ set32(t, speed); ++ if(add_avp(buf, MIN_BPS_AVP, t, 4, 1)) ++ return 1; + return 0; + } + +-int add_serno_avp (struct buffer *buf, unsigned int serno) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0xA | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0xF); +- raw[3] = htons ((serno >> 16) & 0xFFFF); +- raw[4] = htons (serno & 0xFFFF); +- buf->len += 10; +- return 0; +-} +- +-int add_bearer_avp (struct buffer *buf, int bearer) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0xA | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x12); +- raw[3] = htons ((bearer >> 16) & 0xFFFF); +- raw[4] = htons (bearer & 0xFFFF); +- buf->len += 10; +- return 0; +-} +- +-int add_frame_avp (struct buffer *buf, int frame) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0xA | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x13); +- raw[3] = htons ((frame >> 16) & 0xFFFF); +- raw[4] = htons (frame & 0xFFFF); +- buf->len += 10; +- return 0; +-} +- +-int add_txspeed_avp (struct buffer *buf, int speed) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0xA | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x18); +- raw[3] = htons ((speed >> 16) & 0xFFFF); +- raw[4] = htons (speed & 0xFFFF); +- buf->len += 10; +- return 0; +-} +- +-int add_rxspeed_avp (struct buffer *buf, int speed) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0xA | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x26); +- raw[3] = htons ((speed >> 16) & 0xFFFF); +- raw[4] = htons (speed & 0xFFFF); +- buf->len += 10; +- return 0; +-} +- +-int add_physchan_avp (struct buffer *buf, unsigned int physchan) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0x8 | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x19); +- raw[3] = htons ((physchan >> 16) & 0xFFFF); +- raw[4] = htons (physchan & 0xFFFF); +- buf->len += 10; +- return 0; +-} +- +-int add_ppd_avp (struct buffer *buf, _u16 ppd) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0x8 | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x14); +- raw[3] = htons (ppd); +- buf->len += 8; +- return 0; +-} +- +-int add_seqreqd_avp (struct buffer *buf) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0x6 | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x27); +- buf->len += 6; +- return 0; +-} +- +-/* jz: options dor the outgoing call */ +- +-/* jz: Minimum BPS - 16 */ +-int add_minbps_avp (struct buffer *buf, int speed) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0xA | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x10); +- raw[3] = htons ((speed >> 16) & 0xFFFF); +- raw[4] = htons (speed & 0xFFFF); +- buf->len += 10; +- return 0; +-} +- +-/* jz: Maximum BPS - 17 */ +-int add_maxbps_avp (struct buffer *buf, int speed) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons (0xA | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x11); +- raw[3] = htons ((speed >> 16) & 0xFFFF); +- raw[4] = htons (speed & 0xFFFF); +- buf->len += 10; +- return 0; +-} +- +-/* jz: Dialed Number 21 */ +-int add_number_avp (struct buffer *buf, char *no) +-{ +- _u16 *raw = (_u16 *) (buf->start + buf->len); +- raw[0] = htons ((0x6 + strlen (no)) | MBIT); +- raw[1] = htons (VENDOR_ID); +- raw[2] = htons (0x15); +- strncpy ((char *) (&(raw[3])), no, strlen (no)); +- buf->len += 6 + strlen (no); ++/*****************************************************************************/ ++int add_maxbps_avp(struct buffer *buf, int speed) { ++ u_int8_t t[4]; ++ set32(t, speed); ++ if(add_avp(buf, MAX_BPS_AVP, t, 4, 1)) ++ return 1; + return 0; + } ++ ++/*****************************************************************************/ ++int add_number_avp(struct buffer *buf, char *no) { ++ if(add_avp(buf, CALLED_NUMBER_AVP, no, strlen(no), 1)) ++ return 1; ++ return 0; ++} diff --git a/package/l2tpd/patches/02-debian-2-pty-rev.patch b/package/l2tpd/patches/02-debian-2-pty-rev.patch new file mode 100644 index 000000000..135e17e18 --- /dev/null +++ b/package/l2tpd/patches/02-debian-2-pty-rev.patch @@ -0,0 +1,21 @@ +diff -ruN l2tpd-0.70pre-old/l2tpd.c l2tpd-0.70pre-new/l2tpd.c +--- l2tpd-0.70pre-old/l2tpd.c 2005-12-16 12:02:02.000000000 +0100 ++++ l2tpd-0.70pre-new/l2tpd.c 2005-12-16 12:14:24.000000000 +0100 +@@ -336,17 +336,10 @@ + tcgetattr (c->fd, &ptyconf); + *(c->oldptyconf) = ptyconf; + ptyconf.c_cflag &= ~(ICANON | ECHO); +- ptyconf.c_lflag &= ~ECHO; + tcsetattr (c->fd, TCSANOW, &ptyconf); + + snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b); + fd2 = open (tty, O_RDWR); +- if(!fd2) +- log(LOG_WARN, "unable to open tty %s", tty); +- +- /* XXX JEF: CHECK ME */ +- stropt[pos++] = strdup(tty); +- stropt[pos] = NULL; + + #ifdef USE_KERNEL + } diff --git a/package/l2tpd/patches/03-jacco-pty.patch b/package/l2tpd/patches/03-jacco-pty.patch new file mode 100644 index 000000000..67169b8ea --- /dev/null +++ b/package/l2tpd/patches/03-jacco-pty.patch @@ -0,0 +1,1194 @@ +diff -ruN l2tpd-0.70pre-old/l2tpd.c l2tpd-0.70pre-new/l2tpd.c +--- l2tpd-0.70pre-old/l2tpd.c 2005-12-16 12:34:12.000000000 +0100 ++++ l2tpd-0.70pre-new/l2tpd.c 2005-12-16 12:34:54.000000000 +0100 +@@ -16,6 +16,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if (__GLIBC__ < 2) ++# if defined(FREEBSD) ++# include ++# elif defined(LINUX) ++# include ++# elif defined(SOLARIS) ++# include ++# endif ++#else ++# include ++#endif ++#include ++#include ++#include ++#include ++#include ++#ifdef USE_KERNEL ++#include ++#endif ++#include "l2tp.h" ++ ++struct tunnel_list tunnels; ++int max_tunnels = DEF_MAX_TUNNELS; ++struct utsname uts; ++int ppd = 1; /* Packet processing delay */ ++int control_fd; /* descriptor of control area */ ++char *args; ++ ++char *dial_no_tmp; /* jz: Dialnumber for Outgoing Call */ ++int switch_io = 0; /* jz: Switch for Incoming or Outgoing Call */ ++ ++void init_tunnel_list (struct tunnel_list *t) ++{ ++ t->head = NULL; ++ t->count = 0; ++ t->calls = 0; ++} ++ ++/* Now sends to syslog instead - MvO */ ++void show_status (void) ++{ ++ struct schedule_entry *se; ++ struct tunnel *t; ++ struct call *c; ++ struct lns *tlns; ++ struct lac *tlac; ++ struct host *h; ++ int s = 0; ++ log (LOG_WARN, "====== l2tpd statistics ========\n"); ++ log (LOG_WARN, " Scheduler entries:\n"); ++ se = events; ++ while (se) ++ { ++ s++; ++ t = (struct tunnel *) se->data; ++ tlac = (struct lac *) se->data; ++ c = (struct call *) se->data; ++ if (se->func == &hello) ++ { ++ log (LOG_WARN, "%d: HELLO to %d\n", s, t->tid); ++ } ++ else if (se->func == &magic_lac_dial) ++ { ++ log (LOG_WARN, "%d: Magic dial on %s\n", s, tlac->entname); ++ } ++ else if (se->func == &send_zlb) ++ { ++ log (LOG_WARN, "%d: Send payload ZLB on call %d:%d\n", s, ++ c->container->tid, c->cid); ++ } ++ else if (se->func == &dethrottle) ++ { ++ log (LOG_WARN, "%d: Dethrottle call %d:%d\n", s, c->container->tid, ++ c->cid); ++ } ++ else ++ log (LOG_WARN, "%d: Unknown event\n", s); ++ se = se->next; ++ }; ++ log (LOG_WARN, "Total Events scheduled: %d\n", s); ++ log (LOG_WARN, "Number of tunnels open: %d\n", tunnels.count); ++ t = tunnels.head; ++ while (t) ++ { ++ log (LOG_WARN, "Tunnel %s, ID = %d (local), %d (remote) to %s:%d\n" ++ " control_seq_num = %d, control_rec_seq_num = %d,\n" ++ " cLr = %d\n", ++ (t->lac ? t->lac->entname : (t->lns ? t->lns->entname : "")), ++ t->ourtid, t->tid, IPADDY (t->peer.sin_addr), ++ ntohs (t->peer.sin_port), t->control_seq_num, ++ t->control_rec_seq_num, t->cLr); ++ c = t->call_head; ++ while (c) ++ { ++ log (LOG_WARN, ++ "Call %s, ID = %d (local), %d (remote), serno = %u,\n" ++ " data_seq_num = %d, data_rec_seq_num = %d,\n" ++ " pLr = %d, tx = %u bytes (%u), rx= %u bytes (%u)\n", ++ (c->lac ? c->lac-> ++ entname : (c->lns ? c->lns->entname : "")), c->ourcid, ++ c->cid, c->serno, c->data_seq_num, c->data_rec_seq_num, ++ c->pLr, c->tx_bytes, c->tx_pkts, c->rx_bytes, c->rx_pkts); ++ c = c->next; ++ } ++ t = t->next; ++ } ++ log (LOG_WARN, "==========Config File===========\n"); ++ tlns = lnslist; ++ while (tlns) ++ { ++ log (LOG_WARN, "LNS entry %s\n", ++ tlns->entname[0] ? tlns->entname : "(unnamed)"); ++ tlns = tlns->next; ++ }; ++ tlac = laclist; ++ while (tlac) ++ { ++ log (LOG_WARN, "LAC entry %s, LNS is/are:", ++ tlac->entname[0] ? tlac->entname : "(unnamed)"); ++ h = tlac->lns; ++ if (h) ++ { ++ while (h) ++ { ++ log (LOG_WARN, " %s", h->hostname); ++ h = h->next; ++ } ++ } ++ else ++ log (LOG_WARN, " [none]"); ++ log (LOG_WARN, "\n"); ++ tlac = tlac->next; ++ }; ++ log (LOG_WARN, "================================\n"); ++} ++ ++void null_handler(int sig) ++{ ++ /* FIXME ++ * A sighup is received when a call is terminated, unknown origine .. ++ * I catch it and ll looks good, but .. ++ */ ++} ++ ++void status_handler (int sig) ++{ ++ show_status (); ++} ++ ++void child_handler (int signal) ++{ ++ /* ++ * Oops, somebody we launched was killed. ++ * It's time to reap them and close that call. ++ * But first, we have to find out what PID died. ++ * unfortunately, pppd will ++ */ ++ struct tunnel *t; ++ struct call *c; ++ pid_t pid; ++ int status; ++ t = tunnels.head; ++ /* Keep looping until all are cleared */ ++ for(;;) ++ { ++ pid = waitpid (-1, &status, WNOHANG); ++ if (pid < 1) ++ { ++ /* ++ * Oh well, nobody there. Maybe we reaped it ++ * somewhere else already ++ */ ++ return; ++ } ++ while (t) ++ { ++ c = t->call_head; ++ while (c) ++ { ++ if (c->pppd == pid) ++ { ++ if ( WIFEXITED( status ) ) ++ { ++ log (LOG_DEBUG, "%s : pppd exited for call %d with code %d\n", __FUNCTION__, ++ c->cid, WEXITSTATUS( status ) ); ++ } ++ else if( WIFSIGNALED( status ) ) ++ { ++ log (LOG_DEBUG, "%s : pppd terminated for call %d by signal %d\n", __FUNCTION__, ++ c->cid, WTERMSIG( status ) ); ++ } ++ else ++ { ++ log (LOG_DEBUG, "%s : pppd exited for call %d for unknown reason\n", __FUNCTION__, ++ c->cid ); ++ } ++ c->needclose = -1; ++ /* ++ * OK...pppd died, we can go ahead and close the pty for ++ * it ++ */ ++ close (c->fd); ++ c->fd = -1; ++ return; ++ } ++ c = c->next; ++ } ++ t = t->next; ++ } ++ } ++} ++ ++void death_handler (int signal) ++{ ++ /* ++ * If we get here, somebody terminated us with a kill or a control-c. ++ * we call call_close on each tunnel twice to get a StopCCN out ++ * for each one (we can't pause to make sure it's received. ++ * Then we close the connections ++ */ ++ struct tunnel *st, *st2; ++ int sec; ++ log (LOG_CRIT, "%s: Fatal signal %d received\n", __FUNCTION__, signal); ++ st = tunnels.head; ++ while (st) ++ { ++ st2 = st->next; ++ strcpy (st->self->errormsg, "Server closing"); ++ sec = st->self->closing; ++ if (st->lac) ++ st->lac->redial = 0; ++ call_close (st->self); ++ if (!sec) ++ { ++ st->self->closing = -1; ++ call_close (st->self); ++ } ++ st = st2; ++ } ++ ++ /* erase pid file */ ++ unlink (gconfig.pidfile); ++ ++ /* erase control pipe */ ++ unlink(CONTROL_PIPE); ++ ++ exit (1); ++} ++ ++int start_pppd (struct call *c, struct ppp_opts *opts) ++{ ++ char a, b; ++ char tty[80]; ++ char *stropt[80]; ++ struct ppp_opts *p; ++#ifdef USE_KERNEL ++ struct l2tp_call_opts co; ++#endif ++ int pos = 1; ++ int fd2; ++#ifdef DEBUG_PPPD ++ int x; ++#endif ++ struct termios ptyconf; ++ char *str; ++ p = opts; ++ stropt[0] = strdup (PPPD); ++ while (p) ++ { ++ stropt[pos] = (char *) malloc (strlen (p->option) + 1); ++ strncpy (stropt[pos], p->option, strlen (p->option) + 1); ++ pos++; ++ p = p->next; ++ } ++ stropt[pos] = NULL; ++ if (c->pppd > 0) ++ { ++ log (LOG_WARN, "%s: PPP already started on call!\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ if (c->fd > -1) ++ { ++ log (LOG_WARN, "%s: file descriptor already assigned!\n", ++ __FUNCTION__); ++ return -EINVAL; ++ } ++#ifdef USE_KERNEL ++ if (kernel_support) ++ { ++ co.ourtid = c->container->ourtid; ++ co.ourcid = c->ourcid; ++ ioctl (server_socket, L2TPIOCGETCALLOPTS, &co); ++ stropt[pos++] = strdup ("channel"); ++ stropt[pos] = (char *) malloc (10); ++ snprintf (stropt[pos], 10, "%d", co.id); ++ pos++; ++ stropt[pos] = NULL; ++ } ++ else ++ { ++#endif ++ if ((c->fd = getPtyMaster (&a, &b)) < 0) ++ { ++ log (LOG_WARN, "%s: unable to allocate pty, abandoning!\n", ++ __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ /* set fd opened above to not echo so we don't see read our own packets ++ back of the file descriptor that we just wrote them to */ ++ tcgetattr (c->fd, &ptyconf); ++ *(c->oldptyconf) = ptyconf; ++ ptyconf.c_cflag &= ~(ICANON | ECHO); ++ tcsetattr (c->fd, TCSANOW, &ptyconf); ++ ++ snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b); ++ fd2 = open (tty, O_RDWR); ++ ++#ifdef USE_KERNEL ++ } ++#endif ++ str = stropt[0]; ++#ifdef DEBUG_PPPD ++ log (LOG_DEBUG, "%s: I'm running: ", __FUNCTION__); ++ for (x = 0; stropt[x]; x++) ++ { ++ log (LOG_DEBUG, "\"%s\" ", stropt[x]); ++ }; ++ log (LOG_DEBUG, "\n"); ++#endif ++ c->pppd = fork (); ++ if (c->pppd < 0) ++ { ++ log (LOG_WARN, "%s: unable to fork(), abandoning!\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ else if (!c->pppd) ++ { ++ struct call *sc; ++ struct tunnel *st; ++ ++ close (0); ++ close (1); ++ close (2); ++#ifdef USE_KERNEL ++ if (!kernel_support && (fd2 < 0)) ++#else ++ if (fd2 < 0) ++#endif ++ { ++ log (LOG_WARN, "%s: Unable to open %s to launch pppd!\n", ++ __FUNCTION__, tty); ++ exit (1); ++ } ++ dup2 (fd2, 0); ++ dup2 (fd2, 1); ++ ++ ++ /* close all the calls pty fds */ ++ st = tunnels.head; ++ while (st) ++ { ++ sc = st->call_head; ++ while (sc) ++ { ++ close (sc->fd); ++ sc = sc->next; ++ } ++ st = st->next; ++ } ++ ++ /* close the UDP socket fd */ ++ close (server_socket); ++ ++ /* close the control pipe fd */ ++ close (control_fd); ++ ++ if( c->dialing[0] ) ++ { ++ setenv( "CALLER_ID", c->dialing, 1 ); ++ } ++ execv (PPPD, stropt); ++ log (LOG_WARN, "%s: Exec of %s failed!\n", __FUNCTION__, PPPD); ++ exit (1); ++ }; ++ close (fd2); ++ pos = 0; ++ while (stropt[pos]) ++ { ++ free (stropt[pos]); ++ pos++; ++ }; ++ return 0; ++} ++ ++void destroy_tunnel (struct tunnel *t) ++{ ++ /* ++ * Immediately destroy a tunnel (and all its calls) ++ * and free its resources. This may be called ++ * by the tunnel itself,so it needs to be ++ * "suicide safe" ++ */ ++ ++ struct call *c, *me; ++ struct tunnel *p; ++ struct timeval tv; ++ if (!t) ++ return; ++ ++ /* ++ * Save ourselves until the very ++ * end, since we might be calling this ourselves. ++ * We must divorce ourself from the tunnel ++ * structure, however, to avoid recursion ++ * because of the logic of the destroy_call ++ */ ++ me = t->self; ++ ++ /* ++ * Destroy all the member calls ++ */ ++ c = t->call_head; ++ while (c) ++ { ++ destroy_call (c); ++ c = c->next; ++ }; ++ /* ++ * Remove ourselves from the list of tunnels ++ */ ++ ++ if (tunnels.head == t) ++ { ++ tunnels.head = t->next; ++ tunnels.count--; ++ } ++ else ++ { ++ p = tunnels.head; ++ if (p) ++ { ++ while (p->next && (p->next != t)) ++ p = p->next; ++ if (p->next) ++ { ++ p->next = t->next; ++ tunnels.count--; ++ } ++ else ++ { ++ log (LOG_WARN, ++ "%s: unable to locate tunnel in tunnel list\n", ++ __FUNCTION__); ++ } ++ } ++ else ++ { ++ log (LOG_WARN, "%s: tunnel list is empty!\n", __FUNCTION__); ++ } ++ } ++ if (t->lac) ++ { ++ t->lac->t = NULL; ++ if (t->lac->redial && (t->lac->rtimeout > 0) && !t->lac->rsched && ++ t->lac->active) ++ { ++ log (LOG_LOG, "%s: Will redial in %d seconds\n", __FUNCTION__, ++ t->lac->rtimeout); ++ tv.tv_sec = t->lac->rtimeout; ++ tv.tv_usec = 0; ++ t->lac->rsched = schedule (tv, magic_lac_dial, t->lac); ++ } ++ } ++ /* XXX L2TP/IPSec: remove relevant SAs here? NTB 20011010 ++ * XXX But what if another tunnel is using same SA? ++ */ ++ if (t->lns) ++ t->lns->t = NULL; ++ free (t); ++ free (me); ++} ++ ++struct tunnel *l2tp_call (char *host, int port, struct lac *lac, ++ struct lns *lns) ++{ ++ /* ++ * Establish a tunnel from us to host ++ * on port port ++ */ ++ struct call *tmp = NULL; ++ struct hostent *hp; ++ unsigned int addr; ++ port = htons (port); ++ hp = gethostbyname (host); ++ if (!hp) ++ { ++ log (LOG_WARN, "%s: gethostbyname() failed for %s.\n", __FUNCTION__, ++ host); ++ return NULL; ++ } ++ bcopy (hp->h_addr, &addr, hp->h_length); ++ /* Force creation of a new tunnel ++ and set it's tid to 0 to cause ++ negotiation to occur */ ++ /* XXX L2TP/IPSec: Set up SA to addr:port here? NTB 20011010 ++ */ ++ tmp = get_call (0, 0, addr, port); ++ if (!tmp) ++ { ++ log (LOG_WARN, "%s: Unable to create tunnel to %s.\n", __FUNCTION__, ++ host); ++ return NULL; ++ } ++ tmp->container->tid = 0; ++ tmp->container->lac = lac; ++ tmp->container->lns = lns; ++ tmp->lac = lac; ++ tmp->lns = lns; ++ if (lac) ++ lac->t = tmp->container; ++ if (lns) ++ lns->t = tmp->container; ++ /* ++ * Since our state is 0, we will establish a tunnel now ++ */ ++ log (LOG_LOG, "%s:Connecting to host %s, port %d\n", __FUNCTION__, host, ++ ntohs (port)); ++ control_finish (tmp->container, tmp); ++ return tmp->container; ++} ++ ++void magic_lac_tunnel (void *data) ++{ ++ struct lac *lac; ++ lac = (struct lac *) data; ++ if (!lac) ++ { ++ log (LOG_WARN, "%s: magic_lac_tunnel: called on NULL lac!\n", ++ __FUNCTION__); ++ return; ++ } ++ if (lac->lns) ++ { ++ /* FIXME: I should try different LNS's if I get failures */ ++ l2tp_call (lac->lns->hostname, lac->lns->port, lac, NULL); ++ return; ++ } ++ else if (deflac && deflac->lns) ++ { ++ l2tp_call (deflac->lns->hostname, deflac->lns->port, lac, NULL); ++ return; ++ } ++ else ++ { ++ log (LOG_WARN, "%s: Unable to find hostname to dial for '%s'\n", ++ __FUNCTION__, lac->entname); ++ return; ++ } ++} ++ ++struct call *lac_call (int tid, struct lac *lac, struct lns *lns) ++{ ++ struct tunnel *t = tunnels.head; ++ struct call *tmp; ++ while (t) ++ { ++ if (t->ourtid == tid) ++ { ++ tmp = new_call (t); ++ if (!tmp) ++ { ++ log (LOG_WARN, "%s: unable to create new call\n", ++ __FUNCTION__); ++ return NULL; ++ } ++ tmp->next = t->call_head; ++ t->call_head = tmp; ++ t->count++; ++ tmp->cid = 0; ++ tmp->lac = lac; ++ tmp->lns = lns; ++ if (lac) ++ lac->c = tmp; ++ log (LOG_LOG, "%s: Calling on tunnel %d\n", __FUNCTION__, tid); ++ strcpy (tmp->dial_no, dial_no_tmp); /* jz: copy dialnumber to tmp->dial_no */ ++ control_finish (t, tmp); ++ return tmp; ++ } ++ t = t->next; ++ }; ++ log (LOG_DEBUG, "%s: No such tunnel %d to generate call.\n", __FUNCTION__, ++ tid); ++ return NULL; ++} ++ ++void magic_lac_dial (void *data) ++{ ++ struct lac *lac; ++ lac = (struct lac *) data; ++ ++ if (!lac) ++ { ++ log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__); ++ return; ++ } ++ if (!lac->active) ++ { ++ log (LOG_DEBUG, "%s: LAC %s not active", __FUNCTION__, lac->entname); ++ return; ++ } ++ lac->rsched = NULL; ++ lac->rtries++; ++ if (lac->rmax && (lac->rtries > lac->rmax)) ++ { ++ log (LOG_LOG, "%s: maximum retries exceeded.\n", __FUNCTION__); ++ return; ++ } ++ if (!lac->t) ++ { ++#ifdef DEGUG_MAGIC ++ log (LOG_DEBUG, "%s : tunnel not up! Connecting!\n", __FUNCTION__); ++#endif ++ magic_lac_tunnel (lac); ++ return; ++ } ++ lac_call (lac->t->ourtid, lac, NULL); ++} ++ ++void lac_hangup (int cid) ++{ ++ struct tunnel *t = tunnels.head; ++ struct call *tmp; ++ while (t) ++ { ++ tmp = t->call_head; ++ while (tmp) ++ { ++ if (tmp->ourcid == cid) ++ { ++ log (LOG_LOG, ++ "%s :Hanging up call %d, Local: %d, Remote: %d\n", ++ __FUNCTION__, tmp->serno, tmp->ourcid, tmp->cid); ++ strcpy (tmp->errormsg, "Goodbye!"); ++/* tmp->needclose = -1; */ ++ kill (tmp->pppd, SIGTERM); ++ return; ++ } ++ tmp = tmp->next; ++ } ++ t = t->next; ++ }; ++ log (LOG_DEBUG, "%s : No such call %d to hang up.\n", __FUNCTION__, cid); ++ return; ++} ++ ++void lac_disconnect (int tid) ++{ ++ struct tunnel *t = tunnels.head; ++ while (t) ++ { ++ if (t->ourtid == tid) ++ { ++ log (LOG_LOG, ++ "%s: Disconnecting from %s, Local: %d, Remote: %d\n", ++ __FUNCTION__, IPADDY (t->peer.sin_addr), t->ourtid, t->tid); ++ t->self->needclose = -1; ++ strcpy (t->self->errormsg, "Goodbye!"); ++ call_close (t->self); ++ return; ++ } ++ t = t->next; ++ }; ++ log (LOG_DEBUG, "%s: No such tunnel %d to hang up.\n", __FUNCTION__, tid); ++ return; ++} ++ ++struct tunnel *new_tunnel () ++{ ++ struct tunnel *tmp = malloc (sizeof (struct tunnel)); ++ char entropy_buf[2] = "\0"; ++ if (!tmp) ++ return NULL; ++ tmp->control_seq_num = 0; ++ tmp->control_rec_seq_num = 0; ++ tmp->cLr = 0; ++ tmp->call_head = NULL; ++ tmp->next = NULL; ++ tmp->debug = -1; ++ tmp->tid = -1; ++ tmp->hello = NULL; ++#ifndef TESTING ++/* while(get_call((tmp->ourtid = rand() & 0xFFFF),0,0,0)); */ ++#ifdef USE_KERNEL ++ if (kernel_support) ++ tmp->ourtid = ioctl (server_socket, L2TPIOCADDTUNNEL, 0); ++ else ++#endif ++/* tmp->ourtid = rand () & 0xFFFF; */ ++ /* get_entropy((char *)&tmp->ourtid, 2); */ ++ get_entropy(entropy_buf, 2); ++ { ++ int *temp; ++ temp = (int *)entropy_buf; ++ tmp->ourtid = *temp & 0xFFFF; ++#ifdef DEBUG_ENTROPY ++ log(LOG_DEBUG, "ourtid = %u, entropy_buf = %hx\n", tmp->ourtid, *temp); ++#endif ++ } ++#else ++ tmp->ourtid = 0x6227; ++#endif ++ tmp->nego = 0; ++ tmp->count = 0; ++ tmp->state = 0; /* Nothing */ ++ tmp->peer.sin_family = AF_INET; ++ tmp->peer.sin_port = 0; ++ bzero (&(tmp->peer.sin_addr), sizeof (tmp->peer.sin_addr)); ++ tmp->sanity = -1; ++ tmp->qtid = -1; ++ tmp->ourfc = ASYNC_FRAMING | SYNC_FRAMING; ++ tmp->ourbc = 0; ++ tmp->ourtb = (((_u64) rand ()) << 32) | ((_u64) rand ()); ++ tmp->fc = -1; /* These really need to be specified by the peer */ ++ tmp->bc = -1; /* And we want to know if they forgot */ ++ tmp->hostname[0] = 0; ++ tmp->vendor[0] = 0; ++ tmp->secret[0] = 0; ++ if (!(tmp->self = new_call (tmp))) ++ { ++ free (tmp); ++ return NULL; ++ }; ++ tmp->ourrws = DEFAULT_RWS_SIZE; ++ tmp->self->ourfbit = FBIT; ++ tmp->lac = NULL; ++ tmp->lns = NULL; ++ tmp->chal_us.state = 0; ++ tmp->chal_us.secret[0] = 0; ++ memset (tmp->chal_us.reply, 0, MD_SIG_SIZE); ++ tmp->chal_them.state = 0; ++ tmp->chal_them.secret[0] = 0; ++ memset (tmp->chal_them.reply, 0, MD_SIG_SIZE); ++ tmp->chal_them.vector = (unsigned char *) malloc (VECTOR_SIZE); ++ tmp->chal_us.vector = NULL; ++ tmp->hbit = 0; ++ return tmp; ++} ++ ++void do_control () ++{ ++ char buf[1024]; ++ char *host, *tunstr, *callstr, *tmpstr; ++ struct lac *lac; ++ int call; ++ int tunl; ++ int cnt = -1; ++ while (cnt) ++ { ++ cnt = read (control_fd, buf, sizeof (buf)); ++ if (cnt > 0) ++ { ++ if (buf[cnt - 1] == '\n') ++ buf[--cnt] = 0; ++#ifdef DEBUG_CONTROL ++ log (LOG_DEBUG, "%s: Got message \"%s\" (%d bytes long)\n", ++ __FUNCTION__, buf, cnt); ++#endif ++ switch (buf[0]) ++ { ++ case 't': ++ host = strchr (buf, ' '); ++ if(!host) ++ goto out; ++ host++; ++#ifdef DEBUG_CONTROL ++ log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n", ++ __FUNCTION__, host); ++#endif ++ l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL); ++ break; ++ case 'c': /* option 'c' for incoming call */ ++ case 'o': /* option 'o' for outgoing call */ ++ tunstr = strchr (buf, ' '); ++ if(!tunstr) ++ goto out; ++ tunstr++; ++ ++ if(buf[0] == 'c') ++ switch_io = 1; /* Switch for Incoming Calls */ ++ else { ++ switch_io = 0; /* Switch for Outgoing Calls */ ++ tmpstr = strchr(tunstr, ' '); ++ if(!tmpstr) ++ goto out; ++ strncpy(dial_no_tmp,tmpstr, sizeof(*dial_no_tmp)); ++ } ++ ++ lac = laclist; ++ while (lac) ++ { ++ if (!strcasecmp (lac->entname, tunstr)) ++ { ++ lac->active = -1; ++ lac->rtries = 0; ++ if (!lac->c) ++ magic_lac_dial (lac); ++ else ++ log (LOG_DEBUG, ++ "%s: Session '%s' already active!\n", ++ __FUNCTION__, lac->entname); ++ break; ++ } ++ lac = lac->next; ++ } ++ if (lac) ++ break; ++ tunl = atoi (tunstr); ++ if (!tunl) ++ { ++ log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__, ++ tunstr); ++ break; ++ } ++#ifdef DEBUG_CONTROL ++ log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n", ++ __FUNCTION__, tunl); ++#endif ++ lac_call (tunl, NULL, NULL); ++ break; ++ case 'h': ++ callstr = strchr (buf, ' '); ++ if(!callstr) ++ goto out; ++ callstr++; ++ ++ call = atoi (callstr); ++#ifdef DEBUG_CONTROL ++ log (LOG_DEBUG, "%s: Attempting to call %d\n", __FUNCTION__, ++ call); ++#endif ++ lac_hangup (call); ++ break; ++ case 'd': ++ tunstr = strchr (buf, ' '); ++ if(!tunstr) ++ goto out; ++ tunstr++; ++ ++ lac = laclist; ++ while (lac) ++ { ++ if (!strcasecmp (lac->entname, tunstr)) ++ { ++ lac->active = 0; ++ lac->rtries = 0; ++ if (lac->t) ++ lac_disconnect (lac->t->ourtid); ++ else ++ log (LOG_DEBUG, "%s: Session '%s' not up\n", ++ __FUNCTION__, lac->entname); ++ break; ++ } ++ lac = lac->next; ++ } ++ if (lac) ++ break; ++ tunl = atoi (tunstr); ++ if (!tunl) ++ { ++ log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__, ++ tunstr); ++ break; ++ } ++#ifdef DEBUG_CONTROL ++ log (LOG_DEBUG, "%s: Attempting to disconnect tunnel %d\n", ++ __FUNCTION__, tunl); ++#endif ++ lac_disconnect (tunl); ++ break; ++ case 's': ++ show_status (); ++ break; ++ default: ++ log (LOG_DEBUG, "%s: Unknown command %c\n", __FUNCTION__, ++ buf[0]); ++ } ++ } ++ } ++ ++out: ++ /* Otherwise select goes nuts */ ++ close (control_fd); ++ control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600); ++} ++ ++void usage(void) { ++ printf("Usage: l2tpd -D -c [config file] -s [secret file] -p [pid file]\n"); ++ printf("\n"); ++ exit(1); ++} ++ ++void init_args(int argc, char *argv[]) { ++ int i=0; ++ gconfig.daemon=1; ++ memset(gconfig.altauthfile,0,STRLEN); ++ memset(gconfig.altconfigfile,0,STRLEN); ++ memset(gconfig.authfile,0,STRLEN); ++ memset(gconfig.configfile,0,STRLEN); ++ memset(gconfig.pidfile,0,STRLEN); ++ strncpy(gconfig.altauthfile,ALT_DEFAULT_AUTH_FILE, ++ sizeof(gconfig.altauthfile) - 1); ++ strncpy(gconfig.altconfigfile,ALT_DEFAULT_CONFIG_FILE, ++ sizeof(gconfig.altconfigfile) - 1); ++ strncpy(gconfig.authfile,DEFAULT_AUTH_FILE, ++ sizeof(gconfig.authfile) - 1); ++ strncpy(gconfig.configfile,DEFAULT_CONFIG_FILE, ++ sizeof(gconfig.configfile) - 1); ++ strncpy(gconfig.pidfile,DEFAULT_PID_FILE, ++ sizeof(gconfig.pidfile) - 1); ++ for (i = 1; i < argc; i++) { ++ if(! strncmp(argv[i],"-c",2)) { ++ if(++i == argc) ++ usage(); ++ else ++ strncpy(gconfig.configfile,argv[i], ++ sizeof(gconfig.configfile) - 1); ++ } ++ else if (! strncmp(argv[i],"-D",2)) { ++ gconfig.daemon=0; ++ } ++ else if (! strncmp(argv[i],"-s",2)) { ++ if(++i == argc) ++ usage(); ++ else ++ strncpy(gconfig.authfile,argv[i], ++ sizeof(gconfig.authfile) - 1); ++ } ++ else if (! strncmp(argv[i],"-p",2)) { ++ if(++i == argc) ++ usage(); ++ else ++ strncpy(gconfig.pidfile,argv[i], ++ sizeof(gconfig.pidfile) - 1); ++ } ++ else { ++ usage(); ++ } ++ } ++} ++ ++ ++void daemonize() { ++ int pid=0; ++ int i,l; ++ char buf[STRLEN]; ++ ++ if((pid = fork()) < 0) { ++ log(LOG_LOG, "%s: Unable to fork ()\n",__FUNCTION__); ++ close(server_socket); ++ exit(1); ++ } ++ else if (pid) ++ exit(0); ++ ++ ++ close(0); ++ close(1); ++ close(2); ++ dup2(open("/dev/null", O_RDONLY), 0); ++ dup2(open("/dev/null", O_RDONLY), 1); ++ dup2(open("/dev/null", O_RDONLY), 2); ++ ++ /* Read previous pid file. */ ++ if((i = open(gconfig.pidfile,O_RDONLY)) > 0) { ++ l=read(i,buf,sizeof(buf)-1); ++ if (l >= 0) { ++ buf[l] = '\0'; ++ pid = atoi(buf); ++ } ++ close(i); ++ ++ /* if pid is read and process exist exit */ ++ if(pid && !kill(pid, 0)) { ++ log(LOG_LOG, "%s: There's already a l2tpd server running.\n", ++ __FUNCTION__); ++ close(server_socket); ++ exit(1); ++ } ++ ++ /* remove stalled pid file */ ++ unlink(gconfig.pidfile); ++ } ++ ++ pid = setsid(); ++ ++ /* create new pid file */ ++ if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0644)) >= 0) { ++ snprintf (buf, sizeof(buf), "%d", (int)getpid()); ++ write (i, buf, strlen(buf)); ++ close (i); ++ } ++ else { ++ log(LOG_LOG, "%s: could not write pid file %s error %d", ++ __FUNCTION__, gconfig.pidfile, i); ++ close(server_socket); ++ exit(1); ++ } ++} ++ ++ ++void init (int argc,char *argv[]) ++{ ++ struct lac *lac; ++ struct in_addr listenaddr; ++ ++ init_args (argc,argv); ++ srand( time(NULL) ); ++ rand_source = 0; ++ init_addr (); ++ if (init_config ()) ++ { ++ log (LOG_CRIT, "%s: Unable to load config file\n", __FUNCTION__); ++ exit (1); ++ } ++ if (uname (&uts)) ++ { ++ log (LOG_CRIT, "%s : Unable to determine host system\n", ++ __FUNCTION__); ++ exit (1); ++ } ++ init_tunnel_list (&tunnels); ++ if (init_network ()) ++ exit (1); ++ if (gconfig.daemon) ++ daemonize (); ++ signal (SIGTERM, &death_handler); ++ signal (SIGINT, &death_handler); ++ signal (SIGCHLD, &child_handler); ++ signal (SIGUSR1, &status_handler); ++ signal (SIGHUP, &null_handler); ++ init_scheduler (); ++ mkfifo (CONTROL_PIPE, 0600); ++ control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600); ++ if (control_fd < 0) ++ { ++ log (LOG_CRIT, "%s: Unable to open " CONTROL_PIPE " for reading.", ++ __FUNCTION__); ++ exit (1); ++ } ++ log (LOG_LOG, "l2tpd version " SERVER_VERSION " started on %s PID:%d\n", ++ hostname, getpid ()); ++ listenaddr.s_addr = gconfig.listenaddr; ++ log (LOG_LOG, "%s version %s on a %s, listening on IP address %s, port %d\n", uts.sysname, ++ uts.release, uts.machine, inet_ntoa(listenaddr), gconfig.port); ++ lac = laclist; ++ while (lac) ++ { ++ if (lac->autodial) ++ { ++#ifdef DEBUG_MAGIC ++ log (LOG_DEBUG, "%s: Autodialing '%s'\n", __FUNCTION__, ++ lac->entname[0] ? lac->entname : "(unnamed)"); ++#endif ++ lac->active = -1; ++ switch_io = 1; /* If we're a LAC, autodials will be ICRQ's */ ++ magic_lac_dial (lac); ++ } ++ lac = lac->next; ++ } ++} ++ ++int main (int argc, char *argv[]) ++{ ++ init(argc,argv); ++ dial_no_tmp = calloc (128, sizeof (char)); ++ network_thread (); ++ return 0; ++} diff --git a/package/l2tpd/patches/debian-2.patch b/package/l2tpd/patches/debian-2.patch deleted file mode 100644 index 8a6e204c4..000000000 --- a/package/l2tpd/patches/debian-2.patch +++ /dev/null @@ -1,3394 +0,0 @@ ---- l2tpd-0.70-pre20031121.orig/Makefile -+++ l2tpd-0.70-pre20031121/Makefile -@@ -28,7 +28,8 @@ - # become runtime options) debugging flags - # - #DFLAGS= -g -O2 -DDEBUG_PPPD --DFLAGS= -g -O2 -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY -+#DFLAGS= -g -O2 -Wall -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY -+DFLAGS= -ggdb -Wall -DDEBUG_PPPD -DDEBUG_CONTROL -DDEBUG_ENTROPY - # - # Uncomment the next line for Linux - # -@@ -58,7 +59,7 @@ - - FFLAGS= -DIP_ALLOCATION - --CFLAGS= $(DFLAGS) -Wall -DSANITY $(OSFLAGS) $(FFLAGS) -+CFLAGS= $(DFLAGS) -Wall -DSANITY $(OSFLAGS) $(FFLAGS) - HDRS=l2tp.h avp.h misc.h control.h call.h scheduler.h file.h aaa.h md5.h - OBJS=l2tpd.o pty.o misc.o control.o avp.o call.o network.o avpsend.o scheduler.o file.o aaa.o md5.o - LIBS= $(OSLIB) # -lefence # efence for malloc checking ---- l2tpd-0.70-pre20031121.orig/control.c -+++ l2tpd-0.70-pre20031121/control.c -@@ -227,7 +227,7 @@ - add_bearer_caps_avp (buf, t->ourbc); - /* FIXME: Tie breaker */ - add_firmware_avp (buf); -- add_hostname_avp (buf); -+ add_hostname_avp (buf, t); - add_vendor_avp (buf); - add_tunnelid_avp (buf, t->ourtid); - if (t->ourrws >= 0) -@@ -346,7 +346,6 @@ - "%s: Peer did not specify assigned tunnel ID. Closing.\n", - __FUNCTION__); - set_error (c, VENDOR_ERROR, "Specify your assigned tunnel ID"); -- c->needclose = -1; - return -EINVAL; - } - if (!(t->lns = get_lns (t))) -@@ -356,7 +355,6 @@ - "%s: Denied connection to unauthorized peer %s\n", - __FUNCTION__, IPADDY (t->peer.sin_addr)); - set_error (c, VENDOR_ERROR, "No Authorization"); -- c->needclose = -1; - return -EINVAL; - } - t->ourrws = t->lns->tun_rws; -@@ -368,7 +366,6 @@ - "%s: Peer did not specify framing capability. Closing.\n", - __FUNCTION__); - set_error (c, VENDOR_ERROR, "Specify framing capability"); -- c->needclose = -1; - return -EINVAL; - } - /* FIXME: Do we need to be sure they specified a version number? -@@ -380,7 +377,6 @@ - if (DEBUG) log(LOG_DEBUG, - "%s: Peer did not specify bearer capability. Closing.\n",__FUNCTION__); - set_error(c, VENDOR_ERROR, "Specify bearer capability"); -- c->needclose = -1; - return -EINVAL; - } */ - if ((!strlen (t->hostname)) && ((t->chal_us.state) || ((t->lns->challenge)))) -@@ -390,7 +386,6 @@ - "%s: Peer did not specify hostname. Closing.\n", - __FUNCTION__); - set_error (c, VENDOR_ERROR, "Specify your hostname"); -- c->needclose = -1; - return -EINVAL; - } - y = tunnels.head; -@@ -427,7 +422,7 @@ - add_frame_caps_avp (buf, t->ourfc); - add_bearer_caps_avp (buf, t->ourbc); - add_firmware_avp (buf); -- add_hostname_avp (buf); -+ add_hostname_avp (buf, t); - add_vendor_avp (buf); - add_tunnelid_avp (buf, t->ourtid); - if (t->ourrws >= 0) -@@ -481,7 +476,6 @@ - "%s: Peer did not specify framing capability. Closing.\n", - __FUNCTION__); - set_error (c, VENDOR_ERROR, "Specify framing capability"); -- c->needclose = -1; - return -EINVAL; - } - /* FIXME: Do we need to be sure they specified a version number? -@@ -493,7 +487,6 @@ - if (DEBUG) log(LOG_DEBUG, - "%s: Peer did not specify bearer capability. Closing.\n",__FUNCTION__); - set_error(c, VENDOR_ERROR, "Specify bearer capability"); -- c->needclose = -1; - return -EINVAL; - } */ - if ((!strlen (t->hostname)) && ((t->chal_them.state) || ((t->chal_us.state)))) -@@ -503,7 +496,6 @@ - "%s: Peer did not specify hostname. Closing.\n", - __FUNCTION__); - set_error (c, VENDOR_ERROR, "Specify your hostname"); -- c->needclose = -1; - return -EINVAL; - } - if (t->tid <= 0) -@@ -513,7 +505,6 @@ - "%s: Peer did not specify assigned tunnel ID. Closing.\n", - __FUNCTION__); - set_error (c, VENDOR_ERROR, "Specify your assigned tunnel ID"); -- c->needclose = -1; - return -EINVAL; - } - if (t->chal_them.state) -@@ -524,7 +515,6 @@ - set_error (c, VENDOR_ERROR, "No secret key on our side"); - log (LOG_WARN, "%s: No secret key for authenticating '%s'\n", - __FUNCTION__, t->hostname); -- c->needclose = -1; - return -EINVAL; - } - if (memcmp -@@ -534,7 +524,6 @@ - "Invalid challenge authentication"); - log (LOG_DEBUG, "%s: Invalid authentication for host '%s'\n", - __FUNCTION__, t->hostname); -- c->needclose = -1; - return -EINVAL; - } - } -@@ -546,7 +535,6 @@ - log (LOG_WARN, "%s: No secret for authenticating to '%s'\n", - __FUNCTION__, t->hostname); - set_error (c, VENDOR_ERROR, "No secret key on our end"); -- c->needclose = -1; - return -EINVAL; - }; - } -@@ -606,7 +594,6 @@ - "Invalid challenge authentication"); - log (LOG_DEBUG, "%s: Invalid authentication for host '%s'\n", - __FUNCTION__, t->hostname); -- c->needclose = -1; - return -EINVAL; - } - } -@@ -1584,6 +1571,14 @@ - wbuf[pos++] = e; - for (x = 0; x < buf->len; x++) - { -+ // we must at least still have 4 bytes left in the worst case scenario: -+ // 1 for a possible escape, 1 for the value and 1 to end the PPP stream. -+ if(pos >= (sizeof(wbuf) - 4)) { -+ if(DEBUG) -+ log(LOG_CRIT, "%s: rx packet is too big after PPP encoding (size %u, max is %u)\n", -+ __FUNCTION__, buf->len, MAX_RECV_SIZE); -+ return -EINVAL; -+ } - e = *((char *) buf->start + x); - if ((e < 0x20) || (e == PPP_ESCAPE) || (e == PPP_FLAG)) - { -@@ -1592,7 +1587,6 @@ - wbuf[pos++] = PPP_ESCAPE; - } - wbuf[pos++] = e; -- - } - wbuf[pos++] = PPP_FLAG; - x = write (c->fd, wbuf, pos); ---- l2tpd-0.70-pre20031121.orig/misc.h -+++ l2tpd-0.70-pre20031121/misc.h -@@ -80,4 +80,11 @@ - extern void safe_copy (char *, char *, int); - extern void opt_destroy (struct ppp_opts *); - extern struct ppp_opts *add_opt (struct ppp_opts *, char *, ...); -+extern u_int16_t get16(u_int8_t *); -+extern u_int32_t get32(u_int8_t *); -+extern u_int64_t get64(u_int8_t *); -+extern void set16(u_int8_t *, u_int16_t); -+extern void set32(u_int8_t *, u_int32_t); -+extern void set64(u_int8_t *, u_int64_t); -+ - #endif ---- l2tpd-0.70-pre20031121.orig/avp.h -+++ l2tpd-0.70-pre20031121/avp.h -@@ -19,22 +19,35 @@ - - struct avp_hdr - { -- _u16 length; -- _u16 vendorid; -- _u16 attr; -+ u_int16_t length; -+ u_int16_t vendorid; -+ u_int16_t attr; - }; - -+#define AVP_F_MANDATORY 0x1 -+#define AVP_F_FIXLEN 0x2 -+#define AVP_F_ASCII 0x4 -+ - struct avp - { -- int num; /* Number of AVP */ -- int m; /* Set M? */ -- int (*handler) (struct tunnel *, struct call *, void *, int); -- /* This should handle the AVP -- taking a tunnel, call, the data, -- and the length of the AVP as -- parameters. Should return 0 -- upon success */ -- char *description; /* A name, for debugging */ -+ u_int32_t num; /* Number of AVP */ -+ u_int32_t flags; -+ u_int32_t sz; /* expected avp payload size as -+ * (AVP_F_FIXLEN) ? (==) : (!>=) -+ * note: size checked is performed -+ * after unhiding */ -+ u_int8_t allowed_states[8]; /* List of allowed message types for -+ * a particular avp. Fixed len for -+ * alignement issues. */ -+ -+ /* This should handle the AVP taking a tunnel, call, -+ * the data, and the length of the AVP as parameters. -+ * Should return 0 upon success */ -+ int (*handle) (struct tunnel *, struct call *, void *, int); -+ -+ /* This should handle avp specifics sanity checks */ -+ int (*validate) (int, struct tunnel *, struct call *, void *, int); -+ char *description; /* A name, for debugging */ - }; - - extern int handle_avps (struct buffer *buf, struct tunnel *t, struct call *c); -@@ -84,8 +97,56 @@ - #define RESULT_CLEAR 1 - #define RESULT_ERROR 2 - #define RESULT_EXISTS 3 -+ -+/* avp id's */ -+#define MESSAGE_TYPE_AVP 0 -+#define RESULT_CODE_AVP 1 -+#define PROTOCOL_VERSION_AVP 2 -+#define FRAMING_CAP_AVP 3 -+#define BEARER_CAP_AVP 4 -+#define TIE_BREAKER_AVP 5 -+#define FIRMWARE_REV_AVP 6 -+#define HOSTNAME_AVP 7 -+#define VENDOR_NAME_AVP 8 -+#define ASSIGNED_TUN_ID_AVP 9 -+#define RX_WIN_SIZE_AVP 10 -+#define CHALLENGE_AVP 11 -+#define CHALLENGE_RESP_AVP 12 -+#define CAUSE_ERROR_AVP 13 -+#define ASSIGNED_SES_ID_AVP 14 -+#define SERIAL_NUMBER_AVP 15 -+#define MIN_BPS_AVP 16 -+#define MAX_BPS_AVP 17 -+#define BEARER_TYPE_AVP 18 -+#define FRAMING_TYPE_AVP 19 -+#define PACKET_DELAY_AVP 20 -+#define CALLED_NUMBER_AVP 21 -+#define CALLING_NUMBER_AVP 22 -+#define SUB_ADDRESS_AVP 23 -+#define TX_CONNECT_SPEED_AVP 24 -+#define PHYS_CHAN_ID_AVP 25 -+#define INIT_RX_LCP_AVP 26 -+#define LAST_TX_LCP_AVP 27 -+#define LAST_RX_LCP_AVP 28 -+#define PROXY_AUTH_TYPE_AVP 29 -+#define PROXY_AUTH_NAME_AVP 30 -+#define PROXY_AUTH_CHAL_AVP 31 -+#define PROXY_AUTH_ID_AVP 32 -+#define PROXY_AUTH_CHAL_RESP_AVP 33 -+#define CALL_ERROR_AVP 34 -+#define ACCM_AVP 35 -+#define RANDOM_VECTOR_AVP 36 -+#define PRIV_GROUP_ID_AVP 37 -+#define RX_CONNECT_SPEED_AVP 38 -+#define SEQ_REQUIRED_AVP 39 -+#define AVP_MAX SEQ_REQUIRED_AVP -+ -+extern int validate_msgtype_avp(int, struct tunnel *, struct call *, void *, int); -+extern int validate_gen_avp(int, struct tunnel *, struct call *, void *, int); -+ - extern void encrypt_avp (struct buffer *, _u16, struct tunnel *); - extern int decrypt_avp (char *, struct tunnel *); -+ - extern int message_type_avp (struct tunnel *, struct call *, void *, int); - extern int protocol_version_avp (struct tunnel *, struct call *, void *, int); - extern int framing_caps_avp (struct tunnel *, struct call *, void *, int); -@@ -97,12 +158,12 @@ - extern int receive_window_size_avp (struct tunnel *, struct call *, void *, - int); - extern int result_code_avp (struct tunnel *, struct call *, void *, int); --extern int assigned_call_avp (struct tunnel *, struct call *, void *, int); -+extern int assigned_session_avp (struct tunnel *, struct call *, void *, int); - extern int call_serno_avp (struct tunnel *, struct call *, void *, int); - extern int bearer_type_avp (struct tunnel *, struct call *, void *, int); - extern int call_physchan_avp (struct tunnel *, struct call *, void *, int); --extern int dialed_number_avp (struct tunnel *, struct call *, void *, int); --extern int dialing_number_avp (struct tunnel *, struct call *, void *, int); -+extern int called_number_avp (struct tunnel *, struct call *, void *, int); -+extern int calling_number_avp (struct tunnel *, struct call *, void *, int); - extern int sub_address_avp (struct tunnel *, struct call *, void *, int); - extern int frame_type_avp (struct tunnel *, struct call *, void *, int); - extern int rx_speed_avp (struct tunnel *, struct call *, void *, int); -@@ -118,7 +179,7 @@ - extern int add_avp_rws (struct buffer *, _u16); - extern int add_tunnelid_avp (struct buffer *, _u16); - extern int add_vendor_avp (struct buffer *); --extern int add_hostname_avp (struct buffer *); -+extern int add_hostname_avp (struct buffer *, struct tunnel*); - extern int add_firmware_avp (struct buffer *); - extern int add_bearer_caps_avp (struct buffer *buf, _u16 caps); - extern int add_frame_caps_avp (struct buffer *buf, _u16 caps); ---- l2tpd-0.70-pre20031121.orig/network.c -+++ l2tpd-0.70-pre20031121/network.c -@@ -214,6 +214,8 @@ - t->self->needclose = -1; - } - } -+ free(buf->rstart); -+ free(buf); - } - else - { -@@ -371,7 +373,9 @@ - if (debug_network) - { - log (LOG_DEBUG, "%s: recv packet from %s, size = %d," \ --"tunnel = %d, call = %d\n", __FUNCTION__, inet_ntoa (from.sin_addr), recvsize, tunnel, call); -+ "tunnel = %d, call = %d\n", __func__, -+ inet_ntoa (from.sin_addr), recvsize, -+ tunnel, call); - } - if (packet_dump) - { ---- l2tpd-0.70-pre20031121.orig/aaa.c -+++ l2tpd-0.70-pre20031121/aaa.c -@@ -209,9 +209,11 @@ - __FUNCTION__, u, t, s); - #endif - strncpy (secret, s, size); -+ fclose(f); - return -1; - } - } -+ fclose(f); - return 0; - } - ---- l2tpd-0.70-pre20031121.orig/l2tpd.c -+++ l2tpd-0.70-pre20031121/l2tpd.c -@@ -266,6 +266,9 @@ - /* erase pid file */ - unlink (gconfig.pidfile); - -+ /* erase control pipe */ -+ unlink(CONTROL_PIPE); -+ - exit (1); - } - -@@ -333,13 +336,17 @@ - tcgetattr (c->fd, &ptyconf); - *(c->oldptyconf) = ptyconf; - ptyconf.c_cflag &= ~(ICANON | ECHO); -- ptyconf.c_lflag &= ~ECHO; -+ ptyconf.c_lflag &= ~ECHO; - tcsetattr (c->fd, TCSANOW, &ptyconf); - - snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b); - fd2 = open (tty, O_RDWR); -- stropt[pos++] = strdup(tty); -- stropt[pos] = NULL; -+ if(!fd2) -+ log(LOG_WARN, "unable to open tty %s", tty); -+ -+ /* XXX JEF: CHECK ME */ -+ stropt[pos++] = strdup(tty); -+ stropt[pos] = NULL; - - #ifdef USE_KERNEL - } -@@ -623,7 +630,13 @@ - { - struct lac *lac; - lac = (struct lac *) data; -- if (!lac->active) -+ -+ if (!lac) -+ { -+ log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__); -+ return; -+ } -+ if (!lac->active) - { - log (LOG_DEBUG, "%s: LAC %s not active", __FUNCTION__, lac->entname); - return; -@@ -635,11 +648,6 @@ - log (LOG_LOG, "%s: maximum retries exceeded.\n", __FUNCTION__); - return; - } -- if (!lac) -- { -- log (LOG_WARN, "%s : called on NULL lac!\n", __FUNCTION__); -- return; -- } - if (!lac->t) - { - #ifdef DEGUG_MAGIC -@@ -774,12 +782,7 @@ - void do_control () - { - char buf[1024]; -- char *host; -- char *tunstr; -- char *callstr; -- -- char *sub_str; /* jz: use by the strtok function */ -- char *tmp_ptr; /* jz: use by the strtok function */ -+ char *host, *tunstr, *callstr, *tmpstr; - struct lac *lac; - int call; - int tunl; -@@ -792,24 +795,39 @@ - if (buf[cnt - 1] == '\n') - buf[--cnt] = 0; - #ifdef DEBUG_CONTROL -- log (LOG_DEBUG, "%s: Got message %s (%d bytes long)\n", -+ log (LOG_DEBUG, "%s: Got message \"%s\" (%d bytes long)\n", - __FUNCTION__, buf, cnt); - #endif - switch (buf[0]) - { - case 't': -- host = strchr (buf, ' ') + 1; -+ host = strchr (buf, ' '); -+ if(!host) -+ goto out; -+ host++; - #ifdef DEBUG_CONTROL - log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n", - __FUNCTION__, host); - #endif - l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL); - break; -- case 'c': -- -- switch_io = 1; /* jz: Switch for Incoming - Outgoing Calls */ -- -- tunstr = strchr (buf, ' ') + 1; -+ case 'c': /* option 'c' for incoming call */ -+ case 'o': /* option 'o' for outgoing call */ -+ tunstr = strchr (buf, ' '); -+ if(!tunstr) -+ goto out; -+ tunstr++; -+ -+ if(buf[0] == 'c') -+ switch_io = 1; /* Switch for Incoming Calls */ -+ else { -+ switch_io = 0; /* Switch for Outgoing Calls */ -+ tmpstr = strchr(tunstr, ' '); -+ if(!tmpstr) -+ goto out; -+ strncpy(dial_no_tmp,tmpstr, sizeof(*dial_no_tmp)); -+ } -+ - lac = laclist; - while (lac) - { -@@ -842,52 +860,12 @@ - #endif - lac_call (tunl, NULL, NULL); - break; -- -- case 'o': /* jz: option 'o' for doing a outgoing call */ -- -- switch_io = 0; /* jz: Switch for incoming - outgoing Calls */ -- -- sub_str = strchr (buf, ' ') + 1; -- -- tunstr = strtok (sub_str, " "); /* jz: using strtok function to get */ -- tmp_ptr = strtok (NULL, " "); /* params out of the pipe */ -- strcpy (dial_no_tmp, tmp_ptr); -- -- lac = laclist; -- while (lac) -- { -- if (!strcasecmp (lac->entname, tunstr)) -- { -- lac->active = -1; -- lac->rtries = 0; -- if (!lac->c) -- magic_lac_dial (lac); -- else -- log (LOG_DEBUG, -- "%s: Session '%s' already active!\n", -- __FUNCTION__, lac->entname); -- break; -- } -- lac = lac->next; -- } -- if (lac) -- break; -- tunl = atoi (tunstr); -- if (!tunl) -- { -- log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__, -- tunstr); -- break; -- } --#ifdef DEBUG_CONTROL -- log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n", -- __FUNCTION__, tunl); --#endif -- lac_call (tunl, NULL, NULL); -- break; -- - case 'h': -- callstr = strchr (buf, ' ') + 1; -+ callstr = strchr (buf, ' '); -+ if(!callstr) -+ goto out; -+ callstr++; -+ - call = atoi (callstr); - #ifdef DEBUG_CONTROL - log (LOG_DEBUG, "%s: Attempting to call %d\n", __FUNCTION__, -@@ -896,7 +874,11 @@ - lac_hangup (call); - break; - case 'd': -- tunstr = strchr (buf, ' ') + 1; -+ tunstr = strchr (buf, ' '); -+ if(!tunstr) -+ goto out; -+ tunstr++; -+ - lac = laclist; - while (lac) - { -@@ -937,6 +919,8 @@ - } - } - } -+ -+out: - /* Otherwise select goes nuts */ - close (control_fd); - control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600); -@@ -1002,7 +986,6 @@ - int pid=0; - int i,l; - char buf[STRLEN]; -- int pidfilewritten=0; - - if((pid = fork()) < 0) { - log(LOG_LOG, "%s: Unable to fork ()\n",__FUNCTION__); -@@ -1012,56 +995,52 @@ - else if (pid) - exit(0); - -- close(0); -- close(1); -- close(2); -+ -+ close(0); -+ close(1); -+ close(2); -+ dup2(open("/dev/null", O_RDONLY), 0); -+ dup2(open("/dev/null", O_RDONLY), 1); -+ dup2(open("/dev/null", O_RDONLY), 2); - - /* Read previous pid file. */ -- if ((i = open(gconfig.pidfile,O_RDONLY)) > 0) { -- l=read(i,buf,sizeof(buf)-1); -- if (i < 0) { -- log(LOG_LOG, "%s: Unable to read pid file [%s]\n", -- __FUNCTION__, gconfig.pidfile); -- } -- buf[i] = '\0'; -- pid = atoi(buf); -- -- /* If the previous server process is not still running, -- write a new pid file immediately. */ -- if (pid && (pid == getpid () || kill (pid, 0) < 0)) { -- unlink (gconfig.pidfile); -- if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0640)) >= 0) -- { -- snprintf (buf, sizeof(buf), "%d\n", (int)getpid()); -- write (i, buf, strlen(buf)); -- close (i); -- pidfilewritten = 1; -- } -+ if((i = open(gconfig.pidfile,O_RDONLY)) > 0) { -+ l=read(i,buf,sizeof(buf)-1); -+ if (l >= 0) { -+ buf[l] = '\0'; -+ pid = atoi(buf); - } -- else -- { -+ close(i); -+ -+ /* if pid is read and process exist exit */ -+ if(pid && !kill(pid, 0)) { - log(LOG_LOG, "%s: There's already a l2tpd server running.\n", - __FUNCTION__); - close(server_socket); - exit(1); - } -+ -+ /* remove stalled pid file */ -+ unlink(gconfig.pidfile); - } - - pid = setsid(); - -- if(! pidfilewritten) { -- unlink(gconfig.pidfile); -- if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0640)) >= 0) { -- snprintf (buf, strlen(buf), "%d\n", (int)getpid()); -- write (i, buf, strlen(buf)); -- close (i); -- pidfilewritten = 1; -- } -- } -+ /* create new pid file */ -+ if ((i = open (gconfig.pidfile, O_WRONLY | O_CREAT, 0644)) >= 0) { -+ snprintf (buf, sizeof(buf), "%d", (int)getpid()); -+ write (i, buf, strlen(buf)); -+ close (i); -+ } -+ else { -+ log(LOG_LOG, "%s: could not write pid file %s error %d", -+ __FUNCTION__, gconfig.pidfile, i); -+ close(server_socket); -+ exit(1); -+ } - } - - -- - void init (int argc,char *argv[]) - { - struct lac *lac; -@@ -1103,10 +1082,6 @@ - } - log (LOG_LOG, "l2tpd version " SERVER_VERSION " started on %s PID:%d\n", - hostname, getpid ()); -- log (LOG_LOG, -- "Written by Mark Spencer, Copyright (C) 1998, Adtran, Inc.\n"); -- log (LOG_LOG, "Forked by Scott Balmos and David Stipp, (C) 2001\n"); -- log (LOG_LOG, "Inherited by Jeff McAdams, (C) 2002\n"); - listenaddr.s_addr = gconfig.listenaddr; - log (LOG_LOG, "%s version %s on a %s, listening on IP address %s, port %d\n", uts.sysname, - uts.release, uts.machine, inet_ntoa(listenaddr), gconfig.port); ---- l2tpd-0.70-pre20031121.orig/misc.c -+++ l2tpd-0.70-pre20031121/misc.c -@@ -301,3 +301,42 @@ - return -1; - } - } -+ -+u_int16_t get16(u_int8_t *p) { -+ return p[0] << 8 | p[1]; -+} -+ -+u_int32_t get32(u_int8_t *p) { -+ return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; -+} -+ -+u_int64_t get64(u_int8_t *p) { -+ return (u_int64_t)p[0] << 56 | (u_int64_t)p[1] << 48 | -+ (u_int64_t)p[2] << 40 | (u_int64_t)p[3] << 32 | -+ (u_int64_t)p[4] << 24 | (u_int64_t)p[5] << 16 | -+ (u_int64_t)p[6] << 8 | (u_int64_t)p[7]; -+} -+ -+void set16(u_int8_t *cp, u_int16_t x) { -+ *cp++ = x >> 8; -+ *cp = x & 0xff; -+} -+ -+void set32(u_int8_t *cp, u_int32_t x) { -+ *cp++ = x >> 24; -+ *cp++ = (x >> 16) & 0xff; -+ *cp++ = (x >> 8) & 0xff; -+ *cp = x & 0xff; -+} -+ -+void set64(u_int8_t *cp, u_int64_t x) { -+ *cp++ = x >> 56; -+ *cp++ = (x >> 48) & 0xff; -+ *cp++ = (x >> 40) & 0xff; -+ *cp++ = (x >> 32) & 0xff; -+ *cp++ = (x >> 24) & 0xff; -+ *cp++ = (x >> 16) & 0xff; -+ *cp++ = (x >> 8) & 0xff; -+ *cp = x & 0xff; -+} -+ ---- l2tpd-0.70-pre20031121.orig/avp.c -+++ l2tpd-0.70-pre20031121/avp.c -@@ -4,9 +4,12 @@ - * Layer Two Tunnelling Protocol Daemon - * Copyright (C) 1998 Adtran, Inc. - * Copyright (C) 2002 Jeff McAdams -+ * Copyright (C) 2003 Jean-Francois Dive - * - * Mark Spencer - * -+ * 12/2003 parsing sanitization, Jean-Francois Dive -+ * - * This software is distributed under the terms - * of the GPL, which you should have received - * along with this source. -@@ -20,50 +23,53 @@ - #include - #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 - #include --#include -+#include - #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 */ -+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; -+}