Exemple #1
0
/*
 * Remove the mapping between program, version and port.
 * Calls the pmap service remotely to do the un-mapping.
 */
bool_t
pmap_unset(u_long program, u_long version)
{
	struct netconfig *nconf;
	bool_t udp_rslt = FALSE;
	bool_t tcp_rslt = FALSE;

	nconf = __rpc_getconfip("udp");
	if (nconf != NULL) {
		udp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
		    nconf);
		freenetconfigent(nconf);
	}
	nconf = __rpc_getconfip("tcp");
	if (nconf != NULL) {
		tcp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
		    nconf);
		freenetconfigent(nconf);
	}
	/*
	 * XXX: The call may still succeed even if only one of the
	 * calls succeeded.  This was the best that could be
	 * done for backward compatibility.
	 */
	return (tcp_rslt || udp_rslt);
}
Exemple #2
0
bool_t
pmap_set(u_long program, u_long version, int protocol, int port)
{
	bool_t rslt;
	struct netbuf *na;
	struct netconfig *nconf;
	char buf[32];

	if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) {
		return (FALSE);
	}
	nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp");
	if (nconf == NULL) {
		return (FALSE);
	}
	snprintf(buf, sizeof buf, "0.0.0.0.%d.%d", 
	    (((u_int32_t)port) >> 8) & 0xff, port & 0xff);
	na = uaddr2taddr(nconf, buf);
	if (na == NULL) {
		freenetconfigent(nconf);
		return (FALSE);
	}
	rslt = rpcb_set((rpcprog_t)program, (rpcvers_t)version, nconf, na);
	free(na);
	freenetconfigent(nconf);
	return (rslt);
}
Exemple #3
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;
}
Exemple #4
0
/*
 * Get the client's hostname from the transport handle
 * If the name is not available then return "(anon)".
 */
void
getclientsnames(SVCXPRT *transp, struct netbuf **nbuf,
    struct nd_hostservlist **serv)
{
	struct netconfig *nconf;
	char tmp[MAXIPADDRLEN];
	char *host = NULL;

	nconf = getnetconfigent(transp->xp_netid);
	if (nconf == NULL) {
		syslog(LOG_ERR, "%s: getnetconfigent failed",
			transp->xp_netid);
		*serv = anon_client(host);
		return;
	}

	*nbuf = svc_getrpccaller(transp);
	if (*nbuf == NULL) {
		freenetconfigent(nconf);
		*serv = anon_client(host);
		return;
	}

	/*
	 * Use the this API instead of the netdir_getbyaddr()
	 * to avoid service lookup.
	 */
	if (__netdir_getbyaddr_nosrv(nconf, serv, *nbuf)) {
		host = &tmp[0];
		if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
			struct sockaddr_in *sa;

			/* LINTED pointer alignment */
			sa = (struct sockaddr_in *)((*nbuf)->buf);
			(void) inet_ntoa_r(sa->sin_addr, tmp);
			*serv =	anon_client(host);
			freenetconfigent(nconf);
			return;
		} else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) {
			struct sockaddr_in6 *sa;

			/* LINTED pointer alignment */
			sa = (struct sockaddr_in6 *)((*nbuf)->buf);
			(void) inet_ntop(AF_INET6, sa->sin6_addr.s6_addr,
					tmp, INET6_ADDRSTRLEN);
			*serv =	anon_client(host);
			freenetconfigent(nconf);
			return;
		}
		freenetconfigent(nconf);
		*serv = anon_client(host);
		return;
	}
	freenetconfigent(nconf);
}
Exemple #5
0
/* Unregister all the registrations done by register_rpc_service */
void
unregister_rpc_service(const char *fmri, const rpc_info_t *rpc)
{
	int			ver;
	struct netconfig	*nconf;

	debug_msg("Entering unregister_rpc_service, instance: %s", fmri);

	if ((nconf = getnetconfigent(rpc->netid)) == NULL) {
		/*
		 * Don't output an error message if getnetconfigent() fails for
		 * a v6 netid when an IPv6 interface isn't configured.
		 */
		if (!(is_v6_netid(rpc->netid) && !can_use_af(AF_INET6))) {
			error_msg(gettext(
			    "Failed to lookup netid '%s' for instance %s: %s"),
			    rpc->netid, fmri, nc_sperror());
		}
		return;
	}

	for (ver = rpc->lowver; ver <= rpc->highver; ver++)
		(void) rpcb_unset(rpc->prognum, ver, nconf);

	freenetconfigent(nconf);
}
Exemple #6
0
int
add_bndlist(struct netconfig *nconf, struct netbuf *baddr)
{
	struct fdlist *fdl;
	struct netconfig *newnconf;

	newnconf = getnetconfigent(nconf->nc_netid);
	if (newnconf == NULL)
		return (-1);
	fdl = (struct fdlist *)malloc((u_int)sizeof (struct fdlist));
	if (fdl == NULL) {
		freenetconfigent(newnconf);
		syslog(LOG_ERR, "no memory!");
		return (-1);
	}
	fdl->nconf = newnconf;
	fdl->next = NULL;
	if (fdhead == NULL) {
		fdhead = fdl;
		fdtail = fdl;
	} else {
		fdtail->next = fdl;
		fdtail = fdl;
	}
	/* XXX no bound checking for now */
	fdl->check_binding = FALSE;

	return 0;
}
struct servent *
getservbyport_r(int port, const char *proto, struct servent *result,
	char *buffer, int buflen)
{
	struct netconfig *nconf;
	struct	nss_netdirbyaddr_in nssin;
	union	nss_netdirbyaddr_out nssout;
	int neterr;

	if ((nconf = __rpc_getconfip("udp")) == NULL &&
	    (nconf = __rpc_getconfip("tcp")) == NULL) {
		return ((struct servent *)NULL);
	}
	nssin.op_t = NSS_SERV;
	nssin.arg.nss.serv.port = port;
	nssin.arg.nss.serv.proto = proto;
	nssin.arg.nss.serv.buf = buffer;
	nssin.arg.nss.serv.buflen = buflen;

	nssout.nss.serv = result;

	/*
	 * We pass in nconf and let the implementation of this long-named func
	 * decide whether to use the switch based on nc_nlookups.
	 */
	neterr = _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout);

	(void) freenetconfigent(nconf);
	if (neterr != ND_OK) {
		return ((struct servent *)NULL);
	}
	return (nssout.nss.serv);
}
Exemple #8
0
/*
 * Create the client des authentication object. Obsoleted by
 * authdes_seccreate().
 */
AUTH *
authdes_create(char *servername, uint_t window, struct sockaddr_in *syncaddr,
	des_block *ckey)
{
	char *hostname = NULL;

	if (syncaddr) {
		/*
		 * Change addr to hostname, because that is the way
		 * new interface takes it.
		 */
		struct netconfig *nconf;
		struct netbuf nb_syncaddr;
		struct nd_hostservlist *hlist;
		AUTH *nauth;
		int fd;
		struct t_info tinfo;

		if ((nconf = __rpc_getconfip("udp")) == NULL &&
		    (nconf = __rpc_getconfip("tcp")) == NULL)
			goto fallback;

		/* Transform sockaddr_in to netbuf */
		if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) {
			(void) freenetconfigent(nconf);
			goto fallback;
		}
		(void) t_close(fd);
		nb_syncaddr.maxlen = nb_syncaddr.len =
			__rpc_get_a_size(tinfo.addr);
		nb_syncaddr.buf = (char *)syncaddr;
		if (netdir_getbyaddr(nconf, &hlist, &nb_syncaddr)) {
			(void) freenetconfigent(nconf);
			goto fallback;
		}
		if (hlist && hlist->h_cnt > 0 && hlist->h_hostservs)
			hostname = hlist->h_hostservs->h_host;
		nauth = authdes_seccreate(servername, window, hostname, ckey);
		(void) netdir_free((char *)hlist, ND_HOSTSERVLIST);
		(void) freenetconfigent(nconf);
		return (nauth);
	}
fallback:
	return (authdes_seccreate(servername, window, hostname, ckey));
}
Exemple #9
0
/*
 * Registers with rpcbind the program number with all versions, from low to
 * high, with the netid, all specified in 'rpc'. If registration fails,
 * returns -1, else 0.
 */
