Пример #1
0
//****************************************//
//***           Main Function          ***//
//****************************************//
int main(int argn, char *argc[])
{
	//Server parameter is : argc[1] : Server Program Number
	//                                          others arguments depend on server program
	int progNum = atoi(argc[1]);
	SVCXPRT *transp = NULL;
	struct netconfig *nconf;

	//Initialization
	svc_unreg(progNum, VERSNUM);

	if ((nconf = getnetconfigent("udp")) == NULL) {
		fprintf(stderr, "Cannot get netconfig entry for UDP\n");
		exit(1);
	}

	transp = svc_tp_create(exm_proc, progNum, VERSNUM, nconf);

	if (transp == NULL) {
		fprintf(stderr, "Cannot create service.\n");
		exit(1);
	}

	if (!svc_reg(transp, progNum, VERSNUM, exm_proc, nconf)) {
		fprintf(stderr, "svc_reg failed!!\n");
		exit(1);
	}

	svc_run();

	fprintf(stderr, "svc_run() returned.  ERROR has occurred.\n");
	svc_unreg(progNum, VERSNUM);

	return 1;
}
Пример #2
0
/*
 * Adds a socket to the list for servicing by nfscbds.
 */
int
nfscbd_addsock(struct file *fp)
{
	int siz;
	struct socket *so;
	int error;
	SVCXPRT *xprt;

	so = fp->f_data;

	siz = sb_max_adj;
	error = soreserve(so, siz, siz);
	if (error)
		return (error);

	/*
	 * Steal the socket from userland so that it doesn't close
	 * unexpectedly.
	 */
	if (so->so_type == SOCK_DGRAM)
		xprt = svc_dg_create(nfscbd_pool, so, 0, 0);
	else
		xprt = svc_vc_create(nfscbd_pool, so, 0, 0);
	if (xprt) {
		fp->f_ops = &badfileops;
		fp->f_data = NULL;
		svc_reg(xprt, NFS_CALLBCKPROG, NFSV4_CBVERS, nfscb_program,
		    NULL);
		SVC_RELEASE(xprt);
	}

	return (0);
}
Пример #3
0
/*
 * The simple case is allowing the TI-RPC library to create a
 * transport itself, given just the bind address and transport
 * semantics.
 *
 * Our local xprt cache is ignored in this path, since the
 * caller is not interested in sharing listeners or ports, and
 * the library automatically avoids ports already in use.
 *
 * Returns the count of started listeners (one or zero).
 */
static unsigned int
svc_create_nconf_rand_port(const char *name, const rpcprog_t program,
                           const rpcvers_t version,
                           void (*dispatch)(struct svc_req *, SVCXPRT *),
                           struct netconfig *nconf)
{
    struct t_bind bindaddr;
    struct addrinfo *ai;
    SVCXPRT	*xprt;

    ai = svc_create_bindaddr(nconf, 0);
    if (ai == NULL)
        return 0;

    bindaddr.addr.buf = ai->ai_addr;
    bindaddr.qlen = SOMAXCONN;

    xprt = svc_tli_create(RPC_ANYFD, nconf, &bindaddr, 0, 0);
    freeaddrinfo(ai);
    if (xprt == NULL) {
        xlog(D_GENERAL, "Failed to create listener xprt "
             "(%s, %u, %s)", name, version, nconf->nc_netid);
        return 0;
    }

    if (!svc_reg(xprt, program, version, dispatch, nconf)) {
        /* svc_reg(3) destroys @xprt in this case */
        xlog(D_GENERAL, "Failed to register (%s, %u, %s)",
             name, version, nconf->nc_netid);
        return 0;
    }

    return 1;
}
Пример #4
0
void *my_thread_process(void *arg)
{
	SVCXPRT *transp = NULL;
	struct netconfig *nconf = NULL;
	struct netbuf svcaddr;
	int i;

	if (run_mode == 1) {
		fprintf(stderr, "Thread %d\n", atoi(arg));
	}

	nconf = getnetconfigent("udp");
	if (nconf == (struct netconfig *)NULL) {
		//syslog(LOG_ERR, "getnetconfigent for udp failed");
		printf("err nconf\n");
		pthread_exit(1);
	}

	transp = svc_tli_create(RPC_ANYFD, nconf, (struct t_bind *)NULL, 0, 0);

	for (i = 0; i < callNb; i++) {
		svc_unreg(progNum + atoi(arg), VERSNUM);
		svc_reg(transp, progNum + atoi(arg), VERSNUM, exm_proc, nconf);

		svc_unreg(progNum + atoi(arg), VERSNUM);

		//If we are here, test was sucessfull
		thread_array_result[atoi(arg)] += 1;
	}

	pthread_exit(0);
}
Пример #5
0
int
main(int argc, char *argv[])
{
	SVCXPRT *transp;
	socklen_t salen;
	int ok;
	struct sockaddr_storage sa;

	if (argc == 2 && !strcmp(argv[1], "-n"))
		nodaemon = 1;
	if (argc != 1 && !nodaemon)
		usage();

	if (geteuid() == 0) {
		struct passwd *pep = getpwnam("nobody");
		if (pep)
			setuid(pep->pw_uid);
		else
			setuid(getuid());
	}

        /*
         * See if inetd started us
         */
	salen = sizeof(sa);
        if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) {
                from_inetd = 0;
        }

        if (!from_inetd) {
                if (!nodaemon)
                        possess();

		(void)rpcb_unset(WALLPROG, WALLVERS, NULL);
        }

	(void)signal(SIGCHLD, killkids);

	openlog("rpc.rwalld", LOG_CONS|LOG_PID, LOG_DAEMON);

	/* create and register the service */
	if (from_inetd) {
		transp = svc_tli_create(0, NULL, NULL, 0, 0);
		if (transp == NULL) {
			syslog(LOG_ERR, "couldn't create udp service.");
			exit(1);
		}
		ok = svc_reg(transp, WALLPROG, WALLVERS,
			     wallprog_1, NULL);
	} else
		ok = svc_create(wallprog_1,
				WALLPROG, WALLVERS, "udp");
	if (!ok) {
		syslog(LOG_ERR, "unable to register (WALLPROG, WALLVERS, %s)", (!from_inetd)?"udp":"(inetd)");
		exit(1);
	}
	svc_run();
	syslog(LOG_ERR, "svc_run returned");
	exit(1);
}
Пример #6
0
/*
 * Register an RPC server:
 * return 1 on success, 0 otherwise.
 */
int
amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum,
		 void (*dispatch)(struct svc_req *rqstp, SVCXPRT *xprt),
		 u_long protocol, struct netconfig *ncp)
{
  /* on TLI: svc_reg returns 1 on success, 0 otherwise */
  return svc_reg(xprt, prognum, versnum, dispatch, ncp);
}
Пример #7
0
/*
 * Adds a socket to the list for servicing by nfsds.
 */
int
nfsrvd_addsock(struct file *fp)
{
	int siz;
	struct socket *so;
	int error = 0;
	SVCXPRT *xprt;
	static u_int64_t sockref = 0;

	so = fp->f_data;

	siz = sb_max_adj;
	error = soreserve(so, siz, siz);
	if (error)
		goto out;

	/*
	 * Steal the socket from userland so that it doesn't close
	 * unexpectedly.
	 */
	if (so->so_type == SOCK_DGRAM)
		xprt = svc_dg_create(nfsrvd_pool, so, 0, 0);
	else
		xprt = svc_vc_create(nfsrvd_pool, so, 0, 0);
	if (xprt) {
		fp->f_ops = &badfileops;
		fp->f_data = NULL;
		xprt->xp_sockref = ++sockref;
		if (nfs_minvers == NFS_VER2)
			svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program,
			    NULL);
		if (nfs_minvers <= NFS_VER3 && nfs_maxvers >= NFS_VER3)
			svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program,
			    NULL);
		if (nfs_maxvers >= NFS_VER4)
			svc_reg(xprt, NFS_PROG, NFS_VER4, nfssvc_program,
			    NULL);
		if (so->so_type == SOCK_STREAM)
			svc_loss_reg(xprt, nfssvc_loss);
		SVC_RELEASE(xprt);
	}

out:
	NFSEXITCODE(error);
	return (error);
}
Пример #8
0
int main(int argn, char *argc[])
{
	//Program parameters : argc[1] : HostName or Host IP
	//					   argc[2] : Server Program Number
	//					   argc[3] : Number of testes function calls
	//					   other arguments depend on test case
	
	//run_mode can switch into stand alone program or program launch by shell script
	//1 : stand alone, debug mode, more screen information
	//0 : launch by shell script as test case, only one printf -> result status
	int run_mode = 0;
	int test_status = 1; //Default test result set to FAILED
	int progNum = atoi(argc[2]);
	SVCXPRT *transp = NULL;
	struct netconfig *nconf = NULL;
	struct netbuf svcaddr;
    int nbCall = atoi(argc[3]);
	int nbOk = 0;
	int i;
	
	//Initialization
    if (run_mode)
    {
    	printf("Before creation\n");
		printf("nconf : %d\n", nconf);
	}

	nconf = getnetconfigent("udp");
	if (nconf == (struct netconfig *) NULL)
	{
		//syslog(LOG_ERR, "getnetconfigent for udp failed");
		printf("err nconf\n");
		exit(1);
	}

	transp = svc_tli_create(RPC_ANYFD, nconf, 
                            (struct t_bind *)NULL,
                            0, 0);
    
    svc_unreg(progNum, VERSNUM);
    
    for (i = 0; i < nbCall; i++)
	{
		svc_reg(transp, progNum, VERSNUM,
            exm_proc, nconf);
    
    	svc_unreg(progNum, VERSNUM);
    }
    
    //If we are here, test has passed
    test_status = 0;

	//This last printf gives the result status to the tests suite
	//normally should be 0: test has passed or 1: test has failed
	printf("%d\n", test_status);	
	
	return test_status;
}
Пример #9
0
int
main(int argc, char *argv[])
{
	SVCXPRT *transp;
	int ok;
	struct sockaddr_storage from;
	socklen_t fromlen;

	/*
	 * See if inetd started us
	 */
	fromlen = sizeof(from);
	if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) {
		from_inetd = 0;
	}

	if (!from_inetd) {
		daemon(0, 0);

		(void) rpcb_unset(SPRAYPROG, SPRAYVERS, NULL);

		(void) signal(SIGINT, cleanup);
		(void) signal(SIGTERM, cleanup);
		(void) signal(SIGHUP, cleanup);
	} else {
		(void) signal(SIGALRM, die);
		alarm(TIMEOUT);
	}

	openlog("rpc.sprayd", LOG_CONS|LOG_PID, LOG_DAEMON);

	if (from_inetd) {
		transp = svc_tli_create(0, NULL, NULL, 0, 0);
		if (transp == NULL) {
			syslog(LOG_ERR, "cannot create udp service.");
			exit(1);
		}
		ok = svc_reg(transp, SPRAYPROG, SPRAYVERS,
			     spray_service, NULL);
	} else
		ok = svc_create(spray_service,
				SPRAYPROG, SPRAYVERS, "udp");
	if (!ok) {
		syslog(LOG_ERR,
		    "unable to register (SPRAYPROG, SPRAYVERS, %s)",
		    (!from_inetd)?"udp":"(inetd)");
		return 1;
	}

	svc_run();
	syslog(LOG_ERR, "svc_run returned");
	return 1;
}
Пример #10
0
/*
 * If a port is specified on the command line, that port value will be
 * the same for all listeners created here.  Create each listener
 * socket in advance and set SO_REUSEADDR, rather than allowing the
 * RPC library to create the listeners for us on a randomly chosen
 * port via svc_tli_create(RPC_ANYFD).
 *
 * Some callers want to listen for more than one RPC version using the
 * same port number.  For example, mountd could want to listen for MNT
 * version 1, 2, and 3 requests.  This means mountd must use the same
 * set of listener sockets for multiple RPC versions, since, on one
 * system, you can't have two listener sockets with the exact same
 * bind address (and port) and transport protocol.
 *
 * To accomplish this, this function caches xprts as they are created.
 * This cache is checked to see if a previously created xprt can be
 * used, before creating a new xprt for this [program, version].  If
 * there is a cached xprt with the same bindaddr and transport
 * semantics, we simply register the new version with that xprt,
 * rather than creating a fresh xprt for it.
 *
 * The xprt cache implemented here is local to a process.  Two
 * separate RPC daemons can not share a set of listeners.
 *
 * Returns the count of started listeners (one or zero).
 */
