Update Red Hat Copyright Notices
[nbdkit.git] / server / protocol-handshake.c
blob36c23fd402907fe93fe60dd0c80012930bbe8b16
1 /* nbdkit
2 * Copyright Red Hat
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <config.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <inttypes.h>
39 #include <string.h>
40 #include <unistd.h>
42 #include "internal.h"
43 #include "byte-swapping.h"
44 #include "nbd-protocol.h"
46 int
47 protocol_handshake ()
49 int r;
51 lock_request ();
52 if (!newstyle)
53 r = protocol_handshake_oldstyle ();
54 else
55 r = protocol_handshake_newstyle ();
56 unlock_request ();
58 return r;
61 /* Common code used by oldstyle and newstyle protocols to:
63 * - call the backend .open method
65 * - get the export size
67 * - compute the eflags (same between oldstyle and newstyle
68 * protocols)
70 * The protocols must defer this as late as possible so that
71 * unauthorized clients can't cause unnecessary work in .open by
72 * simply opening a TCP connection.
74 int
75 protocol_common_open (uint64_t *exportsize, uint16_t *flags,
76 const char *exportname)
78 GET_CONN;
79 int64_t size;
80 uint16_t eflags = NBD_FLAG_HAS_FLAGS;
81 int fl;
83 conn->top_context = backend_open (top, read_only, exportname, false);
84 if (conn->top_context == NULL)
85 return -1;
87 /* Prepare (for filters), called just after open. */
88 if (backend_prepare (conn->top_context) == -1)
89 return -1;
91 size = backend_get_size (conn->top_context);
92 if (size == -1)
93 return -1;
94 if (size < 0) {
95 nbdkit_error (".get_size function returned invalid value "
96 "(%" PRIi64 ")", size);
97 return -1;
100 /* Check all flags even if they won't be advertised, to prime the
101 * cache and make later request validation easier.
103 fl = backend_can_write (conn->top_context);
104 if (fl == -1)
105 return -1;
106 if (!fl)
107 eflags |= NBD_FLAG_READ_ONLY;
109 fl = backend_can_zero (conn->top_context);
110 if (fl == -1)
111 return -1;
112 if (fl)
113 eflags |= NBD_FLAG_SEND_WRITE_ZEROES;
115 fl = backend_can_fast_zero (conn->top_context);
116 if (fl == -1)
117 return -1;
118 if (fl)
119 eflags |= NBD_FLAG_SEND_FAST_ZERO;
121 fl = backend_can_trim (conn->top_context);
122 if (fl == -1)
123 return -1;
124 if (fl)
125 eflags |= NBD_FLAG_SEND_TRIM;
127 fl = backend_can_fua (conn->top_context);
128 if (fl == -1)
129 return -1;
130 if (fl)
131 eflags |= NBD_FLAG_SEND_FUA;
133 fl = backend_can_flush (conn->top_context);
134 if (fl == -1)
135 return -1;
136 if (fl)
137 eflags |= NBD_FLAG_SEND_FLUSH;
139 fl = backend_is_rotational (conn->top_context);
140 if (fl == -1)
141 return -1;
142 if (fl)
143 eflags |= NBD_FLAG_ROTATIONAL;
145 /* multi-conn is useless if parallel connections are not allowed. */
146 fl = backend_can_multi_conn (conn->top_context);
147 if (fl == -1)
148 return -1;
149 if (fl && (thread_model > NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS))
150 eflags |= NBD_FLAG_CAN_MULTI_CONN;
152 fl = backend_can_cache (conn->top_context);
153 if (fl == -1)
154 return -1;
155 if (fl)
156 eflags |= NBD_FLAG_SEND_CACHE;
158 /* The result of this is not directly advertised as part of the
159 * handshake, but priming the cache here makes BLOCK_STATUS handling
160 * not have to worry about errors, and makes test-layers easier to
161 * write.
163 fl = backend_can_extents (conn->top_context);
164 if (fl == -1)
165 return -1;
167 if (conn->structured_replies)
168 eflags |= NBD_FLAG_SEND_DF;
170 *exportsize = size;
171 *flags = eflags;
172 return 0;