16 #include <sys/types.h>
17 #include <sys/socket.h>
20 #ifdef HAVE_SYS_MOUNT_H
21 #include <sys/mount.h>
30 struct addrinfo *res, *aitmp, hints;
32 char privmask[strlen(mask)+1];
34 int addrlen = addr->sa_family == AF_INET ? 4 : 16;
36 assert(addr->sa_family == AF_INET || addr->sa_family == AF_INET6);
38 strcpy(privmask, mask);
40 memset(&hints, 0,
sizeof(hints));
41 hints.ai_family = AF_UNSPEC;
42 hints.ai_flags = AI_NUMERICHOST;
44 if((masksep = strchr(privmask,
'/'))) {
46 masklen = strtol(++masksep, NULL, 10);
48 masklen = addrlen * 8;
52 if((e = getaddrinfo(privmask, NULL, &hints, &res))) {
58 const uint8_t* byte_s;
61 int len_left = masklen;
62 if(res->ai_family != addr->sa_family) {
65 switch(addr->sa_family) {
67 byte_s = (
const uint8_t*)(&(((
struct sockaddr_in*)addr)->sin_addr));
68 byte_t = (uint8_t*)(&(((
struct sockaddr_in*)(res->ai_addr))->sin_addr));
71 byte_s = (
const uint8_t*)(&(((
struct sockaddr_in6*)addr)->sin6_addr));
72 byte_t = (uint8_t*)(&(((
struct sockaddr_in6*)(res->ai_addr))->sin6_addr));
75 while(len_left >= 8) {
76 if(*byte_s != *byte_t) {
84 if((*byte_s & mask) != (*byte_t & mask)) {
102 for(
int i = 7; i + masklen > 7; i--) {
114 msg(LOG_INFO,
"No authorization file, granting access.");
119 msg(LOG_INFO,
"Can't open authorization file %s (%s).",
124 while (fgets(line,
LINELEN,f)!=NULL) {
127 if((pos = strchr(line,
'#'))) {
132 while((*pos) && isspace(*pos)) {
198 struct stat stat_buf;
201 #ifdef HAVE_SYS_MOUNT_H
202 #ifdef HAVE_SYS_IOCTL_H
204 DEBUG(
"looking for export size with ioctl BLKGETSIZE64\n");
205 if (!ioctl(fhandle, BLKGETSIZE64, &bytes) && bytes) {
212 DEBUG(
"looking for fhandle size with fstat\n");
213 stat_buf.st_size = 0;
214 error = fstat(fhandle, &stat_buf);
218 if (S_ISREG(stat_buf.st_mode) || (stat_buf.st_size > 0))
219 return (uint64_t)stat_buf.st_size;
221 DEBUG(
"fstat failed: %s", strerror(errno));
224 DEBUG(
"looking for fhandle size with lseek SEEK_END\n");
225 es = lseek(fhandle, (off_t)0, SEEK_END);
226 if (es > ((off_t)0)) {
229 DEBUG(
"lseek failed: %d", errno==EBADF?1:(errno==ESPIPE?2:(errno==EINVAL?3:4)));
232 DEBUG(
"Could not find size of exported block device: %s", strerror(errno));
250 DEBUG(
"TRIM not supported yet on copy-on-write exports");
262 DEBUG(
"Performed TRIM request on TREE structure from %llu to %llu", (
unsigned long long) req->
from, (
unsigned long long) req->
len);
269 if(i<client->export->len) {
277 off_t curlen = next.
startoff - reqoff;
278 off_t reqlen = curlen - reqoff > req->
len ? req->
len : curlen - reqoff;
283 }
while(i < client->export->len && cur.
startoff < (req->
from + req->
len));
284 DEBUG(
"Performed TRIM request from %llu to %llu", (
unsigned long long) req->
from, (
unsigned long long) req->
len);
289 if (lseek(handle, a, SEEK_SET) < 0) {
290 err(
"Can not seek locally!\n");
gchar * servename
name of the export as selected by nbd-client
GArray * export
array of FILE_INFO of exported files; array size is always 1 unless we're doing the multiple file opt...
void delete_treefile(char *name, off_t size, off_t pos)
Variables associated with a server.
uint8_t getmaskbyte(int masklen)
Gets a byte to allow for address masking.
SERVER * server
The server this client is getting data from.
gchar * postrun
command that will be ran after the client disconnects
int exptrim(struct nbd_request *req, CLIENT *client)
Punch a hole in the backend file (if supported by the current system).
#define msg(prio,...)
Logging macros.
int fhandle
file descriptor
bool address_matches(const char *mask, const struct sockaddr *addr, GError **err)
Check whether a given address matches a given netmask.
#define F_COPYONWRITE
flag to tell us a file is exported using copyonwrite
off_t startoff
starting offset of this file
gchar * cowdir
directory for copy-on-write diff files.
#define F_READONLY
Per-export flags:
struct sockaddr_storage clientaddr
peer, in binary format, network byte order
int flags
flags associated with this exported file
#define TREEPAGESIZE
tree (block) files uses those chunks
#define F_TREEFILES
flag to tell us a file is exported using -t
gchar * exportname
(unprocessed) filename of the file we're exporting
gchar * transactionlog
filename for transaction log
gchar * listenaddr
The IP address we're listening on.
Variables associated with a client connection.
struct nbd_reply __attribute__
Failed to get address info.
SERVER * dup_serve(const SERVER *const s)
duplicate server
Variables associated with an open file.
void myseek(int handle, off_t a)
seek to a position in a file, with error handling.
uint64_t size_autodetect(int fhandle)
Detect the size of a file.
int max_connections
maximum number of opened connections
VIRT_STYLE virtstyle
The style of virtualization, if any.
uint64_t expected_size
size of the exported file as it was told to us through configuration
gchar * prerun
command to be ran after connecting a client, but before starting to serve
uint64_t exportsize
size of the file we're exporting
char * authname
filename of the authorization file
#define LINELEN
Size of static buffer used to read the authorization file (yuck)
void punch_hole(int fd, off_t off, off_t len)
#define NBDS_ERR
Error domain common for all NBD server errors.
uint8_t cidrlen
The length of the mask when we use CIDR-style virtualization.
char * exportname
(processed) filename of the file we're exporting
int authorized_client(CLIENT *opts)
Check whether a client is allowed to connect.