]>
Commit | Line | Data |
---|---|---|
d4697bc9 | 1 | /* Copyright (C) 1992-2014 Free Software Foundation, Inc. |
ebbad4cc | 2 | This file is part of the GNU C Library. |
28f540f4 | 3 | |
ebbad4cc | 4 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
28f540f4 | 8 | |
ebbad4cc UD |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 12 | Lesser General Public License for more details. |
28f540f4 | 13 | |
41bdb6e2 | 14 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
15 | License along with the GNU C Library; if not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
28f540f4 | 17 | |
28f540f4 RM |
18 | #include <errno.h> |
19 | #include <sys/socket.h> | |
20 | #include <hurd.h> | |
21 | #include <hurd/fd.h> | |
22 | #include <hurd/socket.h> | |
23 | #include <hurd/paths.h> | |
24 | #include <fcntl.h> | |
25 | #include <stddef.h> | |
26 | #include <hurd/ifsock.h> | |
27 | #include <sys/un.h> | |
28 | #include <string.h> | |
29 | ||
30 | /* Give the socket FD the local address ADDR (which is LEN bytes long). */ | |
31 | int | |
b2bffca2 | 32 | __bind (int fd, __CONST_SOCKADDR_ARG addrarg, socklen_t len) |
28f540f4 RM |
33 | { |
34 | addr_port_t aport; | |
35 | error_t err; | |
d6765f1d | 36 | const struct sockaddr_un *addr = addrarg.__sockaddr_un__; |
28f540f4 | 37 | |
be7e3b7e | 38 | if (addr->sun_family == AF_LOCAL) |
28f540f4 RM |
39 | { |
40 | /* For the local domain, we must create a node in the filesystem | |
41 | using the ifsock translator and then fetch the address from it. */ | |
28f540f4 | 42 | file_t dir, node; |
6d5cbf7b MB |
43 | char name[len - offsetof (struct sockaddr_un, sun_path) + 1], *n; |
44 | ||
45 | strncpy (name, addr->sun_path, sizeof name - 1); | |
46 | name[sizeof name - 1] = '\0'; /* Make sure */ | |
47 | ||
28f540f4 RM |
48 | dir = __file_name_split (name, &n); |
49 | if (dir == MACH_PORT_NULL) | |
50 | return -1; | |
be7e3b7e | 51 | |
28f540f4 RM |
52 | /* Create a new, unlinked node in the target directory. */ |
53 | err = __dir_mkfile (dir, O_CREAT, 0666 & ~_hurd_umask, &node); | |
54 | ||
55 | if (! err) | |
56 | { | |
28f540f4 | 57 | /* Set the node's translator to make it a local-domain socket. */ |
be7e3b7e | 58 | err = __file_set_translator (node, |
28f540f4 RM |
59 | FS_TRANS_EXCL | FS_TRANS_SET, |
60 | FS_TRANS_EXCL | FS_TRANS_SET, 0, | |
61 | _HURD_IFSOCK, sizeof _HURD_IFSOCK, | |
62 | MACH_PORT_NULL, | |
63 | MACH_MSG_TYPE_COPY_SEND); | |
221c5084 | 64 | if (! err) |
be7e3b7e RM |
65 | { |
66 | /* Link the node, now a socket, into the target directory. */ | |
0e3426bb | 67 | err = __dir_link (dir, node, n, 1); |
be7e3b7e RM |
68 | if (err == EEXIST) |
69 | err = EADDRINUSE; | |
70 | } | |
924b9ff6 | 71 | __mach_port_deallocate (__mach_task_self (), node); |
28f540f4 | 72 | if (! err) |
221c5084 | 73 | { |
924b9ff6 | 74 | /* Get a port to the ifsock translator. */ |
a4969614 | 75 | file_t ifsock = __file_name_lookup_under (dir, n, 0, 0); |
924b9ff6 | 76 | if (ifsock == MACH_PORT_NULL) |
221c5084 | 77 | { |
924b9ff6 RM |
78 | err = errno; |
79 | /* If we failed, get rid of the node we created. */ | |
80 | __dir_unlink (dir, n); | |
221c5084 | 81 | } |
a4969614 RM |
82 | else |
83 | { | |
84 | /* Get the address port. */ | |
85 | err = __ifsock_getsockaddr (ifsock, &aport); | |
86 | if (err == MIG_BAD_ID || err == EOPNOTSUPP) | |
87 | /* We are not talking to /hurd/ifsock. Probably | |
88 | someone came in after we linked our node, unlinked | |
89 | it, and replaced it with a different node, before we | |
90 | did our lookup. Treat it as if our link had failed | |
91 | with EEXIST. */ | |
92 | err = EADDRINUSE; | |
93 | } | |
94 | __mach_port_deallocate (__mach_task_self (), ifsock); | |
221c5084 | 95 | } |
28f540f4 RM |
96 | } |
97 | __mach_port_deallocate (__mach_task_self (), dir); | |
98 | ||
99 | if (err) | |
100 | return __hurd_fail (err); | |
101 | } | |
102 | else | |
103 | err = EIEIO; | |
104 | ||
105 | err = HURD_DPORT_USE (fd, | |
106 | ({ | |
107 | if (err) | |
108 | err = __socket_create_address (port, | |
be7e3b7e | 109 | addr->sun_family, |
28f540f4 | 110 | (char *) addr, len, |
853f0eea | 111 | &aport); |
28f540f4 RM |
112 | if (! err) |
113 | { | |
114 | err = __socket_bind (port, aport); | |
115 | __mach_port_deallocate (__mach_task_self (), | |
116 | aport); | |
117 | } | |
118 | err; | |
119 | })); | |
120 | ||
121 | return err ? __hurd_dfail (fd, err) : 0; | |
122 | } | |
b2bffca2 UD |
123 | |
124 | weak_alias (__bind, bind) |