示例#1
0
文件: svc_dg.c 项目: linuxbox2/ntirpc
static enum xprt_stat
svc_dg_decode(struct svc_req *req)
{
	XDR *xdrs = req->rq_xdrs;
	SVCXPRT *xprt = req->rq_xprt;

	xdrs->x_op = XDR_DECODE;
	XDR_SETPOS(xdrs, 0);
	rpc_msg_init(&req->rq_msg);

	if (!xdr_dplx_decode(xdrs, &req->rq_msg)) {
		__warnx(TIRPC_DEBUG_FLAG_ERROR,
			"%s: %p fd %d failed (will set dead)",
			__func__, xprt, xprt->xp_fd);
		return (XPRT_DIED);
	}

	/* in order of likelihood */
	if (req->rq_msg.rm_direction == CALL) {
		/* an ordinary call header */
		return xprt->xp_dispatch.process_cb(req);
	}

	if (req->rq_msg.rm_direction == REPLY) {
		/* reply header (xprt OK) */
		return clnt_req_process_reply(xprt->xp_parent, req);
	}

	__warnx(TIRPC_DEBUG_FLAG_WARN,
		"%s: %p fd %d failed direction %" PRIu32
		" (will set dead)",
		__func__, __func__, xprt, xprt->xp_fd,
		req->rq_msg.rm_direction);
	return (XPRT_DIED);
}
示例#2
0
struct rpc_dplx_rec *
rpc_dplx_lookup_rec(int fd, uint32_t iflags, uint32_t *oflags)
{
    struct rbtree_x_part *t;
    struct rpc_dplx_rec rk, *rec = NULL;
    struct opr_rbtree_node *nv;

    cond_init_rpc_dplx();

    rk.fd_k = fd;
    t = rbtx_partition_of_scalar(&(rpc_dplx_rec_set.xt), fd);

    rwlock_rdlock(&t->lock);
    nv = opr_rbtree_lookup(&t->t, &rk.node_k);

    /* XXX rework lock+insert case, so that new entries are inserted
     * locked, and t->lock critical section is reduced */

    if (! nv) {
        rwlock_unlock(&t->lock);
        rwlock_wrlock(&t->lock);
        nv = opr_rbtree_lookup(&t->t, &rk.node_k);
        if (! nv) {
            rec = alloc_dplx_rec();
            if (! rec) {
                __warnx(TIRPC_DEBUG_FLAG_LOCK,
                        "%s: failed allocating rpc_dplx_rec", __func__);
                goto unlock;
            }

            /* tell the caller */
            *oflags = RPC_DPLX_LKP_OFLAG_ALLOC;

            rec->fd_k = fd;

            if (opr_rbtree_insert(&t->t, &rec->node_k)) {
                /* cant happen */
                __warnx(TIRPC_DEBUG_FLAG_LOCK,
                        "%s: collision inserting in locked rbtree partition",
                        __func__);
                free_dplx_rec(rec);
            }
        }
    }
    else {
        rec = opr_containerof(nv, struct rpc_dplx_rec, node_k);
        *oflags = RPC_DPLX_LKP_FLAG_NONE;
    }

    rpc_dplx_ref(rec, (iflags & RPC_DPLX_LKP_IFLAG_LOCKREC) ?
                 RPC_DPLX_FLAG_LOCK :
                 RPC_DPLX_FLAG_NONE);

unlock:
    rwlock_unlock(&t->lock);

    return (rec);
}
示例#3
0
/*
 * 3. Validate
 */
