ndrdump: print public structures
authorGary Lockyer <gary@catalyst.net.nz>
Tue, 4 Jun 2019 20:44:09 +0000 (08:44 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 6 Jun 2019 03:30:18 +0000 (03:30 +0000)
Add a struct option to ndrdump that will allow it to print public
structures.
  i.e. binn/ndrdump dns dns_name_packet struct data.file

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
librpc/tools/ndrdump.1.xml
librpc/tools/ndrdump.c
selftest/knownfail.d/ndrdump [deleted file]

index e148eee0f034f0827da3c066e9f3911cacbd2665..fa6d763d18f74f5279c092207c974f3d9c41a581 100644 (file)
@@ -21,8 +21,8 @@
                <command>ndrdump</command>
                <arg choice="opt">-c context</arg>
                <arg choice="req">pipe</arg>
-               <arg choice="req">function</arg>
-               <arg choice="req">in|out</arg>
+               <arg choice="req">format</arg>
+               <arg choice="req">in|out|struct</arg>
                <arg choice="req">filename</arg>
        </cmdsynopsis>
        <cmdsynopsis>
        <title>DESCRIPTION</title>
 
        <para>ndrdump tries to parse the specified <replaceable>filename</replaceable>
-               using Samba's parser for the specified pipe and function. The 
+               using Samba's parser for the specified pipe and format. The
                third argument should be 
-               either <emphasis>in</emphasis> or <emphasis>out</emphasis>, depending 
-               on whether the data should be parsed as a request or a reply.</para>
+               either <emphasis>in</emphasis>, <emphasis>out</emphasis>
+               or <emphasis>struct</emphasis>depending
+               on whether the data should be parsed as a request, reply or a
+               public structure.</para>
 
        <para>Running ndrdump without arguments will list the pipes for which 
                parsers are available.</para>
 
-       <para>Running ndrdump with one argument will list the functions that 
+       <para>Running ndrdump with one argument will list the functions and
+               public structures that
                Samba can parse for the specified pipe.</para>
 
        <para>The primary function of ndrdump is debugging Samba's internal 
index ef7f9c6613909816e12d3938d26d6c488c3bf60c..bd4f277607b26beb72a69d4e8e5cdf8df185ab96 100644 (file)
@@ -48,6 +48,35 @@ static const struct ndr_interface_call *find_function(
        return &p->calls[i];
 }
 
+/*
+ * Find a public structure on the pipe and return it as if it were
+ * a function (as the rest of ndrdump is based around functions)
+ */
+static const struct ndr_interface_call *find_struct(
+       const struct ndr_interface_table *p,
+       const char *struct_name,
+       struct ndr_interface_call *out_buffer)
+{
+       int i;
+       for (i=0;i<p->num_public_structs;i++) {
+               if (strcmp(p->public_structs[i].name, struct_name) == 0) {
+                       break;
+               }
+       }
+       if (i == p->num_public_structs) {
+               printf("Public structure '%s' not found\n", struct_name);
+               exit(1);
+       }
+       *out_buffer = (struct ndr_interface_call) {
+               .name = p->public_structs[i].name,
+               .struct_size = p->public_structs[i].struct_size,
+               .ndr_pull = p->public_structs[i].ndr_pull,
+               .ndr_push = p->public_structs[i].ndr_push,
+               .ndr_print = p->public_structs[i].ndr_print
+       };
+       return out_buffer;
+}
+
 _NORETURN_ static void show_pipes(void)
 {
        const struct ndr_interface_list *l;
@@ -71,6 +100,10 @@ _NORETURN_ static void show_functions(const struct ndr_interface_table *p)
        for (i=0;i<p->num_calls;i++) {
                printf("\t0x%02x (%2d) %s\n", i, i, p->calls[i].name);
        }
+       printf("known public structures on '%s' are:\n", p->name);
+       for (i=0;i<p->num_public_structs;i++) {
+               printf("\t%s\n", p->public_structs[i].name);
+       }
        exit(1);
 }
 
@@ -194,7 +227,21 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
 {
        const struct ndr_interface_table *p = NULL;
        const struct ndr_interface_call *f;
-       const char *pipe_name, *function, *inout, *filename;
+       struct ndr_interface_call f_buffer;
+       const char *pipe_name = NULL;
+       const char *filename = NULL;
+       /*
+        * The format type:
+        *   in:     a request
+        *   out:    a response
+        *   struct: a public structure
+        */
+       const char *type = NULL;
+       /*
+        * Format is either the name of the decoding function or the
+        * name of a public structure
+        */
+       const char *format = NULL;
        uint8_t *data;
        size_t size;
        DATA_BLOB blob;
@@ -244,7 +291,7 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
        pc = poptGetContext("ndrdump", argc, argv, long_options, 0);
        
        poptSetOtherOptionHelp(
-               pc, "<pipe|uuid> <function> <inout> [<filename>]");
+               pc, "<pipe|uuid> <format> <in|out|struct> [<filename>]");
 
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
@@ -302,29 +349,34 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
                exit(1);
        }
 