static unsigned int
svc_create_nconf_fixed_port(const char *name, const rpcprog_t program,
                            const rpcvers_t version,
                            void (*dispatch)(struct svc_req *, SVCXPRT *),
                            const uint16_t port, struct netconfig *nconf)
{
    struct addrinfo *ai;
    SVCXPRT	*xprt;

    ai = svc_create_bindaddr(nconf, port);
    if (ai == NULL)
        return 0;

    xprt = svc_create_find_xprt(ai->ai_addr, nconf);
    if (xprt == NULL) {
        int fd;

        fd = svc_create_sock(ai->ai_addr, ai->ai_addrlen, nconf);
        if (fd == -1)
            goto out_free;

        xprt = svc_tli_create(fd, nconf, NULL, 0, 0);
        if (xprt == NULL) {
            xlog(D_GENERAL, "Failed to create listener xprt "
                 "(%s, %u, %s)", name, version, nconf->nc_netid);
            (void)close(fd);
            goto out_free;
        }
    }

    if (!svc_reg(xprt, program, version, dispatch, nconf)) {
        /* svc_reg(3) destroys @xprt in this case */
        xlog(D_GENERAL, "Failed to register (%s, %u, %s)",
             name, version, nconf->nc_netid);
        goto out_free;
    }

    svc_create_cache_xprt(xprt);

    freeaddrinfo(ai);
    return 1;

out_free:
    freeaddrinfo(ai);
    return 0;
}
Пример #11
0
/*
 * Create the nfs service for amd
 * return 0 (TRUE) if OK, 1 (FALSE) if failed.
 */
int
create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version)
{
  char *nettype = "ticlts";

  nfsncp = getnetconfigent(nettype);
  if (nfsncp == NULL) {
    plog(XLOG_ERROR, "cannot getnetconfigent for %s", nettype);
    /* failed with ticlts, try plain udp (hpux11) */
    nettype = "udp";
    nfsncp = getnetconfigent(nettype);
    if (nfsncp == NULL) {
      plog(XLOG_ERROR, "cannot getnetconfigent for %s", nettype);
      return 1;
    }
  }
  *nfs_xprtp = svc_tli_create(RPC_ANYFD, nfsncp, NULL, 0, 0);
  if (*nfs_xprtp == NULL) {
    plog(XLOG_ERROR, "cannot create nfs tli service for amd");
    return 1;
  }

  /*
   * Get the service file descriptor and check its number to see if
   * the t_open failed.  If it succeeded, then go on to binding to a
   * reserved nfs port.
   */
  *soNFSp = (*nfs_xprtp)->xp_fd;
  if (*soNFSp < 0 || bind_nfs_port(*soNFSp, nfs_portp) < 0) {
    plog(XLOG_ERROR, "Can't create privileged nfs port (TLI)");
    svc_destroy(*nfs_xprtp);
    return 1;
  }
  if (svc_reg(*nfs_xprtp, NFS_PROGRAM, nfs_version, dispatch_fxn, NULL) != 1) {
    plog(XLOG_ERROR, "could not register amd NFS service");
    svc_destroy(*nfs_xprtp);
    return 1;
  }

  return 0;			/* all is well */
}
Пример #12
0
int
main(int argc, char *argv[])
{
	pid_t pid;
	int i;
	int connmaxrec = RPC_MAXDATASIZE;

	/*
	 * Set non-blocking mode and maximum record size for
	 * connection oriented RPC transports.
	 */
	if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) {
		msgout("unable to set maximum RPC record size");
	}

	/*
	 * If stdin looks like a TLI endpoint, we assume
	 * that we were started by a port monitor. If
	 * t_getstate fails with TBADF, this is not a
	 * TLI endpoint.
	 */
	if (t_getstate(0) != -1 || t_errno != TBADF) {
		char *netid;
		struct netconfig *nconf = NULL;
		SVCXPRT *transp;
		int pmclose;
		extern char *getenv();

		_rpcpmstart = 1;
		openlog("rusers", LOG_PID, LOG_DAEMON);
		if ((netid = getenv("NLSPROVIDER")) == NULL) {
#ifdef DEBUG
			msgout("cannot get transport name");
#endif
		} else if ((nconf = getnetconfigent(netid)) == NULL) {
#ifdef DEBUG
			msgout("cannot get transport info");
#endif
		}
		if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
			msgout("cannot create server handle");
			exit(1);
		}
		if (nconf)
			freenetconfigent(nconf);
		if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_3, rusers_service,
				0)) {
	msgout("unable to register (RUSERSPROG, RUSERSVERS_3).");
			exit(1);
		}
		if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_IDLE,
				rusers_service, 0)) {
	msgout("unable to register (RUSERSPROG, RUSERSVERS_IDLE).");
			exit(1);
		}
		(void) signal(SIGALRM, closedown);
		(void) alarm(_RPCSVC_CLOSEDOWN);
		svc_run();
		msgout("svc_run returned");
		exit(1);
		/* NOTREACHED */
	}
#ifndef RPC_SVC_FG
	pid = fork();
	if (pid < 0) {
		perror("rpc.rusersd: cannot fork");
		exit(1);
	}
	if (pid)
		exit(0);
	for (i = 0; i < 20; i++)
		(void) close(i);
	setsid();
	openlog("rusers", LOG_PID, LOG_DAEMON);
#endif
	if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_3, "netpath")) {
	    msgout("unable to create (RUSERSPROG, RUSERSVERS_3) for netpath");
		exit(1);
	}
	if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_IDLE,
			"netpath")) {
	    msgout(
		"unable to create (RUSERSPROG, RUSERSVERS_IDLE) for netpath");
		exit(1);
	}

	svc_run();
	msgout("svc_run returned");
	return (1);
}
Пример #13
0
/*
 * Adds the entry into the rpcbind database.
 * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
 * Returns 0 if succeeds, else fails
 */
static int
init_transport(struct netconfig *nconf)
{
	int fd;
	struct t_bind taddr;
	struct addrinfo hints, *res = NULL;
	struct __rpc_sockinfo si;
	SVCXPRT	*my_xprt;
	int status;	/* bound checking ? */
	int aicode;
	int addrlen;
	struct sockaddr *sa;
	struct sockaddr_un sun;
	const int one = 1;

	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
		(nconf->nc_semantics != NC_TPI_COTS) &&
		(nconf->nc_semantics != NC_TPI_COTS_ORD))
		return 1;	/* not my type */
#ifdef RPCBIND_DEBUG
	if (debugging) {
		int i;
		char **s;

		(void)fprintf(stderr, "%s: %ld lookup routines :\n",
		    nconf->nc_netid, nconf->nc_nlookups);
		for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
		     i++, s++)
			(void)fprintf(stderr, "[%d] - %s\n", i, *s);
	}
#endif

	/*
	 * XXX - using RPC library internal functions.
	 */
	if ((fd = __rpc_nconf2fd(nconf)) < 0) {
		if (errno == EAFNOSUPPORT)
			return 1;
		warn("Cannot create socket for `%s'", nconf->nc_netid);
		return 1;
	}

	if (!__rpc_nconf2sockinfo(nconf, &si)) {
		warnx("Cannot get information for `%s'", nconf->nc_netid);
		return 1;
	}

	if (si.si_af == AF_INET6) {
		/*
		 * We're doing host-based access checks here, so don't allow
		 * v4-in-v6 to confuse things.
		 */
		if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one,
		    sizeof one) < 0) {
			warn("Can't make socket ipv6 only");
			return 1;
		}
	}


	if (!strcmp(nconf->nc_netid, "local")) {
		(void)memset(&sun, 0, sizeof sun);
		sun.sun_family = AF_LOCAL;
#ifdef RPCBIND_RUMP
		(void)rump_sys_unlink(_PATH_RPCBINDSOCK);
#else
		(void)unlink(_PATH_RPCBINDSOCK);
#endif
		(void)strlcpy(sun.sun_path, _PATH_RPCBINDSOCK,
		    sizeof(sun.sun_path));
		sun.sun_len = SUN_LEN(&sun);
		addrlen = sizeof(struct sockaddr_un);
		sa = (struct sockaddr *)&sun;
	} else {
		/* Get rpcbind's address on this transport */

		(void)memset(&hints, 0, sizeof hints);
		hints.ai_flags = AI_PASSIVE;
		hints.ai_family = si.si_af;
		hints.ai_socktype = si.si_socktype;
		hints.ai_protocol = si.si_proto;
		if ((aicode = getaddrinfo(NULL, servname, &hints, &res)) != 0) {
			warnx("Cannot get local address for `%s' (%s)",
			    nconf->nc_netid, gai_strerror(aicode));
			return 1;
		}
		addrlen = res->ai_addrlen;
		sa = (struct sockaddr *)res->ai_addr;
	}

	if (bind(fd, sa, addrlen) < 0) {
		warn("Cannot bind `%s'", nconf->nc_netid);
		if (res != NULL)
			freeaddrinfo(res);
		return 1;
	}
#ifndef RPCBIND_RUMP
	if (sa->sa_family == AF_LOCAL)
		if (chmod(sun.sun_path, S_IRWXU|S_IRWXG|S_IRWXO) == -1)
			warn("Cannot chmod `%s'", sun.sun_path);
#endif

	/* Copy the address */
	taddr.addr.len = taddr.addr.maxlen = addrlen;
	taddr.addr.buf = malloc(addrlen);
	if (taddr.addr.buf == NULL) {
		warn("Cannot allocate memory for `%s' address",
		    nconf->nc_netid);
		if (res != NULL)
			freeaddrinfo(res);
		return 1;
	}
	(void)memcpy(taddr.addr.buf, sa, addrlen);
#ifdef RPCBIND_DEBUG
	if (debugging) {
		/* for debugging print out our universal address */
		char *uaddr;
		struct netbuf nb;

		nb.buf = sa;
		nb.len = nb.maxlen = sa->sa_len;
		uaddr = taddr2uaddr(nconf, &nb);
		(void)fprintf(stderr, "rpcbind: my address is %s fd=%d\n",
		    uaddr, fd);
		(void)free(uaddr);
	}
#endif

	if (res != NULL)
		freeaddrinfo(res);

	if (nconf->nc_semantics != NC_TPI_CLTS)
		listen(fd, SOMAXCONN);
		
	my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE,
	    RPC_MAXDATASIZE);
	if (my_xprt == NULL) {
		warnx("Could not create service for `%s'", nconf->nc_netid);
		goto error;
	}

#ifdef PORTMAP
	/*
	 * Register both the versions for tcp/ip, udp/ip and local.
	 */
	if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
		(strcmp(nconf->nc_proto, NC_TCP) == 0 ||
		strcmp(nconf->nc_proto, NC_UDP) == 0)) ||
		strcmp(nconf->nc_netid, "local") == 0) {
		struct pmaplist *pml;

		if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
			pmap_service, 0)) {
			warn("Could not register on `%s'", nconf->nc_netid);
			goto error;
		}
		pml = malloc(sizeof (struct pmaplist));
		if (pml == NULL) {
			warn("Cannot allocate memory");
			goto error;
		}
		pml->pml_map.pm_prog = PMAPPROG;
		pml->pml_map.pm_vers = PMAPVERS;
		pml->pml_map.pm_port = PMAPPORT;
		if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
			if (tcptrans[0]) {
				warnx(
				    "Cannot have more than one TCP transport");
				free(pml);
				goto error;
			}
			tcptrans = strdup(nconf->nc_netid);
			if (tcptrans == NULL) {
				free(pml);
				warn("Cannot allocate memory");
				goto error;
			}
			pml->pml_map.pm_prot = IPPROTO_TCP;

			/* Let's snarf the universal address */
			/* "h1.h2.h3.h4.p1.p2" */
			tcp_uaddr = taddr2uaddr(nconf, &taddr.addr);
		} else if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
			if (udptrans[0]) {
				free(pml);
				warnx(
				"Cannot have more than one UDP transport");
				goto error;
			}
			udptrans = strdup(nconf->nc_netid);
			if (udptrans == NULL) {
				free(pml);
				warn("Cannot allocate memory");
				goto error;
			}
			pml->pml_map.pm_prot = IPPROTO_UDP;

			/* Let's snarf the universal address */
			/* "h1.h2.h3.h4.p1.p2" */
			udp_uaddr = taddr2uaddr(nconf, &taddr.addr);
		}
		pml->pml_next = list_pml;
		list_pml = pml;

		/* Add version 3 information */
		pml = malloc(sizeof (struct pmaplist));
		if (pml == NULL) {
			warn("Cannot allocate memory");
			goto error;
		}
		pml->pml_map = list_pml->pml_map;
		pml->pml_map.pm_vers = RPCBVERS;
		pml->pml_next = list_pml;
		list_pml = pml;

		/* Add version 4 information */
		pml = malloc(sizeof (struct pmaplist));
		if (pml == NULL) {
			warn("Cannot allocate memory");
			goto error;
		}
		pml->pml_map = list_pml->pml_map;
		pml->pml_map.pm_vers = RPCBVERS4;
		pml->pml_next = list_pml;
		list_pml = pml;

		/* Also add version 2 stuff to rpcbind list */
		rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
	}
