added preliminary ascend binary support
authoraland <aland>
Thu, 26 Aug 1999 20:13:59 +0000 (20:13 +0000)
committeraland <aland>
Thu, 26 Aug 1999 20:13:59 +0000 (20:13 +0000)
src/lib/Makefile.in
src/lib/dict.c
src/lib/filters.c [new file with mode: 0644]
src/lib/print.c
src/lib/radius.c
src/lib/valuepair.c

index 74b4bec..33e6e30 100644 (file)
@@ -1,7 +1,8 @@
 
 @INCLUDE@ @IQUOTE@../../Make.inc@IQUOTE@
 
-OBJS           = dict.o md5.o print.o radius.o valuepair.o token.o misc.o log.o
+OBJS           = dict.o md5.o print.o radius.o valuepair.o token.o misc.o \
+               log.o filters.o
 
 INCLUDES       = ../include/radius.h ../include/libradius.h
 BUILDDBM       = @BUILDDBM@
@@ -14,6 +15,9 @@ libradius.a: $(OBJS)
        $(AR) rv libradius.a $(OBJS)
        $(RANLIB) libradius.a
 
+filters.o: filters.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c filters.c
+
 print.o: print.c $(INCLUDES)
        $(CC) $(CFLAGS) -c print.c
 
index 9ba6762..bea4f73 100644 (file)
@@ -1,11 +1,13 @@
 /*
  * dict.c      Routines to read the dictionary file.
  *
- * Version:    @(#)dict.c  2.30  25-Jul-1999  miquels@cistron.nl
+ * Version:    $Id$
  *
  */
 
-#include       <autoconf.h>
+static const char rcsid[] = "$Id$";
+
+#include       "autoconf.h"
 
 #include       <stdio.h>
 #include       <stdlib.h>
@@ -30,6 +32,9 @@ static char *dtypes[] = {
        "integer",
        "ipaddr",
        "date",
+#ifdef ASCEND_BINARY
+       "abinary",
+#endif
        NULL,
 };
 
