A new RPC pipe! The \pipe\echo named pipe is for testing large RPC
authorTim Potter <tpot@samba.org>
Fri, 11 Apr 2003 04:09:14 +0000 (04:09 +0000)
committerTim Potter <tpot@samba.org>
Fri, 11 Apr 2003 04:09:14 +0000 (04:09 +0000)
requests and responses and is only compiled in when --enable-developer
is passed to configure.  It includes server and client side code for
generating and responding to functions on this pipe.  The functions are:

 - AddOne: add one to the uint32 argument and return ig
 - EchoData: echo back a variable sized char array to the caller
 - SourceData: request a variable sized char array
 - SinkData: send a variable sized char array and throw it away

There's a win32 implementation of the client and server in the
junkcode CVS repository in the rpcecho-win32 subdirectory.
(This used to be commit 4ccd34ef836eba05f81dc2da73fd7cfaac201798)

14 files changed:
source3/Makefile.in
source3/configure.in
source3/include/ntdomain.h
source3/include/rpc_echo.h [new file with mode: 0644]
source3/include/smb.h
source3/lib/util.c
source3/rpc_client/cli_echo.c [new file with mode: 0644]
source3/rpc_parse/parse_echo.c [new file with mode: 0644]
source3/rpc_parse/parse_rpc.c
source3/rpc_server/srv_echo.c [new file with mode: 0644]
source3/rpc_server/srv_echo_nt.c [new file with mode: 0644]
source3/rpcclient/cmd_echo.c [new file with mode: 0644]
source3/rpcclient/rpcclient.c
source3/smbd/nttrans.c

index 99e557b7a74dfbad15b34e20100d599a53975cc5..641294790d9abacfdd30c4921c1219feacca6112 100644 (file)
@@ -226,7 +226,7 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
               rpc_client/cli_wkssvc.o rpc_client/cli_dfs.o \
               rpc_client/cli_reg.o rpc_client/cli_pipe.o \
               rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o  \
-              rpc_client/cli_ds.o libsmb/namequery_dc.o
+              rpc_client/cli_ds.o rpc_client/cli_echo.o libsmb/namequery_dc.o
 
 LIBMSRPC_SERVER_OBJ = libsmb/trusts_util.o
 
@@ -253,6 +253,8 @@ RPC_SPOOLSS_OBJ = rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o
 RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o rpc_server/srv_util.o \
                rpc_server/srv_pipe.o rpc_server/srv_lsa_hnd.o
 
+RPC_ECHO_OBJ = rpc_server/srv_echo.o rpc_server/srv_echo_nt.o
+
 RPC_SERVER_OBJ = @RPC_STATIC@ $(RPC_PIPE_OBJ)
 
 # this includes only the low level parse code, not stuff
@@ -265,6 +267,7 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \
                 rpc_parse/parse_samr.o rpc_parse/parse_srv.o \
                 rpc_parse/parse_wks.o rpc_parse/parse_ds.o \
                rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o \
+               rpc_parse/parse_echo.o \
                $(REGOBJS_OBJ)
 
 
@@ -424,7 +427,8 @@ RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \
                 rpcclient/cmd_samr.o rpcclient/cmd_spoolss.o \
                 rpcclient/cmd_netlogon.o rpcclient/cmd_srvsvc.o \
                 rpcclient/cmd_dfs.o rpcclient/cmd_reg.o \
-                rpcclient/display_sec.o rpcclient/cmd_ds.o
+                rpcclient/display_sec.o rpcclient/cmd_ds.o \
+                rpcclient/cmd_echo.o
 
 RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
              $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
@@ -557,7 +561,7 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \
            $(LIB_SMBD_OBJ) $(SAM_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
            $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) \
            $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \
-           $(IDMAP_OBJ)
+           $(IDMAP_OBJ) $(RPC_ECHO_OBJ)
 
 NSS_OBJ_0 = nsswitch/wins.o $(PARAM_OBJ) $(UBIQX_OBJ) $(LIBSMB_OBJ) \
            $(LIB_OBJ) $(NSSWINS_OBJ)
@@ -943,6 +947,11 @@ bin/librpc_netdfs.@SHLIBEXT@: $(RPC_DFS_OBJ)
        @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_DFS_OBJ) -lc \
                @SONAMEFLAG@`basename $@`
 
