16 #include <sys/types.h>
17 #include <sys/socket.h>
19 #define LINELEN 256 /**< Size of static buffer used to read the
20 authorization file (yuck) */
24 bool address_matches(const char* mask
, const void* addr
, int af
, GError
** err
) {
25 struct addrinfo
*res
, *aitmp
, hints
;
27 char privmask
[strlen(mask
)+1];
29 int addrlen
= af
== AF_INET
? 4 : 16;
31 assert(af
== AF_INET
|| af
== 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
))) {
48 g_set_error(err
, NBDS_ERR
, NBDS_ERR_GAI
, "could not parse netmask line: %s", gai_strerror(e
));
53 const uint8_t* byte_s
= addr
;
56 int len_left
= masklen
;
57 if(res
->ai_family
!= af
) {
62 byte_t
= (uint8_t*)(&(((struct sockaddr_in
*)(res
->ai_addr
))->sin_addr
));
65 byte_t
= (uint8_t*)(&(((struct sockaddr_in6
*)(res
->ai_addr
))->sin6_addr
));
68 while(len_left
>= 8) {
69 if(*byte_s
!= *byte_t
) {
76 mask
= getmaskbyte(len_left
);
77 if((*byte_s
& mask
) != (*byte_t
& mask
)) {
90 uint8_t getmaskbyte(int masklen
) {
95 for(int i
= 7; i
+ masklen
> 7; i
--) {
102 int authorized_client(CLIENT
*opts
) {
107 struct in_addr client
;
108 struct in_addr cltemp
;
111 if ((f
=fopen(opts
->server
->authname
,"r"))==NULL
) {
112 msg(LOG_INFO
, "Can't open authorization file %s (%s).",
113 opts
->server
->authname
, strerror(errno
));
117 while (fgets(line
,LINELEN
,f
)!=NULL
) {
120 if((pos
= strchr(line
, '#'))) {
123 /* Skip whitespace */
125 while((*pos
) && isspace(*pos
)) {
128 /* Skip content-free lines */
132 struct sockaddr
* sa
= (struct sockaddr
*)&opts
->clientaddr
;
133 if(address_matches(line
, sa
->sa_data
, sa
->sa_family
, NULL
)) {
144 * @param s the old server we want to duplicate
145 * @return new duplicated server
147 SERVER
* dup_serve(const SERVER
*const s
) {
148 SERVER
*serve
= NULL
;
150 serve
=g_new0(SERVER
, 1);
155 serve
->exportname
= g_strdup(s
->exportname
);
157 serve
->expected_size
= s
->expected_size
;
160 serve
->listenaddr
= g_strdup(s
->listenaddr
);
162 serve
->port
= s
->port
;
165 serve
->authname
= strdup(s
->authname
);
167 serve
->flags
= s
->flags
;
168 serve
->socket
= s
->socket
;
169 serve
->socket_family
= s
->socket_family
;
170 serve
->virtstyle
= s
->virtstyle
;
171 serve
->cidrlen
= s
->cidrlen
;
174 serve
->prerun
= g_strdup(s
->prerun
);
177 serve
->postrun
= g_strdup(s
->postrun
);
179 if(s
->transactionlog
)
180 serve
->transactionlog
= g_strdup(s
->transactionlog
);
183 serve
->servename
= g_strdup(s
->servename
);
185 serve
->max_connections
= s
->max_connections
;
190 int append_serve(const SERVER
*const s
, GArray
*const a
) {
192 struct addrinfo hints
;
193 struct addrinfo
*ai
= NULL
;
194 struct addrinfo
*rp
= NULL
;
195 char host
[NI_MAXHOST
];
205 port
= g_strdup_printf("%d", s
->port
);
207 memset(&hints
,'\0',sizeof(hints
));
208 hints
.ai_family
= AF_UNSPEC
;
209 hints
.ai_socktype
= SOCK_STREAM
;
210 hints
.ai_flags
= AI_ADDRCONFIG
| AI_PASSIVE
;
211 hints
.ai_protocol
= IPPROTO_TCP
;
213 e
= getaddrinfo(s
->listenaddr
, port
, &hints
, &ai
);
219 for (rp
= ai
; rp
!= NULL
; rp
= rp
->ai_next
) {
220 e
= getnameinfo(rp
->ai_addr
, rp
->ai_addrlen
, host
, sizeof(host
), NULL
, 0, NI_NUMERICHOST
);
222 if (e
!= 0) { // error
223 fprintf(stderr
, "getnameinfo: %s\n", gai_strerror(e
));
227 // duplicate server and set listenaddr to resolved IP address
230 ns
->listenaddr
= g_strdup(host
);
231 ns
->socket_family
= rp
->ai_family
;
232 g_array_append_val(a
, *ns
);
240 fprintf(stderr
, "getaddrinfo failed on listen host/address: %s (%s)\n", s
->listenaddr
? s
->listenaddr
: "any", gai_strerror(e
));
250 uint64_t size_autodetect(int fhandle
) {
252 u64 bytes
__attribute__((unused
));
253 struct stat stat_buf
;
256 #ifdef HAVE_SYS_MOUNT_H
257 #ifdef HAVE_SYS_IOCTL_H
259 DEBUG("looking for export size with ioctl BLKGETSIZE64\n");
260 if (!ioctl(fhandle
, BLKGETSIZE64
, &bytes
) && bytes
) {
263 #endif /* BLKGETSIZE64 */
264 #endif /* HAVE_SYS_IOCTL_H */
265 #endif /* HAVE_SYS_MOUNT_H */
267 DEBUG("looking for fhandle size with fstat\n");
268 stat_buf
.st_size
= 0;
269 error
= fstat(fhandle
, &stat_buf
);
271 /* always believe stat if a regular file as it might really
273 if (S_ISREG(stat_buf
.st_mode
) || (stat_buf
.st_size
> 0))
274 return (uint64_t)stat_buf
.st_size
;
276 DEBUG("fstat failed: %s", strerror(errno
));
279 DEBUG("looking for fhandle size with lseek SEEK_END\n");
280 es
= lseek(fhandle
, (off_t
)0, SEEK_END
);
281 if (es
> ((off_t
)0)) {
284 DEBUG("lseek failed: %d", errno
==EBADF
?1:(errno
==ESPIPE
?2:(errno
==EINVAL
?3:4)));
287 DEBUG("Could not find size of exported block device: %s", strerror(errno
));