1/* ex: set shiftwidth=4 softtabstop=4 expandtab: */ 2/* 3 * echo_client : demo DCE RPC application 4 * 5 * Jim Doyle, jrd@bu.edu, 09-05-1998 6 * 7 * 8 */ 9#if HAVE_CONFIG_H 10#include <config.h> 11#endif 12 13#include <stdio.h> 14#include <string.h> 15#include <stdlib.h> 16#include <unistd.h> 17#include <compat/dcerpc.h> 18#include "echo.h" 19#include "misc.h" 20 21#ifndef HAVE_GETOPT_H 22#include "getopt.h" 23#endif 24 25#define MAX_USER_INPUT 128 26#define MAX_LINE 100 * 1024 27 28#ifdef _WIN32 29#define EOF_STRING "^Z" 30#else 31#define EOF_STRING "^D" 32#endif 33 34/* 35 * Forward declarations 36 */ 37 38static int 39get_client_rpc_binding( 40 rpc_binding_handle_t * binding_handle, 41 rpc_if_handle_t interface_spec, 42 const char * hostname, 43 const char * protocol, 44 const char * endpoint 45 ); 46 47/* 48 * usage() 49 */ 50 51static void usage(void) 52{ 53 printf("usage: echo_server [-h hostname] -e endpoint -n|-u|-t\n"); 54 printf(" -h: specify host of RPC server (default is localhost)\n"); 55 printf(" -e: specify endpoint for protocol\n"); 56 printf(" -n: use named pipe protocol\n"); 57 printf(" -u: use UDP protocol\n"); 58 printf(" -t: use TCP protocol (default)\n"); 59 printf(" -g: instead of prompting, generate a data string of the specified length\n"); 60 printf(" -d: turn on debugging\n"); 61 printf("\n"); 62 exit(1); 63} 64 65/* XXX this needs a home in the public headers ... */ 66extern void rpc__dbg_set_switches( 67 const char * /*s*/, 68 unsigned32 * /*st*/ 69 ); 70 71int 72main( 73 int argc, 74 char *argv[] 75 ) 76{ 77 78 /* 79 * command line processing and options stuff 80 */ 81 82 extern char *optarg; 83 extern int optind, opterr, optopt; 84 int c; 85 86 const char * rpc_host = "127.0.0.1"; 87 const char * protocol = PROTOCOL_TCP; 88 const char * endpoint = NULL; 89 90 char buf[MAX_LINE+1]; 91 92 /* 93 * stuff needed to make RPC calls 94 */ 95 96 unsigned32 status; 97 rpc_binding_handle_t echo_server; 98 args * inargs; 99 args * outargs; 100 int ok; 101 unsigned32 i; 102 int generate_length = -1; 103 104 char * nl; 105 106 /* 107 * Process the cmd line args 108 */ 109 110 while ((c = getopt(argc, argv, "h:e:nutdg:")) != EOF) 111 { 112 switch (c) 113 { 114 case 'h': 115 rpc_host = optarg; 116 break; 117 case 'e': 118 endpoint = optarg; 119 break; 120 case 'n': 121 protocol = PROTOCOL_NP; 122 break; 123 case 'u': 124 protocol = PROTOCOL_UDP; 125 break; 126 case 't': 127 protocol = PROTOCOL_TCP; 128 break; 129 case 'd': 130#ifdef _WIN32 131 printf("This option is only supported on Linux.\n"); 132#else 133 rpc__dbg_set_switches("0-19.10", &status); 134 //Skip 20, which is memory allocs and frees 135 rpc__dbg_set_switches("21-43.10", &status); 136#endif 137 break; 138 case 'g': 139 generate_length = strtol(optarg, NULL, 10); 140 break; 141 default: 142 usage(); 143 } 144 } 145 146 if(!endpoint || !protocol) 147 { 148 usage(); 149 exit(1); 150 } 151 152 /* 153 * Get a binding handle to the server using the following params: 154 * 155 * 1. the hostname where the server lives 156 * 2. the interface description structure of the IDL interface 157 * 3. the desired transport protocol (UDP or TCP) 158 */ 159 160 if (get_client_rpc_binding(&echo_server, 161 echo_v1_0_c_ifspec, 162 rpc_host, 163 protocol, 164 endpoint) == 0) 165 { 166 printf ("Couldn't obtain RPC server binding. exiting.\n"); 167 exit(1); 168 } 169 170 171 /* 172 * Allocate an "args" struct with enough room to accomodate 173 * the max number of lines of text we can can from stdin. 174 */ 175 176 inargs = (args *)malloc(sizeof(args) + MAX_USER_INPUT * sizeof(string_t)); 177 if (inargs == NULL) printf("FAULT. Didn't allocate inargs.\n"); 178 179 if (generate_length < 0) 180 { 181 /* 182 * Get text from the user and pack into args. 183 */ 184 185 printf ("enter stuff (%s on an empty line when done):\n\n\n", EOF_STRING); 186 i = 0; 187 while (!feof(stdin) && i < MAX_USER_INPUT ) 188 { 189 if (NULL==fgets(buf, MAX_LINE, stdin)) 190 break; 191 if ((nl=strchr(buf, '\n'))) /* strip the newline */ 192 *nl=0; 193 inargs->argv[i] = (string_t)strdup(buf); /* copy from buf */ 194 i++; 195 } 196 inargs->argc = i; 197 } 198 else 199 { 200 inargs->argv[0] = malloc(generate_length + 1); 201 inargs->argv[0][0] = 's'; 202 203 for(i = 1; i < (unsigned long)generate_length; i++) 204 { 205 inargs->argv[0][i] = i%10 + '0'; 206 } 207 208 if(generate_length > 0) 209 inargs->argv[0][generate_length - 1] = 'e'; 210 inargs->argv[0][generate_length] = '\0'; 211 inargs->argc = 1; 212 } 213 214 /* 215 * Do the RPC call 216 */ 217 218 printf ("calling server\n"); 219 ok = ReverseIt(echo_server, inargs, &outargs, &status); 220 221 /* 222 * Print the results 223 */ 224 225 if (ok && status == error_status_ok) 226 { 227 printf ("got response from server. results: \n"); 228 for (i=0; i<outargs->argc; i++) 229 printf("\t[%d]: %s\n", i, outargs->argv[i]); 230 printf("\n===================================\n"); 231 232 } 233 234 if (status != error_status_ok) 235 chk_dce_err(status, "ReverseIt()", "main()", 1); 236 237 /* 238 * Done. Now gracefully teardown the RPC binding to the server 239 */ 240 241 rpc_binding_free(&echo_server, &status); 242 exit(0); 243 244} 245 246/*========================================================================== 247 * 248 * get_client_rpc_binding() 249 * 250 *========================================================================== 251 * 252 * Gets a binding handle to an RPC interface. 253 * 254 * parameters: 255 * 256 * [out] binding_handle 257 * [in] interface_spec <- DCE Interface handle for service 258 * [in] hostname <- Internet hostname where server lives 259 * [in] protocol <- "ncacn_ip_tcp", etc. 260 * [in] endpoint <- optional 261 * 262 *==========================================================================*/ 263 264static int 265get_client_rpc_binding( 266 rpc_binding_handle_t * binding_handle, 267 rpc_if_handle_t interface_spec, 268 const char * hostname, 269 const char * protocol, 270 const char * endpoint 271 ) 272{ 273 unsigned_char_p_t string_binding = NULL; 274 error_status_t status; 275 276 /* 277 * create a string binding given the command line parameters and 278 * resolve it into a full binding handle using the endpoint mapper. 279 * The binding handle resolution is handled by the runtime library 280 */ 281 282 rpc_string_binding_compose(NULL, 283 (unsigned_char_p_t)protocol, 284 (unsigned_char_p_t)hostname, 285 (unsigned_char_p_t)endpoint, 286 NULL, 287 &string_binding, 288 &status); 289 chk_dce_err(status, "rpc_string_binding_compose()", "get_client_rpc_binding", 1); 290 291 292 rpc_binding_from_string_binding(string_binding, 293 binding_handle, 294 &status); 295 chk_dce_err(status, "rpc_binding_from_string_binding()", "get_client_rpc_binding", 1); 296 297 if (!endpoint) 298 { 299 /* 300 * Resolve the partial binding handle using the endpoint mapper 301 */ 302 303 rpc_ep_resolve_binding(*binding_handle, 304 interface_spec, 305 &status); 306 chk_dce_err(status, "rpc_ep_resolve_binding()", "get_client_rpc_binding", 1); 307 } 308 309 rpc_string_free(&string_binding, &status); 310 chk_dce_err(status, "rpc_string_free()", "get_client_rpc_binding", 1); 311 312 /* 313 * Get a printable rendition of the binding handle and echo to 314 * the user. 315 */ 316 317 rpc_binding_to_string_binding(*binding_handle, 318 (unsigned char **)&string_binding, 319 &status); 320 chk_dce_err(status, "rpc_binding_to_string_binding()", "get_client_rpc_binding", 1); 321 322 printf("fully resolving binding for server is: %s\n", string_binding); 323 324 rpc_string_free(&string_binding, &status); 325 chk_dce_err(status, "rpc_string_free()", "get_client_rpc_binding", 1); 326 327 return 1; 328} 329