]> arthur.barton.de Git - netatalk.git/blob - etc/cnid_dbd/usockfd.c
Remove SO_RCVTIMEO/SO_SNDTIMEO, switch to non-blocking IO
[netatalk.git] / etc / cnid_dbd / usockfd.c
1 /*
2  * Copyright (C) Joerg Lenneis 2003
3  * All Rights Reserved.  See COPYING.
4  */
5
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif /* HAVE_CONFIG_H */
9
10
11 #include <stdlib.h>
12 #include <string.h>
13 #include <errno.h>
14 #ifdef HAVE_UNISTD_H
15 #include <unistd.h>
16 #endif /* HAVE_UNISTD_H */
17 #include <sys/un.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <netdb.h>
22
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif /* HAVE_SYS_TYPES_H */
26 #ifdef HAVE_SYS_TIME_H
27 #include <sys/time.h>
28 #endif /* HAVE_SYS_TIME_H */
29
30
31 #include <atalk/logger.h>
32 #include "usockfd.h"
33
34 #include <sys/select.h>
35
36 int usockfd_create(char *usock_fn, mode_t mode, int backlog)
37 {
38     int sockfd;
39     struct sockaddr_un addr;
40
41
42     if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
43         LOG(log_error, logtype_cnid, "error in socket call: %s",
44             strerror(errno));
45         return -1;
46     }
47      
48     if (unlink(usock_fn) < 0 && errno != ENOENT) {
49         LOG(log_error, logtype_cnid, "error unlinking unix socket file %s: %s",
50             usock_fn, strerror(errno));
51         return -1;
52     }
53     memset((char *) &addr, 0, sizeof(struct sockaddr_un));
54     addr.sun_family = AF_UNIX;
55     strncpy(addr.sun_path, usock_fn, sizeof(addr.sun_path) - 1);
56     if (bind(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) < 0) {
57         LOG(log_error, logtype_cnid, "error binding to socket for %s: %s",
58             usock_fn, strerror(errno));
59         return -1;
60     }
61
62     if (listen(sockfd, backlog) < 0) {
63         LOG(log_error, logtype_cnid, "error in listen for %s: %s",
64             usock_fn, strerror(errno));
65         return -1;
66     }
67
68     if (chmod(usock_fn, mode) < 0) {
69         LOG(log_error, logtype_cnid, "error changing permissions for %s: %s",
70             usock_fn, strerror(errno));
71         close(sockfd);
72         return -1;
73     }
74
75     return sockfd;
76 }
77
78 /* ---------------
79  * create a tcp socket
80  */
81 int tsockfd_create(char *host, char *port, int backlog)
82 {
83     int sockfd, flag, ret;
84     struct addrinfo hints, *servinfo, *p;
85
86     /* Prepare hint for getaddrinfo */
87     memset(&hints, 0, sizeof hints);
88     hints.ai_family = AF_UNSPEC;
89     hints.ai_socktype = SOCK_STREAM;
90
91     if ((ret = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
92         LOG(log_error, logtype_default, "tsockfd_create: getaddrinfo: %s\n", gai_strerror(ret));
93         return 0;
94     }
95
96     /* create a socket */
97     /* loop through all the results and bind to the first we can */
98     for (p = servinfo; p != NULL; p = p->ai_next) {
99         if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
100             LOG(log_info, logtype_default, "tsockfd_create: socket: %s", strerror(errno));
101             continue;
102         }
103
104         /*
105          * Set some socket options:
106          * SO_REUSEADDR deals w/ quick close/opens
107          * TCP_NODELAY diables Nagle
108          */
109 #ifdef SO_REUSEADDR
110         flag = 1;
111         setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
112 #endif
113
114 #ifdef USE_TCP_NODELAY
115 #ifndef SOL_TCP
116 #define SOL_TCP IPPROTO_TCP
117 #endif
118         flag = 1;
119         setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));
120 #endif /* USE_TCP_NODELAY */
121             
122         if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
123             close(sockfd);
124             LOG(log_info, logtype_default, "tsockfd_create: bind: %s\n", strerror(errno));
125             continue;
126         }
127
128         if (listen(sockfd, backlog) < 0) {
129             close(sockfd);
130             LOG(log_info, logtype_default, "tsockfd_create: listen: %s\n", strerror(errno));
131             continue;
132         }
133
134         /* We got a socket */
135         break;
136     }
137
138     if (p == NULL)  {
139         LOG(log_error, logtype_default, "tsockfd_create: no suitable network config %s:%s", host, port);
140         freeaddrinfo(servinfo);
141         return -1;
142     }
143
144     freeaddrinfo(servinfo);
145     return sockfd;
146 }
147
148 /* --------------------- */
149 int usockfd_check(int sockfd, const sigset_t *sigset)
150 {
151     int fd;
152     socklen_t size;
153     fd_set readfds;
154     int ret;
155     struct timeval tv;
156      
157     FD_ZERO(&readfds);
158     FD_SET(sockfd, &readfds);
159
160     if ((ret = pselect(sockfd + 1, &readfds, NULL, NULL, NULL, sigset)) < 0) {
161         if (errno == EINTR)
162             return 0;
163         LOG(log_error, logtype_cnid, "error in select: %s",
164             strerror(errno));
165         return -1;
166     }
167
168     if (ret) {
169         size = 0;
170         if ((fd = accept(sockfd, NULL, &size)) < 0) {
171             if (errno == EINTR)
172                 return 0;
173             LOG(log_error, logtype_cnid, "error in accept: %s", 
174                 strerror(errno));
175             return -1;
176         }
177         if (setnonblock(fd, 1) != 0) {
178             LOG(log_error, logtype_cnid, "setnonblock: %s", strerror(errno));
179             return -1;
180         }
181         return fd;
182     } else
183         return 0;
184 }