nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* source: xio-unix.c */
2 /* Copyright Gerhard Rieger */
3 /* Published under the GNU General Public License V.2, see file COPYING */
4  
5 /* this file contains the source for opening addresses of UNIX socket type */
6  
7 #include "xiosysincludes.h"
8 #include "xioopen.h"
9  
10 #include "xio-socket.h"
11 #include "xio-listen.h"
12 #include "xio-unix.h"
13 #include "xio-named.h"
14  
15  
16 #if WITH_UNIX
17  
18 /* to avoid unneccessary "live" if () conditionals when no abstract support is
19 compiled in (or at least to give optimizing compilers a good chance) we need
20 a constant that can be used in C expressions */
21 #if WITH_ABSTRACT_UNIXSOCKET
22 # define ABSTRACT 1
23 #else
24 # define ABSTRACT 0
25 #endif
26 static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3);
27 static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3);
28 static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3);
29 static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3);
30 static
31 int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
32 int xioflags, xiofile_t *xxfd, unsigned groups,
33 int abstract, int dummy2, int dummy3);
34 static
35 int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3);
36  
37 /* the first free parameter is 0 for "normal" unix domain sockets, or 1 for
38 abstract unix sockets (Linux); the second and third parameters are unsused */
39 static const struct xioaddr_endpoint_desc xioendpoint_unix_connect1 = { XIOADDR_SYS, "unix-connect", 1, XIOBIT_ALL, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_connect, 0, 0, 0 HELP(":<filename>") };
40 const union xioaddr_desc *xioaddrs_unix_connect[] = { (union xioaddr_desc *)&xioendpoint_unix_connect1, NULL };
41  
42 #if WITH_LISTEN
43 static const struct xioaddr_endpoint_desc xioendpoint_unix_listen1 = { XIOADDR_SYS, "unix-listen", 1, XIOBIT_ALL, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_listen, 0, 0, 0 HELP(":<filename>") };
44 const union xioaddr_desc *xioaddrs_unix_listen[] = { (union xioaddr_desc *)&xioendpoint_unix_listen1, NULL };
45 #endif /* WITH_LISTEN */
46  
47 static const struct xioaddr_endpoint_desc xioendpoint_unix_sendto1 = { XIOADDR_SYS, "unix-sendto", 1, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_sendto, 0, 0, 0 HELP(":<filename>") };
48 const union xioaddr_desc *xioaddrs_unix_sendto[] = { (union xioaddr_desc *)&xioendpoint_unix_sendto1, NULL };
49  
50 static const struct xioaddr_endpoint_desc xioendpoint_unix_recvfrom1= { XIOADDR_SYS, "unix-recvfrom",1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_unix_recvfrom, 0, 0, 0 HELP(":<filename>") };
51 const union xioaddr_desc *xioaddrs_unix_recvfrom[]= { (union xioaddr_desc *)&xioendpoint_unix_recvfrom1, NULL };
52  
53 static const struct xioaddr_endpoint_desc xioendpoint_unix_recv1 = { XIOADDR_SYS, "unix-recv", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_unix_recv, 0, 0, 0 HELP(":<filename>") };
54 const union xioaddr_desc *xioaddrs_unix_recv[] = { (union xioaddr_desc *)&xioendpoint_unix_recv1, NULL };
55  
56 static const struct xioaddr_endpoint_desc xioendpoint_unix_client1 = { XIOADDR_SYS, "unix-client", 1, XIOBIT_ALL, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_client, 0, 0, 0 HELP(":<filename>") };
57 const union xioaddr_desc *xioaddrs_unix_client[] = { (union xioaddr_desc *)&xioendpoint_unix_client1, NULL };
58  
59 #if WITH_ABSTRACT_UNIXSOCKET
60 static const struct xioaddr_endpoint_desc xioendpoint_abstract_connect1 = { XIOADDR_SYS, "abstract-connect", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_connect, 1, 0, 0 HELP(":<filename>") };
61 const union xioaddr_desc *xioaddrs_abstract_connect[] = { (union xioaddr_desc *)&xioendpoint_abstract_connect1, NULL };
62 #if WITH_LISTEN
63 static const struct xioaddr_endpoint_desc xioendpoint_abstract_listen1 = { XIOADDR_SYS, "abstract-listen", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_listen, 1, 0, 0 HELP(":<filename>") };
64 const union xioaddr_desc *xioaddrs_abstract_listen[] = { (union xioaddr_desc *)&xioendpoint_abstract_listen1, NULL };
65 #endif /* WITH_LISTEN */
66 static const struct xioaddr_endpoint_desc xioendpoint_abstract_sendto1 = { XIOADDR_SYS, "abstract-sendto", 1, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_sendto, 1, 0, 0 HELP(":<filename>") };
67 const union xioaddr_desc *xioaddrs_abstract_sendto[] = { (union xioaddr_desc *)&xioendpoint_abstract_sendto1, NULL };
68 static const struct xioaddr_endpoint_desc xioendpoint_abstract_recvfrom1= { XIOADDR_SYS, "abstract-recvfrom", 1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_unix_recvfrom, 1, 0, 0 HELP(":<filename>") };
69 const union xioaddr_desc *xioaddrs_abstract_recvfrom[] = { (union xioaddr_desc *)&xioendpoint_abstract_recvfrom1, NULL };
70 static const struct xioaddr_endpoint_desc xioendpoint_abstract_recv1 = { XIOADDR_SYS, "abstract-recv", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_unix_recv, 1, 0, 0 HELP(":<filename>") };
71 const union xioaddr_desc *xioaddrs_abstract_recv[] = { (union xioaddr_desc *)&xioendpoint_abstract_recv1, NULL };
72 static const struct xioaddr_endpoint_desc xioendpoint_abstract_client1 = { XIOADDR_SYS, "abstract-client", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_client, 1, 0, 0 HELP(":<filename>") };
73 const union xioaddr_desc *xioaddrs_abstract_client[] = { (union xioaddr_desc *)&xioendpoint_abstract_client1, NULL };
74 #endif /* WITH_ABSTRACT_UNIXSOCKET */
75  
76 const struct optdesc xioopt_unix_tightsocklen = { "unix-tightsocklen", "tightsocklen", OPT_UNIX_TIGHTSOCKLEN, GROUP_SOCK_UNIX, PH_PREBIND, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.un.tight), XIO_SIZEOF(para.socket.un.tight) };
77  
78  
79 /* fills the socket address struct and returns its effective length.
80 abstract is usually 0; != 0 generates an abstract socket address on Linux.
81 tight!=0 calculates the resulting length from the path length, not from the
82 structures length; this is more common (see option unix-tightsocklen)
83 the struct need not be initialized when calling this function.
84 */
85 socklen_t
86 xiosetunix(int pf,
87 struct sockaddr_un *saun,
88 const char *path,
89 bool abstract,
90 bool tight) {
91 size_t pathlen;
92 socklen_t len;
93  
94 socket_un_init(saun);
95 #ifdef WITH_ABSTRACT_UNIXSOCKET
96 if (abstract) {
97 if ((pathlen = strlen(path)) >= sizeof(saun->sun_path)) {
98 Warn2("socket address "F_Zu" characters long, truncating to "F_Zu"",
99 pathlen+1, sizeof(saun->sun_path));
100 }
101 saun->sun_path[0] = '\0'; /* so it's abstract */
102 strncpy(saun->sun_path+1, path, sizeof(saun->sun_path)-1); /* ok */
103 if (tight) {
104 len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+
105 MIN(pathlen+1, sizeof(saun->sun_path));
106 #if HAVE_STRUCT_SOCKADDR_SALEN
107 saun->sun_len = len;
108 #endif
109 } else {
110 len = sizeof(struct sockaddr_un);
111 }
112 return len;
113 }
114 #endif /* WITH_ABSTRACT_UNIXSOCKET */
115  
116 if ((pathlen = strlen(path)) > sizeof(saun->sun_path)) {
117 Warn2("unix socket address "F_Zu" characters long, truncating to "F_Zu"",
118 pathlen, sizeof(saun->sun_path));
119 }
120 strncpy(saun->sun_path, path, sizeof(saun->sun_path)); /* ok */
121 if (tight) {
122 len = sizeof(struct sockaddr_un)-sizeof(saun->sun_path)+
123 MIN(pathlen, sizeof(saun->sun_path));
124 #if HAVE_STRUCT_SOCKADDR_SALEN
125 saun->sun_len = len;
126 #endif
127 } else {
128 len = sizeof(struct sockaddr_un);
129 }
130 return len;
131 }
132  
133 #if WITH_LISTEN
134 static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) {
135 /* we expect the form: filename */
136 const char *name;
137 xiosingle_t *xfd = &xxfd->stream;
138 int pf = PF_UNIX;
139 int socktype = SOCK_STREAM;
140 int protocol = 0;
141 struct sockaddr_un us;
142 socklen_t uslen;
143 struct opt *opts0 = NULL;
144 pid_t pid = Getpid();
145 bool opt_unlink_early = false;
146 bool opt_unlink_close = true;
147 int result;
148  
149 if (argc != 2) {
150 Error2("%s: wrong number of parameters (%d instead of 1)",
151 argv[0], argc-1);
152 return STAT_NORETRY;
153 }
154 name = argv[1];
155  
156 xfd->para.socket.un.tight = true;
157 retropt_socket_pf(opts, &pf);
158  
159 if (!(ABSTRACT && abstract)) {
160 /* only for non abstract because abstract do not work in file system */
161 retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
162 retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
163 }
164  
165 if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
166 applyopts(-1, opts, PH_INIT);
167 applyopts_named(name, opts, PH_EARLY); /* umask! */
168 applyopts_offset(xfd, opts);
169 applyopts(-1, opts, PH_EARLY);
170  
171 uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight);
172  
173 if (!(ABSTRACT && abstract)) {
174 if (opt_unlink_early) {
175 if (Unlink(name) < 0) {
176 if (errno == ENOENT) {
177 Warn2("unlink(\"%s\"): %s", name, strerror(errno));
178 } else {
179 Error2("unlink(\"%s\"): %s", name, strerror(errno));
180 }
181 }
182 } else {
183 struct stat buf;
184 if (Lstat(name, &buf) == 0) {
185 Error1("\"%s\" exists", name);
186 return STAT_RETRYLATER;
187 }
188 }
189 if (opt_unlink_close) {
190 if ((xfd->unlink_close = strdup(name)) == NULL) {
191 Error1("strdup(\"%s\"): out of memory", name);
192 }
193 xfd->opt_unlink_close = true;
194 }
195  
196 /* trying to set user-early, perm-early etc. here is useless because
197 file system entry is available only past bind() call. */
198 }
199  
200 opts0 = copyopts(opts, GROUP_ALL);
201  
202 /* this may fork() */
203 if ((result =
204 xioopen_listen(xfd, xioflags,
205 (struct sockaddr *)&us, uslen,
206 opts, opts0, pf, socktype, protocol))
207 != 0)
208 return result;
209  
210 if (!(ABSTRACT && abstract)) {
211 if (opt_unlink_close) {
212 if (pid != Getpid()) {
213 /* in a child process - do not unlink-close here! */
214 xfd->opt_unlink_close = false;
215 }
216 }
217 }
218  
219 return 0;
220 }
221 #endif /* WITH_LISTEN */
222  
223  
224 static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) {
225 /* we expect the form: filename */
226 const char *name;
227 struct single *xfd = &xxfd->stream;
228 int rw = (xioflags&XIO_ACCMODE);
229 int pf = PF_UNIX;
230 int socktype = SOCK_STREAM;
231 int protocol = 0;
232 struct sockaddr_un them, us;
233 socklen_t themlen, uslen = sizeof(us);
234 bool needbind = false;
235 bool opt_unlink_close = false;
236 int result;
237  
238 if (argc != 2) {
239 Error2("%s: wrong number of parameters (%d instead of 1)",
240 argv[0], argc-1);
241 return STAT_NORETRY;
242 }
243  
244 name = argv[1];
245  
246 xfd->para.socket.un.tight = true;
247 retropt_socket_pf(opts, &pf);
248 xfd->howtoshut = XIOSHUT_DOWN;
249 if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
250 applyopts(-1, opts, PH_INIT);
251 applyopts_offset(xfd, opts);
252 applyopts(-1, opts, PH_EARLY);
253  
254 themlen = xiosetunix(pf, &them, name, abstract, xfd->para.socket.un.tight);
255 if (!(ABSTRACT && abstract)) {
256 /* only for non abstract because abstract do not work in file system */
257 retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
258 }
259 if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
260 (abstract<<1)|xfd->para.socket.un.tight, 0, 0) == STAT_OK) {
261 needbind = true;
262 }
263  
264 if (opt_unlink_close) {
265 if ((xfd->unlink_close = strdup(name)) == NULL) {
266 Error1("strdup(\"%s\"): out of memory", name);
267 }
268 xfd->opt_unlink_close = true;
269 }
270  
271 if ((result =
272 xioopen_connect(xfd,
273 needbind?(struct sockaddr *)&us:NULL, uslen,
274 (struct sockaddr *)&them, themlen,
275 opts, pf, socktype, protocol, false)) != 0) {
276 return result;
277 }
278 if (XIOWITHWR(rw)) xfd->wfd = xfd->rfd;
279 if (!XIOWITHRD(rw)) xfd->rfd = -1;
280 if ((result = _xio_openlate(xfd, opts)) < 0) {
281 return result;
282 }
283 return STAT_OK;
284 }
285  
286  
287 /*
288 returns the resulting FD in xfd->rfd, independend of xioflags
289 */
290 static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy, int dummy3) {
291 /* we expect the form: filename */
292 const char *name;
293 xiosingle_t *xfd = &xxfd->stream;
294 int rw = (xioflags&XIO_ACCMODE);
295 int pf = PF_UNIX;
296 int socktype = SOCK_DGRAM;
297 int protocol = 0;
298 union sockaddr_union us;
299 socklen_t uslen = sizeof(us);
300 bool needbind = false;
301 bool opt_unlink_close = false;
302 int result;
303  
304 if (argc != 2) {
305 Error2("%s: wrong number of parameters (%d instead of 1)",
306 argv[0], argc-1);
307 return STAT_NORETRY;
308 }
309  
310 uslen = socket_init(pf, &us);
311 xfd->salen = socket_init(pf, &xfd->peersa);
312  
313 retropt_int(opts, OPT_SO_TYPE, &socktype);
314  
315 name = argv[1];
316  
317 xfd->para.socket.un.tight = true;
318 retropt_socket_pf(opts, &pf);
319 applyopts_offset(xfd, opts);
320  
321 xfd->salen = xiosetunix(pf, &xfd->peersa.un, name, abstract, xfd->para.socket.un.tight);
322  
323 if (!(ABSTRACT && abstract)) {
324 /* only for non abstract because abstract do not work in file system */
325 retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
326 }
327  
328 xfd->dtype = XIODATA_RECVFROM;
329  
330 if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
331 (abstract<<1)| xfd->para.socket.un.tight, 0, 0) == STAT_OK) {
332 needbind = true;
333 }
334  
335 if (opt_unlink_close) {
336 if ((xfd->unlink_close = strdup(name)) == NULL) {
337 Error1("strdup(\"%s\"): out of memory", name);
338 }
339 xfd->opt_unlink_close = true;
340 }
341  
342 if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
343 applyopts(-1, opts, PH_INIT);
344  
345 if ((result =
346 _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
347 opts, xioflags, xfd, groups,
348 pf, socktype, protocol)) != STAT_OK) {
349 return result;
350 }
351 if (XIOWITHWR(rw)) xfd->wfd = xfd->rfd;
352 if (!XIOWITHRD(rw)) xfd->rfd = -1;
353 return STAT_OK;
354 }
355  
356  
357 static
358 int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
359 int xioflags, xiofile_t *xxfd, unsigned groups,
360 int abstract, int dummy2, int dummy3) {
361 /* we expect the form: filename */
362 const char *name;
363 xiosingle_t *xfd = &xxfd->stream;
364 int pf = PF_UNIX;
365 int socktype = SOCK_DGRAM;
366 int protocol = 0;
367 struct sockaddr_un us;
368 socklen_t uslen;
369 bool needbind = true;
370 bool opt_unlink_early = false;
371 bool opt_unlink_close = true;
372  
373 if (argc != 2) {
374 Error2("%s: wrong number of parameters (%d instead of 1)",
375 argv[0], argc-1);
376 return STAT_NORETRY;
377 }
378 name = argv[1];
379  
380 xfd->para.socket.un.tight = true;
381 retropt_socket_pf(opts, &pf);
382 retropt_int(opts, OPT_SO_TYPE, &socktype);
383  
384 if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
385 applyopts(-1, opts, PH_INIT);
386 applyopts_named(name, opts, PH_EARLY); /* umask! */
387 applyopts_offset(xfd, opts);
388 retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
389 retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
390  
391 if (!(ABSTRACT && abstract)) {
392 /* only for non abstract because abstract do not work in file system */
393 retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
394 retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
395 }
396 applyopts(-1, opts, PH_EARLY);
397  
398 uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight);
399  
400 #if 0
401 if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen,
402 (abstract<<1)|xfd->para.socket.un.tight, 0, 0) == STAT_OK) {
403 }
404 #endif
405  
406 if (!(ABSTRACT && abstract)) {
407 if (opt_unlink_early) {
408 if (Unlink(name) < 0) {
409 if (errno == ENOENT) {
410 Warn2("unlink(\"%s\"): %s", name, strerror(errno));
411 } else {
412 Error2("unlink(\"%s\"): %s", name, strerror(errno));
413 }
414 }
415 } else {
416 struct stat buf;
417 if (Lstat(name, &buf) == 0) {
418 Error1("\"%s\" exists", name);
419 return STAT_RETRYLATER;
420 }
421 }
422 if (opt_unlink_close) {
423 if ((xfd->unlink_close = strdup(name)) == NULL) {
424 Error1("strdup(\"%s\"): out of memory", name);
425 }
426 xfd->opt_unlink_close = true;
427 }
428  
429 /* trying to set user-early, perm-early etc. here is useless because
430 file system entry is available only past bind() call. */
431 }
432 applyopts_named(name, opts, PH_EARLY); /* umask! */
433  
434 xfd->para.socket.la.soa.sa_family = pf;
435  
436 xfd->dtype = XIODATA_RECVFROM_ONE;
437  
438 /* this may fork */
439 return
440 _xioopen_dgram_recvfrom(xfd, xioflags,
441 needbind?(struct sockaddr *)&us:NULL, uslen,
442 opts, pf, socktype, protocol, E_ERROR);
443 }
444  
445  
446 static
447 int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
448 int xioflags, xiofile_t *xxfd, unsigned groups,
449 int abstract, int dummy2, int dummy3) {
450 /* we expect the form: filename */
451 const char *name;
452 xiosingle_t *xfd = &xxfd->stream;
453 int pf = PF_UNIX;
454 int socktype = SOCK_DGRAM;
455 int protocol = 0;
456 union sockaddr_union us;
457 socklen_t uslen;
458 bool opt_unlink_early = false;
459 bool opt_unlink_close = true;
460 int result;
461  
462 if (argc != 2) {
463 Error2("%s: wrong number of parameters (%d instead of 1)",
464 argv[0], argc-1);
465 return STAT_NORETRY;
466 }
467 name = argv[1];
468  
469 xfd->para.socket.un.tight = true;
470 retropt_socket_pf(opts, &pf);
471 if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
472 applyopts(-1, opts, PH_INIT);
473 applyopts_named(name, opts, PH_EARLY); /* umask! */
474 applyopts_offset(xfd, opts);
475  
476 if (!(ABSTRACT && abstract)) {
477 /* only for non abstract because abstract do not work in file system */
478 retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
479 retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
480  
481 }
482 applyopts(-1, opts, PH_EARLY);
483  
484 uslen = xiosetunix(pf, &us.un, name, abstract, xfd->para.socket.un.tight);
485  
486 #if 0
487 if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
488 (abstract<<1)|xfd->para.socket.un.tight, 0, 0)
489 == STAT_OK) {
490 }
491 #endif
492  
493 if (!(ABSTRACT && abstract)) {
494 if (opt_unlink_early) {
495 if (Unlink(name) < 0) {
496 if (errno == ENOENT) {
497 Warn2("unlink(\"%s\"): %s", name, strerror(errno));
498 } else {
499 Error2("unlink(\"%s\"): %s", name, strerror(errno));
500 }
501 }
502 } else {
503 struct stat buf;
504 if (Lstat(name, &buf) == 0) {
505 Error1("\"%s\" exists", name);
506 return STAT_RETRYLATER;
507 }
508 }
509 if (opt_unlink_close) {
510 if ((xfd->unlink_close = strdup(name)) == NULL) {
511 Error1("strdup(\"%s\"): out of memory", name);
512 }
513 xfd->opt_unlink_close = true;
514 }
515 }
516 applyopts_named(name, opts, PH_EARLY); /* umask! */
517  
518 xfd->para.socket.la.soa.sa_family = pf;
519  
520 xfd->dtype = XIODATA_RECV;
521 result = _xioopen_dgram_recv(xfd, xioflags, &us.soa, uslen,
522 opts, pf, socktype, protocol, E_ERROR);
523 return result;
524 }
525  
526  
527 static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) {
528 /* we expect the form: filename */
529 if (argc != 2) {
530 Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
531 }
532  
533 return
534 _xioopen_unix_client(&xxfd->stream, xioflags, groups, abstract, opts,
535 argv[1]);
536 }
537  
538 /* establishes communication with an existing UNIX type socket. supports stream
539 and datagram socket types: first tries to connect(), but when this fails it
540 falls back to sendto().
541 applies and consumes the following option:
542 PH_INIT, PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND,
543 PH_CONNECTED, PH_LATE, ?PH_CONNECT
544 OFUNC_OFFSET,
545 OPT_PROTOCOL_FAMILY, OPT_UNIX_TIGHTSOCKLEN, OPT_UNLINK_CLOSE, OPT_BIND,
546 OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_CLOEXEC, OPT_USER, OPT_GROUP, ?OPT_FORK,
547 */
548 int
549 _xioopen_unix_client(xiosingle_t *xfd, int xioflags, unsigned groups,
550 int abstract, struct opt *opts, const char *name) {
551 int rw = (xioflags&XIO_ACCMODE);
552 int pf = PF_UNIX;
553 int socktype = 0; /* to be determined by server socket type */
554 int protocol = 0;
555 union sockaddr_union them, us;
556 socklen_t themlen, uslen = sizeof(us);
557 bool needbind = false;
558 bool opt_unlink_close = false;
559 struct opt *opts0;
560 int result;
561  
562 xfd->para.socket.un.tight = true;
563 retropt_socket_pf(opts, &pf);
564 if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
565 applyopts(-1, opts, PH_INIT);
566 applyopts_offset(xfd, opts);
567 applyopts(-1, opts, PH_EARLY);
568  
569 themlen = xiosetunix(pf, &them.un, name, abstract, xfd->para.socket.un.tight);
570 if (!(ABSTRACT && abstract)) {
571 /* only for non abstract because abstract do not work in file system */
572 retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
573 }
574 if (retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen,
575 (abstract<<1)|xfd->para.socket.un.tight, 0, 0)
576 != STAT_NOACTION) {
577 needbind = true;
578 }
579  
580 if (opt_unlink_close) {
581 if ((xfd->unlink_close = strdup(name)) == NULL) {
582 Error1("strdup(\"%s\"): out of memory", name);
583 }
584 xfd->opt_unlink_close = true;
585 }
586  
587 /* save options, because we might have to start again */
588 opts0 = copyopts(opts, GROUP_ALL);
589  
590 /* xfd->dtype = DATA_STREAM; // is default */
591 if ((result =
592 xioopen_connect(xfd,
593 needbind?(struct sockaddr *)&us:NULL, uslen,
594 (struct sockaddr *)&them, themlen,
595 opts, pf, socktype?socktype:SOCK_STREAM, protocol,
596 false)) != 0) {
597 if (errno == EPROTOTYPE) {
598 if (needbind) {
599 Unlink(us.un.sun_path);
600 }
601  
602 dropopts2(opts, PH_INIT, PH_SPEC); opts = opts0;
603  
604 xfd->peersa = them;
605 xfd->salen = sizeof(struct sockaddr_un);
606 if ((result =
607 _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
608 opts, xioflags, xfd, groups,
609 pf, socktype?socktype:SOCK_DGRAM, protocol))
610 != 0) {
611 return result;
612 }
613 xfd->dtype = XIODATA_RECVFROM;
614 }
615 }
616 if (XIOWITHWR(rw)) xfd->wfd = xfd->rfd;
617 if (!XIOWITHRD(rw)) xfd->rfd = -1;
618 if ((result = _xio_openlate(xfd, opts)) < 0) {
619 return result;
620 }
621 return 0;
622 }
623  
624  
625 /* returns information that can be used for constructing an environment
626 variable describing the socket address.
627 if idx is 0, this function writes "ADDR" into namebuff and the path into
628 valuebuff, and returns 0 (which means that no more info is there).
629 if idx is != 0, it returns -1
630 namelen and valuelen contain the max. allowed length of output chars in the
631 respective buffer.
632 on error this function returns -1.
633 */
634 int
635 xiosetsockaddrenv_unix(int idx, char *namebuff, size_t namelen,
636 char *valuebuff, size_t valuelen,
637 struct sockaddr_un *sa, socklen_t salen, int ipproto) {
638 if (idx != 0) {
639 return -1;
640 }
641 strcpy(namebuff, "ADDR");
642 sockaddr_unix_info(sa, salen, valuebuff, valuelen);
643 return 0;
644 }
645  
646 #endif /* WITH_UNIX */