1 /* 2 * Copyright 2012, 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 <portability.h> 18 #include <unistd.h> 19 #include <sys/socket.h> 20 #include <fcntl.h> 21 #include <netdb.h> 22 23 #include <socket_portable.h> 24 #include <fcntl_portable.h> 25 #include <netdb_portable.h> 26 #include <portability.h> 27 28 #define PORTABLE_TAG "socket_portable" 29 #include <log_portable.h> 30 31 32 #if SOCK_STREAM==SOCK_STREAM_PORTABLE 33 #error Bad build environment 34 #endif 35 36 /* LTP defaults to using O_NONBLOCK if SOCK_NONBLOCK is not defined. */ 37 #ifndef SOCK_NONBLOCK_PORTABLE 38 # define SOCK_NONBLOCK_PORTABLE O_NONBLOCK_PORTABLE 39 #endif 40 #ifndef SOCK_NONBLOCK 41 # define SOCK_NONBLOCK O_NONBLOCK 42 #endif 43 44 /* Current NDK headers do not define SOCK_CLOEXEC or O_CLOEXEC */ 45 #if !defined(SOCK_CLOEXEC_PORTABLE) && defined(O_CLOEXEC_PORTABLE) 46 # define SOCK_CLOEXEC_PORTABLE O_CLOEXEC_PORTABLE 47 #endif 48 #if !defined(SOCK_CLOEXEC) && defined(O_CLOEXEC) 49 # define SOCK_CLOEXEC O_CLOEXEC 50 #endif 51 52 53 /* 54 * Portable to Native socktype mapper. 55 */ 56 static inline int socktype_pton(int portable_type) 57 { 58 int native_type = 0; 59 60 ALOGV("%s(portable_type:0x%x) {", __func__, portable_type); 61 62 if (portable_type & SOCK_NONBLOCK_PORTABLE) { 63 native_type |= SOCK_NONBLOCK; 64 portable_type &= ~SOCK_NONBLOCK_PORTABLE; 65 } 66 67 #if defined(SOCK_CLOEXEC_PORTABLE) && defined(SOCK_CLOEXEC) 68 if (portable_type & SOCK_CLOEXEC_PORTABLE) { 69 native_type |= SOCK_CLOEXEC; 70 portable_type &= ~SOCK_CLOEXEC_PORTABLE; 71 } 72 #endif 73 74 switch (portable_type) { 75 case SOCK_STREAM_PORTABLE: native_type |= SOCK_STREAM; break; 76 case SOCK_DGRAM_PORTABLE: native_type |= SOCK_DGRAM; break; 77 case SOCK_RAW_PORTABLE: native_type |= SOCK_RAW; break; 78 case SOCK_RDM_PORTABLE: native_type |= SOCK_RDM; break; 79 case SOCK_SEQPACKET_PORTABLE: native_type |= SOCK_SEQPACKET; break; 80 case SOCK_PACKET_PORTABLE: native_type |= SOCK_PACKET; break; 81 default: 82 ALOGE("%s: case default: native_type:0x%x |= portable_type:0x%x:[UNKNOWN!];", __func__, 83 native_type, portable_type); 84 85 native_type |= portable_type; 86 break; 87 } 88 ALOGV("%s: return(native_type:%d); }", __func__, native_type); 89 return native_type; 90 } 91 92 93 /* 94 * Native to Portable socktype mapper. 95 */ 96 static inline int socktype_ntop(int native_type) 97 { 98 int portable_type = 0; 99 100 ALOGV("%s(native_type:0x%x) {", __func__, native_type); 101 102 if (native_type & SOCK_NONBLOCK) { 103 portable_type |= SOCK_NONBLOCK_PORTABLE; 104 native_type &= ~SOCK_NONBLOCK; 105 } 106 107 #if defined(SOCK_CLOEXEC_PORTABLE) && defined(SOCK_CLOEXEC) 108 if (native_type & SOCK_CLOEXEC) { 109 portable_type |= SOCK_CLOEXEC_PORTABLE; 110 native_type &= ~SOCK_CLOEXEC; 111 } 112 #endif 113 114 switch (native_type) { 115 case SOCK_STREAM: portable_type |= SOCK_STREAM_PORTABLE; break; 116 case SOCK_DGRAM: portable_type |= SOCK_DGRAM_PORTABLE; break; 117 case SOCK_RAW: portable_type |= SOCK_RAW_PORTABLE; break; 118 case SOCK_RDM: portable_type |= SOCK_RDM_PORTABLE; break; 119 case SOCK_SEQPACKET: portable_type |= SOCK_SEQPACKET_PORTABLE; break; 120 case SOCK_PACKET: portable_type |= SOCK_PACKET_PORTABLE; break; 121 default: 122 portable_type |= native_type; 123 ALOGE("%s: case default: portable_type:0x%x |= native_type:0x%x:[UNKNOWN!];", __func__, 124 portable_type, native_type); 125 } 126 ALOGV("%s: return(portable_type:%d); }", __func__, portable_type); 127 return portable_type; 128 } 129 130 131 extern int REAL(socket)(int, int, int); 132 133 int WRAP(socket)(int domain, int type, int protocol) { 134 int rv; 135 136 ALOGV(" "); 137 ALOGV("%s(domain:%d, type:%d, protocol:%d) {", __func__, 138 domain, type, protocol); 139 140 rv = REAL(socket)(domain, socktype_pton(type), protocol); 141 142 ALOGV("%s: return(rv:%d); }", __func__, rv); 143 return rv; 144 } 145 146 147 int WRAP(socketpair)(int domain, int type, int protocol, int sv[2]) { 148 int rv; 149 150 ALOGV(" "); 151 ALOGV("%s(domain:%d, type:%d, protocol:%d, sv[2]:%p) {", __func__, 152 domain, type, protocol, sv); 153 154 rv = REAL(socketpair)(domain, socktype_pton(type), protocol, sv); 155 156 if ((rv != 0) || invalid_pointer(sv)) { 157 ALOGV("%s: return(rv:%d); }", __func__, 158 rv); 159 } else { 160 ALOGV("%s: return(rv:%d); sv[0]:%d; sv[1]:%d;}", __func__, 161 rv, sv[0], sv[1]); 162 } 163 return rv; 164 } 165 166 #define PRINT_ADDRINFO(p) { \ 167 ALOGV("%s: p:%p->{ai_flags:%d, ai_family:%d, ai_socktype:%d, ai_protocol:%d, ...", __func__, \ 168 p, p->ai_flags, p->ai_family, p->ai_socktype, p->ai_protocol); \ 169 \ 170 ALOGV("%s: p:%p->{... ai_addrlen:%d, ai_addr:%p, ai_canonname:%p, p->ai_next:%p);", __func__,\ 171 p, p->ai_addrlen, p->ai_addr, p->ai_canonname, p->ai_next); \ 172 } 173 174 /* 175 * Returns a list of portable addrinfo structures that are 176 * later made free with a call to the portable version of 177 * freeaddrinfo(); which is written below this function. 178 */ 179 int WRAP(getaddrinfo)(const char *node, const char *service, 180 struct addrinfo_portable *portable_hints, 181 struct addrinfo_portable **portable_results) 182 { 183 int rv; 184 struct addrinfo *native_hints; 185 struct addrinfo **native_results, *rp; 186 int saved_portable_socktype; 187 188 ALOGV(" "); 189 ALOGV("%s(node:%p, service:%p, portable_hints:%p, portable_results:%p) {", __func__, 190 node, service, portable_hints, portable_results); 191 192 PRINT_ADDRINFO(portable_hints); 193 194 /* 195 * The only part of the addrinfo structure that needs to be modified 196 * between ARM and MIPS is the socktype; 197 */ 198 ASSERT(sizeof(struct addrinfo_portable) == sizeof(struct addrinfo)); 199 native_hints = ((struct addrinfo *) portable_hints); 200 if (native_hints != NULL) { 201 saved_portable_socktype = portable_hints->ai_socktype; 202 native_hints->ai_socktype = socktype_pton(saved_portable_socktype); 203 } 204 ASSERT(portable_results != NULL); 205 native_results = (struct addrinfo **) portable_results; 206 207 rv = REAL(getaddrinfo)(node, service, native_hints, native_results); 208 209 if (native_hints != NULL) { 210 portable_hints->ai_socktype = saved_portable_socktype; 211 } 212 213 214 /* 215 * Map socktypes in the return list of addrinfo structures from native to portable. 216 * Assuming getaddrinfo() has left structure writeable and the list is generated 217 * on each call. This seems to be true when looking at the man page and the code 218 * at: 219 * ./bionic/libc/netbsd/net/getaddrinfo.c 220 */ 221 for (rp = *native_results; rp != NULL; rp = rp->ai_next) { 222 PRINT_ADDRINFO(rp); 223 rp->ai_socktype = socktype_ntop(rp->ai_socktype); 224 } 225 ALOGV("%s: return(rv:%d); }", __func__, rv); 226 return rv; 227 } 228 229 230 /* 231 * Free the results list returned from a previous call 232 * to the portable version of getaddrinfo(). 233 */ 234 void WRAP(freeaddrinfo)(struct addrinfo_portable *portable_results) 235 { 236 struct addrinfo *native_results, *rp; 237 238 ALOGV(" "); 239 ALOGV("%s(portable_results:%p) {", __func__, portable_results); 240 241 PRINT_ADDRINFO(portable_results); 242 243 /* 244 * The only part of each addrinfo structure that needs to be modified 245 * between ARM and MIPS is the socktype; 246 * 247 * Map socktypes in the return list of iportable addrinfo structures back to native. 248 * Again, assuming getaddrinfo() has left structure writeable and the list is generated 249 * on each call. This seems to be true when looking at the man page and the code. 250 */ 251 ASSERT(sizeof(struct addrinfo_portable) == sizeof(struct addrinfo)); 252 native_results = ((struct addrinfo *) portable_results); 253 for (rp = native_results; rp != NULL; rp = rp->ai_next) { 254 PRINT_ADDRINFO(rp); 255 rp->ai_socktype = socktype_pton(rp->ai_socktype); /* Likely not really necessary */ 256 } 257 REAL(freeaddrinfo)(native_results); 258 259 ALOGV("%s: return; }", __func__); 260 return; 261 } 262