Example #1
0
TEST(test_encoder, test_encode_procedure_message) {
  uint8_t data[256];
  krpc_call_t call;
  krpc_argument_t arguments[0];
  ASSERT_EQ(KRPC_OK, krpc_call(&call, 99, 42, 0, arguments));
  pb_ostream_t stream = pb_ostream_from_buffer(data, sizeof(data));
  ASSERT_EQ(KRPC_OK, krpc_encode_message_ProcedureCall(&stream, &call.message));
  std::string expected = "0a0012002063282a";
  ASSERT_EQ(expected, hexlify(data, stream.bytes_written));
}
Example #2
0
File: krpc_subr.c Project: argp/xnu
/*
 * Call portmap to lookup a port number for a particular rpc program
 * Returns non-zero error on failure.
 */
int
krpc_portmap(
	struct sockaddr_in *sin,	/* server address */
	u_int prog, u_int vers, u_int proto,	/* host order */
	u_int16_t *portp)		/* network order */
{
	struct sdata {
		u_int32_t prog;		/* call program */
		u_int32_t vers;		/* call version */
		u_int32_t proto;	/* call protocol */
		u_int32_t port;		/* call port (unused) */
	} *sdata;
	struct rdata {
		u_int16_t pad;
		u_int16_t port;
	} *rdata;
	mbuf_t m;
	int error;

	/* The portmapper port is fixed. */
	if (prog == PMAPPROG) {
		*portp = htons(PMAPPORT);
		return 0;
	}

	error = mbuf_gethdr(MBUF_WAITOK, MBUF_TYPE_DATA, &m);
	if (error)
		return error;
	mbuf_setlen(m, sizeof(*sdata));
	mbuf_pkthdr_setlen(m, sizeof(*sdata));
	sdata = mbuf_data(m);

	/* Do the RPC to get it. */
	sdata->prog = htonl(prog);
	sdata->vers = htonl(vers);
	sdata->proto = htonl(proto);
	sdata->port = 0;

	sin->sin_port = htons(PMAPPORT);
	error = krpc_call(sin, SOCK_DGRAM, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, &m, NULL);
	if (error) 
		return error;

	rdata = mbuf_data(m);

	if (mbuf_len(m) >= sizeof(*rdata)) {
		*portp = rdata->port;
	}

	if (mbuf_len(m) < sizeof(*rdata) || !rdata->port)
		error = EPROGUNAVAIL;

	mbuf_freem(m);
	return (error);
}
Example #3
0
TEST(test_encoder, test_encode_procedure_message_with_args) {
  uint8_t data[256];
  int32_t x = 42;
  double y = 3.14159;
  krpc_call_t call;
  krpc_argument_t arguments[2];
  ASSERT_EQ(KRPC_OK, krpc_call(&call, 99, 42, 2, arguments));
  ASSERT_EQ(KRPC_OK, krpc_add_argument(&call, 0, &krpc_encode_callback_int32, &x));
  ASSERT_EQ(KRPC_OK, krpc_add_argument(&call, 1, &krpc_encode_callback_double, &y));
  pb_ostream_t stream = pb_ostream_from_buffer(data, sizeof(data));
  ASSERT_EQ(KRPC_OK, krpc_encode_message_ProcedureCall(&stream, &call.message));
  std::string expected = "0a0012001a031201541a0c080112086e861bf0f92109402063282a";
  ASSERT_EQ(expected, hexlify(data, stream.bytes_written));
}
Example #4
0
/*
 * Call portmap to lookup a port number for a particular rpc program
 * Returns non-zero error on failure.
 */
int
krpc_portmap(struct sockaddr_in *sin, u_int prog, u_int vers, u_int16_t *portp)
{
	struct sdata {
		u_int32_t prog;		/* call program */
		u_int32_t vers;		/* call version */
		u_int32_t proto;	/* call protocol */
		u_int32_t port;		/* call port (unused) */
	} *sdata;
	struct rdata {
		u_int16_t pad;
		u_int16_t port;
	} *rdata;
	struct mbuf *m;
	int error;

	/* The portmapper port is fixed. */
	if (prog == PMAPPROG) {
		*portp = htons(PMAPPORT);
		return 0;
	}

	m = m_get(M_WAIT, MT_DATA);
	sdata = mtod(m, struct sdata *);
	m->m_len = sizeof(*sdata);

	/* Do the RPC to get it. */
	sdata->prog = txdr_unsigned(prog);
	sdata->vers = txdr_unsigned(vers);
	sdata->proto = txdr_unsigned(IPPROTO_UDP);
	sdata->port = 0;

	sin->sin_port = htons(PMAPPORT);
	error = krpc_call(sin, PMAPPROG, PMAPVERS,
	    PMAPPROC_GETPORT, &m, NULL, -1);
	if (error) 
		return error;

	if (m->m_len < sizeof(*rdata)) {
		m = m_pullup(m, sizeof(*rdata));
		if (m == NULL)
			return ENOBUFS;
	}
	rdata = mtod(m, struct rdata *);
	*portp = rdata->port;

	m_freem(m);
	return 0;
}
Example #5
0
/*
 * RPC: mountd/mount
 * Given a server pathname, get an NFS file handle.
 * Also, sets sin->sin_port to the NFS service port.
 */