-       function = poptGetArg(pc);
-       inout = poptGetArg(pc);
+       format = poptGetArg(pc);
+       type = poptGetArg(pc);
        filename = poptGetArg(pc);
 
-       if (!function || !inout) {
+       if (!format || !type) {
                poptPrintUsage(pc, stderr, 0);
                show_functions(p);
                exit(1);
        }
 
-       f = find_function(p, function);
-
-       if (strcmp(inout, "in") == 0 ||
-           strcmp(inout, "request") == 0) {
-               flags |= NDR_IN;
-       } else if (strcmp(inout, "out") == 0 ||
-                  strcmp(inout, "response") == 0) {
-               flags |= NDR_OUT;
+       if (strcmp(type, "struct") == 0) {
+               flags = 0; /* neither NDR_IN nor NDR_OUT */
+               f = find_struct(p, format, &f_buffer);
        } else {
-               printf("Bad inout value '%s'\n", inout);
-               exit(1);
+               f = find_function(p, format);
+               if (strcmp(type, "in") == 0 ||
+                   strcmp(type, "request") == 0) {
+                       flags |= NDR_IN;
+               } else if (strcmp(type, "out") == 0 ||
+                          strcmp(type, "response") == 0) {
+                       flags |= NDR_OUT;
+               } else {
+                       printf("Bad type value '%s'\n", type);
+                       exit(1);
+               }
        }
 
+
        mem_ctx = talloc_init("ndrdump");
 
        st = talloc_zero_size(mem_ctx, f->struct_size);
@@ -442,7 +494,10 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
        TALLOC_FREE(sec_vt);
 
        if (flags & NDR_OUT) {
-               status = ndrdump_pull_and_print_pipes(function, ndr_pull, ndr_print, &f->out_pipes);
+               status = ndrdump_pull_and_print_pipes(format,
+                                                     ndr_pull,
+                                                     ndr_print,
+                                                     &f->out_pipes);
                if (!NT_STATUS_IS_OK(status)) {
                        printf("dump FAILED\n");
                        exit(1);
@@ -472,7 +527,7 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
                ndrdump_data(blob.data, blob.length, dumpdata);
        }
 
-       f->ndr_print(ndr_print, function, flags, st);
+       f->ndr_print(ndr_print, format, flags, st);
 
        if (!NT_STATUS_IS_OK(status)) {
                printf("dump FAILED\n");
@@ -480,7 +535,10 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
        }
 
        if (flags & NDR_IN) {
-               status = ndrdump_pull_and_print_pipes(function, ndr_pull, ndr_print, &f->in_pipes);
+               status = ndrdump_pull_and_print_pipes(format,
+                                                     ndr_pull,
+                                                     ndr_print,
+                                                     &f->in_pipes);
                if (!NT_STATUS_IS_OK(status)) {
                        printf("dump FAILED\n");
                        exit(1);
@@ -554,7 +612,9 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
                ndr_v_print = talloc_zero(mem_ctx, struct ndr_print);
                ndr_v_print->print = ndr_print_debug_helper;
                ndr_v_print->depth = 1;
-               f->ndr_print(ndr_v_print, function, flags, v_st);
+               f->ndr_print(ndr_v_print,
+                            format,
+                            flags, v_st);
 
                if (blob.length != v_blob.length) {
                        printf("WARNING! orig bytes:%llu validated pushed bytes:%llu\n", 
diff --git a/selftest/knownfail.d/ndrdump b/selftest/knownfail.d/ndrdump
deleted file mode 100644 (file)
index 9f7335f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba.tests.blackbox.ndrdump.samba.tests.blackbox.ndrdump.NdrDumpTests.test_ndrdump_with_hex_struct_name\(none\)