Wireshark-dev: Re: [Wireshark-dev] Has anyone created an XDR to Dissector tool?
From: Richard Sharpe <realrichardsharpe@xxxxxxxxx>
Date: Thu, 8 Sep 2016 07:40:06 -0700
On Wed, Aug 31, 2016 at 3:19 PM, Richard Sharpe <realrichardsharpe@xxxxxxxxx> wrote: > Hi folks, > > I find myself dealing with XDR a lot these days and rolling dissectors > by hand is a pain. > > Has anyone written a tool that can go from XDR to a dissector? > > If not, I can give it a try. More WIP: Closer now. About 80% done. Will probably have to extract this from glibc and add it to one of the stand-alone versions of rpcgen. Will also have to make sure that doing so handles the latest versions of the XDR RFC, although those are from long ago. Probably haven't changed in the last year or ten. -- Regards, Richard Sharpe (何以解憂?唯有杜康。--曹操)
From 8429e4b0f7a09e1d6d01233b85696bdaeec8b577 Mon Sep 17 00:00:00 2001 From: Richard Sharpe <rsharpe@xxxxxxxxx> Date: Sat, 3 Sep 2016 18:31:10 -0700 Subject: [PATCH] The WIP so far ... --- sunrpc/Makefile | 2 +- sunrpc/rpc_main.c | 65 +++- sunrpc/rpc_wireshark.c | 669 +++++++++++++++++++++++++++++++++++++++++ sunrpc/rpc_wireshark.h | 15 + sunrpc/rpcsvc/wireshark_test.x | 79 +++++ 5 files changed, 822 insertions(+), 8 deletions(-) create mode 100644 sunrpc/rpc_wireshark.c create mode 100644 sunrpc/rpc_wireshark.h create mode 100644 sunrpc/rpcsvc/wireshark_test.x diff --git a/sunrpc/Makefile b/sunrpc/Makefile index 789ef42..ed5e9f0 100644 --- a/sunrpc/Makefile +++ b/sunrpc/Makefile @@ -92,7 +92,7 @@ endif install-bin := rpcgen rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \ rpc_scan.o rpc_util.o rpc_svcout.o rpc_clntout.o \ - rpc_tblout.o rpc_sample.o + rpc_tblout.o rpc_sample.o rpc_wireshark.o extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) others += rpcgen diff --git a/sunrpc/rpc_main.c b/sunrpc/rpc_main.c index 0a51e2c..463125a 100644 --- a/sunrpc/rpc_main.c +++ b/sunrpc/rpc_main.c @@ -49,6 +49,7 @@ #include "rpc_parse.h" #include "rpc_util.h" #include "rpc_scan.h" +#include "rpc_wireshark.h" #include "proto.h" #include "../version.h" @@ -68,6 +69,7 @@ struct commandline int tflag; /* dispatch Table file */ int Ssflag; /* produce server sample code */ int Scflag; /* produce client sample code */ + int Wflag; /* Produce a wireshark dissector */ int makefileflag; /* Generate a template Makefile */ const char *infile; /* input module name */ const char *outfile; /* output module name */ @@ -125,6 +127,8 @@ static void svc_output (const char *infile, const char *define, int extend, const char *outfile); static void clnt_output (const char *infile, const char *define, int extend, const char *outfile); +static void wireshark_output (const char *infile, const char *define, + int extend, const char *outfile); static void mkfile_output (struct commandline *cmd); static int do_registers (int argc, const char *argv[]); static void addarg (const char *cp); @@ -183,7 +187,7 @@ main (int argc, const char *argv[]) usage (stderr, 1); if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag || - cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) + cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag || cmd.Wflag) { checkfiles (cmd.infile, cmd.outfile); } @@ -205,6 +209,8 @@ main (int argc, const char *argv[]) svc_output (cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile); else if (cmd.Scflag) clnt_output (cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile); + else if (cmd.Wflag) + wireshark_output (cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); else if (cmd.makefileflag) mkfile_output (&cmd); else @@ -364,7 +370,7 @@ open_input (const char *infile, const char *define) putarg (1, CPPFLAGS); addarg (define); if (infile) - addarg (infile); + addarg (infilename); addarg ((char *) NULL); close (1); dup2 (pd[1], 1); @@ -909,6 +915,47 @@ clnt_output (const char *infile, const char *define, int extend, close_output (outfilename); } +/* + * generate wireshark dissector + * + * Pass over the list of definitions as many times as needed to + * generate the following: + * + * 1. The Preamble containing includes, the program define and the + * forward declarations needed. + * 2. The ett values + * 3. The hf values needed. + * 4. The value strings needed. + * 5. The structure dissections. + * 6. The program dissections. + * 7. The epilog containing initialization of the hf and ett values + * and etc. + * + * We can do that because we have all we need in the list. + */ +static void +wireshark_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + definition *def; + const char *outfilename; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + checkfiles (infile, outfilename); + + while ((def = get_definition ()) != NULL) + { + + } + + write_wireshark(); + + close_input (); + close_output (outfilename); +} + static const char space[] = " "; static char * @@ -1131,9 +1178,9 @@ checkfiles (const char *infile, const char *outfile) fprintf (stderr, /* TRANS: the file will not be removed; this is an TRANS: informative message. */ - _("file `%s' already exists and may be overwritten\n"), - outfile); - crash (); + _("file `%s' already exists and may be overwritten: %s\n"), + outfile, strerror(errno)); + /*crash ();*/ } } } @@ -1200,6 +1247,7 @@ parseargs (int argc, const char *argv[], struct commandline *cmd) case 'l': case 'm': case 't': + case 'W': if (flag[c]) return 0; flag[c] = 1; @@ -1339,6 +1387,7 @@ parseargs (int argc, const char *argv[], struct commandline *cmd) cmd->tflag = flag['t']; cmd->Ssflag = flag['S']; cmd->Scflag = flag['C']; + cmd->Wflag = flag['W']; cmd->makefileflag = flag['M']; #ifndef _RPC_THREAD_SAFE_ @@ -1377,7 +1426,8 @@ parseargs (int argc, const char *argv[], struct commandline *cmd) /* check no conflicts with file generation flags */ nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag + - cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag; + cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag + + cmd->Wflag; if (nflags == 0) { @@ -1405,7 +1455,7 @@ static void usage (FILE *stream, int status) { fprintf (stream, _("usage: %s infile\n"), cmdname); - fprintf (stream, _("\t%s [-abkCLNTM][-Dname[=value]] [-i size] \ + fprintf (stream, _("\t%s [-abkCLNTMW][-Dname[=value]] [-i size] \ [-I [-K seconds]] [-Y path] infile\n"), cmdname); fprintf (stream, _("\t%s [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm] \ [-o outfile] [infile]\n"), cmdname); @@ -1441,6 +1491,7 @@ options_usage (FILE *stream, int status) f_print (stream, _("-Sm \t\tgenerate makefile template \n")); f_print (stream, _("-t\t\tgenerate RPC dispatch table\n")); f_print (stream, _("-T\t\tgenerate code to support RPC dispatch tables\n")); + f_print (stream, _("-T\t\tgenerate code for a Wireshark dissector\n")); f_print (stream, _("-Y path\t\tdirectory name to find C preprocessor (cpp)\n")); f_print (stream, _("-5\t\tSysVr4 compatibility mode\n")); f_print (stream, _("--help\t\tgive this help list\n")); diff --git a/sunrpc/rpc_wireshark.c b/sunrpc/rpc_wireshark.c new file mode 100644 index 0000000..cfbbaa7 --- /dev/null +++ b/sunrpc/rpc_wireshark.c @@ -0,0 +1,669 @@ +/* @(#)rpc_wireshark.c 1.0 16/09/01 + * + * Copyright to be determined ... + * + * rpc_wireshark.c, The actual code for generating the dissector in rpcgen. + */ + +#include <stdio.h> +#include <string.h> +#include "rpc/types.h" +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" +#include "rpc_wireshark.h" + +static void write_wireshark_boilerplate (definition *def); +static void write_wireshark_forward_defs (definition *prog); +static void write_wireshark_ett_fields (definition *prog); +static void write_wireshark_hf_fields (definition *prog); +static void write_wireshark_enum_decls (definition *prog); +static void write_wireshark_structs_unions_dissect (definition *prog); +static void write_wireshark_struct_dissect (definition *prog, definition *st); +static void write_wireshark_union_dissect (definition *prog, definition *st); +static void write_wireshark_req_rsp_dissect (definition *prog); +static void write_wireshark_register_arrays (definition *prog); +static void write_wireshark_trailer (definition *prog); + +static typedef_list *typedefs = NULL; +static typedef_list **typedefs_end = &typedefs; + +void write_wireshark(void) +{ + list *l; + definition *def, *prog = NULL; + + /* Handle the prelude ... */ + for (l = defined; l != NULL; l = l->next) + { + typedef_list *list_elt; + + def = (definition *) l->val; + switch (def->def_kind) + { + case DEF_PROGRAM: + + prog = def; + write_wireshark_boilerplate (def); + break; + + case DEF_TYPEDEF: + list_elt = calloc(1, sizeof(typedef_list)); + *typedefs_end = list_elt; + list_elt->def = def; + typedefs_end = &list_elt->next; + break; + + default: + break; + } + } + + /* + * Now, do all the forward declarations we need. + * We need one for each data structure and + * one for each function in version defs. + */ + write_wireshark_forward_defs (prog); + + write_wireshark_ett_fields (prog); + + write_wireshark_hf_fields (prog); + + write_wireshark_enum_decls (prog); + + write_wireshark_structs_unions_dissect (prog); + + write_wireshark_req_rsp_dissect (prog); + + write_wireshark_register_arrays (prog); + + write_wireshark_trailer (prog); +} + +static void write_wireshark_boilerplate(definition *def) +{ + fprintf(fout, +"/* packet-%s.c\n" +" * Routines for %s dissection\n" +" * Copyright %s, %s\n" +" *\n" +" * Wireshark - Network traffic analyzer\n" +" * By Gerald Combs <gerald@xxxxxxxxxxxxx>\n" +" * Copyright 1998 Gerald Combs\n" +" *\n" +" * Portions copied shamelessly from packet-nfs.c\n" +" *\n" +" * This program is free software; you can redistribute it and/or\n" +" * modify it under the terms of the GNU General Public License\n" +" * as published by the Free Software Foundation; either version 2\n" +" * of the License, or (at your option) any later version.\n" +" *\n" +" * This program is distributed in the hope that it will be useful,\n" +" * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +" * GNU General Public License for more details.\n" +" *\n" +" * You should have received a copy of the GNU General Public License\n" +" * along with this program; if not, write to the Free Software\n" +" * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" +" *\n" +" * GENERATED BY RPCGEN. DO NOT DO SERIOUS EDITS.\n" +" * NOTE, USES WIRESHARK 2.x APIs. MAY NEED CHANGES.\n" +" */\n" +"\n" +"#include \"config.h\"\n" +"\n" +"#include <stdio.h>\n" +"\n" +"#include <epan/packet.h>\n" +"#include <epan/prefs.h>\n" +"#include <epan/exceptions.h>\n" +"#include <epan/expert.h>\n" +"#include <epan/to_str.h>\n" +"#include <epan/decode_as.h>\n" +"#include <wsutil/crc16.h>\n" +"#include <wsutil/crc32.h>\n" +"#include \"packet-rpc.h\"\n" +"\n" +"#define %s %s\n\n" +"void proto_register_%s(void);\n" +"void proto_reg_handoff_%s(void);\n\n", + def->def_name, def->def_name, "@COPYRIGHTDATE@", "@COPYRIGHTOWNER@", + def->def_name, def->def.pr.prog_num, + def->def_name, def->def_name); + + /* TODO: Fix the year and pickyp the copyright somehow. */ +} + +static void write_wireshark_forward_defs(definition *prog) +{ + list *l; + definition *def; + + /* + * If there is no program definition, the structure names + * do not need qualification as they have to be unique anyway. + */ + + for (l = defined; l != NULL; l = l->next) + { + version_list *v = NULL; + proc_list *p = NULL; + + def = (definition *) l->val; + switch (def->def_kind) { + case DEF_STRUCT: + case DEF_UNION: + fprintf(fout, "%sdissect_%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);\n", + (prog ? "static " : ""), def->def_name); + break; + + case DEF_PROGRAM: + for (v = def->def.pr.versions; v != NULL; v = v->next) + { + for (p = v->procs; p != NULL; p = p->next) + { + const char * tplt = "static dissect_%s_%s(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);\n"; + fprintf(fout, tplt, p->proc_name, "call"); + fprintf(fout, tplt, p->proc_name, "reply"); + } + } + break; + + default: + break; + } + } + + fprintf(fout, "\n"); +} + +static void write_wireshark_ett_fields (definition *prog) +{ + list *l; + definition *def; + + if (prog) + fprintf(fout, "static gint ett_%s = -1;\n", prog->def_name); + + for (l = defined; l != NULL; l = l->next) + { + version_list *v = NULL; + proc_list *p = NULL; + + def = (definition *) l->val; + switch (def->def_kind) { + case DEF_STRUCT: + case DEF_UNION: + fprintf(fout, "static gint ett_%s = -1;\n", def->def_name); + break; + + /* Not clear we need these */ + case DEF_PROGRAM: + for (v = def->def.pr.versions; v != NULL; v = v->next) + { + for (p = v->procs; p != NULL; p = p->next) + { + fprintf(fout, "static gint ett_%s = -1;\n", p->proc_name); + } + } + break; + + default: + break; + } + } + + fprintf(fout, "\n"); +} + +static void write_wireshark_hf_fields (definition *prog) +{ + list *l; + definition *def; + + if (prog) + fprintf(fout, "static gint hf_%s = -1;\n", prog->def_name); + + for (l = defined; l != NULL; l = l->next) + { + decl_list *d = NULL; + version_list *v = NULL; + proc_list *p = NULL; + + def = (definition *) l->val; + switch (def->def_kind) + { + case DEF_STRUCT: + for (d = def->def.st.decls; d != NULL; d = d->next) + { + /* + * field names must be qualified by the parent because + * because there could be two fields with the same + * name in different structures. + */ + fprintf(fout, "static int hf_%s_%s = -1;\n", + def->def_name, d->decl.name); + } + break; + + case DEF_PROGRAM: + for (v = def->def.pr.versions; v != NULL; v = v->next) + { + // hf fields for the versions + fprintf(fout, "static int hf_%s_procedure_v%s = -1;\n", + prog->def_name, v->vers_num); + + for (p = v->procs; p != NULL; p = p->next) + { + fprintf(fout, "//PROC: N: %s, arg#: %d, an: %s\n", + p->proc_name, p->arg_num, p->args.argname); + } + } + break; + + default: + break; + } + } + + fprintf(fout, "\n"); +} + +static void write_wireshark_enum_decls (definition *prog) +{ + + list *l; + definition *def; + + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + + if (def->def_kind == DEF_ENUM) + { + enumval_list *e = NULL; + + fprintf(fout, "static const value_string %s_vals[] = {\n", + def->def_name); + + for (e = def->def.en.vals; e != NULL; e = e->next) + { + fprintf(fout, "\t{ %s, \"%s\" },\n", e->assignment, e->name); + } + + fprintf(fout, "\t{ 0, NULL }\n};\n\n"); + + } + } +} + +static void write_wireshark_structs_unions_dissect (definition *prog) +{ + list *l; + definition *def; + + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + + switch (def->def_kind) + { + case DEF_STRUCT: + write_wireshark_struct_dissect (prog, def); + break; + + case DEF_UNION: + write_wireshark_union_dissect (prog, def); + break; + + default: + break; + } + } +} + +/* + * Map the incoming types to base types if we have them ... + * + * We deal with opaque and string separately. Min size is 4 bytes, as per + * the spec. Will have to add float types. + * + * The first array must be kept sorted! They have to be kept in sync. + */ +static const char *known_types[] = { + "bool", "char", "long", "quad_t", "short", "u_char", "u_int", + "u_long", "u_quad_t", "u_short" +}; +#if 0 +static const char *rpc_types[] = { "FT_INT32", "FT_BYTES", "FT_INT64", + "FT_INT16", "FT_UINT8", "FT_UINT32", "FT_UINT32", "FT_UINT64", + "FT_UINT16" +}; +#endif +static const int type_sizes[] = { 4, 4, 4, 8, 4, 4, 4, 4, 8, 4 }; + +static const char *var_types[] = { + "guint32", "guint32", "guint32", "guint64", "guint32", "guint32", + "guint32", "guint32", "guint64", "guint32" +}; + +static const char *access_names[] = { + "ntohl", "ntohl", "ntohl", "ntoh64", "ntohl", "ntohl", + "htohl", "ntohl", "ntoh64", "ntohl" +}; + +static const char *proto_item_names[] = { + "int", "int", "int", "int64", "int", "uint", "uint", + "uint", "uint64", "uint" +}; + +/* + * Return 1 if the type is a base type, and then its size. We must + * resolve any typedefs along the way. So, search the list to see + * if the type resolves there, and keep resolving them if needed. + */ +definition *resolve_type(const char *type) +{ + definition *resolved = NULL; + typedef_list *l = typedefs; + + /* Need to keep trying until cannot resolve again */ + while (l) + { + if (strcmp(type, l->def->def_name) == 0) + { + resolved = l->def; + break; + } + l = l->next; + } + return resolved; +} + +static const char *is_base_type(const char *type, int *len, int *index) +{ + definition *def = resolve_type(type); + int array_size = sizeof(known_types)/sizeof(char *), i; + const char *ret = NULL; + + *len = 0; *index = -1; + if (def) + { + type = def->def.ty.old_type; + } + + for (i = 0; i < array_size; i++) + { + if (strcmp(type, known_types[i]) == 0) + { + *len = type_sizes[i]; + *index = i; + ret = type; + break; + } + } + + return ret; +} + +static void write_wireshark_decl(declaration *decl, const char *parent_name, + int *iter_needed) +{ + switch (decl->rel) + { + int len = 0, index = 0; + + case REL_VECTOR: + /* + * Generate each of the items. If they are simple types, + * then just insert them, but if not, then will have to dissect + * them. + * + * The basic unit is 4 bytes, unless a string or opaque, but + * even then, they still round up to 4 bytes. + * + * A vector of opaque bytes is different, however, as is + * a vector of bytes. Strings can only be arrays. No need + * to deal with them here. + */ + fprintf(fout, "//V, P=%s T=%s N=%s L=%s\n", decl->prefix, decl->type, + decl->name, decl->array_max); + if (strcmp(decl->type, "opaque") == 0) + { + // If it is opaque, just pull off that many bytes. + fprintf(fout, "\t\tproto_tree_add_item(subtree, hf_%s_%s, tvb, " + "offset, %s, ENC_BIG_ENDIAN);\n", + parent_name, decl->name, decl->array_max); + fprintf(fout, "\t\toffset += %s;\n", decl->array_max); + fprintf(fout, "\t\toffset += 4 - (%s %% 4);\n", + decl->array_max); // Roundup + return; + } + + // Add a subtree for the Array ... + if (*iter_needed) + { + fprintf(fout, "\n\t\tint i = 0;\n"); /* Assumes C99? */ + *iter_needed = 0; + } + fprintf(fout, "\t\tfor (i = 0; i < %s; i++) {\n", + decl->array_max); + if (is_base_type(decl->type, &len, &index)) + { + fprintf(fout, "\t\t\t%s val;\n\n", var_types[index]); + fprintf(fout, "\t\t\tval = tvb_get_%s(tvb, offset);\n", + access_names[index]); + fprintf(fout, "\t\t\tproto_tree_add_%s_format(subtree, hf_%s_%s, " + "tvb, offset, %d, val, \"%s[%%d]\", i);\n", + proto_item_names[index], parent_name, decl->name, + len, decl->name); + fprintf(fout, "\t\t\toffset += %d\n", type_sizes[index]); + } + else + { + fprintf(fout, "\t\t\tchar label[%lu];\n\n", + strlen(decl->name) + 3 + strlen(decl->array_max)); + fprintf(fout, "\t\t\tsprintf(label, \"%s[%%d]\",i);\n", + decl->name); + fprintf(fout, "\t\t\toffset += dissect_%s(tvb, subtree, offset, " + "label);\n", decl->type); + } + fprintf(fout, "\t\t}\n\n"); + break; + + case REL_ARRAY: + /* if it's a base type (including via typedef, then generate + * direct code, otherwise, call a separate dissect function + * + * This is for variable-length arrays, but strings are different. + */ + fprintf(fout, "//A, P=%s T=%s N=%s L=%s\n", decl->prefix, decl->type, + decl->name, decl->array_max); + // Insert code to get the length + fprintf(fout, "\t\tguint len = tvb_get_ntohl(tvb, offset);\n"); + fprintf(fout, "\t\toffset += 4;\n\n"); + // If a bunch of opaque bytes ... just handle them. + if (strcmp(decl->type, "opaque") == 0) + { + fprintf(fout, "\t\tproto_tree_add_item(subtree, hf_%s_%s, tvb, " + "offset, len, ENC_BIG_ENDIAN);\n", + parent_name, decl->name); + fprintf(fout, "\t\toffset += len;\n"); + fprintf(fout, "\t\toffset += 4 - (len %% 4);\n"); // Roundup + return; + } + if (strcmp(decl->type, "string") == 0) // Merge with above? + { + fprintf(fout, "\t\tproto_tree_add_item(subtree, hf_%s_%s, tvb, " + "offset, len, ENC_BIG_ENDIAN);\n", + parent_name, decl->name); + fprintf(fout, "\t\toffset += len;\n"); + fprintf(fout, "\t\toffset += 4 - (len %% 4);\n"); // Roundup + return; + } + if (*iter_needed) + { + fprintf(fout, "\t\tint i = 0;\n"); + *iter_needed = 0; + } + fprintf(fout, "\t\tfor (i = 0; i < len; i++) {\n"); + if (is_base_type(decl->type, &len, &index)) + { + fprintf(fout, "\t\t\t%s val;\n\n", var_types[index]); + fprintf(fout, "\t\t\tval = tvb_get_%s(tvb, offset);\n", + access_names[index]); + fprintf(fout, "\t\t\tproto_tree_add_%s_format(subtree, hf_%s_%s, " + "tvb, offset, %d, val, \"%s[%%d]\", i);\n", + proto_item_names[index], parent_name, decl->name, + len, decl->name); + fprintf(fout, "\t\t\toffset += %d\n", type_sizes[index]); + } + else + { + fprintf(fout, "\t\t\tchar label[%lu];\n\n", + strlen(decl->name) + 3 + strlen(decl->array_max)); + fprintf(fout, "\t\t\tsprintf(label, \"%s[%%d]\",i);\n", + decl->name); + fprintf(fout, "\t\t\toffset += dissect_%s(tvb, subtree, offset, " + "label);\n", decl->type); + } + fprintf(fout, "\t\t}\n\n"); + break; + + case REL_ALIAS: + // If it is a direct base type, or resolves to a direct base type + // we can handle it here. However, if it resolves to a vector or + // an array, we have to send it back through. + fprintf(fout, "//AL: P=%s, T=%s, N=%s\n", decl->prefix, decl->type, + decl->name); + if (is_base_type(decl->type, &len, &index)) + { + fprintf(fout, "\t\tproto_tree_add_item(subtree, hf_%s_%s, tvb, " + "offset, %d, ENC_BIG_ENDIAN);\n", + parent_name, decl->name, len); + fprintf(fout, "\t\toffset += %d;\n", len); + } + else + { + definition *def; + // It might be a typedef to an array, or something defined + // in another XDR file ... generate the correct stuff. + // Here, it cannot be a vector or array. + def = resolve_type(decl->type); + if (def) + { + struct declaration new_decl; + + new_decl.name = decl->name; + new_decl.prefix = def->def.ty.old_prefix; + new_decl.type = def->def.ty.old_type; + new_decl.rel = def->def.ty.rel; + new_decl.array_max = def->def.ty.array_max; + write_wireshark_decl(&new_decl, parent_name, iter_needed); + } + else + { + fprintf(fout, "\t\toffset += dissect_%s(tvb, subtree, " + "offset);", decl->name); + } + } + break; + + default: + break; + } +} + +static void write_wireshark_struct_dissect(definition *prog, definition *st) +{ + struct decl_list *d = NULL; + int iter_needed = 1; // Used in write_wireshark_decl + + /* + * Make a pass for those fields that require two levels of dissecton. + */ + + fprintf(fout, "%sint\ndissect_%s(tvbuff_t *tvb, proto_tree *tree, " + "int offset, const char *label)\n", + (prog ? "static " : ""), st->def_name); + fprintf(fout, "{\n"); + fprintf(fout, "\tif (tree) {\n"); + fprintf(fout, "\t\tproto_tree subtree = NULL;\n" + "\t\tproto_item it = NULL;\n" + "\t\tint old_offset = offset;\n\n"); + /* Insert a subtree named by this structure name */ + fprintf(fout, "\t\tsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, " + "ett_%s, &it, label);\n", + st->def_name); + for (d = st->def.st.decls; d != NULL; d = d->next) + { + write_wireshark_decl(&d->decl, st->def_name, &iter_needed); + } + /* Insert code to fix up the length of the byte stream covered by this */ + fprintf(fout, "\n"); + fprintf(fout, "\t\tproto_item_set_len(it, offset - old_offset);\n"); + fprintf(fout, "\t}\n\n\treturn offset;\n}\n\n"); +} + +static void write_wireshark_union_dissect(definition *prog, definition *un) +{ + +} + +static void write_wireshark_req_rsp_dissect (definition *prog) +{ + +} + +static void write_wireshark_register_arrays (definition *prog) +{ + +} + +static void write_wireshark_version (definition *prog, version_list *vers) +{ + struct proc_list *p; + + fprintf(fout, "static const vsff %s_v%s_proc[] = {\n", + prog->def_name, vers->vers_num); + for (p = vers->procs; p != NULL; p = p->next) + { + fprintf(fout, "\t{ %s, \"%s\", %s_call, %s_reply },\n", + p->proc_num, p->proc_name, p->proc_name, p->proc_name); + } + fprintf(fout, "};\n\n"); +} + +static void write_wireshark_trailer (definition *prog) +{ + if (prog) + { + struct version_list *v; + // Generate per-version proc info arrays + for (v = prog->def.pr.versions; v != NULL; v = v->next) + { + write_wireshark_version(prog, v); + } + + // Generate version info array + fprintf(fout, "static const rpc_prog_vers_info %s_vers_info[] = {\n", + prog->def_name); + for (v = prog->def.pr.versions; v != NULL; v = v->next) + { + fprintf(fout, "\t{ %s, %s_v%s_proc, &hf_%s_procedure_v%s },\n", + v->vers_num, prog->def_name, v->vers_num, + prog->def_name, v->vers_num); + } + fprintf(fout, "};\n\n"); + + // Now, the registration + fprintf(fout, "void\nproto_reg_handoff_%s(void)\n", prog->def_name); + fprintf(fout, "{\n\trpc_init_prog(proto_%s, %s, ett_%s," + "\t G_N_ELEMENTS(%s_vers_info), %s_vers_info);\n", + prog->def_name, prog->def.pr.prog_num, prog->def_name, + prog->def_name, prog->def_name); + fprintf(fout, "}"); + } +} diff --git a/sunrpc/rpc_wireshark.h b/sunrpc/rpc_wireshark.h new file mode 100644 index 0000000..7a6abea --- /dev/null +++ b/sunrpc/rpc_wireshark.h @@ -0,0 +1,15 @@ +/* @(#)rpc_wireshark.h 1.0 16/09/01 + * + * Copyright to be determined ... + * + * rpc_wireshark.h, Definitions for the generation of a wireshark + * dissector in rpcgen + */ + +struct typedef_list { + struct definition *def; + struct typedef_list *next; +}; +typedef struct typedef_list typedef_list; + +void write_wireshark (void); diff --git a/sunrpc/rpcsvc/wireshark_test.x b/sunrpc/rpcsvc/wireshark_test.x new file mode 100644 index 0000000..966260c --- /dev/null +++ b/sunrpc/rpcsvc/wireshark_test.x @@ -0,0 +1,79 @@ +/* + * A test of the wireshark dissector. + */ + +const STRING_LEN = 32; + +enum enum_1 { + ENUM_OK = 0, + ENUM_NOT = 1, + ENUM_OTHER = 2 +}; + +struct mult_def_struct { + hyper big; + opaque op[12]; + char str[13]; + unsigned int smallu; + hyper big2; + hyper big3[10]; + string sss<12>; + string var<>; +}; + +typedef opaque fixed_t[12]; + +typedef opaque some_t<STRING_LEN>; + +struct fixed_and_variable { + fixed_t fixed; + some_t variable; +}; + +struct funny { + multi_def_struct parms[10]; + multi_def_struct vars<>; +}; + +struct direct_etc { + opaque fixed[13]; + opaque variable<23>; +}; + +typedef unsigned int uint32_t; +typedef uint32_t my_type_t; + +typedef three_parm_struct list_of_parm<>; + +struct both { + uint32_t xxx[32]; + uint32_t yyy<16>; +}; + +struct special { + char aaa[12]; + unsigned char bbb<12>; +}; + +struct another { + uint32 aaa[12]; +}; + +/* The program with two versions */ +program WIRESHARK_TEST { + /* + * V1 had some simple functions + */ + version WIRESHARK_TEST_V1 { + void NULL(void) = 0; + + unsigned int OneParmSimpleReturn(unsigned int) = 1; + + int OneStructSimpleReturn(struct three_parm_struct parm1) = 2; + + enum enum_1 OneStringParameReturnEnum(string str<STRING_LEN>) = 3; + unsigned int OneOpaqueTypedefReturnInt(Some_t) = 4; + + unsigned int TwoTypesReturnInt(struct multi_def_struct, int) = 5; + } = 1; +} = 123456; -- 2.4.3
- Prev by Date: [Wireshark-dev] Wireshark 2.2.0 is now available
- Next by Date: [Wireshark-dev] Wireshark 2.0.6 is now available
- Previous by thread: Re: [Wireshark-dev] Has anyone created an XDR to Dissector tool?
- Next by thread: [Wireshark-dev] Compiling on Centos7
- Index(es):