changeset 373:0cb02e490017

Added sub_echo_drop files
author Sebastien Decugis <sdecugis@nict.go.jp>
date Mon, 25 May 2009 17:25:53 +0900
parents 0bc3e03125db
children 883330e610e1
files doc/sub_echo_drop.conf.sample extensions/radius_gw/sub_echo_drop.c extensions/radius_gw/sub_echo_drop.h extensions/radius_gw/sub_echo_drop.l extensions/radius_gw/sub_echo_drop.y
diffstat 5 files changed, 573 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/sub_echo_drop.conf.sample	Mon May 25 17:25:53 2009 +0900
@@ -0,0 +1,35 @@
+# Sample configuration file for the sub_echo_drop subextension of radius_gw.
+#
+# This extension allows to easily specify the following handling of RADIUS attributes
+# received in a RADIUS request:
+#  - ECHO: the attribute will be copied as-is in the RADIUS answer.
+#  - DROP: the attribute is discarded.
+#
+# In both cases, the attribute is NOT converted to Diameter.
+#
+# Note that this extension needs a session module extension processed the message previously,
+# if the ECHO handling is to be used.
+#
+# This file contains lines like this:
+# <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>: 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.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/radius_gw/sub_echo_drop.c	Mon May 25 17:25:53 2009 +0900
@@ -0,0 +1,111 @@
+/*********************************************************************************************************
+* 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 sub_echo_drop.h for details */
+
+#define DECLARE_API_POINTERS
+#include "sub_echo_drop.h"
+
+int sub_echo_drop_verbosity = 2;
+
+static struct rga_conf_state * sed_cs_create(char * conffile)
+{
+	struct rga_conf_state * cs = NULL;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	if ( ! conffile ) {
+		log_error("No configuration file specified for extension sub_echo_drop!\n");
+		return NULL;
+	}
+	
+	/* Create a new storage for extension state */
+	CHECK_MALLOC_DO( cs = malloc(sizeof(struct rga_conf_state)), return NULL );
+	memset(cs, 0, sizeof(struct rga_conf_state));
+	
+	rg_list_init(&cs->conf);
+	
+	/* Initialize the session handler, to store "echo" attributes */
+	CHECK_FCT_DO( sess_regext( &cs->sess_hdl ), { free(cs); return NULL; } );
+	
+	/* Parse the configuration file with the yacc parser */
+	cs->conffile = conffile;
+	CHECK_FCT_DO( sed_conf_parse(cs), { sess_deregext(cs->sess_hdl); free(cs); return NULL; } );
+	
+	/* We're done */
+	return cs;
+}
+
+static void sed_cs_destroy(struct rga_conf_state * cs)
+{
+	
+	TRACE_ENTRY("%p", cs);
+	CHECK_PARAMS_DO( cs, );
+	
+	while (! rg_list_is_empty(&cs->conf) ) {
+		struct rg_list * li = cs->conf.next;
+		rg_list_unlink(li);
+		free(li);
+	}
+	
+	CHECK_FCT_DO( sess_deregext( cs->sess_hdl ),  );
+	
+	free(cs);
+	return;
+}
+
+
+int rga_register(int version, waaad_api_t * waaad_api, struct radius_gw_api * api)
+{
+	TRACE_ENTRY("%d %p %p", version, waaad_api, api);
+	CHECK_PARAMS( waaad_api && api );
+	
+	if (version != RADIUS_GW_API_VER) {
+		log_error("ABI version mismatch, please recompile this extension (%s)\n", __FILE__);
+		return EINVAL;
+	}
+	
+	/* Required to use the waaad api from this sub-extension: */
+	EXTENSION_API_INIT_INTERN( API_MODULE_ALL, "sub_echo_drop", waaad_api );
+	
+	/* Initialize the radius_gw api callbacks */
+	api->rga_conf_parse_cb = sed_cs_create;
+	api->rga_conf_free_cb  = sed_cs_destroy;
+	api->rga_rad_req_cb    = NULL;
+	api->rga_diam_ans_cb   = NULL;
+	
+	/* We're done, we must not initialize any state here since the extension must be re-entrant, but in sample_conf_parse */
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/radius_gw/sub_echo_drop.h	Mon May 25 17:25:53 2009 +0900
@@ -0,0 +1,85 @@
+/*********************************************************************************************************
+* 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.								 *
+*********************************************************************************************************/
+
+/* Sub-extension for radius_gw, 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) */
+
+#ifndef _SUB_ECHO_DROP
+#define _SUB_ECHO_DROP
+
+#define IN_EXTENSION
+#define DEFINE_DEBUG_MACRO	sub_echo_drop
+
+#include <waaad/waaad.h>
+#include "rg_common.h"
+#include <stdint.h>
+
+extern int sub_echo_drop_verbosity;
+
+#define ACT_ECHO 1
+#define ACT_DROP 2
+
+struct sed_conf_item {
+	struct rg_list 	chain;
+	
+	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 */
+};
+	
+struct rga_conf_state {
+	/* Input: configuration file */
+	char * conffile;
+	
+	/* Parsed configuration: what to do with attributes (list of struct sed_conf_item) */
+	struct rg_list conf;
+	
+	/* Session handler where "echo" attributes are kept */
+	sess_reg_t * sess_hdl;
+};
+
+/* The yacc parser */
+int sed_conf_parse(struct rga_conf_state *cs);
+
+#endif /* _SUB_ECHO_DROP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/radius_gw/sub_echo_drop.l	Mon May 25 17:25:53 2009 +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 sub echo/drop extension */
+
+%{
+#include "sub_echo_drop.h"
+#include "sub_echo_drop.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 */
+					log_error("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 */
+<*>.			{ 
+				log_error("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/radius_gw/sub_echo_drop.y	Mon May 25 17:25:53 2009 +0900
@@ -0,0 +1,243 @@
+/*********************************************************************************************************
+* 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 sub extension. 
+See doc/sub_echo_drop.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 {struct rga_conf_state *cs}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "sub_echo_drop.h"
+#include "sub_echo_drop.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+/* Forward declaration */
+int yyparse(struct rga_conf_state *conffile);
+
+/* Parse the configuration file */
+int sed_conf_parse(struct rga_conf_state *cs)
+{
+	extern FILE * sub_echo_dropin;
+	int ret;
+	
+	sub_echo_dropin = fopen(cs->conffile, "r");
+	if (sub_echo_dropin == NULL) {
+		ret = errno;
+		log_error("Unable to open extension configuration file %s for reading: %s\n", cs->conffile, strerror(ret));
+		return ret;
+	}
+
+	ret = sub_echo_dropparse(cs);
+
+	fclose(sub_echo_dropin);
+
+	if (ret != 0) {
+		return EINVAL;
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int sub_echo_droplex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, struct rga_conf_state *cs, char const *s)
+{
+	if (ploc->first_line != ploc->last_line)
+		log_error("%s:%d.%d-%d.%d : %s\n", cs->conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		log_error("%s:%d.%d-%d : %s\n", cs->conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		log_error("%s:%d.%d : %s\n", cs->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 sed_conf_item * new;
+				struct rg_list * li;
+
+				if ($4 >= (1 << 8)) {
+					yyerror (&yylloc, cs, "Too big value for attribute CODE");
+					YYERROR;
+				}
+				
+				/* Create a new list item */
+				CHECK_MALLOC_DO( new = malloc(sizeof(struct sed_conf_item)), 
+					{
+						yyerror (&yylloc, cs, "Memory allocation error");
+						YYERROR;
+					} );
+				memset(new, 0, sizeof(struct sed_conf_item));
+				
+				rg_list_init(&new->chain);
+				
+				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->conf.next; li != &cs->conf; li = li->next) {
+					struct sed_conf_item *sci = (struct sed_conf_item *)li;
+					/* Order first by attribute code */
+					if (sci->code > new->code)
+						break;
+					if (sci->code < new->code)
+						continue;
+					
+					/* Then by VSA flag */
+					if (! new->vsa)
+						break;
+					if (! sci->vsa)
+						continue;
+					
+					/* Then by vendor value */
+					if (sci->vendor_id >= new->vendor_id)
+						break;
+				}
+				
+				rg_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, cs, "Too big value for TLV type");
+					YYERROR;
+				}
+				attrinfo.type = $2;
+				attrinfo.tlv = 1;
+			}
+			| TOK_EXT INTEGER
+			{
+				if ($2 >= (1 << 16)) {
+					yyerror (&yylloc, cs, "Too big value for Ext-Type");
+					YYERROR;
+				}
+				attrinfo.extype = $2;
+				attrinfo.ext = 1;
+			}
+			;	
+
"Welcome to our mercurial repository"