~ubuntu-branches/ubuntu/vivid/rpcbind/vivid

« back to all changes in this revision

Viewing changes to .pc/run-migration/src/rpcinfo.c

  • Committer: Steve Langasek
  • Date: 2011-10-17 18:56:40 UTC
  • Revision ID: steve.langasek@canonical.com-20111017185640-o4znlqhozm5vsuue
also handle /var/run/rpcbind.sock

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2009, Sun Microsystems, Inc.
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 * - Redistributions of source code must retain the above copyright notice,
 
8
 *   this list of conditions and the following disclaimer.
 
9
 * - Redistributions in binary form must reproduce the above copyright notice,
 
10
 *   this list of conditions and the following disclaimer in the documentation
 
11
 *   and/or other materials provided with the distribution.
 
12
 * - Neither the name of Sun Microsystems, Inc. nor the names of its
 
13
 *   contributors may be used to endorse or promote products derived
 
14
 *   from this software without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
17
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
19
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 
20
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
21
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
22
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
23
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
24
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
25
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
26
 * POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
/*
 
29
 * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
 
30
 */
 
31
/*
 
32
 * rpcinfo: ping a particular rpc program
 
33
 *      or dump the the registered programs on the remote machine.
 
34
 */
 
35
 
 
36
/*
 
37
 * We are for now defining PORTMAP here.  It doesnt even compile
 
38
 * unless it is defined.
 
39
 */
 
40
#ifndef PORTMAP
 
41
#define PORTMAP
 
42
#endif
 
43
 
 
44
/*
 
45
 * If PORTMAP is defined, rpcinfo will talk to both portmapper and
 
46
 * rpcbind programs; else it talks only to rpcbind. In the latter case
 
47
 * all the portmapper specific options such as -u, -t, -p become void.
 
48
 */
 
49
#include <sys/types.h>
 
50
#include <sys/socket.h>
 
51
#include <sys/un.h>
 
52
#include <rpc/rpc.h>
 
53
#include <stdio.h>
 
54
#include <rpc/rpcb_prot.h>
 
55
#include <rpc/rpcent.h>
 
56
#include <rpc/nettype.h>
 
57
#include <rpc/rpc_com.h>
 
58
#include <stdlib.h>
 
59
#include <string.h>
 
60
#include <unistd.h>
 
61
#include <err.h>
 
62
#include <ctype.h>
 
63
 
 
64
#ifdef PORTMAP                  /* Support for version 2 portmapper */
 
65
#include <netinet/in.h>
 
66
#include <netdb.h>
 
67
#include <arpa/inet.h>
 
68
#include <rpc/pmap_prot.h>
 
69
#include <rpc/pmap_clnt.h>
 
70
#endif
 
71
 
 
72
#define max(a,b) ((a) > (b) ? (a) : (b))
 
73
 
 
74
#define MIN_VERS        ((u_long)0)
 
75
#define MAX_VERS        ((u_long)4294967295UL)
 
76
#define UNKNOWN         "unknown"
 
77
 
 
78
/*
 
79
 * Functions to be performed.
 
80
 */
 
81
#define NONE            0       /* no function */
 
82
#define PMAPDUMP        1       /* dump portmapper registrations */
 
83
#define TCPPING         2       /* ping TCP service */
 
84
#define UDPPING         3       /* ping UDP service */
 
85
#define BROADCAST       4       /* ping broadcast service */
 
86
#define DELETES         5       /* delete registration for the service */
 
87
#define ADDRPING        6       /* pings at the given address */
 
88
#define PROGPING        7       /* pings a program on a given host */
 
89
#define RPCBDUMP        8       /* dump rpcbind registrations */
 
90
#define RPCBDUMP_SHORT  9       /* dump rpcbind registrations - short version */
 
91
#define RPCBADDRLIST    10      /* dump addr list about one prog */
 
92
#define RPCBGETSTAT     11      /* Get statistics */
 
93
 
 
94
struct netidlist
 
95
{
 
96
  char *netid;
 
97
  struct netidlist *next;
 
98
};
 
99
 
 
100
struct verslist
 
101
{
 
102
  int vers;
 
103
  struct verslist *next;
 
104
};
 
105
 
 
106
struct rpcbdump_short
 
107
{
 
108
  u_long prog;
 
109
  struct verslist *vlist;
 
110
  struct netidlist *nlist;
 
111
  struct rpcbdump_short *next;
 
112
  char *owner;
 
113
};
 
114
 
 
115
 
 
116
#ifdef PORTMAP
 
117
static void ip_ping (u_short, char *, int, char **);
 
118
static CLIENT *clnt_com_create (struct sockaddr_in *, u_long, u_long, int *,
 
119
                                char *);
 
120
static void pmapdump (int, char **);
 
121
static void get_inet_address (struct sockaddr_in *, char *);
 
122
#endif
 
123
 
 
124
static bool_t reply_proc (void *, struct netbuf *, struct netconfig *);
 
125
static void brdcst (int, char **);
 
126
static void addrping (char *, char *, int, char **);
 
127
static void progping (char *, int, char **);
 
128
static CLIENT *clnt_addr_create (char *, struct netconfig *, u_long, u_long);
 
129
static CLIENT *clnt_rpcbind_create (char *, int, struct netbuf **);
 
130
static CLIENT *getclnthandle (char *, struct netconfig *, u_long,
 
131
                              struct netbuf **);
 
132
static int pstatus (CLIENT *, u_long, u_long);
 
133
static void rpcbdump (int, char *, int, char **);
 
134
static void rpcbgetstat (int, char **);
 
135
static void rpcbaddrlist (char *, int, char **);
 
136
static void deletereg (char *, int, char **);
 
137
static void print_rmtcallstat (int, rpcb_stat *);
 
138
static void print_getaddrstat (int, rpcb_stat *);
 
139
static void usage (void);
 
140
static u_long getprognum (char *);
 
141
static u_long getvers (char *);
 
142
static char *spaces (int);
 
143
static bool_t add_version (struct rpcbdump_short *, u_long);
 
144
static bool_t add_netid (struct rpcbdump_short *, char *);
 
145
 
 
146
int main (int argc, char **argv);
 
147
 
 
148
int
 
149
main (int argc, char **argv)
 
150
{
 
151
  register int c;
 
152
  int errflg;
 
153
  int function;
 
154
  char *netid = NULL;
 
155
  char *address = NULL;
 
156
#ifdef PORTMAP
 
157
  char *strptr;
 
158
  u_short portnum = 0;
 
159
#endif
 
160
 
 
161
  function = NONE;
 
162
  errflg = 0;
 
163
#ifdef PORTMAP
 
164
  while ((c = getopt (argc, argv, "a:bdlmn:pstT:u")) != -1)
 
165
#else
 
166
  while ((c = getopt (argc, argv, "a:bdlmn:sT:")) != -1)
 
167
#endif
 
168
    {
 
169
      switch (c)
 
170
        {
 
171
#ifdef PORTMAP
 
172
        case 'p':
 
173
          if (function != NONE)
 
174
            errflg = 1;
 
175
          else
 
176
            function = PMAPDUMP;
 
177
          break;
 
178
 
 
179
        case 't':
 
180
          if (function != NONE)
 
181
            errflg = 1;
 
182
          else
 
183
            function = TCPPING;
 
184
          break;
 
185
 
 
186
        case 'u':
 
187
          if (function != NONE)
 
188
            errflg = 1;
 
189
          else
 
190
            function = UDPPING;
 
191
          break;
 
192
 
 
193
        case 'n':
 
194
          portnum = (u_short) strtol (optarg, &strptr, 10);
 
195
          if (strptr == optarg || *strptr != '\0')
 
196
            {
 
197
              fprintf (stderr, "rpcinfo: %s is illegal port number\n",
 
198
                       optarg);
 
199
              exit (1);
 
200
            }
 
201
          break;
 
202
#endif
 
203
 
 
204
        case 'a':
 
205
          address = optarg;
 
206
          if (function != NONE)
 
207
            errflg = 1;
 
208
          else
 
209
            function = ADDRPING;
 
210
          break;
 
211
 
 
212
        case 'b':
 
213
          if (function != NONE)
 
214
            errflg = 1;
 
215
          else
 
216
            function = BROADCAST;
 
217
          break;
 
218
 
 
219
        case 'd':
 
220
          if (function != NONE)
 
221
            errflg = 1;
 
222
          else
 
223
            function = DELETES;
 
224
          break;
 
225
 
 
226
        case 'l':
 
227
          if (function != NONE)
 
228
            errflg = 1;
 
229
          else
 
230
            function = RPCBADDRLIST;
 
231
          break;
 
232
 
 
233
        case 'm':
 
234
          if (function != NONE)
 
235
            errflg = 1;
 
236
          else
 
237
            function = RPCBGETSTAT;
 
238
          break;
 
239
 
 
240
        case 's':
 
241
          if (function != NONE)
 
242
            errflg = 1;
 
243
          else
 
244
            function = RPCBDUMP_SHORT;
 
245
          break;
 
246
 
 
247
        case 'T':
 
248
          netid = optarg;
 
249
          break;
 
250
        case '?':
 
251
          errflg = 1;
 
252
          break;
 
253
        }
 
254
    }
 
255
 
 
256
  if (errflg || ((function == ADDRPING) && !netid))
 
257
    {
 
258
      usage ();
 
259
      return 1;
 
260
    }
 
261
 
 
262
  if (function == NONE)
 
263
    {
 
264
      if (argc - optind > 1)
 
265
        function = PROGPING;
 
266
      else
 
267
        function = RPCBDUMP;
 
268
    }
 
269
 
 
270
  switch (function)
 
271
    {
 
272
#ifdef PORTMAP
 
273
    case PMAPDUMP:
 
274
      if (portnum != 0)
 
275
        {
 
276
          usage ();
 
277
          return 1;
 
278
        }
 
279
      pmapdump (argc - optind, argv + optind);
 
280
      break;
 
281
 
 
282
    case UDPPING:
 
283
      ip_ping (portnum, "udp", argc - optind, argv + optind);
 
284
      break;
 
285
 
 
286
    case TCPPING:
 
287
      ip_ping (portnum, "tcp", argc - optind, argv + optind);
 
288
      break;
 
289
#endif
 
290
    case BROADCAST:
 
291
      brdcst (argc - optind, argv + optind);
 
292
      break;
 
293
    case DELETES:
 
294
      deletereg (netid, argc - optind, argv + optind);
 
295
      break;
 
296
    case ADDRPING:
 
297
      addrping (address, netid, argc - optind, argv + optind);
 
298
      break;
 
299
    case PROGPING:
 
300
      progping (netid, argc - optind, argv + optind);
 
301
      break;
 
302
    case RPCBDUMP:
 
303
    case RPCBDUMP_SHORT:
 
304
      rpcbdump (function, netid, argc - optind, argv + optind);
 
305
      break;
 
306
    case RPCBGETSTAT:
 
307
      rpcbgetstat (argc - optind, argv + optind);
 
308
      break;
 
309
    case RPCBADDRLIST:
 
310
      rpcbaddrlist (netid, argc - optind, argv + optind);
 
311
      break;
 
312
    }
 
313
  return (0);
 
314
}
 