+bin/librpc_echo.@SHLIBEXT@: $(RPC_ECHO_OBJ)
+       @echo "Linking $@"
+       @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_ECHO_OBJ) -lc \
+               @SONAMEFLAG@`basename $@`
+
 nsswitch/libnss_wins.@SHLIBEXT@: $(NSS_OBJ)
        @echo "Linking $@"
        @$(SHLD) $(LDSHFLAGS) -o $@ $(NSS_OBJ) -lc \
index c2b7ae276543d4a4b1c1173bbf9648e7eb84a5e2..ce53358d09b80d9914b333af1e0bbdc6ab1d36cf 100644 (file)
@@ -247,6 +247,10 @@ dnl Add modules that have to be built by default here
 dnl These have to be built static:
 default_static_modules="pdb_smbpasswd pdb_tdbsam pdb_unix rpc_lsa rpc_samr rpc_reg rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin idmap_winbind"
 
+if test "x$enable_developer" = xyes; then
+   default_static_modules="$default_static_modules rpc_echo"
+fi
+
 dnl These are preferably build shared, and static if dlopen() is not available
 default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_fake_perms vfs_netatalk"
 
@@ -3460,6 +3464,7 @@ SMB_MODULE(rpc_dfs, \$(RPC_DFS_OBJ), "bin/librpc_netdfs.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_srv, \$(RPC_SVC_OBJ), "bin/librpc_srvsvc.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_spoolss, \$(RPC_SPOOLSS_OBJ), "bin/librpc_spoolss.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_samr, \$(RPC_SAMR_OBJ), "bin/librpc_samr.$SHLIBEXT", RPC)
+SMB_MODULE(rpc_echo, \$(RPC_ECHO_OBJ), "bin/librpc_echo.$SHLIBEXT", RPC)
 SMB_SUBSYSTEM(RPC)
 
 SMB_MODULE(charset_weird, modules/developer.o, "bin/developer.$SHLIBEXT", CHARSET)
index 9216640c039a065e3cf5dfe0d04a0c10f39c35aa..b6ab4fd0c50ede3795c95a623edc4499c5d7c24a 100644 (file)
@@ -385,4 +385,6 @@ struct acct_info
 #include "rpc_spoolss.h"
 #include "rpc_dfs.h"
 #include "rpc_ds.h"
+#include "rpc_echo.h"
+
 #endif /* _NT_DOMAIN_H */
diff --git a/source3/include/rpc_echo.h b/source3/include/rpc_echo.h
new file mode 100644 (file)
index 0000000..8fa389c
--- /dev/null
@@ -0,0 +1,74 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Samba rpcecho definitions.
+
+   Copyright (C) Tim Potter 2003
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful, 
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _RPC_ECHO_H
+#define _RPC_ECHO_H
+
+#define ECHO_ADD_ONE          0x00
+#define ECHO_DATA             0x01
+#define ECHO_SINK_DATA        0x02
+#define ECHO_SOURCE_DATA      0x03
+
+typedef struct echo_q_add_one
+{
+       uint32 request;
+} ECHO_Q_ADD_ONE;
+
+typedef struct echo_r_add_one
+{
+       uint32 response;
+} ECHO_R_ADD_ONE;
+
+typedef struct echo_q_echo_data
+{
+       uint32 size;
+       char *data;
+} ECHO_Q_ECHO_DATA;
+
+typedef struct echo_r_echo_data
+{
+       uint32 size;
+       char *data;
+} ECHO_R_ECHO_DATA;
+
+typedef struct echo_q_source_data
+{
+       uint32 size;
+} ECHO_Q_SOURCE_DATA;
+
+typedef struct echo_r_source_data
+{
+       uint32 size;
+       char *data;
+} ECHO_R_SOURCE_DATA;
+
+typedef struct echo_q_sink_data
+{
+       uint32 size;
+       char *data;
+} ECHO_Q_SINK_DATA;
+
+typedef struct echo_r_sink_data
+{
+} ECHO_R_SINK_DATA;
+
+#endif  
index 78690cd524475c7e0923dc5321c5b4394fde3717..02b5b9435eeba97897650353723bdbac861dc5a4 100644 (file)
@@ -187,6 +187,7 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN];
 #define PIPE_LSARPC   "\\PIPE\\lsarpc"
 #define PIPE_SPOOLSS  "\\PIPE\\spoolss"
 #define PIPE_NETDFS   "\\PIPE\\netdfs"