int
md_mount(struct sockaddr_in *mdsin,		/* mountd server address */
	 char *path,
	 u_char *fhp,
	 int *fhsizep,
	 struct nfs_args *args,
	 struct thread *td)
{
	struct mbuf *m;
	int error;
	int authunixok;
	int authcount;
	int authver;
	
	/* First try NFS v3 */
	/* Get port number for MOUNTD. */
	error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3,
			     &mdsin->sin_port, td);
	if (error == 0) {
		m = xdr_string_encode(path, strlen(path));
		
		/* Do RPC to mountd. */
		error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3,
				  RPCMNT_MOUNT, &m, NULL, td);
	}
	if (error == 0) {
		args->flags |= NFSMNT_NFSV3;
	} else {
		/* Fallback to NFS v2 */
		
		/* Get port number for MOUNTD. */
		error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
				     &mdsin->sin_port, td);
		if (error != 0)
			return error;
		
		m = xdr_string_encode(path, strlen(path));
		
		/* Do RPC to mountd. */
		error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
				  RPCMNT_MOUNT, &m, NULL, td);
		if (error != 0)
			return error;	/* message already freed */
		args->flags &= ~NFSMNT_NFSV3;
	}

	if (xdr_int_decode(&m, &error) != 0 || error != 0)
		goto bad;
	
	if ((args->flags & NFSMNT_NFSV3) != 0) {
		if (xdr_int_decode(&m, fhsizep) != 0 ||
		    *fhsizep > NFSX_V3FHMAX ||
		    *fhsizep <= 0)
			goto bad;
	} else
		*fhsizep = NFSX_V2FH;

	if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
		goto bad;

	if (args->flags & NFSMNT_NFSV3) {
		if (xdr_int_decode(&m, &authcount) != 0)
			goto bad;
		authunixok = 0;
		if (authcount < 0 || authcount > 100)
			goto bad;
		while (authcount > 0) {
			if (xdr_int_decode(&m, &authver) != 0)
				goto bad;
			if (authver == RPCAUTH_UNIX)
				authunixok = 1;
			authcount--;
		}
		if (authunixok == 0)
			goto bad;
	}
	  
	/* Set port number for NFS use. */
	error = krpc_portmap(mdsin, NFS_PROG,
			     (args->flags &
			      NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
			     &mdsin->sin_port, td);
	
	goto out;
	
bad:
	error = EBADRPC;
	
out:
	m_freem(m);
	return error;
}
Example #6
0
/*
 * RPC: mountd/mount
 * Given a server pathname, get an NFS file handle.
 * Also, sets sin->sin_port to the NFS service port.
 *
 * mdsin   mountd server address
 */
static int
md_mount(struct sockaddr_in *mdsin, char *path,
	 struct nfs_args *argp, struct lwp *lwp)
{
	/* The RPC structures */
	struct rdata {
		u_int32_t errno;
		union {
			u_int8_t  v2fh[NFSX_V2FH];
			struct {
				u_int32_t fhlen;
				u_int8_t  fh[1];
			} v3fh;
		} fh;
	} *rdata;
	struct mbuf *m;
	u_int8_t *fh;
	int minlen, error;
	int mntver;

	mntver = (argp->flags & NFSMNT_NFSV3) ? 3 : 2;
	do {
		/*
		 * Get port number for MOUNTD.
		 */
		error = krpc_portmap(mdsin, RPCPROG_MNT, mntver,
		                    IPPROTO_UDP, &mdsin->sin_port, lwp);
		if (error)
			continue;

		/* This mbuf is consumed by krpc_call. */
		m = xdr_string_encode(path, strlen(path));
		if (m == NULL)
			return ENOMEM;

		/* Do RPC to mountd. */
		error = krpc_call(mdsin, RPCPROG_MNT, mntver,
		                  RPCMNT_MOUNT, &m, NULL, lwp);
		if (error != EPROGMISMATCH)
			break;
		/* Try lower version of mountd. */
	} while (--mntver >= 1);
	if (error) {
		printf("nfs_boot: mountd error=%d\n", error);
		return error;
	}
	if (mntver != 3)
		argp->flags &= ~NFSMNT_NFSV3;

	/* The reply might have only the errno. */
	if (m->m_len < 4)
		goto bad;
	/* Have at least errno, so check that. */
	rdata = mtod(m, struct rdata *);
	error = fxdr_unsigned(u_int32_t, rdata->errno);
	if (error)
		goto out;

	/* Have errno==0, so the fh must be there. */
	if (mntver == 3) {
		argp->fhsize   = fxdr_unsigned(u_int32_t, rdata->fh.v3fh.fhlen);
		if (argp->fhsize > NFSX_V3FHMAX)
			goto bad;
		minlen = 2 * sizeof(u_int32_t) + argp->fhsize;
	} else {
		argp->fhsize   = NFSX_V2FH;
		minlen = sizeof(u_int32_t) + argp->fhsize;
	}

	if (m->m_len < minlen) {
		m = m_pullup(m, minlen);
		if (m == NULL)
			return(EBADRPC);
		rdata = mtod(m, struct rdata *);
	}