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)
33 return map_nt_error_from_unix(ernum);
36 static NTSTATUS unixdom_init(struct socket_context *sock)
38 sock->fd = socket(PF_UNIX, SOCK_STREAM, 0);
40 return NT_STATUS_INSUFFICIENT_RESOURCES;
42 sock->private_data = NULL;
47 static void unixdom_close(struct socket_context *sock)
52 static NTSTATUS unixdom_connect(struct socket_context *sock,
53 const char *my_address, int my_port,
54 const char *srv_address, int srv_port,
57 struct sockaddr_un srv_addr;
60 if (strlen(srv_address)+1 > sizeof(srv_addr.sun_path)) {
61 return NT_STATUS_INVALID_PARAMETER;
64 ZERO_STRUCT(srv_addr);
65 srv_addr.sun_family = AF_UNIX;
66 strncpy(srv_addr.sun_path, srv_address, sizeof(srv_addr.sun_path));
68 if (!(flags & SOCKET_FLAG_BLOCK)) {
69 ret = set_blocking(sock->fd, False);
71 return NT_STATUS_INVALID_PARAMETER;
75 ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr));
77 return unixdom_error(errno);
80 sock->state = SOCKET_STATE_CLIENT_CONNECTED;
85 static NTSTATUS unixdom_listen(struct socket_context *sock,
86 const char *my_address, int port,
87 int queue_size, uint32_t flags)
89 struct sockaddr_un my_addr;
92 if (strlen(my_address)+1 > sizeof(my_addr.sun_path)) {
93 return NT_STATUS_INVALID_PARAMETER;
96 /* delete if it already exists */
100 my_addr.sun_family = AF_UNIX;
101 strncpy(my_addr.sun_path, my_address, sizeof(my_addr.sun_path));
103 ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
105 return unixdom_error(errno);
108 ret = listen(sock->fd, queue_size);
110 return unixdom_error(errno);
113 if (!(flags & SOCKET_FLAG_BLOCK)) {
114 ret = set_blocking(sock->fd, False);
116 return unixdom_error(errno);
120 sock->state = SOCKET_STATE_SERVER_LISTEN;
121 sock->private_data = (void *)talloc_strdup(sock, my_address);
126 static NTSTATUS unixdom_accept(struct socket_context *sock,
127 struct socket_context **new_sock,
130 struct sockaddr_un cli_addr;
131 socklen_t cli_addr_len = sizeof(cli_addr);
134 new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len);
136 return unixdom_error(errno);
139 (*new_sock) = talloc_p(NULL, struct socket_context);
142 return NT_STATUS_NO_MEMORY;
145 /* copy the socket_context */
146 (*new_sock)->type = sock->type;
147 (*new_sock)->state = SOCKET_STATE_SERVER_CONNECTED;
148 (*new_sock)->flags = flags;
150 (*new_sock)->fd = new_fd;
152 (*new_sock)->private_data = NULL;
153 (*new_sock)->ops = sock->ops;
158 static NTSTATUS unixdom_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
159 DATA_BLOB *blob, size_t wantlen, uint32_t flags)
165 buf = talloc(mem_ctx, wantlen);
167 return NT_STATUS_NO_MEMORY;
170 /* TODO: we need to map all flags here */
171 if (flags & SOCKET_FLAG_PEEK) {
175 if (!(flags & SOCKET_FLAG_BLOCK)) {
176 flgs |= MSG_DONTWAIT;
179 if (flags & SOCKET_FLAG_BLOCK) {
183 gotlen = recv(sock->fd, buf, wantlen, flgs);
186 return NT_STATUS_END_OF_FILE;
187 } else if (gotlen == -1) {
188 NTSTATUS status = unixdom_error(errno);
193 blob->length = gotlen;
194 blob->data = talloc_realloc(mem_ctx, buf, gotlen);
196 return NT_STATUS_NO_MEMORY;
202 static NTSTATUS unixdom_send(struct socket_context *sock, TALLOC_CTX *mem_ctx,
203 const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
210 /* TODO: we need to map all flags here */
211 if (!(flags & SOCKET_FLAG_BLOCK)) {
212 flgs |= MSG_DONTWAIT;
215 len = send(sock->fd, blob->data, blob->length, flgs);
217 return unixdom_error(errno);
225 static NTSTATUS unixdom_set_option(struct socket_context *sock,
226 const char *option, const char *val)
231 static char *unixdom_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
233 return talloc_strdup(mem_ctx, "LOCAL/unixdom");
236 static char *unixdom_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
238 return talloc_strdup(mem_ctx, "LOCAL/unixdom");
241 static int unixdom_get_peer_port(struct socket_context *sock)
246 static char *unixdom_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
248 return talloc_strdup(mem_ctx, "LOCAL/unixdom");
251 static int unixdom_get_my_port(struct socket_context *sock)
256 static int unixdom_get_fd(struct socket_context *sock)
261 static const struct socket_ops unixdom_ops = {
263 .type = SOCKET_TYPE_STREAM,
265 .init = unixdom_init,
266 .connect = unixdom_connect,
267 .listen = unixdom_listen,
268 .accept = unixdom_accept,
269 .recv = unixdom_recv,
270 .send = unixdom_send,
271 .close = unixdom_close,
273 .set_option = unixdom_set_option,
275 .get_peer_name = unixdom_get_peer_name,
276 .get_peer_addr = unixdom_get_peer_addr,
277 .get_peer_port = unixdom_get_peer_port,
278 .get_my_addr = unixdom_get_my_addr,
279 .get_my_port = unixdom_get_my_port,
281 .get_fd = unixdom_get_fd
284 const struct socket_ops *socket_unixdom_ops(void)
289 NTSTATUS socket_unixdom_init(void)