int
register_rpc_service(const char *fmri, const rpc_info_t *rpc)
{
	struct netconfig	*nconf;
	int			ver;

	debug_msg("Entering register_rpc_service: instance: %s", fmri);

	if ((nconf = getnetconfigent(rpc->netid)) == NULL) {
		/*
		 * Check whether getnetconfigent() failed as a result of
		 * having no IPv6 interfaces configured for a v6 netid, or
		 * as a result of a 'real' error, and output an appropriate
		 * message with an appropriate severity.
		 */
		if (is_v6_netid(rpc->netid) && !can_use_af(AF_INET6)) {
			warn_msg(gettext(
			    "Couldn't register netid %s for RPC instance %s "
			    "because no IPv6 interfaces are plumbed"),
			    rpc->netid, fmri);
		} else {
			error_msg(gettext(
			    "Failed to lookup netid '%s' for instance %s: %s"),
			    rpc->netid, fmri, nc_sperror());
		}
		return (-1);
	}

	for (ver = rpc->lowver; ver <= rpc->highver; ver++) {
		if (!rpcb_set(rpc->prognum, ver, nconf, &(rpc->netbuf))) {
			error_msg(gettext("Failed to register version %d "
			    "of RPC service instance %s, netid %s"), ver,
			    fmri, rpc->netid);

			for (ver--; ver >= rpc->lowver; ver--)
				(void) rpcb_unset(rpc->prognum, ver, nconf);

			freenetconfigent(nconf);
			return (-1);
		}
	}

	freenetconfigent(nconf);
	return (0);
}
Exemple #10
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);
}
Exemple #11
0
/*
 * Find netconfig info for TCP/UDP device, and fill in the knetconfig
 * structure.  If in_ncp is not NULL, use that instead of defaulting
 * to a TCP/UDP service.  If in_ncp is NULL, then use the service type
 * specified in nc_protoname (which may be either "tcp" or "udp").  If
 * nc_protoname is NULL, default to UDP.
 */
int
get_knetconfig(struct knetconfig **kncpp, struct netconfig *in_ncp, char *nc_protoname)
{
  struct netconfig *ncp = NULL;
  struct stat statbuf;

  if (in_ncp)
    ncp = in_ncp;
  else {
    if (nc_protoname)
      ncp = getnetconfigent(nc_protoname);
    else
      ncp = getnetconfigent(NC_UDP);
  }
  if (!ncp)
    return -2;

  *kncpp = (struct knetconfig *) xzalloc(sizeof(struct knetconfig));
  if (*kncpp == (struct knetconfig *) NULL) {
    if (!in_ncp)
      freenetconfigent(ncp);
    return -3;
  }
  (*kncpp)->knc_semantics = ncp->nc_semantics;
  (*kncpp)->knc_protofmly = strdup(ncp->nc_protofmly);
  (*kncpp)->knc_proto = strdup(ncp->nc_proto);

  if (stat(ncp->nc_device, &statbuf) < 0) {
    plog(XLOG_ERROR, "could not stat() %s: %m", ncp->nc_device);
    XFREE(*kncpp);
    *kncpp = NULL;
    if (!in_ncp)
      freenetconfigent(ncp);
    return -3;			/* amd will end (free not needed) */
  }
  (*kncpp)->knc_rdev = (dev_t) statbuf.st_rdev;
  if (!in_ncp) {		/* free only if argument not passed */
    freenetconfigent(ncp);
    ncp = NULL;
  }
  return 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);
}
Exemple #13
0
static PyObject * portmap_unset(PyObject *self, PyObject *args)
{
	unsigned long program, version;
	struct netconfig *nconf;
	
	if (!PyArg_ParseTuple(args, "kk:unset",
			      &program, &version))
		return NULL;

	pmap_unset(program, version);
	nconf = getnetconfigent("udp6");
	if (nconf != NULL) {
		rpcb_unset((rpcprog_t)program, (rpcvers_t)version, nconf);
		freenetconfigent(nconf);
	}
	nconf = getnetconfigent("tcp6");
	if (nconf != NULL) {
		rpcb_unset((rpcprog_t)program, (rpcvers_t)version, nconf);
		freenetconfigent(nconf);
	}
	
	Py_INCREF(Py_None);
	return Py_None;
}
Exemple #14
0
static int
tryconf(struct conf *cfg, int t, int reregister)
{
	struct addrinfo hints;
	int ecode;

	memset(&hints, 0, sizeof hints);
	hints.ai_flags = AI_PASSIVE;
	hints.ai_family = cfg_family[t];
	hints.ai_socktype = cfg_socktype[t];
	hints.ai_protocol = cfg_protocol[t];

	ecode = getaddrinfo(NULL, "nfs", &hints, &cfg->ai);
	if (ecode != 0) {
		logit(LOG_ERR, "getaddrinfo %s: %s", cfg_netconf[t],
		    gai_strerror(ecode));
		return -1;
	}

	cfg->nc = getnetconfigent(cfg_netconf[t]);

	if (cfg->nc == NULL) {
		logit(LOG_ERR, "getnetconfigent %s failed: %s",
		    cfg_netconf[t], strerror(errno));
		goto out;
	}

	cfg->nb.buf = cfg->ai->ai_addr;
	cfg->nb.len = cfg->nb.maxlen = cfg->ai->ai_addrlen;
	if (reregister)
		if (!rpcb_set(RPCPROG_NFS, 2, cfg->nc, &cfg->nb)) {
			logit(LOG_ERR, "rpcb_set %s failed", cfg_netconf[t]);
			goto out1;
		}
	return 0;
out1:
	freenetconfigent(cfg->nc);
	cfg->nc = NULL;
out:
	freeaddrinfo(cfg->ai);
	cfg->ai = NULL;
	return -1;
}
Exemple #15
0
/*
 * If 'proto' is a valid netid,  and no memory allocations fail, returns a
 * pointer to an allocated and initialized rpc_info_t, else NULL.
 */
static rpc_info_t *
create_rpc_info(const char *proto, int pnum, int low_ver, int high_ver)
{
	struct netconfig	*nconf;
	rpc_info_t		*ret;

	if ((ret = calloc(1, sizeof (rpc_info_t))) == NULL)
		return (NULL);

	ret->netbuf.maxlen = sizeof (struct sockaddr_storage);
	if ((ret->netbuf.buf = malloc(ret->netbuf.maxlen)) == NULL) {
		free(ret);
		return (NULL);
	}

	ret->prognum = pnum;
	ret->lowver = low_ver;
	ret->highver = high_ver;

	if ((ret->netid = strdup(proto)) == NULL) {
		destroy_rpc_info(ret);
		return (NULL);
	}

	/*
	 * Determine whether this is a loopback transport. If getnetconfigent()
	 * fails, we check to see whether it was the result of a v6 proto
	 * being specified and no IPv6 interface was configured on the system;
	 * if this holds, we know it must not be a loopback transport, else
	 * getnetconfigent() must be miss-behaving, so return an error.
	 */
	if ((nconf = getnetconfigent(proto)) != NULL) {
		if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
			ret->is_loopback = B_TRUE;
		freenetconfigent(nconf);
	} else if (!v6_proto(proto)) {
		destroy_rpc_info(ret);
		return (NULL);
	}

	return (ret);
}
Exemple #16
0
/* netconfig(3) fallback approach */
static char *
__so_socket_path_netconfig(int domain, int type, int protocol)
{
	int semantics1 = 0, semantics2 = 0;
	const char *proto = NULL;
	const char *family = NULL;
	struct netconfig *nc;
	char *result = NULL;

	if (__so_map_socket_to_netconfig(domain, type, protocol,
					 &semantics1, &semantics2, &family, &proto) == -1)
		return (NULL);

	if ((nc = getnetconfigent(proto)) != NULL) {
		if ((result = strdup(nc->nc_device)) == NULL)
			nc_error = NC_NOMEM;
		freenetconfigent(nc);
	}
	if (!result) {
		nc_perror("socklib");
	}
	return (result);
}
Exemple #17
0
/*
 * A common clnt create routine
 */