static bool
authdes_validate(AUTH *auth, struct opaque_auth *rverf)
{
	/* LINTED pointer alignment */
	struct ad_private *ad = AUTH_PRIVATE(auth);
	struct authdes_verf verf;
	int status;
	uint32_t *ixdr;
	des_block buf;

	if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT)
		return (false);

	/* LINTED pointer alignment */
	ixdr = (uint32_t *) rverf->oa_base;
	buf.key.high = (uint32_t) *ixdr++;
	buf.key.low = (uint32_t) *ixdr++;
	verf.adv_int_u = (uint32_t) *ixdr++;

	/*
	 * Decrypt the timestamp
	 */
	status =
	    ecb_crypt((char *)&auth->ah_key, (char *)&buf,
		      (u_int) sizeof(des_block), DES_DECRYPT | DES_HW);

	if (DES_FAILED(status)) {
		__warnx(TIRPC_DEBUG_FLAG_AUTH,
			"authdes_validate: DES decryption failure");
		return (false);
	}

	/*
	 * xdr the decrypted timestamp
	 */
	/* LINTED pointer alignment */
	ixdr = (uint32_t *) buf.c;
	verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1;
	verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr);

	/*
	 * validate
	 */
	if (bcmp
	    ((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
	     sizeof(struct timeval)) != 0) {
		__warnx(TIRPC_DEBUG_FLAG_AUTH,
			"authdes_validate: verifier mismatch");
		return (false);
	}

	/*
	 * We have a nickname now, let's use it
	 */
	ad->ad_nickname = verf.adv_nickname;
	ad->ad_cred.adc_namekind = ADN_NICKNAME;
	return (true);
}
示例#4
0
文件: svc_dg.c 项目: linuxbox2/ntirpc
static enum xprt_stat
svc_dg_reply(struct svc_req *req)
{
	SVCXPRT *xprt = req->rq_xprt;
	struct rpc_dplx_rec *rec = REC_XPRT(xprt);
	XDR *xdrs = rec->ioq.xdrs;
	struct svc_dg_xprt *su = DG_DR(rec);
	struct msghdr *msg = &su->su_msghdr;
	struct iovec iov;
	size_t slen;

	if (!xprt->xp_remote.nb.len) {
		__warnx(TIRPC_DEBUG_FLAG_WARN,
			"%s: %p fd %d has no remote address",
			__func__, xprt, xprt->xp_fd);
		return (XPRT_IDLE);
	}
	xdrs->x_op = XDR_ENCODE;
	XDR_SETPOS(xdrs, 0);

	if (!xdr_reply_encode(xdrs, &req->rq_msg)) {
		__warnx(TIRPC_DEBUG_FLAG_ERROR,
			"%s: %p fd %d xdr_reply_encode failed (will set dead)",
			__func__, xprt, xprt->xp_fd);
		return (XPRT_DIED);
	}

	if (req->rq_msg.rm_reply.rp_stat == MSG_ACCEPTED
	 && req->rq_msg.rm_reply.rp_acpt.ar_stat == SUCCESS
	 && req->rq_auth
	 && !SVCAUTH_WRAP(req, xdrs)) {
		__warnx(TIRPC_DEBUG_FLAG_ERROR,
			"%s: %p fd %d SVCAUTH_WRAP failed (will set dead)",
			__func__, xprt, xprt->xp_fd);
		return (XPRT_DIED);
	}
	iov.iov_base = &su[1];
	iov.iov_len = slen = XDR_GETPOS(xdrs);
	msg->msg_iov = &iov;
	msg->msg_iovlen = 1;
	msg->msg_name = (struct sockaddr *)&xprt->xp_remote.ss;
	msg->msg_namelen = xprt->xp_remote.nb.len;
	/* cmsg already set in svc_dg_rendezvous */

	if (sendmsg(xprt->xp_fd, msg, 0) != (ssize_t) slen) {
		__warnx(TIRPC_DEBUG_FLAG_ERROR,
			"%s: %p fd %d sendmsg failed (will set dead)",
			__func__, xprt, xprt->xp_fd);
		return (XPRT_DIED);
	}

	return (XPRT_IDLE);
}
示例#5
0
static bool
svc_rdma_reply(SVCXPRT *xprt, struct svc_req *req, struct rpc_msg *msg)
{
	struct rpc_rdma_cbc *cbc = req->rq_context;
	XDR *xdrs = cbc->holdq.xdrs;
	xdrproc_t proc;
	void *where;
	bool has_args;

	__warnx(TIRPC_DEBUG_FLAG_SVC_RDMA,
		"%s() xprt %p cbc %p outgoing xdr %p\n",
		__func__, xprt, cbc, xdrs);

	if (msg->rm_reply.rp_stat == MSG_ACCEPTED
	 && msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
	    has_args = TRUE;
	    proc = msg->acpted_rply.ar_results.proc;
	    where = msg->acpted_rply.ar_results.where;
	    msg->acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
	    msg->acpted_rply.ar_results.where = NULL;
	} else {
	    has_args = FALSE;
	    proc = NULL;
	    where = NULL;
	}

	if (!xdr_rdma_svc_reply(cbc, 0)){
		__warnx(TIRPC_DEBUG_FLAG_SVC_RDMA,
			"%s: xdr_rdma_svc_reply failed (will set dead)",
			__func__);
		return (FALSE);
	}
	xdrs->x_op = XDR_ENCODE;

	if (!xdr_reply_encode(xdrs, msg)) {
		__warnx(TIRPC_DEBUG_FLAG_SVC_RDMA,
			"%s: xdr_reply_encode failed (will set dead)",
			__func__);
		return (FALSE);
	}
	xdr_tail_update(xdrs);

	if (has_args && req->rq_auth
	  && !SVCAUTH_WRAP(req->rq_auth, req, xdrs, proc, where)) {
		__warnx(TIRPC_DEBUG_FLAG_SVC_RDMA,
			"%s: SVCAUTH_WRAP failed (will set dead)",
			__func__);
		return (FALSE);
	}
	xdr_tail_update(xdrs);

	return xdr_rdma_svc_flushout(cbc);
}
示例#6
0
void
authgss_hash_init()
{
	int ix, code = 0;

	mutex_lock(&authgss_hash_st.lock);

	/* once */
	if (authgss_hash_st.initialized)
		goto unlock;

	code =
	    rbtx_init(&authgss_hash_st.xt, svc_rpc_gss_cmpf,
		      __svc_params->gss.ctx_hash_partitions,
		      RBT_X_FLAG_ALLOC | RBT_X_FLAG_CACHE_RT);
	if (code)
		__warnx(TIRPC_DEBUG_FLAG_RPCSEC_GSS, "%s: rbtx_init failed",
			__func__);

	/* init read-through cache */
	for (ix = 0; ix < __svc_params->gss.ctx_hash_partitions; ++ix) {
		struct rbtree_x_part *xp = &(authgss_hash_st.xt.tree[ix]);
		struct authgss_x_part *axp;
		xp->cache =
		    mem_zalloc(authgss_hash_st.xt.cachesz *
			       sizeof(struct opr_rbtree_node *));
		if (unlikely(!xp->cache)) {
			__warnx(TIRPC_DEBUG_FLAG_RPCSEC_GSS,
				"%s: rbtx cache partition alloc failed",
				__func__);
			authgss_hash_st.xt.cachesz = 0;
			break;
		}
		/* partition ctx LRU */
		axp = (struct authgss_x_part *)
		    mem_alloc(sizeof(struct authgss_x_part));
		TAILQ_INIT(&axp->lru_q);
		xp->u1 = axp;
	}

	authgss_hash_st.size = 0;
	authgss_hash_st.max_part =
	    __svc_params->gss.max_gc / authgss_hash_st.xt.npart;
	authgss_hash_st.initialized = true;

 unlock:
	mutex_unlock(&authgss_hash_st.lock);
}
示例#7
0
/*
 * Create an xdr handle for xdrrec
 * xdr_inrec_create fills in xdrs.  Sendsize and recvsize are
 * send and recv buffer sizes (0 => use default).
 * tcp_handle is an opaque handle that is passed as the first parameter to
 * the procedures readit and writeit.  Readit and writeit are read and
 * write respectively.   They are like the system
 * calls expect that they take an opaque handle rather than an fd.
 */
