Imported Upstream version 0.0~git20110716.8c27363
[deb_libnfs.git] / examples / nfsclient-raw.c
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"
23 #define EXPORT "/shared"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <poll.h>
29 #include "libnfs.h"
30 #include "libnfs-raw.h"
31 #include "libnfs-raw-mount.h"
32 #include "libnfs-raw-nfs.h"
33 #include "libnfs-raw-rquota.h"
34
35 struct client {
36 char *server;
37 char *export;
38 uint32_t mount_port;
39 uint32_t rquota_port;
40 int is_finished;
41 struct nfs_fh3 rootfh;
42 };
43
44 void rquota_getquota_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data)
45 {
46 struct client *client = private_data;
47 // GETQUOTA1res *res = data;
48
49 if (status == RPC_STATUS_ERROR) {
50 printf("rquota/getquota call failed with \"%s\"\n", (char *)data);
51 exit(10);
52 }
53 if (status != RPC_STATUS_SUCCESS) {
54 printf("rquota/getquota call to server %s failed, status:%d\n", client->server, status);
55 exit(10);
56 }
57
58 printf("rquota responded ok\n");
59 client->is_finished = 1;
60 }
61
62 void rquota_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data)
63 {
64 struct client *client = private_data;
65
66 if (status != RPC_STATUS_SUCCESS) {
67 printf("connection to RPC.RQUOTAD on server %s failed\n", client->server);
68 exit(10);
69 }
70
71 printf("Connected to RPC.RQUOTAD on %s:%d\n", client->server, client->rquota_port);
72 printf("Send GETQUOTA request for uid 100\n");
73 if (rpc_rquota1_getquota_async(rpc, rquota_getquota_cb, EXPORT, 100, client) != 0) {
74 printf("Failed to send fsinfo request\n");
75 exit(10);
76 }
77 }
78
79 void acl_getacl_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data)
80 {
81 struct client *client = private_data;
82 GETACL3res *res = data;
83
84 printf("Got NFSACL/GETACL reply\n");
85
86 if (status == RPC_STATUS_SUCCESS) {
87 printf("Got an ACL : ACL status:%d\n", res->status);
88 if (res->status == NFS3_OK) {
89 int i;
90 printf("ACL MASK 0x%08x\n", res->GETACL3res_u.resok.mask);
91 printf("NUM ACE %d\n", res->GETACL3res_u.resok.ace_count);
92 for (i=0; i<res->GETACL3res_u.resok.ace.ace_len; i++) {
93 printf("Type:0x%08x\n", res->GETACL3res_u.resok.ace.ace_val[i].type);
94 printf("ID:%d\n", res->GETACL3res_u.resok.ace.ace_val[i].id);
95 printf("Perm:0x%08x\n", res->GETACL3res_u.resok.ace.ace_val[i].perm);
96 }
97 }
98 }
99
100 printf("Disconnect socket from nfs server\n");
101 if (rpc_disconnect(rpc, "normal disconnect") != 0) {
102 printf("Failed to disconnect socket to nfs\n");
103 exit(10);
104 }
105
106 printf("Connect to RPC.RQUOTAD on %s:%d\n", client->server, client->rquota_port);
107 if (rpc_connect_async(rpc, client->server, client->rquota_port, rquota_connect_cb, client) != 0) {
108 printf("Failed to start connection\n");
109 exit(10);
110 }
111 }
112
113 void acl_null_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data)
114 {
115 struct client *client = private_data;
116
117 printf("Got NFSACL/NULL reply\n");
118 printf("Get ACL for root handle\n");
119
120 if (rpc_nfsacl_getacl_async(rpc, acl_getacl_cb, &client->rootfh, NFSACL_MASK_ACL_ENTRY|NFSACL_MASK_ACL_COUNT|NFSACL_MASK_ACL_DEFAULT_ENTRY|NFSACL_MASK_ACL_DEFAULT_COUNT, client) != 0) {
121 printf("Failed to send getacl request\n");
122 exit(10);
123 }
124
125 }
126
127 void nfs_fsinfo_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data)
128 {
129 struct client *client = private_data;
130 FSINFO3res *res = data;
131
132 if (status == RPC_STATUS_ERROR) {
133 printf("nfs/fsinfo call failed with \"%s\"\n", (char *)data);
134 exit(10);
135 }
136 if (status != RPC_STATUS_SUCCESS) {
137 printf("nfs/fsinfo call to server %s failed, status:%d\n", client->server, status);
138 exit(10);
139 }
140
141 printf("Got reply from server for NFS/FSINFO procedure.\n");
142 printf("Read Max:%d\n", (int)res->FSINFO3res_u.resok.rtmax);
143 printf("Write Max:%d\n", (int)res->FSINFO3res_u.resok.wtmax);
144
145 printf("Send NFSACL/NULL request\n");
146 if (rpc_nfsacl_null_async(rpc, acl_null_cb, client) != 0) {
147 printf("Failed to send acl/null request\n");
148 exit(10);
149 }
150 }
151
152
153 void nfs_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data)
154 {
155 struct client *client = private_data;
156
157 if (status != RPC_STATUS_SUCCESS) {
158 printf("connection to RPC.MOUNTD on server %s failed\n", client->server);
159 exit(10);
160 }
161
162 printf("Connected to RPC.NFSD on %s:%d\n", client->server, client->mount_port);
163 printf("Send FSINFO request\n");
164 if (rpc_nfs_fsinfo_async(rpc, nfs_fsinfo_cb, &client->rootfh, client) != 0) {
165 printf("Failed to send fsinfo request\n");
166 exit(10);
167 }
168 }
169
170 void mount_mnt_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
171 {
172 struct client *client = private_data;
173 mountres3 *mnt = data;
174
175 if (status == RPC_STATUS_ERROR) {
176 printf("mount/mnt call failed with \"%s\"\n", (char *)data);
177 exit(10);
178 }
179 if (status != RPC_STATUS_SUCCESS) {
180 printf("mount/mnt call to server %s failed, status:%d\n", client->server, status);
181 exit(10);
182 }
183
184 printf("Got reply from server for MOUNT/MNT procedure.\n");
185 client->rootfh.data.data_len = mnt->mountres3_u.mountinfo.fhandle.fhandle3_len;
186 client->rootfh.data.data_val = malloc(client->rootfh.data.data_len);
187 memcpy(client->rootfh.data.data_val, mnt->mountres3_u.mountinfo.fhandle.fhandle3_val, client->rootfh.data.data_len);
188
189 printf("Disconnect socket from mountd server\n");
190 if (rpc_disconnect(rpc, "normal disconnect") != 0) {
191 printf("Failed to disconnect socket to mountd\n");
192 exit(10);
193 }
194
195 printf("Connect to RPC.NFSD on %s:%d\n", client->server, 2049);
196 if (rpc_connect_async(rpc, client->server, 2049, nfs_connect_cb, client) != 0) {
197 printf("Failed to start connection\n");
198 exit(10);
199 }
200 }
201
202
203
204 void mount_export_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
205 {
206 struct client *client = private_data;
207 exports export = *(exports *)data;
208
209 if (status == RPC_STATUS_ERROR) {
210 printf("mount null call failed with \"%s\"\n", (char *)data);
211 exit(10);
212 }
213 if (status != RPC_STATUS_SUCCESS) {
214 printf("mount null call to server %s failed, status:%d\n", client->server, status);
215 exit(10);
216 }
217
218 printf("Got reply from server for MOUNT/EXPORT procedure.\n");
219 while (export != NULL) {
220 printf("Export: %s\n", export->ex_dir);
221 export = export->ex_next;
222 }
223 printf("Send MOUNT/MNT command for %s\n", client->export);
224 if (rpc_mount_mnt_async(rpc, mount_mnt_cb, client->export, client) != 0) {
225 printf("Failed to send mnt request\n");
226 exit(10);
227 }
228 }
229
230 void mount_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
231 {
232 struct client *client = private_data;
233
234 if (status == RPC_STATUS_ERROR) {
235 printf("mount null call failed with \"%s\"\n", (char *)data);
236 exit(10);
237 }
238 if (status != RPC_STATUS_SUCCESS) {
239 printf("mount null call to server %s failed, status:%d\n", client->server, status);
240 exit(10);
241 }
242
243 printf("Got reply from server for MOUNT/NULL procedure.\n");
244 printf("Send MOUNT/EXPORT command\n");
245 if (rpc_mount_export_async(rpc, mount_export_cb, client) != 0) {
246 printf("Failed to send export request\n");
247 exit(10);
248 }
249 }
250
251 void mount_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data)
252 {
253 struct client *client = private_data;
254
255 if (status != RPC_STATUS_SUCCESS) {
256 printf("connection to RPC.MOUNTD on server %s failed\n", client->server);
257 exit(10);
258 }
259
260 printf("Connected to RPC.MOUNTD on %s:%d\n", client->server, client->mount_port);
261 printf("Send NULL request to check if RPC.MOUNTD is actually running\n");
262 if (rpc_mount_null_async(rpc, mount_null_cb, client) != 0) {
263 printf("Failed to send null request\n");
264 exit(10);
265 }
266 }
267
268
269 void pmap_getport2_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
270 {
271 struct client *client = private_data;
272
273 if (status == RPC_STATUS_ERROR) {
274 printf("portmapper getport call failed with \"%s\"\n", (char *)data);
275 exit(10);
276 }
277 if (status != RPC_STATUS_SUCCESS) {
278 printf("portmapper getport call to server %s failed, status:%d\n", client->server, status);
279 exit(10);
280 }
281
282 client->mount_port = *(uint32_t *)data;
283 printf("GETPORT returned RPC.MOUNTD is on port:%d\n", client->mount_port);
284 if (client->mount_port == 0) {
285 printf("RPC.MOUNTD is not available on server : %s:%d\n", client->server, client->mount_port);
286 exit(10);
287 }
288
289 printf("Disconnect socket from portmap server\n");
290 if (rpc_disconnect(rpc, "normal disconnect") != 0) {
291 printf("Failed to disconnect socket to portmapper\n");
292 exit(10);
293 }
294
295 printf("Connect to RPC.MOUNTD on %s:%d\n", client->server, client->mount_port);
296 if (rpc_connect_async(rpc, client->server, client->mount_port, mount_connect_cb, client) != 0) {
297 printf("Failed to start connection\n");
298 exit(10);
299 }
300 }
301
302 void pmap_getport1_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
303 {
304 struct client *client = private_data;
305
306 if (status == RPC_STATUS_ERROR) {
307 printf("portmapper getport call failed with \"%s\"\n", (char *)data);
308 exit(10);
309 }
310 if (status != RPC_STATUS_SUCCESS) {
311 printf("portmapper getport call to server %s failed, status:%d\n", client->server, status);
312 exit(10);
313 }
314
315 client->rquota_port = *(uint32_t *)data;
316 printf("GETPORT returned RPC.RQUOTAD on port:%d\n", client->rquota_port);
317 if (client->rquota_port == 0) {
318 printf("RPC.RQUOTAD is not available on server : %s:%d\n", client->server, client->rquota_port);
319 // exit(10);
320 }
321
322 printf("Send getport request asking for MOUNT port\n");
323 if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, pmap_getport2_cb, client) != 0) {
324 printf("Failed to send getport request\n");
325 exit(10);
326 }
327 }
328
329 void pmap_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data)
330 {
331 struct client *client = private_data;
332
333 if (status == RPC_STATUS_ERROR) {
334 printf("portmapper null call failed with \"%s\"\n", (char *)data);
335 exit(10);
336 }
337 if (status != RPC_STATUS_SUCCESS) {
338 printf("portmapper null call to server %s failed, status:%d\n", client->server, status);
339 exit(10);
340 }
341
342 printf("Got reply from server for PORTMAP/NULL procedure.\n");
343 printf("Send getport request asking for MOUNT port\n");
344 if (rpc_pmap_getport_async(rpc, RQUOTA_PROGRAM, RQUOTA_V1, pmap_getport1_cb, client) != 0) {
345 printf("Failed to send getport request\n");
346 exit(10);
347 }
348 }
349
350 void pmap_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data)
351 {
352 struct client *client = private_data;
353
354 printf("pmap_connect_cb status:%d.\n", status);
355 if (status != RPC_STATUS_SUCCESS) {
356 printf("connection to portmapper on server %s failed\n", client->server);
357 exit(10);
358 }
359
360 printf("Send NULL request to check if portmapper is actually running\n");
361 if (rpc_pmap_null_async(rpc, pmap_null_cb, client) != 0) {
362 printf("Failed to send null request\n");
363 exit(10);
364 }
365 }
366
367
368 int main(int argc _U_, char *argv[] _U_)
369 {
370 struct rpc_context *rpc;
371 struct pollfd pfd;
372 struct client client;
373
374 rpc = rpc_init_context();
375 if (rpc == NULL) {
376 printf("failed to init context\n");
377 exit(10);
378 }
379
380 client.server = SERVER;
381 client.export = EXPORT;
382 client.is_finished = 0;
383 if (rpc_connect_async(rpc, client.server, 111, pmap_connect_cb, &client) != 0) {
384 printf("Failed to start connection\n");
385 exit(10);
386 }
387
388 for (;;) {
389 pfd.fd = rpc_get_fd(rpc);
390 pfd.events = rpc_which_events(rpc);
391
392 if (poll(&pfd, 1, -1) < 0) {
393 printf("Poll failed");
394 exit(10);
395 }
396 if (rpc_service(rpc, pfd.revents) < 0) {
397 printf("rpc_service failed\n");
398 break;
399 }
400 if (client.is_finished) {
401 break;
402 }
403 }
404
405 rpc_destroy_context(rpc);
406 rpc=NULL;
407 printf("nfsclient finished\n");
408 return 0;
409 }