@@ -72,21 +72,68 @@ static struct protocol proto_unix = {
72
72
********************************/
73
73
74
74
75
- /* This function creates a named PF_UNIX stream socket at address <path>. Note
76
- * that the path cannot be NULL nor empty. <uid> and <gid> different of -1 will
77
- * be used to change the socket owner. If <mode> is not 0, it will be used to
78
- * restrict access to the socket. While it is known not to be portable on every
79
- * OS, it's still useful where it works.
80
- * It returns the assigned file descriptor, or -1 in the event of an error.
75
+ /* Tries to destroy the UNIX stream socket <path>. The socket must not be used
76
+ * anymore. It practises best effort, and no error is returned.
77
+ */
78
+ static void destroy_uxst_socket (const char * path )
79
+ {
80
+ struct sockaddr_un addr ;
81
+ int sock , ret ;
82
+
83
+ /* We might have been chrooted, so we may not be able to access the
84
+ * socket. In order to avoid bothering the other end, we connect with a
85
+ * wrong protocol, namely SOCK_DGRAM. The return code from connect()
86
+ * is enough to know if the socket is still live or not. If it's live
87
+ * in mode SOCK_STREAM, we get EPROTOTYPE or anything else but not
88
+ * ECONNREFUSED. In this case, we do not touch it because it's used
89
+ * by some other process.
90
+ */
91
+ sock = socket (PF_UNIX , SOCK_DGRAM , 0 );
92
+ if (sock < 0 )
93
+ return ;
94
+
95
+ addr .sun_family = AF_UNIX ;
96
+ strncpy (addr .sun_path , path , sizeof (addr .sun_path ));
97
+ addr .sun_path [sizeof (addr .sun_path ) - 1 ] = 0 ;
98
+ ret = connect (sock , (struct sockaddr * )& addr , sizeof (addr ));
99
+ if (ret < 0 && errno == ECONNREFUSED ) {
100
+ /* Connect failed: the socket still exists but is not used
101
+ * anymore. Let's remove this socket now.
102
+ */
103
+ unlink (path );
104
+ }
105
+ close (sock );
106
+ }
107
+
108
+
109
+ /********************************
110
+ * 2) listener-oriented functions
111
+ ********************************/
112
+
113
+
114
+ /* This function creates a UNIX socket associated to the listener. It changes
115
+ * the state from ASSIGNED to LISTEN. The socket is NOT enabled for polling.
116
+ * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
81
117
*/
82
- static int create_uxst_socket ( const char * path , uid_t uid , gid_t gid , mode_t mode , int backlog , char * errmsg , int errlen )
118
+ static int uxst_bind_listener ( struct listener * listener , char * errmsg , int errlen )
83
119
{
120
+ int fd ;
84
121
char tempname [MAXPATHLEN ];
85
122
char backname [MAXPATHLEN ];
86
123
struct sockaddr_un addr ;
87
124
const char * msg = NULL ;
125
+ const char * path ;
126
+
127
+ int ret ;
88
128
89
- int ret , sock ;
129
+ /* ensure we never return garbage */
130
+ if (errmsg && errlen )
131
+ * errmsg = 0 ;
132
+
133
+ if (listener -> state != LI_ASSIGNED )
134
+ return ERR_NONE ; /* already bound */
135
+
136
+ path = ((struct sockaddr_un * )& listener -> addr )-> sun_path ;
90
137
91
138
/* 1. create socket names */
92
139
if (!path [0 ]) {
@@ -128,35 +175,41 @@ static int create_uxst_socket(const char *path, uid_t uid, gid_t gid, mode_t mod
128
175
strncpy (addr .sun_path , tempname , sizeof (addr .sun_path ));
129
176
addr .sun_path [sizeof (addr .sun_path ) - 1 ] = 0 ;
130
177
131
- sock = socket (PF_UNIX , SOCK_STREAM , 0 );
132
- if (sock < 0 ) {
178
+ fd = socket (PF_UNIX , SOCK_STREAM , 0 );
179
+ if (fd < 0 ) {
133
180
msg = "cannot create UNIX socket" ;
134
181
goto err_unlink_back ;
135
182
}
136
183
137
- if (sock >= global .maxsock ) {
184
+ if (fd >= global .maxsock ) {
138
185
msg = "socket(): not enough free sockets, raise -n argument" ;
139
186
goto err_unlink_temp ;
140
187
}
141
-
142
- if (fcntl (sock , F_SETFL , O_NONBLOCK ) == -1 ) {
188
+
189
+ if (fcntl (fd , F_SETFL , O_NONBLOCK ) == -1 ) {
143
190
msg = "cannot make UNIX socket non-blocking" ;
144
191
goto err_unlink_temp ;
145
192
}
146
-
147
- if (bind (sock , (struct sockaddr * )& addr , sizeof (addr )) < 0 ) {
193
+
194
+ if (bind (fd , (struct sockaddr * )& addr , sizeof (addr )) < 0 ) {
148
195
/* note that bind() creates the socket <tempname> on the file system */
149
196
msg = "cannot bind UNIX socket" ;
150
197
goto err_unlink_temp ;
151
198
}
152
199
153
- if (((uid != -1 || gid != -1 ) && (chown (tempname , uid , gid ) == -1 )) ||
154
- (mode != 0 && chmod (tempname , mode ) == -1 )) {
200
+ /* <uid> and <gid> different of -1 will be used to change the socket owner.
201
+ * If <mode> is not 0, it will be used to restrict access to the socket.
202
+ * While it is known not to be portable on every OS, it's still useful
203
+ * where it works.
204
+ */
205
+ if (((listener -> perm .ux .uid != -1 || listener -> perm .ux .gid != -1 ) &&
206
+ (chown (tempname , listener -> perm .ux .uid , listener -> perm .ux .gid ) == -1 )) ||
207
+ (listener -> perm .ux .mode != 0 && chmod (tempname , listener -> perm .ux .mode ) == -1 )) {
155
208
msg = "cannot change UNIX socket ownership" ;
156
209
goto err_unlink_temp ;
157
210
}
158
211
159
- if (listen (sock , backlog ) < 0 ) {
212
+ if (listen (fd , listener -> backlog ? listener -> backlog : listener -> maxconn ) < 0 ) {
160
213
msg = "cannot listen to UNIX socket" ;
161
214
goto err_unlink_temp ;
162
215
}
@@ -174,87 +227,6 @@ static int create_uxst_socket(const char *path, uid_t uid, gid_t gid, mode_t mod
174
227
/* 6. cleanup */
175
228
unlink (backname ); /* no need to keep this one either */
176
229
177
- return sock ;
178
-
179
- err_rename :
180
- ret = rename (backname , path );
181
- if (ret < 0 && errno == ENOENT )
182
- unlink (path );
183
- err_unlink_temp :
184
- unlink (tempname );
185
- close (sock );
186
- err_unlink_back :
187
- unlink (backname );
188
- err_return :
189
- if (msg && errlen )
190
- snprintf (errmsg , errlen , "%s [%s]" , msg , path );
191
-
192
- return -1 ;
193
- }
194
-
195
- /* Tries to destroy the UNIX stream socket <path>. The socket must not be used
196
- * anymore. It practises best effort, and no error is returned.
197
- */
198
- static void destroy_uxst_socket (const char * path )
199
- {
200
- struct sockaddr_un addr ;
201
- int sock , ret ;
202
-
203
- /* We might have been chrooted, so we may not be able to access the
204
- * socket. In order to avoid bothering the other end, we connect with a
205
- * wrong protocol, namely SOCK_DGRAM. The return code from connect()
206
- * is enough to know if the socket is still live or not. If it's live
207
- * in mode SOCK_STREAM, we get EPROTOTYPE or anything else but not
208
- * ECONNREFUSED. In this case, we do not touch it because it's used
209
- * by some other process.
210
- */
211
- sock = socket (PF_UNIX , SOCK_DGRAM , 0 );
212
- if (sock < 0 )
213
- return ;
214
-
215
- addr .sun_family = AF_UNIX ;
216
- strncpy (addr .sun_path , path , sizeof (addr .sun_path ));
217
- addr .sun_path [sizeof (addr .sun_path ) - 1 ] = 0 ;
218
- ret = connect (sock , (struct sockaddr * )& addr , sizeof (addr ));
219
- if (ret < 0 && errno == ECONNREFUSED ) {
220
- /* Connect failed: the socket still exists but is not used
221
- * anymore. Let's remove this socket now.
222
- */
223
- unlink (path );
224
- }
225
- close (sock );
226
- }
227
-
228
-
229
- /********************************
230
- * 2) listener-oriented functions
231
- ********************************/
232
-
233
-
234
- /* This function creates the UNIX socket associated to the listener. It changes
235
- * the state from ASSIGNED to LISTEN. The socket is NOT enabled for polling.
236
- * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
237
- */
238
- static int uxst_bind_listener (struct listener * listener , char * errmsg , int errlen )
239
- {
240
- int fd ;
241
-
242
- /* ensure we never return garbage */
243
- if (errmsg && errlen )
244
- * errmsg = 0 ;
245
-
246
- if (listener -> state != LI_ASSIGNED )
247
- return ERR_NONE ; /* already bound */
248
-
249
- fd = create_uxst_socket (((struct sockaddr_un * )& listener -> addr )-> sun_path ,
250
- listener -> perm .ux .uid ,
251
- listener -> perm .ux .gid ,
252
- listener -> perm .ux .mode ,
253
- listener -> backlog ? listener -> backlog : listener -> maxconn ,
254
- errmsg , errlen );
255
- if (fd == -1 ) {
256
- return ERR_FATAL | ERR_ALERT ;
257
- }
258
230
/* the socket is now listening */
259
231
listener -> fd = fd ;
260
232
listener -> state = LI_LISTEN ;
@@ -269,6 +241,19 @@ static int uxst_bind_listener(struct listener *listener, char *errmsg, int errle
269
241
fdinfo [fd ].peeraddr = NULL ;
270
242
fdinfo [fd ].peerlen = 0 ;
271
243
return ERR_NONE ;
244
+ err_rename :
245
+ ret = rename (backname , path );
246
+ if (ret < 0 && errno == ENOENT )
247
+ unlink (path );
248
+ err_unlink_temp :
249
+ unlink (tempname );
250
+ close (fd );
251
+ err_unlink_back :
252
+ unlink (backname );
253
+ err_return :
254
+ if (msg && errlen )
255
+ snprintf (errmsg , errlen , "%s [%s]" , msg , path );
256
+ return ERR_FATAL | ERR_ALERT ;
272
257
}
273
258
274
259
/* This function closes the UNIX sockets for the specified listener.
0 commit comments