changeset 1340:daf61e573fee

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.
author Thomas Klausner <tk@giga.or.at>
date Tue, 09 Apr 2019 15:57:12 +0200
parents e70ce64ce689
children b0401251d8c0
files doc/rt_deny_by_size.conf.sample extensions/CMakeLists.txt extensions/rt_deny_by_size/CMakeLists.txt extensions/rt_deny_by_size/rt_deny_by_size.c extensions/rt_deny_by_size/rt_deny_by_size.h extensions/rt_deny_by_size/rt_deny_by_size_conf.l extensions/rt_deny_by_size/rt_deny_by_size_conf.y
diffstat 7 files changed, 470 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /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;
--- 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)
--- /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)
--- /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 <tk@giga.or.at>								 *
+*													 *
+* 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 <signal.h>
+
+/* 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);
--- /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 <tk@giga.or.at>								 *
+*													 *
+* 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 <freeDiameter/extension.h>
+
+
+/* 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;
+
--- /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 <tk@giga.or.at> based on code by Sebastien Decugis <sdecugis@freediameter.net>*
+*													 *
+* 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;
+			}
+
+%%
--- /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 <tk@giga.or.at>								 *
+*													 *
+* 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> 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;
+			}
+			;
"Welcome to our mercurial repository"