315
 
 
316
static CLIENT *
 
317
local_rpcb (rpcprog_t prog, rpcvers_t vers)
 
318
{
 
319
#if 0
 
320
  void *localhandle;
 
321
  struct netconfig *nconf;
 
322
  CLIENT *clnt;
 
323
 
 
324
  localhandle = setnetconfig();
 
325
  while ((nconf = getnetconfig(localhandle)) != NULL) {
 
326
    if (nconf->nc_protofmly != NULL &&
 
327
        strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
 
328
      break;
 
329
  }
 
330
  if (nconf == NULL) {
 
331
    warnx("getnetconfig: %s", nc_sperror());
 
332
    return (NULL);
 
333
  }
 
334
 
 
335
  clnt = clnt_tp_create (/* "localhost"*/ NULL, prog, vers, nconf);
 
336
  endnetconfig(localhandle);
 
337
  return clnt;
 
338
#else
 
339
  struct netbuf nbuf;
 
340
  struct sockaddr_un sun;
 
341
  int sock;
 
342
 
 
343
  memset (&sun, 0, sizeof sun);
 
344
  sock = socket (AF_LOCAL, SOCK_STREAM, 0);
 
345
  if (sock < 0)
 
346
    return NULL;
 
347
 
 
348
  sun.sun_family = AF_LOCAL;
 
349
  strcpy (sun.sun_path, _PATH_RPCBINDSOCK);
 
350
  nbuf.len = SUN_LEN (&sun);
 
351
  nbuf.maxlen = sizeof (struct sockaddr_un);
 
352
  nbuf.buf = &sun;
 
353
 
 
354
  return clnt_vc_create (sock, &nbuf, prog, vers, 0, 0);
 
355
#endif
 
356
}
 
357
 
 
358
#ifdef PORTMAP
 
359
static CLIENT *
 
360
clnt_com_create (addr, prog, vers, fdp, trans)
 
361
     struct sockaddr_in *addr;
 
362
     u_long prog;
 
363
     u_long vers;
 
364
     int *fdp;
 
365
     char *trans;
 
366
{
 
367
  CLIENT *clnt;
 
368
 
 
369
  if (strcmp (trans, "tcp") == 0)
 
370
    {
 
371
      clnt = clnttcp_create (addr, prog, vers, fdp, 0, 0);
 
372
    }
 
373
  else
 
374
    {
 
375
      struct timeval to;
 
376
 
 
377
      to.tv_sec = 5;
 
378
      to.tv_usec = 0;
 
379
      clnt = clntudp_create (addr, prog, vers, to, fdp);
 
380
    }
 
381
  if (clnt == (CLIENT *) NULL)
 
382
    {
 
383
      clnt_pcreateerror ("rpcinfo");
 
384
      if (vers == MIN_VERS)
 
385
        printf ("program %lu is not available\n", prog);
 
386
      else
 
387
        printf ("program %lu version %lu is not available\n", prog, vers);
 
388
      exit (1);
 
389
    }
 
390
  return (clnt);
 
391
}
 
392
 
 
393
/*
 
394
 * If portnum is 0, then go and get the address from portmapper, which happens
 
395
 * transparently through clnt*_create(); If version number is not given, it
 
396
 * tries to find out the version number by making a call to version 0 and if
 
397
 * that fails, it obtains the high order and the low order version number. If
 
398
 * version 0 calls succeeds, it tries for MAXVERS call and repeats the same.
 
399
 */
 
400
static void
 
401
ip_ping (portnum, trans, argc, argv)
 
402
     u_short portnum;
 
403
     char *trans;
 
404
     int argc;
 
405
     char **argv;
 
406
{
 
407
  CLIENT *client;
 
408
  int fd = RPC_ANYFD;
 
409
  struct timeval to;
 
410
  struct sockaddr_in addr;
 
411
  enum clnt_stat rpc_stat;
 
412
  u_long prognum, vers, minvers, maxvers;
 
413
  struct rpc_err rpcerr;
 
414
  int failure = 0;
 
415
 
 
416
  if (argc < 2 || argc > 3)
 
417
    {
 
418
      usage ();
 
419
      exit (1);
 
420
    }
 
421
  to.tv_sec = 10;
 
422
  to.tv_usec = 0;
 
423
  prognum = getprognum (argv[1]);
 
424
  get_inet_address (&addr, argv[0]);
 
425
  if (argc == 2)
 
426
    {                           /* Version number not known */
 
427
      /*
 
428
       * A call to version 0 should fail with a program/version
 
429
       * mismatch, and give us the range of versions supported.
 
430
       */
 
431
      vers = MIN_VERS;
 
432
    }
 
433
  else
 
434
    {
 
435
      vers = getvers (argv[2]);
 
436
    }
 
437
  addr.sin_port = htons (portnum);
 
438
  client = clnt_com_create (&addr, prognum, vers, &fd, trans);
 
439
  rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
 
440
                        (char *) NULL, (xdrproc_t) xdr_void, (char *) NULL,
 
441
                        to);
 
442
  if (argc != 2)
 
443
    {
 
444
      /* Version number was known */
 
445
      if (pstatus (client, prognum, vers) < 0)
 
446
        exit (1);
 
447
      (void) CLNT_DESTROY (client);
 
448
      return;
 
449
    }
 
450
  /* Version number not known */
 
451
  (void) CLNT_CONTROL (client, CLSET_FD_NCLOSE, (char *) NULL);
 
452
  if (rpc_stat == RPC_PROGVERSMISMATCH)
 
453
    {
 
454
      clnt_geterr (client, &rpcerr);
 
455
      minvers = rpcerr.re_vers.low;
 
456
      maxvers = rpcerr.re_vers.high;
 
457
    }
 
458
  else if (rpc_stat == RPC_SUCCESS)
 
459
    {
 
460
      /*
 
461
       * Oh dear, it DOES support version 0.
 
462
       * Let's try version MAX_VERS.
 
463
       */
 
464
      (void) CLNT_DESTROY (client);
 
465
      addr.sin_port = htons (portnum);
 
466
      client = clnt_com_create (&addr, prognum, MAX_VERS, &fd, trans);
 
467
      rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
 
468
                            (char *) NULL, (xdrproc_t) xdr_void,
 
469
                            (char *) NULL, to);
 
470
      if (rpc_stat == RPC_PROGVERSMISMATCH)
 
471
        {
 
472
          clnt_geterr (client, &rpcerr);
 
473
          minvers = rpcerr.re_vers.low;
 
474
          maxvers = rpcerr.re_vers.high;
 
475
        }
 
476
      else if (rpc_stat == RPC_SUCCESS)
 
477
        {
 
478
          /*
 
479
           * It also supports version MAX_VERS.
 
480
           * Looks like we have a wise guy.
 
481
           * OK, we give them information on all
 
482
           * 4 billion versions they support...
 
483
           */
 
484
          minvers = 0;
 
485
          maxvers = MAX_VERS;
 
486
        }
 
487
      else
 
488
        {
 
489
          (void) pstatus (client, prognum, MAX_VERS);
 
490
          exit (1);
 
491
        }
 
492
    }
 
493
  else
 
494
    {
 
495
      (void) pstatus (client, prognum, (u_long) 0);
 
496
      exit (1);
 
497
    }
 
498
  (void) CLNT_DESTROY (client);
 
499
  for (vers = minvers; vers <= maxvers; vers++)
 
500
    {
 
501
      addr.sin_port = htons (portnum);
 
502
      client = clnt_com_create (&addr, prognum, vers, &fd, trans);
 
503
      rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
 
504
                            (char *) NULL, (xdrproc_t) xdr_void,
 
505
                            (char *) NULL, to);
 
506
      if (pstatus (client, prognum, vers) < 0)
 
507
        failure = 1;
 
508
      (void) CLNT_DESTROY (client);
 
509
    }
 
510
  if (failure)
 
511
    exit (1);
 
512
  (void) close (fd);
 
513
  return;
 
514
}
 
515
 
 
516
/*
 
517
 * Dump all the portmapper registerations
 
518
 */
 
519
static void
 
520
pmapdump (argc, argv)
 
521
     int argc;
 
522
     char **argv;
 
