• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
socktype_pton(int portable_type)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  */
socktype_ntop(int native_type)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 
WRAP(socket)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 
WRAP(socketpair)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  */
WRAP(getaddrinfo)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  */
WRAP(freeaddrinfo)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