Navigation


Changeset 1338:f1b65381c1e7 in freeDiameter


Ignore:
Timestamp:
Apr 9, 2019, 10:48:45 PM (5 years ago)
Author:
Thomas Klausner <tk@giga.or.at>
Branch:
default
Phase:
public
histedit_source:
a96776a293770a9223f9cf06945dfdcf3844398a
Message:

rt_ereg: Support config reload. Support grouped AVPs. Support multiple separate AVPs.

Written for Effortel Technologies SA, published with their consent.

Files:
4 edited

Legend:

Unmodified
Added
Removed
  • doc/rt_ereg.conf.sample

    r525 r1338  
    44# The rt_ereg extension allows creation of routing rules based on AVP value matching regular expressions.
    55
     6# This extension supports configuration reload at runtime. Send
     7# signal SIGUSR1 to the process to cause the process to reload its
     8# config.
     9
    610# First, one must indicate which AVP should be used for matching.
    711# At the moment, only AVP with OCTETSTRING types are valid.
    812#  AVP = "User-Name";
     13# It is possible to specify AVPs below GROUPED AVPs with the by separating AVPs with a colon (':'):
     14#  AVP = "Grouped-AVP1" : "Grouped-AVP2" : "Octetstring-AVP";
    915# This parameter is mandatory. There is no default value.
    1016
     
    2026#    (reminder: the server with the peer with the highest score gets the message)
    2127# Note that all rules are tested for each message that contain the AVP, not only the first match.
     28
     29# There can be multiple blocks of AVPs and rules; just start the next one with another AVP line:
     30#  AVP = "Other-AVP";
     31# and continue with rules as above.
  • extensions/rt_ereg/rtereg.c

    r1216 r1338  
    3434*********************************************************************************************************/
    3535
    36 /* 
     36/*
    3737 * This extension allows to perform some pattern-matching on an AVP
    3838 * and send the message to a server accordingly.
     
    4040 */
    4141
     42#include <pthread.h>
     43#include <signal.h>
     44
    4245#include "rtereg.h"
    4346
     47static pthread_rwlock_t rte_lock;
     48
     49#define MODULE_NAME "rt_ereg"
     50
     51static char *rt_ereg_config_file;
     52
    4453/* The configuration structure */
    45 struct rtereg_conf rtereg_conf;
     54struct rtereg_conf *rtereg_conf;
     55int rtereg_conf_size;
    4656
    4757#ifndef HAVE_REG_STARTEND
     
    5161#endif /* HAVE_REG_STARTEND */
    5262
    53 static int proceed(char * value, size_t len, struct fd_list * candidates)
     63static int rtereg_init(void);
     64static int rtereg_init_config(void);
     65static void rtereg_fini(void);
     66
     67void rtereg_conf_free(struct rtereg_conf *config_struct, int config_size)
     68{
     69        int i, j;
     70
     71        /* Destroy the data */
     72        for (j=0; j<config_size; j++) {
     73                if (config_struct[j].rules) {
     74                        for (i = 0; i < config_struct[j].rules_nb; i++) {
     75                                free(config_struct[j].rules[i].pattern);
     76                                free(config_struct[j].rules[i].server);
     77                                regfree(&config_struct[j].rules[i].preg);
     78                        }
     79                }
     80                free(config_struct[j].avps);
     81                free(config_struct[j].rules);
     82        }
     83        free(config_struct);
     84}
     85
     86static int proceed(char * value, size_t len, struct fd_list * candidates, int conf)
    5487{
    5588        int i;
    56        
    57         for (i = 0; i < rtereg_conf.rules_nb; i++) {
     89
     90        for (i = 0; i < rtereg_conf[conf].rules_nb; i++) {
    5891                /* Does this pattern match the value? */
    59                 struct rtereg_rule * r = &rtereg_conf.rules[i];
     92                struct rtereg_rule * r = &rtereg_conf[conf].rules[i];
    6093                int err = 0;
    6194                struct fd_list * c;
    62                
     95
    6396                TRACE_DEBUG(ANNOYING, "Attempt pattern matching of '%.*s' with rule '%s'", (int)len, value, r->pattern);
    64                
     97
    6598                #ifdef HAVE_REG_STARTEND
    6699                {
     
    77110                }
    78111                #endif /* HAVE_REG_STARTEND */
    79                
     112
    80113                if (err == REG_NOMATCH)
    81114                        continue;
    82                        
     115
    83116                if (err != 0) {
    84117                        char * errstr;
     
    100133                        /* Free the buffer, return the error */
    101134                        free(errstr);
    102                        
     135
    103136                        return (err == REG_ESPACE) ? ENOMEM : EINVAL;
    104137                }
    105                
     138
    106139                /* From this point, the expression matched the AVP value */
    107140                TRACE_DEBUG(FULL, "[rt_ereg] Match: '%s' to value '%.*s' => '%s' += %d",
     
    111144                                        r->server,
    112145                                        r->score);
    113                
     146
    114147                for (c = candidates->next; c != candidates; c = c->next) {
    115148                        struct rtd_candidate * cand = (struct rtd_candidate *)c;
     
    121154                }
    122155        };
    123        
     156
     157        return 0;
     158}
     159
     160static int find_avp(msg_or_avp *where, int conf_index, int level, struct fd_list * candidates)
     161{
     162        struct dict_object *what;
     163        struct dict_avp_data dictdata;
     164        struct avp *nextavp = NULL;
     165        struct avp_hdr *avp_hdr = NULL;
     166
     167        /* iterate over all AVPs and try to find a match */
     168//      for (i = 0; i<rtereg_conf[j].level; i++) {
     169        if (level > rtereg_conf[conf_index].level) {
     170                TRACE_DEBUG(INFO, "internal error, dug too deep");
     171                return 1;
     172        }
     173        what = rtereg_conf[conf_index].avps[level];
     174
     175        CHECK_FCT(fd_dict_getval(what, &dictdata));
     176        CHECK_FCT(fd_msg_browse(where, MSG_BRW_FIRST_CHILD, (void *)&nextavp, NULL));
     177        while (nextavp) {
     178                CHECK_FCT(fd_msg_avp_hdr(nextavp, &avp_hdr));
     179                if ((avp_hdr->avp_code == dictdata.avp_code) && (avp_hdr->avp_vendor == dictdata.avp_vendor)) {
     180                        if (level != rtereg_conf[conf_index].level - 1) {
     181                                TRACE_DEBUG(INFO, "[rt_ereg] found grouped AVP %d (vendor %d), digging deeper", avp_hdr->avp_code, avp_hdr->avp_vendor);
     182                                CHECK_FCT(find_avp(nextavp, conf_index, level+1, candidates));
     183                        } else {
     184                                TRACE_DEBUG(INFO, "[rt_ereg] found AVP %d (vendor %d)", avp_hdr->avp_code, avp_hdr->avp_vendor);
     185                                if (avp_hdr->avp_value != NULL) {
     186#ifndef HAVE_REG_STARTEND
     187                                        int ret;
     188
     189                                        /* Lock the buffer */
     190                                        CHECK_POSIX( pthread_mutex_lock(&mtx) );
     191
     192                                        /* Augment the buffer if needed */
     193                                        if (avp_hdr->avp_value->os.len >= bufsz) {
     194                                                CHECK_MALLOC_DO( buf = realloc(buf, avp_hdr->avp_value->os.len + 1),
     195                                                        { pthread_mutex_unlock(&mtx); return ENOMEM; } );
     196                                        }
     197
     198                                        /* Copy the AVP value */
     199                                        memcpy(buf, avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len);
     200                                        buf[avp_hdr->avp_value->os.len] = '\0';
     201
     202                                        /* Now apply the rules */
     203                                        ret = proceed(buf, avp_hdr->avp_value->os.len, candidates, conf_index);
     204
     205                                        CHECK_POSIX(pthread_mutex_unlock(&mtx));
     206
     207                                        CHECK_FCT(ret);
     208#else /* HAVE_REG_STARTEND */
     209                                        CHECK_FCT( proceed((char *) avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len, candidates, conf_index) );
     210#endif /* HAVE_REG_STARTEND */
     211                                }
     212                        }
     213                }
     214                CHECK_FCT(fd_msg_browse(nextavp, MSG_BRW_NEXT, (void *)&nextavp, NULL));
     215        }
     216
    124217        return 0;
    125218}
     
    128221static int rtereg_out(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
    129222{
    130         struct msg * msg = *pmsg;
    131         struct avp * avp = NULL;
    132        
    133         TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
    134        
    135         CHECK_PARAMS(msg && candidates);
    136        
     223        msg_or_avp *where;
     224        int j, ret;
     225
     226        TRACE_ENTRY("%p %p %p", cbdata, *pmsg, candidates);
     227
     228        CHECK_PARAMS(pmsg && *pmsg && candidates);
     229
     230        if (pthread_rwlock_rdlock(&rte_lock) != 0) {
     231                fd_log_notice("%s: read-lock failed, skipping handler", MODULE_NAME);
     232                return 0;
     233        }
     234        ret = 0;
    137235        /* Check if it is worth processing the message */
    138         if (FD_IS_LIST_EMPTY(candidates)) {
    139                 return 0;
    140         }
    141        
    142         /* Now search the AVP in the message */
    143         CHECK_FCT( fd_msg_search_avp ( msg, rtereg_conf.avp, &avp ) );
    144         if (avp != NULL) {
    145                 struct avp_hdr * ahdr = NULL;
    146                 CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
    147                 if (ahdr->avp_value != NULL) {
    148 #ifndef HAVE_REG_STARTEND
    149                         int ret;
    150                
    151                         /* Lock the buffer */
    152                         CHECK_POSIX( pthread_mutex_lock(&mtx) );
    153                        
    154                         /* Augment the buffer if needed */
    155                         if (ahdr->avp_value->os.len >= bufsz) {
    156                                 CHECK_MALLOC_DO( buf = realloc(buf, ahdr->avp_value->os.len + 1),
    157                                         { pthread_mutex_unlock(&mtx); return ENOMEM; } );
     236        if (!FD_IS_LIST_EMPTY(candidates)) {
     237                /* Now search the AVPs in the message */
     238
     239                for (j=0; j<rtereg_conf_size; j++) {
     240                        where = *pmsg;
     241                        TRACE_DEBUG(INFO, "[rt_ereg] iterating over AVP group %d", j);
     242                        if ((ret=find_avp(where, j, 0, candidates)) != 0) {
     243                                break;
    158244                        }
    159                        
    160                         /* Copy the AVP value */
    161                         memcpy(buf, ahdr->avp_value->os.data, ahdr->avp_value->os.len);
    162                         buf[ahdr->avp_value->os.len] = '\0';
    163                        
    164                         /* Now apply the rules */
    165                         ret = proceed(buf, ahdr->avp_value->os.len, candidates);
    166                        
    167                         CHECK_POSIX(pthread_mutex_unlock(&mtx));
    168                        
    169                         CHECK_FCT(ret);
    170 #else /* HAVE_REG_STARTEND */
    171                         CHECK_FCT( proceed((char *) ahdr->avp_value->os.data, ahdr->avp_value->os.len, candidates) );
    172 #endif /* HAVE_REG_STARTEND */
    173                 }
    174         }
    175        
    176         return 0;
     245                }
     246        }
     247        if (pthread_rwlock_unlock(&rte_lock) != 0) {
     248                fd_log_notice("%s: read-unlock failed after rtereg_out, exiting", MODULE_NAME);
     249                exit(1);
     250        }
     251
     252        return ret;
    177253}
    178254
     
    180256static struct fd_rt_out_hdl * rtereg_hdl = NULL;
    181257
     258static volatile int in_signal_handler = 0;
     259
     260/* signal handler */
     261static void sig_hdlr(void)
     262{
     263        struct rtereg_conf *old_config;
     264        int old_config_size;
     265
     266        if (in_signal_handler) {
     267                fd_log_error("%s: already handling a signal, ignoring new one", MODULE_NAME);
     268                return;
     269        }
     270        in_signal_handler = 1;
     271
     272        if (pthread_rwlock_wrlock(&rte_lock) != 0) {
     273                fd_log_error("%s: locking failed, aborting config reload", MODULE_NAME);
     274                return;
     275        }
     276
     277        /* save old config in case reload goes wrong */
     278        old_config = rtereg_conf;
     279        old_config_size = rtereg_conf_size;
     280        rtereg_conf = NULL;
     281        rtereg_conf_size = 0;
     282
     283        if (rtereg_init_config() != 0) {
     284                fd_log_notice("%s: error reloading configuration, restoring previous configuration", MODULE_NAME);
     285                rtereg_conf = old_config;
     286                rtereg_conf_size = old_config_size;
     287        } else {
     288                rtereg_conf_free(old_config, old_config_size);
     289        }
     290
     291        if (pthread_rwlock_unlock(&rte_lock) != 0) {
     292                fd_log_error("%s: unlocking failed after config reload, exiting", MODULE_NAME);
     293                exit(1);
     294        }
     295
     296        fd_log_notice("%s: reloaded configuration, %d AVP group%s defined", MODULE_NAME, rtereg_conf_size, rtereg_conf_size != 1 ? "s" : "");
     297
     298        in_signal_handler = 0;
     299}
     300
    182301/* entry point */
    183302static int rtereg_entry(char * conffile)
    184303{
    185304        TRACE_ENTRY("%p", conffile);
    186        
     305
     306        rt_ereg_config_file = conffile;
     307
     308        if (rtereg_init() != 0) {
     309            return 1;
     310        }
     311
     312        /* Register reload callback */
     313        CHECK_FCT(fd_event_trig_regcb(SIGUSR1, MODULE_NAME, sig_hdlr));
     314
     315        fd_log_notice("%s: configured, %d AVP group%s defined", MODULE_NAME, rtereg_conf_size, rtereg_conf_size != 1 ? "s" : "");
     316
     317        return 0;
     318}
     319
     320static int rtereg_init_config(void)
     321{
    187322        /* Initialize the configuration */
    188         memset(&rtereg_conf, 0, sizeof(rtereg_conf));
    189        
     323        if ((rtereg_conf=malloc(sizeof(*rtereg_conf))) == NULL) {
     324            TRACE_DEBUG(INFO, "malloc failured");
     325            return 1;
     326        }
     327        rtereg_conf_size = 1;
     328        memset(rtereg_conf, 0, sizeof(*rtereg_conf));
     329
    190330        /* Parse the configuration file */
    191         CHECK_FCT( rtereg_conf_handle(conffile) );
    192        
     331        CHECK_FCT( rtereg_conf_handle(rt_ereg_config_file) );
     332
     333        return 0;
     334}
     335
     336
     337/* Load */
     338static int rtereg_init(void)
     339{
     340        int ret;
     341
     342        pthread_rwlock_init(&rte_lock, NULL);
     343
     344        if (pthread_rwlock_wrlock(&rte_lock) != 0) {
     345                fd_log_notice("%s: write-lock failed, aborting", MODULE_NAME);
     346                return EDEADLK;
     347        }
     348
     349        if ((ret=rtereg_init_config()) != 0) {
     350                pthread_rwlock_unlock(&rte_lock);
     351                return ret;
     352        }
     353
     354        if (pthread_rwlock_unlock(&rte_lock) != 0) {
     355                fd_log_notice("%s: write-unlock failed, aborting", MODULE_NAME);
     356                return EDEADLK;
     357        }
     358
    193359        /* Register the callback */
    194360        CHECK_FCT( fd_rt_out_register( rtereg_out, NULL, 1, &rtereg_hdl ) );
    195        
     361
    196362        /* We're done */
    197363        return 0;
     
    199365
    200366/* Unload */
    201 void fd_ext_fini(void)
    202 {
    203         int i;
     367static void rtereg_fini(void)
     368{
    204369        TRACE_ENTRY();
    205        
     370
    206371        /* Unregister the cb */
    207372        CHECK_FCT_DO( fd_rt_out_unregister ( rtereg_hdl, NULL ), /* continue */ );
    208        
     373
    209374        /* Destroy the data */
    210         if (rtereg_conf.rules)
    211                 for (i = 0; i < rtereg_conf.rules_nb; i++) {
    212                         free(rtereg_conf.rules[i].pattern);
    213                         free(rtereg_conf.rules[i].server);
    214                         regfree(&rtereg_conf.rules[i].preg);
    215                 }
    216         free(rtereg_conf.rules);
     375        rtereg_conf_free(rtereg_conf, rtereg_conf_size);
     376        rtereg_conf = NULL;
     377        rtereg_conf_size = 0;
    217378#ifndef HAVE_REG_STARTEND
    218379        free(buf);
     380        buf = NULL;
    219381#endif /* HAVE_REG_STARTEND */
    220        
     382
    221383        /* Done */
    222384        return ;
    223385}
    224386
    225 EXTENSION_ENTRY("rt_ereg", rtereg_entry);
     387void fd_ext_fini(void)
     388{
     389        rtereg_fini();
     390}
     391
     392EXTENSION_ENTRY(MODULE_NAME, rtereg_entry);
  • extensions/rt_ereg/rtereg.h

    r741 r1338  
    5858        int                     rules_nb; /* Number of rules in the configuration */
    5959        struct rtereg_rule      *rules;   /* The array of rules */
     60
     61        int                     level;    /* how many levels of AVPs we have to dig down into */
     62        int                     finished; /* AVP fully configured, for configuration file reading */
     63        struct dict_object      **avps;   /* cache the dictionary objects that we are searching */
    6064       
    61         struct dict_object * avp; /* cache the dictionary object that we are searching */
    62        
    63 } rtereg_conf;
     65} *rtereg_conf;
    6466
     67extern int rtereg_conf_size;
  • extensions/rt_ereg/rtereg_conf.y

    r1127 r1338  
    3838
    3939/* For development only : */
    40 %debug 
     40%debug
    4141%error-verbose
    4242
     
    4545
    4646/* Keep track of location */
    47 %locations 
     47%locations
    4848%pure-parser
    4949
     
    5454/* Forward declaration */
    5555int yyparse(char * conffile);
     56void rtereg_confrestart(FILE *input_file);
    5657
    5758/* Parse the configuration file */
     
    6061        extern FILE * rtereg_confin;
    6162        int ret;
    62        
     63
    6364        TRACE_ENTRY("%p", conffile);
    64        
     65
    6566        TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
    66        
     67
    6768        rtereg_confin = fopen(conffile, "r");
    6869        if (rtereg_confin == NULL) {
    6970                ret = errno;
    7071                fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
    71                 TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
     72                TRACE_DEBUG (INFO, "rt_ereg: error occurred, message logged -- configuration file.");
    7273                return ret;
    7374        }
    7475
     76        rtereg_confrestart(rtereg_confin);
    7577        ret = yyparse(conffile);
    7678
    7779        fclose(rtereg_confin);
    7880
     81        if (rtereg_conf[rtereg_conf_size-1].finished == 0) {
     82                TRACE_DEBUG(INFO, "rt_ereg: configuration invalid, AVP ended without OCTETSTRING AVP");
     83                return EINVAL;
     84        }
     85
    7986        if (ret != 0) {
    80                 TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
     87                TRACE_DEBUG(INFO, "rt_ereg: unable to parse the configuration file.");
    8188                return EINVAL;
    8289        } else {
    83                 TRACE_DEBUG(FULL, "[rt-ereg] Added %d rules successfully.", rtereg_conf.rules_nb);
    84         }
    85        
     90                int i, sum = 0;
     91                for (i=0; i<rtereg_conf_size; i++) {
     92                        sum += rtereg_conf[i].rules_nb;
     93                }
     94                TRACE_DEBUG(FULL, "[rt-ereg] Added %d rules successfully.", sum);
     95        }
     96
     97        return 0;
     98}
     99
     100int avp_add(const char *name)
     101{
     102        void *ret;
     103        int level;
     104
     105        if (rtereg_conf[rtereg_conf_size-1].finished) {
     106                if ((ret = realloc(rtereg_conf, sizeof(*rtereg_conf)*(rtereg_conf_size+1))) == NULL) {
     107                        TRACE_DEBUG(INFO, "rt_ereg: realloc failed");
     108                        return -1;
     109                }
     110                rtereg_conf_size++;
     111                rtereg_conf = ret;
     112                memset(&rtereg_conf[rtereg_conf_size-1], 0, sizeof(*rtereg_conf));
     113                TRACE_DEBUG(INFO, "rt_ereg: New AVP group found starting with %s", name);
     114        }
     115        level = rtereg_conf[rtereg_conf_size-1].level + 1;
     116
     117        if ((ret = realloc(rtereg_conf[rtereg_conf_size-1].avps, sizeof(*rtereg_conf[rtereg_conf_size-1].avps)*level)) == NULL) {
     118                TRACE_DEBUG(INFO, "rt_ereg: realloc failed");
     119                return -1;
     120        }
     121        rtereg_conf[rtereg_conf_size-1].avps = ret;
     122
     123        CHECK_FCT_DO( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, name, &rtereg_conf[rtereg_conf_size-1].avps[level-1], ENOENT ),
     124                      {
     125                              TRACE_DEBUG(INFO, "rt_ereg: Unable to find '%s' AVP in the loaded dictionaries.", name);
     126                              return -1;
     127                      } );
     128
     129        /* Now check the type */
     130        {
     131                struct dict_avp_data data;
     132                CHECK_FCT( fd_dict_getval( rtereg_conf[rtereg_conf_size-1].avps[level-1], &data) );
     133                if (data.avp_basetype == AVP_TYPE_OCTETSTRING) {
     134                        rtereg_conf[rtereg_conf_size-1].finished = 1;
     135                } else if (data.avp_basetype != AVP_TYPE_GROUPED) {
     136                        TRACE_DEBUG(INFO, "rt_ereg: '%s' AVP is not an OCTETSTRING nor GROUPED AVP (%d).", name, data.avp_basetype);
     137                        return -1;
     138                }
     139        }
     140        rtereg_conf[rtereg_conf_size-1].level = level;
    86141        return 0;
    87142}
     
    93148void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
    94149{
    95         TRACE_DEBUG(INFO, "Error in configuration parsing");
    96        
     150        TRACE_DEBUG(INFO, "rt_ereg: error in configuration parsing");
     151
    97152        if (ploc->first_line != ploc->last_line)
    98153                fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
     
    126181
    127182        /* The grammar definition */
    128 conffile:               rules avp rules
    129                         ;
    130                        
     183conffile:               avp rules
     184                        | conffile avp rules
     185                        ;
     186
    131187        /* a server entry */
    132 avp:                    AVP '=' QSTRING ';'
    133                         {
    134                                 if (rtereg_conf.avp != NULL) {
    135                                         yyerror(&yylloc, conffile, "Only one AVP can be specified");
    136                                         YYERROR;
    137                                 }
    138                                
    139                                 CHECK_FCT_DO( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, $3, &rtereg_conf.avp, ENOENT ),
    140                                         {
    141                                                 TRACE_DEBUG(INFO, "Unable to find '%s' AVP in the loaded dictionaries.", $3);
    142                                                 yyerror (&yylloc, conffile, "Invalid AVP value.");
    143                                                 YYERROR;
    144                                         } );
    145                                
    146                                 /* Now check the type */
    147                                 {
    148                                         struct dict_avp_data data;
    149                                         CHECK_FCT( fd_dict_getval( rtereg_conf.avp, &data) );
    150                                         CHECK_PARAMS_DO (data.avp_basetype == AVP_TYPE_OCTETSTRING,
    151                                                 {
    152                                                         TRACE_DEBUG(INFO, "'%s' AVP in not an OCTETSTRING AVP (%d).", $3, data.avp_basetype);
    153                                                         yyerror (&yylloc, conffile, "AVP in not an OCTETSTRING type.");
    154                                                         YYERROR;
    155                                                 } );
    156                                 }
    157                         }
    158                         ;
    159                        
     188avp:                    AVP '=' avp_part ';'
     189                        ;
     190
     191avp_part:               avp_part ':' QSTRING { if (avp_add($3) < 0) { YYERROR; } }
     192                        | QSTRING { if (avp_add($1) < 0) { YYERROR; } }
     193                        ;
     194
    160195rules:                  /* empty OK */
    161196                        | rules rule
    162197                        ;
    163                        
     198
    164199rule:                   QSTRING ':' QSTRING '+' '=' INTEGER ';'
    165200                        {
    166201                                struct rtereg_rule * new;
    167202                                int err;
    168                                
     203
    169204                                /* Add new rule in the array */
    170                                 rtereg_conf.rules_nb += 1;
    171                                 CHECK_MALLOC_DO(rtereg_conf.rules = realloc(rtereg_conf.rules, rtereg_conf.rules_nb * sizeof(struct rtereg_rule)),
     205                                rtereg_conf[rtereg_conf_size-1].rules_nb += 1;
     206                                CHECK_MALLOC_DO(rtereg_conf[rtereg_conf_size-1].rules = realloc(rtereg_conf[rtereg_conf_size-1].rules, rtereg_conf[rtereg_conf_size-1].rules_nb * sizeof(struct rtereg_rule)),
    172207                                        {
    173208                                                yyerror (&yylloc, conffile, "Not enough memory to store the configuration...");
    174209                                                YYERROR;
    175210                                        } );
    176                                
    177                                 new = &rtereg_conf.rules[rtereg_conf.rules_nb - 1];
    178                                
     211
     212                                new = &rtereg_conf[rtereg_conf_size-1].rules[rtereg_conf[rtereg_conf_size-1].rules_nb - 1];
     213
    179214                                new->pattern = $1;
    180215                                new->server  = $3;
    181216                                new->score   = $6;
    182                                
     217
    183218                                /* Attempt to compile the regex */
    184219                                CHECK_FCT_DO( err=regcomp(&new->preg, new->pattern, REG_EXTENDED | REG_NOSUB),
     
    188223
    189224                                                /* Error while compiling the regex */
    190                                                 TRACE_DEBUG(INFO, "Error while compiling the regular expression '%s':", new->pattern);
     225                                                TRACE_DEBUG(INFO, "rt_ereg: error while compiling the regular expression '%s':", new->pattern);
    191226
    192227                                                /* Get the error message size */
     
    199234                                                regerror(err, &new->preg, buf, bl);
    200235                                                TRACE_DEBUG(INFO, "\t%s", buf);
    201                                                
     236
    202237                                                /* Free the buffer, return the error */
    203238                                                free(buf);
    204                                                
     239
    205240                                                yyerror (&yylloc, conffile, "Invalid regular expression.");
    206241                                                YYERROR;
Note: See TracChangeset for help on using the changeset viewer.