rpcbind.c revision 173412
1109363Smbr/* $NetBSD: rpcbind.c,v 1.3 2002/11/08 00:16:40 fvdl Exp $ */ 274462Salfred/* $FreeBSD: head/usr.sbin/rpcbind/rpcbind.c 173412 2007-11-07 10:53:41Z kevlo $ */ 374462Salfred 474462Salfred/* 574462Salfred * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 674462Salfred * unrestricted use provided that this legend is included on all tape 774462Salfred * media and as a part of the software program in whole or part. Users 874462Salfred * may copy or modify Sun RPC without charge, but are not authorized 974462Salfred * to license or distribute it to anyone else except as part of a product or 1074462Salfred * program developed by the user. 1174462Salfred * 1274462Salfred * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1374462Salfred * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1474462Salfred * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1574462Salfred * 1674462Salfred * Sun RPC is provided with no support and without any obligation on the 1774462Salfred * part of Sun Microsystems, Inc. to assist in its use, correction, 1874462Salfred * modification or enhancement. 1974462Salfred * 2074462Salfred * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 2174462Salfred * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 2274462Salfred * OR ANY PART THEREOF. 2374462Salfred * 2474462Salfred * In no event will Sun Microsystems, Inc. be liable for any lost revenue 2574462Salfred * or profits or other special, indirect and consequential damages, even if 2674462Salfred * Sun has been advised of the possibility of such damages. 2774462Salfred * 2874462Salfred * Sun Microsystems, Inc. 2974462Salfred * 2550 Garcia Avenue 3074462Salfred * Mountain View, California 94043 3174462Salfred */ 3274462Salfred/* 3374462Salfred * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc. 3474462Salfred */ 3574462Salfred 3674462Salfred/* #ident "@(#)rpcbind.c 1.19 94/04/25 SMI" */ 3774462Salfred 3874462Salfred#if 0 3974462Salfred#ifndef lint 4074462Salfredstatic char sccsid[] = "@(#)rpcbind.c 1.35 89/04/21 Copyr 1984 Sun Micro"; 4174462Salfred#endif 4274462Salfred#endif 4374462Salfred 4474462Salfred/* 4574462Salfred * rpcbind.c 4674462Salfred * Implements the program, version to address mapping for rpc. 4774462Salfred * 4874462Salfred */ 4974462Salfred 5074462Salfred#include <sys/types.h> 5174462Salfred#include <sys/stat.h> 5274462Salfred#include <sys/errno.h> 5374462Salfred#include <sys/time.h> 5474462Salfred#include <sys/resource.h> 5574462Salfred#include <sys/wait.h> 5674462Salfred#include <sys/signal.h> 5774462Salfred#include <sys/socket.h> 5874462Salfred#include <sys/un.h> 5974462Salfred#include <rpc/rpc.h> 60109363Smbr#include <rpc/rpc_com.h> 6174462Salfred#ifdef PORTMAP 6274462Salfred#include <netinet/in.h> 6374462Salfred#endif 64104592Salfred#include <arpa/inet.h> 65107725Smbr#include <fcntl.h> 6674462Salfred#include <netdb.h> 6774462Salfred#include <stdio.h> 6874462Salfred#include <netconfig.h> 6974462Salfred#include <stdlib.h> 7074462Salfred#include <unistd.h> 7174462Salfred#include <syslog.h> 7274462Salfred#include <err.h> 7374462Salfred#include <libutil.h> 7474462Salfred#include <pwd.h> 7574462Salfred#include <string.h> 7674462Salfred#include <errno.h> 7774462Salfred#include "rpcbind.h" 7874462Salfred 7974462Salfred/* Global variables */ 8074462Salfredint debugging = 0; /* Tell me what's going on */ 8174462Salfredint doabort = 0; /* When debugging, do an abort on errors */ 8274462Salfredrpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */ 8374462Salfred 8474462Salfred/* who to suid to if -s is given */ 8574462Salfred#define RUN_AS "daemon" 8674462Salfred 87107725Smbr#define RPCBINDDLOCK "/var/run/rpcbind.lock" 88107725Smbr 8974462Salfredint runasdaemon = 0; 9074462Salfredint insecure = 0; 9174462Salfredint oldstyle_local = 0; 9274462Salfredint verboselog = 0; 9374462Salfred 9499774Salfredchar **hosts = NULL; 95168969Smatteoint ipv6_only = 0; 9699774Salfredint nhosts = 0; 9799774Salfredint on = 1; 98107725Smbrint rpcbindlockfd; 9999774Salfred 10074462Salfred#ifdef WARMSTART 10174462Salfred/* Local Variable */ 102108533Sschweikhstatic int warmstart = 0; /* Grab an old copy of registrations. */ 10374462Salfred#endif 10474462Salfred 10574462Salfred#ifdef PORTMAP 10674462Salfredstruct pmaplist *list_pml; /* A list of version 2 rpcbind services */ 10774462Salfredchar *udptrans; /* Name of UDP transport */ 10874462Salfredchar *tcptrans; /* Name of TCP transport */ 10974462Salfredchar *udp_uaddr; /* Universal UDP address */ 11074462Salfredchar *tcp_uaddr; /* Universal TCP address */ 11174462Salfred#endif 11274462Salfredstatic char servname[] = "rpcbind"; 11374462Salfredstatic char superuser[] = "superuser"; 11474462Salfred 115173412Skevloint main(int, char *[]); 11674462Salfred 117173412Skevlostatic int init_transport(struct netconfig *); 118173412Skevlostatic void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *, 119173412Skevlo struct netbuf *); 120173412Skevlostatic void terminate(int); 121173412Skevlostatic void parseargs(int, char *[]); 12274462Salfred 12374462Salfredint 12474462Salfredmain(int argc, char *argv[]) 12574462Salfred{ 12674462Salfred struct netconfig *nconf; 12774462Salfred void *nc_handle; /* Net config handle */ 12874462Salfred struct rlimit rl; 129109363Smbr int maxrec = RPC_MAXDATASIZE; 13074462Salfred 13174462Salfred parseargs(argc, argv); 13274462Salfred 133107725Smbr /* Check that another rpcbind isn't already running. */ 134107725Smbr if ((rpcbindlockfd = (open(RPCBINDDLOCK, 135107725Smbr O_RDONLY|O_CREAT, 0444))) == -1) 136107725Smbr err(1, "%s", RPCBINDDLOCK); 137107725Smbr 138107725Smbr if(flock(rpcbindlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 139107725Smbr errx(1, "another rpcbind is already running. Aborting"); 140107725Smbr 14174462Salfred getrlimit(RLIMIT_NOFILE, &rl); 14274462Salfred if (rl.rlim_cur < 128) { 14374462Salfred if (rl.rlim_max <= 128) 14474462Salfred rl.rlim_cur = rl.rlim_max; 14574462Salfred else 14674462Salfred rl.rlim_cur = 128; 14774462Salfred setrlimit(RLIMIT_NOFILE, &rl); 14874462Salfred } 14974462Salfred openlog("rpcbind", LOG_CONS, LOG_DAEMON); 15074462Salfred if (geteuid()) { /* This command allowed only to root */ 15174462Salfred fprintf(stderr, "Sorry. You are not superuser\n"); 15274462Salfred exit(1); 15374462Salfred } 15474462Salfred nc_handle = setnetconfig(); /* open netconfig file */ 15574462Salfred if (nc_handle == NULL) { 15674462Salfred syslog(LOG_ERR, "could not read /etc/netconfig"); 15774462Salfred exit(1); 15874462Salfred } 15974462Salfred#ifdef PORTMAP 16074462Salfred udptrans = ""; 16174462Salfred tcptrans = ""; 16274462Salfred#endif 16374462Salfred 164107952Smbr nconf = getnetconfigent("local"); 165107952Smbr if (nconf == NULL) 166107952Smbr nconf = getnetconfigent("unix"); 16774462Salfred if (nconf == NULL) { 16874462Salfred syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]); 16974462Salfred exit(1); 17074462Salfred } 171109363Smbr 172109363Smbr rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); 173109363Smbr 17474462Salfred init_transport(nconf); 17574462Salfred 17674462Salfred while ((nconf = getnetconfig(nc_handle))) { 177168969Smatteo if (nconf->nc_flag & NC_VISIBLE) 178168969Smatteo if (ipv6_only == 1 && strcmp(nconf->nc_protofmly, 179168969Smatteo "inet") == 0) { 180168969Smatteo /* DO NOTHING */ 181168969Smatteo } else 182168969Smatteo init_transport(nconf); 18374462Salfred } 18474462Salfred endnetconfig(nc_handle); 18574462Salfred 18674462Salfred /* catch the usual termination signals for graceful exit */ 18774462Salfred (void) signal(SIGCHLD, reap); 18874462Salfred (void) signal(SIGINT, terminate); 18974462Salfred (void) signal(SIGTERM, terminate); 19074462Salfred (void) signal(SIGQUIT, terminate); 19174462Salfred /* ignore others that could get sent */ 19274462Salfred (void) signal(SIGPIPE, SIG_IGN); 19374462Salfred (void) signal(SIGHUP, SIG_IGN); 19474462Salfred (void) signal(SIGUSR1, SIG_IGN); 19574462Salfred (void) signal(SIGUSR2, SIG_IGN); 19674462Salfred#ifdef WARMSTART 19774462Salfred if (warmstart) { 19874462Salfred read_warmstart(); 19974462Salfred } 20074462Salfred#endif 20174462Salfred if (debugging) { 20274462Salfred printf("rpcbind debugging enabled."); 20374462Salfred if (doabort) { 20474462Salfred printf(" Will abort on errors!\n"); 20574462Salfred } else { 20674462Salfred printf("\n"); 20774462Salfred } 20874462Salfred } else { 20974462Salfred if (daemon(0, 0)) 21074462Salfred err(1, "fork failed"); 21174462Salfred } 21274462Salfred 21374462Salfred if (runasdaemon) { 21474462Salfred struct passwd *p; 21574462Salfred 21674462Salfred if((p = getpwnam(RUN_AS)) == NULL) { 21774462Salfred syslog(LOG_ERR, "cannot get uid of daemon: %m"); 21874462Salfred exit(1); 21974462Salfred } 22074462Salfred if (setuid(p->pw_uid) == -1) { 22174462Salfred syslog(LOG_ERR, "setuid to daemon failed: %m"); 22274462Salfred exit(1); 22374462Salfred } 22474462Salfred } 22574462Salfred 22674462Salfred network_init(); 22774462Salfred 22874462Salfred my_svc_run(); 22974462Salfred syslog(LOG_ERR, "svc_run returned unexpectedly"); 23074462Salfred rpcbind_abort(); 23174462Salfred /* NOTREACHED */ 23274462Salfred 23374462Salfred return 0; 23474462Salfred} 23574462Salfred 23674462Salfred/* 23774462Salfred * Adds the entry into the rpcbind database. 23874462Salfred * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also 23974462Salfred * Returns 0 if succeeds, else fails 24074462Salfred */ 24174462Salfredstatic int 24274462Salfredinit_transport(struct netconfig *nconf) 24374462Salfred{ 24474462Salfred int fd; 24574462Salfred struct t_bind taddr; 24674462Salfred struct addrinfo hints, *res = NULL; 24774462Salfred struct __rpc_sockinfo si; 24874462Salfred SVCXPRT *my_xprt; 24974462Salfred int status; /* bound checking ? */ 25074462Salfred int aicode; 25174462Salfred int addrlen; 25299774Salfred int nhostsbak; 25399774Salfred int checkbind; 25474462Salfred struct sockaddr *sa; 25599774Salfred u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 25674462Salfred struct sockaddr_un sun; 25774462Salfred mode_t oldmask; 25874462Salfred 25974462Salfred if ((nconf->nc_semantics != NC_TPI_CLTS) && 260168969Smatteo (nconf->nc_semantics != NC_TPI_COTS) && 261168969Smatteo (nconf->nc_semantics != NC_TPI_COTS_ORD)) 262168969Smatteo return (1); /* not my type */ 26374462Salfred#ifdef ND_DEBUG 26474462Salfred if (debugging) { 265168969Smatteo int i; 266168969Smatteo char **s; 26774462Salfred 268168969Smatteo (void)fprintf(stderr, "%s: %ld lookup routines :\n", 269168969Smatteo nconf->nc_netid, nconf->nc_nlookups); 270168969Smatteo for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups; 271168969Smatteo i++, s++) 272168969Smatteo fprintf(stderr, "[%d] - %s\n", i, *s); 27374462Salfred } 27474462Salfred#endif 27574462Salfred 27674462Salfred /* 277168969Smatteo * XXX - using RPC library internal functions. 27874462Salfred */ 279169174Smatteo if ((strcmp(nconf->nc_netid, "local") == 0) || 280169174Smatteo (strcmp(nconf->nc_netid, "unix") == 0)) { 281169174Smatteo /* 282169174Smatteo * For other transports we call this later, for each socket we 283169174Smatteo * like to bind. 284169174Smatteo */ 285169174Smatteo if ((fd = __rpc_nconf2fd(nconf)) < 0) { 286169174Smatteo int non_fatal = 0; 287169174Smatteo if (errno == EPROTONOSUPPORT) 288169174Smatteo non_fatal = 1; 289169174Smatteo syslog(non_fatal?LOG_DEBUG:LOG_ERR, "cannot create socket for %s", 290169174Smatteo nconf->nc_netid); 291169174Smatteo return (1); 292169174Smatteo } 293169174Smatteo } 294133789Smbr 29574462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) { 296168969Smatteo syslog(LOG_ERR, "cannot get information for %s", 297168969Smatteo nconf->nc_netid); 298168969Smatteo return (1); 29974462Salfred } 30074462Salfred 301107952Smbr if ((strcmp(nconf->nc_netid, "local") == 0) || 302107952Smbr (strcmp(nconf->nc_netid, "unix") == 0)) { 303168969Smatteo memset(&sun, 0, sizeof sun); 304168969Smatteo sun.sun_family = AF_LOCAL; 305168969Smatteo unlink(_PATH_RPCBINDSOCK); 306168969Smatteo strcpy(sun.sun_path, _PATH_RPCBINDSOCK); 307168969Smatteo sun.sun_len = SUN_LEN(&sun); 308168969Smatteo addrlen = sizeof (struct sockaddr_un); 309168969Smatteo sa = (struct sockaddr *)&sun; 31074462Salfred } else { 311168969Smatteo /* Get rpcbind's address on this transport */ 31274462Salfred 313168969Smatteo memset(&hints, 0, sizeof hints); 314168969Smatteo hints.ai_flags = AI_PASSIVE; 315168969Smatteo hints.ai_family = si.si_af; 316168969Smatteo hints.ai_socktype = si.si_socktype; 317168969Smatteo hints.ai_protocol = si.si_proto; 31899774Salfred } 31999774Salfred 320169174Smatteo if ((strcmp(nconf->nc_netid, "local") != 0) && 321169174Smatteo (strcmp(nconf->nc_netid, "unix") != 0)) { 322168969Smatteo /* 323169174Smatteo * If no hosts were specified, just bind to INADDR_ANY. 324169174Smatteo * Otherwise make sure 127.0.0.1 is added to the list. 325168969Smatteo */ 326169174Smatteo nhostsbak = nhosts; 327169174Smatteo nhostsbak++; 328169174Smatteo hosts = realloc(hosts, nhostsbak * sizeof(char *)); 329169174Smatteo if (nhostsbak == 1) 330169174Smatteo hosts[0] = "*"; 331169174Smatteo else { 332169174Smatteo if (hints.ai_family == AF_INET) { 333169174Smatteo hosts[nhostsbak - 1] = "127.0.0.1"; 334169174Smatteo } else if (hints.ai_family == AF_INET6) { 335169174Smatteo hosts[nhostsbak - 1] = "::1"; 336169174Smatteo } else 337169174Smatteo return 1; 338168969Smatteo } 339169174Smatteo 340169174Smatteo /* 341169174Smatteo * Bind to specific IPs if asked to 342169174Smatteo */ 343169174Smatteo checkbind = 1; 344169174Smatteo while (nhostsbak > 0) { 345169174Smatteo --nhostsbak; 346169174Smatteo /* 347169174Smatteo * XXX - using RPC library internal functions. 348169174Smatteo */ 349169174Smatteo if ((fd = __rpc_nconf2fd(nconf)) < 0) { 350169174Smatteo int non_fatal = 0; 351169174Smatteo if (errno == EPROTONOSUPPORT && 352169174Smatteo nconf->nc_semantics != NC_TPI_CLTS) 353169174Smatteo non_fatal = 1; 354169174Smatteo syslog(non_fatal ? LOG_DEBUG : LOG_ERR, 355169174Smatteo "cannot create socket for %s", nconf->nc_netid); 356169174Smatteo return (1); 35799774Salfred } 358169174Smatteo switch (hints.ai_family) { 359169174Smatteo case AF_INET: 360168969Smatteo if (inet_pton(AF_INET, hosts[nhostsbak], 361169174Smatteo host_addr) == 1) { 362169174Smatteo hints.ai_flags &= AI_NUMERICHOST; 363169174Smatteo } else { 364169174Smatteo /* 365169174Smatteo * Skip if we have an AF_INET6 adress. 366169174Smatteo */ 367169174Smatteo if (inet_pton(AF_INET6, 368172901Smatteo hosts[nhostsbak], host_addr) == 1) { 369172901Smatteo close(fd); 370169174Smatteo continue; 371172901Smatteo } 372169174Smatteo } 373169174Smatteo break; 374169174Smatteo case AF_INET6: 375169174Smatteo if (inet_pton(AF_INET6, hosts[nhostsbak], 376169174Smatteo host_addr) == 1) { 377169174Smatteo hints.ai_flags &= AI_NUMERICHOST; 378169174Smatteo } else { 379169174Smatteo /* 380169174Smatteo * Skip if we have an AF_INET adress. 381169174Smatteo */ 382169174Smatteo if (inet_pton(AF_INET, hosts[nhostsbak], 383172901Smatteo host_addr) == 1) { 384172901Smatteo close(fd); 385172901Smatteo continue; 386172901Smatteo } 387169174Smatteo } 388169174Smatteo if (setsockopt(fd, IPPROTO_IPV6, 389169174Smatteo IPV6_V6ONLY, &on, sizeof on) < 0) { 390169174Smatteo syslog(LOG_ERR, 391169174Smatteo "can't set v6-only binding for " 392169174Smatteo "ipv6 socket: %m"); 393168969Smatteo continue; 394169174Smatteo } 395169174Smatteo break; 396169174Smatteo default: 397169174Smatteo break; 39874462Salfred } 399169174Smatteo 400169174Smatteo /* 401169174Smatteo * If no hosts were specified, just bind to INADDR_ANY 402169174Smatteo */ 403169174Smatteo if (strcmp("*", hosts[nhostsbak]) == 0) 404169174Smatteo hosts[nhostsbak] = NULL; 405169174Smatteo if ((strcmp(nconf->nc_netid, "local") != 0) && 406169174Smatteo (strcmp(nconf->nc_netid, "unix") != 0)) { 407169174Smatteo if ((aicode = getaddrinfo(hosts[nhostsbak], 408169174Smatteo servname, &hints, &res)) != 0) { 409169174Smatteo syslog(LOG_ERR, 410169174Smatteo "cannot get local address for %s: %s", 411169174Smatteo nconf->nc_netid, gai_strerror(aicode)); 412169174Smatteo continue; 413169174Smatteo } 414169174Smatteo addrlen = res->ai_addrlen; 415169174Smatteo sa = (struct sockaddr *)res->ai_addr; 416169174Smatteo } 417169174Smatteo oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 418169174Smatteo if (bind(fd, sa, addrlen) != 0) { 419169174Smatteo syslog(LOG_ERR, "cannot bind %s on %s: %m", 420169174Smatteo (hosts[nhostsbak] == NULL) ? "*" : 421169174Smatteo hosts[nhostsbak], nconf->nc_netid); 422169174Smatteo if (res != NULL) 423169174Smatteo freeaddrinfo(res); 424168969Smatteo continue; 425169174Smatteo } else 426169174Smatteo checkbind++; 427169174Smatteo (void)umask(oldmask); 42874462Salfred 429169174Smatteo /* Copy the address */ 430169174Smatteo taddr.addr.len = taddr.addr.maxlen = addrlen; 431169174Smatteo taddr.addr.buf = malloc(addrlen); 432169174Smatteo if (taddr.addr.buf == NULL) { 433168969Smatteo syslog(LOG_ERR, 434169174Smatteo "cannot allocate memory for %s address", 435169174Smatteo nconf->nc_netid); 436169174Smatteo if (res != NULL) 437169174Smatteo freeaddrinfo(res); 438169174Smatteo return 1; 43999774Salfred } 440169174Smatteo memcpy(taddr.addr.buf, sa, addrlen); 441169174Smatteo#ifdef ND_DEBUG 442169174Smatteo if (debugging) { 443169174Smatteo /* 444169174Smatteo * for debugging print out our universal 445169174Smatteo * address 446169174Smatteo */ 447169174Smatteo char *uaddr; 448169174Smatteo struct netbuf nb; 449169174Smatteo 450169174Smatteo nb.buf = sa; 451169174Smatteo nb.len = nb.maxlen = sa->sa_len; 452169174Smatteo uaddr = taddr2uaddr(nconf, &nb); 453169174Smatteo (void)fprintf(stderr, 454169174Smatteo "rpcbind : my address is %s\n", uaddr); 455169174Smatteo (void)free(uaddr); 456169174Smatteo } 457169174Smatteo#endif 458170457Smatteo 459169174Smatteo if (nconf->nc_semantics != NC_TPI_CLTS) 460169174Smatteo listen(fd, SOMAXCONN); 461169174Smatteo 462169174Smatteo my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 463169174Smatteo RPC_MAXDATASIZE, RPC_MAXDATASIZE); 464169174Smatteo if (my_xprt == (SVCXPRT *)NULL) { 465169174Smatteo syslog(LOG_ERR, "%s: could not create service", 466169174Smatteo nconf->nc_netid); 467169174Smatteo goto error; 468169174Smatteo } 469168969Smatteo } 470169174Smatteo if (!checkbind) 471169174Smatteo return 1; 472169174Smatteo } else { 473168969Smatteo oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 474169174Smatteo if (bind(fd, sa, addrlen) < 0) { 475169174Smatteo syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid); 476168969Smatteo if (res != NULL) 477168969Smatteo freeaddrinfo(res); 478169174Smatteo return 1; 479169174Smatteo } 480169174Smatteo (void) umask(oldmask); 481168969Smatteo 482168969Smatteo /* Copy the address */ 483168969Smatteo taddr.addr.len = taddr.addr.maxlen = addrlen; 484168969Smatteo taddr.addr.buf = malloc(addrlen); 485168969Smatteo if (taddr.addr.buf == NULL) { 486169174Smatteo syslog(LOG_ERR, "cannot allocate memory for %s address", 487168969Smatteo nconf->nc_netid); 488168969Smatteo if (res != NULL) 489168969Smatteo freeaddrinfo(res); 490168969Smatteo return 1; 491168969Smatteo } 492168969Smatteo memcpy(taddr.addr.buf, sa, addrlen); 49374462Salfred#ifdef ND_DEBUG 494168969Smatteo if (debugging) { 495169174Smatteo /* for debugging print out our universal address */ 496168969Smatteo char *uaddr; 497168969Smatteo struct netbuf nb; 49874462Salfred 499168969Smatteo nb.buf = sa; 500168969Smatteo nb.len = nb.maxlen = sa->sa_len; 501168969Smatteo uaddr = taddr2uaddr(nconf, &nb); 502169174Smatteo (void) fprintf(stderr, "rpcbind : my address is %s\n", 503169174Smatteo uaddr); 504169174Smatteo (void) free(uaddr); 505168969Smatteo } 50674462Salfred#endif 50774462Salfred 508168969Smatteo if (nconf->nc_semantics != NC_TPI_CLTS) 509168969Smatteo listen(fd, SOMAXCONN); 51074462Salfred 511168969Smatteo my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 512168969Smatteo RPC_MAXDATASIZE, RPC_MAXDATASIZE); 513168969Smatteo if (my_xprt == (SVCXPRT *)NULL) { 514168969Smatteo syslog(LOG_ERR, "%s: could not create service", 515168969Smatteo nconf->nc_netid); 516168969Smatteo goto error; 517168969Smatteo } 51874462Salfred } 51974462Salfred 52074462Salfred#ifdef PORTMAP 52174462Salfred /* 52274462Salfred * Register both the versions for tcp/ip, udp/ip and local. 52374462Salfred */ 52474462Salfred if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 && 52574462Salfred (strcmp(nconf->nc_proto, NC_TCP) == 0 || 52674462Salfred strcmp(nconf->nc_proto, NC_UDP) == 0)) || 527107952Smbr (strcmp(nconf->nc_netid, "unix") == 0) || 528107952Smbr (strcmp(nconf->nc_netid, "local") == 0)) { 52974462Salfred struct pmaplist *pml; 53074462Salfred 53174462Salfred if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, 532121657Smbr pmap_service, 0)) { 53374462Salfred syslog(LOG_ERR, "could not register on %s", 53474462Salfred nconf->nc_netid); 53574462Salfred goto error; 53674462Salfred } 53796788Sjmallett pml = malloc(sizeof (struct pmaplist)); 53896788Sjmallett if (pml == NULL) { 53974462Salfred syslog(LOG_ERR, "no memory!"); 54074462Salfred exit(1); 54174462Salfred } 54274462Salfred pml->pml_map.pm_prog = PMAPPROG; 54374462Salfred pml->pml_map.pm_vers = PMAPVERS; 54474462Salfred pml->pml_map.pm_port = PMAPPORT; 54574462Salfred if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 54674462Salfred if (tcptrans[0]) { 54774462Salfred syslog(LOG_ERR, 54874462Salfred "cannot have more than one TCP transport"); 54974462Salfred goto error; 55074462Salfred } 55174462Salfred tcptrans = strdup(nconf->nc_netid); 55274462Salfred pml->pml_map.pm_prot = IPPROTO_TCP; 55374462Salfred 55474462Salfred /* Let's snarf the universal address */ 55574462Salfred /* "h1.h2.h3.h4.p1.p2" */ 55674462Salfred tcp_uaddr = taddr2uaddr(nconf, &taddr.addr); 55774462Salfred } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 55874462Salfred if (udptrans[0]) { 55974462Salfred syslog(LOG_ERR, 56074462Salfred "cannot have more than one UDP transport"); 56174462Salfred goto error; 56274462Salfred } 56374462Salfred udptrans = strdup(nconf->nc_netid); 56474462Salfred pml->pml_map.pm_prot = IPPROTO_UDP; 56574462Salfred 56674462Salfred /* Let's snarf the universal address */ 56774462Salfred /* "h1.h2.h3.h4.p1.p2" */ 56874462Salfred udp_uaddr = taddr2uaddr(nconf, &taddr.addr); 569107952Smbr } else if (strcmp(nconf->nc_netid, "local") == 0) 57074462Salfred pml->pml_map.pm_prot = IPPROTO_ST; 571107952Smbr else if (strcmp(nconf->nc_netid, "unix") == 0) 572107952Smbr pml->pml_map.pm_prot = IPPROTO_ST; 57374462Salfred pml->pml_next = list_pml; 57474462Salfred list_pml = pml; 57574462Salfred 57674462Salfred /* Add version 3 information */ 57796788Sjmallett pml = malloc(sizeof (struct pmaplist)); 57896788Sjmallett if (pml == NULL) { 57974462Salfred syslog(LOG_ERR, "no memory!"); 58074462Salfred exit(1); 58174462Salfred } 58274462Salfred pml->pml_map = list_pml->pml_map; 58374462Salfred pml->pml_map.pm_vers = RPCBVERS; 58474462Salfred pml->pml_next = list_pml; 58574462Salfred list_pml = pml; 58674462Salfred 58774462Salfred /* Add version 4 information */ 58896788Sjmallett pml = malloc (sizeof (struct pmaplist)); 58996788Sjmallett if (pml == NULL) { 59074462Salfred syslog(LOG_ERR, "no memory!"); 59174462Salfred exit(1); 59274462Salfred } 59374462Salfred pml->pml_map = list_pml->pml_map; 59474462Salfred pml->pml_map.pm_vers = RPCBVERS4; 59574462Salfred pml->pml_next = list_pml; 59674462Salfred list_pml = pml; 59774462Salfred 59874462Salfred /* Also add version 2 stuff to rpcbind list */ 59974462Salfred rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr); 60074462Salfred } 60174462Salfred#endif 60274462Salfred 60374462Salfred /* version 3 registration */ 60474462Salfred if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) { 60574462Salfred syslog(LOG_ERR, "could not register %s version 3", 60674462Salfred nconf->nc_netid); 60774462Salfred goto error; 60874462Salfred } 60974462Salfred rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr); 61074462Salfred 61174462Salfred /* version 4 registration */ 61274462Salfred if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) { 61374462Salfred syslog(LOG_ERR, "could not register %s version 4", 61474462Salfred nconf->nc_netid); 61574462Salfred goto error; 61674462Salfred } 61774462Salfred rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr); 61874462Salfred 61974462Salfred /* decide if bound checking works for this transport */ 62074462Salfred status = add_bndlist(nconf, &taddr.addr); 62174462Salfred#ifdef BIND_DEBUG 62274462Salfred if (debugging) { 62374462Salfred if (status < 0) { 62474462Salfred fprintf(stderr, "Error in finding bind status for %s\n", 62574462Salfred nconf->nc_netid); 62674462Salfred } else if (status == 0) { 62774462Salfred fprintf(stderr, "check binding for %s\n", 62874462Salfred nconf->nc_netid); 62974462Salfred } else if (status > 0) { 63074462Salfred fprintf(stderr, "No check binding for %s\n", 63174462Salfred nconf->nc_netid); 63274462Salfred } 63374462Salfred } 63474462Salfred#endif 63574462Salfred /* 63674462Salfred * rmtcall only supported on CLTS transports for now. 63774462Salfred */ 63874462Salfred if (nconf->nc_semantics == NC_TPI_CLTS) { 63974462Salfred status = create_rmtcall_fd(nconf); 64074462Salfred 64174462Salfred#ifdef BIND_DEBUG 64274462Salfred if (debugging) { 64374462Salfred if (status < 0) { 64474462Salfred fprintf(stderr, 64574462Salfred "Could not create rmtcall fd for %s\n", 64674462Salfred nconf->nc_netid); 64774462Salfred } else { 64874462Salfred fprintf(stderr, "rmtcall fd for %s is %d\n", 64974462Salfred nconf->nc_netid, status); 65074462Salfred } 65174462Salfred } 65274462Salfred#endif 65374462Salfred } 65474462Salfred return (0); 65574462Salfrederror: 65674462Salfred close(fd); 65774462Salfred return (1); 65874462Salfred} 65974462Salfred 66074462Salfredstatic void 66174462Salfredrbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf, 66274462Salfred struct netbuf *addr) 66374462Salfred{ 66474462Salfred rpcblist_ptr rbl; 66574462Salfred 66696788Sjmallett rbl = malloc(sizeof (rpcblist)); 66796788Sjmallett if (rbl == NULL) { 66874462Salfred syslog(LOG_ERR, "no memory!"); 66974462Salfred exit(1); 67074462Salfred } 67174462Salfred 67274462Salfred rbl->rpcb_map.r_prog = prog; 67374462Salfred rbl->rpcb_map.r_vers = vers; 67474462Salfred rbl->rpcb_map.r_netid = strdup(nconf->nc_netid); 67574462Salfred rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr); 67674462Salfred rbl->rpcb_map.r_owner = strdup(superuser); 67774462Salfred rbl->rpcb_next = list_rbl; /* Attach to global list */ 67874462Salfred list_rbl = rbl; 67974462Salfred} 68074462Salfred 68174462Salfred/* 68274462Salfred * Catch the signal and die 68374462Salfred */ 68474462Salfredstatic void 685104592Salfredterminate(int dummy __unused) 68674462Salfred{ 687107725Smbr close(rpcbindlockfd); 68874462Salfred#ifdef WARMSTART 68974462Salfred syslog(LOG_ERR, 69074462Salfred "rpcbind terminating on signal. Restart with \"rpcbind -w\""); 69174462Salfred write_warmstart(); /* Dump yourself */ 69274462Salfred#endif 69374462Salfred exit(2); 69474462Salfred} 69574462Salfred 69674462Salfredvoid 69774462Salfredrpcbind_abort() 69874462Salfred{ 69974462Salfred#ifdef WARMSTART 70074462Salfred write_warmstart(); /* Dump yourself */ 70174462Salfred#endif 70274462Salfred abort(); 70374462Salfred} 70474462Salfred 70574462Salfred/* get command line options */ 70674462Salfredstatic void 70774462Salfredparseargs(int argc, char *argv[]) 70874462Salfred{ 70974462Salfred int c; 71074462Salfred 711137327Sdd#ifdef WARMSTART 712137327Sdd#define WSOP "w" 713137327Sdd#else 714137327Sdd#define WSOP "" 715137327Sdd#endif 716168969Smatteo while ((c = getopt(argc, argv, "6adh:iLls" WSOP)) != -1) { 71774462Salfred switch (c) { 718168969Smatteo case '6': 719168969Smatteo ipv6_only = 1; 720168969Smatteo break; 72174462Salfred case 'a': 72274462Salfred doabort = 1; /* when debugging, do an abort on */ 72374462Salfred break; /* errors; for rpcbind developers */ 72474462Salfred /* only! */ 72574462Salfred case 'd': 72674462Salfred debugging = 1; 72774462Salfred break; 72899774Salfred case 'h': 72999774Salfred ++nhosts; 73099774Salfred hosts = realloc(hosts, nhosts * sizeof(char *)); 73199774Salfred if (hosts == NULL) 73299774Salfred errx(1, "Out of memory"); 73399774Salfred hosts[nhosts - 1] = strdup(optarg); 73499774Salfred if (hosts[nhosts - 1] == NULL) 73599774Salfred errx(1, "Out of memory"); 73699774Salfred break; 73774462Salfred case 'i': 73874462Salfred insecure = 1; 73974462Salfred break; 74074462Salfred case 'L': 74174462Salfred oldstyle_local = 1; 74274462Salfred break; 74374462Salfred case 'l': 74474462Salfred verboselog = 1; 74574462Salfred break; 74674462Salfred case 's': 74774462Salfred runasdaemon = 1; 74874462Salfred break; 74974462Salfred#ifdef WARMSTART 75074462Salfred case 'w': 75174462Salfred warmstart = 1; 75274462Salfred break; 75374462Salfred#endif 75474462Salfred default: /* error */ 755137327Sdd fprintf(stderr, 756168969Smatteo "usage: rpcbind [-6adiLls%s] [-h bindip]\n", 757137327Sdd WSOP); 75874462Salfred exit (1); 75974462Salfred } 76074462Salfred } 76174462Salfred if (doabort && !debugging) { 76274462Salfred fprintf(stderr, 76374462Salfred "-a (abort) specified without -d (debugging) -- ignored.\n"); 76474462Salfred doabort = 0; 76574462Salfred } 766137327Sdd#undef WSOP 76774462Salfred} 76874462Salfred 76974462Salfredvoid 770104592Salfredreap(int dummy __unused) 77174462Salfred{ 77274462Salfred int save_errno = errno; 77374462Salfred 77474462Salfred while (wait3(NULL, WNOHANG, NULL) > 0) 77574462Salfred ; 77674462Salfred errno = save_errno; 77774462Salfred} 77874462Salfred 77974462Salfredvoid 780104592Salfredtoggle_verboselog(int dummy __unused) 78174462Salfred{ 78274462Salfred verboselog = !verboselog; 78374462Salfred} 784