523
{
 
524
  struct sockaddr_in server_addr;
 
525
  struct pmaplist *head = NULL;
 
526
  int socket = RPC_ANYSOCK;
 
527
  struct timeval minutetimeout;
 
528
  register CLIENT *client;
 
529
  struct rpcent *rpc;
 
530
  enum clnt_stat clnt_st;
 
531
  struct rpc_err err;
 
532
  char *host = NULL;
 
533
 
 
534
  if (argc > 1)
 
535
    {
 
536
      usage ();
 
537
      exit (1);
 
538
    }
 
539
  if (argc == 1)
 
540
    {
 
541
      host = argv[0];
 
542
      get_inet_address (&server_addr, host);
 
543
      server_addr.sin_port = htons (PMAPPORT);
 
544
      client = clnttcp_create (&server_addr, PMAPPROG, PMAPVERS,
 
545
                               &socket, 50, 500);
 
546
    }
 
547
  else
 
548
    client = local_rpcb (PMAPPROG, PMAPVERS);
 
549
 
 
550
  if (client == NULL)
 
551
    {
 
552
      if (rpc_createerr.cf_stat == RPC_TLIERROR)
 
553
        {
 
554
          /*
 
555
           * "Misc. TLI error" is not too helpful. Most likely
 
556
           * the connection to the remote server timed out, so
 
557
           * this error is at least less perplexing.
 
558
           */
 
559
          rpc_createerr.cf_stat = RPC_PMAPFAILURE;
 
560
          rpc_createerr.cf_error.re_status = RPC_FAILED;
 
561
        }
 
562
      clnt_pcreateerror ("rpcinfo: can't contact portmapper");
 
563
      exit (1);
 
564
    }
 
565
 
 
566
  minutetimeout.tv_sec = 60;
 
567
  minutetimeout.tv_usec = 0;
 
568
 
 
569
  clnt_st = CLNT_CALL (client, PMAPPROC_DUMP, (xdrproc_t) xdr_void,
 
570
                       NULL, (xdrproc_t) xdr_pmaplist_ptr, (char *) &head,
 
571
                       minutetimeout);
 
572
  if (clnt_st != RPC_SUCCESS)
 
573
    {
 
574
      if ((clnt_st == RPC_PROGVERSMISMATCH) || (clnt_st == RPC_PROGUNAVAIL))
 
575
        {
 
576
          CLNT_GETERR (client, &err);
 
577
          if (err.re_vers.low > PMAPVERS)
 
578
            fprintf (stderr,
 
579
                     "%s does not support portmapper.  Try rpcinfo %s instead\n",
 
580
                     host, host);
 
581
          exit (1);
 
582
        }
 
583
      clnt_perror (client, "rpcinfo: can't contact portmapper");
 
584
      exit (1);
 
585
    }
 
586
  if (head == NULL)
 
587
    {
 
588
      printf ("No remote programs registered.\n");
 
589
    }
 
590
  else
 
591
    {
 
592
      printf ("   program vers proto   port  service\n");
 
593
      for (; head != NULL; head = head->pml_next)
 
594
        {
 
595
          printf ("%10ld%5ld", head->pml_map.pm_prog, head->pml_map.pm_vers);
 
596
          if (head->pml_map.pm_prot == IPPROTO_UDP)
 
597
            printf ("%6s", "udp");
 
598
          else if (head->pml_map.pm_prot == IPPROTO_TCP)
 
599
            printf ("%6s", "tcp");
 
600
          else
 
601
            printf ("%6ld", head->pml_map.pm_prot);
 
602
          printf ("%7ld", head->pml_map.pm_port);
 
603
          rpc = getrpcbynumber (head->pml_map.pm_prog);
 
604
          if (rpc)
 
605
            printf ("  %s\n", rpc->r_name);
 
606
          else
 
607
            printf ("\n");
 
608
        }
 
609
    }
 
610
}
 
611
 
 
612
static void
 
613
get_inet_address (addr, host)
 
614
     struct sockaddr_in *addr;
 
615
     char *host;
 
616
{
 
617
  struct netconfig *nconf;
 
618
  struct addrinfo hints, *res;
 
619
  int error;
 
620
 
 
621
  (void) memset ((char *) addr, 0, sizeof (*addr));
 
622
  addr->sin_addr.s_addr = inet_addr (host);
 
623
  if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0)
 
624
    {
 
625
      if ((nconf = __rpc_getconfip ("udp")) == NULL &&
 
626
          (nconf = __rpc_getconfip ("tcp")) == NULL)
 
627
        {
 
628
          fprintf (stderr, "rpcinfo: couldn't find a suitable transport\n");
 
629
          exit (1);
 
630
        }
 
631
      else
 
632
        {
 
633
          memset (&hints, 0, sizeof hints);
 
634
          hints.ai_family = AF_INET;
 
635
          if ((error = getaddrinfo (host, "rpcbind", &hints, &res)) != 0 &&
 
636
              (error = getaddrinfo (host, "portmapper", &hints, &res)) != 0)
 
637
            {
 
638
              fprintf (stderr, "rpcinfo: %s: %s\n",
 
639
                       host, gai_strerror (error));
 
640
              exit (1);
 
641
            }
 
642
          else
 
643
            {
 
644
              memcpy (addr, res->ai_addr, res->ai_addrlen);
 
645
              freeaddrinfo (res);
 
646
            }
 
647
          (void) freenetconfigent (nconf);
 
648
        }
 
649
    }
 
650
  else
 
651
    {
 
652
      addr->sin_family = AF_INET;
 
653
    }
 
654
}
 
655
#endif /* PORTMAP */
 
656
 
 
657
static int
 
658
sa_len(struct sockaddr *sa)
 
659
{
 
660
    socklen_t salen;
 
661
 
 
662
    switch (sa->sa_family)
 
663
    {
 
664
        case AF_LOCAL:
 
665
            salen = sizeof (struct sockaddr_un);
 
666
            break;
 
667
        case AF_INET:
 
668
            salen = sizeof (struct sockaddr_in);
 
669
            break;
 
670
        case AF_INET6:
 
671
            salen = sizeof (struct sockaddr_in6);
 
672
            break;
 
673
        default:
 
674
            salen = 0;
 
675
            break;
 
676
    }
 
677
    return salen;
 
678
}
 
679
 
 
680
/*
 
681
 * reply_proc collects replies from the broadcast.
 
682
 * to get a unique list of responses the output of rpcinfo should
 
683
 * be piped through sort(1) and then uniq(1).
 
684
 */
 
685
 
 
686
 /*ARGSUSED*/ static bool_t
 
687
reply_proc (res, who, nconf)
 
688
     void *res;                 /* Nothing comes back */
 
689
     struct netbuf *who;        /* Who sent us the reply */
 
690
     struct netconfig *nconf;   /* On which transport the reply came */
 
691
{
 
692
  char *uaddr;
 
693
  char hostbuf[NI_MAXHOST];
 
694
  char *hostname;
 
695
  struct sockaddr *sa = (struct sockaddr *) who->buf;
 
696
 
 
697
  if (getnameinfo (sa, sa_len (sa), hostbuf, NI_MAXHOST, NULL, 0, 0))
 
698
    {
 
699
      hostname = UNKNOWN;
 
700
    }
 
701
  else
 
702
    {
 
703
      hostname = hostbuf;
 
704
    }
 
705
  if (!(uaddr = taddr2uaddr (nconf, who)))
 
706
    {
 
707
      uaddr = UNKNOWN;
 
708
    }
 
709
  printf ("%s\t%s\n", uaddr, hostname);
 
710
  if (strcmp (uaddr, UNKNOWN))
 
711
    free ((char *) uaddr);
 
712
  return (FALSE);
 
713
}
 
714
 
 
715
static void
 
716
brdcst (argc, argv)
 
717
     int argc;
 
718
     char **argv;
 
719
{
 
720
  enum clnt_stat rpc_stat;
 
721
  u_long prognum, vers;
 
722
 
 
723
  if (argc != 2)
 
724
    {
 
725
      usage ();
 
726
      exit (1);
 
727
    }
 
728
  prognum = getprognum (argv[0]);
 
729
  vers = getvers (argv[1]);
 
730
  rpc_stat = rpc_broadcast (prognum, vers, NULLPROC,
 
731
                            (xdrproc_t) xdr_void, (char *) NULL,
 
732
                            (xdrproc_t) xdr_void, (char *) NULL,
 
733
                            (resultproc_t) reply_proc, NULL);
 
734
  if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT))
 
735
    {
 
736
      fprintf (stderr, "rpcinfo: broadcast failed: %s\n",
 
737
               clnt_sperrno (rpc_stat));
 
738
      exit (1);
 
739
    }
 
740
  exit (0);
 
741
}
 
742
 
 
743
static bool_t
 
744
add_version (rs, vers)
 
745
     struct rpcbdump_short *rs;
 
746
     u_long vers;
 
747
{
 
748
  struct verslist *vl;
 
749
 
 
750
  for (vl = rs->vlist; vl; vl = vl->next)
 
751
    if (vl->vers == vers)
 
752
      break;
 
753
  if (vl)
 
754
    return (TRUE);
 
755
  vl = (struct verslist *) malloc (sizeof (struct verslist));
 
756
  if (vl == NULL)
 
757
    return (FALSE);
 
758
  vl->vers = vers;
 
759
  vl->next = rs->vlist;
 
760
  rs->vlist = vl;
 
761
  return (TRUE);
 
762
}
 
763
 
 
764
static bool_t
 
765
add_netid (rs, netid)
 
766
     struct rpcbdump_short *rs;
 
767
     char *netid;
 
768
{
 
769
  struct netidlist *nl;
 
770
 
 
771
  for (nl = rs->nlist; nl; nl = nl->next)
 
772
    if (strcmp (nl->netid, netid) == 0)
 
773
      break;
 
774
  if (nl)
 
775
    return (TRUE);
 
776
  nl = (struct netidlist *) malloc (sizeof (struct netidlist));
 
777
  if (nl == NULL)
 
778
    return (FALSE);
 
779
  nl->netid = netid;
 
780
  nl->next = rs->nlist;
 
781
  rs->nlist = nl;
 
782
  return (TRUE);
 
783
}
 
784
 
 
785
static void
 
786
rpcbdump (dumptype, netid, argc, argv)
 
787
     int dumptype;
 
788
     char *netid;
 
789
     int argc;
 
790
     char **argv;
 