static CLIENT *
clnt_com_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers,
	int *sockp, uint_t sendsz, uint_t recvsz, char *tp)
{
	CLIENT *cl;
	int madefd = FALSE;
	int fd = *sockp;
	struct t_info tinfo;
	struct netconfig *nconf;
	int port;
	struct netbuf bindaddr;
	bool_t locked = TRUE;

	(void) mutex_lock(&rpcsoc_lock);
	if ((nconf = __rpc_getconfip(tp)) == NULL) {
		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
		(void) mutex_unlock(&rpcsoc_lock);
		return (NULL);
	}
	if (fd == RPC_ANYSOCK) {
		fd = t_open(nconf->nc_device, O_RDWR, &tinfo);
		if (fd == -1)
			goto syserror;
		RPC_RAISEFD(fd);
		madefd = TRUE;
	} else {
		if (t_getinfo(fd, &tinfo) == -1)
			goto syserror;
	}

	if (raddr->sin_port == 0) {
		uint_t proto;
		ushort_t sport;

		/* pmap_getport is recursive */
		(void) mutex_unlock(&rpcsoc_lock);
		proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
		sport = pmap_getport(raddr, prog, vers, proto);
		if (sport == 0) {
			locked = FALSE;
			goto err;
		}
		raddr->sin_port = htons(sport);
		/* pmap_getport is recursive */
		(void) mutex_lock(&rpcsoc_lock);
	}

	/* Transform sockaddr_in to netbuf */
	bindaddr.maxlen = bindaddr.len =  __rpc_get_a_size(tinfo.addr);
	bindaddr.buf = (char *)raddr;

	(void) __rpc_bindresvport(fd, NULL, &port, 0);
	cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
				sendsz, recvsz);
	if (cl) {
		if (madefd == TRUE) {
			/*
			 * The fd should be closed while destroying the handle.
			 */
			(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
			*sockp = fd;
		}
		(void) freenetconfigent(nconf);
		(void) mutex_unlock(&rpcsoc_lock);
		return (cl);
	}
	goto err;

syserror:
	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
	rpc_createerr.cf_error.re_errno = errno;
	rpc_createerr.cf_error.re_terrno = t_errno;

err:	if (madefd == TRUE)
		(void) t_close(fd);
	(void) freenetconfigent(nconf);
	if (locked == TRUE)
		(void) mutex_unlock(&rpcsoc_lock);
	return (NULL);
}
Exemple #18
0
/*
 * This is the IPv6 interface for "gethostbyaddr".
 */
