Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
int main(int argn, char *argc[])
{
	/*
	 * argc[1] - HostName or Host IP
	 * argc[2] - Server Program Number
	 */

	int test_status = 1;
	int progNum = atoi(argc[2]);
	SVCXPRT *transp = NULL;
	struct netconfig *nconf = NULL;

	nconf = getnetconfigent("udp");
	if (nconf == (struct netconfig *)NULL) {
		printf("err nconf\n");
		exit(1);
	}

	transp = svc_tli_create(RPC_ANYFD, nconf, (struct t_bind *)NULL, 0, 0);
	if (transp == NULL) {
		printf("svc_tli_create() failed\n");
		exit(1);
	}

	test_status = !rpcb_set(progNum, VERSNUM, nconf, &(transp->xp_ltaddr));

	if (!rpcb_unset(progNum, VERSNUM, nconf)) {
		printf("rpcb_unset() failed\n");
		exit(1);
	}

	printf("%d\n", test_status);

	return test_status;
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
/*
 * A common server create routine
 */
static SVCXPRT *
svc_com_create(int fd, u_int sendsize, u_int recvsize, const char *netid)
{
	struct netconfig *nconf;
	SVCXPRT *svc;
	int madefd = FALSE;
	int port;
	struct sockaddr_in sccsin;

	_DIAGASSERT(netid != NULL);

	if ((nconf = __rpc_getconfip(netid)) == NULL) {
		(void) syslog(LOG_ERR, "Could not get %s transport", netid);
		return (NULL);
	}
	if (fd == RPC_ANYSOCK) {
		fd = __rpc_nconf2fd(nconf);
		if (fd == -1) {
			(void) freenetconfigent(nconf);
			(void) syslog(LOG_ERR,
			"svc%s_create: could not open connection", netid);
			return (NULL);
		}
		madefd = TRUE;
	}

	memset(&sccsin, 0, sizeof sccsin);
	sccsin.sin_family = AF_INET;
	(void)bindresvport(fd, &sccsin);

	switch (nconf->nc_semantics) {
	case NC_TPI_COTS:
	case NC_TPI_COTS_ORD:
		if (listen(fd, SOMAXCONN) == -1) {
			(void) syslog(LOG_ERR,
			    "svc%s_create: listen(2) failed: %s",
			    netid, strerror(errno));
			(void) freenetconfigent(nconf);
			goto out;
		}
		break;
	default:
		break;
	}

	svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize);
	(void) freenetconfigent(nconf);
	if (svc == NULL)
		goto out;
	port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
	svc->xp_port = ntohs(port);
	return svc;
out:
	if (madefd)
		(void) close(fd);
	return NULL;
}
Ejemplo n.º 7
0
/*
 * Creates, registers, and returns a (rpc) unix based transporter.
 * Obsoleted by svc_vc_create().
 */
SVCXPRT *
svcunix_create(int sock, u_int sendsize, u_int recvsize, char *path)
{
	struct netconfig *nconf;
	void *localhandle;
	struct sockaddr_un sun;
	struct sockaddr *sa;
	struct t_bind taddr;
	SVCXPRT *xprt;
	int addrlen;

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

	if ((sock = __rpc_nconf2fd(nconf)) < 0)
		goto done;

	memset(&sun, 0, sizeof sun);
	sun.sun_family = AF_LOCAL;
	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
	    sizeof(sun.sun_path))
		goto done;
	sun.sun_len = SUN_LEN(&sun);
	addrlen = sizeof (struct sockaddr_un);
	sa = (struct sockaddr *)&sun;

	if (_bind(sock, sa, addrlen) < 0)
		goto done;

	taddr.addr.len = taddr.addr.maxlen = addrlen;
	taddr.addr.buf = malloc(addrlen);
	if (taddr.addr.buf == NULL)
		goto done;
	memcpy(taddr.addr.buf, sa, addrlen);

	if (nconf->nc_semantics != NC_TPI_CLTS) {
		if (_listen(sock, SOMAXCONN) < 0) {
			free(taddr.addr.buf);
			goto done;
		}
	}

	xprt = (SVCXPRT *)svc_tli_create(sock, nconf, &taddr, sendsize, recvsize);

done:
	endnetconfig(localhandle);
	return(xprt);
}
Ejemplo n.º 8
0
/*
 * Create the amq service for amd (both TCP and UDP)
 */
