コード例 #1
0
ファイル: msg-nfs3.c プロジェクト: lkzhd/glusterfs-annotation
/* Decode the mount path from the network message in inmsg
 * into the memory referenced by outpath.iov_base.
 * The size allocated for outpath.iov_base is outpath.iov_len.
 * The size of the path extracted from the message is returned.
 */
ssize_t
xdr_to_mountpath (struct iovec outpath, struct iovec inmsg)
{
    XDR     xdr;
    ssize_t ret = -1;
    char    *mntpath = NULL;

    if ((!outpath.iov_base) || (!inmsg.iov_base))
        return -1;

    xdrmem_create (&xdr, inmsg.iov_base, (unsigned int)inmsg.iov_len,
                   XDR_DECODE);

    mntpath = outpath.iov_base;
    if (!xdr_dirpath (&xdr, (dirpath *)&mntpath)) {
        ret = -1;
        goto ret;
    }

    ret = xdr_decoded_length (xdr);

ret:
    return ret;
}
コード例 #2
0
gboolean gvir_sandbox_rpcpacket_encode_payload_raw(GVirSandboxRPCPacket *msg,
                                                   const char *data,
                                                   gsize len,
                                                   GError **error)
{
    XDR xdr;
    unsigned int msglen;

    if ((msg->bufferLength - msg->bufferOffset) < len) {
        g_set_error(error, 0, 0,
                    "Raw data too long to send (%zu bytes needed, %zu bytes available)",
                    len, (msg->bufferLength - msg->bufferOffset));
        return FALSE;
    }

    memcpy(msg->buffer + msg->bufferOffset, data, len);
    msg->bufferOffset += len;

    /* Re-encode the length word. */
    xdrmem_create(&xdr, msg->buffer, GVIR_SANDBOX_PROTOCOL_LEN_MAX, XDR_ENCODE);
    msglen = msg->bufferOffset;
    if (!xdr_u_int(&xdr, &msglen)) {
        g_set_error(error, 0, 0,
                    "%s", "Unable to encode message length");
        goto error;
    }
    xdr_destroy(&xdr);

    msg->bufferLength = msg->bufferOffset;
    msg->bufferOffset = 0;
    return TRUE;

error:
    xdr_destroy(&xdr);
    return FALSE;
}
コード例 #3
0
gboolean gvir_sandbox_rpcpacket_encode_payload_empty(GVirSandboxRPCPacket *msg,
                                                     GError **error)
{
    XDR xdr;
    unsigned int msglen;

    /* Re-encode the length word. */
    xdrmem_create(&xdr, msg->buffer, GVIR_SANDBOX_PROTOCOL_LEN_MAX, XDR_ENCODE);
    msglen = msg->bufferOffset;
    if (!xdr_u_int(&xdr, &msglen)) {
        g_set_error(error, 0, 0,
                    "%s", "Unable to encode message length");
        goto error;
    }
    xdr_destroy(&xdr);

    msg->bufferLength = msg->bufferOffset;
    msg->bufferOffset = 0;
    return TRUE;

error:
    xdr_destroy(&xdr);
    return FALSE;
}
コード例 #4
0
ファイル: nfs3.c プロジェクト: shehjart/unfsclient
RMDIR3args * 
xdr_to_RMDIR3args(char *msg, int len)
{
	RMDIR3args *args = NULL;
	XDR xdr;

	if(msg == NULL)
		return NULL;

	args = (RMDIR3args *)mem_alloc(sizeof(RMDIR3args));
	if(args == NULL)
		return NULL;
	
	xdrmem_create(&xdr, msg, len, XDR_DECODE);
	
	args->object.dir.data.data_val = NULL;
	args->object.name = NULL;
	if(!xdr_RMDIR3args(&xdr, args)) {
		mem_free(args, sizeof(RMDIR3args));
		return NULL;
	}

	return args;
}
コード例 #5
0
ファイル: nfs3.c プロジェクト: shehjart/unfsclient
MKNOD3args * 
xdr_to_MKNOD3args(char *msg, int len)
{
	MKNOD3args *args = NULL;
	XDR xdr;

	if(msg == NULL)
		return NULL;

	args = (MKNOD3args *)mem_alloc(sizeof(MKNOD3args));
	if(args == NULL)
		return NULL;
	
	xdrmem_create(&xdr, msg, len, XDR_DECODE);
	
	args->where.dir.data.data_val = NULL;
	args->where.name = NULL;
	if(!xdr_MKNOD3args(&xdr, args)) {
		mem_free(args, sizeof(MKNOD3args));
		return NULL;
	}

	return args;
}
コード例 #6
0
ファイル: virnetmessage.c プロジェクト: aruiz/libvirt
int virNetMessageDecodeNumFDs(virNetMessagePtr msg)
{
    XDR xdr;
    unsigned int numFDs;
    int ret = -1;
    size_t i;

    xdrmem_create(&xdr, msg->buffer + msg->bufferOffset,
                  msg->bufferLength - msg->bufferOffset, XDR_DECODE);
    if (!xdr_u_int(&xdr, &numFDs)) {
        virReportError(VIR_ERR_RPC, "%s", _("Unable to decode number of FDs"));
        goto cleanup;
    }
    msg->bufferOffset += xdr_getpos(&xdr);

    if (numFDs > VIR_NET_MESSAGE_NUM_FDS_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("Received too many FDs %d, expected %d maximum"),
                       numFDs, VIR_NET_MESSAGE_NUM_FDS_MAX);
        goto cleanup;
    }

    msg->nfds = numFDs;
    if (VIR_ALLOC_N(msg->fds, msg->nfds) < 0)
        goto cleanup;
    for (i = 0; i < msg->nfds; i++)
        msg->fds[i] = -1;

    VIR_DEBUG("Got %zu FDs from peer", msg->nfds);

    ret = 0;

 cleanup:
    xdr_destroy(&xdr);
    return ret;
}
コード例 #7
0
ファイル: xdr-rpc.c プロジェクト: gluster/glusterfs
int
rpc_reply_to_xdr(struct rpc_msg *reply, char *dest, size_t len,
                 struct iovec *dst)
{
    XDR xdr;
    int ret = -1;

    GF_VALIDATE_OR_GOTO("rpc", reply, out);
    GF_VALIDATE_OR_GOTO("rpc", dest, out);
    GF_VALIDATE_OR_GOTO("rpc", dst, out);

    xdrmem_create(&xdr, dest, len, XDR_ENCODE);
    if (!xdr_replymsg(&xdr, reply)) {
        gf_log("rpc", GF_LOG_WARNING, "failed to encode reply msg");
        goto out;
    }

    dst->iov_base = dest;
    dst->iov_len = xdr_encoded_length(xdr);

    ret = 0;
out:
    return ret;
}
コード例 #8
0
ファイル: xdrutil.c プロジェクト: AlissonGiron/open-vm-tools
Bool
XdrUtil_Deserialize(const void *data,  // IN
                    size_t dataLen,    // IN
                    void *xdrProc,     // IN
                    void *dest)        // IN
{
   Bool ret;
   xdrproc_t proc = xdrProc;
   XDR xdrs;

   ASSERT(data != NULL);
   ASSERT(xdrProc != NULL);
   ASSERT(dest != NULL);

   xdrmem_create(&xdrs, (char *) data, dataLen, XDR_DECODE);
   ret = (Bool) proc(&xdrs, dest, 0);
   xdr_destroy(&xdrs);

   if (!ret) {
      VMX_XDR_FREE(proc, dest);
   }

   return ret;
}
コード例 #9
0
ファイル: auth_none.c プロジェクト: apprisi/illumos-gate
AUTH *
authnone_create(void)
{
	struct authnone_private *ap = authnone_private;
	XDR xdr_stream;
	XDR *xdrs;

	if (ap == 0) {
		ap = &authnone_local;
		authnone_private = ap;
	}
	if (!ap->mcnt) {
		ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
		ap->no_client.ah_ops = authnone_ops();
		xdrs = &xdr_stream;
		xdrmem_create(xdrs, ap->marshalled_client,
			(uint_t)MAX_MARSHEL_SIZE, XDR_ENCODE);
		(void) xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
		(void) xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
		ap->mcnt = XDR_GETPOS(xdrs);
		XDR_DESTROY(xdrs);
	}
	return (&ap->no_client);
}
コード例 #10
0
ファイル: lib.rtask.c プロジェクト: FSchumacher/openlava
int
rgetpidCompletionHandler_(struct lsRequest *request)
{
    struct resPid pidReply;
    XDR xdrs;
    int rc;


    rc = resRC2LSErr_(request->rc);
    if (rc != 0)
	return(-1);

    xdrmem_create(&xdrs, request->replyBuf, sizeof(struct resPid), XDR_DECODE);
    if (! xdr_resGetpid(&xdrs, &pidReply, NULL)) {
	lserrno = LSE_BAD_XDR;
	xdr_destroy(&xdrs);
	return(-1);
    }

    *((int *)request->extra) = pidReply.pid;
    xdr_destroy(&xdrs);
    return(0);

}
コード例 #11
0
ファイル: expgw_rpc_generic.c プロジェクト: dcasier/rozofs
/**
* ROZOFS Generic RPC Request transaction in non-blocking mode

 That service initiates RPC call towards the destination referenced by its associated load balancing group
 WHen the transaction is started, the application will received the response thanks the provided callback

 The first parameter is a user dependent reference and the second pointer is the pointer to the decoded
 area.
 In case of decoding error, transmission error, the second pointer is NULL and errno is asserted with the
 error.

 The array provided for decoding the response might be a static variable within  the user context or
 can be an allocated array. If that array has be allocated by the application it is up to the application
 to release it

 @param lbg_id     : reference of the load balancing group of the exportd
 @param prog       : program
 @param vers       : program version
 @param opcode     : metadata opcode
 @param encode_fct : encoding function
 @param msg2encode_p     : pointer to the message to encode
 @param decode_fct  : xdr function for message decoding
 @param ret: pointer to the array that is used for message decoding
 @parem ret_len : length of the array used for decoding
 @param recv_cbk   : receive callback function (for interpretation of the rpc result
 @param ctx_p      : pointer to the user context

 @retval 0 on success;
 @retval -1 on error,, errno contains the cause
 */
int rozofs_rpc_non_blocking_req_send (int lbg_id,uint32_t prog,uint32_t vers,
                                      int opcode,xdrproc_t encode_fct,void *msg2encode_p,
                                      xdrproc_t decode_fct,
                                      sys_recv_pf_t recv_cbk,void *ctx_p,
                                      void *ret,int ret_len)
{
    DEBUG_FUNCTION;

    uint8_t           *arg_p;
    uint32_t          *header_size_p;
    rozofs_tx_ctx_t   *rozofs_tx_ctx_p = NULL;
    void              *xmit_buf = NULL;
    int               bufsize;
    int               ret;
    int               position;
    XDR               xdrs;
    struct rpc_msg   call_msg;
    uint32_t         null_val = 0;

    rozofs_tx_rpc_ctx_t *rpc_ctx_p = NULL;

    /*
    ** allocate a rpc context
    */
    rozofs_rpc_p = rozofs_rpc_req_alloc();
    if (rozofs_rpc_p == NULL)
    {
        /*
        ** out of context
        */
        errno = ENOMEM;
        goto error;
    }
    /*
    ** save the rpc parameter of the caller
    */
    rpc_ctx_p = &rozofs_tx_ctx_p->rpc_ctx;
    rpc_ctx_p->user_ref   = ctx_p;       /* save the user reference of the caller   */
    rpc_ctx_p->xdr_result = decode_fct;  /* save the decoding procedure  */
    rpc_ctx_p->response_cbk = recv_cbk ;
    rpc_ctx_p->ret_len  = ret_len;
    rpc_ctx_p->ret_p  = ret;
    START_RPC_REQ_PROFILING_START(rpc_ctx_p);
    /*
    ** allocate a transaction context
    */
    rozofs_tx_ctx_p = rozofs_tx_alloc();
    if (rozofs_tx_ctx_p == NULL)
    {
        /*
        ** out of context
        ** --> put a pending list for the future to avoid repluing ENOMEM
        */
        TX_STATS(ROZOFS_TX_NO_CTX_ERROR);
        errno = ENOMEM;
        goto error;
    }

    /*
    ** allocate an xmit buffer
    */
    xmit_buf = ruc_buf_getBuffer(ROZOFS_TX_LARGE_TX_POOL);
    if (xmit_buf == NULL)
    {
        /*
        ** something rotten here, we exit we an error
        ** without activating the FSM
        */
        TX_STATS(ROZOFS_TX_NO_BUFFER_ERROR);
        errno = ENOMEM;
        goto error;
    }
    /*
    ** store the reference of the xmit buffer in the transaction context: might be useful
    ** in case we want to remove it from a transmit list of the underlying network stacks
    */
    rozofs_tx_save_xmitBuf(rozofs_tx_ctx_p,xmit_buf);
    /*
    ** get the pointer to the payload of the buffer
    */
    header_size_p  = (uint32_t*) ruc_buf_getPayload(xmit_buf);
    arg_p = (uint8_t*)(header_size_p+1);
    /*
    ** create the xdr_mem structure for encoding the message
    */
    bufsize = ruc_buf_getMaxPayloadLen(xmit_buf);
    xdrmem_create(&xdrs,(char*)arg_p,bufsize,XDR_ENCODE);
    /*
    ** fill in the rpc header
    */
    call_msg.rm_direction = CALL;
    /*
    ** allocate a xid for the transaction
    */
    call_msg.rm_xid             = rozofs_tx_alloc_xid(rozofs_tx_ctx_p);
    call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
    /* XXX: prog and vers have been long historically :-( */
    call_msg.rm_call.cb_prog = (uint32_t)prog;
    call_msg.rm_call.cb_vers = (uint32_t)vers;
    if (! xdr_callhdr(&xdrs, &call_msg))
    {
        /*
        ** THIS MUST NOT HAPPEN
        */
        TX_STATS(ROZOFS_TX_ENCODING_ERROR);
        errno = EPROTO;
        goto error;
    }
    /*
    ** insert the procedure number, NULL credential and verifier
    */
    XDR_PUTINT32(&xdrs, (int32_t *)&opcode);
    XDR_PUTINT32(&xdrs, (int32_t *)&null_val);
    XDR_PUTINT32(&xdrs, (int32_t *)&null_val);
    XDR_PUTINT32(&xdrs, (int32_t *)&null_val);
    XDR_PUTINT32(&xdrs, (int32_t *)&null_val);

    /*
    ** ok now call the procedure to encode the message
    */
    if ((*encode_fct)(&xdrs,msg2encode_p) == FALSE)
    {
        TX_STATS(ROZOFS_TX_ENCODING_ERROR);
        errno = EPROTO;
        goto error;
    }
    /*
    ** Now get the current length and fill the header of the message
    */
    position = XDR_GETPOS(&xdrs);
    /*
    ** update the length of the message : must be in network order
    */
    *header_size_p = htonl(0x80000000 | position);
    /*
    ** set the payload length in the xmit buffer
    */
    int total_len = sizeof(*header_size_p)+ position;
    ruc_buf_setPayloadLen(xmit_buf,total_len);
    /*
    ** store the receive call back and its associated parameter
    */
    rozofs_tx_ctx_p->recv_cbk   = rozofs_rpc_generic_reply_cbk;
    rozofs_tx_ctx_p->user_param = rpc_ctx_p;
    /*
    ** now send the message
    */
    ret = north_lbg_send(lbg_id,xmit_buf);
    if (ret < 0)
    {
        TX_STATS(ROZOFS_TX_SEND_ERROR);
        errno = EFAULT;
        goto error;
    }
    TX_STATS(ROZOFS_TX_SEND);

    /*
    ** OK, so now finish by starting the guard timer
    */
    rozofs_tx_start_timer(rozofs_tx_ctx_p, 25);
    return 0;

error:
    if (rozofs_tx_ctx_p != NULL) rozofs_tx_free_from_ptr(rozofs_tx_ctx_p);
    if (rpc_ctx_p != NULL) rozofs_rpc_req_free(rpc_ctx_p);
    return -1;
}
コード例 #12
0
ファイル: svc_dg.c プロジェクト: vganapathi/ntirpc
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);
}
コード例 #13
0
ファイル: clnt_vc.c プロジェクト: ngkaho1234/freebsd
/*
 * Create a client handle for a connection.
 * Default options are set, which the user can change using clnt_control()'s.
 * The rpc/vc package does buffering similar to stdio, so the client
 * must pick send and receive buffer sizes, 0 => use the default.
 * NB: fd is copied into a private area.
 * NB: The rpch->cl_auth is set null authentication. Caller may wish to
 * set this something more useful.
 *
 * fd should be an open socket
 *
 * fd - open file descriptor
 * raddr - servers address
 * prog  - program number
 * vers  - version number
 * sendsz - buffer send size
 * recvsz - buffer recv size
 */
CLIENT *
clnt_vc_create(int fd, const struct netbuf *raddr, const rpcprog_t prog,
    const rpcvers_t vers, u_int sendsz, u_int recvsz)
{
	CLIENT *cl;			/* client handle */
	struct ct_data *ct = NULL;	/* client handle */
	struct timeval now;
	struct rpc_msg call_msg;
	static u_int32_t disrupt;
	sigset_t mask;
	sigset_t newmask;
	struct sockaddr_storage ss;
	socklen_t slen;
	struct __rpc_sockinfo si;

	if (disrupt == 0)
		disrupt = (u_int32_t)(long)raddr;

	cl = (CLIENT *)mem_alloc(sizeof (*cl));
	ct = (struct ct_data *)mem_alloc(sizeof (*ct));
	if ((cl == (CLIENT *)NULL) || (ct == (struct ct_data *)NULL)) {
		(void) syslog(LOG_ERR, clnt_vc_errstr,
		    clnt_vc_str, __no_mem_str);
		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
		rpc_createerr.cf_error.re_errno = errno;
		goto err;
	}
	ct->ct_addr.buf = NULL;
	sigfillset(&newmask);
	thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
	mutex_lock(&clnt_fd_lock);
	if (vc_fd_locks == (int *) NULL) {
		int cv_allocsz, fd_allocsz;
		int dtbsize = __rpc_dtbsize();

		fd_allocsz = dtbsize * sizeof (int);
		vc_fd_locks = (int *) mem_alloc(fd_allocsz);
		if (vc_fd_locks == (int *) NULL) {
			mutex_unlock(&clnt_fd_lock);
			thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
			goto err;
		} else
			memset(vc_fd_locks, '\0', fd_allocsz);

		assert(vc_cv == (cond_t *) NULL);
		cv_allocsz = dtbsize * sizeof (cond_t);
		vc_cv = (cond_t *) mem_alloc(cv_allocsz);
		if (vc_cv == (cond_t *) NULL) {
			mem_free(vc_fd_locks, fd_allocsz);
			vc_fd_locks = (int *) NULL;
			mutex_unlock(&clnt_fd_lock);
			thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
			goto err;
		} else {
			int i;

			for (i = 0; i < dtbsize; i++)
				cond_init(&vc_cv[i], 0, (void *) 0);
		}
	} else
		assert(vc_cv != (cond_t *) NULL);

	/*
	 * XXX - fvdl connecting while holding a mutex?
	 */
	slen = sizeof ss;
	if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
		if (errno != ENOTCONN) {
			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
			rpc_createerr.cf_error.re_errno = errno;
			mutex_unlock(&clnt_fd_lock);
			thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
			goto err;
		}
		if (_connect(fd, (struct sockaddr *)raddr->buf, raddr->len) < 0){
			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
			rpc_createerr.cf_error.re_errno = errno;
			mutex_unlock(&clnt_fd_lock);
			thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
			goto err;
		}
	}
	mutex_unlock(&clnt_fd_lock);
	thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
	if (!__rpc_fd2sockinfo(fd, &si))
		goto err;

	ct->ct_closeit = FALSE;

	/*
	 * Set up private data struct
	 */
	ct->ct_fd = fd;
	ct->ct_wait.tv_usec = 0;
	ct->ct_waitset = FALSE;
	ct->ct_addr.buf = malloc(raddr->maxlen);
	if (ct->ct_addr.buf == NULL)
		goto err;
	memcpy(ct->ct_addr.buf, raddr->buf, raddr->len);
	ct->ct_addr.len = raddr->len;
	ct->ct_addr.maxlen = raddr->maxlen;

	/*
	 * Initialize call message
	 */
	(void)gettimeofday(&now, NULL);
	call_msg.rm_xid = ((u_int32_t)++disrupt) ^ __RPC_GETXID(&now);
	call_msg.rm_direction = CALL;
	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
	call_msg.rm_call.cb_prog = (u_int32_t)prog;
	call_msg.rm_call.cb_vers = (u_int32_t)vers;

	/*
	 * pre-serialize the static part of the call msg and stash it away
	 */
	xdrmem_create(&(ct->ct_xdrs), ct->ct_u.ct_mcallc, MCALL_MSG_SIZE,
	    XDR_ENCODE);
	if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
		if (ct->ct_closeit) {
			(void)_close(fd);
		}
		goto err;
	}
	ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
	XDR_DESTROY(&(ct->ct_xdrs));
	assert(ct->ct_mpos + sizeof(uint32_t) <= MCALL_MSG_SIZE);

	/*
	 * Create a client handle which uses xdrrec for serialization
	 * and authnone for authentication.
	 */
	cl->cl_ops = clnt_vc_ops();
	cl->cl_private = ct;
	cl->cl_auth = authnone_create();
	sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
	recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
	xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
	    cl->cl_private, read_vc, write_vc);
	return (cl);

err:
	if (ct) {
		if (ct->ct_addr.len)
			mem_free(ct->ct_addr.buf, ct->ct_addr.len);
		mem_free(ct, sizeof (struct ct_data));
	}
	if (cl)
		mem_free(cl, sizeof (CLIENT));
	return ((CLIENT *)NULL);
}
コード例 #14
0
ファイル: clnt_dg.c プロジェクト: bahamas10/openzfs
/*
 * Connection less client creation returns with client handle parameters.
 * Default options are set, which the user can change using clnt_control().
 * fd should be open and bound.
 * NB: The rpch->cl_auth is initialized to null authentication.
 * 	Caller may wish to set this something more useful.
 *
 * sendsz and recvsz are the maximum allowable packet sizes that can be
 * sent and received. Normally they are the same, but they can be
 * changed to improve the program efficiency and buffer allocation.
 * If they are 0, use the transport default.
 *
 * If svcaddr is NULL, returns NULL.
 */
CLIENT *
clnt_dg_create(const int fd, struct netbuf *svcaddr, const rpcprog_t program,
	const rpcvers_t version, const uint_t sendsz, const uint_t recvsz)
{
	CLIENT *cl = NULL;		/* client handle */
	struct cu_data *cu = NULL;	/* private data */
	struct t_unitdata *tr_data;
	struct t_info tinfo;
	struct timeval now;
	struct rpc_msg call_msg;
	uint_t ssz;
	uint_t rsz;

	sig_mutex_lock(&dgtbl_lock);
	if ((dgtbl == NULL) && ((dgtbl = rpc_fd_init()) == NULL)) {
		sig_mutex_unlock(&dgtbl_lock);
		goto err1;
	}
	sig_mutex_unlock(&dgtbl_lock);

	if (svcaddr == NULL) {
		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
		return (NULL);
	}
	if (t_getinfo(fd, &tinfo) == -1) {
		rpc_createerr.cf_stat = RPC_TLIERROR;
		rpc_createerr.cf_error.re_errno = 0;
		rpc_createerr.cf_error.re_terrno = t_errno;
		return (NULL);
	}
	/*
	 * Setup to rcv datagram error, we ignore any errors returned from
	 * __rpc_tli_set_options() as SO_DGRAM_ERRIND is only relevant to
	 * udp/udp6 transports and this point in the code we only know that
	 * we are using a connection less transport.
	 */
	if (tinfo.servtype == T_CLTS)
		(void) __rpc_tli_set_options(fd, SOL_SOCKET, SO_DGRAM_ERRIND,
		    1);
	/*
	 * Find the receive and the send size
	 */
	ssz = __rpc_get_t_size((int)sendsz, tinfo.tsdu);
	rsz = __rpc_get_t_size((int)recvsz, tinfo.tsdu);
	if ((ssz == 0) || (rsz == 0)) {
		rpc_createerr.cf_stat = RPC_TLIERROR; /* XXX */
		rpc_createerr.cf_error.re_errno = 0;
		rpc_createerr.cf_error.re_terrno = 0;
		return (NULL);
	}

	if ((cl = malloc(sizeof (CLIENT))) == NULL)
		goto err1;
	/*
	 * Should be multiple of 4 for XDR.
	 */
	ssz = ((ssz + 3) / 4) * 4;
	rsz = ((rsz + 3) / 4) * 4;
	cu = malloc(sizeof (*cu) + ssz + rsz);
	if (cu == NULL)
		goto err1;
	if ((cu->cu_raddr.buf = malloc(svcaddr->len)) == NULL)
		goto err1;
	(void) memcpy(cu->cu_raddr.buf, svcaddr->buf, (size_t)svcaddr->len);
	cu->cu_raddr.len = cu->cu_raddr.maxlen = svcaddr->len;
	cu->cu_outbuf_start = &cu->cu_inbuf[rsz];
	/* Other values can also be set through clnt_control() */
	cu->cu_wait.tv_sec = 15;	/* heuristically chosen */
	cu->cu_wait.tv_usec = 0;
	cu->cu_total.tv_sec = -1;
	cu->cu_total.tv_usec = -1;
	cu->cu_sendsz = ssz;
	cu->cu_recvsz = rsz;
	(void) gettimeofday(&now, NULL);
	call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
	call_msg.rm_call.cb_prog = program;
	call_msg.rm_call.cb_vers = version;
	xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, ssz, XDR_ENCODE);
	if (!xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
		rpc_createerr.cf_stat = RPC_CANTENCODEARGS;  /* XXX */
		rpc_createerr.cf_error.re_errno = 0;
		rpc_createerr.cf_error.re_terrno = 0;
		goto err2;
	}
	cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
	XDR_DESTROY(&(cu->cu_outxdrs));
	xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf_start, ssz, XDR_ENCODE);
/* LINTED pointer alignment */
	tr_data = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ADDR | T_OPT);
	if (tr_data == NULL) {
		goto err1;
	}
	tr_data->udata.maxlen = cu->cu_recvsz;
	tr_data->udata.buf = cu->cu_inbuf;
	cu->cu_tr_data = tr_data;

	/*
	 * By default, closeit is always FALSE. It is users responsibility
	 * to do a t_close on it, else the user may use clnt_control
	 * to let clnt_destroy do it for him/her.
	 */
	cu->cu_closeit = FALSE;
	cu->cu_fd = fd;
	cl->cl_ops = clnt_dg_ops();
	cl->cl_private = (caddr_t)cu;
	cl->cl_auth = authnone_create();
	cl->cl_tp = NULL;
	cl->cl_netid = NULL;
	cu->pfdp.fd = cu->cu_fd;
	cu->pfdp.events = MASKVAL;
	return (cl);
err1:
	(void) syslog(LOG_ERR, mem_err_clnt_dg);
	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
	rpc_createerr.cf_error.re_errno = errno;
	rpc_createerr.cf_error.re_terrno = 0;
err2:
	if (cl) {
		free(cl);
		if (cu) {
			free(cu->cu_raddr.buf);
			free(cu);
		}
	}
	return (NULL);
}
コード例 #15
0
ファイル: svc.c プロジェクト: vonwenm/pbft
enum auth_stat
svcbyz_auth_unix(struct svc_req *rqst, struct rpc_msg *msg) {
  register enum auth_stat stat;
  XDR xdrs;
  register struct authunix_parms *aup;
  register int *buf;
  struct area {
    struct authunix_parms area_aup;
    char area_machname[MAX_MACHINE_NAME+1];
    unsigned int area_gids[NGRPS]; // JC: changed to unsigned
  } *area;
  u_int auth_len;
  int str_len, gid_len;
  register int i;

  area = (struct area *) rqst->rq_clntcred;
  aup = &area->area_aup;
  aup->aup_machname = area->area_machname;
  aup->aup_gids = area->area_gids;
  auth_len = (unsigned int)msg->rm_call.cb_cred.oa_length;
  xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE);
  buf = XDR_INLINE(&xdrs, auth_len);
  if (buf != NULL) {
    aup->aup_time = IXDR_GET_LONG(buf);
    str_len = IXDR_GET_U_LONG(buf);
    if (str_len > MAX_MACHINE_NAME) {
      stat = AUTH_BADCRED;
      goto done;
    }
    bcopy((caddr_t)buf, aup->aup_machname, (u_int)str_len);
    aup->aup_machname[str_len] = 0;
    str_len = RNDUP(str_len);
    buf += str_len / sizeof(int);
    aup->aup_uid = IXDR_GET_LONG(buf);
    aup->aup_gid = IXDR_GET_LONG(buf);
    gid_len = IXDR_GET_U_LONG(buf);
    if (gid_len > NGRPS) {
      stat = AUTH_BADCRED;
      goto done;
    }
    aup->aup_len = gid_len;
    for (i = 0; i < gid_len; i++) {
      aup->aup_gids[i] = IXDR_GET_LONG(buf);
    }
    /*
     * five is the smallest unix credentials structure -
     * timestamp, hostname len (0), uid, gid, and gids len (0).
     */
    if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
      (void) printf("bad auth_len gid %d str %d auth %d\n",
		    gid_len, str_len, auth_len);
      stat = AUTH_BADCRED;
      goto done;
    }
  } else if (! xdr_authunix_parms(&xdrs, aup)) {
    xdrs.x_op = XDR_FREE;
    (void)xdr_authunix_parms(&xdrs, aup);
    stat = AUTH_BADCRED;
    goto done;
  }
  rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
  rqst->rq_xprt->xp_verf.oa_length = 0;
  stat = AUTH_OK;
done:
  XDR_DESTROY(&xdrs);
  return (stat);
}
コード例 #16
0
ファイル: guestfsd.c プロジェクト: gaowanlong/libguestfs
int
main (int argc, char *argv[])
{
  static const char *options = "rv?";
  static const struct option long_options[] = {
    { "help", 0, 0, '?' },
    { "verbose", 0, 0, 'v' },
    { 0, 0, 0, 0 }
  };
  int c;
  char *cmdline;

  ignore_value (chdir ("/"));

  if (winsock_init () == -1)
    error (EXIT_FAILURE, 0, "winsock initialization failed");

#ifdef HAVE_REGISTER_PRINTF_SPECIFIER
  /* http://udrepper.livejournal.com/20948.html */
  register_printf_specifier ('Q', print_shell_quote, print_arginfo);
  register_printf_specifier ('R', print_sysroot_shell_quote, print_arginfo);
#else
#ifdef HAVE_REGISTER_PRINTF_FUNCTION
  register_printf_function ('Q', print_shell_quote, print_arginfo);
  register_printf_function ('R', print_sysroot_shell_quote, print_arginfo);
#else
#error "HAVE_REGISTER_PRINTF_{SPECIFIER|FUNCTION} not defined"
#endif
#endif

  struct stat statbuf;
  if (stat ("/", &statbuf) == 0)
    root_device = statbuf.st_dev;

  for (;;) {
    c = getopt_long (argc, argv, options, long_options, NULL);
    if (c == -1) break;

    switch (c) {
      /* The -r flag is used when running standalone.  It changes
       * several aspects of the daemon.
       */
    case 'r':
      sysroot = "";
      sysroot_len = 0;
      autosync_umount = 0;
      break;

    case 'v':
      verbose = 1;
      break;

    case '?':
      usage ();
      exit (EXIT_SUCCESS);

    default:
      fprintf (stderr, "guestfsd: unexpected command line option 0x%x\n", c);
      exit (EXIT_FAILURE);
    }
  }

  if (optind < argc) {
    usage ();
    exit (EXIT_FAILURE);
  }

  cmdline = read_cmdline ();

  /* Set the verbose flag. */
  verbose = verbose ||
    (cmdline && strstr (cmdline, "guestfs_verbose=1") != NULL);
  if (verbose)
    printf ("verbose daemon enabled\n");

  if (verbose) {
    if (cmdline)
      printf ("linux commmand line: %s\n", cmdline);
    else
      printf ("could not read linux command line\n");
  }

#ifndef WIN32
  /* Make sure SIGPIPE doesn't kill us. */
  struct sigaction sa;
  memset (&sa, 0, sizeof sa);
  sa.sa_handler = SIG_IGN;
  sa.sa_flags = 0;
  if (sigaction (SIGPIPE, &sa, NULL) == -1)
    perror ("sigaction SIGPIPE"); /* but try to continue anyway ... */
#endif

#ifdef WIN32
# define setenv(n,v,f) _putenv(n "=" v)
#endif
  /* Set up a basic environment.  After we are called by /init the
   * environment is essentially empty.
   * https://bugzilla.redhat.com/show_bug.cgi?id=502074#c5
   *
   * NOTE: if you change $PATH, you must also change 'prog_exists'
   * function below.
   */
  setenv ("PATH", "/sbin:/usr/sbin:/bin:/usr/bin", 1);
  setenv ("SHELL", "/bin/sh", 1);
  setenv ("LC_ALL", "C", 1);
  setenv ("TERM", "dumb", 1);

#ifndef WIN32
  /* We document that umask defaults to 022 (it should be this anyway). */
  umask (022);
#else
  /* This is the default for Windows anyway.  It's not even clear if
   * Windows ever uses this -- the MSDN documentation for the function
   * contains obvious errors.
   */
  _umask (0);
#endif

  /* Make a private copy of /etc/lvm so we can change the config (see
   * daemon/lvm-filter.c).
   */
  copy_lvm ();

  /* Connect to virtio-serial channel. */
  int sock = open (VIRTIO_SERIAL_CHANNEL, O_RDWR | O_CLOEXEC);
  if (sock == -1) {
    fprintf (stderr,
             "\n"
             "Failed to connect to virtio-serial channel.\n"
             "\n"
             "This is a fatal error and the appliance will now exit.\n"
             "\n"
             "Usually this error is caused by either QEMU or the appliance\n"
             "kernel not supporting the vmchannel method that the\n"
             "libguestfs library chose to use.  Please run\n"
             "'libguestfs-test-tool' and provide the complete, unedited\n"
             "output to the libguestfs developers, either in a bug report\n"
             "or on the libguestfs redhat com mailing list.\n"
             "\n");
    perror (VIRTIO_SERIAL_CHANNEL);
    exit (EXIT_FAILURE);
  }

  /* Send the magic length message which indicates that
   * userspace is up inside the guest.
   */
  char lenbuf[4];
  XDR xdr;
  uint32_t len = GUESTFS_LAUNCH_FLAG;
  xdrmem_create (&xdr, lenbuf, sizeof lenbuf, XDR_ENCODE);
  xdr_u_int (&xdr, &len);

  if (xwrite (sock, lenbuf, sizeof lenbuf) == -1) {
    perror ("xwrite");
    exit (EXIT_FAILURE);
  }

  xdr_destroy (&xdr);

  /* Enter the main loop, reading and performing actions. */
  main_loop (sock);

  exit (EXIT_SUCCESS);
}
コード例 #17
0
ファイル: kproplog.c プロジェクト: AlainODea/illumos-gate
/*
 * Print the update entry information
 */
static void
print_update(kdb_hlog_t *ulog, uint32_t entry, bool_t verbose)
{
	XDR		xdrs;
	uint32_t	start_sno, i, j, indx;
	char		*dbprinc;
	kdb_ent_header_t *indx_log;
	kdb_incr_update_t upd;

	if (entry && (entry < ulog->kdb_num))
		start_sno = ulog->kdb_last_sno - entry;
	else
		start_sno = ulog->kdb_first_sno - 1;

	for (i = start_sno; i < ulog->kdb_last_sno; i++) {
		indx = i % ulog->kdb_num;

		indx_log = (kdb_ent_header_t *)INDEX(ulog, indx);

		/*
		 * Check for corrupt update entry
		 */
		if (indx_log->kdb_umagic != KDB_UMAGIC) {
			(void) fprintf(stderr,
			    gettext("Corrupt update entry\n\n"));
			exit(1);
		}

		(void) memset((char *)&upd, 0, sizeof (kdb_incr_update_t));
		xdrmem_create(&xdrs, (char *)indx_log->entry_data,
		    indx_log->kdb_entry_size, XDR_DECODE);
		if (!xdr_kdb_incr_update_t(&xdrs, &upd)) {
			(void) printf(gettext("Entry data decode failure\n\n"));
			exit(1);
		}

		(void) printf("---\n");
		(void) printf(gettext("Update Entry\n"));

		(void) printf(gettext("\tUpdate serial # : %u\n"),
		    indx_log->kdb_entry_sno);

		(void) printf(gettext("\tUpdate operation : "));
		if (upd.kdb_deleted)
			(void) printf(gettext("Delete\n"));
		else
			(void) printf(gettext("Add\n"));

		dbprinc = malloc(upd.kdb_princ_name.utf8str_t_len + 1);
		if (dbprinc == NULL) {
			(void) printf(gettext("Could not allocate "
			    "principal name\n\n"));
			exit(1);
		}
		(void) strlcpy(dbprinc, upd.kdb_princ_name.utf8str_t_val,
		    (upd.kdb_princ_name.utf8str_t_len + 1));
		(void) printf(gettext("\tUpdate principal : %s\n"), dbprinc);

		(void) printf(gettext("\tUpdate size : %u\n"),
		    indx_log->kdb_entry_size);

		(void) printf(gettext("\tUpdate committed : %s\n"),
		    indx_log->kdb_commit ? "True" : "False");

		if (indx_log->kdb_time.seconds == 0L)
			(void) printf(gettext("\tUpdate time stamp : None\n"));
		else
			(void) printf(gettext("\tUpdate time stamp : %s"),
			    ctime((time_t *)&(indx_log->kdb_time.seconds)));

		(void) printf(gettext("\tAttributes changed : %d\n"),
		    upd.kdb_update.kdbe_t_len);

		if (verbose)
			for (j = 0; j < upd.kdb_update.kdbe_t_len; j++)
				print_attr(
				    upd.kdb_update.kdbe_t_val[j].av_type);

		xdr_free(xdr_kdb_incr_update_t, (char *)&upd);
		if (dbprinc)
			free(dbprinc);
	} /* for */
}
コード例 #18
0
ファイル: lib.lim.c プロジェクト: Tambralinga/openlava
int
callLim_(enum limReqCode reqCode,
         void *dsend,
         bool_t (*xdr_sfunc)(),
         void *drecv,
         bool_t (*xdr_rfunc)(),
         char *host,
         int options,
         struct LSFHeader *hdr)
{
    struct LSFHeader reqHdr;
    struct LSFHeader replyHdr;
    XDR    xdrs;
    char   sbuf[8*MSGSIZE];
    char   rbuf[MAXMSGLEN];
    char   *repBuf;
    enum limReplyCode limReplyCode;
    static char first = TRUE;
    int reqLen;

    masterLimDown = FALSE;
    if (first) {

        if (initLimSock_() < 0)
            return(-1);
        first = FALSE;

        if (genParams_[LSF_API_CONNTIMEOUT].paramValue) {
            conntimeout_ = atoi(genParams_[LSF_API_CONNTIMEOUT].paramValue);
            if (conntimeout_ <= 0)
                conntimeout_ =  CONNECT_TIMEOUT;
        }

        if (genParams_[LSF_API_RECVTIMEOUT].paramValue) {
            recvtimeout_ = atoi(genParams_[LSF_API_RECVTIMEOUT].paramValue);
            if (recvtimeout_ <= 0)
                recvtimeout_ = RECV_TIMEOUT;
        }
    }

    initLSFHeader_(&reqHdr);
    reqHdr.opCode = reqCode;

    reqHdr.refCode  = getRefNum_();
    reqHdr.version = OPENLAVA_VERSION;

    xdrmem_create(&xdrs, sbuf, 8*MSGSIZE, XDR_ENCODE);
    if (!xdr_encodeMsg(&xdrs, dsend, &reqHdr, xdr_sfunc, 0, NULL)) {
        xdr_destroy(&xdrs);
        lserrno = LSE_BAD_XDR;
        return -1;
    }

    reqLen = XDR_GETPOS(&xdrs);
    xdr_destroy(&xdrs);
    if (options & _USE_TCP_) {
        if (callLimTcp_(sbuf, &repBuf, reqLen, &replyHdr, options) < 0)
            return -1;
        if (replyHdr.length != 0)
            xdrmem_create(&xdrs, repBuf, XDR_DECODE_SIZE_(replyHdr.length),
                          XDR_DECODE);
        else
            xdrmem_create(&xdrs, rbuf, MAXMSGLEN, XDR_DECODE);
    } else {
        if (callLimUdp_(sbuf, rbuf, reqLen, &reqHdr, host, options) < 0)
            return -1;
        if (options & _NON_BLOCK_)
            return 0;
        xdrmem_create(&xdrs, rbuf, MAXMSGLEN, XDR_DECODE);
    }

    if (!(options & _USE_TCP_)) {
        if (!xdr_LSFHeader(&xdrs, &replyHdr)) {
            xdr_destroy(&xdrs);
            lserrno = LSE_BAD_XDR;
            return -1;
        }
    }

    limReplyCode = replyHdr.opCode;

    lsf_lim_version = (int)replyHdr.version;

    switch (limReplyCode) {
        case LIME_NO_ERR:
            if (drecv != NULL) {
                if (! (*xdr_rfunc) (&xdrs, drecv, &replyHdr)) {
                    xdr_destroy(&xdrs);
                    if (options & _USE_TCP_)
                        FREEUP(repBuf);
                    lserrno = LSE_BAD_XDR;
                    return -1;
                }
            }
            xdr_destroy(&xdrs);
            if (options & _USE_TCP_)
                FREEUP(repBuf);
            if (hdr != NULL)
                *hdr = replyHdr;
            return (0);

        default:
            xdr_destroy(&xdrs);
            if (options & _USE_TCP_)
                FREEUP(repBuf);
            err_return_(limReplyCode);
            return (-1);
    }

}
コード例 #19
0
ファイル: clnt_tcp.c プロジェクト: darksoul42/bitrig
/*
 * Create a client handle for a tcp/ip connection.
 * If *sockp<0, *sockp is set to a newly created TCP socket and it is
 * connected to raddr.  If *sockp non-negative then
 * raddr is ignored.  The rpc/tcp package does buffering
 * similar to stdio, so the client must pick send and receive buffer sizes,];
 * 0 => use the default.
 * If raddr->sin_port is 0, then a binder on the remote machine is
 * consulted for the right port number.
 * NB: *sockp is copied into a private area.
 * NB: It is the client's responsibility to close *sockp, unless
 *     clnttcp_create() was called with *sockp = -1 (so it created
 *     the socket), and CLNT_DESTROY() is used.
 * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
 * something more useful.
 */
CLIENT *
clnttcp_create(struct sockaddr_in *raddr, u_long prog, u_long vers, int *sockp,
    u_int sendsz, u_int recvsz)
{
	CLIENT *h;
	struct ct_data *ct = NULL;
	struct timeval now;
	struct rpc_msg call_msg;

	h  = (CLIENT *)mem_alloc(sizeof(*h));
	if (h == NULL) {
		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
		rpc_createerr.cf_error.re_errno = errno;
		goto fooy;
	}
	ct = (struct ct_data *)mem_alloc(sizeof(*ct));
	if (ct == NULL) {
		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
		rpc_createerr.cf_error.re_errno = errno;
		goto fooy;
	}

	/*
	 * If no port number given ask the pmap for one
	 */
	if (raddr->sin_port == 0) {
		u_short port;
		if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
			mem_free((caddr_t)ct, sizeof(struct ct_data));
			mem_free((caddr_t)h, sizeof(CLIENT));
			return (NULL);
		}
		raddr->sin_port = htons(port);
	}

	/*
	 * If no socket given, open one
	 */
	if (*sockp < 0) {
		*sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		(void)bindresvport(*sockp, NULL);
		if ((*sockp < 0)
		    || (connect(*sockp, (struct sockaddr *)raddr,
		    sizeof(*raddr)) < 0)) {
			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
			rpc_createerr.cf_error.re_errno = errno;
			if (*sockp != -1)
				(void)close(*sockp);
			goto fooy;
		}
		ct->ct_closeit = TRUE;
	} else {
		ct->ct_closeit = FALSE;
	}

	/*
	 * Set up private data struct
	 */
	ct->ct_sock = *sockp;
	ct->ct_wait.tv_usec = 0;
	ct->ct_waitset = FALSE;
	ct->ct_addr = *raddr;

	/*
	 * Initialize call message
	 */
	(void)gettimeofday(&now, NULL);
	call_msg.rm_xid = arc4random();
	call_msg.rm_direction = CALL;
	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
	call_msg.rm_call.cb_prog = prog;
	call_msg.rm_call.cb_vers = vers;

	/*
	 * pre-serialize the static part of the call msg and stash it away
	 */
	xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
	    XDR_ENCODE);
	if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
		if (ct->ct_closeit) {
			(void)close(*sockp);
		}
		goto fooy;
	}
	ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
	XDR_DESTROY(&(ct->ct_xdrs));

	/*
	 * Create a client handle which uses xdrrec for serialization
	 * and authnone for authentication.
	 */
	xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
	    (caddr_t)ct, (int(*)(caddr_t, caddr_t, int))readtcp,
	    (int(*)(caddr_t, caddr_t, int))writetcp);
	h->cl_ops = &tcp_ops;
	h->cl_private = (caddr_t) ct;
	h->cl_auth = authnone_create();
	if (h->cl_auth == NULL) {
		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
		rpc_createerr.cf_error.re_errno = errno;
		goto fooy;
	}
	return (h);

fooy:
	/*
	 * Something goofed, free stuff and barf
	 */
	if (ct)
		mem_free((caddr_t)ct, sizeof(struct ct_data));
	if (h)
		mem_free((caddr_t)h, sizeof(CLIENT));
	return (NULL);
}
コード例 #20
0
ファイル: svc_auth_gss.c プロジェクト: nfs-ganesha/ntirpc
enum auth_stat
_svcauth_gss(struct svc_req *req, struct rpc_msg *msg,
	     bool *no_dispatch)
{
	XDR xdrs[1];
	SVCAUTH *auth;
	struct svc_rpc_gss_data *gd = NULL;
	struct rpc_gss_cred *gc = NULL;
	struct rpc_gss_init_res gr;
	int call_stat, offset;
	OM_uint32 min_stat;
	bool gd_locked = false;
	bool gd_hashed = false;

	/* Initialize reply. */
	req->rq_verf = _null_auth;

	/* Unserialize client credentials. */
	if (req->rq_cred.oa_length <= 0)
		svcauth_gss_return(AUTH_BADCRED);

	gc = (struct rpc_gss_cred *)req->rq_clntcred;
	memset(gc, 0, sizeof(struct rpc_gss_cred));

	xdrmem_create(xdrs, req->rq_cred.oa_base, req->rq_cred.oa_length,
		      XDR_DECODE);

	if (!xdr_rpc_gss_cred(xdrs, gc)) {
		XDR_DESTROY(xdrs);
		svcauth_gss_return(AUTH_BADCRED);
	}
	XDR_DESTROY(xdrs);

	/* Check version. */
	if (gc->gc_v != RPCSEC_GSS_VERSION)
		svcauth_gss_return(AUTH_BADCRED);

	if (gc->gc_seq > RPCSEC_GSS_MAXSEQ)
		svcauth_gss_return(RPCSEC_GSS_CTXPROBLEM);

	if (gc->gc_proc > RPCSEC_GSS_MAXPROC)
		svcauth_gss_return(AUTH_BADCRED);

	/* Check RPCSEC_GSS service. */
	if (gc->gc_svc != RPCSEC_GSS_SVC_NONE
	    && gc->gc_svc != RPCSEC_GSS_SVC_INTEGRITY
	    && gc->gc_svc != RPCSEC_GSS_SVC_PRIVACY)
		svcauth_gss_return(AUTH_BADCRED);

	/* Context lookup. */
	if ((gc->gc_proc == RPCSEC_GSS_DATA)
	    || (gc->gc_proc == RPCSEC_GSS_DESTROY)) {

		/* Per RFC 2203 5.3.3.3, if a valid security context
		 * cannot be found to authorize a request, the
		 * implementation returns RPCSEC_GSS_CREDPROBLEM.
		 * N.B., we are explicitly allowed to discard contexts
		 * for any reason (e.g., to save space). */
		gd = authgss_ctx_hash_get(gc);
		if (!gd)
			svcauth_gss_return(RPCSEC_GSS_CREDPROBLEM);
		gd_hashed = true;
		if (gc->gc_svc != gd->sec.svc)
			gd->sec.svc = gc->gc_svc;
	}

	if (!gd) {
		/* Allocate and set up server auth handle. */
		auth = mem_alloc(sizeof(SVCAUTH));
		gd = alloc_svc_rpc_gss_data();
		auth->svc_ah_ops = &svc_auth_gss_ops;
		auth->svc_ah_private = (caddr_t) gd;
		gd->auth = auth;
	}

	/* Serialize context. */
	mutex_lock(&gd->lock);
	gd_locked = true;

	/* thread auth */
	req->rq_auth = gd->auth;

	/* Check sequence number. */
	if (gd->established) {
		if (get_time_fast() >= gd->endtime) {
			*no_dispatch = true;
			svcauth_gss_return(RPCSEC_GSS_CREDPROBLEM);
		}

		/* XXX implied serialization?  or just fudging?  advance if
		 * greater? */
		offset = gd->seqlast - gc->gc_seq;
		if (offset < 0) {
			gd->seqlast = gc->gc_seq;
			offset = 0 - offset;
			gd->seqmask <<= offset;
			offset = 0;
		} else if (offset >= gd->win || (gd->seqmask & (1 << offset))) {
			*no_dispatch = true;
			svcauth_gss_return(AUTH_OK);
		}
		gd->seqmask |= (1 << offset);	/* XXX harmless */

		req->rq_ap1 = (void *)(uintptr_t) gc->gc_seq; /* GCC casts */
		req->rq_clntname = (char *) gd->client_name;
		req->rq_svcname = (char *) gd->ctx;
	}

	/* gd->established */
	/* Handle RPCSEC_GSS control procedure. */
	switch (gc->gc_proc) {

	case RPCSEC_GSS_INIT:
	case RPCSEC_GSS_CONTINUE_INIT:

		if (req->rq_proc != NULLPROC)
			svcauth_gss_return(AUTH_FAILED); /* XXX ? */

		/* XXX why unconditionally acquire creds? */
		if (!svcauth_gss_acquire_cred())
			svcauth_gss_return(AUTH_FAILED);

		if (!svcauth_gss_accept_sec_context(req, gd, &gr))
			svcauth_gss_return(AUTH_REJECTEDCRED);

		if (!svcauth_gss_nextverf(req, gd, htonl(gr.gr_win))) {
			/* XXX check */
			gss_release_buffer(&min_stat, &gr.gr_token);
			mem_free(gr.gr_ctx.value, 0);
			svcauth_gss_return(AUTH_FAILED);
		}

		*no_dispatch = true;

		call_stat =
		    svc_sendreply(req->rq_xprt, req,
				  (xdrproc_t) xdr_rpc_gss_init_res,
				  (caddr_t) &gr);

		/* XXX */
		gss_release_buffer(&min_stat, &gr.gr_token);
		gss_release_buffer(&min_stat, &gd->checksum);
		mem_free(gr.gr_ctx.value, 0);

		if (!call_stat)
			svcauth_gss_return(AUTH_FAILED);

		if (gr.gr_major == GSS_S_COMPLETE) {
			gd->established = true;
			if (!gd_hashed) {

				/* krb5 pac -- try all that apply */
				gss_buffer_desc attr, display_buffer;

				/* completely generic */
				int auth = 1, comp = 0, more = -1;

				memset(&gd->pac.ms_pac, 0,
				       sizeof(gss_buffer_desc));
				memset(&display_buffer, 0,
				       sizeof(gss_buffer_desc));

				/* MS AD */
				attr.value = "urn:mspac:";
				attr.length = 10;

				gr.gr_major =
				    gss_get_name_attribute(&gr.gr_minor,
							   gd->client_name,
							   &attr, &auth, &comp,
							   &gd->pac.ms_pac,
							   &display_buffer,
							   &more);

				if (gr.gr_major == GSS_S_COMPLETE) {
					/* dont need it */
					gss_release_buffer(&gr.gr_minor,
							   &display_buffer);
					gd->flags |= SVC_RPC_GSS_FLAG_MSPAC;
				}

				(void)authgss_ctx_hash_set(gd);
			}
		}
		break;

		/* XXX next 2 cases:  is it correct to leave gd in cache
		 * after a validate or verf failure ? */

	case RPCSEC_GSS_DATA:
		call_stat = svcauth_gss_validate(req, gd, msg);
		switch (call_stat) {
		default:
			svcauth_gss_return(RPCSEC_GSS_CREDPROBLEM);
		case 0:
			break;
		}

		if (!svcauth_gss_nextverf(req, gd, htonl(gc->gc_seq)))
			svcauth_gss_return(AUTH_FAILED);
		break;

	case RPCSEC_GSS_DESTROY:
		if (req->rq_proc != NULLPROC)
			svcauth_gss_return(AUTH_FAILED);	/* XXX ? */

		if (svcauth_gss_validate(req, gd, msg))
			svcauth_gss_return(RPCSEC_GSS_CREDPROBLEM);

		if (!svcauth_gss_nextverf(req, gd, htonl(gc->gc_seq)))
			svcauth_gss_return(AUTH_FAILED);

		*no_dispatch = true;

		(void)authgss_ctx_hash_del(gd);

		/* avoid lock order reversal gd->lock, xprt->xp_lock */
		mutex_unlock(&gd->lock);
		gd_locked = false;

		call_stat =
		    svc_sendreply(req->rq_xprt, req, (xdrproc_t) xdr_void,
				  (caddr_t) NULL);

		/* We acquired a reference on gd with authgss_ctx_hash_get
		 * call.  Time to release the reference as we don't need
		 * gd anymore.
		 */
		unref_svc_rpc_gss_data(gd, SVC_RPC_GSS_FLAG_NONE);
		req->rq_auth = &svc_auth_none;

		break;

	default:
		svcauth_gss_return(AUTH_REJECTEDCRED);
		break;
	}

	svcauth_gss_return(AUTH_OK);
}
コード例 #21
0
ファイル: rpcauth.c プロジェクト: Beautifu/xserver
static char *
authdes_ezdecode(const char *inmsg, int len)
{
    struct rpc_msg msg;
    char cred_area[MAX_AUTH_BYTES];
    char verf_area[MAX_AUTH_BYTES];
    char *temp_inmsg;
    struct svc_req r;
    bool_t res0, res1;
    XDR xdr;
    SVCXPRT xprt;

    temp_inmsg = malloc(len);
    memmove(temp_inmsg, inmsg, len);

    memset((char *) &msg, 0, sizeof(msg));
    memset((char *) &r, 0, sizeof(r));
    memset(cred_area, 0, sizeof(cred_area));
    memset(verf_area, 0, sizeof(verf_area));

    msg.rm_call.cb_cred.oa_base = cred_area;
    msg.rm_call.cb_verf.oa_base = verf_area;
    why = AUTH_FAILED;
    xdrmem_create(&xdr, temp_inmsg, len, XDR_DECODE);

    if ((r.rq_clntcred = malloc(MAX_AUTH_BYTES)) == NULL)
        goto bad1;
    r.rq_xprt = &xprt;

    /* decode into msg */
    res0 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_cred));
    res1 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_verf));
    if (!(res0 && res1))
        goto bad2;

    /* do the authentication */

    r.rq_cred = msg.rm_call.cb_cred;    /* read by opaque stuff */
    if (r.rq_cred.oa_flavor != AUTH_DES) {
        why = AUTH_TOOWEAK;
        goto bad2;
    }
#ifdef SVR4
    if ((why = __authenticate(&r, &msg)) != AUTH_OK) {
#else
    if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
#endif
        goto bad2;
    }
    return (((struct authdes_cred *) r.rq_clntcred)->adc_fullname.name);

bad2:
    free(r.rq_clntcred);
bad1:
    return ((char *) 0);        /* ((struct authdes_cred *) NULL); */
}

static XID rpc_id = (XID) ~0L;

static Bool
CheckNetName(unsigned char *addr, short len, pointer closure)
{
    return (len == strlen((char *) closure) &&
            strncmp((char *) addr, (char *) closure, len) == 0);
}

static char rpc_error[MAXNETNAMELEN + 50];

_X_HIDDEN XID
SecureRPCCheck(unsigned short data_length, const char *data,
               ClientPtr client, const char **reason)
{
    char *fullname;

    if (rpc_id == (XID) ~0L) {
        *reason = "Secure RPC authorization not initialized";
    }
    else {
        fullname = authdes_ezdecode(data, data_length);
        if (fullname == (char *) 0) {
            snprintf(rpc_error, sizeof(rpc_error),
                     "Unable to authenticate secure RPC client (why=%d)", why);
            *reason = rpc_error;
        }
        else {
            if (ForEachHostInFamily(FamilyNetname, CheckNetName, fullname))
                return rpc_id;
            snprintf(rpc_error, sizeof(rpc_error),
                     "Principal \"%s\" is not authorized to connect", fullname);
            *reason = rpc_error;
        }
    }
    return (XID) ~0L;
}
コード例 #22
0
ファイル: rt_alimserver.c プロジェクト: hfuhuang/proview
int main (int argc, char **argv)
{
  pwr_tStatus      sts;
  unsigned int     size;
  qcom_sQid        myQId;
  alimsrv_sSupDataBuf *bp;
  qcom_sGet        get;
  qcom_sPut        put;
  alimsrv_sRequest request;
  XDR              xdrs;
  qcom_sQattr      qAttr;

  errh_Init("pwr_alim", errh_eAnix_alim);
  errh_SetStatus( PWR__SRVSTARTUP);

  if (!qcom_Init(&sts, 0, "pwr_alim")) {
    errh_Fatal("qcom_Init, %m", sts);
    exit(-1);
  } 

  myQId.qix = alimsrv_cQix;
  myQId.nid = 0;
  qAttr.type  = qcom_eQtype_private;
  qAttr.quota = 100;
  if (!qcom_CreateQ(&sts, &myQId,  &qAttr, "pwr_alim")) {
    errh_Fatal("qcom_CreateQ, %m", sts);
    errh_SetStatus( PWR__SRVTERM);
    exit(-1);
  } 
  if (!qcom_Bind(&sts, &myQId, &qcom_cQini)) {
    errh_Fatal("qcom_Bind, %m", sts);
    errh_SetStatus( PWR__SRVTERM);
    exit(-1);
  }

  sts = gdh_Init("pwr_alim");
  if (EVEN(sts)) {
    errh_Fatal("gdh_Init, %m", sts);
    errh_SetStatus( PWR__SRVTERM);
    exit(-1);
  } 

  init();

  errh_SetStatus( PWR__SRUN);

  /* Loop forever and receive objid's */

  for (;;) {
    do {
      get.maxSize = sizeof(request);
      get.data = (char *)&request;
      qcom_Get(&sts, &myQId, &get, qcom_cTmoEternal);
      if (sts != QCOM__TMO && sts != QCOM__QEMPTY) {
        if (get.type.b == qcom_eBtype_event) {
          event(&get);
        }
      }
    } while (ODD(sts) && get.type.s != alimsrv_eSubType_Request && get.type.b != alimsrv_cMsgType);

    if (EVEN(sts)) {
      errh_Error("qcom_Get, %m",sts);
      continue;
    }

    if (request.Xdr) {
      xdrmem_create(&xdrs, (char *)&request, sizeof(request), XDR_DECODE);
      if (!xdr_alimsrv_sRequest(&xdrs, &request)) {
	errh_Error("XDR Decode failed");
	continue;
      }
    }

    bp = buildBuffer(&request, &size);

    if (ODD(sts)) {
      bp->Xdr = TRUE;
      xdrmem_create(&xdrs, (char *)bp, size, XDR_ENCODE);
      if (!xdr_alimsrv_sSupDataBuf(&xdrs, bp)) {
	errh_Error("XDR Encode failed");
      } else {
	put.type.b = alimsrv_cMsgType;
	put.type.s = alimsrv_eSubType_Answer;
	put.reply = myQId;
	put.data = (char *) bp;
	put.size = size;

	if (!qcom_Reply(&sts, &get, &put))
	  errh_Error("qcom_Respond, %m", sts);
      }            

      free(bp);
    }
  }    
}
コード例 #23
0
CLIENT *qrpc_clnt_raw_create(u_long prog, u_long vers,
		const char *const srcif_name, const uint8_t * dmac_addr, uint8_t sess_id)
{
	CLIENT *client;
	int rawsock_fd;
	struct qrpc_clnt_raw_priv *priv;
	struct rpc_msg call_msg;

	rawsock_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (rawsock_fd < 0)
		return NULL;

	if (qrpc_set_prot_filter(rawsock_fd, QRPC_RAW_SOCK_PROT) < 0) {
		close(rawsock_fd);
		return NULL;
	}

	priv = calloc(1, sizeof(*priv));
	if (!priv) {
		close(rawsock_fd);
		return NULL;
	}

	priv->raw_sock = rawsock_fd;
	priv->outbuf = calloc(1, QRPC_BUFFER_LEN);
	priv->inbuf = calloc(1, QRPC_BUFFER_LEN);
	priv->out_pktbuf = calloc(1, ETH_FRAME_LEN);
	priv->in_pktbuf = calloc(1, ETH_FRAME_LEN);
	if (!priv->outbuf || !priv->inbuf || !priv->out_pktbuf || !priv->in_pktbuf) {
		qrpc_clnt_raw_free_priv(priv);
		return NULL;
	}

	if (qrpc_clnt_raw_config_dst(rawsock_fd, srcif_name, &priv->dst_addr,
					dmac_addr, &priv->out_hdr.qhdr,
						QRPC_RAW_SOCK_PROT) < 0) {
		qrpc_clnt_raw_free_priv(priv);
		return NULL;
	}

	client = calloc(1, sizeof(*client));
	if (!client) {
		qrpc_clnt_raw_free_priv(priv);
		return NULL;
	}

	client->cl_ops = (struct clnt_ops *)&qrpc_clnt_raw_ops;
	client->cl_private = (caddr_t) priv;
	client->cl_auth = authnone_create();

	xdrmem_create(&priv->xdrs_in, (char *)priv->inbuf + sizeof(struct qrpc_frame_hdr),
			QRPC_BUFFER_LEN - sizeof(struct qrpc_frame_hdr), XDR_DECODE);

	xdrmem_create(&priv->xdrs_out, (char *)priv->outbuf,
			QRPC_BUFFER_LEN, XDR_ENCODE);
	call_msg.rm_xid = getpid();
	call_msg.rm_direction = CALL;
	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
	call_msg.rm_call.cb_prog = prog;
	call_msg.rm_call.cb_vers = vers;
	if (!xdr_callhdr(&priv->xdrs_out, &call_msg)) {
		qrpc_clnt_raw_free_priv(priv);
		free(client);
		return NULL;
	}
	priv->xdrs_outpos = XDR_GETPOS(&(priv->xdrs_out));

	priv->sess_id = sess_id;

	return client;
}
コード例 #24
0
ファイル: readbuf.c プロジェクト: AlainODea/illumos-gate
/*
 * Free the nfslog buffer and its associated allocations
 */
static void
nfslog_free_buf(struct nfslog_buf *lbp, int close_quick)
{
	XDR	xdrs;
	int	error;
	caddr_t buffer;
	struct nfslog_lr *lrp, *lrp_next;
	struct processed_records *prp, *tprp;

	/* work to free the offset records and rewrite header */
	if (lbp->prp) {
		if (lbp->last_record_offset == lbp->prp->start_offset) {

			/* adjust the offset for the entire buffer */
			lbp->last_record_offset =
				lbp->prp->start_offset + lbp->prp->len;

			nfslog_rewrite_bufheader(lbp);
		}
		if (close_quick)
			return;
		prp = lbp->prp;
		do {
			tprp = prp->next;
			free(prp);
			prp = tprp;
		} while (lbp->prp != prp);
	}

	if (close_quick)
		return;

	/* Take care of the queue log records first */
	if (lbp->lrps != NULL) {
		lrp = lbp->lrps;
		do {
			lrp_next = lrp->next;
			nfslog_free_logrecord(lrp, FALSE);
			lrp = lrp_next;
		} while (lrp != lbp->lrps);
		lbp->lrps = NULL;
	}

	/* The buffer header was decoded and needs to be freed */
	if (lbp->bh.bh_length != 0) {
		buffer = (lbp->bh_lrp->buffer != NULL ?
			lbp->bh_lrp->buffer : (caddr_t)lbp->mmap_addr);
		xdrmem_create(&xdrs, buffer, lbp->bh_lrp->recsize, XDR_FREE);
		(void) xdr_nfslog_buffer_header(&xdrs, &lbp->bh);
		lbp->bh.bh_length = 0;
	}

	/* get rid of the bufheader lrp */
	if (lbp->bh_lrp != NULL) {
		free_lrp(lbp->bh_lrp);
		lbp->bh_lrp = NULL;
	}

	/* Clean up for mmap() usage */
	if (lbp->mmap_addr != (intptr_t)MAP_FAILED) {
		if (munmap((void *)lbp->mmap_addr, lbp->filesize)) {
			error = errno;
			syslog(LOG_ERR, gettext("munmap failed: %s: %s"),
				(lbp->bufpath != NULL ? lbp->bufpath : ""),
				strerror(error));
		}
		lbp->mmap_addr = (intptr_t)MAP_FAILED;
	}

	/* Finally close the buffer file */
	if (lbp->fd >= 0) {
		lbp->fl.l_type = F_UNLCK;
		if (fcntl(lbp->fd, F_SETLK, &lbp->fl) == -1) {
			error = errno;
			syslog(LOG_ERR,
				gettext("Cannot unlock file %s: %s"),
				(lbp->bufpath != NULL ? lbp->bufpath : ""),
				strerror(error));
		}
		(void) close(lbp->fd);
		lbp->fd = -1;
	}
	if (lbp->bufpath != NULL)
		free(lbp->bufpath);
}
コード例 #25
0
ファイル: auth_unix.c プロジェクト: AgamAgarwal/minix
/*
 * Create a unix style authenticator.
 * Returns an auth handle with the given stuff in it.
 */
AUTH *
authunix_create(char *machname, int uid, int gid, int len, int *aup_gids)
{
	struct authunix_parms aup;
	char mymem[MAX_AUTH_BYTES];
	struct timeval now;
	XDR xdrs;
	AUTH *auth;
	struct audata *au;

	/*
	 * Allocate and set up auth handle
	 */
	au = NULL;
	auth = mem_alloc(sizeof(*auth));
#ifndef KERNEL
	if (auth == NULL) {
		warnx("authunix_create: out of memory");
		goto cleanup_authunix_create;
	}
#endif
	au = mem_alloc(sizeof(*au));
#ifndef KERNEL
	if (au == NULL) {
		warnx("authunix_create: out of memory");
		goto cleanup_authunix_create;
	}
#endif
	auth->ah_ops = authunix_ops();
	auth->ah_private = au;
	auth->ah_verf = au->au_shcred = _null_auth;
	au->au_shfaults = 0;
	au->au_origcred.oa_base = NULL;

	/*
	 * fill in param struct from the given params
	 */
	(void)gettimeofday(&now, NULL);
	aup.aup_time = (u_long)now.tv_sec;	/* XXX: truncate on 32 bit */
	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, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
	if (! xdr_authunix_parms(&xdrs, &aup)) 
		abort();
	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
	au->au_origcred.oa_flavor = AUTH_UNIX;
#ifdef KERNEL
	au->au_origcred.oa_base = mem_alloc((size_t)len);
#else
	if ((au->au_origcred.oa_base = mem_alloc((size_t)len)) == NULL) {
		warnx("authunix_create: out of memory");
		goto cleanup_authunix_create;
	}
#endif
	memmove(au->au_origcred.oa_base, mymem, (size_t)len);

	/*
	 * set auth handle to reflect new cred.
	 */
	auth->ah_cred = au->au_origcred;
	marshal_new_auth(auth);
	return (auth);
#ifndef KERNEL
 cleanup_authunix_create:
	if (auth)
		mem_free(auth, sizeof(*auth));
	if (au) {
		if (au->au_origcred.oa_base)
			mem_free(au->au_origcred.oa_base, (u_int)len);
		mem_free(au, sizeof(*au));
	}
	return (NULL);
#endif
}
コード例 #26
0
ファイル: readbuf.c プロジェクト: AlainODea/illumos-gate
/*
 * We are reading a record from the log buffer file.  Since we are reading
 * an XDR stream, we first have to read the first integer to determine
 * how much to read in whole for this record.  Our preference is to use
 * mmap() but if failed initially we will be using read().  Need to be
 * careful about proper initialization of the log record both from a field
 * perspective and for XDR decoding.
 */
static struct nfslog_lr *
nfslog_read_buffer(struct nfslog_buf *lbp)
{
	XDR xdrs;
	unsigned int	record_size;
	struct nfslog_lr *lrp;
	char		*sizebuf, tbuf[16];
	caddr_t		buffer;
	offset_t	next_rec;

	lrp = (struct nfslog_lr *)malloc(sizeof (*lrp));
	bzero(lrp, sizeof (*lrp));

	/* Check to see if mmap worked */
	if (lbp->mmap_addr == (intptr_t)MAP_FAILED) {
		/*
		 * EOF or other failure; we don't try to recover, just return
		 */
		if (read(lbp->fd, tbuf, BYTES_PER_XDR_UNIT) <= 0) {
			free_lrp(lrp);
			return (NULL);
		}
		sizebuf = tbuf;
	} else {
		/* EOF check for the mmap() case */
		if (lbp->filesize <= lbp->next_rec - lbp->mmap_addr) {
			free_lrp(lrp);
			return (NULL);
		}
		sizebuf = (char *)(uintptr_t)lbp->next_rec;
	}

	/* We have to XDR the first int so we know how much is in this record */
	xdrmem_create(&xdrs, sizebuf, sizeof (unsigned int), XDR_DECODE);

	if (!xdr_u_int(&xdrs, &record_size)) {
		free_lrp(lrp);
		return (NULL);
	}

	lrp->recsize = record_size;
	next_rec = lbp->next_rec + lrp->recsize;

	if (lbp->mmap_addr == (intptr_t)MAP_FAILED) {
		/*
		 * Read() case - shouldn't be used very much.
		 * Note: The 'buffer' field is used later on
		 * to determine which method is being used mmap()|read()
		 */
		if (lbp->filesize < next_rec) {
			/* partial record from buffer */
			syslog(LOG_ERR, gettext(
				"Last partial record in work buffer %s "
				"discarded\n"), lbp->bufpath);
			free_lrp(lrp);
			return (NULL);
		}

		if ((lrp->buffer = malloc(lrp->recsize)) == NULL) {
			free_lrp(lrp);
			return (NULL);
		}
		bcopy(sizebuf, lrp->buffer, BYTES_PER_XDR_UNIT);
		if (read(lbp->fd, &lrp->buffer[BYTES_PER_XDR_UNIT],
			lrp->recsize - BYTES_PER_XDR_UNIT) <= 0) {
			free_lrp(lrp);
			return (NULL);
		}
	} else if (lbp->filesize < next_rec - lbp->mmap_addr) {
			/* partial record from buffer */
			syslog(LOG_ERR, gettext(
				"Last partial record in work buffer %s "
				"discarded\n"), lbp->bufpath);
			free_lrp(lrp);
			return (NULL);
	}


	/* other initializations */
	lrp->next = lrp->prev = lrp;
	/* Keep track of the offset at which this record was read */
	if (lbp->mmap_addr == (intptr_t)MAP_FAILED)
		lrp->f_offset = lbp->next_rec;
	else
		lrp->f_offset = lbp->next_rec - lbp->mmap_addr;
	/* This is the true address of the record */
	lrp->record = lbp->next_rec;
	lrp->xdrargs = lrp->xdrres = NULL;
	lrp->lbp = lbp;

	/* Here is the logic for mmap() vs. read() */
	buffer = (lrp->buffer != NULL ? lrp->buffer : (caddr_t)lrp->record);

	/* Setup for the 'real' XDR decode of the entire record */
	xdrmem_create(&lrp->xdrs, buffer, lrp->recsize, XDR_DECODE);

	/* calculate the offset for the next record */
	lbp->next_rec = next_rec;

	return (lrp);
}
コード例 #27
0
ファイル: clnt_dg.c プロジェクト: bahamas10/openzfs
static enum clnt_stat
clnt_dg_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp,
	xdrproc_t xresults, caddr_t resultsp, struct timeval utimeout)
{
/* LINTED pointer alignment */
	struct cu_data *cu = (struct cu_data *)cl->cl_private;
	XDR *xdrs;
	int outlen;
	struct rpc_msg reply_msg;
	XDR reply_xdrs;
	struct timeval time_waited;
	bool_t ok;
	int nrefreshes = 2;		/* number of times to refresh cred */
	struct timeval timeout;
	struct timeval retransmit_time;
	struct timeval poll_time;
	struct timeval startime, curtime;
	struct t_unitdata tu_data;
	int res;			/* result of operations */
	uint32_t x_id;

	if (rpc_fd_lock(dgtbl, cu->cu_fd)) {
		rpc_callerr.re_status = RPC_FAILED;
		rpc_callerr.re_errno = errno;
		rpc_fd_unlock(dgtbl, cu->cu_fd);
		return (RPC_FAILED);
	}

	if (cu->cu_total.tv_usec == -1) {
		timeout = utimeout;	/* use supplied timeout */
	} else {
		timeout = cu->cu_total;	/* use default timeout */
	}

	time_waited.tv_sec = 0;
	time_waited.tv_usec = 0;
	retransmit_time = cu->cu_wait;

	tu_data.addr = cu->cu_raddr;

call_again:
	xdrs = &(cu->cu_outxdrs);
	xdrs->x_op = XDR_ENCODE;
	XDR_SETPOS(xdrs, 0);
	/*
	 * Due to little endian byte order, it is necessary to convert to host
	 * format before incrementing xid.
	 */
	/* LINTED pointer cast */
	x_id = ntohl(*(uint32_t *)(cu->cu_outbuf)) + 1;		/* set XID */
	/* LINTED pointer cast */
	*(uint32_t *)cu->cu_outbuf = htonl(x_id);

	if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
		if ((!XDR_PUTBYTES(xdrs, cu->cu_outbuf, cu->cu_xdrpos)) ||
		    (!XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
		    (!AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
		    (!xargs(xdrs, argsp))) {
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (rpc_callerr.re_status = RPC_CANTENCODEARGS);
		}
	} else {
/* LINTED pointer alignment */
		uint32_t *u = (uint32_t *)&cu->cu_outbuf[cu->cu_xdrpos];
		IXDR_PUT_U_INT32(u, proc);
		if (!__rpc_gss_wrap(cl->cl_auth, cu->cu_outbuf,
		    ((char *)u) - cu->cu_outbuf, xdrs, xargs, argsp)) {
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (rpc_callerr.re_status = RPC_CANTENCODEARGS);
		}
	}
	outlen = (int)XDR_GETPOS(xdrs);

send_again:
	tu_data.udata.buf = cu->cu_outbuf_start;
	tu_data.udata.len = outlen;
	tu_data.opt.len = 0;
	if (t_sndudata(cu->cu_fd, &tu_data) == -1) {
		rpc_callerr.re_terrno = t_errno;
		rpc_callerr.re_errno = errno;
		rpc_fd_unlock(dgtbl, cu->cu_fd);
		return (rpc_callerr.re_status = RPC_CANTSEND);
	}

	/*
	 * Hack to provide rpc-based message passing
	 */
	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
		rpc_fd_unlock(dgtbl, cu->cu_fd);
		return (rpc_callerr.re_status = RPC_TIMEDOUT);
	}
	/*
	 * sub-optimal code appears here because we have
	 * some clock time to spare while the packets are in flight.
	 * (We assume that this is actually only executed once.)
	 */
	reply_msg.acpted_rply.ar_verf = _null_auth;
	reply_msg.acpted_rply.ar_results.where = NULL;
	reply_msg.acpted_rply.ar_results.proc = xdr_void;

	/*
	 * Set polling time so that we don't wait for
	 * longer than specified by the total time to wait,
	 * or the retransmit time.
	 */
	poll_time.tv_sec = timeout.tv_sec - time_waited.tv_sec;
	poll_time.tv_usec = timeout.tv_usec - time_waited.tv_usec;
	while (poll_time.tv_usec < 0) {
		poll_time.tv_usec += 1000000;
		poll_time.tv_sec--;
	}

	if (poll_time.tv_sec < 0 || (poll_time.tv_sec == 0 &&
	    poll_time.tv_usec == 0)) {
		/*
		 * this could happen if time_waited >= timeout
		 */
		rpc_fd_unlock(dgtbl, cu->cu_fd);
		return (rpc_callerr.re_status = RPC_TIMEDOUT);
	}

	if (poll_time.tv_sec > retransmit_time.tv_sec ||
	    (poll_time.tv_sec == retransmit_time.tv_sec &&
	    poll_time.tv_usec > retransmit_time.tv_usec))
		poll_time = retransmit_time;


	for (;;) {

		(void) gettimeofday(&startime, NULL);

		switch (poll(&cu->pfdp, 1,
		    __rpc_timeval_to_msec(&poll_time))) {
		case -1:
			if (errno != EINTR && errno != EAGAIN) {
				rpc_callerr.re_errno = errno;
				rpc_callerr.re_terrno = 0;
				rpc_fd_unlock(dgtbl, cu->cu_fd);
				return (rpc_callerr.re_status = RPC_CANTRECV);
			}
			/*FALLTHROUGH*/

		case 0:
			/*
			 * update time waited
			 */
timeout:			(void) gettimeofday(&curtime, NULL);
			time_waited.tv_sec += curtime.tv_sec - startime.tv_sec;
			time_waited.tv_usec += curtime.tv_usec -
			    startime.tv_usec;
			while (time_waited.tv_usec >= 1000000) {
				time_waited.tv_usec -= 1000000;
				time_waited.tv_sec++;
			}
			while (time_waited.tv_usec < 0) {
				time_waited.tv_usec += 1000000;
				time_waited.tv_sec--;
			}

			/*
			 * decrement time left to poll by same amount
			 */
			poll_time.tv_sec -= curtime.tv_sec - startime.tv_sec;
			poll_time.tv_usec -= curtime.tv_usec - startime.tv_usec;
			while (poll_time.tv_usec >= 1000000) {
				poll_time.tv_usec -= 1000000;
				poll_time.tv_sec++;
			}
			while (poll_time.tv_usec < 0) {
				poll_time.tv_usec += 1000000;
				poll_time.tv_sec--;
			}

			/*
			 * if there's time left to poll, poll again
			 */
			if (poll_time.tv_sec > 0 ||
			    (poll_time.tv_sec == 0 && poll_time.tv_usec > 0))
				continue;

			/*
			 * if there's more time left, retransmit;
			 * otherwise, return timeout error
			 */
			if (time_waited.tv_sec < timeout.tv_sec ||
			    (time_waited.tv_sec == timeout.tv_sec &&
			    time_waited.tv_usec < timeout.tv_usec)) {
				/*
				 * update retransmit_time
				 */
				retransmit_time.tv_usec *= 2;
				retransmit_time.tv_sec *= 2;
				while (retransmit_time.tv_usec >= 1000000) {
					retransmit_time.tv_usec -= 1000000;
					retransmit_time.tv_sec++;
				}
				if (retransmit_time.tv_sec >= RPC_MAX_BACKOFF) {
					retransmit_time.tv_sec =
					    RPC_MAX_BACKOFF;
					retransmit_time.tv_usec = 0;
				}
				/*
				 * redo AUTH_MARSHAL if AUTH_DES or RPCSEC_GSS.
				 */
				if (cl->cl_auth->ah_cred.oa_flavor ==
				    AUTH_DES ||
				    cl->cl_auth->ah_cred.oa_flavor ==
				    RPCSEC_GSS)
					goto call_again;
				else
					goto send_again;
			}
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (rpc_callerr.re_status = RPC_TIMEDOUT);

		default:
			break;
		}

		if (cu->pfdp.revents & POLLNVAL || (cu->pfdp.revents == 0)) {
			rpc_callerr.re_status = RPC_CANTRECV;
			/*
			 *	Note:  we're faking errno here because we
			 *	previously would have expected select() to
			 *	return -1 with errno EBADF.  Poll(BA_OS)
			 *	returns 0 and sets the POLLNVAL revents flag
			 *	instead.
			 */
			rpc_callerr.re_errno = errno = EBADF;
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (-1);
		}

		/* We have some data now */
		do {
			int moreflag;		/* flag indicating more data */

			moreflag = 0;

			res = t_rcvudata(cu->cu_fd, cu->cu_tr_data, &moreflag);

			if (moreflag & T_MORE) {
				/*
				 * Drop this packet. I aint got any
				 * more space.
				 */
				res = -1;
				/* I should not really be doing this */
				errno = 0;
				/*
				 * XXX: Not really Buffer overflow in the
				 * sense of TLI.
				 */
				t_errno = TBUFOVFLW;
			}
		} while (res < 0 && (t_errno == TSYSERR && errno == EINTR));
		if (res < 0) {
			int err, errnoflag = FALSE;
#ifdef sun
			if (t_errno == TSYSERR && errno == EWOULDBLOCK)
#else
			if (t_errno == TSYSERR && errno == EAGAIN)
#endif
				continue;
			if (t_errno == TLOOK) {
				if ((err = _rcv_unitdata_err(cu)) == 0)
					continue;
				else if (err == 1)
					errnoflag = TRUE;
			} else {
				rpc_callerr.re_terrno = t_errno;
			}
			if (errnoflag == FALSE)
				rpc_callerr.re_errno = errno;
			rpc_fd_unlock(dgtbl, cu->cu_fd);
			return (rpc_callerr.re_status = RPC_CANTRECV);
		}
		if (cu->cu_tr_data->udata.len < (uint_t)sizeof (uint32_t))
			continue;
		/* see if reply transaction id matches sent id */
		/* LINTED pointer alignment */
		if (*((uint32_t *)(cu->cu_inbuf)) !=
		    /* LINTED pointer alignment */
		    *((uint32_t *)(cu->cu_outbuf)))
			goto timeout;
		/* we now assume we have the proper reply */
		break;
	}

	/*
	 * now decode and validate the response
	 */

	xdrmem_create(&reply_xdrs, cu->cu_inbuf,
	    (uint_t)cu->cu_tr_data->udata.len, XDR_DECODE);
	ok = xdr_replymsg(&reply_xdrs, &reply_msg);
	/* XDR_DESTROY(&reply_xdrs);	save a few cycles on noop destroy */
	if (ok) {
		if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
		    (reply_msg.acpted_rply.ar_stat == SUCCESS))
			rpc_callerr.re_status = RPC_SUCCESS;
		else
			__seterr_reply(&reply_msg, &(rpc_callerr));

		if (rpc_callerr.re_status == RPC_SUCCESS) {
			if (!AUTH_VALIDATE(cl->cl_auth,
			    &reply_msg.acpted_rply.ar_verf)) {
				rpc_callerr.re_status = RPC_AUTHERROR;
				rpc_callerr.re_why = AUTH_INVALIDRESP;
			} else if (cl->cl_auth->ah_cred.oa_flavor !=
			    RPCSEC_GSS) {
				if (!(*xresults)(&reply_xdrs, resultsp)) {
					if (rpc_callerr.re_status ==
					    RPC_SUCCESS)
						rpc_callerr.re_status =
						    RPC_CANTDECODERES;
				}
			} else if (!__rpc_gss_unwrap(cl->cl_auth, &reply_xdrs,
			    xresults, resultsp)) {
				if (rpc_callerr.re_status == RPC_SUCCESS)
					rpc_callerr.re_status =
					    RPC_CANTDECODERES;
			}
		}		/* end successful completion */
		/*
		 * If unsuccesful AND error is an authentication error
		 * then refresh credentials and try again, else break
		 */
		else if (rpc_callerr.re_status == RPC_AUTHERROR)
			/* maybe our credentials need to be refreshed ... */
			if (nrefreshes-- &&
			    AUTH_REFRESH(cl->cl_auth, &reply_msg))
				goto call_again;
			else
				/*
				 * We are setting rpc_callerr here given that
				 * libnsl is not reentrant thereby
				 * reinitializing the TSD.  If not set here then
				 * success could be returned even though refresh
				 * failed.
				 */
				rpc_callerr.re_status = RPC_AUTHERROR;

		/* end of unsuccessful completion */
		/* free verifier */
		if (reply_msg.rm_reply.rp_stat == MSG_ACCEPTED &&
		    reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
			xdrs->x_op = XDR_FREE;
			(void) xdr_opaque_auth(xdrs,
			    &(reply_msg.acpted_rply.ar_verf));
		}
	}	/* end of valid reply message */
	else {
		rpc_callerr.re_status = RPC_CANTDECODERES;

	}
	rpc_fd_unlock(dgtbl, cu->cu_fd);
	return (rpc_callerr.re_status);
}
コード例 #28
0
ファイル: readbuf.c プロジェクト: AlainODea/illumos-gate
/*
 * We are rewriting the buffer header at the start of the log buffer
 * for the sole purpose of resetting the bh_offset field.  This is
 * supposed to represent the progress that the nfslogd daemon has made
 * in its processing of the log buffer file.
 * 'lbp->last_record_offset' contains the absolute offset of the end
 * of the last element processed. The on-disk buffer offset is relative
 * to the buffer header, therefore we subtract the length of the buffer
 * header from the absolute offset.
 */
static void
nfslog_rewrite_bufheader(struct nfslog_buf *lbp)
{
	XDR xdrs;
	nfslog_buffer_header bh;
	/* size big enough for buffer header encode */
#define	XBUFSIZE 128
	char buffer[XBUFSIZE];
	unsigned int wsize;

	/*
	 * if version 1 buffer is large and the current offset cannot be
	 * represented, then don't update the offset in the buffer.
	 */
	if (lbp->bh.bh_flags & NFSLOG_BH_OFFSET_OVERFLOW) {
		/* No need to update the header - offset too big */
		return;
	}
	/*
	 * build the buffer header from the original that was saved
	 * on initialization; note that the offset is taken from the
	 * last record processed (the last offset that represents
	 * all records processed without any holes in the processing)
	 */
	bh = lbp->bh;

	/*
	 * if version 1 buffer is large and the current offset cannot be
	 * represented in 32 bits, then save only the last valid offset
	 * in the buffer and mark the flags to indicate that.
	 */
	if ((bh.bh_version > 1) ||
		(lbp->last_record_offset - bh.bh_length < UINT32_MAX)) {
		bh.bh_offset = lbp->last_record_offset - bh.bh_length;
	} else {
		/* don't update the offset in the buffer */
		bh.bh_flags |= NFSLOG_BH_OFFSET_OVERFLOW;
		lbp->bh.bh_flags = bh.bh_flags;
		syslog(LOG_ERR, gettext(
			"nfslog_rewrite_bufheader: %s: offset does not fit "
			"in a 32 bit field\n"), lbp->bufpath);
	}

	xdrmem_create(&xdrs, buffer, XBUFSIZE, XDR_ENCODE);

	if (!xdr_nfslog_buffer_header(&xdrs, &bh)) {
		syslog(LOG_ERR, gettext(
			"error in re-writing buffer file %s header\n"),
			lbp->bufpath);
		return;
	}

	wsize = xdr_getpos(&xdrs);

	if (lbp->mmap_addr == (intptr_t)MAP_FAILED) {
		/* go to the beginning of the file */
		(void) lseek(lbp->fd, 0, SEEK_SET);
		(void) write(lbp->fd, buffer, wsize);
		(void) lseek(lbp->fd, lbp->next_rec, SEEK_SET);
		(void) fsync(lbp->fd);
	} else {
		bcopy(buffer, (void *)lbp->mmap_addr, wsize);
		(void) msync((void *)lbp->mmap_addr, wsize, MS_SYNC);
	}
}
コード例 #29
0
ファイル: clnt_tcp.c プロジェクト: OPSF/uClinux
CLIENT *
clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers,
		int *sockp, u_int sendsz, u_int recvsz)
{
  CLIENT *h;
  struct ct_data *ct;
  struct rpc_msg call_msg;

  h = (CLIENT *) mem_alloc (sizeof (*h));
  ct = (struct ct_data *) mem_alloc (sizeof (*ct));
  if (h == NULL || ct == NULL)
    {
      struct rpc_createerr *ce = &get_rpc_createerr ();
#ifdef USE_IN_LIBIO
      if (_IO_fwide (stderr, 0) > 0)
	(void) fwprintf (stderr, L"%s",
			   _("clnttcp_create: out of memory\n"));
      else
#endif
	(void) fputs (_("clnttcp_create: out of memory\n"), stderr);
      ce->cf_stat = RPC_SYSTEMERROR;
      ce->cf_error.re_errno = ENOMEM;
      goto fooy;
    }

  /*
   * If no port number given ask the pmap for one
   */
  if (raddr->sin_port == 0)
    {
      u_short port;
      if ((port = pmap_getport (raddr, prog, vers, IPPROTO_TCP)) == 0)
	{
	  mem_free ((caddr_t) ct, sizeof (struct ct_data));
	  mem_free ((caddr_t) h, sizeof (CLIENT));
	  return ((CLIENT *) NULL);
	}
      raddr->sin_port = htons (port);
    }

  /*
   * If no socket given, open one
   */
  if (*sockp < 0)
    {
      *sockp = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
      (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
      if ((*sockp < 0)
	  || (connect (*sockp, (struct sockaddr *) raddr,
			 sizeof (*raddr)) < 0))
	{
	  struct rpc_createerr *ce = &get_rpc_createerr ();
	  ce->cf_stat = RPC_SYSTEMERROR;
	  ce->cf_error.re_errno = errno;
	  if (*sockp >= 0)
	    (void) close (*sockp);
	  goto fooy;
	}
      ct->ct_closeit = TRUE;
    }
  else
    {
      ct->ct_closeit = FALSE;
    }

  /*
   * Set up private data struct
   */
  ct->ct_sock = *sockp;
  ct->ct_wait.tv_usec = 0;
  ct->ct_waitset = FALSE;
  ct->ct_addr = *raddr;

  /*
   * Initialize call message
   */
  call_msg.rm_xid = _create_xid ();
  call_msg.rm_direction = CALL;
  call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  call_msg.rm_call.cb_prog = prog;
  call_msg.rm_call.cb_vers = vers;

  /*
   * pre-serialize the static part of the call msg and stash it away
   */
  xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
		 XDR_ENCODE);
  if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
    {
      if (ct->ct_closeit)
	{
	  (void) close (*sockp);
	}
      goto fooy;
    }
  ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
  XDR_DESTROY (&(ct->ct_xdrs));

  /*
   * Create a client handle which uses xdrrec for serialization
   * and authnone for authentication.
   */
  xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
		 (caddr_t) ct, readtcp, writetcp);
  h->cl_ops = &tcp_ops;
  h->cl_private = (caddr_t) ct;
  h->cl_auth = authnone_create ();
  return h;

