--- 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; +}