void
xdr_inrec_create(XDR *xdrs,
              u_int recvsize,
              void *tcp_handle,
              /* like read, but pass it a tcp_handle, not sock */
              int (*readit)(XDR *, void *, void *, int))
{
    RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM));

    if (rstrm == NULL) {
        __warnx(TIRPC_DEBUG_FLAG_XDRREC,
                "xdr_inrec_create: out of memory");
        /*
         *  This is bad.  Should rework xdr_inrec_create to
         *  return a handle, and in this case return NULL
         */
        return;
    }
    rstrm->recvsize = recvsize = fix_buf_size(recvsize);
    rstrm->in_base = mem_alloc(recvsize);
    if (rstrm->in_base == NULL) {
        __warnx(TIRPC_DEBUG_FLAG_XDRREC,
                "xdr_inrec_create: out of memory");
        mem_free(rstrm, sizeof(RECSTREAM));
        return;
    }
    /*
     * now the rest ...
     */
    xdrs->x_ops = &xdr_inrec_ops;
    xdrs->x_lib[0] = NULL;
    xdrs->x_lib[1] = NULL;
    xdrs->x_public = NULL;
    xdrs->x_private = rstrm;
    xdrs->x_flags = XDR_FLAG_CKSUM;
    rstrm->xdrs = xdrs;
    rstrm->tcp_handle = tcp_handle;
    rstrm->readit = readit;
    rstrm->in_size = recvsize;
    rstrm->in_boundry = rstrm->in_base;
    rstrm->in_finger = (rstrm->in_boundry += recvsize);
    rstrm->fbtbc = 0;
    rstrm->last_frag = TRUE;
    rstrm->in_haveheader = FALSE;
    rstrm->offset = 0;
    rstrm->cksum = 0;
    rstrm->cklen = 256;
}
示例#8
0
文件: svc_dg.c 项目: linuxbox2/ntirpc
static void
svc_dg_destroy_it(SVCXPRT *xprt, u_int flags, const char *tag, const int line)
{
	struct timespec ts = {
		.tv_sec = 0,
		.tv_nsec = 0,
	};

	if (!xprt->xp_parent) {
		/* only original parent is registered */
		svc_rqst_xprt_unregister(xprt);
	}

	__warnx(TIRPC_DEBUG_FLAG_REFCNT,
		"%s() %p fd %d xp_refs %" PRIu32
		" should actually destroy things @ %s:%d",
		__func__, xprt, xprt->xp_fd, xprt->xp_refs, tag, line);

	while (atomic_postset_uint16_t_bits(&(REC_XPRT(xprt)->ioq.ioq_s.qflags),
					    IOQ_FLAG_WORKING)
	       & IOQ_FLAG_WORKING) {
		nanosleep(&ts, NULL);
	}

	REC_XPRT(xprt)->ioq.ioq_wpe.fun = svc_dg_destroy_task;
	work_pool_submit(&svc_work_pool, &(REC_XPRT(xprt)->ioq.ioq_wpe));
}

static void
svc_dg_destroy(SVCXPRT *xprt, u_int flags, const char *tag, const int line)
{
	svc_dg_destroy_it(xprt, flags, tag, line);
}
示例#9
0
/*
 * writes data to the tcp connection.
 * Any error is fatal and the connection is closed.
 */