#endif

	/* version 3 registration */
	if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
		warn("Could not register %s version 3", nconf->nc_netid);
		goto error;
	}
	rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);

	/* version 4 registration */
	if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
		warn("Could not register %s version 4", nconf->nc_netid);
		goto error;
	}
	rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);

	/* decide if bound checking works for this transport */
	status = add_bndlist(nconf, &taddr.addr);
#ifdef RPCBIND_DEBUG
	if (debugging) {
		if (status < 0) {
			fprintf(stderr, "Error in finding bind status for %s\n",
				nconf->nc_netid);
		} else if (status == 0) {
			fprintf(stderr, "check binding for %s\n",
				nconf->nc_netid);
		} else if (status > 0) {
			fprintf(stderr, "No check binding for %s\n",
				nconf->nc_netid);
		}
	}
#else
	__USE(status);
#endif
	/*
	 * rmtcall only supported on CLTS transports for now.
	 */
	if (nconf->nc_semantics == NC_TPI_CLTS) {
		status = create_rmtcall_fd(nconf);

#ifdef RPCBIND_DEBUG
		if (debugging) {
			if (status < 0) {
				fprintf(stderr,
				    "Could not create rmtcall fd for %s\n",
					nconf->nc_netid);
			} else {
				fprintf(stderr, "rmtcall fd for %s is %d\n",
					nconf->nc_netid, status);
			}
		}
#endif
	}
	return (0);
error:
#ifdef RPCBIND_RUMP
	(void)rump_sys_close(fd);
#else
	(void)close(fd);
#endif
	return (1);
}
Пример #14
0
/*
 * Adds the entry into the rpcbind database.
 * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
 * Returns 0 if succeeds, else fails
 */
static int
init_transport(struct netconfig *nconf)
{
    int fd;
    struct t_bind taddr;
    struct addrinfo hints, *res = NULL;
    struct __rpc_sockinfo si;
    SVCXPRT	*my_xprt;
    int status;	/* bound checking ? */
    int aicode;
    int addrlen;
    int nhostsbak;
    int bound;
    struct sockaddr *sa;
    u_int32_t host_addr[4];  /* IPv4 or IPv6 */
    struct sockaddr_un sun;
    mode_t oldmask;

    if ((nconf->nc_semantics != NC_TPI_CLTS) &&
            (nconf->nc_semantics != NC_TPI_COTS) &&
            (nconf->nc_semantics != NC_TPI_COTS_ORD))
        return (1);	/* not my type */
#ifdef ND_DEBUG
    if (debugging) {
        int i;
        char **s;

        (void)fprintf(stderr, "%s: %ld lookup routines :\n",
                      nconf->nc_netid, nconf->nc_nlookups);
        for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
                i++, s++)
            fprintf(stderr, "[%d] - %s\n", i, *s);
    }
#endif

    /*
     * XXX - using RPC library internal functions.
     */
    if ((strcmp(nconf->nc_netid, "local") == 0) ||
            (strcmp(nconf->nc_netid, "unix") == 0)) {
        /*
         * For other transports we call this later, for each socket we
         * like to bind.
         */
        if ((fd = __rpc_nconf2fd(nconf)) < 0) {
            int non_fatal = 0;
            if (errno == EAFNOSUPPORT)
                non_fatal = 1;
            syslog(non_fatal?LOG_DEBUG:LOG_ERR, "cannot create socket for %s",
                   nconf->nc_netid);
            return (1);
        }
    }

    if (!__rpc_nconf2sockinfo(nconf, &si)) {
        syslog(LOG_ERR, "cannot get information for %s",
               nconf->nc_netid);
        return (1);
    }

    if ((strcmp(nconf->nc_netid, "local") == 0) ||
            (strcmp(nconf->nc_netid, "unix") == 0)) {
        memset(&sun, 0, sizeof sun);
        sun.sun_family = AF_LOCAL;
        unlink(_PATH_RPCBINDSOCK);
        strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
        sun.sun_len = SUN_LEN(&sun);
        addrlen = sizeof (struct sockaddr_un);
        sa = (struct sockaddr *)&sun;
    } else {
        /* Get rpcbind's address on this transport */

        memset(&hints, 0, sizeof hints);
        hints.ai_flags = AI_PASSIVE;
        hints.ai_family = si.si_af;
        hints.ai_socktype = si.si_socktype;
        hints.ai_protocol = si.si_proto;
    }

    if ((strcmp(nconf->nc_netid, "local") != 0) &&
            (strcmp(nconf->nc_netid, "unix") != 0)) {
        /*
         * If no hosts were specified, just bind to INADDR_ANY.
         * Otherwise  make sure 127.0.0.1 is added to the list.
         */
        nhostsbak = nhosts + 1;
        hosts = realloc(hosts, nhostsbak * sizeof(char *));
        if (nhostsbak == 1)
            hosts[0] = "*";
        else {
            if (hints.ai_family == AF_INET) {
                hosts[nhostsbak - 1] = "127.0.0.1";
            } else if (hints.ai_family == AF_INET6) {
                hosts[nhostsbak - 1] = "::1";
            } else
                return 1;
        }

        /*
         * Bind to specific IPs if asked to
         */
        bound = 0;
        while (nhostsbak > 0) {
            --nhostsbak;
            /*
             * XXX - using RPC library internal functions.
             */
            if ((fd = __rpc_nconf2fd(nconf)) < 0) {
                int non_fatal = 0;
                if (errno == EAFNOSUPPORT &&
                        nconf->nc_semantics != NC_TPI_CLTS)
                    non_fatal = 1;
                syslog(non_fatal ? LOG_DEBUG : LOG_ERR,
                       "cannot create socket for %s", nconf->nc_netid);
                return (1);
            }
            switch (hints.ai_family) {
            case AF_INET:
                if (inet_pton(AF_INET, hosts[nhostsbak],
                              host_addr) == 1) {
                    hints.ai_flags &= AI_NUMERICHOST;
                } else {
                    /*
                     * Skip if we have an AF_INET6 address.
                     */
                    if (inet_pton(AF_INET6,
                                  hosts[nhostsbak], host_addr) == 1) {
                        close(fd);
                        continue;
                    }
                }
                break;
            case AF_INET6:
                if (inet_pton(AF_INET6, hosts[nhostsbak],
                              host_addr) == 1) {
                    hints.ai_flags &= AI_NUMERICHOST;
                } else {
                    /*
                     * Skip if we have an AF_INET address.
                     */
                    if (inet_pton(AF_INET, hosts[nhostsbak],
                                  host_addr) == 1) {
                        close(fd);
                        continue;
                    }
                }
                if (setsockopt(fd, IPPROTO_IPV6,
                               IPV6_V6ONLY, &on, sizeof on) < 0) {
                    syslog(LOG_ERR,
                           "can't set v6-only binding for "
                           "ipv6 socket: %m");
                    continue;
                }
                break;
            default:
                break;
            }

            /*
             * If no hosts were specified, just bind to INADDR_ANY
             */
            if (strcmp("*", hosts[nhostsbak]) == 0)
                hosts[nhostsbak] = NULL;
            if ((strcmp(nconf->nc_netid, "local") != 0) &&
                    (strcmp(nconf->nc_netid, "unix") != 0)) {
                if ((aicode = getaddrinfo(hosts[nhostsbak],
                                          servname, &hints, &res)) != 0) {
                    syslog(LOG_ERR,
                           "cannot get local address for %s: %s",
                           nconf->nc_netid, gai_strerror(aicode));
                    continue;
                }
                addrlen = res->ai_addrlen;
                sa = (struct sockaddr *)res->ai_addr;
            }
            oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
            if (bind(fd, sa, addrlen) != 0) {
                syslog(LOG_ERR, "cannot bind %s on %s: %m",
                       (hosts[nhostsbak] == NULL) ? "*" :
                       hosts[nhostsbak], nconf->nc_netid);
                if (res != NULL)
                    freeaddrinfo(res);
                continue;
            } else
                bound = 1;
            (void)umask(oldmask);

            /* Copy the address */
            taddr.addr.len = taddr.addr.maxlen = addrlen;
            taddr.addr.buf = malloc(addrlen);
            if (taddr.addr.buf == NULL) {
                syslog(LOG_ERR,
                       "cannot allocate memory for %s address",
                       nconf->nc_netid);
                if (res != NULL)
                    freeaddrinfo(res);
                return 1;
            }
            memcpy(taddr.addr.buf, sa, addrlen);
#ifdef ND_DEBUG
            if (debugging) {
                /*
                 * for debugging print out our universal
                 * address
                 */
                char *uaddr;
                struct netbuf nb;

                nb.buf = sa;
                nb.len = nb.maxlen = sa->sa_len;
                uaddr = taddr2uaddr(nconf, &nb);
                (void)fprintf(stderr,
                              "rpcbind : my address is %s\n", uaddr);
                (void)free(uaddr);
            }
#endif

            if (nconf->nc_semantics != NC_TPI_CLTS)
                listen(fd, SOMAXCONN);

            my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
                                                RPC_MAXDATASIZE, RPC_MAXDATASIZE);
            if (my_xprt == (SVCXPRT *)NULL) {
                syslog(LOG_ERR, "%s: could not create service",
                       nconf->nc_netid);
                goto error;
            }
        }
        if (!bound)
            return 1;
    } else {
        oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
        if (bind(fd, sa, addrlen) < 0) {
            syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
            if (res != NULL)
                freeaddrinfo(res);
            return 1;
        }
        (void) umask(oldmask);

        /* Copy the address */
        taddr.addr.len = taddr.addr.maxlen = addrlen;
        taddr.addr.buf = malloc(addrlen);
        if (taddr.addr.buf == NULL) {
            syslog(LOG_ERR, "cannot allocate memory for %s address",
                   nconf->nc_netid);
            if (res != NULL)
                freeaddrinfo(res);
            return 1;
        }
        memcpy(taddr.addr.buf, sa, addrlen);
#ifdef ND_DEBUG
        if (debugging) {
            /* for debugging print out our universal address */
            char *uaddr;
            struct netbuf nb;

            nb.buf = sa;
            nb.len = nb.maxlen = sa->sa_len;
            uaddr = taddr2uaddr(nconf, &nb);
            (void) fprintf(stderr, "rpcbind : my address is %s\n",
                           uaddr);
            (void) free(uaddr);
        }
#endif

        if (nconf->nc_semantics != NC_TPI_CLTS)
            listen(fd, SOMAXCONN);

        my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
                                            RPC_MAXDATASIZE, RPC_MAXDATASIZE);
        if (my_xprt == (SVCXPRT *)NULL) {
            syslog(LOG_ERR, "%s: could not create service",
                   nconf->nc_netid);
            goto error;
        }
    }

