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