struct hostent *
getipnodebyaddr(const void *src, size_t len, int type, int *error_num)
{
	struct in6_addr *addr6 = 0;
	struct in_addr *addr4 = 0;
	nss_XbyY_buf_t *buf = 0;
	nss_XbyY_buf_t *res = 0;
	struct netconfig *nconf;
	struct hostent *hp = 0;
	struct	nss_netdirbyaddr_in nssin;
	union	nss_netdirbyaddr_out nssout;
	int neterr;
	char tmpbuf[64];

	if (type == AF_INET6) {
		if ((addr6 = (struct in6_addr *)src) == NULL) {
			*error_num = HOST_NOT_FOUND;
			return (NULL);
		}
	} else if (type == AF_INET) {
		if ((addr4 = (struct in_addr *)src) == NULL) {
			*error_num = HOST_NOT_FOUND;
			return (NULL);
		}
	} else {
		*error_num = HOST_NOT_FOUND;
		return (NULL);
	}
	/*
	 * Specific case: query for "::"
	 */
	if (type == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(addr6)) {
		*error_num = HOST_NOT_FOUND;
		return (NULL);
	}
	/*
	 * Step 1: IPv4-mapped address  or IPv4 Compat
	 */
	if ((type == AF_INET6 && len == 16) &&
	    ((IN6_IS_ADDR_V4MAPPED(addr6)) ||
	    (IN6_IS_ADDR_V4COMPAT(addr6)))) {
		if ((buf = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) {
			*error_num = NO_RECOVERY;
			return (NULL);
		}
		if ((nconf = __rpc_getconfip("udp")) == NULL &&
		    (nconf = __rpc_getconfip("tcp")) == NULL) {
			*error_num = NO_RECOVERY;
			__IPv6_cleanup(buf);
			return (NULL);
		}
		nssin.op_t = NSS_HOST6;
		if (IN6_IS_ADDR_V4COMPAT(addr6)) {
			(void) memcpy(tmpbuf, addr6, sizeof (*addr6));
			tmpbuf[10] = 0xffU;
			tmpbuf[11] = 0xffU;
			nssin.arg.nss.host.addr = (const char *)tmpbuf;
		} else {
			nssin.arg.nss.host.addr = (const char *)addr6;
		}
		nssin.arg.nss.host.len = sizeof (struct in6_addr);
		nssin.arg.nss.host.type = AF_INET6;
		nssin.arg.nss.host.buf = buf->buffer;
		nssin.arg.nss.host.buflen = buf->buflen;

		nssout.nss.host.hent = buf->result;
		nssout.nss.host.herrno_p = error_num;
		/*
		 * We pass in nconf and let the implementation of the
		 * long-named func decide whether to use the switch based on
		 * nc_nlookups.
		 */
		neterr =
		    _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout);

		(void) freenetconfigent(nconf);
		if (neterr != ND_OK) {
			/* Failover case, try hosts db for v4 address */
			if (!gethostbyaddr_r(((char *)addr6) + 12,
			    sizeof (in_addr_t), AF_INET, buf->result,
			    buf->buffer, buf->buflen, error_num)) {
				__IPv6_cleanup(buf);
				return (NULL);
			}
			/* Found one, now format it into mapped/compat addr */
			if ((res = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) {
				__IPv6_cleanup(buf);
				*error_num = NO_RECOVERY;
				return (NULL);
			}
			/* Convert IPv4 to mapped/compat address w/name */
			hp = res->result;
			(void) __mapv4tov6(buf->result, 0, res,
			    IN6_IS_ADDR_V4MAPPED(addr6));
			__IPv6_cleanup(buf);
			free(res);
			return (hp);
		}
		/*
		 * At this point, we'll have a v4mapped hostent. If that's
		 * what was passed in, just return. If the request was a compat,
		 * twiggle the two bytes to make the mapped address a compat.
		 */
		hp = buf->result;
		if (IN6_IS_ADDR_V4COMPAT(addr6)) {
			/* LINTED pointer cast */
			addr6 = (struct in6_addr *)hp->h_addr_list[0];
			addr6->s6_addr[10] = 0;
			addr6->s6_addr[11] = 0;
		}
		free(buf);
		return (hp);
	}
	/*
	 * Step 2: AF_INET, v4 lookup. Since we're going to search the
	 * ipnodes (v6) path first, we need to treat this as a v4mapped
	 * address. nscd(1m) caches v4 from ipnodes as mapped v6's. The
	 * switch backend knows to lookup v4's (not v4mapped) from the
	 * name services.
	 */
	if (type == AF_INET) {
		struct in6_addr v4mapbuf;
		addr6 = &v4mapbuf;

		IN6_INADDR_TO_V4MAPPED(addr4, addr6);
		if ((nconf = __rpc_getconfip("udp")) == NULL &&
		    (nconf = __rpc_getconfip("tcp")) == NULL) {
			*error_num = NO_RECOVERY;
			return (NULL);
		}
		if ((buf = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) {
			*error_num = NO_RECOVERY;
			freenetconfigent(nconf);
			return (NULL);
		}
		nssin.op_t = NSS_HOST6;
		nssin.arg.nss.host.addr = (const char *)addr6;
		nssin.arg.nss.host.len = sizeof (struct in6_addr);
		nssin.arg.nss.host.type = AF_INET6;
		nssin.arg.nss.host.buf = buf->buffer;
		nssin.arg.nss.host.buflen = buf->buflen;

		nssout.nss.host.hent = buf->result;
		nssout.nss.host.herrno_p = error_num;
		/*
		 * We pass in nconf and let the implementation of the
		 * long-named func decide whether to use the switch based on
		 * nc_nlookups.
		 */
		neterr =
		    _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout);

		(void) freenetconfigent(nconf);
		if (neterr != ND_OK) {
			/* Failover case, try hosts db for v4 address */
			hp = buf->result;
			if (!gethostbyaddr_r(src, len, type, buf->result,
			    buf->buffer, buf->buflen, error_num)) {
				__IPv6_cleanup(buf);
				return (NULL);
			}
			free(buf);
			return (hp);
		}
		if ((hp = __mappedtov4(buf->result, error_num)) == NULL) {
			__IPv6_cleanup(buf);
			return (NULL);
		}
		__IPv6_cleanup(buf);
		return (hp);
	}
	/*
	 * Step 3: AF_INET6, plain vanilla v6 getipnodebyaddr() call.
	 */
	if (type == AF_INET6) {
		if ((nconf = __rpc_getconfip("udp")) == NULL &&
		    (nconf = __rpc_getconfip("tcp")) == NULL) {
			*error_num = NO_RECOVERY;
			return (NULL);
		}
		if ((buf = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == 0) {
			*error_num = NO_RECOVERY;
			freenetconfigent(nconf);
			return (NULL);
		}
		nssin.op_t = NSS_HOST6;
		nssin.arg.nss.host.addr = (const char *)addr6;
		nssin.arg.nss.host.len = len;
		nssin.arg.nss.host.type = type;
		nssin.arg.nss.host.buf = buf->buffer;
		nssin.arg.nss.host.buflen = buf->buflen;

		nssout.nss.host.hent = buf->result;
		nssout.nss.host.herrno_p = error_num;
		/*
		 * We pass in nconf and let the implementation of the
		 * long-named func decide whether to use the switch based on
		 * nc_nlookups.
		 */
		neterr =
		    _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout);

		(void) freenetconfigent(nconf);
		if (neterr != ND_OK) {
			__IPv6_cleanup(buf);
			return (NULL);
		}
		free(buf);
		return (nssout.nss.host.hent);
	}
	/*
	 * If we got here, unknown type.
	 */
	*error_num = HOST_NOT_FOUND;
	return (NULL);
}
Exemple #19
0
struct hostent *
getipnodebyname(const char *name, int af, int flags, int *error_num)
{
	struct hostent		*hp = NULL;
	nss_XbyY_buf_t		*buf4 = NULL;
	nss_XbyY_buf_t		*buf6 = NULL;
	struct netconfig	*nconf;
	struct nss_netdirbyname_in	nssin;
	union nss_netdirbyname_out	nssout;
	int			ret;
	uint_t			ipnode_bits;

	if ((nconf = __rpc_getconfip("udp")) == NULL &&
	    (nconf = __rpc_getconfip("tcp")) == NULL) {
		*error_num = NO_RECOVERY;
		return (NULL);
	}

	ipnode_bits = getipnodebyname_processflags(name, af, flags);

	/* Make sure we have something to look up. */
	if (!(ipnode_bits & (IPNODE_WANTIPV6 | IPNODE_WANTIPV4))) {
		*error_num = HOST_NOT_FOUND;
		goto cleanup;
	}

	/*
	 * Perform the requested lookups.  We always look through
	 * ipnodes first for both IPv4 and IPv6 addresses.  Depending
	 * on what was returned and what was needed, we either filter
	 * out the garbage, or ask for more using hosts.
	 */
	if (ipnode_bits & IPNODE_LOOKUPIPNODES) {
		if ((buf6 = __IPv6_alloc(NSS_BUFLEN_IPNODES)) == NULL) {
			*error_num = NO_RECOVERY;
			goto cleanup;
		}
		nssin.op_t = NSS_HOST6;
		nssin.arg.nss.host6.name = name;
		nssin.arg.nss.host6.buf = buf6->buffer;
		nssin.arg.nss.host6.buflen = buf6->buflen;
		nssin.arg.nss.host6.af_family = af;
		nssin.arg.nss.host6.flags = flags;
		nssout.nss.host.hent = buf6->result;
		nssout.nss.host.herrno_p = error_num;
		ret = _get_hostserv_inetnetdir_byname(nconf, &nssin, &nssout);
		if (ret != ND_OK) {
			__IPv6_cleanup(buf6);
			buf6 = NULL;
		} else if (ipnode_bits & IPNODE_WANTIPV4) {
			/*
			 * buf6 may have all that we need if we either
			 * only wanted IPv4 addresses if there were no
			 * IPv6 addresses returned, or if there are
			 * IPv4-mapped addresses in buf6.  If either
			 * of these are true, then there's no need to
			 * look in hosts.
			 */
			if (ipnode_bits & IPNODE_IPV4IFNOIPV6 ||
			    __find_mapped(buf6->result, 0) != 0) {
				ipnode_bits &= ~IPNODE_LOOKUPHOSTS;
			} else if (!(ipnode_bits & IPNODE_WANTIPV6)) {
				/*
				 * If all we're looking for are IPv4
				 * addresses and there are none in
				 * buf6 then buf6 is now useless.
				 */
				__IPv6_cleanup(buf6);
				buf6 = NULL;
			}
		}
	}
	if (ipnode_bits & IPNODE_LOOKUPHOSTS) {
		if ((buf4 = __IPv6_alloc(NSS_BUFLEN_HOSTS)) == NULL) {
			*error_num = NO_RECOVERY;
			goto cleanup;
		}
		nssin.op_t = NSS_HOST;
		nssin.arg.nss.host.name = name;
		nssin.arg.nss.host.buf = buf4->buffer;
		nssin.arg.nss.host.buflen = buf4->buflen;
		nssout.nss.host.hent = buf4->result;
		nssout.nss.host.herrno_p = error_num;
		ret = _get_hostserv_inetnetdir_byname(nconf, &nssin, &nssout);
		if (ret != ND_OK) {
			__IPv6_cleanup(buf4);
			buf4 = NULL;
		}
	}

	if (buf6 == NULL && buf4 == NULL) {
		*error_num = HOST_NOT_FOUND;
		goto cleanup;
	}

	/* Extract the appropriate addresses from the returned buffer(s). */
	switch (af) {
	case AF_INET6: {
		if (buf4 != NULL) {
			nss_XbyY_buf_t *mergebuf;

			/*
			 * The IPv4 results we have need to be
			 * converted to IPv4-mapped addresses,
			 * conditionally merged with the IPv6
			 * results, and the end result needs to be
			 * re-ordered.
			 */
			mergebuf = __IPv6_alloc(NSS_BUFLEN_IPNODES);
			if (mergebuf == NULL) {
				*error_num = NO_RECOVERY;
				goto cleanup;
			}
			hp = __mapv4tov6(buf4->result,
			    ((buf6 != NULL) ? buf6->result : NULL),
			    mergebuf, 1);
			if (hp != NULL)
				order_haddrlist_af(AF_INET6, hp->h_addr_list);
			else
				*error_num = NO_RECOVERY;
			free(mergebuf);
		}

		if (buf4 == NULL && buf6 != NULL) {
			hp = buf6->result;

			/*
			 * We have what we need in buf6, but we may need
			 * to filter out some addresses depending on what
			 * is being asked for.
			 */
			if (!(ipnode_bits & IPNODE_WANTIPV4))
				hp = __filter_addresses(AF_INET, buf6->result);
			else if (!(ipnode_bits & IPNODE_WANTIPV6))
				hp = __filter_addresses(AF_INET6, buf6->result);

			/*
			 * We've been asked to unmap v4 addresses. This
			 * situation implies IPNODE_WANTIPV4 and
			 * !IPNODE_WANTIPV6.
			 */
			if (hp != NULL && (ipnode_bits & IPNODE_UNMAP)) {
				/*
				 * Just set hp to a new value, cleanup: will
				 * free the old one
				 */
				hp = __mappedtov4(hp, error_num);
			} else if (hp == NULL)
				*error_num = NO_ADDRESS;
		}

		break;
	}

	case AF_INET:
		/* We could have results in buf6 or buf4, not both */
		if (buf6 != NULL) {
			/*
			 * Extract the IPv4-mapped addresses from buf6
			 * into hp.
			 */
			hp = __mappedtov4(buf6->result, error_num);
		} else {
			/* We have what we need in buf4. */
			hp = buf4->result;
			if (ipnode_bits & IPNODE_LITERAL) {
				/*
				 * There is a special case here for literal
				 * IPv4 address strings.  The hosts
				 * front-end sets h_aliases to a one
				 * element array containing a single NULL
				 * pointer (in ndaddr2hent()), while
				 * getipnodebyname() requires h_aliases to
				 * be a NULL pointer itself.  We're not
				 * going to change the front-end since it
				 * needs to remain backward compatible for
				 * gethostbyname() and friends.  Just set
				 * h_aliases to NULL here instead.
				 */
				hp->h_aliases = NULL;
			}
		}

		break;

	default:
		break;
	}

cleanup:
	/*
	 * Free the memory we allocated, but make sure we don't free
	 * the memory we're returning to the caller.
	 */
	if (buf6 != NULL) {
		if (buf6->result == hp)
			buf6->result = NULL;
		__IPv6_cleanup(buf6);
	}
	if (buf4 != NULL) {
		if (buf4->result == hp)
			buf4->result = NULL;
		__IPv6_cleanup(buf4);
	}
	(void) freenetconfigent(nconf);

	return (hp);
}
Exemple #20
0
/*
 * A common clnt create routine
 */
static CLIENT *
clnt_com_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers,
	int *sockp, u_int sendsz, u_int recvsz, const char *tp)
{
	CLIENT *cl;
	int madefd = FALSE;
	int fd;
	struct netconfig *nconf;
	struct netbuf bindaddr;

	_DIAGASSERT(raddr != NULL);
	_DIAGASSERT(sockp != NULL);
	_DIAGASSERT(tp != NULL);

	fd = *sockp;

	mutex_lock(&rpcsoc_lock);
	if ((nconf = __rpc_getconfip(tp)) == NULL) {
		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
		mutex_unlock(&rpcsoc_lock);
		return (NULL);
	}
	if (fd == RPC_ANYSOCK) {
		fd = __rpc_nconf2fd(nconf);
		if (fd == -1)
			goto syserror;
		madefd = TRUE;
	}

	if (raddr->sin_port == 0) {
		u_int proto;
		u_short sport;

		mutex_unlock(&rpcsoc_lock);	/* pmap_getport is recursive */
		proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
		sport = pmap_getport(raddr, (u_long)prog, (u_long)vers,
		    proto);
		if (sport == 0) {
			goto err;
		}
		raddr->sin_port = htons(sport);
		mutex_lock(&rpcsoc_lock);	/* pmap_getport is recursive */
	}

	/* Transform sockaddr_in to netbuf */
	bindaddr.maxlen = bindaddr.len =  sizeof (struct sockaddr_in);
	bindaddr.buf = raddr;

	(void)bindresvport(fd, NULL);
	cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
				sendsz, recvsz);
	if (cl) {
		if (madefd == TRUE) {
			/*
			 * The fd should be closed while destroying the handle.
			 */
			(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
			*sockp = fd;
		}
		(void) freenetconfigent(nconf);
		mutex_unlock(&rpcsoc_lock);
		return (cl);
	}
	goto err;

syserror:
	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
	rpc_createerr.cf_error.re_errno = errno;

err:	if (madefd == TRUE)
		(void) close(fd);
	(void) freenetconfigent(nconf);
	mutex_unlock(&rpcsoc_lock);
	return (NULL);
}
Exemple #21
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);
}
Exemple #22
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;
}
Exemple #23
0
/*
 * Create an rpc client attached to the mount daemon.
 */
