modules/ac/access_control.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- AC_to_string_header
- AC_to_string
- AC_credit_to_string
- AC_acl_to_string_header
- AC_acl_to_string
- AC_findexless_acl_l
- AC_findcreate_acl_l
- AC_findcreate_account_l
- AC_fetch_acc
- AC_check_acl
- AC_acc_addup
- AC_commit_credit
- AC_acl_sql
- AC_ban_set
- AC_asc_ban_set
- AC_commit
- AC_decay_hook
- AC_decay
- AC_acc_load
- AC_build
- AC_rxwalkhook_print
- 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