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)
76 static NTSTATUS unixdom_connect(struct socket_context *sock,
77 const char *my_address, int my_port,
78 const char *srv_address, int srv_port,
81 struct sockaddr_un srv_addr;
84 if (strlen(srv_address)+1 > sizeof(srv_addr.sun_path)) {
85 return NT_STATUS_INVALID_PARAMETER;
88 ZERO_STRUCT(srv_addr);
89 srv_addr.sun_family = AF_UNIX;
90 strncpy(srv_addr.sun_path, srv_address, sizeof(srv_addr.sun_path));
92 if (!(flags & SOCKET_FLAG_BLOCK)) {
93 ret = set_blocking(sock->fd, False);
95 return NT_STATUS_INVALID_PARAMETER;
99 ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr));
101 return unixdom_error(errno);
104 sock->state = SOCKET_STATE_CLIENT_CONNECTED;
109 static NTSTATUS unixdom_listen(struct socket_context *sock,
110 const char *my_address, int port,
111 int queue_size, uint32_t flags)
113 struct sockaddr_un my_addr;
116 if (strlen(my_address)+1 > sizeof(my_addr.sun_path)) {
117 return NT_STATUS_INVALID_PARAMETER;
120 /* delete if it already exists */
123 ZERO_STRUCT(my_addr);
124 my_addr.sun_family = AF_UNIX;
125 strncpy(my_addr.sun_path, my_address, sizeof(my_addr.sun_path));
127 ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
129 return unixdom_error(errno);
132 ret = listen(sock->fd, queue_size);
134 return unixdom_error(errno);
137 if (!(flags & SOCKET_FLAG_BLOCK)) {
138 ret = set_blocking(sock->fd, False);
140 return unixdom_error(errno);
144 sock->state = SOCKET_STATE_SERVER_LISTEN;
145 sock->private_data = (void *)talloc_strdup(sock, my_address);
150 static NTSTATUS unixdom_accept(struct socket_context *sock,
151 struct socket_context **new_sock,
154 struct sockaddr_un cli_addr;
155 socklen_t cli_addr_len = sizeof(cli_addr);
158 new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len);
160 return unixdom_error(errno);
163 (*new_sock) = talloc_p(NULL, struct socket_context);
166 return NT_STATUS_NO_MEMORY;
169 /* copy the socket_context */
170 (*new_sock)->type = sock->type;
171 (*new_sock)->state = SOCKET_STATE_SERVER_CONNECTED;
172 (*new_sock)->flags = flags;
174 (*new_sock)->fd = new_fd;
176 (*new_sock)->private_data = NULL;
177 (*new_sock)->ops = sock->ops;
182 static NTSTATUS unixdom_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx,
183 DATA_BLOB *blob, size_t wantlen, uint32_t flags)
189 buf = talloc(mem_ctx, wantlen);
191 return NT_STATUS_NO_MEMORY;
194 /* TODO: we need to map all flags here */
195 if (flags & SOCKET_FLAG_PEEK) {
199 if (!(flags & SOCKET_FLAG_BLOCK)) {
200 flgs |= MSG_DONTWAIT;
203 if (flags & SOCKET_FLAG_BLOCK) {
207 gotlen = recv(sock->fd, buf, wantlen, flgs);
210 return NT_STATUS_END_OF_FILE;
211 } else if (gotlen == -1) {
212 NTSTATUS status = unixdom_error(errno);
217 blob->length = gotlen;
218 blob->data = talloc_realloc(mem_ctx, buf, gotlen);
220 return NT_STATUS_NO_MEMORY;
226 static NTSTATUS unixdom_send(struct socket_context *sock, TALLOC_CTX *mem_ctx,
227 const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
234 /* TODO: we need to map all flags here */
235 if (!(flags & SOCKET_FLAG_BLOCK)) {
236 flgs |= MSG_DONTWAIT;
239 len = send(sock->fd, blob->data, blob->length, flgs);
241 return unixdom_error(errno);
249 static NTSTATUS unixdom_set_option(struct socket_context *sock,
250 const char *option, const char *val)
252 set_socket_options(sock->fd, option);
256 static char *unixdom_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
258 return talloc_strdup(mem_ctx, "LOCAL/unixdom");
261 static char *unixdom_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
263 return talloc_strdup(mem_ctx, "LOCAL/unixdom");
266 static int unixdom_get_peer_port(struct socket_context *sock)
271 static char *unixdom_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
273 return talloc_strdup(mem_ctx, "LOCAL/unixdom");
276 static int unixdom_get_my_port(struct socket_context *sock)
281 static int unixdom_get_fd(struct socket_context *sock)
286 static const struct socket_ops unixdom_ops = {
288 .type = SOCKET_TYPE_STREAM,
290 .init = unixdom_init,
291 .connect = unixdom_connect,
292 .listen = unixdom_listen,
293 .accept = unixdom_accept,
294 .recv = unixdom_recv,
295 .send = unixdom_send,
296 .close = unixdom_close,
298 .set_option = unixdom_set_option,
300 .get_peer_name = unixdom_get_peer_name,
301 .get_peer_addr = unixdom_get_peer_addr,
302 .get_peer_port = unixdom_get_peer_port,
303 .get_my_addr = unixdom_get_my_addr,
304 .get_my_port = unixdom_get_my_port,
306 .get_fd = unixdom_get_fd
309 const struct socket_ops *socket_unixdom_ops(void)
314 NTSTATUS socket_unixdom_init(void)