Lines 43-49
Link Here
|
43 |
#include <sys/bio.h> |
43 |
#include <sys/bio.h> |
44 |
#include <netinet/in.h> |
44 |
#include <netinet/in.h> |
45 |
#include <netinet/tcp.h> |
45 |
#include <netinet/tcp.h> |
|
|
46 |
#include <netinet/sctp.h> |
46 |
#include <arpa/inet.h> |
47 |
#include <arpa/inet.h> |
|
|
48 |
#include <netdb.h> |
47 |
#include <signal.h> |
49 |
#include <signal.h> |
48 |
#include <assert.h> |
50 |
#include <assert.h> |
49 |
#include <err.h> |
51 |
#include <err.h> |
Lines 68-74
Link Here
|
68 |
time_t c_birthtime; |
70 |
time_t c_birthtime; |
69 |
char *c_path; |
71 |
char *c_path; |
70 |
uint64_t c_token; |
72 |
uint64_t c_token; |
71 |
in_addr_t c_srcip; |
73 |
struct sockaddr_storage c_srcaddr; |
|
|
74 |
uint64_t c_send_seq; |
75 |
uint64_t c_recv_seq; |
72 |
LIST_ENTRY(ggd_connection) c_next; |
76 |
LIST_ENTRY(ggd_connection) c_next; |
73 |
}; |
77 |
}; |
74 |
|
78 |
|
Lines 80-98
Link Here
|
80 |
#define r_cmd r_hdr.gh_cmd |
84 |
#define r_cmd r_hdr.gh_cmd |
81 |
#define r_offset r_hdr.gh_offset |
85 |
#define r_offset r_hdr.gh_offset |
82 |
#define r_length r_hdr.gh_length |
86 |
#define r_length r_hdr.gh_length |
|
|
87 |
#define r_seq r_hdr.gh_seq |
83 |
#define r_error r_hdr.gh_error |
88 |
#define r_error r_hdr.gh_error |
84 |
|
89 |
|
85 |
struct ggd_export { |
90 |
struct ggd_export { |
86 |
char *e_path; /* path to device/file */ |
91 |
char *e_path; /* path to device/file */ |
87 |
in_addr_t e_ip; /* remote IP address */ |
92 |
struct sockaddr_storage e_addr; /* remote IP address */ |
88 |
in_addr_t e_mask; /* IP mask */ |
93 |
struct sockaddr_storage e_mask; /* IP mask */ |
89 |
unsigned e_flags; /* flags (RO/RW) */ |
94 |
unsigned e_flags; /* flags (RO/RW) */ |
90 |
SLIST_ENTRY(ggd_export) e_next; |
95 |
SLIST_ENTRY(ggd_export) e_next; |
|
|
96 |
}; |
97 |
|
98 |
struct ggd_listen { |
99 |
const char *l_name; /* host name / address */ |
100 |
struct sockaddr_storage l_addr; /* bind address & port */ |
101 |
int l_fd; /* socket */ |
102 |
SLIST_ENTRY(ggd_listen) l_next; |
91 |
}; |
103 |
}; |
92 |
|
104 |
|
93 |
static const char *exports_file = GGATED_EXPORT_FILE; |
105 |
static const char *exports_file = GGATED_EXPORT_FILE; |
94 |
static int got_sighup = 0; |
106 |
static int got_sighup = 0; |
95 |
in_addr_t bindaddr; |
107 |
static int ai_protocol = 0; |
|
|
108 |
struct addrinfo hints; |
96 |
|
109 |
|
97 |
static TAILQ_HEAD(, ggd_request) inqueue = TAILQ_HEAD_INITIALIZER(inqueue); |
110 |
static TAILQ_HEAD(, ggd_request) inqueue = TAILQ_HEAD_INITIALIZER(inqueue); |
98 |
static TAILQ_HEAD(, ggd_request) outqueue = TAILQ_HEAD_INITIALIZER(outqueue); |
111 |
static TAILQ_HEAD(, ggd_request) outqueue = TAILQ_HEAD_INITIALIZER(outqueue); |
Lines 110-185
Link Here
|
110 |
usage(void) |
123 |
usage(void) |
111 |
{ |
124 |
{ |
112 |
|
125 |
|
113 |
fprintf(stderr, "usage: %s [-nv] [-a address] [-p port] [-R rcvbuf] " |
126 |
fprintf(stderr, "usage: %s [-fnv] [-a address] [-p port] [-R rcvbuf] " |
114 |
"[-S sndbuf] [exports file]\n", getprogname()); |
127 |
"[-S sndbuf] [exports file]\n", getprogname()); |
115 |
exit(EXIT_FAILURE); |
128 |
exit(EXIT_FAILURE); |
116 |
} |
129 |
} |
117 |
|
130 |
|
118 |
static char * |
131 |
static void |
119 |
ip2str(in_addr_t ip) |
132 |
summary(void) |
|
|
133 |
{ |
134 |
struct ggd_connection *conn, *tconn; |
135 |
|
136 |
char buf[1024]; |
137 |
|
138 |
/* Use snprintf(3) so that we don't reenter stdio(3). */ |
139 |
LIST_FOREACH_SAFE(conn, &connections, c_next, tconn) { |
140 |
snprintf(buf, sizeof(buf), |
141 |
"path %s\n" |
142 |
"send_seq %llu\n" |
143 |
"recv_seq %llu\n" |
144 |
"", |
145 |
conn->c_path, |
146 |
conn->c_send_seq, conn->c_recv_seq); |
147 |
write(STDERR_FILENO, buf, strlen(buf)); |
148 |
} |
149 |
} |
150 |
|
151 |
static void |
152 |
summaryx(int notused __unused) |
120 |
{ |
153 |
{ |
121 |
static char sip[16]; |
154 |
int save_errno = errno; |
122 |
|
155 |
|
123 |
snprintf(sip, sizeof(sip), "%u.%u.%u.%u", |
156 |
summary(); |
124 |
((ip >> 24) & 0xff), |
157 |
errno = save_errno; |
125 |
((ip >> 16) & 0xff), |
|
|
126 |
((ip >> 8) & 0xff), |
127 |
(ip & 0xff)); |
128 |
return (sip); |
129 |
} |
158 |
} |
130 |
|
159 |
|
131 |
static in_addr_t |
160 |
static const char * |
132 |
countmask(unsigned m) |
161 |
ip2str(struct sockaddr *addr) |
133 |
{ |
162 |
{ |
134 |
in_addr_t mask; |
163 |
static char sip[64]; |
135 |
|
164 |
|
136 |
if (m == 0) { |
165 |
if (getnameinfo(addr, addr->sa_len, sip, sizeof(sip), |
137 |
mask = 0x0; |
166 |
NULL, 0, NI_NUMERICHOST) == 0) |
138 |
} else { |
167 |
return (sip); |
139 |
mask = 1 << (32 - m); |
168 |
|
140 |
mask--; |
169 |
return ("Unknown"); |
141 |
mask = ~mask; |
170 |
} |
|
|
171 |
|
172 |
static struct sockaddr_storage |
173 |
countmask(struct sockaddr* addr, int mask) /* also normalizes addr */ |
174 |
{ |
175 |
struct sockaddr_storage ss; |
176 |
int i, alen; |
177 |
unsigned char *mp, *ap; |
178 |
|
179 |
bzero(&ss, sizeof(ss)); |
180 |
ss.ss_family = addr->sa_family; |
181 |
ss.ss_len = addr->sa_len; |
182 |
|
183 |
switch (addr->sa_family) { |
184 |
case AF_INET: |
185 |
alen = 4; /* 32 bits */ |
186 |
ap = (unsigned char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr; |
187 |
mp = (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr; |
188 |
break; |
189 |
case AF_INET6: |
190 |
alen = 16; /* 128 bits */ |
191 |
ap = (unsigned char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr; |
192 |
mp = (unsigned char*)&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr; |
193 |
break; |
194 |
default: |
195 |
g_gate_xlog("Unknown address family in countmask"); |
196 |
return ss; |
197 |
} |
198 |
|
199 |
i = 0; |
200 |
while (mask > 0 && i < alen) { |
201 |
if (mask < 8) { |
202 |
mp[i] = ~(0xff >> mask); |
203 |
ap[i] &= mp[i]; |
204 |
} else |
205 |
mp[i] = 0xff; |
206 |
i++; |
207 |
mask -= 8; |
208 |
} |
209 |
while (i < alen) { /* zero out remaining bits of addr */ |
210 |
ap[i] = 0; |
211 |
i++; |
142 |
} |
212 |
} |
143 |
return (mask); |
213 |
|
|
|
214 |
return (ss); |
144 |
} |
215 |
} |
145 |
|
216 |
|
146 |
static void |
217 |
static void |
147 |
line_parse(char *line, unsigned lineno) |
218 |
line_parse(char *line, unsigned lineno) |
148 |
{ |
219 |
{ |
149 |
struct ggd_export *ex; |
220 |
struct ggd_export *ex; |
150 |
char *word, *path, *sflags; |
221 |
char *pmask, *word, *path, *sflags; |
151 |
unsigned flags, i, vmask; |
222 |
unsigned flags, i; |
152 |
in_addr_t ip, mask; |
223 |
int vmask; |
|
|
224 |
struct addrinfo *res, *p; |
153 |
|
225 |
|
154 |
ip = mask = flags = vmask = 0; |
226 |
flags = vmask = 0; |
155 |
path = NULL; |
227 |
path = NULL; |
156 |
sflags = NULL; |
228 |
sflags = NULL; |
|
|
229 |
pmask = NULL; |
157 |
|
230 |
|
158 |
for (i = 0, word = strtok(line, " \t"); word != NULL; |
231 |
for (i = 0, word = strtok(line, " \t"); word != NULL; |
159 |
i++, word = strtok(NULL, " \t")) { |
232 |
i++, word = strtok(NULL, " \t")) { |
160 |
switch (i) { |
233 |
switch (i) { |
161 |
case 0: /* IP address or host name */ |
234 |
case 0: /* IP address or host name */ |
162 |
ip = g_gate_str2ip(strsep(&word, "/")); |
235 |
// bzero(&hints, sizeof(hints)); |
163 |
if (ip == INADDR_NONE) { |
236 |
// hints.ai_family = PF_UNSPEC; |
|
|
237 |
// hints.ai_socktype = SOCKET_STREAM; |
238 |
if (getaddrinfo(strsep(&word, "/"), NULL, &hints, |
239 |
&res) != 0) |
164 |
g_gate_xlog("Invalid IP/host name at line %u.", |
240 |
g_gate_xlog("Invalid IP/host name at line %u.", |
165 |
lineno); |
241 |
lineno); |
166 |
} |
242 |
pmask = word; |
167 |
ip = ntohl(ip); |
|
|
168 |
if (word == NULL) |
169 |
vmask = 32; |
170 |
else { |
171 |
errno = 0; |
172 |
vmask = strtoul(word, NULL, 10); |
173 |
if (vmask == 0 && errno != 0) { |
174 |
g_gate_xlog("Invalid IP mask value at " |
175 |
"line %u.", lineno); |
176 |
} |
177 |
if ((unsigned)vmask > 32) { |
178 |
g_gate_xlog("Invalid IP mask value at line %u.", |
179 |
lineno); |
180 |
} |
181 |
} |
182 |
mask = countmask(vmask); |
183 |
break; |
243 |
break; |
184 |
case 1: /* flags */ |
244 |
case 1: /* flags */ |
185 |
if (strcasecmp("rd", word) == 0 || |
245 |
if (strcasecmp("rd", word) == 0 || |
Lines 209-230
Link Here
|
209 |
if (i != 3) |
269 |
if (i != 3) |
210 |
g_gate_xlog("Too few arguments at line %u.", lineno); |
270 |
g_gate_xlog("Too few arguments at line %u.", lineno); |
211 |
|
271 |
|
212 |
ex = malloc(sizeof(*ex)); |
272 |
p = res; |
213 |
if (ex == NULL) |
273 |
while (p) { |
214 |
g_gate_xlog("No enough memory."); |
274 |
ex = malloc(sizeof(*ex)); |
215 |
ex->e_path = strdup(path); |
275 |
if (ex == NULL) |
216 |
if (ex->e_path == NULL) |
276 |
g_gate_xlog("Not enough memory."); |
217 |
g_gate_xlog("No enough memory."); |
277 |
ex->e_path = strdup(path); |
218 |
|
278 |
if (ex->e_path == NULL) |
219 |
/* Made 'and' here. */ |
279 |
g_gate_xlog("Not enough memory."); |
220 |
ex->e_ip = (ip & mask); |
280 |
|
221 |
ex->e_mask = mask; |
281 |
if (pmask == NULL && p->ai_family == AF_INET6) |
222 |
ex->e_flags = flags; |
282 |
vmask = 128; |
|
|
283 |
else if (pmask == NULL) |
284 |
vmask = 32; |
285 |
else { |
286 |
errno = 0; |
287 |
vmask = strtoul(pmask, NULL, 10); |
288 |
if (vmask == 0 && errno != 0) { |
289 |
g_gate_xlog("Invalid IP mask value at " |
290 |
"line %u.", lineno); |
291 |
} |
292 |
} |
293 |
|
294 |
if ((vmask > 32 && p->ai_family == AF_INET) || |
295 |
(vmask > 128 && p->ai_family == AF_INET6)) |
296 |
g_gate_xlog("Invalid IP mask value at line %u", |
297 |
lineno); |
298 |
|
299 |
memcpy(&ex->e_addr, p->ai_addr, p->ai_addrlen); |
300 |
ex->e_mask = countmask((struct sockaddr*)&ex->e_addr, vmask); |
301 |
ex->e_flags = flags; |
223 |
|
302 |
|
224 |
SLIST_INSERT_HEAD(&exports, ex, e_next); |
303 |
SLIST_INSERT_HEAD(&exports, ex, e_next); |
|
|
304 |
|
305 |
g_gate_log(LOG_DEBUG, "Added %s/%u %s %s to exports list.", |
306 |
ip2str((struct sockaddr*)&ex->e_addr), vmask, path, sflags); |
307 |
|
308 |
p = p->ai_next; |
309 |
} |
225 |
|
310 |
|
226 |
g_gate_log(LOG_DEBUG, "Added %s/%u %s %s to exports list.", |
311 |
freeaddrinfo(res); |
227 |
ip2str(ex->e_ip), vmask, path, sflags); |
|
|
228 |
} |
312 |
} |
229 |
|
313 |
|
230 |
static void |
314 |
static void |
Lines 302-313
Link Here
|
302 |
exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit, |
386 |
exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit, |
303 |
struct ggd_connection *conn) |
387 |
struct ggd_connection *conn) |
304 |
{ |
388 |
{ |
305 |
char ipmask[32]; /* 32 == strlen("xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx")+1 */ |
389 |
char ipmask[80]; /* 80 == strlen("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")+1 */ |
306 |
int error = 0, flags; |
390 |
int error = 0, flags; |
307 |
|
391 |
|
308 |
strlcpy(ipmask, ip2str(ex->e_ip), sizeof(ipmask)); |
392 |
strlcpy(ipmask, ip2str((struct sockaddr*)&ex->e_addr), sizeof(ipmask)); |
309 |
strlcat(ipmask, "/", sizeof(ipmask)); |
393 |
strlcat(ipmask, "/", sizeof(ipmask)); |
310 |
strlcat(ipmask, ip2str(ex->e_mask), sizeof(ipmask)); |
394 |
strlcat(ipmask, ip2str((struct sockaddr*)&ex->e_mask), sizeof(ipmask)); |
311 |
if ((cinit->gc_flags & GGATE_FLAG_RDONLY) != 0) { |
395 |
if ((cinit->gc_flags & GGATE_FLAG_RDONLY) != 0) { |
312 |
if (ex->e_flags == O_WRONLY) { |
396 |
if (ex->e_flags == O_WRONLY) { |
313 |
g_gate_log(LOG_WARNING, "Read-only access requested, " |
397 |
g_gate_log(LOG_WARNING, "Read-only access requested, " |
Lines 355-371
Link Here
|
355 |
return (0); |
439 |
return (0); |
356 |
} |
440 |
} |
357 |
|
441 |
|
|
|
442 |
static int |
443 |
mask_compare(struct sockaddr *a, struct sockaddr *b, struct sockaddr *m) { |
444 |
unsigned char *ap, *bp, *mp; |
445 |
int alen; |
446 |
if (a->sa_family != m->sa_family || b->sa_family != m->sa_family) |
447 |
return (0); |
448 |
|
449 |
switch (m->sa_family) { |
450 |
case AF_INET: |
451 |
alen = 4; |
452 |
ap = (unsigned char*)&((struct sockaddr_in*)a)->sin_addr.s_addr; |
453 |
bp = (unsigned char*)&((struct sockaddr_in*)b)->sin_addr.s_addr; |
454 |
mp = (unsigned char*)&((struct sockaddr_in*)m)->sin_addr.s_addr; |
455 |
break; |
456 |
case AF_INET6: |
457 |
alen = 16; |
458 |
ap = (unsigned char*)&((struct sockaddr_in6*)a)->sin6_addr.s6_addr; |
459 |
bp = (unsigned char*)&((struct sockaddr_in6*)b)->sin6_addr.s6_addr; |
460 |
mp = (unsigned char*)&((struct sockaddr_in6*)m)->sin6_addr.s6_addr; |
461 |
break; |
462 |
default: |
463 |
return (0); |
464 |
} |
465 |
|
466 |
while (alen > 0) { |
467 |
if ((*ap & *mp) != (*bp & *mp)) |
468 |
return (0); |
469 |
|
470 |
ap++; |
471 |
bp++; |
472 |
mp++; |
473 |
alen--; |
474 |
} |
475 |
|
476 |
return (1); |
477 |
} |
478 |
|
358 |
static struct ggd_export * |
479 |
static struct ggd_export * |
359 |
exports_find(struct sockaddr *s, struct g_gate_cinit *cinit, |
480 |
exports_find(struct sockaddr *s, struct g_gate_cinit *cinit, |
360 |
struct ggd_connection *conn) |
481 |
struct ggd_connection *conn) |
361 |
{ |
482 |
{ |
362 |
struct ggd_export *ex; |
483 |
struct ggd_export *ex; |
363 |
in_addr_t ip; |
|
|
364 |
int error; |
484 |
int error; |
365 |
|
485 |
|
366 |
ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); |
|
|
367 |
SLIST_FOREACH(ex, &exports, e_next) { |
486 |
SLIST_FOREACH(ex, &exports, e_next) { |
368 |
if ((ip & ex->e_mask) != ex->e_ip) { |
487 |
if (!mask_compare(s, (struct sockaddr*)&ex->e_addr, |
|
|
488 |
(struct sockaddr*)&ex->e_mask)) { |
369 |
g_gate_log(LOG_DEBUG, "exports[%s]: IP mismatch.", |
489 |
g_gate_log(LOG_DEBUG, "exports[%s]: IP mismatch.", |
370 |
ex->e_path); |
490 |
ex->e_path); |
371 |
continue; |
491 |
continue; |
Lines 384-390
Link Here
|
384 |
} |
504 |
} |
385 |
} |
505 |
} |
386 |
g_gate_log(LOG_WARNING, "Unauthorized connection from: %s.", |
506 |
g_gate_log(LOG_WARNING, "Unauthorized connection from: %s.", |
387 |
ip2str(ip)); |
507 |
ip2str(s)); |
388 |
errno = EPERM; |
508 |
errno = EPERM; |
389 |
return (NULL); |
509 |
return (NULL); |
390 |
} |
510 |
} |
Lines 404-410
Link Here
|
404 |
LIST_REMOVE(conn, c_next); |
524 |
LIST_REMOVE(conn, c_next); |
405 |
g_gate_log(LOG_NOTICE, |
525 |
g_gate_log(LOG_NOTICE, |
406 |
"Connection from %s [%s] removed.", |
526 |
"Connection from %s [%s] removed.", |
407 |
ip2str(conn->c_srcip), conn->c_path); |
527 |
ip2str((struct sockaddr*)&conn->c_srcaddr), |
|
|
528 |
conn->c_path); |
408 |
close(conn->c_diskfd); |
529 |
close(conn->c_diskfd); |
409 |
close(conn->c_sendfd); |
530 |
close(conn->c_sendfd); |
410 |
close(conn->c_recvfd); |
531 |
close(conn->c_recvfd); |
Lines 430-436
Link Here
|
430 |
connection_new(struct g_gate_cinit *cinit, struct sockaddr *s, int sfd) |
551 |
connection_new(struct g_gate_cinit *cinit, struct sockaddr *s, int sfd) |
431 |
{ |
552 |
{ |
432 |
struct ggd_connection *conn; |
553 |
struct ggd_connection *conn; |
433 |
in_addr_t ip; |
|
|
434 |
|
554 |
|
435 |
/* |
555 |
/* |
436 |
* First, look for old connections. |
556 |
* First, look for old connections. |
Lines 449-456
Link Here
|
449 |
return (NULL); |
569 |
return (NULL); |
450 |
} |
570 |
} |
451 |
conn->c_token = cinit->gc_token; |
571 |
conn->c_token = cinit->gc_token; |
452 |
ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); |
572 |
memcpy(&conn->c_srcaddr, s, s->sa_len); |
453 |
conn->c_srcip = ip; |
|
|
454 |
conn->c_sendfd = conn->c_recvfd = -1; |
573 |
conn->c_sendfd = conn->c_recvfd = -1; |
455 |
if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) |
574 |
if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) |
456 |
conn->c_sendfd = sfd; |
575 |
conn->c_sendfd = sfd; |
Lines 461-467
Link Here
|
461 |
time(&conn->c_birthtime); |
580 |
time(&conn->c_birthtime); |
462 |
conn->c_flags = cinit->gc_flags; |
581 |
conn->c_flags = cinit->gc_flags; |
463 |
LIST_INSERT_HEAD(&connections, conn, c_next); |
582 |
LIST_INSERT_HEAD(&connections, conn, c_next); |
464 |
g_gate_log(LOG_DEBUG, "Connection created [%s, %s].", ip2str(ip), |
583 |
g_gate_log(LOG_DEBUG, "Connection created [%s, %s].", ip2str(s), |
465 |
conn->c_path); |
584 |
conn->c_path); |
466 |
return (conn); |
585 |
return (conn); |
467 |
} |
586 |
} |
Lines 470-482
Link Here
|
470 |
connection_add(struct ggd_connection *conn, struct g_gate_cinit *cinit, |
589 |
connection_add(struct ggd_connection *conn, struct g_gate_cinit *cinit, |
471 |
struct sockaddr *s, int sfd) |
590 |
struct sockaddr *s, int sfd) |
472 |
{ |
591 |
{ |
473 |
in_addr_t ip; |
|
|
474 |
|
475 |
ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); |
476 |
if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) { |
592 |
if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) { |
477 |
if (conn->c_sendfd != -1) { |
593 |
if (conn->c_sendfd != -1) { |
478 |
g_gate_log(LOG_WARNING, |
594 |
g_gate_log(LOG_WARNING, |
479 |
"Send socket already exists [%s, %s].", ip2str(ip), |
595 |
"Send socket already exists [%s, %s].", ip2str(s), |
480 |
conn->c_path); |
596 |
conn->c_path); |
481 |
return (EEXIST); |
597 |
return (EEXIST); |
482 |
} |
598 |
} |
Lines 485-496
Link Here
|
485 |
if (conn->c_recvfd != -1) { |
601 |
if (conn->c_recvfd != -1) { |
486 |
g_gate_log(LOG_WARNING, |
602 |
g_gate_log(LOG_WARNING, |
487 |
"Receive socket already exists [%s, %s].", |
603 |
"Receive socket already exists [%s, %s].", |
488 |
ip2str(ip), conn->c_path); |
604 |
ip2str(s), conn->c_path); |
489 |
return (EEXIST); |
605 |
return (EEXIST); |
490 |
} |
606 |
} |
491 |
conn->c_recvfd = sfd; |
607 |
conn->c_recvfd = sfd; |
492 |
} |
608 |
} |
493 |
g_gate_log(LOG_DEBUG, "Connection added [%s, %s].", ip2str(ip), |
609 |
g_gate_log(LOG_DEBUG, "Connection added [%s, %s].", ip2str(s), |
494 |
conn->c_path); |
610 |
conn->c_path); |
495 |
return (0); |
611 |
return (0); |
496 |
} |
612 |
} |
Lines 505-515
Link Here
|
505 |
|
621 |
|
506 |
LIST_REMOVE(conn, c_next); |
622 |
LIST_REMOVE(conn, c_next); |
507 |
g_gate_log(LOG_DEBUG, "Connection removed [%s %s].", |
623 |
g_gate_log(LOG_DEBUG, "Connection removed [%s %s].", |
508 |
ip2str(conn->c_srcip), conn->c_path); |
624 |
ip2str((struct sockaddr*)&conn->c_srcaddr), conn->c_path); |
509 |
if (conn->c_sendfd != -1) |
625 |
if (conn->c_sendfd != -1) |
510 |
close(conn->c_sendfd); |
626 |
close(conn->c_sendfd); |
511 |
if (conn->c_recvfd != -1) |
627 |
if (conn->c_recvfd != -1) |
512 |
close(conn->c_recvfd); |
628 |
close(conn->c_recvfd); |
|
|
629 |
close(conn->c_diskfd); |
513 |
free(conn->c_path); |
630 |
free(conn->c_path); |
514 |
free(conn); |
631 |
free(conn); |
515 |
} |
632 |
} |
Lines 642-652
Link Here
|
642 |
} else if (data != sizeof(req->r_hdr)) { |
759 |
} else if (data != sizeof(req->r_hdr)) { |
643 |
g_gate_xlog("Malformed hdr packet received."); |
760 |
g_gate_xlog("Malformed hdr packet received."); |
644 |
} |
761 |
} |
645 |
g_gate_log(LOG_DEBUG, "Received hdr packet."); |
|
|
646 |
g_gate_swap2h_hdr(&req->r_hdr); |
762 |
g_gate_swap2h_hdr(&req->r_hdr); |
|
|
763 |
g_gate_log(LOG_DEBUG, "Received hdr packet (seq=%llu).", req->r_seq); |
764 |
conn->c_recv_seq = req->r_seq; |
647 |
|
765 |
|
648 |
g_gate_log(LOG_DEBUG, "%s: offset=%jd length=%u", __func__, |
766 |
g_gate_log(LOG_DEBUG, "%s: (offset=%jd length=%u", __func__, |
649 |
(intmax_t)req->r_offset, (unsigned)req->r_length); |
767 |
req->r_seq, (intmax_t)req->r_offset, (unsigned)req->r_length); |
650 |
|
768 |
|
651 |
/* |
769 |
/* |
652 |
* Allocate memory for data. |
770 |
* Allocate memory for data. |
Lines 657-664
Link Here
|
657 |
* Receive data to write for WRITE request. |
775 |
* Receive data to write for WRITE request. |
658 |
*/ |
776 |
*/ |
659 |
if (req->r_cmd == GGATE_CMD_WRITE) { |
777 |
if (req->r_cmd == GGATE_CMD_WRITE) { |
660 |
g_gate_log(LOG_DEBUG, "Waiting for %u bytes of data...", |
778 |
g_gate_log(LOG_DEBUG, "Waiting for %u bytes of data (seq=%llu).", |
661 |
req->r_length); |
779 |
req->r_length, req->r_seq); |
662 |
data = g_gate_recv(fd, req->r_data, req->r_length, |
780 |
data = g_gate_recv(fd, req->r_data, req->r_length, |
663 |
MSG_WAITALL); |
781 |
MSG_WAITALL); |
664 |
if (data == -1) { |
782 |
if (data == -1) { |
Lines 795-802
Link Here
|
795 |
g_gate_xlog("Error while sending hdr packet: %s.", |
913 |
g_gate_xlog("Error while sending hdr packet: %s.", |
796 |
strerror(errno)); |
914 |
strerror(errno)); |
797 |
} |
915 |
} |
798 |
g_gate_log(LOG_DEBUG, "Sent hdr packet."); |
|
|
799 |
g_gate_swap2h_hdr(&req->r_hdr); |
916 |
g_gate_swap2h_hdr(&req->r_hdr); |
|
|
917 |
g_gate_log(LOG_DEBUG, "Sent hdr packet (seq=%llu).", req->r_hdr.gh_seq); |
918 |
conn->c_send_seq = req->r_seq; |
800 |
if (req->r_data != NULL) { |
919 |
if (req->r_data != NULL) { |
801 |
data = g_gate_send(fd, req->r_data, req->r_length, 0); |
920 |
data = g_gate_send(fd, req->r_data, req->r_length, 0); |
802 |
if (data != (ssize_t)req->r_length) { |
921 |
if (data != (ssize_t)req->r_length) { |
Lines 815-824
Link Here
|
815 |
static void |
934 |
static void |
816 |
log_connection(struct sockaddr *from) |
935 |
log_connection(struct sockaddr *from) |
817 |
{ |
936 |
{ |
818 |
in_addr_t ip; |
937 |
g_gate_log(LOG_INFO, "Connection from: %s.", ip2str(from)); |
819 |
|
|
|
820 |
ip = htonl(((struct sockaddr_in *)(void *)from)->sin_addr.s_addr); |
821 |
g_gate_log(LOG_INFO, "Connection from: %s.", ip2str(ip)); |
822 |
} |
938 |
} |
823 |
|
939 |
|
824 |
static int |
940 |
static int |
Lines 940-975
Link Here
|
940 |
int |
1056 |
int |
941 |
main(int argc, char *argv[]) |
1057 |
main(int argc, char *argv[]) |
942 |
{ |
1058 |
{ |
943 |
struct sockaddr_in serv; |
1059 |
SLIST_HEAD(, ggd_listen) listens = SLIST_HEAD_INITIALIZER(&listens); |
944 |
struct sockaddr from; |
1060 |
struct ggd_listen *cl, *nl; |
|
|
1061 |
struct addrinfo *res, *p; |
1062 |
struct sockaddr_storage from; |
1063 |
struct protoent *pent; |
945 |
socklen_t fromlen; |
1064 |
socklen_t fromlen; |
946 |
int sfd, tmpsfd; |
1065 |
int maxfd, tmpsfd; |
947 |
unsigned port; |
1066 |
fd_set listenfds; |
|
|
1067 |
const char *port; |
1068 |
int foreground = 0; |
1069 |
|
1070 |
bzero(&hints, sizeof(hints)); |
1071 |
hints.ai_family = PF_UNSPEC; /* Bind to all address families */ |
1072 |
hints.ai_flags = AI_PASSIVE; |
1073 |
hints.ai_socktype = SOCK_STREAM; |
948 |
|
1074 |
|
949 |
bindaddr = htonl(INADDR_ANY); |
1075 |
port = G_GATE_PORT_STR; |
950 |
port = G_GATE_PORT; |
|
|
951 |
for (;;) { |
1076 |
for (;;) { |
952 |
int ch; |
1077 |
int ch; |
953 |
|
1078 |
|
954 |
ch = getopt(argc, argv, "a:hnp:R:S:v"); |
1079 |
ch = getopt(argc, argv, "a:fhnp:R:S:vF:P:"); |
955 |
if (ch == -1) |
1080 |
if (ch == -1) |
956 |
break; |
1081 |
break; |
957 |
switch (ch) { |
1082 |
switch (ch) { |
958 |
case 'a': |
1083 |
case 'a': |
959 |
bindaddr = g_gate_str2ip(optarg); |
1084 |
nl = malloc(sizeof(*nl)); |
960 |
if (bindaddr == INADDR_NONE) { |
1085 |
bzero(nl, sizeof(*nl)); |
|
|
1086 |
nl->l_name = optarg; |
1087 |
/* delay resolution until we know port number */ |
1088 |
SLIST_INSERT_HEAD(&listens, nl, l_next); |
1089 |
break; |
1090 |
case 'n': |
1091 |
nagle = 0; |
1092 |
break; |
1093 |
case 'F': |
1094 |
switch (*optarg) { |
1095 |
case '4': |
1096 |
hints.ai_family = PF_INET; |
1097 |
break; |
1098 |
case '6': |
1099 |
hints.ai_family = PF_INET6; |
1100 |
break; |
1101 |
case '0': |
1102 |
hints.ai_family = PF_UNSPEC; |
1103 |
break; |
1104 |
default: |
1105 |
usage(); |
1106 |
} |
1107 |
break; |
1108 |
case 'P': |
1109 |
if (optarg && (pent = getprotobyname(optarg))) |
1110 |
ai_protocol = pent->p_proto; |
1111 |
else { |
1112 |
ai_protocol = 0; |
1113 |
/* |
961 |
errx(EXIT_FAILURE, |
1114 |
errx(EXIT_FAILURE, |
962 |
"Invalid IP/host name to bind to."); |
1115 |
"protocol %s does not exist.", optarg); |
|
|
1116 |
*/ |
963 |
} |
1117 |
} |
964 |
break; |
1118 |
break; |
965 |
case 'n': |
1119 |
case '4': |
|
|
1120 |
hints.ai_family = PF_INET; |
1121 |
break; |
1122 |
case '6': |
1123 |
hints.ai_family = PF_INET6; |
1124 |
break; |
1125 |
case 'x': |
1126 |
/* "man netstat" shows AF_INET has sctp. */ |
1127 |
hints.ai_family = PF_INET; |
1128 |
hints.ai_family = PF_INET6; /* test... */ |
1129 |
/* hints.ai_protocol = IPPROTO_SCTP; */ |
1130 |
ai_protocol = IPPROTO_SCTP; |
966 |
nagle = 0; |
1131 |
nagle = 0; |
967 |
break; |
1132 |
break; |
968 |
case 'p': |
1133 |
case 'p': |
969 |
errno = 0; |
1134 |
port = optarg; |
970 |
port = strtoul(optarg, NULL, 10); |
|
|
971 |
if (port == 0 && errno != 0) |
972 |
errx(EXIT_FAILURE, "Invalid port."); |
973 |
break; |
1135 |
break; |
974 |
case 'R': |
1136 |
case 'R': |
975 |
errno = 0; |
1137 |
errno = 0; |
Lines 983-990
Link Here
|
983 |
if (sndbuf == 0 && errno != 0) |
1145 |
if (sndbuf == 0 && errno != 0) |
984 |
errx(EXIT_FAILURE, "Invalid sndbuf."); |
1146 |
errx(EXIT_FAILURE, "Invalid sndbuf."); |
985 |
break; |
1147 |
break; |
|
|
1148 |
case 'f': |
1149 |
foreground = 1; |
1150 |
break; |
986 |
case 'v': |
1151 |
case 'v': |
987 |
g_gate_verbose++; |
1152 |
g_gate_verbose++; |
|
|
1153 |
foreground = 1; |
988 |
break; |
1154 |
break; |
989 |
case 'h': |
1155 |
case 'h': |
990 |
default: |
1156 |
default: |
Lines 998-1044
Link Here
|
998 |
exports_file = argv[0]; |
1164 |
exports_file = argv[0]; |
999 |
exports_get(); |
1165 |
exports_get(); |
1000 |
|
1166 |
|
1001 |
if (!g_gate_verbose) { |
1167 |
if (SLIST_EMPTY(&listens)) { |
|
|
1168 |
if (getaddrinfo(NULL, port, &hints, &res)) |
1169 |
g_gate_xlog("Cannot get passive address: %s", |
1170 |
strerror(errno)); |
1171 |
|
1172 |
p = res; |
1173 |
while (p) { |
1174 |
nl = malloc(sizeof(*nl)); |
1175 |
bzero(nl, sizeof(*nl)); |
1176 |
memcpy(&nl->l_addr, p->ai_addr, p->ai_addrlen); |
1177 |
SLIST_INSERT_HEAD(&listens, nl, l_next); |
1178 |
|
1179 |
p = p->ai_next; |
1180 |
} |
1181 |
freeaddrinfo(res); |
1182 |
} else { |
1183 |
/* Bind to some specific addresses */ |
1184 |
SLIST_FOREACH(cl, &listens, l_next) { |
1185 |
if (getaddrinfo(cl->l_name, port, &hints, &res)) |
1186 |
g_gate_xlog("Invalid IP/host name to bind to: " |
1187 |
"%s", cl->l_name); |
1188 |
|
1189 |
/* Re-use current list entry for first match, add |
1190 |
* new ones after that */ |
1191 |
p = res; |
1192 |
nl = cl; |
1193 |
while (p) { |
1194 |
if (p != res) { |
1195 |
nl = malloc(sizeof(*nl)); |
1196 |
bzero(nl, sizeof(*nl)); |
1197 |
} |
1198 |
|
1199 |
memcpy(&nl->l_addr, p->ai_addr, p->ai_addrlen); |
1200 |
|
1201 |
if (p != res) { |
1202 |
SLIST_INSERT_HEAD(&listens, nl, l_next); |
1203 |
} |
1204 |
p = p->ai_next; |
1205 |
} |
1206 |
freeaddrinfo(res); |
1207 |
} |
1208 |
} |
1209 |
|
1210 |
/* Actually create sockets and bind to them */ |
1211 |
maxfd = 0; |
1212 |
SLIST_FOREACH(cl, &listens, l_next) { |
1213 |
cl->l_fd = socket(cl->l_addr.ss_family, |
1214 |
hints.ai_socktype, ai_protocol); |
1215 |
if (cl->l_fd == -1) |
1216 |
g_gate_xlog("Cannot open stream socket: %s.", |
1217 |
strerror(errno)); |
1218 |
g_gate_socket_settings(cl->l_fd); |
1219 |
|
1220 |
if (bind(cl->l_fd, (struct sockaddr *)&cl->l_addr, |
1221 |
cl->l_addr.ss_len) == -1) { |
1222 |
g_gate_log(LOG_WARNING, "bind(): %s.", strerror(errno)); |
1223 |
continue; |
1224 |
} |
1225 |
if (listen(cl->l_fd, 5) == -1) |
1226 |
g_gate_xlog("listen(): %s.", strerror(errno)); |
1227 |
|
1228 |
if (maxfd <= cl->l_fd) |
1229 |
maxfd = cl->l_fd + 1; |
1230 |
|
1231 |
g_gate_log(LOG_INFO, "Listen on address: %s (%s).", |
1232 |
ip2str((struct sockaddr *)&cl->l_addr), port); |
1233 |
} |
1234 |
|
1235 |
signal(SIGINFO, summaryx); |
1236 |
if (!foreground) { |
1002 |
/* Run in daemon mode. */ |
1237 |
/* Run in daemon mode. */ |
1003 |
if (daemon(0, 0) == -1) |
1238 |
if (daemon(0, 0) == -1) |
1004 |
g_gate_xlog("Cannot daemonize: %s", strerror(errno)); |
1239 |
g_gate_xlog("Cannot daemonize: %s", strerror(errno)); |
1005 |
} |
1240 |
} |
1006 |
|
1241 |
|
1007 |
signal(SIGCHLD, SIG_IGN); |
1242 |
signal(SIGCHLD, SIG_IGN); |
1008 |
|
|
|
1009 |
sfd = socket(AF_INET, SOCK_STREAM, 0); |
1010 |
if (sfd == -1) |
1011 |
g_gate_xlog("Cannot open stream socket: %s.", strerror(errno)); |
1012 |
bzero(&serv, sizeof(serv)); |
1013 |
serv.sin_family = AF_INET; |
1014 |
serv.sin_addr.s_addr = bindaddr; |
1015 |
serv.sin_port = htons(port); |
1016 |
|
1017 |
g_gate_socket_settings(sfd); |
1018 |
|
1019 |
if (bind(sfd, (struct sockaddr *)&serv, sizeof(serv)) == -1) |
1020 |
g_gate_xlog("bind(): %s.", strerror(errno)); |
1021 |
if (listen(sfd, 5) == -1) |
1022 |
g_gate_xlog("listen(): %s.", strerror(errno)); |
1023 |
|
1024 |
g_gate_log(LOG_INFO, "Listen on port: %d.", port); |
1025 |
|
1026 |
signal(SIGHUP, huphandler); |
1243 |
signal(SIGHUP, huphandler); |
1027 |
|
1244 |
|
1028 |
for (;;) { |
1245 |
for (;;) { |
1029 |
fromlen = sizeof(from); |
1246 |
FD_ZERO(&listenfds); |
1030 |
tmpsfd = accept(sfd, &from, &fromlen); |
1247 |
SLIST_FOREACH(cl, &listens, l_next) { |
1031 |
if (tmpsfd == -1) |
1248 |
FD_SET(cl->l_fd, &listenfds); |
1032 |
g_gate_xlog("accept(): %s.", strerror(errno)); |
1249 |
} |
|
|
1250 |
|
1251 |
select(maxfd, &listenfds, NULL, NULL, NULL); |
1033 |
|
1252 |
|
1034 |
if (got_sighup) { |
1253 |
if (got_sighup) { |
1035 |
got_sighup = 0; |
1254 |
got_sighup = 0; |
1036 |
exports_get(); |
1255 |
exports_get(); |
1037 |
} |
1256 |
} |
1038 |
|
1257 |
|
1039 |
if (!handshake(&from, tmpsfd)) |
1258 |
SLIST_FOREACH(cl, &listens, l_next) { |
1040 |
close(tmpsfd); |
1259 |
if (!FD_ISSET(cl->l_fd, &listenfds)) |
|
|
1260 |
continue; |
1261 |
|
1262 |
fromlen = sizeof(from); |
1263 |
tmpsfd = accept(cl->l_fd, (struct sockaddr*)&from, |
1264 |
&fromlen); |
1265 |
|
1266 |
if (tmpsfd == -1) { |
1267 |
g_gate_log(LOG_WARNING, "accept(): %s.", |
1268 |
strerror(errno)); |
1269 |
continue; |
1270 |
} |
1271 |
|
1272 |
if (!handshake((struct sockaddr*)&from, tmpsfd)) |
1273 |
close(tmpsfd); |
1274 |
} |
1275 |
} |
1276 |
while (!SLIST_EMPTY(&listens)) { |
1277 |
cl = SLIST_FIRST(&listens); |
1278 |
close(cl->l_fd); |
1279 |
SLIST_REMOVE_HEAD(&listens, l_next); |
1280 |
free(cl); |
1041 |
} |
1281 |
} |
1042 |
close(sfd); |
|
|
1043 |
exit(EXIT_SUCCESS); |
1282 |
exit(EXIT_SUCCESS); |
1044 |
} |
1283 |
} |