1109363Smbr/* $NetBSD: rpcbind.c,v 1.3 2002/11/08 00:16:40 fvdl Exp $ */ 274462Salfred/* $FreeBSD$ */ 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; 95203710Simpstruct sockaddr **bound_sa; 96168969Smatteoint ipv6_only = 0; 9799774Salfredint nhosts = 0; 9899774Salfredint on = 1; 99107725Smbrint rpcbindlockfd; 10099774Salfred 10174462Salfred#ifdef WARMSTART 10274462Salfred/* Local Variable */ 103108533Sschweikhstatic int warmstart = 0; /* Grab an old copy of registrations. */ 10474462Salfred#endif 10574462Salfred 10674462Salfred#ifdef PORTMAP 10774462Salfredstruct pmaplist *list_pml; /* A list of version 2 rpcbind services */ 10874462Salfredchar *udptrans; /* Name of UDP transport */ 10974462Salfredchar *tcptrans; /* Name of TCP transport */ 11074462Salfredchar *udp_uaddr; /* Universal UDP address */ 11174462Salfredchar *tcp_uaddr; /* Universal TCP address */ 11274462Salfred#endif 11374462Salfredstatic char servname[] = "rpcbind"; 11474462Salfredstatic char superuser[] = "superuser"; 11574462Salfred 116173412Skevloint main(int, char *[]); 11774462Salfred 118173412Skevlostatic int init_transport(struct netconfig *); 119173412Skevlostatic void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *, 120173412Skevlo struct netbuf *); 121173412Skevlostatic void terminate(int); 122173412Skevlostatic void parseargs(int, char *[]); 123203710Simpstatic void update_bound_sa(void); 12474462Salfred 12574462Salfredint 12674462Salfredmain(int argc, char *argv[]) 12774462Salfred{ 12874462Salfred struct netconfig *nconf; 12974462Salfred void *nc_handle; /* Net config handle */ 13074462Salfred struct rlimit rl; 131109363Smbr int maxrec = RPC_MAXDATASIZE; 13274462Salfred 13374462Salfred parseargs(argc, argv); 13474462Salfred 135203710Simp update_bound_sa(); 136203710Simp 137107725Smbr /* Check that another rpcbind isn't already running. */ 138107725Smbr if ((rpcbindlockfd = (open(RPCBINDDLOCK, 139107725Smbr O_RDONLY|O_CREAT, 0444))) == -1) 140107725Smbr err(1, "%s", RPCBINDDLOCK); 141107725Smbr 142107725Smbr if(flock(rpcbindlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 143107725Smbr errx(1, "another rpcbind is already running. Aborting"); 144107725Smbr 14574462Salfred getrlimit(RLIMIT_NOFILE, &rl); 14674462Salfred if (rl.rlim_cur < 128) { 14774462Salfred if (rl.rlim_max <= 128) 14874462Salfred rl.rlim_cur = rl.rlim_max; 14974462Salfred else 15074462Salfred rl.rlim_cur = 128; 15174462Salfred setrlimit(RLIMIT_NOFILE, &rl); 15274462Salfred } 15374462Salfred openlog("rpcbind", LOG_CONS, LOG_DAEMON); 15474462Salfred if (geteuid()) { /* This command allowed only to root */ 15574462Salfred fprintf(stderr, "Sorry. You are not superuser\n"); 15674462Salfred exit(1); 15774462Salfred } 15874462Salfred nc_handle = setnetconfig(); /* open netconfig file */ 15974462Salfred if (nc_handle == NULL) { 16074462Salfred syslog(LOG_ERR, "could not read /etc/netconfig"); 16174462Salfred exit(1); 16274462Salfred } 16374462Salfred#ifdef PORTMAP 16474462Salfred udptrans = ""; 16574462Salfred tcptrans = ""; 16674462Salfred#endif 16774462Salfred 168107952Smbr nconf = getnetconfigent("local"); 169107952Smbr if (nconf == NULL) 170107952Smbr nconf = getnetconfigent("unix"); 17174462Salfred if (nconf == NULL) { 17274462Salfred syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]); 17374462Salfred exit(1); 17474462Salfred } 175109363Smbr 176109363Smbr rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); 177109363Smbr 17874462Salfred init_transport(nconf); 17974462Salfred 18074462Salfred while ((nconf = getnetconfig(nc_handle))) { 181224001Sdelphij if (nconf->nc_flag & NC_VISIBLE) { 182168969Smatteo if (ipv6_only == 1 && strcmp(nconf->nc_protofmly, 183168969Smatteo "inet") == 0) { 184168969Smatteo /* DO NOTHING */ 185168969Smatteo } else 186168969Smatteo init_transport(nconf); 187224001Sdelphij } 18874462Salfred } 18974462Salfred endnetconfig(nc_handle); 19074462Salfred 19174462Salfred /* catch the usual termination signals for graceful exit */ 19274462Salfred (void) signal(SIGCHLD, reap); 19374462Salfred (void) signal(SIGINT, terminate); 19474462Salfred (void) signal(SIGTERM, terminate); 19574462Salfred (void) signal(SIGQUIT, terminate); 19674462Salfred /* ignore others that could get sent */ 19774462Salfred (void) signal(SIGPIPE, SIG_IGN); 19874462Salfred (void) signal(SIGHUP, SIG_IGN); 19974462Salfred (void) signal(SIGUSR1, SIG_IGN); 20074462Salfred (void) signal(SIGUSR2, SIG_IGN); 20174462Salfred#ifdef WARMSTART 20274462Salfred if (warmstart) { 20374462Salfred read_warmstart(); 20474462Salfred } 20574462Salfred#endif 20674462Salfred if (debugging) { 20774462Salfred printf("rpcbind debugging enabled."); 20874462Salfred if (doabort) { 20974462Salfred printf(" Will abort on errors!\n"); 21074462Salfred } else { 21174462Salfred printf("\n"); 21274462Salfred } 21374462Salfred } else { 21474462Salfred if (daemon(0, 0)) 21574462Salfred err(1, "fork failed"); 21674462Salfred } 21774462Salfred 21874462Salfred if (runasdaemon) { 21974462Salfred struct passwd *p; 22074462Salfred 22174462Salfred if((p = getpwnam(RUN_AS)) == NULL) { 22274462Salfred syslog(LOG_ERR, "cannot get uid of daemon: %m"); 22374462Salfred exit(1); 22474462Salfred } 22574462Salfred if (setuid(p->pw_uid) == -1) { 22674462Salfred syslog(LOG_ERR, "setuid to daemon failed: %m"); 22774462Salfred exit(1); 22874462Salfred } 22974462Salfred } 23074462Salfred 23174462Salfred network_init(); 23274462Salfred 23374462Salfred my_svc_run(); 23474462Salfred syslog(LOG_ERR, "svc_run returned unexpectedly"); 23574462Salfred rpcbind_abort(); 23674462Salfred /* NOTREACHED */ 23774462Salfred 23874462Salfred return 0; 23974462Salfred} 24074462Salfred 24174462Salfred/* 24274462Salfred * Adds the entry into the rpcbind database. 24374462Salfred * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also 24474462Salfred * Returns 0 if succeeds, else fails 24574462Salfred */ 24674462Salfredstatic int 24774462Salfredinit_transport(struct netconfig *nconf) 24874462Salfred{ 24974462Salfred int fd; 25074462Salfred struct t_bind taddr; 25174462Salfred struct addrinfo hints, *res = NULL; 25274462Salfred struct __rpc_sockinfo si; 25374462Salfred SVCXPRT *my_xprt; 25474462Salfred int status; /* bound checking ? */ 25574462Salfred int aicode; 25674462Salfred int addrlen; 25799774Salfred int nhostsbak; 258176290Syar int bound; 25974462Salfred struct sockaddr *sa; 26099774Salfred u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 26174462Salfred struct sockaddr_un sun; 26274462Salfred mode_t oldmask; 26374462Salfred 26474462Salfred if ((nconf->nc_semantics != NC_TPI_CLTS) && 265168969Smatteo (nconf->nc_semantics != NC_TPI_COTS) && 266168969Smatteo (nconf->nc_semantics != NC_TPI_COTS_ORD)) 267168969Smatteo return (1); /* not my type */ 26874462Salfred#ifdef ND_DEBUG 26974462Salfred if (debugging) { 270168969Smatteo int i; 271168969Smatteo char **s; 27274462Salfred 273168969Smatteo (void)fprintf(stderr, "%s: %ld lookup routines :\n", 274168969Smatteo nconf->nc_netid, nconf->nc_nlookups); 275168969Smatteo for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups; 276168969Smatteo i++, s++) 277168969Smatteo fprintf(stderr, "[%d] - %s\n", i, *s); 27874462Salfred } 27974462Salfred#endif 28074462Salfred 28174462Salfred /* 282168969Smatteo * XXX - using RPC library internal functions. 28374462Salfred */ 284169174Smatteo if ((strcmp(nconf->nc_netid, "local") == 0) || 285169174Smatteo (strcmp(nconf->nc_netid, "unix") == 0)) { 286169174Smatteo /* 287169174Smatteo * For other transports we call this later, for each socket we 288169174Smatteo * like to bind. 289169174Smatteo */ 290169174Smatteo if ((fd = __rpc_nconf2fd(nconf)) < 0) { 291169174Smatteo int non_fatal = 0; 292169174Smatteo if (errno == EPROTONOSUPPORT) 293169174Smatteo non_fatal = 1; 294169174Smatteo syslog(non_fatal?LOG_DEBUG:LOG_ERR, "cannot create socket for %s", 295169174Smatteo nconf->nc_netid); 296169174Smatteo return (1); 297169174Smatteo } 298169174Smatteo } 299133789Smbr 30074462Salfred if (!__rpc_nconf2sockinfo(nconf, &si)) { 301168969Smatteo syslog(LOG_ERR, "cannot get information for %s", 302168969Smatteo nconf->nc_netid); 303168969Smatteo return (1); 30474462Salfred } 30574462Salfred 306107952Smbr if ((strcmp(nconf->nc_netid, "local") == 0) || 307107952Smbr (strcmp(nconf->nc_netid, "unix") == 0)) { 308168969Smatteo memset(&sun, 0, sizeof sun); 309168969Smatteo sun.sun_family = AF_LOCAL; 310168969Smatteo unlink(_PATH_RPCBINDSOCK); 311168969Smatteo strcpy(sun.sun_path, _PATH_RPCBINDSOCK); 312168969Smatteo sun.sun_len = SUN_LEN(&sun); 313168969Smatteo addrlen = sizeof (struct sockaddr_un); 314168969Smatteo sa = (struct sockaddr *)&sun; 31574462Salfred } else { 316168969Smatteo /* Get rpcbind's address on this transport */ 31774462Salfred 318168969Smatteo memset(&hints, 0, sizeof hints); 319168969Smatteo hints.ai_flags = AI_PASSIVE; 320168969Smatteo hints.ai_family = si.si_af; 321168969Smatteo hints.ai_socktype = si.si_socktype; 322168969Smatteo hints.ai_protocol = si.si_proto; 32399774Salfred } 32499774Salfred 325169174Smatteo if ((strcmp(nconf->nc_netid, "local") != 0) && 326169174Smatteo (strcmp(nconf->nc_netid, "unix") != 0)) { 327168969Smatteo /* 328169174Smatteo * If no hosts were specified, just bind to INADDR_ANY. 329169174Smatteo * Otherwise make sure 127.0.0.1 is added to the list. 330168969Smatteo */ 331203710Simp nhostsbak = nhosts + 1; 332169174Smatteo hosts = realloc(hosts, nhostsbak * sizeof(char *)); 333169174Smatteo if (nhostsbak == 1) 334169174Smatteo hosts[0] = "*"; 335169174Smatteo else { 336169174Smatteo if (hints.ai_family == AF_INET) { 337169174Smatteo hosts[nhostsbak - 1] = "127.0.0.1"; 338169174Smatteo } else if (hints.ai_family == AF_INET6) { 339169174Smatteo hosts[nhostsbak - 1] = "::1"; 340169174Smatteo } else 341169174Smatteo return 1; 342168969Smatteo } 343169174Smatteo 344169174Smatteo /* 345169174Smatteo * Bind to specific IPs if asked to 346169174Smatteo */ 347176290Syar bound = 0; 348169174Smatteo while (nhostsbak > 0) { 349169174Smatteo --nhostsbak; 350169174Smatteo /* 351169174Smatteo * XXX - using RPC library internal functions. 352169174Smatteo */ 353169174Smatteo if ((fd = __rpc_nconf2fd(nconf)) < 0) { 354169174Smatteo int non_fatal = 0; 355169174Smatteo if (errno == EPROTONOSUPPORT && 356169174Smatteo nconf->nc_semantics != NC_TPI_CLTS) 357169174Smatteo non_fatal = 1; 358169174Smatteo syslog(non_fatal ? LOG_DEBUG : LOG_ERR, 359169174Smatteo "cannot create socket for %s", nconf->nc_netid); 360169174Smatteo return (1); 36199774Salfred } 362169174Smatteo switch (hints.ai_family) { 363169174Smatteo case AF_INET: 364168969Smatteo if (inet_pton(AF_INET, hosts[nhostsbak], 365169174Smatteo host_addr) == 1) { 366169174Smatteo hints.ai_flags &= AI_NUMERICHOST; 367169174Smatteo } else { 368169174Smatteo /* 369169174Smatteo * Skip if we have an AF_INET6 adress. 370169174Smatteo */ 371169174Smatteo if (inet_pton(AF_INET6, 372172901Smatteo hosts[nhostsbak], host_addr) == 1) { 373172901Smatteo close(fd); 374169174Smatteo continue; 375172901Smatteo } 376169174Smatteo } 377169174Smatteo break; 378169174Smatteo case AF_INET6: 379169174Smatteo if (inet_pton(AF_INET6, hosts[nhostsbak], 380169174Smatteo host_addr) == 1) { 381169174Smatteo hints.ai_flags &= AI_NUMERICHOST; 382169174Smatteo } else { 383169174Smatteo /* 384169174Smatteo * Skip if we have an AF_INET adress. 385169174Smatteo */ 386169174Smatteo if (inet_pton(AF_INET, hosts[nhostsbak], 387172901Smatteo host_addr) == 1) { 388172901Smatteo close(fd); 389172901Smatteo continue; 390172901Smatteo } 391169174Smatteo } 392169174Smatteo if (setsockopt(fd, IPPROTO_IPV6, 393169174Smatteo IPV6_V6ONLY, &on, sizeof on) < 0) { 394169174Smatteo syslog(LOG_ERR, 395169174Smatteo "can't set v6-only binding for " 396169174Smatteo "ipv6 socket: %m"); 397168969Smatteo continue; 398169174Smatteo } 399169174Smatteo break; 400169174Smatteo default: 401169174Smatteo break; 40274462Salfred } 403169174Smatteo 404169174Smatteo /* 405169174Smatteo * If no hosts were specified, just bind to INADDR_ANY 406169174Smatteo */ 407169174Smatteo if (strcmp("*", hosts[nhostsbak]) == 0) 408169174Smatteo hosts[nhostsbak] = NULL; 409169174Smatteo if ((strcmp(nconf->nc_netid, "local") != 0) && 410169174Smatteo (strcmp(nconf->nc_netid, "unix") != 0)) { 411169174Smatteo if ((aicode = getaddrinfo(hosts[nhostsbak], 412169174Smatteo servname, &hints, &res)) != 0) { 413169174Smatteo syslog(LOG_ERR, 414169174Smatteo "cannot get local address for %s: %s", 415169174Smatteo nconf->nc_netid, gai_strerror(aicode)); 416169174Smatteo continue; 417169174Smatteo } 418169174Smatteo addrlen = res->ai_addrlen; 419169174Smatteo sa = (struct sockaddr *)res->ai_addr; 420169174Smatteo } 421169174Smatteo oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 422169174Smatteo if (bind(fd, sa, addrlen) != 0) { 423169174Smatteo syslog(LOG_ERR, "cannot bind %s on %s: %m", 424169174Smatteo (hosts[nhostsbak] == NULL) ? "*" : 425169174Smatteo hosts[nhostsbak], nconf->nc_netid); 426169174Smatteo if (res != NULL) 427169174Smatteo freeaddrinfo(res); 428168969Smatteo continue; 429169174Smatteo } else 430176290Syar bound = 1; 431169174Smatteo (void)umask(oldmask); 43274462Salfred 433169174Smatteo /* Copy the address */ 434169174Smatteo taddr.addr.len = taddr.addr.maxlen = addrlen; 435169174Smatteo taddr.addr.buf = malloc(addrlen); 436169174Smatteo if (taddr.addr.buf == NULL) { 437168969Smatteo syslog(LOG_ERR, 438169174Smatteo "cannot allocate memory for %s address", 439169174Smatteo nconf->nc_netid); 440169174Smatteo if (res != NULL) 441169174Smatteo freeaddrinfo(res); 442169174Smatteo return 1; 44399774Salfred } 444169174Smatteo memcpy(taddr.addr.buf, sa, addrlen); 445169174Smatteo#ifdef ND_DEBUG 446169174Smatteo if (debugging) { 447169174Smatteo /* 448169174Smatteo * for debugging print out our universal 449169174Smatteo * address 450169174Smatteo */ 451169174Smatteo char *uaddr; 452169174Smatteo struct netbuf nb; 453169174Smatteo 454169174Smatteo nb.buf = sa; 455169174Smatteo nb.len = nb.maxlen = sa->sa_len; 456169174Smatteo uaddr = taddr2uaddr(nconf, &nb); 457169174Smatteo (void)fprintf(stderr, 458169174Smatteo "rpcbind : my address is %s\n", uaddr); 459169174Smatteo (void)free(uaddr); 460169174Smatteo } 461169174Smatteo#endif 462170457Smatteo 463169174Smatteo if (nconf->nc_semantics != NC_TPI_CLTS) 464169174Smatteo listen(fd, SOMAXCONN); 465169174Smatteo 466169174Smatteo my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 467169174Smatteo RPC_MAXDATASIZE, RPC_MAXDATASIZE); 468169174Smatteo if (my_xprt == (SVCXPRT *)NULL) { 469169174Smatteo syslog(LOG_ERR, "%s: could not create service", 470169174Smatteo nconf->nc_netid); 471169174Smatteo goto error; 472169174Smatteo } 473168969Smatteo } 474176290Syar if (!bound) 475169174Smatteo return 1; 476169174Smatteo } else { 477168969Smatteo oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 478169174Smatteo if (bind(fd, sa, addrlen) < 0) { 479169174Smatteo syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid); 480168969Smatteo if (res != NULL) 481168969Smatteo freeaddrinfo(res); 482169174Smatteo return 1; 483169174Smatteo } 484169174Smatteo (void) umask(oldmask); 485168969Smatteo 486168969Smatteo /* Copy the address */ 487168969Smatteo taddr.addr.len = taddr.addr.maxlen = addrlen; 488168969Smatteo taddr.addr.buf = malloc(addrlen); 489168969Smatteo if (taddr.addr.buf == NULL) { 490169174Smatteo syslog(LOG_ERR, "cannot allocate memory for %s address", 491168969Smatteo nconf->nc_netid); 492168969Smatteo if (res != NULL) 493168969Smatteo freeaddrinfo(res); 494168969Smatteo return 1; 495168969Smatteo } 496168969Smatteo memcpy(taddr.addr.buf, sa, addrlen); 49774462Salfred#ifdef ND_DEBUG 498168969Smatteo if (debugging) { 499169174Smatteo /* for debugging print out our universal address */ 500168969Smatteo char *uaddr; 501168969Smatteo struct netbuf nb; 50274462Salfred 503168969Smatteo nb.buf = sa; 504168969Smatteo nb.len = nb.maxlen = sa->sa_len; 505168969Smatteo uaddr = taddr2uaddr(nconf, &nb); 506169174Smatteo (void) fprintf(stderr, "rpcbind : my address is %s\n", 507169174Smatteo uaddr); 508169174Smatteo (void) free(uaddr); 509168969Smatteo } 51074462Salfred#endif 51174462Salfred 512168969Smatteo if (nconf->nc_semantics != NC_TPI_CLTS) 513168969Smatteo listen(fd, SOMAXCONN); 51474462Salfred 515168969Smatteo my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 516168969Smatteo RPC_MAXDATASIZE, RPC_MAXDATASIZE); 517168969Smatteo if (my_xprt == (SVCXPRT *)NULL) { 518168969Smatteo syslog(LOG_ERR, "%s: could not create service", 519168969Smatteo nconf->nc_netid); 520168969Smatteo goto error; 521168969Smatteo } 52274462Salfred } 52374462Salfred 52474462Salfred#ifdef PORTMAP 52574462Salfred /* 52674462Salfred * Register both the versions for tcp/ip, udp/ip and local. 52774462Salfred */ 52874462Salfred if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 && 52974462Salfred (strcmp(nconf->nc_proto, NC_TCP) == 0 || 53074462Salfred strcmp(nconf->nc_proto, NC_UDP) == 0)) || 531107952Smbr (strcmp(nconf->nc_netid, "unix") == 0) || 532107952Smbr (strcmp(nconf->nc_netid, "local") == 0)) { 53374462Salfred struct pmaplist *pml; 53474462Salfred 53574462Salfred if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, 536121657Smbr pmap_service, 0)) { 53774462Salfred syslog(LOG_ERR, "could not register on %s", 53874462Salfred nconf->nc_netid); 53974462Salfred goto error; 54074462Salfred } 54196788Sjmallett pml = malloc(sizeof (struct pmaplist)); 54296788Sjmallett if (pml == NULL) { 54374462Salfred syslog(LOG_ERR, "no memory!"); 54474462Salfred exit(1); 54574462Salfred } 54674462Salfred pml->pml_map.pm_prog = PMAPPROG; 54774462Salfred pml->pml_map.pm_vers = PMAPVERS; 54874462Salfred pml->pml_map.pm_port = PMAPPORT; 54974462Salfred if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 55074462Salfred if (tcptrans[0]) { 55174462Salfred syslog(LOG_ERR, 55274462Salfred "cannot have more than one TCP transport"); 55374462Salfred goto error; 55474462Salfred } 55574462Salfred tcptrans = strdup(nconf->nc_netid); 55674462Salfred pml->pml_map.pm_prot = IPPROTO_TCP; 55774462Salfred 55874462Salfred /* Let's snarf the universal address */ 55974462Salfred /* "h1.h2.h3.h4.p1.p2" */ 56074462Salfred tcp_uaddr = taddr2uaddr(nconf, &taddr.addr); 56174462Salfred } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 56274462Salfred if (udptrans[0]) { 56374462Salfred syslog(LOG_ERR, 56474462Salfred "cannot have more than one UDP transport"); 56574462Salfred goto error; 56674462Salfred } 56774462Salfred udptrans = strdup(nconf->nc_netid); 56874462Salfred pml->pml_map.pm_prot = IPPROTO_UDP; 56974462Salfred 57074462Salfred /* Let's snarf the universal address */ 57174462Salfred /* "h1.h2.h3.h4.p1.p2" */ 57274462Salfred udp_uaddr = taddr2uaddr(nconf, &taddr.addr); 573107952Smbr } else if (strcmp(nconf->nc_netid, "local") == 0) 57474462Salfred pml->pml_map.pm_prot = IPPROTO_ST; 575107952Smbr else if (strcmp(nconf->nc_netid, "unix") == 0) 576107952Smbr pml->pml_map.pm_prot = IPPROTO_ST; 57774462Salfred pml->pml_next = list_pml; 57874462Salfred list_pml = pml; 57974462Salfred 58074462Salfred /* Add version 3 information */ 58196788Sjmallett pml = malloc(sizeof (struct pmaplist)); 58296788Sjmallett if (pml == NULL) { 58374462Salfred syslog(LOG_ERR, "no memory!"); 58474462Salfred exit(1); 58574462Salfred } 58674462Salfred pml->pml_map = list_pml->pml_map; 58774462Salfred pml->pml_map.pm_vers = RPCBVERS; 58874462Salfred pml->pml_next = list_pml; 58974462Salfred list_pml = pml; 59074462Salfred 59174462Salfred /* Add version 4 information */ 59296788Sjmallett pml = malloc (sizeof (struct pmaplist)); 59396788Sjmallett if (pml == NULL) { 59474462Salfred syslog(LOG_ERR, "no memory!"); 59574462Salfred exit(1); 59674462Salfred } 59774462Salfred pml->pml_map = list_pml->pml_map; 59874462Salfred pml->pml_map.pm_vers = RPCBVERS4; 59974462Salfred pml->pml_next = list_pml; 60074462Salfred list_pml = pml; 60174462Salfred 60274462Salfred /* Also add version 2 stuff to rpcbind list */ 60374462Salfred rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr); 60474462Salfred } 60574462Salfred#endif 60674462Salfred 60774462Salfred /* version 3 registration */ 60874462Salfred if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) { 60974462Salfred syslog(LOG_ERR, "could not register %s version 3", 61074462Salfred nconf->nc_netid); 61174462Salfred goto error; 61274462Salfred } 61374462Salfred rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr); 61474462Salfred 61574462Salfred /* version 4 registration */ 61674462Salfred if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) { 61774462Salfred syslog(LOG_ERR, "could not register %s version 4", 61874462Salfred nconf->nc_netid); 61974462Salfred goto error; 62074462Salfred } 62174462Salfred rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr); 62274462Salfred 62374462Salfred /* decide if bound checking works for this transport */ 62474462Salfred status = add_bndlist(nconf, &taddr.addr); 62574462Salfred#ifdef BIND_DEBUG 62674462Salfred if (debugging) { 62774462Salfred if (status < 0) { 62874462Salfred fprintf(stderr, "Error in finding bind status for %s\n", 62974462Salfred nconf->nc_netid); 63074462Salfred } else if (status == 0) { 63174462Salfred fprintf(stderr, "check binding for %s\n", 63274462Salfred nconf->nc_netid); 63374462Salfred } else if (status > 0) { 63474462Salfred fprintf(stderr, "No check binding for %s\n", 63574462Salfred nconf->nc_netid); 63674462Salfred } 63774462Salfred } 63874462Salfred#endif 63974462Salfred /* 64074462Salfred * rmtcall only supported on CLTS transports for now. 64174462Salfred */ 64274462Salfred if (nconf->nc_semantics == NC_TPI_CLTS) { 64374462Salfred status = create_rmtcall_fd(nconf); 64474462Salfred 64574462Salfred#ifdef BIND_DEBUG 64674462Salfred if (debugging) { 64774462Salfred if (status < 0) { 64874462Salfred fprintf(stderr, 64974462Salfred "Could not create rmtcall fd for %s\n", 65074462Salfred nconf->nc_netid); 65174462Salfred } else { 65274462Salfred fprintf(stderr, "rmtcall fd for %s is %d\n", 65374462Salfred nconf->nc_netid, status); 65474462Salfred } 65574462Salfred } 65674462Salfred#endif 65774462Salfred } 65874462Salfred return (0); 65974462Salfrederror: 66074462Salfred close(fd); 66174462Salfred return (1); 66274462Salfred} 66374462Salfred 664203710Simp/* 665203710Simp * Create the list of addresses that we're bound to. Normally, this 666203710Simp * list is empty because we're listening on the wildcard address 667203710Simp * (nhost == 0). If -h is specified on the command line, then 668203710Simp * bound_sa will have a list of the addresses that the program binds 669203710Simp * to specifically. This function takes that list and converts them to 670203710Simp * struct sockaddr * and stores them in bound_sa. 671203710Simp */ 67274462Salfredstatic void 673203710Simpupdate_bound_sa(void) 674203710Simp{ 675203710Simp struct addrinfo hints, *res = NULL; 676203710Simp int i; 677203710Simp 678203710Simp if (nhosts == 0) 679203710Simp return; 680203710Simp bound_sa = malloc(sizeof(*bound_sa) * nhosts); 681203710Simp memset(&hints, 0, sizeof(hints)); 682203710Simp hints.ai_family = PF_UNSPEC; 683203710Simp for (i = 0; i < nhosts; i++) { 684203710Simp if (getaddrinfo(hosts[i], NULL, &hints, &res) != 0) 685203710Simp continue; 686203710Simp bound_sa[i] = malloc(res->ai_addrlen); 687203710Simp memcpy(bound_sa[i], res->ai_addr, res->ai_addrlen); 688203710Simp } 689203710Simp} 690203710Simp 691203710Simp/* 692203710Simp * Match the sa against the list of addresses we've bound to. If 693203710Simp * we've not specifically bound to anything, we match everything. 694203710Simp * Otherwise, if the IPv4 or IPv6 address matches one of the addresses 695203710Simp * in bound_sa, we return true. If not, we return false. 696203710Simp */ 697203710Simpint 698203710Simplisten_addr(const struct sockaddr *sa) 699203710Simp{ 700203710Simp int i; 701203710Simp 702203710Simp /* 703203710Simp * If nhosts == 0, then there were no -h options on the 704203710Simp * command line, so all addresses are addresses we're 705203710Simp * listening to. 706203710Simp */ 707203710Simp if (nhosts == 0) 708203710Simp return 1; 709203710Simp for (i = 0; i < nhosts; i++) { 710203710Simp if (bound_sa[i] == NULL || 711203710Simp sa->sa_family != bound_sa[i]->sa_family) 712203710Simp continue; 713203710Simp switch (sa->sa_family) { 714203710Simp case AF_INET: 715203710Simp if (memcmp(&SA2SINADDR(sa), &SA2SINADDR(bound_sa[i]), 716203710Simp sizeof(struct in_addr)) == 0) 717203710Simp return (1); 718203710Simp break; 719203710Simp#ifdef INET6 720203710Simp case AF_INET6: 721203710Simp if (memcmp(&SA2SIN6ADDR(sa), &SA2SIN6ADDR(bound_sa[i]), 722203710Simp sizeof(struct in6_addr)) == 0) 723203710Simp return (1); 724203710Simp break; 725203710Simp#endif 726203710Simp default: 727203710Simp break; 728203710Simp } 729203710Simp } 730203710Simp return (0); 731203710Simp} 732203710Simp 733203710Simpstatic void 73474462Salfredrbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf, 73574462Salfred struct netbuf *addr) 73674462Salfred{ 73774462Salfred rpcblist_ptr rbl; 73874462Salfred 73996788Sjmallett rbl = malloc(sizeof (rpcblist)); 74096788Sjmallett if (rbl == NULL) { 74174462Salfred syslog(LOG_ERR, "no memory!"); 74274462Salfred exit(1); 74374462Salfred } 74474462Salfred 74574462Salfred rbl->rpcb_map.r_prog = prog; 74674462Salfred rbl->rpcb_map.r_vers = vers; 74774462Salfred rbl->rpcb_map.r_netid = strdup(nconf->nc_netid); 74874462Salfred rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr); 74974462Salfred rbl->rpcb_map.r_owner = strdup(superuser); 75074462Salfred rbl->rpcb_next = list_rbl; /* Attach to global list */ 75174462Salfred list_rbl = rbl; 75274462Salfred} 75374462Salfred 75474462Salfred/* 75574462Salfred * Catch the signal and die 75674462Salfred */ 75774462Salfredstatic void 758104592Salfredterminate(int dummy __unused) 75974462Salfred{ 760107725Smbr close(rpcbindlockfd); 76174462Salfred#ifdef WARMSTART 76274462Salfred syslog(LOG_ERR, 76374462Salfred "rpcbind terminating on signal. Restart with \"rpcbind -w\""); 76474462Salfred write_warmstart(); /* Dump yourself */ 76574462Salfred#endif 76674462Salfred exit(2); 76774462Salfred} 76874462Salfred 76974462Salfredvoid 770224001Sdelphijrpcbind_abort(void) 77174462Salfred{ 77274462Salfred#ifdef WARMSTART 77374462Salfred write_warmstart(); /* Dump yourself */ 77474462Salfred#endif 77574462Salfred abort(); 77674462Salfred} 77774462Salfred 77874462Salfred/* get command line options */ 77974462Salfredstatic void 78074462Salfredparseargs(int argc, char *argv[]) 78174462Salfred{ 78274462Salfred int c; 78374462Salfred 784137327Sdd#ifdef WARMSTART 785137327Sdd#define WSOP "w" 786137327Sdd#else 787137327Sdd#define WSOP "" 788137327Sdd#endif 789168969Smatteo while ((c = getopt(argc, argv, "6adh:iLls" WSOP)) != -1) { 79074462Salfred switch (c) { 791168969Smatteo case '6': 792168969Smatteo ipv6_only = 1; 793168969Smatteo break; 79474462Salfred case 'a': 79574462Salfred doabort = 1; /* when debugging, do an abort on */ 79674462Salfred break; /* errors; for rpcbind developers */ 79774462Salfred /* only! */ 79874462Salfred case 'd': 79974462Salfred debugging = 1; 80074462Salfred break; 80199774Salfred case 'h': 80299774Salfred ++nhosts; 80399774Salfred hosts = realloc(hosts, nhosts * sizeof(char *)); 80499774Salfred if (hosts == NULL) 80599774Salfred errx(1, "Out of memory"); 80699774Salfred hosts[nhosts - 1] = strdup(optarg); 80799774Salfred if (hosts[nhosts - 1] == NULL) 80899774Salfred errx(1, "Out of memory"); 80999774Salfred break; 81074462Salfred case 'i': 81174462Salfred insecure = 1; 81274462Salfred break; 81374462Salfred case 'L': 81474462Salfred oldstyle_local = 1; 81574462Salfred break; 81674462Salfred case 'l': 81774462Salfred verboselog = 1; 81874462Salfred break; 81974462Salfred case 's': 82074462Salfred runasdaemon = 1; 82174462Salfred break; 82274462Salfred#ifdef WARMSTART 82374462Salfred case 'w': 82474462Salfred warmstart = 1; 82574462Salfred break; 82674462Salfred#endif 82774462Salfred default: /* error */ 828137327Sdd fprintf(stderr, 829168969Smatteo "usage: rpcbind [-6adiLls%s] [-h bindip]\n", 830137327Sdd WSOP); 83174462Salfred exit (1); 83274462Salfred } 83374462Salfred } 83474462Salfred if (doabort && !debugging) { 83574462Salfred fprintf(stderr, 83674462Salfred "-a (abort) specified without -d (debugging) -- ignored.\n"); 83774462Salfred doabort = 0; 83874462Salfred } 839137327Sdd#undef WSOP 84074462Salfred} 84174462Salfred 84274462Salfredvoid 843104592Salfredreap(int dummy __unused) 84474462Salfred{ 84574462Salfred int save_errno = errno; 84674462Salfred 84774462Salfred while (wait3(NULL, WNOHANG, NULL) > 0) 84874462Salfred ; 84974462Salfred errno = save_errno; 85074462Salfred} 85174462Salfred 85274462Salfredvoid 853104592Salfredtoggle_verboselog(int dummy __unused) 85474462Salfred{ 85574462Salfred verboselog = !verboselog; 85674462Salfred} 857