socket_local_server.c revision 4f6e8d7a00cbeda1e70cc15be9c4af1018bdad53
1/* libs/cutils/socket_local_server.c
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <cutils/sockets.h>
19
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23#include <errno.h>
24#include <stddef.h>
25
26#ifdef HAVE_WINSOCK
27
28int socket_local_server(const char *name, int namespaceId, int type)
29{
30    errno = ENOSYS;
31    return -1;
32}
33
34#else /* !HAVE_WINSOCK */
35
36#include <sys/socket.h>
37#include <sys/un.h>
38#include <sys/select.h>
39#include <sys/types.h>
40#include <netinet/in.h>
41
42#include "socket_local.h"
43
44#define LISTEN_BACKLOG 4
45
46
47/**
48 * Binds a pre-created socket(AF_LOCAL) 's' to 'name'
49 * returns 's' on success, -1 on fail
50 *
51 * Does not call listen()
52 */
53int socket_local_server_bind(int s, const char *name, int namespaceId)
54{
55    struct sockaddr_un addr;
56    socklen_t alen;
57    int n;
58    int err;
59
60    err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
61
62    if (err < 0) {
63        return -1;
64    }
65
66    /* basically: if this is a filesystem path, unlink first */
67#ifndef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
68    if (1) {
69#else
70    if (namespaceId == ANDROID_SOCKET_NAMESPACE_RESERVED
71        || namespaceId == ANDROID_SOCKET_NAMESPACE_FILESYSTEM) {
72#endif
73        /*ignore ENOENT*/
74        unlink(addr.sun_path);
75    }
76
77    n = 1;
78    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
79
80    if(bind(s, (struct sockaddr *) &addr, alen) < 0) {
81        return -1;
82    }
83
84    return s;
85
86}
87
88
89/** Open a server-side UNIX domain datagram socket in the Linux non-filesystem
90 *  namespace
91 *
92 *  Returns fd on success, -1 on fail
93 */
94
95int socket_local_server(const char *name, int namespace, int type)
96{
97    int err;
98    int s;
99
100    s = socket(AF_LOCAL, type, 0);
101    if (s < 0) return -1;
102
103    err = socket_local_server_bind(s, name, namespace);
104
105    if (err < 0) {
106        close(s);
107        return -1;
108    }
109
110    if (type == SOCK_STREAM) {
111        int ret;
112
113        ret = listen(s, LISTEN_BACKLOG);
114
115        if (ret < 0) {
116            close(s);
117            return -1;
118        }
119    }
120
121    return s;
122}
123
124#endif /* !HAVE_WINSOCK */
125