Network Block Device @PACKAGE_VERSION@

nbdsrv.h

Go to the documentation of this file.
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