#ifdef PORTMAP
    /*
     * Register both the versions for tcp/ip, udp/ip and local.
     */
    if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
            (strcmp(nconf->nc_proto, NC_TCP) == 0 ||
             strcmp(nconf->nc_proto, NC_UDP) == 0)) ||
            (strcmp(nconf->nc_netid, "unix") == 0) ||
            (strcmp(nconf->nc_netid, "local") == 0)) {
        struct pmaplist *pml;

        if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
                          pmap_service, 0)) {
            syslog(LOG_ERR, "could not register on %s",
                   nconf->nc_netid);
            goto error;
        }
        pml = malloc(sizeof (struct pmaplist));
        if (pml == NULL) {
            syslog(LOG_ERR, "no memory!");
            exit(1);
        }
        pml->pml_map.pm_prog = PMAPPROG;
        pml->pml_map.pm_vers = PMAPVERS;
        pml->pml_map.pm_port = PMAPPORT;
        if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
            if (tcptrans[0]) {
                syslog(LOG_ERR,
                       "cannot have more than one TCP transport");
                goto error;
            }
            tcptrans = strdup(nconf->nc_netid);
            pml->pml_map.pm_prot = IPPROTO_TCP;

            /* Let's snarf the universal address */
            /* "h1.h2.h3.h4.p1.p2" */
            tcp_uaddr = taddr2uaddr(nconf, &taddr.addr);
        } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
            if (udptrans[0]) {
                syslog(LOG_ERR,
                       "cannot have more than one UDP transport");
                goto error;
            }
            udptrans = strdup(nconf->nc_netid);
            pml->pml_map.pm_prot = IPPROTO_UDP;

            /* Let's snarf the universal address */
            /* "h1.h2.h3.h4.p1.p2" */
            udp_uaddr = taddr2uaddr(nconf, &taddr.addr);
        } else if (strcmp(nconf->nc_netid, "local") == 0)
            pml->pml_map.pm_prot = IPPROTO_ST;
        else if (strcmp(nconf->nc_netid, "unix") == 0)
            pml->pml_map.pm_prot = IPPROTO_ST;
        pml->pml_next = list_pml;
        list_pml = pml;

        /* Add version 3 information */
        pml = malloc(sizeof (struct pmaplist));
        if (pml == NULL) {
            syslog(LOG_ERR, "no memory!");
            exit(1);
        }
        pml->pml_map = list_pml->pml_map;
        pml->pml_map.pm_vers = RPCBVERS;
        pml->pml_next = list_pml;
        list_pml = pml;

        /* Add version 4 information */
        pml = malloc (sizeof (struct pmaplist));
        if (pml == NULL) {
            syslog(LOG_ERR, "no memory!");
            exit(1);
        }
        pml->pml_map = list_pml->pml_map;
        pml->pml_map.pm_vers = RPCBVERS4;
        pml->pml_next = list_pml;
        list_pml = pml;

        /* Also add version 2 stuff to rpcbind list */
        rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
    }
#endif

    /* version 3 registration */
    if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
        syslog(LOG_ERR, "could not register %s version 3",
               nconf->nc_netid);
        goto error;
    }
    rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);

    /* version 4 registration */
    if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
        syslog(LOG_ERR, "could not register %s version 4",
               nconf->nc_netid);
        goto error;
    }
    rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);

    /* decide if bound checking works for this transport */
    status = add_bndlist(nconf, &taddr.addr);
#ifdef BIND_DEBUG
    if (debugging) {
        if (status < 0) {
            fprintf(stderr, "Error in finding bind status for %s\n",
                    nconf->nc_netid);
        } else if (status == 0) {
            fprintf(stderr, "check binding for %s\n",
                    nconf->nc_netid);
        } else if (status > 0) {
            fprintf(stderr, "No check binding for %s\n",
                    nconf->nc_netid);
        }
    }
#endif
    /*
     * rmtcall only supported on CLTS transports for now.
     */
    if (nconf->nc_semantics == NC_TPI_CLTS) {
        status = create_rmtcall_fd(nconf);

#ifdef BIND_DEBUG
        if (debugging) {
            if (status < 0) {
                fprintf(stderr,
                        "Could not create rmtcall fd for %s\n",
                        nconf->nc_netid);
            } else {
                fprintf(stderr, "rmtcall fd for %s is %d\n",
                        nconf->nc_netid, status);
            }
        }
#endif
    }
    return (0);
error:
    close(fd);
    return (1);
}
Пример #15
0
int
main(int argc, char *argv[])
{
	SVCXPRT *transp;
	int ok;
	struct sockaddr_storage from;
	socklen_t fromlen;

        if (argc == 2)
                closedown = atoi(argv[1]);
        if (closedown <= 0)
                closedown = 20;

        /*
         * See if inetd started us
         */
	fromlen = sizeof(from);
        if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) {
                from_inetd = 0;
        }

        if (!from_inetd) {
                daemon(0, 0);

                (void)rpcb_unset(RSTATPROG, RSTATVERS_TIME, NULL);
                (void)rpcb_unset(RSTATPROG, RSTATVERS_SWTCH, NULL);
                (void)rpcb_unset(RSTATPROG, RSTATVERS_ORIG, NULL);

		(void) signal(SIGINT, cleanup);
		(void) signal(SIGTERM, cleanup);
		(void) signal(SIGHUP, cleanup);
        }

        openlog("rpc.rstatd", LOG_CONS|LOG_PID, LOG_DAEMON);

	if (from_inetd) {
		transp = svc_tli_create(0, NULL, NULL, 0, 0);
		if (transp == NULL) {
			syslog(LOG_ERR, "cannot create udp service.");
			exit(1);
		}
		ok = svc_reg(transp, RSTATPROG, RSTATVERS_TIME,
			     rstat_service, NULL);
	} else
		ok = svc_create(rstat_service,
				RSTATPROG, RSTATVERS_TIME, "udp");
	if (!ok) {
		syslog(LOG_ERR, "unable to register (RSTATPROG, RSTATVERS_TIME, %s)", (!from_inetd)?"udp":"(inetd)");
  		exit(1);
	}
	if (from_inetd)
		ok = svc_reg(transp, RSTATPROG, RSTATVERS_SWTCH,
			     rstat_service, NULL);
	else
		ok = svc_create(rstat_service,
				RSTATPROG, RSTATVERS_SWTCH, "udp");
	if (!ok) {
		syslog(LOG_ERR, "unable to register (RSTATPROG, RSTATVERS_SWTCH, %s)", (!from_inetd)?"udp":"(inetd)");
  		exit(1);
	}
	if (from_inetd)
		ok = svc_reg(transp, RSTATPROG, RSTATVERS_ORIG,
			     rstat_service, NULL);
	else
		ok = svc_create(rstat_service,
				RSTATPROG, RSTATVERS_ORIG, "udp");
	if (!ok) {
		syslog(LOG_ERR, "unable to register (RSTATPROG, RSTATVERS_ORIG, %s)", (!from_inetd)?"udp":"(inetd)");
  		exit(1);
	}

        svc_run();
	syslog(LOG_ERR, "svc_run returned");
	exit(1);
}
Пример #16
0
/*
 * Create the autofs service for amd
 */
int
create_autofs_service(void)
{
  struct t_bind *tbp = 0;
  int fd = -1, err = 1;		/* assume failed */

  plog(XLOG_INFO, "creating autofs service listener");
  autofs_ncp = getnetconfigent(autofs_conftype);
  if (autofs_ncp == NULL) {
    plog(XLOG_ERROR, "create_autofs_service: cannot getnetconfigent for %s", autofs_conftype);
    goto out;
  }

  fd = t_open(autofs_ncp->nc_device, O_RDWR, NULL);
  if (fd < 0) {
    plog(XLOG_ERROR, "create_autofs_service: t_open failed (%s)",
	 t_errlist[t_errno]);
    goto out;
  }

  tbp = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR);
  if (!tbp) {
    plog(XLOG_ERROR, "create_autofs_service: t_alloca failed");
    goto out;
  }

  if (get_autofs_address(autofs_ncp, tbp) != 0) {
    plog(XLOG_ERROR, "create_autofs_service: get_autofs_address failed");
    goto out;
  }

  autofs_xprt = svc_tli_create(fd, autofs_ncp, tbp, 0, 0);
  if (autofs_xprt == NULL) {
    plog(XLOG_ERROR, "cannot create autofs tli service for amd");
    goto out;
  }

  rpcb_unset(AUTOFS_PROG, AUTOFS_VERS, autofs_ncp);
  if (svc_reg(autofs_xprt, AUTOFS_PROG, AUTOFS_VERS, autofs_program_1, autofs_ncp) == FALSE) {
    plog(XLOG_ERROR, "could not register amd AUTOFS service");
    goto out;
  }
  err = 0;
  goto really_out;

out:
  if (autofs_ncp)
    freenetconfigent(autofs_ncp);
  if (autofs_xprt)
    SVC_DESTROY(autofs_xprt);
  else {
    if (fd > 0)
      t_close(fd);
  }

really_out:
  if (tbp)
    t_free((char *) tbp, T_BIND);

  dlog("create_autofs_service: returning %d\n", err);
  return err;
}
Пример #17
0
int
main(int argc, char *argv[])
{
	pid_t pid;
	int c;
	char *progname = argv[0];
	int connmaxrec = RPC_MAXDATASIZE;

	while ((c = getopt(argc, argv, "d")) != -1)
		switch ((char)c) {
		case 'd':
			debug++;
			break;
		default:
			(void) fprintf(stderr, "usage: %s [-d]\n", progname);
			exit(EXIT_FAILURE);
		}


	/*
	 * Set non-blocking mode and maximum record size for
	 * connection oriented RPC transports.
	 */
	if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) {
		msgout("unable to set maximum RPC record size");
	}

	/*
	 * If stdin looks like a TLI endpoint, we assume
	 * that we were started by a port monitor. If
	 * t_getstate fails with TBADF, this is not a
	 * TLI endpoint.
	 */
	if (t_getstate(0) != -1 || t_errno != TBADF) {
		char *netid;
		struct netconfig *nconf = NULL;
		SVCXPRT *transp;
		int pmclose;

		if ((netid = getenv("NLSPROVIDER")) == NULL) {
			if (debug)
				msgout("cannot get transport name");
		} else if ((nconf = getnetconfigent(netid)) == NULL) {
			if (debug)
				msgout("cannot get transport info");
		}
		pmclose = (t_getstate(0) != T_DATAXFER);
		if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
			msgout("cannot create server handle");
			exit(EXIT_FAILURE);
		}
		if (nconf)
			freenetconfigent(nconf);
		if (!svc_reg(transp, BOOTPARAMPROG, BOOTPARAMVERS,
		    bootparamprog_1, 0)) {
			msgout("unable to register (BOOTPARAMPROG, "
			    "BOOTPARAMVERS).");
			exit(EXIT_FAILURE);
		}
		if (pmclose) {
			(void) signal(SIGALRM, closedown);
			(void) alarm(_RPCSVC_CLOSEDOWN);
		}

		svc_run();
		exit(EXIT_FAILURE);
		/* NOTREACHED */
	}

	/*
	 * run this process in the background only if it was started from
	 * a shell and the debug flag was not given.
	 */
	if (!server_child && !debug) {
		pid = fork();
		if (pid < 0) {
			perror("cannot fork");
			exit(EXIT_FAILURE);
		}
		if (pid)
			exit(EXIT_SUCCESS);

		closefrom(0);
		(void) setsid();
	}

	/*
	 * messges go to syslog if the program was started by
	 * another server, or if it was run from the command line without
	 * the debug flag.
	 */
	if (server_child || !debug)
		openlog("bootparam_prot", LOG_PID, LOG_DAEMON);

	if (debug) {
		if (debug == 1)
			msgout("in debug mode.");
		else
			msgout("in debug mode (level %d).", debug);
	}

	if (!svc_create(bootparamprog_1, BOOTPARAMPROG, BOOTPARAMVERS,
			"netpath")) {
		msgout("unable to create (BOOTPARAMPROG, BOOTPARAMVERS) "
		    "for netpath.");
		exit(EXIT_FAILURE);
	}

	svc_run();
	msgout("svc_run returned");
	return (EXIT_FAILURE);
}
Пример #18
0
/*
 * register an RPC server
 */
int
amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum, void (*dispatch)(), u_long protocol, struct netconfig *ncp)
{
  return svc_reg(xprt, prognum, versnum, dispatch, ncp);
}
Пример #19
0
/*
 * Called after all the create_service() calls have succeeded, to complete
 * the setup and registration.
 */
