@ -41,89 +41,87 @@
// XML elements in result
// they MUST NOT have a number on the tail
// because pike uses it for "row" numbering
static const char * const MAX_HITS = " max_hits " ;
static const char * const IP_ADDR = " ip_addr " ;
static const char * const LEAF_HITS_PREV = " leaf_hits_prev " ;
static const char * const LEAF_HITS_CURR = " leaf_hits_curr " ;
static const char * const EXPIRES = " expires " ;
static const char * const STATUS = " status " ;
static const char * const NUMBER_OF_ROWS = " number_of_rows " ;
static const char * const MAX_HITS = " max_hits " ;
static const char * const IP_ADDR = " ip_addr " ;
static const char * const LEAF_HITS_PREV = " leaf_hits_prev " ;
static const char * const LEAF_HITS_CURR = " leaf_hits_curr " ;
static const char * const EXPIRES = " expires " ;
static const char * const STATUS = " status " ;
static const char * const NUMBER_OF_ROWS = " number_of_rows " ;
# define IP_ADDR_MAX_LENGTH 40
# define STATUS_MAX_LENGTH 10
typedef struct TopItem
{
char ip_addr [ IP_ADDR_MAX_LENGTH ] ;
in_addr_t ipv4_addr ; /* uint32_t */
struct in6_addr ipv6_addr ;
unsigned short leaf_hits [ 2 ] ;
unsigned int expires ;
# define STATUS_MAX_LENGTH 10
typedef struct TopItem {
char ip_addr [ IP_ADDR_MAX_LENGTH ] ;
in_addr_t ipv4_addr ; /* uint32_t */
struct in6_addr ipv6_addr ;
unsigned short leaf_hits [ 2 ] ;
unsigned int expires ;
char status [ STATUS_MAX_LENGTH ] ;
int num_of_ips ; /* number of IP addresses in aggregated result */
int num_of_ips ; /* number of IP addresses in aggregated result */
} TopItem ;
int compare_TopItem_hits ( const void * left , const void * right )
int compare_TopItem_hits ( const void * left , const void * right )
{
TopItem * li = ( TopItem * ) left ;
TopItem * ri = ( TopItem * ) right ;
return li - > leaf_hits [ 0 ] + li - > leaf_hits [ 1 ] - ri - > leaf_hits [ 0 ]
- ri - > leaf_hits [ 1 ] ;
return li - > leaf_hits [ 0 ] + li - > leaf_hits [ 1 ] - ri - > leaf_hits [ 0 ] - ri - > leaf_hits [ 1 ] ;
}
/** Compare function to qsort array in reverse order (big er first) */
int compare_TopItem_hits_reverse ( const void * left , const void * right )
/** Compare function to qsort array in reverse order (big g er first) */
int compare_TopItem_hits_reverse ( const void * left , const void * right )
{
return compare_TopItem_hits ( right , left ) ;
}
int compare_TopItem_ipv4_addr ( const void * item1 , const void * item2 )
{
return ( ( TopItem * ) item1 ) - > ipv4_addr - ( ( TopItem * ) item2 ) - > ipv4_addr ;
return ( ( TopItem * ) item1 ) - > ipv4_addr - ( ( TopItem * ) item2 ) - > ipv4_addr ;
}
/**
* @ return concatenated string in newly allocated memory
*/
static char * concat ( const char * name , int index )
static char * concat ( const char * name , int index )
{
char * ptr ;
int rv ;
rv = asprintf ( & ptr , " %s%d " , name , index ) ;
if ( rv = = - 1 )
if ( rv = = - 1 )
return 0 ;
return ptr ;
}
static void strfree ( char * ptr )
static void strfree ( char * ptr )
{
if ( ptr )
if ( ptr )
free ( ptr ) ;
}
static void die_if_fault_occurred ( xmlrpc_env * env )
static void die_if_fault_occurred ( xmlrpc_env * env )
{
if ( env - > fault_occurred ) {
fprintf ( stderr , " XML-RPC Fault: %s (%d) \n " , env - > fault_string ,
env - > fault_ code) ;
if ( env - > fault_occurred ) {
fprintf ( stderr , " XML-RPC Fault: %s (%d) \n " ,
env - > fault_ string, env - > fault_ code) ;
exit ( 1 ) ;
}
}
/** @return 0 if everything is OK, 1 otherwise */
static int fault_occurred ( xmlrpc_env * env )
static int fault_occurred ( xmlrpc_env * env )
{
if ( env - > fault_occurred ) {
fprintf ( stderr , " XML-RPC Fault: %s (%d) \n " , env - > fault_string ,
env - > fault_ code) ;
if ( env - > fault_occurred ) {
fprintf ( stderr , " XML-RPC Fault: %s (%d) \n " ,
env - > fault_ string, env - > fault_ code) ;
return 1 ;
}
return 0 ;
}
static void die_if_fault_occurred_line ( xmlrpc_env * env , int line )
static void die_if_fault_occurred_line ( xmlrpc_env * env , int line )
{
if ( env - > fault_occurred )
if ( env - > fault_occurred )
fprintf ( stderr , " LINE: %d \n " , line ) ;
die_if_fault_occurred ( env ) ;
}
@ -131,26 +129,23 @@ static void die_if_fault_occurred_line(xmlrpc_env *env, int line)
void print_help ( )
{
printf ( " \n " ) ;
if ( isatty ( 1 ) )
printf ( " usage: \033 [1mpike_top <ser addr>:<port> [--hot|--warm|--all] "
" [--mask] \033 [0m \n " ) ;
if ( isatty ( 1 ) )
printf ( " usage: \033 [1mpike_top <ser addr>:<port> [--hot|--warm|--all] [--mask] \033 [0m \n " ) ;
else
printf ( " usage: pike_top <ser addr>:<port> [--hot|--warm|--all] "
" [--mask] [--ipleaf|--inner] \n " ) ;
printf ( " usage: pike_top <ser addr>:<port> [--hot|--warm|--all] [--mask] [--ipleaf|--inner] \n " ) ;
printf ( " \n " ) ;
printf ( " \t options: \n "
" \t \t --hot ... show hot IP leaves \n "
" \t \t --all ... show all IP leaves \n "
" \t \t --mask ... aggregate results regarding IP mask length \n "
" \t \t (default 32, i.e. not aggregate) \n "
" \t \t IPv4 only at this time \n \n "
" \t \t \t default is to show HOT nodes \n \n " ) ;
if ( isatty ( 1 ) )
printf ( " You can use \033 [1mwatch \033 [0m(1) utility for periodical "
" output. \n \n " ) ;
" \t \t --hot ... show hot IP leaves \n "
" \t \t --all ... show all IP leaves \n "
" \t \t --mask ... aggregate results regarding IP mask length \n "
" \t \t (default 32, i.e. not aggregate) \n "
" \t \t IPv4 only at this time \n \n "
" \t \t \t default is to show HOT nodes \n \n " ) ;
if ( isatty ( 1 ) )
printf ( " You can use \033 [1mwatch \033 [0m(1) utility for periodical output. \n \n " ) ;
else
printf ( " You can use watch(1) utility for periodical output. \n \n " ) ;
/*
/*
printf ( " Note: \n "
" It is a question if reporting warm nodes is useful and if yes, how to report \n "
" them. I feel that should be more welcome to report parents of warm nodes, \n "
@ -159,36 +154,39 @@ void print_help()
}
/* Following options are conforming to definition of node status defined in pike/ip_tree.h */
# define OPT_WARM 1
# define OPT_HOT 2
# define OPT_ALL 3
# define OPT_WARM 1
# define OPT_HOT 2
# define OPT_ALL 3
/**
* @ param options ORed cmdline options
* @ return position of first non option parameter
*/
int process_options ( int argc , char * argv [ ] , int * options , int * mask_length )
{
static struct option long_options [ ] = { { " hot " , 0 , 0 , ' h ' } ,
/* {"warm", 0, 0, 'w'}, */
{ " all " , 0 , 0 , ' a ' } , { " mask " , 0 , 0 , ' m ' } , { " help " , 0 , 0 , ' ? ' } ,
{ 0 , 0 , 0 , 0 } } ;
static struct option long_options [ ] = {
{ " hot " , 0 , 0 , ' h ' } ,
/* {"warm", 0, 0, 'w'}, */
{ " all " , 0 , 0 , ' a ' } ,
{ " mask " , 0 , 0 , ' m ' } ,
{ " help " , 0 , 0 , ' ? ' } ,
{ 0 , 0 , 0 , 0 }
} ;
int c , index , counter ;
* options = 0 ;
counter = 0 ;
while ( ( c = getopt_long ( argc , argv , " hwam: " , long_options , & index ) ) ! = - 1 ) {
switch ( c ) {
while ( ( c = getopt_long ( argc , argv , " hwam: " , long_options , & index ) ) ! = - 1 ) {
switch ( c ) {
case ' h ' :
* options = OPT_HOT ;
+ + counter ;
break ;
/* case 'w':
/* case 'w':
* options = OPT_WARM ;
+ + counter ;
break ;
*/
case ' a ' :
*/ case ' a ' :
* options = OPT_ALL ;
+ + counter ;
break ;
@ -203,13 +201,13 @@ int process_options(int argc, char *argv[], int *options, int *mask_length)
break ;
}
}
if ( counter > 1 ) {
fprintf ( stderr , " ERROR: Node type selectors are ex lusive, only one of "
if ( counter > 1 ) {
fprintf ( stderr , " ERROR: Node type selectors are ex c lusive, only one of "
" them can be used \n " ) ;
print_help ( ) ;
exit ( 1 ) ;
}
if ( * options = = 0 )
if ( * options = = 0 )
* options = OPT_HOT ;
return optind ;
@ -222,19 +220,18 @@ int process_options(int argc, char *argv[], int *options, int *mask_length)
* @ param rv returned value
* @ return 1 if succeed and 0 otherwise
*/
int get_int_from_struct_by_name (
xmlrpc_value * structP , const char * element_name , int * rv )
int get_int_from_struct_by_name ( xmlrpc_value * structP , const char * element_name , int * rv )
{
xmlrpc_env env ;
xmlrpc_env_init ( & env ) ;
xmlrpc_value * valueP ;
xmlrpc_struct_find_value ( & env , structP , element_name , & valueP ) ;
if ( env . fault_occurred )
if ( env . fault_occurred )
goto error ;
xmlrpc_read_int ( & env , valueP , rv ) ;
if ( env . fault_occurred )
if ( env . fault_occurred )
goto error1 ;
xmlrpc_DECREF ( valueP ) ;
@ -251,9 +248,8 @@ error:
* @ param rv contains newly allocated string or NULL if fails
* @ return 1 if succeed and 0 otherwise
*/
/* FIXME terminates the programm if it fails */
int get_string_from_struct_by_name (
xmlrpc_value * structP , const char * element_name , char * * rv )
/* FIXME terminates the programme if it fails */
int get_string_from_struct_by_name ( xmlrpc_value * structP , const char * element_name , char * * rv )
{
xmlrpc_env env ;
xmlrpc_env_init ( & env ) ;
@ -281,8 +277,7 @@ int get_int_from_struct_by_idx(xmlrpc_value *structP, int index, int *rv)
xmlrpc_value * keyP ;
xmlrpc_value * valueP ;
xmlrpc_struct_read_member ( & env , structP , index , & keyP ,
& valueP ) ; /* increment refcount of returned values */
xmlrpc_struct_read_member ( & env , structP , index , & keyP , & valueP ) ; /* increment refcount of returned values */
die_if_fault_occurred_line ( & env , __LINE__ ) ;
xmlrpc_read_int ( & env , valueP , rv ) ;
die_if_fault_occurred_line ( & env , __LINE__ ) ;
@ -290,20 +285,17 @@ int get_int_from_struct_by_idx(xmlrpc_value *structP, int index, int *rv)
return 1 ;
}
enum _value_type
{
enum _value_type {
TYPE_NOT_DEF = 0 ,
TYPE_INTEGER = 1 ,
TYPE_STRING = 2
TYPE_STRING = 2
} ;
typedef enum _value_type value_type ;
struct _key_value_pair
{
struct _key_value_pair {
char * key ;
value_type type ;
union value
{
union value {
int integer ;
char * string ;
void * value ;
@ -312,10 +304,10 @@ struct _key_value_pair
typedef struct _key_value_pair key_value_pair ;
void key_value_pair_cleanup ( key_value_pair * kvp )
{
if ( kvp & & kvp - > key ) {
if ( kvp & & kvp - > key ) {
free ( kvp - > key ) ;
}
if ( kvp & & kvp - > type = = TYPE_STRING & & kvp - > value . string ) {
if ( kvp & & kvp - > type = = TYPE_STRING & & kvp - > value . string ) {
free ( kvp - > value . string ) ;
}
kvp - > key = 0 ;
@ -329,7 +321,7 @@ void key_value_pair_cleanup(key_value_pair *kvp)
* @ param rv pointer to key_value_pair
* @ return 1 if succeed and 0 otherwise
*/
/* FIXME terminates the programm if it fails */
/* FIXME terminates the programm e if it fails */
int get_struct_item_by_idx ( xmlrpc_value * structP , int index , key_value_pair * rv )
{
xmlrpc_env env ;
@ -339,12 +331,11 @@ int get_struct_item_by_idx(xmlrpc_value *structP, int index, key_value_pair *rv)
int length ;
const char * string ;
xmlrpc_struct_read_member ( & env , structP , index , & keyP ,
& valueP ) ; /* increment refcount of returned values */
xmlrpc_struct_read_member ( & env , structP , index , & keyP , & valueP ) ; /* increment refcount of returned values */
die_if_fault_occurred_line ( & env , __LINE__ ) ;
xmlrpc_read_string ( & env , keyP , ( const char * * ) & rv - > key ) ;
/* handle value type */
switch ( xmlrpc_value_type ( valueP ) ) {
switch ( xmlrpc_value_type ( valueP ) ) {
case XMLRPC_TYPE_INT :
xmlrpc_read_int ( & env , valueP , & rv - > value . integer ) ;
die_if_fault_occurred_line ( & env , __LINE__ ) ;
@ -352,19 +343,16 @@ int get_struct_item_by_idx(xmlrpc_value *structP, int index, key_value_pair *rv)
break ;
case XMLRPC_TYPE_STRING :
xmlrpc_read_string ( & env , valueP , & string ) ;
printf ( " get_struct_item_by_idx: ptr = %p, string value = '%s' \n " ,
string , string ) ;
printf ( " get_struct_item_by_idx: ptr = %p, string value = '%s' \n " , string , string ) ;
die_if_fault_occurred_line ( & env , __LINE__ ) ;
rv - > value . string = ( char * ) string ;
rv - > type = TYPE_STRING ;
break ;
default :
fprintf ( stderr ,
" Wrong type of return value in key: '%s', exiting... \n " ,
rv - > key ) ;
fprintf ( stderr , " Wrong type of return value in key: '%s', exiting... \n " , rv - > key ) ;
exit ( 1 ) ;
}
xmlrpc_DECREF ( keyP ) ; /* decrement refcount */
xmlrpc_DECREF ( keyP ) ; /* decrement refcount */
xmlrpc_DECREF ( valueP ) ;
die_if_fault_occurred_line ( & env , __LINE__ ) ;
/* FIXME add error handling */
@ -384,7 +372,7 @@ int read_row(xmlrpc_value *structP, int index, TopItem *top_item)
char * string = 0 ;
elem = concat ( IP_ADDR , index ) ;
if ( ! get_string_from_struct_by_name ( structP , elem , & string ) )
if ( ! get_string_from_struct_by_name ( structP , elem , & string ) )
goto error ;
strncpy ( top_item - > ip_addr , string , sizeof ( top_item - > ip_addr ) ) ;
free ( string ) ;
@ -392,25 +380,22 @@ int read_row(xmlrpc_value *structP, int index, TopItem *top_item)
free ( elem ) ;
elem = concat ( LEAF_HITS_PREV , index ) ;
if ( ! get_int_from_struct_by_name (
structP , elem , ( unsigned int * ) & top_item - > leaf_hits [ 0 ] ) )
if ( ! get_int_from_struct_by_name ( structP , elem , ( unsigned int * ) & top_item - > leaf_hits [ 0 ] ) )
goto error ;
free ( elem ) ;
elem = concat ( LEAF_HITS_CURR , index ) ;
if ( ! get_int_from_struct_by_name (
structP , elem , ( unsigned int * ) & top_item - > leaf_hits [ 1 ] ) )
if ( ! get_int_from_struct_by_name ( structP , elem , ( unsigned int * ) & top_item - > leaf_hits [ 1 ] ) )
goto error ;
free ( elem ) ;
elem = concat ( EXPIRES , index ) ;
if ( ! get_int_from_struct_by_name (
structP , elem , ( unsigned int * ) & top_item - > expires ) )
if ( ! get_int_from_struct_by_name ( structP , elem , ( unsigned int * ) & top_item - > expires ) )
goto error ;
free ( elem ) ;
elem = concat ( STATUS , index ) ;
if ( ! get_string_from_struct_by_name ( structP , elem , & string ) )
if ( ! get_string_from_struct_by_name ( structP , elem , & string ) )
goto error ;
strncpy ( top_item - > status , string , sizeof ( top_item - > status ) ) ;
free ( string ) ;
@ -419,7 +404,7 @@ int read_row(xmlrpc_value *structP, int index, TopItem *top_item)
return 1 ;
error :
if ( string )
if ( string )
free ( string ) ;
free ( elem ) ;
@ -430,41 +415,37 @@ void print_row(TopItem *ti)
{
char * fmt ;
if ( ! ti ) {
printf ( " %-15s %10s %10s %10s %-10s \n " , " IP address " , " HITS PREV " ,
" HITS CURR " , " EXPIRES " , " STATUS " ) ;
if ( ! ti ) {
printf ( " %-15s %10s %10s %10s %-10s \n " , " IP address " , " HITS PREV " , " HITS CURR " , " EXPIRES " , " STATUS " ) ;
return ;
}
if ( strlen ( ti - > ip_addr ) > 15 ) // IPv6 addr
if ( strlen ( ti - > ip_addr ) > 15 ) // IPv6 addr
fmt = " %s \n %10d %10d %10d %-10s \n " ;
else
fmt = " %-15s %10d %10d %10d %-10s \n " ;
printf ( fmt , ti - > ip_addr , ti - > leaf_hits [ 0 ] , ti - > leaf_hits [ 1 ] , ti - > expires ,
ti - > status ) ;
printf ( fmt , ti - > ip_addr , ti - > leaf_hits [ 0 ] , ti - > leaf_hits [ 1 ] , ti - > expires , ti - > status ) ;
}
void print_row_agg ( TopItem * ti ) /* IPv4 only */
void print_row_agg ( TopItem * ti ) /* IPv4 only */
{
char * fmt ;
if ( ! ti ) {
printf ( " %-15s %10s %10s %5s \n " , " IP address " , " HITS PREV " , " HITS CURR " ,
" COUNT " ) ;
if ( ! ti ) {
printf ( " %-15s %10s %10s %5s \n " , " IP address " , " HITS PREV " , " HITS CURR " , " COUNT " ) ;
return ;
}
fmt = " %-15s %10d %10d %5d \n " ;
printf ( fmt , ti - > ip_addr , ti - > leaf_hits [ 0 ] , ti - > leaf_hits [ 1 ] ,
ti - > num_of_ips ) ;
printf ( fmt , ti - > ip_addr , ti - > leaf_hits [ 0 ] , ti - > leaf_hits [ 1 ] , ti - > num_of_ips ) ;
}
uint32_t mask ( int msklen )
uint32_t mask ( int msklen )
{
if ( msklen )
return 0xffffffff ^ ( ( 1 < < ( 32 - msklen ) ) - 1 ) ;
if ( msklen )
return 0xffffffff ^ ( ( 1 < < ( 32 - msklen ) ) - 1 ) ;
else
return 0 ;
}
@ -474,54 +455,54 @@ void print_rows(TopItem *root, int nmemb, int mask_length)
int i ;
void ( * print_function ) ( TopItem * ) ;
if ( mask_length = = 32 )
if ( mask_length = = 32 )
print_function = print_row ;
else
print_function = print_row_agg ;
print_function ( 0 ) ;
for ( i = 0 ; i < nmemb ; + + i , + + root ) {
for ( i = 0 ; i < nmemb ; + + i , + + root ) {
print_function ( root ) ;
}
}
int main ( int argc , char * argv [ ] )
int main ( int argc , char * argv [ ] )
{
xmlrpc_env env ;
xmlrpc_value * resultP ;
xmlrpc_value * keyP ;
xmlrpc_value * valueP ;
xmlrpc_value * resultP ;
xmlrpc_value * keyP ;
xmlrpc_value * valueP ;
int struct_size ;
int i , j ;
size_t length ;
const char * str_key_value ;
xmlrpc_int int_key_value ;
const char * str_key_value ;
xmlrpc_int int_key_value ;
unsigned int max_hits = 0 ;
unsigned int rows = 0 ;
int rv ;
char * uri ;
int options ; /* what kind of nodes should be processed */
int uri_pos ; /* position of first non option argument */
int options ; /* what kind of nodes should be processed */
int uri_pos ; /* position of first non option argument */
char stropts [ 16 ] ;
int pos = 0 ;
int mask_length = 32 ; /* 32 means NO aggregate */
int pos = 0 ;
int mask_length = 32 ; /* 32 means NO aggregate */
if ( argc - 1 < 1 ) {
if ( argc - 1 < 1 ) {
print_help ( ) ;
exit ( 0 ) ;
}
uri_pos = process_options ( argc , argv , & options , & mask_length ) ;
switch ( options ) {
switch ( options ) {
case OPT_HOT :
sprintf ( stropts , " HOT " ) ;
break ;
sprintf ( stropts , " HOT " ) ;
break ;
case OPT_ALL :
sprintf ( stropts , " ALL " ) ;
break ;
sprintf ( stropts , " ALL " ) ;
break ;
case OPT_WARM :
sprintf ( stropts , " WARM " ) ;
break ;
sprintf ( stropts , " WARM " ) ;
break ;
}
printf ( " Nodes = %s \n " , stropts ) ;
printf ( " Mask = /%d \n " , mask_length ) ;
@ -538,12 +519,14 @@ int main(int argc, char *argv[])
const char * const format , . . . ) ;
*/
asprintf ( & uri , " http://%s/RPC2 " , argv [ uri_pos ] ) ;
resultP = xmlrpc_client_call ( & env , uri , " pike.top " , " (s) " , stropts ) ;
resultP = xmlrpc_client_call ( & env , uri ,
" pike.top " ,
" (s) " , stropts ) ;
free ( uri ) ;
die_if_fault_occurred_line ( & env , __LINE__ ) ;
/* parse returned structure */
if ( xmlrpc_value_type ( resultP ) ! = XMLRPC_TYPE_STRUCT ) {
if ( xmlrpc_value_type ( resultP ) ! = XMLRPC_TYPE_STRUCT ) {
printf ( " unexpected result - should be structure \n " ) ;
xmlrpc_env_clean ( & env ) ;
xmlrpc_client_cleanup ( ) ;
@ -552,84 +535,80 @@ int main(int argc, char *argv[])
struct_size = xmlrpc_struct_size ( & env , resultP ) ;
die_if_fault_occurred_line ( & env , __LINE__ ) ;
// printf("Struct size: %d\n", struct_size);
// printf("Struct size: %d\n", struct_size);
if ( ! get_int_from_struct_by_name ( resultP , MAX_HITS , & max_hits ) ) {
fprintf ( stderr , " ERROR: %s not foun g in result\n " , MAX_HITS ) ;
exit ( 1 ) ;
if ( ! get_int_from_struct_by_name ( resultP , MAX_HITS , & max_hits ) ) {
fprintf ( stderr , " ERROR: %s not foun d in result\n " , MAX_HITS ) ;
exit ( 1 ) ;
}
printf ( " max_hits = %d \n " , max_hits ) ;
if ( ! get_int_from_struct_by_name ( resultP , NUMBER_OF_ROWS , & rows ) ) {
fprintf ( stderr , " ERROR: %s not foun g in result\n " , NUMBER_OF_ROWS ) ;
exit ( 1 ) ;
if ( ! get_int_from_struct_by_name ( resultP , NUMBER_OF_ROWS , & rows ) ) {
fprintf ( stderr , " ERROR: %s not foun d in result\n " , NUMBER_OF_ROWS ) ;
exit ( 1 ) ;
}
printf ( " rows = %d \n " , rows ) ;
TopItem top_items [ rows ] ;
TopItem * item ; /* tmp item ptr */
TopItem * result_items = top_items ; /* if no aggregation use this */
TopItem * item ; /* tmp item ptr */
TopItem * result_items = top_items ; /* if no aggregation use this */
memset ( top_items , 0 , sizeof ( top_items ) ) ;
/* aggregated values */
if ( rows = = 0 )
if ( rows = = 0 )
return 0 ;
for ( i = 0 , item = top_items ; i < rows ; + + i , + + item ) {
if ( ! read_row ( resultP , i , item ) ) {
for ( i = 0 , item = top_items ; i < rows ; + + i , + + item ) {
if ( ! read_row ( resultP , i , item ) ) {
fprintf ( stderr , " ERROR: while reading row number %d \n " , i ) ;
}
/* fill in ipv4 addr */
// printf("item[%d].ip_addr = %s, len = %d\n", i, item->ip_addr, strlen(item->ip_addr));
// printf("item[%d].ip_addr = %s, len = %d\n", i, item->ip_addr, strlen(item->ip_addr));
rv = inet_pton ( AF_INET , item - > ip_addr , & item - > ipv4_addr ) ;
if ( rv > 0 ) {
// printf("IPv4 addr: %x\n", item->ipv4_addr);
if ( rv > 0 ) {
// printf("IPv4 addr: %x\n", item->ipv4_addr);
} else {
fprintf ( stderr ,
" IP conversion failed - not an IPv4 address: '%s' \n " ,
item - > ip_addr ) ; /* conversion failed from any reason */
fprintf ( stderr , " IP conversion failed - not an IPv4 address: '%s' \n " , item - > ip_addr ) ; /* conversion failed from any reason */
printf ( " item[%d].ipv4_addr = %x \n " , i , item - > ipv4_addr ) ;
}
}
assert ( rows > 0 ) ;
assert ( rows > 0 ) ;
/* if IP mask length is shorter than 32 then aggregate list according to the mask */
if ( mask_length < 32 ) {
if ( mask_length < 32 ) {
uint32_t ip_mask = htonl ( mask ( mask_length ) ) ;
qsort ( top_items , rows , sizeof ( TopItem ) ,
compare_TopItem_ipv4_addr ) ; /* sort by IPv4 */
qsort ( top_items , rows , sizeof ( TopItem ) , compare_TopItem_ipv4_addr ) ; /* sort by IPv4 */
/* skip items without ipv4 address */
i = 0 ; /* index of non aggregated items */
while ( ! top_items [ i ] . ipv4_addr & & i < rows ) {
printf ( " Skip item[%d] - do not has IPv4 address: %s \n " , i ,
top_items [ i ] . ip_addr ) ;
i = 0 ; /* index of non aggregated items */
while ( ! top_items [ i ] . ipv4_addr & & i < rows ) {
printf ( " Skip item[%d] - do not has IPv4 address: %s \n " , i , top_items [ i ] . ip_addr ) ;
memset ( & top_items [ i ] , 0 , sizeof ( TopItem ) ) ;
+ + i ;
}
j = 0 ; /* index of aggregated items */
if ( i = = 0 )
j = 0 ; /* index of aggregated items */
if ( i = = 0 )
+ + i ;
top_items [ 0 ] . ipv4_addr & = ip_mask ;
top_items [ 0 ] . num_of_ips = 1 ;
inet_ntop ( AF_INET , & top_items [ 0 ] . ipv4_addr , top_items [ 0 ] . ip_addr ,
sizeof ( top_items [ 0 ] . ip_addr ) ) ;
while ( i < rows ) {
inet_ntop ( AF_INET , & top_items [ 0 ] . ipv4_addr , top_items [ 0 ] . ip_addr , sizeof ( top_items [ 0 ] . ip_addr ) ) ;
while ( i < rows ) {
top_items [ i ] . ipv4_addr & = ip_mask ;
if ( top_items [ j ] . ipv4_addr = = top_items [ i ] . ipv4_addr ) {
if ( top_items [ j ] . ipv4_addr = = top_items [ i ] . ipv4_addr ) {
top_items [ j ] . leaf_hits [ 0 ] + = top_items [ i ] . leaf_hits [ 0 ] ;
top_items [ j ] . leaf_hits [ 1 ] + = top_items [ i ] . leaf_hits [ 1 ] ;
+ + ( top_items [ j ] . num_of_ips ) ;
+ + i ;
} else {
}
else {
+ + j ;
top_items [ j ] = top_items [ i ] ;
top_items [ j ] . num_of_ips = 1 ;
inet_ntop ( AF_INET , & top_items [ j ] . ipv4_addr ,
top_items [ j ] . ip_addr , sizeof ( top_items [ j ] . ip_addr ) ) ;
inet_ntop ( AF_INET , & top_items [ j ] . ipv4_addr , top_items [ j ] . ip_addr , sizeof ( top_items [ j ] . ip_addr ) ) ;
+ + i ;
}
}
@ -638,7 +617,7 @@ int main(int argc, char *argv[])
qsort ( top_items , rows , sizeof ( TopItem ) , compare_TopItem_hits_reverse ) ;
print_rows ( top_items , rows , mask_length ) ;
print_rows ( top_items , rows , mask_length ) ;
/* Dispose of our result value. */
xmlrpc_DECREF ( resultP ) ;