g_string_sprintf --> g_string_printf and g_string_sprintfa --> g_string_append_printf
[metze/wireshark/wip.git] / epan / radius_dict.l
1 /*
2  * We don't use unput, so don't generate code for it.
3  */
4 %option nounput
5
6 /*
7  * We don't read from the terminal.
8  */
9 %option never-interactive
10
11 /*
12  * The language we're scanning is case-insensitive.
13  */
14 %option caseless
15
16 /*
17  * Prefix scanner routines with "Radius" rather than "yy", so this scanner
18  * can coexist with other scanners.
19  */
20 %option prefix="Radius"
21
22 %option outfile="radius_dict.c"
23
24 %{
25         /* radius_dict.l
26         *
27         * RADIUS dictionary parser
28         *
29         * $Id$
30         *
31         * Wireshark - Network traffic analyzer
32         * By Gerald Combs <gerald@wireshark.org>
33         * Copyright 1998 Gerald Combs
34         *
35         * This program is free software; you can redistribute it and/or
36         * modify it under the terms of the GNU General Public License
37         * as published by the Free Software Foundation; either version 2
38         * of the License, or (at your option) any later version.
39         *
40         * This program is distributed in the hope that it will be useful,
41         * but WITHOUT ANY WARRANTY; without even the implied warranty of
42         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43         * GNU General Public License for more details.
44         *
45         * You should have received a copy of the GNU General Public License
46         * along with this program; if not, write to the Free Software
47         * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
48         */
49
50 #ifdef HAVE_CONFIG_H
51 #include "config.h"
52 #endif
53
54 #include <glib.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <errno.h>
59 #include <epan/packet.h>
60 #include <epan/dissectors/packet-radius.h>
61 #include "radius_dict_lex.h"
62 #include <wiretap/file_util.h>
63
64 #ifdef _WIN32
65 /* disable Windows VC compiler warning "signed/unsigned mismatch" associated  */
66 /* with YY_INPUT code generated by flex versions such as 2.5.35.              */
67 #pragma warning (disable:4018)
68 #endif
69
70 #define ECHO
71 #define MAX_INCLUDE_DEPTH 10
72
73         void add_vendor(const gchar* name, guint32 vendor_id);
74         void add_value(const gchar* attrib_name,const  gchar* value_repr, long value);
75         void add_attribute(const gchar*,const  gchar*, radius_attr_dissector_t,const  gchar*, gboolean, gboolean);
76
77         static YY_BUFFER_STATE include_stack[10];
78         static int include_stack_ptr = 0;
79
80         static radius_dictionary_t* dict = NULL;
81         static GHashTable* value_strings = NULL; /* GArray(value_string) by attribute name */
82
83         static gchar* attr_name = NULL;
84         static gchar* attr_id = NULL;
85         static radius_attr_dissector_t* attr_type = NULL;
86         static gchar* attr_vendor = NULL;
87         static gchar* vendor_name = NULL;
88         static gchar* value_repr = NULL;
89         static gboolean encrypted = FALSE;
90         static gboolean has_tag = FALSE;
91         static gchar* current_vendor = NULL;
92
93         static GString* error = NULL;
94         static gchar* directory = NULL;
95         static int linenums[] = {1,1,1,1,1,1,1,1,1,1};
96         static gchar* fullpaths[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
97
98 %}
99
100 %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
101 %%
102 [:blank:]   ;
103 #[^\n]*         ;
104
105 <JUNK>.*\qn             ;
106
107 <WS_OUT>VENDOR { BEGIN VENDOR; }
108 <WS_OUT>ATTRIBUTE { BEGIN ATTR; }
109 <WS_OUT>VALUE { BEGIN VALUE; }
110 <WS_OUT>\$INCLUDE { BEGIN INCLUDE; }
111 <WS_OUT>BEGIN-VENDOR { BEGIN BEGIN_VENDOR; }
112 <WS_OUT>END-VENDOR { BEGIN END_VENDOR; }
113
114 <BEGIN_VENDOR>[0-9a-z_-]+ {
115     if (current_vendor) {
116         g_free(current_vendor);
117     }
118     current_vendor = g_strdup(yytext);
119     BEGIN WS_OUT;
120 }
121 <END_VENDOR>[^\n]* {
122     if (current_vendor) {
123         g_free(current_vendor);
124         current_vendor = NULL;
125     }
126     BEGIN WS_OUT;
127 }
128
129 <VENDOR>[0-9a-z_-]+   { vendor_name = g_strdup(yytext); BEGIN VENDOR_W_NAME; }
130 <VENDOR_W_NAME>[0-9]+   {
131     add_vendor(vendor_name,strtol(yytext,NULL,10));
132     g_free(vendor_name);
133     BEGIN WS_OUT;
134 }
135 <VENDOR_W_NAME>0x[0-9a-f]+   {
136     add_vendor(vendor_name,strtol(yytext,NULL,16));
137     g_free(vendor_name);
138     BEGIN WS_OUT;
139 }
140
141 <ATTR>[0-9a-z_/-]+                      { attr_name = g_strdup(yytext); encrypted = FALSE; has_tag = FALSE; BEGIN ATTR_W_NAME; }
142 <ATTR_W_NAME>[0-9]+                     { attr_id = g_strdup(yytext);  BEGIN ATTR_W_ID;}
143 <ATTR_W_NAME>0x[0-9a-f]+                { attr_id = g_strdup_printf("%u",(int)strtoul(yytext,NULL,16)); BEGIN ATTR_W_ID;}
144 <ATTR_W_ID>integer                      { attr_type = radius_integer;  BEGIN ATTR_W_TYPE; }
145 <ATTR_W_ID>string                       { attr_type = radius_string;  BEGIN ATTR_W_TYPE; }
146 <ATTR_W_ID>octets                       { attr_type = radius_octets;  BEGIN ATTR_W_TYPE; }
147 <ATTR_W_ID>ipaddr                       { attr_type = radius_ipaddr;  BEGIN ATTR_W_TYPE; }
148 <ATTR_W_ID>ipv6addr                     { attr_type = radius_ipv6addr;  BEGIN ATTR_W_TYPE; }
149 <ATTR_W_ID>ipxnet                       { attr_type = radius_ipxnet;  BEGIN ATTR_W_TYPE; }
150 <ATTR_W_ID>date                         { attr_type = radius_date;  BEGIN ATTR_W_TYPE; }
151 <ATTR_W_ID>ifid                         { attr_type = radius_ifid;  BEGIN ATTR_W_TYPE; }
152 <ATTR_W_ID>[0-9a-z_-]+                  { attr_type = radius_octets;  BEGIN ATTR_W_TYPE; }
153 <ATTR_W_TYPE>has_tag[,]?                { has_tag = TRUE; }
154 <ATTR_W_TYPE>encrypt=1[,]?              { encrypted=TRUE; }
155 <ATTR_W_TYPE>[0-9a-z_-]+=([^\n]*)       ;
156 <ATTR_W_TYPE>[0-9a-z_-]+                {
157     attr_vendor = g_strdup(yytext);
158     add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag);
159     g_free(attr_id);
160     g_free(attr_vendor);
161     g_free(attr_name);
162     attr_id = NULL;
163     attr_vendor = NULL;
164     attr_name = NULL;
165     BEGIN WS_OUT;
166 }
167 <ATTR_W_TYPE>\n                                         {
168     add_attribute(attr_name,attr_id,attr_type,current_vendor,encrypted,has_tag);
169     g_free(attr_id);
170     g_free(attr_name);
171     linenums[include_stack_ptr]++;
172     has_tag = FALSE;
173     encrypted=FALSE;
174     BEGIN WS_OUT;
175 }
176 <ATTR_W_VENDOR>\n                                       {
177     add_attribute(attr_name,attr_id,attr_type,attr_vendor,encrypted,has_tag);
178     g_free(attr_id);
179     g_free(attr_vendor);
180     g_free(attr_name);
181     linenums[include_stack_ptr]++;
182     BEGIN WS_OUT;
183 };
184
185 <VALUE>[0-9a-z_/-]+                                     { attr_name = g_strdup(yytext); BEGIN VALUE_W_ATTR; }
186 <VALUE_W_ATTR>[^[:blank:]]+                     { value_repr = g_strdup(yytext); BEGIN VALUE_W_NAME; }
187 <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;}
188 <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;}
189
190 <INCLUDE>[^[:blank:]\n]+   {
191         if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
192                 g_string_append_printf(error, "$INCLUDE files nested to deeply\n");
193                 yyterminate();
194         }
195
196         include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
197
198         fullpaths[include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
199             directory,yytext);
200
201         yyin = eth_fopen( fullpaths[include_stack_ptr], "r" );
202
203         if (!yyin) {
204                 if (errno) {
205                         g_string_append_printf(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
206                         yyterminate();
207                 }
208         } else {
209                 linenums[include_stack_ptr] = 1;
210                 yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
211         }
212
213
214         BEGIN WS_OUT;
215 }
216
217 <<EOF>> {
218
219         fclose(yyin);
220         yyin = NULL;
221
222         if ( --include_stack_ptr < 0 ) {
223                 yyterminate();
224         } else {
225                 g_free(fullpaths[include_stack_ptr+1]);
226                 fullpaths[include_stack_ptr+1] = NULL;
227
228                 yy_delete_buffer( YY_CURRENT_BUFFER );
229                 yy_switch_to_buffer(include_stack[include_stack_ptr]);
230         }
231
232         BEGIN WS_OUT;
233 }
234
235 \n      { linenums[include_stack_ptr]++; BEGIN WS_OUT; }
236
237
238 %%
239
240 void add_vendor(const gchar* name, guint32 vendor_id) {
241         radius_vendor_info_t* v = g_malloc(sizeof(radius_vendor_info_t));
242
243         v->name = g_strdup(name);
244         v->code = vendor_id;
245         v->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
246         v->ett = -1;
247
248         g_hash_table_insert(dict->vendors_by_id,GUINT_TO_POINTER(v->code),v);
249         g_hash_table_insert(dict->vendors_by_name, (gpointer) v->name, v);
250 }
251
252 void add_attribute(const gchar* name, const  gchar* code, radius_attr_dissector_t type, const  gchar* vendor_name, gboolean crypt, gboolean tagged) {
253         radius_attr_info_t* a = g_malloc(sizeof(radius_attr_info_t));
254         GHashTable* by_id;
255
256         if (vendor_name) {
257                 radius_vendor_info_t* v;
258                 v = g_hash_table_lookup(dict->vendors_by_name,vendor_name);
259
260                 if (! v) {
261                         g_string_append_printf(error, "Vendor: '%s', does not exist in %s:%i \n", vendor_name, fullpaths[include_stack_ptr], linenums[include_stack_ptr] );
262                         BEGIN JUNK;
263                         return;
264                 } else {
265                         by_id = v->attrs_by_id;
266                 }
267         } else {
268                 by_id = dict->attrs_by_id;
269         }
270
271         a->name = g_strdup(name);
272         a->code = strtol(code,NULL,10);
273         a->encrypt = crypt;
274         a->tagged =  tagged;
275         a->type = type;
276         a->dissector = NULL;
277         a->vs = NULL;
278         a->hf = -1;
279         a->hf64 = -1;
280         a->hf_tag = -1;
281         a->hf_len = -1;
282         a->ett = -1;
283
284         g_hash_table_insert(by_id,GUINT_TO_POINTER(a->code),a);
285         g_hash_table_insert(dict->attrs_by_name,(gpointer) (a->name),a);
286 }
287
288 void add_value(const gchar* attrib_name, const gchar* value_repr, long value) {
289         value_string v;
290         GArray* a = g_hash_table_lookup(value_strings,attrib_name);
291
292         if (! a) {
293                 a = g_array_new(TRUE,TRUE,sizeof(value_string));
294                 g_hash_table_insert(value_strings,g_strdup(attrib_name),a);
295         }
296
297         v.value = value;
298         v.strptr = g_strdup(value_repr);
299
300         g_array_append_val(a,v);
301 }
302
303
304 static void setup_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
305         radius_attr_info_t* a = v;
306         gpointer key;
307
308         union {
309                 GArray* a;
310                 gpointer p;
311         } vs;
312
313         if (g_hash_table_lookup_extended(value_strings,a->name,&key,&vs.p) ) {
314                 a->vs = (value_string*) vs.a->data;
315                 g_array_free(vs.a,FALSE);
316                 g_hash_table_remove(value_strings,key);
317                 g_free(key);
318         }
319 }
320
321 static void setup_vendors(gpointer k _U_, gpointer v, gpointer p) {
322         radius_vendor_info_t* vnd = v;
323
324         g_hash_table_foreach(vnd->attrs_by_id,setup_attrs,p);
325 }
326
327 static gboolean destroy_value_strings(gpointer k, gpointer v, gpointer p _U_) {
328     value_string* vs = (value_string*)(((GArray*)v)->data);
329
330         g_free(k);
331
332     for (;vs->strptr;vs++) {
333         g_free((void*)vs->strptr);
334     }
335
336         g_array_free(v,TRUE);
337         return TRUE;
338 }
339
340 static gboolean destroy_attrs(gpointer k _U_, gpointer v, gpointer p _U_) {
341         radius_attr_info_t* a = v;
342         int i;
343
344         g_free((gpointer) (a->name));
345         if (a->vs) {
346                 for(i=0; a->vs[i].strptr; i++) {
347                         g_free((void *)a->vs[i].strptr);
348                 }
349                 g_free((void *)a->vs);
350         }
351         g_free(a);
352         return TRUE;
353 }
354
355 static gboolean destroy_vendors(gpointer k _U_, gpointer v, gpointer p) {
356         radius_vendor_info_t* vnd = v;
357         g_free( (gpointer) vnd->name);
358         g_hash_table_foreach_remove(vnd->attrs_by_id,destroy_attrs,p);
359         g_hash_table_destroy(vnd->attrs_by_id);
360         g_free(vnd);
361         return TRUE;
362 }
363
364 static void destroy_dict(radius_dictionary_t* d) {
365         g_hash_table_foreach_remove(d->attrs_by_id,destroy_attrs,NULL);
366         g_hash_table_foreach_remove(d->vendors_by_id,destroy_vendors,NULL);
367         g_hash_table_destroy(d->vendors_by_id);
368         g_hash_table_destroy(d->attrs_by_id);
369         g_hash_table_destroy(d->vendors_by_name);
370         g_hash_table_destroy(d->attrs_by_name);
371         g_free(d);
372 }
373
374 gboolean radius_load_dictionary (radius_dictionary_t* d, gchar* dir, const gchar* filename, gchar** err_str) {
375         int i;
376
377         dict = d;
378         directory = dir;
379
380         fullpaths[include_stack_ptr] = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
381             directory,filename);
382
383         error = g_string_new("");
384
385         yyin = eth_fopen(fullpaths[include_stack_ptr],"r");
386
387         if (!yyin) {
388                 g_string_append_printf(error, "Could not open file: '%s', error: %s\n", fullpaths[include_stack_ptr], strerror(errno) );
389                 g_free(fullpaths[include_stack_ptr]);
390                 *err_str = error->str;
391                 g_string_free(error,FALSE);
392                 return FALSE;
393         }
394
395         value_strings = g_hash_table_new(g_str_hash,g_str_equal);
396
397         BEGIN WS_OUT;
398
399         yylex();
400
401         if (yyin != NULL) fclose(yyin);
402         yyin = NULL;
403
404         for (i=0; i < 10; i++) {
405                 if (fullpaths[i]) g_free(fullpaths[i]);
406         }
407
408         g_hash_table_foreach(dict->attrs_by_id,setup_attrs,NULL);
409         g_hash_table_foreach(dict->vendors_by_id,setup_vendors,NULL);
410         g_hash_table_foreach_remove(value_strings,destroy_value_strings,NULL);
411
412         if (error->len > 0) {
413                  *err_str = error->str;
414                 g_string_free(error,FALSE);
415                 destroy_dict(dict);
416                 return FALSE;
417         } else {
418                 *err_str = NULL;
419                 g_string_free(error,TRUE);
420                 return TRUE;
421         }
422 }
423
424 /*
425  * We want to stop processing when we get to the end of the input.
426  * (%option noyywrap is not used because if used then 
427  * some flex versions (eg: 2.5.35) generate code which causes
428  * warnings by the Windows VC compiler).
429  */
430
431 int yywrap(void) {
432     return 1;
433 }