Common subdirectories: src.orig/CVS and src/CVS
diff -c --new-file src.orig/Make.inc src/Make.inc
*** src.orig/Make.inc	Fri Dec 17 15:37:16 1999
--- src/Make.inc	Fri Jan 21 10:52:17 2000
***************
*** 4,15 ****
  #
  #
  
! SERVER_OBJS    = radiusd.o dict.o files.o util.o md5.o attrprint.o \
  			acct.o radius.o pam.o log.o version.o proxy.o \
  			exec.o auth.o timestr.o cache.o
! SERVERDBM_OBJS = radiusddbm.o dict.o filesdbm.o util.o md5.o attrprint.o \
! 			acct.o radius.o pam.o log.o versiondbm.o proxy.o \
! 			exec.o auth.o timestr.o cache.o
  SERVER_SRCS    = radiusd.c dict.c files.c util.c md5.c attrprint.c acct.c \
  			radius.c pam.c log.c version.c proxy.c \
  			exec.c auth.c timestr.c cache.c
--- 4,15 ----
  #
  #
  
! SERVER_OBJS    = radiusd.o dict.o files.o filters.o util.o md5.o attrprint.o \
  			acct.o radius.o pam.o log.o version.o proxy.o \
  			exec.o auth.o timestr.o cache.o
! SERVERDBM_OBJS = radiusddbm.o dict.o filesdbm.o filters.o util.o md5.o \
! 			attrprint.o acct.o radius.o pam.o log.o versiondbm.o \
! 			proxy.o  exec.o auth.o timestr.o cache.o
  SERVER_SRCS    = radiusd.c dict.c files.c util.c md5.c attrprint.c acct.c \
  			radius.c pam.c log.c version.c proxy.c \
  			exec.c auth.c timestr.c cache.c
***************
*** 47,52 ****
--- 47,56 ----
  filesdbm.o: files.c $(INCLUDES)
  	$(CC) $(CFLAGS) $(DBM) $(PAM) -o filesdbm.o -c files.c
  
+ filters.o: filters.c $(INCLUDES)
+ 	$(CC) $(CFLAGS) -c filters.c
+ 
+ 
  radius.o: radius.c $(INCLUDES)
  	$(CC) $(CFLAGS) -c radius.c
  
***************
*** 97,110 ****
  	$(CC) $(LDFLAGS) -o raduse raduse.o $(LIBS)
  
  radzap: radzap.o util.o
! 	$(CC) $(LDFLAGS) -o radzap radzap.o util.o $(LIBS)
  
  lint:
  	-lint -hbacvx -DLINT $(SERVER_SRCS)
  	-lint -hbacvx -DLINT ../radpass.c ../md5.c ../util.c
  
  clean:
! 	rm -f *.o radiusd radwho raduse radtest radzap builddbm radiusd.dbm
  	rm -f ../build ../debian/substvars ../debian/files
  
  install:
--- 101,114 ----
  	$(CC) $(LDFLAGS) -o raduse raduse.o $(LIBS)
  
  radzap: radzap.o util.o
! 	$(CC) $(LDFLAGS) -o radzap  radzap.o util.o $(LIBS)
  
  lint:
  	-lint -hbacvx -DLINT $(SERVER_SRCS)
  	-lint -hbacvx -DLINT ../radpass.c ../md5.c ../util.c
  
  clean:
! 	rm -f *.o radiusd radlast radwho raduse radtest radzap builddbm radiusd.dbm
  	rm -f ../build ../debian/substvars ../debian/files
  
  install:
diff -c --new-file src.orig/attrprint.c src/attrprint.c
*** src.orig/attrprint.c	Fri Dec 17 15:37:16 1999
--- src/attrprint.c	Fri Jan 21 10:52:17 2000
***************
*** 158,163 ****
--- 158,175 ----
  					localtime((time_t *)&pair->lvalue));
  		fprintf(fd, "%s = \"%s\"", pair->name, buffer);
  		break;
+ 	case PW_TYPE_FILTER_BINARY:
+                {
+                        int ix;
+ 
+                        fprintf( fd, "%s = ", pair->name );
+                        for ( ix = 0; ix < pair->lvalue; ix += 1 ) {
+                                 fprintf( fd, " %02x", (unsigned char)(pair->strvalue[ ix ]) );
+                        }
+                        printf( "\n" );
+                }
+                break;
+ 
  
  	default:
  		fprintf(fd, "Unknown type %d", pair->type);
diff -c --new-file src.orig/dict.c src/dict.c
*** src.orig/dict.c	Fri Dec 17 15:37:18 1999
--- src/dict.c	Fri Jan 21 10:52:17 2000
***************
*** 236,241 ****
--- 236,244 ----
  			else if(strcmp(typestr, "date") == 0) {
  				type = PW_TYPE_DATE;
  			}
