10 #include <sys/socket.h>
11 #include <sys/types.h>
12 #include <semaphore.h>
18 * Types of virtuatlization
21 VIRT_NONE
=0, /**< No virtualization */
22 VIRT_IPLIT
, /**< Literal IP address as part of the filename */
23 VIRT_IPHASH
, /**< Replacing all dots in an ip address by a / before
24 doing the same as in IPLIT */
25 VIRT_CIDR
, /**< Every subnet in its own directory */
29 * Variables associated with a server.
32 gchar
* exportname
; /**< (unprocessed) filename of the file we're exporting */
33 uint64_t expected_size
; /**< size of the exported file as it was told to
34 us through configuration */
35 gchar
* listenaddr
; /**< The IP address we're listening on */
36 char* authname
; /**< filename of the authorization file */
37 int flags
; /**< flags associated with this exported file */
38 VIRT_STYLE virtstyle
;/**< The style of virtualization, if any */
39 uint8_t cidrlen
; /**< The length of the mask when we use
40 CIDR-style virtualization */
41 gchar
* prerun
; /**< command to be ran after connecting a client,
42 but before starting to serve */
43 gchar
* postrun
; /**< command that will be ran after the client
45 gchar
* servename
; /**< name of the export as selected by nbd-client */
46 int max_connections
; /**< maximum number of opened connections */
47 int numclients
; /**< number of clients connected to this export */
48 gchar
* transactionlog
;/**< filename for transaction log */
49 gchar
* cowdir
; /**< directory for copy-on-write diff files. */
50 int refcnt
; /**< reference counter */
54 * Variables associated with a client connection
56 typedef struct _client
{
57 uint64_t exportsize
; /**< size of the file we're exporting */
58 char *clientname
; /**< peer, in human-readable format */
59 struct sockaddr_storage clientaddr
; /**< peer, in binary format, network byte order */
60 char *exportname
; /**< (processed) filename of the file we're exporting */
61 GArray
*export
; /**< array of FILE_INFO of exported files;
62 array size is always 1 unless we're doing
63 the multiple file option */
64 pthread_rwlock_t export_lock
;
65 int net
; /**< The actual client socket */
66 SERVER
*server
; /**< The server this client is getting data from */
67 char* difffilename
; /**< filename of the copy-on-write file, if any */
68 int difffile
; /**< filedescriptor of copyonwrite file. @todo shouldn't this be an array too? (cfr
69 export) Or make -m and -c mutually exclusive */
70 uint32_t difffilelen
; /**< number of pages in difffile */
71 uint32_t *difmap
; /**< see comment on the global difmap for this one */
72 int transactionlogfd
; /**< fd for transaction log */
73 char semname
[100]; /**< name of the posix sem that protects access to the transaction log */
74 sem_t
*logsem
; /**< posix sem that protects access to the transaction log */
75 int clientfeats
; /**< Client flags specified during negotiation */
76 int clientflags
; /**< Internal flags for this client, as determined by nbd-server */
77 pthread_mutex_t lock
; /**< socket lock */
78 void *tls_session
; /**< TLS session context. Is NULL unless STARTTLS
79 has been negotiated. */
80 int (*socket_read
)(struct _client
*, void* buf
, size_t len
);
81 int (*socket_write
)(struct _client
*, const void* buf
, size_t len
);
82 void (*socket_closed
)(struct _client
*);
86 * Variables associated with an open file
89 int fhandle
; /**< file descriptor */
90 off_t startoff
; /**< starting offset of this file */
94 struct nbd_request
*req
;
97 size_t current_offset
;
99 unsigned int is_structured
: 1;
103 /* Constants and macros */
106 * Error domain common for all NBD server errors.
108 #define NBDS_ERR g_quark_from_static_string("server-error-quark")
111 * NBD server error codes.
114 NBDS_ERR_CFILE_NOTFOUND
, /**< The configuration file is not found */
115 NBDS_ERR_CFILE_MISSING_GENERIC
, /**< The (required) group "generic" is missing */
116 NBDS_ERR_CFILE_KEY_MISSING
, /**< A (required) key is missing */
117 NBDS_ERR_CFILE_VALUE_INVALID
, /**< A value is syntactically invalid */
118 NBDS_ERR_CFILE_VALUE_UNSUPPORTED
, /**< A value is not supported in this build */
119 NBDS_ERR_CFILE_NO_EXPORTS
, /**< A config file was specified that does not
120 define any exports */
121 NBDS_ERR_CFILE_INCORRECT_PORT
, /**< The reserved port was specified for an
123 NBDS_ERR_CFILE_DIR_UNKNOWN
, /**< A directory requested does not exist*/
124 NBDS_ERR_CFILE_READDIR_ERR
, /**< Error occurred during readdir() */
125 NBDS_ERR_CFILE_INVALID_SPLICE
, /**< We can't use splice with the other options
126 specified for the export. */
127 NBDS_ERR_SO_LINGER
, /**< Failed to set SO_LINGER to a socket */
128 NBDS_ERR_SO_REUSEADDR
, /**< Failed to set SO_REUSEADDR to a socket */
129 NBDS_ERR_SO_KEEPALIVE
, /**< Failed to set SO_KEEPALIVE to a socket */
130 NBDS_ERR_GAI
, /**< Failed to get address info */
131 NBDS_ERR_SOCKET
, /**< Failed to create a socket */
132 NBDS_ERR_BIND
, /**< Failed to bind an address to socket */
133 NBDS_ERR_LISTEN
, /**< Failed to start listening on a socket */
134 NBDS_ERR_SYS
, /**< Underlying system call or library error */
135 NBDS_ERR_CFILE_INVALID_WAIT
, /**< We can't use wait with the other options
136 specified for the export. */
142 * @todo remove this. We should use g_log in all cases, and use the
143 * logging mangler to redirect to syslog if and when necessary.
146 #define msg(prio, ...) syslog(prio, __VA_ARGS__)
148 #define msg(prio, ...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, __VA_ARGS__)
150 #define MY_NAME "nbd_server"
152 /** Per-export flags: */
153 #define F_READONLY 1 /**< flag to tell us a file is readonly */
154 #define F_MULTIFILE 2 /**< flag to tell us a file is exported using -m */
155 #define F_COPYONWRITE 4 /**< flag to tell us a file is exported using
157 #define F_AUTOREADONLY 8 /**< flag to tell us a file is set to autoreadonly */
158 #define F_SPARSE 16 /**< flag to tell us copyronwrite should use a sparse file */
159 #define F_SDP 32 /**< flag to tell us the export should be done using the Socket Direct Protocol for RDMA */
160 #define F_SYNC 64 /**< Whether to fsync() after a write */
161 #define F_FLUSH 128 /**< Whether server wants FLUSH to be sent by the client */
162 #define F_FUA 256 /**< Whether server wants FUA to be sent by the client */
163 #define F_ROTATIONAL 512 /**< Whether server wants the client to implement the elevator algorithm */
164 #define F_TEMPORARY 1024 /**< Whether the backing file is temporary and should be created then unlinked */
165 #define F_TRIM 2048 /**< Whether server wants TRIM (discard) to be sent by the client */
166 #define F_FIXED 4096 /**< Client supports fixed new-style protocol (and can thus send us extra options */
167 #define F_TREEFILES 8192 /**< flag to tell us a file is exported using -t */
168 #define F_FORCEDTLS 16384 /**< TLS is required, either for the server as a whole or for a given export */
169 #define F_SPLICE 32768 /**< flag to tell us to use splice for read/write operations */
170 #define F_WAIT 65536 /**< flag to tell us to wait for file creation */
171 #define F_DATALOG 131072 /**< flag to tell us that the transaction log shall contain the written data */
173 /** Internal flags (for clientflags) */
175 #define F_STRUCTURED 1
180 * Check whether a given address matches a given netmask.
182 * @param mask the address or netmask to check against, in ASCII representation
183 * @param addr the address to check
185 * @return true if the address matches the mask, false otherwise; in case of
186 * failure to parse netmask, returns false with err set appropriately.
187 * @todo decide what to do with v6-mapped IPv4 addresses.
189 bool address_matches(const char* mask
, const struct sockaddr
* addr
, GError
** err
);
192 * Gets a byte to allow for address masking.
194 * @param masklen the length of the requested mask.
195 * @return if the length of the mask is 8 or longer, 0xFF. Otherwise, a byte
196 * with `masklen' number of leading bits set to 1, everything else set to 0.
198 uint8_t getmaskbyte(int masklen
) G_GNUC_PURE
;
201 * Check whether a client is allowed to connect. Works with an authorization
202 * file which contains one line per machine or network, with CIDR-style
205 * @param opts The client who's trying to connect.
206 * @return 0 - authorization refused, 1 - OK
208 int authorized_client(CLIENT
*opts
);
212 * @param s the old server we want to duplicate
213 * @return new duplicated server
215 SERVER
* dup_serve(const SERVER
*const s
);
218 * Detect the size of a file.
220 * @param fhandle An open filedescriptor
221 * @return the size of the file, or UINT64_MAX if detection was
224 uint64_t size_autodetect(int fhandle
);
227 * increase the ref counter for a SERVER
229 * @param s the server to increase
231 SERVER
* serve_inc_ref(SERVER
*s
);
234 * decrement the reference counter or a SERVER
236 * @param s the server to decrement
238 SERVER
* serve_dec_ref(SERVER
*s
);
241 * Punch a hole in the backend file (if supported by the current system).
243 * @param req the request for which this is being processed
244 * @param client the client for which we're processing this request
246 int exptrim(struct nbd_request
* req
, CLIENT
* client
);