update to newest ct; fixes #60
[beanstalkd.git] / net.c
blob78ea567615312dc04b0d3ed0633c04f467c08ea5
1 /* Copyright (C) 2007 Keith Rarick and Philotic Inc.
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include <netdb.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <netinet/tcp.h>
25 #include "dat.h"
26 #include "sd-daemon.h"
28 int
29 make_server_socket(char *host, char *port)
31 int fd = -1, flags, r;
32 struct linger linger = {0, 0};
33 struct addrinfo *airoot, *ai, hints;
35 /* See if we got a listen fd from systemd. If so, all socket options etc
36 * are already set, so we check that the fd is a TCP listen socket and
37 * return. */
38 r = sd_listen_fds(1);
39 if (r < 0) {
40 return twarn("sd_listen_fds"), -1;
42 if (r > 0) {
43 if (r > 1) {
44 twarnx("inherited more than one listen socket;"
45 " ignoring all but the first");
46 r = 1;
48 fd = SD_LISTEN_FDS_START;
49 r = sd_is_socket_inet(fd, 0, SOCK_STREAM, 1, 0);
50 if (r < 0) {
51 errno = -r;
52 twarn("sd_is_socket_inet");
53 return -1;
55 if (!r) {
56 twarnx("inherited fd is not a TCP listen socket");
57 return -1;
59 return fd;
62 memset(&hints, 0, sizeof(hints));
63 hints.ai_family = PF_UNSPEC;
64 hints.ai_socktype = SOCK_STREAM;
65 hints.ai_flags = AI_PASSIVE;
66 r = getaddrinfo(host, port, &hints, &airoot);
67 if (r == -1)
68 return twarn("getaddrinfo()"), -1;
70 for(ai = airoot; ai; ai = ai->ai_next) {
71 fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
72 if (fd == -1) {
73 twarn("socket()");
74 continue;
77 flags = fcntl(fd, F_GETFL, 0);
78 if (flags < 0) {
79 twarn("getting flags");
80 close(fd);
81 continue;
84 r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
85 if (r == -1) {
86 twarn("setting O_NONBLOCK");
87 close(fd);
88 continue;
91 flags = 1;
92 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof flags);
93 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof flags);
94 setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger, sizeof linger);
95 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof flags);
97 r = bind(fd, ai->ai_addr, ai->ai_addrlen);
98 if (r == -1) {
99 twarn("bind()");
100 close(fd);
101 continue;
104 r = listen(fd, 1024);
105 if (r == -1) {
106 twarn("listen()");
107 close(fd);
108 continue;
111 break;
114 freeaddrinfo(airoot);
116 if(ai == NULL)
117 fd = -1;
119 return fd;