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