4 %option never-interactive
5 %option prefix="Radius"
8 %option outfile="radius_dict.c"
13 * RADIUS dictionary parser
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
19 * Copyright 1998 Gerald Combs
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #include <epan/packet.h>
47 #include <epan/dissectors/packet-radius.h>
49 #define MAX_INCLUDE_DEPTH 10
51 void add_vendor(const gchar* name, guint32 vendor_id);
52 void add_value(const gchar* attrib_name,const gchar* value_repr, long value);
53 void add_attribute(const gchar*,const gchar*, radius_attr_dissector_t,const gchar*, gboolean, gboolean);
55 static YY_BUFFER_STATE include_stack[10];
56 static int include_stack_ptr = 0;
58 static radius_dictionary_t* dict = NULL;
59 static GHashTable* value_strings = NULL; /* GArray(value_string) by attribute name */
61 static gchar* attr_name = NULL;
62 static gchar* attr_id = NULL;
63 static radius_attr_dissector_t* attr_type = NULL;
64 static gchar* attr_vendor = NULL;
65 static gchar* vendor_name = NULL;
66 static gchar* value_repr = NULL;
67 static gboolean encrypted = FALSE;
68 static gboolean has_tag = FALSE;
69 static gchar* current_vendor = NULL;
71 static GString* error = NULL;
72 static gchar* directory = NULL;
73 static int linenums[] = {1,1,1,1,1,1,1,1,1,1};
74 static gchar* fullpaths[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
78 %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
85 <OUT>VENDOR { BEGIN VENDOR; }
86 <OUT>ATTRIBUTE { BEGIN ATTR; }
87 <OUT>VALUE { BEGIN VALUE; }
88 <OUT>\$INCLUDE { BEGIN INCLUDE; }
89 <OUT>BEGIN-VENDOR { BEGIN BEGIN_VENDOR; }
90 <OUT>END-VENDOR { BEGIN END_VENDOR; }
92 <BEGIN_VENDOR>[0-9a-z_-]+ {
94 g_free(current_vendor);
96 current_vendor = g_strdup(yytext);
100 if (current_vendor) {
101 g_free(current_vendor);
102 current_vendor = NULL;
107 <VENDOR>[0-9a-z_-]+ { vendor_name = g_strdup(yytext); BEGIN VENDOR_W_NAME; }
108 <VENDOR_W_NAME>[0-9]+ {
109 add_vendor(vendor_name,strtol(yytext,NULL,10));
113 <VENDOR_W_NAME>0x[0-9a-f]+ {
114 add_vendor(vendor_name,strtol(yytext,NULL,16));
119 <ATTR>[0-9a-z_/-]+ { attr_name = g_strdup(yytext); encrypted = FALSE; has_tag = FALSE; BEGIN ATTR_W_NAME; }
120 <ATTR_W_NAME>[0-9]+ { attr_id = g_strdup(yytext); BEGIN ATTR_W_ID;}
121 <ATTR_W_NAME>0x[0-9a-f]+ { attr_id = g_strdup_printf("%u",(int)strtoul(yytext,NULL,16)); BEGIN ATTR_W_ID;}
122 <ATTR_W_ID>integer { attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
123 <ATTR_W_ID>string { attr_type = radius_string; BEGIN ATTR_W_TYPE; }
124 <ATTR_W_ID>octets { attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
125 <ATTR_W_ID>ipaddr { attr_type = radius_ipaddr; BEGIN ATTR_W_TYPE; }
126 <ATTR_W_ID>ipv6addr { attr_type = radius_ipv6addr; BEGIN ATTR_W_TYPE; }
127 <ATTR_W_ID>ipxnet { attr_type = radius_ipxnet; BEGIN ATTR_W_TYPE; }
128 <ATTR_W_ID>date { attr_type = radius_date; BEGIN ATTR_W_TYPE; }
129 <ATTR_W_ID>ifid { attr_type = radius_ifid; BEGIN ATTR_W_TYPE; }
130 <ATTR_W_ID>[0-9a-z_-]+ { attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
131 <ATTR_W_TYPE>has_tag[,]? { has_tag = TRUE; }
132 <ATTR_W_TYPE>encrypt=1[,]? { encrypted=TRUE; }
133 <ATTR_W_TYPE>[0-9a-z_-]+=([^\n]*) ;
134 <ATTR_W_TYPE>[0-9a-z_-]+ {
135 attr_vendor = g_strdup(yytext);
136 add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag);
146 add_attribute(attr_name,attr_id,attr_type,current_vendor,encrypted,has_tag);
149 linenums[include_stack_ptr]++;
155 add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag);
159 linenums[include_stack_ptr]++;
163 <VALUE>[0-9a-z_/-]+ { attr_name = g_strdup(yytext); BEGIN VALUE_W_ATTR; }
164 <VALUE_W_ATTR>[^[:blank:]]+ { value_repr = g_strdup(yytext); BEGIN VALUE_W_NAME; }
165 <VALUE_W_NAME>[0-9]+ { add_value(attr_name,value_repr,strtol(yytext,NULL,10)); g_free(attr_name); g_free(value_repr); BEGIN OUT;}
166 <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 OUT;}
168 <INCLUDE>[^[:blank:]\n]+ {
169 if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
170 g_string_sprintfa(error, "$INCLUDE files nested to deeply\n");
174 include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
176 fullpaths[include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
179 yyin = fopen( fullpaths[include_stack_ptr], "r" );
183 g_string_sprintfa(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
187 linenums[include_stack_ptr] = 1;
188 yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
200 if ( --include_stack_ptr < 0 ) {
203 g_free(fullpaths[include_stack_ptr+1]);
204 fullpaths[include_stack_ptr+1] = NULL;
206 yy_delete_buffer( YY_CURRENT_BUFFER );
207 yy_switch_to_buffer(include_stack[include_stack_ptr]);
213 \n { linenums[include_stack_ptr]++; BEGIN OUT; }
218 void add_vendor(const gchar* name, guint32 vendor_id) {
219 radius_vendor_info_t* v = g_malloc(sizeof(radius_vendor_info_t));
221 v->name = g_strdup(name);
223 v->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
226 g_hash_table_insert(dict->vendors_by_id,GUINT_TO_POINTER(v->code),v);
227 g_hash_table_insert(dict->vendors_by_name,v->name,v);
230 void add_attribute(const gchar* name, const gchar* code, radius_attr_dissector_t type, const gchar* vendor_name, gboolean crypt, gboolean tagged) {
231 radius_attr_info_t* a = g_malloc(sizeof(radius_attr_info_t));
235 radius_vendor_info_t* v;
236 v = g_hash_table_lookup(dict->vendors_by_name,vendor_name);
239 g_string_sprintfa(error, "Vendor: '%s', does not exist in %s:%i \n", vendor_name, fullpaths[include_stack_ptr], linenums[include_stack_ptr] );
243 by_id = v->attrs_by_id;
246 by_id = dict->attrs_by_id;
249 a->name = g_strdup(name);
250 a->code = strtol(code,NULL,10);
262 g_hash_table_insert(by_id,GUINT_TO_POINTER(a->code),a);
263 g_hash_table_insert(dict->attrs_by_name,(gpointer) (a->name),a);
266 void add_value(const gchar* attrib_name, const gchar* value_repr, long value) {
268 GArray* a = g_hash_table_lookup(value_strings,attrib_name);
271 a = g_array_new(TRUE,TRUE,sizeof(value_string));
272 g_hash_table_insert(value_strings,g_strdup(attrib_name),a);
276 v.strptr = g_strdup(value_repr);
278 g_array_append_val(a,v);
282 static void setup_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
283 radius_attr_info_t* a = v;
291 if (g_hash_table_lookup_extended(value_strings,a->name,&key,&vs.p) ) {
292 a->vs = (value_string*) vs.a->data;
293 g_array_free(vs.a,FALSE);
294 g_hash_table_remove(value_strings,key);
299 static void setup_vendors(gpointer k _U_, gpointer v, gpointer p) {
300 radius_vendor_info_t* vnd = v;
302 g_hash_table_foreach(vnd->attrs_by_id,setup_attrs,p);
305 static gboolean destroy_value_strings(gpointer k, gpointer v, gpointer p _U_) {
306 value_string* vs = (value_string*)(((GArray*)v)->data);
310 for (;vs->strptr;vs++) {
311 g_free((void*)vs->strptr);
314 g_array_free(v,TRUE);
318 static gboolean destroy_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
319 radius_attr_info_t* a = v;
322 g_free((gpointer) (a->name));
324 for(i=0; a->vs[i].strptr; i++) {
325 g_free((void *)a->vs[i].strptr);
327 g_free((void *)a->vs);
333 static gboolean destroy_vendors(gpointer k _U_, gpointer v, gpointer p) {
334 radius_vendor_info_t* vnd = v;
336 g_hash_table_foreach_remove(vnd->attrs_by_id,destroy_attrs,p);
337 g_hash_table_destroy(vnd->attrs_by_id);
342 static void destroy_dict(radius_dictionary_t* d) {
343 g_hash_table_foreach_remove(d->attrs_by_id,destroy_attrs,NULL);
344 g_hash_table_foreach_remove(d->vendors_by_id,destroy_vendors,NULL);
345 g_hash_table_destroy(d->vendors_by_id);
346 g_hash_table_destroy(d->attrs_by_id);
347 g_hash_table_destroy(d->vendors_by_name);
348 g_hash_table_destroy(d->attrs_by_name);
352 radius_dictionary_t* radius_load_dictionary (gchar* dir, const gchar* filename, gchar** err_str) {
357 fullpaths[include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
360 error = g_string_new("");
362 yyin = fopen(fullpaths[include_stack_ptr],"r");
365 g_string_sprintfa(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
366 g_free(fullpaths[include_stack_ptr]);
367 *err_str = error->str;
368 g_string_free(error,FALSE);
372 dict = g_malloc(sizeof(radius_dictionary_t));
373 dict->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
374 dict->attrs_by_name = g_hash_table_new(g_str_hash,g_str_equal);
375 dict->vendors_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
376 dict->vendors_by_name = g_hash_table_new(g_str_hash,g_str_equal);
378 value_strings = g_hash_table_new(g_str_hash,g_str_equal);
384 if (yyin != NULL) fclose(yyin);
387 for (i=0; i < 10; i++) {
388 if (fullpaths[i]) g_free(fullpaths[i]);
391 g_hash_table_foreach(dict->attrs_by_id,setup_attrs,NULL);
392 g_hash_table_foreach(dict->vendors_by_id,setup_vendors,NULL);
393 g_hash_table_foreach_remove(value_strings,destroy_value_strings,NULL);
395 if (error->len > 0) {
396 *err_str = error->str;
397 g_string_free(error,FALSE);
402 g_string_free(error,TRUE);