|
Network Block Device @PACKAGE_VERSION@
|
00001 #ifndef NBDSRV_H 00002 #define NBDSRV_H 00003 00004 #include "lfs.h" 00005 00006 #include <glib.h> 00007 #include <stdbool.h> 00008 #include <stdint.h> 00009 00010 #include <sys/socket.h> 00011 #include <sys/types.h> 00012 #include "nbd.h" 00013 00014 /* Structures */ 00015 00016 /** 00017 * Types of virtuatlization 00018 **/ 00019 typedef enum { 00020 VIRT_NONE=0, /**< No virtualization */ 00021 VIRT_IPLIT, /**< Literal IP address as part of the filename */ 00022 VIRT_IPHASH, /**< Replacing all dots in an ip address by a / before 00023 doing the same as in IPLIT */ 00024 VIRT_CIDR, /**< Every subnet in its own directory */ 00025 } VIRT_STYLE; 00026 00027 /** 00028 * Variables associated with a server. 00029 **/ 00030 typedef struct { 00031 gchar* exportname; /**< (unprocessed) filename of the file we're exporting */ 00032 uint64_t expected_size; /**< size of the exported file as it was told to 00033 us through configuration */ 00034 gchar* listenaddr; /**< The IP address we're listening on */ 00035 char* authname; /**< filename of the authorization file */ 00036 int flags; /**< flags associated with this exported file */ 00037 VIRT_STYLE virtstyle;/**< The style of virtualization, if any */ 00038 uint8_t cidrlen; /**< The length of the mask when we use 00039 CIDR-style virtualization */ 00040 gchar* prerun; /**< command to be ran after connecting a client, 00041 but before starting to serve */ 00042 gchar* postrun; /**< command that will be ran after the client 00043 disconnects */ 00044 gchar* servename; /**< name of the export as selected by nbd-client */ 00045 int max_connections; /**< maximum number of opened connections */ 00046 gchar* transactionlog;/**< filename for transaction log */ 00047 gchar* cowdir; /**< directory for copy-on-write diff files. */ 00048 } SERVER; 00049 00050 /** 00051 * Variables associated with a client connection 00052 */ 00053 typedef struct { 00054 uint64_t exportsize; /**< size of the file we're exporting */ 00055 char *clientname; /**< peer, in human-readable format */ 00056 struct sockaddr_storage clientaddr; /**< peer, in binary format, network byte order */ 00057 char *exportname; /**< (processed) filename of the file we're exporting */ 00058 GArray *export; /**< array of FILE_INFO of exported files; 00059 array size is always 1 unless we're 00060 doing the multiple file option */ 00061 int net; /**< The actual client socket */ 00062 SERVER *server; /**< The server this client is getting data from */ 00063 char* difffilename; /**< filename of the copy-on-write file, if any */ 00064 int difffile; /**< filedescriptor of copyonwrite file. @todo 00065 shouldn't this be an array too? (cfr export) Or 00066 make -m and -c mutually exclusive */ 00067 uint32_t difffilelen; /**< number of pages in difffile */ 00068 uint32_t *difmap; /**< see comment on the global difmap for this one */ 00069 gboolean modern; /**< client was negotiated using modern negotiation protocol */ 00070 int transactionlogfd;/**< fd for transaction log */ 00071 int clientfeats; /**< Features supported by this client */ 00072 pthread_mutex_t lock; 00073 } CLIENT; 00074 00075 /** 00076 * Variables associated with an open file 00077 **/ 00078 typedef struct { 00079 int fhandle; /**< file descriptor */ 00080 off_t startoff; /**< starting offset of this file */ 00081 } FILE_INFO; 00082 00083 /* Constants and macros */ 00084 00085 /** 00086 * Error domain common for all NBD server errors. 00087 **/ 00088 #define NBDS_ERR g_quark_from_static_string("server-error-quark") 00089 00090 /** 00091 * NBD server error codes. 00092 **/ 00093 typedef enum { 00094 NBDS_ERR_CFILE_NOTFOUND, /**< The configuration file is not found */ 00095 NBDS_ERR_CFILE_MISSING_GENERIC, /**< The (required) group "generic" is missing */ 00096 NBDS_ERR_CFILE_KEY_MISSING, /**< A (required) key is missing */ 00097 NBDS_ERR_CFILE_VALUE_INVALID, /**< A value is syntactically invalid */ 00098 NBDS_ERR_CFILE_VALUE_UNSUPPORTED, /**< A value is not supported in this build */ 00099 NBDS_ERR_CFILE_NO_EXPORTS, /**< A config file was specified that does not 00100 define any exports */ 00101 NBDS_ERR_CFILE_INCORRECT_PORT, /**< The reserved port was specified for an 00102 old-style export. */ 00103 NBDS_ERR_CFILE_DIR_UNKNOWN, /**< A directory requested does not exist*/ 00104 NBDS_ERR_CFILE_READDIR_ERR, /**< Error occurred during readdir() */ 00105 NBDS_ERR_SO_LINGER, /**< Failed to set SO_LINGER to a socket */ 00106 NBDS_ERR_SO_REUSEADDR, /**< Failed to set SO_REUSEADDR to a socket */ 00107 NBDS_ERR_SO_KEEPALIVE, /**< Failed to set SO_KEEPALIVE to a socket */ 00108 NBDS_ERR_GAI, /**< Failed to get address info */ 00109 NBDS_ERR_SOCKET, /**< Failed to create a socket */ 00110 NBDS_ERR_BIND, /**< Failed to bind an address to socket */ 00111 NBDS_ERR_LISTEN, /**< Failed to start listening on a socket */ 00112 NBDS_ERR_SYS, /**< Underlying system call or library error */ 00113 } NBDS_ERRS; 00114 00115 /** 00116 * Logging macros. 00117 * 00118 * @todo remove this. We should use g_log in all cases, and use the 00119 * logging mangler to redirect to syslog if and when necessary. 00120 */ 00121 #ifdef ISSERVER 00122 #define msg(prio, ...) syslog(prio, __VA_ARGS__) 00123 #else 00124 #define msg(prio, ...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, __VA_ARGS__) 00125 #endif 00126 #define MY_NAME "nbd_server" 00127 00128 /** Per-export flags: */ 00129 #define F_READONLY 1 /**< flag to tell us a file is readonly */ 00130 #define F_MULTIFILE 2 /**< flag to tell us a file is exported using -m */ 00131 #define F_COPYONWRITE 4 /**< flag to tell us a file is exported using 00132 copyonwrite */ 00133 #define F_AUTOREADONLY 8 /**< flag to tell us a file is set to autoreadonly */ 00134 #define F_SPARSE 16 /**< flag to tell us copyronwrite should use a sparse file */ 00135 #define F_SDP 32 /**< flag to tell us the export should be done using the Socket Direct Protocol for RDMA */ 00136 #define F_SYNC 64 /**< Whether to fsync() after a write */ 00137 #define F_FLUSH 128 /**< Whether server wants FLUSH to be sent by the client */ 00138 #define F_FUA 256 /**< Whether server wants FUA to be sent by the client */ 00139 #define F_ROTATIONAL 512 /**< Whether server wants the client to implement the elevator algorithm */ 00140 #define F_TEMPORARY 1024 /**< Whether the backing file is temporary and should be created then unlinked */ 00141 #define F_TRIM 2048 /**< Whether server wants TRIM (discard) to be sent by the client */ 00142 #define F_FIXED 4096 /**< Client supports fixed new-style protocol (and can thus send us extra options */ 00143 #define F_TREEFILES 8192 /**< flag to tell us a file is exported using -t */ 00144 00145 /* Functions */ 00146 00147 /** 00148 * Check whether a given address matches a given netmask. 00149 * 00150 * @param mask the address or netmask to check against, in ASCII representation 00151 * @param addr the address to check 00152 * 00153 * @return true if the address matches the mask, false otherwise; in case of 00154 * failure to parse netmask, returns false with err set appropriately. 00155 * @todo decide what to do with v6-mapped IPv4 addresses. 00156 */ 00157 bool address_matches(const char* mask, const struct sockaddr* addr, GError** err); 00158 00159 /** 00160 * Gets a byte to allow for address masking. 00161 * 00162 * @param masklen the length of the requested mask. 00163 * @return if the length of the mask is 8 or longer, 0xFF. Otherwise, a byte 00164 * with `masklen' number of leading bits set to 1, everything else set to 0. 00165 */ 00166 uint8_t getmaskbyte(int masklen) G_GNUC_PURE; 00167 00168 /** 00169 * Check whether a client is allowed to connect. Works with an authorization 00170 * file which contains one line per machine or network, with CIDR-style 00171 * netmasks. 00172 * 00173 * @param opts The client who's trying to connect. 00174 * @return 0 - authorization refused, 1 - OK 00175 **/ 00176 int authorized_client(CLIENT *opts); 00177 00178 /** 00179 * duplicate server 00180 * @param s the old server we want to duplicate 00181 * @return new duplicated server 00182 **/ 00183 SERVER* dup_serve(const SERVER *const s); 00184 00185 /** 00186 * Detect the size of a file. 00187 * 00188 * @param fhandle An open filedescriptor 00189 * @return the size of the file, or UINT64_MAX if detection was 00190 * impossible. 00191 **/ 00192 uint64_t size_autodetect(int fhandle); 00193 00194 /** 00195 * Punch a hole in the backend file (if supported by the current system). 00196 * 00197 * @param req the request for which this is being processed 00198 * @param client the client for which we're processing this request 00199 **/ 00200 int exptrim(struct nbd_request* req, CLIENT* client); 00201 00202 /** 00203 * seek to a position in a file, with error handling. 00204 * @param handle a filedescriptor 00205 * @param a position to seek to 00206 * @todo get rid of this. 00207 **/ 00208 void myseek(int handle, off_t a); 00209 #endif //NBDSRV_H
1.7.3