diff --git a/src/lib/filters.c b/src/lib/filters.c
new file mode 100644 (file)
index 0000000..f3b27ba
--- /dev/null
@@ -0,0 +1,1355 @@
+/*
+ * ASCEND: @(#)filters.c       1.3 (95/07/25 00:55:30)
+ *
+ *      Copyright (c) 1994 Ascend Communications, Inc.
+ *      All rights reserved.
+ *
+ *     Permission to copy all or part of this material for any purpose is
+ *     granted provided that the above copyright notice and this paragraph
+ *     are duplicated in all copies.  THIS SOFTWARE IS PROVIDED ``AS IS''
+ *     AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ *     LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *     FOR A PARTICULAR PURPOSE.
+ */
+
+/* $Id$ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <sys/time.h>  /* gettimeofday() */
+
+#include "libradius.h"
+
+static VALUE_PAIR      *prevRadPair = NULL;
+
+#define PRINTF( x ) if (librad_debug) librad_log x
+
+#define NO_TOKEN -1
+
+/*
+ * Two types of filters are supported, GENERIC and IP.  The identifiers
+ * are:
+ */
+
+#define RAD_FILTER_GENERIC     0
+#define RAD_FILTER_IP          1
+#define RAD_FILTER_IPX         2
+
+/*
+ * Generic filters mask and match up to RAD_MAX_FILTER_LEN bytes
+ * starting at some offset.  The length is:
+ */
+#define RAD_MAX_FILTER_LEN     6
+
+/*
+ * RadFilterComparison:
+ *
+ * An enumerated values for the IP filter port comparisons.
+ */
+typedef enum {
+       RAD_NO_COMPARE,
+       RAD_COMPARE_LESS,
+       RAD_COMPARE_EQUAL,
+       RAD_COMPARE_GREATER,
+       RAD_COMPARE_NOT_EQUAL
+} RadFilterComparison;
+
+    /*
+     * RadIpFilter:
+     *
+     * The binary format of an IP filter.  ALL fields are stored in
+     * network byte order.
+     *
+     * srcip:          The source IP address.
+     *
+     * dstip:          The destination IP address.
+     *
+     * srcmask:        The number of leading one bits in the source address
+     *                 mask.  Specifies the bits of interest.
+     *
+     * dstmask:        The number of leading one bits in the destination
+     *                 address mask. Specifies the bits of interest.
+     *
+     * proto:          The IP protocol number
+     *
+     * establised:     A boolean value.  TRUE when we care about the
+     *                 established state of a TCP connection.  FALSE when
+     *                 we dont care.
+     *
+     * srcport:        TCP or UDP source port number.
+     *
+     * dstport:        TCP or UDP destination port number.
+     *
+     * srcPortCmp:     One of the values of the RadFilterComparison enumeration
+     *                 specifying how to compare the srcport value.
+     *
+     * dstPortCmp:     One of the values of the RadFilterComparison enumeration
+     *                 specifying how to compare the dstport value.
+     *
+     * fill:           Round things out to a dword boundary.
+     */
+typedef struct radip {
+    UINT4              srcip;
+    UINT4              dstip;
+    unsigned char      srcmask;
+    unsigned char      dstmask;
+    unsigned char      proto;
+    unsigned char      established;
+    unsigned short     srcport;
+    unsigned short     dstport;
+    unsigned char      srcPortComp;
+    unsigned char      dstPortComp;
+    unsigned char       fill[4];        /* used to be fill[2] */
+} RadIpFilter;
+
+    /*
+     * RadIpxFilter:
+     * The binary format of a GENERIC filter.  ALL fields are stored in
+     * network byte order.
+     *
+     *  srcIpxNet:      Source IPX Net address
+     *
+     *  srcIpxNode:     Source IPX Node address
+     *
+     *  srcIpxSoc:      Source IPX socket address
+     *
+     *  dstIpxNet:      Destination IPX Net address
+     *
+     *  dstIpxNode:     Destination IPX Node address
+     *
+     *  dstIpxSoc:      Destination IPX socket address
+     *
+     *  srcSocComp:     Source socket compare value
+     *
+     *  dstSocComp:     Destination socket compare value
+     *
+     */
+typedef struct radipx {                         
+    IpxNet              srcIpxNet;                      /* LongWord */
+    IpxNode             srcIpxNode;                     /* Byte[6] */
+    IpxSocket           srcIpxSoc;                      /* Word */
+    IpxNet              dstIpxNet;                      /* LongWord */
+    IpxNode             dstIpxNode;                     /* Byte[6] */
+    IpxSocket           dstIpxSoc;                      /* Word */
+    unsigned char       srcSocComp;
+    unsigned char       dstSocComp;
+} RadIpxFilter;
+
+    /*
+     * RadGenericFilter:
+     *
+     * The binary format of a GENERIC filter.  ALL fields are stored in
+     * network byte order.
+     *
+     * offset:         Number of bytes into packet to start comparison.
+     *
+     * len:            Number of bytes to mask and compare.  May not
+     *                 exceed RAD_MAX_FILTER_LEN.
+     *
+     * more:           Boolean.  If non-zero the next filter entry is
+     *                 also to be applied to a packet.
+     *
+     * mask:           A bit mask specifying the bits to compare.
+     *
+     * value:          A value to compare against the masked bits at
+     *                 offset in a users packet.
+     *                 
+     * compNeq:        Defines type of comarison (Equal or Notequal)
+     *                 default is Equal.
+     *
+     * fill:           Round things out to a dword boundary
+     */
+typedef struct radgeneric {
+    unsigned short     offset;
+    unsigned short     len;
+    unsigned short     more;
+    unsigned char      mask[ RAD_MAX_FILTER_LEN ];
+    unsigned char      value[ RAD_MAX_FILTER_LEN ];
+    unsigned char      compNeq;
+    unsigned char       fill[3];        /* used to be fill */
+} RadGenericFilter;
+
+    /*
+     * RadFilter:
+     *
+     * A binary filter element.  Contains either a RadIpFilter or a
+     * RadGenericFilter.  All fields are stored in network byte order.
+     *
+     * type:           Either RAD_FILTER_GENERIC or RAD_FILTER_IP.
+     *
+     * forward:        TRUE if we should forward packets that match this
+     *                 filter, FALSE if we should drop packets that match
+     *                 this filter.
+     *
+     * indirection:    TRUE if this is an input filter, FALSE if this is
+     *                 an output filter.
+     *
+     * fill:           Round things out to a dword boundary.
+     *
+     * u:              A union of
+     *                 ip:             An ip filter entry
+     *                 generic:        A generic filter entry
+     */
+typedef struct filter {
+    unsigned char      type;
+    unsigned char      forward;
+    unsigned char      indirection;
+    unsigned char      fill;
+    union {
+       RadIpFilter      ip;
+       RadIpxFilter     ipx;
+       RadGenericFilter generic;
+    } u;
+} RadFilter;
+#define SIZEOF_RADFILTER 26
+
+typedef struct {
+    const char*        name;
+    int        value;
+} KeywordStruct;
+
+    /*
+     * FilterPortType:
+     *
+     * Ascii names of some well known tcp/udp services.
+     * Used for filtering on a port type.
+     *
+     */
+
+static KeywordStruct _filterPortType[] = {
+    { "ftp-data", 20 },
+    { "ftp", 21 },
+    { "telnet", 23 },
+    { "smtp", 25 },
+    { "nameserver", 42 },
+    { "domain", 53 },
+    { "tftp", 69 },
+    { "gopher", 70 },
+    { "finger", 79 },
+    { "www", 80 },
+    { "kerberos", 88 },
+    { "hostname", 101 },
+    { "nntp", 119 },
+    { "ntp", 123 },
+    { "exec", 512 },
+    { "login", 513 },
+    { "cmd", 514 },
+    { "talk", 517 },
+    {  NULL , NO_TOKEN },
+};
+
+typedef enum {
+    FILTER_IP_TYPE,
+    FILTER_GENERIC_TYPE,
+    FILTER_IN,
+    FILTER_OUT,
+    FILTER_FORWARD,
+    FILTER_DROP,
+    FILTER_GENERIC_OFFSET,
+    FILTER_GENERIC_MASK,
+    FILTER_GENERIC_VALUE,
+    FILTER_GENERIC_COMPNEQ,
+    FILTER_GENERIC_COMPEQ,
+    FILTER_MORE,
+    FILTER_IP_DST,
+    FILTER_IP_SRC,
+    FILTER_IP_PROTO,
+    FILTER_IP_DST_PORT,
+    FILTER_IP_SRC_PORT,
+    FILTER_EST,
+    FILTER_IPX_TYPE,
+    FILTER_IPX_DST_IPXNET,
+    FILTER_IPX_DST_IPXNODE,
+    FILTER_IPX_DST_IPXSOCK,
+    FILTER_IPX_SRC_IPXNET,
+    FILTER_IPX_SRC_IPXNODE,
+    FILTER_IPX_SRC_IPXSOCK
+} FilterTokens;
+
+
+static KeywordStruct _filterKeywords[] = {
+    { "ip",    FILTER_IP_TYPE },
+    { "generic",FILTER_GENERIC_TYPE },
+    { "in",    FILTER_IN },
+    { "out",   FILTER_OUT },
+    { "forward",FILTER_FORWARD },
+    { "drop",  FILTER_DROP },
+    { "dstip",  FILTER_IP_DST },
+    { "srcip",  FILTER_IP_SRC },
+    { "dstport",FILTER_IP_DST_PORT },
+    { "srcport",FILTER_IP_SRC_PORT },
+    { "est",   FILTER_EST },
+    { "more",  FILTER_MORE },
+    { "!=",    FILTER_GENERIC_COMPNEQ },
+    { "==",    FILTER_GENERIC_COMPEQ  },
+    { "ipx",   FILTER_IPX_TYPE  },
+    { "dstipxnet",     FILTER_IPX_DST_IPXNET  },
+    { "dstipxnode",    FILTER_IPX_DST_IPXNODE  },
+    { "dstipxsock",    FILTER_IPX_DST_IPXSOCK  },
+    { "srcipxnet",     FILTER_IPX_SRC_IPXNET  },
+    { "srcipxnode",    FILTER_IPX_SRC_IPXNODE  },
+    { "srcipxsock",    FILTER_IPX_SRC_IPXSOCK  },
+    {  NULL , NO_TOKEN },
+};
+
+#define FILTER_DIRECTION       0
+#define FILTER_DISPOSITION     1
+#define IP_FILTER_COMPLETE     0x3     /* bits shifted by FILTER_DIRECTION */
+                                       /* FILTER_DISPOSITION */
+
+#define IPX_FILTER_COMPLETE      0x3     /* bits shifted by FILTER_DIRECTION */
+                                        /* FILTER_DISPOSITION */
+
+#define GENERIC_FILTER_COMPLETE 0x1c3  /* bits shifted for FILTER_DIRECTION */
+                                       /* FILTER_DISPOSITION, FILTER_GENERIC_OFFSET*/
+                                       /* FILTER_GENERIC_MASK, FILTER_GENERIC_VALUE*/
+
+    /*
+     * FilterProtoName:
+     *
+     * Ascii name of protocols used for filtering.
+     *
+     */
+static KeywordStruct _filterProtoName[] = {
+    { "tcp",  6 },
+    { "udp",  17 },
+    { "ospf", 89 },
+    { "icmp", 1 },
+    {  NULL , NO_TOKEN },
+};
+
+static KeywordStruct _filterCompare[] = {
+    { ">", RAD_COMPARE_GREATER },
+    { "=", RAD_COMPARE_EQUAL },
+    { "<", RAD_COMPARE_LESS },
+    { "!=", RAD_COMPARE_NOT_EQUAL },
+    {  NULL , NO_TOKEN },
+};
+
+static char    curString[512];
+
+int findKey ( char *string, KeywordStruct *list );
+static int isAllDigit ( char *token );
+static short a2octet ( char *tok, char *retBuf );
+static char defaultNetmask ( unsigned long address );
+static int ipAddressStringToValue ( char *string, unsigned long *ipAddress,
+                                        char *netmask);
+static int parseIpFilter ( RadFilter *curEntry );
+static int parseGenericFilter ( RadFilter *curEntry );
+static int parseIpxFilter ( RadFilter *curEntry );
+static int stringToNode   ( unsigned char* dest,  unsigned char* src );
+
+    /*
+     * findKey:
+     *
+     * Given a table of keywords, it will try and match string to an
+     * entry. If it does it returns that keyword value. if no NO_TOKEN is
+     * returned. A sanity check is made for upper case characters.
+     *
+     * string:                 Pointer to the token to match.
+     *
+     * list:                   Point to the list of keywords.
+     *
+     * returns:                Keyword value on a match or NO_TOKEN.
+     */
+int findKey(char *string, KeywordStruct *list)
+{
+    short      len;
+    KeywordStruct*  entry;
+    char       buf[80], *ptr;
+
+    len = strlen( (char *) string );
+    for( ptr = buf ; len; len--, string++ ) {
+       if( isupper( *string ) ) {
+           *ptr++ = tolower( *string );
+       } else {
+           *ptr++ = *string;
+       }
+    }
+    *ptr = 0;
+    entry = list;
+    while( entry->name ) {
+       if( strcmp( entry->name, buf ) == 0 ) {
+           break;
+       }
+       entry++;
+    }
+    return( entry->value );
+}
+
+    /*
+     * isAllDigit:
+     *
+     * Routine checks a string to make sure all values are digits.
+     *
+     * token:                  Pointer to sting to check.
+     *
+     *         returns:                TRUE if all digits, or FALSE.
+     *
+     */
+
+static int
+isAllDigit(token)
+char   *token;
+{
+    int i;
+
+    i = strlen( (char *) token );
+    while( i-- ) {
+       if( isdigit( *token ) ) {
+           token++;
+       } else {
+           break;
+       }
+    }
+    if( i > 0 ) {
+       return( FALSE );
+    } 
+
+    return( TRUE );
+}
+
+    /*
+     * a2octet:
+     *
+     * Converts the ascii mask and value for generic filters into octets.
+     * It also does a sanity check to see if the string is greater than
+     * MAX_FILTER_LEN. It assumes the sting is hex with NO leading "0x"
+     *
+     * tok:                    Pointer to the string.
+     *
+     *  retBuf:                        Pointer to place the octets.
+     *
+     * returns:                Number of octects or -1 for error.
+     * 
+     */
+static short
+a2octet(tok, retBuf)
+char   *tok;
+char   *retBuf;
+{
+    short      rc, len, val, retLen, i;
+    char       buf[ RAD_MAX_FILTER_LEN *2 ];
+    char       *octet = buf;
+
+    rc = -1;
+    retLen = 0;
+
+    if( ( len = strlen( (char*) tok ) ) <= ( RAD_MAX_FILTER_LEN*2 ) ) {
+       retLen = len/2;
+       if( len % 2 ) {
+           retLen++;
+       }
+       memset( buf, '\0', RAD_MAX_FILTER_LEN * 2 );
+       for( ; len; len-- ) {
+           if( *tok <= '9' && *tok >= '0' ) {
+               val = '0';
+               *octet++ = *tok++ - val;
+           } else if( isxdigit( *tok ) ) {
+               if( *tok > 'Z' ) {
+                   val = 'a';
+               } else {
+                   val = 'A';
+               }
+               *octet++ = ( *tok++ - val ) + 10;
+           } else {
+               break;  
+           }
+       }
+       if( !len ) {
+           /* merge the values */
+           for( i = 0; i < RAD_MAX_FILTER_LEN*2; i+=2 ) {
+               *retBuf++ = (buf[i] << 4) | buf[i+1];
+           }
+       }
+    }
+
+    if( len ) {
+       rc = -1;
+    } else {
+       rc = retLen;
+    }
+    return( rc );
+}
+
+
+
+    /*
+     * defaultNetmask:
+     *
+     * Given an ip address this routine calculate a default netmask.
+     *
+     * address:                Ip address.
+     *
+     * returns:                Number of bits for the netmask
+     *
+     */
+static char
+defaultNetmask(address)
+unsigned long  address;
+{
+    char netmask;
+
+    if ( ! address ) {
+       netmask = 0;
+    } else if (( address & htonl( 0x80000000 ) ) == 0 ) {
+       netmask = 8;
+    } else if (( address & htonl( 0xc0000000 ) ) == htonl( 0x80000000 ) ) {
+       netmask = 16;
+    } else if (( address & htonl( 0xe0000000 ) ) == htonl( 0xc0000000 ) ) {
+       netmask = 24;
+    } else {
+       netmask = 32;
+    }
+    return netmask;
+}
+
+               
+static char ipAddressDigits[] = "1234567890./";
+    /*
+     * This functions attempts to convert an IP address in ASCII dot
+     * with an optional netmask part to a pair of IpAddress.  Note:
+     * An IpAddress is always stored in network byte order.
+     *
+     * Parameters:
+     *
+     *  string:                Pointer to a NULL terminated IP address in dot 
+     *                 notation followed by an optional /nn to indicate
+     *                 the number leading of bits in the netmask.
+     * 
+     *  ipAddress:     Pointer to an IpAddress where the converted
+     *                 address will be stored.
+     *
+     * netmask:        Pointer to an IpAddress where the netmask
+     *                 will be stored.  If no netmask is passed as
+     *                 as part of the address the default netmask will
+     *                 be stored here.
+     *
+     * Returns:
+     * <>              TRUE if valid conversion, FALSE otherwise.
+     *
+     * *ipAddress:     If function returns TRUE, the IP address in NBO.
+     * *netmask:       If function returns TRUE, the netmask in NBO.
+     */
+
+static int
+ipAddressStringToValue(char *string, unsigned long *ipAddress,
+       char *netmask)
+{
+    u_char*    dst;
+    char*      cp;
+    int                numDots;
+    int                i;
+    long       value;
+
+    if ( ! string ) {
+       return(FALSE);
+    }
+
+    /* Allow an IP address to be blanked instead of forcing entry of
+       0.0.0.0 -- the user will like it. */
+
+    if ( *string == 0 ) {
+       *ipAddress = 0;
+       *netmask = 0;
+       return TRUE;
+    }
+
+    /* First just count the number of dots in the address.  If there
+       are more or less than three the address is invalid. */
+
+    cp = string;
+    numDots = 0;
+    while( *cp ) {
+       if( !strchr( ipAddressDigits, *cp) ) {
+           return( FALSE );
+       }
+       if ( *cp == '.') {
+           ++numDots;
+       }
+       ++cp;
+    }
+    if ( numDots != 3 ) {
+       return( FALSE );
+    }
+
+    dst = (u_char *) ipAddress;
+    cp = string;
+
+    for ( i = 0; i < sizeof( *ipAddress ); i++ ) {
+       value = strtol( cp, (char**) &cp, 10 );
+       if (( value < 0 ) || ( value > 255 )) {
+           return( FALSE );
+       }
+       *dst++ = (u_char) value;
+       if ( *cp == '.' ) {
+           cp += 1;
+       }
+    }
+
+    /* If there is a netmask part, parse it, otherwise figure out the
+       default netmask for this class of address. */
+
+    if ( *cp == '/' ) {
+       value = strtol( cp + 1, (char**) &cp, 10 );
+       if (( *cp != 0 ) || ( value < 0 ) || ( value > 32 )) {
+           return FALSE;
+       }
+       *netmask = (char) value;
+    } else {
+       *netmask = defaultNetmask( *ipAddress );
+    }
+    return TRUE;
+}
+
+    /*
+     * Convert a 12 digit string representation of a hex data field to a
+     * value.
+     */
+static int
+stringToNode(dest, src )
+unsigned char*         dest;
+unsigned char*  src;
+{
+    int         srcIx = 0;
+    int         ix;
+    int         nibble1;
+    int         nibble2;
+    int                temp;
+    unsigned char *src1;
+
+    src1 = (unsigned char *) strchr(src, 'x');
+
+    if (src1 == NULL)
+       src1 = (unsigned char *) strchr(src,'X');
+
+    if (src1 == NULL)
+       src1 = src;
+    else
+       src1++;
+
+    /* skip any leading 0x or 0X 's */
+    temp = strlen( (char*) src1 );
+    if( strlen( (unsigned char*) src1 ) != ( IPX_NODE_ADDR_LEN * 2 ) ) {
+        return( FALSE );
+    }
+
+    for ( ix = 0; ix < IPX_NODE_ADDR_LEN; ++ix ) {
+        if ( src1[ srcIx ] <= '9' ) {
+            nibble1 = src1[ srcIx ] & 0x0f;
+        } else {
+            nibble1 = (src1[ srcIx ] & 0x0f) + 9;
+        }
+        srcIx += 1;
+        if ( src1[ srcIx ] <= '9' ) {
+            nibble2 = src1[ srcIx ] & 0x0f;
+        } else {
+            nibble2 = (src1[ srcIx ] & 0x0f) + 9;
+        }
+        srcIx += 1;
+        ((unsigned char *) dest)[ ix ] = (unsigned char) (nibble1 << 4) + nibble2;
+    }
+
+    return( TRUE );
+}
+
+
+    /*
+     * parseIpxFilter:
+     *
+     * This routine parses an IPX filter string from a RADIUS
+     * reply. The format of the string is:
+     *
+     * ipx dir action [ srcipxnet nnnn srcipxnode mmmmm [srcipxsoc cmd value ]]
+     *                        [ dstipxnet nnnn dstipxnode mmmmm [dstipxsoc cmd value ]]
+     *
+     * Fields in [...] are optional.
+     * where:
+     *
+     *  ipx:           Keyword to designate an IPX filter. Actually this
+     *                 has been determined by parseFilter.
+     *
+     * dir:            Filter direction. "IN" or "OUT"
+     *
+     * action:         Filter action. "FORWARD" or "DROP"
+     *
+     *  srcipxnet:      Keyword for source IPX address.
+     *                  nnnn = IPX Node address.
+     *
+     *  srcipxnode:     Keyword for source IPX Node address.
+     *                  mmmmm = IPX Node Address, could be FFFFFF.
+     *                  A vlid ipx node number should accompany ipx net number.
+     *
+     *  srcipxsoc:      Keyword for source IPX socket address.
+     *
+     *  cmd:            One of ">" or "<" or "=" or "!=".
+     *
+     *  value:          Socket value to be compared against, in hex. 
+     *                 
+     * dstipxnet:      Keyword for destination IPX address.
+     *                 nnnn = IPX Node address. 
+     *                 
+     * dstipxnode:     Keyword for destination IPX Node address.
+     *                 mmmmm = IPX Node Address, could be FFFFFF.
+     *                 A vlid ipx node number should accompany ipx net number.
+     *                 
+     * dstipxsoc:      Keyword for destination IPX socket address.
+     *                 
+     * cmd:            One of ">" or "<" or "=" or "!=".
+     *                 
+     * value:          Socket value to be compared against, in hex.            
+     *                 
+     *                 
+     * expects:
+     *
+     * curEntry:       Pointer to place the filter structure
+     *
+     * returns:        -1 for error or 0 for OK
+     * 
+     */
+
+static int 
+parseIpxFilter(curEntry)
+RadFilter      *curEntry;
+{
+    unsigned long      elements = 0l;
+    int                        tok; 
+    char*              token;
+    RadIpxFilter*      ipx;
+
+    token = (char *) strtok( NULL, " " ); 
+
+    memset( curEntry, '\0', sizeof( RadFilter ) );
+    curEntry->type = RAD_FILTER_IPX; 
+    ipx = &curEntry->u.ipx;
+    while( token ) {
+       tok = findKey( token, _filterKeywords );
+       switch( tok ) {
+           case FILTER_IN:
+           case FILTER_OUT:
+               curEntry->indirection = tok == FILTER_IN ? TRUE: FALSE;
+               PRINTF((" got FILTER %s ", tok == FILTER_IN?"IN":"OUT"));
+               elements |= (1 << FILTER_DIRECTION );
+               break;
+
+           case FILTER_FORWARD:
+           case FILTER_DROP:
+               PRINTF((" got FILTER %s ",
+                       tok == FILTER_DROP? "DROP":"FORWARD"));
+
+               elements |= (1 << FILTER_DISPOSITION );
+               if( tok == FILTER_FORWARD ) {
+                   curEntry->forward = TRUE;
+               } else {
+                   curEntry->forward = FALSE;
+               }
+               break;
+
+           case FILTER_IPX_DST_IPXNET:
+           case FILTER_IPX_SRC_IPXNET:
+                PRINTF((" got FILTER_IPX %s IPXNET ",
+                        tok == FILTER_IPX_DST_IPXNET ? "DST":"SRC"));
+               token = (char *) strtok( NULL, " " );
+
+               if ( token ) {
+                   if( tok == FILTER_IPX_DST_IPXNET ) {
+                       ipx->dstIpxNet = ntohl( strtol( token, 0, 16 ));
+                       PRINTF(("D.Net: %08lX  token: %s \n", htonl(ipx->dstIpxNet), token));
+                   } else {
+                       ipx->srcIpxNet = ntohl( strtol( token, 0, 16 ));
+                       PRINTF(("S Net: %08lX token: %s \n", htonl(ipx->srcIpxNet), token));
+                   }
+                   break;
+               } 
+               goto doneErr; 
+
+            case FILTER_IPX_DST_IPXNODE:
+            case FILTER_IPX_SRC_IPXNODE:
+                PRINTF((" got FILTER_IPX %s IPXNODE ",
+                       tok == FILTER_IPX_DST_IPXNODE ? "DST":"SRC"));
+               token = (char *) strtok( NULL, " " );
+
+               if ( token ) {
+                   if ( tok == FILTER_IPX_DST_IPXNODE) {
+                       stringToNode( (unsigned char *)ipx->dstIpxNode, (unsigned char*)token );
+                       PRINTF(("D. Node: %08lX%04X \n", 
+                               htonl((*(int *)(ipx->dstIpxNode))),
+                               htons((*(short *)(ipx->dstIpxNode+4)))));
+                   } else {
+                       stringToNode( (unsigned char *)ipx->srcIpxNode, (unsigned char*)token );
+                       PRINTF(("S. Node: %08lX%04X \n", 
+                               htonl((*(int *)(ipx->srcIpxNode))),
+                               htons((*(short *)(ipx->srcIpxNode+4)))));
+                   }
+                   break;
+               }
+                goto doneErr;
+
+            case FILTER_IPX_DST_IPXSOCK:
+            case FILTER_IPX_SRC_IPXSOCK:
+           {
+               RadFilterComparison cmp;
+
+                PRINTF((" got FILTER_IPX %s IPXSOCK",
+                       tok == FILTER_IPX_DST_IPXSOCK ? "DST":"SRC"));
+                token = (char *) strtok( NULL, " " );
+
+               if ( token ) {
+                   cmp = findKey( token, _filterCompare );
+                   PRINTF((" cmp value = %d \n", cmp ));
+                   if( cmp != NO_TOKEN ) {
+                   token = (char *) strtok( NULL, " " );
+                       if ( token ) {
+                           if ( tok == FILTER_IPX_DST_IPXSOCK ) {
+                               ipx->dstSocComp = cmp;
+                               ipx->dstIpxSoc = 
+                           ntohs( (IpxSocket) strtol( token, NULL, 16 ));
+                               PRINTF(("%X \n", htons(ipx->dstIpxSoc)));
+                           } else {
+                               ipx->srcSocComp = cmp;
+                               ipx->srcIpxSoc 
+                                   = ntohs( (IpxSocket) strtol( token, NULL, 16 ));
+                               PRINTF(("%X \n", htons(ipx->srcIpxSoc)));
+                           }
+                           break;
+                       }
+                   }
+               }
+               goto doneErr;
+            }
+
+           default:
+               /* no keyword match */
+               goto doneErr;
+       }
+        token = (char *) strtok( NULL, " " ); 
+    } 
+
+    if( elements == IPX_FILTER_COMPLETE ) {
+       return( 0 );
+    }
+
+doneErr:
+    PRINTF(( "RADIF: IPX Filter syntax error %s \n", token ));
+    librad_log("ipx filter error: do not recognize %s in %s \n",
+             token, curString );
+    return( -1 );
+}
+
+    /*
+     * parseIpFilter:
+     *
+     * This routine parses an IP filter string from a RADIUS
+     * reply. The format of the string is:
+     *
+     * ip dir action [ dstip n.n.n.n/nn ] [ srcip n.n.n.n/nn ]
+     *     [ proto [ dstport cmp value ] [ srcport cmd value ] [ est ] ] 
+     *
+     * Fields in [...] are optional.
+     * where:
+     *
+     *  ip:            Keyword to designate an IP filter. Actually this
+     *                 has been determined by parseFilter.
+     *
+     * dir:            Filter direction. "IN" or "OUT"
+     *
+     * action:         Filter action. "FORWARD" or "DROP"
+     *
+     * dstip:          Keyword for destination IP address.
+     *                 n.n.n.n = IP address. /nn - netmask. 
+     *                 
+     * srcip:          Keyword for source IP address.
+     *                 n.n.n.n = IP address. /nn - netmask. 
+     *                 
+     * proto:          Optional protocol field. Either a name or
+     *                 number. Known names are in FilterProtoName[].
+     *                 
+     * dstpost:        Keyword for destination port. Only valid with tcp
+     *                 or udp. 'cmp' are in FilterPortType[]. 'value' can be
+     *                 a name or number.
+     *
+     * srcpost:        Keyword for source port. Only valid with tcp
+     *                 or udp. 'cmp' are in FilterPortType[]. 'value' can be
+     *                 a name or number.
+     *                 
+     * est:            Keyword for TCP established. Valid only for tcp.
+     *                 
+     * expects:
+     *
+     * curEntry:       Pointer to place the filter structure
+     *
+     * returns:        -1 for error or 0 for OK
+     * 
+     */
+
+static int 
+parseIpFilter(curEntry)
+RadFilter      *curEntry;
+{
+    unsigned long      elements = 0l;
+    int                        tok; 
+    char*              token;
+    RadIpFilter*       ip;
+
+    token = (char *) strtok( NULL, " " ); 
+
+    PRINTF((" in ip  filter \n")); 
+
+    memset( curEntry, '\0', sizeof( RadFilter ) );
+    curEntry->type = RAD_FILTER_IP; 
+    ip = &curEntry->u.ip;
+    ip->established = FALSE;
+    while( token ) {
+       PRINTF((" token %s ", token ));
+       tok = findKey( token, _filterKeywords );
+       switch( tok ) {
+           case FILTER_IN:
+           case FILTER_OUT:
+               curEntry->indirection = tok == FILTER_IN ? TRUE: FALSE;
+               PRINTF((" got %s ", tok == FILTER_IN?"FILTER_IN":"FILTER_OUT"));
+               elements |= (1 << FILTER_DIRECTION );
+               break;
+           case FILTER_FORWARD:
+           case FILTER_DROP:
+               PRINTF((" got %s ", tok == FILTER_DROP?
+                       "FILTER_DROP":"FILTER_FORWARD"));
+               elements |= (1 << FILTER_DISPOSITION );
+               if( tok == FILTER_FORWARD ) {
+                   curEntry->forward = TRUE;
+               } else {
+                   curEntry->forward = FALSE;
+               }
+               break;
+           case FILTER_IP_DST:
+           case FILTER_IP_SRC:
+               PRINTF((" got %s ", tok == FILTER_IP_DST?
+                       "FILTER_IP_DST":"FILTER_IP_SRC"));
+               token = (char *) strtok( NULL, " " );
+               if ( token ) {
+                   if( tok == FILTER_IP_DST ) {
+                       
+                       if( ipAddressStringToValue( (char*)token, 
+                                &ip->dstip, (char *)&ip->dstmask ) ) {
+                           PRINTF((" ip %lx netmask %lx \n", ip->dstip, 
+                                    ip->dstmask ));
+                           break;
+                       }
+                   } else {
+                       if( ipAddressStringToValue( (char *)token, 
+                               &ip->srcip, (char *)&ip->srcmask ) ) {
+                           PRINTF((" ip %lx netmask %lx \n", ip->srcip,
+                                    ip->srcmask ));
+                           break;
+                       }
+                   }
+               } 
+
+               PRINTF(( "RADIF: IP Filter syntax error %s \n", token ));
+               librad_log("ip filter error: do not recognize %s in %s \n",
+                         token, curString );
+               goto doneErr ;
+
+           case FILTER_IP_DST_PORT:
+           case FILTER_IP_SRC_PORT:
+           {
+               RadFilterComparison cmp;
+               short            port;
+
+               PRINTF((" got %s ", tok == FILTER_IP_DST_PORT?
+                       "FILTER_IP_DST_PORT":"FILTER_IP_SRC_PORT"));
+               token = (char *) strtok( NULL, " " );
+               if ( token ) {
+                   cmp = findKey( token, _filterCompare );
+                   PRINTF((" cmp value = %d \n", cmp ));
+                   if( cmp != NO_TOKEN ) {
+                       token = (char *) strtok( NULL, " " );
+                       if ( token ) {
+                           if( isAllDigit( token ) ) {
+                               port = atoi( (char *) token );
+                           } else {
+                               port = findKey( token, _filterPortType );
+                           }
+                           if( port != (short) NO_TOKEN ) {
+                               PRINTF((" port = %d \n", port ));
+                               if( tok == FILTER_IP_DST_PORT ) {
+                                   ip->dstPortComp = cmp;
+                                   ip->dstport = htons( port );
+                               } else {
+                                   ip->srcPortComp = cmp;
+                                   ip->srcport = htons( port );
+                               }
+                               break;
+                           }
+                       }
+                   }
+               }
+               librad_log( "ip filter error: do not recognize %s in %s \n",
+                         token, curString );
+               PRINTF(( "RADIF: IP Filter syntax error %s \n", token ));
+               goto doneErr;
+               break;
+           }
+           case FILTER_EST:
+               PRINTF((" got est %s ", token ));
+               ip->established = TRUE;
+               break;
+           default:
+               /* no keyword match but may match a protocol list */
+               if( isAllDigit( token ) ) {
+                   tok = atoi( (char *) token );
+               } else {
+                   tok = findKey( token, _filterProtoName );
+
+                   if( tok == NO_TOKEN ) {
+                       PRINTF(( "RADIF: IP proto error %s \n", token ));
+                       librad_log("ip filter error: do not recognize %s in %s \n",
+                            token, curString );
+                       goto doneErr;
+                   }
+               }
+               ip->proto = tok;
+               PRINTF(("ip proto cmd = %d ", tok));
+       }
+        token = (char *) strtok( NULL, " " ); 
+    } 
+
+    if( elements == IP_FILTER_COMPLETE ) {
+       return( 0 );
+    }
+
+doneErr:
+    PRINTF((" done err \n"));
+    return( -1 );
+}
+
+    /*
+     * parseGenericFilter:
+     *
+     * This routine parses a Generic filter string from a RADIUS
+     * reply. The format of the string is:
+     *
+     * GENERIC dir action offset mask value [== or != ] [more]
+     *
+     * Fields in [...] are optional.
+     * where:
+     *
+     *         generic:        Keyword to indicate a generic filter. This
+     *                 has been determined by parseFilter.
+     *
+     * dir:            Filter direction. "IN" or "OUT"
+     *
+     * action:         Filter action. "FORWARD" or "DROP"
+     *
+     * offset:         A Number. Specifies an offset into a frame 
+     *                 to start comparing.
+     *                 
+     * mask:           A hexadecimal mask of bits to compare.
+     *                 
+     * value:          A value to compare with the masked data.
+     *
+     * compNeq:        Defines type of comparison. ( "==" or "!=")
+     *                 Default is "==".
+     *                 
+     * more:           Optional keyword MORE, to represent the attachment
+     *                 to the next entry.
+     *
+     * expects:
+     *
+     * curEntry:       Pointer to place the filter structure
+     *
+     * returns:        -1 for error or 0 for OK
+     * 
+     */
+
+static int
+parseGenericFilter(curEntry)
+RadFilter      *curEntry;
+{
+    unsigned long      elements = 0l; 
+    int                        tok; 
+    int                        gstate = FILTER_GENERIC_OFFSET;
+    char*              token;
+    short              valLen, maskLen;
+    RadGenericFilter*  gen;
+
+    token = (char *) strtok( NULL, " " ); 
+
+    PRINTF((" in parse generic filter \n")); 
+
+    maskLen = 0;
+    memset( (char *)curEntry, '\0', sizeof( RadFilter ) );
+    curEntry->type = RAD_FILTER_GENERIC;
+    gen = &curEntry->u.generic;
+    gen->more = FALSE; 
+    gen->compNeq = FALSE;      
+
+    while( token ) {
+       PRINTF((" token %s ", token ));
+       tok = findKey( token, _filterKeywords );
+       PRINTF(("tok %d ", tok));
+       switch( tok ) {
+           case FILTER_IN:
+           case FILTER_OUT:
+               curEntry->indirection = tok == FILTER_IN ? TRUE: FALSE;
+               elements |= (1 << FILTER_DIRECTION );
+               PRINTF((" got %s ", tok == FILTER_IN?"FILTER_IN":"FILTER_OUT"));
+               break;
+           case FILTER_FORWARD:
+           case FILTER_DROP:
+               elements |= (1 << FILTER_DISPOSITION );
+               PRINTF((" got %s ", tok == FILTER_DROP?
+                       "FILTER_DROP":"FILTER_FORWARD"));
+               if( tok == FILTER_FORWARD ) {
+                   curEntry->forward = TRUE;
+               } else {
+                   curEntry->forward = FALSE;
+               }
+               break;
+           case FILTER_GENERIC_COMPNEQ:
+               gen->compNeq = TRUE;
+               PRINTF((" got compare %s ", token));
+               break;
+           case FILTER_GENERIC_COMPEQ:
+               gen->compNeq = FALSE;
+               PRINTF((" got compare %s ", token));
+               break;
+           case FILTER_MORE:
+               gen->more = htons( TRUE );
+               PRINTF((" got more %s ", token ));
+               break;
+           default:
+               elements |= ( 1 << gstate );
+               switch( gstate ) {
+                   case FILTER_GENERIC_OFFSET:
+                       gstate = FILTER_GENERIC_MASK;
+                       gen->offset = htons( atoi( (char *) token ) );
+                       break;
+                   case FILTER_GENERIC_MASK:
+                       gstate = FILTER_GENERIC_VALUE;
+                       maskLen = a2octet( token, (char *)gen->mask );
+                       if( maskLen == (short) -1 ) {
+                           librad_log("filter mask error: %s \n", curString );
+                           goto doneErr;
+                       }
+                       PRINTF((" octet retlen = %d ", maskLen ));
+                       for( tok = 0; tok < maskLen; tok++) {
+                           PRINTF(("%2x", gen->mask[tok]));
+                       }
+                       PRINTF(("\n"));
+                       break;
+                   case FILTER_GENERIC_VALUE:
+                       gstate ++;
+                       valLen = a2octet( token, (char *)gen->value );
+                       if( valLen != maskLen ) {
+                           librad_log("filter value size is not the same size as the filter mask: %s \n", 
+                                    curString );
+                           goto doneErr;
+                       }
+                       gen->len = htons( valLen );
+                       PRINTF((" octet retlen = %d ", maskLen ));
+                       for( tok = 0; tok < maskLen; tok++) {
+                           PRINTF(("%2x", gen->value[tok]));
+                       }
+                       PRINTF(("\n"));
+                       break;
+                   default:
+                       librad_log("filter: do not know %s in %s \n",
+                                token, curString );
+                       PRINTF(( "RADIF: Filter syntax error %s \n", token ));
+                       goto doneErr;    
+               }
+       }
+        token = (char *) strtok( NULL, " " ); 
+    }
+
+    if( elements == GENERIC_FILTER_COMPLETE ) {
+       return( 0 );
+    }
+
+doneErr:
+    PRINTF((" done err \n"));
+    return( -1 );
+}
+                      
+    /*
+     * filterBinary:
+     *
+     * This routine will call routines to parse entries from an ASCII format
+     * to a binary format recognized by the Ascend boxes.
+     *
+     * pair:                   Pointer to value_pair to place return.
+     *
+     * valstr:                 The string to parse     
+     *
+     * return:                 -1 for error or 0.
+     */
+int 
+filterBinary(VALUE_PAIR *pair, char *valstr)
+{
+
+    char*              token;
+    unsigned long      tok;
+    int                        rc;
+    RadFilter          radFil, *filt;
+    RadGenericFilter*  gen;
+
+    rc = -1;
+    strcpy( curString, valstr );
+
+    token = (char *) strtok( (char *)valstr, " " );
+    tok = findKey( token, _filterKeywords );
+    pair->length = SIZEOF_RADFILTER;
+    switch( tok ) {
+      case FILTER_IP_TYPE:
+       rc = parseIpFilter( &radFil );
+       break;
+      case FILTER_GENERIC_TYPE:
+       rc = parseGenericFilter( &radFil );
+       break;
+      case  FILTER_IPX_TYPE:
+       rc = parseIpxFilter( &radFil );
+        break;
+    }
+
+    /*
+     * if more is set then this new entry must exist, be a 
+     * FILTER_GENERIC_TYPE, direction and disposition must match for 
+     * the previous more to be valid. If any should fail then TURN OFF 
+     * previos more
+     */
+    if( prevRadPair ) {
+       filt = ( RadFilter * )prevRadPair->strvalue;
+       if(( tok != FILTER_GENERIC_TYPE ) || (rc == -1 ) ||
+          ( prevRadPair->attribute != pair->attribute ) || 
+          ( filt->indirection != radFil.indirection ) || 
+          ( filt->forward != radFil.forward ) ) {
+           gen = &filt->u.generic;
+           gen->more = FALSE;
+           librad_log("filterBinary:  'more' for previous entry doesn't match: %s.\n",
+                    curString );
+       }
+    }
+    prevRadPair = NULL;
+    if( rc != -1 && tok == FILTER_GENERIC_TYPE ) {
+       if( radFil.u.generic.more ) {
+           prevRadPair = pair;
+       } 
+    }
+
+    if( rc != -1 ) {
+       memcpy( pair->strvalue, (char *) &radFil, pair->length );
+    }
+    return(rc);
+}
+
+void print_abinary(VALUE_PAIR *vp, u_char *buffer, int len)
+{
+  int i;
+  char *p;
+  RadFilter    filter;
+  
+  static char *filter_type[] = {"generic", "ip", "ipx"};
+  static char *action[] = {"drop", "forward"};
+  static char *direction[] = {"output", "input"};
+  static char *compare[] = {"", "<", "=", ">", "!="};
+  
+  p = buffer;
+
+  *(p++) = '"';
+
+  /*
+   *  Just for paranoia
+   */
+  if (vp->length != SIZEOF_RADFILTER) {
+    for (i = 0; i < vp->length; i++) {
+      sprintf(p, "%02x", vp->strvalue[i]);
+      p += 2;
+    }
+    strcpy(p, "\"");
+    return;
+  }
+
+  memcpy(&filter, vp->strvalue, SIZEOF_RADFILTER);
+
+
+  if (filter.type == RAD_FILTER_IP) {
+    i = snprintf(p, len - 2, "%s %s srcip %d.%d.%d.%d/%d dstip %d.%d.%d.%d/%d %s %d dstport %s %d srcport %s %d",
+                filter_type[filter.type],
+                direction[filter.indirection & 0x01],
+
+                ((u_char *) &filter.u.ip.srcip)[0],
+                ((u_char *) &filter.u.ip.srcip)[1],
+                ((u_char *) &filter.u.ip.srcip)[2],
+                ((u_char *) &filter.u.ip.srcip)[3],
+                filter.u.ip.srcmask,
+
+                ((u_char *) &filter.u.ip.dstip)[0],
+                ((u_char *) &filter.u.ip.dstip)[1],
+                ((u_char *) &filter.u.ip.dstip)[2],
+                ((u_char *) &filter.u.ip.dstip)[3],
+                filter.u.ip.dstmask,
+
+                action[filter.forward & 0x01],
+
+                filter.u.ip.proto,
+
+                compare[filter.u.ip.dstPortComp], ntohs(filter.u.ip.dstport),
+
+                compare[filter.u.ip.srcPortComp], ntohs(filter.u.ip.srcport));
+    p += i;
+  }
+
+  *(p++) = '"';
+  *p = '\0';
+}
+
+/*
+  Test case"
+
+"ip out srcip 10.1.1.0/24 forward 6 dstport = 80 srcport < 1023"
+
+ This filter would translate to the binary format listed below.
+ The map below defines what each field stands for:
+
+ 01 01 00 00 0a010100 00000000 18 00 06 00 03FF 0050 01 02 0000
+ AA BB CC DD EEEEEEEE FFFFFFFF GG HH II JJ KKKK LLLL MM NN OOOO
+
+ AA          Filter type
+                 00 = generic
+                 01 = IP
+                 02 = IPX
+ BB          Action
+                 00 = drop (block) packet
+                 01 = forward packet
+ CC          Direction
+                 00 = output filter
+                 01 = input filter
+ DD          Blank
+ EEEEEEEE    Source IP address
+ FFFFFFFF    Destination IP address
+ GG          Source netmask in bits
+ HH          Destination netmask in bits
+ II          Protocol number
+ JJ          Blank
+ KKKK        Source port number
+ LLLL        Destination port number
+ MM          Source compare
+ NN          Destination compare
+                 00 = none
+                 01 = greater than
+                 02 = equal
+                 03 = less than
+                 04 = not equal
+ OOOO        Padding
+
+
+
+*/
index 6ddc90a..5d9b65c 100644 (file)
@@ -1,10 +1,12 @@
 /*
  * print.c     Routines to print stuff.
  *
- * Version:    @(#)print.c  1.00  26-Oct-1998  miquels@cistron.nl
+ * Version:    $Id$
  *
  */
 
