From 8429e4b0f7a09e1d6d01233b85696bdaeec8b577 Mon Sep 17 00:00:00 2001 From: Richard Sharpe 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 +#include +#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 \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 \n" +"\n" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +"#include \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; + +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) = 3; + unsigned int OneOpaqueTypedefReturnInt(Some_t) = 4; + + unsigned int TwoTypesReturnInt(struct multi_def_struct, int) = 5; + } = 1; +} = 123456; -- 2.4.3