Lines 44-49
Link Here
|
44 |
#include <netinet/in.h> |
44 |
#include <netinet/in.h> |
45 |
#include <netinet/tcp.h> |
45 |
#include <netinet/tcp.h> |
46 |
#include <arpa/inet.h> |
46 |
#include <arpa/inet.h> |
|
|
47 |
#include <netdb.h> |
47 |
#include <signal.h> |
48 |
#include <signal.h> |
48 |
#include <assert.h> |
49 |
#include <assert.h> |
49 |
#include <err.h> |
50 |
#include <err.h> |
Lines 68-74
Link Here
|
68 |
time_t c_birthtime; |
69 |
time_t c_birthtime; |
69 |
char *c_path; |
70 |
char *c_path; |
70 |
uint64_t c_token; |
71 |
uint64_t c_token; |
71 |
in_addr_t c_srcip; |
72 |
struct sockaddr_storage c_srcaddr; |
72 |
LIST_ENTRY(ggd_connection) c_next; |
73 |
LIST_ENTRY(ggd_connection) c_next; |
73 |
}; |
74 |
}; |
74 |
|
75 |
|
Lines 83-98
Link Here
|
83 |
#define r_error r_hdr.gh_error |
84 |
#define r_error r_hdr.gh_error |
84 |
|
85 |
|
85 |
struct ggd_export { |
86 |
struct ggd_export { |
86 |
char *e_path; /* path to device/file */ |
87 |
char *e_path; /* path to device/file */ |
87 |
in_addr_t e_ip; /* remote IP address */ |
88 |
struct sockaddr_storage e_addr; /* remote IP address */ |
88 |
in_addr_t e_mask; /* IP mask */ |
89 |
struct sockaddr_storage e_mask; /* IP mask */ |
89 |
unsigned e_flags; /* flags (RO/RW) */ |
90 |
unsigned e_flags; /* flags (RO/RW) */ |
90 |
SLIST_ENTRY(ggd_export) e_next; |
91 |
SLIST_ENTRY(ggd_export) e_next; |
|
|
92 |
}; |
93 |
|
94 |
struct ggd_listen { |
95 |
const char *l_name; /* host name / address */ |
96 |
struct sockaddr_storage l_addr; /* bind address & port */ |
97 |
int l_fd; /* socket */ |
98 |
SLIST_ENTRY(ggd_listen) l_next; |
91 |
}; |
99 |
}; |
92 |
|
100 |
|
93 |
static const char *exports_file = GGATED_EXPORT_FILE; |
101 |
static const char *exports_file = GGATED_EXPORT_FILE; |
94 |
static int got_sighup = 0; |
102 |
static int got_sighup = 0; |
95 |
in_addr_t bindaddr; |
|
|
96 |
|
103 |
|
97 |
static TAILQ_HEAD(, ggd_request) inqueue = TAILQ_HEAD_INITIALIZER(inqueue); |
104 |
static TAILQ_HEAD(, ggd_request) inqueue = TAILQ_HEAD_INITIALIZER(inqueue); |
98 |
static TAILQ_HEAD(, ggd_request) outqueue = TAILQ_HEAD_INITIALIZER(outqueue); |
105 |
static TAILQ_HEAD(, ggd_request) outqueue = TAILQ_HEAD_INITIALIZER(outqueue); |
Lines 115-185
Link Here
|
115 |
exit(EXIT_FAILURE); |
122 |
exit(EXIT_FAILURE); |
116 |
} |
123 |
} |
117 |
|
124 |
|
118 |
static char * |
125 |
static const char * |
119 |
ip2str(in_addr_t ip) |
126 |
ip2str(struct sockaddr *addr) |
120 |
{ |
127 |
{ |
121 |
static char sip[16]; |
128 |
static char sip[64]; |
|
|
129 |
|
130 |
if (getnameinfo(addr, addr->sa_len, sip, sizeof(sip), |
131 |
NULL, 0, NI_NUMERICHOST) == 0) |
132 |
return (sip); |
122 |
|
133 |
|
123 |
snprintf(sip, sizeof(sip), "%u.%u.%u.%u", |
134 |
return ("Unknown"); |
124 |
((ip >> 24) & 0xff), |
|
|
125 |
((ip >> 16) & 0xff), |
126 |
((ip >> 8) & 0xff), |
127 |
(ip & 0xff)); |
128 |
return (sip); |
129 |
} |
135 |
} |
130 |
|
136 |
|
131 |
static in_addr_t |
137 |
static struct sockaddr_storage |
132 |
countmask(unsigned m) |
138 |
countmask(struct sockaddr* addr, int mask) /* also normalizes addr */ |
133 |
{ |
139 |
{ |
134 |
in_addr_t mask; |
140 |
struct sockaddr_storage ss; |
|
|
141 |
int i, alen; |
142 |
unsigned char *mp, *ap; |
135 |
|
143 |
|
136 |
if (m == 0) { |
144 |
bzero(&ss, sizeof(ss)); |
137 |
mask = 0x0; |
145 |
ss.ss_family = addr->sa_family; |
138 |
} else { |
146 |
ss.ss_len = addr->sa_len; |
139 |
mask = 1 << (32 - m); |
147 |
|
140 |
mask--; |
148 |
switch (addr->sa_family) { |
141 |
mask = ~mask; |
149 |
case AF_INET: |
|
|
150 |
alen = 4; /* 32 bits */ |
151 |
ap = (unsigned char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr; |
152 |
mp = (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr; |
153 |
break; |
154 |
case AF_INET6: |
155 |
alen = 16; /* 128 bits */ |
156 |
ap = (unsigned char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr; |
157 |
mp = (unsigned char*)&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr; |
158 |
break; |
159 |
default: |
160 |
g_gate_xlog("Unknown address family in countmask"); |
161 |
} |
162 |
|
163 |
i = 0; |
164 |
while (mask > 0 && i < alen) { |
165 |
if (mask < 8) { |
166 |
mp[i] = ~(0xff >> mask); |
167 |
ap[i] &= mp[i]; |
168 |
} else |
169 |
mp[i] = 0xff; |
170 |
i++; |
171 |
mask -= 8; |
142 |
} |
172 |
} |
143 |
return (mask); |
173 |
while (i < alen) { /* zero out remaining bits of addr */ |
|
|
174 |
ap[i] = 0; |
175 |
i++; |
176 |
} |
177 |
|
178 |
return (ss); |
144 |
} |
179 |
} |
145 |
|
180 |
|
146 |
static void |
181 |
static void |
147 |
line_parse(char *line, unsigned lineno) |
182 |
line_parse(char *line, unsigned lineno) |
148 |
{ |
183 |
{ |
149 |
struct ggd_export *ex; |
184 |
struct ggd_export *ex; |
150 |
char *word, *path, *sflags; |
185 |
char *pmask, *word, *path, *sflags; |
151 |
unsigned flags, i, vmask; |
186 |
unsigned flags, i; |
152 |
in_addr_t ip, mask; |
187 |
int vmask; |
|
|
188 |
struct addrinfo hints, *res, *p; |
153 |
|
189 |
|
154 |
ip = mask = flags = vmask = 0; |
190 |
flags = vmask = 0; |
155 |
path = NULL; |
191 |
path = NULL; |
156 |
sflags = NULL; |
192 |
sflags = NULL; |
|
|
193 |
pmask = NULL; |
157 |
|
194 |
|
158 |
for (i = 0, word = strtok(line, " \t"); word != NULL; |
195 |
for (i = 0, word = strtok(line, " \t"); word != NULL; |
159 |
i++, word = strtok(NULL, " \t")) { |
196 |
i++, word = strtok(NULL, " \t")) { |
160 |
switch (i) { |
197 |
switch (i) { |
161 |
case 0: /* IP address or host name */ |
198 |
case 0: /* IP address or host name */ |
162 |
ip = g_gate_str2ip(strsep(&word, "/")); |
199 |
bzero(&hints, sizeof(hints)); |
163 |
if (ip == INADDR_NONE) { |
200 |
hints.ai_family = PF_UNSPEC; |
|
|
201 |
hints.ai_socktype = SOCK_STREAM; |
202 |
if (getaddrinfo(strsep(&word, "/"), NULL, &hints, |
203 |
&res) != 0) |
164 |
g_gate_xlog("Invalid IP/host name at line %u.", |
204 |
g_gate_xlog("Invalid IP/host name at line %u.", |
165 |
lineno); |
205 |
lineno); |
166 |
} |
206 |
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; |
207 |
break; |
184 |
case 1: /* flags */ |
208 |
case 1: /* flags */ |
185 |
if (strcasecmp("rd", word) == 0 || |
209 |
if (strcasecmp("rd", word) == 0 || |
Lines 209-230
Link Here
|
209 |
if (i != 3) |
233 |
if (i != 3) |
210 |
g_gate_xlog("Too few arguments at line %u.", lineno); |
234 |
g_gate_xlog("Too few arguments at line %u.", lineno); |
211 |
|
235 |
|
212 |
ex = malloc(sizeof(*ex)); |
236 |
p = res; |
213 |
if (ex == NULL) |
237 |
while (p) { |
214 |
g_gate_xlog("No enough memory."); |
238 |
ex = malloc(sizeof(*ex)); |
215 |
ex->e_path = strdup(path); |
239 |
if (ex == NULL) |
216 |
if (ex->e_path == NULL) |
240 |
g_gate_xlog("Not enough memory."); |
217 |
g_gate_xlog("No enough memory."); |
241 |
ex->e_path = strdup(path); |
218 |
|
242 |
if (ex->e_path == NULL) |
219 |
/* Made 'and' here. */ |
243 |
g_gate_xlog("Not enough memory."); |
220 |
ex->e_ip = (ip & mask); |
244 |
|
221 |
ex->e_mask = mask; |
245 |
if (pmask == NULL && p->ai_family == AF_INET6) |
222 |
ex->e_flags = flags; |
246 |
vmask = 128; |
|
|
247 |
else if (pmask == NULL) |
248 |
vmask = 32; |
249 |
else { |
250 |
errno = 0; |
251 |
vmask = strtoul(pmask, NULL, 10); |
252 |
if (vmask == 0 && errno != 0) { |
253 |
g_gate_xlog("Invalid IP mask value at " |
254 |
"line %u.", lineno); |
255 |
} |
256 |
} |
257 |
|
258 |
if ((vmask > 32 && p->ai_family == AF_INET) || |
259 |
(vmask > 128 && p->ai_family == AF_INET6)) |
260 |
g_gate_xlog("Invalid IP mask value at line %u", |
261 |
lineno); |
262 |
|
263 |
memcpy(&ex->e_addr, p->ai_addr, p->ai_addrlen); |
264 |
ex->e_mask = countmask((struct sockaddr*)&ex->e_addr, vmask); |
265 |
ex->e_flags = flags; |
266 |
|
267 |
SLIST_INSERT_HEAD(&exports, ex, e_next); |
223 |
|
268 |
|
224 |
SLIST_INSERT_HEAD(&exports, ex, e_next); |
269 |
g_gate_log(LOG_DEBUG, "Added %s/%u %s %s to exports list.", |
|
|
270 |
ip2str((struct sockaddr*)&ex->e_addr), vmask, path, sflags); |
225 |
|
271 |
|
226 |
g_gate_log(LOG_DEBUG, "Added %s/%u %s %s to exports list.", |
272 |
p = p->ai_next; |
227 |
ip2str(ex->e_ip), vmask, path, sflags); |
273 |
} |
|
|
274 |
|
275 |
freeaddrinfo(res); |
228 |
} |
276 |
} |
229 |
|
277 |
|
230 |
static void |
278 |
static void |
Lines 302-313
Link Here
|
302 |
exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit, |
350 |
exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit, |
303 |
struct ggd_connection *conn) |
351 |
struct ggd_connection *conn) |
304 |
{ |
352 |
{ |
305 |
char ipmask[32]; /* 32 == strlen("xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx")+1 */ |
353 |
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; |
354 |
int error = 0, flags; |
307 |
|
355 |
|
308 |
strlcpy(ipmask, ip2str(ex->e_ip), sizeof(ipmask)); |
356 |
strlcpy(ipmask, ip2str((struct sockaddr*)&ex->e_addr), sizeof(ipmask)); |
309 |
strlcat(ipmask, "/", sizeof(ipmask)); |
357 |
strlcat(ipmask, "/", sizeof(ipmask)); |
310 |
strlcat(ipmask, ip2str(ex->e_mask), sizeof(ipmask)); |
358 |
strlcat(ipmask, ip2str((struct sockaddr*)&ex->e_mask), sizeof(ipmask)); |
311 |
if ((cinit->gc_flags & GGATE_FLAG_RDONLY) != 0) { |
359 |
if ((cinit->gc_flags & GGATE_FLAG_RDONLY) != 0) { |
312 |
if (ex->e_flags == O_WRONLY) { |
360 |
if (ex->e_flags == O_WRONLY) { |
313 |
g_gate_log(LOG_WARNING, "Read-only access requested, " |
361 |
g_gate_log(LOG_WARNING, "Read-only access requested, " |
Lines 355-371
Link Here
|
355 |
return (0); |
403 |
return (0); |
356 |
} |
404 |
} |
357 |
|
405 |
|
|
|
406 |
static int |
407 |
mask_compare(struct sockaddr *a, struct sockaddr *b, struct sockaddr *m) { |
408 |
unsigned char *ap, *bp, *mp; |
409 |
int alen; |
410 |
if (a->sa_family != m->sa_family || b->sa_family != m->sa_family) |
411 |
return (0); |
412 |
|
413 |
switch (m->sa_family) { |
414 |
case AF_INET: |
415 |
alen = 4; |
416 |
ap = (unsigned char*)&((struct sockaddr_in*)a)->sin_addr.s_addr; |
417 |
bp = (unsigned char*)&((struct sockaddr_in*)b)->sin_addr.s_addr; |
418 |
mp = (unsigned char*)&((struct sockaddr_in*)m)->sin_addr.s_addr; |
419 |
break; |
420 |
case AF_INET6: |
421 |
alen = 16; |
422 |
ap = (unsigned char*)&((struct sockaddr_in6*)a)->sin6_addr.s6_addr; |
423 |
bp = (unsigned char*)&((struct sockaddr_in6*)b)->sin6_addr.s6_addr; |
424 |
mp = (unsigned char*)&((struct sockaddr_in6*)m)->sin6_addr.s6_addr; |
425 |
break; |
426 |
default: |
427 |
return (0); |
428 |
} |
429 |
|
430 |
while (alen > 0) { |
431 |
if ((*ap & *mp) != (*bp & *mp)) |
432 |
return (0); |
433 |
|
434 |
ap++; |
435 |
bp++; |
436 |
mp++; |
437 |
alen--; |
438 |
} |
439 |
|
440 |
return (1); |
441 |
} |
442 |
|
358 |
static struct ggd_export * |
443 |
static struct ggd_export * |
359 |
exports_find(struct sockaddr *s, struct g_gate_cinit *cinit, |
444 |
exports_find(struct sockaddr *s, struct g_gate_cinit *cinit, |
360 |
struct ggd_connection *conn) |
445 |
struct ggd_connection *conn) |
361 |
{ |
446 |
{ |
362 |
struct ggd_export *ex; |
447 |
struct ggd_export *ex; |
363 |
in_addr_t ip; |
|
|
364 |
int error; |
448 |
int error; |
365 |
|
449 |
|
366 |
ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); |
|
|
367 |
SLIST_FOREACH(ex, &exports, e_next) { |
450 |
SLIST_FOREACH(ex, &exports, e_next) { |
368 |
if ((ip & ex->e_mask) != ex->e_ip) { |
451 |
if (!mask_compare(s, (struct sockaddr*)&ex->e_addr, |
|
|
452 |
(struct sockaddr*)&ex->e_mask)) { |
369 |
g_gate_log(LOG_DEBUG, "exports[%s]: IP mismatch.", |
453 |
g_gate_log(LOG_DEBUG, "exports[%s]: IP mismatch.", |
370 |
ex->e_path); |
454 |
ex->e_path); |
371 |
continue; |
455 |
continue; |
Lines 384-390
Link Here
|
384 |
} |
468 |
} |
385 |
} |
469 |
} |
386 |
g_gate_log(LOG_WARNING, "Unauthorized connection from: %s.", |
470 |
g_gate_log(LOG_WARNING, "Unauthorized connection from: %s.", |
387 |
ip2str(ip)); |
471 |
ip2str(s)); |
388 |
errno = EPERM; |
472 |
errno = EPERM; |
389 |
return (NULL); |
473 |
return (NULL); |
390 |
} |
474 |
} |
Lines 404-410
Link Here
|
404 |
LIST_REMOVE(conn, c_next); |
488 |
LIST_REMOVE(conn, c_next); |
405 |
g_gate_log(LOG_NOTICE, |
489 |
g_gate_log(LOG_NOTICE, |
406 |
"Connection from %s [%s] removed.", |
490 |
"Connection from %s [%s] removed.", |
407 |
ip2str(conn->c_srcip), conn->c_path); |
491 |
ip2str((struct sockaddr*)&conn->c_srcaddr), |
|
|
492 |
conn->c_path); |
408 |
close(conn->c_diskfd); |
493 |
close(conn->c_diskfd); |
409 |
close(conn->c_sendfd); |
494 |
close(conn->c_sendfd); |
410 |
close(conn->c_recvfd); |
495 |
close(conn->c_recvfd); |
Lines 430-436
Link Here
|
430 |
connection_new(struct g_gate_cinit *cinit, struct sockaddr *s, int sfd) |
515 |
connection_new(struct g_gate_cinit *cinit, struct sockaddr *s, int sfd) |
431 |
{ |
516 |
{ |
432 |
struct ggd_connection *conn; |
517 |
struct ggd_connection *conn; |
433 |
in_addr_t ip; |
|
|
434 |
|
518 |
|
435 |
/* |
519 |
/* |
436 |
* First, look for old connections. |
520 |
* First, look for old connections. |
Lines 449-456
Link Here
|
449 |
return (NULL); |
533 |
return (NULL); |
450 |
} |
534 |
} |
451 |
conn->c_token = cinit->gc_token; |
535 |
conn->c_token = cinit->gc_token; |
452 |
ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); |
536 |
memcpy(&conn->c_srcaddr, s, s->sa_len); |
453 |
conn->c_srcip = ip; |
|
|
454 |
conn->c_sendfd = conn->c_recvfd = -1; |
537 |
conn->c_sendfd = conn->c_recvfd = -1; |
455 |
if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) |
538 |
if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) |
456 |
conn->c_sendfd = sfd; |
539 |
conn->c_sendfd = sfd; |
Lines 461-467
Link Here
|
461 |
time(&conn->c_birthtime); |
544 |
time(&conn->c_birthtime); |
462 |
conn->c_flags = cinit->gc_flags; |
545 |
conn->c_flags = cinit->gc_flags; |
463 |
LIST_INSERT_HEAD(&connections, conn, c_next); |
546 |
LIST_INSERT_HEAD(&connections, conn, c_next); |
464 |
g_gate_log(LOG_DEBUG, "Connection created [%s, %s].", ip2str(ip), |
547 |
g_gate_log(LOG_DEBUG, "Connection created [%s, %s].", ip2str(s), |
465 |
conn->c_path); |
548 |
conn->c_path); |
466 |
return (conn); |
549 |
return (conn); |
467 |
} |
550 |
} |
Lines 470-482
Link Here
|
470 |
connection_add(struct ggd_connection *conn, struct g_gate_cinit *cinit, |
553 |
connection_add(struct ggd_connection *conn, struct g_gate_cinit *cinit, |
471 |
struct sockaddr *s, int sfd) |
554 |
struct sockaddr *s, int sfd) |
472 |
{ |
555 |
{ |
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) { |
556 |
if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) { |
477 |
if (conn->c_sendfd != -1) { |
557 |
if (conn->c_sendfd != -1) { |
478 |
g_gate_log(LOG_WARNING, |
558 |
g_gate_log(LOG_WARNING, |
479 |
"Send socket already exists [%s, %s].", ip2str(ip), |
559 |
"Send socket already exists [%s, %s].", ip2str(s), |
480 |
conn->c_path); |
560 |
conn->c_path); |
481 |
return (EEXIST); |
561 |
return (EEXIST); |
482 |
} |
562 |
} |
Lines 485-496
Link Here
|
485 |
if (conn->c_recvfd != -1) { |
565 |
if (conn->c_recvfd != -1) { |
486 |
g_gate_log(LOG_WARNING, |
566 |
g_gate_log(LOG_WARNING, |
487 |
"Receive socket already exists [%s, %s].", |
567 |
"Receive socket already exists [%s, %s].", |
488 |
ip2str(ip), conn->c_path); |
568 |
ip2str(s), conn->c_path); |
489 |
return (EEXIST); |
569 |
return (EEXIST); |
490 |
} |
570 |
} |
491 |
conn->c_recvfd = sfd; |
571 |
conn->c_recvfd = sfd; |
492 |
} |
572 |
} |
493 |
g_gate_log(LOG_DEBUG, "Connection added [%s, %s].", ip2str(ip), |
573 |
g_gate_log(LOG_DEBUG, "Connection added [%s, %s].", ip2str(s), |
494 |
conn->c_path); |
574 |
conn->c_path); |
495 |
return (0); |
575 |
return (0); |
496 |
} |
576 |
} |
Lines 505-511
Link Here
|
505 |
|
585 |
|
506 |
LIST_REMOVE(conn, c_next); |
586 |
LIST_REMOVE(conn, c_next); |
507 |
g_gate_log(LOG_DEBUG, "Connection removed [%s %s].", |
587 |
g_gate_log(LOG_DEBUG, "Connection removed [%s %s].", |
508 |
ip2str(conn->c_srcip), conn->c_path); |
588 |
ip2str((struct sockaddr*)&conn->c_srcaddr), conn->c_path); |
509 |
if (conn->c_sendfd != -1) |
589 |
if (conn->c_sendfd != -1) |
510 |
close(conn->c_sendfd); |
590 |
close(conn->c_sendfd); |
511 |
if (conn->c_recvfd != -1) |
591 |
if (conn->c_recvfd != -1) |
Lines 815-824
Link Here
|
815 |
static void |
895 |
static void |
816 |
log_connection(struct sockaddr *from) |
896 |
log_connection(struct sockaddr *from) |
817 |
{ |
897 |
{ |
818 |
in_addr_t ip; |
898 |
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 |
} |
899 |
} |
823 |
|
900 |
|
824 |
static int |
901 |
static int |
Lines 940-953
Link Here
|
940 |
int |
1017 |
int |
941 |
main(int argc, char *argv[]) |
1018 |
main(int argc, char *argv[]) |
942 |
{ |
1019 |
{ |
943 |
struct sockaddr_in serv; |
1020 |
SLIST_HEAD(, ggd_listen) listens = SLIST_HEAD_INITIALIZER(&listens); |
944 |
struct sockaddr from; |
1021 |
struct ggd_listen *cl, *nl; |
|
|
1022 |
struct addrinfo hints, *res, *p; |
1023 |
struct sockaddr_storage from; |
945 |
socklen_t fromlen; |
1024 |
socklen_t fromlen; |
946 |
int sfd, tmpsfd; |
1025 |
int maxfd, tmpsfd; |
947 |
unsigned port; |
1026 |
fd_set listenfds; |
|
|
1027 |
const char *port; |
948 |
|
1028 |
|
949 |
bindaddr = htonl(INADDR_ANY); |
1029 |
port = G_GATE_PORT_STR; |
950 |
port = G_GATE_PORT; |
|
|
951 |
for (;;) { |
1030 |
for (;;) { |
952 |
int ch; |
1031 |
int ch; |
953 |
|
1032 |
|
Lines 956-975
Link Here
|
956 |
break; |
1035 |
break; |
957 |
switch (ch) { |
1036 |
switch (ch) { |
958 |
case 'a': |
1037 |
case 'a': |
959 |
bindaddr = g_gate_str2ip(optarg); |
1038 |
nl = malloc(sizeof(*nl)); |
960 |
if (bindaddr == INADDR_NONE) { |
1039 |
bzero(nl, sizeof(*nl)); |
961 |
errx(EXIT_FAILURE, |
1040 |
nl->l_name = optarg; |
962 |
"Invalid IP/host name to bind to."); |
1041 |
/* delay resolution until we know port number */ |
963 |
} |
1042 |
SLIST_INSERT_HEAD(&listens, nl, l_next); |
964 |
break; |
1043 |
break; |
965 |
case 'n': |
1044 |
case 'n': |
966 |
nagle = 0; |
1045 |
nagle = 0; |
967 |
break; |
1046 |
break; |
968 |
case 'p': |
1047 |
case 'p': |
969 |
errno = 0; |
1048 |
port = optarg; |
970 |
port = strtoul(optarg, NULL, 10); |
|
|
971 |
if (port == 0 && errno != 0) |
972 |
errx(EXIT_FAILURE, "Invalid port."); |
973 |
break; |
1049 |
break; |
974 |
case 'R': |
1050 |
case 'R': |
975 |
errno = 0; |
1051 |
errno = 0; |
Lines 998-1003
Link Here
|
998 |
exports_file = argv[0]; |
1074 |
exports_file = argv[0]; |
999 |
exports_get(); |
1075 |
exports_get(); |
1000 |
|
1076 |
|
|
|
1077 |
if (SLIST_EMPTY(&listens)) { |
1078 |
/* Bind to all address families */ |
1079 |
bzero(&hints, sizeof(hints)); |
1080 |
hints.ai_family = PF_UNSPEC; |
1081 |
hints.ai_flags = AI_PASSIVE; |
1082 |
hints.ai_socktype = SOCK_STREAM; |
1083 |
if (getaddrinfo(NULL, port, &hints, &res)) |
1084 |
g_gate_xlog("Cannot get passive address: %s", |
1085 |
strerror(errno)); |
1086 |
|
1087 |
p = res; |
1088 |
while (p) { |
1089 |
nl = malloc(sizeof(*nl)); |
1090 |
bzero(nl, sizeof(*nl)); |
1091 |
memcpy(&nl->l_addr, p->ai_addr, p->ai_addrlen); |
1092 |
SLIST_INSERT_HEAD(&listens, nl, l_next); |
1093 |
|
1094 |
p = p->ai_next; |
1095 |
} |
1096 |
freeaddrinfo(res); |
1097 |
} else { |
1098 |
/* Bind to some specific addresses */ |
1099 |
SLIST_FOREACH(cl, &listens, l_next) { |
1100 |
bzero(&hints, sizeof(hints)); |
1101 |
hints.ai_family = PF_UNSPEC; |
1102 |
hints.ai_socktype = SOCK_STREAM; |
1103 |
if (getaddrinfo(cl->l_name, port, &hints, &res)) |
1104 |
g_gate_xlog("Invalid IP/host name to bind to: " |
1105 |
"%s", cl->l_name); |
1106 |
|
1107 |
/* Re-use current list entry for first match, add |
1108 |
* new ones after that */ |
1109 |
p = res; |
1110 |
nl = cl; |
1111 |
while (p) { |
1112 |
if (p != res) { |
1113 |
nl = malloc(sizeof(*nl)); |
1114 |
bzero(nl, sizeof(*nl)); |
1115 |
} |
1116 |
|
1117 |
memcpy(&nl->l_addr, p->ai_addr, p->ai_addrlen); |
1118 |
|
1119 |
if (p != res) { |
1120 |
SLIST_INSERT_HEAD(&listens, nl, l_next); |
1121 |
} |
1122 |
p = p->ai_next; |
1123 |
} |
1124 |
freeaddrinfo(res); |
1125 |
} |
1126 |
} |
1127 |
|
1128 |
/* Actually create sockets and bind to them */ |
1129 |
maxfd = 0; |
1130 |
SLIST_FOREACH(cl, &listens, l_next) { |
1131 |
cl->l_fd = socket(cl->l_addr.ss_family, SOCK_STREAM, 0); |
1132 |
if (cl->l_fd == -1) |
1133 |
g_gate_xlog("Cannot open stream socket: %s.", |
1134 |
strerror(errno)); |
1135 |
g_gate_socket_settings(cl->l_fd); |
1136 |
|
1137 |
if (bind(cl->l_fd, (struct sockaddr *)&cl->l_addr, |
1138 |
cl->l_addr.ss_len) == -1) |
1139 |
g_gate_xlog("bind(): %s.", strerror(errno)); |
1140 |
if (listen(cl->l_fd, 5) == -1) |
1141 |
g_gate_xlog("listen(): %s.", strerror(errno)); |
1142 |
|
1143 |
if (maxfd <= cl->l_fd) |
1144 |
maxfd = cl->l_fd + 1; |
1145 |
|
1146 |
g_gate_log(LOG_INFO, "Listen on address: %s (%s).", |
1147 |
ip2str((struct sockaddr *)&cl->l_addr), port); |
1148 |
} |
1149 |
|
1001 |
if (!g_gate_verbose) { |
1150 |
if (!g_gate_verbose) { |
1002 |
/* Run in daemon mode. */ |
1151 |
/* Run in daemon mode. */ |
1003 |
if (daemon(0, 0) == -1) |
1152 |
if (daemon(0, 0) == -1) |
Lines 1005-1044
Link Here
|
1005 |
} |
1154 |
} |
1006 |
|
1155 |
|
1007 |
signal(SIGCHLD, SIG_IGN); |
1156 |
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); |
1157 |
signal(SIGHUP, huphandler); |
1027 |
|
1158 |
|
1028 |
for (;;) { |
1159 |
for (;;) { |
1029 |
fromlen = sizeof(from); |
1160 |
FD_ZERO(&listenfds); |
1030 |
tmpsfd = accept(sfd, &from, &fromlen); |
1161 |
SLIST_FOREACH(cl, &listens, l_next) { |
1031 |
if (tmpsfd == -1) |
1162 |
FD_SET(cl->l_fd, &listenfds); |
1032 |
g_gate_xlog("accept(): %s.", strerror(errno)); |
1163 |
} |
|
|
1164 |
|
1165 |
select(maxfd, &listenfds, NULL, NULL, NULL); |
1033 |
|
1166 |
|
1034 |
if (got_sighup) { |
1167 |
if (got_sighup) { |
1035 |
got_sighup = 0; |
1168 |
got_sighup = 0; |
1036 |
exports_get(); |
1169 |
exports_get(); |
1037 |
} |
1170 |
} |
1038 |
|
1171 |
|
1039 |
if (!handshake(&from, tmpsfd)) |
1172 |
SLIST_FOREACH(cl, &listens, l_next) { |
1040 |
close(tmpsfd); |
1173 |
if (!FD_ISSET(cl->l_fd, &listenfds)) |
|
|
1174 |
continue; |
1175 |
|
1176 |
fromlen = sizeof(from); |
1177 |
tmpsfd = accept(cl->l_fd, (struct sockaddr*)&from, |
1178 |
&fromlen); |
1179 |
|
1180 |
if (tmpsfd == -1) { |
1181 |
g_gate_log(LOG_WARNING, "accept(): %s.", |
1182 |
strerror(errno)); |
1183 |
continue; |
1184 |
} |
1185 |
|
1186 |
if (!handshake((struct sockaddr*)&from, tmpsfd)) |
1187 |
close(tmpsfd); |
1188 |
} |
1189 |
} |
1190 |
while (!SLIST_EMPTY(&listens)) { |
1191 |
cl = SLIST_FIRST(&listens); |
1192 |
close(cl->l_fd); |
1193 |
SLIST_REMOVE_HEAD(&listens, l_next); |
1194 |
free(cl); |
1041 |
} |
1195 |
} |
1042 |
close(sfd); |
|
|
1043 |
exit(EXIT_SUCCESS); |
1196 |
exit(EXIT_SUCCESS); |
1044 |
} |
1197 |
} |