static inline int
svc_write_vc(XDR *xdrs, void *ctp, void *buf, int len)
{
    SVCXPRT *xprt;
    struct x_vc_data *xd;
    struct timespec ts0, ts1;
    int i, cnt;

    xd = (struct x_vc_data *) ctp;
    xprt = xd->rec->hdl.xprt;

    if (xd->shared.nonblock)
        (void) clock_gettime(CLOCK_MONOTONIC_FAST, &ts0);

    for (cnt = len; cnt > 0; cnt -= i, buf += i) {
        i = write(xprt->xp_fd, buf, (size_t)cnt);
        if (i  < 0) {
            if (errno != EAGAIN || !xd->shared.nonblock) {
                __warnx(TIRPC_DEBUG_FLAG_SVC_VC,
                        "%s: short write !EAGAIN (will set dead)",
                        __func__);
                cfconn_set_dead(xprt, xd);
                return (-1);
            }
            if (xd->shared.nonblock && i != cnt) {
                /*
                 * For non-blocking connections, do not
                 * take more than 2 seconds writing the
                 * data out.
                 *
                 * XXX 2 is an arbitrary amount.
                 */
                (void) clock_gettime(CLOCK_MONOTONIC_FAST, &ts1);
                if (ts1.tv_sec - ts0.tv_sec >= 2) {
                    __warnx(TIRPC_DEBUG_FLAG_SVC_VC,
                            "%s: short write !EAGAIN (will set dead)",
                            __func__);
                    cfconn_set_dead(xprt, xd);
                    return (-1);
                }
            }
        }
    }

    return (len);
}
示例#10
0
static inline int
svc_read_vc(XDR *xdrs, void *ctp, void *buf, int len)
{
    SVCXPRT *xprt;
    int milliseconds = 35 * 1000; /* XXX shouldn't this be configurable? */
    struct pollfd pollfd;
    struct x_vc_data *xd;

    xd = (struct x_vc_data *) ctp;
    xprt = xd->rec->hdl.xprt;

    if (xd->shared.nonblock) {
        len = read(xprt->xp_fd, buf, (size_t)len);
        if (len < 0) {
            if (errno == EAGAIN)
                len = 0;
            else
                goto fatal_err;
        }
        if (len != 0)
            (void) clock_gettime(
                CLOCK_MONOTONIC_FAST, &xd->sx.last_recv);
        return len;
    }

    do {
        pollfd.fd = xprt->xp_fd;
        pollfd.events = POLLIN;
        pollfd.revents = 0;
        switch (poll(&pollfd, 1, milliseconds)) {
        case -1:
            if (errno == EINTR)
                continue;
            /*FALLTHROUGH*/
        case 0:
            __warnx(TIRPC_DEBUG_FLAG_SVC_VC,
                    "%s: poll returns 0 (will set dead)",
                    __func__);
            goto fatal_err;

        default:
            break;
        }
    } while ((pollfd.revents & POLLIN) == 0);

    if ((len = read(xprt->xp_fd, buf, (size_t)len)) > 0) {
        (void) clock_gettime(
            CLOCK_MONOTONIC_FAST, &xd->sx.last_recv);
        return (len);
    }

fatal_err:
    cfconn_set_dead(xprt, xd);
    return (-1);
}
示例#11
0
static bool
svc_rdma_recv(SVCXPRT *xprt, struct svc_req *req)
{
	struct rpc_rdma_cbc *cbc = req->rq_context;
	XDR *xdrs = cbc->holdq.xdrs;

	__warnx(TIRPC_DEBUG_FLAG_SVC_RDMA,
		"%s() xprt %p cbc %p incoming xdr %p\n",
		__func__, xprt, cbc, xdrs);

	req->rq_msg = alloc_rpc_msg();

	if (!xdr_rdma_svc_recv(cbc, 0)){
		__warnx(TIRPC_DEBUG_FLAG_SVC_RDMA,
			"%s: xdr_rdma_svc_recv failed",
			__func__);
		return (FALSE);
	}
	xdrs->x_op = XDR_DECODE;

	/* No need, already positioned to beginning ...
	XDR_SETPOS(xdrs, 0);
	 */
	if (!xdr_dplx_decode(xdrs, req->rq_msg)) {
		__warnx(TIRPC_DEBUG_FLAG_SVC_RDMA,
			"%s: xdr_dplx_decode failed",
			__func__);
		return (FALSE);
	}

	req->rq_xprt = xprt;
	req->rq_prog = req->rq_msg->rm_call.cb_prog;
	req->rq_vers = req->rq_msg->rm_call.cb_vers;
	req->rq_proc = req->rq_msg->rm_call.cb_proc;
	req->rq_xid = req->rq_msg->rm_xid;
	req->rq_clntcred = req->rq_msg->rq_cred_body;

	/* the checksum */
	req->rq_cksum = 0;

	return (TRUE);
}
示例#12
0
int
_des_crypt_call(char *buf, int len, struct desparams *dparms)
{
	CLIENT *clnt;
	desresp  *result_1;
	desargs  des_crypt_1_arg;
	struct netconfig *nconf;
	void *localhandle;
	int stat;

	nconf = NULL;
	localhandle = setnetconfig();
	while ((nconf = getnetconfig(localhandle)) != NULL) {
		if (nconf->nc_protofmly != NULL &&
		     strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
			break;
	}
	if (nconf == NULL) {
		__warnx("getnetconfig: %s", nc_sperror());
		return(DESERR_HWERROR);
	}
	clnt = clnt_tp_ncreate(NULL, CRYPT_PROG, CRYPT_VERS, nconf);
	if (clnt == (CLIENT *) NULL) {
		endnetconfig(localhandle);
		return(DESERR_HWERROR);
	}
	endnetconfig(localhandle);

	des_crypt_1_arg.desbuf.desbuf_len = len;
	des_crypt_1_arg.desbuf.desbuf_val = buf;
	des_crypt_1_arg.des_dir = dparms->des_dir;
	des_crypt_1_arg.des_mode = dparms->des_mode;
	bcopy(dparms->des_ivec, des_crypt_1_arg.des_ivec, 8);
	bcopy(dparms->des_key, des_crypt_1_arg.des_key, 8);

	result_1 = des_crypt_1(&des_crypt_1_arg, clnt);
	if (result_1 == (desresp *) NULL) {
		clnt_destroy(clnt);
		return(DESERR_HWERROR);
	}

	stat = result_1->stat;

	if (result_1->stat == DESERR_NONE ||
	    result_1->stat == DESERR_NOHWDEVICE) {
		bcopy(result_1->desbuf.desbuf_val, buf, len);
		bcopy(result_1->des_ivec, dparms->des_ivec, 8);
	}

	clnt_freeres(clnt, (xdrproc_t)xdr_desresp, result_1);
	clnt_destroy(clnt);

	return(stat);
}
示例#13
0
/*
 * Create a unix style authenticator.
 * Returns an auth handle with the given stuff in it.
 */
AUTH *
authunix_ncreate(char *machname, uid_t uid, gid_t gid, int len,
		 gid_t *aup_gids)
{
	struct audata *au = mem_alloc(sizeof(*au));
	AUTH *auth = &au->au_auth;
	struct authunix_parms aup;
	struct timespec now;
	XDR xdrs;

	/*
	 * Allocate and set up auth handle
	 */
	auth->ah_ops = authunix_ops();
	auth->ah_private = NULL;
	auth->ah_error.re_status = RPC_SUCCESS;
	auth->ah_verf = au->au_shcred = _null_auth;
	auth->ah_refcnt = 1;
	au->au_shfaults = 0;

	/*
	 * fill in param struct from the given params
	 */
	(void)clock_gettime(CLOCK_MONOTONIC_FAST, &now);
	aup.aup_time = now.tv_sec;
	aup.aup_machname = machname;
	aup.aup_uid = uid;
	aup.aup_gid = gid;
	aup.aup_len = (u_int) len;
	aup.aup_gids = aup_gids;

	/*
	 * Serialize the parameters into origcred
	 */
	xdrmem_create(&xdrs, au->au_origcred.oa_body, MAX_AUTH_BYTES,
		      XDR_ENCODE);
	if (!xdr_authunix_parms(&xdrs, &aup)) {
		__warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: %s",
			__func__, clnt_sperrno(RPC_CANTENCODEARGS));
		auth->ah_error.re_status = RPC_CANTENCODEARGS;
		return (auth);
	}
	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
	au->au_origcred.oa_flavor = AUTH_UNIX;

	/*
	 * set auth handle to reflect new cred.
	 */
	auth->ah_cred = au->au_origcred;
	/* auth_get not needed:  ah_refcnt == 1, as desired */
	marshal_new_auth(auth);
	/* */
	return (auth);
}
示例#14
0
int32_t
rpc_dplx_unref(struct rpc_dplx_rec *rec, u_int flags)
{
    struct rbtree_x_part *t;
    struct opr_rbtree_node *nv;
    int32_t refcnt;

    if (! (flags & RPC_DPLX_FLAG_LOCKED))
        REC_LOCK(rec);

    refcnt = --(rec->refcnt);

    __warnx(TIRPC_DEBUG_FLAG_REFCNT,
            "%s: postunref %p rec->refcnt %u",
            __func__, rec, refcnt);

    if (rec->refcnt == 0) {
        t = rbtx_partition_of_scalar(&rpc_dplx_rec_set.xt, rec->fd_k);
        REC_UNLOCK(rec);
        rwlock_wrlock(&t->lock);
        nv = opr_rbtree_lookup(&t->t, &rec->node_k);
        rec = NULL;
        if (nv) {
            rec = opr_containerof(nv, struct rpc_dplx_rec, node_k);
            REC_LOCK(rec);
            if (rec->refcnt == 0) {
                (void) opr_rbtree_remove(&t->t, &rec->node_k);
                REC_UNLOCK(rec);
                __warnx(TIRPC_DEBUG_FLAG_REFCNT,
                        "%s: free rec %p rec->refcnt %u",
                        __func__, rec, refcnt);

                free_dplx_rec(rec);
                rec = NULL;
            } else {
                refcnt = rec->refcnt;
            }
        }
        rwlock_unlock(&t->lock);
    }
示例#15
0
/*
 * Create a client handle for memory based rpc.
 */
CLIENT *
clnt_raw_ncreate(rpcprog_t prog, rpcvers_t vers)
{
    struct clntraw_private *clp;
    struct rpc_msg call_msg;
    XDR *xdrs;
    CLIENT *client;

    mutex_lock(&clntraw_lock);
    clp = clntraw_private;
    if (clp == NULL) {
        clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
        if (clp == NULL) {
            mutex_unlock(&clntraw_lock);
            return NULL;
        }
        if (__rpc_rawcombuf == NULL)
            __rpc_rawcombuf =
                (char *)calloc(UDPMSGSIZE, sizeof (char));
        clp->_raw_buf = __rpc_rawcombuf;
        clntraw_private = clp;
    }
    xdrs = &clp->xdr_stream;
    client = &clp->client_object;
    /*
     * pre-serialize the static part of the call msg and stash it away
     */
    call_msg.rm_direction = CALL;
    call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
    /* XXX: prog and vers have been long historically :-( */
    call_msg.rm_call.cb_prog = (u_int32_t)prog;
    call_msg.rm_call.cb_vers = (u_int32_t)vers;
    xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
    if (! xdr_callhdr(xdrs, &call_msg))
        __warnx(TIRPC_DEBUG_FLAG_CLNT_RAW,
                "clntraw_create - Fatal header serialization error.");
    clp->mcnt = XDR_GETPOS(xdrs);
    XDR_DESTROY(xdrs);

    /*
     * Set xdrmem for client/server shared buffer
     */
    xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);

    /*
     * create client handle
     */
    client->cl_ops = clnt_raw_ops();
    mutex_unlock(&clntraw_lock);
    return (client);
}
示例#16
0
static int
svcauth_gss_validate(struct svc_req *req,
		     struct svc_rpc_gss_data *gd,
		     struct rpc_msg *msg)
{
	struct opaque_auth *oa;
	gss_buffer_desc rpcbuf, checksum;
	OM_uint32 maj_stat, min_stat, qop_state;
	u_char rpchdr[RPCHDR_LEN];
	int32_t *buf;