CLIENT *
get_mount_client(char *host, struct sockaddr_in *unused_sin, struct timeval *tv, int *sock, u_long mnt_version)
{
  CLIENT *client;
  struct netbuf nb;
  struct netconfig *nc = NULL;
  struct sockaddr_in sin;

  nb.maxlen = sizeof(sin);
  nb.buf = (char *) &sin;

  /*
   * First try a TCP handler
   */

  /*
   * Find mountd address on TCP
   */
  if ((nc = getnetconfigent(NC_TCP)) == NULL) {
    plog(XLOG_ERROR, "getnetconfig for tcp failed: %s", nc_sperror());
    goto tryudp;
  }
  if (!rpcb_getaddr(MOUNTPROG, mnt_version, nc, &nb, host)) {
    /*
     * don't print error messages here, since mountd might legitimately
     * serve udp only
     */
    goto tryudp;
  }
  /*
   * Create privileged TCP socket
   */
  *sock = t_open(nc->nc_device, O_RDWR, 0);

  if (*sock < 0) {
    plog(XLOG_ERROR, "t_open %s: %m", nc->nc_device);
    goto tryudp;
  }
  if (bind_resv_port(*sock, (u_short *) 0) < 0)
    plog(XLOG_ERROR, "couldn't bind mountd socket to privileged port");

  if ((client = clnt_vc_create(*sock, &nb, MOUNTPROG, mnt_version, 0, 0))
      == (CLIENT *) NULL) {
    plog(XLOG_ERROR, "clnt_vc_create failed");
    t_close(*sock);
    goto tryudp;
  }
  /* tcp succeeded */
  dlog("get_mount_client: using tcp, port %d", sin.sin_port);
  if (nc)
    freenetconfigent(nc);
  return client;

tryudp:
  /* first free possibly previously allocated netconfig entry */
  if (nc)
    freenetconfigent(nc);

  /*
   * TCP failed so try UDP
   */

  /*
   * Find mountd address on UDP
   */
  if ((nc = getnetconfigent(NC_UDP)) == NULL) {
    plog(XLOG_ERROR, "getnetconfig for udp failed: %s", nc_sperror());
    goto badout;
  }
  if (!rpcb_getaddr(MOUNTPROG, mnt_version, nc, &nb, host)) {
    plog(XLOG_ERROR, "%s",
	 clnt_spcreateerror("couldn't get mountd address on udp"));
    goto badout;
  }
  /*
   * Create privileged UDP socket
   */
  *sock = t_open(nc->nc_device, O_RDWR, 0);

  if (*sock < 0) {
    plog(XLOG_ERROR, "t_open %s: %m", nc->nc_device);
    goto badout;		/* neither tcp not udp succeeded */
  }
  if (bind_resv_port(*sock, (u_short *) 0) < 0)
    plog(XLOG_ERROR, "couldn't bind mountd socket to privileged port");

  if ((client = clnt_dg_create(*sock, &nb, MOUNTPROG, mnt_version, 0, 0))
      == (CLIENT *) NULL) {
    plog(XLOG_ERROR, "clnt_dg_create failed");
    t_close(*sock);
    goto badout;		/* neither tcp not udp succeeded */
  }
  if (clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) tv) == FALSE) {
    plog(XLOG_ERROR, "clnt_control CLSET_RETRY_TIMEOUT for udp failed");
    clnt_destroy(client);
    goto badout;		/* neither tcp not udp succeeded */
  }
  /* udp succeeded */
  dlog("get_mount_client: using udp, port %d", sin.sin_port);
  return client;

