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 #if defined(_WIN32) 26 27 int socket_local_client(const char *name, int namespaceId, int type) 28 { 29 errno = ENOSYS; 30 return -1; 31 } 32 33 #else /* !_WIN32 */ 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_unix.h" 41 42 #define UNUSED __attribute__((unused)) 43 44 #define LISTEN_BACKLOG 4 45 46 /* Documented in header file. */ 47 int 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; 115 error: 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 */ 126 int 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 145 error: 146 return -1; 147 } 148 149 /** 150 * connect to peer named "name" 151 * returns fd or -1 on error 152 */ 153 int 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 /* !_WIN32 */ 169