	memset(rpchdr, 0, RPCHDR_LEN);

	/* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */
	oa = &msg->rm_call.cb_cred;
	if (oa->oa_length > MAX_AUTH_BYTES)
		return GSS_S_CALL_BAD_STRUCTURE;
	/* XXX since MAX_AUTH_BYTES is 400, the following code trivially
	 * overruns (up to 431 per Coverity, but compare RPCHDR_LEN with
	 * what is marshalled below). */

	buf = (int32_t *) rpchdr;
	IXDR_PUT_LONG(buf, msg->rm_xid);
	IXDR_PUT_ENUM(buf, msg->rm_direction);
	IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers);
	IXDR_PUT_LONG(buf, msg->rm_call.cb_prog);
	IXDR_PUT_LONG(buf, msg->rm_call.cb_vers);
	IXDR_PUT_LONG(buf, msg->rm_call.cb_proc);
	IXDR_PUT_ENUM(buf, oa->oa_flavor);
	IXDR_PUT_LONG(buf, oa->oa_length);
	if (oa->oa_length) {
		memcpy((caddr_t) buf, oa->oa_base, oa->oa_length);
		buf += RNDUP(oa->oa_length) / sizeof(int32_t);
	}
	rpcbuf.value = rpchdr;
	rpcbuf.length = (u_char *) buf - rpchdr;

	checksum.value = msg->rm_call.cb_verf.oa_base;
	checksum.length = msg->rm_call.cb_verf.oa_length;

	maj_stat =
	    gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum, &qop_state);

	if (maj_stat != GSS_S_COMPLETE) {
		__warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: %d %d", __func__, maj_stat,
			min_stat);
		return (maj_stat);
	}
	return GSS_S_COMPLETE;
}
示例#17
0
/*
 * svc_rdma_ncreate: waits for connection request and returns transport
 */
