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 27 int 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. */ 45 int 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; 113 error: 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 */ 124 int 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 144 error: 145 return -1; 146 } 147 148 /** 149 * connect to peer named "name" 150 * returns fd or -1 on error 151 */ 152 int 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