1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/sockets.h>
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stddef.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_WINSOCK
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint socket_local_client(const char *name, int namespaceId, int type)
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    errno = ENOSYS;
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else /* !HAVE_WINSOCK */
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h>
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/un.h>
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/select.h>
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "socket_local.h"
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LISTEN_BACKLOG 4
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Documented in header file. */
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint socket_make_sockaddr_un(const char *name, int namespaceId,
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct sockaddr_un *p_addr, socklen_t *alen)
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset (p_addr, 0, sizeof (*p_addr));
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t namelen;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch (namespaceId) {
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            namelen  = strlen(name);
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // Test with length +1 for the *initial* '\0'.
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if ((namelen + 1) > sizeof(p_addr->sun_path)) {
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                goto error;
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /*
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             * Note: The path in this case is *not* supposed to be
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             * '\0'-terminated. ("man 7 unix" for the gory details.)
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             */
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p_addr->sun_path[0] = 0;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            memcpy(p_addr->sun_path + 1, name, namelen);
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* this OS doesn't have the Linux abstract namespace */
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* unix_path_max appears to be missing on linux */
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (namelen > sizeof(*p_addr)
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    - offsetof(struct sockaddr_un, sun_path) - 1) {
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                goto error;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            strcat(p_addr->sun_path, name);
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ANDROID_SOCKET_NAMESPACE_RESERVED:
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* unix_path_max appears to be missing on linux */
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (namelen > sizeof(*p_addr)
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    - offsetof(struct sockaddr_un, sun_path) - 1) {
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                goto error;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            strcat(p_addr->sun_path, name);
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            namelen = strlen(name);
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* unix_path_max appears to be missing on linux */
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (namelen > sizeof(*p_addr)
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    - offsetof(struct sockaddr_un, sun_path) - 1) {
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                goto error;
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            strcpy(p_addr->sun_path, name);
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        default:
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // invalid namespace id
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p_addr->sun_family = AF_LOCAL;
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecterror:
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/**
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * connect to peer named "name" on fd
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * returns same fd or -1 on error.
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * fd is not closed on error. that's your job.
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Used by AndroidSocketImpl
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint socket_local_client_connect(int fd, const char *name, int namespaceId,
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int type)
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct sockaddr_un addr;
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    socklen_t alen;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t namelen;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int err;
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (err < 0) {
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto error;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto error;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return fd;
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecterror:
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/**
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * connect to peer named "name"
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * returns fd or -1 on error
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint socket_local_client(const char *name, int namespaceId, int type)
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int s;
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    s = socket(AF_LOCAL, type, 0);
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(s < 0) return -1;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close(s);
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* !HAVE_WINSOCK */
168