791
{
 
792
  rpcblist_ptr head = NULL;
 
793
  struct timeval minutetimeout;
 
794
  register CLIENT *client;
 
795
  struct rpcent *rpc;
 
796
  char *host;
 
797
  struct netidlist *nl;
 
798
  struct verslist *vl;
 
799
  struct rpcbdump_short *rs, *rs_tail = NULL;
 
800
  char buf[256];
 
801
  enum clnt_stat clnt_st;
 
802
  struct rpc_err err;
 
803
  struct rpcbdump_short *rs_head = NULL;
 
804
 
 
805
  if (argc > 1)
 
806
    {
 
807
      usage ();
 
808
      exit (1);
 
809
    }
 
810
  if (argc == 1)
 
811
    {
 
812
      host = argv[0];
 
813
      if (netid == NULL)
 
814
        {
 
815
          client = clnt_rpcbind_create (host, RPCBVERS, NULL);
 
816
        }
 
817
      else
 
818
        {
 
819
          struct netconfig *nconf;
 
820
 
 
821
          nconf = getnetconfigent (netid);
 
822
          if (nconf == NULL)
 
823
            {
 
824
              nc_perror ("rpcinfo: invalid transport");
 
825
              exit (1);
 
826
            }
 
827
          client = getclnthandle (host, nconf, RPCBVERS, NULL);
 
828
          if (nconf)
 
829
            (void) freenetconfigent (nconf);
 
830
        }
 
831
    }
 
832
  else
 
833
    client = local_rpcb (PMAPPROG, RPCBVERS);
 
834
 
 
835
  if (client == (CLIENT *) NULL)
 
836
    {
 
837
      clnt_pcreateerror ("rpcinfo: can't contact rpcbind");
 
838
      exit (1);
 
839
    }
 
840
  minutetimeout.tv_sec = 60;
 
841
  minutetimeout.tv_usec = 0;
 
842
  clnt_st = CLNT_CALL (client, RPCBPROC_DUMP, (xdrproc_t) xdr_void,
 
843
                       NULL, (xdrproc_t) xdr_rpcblist_ptr, (char *) &head,
 
844
                       minutetimeout);
 
845
  if (clnt_st != RPC_SUCCESS)
 
846
    {
 
847
      if ((clnt_st == RPC_PROGVERSMISMATCH) || (clnt_st == RPC_PROGUNAVAIL))
 
848
        {
 
849
          int vers;
 
850
 
 
851
          CLNT_GETERR (client, &err);
 
852
          if (err.re_vers.low == RPCBVERS4)
 
853
            {
 
854
              vers = RPCBVERS4;
 
855
              clnt_control (client, CLSET_VERS, (char *) &vers);
 
856
              clnt_st = CLNT_CALL (client, RPCBPROC_DUMP,
 
857
                                   (xdrproc_t) xdr_void, NULL,
 
858
                                   (xdrproc_t) xdr_rpcblist_ptr,
 
859
                                   (char *) &head, minutetimeout);
 
860
              if (clnt_st != RPC_SUCCESS)
 
861
                goto failed;
 
862
            }
 
863
          else
 
864
            {
 
865
              if (err.re_vers.high == PMAPVERS)
 
866
                {
 
867
                  int high, low;
 
868
                  struct pmaplist *pmaphead = NULL;
 
869
                  rpcblist_ptr list, prev = NULL;
 
870
 
 
871
                  vers = PMAPVERS;
 
872
                  clnt_control (client, CLSET_VERS, (char *) &vers);
 
873
                  clnt_st = CLNT_CALL (client, PMAPPROC_DUMP,
 
874
                                       (xdrproc_t) xdr_void, NULL,
 
875
                                       (xdrproc_t) xdr_pmaplist_ptr,
 
876
                                       (char *) &pmaphead, minutetimeout);
 
877
                  if (clnt_st != RPC_SUCCESS)
 
878
                    goto failed;
 
879
                  /*
 
880
                   * convert to rpcblist_ptr format
 
881
                   */
 
882
                  for (head = NULL; pmaphead != NULL;
 
883
                       pmaphead = pmaphead->pml_next)
 
884
                    {
 
885
                      list = (rpcblist *) malloc (sizeof (rpcblist));
 
886
                      if (list == NULL)
 
887
                        goto error;
 
888
                      if (head == NULL)
 
889
                        head = list;
 
890
                      else
 
891
                        prev->rpcb_next = (rpcblist_ptr) list;
 
892
 
 
893
                      list->rpcb_next = NULL;
 
894
                      list->rpcb_map.r_prog = pmaphead->pml_map.pm_prog;
 
895
                      list->rpcb_map.r_vers = pmaphead->pml_map.pm_vers;
 
896
                      if (pmaphead->pml_map.pm_prot == IPPROTO_UDP)
 
897
                        list->rpcb_map.r_netid = "udp";
 
898
                      else if (pmaphead->pml_map.pm_prot == IPPROTO_TCP)
 
899
                        list->rpcb_map.r_netid = "tcp";
 
900
                      else
 
901
                        {
 
902
#define MAXLONG_AS_STRING       "2147483648"
 
903
                          list->rpcb_map.r_netid =
 
904
                            malloc (strlen (MAXLONG_AS_STRING) + 1);
 
905
                          if (list->rpcb_map.r_netid == NULL)
 
906
                            goto error;
 
907
                          sprintf (list->rpcb_map.r_netid, "%6ld",
 
908
                                   pmaphead->pml_map.pm_prot);
 
909
                        }
 
910
                      list->rpcb_map.r_owner = UNKNOWN;
 
911
                      low = pmaphead->pml_map.pm_port & 0xff;
 
912
                      high = (pmaphead->pml_map.pm_port >> 8) & 0xff;
 
913
                      list->rpcb_map.r_addr = strdup ("0.0.0.0.XXX.XXX");
 
914
                      sprintf (&list->rpcb_map.r_addr[8], "%d.%d", high, low);
 
915
                      prev = list;
 
916
                    }
 
917
                }
 
918
            }
 
919
        }
 
920
      else
 
921
        {                       /* any other error */
 
922
        failed:
 
923
          clnt_perror (client, "rpcinfo: can't contact rpcbind: ");
 
924
          exit (1);
 
925
        }
 
926
    }
 
927
  if (head == NULL)
 
928
    {
 
929
      printf ("No remote programs registered.\n");
 
930
    }
 
931
  else if (dumptype == RPCBDUMP)
 
932
    {
 
933
      printf
 
934
        ("   program version netid     address                service    owner\n");
 
935
      for (; head != NULL; head = head->rpcb_next)
 
936
        {
 
937
          printf ("%10u%5u    ",
 
938
                  head->rpcb_map.r_prog, head->rpcb_map.r_vers);
 
939
          printf ("%-9s ", head->rpcb_map.r_netid);
 
940
          printf ("%-22s", head->rpcb_map.r_addr);
 
941
          rpc = getrpcbynumber (head->rpcb_map.r_prog);
 
942
          if (rpc)
 
943
            printf (" %-10s", rpc->r_name);
 
944
          else
 
945
            printf (" %-10s", "-");
 
946
          printf (" %s\n", head->rpcb_map.r_owner);
 
947
        }
 
948
    }
 
949
  else if (dumptype == RPCBDUMP_SHORT)
 
950
    {
 
951
      for (; head != NULL; head = head->rpcb_next)
 
952
        {
 
953
          for (rs = rs_head; rs; rs = rs->next)
 
954
            if (head->rpcb_map.r_prog == rs->prog)
 
955
              break;
 
956
          if (rs == NULL)
 
957
            {
 
958
              rs = (struct rpcbdump_short *)
 
959
                malloc (sizeof (struct rpcbdump_short));
 
960
              if (rs == NULL)
 
961
                goto error;
 
962
              rs->next = NULL;
 
963
              if (rs_head == NULL)
 
964
                {
 
965
                  rs_head = rs;
 
966
                  rs_tail = rs;
 
967
                }
 
968
              else
 
969
                {
 
970
                  rs_tail->next = rs;
 
971
                  rs_tail = rs;
 
972
                }
 
973
              rs->prog = head->rpcb_map.r_prog;
 
974
              rs->owner = head->rpcb_map.r_owner;
 
975
              rs->nlist = NULL;
 
976
              rs->vlist = NULL;
 
977
            }
 
978
          if (add_version (rs, head->rpcb_map.r_vers) == FALSE)
 
979
            goto error;
 
980
          if (add_netid (rs, head->rpcb_map.r_netid) == FALSE)
 
981
            goto error;
 
982
        }
 
983
      printf
 
984
        ("   program version(s) netid(s)                         service     owner\n");
 
985
      for (rs = rs_head; rs; rs = rs->next)
 
986
        {
 
987
          char *p = buf;
 
988
 
 
989
          printf ("%10ld  ", rs->prog);
 
990
          for (vl = rs->vlist; vl; vl = vl->next)
 
991
            {
 
992
              sprintf (p, "%d", vl->vers);
 
993
              p = p + strlen (p);
 
994
              if (vl->next)
 
995
                sprintf (p++, ",");
 
996
            }
 
997
          printf ("%-10s", buf);
 
998
          buf[0] = '\0';
 
999
          for (nl = rs->nlist; nl; nl = nl->next)
 
1000
            {
 
1001
              strcat (buf, nl->netid);
 
1002
              if (nl->next)
 
1003
                strcat (buf, ",");
 
1004
            }
 
1005
          printf ("%-32s", buf);
 
1006
          rpc = getrpcbynumber (rs->prog);
 
1007
          if (rpc)
 
1008
            printf (" %-11s", rpc->r_name);
 
1009
          else
 
1010
            printf (" %-11s", "-");
 
1011
          printf (" %s\n", rs->owner);
 
1012
        }
 
1013
    }
 
1014
  clnt_destroy (client);
 
1015
  return;
 
1016
error:fprintf (stderr, "rpcinfo: no memory\n");
 
1017
  return;
 
1018
}
 
1019
 
 
1020
static char nullstring[] = "\000";
 
1021
 
 
1022
static void
 
1023
rpcbaddrlist (netid, argc, argv)
 
1024
     char *netid;
 
1025
     int argc;
 
1026
     char **argv;
 
