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 <errno.h> 18#include <stddef.h> 19#include <stdlib.h> 20#include <string.h> 21#include <unistd.h> 22 23#include <cutils/sockets.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 UNUSED __attribute__((unused)) 43 44#define LISTEN_BACKLOG 4 45 46/* Documented in header file. */ 47int socket_make_sockaddr_un(const char *name, int namespaceId, 48 struct sockaddr_un *p_addr, socklen_t *alen) 49{ 50 memset (p_addr, 0, sizeof (*p_addr)); 51 size_t namelen; 52 53 switch (namespaceId) { 54 case ANDROID_SOCKET_NAMESPACE_ABSTRACT: 55#if defined(__linux__) 56 namelen = strlen(name); 57 58 // Test with length +1 for the *initial* '\0'. 59 if ((namelen + 1) > sizeof(p_addr->sun_path)) { 60 goto error; 61 } 62 63 /* 64 * Note: The path in this case is *not* supposed to be 65 * '\0'-terminated. ("man 7 unix" for the gory details.) 66 */ 67 68 p_addr->sun_path[0] = 0; 69 memcpy(p_addr->sun_path + 1, name, namelen); 70#else 71 /* this OS doesn't have the Linux abstract namespace */ 72 73 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX); 74 /* unix_path_max appears to be missing on linux */ 75 if (namelen > sizeof(*p_addr) 76 - offsetof(struct sockaddr_un, sun_path) - 1) { 77 goto error; 78 } 79 80 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX); 81 strcat(p_addr->sun_path, name); 82#endif 83 break; 84 85 case ANDROID_SOCKET_NAMESPACE_RESERVED: 86 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX); 87 /* unix_path_max appears to be missing on linux */ 88 if (namelen > sizeof(*p_addr) 89 - offsetof(struct sockaddr_un, sun_path) - 1) { 90 goto error; 91 } 92 93 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX); 94 strcat(p_addr->sun_path, name); 95 break; 96 97 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM: 98 namelen = strlen(name); 99 /* unix_path_max appears to be missing on linux */ 100 if (namelen > sizeof(*p_addr) 101 - offsetof(struct sockaddr_un, sun_path) - 1) { 102 goto error; 103 } 104 105 strcpy(p_addr->sun_path, name); 106 break; 107 default: 108 // invalid namespace id 109 return -1; 110 } 111 112 p_addr->sun_family = AF_LOCAL; 113 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1; 114 return 0; 115error: 116 return -1; 117} 118 119/** 120 * connect to peer named "name" on fd 121 * returns same fd or -1 on error. 122 * fd is not closed on error. that's your job. 123 * 124 * Used by AndroidSocketImpl 125 */ 126int socket_local_client_connect(int fd, const char *name, int namespaceId, 127 int type UNUSED) 128{ 129 struct sockaddr_un addr; 130 socklen_t alen; 131 int err; 132 133 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen); 134 135 if (err < 0) { 136 goto error; 137 } 138 139 if(connect(fd, (struct sockaddr *) &addr, alen) < 0) { 140 goto error; 141 } 142 143 return fd; 144 145error: 146 return -1; 147} 148 149/** 150 * connect to peer named "name" 151 * returns fd or -1 on error 152 */ 153int socket_local_client(const char *name, int namespaceId, int type) 154{ 155 int s; 156 157 s = socket(AF_LOCAL, type, 0); 158 if(s < 0) return -1; 159 160 if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) { 161 close(s); 162 return -1; 163 } 164 165 return s; 166} 167 168#endif /* !HAVE_WINSOCK */ 169