changeset 269:c78f623c702d

Ported the Echo/Drop plugin from waaad (missing files)
author Sebastien Decugis <sdecugis@nict.go.jp>
date Mon, 19 Apr 2010 16:58:12 +0900
parents b364ffffa2ed
children 47fff7a7af06
files doc/echodrop.rgwx.conf.sample extensions/app_radgw/rgwx_echodrop.c extensions/app_radgw/rgwx_echodrop.h extensions/app_radgw/rgwx_echodrop.l extensions/app_radgw/rgwx_echodrop.y
diffstat 5 files changed, 744 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /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:
+# <action> CODE <code> [ VENDOR <vid> [ TLV <type> | EXT <ext-type> ] ];
+# Where:
+#    <action>: is either DROP or ECHO.
+#    <code>  : 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)
+#    <vid> : a Vendor value (32 bit), see RFC2865 section 5.26 for detail.
+#
+#  <type>    : The attribute is interpreted as TLV (rfc3865, section 5.26) 
+#		and we match only this "vendor type" value (8 bits).
+#
+#  <ext-type>: 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
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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
+};	
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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);
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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; 
+			}
+
+%%
--- /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 <sdecugis@nict.go.jp>							 *
+*													 *
+* 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> INTEGER
+%type  <integer> 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;
+			}
+			;	
+
"Welcome to our mercurial repository"