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