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