static void
complete_service(struct netconfig *nconf, char *port_str)
{
	struct addrinfo hints, *res = NULL;
	struct __rpc_sockinfo si;
	struct netbuf servaddr;
	SVCXPRT	*transp = NULL;
	int aicode, fd, nhostsbak;
	int registered = 0;

	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
	    (nconf->nc_semantics != NC_TPI_COTS) &&
	    (nconf->nc_semantics != NC_TPI_COTS_ORD))
		return;	/* not my type */

	/*
	 * XXX - using RPC library internal functions.
	 */
	if (!__rpc_nconf2sockinfo(nconf, &si)) {
		syslog(LOG_ERR, "cannot get information for %s",
		    nconf->nc_netid);
		return;
	}

	nhostsbak = nhosts;
	while (nhostsbak > 0) {
		--nhostsbak;
		if (sock_fdpos >= sock_fdcnt) {
			/* Should never happen. */
			syslog(LOG_ERR, "Ran out of socket fd's");
			return;
		}
		fd = sock_fd[sock_fdpos++];
		if (fd < 0)
			continue;

		if (nconf->nc_semantics != NC_TPI_CLTS)
			listen(fd, SOMAXCONN);

		transp = svc_tli_create(fd, nconf, NULL,
		RPC_MAXDATASIZE, RPC_MAXDATASIZE);

		if (transp != (SVCXPRT *) NULL) {
			if (!svc_register(transp, SM_PROG, SM_VERS,
			    sm_prog_1, 0)) {
				syslog(LOG_ERR, "can't register on %s",
				    nconf->nc_netid);
			} else {
				if (!svc_reg(transp, SM_PROG, SM_VERS,
				    sm_prog_1, NULL)) 
					syslog(LOG_ERR,
					    "can't register %s SM_PROG service",
					    nconf->nc_netid);
			}
		} else 
			syslog(LOG_WARNING, "can't create %s services",
			    nconf->nc_netid);

		if (registered == 0) {
			registered = 1;
			memset(&hints, 0, sizeof hints);
			hints.ai_flags = AI_PASSIVE;
			hints.ai_family = si.si_af;
			hints.ai_socktype = si.si_socktype;
			hints.ai_protocol = si.si_proto;


			if ((aicode = getaddrinfo(NULL, port_str, &hints,
			    &res)) != 0) {
				syslog(LOG_ERR, "cannot get local address: %s",
				    gai_strerror(aicode));
				exit(1);
			}

			servaddr.buf = malloc(res->ai_addrlen);
			memcpy(servaddr.buf, res->ai_addr, res->ai_addrlen);
			servaddr.len = res->ai_addrlen;

			rpcb_set(SM_PROG, SM_VERS, nconf, &servaddr);

			xcreated++;
			freeaddrinfo(res);
		}
	} /* end while */
}
Пример #20
0
/*
 * Adds the entry into the rpcbind database.
 * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
 * Returns 0 if succeeds, else fails
 */
static int
init_transport(struct netconfig *nconf)
{
	int fd = -1;
	struct t_bind taddr;
	struct addrinfo hints, *res;
	struct __rpc_sockinfo si;
	SVCXPRT	*my_xprt = NULL;
	int status;	/* bound checking ? */
	int aicode;
	int addrlen = 0;
	int nhostsbak;
	int checkbind;
	struct sockaddr *sa = NULL;
	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
	struct sockaddr_un sun;
	mode_t oldmask;
        res = NULL;

	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
		(nconf->nc_semantics != NC_TPI_COTS) &&
		(nconf->nc_semantics != NC_TPI_COTS_ORD))
		return (1);	/* not my type */
#ifdef RPCBIND_DEBUG
	if (debugging) {
		int i;
		char **s;

		(void) fprintf(stderr, "%s: %ld lookup routines :\n",
			nconf->nc_netid, nconf->nc_nlookups);
		for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
		     i++, s++)
			fprintf(stderr, "[%d] - %s\n", i, *s);
	}
#endif

	/*
	 * XXX - using RPC library internal functions. For NC_TPI_CLTS
	 * we call this later, for each socket we like to bind.
	 */
	if (nconf->nc_semantics != NC_TPI_CLTS) {
		if ((fd = __rpc_nconf2fd(nconf)) < 0) {
			syslog(LOG_ERR, "cannot create socket for %s",
			    nconf->nc_netid);
			return (1);
		}
	}

	if (!__rpc_nconf2sockinfo(nconf, &si)) {
		syslog(LOG_ERR, "cannot get information for %s",
		    nconf->nc_netid);
		return (1);
	}

	if ((strcmp(nconf->nc_netid, "local") == 0) ||
	    (strcmp(nconf->nc_netid, "unix") == 0)) {
		memset(&sun, 0, sizeof sun);
		sun.sun_family = AF_LOCAL;
		unlink(_PATH_RPCBINDSOCK);
		strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
		addrlen = SUN_LEN(&sun);
		sa = (struct sockaddr *)&sun;
	} else {
		/* Get rpcbind's address on this transport */

		memset(&hints, 0, sizeof hints);
		hints.ai_flags = AI_PASSIVE;
		hints.ai_family = si.si_af;
		hints.ai_socktype = si.si_socktype;
		hints.ai_protocol = si.si_proto;
	}
	if (nconf->nc_semantics == NC_TPI_CLTS) {
		/*
		 * If no hosts were specified, just bind to INADDR_ANY.  Otherwise
		 * make sure 127.0.0.1 is added to the list.
		 */
		nhostsbak = nhosts;
		nhostsbak++;
		hosts = realloc(hosts, nhostsbak * sizeof(char *));
		if (nhostsbak == 1)
			hosts[0] = "*";
		else {
			if (hints.ai_family == AF_INET) {
				hosts[nhostsbak - 1] = "127.0.0.1";
			} else if (hints.ai_family == AF_INET6) {
				hosts[nhostsbak - 1] = "::1";
			} else
				return 1;
		}

	       /*
		* Bind to specific IPs if asked to
		*/
		checkbind = 0;
		while (nhostsbak > 0) {
			--nhostsbak;
			/*
			 * XXX - using RPC library internal functions.
			 */
			if ((fd = __rpc_nconf2fd(nconf)) < 0) {
				syslog(LOG_ERR, "cannot create socket for %s",
				    nconf->nc_netid);
				return (1);
			}
			switch (hints.ai_family) {
			case AF_INET:
				if (inet_pton(AF_INET, hosts[nhostsbak],
				    host_addr) == 1) {
					hints.ai_flags &= AI_NUMERICHOST;
				} else {
					/*
					 * Skip if we have an AF_INET6 adress.
					 */
					if (inet_pton(AF_INET6,
					    hosts[nhostsbak], host_addr) == 1)
						continue;
				}
				break;
			case AF_INET6:
				if (inet_pton(AF_INET6, hosts[nhostsbak],
				    host_addr) == 1) {
					hints.ai_flags &= AI_NUMERICHOST;
				} else {
					/*
					 * Skip if we have an AF_INET adress.
					 */
					if (inet_pton(AF_INET, hosts[nhostsbak],
					    host_addr) == 1)
						continue;
				}
	        		break;
			default:
				break;
			}

			/*
			 * If no hosts were specified, just bind to INADDR_ANY
			 */
			if (strcmp("*", hosts[nhostsbak]) == 0)
				hosts[nhostsbak] = NULL;

			if ((aicode = getaddrinfo(hosts[nhostsbak],
			    servname, &hints, &res)) != 0) {
			  if ((aicode = getaddrinfo(hosts[nhostsbak],
						    "portmapper", &hints, &res)) != 0) {
				syslog(LOG_ERR,
				    "cannot get local address for %s: %s",
				    nconf->nc_netid, gai_strerror(aicode));
				continue;
			  }
			}
			addrlen = res->ai_addrlen;
			sa = (struct sockaddr *)res->ai_addr;
			oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
                        if (bind(fd, sa, addrlen) != 0) {
				syslog(LOG_ERR, "cannot bind %s on %s: %m",
					(hosts[nhostsbak] == NULL) ? "*" :
					hosts[nhostsbak], nconf->nc_netid);
				if (res != NULL)
					freeaddrinfo(res);
				continue;
			} else
				checkbind++;
			(void) umask(oldmask);

			/* Copy the address */
			taddr.addr.maxlen = taddr.addr.len = addrlen;
			taddr.addr.buf = malloc(addrlen);
			if (taddr.addr.buf == NULL) {
				syslog(LOG_ERR,
				    "cannot allocate memory for %s address",
				    nconf->nc_netid);
				if (res != NULL)
					freeaddrinfo(res);
				return 1;
			}
			memcpy(taddr.addr.buf, sa, addrlen);
#ifdef RPCBIND_DEBUG
			if (debugging) {
				/*
				 * for debugging print out our universal
				 * address
				 */
				char *uaddr;
				struct netbuf nb;
				int sa_size = 0;

				nb.buf = sa;
				switch( sa->sa_family){
				case AF_INET:
				  sa_size = sizeof (struct sockaddr_in);
				  break;
				case AF_INET6:
				  sa_size = sizeof (struct sockaddr_in6);				 
				  break;
				}
				nb.len = nb.maxlen = sa_size;
				uaddr = taddr2uaddr(nconf, &nb);
				(void) fprintf(stderr,
				    "rpcbind : my address is %s\n", uaddr);
				(void) free(uaddr);
			}
#endif
			my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 
                                RPC_MAXDATASIZE, RPC_MAXDATASIZE);
			if (my_xprt == (SVCXPRT *)NULL) {
				syslog(LOG_ERR, "%s: could not create service", 
                                        nconf->nc_netid);
				goto error;
			}
		}
		if (!checkbind)
			return 1;
	} else {	/* NC_TPI_COTS */
		if ((strcmp(nconf->nc_netid, "local") != 0) &&
		    (strcmp(nconf->nc_netid, "unix") != 0)) {
			if ((aicode = getaddrinfo(NULL, servname, &hints, &res))!= 0) {
			  if ((aicode = getaddrinfo(NULL, "portmapper", &hints, &res))!= 0) {
			  printf("cannot get local address for %s: %s",  nconf->nc_netid, gai_strerror(aicode));
			  syslog(LOG_ERR,
				    "cannot get local address for %s: %s",
				    nconf->nc_netid, gai_strerror(aicode));
				return 1;
			  }
			}
			addrlen = res->ai_addrlen;
			sa = (struct sockaddr *)res->ai_addr;
		}
		oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
		__rpc_fd2sockinfo(fd, &si);
		if (bind(fd, sa, addrlen) < 0) {
			syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
			if (res != NULL)
				freeaddrinfo(res);
			return 1;
		}
		(void) umask(oldmask);

		/* Copy the address */
		taddr.addr.len = taddr.addr.maxlen = addrlen;
		taddr.addr.buf = malloc(addrlen);
		if (taddr.addr.buf == NULL) {
			syslog(LOG_ERR, "cannot allocate memory for %s address",
			    nconf->nc_netid);
			if (res != NULL)
				freeaddrinfo(res);
			return 1;
		}
		memcpy(taddr.addr.buf, sa, addrlen);
#ifdef RPCBIND_DEBUG
		if (debugging) {
			/* for debugging print out our universal address */
			char *uaddr;
			struct netbuf nb;
		        int sa_size2 = 0;

			nb.buf = sa;
			switch( sa->sa_family){
			case AF_INET:
			  sa_size2 = sizeof (struct sockaddr_in);
			  break;
			case AF_INET6:
			  sa_size2 = sizeof (struct sockaddr_in6);				 
			  break;
			}
			nb.len = nb.maxlen = sa_size2;
			uaddr = taddr2uaddr(nconf, &nb);
			(void) fprintf(stderr, "rpcbind : my address is %s\n",
			    uaddr);
			(void) free(uaddr);
		}
#endif

		listen(fd, SOMAXCONN);

		my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
		if (my_xprt == (SVCXPRT *)NULL) {
			syslog(LOG_ERR, "%s: could not create service",
					nconf->nc_netid);
			goto error;
		}
	}