+static const char rcsid[] = "$Id$";
+
 #include       "autoconf.h"
 
 #include       <stdio.h>
@@ -132,8 +134,14 @@ int vp_prints(char *out, int outlen, VALUE_PAIR *vp)
                        else
                                a = ip_ntoa(NULL, vp->lvalue);
                        break;
+#ifdef ASCEND_BINARY
+               case PW_TYPE_ABINARY:
+                 a = buf;
+                 print_abinary(vp, buf, sizeof(buf));
+                 break;
+#endif
                default:
-                       a = "UNKNOWN";
+                       a = "UNKNOWN-TYPE";
                        break;
        }
        strncpy(out, a, outlen);
index dbcdddf..28f7c53 100644 (file)
@@ -1,18 +1,18 @@
 /*
  * radius.c    Functions to send/receive radius packets.
  *
- * Version:    @(#)radius.c  2.35  19-Jul-1999  miquels@cistron.nl
+ * Version:    $Id$
  *
  */
 
-char radius_sccsid[] =
-"@(#)radius.c  2.35 Copyright 1998-1999 Cistron Internet Services B.V.";
+static const char rcsid[] = "$Id$";
 
 #include       "autoconf.h"
 
 #include       <sys/types.h>
 #include       <sys/time.h>
 #include       <netinet/in.h>
