diff options
author | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2005-02-04 04:37:47 +0000 |
---|---|---|
committer | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2005-02-04 04:37:47 +0000 |
commit | 975a76b44fa49d7463c376ad4e4aa47a05b94433 (patch) | |
tree | 320b0fcd5960841dd2915485b3e204dc62673777 /epan | |
parent | 3e80f3680a3d47aa48f1ef8a73d51245222488e7 (diff) |
check in new directory for the files for autogenerating dcerpc interfaces
and the prototype idl compiler.
this is not ready for wide use yet but is useful with a svn area where we can sync our changes to the compiler.
svn path=/trunk/; revision=13280
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/dcerpc/idl2eth.c | 3086 |
1 files changed, 3086 insertions, 0 deletions
diff --git a/epan/dissectors/dcerpc/idl2eth.c b/epan/dissectors/dcerpc/idl2eth.c new file mode 100644 index 0000000000..a895736760 --- /dev/null +++ b/epan/dissectors/dcerpc/idl2eth.c @@ -0,0 +1,3086 @@ +/* +TODO + check that every cnf defined type,hffield,rename,... has been referenced + at least once and if not, abort with an error + + need to distinguish between NTTIME (absolute time) and relative time + + prune_xxx should only act inside of '[' ']' + + add support for bool8,16,32,64 with tfs strings + + add the remaining array type (uvarray) + + add code to verify that union tag length is correct +*/ +/* All field dissectors that call a normal type + (i.e. not a pointer, not an array) + has a local variable guint param declared which is passed on to the + type dissector. + The default value is 0 but the PARAM_VALUE conformance tag can be used to + change it. + This is only meaningful if the called type dissector actually does anything + with this parameter. +*/ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +FILE *fh, *tfh, *eth_code, *eth_hdr, *eth_hf, *eth_hfarr, *eth_ett, *eth_ettarr, *eth_ft, *eth_handoff; +char *uuid=NULL; +char *version=NULL; +char *pointer_default=NULL; +char *ifname=NULL; +char hf_status[256]; +int lineno,linepos; +char line[1024]; + + +#define FPRINTF(fh, ...) \ + {\ + fprintf(stderr, __VA_ARGS__ );\ + if(fh)fprintf(fh, __VA_ARGS__ );\ + } + + +typedef struct _pointer_item_t { + struct _pointer_item_t *next; + char *type; +} pointer_item_t; + +#define BI_CASE 0x00000001 +#define BI_CASE_DEFAULT 0x00000002 +#define BI_IN 0x00000004 +#define BI_OUT 0x00000008 +#define BI_SIZE_IS 0x00000010 +#define BI_LENGTH_IS 0x00000020 +#define BI_POINTER 0x00000040 +#define BI_BITMAP32 0x00000100 +typedef struct _bracket_item_t { + long int flags; + char *case_name; + pointer_item_t *pointer_list; +} bracket_item_t; + +typedef struct _no_emit_item_t { + struct _no_emit_item_t *next; + char *name; +} no_emit_item_t; +no_emit_item_t *no_emit_list=NULL; + +typedef struct _hf_rename_item_t { + struct _hf_rename_item_t *next; + char *old_name; + char *new_name; +} hf_rename_item_t; +hf_rename_item_t *hf_rename_list=NULL; + +typedef struct _enum_list_t { + struct _enum_list_t *next; + char *name; + int val; +} enum_list_t; + + +typedef struct _token_item_t { + struct _token_item_t *next; + char *str; +} token_item_t; +token_item_t *token_list=NULL; +token_item_t *last_token_item=NULL; + + +typedef struct _type_item_t { + struct _type_item_t *next; + char *name; + char *dissector; + char *ft_type; + char *base_type; + char *mask; + char *vals; + int alignment; +} type_item_t; +type_item_t *type_list=NULL; + +typedef struct _union_tag_size_item_t { + struct _union_tag_size_item_t *next; + char *name; + int size; +} union_tag_size_item_t; +union_tag_size_item_t *union_tag_size_list=NULL; + +typedef struct _hf_field_item_t { + struct _hf_field_item_t *next; + char *name; + char *ft_type; +} hf_field_item_t; +hf_field_item_t *hf_field_list=NULL; + +typedef struct _dissector_param_value_t { + struct _dissector_param_value_t *next; + char *name; + char *value; +} dissector_param_value_t; +dissector_param_value_t *dissector_param_list=NULL; + +void +register_dissector_param_value(char *name, char *value) +{ + dissector_param_value_t *dpv; + dpv=malloc(sizeof(dissector_param_value_t)); + dpv->next=dissector_param_list; + dissector_param_list=dpv; + dpv->name=strdup(name); + dpv->value=strdup(value); +} + +char * +find_dissector_param_value(char *name) +{ + dissector_param_value_t *dpv; + for(dpv=dissector_param_list;dpv;dpv=dpv->next){ + if(!strcmp(name,dpv->name)){ + return dpv->value; + } + } + return "0"; +} + +pointer_item_t * +prepend_pointer_list(pointer_item_t *ptrs, int num_pointers) +{ + pointer_item_t *pi; + + pi=ptrs; + while(pi){ + if(num_pointers)num_pointers--; + pi=pi->next; + } + if(!pi)pi=ptrs; + while(num_pointers--){ + pi=malloc(sizeof(pointer_item_t)); + pi->next=ptrs; + pi->type=pointer_default; + ptrs=pi; + } + ptrs=pi; + + return ptrs; +} + +char * +ptr_to_define(char *pointer_type) +{ + if(!strcmp(pointer_type, "unique")){ + return "NDR_POINTER_UNIQUE"; + } else if(!strcmp(pointer_type, "ref")){ + return "NDR_POINTER_REF"; + } else if(!strcmp(pointer_type, "ptr")){ + return "NDR_POINTER_PTR"; + } + + fprintf(stderr, "prt_to_define, weirdo pointer :%s\n", pointer_type); + exit(10); +} + +int +get_union_tag_size(char *name) +{ + union_tag_size_item_t *utsi; + for(utsi=union_tag_size_list;utsi;utsi=utsi->next){ + if(!strcmp(name, utsi->name)){ + return utsi->size; + } + } + fprintf(stderr, "ERROR: size of tag for union:%s is not known\n", name); + fprintf(stderr, " use the UNION_TAG_SIZE directive to specify it in teh conformance file\n", name); + exit(10); +} + + +/* this function will add an entry to the hf_rename list */ +void +register_hf_rename(char *old_name, char *new_name) +{ + hf_rename_item_t *new_item; + new_item=malloc(sizeof(hf_rename_item_t)); + new_item->next=hf_rename_list; + hf_rename_list=new_item; + new_item->old_name=strdup(old_name); + new_item->new_name=strdup(new_name); +} + +hf_field_item_t * +find_hf_field(char *name) +{ + hf_field_item_t *hfi; + + for(hfi=hf_field_list;hfi;hfi=hfi->next){ + if(!strcmp(hfi->name, name)){ + return hfi; + } + } + fprintf(stderr, "find_hf_field: unknown hf_field:%s\n",name); + Exit(10); +} + + +/* this function will create the code required for a hf field. + it MIGTH rename the field so a user MUST use the name returned + from this function. + for fields that are to be renamed no code is generated +*/ +char * +register_hf_field(char *hf_name, char *title, char *filter_name, char *ft_type, char *base_type, char *valsstring, char *mask, char *blurb) +{ + hf_field_item_t *hfi; + hf_rename_item_t *hri; + + /* dont generate code for renamed hf fields just return the new name*/ + for(hri=hf_rename_list;hri;hri=hri->next){ + if(!strcmp(hf_name, hri->old_name)){ + hfi=find_hf_field(hri->new_name); + if(strcmp(ft_type, hfi->ft_type)){ + fprintf(stderr, "register_hf_field: hf_fields %s and %s have different types %s %s\n",hf_name,hfi->name,ft_type,hfi->ft_type); + Exit(10); + } + return hri->new_name; + } + } + + hfi=malloc(sizeof(hf_field_item_t)); + hfi->next=hf_field_list; + hf_field_list=hfi; + hfi->name=strdup(hf_name); + hfi->ft_type=strdup(ft_type); + + FPRINTF(eth_hf, "static int %s = -1;\n", hf_name); + FPRINTF(eth_hfarr, " { &%s,\n", hf_name); + FPRINTF(eth_hfarr, " { \"%s\", \"%s\", %s, %s,\n", title, filter_name, ft_type, base_type); + FPRINTF(eth_hfarr, " %s, %s,\n", valsstring, mask); + FPRINTF(eth_hfarr, " \"%s\", HFILL }},\n", blurb); + FPRINTF(eth_hfarr, "\n"); + + return hf_name; +} + +/* this function will parse the no emit list and decide whether code should + be generated for this dissector or if we should only register the type. +*/ +int +check_if_to_emit(char *name) +{ + no_emit_item_t *nel; + + for(nel=no_emit_list;nel;nel=nel->next){ + if(!strcmp(name, nel->name)){ + FPRINTF(NULL, "SKIPPED emitting of %s\n",name); + return 0; + } + } + return 1; +} + + +void +prune_keywords(char *name) +{ + token_item_t *ti, *prevti; + + for(ti=token_list;ti;ti=ti->next){ + if(!ti->next){ + break; + } + if(!strcmp(ti->next->str, name)){ + if(!strcmp(ti->next->next->str, ",")){ + ti->next=ti->next->next->next; + } else { + ti->next=ti->next->next; + } + } + } +} +void +rename_tokens(char *old_name, char *new_name) +{ + token_item_t *ti; + + for(ti=token_list;ti;ti=ti->next){ + if(!strcmp(ti->str, old_name)){ + ti->str=strdup(new_name); + } + } +} + +void +prune_keyword_parameters(char *name) +{ + token_item_t *ti, *tmpti; + + for(ti=token_list;ti;ti=ti->next){ + if(!strcmp(ti->str, name)){ + if(!strcmp(ti->next->str, "(")){ + tmpti=ti; + while(1){ + if(!strcmp(tmpti->str, ")")){ + ti->next=tmpti->next; + break; + } + tmpti=tmpti->next; + } + } + } + } +} + +/* this function will parse a bracket item + [ ... ] + it will return the token of the next item following the ']' +*/ +token_item_t * +parsebrackets(token_item_t *ti, bracket_item_t **bracket){ + bracket_item_t *br; + + if(strcmp(ti->str, "[")){ + fprintf(stderr, "ERROR: parsebrackets first token is not '['\n"); + Exit(10); + } + ti=ti->next; + + br=malloc(sizeof(bracket_item_t)); + *bracket=br; + br->flags=0; + br->case_name=NULL; + br->pointer_list=NULL; + + while(ti){ + if( !strcmp(ti->str, "{") + ||!strcmp(ti->str, "}")){ + fprintf(stderr, "ERROR: parsebrackets '{' '}' inside bracket item\n"); + Exit(10); + } + + if(!strcmp(ti->str, "[")){ + fprintf(stderr, "ERROR: parsebrackets '[' inside bracket item\n"); + Exit(10); + } + + /* finished */ + if(!strcmp(ti->str, "]")){ + /* check for [ ... ] [ ...] */ + ti=ti->next; + + if(!strcmp(ti->str, "[")){ + ti=ti->next; + continue; + } + return ti; + } + + /* just ignore all ',' */ + if(!strcmp(ti->str, ",")){ + ti=ti->next; + continue; + } + + /* case '(' tag ')' */ + if(!strcmp(ti->str, "case")){ + br->flags|=BI_CASE; + ti=ti->next; + + if(strcmp(ti->str, "(")){ + fprintf(stderr, "ERROR: parsebrackets case not followed by '('\n"); + Exit(10); + } + ti=ti->next; + + /* name */ + br->case_name=ti->str; + ti=ti->next; + + if(strcmp(ti->str, ")")){ + fprintf(stderr, "ERROR: parsebrackets case does not end with ')'\n"); + Exit(10); + } + ti=ti->next; + continue; + } + + /* default */ + if(!strcmp(ti->str, "default")){ + br->flags|=BI_CASE; + br->flags|=BI_CASE_DEFAULT; + ti=ti->next; + continue; + } + + /* in */ + if(!strcmp(ti->str, "in")){ + br->flags|=BI_IN; + ti=ti->next; + continue; + } + + /* out */ + if(!strcmp(ti->str, "out")){ + br->flags|=BI_OUT; + ti=ti->next; + continue; + } + + /* public : we dont care about this one */ + if(!strcmp(ti->str, "public")){ + ti=ti->next; + continue; + } + + /* switch_is */ + if(!strcmp(ti->str, "switch_is")){ + fprintf(stderr, "WARNING: parsebrackets can not handle switch_is properly yet so we can not verify the tag size\n"); + while(ti){ + if(!strcmp(ti->str, ")")){ + ti=ti->next; + break; + } + ti=ti->next; + } + continue; + } + + /* switch_is */ + if(!strcmp(ti->str, "subcontext")){ + while(ti){ + if(!strcmp(ti->str, ")")){ + ti=ti->next; + break; + } + ti=ti->next; + } + continue; + } + + /* value we dont care about this one so just skip it */ + if(!strcmp(ti->str, "value")){ + int level; + ti=ti->next; + if( strcmp(ti->str, "(") ){ + fprintf(stderr, "WARNING: parsebrackets value was not followed by '('\n"); + Exit(10); + } + level=0; + while(ti){ + if(!strcmp(ti->str, "(")){ + ti=ti->next; + level++; + continue; + } + if(!strcmp(ti->str, ")")){ + ti=ti->next; + level--; + if(level){ + continue; + } + break; + } + ti=ti->next; + } + continue; + } + + /* range we dont care about this one so just skip it */ + if(!strcmp(ti->str, "range")){ + int level; + ti=ti->next; + if( strcmp(ti->str, "(") ){ + fprintf(stderr, "WARNING: parsebrackets range was not followed by '('\n"); + Exit(10); + } + level=0; + while(ti){ + if(!strcmp(ti->str, "(")){ + ti=ti->next; + level++; + continue; + } + if(!strcmp(ti->str, ")")){ + ti=ti->next; + level--; + if(level){ + continue; + } + break; + } + ti=ti->next; + } + continue; + } + + /* flag we dont care about this one so just skip it */ + if(!strcmp(ti->str, "flag")){ + int level; + ti=ti->next; + if( strcmp(ti->str, "(") ){ + fprintf(stderr, "WARNING: parsebrackets flag was not followed by '('\n"); + Exit(10); + } + level=0; + while(ti){ + if(!strcmp(ti->str, "(")){ + ti=ti->next; + level++; + continue; + } + if(!strcmp(ti->str, ")")){ + ti=ti->next; + level--; + if(level){ + continue; + } + break; + } + ti=ti->next; + } + continue; + } + + /* size_is */ + if(!strcmp(ti->str, "size_is")){ + br->flags|=BI_SIZE_IS; + ti=ti->next; + continue; + } + + /* length_is */ + if(!strcmp(ti->str, "length_is")){ + br->flags|=BI_LENGTH_IS; + ti=ti->next; + continue; + } + + /* bitmap32bit */ + if(!strcmp(ti->str, "bitmap32bit")){ + br->flags|=BI_BITMAP32; + ti=ti->next; + continue; + } + + /* ref, unique or ptr */ + if(!strcmp(ti->str, "ref") + || !strcmp(ti->str, "unique") + || !strcmp(ti->str, "ptr")){ + pointer_item_t *newpi; + + br->flags|=BI_POINTER; + newpi=malloc(sizeof(pointer_item_t)); + newpi->next=NULL; + newpi->type=ti->str; + newpi->next=br->pointer_list; + br->pointer_list=newpi; + ti=ti->next; + continue; + } + + fprintf(stderr, "ERROR: parsebrackets should not be reached unknown tag:%s\n", ti->str); + Exit(10); + } +} + +/* this function will register a new type learnt from the IDL file +*/ +static type_item_t * +register_new_type(char *name, char *dissectorname, char *ft_type, char *base_type, char *mask, char *valsstring, int alignment){ + type_item_t *new_type; + +FPRINTF(NULL,"XXX new type:%s dissector:%s Type:%s Base:%s Mask:%s Vals:%s alignment:%d\n", name, dissectorname, ft_type, base_type, mask, valsstring, alignment); + + new_type=malloc(sizeof(type_item_t)); + new_type->next=type_list; + new_type->name=strdup(name); + new_type->dissector=strdup(dissectorname); + new_type->ft_type=strdup(ft_type); + new_type->base_type=strdup(base_type); + new_type->mask=strdup(mask); + new_type->vals=strdup(valsstring); + new_type->alignment=alignment; + type_list=new_type; + + return new_type; +} + + +/* this function will print the remaining content of the token list +*/ +void printtokenlist(int count) +{ + token_item_t *ti; + fprintf(stderr, "TOKENLIST:\n"); + for(ti=token_list;ti&&count;count--,ti=ti->next){ + fprintf(stderr, "Token \"%s\"\n",ti->str); + } + if(!count){ + fprintf(stderr, " ...\n"); + } +} + + +/* this function will parse the header and pick up the fields + * we are interested in. + * the header is supposed to start at the very first token and look like + * [ <fields> ] inteface <ifname> { + * + * we are interested in the fields: + * uuid + * version + * pointer_default + * + * this function will also remove the header from the token list + */ +void parseheader(void) +{ + char filter_name[256]; + token_item_t *ti; + int level=0; + int major, minor; + + ti=token_list; + if(!ti){ + fprintf(stderr, "ERRO: no tokens\n"); + Exit(10); + } + + /* first token must be '[' */ + if( strcmp(ti->str, "[") ){ + fprintf(stderr, "ERROR: first token is not '['\n"); + Exit(10); + } + + for(ti=token_list;ti;ti=ti->next){ + if( !strcmp(ti->str, "[")){ + level++; + continue; + } + if( !strcmp(ti->str, "]")){ + level--; + if(!level){ + token_list=ti->next; + break; + } + } + if(level==1){ + if( !strcmp(ti->str, "uuid")){ + uuid=ti->next->next->str; + FPRINTF(NULL,"UUID:%s\n",uuid); + } + if( !strcmp(ti->str, "version")){ + version=ti->next->next->str; + FPRINTF(NULL,"VERSION:%s\n",version); + } + if( !strcmp(ti->str, "pointer_default")){ + if(!strcmp(ti->next->next->str, "unique")){ + pointer_default="unique"; + } else if(!strcmp(ti->next->next->str, "ptr")){ + pointer_default="ptr"; + } else { + fprintf(stderr, "ERROR: unknown pointer type\n"); + Exit(10); + } + FPRINTF(NULL,"POINTER_DEFAULT:%s\n",pointer_default); + } + } + } + if(!token_list){ + fprintf(stderr, "ERROR: ran outof tokens inside header\n"); + Exit(10); + } + /* interface */ + if(strcmp(token_list->str, "interface")){ + fprintf(stderr, "ERROR: interface not found\n"); + Exit(10); + } + token_list=token_list->next; + /* interface name */ + ifname=token_list->str; + token_list=token_list->next; + FPRINTF(NULL,"Interface:%s\n",ifname); + + /* opnum */ + sprintf(hf_status, "hf_%s_opnum", ifname); + sprintf(filter_name, "%s.opnum", ifname); + register_hf_field(hf_status, "Operation", filter_name, "FT_UINT16", "BASE_DEC", "NULL", "0", ""); + + /* status */ + sprintf(hf_status, "hf_%s_rc", ifname); + sprintf(filter_name, "%s.rc", ifname); + register_hf_field(hf_status, "Return code", filter_name, "FT_UINT32", "BASE_HEX", "VALS(NT_errors)", "0", ""); + + FPRINTF(eth_ett, "static gint ett_%s = -1;\n", ifname); + FPRINTF(eth_ettarr, " &ett_%s,\n", ifname); + + /* the body must start with { */ + if(strcmp(token_list->str, "{")){ + fprintf(stderr, "ERROR: body does not start with '{'\n"); + Exit(10); + } + + /* skip the initial '{' */ + token_list=token_list->next; + + if(!uuid){ + fprintf(stderr, "ERROR: no uuid found\n"); + Exit(10); + } + FPRINTF(eth_code,"static e_uuid_t uuid_dcerpc_%s = {\n", ifname); + FPRINTF(eth_code," 0x%c%c%c%c%c%c%c%c, 0x%c%c%c%c, 0x%c%c%c%c,\n",uuid[1],uuid[2],uuid[3],uuid[4],uuid[5],uuid[6],uuid[7],uuid[8],uuid[10],uuid[11],uuid[12],uuid[13],uuid[15],uuid[16],uuid[17],uuid[18]); + FPRINTF(eth_code," { 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c}\n",uuid[20],uuid[21],uuid[22],uuid[23],uuid[25],uuid[26],uuid[27],uuid[28],uuid[29],uuid[30],uuid[31],uuid[32],uuid[33],uuid[34],uuid[35],uuid[36]); + FPRINTF(eth_code,"};\n"); + FPRINTF(eth_code,"\n"); + + sscanf(version, "%d.%d", &major, &minor); + FPRINTF(eth_code,"static guint16 ver_%s = %d;\n", ifname, major); + FPRINTF(eth_code,"\n"); + + FPRINTF(eth_handoff, " dcerpc_init_uuid(proto_%s, ett_%s,\n", ifname, ifname); + FPRINTF(eth_handoff, " &uuid_dcerpc_%s, ver_%s,\n", ifname, ifname); + FPRINTF(eth_handoff, " function_dissectors, hf_%s_opnum);\n", ifname); +} + + + +/* this helper function is called by the tokenizer and will just append the + current token to the linked list +*/ +void pushtoken(char *token) +{ + token_item_t *new_token_item; + new_token_item=malloc(sizeof(token_item_t)); + new_token_item->next=NULL; + new_token_item->str=token; + if(!token_list){ + token_list=new_token_item; + } else { + last_token_item->next=new_token_item; + } + last_token_item=new_token_item; +} + +/* this function reads the idl file and translates it into tokens. + the tokens are stored in a linked list token_list of type token_item_t +*/ +void tokenize(void) +{ + int ch; + int fullinecomment=0; + int normalcomment=0; + int insidequote=0; + char qs[1024]; + int qspos; + int insidetoken=0; + char token[1024]; + int tokenpos; + + while(!feof(fh)){ + ch=fgetc(fh); + + /* full line comment */ + if(fullinecomment){ + if( (ch=='\n')||(ch=='\r') ){ + fullinecomment=0; + linepos=0; + } + continue; + } + if( (ch=='#')&&(linepos==0) ){ + fullinecomment=1; + continue; + } + + /* normal comment */ + if(normalcomment==0){ + if(ch=='/'){ + int nextch; + nextch=fgetc(fh); + if(nextch=='*'){ + normalcomment=1; + continue; + } + ungetc(nextch, fh); + } + } else { + if(ch=='*'){ + int nextch; + nextch=fgetc(fh); + if(nextch=='/'){ + normalcomment=0; + continue; + } + ungetc(nextch, fh); + } + continue; + } + + /* quoted string */ + if(insidequote){ + if(ch=='"'){ + insidequote=0; + qs[qspos++]='"'; + qs[qspos]=0; + pushtoken(strdup(qs)); + continue; + } else { + qs[qspos++]=(char)ch; + continue; + } + } else { + if(ch=='"'){ + insidequote=1; + qs[0]='"'; + qspos=1; + continue; + } + } + + + switch(ch){ + case '\n': + case '\r': + if(insidetoken){ + insidetoken=0; + token[tokenpos]=0; + pushtoken(strdup(token)); + } + line[linepos]=0; +/*printf("line %d [%s]\n",lineno,line);*/ + linepos=0; + lineno++; + break; + case '\t': + case ' ': + if(insidetoken){ + insidetoken=0; + token[tokenpos]=0; + pushtoken(strdup(token)); + } + break; + case '[': + case ']': + case '(': + case ')': + case ',': + case ';': + case '*': + case '=': + if(insidetoken){ + insidetoken=0; + token[tokenpos]=0; + pushtoken(strdup(token)); + } + token[0]=(char)ch; + token[1]=0; + pushtoken(strdup(token)); + break; + default: + if(!insidetoken){ + tokenpos=0; + } + insidetoken=1; + token[tokenpos++]=(char)ch; + line[linepos++]=(char)ch; + break; + } + + } +} + + +static type_item_t * +find_type(char *name) +{ + type_item_t *tmptype; + for(tmptype=type_list;tmptype;tmptype=tmptype->next){ + if(!strcmp(tmptype->name, name)){ + break; + } + } + /* autogenerate built in types */ + if(!tmptype){ + char dissectorname[256]; + if(!strcmp(name,"uint16")){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_uint16(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("uint16", dissectorname, "FT_UINT16", "BASE_DEC", "0", "NULL", 2); + } else if(!strcmp(name,"int16")){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_uint16(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("int16", dissectorname, "FT_INT16", "BASE_DEC", "0", "NULL", 2); + } else if(!strcmp(name,"uint32")){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("uint32", dissectorname, "FT_UINT32", "BASE_DEC", "0", "NULL", 4); + } else if( (!strcmp(name,"int32")) + || (!strcmp(name,"long")) ){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("int32", dissectorname, "FT_INT32", "BASE_DEC", "0", "NULL", 4); + tmptype=register_new_type("long", dissectorname, "FT_INT32", "BASE_DEC", "0", "NULL", 4); + } else if( (!strcmp(name,"uint8")) ){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_uint8(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("uint8", dissectorname, "FT_UINT8", "BASE_DEC", "0", "NULL", 1); + } else if( (!strcmp(name,"int8")) + || (!strcmp(name, "char")) ){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_uint8(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("int8", dissectorname, "FT_INT8", "BASE_DEC", "0", "NULL", 1); + tmptype=register_new_type("char", dissectorname, "FT_INT8", "BASE_DEC", "0", "NULL", 1); + } else if(!strcmp(name,"bool8")){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_uint8(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("bool8", dissectorname, "FT_INT8", "BASE_DEC", "0", "NULL", 1); + } else if(!strcmp(name,"unistr")){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep, 2, hf_index, FALSE, NULL);\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("unistr", dissectorname, "FT_STRING", "BASE_DEC", "0", "NULL", 4); + } else if(!strcmp(name,"ascstr")){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep, 1, hf_index, FALSE, NULL);\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("ascstr", dissectorname, "FT_STRING", "BASE_DEC", "0", "NULL", 4); + } else if(!strcmp(name,"GUID") + ||!strcmp(name,"uuid_t")){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_uuid_t(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type(name, dissectorname, "FT_STRING", "BASE_NONE", "0", "NULL", 4); + } else if(!strcmp(name,"policy_handle")){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static e_ctx_hnd policy_hnd;\n"); + FPRINTF(eth_code, "static proto_item *hnd_item;\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,\n"); + FPRINTF(eth_code, " hf_index, &policy_hnd, &hnd_item,\n"); + FPRINTF(eth_code, " param&0x01, param&0x02);\n"); + + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("policy_handle", dissectorname, "FT_BYTES", "BASE_NONE", "0", "NULL", 4); + } else if(!strcmp(name,"NTTIME")){ + /* 8 bytes, aligned to 4 bytes */ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep, hf_index);\n"); + + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("NTTIME", dissectorname, "FT_ABSOLUTE_TIME", "BASE_NONE", "0", "NULL", 4); + } else if(!strcmp(name,"NTTIME_hyper")){ + /* 8 bytes, aligned to 8 bytes */ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " ALIGN_TO_8_BYTES;\n"); + FPRINTF(eth_code, " offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep, hf_index);\n"); + + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("NTTIME_hyper", dissectorname, "FT_ABSOLUTE_TIME", "BASE_NONE", "0", "NULL", 4); + } else if(!strcmp(name,"udlong")){ + /* 8 bytes, aligned to 4 bytes */ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " offset=dissect_ndr_duint32(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("udlong", dissectorname, "FT_UINT64", "BASE_DEC", "0", "NULL", 4); + } else if(!strcmp(name,"dlong")){ + /* 8 bytes, aligned to 4 bytes */ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " offset=dissect_ndr_duint32(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("dlong", dissectorname, "FT_INT64", "BASE_DEC", "0", "NULL", 4); + } else if(!strcmp(name,"uint64")){ + /* 8 bytes, aligned to 8 bytes */ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " \n"); + FPRINTF(eth_code, " ALIGN_TO_8_BYTES;\n"); + FPRINTF(eth_code, " offset=dissect_ndr_uint64(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("uint64", dissectorname, "FT_UINT64", "BASE_DEC", "0", "NULL", 8); + } else if(!strcmp(name,"time_t")){ + sprintf(dissectorname, "%s_dissect_%s", ifname, name); + FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " \n"); + FPRINTF(eth_code, " offset=dissect_ndr_time_t(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + tmptype=register_new_type("time_t", dissectorname, "FT_ABSOLUTE_TIME", "BASE_DEC", "0", "NULL", 4); + } + } + + return tmptype; +} + + +/* this function will skip past an entire declare ... ; statement */ +void skipdeclare(void) +{ + token_item_t *ti; + + /* first must be the keyword const */ + ti=token_list; + if(strcmp(ti->str, "declare")){ + fprintf(stderr, "ERROR: skipdeclare first token is not 'declare'\n"); + Exit(10); + } + while(strcmp(ti->str, ";")){ + ti=ti->next; + } + ti=ti->next; + + token_list=ti; +} + +/* this function will parse a + const + and generate the appropriate code + const must be followed by a suitable keyword [uint16|uint32|...] + the const will later be removed from the token list + the function assumes that the const is the first object in the token_list +*/ +void parseconst(void) +{ + token_item_t *ti; + type_item_t *type_item; + char *name, *value; + + /* first must be the keyword const */ + ti=token_list; + if(strcmp(ti->str, "const")){ + fprintf(stderr, "ERROR: const first token is not 'const'\n"); + Exit(10); + } + ti=ti->next; + + /* just skip second token */ + ti=ti->next; + + /* third is a variable and not a type */ + if(find_type(ti->str)){ + fprintf(stderr, "ERROR: const, not a variable name:%s\n", ti->str); + Exit(10); + } + name=ti->str; + ti=ti->next; + + /* fourth is '=' */ + if(strcmp(ti->str, "=")){ + fprintf(stderr, "ERROR: const fourth token is not '='\n"); + Exit(10); + } + ti=ti->next; + + /* fifth is the value */ + value=ti->str; + ti=ti->next; + + /* sixth is ';' */ + if(strcmp(ti->str, ";")){ + fprintf(stderr, "ERROR: const sixth token is not ';'\n"); + Exit(10); + } + ti=ti->next; + + FPRINTF(NULL,"\nCONST:%s\n-------\n",name); + + FPRINTF(eth_hdr, "#define %s %s\n", name, value); + + FPRINTF(NULL,"\n----------\nEND CONST:%s\n",name); + + token_list=ti; +} + +/* this function will parse a + typedef struct { + construct and generate the appropriate code. + the typedef will be removed from the token_list once it has been processed + the function assumes that the typedef is the first object in the token_list + the function will be called twice, once with pass=0 and once with pass=1 + which controls whether subdissectors are to be generated or whether the + struct dissector itself is to be generated +*/ +void parsetypedefstruct(int pass) +{ + token_item_t *ti, *tmpti; + char *struct_name; + char dissectorname[256]; + char tmpstr[256], *ptmpstr; + int level, num_pointers; + static int alignment; + type_item_t *type_item; + char hf_index[256]; + bracket_item_t *bi=NULL; + pointer_item_t *pi; + char *pointer_type; + char *field_name; + int fixed_array_size; + int is_array_of_pointers; + + ti=token_list; + if(strcmp(ti->str, "typedef")){ + fprintf(stderr, "ERROR: typedefstruct first token is not 'typedef'\n"); + Exit(10); + } + ti=ti->next; + + if(!strcmp(ti->str, "[")){ + ti=parsebrackets(ti, &bi); + } + /* check that we know how to handle the bracket thing */ + if(bi){ + if(bi->flags){ + fprintf(stderr, "ERROR: typedefstruct unknown bracket flags encountered : 0x%08x\n",bi->flags); + Exit(10); + } + } + + if(strcmp(ti->str, "struct")){ + fprintf(stderr, "ERROR: typedefstruct second token is not 'struct'\n"); + Exit(10); + } + ti=ti->next; + + if(strcmp(ti->str, "{")){ + fprintf(stderr, "ERROR: typedefstruct third token is not '{'\n"); + Exit(10); + } + ti=ti->next; + + /* search forward until the '}' so we can find the name of the struct */ + for(tmpti=ti,level=0;tmpti;tmpti=tmpti->next){ + if(!strcmp(tmpti->str, "{")){ + level++; + continue; + } + if(!strcmp(tmpti->str, "}")){ + if(!level){ + break; + } + level--; + continue; + } + } + struct_name=tmpti->next->str; + sprintf(dissectorname, "%s_dissect_%s", ifname, struct_name); + + FPRINTF(NULL,"\nSTRUCT:%s pass:%d\n-------\n",struct_name,pass); + + if(!check_if_to_emit(dissectorname)){ + ti=tmpti; + goto typedef_struct_finished; + } + + /* this is pass 0 so reset alignment to zero and update as items are + processed. we need alignment when pass 1 is run */ + if(pass==0){ + alignment=0; + } + /* pass 1 generate header for the struct dissector */ + if(pass==1){ + FPRINTF(eth_ett, "static gint ett_%s_%s = -1;\n", ifname, struct_name); + FPRINTF(eth_ettarr, " &ett_%s_%s,\n", ifname, struct_name); + FPRINTF(eth_hdr, "int %s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param);\n", dissectorname); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " proto_item *item=NULL;\n"); + FPRINTF(eth_code, " proto_tree *tree=NULL;\n"); + FPRINTF(eth_code, " int old_offset;\n"); + FPRINTF(eth_code, "\n"); + switch(alignment){ + case 1: + break; + case 2: + FPRINTF(eth_code, " ALIGN_TO_2_BYTES;\n"); + FPRINTF(eth_code, "\n"); + break; + case 4: + FPRINTF(eth_code, " ALIGN_TO_4_BYTES;\n"); + FPRINTF(eth_code, "\n"); + break; + case 8: + FPRINTF(eth_code, " ALIGN_TO_8_BYTES;\n"); + FPRINTF(eth_code, "\n"); + break; + default: + fprintf(stderr, "ERROR: can not handle alignment:%d\n",alignment); + Exit(10); + } + FPRINTF(eth_code, " old_offset=offset;\n"); + FPRINTF(eth_code, " if(parent_tree){\n"); + FPRINTF(eth_code, " item=proto_tree_add_item(parent_tree, hf_index, tvb, offset, -1, TRUE);\n"); + FPRINTF(eth_code, " tree=proto_item_add_subtree(item, ett_%s_%s);\n", ifname, struct_name); + FPRINTF(eth_code, " }\n"); + FPRINTF(eth_code, "\n"); + } + + /* scan the struct and create all subdissectors */ + level=0; + while(ti){ + if(!strcmp(ti->str, "{")){ + level++; + ti=ti->next; + continue; + } + if(!strcmp(ti->str, "}")){ + if(!level){ + break; + } + level--; + ti=ti->next; + continue; + } + if(!strcmp(ti->str, "[")){ + ti=parsebrackets(ti, &bi); + continue; + } + + /* check that we know how to handle the bracket thing */ + if(bi){ + if(bi->flags&(~(BI_SIZE_IS|BI_LENGTH_IS|BI_POINTER))){ + fprintf(stderr, "ERROR: typedefstruct unknown bracket flags encountered : 0x%08x\n",bi->flags); + Exit(10); + } + } + + /* handle the type, verify that we KNOW this type */ + type_item=find_type(ti->str); + if(!type_item){ + fprintf(stderr, "ERROR : typedefstruct unknown type %s\n",ti->str); + Exit(10); + } + ti=ti->next; + /* count the levels of pointers */ + for(num_pointers=0;!strcmp(ti->str, "*");ti=ti->next){ + num_pointers++; + /* poitners are aligned at 4 byte boundaries */ + if(alignment<4){ + alignment=4; + } + } + /* now that we know how many real poitner there were we must + prepend default pointers to the list so it has the right + length. + */ + pi=prepend_pointer_list(bi?bi->pointer_list:NULL, num_pointers); + /* keep track of alignment */ + if(alignment<type_item->alignment){ + alignment=type_item->alignment; + } + + field_name=ti->str; + ti=ti->next; + + /* see if it is a fixed array */ + fixed_array_size=0; + is_array_of_pointers=0; + if(!strcmp(ti->str, "[")){ + char fss[256]; + + /* this might be a fixed array */ + ti=ti->next; + + fixed_array_size=atoi(ti->str); + sprintf(fss, "%d", fixed_array_size); + + if(!strcmp("*", ti->str)){ + if(bi && !(bi->flags|BI_POINTER)){ + pi=prepend_pointer_list(pi, 1); + } + fixed_array_size=0; + is_array_of_pointers=1; + } else if(strcmp(fss, ti->str)){ + fprintf(stderr, "ERROR: typedefstruct (%s) fixed array size looks different to calculated one %s!=%s\n", struct_name, fss, ti->str); + Exit(10); + } + ti=ti->next; + + if(strcmp(ti->str, "]")){ + fprintf(stderr, "ERROR: typedefstruct fixed array does not end with ']''\n"); + Exit(10); + } + ti=ti->next; + } + + sprintf(hf_index, "hf_%s_%s_%s", ifname, struct_name, field_name); + /* pass 0 generate subdissectors */ + if(pass==0){ + char filter_name[256]; + char *hf; + + sprintf(tmpstr, "%s_dissect_%s_%s", ifname, struct_name, field_name); + ptmpstr=strdup(tmpstr); + sprintf(filter_name, "%s.%s.%s", ifname, struct_name, field_name); + hf=register_hf_field(hf_index, field_name, filter_name, type_item->ft_type, type_item->base_type, type_item->vals, type_item->mask, ""); + + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", ptmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " guint32 param=%s;\n",find_dissector_param_value(ptmpstr)); + FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, drep, %s, param);\n", type_item->dissector, hf); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + + if(is_array_of_pointers){ + pointer_type=pi->type; + pi=pi->next; + sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, %s, %s, \"%s\", -1);\n", ptmpstr, ptr_to_define(pointer_type), field_name); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + + ptmpstr=strdup(tmpstr); + } else if(fixed_array_size){ + sprintf(tmpstr, "fixedarray_%s", ptmpstr); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " int count=%d;\n",fixed_array_size); + FPRINTF(eth_code, " while(count--){\n"); + FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, drep);\n", ptmpstr); + FPRINTF(eth_code, " }\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + ptmpstr=strdup(tmpstr); + } + + /* handle switch_is */ + if(bi){ + switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){ + case 0: + break; + case BI_SIZE_IS: + sprintf(tmpstr, "ucarray_%s", ptmpstr); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, %s);\n", ptmpstr); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + ptmpstr=strdup(tmpstr); + break; + case BI_SIZE_IS|BI_LENGTH_IS: + sprintf(tmpstr, "ucvarray_%s", ptmpstr); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep, %s);\n", ptmpstr); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + ptmpstr=strdup(tmpstr); + break; + default: + fprintf(stderr, "ERROR: typedefstruct can not handle this combination of sizeis/lengthis\n"); + Exit(10); + } + } + + /* handle pointers */ + while(num_pointers--){ + pointer_type=pi->type; + pi=pi->next; + sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, %s, %s, \"%s\", -1);\n", ptmpstr, ptr_to_define(pointer_type), field_name); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + + ptmpstr=strdup(tmpstr); + } + } + + if(pass==1){ + sprintf(tmpstr, "%s_dissect_%s_%s", ifname, struct_name, field_name); + ptmpstr=strdup(tmpstr); + + /* handle fixedsizearrays */ + if(is_array_of_pointers){ + pointer_type=pi->type; + pi=pi->next; + sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr); + ptmpstr=strdup(tmpstr); + } else if(fixed_array_size){ + sprintf(tmpstr, "fixedarray_%s", ptmpstr); + ptmpstr=strdup(tmpstr); + } + + /* handle switch_is */ + if(bi){ + switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){ + case 0: + break; + case BI_SIZE_IS: + sprintf(tmpstr, "ucarray_%s", ptmpstr); + ptmpstr=strdup(tmpstr); + break; + case BI_SIZE_IS|BI_LENGTH_IS: + sprintf(tmpstr, "ucvarray_%s", ptmpstr); + ptmpstr=strdup(tmpstr); + break; + default: + fprintf(stderr, "ERROR: typedefstruct can not handle this combination of sizeis/lengthis\n"); + Exit(10); + } + } + + /* handle pointers */ + while(num_pointers--){ + pointer_type=pi->type; + pi=pi->next; + sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr); + ptmpstr=strdup(tmpstr); + } + + FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, drep);\n", ptmpstr); + FPRINTF(eth_code, "\n"); + } + + if(strcmp(ti->str,";")){ + fprintf(stderr, "ERROR: field does not en with ';'\n"); + Exit(10); + } + ti=ti->next; + bi=NULL; /* clear bi before we start on the next field */ + } + + if(pass==1){ + FPRINTF(eth_code, " proto_item_set_len(item, offset-old_offset);\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + register_new_type(struct_name, dissectorname, "FT_NONE", "BASE_NONE", "0", "NULL", alignment); + } + + +typedef_struct_finished: + FPRINTF(NULL,"\nEND STRUCT:%s pass:%d\n-------\n",struct_name,pass); + + /* only advance token_list for pass==1 + ti now points to the '}' token + */ + if(pass==1){ + if(strcmp(ti->str,"}")){ + fprintf(stderr, "ERROR: struct does not end with '}'\n"); + Exit(10); + } + ti=ti->next; + + /* just skip the name */ + ti=ti->next; + + if(strcmp(ti->str,";")){ + fprintf(stderr, "ERROR: struct does not end with ';'\n"); + Exit(10); + } + ti=ti->next; + + token_list=ti; + } +} + +/* this function will parse a + typedef bitmap { + construct and generate the appropriate code. + the typedef will be removed from the token_list once it has been processed + the function assumes that the typedef is the first object in the token_list + the function will be called twice, once with pass=0 and once with pass=1 + which controls whether subdissectors are to be generated or whether the + bitmap dissector itself is to be generated + + bitmaps are by default 32 bits +*/ +void parsetypedefbitmap(int pass) +{ + token_item_t *ti, *tmpti; + char *bitmap_name; + char dissectorname[256], hf_bitname[256]; + int alignment, val; + char *name, *value; + bracket_item_t *bi=NULL; + + char tmpstr[256], *ptmpstr; + type_item_t *type_item; + char hf_index[256]; + + ti=token_list; + if(strcmp(ti->str, "typedef")){ + fprintf(stderr, "ERROR: typedefbitmap first token is not 'typedef'\n"); + Exit(10); + } + ti=ti->next; + + alignment=4; /* default size is 32 bits */ + + if(!strcmp(ti->str, "[")){ + ti=parsebrackets(ti, &bi); + } + /* check that we know how to handle the bracket thing */ + if(bi){ + if(bi->flags&(~(BI_BITMAP32))){ + fprintf(stderr, "ERROR: typedefbitmap unknown bracket flags encountered : 0x%08x\n",bi->flags); + Exit(10); + } + if(bi->flags&BI_BITMAP32){ + alignment=4; + } + } + + + if(strcmp(ti->str, "bitmap")){ + fprintf(stderr, "ERROR: typedefbitmap second token is not 'bitmap'\n"); + Exit(10); + } + ti=ti->next; + + if(strcmp(ti->str, "{")){ + fprintf(stderr, "ERROR: typedefbitmap third token is not '{'\n"); + Exit(10); + } + ti=ti->next; + + /* search forward until the '}' so we can find the name of the bitmap */ + for(tmpti=ti;tmpti;tmpti=tmpti->next){ + if(!strcmp(tmpti->str, "{")){ + fprintf(stderr, "ERROR: typedefbitmap '{' encountered inside bitmap\n"); + Exit(10); + } + if(!strcmp(tmpti->str, "}")){ + break; + } + } + bitmap_name=tmpti->next->str; + sprintf(dissectorname, "%s_dissect_%s", ifname, bitmap_name); + + FPRINTF(NULL,"\nBITMAP:%s pass:%d\n-------\n",bitmap_name,pass); + + /* pass 1 generate header for the struct dissector */ + if(pass==1){ + FPRINTF(eth_ett, "static gint ett_%s_%s = -1;\n", ifname, bitmap_name); + FPRINTF(eth_ettarr, " &ett_%s_%s,\n", ifname, bitmap_name); + FPRINTF(eth_hdr, "int %s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param);\n", dissectorname); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " proto_item *item=NULL;\n"); + FPRINTF(eth_code, " proto_tree *tree=NULL;\n"); + switch(alignment){ + case 4: + FPRINTF(eth_code, " guint32 flags;\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " ALIGN_TO_4_BYTES;\n"); + break; + default: + fprintf(stderr, "ERROR: typedefbitmap can not handle alignment:%d\n",alignment); + Exit(10); + } + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " if(parent_tree){\n"); + FPRINTF(eth_code, " item=proto_tree_add_item(parent_tree, hf_index, tvb, offset, %d, TRUE);\n", alignment); + FPRINTF(eth_code, " tree=proto_item_add_subtree(item, ett_%s_%s);\n", ifname, bitmap_name); + FPRINTF(eth_code, " }\n"); + FPRINTF(eth_code, "\n"); + switch(alignment){ + case 4: + FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &flags);\n"); + FPRINTF(eth_code, "\n"); + break; + default: + fprintf(stderr, "ERROR: typedefbitmap can not handle alignment:%d\n",alignment); + Exit(10); + } + FPRINTF(eth_code, "\n"); + } + + /* scan the struct and create call for all bits */ + while(ti){ + if(!strcmp(ti->str, "}")){ + break; + } + if(!strcmp(ti->str, "[")){ + fprintf(stderr, "ERROR: typedefbitmap can not handle '[' yet\n"); + Exit(10); + } + + name=ti->str; + ti=ti->next; + sprintf(hf_bitname, "hf_%s_%s_%s", ifname, bitmap_name, name); + + if(strcmp(ti->str, "=")){ + fprintf(stderr, "ERROR: typedefbitmap i expected a '=' here\n"); + Exit(10); + } + ti=ti->next; + + value=ti->str; + ti=ti->next; + if(!strncmp(value, "0x", 2)){ + sscanf(value, "0x%x", &val); + } else { + fprintf(stderr, "ERROR: typedefbitmap can only handle hexadecimal constants\n"); + Exit(10); + } + + if( val&(val-1) ){ + fprintf(stderr, "ERROR: typedefbitmap can only handle single bit fields\n"); + Exit(10); + } + + if(pass==0){ + char filter_name[256], base_name[256], tfs_name[256]; + char *hf; + sprintf(filter_name, "%s.%s.%s", ifname, bitmap_name, name); + sprintf(base_name, "%d", alignment*8); + sprintf(tfs_name, "TFS(&%s_tfs)", name); + hf=register_hf_field(hf_bitname, name, filter_name, "FT_BOOLEAN", base_name, tfs_name, value, ""); + + FPRINTF(eth_code, "static const true_false_string %s_tfs = {\n",name); + FPRINTF(eth_code, " \"%s is SET\",\n", name); + FPRINTF(eth_code, " \"%s is NOT set\"\n", name); + FPRINTF(eth_code, "};\n"); + FPRINTF(eth_code, "\n"); + } + + if(pass==1){ + FPRINTF(eth_code, " proto_tree_add_boolean(tree, %s, tvb, offset-%d, %d, flags);\n", hf_bitname, alignment, alignment); + FPRINTF(eth_code, " if(flags&%s){\n", value); + FPRINTF(eth_code, " proto_item_append_text(item, \" %s\");\n", name); + FPRINTF(eth_code, " }\n"); + FPRINTF(eth_code, " flags&=(~%s);\n", value); + FPRINTF(eth_code, "\n"); + } + + if(!strcmp(ti->str, ",")){ + ti=ti->next; + continue; + } + } + + if(pass==1){ + FPRINTF(eth_code, " if(flags){\n"); + FPRINTF(eth_code, " proto_item_append_text(item, \"UNKNOWN-FLAGS\");\n"); + FPRINTF(eth_code, " }\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + switch(alignment){ + case 4: + register_new_type(bitmap_name, dissectorname, "FT_UINT32", "BASE_HEX", "0", "NULL", alignment); + break; + default: + fprintf(stderr, "ERROR: typedefbitmap can not handle alignment:%d\n",alignment); + Exit(10); + } + } + + FPRINTF(NULL,"\nEND BITMAP:%s pass:%d\n-------\n",bitmap_name,pass); + + /* only advance token_list for pass==1 + ti now points to the '}' token + */ + if(pass==1){ + if(strcmp(ti->str,"}")){ + fprintf(stderr, "ERROR: bitmap does not end with '}'\n"); + Exit(10); + } + ti=ti->next; + + /* just skip the name */ + ti=ti->next; + + if(strcmp(ti->str,";")){ + fprintf(stderr, "ERROR: bitmap does not end with ';'\n"); + Exit(10); + } + ti=ti->next; + + token_list=ti; + } +} + +/* this function will parse a + typedef union { + construct and generate the appropriate code. + the typedef will be removed from the token_list once it has been processed + the function assumes that the typedef is the first object in the token_list + the function will be called twice, once with pass=0 and once with pass=1 + which controls whether subdissectors are to be generated or whether the + union dissector itself is to be generated +*/ +void parsetypedefunion(int pass) +{ + char *union_name; + token_item_t *ti, *tmpti; + char dissectorname[256]; + bracket_item_t *bi=NULL; + char tmpstr[256], *ptmpstr; + int level, num_pointers; + static int alignment; + type_item_t *type_item; + char hf_index[256]; + int tag_alignment, item_alignment; + + ti=token_list; + if(strcmp(ti->str, "typedef")){ + fprintf(stderr, "ERROR: typedefunion first token is not 'typedef'\n"); + Exit(10); + } + ti=ti->next; + + if(strcmp(ti->str, "union")){ + fprintf(stderr, "ERROR: typedefunion second token is not 'union'\n"); + Exit(10); + } + ti=ti->next; + + if(strcmp(ti->str, "{")){ + fprintf(stderr, "ERROR: typedefunion third token is not '{'\n"); + Exit(10); + } + ti=ti->next; + + /* search forward until the '}' so we can find the name of the union */ + for(tmpti=ti,level=0;tmpti;tmpti=tmpti->next){ + if(!strcmp(tmpti->str, "{")){ + level++; + continue; + } + if(!strcmp(tmpti->str, "}")){ + if(!level){ + break; + } + level--; + continue; + } + } + union_name=tmpti->next->str; + sprintf(dissectorname, "%s_dissect_union_%s", ifname, union_name); + + FPRINTF(NULL,"\nUNION:%s pass:%d\n-------\n",union_name,pass); + + tag_alignment=get_union_tag_size(union_name); + + + /* this is pass 0 so reset alignment to the minimum possible value + and update as items are processed. + we need alignment when pass 1 is run + */ + if(pass==0){ + alignment=tag_alignment; + } + + /* pass 1 generate header for the struct dissector */ + if(pass==1){ + FPRINTF(eth_ett, "static gint ett_%s_%s = -1;\n", ifname, union_name); + FPRINTF(eth_ettarr, " &ett_%s_%s,\n", ifname, union_name); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " proto_item *item=NULL;\n"); + FPRINTF(eth_code, " proto_tree *tree=NULL;\n"); + FPRINTF(eth_code, " int old_offset;\n"); + /* we do alignment on the tag itself here so that + we skip any alignment padding prior to where the tag + itself starts, this makes the byterange in the hexpane + for the union expansion start with the first byte of the tag + */ + switch(tag_alignment){ + case 1: + break; + case 2: + FPRINTF(eth_code, " guint16 level;\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " ALIGN_TO_2_BYTES;\n"); + FPRINTF(eth_code, "\n"); + break; + case 4: + FPRINTF(eth_code, " guint32 level;\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " ALIGN_TO_4_BYTES;\n"); + FPRINTF(eth_code, "\n"); + break; + default: + fprintf(stderr, "ERROR: typedefunion 1 can not handle alignment:%d\n",alignment); + Exit(10); + } + FPRINTF(eth_code, " old_offset=offset;\n"); + FPRINTF(eth_code, " if(parent_tree){\n"); + FPRINTF(eth_code, " item=proto_tree_add_text(parent_tree, tvb, offset, -1, \"%s\");\n", union_name); + FPRINTF(eth_code, " tree=proto_item_add_subtree(item, ett_%s_%s);\n", ifname, union_name); + FPRINTF(eth_code, " }\n"); + FPRINTF(eth_code, "\n"); + switch(tag_alignment){ + case 1: + break; + case 2: + FPRINTF(eth_code, " offset=dissect_ndr_uint16(tvb, offset, pinfo, tree,\n"); + FPRINTF(eth_code, " drep, hf_index, &level);\n"); + break; + case 4: + FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, tree,\n"); + FPRINTF(eth_code, " drep, hf_index, &level);\n"); + break; + default: + fprintf(stderr, "ERROR: typedefunion 2 can not handle alignment:%d\n",alignment); + Exit(10); + } + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " switch(level){\n"); + } + + /* scan the struct and create all subdissectors */ + level=0; + while(ti){ + if(!strcmp(ti->str, "{")){ + ti=ti->next; + level++; + continue; + } + if(!strcmp(ti->str, "}")){ + if(!level){ + break; + } + ti=ti->next; + level--; + continue; + } + if(!strcmp(ti->str, "[")){ + ti=parsebrackets(ti, &bi); + continue; + } + + if(!bi){ + fprintf(stderr, "ERROR : typedefunion no brackets found for case\n"); + Exit(10); + } + /* make sure we catch when we havent implemented everything + yet. + we currently only know about CASE and CASE_DEFAULT flags + */ + if(bi->flags&(~(BI_CASE|BI_CASE_DEFAULT|BI_POINTER))){ + fprintf(stderr, "ERROR: typedefunion unknown bracket flags encountered : 0x%08x\n",bi->flags); + Exit(10); + } + if(!(bi->flags&BI_CASE)){ + fprintf(stderr, "ERROR : typedefunion no case found in brackets\n"); + Exit(10); + } + /* only empty default cases for now */ + if(bi->flags&BI_CASE_DEFAULT){ + if(strcmp(ti->str,";")){ + fprintf(stderr, "ERROR: default tag is not empty\n"); + Exit(10); + } + ti=ti->next; + continue; + } + + /* just skip all and any 'empty' arms */ + if(!strcmp(ti->str, ";")){ + ti=ti->next; + continue; + } + + /* handle the type, verify that we KNOW this type */ + type_item=find_type(ti->str); + if(!type_item){ + fprintf(stderr, "ERROR : typedefunion unknown type %s\n",ti->str); + Exit(10); + } + ti=ti->next; + /* count the levels of pointers */ + for(num_pointers=0;!strcmp(ti->str, "*");ti=ti->next){ + num_pointers++; + } + + /* keep track of alignment */ + if(num_pointers){ + item_alignment=4; + } else { + item_alignment=type_item->alignment; + } + if(alignment<item_alignment){ + alignment=item_alignment; + } + + sprintf(hf_index, "hf_%s_%s_%s_%s", ifname, union_name, bi->case_name, ti->str); + /* pass 0 generate subdissectors */ + if(pass==0){ + char filter_name[256]; + char *hf; + sprintf(tmpstr, "%s_dissect_union_%s_%s_%s", ifname, union_name, bi->case_name, ti->str); + ptmpstr=strdup(tmpstr); + + sprintf(filter_name, "%s.%s.%s", ifname, union_name, ti->str); + hf=register_hf_field(hf_index, ti->str, filter_name, type_item->ft_type, type_item->base_type, type_item->vals, type_item->mask, ""); + + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", ptmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " guint32 param=%s;\n",find_dissector_param_value(ptmpstr)); + FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, drep, %s, param);\n", type_item->dissector, hf); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + + /* handle pointers */ + while(num_pointers--){ + sprintf(tmpstr, "%s_%s", ptmpstr, "unique"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, %s, NDR_POINTER_UNIQUE, \"%s\", -1);\n", ptmpstr, ti->str); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + + ptmpstr=strdup(tmpstr); + + } + } + + if(pass==1){ + /* handle pointers */ + sprintf(tmpstr, "%s_dissect_union_%s_%s_%s", ifname, union_name, bi->case_name, ti->str); + ptmpstr=strdup(tmpstr); + while(num_pointers--){ + sprintf(tmpstr, "%s_%s", ptmpstr, "unique"); + ptmpstr=strdup(tmpstr); + } + + FPRINTF(eth_code, " case %s:\n",bi->case_name); + /* each arm itself is aligned independently */ + switch(item_alignment){ + case 1: + break; + case 2: + FPRINTF(eth_code, " ALIGN_TO_2_BYTES;\n"); + break; + case 4: + FPRINTF(eth_code, " ALIGN_TO_4_BYTES;\n"); + break; + case 8: + FPRINTF(eth_code, " ALIGN_TO_8_BYTES;\n"); + break; + default: + fprintf(stderr, "ERROR: typedefunion 3 can not handle alignment:%d\n",item_alignment); + Exit(10); + } + FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, drep);\n", ptmpstr); + FPRINTF(eth_code, " break;\n"); + FPRINTF(eth_code, "\n"); + } + ti=ti->next; + + if(strcmp(ti->str,";")){ + fprintf(stderr, "ERROR: field does not end with ';'\n"); + Exit(10); + } + ti=ti->next; + } + + if(pass==1){ + FPRINTF(eth_code, " }\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " proto_item_set_len(item, offset-old_offset);\n"); + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + switch(tag_alignment){ + case 2: + register_new_type(union_name, dissectorname, "FT_UINT16", "BASE_DEC", "0", "NULL", alignment); + break; + case 4: + register_new_type(union_name, dissectorname, "FT_UINT32", "BASE_DEC", "0", "NULL", alignment); + break; + default: + fprintf(stderr, "ERROR: typedefunion 4 can not handle alignment:%d\n",alignment); + Exit(10); + } + } + + FPRINTF(NULL,"\nEND UNION:%s pass:%d\n-------\n",union_name,pass); + + /* only advance token_list for pass==1 + ti now points to the '}' token + */ + if(pass==1){ + if(strcmp(ti->str,"}")){ + fprintf(stderr, "ERROR: union does not end with '}'\n"); + Exit(10); + } + ti=ti->next; + + /* just skip the name */ + ti=ti->next; + + if(strcmp(ti->str,";")){ + fprintf(stderr, "ERROR: union does not end with ';'\n"); + Exit(10); + } + ti=ti->next; + + token_list=ti; + } +} + + +/* this function will parse a + WERROR function ( + construct and generate the appropriate code. + the function will be removed from the token_list once it has been processed + the function assumes that the function is the first object in the token_list + the function will be called three times with + pass=0 generate subdissectors and entries for the function table + pass=1 generate code for the REQUEST + pass=2 generate code for the REPLY +*/ +void parsefunction(int pass) +{ + char *function_name; + static int funcno=0; + token_item_t *ti; + bracket_item_t *bi=NULL; + pointer_item_t *pi; + char *pointer_type; + + char tmpstr[256], *ptmpstr; + int level, num_pointers; + type_item_t *type_item; + char hf_index[256]; + + ti=token_list; + if(strcmp(ti->str, "WERROR")){ + fprintf(stderr, "ERROR: function first token is not 'WERROR'\n"); + Exit(10); + } + ti=ti->next; + + function_name=ti->str; + ti=ti->next; + + if(strcmp(ti->str, "(")){ + fprintf(stderr, "ERROR: function third token is not '('\n"); + Exit(10); + } + ti=ti->next; + + FPRINTF(NULL,"\nFUNCTION:%s pass:%d\n-------\n",function_name,pass); + + if(pass==0){ + FPRINTF(eth_ft, " { %d, \"%s\",\n",funcno,function_name); + FPRINTF(eth_ft, " %s_dissect_%s_request,\n", ifname, function_name); + FPRINTF(eth_ft, " %s_dissect_%s_response },\n", ifname, function_name); + funcno++; + } + + /* pass 1,2 generate header for the function dissector */ + if((pass==1)||(pass==2)){ + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s_dissect_%s_%s(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_)\n", ifname, function_name, (pass==1)?"request":"response"); + FPRINTF(eth_code, "{\n"); + } + + /* scan the struct and create all subdissectors */ + level=0; + while(ti){ + if(!strcmp(ti->str, "(")){ + ti=ti->next; + level++; + continue; + } + if(!strcmp(ti->str, ")")){ + if(!level){ + break; + } + ti=ti->next; + level--; + continue; + } + if(!strcmp(ti->str, "[")){ + ti=parsebrackets(ti, &bi); + continue; + } + + if(!bi){ + fprintf(stderr, "ERROR : function no brackets found for case\n"); + Exit(10); + } + + /* make sure we catch when we havent implemented everything + yet. + we currently only know about IN and OUT flags + */ + if(bi->flags&(~(BI_IN|BI_OUT|BI_POINTER|BI_SIZE_IS|BI_LENGTH_IS))){ + fprintf(stderr, "ERROR: function unknown bracket flags encountered : 0x%08x\n",bi->flags); + Exit(10); + } + if(!(bi->flags&(BI_IN|BI_OUT))){ + fprintf(stderr, "ERROR : function parameter is neither in nor out\n"); + Exit(10); + } + + /* handle the type, verify that we KNOW this type */ + type_item=find_type(ti->str); + if(!type_item){ + fprintf(stderr, "ERROR : function unknown type %s\n",ti->str); + Exit(10); + } + ti=ti->next; + /* count the levels of pointers */ + for(num_pointers=0;!strcmp(ti->str, "*");ti=ti->next){ + num_pointers++; + } + + /* now that we know how many real poitner there were we must + prepend default pointers to the list so it has the right + length. + */ + pi=prepend_pointer_list(bi->pointer_list, num_pointers); + + sprintf(hf_index, "hf_%s_%s_%s", ifname, function_name, ti->str); + /* pass 0 generate subdissectors */ + if(pass==0){ + char filter_name[256]; + char *hf; + + sprintf(tmpstr, "%s_dissect_%s_%s", ifname, function_name, ti->str); + ptmpstr=strdup(tmpstr); + + + sprintf(filter_name, "%s.%s.%s", ifname, function_name, ti->str); + hf=register_hf_field(hf_index, ti->str, filter_name, type_item->ft_type, type_item->base_type, type_item->vals, type_item->mask, ""); + + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", ptmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " guint32 param=%s;\n",find_dissector_param_value(ptmpstr)); + FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, drep, %s, param);\n", type_item->dissector, hf); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + + + /* handle switch_is */ + if(bi){ + switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){ + case 0: + break; + case BI_SIZE_IS|BI_LENGTH_IS: + sprintf(tmpstr, "ucvarray_%s", ptmpstr); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep, %s);\n", ptmpstr); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + ptmpstr=strdup(tmpstr); + break; + case BI_SIZE_IS: + sprintf(tmpstr, "ucarray_%s", ptmpstr); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, %s);\n", ptmpstr); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + ptmpstr=strdup(tmpstr); + break; + default: + fprintf(stderr, "ERROR: typedeffunction can not handle this combination of sizeis/lengthis\n"); + Exit(10); + } + } + + /* handle pointers */ + while(num_pointers--){ + pointer_type=pi->type; + pi=pi->next; + sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr); + FPRINTF(eth_code, "static int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n", tmpstr); + FPRINTF(eth_code, "{\n"); + FPRINTF(eth_code, " offset=dissect_ndr_pointer(tvb, offset, pinfo, tree, drep, %s, %s, \"%s\", -1);\n", ptmpstr, ptr_to_define(pointer_type), ti->str); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + + ptmpstr=strdup(tmpstr); + + } + } + + if((pass==1)||(pass==2)){ + sprintf(tmpstr, "%s_dissect_%s_%s", ifname, function_name, ti->str); + ptmpstr=strdup(tmpstr); + + if(bi){ + switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){ + case 0: + break; + case BI_SIZE_IS|BI_LENGTH_IS: + sprintf(tmpstr, "ucvarray_%s", ptmpstr); + ptmpstr=strdup(tmpstr); + break; + case BI_SIZE_IS: + sprintf(tmpstr, "ucarray_%s", ptmpstr); + ptmpstr=strdup(tmpstr); + break; + default: + fprintf(stderr, "ERROR: typedeffunction can not handle this combination of sizeis/lengthis\n"); + Exit(10); + } + } + + /* handle pointers */ + while(num_pointers--){ + pointer_type=pi->type; + pi=pi->next; + sprintf(tmpstr, "%s_%s", pointer_type, ptmpstr); + ptmpstr=strdup(tmpstr); + } + + if((pass==1)&&(bi->flags&BI_IN)){ + FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, drep);\n", ptmpstr); + FPRINTF(eth_code, "\n"); + } + if((pass==2)&&(bi->flags&BI_OUT)){ + FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, drep);\n", ptmpstr); + FPRINTF(eth_code, "\n"); + } + } + ti=ti->next; + + + if(!strcmp(ti->str,",")){ + ti=ti->next; + continue; + } + } + + if((pass==1)||(pass==2)){ + if(pass==2){ + FPRINTF(eth_code, " offset=dissect_ntstatus(tvb, offset, pinfo, tree, drep, %s, NULL);\n", hf_status); + FPRINTF(eth_code, "\n"); + } + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + } + + FPRINTF(NULL,"\nEND FUNCTION:%s pass:%d\n-------\n",function_name,pass); + + /* only advance token_list for pass==2 + ti now points to the ')' token + */ + if(pass==2){ + if(strcmp(ti->str,")")){ + fprintf(stderr, "ERROR: function does not end with ')'\n"); + Exit(10); + } + ti=ti->next; + + if(strcmp(ti->str,";")){ + fprintf(stderr, "ERROR: function does not end with ';'\n"); + Exit(10); + } + ti=ti->next; + + token_list=ti; + } +} + + +/* this function will parse a + typedef enum { + or a + typedef [ v1_enum ] enum { + construct and generate the appropriate code. + the typedef will be removed from the token_list once it has been processed + the function assumes that the typedef is the first object in the token_list +*/ +void parsetypedefenum(void) +{ + token_item_t *ti; + enum_list_t *enum_list, *el, *lastel; + int eval, enumsize; + char dissectorname[256], valsstring[256], hfvalsstring[256]; + + enumsize=16; + + ti=token_list; + if(strcmp(ti->str, "typedef")){ + fprintf(stderr, "ERROR: typedefenum first token is not 'typedef'\n"); + Exit(10); + } + ti=ti->next; + + /* this could be a [ v1_enum ] */ + if(!strcmp(ti->str, "[")){ + ti=ti->next; + + if(strcmp(ti->str, "v1_enum")){ + fprintf(stderr, "ERROR: typedefenum not 'v1_enum' inside brackets\n"); + Exit(10); + } + ti=ti->next; + + if(strcmp(ti->str, "]")){ + fprintf(stderr, "ERROR: typedefenum 'v1_enum' is not followed by ']'\n"); + Exit(10); + } + ti=ti->next; + + enumsize=32; + } + + + if(strcmp(ti->str, "enum")){ + fprintf(stderr, "ERROR: typedefenum second token is not 'enum'\n"); + Exit(10); + } + ti=ti->next; + + if(strcmp(ti->str, "{")){ + fprintf(stderr, "ERROR: typedefenum third token is not '{'\n"); + Exit(10); + } + ti=ti->next; + + /* now parse all values until we find the "}" */ + eval=0; + enum_list=NULL; + lastel=NULL; + while(1){ + /* check for '}' */ + if(!strcmp(ti->str,"}")){ + ti=ti->next; + break; + } + + /* handle 4 types of entries: + * 1, CONST = value, + * 2, CONST, + * 3, CONST = value} + * 4, CONST} + */ + el=malloc(sizeof(enum_list_t)); + el->next=NULL; + if(!enum_list){ + enum_list=el; + } else { + lastel->next=el; + } + lastel=el; + + /* grab CONST */ + el->name=ti->str; + ti=ti->next; + + /* grab separator */ + if(!strcmp(ti->str,"=")){ + ti=ti->next; + /* grab value */ + el->val=atoi(ti->str); + ti=ti->next; + } else { + el->val=eval; + } + eval=el->val+1; + + /* check for ',' */ + if(!strcmp(ti->str,",")){ + ti=ti->next; + continue; + } + + /* check for '}' */ + if(!strcmp(ti->str,"}")){ + ti=ti->next; + break; + } + + fprintf(stderr,"ERROR: typedefenum should not be reached\n"); + Exit(10); + } + + /* verify that it ends with a ';' */ + if(strcmp(ti->next->str,";")){ + fprintf(stderr,"ERROR enum terminator is not ';'\n"); + Exit(10); + } + + sprintf(valsstring, "%s_%s_vals", ifname, ti->str); + sprintf(dissectorname, "%s_dissect_%s", ifname, ti->str); + + FPRINTF(NULL,"\nENUM:%s\n-------\n",ti->str); + + FPRINTF(eth_hdr, "\n"); + for(el=enum_list;el;el=el->next){ + FPRINTF(eth_hdr, "#define %s %d\n", el->name, el->val); + } + + FPRINTF(eth_hdr, "\n"); + FPRINTF(eth_hdr, "extern const value_string %s[];\n", valsstring); + FPRINTF(eth_hdr, "int %s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param);\n", dissectorname); + + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "const value_string %s[] = {\n", valsstring); + + for(el=enum_list;el;el=el->next){ + FPRINTF(eth_code, " { %d , \"%s\" },\n", el->val, el->name); + } + FPRINTF(eth_code, " { 0 , NULL }\n"); + FPRINTF(eth_code, "};\n"); + + FPRINTF(eth_code, "\n"); + FPRINTF(eth_code, "int\n"); + FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname); + FPRINTF(eth_code, "{\n"); + switch(enumsize){ + case 16: + FPRINTF(eth_code, " offset=dissect_ndr_uint16(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + break; + case 32: + FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_index, NULL);\n"); + break; + default: + fprintf(stderr,"ERROR enum unknown size\n"); + Exit(10); + } + + FPRINTF(eth_code, " return offset;\n"); + FPRINTF(eth_code, "}\n"); + FPRINTF(eth_code, "\n"); + + + sprintf(hfvalsstring, "VALS(%s)", valsstring); + switch(enumsize){ + case 16: + register_new_type(ti->str, dissectorname, "FT_INT16", "BASE_DEC", "0", hfvalsstring, 2); + break; + case 32: + register_new_type(ti->str, dissectorname, "FT_INT32", "BASE_DEC", "0", hfvalsstring, 4); + break; + default: + fprintf(stderr,"ERROR enum unknown size\n"); + Exit(10); + } + + FPRINTF(NULL,"\n----------\nEND ENUM:%s\n",ti->str); + + /* skip past the name and the ';' */ + token_list=ti->next->next; +} + +typedef struct _trimmed_prefixes_t { + struct _trimmed_prefixes_t *next; + char *name; +} trimmed_prefixes_t; +trimmed_prefixes_t *prefixes_to_trim=NULL; + +void preparetrimprefix(char *prefix_name) +{ + trimmed_prefixes_t *new_prefix; + new_prefix=malloc(sizeof(trimmed_prefixes_t)); + new_prefix->next=prefixes_to_trim; + prefixes_to_trim=new_prefix; + new_prefix->name=strdup(prefix_name); +} +void +trimprefix(void) +{ + token_item_t *ti; + trimmed_prefixes_t *pfx; + int len; + + for(pfx=prefixes_to_trim;pfx;pfx=pfx->next){ + len=strlen(pfx->name); + for(ti=token_list;ti;ti=ti->next){ + if(!strncmp(ti->str, pfx->name, len)){ + ti->str+=len; + } + } + } +} + +int Exit(int code) +{ + fprintf(stderr, "The tokens remaining when aborting:\n"); + printtokenlist(10); + + exit(code); +} + +void usage(void) +{ + fprintf(stderr, "Usage: idl2eth <interface>\n"); +} + +void +mergefile(char *name, FILE *outfile) +{ + FILE *infile; + + fprintf(outfile, "\n\n/* INCLUDED FILE : %s */\n", name); + infile=fopen(name, "r"); + while(!feof(infile)){ + int ch; + ch=fgetc(infile); + if(ch!=-1){ + fputc(ch, outfile); + } + } + fclose(infile); + fprintf(outfile, "/* END OF INCLUDED FILE : %s */\n\n\n", name); +} + + + +char * +str_read_string(char *str, char **name) +{ + char tmpstr[256], *strptr; + int skip_blanks; + int quoted_string; + + strptr=tmpstr; + skip_blanks=1; + quoted_string=0; + while(1){ + if(!*str){ + *strptr=0; + *name=strdup(tmpstr); + return str; + } + if(skip_blanks){ + if( (*str==' ') || (*str=='\t') ){ + str++; + continue; + } + if( *str=='"' ){ + str++; + quoted_string=1; + } + skip_blanks=0; + continue; + } + if( (*str==' ') || (*str=='\t') ){ + if(quoted_string){ + *strptr++ = *str++; + continue; + } + *strptr=0; + *name=strdup(tmpstr); + return str; + } + if( (*str=='"') || (*str=='\n') ){ + *strptr=0; + *name=strdup(tmpstr); + return ++str; + } + *strptr++ = *str++; + } + return NULL; +} + +void +readcnffile(FILE *fh) +{ + char cnfline[1024]; + + FPRINTF(NULL, "Reading conformance file\n=======================\n"); + while(!feof(fh)){ + cnfline[0]=0; + fgets(cnfline, 1023, fh); + if(!cnfline[0]){ + continue; + } + if(cnfline[0]=='#'){ + /* ignore all comments */ + } else if(!strncmp(cnfline, "NOEMIT", 6)){ + no_emit_item_t *nei; + char *str, *name; + + str=cnfline+6; + str=str_read_string(str, &name); + nei=malloc(sizeof(no_emit_item_t)); + nei->next=no_emit_list; + no_emit_list=nei; + nei->name=name; + FPRINTF(NULL, "NOEMIT : %s\n", nei->name); + } else if(!strncmp(cnfline, "TYPE", 4)){ + char *name, *dissectorname, *ft_type, *base_type; + char *mask, *valsstring, *al; + char *str; + int alignment; + + str=cnfline+4; + str=str_read_string(str, &name); + str=str_read_string(str, &dissectorname); + str=str_read_string(str, &ft_type); + str=str_read_string(str, &base_type); + str=str_read_string(str, &mask); + str=str_read_string(str, &valsstring); + str=str_read_string(str, &al); + alignment=atoi(al); + + FPRINTF(NULL, "TYPE : X%s,%sX\n", name, dissectorname); + register_new_type(name, dissectorname, ft_type, base_type, mask, valsstring, alignment); + } else if(!strncmp(cnfline, "PARAM_VALUE", 11)){ + char *dissectorname, *value; + char *str; + + str=cnfline+11; + str=str_read_string(str, &dissectorname); + str=str_read_string(str, &value); + + FPRINTF(NULL, "PARAM_VALUE : %s=%s\n", dissectorname,value); + register_dissector_param_value(dissectorname, value); + } else if(!strncmp(cnfline, "HF_FIELD", 8)){ + char *hf_index, *title, *filter_name, *ft_type; + char *base_type, *valsstring, *mask, *blurb; + char *str; + + str=cnfline+8; + str=str_read_string(str, &hf_index); + str=str_read_string(str, &title); + str=str_read_string(str, &filter_name); + str=str_read_string(str, &ft_type); + str=str_read_string(str, &base_type); + str=str_read_string(str, &valsstring); + str=str_read_string(str, &mask); + str=str_read_string(str, &blurb); + FPRINTF(NULL, "HF_FIELD: %s \"%s\"\n", hf_index, title); + register_hf_field(hf_index, title, filter_name, ft_type, base_type, valsstring, mask, blurb); + } else if(!strncmp(cnfline, "HF_RENAME", 9)){ + char *old_name, *new_name; + char *str; + + str=cnfline+9; + str=str_read_string(str, &old_name); + str=str_read_string(str, &new_name); + FPRINTF(NULL, "HF_RENAME: %s -> %s\n", old_name, new_name); + register_hf_rename(old_name, new_name); + } else if(!strncmp(cnfline, "UNION_TAG_SIZE", 14)){ + char *union_name, *union_tag; + int union_tag_size; + union_tag_size_item_t *utsi; + char *str; + + str=cnfline+14; + str=str_read_string(str, &union_name); + str=str_read_string(str, &union_tag); + union_tag_size=atoi(union_tag); + FPRINTF(NULL, "UNION_TAG_SIZE: %s == %d\n", union_name, union_tag_size); + utsi=malloc(sizeof(union_tag_size_item_t)); + utsi->next=union_tag_size_list; + union_tag_size_list=utsi; + utsi->name=strdup(union_name); + utsi->size=union_tag_size; + } else if(!strncmp(cnfline, "STRIP_PREFIX", 12)){ + char *prefix_name; + char *str; + + str=cnfline+12; + str=str_read_string(str, &prefix_name); + FPRINTF(NULL, "STRIP_PREFIX: %s\n", prefix_name); + preparetrimprefix(prefix_name); + } else { + fprintf(stderr, "ERROR: could not parse cnf directive:%s\n",cnfline); + exit(10); + } + } +} + +int main(int argc, char *argv[]) +{ + char idlfile[256]; + char cnffile[256]; + char prefix_str[256]; + bracket_item_t *bi; + + if(argc!=2){ + usage(); + exit(0); + } + + eth_code=fopen("ETH_CODE", "w"); + eth_hdr=fopen("ETH_HDR", "w"); + eth_hfarr=fopen("ETH_HFARR", "w"); + eth_hf=fopen("ETH_HF", "w"); + eth_ettarr=fopen("ETH_ETTARR", "w"); + eth_ett=fopen("ETH_ETT", "w"); + eth_ft=fopen("ETH_FT", "w"); + eth_handoff=fopen("ETH_HANDOFF", "w"); + + sprintf(idlfile, "%s.cnf", argv[1]); + fh=fopen(idlfile,"r"); + if(fh){ + readcnffile(fh); + fclose(fh); + } + + sprintf(idlfile, "%s.idl", argv[1]); + fh=fopen(idlfile,"r"); + if(!fh){ + fprintf(stderr, "ERROR: could not open idl-file:%s\n",idlfile); + Exit(0); + } + + lineno=0; + linepos=0; + tokenize(); + prune_keyword_parameters("size_is"); + prune_keyword_parameters("length_is"); + rename_tokens("NTSTATUS", "WERROR"); + rename_tokens("unistr_noterm", "unistr"); + rename_tokens("ascstr_noterm", "ascstr"); + rename_tokens("hyper", "uint64"); + FPRINTF(NULL,"\n\nParsing header:\n================\n"); + parseheader(); + + /* some idl files prepend a lot of symbols with <ifname>_ + search through the tokenlist and remove all such + prefixes + */ + sprintf(prefix_str, "%s_", ifname); + preparetrimprefix(prefix_str); + trimprefix(); + + /* this is the main loop, each iteration it tries to identify what + kind of construct is the first entry in the token_list and call + the appropriate handler + */ + while(1) { + /* just skip any [ ] that starts a new construct */ + if( !strcmp(token_list->str, "[") ){ + token_list=parsebrackets(token_list, &bi); + continue; + } + + /* typedef enum { */ + if( !strcmp(token_list->str,"typedef") + &&!strcmp(token_list->next->str,"enum") ){ + parsetypedefenum(); + continue; + } + + /* typedef [ v1_enum ] enum { */ + if( !strcmp(token_list->str,"typedef") + &&!strcmp(token_list->next->str,"[") + &&!strcmp(token_list->next->next->str,"v1_enum") + &&!strcmp(token_list->next->next->next->str,"]") + &&!strcmp(token_list->next->next->next->next->str,"enum") ){ + parsetypedefenum(); + continue; + } + + /* const */ + if( !strcmp(token_list->str,"const") ){ + parseconst(); + continue; + } + + /* typedef struct { */ + if( !strcmp(token_list->str,"typedef") ){ + token_item_t *tmpti; + + tmpti=token_list->next; + if( !strcmp(tmpti->str, "[") ){ + tmpti=parsebrackets(tmpti, &bi); + /* do some sanity checks here of bi->flags */ + } + if( !strcmp(tmpti->str, "struct") ){ + parsetypedefstruct(0); + parsetypedefstruct(1); + continue; + } + } + + /* typedef union { */ + if( !strcmp(token_list->str,"typedef") + &&!strcmp(token_list->next->str,"union") ){ + parsetypedefunion(0); + parsetypedefunion(1); + continue; + } + + /* typedef bitmap { */ + if( !strcmp(token_list->str,"typedef") ){ + token_item_t *tmpti; + + tmpti=token_list->next; + if( !strcmp(tmpti->str, "[") ){ + tmpti=parsebrackets(tmpti, &bi); + /* do some sanity checks here of bi->flags */ + } + if( !strcmp(tmpti->str, "bitmap") ){ + parsetypedefbitmap(0); + parsetypedefbitmap(1); + continue; + } + } + + /* functions: WERROR function '(' */ + if( !strcmp(token_list->str,"WERROR") + &&!strcmp(token_list->next->next->str,"(") ){ + parsefunction(0); + parsefunction(1); + parsefunction(2); + continue; + } + + /* declare ... ; */ + if( !strcmp(token_list->str,"declare") ){ + skipdeclare(); + continue; + } + + + break; + }; + + + fclose(eth_code); + fclose(eth_hdr); + fclose(eth_hf); + fclose(eth_hfarr); + fclose(eth_ett); + fclose(eth_ettarr); + fclose(eth_ft); + fclose(eth_handoff); + + /* unless the token_list now only contains a single token : '}' + we have failed to compile the idl file properly + */ + if( strcmp(token_list->str, "}") || token_list->next){ + fprintf(stderr, "ERROR: we did not process all tokens. Compiler is incomplete.\n===========================================\n"); + printtokenlist(10); + exit(10); + } + + /* merge code and template into dissector */ + sprintf(line, "packet-dcerpc-%s.c", ifname); + fh=fopen(line, "w"); + tfh=fopen("template.c", "r"); + if(!tfh){ + fprintf(stderr, "ERROR: could not find template.c\n"); + exit(10); + } + while(!feof(tfh)){ + line[0]=0; + fgets(line, 1024, tfh); + if(!strncmp(line, "ETH_CODE", 8)){ + mergefile("ETH_CODE",fh); + } else if(!strncmp(line, "ETH_HDR", 7)){ + mergefile("ETH_HDR",fh); + } else if(!strncmp(line, "ETH_HFARR", 9)){ + mergefile("ETH_HFARR",fh); + } else if(!strncmp(line, "ETH_HF", 6)){ + mergefile("ETH_HF",fh); + } else if(!strncmp(line, "ETH_ETTARR", 10)){ + mergefile("ETH_ETTARR",fh); + } else if(!strncmp(line, "ETH_ETT", 7)){ + mergefile("ETH_ETT",fh); + } else if(!strncmp(line, "ETH_FT", 6)){ + mergefile("ETH_FT",fh); + } else if(!strncmp(line, "ETH_HANDOFF", 11)){ + mergefile("ETH_HANDOFF",fh); + } else { + fputs(line, fh); + } + } + fclose(fh); + fclose(tfh); + + + sprintf(line, "packet-dcerpc-%s.h", ifname); + fh=fopen(line, "w"); + tfh=fopen("template.h", "r"); + if(!tfh){ + fprintf(stderr, "ERROR: could not find template.h\n"); + exit(10); + } + while(!feof(tfh)){ + line[0]=0; + fgets(line, 1024, tfh); + if(!strncmp(line, "ETH_CODE", 8)){ + mergefile("ETH_CODE",fh); + } else if(!strncmp(line, "ETH_HDR", 7)){ + mergefile("ETH_HDR",fh); + } else if(!strncmp(line, "ETH_HFARR", 9)){ + mergefile("ETH_HFARR",fh); + } else if(!strncmp(line, "ETH_HF", 6)){ + mergefile("ETH_HF",fh); + } else if(!strncmp(line, "ETH_ETTARR", 10)){ + mergefile("ETH_ETTARR",fh); + } else if(!strncmp(line, "ETH_ETT", 7)){ + mergefile("ETH_ETT",fh); + } else if(!strncmp(line, "ETH_FT", 6)){ + mergefile("ETH_FT",fh); + } else if(!strncmp(line, "ETH_HANDOFF", 11)){ + mergefile("ETH_HANDOFF",fh); + } else { + fputs(line, fh); + } + } + + printf("%s was successfully compiled\n", ifname); + + fclose(fh); + fclose(tfh); + + return 0; +} + |