2 Unix SMB/CIFS implementation.
4 unix domain socket functions
6 Copyright (C) Stefan Metzmacher 2004
7 Copyright (C) Andrew Tridgell 2004
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 approximate errno mapping
31 static NTSTATUS unixdom_error(int ernum)
39 return NT_STATUS_INVALID_PARAMETER;
42 return STATUS_MORE_ENTRIES;
44 return NT_STATUS_CONNECTION_REFUSED;
47 return NT_STATUS_NO_MEMORY;
50 return NT_STATUS_INSUFFICIENT_RESOURCES;
52 return NT_STATUS_CONNECTION_DISCONNECTED;
54 return NT_STATUS_INVALID_BUFFER_SIZE;
57 return NT_STATUS_UNSUCCESSFUL;
60 static NTSTATUS unixdom_init(struct socket_context *sock)
62 sock->fd = socket(PF_UNIX, SOCK_STREAM, 0);
64 return NT_STATUS_INSUFFICIENT_RESOURCES;
66 sock->private_data = NULL;
71 static void unixdom_close(struct socket_context *sock)
74 /* if we were listening, then don't leave the socket lying
75 around in the filesystem */
78 /* FIXME - this doesn't work after fork(), etc */
79 if (sock->private_data) {
80 unlink((const char *)sock->private_data);
85 static NTSTATUS unixdom_connect(struct socket_context *sock,
86 const char *my_address, int my_port,
87 const char *srv_address, int srv_port,
90 struct sockaddr_un srv_addr;
93 if (strlen(srv_address)+1 > sizeof(srv_addr.sun_path)) {
94 return NT_STATUS_INVALID_PARAMETER;
97 ZERO_STRUCT(srv_addr);
98 srv_addr.sun_family = AF_UNIX;
99 strncpy(srv_addr.sun_path, srv_address, sizeof(srv_addr.sun_path));
101 if (!(flags & SOCKET_FLAG_BLOCK)) {
102 ret = set_blocking(sock->fd, False);
104 return NT_STATUS_INVALID_PARAMETER;
108 ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr));
110 return unixdom_error(errno);
113 sock->state = SOCKET_STATE_CLIENT_CONNECTED;
118 static NTSTATUS unixdom_listen(struct socket_context *sock,
119 const char *my_address, int port,
120 int queue_size, uint32_t flags)
122 struct sockaddr_un my_addr;
125 if (strlen(my_address)+1 > sizeof(my_addr.sun_path)) {
126 return NT_STATUS_INVALID_PARAMETER;
129 /* delete if it already exists */
132 ZERO_STRUCT(my_addr);
133 my_addr.sun_family = AF_UNIX;
134 strncpy(my_addr.sun_path, my_address, sizeof(my_addr.sun_path));
136 ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
138 return unixdom_error(errno);
141 ret = listen(sock->fd, queue_size);
143 return unixdom_error(errno);
146 if (!(flags & SOCKET_FLAG_BLOCK)) {
147 ret = set_blocking(sock->fd, False);
149 return unixdom_error(errno);
153 sock->state = SOCKET_STATE_SERVER_LISTEN;
154 sock->private_data = (void *)talloc_strdup(sock, my_address);
159 static NTSTATUS unixdom_accept(struct socket_context *sock,
160 struct socket_context **new_sock,
163 struct sockaddr_un cli_addr;
164 socklen_t cli_addr_len = sizeof(cli_addr);
167 new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len);
169 return unixdom_error(errno);
172 (*new_sock) = talloc_p(NULL, struct socket_context);
175 return NT_STATUS_NO_MEMORY;
178 /* copy the socket_context */
179 (*new_sock)->type = sock->type;
180 (*new_sock)->state = SOCKET_STATE_SERVER_CONNECTED;
181 (*new_sock)->flags = flags;
183 (*new_sock)->fd = new_fd;
185 (*new_sock)->private_data = NULL;
186 (*new_sock)->ops = sock->ops;
191 static NTSTATUS unixdom_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
192 DATA_BLOB *blob, size_t wantlen, uint32_t flags)
198 buf = talloc(mem_ctx, wantlen);
200 return NT_STATUS_NO_MEMORY;
203 /* TODO: we need to map all flags here */
204 if (flags & SOCKET_FLAG_PEEK) {
208 if (!(flags & SOCKET_FLAG_BLOCK)) {
209 flgs |= MSG_DONTWAIT;
212 if (flags & SOCKET_FLAG_BLOCK) {
216 gotlen = recv(sock->fd, buf, wantlen, flgs);
219 return NT_STATUS_END_OF_FILE;
220 } else if (gotlen == -1) {
221 NTSTATUS status = unixdom_error(errno);
226 blob->length = gotlen;
227 blob->data = talloc_realloc(mem_ctx, buf, gotlen);
229 return NT_STATUS_NO_MEMORY;
235 static NTSTATUS unixdom_send(struct socket_context *sock, TALLOC_CTX *mem_ctx,
236 const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
243 /* TODO: we need to map all flags here */
244 if (!(flags & SOCKET_FLAG_BLOCK)) {
245 flgs |= MSG_DONTWAIT;
248 len = send(sock->fd, blob->data, blob->length, flgs);
250 return unixdom_error(errno);
258 static NTSTATUS unixdom_set_option(struct socket_context *sock,
259 const char *option, const char *val)
261 set_socket_options(sock->fd, option);
265 static char *unixdom_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
267 return talloc_strdup(mem_ctx, "LOCAL/unixdom");
270 static char *unixdom_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
272 return talloc_strdup(mem_ctx, "LOCAL/unixdom");
275 static int unixdom_get_peer_port(struct socket_context *sock)
280 static char *unixdom_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
282 return talloc_strdup(mem_ctx, "LOCAL/unixdom");
285 static int unixdom_get_my_port(struct socket_context *sock)
290 static int unixdom_get_fd(struct socket_context *sock)
295 static const struct socket_ops unixdom_ops = {
297 .type = SOCKET_TYPE_STREAM,
299 .init = unixdom_init,
300 .connect = unixdom_connect,
301 .listen = unixdom_listen,
302 .accept = unixdom_accept,
303 .recv = unixdom_recv,
304 .send = unixdom_send,
305 .close = unixdom_close,
307 .set_option = unixdom_set_option,
309 .get_peer_name = unixdom_get_peer_name,
310 .get_peer_addr = unixdom_get_peer_addr,
311 .get_peer_port = unixdom_get_peer_port,
312 .get_my_addr = unixdom_get_my_addr,
313 .get_my_port = unixdom_get_my_port,
315 .get_fd = unixdom_get_fd
318 const struct socket_ops *socket_unixdom_ops(void)
323 NTSTATUS socket_unixdom_init(void)