SVCXPRT *
svc_rdma_ncreate(void *arg, const u_int sendsize, const u_int recvsize,
		 const u_int flags)
{
	struct svc_rdma_xdr *sm;
	struct sockaddr_storage *ss;
	RDMAXPRT *l_xprt = arg;
	RDMAXPRT *xprt = rpc_rdma_accept_wait(l_xprt, l_xprt->xa->timeout);

	if (!xprt) {
		__warnx(TIRPC_DEBUG_FLAG_ERROR,
			"%s:%u ERROR (return)",
			__func__, __LINE__);
		return (NULL);
	}

	sm = mem_zalloc(sizeof (*sm));

	sm->sm_xdrs.x_lib[1] = xprt;
	xprt->xprt.xp_p2 = sm;

	xprt->xprt.xp_flags = flags;
	/* fixme: put something here, but make it not work on fd operations. */
	xprt->xprt.xp_fd = -1;

	ss = (struct sockaddr_storage *)rdma_get_local_addr(xprt->cm_id);
	__rpc_set_address(&xprt->xprt.xp_local, ss, 0);

	ss = (struct sockaddr_storage *)rdma_get_peer_addr(xprt->cm_id);
	__rpc_set_address(&xprt->xprt.xp_remote, ss, 0);

	svc_rdma_ops(&xprt->xprt);

	if (xdr_rdma_create(&sm->sm_xdrs, xprt, sendsize, recvsize, flags)) {
		goto freedata;
	}

	if (rpc_rdma_accept_finalize(xprt)) {
		goto freedata;
	}

	return (&xprt->xprt);

freedata:
	mem_free(sm, sizeof (*sm));
	xprt->xprt.xp_p2 = NULL;
	xprt_unregister(&xprt->xprt);
	return (NULL);
}
示例#18
0
rpc_ctx_t *
alloc_rpc_call_ctx(CLIENT *clnt, rpcproc_t proc, xdrproc_t xdr_args,
                   void *args_ptr, xdrproc_t xdr_results, void *results_ptr,
                   struct timeval timeout)
{
    struct x_vc_data *xd = (struct x_vc_data *) clnt->cl_p1;
    struct rpc_dplx_rec *rec = xd->rec;
    rpc_ctx_t *ctx;

    ctx = mem_alloc(sizeof(rpc_ctx_t));
    if (! ctx)
        goto out;

    /* potects this */
    mutex_init(&ctx->we.mtx, NULL);
    cond_init(&ctx->we.cv, 0, NULL);

    /* rec->calls and rbtree protected by (adaptive) mtx */
    mutex_lock(&rec->mtx);

    /* XXX we hold the client-fd lock */
    ctx->xid = ++(xd->cx.calls.xid);

    /* some of this looks like overkill;  it's here to support future,
     * fully async calls */
    ctx->ctx_u.clnt.clnt = clnt;
    ctx->ctx_u.clnt.timeout.tv_sec = 0;
    ctx->ctx_u.clnt.timeout.tv_nsec = 0;
    timespec_addms(&ctx->ctx_u.clnt.timeout, tv_to_ms(&timeout));
    ctx->msg = alloc_rpc_msg();
    ctx->flags = 0;

    /* stash it */
    if (opr_rbtree_insert(&xd->cx.calls.t, &ctx->node_k)) {
        __warnx(TIRPC_DEBUG_FLAG_RPC_CTX,
                "%s: call ctx insert failed (xid %d client %p)",
                __func__,
                ctx->xid, clnt);
        mutex_unlock(&rec->mtx);
        mem_free(ctx, sizeof(rpc_ctx_t));
        ctx = NULL;
        goto out;
    }

    mutex_unlock(&rec->mtx);

out:
    return (ctx);
}
示例#19
0
/*
 * XDR counted bytes
 * *cpp is a pointer to the bytes, *sizep is the count.
 * If *cpp is NULL maxsize bytes are allocated
 */
bool
xdr_bytes(XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize)
{
    char *sp = *cpp;  /* sp is the actual string pointer */
    u_int nodesize;

    /*
     * first deal with the length since xdr bytes are counted
     */
    if (! xdr_u_int(xdrs, sizep)) {
        return (FALSE);
    }
    nodesize = *sizep;
    if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
        return (FALSE);
    }

    /*
     * now deal with the actual bytes
     */
    switch (xdrs->x_op) {

    case XDR_DECODE:
        if (nodesize == 0) {
            return (TRUE);
        }
        if (sp == NULL) {
            *cpp = sp = mem_alloc(nodesize);
        }
        if (sp == NULL) {
            __warnx(TIRPC_DEBUG_FLAG_XDR,
                    "xdr_bytes: out of memory");
            return (FALSE);
        }
        /* FALLTHROUGH */

    case XDR_ENCODE:
        return (xdr_opaque(xdrs, sp, nodesize));

    case XDR_FREE:
        if (sp != NULL) {
            mem_free(sp, nodesize);
            *cpp = NULL;
        }
        return (TRUE);
    }
    /* NOTREACHED */
    return (FALSE);
}
示例#20
0
 /*ARGSUSED*/
static bool
authdes_refresh(AUTH *auth, void *dummy)
{
/* LINTED pointer alignment */
	struct ad_private *ad = AUTH_PRIVATE(auth);
	struct authdes_cred *cred = &ad->ad_cred;
	int ok;
	netobj pkey;

	if (ad->ad_dosync) {
		ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr,
					   ad->ad_timehost, &(ad->ad_uaddr),
					   &(ad->ad_netid));
		if (!ok) {
			/*
			 * Hope the clocks are synced!
			 */
			ad->ad_dosync = 0;
			__warnx(TIRPC_DEBUG_FLAG_AUTH,
				"authdes_refresh: unable to synchronize clock");
		}
	}
	ad->ad_xkey = auth->ah_key;
	pkey.n_bytes = (char *)(ad->ad_pkey);
	pkey.n_len = (u_int) strlen((char *)ad->ad_pkey) + 1;
	if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
		__warnx(TIRPC_DEBUG_FLAG_AUTH,
			"authdes_refresh: keyserv(1m) is unable to encrypt "
			"session key");
		return (false);
	}
	cred->adc_fullname.key = ad->ad_xkey;
	cred->adc_namekind = ADN_FULLNAME;
	cred->adc_fullname.name = ad->ad_fullname;
	return (true);
}
示例#21
0
/*
 * Marshals (pre-serializes) an auth struct.
 * sets private data, au_marshed and au_mpos
 */
