+%top {
+/* Include this before everything else, for various large-file definitions */
+#include "config.h"
+}
+
/*
- * We want to stop processing when we get to the end of the input.
+ * We want a reentrant scanner.
*/
-%option noyywrap
+%option reentrant
+
+/*
+ * We don't use input, so don't generate code for it.
+ */
+%option noinput
/*
* We don't use unput, so don't generate code for it.
%option nounput
/*
- * We don't read from the terminal.
+ * We don't read interactively from the terminal.
*/
%option never-interactive
+/*
+ * We want to stop processing when we get to the end of the input.
+ */
+%option noyywrap
+
/*
* The language we're scanning is case-insensitive.
*/
%option caseless
/*
- * Prefix scanner routines with "Radius" rather than "yy", so this scanner
+ * The type for the state we keep for a scanner.
+ */
+%option extra-type="Radius_scanner_state_t*"
+
+/*
+ * We have to override the memory allocators so that we don't get
+ * "unused argument" warnings from the yyscanner argument (which
+ * we don't use, as we have a global memory allocator).
+ *
+ * We provide, as macros, our own versions of the routines generated by Flex,
+ * which just call malloc()/realloc()/free() (as the Flex versions do),
+ * discarding the extra argument.
+ */
+%option noyyalloc
+%option noyyrealloc
+%option noyyfree
+
+/*
+ * Prefix scanner routines with "Radius_" rather than "yy", so this scanner
* can coexist with other scanners.
*/
-%option prefix="Radius"
+%option prefix="Radius_"
%option outfile="radius_dict.c"
*
* RADIUS dictionary parser
*
- * $Id$
- *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <epan/packet.h>
#include <epan/dissectors/packet-radius.h>
-#include "radius_dict_lex.h"
-#include <wiretap/file_util.h>
+#include <wsutil/file_util.h>
-#define ECHO
-#define MAX_INCLUDE_DEPTH 10
+/*
+ * Disable diagnostics in the code generated by Flex.
+ */
+DIAG_OFF_FLEX
- void add_vendor(const gchar* name, guint32 vendor_id);
- void add_value(const gchar* attrib_name,const gchar* value_repr, long value);
- void add_attribute(const gchar*,const gchar*, radius_attr_dissector_t,const gchar*, gboolean, gboolean);
+/*
+ * See
+ *
+ * http://freeradius.org/radiusd/man/dictionary.html
+ *
+ * for the format of RADIUS dictionary files.
+ *
+ * XXX - features not currently supported:
+ *
+ * integer64, ipv4prefix, combo-prefix, bool, size, decimal,
+ * timeval, struct, extended, long-extended, vsa, evs, vendor,
+ * cidr, uint{8,16,32,64}, int{8,16,32,64} as attribute types
+ * (some of these aren't documented);
+ *
+ * octets[N], where N is an integer, as an attribute type
+ * (not documented in the man page);
+ *
+ * internal, array, concat, and virtual as attribute flags (not
+ * documented in the man page);
+ *
+ * We should, perhaps, adopt FreeRADIUS's dictionary-parsing code in
+ * src/lib/dict.c and use that, rather than writing our own parser.
+ * See bug 13176.
+ */
+#define YY_USER_INIT BEGIN WS_OUT;
- static YY_BUFFER_STATE include_stack[10];
- static int include_stack_ptr = 0;
+#define ECHO
+#define MAX_INCLUDE_DEPTH 10
- static radius_dictionary_t* dict = NULL;
- static GHashTable* value_strings = NULL; /* GArray(value_string) by attribute name */
+typedef struct {
+ YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+ int include_stack_ptr;
+
+ radius_dictionary_t* dict;
+ GHashTable* value_strings; /* GArray(value_string) by attribute name */
+
+ gchar* attr_name;
+ gchar* attr_id;
+ radius_attr_dissector_t* attr_type;
+ gchar* attr_vendor;
+ gchar* vendor_name;
+ guint32 vendor_id;
+ guint vendor_type_octets;
+ guint vendor_length_octets;
+ gboolean vendor_has_flags;
+ gchar* value_repr;
+ guint encrypted;
+ gboolean has_tag;
+ gchar* current_vendor;
+ guint current_vendor_evs_type;
+ gchar* current_attr;
+
+ gchar* directory;
+ gchar* fullpaths[MAX_INCLUDE_DEPTH];
+ int linenums[MAX_INCLUDE_DEPTH];
+
+ GString* error;
+} Radius_scanner_state_t;
+
+static void add_vendor(Radius_scanner_state_t* state, const gchar* name, guint32 id, guint type_octets, guint length_octets, gboolean has_flags);
+static gboolean add_attribute(Radius_scanner_state_t* state, const gchar*,const gchar*, radius_attr_dissector_t,const gchar*, guint, gboolean, const gchar*);
+static gboolean add_tlv(Radius_scanner_state_t* state, const gchar* name, const gchar* code, radius_attr_dissector_t type, const gchar* attr);
+static void add_value(Radius_scanner_state_t* state, const gchar* attrib_name, const gchar* repr, guint32 value);
- static gchar* attr_name = NULL;
- static gchar* attr_id = NULL;
- static radius_attr_dissector_t* attr_type = NULL;
- static gchar* attr_vendor = NULL;
- static gchar* vendor_name = NULL;
- static gchar* value_repr = NULL;
- static gboolean encrypted = FALSE;
- static gboolean has_tag = FALSE;
- static gchar* current_vendor = NULL;
+/*
+ * Sleazy hack to suppress compiler warnings in yy_fatal_error().
+ */
+#define YY_EXIT_FAILURE ((void)yyscanner, 2)
- static GString* error = NULL;
- static gchar* directory = NULL;
- static int linenums[] = {1,1,1,1,1,1,1,1,1,1};
- static gchar* fullpaths[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+/*
+ * Macros for the allocators, to discard the extra argument.
+ */
+#define Radius_alloc(size, yyscanner) (void *)malloc(size)
+#define Radius_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
+#define Radius_free(ptr, yyscanner) free((char *)ptr)
%}
-%START WS_OUT VENDOR VENDOR_W_NAME ATTR ATTR_W_NAME ATTR_W_ID ATTR_W_TYPE ATTR_W_VENDOR VALUE VALUE_W_ATTR VALUE_W_NAME INCLUDE JUNK BEGIN_VENDOR END_VENDOR
+/* Note: FreeRadius allows VENDOR, ATTRIBUTE and VALUE names to contain any non-blank character.
+ * Using a negated "blank character class" pattern below for those names fails for some reason
+ * so for now the patterns for each name type include those characters found for the corresponding
+ * name types in the FreeRadius dictionaries.
+ */
+
+%START WS_OUT VENDOR VENDOR_W_NAME ATTR ATTR_W_NAME ATTR_W_ID ATTR_W_TYPE VALUE VALUE_W_ATTR VALUE_W_NAME INCLUDE JUNK BEGIN_VENDOR BEGIN_VENDOR_FORMAT END_VENDOR VENDOR_W_ID VENDOR_W_FORMAT VENDOR_W_TYPE_OCTETS VENDOR_W_LENGTH_OCTETS VENDOR_W_CONTINUATION BEGIN_TLV END_TLV
%%
[:blank:] ;
#[^\n]* ;
<WS_OUT>\$INCLUDE { BEGIN INCLUDE; }
<WS_OUT>BEGIN-VENDOR { BEGIN BEGIN_VENDOR; }
<WS_OUT>END-VENDOR { BEGIN END_VENDOR; }
+<WS_OUT>BEGIN-TLV { BEGIN BEGIN_TLV; }
+<WS_OUT>END-TLV { BEGIN END_TLV; }
<BEGIN_VENDOR>[0-9a-z_-]+ {
- if (current_vendor) {
- g_free(current_vendor);
+ if (yyextra->current_vendor) {
+ g_free(yyextra->current_vendor);
+ }
+ yyextra->current_vendor = g_strdup(yytext);
+ BEGIN BEGIN_VENDOR_FORMAT;
+}
+<BEGIN_VENDOR_FORMAT>format=Extended-Vendor-Specific-[123456] {
+ if (strcmp(yytext, "format=Extended-Vendor-Specific-1") == 0) {
+ yyextra->current_vendor_evs_type = 241;
+ } else if(strcmp(yytext, "format=Extended-Vendor-Specific-2") == 0) {
+ yyextra->current_vendor_evs_type = 242;
+ } else if(strcmp(yytext, "format=Extended-Vendor-Specific-3") == 0) {
+ yyextra->current_vendor_evs_type = 243;
+ } else if(strcmp(yytext, "format=Extended-Vendor-Specific-4") == 0) {
+ yyextra->current_vendor_evs_type = 244;
+ } else if(strcmp(yytext, "format=Extended-Vendor-Specific-5") == 0) {
+ yyextra->current_vendor_evs_type = 245;
+ } else if(strcmp(yytext, "format=Extended-Vendor-Specific-6") == 0) {
+ yyextra->current_vendor_evs_type = 246;
}
- current_vendor = g_strdup(yytext);
BEGIN WS_OUT;
}
+<BEGIN_VENDOR_FORMAT>\n {BEGIN WS_OUT;}
+
<END_VENDOR>[^\n]* {
- if (current_vendor) {
- g_free(current_vendor);
- current_vendor = NULL;
+ if (yyextra->current_vendor) {
+ g_free(yyextra->current_vendor);
+ yyextra->current_vendor = NULL;
}
+ yyextra->current_vendor_evs_type = 0;
BEGIN WS_OUT;
}
-<VENDOR>[0-9a-z_-]+ { vendor_name = g_strdup(yytext); BEGIN VENDOR_W_NAME; }
-<VENDOR_W_NAME>[0-9]+ {
- add_vendor(vendor_name,strtol(yytext,NULL,10));
- g_free(vendor_name);
+<BEGIN_TLV>[0-9a-z_-]+ {
+ if (yyextra->current_attr) {
+ g_free(yyextra->current_attr);
+ }
+ yyextra->current_attr = g_strdup(yytext);
BEGIN WS_OUT;
}
+<END_TLV>[^\n]* {
+ if (yyextra->current_attr) {
+ g_free(yyextra->current_attr);
+ yyextra->current_attr = NULL;
+ }
+ BEGIN WS_OUT;
+}
+
+<VENDOR>[0-9a-z_-]+ {
+ yyextra->vendor_name = g_strdup(yytext);
+ yyextra->vendor_type_octets = 1;
+ yyextra->vendor_length_octets = 1;
+ yyextra->vendor_has_flags = FALSE;
+ BEGIN VENDOR_W_NAME;
+}
+<VENDOR_W_NAME>[0-9]+ {
+ yyextra->vendor_id = (guint32) strtoul(yytext,NULL,10);
+ BEGIN VENDOR_W_ID;
+}
<VENDOR_W_NAME>0x[0-9a-f]+ {
- add_vendor(vendor_name,strtol(yytext,NULL,16));
- g_free(vendor_name);
+ yyextra->vendor_id = (guint32) strtoul(yytext,NULL,16);
+ BEGIN VENDOR_W_ID;
+}
+<VENDOR_W_ID>format= {
+ BEGIN VENDOR_W_FORMAT;
+}
+<VENDOR_W_FORMAT>[124] {
+ yyextra->vendor_type_octets = (guint) strtoul(yytext,NULL,10);
+ BEGIN VENDOR_W_TYPE_OCTETS;
+}
+<VENDOR_W_TYPE_OCTETS>,[012] {
+ yyextra->vendor_length_octets = (guint) strtoul(yytext+1,NULL,10);
+ BEGIN VENDOR_W_LENGTH_OCTETS;
+}
+<VENDOR_W_LENGTH_OCTETS>,c {
+ yyextra->vendor_has_flags = TRUE;
+ BEGIN VENDOR_W_CONTINUATION;
+}
+<VENDOR_W_FORMAT>\n |
+<VENDOR_W_TYPE_OCTETS>\n |
+<VENDOR_W_LENGTH_OCTETS>\n |
+<VENDOR_W_CONTINUATION>\n |
+<VENDOR_W_ID>\n {
+ add_vendor(yyextra, yyextra->vendor_name, yyextra->vendor_id, yyextra->vendor_type_octets, yyextra->vendor_length_octets, yyextra->vendor_has_flags);
+ g_free(yyextra->vendor_name);
BEGIN WS_OUT;
}
-<ATTR>[0-9a-z_/-]+ { attr_name = g_strdup(yytext); encrypted = FALSE; has_tag = FALSE; BEGIN ATTR_W_NAME; }
-<ATTR_W_NAME>[0-9]+ { attr_id = g_strdup(yytext); BEGIN ATTR_W_ID;}
-<ATTR_W_NAME>0x[0-9a-f]+ { attr_id = g_strdup_printf("%u",(int)strtoul(yytext,NULL,16)); BEGIN ATTR_W_ID;}
-<ATTR_W_ID>integer { attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>string { attr_type = radius_string; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>octets { attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ipaddr { attr_type = radius_ipaddr; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ipv6addr { attr_type = radius_ipv6addr; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ipxnet { attr_type = radius_ipxnet; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>date { attr_type = radius_date; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>ifid { attr_type = radius_ifid; BEGIN ATTR_W_TYPE; }
-<ATTR_W_ID>[0-9a-z_-]+ { attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
-<ATTR_W_TYPE>has_tag[,]? { has_tag = TRUE; }
-<ATTR_W_TYPE>encrypt=1[,]? { encrypted=TRUE; }
+<ATTR>[0-9a-z_/.-]+ { yyextra->attr_name = g_strdup(yytext); yyextra->encrypted = 0; yyextra->has_tag = FALSE; BEGIN ATTR_W_NAME; }
+<ATTR_W_NAME>[0-9.]+ { yyextra->attr_id = g_strdup(yytext); BEGIN ATTR_W_ID;}
+<ATTR_W_NAME>0x[0-9a-f]+ { yyextra->attr_id = g_strdup_printf("%u",(int)strtoul(yytext,NULL,16)); BEGIN ATTR_W_ID;}
+<ATTR_W_ID>integer { yyextra->attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>string { yyextra->attr_type = radius_string; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>octets { yyextra->attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ipaddr { yyextra->attr_type = radius_ipaddr; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ipv6addr { yyextra->attr_type = radius_ipv6addr; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ipv6prefix { yyextra->attr_type = radius_ipv6prefix; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ipxnet { yyextra->attr_type = radius_ipxnet; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>date { yyextra->attr_type = radius_date; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>abinary { yyextra->attr_type = radius_abinary; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ether { yyextra->attr_type = radius_ether; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ifid { yyextra->attr_type = radius_ifid; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>byte { yyextra->attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>short { yyextra->attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>signed { yyextra->attr_type = radius_signed; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>combo-ip { yyextra->attr_type = radius_combo_ip; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>tlv { yyextra->attr_type = radius_tlv; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>[0-9a-z_-]+ { yyextra->attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
+<ATTR_W_TYPE>has_tag[,]? { yyextra->has_tag = TRUE; }
+<ATTR_W_TYPE>encrypt=[123][,]? { yyextra->encrypted = (guint) strtoul(yytext+8,NULL,10); }
<ATTR_W_TYPE>[0-9a-z_-]+=([^\n]*) ;
<ATTR_W_TYPE>[0-9a-z_-]+ {
- attr_vendor = g_strdup(yytext);
- add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag);
- g_free(attr_id);
- g_free(attr_vendor);
- g_free(attr_name);
- attr_id = NULL;
- attr_vendor = NULL;
- attr_name = NULL;
- BEGIN WS_OUT;
+ /*
+ * Support for "ATTRIBUTE name oid type vendor", where the token
+ * following the type matches neither has_tag nor encrypt={1,2,3},
+ * but is a sequence of digits, lower-case letters, underscores,
+ * and hyphens.
+ *
+ * We mark this as a vendor-specific attribute (VSA), with the token
+ * following the type being the vendor name; this notation is deprecated
+ * in favor of BEGIN-VENDOR/END-VENDOR blocks.
+ */
+ gboolean attribute_ok;
+
+ yyextra->attr_vendor = g_strdup(yytext);
+ attribute_ok = add_attribute(yyextra, yyextra->attr_name, yyextra->attr_id, yyextra->attr_type, yyextra->attr_vendor, yyextra->encrypted, yyextra->has_tag, yyextra->current_attr);
+ g_free(yyextra->attr_id);
+ g_free(yyextra->attr_vendor);
+ g_free(yyextra->attr_name);
+ yyextra->attr_id = NULL;
+ yyextra->attr_vendor = NULL;
+ yyextra->attr_name = NULL;
+ if (attribute_ok)
+ BEGIN WS_OUT;
+ else
+ BEGIN JUNK;
}
<ATTR_W_TYPE>\n {
- add_attribute(attr_name,attr_id,attr_type,current_vendor,encrypted,has_tag);
- g_free(attr_id);
- g_free(attr_name);
- linenums[include_stack_ptr]++;
- has_tag = FALSE;
- encrypted=FALSE;
+ add_attribute(yyextra, yyextra->attr_name, yyextra->attr_id, yyextra->attr_type, yyextra->current_vendor, yyextra->encrypted, yyextra->has_tag, yyextra->current_attr);
+ g_free(yyextra->attr_id);
+ g_free(yyextra->attr_name);
+ yyextra->linenums[yyextra->include_stack_ptr]++;
+ yyextra->has_tag = FALSE;
+ yyextra->encrypted=FALSE;
BEGIN WS_OUT;
}
-<ATTR_W_VENDOR>\n {
- add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag);
- g_free(attr_id);
- g_free(attr_vendor);
- g_free(attr_name);
- linenums[include_stack_ptr]++;
- BEGIN WS_OUT;
-};
-<VALUE>[0-9a-z_/-]+ { attr_name = g_strdup(yytext); BEGIN VALUE_W_ATTR; }
-<VALUE_W_ATTR>[^[:blank:]]+ { value_repr = g_strdup(yytext); BEGIN VALUE_W_NAME; }
-<VALUE_W_NAME>[0-9]+ { add_value(attr_name,value_repr,strtol(yytext,NULL,10)); g_free(attr_name); g_free(value_repr); BEGIN WS_OUT;}
-<VALUE_W_NAME>0x[0-9a-f]+ { add_value(attr_name,value_repr,strtol(yytext,NULL,16)); g_free(attr_name); g_free(value_repr); BEGIN WS_OUT;}
+<VALUE>[0-9a-z_/-]+ { yyextra->attr_name = g_strdup(yytext); BEGIN VALUE_W_ATTR; }
+<VALUE_W_ATTR>[^[:blank:]]+ { yyextra->value_repr = g_strdup(yytext); BEGIN VALUE_W_NAME; }
+<VALUE_W_NAME>[0-9]+ { add_value(yyextra, yyextra->attr_name,yyextra->value_repr, (guint32) strtoul(yytext,NULL,10)); g_free(yyextra->attr_name); g_free(yyextra->value_repr); BEGIN WS_OUT;}
+<VALUE_W_NAME>0x[0-9a-f]+ { add_value(yyextra, yyextra->attr_name,yyextra->value_repr, (guint32) strtoul(yytext,NULL,16)); g_free(yyextra->attr_name); g_free(yyextra->value_repr); BEGIN WS_OUT;}
<INCLUDE>[^[:blank:]\n]+ {
- if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
- g_string_sprintfa(error, "$INCLUDE files nested to deeply\n");
+ if ( yyextra->include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
+ g_string_append_printf(yyextra->error, "$INCLUDE files nested too deeply\n");
yyterminate();
}
- include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
+ yyextra->include_stack[yyextra->include_stack_ptr++] = YY_CURRENT_BUFFER;
- fullpaths[include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
- directory,yytext);
+ yyextra->fullpaths[yyextra->include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+ yyextra->directory,yytext);
- yyin = eth_fopen( fullpaths[include_stack_ptr], "r" );
+ yyin = ws_fopen( yyextra->fullpaths[yyextra->include_stack_ptr], "r" );
if (!yyin) {
if (errno) {
- g_string_sprintfa(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
- yyterminate();
+ g_string_append_printf(yyextra->error,
+ "Could not open file: '%s', error: %s\n",
+ yyextra->fullpaths[yyextra->include_stack_ptr],
+ g_strerror(errno) );
+ } else {
+ g_string_append_printf(yyextra->error,
+ "Could not open file: '%s', no errno\n",
+ yyextra->fullpaths[yyextra->include_stack_ptr]);
}
+ g_free(yyextra->fullpaths[yyextra->include_stack_ptr]);
+ yyextra->fullpaths[yyextra->include_stack_ptr] = NULL;
+ yyextra->include_stack_ptr--;
} else {
- linenums[include_stack_ptr] = 1;
- yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
+ yyextra->linenums[yyextra->include_stack_ptr] = 1;
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner), yyscanner);
}
fclose(yyin);
yyin = NULL;
- if ( --include_stack_ptr < 0 ) {
+ if ( --yyextra->include_stack_ptr < 0 ) {
yyterminate();
} else {
- g_free(fullpaths[include_stack_ptr+1]);
- fullpaths[include_stack_ptr+1] = NULL;
+ g_free(yyextra->fullpaths[yyextra->include_stack_ptr+1]);
+ yyextra->fullpaths[yyextra->include_stack_ptr+1] = NULL;
- yy_delete_buffer( YY_CURRENT_BUFFER );
- yy_switch_to_buffer(include_stack[include_stack_ptr]);
+ Radius__delete_buffer(YY_CURRENT_BUFFER, yyscanner);
+ Radius__switch_to_buffer(yyextra->include_stack[yyextra->include_stack_ptr], yyscanner);
}
BEGIN WS_OUT;
}
-\n { linenums[include_stack_ptr]++; BEGIN WS_OUT; }
+\n { yyextra->linenums[yyextra->include_stack_ptr]++; BEGIN WS_OUT; }
%%
-void add_vendor(const gchar* name, guint32 vendor_id) {
- radius_vendor_info_t* v = g_malloc(sizeof(radius_vendor_info_t));
-
- v->name = g_strdup(name);
- v->code = vendor_id;
- v->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
- v->ett = -1;
-
- g_hash_table_insert(dict->vendors_by_id,GUINT_TO_POINTER(v->code),v);
- g_hash_table_insert(dict->vendors_by_name, (gpointer) v->name, v);
+/*
+ * Turn diagnostics back on, so we check the code that we've written.
+ */
+DIAG_ON_FLEX
+
+static void add_vendor(Radius_scanner_state_t* state, const gchar* name, guint32 id, guint type_octets, guint length_octets, gboolean has_flags) {
+ radius_vendor_info_t* v;
+
+ v = (radius_vendor_info_t *)g_hash_table_lookup(state->dict->vendors_by_id, GUINT_TO_POINTER(id));
+
+ if (!v) {
+ /*
+ * New vendor.
+ * Allocate a new entry and insert it into the by-ID and
+ * by-name hash tables.
+ */
+ v = g_new(radius_vendor_info_t,1);
+ v->attrs_by_id = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_radius_attr_info);
+ v->code = id;
+ v->ett = -1;
+ v->name = g_strdup(name);
+ v->type_octets = type_octets;
+ v->length_octets = length_octets;
+ v->has_flags = has_flags;
+
+ g_hash_table_insert(state->dict->vendors_by_id,GUINT_TO_POINTER(v->code),v);
+ g_hash_table_insert(state->dict->vendors_by_name, (gpointer) v->name, v);
+ } else {
+ /*
+ * This vendor is already in the table.
+ *
+ * Assume that the dictionary knows the 'ground truth' about
+ * the type/length/has_flags information and thus allow the
+ * dictionary to overwrite these values even for vendors that
+ * have already been loaded.
+ *
+ * XXX - this could be due to the vendor being in multiple
+ * dictionary files, rather than having been specially
+ * entered by the RADIUS dissector, as a side effect of
+ * specially entering an attribute; should we report vendors
+ * that appear in different dictionaries with different
+ * properties?
+ */
+ v->type_octets = type_octets;
+ v->length_octets = length_octets;
+ v->has_flags = has_flags;
+
+ /*
+ * Did the name change?
+ */
+ if (g_strcmp0(v->name, name) != 0) {
+ /*
+ * Yes. Remove the entry from the by-name hash table
+ * and re-insert it with the new name.
+ */
+ g_hash_table_remove(state->dict->vendors_by_name, (gpointer) v->name);
+ g_free((gpointer) v->name);
+ v->name = g_strdup(name);
+ g_hash_table_insert(state->dict->vendors_by_name, (gpointer) v->name, v);
+ }
+ }
}
-void add_attribute(const gchar* name, const gchar* code, radius_attr_dissector_t type, const gchar* vendor_name, gboolean crypt, gboolean tagged) {
- radius_attr_info_t* a = g_malloc(sizeof(radius_attr_info_t));
+static gboolean add_attribute(Radius_scanner_state_t* state, const gchar* name, const gchar* codestr, radius_attr_dissector_t type, const gchar* vendor, guint encrypted_flag, gboolean tagged, const gchar* attr) {
+ radius_attr_info_t* a;
GHashTable* by_id;
+ radius_attr_type_t code;
+ guint8 code0 = 0, code1 = 0;
+ gchar *dot, *buf = NULL;
+
+ if (attr){
+ return add_tlv(state, name, codestr, type, attr);
+ }
- if (vendor_name) {
- radius_vendor_info_t* v;
- v = g_hash_table_lookup(dict->vendors_by_name,vendor_name);
+ buf = g_strdup(codestr);
+ dot = strchr(codestr, '.');
+ if (dot)
+ *dot = '\0';
+ code0 = (guint8) strtoul(buf, NULL, 10);
+ if (dot)
+ code1 = (guint8) strtoul(dot + 1, NULL, 10);
+ g_free(buf);
+
+ memset(&code, 0, sizeof(code));
+ if (vendor) {
+ if (state->current_vendor_evs_type) {
+ code.u8_code[0] = (guint8) state->current_vendor_evs_type;
+ code.u8_code[1] = code0;
+ } else {
+ code.u8_code[0] = code0;
+ code.u8_code[1] = 0;
+ }
+ radius_vendor_info_t* v = (radius_vendor_info_t *)g_hash_table_lookup(state->dict->vendors_by_name,vendor);
if (! v) {
- g_string_sprintfa(error, "Vendor: '%s', does not exist in %s:%i \n", vendor_name, fullpaths[include_stack_ptr], linenums[include_stack_ptr] );
- BEGIN JUNK;
- return;
+ g_string_append_printf(state->error, "Vendor: '%s', does not exist in %s:%i \n", vendor, state->fullpaths[state->include_stack_ptr], state->linenums[state->include_stack_ptr] );
+ return FALSE;
} else {
by_id = v->attrs_by_id;
}
} else {
- by_id = dict->attrs_by_id;
+ code.u8_code[0] = code0;
+ code.u8_code[1] = code1;
+
+ by_id = state->dict->attrs_by_id;
+ }
+
+ a=(radius_attr_info_t*)g_hash_table_lookup(by_id, GUINT_TO_POINTER(code.value));
+
+ if (!a) {
+ /*
+ * New attribute.
+ * Allocate a new entry and insert it into the by-ID and
+ * by-name hash tables.
+ */
+ a = g_new(radius_attr_info_t,1);
+ a->code = code;
+ a->name = g_strdup(name);
+ a->dissector = NULL;
+ a->encrypt = encrypted_flag;
+ a->tagged = tagged;
+ a->type = type;
+ a->vs = NULL;
+ a->hf = -1;
+ a->hf_alt = -1;
+ a->hf_tag = -1;
+ a->hf_len = -1;
+ a->ett = -1;
+ a->tlvs_by_id = NULL;
+ g_hash_table_insert(by_id, GUINT_TO_POINTER(code.value),a);
+ g_hash_table_insert(state->dict->attrs_by_name,(gpointer) (a->name),a);
+ } else {
+ /*
+ * This attribute is already in the table.
+ *
+ * Overwrite the encrypted flag, tagged property, and type;
+ * the other properties don't get set until after we've
+ * finished reading the dictionaries.
+ *
+ * XXX - this could be due to the attribute being in
+ * multiple dictionary files, rather than having been
+ * specially entered by the RADIUS dissector to give it
+ * a special dissection routine; should we report attributes
+ * that appear in different dictionaries with different
+ * properties?
+ */
+ a->encrypt = encrypted_flag;
+ a->tagged = tagged;
+ a->type = type;
+
+ /*
+ * Did the name change?
+ */
+ if (g_strcmp0(a->name, name) != 0) {
+ /*
+ * Yes. Steal the entry from the by-name hash table
+ * and re-insert it with the new name. (Don't
+ * remove it - that calls the free routine, which
+ * frees up the entry.)
+ */
+ g_hash_table_steal(state->dict->attrs_by_name, (gpointer) (a->name));
+ g_free((gpointer) a->name);
+ a->name = g_strdup(name);
+ g_hash_table_insert(state->dict->attrs_by_name, (gpointer) (a->name),a);
+ }
+ }
+ return TRUE;
+}
+
+static gboolean add_tlv(Radius_scanner_state_t* state, const gchar* name, const gchar* codestr, radius_attr_dissector_t type, const gchar* attr) {
+ radius_attr_info_t* a;
+ radius_attr_info_t* s;
+ radius_attr_type_t code;
+
+ a = (radius_attr_info_t*)g_hash_table_lookup(state->dict->attrs_by_name, attr);
+
+ if (! a) {
+ g_string_append_printf(state->error, "Attr: '%s', does not exist in %s:%i \n", attr, state->fullpaths[state->include_stack_ptr], state->linenums[state->include_stack_ptr]);
+ return FALSE;
+ }
+
+ if (type == radius_tlv) {
+ g_string_append_printf(state->error, "sub-TLV: '%s', sub-TLV's type is specified as tlv in %s:%i \n", name, state->fullpaths[state->include_stack_ptr], state->linenums[state->include_stack_ptr]);
+ return FALSE;
+ }
+
+
+ if (! a->tlvs_by_id) {
+ a->tlvs_by_id = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_radius_attr_info);
}
- a->name = g_strdup(name);
- a->code = strtol(code,NULL,10);
- a->encrypt = crypt;
- a->tagged = tagged;
- a->type = type;
- a->dissector = NULL;
- a->vs = NULL;
- a->hf = -1;
- a->hf64 = -1;
- a->hf_tag = -1;
- a->hf_len = -1;
- a->ett = -1;
-
- g_hash_table_insert(by_id,GUINT_TO_POINTER(a->code),a);
- g_hash_table_insert(dict->attrs_by_name,(gpointer) (a->name),a);
+ memset(&code, 0, sizeof(code));
+ code.u8_code[0] = (guint8) strtoul(codestr, NULL, 10);
+
+ s = (radius_attr_info_t*)g_hash_table_lookup(a->tlvs_by_id, GUINT_TO_POINTER(code.value));
+
+ if (!s) {
+ /*
+ * This TLV doesn't yet exist in this attribute's TLVs-by-ID
+ * hash table. Add it.
+ */
+ s = g_new(radius_attr_info_t,1);
+ s->name = g_strdup(name);
+ s->dissector = NULL;
+ s->code = code;
+ s->type = type;
+ s->encrypt = FALSE;
+ s->tagged = FALSE;
+ s->dissector = NULL;
+ s->vs = NULL;
+ s->hf = -1;
+ s->hf_alt = -1;
+ s->hf_tag = -1;
+ s->hf_len = -1;
+ s->ett = -1;
+ s->tlvs_by_id = NULL;
+
+ g_hash_table_insert(a->tlvs_by_id,GUINT_TO_POINTER(s->code.value),s);
+ g_hash_table_insert(state->dict->tlvs_by_name,(gpointer) (s->name),s);
+ }
+
+ /*
+ * If it *does* exist, leave it alone; there shouldn't be duplicate
+ * entries by name in the dictionaries (even if there might be
+ * multiple entries for a given attribute in the dictionaries, each
+ * one adding some TLV values), and we don't directly add entries
+ * for TLVs in the RADIUS dissector.
+ *
+ * XXX - report the duplicate entries?
+ */
+ return TRUE;
}
-void add_value(const gchar* attrib_name, const gchar* value_repr, long value) {
+void add_value(Radius_scanner_state_t* state, const gchar* attrib_name, const gchar* repr, guint32 value) {
value_string v;
- GArray* a = g_hash_table_lookup(value_strings,attrib_name);
+ GArray* a = (GArray*)g_hash_table_lookup(state->value_strings,attrib_name);
if (! a) {
- a = g_array_new(TRUE,TRUE,sizeof(value_string));
- g_hash_table_insert(value_strings,g_strdup(attrib_name),a);
+ /* Ensure that the array is zero terminated. */
+ a = g_array_new(TRUE, TRUE, sizeof(value_string));
+ g_hash_table_insert(state->value_strings, g_strdup(attrib_name), a);
}
v.value = value;
- v.strptr = g_strdup(value_repr);
+ v.strptr = g_strdup(repr);
g_array_append_val(a,v);
}
-
-static void setup_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
- radius_attr_info_t* a = v;
+static void setup_tlvs(gpointer k _U_, gpointer v, gpointer p) {
+ radius_attr_info_t* s = (radius_attr_info_t*)v;
+ Radius_scanner_state_t* state = (Radius_scanner_state_t*)p;
gpointer key;
union {
gpointer p;
} vs;
- if (g_hash_table_lookup_extended(value_strings,a->name,&key,&vs.p) ) {
- a->vs = (value_string*) vs.a->data;
- g_array_free(vs.a,FALSE);
- g_hash_table_remove(value_strings,key);
+ if (g_hash_table_lookup_extended(state->value_strings, s->name, &key, &vs.p)) {
+ g_hash_table_steal(state->value_strings, key);
+ s->vs = (value_string*)(void *)g_array_free(vs.a, FALSE);
g_free(key);
}
}
-static void setup_vendors(gpointer k _U_, gpointer v, gpointer p) {
- radius_vendor_info_t* vnd = v;
+static void setup_attrs(gpointer k _U_, gpointer v, gpointer p) {
+ radius_attr_info_t* a = (radius_attr_info_t*)v;
+ Radius_scanner_state_t* state = (Radius_scanner_state_t*)p;
+ gpointer key;
- g_hash_table_foreach(vnd->attrs_by_id,setup_attrs,p);
-}
+ union {
+ GArray* a;
+ gpointer p;
+ } vs;
-static gboolean destroy_value_strings(gpointer k, gpointer v, gpointer p _U_) {
- value_string* vs = (value_string*)(((GArray*)v)->data);
+ if (g_hash_table_lookup_extended(state->value_strings, a->name, &key, &vs.p) ) {
+ g_hash_table_steal(state->value_strings, key);
+ a->vs = (value_string*)(void *)g_array_free(vs.a, FALSE);
+ g_free(key);
+ }
- g_free(k);
+ if (a->tlvs_by_id) {
+ g_hash_table_foreach(a->tlvs_by_id, setup_tlvs, p);
+ }
+}
- for (;vs->strptr;vs++) {
- g_free((void*)vs->strptr);
- }
+static void setup_vendors(gpointer k _U_, gpointer v, gpointer p) {
+ radius_vendor_info_t* vnd = (radius_vendor_info_t*)v;
- g_array_free(v,TRUE);
- return TRUE;
+ g_hash_table_foreach(vnd->attrs_by_id,setup_attrs,p);
}
-static gboolean destroy_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
- radius_attr_info_t* a = v;
- int i;
+static void destroy_value_strings(gpointer v) {
+ value_string* vs = (value_string*)(void *)(((GArray*)v)->data);
- g_free((gpointer) (a->name));
- if (a->vs) {
- for(i=0; a->vs[i].strptr; i++) {
- g_free((void *)a->vs[i].strptr);
- }
- g_free((void *)a->vs);
+ for (;vs->strptr;vs++) {
+ g_free((void*)vs->strptr);
}
- g_free(a);
- return TRUE;
-}
-
-static gboolean destroy_vendors(gpointer k _U_, gpointer v, gpointer p) {
- radius_vendor_info_t* vnd = v;
- g_free( (gpointer) vnd->name);
- g_hash_table_foreach_remove(vnd->attrs_by_id,destroy_attrs,p);
- g_hash_table_destroy(vnd->attrs_by_id);
- g_free(vnd);
- return TRUE;
-}
-static void destroy_dict(radius_dictionary_t* d) {
- g_hash_table_foreach_remove(d->attrs_by_id,destroy_attrs,NULL);
- g_hash_table_foreach_remove(d->vendors_by_id,destroy_vendors,NULL);
- g_hash_table_destroy(d->vendors_by_id);
- g_hash_table_destroy(d->attrs_by_id);
- g_hash_table_destroy(d->vendors_by_name);
- g_hash_table_destroy(d->attrs_by_name);
- g_free(d);
+ g_array_free((GArray*)v,TRUE);
}
-radius_dictionary_t* radius_load_dictionary (gchar* dir, const gchar* filename, gchar** err_str) {
+gboolean radius_load_dictionary (radius_dictionary_t* d, gchar* dir, const gchar* filename, gchar** err_str) {
+ FILE *in;
+ yyscan_t scanner;
+ Radius_scanner_state_t state;
int i;
- directory = dir;
-
- fullpaths[include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
- directory,filename);
+ state.include_stack_ptr = 0;
+
+ state.dict = d;
+ state.value_strings = NULL;
+
+ state.attr_name = NULL;
+ state.attr_id = NULL;
+ state.attr_type = NULL;
+ state.attr_vendor = NULL;
+ state.vendor_name = NULL;
+ state.vendor_id = 0;
+ state.vendor_type_octets = 1;
+ state.vendor_length_octets = 1;
+ state.vendor_has_flags = FALSE;
+ state.value_repr = NULL;
+ state.encrypted = 0;
+ state.has_tag = FALSE;
+ state.current_vendor = NULL;
+ state.current_vendor_evs_type = 0;
+ state.current_attr = NULL;
+
+ state.directory = dir;
+
+ state.fullpaths[0] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+ state.directory,filename);
+ state.linenums[0] = 1;
+ for (i = 1; i < MAX_INCLUDE_DEPTH; i++) {
+ state.fullpaths[i] = NULL;
+ state.linenums[i] = 1;
+ }
- error = g_string_new("");
+ state.error = g_string_new("");
- yyin = eth_fopen(fullpaths[include_stack_ptr],"r");
+ in = ws_fopen(state.fullpaths[0],"r");
- if (!yyin) {
- g_string_sprintfa(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
- g_free(fullpaths[include_stack_ptr]);
- *err_str = error->str;
- g_string_free(error,FALSE);
- return NULL;
+ if (!in) {
+ g_string_append_printf(state.error, "Could not open file: '%s', error: %s\n", state.fullpaths[0], g_strerror(errno));
+ g_free(state.fullpaths[0]);
+ *err_str = g_string_free(state.error,FALSE);
+ return FALSE;
}
- dict = g_malloc(sizeof(radius_dictionary_t));
- dict->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
- dict->attrs_by_name = g_hash_table_new(g_str_hash,g_str_equal);
- dict->vendors_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
- dict->vendors_by_name = g_hash_table_new(g_str_hash,g_str_equal);
+ state.value_strings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, destroy_value_strings);
- value_strings = g_hash_table_new(g_str_hash,g_str_equal);
+ if (Radius_lex_init(&scanner) != 0) {
+ g_string_append_printf(state.error, "Can't initialize scanner: %s",
+ strerror(errno));
+ fclose(in);
+ g_free(state.fullpaths[0]);
+ *err_str = g_string_free(state.error,FALSE);
+ return FALSE;
+ }
- BEGIN WS_OUT;
+ Radius_set_in(in, scanner);
- yylex();
+ /* Associate the state with the scanner */
+ Radius_set_extra(&state, scanner);
- if (yyin != NULL) fclose(yyin);
- yyin = NULL;
+ Radius_lex(scanner);
+
+ Radius_lex_destroy(scanner);
+ /*
+ * XXX - can the lexical analyzer terminate without closing
+ * all open input files?
+ */
- for (i=0; i < 10; i++) {
- if (fullpaths[i]) g_free(fullpaths[i]);
+ for (i = 0; i < MAX_INCLUDE_DEPTH; i++) {
+ g_free(state.fullpaths[i]);
}
- g_hash_table_foreach(dict->attrs_by_id,setup_attrs,NULL);
- g_hash_table_foreach(dict->vendors_by_id,setup_vendors,NULL);
- g_hash_table_foreach_remove(value_strings,destroy_value_strings,NULL);
+ g_hash_table_foreach(state.dict->attrs_by_id,setup_attrs,&state);
+ g_hash_table_foreach(state.dict->vendors_by_id,setup_vendors,&state);
+ g_hash_table_destroy(state.value_strings);
- if (error->len > 0) {
- *err_str = error->str;
- g_string_free(error,FALSE);
- destroy_dict(dict);
- return NULL;
+ if (state.error->len > 0) {
+ *err_str = g_string_free(state.error,FALSE);
+ return FALSE;
} else {
*err_str = NULL;
- g_string_free(error,TRUE);
- return dict;
+ g_string_free(state.error,TRUE);
+ return TRUE;
}
}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */