예제 #1
0
/*
 * 0.	Get the server port number if not yet set
 */
static void
call_bind(struct rpc_task *task)
{
	struct rpc_clnt	*clnt = task->tk_client;

	task->tk_action = call_reserve;
	task->tk_status = 0;
	if (!clnt->cl_port)
		rpc_getport(task, clnt);
}
예제 #2
0
/*
 * Make a rpc call; return length of answer
 * Note: Caller must leave room for headers.
 */
ssize_t
rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc,
	void *sdata, size_t slen, void **rdata, void **pkt)
{
	ssize_t cc, rsize;
	struct auth_info *auth;
	struct rpc_call *call;
	struct rpc_reply *reply;
	char *send_head, *send_tail;
	void *ptr;
	n_long x;
	int port;	/* host order */

#ifdef RPC_DEBUG
	if (debug)
		printf("rpc_call: prog=0x%x vers=%d proc=%d\n",
		    prog, vers, proc);
#endif

	port = rpc_getport(d, prog, vers);
	if (port == -1)
		return (-1);

	d->destport = htons(port);

	/*
	 * Prepend authorization stuff and headers.
	 * Note, must prepend things in reverse order.
	 */
	send_head = sdata;
	send_tail = (char *)sdata + slen;

	/* Auth verifier is always auth_null */
	send_head -= sizeof(*auth);
	auth = (struct auth_info *)send_head;
	auth->authtype = htonl(RPCAUTH_NULL);
	auth->authlen = 0;

	/* Auth credentials: always auth unix (as root) */
	send_head -= sizeof(struct auth_unix);
	bzero(send_head, sizeof(struct auth_unix));
	send_head -= sizeof(*auth);
	auth = (struct auth_info *)send_head;
	auth->authtype = htonl(RPCAUTH_UNIX);
	auth->authlen = htonl(sizeof(struct auth_unix));

	/* RPC call structure. */
	send_head -= sizeof(*call);
	call = (struct rpc_call *)send_head;
	rpc_xid++;
	call->rp_xid       = htonl(rpc_xid);
	call->rp_direction = htonl(RPC_CALL);
	call->rp_rpcvers   = htonl(RPC_VER2);
	call->rp_prog = htonl(prog);
	call->rp_vers = htonl(vers);
	call->rp_proc = htonl(proc);

	ptr = NULL;
	cc = sendrecv(d,
	    sendudp, send_head, send_tail - send_head,
	    recvrpc, &ptr, (void **)&reply);

#ifdef RPC_DEBUG
	if (debug)
		printf("callrpc: cc=%zd\n", cc);
#endif
	if (cc == -1)
		return (-1);

	if (cc <= sizeof(*reply)) {
		errno = EBADRPC;
		free(ptr);
		return (-1);
	}

	/*
	 * Check the RPC reply status.
	 * The xid, dir, astatus were already checked.
	 */
	auth = &reply->rp_u.rpu_rok.rok_auth;
	x = ntohl(auth->authlen);
	if (x != 0) {
#ifdef RPC_DEBUG
		if (debug)
			printf("callrpc: reply auth != NULL\n");
#endif
		errno = EBADRPC;
		free(ptr);
		return (-1);
	}
	x = ntohl(reply->rp_u.rpu_rok.rok_status);
	if (x != 0) {
		printf("callrpc: error = %ld\n", (long)x);
		errno = EBADRPC;
		free(ptr);
		return (-1);
	}

	rsize = cc - sizeof(*reply);
	*rdata = (void *)((uintptr_t)reply + sizeof(*reply));
	*pkt = ptr;
	return (rsize);
}
예제 #3
0
파일: rpc.c 프로젝트: appleorange1/bitrig
/*
 * Make a rpc call; return length of answer
 * Note: Caller must leave room for headers.
 */
ssize_t
rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc, void *sdata,
    size_t slen, void *rdata, size_t rlen)
{
	ssize_t cc;
	struct auth_info *auth;
	struct rpc_call *call;
	struct rpc_reply *reply;
	char *send_head, *send_tail;
	char *recv_head, *recv_tail;
	n_long x;
	int port;	/* host order */

#ifdef RPC_DEBUG
	if (debug)
		printf("rpc_call: prog=0x%x vers=%d proc=%d\n",
		    prog, vers, proc);
#endif

	port = rpc_getport(d, prog, vers);
	if (port == -1)
		return (-1);

	d->destport = htons(port);

	/*
	 * Prepend authorization stuff and headers.
	 * Note, must prepend things in reverse order.
	 */
	send_head = sdata;
	send_tail = (char *)sdata + slen;

	/* Auth verifier is always auth_null */
	send_head -= sizeof(*auth);
	auth = (struct auth_info *)send_head;
	auth->authtype = htonl(RPCAUTH_NULL);
	auth->authlen = 0;

#if 1
	/* Auth credentials: always auth unix (as root) */
	send_head -= sizeof(struct auth_unix);
	bzero(send_head, sizeof(struct auth_unix));
	send_head -= sizeof(*auth);
	auth = (struct auth_info *)send_head;
	auth->authtype = htonl(RPCAUTH_UNIX);
	auth->authlen = htonl(sizeof(struct auth_unix));
#else
	/* Auth credentials: always auth_null (XXX OK?) */
	send_head -= sizeof(*auth);
	auth = send_head;
	auth->authtype = htonl(RPCAUTH_NULL);
	auth->authlen = 0;
#endif

	/* RPC call structure. */
	send_head -= sizeof(*call);
	call = (struct rpc_call *)send_head;
	rpc_xid++;
	call->rp_xid       = htonl(rpc_xid);
	call->rp_direction = htonl(RPC_CALL);
	call->rp_rpcvers   = htonl(RPC_VER2);
	call->rp_prog = htonl(prog);
	call->rp_vers = htonl(vers);
	call->rp_proc = htonl(proc);

	/* Make room for the rpc_reply header. */
	recv_head = rdata;
	recv_tail = (char *)rdata + rlen;
	recv_head -= sizeof(*reply);

	cc = sendrecv(d,
	    sendudp, send_head, send_tail - send_head,
	    recvrpc, recv_head, recv_tail - recv_head);

#ifdef RPC_DEBUG
	if (debug)
		printf("callrpc: cc=%d rlen=%d\n", cc, rlen);
#endif
	if (cc < -1)
		return (-1);

	if ((size_t)cc <= sizeof(*reply)) {
		errno = EBADRPC;
		return (-1);
	}

	recv_tail = recv_head + cc;

	/*
	 * Check the RPC reply status.
	 * The xid, dir, astatus were already checked.
	 */
	reply = (struct rpc_reply *)recv_head;
	auth = &reply->rp_u.rpu_rok.rok_auth;
	x = ntohl(auth->authlen);
	if (x != 0) {
#ifdef RPC_DEBUG
		if (debug)
			printf("callrpc: reply auth != NULL\n");
#endif
		errno = EBADRPC;
		return(-1);
	}
	x = ntohl(reply->rp_u.rpu_rok.rok_status);
	if (x != 0) {
		printf("callrpc: error = %d\n", x);
		errno = EBADRPC;
		return(-1);
	}
	recv_head += sizeof(*reply);

	return (ssize_t)(recv_tail - recv_head);
}