modules/ac/access_control.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. AC_to_string_header
  2. AC_to_string
  3. AC_credit_to_string
  4. AC_acl_to_string_header
  5. AC_acl_to_string
  6. AC_findexless_acl_l
  7. AC_findcreate_acl_l
  8. AC_findcreate_account_l
  9. AC_fetch_acc
  10. AC_check_acl
  11. AC_acc_addup
  12. AC_commit_credit
  13. AC_acl_sql
  14. AC_ban_set
  15. AC_asc_ban_set
  16. AC_commit
  17. AC_decay_hook
  18. AC_decay
  19. AC_acc_load
  20. AC_build
  21. AC_rxwalkhook_print
  22. AC_rxwalkhook_print_acl

   1 /***************************************
   2   $Revision: 1.20 $
   3 
   4   Access control module (ac) - access control for the query part
   5 
   6   Status: NOT REVIEWED, TESTED
   7   
   8   Design and implementation by: Marek Bukowy
   9   
  10   ******************/ /******************
  11   Copyright (c) 1999                              RIPE NCC
  12  
  13   All Rights Reserved
  14   
  15   Permission to use, copy, modify, and distribute this software and its
  16   documentation for any purpose and without fee is hereby granted,
  17   provided that the above copyright notice appear in all copies and that
  18   both that copyright notice and this permission notice appear in
  19   supporting documentation, and that the name of the author not be
  20   used in advertising or publicity pertaining to distribution of the
  21   software without specific, written prior permission.
  22   
  23   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  24   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  25   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  26   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  27   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  28   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  29   ***************************************/
  30 #include <stdio.h>
  31 #include <glib.h>
  32 
  33 #define AC_OK RX_OK
  34 #define AC_INVARG IP_INVARG
  35 
  36 #define AC_IMPL
  37 #include <rxroutines.h>
  38 #include <erroutines.h>
  39 #include <access_control.h>
  40 #include "socket.h"
  41 #include "mysql_driver.h"
  42 #include <constants.h>
  43 #include <server.h>
  44 
  45 #define AC_DECAY_TIME 600
  46 
  47 /* formats for printing the access control list entries */
  48 #define ACL_FORMAT        "%10d %10d %10d %10d %10d"
  49 #define ACL_HEADER  "%-20s %10s %10s %10s %10s %10s\n"
  50 
  51 /* formats for printing the accounting entries */
  52 #define ACC_FORMAT       "%4d    %4d    %4d    %4d    %6d    %6d    %6d"
  53 #define ACC_HEADER "%-20s %4s    %4s    %4s    %4s    %6s    %6s    %6s\n"
  54 
  55 
  56 /*++++++++++++++++++++++++++++++++++++++
  57   AC_to_string_header:
  58 
  59   produce a header for the access stats printout  
  60 
  61   returns an allocated string
  62   ++++++++++++++++++++++++++++++++++++++*/
  63 char *AC_to_string_header(void) 
     /* [<][>][^][v][top][bottom][index][help] */
  64 {
  65   char *result_buf;
  66 
  67   dieif( wr_malloc( (void **) &result_buf, 256) != UT_OK );
  68   
  69   sprintf(result_buf, ACC_HEADER, 
  70           "ip", "conn", "pass", "deny", "qry", "pub", "priv", "bonus" );
  71 
  72   return result_buf;
  73 }
  74 
  75 /*++++++++++++++++++++++++++++++++++++++
  76   AC_to_string:
  77 
  78   Show an access structure  
  79 
  80   returns an allocated string
  81   ++++++++++++++++++++++++++++++++++++++*/
  82 char *AC_to_string(GList *leafptr)
     /* [<][>][^][v][top][bottom][index][help] */
  83 {
  84   char *result_buf;
  85   acc_st *a = leafptr->data;
  86 
  87   if( wr_malloc( (void **) &result_buf, 256) != UT_OK ) {
  88     /* XXX generic malloc handler pending ...*/
  89     return NULL;
  90   }
  91   
  92   if( a == NULL ) {
  93     strcpy(result_buf, "DATA MISSING!");
  94   }
  95   else {
  96     sprintf(result_buf,  ACC_FORMAT,
  97             a->connections,
  98             a->addrpasses,
  99             a->denials,
 100             a->queries,     
 101             a->public_objects,
 102             a->private_objects,
 103             a->private_bonus
 104             );
 105   }
 106   
 107   return result_buf;
 108 } /* AC_to_string() */
 109 
 110 
 111 /*++++++++++++++++++++++++++++++++++++++
 112   AC_credit_to_string:
 113  
 114  Show credit used (for logging of queries)
 115  
 116  acc_st *a     - the credit structure
 117  
 118  returns an allocated string
 119  ++++++++++++++++++++++++++++++++++++++*/
 120 char *AC_credit_to_string(acc_st *a)
     /* [<][>][^][v][top][bottom][index][help] */
 121 {
 122   char *result_buf;
 123   
 124   if( wr_malloc( (void **) &result_buf, 64) != UT_OK ) {
 125     /* XXX generic malloc handler pending ...*/
 126     return NULL;
 127   }
 128   
 129   dieif( a == NULL );
 130   
 131   sprintf(result_buf,"%d+%d%s",
 132           a->private_objects,
 133           a->public_objects,
 134           a->denials ? " **DENIED**" : ""
 135           );
 136   
 137   return result_buf;
 138 } /* AC_credit_to_string */ 
 139 
 140 
 141 /*+++++++++++++++++++++++++++++++++++++++
 142   AC_acl_to_string_header:
 143 
 144   produce a header for the acl printout
 145 
 146   returns an allocated string
 147   ++++++++++++++++++++++++++++++++++++++*/
 148 char *
 149 AC_acl_to_string_header(void)
     /* [<][>][^][v][top][bottom][index][help] */
 150 {
 151   char *result_buf;
 152   dieif( wr_malloc( (void **) &result_buf, 256) != UT_OK );
 153 
 154   sprintf(result_buf, ACL_HEADER, "ip",
 155           "maxbonus", "maxdenials", "maxpublic", "ban", "trustpass" );
 156 
 157   return result_buf;
 158 }
 159 
 160 
 161 
 162 /*++++++++++++++++++++++++++++++++++++++
 163   AC_acl_to_string:
 164 
 165   Show an access control list structure
 166 
 167   returns an allocated string
 168   ++++++++++++++++++++++++++++++++++++++*/
 169 char *AC_acl_to_string(GList *leafptr)
     /* [<][>][^][v][top][bottom][index][help] */
 170 {
 171   char *result_buf;
 172   acl_st *a = leafptr->data;
 173 
 174   if( wr_malloc( (void **) &result_buf, 256) != UT_OK ) {
 175     /* XXX generic malloc handler pending ...*/
 176     return NULL;
 177   }
 178   
 179   if( a != NULL ) {
 180     sprintf(result_buf, ACL_FORMAT,
 181             a->maxbonus,
 182             a->maxdenials,
 183             a->maxpublic,
 184             a->deny,     
 185             a->trustpass
 186             );
 187   }
 188   else {
 189     strcpy(result_buf, "DATA MISSING\n");
 190   }
 191   
 192   return result_buf;
 193 } /* AC_acl_to_string() */
 194 
 195 
 196 /*+++++++++++++++++++++++++++++++++++++++
 197   AC_findexless_acl_l:
 198 
 199   find the exact or less specific match for the given prefix in the acl tree.
 200 
 201   ip_prefix_t *prefix - prefix to look for
 202   acl_st *store_acl   - pointer to store the output
 203 
 204   returns error code from RX or OK
 205 
 206   MT-Note: assumes locked acl tree
 207   ++++++++++++++++++++++++++++++++++++++*/
 208 er_ret_t
 209 AC_findexless_acl_l(ip_prefix_t *prefix, acl_st *store_acl)
     /* [<][>][^][v][top][bottom][index][help] */
 210 {
 211   GList       *datlist=NULL;
 212   er_ret_t    ret_err;
 213   rx_datref_t *datref;  
 214 
 215   if( (ret_err = RX_bin_search(RX_SRCH_EXLESS, 0, 0, act_acl, 
 216                                prefix, &datlist, RX_ANS_ALL)
 217        ) != RX_OK   ||  g_list_length(datlist) == 0 ) {
 218     /* acl tree is not configured at all ! There always must be a
 219        catch-all record with defaults */
 220     die;
 221   }
 222 
 223   datref = (rx_datref_t *)g_list_nth_data(datlist,0);
 224 
 225   *store_acl = * ((acl_st *)  datref->leafptr);
 226 
 227   wr_clear_list( &datlist );
 228 
 229   /* XXX dbg checking tree consistency */
 230   {
 231     rx_treecheck_t errorfound;
 232     er_ret_t err;
 233     if( (err=RX_treecheck(act_acl, 1, &errorfound)) != RX_OK ) {
 234       fprintf(stderr, "Nope! %d returned \n", err);
 235       die;
 236     }
 237   }  
 238 
 239   return ret_err;
 240 }
 241 /* AC_findexless_acl_l */
 242 
 243 
 244 /*+++++++++++++++++++++++++++++++++++++++
 245   AC_findcreate_acl_l:
 246   
 247   find or create an entry for the given prefix in the acl tree.
 248 
 249   ip_prefix_t *prefix - prefix to look for 
 250   acl_st **store_acl  - pointer to store the ptr to the acl struct 
 251                         (initialised to the values of the parent entry 
 252                         if just created)
 253 
 254   returns error code from RX or OK
 255 
 256   MT-Note: assumes locked acl tree
 257   ++++++++++++++++++++++++++++++++++++++*/
 258 er_ret_t
 259 AC_findcreate_acl_l(ip_prefix_t *prefix, acl_st **store_acl)
     /* [<][>][^][v][top][bottom][index][help] */
 260 {
 261   GList       *datlist=NULL;
 262   er_ret_t    ret_err;
 263   acl_st      *newacl;
 264   acl_st acl_copy;    
 265 
 266   if( NOERR(ret_err = RX_bin_search(RX_SRCH_EXACT, 0, 0, act_acl, 
 267                                     prefix, &datlist, RX_ANS_ALL)
 268             )) {
 269     
 270     switch( g_list_length(datlist)) {
 271     case 0:
 272       dieif( wr_calloc((void **)&newacl, 1, sizeof(acl_st)) != UT_OK );
 273       
 274       /* make the new one inherit all parameters after the old one */
 275       
 276       AC_findexless_acl_l(prefix, &acl_copy);
 277 
 278       *newacl = acl_copy;
 279       
 280       /* link in */
 281       rx_bin_node(RX_OPER_CRE, prefix, act_acl, (rx_dataleaf_t *)newacl);
 282       break;
 283     case 1:
 284       {
 285         /* Uh-oh, the guy is already known ! (or special, in any case) */ 
 286         rx_datref_t *datref = (rx_datref_t *)g_list_nth_data(datlist,0);
 287         newacl = (acl_st *) datref->leafptr;
 288       }
 289       break;
 290     default:
 291       die;
 292     }
 293   } 
 294 
 295   /* free search results */
 296   wr_clear_list( &datlist );
 297   
 298   /* store */
 299   *store_acl = newacl;
 300   return ret_err;
 301 }
 302 /* AC_findcreate_acl_l */
 303 
 304 
 305 /*+++++++++++++++++++++++++++++++++++++++
 306   AC_findcreate_account_l:
 307   
 308   finds exact prefix in the accounting tree
 309   or creates area initialised to zeros + sets ptr to it.
 310   
 311   rx_tree_t *tree     - the tree
 312   ip_prefix_t *prefix - prefix to look for 
 313   acc_st **store_acl  - pointer to store the ptr to the account struct 
 314 
 315   returns error code from RX or OK
 316 
 317   MT-Note: assumes locked accounting tree 
 318   ++++++++++++++++++++++++++++++++++++++*/
 319 er_ret_t 
 320 AC_findcreate_account_l(rx_tree_t *tree, ip_prefix_t *prefix, 
     /* [<][>][^][v][top][bottom][index][help] */
 321                         acc_st **acc_store)
 322 {
 323   GList       *datlist=NULL;
 324   er_ret_t    ret_err;
 325   acc_st      *recacc;
 326 
 327   if( (ret_err = RX_bin_search(RX_SRCH_EXACT, 0, 0, tree, 
 328                                prefix, &datlist, RX_ANS_ALL)) == RX_OK ) {
 329     switch( g_list_length(datlist) ) {
 330     case 0:
 331       /* need to create a new accounting record */
 332       if( (ret_err = wr_malloc( (void **)& recacc, sizeof(acc_st))) == UT_OK ) {
 333         /*  counters = init to zeros */
 334         memset( recacc, 0, sizeof(acc_st));
 335         
 336         /* attach. The recacc is to be treated as a dataleaf
 337            (must use lower levels than RX_asc_*)
 338         */
 339         ret_err = rx_bin_node( RX_OPER_CRE, prefix, 
 340                                act_runtime, (rx_dataleaf_t *)recacc );
 341       }
 342       break;
 343     case 1:
 344       {
 345         rx_datref_t *datref = (rx_datref_t *) g_list_nth_data( datlist,0 );
 346         
 347         /* OK, there is a record already */
 348         recacc = (acc_st *) datref->leafptr;
 349         
 350       }
 351       break;
 352     default: die; /* there shouldn't be more than 1 entry per IP */
 353     }
 354   }
 355     
 356   wr_clear_list( &datlist );
 357   
 358   *acc_store = recacc;
 359   
 360   return ret_err;
 361 }
 362 
 363 
 364 /*++++++++++++++++++++++++++++++++++++++
 365   AC_fetch_acc:
 366 
 367   Finds the runtime accounting record for this IP, 
 368   stores a copy of it in acc_store. 
 369   If not found, then it is created and initialised to zeros in findcreate()
 370 
 371   ip_addr_t *addr  - address
 372   acc_st *acc_store - pointer to store the account struct 
 373 
 374   MT-Note: locks/unlocks the accounting tree
 375   ++++++++++++++++++++++++++++++++++++++*/
 376 er_ret_t AC_fetch_acc( ip_addr_t *addr, acc_st *acc_store)
     /* [<][>][^][v][top][bottom][index][help] */
 377 {
 378   er_ret_t ret_err;
 379   ip_prefix_t prefix;
 380   acc_st *ac_ptr;
 381 
 382   prefix.ip = *addr;
 383   prefix.bits = IP_sizebits(addr->space);
 384 
 385   TH_acquire_read_lock( &(act_runtime->rwlock) );
 386   
 387   ret_err = AC_findcreate_account_l(act_runtime, &prefix, &ac_ptr);
 388   *acc_store = *ac_ptr;
 389 
 390   TH_release_read_lock( &(act_runtime->rwlock) );
 391 
 392   return ret_err;
 393 }/* AC_fetch_acc() */
 394 
 395 
 396 /*++++++++++++++++++++++++++++++++++++++  
 397   AC_check_acl:
 398   
 399   search for this ip or less specific record in the access control tree
 400   
 401   if( bonus in combined runtime+connection accountings > max_bonus in acl)
 402             set denial in the acl for this ip (create if needed)
 403   if( combined denialcounter > max_denials in acl)
 404             set the permanent ban in acl; save in SQL too
 405   calculate credit if pointer provided
 406   save the access record (ip if created or found/prefix otherwise) 
 407             at *acl_store if provided
 408 
 409   ip_addr_t *addr  - address
 410   acc_st *acc_store - pointer to store the *credit* account struct 
 411   acl_st *acl_store - pointer to store the acl struct 
 412   
 413   any of the args except address can be NULL
 414 
 415   returns error code from RX or OK
 416 
 417   MT-Note: locks/unlocks the accounting tree
 418   ++++++++++++++++++++++++++++++++++++++*/
 419 er_ret_t AC_check_acl( ip_addr_t *addr, 
     /* [<][>][^][v][top][bottom][index][help] */
 420                        acc_st *credit_acc,
 421                        acl_st *acl_store
 422                        )
 423 {
 424   ip_prefix_t prefix;
 425   er_ret_t    ret_err;
 426   acl_st      acl_record;
 427   acc_st      run_acc;
 428 
 429   AC_fetch_acc( addr, &run_acc );
 430   
 431   prefix.ip = *addr;
 432   prefix.bits = IP_sizebits(addr->space);
 433   
 434   /* lock the tree accordingly */
 435   TH_acquire_read_lock( &(act_acl->rwlock) );  
 436   
 437   /* find an applicable record */
 438   AC_findexless_acl_l(&prefix, &acl_record);
 439   
 440   /* calculate the credit if pointer given */
 441   if( credit_acc ) {
 442     memset( credit_acc, 0, sizeof(acc_st));
 443     credit_acc->public_objects =                       /* -1 == unlimited */
 444       acl_record.maxpublic - run_acc.public_objects;
 445     credit_acc->private_objects =
 446       acl_record.maxbonus - run_acc.private_bonus;
 447   }
 448 
 449   /* copy the acl record if asked for it*/
 450   if( acl_store ) {
 451     *acl_store =  acl_record;
 452   }
 453 
 454   /* release lock */
 455   TH_release_read_lock( &(act_acl->rwlock) );
 456   
 457  
 458   return ret_err;
 459 }
 460 
 461 
 462 
 463 /*++++++++++++++++++++++++++++++++++++++  
 464   AC_acc_addup:
 465 
 466   Add/subtract the values from one accounting structure to another
 467 
 468   acc_st *a  - this one gets changed
 469   acc_st *b  - this one provides the values to change a
 470   int minus  - triggers subtraction if non-zero
 471 
 472 +++++++++++++++++++++++++++++++++++++++*/
 473 void AC_acc_addup(acc_st *a, acc_st *b, int minus)
     /* [<][>][^][v][top][bottom][index][help] */
 474 {
 475   int mul = minus ? -1 : 1;
 476   
 477   /* add all counters from b to those in a */
 478   a->connections     +=  mul * b->connections;   
 479   a->addrpasses      +=  mul * b->addrpasses;  
 480  
 481   a->denials         +=  mul * b->denials;      
 482   a->queries         +=  mul * b->queries;       
 483   a->public_objects  +=  mul * b->public_objects;
 484   a->private_objects +=  mul * b->private_objects;
 485   a->private_bonus   +=  mul * b->private_bonus;
 486 }/* AC_acc_addup */
 487 
 488 /*++++++++++++++++++++++++++++++++++++++ 
 489   AC_commit_credit:
 490 
 491   performs the commit on an accounting tree (locks them first)
 492   stores a copy of the accounting record at rec_store
 493 
 494   rx_tree_t *tree      - the tree
 495   ip_prefix_t *prefix  - prefix (usually a /32)
 496   acc_st *acc_conn     - credit used
 497   acc_st *rec_store    - pointer to store the account struct 
 498 
 499   returns error code from AC_findcreate_account_l or OK
 500 
 501   MT-Note: locks/unlocks the accounting tree
 502 +++++++++++++++++++++++++++++++++++++++*/
 503 er_ret_t 
 504 AC_commit_credit(rx_tree_t *tree, ip_prefix_t *prefix, 
     /* [<][>][^][v][top][bottom][index][help] */
 505                  acc_st *acc_conn, acc_st *rec_store )
 506 {
 507   acc_st      *accountrec;
 508   er_ret_t    ret_err;
 509 
 510 
 511   acc_conn->private_bonus = acc_conn->private_objects;
 512 
 513   TH_acquire_write_lock( &(tree->rwlock) );
 514 
 515   ret_err = AC_findcreate_account_l(act_runtime, prefix, &accountrec);
 516   
 517   if( NOERR(ret_err)) {
 518     AC_acc_addup(accountrec, acc_conn, ACC_PLUS);
 519   }
 520 
 521   TH_release_write_lock( &(tree->rwlock) );
 522  
 523   *rec_store = *accountrec;
 524   
 525   return ret_err;
 526 }/* AC_commit_credit */
 527 
 528 
 529 
 530 /*++++++++++++++++++++++++++++++++++++++  
 531   AC_acl_sql:
 532 
 533   updates/creates a record for the given prefix in the acl table of 
 534   the RIPADMIN database. Adds a comment.
 535 
 536   ip_prefix_t *prefix  - prefix
 537   acl_st *newacl       - new values to store in the database
 538   char *newcomment     - comment to be added (must not be NULL)
 539   
 540   placeholder: it may return an error code from SQ - as soon as sq 
 541   implements common error scheme
 542 
 543  ++++++++++++++++++++++++++++++++++++++*/
 544 er_ret_t 
 545 AC_acl_sql(ip_prefix_t *prefix, acl_st *newacl, char *newcomment )
     /* [<][>][^][v][top][bottom][index][help] */
 546 {  
 547   SQ_connection_t *sql_connection = NULL;
 548   SQ_result_set_t *result;
 549   SQ_row_t *row;
 550   char *oldcomment;
 551   char *query;
 552   char querybuf[256];
 553   
 554   sql_connection = SQ_get_connection(CO_get_host(),
 555                                      CO_get_database_port(),
 556                                      "RIPADMIN",
 557                                      CO_get_user(), 
 558                                      CO_get_password() );
 559   
 560   /* get the old entry, extend it */
 561   sprintf(querybuf, "SELECT comment FROM acl WHERE "
 562           "prefix = %u AND prefix_length = %d", 
 563           prefix->ip.words[0],
 564           prefix->bits);
 565   dieif( SQ_execute_query(sql_connection, querybuf, &result) == -1 );
 566   
 567   if( SQ_num_rows(result) == 1 ) {
 568     dieif( (row = SQ_row_next(result)) == NULL);
 569     oldcomment = SQ_get_column_string(result, row, 0);
 570   }
 571   else {
 572     oldcomment = "";
 573   }
 574 
 575   SQ_free_result(result);
 576   
 577   /* must hold the thing below (REPLACE..blah blah blah) + text */
 578   dieif( wr_malloc((void **)&query, 
 579                    strlen(oldcomment) + strlen(newcomment) + 256) != UT_OK );
 580   
 581   /* compose new entry and insert it */
 582   sprintf(query, "REPLACE INTO acl VALUES(%u, %d, %d, %d, %d, %d, %d,"
 583           "\"%s%s%s\")",
 584           prefix->ip.words[0],
 585           prefix->bits,
 586           newacl->maxbonus,
 587           newacl->maxpublic,
 588           newacl->maxdenials,
 589           newacl->deny,
 590           newacl->trustpass,
 591           oldcomment, 
 592           strlen(oldcomment) > 0 ? "\n" : "",
 593           newcomment
 594           );
 595   
 596   SQ_execute_query(sql_connection, query, NULL);
 597   SQ_close_connection(sql_connection);
 598   
 599   wr_free(query);
 600   
 601   return AC_OK;
 602 
 603 }/* AC_acl_sql */
 604 
 605 /*++++++++++++++++++++++++++++++++++++++ 
 606   AC_ban_set:
 607   
 608   re/sets the permanent ban flag both in the acl tree in memory
 609   and the sql table. The "text" is appended to the comment 
 610   in the sql record (the expected cases are
 611   - "automatic" in case the limit is exceeded and ban is set by s/w
 612   - "manual"    in case it is (un)set from the config iface
 613 
 614   ip_prefix_t *prefix   - prefix 
 615   char *text            - usually "automatic" or "manual"  
 616   int denyflag          - new value of the denyflag (ban)
 617   
 618   returns error code from AC_acl_sql or OK
 619   +++++++++++++++++++++++++++++++++++++++*/
 620 er_ret_t
 621 AC_ban_set(ip_prefix_t *prefix, char *text, int denyflag)
     /* [<][>][^][v][top][bottom][index][help] */
 622 {
 623   acl_st *treeacl;
 624   char newcomment[256];
 625   er_ret_t ret_err;
 626   time_t  clock;
 627   char timebuf[26];
 628   
 629   time(&clock);
 630   ctime_r(&clock, timebuf);
 631 
 632   sprintf(newcomment,"%s permanent ban set to %d at %s", text, 
 633           denyflag, timebuf);
 634     
 635   TH_acquire_write_lock( &(act_acl->rwlock) );  
 636 
 637   /* find a record in the tree */  
 638   if( NOERR(ret_err = AC_findcreate_acl_l( prefix, &treeacl )) ) {
 639     treeacl->deny = denyflag;
 640     ret_err = AC_acl_sql( prefix, treeacl, newcomment );
 641   }
 642   TH_release_write_lock( &(act_acl->rwlock) );
 643 
 644   return ret_err;
 645 }/* AC_ban_set */
 646 
 647 
 648 /*++++++++++++++++++++++++++++++++++++++ 
 649   AC_asc_ban_set:
 650   
 651   sets ban on text address/range. Parses the text address/range/prefix 
 652   and then calls AC_ban_set on that prefix. 
 653   
 654   Precondition: if the key is a range, it must decompose into one prefix 
 655   
 656   returns error code from IP_smart_conv, AC_ban_set or 
 657   AC_INVARG if range composed
 658   +++++++++++++++++++++++++++++++++++++++*/
 659 er_ret_t
 660 AC_asc_ban_set(char *addrstr, char *text, int denyflag)
     /* [<][>][^][v][top][bottom][index][help] */
 661 {
 662   er_ret_t ret_err;
 663   GList *preflist = NULL;
 664   ip_keytype_t key_type;
 665 
 666   if( (ret_err = IP_smart_conv(addrstr, 0, 0,
 667                                &preflist, IP_PLAIN, &key_type)) != IP_OK ) {
 668     return ret_err;
 669   }
 670   
 671   /* allow only one prefix */
 672   /* The argument can be even a range, but must decompose into one prefix */
 673   if(  NOERR(ret_err) && g_list_length( preflist ) != 1 ) {
 674     ret_err = AC_INVARG;
 675   }
 676   
 677   if( NOERR(ret_err) ) {
 678     ret_err = AC_ban_set( (g_list_first(preflist)->data), text, denyflag);
 679   }
 680 
 681   wr_clear_list( &preflist );
 682   
 683   return ret_err;
 684 }/* AC_asc_ban_set */
 685 
 686 
 687 /*++++++++++++++++++++++++++++++++++++++ 
 688   AC_commit:
 689 
 690   commits the credit into all accounting trees, (XXX: only one at the moment)
 691   checks the limits and sets automatic ban if limit exceeded.
 692 
 693   ip_addr_t *addr  - user's address
 694   acc_st *acc_conn - credit used
 695   acl_st *acl_copy - pointer to store a copy of the acl
 696 
 697   returns error code from AC_commit_credit or AC_ban_set or OK.
 698 
 699   outline:
 700         lock runtime + minute accounting trees 
 701         -----------------------  XXX runtime only for the moment
 702            find or create entries, 
 703            increase accounting values by the values from passed acc
 704            check values against acl, see if permanent ban applies
 705 
 706            reset the connection acc
 707         unlock accounting trees
 708 
 709         if permanent ban - set it! :
 710             lock acl
 711             find/create IP in memory
 712             set ban
 713             find/create IP in SQL
 714             copy old values (if any), set ban, append comment
 715             unlock acl
 716 
 717  +++++++++++++++++++++++++++++++++++++++*/
 718 er_ret_t AC_commit(ip_addr_t *addr, acc_st *acc_conn, acl_st *acl_copy) { 
     /* [<][>][^][v][top][bottom][index][help] */
 719   acc_st   account;
 720   er_ret_t ret_err;
 721   ip_prefix_t prefix;
 722 
 723   prefix.ip = *addr;
 724   prefix.bits = IP_sizebits(addr->space);
 725   
 726   ret_err = AC_commit_credit(act_runtime, &prefix, acc_conn, &account);
 727   /* XXX add more trees here */
 728   
 729   memset(acc_conn,0, sizeof(acc_st));
 730 
 731   /* set permanent ban if deserved  and if not set yet */
 732   if( account.denials > acl_copy->maxdenials 
 733       && acl_copy->deny == 0 
 734       && NOERR(ret_err) ) {
 735     
 736     ret_err = AC_ban_set(&prefix, "Automatic", 1);
 737   }
 738 
 739   return ret_err;
 740 } /* AC_commit */
 741 
 742 
 743 /*++++++++++++++++++++++++++++++++++++++ 
 744   AC_decay_hook:
 745 
 746   action performed on a single account node during decay (diminishing the
 747   bonus). Conforms to rx_walk_tree interface, therefore some of the 
 748   arguments do not apply and are not used.
 749 
 750   rx_node_t *node  - pointer to the node of the radix tree
 751   int level        - n/a
 752   int nodecounter  - n/a
 753   void *con        - n/a
 754 
 755   returns always OK
 756 +++++++++++++++++++++++++++++++++++++++*/
 757 er_ret_t AC_decay_hook(rx_node_t *node, int level, int nodecounter, void *con)
     /* [<][>][^][v][top][bottom][index][help] */
 758 {
 759   acc_st *a = node->leaves_ptr->data;
 760   
 761   a->private_bonus *= 0.95;
 762 
 763   return RX_OK;
 764 } /* AC_decay_hook() */
 765 
 766 
 767 
 768 /*++++++++++++++++++++++++++++++++++++++
 769   AC_decay:
 770   
 771   Every AC_DECAY_TIME goes through the accounting tree(s) and decays the 
 772   bonus values.
 773   
 774   returns always OK
 775 
 776   MT-Note  This should be run as a detached thread.
 777   +++++++++++++++++++++++++++++++++++++++*/
 778 er_ret_t AC_decay(void) {
     /* [<][>][^][v][top][bottom][index][help] */
 779   er_ret_t ret_err;
 780 
 781   
 782   while(CO_get_do_server()) {
 783 
 784     TH_acquire_write_lock( &(act_runtime->rwlock) );
 785 
 786     if( act_runtime->top_ptr != NULL ) {
 787        rx_walk_tree(act_runtime->top_ptr, AC_decay_hook,
 788                          RX_WALK_SKPGLU,  /* skip glue nodes */
 789                          255, 0, 0, NULL, &ret_err);
 790     }
 791 
 792     /* it should also be as smart as to delete nodes that have reached 
 793        zero, otherwise the whole of memory will be filled.
 794        Next release :-)
 795     */
 796 
 797     TH_release_write_lock( &(act_runtime->rwlock) );
 798 
 799     printf("AC: decaying access tree. (Every %d seconds)\n", AC_DECAY_TIME);
 800 
 801     SV_sleep(LOCK_SHTDOWN, AC_DECAY_TIME);
 802   }
 803 
 804   return ret_err;
 805 } /* AC_decay() */
 806 
 807 
 808 /*++++++++++++++++++++++++++++++++++++++ 
 809   AC_acc_load:
 810 
 811   loads the acl access tree from the acl table of the RIPADMIN database.
 812   (takes port/host/user/password from the config module).
 813   
 814   bails out if encounters problems with the database (logs to stderr).
 815 
 816   returns error code from RX_bin_node or wr_malloc.
 817   ++++++++++++++++++++++++++++++++++++++*/
 818 er_ret_t AC_acc_load(void)
     /* [<][>][^][v][top][bottom][index][help] */
 819 {
 820   SQ_connection_t *con=NULL;
 821   SQ_result_set_t *result;
 822   SQ_row_t *row;
 823   er_ret_t ret_err = RX_OK;
 824 
 825   if( (con = SQ_get_connection(CO_get_host(), CO_get_database_port(), 
 826                         "RIPADMIN", CO_get_user(), CO_get_password() )
 827        ) == NULL ) {
 828     fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con));
 829     die;
 830   }
 831   
 832   if( SQ_execute_query(con, "SELECT * FROM acl", &result) == -1 ) {
 833       fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con));
 834       die;
 835   }
 836   
 837   TH_acquire_write_lock( &(act_acl->rwlock) );
 838 
 839   while ( (row = SQ_row_next(result)) != NULL && ret_err == RX_OK) {
 840     ip_prefix_t mypref;
 841     acl_st *newacl;
 842     char *col[7];
 843     unsigned myint;
 844     int i;
 845 
 846     memset(&mypref, 0, sizeof(ip_prefix_t));
 847     mypref.ip.space = IP_V4;
 848     
 849     if( (ret_err = wr_malloc( (void **)& newacl, sizeof(acl_st))
 850          ) == UT_OK ) {
 851 
 852       for(i=0; i<7; i++) {
 853         if ( (col[i] = SQ_get_column_string(result, row, i)) == NULL) {
 854           die;
 855         }
 856       }
 857       
 858       /* prefix ip */
 859       if( sscanf(col[0], "%u", &mypref.ip.words[0] ) < 1 ) { die; }
 860       
 861       /* prefix length */
 862       if( sscanf(col[1], "%u", &mypref.bits ) < 1 ) { die; }
 863       
 864       /* acl contents */
 865       if( sscanf(col[2], "%u",  & (newacl->maxbonus)   ) < 1 ) { die; }
 866       if( sscanf(col[3], "%u",  & (newacl->maxpublic)   ) < 1 ) { die; }
 867       if( sscanf(col[4], "%hd", & (newacl->maxdenials) ) < 1 ) { die; }
 868       
 869       /* these are chars therefore cannot read directly */
 870       if( sscanf(col[5], "%u", &myint              ) < 1 ) { die; }
 871       else {
 872         newacl->deny = myint;
 873       }
 874       if( sscanf(col[6], "%u", &myint  ) < 1 ) { die; }
 875       else {
 876         newacl->trustpass = myint;
 877       }
 878       
 879       /* free space */
 880       for(i=0; i<6; i++) {
 881           wr_free(col[i]);
 882       }
 883       
 884       /* now add to the tree */      
 885       ret_err = rx_bin_node( RX_OPER_CRE, &mypref, 
 886                              act_acl, (rx_dataleaf_t *) newacl );
 887     }
 888   } /* while row */
 889 
 890   TH_release_write_lock( &(act_acl->rwlock) );
 891 
 892   SQ_free_result(result);
 893   /* Close connection */
 894   SQ_close_connection(con);
 895 
 896   return ret_err;
 897 } /* AC_acc_load */
 898 
 899 
 900 
 901 /*++++++++++++++++++++++++++++++++++++++ 
 902   AC_build:
 903 
 904   creates empty trees for accounting/acl.
 905   
 906   returns error code from RX_tree_cre or OK.
 907   (XXX): just now only bails out when encounters problems.
 908   ++++++++++++++++++++++++++++++++++++++*/
 909 er_ret_t AC_build(void) 
     /* [<][>][^][v][top][bottom][index][help] */
 910 {
 911   /* create trees */
 912   if (      RX_tree_cre("0.0.0.0/0", RX_FAM_IP, RX_MEM_RAMONLY, 
 913                         RX_SUB_NONE, &act_runtime) != RX_OK
 914          || RX_tree_cre("0.0.0.0/0", RX_FAM_IP, RX_MEM_RAMONLY, 
 915                         RX_SUB_NONE, &act_hour) != RX_OK
 916          || RX_tree_cre("0.0.0.0/0", RX_FAM_IP, RX_MEM_RAMONLY, 
 917                         RX_SUB_NONE, &act_minute) != RX_OK
 918          || RX_tree_cre("0.0.0.0/0", RX_FAM_IP, RX_MEM_RAMONLY, 
 919                         RX_SUB_NONE, &act_acl) != RX_OK
 920          )
 921     die; /*can be changed to an error and handled ... some day */
 922 
 923   return RX_OK;
 924 }
 925 
 926 /*++++++++++++++++++++++++++++++++++++++ 
 927   AC_rxwalkhook_print:
 928 
 929   action performed on a single account node 
 930   when listing the contents of the access tree: format and print the
 931   data from this node.
 932 
 933   Conforms to rx_walk_tree interface, therefore some of the 
 934   arguments do not apply and are not used.
 935   
 936   rx_node_t *node  - pointer to the node of the radix tree
 937   int level        - n/a
 938   int nodecounter  - n/a
 939   void *con        - pointer to the connection structure (prints to it)
 940   
 941   returns always OK 
 942 +++++++++++++++++++++++++++++++++++++++*/
 943 er_ret_t AC_rxwalkhook_print(rx_node_t *node, 
     /* [<][>][^][v][top][bottom][index][help] */
 944                              int level, int nodecounter, 
 945                              void *con)
 946 {
 947   char adstr[IP_ADDRSTR_MAX];
 948   char line[1024];
 949   char *dat;
 950   
 951   
 952     if( IP_addr_b2a(&(node->prefix.ip), adstr, IP_ADDRSTR_MAX) != IP_OK ) {
 953       die; /* program error. */
 954     }
 955     
 956     sprintf(line, "%-20s %s\n", adstr, 
 957             dat=AC_to_string( node->leaves_ptr ));
 958     wr_free(dat);
 959     
 960     SK_cd_puts((sk_conn_st *)con, line);
 961     return RX_OK;
 962 } /* AC_rxwalkhook_print */
 963 
 964 
 965 /*++++++++++++++++++++++++++++++++++++++
 966   AC_rxwalkhook_print_acl:
 967   
 968   action performed on a single account node 
 969   when listing the contents of the acl tree: format and print the
 970   data from this node.
 971 
 972   Conforms to rx_walk_tree interface, therefore some of the 
 973   arguments do not apply and are not used.
 974   
 975   rx_node_t *node  - pointer to the node of the radix tree
 976   int level        - n/a
 977   int nodecounter  - n/a
 978   void *con        - pointer to the connection structure (prints to it)
 979 
 980   returns always OK 
 981   +++++++++++++++++++++++++++++++++++++++*/
 982 er_ret_t AC_rxwalkhook_print_acl(rx_node_t *node, 
     /* [<][>][^][v][top][bottom][index][help] */
 983                              int level, int nodecounter, 
 984                              void *con)
 985 {
 986   char prefstr[IP_PREFSTR_MAX];
 987   char line[1024];
 988   char *dat;
 989   
 990   
 991     if( IP_pref_b2a(&(node->prefix), prefstr, IP_PREFSTR_MAX) != IP_OK ) {
 992       die; /* program error. */
 993     }
 994     
 995     sprintf(line, "%-20s %s\n", prefstr, 
 996             dat=AC_acl_to_string( node->leaves_ptr ));
 997     wr_free(dat);
 998     
 999     SK_cd_puts((sk_conn_st *)con, line);
1000     return RX_OK;
1001 }/* AC_rxwalkhook_print_acl */
1002 

/* [<][>][^][v][top][bottom][index][help] */