# HG changeset patch # User Thomas Klausner # Date 1554818232 -7200 # Node ID daf61e573feeb3485ef4e95555e4c9df768c20be # Parent e70ce64ce6893e215621778e3680994ba761d5ad rt_deny_by_size: new extension This extension denies messages that are larger than a configured size. The size is configurable in a config file, and the extension allows reloading its config using SIGUSR1. Written for Effortel Technologies SA and published with their consent. diff -r e70ce64ce689 -r daf61e573fee doc/rt_deny_by_size.conf.sample --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/rt_deny_by_size.conf.sample Tue Apr 09 15:57:12 2019 +0200 @@ -0,0 +1,11 @@ +# This file contains information for configuring the rt_deny_by_size extension. +# +# The rt_deny_by_size extension returns errors for messages above a particular size. +# +# This extension supports configuration reload at runtime. Send +# signal SIGUSR1 to the process to cause the process to reload its +# config. +# +# Configure the maximum allowed message size to still pass through; +# defaults to 4096, if config file is empty +#MaximumSize=4096; diff -r e70ce64ce689 -r daf61e573fee extensions/CMakeLists.txt --- a/extensions/CMakeLists.txt Tue Apr 09 15:49:17 2019 +0200 +++ b/extensions/CMakeLists.txt Tue Apr 09 15:57:12 2019 +0200 @@ -70,6 +70,7 @@ FD_EXTENSION_SUBDIR(rt_busypeers "Handling of Diameter TOO_BUSY messages and relay timeouts" ON) FD_EXTENSION_SUBDIR(rt_default "Configurable routing rules for freeDiameter" ON) +FD_EXTENSION_SUBDIR(rt_deny_by_size "Deny messages that are larger than a configured size" ON) FD_EXTENSION_SUBDIR(rt_ereg "Configurable routing based on regexp matching of AVP values" OFF) FD_EXTENSION_SUBDIR(rt_ignore_dh "Stow Destination-Host in Proxy-Info, restore to Origin-Host for answers" ON) FD_EXTENSION_SUBDIR(rt_load_balance "Balance load over multiple equal hosts, based on outstanding requests" ON) diff -r e70ce64ce689 -r daf61e573fee extensions/rt_deny_by_size/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/rt_deny_by_size/CMakeLists.txt Tue Apr 09 15:57:12 2019 +0200 @@ -0,0 +1,29 @@ +# The rt_deny_by_size extension +PROJECT("Routing extension to deny messages that are over a particular size" C) + +# Parser files +BISON_FILE(rt_deny_by_size_conf.y) +FLEX_FILE(rt_deny_by_size_conf.l) +SET_SOURCE_FILES_PROPERTIES(lex.rt_deny_by_size_conf.c rt_deny_by_size_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}") + +# List of source files +SET( RT_DENY_BY_SIZE_SRC + rt_deny_by_size.c + rt_deny_by_size.h + lex.rt_deny_by_size_conf.c + rt_deny_by_size_conf.tab.c + rt_deny_by_size_conf.tab.h +) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + +# Compile these files as a freeDiameter extension +FD_ADD_EXTENSION(rt_deny_by_size ${RT_DENY_BY_SIZE_SRC}) + +#### +## INSTALL section ## + +# We install with the daemon component because it is a base feature. +INSTALL(TARGETS rt_deny_by_size + LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX} + COMPONENT freeDiameter-daemon) diff -r e70ce64ce689 -r daf61e573fee extensions/rt_deny_by_size/rt_deny_by_size.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/rt_deny_by_size/rt_deny_by_size.c Tue Apr 09 15:57:12 2019 +0200 @@ -0,0 +1,122 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Thomas Klausner * +* * +* Copyright (c) 2018, Thomas Klausner * +* All rights reserved. * +* * +* Written under contract by Effortel Technologies SA, http://effortel.com/ * +* * +* 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. * +*********************************************************************************************************/ + +#include + +/* See doc/rt_deny_by_size.conf.sample for more details about the features of this extension */ +#include "rt_deny_by_size.h" + +/* The configuration structure */ +struct rt_deny_by_size_conf rt_deny_by_size_conf; + +static struct fd_rt_fwd_hdl * rt__deny_by_size_hdl = NULL; +static char *config_file = NULL; +#define MODULE_NAME "rt_deny_by_size" +#define DEFAULT_MAX_SIZE 4096; + +/* the routing callback that handles all the tasks of this extension */ +static int rt_deny_by_size_fwd_cb(void * cbdata, struct msg ** pmsg) +{ + struct msg_hdr * hdr; + + /* Get the header of the message */ + CHECK_FCT(fd_msg_hdr(*pmsg, &hdr)); + + if (hdr->msg_length > rt_deny_by_size_conf.maximum_size) { + if (hdr->msg_flags & CMD_FLAG_REQUEST) { + /* Create an answer */ + CHECK_FCT(fd_msg_new_answer_from_req(fd_g_config->cnf_dict, pmsg, MSGFL_ANSW_ERROR)); + CHECK_FCT(fd_msg_rescode_set(*pmsg, "DIAMETER_UNABLE_TO_COMPLY", "[rt_deny_by_size] Message is too big", NULL, 2)); + CHECK_FCT( fd_msg_send(pmsg, NULL, NULL) ); + } + } + + return 0; +} + +static void sig_hdlr(void) +{ + int old_maximum_size; + + old_maximum_size = rt_deny_by_size_conf.maximum_size; + if (rt_deny_by_size_conf_handle(config_file) != 0) { + fd_log_error("%s: error during config file reload, restoring previous value", MODULE_NAME); + rt_deny_by_size_conf.maximum_size = old_maximum_size; + } + fd_log_notice("%s: reloaded configuration, maximum size now %d", MODULE_NAME, rt_deny_by_size_conf.maximum_size); +} + +/* entry point */ +static int rt_deny_by_size_entry(char * conffile) +{ + TRACE_ENTRY("%p", conffile); + + config_file = conffile; + /* Initialize the configuration */ + memset(&rt_deny_by_size_conf, 0, sizeof(rt_deny_by_size_conf)); + rt_deny_by_size_conf.maximum_size = DEFAULT_MAX_SIZE; + + /* Parse the configuration file */ + CHECK_FCT(rt_deny_by_size_conf_handle(config_file)); + + /* Register the callback */ + CHECK_FCT(fd_rt_fwd_register(rt_deny_by_size_fwd_cb, NULL, RT_FWD_REQ, &rt__deny_by_size_hdl)); + + /* Register reload callback */ + CHECK_FCT(fd_event_trig_regcb(SIGUSR1, MODULE_NAME, sig_hdlr)); + + fd_log_notice("Extension 'Deny by size' initialized with maximum size %d", rt_deny_by_size_conf.maximum_size); + + /* We're done */ + return 0; +} + +/* Unload */ +void fd_ext_fini(void) +{ + TRACE_ENTRY(); + + /* Unregister the cb */ + if (rt__deny_by_size_hdl) { + CHECK_FCT_DO(fd_rt_fwd_unregister(rt__deny_by_size_hdl, NULL), /* continue */); + } + + /* Done */ + return ; +} + +EXTENSION_ENTRY(MODULE_NAME, rt_deny_by_size_entry); diff -r e70ce64ce689 -r daf61e573fee extensions/rt_deny_by_size/rt_deny_by_size.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/rt_deny_by_size/rt_deny_by_size.h Tue Apr 09 15:57:12 2019 +0200 @@ -0,0 +1,53 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Thomas Klausner * +* * +* Copyright (c) 2018, Thomas Klausner * +* All rights reserved. * +* * +* Written under contract by Effortel Technologies SA, http://effortel.com/ * +* * +* 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 the rt_deny_by_size.conf.sample file for the format of the configuration file. + */ + +/* FreeDiameter's common include file */ +#include + + +/* Parse the configuration file */ +int rt_deny_by_size_conf_handle(char * conffile); + +/* The configuration structure */ +extern struct rt_deny_by_size_conf { + int maximum_size; +} rt_deny_by_size_conf; + diff -r e70ce64ce689 -r daf61e573fee extensions/rt_deny_by_size/rt_deny_by_size_conf.l --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/rt_deny_by_size/rt_deny_by_size_conf.l Tue Apr 09 15:57:12 2019 +0200 @@ -0,0 +1,107 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Authors: Thomas Klausner based on code by Sebastien Decugis * +* * +* Copyright (c) 2018, Thomas Klausner * +* Copyright (c) 2013, WIDE Project and NICT * +* All rights reserved. * +* * +* Written under contract by Effortel Technologies SA, http://effortel.com/ * +* * +* 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 + * + */ + +%{ +#include "rt_deny_by_size.h" +#include "rt_deny_by_size_conf.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; \ +} + +/* Avoid warning with newer flex */ +#define YY_NO_INPUT + +%} + +qstring \"[^\"\n]*\" + + +%option bison-bridge bison-locations +%option noyywrap +%option nounput + +%% + + /* Update the line count */ +\n { + yylloc->first_line++; + yylloc->last_line++; + yylloc->last_column=0; + } + + /* Eat all spaces but not new lines */ +([[:space:]]{-}[\n])+ ; + /* Eat all comments */ +#.*$ ; + + /* Recognize any integer */ +[-]?[[:digit:]]+ { + /* Convert this to an integer value */ + int ret=0; + ret = sscanf(yytext, "%i", &yylval->integer); + if (ret != 1) { + /* No matching: an error occurred */ + TRACE_ERROR("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno)); + return LEX_ERROR; /* trig an error in yacc parser */ + /* Maybe we could REJECT instead of failing here? */ + } + return INTEGER; + } + + + + /* The key words */ +(?i:"MaximumSize") { return MAXIMUMSIZE; } + + /* Valid single characters for yyparse */ +[=;] { return yytext[0]; } + + /* Unrecognized sequence, if it did not match any previous pattern */ +[^[:space:]=;\n]+ { + TRACE_ERROR("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext); + return LEX_ERROR; + } + +%% diff -r e70ce64ce689 -r daf61e573fee extensions/rt_deny_by_size/rt_deny_by_size_conf.y --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/rt_deny_by_size/rt_deny_by_size_conf.y Tue Apr 09 15:57:12 2019 +0200 @@ -0,0 +1,147 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Thomas Klausner * +* * +* Copyright (c) 2018, Thomas Klausner * +* All rights reserved. * +* * +* Written under contract by Effortel Technologies SA, http://effortel.com/ * +* * +* 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 extension's configuration parser. + */ + +/* For development only : */ +%debug +%error-verbose + +/* The parser receives the configuration file filename as parameter */ +%parse-param {char * conffile} + +/* Keep track of location */ +%locations +%pure-parser + +%{ +#include "rt_deny_by_size.h" +#include "rt_deny_by_size_conf.tab.h" + +/* Forward declaration */ +int rt_deny_by_size_confparse(char *conffile); +void rt_deny_by_size_confrestart(FILE *input_file); + +/* Parse the configuration file */ +int rt_deny_by_size_conf_handle(char * conffile) +{ + extern FILE *rt_deny_by_size_confin; + int ret; + + TRACE_ENTRY("%p", conffile); + + TRACE_DEBUG(FULL, "Parsing configuration file: %s...", conffile); + + rt_deny_by_size_confin = fopen(conffile, "r"); + if (rt_deny_by_size_confin == NULL) { + ret = errno; + TRACE_ERROR("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret)); + return ret; + } + + rt_deny_by_size_confrestart(rt_deny_by_size_confin); + ret = rt_deny_by_size_confparse(conffile); + + fclose(rt_deny_by_size_confin); + + if (ret != 0) { + TRACE_ERROR( "Unable to parse the configuration file %s.", conffile); + return EINVAL; + } else { + TRACE_DEBUG(FULL, "[rt__deny_by_size] MaximumSize: %d.", rt_deny_by_size_conf.maximum_size); + } + + return 0; +} + +/* The Lex parser prototype */ +int rt_deny_by_size_conflex(YYSTYPE *lvalp, YYLTYPE *llocp); + +/* Function to report the errors */ +void yyerror (YYLTYPE *ploc, char * conffile, char const *s) +{ + TRACE_DEBUG(INFO, "Error in configuration parsing"); + + if (ploc->first_line != ploc->last_line) + fd_log_error("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s); + else if (ploc->first_column != ploc->last_column) + fd_log_error("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s); + else + fd_log_error("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s); +} + +%} + +/* Values returned by lex for token */ +%union { + int integer; +} + +/* In case of error in the lexical analysis */ +%token LEX_ERROR + +/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */ +%token INTEGER + +/* Tokens */ +%token MAXIMUMSIZE + + +/* -------------------------------------- */ +%% + + /* The grammar definition */ +conffile: /* empty is OK */ + | conffile size + | conffile errors + { + yyerror(&yylloc, conffile, "An error occurred while parsing the configuration file"); + YYABORT; + } + ; + + /* Lexical or syntax error */ +errors: LEX_ERROR + | error + ; + +size: MAXIMUMSIZE '=' INTEGER ';' + { + rt_deny_by_size_conf.maximum_size=$3; + } + ;