#ifdef PORTMAP
	/*
	 * Register both the versions for tcp/ip, udp/ip.
	 */
	if (si.si_af == AF_INET &&
	    (si.si_proto == IPPROTO_TCP || si.si_proto == IPPROTO_UDP)) {
		struct pmaplist *pml;

		pml = malloc(sizeof (struct pmaplist));
		if (pml == NULL) {
			syslog(LOG_ERR, "no memory!");
			exit(1);
		}
		pml->pml_map.pm_prog = PMAPPROG;
		pml->pml_map.pm_vers = PMAPVERS;
		pml->pml_map.pm_port = PMAPPORT;
		pml->pml_map.pm_prot = si.si_proto;

		switch (si.si_proto) {
		case IPPROTO_TCP:
			tcptrans = strdup(nconf->nc_netid);
			break;
		case IPPROTO_UDP:
			udptrans = strdup(nconf->nc_netid);
			break;
		} 
		pml->pml_next = list_pml;
		list_pml = pml;

		/* Add version 3 information */
		pml = malloc(sizeof (struct pmaplist));
		if (pml == NULL) {
			syslog(LOG_ERR, "no memory!");
			exit(1);
		}
		pml->pml_map = list_pml->pml_map;
		pml->pml_map.pm_vers = RPCBVERS;
		pml->pml_next = list_pml;
		list_pml = pml;

		/* Add version 4 information */
		pml = malloc (sizeof (struct pmaplist));
		if (pml == NULL) {
			syslog(LOG_ERR, "no memory!");
			exit(1);
		}
		pml->pml_map = list_pml->pml_map;
		pml->pml_map.pm_vers = RPCBVERS4;
		pml->pml_next = list_pml;
		list_pml = pml;

		/* Also add version 2 stuff to rpcbind list */
		rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
	}

	/* We need to support portmap over IPv4. It makes sense to
	 * support it over AF_LOCAL as well, because that allows
	 * rpcbind to identify the owner of a socket much better
	 * than by relying on privileged ports to tell root from
	 * non-root users. */
	if (si.si_af == AF_INET || si.si_af == AF_LOCAL) {
		if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, pmap_service, 0)) {
			syslog(LOG_ERR, "could not register on %s",
					nconf->nc_netid);
			goto error;
		}
	}
#endif

	/* version 3 registration */
	if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
		syslog(LOG_ERR, "could not register %s version 3",
				nconf->nc_netid);
		goto error;
	}
	rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);

	/* version 4 registration */
	if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
		syslog(LOG_ERR, "could not register %s version 4",
				nconf->nc_netid);
		goto error;
	}
	rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);

	/* decide if bound checking works for this transport */
	status = add_bndlist(nconf, &taddr.addr);
#ifdef RPCBIND_DEBUG
	if (debugging) {
		if (status < 0) {
			fprintf(stderr, "Error in finding bind status for %s\n",
				nconf->nc_netid);
		} else if (status == 0) {
			fprintf(stderr, "check binding for %s\n",
				nconf->nc_netid);
		} else if (status > 0) {
			fprintf(stderr, "No check binding for %s\n",
				nconf->nc_netid);
		}
	}
#endif
	/*
	 * rmtcall only supported on CLTS transports for now.
	 */
	if (nconf->nc_semantics == NC_TPI_CLTS) {
		status = create_rmtcall_fd(nconf);

#ifdef RPCBIND_DEBUG
		if (debugging) {
			if (status < 0) {
				fprintf(stderr,
				    "Could not create rmtcall fd for %s\n",
					nconf->nc_netid);
			} else {
				fprintf(stderr, "rmtcall fd for %s is %d\n",
					nconf->nc_netid, status);
			}
		}
#endif
	}
	return (0);
error:
	close(fd);
	return (1);
}
Пример #21
0
/*ARGSUSED*/
int
main(int argc, char *argv[])
{
	register SVCXPRT *transp;

	load_libzfs();

	/*
	 * If stdin looks like a TLI endpoint, we assume
	 * that we were started by a port monitor. If
	 * t_getstate fails with TBADF, this is not a
	 * TLI endpoint.
	 */
	if (t_getstate(0) != -1 || t_errno != TBADF) {
		char *netid;
		struct netconfig *nconf = NULL;

		openlog("rquotad", LOG_PID, LOG_DAEMON);

		if ((netid = getenv("NLSPROVIDER")) == NULL) {
			struct t_info tinfo;

			if (t_sync(0) == -1) {
				syslog(LOG_ERR, "could not do t_sync");
				zexit(1);
			}
			if (t_getinfo(0, &tinfo) == -1) {
				syslog(LOG_ERR, "t_getinfo failed");
				zexit(1);
			}
			if (tinfo.servtype == T_CLTS) {
				if (tinfo.addr == INET_ADDRSTRLEN)
					netid = "udp";
				else
					netid = "udp6";
			} else {
				syslog(LOG_ERR, "wrong transport");
				zexit(1);
			}
		}
		if ((nconf = getnetconfigent(netid)) == NULL) {
			syslog(LOG_ERR, "cannot get transport info");
		}

		if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
			syslog(LOG_ERR, "cannot create server handle");
			zexit(1);
		}
		if (nconf)
			freenetconfigent(nconf);

		if (!svc_reg(transp, RQUOTAPROG, RQUOTAVERS, dispatch, 0)) {
			syslog(LOG_ERR,
			    "unable to register (RQUOTAPROG, RQUOTAVERS).");
			zexit(1);
		}

		(void) sigset(SIGALRM, (void(*)(int)) closedown);
		(void) alarm(RPCSVC_CLOSEDOWN);

		svc_run();
		zexit(1);
		/* NOTREACHED */
	}

	/*
	 * Started from a shell - fork the daemon.
	 */

	switch (fork()) {
	case 0:		/* child */
		break;
	case -1:
		perror("rquotad: can't fork");
		zexit(1);
	default:	/* parent */
		zexit(0);
	}

	/*
	 * Close existing file descriptors, open "/dev/null" as
	 * standard input, output, and error, and detach from
	 * controlling terminal.
	 */
	closefrom(0);
	(void) open("/dev/null", O_RDONLY);
	(void) open("/dev/null", O_WRONLY);
	(void) dup(1);
	(void) setsid();

	openlog("rquotad", LOG_PID, LOG_DAEMON);

	/*
	 * Create datagram service
	 */
	if (svc_create(dispatch, RQUOTAPROG, RQUOTAVERS, "datagram_v") == 0) {
		syslog(LOG_ERR, "couldn't register datagram_v service");
		zexit(1);
	}

	/*
	 * Start serving
	 */
	svc_run();
	syslog(LOG_ERR, "Error: svc_run shouldn't have returned");
	return (1);
}
Пример #22
0
int
main(int argc, char **argv)
{
	int nflag = 0;
	int c;
	int warn = 0;
	char *path = NULL;
	void *localhandle;
	SVCXPRT *transp;
	struct netconfig *nconf = NULL;

	__key_encryptsession_pk_LOCAL = &key_encrypt_pk_2_svc_prog;
	__key_decryptsession_pk_LOCAL = &key_decrypt_pk_2_svc_prog;
	__key_gendes_LOCAL = &key_gen_1_svc_prog;

	while ((c = getopt(argc, argv, "ndDvp:")) != -1)
		switch (c) {
		case 'n':
			nflag++;
			break;
		case 'd':
			pk_nodefaultkeys();
			break;
		case 'D':
			debugging = 1;
			break;
		case 'v':
			warn = 1;
			break;
		case 'p':
			path = optarg;
			break;
		default:
			usage();
		}

	load_des(warn, path);
	__des_crypt_LOCAL = _my_crypt;
	if (svc_auth_reg(AUTH_DES, _svcauth_des) == -1)
		errx(1, "failed to register AUTH_DES authenticator");

	if (optind != argc) {
		usage();
	}

	/*
	 * Initialize
	 */
	umask(S_IXUSR|S_IXGRP|S_IXOTH);
	if (geteuid() != 0)
		errx(1, "keyserv must be run as root");
	setmodulus(HEXMODULUS);
	getrootkey(&masterkey, nflag);

	rpcb_unset(KEY_PROG, KEY_VERS, NULL);
	rpcb_unset(KEY_PROG, KEY_VERS2, NULL);

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS,
		"netpath") == 0) {
		fprintf(stderr, "%s: unable to create service\n", argv[0]);
		exit(1);
	}

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS2,
	"netpath") == 0) {
		fprintf(stderr, "%s: unable to create service\n", argv[0]);
		exit(1);
	}

	localhandle = setnetconfig();
	while ((nconf = getnetconfig(localhandle)) != NULL) {
		if (nconf->nc_protofmly != NULL &&
		    strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
			break;
	}

	if (nconf == NULL)
		errx(1, "getnetconfig: %s", nc_sperror());

	unlink(KEYSERVSOCK);
	rpcb_unset(CRYPT_PROG, CRYPT_VERS, nconf);
	transp = svcunix_create(RPC_ANYSOCK, 0, 0, KEYSERVSOCK);
	if (transp == NULL)
		errx(1, "cannot create AF_LOCAL service");
	if (!svc_reg(transp, KEY_PROG, KEY_VERS, keyprogram, nconf))
		errx(1, "unable to register (KEY_PROG, KEY_VERS, unix)");
	if (!svc_reg(transp, KEY_PROG, KEY_VERS2, keyprogram, nconf))
		errx(1, "unable to register (KEY_PROG, KEY_VERS2, unix)");
	if (!svc_reg(transp, CRYPT_PROG, CRYPT_VERS, crypt_prog_1, nconf))
		errx(1, "unable to register (CRYPT_PROG, CRYPT_VERS, unix)");

	endnetconfig(localhandle);

	umask(066);	/* paranoia */

	if (!debugging) {
		daemon(0,0);
	}

	signal(SIGPIPE, SIG_IGN);

	svc_run();
	abort();
	/* NOTREACHED */
}
Пример #23
0
/*
 * The highest level interface for server creation.
 * Copied from svc_generic.c and cmd/keyserv/key_generic.c, but adapted
 * to work only for TPI_CLTS semantics, and to be called only once
 * from kwarnd.c. Returns 1 (interface created) on success and 0
 * (no interfaces created) on failure.
 */
