Line | Count | Source |
1 | | /* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ |
2 | | /* |
3 | | Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com> |
4 | | |
5 | | This program is free software; you can redistribute it and/or modify |
6 | | it under the terms of the GNU Lesser General Public License as published by |
7 | | the Free Software Foundation; either version 2.1 of the License, or |
8 | | (at your option) any later version. |
9 | | |
10 | | This program is distributed in the hope that it will be useful, |
11 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | GNU Lesser General Public License for more details. |
14 | | |
15 | | You should have received a copy of the GNU Lesser General Public License |
16 | | along with this program; if not, see <http://www.gnu.org/licenses/>. |
17 | | */ |
18 | | #ifdef HAVE_CONFIG_H |
19 | | #include "config.h" |
20 | | #endif |
21 | | |
22 | | #ifdef __linux__ |
23 | | #define _GNU_SOURCE |
24 | | #endif |
25 | | |
26 | | #ifdef AROS |
27 | | #include "aros_compat.h" |
28 | | #endif |
29 | | |
30 | | #ifdef PS2_EE |
31 | | #include "ps2_compat.h" |
32 | | #endif |
33 | | |
34 | | #ifdef PS3_PPU |
35 | | #include "ps3_compat.h" |
36 | | #endif |
37 | | |
38 | | #ifdef WIN32 |
39 | | #include <win32/win32_compat.h> |
40 | | #endif |
41 | | |
42 | | #ifdef HAVE_ARPA_INET_H |
43 | | #include <arpa/inet.h> |
44 | | #endif |
45 | | |
46 | | #ifdef HAVE_POLL_H |
47 | | #include <poll.h> |
48 | | #endif |
49 | | |
50 | | #if defined(HAVE_SYS_UIO_H) || (defined(__APPLE__) && defined(__MACH__)) |
51 | | #include <sys/uio.h> |
52 | | #endif |
53 | | |
54 | | #ifdef HAVE_UNISTD_H |
55 | | #include <unistd.h> |
56 | | #endif |
57 | | |
58 | | #ifdef HAVE_SYS_IOCTL_H |
59 | | #include <sys/ioctl.h> |
60 | | #endif |
61 | | |
62 | | #ifdef HAVE_SYS_SOCKET_H |
63 | | #include <sys/socket.h> |
64 | | #endif |
65 | | |
66 | | #ifdef HAVE_NETINET_IN_H |
67 | | #include <netinet/in.h> |
68 | | #endif |
69 | | |
70 | | #ifdef HAVE_NETINET_TCP_H |
71 | | #include <netinet/tcp.h> |
72 | | #endif |
73 | | |
74 | | #ifdef HAVE_NETDB_H |
75 | | #include <netdb.h> |
76 | | #endif |
77 | | |
78 | | #ifdef HAVE_SYS_FILIO_H |
79 | | #include <sys/filio.h> |
80 | | #endif |
81 | | |
82 | | #ifdef HAVE_SYS_SOCKIO_H |
83 | | #include <sys/sockio.h> |
84 | | #endif |
85 | | |
86 | | #include <stdio.h> |
87 | | #include <stdlib.h> |
88 | | #include <assert.h> |
89 | | #include <fcntl.h> |
90 | | #include <string.h> |
91 | | #include <errno.h> |
92 | | #include <time.h> |
93 | | #include <limits.h> |
94 | | #include <sys/types.h> |
95 | | #include "libnfs-zdr.h" |
96 | | #include "libnfs.h" |
97 | | #include "libnfs-raw.h" |
98 | | #include "libnfs-private.h" |
99 | | #include "slist.h" |
100 | | |
101 | | #ifdef WIN32 |
102 | | //has to be included after stdlib!! |
103 | | #include "win32_errnowrapper.h" |
104 | | #endif |
105 | | |
106 | | #ifndef MSG_NOSIGNAL |
107 | | #if (defined(__APPLE__) && defined(__MACH__)) || defined(PS2_EE) |
108 | | #define MSG_NOSIGNAL 0 |
109 | | #endif |
110 | | #endif |
111 | | |
112 | | static int |
113 | | rpc_reconnect_requeue(struct rpc_context *rpc); |
114 | | |
115 | | static int |
116 | | rpc_set_sockaddr(struct rpc_context *rpc, const char *server, int port); |
117 | | |
118 | | #ifdef HAVE_NFS4_2 |
119 | | static void |
120 | | rpc_nfs4_rebind_session(struct rpc_context *rpc); |
121 | | #endif /* HAVE_NFS4_2 */ |
122 | | |
123 | | /* |
124 | | * How hard rpc_set_sockaddr() tries when the resolver reports a transient |
125 | | * failure. This runs on the caller's event loop thread, so keep it short. |
126 | | */ |
127 | 0 | #define RESOLVE_RETRIES 3 |
128 | 0 | #define RESOLVE_RETRY_NSECS (100 * 1000 * 1000) |
129 | | |
130 | | static int |
131 | | create_socket(int domain, int type, int protocol) |
132 | 0 | { |
133 | 0 | #ifdef SOCK_CLOEXEC |
134 | 0 | #ifdef __linux__ |
135 | | /* Linux-specific extension (since 2.6.27): set the |
136 | | close-on-exec flag on all sockets to avoid leaking file |
137 | | descriptors to child processes */ |
138 | 0 | int fd = socket(domain, type|SOCK_CLOEXEC, protocol); |
139 | 0 | if (fd >= 0 || errno != EINVAL) { |
140 | 0 | if (type == SOCK_DGRAM) { |
141 | 0 | int opt; |
142 | 0 | if (domain == AF_INET) { |
143 | 0 | opt = 1; |
144 | 0 | setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)); |
145 | 0 | } else { |
146 | 0 | opt = 1; |
147 | 0 | setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)); |
148 | 0 | } |
149 | 0 | } |
150 | 0 | return fd; |
151 | 0 | } |
152 | 0 | #endif |
153 | 0 | #endif |
154 | | |
155 | 0 | return socket(domain, type, protocol); |
156 | 0 | } |
157 | | |
158 | | static int |
159 | | set_nonblocking(int fd) |
160 | 0 | { |
161 | 0 | int v = 0; |
162 | | #if defined(WIN32) |
163 | | u_long nonblocking=1; |
164 | | v = ioctl(fd, FIONBIO, &nonblocking); |
165 | | #else |
166 | 0 | v = fcntl(fd, F_GETFL, 0); |
167 | 0 | v = fcntl(fd, F_SETFL, v | O_NONBLOCK); |
168 | 0 | #endif |
169 | 0 | return v; |
170 | 0 | } |
171 | | |
172 | | static void |
173 | | set_nolinger(int fd) |
174 | 0 | { |
175 | 0 | #if !defined(PS2_EE) |
176 | 0 | struct linger lng; |
177 | 0 | lng.l_onoff = 1; |
178 | 0 | lng.l_linger = 0; |
179 | 0 | setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&lng, sizeof(lng)); |
180 | 0 | #endif |
181 | 0 | } |
182 | | |
183 | | static int |
184 | | set_bind_device(int fd, char *ifname) |
185 | 0 | { |
186 | 0 | int rc = 0; |
187 | |
|
188 | 0 | #ifdef HAVE_SO_BINDTODEVICE |
189 | 0 | if (*ifname) { |
190 | 0 | rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, |
191 | 0 | strlen(ifname)); |
192 | 0 | } |
193 | |
|
194 | 0 | #endif |
195 | 0 | return rc; |
196 | 0 | } |
197 | | |
198 | | #ifdef HAVE_NETINET_TCP_H |
199 | | static int |
200 | | set_tcp_sockopt(int sockfd, int optname, int value) |
201 | 0 | { |
202 | 0 | int level; |
203 | |
|
204 | | #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun) || (defined(__APPLE__) && defined(__MACH__)) |
205 | | struct protoent *buf; |
206 | | |
207 | | if ((buf = getprotobyname("tcp")) != NULL) |
208 | | level = buf->p_proto; |
209 | | else |
210 | | return -1; |
211 | | #else |
212 | 0 | level = SOL_TCP; |
213 | 0 | #endif |
214 | |
|
215 | 0 | return setsockopt(sockfd, level, optname, (char *)&value, |
216 | 0 | sizeof(value)); |
217 | 0 | } |
218 | | |
219 | | static int |
220 | | set_keepalive(struct rpc_context *rpc, int sockfd) |
221 | 0 | { |
222 | 0 | #ifdef SO_KEEPALIVE |
223 | 0 | const int enable_keepalive = 1; |
224 | |
|
225 | 0 | if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, |
226 | 0 | &enable_keepalive, sizeof(enable_keepalive)) != 0) { |
227 | 0 | RPC_LOG(rpc, 2, "setsockopt(SO_KEEPALIVE) failed: %s", strerror(errno)); |
228 | 0 | return -1; |
229 | 0 | } |
230 | 0 | #endif |
231 | | |
232 | | /* |
233 | | * Following code uses Linux specific socket options to change keepalive |
234 | | * settings for the socket. |
235 | | * |
236 | | * TODO: Add for non-Linux clients. |
237 | | */ |
238 | | |
239 | 0 | #if defined(TCP_KEEPIDLE) |
240 | 0 | { |
241 | | /* First keepalive probe after 60 secs of inactivity */ |
242 | 0 | const int keepidle_secs = 60; |
243 | |
|
244 | 0 | if (set_tcp_sockopt(sockfd, TCP_KEEPIDLE, keepidle_secs) != 0) { |
245 | 0 | RPC_LOG(rpc, 2, "setsockopt(TCP_KEEPIDLE) failed: %s", strerror(errno)); |
246 | 0 | return -1; |
247 | 0 | } |
248 | 0 | } |
249 | 0 | #endif |
250 | | |
251 | 0 | #if defined(TCP_KEEPINTVL) |
252 | 0 | { |
253 | | /* Send keepalive probe every 60 secs */ |
254 | 0 | const int keepinterval_secs = 60; |
255 | |
|
256 | 0 | if (set_tcp_sockopt(sockfd, TCP_KEEPINTVL, keepinterval_secs) != 0) { |
257 | 0 | RPC_LOG(rpc, 2, "setsockopt(TCP_KEEPINTVL) failed: %s", strerror(errno)); |
258 | 0 | return -1; |
259 | 0 | } |
260 | 0 | } |
261 | 0 | #endif |
262 | | |
263 | 0 | #if defined(TCP_KEEPCNT) |
264 | 0 | { |
265 | | /* Terminate connection after 3 failed keepalives */ |
266 | 0 | const int keepcnt = 3; |
267 | |
|
268 | 0 | if (set_tcp_sockopt(sockfd, TCP_KEEPCNT, keepcnt) != 0) { |
269 | 0 | RPC_LOG(rpc, 2, "setsockopt(TCP_KEEPCNT) failed: %s", strerror(errno)); |
270 | 0 | return -1; |
271 | 0 | } |
272 | 0 | } |
273 | 0 | #endif |
274 | | |
275 | 0 | return 0; |
276 | 0 | } |
277 | | #endif /* HAVE_NETINET_TCP_H */ |
278 | | |
279 | | int |
280 | | rpc_get_fd(struct rpc_context *rpc) |
281 | 0 | { |
282 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
283 | |
|
284 | 0 | if (rpc->old_fd) { |
285 | 0 | return rpc->old_fd; |
286 | 0 | } |
287 | | |
288 | 0 | return rpc->fd; |
289 | 0 | } |
290 | | |
291 | | int |
292 | | rpc_get_evfd(struct rpc_context *rpc) |
293 | 0 | { |
294 | 0 | return rpc->evfd; |
295 | 0 | } |
296 | | |
297 | | void |
298 | | rpc_wakeup_service_thread(struct rpc_context *rpc) |
299 | 0 | { |
300 | | #ifdef LIBNFS_EVENTFD_WAKEUP |
301 | | uint64_t val = 1; |
302 | | ssize_t cnt; |
303 | | |
304 | | if (rpc->evfd == -1) { |
305 | | return; |
306 | | } |
307 | | |
308 | | cnt = write(rpc->evfd, &val, sizeof(val)); |
309 | | if (cnt != (ssize_t)sizeof(val)) { |
310 | | /* |
311 | | * Losing a wakeup only costs us up to rpc->poll_timeout of |
312 | | * latency, so log it and carry on rather than failing the |
313 | | * caller, who is usually mid-enqueue and holding rpc_mutex. |
314 | | */ |
315 | | RPC_LOG(rpc, 2, "Failed to signal service thread on evfd %d: %s", |
316 | | rpc->evfd, strerror(errno)); |
317 | | } |
318 | | #else |
319 | | /* |
320 | | * No wakeup fd on this build, so nothing to poke and no reference to |
321 | | * write(), which MSVC does not declare. |
322 | | */ |
323 | 0 | (void)rpc; |
324 | 0 | #endif |
325 | 0 | } |
326 | | |
327 | | /* |
328 | | * Does rpc->outqueue have one or more PDUs waiting to be sent out? |
329 | | * Takes rpc_mutex, so it must not be called with the mutex already held. |
330 | | */ |
331 | | static bool_t |
332 | | rpc_outqueue_present(struct rpc_context *rpc) |
333 | 0 | { |
334 | 0 | bool_t present; |
335 | |
|
336 | | #ifdef HAVE_MULTITHREADING |
337 | | if (rpc->multithreading_enabled) { |
338 | | nfs_mt_mutex_lock(&rpc->rpc_mutex); |
339 | | } |
340 | | #endif /* HAVE_MULTITHREADING */ |
341 | |
|
342 | 0 | present = (rpc->outqueue.head != NULL); |
343 | 0 | assert(present == (rpc->stats.outqueue_len != 0)); |
344 | |
|
345 | | #ifdef HAVE_MULTITHREADING |
346 | | if (rpc->multithreading_enabled) { |
347 | | nfs_mt_mutex_unlock(&rpc->rpc_mutex); |
348 | | } |
349 | | #endif /* HAVE_MULTITHREADING */ |
350 | |
|
351 | 0 | return present; |
352 | 0 | } |
353 | | |
354 | | #ifdef HAVE_NFS4_2 |
355 | | /* |
356 | | * Is the pdu at the head of the send queue one that cannot go out yet because |
357 | | * the session has no free slot? The queue is walked by the service thread, so |
358 | | * the head has to be read under the same lock rpc_outqueue_present() uses |
359 | | * rather than dereferenced on its own. |
360 | | */ |
361 | | static bool_t |
362 | | rpc_outqueue_head_waits_for_slot(struct rpc_context *rpc) |
363 | 0 | { |
364 | 0 | bool_t waiting; |
365 | |
|
366 | | #ifdef HAVE_MULTITHREADING |
367 | | if (rpc->multithreading_enabled) { |
368 | | nfs_mt_mutex_lock(&rpc->rpc_mutex); |
369 | | } |
370 | | #endif /* HAVE_MULTITHREADING */ |
371 | 0 | waiting = rpc->outqueue.head != NULL && |
372 | 0 | rpc->outqueue.head->nfs4_needs_slot && |
373 | 0 | !rpc->outqueue.head->nfs4_slot_held; |
374 | | #ifdef HAVE_MULTITHREADING |
375 | | if (rpc->multithreading_enabled) { |
376 | | nfs_mt_mutex_unlock(&rpc->rpc_mutex); |
377 | | } |
378 | | #endif /* HAVE_MULTITHREADING */ |
379 | | |
380 | | /* |
381 | | * The slot table has its own lock, taken after rpc_mutex is dropped |
382 | | * so that the two are never held at once. |
383 | | */ |
384 | 0 | return waiting && !nfs4_session_has_free_slot(rpc); |
385 | 0 | } |
386 | | #endif /* HAVE_NFS4_2 */ |
387 | | |
388 | | int |
389 | | rpc_which_events(struct rpc_context *rpc) |
390 | 0 | { |
391 | 0 | int events; |
392 | |
|
393 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
394 | |
|
395 | 0 | events = rpc->is_connected ? POLLIN : POLLOUT; |
396 | |
|
397 | 0 | if (rpc->is_udp != 0) { |
398 | | /* for udp sockets we only wait for pollin */ |
399 | 0 | return POLLIN; |
400 | 0 | } |
401 | | |
402 | 0 | if (rpc_outqueue_present(rpc)) { |
403 | 0 | events |= POLLOUT; |
404 | 0 | } |
405 | |
|
406 | 0 | #ifdef HAVE_NFS4_2 |
407 | | /* |
408 | | * An NFSv4.2 COMPOUND cannot go out until a session slot frees up, and |
409 | | * a slot only frees when a reply arrives. Asking for POLLOUT while the |
410 | | * slot table is full would just spin, since the socket is writable and |
411 | | * we would decline to write, so wait on POLLIN alone until then. |
412 | | * |
413 | | * This looks at the head of the queue only, and only at whether that |
414 | | * one pdu carries a SEQUENCE. An NFSv4.0 or NFSv3 pdu never does, so |
415 | | * nothing here can throttle them. |
416 | | */ |
417 | 0 | if ((events & POLLOUT) && rpc_outqueue_head_waits_for_slot(rpc)) { |
418 | 0 | events &= ~POLLOUT; |
419 | 0 | } |
420 | 0 | #endif /* HAVE_NFS4_2 */ |
421 | |
|
422 | 0 | return events; |
423 | 0 | } |
424 | | |
425 | | void |
426 | | rpc_disable_socket(struct rpc_context *rpc, int val) |
427 | 0 | { |
428 | 0 | rpc->socket_disabled = val; |
429 | 0 | } |
430 | | |
431 | | int |
432 | | rpc_write_to_socket(struct rpc_context *rpc) |
433 | 0 | { |
434 | 0 | struct rpc_pdu *pdu; |
435 | 0 | struct iovec fast_iov[RPC_FAST_VECTORS]; |
436 | 0 | struct iovec *iov = fast_iov; |
437 | 0 | int iovcnt = RPC_FAST_VECTORS; |
438 | 0 | int ret = 0; |
439 | |
|
440 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
441 | 0 | if (rpc->socket_disabled) { |
442 | 0 | return 0; |
443 | 0 | } |
444 | 0 | if (rpc->fd == -1) { |
445 | 0 | rpc_set_error(rpc, "trying to write but not connected"); |
446 | 0 | return -1; |
447 | 0 | } |
448 | | |
449 | | #ifdef HAVE_MULTITHREADING |
450 | | if (rpc->multithreading_enabled) { |
451 | | nfs_mt_mutex_lock(&rpc->rpc_mutex); |
452 | | } |
453 | | #endif /* HAVE_MULTITHREADING */ |
454 | | |
455 | | /* Write several pdus at once */ |
456 | 0 | while ((rpc->max_waitpdu_len == 0 || |
457 | 0 | rpc->max_waitpdu_len > rpc->waitpdu_len) && |
458 | 0 | (pdu = rpc->outqueue.head) != NULL) { |
459 | 0 | int niov = 0; |
460 | 0 | uint32_t num_pdus = 0; |
461 | 0 | char *last_buf = NULL; |
462 | 0 | ssize_t count; |
463 | |
|
464 | 0 | assert(pdu->out.niov <= pdu->out.iov_capacity); |
465 | 0 | assert(pdu->out.iov_capacity <= RPC_MAX_VECTORS); |
466 | |
|
467 | 0 | if (pdu->out.niov > iovcnt && iovcnt != RPC_MAX_VECTORS) { |
468 | 0 | assert(iov == fast_iov); |
469 | 0 | iov = (struct iovec *) calloc(RPC_MAX_VECTORS, |
470 | 0 | sizeof(struct iovec)); |
471 | | /* |
472 | | * If allocation fails, continue with smaller iov. |
473 | | * It'll require more writev() calls to send out one |
474 | | * pdu, but it'll work. |
475 | | */ |
476 | 0 | if (iov != NULL) { |
477 | 0 | iovcnt = RPC_MAX_VECTORS; |
478 | 0 | } else { |
479 | 0 | iov = fast_iov; |
480 | 0 | iovcnt = RPC_FAST_VECTORS; |
481 | 0 | } |
482 | 0 | } |
483 | |
|
484 | 0 | do { |
485 | 0 | size_t num_done = pdu->out.num_done; |
486 | 0 | int pdu_niov = pdu->out.niov; |
487 | 0 | int i; |
488 | | |
489 | | /* Fully sent PDU should not be sitting in outqueue */ |
490 | 0 | assert(num_done < pdu->out.total_size); |
491 | |
|
492 | 0 | #ifdef HAVE_NFS4_2 |
493 | | /* |
494 | | * An NFSv4.2 COMPOUND claims its session slot here, |
495 | | * as it is about to be written, rather than when it |
496 | | * was built. That is what lets an application queue |
497 | | * up as many requests as it likes while only as many |
498 | | * as the session has slots are in flight. When no |
499 | | * slot is free we stop building this batch and leave |
500 | | * the rest queued; a reply will free one and |
501 | | * rpc_which_events() asks for POLLOUT again. |
502 | | * |
503 | | * Only a pdu carrying a SEQUENCE gets here, so an |
504 | | * NFSv4.0 or NFSv3 pdu is never held back. |
505 | | */ |
506 | 0 | if (pdu->nfs4_needs_slot && !pdu->nfs4_slot_held && |
507 | 0 | nfs4_pdu_take_slot(rpc, pdu) < 0) { |
508 | 0 | break; |
509 | 0 | } |
510 | 0 | #endif /* HAVE_NFS4_2 */ |
511 | | |
512 | 0 | for (i = 0; i < pdu_niov; i++) { |
513 | 0 | char *buf = pdu->out.iov[i].buf; |
514 | 0 | size_t len = pdu->out.iov[i].len; |
515 | 0 | if (num_done >= len) { |
516 | 0 | num_done -= len; |
517 | 0 | continue; |
518 | 0 | } |
519 | 0 | buf += num_done; |
520 | 0 | len -= num_done; |
521 | 0 | num_done = 0; |
522 | | |
523 | | /* Concatenate continous blocks */ |
524 | 0 | if (last_buf != buf) { |
525 | 0 | iov[niov].iov_base = buf; |
526 | 0 | iov[niov].iov_len = len; |
527 | 0 | niov++; |
528 | 0 | if (niov >= iovcnt) |
529 | 0 | break; |
530 | 0 | last_buf = (buf + len); |
531 | 0 | } else { |
532 | 0 | iov[niov - 1].iov_len += len; |
533 | 0 | last_buf += len; |
534 | 0 | } |
535 | 0 | } |
536 | |
|
537 | 0 | num_pdus++; |
538 | 0 | pdu = pdu->next; |
539 | 0 | } while ((rpc->max_waitpdu_len == 0 || |
540 | 0 | rpc->max_waitpdu_len > (rpc->waitpdu_len + num_pdus)) && |
541 | 0 | pdu != NULL && niov < iovcnt); |
542 | |
|
543 | 0 | #ifdef HAVE_NFS4_2 |
544 | | /* |
545 | | * The head of the queue is waiting for a session slot, so |
546 | | * there is nothing to write yet. rpc_which_events() will stop |
547 | | * asking for POLLOUT until a reply frees one. |
548 | | */ |
549 | 0 | if (niov == 0) { |
550 | 0 | ret = 0; |
551 | 0 | goto finished; |
552 | 0 | } |
553 | 0 | #endif /* HAVE_NFS4_2 */ |
554 | | |
555 | | /* |
556 | | * We must never be doing 0-byte writes as those can get into |
557 | | * infinite loop. |
558 | | */ |
559 | 0 | assert(niov > 0); |
560 | |
|
561 | 0 | count = writev(rpc->fd, iov, niov); |
562 | 0 | if (count == -1) { |
563 | 0 | if (errno == EAGAIN || errno == EWOULDBLOCK) { |
564 | | /* |
565 | | * The socket send buffer is full. Close out |
566 | | * the current run of bytes written, we will |
567 | | * not write again until poll() reports |
568 | | * POLLOUT. |
569 | | * |
570 | | * Only a run that actually wrote something is |
571 | | * a sample. Once the buffer is full every |
572 | | * further attempt returns EAGAIN having |
573 | | * written nothing, and counting those empty |
574 | | * runs would drag the average to zero. |
575 | | */ |
576 | 0 | if (rpc->stats.last_write_bytes_before_eagain) { |
577 | 0 | rpc->stats.tot_write_bytes_before_eagain += |
578 | 0 | rpc->stats.last_write_bytes_before_eagain; |
579 | 0 | rpc->stats.last_write_bytes_before_eagain = 0; |
580 | 0 | INC_STATS(rpc, num_write_eagain); |
581 | 0 | } |
582 | |
|
583 | 0 | ret = 0; |
584 | 0 | goto finished; |
585 | 0 | } |
586 | 0 | rpc_set_error_locked(rpc, "Error when writing to " |
587 | 0 | "socket :%d %s", errno, |
588 | 0 | rpc_get_error(rpc)); |
589 | 0 | ret = -1; |
590 | 0 | goto finished; |
591 | 0 | } |
592 | | |
593 | 0 | rpc->stats.last_write_bytes_before_eagain += count; |
594 | | |
595 | | /* Check how many pdu we completed */ |
596 | 0 | while (count > 0 && (pdu = rpc->outqueue.head) != NULL) { |
597 | 0 | size_t remaining = (pdu->out.total_size - pdu->out.num_done); |
598 | 0 | if (remaining <= count) { |
599 | 0 | unsigned int hash; |
600 | |
|
601 | 0 | count -= remaining; |
602 | |
|
603 | 0 | pdu->out.num_done = pdu->out.total_size; |
604 | 0 | #ifdef HAVE_NFS4_2 |
605 | 0 | pdu->nfs4_slot_sent = 1; |
606 | 0 | #endif /* HAVE_NFS4_2 */ |
607 | |
|
608 | 0 | rpc->outqueue.head = pdu->next; |
609 | 0 | if (rpc->outqueue.head == NULL) |
610 | 0 | rpc->outqueue.tail = NULL; |
611 | | |
612 | | /* |
613 | | * We just dequeued the last high priority pdu, |
614 | | * the high priority run is now empty. |
615 | | */ |
616 | 0 | if (rpc->outqueue.tailp == pdu) |
617 | 0 | rpc->outqueue.tailp = NULL; |
618 | |
|
619 | 0 | assert(rpc->stats.outqueue_len > 0); |
620 | 0 | rpc->stats.outqueue_len--; |
621 | | |
622 | | /* RPC sent, original or retransmit */ |
623 | 0 | INC_STATS(rpc, num_req_sent); |
624 | |
|
625 | 0 | #ifdef HAVE_CLOCK_GETTIME |
626 | | /* |
627 | | * Now this RPC is completely written over the socket. |
628 | | * Note current wallclock time as the dispatch time. |
629 | | */ |
630 | 0 | pdu->dispatch_usecs = rpc_wallclock_time(); |
631 | 0 | #endif |
632 | |
|
633 | 0 | if (pdu->discard_after_sending) { |
634 | 0 | rpc_free_pdu(rpc, pdu); |
635 | 0 | ret = 0; |
636 | 0 | goto finished; |
637 | 0 | } |
638 | | |
639 | 0 | hash = rpc_hash_xid(rpc, pdu->xid); |
640 | 0 | rpc_enqueue(&rpc->waitpdu[hash], pdu); |
641 | 0 | rpc->waitpdu_len++; |
642 | |
|
643 | 0 | pdu->pdu_stats.send_timestamp = rpc_current_time_us(); |
644 | 0 | if (rpc->stats_cb) { |
645 | 0 | rpc->stats_cb(rpc, &pdu->pdu_stats, rpc->stats_private_data); |
646 | 0 | } |
647 | 0 | } else { |
648 | 0 | pdu->out.num_done += count; |
649 | 0 | #ifdef HAVE_NFS4_2 |
650 | 0 | pdu->nfs4_slot_sent = 1; |
651 | 0 | #endif /* HAVE_NFS4_2 */ |
652 | 0 | break; |
653 | 0 | } |
654 | 0 | } |
655 | 0 | } |
656 | | |
657 | 0 | finished: |
658 | | #ifdef HAVE_MULTITHREADING |
659 | | if (rpc->multithreading_enabled) { |
660 | | nfs_mt_mutex_unlock(&rpc->rpc_mutex); |
661 | | } |
662 | | #endif /* HAVE_MULTITHREADING */ |
663 | | |
664 | | /* Free iov if dynamically allocated */ |
665 | 0 | if (iov != fast_iov) { |
666 | 0 | assert(iovcnt > RPC_FAST_VECTORS); |
667 | 0 | free(iov); |
668 | 0 | } |
669 | |
|
670 | 0 | return ret; |
671 | 0 | } |
672 | | |
673 | | static int adjust_inbuf(struct rpc_context *rpc, uint32_t pdu_size) |
674 | 0 | { |
675 | 0 | char *buf; |
676 | |
|
677 | 0 | if (rpc->inbuf_size < pdu_size) { |
678 | | /* |
679 | | * Bound on what a server can make us allocate. This tracks |
680 | | * the inbound record limit rather than NFS_MAX_XFER_SIZE, |
681 | | * which covers outbound WRITE payloads too and is far larger. |
682 | | */ |
683 | 0 | if (pdu_size > MAX_FRAGMENT_SIZE + 4096) { |
684 | 0 | rpc_set_error(rpc, "Incoming PDU exceeds limit of %d " |
685 | 0 | "bytes.", MAX_FRAGMENT_SIZE + 4096); |
686 | 0 | return -1; |
687 | 0 | } |
688 | 0 | buf = realloc(rpc->inbuf, pdu_size); |
689 | 0 | if (buf == NULL) { |
690 | 0 | rpc_set_error(rpc, "Failed to allocate buffer of %d " |
691 | 0 | "bytes for pdu, errno:%d. Closing " |
692 | 0 | "socket.", (int)pdu_size, errno); |
693 | 0 | return -1; |
694 | 0 | } |
695 | 0 | rpc->inbuf_size = pdu_size; |
696 | 0 | rpc->inbuf = buf; |
697 | 0 | } |
698 | 0 | return 0; |
699 | 0 | } |
700 | | |
701 | | static char *rpc_reassemble_pdu(struct rpc_context *rpc, uint32_t *pdu_size) |
702 | 0 | { |
703 | 0 | struct rpc_fragment *fragment; |
704 | 0 | char *reasbuf = NULL, *ptr; |
705 | 0 | uint32_t size; |
706 | |
|
707 | 0 | size = rpc->inpos; |
708 | 0 | for (fragment = rpc->fragments; fragment; fragment = fragment->next) { |
709 | 0 | size += fragment->size; |
710 | 0 | if (size < fragment->size) { |
711 | 0 | rpc_set_error(rpc, "Fragments too large"); |
712 | 0 | rpc_free_all_fragments(rpc); |
713 | 0 | return NULL; |
714 | 0 | } |
715 | 0 | } |
716 | | |
717 | 0 | reasbuf = malloc(size); |
718 | 0 | if (reasbuf == NULL) { |
719 | 0 | rpc_set_error(rpc, "Failed to reassemble PDU"); |
720 | 0 | rpc_free_all_fragments(rpc); |
721 | 0 | return NULL; |
722 | 0 | } |
723 | 0 | ptr = reasbuf; |
724 | 0 | for (fragment = rpc->fragments; fragment; fragment = fragment->next) { |
725 | 0 | memcpy(ptr, fragment->data, fragment->size); |
726 | 0 | ptr += fragment->size; |
727 | 0 | } |
728 | 0 | memcpy(ptr, rpc->inbuf, rpc->inpos); |
729 | |
|
730 | 0 | *pdu_size = size; |
731 | 0 | return reasbuf; |
732 | 0 | } |
733 | | |
734 | | static void rpc_finished_pdu(struct rpc_context *rpc) |
735 | 0 | { |
736 | 0 | if (rpc->pdu && rpc->pdu->free_pdu) { |
737 | | /* |
738 | | * For zero-copy read, this is where we call the user callback. |
739 | | */ |
740 | 0 | rpc->pdu->cb(rpc, RPC_STATUS_SUCCESS, rpc->pdu->zdr_decode_buf, rpc->pdu->private_data); |
741 | 0 | } |
742 | 0 | if (rpc->pdu && rpc->pdu->free_zdr) { |
743 | 0 | zdr_destroy(&rpc->pdu->zdr); |
744 | 0 | } |
745 | 0 | rpc->state = READ_RM; |
746 | 0 | rpc->inpos = 0; |
747 | 0 | if (rpc->pdu && (rpc->is_udp == 0 || rpc->is_broadcast == 0)) { |
748 | 0 | #ifdef HAVE_NFS4_2 |
749 | 0 | if (rpc->pdu->nfs4_delay_until) { |
750 | 0 | nfs4_defer_pdu(rpc, rpc->pdu); |
751 | 0 | rpc->pdu = NULL; |
752 | 0 | return; |
753 | 0 | } |
754 | 0 | #endif |
755 | 0 | rpc_free_pdu(rpc, rpc->pdu); |
756 | 0 | rpc->pdu = NULL; |
757 | 0 | } |
758 | 0 | } |
759 | | |
760 | | /* |
761 | | * ZeroCopyReadPreamble. The maximum amount of head data we read for a PDU |
762 | | * assuming that all onc-rpc and protocol layer headers will fit inside this |
763 | | * preamble and that all the remaining data will be READ3/4 payload. |
764 | | */ |
765 | 0 | #define ZCRP 1024 |
766 | | |
767 | 0 | #define MAX_UDP_SIZE 65536 |
768 | | static int |
769 | | rpc_read_from_socket(struct rpc_context *rpc) |
770 | 0 | { |
771 | 0 | ssize_t count; |
772 | 0 | int pos; |
773 | 0 | uint32_t inbuf_size; |
774 | 0 | int saved_fd = rpc->fd; |
775 | 0 | int saved_is_connected = rpc->is_connected; |
776 | |
|
777 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
778 | 0 | if (rpc->socket_disabled) { |
779 | 0 | return 0; |
780 | 0 | } |
781 | 0 | if (rpc->is_udp) { |
782 | 0 | socklen_t socklen = sizeof(rpc->udp_src); |
783 | 0 | char *buf = NULL; |
784 | |
|
785 | 0 | buf = malloc(MAX_UDP_SIZE); |
786 | 0 | if (buf == NULL) { |
787 | 0 | rpc_set_error(rpc, "Failed to malloc buffer for " |
788 | 0 | "recvfrom"); |
789 | 0 | return -1; |
790 | 0 | } |
791 | 0 | #ifdef __linux__ |
792 | 0 | struct sockaddr_in *sin; |
793 | 0 | struct sockaddr_in6 *sin6; |
794 | 0 | char cmbuf[0x100]; |
795 | 0 | struct iovec iov = { buf, MAX_UDP_SIZE }; |
796 | 0 | struct msghdr mh = { |
797 | 0 | .msg_iov = &iov, |
798 | 0 | .msg_iovlen = 1, |
799 | 0 | .msg_name = &rpc->udp_src, |
800 | 0 | .msg_namelen = socklen, |
801 | 0 | .msg_control = cmbuf, |
802 | 0 | .msg_controllen = sizeof(cmbuf), |
803 | 0 | }; |
804 | 0 | count = recvmsg(rpc->fd, &mh, 0); |
805 | 0 | for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh); |
806 | 0 | cmsg != NULL; |
807 | 0 | cmsg = CMSG_NXTHDR(&mh, cmsg)) { |
808 | | /* |
809 | | * IPv6 packet info arrives as IPV6_PKTINFO, which is |
810 | | * a different value from IP_PKTINFO, so testing only |
811 | | * the latter discarded every IPv6 cmsg and left |
812 | | * udp_dst unset for IPv6. |
813 | | */ |
814 | 0 | if (cmsg->cmsg_type != IP_PKTINFO && |
815 | 0 | cmsg->cmsg_type != IPV6_PKTINFO) { |
816 | 0 | continue; |
817 | 0 | } |
818 | 0 | switch (cmsg->cmsg_level) { |
819 | 0 | case IPPROTO_IP: |
820 | 0 | sin = (struct sockaddr_in *)&rpc->udp_dst; |
821 | 0 | sin->sin_family = AF_INET; |
822 | 0 | sin->sin_addr.s_addr = ((struct in_pktinfo *)(void *)CMSG_DATA(cmsg))->ipi_addr.s_addr; |
823 | 0 | break; |
824 | 0 | case IPPROTO_IPV6: |
825 | 0 | sin6 = (struct sockaddr_in6 *)&rpc->udp_dst; |
826 | 0 | sin6->sin6_family = AF_INET6; |
827 | 0 | memcpy(&sin6->sin6_addr.s6_addr[0], &((struct in6_pktinfo *)(void *)CMSG_DATA(cmsg))->ipi6_addr.s6_addr[0], 16); |
828 | 0 | break; |
829 | 0 | } |
830 | 0 | break; |
831 | 0 | } |
832 | | #else /* __linux__ */ |
833 | | count = recvfrom(rpc->fd, buf, MAX_UDP_SIZE, MSG_DONTWAIT, |
834 | | (struct sockaddr *)&rpc->udp_src, &socklen); |
835 | | #endif /* __linux__ */ |
836 | 0 | if (count == -1) { |
837 | 0 | free(buf); |
838 | 0 | if (errno == EINTR || errno == EAGAIN) { |
839 | 0 | return 0; |
840 | 0 | } |
841 | 0 | rpc_set_error(rpc, "Failed recvfrom: %s", |
842 | 0 | strerror(errno)); |
843 | 0 | return -1; |
844 | 0 | } |
845 | 0 | if (!rpc->is_server_context) { |
846 | 0 | rpc->rm_xid[0] = count; |
847 | 0 | rpc->rm_xid[1] = ntohl(*(uint32_t *)(void *)&buf[0]); |
848 | 0 | rpc->pdu = rpc_find_pdu(rpc, ntohl(*(uint32_t *)(void *)&buf[0])); |
849 | 0 | if (rpc->pdu == NULL) { |
850 | 0 | rpc_set_error(rpc, "Failed to match incoming PDU/XID." |
851 | 0 | " Ignoring PDU"); |
852 | 0 | free(buf); |
853 | 0 | return 0; |
854 | 0 | } |
855 | 0 | } |
856 | 0 | if (rpc->pdu) { |
857 | 0 | rpc->pdu->resp_size = count; |
858 | 0 | } |
859 | 0 | if (rpc_process_pdu(rpc, buf, count) != 0) { |
860 | 0 | rpc_set_error(rpc, "Invalid/garbage pdu received from " |
861 | 0 | "server. Ignoring PDU"); |
862 | 0 | free(buf); |
863 | 0 | return -1; |
864 | 0 | } |
865 | 0 | free(buf); |
866 | 0 | return 0; |
867 | 0 | } |
868 | | |
869 | 0 | while (1){ |
870 | | /* |
871 | | * A reply callback may disconnect the current endpoint and |
872 | | * start a new asynchronous connection. For example, the |
873 | | * portmapper callback replaces the connected portmapper |
874 | | * socket with a mountd socket that is still connecting. |
875 | | * Leave the read loop and let poll() finish that connection |
876 | | * before attempting to read from the replacement socket. |
877 | | */ |
878 | 0 | if (!rpc->is_server_context && !rpc->is_connected) { |
879 | 0 | return 0; |
880 | 0 | } |
881 | | |
882 | 0 | if (rpc->inpos == 0) { |
883 | 0 | switch (rpc->state) { |
884 | 0 | case READ_RM: |
885 | 0 | if (rpc->fragments) { |
886 | | /* |
887 | | * Continuation fragment of a record we |
888 | | * are already reassembling. Only the 4 |
889 | | * byte marker follows; the 4 bytes |
890 | | * after it are payload, not an xid. |
891 | | * rpc->pdu was resolved from the first |
892 | | * fragment and must survive. |
893 | | */ |
894 | 0 | rpc->pdu_size = 4; |
895 | 0 | rpc->buf = (char *)&rpc->rm_xid[0]; |
896 | 0 | break; |
897 | 0 | } |
898 | | /* |
899 | | * Read record marker, |
900 | | * And if this is a cleint context read the next 4 bytes |
901 | | * i.e. the XID on a client |
902 | | */ |
903 | 0 | rpc->pdu_size = 8; |
904 | 0 | rpc->buf = (char *)&rpc->rm_xid[0]; |
905 | 0 | rpc->pdu = NULL; |
906 | 0 | break; |
907 | 0 | case READ_PAYLOAD: |
908 | | /* the marker read may have prefetched 4 bytes */ |
909 | 0 | rpc->inpos = rpc->rm_prefetch; |
910 | 0 | rpc->pdu_size = rpc->rm_xid[0]; |
911 | 0 | rpc->buf = rpc->inbuf + rpc->inpos; |
912 | | |
913 | | /* |
914 | | * If it is a READ pdu, just read part of the data |
915 | | * to the buffer and read the remainder directly into |
916 | | * the application iovec. ZCRP is big enough to |
917 | | * "guarantee" that we get the whole onc-rpc as well |
918 | | * as the read3res header into the buffer. |
919 | | * I don't want to have to deal with reading too |
920 | | * little here and having to increase the limit and |
921 | | * restart unmarshalling from scratch. |
922 | | */ |
923 | | /* We do not have rpc->pdu for server context */ |
924 | | #ifdef HAVE_LIBKRB5 |
925 | | /* |
926 | | * KRB5P can not use zero-copy reads |
927 | | */ |
928 | | if (rpc->sec != RPC_SEC_KRB5P) |
929 | | #endif /* HAVE_LIBKRB5 */ |
930 | 0 | if (rpc->pdu && rpc->pdu->in.base && |
931 | 0 | !rpc->fragments && rpc->pdu_size > ZCRP) { |
932 | 0 | rpc->pdu_size = ZCRP; |
933 | 0 | } |
934 | 0 | break; |
935 | 0 | case READ_UNKNOWN: |
936 | 0 | case READ_FRAGMENT: |
937 | | /* the marker read may have prefetched 4 bytes */ |
938 | 0 | rpc->inpos = rpc->rm_prefetch; |
939 | 0 | rpc->pdu_size = rpc->rm_xid[0]; |
940 | 0 | rpc->buf = rpc->inbuf + rpc->inpos; |
941 | 0 | assert(rpc->pdu_size <= rpc->inbuf_size); |
942 | 0 | break; |
943 | 0 | case READ_IOVEC: |
944 | | /* |
945 | | * Set rpc->buf to NULL to convey to the following |
946 | | * code that data must be read into the vector buffer |
947 | | * rpc->pdu->in.iov instead. |
948 | | */ |
949 | 0 | rpc->buf = NULL; |
950 | 0 | rpc->pdu_size = rpc->pdu->read_count; |
951 | 0 | break; |
952 | 0 | case READ_PADDING: |
953 | | /* rm_xid[0] is clamped to be the remaining |
954 | | * amount of data after we have processed |
955 | | * all payload and all iovecs |
956 | | */ |
957 | 0 | rpc->pdu_size = rpc->rm_xid[0]; |
958 | 0 | rpc->buf = rpc->inbuf; |
959 | 0 | break; |
960 | 0 | } |
961 | 0 | } |
962 | | |
963 | 0 | count = rpc->pdu_size - rpc->inpos; |
964 | | /* |
965 | | * When reading padding, clamp this so we do not overwrite |
966 | | * rpc->inbuf/rpc->inbuf_size which we use as the garbage buffer |
967 | | */ |
968 | 0 | if (rpc->state == READ_PADDING) { |
969 | 0 | rpc->buf = rpc->inbuf; |
970 | 0 | if (count > rpc->inbuf_size) { |
971 | 0 | count = rpc->inbuf_size; |
972 | 0 | } |
973 | 0 | } |
974 | |
|
975 | 0 | if (rpc->buf) { |
976 | 0 | count = recv(rpc->fd, rpc->buf, count, MSG_DONTWAIT); |
977 | 0 | } else { |
978 | 0 | assert(rpc->pdu->in.iovcnt > 0); |
979 | 0 | assert(count <= rpc->pdu->in.remaining_size); |
980 | 0 | count = readv(rpc->fd, rpc->pdu->in.iov, rpc->pdu->in.iovcnt); |
981 | 0 | } |
982 | |
|
983 | 0 | if (count < 0) { |
984 | | /* |
985 | | * No more data to read so we can break out of |
986 | | * the loop and return. |
987 | | */ |
988 | 0 | if (errno == EINTR || errno == EAGAIN) { |
989 | 0 | break; |
990 | 0 | } |
991 | 0 | rpc_set_error(rpc, "Read from socket(%d) failed, errno:%d (%s). " |
992 | 0 | "Closing socket.", rpc->fd, errno, strerror(errno)); |
993 | 0 | RPC_LOG(rpc, 2, "Read from socket(%d) failed, errno:%d (%s). " |
994 | 0 | "Closing socket.", rpc->fd, errno, strerror(errno)); |
995 | 0 | return -1; |
996 | 0 | } |
997 | 0 | if (count == 0) { |
998 | 0 | rpc_set_error(rpc, "Remote side closed connection for socket fd %d", |
999 | 0 | rpc->fd); |
1000 | 0 | RPC_LOG(rpc, 2, "Remote side closed connection for socket fd %d", |
1001 | 0 | rpc->fd); |
1002 | | /* remote side has closed the socket. Reconnect. */ |
1003 | 0 | return -1; |
1004 | 0 | } |
1005 | 0 | rpc->inpos += count; |
1006 | |
|
1007 | 0 | if (rpc->buf) { |
1008 | 0 | rpc->buf += count; |
1009 | 0 | } else { |
1010 | 0 | rpc_advance_cursor(rpc, &rpc->pdu->in, count); |
1011 | 0 | } |
1012 | | |
1013 | 0 | if (rpc->inpos == rpc->pdu_size) { |
1014 | 0 | switch (rpc->state) { |
1015 | 0 | case READ_RM: |
1016 | | /* We have just read the record marker */ |
1017 | 0 | rpc->rm_xid[0] = ntohl(rpc->rm_xid[0]); |
1018 | | |
1019 | | /* |
1020 | | * The top bit marks the last fragment of the |
1021 | | * record. Anything else is a continuation and |
1022 | | * has to be stashed until the record is whole. |
1023 | | */ |
1024 | 0 | rpc->state = (rpc->rm_xid[0] & 0x80000000) ? |
1025 | 0 | READ_PAYLOAD : READ_FRAGMENT; |
1026 | 0 | rpc->rm_xid[0] &= 0x7fffffff; |
1027 | |
|
1028 | 0 | if (rpc->fragments) { |
1029 | | /* |
1030 | | * Continuation fragment. No xid to |
1031 | | * parse, and no minimum size: only the |
1032 | | * first fragment has to be big enough |
1033 | | * to hold one. Reject an empty one |
1034 | | * though, we would read 0 bytes below |
1035 | | * and mistake that for a closed |
1036 | | * connection. |
1037 | | */ |
1038 | 0 | if (rpc->rm_xid[0] == 0 || |
1039 | 0 | rpc->rm_xid[0] > MAX_FRAGMENT_SIZE) { |
1040 | 0 | rpc_set_error(rpc, "Invalid recordmarker size"); |
1041 | 0 | return -1; |
1042 | 0 | } |
1043 | | /* |
1044 | | * Bound the record, not just each |
1045 | | * fragment, or a peer can chain |
1046 | | * fragments until we run out of |
1047 | | * memory. |
1048 | | */ |
1049 | 0 | if (rpc->rm_xid[0] > |
1050 | 0 | MAX_FRAGMENT_SIZE - rpc->fragments_size) { |
1051 | 0 | rpc_set_error(rpc, "Reassembled record " |
1052 | 0 | "exceeds limit of %d bytes", |
1053 | 0 | MAX_FRAGMENT_SIZE); |
1054 | 0 | return -1; |
1055 | 0 | } |
1056 | 0 | if (adjust_inbuf(rpc, rpc->rm_xid[0]) != 0) { |
1057 | 0 | rpc_set_error(rpc, "adjust_inbuf failed " |
1058 | 0 | "for socket fd %d", rpc->fd); |
1059 | 0 | return -1; |
1060 | 0 | } |
1061 | 0 | rpc->rm_prefetch = 0; |
1062 | 0 | rpc->inpos = 0; |
1063 | 0 | continue; |
1064 | 0 | } |
1065 | | |
1066 | 0 | if (rpc->rm_xid[0] < 8 || rpc->rm_xid[0] > MAX_FRAGMENT_SIZE) { |
1067 | 0 | rpc_set_error(rpc, "Invalid recordmarker size"); |
1068 | 0 | return -1; |
1069 | 0 | } |
1070 | | |
1071 | | /* |
1072 | | * When performing zero-copy read we read just ZCRP bytes |
1073 | | * into rpc->inbuf and read rest of the data directly into |
1074 | | * user provided buffers, so we just need to allocate |
1075 | | * inbuf large enough to hold ZCRP bytes of data, plus 4 |
1076 | | * bytes for the XID, i.e., ZCRP+4 bytes. |
1077 | | * RPC fragments are directly read into rpc->inbuf, no |
1078 | | * zero copy, so we need to allocate space equal to the |
1079 | | * fragment size. For non zero-copy reads also we need to |
1080 | | * allocate the entire PDU size. |
1081 | | */ |
1082 | 0 | inbuf_size = rpc->rm_xid[0]; |
1083 | |
|
1084 | 0 | rpc->rm_xid[1] = ntohl(rpc->rm_xid[1]); |
1085 | 0 | if (!rpc->is_server_context) { |
1086 | 0 | rpc->pdu = rpc_find_pdu(rpc, rpc->rm_xid[1]); |
1087 | |
|
1088 | | #ifdef HAVE_LIBKRB5 |
1089 | | if (rpc->sec != RPC_SEC_KRB5P) |
1090 | | #endif /* HAVE_LIBKRB5 */ |
1091 | 0 | if (rpc->state != READ_FRAGMENT && |
1092 | 0 | !rpc->fragments && |
1093 | 0 | rpc->pdu && rpc->pdu->in.base) { |
1094 | 0 | inbuf_size = ZCRP; |
1095 | 0 | } |
1096 | 0 | } |
1097 | |
|
1098 | 0 | if (adjust_inbuf(rpc, inbuf_size) != 0) { |
1099 | 0 | if (!rpc->is_server_context && rpc->pdu) { |
1100 | | #ifdef HAVE_MULTITHREADING |
1101 | | if (rpc->multithreading_enabled) { |
1102 | | nfs_mt_mutex_lock(&rpc->rpc_mutex); |
1103 | | } |
1104 | | #endif /* HAVE_MULTITHREADING */ |
1105 | | |
1106 | | /* |
1107 | | * queue it back to outqueue for retransmit. |
1108 | | * Note that we don't need to queue it back to |
1109 | | * waitpdu[] queue as returning failure from |
1110 | | * here will force a reconnect, which will anyways |
1111 | | * re-queue everything from waitpdu[] to outqueue. |
1112 | | */ |
1113 | 0 | rpc_return_to_outqueue(rpc, rpc->pdu); |
1114 | 0 | rpc->pdu = NULL; |
1115 | |
|
1116 | | #ifdef HAVE_MULTITHREADING |
1117 | | if (rpc->multithreading_enabled) { |
1118 | | nfs_mt_mutex_unlock(&rpc->rpc_mutex); |
1119 | | } |
1120 | | #endif /* HAVE_MULTITHREADING */ |
1121 | 0 | } |
1122 | |
|
1123 | 0 | rpc_set_error(rpc, "adjust_inbuf failed for socket fd %d", |
1124 | 0 | rpc->fd); |
1125 | 0 | RPC_LOG(rpc, 2, "adjust_inbuf failed for socket fd %d", |
1126 | 0 | rpc->fd); |
1127 | 0 | return -1; |
1128 | 0 | } |
1129 | | |
1130 | | /* Copy the next 4 bytes into inbuf */ |
1131 | 0 | *((uint32_t *)(void *)rpc->inbuf) = htonl(rpc->rm_xid[1]); |
1132 | | |
1133 | | /* but set inpos to 0, we will update it above |
1134 | | * that we have already read these 4 bytes in |
1135 | | * PAYLOAD and FRAGMENT |
1136 | | */ |
1137 | 0 | rpc->rm_prefetch = 4; |
1138 | 0 | rpc->inpos = 0; |
1139 | |
|
1140 | 0 | if (!rpc->is_server_context) { |
1141 | | /* Unknown xid, either unsolicited |
1142 | | * or an xid we have cancelled |
1143 | | */ |
1144 | 0 | if (rpc->pdu == NULL) { |
1145 | 0 | rpc->state = READ_UNKNOWN; |
1146 | 0 | continue; |
1147 | 0 | } |
1148 | 0 | } |
1149 | 0 | continue; |
1150 | 0 | case READ_FRAGMENT: |
1151 | 0 | if (rpc_add_fragment(rpc, rpc->inbuf, rpc->inpos) != 0) { |
1152 | 0 | rpc_set_error(rpc, "Failed to queue fragment for reassembly."); |
1153 | 0 | return -1; |
1154 | 0 | } |
1155 | 0 | rpc->state = READ_RM; |
1156 | 0 | rpc->inpos = 0; |
1157 | 0 | continue; |
1158 | 0 | case READ_UNKNOWN: |
1159 | 0 | rpc->state = READ_RM; |
1160 | 0 | rpc->inpos = 0; |
1161 | 0 | continue; |
1162 | 0 | case READ_PAYLOAD: |
1163 | 0 | if (rpc->fragments) { |
1164 | 0 | rpc->buf = rpc_reassemble_pdu(rpc, &rpc->pdu_size); |
1165 | 0 | if (rpc->buf == NULL) { |
1166 | 0 | return -1; |
1167 | 0 | } |
1168 | 0 | } else { |
1169 | 0 | rpc->buf = rpc->inbuf; |
1170 | 0 | } |
1171 | 0 | if (rpc->pdu) { |
1172 | | /* pdu_size is the RPC message length; +4 for record marker */ |
1173 | 0 | rpc->pdu->resp_size = rpc->pdu_size + 4; |
1174 | 0 | } |
1175 | 0 | if (rpc_process_pdu(rpc, rpc->buf, rpc->pdu_size) != 0) { |
1176 | 0 | rpc_set_error(rpc, "Invalid/garbage pdu" |
1177 | 0 | " received from server. " |
1178 | 0 | "Closing socket"); |
1179 | 0 | return -1; |
1180 | 0 | } |
1181 | 0 | if (rpc->fd != saved_fd || |
1182 | 0 | rpc->is_connected != saved_is_connected) { |
1183 | | /* |
1184 | | * A callback replaced the connection |
1185 | | * under us, so we must not carry on |
1186 | | * reading with state that belongs to |
1187 | | * the old one. The reply we just |
1188 | | * processed still has to be released, |
1189 | | * or every reconnect driven from a |
1190 | | * callback leaks its PDU, which is |
1191 | | * what the mount sequence does at each |
1192 | | * step as it moves between portmap, |
1193 | | * mountd and nfsd. |
1194 | | * |
1195 | | * Finishing here cannot invoke a |
1196 | | * callback twice: free_pdu is only set |
1197 | | * on the zero-copy read path, and that |
1198 | | * path breaks out before running any |
1199 | | * callback, so it cannot be what |
1200 | | * changed the connection. |
1201 | | */ |
1202 | 0 | rpc_finished_pdu(rpc); |
1203 | 0 | return 0; |
1204 | 0 | } |
1205 | | #ifdef HAVE_LIBKRB5 |
1206 | | /* |
1207 | | * Since we don't do zero-copy reads for |
1208 | | * KRB5P we are basically finished processing |
1209 | | * the reply at this point. |
1210 | | */ |
1211 | | if (rpc->sec == RPC_SEC_KRB5P) { |
1212 | | goto payload_finished; |
1213 | | } |
1214 | | #endif /* HAVE_LIBKRB5 */ |
1215 | | /* We do not have rpc->pdu for server context */ |
1216 | 0 | if (rpc->pdu && rpc->pdu->free_zdr) { |
1217 | 0 | if (rpc->program == NFS_PROGRAM && rpc->version == NFS_V3) { |
1218 | | /* |
1219 | | * If the READ failed, bail out here as there is no |
1220 | | * data. |
1221 | | */ |
1222 | 0 | const READ3res *res = (READ3res *)(void *) rpc->pdu->zdr_decode_buf; |
1223 | 0 | if (res->status != NFS3_OK) { |
1224 | 0 | goto payload_finished; |
1225 | 0 | } |
1226 | 0 | } |
1227 | 0 | if (rpc->program == NFS4_PROGRAM && rpc->version == NFS_V4) { |
1228 | | /* |
1229 | | * Same for v4. The COMPOUND status is the status of |
1230 | | * the last op, which for a zero-copy read is the READ. |
1231 | | */ |
1232 | 0 | const COMPOUND4res *res = (COMPOUND4res *)(void *) rpc->pdu->zdr_decode_buf; |
1233 | 0 | if (res->status != NFS4_OK) { |
1234 | 0 | goto payload_finished; |
1235 | 0 | } |
1236 | 0 | } |
1237 | | |
1238 | | /* |
1239 | | * We are doing zero-copy read. |
1240 | | * pdu->read_count is the amount of read data returned by |
1241 | | * the server in this RPC response. |
1242 | | */ |
1243 | 0 | if (!zdr_uint32_t(&rpc->pdu->zdr, &rpc->pdu->read_count)) |
1244 | 0 | return -1; |
1245 | | |
1246 | | /* |
1247 | | * Now pos is pointing at the start of data, and |
1248 | | * rpc->buf/rpc->pdu_size is the record we just |
1249 | | * processed, so "rpc->pdu_size - pos" is the number |
1250 | | * of data bytes we hold. For a single record that is |
1251 | | * rpc->inbuf and is less than ZCRP, since we clamped |
1252 | | * the read size to ZCRP above. For a reply that came |
1253 | | * in fragments it is the reassembly buffer and the |
1254 | | * whole record, so the entire read payload and not |
1255 | | * bounded by ZCRP. rpc->inpos cannot be used here: in |
1256 | | * the reassembled case it only covers the last |
1257 | | * fragment. |
1258 | | */ |
1259 | 0 | pos = zdr_getpos(&rpc->pdu->zdr); |
1260 | 0 | count = rpc->pdu_size - pos; |
1261 | 0 | assert(rpc->fragments || count <= ZCRP); |
1262 | | /* |
1263 | | * No sane server will return more read data than we asked for. |
1264 | | * If the server is buggy and does send more, we discard the extra |
1265 | | * data. |
1266 | | */ |
1267 | 0 | if (rpc->pdu->read_count > rpc->pdu->requested_read_count) { |
1268 | 0 | rpc->pdu->read_count = rpc->pdu->requested_read_count; |
1269 | 0 | } |
1270 | | |
1271 | | /* |
1272 | | * Clamp count to the actual data read, minus any padding. |
1273 | | */ |
1274 | 0 | if (count > rpc->pdu->read_count) { |
1275 | 0 | count = rpc->pdu->read_count; |
1276 | 0 | } |
1277 | 0 | if (rpc->pdu->in.remaining_size > rpc->pdu->read_count) { |
1278 | | /* we got a short read */ |
1279 | 0 | rpc_shrink_cursor(rpc, &rpc->pdu->in, rpc->pdu->read_count); |
1280 | 0 | assert(rpc->pdu->in.remaining_size == rpc->pdu->read_count); |
1281 | 0 | } |
1282 | | |
1283 | | /* XXX With the above two clamps, can this still happen ? */ |
1284 | 0 | if (rpc->pdu->in.remaining_size < count) { |
1285 | 0 | count = rpc->pdu->in.remaining_size; |
1286 | 0 | } |
1287 | 0 | rpc_memcpy_cursor(rpc, &rpc->pdu->in, &rpc->buf[pos], count); |
1288 | |
|
1289 | 0 | if (rpc->pdu->in.remaining_size == 0) { |
1290 | | // handle padding? |
1291 | 0 | } else if (rpc->fragments) { |
1292 | | /* |
1293 | | * A reassembled record is whole, |
1294 | | * so there is nothing left on |
1295 | | * the socket for this reply. If |
1296 | | * it still claims more read data |
1297 | | * than the record carried it is |
1298 | | * malformed, and continuing into |
1299 | | * READ_IOVEC would consume the |
1300 | | * next record as payload and |
1301 | | * desync the stream. |
1302 | | */ |
1303 | 0 | rpc_set_error(rpc, "READ reply declares " |
1304 | 0 | "more data than the " |
1305 | 0 | "reassembled record holds"); |
1306 | 0 | free(rpc->buf); |
1307 | 0 | rpc->buf = NULL; |
1308 | 0 | rpc_free_all_fragments(rpc); |
1309 | 0 | return -1; |
1310 | 0 | } else { |
1311 | 0 | rpc->pdu->read_count -= count; |
1312 | 0 | rpc->state = READ_IOVEC; |
1313 | 0 | rpc->inpos = 0; |
1314 | 0 | rpc->rm_xid[0] -= pos + count; |
1315 | 0 | continue; |
1316 | 0 | } |
1317 | 0 | } |
1318 | 0 | payload_finished: |
1319 | 0 | if (rpc->fragments) { |
1320 | 0 | free(rpc->buf); |
1321 | 0 | rpc->buf = NULL; |
1322 | 0 | rpc_free_all_fragments(rpc); |
1323 | 0 | } |
1324 | 0 | rpc_finished_pdu(rpc); |
1325 | 0 | break; |
1326 | 0 | case READ_IOVEC: |
1327 | 0 | rpc->pdu->read_count -= rpc->pdu_size; |
1328 | 0 | if (rpc->rm_xid[0] < rpc->pdu_size) { |
1329 | 0 | return -1; |
1330 | 0 | } |
1331 | 0 | rpc->rm_xid[0] -= rpc->pdu_size; |
1332 | 0 | if (!rpc->rm_xid[0]) { |
1333 | 0 | rpc_finished_pdu(rpc); |
1334 | 0 | break; |
1335 | 0 | } |
1336 | 0 | rpc->state = READ_PADDING; |
1337 | 0 | rpc->inpos = 0; |
1338 | 0 | continue; |
1339 | 0 | case READ_PADDING: |
1340 | 0 | rpc_finished_pdu(rpc); |
1341 | 0 | break; |
1342 | 0 | } |
1343 | 0 | } |
1344 | 0 | } |
1345 | | |
1346 | 0 | return 0; |
1347 | 0 | } |
1348 | | |
1349 | | static void |
1350 | | maybe_call_connect_cb(struct rpc_context *rpc, int status) |
1351 | 0 | { |
1352 | 0 | rpc_cb tmp_cb = rpc->connect_cb; |
1353 | |
|
1354 | 0 | if (rpc->connect_cb == NULL) { |
1355 | 0 | return; |
1356 | 0 | } |
1357 | | |
1358 | 0 | rpc->connect_cb = NULL; |
1359 | 0 | tmp_cb(rpc, status, rpc->error_string, rpc->connect_data); |
1360 | 0 | } |
1361 | | |
1362 | | /* |
1363 | | * Return value of -1 indicates that the timeout scan discovered one or more |
1364 | | * RPCs with major timeout and caller MUST terminate the connection to try fix |
1365 | | * things. |
1366 | | */ |
1367 | | static int |
1368 | | rpc_timeout_scan(struct rpc_context *rpc) |
1369 | 0 | { |
1370 | 0 | struct rpc_pdu *pdu; |
1371 | 0 | struct rpc_pdu *next_pdu; |
1372 | 0 | uint64_t t = rpc_current_time(); |
1373 | 0 | unsigned int i; |
1374 | | /* Milliseconds since last successful RPC response on this transport */ |
1375 | 0 | const int last_rpc_msecs = |
1376 | 0 | ((rpc->last_successful_rpc_response == 0) ? -1 : |
1377 | 0 | (t - rpc->last_successful_rpc_response)); |
1378 | 0 | bool_t need_reconnect = FALSE; |
1379 | | |
1380 | | /* |
1381 | | * Only scan once per second. |
1382 | | */ |
1383 | 0 | if (t <= rpc->last_timeout_scan + 1000) { |
1384 | 0 | return 0; |
1385 | 0 | } |
1386 | 0 | rpc->last_timeout_scan = t; |
1387 | |
|
1388 | | #ifdef HAVE_MULTITHREADING |
1389 | | if (rpc->multithreading_enabled) { |
1390 | | nfs_mt_mutex_lock(&rpc->rpc_mutex); |
1391 | | } |
1392 | | #endif /* HAVE_MULTITHREADING */ |
1393 | | |
1394 | | /* |
1395 | | * First check requests that have timed out while sitting in outqueue. |
1396 | | * These have not been sent to the server so do not indicate any issue |
1397 | | * with server or connection, hence we do not take any corrective |
1398 | | * action based on these request timeouts. |
1399 | | */ |
1400 | 0 | for (pdu = rpc->outqueue.head; pdu; pdu = next_pdu) { |
1401 | 0 | next_pdu = pdu->next; |
1402 | |
|
1403 | 0 | if (pdu->timeout == 0) { |
1404 | | /* no timeout for this pdu */ |
1405 | 0 | continue; |
1406 | 0 | } |
1407 | 0 | if (t < pdu->timeout) { |
1408 | | /* not expired yet */ |
1409 | 0 | continue; |
1410 | 0 | } |
1411 | | |
1412 | | /* Timed out w/o being sent */ |
1413 | 0 | INC_STATS(rpc, num_timedout_in_outqueue); |
1414 | | |
1415 | | /* |
1416 | | * rpc->retrans > 0 implies that user wants us to retransmit |
1417 | | * timed out RPCs. Note that we treat non-zero rpc->retrans |
1418 | | * as hard mount, so we just advance the timeout values for |
1419 | | * this RPC and leave it in the outqueue. |
1420 | | * Since these have not been sent to the server, they don't |
1421 | | * signify any issue with the server or the connection and |
1422 | | * hence major timeout has no special significance for such |
1423 | | * requests. |
1424 | | */ |
1425 | 0 | if (!pdu->do_not_retry && rpc->retrans > 0) { |
1426 | | /* |
1427 | | * Ask pdu_set_timeout() to advance pdu->timeout and |
1428 | | * pdu->major_timeout. Note that major_timeout has no |
1429 | | * special significance for requests timing out in |
1430 | | * outqueue. |
1431 | | */ |
1432 | 0 | pdu->timeout = 0; |
1433 | 0 | pdu->major_timeout = 0; |
1434 | 0 | pdu_set_timeout(rpc, pdu, t); |
1435 | |
|
1436 | 0 | RPC_LOG(rpc, 2, "[pdu %p] Request timed out in outqueue, " |
1437 | 0 | "will send when connection allows!", pdu); |
1438 | 0 | } else { |
1439 | 0 | if (rpc_remove_pdu_from_queue(&rpc->outqueue, pdu)) { |
1440 | 0 | assert(rpc->stats.outqueue_len > 0); |
1441 | 0 | rpc->stats.outqueue_len--; |
1442 | 0 | } |
1443 | 0 | rpc_set_error_locked(rpc, "command timed out"); |
1444 | 0 | if (pdu->cb) { |
1445 | 0 | pdu->cb(rpc, RPC_STATUS_TIMEOUT, |
1446 | 0 | NULL, pdu->private_data); |
1447 | 0 | } |
1448 | 0 | rpc_free_pdu(rpc, pdu); |
1449 | 0 | } |
1450 | 0 | } |
1451 | | |
1452 | | /* |
1453 | | * Now look for requests in waitpdu. These are requests which have |
1454 | | * been sent to server and we are awaiting response from the server. |
1455 | | * These may indicate an unresponsive server and/or bad connection. |
1456 | | * We log a message on major_timeout and try recovery by dropping |
1457 | | * existing connection and creting a new one. |
1458 | | */ |
1459 | 0 | for (i = 0; i < rpc->num_hashes; i++) { |
1460 | 0 | struct rpc_queue *q; |
1461 | |
|
1462 | 0 | q = &rpc->waitpdu[i]; |
1463 | 0 | for (pdu = q->head; pdu; pdu = next_pdu) { |
1464 | 0 | next_pdu = pdu->next; |
1465 | |
|
1466 | 0 | if (pdu->timeout == 0) { |
1467 | | /* no timeout for this pdu */ |
1468 | 0 | continue; |
1469 | 0 | } |
1470 | 0 | if (t < pdu->timeout && t < pdu->major_timeout) { |
1471 | | /* not expired yet */ |
1472 | 0 | continue; |
1473 | 0 | } |
1474 | | |
1475 | | /* Timed out waiting for response */ |
1476 | 0 | if (t >= pdu->timeout) { |
1477 | 0 | INC_STATS(rpc, num_timedout); |
1478 | 0 | } |
1479 | |
|
1480 | 0 | rpc_remove_pdu_from_queue(q, pdu); |
1481 | 0 | rpc->waitpdu_len--; |
1482 | | |
1483 | | /* |
1484 | | * rpc->retrans > 0 implies that user wants us to |
1485 | | * retransmit timed out RPCs. We update the timeout |
1486 | | * values for these RPCs and move them to outqueue for |
1487 | | * retransmit. |
1488 | | */ |
1489 | 0 | if (!pdu->do_not_retry && rpc->retrans > 0) { |
1490 | | /* Ask pdu_set_timeout() to set pdu->timeout */ |
1491 | 0 | pdu->timeout = 0; |
1492 | |
|
1493 | 0 | if (t >= pdu->major_timeout) { |
1494 | | /* Timed out waiting for response */ |
1495 | 0 | INC_STATS(rpc, num_major_timedout); |
1496 | | |
1497 | | /* Ask pdu_set_timeout() to set pdu->major_timeout */ |
1498 | 0 | pdu->major_timeout = 0; |
1499 | 0 | if (!pdu->snr_logged) { |
1500 | | /* Log only once for an RPC */ |
1501 | 0 | pdu->snr_logged = TRUE; |
1502 | 0 | RPC_LOG(rpc, 1, "[pdu %p] Server %s " |
1503 | 0 | "not responding, still trying", |
1504 | 0 | pdu, rpc->server); |
1505 | 0 | } |
1506 | 0 | if (!need_reconnect) { |
1507 | 0 | need_reconnect = (last_rpc_msecs > rpc->timeout); |
1508 | 0 | } |
1509 | 0 | } |
1510 | | /* Reset the RPC timeout values as appropriate */ |
1511 | 0 | pdu_set_timeout(rpc, pdu, t); |
1512 | | |
1513 | | /* queue it back to outqueue for retransmit */ |
1514 | 0 | rpc_return_to_outqueue(rpc, pdu); |
1515 | 0 | } else { |
1516 | | // qqq move to a temporary queue and process after |
1517 | | // we drop the mutex |
1518 | 0 | rpc_set_error_locked(rpc, "command timed out"); |
1519 | 0 | if (pdu->cb) { |
1520 | 0 | pdu->cb(rpc, RPC_STATUS_TIMEOUT, |
1521 | 0 | NULL, pdu->private_data); |
1522 | 0 | } |
1523 | 0 | rpc_free_pdu(rpc, pdu); |
1524 | 0 | } |
1525 | 0 | } |
1526 | 0 | } |
1527 | | #ifdef HAVE_MULTITHREADING |
1528 | | if (rpc->multithreading_enabled) { |
1529 | | nfs_mt_mutex_unlock(&rpc->rpc_mutex); |
1530 | | } |
1531 | | #endif /* HAVE_MULTITHREADING */ |
1532 | |
|
1533 | 0 | if (need_reconnect) { |
1534 | 0 | RPC_LOG(rpc, 2, "rpc_timeout_scan: Recovery action needed for fd %d", |
1535 | 0 | rpc->fd); |
1536 | 0 | } |
1537 | |
|
1538 | 0 | return (need_reconnect ? -1 : 0); |
1539 | 0 | } |
1540 | | |
1541 | | #ifdef HAVE_NFS4_2 |
1542 | | /* |
1543 | | * The reply to a keepalive SEQUENCE. There is nothing to do with a good one. |
1544 | | * A bad one means the session is no longer there, which is what happens when |
1545 | | * the lease ran out before we got here, so drop it rather than keep sending |
1546 | | * into it. |
1547 | | */ |
1548 | | static void |
1549 | | renew_session_cb(struct rpc_context *rpc, int status, void *command_data, |
1550 | | void *private_data _U_) |
1551 | 0 | { |
1552 | 0 | COMPOUND4res *res = command_data; |
1553 | |
|
1554 | 0 | if (status == RPC_STATUS_SUCCESS && res && res->status == NFS4_OK) { |
1555 | 0 | return; |
1556 | 0 | } |
1557 | 0 | if (status == RPC_STATUS_CANCEL) { |
1558 | 0 | return; |
1559 | 0 | } |
1560 | | |
1561 | 0 | RPC_LOG(rpc, 1, "NFSv4 session keepalive failed, the session is gone. " |
1562 | 0 | "The context has to be remounted."); |
1563 | 0 | nfs4_session_destroy(rpc); |
1564 | 0 | } |
1565 | | |
1566 | | /* |
1567 | | * A session whose lease is never renewed is reaped by the server, and every |
1568 | | * COMPOUND after that fails. Ordinary traffic renews the lease for free, |
1569 | | * since any SEQUENCE does, so this only has to cover a connection that has |
1570 | | * gone quiet: nfs4_pdu_take_slot() pushes the deadline out on every request, |
1571 | | * and this sends a SEQUENCE of its own if the deadline is ever reached. |
1572 | | * |
1573 | | * Driven from rpc_service(), so it needs the application to keep servicing |
1574 | | * the context. One that has stopped doing even that is not going to notice |
1575 | | * the session either way. |
1576 | | */ |
1577 | | static void |
1578 | | rpc_nfs4_maybe_renew_session(struct rpc_context *rpc) |
1579 | 0 | { |
1580 | 0 | uint64_t now; |
1581 | |
|
1582 | 0 | if (!rpc->is_connected || !rpc_nfs4_session_is_valid(rpc)) { |
1583 | 0 | return; |
1584 | 0 | } |
1585 | | |
1586 | 0 | now = rpc_current_time(); |
1587 | 0 | if (rpc->nfs4_renew_due == 0) { |
1588 | 0 | rpc->nfs4_renew_due = now + NFS4_SESSION_RENEW_MSECS; |
1589 | 0 | return; |
1590 | 0 | } |
1591 | 0 | if (now < rpc->nfs4_renew_due) { |
1592 | 0 | return; |
1593 | 0 | } |
1594 | | |
1595 | | /* |
1596 | | * Move the deadline before sending, not after, so that a failure to |
1597 | | * queue does not turn into one attempt per call. |
1598 | | */ |
1599 | 0 | rpc->nfs4_renew_due = now + NFS4_SESSION_RENEW_MSECS; |
1600 | 0 | if (rpc_nfs4_renew_session_task(rpc, renew_session_cb, NULL) == NULL) { |
1601 | 0 | RPC_LOG(rpc, 2, "failed to queue an NFSv4 session keepalive. " |
1602 | 0 | "%s", rpc_get_error(rpc)); |
1603 | 0 | return; |
1604 | 0 | } |
1605 | 0 | RPC_LOG(rpc, 2, "sent an NFSv4 session keepalive"); |
1606 | 0 | } |
1607 | | #endif /* HAVE_NFS4_2 */ |
1608 | | |
1609 | | static void |
1610 | | nfs40_renew_lock(struct rpc_context *rpc) |
1611 | 0 | { |
1612 | | #ifdef HAVE_MULTITHREADING |
1613 | | if (rpc->multithreading_enabled) { |
1614 | | nfs_mt_mutex_lock(&rpc->nfs40_renew_mutex); |
1615 | | } |
1616 | | #endif /* HAVE_MULTITHREADING */ |
1617 | 0 | (void)rpc; |
1618 | 0 | } |
1619 | | |
1620 | | static void |
1621 | | nfs40_renew_unlock(struct rpc_context *rpc) |
1622 | 0 | { |
1623 | | #ifdef HAVE_MULTITHREADING |
1624 | | if (rpc->multithreading_enabled) { |
1625 | | nfs_mt_mutex_unlock(&rpc->nfs40_renew_mutex); |
1626 | | } |
1627 | | #endif /* HAVE_MULTITHREADING */ |
1628 | 0 | (void)rpc; |
1629 | 0 | } |
1630 | | |
1631 | | /* Doubles from 1s on each consecutive failure, capped at the interval. */ |
1632 | | static uint64_t |
1633 | | nfs40_renew_retry(struct rpc_context *rpc) |
1634 | 0 | { |
1635 | 0 | uint64_t retry = rpc->nfs40_renew_backoff ? |
1636 | 0 | rpc->nfs40_renew_backoff * 2 : 1000; |
1637 | |
|
1638 | 0 | if (retry > rpc->nfs40_renew_interval) { |
1639 | 0 | retry = rpc->nfs40_renew_interval; |
1640 | 0 | } |
1641 | 0 | rpc->nfs40_renew_backoff = retry; |
1642 | 0 | return retry; |
1643 | 0 | } |
1644 | | |
1645 | | static void |
1646 | | nfs40_stop_renew_locked(struct rpc_context *rpc) |
1647 | 0 | { |
1648 | 0 | rpc->nfs40_renew_enabled = 0; |
1649 | 0 | rpc->nfs40_renew_pending = 0; |
1650 | 0 | rpc->nfs40_renew_due = 0; |
1651 | 0 | rpc->nfs40_renew_backoff = 0; |
1652 | 0 | rpc->nfs40_renew_epoch++; |
1653 | 0 | } |
1654 | | |
1655 | | void rpc_nfs40_stop_renew(struct rpc_context *rpc) |
1656 | 0 | { |
1657 | 0 | nfs40_renew_lock(rpc); |
1658 | 0 | nfs40_stop_renew_locked(rpc); |
1659 | 0 | nfs40_renew_unlock(rpc); |
1660 | 0 | } |
1661 | | |
1662 | | void rpc_nfs40_start_renew(struct rpc_context *rpc, uint64_t clientid, |
1663 | | uint32_t lease_seconds) |
1664 | 0 | { |
1665 | 0 | nfs40_renew_lock(rpc); |
1666 | 0 | nfs40_stop_renew_locked(rpc); |
1667 | 0 | rpc->nfs40_clientid = clientid; |
1668 | 0 | rpc->nfs40_renew_interval = (uint64_t)lease_seconds * 500; |
1669 | 0 | rpc->nfs40_renew_due = rpc_current_time() + rpc->nfs40_renew_interval; |
1670 | 0 | rpc->nfs40_renew_enabled = 1; |
1671 | 0 | nfs40_renew_unlock(rpc); |
1672 | 0 | } |
1673 | | |
1674 | | /* Milliseconds until rpc_service() next has renewal work, or -1 for none. */ |
1675 | | int rpc_nfs40_renew_delay(struct rpc_context *rpc) |
1676 | 0 | { |
1677 | 0 | uint64_t now, remaining; |
1678 | 0 | int delay = -1; |
1679 | |
|
1680 | 0 | if (!rpc->nfs40_renew_enabled) { |
1681 | 0 | return -1; |
1682 | 0 | } |
1683 | 0 | nfs40_renew_lock(rpc); |
1684 | 0 | if (rpc->is_connected && rpc->nfs40_renew_enabled) { |
1685 | 0 | now = rpc_current_time(); |
1686 | 0 | remaining = rpc->nfs40_renew_due > now ? |
1687 | 0 | rpc->nfs40_renew_due - now : 0; |
1688 | 0 | delay = remaining < INT_MAX ? (int)remaining : INT_MAX; |
1689 | 0 | } |
1690 | 0 | nfs40_renew_unlock(rpc); |
1691 | 0 | return delay; |
1692 | 0 | } |
1693 | | |
1694 | | static void |
1695 | | nfs40_renew_cb(struct rpc_context *rpc, int status, void *command_data, |
1696 | | void *private_data) |
1697 | 0 | { |
1698 | 0 | COMPOUND4res *res = NULL; |
1699 | 0 | uint32_t epoch = (uint32_t)(uintptr_t)private_data; |
1700 | 0 | uint64_t now; |
1701 | |
|
1702 | 0 | if (status == RPC_STATUS_SUCCESS) { |
1703 | 0 | res = command_data; |
1704 | 0 | } |
1705 | 0 | nfs40_renew_lock(rpc); |
1706 | 0 | if (epoch != rpc->nfs40_renew_epoch || !rpc->nfs40_renew_enabled) { |
1707 | 0 | nfs40_renew_unlock(rpc); |
1708 | 0 | return; |
1709 | 0 | } |
1710 | 0 | rpc->nfs40_renew_pending = 0; |
1711 | 0 | now = rpc_current_time(); |
1712 | 0 | if (res && (res->status == NFS4_OK || |
1713 | 0 | res->status == NFS4ERR_CB_PATH_DOWN)) { |
1714 | 0 | rpc->nfs40_renew_due = now + rpc->nfs40_renew_interval; |
1715 | 0 | rpc->nfs40_renew_backoff = 0; |
1716 | 0 | nfs40_renew_unlock(rpc); |
1717 | 0 | RPC_LOG(rpc, 2, "NFSv4.0 lease renewed"); |
1718 | 0 | } else if (res && (res->status == NFS4ERR_EXPIRED || |
1719 | 0 | res->status == NFS4ERR_STALE_CLIENTID)) { |
1720 | 0 | nfs40_stop_renew_locked(rpc); |
1721 | 0 | nfs40_renew_unlock(rpc); |
1722 | 0 | RPC_LOG(rpc, 1, "NFSv4.0 lease lost (%s); context must be remounted", |
1723 | 0 | nfsstat4_to_str(res->status)); |
1724 | 0 | } else { |
1725 | 0 | rpc->nfs40_renew_due = now + nfs40_renew_retry(rpc); |
1726 | 0 | nfs40_renew_unlock(rpc); |
1727 | 0 | RPC_LOG(rpc, 1, "NFSv4.0 RENEW failed (RPC %d, NFS %d)", |
1728 | 0 | status, res ? (int)res->status : -1); |
1729 | 0 | } |
1730 | 0 | } |
1731 | | |
1732 | | /* A RENEW still pending when due is cancelled and resent, if fully sent. */ |
1733 | | static void |
1734 | | rpc_nfs40_maybe_renew(struct rpc_context *rpc) |
1735 | 0 | { |
1736 | 0 | uint64_t now; |
1737 | 0 | uint32_t epoch, stale_xid; |
1738 | 0 | int stalled; |
1739 | 0 | struct rpc_pdu *pdu; |
1740 | |
|
1741 | 0 | if (!rpc->nfs40_renew_enabled) { |
1742 | 0 | return; |
1743 | 0 | } |
1744 | 0 | nfs40_renew_lock(rpc); |
1745 | 0 | if (!rpc->is_connected || !rpc->nfs40_renew_enabled) { |
1746 | 0 | nfs40_renew_unlock(rpc); |
1747 | 0 | return; |
1748 | 0 | } |
1749 | 0 | now = rpc_current_time(); |
1750 | 0 | if (now < rpc->nfs40_renew_due) { |
1751 | 0 | nfs40_renew_unlock(rpc); |
1752 | 0 | return; |
1753 | 0 | } |
1754 | 0 | stalled = rpc->nfs40_renew_pending; |
1755 | 0 | stale_xid = rpc->nfs40_renew_xid; |
1756 | 0 | epoch = rpc->nfs40_renew_epoch; |
1757 | 0 | nfs40_renew_unlock(rpc); |
1758 | |
|
1759 | 0 | if (stalled && rpc_cancel_sent_pdu(rpc, stale_xid) != 0) { |
1760 | | /* Not fully written yet; a new one would only queue behind it. */ |
1761 | 0 | nfs40_renew_lock(rpc); |
1762 | 0 | if (epoch == rpc->nfs40_renew_epoch) { |
1763 | 0 | rpc->nfs40_renew_due = now + rpc->nfs40_renew_interval / 2; |
1764 | 0 | } |
1765 | 0 | nfs40_renew_unlock(rpc); |
1766 | 0 | RPC_LOG(rpc, 1, "NFSv4.0 RENEW still unsent, waiting"); |
1767 | 0 | return; |
1768 | 0 | } |
1769 | | |
1770 | 0 | nfs40_renew_lock(rpc); |
1771 | 0 | if (epoch != rpc->nfs40_renew_epoch) { |
1772 | 0 | nfs40_renew_unlock(rpc); |
1773 | 0 | return; |
1774 | 0 | } |
1775 | 0 | epoch = ++rpc->nfs40_renew_epoch; |
1776 | 0 | rpc->nfs40_renew_due = now + rpc->nfs40_renew_interval / 2; |
1777 | 0 | rpc->nfs40_renew_pending = 1; |
1778 | 0 | nfs40_renew_unlock(rpc); |
1779 | 0 | if (stalled) { |
1780 | 0 | RPC_LOG(rpc, 1, "NFSv4.0 RENEW got no reply, sending another"); |
1781 | 0 | } |
1782 | | |
1783 | | /* Unlocked: queueing takes rpc_mutex. */ |
1784 | 0 | pdu = rpc_nfs40_renew_task(rpc, nfs40_renew_cb, |
1785 | 0 | (void *)(uintptr_t)epoch); |
1786 | 0 | nfs40_renew_lock(rpc); |
1787 | 0 | if (epoch == rpc->nfs40_renew_epoch) { |
1788 | 0 | if (pdu) { |
1789 | 0 | rpc->nfs40_renew_xid = pdu->xid; |
1790 | 0 | } else { |
1791 | 0 | rpc->nfs40_renew_pending = 0; |
1792 | 0 | rpc->nfs40_renew_due = now + nfs40_renew_retry(rpc); |
1793 | 0 | } |
1794 | 0 | } |
1795 | 0 | nfs40_renew_unlock(rpc); |
1796 | 0 | if (pdu == NULL) { |
1797 | 0 | RPC_LOG(rpc, 1, "Failed to queue NFSv4.0 RENEW: %s", |
1798 | 0 | rpc_get_error(rpc)); |
1799 | 0 | return; |
1800 | 0 | } |
1801 | 0 | RPC_LOG(rpc, 2, "Queued NFSv4.0 RENEW"); |
1802 | 0 | } |
1803 | | |
1804 | | int |
1805 | | rpc_service(struct rpc_context *rpc, int revents) |
1806 | 0 | { |
1807 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
1808 | |
|
1809 | 0 | #ifdef HAVE_NFS4_2 |
1810 | 0 | nfs4_service_delayed(rpc); |
1811 | 0 | #endif |
1812 | | |
1813 | | /* |
1814 | | * rpc_timeout_scan() will return -1 to indicate that we need to perform |
1815 | | * recovery action by reconnecting and queueing all RPCs on the new |
1816 | | * connection. Schedule reconnect and requeue and return. Once the new |
1817 | | * connection is ready, events will be processed for that. |
1818 | | */ |
1819 | 0 | if (rpc_timeout_scan(rpc) != 0) { |
1820 | 0 | return rpc_reconnect_requeue(rpc); |
1821 | 0 | } |
1822 | 0 | rpc_nfs40_maybe_renew(rpc); |
1823 | |
|
1824 | 0 | #ifdef HAVE_NFS4_2 |
1825 | 0 | rpc_nfs4_maybe_renew_session(rpc); |
1826 | 0 | #endif /* HAVE_NFS4_2 */ |
1827 | |
|
1828 | 0 | if (revents == -1 || revents & (POLLERR|POLLHUP)) { |
1829 | 0 | if (revents != -1 && revents & POLLERR) { |
1830 | |
|
1831 | | #ifdef WIN32 |
1832 | | char err = 0; |
1833 | | #else |
1834 | 0 | int err = 0; |
1835 | 0 | #endif |
1836 | 0 | socklen_t err_size = sizeof(err); |
1837 | |
|
1838 | 0 | if (getsockopt(rpc->fd, SOL_SOCKET, SO_ERROR, |
1839 | 0 | (char *)&err, &err_size) != 0 || err != 0) { |
1840 | 0 | if (err == 0) { |
1841 | 0 | err = errno; |
1842 | 0 | } |
1843 | 0 | rpc_set_error(rpc, "rpc_service: socket error " |
1844 | 0 | "%s(%d).", |
1845 | 0 | strerror(err), err); |
1846 | 0 | } else { |
1847 | 0 | rpc_set_error(rpc, "rpc_service: POLLERR, " |
1848 | 0 | "Unknown socket error."); |
1849 | 0 | } |
1850 | 0 | } else if (revents != -1 && revents & POLLHUP) { |
1851 | 0 | rpc_set_error(rpc, "Socket failed with POLLHUP"); |
1852 | 0 | } |
1853 | 0 | if (rpc->auto_reconnect) { |
1854 | 0 | return rpc_reconnect_requeue(rpc); |
1855 | 0 | } |
1856 | 0 | rpc_nfs40_stop_renew(rpc); |
1857 | 0 | maybe_call_connect_cb(rpc, RPC_STATUS_ERROR); |
1858 | 0 | return -1; |
1859 | |
|
1860 | 0 | } |
1861 | | |
1862 | 0 | if (rpc->is_connected == 0 && rpc->fd != -1 && (revents & POLLOUT)) { |
1863 | 0 | int err = 0; |
1864 | 0 | socklen_t err_size = sizeof(err); |
1865 | |
|
1866 | 0 | if (getsockopt(rpc->fd, SOL_SOCKET, SO_ERROR, |
1867 | 0 | (char *)&err, &err_size) != 0 || err != 0) { |
1868 | 0 | if (err == 0) { |
1869 | 0 | err = errno; |
1870 | 0 | } |
1871 | 0 | rpc_set_error(rpc, "rpc_service: socket error " |
1872 | 0 | "%s(%d) while connecting.", |
1873 | 0 | strerror(err), err); |
1874 | 0 | maybe_call_connect_cb(rpc, RPC_STATUS_ERROR); |
1875 | 0 | return -1; |
1876 | 0 | } |
1877 | | |
1878 | 0 | rpc->is_connected = 1; |
1879 | 0 | RPC_LOG(rpc, 2, "connection established on fd %d", rpc->fd); |
1880 | 0 | maybe_call_connect_cb(rpc, RPC_STATUS_SUCCESS); |
1881 | 0 | return 0; |
1882 | 0 | } |
1883 | | |
1884 | | #ifdef HAVE_TLS |
1885 | | /* |
1886 | | * We perform TLS handshake in a nonblocking fashion, i.e., we don't |
1887 | | * block on recv() and send(), so if we get a POLLIN or POLLOUT event |
1888 | | * during TLS handshake we must advance the TLS handshake process by |
1889 | | * calling do_tls_handshake() again. do_tls_handshake() will return |
1890 | | * TLS_HANDSHAKE_IN_PROGRESS if it needs to wait for network IO, o/w |
1891 | | * it'll complete the handshake process. |
1892 | | * Note that do_tls_handshake() can correctly handle multiple calls and |
1893 | | * it can advance the handshake process till it either completes successfully |
1894 | | * or fails. |
1895 | | */ |
1896 | | if (rpc->tls_context.state == TLS_HANDSHAKE_IN_PROGRESS && |
1897 | | (revents & (POLLOUT | POLLIN))) { |
1898 | | struct tls_cb_data *data = &rpc->tls_context.data; |
1899 | | |
1900 | | /* Should be only doing this for secure transport */ |
1901 | | assert(rpc->use_tls); |
1902 | | |
1903 | | rpc->tls_context.state = do_tls_handshake(rpc); |
1904 | | |
1905 | | switch (rpc->tls_context.state) { |
1906 | | case TLS_HANDSHAKE_IN_PROGRESS: |
1907 | | RPC_LOG(rpc, 2, "do_tls_handshake() returned " |
1908 | | "TLS_HANDSHAKE_IN_PROGRESS on fd %d", |
1909 | | rpc->fd); |
1910 | | break; |
1911 | | case TLS_HANDSHAKE_COMPLETED: |
1912 | | RPC_LOG(rpc, 2, "do_tls_handshake() returned " |
1913 | | "TLS_HANDSHAKE_COMPLETED on fd %d", |
1914 | | rpc->fd); |
1915 | | data->cb(rpc, RPC_STATUS_SUCCESS, NULL, data->private_data); |
1916 | | break; |
1917 | | case TLS_HANDSHAKE_FAILED: |
1918 | | RPC_LOG(rpc, 1, "do_tls_handshake() returned " |
1919 | | "TLS_HANDSHAKE_FAILED on fd %d", |
1920 | | rpc->fd); |
1921 | | data->cb(rpc, RPC_STATUS_ERROR, "TLS_HANDSHAKE_FAILED", |
1922 | | data->private_data); |
1923 | | break; |
1924 | | default: |
1925 | | /* Should not return any other status */ |
1926 | | assert(0); |
1927 | | } |
1928 | | |
1929 | | return 0; |
1930 | | } |
1931 | | #endif /* HAVE_TLS */ |
1932 | | |
1933 | 0 | if (revents & POLLIN) { |
1934 | 0 | if (rpc_read_from_socket(rpc) != 0) { |
1935 | 0 | if (rpc->is_server_context) { |
1936 | 0 | return -1; |
1937 | 0 | } else { |
1938 | | #ifdef HAVE_TLS |
1939 | | /* |
1940 | | * TODO: read from ktls sockets will fail with EIO |
1941 | | * if TLS records of type other than data |
1942 | | * (e.g., alert or handshake) are received. |
1943 | | * We will need to issue a recvmsg() call |
1944 | | * with enough cmsg space to fetch the |
1945 | | * record type and data correctly. |
1946 | | * We can then log that here to help the |
1947 | | * user. In any case the only valid course |
1948 | | * of action is to terminate the connection |
1949 | | * and reconnect so that we can correctly |
1950 | | * re-auth. |
1951 | | */ |
1952 | | #endif /* HAVE_TLS */ |
1953 | 0 | return rpc_reconnect_requeue(rpc); |
1954 | 0 | } |
1955 | 0 | } |
1956 | 0 | } |
1957 | | |
1958 | | #ifdef HAVE_TLS |
1959 | | /* |
1960 | | * For secure NFS connections we should never write to the socket w/o |
1961 | | * properly completing the TLS handshake. Note that we do allow reads |
1962 | | * from the socket as we would want to read response to the AUTH_TLS |
1963 | | * NULL RPC. |
1964 | | */ |
1965 | | if (rpc->use_tls && (rpc->tls_context.state != TLS_HANDSHAKE_COMPLETED)) { |
1966 | | RPC_LOG(rpc, 2, "TLS handshake state %d on fd %d, skipping socket write!", |
1967 | | rpc->tls_context.state, rpc->fd); |
1968 | | return 0; |
1969 | | } |
1970 | | #endif |
1971 | | |
1972 | 0 | if ((revents & POLLOUT) && rpc_outqueue_present(rpc)) { |
1973 | 0 | if (rpc_write_to_socket(rpc) != 0) { |
1974 | 0 | if (rpc->is_server_context) { |
1975 | 0 | return -1; |
1976 | 0 | } else { |
1977 | 0 | return rpc_reconnect_requeue(rpc); |
1978 | 0 | } |
1979 | 0 | } |
1980 | 0 | } |
1981 | | |
1982 | 0 | return 0; |
1983 | 0 | } |
1984 | | |
1985 | | /* |
1986 | | * Set resiliency related paramters for the RPC context. |
1987 | | * Following are the resiliency parameters for RPC transport: |
1988 | | * 1. num_tcp_reconnect: |
1989 | | * Number of times TCP reconnection is allowed before giving up. |
1990 | | * -1 indicates retry indefinitely. |
1991 | | * 2. timeout: |
1992 | | * How long we wait for an RPC response before retrying the RPC? |
1993 | | * 0 or -1 indicates infinite timeout. |
1994 | | * 3. retrans: |
1995 | | * Number of times an RPC is retried before we consider it a "major timeout" |
1996 | | * and take further recovery actions which might involve reconnection. |
1997 | | */ |
1998 | | void |
1999 | | rpc_set_resiliency(struct rpc_context *rpc, |
2000 | | int num_tcp_reconnect, |
2001 | | int timeout_msecs, |
2002 | | int retrans) |
2003 | 0 | { |
2004 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2005 | | |
2006 | | /* we can not connect and not reconnect on a server context. */ |
2007 | 0 | if (rpc->is_server_context) { |
2008 | 0 | return; |
2009 | 0 | } |
2010 | | |
2011 | 0 | rpc->auto_reconnect = num_tcp_reconnect; |
2012 | 0 | rpc->timeout = timeout_msecs; |
2013 | 0 | rpc->retrans = retrans; |
2014 | 0 | } |
2015 | | |
2016 | | |
2017 | | void |
2018 | | rpc_set_tcp_syncnt(struct rpc_context *rpc, int v) |
2019 | 0 | { |
2020 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2021 | |
|
2022 | 0 | rpc->tcp_syncnt = v; |
2023 | 0 | } |
2024 | | |
2025 | | #ifndef TCP_SYNCNT |
2026 | | #define TCP_SYNCNT 7 |
2027 | | #endif |
2028 | | |
2029 | | static int |
2030 | | rpc_connect_sockaddr_async(struct rpc_context *rpc) |
2031 | 0 | { |
2032 | 0 | struct sockaddr_storage *s = &rpc->s; |
2033 | 0 | socklen_t socksize; |
2034 | |
|
2035 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2036 | | |
2037 | | /* |
2038 | | * The user asked for the server name to be resolved afresh on every |
2039 | | * reconnect, rather than reusing the address we resolved on the |
2040 | | * initial connect. rpc_reconnect_requeue() sets resolve_server. |
2041 | | */ |
2042 | 0 | if (rpc->resolve_server) { |
2043 | 0 | int ret; |
2044 | |
|
2045 | 0 | if (rpc->server == NULL) { |
2046 | 0 | rpc->resolve_server = 0; |
2047 | 0 | rpc_set_error(rpc, "Cannot resolve on reconnect, " |
2048 | 0 | "server name is not known"); |
2049 | 0 | return -1; |
2050 | 0 | } |
2051 | | |
2052 | 0 | RPC_LOG(rpc, 2, "Resolving server %s on reconnect (port %d)", |
2053 | 0 | rpc->server, rpc->port); |
2054 | | |
2055 | | /* |
2056 | | * Left set across the call, rpc_set_sockaddr() uses it to |
2057 | | * decide whether to report an address change. |
2058 | | */ |
2059 | 0 | ret = rpc_set_sockaddr(rpc, rpc->server, rpc->port); |
2060 | 0 | rpc->resolve_server = 0; |
2061 | 0 | if (ret != 0) { |
2062 | 0 | return -1; |
2063 | 0 | } |
2064 | 0 | } |
2065 | | |
2066 | 0 | switch (s->ss_family) { |
2067 | 0 | case AF_INET: |
2068 | 0 | socksize = sizeof(struct sockaddr_in); |
2069 | 0 | rpc->fd = create_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
2070 | 0 | if (rpc->fd == -1) { |
2071 | | /* Report the socket error, not a bogus bind error */ |
2072 | 0 | break; |
2073 | 0 | } |
2074 | 0 | if (set_bind_device(rpc->fd, rpc->ifname) != 0) { |
2075 | 0 | rpc_set_error (rpc, "Failed to bind to interface"); |
2076 | 0 | return -1; |
2077 | 0 | } |
2078 | | |
2079 | 0 | #ifdef HAVE_NETINET_TCP_H |
2080 | 0 | if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) { |
2081 | 0 | set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt); |
2082 | 0 | } |
2083 | 0 | #endif |
2084 | 0 | break; |
2085 | 0 | case AF_INET6: |
2086 | 0 | socksize = sizeof(struct sockaddr_in6); |
2087 | 0 | rpc->fd = create_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); |
2088 | 0 | if (rpc->fd == -1) { |
2089 | | /* Report the socket error, not a bogus bind error */ |
2090 | 0 | break; |
2091 | 0 | } |
2092 | 0 | if (set_bind_device(rpc->fd, rpc->ifname) != 0) { |
2093 | 0 | rpc_set_error (rpc, "Failed to bind to interface"); |
2094 | 0 | return -1; |
2095 | 0 | } |
2096 | | |
2097 | 0 | #ifdef HAVE_NETINET_TCP_H |
2098 | 0 | if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) { |
2099 | 0 | set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt); |
2100 | 0 | } |
2101 | 0 | #endif |
2102 | 0 | break; |
2103 | 0 | default: |
2104 | 0 | rpc_set_error(rpc, "Can not handle AF_FAMILY:%d", s->ss_family); |
2105 | 0 | return -1; |
2106 | 0 | } |
2107 | | |
2108 | 0 | if (rpc->fd == -1) { |
2109 | 0 | rpc_set_error(rpc, "Failed to open socket: %s", strerror(errno)); |
2110 | 0 | return -1; |
2111 | 0 | } |
2112 | | |
2113 | 0 | #if defined(HAVE_NETINET_TCP_H) && defined(TCP_NODELAY) |
2114 | 0 | set_tcp_sockopt(rpc->fd, TCP_NODELAY, 1); |
2115 | 0 | #endif |
2116 | |
|
2117 | 0 | if (rpc->old_fd) { |
2118 | 0 | #if !defined(WIN32) && !defined(PS3_PPU) && !defined(PS2_EE) |
2119 | 0 | if (dup2(rpc->fd, rpc->old_fd) == -1) { |
2120 | 0 | rpc_set_error(rpc, "dup2() failed: %s", strerror(errno)); |
2121 | 0 | return -1; |
2122 | 0 | } |
2123 | 0 | close(rpc->fd); |
2124 | 0 | rpc->fd = rpc->old_fd; |
2125 | | #else |
2126 | | /* On Windows dup2 does not work on sockets |
2127 | | * instead just close the old socket */ |
2128 | | close(rpc->old_fd); |
2129 | | rpc->old_fd = 0; |
2130 | | #endif |
2131 | 0 | } |
2132 | | |
2133 | | /* Some systems allow you to set capabilities on an executable |
2134 | | * to allow the file to be executed with privilege to bind to |
2135 | | * privileged system ports, even if the user is not root. |
2136 | | * |
2137 | | * Opportunistically try to bind the socket to a low numbered |
2138 | | * system port in the hope that the user is either root or the |
2139 | | * executable has the CAP_NET_BIND_SERVICE. |
2140 | | * |
2141 | | * As soon as we fail the bind() with EACCES we know we will never |
2142 | | * be able to bind to a system port so we terminate the loop. |
2143 | | * |
2144 | | * On linux, use |
2145 | | * sudo setcap 'cap_net_bind_service=+ep' /path/executable |
2146 | | * to make the executable able to bind to a system port. |
2147 | | * |
2148 | | * On Windows, there is no concept of privileged ports. Thus |
2149 | | * binding will usually succeed. |
2150 | | */ |
2151 | 0 | { |
2152 | 0 | struct sockaddr_storage ss; |
2153 | 0 | struct sockaddr_in *sin; |
2154 | 0 | #if !defined(PS3_PPU) && !defined(PS2_EE) |
2155 | 0 | struct sockaddr_in6 *sin6; |
2156 | 0 | #endif |
2157 | 0 | static int portOfs = 0; |
2158 | 0 | const int firstPort = 512; /* >= 512 according to Sun docs */ |
2159 | 0 | const int portCount = IPPORT_RESERVED - firstPort; |
2160 | 0 | int startOfs, port, rc; |
2161 | |
|
2162 | 0 | sin = (struct sockaddr_in *)&ss; |
2163 | 0 | #if !defined(PS3_PPU) && !defined(PS2_EE) |
2164 | 0 | sin6 = (struct sockaddr_in6 *)&ss; |
2165 | 0 | #endif |
2166 | 0 | if (portOfs == 0) { |
2167 | 0 | portOfs = rpc_current_time() % 400; |
2168 | 0 | } |
2169 | 0 | startOfs = portOfs; |
2170 | 0 | do { |
2171 | 0 | rc = -1; |
2172 | 0 | port = htons(firstPort + portOfs); |
2173 | 0 | portOfs = (portOfs + 1) % portCount; |
2174 | | |
2175 | | /* skip well-known ports */ |
2176 | 0 | if (!getservbyport(port, "tcp")) { |
2177 | 0 | memset(&ss, 0, sizeof(ss)); |
2178 | |
|
2179 | 0 | switch (s->ss_family) { |
2180 | 0 | case AF_INET: |
2181 | 0 | sin->sin_port = port; |
2182 | 0 | sin->sin_family = AF_INET; |
2183 | | #ifdef HAVE_SOCKADDR_LEN |
2184 | | sin->sin_len = |
2185 | | sizeof(struct sockaddr_in); |
2186 | | #endif |
2187 | 0 | break; |
2188 | 0 | #if !defined(PS3_PPU) && !defined(PS2_EE) |
2189 | 0 | case AF_INET6: |
2190 | 0 | sin6->sin6_port = port; |
2191 | 0 | sin6->sin6_family = AF_INET6; |
2192 | | #ifdef HAVE_SOCKADDR_LEN |
2193 | | sin6->sin6_len = |
2194 | | sizeof(struct sockaddr_in6); |
2195 | | #endif |
2196 | 0 | break; |
2197 | 0 | #endif |
2198 | 0 | } |
2199 | | |
2200 | 0 | rc = bind(rpc->fd, (struct sockaddr *)&ss, |
2201 | 0 | socksize); |
2202 | 0 | #if !defined(WIN32) |
2203 | | /* we got EACCES, so don't try again */ |
2204 | 0 | if (rc != 0 && errno == EACCES) |
2205 | 0 | break; |
2206 | 0 | #endif |
2207 | 0 | } |
2208 | 0 | } while (rc != 0 && portOfs != startOfs); |
2209 | 0 | } |
2210 | | |
2211 | 0 | rpc->is_nonblocking = !set_nonblocking(rpc->fd); |
2212 | 0 | set_nolinger(rpc->fd); |
2213 | |
|
2214 | 0 | #ifdef HAVE_NETINET_TCP_H |
2215 | | /* |
2216 | | * Enable keepalive to detect and terminate dead connections when server |
2217 | | * TCP stops responding. |
2218 | | */ |
2219 | 0 | if (set_keepalive(rpc, rpc->fd) != 0) { |
2220 | 0 | rpc_set_error(rpc, "Cannot enable keepalive for fd %d: %s", |
2221 | 0 | rpc->fd, strerror(errno)); |
2222 | 0 | return -1; |
2223 | 0 | } |
2224 | 0 | #endif |
2225 | | |
2226 | 0 | if (connect(rpc->fd, (struct sockaddr *)s, socksize) != 0 && |
2227 | 0 | errno != EINPROGRESS) { |
2228 | 0 | rpc_set_error(rpc, "connect() to server failed. %s(%d)", |
2229 | 0 | strerror(errno), errno); |
2230 | 0 | return -1; |
2231 | 0 | } |
2232 | | |
2233 | 0 | return 0; |
2234 | 0 | } |
2235 | | |
2236 | | static int |
2237 | | rpc_set_sockaddr(struct rpc_context *rpc, const char *server, int port) |
2238 | 0 | { |
2239 | 0 | struct addrinfo *ai = NULL; |
2240 | 0 | int err, i; |
2241 | | |
2242 | | /* |
2243 | | * A resolver hiccup should not tear the mount down, so retry a |
2244 | | * transient failure a few times. Keep the bound small, this runs on |
2245 | | * the caller's event loop thread. |
2246 | | */ |
2247 | 0 | for (i = 0, err = 0; i < RESOLVE_RETRIES; i++) { |
2248 | 0 | if (i) { |
2249 | 0 | RPC_LOG(rpc, 2, "rpc_set_sockaddr: getaddrinfo(%s) failed " |
2250 | 0 | "temporarily (%d), retrying", server, err); |
2251 | | #if defined(WIN32) |
2252 | | Sleep(RESOLVE_RETRY_NSECS / 1000000); |
2253 | | #else |
2254 | 0 | { |
2255 | 0 | struct timespec ts = {0, RESOLVE_RETRY_NSECS}; |
2256 | 0 | nanosleep(&ts, NULL); |
2257 | 0 | } |
2258 | 0 | #endif |
2259 | 0 | } |
2260 | 0 | err = getaddrinfo(server, NULL, NULL, &ai); |
2261 | 0 | #ifdef EAI_AGAIN |
2262 | | /* Only a transient failure is worth another try. */ |
2263 | 0 | if (err != EAI_AGAIN) |
2264 | 0 | break; |
2265 | | #else |
2266 | | break; |
2267 | | #endif |
2268 | 0 | } |
2269 | |
|
2270 | 0 | if (err != 0) { |
2271 | 0 | rpc_set_error(rpc, "Invalid address:%s. " |
2272 | 0 | "Can not resolv into IPv4/v6 structure. " |
2273 | 0 | "getaddrinfo error %d", server, err); |
2274 | 0 | return -1; |
2275 | 0 | } |
2276 | | |
2277 | 0 | switch (ai->ai_family) { |
2278 | 0 | case AF_INET: |
2279 | 0 | if (rpc->resolve_server && |
2280 | 0 | ((struct sockaddr_in *)&rpc->s)->sin_family == AF_INET) { |
2281 | 0 | const uint32_t o = |
2282 | 0 | ntohl(((struct sockaddr_in *)&rpc->s)->sin_addr.s_addr); |
2283 | 0 | const uint32_t n = |
2284 | 0 | ntohl(((struct sockaddr_in *)(void *)(ai->ai_addr))->sin_addr.s_addr); |
2285 | |
|
2286 | 0 | if (o != n) { |
2287 | 0 | RPC_LOG(rpc, 1, "rpc_set_sockaddr (%s): IPv4 address " |
2288 | 0 | "changed from %u.%u.%u.%u -> %u.%u.%u.%u", |
2289 | 0 | server, |
2290 | 0 | o >> 24, (o >> 16) & 0xff, (o >> 8) & 0xff, o & 0xff, |
2291 | 0 | n >> 24, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff); |
2292 | 0 | } |
2293 | 0 | } |
2294 | |
|
2295 | 0 | ((struct sockaddr_in *)&rpc->s)->sin_family = ai->ai_family; |
2296 | 0 | ((struct sockaddr_in *)&rpc->s)->sin_port = htons(port); |
2297 | 0 | ((struct sockaddr_in *)&rpc->s)->sin_addr = |
2298 | 0 | ((struct sockaddr_in *)(void *)(ai->ai_addr))->sin_addr; |
2299 | | #ifdef HAVE_SOCKADDR_LEN |
2300 | | ((struct sockaddr_in *)&rpc->s)->sin_len = |
2301 | | sizeof(struct sockaddr_in); |
2302 | | #endif |
2303 | 0 | break; |
2304 | 0 | #if !defined(PS3_PPU) && !defined(PS2_EE) |
2305 | 0 | case AF_INET6: |
2306 | 0 | ((struct sockaddr_in6 *)&rpc->s)->sin6_family = ai->ai_family; |
2307 | 0 | ((struct sockaddr_in6 *)&rpc->s)->sin6_port = htons(port); |
2308 | 0 | ((struct sockaddr_in6 *)&rpc->s)->sin6_addr = |
2309 | 0 | ((struct sockaddr_in6 *)(void *)(ai->ai_addr))->sin6_addr; |
2310 | | #ifdef HAVE_SOCKADDR_LEN |
2311 | | ((struct sockaddr_in6 *)&rpc->s)->sin6_len = |
2312 | | sizeof(struct sockaddr_in6); |
2313 | | #endif |
2314 | 0 | break; |
2315 | 0 | #endif |
2316 | 0 | } |
2317 | 0 | freeaddrinfo(ai); |
2318 | | |
2319 | | /* Remember the port so a re-resolve on reconnect can reuse it. */ |
2320 | 0 | rpc->port = port; |
2321 | |
|
2322 | 0 | return 0; |
2323 | 0 | } |
2324 | | |
2325 | | int |
2326 | | rpc_connect_async(struct rpc_context *rpc, const char *server, int port, |
2327 | | rpc_cb cb, void *private_data) |
2328 | 0 | { |
2329 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2330 | |
|
2331 | 0 | if (rpc->is_server_context) { |
2332 | 0 | rpc_set_error(rpc, "Can not connect on a server context"); |
2333 | 0 | return -1; |
2334 | 0 | } |
2335 | | |
2336 | 0 | if (rpc->fd != -1) { |
2337 | 0 | rpc_set_error(rpc, "Trying to connect while already connected"); |
2338 | 0 | return -1; |
2339 | 0 | } |
2340 | | |
2341 | 0 | if (rpc->is_udp != 0) { |
2342 | 0 | rpc_set_error(rpc, "Trying to connect on UDP socket"); |
2343 | 0 | return -1; |
2344 | 0 | } |
2345 | | |
2346 | 0 | rpc->auto_reconnect = 0; |
2347 | |
|
2348 | 0 | if (rpc_set_sockaddr(rpc, server, port) != 0) { |
2349 | 0 | return -1; |
2350 | 0 | } |
2351 | | |
2352 | 0 | rpc->connect_cb = cb; |
2353 | 0 | rpc->connect_data = private_data; |
2354 | |
|
2355 | 0 | if (rpc_connect_sockaddr_async(rpc) != 0) { |
2356 | 0 | rpc->connect_cb = NULL; |
2357 | 0 | return -1; |
2358 | 0 | } |
2359 | | |
2360 | 0 | return 0; |
2361 | 0 | } |
2362 | | |
2363 | | int |
2364 | | rpc_disconnect(struct rpc_context *rpc, const char *error) |
2365 | 0 | { |
2366 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2367 | 0 | rpc_nfs40_stop_renew(rpc); |
2368 | |
|
2369 | 0 | if (rpc->fd != -1) { |
2370 | 0 | close(rpc->fd); |
2371 | 0 | rpc->fd = -1; |
2372 | 0 | } |
2373 | | |
2374 | | /* Do not re-disconnect if we are already disconnected */ |
2375 | 0 | if (!rpc->is_connected) { |
2376 | | /* but a connect still in flight must be cancelled */ |
2377 | 0 | rpc_set_resiliency(rpc, 0, rpc->timeout, 0); |
2378 | 0 | maybe_call_connect_cb(rpc, RPC_STATUS_CANCEL); |
2379 | 0 | return 0; |
2380 | 0 | } |
2381 | | |
2382 | | /* Turn off resiliency */ |
2383 | 0 | rpc_set_resiliency(rpc, 0, rpc->timeout, 0); |
2384 | |
|
2385 | 0 | rpc->is_connected = 0; |
2386 | | |
2387 | | /* |
2388 | | * Whatever we were part way through reading belongs to the socket we |
2389 | | * just closed. Only rpc_reconnect_requeue() reset this, so a plain |
2390 | | * disconnect followed by a fresh connect resumed mid-record and ate |
2391 | | * the new connection's first bytes as the tail of the old one. |
2392 | | * |
2393 | | * rpc->pdu is deliberately left alone here. When the disconnect comes |
2394 | | * from inside a reply callback, which is what the mount sequence |
2395 | | * does, rpc_read_from_socket() sees the connection change under it |
2396 | | * and completes that pdu itself. |
2397 | | */ |
2398 | 0 | rpc->state = READ_RM; |
2399 | 0 | rpc->inpos = 0; |
2400 | 0 | rpc_free_all_fragments(rpc); |
2401 | |
|
2402 | 0 | if (!rpc->is_server_context) { |
2403 | 0 | rpc_error_all_pdus(rpc, error); |
2404 | 0 | } |
2405 | |
|
2406 | 0 | maybe_call_connect_cb(rpc, RPC_STATUS_CANCEL); |
2407 | 0 | return 0; |
2408 | 0 | } |
2409 | | |
2410 | | #ifdef HAVE_TLS |
2411 | | /* |
2412 | | * During TCP reconnection (either server or client closes connection) for secure |
2413 | | * transport we need to perform the TLS handshake. This is the callback function |
2414 | | * called when a TLS handshake performed during reconnection completes. |
2415 | | */ |
2416 | | static void |
2417 | | reconnect_cb_tls(struct rpc_context *rpc, int status, |
2418 | | void *command_data, void *private_data) |
2419 | | { |
2420 | | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2421 | | |
2422 | | /* Must be called only for TLS transport */ |
2423 | | assert(rpc->use_tls); |
2424 | | |
2425 | | /* Must be called only after TLS handshake completes/fails */ |
2426 | | assert(rpc->tls_context.state == TLS_HANDSHAKE_COMPLETED || |
2427 | | rpc->tls_context.state == TLS_HANDSHAKE_FAILED); |
2428 | | |
2429 | | /* |
2430 | | * If handshake failed, restart the entire TCP connection not just the handshake. |
2431 | | * This will create a new connection and perform the handshake. |
2432 | | */ |
2433 | | if (rpc->tls_context.state == TLS_HANDSHAKE_FAILED) { |
2434 | | RPC_LOG(rpc, 1, "reconnect_cb_tls: TLS handshake failed, restarting connection!"); |
2435 | | |
2436 | | if (rpc->fd != -1) { |
2437 | | close(rpc->fd); |
2438 | | rpc->fd = -1; |
2439 | | } |
2440 | | rpc->is_connected = 0; |
2441 | | rpc_reconnect_requeue(rpc); |
2442 | | return; |
2443 | | } |
2444 | | |
2445 | | RPC_LOG(rpc, 2, "reconnect_cb_tls: TLS handshake completed successfully!"); |
2446 | | |
2447 | | #ifdef HAVE_NFS4_2 |
2448 | | rpc_nfs4_rebind_session(rpc); |
2449 | | #endif /* HAVE_NFS4_2 */ |
2450 | | } |
2451 | | #endif |
2452 | | |
2453 | | #ifdef HAVE_NFS4_2 |
2454 | | /* |
2455 | | * Result of rebinding the session to a reconnected socket. A failure here |
2456 | | * means the session is gone for good, usually because the lease ran out |
2457 | | * while we were disconnected. Drop it so that the COMPOUNDs behind it fail |
2458 | | * with a session error rather than being sent into a session the server no |
2459 | | * longer has. |
2460 | | */ |
2461 | | static void |
2462 | | bind_conn_cb(struct rpc_context *rpc, int status, void *command_data, |
2463 | | void *private_data _U_) |
2464 | 0 | { |
2465 | 0 | COMPOUND4res *res = command_data; |
2466 | |
|
2467 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2468 | |
|
2469 | 0 | if (status == RPC_STATUS_SUCCESS && res && res->status == NFS4_OK) { |
2470 | 0 | RPC_LOG(rpc, 2, "NFSv4 session rebound to the new connection"); |
2471 | 0 | return; |
2472 | 0 | } |
2473 | | |
2474 | 0 | RPC_LOG(rpc, 1, "BIND_CONN_TO_SESSION failed, the NFSv4 session is " |
2475 | 0 | "gone. The context has to be remounted."); |
2476 | 0 | nfs4_session_destroy(rpc); |
2477 | 0 | } |
2478 | | |
2479 | | /* |
2480 | | * An NFSv4.1+ session belongs to the connection it was created on. The |
2481 | | * session itself survives a reconnect, since the server holds it until the |
2482 | | * lease expires, but the new connection is not associated with it yet and |
2483 | | * every COMPOUND we are about to retransmit would come back |
2484 | | * NFS4ERR_CONN_NOT_BOUND_TO_SESSION. Rebind before anything else goes out, |
2485 | | * which is why the operation is queued at the head of the send queue. |
2486 | | * |
2487 | | * Called once the connection is ready to carry NFS, which with TLS means |
2488 | | * after the handshake rather than after the TCP connect. |
2489 | | */ |
2490 | | static void |
2491 | | rpc_nfs4_rebind_session(struct rpc_context *rpc) |
2492 | 0 | { |
2493 | 0 | if (!rpc_nfs4_session_is_valid(rpc)) { |
2494 | 0 | return; |
2495 | 0 | } |
2496 | 0 | if (rpc_nfs4_bind_conn_to_session_task(rpc, bind_conn_cb, |
2497 | 0 | NULL) != NULL) { |
2498 | 0 | return; |
2499 | 0 | } |
2500 | | |
2501 | 0 | RPC_LOG(rpc, 1, "failed to rebind the NFSv4 session to the new " |
2502 | 0 | "connection. %s", rpc_get_error(rpc)); |
2503 | 0 | nfs4_session_destroy(rpc); |
2504 | 0 | rpc_error_all_pdus(rpc, "RPC ERROR: Failed to rebind the NFSv4 " |
2505 | 0 | "session to the reconnected socket"); |
2506 | 0 | } |
2507 | | #endif /* HAVE_NFS4_2 */ |
2508 | | |
2509 | | static void |
2510 | | reconnect_cb(struct rpc_context *rpc, int status, void *data, |
2511 | | void *private_data) |
2512 | 0 | { |
2513 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2514 | |
|
2515 | 0 | if (status != RPC_STATUS_SUCCESS) { |
2516 | 0 | rpc_set_error(rpc, "Failed to reconnect async"); |
2517 | 0 | rpc_reconnect_requeue(rpc); |
2518 | 0 | return; |
2519 | 0 | } |
2520 | | |
2521 | 0 | rpc->is_connected = 1; |
2522 | 0 | rpc->connect_cb = NULL; |
2523 | 0 | rpc->old_fd = 0; |
2524 | |
|
2525 | | #ifdef HAVE_TLS |
2526 | | /* |
2527 | | * For secure NFS connections, we need to setup TLS session now. |
2528 | | * Rebinding an NFSv4 session has to wait until the handshake is done, |
2529 | | * so reconnect_cb_tls() does it in that case. |
2530 | | */ |
2531 | | RPC_LOG(rpc, 2, "reconnect_cb called with status %d", status); |
2532 | | if (rpc->use_tls) { |
2533 | | if (rpc_null_task_authtls(rpc, rpc->nfs_version, |
2534 | | reconnect_cb_tls, NULL) == NULL) { |
2535 | | RPC_LOG(rpc, 1, "reconnect_cb: rpc_null_task_authtls() failed, " |
2536 | | "restarting connection!"); |
2537 | | /* |
2538 | | * Force reconnect so that we can time the retries using |
2539 | | * the existing rpc->num_retries. Forcing reconnect also |
2540 | | * has the advantage that it sets up a fresh TCP connection |
2541 | | * in case the older connection had some issues preventing |
2542 | | * successful TLS handshake. |
2543 | | */ |
2544 | | if (rpc->fd != -1) { |
2545 | | close(rpc->fd); |
2546 | | rpc->fd = -1; |
2547 | | } |
2548 | | rpc->is_connected = 0; |
2549 | | rpc_reconnect_requeue(rpc); |
2550 | | return; |
2551 | | } |
2552 | | return; |
2553 | | } |
2554 | | #endif /* HAVE_TLS */ |
2555 | |
|
2556 | 0 | #ifdef HAVE_NFS4_2 |
2557 | 0 | rpc_nfs4_rebind_session(rpc); |
2558 | 0 | #endif /* HAVE_NFS4_2 */ |
2559 | 0 | } |
2560 | | |
2561 | | /* Disconnect but do not error all PDUs, just move pdus in-flight back to the |
2562 | | * outqueue and reconnect. |
2563 | | */ |
2564 | | static int |
2565 | | rpc_reconnect_requeue(struct rpc_context *rpc) |
2566 | 0 | { |
2567 | 0 | struct rpc_pdu *pdu, *next; |
2568 | 0 | unsigned int i; |
2569 | |
|
2570 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2571 | |
|
2572 | 0 | if (rpc->auto_reconnect == 0) { |
2573 | 0 | RPC_LOG(rpc, 1, "reconnect is disabled"); |
2574 | 0 | rpc_error_all_pdus(rpc, "RPC ERROR: Failed to reconnect async"); |
2575 | 0 | return -1; |
2576 | 0 | } |
2577 | | |
2578 | 0 | if (rpc->is_connected) { |
2579 | 0 | rpc->num_retries = rpc->auto_reconnect; |
2580 | 0 | } |
2581 | |
|
2582 | 0 | if (rpc->fd != -1) { |
2583 | 0 | rpc->old_fd = rpc->fd; |
2584 | 0 | } |
2585 | 0 | rpc->fd = -1; |
2586 | 0 | rpc->is_connected = 0; |
2587 | | |
2588 | | /* |
2589 | | * The run of bytes written so far belongs to the socket we just |
2590 | | * dropped, and it was cut short by the disconnect rather than by the |
2591 | | * peer's receive window. Discard it instead of letting it run on into |
2592 | | * the next connection and bias the average downwards. |
2593 | | */ |
2594 | 0 | rpc->stats.last_write_bytes_before_eagain = 0; |
2595 | |
|
2596 | 0 | if (rpc->outqueue.head) { |
2597 | 0 | rpc->outqueue.head->out.num_done = 0; |
2598 | 0 | } |
2599 | |
|
2600 | 0 | rpc->inpos = 0; |
2601 | 0 | rpc->state = READ_RM; |
2602 | | |
2603 | | /* |
2604 | | * Drop all fragments on reconnect |
2605 | | */ |
2606 | 0 | rpc_free_all_fragments(rpc); |
2607 | | |
2608 | | /* Socket is closed so we will not get any replies to any commands |
2609 | | * in flight. Move them all over from the waitpdu queue back to the |
2610 | | * out queue. |
2611 | | */ |
2612 | | #ifdef HAVE_MULTITHREADING |
2613 | | if (rpc->multithreading_enabled) { |
2614 | | nfs_mt_mutex_lock(&rpc->rpc_mutex); |
2615 | | } |
2616 | | #endif /* HAVE_MULTITHREADING */ |
2617 | 0 | for (i = 0; i < rpc->num_hashes; i++) { |
2618 | 0 | struct rpc_queue *q = &rpc->waitpdu[i]; |
2619 | 0 | for (pdu = q->head; pdu; pdu = next) { |
2620 | 0 | next = pdu->next; |
2621 | 0 | rpc_return_to_outqueue(rpc, pdu); |
2622 | 0 | } |
2623 | 0 | rpc_reset_queue(q); |
2624 | 0 | } |
2625 | 0 | rpc->waitpdu_len = 0; |
2626 | | |
2627 | | /* |
2628 | | * If there's any half-read PDU, that needs to be restarted too. |
2629 | | */ |
2630 | 0 | if (rpc->pdu) { |
2631 | 0 | rpc_return_to_outqueue(rpc, rpc->pdu); |
2632 | 0 | rpc->pdu = NULL; |
2633 | 0 | } |
2634 | |
|
2635 | 0 | #ifdef HAVE_NFS4_2 |
2636 | 0 | nfs4_requeue_delayed(rpc); |
2637 | 0 | #endif /* HAVE_NFS4_2 */ |
2638 | |
|
2639 | | #ifdef HAVE_MULTITHREADING |
2640 | | if (rpc->multithreading_enabled) { |
2641 | | nfs_mt_mutex_unlock(&rpc->rpc_mutex); |
2642 | | } |
2643 | | #endif /* HAVE_MULTITHREADING */ |
2644 | |
|
2645 | 0 | if (rpc->auto_reconnect < 0 || rpc->num_retries > 0) { |
2646 | 0 | rpc->num_retries--; |
2647 | 0 | rpc->connect_cb = reconnect_cb; |
2648 | 0 | RPC_LOG(rpc, 1, "reconnect initiated to %s", |
2649 | 0 | rpc->server ? rpc->server : "<last address>"); |
2650 | | /* |
2651 | | * Tell rpc_connect_sockaddr_async() to re-resolve the server |
2652 | | * name first, if the user asked for that behaviour. |
2653 | | */ |
2654 | 0 | rpc->resolve_server = rpc->resolve_on_reconnect; |
2655 | 0 | if (rpc_connect_sockaddr_async(rpc) != 0) { |
2656 | 0 | rpc->connect_cb = NULL; |
2657 | 0 | rpc_error_all_pdus(rpc, "RPC ERROR: Failed to " |
2658 | 0 | "reconnect async"); |
2659 | 0 | return -1; |
2660 | 0 | } |
2661 | 0 | INC_STATS(rpc, num_reconnects); |
2662 | 0 | return 0; |
2663 | 0 | } |
2664 | | |
2665 | 0 | RPC_LOG(rpc, 1, "reconnect: all attempts failed."); |
2666 | 0 | rpc_error_all_pdus(rpc, "RPC ERROR: All attempts to reconnect failed."); |
2667 | 0 | return -1; |
2668 | 0 | } |
2669 | | |
2670 | | |
2671 | | int |
2672 | | rpc_bind_udp(struct rpc_context *rpc, char *addr, int port) |
2673 | 0 | { |
2674 | 0 | struct addrinfo *ai = NULL; |
2675 | 0 | char service[6]; |
2676 | |
|
2677 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2678 | |
|
2679 | 0 | if (rpc->is_udp == 0) { |
2680 | 0 | rpc_set_error(rpc, "Cant not bind UDP. Not UDP context"); |
2681 | 0 | return -1; |
2682 | 0 | } |
2683 | | |
2684 | 0 | sprintf(service, "%d", port); |
2685 | 0 | if (getaddrinfo(addr, service, NULL, &ai) != 0) { |
2686 | 0 | rpc_set_error(rpc, "Invalid address:%s. " |
2687 | 0 | "Can not resolv into IPv4/v6 structure.", addr); |
2688 | 0 | return -1; |
2689 | 0 | } |
2690 | | |
2691 | 0 | switch(ai->ai_family) { |
2692 | 0 | case AF_INET: |
2693 | 0 | rpc->fd = create_socket(ai->ai_family, SOCK_DGRAM, 0); |
2694 | 0 | if (rpc->fd == -1) { |
2695 | 0 | rpc_set_error(rpc, "Failed to create UDP socket: %s", |
2696 | 0 | strerror(errno)); |
2697 | 0 | freeaddrinfo(ai); |
2698 | 0 | return -1; |
2699 | 0 | } |
2700 | | |
2701 | 0 | if (bind(rpc->fd, (struct sockaddr *)ai->ai_addr, |
2702 | 0 | sizeof(struct sockaddr_in)) != 0) { |
2703 | 0 | rpc_set_error(rpc, "Failed to bind to UDP socket: %s", |
2704 | 0 | strerror(errno)); |
2705 | 0 | freeaddrinfo(ai); |
2706 | 0 | return -1; |
2707 | 0 | } |
2708 | 0 | break; |
2709 | 0 | default: |
2710 | 0 | rpc_set_error(rpc, "Can not handle UPD sockets of family %d " |
2711 | 0 | "yet", ai->ai_family); |
2712 | 0 | freeaddrinfo(ai); |
2713 | 0 | return -1; |
2714 | 0 | } |
2715 | | |
2716 | 0 | freeaddrinfo(ai); |
2717 | |
|
2718 | 0 | return 0; |
2719 | 0 | } |
2720 | | |
2721 | | int |
2722 | | rpc_set_udp_destination(struct rpc_context *rpc, char *addr, int port, |
2723 | | int is_broadcast) |
2724 | 0 | { |
2725 | 0 | struct addrinfo *ai = NULL; |
2726 | 0 | char service[6]; |
2727 | |
|
2728 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2729 | |
|
2730 | 0 | if (rpc->is_udp == 0) { |
2731 | 0 | rpc_set_error(rpc, "Can not set destination sockaddr. Not UDP " |
2732 | 0 | "context"); |
2733 | 0 | return -1; |
2734 | 0 | } |
2735 | | |
2736 | 0 | sprintf(service, "%d", port); |
2737 | 0 | if (getaddrinfo(addr, service, NULL, &ai) != 0) { |
2738 | 0 | rpc_set_error(rpc, "Invalid address:%s. " |
2739 | 0 | "Can not resolv into IPv4/v6 structure.", addr); |
2740 | 0 | return -1; |
2741 | 0 | } |
2742 | | |
2743 | 0 | rpc->is_broadcast = is_broadcast; |
2744 | 0 | setsockopt(rpc->fd, SOL_SOCKET, SO_BROADCAST, (char *)&is_broadcast, sizeof(is_broadcast)); |
2745 | |
|
2746 | 0 | memcpy(&rpc->udp_dest, ai->ai_addr, ai->ai_addrlen); |
2747 | 0 | freeaddrinfo(ai); |
2748 | |
|
2749 | 0 | if (!is_broadcast) { |
2750 | 0 | if (connect(rpc->fd, (struct sockaddr *)&rpc->udp_dest, sizeof(rpc->udp_dest)) != 0 && errno != EINPROGRESS) { |
2751 | 0 | rpc_set_error(rpc, "connect() to UDP address failed. %s(%d)", strerror(errno), errno); |
2752 | 0 | return -1; |
2753 | 0 | } |
2754 | 0 | } |
2755 | | |
2756 | 0 | return 0; |
2757 | 0 | } |
2758 | | |
2759 | | struct sockaddr * |
2760 | | rpc_get_udp_src_sockaddr(struct rpc_context *rpc) |
2761 | 0 | { |
2762 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2763 | |
|
2764 | 0 | return (struct sockaddr *)&rpc->udp_src; |
2765 | 0 | } |
2766 | | |
2767 | | #ifdef __linux__ |
2768 | | struct sockaddr * |
2769 | | rpc_get_udp_dst_sockaddr(struct rpc_context *rpc) |
2770 | 0 | { |
2771 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2772 | |
|
2773 | 0 | return (struct sockaddr *)&rpc->udp_dst; |
2774 | 0 | } |
2775 | | #endif |
2776 | | |
2777 | | int |
2778 | | rpc_queue_length(struct rpc_context *rpc) |
2779 | 0 | { |
2780 | 0 | int i = 0; |
2781 | |
|
2782 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2783 | |
|
2784 | | #ifdef HAVE_MULTITHREADING |
2785 | | if (rpc->multithreading_enabled) { |
2786 | | nfs_mt_mutex_lock(&rpc->rpc_mutex); |
2787 | | } |
2788 | | #endif /* HAVE_MULTITHREADING */ |
2789 | | /* |
2790 | | * outqueue_len replaces the open coded walk of rpc->outqueue, and |
2791 | | * unlike that walk it is read under the lock. |
2792 | | */ |
2793 | 0 | i += rpc->stats.outqueue_len; |
2794 | 0 | i += rpc->waitpdu_len; |
2795 | 0 | #ifdef HAVE_NFS4_2 |
2796 | 0 | i += rpc->nfs4_delay_queue_len; |
2797 | 0 | #endif |
2798 | | #ifdef HAVE_MULTITHREADING |
2799 | | if (rpc->multithreading_enabled) { |
2800 | | nfs_mt_mutex_unlock(&rpc->rpc_mutex); |
2801 | | } |
2802 | | #endif /* HAVE_MULTITHREADING */ |
2803 | |
|
2804 | 0 | return i; |
2805 | 0 | } |
2806 | | |
2807 | | int rpc_get_num_awaiting(struct rpc_context *rpc) |
2808 | 0 | { |
2809 | 0 | return rpc->waitpdu_len; |
2810 | 0 | } |
2811 | | |
2812 | | void rpc_set_awaiting_limit(struct rpc_context *rpc, int limit) |
2813 | 0 | { |
2814 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2815 | |
|
2816 | 0 | rpc->max_waitpdu_len = limit; |
2817 | 0 | } |
2818 | | |
2819 | | void |
2820 | | rpc_set_fd(struct rpc_context *rpc, int fd) |
2821 | 0 | { |
2822 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2823 | |
|
2824 | 0 | rpc->fd = fd; |
2825 | 0 | } |
2826 | | |
2827 | | void |
2828 | | rpc_set_resolve_on_reconnect(struct rpc_context *rpc, int enabled) |
2829 | 0 | { |
2830 | 0 | assert(rpc->magic == RPC_CONTEXT_MAGIC); |
2831 | |
|
2832 | 0 | rpc->resolve_on_reconnect = !!enabled; |
2833 | 0 | } |
2834 | | |
2835 | | int |
2836 | | rpc_is_udp_socket(struct rpc_context *rpc) |
2837 | 0 | { |
2838 | | #ifdef WIN32 |
2839 | | char type = 0; |
2840 | | #else |
2841 | 0 | int type = 0; |
2842 | 0 | #endif |
2843 | 0 | socklen_t len = sizeof(type); |
2844 | |
|
2845 | 0 | getsockopt(rpc->fd, SOL_SOCKET, SO_TYPE, &type, &len); |
2846 | | return type == SOCK_DGRAM; |
2847 | 0 | } |