1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * @APPLE_LICENSE_HEADER_END@ 31 */ 32 33/* 34** 35** NAME: 36** 37** epstatus.c 38** 39** FACILITY: 40** 41** Endpoint mapper status. 42** 43** ABSTRACT: 44** 45** EPSTATUS - a tool to display endpoint mapper registrations. 46** 47*/ 48 49#if HAVE_CONFIG_H 50#include <config.h> 51#endif 52 53#include <dce/rpc.h> 54#include <dce/dce.h> 55#include <dce/dce_error.h> 56 57#include <stdio.h> 58#include <stdlib.h> 59#include <string.h> 60#include <stdarg.h> 61#include <getopt.h> 62#if HAVE_SYSEXITS_H 63#include <sysexits.h> 64#endif 65 66#ifndef EX_OSERR 67#define EX_OSERR 71 68#endif 69 70#ifndef EX_USAGE 71#define EX_USAGE 64 72#endif 73 74struct ep_table_entry 75{ 76 rpc_if_id_t te_interface; 77 rpc_binding_handle_t te_binding; 78 idl_uuid_t te_uuid; 79 idl_char * te_annotation; 80}; 81 82static const char PROGNAME[] = "epstatus"; 83static boolean verbose = false; 84 85#if __GNUC__ 86static void 87status_message( 88 FILE * file, 89 error_status_t status, 90 const char * fmt, 91 ...) __attribute__((__format__ (__printf__, 3, 4))); 92#endif 93 94static void 95status_message( 96 FILE * file, 97 error_status_t status, 98 const char * fmt, 99 ...) 100{ 101 dce_error_string_t message; 102 error_status_t error_status; 103 104 va_list args; 105 106 dce_error_inq_text(status, message, 107 (int *)&error_status); 108 if (error_status != rpc_s_ok) 109 { 110 snprintf(message, sizeof(message), "RPC error %#x", status); 111 } 112 113 va_start(args, fmt); 114 vfprintf(file, fmt, args); 115 fprintf(file, " %s\n", message); 116 va_end(args); 117} 118 119static void 120epstatus_usage(void) 121{ 122 fprintf(stderr, "usage: %s [-v]\n", PROGNAME); 123 fprintf(stderr, " -v: Print verbose status messages\n"); 124} 125 126static rpc_binding_handle_t 127ep_binding_from_protseq( 128 const idl_char * protseq) 129{ 130 error_status_t status; 131 unsigned_char_p_t string_binding; 132 rpc_binding_handle_t binding = NULL; 133 134 rpc_string_binding_compose(NULL, (unsigned_char_p_t)protseq, 135 NULL, NULL, NULL, &string_binding, &status); 136 if (status != rpc_s_ok) 137 { 138 status_message(stderr, status, 139 "%s: failed to compose %s binding", PROGNAME, protseq); 140 return NULL; 141 } 142 143 if (verbose) 144 { 145 printf("composed binding string '%s' from protoseq '%s'\n", 146 string_binding, protseq); 147 } 148 149 rpc_binding_from_string_binding(string_binding, &binding, &status); 150 if (status != rpc_s_ok) 151 { 152 status_message(stderr, status, 153 "%s: failed to create %s binding handle", 154 PROGNAME, protseq); 155 156 rpc_string_free(&string_binding, &status); 157 return NULL; 158 } 159 160 /* XXX Setting the timeout doesn't actually seem to allow ncadg_ip_udp 161 * to timeout when the endpoint mapper is not there. Not really sure 162 * why this is. 163 */ 164 rpc_mgmt_set_com_timeout(binding, rpc_c_binding_min_timeout, &status); 165 166 rpc_string_free(&string_binding, &status); 167 return binding; 168} 169 170static void 171ep_table_entry_free( 172 struct ep_table_entry * te) 173{ 174 error_status_t status; 175 176 if (!te) 177 { 178 return; 179 } 180 181 if (te->te_binding) 182 { 183 rpc_binding_free(&te->te_binding, &status); 184 } 185 186 if (te->te_annotation) 187 { 188 rpc_string_free(&te->te_annotation, &status); 189 } 190} 191 192static void 193ep_table_entry_display( 194 const struct ep_table_entry * te) 195{ 196 error_status_t status; 197 198 unsigned_char_p_t rpc_string = NULL; 199 200 printf("interface version: %u.%u\n", 201 te->te_interface.vers_major, 202 te->te_interface.vers_minor); 203 204 uuid_to_string((uuid_p_t)&te->te_interface.uuid, &rpc_string, &status); 205 if (status == rpc_s_ok) 206 { 207 printf("interface UUID: %s\n", rpc_string); 208 rpc_string_free(&rpc_string, &status); 209 } 210 else 211 { 212 status_message(stdout, status, "interface UUID:"); 213 } 214 215 if (te->te_binding) 216 { 217 rpc_binding_to_string_binding(te->te_binding, 218 &rpc_string, &status); 219 if (status == rpc_s_ok) 220 { 221 printf("binding: %s\n", rpc_string); 222 rpc_string_free(&rpc_string, &status); 223 } 224 else 225 { 226 status_message(stdout, status, "binding:"); 227 } 228 229 } 230 else 231 { 232 printf("binding:\n"); 233 } 234 235 uuid_to_string((uuid_p_t)&te->te_uuid, &rpc_string, &status); 236 if (status == rpc_s_ok) 237 { 238 printf("object UUID: %s\n", rpc_string); 239 rpc_string_free(&rpc_string, &status); 240 } 241 else 242 { 243 status_message(stdout, status, "object UUID:"); 244 } 245 246 printf("annotation: %s\n", 247 te->te_annotation ? (const char *)te->te_annotation : ""); 248} 249 250static error_status_t 251ep_status_display( 252 const idl_char * protseq, 253 rpc_binding_handle_t binding, 254 unsigned * count) 255{ 256 error_status_t status; 257 rpc_ep_inq_handle_t inquiry; 258 259 *count = 0; 260 261 if (verbose) 262 { 263 printf("querying endpoints status over %s\n", protseq); 264 } 265 266 rpc_mgmt_ep_elt_inq_begin(binding, rpc_c_ep_all_elts, 267 NULL, rpc_c_vers_all, NULL, &inquiry, &status); 268 if (status != rpc_s_ok) 269 { 270 return status; 271 } 272 273 for (;;) 274 { 275 struct ep_table_entry te; 276 memset(&te, 0, sizeof(te)); 277 278 rpc_mgmt_ep_elt_inq_next(inquiry, &te.te_interface, 279 &te.te_binding, &te.te_uuid, &te.te_annotation, &status); 280 281 if (status == rpc_s_ok) 282 { 283 (*count)++; 284 ep_table_entry_display(&te); 285 ep_table_entry_free(&te); 286 } 287 else if (status == rpc_s_no_more_elements) 288 { 289 break; 290 } 291 else 292 { 293 error_status_t tmp; 294 status_message(stderr, status, 295 "%s: endpoint mapper failed on %s,", 296 PROGNAME, protseq); 297 rpc_mgmt_ep_elt_inq_done(&inquiry, &tmp); 298 return status; 299 } 300 301 } 302 303 rpc_mgmt_ep_elt_inq_done(&inquiry, &status); 304 return rpc_s_ok; 305} 306 307int main(int argc, const char ** argv) 308{ 309 error_status_t status; 310 unsigned i; 311 int opt; 312 313 rpc_protseq_vector_p_t protseq; 314 315 while ((opt = getopt(argc, (void *)argv, "v")) != -1) 316 { 317 switch (opt) 318 { 319 case 'v': 320 verbose = true; 321 break; 322 default: 323 epstatus_usage(); 324 exit(EX_USAGE); 325 } 326 } 327 328 rpc_network_inq_protseqs(&protseq, &status); 329 if (status != rpc_s_ok) 330 { 331 status_message(stderr, status, 332 "%s: no installed protocols", PROGNAME); 333 exit(EX_OSERR); 334 } 335 336 /* For all the installed protocols, try to dump the endpoint mapper 337 * database. 338 */ 339 for (i = 0; i < protseq->count; ++i) 340 { 341 rpc_binding_handle_t binding; 342 unsigned count = 0; 343 344 binding = ep_binding_from_protseq(protseq->protseq[i]); 345 if (binding) 346 { 347 status = ep_status_display(protseq->protseq[i], binding, &count); 348 349 if (status == rpc_s_ok) 350 { 351 rpc_binding_free(&binding, &status); 352 printf("%u endpoints registered\n", count); 353 break; 354 } 355 356 rpc_binding_free(&binding, &status); 357 } 358 } 359 360 rpc_protseq_vector_free(&protseq, &status); 361 362 return 0; 363} 364