16 #include <sys/types.h>
17 #include <sys/socket.h>
25 struct addrinfo *res, *aitmp, hints;
27 char privmask[strlen(mask)+1];
29 int addrlen = addr->sa_family == AF_INET ? 4 : 16;
31 assert(addr->sa_family == AF_INET || addr->sa_family == AF_INET6);
33 strcpy(privmask, mask);
35 memset(&hints, 0,
sizeof(hints));
36 hints.ai_family = AF_UNSPEC;
37 hints.ai_flags = AI_NUMERICHOST;
39 if((masksep = strchr(privmask,
'/'))) {
41 masklen = strtol(++masksep, NULL, 10);
43 masklen = addrlen * 8;
47 if((e = getaddrinfo(privmask, NULL, &hints, &res))) {
53 const uint8_t* byte_s;
56 int len_left = masklen;
57 if(res->ai_family != addr->sa_family) {
60 switch(addr->sa_family) {
62 byte_s = (
const uint8_t*)(&(((
struct sockaddr_in*)addr)->sin_addr));
63 byte_t = (uint8_t*)(&(((
struct sockaddr_in*)(res->ai_addr))->sin_addr));
66 byte_s = (
const uint8_t*)(&(((
struct sockaddr_in6*)addr)->sin6_addr));
67 byte_t = (uint8_t*)(&(((
struct sockaddr_in6*)(res->ai_addr))->sin6_addr));
70 while(len_left >= 8) {
71 if(*byte_s != *byte_t) {
79 if((*byte_s & mask) != (*byte_t & mask)) {
97 for(
int i = 7; i + masklen > 7; i--) {
109 msg(LOG_INFO,
"No authorization file, granting access.");
114 msg(LOG_INFO,
"Can't open authorization file %s (%s).",
119 while (fgets(line,
LINELEN,f)!=NULL) {
122 if((pos = strchr(line,
'#'))) {
127 while((*pos) && isspace(*pos)) {
193 struct addrinfo hints;
194 struct addrinfo *ai = NULL;
195 struct addrinfo *rp = NULL;
196 char host[NI_MAXHOST];
206 port = g_strdup_printf(
"%d", s->
port);
208 memset(&hints,
'\0',
sizeof(hints));
209 hints.ai_family = AF_UNSPEC;
210 hints.ai_socktype = SOCK_STREAM;
211 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
212 hints.ai_protocol = IPPROTO_TCP;
214 e = getaddrinfo(s->
listenaddr, port, &hints, &ai);
220 for (rp = ai; rp != NULL; rp = rp->ai_next) {
221 e = getnameinfo(rp->ai_addr, rp->ai_addrlen, host,
sizeof(host), NULL, 0, NI_NUMERICHOST);
224 fprintf(stderr,
"getnameinfo: %s\n", gai_strerror(e));
233 g_array_append_val(a, *ns);
241 fprintf(stderr,
"getaddrinfo failed on listen host/address: %s (%s)\n", s->
listenaddr ? s->
listenaddr :
"any", gai_strerror(e));
254 struct stat stat_buf;
257 #ifdef HAVE_SYS_MOUNT_H
258 #ifdef HAVE_SYS_IOCTL_H
260 DEBUG(
"looking for export size with ioctl BLKGETSIZE64\n");
261 if (!ioctl(fhandle, BLKGETSIZE64, &bytes) && bytes) {
268 DEBUG(
"looking for fhandle size with fstat\n");
269 stat_buf.st_size = 0;
270 error = fstat(fhandle, &stat_buf);
274 if (S_ISREG(stat_buf.st_mode) || (stat_buf.st_size > 0))
275 return (uint64_t)stat_buf.st_size;
277 DEBUG(
"fstat failed: %s", strerror(errno));
280 DEBUG(
"looking for fhandle size with lseek SEEK_END\n");
281 es = lseek(fhandle, (off_t)0, SEEK_END);
282 if (es > ((off_t)0)) {
285 DEBUG(
"lseek failed: %d", errno==EBADF?1:(errno==ESPIPE?2:(errno==EINVAL?3:4)));
288 DEBUG(
"Could not find size of exported block device: %s", strerror(errno));
gchar * servename
name of the export as selected by nbd-client
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
#define msg(prio,...)
Logging macros.
bool address_matches(const char *mask, const struct sockaddr *addr, GError **err)
Check whether a given address matches a given netmask.
struct sockaddr_storage clientaddr
peer, in binary format, network byte order
int flags
flags associated with this exported file
gchar * exportname
(unprocessed) filename of the file we're exporting
unsigned int port
port we're exporting this file at
gchar * transactionlog
filename for transaction log
gchar * listenaddr
The IP address we're listening on.
int socket
The socket of this server.
Variables associated with a client connection.
struct nbd_reply __attribute__
Failed to get address info.
SERVER * dup_serve(const SERVER *const s)
duplicate server
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.
int append_serve(const SERVER *const s, GArray *const a)
append new server to array
int socket_family
family of the socket
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
char * authname
filename of the authorization file
#define LINELEN
Size of static buffer used to read the authorization file (yuck)
#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.
int authorized_client(CLIENT *opts)
Check whether a client is allowed to connect.