1027
{
 
1028
  rpcb_entry_list_ptr head = NULL;
 
1029
  struct timeval minutetimeout;
 
1030
  register CLIENT *client;
 
1031
  struct rpcent *rpc;
 
1032
  char *host;
 
1033
  RPCB parms;
 
1034
  struct netbuf *targaddr;
 
1035
 
 
1036
  if (argc != 3)
 
1037
    {
 
1038
      usage ();
 
1039
      exit (1);
 
1040
    }
 
1041
  host = argv[0];
 
1042
  if (netid == NULL)
 
1043
    {
 
1044
      client = clnt_rpcbind_create (host, RPCBVERS4, &targaddr);
 
1045
    }
 
1046
  else
 
1047
    {
 
1048
      struct netconfig *nconf;
 
1049
 
 
1050
      nconf = getnetconfigent (netid);
 
1051
      if (nconf == NULL)
 
1052
        {
 
1053
          nc_perror ("rpcinfo: invalid transport");
 
1054
          exit (1);
 
1055
        }
 
1056
      client = getclnthandle (host, nconf, RPCBVERS4, &targaddr);
 
1057
      if (nconf)
 
1058
        (void) freenetconfigent (nconf);
 
1059
    }
 
1060
  if (client == (CLIENT *) NULL)
 
1061
    {
 
1062
      clnt_pcreateerror ("rpcinfo: can't contact rpcbind");
 
1063
      exit (1);
 
1064
    }
 
1065
  minutetimeout.tv_sec = 60;
 
1066
  minutetimeout.tv_usec = 0;
 
1067
 
 
1068
  parms.r_prog = getprognum (argv[1]);
 
1069
  parms.r_vers = getvers (argv[2]);
 
1070
  parms.r_netid = client->cl_netid;
 
1071
  if (targaddr == NULL)
 
1072
    {
 
1073
      parms.r_addr = nullstring;        /* for XDRing */
 
1074
    }
 
1075
  else
 
1076
    {
 
1077
      /*
 
1078
       * We also send the remote system the address we
 
1079
       * used to contact it in case it can help it
 
1080
       * connect back with us
 
1081
       */
 
1082
      struct netconfig *nconf;
 
1083
 
 
1084
      nconf = getnetconfigent (client->cl_netid);
 
1085
      if (nconf != NULL)
 
1086
        {
 
1087
          parms.r_addr = taddr2uaddr (nconf, targaddr);
 
1088
          if (parms.r_addr == NULL)
 
1089
            parms.r_addr = nullstring;
 
1090
          freenetconfigent (nconf);
 
1091
        }
 
1092
      else
 
1093
        {
 
1094
          parms.r_addr = nullstring;    /* for XDRing */
 
1095
        }
 
1096
      free (targaddr->buf);
 
1097
      free (targaddr);
 
1098
    }
 
1099
  parms.r_owner = nullstring;
 
1100
 
 
1101
  if (CLNT_CALL (client, RPCBPROC_GETADDRLIST, (xdrproc_t) xdr_rpcb,
 
1102
                 (char *) &parms, (xdrproc_t) xdr_rpcb_entry_list_ptr,
 
1103
                 (char *) &head, minutetimeout) != RPC_SUCCESS)
 
1104
    {
 
1105
      clnt_perror (client, "rpcinfo: can't contact rpcbind: ");
 
1106
      exit (1);
 
1107
    }
 
1108
  if (head == NULL)
 
1109
    {
 
1110
      printf ("No remote programs registered.\n");
 
1111
    }
 
1112
  else
 
1113
    {
 
1114
      printf
 
1115
        ("   program vers  tp_family/name/class    address\t\t  service\n");
 
1116
      for (; head != NULL; head = head->rpcb_entry_next)
 
1117
        {
 
1118
          rpcb_entry *re;
 
1119
          char buf[128];
 
1120
 
 
1121
          re = &head->rpcb_entry_map;
 
1122
          printf ("%10u%3u    ", parms.r_prog, parms.r_vers);
 
1123
          sprintf (buf, "%s/%s/%s ",
 
1124
                   re->r_nc_protofmly, re->r_nc_proto,
 
1125
                   re->r_nc_semantics == NC_TPI_CLTS ? "clts" :
 
1126
                   re->r_nc_semantics == NC_TPI_COTS ? "cots" : "cots_ord");
 
1127
          printf ("%-24s", buf);
 
1128
          printf ("%-24s", re->r_maddr);
 
1129
          rpc = getrpcbynumber (parms.r_prog);
 
1130
          if (rpc)
 
1131
            printf (" %-13s", rpc->r_name);
 
1132
          else
 
1133
            printf (" %-13s", "-");
 
1134
          printf ("\n");
 
1135
        }
 
1136
    }
 
1137
  clnt_destroy (client);
 
1138
  return;
 
1139
}
 
1140
 
 
1141
/*
 
1142
 * monitor rpcbind
 
1143
 */
 
1144
static void
 
1145
rpcbgetstat (argc, argv)
 
1146
     int argc;
 
1147
     char **argv;
 