+#define PIPE_ECHO     "\\PIPE\\rpcecho"
 
 #define PIPE_NETLOGON_PLAIN "\\NETLOGON"
 
@@ -199,7 +200,8 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN];
 #define PI_WINREG              6
 #define PI_SPOOLSS             7
 #define PI_NETDFS              8
-#define PI_MAX_PIPES           9
+#define PI_ECHO                9
+#define PI_MAX_PIPES           10
 
 /* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */
 typedef struct nttime_info
index 3ecfc9255262490ef620a94d912a3108f8bcea0a..ddc20e492c2210e0535396453f15db51b57cdeac 100644 (file)
@@ -1840,50 +1840,6 @@ enum remote_arch_types get_remote_arch(void)
        return ra_type;
 }
 
-
-void out_ascii(FILE *f, unsigned char *buf,int len)
-{
-       int i;
-       for (i=0;i<len;i++)
-               fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
-}
-
-void out_data(FILE *f,char *buf1,int len, int per_line)
-{
-       unsigned char *buf = (unsigned char *)buf1;
-       int i=0;
-       if (len<=0) {
-               return;
-       }
-
-       fprintf(f, "[%03X] ",i);
-       for (i=0;i<len;) {
-               fprintf(f, "%02X ",(int)buf[i]);
-               i++;
-               if (i%(per_line/2) == 0) fprintf(f, " ");
-               if (i%per_line == 0) {      
-                       out_ascii(f,&buf[i-per_line  ],per_line/2); fprintf(f, " ");
-                       out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
-                       if (i<len) fprintf(f, "[%03X] ",i);
-               }
-       }
-       if ((i%per_line) != 0) {
-               int n;
-
-               n = per_line - (i%per_line);
-               fprintf(f, " ");
-               if (n>(per_line/2)) fprintf(f, " ");
-               while (n--) {
-                       fprintf(f, "   ");
-               }
-               n = MIN(per_line/2,i%per_line);
-               out_ascii(f,&buf[i-(i%per_line)],n); fprintf(f, " ");
-               n = (i%per_line) - n;
-               if (n>0) out_ascii(f,&buf[i-n],n); 
-               fprintf(f, "\n");    
-       }
-}
-
 void print_asc(int level, const unsigned char *buf,int len)
 {
        int i;
diff --git a/source3/rpc_client/cli_echo.c b/source3/rpc_client/cli_echo.c
new file mode 100644 (file)
index 0000000..03a4ab3
--- /dev/null
@@ -0,0 +1,187 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   RPC pipe client
+
+   Copyright (C) Tim Potter 2003
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+NTSTATUS cli_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                         uint32 request, uint32 *response)
+{
+       prs_struct qbuf, rbuf;
+       ECHO_Q_ADD_ONE q;
+       ECHO_R_ADD_ONE r;
+       BOOL result = False;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise parse structures */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       /* Marshall data and send request */
+
+        init_echo_q_add_one(&q, request);
+
+       if (!echo_io_q_add_one("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, ECHO_ADD_ONE, &qbuf, &rbuf))
+               goto done;
+
+       /* Unmarshall response */
+
+       if (!echo_io_r_add_one("", &r, &rbuf, 0))
+               goto done;
+
+       if (response)
+               *response = r.response;
+
+       result = True;
+
+ done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS cli_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                      uint32 size, char *in_data, char **out_data)
+{
+       prs_struct qbuf, rbuf;
+       ECHO_Q_ECHO_DATA q;
+       ECHO_R_ECHO_DATA r;
+       BOOL result = False;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise parse structures */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       /* Marshall data and send request */
+
+        init_echo_q_echo_data(&q, size, in_data);
+
+       if (!echo_io_q_echo_data("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, ECHO_DATA, &qbuf, &rbuf))
+               goto done;
+
+       /* Unmarshall response */
+
+       if (!echo_io_r_echo_data("", &r, &rbuf, 0))
+               goto done;
+
+       result = True;
+
+       if (out_data) {
+               *out_data = talloc(mem_ctx, size);
+               memcpy(*out_data, r.data, size);
+       }
+
+ done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS cli_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                           uint32 size, char *in_data)
+{
+       prs_struct qbuf, rbuf;
+       ECHO_Q_SINK_DATA q;
+       ECHO_R_SINK_DATA r;
+       BOOL result = False;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise parse structures */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       /* Marshall data and send request */
+
+        init_echo_q_sink_data(&q, size, in_data);
+
+       if (!echo_io_q_sink_data("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, ECHO_SINK_DATA, &qbuf, &rbuf)) {
+               goto done;
+       }
+
+       /* Unmarshall response */
+
+       if (!echo_io_r_sink_data("", &r, &rbuf, 0)) {
+               goto done;
+       }
+
+       result = True;
+
+ done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS cli_echo_source_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                             uint32 size, char **out_data)
+{
+       prs_struct qbuf, rbuf;
+       ECHO_Q_SOURCE_DATA q;
+       ECHO_R_SOURCE_DATA r;
+       BOOL result = False;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise parse structures */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       /* Marshall data and send request */
+
+        init_echo_q_source_data(&q, size);
+
+       if (!echo_io_q_source_data("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, ECHO_SOURCE_DATA, &qbuf, &rbuf)) {
+               goto done;
+       }
+
+       /* Unmarshall response */
+
+       if (!echo_io_r_source_data("", &r, &rbuf, 0)) {
+               goto done;
+       }
+
+       result = True;
+
+ done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
diff --git a/source3/rpc_parse/parse_echo.c b/source3/rpc_parse/parse_echo.c
new file mode 100644 (file)
index 0000000..67f9ad7
--- /dev/null
@@ -0,0 +1,166 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *
+ *  RPC Pipe client / server routines
+ *
+ *  Copyright (C) Tim Potter 2003
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+#include "nterr.h"
+#include "rpc_parse.h"   
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_PARSE
+
+void init_echo_q_add_one(ECHO_Q_ADD_ONE *q_d, uint32 request)
+{
+       q_d->request = request;
+}
+
+BOOL echo_io_q_add_one(const char *desc, ECHO_Q_ADD_ONE *q_d,
+                      prs_struct *ps, int depth)
+{
+       if (!prs_uint32("request", ps, 0, &q_d->request))
+               return False;
+
+       return True;
+}
+
+BOOL echo_io_r_add_one(const char *desc, ECHO_R_ADD_ONE *q_d,
+                      prs_struct *ps, int depth)
+{
+       if (!prs_uint32("response", ps, 0, &q_d->response))
+               return False;
+
+       return True;
+}
+
+
+void init_echo_q_echo_data(ECHO_Q_ECHO_DATA *q_d, uint32 size, char *data)
+{
+       q_d->size = size;
+       q_d->data = data;
+}
+
+BOOL echo_io_q_echo_data(const char *desc, ECHO_Q_ECHO_DATA *q_d,
+                         prs_struct *ps, int depth)
+{
+       if (!prs_uint32("size", ps, depth, &q_d->size))
+               return False;
+
+       if (!prs_uint32("size", ps, depth, &q_d->size))
+               return False;
+
+       if (UNMARSHALLING(ps)) {
+               q_d->data = prs_alloc_mem(ps, q_d->size);
+
+               if (!q_d->data)
+                       return False;
+       }
+
+       if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size))
+               return False;
+
+       return True;
+}
+
+BOOL echo_io_r_echo_data(const char *desc, ECHO_R_ECHO_DATA *q_d,
+                         prs_struct *ps, int depth)
+{
+       if (!prs_uint32("size", ps, 0, &q_d->size))
+               return False;
+
+       if (UNMARSHALLING(ps)) {
+               q_d->data = prs_alloc_mem(ps, q_d->size);
+
+               if (!q_d->data)
+                       return False;
+       }
+
+       if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size))
+               return False;
+
+       return True;
+}
+
+void init_echo_q_sink_data(ECHO_Q_SINK_DATA *q_d, uint32 size, char *data)
+{
+       q_d->size = size;
+       q_d->data = data;
+}
+
+BOOL echo_io_q_sink_data(const char *desc, ECHO_Q_SINK_DATA *q_d,
+                        prs_struct *ps, int depth)
+{
+       if (!prs_uint32("size", ps, depth, &q_d->size))
+               return False;
+
+       if (!prs_uint32("size", ps, depth, &q_d->size))
+               return False;
+
+       if (UNMARSHALLING(ps)) {
+               q_d->data = prs_alloc_mem(ps, q_d->size);
+
+               if (!q_d->data)
+                       return False;
+       }
+
+       if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size))
+               return False;
+
+       return True;
+}
+
+BOOL echo_io_r_sink_data(const char *desc, ECHO_R_SINK_DATA *q_d,
+                        prs_struct *ps, int depth)
+{
+       return True;
+}
+
+void init_echo_q_source_data(ECHO_Q_SOURCE_DATA *q_d, uint32 size)
+{
+       q_d->size = size;
+}
+
+BOOL echo_io_q_source_data(const char *desc, ECHO_Q_SOURCE_DATA *q_d,
+                        prs_struct *ps, int depth)
+{
+       if (!prs_uint32("size", ps, depth, &q_d->size))
+               return False;
+
+       return True;
+}
+
+BOOL echo_io_r_source_data(const char *desc, ECHO_R_SOURCE_DATA *q_d,
+                          prs_struct *ps, int depth)
+{
+       if (!prs_uint32("size", ps, 0, &q_d->size))
+               return False;
+
+       if (UNMARSHALLING(ps)) {
+               q_d->data = prs_alloc_mem(ps, q_d->size);
+
+               if (!q_d->data)
+                       return False;
+       }
+
+       if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size))
+               return False;
+
+       return True;
+}
index 656082e05ae0ee0fc4b0bc61040ee072bb50d18b..30909c69105fa9dc7206300bcaecc709ae7770d2 100644 (file)
@@ -138,6 +138,15 @@ interface/version dce/rpc pipe identification
         }, 0x03                             \
 }
 