int
create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp)
{
  /*
   * (partially) create the amq service for amd
   * to be completed further in by caller.
   */

  /* first create the TCP service */
  if (tcp_amqncpp)
    if ((*tcp_amqncpp = getnetconfigent(NC_TCP)) == NULL) {
      plog(XLOG_ERROR, "cannot getnetconfigent for %s", NC_TCP);
      return 1;
    }
  if (tcp_amqpp) {
    *tcp_amqpp = svc_tli_create(RPC_ANYFD, *tcp_amqncpp, NULL, 0, 0);
    if (*tcp_amqpp == NULL) {
      plog(XLOG_ERROR, "cannot create (tcp) tli service for amq");
      return 1;
    }
  }
  if (tcp_soAMQp && tcp_amqpp)
    *tcp_soAMQp = (*tcp_amqpp)->xp_fd;

  /* next create the UDP service */
  if (udp_amqncpp)
    if ((*udp_amqncpp = getnetconfigent(NC_UDP)) == NULL) {
      plog(XLOG_ERROR, "cannot getnetconfigent for %s", NC_UDP);
      return 1;
    }
  if (udp_amqpp) {
    *udp_amqpp = svc_tli_create(RPC_ANYFD, *udp_amqncpp, NULL, 0, 0);
    if (*udp_amqpp == NULL) {
      plog(XLOG_ERROR, "cannot create (udp) tli service for amq");
      return 1;
    }
  }
  if (udp_soAMQp && udp_amqpp)
    *udp_soAMQp = (*udp_amqpp)->xp_fd;

  return 0;			/* all is well */
}
Ejemplo n.º 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;
}
Ejemplo n.º 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;
}
Ejemplo n.º 11
0
//****************************************//
//***           Main Function          ***//
//****************************************//
int main(int argn, char *argc[])
{
	//Server parameter is : argc[1] : Server Program Number
	//					    others arguments depend on server program
	int run_mode = 0;
	int progNum = atoi(argc[1]);
	bool_t rslt;

	SVCXPRT *transp = NULL;
	struct netconfig *nconf;
	struct netbuf svcaddr;

	//Initialization
	svc_unreg(progNum, VERSNUM);

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

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

	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;
}
Ejemplo n.º 12
0
/*
 * A common server create routine
 */
static SVCXPRT *
svc_com_create(int fd, uint_t sendsize, uint_t recvsize, char *netid)
{
	struct netconfig *nconf;
	SVCXPRT *svc;
	int madefd = FALSE;
	int port;
	int res;

	if ((nconf = __rpc_getconfip(netid)) == NULL) {
		(void) syslog(LOG_ERR, "Could not get %s transport", netid);
		return (NULL);
	}
	if (fd == RPC_ANYSOCK) {
		fd = t_open(nconf->nc_device, O_RDWR, NULL);
		if (fd == -1) {
			char errorstr[100];

			__tli_sys_strerror(errorstr, sizeof (errorstr),
					t_errno, errno);
			(void) syslog(LOG_ERR,
			"svc%s_create: could not open connection : %s", netid,
				    errorstr);
			(void) freenetconfigent(nconf);
			return (NULL);
		}
		madefd = TRUE;
	}

	res = __rpc_bindresvport(fd, NULL, &port, 8);
	svc = svc_tli_create(fd, nconf, NULL,
				sendsize, recvsize);
	(void) freenetconfigent(nconf);
	if (svc == NULL) {
		if (madefd)
			(void) t_close(fd);
		return (NULL);
	}
	if (res == -1)
		/* LINTED pointer cast */
		port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
	svc->xp_port = ntohs(port);
	return (svc);
}
Ejemplo n.º 13
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 */
}
Ejemplo n.º 14
0
/*
 * A common server create routine
 */