+#include       <sys/socket.h>
 #include       <arpa/inet.h>
 
 #include       <stdio.h>
@@ -31,8 +31,9 @@ char radius_sccsid[] =
 #endif
 
 /*
- *  ??? Why this number?  The RFC says 4096 octets max,
- *  and most packets are less than 256.
+ *  The RFC says 4096 octets max, and most packets are less than 256.
+ *  However, this number is just larger than the maximum MTU of just
+ *  most types of networks, except maybe for gigabit ethernet.
  */
 #define PACKET_DATA_LEN 1600
 
@@ -188,6 +189,22 @@ int rad_send(RADIUS_PACKET *packet, int activefd, char *secret)
                        ptr += sizeof(UINT4);
                        total_length += sizeof(UINT4) + 2;
                        break;
+#ifdef ASCEND_BINARY
+               case PW_TYPE_ABINARY:
+                       len = reply->length;
+                       if (len >= MAX_STRING_LEN) {
+                               len = MAX_STRING_LEN - 1;
+                       }
+#ifdef ATTRIB_NMC
+                       if (vendorpec != VENDORPEC_USR)
+#endif
+                               *ptr++ = len + 2;
+                       if (length_ptr) *length_ptr += len + 2;
+                       memcpy(ptr, reply->strvalue,len);
+                       ptr += len;
+                       total_length += len + 2;
+                       break;
+#endif
 
                default:
                        break;