+#define SYNT_ECHO_V1                        \
+{                                           \
+        {                                   \
+                0x60a15ec5, 0x4de8, 0x11d7, \
+                { 0xa6, 0x37, 0x00, 0x50,   \
+                  0x56, 0xa2, 0x01, 0x82 }  \
+        }, 0x01                             \
+}
+
 /*
  * IMPORTANT!!  If you update this structure, make sure to
  * update the index #defines in smb.h.
@@ -155,6 +164,7 @@ const struct pipe_id_info pipe_names [] =
        { PIPE_WINREG  , SYNT_WINREG_V1        , PIPE_WINREG   , TRANS_SYNT_V2 },
        { PIPE_SPOOLSS , SYNT_SPOOLSS_V1       , PIPE_SPOOLSS  , TRANS_SYNT_V2 },
        { PIPE_NETDFS  , SYNT_NETDFS_V3        , PIPE_NETDFS   , TRANS_SYNT_V2 },
+       { PIPE_ECHO    , SYNT_ECHO_V1          , PIPE_ECHO     , TRANS_SYNT_V2 },
        { NULL         , SYNT_NONE_V0          , NULL          , SYNT_NONE_V0  }
 };
 
diff --git a/source3/rpc_server/srv_echo.c b/source3/rpc_server/srv_echo.c
new file mode 100644 (file)
index 0000000..dcd8dd0
--- /dev/null
@@ -0,0 +1,137 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  RPC Pipe client / server routines for rpcecho
+ *  Copyright (C) Tim Potter                   2003.
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* This is the interface to the rpcecho pipe. */
+
+#include "includes.h"
+#include "nterr.h"
+
+#ifdef DEVELOPER
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+static BOOL api_add_one(pipes_struct *p)
+{
+       ECHO_Q_ADD_ONE q_u;
+       ECHO_R_ADD_ONE r_u;
+
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if(!echo_io_q_add_one("", &q_u, data, 0))
+               return False;
+       
+       _echo_add_one(p, &q_u, &r_u);
+       
+       if(!echo_io_r_add_one("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+static BOOL api_echo_data(pipes_struct *p)
+{
+       ECHO_Q_ECHO_DATA q_u;
+       ECHO_R_ECHO_DATA r_u;
+
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if(!echo_io_q_echo_data("", &q_u, data, 0))
+               return False;
+       
+       _echo_data(p, &q_u, &r_u);
+       
+       if(!echo_io_r_echo_data("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+static BOOL api_source_data(pipes_struct *p)
+{
+       ECHO_Q_SOURCE_DATA q_u;
+       ECHO_R_SOURCE_DATA r_u;
+
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if(!echo_io_q_source_data("", &q_u, data, 0))
+               return False;
+       
+       _source_data(p, &q_u, &r_u);
+       
+       if(!echo_io_r_source_data("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+static BOOL api_sink_data(pipes_struct *p)
+{
+       ECHO_Q_SINK_DATA q_u;
+       ECHO_R_SINK_DATA r_u;
+
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if(!echo_io_q_sink_data("", &q_u, data, 0))
+               return False;
+       
+       _sink_data(p, &q_u, &r_u);
+       
+       if(!echo_io_r_sink_data("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+\pipe\rpcecho commands
+********************************************************************/
+
+int rpc_echo_init(void)
+{
+       struct api_struct api_echo_cmds[] = {
+               {"ADD_ONE",       ECHO_ADD_ONE,     api_add_one },
+               {"ECHO_DATA",     ECHO_DATA,        api_echo_data },
+               {"SOURCE_DATA",   ECHO_SOURCE_DATA, api_source_data },
+               {"SINK_DATA",     ECHO_SINK_DATA,   api_sink_data },
+       };
+
+       return rpc_pipe_register_commands(
+               "rpcecho", "rpcecho", api_echo_cmds,
+               sizeof(api_echo_cmds) / sizeof(struct api_struct));
+}
+
+#endif /* DEVELOPER */
diff --git a/source3/rpc_server/srv_echo_nt.c b/source3/rpc_server/srv_echo_nt.c
new file mode 100644 (file)
index 0000000..ddb76b3
--- /dev/null
@@ -0,0 +1,78 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  RPC Pipe client / server routines for rpcecho
+ *  Copyright (C) Tim Potter                   2003.
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* This is the interface to the rpcecho pipe. */
+
+#include "includes.h"
+#include "nterr.h"
+
+#ifdef DEVELOPER
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+/* Add one to the input and return it */
+
+void _echo_add_one(pipes_struct *p, ECHO_Q_ADD_ONE *q_u, ECHO_R_ADD_ONE *r_u)
+{
+       DEBUG(10, ("_echo_add_one\n"));
+
+       r_u->response = q_u->request + 1;
+}
+
+/* Echo back an array of data */
+
+void _echo_data(pipes_struct *p, ECHO_Q_ECHO_DATA *q_u, 
+               ECHO_R_ECHO_DATA *r_u)
+{
+       DEBUG(10, ("_echo_data\n"));
+
+       r_u->data = talloc(p->mem_ctx, q_u->size);
+       r_u->size = q_u->size;
+       memcpy(r_u->data, q_u->data, q_u->size);
+}
+
+/* Sink an array of data */
+
+void _sink_data(pipes_struct *p, ECHO_Q_SINK_DATA *q_u, 
+               ECHO_R_SINK_DATA *r_u)
+{
+       DEBUG(10, ("_sink_data\n"));
+
+       /* My that was some yummy data! */
+}
+
+/* Source an array of data */
+
+void _source_data(pipes_struct *p, ECHO_Q_SOURCE_DATA *q_u, 
+                 ECHO_R_SOURCE_DATA *r_u)
+{
+       uint32 i;
+
+       DEBUG(10, ("_source_data\n"));
+
+       r_u->data = talloc(p->mem_ctx, q_u->size);
+       r_u->size = q_u->size;
+
+       for (i = 0; i < r_u->size; i++)
+               r_u->data[i] = i & 0xff;
+}
+
+#endif /* DEVELOPER */
diff --git a/source3/rpcclient/cmd_echo.c b/source3/rpcclient/cmd_echo.c
new file mode 100644 (file)
index 0000000..79ba744
--- /dev/null
@@ -0,0 +1,157 @@
+/* 
+   Unix SMB/CIFS implementation.
+   RPC pipe client
+
+   Copyright (C) Tim Potter 2003
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+static NTSTATUS cmd_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                int argc, const char **argv)
+{
+       uint32 request = 1, response;
+       NTSTATUS result;
+
+       if (argc > 2) {
+               printf("Usage: %s [num]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       if (argc == 2)
+               request = atoi(argv[1]);
+
+       result = cli_echo_add_one(cli, mem_ctx, request, &response);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       printf("%d + 1 = %d\n", request, response);
+
+done:
+       return result;
+}
+
+static NTSTATUS cmd_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                             int argc, const char **argv)
+{
+       uint32 size, i;
+       NTSTATUS result;
+       char *in_data = NULL, *out_data = NULL;
+
+       if (argc != 2) {
+               printf("Usage: %s num\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       size = atoi(argv[1]);
+       in_data = malloc(size);
+
+       for (i = 0; i < size; i++)
+               in_data[i] = i & 0xff;
+
+       result = cli_echo_data(cli, mem_ctx, size, in_data, &out_data);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       for (i = 0; i < size; i++) {
+               if (in_data[i] != out_data[i]) {
+                       printf("mismatch at offset %d, %d != %d\n",
+                              i, in_data[i], out_data[i]);
+               }
+       }
+
+done:
+       SAFE_FREE(in_data);
+
+       return result;
+}
+
+static NTSTATUS cmd_echo_source_data(struct cli_state *cli, 
+                                    TALLOC_CTX *mem_ctx, int argc, 
+                                    const char **argv)
+{
+       uint32 size, i;
+       NTSTATUS result;
+       char *out_data = NULL;
+
+       if (argc != 2) {
+               printf("Usage: %s num\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       size = atoi(argv[1]);
+
+       result = cli_echo_source_data(cli, mem_ctx, size, &out_data);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       for (i = 0; i < size; i++) {
+               if (out_data && out_data[i] != (i & 0xff)) {
+                       printf("mismatch at offset %d, %d != %d\n",
+                              i, out_data[i], i & 0xff);
+               }
+       }
+
+done:
+       return result;
+}
+
+static NTSTATUS cmd_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                  int argc, const char **argv)
+{
+       uint32 size, i;
+       NTSTATUS result;
+       char *in_data = NULL;
+
+       if (argc != 2) {
+               printf("Usage: %s num\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       size = atoi(argv[1]);
+       in_data = malloc(size);
+
+       for (i = 0; i < size; i++)
+               in_data[i] = i & 0xff;
+
+       result = cli_echo_sink_data(cli, mem_ctx, size, in_data);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+done:
+       SAFE_FREE(in_data);
+
+       return result;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set echo_commands[] = {
+
+       { "ECHO" },
+
+       { "echoaddone", RPC_RTYPE_NTSTATUS, cmd_echo_add_one,     NULL, PI_ECHO, "Add one to a number", "" },
+       { "echodata",   RPC_RTYPE_NTSTATUS, cmd_echo_data,        NULL, PI_ECHO, "Echo data",           "" },
+       { "sinkdata",   RPC_RTYPE_NTSTATUS, cmd_echo_sink_data,   NULL, PI_ECHO, "Sink data",           "" },
+       { "sourcedata", RPC_RTYPE_NTSTATUS, cmd_echo_source_data, NULL, PI_ECHO, "Source data",         "" },
+       { NULL }
+};
index 1de181f77c9a20eb5363a20c5d9b9dc00c87bbbc..efc883ff9ff1a2fcef89388361b7ff8479d6dfaa 100644 (file)
@@ -336,6 +336,7 @@ extern struct cmd_set srvsvc_commands[];
 extern struct cmd_set dfs_commands[];
 extern struct cmd_set reg_commands[];
 extern struct cmd_set ds_commands[];
+extern struct cmd_set echo_commands[];
 
 static struct cmd_set *rpcclient_command_list[] = {
        rpcclient_commands,
@@ -347,6 +348,7 @@ static struct cmd_set *rpcclient_command_list[] = {
        srvsvc_commands,
        dfs_commands,
        reg_commands,
+       echo_commands,
        NULL
 };
 
@@ -400,13 +402,14 @@ static NTSTATUS do_cmd(struct cli_state *cli,
 
                if (!cli_nt_open_netlogon(cli, trust_password,
                                          SEC_CHAN_WKSTA)) {
-                       DEBUG(0, ("Could not initialize NETLOGON pipe\n"));
+                       DEBUG(0, ("Could not initialise NETLOGON pipe\n"));
                        return NT_STATUS_UNSUCCESSFUL;
                }
        } else {
                if (cmd_entry->pipe_idx != -1) {
                        if (!cli_nt_session_open(cli, cmd_entry->pipe_idx)) {
-                               DEBUG(0, ("Could not initialize pipe\n"));
+                               DEBUG(0, ("Could not initialise %s\n",
+                                         get_pipe_name_from_index(cmd_entry->pipe_idx)));
                                return NT_STATUS_UNSUCCESSFUL;
                        }
                }
index 6d9c649045904c866b9333da94898cc7f41e97d8..9f7fabb75e44225942db0936926e2c6dedeb8d95 100644 (file)
@@ -40,6 +40,7 @@ static const char *known_nt_pipes[] = {
        "\\winreg",
        "\\spoolss",
        "\\netdfs",
+       "\\rpcecho",
        NULL
 };