1/* 2 RPC echo client. 3 4 Copyright (C) Tim Potter 2003 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#include <stdio.h> 21#include <stdlib.h> 22#include <ctype.h> 23#include "rpcecho.h" 24 25void main(int argc, char **argv) 26{ 27 RPC_STATUS status; 28 char *binding = NULL; 29 const char *username=NULL; 30 const char *password=NULL; 31 const char *domain=NULL; 32 unsigned sec_options = 0; 33 34 argv += 1; 35 argc -= 1; 36 37 while (argc > 2 && argv[0][0] == '-') { 38 const char *option; 39 40 switch (argv[0][1]) { 41 case 'e': 42 binding = argv[1]; 43 break; 44 case 'u': 45 username = argv[1]; 46 break; 47 case 'p': 48 password = argv[1]; 49 break; 50 case 'd': 51 domain = argv[1]; 52 break; 53 case '-': 54 option = &argv[0][2]; 55 if (strcmp(option, "sign") == 0) { 56 if (sec_options == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) { 57 printf("You must choose sign or seal, not both\n"); 58 exit(1); 59 } 60 sec_options = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; 61 } else if (strcmp(option, "seal") == 0) { 62 if (sec_options == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) { 63 printf("You must choose sign or seal, not both\n"); 64 exit(1); 65 } 66 sec_options = RPC_C_AUTHN_LEVEL_PKT_PRIVACY; 67 } else { 68 printf("Bad security option '%s'\n", option); 69 exit(1); 70 } 71 argv++; 72 argc--; 73 continue; 74 default: 75 printf("Bad option -%c\n", argv[0][0]); 76 exit(1); 77 } 78 argv += 2; 79 argc -= 2; 80 } 81 82 if (argc < 2) { 83 printf("Usage: client [options] hostname cmd [args]\n\n"); 84 printf("Where hostname is the name of the host to connect to,\n"); 85 printf("and cmd is the command to execute with optional args:\n\n"); 86 printf("\taddone num\tAdd one to num and return the result\n"); 87 printf("\techodata size\tSend an array of size bytes and receive it back\n"); 88 printf("\tsinkdata size\tSend an array of size bytes\n"); 89 printf("\tsourcedata size\tReceive an array of size bytes\n"); 90 printf("\ttest\trun testcall\n"); 91 printf("\noptions:\n"); 92 printf("\t-u username -d domain -p password -e endpoint\n"); 93 printf("\t--sign --seal\n"); 94 printf("\nExamples:\n"); 95 printf("\tclient HOSTNAME addone 3\n"); 96 printf("\tclient 192.168.115.1 addone 3\n"); 97 printf("\tclient -e ncacn_np:HOSTNAME[\\\\pipe\\\\rpcecho] addone 3\n"); 98 printf("\tclient -e ncacn_ip_tcp:192.168.115.1 addone 3\n"); 99 printf("\tclient -e ncacn_ip_tcp:192.168.115.1 -u tridge -d MYDOMAIN -p PASSWORD addone 3\n"); 100 exit(0); 101 } 102 103 104 if (!binding) { 105 char *network_address = argv[0]; 106 107 argc--; 108 argv++; 109 110 status = RpcStringBindingCompose( 111 NULL, /* uuid */ 112 "ncacn_np", 113 network_address, 114 "\\pipe\\rpcecho", 115 NULL, /* options */ 116 &binding); 117 118 if (status) { 119 printf("RpcStringBindingCompose returned %d\n", status); 120 exit(status); 121 } 122 } 123 124 printf("Endpoint is %s\n", binding); 125 126 status = RpcBindingFromStringBinding( 127 binding, 128 &rpcecho_IfHandle); 129 130 if (status) { 131 printf("RpcBindingFromStringBinding returned %d\n", status); 132 exit(status); 133 } 134 135 if (username) { 136 SEC_WINNT_AUTH_IDENTITY ident = { username, strlen(username), 137 domain, strlen(domain), 138 password, strlen(password), 139 SEC_WINNT_AUTH_IDENTITY_ANSI }; 140 141 status = RpcBindingSetAuthInfo(rpcecho_IfHandle, NULL, 142 sec_options, 143 RPC_C_AUTHN_WINNT, 144 &ident, 0); 145 if (status) { 146 printf ("RpcBindingSetAuthInfo failed: 0x%x\n", status); 147 exit (1); 148 } 149 } 150 151 152 while (argc > 0) { 153 RpcTryExcept { 154 155 /* Add one to a number */ 156 157 if (strcmp(argv[0], "addone") == 0) { 158 int arg, result; 159 160 if (argc < 2) { 161 printf("Usage: addone num\n"); 162 exit(1); 163 } 164 165 arg = atoi(argv[1]); 166 167 AddOne(arg, &result); 168 printf("%d + 1 = %d\n", arg, result); 169 170 argc -= 2; 171 argv += 2; 172 continue; 173 } 174 175 /* Echo an array */ 176 177 if (strcmp(argv[0], "echodata") == 0) { 178 int arg, i; 179 char *indata, *outdata; 180 181 if (argc < 2) { 182 printf("Usage: echo num\n"); 183 exit(1); 184 } 185 186 arg = atoi(argv[1]); 187 188 if ((indata = malloc(arg)) == NULL) { 189 printf("Error allocating %d bytes for input\n", arg); 190 exit(1); 191 } 192 193 if ((outdata = malloc(arg)) == NULL) { 194 printf("Error allocating %d bytes for output\n", arg); 195 exit(1); 196 } 197 198 for (i = 0; i < arg; i++) 199 indata[i] = i & 0xff; 200 201 EchoData(arg, indata, outdata); 202 203 printf("echo %d\n", arg); 204 205 for (i = 0; i < arg; i++) { 206 if (indata[i] != outdata[i]) { 207 printf("data mismatch at offset %d, %d != %d\n", 208 i, indata[i], outdata[i]); 209 exit(0); 210 } 211 } 212 213 argc -= 2; 214 argv += 2; 215 continue; 216 } 217 218 if (strcmp(argv[0], "sinkdata") == 0) { 219 int arg, i; 220 char *indata; 221 222 if (argc < 2) { 223 printf("Usage: sinkdata num\n"); 224 exit(1); 225 } 226 227 arg = atoi(argv[1]); 228 229 if ((indata = malloc(arg)) == NULL) { 230 printf("Error allocating %d bytes for input\n", arg); 231 exit(1); 232 } 233 234 for (i = 0; i < arg; i++) 235 indata[i] = i & 0xff; 236 237 SinkData(arg, indata); 238 239 printf("sinkdata %d\n", arg); 240 argc -= 2; 241 argv += 2; 242 continue; 243 } 244 245 if (strcmp(argv[0], "sourcedata") == 0) { 246 int arg, i; 247 unsigned char *outdata; 248 249 if (argc < 2) { 250 printf("Usage: sourcedata num\n"); 251 exit(1); 252 } 253 254 arg = atoi(argv[1]); 255 256 if ((outdata = malloc(arg)) == NULL) { 257 printf("Error allocating %d bytes for output\n", arg); 258 exit(1); 259 } 260 261 SourceData(arg, outdata); 262 263 printf("sourcedata %d\n", arg); 264 265 for (i = 0; i < arg; i++) { 266 if (outdata[i] != (i & 0xff)) { 267 printf("data mismatch at offset %d, %d != %d\n", 268 i, outdata[i], i & 0xff); 269 } 270 } 271 272 argc -= 2; 273 argv += 2; 274 continue; 275 } 276 277 if (strcmp(argv[0], "test") == 0) { 278 printf("no TestCall\n"); 279 280 argc -= 1; 281 argv += 1; 282 continue; 283 } 284 285 286 if (strcmp(argv[0], "enum") == 0) { 287 enum echo_Enum1 v = ECHO_ENUM1; 288 echo_Enum2 e2; 289 echo_Enum3 e3; 290 291 e2.e1 = 76; 292 e2.e2 = ECHO_ENUM1_32; 293 e3.e1 = ECHO_ENUM2; 294 295 argc -= 1; 296 argv += 1; 297 298 echo_TestEnum(&v, &e2, &e3); 299 300 continue; 301 } 302 303 if (strcmp(argv[0], "double") == 0) { 304 typedef unsigned short uint16; 305 uint16 v = 13; 306 uint16 *pv = &v; 307 uint16 **ppv = &pv; 308 uint16 ret; 309 310 argc -= 1; 311 argv += 1; 312 313 ret = echo_TestDoublePointer(&ppv); 314 315 printf("TestDoublePointer v=%d ret=%d\n", v, ret); 316 317 continue; 318 } 319 320 if (strcmp(argv[0], "sleep") == 0) { 321 long arg, result; 322 323 if (argc < 2) { 324 printf("Usage: sleep num\n"); 325 exit(1); 326 } 327 328 arg = atoi(argv[1]); 329 330// result = TestSleep(arg); 331// printf("Slept for %d seconds\n", result); 332 printf("Sleep disabled (need async code)\n"); 333 334 argc -= 2; 335 argv += 2; 336 continue; 337 } 338 339 printf("Invalid command '%s'\n", argv[0]); 340 goto done; 341 342 } RpcExcept(1) { 343 unsigned long ex; 344 345 ex = RpcExceptionCode(); 346 printf("Runtime error 0x%x\n", ex); 347 } RpcEndExcept 348 } 349 350done: 351 352 status = RpcStringFree(&binding); 353 354 if (status) { 355 printf("RpcStringFree returned %d\n", status); 356 exit(status); 357 } 358 359 status = RpcBindingFree(&rpcecho_IfHandle); 360 361 if (status) { 362 printf("RpcBindingFree returned %d\n", status); 363 exit(status); 364 } 365 366 exit(0); 367} 368