+ 			else if(strcmp(typestr, "abinary") == 0) {
+                                type = PW_TYPE_FILTER_BINARY;
+ 			}
  			else {
  				log(L_ERR|L_CONS,
  			"dict_init: Invalid type on line %d of dictionary",
diff -c --new-file src.orig/files.c src/files.c
*** src.orig/files.c	Fri Dec 17 15:37:19 1999
--- src/files.c	Fri Jan 21 10:52:17 2000
***************
*** 1347,1352 ****
--- 1347,1361 ----
  			pair->operator = operator;
  
  			switch(pair->type) {
+ 			 case PW_TYPE_FILTER_BINARY:
+                                /*
+                                 * special case to convert filter to binary
+                                 */
+                                if ( filterBinary( pair, valstr ) == -1 ) {
+                                        free(pair);
+                                        return(-1);
+                                }
+                                break;
  
  			case PW_TYPE_STRING:
  do_copy:
diff -c --new-file src.orig/filters.c src/filters.c
*** src.orig/filters.c	Wed Dec 31 19:00:00 1969
--- src/filters.c	Fri Jan 21 10:54:00 2000
***************
*** 0 ****
--- 1,1093 ----
+ /*
+  * 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: filters.c,v 1.2 1996/12/11 23:17:08 baskar Exp $ */
+ 
+ #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 "radiusd.h"
+ 
+ VALUE_PAIR*	prevRadPair = 0;
+ 
+ #undef DEBUG
+ #if defined( DEBUG )
+ #define PRINTF( x )	printf x
+ #else
+ #define PRINTF( x )
+ #endif
+ 
+ #define NO_TOKEN -1
+ 
+ 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 ));
+     log(L_ERR, "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 ));
+ 		log(L_ERR, "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;
+ 			    }
+ 			}
+ 		    }
+ 		}
+ 		log( L_ERR, "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 ));
+ 			log(L_ERR, "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 ) {
+ 			    log(L_ERR, "filter mask error: %s \n", _curString );
+ 			    goto doneErr;
+ 			}
+ #ifdef DEBUG
+ 			PRINTF((" octet retlen = %d ", maskLen ));
+ 			for( tok = 0; tok < maskLen; tok++) {
+         		    PRINTF(("%2x", gen->mask[tok]));
+ 		        }
+ 			PRINTF(("\n"));
+ #endif
+ 
+ 			break;
+ 		    case FILTER_GENERIC_VALUE:
+ 			gstate ++;
+ 			valLen = _a2octet( token, (char *)gen->value );
+ 			if( valLen != maskLen ) {
+ 			    log(L_ERR, "filter value size is not the same size as the filter mask: %s \n", 
+ 				     _curString );
+ 			    goto doneErr;
+ 			}
+ 			gen->len = htons( valLen );
+ #ifdef DEBUG
+ 			PRINTF((" octet retlen = %d ", maskLen ));
+ 			for( tok = 0; tok < maskLen; tok++) {
+         		    PRINTF(("%2x", gen->value[tok]));
+ 		        }
+ 			PRINTF(("\n"));
+ #endif
+ 
+ 			break;
+ 		    default:
+ 			log(L_ERR, "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(pair, valstr)
+ VALUE_PAIR	*pair;
+ char		*valstr;
+ {
+ 
+     char*		token;
+     unsigned long	tok;
+     int			rc;
+     RadFilter		radFil, *filt;
+     RadGenericFilter*	gen;
+     char		*copied_valstr;
+ 
+     rc = -1;
+     strcpy( _curString, valstr );
+     copied_valstr = strdup(valstr);
+     if (!copied_valstr) return -1;
+ 
+     token = (char *) strtok( (char *)copied_valstr, " " );
+     tok = _findKey( token, _filterKeywords );
+     pair->lvalue = 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;
+     }
+     free(copied_valstr);
+ 
+     /*
+      * 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;
+ 	    log(L_ERR, "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->lvalue );
+     }
+     return(rc);
+ }
+ 
+ 
diff -c --new-file src.orig/radius.c src/radius.c
*** src.orig/radius.c	Fri Dec 17 15:37:20 1999
--- src/radius.c	Fri Jan 21 10:52:17 2000
***************
*** 22,27 ****
--- 22,33 ----
  
  #include	"radiusd.h"
  
+ /*RELAX start*/
+ u_char    rrnr[32];
+ u_char    rrnrpool[33];
+ u_char    clid_rrnr[32];
+ 
+ /*RELAX stop*/
  /*
   *	Make sure our buffer is aligned.
   */
***************
*** 140,145 ****
--- 146,162 ----
  			 *	should NOT be needed. In fact I have no
  			 *	idea if it is needed :)
  			 */
+ /*RELAX start*/
+                 if (strcmp(reply->name,"Ascend-Dial-Number")== 0
+                     &&rrnr[0]!='\0')
+                 {
+                   sprintf(rrnrpool,"9%s",rrnr);
+                   strcpy(reply->name,"pusegn");
+                   strcpy(reply->strvalue,rrnrpool);
+                 reply->length = strlen(reply->strvalue);
+                 }
+ /*RELAX stop */
+ 
  			if (reply->length == 0 && reply->strvalue[0] != 0)
  				reply->length = strlen(reply->strvalue);
  
***************
*** 169,174 ****
--- 186,202 ----
  			ptr += sizeof(UINT4);
  			total_length += sizeof(UINT4) + 2;
  			break;
+                case PW_TYPE_FILTER_BINARY:
+ 
+                        /* The binary representation of the filter is in
+                           reply->strvalue.  It's length is in reply->lvalue */
+ 
+                        *ptr++ = reply->lvalue + 2;
+                        memcpy( ptr, reply->strvalue, reply->lvalue );
+                        ptr += reply->lvalue;
+                        total_length += reply->lvalue + 2;
+                         break;
+ 
  
  		default:
  			break;
***************
*** 458,463 ****
--- 486,515 ----
  				memset(pair->strvalue, 0, AUTH_STRING_LEN);
  				memcpy(pair->strvalue, ptr, attrlen);
  				debug_pair(stdout, pair);
+ /*RELAX start*/
+                              if (strncmp(pair->name,"User-Name",9)==0)
+                                    {
+                                     char *nwptr;
+                                     rrnr[0]='\0';
+                                     nwptr=index(pair->strvalue,':');
+                                     if (nwptr != NULL)
+                                        {
+                                         *nwptr='\0';
+                                         nwptr++;/* fuer Amt */
+                                         strcpy(rrnr,++nwptr);
+                                     }
+                                     while (*(pair->strvalue)=='0')
+                                          {
+                                           char *nwptr;
+                                           nwptr=pair->strvalue;
+                                           nwptr++;
+                                           strcpy(clid_rrnr,nwptr);
+                                           strcpy(pair->strvalue,clid_rrnr);
+                                     }
+                              }
+ 
+ /*RELAX stop*/
+ 
  				if(first_pair == (VALUE_PAIR *)NULL) {
  					first_pair = pair;
  				}
***************
*** 480,486 ****
  				}
  				prev = pair;
  				break;
