Esempio n. 1
0
static ICBINN *
icbinn_clnt_create_by_fd (int sockfd, struct sockaddr *sa, int sa_len)
{
  ICBINN *icb;
  CLIENT *c;

  struct netbuf raddr;


  memset (&raddr, 0, sizeof (raddr));
  raddr.buf = sa;
  raddr.maxlen = raddr.len = sa_len;

  c =
    clnt_vc_create (sockfd, &raddr, ICBINN_PROT_PROGRAM, ICBINN_PROT_VERSION,
                    0, 0);

  if (!c)
    return NULL;

  icb = (ICBINN *) xmalloc (sizeof (ICBINN));
  icb->c = c;

  return icb;
}
Esempio n. 2
0
/*
 * Create a client handle for a unix connection. Obsoleted by clnt_vc_create()
 */
CLIENT *
clntunix_create(struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp,
    u_int sendsz, u_int recvsz)
{
	struct netbuf *svcaddr;
	CLIENT *cl;
	int len;

	cl = NULL;
	svcaddr = NULL;
	if ((raddr->sun_len == 0) ||
	   ((svcaddr = malloc(sizeof(struct netbuf))) == NULL ) ||
	   ((svcaddr->buf = malloc(sizeof(struct sockaddr_un))) == NULL)) {
		free(svcaddr);
		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
		rpc_createerr.cf_error.re_errno = errno;
		return(cl);
	}
	if (*sockp < 0) {
		*sockp = _socket(AF_LOCAL, SOCK_STREAM, 0);
		len = raddr->sun_len = SUN_LEN(raddr);
		if ((*sockp < 0) || (_connect(*sockp,
		    (struct sockaddr *)raddr, len) < 0)) {
			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
			rpc_createerr.cf_error.re_errno = errno;
			if (*sockp != -1)
				(void)_close(*sockp);
			goto done;
		}
	}
	svcaddr->buf = raddr;
	svcaddr->len = raddr->sun_len;
	svcaddr->maxlen = sizeof (struct sockaddr_un);
	cl = clnt_vc_create(*sockp, svcaddr, prog,
	    vers, sendsz, recvsz);
done:
	free(svcaddr->buf);
	free(svcaddr);
	return(cl);
}
Esempio n. 3
0
/*
 * Generic client creation:  returns client handle.
 * Default options are set, which the user can
 * change using the rpc equivalent of _ioctl()'s : clnt_control().
 * If fd is RPC_ANYFD, it will be opened using nconf.
 * It will be bound if not so.
 * If sizes are 0; appropriate defaults will be chosen.
 */
CLIENT *
clnt_tli_create(int fd, const struct netconfig *nconf,
	struct netbuf *svcaddr, rpcprog_t prog, rpcvers_t vers,
	uint sendsz, uint recvsz)
{
	CLIENT *cl;			/* client handle */
	bool_t madefd = FALSE;		/* whether fd opened here */
	long servtype;
	int one = 1;
	struct __rpc_sockinfo si;
	extern int __rpc_minfd;

	if (fd == RPC_ANYFD) {
		if (nconf == NULL) {
			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
			return (NULL);
		}

		fd = __rpc_nconf2fd(nconf);

		if (fd == -1)
			goto err;
		if (fd < __rpc_minfd)
			fd = __rpc_raise_fd(fd);
		madefd = TRUE;
		servtype = nconf->nc_semantics;
		if (!__rpc_fd2sockinfo(fd, &si))
			goto err;
		bindresvport(fd, NULL);
	} else {
		if (!__rpc_fd2sockinfo(fd, &si))
			goto err;
		servtype = __rpc_socktype2seman(si.si_socktype);
		if (servtype == -1) {
			rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
			return (NULL);
		}
	}

	if (si.si_af != ((struct sockaddr *)svcaddr->buf)->sa_family) {
		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;	/* XXX */
		goto err1;
	}

	switch (servtype) {
	case NC_TPI_COTS:
		cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
		break;
	case NC_TPI_COTS_ORD:
		if (nconf &&
		    ((strcmp(nconf->nc_protofmly, "inet") == 0) ||
		     (strcmp(nconf->nc_protofmly, "inet6") == 0))) {
			setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one,
			    sizeof (one));
		}
		cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
		break;
	case NC_TPI_CLTS:
		cl = clnt_dg_create(fd, svcaddr, prog, vers, sendsz, recvsz);
		break;
	default:
		goto err;
	}

	if (cl == NULL)
		goto err1; /* borrow errors from clnt_dg/vc creates */
	if (nconf) {
		cl->cl_netid = strdup(nconf->nc_netid);
		cl->cl_tp = strdup(nconf->nc_device);
	} else {
		cl->cl_netid = "";
		cl->cl_tp = "";
	}
	if (madefd) {
		(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
/*		(void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL);  */
	};

	return (cl);

err:
	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
	rpc_createerr.cf_error.re_errno = errno;
err1:	if (madefd)
		(void)close(fd);
	return (NULL);
}
Esempio n. 4
0
/* Create a channel for a new clientid (v4) or session, optionally
 * connecting it */