@@ -527,6 +544,9 @@ int rad_decode(RADIUS_PACKET *packet, char *secret)
 
                        switch (attr->type) {
 
+#ifdef ASCEND_BINARY
+                       case PW_TYPE_ABINARY:
+#endif                  
                        case PW_TYPE_STRING:
                                /* attrlen always < MAX_STRING_LEN */
                                memcpy(pair->strvalue, ptr, attrlen);
@@ -666,8 +686,8 @@ int rad_pwdecode(char *passwd, int pwlen, char *secret, char *vector)
                passwd[i] ^= digest[i];
 
        if (pwlen <= 16) {
-               passwd[i] = 0;
-               return 0;
+               passwd[pwlen+1] = 0;
+               return pwlen;
        }
 
        /*
@@ -685,7 +705,7 @@ int rad_pwdecode(char *passwd, int pwlen, char *secret, char *vector)
        }
        passwd[pwlen] = 0;
 
-       return 0;
+       return pwlen;
 }
 
 /*
index fd910ca..fdf8626 100644 (file)
@@ -1,12 +1,11 @@
 /*
  * valuepair.c Functions to handle VALUE_PAIRs
  *
- * Version:    @(#)valuepair.c  1.00  19-Jul-1999  miquels@cistron.nl
+ * Version:    $Id$
  *
  */
 
-char valuepair_sccsid[] =
-"@(#)radius.c  1.00 Copyright 1998-1999 Cistron Internet Services B.V.";
+static const char rcsid[] = "$Id$";
 
 #include       "autoconf.h"
 
@@ -438,6 +437,20 @@ VALUE_PAIR *pairmake(char *attribute, char *value, int operator)
                        }
                        vp->length = 4;
                        break;
+#ifdef ASCEND_BINARY
+               case PW_TYPE_ABINARY:
+                       /*
+                        * special case to convert filter to binary
+                        */
+                       if ( filterBinary( vp, value ) < 0 ) {
+                         librad_log("failed to parse Ascend binary attribute: %s",
+                                    librad_errstr);
+                         free(vp);
+                         return NULL;
+                       }
+                       break;
+
+#endif
                default:
                        free(vp);
                        librad_log("unknown attribute type");