rpcbind.c revision 104592
1205859Sjoel/* $NetBSD: rpcbind.c,v 1.1 2000/06/02 23:15:42 fvdl Exp $ */ 2162874Snetchild/* $FreeBSD: head/usr.sbin/rpcbind/rpcbind.c 104592 2002-10-07 02:56:59Z alfred $ */ 3159687Snetchild 4159687Snetchild/* 5159687Snetchild * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 6159687Snetchild * unrestricted use provided that this legend is included on all tape 7159687Snetchild * media and as a part of the software program in whole or part. Users 8159687Snetchild * may copy or modify Sun RPC without charge, but are not authorized 9159687Snetchild * to license or distribute it to anyone else except as part of a product or 10159687Snetchild * program developed by the user. 11159687Snetchild * 12159687Snetchild * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 13159687Snetchild * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 14159687Snetchild * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 15159687Snetchild * 16159687Snetchild * Sun RPC is provided with no support and without any obligation on the 17159687Snetchild * part of Sun Microsystems, Inc. to assist in its use, correction, 18159687Snetchild * modification or enhancement. 19159687Snetchild * 20159687Snetchild * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 21159687Snetchild * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 22159687Snetchild * OR ANY PART THEREOF. 23159687Snetchild * 24159687Snetchild * In no event will Sun Microsystems, Inc. be liable for any lost revenue 25159687Snetchild * or profits or other special, indirect and consequential damages, even if 26159687Snetchild * Sun has been advised of the possibility of such damages. 27159687Snetchild * 28159687Snetchild * Sun Microsystems, Inc. 29159687Snetchild * 2550 Garcia Avenue 30193640Sariff * Mountain View, California 94043 31193640Sariff */ 32193640Sariff/* 33193640Sariff * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc. 34159687Snetchild */ 35159687Snetchild 36162874Snetchild/* #ident "@(#)rpcbind.c 1.19 94/04/25 SMI" */ 37159687Snetchild 38227293Sed#if 0 39159687Snetchild#ifndef lint 40162874Snetchildstatic char sccsid[] = "@(#)rpcbind.c 1.35 89/04/21 Copyr 1984 Sun Micro"; 41162874Snetchild#endif 42159687Snetchild#endif 43162874Snetchild 44159687Snetchild/* 45159687Snetchild * rpcbind.c 46159687Snetchild * Implements the program, version to address mapping for rpc. 47159687Snetchild * 48159687Snetchild */ 49159687Snetchild 50159687Snetchild#include <sys/types.h> 51162874Snetchild#include <sys/stat.h> 52166713Sariff#include <sys/errno.h> 53159687Snetchild#include <sys/time.h> 54159687Snetchild#include <sys/resource.h> 55159687Snetchild#include <sys/wait.h> 56162874Snetchild#include <sys/signal.h> 57159687Snetchild#include <sys/socket.h> 58159687Snetchild#include <sys/un.h> 59159687Snetchild#include <rpc/rpc.h> 60159687Snetchild#ifdef PORTMAP 61159687Snetchild#include <netinet/in.h> 62159687Snetchild#endif 63159687Snetchild#include <arpa/inet.h> 64159687Snetchild#include <netdb.h> 65159687Snetchild#include <stdio.h> 66159687Snetchild#include <netconfig.h> 67159687Snetchild#include <stdlib.h> 68159687Snetchild#include <unistd.h> 69159687Snetchild#include <syslog.h> 70159687Snetchild#include <err.h> 71159687Snetchild#include <libutil.h> 72159687Snetchild#include <pwd.h> 73159687Snetchild#include <string.h> 74159687Snetchild#include <errno.h> 75159687Snetchild#include "rpcbind.h" 76162874Snetchild 77159687Snetchild/* Global variables */ 78159687Snetchildint debugging = 0; /* Tell me what's going on */ 79159687Snetchildint doabort = 0; /* When debugging, do an abort on errors */ 80159687Snetchildrpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */ 81162874Snetchild 82159687Snetchild/* who to suid to if -s is given */ 83159687Snetchild#define RUN_AS "daemon" 84159687Snetchild 85159687Snetchildint runasdaemon = 0; 86159687Snetchildint insecure = 0; 87159687Snetchildint oldstyle_local = 0; 88159687Snetchildint verboselog = 0; 89162874Snetchild 90162874Snetchildchar **hosts = NULL; 91162874Snetchildint nhosts = 0; 92162874Snetchildint on = 1; 93162874Snetchild 94162874Snetchild#ifdef WARMSTART 95170031Sjoel/* Local Variable */ 96170031Sjoelstatic int warmstart = 0; /* Grab a old copy of registrations */ 97170031Sjoel#endif 98170031Sjoel 99170031Sjoel#ifdef PORTMAP 100170031Sjoelstruct pmaplist *list_pml; /* A list of version 2 rpcbind services */ 101162874Snetchildchar *udptrans; /* Name of UDP transport */ 102159687Snetchildchar *tcptrans; /* Name of TCP transport */ 103162874Snetchildchar *udp_uaddr; /* Universal UDP address */ 104162874Snetchildchar *tcp_uaddr; /* Universal TCP address */ 105162874Snetchild#endif 106159687Snetchildstatic char servname[] = "rpcbind"; 107162874Snetchildstatic char superuser[] = "superuser"; 108159687Snetchild 109159687Snetchildint main __P((int, char *[])); 110162874Snetchild 111159687Snetchildstatic int init_transport __P((struct netconfig *)); 112159687Snetchildstatic void rbllist_add __P((rpcprog_t, rpcvers_t, struct netconfig *, 113162874Snetchild struct netbuf *)); 114159687Snetchildstatic void terminate __P((int)); 115159687Snetchildstatic void parseargs __P((int, char *[])); 116162874Snetchild 117162874Snetchildint 118162874Snetchildmain(int argc, char *argv[]) 119162874Snetchild{ 120162874Snetchild struct netconfig *nconf; 121162874Snetchild void *nc_handle; /* Net config handle */ 122162874Snetchild struct rlimit rl; 123162874Snetchild 124162874Snetchild parseargs(argc, argv); 125162874Snetchild 126162874Snetchild getrlimit(RLIMIT_NOFILE, &rl); 127159687Snetchild if (rl.rlim_cur < 128) { 128159687Snetchild if (rl.rlim_max <= 128) 129159687Snetchild rl.rlim_cur = rl.rlim_max; 130159687Snetchild else 131159687Snetchild rl.rlim_cur = 128; 132159687Snetchild setrlimit(RLIMIT_NOFILE, &rl); 133159687Snetchild } 134159687Snetchild openlog("rpcbind", LOG_CONS, LOG_DAEMON); 135159687Snetchild if (geteuid()) { /* This command allowed only to root */ 136159687Snetchild fprintf(stderr, "Sorry. You are not superuser\n"); 137159687Snetchild exit(1); 138159687Snetchild } 139162874Snetchild nc_handle = setnetconfig(); /* open netconfig file */ 140162874Snetchild if (nc_handle == NULL) { 141159687Snetchild syslog(LOG_ERR, "could not read /etc/netconfig"); 142162874Snetchild exit(1); 143159687Snetchild } 144159687Snetchild#ifdef PORTMAP 145162874Snetchild udptrans = ""; 146159687Snetchild tcptrans = ""; 147162874Snetchild#endif 148159687Snetchild 149159687Snetchild nconf = getnetconfigent("unix"); 150159687Snetchild if (nconf == NULL) { 151162874Snetchild syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]); 152159689Snetchild exit(1); 153159687Snetchild } 154159687Snetchild init_transport(nconf); 155159687Snetchild 156159687Snetchild while ((nconf = getnetconfig(nc_handle))) { 157162874Snetchild if (nconf->nc_flag & NC_VISIBLE) 158159687Snetchild init_transport(nconf); 159159687Snetchild } 160159687Snetchild endnetconfig(nc_handle); 161159687Snetchild 162159687Snetchild /* catch the usual termination signals for graceful exit */ 163159687Snetchild (void) signal(SIGCHLD, reap); 164159687Snetchild (void) signal(SIGINT, terminate); 165159687Snetchild (void) signal(SIGTERM, terminate); 166162874Snetchild (void) signal(SIGQUIT, terminate); 167159687Snetchild /* ignore others that could get sent */ 168159687Snetchild (void) signal(SIGPIPE, SIG_IGN); 169162874Snetchild (void) signal(SIGHUP, SIG_IGN); 170159687Snetchild (void) signal(SIGUSR1, SIG_IGN); 171159687Snetchild (void) signal(SIGUSR2, SIG_IGN); 172159687Snetchild#ifdef WARMSTART 173162874Snetchild if (warmstart) { 174159687Snetchild read_warmstart(); 175159687Snetchild } 176159687Snetchild#endif 177159687Snetchild if (debugging) { 178159687Snetchild printf("rpcbind debugging enabled."); 179159687Snetchild if (doabort) { 180159687Snetchild printf(" Will abort on errors!\n"); 181162874Snetchild } else { 182159687Snetchild printf("\n"); 183159687Snetchild } 184159687Snetchild } else { 185159687Snetchild if (daemon(0, 0)) 186159687Snetchild err(1, "fork failed"); 187159687Snetchild } 188159687Snetchild 189162874Snetchild if (runasdaemon) { 190159687Snetchild struct passwd *p; 191159687Snetchild 192159687Snetchild if((p = getpwnam(RUN_AS)) == NULL) { 193159687Snetchild syslog(LOG_ERR, "cannot get uid of daemon: %m"); 194159687Snetchild exit(1); 195159687Snetchild } 196159687Snetchild if (setuid(p->pw_uid) == -1) { 197162874Snetchild syslog(LOG_ERR, "setuid to daemon failed: %m"); 198159687Snetchild exit(1); 199159687Snetchild } 200159689Snetchild } 201159687Snetchild 202159687Snetchild network_init(); 203159687Snetchild 204159687Snetchild my_svc_run(); 205162874Snetchild syslog(LOG_ERR, "svc_run returned unexpectedly"); 206159687Snetchild rpcbind_abort(); 207159687Snetchild /* NOTREACHED */ 208162874Snetchild 209159687Snetchild return 0; 210159687Snetchild} 211162874Snetchild 212162874Snetchild/* 213159687Snetchild * Adds the entry into the rpcbind database. 214162874Snetchild * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also 215159687Snetchild * Returns 0 if succeeds, else fails 216162874Snetchild */ 217162874Snetchildstatic int 218159687Snetchildinit_transport(struct netconfig *nconf) 219162874Snetchild{ 220159687Snetchild int fd; 221162874Snetchild struct t_bind taddr; 222162874Snetchild struct addrinfo hints, *res = NULL; 223162874Snetchild struct __rpc_sockinfo si; 224162874Snetchild SVCXPRT *my_xprt; 225162874Snetchild int status; /* bound checking ? */ 226162874Snetchild int aicode; 227162874Snetchild int addrlen; 228162874Snetchild int nhostsbak; 229162874Snetchild int checkbind; 230162874Snetchild struct sockaddr *sa; 231162874Snetchild u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 232162874Snetchild struct sockaddr_un sun; 233162874Snetchild mode_t oldmask; 234162874Snetchild 235162874Snetchild if ((nconf->nc_semantics != NC_TPI_CLTS) && 236162874Snetchild (nconf->nc_semantics != NC_TPI_COTS) && 237162874Snetchild (nconf->nc_semantics != NC_TPI_COTS_ORD)) 238162874Snetchild return (1); /* not my type */ 239162874Snetchild#ifdef ND_DEBUG 240162874Snetchild if (debugging) { 241188480Snetchild int i; 242170031Sjoel char **s; 243170031Sjoel 244159687Snetchild (void) fprintf(stderr, "%s: %ld lookup routines :\n", 245159687Snetchild nconf->nc_netid, nconf->nc_nlookups); 246159687Snetchild for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups; 247159687Snetchild i++, s++) 248162874Snetchild fprintf(stderr, "[%d] - %s\n", i, *s); 249159687Snetchild } 250159687Snetchild#endif 251162874Snetchild 252159687Snetchild /* 253162874Snetchild * XXX - using RPC library internal functions. For NC_TPI_CLTS 254159687Snetchild * we call this later, for each socket we like to bind. 255162874Snetchild */ 256162874Snetchild if (nconf->nc_semantics != NC_TPI_CLTS) { 257159687Snetchild if ((fd = __rpc_nconf2fd(nconf)) < 0) { 258162874Snetchild syslog(LOG_ERR, "cannot create socket for %s", 259162874Snetchild nconf->nc_netid); 260162874Snetchild return (1); 261162874Snetchild } 262162874Snetchild } 263162874Snetchild 264162874Snetchild if (!__rpc_nconf2sockinfo(nconf, &si)) { 265159687Snetchild syslog(LOG_ERR, "cannot get information for %s", 266159687Snetchild nconf->nc_netid); 267159687Snetchild return (1); 268159687Snetchild } 269162874Snetchild 270159687Snetchild if (!strcmp(nconf->nc_netid, "unix")) { 271159687Snetchild memset(&sun, 0, sizeof sun); 272162874Snetchild sun.sun_family = AF_LOCAL; 273159687Snetchild unlink(_PATH_RPCBINDSOCK); 274159687Snetchild strcpy(sun.sun_path, _PATH_RPCBINDSOCK); 275159687Snetchild sun.sun_len = SUN_LEN(&sun); 276170031Sjoel addrlen = sizeof (struct sockaddr_un); 277170031Sjoel sa = (struct sockaddr *)&sun; 278162874Snetchild } else { 279162874Snetchild /* Get rpcbind's address on this transport */ 280162874Snetchild 281159687Snetchild memset(&hints, 0, sizeof hints); 282162874Snetchild hints.ai_flags = AI_PASSIVE; 283162874Snetchild hints.ai_family = si.si_af; 284162874Snetchild hints.ai_socktype = si.si_socktype; 285162874Snetchild hints.ai_protocol = si.si_proto; 286213779Srpaulo } 287213779Srpaulo if (nconf->nc_semantics == NC_TPI_CLTS) { 288162874Snetchild /* 289162874Snetchild * If no hosts were specified, just bind to INADDR_ANY. Otherwise 290162874Snetchild * make sure 127.0.0.1 is added to the list. 291162874Snetchild */ 292162874Snetchild nhostsbak = nhosts; 293159687Snetchild nhostsbak++; 294170031Sjoel hosts = realloc(hosts, nhostsbak * sizeof(char *)); 295170031Sjoel if (nhostsbak == 1) 296162874Snetchild hosts[0] = "*"; 297162874Snetchild else { 298162874Snetchild if (hints.ai_family == AF_INET) { 299159687Snetchild hosts[nhostsbak - 1] = "127.0.0.1"; 300162874Snetchild } else if (hints.ai_family == AF_INET6) { 301162874Snetchild hosts[nhostsbak - 1] = "::1"; 302162874Snetchild } else 303162874Snetchild return 1; 304188480Snetchild } 305188480Snetchild 306162874Snetchild /* 307162874Snetchild * Bind to specific IPs if asked to 308162874Snetchild */ 309162874Snetchild checkbind = 1; 310162874Snetchild while (nhostsbak > 0) { 311162874Snetchild --nhostsbak; 312159687Snetchild /* 313162874Snetchild * XXX - using RPC library internal functions. 314159687Snetchild */ 315162874Snetchild if ((fd = __rpc_nconf2fd(nconf)) < 0) { 316162874Snetchild syslog(LOG_ERR, "cannot create socket for %s", 317159687Snetchild nconf->nc_netid); 318162874Snetchild return (1); 319159687Snetchild } 320162874Snetchild switch (hints.ai_family) { 321159687Snetchild case AF_INET: 322162874Snetchild if (inet_pton(AF_INET, hosts[nhostsbak], 323162874Snetchild host_addr) == 1) { 324159687Snetchild hints.ai_flags &= AI_NUMERICHOST; 325162874Snetchild } else { 326159687Snetchild /* 327162874Snetchild * Skip if we have a AF_INET6 adress 328159687Snetchild */ 329162874Snetchild if (inet_pton(AF_INET6, 330162874Snetchild hosts[nhostsbak], host_addr) == 1) 331159687Snetchild continue; 332162874Snetchild } 333162874Snetchild break; 334162874Snetchild case AF_INET6: 335162874Snetchild if (inet_pton(AF_INET6, hosts[nhostsbak], 336162874Snetchild host_addr) == 1) { 337162874Snetchild hints.ai_flags &= AI_NUMERICHOST; 338162874Snetchild } else { 339162874Snetchild /* 340162874Snetchild * Skip if we have a AF_INET adress 341162874Snetchild */ 342162874Snetchild if (inet_pton(AF_INET, hosts[nhostsbak], 343162874Snetchild host_addr) == 1) 344162874Snetchild continue; 345162874Snetchild } 346162874Snetchild if (setsockopt(fd, IPPROTO_IPV6, 347162874Snetchild IPV6_V6ONLY, &on, sizeof on) < 0) { 348162874Snetchild syslog(LOG_ERR, 349162874Snetchild "can't set v6-only binding for " 350162874Snetchild "udp6 socket: %m"); 351162874Snetchild continue; 352162874Snetchild } 353162874Snetchild break; 354170031Sjoel default: 355170031Sjoel break; 356170031Sjoel } 357170031Sjoel 358170031Sjoel /* 359170031Sjoel * If no hosts were specified, just bind to INADDR_ANY 360170031Sjoel */ 361170031Sjoel if (strcmp("*", hosts[nhostsbak]) == 0) 362159687Snetchild hosts[nhostsbak] = NULL; 363159687Snetchild 364159687Snetchild if ((aicode = getaddrinfo(hosts[nhostsbak], 365162874Snetchild servname, &hints, &res)) != 0) { 366162874Snetchild syslog(LOG_ERR, 367 "cannot get local address for %s: %s", 368 nconf->nc_netid, gai_strerror(aicode)); 369 continue; 370 } 371 addrlen = res->ai_addrlen; 372 sa = (struct sockaddr *)res->ai_addr; 373 oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 374 if (bind(fd, sa, addrlen) != 0) { 375 syslog(LOG_ERR, "cannot bind %s on %s: %m", 376 (hosts[nhostsbak] == NULL) ? "*" : 377 hosts[nhostsbak], nconf->nc_netid); 378 if (res != NULL) 379 freeaddrinfo(res); 380 continue; 381 } else 382 checkbind++; 383 (void) umask(oldmask); 384 385 /* Copy the address */ 386 taddr.addr.len = taddr.addr.maxlen = addrlen; 387 taddr.addr.buf = malloc(addrlen); 388 if (taddr.addr.buf == NULL) { 389 syslog(LOG_ERR, 390 "cannot allocate memory for %s address", 391 nconf->nc_netid); 392 if (res != NULL) 393 freeaddrinfo(res); 394 return 1; 395 } 396 memcpy(taddr.addr.buf, sa, addrlen); 397#ifdef ND_DEBUG 398 if (debugging) { 399 /* 400 * for debugging print out our universal 401 * address 402 */ 403 char *uaddr; 404 struct netbuf nb; 405 406 nb.buf = sa; 407 nb.len = nb.maxlen = sa->sa_len; 408 uaddr = taddr2uaddr(nconf, &nb); 409 (void) fprintf(stderr, 410 "rpcbind : my address is %s\n", uaddr); 411 (void) free(uaddr); 412 } 413#endif 414 415 if (nconf->nc_semantics != NC_TPI_CLTS) 416 listen(fd, SOMAXCONN); 417 418 my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 419 0, 0); 420 if (my_xprt == (SVCXPRT *)NULL) { 421 syslog(LOG_ERR, "%s: could not create service", 422 nconf->nc_netid); 423 goto error; 424 } 425 } 426 if (!checkbind) 427 return 1; 428 } else { 429 if (strcmp(nconf->nc_netid, "unix") != 0) { 430 if ((aicode = getaddrinfo(NULL, servname, &hints, &res)) 431 != 0) { 432 syslog(LOG_ERR, 433 "cannot get local address for %s: %s", 434 nconf->nc_netid, gai_strerror(aicode)); 435 return 1; 436 } 437 addrlen = res->ai_addrlen; 438 sa = (struct sockaddr *)res->ai_addr; 439 } 440 oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 441 if (bind(fd, sa, addrlen) < 0) { 442 syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid); 443 if (res != NULL) 444 freeaddrinfo(res); 445 return 1; 446 } 447 (void) umask(oldmask); 448 449 /* Copy the address */ 450 taddr.addr.len = taddr.addr.maxlen = addrlen; 451 taddr.addr.buf = malloc(addrlen); 452 if (taddr.addr.buf == NULL) { 453 syslog(LOG_ERR, "cannot allocate memory for %s address", 454 nconf->nc_netid); 455 if (res != NULL) 456 freeaddrinfo(res); 457 return 1; 458 } 459 memcpy(taddr.addr.buf, sa, addrlen); 460#ifdef ND_DEBUG 461 if (debugging) { 462 /* for debugging print out our universal address */ 463 char *uaddr; 464 struct netbuf nb; 465 466 nb.buf = sa; 467 nb.len = nb.maxlen = sa->sa_len; 468 uaddr = taddr2uaddr(nconf, &nb); 469 (void) fprintf(stderr, "rpcbind : my address is %s\n", 470 uaddr); 471 (void) free(uaddr); 472 } 473#endif 474 475 if (nconf->nc_semantics != NC_TPI_CLTS) 476 listen(fd, SOMAXCONN); 477 478 my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 0, 0); 479 if (my_xprt == (SVCXPRT *)NULL) { 480 syslog(LOG_ERR, "%s: could not create service", 481 nconf->nc_netid); 482 goto error; 483 } 484 } 485 486#ifdef PORTMAP 487 /* 488 * Register both the versions for tcp/ip, udp/ip and local. 489 */ 490 if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 && 491 (strcmp(nconf->nc_proto, NC_TCP) == 0 || 492 strcmp(nconf->nc_proto, NC_UDP) == 0)) || 493 strcmp(nconf->nc_netid, "unix") == 0) { 494 struct pmaplist *pml; 495 496 if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, 497 pmap_service, NULL)) { 498 syslog(LOG_ERR, "could not register on %s", 499 nconf->nc_netid); 500 goto error; 501 } 502 pml = malloc(sizeof (struct pmaplist)); 503 if (pml == NULL) { 504 syslog(LOG_ERR, "no memory!"); 505 exit(1); 506 } 507 pml->pml_map.pm_prog = PMAPPROG; 508 pml->pml_map.pm_vers = PMAPVERS; 509 pml->pml_map.pm_port = PMAPPORT; 510 if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 511 if (tcptrans[0]) { 512 syslog(LOG_ERR, 513 "cannot have more than one TCP transport"); 514 goto error; 515 } 516 tcptrans = strdup(nconf->nc_netid); 517 pml->pml_map.pm_prot = IPPROTO_TCP; 518 519 /* Let's snarf the universal address */ 520 /* "h1.h2.h3.h4.p1.p2" */ 521 tcp_uaddr = taddr2uaddr(nconf, &taddr.addr); 522 } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 523 if (udptrans[0]) { 524 syslog(LOG_ERR, 525 "cannot have more than one UDP transport"); 526 goto error; 527 } 528 udptrans = strdup(nconf->nc_netid); 529 pml->pml_map.pm_prot = IPPROTO_UDP; 530 531 /* Let's snarf the universal address */ 532 /* "h1.h2.h3.h4.p1.p2" */ 533 udp_uaddr = taddr2uaddr(nconf, &taddr.addr); 534 } else if (strcmp(nconf->nc_netid, "unix") == 0) 535 pml->pml_map.pm_prot = IPPROTO_ST; 536 pml->pml_next = list_pml; 537 list_pml = pml; 538 539 /* Add version 3 information */ 540 pml = malloc(sizeof (struct pmaplist)); 541 if (pml == NULL) { 542 syslog(LOG_ERR, "no memory!"); 543 exit(1); 544 } 545 pml->pml_map = list_pml->pml_map; 546 pml->pml_map.pm_vers = RPCBVERS; 547 pml->pml_next = list_pml; 548 list_pml = pml; 549 550 /* Add version 4 information */ 551 pml = malloc (sizeof (struct pmaplist)); 552 if (pml == NULL) { 553 syslog(LOG_ERR, "no memory!"); 554 exit(1); 555 } 556 pml->pml_map = list_pml->pml_map; 557 pml->pml_map.pm_vers = RPCBVERS4; 558 pml->pml_next = list_pml; 559 list_pml = pml; 560 561 /* Also add version 2 stuff to rpcbind list */ 562 rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr); 563 } 564#endif 565 566 /* version 3 registration */ 567 if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) { 568 syslog(LOG_ERR, "could not register %s version 3", 569 nconf->nc_netid); 570 goto error; 571 } 572 rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr); 573 574 /* version 4 registration */ 575 if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) { 576 syslog(LOG_ERR, "could not register %s version 4", 577 nconf->nc_netid); 578 goto error; 579 } 580 rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr); 581 582 /* decide if bound checking works for this transport */ 583 status = add_bndlist(nconf, &taddr.addr); 584#ifdef BIND_DEBUG 585 if (debugging) { 586 if (status < 0) { 587 fprintf(stderr, "Error in finding bind status for %s\n", 588 nconf->nc_netid); 589 } else if (status == 0) { 590 fprintf(stderr, "check binding for %s\n", 591 nconf->nc_netid); 592 } else if (status > 0) { 593 fprintf(stderr, "No check binding for %s\n", 594 nconf->nc_netid); 595 } 596 } 597#endif 598 /* 599 * rmtcall only supported on CLTS transports for now. 600 */ 601 if (nconf->nc_semantics == NC_TPI_CLTS) { 602 status = create_rmtcall_fd(nconf); 603 604#ifdef BIND_DEBUG 605 if (debugging) { 606 if (status < 0) { 607 fprintf(stderr, 608 "Could not create rmtcall fd for %s\n", 609 nconf->nc_netid); 610 } else { 611 fprintf(stderr, "rmtcall fd for %s is %d\n", 612 nconf->nc_netid, status); 613 } 614 } 615#endif 616 } 617 return (0); 618error: 619 close(fd); 620 return (1); 621} 622 623static void 624rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf, 625 struct netbuf *addr) 626{ 627 rpcblist_ptr rbl; 628 629 rbl = malloc(sizeof (rpcblist)); 630 if (rbl == NULL) { 631 syslog(LOG_ERR, "no memory!"); 632 exit(1); 633 } 634 635 rbl->rpcb_map.r_prog = prog; 636 rbl->rpcb_map.r_vers = vers; 637 rbl->rpcb_map.r_netid = strdup(nconf->nc_netid); 638 rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr); 639 rbl->rpcb_map.r_owner = strdup(superuser); 640 rbl->rpcb_next = list_rbl; /* Attach to global list */ 641 list_rbl = rbl; 642} 643 644/* 645 * Catch the signal and die 646 */ 647static void 648terminate(int dummy __unused) 649{ 650#ifdef WARMSTART 651 syslog(LOG_ERR, 652 "rpcbind terminating on signal. Restart with \"rpcbind -w\""); 653 write_warmstart(); /* Dump yourself */ 654#endif 655 exit(2); 656} 657 658void 659rpcbind_abort() 660{ 661#ifdef WARMSTART 662 write_warmstart(); /* Dump yourself */ 663#endif 664 abort(); 665} 666 667/* get command line options */ 668static void 669parseargs(int argc, char *argv[]) 670{ 671 int c; 672 673 while ((c = getopt(argc, argv, "dwah:ilLs")) != -1) { 674 switch (c) { 675 case 'a': 676 doabort = 1; /* when debugging, do an abort on */ 677 break; /* errors; for rpcbind developers */ 678 /* only! */ 679 case 'd': 680 debugging = 1; 681 break; 682 case 'h': 683 ++nhosts; 684 hosts = realloc(hosts, nhosts * sizeof(char *)); 685 if (hosts == NULL) 686 errx(1, "Out of memory"); 687 hosts[nhosts - 1] = strdup(optarg); 688 if (hosts[nhosts - 1] == NULL) 689 errx(1, "Out of memory"); 690 break; 691 case 'i': 692 insecure = 1; 693 break; 694 case 'L': 695 oldstyle_local = 1; 696 break; 697 case 'l': 698 verboselog = 1; 699 break; 700 case 's': 701 runasdaemon = 1; 702 break; 703#ifdef WARMSTART 704 case 'w': 705 warmstart = 1; 706 break; 707#endif 708 default: /* error */ 709 fprintf(stderr, "usage: rpcbind [-Idwils]\n"); 710 exit (1); 711 } 712 } 713 if (doabort && !debugging) { 714 fprintf(stderr, 715 "-a (abort) specified without -d (debugging) -- ignored.\n"); 716 doabort = 0; 717 } 718} 719 720void 721reap(int dummy __unused) 722{ 723 int save_errno = errno; 724 725 while (wait3(NULL, WNOHANG, NULL) > 0) 726 ; 727 errno = save_errno; 728} 729 730void 731toggle_verboselog(int dummy __unused) 732{ 733 verboselog = !verboselog; 734} 735