! 			
  			default:
  				DEBUG("    %s (Unknown Type %d)",
  					attr->name,attr->type);
--- 532,551 ----
  				}
  				prev = pair;
  				break;
! 		
!                     case PW_TYPE_FILTER_BINARY:
!                                memcpy(pair->strvalue, ptr, attrlen);
!                                pair->strvalue[attrlen] = '\0';
!                                if(first_pair == (VALUE_PAIR *)NULL) {
!                                        first_pair = pair;
!                                }
!                                else {
!                                        prev->next = pair;
!                                }
!                                prev = pair;
!                                break;
! 
! 	
  			default:
  				DEBUG("    %s (Unknown Type %d)",
  					attr->name,attr->type);
diff -c --new-file src.orig/radius.h src/radius.h
*** src.orig/radius.h	Fri Dec 17 15:37:20 1999
--- src/radius.h	Fri Jan 21 10:52:17 2000
***************
*** 54,60 ****
  #define PW_TYPE_INTEGER			1
  #define PW_TYPE_IPADDR			2
  #define PW_TYPE_DATE			3
! 
  
  #define	PW_AUTHENTICATION_REQUEST	1
  #define	PW_AUTHENTICATION_ACK		2
--- 54,60 ----
  #define PW_TYPE_INTEGER			1
  #define PW_TYPE_IPADDR			2
  #define PW_TYPE_DATE			3
! #define PW_TYPE_FILTER_BINARY  4       /* ASCEND extension */
  
  #define	PW_AUTHENTICATION_REQUEST	1
  #define	PW_AUTHENTICATION_ACK		2
***************
*** 194,196 ****
--- 194,391 ----
  #define PW_STATUS_ACCOUNTING_ON		7
  #define PW_STATUS_ACCOUNTING_OFF	8
  
+  
+ #define	PW_AUTHENTICATION_REQUEST	1
+ #define PW_STATUS_ACCOUNTING_ON		7
+ #define PW_STATUS_ACCOUNTING_OFF	8
+  
+ /*
+  * ASCEND extensions for ABINARY filters
+  */
+ 
+ #define IPX_NODE_ADDR_LEN		6
+ 
+ typedef UINT4			IpxNet;
+ typedef char			IpxNode[ IPX_NODE_ADDR_LEN ];
+ typedef unsigned short	IpxSocket;
+ 
+ #if ! defined( FALSE )
+ # define FALSE		0
+ # define TRUE		(! FALSE)
+ #endif
+ 
+ /*
+  * 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;
diff -c --new-file src.orig/radiusd.h src/radiusd.h
*** src.orig/radiusd.h	Fri Dec 17 15:37:20 1999
--- src/radiusd.h	Fri Jan 21 10:53:00 2000
***************
*** 279,281 ****
--- 279,290 ----
  /* timestr.c */
  int		timestr_match(char *, time_t);
  
+ void           pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr);
+ 
+ /* filters.c */
+ int            filterBinary(VALUE_PAIR *pair, char *valstr);
+ 
+  /* version.c */
+  void           version();
+ 
+ 