badout:
  /* failed */
  if (nc)
    freenetconfigent(nc);
  return NULL;
}
Exemple #24
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);
}
int nfs41_server_resolve(
    IN const char *hostname,
    IN unsigned short port,
    OUT multi_addr4 *addrs)
{
    int status = ERROR_BAD_NET_NAME;
    char service[16];
    struct addrinfo hints = { 0 }, *res, *info;
    struct netconfig *nconf;
    struct netbuf addr;
    char *netid, *uaddr;

    dprintf(SRVLVL, "--> nfs41_server_resolve(%s:%u)\n",
        hostname, port);

    addrs->count = 0;

    StringCchPrintfA(service, 16, "%u", port);

    /* request a list of tcp addrs for the given hostname,port */
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    if (getaddrinfo(hostname, service, &hints, &res) != 0)
        goto out;

    for (info = res; info != NULL; info = info->ai_next) {
        /* find the appropriate entry in /etc/netconfig */
        switch (info->ai_family) {
        case AF_INET:  netid = "tcp";  break;
        case AF_INET6: netid = "tcp6"; break;
        default: continue;
        }

        nconf = getnetconfigent(netid);
        if (nconf == NULL)
            continue;

        /* convert to a transport-independent universal address */
        addr.buf = info->ai_addr;
        addr.maxlen = addr.len = (unsigned int)info->ai_addrlen;

        uaddr = taddr2uaddr(nconf, &addr);
        freenetconfigent(nconf);

        if (uaddr == NULL)
            continue;

        StringCchCopyA(addrs->arr[addrs->count].netid,
            NFS41_NETWORK_ID_LEN+1, netid);
        StringCchCopyA(addrs->arr[addrs->count].uaddr,
            NFS41_UNIVERSAL_ADDR_LEN+1, uaddr);
        freeuaddr(uaddr);

        status = NO_ERROR;
        if (++addrs->count >= NFS41_ADDRS_PER_SERVER)
            break;
    }
    freeaddrinfo(res);
out:
    if (status)
        dprintf(SRVLVL, "<-- nfs41_server_resolve(%s:%u) returning "
            "error %d\n", hostname, port, status);
    else
        dprintf(SRVLVL, "<-- nfs41_server_resolve(%s:%u) returning "
            "%s\n", hostname, port, addrs->arr[0].uaddr);
    return status;
}
Exemple #26
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);
}
Exemple #27
0
static void
get_xdmcp_sock(void)
{
#ifdef STREAMSCONN
    struct netconfig *nconf;

    if ((xdmcpSocket = t_open("/dev/udp", O_RDWR, 0)) < 0) {
        XdmcpWarning("t_open() of /dev/udp failed");
        return;
    }

    if (t_bind(xdmcpSocket, NULL, NULL) < 0) {
        XdmcpWarning("UDP socket creation failed");
        t_error("t_bind(xdmcpSocket) failed");
        t_close(xdmcpSocket);
        return;
    }

    /*
     * This part of the code looks contrived. It will actually fit in nicely
     * when the CLTS part of Xtrans is implemented.
     */

    if ((nconf = getnetconfigent("udp")) == NULL) {
        XdmcpWarning("UDP socket creation failed: getnetconfigent()");
        t_unbind(xdmcpSocket);
        t_close(xdmcpSocket);
        return;
    }

    if (netdir_options(nconf, ND_SET_BROADCAST, xdmcpSocket, NULL)) {
        XdmcpWarning("UDP set broadcast option failed: netdir_options()");
        freenetconfigent(nconf);
        t_unbind(xdmcpSocket);
        t_close(xdmcpSocket);
        return;
    }

    freenetconfigent(nconf);
#else
    int soopts = 1;

#if defined(IPv6) && defined(AF_INET6)
    if ((xdmcpSocket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
        XdmcpWarning("INET6 UDP socket creation failed");
#endif
    if ((xdmcpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
        XdmcpWarning("UDP socket creation failed");
#ifdef SO_BROADCAST
    else if (setsockopt(xdmcpSocket, SOL_SOCKET, SO_BROADCAST, (char *) &soopts,
                        sizeof(soopts)) < 0)
        XdmcpWarning("UDP set broadcast socket-option failed");
#endif                          /* SO_BROADCAST */
    if (xdmcpSocket >= 0 && xdm_from != NULL) {
        if (bind(xdmcpSocket, (struct sockaddr *) &FromAddress,
                 FromAddressLen) < 0) {
            FatalError("Xserver: failed to bind to -from address: %s\n",
                       xdm_from);
        }
    }
#endif                          /* STREAMSCONN */
}
Exemple #28
0
CLIENT *
get_client(struct sockaddr *host_addr, rpcvers_t vers)
{
	CLIENT *client;
	struct timeval retry_time, time_now;
	int error, i;
	const char *netid;
	struct netconfig *nconf;
	char host[NI_MAXHOST];
	uid_t old_euid;
	int clnt_fd;

	gettimeofday(&time_now, NULL);

	/*
	 * Search for the given client in the cache, zapping any expired
	 * entries that we happen to notice in passing.
	 */
	for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
		client = clnt_cache_ptr[i];
		if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
		    < time_now.tv_sec)) {
			/* Cache entry has expired. */
			if (debug_level > 3)
				syslog(LOG_DEBUG, "Expired CLIENT* in cache");
			clnt_cache_time[i] = 0L;
			clnt_destroy(client);
			clnt_cache_ptr[i] = NULL;
			client = NULL;
		}
		if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i],
		    host_addr) && clnt_cache_vers[i] == vers) {
			/* Found it! */
			if (debug_level > 3)
				syslog(LOG_DEBUG, "Found CLIENT* in cache");
			return (client);
		}
	}

	if (debug_level > 3)
		syslog(LOG_DEBUG, "CLIENT* not found in cache, creating");

	/* Not found in cache.  Free the next entry if it is in use. */
	if (clnt_cache_ptr[clnt_cache_next_to_use]) {
		clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
		clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
	}

	/*
	 * Need a host string for clnt_tp_create. Use NI_NUMERICHOST
	 * to avoid DNS lookups.
	 */
	error = getnameinfo(host_addr, host_addr->sa_len, host, sizeof host,
			    NULL, 0, NI_NUMERICHOST);
	if (error != 0) {
		syslog(LOG_ERR, "unable to get name string for caller: %s",
		       gai_strerror(error));
		return NULL;
	}

#if 1
	if (host_addr->sa_family == AF_INET6)
		netid = "udp6";
	else
		netid = "udp";
#else 
	if (host_addr->sa_family == AF_INET6)
		netid = "tcp6";
	else
		netid = "tcp";
#endif
	nconf = getnetconfigent(netid);
	if (nconf == NULL) {
		syslog(LOG_ERR, "could not get netconfig info for '%s': "
				"no /etc/netconfig file?", netid);
		return NULL;
	}

	client = clnt_tp_create(host, NLM_PROG, vers, nconf);
	freenetconfigent(nconf);

	if (!client) {
		syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create"));
		syslog(LOG_ERR, "Unable to return result to %s", host);
		return NULL;
	}

	/* Get the FD of the client, for bindresvport. */ 
	clnt_control(client, CLGET_FD, &clnt_fd);

	/* Regain root privileges, for bindresvport. */
	old_euid = geteuid();
	seteuid(0);

	/*
	 * Bind the client FD to a reserved port.
	 * Some NFS servers reject any NLM request from a non-reserved port. 
	 */ 
	bindresvport(clnt_fd, NULL);

	/* Drop root privileges again. */
	seteuid(old_euid);

	/* Success - update the cache entry */
	clnt_cache_ptr[clnt_cache_next_to_use] = client;
	memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr,
	    host_addr->sa_len);
	clnt_cache_vers[clnt_cache_next_to_use] = vers;
	clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
	if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE)
		clnt_cache_next_to_use = 0;

	/*
	 * Disable the default timeout, so we can specify our own in calls
	 * to clnt_call().  (Note that the timeout is a different concept
	 * from the retry period set in clnt_udp_create() above.)
	 */
	retry_time.tv_sec = -1;
	retry_time.tv_usec = -1;
	clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);

	if (debug_level > 3)
		syslog(LOG_DEBUG, "Created CLIENT* for %s", host);
	return client;
}
Exemple #29
0
/*
 * valid_props validates all the properties in an array of inetd_prop_t's,
 * marking each property as valid or invalid.  If any properties are invalid,
 * it returns B_FALSE, otherwise it returns B_TRUE.  Note that some properties
 * are interdependent, so if one is invalid, it leaves others in an
 * indeterminate state (such as ISRPC and SVC_NAME).  In this case, the
 * indeterminate property will be marked valid.  IE, the only properties
 * marked invalid are those that are KNOWN to be invalid.
 *
 * Piggy-backed onto this validation if 'fmri' is non-NULL is the construction
 * of a structured configuration, a basic_cfg_t,  which is used by inetd.
 * If 'fmri' is set then the latter three parameters need to be set to
 * non-NULL values, and if the configuration is valid, the storage referenced
 * by cfgpp is set to point at an initialized basic_cfg_t.
 */
