Throw in some casts to squelch warnings, at least with some compilers
[metze/wireshark/wip.git] / epan / radius_dict.l
1 %option noyywrap
2
3 %option nounput
4 %option never-interactive
5 %option prefix="Radius"
6 %option caseless
7
8 %option outfile="radius_dict.c"
9
10 %{
11         /* packet-radius.c
12         *
13         * RADIUS dictionary parser
14         *
15         * $Id$
16         *
17         * Ethereal - Network traffic analyzer
18         * By Gerald Combs <gerald@ethereal.com>
19         * Copyright 1998 Gerald Combs
20         *
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.
25         *
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.
30         *
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.
34         *
35         */
36         
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40         
41 #include <glib.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <epan/packet.h>
47 #include <epan/dissectors/packet-radius.h>
48 #define DIR_SEPARATOR '/'
49 #define ECHO
50 #define MAX_INCLUDE_DEPTH 10
51
52         void add_vendor(gchar* name, guint32 vendor_id);
53         void add_value(gchar* attrib_name, gchar* value_repr, long value);
54         void add_attribute(gchar*, gchar*, radius_attr_dissector_t, gchar*, gboolean, gboolean);
55         
56         static YY_BUFFER_STATE include_stack[10];
57         static int include_stack_ptr = 0;
58         
59         static radius_dictionary_t* dict = NULL;
60         static GHashTable* value_strings = NULL; /* GArray(value_string) by attribute name */
61         
62         static gchar* attr_name = NULL;
63         static gchar* attr_id = NULL;
64         static radius_attr_dissector_t* attr_type = NULL;
65         static gchar* attr_vendor = NULL;
66         static gchar* vendor_name = NULL;
67         static gchar* value_repr = NULL;
68         static gboolean encrypt = FALSE;
69         static gboolean has_tag = FALSE;
70         static gchar* current_vendor = NULL;
71         
72         static GString* error = NULL;
73         static gchar* directory = NULL;
74         static int linenums[] = {1,1,1,1,1,1,1,1,1,1};
75         static gchar* fullpaths[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
76         
77 %}
78
79 %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
80 %%
81 [:blank:]   ;
82 #[^\n]*         ;
83
84 <JUNK>.*\qn             ;
85
86 <OUT>VENDOR { BEGIN VENDOR; }
87 <OUT>ATTRIBUTE { BEGIN ATTR; }
88 <OUT>VALUE { BEGIN VALUE; }
89 <OUT>\$INCLUDE { BEGIN INCLUDE; }
90 <OUT>BEGIN-VENDOR { BEGIN BEGIN_VENDOR; }
91 <OUT>END-VENDOR { BEGIN END_VENDOR; }
92
93 <BEGIN_VENDOR>[0-9a-z_-]+ {current_vendor = g_strdup(yytext); BEGIN OUT; }
94 <END_VENDOR>[^\n]* {if (current_vendor) { g_free(current_vendor); current_vendor = NULL; } BEGIN OUT; }
95
96 <VENDOR>[0-9a-z_-]+   { vendor_name = g_strdup(yytext); BEGIN VENDOR_W_NAME; }
97 <VENDOR_W_NAME>[0-9]+   { add_vendor(vendor_name,strtol(yytext,NULL,10)); BEGIN OUT; }
98 <VENDOR_W_NAME>0x[0-9a-f]+   { add_vendor(vendor_name,strtol(yytext,NULL,16)); BEGIN OUT; }
99
100 <ATTR>[0-9a-z_-]+                                       { attr_name = g_strdup(yytext); encrypt = FALSE; has_tag = FALSE; BEGIN ATTR_W_NAME; }
101 <ATTR_W_NAME>[0-9]+                                     { attr_id = g_strdup(yytext);  BEGIN ATTR_W_ID;}
102 <ATTR_W_NAME>0x[0-9a-f]+                        { attr_id = g_strdup_printf("%u",(int)strtoul(yytext,NULL,16)); BEGIN ATTR_W_ID;}
103 <ATTR_W_ID>integer                                      { attr_type = radius_integer;  BEGIN ATTR_W_TYPE; }
104 <ATTR_W_ID>string                                       { attr_type = radius_string;  BEGIN ATTR_W_TYPE; }
105 <ATTR_W_ID>octets                                       { attr_type = radius_octets;  BEGIN ATTR_W_TYPE; }
106 <ATTR_W_ID>ipaddr                                       { attr_type = radius_ipaddr;  BEGIN ATTR_W_TYPE; }
107 <ATTR_W_ID>date                                         { attr_type = radius_date;  BEGIN ATTR_W_TYPE; }
108 <ATTR_W_ID>ipv6addr                                     { attr_type = radius_ipv6addr;  BEGIN ATTR_W_TYPE; }
109 <ATTR_W_ID>ifid                                         { attr_type = radius_ifid;  BEGIN ATTR_W_TYPE; }
110 <ATTR_W_ID>[0-9a-z_-]+                          { attr_type = radius_octets;  BEGIN ATTR_W_TYPE; }
111 <ATTR_W_TYPE>has_tag[,]?                        { has_tag = TRUE; attr_vendor = NULL;  BEGIN ATTR_W_VENDOR; }
112 <ATTR_W_TYPE>encrypt=1[,]?                      { encrypt=TRUE;  attr_vendor = NULL;  BEGIN ATTR_W_VENDOR; }
113 <ATTR_W_TYPE>[,0-9a-z_-]+=([^\n]+)      { /* ignore other parameters */  attr_vendor = NULL;  BEGIN ATTR_W_VENDOR; }
114 <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; }
115 <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; }
116 <ATTR_W_VENDOR>\n                                       { add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypt,has_tag); linenums[include_stack_ptr]++; BEGIN OUT; };
117
118 <VALUE>[0-9a-z-]+                                       { attr_name = g_strdup(yytext); BEGIN VALUE_W_ATTR; }
119 <VALUE_W_ATTR>[^[:blank:]]+                     { value_repr = g_strdup(yytext); BEGIN VALUE_W_NAME; }
120 <VALUE_W_NAME>[0-9]+                            { add_value(attr_name,value_repr,strtol(yytext,NULL,10));  BEGIN OUT;}
121 <VALUE_W_NAME>0x[0-9a-f]+                       { add_value(attr_name,value_repr,strtol(yytext,NULL,16));  BEGIN OUT;}
122
123 <INCLUDE>[^[:blank:]\n]+   {
124         if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
125                 g_string_sprintfa(error, "$INCLUDE files nested to deeply\n");
126                 yyterminate();
127         }
128         
129         include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
130         
131         fullpaths[include_stack_ptr] = g_strdup_printf("%s%c%s",directory,DIR_SEPARATOR,yytext);
132
133         yyin = fopen( fullpaths[include_stack_ptr], "r" );
134         
135         if (!yyin) {
136                 if (errno) {
137                         g_string_sprintfa(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
138                         yyterminate();
139                 }
140         } else {
141                 linenums[include_stack_ptr] = 1;
142                 yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
143         }
144         
145
146         BEGIN OUT;
147 }
148
149 <<EOF>> {
150         
151         if ( --include_stack_ptr < 0 ) {
152                 yyterminate();
153         } else {
154                 g_free(fullpaths[include_stack_ptr+1]);
155                 fullpaths[include_stack_ptr+1] = NULL;
156                 
157                 yy_delete_buffer( YY_CURRENT_BUFFER );
158                 yy_switch_to_buffer(include_stack[include_stack_ptr]);
159         }
160
161         BEGIN OUT;
162 }
163
164 \n      { linenums[include_stack_ptr]++; BEGIN OUT; }
165
166
167 %%
168
169 void add_vendor(gchar* name, guint32 vendor_id) {
170         radius_vendor_info_t* v = g_malloc(sizeof(radius_vendor_info_t));
171         
172         v->name = name;
173         v->code = vendor_id;
174         v->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
175         
176         g_hash_table_insert(dict->vendors_by_id,GUINT_TO_POINTER(v->code),v);
177         g_hash_table_insert(dict->vendors_by_name,v->name,v);
178 }
179
180 void add_attribute(gchar* name, gchar* code, radius_attr_dissector_t type, gchar* vendor_name, gboolean crypt, gboolean tagged) {
181         radius_attr_info_t* a = g_malloc(sizeof(radius_attr_info_t));
182         GHashTable* by_id;
183         
184         if (vendor_name) {
185                 radius_vendor_info_t* v;
186                 v = g_hash_table_lookup(dict->vendors_by_name,vendor_name);
187                 
188                 if (! v) {
189                         g_string_sprintfa(error, "Vendor: '%s', does not exist in %s:%i \n", vendor_name, fullpaths[include_stack_ptr], linenums[include_stack_ptr] );
190                         g_free(name);
191                         g_free(code);
192                         g_free(vendor_name);
193                         BEGIN JUNK;
194                         return;
195                 } else {
196                         by_id = v->attrs_by_id;
197                 }
198         } else {
199                 by_id = dict->attrs_by_id;
200         }
201         
202         a->name = name;
203         a->code = strtol(code,NULL,10); g_free(code);
204         a->encrypt = crypt;
205         a->tagged =  tagged;
206         a->type = type;
207         a->dissector = NULL;
208         a->vs = NULL;
209         a->hf = -1;
210         a->hf64 = -1;
211         a->hf_tag = -1;
212         a->hf_len = -1;
213         a->ett = -1;
214         
215         g_hash_table_insert(by_id,GUINT_TO_POINTER(a->code),a);
216         g_hash_table_insert(dict->attrs_by_name,a->name,a);
217 }
218
219 void add_value(gchar* attrib_name, gchar* value_repr, long value) {
220         value_string v;
221         GArray* a = g_hash_table_lookup(value_strings,attrib_name);
222         
223         if (! a) {
224                 a = g_array_new(TRUE,TRUE,sizeof(value_string));
225                 g_hash_table_insert(value_strings,attrib_name,a);
226         }
227         
228         v.value = value;
229         v.strptr = value_repr;
230         
231         g_array_append_val(a,v);
232 }
233
234
235 void setup_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
236         radius_attr_info_t* a = v;
237         gpointer key;
238         
239         union {
240                 GArray* a;
241                 gpointer p;
242         } vs;
243         
244         if (g_hash_table_lookup_extended(value_strings,a->name,&key,&vs.p) ) {
245                 a->vs = (value_string*) vs.a->data;
246                 g_array_free(vs.a,FALSE);
247                 g_hash_table_remove(value_strings,key);
248                 g_free(key);
249         }
250 }
251
252 void setup_vendors(gpointer k _U_, gpointer v, gpointer p) {
253         radius_vendor_info_t* vnd = v;
254         
255         g_hash_table_foreach(vnd->attrs_by_id,setup_attrs,p);   
256 }
257
258 gboolean destroy_values(gpointer k, gpointer v, gpointer p _U_) {
259         g_free(k);
260         g_array_free(v,FALSE);
261         return TRUE;
262 }
263
264 gboolean destroy_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
265         radius_attr_info_t* a = v;
266         int i;
267         
268         g_free(a->name);
269         if (a->vs) {
270                 for(i=0; a->vs[i].strptr; i++) {
271                         g_free((void *)a->vs[i].strptr);
272                 }
273                 g_free((void *)a->vs);
274         }
275         g_free(a);
276         return TRUE;
277 }
278
279 gboolean destroy_vendors(gpointer k _U_, gpointer v, gpointer p) {
280         radius_vendor_info_t* vnd = v;
281         g_free(vnd->name);
282         g_hash_table_foreach_remove(vnd->attrs_by_id,destroy_attrs,p);
283         g_hash_table_destroy(vnd->attrs_by_id);
284         g_free(vnd);
285         return TRUE;
286 }
287
288 void destroy_dict(radius_dictionary_t* d) {
289         g_hash_table_foreach_remove(d->attrs_by_id,destroy_attrs,NULL);
290         g_hash_table_foreach_remove(d->vendors_by_id,destroy_vendors,NULL);     
291         g_hash_table_destroy(d->vendors_by_id);
292         g_hash_table_destroy(d->attrs_by_id);
293         g_hash_table_destroy(d->vendors_by_name);
294         g_hash_table_destroy(d->attrs_by_name);
295         g_free(d);
296 }
297
298 radius_dictionary_t* radius_load_dictionary (gchar* dir, gchar* filename, gchar** err_str) {
299         int i;
300         
301         directory = dir;
302         
303         fullpaths[include_stack_ptr] = g_strdup_printf("%s%c%s",directory,DIR_SEPARATOR,filename);
304         
305         error = g_string_new("");
306
307         yyin = fopen(fullpaths[include_stack_ptr],"r");
308         
309         if (!yyin) {
310                 g_string_sprintfa(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
311                 g_free(fullpaths[include_stack_ptr]);
312                 *err_str = error->str;
313                 g_string_free(error,FALSE);
314                 return NULL;
315         }
316
317         dict = g_malloc(sizeof(radius_dictionary_t));
318         dict->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
319         dict->attrs_by_name = g_hash_table_new(g_str_hash,g_str_equal);
320         dict->vendors_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
321         dict->vendors_by_name = g_hash_table_new(g_str_hash,g_str_equal);
322         
323         value_strings = g_hash_table_new(g_str_hash,g_str_equal);
324         
325         BEGIN OUT;
326
327         yylex();
328
329         for (i=0; i < 10; i++) {
330                 if (fullpaths[i]) g_free(fullpaths[i]);
331         }
332                 
333         g_hash_table_foreach(dict->attrs_by_id,setup_attrs,NULL);
334         g_hash_table_foreach(dict->vendors_by_id,setup_vendors,NULL);   
335         g_hash_table_foreach_remove(value_strings,destroy_values,NULL);
336         
337         if (error->len > 0) {
338                  *err_str = error->str;
339                 g_string_free(error,FALSE);
340                 destroy_dict(dict);
341                 return NULL;
342         } else {
343                 *err_str = NULL;
344                 g_string_free(error,TRUE);
345                 return dict;
346         }
347 }