int nfs_rpc_create_chan_v40(nfs_client_id_t *pclientid,
                            uint32_t flags)
{
    struct netbuf raddr;
    int fd, proto, code = 0;
    rpc_call_channel_t *chan = &pclientid->cid_cb.cb_u.v40.cb_chan;



    assert(! chan->clnt);

    /* XXX we MUST error RFC 3530bis, sec. 3.3.3 */
    if (! supported_auth_flavor(pclientid->cid_credential.flavor)) {
        code = EINVAL;
        goto out;
    }

    chan->type = RPC_CHAN_V40;
    chan->nvu.v40.pclientid = pclientid;

    code = nfs_clid_connected_socket(pclientid, &fd, &proto);
    if (code) {
        LogWarn(COMPONENT_NFS_CB,
                 "Failed creating socket");
        goto out;
    }

    raddr.buf = &pclientid->cid_cb.cid_addr.ss;

    switch (proto) {
    case IPPROTO_TCP:
        raddr.maxlen = raddr.len = sizeof(struct sockaddr_in);
        chan->clnt = clnt_vc_create(fd,
                                    &raddr,
                                    pclientid->cid_cb.cid_program,
                                    1 /* Errata ID: 2291 */,
                                    0, 0);
        break;
    case IPPROTO_UDP:
        raddr.maxlen = raddr.len = sizeof(struct sockaddr_in6);
        chan->clnt = clnt_dg_create(fd,
                                    &raddr,
                                    pclientid->cid_cb.cid_program,
                                    1 /* Errata ID: 2291 */,
                                    0, 0);
        break;
    default:
        break;
    }

    if (! chan->clnt) {
        code = EINVAL;
        goto out;
    }

    /* channel protection */
    if (! nfs_rpc_callback_seccreate(chan)) {
        /* XXX */
        code = EINVAL;
    }

out:
    return (code);
}
Esempio n. 5
0
static enum clnt_stat
clnt_reconnect_connect(CLIENT *cl)
{
	struct thread *td = curthread;
	struct rc_data *rc = (struct rc_data *)cl->cl_private;
	struct socket *so;
	enum clnt_stat stat;
	int error;
	int one = 1;
	struct ucred *oldcred;
	CLIENT *newclient = NULL;

	mtx_lock(&rc->rc_lock);
	while (rc->rc_connecting) {
		error = msleep(rc, &rc->rc_lock,
		    rc->rc_intr ? PCATCH : 0, "rpcrecon", 0);
		if (error) {
			mtx_unlock(&rc->rc_lock);
			return (RPC_INTR);
		}
	}
	if (rc->rc_closed) {
		mtx_unlock(&rc->rc_lock);
		return (RPC_CANTSEND);
	}
	if (rc->rc_client) {
		mtx_unlock(&rc->rc_lock);
		return (RPC_SUCCESS);
	}

	/*
	 * My turn to attempt a connect. The rc_connecting variable
	 * serializes the following code sequence, so it is guaranteed
	 * that rc_client will still be NULL after it is re-locked below,
	 * since that is the only place it is set non-NULL.
	 */
	rc->rc_connecting = TRUE;
	mtx_unlock(&rc->rc_lock);

	oldcred = td->td_ucred;
	td->td_ucred = rc->rc_ucred;
	so = __rpc_nconf2socket(rc->rc_nconf);
	if (!so) {
		stat = rpc_createerr.cf_stat = RPC_TLIERROR;
		rpc_createerr.cf_error.re_errno = 0;
		td->td_ucred = oldcred;
		goto out;
	}

	if (rc->rc_privport)
		bindresvport(so, NULL);

	if (rc->rc_nconf->nc_semantics == NC_TPI_CLTS)
		newclient = clnt_dg_create(so,
		    (struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers,
		    rc->rc_sendsz, rc->rc_recvsz);
	else
		newclient = clnt_vc_create(so,
		    (struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers,
		    rc->rc_sendsz, rc->rc_recvsz, rc->rc_intr);
	td->td_ucred = oldcred;

	if (!newclient) {
		soclose(so);
		rc->rc_err = rpc_createerr.cf_error;
		stat = rpc_createerr.cf_stat;
		goto out;
	}

	CLNT_CONTROL(newclient, CLSET_FD_CLOSE, 0);
	CLNT_CONTROL(newclient, CLSET_CONNECT, &one);
	CLNT_CONTROL(newclient, CLSET_TIMEOUT, &rc->rc_timeout);
	CLNT_CONTROL(newclient, CLSET_RETRY_TIMEOUT, &rc->rc_retry);
	CLNT_CONTROL(newclient, CLSET_WAITCHAN, rc->rc_waitchan);
	CLNT_CONTROL(newclient, CLSET_INTERRUPTIBLE, &rc->rc_intr);
	if (rc->rc_backchannel != NULL)
		CLNT_CONTROL(newclient, CLSET_BACKCHANNEL, rc->rc_backchannel);
	stat = RPC_SUCCESS;

out:
	mtx_lock(&rc->rc_lock);
	KASSERT(rc->rc_client == NULL, ("rc_client not null"));
	if (!rc->rc_closed) {
		rc->rc_client = newclient;
		newclient = NULL;
	}
	rc->rc_connecting = FALSE;
	wakeup(rc);
	mtx_unlock(&rc->rc_lock);

	if (newclient) {
		/*
		 * It has been closed, so discard the new client.
		 * nb: clnt_[dg|vc]_close()/clnt_[dg|vc]_destroy() cannot
		 * be called with the rc_lock mutex held, since they may
		 * msleep() while holding a different mutex.
		 */
		CLNT_CLOSE(newclient);
		CLNT_RELEASE(newclient);
	}

	return (stat);
}
Esempio n. 6
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;
}