📄 filters.c
字号:
/* * 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. * * Modifications to this file for yardradius are under YardRadius copyright, * as follows: * * Copyright (C) 2004, Francesco P. Lovergine. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms stated in the LICENSE file which should be * enclosed with sources. *//* FIXME: A bit revised for inclusion in yardradius, needs major revision *//* $Id: filters.c,v 1.1.2.2 2004/08/27 21:45:16 flovergine Exp $ */#include "yard.h"#if defined(ASCEND_BINARY)VALUE_PAIR* prevRadPair = NULL;#define NO_TOKEN -1typedef 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];static 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. */static int _findKey(char *string, KeywordStruct *list){ KeywordStruct *entry; char *buf, *ptr; buf = strdup(string); for( ptr = buf ; buf && *ptr ; ptr++ ) { if ( isupper( *ptr ) ) *ptr = tolower( *ptr ); } entry = list; while( entry->name ) { if( strcmp( entry->name, buf ) == 0 ) { break; } entry++; } free(buf); 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(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(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(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;} /* * 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( (char*)"1234567890./", *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( 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(RadFilter*curEntry){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -