[BACK]Return to rpcinfo.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rpcinfo

Annotation of src/usr.bin/rpcinfo/rpcinfo.c, Revision 1.14

1.14    ! millert     1: /*     $OpenBSD: rpcinfo.c,v 1.13 2009/10/27 23:59:42 deraadt Exp $    */
1.1       deraadt     2:
                      3: /*
1.14    ! millert     4:  * Copyright (c) 2010, Oracle America, Inc.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions are
        !             8:  * met:
        !             9:  *
        !            10:  *     * Redistributions of source code must retain the above copyright
        !            11:  *       notice, this list of conditions and the following disclaimer.
        !            12:  *     * Redistributions in binary form must reproduce the above
        !            13:  *       copyright notice, this list of conditions and the following
        !            14:  *       disclaimer in the documentation and/or other materials
        !            15:  *       provided with the distribution.
        !            16:  *     * Neither the name of the "Oracle America, Inc." nor the names of its
        !            17:  *       contributors may be used to endorse or promote products derived
        !            18:  *       from this software without specific prior written permission.
        !            19:  *
        !            20:  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
        !            21:  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
        !            22:  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
        !            23:  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
        !            24:  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
        !            25:  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
        !            27:  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            28:  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
        !            29:  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
        !            30:  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        !            31:  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1       deraadt    32:  */
                     33:
                     34: /*
                     35:  * rpcinfo: ping a particular rpc program
                     36:  *     or dump the portmapper
                     37:  */
                     38:
                     39: #include <rpc/rpc.h>
                     40: #include <stdio.h>
                     41: #include <sys/socket.h>
                     42: #include <netdb.h>
                     43: #include <rpc/pmap_prot.h>
                     44: #include <rpc/pmap_clnt.h>
                     45: #include <signal.h>
1.7       pvalchev   46: #include <string.h>
                     47: #include <stdlib.h>
                     48: #include <unistd.h>
1.1       deraadt    49: #include <ctype.h>
1.5       deraadt    50: #include <errno.h>
1.11      millert    51: #include <limits.h>
1.1       deraadt    52: #include <arpa/inet.h>
                     53:
                     54: #define MAXHOSTLEN 256
                     55:
                     56: #define        MIN_VERS        ((u_long) 0)
                     57: #define        MAX_VERS        ((u_long) 4294967295UL)
                     58:
1.5       deraadt    59: void   udpping(u_short portflag, int argc, char **argv);
                     60: void   tcpping(u_short portflag, int argc, char **argv);
                     61: int    pstatus(CLIENT *client, u_long prognum, u_long vers);
                     62: void   pmapdump(int argc, char **argv);
1.6       millert    63: bool_t reply_proc(caddr_t res, struct sockaddr_in *who);
1.5       deraadt    64: void   brdcst(int argc, char **argv);
                     65: void   deletereg(int argc, char **argv);
                     66: void   setreg(int argc, char **argv);
                     67: void   usage(char *);
                     68: int    getprognum(char *arg, u_long *ulp);
                     69: int    getul(char *arg, u_long *ulp);
                     70: void   get_inet_address(struct sockaddr_in *addr, char *host);
1.1       deraadt    71:
                     72: /*
                     73:  * Functions to be performed.
                     74:  */
                     75: #define        NONE            0       /* no function */
                     76: #define        PMAPDUMP        1       /* dump portmapper registrations */
                     77: #define        TCPPING         2       /* ping TCP service */
                     78: #define        UDPPING         3       /* ping UDP service */
                     79: #define        BRDCST          4       /* ping broadcast UDP service */
                     80: #define DELETES                5       /* delete registration for the service */
1.5       deraadt    81: #define SETS           6       /* set registration for the service */
1.1       deraadt    82:
                     83: int
1.9       deraadt    84: main(int argc, char *argv[])
1.1       deraadt    85: {
1.8       mpech      86:        int c;
1.1       deraadt    87:        extern char *optarg;
                     88:        extern int optind;
                     89:        int errflg;
                     90:        int function;
                     91:        u_short portnum;
1.5       deraadt    92:        u_long tmp;
1.1       deraadt    93:
                     94:        function = NONE;
                     95:        portnum = 0;
                     96:        errflg = 0;
1.5       deraadt    97:        while ((c = getopt(argc, argv, "ptubdsn:")) != -1) {
1.1       deraadt    98:                switch (c) {
                     99:
                    100:                case 'p':
                    101:                        if (function != NONE)
                    102:                                errflg = 1;
                    103:                        else
                    104:                                function = PMAPDUMP;
                    105:                        break;
                    106:
                    107:                case 't':
                    108:                        if (function != NONE)
                    109:                                errflg = 1;
                    110:                        else
                    111:                                function = TCPPING;
                    112:                        break;
                    113:
                    114:                case 'u':
                    115:                        if (function != NONE)
                    116:                                errflg = 1;
                    117:                        else
                    118:                                function = UDPPING;
                    119:                        break;
                    120:
                    121:                case 'b':
                    122:                        if (function != NONE)
                    123:                                errflg = 1;
                    124:                        else
                    125:                                function = BRDCST;
                    126:                        break;
                    127:
                    128:                case 'n':
1.5       deraadt   129:                        if (getul(optarg, &tmp))
                    130:                                usage("invalid port number");
                    131:                        if (tmp >= 65536)
                    132:                                usage("port number out of range");
                    133:                        portnum = (u_short)tmp;
1.1       deraadt   134:                        break;
                    135:
                    136:                case 'd':
                    137:                        if (function != NONE)
                    138:                                errflg = 1;
                    139:                        else
                    140:                                function = DELETES;
                    141:                        break;
                    142:
1.5       deraadt   143:                case 's':
                    144:                        if (function != NONE)
                    145:                                errflg = 1;
                    146:                        else
                    147:                                function = SETS;
                    148:                        break;
                    149:
                    150:
1.1       deraadt   151:                case '?':
                    152:                        errflg = 1;
                    153:                }
                    154:        }
                    155:
1.5       deraadt   156:        if (errflg || function == NONE)
                    157:                usage(NULL);
1.1       deraadt   158:
                    159:        switch (function) {
                    160:
                    161:        case PMAPDUMP:
1.5       deraadt   162:                if (portnum != 0)
                    163:                        usage(NULL);
1.1       deraadt   164:                pmapdump(argc - optind, argv + optind);
                    165:                break;
                    166:
                    167:        case UDPPING:
                    168:                udpping(portnum, argc - optind, argv + optind);
                    169:                break;
                    170:
                    171:        case TCPPING:
                    172:                tcpping(portnum, argc - optind, argv + optind);
                    173:                break;
                    174:
                    175:        case BRDCST:
1.5       deraadt   176:                if (portnum != 0)
                    177:                        usage(NULL);
                    178:
1.1       deraadt   179:                brdcst(argc - optind, argv + optind);
                    180:                break;
                    181:
                    182:        case DELETES:
                    183:                deletereg(argc - optind, argv + optind);
                    184:                break;
1.5       deraadt   185:
                    186:        case SETS:
                    187:                setreg(argc - optind, argv + optind);
                    188:                break;
1.1       deraadt   189:        }
                    190:
                    191:        return (0);
                    192: }
                    193:
1.5       deraadt   194: void
1.9       deraadt   195: udpping(u_short portnum, int argc, char **argv)
1.1       deraadt   196: {
                    197:        struct timeval to;
                    198:        struct sockaddr_in addr;
                    199:        enum clnt_stat rpc_stat;
                    200:        CLIENT *client;
                    201:        u_long prognum, vers, minvers, maxvers;
                    202:        int sock = RPC_ANYSOCK;
                    203:        struct rpc_err rpcerr;
                    204:        int failure;
                    205:
1.5       deraadt   206:        if (argc < 2)
                    207:                usage("too few arguments");
                    208:        if (argc > 3)
                    209:                usage("too many arguments");
                    210:        if (getprognum(argv[1], &prognum))
                    211:                usage("program number out of range");
                    212:
1.1       deraadt   213:        get_inet_address(&addr, argv[0]);
                    214:        /* Open the socket here so it will survive calls to clnt_destroy */
1.3       deraadt   215:        sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1.1       deraadt   216:        if (sock < 0) {
                    217:                perror("rpcinfo: socket");
                    218:                exit(1);
                    219:        }
1.3       deraadt   220:        if (getuid() == 0)
                    221:                bindresvport(sock, NULL);
1.1       deraadt   222:        failure = 0;
                    223:        if (argc == 2) {
                    224:                /*
                    225:                 * A call to version 0 should fail with a program/version
                    226:                 * mismatch, and give us the range of versions supported.
                    227:                 */
                    228:                addr.sin_port = htons(portnum);
                    229:                to.tv_sec = 5;
                    230:                to.tv_usec = 0;
                    231:                if ((client = clntudp_create(&addr, prognum, (u_long)0,
                    232:                    to, &sock)) == NULL) {
                    233:                        clnt_pcreateerror("rpcinfo");
                    234:                        printf("program %lu is not available\n",
                    235:                            prognum);
                    236:                        exit(1);
                    237:                }
                    238:                to.tv_sec = 10;
                    239:                to.tv_usec = 0;
                    240:                rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
                    241:                    xdr_void, (char *)NULL, to);
                    242:                if (rpc_stat == RPC_PROGVERSMISMATCH) {
                    243:                        clnt_geterr(client, &rpcerr);
                    244:                        minvers = rpcerr.re_vers.low;
                    245:                        maxvers = rpcerr.re_vers.high;
                    246:                } else if (rpc_stat == RPC_SUCCESS) {
                    247:                        /*
                    248:                         * Oh dear, it DOES support version 0.
                    249:                         * Let's try version MAX_VERS.
                    250:                         */
                    251:                        addr.sin_port = htons(portnum);
                    252:                        to.tv_sec = 5;
                    253:                        to.tv_usec = 0;
                    254:                        if ((client = clntudp_create(&addr, prognum, MAX_VERS,
                    255:                            to, &sock)) == NULL) {
                    256:                                clnt_pcreateerror("rpcinfo");
                    257:                                printf("program %lu version %lu is not available\n",
                    258:                                    prognum, MAX_VERS);
                    259:                                exit(1);
                    260:                        }
                    261:                        to.tv_sec = 10;
                    262:                        to.tv_usec = 0;
                    263:                        rpc_stat = clnt_call(client, NULLPROC, xdr_void,
                    264:                            (char *)NULL, xdr_void, (char *)NULL, to);
                    265:                        if (rpc_stat == RPC_PROGVERSMISMATCH) {
                    266:                                clnt_geterr(client, &rpcerr);
                    267:                                minvers = rpcerr.re_vers.low;
                    268:                                maxvers = rpcerr.re_vers.high;
                    269:                        } else if (rpc_stat == RPC_SUCCESS) {
                    270:                                /*
                    271:                                 * It also supports version MAX_VERS.
                    272:                                 * Looks like we have a wise guy.
                    273:                                 * OK, we give them information on all
                    274:                                 * 4 billion versions they support...
                    275:                                 */
                    276:                                minvers = 0;
                    277:                                maxvers = MAX_VERS;
                    278:                        } else {
                    279:                                (void) pstatus(client, prognum, MAX_VERS);
                    280:                                exit(1);
                    281:                        }
                    282:                } else {
                    283:                        (void) pstatus(client, prognum, (u_long)0);
                    284:                        exit(1);
                    285:                }
                    286:                clnt_destroy(client);
                    287:                for (vers = minvers; vers <= maxvers; vers++) {
                    288:                        addr.sin_port = htons(portnum);
                    289:                        to.tv_sec = 5;
                    290:                        to.tv_usec = 0;
                    291:                        if ((client = clntudp_create(&addr, prognum, vers,
                    292:                            to, &sock)) == NULL) {
                    293:                                clnt_pcreateerror("rpcinfo");
                    294:                                printf("program %lu version %lu is not available\n",
                    295:                                    prognum, vers);
                    296:                                exit(1);
                    297:                        }
                    298:                        to.tv_sec = 10;
                    299:                        to.tv_usec = 0;
                    300:                        rpc_stat = clnt_call(client, NULLPROC, xdr_void,
                    301:                            (char *)NULL, xdr_void, (char *)NULL, to);
                    302:                        if (pstatus(client, prognum, vers) < 0)
                    303:                                failure = 1;
                    304:                        clnt_destroy(client);
                    305:                }
1.5       deraadt   306:        } else {
                    307:                getul(argv[2], &vers);          /* XXX */
1.1       deraadt   308:                addr.sin_port = htons(portnum);
                    309:                to.tv_sec = 5;
                    310:                to.tv_usec = 0;
                    311:                if ((client = clntudp_create(&addr, prognum, vers,
                    312:                    to, &sock)) == NULL) {
                    313:                        clnt_pcreateerror("rpcinfo");
                    314:                        printf("program %lu version %lu is not available\n",
                    315:                            prognum, vers);
                    316:                        exit(1);
                    317:                }
                    318:                to.tv_sec = 10;
                    319:                to.tv_usec = 0;
                    320:                rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
                    321:                    xdr_void, (char *)NULL, to);
                    322:                if (pstatus(client, prognum, vers) < 0)
                    323:                        failure = 1;
                    324:        }
                    325:        (void) close(sock); /* Close it up again */
                    326:        if (failure)
                    327:                exit(1);
                    328: }
                    329:
1.5       deraadt   330: void
1.9       deraadt   331: tcpping(u_short portnum, int argc, char **argv)
1.1       deraadt   332: {
                    333:        struct timeval to;
                    334:        struct sockaddr_in addr;
                    335:        enum clnt_stat rpc_stat;
                    336:        CLIENT *client;
                    337:        u_long prognum, vers, minvers, maxvers;
                    338:        int sock = RPC_ANYSOCK;
                    339:        struct rpc_err rpcerr;
                    340:        int failure;
                    341:
1.5       deraadt   342:        if (argc < 2)
                    343:                usage("too few arguments");
                    344:        if (argc > 3)
                    345:                usage("too many arguments");
                    346:        if (getprognum(argv[1], &prognum))
                    347:                usage("program number out of range");
                    348:
1.1       deraadt   349:        get_inet_address(&addr, argv[0]);
                    350:        failure = 0;
                    351:        if (argc == 2) {
                    352:                /*
                    353:                 * A call to version 0 should fail with a program/version
                    354:                 * mismatch, and give us the range of versions supported.
                    355:                 */
                    356:                addr.sin_port = htons(portnum);
                    357:                if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
                    358:                    &sock, 0, 0)) == NULL) {
                    359:                        clnt_pcreateerror("rpcinfo");
                    360:                        printf("program %lu is not available\n",
                    361:                            prognum);
                    362:                        exit(1);
                    363:                }
                    364:                to.tv_sec = 10;
                    365:                to.tv_usec = 0;
                    366:                rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
                    367:                    xdr_void, (char *)NULL, to);
                    368:                if (rpc_stat == RPC_PROGVERSMISMATCH) {
                    369:                        clnt_geterr(client, &rpcerr);
                    370:                        minvers = rpcerr.re_vers.low;
                    371:                        maxvers = rpcerr.re_vers.high;
                    372:                } else if (rpc_stat == RPC_SUCCESS) {
                    373:                        /*
                    374:                         * Oh dear, it DOES support version 0.
                    375:                         * Let's try version MAX_VERS.
                    376:                         */
                    377:                        addr.sin_port = htons(portnum);
                    378:                        if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
                    379:                            &sock, 0, 0)) == NULL) {
                    380:                                clnt_pcreateerror("rpcinfo");
                    381:                                printf("program %lu version %lu is not available\n",
                    382:                                    prognum, MAX_VERS);
                    383:                                exit(1);
                    384:                        }
                    385:                        to.tv_sec = 10;
                    386:                        to.tv_usec = 0;
                    387:                        rpc_stat = clnt_call(client, NULLPROC, xdr_void,
                    388:                            (char *)NULL, xdr_void, (char *)NULL, to);
                    389:                        if (rpc_stat == RPC_PROGVERSMISMATCH) {
                    390:                                clnt_geterr(client, &rpcerr);
                    391:                                minvers = rpcerr.re_vers.low;
                    392:                                maxvers = rpcerr.re_vers.high;
                    393:                        } else if (rpc_stat == RPC_SUCCESS) {
                    394:                                /*
                    395:                                 * It also supports version MAX_VERS.
                    396:                                 * Looks like we have a wise guy.
                    397:                                 * OK, we give them information on all
                    398:                                 * 4 billion versions they support...
                    399:                                 */
                    400:                                minvers = 0;
                    401:                                maxvers = MAX_VERS;
                    402:                        } else {
                    403:                                (void) pstatus(client, prognum, MAX_VERS);
                    404:                                exit(1);
                    405:                        }
                    406:                } else {
                    407:                        (void) pstatus(client, prognum, MIN_VERS);
                    408:                        exit(1);
                    409:                }
                    410:                clnt_destroy(client);
                    411:                (void) close(sock);
                    412:                sock = RPC_ANYSOCK; /* Re-initialize it for later */
                    413:                for (vers = minvers; vers <= maxvers; vers++) {
                    414:                        addr.sin_port = htons(portnum);
                    415:                        if ((client = clnttcp_create(&addr, prognum, vers,
                    416:                            &sock, 0, 0)) == NULL) {
                    417:                                clnt_pcreateerror("rpcinfo");
                    418:                                printf("program %lu version %lu is not available\n",
                    419:                                    prognum, vers);
                    420:                                exit(1);
                    421:                        }
                    422:                        to.tv_usec = 0;
                    423:                        to.tv_sec = 10;
                    424:                        rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
                    425:                            xdr_void, (char *)NULL, to);
                    426:                        if (pstatus(client, prognum, vers) < 0)
                    427:                                failure = 1;
                    428:                        clnt_destroy(client);
                    429:                        (void) close(sock);
                    430:                        sock = RPC_ANYSOCK;
                    431:                }
1.5       deraadt   432:        } else {
                    433:                getul(argv[2], &vers);          /* XXX */
1.1       deraadt   434:                addr.sin_port = htons(portnum);
                    435:                if ((client = clnttcp_create(&addr, prognum, vers, &sock,
                    436:                    0, 0)) == NULL) {
                    437:                        clnt_pcreateerror("rpcinfo");
                    438:                        printf("program %lu version %lu is not available\n",
                    439:                            prognum, vers);
                    440:                        exit(1);
                    441:                }
                    442:                to.tv_usec = 0;
                    443:                to.tv_sec = 10;
                    444:                rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
                    445:                    xdr_void, (char *)NULL, to);
                    446:                if (pstatus(client, prognum, vers) < 0)
                    447:                        failure = 1;
                    448:        }
                    449:        if (failure)
                    450:                exit(1);
                    451: }
                    452:
                    453: /*
                    454:  * This routine should take a pointer to an "rpc_err" structure, rather than
                    455:  * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
                    456:  * a CLIENT structure rather than a pointer to an "rpc_err" structure.
                    457:  * As such, we have to keep the CLIENT structure around in order to print
                    458:  * a good error message.
                    459:  */
1.5       deraadt   460: int
1.9       deraadt   461: pstatus(CLIENT *client, u_long prognum, u_long vers)
1.1       deraadt   462: {
                    463:        struct rpc_err rpcerr;
                    464:
                    465:        clnt_geterr(client, &rpcerr);
                    466:        if (rpcerr.re_status != RPC_SUCCESS) {
                    467:                clnt_perror(client, "rpcinfo");
                    468:                printf("program %lu version %lu is not available\n",
                    469:                    prognum, vers);
                    470:                return (-1);
                    471:        } else {
                    472:                printf("program %lu version %lu ready and waiting\n",
                    473:                    prognum, vers);
                    474:                return (0);
                    475:        }
                    476: }
                    477:
1.5       deraadt   478: void
1.9       deraadt   479: pmapdump(int argc, char **argv)
1.1       deraadt   480: {
                    481:        struct sockaddr_in server_addr;
1.8       mpech     482:        struct hostent *hp;
1.1       deraadt   483:        struct pmaplist *head = NULL;
                    484:        int socket = RPC_ANYSOCK;
                    485:        struct timeval minutetimeout;
1.8       mpech     486:        CLIENT *client;
1.1       deraadt   487:        struct rpcent *rpc;
                    488:
1.5       deraadt   489:        if (argc > 1)
                    490:                usage("too many arguments");
                    491:
1.1       deraadt   492:        if (argc == 1)
                    493:                get_inet_address(&server_addr, argv[0]);
                    494:        else {
                    495:                bzero((char *)&server_addr, sizeof server_addr);
                    496:                server_addr.sin_family = AF_INET;
                    497:                if ((hp = gethostbyname("localhost")) != NULL)
                    498:                        bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
                    499:                            hp->h_length);
                    500:                else
                    501:                        (void) inet_aton("0.0.0.0", &server_addr.sin_addr);
                    502:        }
                    503:        minutetimeout.tv_sec = 60;
                    504:        minutetimeout.tv_usec = 0;
                    505:        server_addr.sin_port = htons(PMAPPORT);
                    506:        if ((client = clnttcp_create(&server_addr, PMAPPROG,
                    507:            PMAPVERS, &socket, 50, 500)) == NULL) {
                    508:                clnt_pcreateerror("rpcinfo: can't contact portmapper");
                    509:                exit(1);
                    510:        }
                    511:        if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
                    512:            xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
                    513:                fprintf(stderr, "rpcinfo: can't contact portmapper: ");
                    514:                clnt_perror(client, "rpcinfo");
                    515:                exit(1);
                    516:        }
                    517:        if (head == NULL) {
                    518:                printf("No remote programs registered.\n");
                    519:        } else {
                    520:                printf("   program vers proto   port\n");
                    521:                for (; head != NULL; head = head->pml_next) {
                    522:                        printf("%10ld%5ld",
                    523:                            head->pml_map.pm_prog,
                    524:                            head->pml_map.pm_vers);
                    525:                        if (head->pml_map.pm_prot == IPPROTO_UDP)
                    526:                                printf("%6s",  "udp");
                    527:                        else if (head->pml_map.pm_prot == IPPROTO_TCP)
                    528:                                printf("%6s", "tcp");
                    529:                        else
                    530:                                printf("%6ld",  head->pml_map.pm_prot);
                    531:                        printf("%7ld",  head->pml_map.pm_port);
                    532:                        rpc = getrpcbynumber(head->pml_map.pm_prog);
                    533:                        if (rpc)
                    534:                                printf("  %s\n", rpc->r_name);
                    535:                        else
                    536:                                printf("\n");
                    537:                }
                    538:        }
                    539: }
                    540:
                    541: /*
                    542:  * reply_proc collects replies from the broadcast.
                    543:  * to get a unique list of responses the output of rpcinfo should
                    544:  * be piped through sort(1) and then uniq(1).
                    545:  */
                    546: /*ARGSUSED*/
