2 /* Include this before everything else, for various large-file definitions */
7 * We want a reentrant scanner.
12 * We don't use input, so don't generate code for it.
17 * We don't use unput, so don't generate code for it.
22 * We don't read interactively from the terminal.
24 %option never-interactive
27 * We want to stop processing when we get to the end of the input.
32 * The language we're scanning is case-insensitive.
37 * The type for the state we keep for a scanner.
39 %option extra-type="Radius_scanner_state_t*"
42 * We have to override the memory allocators so that we don't get
43 * "unused argument" warnings from the yyscanner argument (which
44 * we don't use, as we have a global memory allocator).
46 * We provide, as macros, our own versions of the routines generated by Flex,
47 * which just call malloc()/realloc()/free() (as the Flex versions do),
48 * discarding the extra argument.
55 * Prefix scanner routines with "Radius_" rather than "yy", so this scanner
56 * can coexist with other scanners.
58 %option prefix="Radius_"
60 %option outfile="radius_dict.c"
65 * RADIUS dictionary parser
67 * Wireshark - Network traffic analyzer
68 * By Gerald Combs <gerald@wireshark.org>
69 * Copyright 1998 Gerald Combs
71 * This program is free software; you can redistribute it and/or
72 * modify it under the terms of the GNU General Public License
73 * as published by the Free Software Foundation; either version 2
74 * of the License, or (at your option) any later version.
76 * This program is distributed in the hope that it will be useful,
77 * but WITHOUT ANY WARRANTY; without even the implied warranty of
78 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
79 * GNU General Public License for more details.
81 * You should have received a copy of the GNU General Public License
82 * along with this program; if not, write to the Free Software
83 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
91 #include <epan/packet.h>
92 #include <epan/dissectors/packet-radius.h>
93 #include <wsutil/file_util.h>
98 * http://freeradius.org/radiusd/man/dictionary.html
100 * for the format of RADIUS dictionary files.
102 * XXX - features not currently supported:
104 * dotted number values for the oid field;
106 * integer64, ipv4prefix, combo-prefix, bool, size, decimal,
107 * timeval, struct, extended, long-extended, vsa, evs, vendor,
108 * cidr, uint{8,16,32,64}, int{8,16,32,64} as attribute types
109 * (some of these aren't documented);
111 * octets[N], where N is an integer, as an attribute type
112 * (not documented in the man page);
114 * internal, array, concat, and virtual as attribute flags;
116 * format= for BEGIN-VENDOR.
118 * We should, perhaps, adopt FreeRADIUS's dictionary-parsing code in
119 * src/lib/dict.c and use that, rather than writing our own parser.
122 #define YY_USER_INIT BEGIN WS_OUT;
125 /* disable Windows VC compiler warning "signed/unsigned mismatch" associated */
126 /* with YY_INPUT code generated by flex versions such as 2.5.35. */
127 #pragma warning (disable:4018)
131 #define MAX_INCLUDE_DEPTH 10
134 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
135 int include_stack_ptr;
137 radius_dictionary_t* dict;
138 GHashTable* value_strings; /* GArray(value_string) by attribute name */
142 radius_attr_dissector_t* attr_type;
146 guint vendor_type_octets;
147 guint vendor_length_octets;
148 gboolean vendor_has_flags;
152 gchar* current_vendor;
156 gchar* fullpaths[MAX_INCLUDE_DEPTH];
157 int linenums[MAX_INCLUDE_DEPTH];
160 } Radius_scanner_state_t;
162 static void add_vendor(Radius_scanner_state_t* state, const gchar* name, guint32 id, guint type_octets, guint length_octets, gboolean has_flags);
163 static gboolean add_attribute(Radius_scanner_state_t* state, const gchar*,const gchar*, radius_attr_dissector_t,const gchar*, guint, gboolean, const gchar*);
164 static gboolean add_tlv(Radius_scanner_state_t* state, const gchar* name, const gchar* code, radius_attr_dissector_t type, const gchar* attr);
165 static void add_value(Radius_scanner_state_t* state, const gchar* attrib_name, const gchar* repr, guint32 value);
168 * Sleazy hack to suppress compiler warnings in yy_fatal_error().
170 #define YY_EXIT_FAILURE ((void)yyscanner, 2)
173 * Macros for the allocators, to discard the extra argument.
175 #define Radius_alloc(size, yyscanner) (void *)malloc(size)
176 #define Radius_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
177 #define Radius_free(ptr, yyscanner) free((char *)ptr)
181 /* Note: FreeRadius allows VENDOR, ATTRIBUTE and VALUE names to contain any non-blank character.
182 * Using a negated "blank character class" pattern below for those names fails for some reason
183 * so for now the patterns for each name type include those characters found for the corresponding
184 * name types in the FreeRadius dictionaries.
187 %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 VENDOR_W_ID VENDOR_W_FORMAT VENDOR_W_TYPE_OCTETS VENDOR_W_LENGTH_OCTETS VENDOR_W_CONTINUATION BEGIN_TLV END_TLV
194 <WS_OUT>VENDOR { BEGIN VENDOR; }
195 <WS_OUT>ATTRIBUTE { BEGIN ATTR; }
196 <WS_OUT>VALUE { BEGIN VALUE; }
197 <WS_OUT>\$INCLUDE { BEGIN INCLUDE; }
198 <WS_OUT>BEGIN-VENDOR { BEGIN BEGIN_VENDOR; }
199 <WS_OUT>END-VENDOR { BEGIN END_VENDOR; }
200 <WS_OUT>BEGIN-TLV { BEGIN BEGIN_TLV; }
201 <WS_OUT>END-TLV { BEGIN END_TLV; }
203 <BEGIN_VENDOR>[0-9a-z_-]+ {
204 if (yyextra->current_vendor) {
205 g_free(yyextra->current_vendor);
207 yyextra->current_vendor = g_strdup(yytext);
211 if (yyextra->current_vendor) {
212 g_free(yyextra->current_vendor);
213 yyextra->current_vendor = NULL;
218 <BEGIN_TLV>[0-9a-z_-]+ {
219 if (yyextra->current_attr) {
220 g_free(yyextra->current_attr);
222 yyextra->current_attr = g_strdup(yytext);
226 if (yyextra->current_attr) {
227 g_free(yyextra->current_attr);
228 yyextra->current_attr = NULL;
233 <VENDOR>[0-9a-z_-]+ {
234 yyextra->vendor_name = g_strdup(yytext);
235 yyextra->vendor_type_octets = 1;
236 yyextra->vendor_length_octets = 1;
237 yyextra->vendor_has_flags = FALSE;
240 <VENDOR_W_NAME>[0-9]+ {
241 yyextra->vendor_id = (guint32) strtoul(yytext,NULL,10);
244 <VENDOR_W_NAME>0x[0-9a-f]+ {
245 yyextra->vendor_id = (guint32) strtoul(yytext,NULL,16);
248 <VENDOR_W_ID>format= {
249 BEGIN VENDOR_W_FORMAT;
251 <VENDOR_W_FORMAT>[124] {
252 yyextra->vendor_type_octets = (guint) strtoul(yytext,NULL,10);
253 BEGIN VENDOR_W_TYPE_OCTETS;
255 <VENDOR_W_TYPE_OCTETS>,[012] {
256 yyextra->vendor_length_octets = (guint) strtoul(yytext+1,NULL,10);
257 BEGIN VENDOR_W_LENGTH_OCTETS;
259 <VENDOR_W_LENGTH_OCTETS>,c {
260 yyextra->vendor_has_flags = TRUE;
261 BEGIN VENDOR_W_CONTINUATION;
263 <VENDOR_W_FORMAT>\n |
264 <VENDOR_W_TYPE_OCTETS>\n |
265 <VENDOR_W_LENGTH_OCTETS>\n |
266 <VENDOR_W_CONTINUATION>\n |
268 add_vendor(yyextra, yyextra->vendor_name, yyextra->vendor_id, yyextra->vendor_type_octets, yyextra->vendor_length_octets, yyextra->vendor_has_flags);
269 g_free(yyextra->vendor_name);
273 <ATTR>[0-9a-z_/.-]+ { yyextra->attr_name = g_strdup(yytext); yyextra->encrypted = 0; yyextra->has_tag = FALSE; BEGIN ATTR_W_NAME; }
274 <ATTR_W_NAME>[0-9]+ { yyextra->attr_id = g_strdup(yytext); BEGIN ATTR_W_ID;}
275 <ATTR_W_NAME>0x[0-9a-f]+ { yyextra->attr_id = g_strdup_printf("%u",(int)strtoul(yytext,NULL,16)); BEGIN ATTR_W_ID;}
276 <ATTR_W_ID>integer { yyextra->attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
277 <ATTR_W_ID>string { yyextra->attr_type = radius_string; BEGIN ATTR_W_TYPE; }
278 <ATTR_W_ID>octets { yyextra->attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
279 <ATTR_W_ID>ipaddr { yyextra->attr_type = radius_ipaddr; BEGIN ATTR_W_TYPE; }
280 <ATTR_W_ID>ipv6addr { yyextra->attr_type = radius_ipv6addr; BEGIN ATTR_W_TYPE; }
281 <ATTR_W_ID>ipv6prefix { yyextra->attr_type = radius_ipv6prefix; BEGIN ATTR_W_TYPE; }
282 <ATTR_W_ID>ipxnet { yyextra->attr_type = radius_ipxnet; BEGIN ATTR_W_TYPE; }
283 <ATTR_W_ID>date { yyextra->attr_type = radius_date; BEGIN ATTR_W_TYPE; }
284 <ATTR_W_ID>abinary { yyextra->attr_type = radius_abinary; BEGIN ATTR_W_TYPE; }
285 <ATTR_W_ID>ether { yyextra->attr_type = radius_ether; BEGIN ATTR_W_TYPE; }
286 <ATTR_W_ID>ifid { yyextra->attr_type = radius_ifid; BEGIN ATTR_W_TYPE; }
287 <ATTR_W_ID>byte { yyextra->attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
288 <ATTR_W_ID>short { yyextra->attr_type = radius_integer; BEGIN ATTR_W_TYPE; }
289 <ATTR_W_ID>signed { yyextra->attr_type = radius_signed; BEGIN ATTR_W_TYPE; }
290 <ATTR_W_ID>combo-ip { yyextra->attr_type = radius_combo_ip; BEGIN ATTR_W_TYPE; }
291 <ATTR_W_ID>tlv { yyextra->attr_type = radius_tlv; BEGIN ATTR_W_TYPE; }
292 <ATTR_W_ID>[0-9a-z_-]+ { yyextra->attr_type = radius_octets; BEGIN ATTR_W_TYPE; }
293 <ATTR_W_TYPE>has_tag[,]? { yyextra->has_tag = TRUE; }
294 <ATTR_W_TYPE>encrypt=[123][,]? { yyextra->encrypted = (guint) strtoul(yytext+8,NULL,10); }
295 <ATTR_W_TYPE>[0-9a-z_-]+=([^\n]*) ;
296 <ATTR_W_TYPE>[0-9a-z_-]+ {
297 gboolean attribute_ok;
299 yyextra->attr_vendor = g_strdup(yytext);
300 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);
301 g_free(yyextra->attr_id);
302 g_free(yyextra->attr_vendor);
303 g_free(yyextra->attr_name);
304 yyextra->attr_id = NULL;
305 yyextra->attr_vendor = NULL;
306 yyextra->attr_name = NULL;
313 add_attribute(yyextra, yyextra->attr_name, yyextra->attr_id, yyextra->attr_type, yyextra->current_vendor, yyextra->encrypted, yyextra->has_tag, yyextra->current_attr);
314 g_free(yyextra->attr_id);
315 g_free(yyextra->attr_name);
316 yyextra->linenums[yyextra->include_stack_ptr]++;
317 yyextra->has_tag = FALSE;
318 yyextra->encrypted=FALSE;
322 add_attribute(yyextra, yyextra->attr_name, yyextra->attr_id, yyextra->attr_type, yyextra->attr_vendor, yyextra->encrypted, yyextra->has_tag, yyextra->current_attr);
323 g_free(yyextra->attr_id);
324 g_free(yyextra->attr_vendor);
325 g_free(yyextra->attr_name);
326 yyextra->linenums[yyextra->include_stack_ptr]++;
330 <VALUE>[0-9a-z_/-]+ { yyextra->attr_name = g_strdup(yytext); BEGIN VALUE_W_ATTR; }
331 <VALUE_W_ATTR>[^[:blank:]]+ { yyextra->value_repr = g_strdup(yytext); BEGIN VALUE_W_NAME; }
332 <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;}
333 <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;}
335 <INCLUDE>[^[:blank:]\n]+ {
336 if ( yyextra->include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
337 g_string_append_printf(yyextra->error, "$INCLUDE files nested too deeply\n");
341 yyextra->include_stack[yyextra->include_stack_ptr++] = YY_CURRENT_BUFFER;
343 yyextra->fullpaths[yyextra->include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
344 yyextra->directory,yytext);
346 yyin = ws_fopen( yyextra->fullpaths[yyextra->include_stack_ptr], "r" );
350 g_string_append_printf(yyextra->error,
351 "Could not open file: '%s', error: %s\n",
352 yyextra->fullpaths[yyextra->include_stack_ptr],
355 g_string_append_printf(yyextra->error,
356 "Could not open file: '%s', no errno\n",
357 yyextra->fullpaths[yyextra->include_stack_ptr]);
359 g_free(yyextra->fullpaths[yyextra->include_stack_ptr]);
360 yyextra->fullpaths[yyextra->include_stack_ptr] = NULL;
361 yyextra->include_stack_ptr--;
363 yyextra->linenums[yyextra->include_stack_ptr] = 1;
364 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner), yyscanner);
376 if ( --yyextra->include_stack_ptr < 0 ) {
379 g_free(yyextra->fullpaths[yyextra->include_stack_ptr+1]);
380 yyextra->fullpaths[yyextra->include_stack_ptr+1] = NULL;
382 Radius__delete_buffer(YY_CURRENT_BUFFER, yyscanner);
383 Radius__switch_to_buffer(yyextra->include_stack[yyextra->include_stack_ptr], yyscanner);
389 \n { yyextra->linenums[yyextra->include_stack_ptr]++; BEGIN WS_OUT; }
394 static void add_vendor(Radius_scanner_state_t* state, const gchar* name, guint32 id, guint type_octets, guint length_octets, gboolean has_flags) {
395 radius_vendor_info_t* v;
397 v = (radius_vendor_info_t *)g_hash_table_lookup(state->dict->vendors_by_id, GUINT_TO_POINTER(id));
402 * Allocate a new entry and insert it into the by-ID and
403 * by-name hash tables.
405 v = g_new(radius_vendor_info_t,1);
406 v->attrs_by_id = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_radius_attr_info);
409 v->name = g_strdup(name);
410 v->type_octets = type_octets;
411 v->length_octets = length_octets;
412 v->has_flags = has_flags;
414 g_hash_table_insert(state->dict->vendors_by_id,GUINT_TO_POINTER(v->code),v);
415 g_hash_table_insert(state->dict->vendors_by_name, (gpointer) v->name, v);
418 * This vendor is already in the table.
420 * Assume that the dictionary knows the 'ground truth' about
421 * the type/length/has_flags information and thus allow the
422 * dictionary to overwrite these values even for vendors that
423 * have already been loaded.
425 * XXX - this could be due to the vendor being in multiple
426 * dictionary files, rather than having been specially
427 * entered by the RADIUS dissector, as a side effect of
428 * specially entering an attribute; should we report vendors
429 * that appear in different dictionaries with different
432 v->type_octets = type_octets;
433 v->length_octets = length_octets;
434 v->has_flags = has_flags;
437 * Did the name change?
439 if (g_strcmp0(v->name, name) != 0) {
441 * Yes. Remove the entry from the by-name hash table
442 * and re-insert it with the new name.
444 g_hash_table_remove(state->dict->vendors_by_name, (gpointer) v->name);
445 g_free((gpointer) v->name);
446 v->name = g_strdup(name);
447 g_hash_table_insert(state->dict->vendors_by_name, (gpointer) v->name, v);
452 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) {
453 radius_attr_info_t* a;
458 return add_tlv(state, name, codestr, type, attr);
463 radius_vendor_info_t* v;
464 v = (radius_vendor_info_t *)g_hash_table_lookup(state->dict->vendors_by_name,vendor);
467 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] );
470 by_id = v->attrs_by_id;
473 by_id = state->dict->attrs_by_id;
476 code= (guint32) strtoul(codestr, NULL, 10);
478 a=(radius_attr_info_t*)g_hash_table_lookup(by_id, GUINT_TO_POINTER(code));
483 * Allocate a new entry and insert it into the by-ID and
484 * by-name hash tables.
486 a = g_new(radius_attr_info_t,1);
488 a->name = g_strdup(name);
490 a->encrypt = encrypted_flag;
499 a->tlvs_by_id = NULL;
500 g_hash_table_insert(by_id, GUINT_TO_POINTER(code),a);
501 g_hash_table_insert(state->dict->attrs_by_name,(gpointer) (a->name),a);
504 * This attribute is already in the table.
506 * Overwrite the encrypted flag, tagged property, and type;
507 * the other properties don't get set until after we've
508 * finished reading the dictionaries.
510 * XXX - this could be due to the attribute being in
511 * multiple dictionary files, rather than having been
512 * specially entered by the RADIUS dissector to give it
513 * a special dissection routine; should we report attributes
514 * that appear in different dictionaries with different
517 a->encrypt = encrypted_flag;
522 * Did the name change?
524 if (g_strcmp0(a->name, name) != 0) {
526 * Yes. Remove the entry from the by-name hash table
527 * and re-insert it with the new name.
529 g_hash_table_remove(state->dict->attrs_by_name, (gpointer) (a->name));
530 g_free((gpointer) a->name);
531 a->name = g_strdup(name);
532 g_hash_table_insert(state->dict->attrs_by_name, (gpointer) (a->name),a);
538 static gboolean add_tlv(Radius_scanner_state_t* state, const gchar* name, const gchar* codestr, radius_attr_dissector_t type, const gchar* attr) {
539 radius_attr_info_t* a;
540 radius_attr_info_t* s;
543 a = (radius_attr_info_t*)g_hash_table_lookup(state->dict->attrs_by_name, attr);
546 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]);
550 if (type == radius_tlv) {
551 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]);
556 if (! a->tlvs_by_id) {
557 a->tlvs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
560 code = (guint32) strtoul(codestr, NULL, 10);
562 s = (radius_attr_info_t*)g_hash_table_lookup(a->tlvs_by_id, GUINT_TO_POINTER(code));
566 * This TLV doesn't yet exist in this attribute's TLVs-by-ID
567 * hash table. Add it.
569 s = g_new(radius_attr_info_t,1);
570 s->name = g_strdup(name);
583 s->tlvs_by_id = NULL;
585 g_hash_table_insert(a->tlvs_by_id,GUINT_TO_POINTER(s->code),s);
586 g_hash_table_insert(state->dict->tlvs_by_name,(gpointer) (s->name),s);
590 * If it *does* exist, leave it alone; there shouldn't be duplicate
591 * entries by name in the dictionaries (even if there might be
592 * multiple entries for a given attribute in the dictionaries, each
593 * one adding some TLV values), and we don't directly add entries
594 * for TLVs in the RADIUS dissector.
596 * XXX - report the duplicate entries?
601 void add_value(Radius_scanner_state_t* state, const gchar* attrib_name, const gchar* repr, guint32 value) {
603 GArray* a = (GArray*)g_hash_table_lookup(state->value_strings,attrib_name);
606 a = g_array_new(TRUE,TRUE,sizeof(value_string));
607 g_hash_table_insert(state->value_strings,g_strdup(attrib_name),a);
611 v.strptr = g_strdup(repr);
613 g_array_append_val(a,v);
616 static void setup_tlvs(gpointer k _U_, gpointer v, gpointer p) {
617 radius_attr_info_t* s = (radius_attr_info_t*)v;
618 Radius_scanner_state_t* state = (Radius_scanner_state_t*)p;
626 if (g_hash_table_lookup_extended(state->value_strings, s->name, &key, &vs.p)) {
627 s->vs = (value_string*)(void *)vs.a->data;
628 g_array_free(vs.a, FALSE);
629 g_hash_table_remove(state->value_strings, key);
634 static void setup_attrs(gpointer k _U_, gpointer v, gpointer p) {
635 radius_attr_info_t* a = (radius_attr_info_t*)v;
636 Radius_scanner_state_t* state = (Radius_scanner_state_t*)p;
644 if (g_hash_table_lookup_extended(state->value_strings,a->name,&key,&vs.p) ) {
645 a->vs = (value_string*)(void *)vs.a->data;
646 g_array_free(vs.a,FALSE);
647 g_hash_table_remove(state->value_strings,key);
652 g_hash_table_foreach(a->tlvs_by_id, setup_tlvs, p);
656 static void setup_vendors(gpointer k _U_, gpointer v, gpointer p) {
657 radius_vendor_info_t* vnd = (radius_vendor_info_t*)v;
659 g_hash_table_foreach(vnd->attrs_by_id,setup_attrs,p);
662 static gboolean destroy_value_strings(gpointer k, gpointer v, gpointer p _U_) {
663 value_string* vs = (value_string*)(void *)(((GArray*)v)->data);
667 for (;vs->strptr;vs++) {
668 g_free((void*)vs->strptr);
671 g_array_free((GArray*)v,TRUE);
675 gboolean radius_load_dictionary (radius_dictionary_t* d, gchar* dir, const gchar* filename, gchar** err_str) {
678 Radius_scanner_state_t state;
681 state.include_stack_ptr = 0;
684 state.value_strings = NULL;
686 state.attr_name = NULL;
687 state.attr_id = NULL;
688 state.attr_type = NULL;
689 state.attr_vendor = NULL;
690 state.vendor_name = NULL;
692 state.vendor_type_octets = 1;
693 state.vendor_length_octets = 1;
694 state.vendor_has_flags = FALSE;
695 state.value_repr = NULL;
697 state.has_tag = FALSE;
698 state.current_vendor = NULL;
699 state.current_attr = NULL;
701 state.directory = dir;
703 state.fullpaths[0] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
704 state.directory,filename);
705 state.linenums[0] = 1;
706 for (i = 1; i < MAX_INCLUDE_DEPTH; i++) {
707 state.fullpaths[i] = NULL;
708 state.linenums[i] = 1;
711 state.error = g_string_new("");
713 in = ws_fopen(state.fullpaths[0],"r");
716 g_string_append_printf(state.error, "Could not open file: '%s', error: %s\n", state.fullpaths[0], g_strerror(errno));
717 g_free(state.fullpaths[0]);
718 *err_str = g_string_free(state.error,FALSE);
722 state.value_strings = g_hash_table_new(g_str_hash,g_str_equal);
724 if (Radius_lex_init(&scanner) != 0) {
725 g_string_append_printf(state.error, "Can't initialize scanner: %s",
728 g_free(state.fullpaths[0]);
729 *err_str = g_string_free(state.error,FALSE);
733 Radius_set_in(in, scanner);
735 /* Associate the state with the scanner */
736 Radius_set_extra(&state, scanner);
740 Radius_lex_destroy(scanner);
742 * XXX - can the lexical analyzer terminate without closing
743 * all open input files?
746 for (i = 0; i < MAX_INCLUDE_DEPTH; i++) {
747 if (state.fullpaths[i])
748 g_free(state.fullpaths[i]);
751 g_hash_table_foreach(state.dict->attrs_by_id,setup_attrs,&state);
752 g_hash_table_foreach(state.dict->vendors_by_id,setup_vendors,&state);
753 g_hash_table_foreach_remove(state.value_strings,destroy_value_strings,NULL);
755 if (state.error->len > 0) {
756 *err_str = g_string_free(state.error,FALSE);
760 g_string_free(state.error,TRUE);
766 * Editor modelines - http://www.wireshark.org/tools/modelines.html
771 * indent-tabs-mode: t
774 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
775 * :indentSize=8:tabSize=8:noTabs=false: