summaryrefslogtreecommitdiff
path: root/epan/radius_dict.l
diff options
context:
space:
mode:
Diffstat (limited to 'epan/radius_dict.l')
-rw-r--r--epan/radius_dict.l321
1 files changed, 321 insertions, 0 deletions
diff --git a/epan/radius_dict.l b/epan/radius_dict.l
new file mode 100644
index 0000000000..1ff238c738
--- /dev/null
+++ b/epan/radius_dict.l
@@ -0,0 +1,321 @@
+%option noyywrap
+
+%option nounput
+%option never-interactive
+%option prefix="Radius"
+%option caseless
+
+%option outfile="radius_dict.c"
+
+%{
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <epan/packet.h>
+#include <epan/dissectors/packet-radius.h>
+#define DIR_SEPARATOR '/'
+#define ECHO
+#define MAX_INCLUDE_DEPTH 10
+
+ void add_vendor(gchar* name, guint32 vendor_id);
+ void add_value(gchar* attrib_name, gchar* value_repr, long value);
+ void add_attribute(gchar*, gchar*, radius_attr_dissector_t, gchar*, gboolean, gboolean);
+
+ static YY_BUFFER_STATE include_stack[10];
+ static int include_stack_ptr = 0;
+
+ static radius_dictionary_t* dict = NULL;
+ static GHashTable* value_strings = NULL; /* GArray(value_string) by attribute name */
+
+ 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 encrypt = FALSE;
+ static gboolean has_tag = FALSE;
+ static gchar* current_vendor = NULL;
+
+ 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};
+
+%}
+
+%START 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
+%%
+[:blank:] ;
+#[^\n]* ;
+
+<JUNK>.*\qn ;
+
+<OUT>VENDOR { BEGIN VENDOR; }
+<OUT>ATTRIBUTE { BEGIN ATTR; }
+<OUT>VALUE { BEGIN VALUE; }
+<OUT>\$INCLUDE { BEGIN INCLUDE; }
+<OUT>BEGIN-VENDOR { BEGIN BEGIN_VENDOR; }
+<OUT>END-VENDOR { BEGIN END_VENDOR; }
+
+<BEGIN_VENDOR>[0-9a-z_-]+ {current_vendor = g_strdup(yytext); BEGIN OUT; }
+<END_VENDOR>[^\n]* {if (current_vendor) { g_free(current_vendor); current_vendor = NULL; } BEGIN 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)); BEGIN OUT; }
+<VENDOR_W_NAME>0x[0-9a-f]+ { add_vendor(vendor_name,strtol(yytext,NULL,16)); BEGIN OUT; }
+
+<ATTR>[0-9a-z_-]+ { attr_name = g_strdup(yytext); encrypt = 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>date { attr_type = radius_date; BEGIN ATTR_W_TYPE; }
+<ATTR_W_ID>ipv6addr { attr_type = radius_ipv6addr; 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_vendor = NULL; BEGIN ATTR_W_VENDOR; }
+<ATTR_W_TYPE>encrypt=1[,]? { encrypt=TRUE; attr_vendor = NULL; BEGIN ATTR_W_VENDOR; }
+<ATTR_W_TYPE>[,0-9a-z_-]+=([^\n]+) { /* ignore other parameters */ attr_vendor = NULL; BEGIN ATTR_W_VENDOR; }
+<ATTR_W_TYPE>[0-9a-z_-]+ { attr_vendor = g_strdup(yytext); add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypt,has_tag); attr_vendor = NULL; BEGIN OUT; }
+<ATTR_W_TYPE>\n { add_attribute(attr_name,attr_id,attr_type,current_vendor ? g_strdup(current_vendor) : NULL ,encrypt,has_tag); linenums[include_stack_ptr]++; BEGIN OUT; }
+<ATTR_W_VENDOR>\n { add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypt,has_tag); linenums[include_stack_ptr]++; BEGIN 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)); BEGIN OUT;}
+<VALUE_W_NAME>0x[0-9a-f]+ { add_value(attr_name,value_repr,strtol(yytext,NULL,16)); BEGIN OUT;}
+
+<INCLUDE>[^[:blank:]\n]+ {
+ if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
+ g_string_sprintfa(error, "$INCLUDE files nested to deeply\n");
+ yyterminate();
+ }
+
+ include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
+
+ fullpaths[include_stack_ptr] = g_strdup_printf("%s%c%s",directory,DIR_SEPARATOR,yytext);
+
+ yyin = fopen( fullpaths[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();
+ }
+ } else {
+ linenums[include_stack_ptr] = 1;
+ yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
+ }
+
+
+ BEGIN OUT;
+}
+
+<<EOF>> {
+
+ if ( --include_stack_ptr < 0 ) {
+ yyterminate();
+ } else {
+ g_free(fullpaths[include_stack_ptr+1]);
+ fullpaths[include_stack_ptr+1] = NULL;
+
+ yy_delete_buffer( YY_CURRENT_BUFFER );
+ yy_switch_to_buffer(include_stack[include_stack_ptr]);
+ }
+
+ BEGIN OUT;
+}
+
+\n { linenums[include_stack_ptr]++; BEGIN OUT; }
+
+
+%%
+
+void add_vendor(gchar* name, guint32 vendor_id) {
+ radius_vendor_info_t* v = g_malloc(sizeof(radius_vendor_info_t));
+
+ v->name = name;
+ v->code = vendor_id;
+ v->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
+
+ g_hash_table_insert(dict->vendors_by_id,GUINT_TO_POINTER(v->code),v);
+ g_hash_table_insert(dict->vendors_by_name,v->name,v);
+}
+
+void add_attribute(gchar* name, gchar* code, radius_attr_dissector_t type, gchar* vendor_name, gboolean crypt, gboolean tagged) {
+ radius_attr_info_t* a = g_malloc(sizeof(radius_attr_info_t));
+ GHashTable* by_id;
+
+ if (vendor_name) {
+ radius_vendor_info_t* v;
+ v = g_hash_table_lookup(dict->vendors_by_name,vendor_name);
+
+ 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] );
+ g_free(name);
+ g_free(code);
+ g_free(vendor_name);
+ BEGIN JUNK;
+ return;
+ } else {
+ by_id = v->attrs_by_id;
+ }
+ } else {
+ by_id = dict->attrs_by_id;
+ }
+
+ a->name = name;
+ a->code = strtol(code,NULL,10); g_free(code);
+ 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,a->name,a);
+}
+
+void add_value(gchar* attrib_name, gchar* value_repr, long value) {
+ value_string v;
+ GArray* a = g_hash_table_lookup(value_strings,attrib_name);
+
+ if (! a) {
+ a = g_array_new(TRUE,TRUE,sizeof(value_string));
+ g_hash_table_insert(value_strings,attrib_name,a);
+ }
+
+ v.value = value;
+ v.strptr = value_repr;
+
+ g_array_append_val(a,v);
+}
+
+
+void setup_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
+ radius_attr_info_t* a = v;
+ gpointer key;
+
+ union {
+ GArray* a;
+ 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);
+ g_free(key);
+ }
+}
+
+void setup_vendors(gpointer k _U_, gpointer v, gpointer p) {
+ radius_vendor_info_t* vnd = v;
+
+ g_hash_table_foreach(vnd->attrs_by_id,setup_attrs,p);
+}
+
+gboolean destroy_values(gpointer k, gpointer v, gpointer p _U_) {
+ g_free(k);
+ g_array_free(v,FALSE);
+ return TRUE;
+}
+
+gboolean destroy_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
+ radius_attr_info_t* a = v;
+ int i;
+
+ g_free(a->name);
+ if (a->vs) {
+ for(i=0; a->vs[i].strptr; i++) {
+ g_free(a->vs[i].strptr); /* fake const warning */
+ }
+ g_free(a->vs);
+ }
+ g_free(a);
+ return TRUE;
+}
+
+gboolean destroy_vendors(gpointer k _U_, gpointer v, gpointer p) {
+ radius_vendor_info_t* vnd = v;
+ g_free(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;
+}
+
+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);
+}
+
+radius_dictionary_t* radius_load_dictionary (gchar* dir, gchar* filename, gchar** err_str) {
+ int i;
+
+ directory = dir;
+
+ fullpaths[include_stack_ptr] = g_strdup_printf("%s%c%s",directory,DIR_SEPARATOR,filename);
+
+ error = g_string_new("");
+
+ yyin = fopen(fullpaths[include_stack_ptr],"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;
+ }
+
+ 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);
+
+ value_strings = g_hash_table_new(g_str_hash,g_str_equal);
+
+ BEGIN OUT;
+
+ yylex();
+
+ for (i=0; i < 10; i++) {
+ if (fullpaths[i]) g_free(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_values,NULL);
+
+ if (error->len > 0) {
+ *err_str = error->str;
+ g_string_free(error,FALSE);
+ destroy_dict(dict);
+ return NULL;
+ } else {
+ *err_str = NULL;
+ g_string_free(error,TRUE);
+ return dict;
+ }
+}