Read the max read/write sizes supported when connecting to NFS
[deb_libnfs.git] / examples / nfsclient-raw.c
CommitLineData
84004dbf
RS
1/*
2 Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2010
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
16*/
17
18/* Example program using the lowlevel raw interface.
19 * This allow accurate control of the exact commands that are being used.
20 */
21
22#define SERVER "10.1.1.27"
f4b9cb0e 23#define EXPORT "/shared"
84004dbf
RS
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <poll.h>
28#include "libnfs.h"
29#include "libnfs-raw.h"
30#include "libnfs-raw-mount.h"
f4b9cb0e 31#include "libnfs-raw-nfs.h"
84004dbf
RS
32
33struct client {
34 char *server;
35 char *export;
36 uint32_t mount_port;
37 int is_finished;
f4b9cb0e 38 struct nfs_fh3 rootfh;
84004dbf
RS
39};
40
f4b9cb0e
RS
41void nfs_fsinfo_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
42{
43 struct client *client = private_data;
44 FSINFO3res *res = data;
45
46 if (status == RPC_STATUS_ERROR) {
47 printf("nfs/fsinfo call failed with \"%s\"\n", (char *)data);
48 exit(10);
49 }
50 if (status != RPC_STATUS_SUCCESS) {
51 printf("nfs/fsinfo call to server %s failed, status:%d\n", client->server, status);
52 exit(10);
53 }
54
55 printf("Got reply from server for NFS/FSINFO procedure.\n");
56 printf("Read Max:%d\n", (int)res->FSINFO3res_u.resok.rtmax);
57 printf("Write Max:%d\n", (int)res->FSINFO3res_u.resok.wtmax);
58 client->is_finished = 1;
59}
60
61
62void nfs_connect_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
63{
64 struct client *client = private_data;
65
66 if (status != RPC_STATUS_SUCCESS) {
67 printf("connection to RPC.MOUNTD on server %s failed\n", client->server);
68 exit(10);
69 }
70
71 printf("Connected to RPC.NFSDD on %s:%d\n", client->server, client->mount_port);
72 printf("Send FSINFO request\n");
73 if (rpc_nfs_fsinfo_async(rpc, nfs_fsinfo_cb, &client->rootfh, client) != 0) {
74 printf("Failed to send fsinfo request\n");
75 exit(10);
76 }
77}
78
84004dbf
RS
79void mount_mnt_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
80{
81 struct client *client = private_data;
f4b9cb0e 82 mountres3 *mnt = data;
84004dbf
RS
83
84 if (status == RPC_STATUS_ERROR) {
85 printf("mount/mnt call failed with \"%s\"\n", (char *)data);
86 exit(10);
87 }
88 if (status != RPC_STATUS_SUCCESS) {
89 printf("mount/mnt call to server %s failed, status:%d\n", client->server, status);
90 exit(10);
91 }
92
93 printf("Got reply from server for MOUNT/MNT procedure.\n");
f4b9cb0e
RS
94 client->rootfh.data.data_len = mnt->mountres3_u.mountinfo.fhandle.fhandle3_len;
95 client->rootfh.data.data_val = malloc(client->rootfh.data.data_len);
96 memcpy(client->rootfh.data.data_val, mnt->mountres3_u.mountinfo.fhandle.fhandle3_val, client->rootfh.data.data_len);
97
98 printf("Disconnect socket from mountd server\n");
99 if (rpc_disconnect(rpc, "normal disconnect") != 0) {
100 printf("Failed to disconnect socket to mountd\n");
101 exit(10);
102 }
103
104 printf("Connect to RPC.NFSDD on %s:%d\n", client->server, 2049);
105 if (rpc_connect_async(rpc, client->server, 2049, nfs_connect_cb, client) != 0) {
106 printf("Failed to start connection\n");
107 exit(10);
108 }
84004dbf
RS
109}
110
111
112void mount_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
113{
114 struct client *client = private_data;
115
116 if (status == RPC_STATUS_ERROR) {
117 printf("mount null call failed with \"%s\"\n", (char *)data);
118 exit(10);
119 }
120 if (status != RPC_STATUS_SUCCESS) {
121 printf("mount null call to server %s failed, status:%d\n", client->server, status);
122 exit(10);
123 }
124
125 printf("Got reply from server for MOUNT/NULL procedure.\n");
126 printf("Send MOUNT/MNT command for %s\n", client->export);
127 if (rpc_mount_mnt_async(rpc, mount_mnt_cb, client->export, client) != 0) {
128 printf("Failed to send mnt request\n");
129 exit(10);
130 }
84004dbf
RS
131}
132
133void mount_connect_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
134{
135 struct client *client = private_data;
136
137 if (status != RPC_STATUS_SUCCESS) {
138 printf("connection to RPC.MOUNTD on server %s failed\n", client->server);
139 exit(10);
140 }
141
142 printf("Connected to RPC.MOUNTD on %s:%d\n", client->server, client->mount_port);
143 printf("Send NULL request to check if RPC.MOUNTD is actually running\n");
144 if (rpc_mount_null_async(rpc, mount_null_cb, client) != 0) {
145 printf("Failed to send null request\n");
146 exit(10);
147 }
148}
149
150
151void pmap_getport_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
152{
153 struct client *client = private_data;
154 uint32_t port;
155
156 if (status == RPC_STATUS_ERROR) {
157 printf("portmapper getport call failed with \"%s\"\n", (char *)data);
158 exit(10);
159 }
160 if (status != RPC_STATUS_SUCCESS) {
161 printf("portmapper getport call to server %s failed, status:%d\n", client->server, status);
162 exit(10);
163 }
164
165 client->mount_port = *(uint32_t *)data;
166 printf("GETPORT returned Port:%d\n", client->mount_port);
167 if (client->mount_port == 0) {
168 printf("RPC.MOUNTD is not available on server : %s\n", client->server, client->mount_port);
169 exit(10);
170 }
171
172 printf("Disconnect socket from portmap server\n");
173 if (rpc_disconnect(rpc, "normal disconnect") != 0) {
174 printf("Failed to disconnect socket to portmapper\n");
175 exit(10);
176 }
177
178 printf("Connect to RPC.MOUNTD on %s:%d\n", client->server, client->mount_port);
179 if (rpc_connect_async(rpc, client->server, client->mount_port, mount_connect_cb, client) != 0) {
180 printf("Failed to start connection\n");
181 exit(10);
182 }
183}
184
185
186void pmap_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
187{
188 struct client *client = private_data;
189
190 if (status == RPC_STATUS_ERROR) {
191 printf("portmapper null call failed with \"%s\"\n", (char *)data);
192 exit(10);
193 }
194 if (status != RPC_STATUS_SUCCESS) {
195 printf("portmapper null call to server %s failed, status:%d\n", client->server, status);
196 exit(10);
197 }
198
199 printf("Got reply from server for PORTMAP/NULL procedure.\n");
200 printf("Send getport request asking for MOUNT port\n");
201 if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, pmap_getport_cb, client) != 0) {
202 printf("Failed to send getport request\n");
203 exit(10);
204 }
205}
206
207void pmap_connect_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
208{
209 struct client *client = private_data;
210
211 printf("pmap_connect_cb status:%d.\n", status);
212 if (status != RPC_STATUS_SUCCESS) {
213 printf("connection to portmapper on server %s failed\n", client->server);
214 exit(10);
215 }
216
217 printf("Send NULL request to check if portmapper is actually running\n");
218 if (rpc_pmap_null_async(rpc, pmap_null_cb, client) != 0) {
219 printf("Failed to send null request\n");
220 exit(10);
221 }
222}
223
224
225int main(int argc, char *argv[])
226{
227 struct rpc_context *rpc;
228 struct pollfd pfd;
229 int ret;
230 struct client client;
231
232 rpc = rpc_init_context();
233 if (rpc == NULL) {
234 printf("failed to init context\n");
235 exit(10);
236 }
237
238 client.server = SERVER;
239 client.export = EXPORT;
240 client.is_finished = 0;
241 if (rpc_connect_async(rpc, client.server, 111, pmap_connect_cb, &client) != 0) {
242 printf("Failed to start connection\n");
243 exit(10);
244 }
245
246 for (;;) {
247 pfd.fd = rpc_get_fd(rpc);
248 pfd.events = rpc_which_events(rpc);
249
250 if (poll(&pfd, 1, -1) < 0) {
251 printf("Poll failed");
252 exit(10);
253 }
254 if (rpc_service(rpc, pfd.revents) < 0) {
255 printf("rpc_service failed\n");
256 break;
257 }
258 if (client.is_finished) {
259 break;
260 }
261 }
262
263 rpc_destroy_context(rpc);
264 rpc=NULL;
265 printf("nfsclient finished\n");
266 return 0;
267}