int
svc_create_local_service(void (*dispatch) (),		/* Dispatch function */
			u_long prognum,			/* Program number */
			u_long versnum,			/* Version number */
			char *nettype,			/* Networktype token */
			char *servname)			/* name of the srvc */
{
	int num = 0;
	SVCXPRT *xprt;
	struct netconfig *nconf;
	struct t_bind *bind_addr;
	void *net;
	int fd;
	struct nd_hostserv ns;
	struct nd_addrlist *nas;

	if ((net = __rpc_setconf(nettype)) == 0) {
		(void) syslog(LOG_ERR,
		gettext("svc_create: could not read netconfig database"));
		return (0);
	}
	while (nconf = __rpc_getconf(net)) {
		if ((strcmp(nconf->nc_protofmly, NC_LOOPBACK)) ||
				(nconf->nc_semantics != NC_TPI_COTS_ORD))
			continue;

		if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) < 0) {
			(void) syslog(LOG_ERR,
			gettext("svc_create: %s: cannot open connection: %s"),
				nconf->nc_netid, t_errlist[t_errno]);
			break;
		}

		/*
		 * Negotiate for returning the uid of the caller.
		 * This should be done before enabling the endpoint for
		 * service via t_bind() (called in svc_tli_create())
		 * so that requests to kwarnd contain the uid.
		 */
		if (__rpc_negotiate_uid(fd) != 0) {
			syslog(LOG_ERR,
			gettext("Could not negotiate for"
				" uid with loopback transport %s"),
				nconf->nc_netid);
			t_close(fd);
			break;
		}

		/* LINTED pointer alignment */
		bind_addr = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR);
		if ((bind_addr == NULL)) {
			(void) t_close(fd);
			(void) syslog(LOG_ERR,
				gettext("svc_create: t_alloc failed\n"));
			break;
		}
		ns.h_host = HOST_SELF;
		ns.h_serv = servname;
		if (!netdir_getbyname(nconf, &ns, &nas)) {
			/* Copy the address */
			bind_addr->addr.len = nas->n_addrs->len;
			(void) memcpy(bind_addr->addr.buf, nas->n_addrs->buf,
				(int) nas->n_addrs->len);
			bind_addr->qlen = 8;
			netdir_free((char *) nas, ND_ADDRLIST);
		} else {
			(void) syslog(LOG_ERR,
			gettext("svc_create: no well known "
				"address for %s on %s\n"),
				servname, nconf->nc_netid);
			(void) t_free((char *) bind_addr, T_BIND);
			bind_addr = NULL;
		}

		xprt = svc_tli_create(fd, nconf, bind_addr, 0, 0);
		if (bind_addr)
			(void) t_free((char *) bind_addr, T_BIND);
		if (xprt == NULL) {
			(void) t_close(fd);
			(void) syslog(LOG_ERR,
			    gettext("svc_create: svc_tli_create failed\n"));
			break;
		} else {
			(void) rpcb_unset(prognum, versnum, nconf);
			if (svc_reg(xprt, prognum, versnum, dispatch, nconf)
					== FALSE) {
				(void) syslog(LOG_ERR,
				gettext("svc_create: cannot"
					" register %d vers %d on %s"),
					prognum, versnum, nconf->nc_netid);
				SVC_DESTROY(xprt);	/* also t_closes fd */
				break;
			}
			num = 1;
			break;
		}
	}
	__rpc_endconf(net);
	return (num);
}
Пример #24
0
int
rpc_reg(const rpcprog_t prognum, const rpcvers_t versnum,
	const rpcproc_t procnum, char *(*progname)(), const xdrproc_t inproc,
	const xdrproc_t outproc, const char *nettype)
{
	struct netconfig *nconf;
	int done = FALSE;
	void *handle;
	extern mutex_t proglst_lock;

	if (procnum == NULLPROC) {
		(void) syslog(LOG_ERR, (const char *) "%s: %s %d",
			rpc_reg_msg,
			(const char *) "can't reassign procedure number %d",
			NULLPROC);
		return (-1);
	}

	if (nettype == NULL)
		nettype = "netpath";		/* The default behavior */
	if ((handle = __rpc_setconf((char *)nettype)) == NULL) {
		(void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg, __reg_err1);
		return (-1);
	}
/* VARIABLES PROTECTED BY proglst_lock: proglst */
	(void) mutex_lock(&proglst_lock);
	while (nconf = __rpc_getconf(handle)) {
		struct proglst *pl;
		SVCXPRT *svcxprt;
		int madenow;
		uint_t recvsz;
		char *xdrbuf;
		char *netid;

		madenow = FALSE;
		svcxprt = NULL;
		for (pl = proglst; pl; pl = pl->p_nxt)
			if (strcmp(pl->p_netid, nconf->nc_netid) == 0) {
				svcxprt = pl->p_transp;
				xdrbuf = pl->p_xdrbuf;
				recvsz = pl->p_recvsz;
				netid = pl->p_netid;
				break;
			}

		if (svcxprt == NULL) {
			struct t_info tinfo;

			svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
			if (svcxprt == NULL)
				continue;
			if (t_getinfo(svcxprt->xp_fd, &tinfo) == -1) {
				char errorstr[100];

				__tli_sys_strerror(errorstr, sizeof (errorstr),
						t_errno, errno);
				(void) syslog(LOG_ERR, "%s : %s : %s",
					rpc_reg_msg, "t_getinfo failed",
					errorstr);
				SVC_DESTROY(svcxprt);
				continue;
			}
			if ((recvsz = __rpc_get_t_size(0, tinfo.tsdu)) == 0) {
				(void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg,
					__reg_err3);
				SVC_DESTROY(svcxprt);
				continue;
			}
			if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) ||
				((netid = strdup(nconf->nc_netid)) == NULL)) {
				(void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg,
					__no_mem_str);
				SVC_DESTROY(svcxprt);
				break;
			}
			madenow = TRUE;
		}
		/*
		 * Check if this (program, version, netid) had already been
		 * registered.  The check may save a few RPC calls to rpcbind
		 */
		for (pl = proglst; pl; pl = pl->p_nxt)
			if ((pl->p_prognum == prognum) &&
				(pl->p_versnum == versnum) &&
				(strcmp(pl->p_netid, netid) == 0))
				break;
		if (pl == NULL) { /* Not yet */
			/*
			 * Note that if we're using a portmapper
			 * instead of rpcbind then we can't do an
			 * unregister operation here.
			 *
			 * The reason is that the portmapper unset
			 * operation removes all the entries for a
			 * given program/version regardelss of
			 * transport protocol.
			 *
			 * The caller of this routine needs to ensure
			 * that __pmap_unset() has been called for all
			 * program/version service pairs they plan
			 * to support before they start registering
			 * each program/version/protocol triplet.
			 */
			if (!use_portmapper)
				(void) rpcb_unset(prognum, versnum, nconf);
		} else {
			/* so that svc_reg does not call rpcb_set() */
			nconf = NULL;
		}

		if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) {
			(void) syslog(LOG_ERR,
				"%s couldn't register prog %d vers %d for %s",
				rpc_reg_msg, prognum, versnum, netid);
			if (madenow) {
				SVC_DESTROY(svcxprt);
				free(xdrbuf);
				free(netid);
			}
			continue;
		}

		pl = malloc(sizeof (struct proglst));
		if (pl == NULL) {
			(void) syslog(LOG_ERR, rpc_reg_err, rpc_reg_msg,
					__no_mem_str);
			if (madenow) {
				SVC_DESTROY(svcxprt);
				free(xdrbuf);
				free(netid);
			}
			break;
		}
		pl->p_progname = progname;
		pl->p_prognum = prognum;
		pl->p_versnum = versnum;
		pl->p_procnum = procnum;
		pl->p_inproc = inproc;
		pl->p_outproc = outproc;
		pl->p_transp = svcxprt;
		pl->p_xdrbuf = xdrbuf;
		pl->p_recvsz = recvsz;
		pl->p_netid = netid;
		pl->p_nxt = proglst;
		proglst = pl;
		done = TRUE;
	}
	__rpc_endconf(handle);
	(void) mutex_unlock(&proglst_lock);

	if (done == FALSE) {
		(void) syslog(LOG_ERR,
			(const char *) "%s cant find suitable transport for %s",
			rpc_reg_msg, nettype);
		return (-1);
	}
	return (0);
}
Пример #25
0
/*
 * We use our own private version of svc_create() which registers our services
 * only on loopback transports and enables an option whereby Solaris ucreds
 * are associated with each connection, permitting us to check privilege bits.
 */
static int
fmd_rpc_svc_create_local(void (*disp)(struct svc_req *, SVCXPRT *),
    rpcprog_t prog, rpcvers_t vers, uint_t ssz, uint_t rsz, int force)
{
	struct netconfig *ncp;
	struct netbuf buf;
	SVCXPRT *xprt;
	void *hdl;
	int fd, n = 0;

	char door[PATH_MAX];
	time_t tm;

	if ((hdl = setnetconfig()) == NULL) {
		fmd_error(EFMD_RPC_REG, "failed to iterate over "
		    "netconfig database: %s\n", nc_sperror());
		return (fmd_set_errno(EFMD_RPC_REG));
	}

	if (force)
		svc_unreg(prog, vers); /* clear stale rpcbind registrations */

	buf.buf = alloca(_SS_MAXSIZE);
	buf.maxlen = _SS_MAXSIZE;
	buf.len = 0;

	while ((ncp = getnetconfig(hdl)) != NULL) {
		if (strcmp(ncp->nc_protofmly, NC_LOOPBACK) != 0)
			continue;

		if (!force && rpcb_getaddr(prog, vers, ncp, &buf, HOST_SELF)) {
			(void) endnetconfig(hdl);
			return (fmd_set_errno(EFMD_RPC_BOUND));
		}

		if ((fd = t_open(ncp->nc_device, O_RDWR, NULL)) == -1) {
			fmd_error(EFMD_RPC_REG, "failed to open %s: %s\n",
			    ncp->nc_device, t_strerror(t_errno));
			continue;
		}

		svc_fd_negotiate_ucred(fd); /* enable ucred option on xprt */

		if ((xprt = svc_tli_create(fd, ncp, NULL, ssz, rsz)) == NULL) {
			(void) t_close(fd);
			continue;
		}

		if (svc_reg(xprt, prog, vers, disp, ncp) == FALSE) {
			fmd_error(EFMD_RPC_REG, "failed to register "
			    "rpc service on %s\n", ncp->nc_netid);
			svc_destroy(xprt);
			continue;
		}

		n++;
	}

	(void) endnetconfig(hdl);

	/*
	 * If we failed to register services (n == 0) because rpcbind is down,
	 * then check to see if the RPC door file exists before attempting an
	 * svc_door_create(), which cleverly destroys any existing door file.
	 * The RPC APIs have no stable errnos, so we use rpcb_gettime() as a
	 * hack to determine if rpcbind itself is down.
	 */
	if (!force && n == 0 && rpcb_gettime(HOST_SELF, &tm) == FALSE &&
	    snprintf(door, sizeof (door), RPC_DOOR_RENDEZVOUS,
	    prog, vers) > 0 && access(door, F_OK) == 0)
		return (fmd_set_errno(EFMD_RPC_BOUND));

	/*
	 * Attempt to create a door server for the RPC program as well.  Limit
	 * the maximum request size for the door transport to the receive size.
	 */
	if ((xprt = svc_door_create(disp, prog, vers, ssz)) == NULL) {
		fmd_error(EFMD_RPC_REG, "failed to create door for "
		    "rpc service 0x%lx/0x%lx\n", prog, vers);
	} else {
		(void) svc_control(xprt, SVCSET_CONNMAXREC, &rsz);
		n++;
	}

	return (n);
}
Пример #26
0
/*
 * For simplified, easy to use kind of rpc interfaces.
 * nettype indicates the type of transport on which the service will be
 * listening. Used for conservation of the system resource. Only one
 * handle is created for all the services (actually one of each netid)
 * and same xdrbuf is used for same netid. The size of the arguments
 * is also limited by the recvsize for that transport, even if it is
 * a COTS transport. This may be wrong, but for cases like these, they
 * should not use the simplified interfaces like this.
 *
 * prognum - program number
 * versnum - version number
 * procnum - procedure number
 * progname - Server routine
 * inproc, outproc - in/out XDR procedures
 * nettype - nettype
 */
