vfs_ceph: fix strict_allocate_ftruncate()
[Samba.git] / source3 / rpcclient / cmd_witness.c
blob733424beac333f872ac7fdadd9a7b68794c02032
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
5 Copyright (C) Gregor Beck 2013-2014
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "rpcclient.h"
23 #include "librpc/gen_ndr/ndr_witness_c.h"
24 #include <popt.h>
27 * We have to use the same connection for each subcommand
28 * for the context handles to be meaningful.
30 static void use_only_one_rpc_pipe_hack(struct rpc_pipe_client *cli);
32 static WERROR cmd_witness_GetInterfaceList(struct rpc_pipe_client *cli,
33 TALLOC_CTX *mem_ctx, int argc,
34 const char **argv)
36 NTSTATUS status;
37 WERROR result;
38 TALLOC_CTX *frame = talloc_stackframe();
39 struct witness_interfaceList *interface_list = NULL;
40 uint32_t num_interfaces, n;
41 struct witness_interfaceInfo *interfaces;
43 use_only_one_rpc_pipe_hack(cli);
45 status = dcerpc_witness_GetInterfaceList(cli->binding_handle, frame,
46 &interface_list, &result);
47 if (!NT_STATUS_IS_OK(status)) {
48 DEBUG(0, ("dcerpc_witness_GetInterfaceList failed, status: %s\n", nt_errstr(status)));
49 result = ntstatus_to_werror(status);
50 goto done;
52 if (!W_ERROR_IS_OK(result)) {
53 DEBUG(0, ("dcerpc_witness_GetInterfaceList failed, error: %s\n", win_errstr(result)));
54 goto done;
57 SMB_ASSERT(interface_list);
58 interfaces = interface_list->interfaces;
59 num_interfaces = interface_list->num_interfaces;
61 for (n=0; n < num_interfaces; n++) {
62 char wif = (interfaces[n].flags & WITNESS_INFO_WITNESS_IF) ? '*' : ' ';
63 char state = 'X';
65 if (interfaces[n].state == WITNESS_STATE_AVAILABLE) {
66 state = '+';
67 } else if (interfaces[n].state == WITNESS_STATE_UNAVAILABLE) {
68 state = '-';
69 } else if (interfaces[n].state == WITNESS_STATE_UNKNOWN) {
70 state = '?';
73 d_printf("%c%c %s", wif, state, interfaces[n].group_name);
75 if (interfaces[n].flags & WITNESS_INFO_IPv4_VALID) {
76 d_printf(" %s", interfaces[n].ipv4);
79 if (interfaces[n].flags & WITNESS_INFO_IPv6_VALID) {
80 d_printf(" %s", interfaces[n].ipv6);
83 switch (interfaces[n].version) {
84 case WITNESS_V1:
85 d_printf(" V1");
86 break;
87 case WITNESS_V2:
88 d_printf(" V2");
89 break;
90 default:
91 d_printf(" Unsuported Version (0x%08x)", interfaces[n].version);
94 d_printf("\n");
97 done:
98 talloc_free(frame);
99 return result;
102 static WERROR cmd_witness_Register(struct rpc_pipe_client *cli,
103 TALLOC_CTX *mem_ctx, int argc,
104 const char **argv)
106 static char hostname[MAXHOSTNAMELEN] = {'\0'};
107 NTSTATUS status;
108 WERROR result = WERR_OK;
109 TALLOC_CTX *frame = talloc_stackframe();
110 struct policy_handle hnd;
111 const char *net_name = NULL;
112 const char *ip_addr = NULL;
113 const char *client_name = hostname;
114 long version = WITNESS_V1;
115 int c;
116 poptContext optCon;
117 struct poptOption optionsTable[] = {
119 .longName = "version",
120 .shortName = 'v',
121 .argInfo = POPT_ARG_LONG|POPT_ARGFLAG_SHOW_DEFAULT,
122 .arg = &version,
123 .val = WITNESS_V2,
124 .descrip = "witness version",
125 .argDescrip = "version"
128 .longName = "V1",
129 .shortName = '1',
130 .argInfo = POPT_ARG_LONG|POPT_ARG_VAL,
131 .arg = &version,
132 .val = WITNESS_V1,
133 .descrip = "witness version 1",
134 .argDescrip = NULL
137 .longName = "V2",
138 .shortName = '2',
139 .argInfo = POPT_ARG_LONG|POPT_ARG_VAL,
140 .arg = &version,
141 .val = WITNESS_V2,
142 .descrip = "witness version 2",
143 .argDescrip = NULL
146 .longName = "net",
147 .shortName = 'n',
148 .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,
149 .arg = &net_name,
150 .val = 0,
151 .descrip = "net name",
152 .argDescrip = NULL
155 .longName = "ip",
156 .shortName = 'i',
157 .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,
158 .arg = &ip_addr,
159 .val = 0,
160 .descrip = "ip address",
161 .argDescrip = NULL
164 .longName = "client",
165 .shortName = 'c',
166 .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT|POPT_ARGFLAG_OPTIONAL,
167 .arg = &client_name,
168 .val = 0,
169 .descrip = "client name",
170 .argDescrip = NULL
172 POPT_TABLEEND
175 use_only_one_rpc_pipe_hack(cli);
177 if (hostname[0] == '\0') {
178 gethostname (hostname, sizeof(hostname));
181 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
183 while ((c = poptGetNextOpt(optCon)) >= 0) { }
185 if (c < -1) {
186 /* an error occurred during option processing */
187 d_fprintf(stderr, "%s: %s\n",
188 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
189 poptStrerror(c));
190 goto done;
193 if (argc < 2 || poptPeekArg(optCon) != NULL) {
194 poptPrintHelp(optCon, stderr, 0);
195 goto done;
198 status = dcerpc_witness_Register(cli->binding_handle, frame,
199 &hnd,
200 version,
201 net_name, ip_addr, client_name,
202 &result);
203 if (!NT_STATUS_IS_OK(status)) {
204 DEBUG(0, ("dcerpc_witness_Register failed, status: %s\n", nt_errstr(status)));
205 result = ntstatus_to_werror(status);
206 goto done;
208 if (!W_ERROR_IS_OK(result)) {
209 DEBUG(0, ("dcerpc_witness_Register failed, error: %s\n", win_errstr(result)));
210 goto done;
213 d_printf("%x:%s\n", hnd.handle_type, GUID_string(frame, &hnd.uuid));
215 done:
216 talloc_free(frame);
217 return result;
220 static WERROR cmd_witness_RegisterEx(struct rpc_pipe_client *cli,
221 TALLOC_CTX *mem_ctx, int argc,
222 const char **argv)
224 static char hostname[MAXHOSTNAMELEN] = {'\0'};
225 NTSTATUS status;
226 WERROR result = WERR_OK;
227 TALLOC_CTX *frame = talloc_stackframe();
228 struct policy_handle hnd;
229 const char *net_name = NULL;
230 const char *ip_addr = NULL;
231 const char *share_name = NULL;
232 const char *client_name = hostname;
233 long version = WITNESS_V2;
234 long flags = 0;
235 long timeout = 0;
236 int c;
237 poptContext optCon;
238 struct poptOption optionsTable[] = {
240 .longName = "version",
241 .shortName = 'v',
242 .argInfo = POPT_ARG_LONG|POPT_ARGFLAG_SHOW_DEFAULT,
243 .arg = &version,
244 .val = WITNESS_V2,
245 .descrip = "witness version",
246 .argDescrip = "version"
249 .longName = "V1",
250 .shortName = '1',
251 .argInfo = POPT_ARG_LONG|POPT_ARG_VAL,
252 .arg = &version,
253 .val = WITNESS_V1,
254 .descrip = "witness version 1",
257 .longName = "V2",
258 .shortName = '2',
259 .argInfo = POPT_ARG_LONG|POPT_ARG_VAL,
260 .arg = &version,
261 .val = WITNESS_V2,
262 .descrip = "witness version 2",
265 .longName = "net",
266 .shortName = 'n',
267 .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,
268 .arg = &net_name,
269 .val = 0,
270 .descrip = "net name",
273 .longName = "ip",
274 .shortName = 'i',
275 .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,
276 .arg = &ip_addr,
277 .val = 0,
278 .descrip = "ip address",
281 .longName = "share",
282 .shortName = 's',
283 .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,
284 .arg = &share_name,
285 .val = 0,
286 .descrip = "share name",
289 .longName = "client",
290 .shortName = 'c',
291 .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT|POPT_ARGFLAG_OPTIONAL,
292 .arg = &client_name,
293 .val = 0,
294 .descrip = "client name",
297 .longName = "flags",
298 .shortName = 'f',
299 .argInfo = POPT_ARG_LONG|POPT_ARGFLAG_OR|POPT_ARGFLAG_SHOW_DEFAULT,
300 .arg = &flags,
301 .val = 0,
302 .descrip = "flags",
305 .longName = "timeout",
306 .shortName = 't',
307 .argInfo = POPT_ARG_LONG|POPT_ARGFLAG_SHOW_DEFAULT,
308 .arg = &timeout,
309 .val = 0,
310 .descrip = "timeout",
312 POPT_TABLEEND
315 use_only_one_rpc_pipe_hack(cli);
317 if (hostname[0] == '\0') {
318 gethostname (hostname, sizeof(hostname));
321 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
323 while ((c = poptGetNextOpt(optCon)) >= 0) { }
325 if (c < -1) {
326 /* an error occurred during option processing */
327 d_fprintf(stderr, "%s: %s\n",
328 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
329 poptStrerror(c));
330 goto done;
333 if (argc < 2 || poptPeekArg(optCon) != NULL) {
334 poptPrintHelp(optCon, stderr, 0);
335 goto done;
338 status = dcerpc_witness_RegisterEx(cli->binding_handle, frame,
339 &hnd,
340 version,
341 net_name, share_name, ip_addr, client_name,
342 flags, timeout,
343 &result);
344 if (!NT_STATUS_IS_OK(status)) {
345 DEBUG(0, ("dcerpc_witness_RegisterEx failed, status: %s\n", nt_errstr(status)));
346 result = ntstatus_to_werror(status);
347 goto done;
349 if (!W_ERROR_IS_OK(result)) {
350 DEBUG(0, ("dcerpc_witness_RegisterEx failed, error: %s\n", win_errstr(result)));
351 goto done;
354 d_printf("%x:%s\n", hnd.handle_type, GUID_string(frame, &hnd.uuid));
356 done:
357 poptFreeContext(optCon);
358 talloc_free(frame);
359 return result;
362 static bool
363 read_context_handle(const char *str, struct policy_handle *hnd)
365 NTSTATUS status;
366 long type;
367 char *pos;
368 struct GUID guid;
370 type = strtol(str, &pos, 16);
371 if (*pos != ':') {
372 DEBUG(0, ("read_context_handle: failed to parse type\n"));
373 return false;
375 status = GUID_from_string(pos+1, &guid);
376 if (!NT_STATUS_IS_OK(status)) {
377 DEBUG(0, ("read_context_handle: failed to parse guid %s\n", nt_errstr(status)));
378 return false;
381 hnd->handle_type = type;
382 hnd->uuid = guid;
383 return true;
386 static WERROR cmd_witness_UnRegister(struct rpc_pipe_client *cli,
387 TALLOC_CTX *mem_ctx, int argc,
388 const char **argv)
390 NTSTATUS status;
391 WERROR result = WERR_OK;
392 TALLOC_CTX *frame = talloc_stackframe();
393 struct policy_handle hnd;
395 use_only_one_rpc_pipe_hack(cli);
397 if (argc != 2) {
398 d_printf("%s <context_handle>\n", argv[0]);
399 goto done;
402 if (!read_context_handle(argv[1], &hnd)) {
403 result = WERR_INVALID_PARAMETER;
404 goto done;
407 status = dcerpc_witness_UnRegister(cli->binding_handle, frame,
408 hnd, &result);
409 if (!NT_STATUS_IS_OK(status)) {
410 DEBUG(0, ("dcerpc_witness_UnRegister failed, status: %s\n", nt_errstr(status)));
411 result = ntstatus_to_werror(status);
412 goto done;
414 if (!W_ERROR_IS_OK(result)) {
415 DEBUG(0, ("dcerpc_witness_UnRegister failed, error: %s\n", win_errstr(result)));
416 goto done;
419 done:
420 talloc_free(frame);
421 return result;
424 static void print_notify_response_resource_change(struct witness_ResourceChange *r)
426 const char *type_str;
428 if (r->type == WITNESS_RESOURCE_STATE_UNKNOWN) {
429 type_str = "Unknown";
430 } else if (r->type == WITNESS_RESOURCE_STATE_AVAILABLE) {
431 type_str = "Available\n";
432 } else if (r->type == WITNESS_RESOURCE_STATE_UNAVAILABLE) {
433 type_str = "Unavailable";
434 } else {
435 type_str = talloc_asprintf(r, "Invalid (%u)", r->type);
437 d_printf("%s -> %s\n", r->name, type_str);
440 static void print_notify_response_ip_addr_info_list(struct witness_IPaddrInfoList *r)
442 int i;
444 for (i=0; i < r->num; i++) {
445 uint32_t flags = r->addr[i].flags;
446 const char *str4 = r->addr[i].ipv4;
447 const char *str6 = r->addr[i].ipv6;
449 d_printf("Flags 0x%08x", flags);
450 if (flags & WITNESS_IPADDR_V4) {
451 d_printf(" %s", str4);
453 if (flags & WITNESS_IPADDR_V6) {
454 d_printf(" %s", str6);
456 if (flags & WITNESS_IPADDR_ONLINE) {
457 d_printf(" Online");
459 if (flags & WITNESS_IPADDR_ONLINE) {
460 d_printf(" Offline");
462 d_printf("\n");
466 static void print_notify_response(union witness_notifyResponse_message *r,
467 uint32_t type)
469 switch (type) {
470 case WITNESS_NOTIFY_RESOURCE_CHANGE:
471 print_notify_response_resource_change(&r->resource_change);
472 break;
473 case WITNESS_NOTIFY_CLIENT_MOVE:
474 case WITNESS_NOTIFY_SHARE_MOVE:
475 case WITNESS_NOTIFY_IP_CHANGE:
476 print_notify_response_ip_addr_info_list(&r->client_move);
477 break;
478 default:
479 break;
483 static WERROR cmd_witness_AsyncNotify(struct rpc_pipe_client *cli,
484 TALLOC_CTX *mem_ctx, int argc,
485 const char **argv)
487 NTSTATUS status;
488 WERROR result = WERR_OK;
489 TALLOC_CTX *frame = talloc_stackframe();
490 struct policy_handle hnd;
491 struct witness_notifyResponse *response = NULL;
492 uint32_t timeout;
493 int i;
495 use_only_one_rpc_pipe_hack(cli);
497 if (argc != 2) {
498 d_printf("%s <context_handle>\n", argv[0]);
499 goto done;
502 if (!read_context_handle(argv[1], &hnd)) {
503 result = WERR_INVALID_PARAMETER;
504 goto done;
507 timeout = dcerpc_binding_handle_set_timeout(cli->binding_handle, UINT32_MAX);
508 status = dcerpc_witness_AsyncNotify(cli->binding_handle, frame, hnd,
509 &response, &result);
510 dcerpc_binding_handle_set_timeout(cli->binding_handle, timeout);
511 if (!NT_STATUS_IS_OK(status)) {
512 DEBUG(0, ("dcerpc_witness_AsyncNotify failed, status: %s\n", nt_errstr(status)));
513 result = ntstatus_to_werror(status);
514 goto done;
516 if (!W_ERROR_IS_OK(result)) {
517 DEBUG(0, ("dcerpc_witness_AsyncNotify failed, error: %s\n", win_errstr(result)));
518 goto done;
521 if (response == NULL) {
522 d_printf("Got an empty response\n");
523 goto done;
526 switch(response->type) {
527 case WITNESS_NOTIFY_RESOURCE_CHANGE:
528 d_printf("Resource change");
529 break;
530 case WITNESS_NOTIFY_CLIENT_MOVE:
531 d_printf("Client move");
532 break;
533 case WITNESS_NOTIFY_SHARE_MOVE:
534 d_printf("Share move");
535 break;
536 case WITNESS_NOTIFY_IP_CHANGE:
537 d_printf("IP change");
538 break;
539 default:
540 d_printf("Unknown (0x%x)", (int)response->type);
542 d_printf(" with %d messages\n", response->num);
544 for (i=0; i < response->num; i++) {
545 print_notify_response(&response->messages[i], response->type);
547 done:
548 talloc_free(frame);
549 return result;
552 struct cmd_set witness_commands[] = {
554 .name = "WITNESS",
557 .name = "GetInterfaceList",
558 .returntype = RPC_RTYPE_WERROR,
559 .ntfn = NULL,
560 .wfn = &cmd_witness_GetInterfaceList,
561 .table = &ndr_table_witness,
562 .rpc_pipe = NULL,
563 .description = "",
564 .usage = "",
567 .name = "Register",
568 .returntype = RPC_RTYPE_WERROR,
569 .ntfn = NULL,
570 .wfn = &cmd_witness_Register,
571 .table = &ndr_table_witness,
572 .rpc_pipe = NULL,
573 .description = "",
574 .usage = "",
577 .name = "UnRegister",
578 .returntype = RPC_RTYPE_WERROR,
579 .ntfn = NULL,
580 .wfn = &cmd_witness_UnRegister,
581 .table = &ndr_table_witness,
582 .rpc_pipe = NULL,
583 .description = "",
584 .usage = "",
587 .name = "AsyncNotify",
588 .returntype = RPC_RTYPE_WERROR,
589 .ntfn = NULL,
590 .wfn = &cmd_witness_AsyncNotify,
591 .table = &ndr_table_witness,
592 .rpc_pipe = NULL,
593 .description = "",
594 .usage = "",
597 .name = "RegisterEx",
598 .returntype = RPC_RTYPE_WERROR,
599 .ntfn = NULL,
600 .wfn = &cmd_witness_RegisterEx,
601 .table = &ndr_table_witness,
602 .rpc_pipe = NULL,
603 .description = "",
604 .usage = "",
607 .name = NULL,
612 * We have to use the same connection for each subcommand
613 * for the context handles to be meaningful.
615 static void use_only_one_rpc_pipe_hack(struct rpc_pipe_client *cli)
617 struct cmd_set *ptr;
619 for (ptr = &witness_commands[0]; ptr->name; ptr++) {
620 ptr->rpc_pipe = cli;