boolean_t
valid_props(inetd_prop_t *prop, const char *fmri, basic_cfg_t **cfgpp,
    uu_list_pool_t *proto_info_pool, uu_list_pool_t *tlx_ci_pool)
{
	char			*bufp, *cp;
	boolean_t		ret = B_TRUE;
	int			i;
	long			uidl;
	boolean_t		isrpc;
	int			sock_type_id;
	int			rpc_pnum;
	int			rpc_lv, rpc_hv;
	basic_cfg_t		*cfg;
	char			*proto = NULL;
	int			pi;
	char			**netids = NULL;
	int			ni = 0;

	if (fmri != NULL)
		assert((cfgpp != NULL) && (proto_info_pool != NULL) &&
		    (tlx_ci_pool != NULL));

	/*
	 * Set all checkable properties to valid as a baseline.  We'll be
	 * marking all invalid properties.
	 */
	for (i = 0; prop[i].ip_name != NULL; i++) {
		if (prop[i].ip_error != IVE_UNSET)
			prop[i].ip_error = IVE_VALID;
	}

	if (((cfg = calloc(1, sizeof (basic_cfg_t))) == NULL) ||
	    ((fmri != NULL) &&
	    ((cfg->proto_list = uu_list_create(proto_info_pool, NULL, 0)) ==
	    NULL))) {
		free(cfg);
		return (B_FALSE);
	}

	/* Check a service name was supplied */
	if ((prop[PT_SVC_NAME_INDEX].ip_error == IVE_UNSET) ||
	    ((cfg->svc_name =
	    strdup(prop[PT_SVC_NAME_INDEX].ip_value.iv_string)) == NULL))
		prop[PT_SVC_NAME_INDEX].ip_error = IVE_INVALID;

	/* Check that iswait and isrpc have valid boolean values */

	if ((prop[PT_ISWAIT_INDEX].ip_error == IVE_UNSET) ||
	    (((cfg->iswait = prop[PT_ISWAIT_INDEX].ip_value.iv_boolean) !=
	    B_TRUE) && (cfg->iswait != B_FALSE)))
		prop[PT_ISWAIT_INDEX].ip_error = IVE_INVALID;

	if ((prop[PT_ISRPC_INDEX].ip_error == IVE_UNSET) ||
	    (((isrpc = prop[PT_ISRPC_INDEX].ip_value.iv_boolean) != B_TRUE) &&
	    (isrpc != B_FALSE))) {
		prop[PT_ISRPC_INDEX].ip_error = IVE_INVALID;
	} else if (isrpc) {
		/*
		 * This is an RPC service, so ensure that the RPC version
		 * numbers are zero or greater, that the low version isn't
		 * greater than the high version and a valid program name
		 * is supplied.
		 */

		if ((prop[PT_RPC_LW_VER_INDEX].ip_error == IVE_UNSET) ||
		    ((rpc_lv = prop[PT_RPC_LW_VER_INDEX].ip_value.iv_int) <
		    0))
			prop[PT_RPC_LW_VER_INDEX].ip_error = IVE_INVALID;

		if ((prop[PT_RPC_HI_VER_INDEX].ip_error == IVE_UNSET) ||
		    ((rpc_hv = prop[PT_RPC_HI_VER_INDEX].ip_value.iv_int) <
		    0))
			prop[PT_RPC_HI_VER_INDEX].ip_error = IVE_INVALID;

		if ((prop[PT_RPC_LW_VER_INDEX].ip_error != IVE_INVALID) &&
		    (prop[PT_RPC_HI_VER_INDEX].ip_error != IVE_INVALID) &&
		    (rpc_lv > rpc_hv)) {
			prop[PT_RPC_LW_VER_INDEX].ip_error = IVE_INVALID;
			prop[PT_RPC_HI_VER_INDEX].ip_error = IVE_INVALID;
		}

		if ((cfg->svc_name != NULL) &&
		    ((rpc_pnum = get_rpc_prognum(cfg->svc_name)) == -1))
			prop[PT_SVC_NAME_INDEX].ip_error = IVE_INVALID;
	}

	/* Check that the socket type is one of the acceptable values. */
	cfg->istlx = B_FALSE;
	if ((prop[PT_SOCK_TYPE_INDEX].ip_error == IVE_UNSET) ||
	    ((sock_type_id = get_sock_type_id(
	    prop[PT_SOCK_TYPE_INDEX].ip_value.iv_string)) == -1) &&
	    !(cfg->istlx = is_tlx_service(prop)))
		prop[PT_SOCK_TYPE_INDEX].ip_error = IVE_INVALID;

	/* Get the bind address */
	if (!cfg->istlx && prop[PT_BIND_ADDR_INDEX].ip_error != IVE_UNSET &&
	    (cfg->bind_addr =
	    strdup(prop[PT_BIND_ADDR_INDEX].ip_value.iv_string)) == NULL)
		prop[PT_BIND_ADDR_INDEX].ip_error = IVE_INVALID;

	/*
	 * Iterate through all the different protos/netids resulting from the
	 * proto property and check that they're valid and perform checks on
	 * other fields that are tied-in with the proto.
	 */

	pi = 0;
	do {
		socket_info_t		*si = NULL;
		tlx_info_t		*ti = NULL;
		proto_info_t		*p_inf = NULL;
		boolean_t		v6only = B_FALSE;
		char			*only;
		boolean_t		invalid_proto = B_FALSE;
		char			**protos;
		struct protoent		pe;
		char			gpbuf[1024];
		struct netconfig	*nconf = NULL;

		/*
		 * If we don't know whether it's an rpc service or its
		 * endpoint type, we can't do any of the proto checks as we
		 * have no context; break out.
		 */
		if ((prop[PT_ISRPC_INDEX].ip_error != IVE_VALID) ||
		    (prop[PT_SOCK_TYPE_INDEX].ip_error != IVE_VALID))
			break;

		/* skip proto specific processing if the proto isn't set. */
		if (prop[PT_PROTO_INDEX].ip_error == IVE_UNSET) {
			invalid_proto = B_TRUE;
			goto past_proto_processing;
		}
		protos = prop[PT_PROTO_INDEX].ip_value.iv_string_list;

		/*
		 * Get the next netid/proto.
		 */

		if (!cfg->istlx || !isrpc) {
			proto = protos[pi++];
		/*
		 * This is a TLI/RPC service, so get the next netid, expanding
		 * any supplied nettype.
		 */
		} else if ((netids == NULL) ||
		    ((proto = netids[ni++]) == NULL)) {
			/*
			 * Either this is the first time around or
			 * we've exhausted the last set of netids, so
			 * try and get the next set using the currently
			 * indexed proto entry.
			 */

			if (netids != NULL) {
				destroy_strings(netids);
				netids = NULL;
			}

			if (protos[pi] != NULL) {
				if ((netids = get_netids(protos[pi++])) ==
				    NULL) {
					invalid_proto = B_TRUE;
					proto = protos[pi - 1];
				} else {
					ni = 0;
					proto = netids[ni++];
				}
			} else {
				proto = NULL;
			}
		}

		if (proto == NULL)
			break;

		if (invalid_proto)
			goto past_proto_processing;

		/* strip a trailing only to simplify further processing */
		only = proto + strlen(proto) - (sizeof ("6only") - 1);
		if ((only > proto) && (strcmp(only, "6only") == 0)) {
			*++only = '\0';
			v6only = B_TRUE;
		}

		/* validate the proto/netid */

		if (!cfg->istlx) {
			if (!valid_socket_proto(proto))
				invalid_proto = B_TRUE;
		} else {
			/*
			 * Check if we've got a valid netid. If
			 * getnetconfigent() fails, we check to see whether
			 * we've got a v6 netid that may have been rejected
			 * because no IPv6 interface was configured before
			 * flagging 'proto' as invalid. If the latter condition
			 * holds, we don't flag the proto as invalid, and
			 * leave inetd to handle the value appropriately
			 * when it tries to listen on behalf of the service.
			 */
			if (((nconf = getnetconfigent(proto)) == NULL) &&
			    !v6_proto(proto))
				invalid_proto = B_TRUE;
		}
		if (invalid_proto)
			goto past_proto_processing;

		/*
		 * dissallow datagram type nowait services
		 */
		if ((prop[PT_ISWAIT_INDEX].ip_error == IVE_VALID) &&
		    !cfg->iswait) {
			if (strncmp(proto, SOCKET_PROTO_UDP,
			    sizeof (SOCKET_PROTO_UDP) - 1) == 0) {
				invalid_proto = B_TRUE;
			} else if (cfg->istlx && (nconf != NULL) &&
			    (nconf->nc_semantics == NC_TPI_CLTS)) {
					invalid_proto = B_TRUE;
			}
			if (invalid_proto) {
				prop[PT_ISWAIT_INDEX].ip_error = IVE_INVALID;
				goto past_proto_processing;
			}
		}

		/*
		 * We're running in validate only mode. Don't bother creating
		 * any proto structures (they don't do any further validation).
		 */
		if (fmri == NULL)
			goto past_proto_processing;

		/*
		 * Create the apropriate transport info structure.
		 */
		if (cfg->istlx) {
			if ((ti = create_tlx_info(proto, tlx_ci_pool)) != NULL)
				p_inf = (proto_info_t *)ti;
		} else {
			struct sockaddr_storage *ss;

			if ((si = calloc(1, sizeof (socket_info_t))) != NULL) {
				p_inf = (proto_info_t *)si;
				si->type = sock_type_id;
				ss = &si->local_addr;

				if (v6_socket_proto(proto)) {
					ss->ss_family = AF_INET6;
					/* already in network order */
					((struct sockaddr_in6 *)ss)->sin6_addr =
					    in6addr_any;
				} else {
					ss->ss_family = AF_INET;
					((struct sockaddr_in *)ss)->sin_addr.
					    s_addr = htonl(INADDR_ANY);
				}
				if (set_bind_addr(ss, cfg->bind_addr) != 0) {
					prop[PT_BIND_ADDR_INDEX].ip_error =
					    IVE_INVALID;
				}
			}
		}
		if (p_inf == NULL) {
			invalid_proto = B_TRUE;
			goto past_proto_processing;
		}

		p_inf->v6only = v6only;

		/*
		 * Store the supplied proto string for error reporting,
		 * re-attaching the 'only' suffix if one was taken off.
		 */
		if ((p_inf->proto = malloc(strlen(proto) + 5)) == NULL) {
			invalid_proto = B_TRUE;
			goto past_proto_processing;
		} else {
			(void) strlcpy(p_inf->proto, proto, strlen(proto) + 5);
			if (v6only)
				(void) strlcat(p_inf->proto, "only",
				    strlen(proto) + 5);
		}

		/*
		 * Validate and setup RPC/non-RPC specifics.
		 */

		if (isrpc) {
			rpc_info_t *ri;

			if ((rpc_pnum != -1) && (rpc_lv != -1) &&
			    (rpc_hv != -1)) {
				if ((ri = create_rpc_info(proto, rpc_pnum,
				    rpc_lv, rpc_hv)) == NULL) {
					invalid_proto = B_TRUE;
				} else {
					p_inf->ri = ri;
				}
			}
		}

past_proto_processing:
		/* validate non-RPC service name */
		if (!isrpc && (cfg->svc_name != NULL)) {
			struct servent	se;
			char		gsbuf[NSS_BUFLEN_SERVICES];
			char		*gsproto = proto;

			if (invalid_proto) {
				/*
				 * Make getservbyname_r do its lookup without a
				 * proto.
				 */
				gsproto = NULL;
			} else if (gsproto != NULL) {
				/*
				 * Since getservbyname & getprotobyname don't
				 * support tcp6, udp6 or sctp6 take off the 6
				 * digit from protocol.
				 */
				if (v6_socket_proto(gsproto))
					gsproto[strlen(gsproto) - 1] = '\0';
			}

			if (getservbyname_r(cfg->svc_name, gsproto, &se, gsbuf,
			    sizeof (gsbuf)) == NULL) {
				if (gsproto != NULL)
					invalid_proto = B_TRUE;
				prop[PT_SVC_NAME_INDEX].ip_error = IVE_INVALID;
			} else if (cfg->istlx && (ti != NULL)) {
				/* LINTED E_BAD_PTR_CAST_ALIGN */
				SS_SETPORT(*(struct sockaddr_storage *)
				    ti->local_addr.buf, se.s_port);
			} else if (!cfg->istlx && (si != NULL)) {
				if ((gsproto != NULL) &&
				    getprotobyname_r(gsproto, &pe, gpbuf,
				    sizeof (gpbuf)) == NULL) {
					invalid_proto = B_TRUE;
				} else {
					si->protocol = pe.p_proto;
				}
				SS_SETPORT(si->local_addr, se.s_port);
			}

		}

		if (p_inf != NULL) {
			p_inf->listen_fd = -1;

			/* add new proto entry to proto_list */
			uu_list_node_init(p_inf, &p_inf->link, proto_info_pool);
			(void) uu_list_insert_after(cfg->proto_list, NULL,
			    p_inf);
		}

		if (nconf != NULL)
			freenetconfigent(nconf);
		if (invalid_proto)
			prop[PT_PROTO_INDEX].ip_error = IVE_INVALID;
	} while (proto != NULL);	/* while just processed a proto */

	/*
	 * Check that the exec string for the start method actually exists and
	 * that the user is either a valid username or uid. Note we don't
	 * mandate the setting of these fields, and don't do any checks
	 * for arg0, hence its absence.
	 */

	if (prop[PT_EXEC_INDEX].ip_error != IVE_UNSET) {
		/* Don't pass any arguments to access() */
		if ((bufp = strdup(
		    prop[PT_EXEC_INDEX].ip_value.iv_string)) == NULL) {
			prop[PT_EXEC_INDEX].ip_error = IVE_INVALID;
		} else {
			if ((cp = strpbrk(bufp, " \t")) != NULL)
				*cp = '\0';

			if ((access(bufp, F_OK) == -1) && (errno == ENOENT))
				prop[PT_EXEC_INDEX].ip_error = IVE_INVALID;
			free(bufp);
		}
	}

	if (prop[PT_USER_INDEX].ip_error != IVE_UNSET) {
		char		pw_buf[NSS_BUFLEN_PASSWD];
		struct passwd	pw;

		if (getpwnam_r(prop[PT_USER_INDEX].ip_value.iv_string, &pw,
		    pw_buf, NSS_BUFLEN_PASSWD) == NULL) {
			errno = 0;
			uidl = strtol(prop[PT_USER_INDEX].ip_value.iv_string,
			    &bufp, 10);
			if ((errno != 0) || (*bufp != '\0') ||
			    (getpwuid_r(uidl, &pw, pw_buf,
			    NSS_BUFLEN_PASSWD) == NULL))
				prop[PT_USER_INDEX].ip_error = IVE_INVALID;
		}
	}

	/*
	 * Iterate through the properties in the array verifying that any
	 * default properties are valid, and setting the return boolean
	 * according to whether any properties were marked invalid.
	 */

	for (i = 0; prop[i].ip_name != NULL; i++) {
		if (prop[i].ip_error == IVE_UNSET)
			continue;

		if (prop[i].ip_default &&
		    !valid_default_prop(prop[i].ip_name, &prop[i].ip_value))
			prop[i].ip_error = IVE_INVALID;

		if (prop[i].ip_error == IVE_INVALID)
			ret = B_FALSE;
	}

	/* pass back the basic_cfg_t if requested and it's a valid config */
	if ((cfgpp != NULL) && ret) {
		*cfgpp = cfg;
	} else {
		destroy_basic_cfg(cfg);
	}

	return (ret);
}
Exemple #30
0
CreateWellKnownSockets ()
{
    struct t_bind bind_addr;
    struct netconfig *nconf;
    struct nd_hostserv service;
    struct nd_addrlist *servaddrs;
    char *name, *localHostname();
    char bindbuf[15];
    int it;

    if (request_port == 0)
	return;
    Debug ("creating UDP stream %d\n", request_port);

    nconf = getnetconfigent("udp");
    if (!nconf) {
	t_error("getnetconfigent udp");
	return;
    }

    xdmcpFd = t_open(nconf->nc_device, O_RDWR, NULL);
    if (xdmcpFd == -1) {
	LogError ("XDMCP stream creation failed\n");
	t_error ("t_open");
	return;
    }
    name = localHostname ();
    registerHostname (name, strlen (name));
    RegisterCloseOnFork (xdmcpFd);

    service.h_host = HOST_SELF;
    sprintf(bindbuf, "%d", request_port);
    service.h_serv = bindbuf;
    netdir_getbyname(nconf, &service, &servaddrs);
    freenetconfigent(nconf);

    bind_addr.qlen = 5;
    bind_addr.addr.buf = servaddrs->n_addrs[0].buf;
    bind_addr.addr.len = servaddrs->n_addrs[0].len;
    it = t_bind(xdmcpFd, &bind_addr, &bind_addr);
    netdir_free(servaddrs, ND_ADDRLIST);
    if (it < 0)
    {
	LogError ("error binding STREAMS address %d\n", request_port);
	t_error("t_bind");	/* also goes to log file */
	t_close (xdmcpFd);
	xdmcpFd = -1;
	return;
    }
    WellKnownSocketsMax = xdmcpFd;
    FD_SET (xdmcpFd, &WellKnownSocketsMask);

    chooserFd = t_open ("/dev/tcp", O_RDWR, NULL);
    Debug ("Created chooser fd %d\n", chooserFd);
    if (chooserFd == -1)
    {
	LogError ("chooser stream creation failed\n");
	t_error("t_open chooser");
	return;
    }
    if (chooserFd > WellKnownSocketsMax)
	WellKnownSocketsMax = chooserFd;
    FD_SET (chooserFd, &WellKnownSocketsMask);
}