static void
marshal_new_auth(AUTH *auth)
{
	XDR xdrs[1];
	struct audata *au = AUTH_PRIVATE(auth);

	assert(auth != NULL);

	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
	if ((!xdr_opaque_auth_encode(xdrs, &(auth->ah_cred)))
	    || (!xdr_opaque_auth_encode(xdrs, &(auth->ah_verf))))
		__warnx(TIRPC_DEBUG_FLAG_AUTH,
			"auth_none.c - Fatal marshalling " "problem");
	else
		au->au_mpos = XDR_GETPOS(xdrs);
	XDR_DESTROY(xdrs);
}
示例#22
0
/*
 * reads data from the tcp or udp connection.
 * any error is fatal and the connection is closed.
 * (And a read of zero bytes is a half closed stream => error.)
 * All read operations timeout after 35 seconds.  A timeout is
 * fatal for the connection.
 */
static inline size_t
svc_readv_vc(XDR *xdrs, void *ctp, struct iovec *iov, int iovcnt,
             u_int flags)
{
    SVCXPRT *xprt;
    int milliseconds = 35 * 1000; /* XXX shouldn't this be configurable? */
    struct pollfd pollfd;
    struct x_vc_data *xd;
    size_t nbytes = -1;

    xd = (struct x_vc_data *) ctp;
    xprt = xd->rec->hdl.xprt;

    do {
        pollfd.fd = xprt->xp_fd;
        pollfd.events = POLLIN;
        pollfd.revents = 0;
        switch (poll(&pollfd, 1, milliseconds)) {
        case -1:
            if (errno == EINTR)
                continue;
            /*FALLTHROUGH*/
        case 0:
            __warnx(TIRPC_DEBUG_FLAG_SVC_VC,
                    "%s: poll returns 0 (will set dead)",
                    __func__);
            goto fatal_err;
        default:
            break;
        }
    } while ((pollfd.revents & POLLIN) == 0);

    if ((nbytes = readv(xprt->xp_fd, iov, iovcnt)) > 0) {
        (void) clock_gettime(CLOCK_MONOTONIC_FAST, &xd->sx.last_recv);
        goto out;
    }

fatal_err:
    cfconn_set_dead(xprt, xd);
out:
    return (nbytes);
}
示例#23
0
static void
svc_rdma_destroy(SVCXPRT *xprt, u_int flags, const char *tag, const int line)
{
	struct svc_rdma_xdr *sm = sm_data(xprt);

	__warnx(TIRPC_DEBUG_FLAG_REFCNT,
		"%s() %p xp_refs %" PRId32
		" should actually destroy things @ %s:%d",
		__func__, xprt, xprt->xp_refs, tag, line);

	xdr_rdma_destroy(&(sm->sm_xdrs));
	mem_free(sm, sizeof (*sm));

	if (xprt->xp_ops->xp_free_user_data) {
		/* call free hook */
		xprt->xp_ops->xp_free_user_data(xprt);
	}

	rpc_rdma_destroy(xprt);
}
示例#24
0
AUTH *
authdes_nseccreate(const char *servername, const u_int win,
		   const char *timehost, const des_block *ckey)
{
	u_char pkey_data[1024];
	netobj pkey;
	AUTH *dummy;

	if (!getpublickey(servername, (char *)pkey_data)) {
		__warnx(TIRPC_DEBUG_FLAG_AUTH,
			"authdes_nseccreate: no public key found for %s",
			servername);
		return (NULL);
	}

	pkey.n_bytes = (char *)pkey_data;
	pkey.n_len = (u_int) strlen((char *)pkey_data) + 1;
	dummy =
	    authdes_pk_nseccreate(servername, &pkey, win, timehost, ckey, NULL);
	return (dummy);
}
示例#25
0
/*
 * writes data to the tcp connection.
 * Any error is fatal and the connection is closed.
 */