static SVCXPRT *
svc_com_create(int fd, u_int sendsize, u_int recvsize, char *netid)
{
	struct netconfig *nconf;
	SVCXPRT *svc;
	int madefd = FALSE;
	int port;
	struct sockaddr_in sin;

	if ((nconf = __rpc_getconfip(netid)) == NULL) {
		(void) syslog(LOG_ERR, "Could not get %s transport", netid);
		return (NULL);
	}
	if (fd == RPC_ANYSOCK) {
		fd = __rpc_nconf2fd(nconf);
		if (fd == -1) {
			(void) freenetconfigent(nconf);
			(void) syslog(LOG_ERR,
			"svc%s_create: could not open connection", netid);
			return (NULL);
		}
		madefd = TRUE;
	}

	memset(&sin, 0, sizeof sin);
	sin.sin_family = AF_INET;
	bindresvport(fd, &sin);
	_listen(fd, SOMAXCONN);
	svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize);
	(void) freenetconfigent(nconf);
	if (svc == NULL) {
		if (madefd)
			(void)_close(fd);
		return (NULL);
	}
	port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
	svc->xp_port = ntohs(port);
	return (svc);
}
Ejemplo n.º 15
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);
}
Ejemplo n.º 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;
}
Ejemplo n.º 17
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);
}
Ejemplo n.º 18
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);
}
Ejemplo n.º 19
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);
}
Ejemplo n.º 20
0
int main(int argn, char *argc[])
{
	//Program parameters : argc[1] : HostName or Host IP
	//					   argc[2] : Server Program Number
	//					   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 = 0; //Default test result set to PASS
	int progNum = atoi(argc[2]);
	int i;
	params paramList[NBCASE];
	SVCXPRT *transp = NULL;
	struct netconfig *nconf = NULL;

	//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");
		fprintf(stderr, "err nconf\n");
		printf("5\n");
		exit(1);
	}

	//Test arguments initialization
	paramList[0].bufmin = 0;
	paramList[0].bufmax = 2147483647;
	paramList[1].bufmin = 2147483647;
	paramList[1].bufmax = 0;
	paramList[2].bufmin = 2147483647;
	paramList[2].bufmax = 2147483647;

	//Call tested function using all tests cases
	for (i = 0; i < NBCASE; i++)
	{
		//Debug mode prints
		if (run_mode == 1)
		{
			printf("Test using values : %d ", paramList[i].bufmin);
			printf("%d", paramList[i].bufmax);
			printf("\n");
		}

		//Call function
		transp = svc_tli_create(RPC_ANYFD, nconf,
                            	(struct t_bind *)NULL,
                            	paramList[i].bufmin, paramList[i].bufmax);

		//Check result
		if (transp == NULL)
		{
			//test has failed
			test_status = 1;
			break;
		}
	}

	//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;
}
Ejemplo n.º 21
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);
}
Ejemplo n.º 22
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);
}
Ejemplo n.º 23
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);
}
Ejemplo n.º 24
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);
}
Ejemplo n.º 25
0
/*
 * Create the amq service for amd (both TCP and UDP)
 */
