]> arthur.barton.de Git - netatalk.git/blob - etc/cnid_dbd/usockfd.c
- merge branch-netatalk-afp-3x-dev, HEAD was tagged before
[netatalk.git] / etc / cnid_dbd / usockfd.c
1 /*
2  * $Id: usockfd.c,v 1.2 2005-04-28 20:49:49 bfernhomberg 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
37 int usockfd_create(char *usock_fn, mode_t mode, int backlog)
38 {
39     int sockfd;
40     struct sockaddr_un addr;
41
42
43     if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
44         LOG(log_error, logtype_cnid, "error in socket call: %s",
45             strerror(errno));
46         return -1;
47     }
48      
49     if (unlink(usock_fn) < 0 && errno != ENOENT) {
50         LOG(log_error, logtype_cnid, "error unlinking unix socket file %s: %s",
51             usock_fn, strerror(errno));
52         return -1;
53     }
54     memset((char *) &addr, 0, sizeof(struct sockaddr_un));
55     addr.sun_family = AF_UNIX;
56     strncpy(addr.sun_path, usock_fn, sizeof(addr.sun_path) - 1);
57     if (bind(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) < 0) {
58         LOG(log_error, logtype_cnid, "error binding to socket for %s: %s",
59             usock_fn, strerror(errno));
60         return -1;
61     }
62
63     if (listen(sockfd, backlog) < 0) {
64         LOG(log_error, logtype_cnid, "error in listen for %s: %s",
65             usock_fn, strerror(errno));
66         return -1;
67     }
68
69     if (chmod(usock_fn, mode) < 0) {
70         LOG(log_error, logtype_cnid, "error changing permissions for %s: %s",
71             usock_fn, strerror(errno));
72         close(sockfd);
73         return -1;
74     }
75
76     return sockfd;
77 }
78
79 /* ---------------
80    create a tcp socket (should share dsi stuff)
81 */
82 int tsockfd_create(char *host, u_int16_t ipport, int backlog)
83 {
84     int sockfd;
85     struct sockaddr_in server;
86     struct hostent     *hp;  
87     int                port;
88     
89     hp=gethostbyname(host);
90     if (!hp) {
91         unsigned long int addr=inet_addr(host);
92         if (addr!= (unsigned)-1)
93             hp=gethostbyaddr((char*)addr,sizeof(addr),AF_INET);
94  
95         if (!hp) {
96             LOG(log_error, logtype_cnid, "gethostbyaddr %s: %s", host, strerror(errno));
97             return -1;
98         }
99     }
100     memcpy((char*)&server.sin_addr,(char*)hp->h_addr,sizeof(server.sin_addr));    
101
102     if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
103         LOG(log_error, logtype_cnid, "error in socket call: %s", strerror(errno));
104         return -1;
105     }
106      
107     port = htons(ipport);
108     
109     server.sin_family = AF_INET;
110     server.sin_port = port;
111
112 #ifdef SO_REUSEADDR
113     port = 1;
114     setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &port, sizeof(port));
115 #endif /* SO_REUSEADDR */
116
117 #ifdef USE_TCP_NODELAY 
118 #ifndef SOL_TCP
119 #define SOL_TCP IPPROTO_TCP
120 #endif /* ! SOL_TCP */
121     port = 1;
122     setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &port, sizeof(port));
123 #endif /* USE_TCP_NODELAY */
124
125     if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
126         LOG(log_error, logtype_cnid, "error binding to socket for %s: %s",
127             host, strerror(errno));
128         return -1;
129     }
130
131     if (listen(sockfd, backlog) < 0) {
132         LOG(log_error, logtype_cnid, "error in listen for %s: %s",
133             host, strerror(errno));
134         return -1;
135     }
136
137     return sockfd;
138 }
139
140 /* --------------------- */
141 int usockfd_check(int sockfd, unsigned long ndelay)
142 {
143     int fd;
144     int size;
145     fd_set readfds;
146     struct timeval tv;
147     int ret;
148      
149     FD_ZERO(&readfds);
150     FD_SET(sockfd, &readfds);
151
152     tv.tv_usec = ndelay % 1000000;
153     tv.tv_sec  = ndelay / 1000000;
154     if ((ret = select(sockfd + 1, &readfds, NULL, NULL, &tv)) < 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 }