int
rpc_reg(rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum,
    char *(*progname)(char *), xdrproc_t inproc, xdrproc_t outproc,
    char *nettype)
{
	struct netconfig *nconf;
	int done = FALSE;
	void *handle;


	if (procnum == NULLPROC) {
		warnx("%s can't reassign procedure number %u", rpc_reg_msg,
			NULLPROC);
		return (-1);
	}

	if (nettype == NULL)
		nettype = "netpath";		/* The default behavior */
	if ((handle = __rpc_setconf(nettype)) == NULL) {
		warnx(rpc_reg_err, rpc_reg_msg, __reg_err1);
		return (-1);
	}
/* VARIABLES PROTECTED BY proglst_lock: proglst */
	mutex_lock(&proglst_lock);
	while ((nconf = __rpc_getconf(handle)) != NULL) {
		struct proglst *pl;
		SVCXPRT *svcxprt;
		int madenow;
		u_int recvsz;
		char *xdrbuf;
		char *netid;

		madenow = FALSE;
		svcxprt = NULL;
		recvsz = 0;
		xdrbuf = netid = NULL;
		for (pl = proglst; pl; pl = pl->p_nxt) {
			if (strcmp(pl->p_netid, nconf->nc_netid) == 0) {
				svcxprt = pl->p_transp;
				xdrbuf = pl->p_xdrbuf;
				recvsz = pl->p_recvsz;
				netid = pl->p_netid;
				break;
			}
		}

		if (svcxprt == NULL) {
			struct __rpc_sockinfo si;

			svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
			if (svcxprt == NULL)
				continue;
			if (!__rpc_fd2sockinfo(svcxprt->xp_fd, &si)) {
				warnx(rpc_reg_err, rpc_reg_msg, __reg_err2);
				SVC_DESTROY(svcxprt);
				continue;
			}
			recvsz = __rpc_get_t_size(si.si_af, si.si_proto, 0);
			if (recvsz == 0) {
				warnx(rpc_reg_err, rpc_reg_msg, __reg_err3);
				SVC_DESTROY(svcxprt);
				continue;
			}
			if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) ||
				((netid = strdup(nconf->nc_netid)) == NULL)) {
				warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
				free(xdrbuf);
				free(netid);
				SVC_DESTROY(svcxprt);
				break;
			}
			madenow = TRUE;
		}
		/*
		 * Check if this (program, version, netid) had already been
		 * registered.  The check may save a few RPC calls to rpcbind
		 */
		for (pl = proglst; pl; pl = pl->p_nxt)
			if ((pl->p_prognum == prognum) &&
				(pl->p_versnum == versnum) &&
				(strcmp(pl->p_netid, netid) == 0))
				break;
		if (pl == NULL) { /* Not yet */
			(void) rpcb_unset(prognum, versnum, nconf);
		} else {
			/* so that svc_reg does not call rpcb_set() */
			nconf = NULL;
		}

		if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) {
			warnx("%s couldn't register prog %u vers %u for %s",
				rpc_reg_msg, (unsigned)prognum,
				(unsigned)versnum, netid);
			if (madenow) {
				SVC_DESTROY(svcxprt);
				free(xdrbuf);
				free(netid);
			}
			continue;
		}

		pl = malloc(sizeof (struct proglst));
		if (pl == NULL) {
			warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
			if (madenow) {
				SVC_DESTROY(svcxprt);
				free(xdrbuf);
				free(netid);
			}
			break;
		}
		pl->p_progname = progname;
		pl->p_prognum = prognum;
		pl->p_versnum = versnum;
		pl->p_procnum = procnum;
		pl->p_inproc = inproc;
		pl->p_outproc = outproc;
		pl->p_transp = svcxprt;
		pl->p_xdrbuf = xdrbuf;
		pl->p_recvsz = recvsz;
		pl->p_netid = netid;
		pl->p_nxt = proglst;
		proglst = pl;
		done = TRUE;
	}
	__rpc_endconf(handle);
	mutex_unlock(&proglst_lock);

	if (done == FALSE) {
		warnx("%s can't find suitable transport for %s",
			rpc_reg_msg, nettype);
		return (-1);
	}
	return (0);
}
Пример #27
0
int
main(int argc, char **argv)
{
	int ch, i, s;
	void *nc_handle;
	char *endptr, **hosts_bak;
	struct sigaction sigalarm;
	int grace_period = 30;
	struct netconfig *nconf;
	int have_v6 = 1;
	int maxrec = RPC_MAXDATASIZE;
	in_port_t svcport = 0;
	int attempt_cnt, port_len, port_pos, ret;
	char **port_list;

	while ((ch = getopt(argc, argv, "d:g:h:p:")) != (-1)) {
		switch (ch) {
		case 'd':
			debug_level = atoi(optarg);
			if (!debug_level) {
				usage();
				/* NOTREACHED */
			}
			break;
		case 'g':
			grace_period = atoi(optarg);
			if (!grace_period) {
				usage();
				/* NOTREACHED */
			}
			break;
		case 'h':
			++nhosts;
			hosts_bak = hosts;
			hosts_bak = realloc(hosts, nhosts * sizeof(char *));
			if (hosts_bak == NULL) {
				if (hosts != NULL) {
					for (i = 0; i < nhosts; i++) 
						free(hosts[i]);
					free(hosts);
					out_of_mem();
				}
			}
			hosts = hosts_bak;
			hosts[nhosts - 1] = strdup(optarg);
			if (hosts[nhosts - 1] == NULL) {
				for (i = 0; i < (nhosts - 1); i++) 
					free(hosts[i]);
				free(hosts);
				out_of_mem();
			}
			break;
		case 'p':
			endptr = NULL;
			svcport = (in_port_t)strtoul(optarg, &endptr, 10);
			if (endptr == NULL || *endptr != '\0' ||
			    svcport == 0 || svcport >= IPPORT_MAX)
				usage();
			svcport_str = strdup(optarg);
			break;
		default:
		case '?':
			usage();
			/* NOTREACHED */
		}
	}
	if (geteuid()) { /* This command allowed only to root */
		fprintf(stderr, "Sorry. You are not superuser\n");
		exit(1);
        }

	kernel_lockd = FALSE;
	kernel_lockd_client = FALSE;
	if (modfind("nfslockd") < 0) {
		if (kldload("nfslockd") < 0) {
			fprintf(stderr, "Can't find or load kernel support for rpc.lockd - using non-kernel implementation\n");
		} else {
			kernel_lockd = TRUE;
		}
	} else {
		kernel_lockd = TRUE;
	}
	if (kernel_lockd) {
		if (getosreldate() >= 800040)
			kernel_lockd_client = TRUE;
	}

	(void)rpcb_unset(NLM_PROG, NLM_SM, NULL);
	(void)rpcb_unset(NLM_PROG, NLM_VERS, NULL);
	(void)rpcb_unset(NLM_PROG, NLM_VERSX, NULL);
	(void)rpcb_unset(NLM_PROG, NLM_VERS4, NULL);

	/*
	 * Check if IPv6 support is present.
	 */
	s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
	if (s < 0)
		have_v6 = 0;
	else 
		close(s);

	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);

	/*
	 * If no hosts were specified, add a wildcard entry to bind to
	 * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the
	 * list.
	 */
	if (nhosts == 0) {
		hosts = malloc(sizeof(char**));
		if (hosts == NULL)
			out_of_mem();

		hosts[0] = "*";
		nhosts = 1;
	} else {
		hosts_bak = hosts;
		if (have_v6) {
			hosts_bak = realloc(hosts, (nhosts + 2) *
			    sizeof(char *));
			if (hosts_bak == NULL) {
				for (i = 0; i < nhosts; i++)
					free(hosts[i]);
				free(hosts);
				out_of_mem();
			} else
				hosts = hosts_bak;

			nhosts += 2;
			hosts[nhosts - 2] = "::1";
		} else {
			hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *));
			if (hosts_bak == NULL) {
				for (i = 0; i < nhosts; i++)
					free(hosts[i]);

				free(hosts);
				out_of_mem();
			} else {
				nhosts += 1;
				hosts = hosts_bak;
			}
		}
		hosts[nhosts - 1] = "127.0.0.1";
	}

	if (kernel_lockd) {
		if (!kernel_lockd_client) {
			/*
			 * For the case where we have a kernel lockd but it
			 * doesn't provide client locking, we run a cut-down
			 * RPC service on a local-domain socket. The kernel's
			 * RPC server will pass what it can't handle (mainly
			 * client replies) down to us.
			 */
			struct sockaddr_un sun;
			int fd, oldmask;
			SVCXPRT *xprt;

			memset(&sun, 0, sizeof sun);
			sun.sun_family = AF_LOCAL;
			unlink(_PATH_RPCLOCKDSOCK);
			strcpy(sun.sun_path, _PATH_RPCLOCKDSOCK);
			sun.sun_len = SUN_LEN(&sun);
			fd = socket(AF_LOCAL, SOCK_STREAM, 0);
			if (!fd) {
				err(1, "Can't create local lockd socket");
			}
			oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
			if (bind(fd, (struct sockaddr *) &sun, sun.sun_len) < 0) {
				err(1, "Can't bind local lockd socket");
			}
			umask(oldmask);
			if (listen(fd, SOMAXCONN) < 0) {
				err(1, "Can't listen on local lockd socket");
			}
			xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
			if (!xprt) {
				err(1, "Can't create transport for local lockd socket");
			}
			if (!svc_reg(xprt, NLM_PROG, NLM_VERS4, nlm_prog_4, NULL)) {
				err(1, "Can't register service for local lockd socket");
			}
		}

		/*
		 * We need to look up the addresses so that we can
		 * hand uaddrs (ascii encoded address+port strings) to
		 * the kernel.
		 */
		nc_handle = setnetconfig();
		while ((nconf = getnetconfig(nc_handle))) {
			/* We want to listen only on udp6, tcp6, udp, tcp transports */
			if (nconf->nc_flag & NC_VISIBLE) {
				/* Skip if there's no IPv6 support */
				if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
					/* DO NOTHING */
				} else {
					lookup_addresses(nconf);
				}
			}
		}
		endnetconfig(nc_handle);
	} else {
		attempt_cnt = 1;
		sock_fdcnt = 0;
		sock_fd = NULL;
		port_list = NULL;
		port_len = 0;
		nc_handle = setnetconfig();
		while ((nconf = getnetconfig(nc_handle))) {
			/* We want to listen only on udp6, tcp6, udp, tcp transports */
			if (nconf->nc_flag & NC_VISIBLE) {
				/* Skip if there's no IPv6 support */
				if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
					/* DO NOTHING */
				} else {
					ret = create_service(nconf);
					if (ret == 1)
						/* Ignore this call */
						continue;
					if (ret < 0) {
						/*
						 * Failed to bind port, so close
						 * off all sockets created and
						 * try again if the port# was
						 * dynamically assigned via
						 * bind(2).
						 */
						clearout_service();
						if (mallocd_svcport != 0 &&
						    attempt_cnt <
						    GETPORT_MAXTRY) {
							free(svcport_str);
							svcport_str = NULL;
							mallocd_svcport = 0;
						} else {
							errno = EADDRINUSE;
							syslog(LOG_ERR,
							 "bindresvport_sa: %m");
							exit(1);
						}
	
						/*
						 * Start over at the first
						 * service.
						 */
						free(sock_fd);
						sock_fdcnt = 0;
						sock_fd = NULL;
						nc_handle = setnetconfig();
						attempt_cnt++;
					} else if (mallocd_svcport != 0 &&
					    attempt_cnt == GETPORT_MAXTRY) {
						/*
						 * For the last attempt, allow
						 * different port #s for each
						 * nconf by saving the
						 * svcport_str and setting it
						 * back to NULL.
						 */
						port_list = realloc(port_list,
						    (port_len + 1) *
						    sizeof(char *));
						if (port_list == NULL)
							out_of_mem();
						port_list[port_len++] =
						    svcport_str;
						svcport_str = NULL;
						mallocd_svcport = 0;
					}
				}
			}
		}

		/*
		 * Successfully bound the ports, so call complete_service() to
		 * do the rest of the setup on the service(s).
		 */
		sock_fdpos = 0;
		port_pos = 0;
		nc_handle = setnetconfig();
		while ((nconf = getnetconfig(nc_handle))) {
			/* We want to listen only on udp6, tcp6, udp, tcp transports */
			if (nconf->nc_flag & NC_VISIBLE) {
				/* Skip if there's no IPv6 support */
				if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
					/* DO NOTHING */
				} else if (port_list != NULL) {
					if (port_pos >= port_len) {
						syslog(LOG_ERR,
						    "too many port#s");
						exit(1);
					}
					complete_service(nconf,
					    port_list[port_pos++]);
				} else
					complete_service(nconf, svcport_str);
			}
		}
		endnetconfig(nc_handle);
		free(sock_fd);
		if (port_list != NULL) {
			for (port_pos = 0; port_pos < port_len; port_pos++)
				free(port_list[port_pos]);
			free(port_list);
		}
	}

	/*
	 * Note that it is NOT sensible to run this program from inetd - the
	 * protocol assumes that it will run immediately at boot time.
	 */
	if (daemon(0, debug_level > 0)) {
		err(1, "cannot fork");
		/* NOTREACHED */
	}

	openlog("rpc.lockd", 0, LOG_DAEMON);
	if (debug_level)
		syslog(LOG_INFO, "Starting, debug level %d", debug_level);
	else
		syslog(LOG_INFO, "Starting");

	sigalarm.sa_handler = (sig_t) sigalarm_handler;
	sigemptyset(&sigalarm.sa_mask);
	sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */
	sigalarm.sa_flags |= SA_RESTART;
	if (sigaction(SIGALRM, &sigalarm, NULL) != 0) {
		syslog(LOG_WARNING, "sigaction(SIGALRM) failed: %s",
		    strerror(errno));
		exit(1);
	}

	if (kernel_lockd) {
		if (!kernel_lockd_client) {
			init_nsm();
			client_pid = client_request();

			/*
			 * Create a child process to enter the kernel and then
			 * wait for RPCs on our local domain socket.
			 */
			if (!fork())
				nlm_syscall(debug_level, grace_period,
				    naddrs, addrs);
			else
				svc_run();
		} else {
			/*
			 * The kernel lockd implementation provides
			 * both client and server so we don't need to
			 * do anything else.
			 */
			nlm_syscall(debug_level, grace_period, naddrs, addrs);
		}
	} else {
		grace_expired = 0;
		alarm(grace_period);

		init_nsm();

		client_pid = client_request();

		svc_run();		/* Should never return */
	}
	exit(1);
}