1.5       deraadt   547: bool_t
1.9       deraadt   548: reply_proc(caddr_t res, struct sockaddr_in *who)
1.1       deraadt   549: {
1.8       mpech     550:        struct hostent *hp;
1.1       deraadt   551:
                    552:        hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
                    553:            AF_INET);
                    554:        printf("%s %s\n", inet_ntoa(who->sin_addr),
                    555:            (hp == NULL) ? "(unknown)" : hp->h_name);
                    556:        return(FALSE);
                    557: }
                    558:
1.5       deraadt   559: void
1.9       deraadt   560: brdcst(int argc, char **argv)
1.1       deraadt   561: {
                    562:        enum clnt_stat rpc_stat;
1.5       deraadt   563:        u_long prognum, vers_num;
1.1       deraadt   564:
1.5       deraadt   565:        if (argc != 2)
                    566:                usage("incorrect number of arguments");
                    567:        if (getprognum(argv[1], &prognum))
                    568:                usage("program number out of range");
                    569:        if (getul(argv[1], &vers_num))
                    570:                usage("version number out of range");
                    571:
                    572:        rpc_stat = clnt_broadcast(prognum, vers_num, NULLPROC, xdr_void,
1.6       millert   573:            (char *)NULL, xdr_void, (char *)NULL, reply_proc);
1.1       deraadt   574:        if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
                    575:                fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
                    576:                    clnt_sperrno(rpc_stat));
                    577:                exit(1);
                    578:        }
                    579:        exit(0);
                    580: }
                    581:
1.5       deraadt   582: void
1.9       deraadt   583: deletereg(int argc, char **argv)
1.5       deraadt   584: {
                    585:        u_long prog_num, version_num;
                    586:
                    587:        if (argc != 2)
                    588:                usage("incorrect number of arguments");
                    589:        if (getprognum(argv[0], &prog_num))
                    590:                usage("program number out of range");
                    591:        if (getul(argv[1], &version_num))
                    592:                usage("version number out of range");
1.1       deraadt   593:
1.5       deraadt   594:        if ((pmap_unset(prog_num, version_num)) == 0) {
                    595:                fprintf(stderr, "rpcinfo: Could not delete "
                    596:                    "registration for prog %s version %s\n",
                    597:                    argv[0], argv[1]);
                    598:                exit(1);
1.1       deraadt   599:        }
1.5       deraadt   600: }
                    601:
                    602: void
