]> arthur.barton.de Git - netatalk.git/blob - etc/cnid_dbd/usockfd.c
888d914b39bf1fcb23bac0625cdc24037d31afd7
[netatalk.git] / etc / cnid_dbd / usockfd.c
1 /*
2  * $Id: usockfd.c,v 1.5 2009-10-18 20:21:09 didg Exp $
3  *
4  * Copyright (C) Joerg Lenneis 2003
5  * All Rights Reserved.  See COPYING.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
16 #ifdef HAVE_UNISTD_H
17 #include <unistd.h>
18 #endif /* HAVE_UNISTD_H */
19 #include <sys/un.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
23 #include <netdb.h>
24
25 #ifdef HAVE_SYS_TYPES_H
26 #include <sys/types.h>
27 #endif /* HAVE_SYS_TYPES_H */
28 #ifdef HAVE_SYS_TIME_H
29 #include <sys/time.h>
30 #endif /* HAVE_SYS_TIME_H */
31
32
33 #include <atalk/logger.h>
34 #include "usockfd.h"
35
36 #include <sys/select.h>
37
38 int usockfd_create(char *usock_fn, mode_t mode, int backlog)
39 {
40     int sockfd;
41     struct sockaddr_un addr;
42
43
44     if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
45         LOG(log_error, logtype_cnid, "error in socket call: %s",
46             strerror(errno));
47         return -1;
48     }
49      
50     if (unlink(usock_fn) < 0 && errno != ENOENT) {
51         LOG(log_error, logtype_cnid, "error unlinking unix socket file %s: %s",
52             usock_fn, strerror(errno));
53         return -1;
54     }
55     memset((char *) &addr, 0, sizeof(struct sockaddr_un));
56     addr.sun_family = AF_UNIX;
57     strncpy(addr.sun_path, usock_fn, sizeof(addr.sun_path) - 1);
58     if (bind(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) < 0) {
59         LOG(log_error, logtype_cnid, "error binding to socket for %s: %s",
60             usock_fn, strerror(errno));
61         return -1;
62     }
63
64     if (listen(sockfd, backlog) < 0) {
65         LOG(log_error, logtype_cnid, "error in listen for %s: %s",
66             usock_fn, strerror(errno));
67         return -1;
68     }
69
70     if (chmod(usock_fn, mode) < 0) {
71         LOG(log_error, logtype_cnid, "error changing permissions for %s: %s",
72             usock_fn, strerror(errno));
73         close(sockfd);
74         return -1;
75     }
76
77     return sockfd;
78 }
79
80 /* ---------------
81    create a tcp socket (should share dsi stuff)
82 */
83 int tsockfd_create(char *host, u_int16_t ipport, int backlog)
84 {
85     int sockfd;
86     struct sockaddr_in server;
87     struct hostent     *hp;  
88     int                port;
89     
90     hp=gethostbyname(host);
91     if (!hp) {
92         unsigned long int addr=inet_addr(host);
93         if (addr!= (unsigned)-1)
94             hp=gethostbyaddr((char*)addr,sizeof(addr),AF_INET);
95  
96         if (!hp) {
97             LOG(log_error, logtype_cnid, "gethostbyaddr %s: %s", host, strerror(errno));
98             return -1;
99         }
100     }
101     memcpy((char*)&server.sin_addr,(char*)hp->h_addr,sizeof(server.sin_addr));    
102
103     if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
104         LOG(log_error, logtype_cnid, "error in socket call: %s", strerror(errno));
105         return -1;
106     }
107      
108     port = htons(ipport);
109     
110     server.sin_family = AF_INET;
111     server.sin_port = port;
112
113 #ifdef SO_REUSEADDR
114     port = 1;
115     setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &port, sizeof(port));
116 #endif /* SO_REUSEADDR */
117
118 #ifdef USE_TCP_NODELAY 
119 #ifndef SOL_TCP
120 #define SOL_TCP IPPROTO_TCP
121 #endif /* ! SOL_TCP */
122     port = 1;
123     setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &port, sizeof(port));
124 #endif /* USE_TCP_NODELAY */
125
126     if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
127         LOG(log_error, logtype_cnid, "error binding to socket for %s: %s",
128             host, strerror(errno));
129         return -1;
130     }
131
132     if (listen(sockfd, backlog) < 0) {
133         LOG(log_error, logtype_cnid, "error in listen for %s: %s",
134             host, strerror(errno));
135         return -1;
136     }
137
138     return sockfd;
139 }
140
141 /* --------------------- */
142 int usockfd_check(int sockfd, const sigset_t *sigset)
143 {
144     int fd;
145     socklen_t size;
146     fd_set readfds;
147     int ret;
148     struct timeval tv;
149      
150     FD_ZERO(&readfds);
151     FD_SET(sockfd, &readfds);
152
153     if ((ret = pselect(sockfd + 1, &readfds, NULL, NULL, NULL, sigset)) < 0) {
154         if (errno == EINTR)
155             return 0;
156         LOG(log_error, logtype_cnid, "error in select: %s",
157             strerror(errno));
158         return -1;
159     }
160
161     if (ret) {
162         size = 0;
163         if ((fd = accept(sockfd, NULL, &size)) < 0) {
164             if (errno == EINTR)
165                 return 0;
166             LOG(log_error, logtype_cnid, "error in accept: %s", 
167                 strerror(errno));
168             return -1;
169         }
170         tv.tv_sec = 5;
171         tv.tv_usec = 0;
172         if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
173             LOG(log_error, logtype_cnid, "set SO_RCVTIMEO: %s", strerror(errno));
174             close(fd);
175             return -1;
176         }
177         return fd;
178     } else
179         return 0;
180 }