fooy:
  /*
   * Something goofed, free stuff and barf
   */
  mem_free ((caddr_t) ct, sizeof (struct ct_data));
  mem_free ((caddr_t) h, sizeof (CLIENT));
  return ((CLIENT *) NULL);
}
コード例 #30
0
ファイル: nfs_cast.c プロジェクト: AlainODea/illumos-gate
/*
 * This routine is designed to be able to "ping"
 * a list of hosts and create a list of responding
 * hosts sorted by response time.
 * This must be done without any prior
 * contact with the host - therefore the "ping"
 * must be to a "well-known" address.  The outstanding
 * candidate here is the address of "rpcbind".
 *
 * A response to a ping is no guarantee that the host
 * is running NFS, has a mount daemon, or exports
 * the required filesystem.  If the subsequent
 * mount attempt fails then the host will be marked
 * "ignore" and the host list will be re-pinged
 * (sans the bad host). This process continues
 * until a successful mount is achieved or until
 * there are no hosts left to try.
 */
enum clnt_stat
nfs_cast(struct mapfs *mfs_in, struct mapfs **mfs_out, int timeout)
{
	enum clnt_stat stat;
	AUTH *sys_auth = authsys_create_default();
	XDR xdr_stream;
	register XDR *xdrs = &xdr_stream;
	int outlen;
	int if_inx;
	int tsec;
	int flag;
	int sent, addr_cnt, rcvd, if_cnt;
	fd_set readfds, mask;
	register ulong_t xid;		/* xid - unique per addr */
	register int i;
	struct rpc_msg msg;
	struct timeval t, rcv_timeout;
	char outbuf[UDPMSGSIZE], inbuf[UDPMSGSIZE];
	struct t_unitdata t_udata, t_rdata;
	struct nd_hostserv hs;
	struct nd_addrlist *retaddrs;
	struct transp *tr_head;
	struct transp *trans, *prev_trans;
	struct addrs *a, *prev_addr;
	struct tstamps *ts, *prev_ts;
	NCONF_HANDLE *nc = NULL;
	struct netconfig *nconf;
	struct rlimit rl;
	int dtbsize;
	struct mapfs *mfs;

	/*
	 * For each connectionless transport get a list of
	 * host addresses.  Any single host may have
	 * addresses on several transports.
	 */
	addr_cnt = sent = rcvd = 0;
	tr_head = NULL;
	FD_ZERO(&mask);

	/*
	 * Set the default select size to be the maximum FD_SETSIZE, unless
	 * the current rlimit is lower.
	 */
	dtbsize = FD_SETSIZE;
	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
		if (rl.rlim_cur < FD_SETSIZE)
			dtbsize = rl.rlim_cur;
	}

	prev_trans = NULL;
	prev_addr = NULL;
	prev_ts = NULL;
	for (mfs = mfs_in; mfs; mfs = mfs->mfs_next) {

		if (trace > 2)
			trace_prt(1, "nfs_cast: host=%s\n", mfs->mfs_host);

		nc = setnetconfig();
		if (nc == NULL) {
			stat = RPC_CANTSEND;
			goto done_broad;
		}
		while (nconf = getnetconfig(nc)) {
			if (!(nconf->nc_flag & NC_VISIBLE) ||
			    nconf->nc_semantics != NC_TPI_CLTS ||
			    (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0))
				continue;
			trans = (struct transp *)malloc(sizeof (*trans));
			if (trans == NULL) {
				syslog(LOG_ERR, "no memory");
				stat = RPC_CANTSEND;
				goto done_broad;
			}
			(void) memset(trans, 0, sizeof (*trans));
			if (tr_head == NULL)
				tr_head = trans;
			else
				prev_trans->tr_next = trans;
			prev_trans = trans;

			trans->tr_fd = t_open(nconf->nc_device, O_RDWR, NULL);
			if (trans->tr_fd < 0) {
				syslog(LOG_ERR, "nfscast: t_open: %s:%m",
					nconf->nc_device);
				stat = RPC_CANTSEND;
				goto done_broad;
			}
			if (t_bind(trans->tr_fd, (struct t_bind *)NULL,
				(struct t_bind *)NULL) < 0) {
				syslog(LOG_ERR, "nfscast: t_bind: %m");
				stat = RPC_CANTSEND;
				goto done_broad;
			}
			trans->tr_taddr =
				/* LINTED pointer alignment */
			(struct t_bind *)t_alloc(trans->tr_fd, T_BIND, T_ADDR);
			if (trans->tr_taddr == (struct t_bind *)NULL) {
				syslog(LOG_ERR, "nfscast: t_alloc: %m");
				stat = RPC_SYSTEMERROR;
				goto done_broad;
			}

			trans->tr_device = nconf->nc_device;
			FD_SET(trans->tr_fd, &mask);

			if_inx = 0;
			hs.h_host = mfs->mfs_host;
			hs.h_serv = "rpcbind";
			if (netdir_getbyname(nconf, &hs, &retaddrs) == ND_OK) {

				/*
				 * If mfs->ignore is previously set for
				 * this map, clear it. Because a host can
				 * have either v6 or v4 address
				 */
				if (mfs->mfs_ignore == 1)
					mfs->mfs_ignore = 0;

				a = (struct addrs *)malloc(sizeof (*a));
				if (a == NULL) {
					syslog(LOG_ERR, "no memory");
					stat = RPC_CANTSEND;
					goto done_broad;
				}
				(void) memset(a, 0, sizeof (*a));
				if (trans->tr_addrs == NULL)
					trans->tr_addrs = a;
				else
					prev_addr->addr_next = a;
				prev_addr = a;
				a->addr_if_tstamps = NULL;
				a->addr_mfs = mfs;
				a->addr_addrs = retaddrs;
				if_cnt = retaddrs->n_cnt;
				while (if_cnt--) {
					ts = (struct tstamps *)
						malloc(sizeof (*ts));
					if (ts == NULL) {
						syslog(LOG_ERR, "no memory");
						stat = RPC_CANTSEND;
						goto done_broad;
					}
					(void) memset(ts, 0, sizeof (*ts));
					ts->ts_penalty = mfs->mfs_penalty;
					if (a->addr_if_tstamps == NULL)
						a->addr_if_tstamps = ts;
					else
						prev_ts->ts_next = ts;
					prev_ts = ts;
					ts->ts_inx = if_inx++;
					addr_cnt++;
				}
				break;
			} else {
				mfs->mfs_ignore = 1;
				if (verbose)
					syslog(LOG_ERR,
				"%s:%s address not known",
				mfs->mfs_host,
				strcmp(nconf->nc_proto, NC_INET)?"IPv6":"IPv4");
			}
		} /* while */

		endnetconfig(nc);
		nc = NULL;
	} /* for */
	if (addr_cnt == 0) {
		syslog(LOG_ERR, "nfscast: couldn't find addresses");
		stat = RPC_CANTSEND;
		goto done_broad;
	}

	(void) gettimeofday(&t, (struct timezone *)0);
	xid = (getpid() ^ t.tv_sec ^ t.tv_usec) & ~0xFF;
	t.tv_usec = 0;

	/* serialize the RPC header */

	msg.rm_direction = CALL;
	msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
	msg.rm_call.cb_prog = RPCBPROG;
	/*
	 * we can not use RPCBVERS here since it doesn't exist in 4.X,
	 * the fix to bug 1139883 has made the 4.X portmapper silent to
	 * version mismatches. This causes the RPC call to the remote
	 * portmapper to simply be ignored if it's not Version 2.
	 */
	msg.rm_call.cb_vers = PMAPVERS;
	msg.rm_call.cb_proc = NULLPROC;
	if (sys_auth == (AUTH *)NULL) {
		stat = RPC_SYSTEMERROR;
		goto done_broad;
	}
	msg.rm_call.cb_cred = sys_auth->ah_cred;
	msg.rm_call.cb_verf = sys_auth->ah_verf;
	xdrmem_create(xdrs, outbuf, sizeof (outbuf), XDR_ENCODE);
	if (! xdr_callmsg(xdrs, &msg)) {
		stat = RPC_CANTENCODEARGS;
		goto done_broad;
	}
	outlen = (int)xdr_getpos(xdrs);
	xdr_destroy(xdrs);

	t_udata.opt.len = 0;
	t_udata.udata.buf = outbuf;
	t_udata.udata.len = outlen;

	/*
	 * Basic loop: send packet to all hosts and wait for response(s).
	 * The response timeout grows larger per iteration.
	 * A unique xid is assigned to each address in order to
	 * correctly match the replies.
	 */
	for (tsec = 4; timeout > 0; tsec *= 2) {

		timeout -= tsec;
		if (timeout <= 0)
			tsec += timeout;

		rcv_timeout.tv_sec = tsec;
		rcv_timeout.tv_usec = 0;

		sent = 0;
		for (trans = tr_head; trans; trans = trans->tr_next) {
			for (a = trans->tr_addrs; a; a = a->addr_next) {
				struct netbuf *if_netbuf =
					a->addr_addrs->n_addrs;
				ts = a->addr_if_tstamps;
				if_cnt = a->addr_addrs->n_cnt;
				while (if_cnt--) {

					/*
					 * xid is the first thing in
					 * preserialized buffer
					 */
					/* LINTED pointer alignment */
					*((ulong_t *)outbuf) =
						htonl(xid + ts->ts_inx);
					(void) gettimeofday(&(ts->ts_timeval),
						(struct timezone *)0);
					/*
					 * Check if already received
					 * from a previous iteration.
					 */
					if (ts->ts_rcvd) {
						sent++;
						ts = ts->ts_next;
						continue;
					}

					t_udata.addr = *if_netbuf++;

					if (t_sndudata(trans->tr_fd,
							&t_udata) == 0) {
						sent++;
					}

					ts = ts->ts_next;
				}
			}
		}
		if (sent == 0) {		/* no packets sent ? */
			stat = RPC_CANTSEND;
			goto done_broad;
		}

		/*
		 * Have sent all the packets.  Now collect the responses...
		 */
		rcvd = 0;
	recv_again:
		msg.acpted_rply.ar_verf = _null_auth;
		msg.acpted_rply.ar_results.proc = xdr_void;
		readfds = mask;

		switch (select(dtbsize, &readfds,
			(fd_set *)NULL, (fd_set *)NULL, &rcv_timeout)) {

		case 0: /* Timed out */
			/*
			 * If we got at least one response in the
			 * last interval, then don't wait for any
			 * more.  In theory we should wait for
			 * the max weighting (penalty) value so
			 * that a very slow server has a chance to
			 * respond but this could take a long time
			 * if the admin has set a high weighting
			 * value.
			 */
			if (rcvd > 0)
				goto done_broad;

			stat = RPC_TIMEDOUT;
			continue;

		case -1:  /* some kind of error */
			if (errno == EINTR)
				goto recv_again;
			syslog(LOG_ERR, "nfscast: select: %m");
			if (rcvd == 0)
				stat = RPC_CANTRECV;
			goto done_broad;

		}  /* end of select results switch */

		for (trans = tr_head; trans; trans = trans->tr_next) {
			if (FD_ISSET(trans->tr_fd, &readfds))
				break;
		}
		if (trans == NULL)
			goto recv_again;

	try_again:
		t_rdata.addr = trans->tr_taddr->addr;
		t_rdata.udata.buf = inbuf;
		t_rdata.udata.maxlen = sizeof (inbuf);
		t_rdata.udata.len = 0;
		t_rdata.opt.len = 0;
		if (t_rcvudata(trans->tr_fd, &t_rdata, &flag) < 0) {
			if (errno == EINTR)
				goto try_again;
			syslog(LOG_ERR, "nfscast: t_rcvudata: %s:%m",
				trans->tr_device);
			stat = RPC_CANTRECV;
			continue;
		}
		if (t_rdata.udata.len < sizeof (ulong_t))
			goto recv_again;
		if (flag & T_MORE) {
			syslog(LOG_ERR,
				"nfscast: t_rcvudata: %s: buffer overflow",
				trans->tr_device);
			goto recv_again;
		}

		/*
		 * see if reply transaction id matches sent id.
		 * If so, decode the results.
		 * Note: received addr is ignored, it could be
		 * different from the send addr if the host has
		 * more than one addr.
		 */
		xdrmem_create(xdrs, inbuf, (uint_t)t_rdata.udata.len,
								XDR_DECODE);
		if (xdr_replymsg(xdrs, &msg)) {
		    if (msg.rm_reply.rp_stat == MSG_ACCEPTED &&
			(msg.rm_xid & ~0xFF) == xid) {
			struct addrs *curr_addr;

			i = msg.rm_xid & 0xFF;
			for (curr_addr = trans->tr_addrs; curr_addr;
			    curr_addr = curr_addr->addr_next) {
			    for (ts = curr_addr->addr_if_tstamps; ts;
				ts = ts->ts_next)
				if (ts->ts_inx == i && !ts->ts_rcvd) {
					ts->ts_rcvd = 1;
					calc_resp_time(&ts->ts_timeval);
					stat = RPC_SUCCESS;
					rcvd++;
					break;
				}
			}
		    } /* otherwise, we just ignore the errors ... */
		}
		xdrs->x_op = XDR_FREE;
		msg.acpted_rply.ar_results.proc = xdr_void;
		(void) xdr_replymsg(xdrs, &msg);
		XDR_DESTROY(xdrs);
		if (rcvd == sent)
			goto done_broad;
		else
			goto recv_again;
	}
	if (!rcvd)
		stat = RPC_TIMEDOUT;

done_broad:
	if (rcvd) {
		*mfs_out = sort_responses(tr_head);
		stat = RPC_SUCCESS;
	}
	if (nc)
		endnetconfig(nc);
	free_transports(tr_head);
	AUTH_DESTROY(sys_auth);
	return (stat);
}