1.9       deraadt   603: setreg(int argc, char **argv)
1.5       deraadt   604: {
                    605:        u_long prog_num, version_num, port_num;
                    606:
                    607:        if (argc != 3)
                    608:                usage("incorrect number of arguments");
                    609:        if (getprognum(argv[0], &prog_num))
                    610:                usage("cannot parse program number");
                    611:        if (getul(argv[1], &version_num))
                    612:                usage("cannot parse version number");
                    613:        if (getul(argv[2], &port_num))
                    614:                usage("cannot parse port number");
                    615:        if (port_num >= 65536)
                    616:                usage("port number out of range");
                    617:
1.10      deraadt   618:        if ((pmap_set(prog_num, version_num, IPPROTO_TCP,
1.5       deraadt   619:            (u_short)port_num)) == 0) {
                    620:                fprintf(stderr, "rpcinfo: Could not set registration "
1.10      deraadt   621:                    "for prog %s version %s port %s protocol IPPROTO_TCP\n",
                    622:                    argv[0], argv[1], argv[2]);
                    623:                exit(1);
                    624:        }
                    625:        if ((pmap_set(prog_num, version_num, IPPROTO_UDP,
                    626:            (u_short)port_num)) == 0) {
                    627:                fprintf(stderr, "rpcinfo: Could not set registration "
                    628:                    "for prog %s version %s port %s protocol IPPROTO_UDP\n",
1.5       deraadt   629:                    argv[0], argv[1], argv[2]);
                    630:                exit(1);
1.1       deraadt   631:        }
                    632: }
                    633:
1.5       deraadt   634: void
                    635: usage(char *msg)
1.1       deraadt   636: {
1.5       deraadt   637:        if (msg)
                    638:                fprintf(stderr,
                    639:                    "rpcinfo: %s\n", msg);
1.12      jmc       640:        fprintf(stderr, "usage: rpcinfo -b program version\n");
                    641:        fprintf(stderr, "       rpcinfo -d program version\n");
                    642:        fprintf(stderr, "       rpcinfo -p [host]\n");
                    643:        fprintf(stderr, "       rpcinfo -s program version port\n");
1.5       deraadt   644:        fprintf(stderr,
1.12      jmc       645:            "       rpcinfo [-n portnum] -t host program [version]\n");
1.5       deraadt   646:        fprintf(stderr,
1.12      jmc       647:            "       rpcinfo [-n portnum] -u host program [version]\n");
1.5       deraadt   648:        exit(1);
1.1       deraadt   649: }
                    650:
1.5       deraadt   651: int
1.9       deraadt   652: getprognum(char *arg, u_long *ulp)
1.1       deraadt   653: {
1.8       mpech     654:        struct rpcent *rpc;
1.1       deraadt   655:
                    656:        if (isalpha(*arg)) {
                    657:                rpc = getrpcbyname(arg);
                    658:                if (rpc == NULL) {
                    659:                        fprintf(stderr, "rpcinfo: %s is unknown service\n",
                    660:                            arg);
                    661:                        exit(1);
                    662:                }
1.5       deraadt   663:                *ulp = rpc->r_number;
                    664:                return 0;
1.1       deraadt   665:        }
1.5       deraadt   666:        return getul(arg, ulp);
1.1       deraadt   667: }
                    668:
1.5       deraadt   669: int
1.9       deraadt   670: getul(char *arg, u_long *ulp)
1.1       deraadt   671: {
1.5       deraadt   672:        u_long ul;
                    673:        int save_errno = errno;
                    674:        char *ep;
                    675:        int ret = 1;
                    676:
                    677:        errno = 0;
                    678:        ul = strtoul(arg, &ep, 10);
                    679:        if (arg[0] == '\0' || *ep != '\0')
                    680:                goto fail;
                    681:        if (errno == ERANGE && ul == ULONG_MAX)
                    682:                goto fail;
                    683:        *ulp = ul;
                    684:        ret = 0;
                    685: fail:
                    686:        errno = save_errno;
                    687:        return (ret);
1.1       deraadt   688: }
                    689:
1.5       deraadt   690: void
1.9       deraadt   691: get_inet_address(struct sockaddr_in *addr, char *host)
1.1       deraadt   692: {
1.8       mpech     693:        struct hostent *hp;
1.1       deraadt   694:
                    695:        bzero((char *)addr, sizeof *addr);
                    696:        if (inet_aton(host, &addr->sin_addr) == 0) {
                    697:                if ((hp = gethostbyname(host)) == NULL) {
1.5       deraadt   698:                        fprintf(stderr, "rpcinfo: %s is unknown host\n",
                    699:                            host);
1.1       deraadt   700:                        exit(1);
                    701:                }
                    702:                bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length);
                    703:        }
                    704:        addr->sin_family = AF_INET;
                    705: }