int
create_amq_service(int *udp_soAMQp,
		   SVCXPRT **udp_amqpp,
		   struct netconfig **udp_amqncpp,
		   int *tcp_soAMQp,
		   SVCXPRT **tcp_amqpp,
		   struct netconfig **tcp_amqncpp,
		   u_short preferred_amq_port)
{
  /*
   * (partially) create the amq service for amd
   * to be completed further in by caller.
   * XXX: is this "partially" still true?!  See amd/nfs_start.c. -Erez
   */

  /* first create the TCP service */
  if (tcp_amqncpp)
    if ((*tcp_amqncpp = getnetconfigent(NC_TCP)) == NULL) {
      plog(XLOG_ERROR, "cannot getnetconfigent for %s", NC_TCP);
      return 1;
    }

  if (tcp_amqpp) {
    if (preferred_amq_port > 0) {
      struct t_bind *tbp = NULL;
      int sock;

      plog(XLOG_INFO, "requesting preferred amq TCP port %d", preferred_amq_port);
      sock = bind_preferred_amq_port(preferred_amq_port, *tcp_amqncpp, &tbp);
      if (sock < 0) {
	plog(XLOG_ERROR, "bind_preferred_amq_port failed for TCP port %d: %s",
	     preferred_amq_port, t_errlist[t_errno]);
	return 1;
      }
      *tcp_amqpp = svc_tli_create(sock, *tcp_amqncpp, tbp, 0, 0);
      if (*tcp_amqpp != NULL)
	plog(XLOG_INFO, "amq service bound to TCP port %d", preferred_amq_port);
      t_free((char *) tbp, T_BIND);
    } else {
      /* select any port */
      *tcp_amqpp = svc_tli_create(RPC_ANYFD, *tcp_amqncpp, NULL, 0, 0);
    }
    if (*tcp_amqpp == NULL) {
      plog(XLOG_ERROR, "cannot create (tcp) tli service for amq");
      return 1;
    }
  }
  if (tcp_soAMQp && tcp_amqpp)
    *tcp_soAMQp = (*tcp_amqpp)->xp_fd;

  /* next create the UDP service */
  if (udp_amqncpp)
    if ((*udp_amqncpp = getnetconfigent(NC_UDP)) == NULL) {
      plog(XLOG_ERROR, "cannot getnetconfigent for %s", NC_UDP);
      return 1;
    }
  if (udp_amqpp) {
    if (preferred_amq_port > 0) {
      struct t_bind *tbp = NULL;
      int sock;

      plog(XLOG_INFO, "requesting preferred amq UDP port %d", preferred_amq_port);
      sock = bind_preferred_amq_port(preferred_amq_port, *udp_amqncpp, &tbp);
      if (sock < 0) {
	plog(XLOG_ERROR, "bind_preferred_amq_port failed for UDP port %d: %s",
	     preferred_amq_port, t_errlist[t_errno]);
	return 1;
      }
      *udp_amqpp = svc_tli_create(sock, *udp_amqncpp, tbp, 0, 0);
      if (*udp_amqpp != NULL)
	plog(XLOG_INFO, "amq service bound to UDP port %d", preferred_amq_port);
      t_free((char *) tbp, T_BIND);
    } else {
      /* select any port */
      *udp_amqpp = svc_tli_create(RPC_ANYFD, *udp_amqncpp, NULL, 0, 0);
    }
    if (*udp_amqpp == NULL) {
      plog(XLOG_ERROR, "cannot create (udp) tli service for amq");
      return 1;
    }
  }
  if (udp_soAMQp && udp_amqpp)
    *udp_soAMQp = (*udp_amqpp)->xp_fd;

  return 0;			/* all is well */
}
Ejemplo n.º 26
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);
}
Ejemplo n.º 27
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);
}
Ejemplo n.º 28
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 */
}
Ejemplo n.º 29
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);
}
Ejemplo n.º 30
0
static int getprognum(long *prognum, SVCXPRT **xprt, char *fd_str,
			char *prog_str, long vers, char *tp_type)
{
	static ulong_t start = 0x40000000;
	int fd;
#ifdef TDRPC
	ushort_t port;
	int proto;
#else
	struct netconfig *nc;
	struct netbuf *nb;
#endif

	/* If prognum specified, use it instead of transient hassel. */
	if (*prognum) {
		*xprt = NULL;
		sprintf(fd_str, "-1"); /* have child close all fds */
		sprintf(prog_str, "%u", *prognum);
		return (TRUE);
	}

	/*
	 * Transient hassel:
	 *	- parent must create mapping since someone else could
	 *	  steal the transient prognum before child created it
	 * 	- pass the child the fd to use for service
	 * 	- close the fd (after exec), free xprt, leave mapping intact
	 */
#ifdef TDRPC
	if (strcmp(tp_type, "udp") != 0) {
		proto = IPPROTO_UDP;
		*xprt = svcudp_bufcreate(RPC_ANYSOCK, 0, 0);
	} else {
		proto = IPPROTO_TCP;
		*xprt = svctcp_create(RPC_ANYSOCK, 0, 0);
	}
	if (*xprt == NULL)
		return (FALSE);
	port = (*xprt)->xp_port;
	fd = (*xprt)->xp_sock;
	while (!pmap_set(start, vers, proto, port))
		start++;
#else
	/* tp_type is legit: users choice or a loopback netid */
	if ((nc = getnetconfigent(tp_type)) == NULL)
		return (FALSE);
	if ((*xprt = svc_tli_create(RPC_ANYFD, nc, NULL, 0, 0)) == NULL) {
		freenetconfigent(nc);
		return (FALSE);
	}
	nb = &(*xprt)->xp_ltaddr;
	fd = (*xprt)->xp_fd;
	while (!rpcb_set(start, vers, nc, nb))
		start++;
	freenetconfigent(nc);
#endif

	*prognum = start;
	sprintf(fd_str, "%u", fd);
	sprintf(prog_str, "%u", *prognum);

	return (TRUE);
}