1148
{
 
1149
  rpcb_stat_byvers inf;
 
1150
  struct timeval minutetimeout;
 
1151
  register CLIENT *client;
 
1152
  char *host;
 
1153
  int i, j;
 
1154
  rpcbs_addrlist *pa;
 
1155
  rpcbs_rmtcalllist *pr;
 
1156
  int cnt, flen;
 
1157
#define MAXFIELD        64
 
1158
  char fieldbuf[MAXFIELD];
 
1159
#define MAXLINE         256
 
1160
  char linebuf[MAXLINE];
 
1161
  char *cp, *lp;
 
1162
  char *pmaphdr[] = {
 
1163
    "NULL", "SET", "UNSET", "GETPORT",
 
1164
    "DUMP", "CALLIT"
 
1165
  };
 
1166
  char *rpcb3hdr[] = {
 
1167
    "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
 
1168
    "U2T", "T2U"
 
1169
  };
 
1170
  char *rpcb4hdr[] = {
 
1171
    "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
 
1172
    "U2T", "T2U", "VERADDR", "INDRECT", "GETLIST", "GETSTAT"
 
1173
  };
 
1174
 
 
1175
#define TABSTOP 8
 
1176
 
 
1177
  if (argc >= 1)
 
1178
    {
 
1179
      host = argv[0];
 
1180
      client = clnt_rpcbind_create (host, RPCBVERS4, NULL);
 
1181
    }
 
1182
  else
 
1183
    client = local_rpcb (PMAPPROG, RPCBVERS4);
 
1184
  if (client == (CLIENT *) NULL)
 
1185
    {
 
1186
      clnt_pcreateerror ("rpcinfo: can't contact rpcbind");
 
1187
      exit (1);
 
1188
    }
 
1189
  minutetimeout.tv_sec = 60;
 
1190
  minutetimeout.tv_usec = 0;
 
1191
  memset ((char *) &inf, 0, sizeof (rpcb_stat_byvers));
 
1192
  if (CLNT_CALL (client, RPCBPROC_GETSTAT, (xdrproc_t) xdr_void, NULL,
 
1193
                 (xdrproc_t) xdr_rpcb_stat_byvers, (char *) &inf,
 
1194
                 minutetimeout) != RPC_SUCCESS)
 
1195
    {
 
1196
      clnt_perror (client, "rpcinfo: can't contact rpcbind: ");
 
1197
      exit (1);
 
1198
    }
 
1199
  printf ("PORTMAP (version 2) statistics\n");
 
1200
  lp = linebuf;
 
1201
  for (i = 0; i <= rpcb_highproc_2; i++)
 
1202
    {
 
1203
      fieldbuf[0] = '\0';
 
1204
      switch (i)
 
1205
        {
 
1206
        case PMAPPROC_SET:
 
1207
          sprintf (fieldbuf, "%d/", inf[RPCBVERS_2_STAT].setinfo);
 
1208
          break;
 
1209
        case PMAPPROC_UNSET:
 
1210
          sprintf (fieldbuf, "%d/", inf[RPCBVERS_2_STAT].unsetinfo);
 
1211
          break;
 
1212
        case PMAPPROC_GETPORT:
 
1213
          cnt = 0;
 
1214
          for (pa = inf[RPCBVERS_2_STAT].addrinfo; pa; pa = pa->next)
 
1215
            cnt += pa->success;
 
1216
          sprintf (fieldbuf, "%d/", cnt);
 
1217
          break;
 
1218
        case PMAPPROC_CALLIT:
 
1219
          cnt = 0;
 
1220
          for (pr = inf[RPCBVERS_2_STAT].rmtinfo; pr; pr = pr->next)
 
1221
            cnt += pr->success;
 
1222
          sprintf (fieldbuf, "%d/", cnt);
 
1223
          break;
 
1224
        default:
 
1225
          break;                /* For the remaining ones */
 
1226
        }
 
1227
      cp = &fieldbuf[0] + strlen (fieldbuf);
 
1228
      sprintf (cp, "%d", inf[RPCBVERS_2_STAT].info[i]);
 
1229
      flen = strlen (fieldbuf);
 
1230
      printf ("%s%s", pmaphdr[i],
 
1231
              spaces ((TABSTOP * (1 + flen / TABSTOP))
 
1232
                      - strlen (pmaphdr[i])));
 
1233
      sprintf (lp, "%s%s", fieldbuf,
 
1234
               spaces (cnt = ((TABSTOP * (1 + flen / TABSTOP)) - flen)));
 
1235
      lp += (flen + cnt);
 
1236
    }
 
1237
  printf ("\n%s\n\n", linebuf);
 
1238
 
 
1239
  if (inf[RPCBVERS_2_STAT].info[PMAPPROC_CALLIT])
 
1240
    {
 
1241
      printf ("PMAP_RMTCALL call statistics\n");
 
1242
      print_rmtcallstat (RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
 
1243
      printf ("\n");
 
1244
    }
 
1245
 
 
1246
  if (inf[RPCBVERS_2_STAT].info[PMAPPROC_GETPORT])
 
1247
    {
 
1248
      printf ("PMAP_GETPORT call statistics\n");
 
1249
      print_getaddrstat (RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
 
1250
      printf ("\n");
 
1251
    }
 
1252
 
 
1253
  printf ("RPCBIND (version 3) statistics\n");
 
1254
  lp = linebuf;
 
1255
  for (i = 0; i <= rpcb_highproc_3; i++)
 
1256
    {
 
1257
      fieldbuf[0] = '\0';
 
1258
      switch (i)
 
1259
        {
 
1260
        case RPCBPROC_SET:
 
1261
          sprintf (fieldbuf, "%d/", inf[RPCBVERS_3_STAT].setinfo);
 
1262
          break;
 
1263
        case RPCBPROC_UNSET:
 
1264
          sprintf (fieldbuf, "%d/", inf[RPCBVERS_3_STAT].unsetinfo);
 
1265
          break;
 
1266
        case RPCBPROC_GETADDR:
 
1267
          cnt = 0;
 
1268
          for (pa = inf[RPCBVERS_3_STAT].addrinfo; pa; pa = pa->next)
 
1269
            cnt += pa->success;
 
1270
          sprintf (fieldbuf, "%d/", cnt);
 
1271
          break;
 
1272
        case RPCBPROC_CALLIT:
 
1273
          cnt = 0;
 
1274
          for (pr = inf[RPCBVERS_3_STAT].rmtinfo; pr; pr = pr->next)
 
1275
            cnt += pr->success;
 
1276
          sprintf (fieldbuf, "%d/", cnt);
 
1277
          break;
 
1278
        default:
 
1279
          break;                /* For the remaining ones */
 
1280
        }
 
1281
      cp = &fieldbuf[0] + strlen (fieldbuf);
 
1282
      sprintf (cp, "%d", inf[RPCBVERS_3_STAT].info[i]);
 
1283
      flen = strlen (fieldbuf);
 
1284
      printf ("%s%s", rpcb3hdr[i],
 
1285
              spaces ((TABSTOP * (1 + flen / TABSTOP))
 
1286
                      - strlen (rpcb3hdr[i])));
 
1287
      sprintf (lp, "%s%s", fieldbuf,
 
1288
               spaces (cnt = ((TABSTOP * (1 + flen / TABSTOP)) - flen)));
 
1289
      lp += (flen + cnt);
 
1290
    }
 
1291
  printf ("\n%s\n\n", linebuf);
 
1292
 
 
1293
  if (inf[RPCBVERS_3_STAT].info[RPCBPROC_CALLIT])
 
1294
    {
 
1295
      printf ("RPCB_RMTCALL (version 3) call statistics\n");
 
1296
      print_rmtcallstat (RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
 
1297
      printf ("\n");
 
1298
    }
 
1299
 
 
1300
  if (inf[RPCBVERS_3_STAT].info[RPCBPROC_GETADDR])
 
1301
    {
 
1302
      printf ("RPCB_GETADDR (version 3) call statistics\n");
 
1303
      print_getaddrstat (RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
 
1304
      printf ("\n");
 
1305
    }
 
1306
 
 
1307
  printf ("RPCBIND (version 4) statistics\n");
 
1308
 
 
1309
  for (j = 0; j <= 9; j += 9)
 
1310
    {                           /* Just two iterations for printing */
 
1311
      lp = linebuf;
 
1312
      for (i = j; i <= max (8, rpcb_highproc_4 - 9 + j); i++)
 
1313
        {
 
1314
          fieldbuf[0] = '\0';
 
1315
          switch (i)
 
1316
            {
 
1317
            case RPCBPROC_SET:
 
1318
              sprintf (fieldbuf, "%d/", inf[RPCBVERS_4_STAT].setinfo);
 
1319
              break;
 
1320
            case RPCBPROC_UNSET:
 
1321
              sprintf (fieldbuf, "%d/", inf[RPCBVERS_4_STAT].unsetinfo);
 
1322
              break;
 
1323
            case RPCBPROC_GETADDR:
 
1324
              cnt = 0;
 
1325
              for (pa = inf[RPCBVERS_4_STAT].addrinfo; pa; pa = pa->next)
 
1326
                cnt += pa->success;
 
1327
              sprintf (fieldbuf, "%d/", cnt);
 
1328
              break;
 
1329
            case RPCBPROC_CALLIT:
 
1330
              cnt = 0;
 
1331
              for (pr = inf[RPCBVERS_4_STAT].rmtinfo; pr; pr = pr->next)
 
1332
                cnt += pr->success;
 
1333
              sprintf (fieldbuf, "%d/", cnt);
 
1334
              break;
 
1335
            default:
 
1336
              break;            /* For the remaining ones */
 
1337
            }
 
1338
          cp = &fieldbuf[0] + strlen (fieldbuf);
 
1339
          /*
 
1340
           * XXX: We also add RPCBPROC_GETADDRLIST queries to
 
1341
           * RPCB_GETADDR because rpcbind includes the
 
1342
           * RPCB_GETADDRLIST successes in RPCB_GETADDR.
 
1343
           */
 
1344
          if (i != RPCBPROC_GETADDR)
 
1345
            sprintf (cp, "%d", inf[RPCBVERS_4_STAT].info[i]);
 
1346
          else
 
1347
            sprintf (cp, "%d", inf[RPCBVERS_4_STAT].info[i] +
 
1348
                     inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDRLIST]);
 
1349
          flen = strlen (fieldbuf);
 
1350
          printf ("%s%s", rpcb4hdr[i],
 
1351
                  spaces ((TABSTOP * (1 + flen / TABSTOP))
 
1352
                          - strlen (rpcb4hdr[i])));
 
1353
          sprintf (lp, "%s%s", fieldbuf,
 
1354
                   spaces (cnt = ((TABSTOP * (1 + flen / TABSTOP)) - flen)));
 
1355
          lp += (flen + cnt);
 
1356
        }
 
1357
      printf ("\n%s\n", linebuf);
 
1358
    }
 
1359
 
 
1360
  if (inf[RPCBVERS_4_STAT].info[RPCBPROC_CALLIT] ||
 
1361
      inf[RPCBVERS_4_STAT].info[RPCBPROC_INDIRECT])
 
1362
    {
 
1363
      printf ("\n");
 
1364
      printf ("RPCB_RMTCALL (version 4) call statistics\n");
 
1365
      print_rmtcallstat (RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
 
1366
    }
 
1367
 
 
1368
  if (inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDR])
 
1369
    {
 
1370
      printf ("\n");
 
1371
      printf ("RPCB_GETADDR (version 4) call statistics\n");
 
1372
      print_getaddrstat (RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
 
1373
    }
 
1374
  clnt_destroy (client);
 
1375
}
 
1376
 
 
1377
/*
 
1378
 * Delete registeration for this (prog, vers, netid)
 
1379
 */
 
1380
static void
 
1381
deletereg (netid, argc, argv)
 
1382
     char *netid;
 
1383
     int argc;
 
1384
     char **argv;
 
1385
{
 
1386
  struct netconfig *nconf = NULL;
 
1387
 
 
1388
  if (argc != 2)
 
1389
    {
 
1390
      usage ();
 
1391
      exit (1);
 
1392
    }
 
1393
  if (netid)
 
1394
    {
 
1395
      nconf = getnetconfigent (netid);
 
1396
      if (nconf == NULL)
 
1397
        {
 
1398
          fprintf (stderr, "rpcinfo: netid %s not supported\n", netid);
 
1399
          exit (1);
 
1400
        }
 
1401
    }
 
1402
  if ((rpcb_unset (getprognum (argv[0]), getvers (argv[1]), nconf)) == 0)
 
1403
    {
 
1404
      fprintf (stderr,
 
1405
               "rpcinfo: Could not delete registration for prog %s version %s\n",
 
1406
               argv[0], argv[1]);
 
1407
      exit (1);
 
1408
    }
 
1409
}
 
1410
 
 
1411
/*
 
1412
 * Create and return a handle for the given nconf.
 
1413
 * Exit if cannot create handle.
 
1414
 */
 
1415
static CLIENT *
 
1416
clnt_addr_create (address, nconf, prog, vers)
 
1417
     char *address;
 
1418
     struct netconfig *nconf;
 
1419
     u_long prog;
 
1420
     u_long vers;
 
1421
{
 
1422
  CLIENT *client;
 
1423
  static struct netbuf *nbuf;
 
1424
  static int fd = RPC_ANYFD;
 
1425
 
 
1426
  if (fd == RPC_ANYFD)
 
1427
    {
 
1428
      if ((fd = __rpc_nconf2fd (nconf)) == -1)
 
1429
        {
 
1430
          rpc_createerr.cf_stat = RPC_TLIERROR;
 
1431
          clnt_pcreateerror ("rpcinfo");
 
1432
          exit (1);
 
1433
        }
 
1434
      /* Convert the uaddr to taddr */
 
1435
      nbuf = uaddr2taddr (nconf, address);
 
1436
      if (nbuf == NULL)
 
1437
        {
 
1438
          errx (1, "rpcinfo: no address for client handle");
 
1439
          exit (1);
 
1440
        }
 
1441
    }
 
1442
  client = clnt_tli_create (fd, nconf, nbuf, prog, vers, 0, 0);
 
1443
  if (client == (CLIENT *) NULL)
 
1444
    {
 
1445
      clnt_pcreateerror ("rpcinfo");
 
1446
      exit (1);
 
1447
    }
 
1448
  return (client);
 
1449
}
 
1450
 
 
1451
/*
 
1452
 * If the version number is given, ping that (prog, vers); else try to find
 
1453
 * the version numbers supported for that prog and ping all the versions.
 
1454
 * Remote rpcbind is not contacted for this service. The requests are
 
1455
 * sent directly to the services themselves.
 
1456
 */
 
1457
static void
 
1458
addrping (address, netid, argc, argv)
 
1459
     char *address;
 
1460
     char *netid;
 
1461
     int argc;
 
1462
     char **argv;
 
1463
{
 
1464
  CLIENT *client;
 
1465
  struct timeval to;
 
1466
  enum clnt_stat rpc_stat;
 
1467
  u_int32_t prognum, versnum, minvers, maxvers;
 
1468
  struct rpc_err rpcerr;
 
1469
  int failure = 0;
 
1470
  struct netconfig *nconf;
 
1471
  int fd;
 
1472
 
 
1473
  if (argc < 1 || argc > 2 || (netid == NULL))
 
1474
    {
 
1475
      usage ();
 
1476
      exit (1);
 
1477
    }
 
1478
  nconf = getnetconfigent (netid);
 
1479
  if (nconf == (struct netconfig *) NULL)
 
1480
    {
 
1481
      fprintf (stderr, "rpcinfo: Could not find %s\n", netid);
 
1482
      exit (1);
 
1483
    }
 
1484
  to.tv_sec = 10;
 
1485
  to.tv_usec = 0;
 
1486
  prognum = getprognum (argv[0]);
 
1487
  if (argc == 1)
 
1488
    {                           /* Version number not known */
 
1489
      /*
 
1490
       * A call to version 0 should fail with a program/version
 
1491
       * mismatch, and give us the range of versions supported.
 
1492
       */
 
1493
      versnum = MIN_VERS;
 
1494
    }
 
1495
  else
 
1496
    {
 
1497
      versnum = getvers (argv[1]);
 
1498
    }
 
1499
  client = clnt_addr_create (address, nconf, prognum, versnum);
 
1500
  rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
 
1501
                        (char *) NULL, (xdrproc_t) xdr_void,
 
1502
                        (char *) NULL, to);
 
1503
  if (argc == 2)
 
1504
    {
 
1505
      /* Version number was known */
 
1506
      if (pstatus (client, prognum, versnum) < 0)
 
1507
        failure = 1;
 
1508
      (void) CLNT_DESTROY (client);
 
1509
      if (failure)
 
1510
        exit (1);
 
1511
      return;
 
1512
    }
 
1513
  /* Version number not known */
 
1514
  (void) CLNT_CONTROL (client, CLSET_FD_NCLOSE, (char *) NULL);
 
1515
  (void) CLNT_CONTROL (client, CLGET_FD, (char *) &fd);
 
1516
  if (rpc_stat == RPC_PROGVERSMISMATCH)
 
1517
    {
 
1518
      clnt_geterr (client, &rpcerr);
 
1519
      minvers = rpcerr.re_vers.low;
 
1520
      maxvers = rpcerr.re_vers.high;
 
1521
    }
 
1522
  else if (rpc_stat == RPC_SUCCESS)
 
1523
    {
 
1524
      /*
 
1525
       * Oh dear, it DOES support version 0.
 
1526
       * Let's try version MAX_VERS.
 
1527
       */
 
1528
      (void) CLNT_DESTROY (client);
 
1529
      client = clnt_addr_create (address, nconf, prognum, MAX_VERS);
 
1530
      rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
 
1531
                            (char *) NULL, (xdrproc_t) xdr_void,
 
1532
                            (char *) NULL, to);
 
1533
      if (rpc_stat == RPC_PROGVERSMISMATCH)
 
1534
        {
 
1535
          clnt_geterr (client, &rpcerr);
 
1536
          minvers = rpcerr.re_vers.low;
 
1537
          maxvers = rpcerr.re_vers.high;
 
1538
        }
 
1539
      else if (rpc_stat == RPC_SUCCESS)
 
1540
        {
 
1541
          /*
 
1542
           * It also supports version MAX_VERS.
 
1543
           * Looks like we have a wise guy.
 
1544
           * OK, we give them information on all
 
1545
           * 4 billion versions they support...
 
1546
           */
 
1547
          minvers = 0;
 
1548
          maxvers = MAX_VERS;
 
1549
        }
 
1550
      else
 
1551
        {
 
1552
          (void) pstatus (client, prognum, MAX_VERS);
 
1553
          exit (1);
 
1554
        }
 
1555
    }
 
1556
  else
 
1557
    {
 
1558
      (void) pstatus (client, prognum, (u_long) 0);
 
1559
      exit (1);
 
1560
    }
 
1561
  (void) CLNT_DESTROY (client);
 
1562
  for (versnum = minvers; versnum <= maxvers; versnum++)
 
1563
    {
 
1564
      client = clnt_addr_create (address, nconf, prognum, versnum);
 
1565
      rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
 
1566
                            (char *) NULL, (xdrproc_t) xdr_void,
 
1567
                            (char *) NULL, to);
 
1568
      if (pstatus (client, prognum, versnum) < 0)
 
1569
        failure = 1;
 
1570
      (void) CLNT_DESTROY (client);
 
1571
    }
 
1572
  (void) close (fd);
 
1573
  if (failure)
 
1574
    exit (1);
 
1575
  return;
 
1576
}
 
1577
 
 
1578
/*
 
1579
 * If the version number is given, ping that (prog, vers); else try to find
 
1580
 * the version numbers supported for that prog and ping all the versions.
 
1581
 * Remote rpcbind is *contacted* for this service. The requests are
 
1582
 * then sent directly to the services themselves.
 
1583
 */
 
1584
static void
 
1585
progping (netid, argc, argv)
 
1586
     char *netid;
 
1587
     int argc;
 
1588
     char **argv;
 
1589
{
 
1590
  CLIENT *client;
 
1591
  struct timeval to;
 
1592
  enum clnt_stat rpc_stat;
 
1593
  u_int32_t prognum, versnum, minvers, maxvers;
 
1594
  struct rpc_err rpcerr;
 
1595
  int failure = 0;
 
1596
  struct netconfig *nconf;
 
1597
 
 
1598
  if (argc < 2 || argc > 3 || (netid == NULL))
 
1599
    {
 
1600
      usage ();
 
1601
      exit (1);
 
1602
    }
 
1603
  prognum = getprognum (argv[1]);
 
1604
  if (argc == 2)
 
1605
    {                           /* Version number not known */
 
1606
      /*
 
1607
       * A call to version 0 should fail with a program/version
 
1608
       * mismatch, and give us the range of versions supported.
 
1609
       */
 
1610
      versnum = MIN_VERS;
 
1611
    }
 
1612
  else
 
1613
    {
 
1614
      versnum = getvers (argv[2]);
 
1615
    }
 
1616
  if (netid)
 
1617
    {
 
1618
      nconf = getnetconfigent (netid);
 
1619
      if (nconf == (struct netconfig *) NULL)
 
1620
        {
 
1621
          fprintf (stderr, "rpcinfo: Could not find %s\n", netid);
 
1622
          exit (1);
 
1623
        }
 
1624
      client = clnt_tp_create (argv[0], prognum, versnum, nconf);
 
1625
    }
 
1626
  else
 
1627
    {
 
1628
      client = clnt_create (argv[0], prognum, versnum, "NETPATH");
 
1629
    }
 
1630
  if (client == (CLIENT *) NULL)
 
1631
    {
 
1632
      clnt_pcreateerror ("rpcinfo");
 
1633
      exit (1);
 
1634
    }
 
1635
  to.tv_sec = 10;
 
1636
  to.tv_usec = 0;
 
1637
  rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
 
1638
                        (char *) NULL, (xdrproc_t) xdr_void,
 
1639
                        (char *) NULL, to);
 
1640
  if (argc == 3)
 
1641
    {
 
1642
      /* Version number was known */
 
1643
      if (pstatus (client, prognum, versnum) < 0)
 
1644
        failure = 1;
 
1645
      (void) CLNT_DESTROY (client);
 
1646
      if (failure)
 
1647
        exit (1);
 
1648
      return;
 
1649
    }
 
1650
  /* Version number not known */
 
1651
  if (rpc_stat == RPC_PROGVERSMISMATCH)
 
1652
    {
 
1653
      clnt_geterr (client, &rpcerr);
 
1654
      minvers = rpcerr.re_vers.low;
 
1655
      maxvers = rpcerr.re_vers.high;
 
1656
    }
 
1657
  else if (rpc_stat == RPC_SUCCESS)
 
1658
    {
 
1659
      /*
 
1660
       * Oh dear, it DOES support version 0.
 
1661
       * Let's try version MAX_VERS.
 
1662
       */
 
1663
      versnum = MAX_VERS;
 
1664
      (void) CLNT_CONTROL (client, CLSET_VERS, (char *) &versnum);
 
1665
      rpc_stat = CLNT_CALL (client, NULLPROC,
 
1666
                            (xdrproc_t) xdr_void, (char *) NULL,
 
1667
                            (xdrproc_t) xdr_void, (char *) NULL, to);
 
1668
      if (rpc_stat == RPC_PROGVERSMISMATCH)
 
1669
        {
 
1670
          clnt_geterr (client, &rpcerr);
 
1671
          minvers = rpcerr.re_vers.low;
 
1672
          maxvers = rpcerr.re_vers.high;
 
1673
        }
 
1674
      else if (rpc_stat == RPC_SUCCESS)
 
1675
        {
 
1676
          /*
 
1677
           * It also supports version MAX_VERS.
 
1678
           * Looks like we have a wise guy.
 
1679
           * OK, we give them information on all
 
1680
           * 4 billion versions they support...
 
1681
           */
 
1682
          minvers = 0;
 
1683
          maxvers = MAX_VERS;
 
1684
        }
 
1685
      else
 
1686
        {
 
1687
          (void) pstatus (client, prognum, MAX_VERS);
 
1688
          exit (1);
 
1689
        }
 
1690
    }
 
1691
  else
 
1692
    {
 
1693
      (void) pstatus (client, prognum, (u_long) 0);
 
1694
      exit (1);
 
1695
    }
 
1696
  for (versnum = minvers; versnum <= maxvers; versnum++)
 
1697
    {
 
1698
      (void) CLNT_CONTROL (client, CLSET_VERS, (char *) &versnum);
 
1699
      rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
 
1700
                            (char *) NULL, (xdrproc_t) xdr_void,
 
1701
                            (char *) NULL, to);
 
1702
      if (pstatus (client, prognum, versnum) < 0)
 
1703
        failure = 1;
 
1704
    }
 
