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