static size_t
svc_writev_vc(XDR *xdrs, void *ctp, struct iovec *iov, int iovcnt,
              u_int flags)
{
    SVCXPRT *xprt;
    struct x_vc_data *xd;
    size_t nbytes;

    xd = (struct x_vc_data *) ctp;
    xprt = xd->rec->hdl.xprt;

    nbytes = writev(xprt->xp_fd, iov, iovcnt);
    if (nbytes  < 0) {
        __warnx(TIRPC_DEBUG_FLAG_SVC_VC,
                "%s: short writev (will set dead)",
                __func__);
        cfconn_set_dead(xprt, xd);
        return (-1);
    }

    return (nbytes);
}
示例#26
0
文件: svc_dg.c 项目: linuxbox2/ntirpc
static void
svc_dg_destroy_task(struct work_pool_entry *wpe)
{
	struct rpc_dplx_rec *rec =
			opr_containerof(wpe, struct rpc_dplx_rec, ioq.ioq_wpe);
	uint16_t xp_flags;

	__warnx(TIRPC_DEBUG_FLAG_REFCNT,
		"%s() %p fd %d xp_refs %" PRIu32,
		__func__, rec, rec->xprt.xp_fd, rec->xprt.xp_refs);

	if (rec->xprt.xp_refs) {
		/* instead of nanosleep */
		work_pool_submit(&svc_work_pool, &(rec->ioq.ioq_wpe));
		return;
	}

	xp_flags = atomic_postclear_uint16_t_bits(&rec->xprt.xp_flags,
						  SVC_XPRT_FLAG_CLOSE);
	if ((xp_flags & SVC_XPRT_FLAG_CLOSE)
	    && rec->xprt.xp_fd != RPC_ANYFD) {
		(void)close(rec->xprt.xp_fd);
		rec->xprt.xp_fd = RPC_ANYFD;
	}

	if (rec->xprt.xp_ops->xp_free_user_data)
		rec->xprt.xp_ops->xp_free_user_data(&rec->xprt);

	if (rec->xprt.xp_tp)
		mem_free(rec->xprt.xp_tp, 0);
	if (rec->xprt.xp_netid)
		mem_free(rec->xprt.xp_netid, 0);

	if (rec->xprt.xp_parent)
		SVC_RELEASE(rec->xprt.xp_parent, SVC_RELEASE_FLAG_NONE);

	svc_dg_xprt_free(DG_DR(rec));
}
示例#27
0
void rpc_ctx_next_xid(rpc_ctx_t *ctx, uint32_t flags)
{
    struct x_vc_data *xd = (struct x_vc_data *) ctx->ctx_u.clnt.clnt->cl_p1;
    struct rpc_dplx_rec *rec = xd->rec;

    assert (flags & RPC_CTX_FLAG_LOCKED);

    mutex_lock(&rec->mtx);
    opr_rbtree_remove(&xd->cx.calls.t, &ctx->node_k);
    ctx->xid = ++(xd->cx.calls.xid);
    if (opr_rbtree_insert(&xd->cx.calls.t, &ctx->node_k)) {
        mutex_unlock(&rec->mtx);
        __warnx(TIRPC_DEBUG_FLAG_RPC_CTX,
                "%s: call ctx insert failed (xid %d client %p)",
                __func__,
                ctx->xid,
                ctx->ctx_u.clnt.clnt);
        goto out;
    }
    mutex_unlock(&rec->mtx);
out:
    return;
}
示例#28
0
void rpc_dplx_init()
{
    int code = 0;

    /* XXX */
    mutex_lock(&rpc_dplx_rec_set.clnt_fd_lock);

    if (initialized)
        goto unlock;

    /* one of advantages of this RBT is convenience of external
     * iteration, we'll go to that shortly */
    code = rbtx_init(&rpc_dplx_rec_set.xt, rpc_dplx_cmpf /* NULL (inline) */,
                     RPC_DPLX_PARTITIONS, RBT_X_FLAG_ALLOC);
    if (code)
        __warnx(TIRPC_DEBUG_FLAG_LOCK,
                "rpc_dplx_init: rbtx_init failed");

    initialized = TRUE;

unlock:
    mutex_unlock(&rpc_dplx_rec_set.clnt_fd_lock);
}
示例#29
0
int
__rpc_raise_fd(int fd)
{
	int nfd;

	if (fd >= __rpc_minfd)
		return (fd);

	if ((nfd = fcntl(fd, F_DUPFD, __rpc_minfd)) == -1)
		return (fd);

	if (fsync(nfd) == -1) {
		close(nfd);
		return (fd);
	}

	if (close(fd) == -1) {
	    /* this is okay, we will log an error, then use the new fd */
	    __warnx("could not close() fd %d; mem & fd leak", fd);
	}

	return (nfd);
}
示例#30
0
SVCXPRT *
svc_dg_ncreate(int fd, u_int sendsize, u_int recvsize)
{
    SVCXPRT *xprt;
    struct svc_dg_data *su = NULL;
    struct __rpc_sockinfo si;
    struct sockaddr_storage ss;
    socklen_t slen;
    uint32_t oflags;

    if (!__rpc_fd2sockinfo(fd, &si)) {
        __warnx(TIRPC_DEBUG_FLAG_SVC_DG,
                svc_dg_str, svc_dg_err1);
        return (NULL);
    }
    /*
     * Find the receive and the send size
     */
    sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
    recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
    if ((sendsize == 0) || (recvsize == 0)) {
        __warnx(TIRPC_DEBUG_FLAG_SVC_DG,
                svc_dg_str, svc_dg_err2);
        return (NULL);
    }

    xprt = mem_alloc(sizeof (SVCXPRT));
    if (xprt == NULL)
        goto freedata;
    memset(xprt, 0, sizeof (SVCXPRT));

    /* Init SVCXPRT locks, etc */
    mutex_init(&xprt->xp_lock, NULL);
    mutex_init(&xprt->xp_auth_lock, NULL);

    su = mem_alloc(sizeof (*su));
    if (su == NULL)
        goto freedata;
    su->su_iosz = ((MAX(sendsize, recvsize) + 3) / 4) * 4;
    if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL)
        goto freedata;
    xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz,
                  XDR_DECODE);

    su->su_cache = NULL;
    xprt->xp_flags = SVC_XPRT_FLAG_NONE;
    xprt->xp_refcnt = 1;
    xprt->xp_fd = fd;
    xprt->xp_p2 = su;
    svc_dg_ops(xprt);
    xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);

    slen = sizeof ss;
    if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
        goto freedata;

    __rpc_set_netbuf(&xprt->xp_ltaddr, &ss, slen);

    switch (ss.ss_family) {
    case AF_INET:
        xprt->xp_port = ntohs(((struct sockaddr_in *) &ss)->sin_port);
        break;
#ifdef INET6
    case AF_INET6:
        xprt->xp_port = ntohs(((struct sockaddr_in6 *) &ss)->sin6_port);
        break;
#endif
    case AF_LOCAL:
        /* no port */
        break;
    default:
        break;
    }

    /* Enable reception of IP*_PKTINFO control msgs */
    svc_dg_enable_pktinfo(fd, &si);

    /* Make reachable */
    xprt->xp_p5 = rpc_dplx_lookup_rec(xprt->xp_fd,
                                      RPC_DPLX_FLAG_NONE, &oflags); /* ref+1 */
    svc_rqst_init_xprt(xprt);

    /* Conditional xprt_register */
    if (! (__svc_params->flags & SVC_FLAG_NOREG_XPRTS))
        xprt_register(xprt);

    return (xprt);
freedata:
    __warnx(TIRPC_DEBUG_FLAG_SVC_DG,
            svc_dg_str, __no_mem_str);
    if (xprt) {
        if (su)
            (void) mem_free(su, sizeof (*su));
        svc_rqst_finalize_xprt(xprt, SVC_RQST_FLAG_NONE);
        (void) mem_free(xprt, sizeof (SVCXPRT));
    }
    return (NULL);
}