1705
  (void) CLNT_DESTROY (client);
 
1706
  if (failure)
 
1707
    exit (1);
 
1708
  return;
 
1709
}
 
1710
 
 
1711
static void
 
1712
usage ()
 
1713
{
 
1714
  fprintf (stderr, "Usage: rpcinfo [-m | -s] [host]\n");
 
1715
#ifdef PORTMAP
 
1716
  fprintf (stderr, "       rpcinfo -p [host]\n");
 
1717
#endif
 
1718
  fprintf (stderr, "       rpcinfo -T netid host prognum [versnum]\n");
 
1719
  fprintf (stderr, "       rpcinfo -l host prognum versnum\n");
 
1720
#ifdef PORTMAP
 
1721
  fprintf (stderr,
 
1722
           "       rpcinfo [-n portnum] -u | -t host prognum [versnum]\n");
 
1723
#endif
 
1724
  fprintf (stderr,
 
1725
           "       rpcinfo -a serv_address -T netid prognum [version]\n");
 
1726
  fprintf (stderr, "       rpcinfo -b prognum versnum\n");
 
1727
  fprintf (stderr, "       rpcinfo -d [-T netid] prognum versnum\n");
 
1728
}
 
1729
 
 
1730
static u_long
 
1731
getprognum (arg)
 
1732
     char *arg;
 
1733
{
 
1734
  char *strptr;
 
1735
  register struct rpcent *rpc;
 
1736
  register u_long prognum;
 
1737
  char *tptr = arg;
 
1738
 
 
1739
  while (*tptr && isdigit (*tptr++));
 
1740
  if (*tptr || isalpha (*(tptr - 1)))
 
1741
    {
 
1742
      rpc = getrpcbyname (arg);
 
1743
      if (rpc == NULL)
 
1744
        {
 
1745
          fprintf (stderr, "rpcinfo: %s is unknown service\n", arg);
 
1746
          exit (1);
 
1747
        }
 
1748
      prognum = rpc->r_number;
 
1749
    }
 
1750
  else
 
1751
    {
 
1752
      prognum = strtol (arg, &strptr, 10);
 
1753
      if (strptr == arg || *strptr != '\0')
 
1754
        {
 
1755
          fprintf (stderr, "rpcinfo: %s is illegal program number\n", arg);
 
1756
          exit (1);
 
1757
        }
 
1758
    }
 
1759
  return (prognum);
 
1760
}
 
1761
 
 
1762
static u_long
 
1763
getvers (arg)
 
1764
     char *arg;
 
1765
{
 
1766
  char *strptr;
 
1767
  register u_long vers;
 
1768
 
 
1769
  vers = (int) strtol (arg, &strptr, 10);
 
1770
  if (strptr == arg || *strptr != '\0')
 
1771
    {
 
1772
      fprintf (stderr, "rpcinfo: %s is illegal version number\n", arg);
 
1773
      exit (1);
 
1774
    }
 
1775
  return (vers);
 
1776
}
 
1777
 
 
1778
/*
 
1779
 * This routine should take a pointer to an "rpc_err" structure, rather than
 
1780
 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
 
1781
 * a CLIENT structure rather than a pointer to an "rpc_err" structure.
 
1782
 * As such, we have to keep the CLIENT structure around in order to print
 
1783
 * a good error message.
 
1784
 */
 
1785
static int
 
1786
pstatus (client, prog, vers)
 
1787
     register CLIENT *client;
 
1788
     u_long prog;
 
1789
     u_long vers;
 
1790
{
 
1791
  struct rpc_err rpcerr;
 
1792
 
 
1793
  clnt_geterr (client, &rpcerr);
 
1794
  if (rpcerr.re_status != RPC_SUCCESS)
 
1795
    {
 
1796
      clnt_perror (client, "rpcinfo");
 
1797
      printf ("program %lu version %lu is not available\n", prog, vers);
 
1798
      return (-1);
 
1799
    }
 
1800
  else
 
1801
    {
 
1802
      printf ("program %lu version %lu ready and waiting\n", prog, vers);
 
1803
      return (0);
 
1804
    }
 
1805
}
 
1806
 
 
1807
static CLIENT *
 
1808
clnt_rpcbind_create (host, rpcbversnum, targaddr)
 
1809
     char *host;
 
1810
     int rpcbversnum;
 
1811
     struct netbuf **targaddr;
 
1812
{
 
1813
  static char *tlist[3] = {
 
1814
    "circuit_n", "circuit_v", "datagram_v"
 
1815
  };
 
1816
  int i;
 
1817
  struct netconfig *nconf;
 
1818
  CLIENT *clnt = NULL;
 
1819
  void *handle;
 
1820
 
 
1821
  rpc_createerr.cf_stat = RPC_SUCCESS;
 
1822
  for (i = 0; i < 3; i++)
 
1823
    {
 
1824
      if ((handle = __rpc_setconf (tlist[i])) == NULL)
 
1825
        continue;
 
1826
      while (clnt == (CLIENT *) NULL)
 
1827
        {
 
1828
          if ((nconf = __rpc_getconf (handle)) == NULL)
 
1829
            {
 
1830
              if (rpc_createerr.cf_stat == RPC_SUCCESS)
 
1831
                rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
 
1832
              break;
 
1833
            }
 
1834
          clnt = getclnthandle (host, nconf, rpcbversnum, targaddr);
 
1835
        }
 
1836
      if (clnt)
 
1837
        break;
 
1838
      __rpc_endconf (handle);
 
1839
    }
 
1840
  return (clnt);
 
1841
}
 
1842
 
 
1843
static CLIENT *
 
1844
getclnthandle (host, nconf, rpcbversnum, targaddr)
 
1845
     char *host;
 
1846
     struct netconfig *nconf;
 
1847
     u_long rpcbversnum;
 
1848
     struct netbuf **targaddr;
 
1849
{
 
1850
  struct netbuf addr;
 
1851
  struct addrinfo hints, *res;
 
1852
  CLIENT *client = NULL;
 
1853
 
 
1854
  /* Get the address of the rpcbind */
 
1855
  memset (&hints, 0, sizeof hints);
 
1856
  if ((getaddrinfo (host, "rpcbind", &hints, &res) != 0) &&
 
1857
      (getaddrinfo (host, "portmapper",&hints, &res) != 0))
 
1858
    {
 
1859
      rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
 
1860
      return (NULL);
 
1861
    }
 
1862
  addr.len = addr.maxlen = res->ai_addrlen;
 
1863
  addr.buf = res->ai_addr;
 
1864
  client = clnt_tli_create (RPC_ANYFD, nconf, &addr, RPCBPROG,
 
1865
                            rpcbversnum, 0, 0);
 
1866
  if (client)
 
1867
    {
 
1868
      if (targaddr != NULL)
 
1869
        {
 
1870
          *targaddr = (struct netbuf *) malloc (sizeof (struct netbuf));
 
1871
          if (*targaddr != NULL)
 
1872
            {
 
1873
              (*targaddr)->maxlen = addr.maxlen;
 
1874
              (*targaddr)->len = addr.len;
 
1875
              (*targaddr)->buf = (char *) malloc (addr.len);
 
1876
              if ((*targaddr)->buf != NULL)
 
1877
                {
 
1878
                  memcpy ((*targaddr)->buf, addr.buf, addr.len);
 
1879
                }
 
1880
            }
 
1881
        }
 
1882
    }
 
1883
  else
 
1884
    {
 
1885
      if (rpc_createerr.cf_stat == RPC_TLIERROR)
 
1886
        {
 
1887
          /*
 
1888
           * Assume that the other system is dead; this is a
 
1889
           * better error to display to the user.
 
1890
           */
 
1891
          rpc_createerr.cf_stat = RPC_RPCBFAILURE;
 
1892
          rpc_createerr.cf_error.re_status = RPC_FAILED;
 
1893
        }
 
1894
    }
 
1895
  freeaddrinfo (res);
 
1896
  return (client);
 
1897
}
 
1898
 
 
1899
static void
 
1900
print_rmtcallstat (rtype, infp)
 
1901
     int rtype;
 
1902
     rpcb_stat *infp;
 
1903
{
 
1904
  register rpcbs_rmtcalllist_ptr pr;
 
1905
  struct rpcent *rpc;
 
1906
 
 
1907
  if (rtype == RPCBVERS_4_STAT)
 
1908
    printf ("prog\t\tvers\tproc\tnetid\tindirect success failure\n");
 
1909
  else
 
1910
    printf ("prog\t\tvers\tproc\tnetid\tsuccess\tfailure\n");
 
1911
  for (pr = infp->rmtinfo; pr; pr = pr->next)
 
1912
    {
 
1913
      rpc = getrpcbynumber (pr->prog);
 
1914
      if (rpc)
 
1915
        printf ("%-16s", rpc->r_name);
 
1916
      else
 
1917
        printf ("%-16d", pr->prog);
 
1918
      printf ("%d\t%d\t%s\t", pr->vers, pr->proc, pr->netid);
 
1919
      if (rtype == RPCBVERS_4_STAT)
 
1920
        printf ("%d\t ", pr->indirect);
 
1921
      printf ("%d\t%d\n", pr->success, pr->failure);
 
1922
    }
 
1923
}
 
1924
 
 
1925
static void
 
1926
print_getaddrstat (rtype, infp)
 
1927
     int rtype;
 
1928
     rpcb_stat *infp;
 
1929
{
 
1930
  rpcbs_addrlist_ptr al;
 
1931
  register struct rpcent *rpc;
 
1932
 
 
1933
  printf ("prog\t\tvers\tnetid\t  success\tfailure\n");
 
1934
  for (al = infp->addrinfo; al; al = al->next)
 
1935
    {
 
1936
      rpc = getrpcbynumber (al->prog);
 
1937
      if (rpc)
 
1938
        printf ("%-16s", rpc->r_name);
 
1939
      else
 
1940
        printf ("%-16d", al->prog);
 
1941
      printf ("%d\t%s\t  %-12d\t%d\n",
 
1942
              al->vers, al->netid, al->success, al->failure);
 
1943
    }
 
1944
}
 
1945
 
 
1946
static char *
 
1947
spaces (howmany)
 
1948
     int howmany;
 
1949
{
 
1950
  static char space_array[] =   /* 64 spaces */
 
1951
    "                                                                ";
 
1952
 
 
1953
  if (howmany <= 0 || howmany > sizeof (space_array))
 
1954
    {
 
1955
      return ("");
 
1956
    }
 
1957
  return (&space_array[sizeof (space_array) - howmany - 1]);
 
1958
}