1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
#include <sys/types.h>
#include <netinet/in.h>
#include <asm/byteorder.h> /* __constant_hton* */
#include <stdio.h>
#include <stdlib.h>
#include "nfsmount.h"
#include "sunrpc.h"
struct portmap_call {
struct rpc_call rpc;
uint32_t program;
uint32_t version;
uint32_t proto;
uint32_t port;
};
struct portmap_reply {
struct rpc_reply rpc;
uint32_t port;
};
static struct portmap_call call = {
.rpc = {
.program = __constant_htonl(RPC_PMAP_PROGRAM),
.prog_vers = __constant_htonl(RPC_PMAP_VERSION),
.proc = __constant_htonl(PMAP_PROC_GETPORT),
}
};
uint32_t portmap(uint32_t server, uint32_t program, uint32_t version, uint32_t proto)
{
struct portmap_reply reply;
struct client *clnt;
struct rpc rpc;
uint32_t port = 0;
clnt = tcp_client(server, RPC_PMAP_PORT, 0);
if (clnt == NULL) {
clnt = udp_client(server, RPC_PMAP_PORT, 0);
if (clnt == NULL)
goto bail;
}
call.program = htonl(program);
call.version = htonl(version);
call.proto = htonl(proto);
rpc.call = (struct rpc_call *)&call;
rpc.call_len = sizeof(call);
rpc.reply = (struct rpc_reply *)&reply;
rpc.reply_len = sizeof(reply);
if (rpc_call(clnt, &rpc) < 0)
goto bail;
if (rpc.reply_len < sizeof(reply)) {
fprintf(stderr, "incomplete reply: %zu < %zu\n",
rpc.reply_len, sizeof(reply));
goto bail;
}
port = ntohl(reply.port);
bail:
dprintf("Port for %d/%d[%s]: %d\n", program, version,
proto == IPPROTO_TCP ? "tcp" : "udp", port);
if (clnt)
client_free(clnt);
return port;
}
|