# HG changeset patch # User Sebastien Decugis # Date 1271663892 -32400 # Node ID c78f623c702d6f70cc55518af0c443fb34847323 # Parent b364ffffa2ed547b29282c205abcdff94f39150a Ported the Echo/Drop plugin from waaad (missing files) diff -r b364ffffa2ed -r c78f623c702d doc/echodrop.rgwx.conf.sample --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/echodrop.rgwx.conf.sample Mon Apr 19 16:58:12 2010 +0900 @@ -0,0 +1,35 @@ +# Sample configuration file for the echodrop.rgwx plugin of RADIUS/Diameter translation agent. +# +# This plugin allows to easily specify the following handling of RADIUS attributes +# received in a RADIUS request: +# - ECHO: the attribute will be copied verbatim in the RADIUS answer. +# - DROP: the attribute is discarded. +# +# In both cases, the attribute is NOT translated in Diameter message. +# +# The format of this file is: +# CODE [ VENDOR [ TLV | EXT ] ]; +# Where: +# : is either DROP or ECHO. +# : is a (decimal) integer between 0 and 255, and designates the type of the attribute. +# +# The remaining of the line is optional, and should only be used +# with lines containing "CODE 26" (Vendor-Specific Attribute) +# : a Vendor value (32 bit), see RFC2865 section 5.26 for detail. +# +# : The attribute is interpreted as TLV (rfc3865, section 5.26) +# and we match only this "vendor type" value (8 bits). +# +# : NOTE: THIS OPTION IS NOT SUPPORTED PROPERLY YET!!!! +# The attribute is interpreted as extended attribute (draft-ietf-radext-extended-attributes-08) +# and we match only this "Ext-Type" value (16 bits). +# This option should only be used with "CODE 26 VENDOR 0". +# + +# Examples: +# ECHO code 25 ; # Class attributes +# DROP code 18 ; # Reply-Message attribute, should not be included in requests +# DROP code 26 vendor 9 ; # Drop any Cisco-specific attribute +# ECHO code 26 vendor 0 ext 256 ; # Echo any extended attribute with the type 256. + +ECHO code 33 ; # RADIUS Proxy-State attribute diff -r b364ffffa2ed -r c78f623c702d extensions/app_radgw/rgwx_echodrop.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/app_radgw/rgwx_echodrop.c Mon Apr 19 16:58:12 2010 +0900 @@ -0,0 +1,286 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2009, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* See rgwx_echodrop.h for details */ + +#include "rgwx_echodrop.h" + +/* If a session is destroyed, empty the list of ed_saved_attribute */ +static void state_delete(void * arg) { + struct fd_list * list = (struct fd_list *)arg; + + CHECK_PARAMS_DO( list, return ); + + while (!FD_IS_LIST_EMPTY(list)) { + struct ed_saved_attribute * esa = (struct ed_saved_attribute *)(list->next); + fd_list_unlink(&esa->chain); + free(esa); + } + free(list); +} + + +/* Initialize the plugin and parse the configuration. */ +static int ed_conf_parse(char * conffile, struct rgwp_config ** state) +{ + struct rgwp_config * new; + + TRACE_ENTRY("%p %p", conffile, state); + CHECK_PARAMS( state ); + CHECK_PARAMS_DO( conffile, { fd_log_debug("[echodrop.rgwx] The configuration file is not optional for this plugin.\n"); return EINVAL; } ); + + CHECK_MALLOC( new = malloc(sizeof(struct rgwp_config)) ); + memset(new, 0, sizeof(struct rgwp_config)); + + /* Initialize the list of attributes to handle */ + fd_list_init(&new->attributes, NULL); + + /* Create the session handler */ + CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, state_delete ) ); + + /* Parse the configuration file */ + CHECK_FCT( ed_conffile_parse(conffile, new) ); + + if (TRACE_BOOL(FULL)) { + TRACE_DEBUG(INFO, "Echo/Drop plugin configuration ('%s'):", conffile); + struct fd_list * li; + + for (li = new->attributes.next; li != &new->attributes; li = li->next) { + struct ed_conf_attribute * eca = (struct ed_conf_attribute *)li; + char * act = (eca->action == ACT_ECHO) ? "ECHO" : "DROP"; + if (eca->ext) { + fd_log_debug(" %s Code: %hhu, Vendor: %u, Ext-Type: %hu\n", act, eca->code, eca->vendor_id, eca->extype); + continue; + } + if (eca->tlv) { + fd_log_debug(" %s Code: %hhu, Vendor: %u, Type: %hhu\n", act, eca->code, eca->vendor_id, eca->type); + continue; + } + if (eca->vsa) { + fd_log_debug(" %s Code: %hhu, Vendor: %u\n", act, eca->code, eca->vendor_id); + continue; + } + fd_log_debug(" %s Code: %hhu\n", act, eca->code); + } + } + + /* OK, we are done */ + *state = new; + return 0; +} + +/* Destroy the state */ +static void ed_conf_free(struct rgwp_config * state) +{ + TRACE_ENTRY("%p", state); + CHECK_PARAMS_DO( state, return ); + CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl ), ); + while (! FD_IS_LIST_EMPTY(&state->attributes) ) { + struct fd_list * li = state->attributes.next; + fd_list_unlink(li); + free(li); + } + free(state); + return; +} + + +/* Handle attributes from a RADIUS request as specified in the configuration */ +static int ed_rad_req( struct rgwp_config * cs, struct session * session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli ) +{ + size_t nattr_used = 0; + int idx; + + struct fd_list echo_list = FD_LIST_INITIALIZER(echo_list); + struct fd_list *li; + + TRACE_ENTRY("%p %p %p %p %p %p", cs, session, rad_req, rad_ans, diam_fw, cli); + CHECK_PARAMS(cs && rad_req); + + /* For each attribute in the original message */ + for (idx = 0; idx < rad_req->attr_used; idx++) { + int action = 0; + struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]); + + /* Look if we have a matching attribute in our configuration */ + for (li = cs->attributes.next; li != &cs->attributes; li = li->next) { + struct ed_conf_attribute * eca = (struct ed_conf_attribute *)li; + uint32_t vid; + unsigned char * ptr; + + if (eca->code < attr->type) + continue; + if (eca->code > attr->type) + break; + + /* the code matches one in our configuration, check additional data if needed */ + + if (! eca->vsa) { + action = eca->action; + break; + } + + if (attr->length < 8) + continue; + + ptr = (unsigned char *)(attr + 1); + /* since attr is not aligned, we may not access *(attr+1) directly */ + memcpy(&vid, ptr, sizeof(uint32_t)); + + if (eca->vendor_id < ntohl(vid)) + continue; + if (eca->vendor_id > ntohl(vid)) + break; + + /* The vendor matches our configured line... */ + + if ( ! eca->tlv && ! eca->ext ) { + action = eca->action; + break; + } + + if (attr->length < 10) + continue; + + if (eca->tlv) { + struct radius_attr_vendor * tl = (struct radius_attr_vendor *)(ptr + sizeof(uint32_t)); + if (tl->vendor_type == eca->type) { + action = eca->action; + break; + } + continue; + } + + if (eca->ext) { + /* To be done */ + fd_log_debug("Extended attributes are not implemented yet!\n"); + ASSERT(0); + continue; + } + } + + switch (action) { + case ACT_DROP: + TRACE_DEBUG(FULL, "Dropping attribute with code %hhd", attr->type); + break; + + case ACT_ECHO: + { + struct ed_saved_attribute * esa = NULL; + TRACE_DEBUG(FULL, "Saving attribute with code %hhd", attr->type); + CHECK_MALLOC( esa = malloc(sizeof(struct ed_saved_attribute) + attr->length - sizeof(struct radius_attr_hdr)) ); + fd_list_init(&esa->chain, NULL); + memcpy(&esa->attr, attr, attr->length); + fd_list_insert_before(&echo_list, &esa->chain); + } + break; + + default: /* Attribute was not specified in the configuration */ + /* We just keep the attribute in the RADIUS message */ + rad_req->attr_pos[nattr_used++] = rad_req->attr_pos[idx]; + } + } + rad_req->attr_used = nattr_used; + + /* Save the echoed values in the session, if any */ + if (!FD_IS_LIST_EMPTY(&echo_list)) { + CHECK_PARAMS(session); + + /* Move the values in a dynamically allocated list */ + CHECK_MALLOC( li = malloc(sizeof(struct fd_list)) ); + fd_list_init(li, NULL); + fd_list_move_end(li, &echo_list); + + /* Save the list in the session */ + CHECK_FCT( fd_sess_state_store( cs->sess_hdl, session, &li ) ); + } + + return 0; +} + +/* Process an answer: add the ECHO attributes back, if any */ +static int ed_diam_ans( struct rgwp_config * cs, struct session * session, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli ) +{ + int ret; + struct fd_list * list = NULL; + + TRACE_ENTRY("%p %p %p %p %p", cs, session, diam_ans, rad_fw, cli); + CHECK_PARAMS(cs); + + /* If there is no session associated, just give up */ + if (! session ) { + TRACE_DEBUG(FULL, "No session associated with the message, nothing to do here..."); + return 0; + } + + /* Now try and retrieve any data from the session */ + CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, session, &list ) ); + if (list == NULL) { + /* No attribute saved in the session, just return */ + return 0; + } + + /* From this point on, we have a list of attributes to add to the radius message */ + + CHECK_PARAMS( rad_fw && *rad_fw); + + while (! FD_IS_LIST_EMPTY(list) ) { + struct ed_saved_attribute * esa = (struct ed_saved_attribute *)(list->next); + struct radius_attr_hdr * rc; + + fd_list_unlink(&esa->chain); + + TRACE_DEBUG(FULL, "Echo attribute in the RADIUS answer: type %hhu, len: %hhu", esa->attr.type, esa->attr.length); + + /* Add this attribute in the RADIUS message */ + CHECK_MALLOC( radius_msg_add_attr(*rad_fw, esa->attr.type, (unsigned char *)(esa + 1), esa->attr.length - sizeof(struct radius_attr_hdr)) ); + + free(esa); + } + free(list); + + return 0; +} + + + +/* The exported symbol */ +struct rgw_api rgwp_descriptor = { + .rgwp_name = "echo/drop", + .rgwp_conf_parse = ed_conf_parse, + .rgwp_conf_free = ed_conf_free, + .rgwp_rad_req = ed_rad_req, + .rgwp_diam_ans = ed_diam_ans +}; diff -r b364ffffa2ed -r c78f623c702d extensions/app_radgw/rgwx_echodrop.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/app_radgw/rgwx_echodrop.h Mon Apr 19 16:58:12 2010 +0900 @@ -0,0 +1,84 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2010, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* RADIUS translation plugin, to handle specific RADIUS attributes by either caching them and +adding them to a corresponding RADIUS reply, or just dropping the attributes (no conversion to Diameter) */ +/* This extension is a kind of swiss army-knife for interoperability, must be used with care. + All attribute behaviors are specified through the configuration file of the extension + */ + +#include "rgw_common.h" + +/* Action associated with an attribute */ +#define ACT_ECHO 1 +#define ACT_DROP 2 + +/* Result of configuration parsing */ +struct rgwp_config { + /* list of attributes and associated actions */ + struct fd_list attributes; + + /* Handler to store the echo'ed attributes values */ + struct session_handler * sess_hdl; +}; + +/* An item of the attribute list */ +struct ed_conf_attribute { + struct fd_list chain; /* link in the list */ + + struct { + unsigned action :2; /* ACT_ECHO or ACT_DROP */ + unsigned vsa :1; /* Interpret as Vendor-Specific, and match the vendor id in addition to the code */ + unsigned tlv :1; /* Interpret as Vendor-Specific with TLV format, and match the type also */ + unsigned ext :1; /* Interpret as radius extended attribute, and match the ext-type also */ + }; + + uint32_t vendor_id; /* vendor id to match when vsa = 1 */ + uint16_t extype; /* Ext-Type value to match if ext = 1 */ + uint8_t type; /* Type value to match if tlv = 1; */ + + uint8_t code; /* The attribute code, the list is ordered by this value */ +}; + +/* For ECHO items, we save a list of these in the session */ +struct ed_saved_attribute { + struct fd_list chain; + struct radius_attr_hdr attr; /* copy of the attribute */ + /* The data of the attribute follows ... */ +}; + + +/* The yacc parser */ +int ed_conffile_parse(char * conffile, struct rgwp_config *cs); diff -r b364ffffa2ed -r c78f623c702d extensions/app_radgw/rgwx_echodrop.l --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/app_radgw/rgwx_echodrop.l Mon Apr 19 16:58:12 2010 +0900 @@ -0,0 +1,99 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2009, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Tokenizer for echo/drop plugin */ + +%{ +#include "rgwx_echodrop.h" +#include "rgwx_echodrop.tab.h" + +/* Update the column information */ +#define YY_USER_ACTION { \ + yylloc->first_column = yylloc->last_column + 1; \ + yylloc->last_column = yylloc->first_column + yyleng - 1; \ +} + +/* %option noinput ? */ +#define YY_NO_INPUT +%} + +%option bison-bridge bison-locations +%option noyywrap +%option nounput + +%% + +<*>\n { + /* Update the line count */ + yylloc->first_line++; + yylloc->last_line++; + yylloc->last_column=0; + } + +<*>([[:space:]]{-}[\n])+ ; /* Eat all spaces, not new lines */ +<*>#.*$ ; /* Eat all comments */ + +[[:digit:]]+ { + /* Match an integer (not hexa) */ + int ret = sscanf(yytext, "%d", &yylval->integer); + if (ret != 1) { + /* No matching: an error occurred */ + fd_log_debug("[echodrop.rgwx] Unable to convert the value '%s' to a valid number: %s\n", yytext, strerror(errno)); + return LEX_ERROR; /* trig an error in yacc parser */ + /* Maybe we could REJECT instead of failing here? */ + } + return INTEGER; + } + +(?i:"echo") { return TOK_ECHO; } +(?i:"drop") { return TOK_DROP; } +(?i:"code") { return TOK_CODE; } +(?i:"vendor") { return TOK_VENDOR; } +(?i:"tlv") { return TOK_TLV; } +(?i:"ext") { return TOK_EXT; } + + /* Valid single characters for yyparse */ +<*>[;] { return yytext[0]; } + + + /* Unrecognized token */ +<*>[[:alnum:]]+ | /* This rule is only useful to print a complete token in error messages */ + /* Unrecognized character */ +<*>. { + fd_log_debug("[echodrop.rgwx] Unrecognized text on line %d col %d: '%s'.\n", yylloc->first_line, yylloc->first_column, yytext); + return LEX_ERROR; + } + +%% diff -r b364ffffa2ed -r c78f623c702d extensions/app_radgw/rgwx_echodrop.y --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/app_radgw/rgwx_echodrop.y Mon Apr 19 16:58:12 2010 +0900 @@ -0,0 +1,240 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2009, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Yacc parser for echo/drop plugin. +See doc/echodrop.rgwx.conf.sample for description of the parsed format. */ + + +/* For development only : */ +%debug +%error-verbose + +/* The parser receives the configuration file filename and the conf structure as parameter */ +%parse-param {char * conffile} +%parse-param {struct rgwp_config *cs} + +/* Keep track of location */ +%locations +%pure-parser + +%{ +#include "rgwx_echodrop.h" +#include "rgwx_echodrop.tab.h" /* bison is not smart enough to define the YYLTYPE before including this code, so... */ + +/* Parse the configuration file */ +int ed_conffile_parse(char * conffile, struct rgwp_config *cs) +{ + extern FILE * rgwx_echodropin; + int ret; + + rgwx_echodropin = fopen(conffile, "r"); + if (rgwx_echodropin == NULL) { + ret = errno; + fd_log_debug("[echodrop.rgwx] Unable to open plugin configuration file %s for reading: %s\n", conffile, strerror(ret)); + return ret; + } + + ret = rgwx_echodropparse(conffile, cs); + + fclose(rgwx_echodropin); + + if (ret != 0) { + return EINVAL; + } + + return 0; +} + +/* Function to report the errors */ +void yyerror (YYLTYPE *ploc, char * conffile, struct rgwp_config *cs, char const *s) +{ + if (ploc->first_line != ploc->last_line) + fd_log_debug("%s:%d.%d-%d.%d : %s\n", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s); + else if (ploc->first_column != ploc->last_column) + fd_log_debug("%s:%d.%d-%d : %s\n", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s); + else + fd_log_debug("%s:%d.%d : %s\n", conffile, ploc->first_line, ploc->first_column, s); +} + +static struct { + struct { + unsigned vendor :1; + unsigned tlv :1; + unsigned ext :1; + }; + uint8_t type; + uint16_t extype; + uint32_t vendor_id; +} attrinfo; + + +%} + +/* Values returned by lex for tokens */ +%union { + unsigned integer; /* Value */ +} + +/* typed data */ +%token INTEGER +%type action + +/* simple tokens */ +%token TOK_ECHO +%token TOK_DROP +%token TOK_CODE +%token TOK_VENDOR +%token TOK_TLV +%token TOK_EXT + +/* In case of error in the lexical analysis */ +%token LEX_ERROR + + +/* -------------------------------------- */ +%% + + /* The grammar definition */ +conffile: /* empty grammar is OK */ + | conffile attrdef + ; + + /* An attribute line */ +attrdef: { + memset(&attrinfo, 0, sizeof(attrinfo)); + } + action TOK_CODE INTEGER vendordef ';' + { + struct ed_conf_attribute * new; + struct fd_list * li; + + if ($4 >= 256) { + yyerror (&yylloc, conffile, cs, "Too big value for attribute CODE"); + YYERROR; + } + + /* Create a new list item */ + CHECK_MALLOC_DO( new = malloc(sizeof(struct ed_conf_attribute)), + { + yyerror (&yylloc, conffile, cs, "Memory allocation error"); + YYERROR; + } ); + memset(new, 0, sizeof(struct ed_conf_attribute)); + + fd_list_init(&new->chain, NULL); + + new->action = $2; + new->vsa = attrinfo.vendor; + new->tlv = attrinfo.tlv; + new->ext = attrinfo.ext; + + if (new->vsa) + new->vendor_id = attrinfo.vendor_id; + if (new->tlv) + new->type = attrinfo.type; + if (new->ext) + new->extype = attrinfo.extype; + + new->code = $4; + + /* Now place this attribute in the list */ + for (li = cs->attributes.next; li != &cs->attributes; li = li->next) { + struct ed_conf_attribute *eca = (struct ed_conf_attribute *)li; + /* Order first by attribute code */ + if (eca->code > new->code) + break; + if (eca->code < new->code) + continue; + + /* Then by VSA flag */ + if (! new->vsa) + break; + if (! eca->vsa) + continue; + + /* Then by vendor value */ + if (eca->vendor_id >= new->vendor_id) + break; + } + + fd_list_insert_before(li, &new->chain); + } + ; + + /* What to do with the specified attribute */ +action: TOK_ECHO + { + $$ = ACT_ECHO; + } + | + TOK_DROP + { + $$ = ACT_DROP; + } + ; + + /* Vendor specifics, if any */ +vendordef: /* empty OK */ + | TOK_VENDOR INTEGER specif + { + attrinfo.vendor_id = $2; + attrinfo.vendor = 1; + } + ; + + /* Any additional specification ? */ +specif: /* empty OK */ + | TOK_TLV INTEGER + { + if ($2 >= (1 << 8)) { + yyerror (&yylloc, conffile, cs, "Too big value for TLV type"); + YYERROR; + } + attrinfo.type = $2; + attrinfo.tlv = 1; + } + | TOK_EXT INTEGER + { + if ($2 >= (1 << 16)) { + yyerror (&yylloc, conffile, cs, "Too big value for Ext-Type"); + YYERROR; + } + attrinfo.extype = $2; + attrinfo.ext = 1; + yyerror (&yylloc, conffile, cs, "The EXT option is not supported in this version."); + YYERROR; + } + ; +