version 1.7, 2015/12/25 17:16:43 |
version 1.8, 2016/01/08 13:14:11 |
|
|
#include <netinet/tcp.h> |
#include <netinet/tcp.h> |
#include <netdb.h> |
#include <netdb.h> |
|
|
#include <err.h> |
|
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#include <poll.h> |
#include <poll.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
|
#include <string.h> |
#include <string.h> |
#include <unistd.h> |
#include <unistd.h> |
|
|
|
|
} |
} |
*pf = f->next; |
*pf = f->next; |
|
|
if (f->path != NULL) |
if (f->path != NULL) { |
|
unlink(f->path); |
xfree(f->path); |
xfree(f->path); |
|
} |
file_del(f->file); |
file_del(f->file); |
close(f->fd); |
close(f->fd); |
xfree(f); |
xfree(f); |
} |
} |
|
|
void |
int |
listen_new_un(char *path) |
listen_new_un(char *path) |
{ |
{ |
int sock, oldumask; |
int sock, oldumask; |
|
|
|
|
sock = socket(AF_UNIX, SOCK_STREAM, 0); |
sock = socket(AF_UNIX, SOCK_STREAM, 0); |
if (sock < 0) { |
if (sock < 0) { |
perror("socket"); |
log_puts(path); |
exit(1); |
log_puts(": failed to create socket\n"); |
|
return 0; |
} |
} |
if (unlink(path) < 0 && errno != ENOENT) { |
if (unlink(path) < 0 && errno != ENOENT) { |
perror("unlink"); |
log_puts(path); |
|
log_puts(": failed to unlink socket\n"); |
goto bad_close; |
goto bad_close; |
} |
} |
sockname.sun_family = AF_UNIX; |
sockname.sun_family = AF_UNIX; |
|
|
oldumask = umask(0111); |
oldumask = umask(0111); |
if (bind(sock, (struct sockaddr *)&sockname, |
if (bind(sock, (struct sockaddr *)&sockname, |
sizeof(struct sockaddr_un)) < 0) { |
sizeof(struct sockaddr_un)) < 0) { |
perror("bind"); |
log_puts(path); |
|
log_puts(": failed to bind socket\n"); |
goto bad_close; |
goto bad_close; |
} |
} |
if (listen(sock, 1) < 0) { |
if (listen(sock, 1) < 0) { |
perror("listen"); |
log_puts(path); |
|
log_puts(": failed to listen\n"); |
goto bad_close; |
goto bad_close; |
} |
} |
umask(oldumask); |
umask(oldumask); |
|
|
if (f->file == NULL) |
if (f->file == NULL) |
goto bad_close; |
goto bad_close; |
f->path = xstrdup(path); |
f->path = xstrdup(path); |
if (f->path == NULL) { |
|
perror("strdup"); |
|
exit(1); |
|
} |
|
f->fd = sock; |
f->fd = sock; |
f->next = listen_list; |
f->next = listen_list; |
listen_list = f; |
listen_list = f; |
return; |
return 1; |
bad_close: |
bad_close: |
close(sock); |
close(sock); |
exit(1); |
return 0; |
} |
} |
|
|
void |
int |
listen_new_tcp(char *addr, unsigned int port) |
listen_new_tcp(char *addr, unsigned int port) |
{ |
{ |
char *host, serv[sizeof(unsigned int) * 3 + 1]; |
char *host, serv[sizeof(unsigned int) * 3 + 1]; |
|
|
aihints.ai_protocol = IPPROTO_TCP; |
aihints.ai_protocol = IPPROTO_TCP; |
error = getaddrinfo(host, serv, &aihints, &ailist); |
error = getaddrinfo(host, serv, &aihints, &ailist); |
if (error) { |
if (error) { |
fprintf(stderr, "%s: %s\n", addr, gai_strerror(error)); |
log_puts(addr); |
exit(1); |
log_puts(": failed to resolve address\n"); |
|
return 0; |
} |
} |
|
|
/* |
/* |
|
|
for (ai = ailist; ai != NULL; ai = ai->ai_next) { |
for (ai = ailist; ai != NULL; ai = ai->ai_next) { |
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
if (s < 0) { |
if (s < 0) { |
perror("socket"); |
log_puts(addr); |
|
log_puts(": failed to create socket\n"); |
continue; |
continue; |
} |
} |
opt = 1; |
opt = 1; |
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, |
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, |
&opt, sizeof(int)) < 0) { |
&opt, sizeof(int)) < 0) { |
perror("setsockopt"); |
log_puts(addr); |
|
log_puts(": failed to set SO_REUSEADDR\n"); |
goto bad_close; |
goto bad_close; |
} |
} |
|
if (ai->ai_family == AF_INET6) { |
|
/* |
|
* make sure IPv6 sockets are restricted to IPv6 |
|
* addresses because we already use a IP socket |
|
* for IP addresses |
|
*/ |
|
opt = 1; |
|
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, |
|
&opt, sizeof(int)) < 0) { |
|
log_puts(addr); |
|
log_puts(": failed to set IPV6_V6ONLY\n"); |
|
goto bad_close; |
|
} |
|
} |
|
|
if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) { |
if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) { |
perror("bind"); |
log_puts(addr); |
|
log_puts(": failed to bind socket\n"); |
goto bad_close; |
goto bad_close; |
} |
} |
if (listen(s, 1) < 0) { |
if (listen(s, 1) < 0) { |
perror("listen"); |
log_puts(addr); |
|
log_puts(": failed to listen\n"); |
goto bad_close; |
goto bad_close; |
} |
} |
f = xmalloc(sizeof(struct listen)); |
f = xmalloc(sizeof(struct listen)); |
|
|
n++; |
n++; |
} |
} |
freeaddrinfo(ailist); |
freeaddrinfo(ailist); |
if (n == 0) |
return n; |
exit(1); |
|
} |
} |
|
|
int |
int |
|
|
continue; |
continue; |
if (errno == ENFILE || errno == EMFILE) |
if (errno == ENFILE || errno == EMFILE) |
file_slowaccept = 1; |
file_slowaccept = 1; |
else if (errno != ECONNABORTED && errno != EWOULDBLOCK) |
|
perror("accept"); |
|
return; |
return; |
} |
} |
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { |
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { |
perror("fcntl(sock, O_NONBLOCK)"); |
file_log(f->file); |
|
log_puts(": failed to set non-blocking mode\n"); |
close(sock); |
close(sock); |
return; |
return; |
} |
} |
|
|
opt = 1; |
opt = 1; |
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, |
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, |
&opt, sizeof(int)) < 0) { |
&opt, sizeof(int)) < 0) { |
perror("setsockopt"); |
file_log(f->file); |
|
log_puts(": failed to set TCP_NODELAY flag\n"); |
close(sock); |
close(sock); |
return; |
return; |
} |
} |