1 /*
2 * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
3 *
4 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
5 */
6
7 #include <stddef.h>
8 #include <sys/syscall.h>
9 #include <sys/socket.h>
10 #include <cancel.h>
11 #include <bits/kernel-features.h>
12
13 #if defined(__UCLIBC_USE_TIME64__)
14 #include "internal/time64_helpers.h"
15 #endif
16
17 #ifdef __NR_socketcall
18 /* Various socketcall numbers */
19 #define SYS_SOCKET 1
20 #define SYS_BIND 2
21 #define SYS_CONNECT 3
22 #define SYS_LISTEN 4
23 #define SYS_ACCEPT 5
24 #define SYS_GETSOCKNAME 6
25 #define SYS_GETPEERNAME 7
26 #define SYS_SOCKETPAIR 8
27 #define SYS_SEND 9
28 #define SYS_RECV 10
29 #define SYS_SENDTO 11
30 #define SYS_RECVFROM 12
31 #define SYS_SHUTDOWN 13
32 #define SYS_SETSOCKOPT 14
33 #define SYS_GETSOCKOPT 15
34 #define SYS_SENDMSG 16
35 #define SYS_RECVMSG 17
36 #define SYS_ACCEPT4 18
37 #define SYS_RECVMMSG 19
38 #define SYS_SENDMMSG 20
39 #endif
40
41 /* exposed on x86 since Linux commit 9dea5dc921b5f4045a18c63eb92e84dc274d17eb */
42 #if defined(__sparc__) || defined(__i386__)
43 #undef __NR_accept
44 #undef __NR_accept4
45 #undef __NR_bind
46 #undef __NR_connect
47 #undef __NR_getpeername
48 #undef __NR_getsockname
49 #undef __NR_getsockopt
50 #undef __NR_listen
51 #undef __NR_recv
52 #undef __NR_recvfrom
53 #undef __NR_recvmsg
54 #undef __NR_send
55 #undef __NR_sendmsg
56 #undef __NR_sendto
57 #undef __NR_setsockopt
58 #undef __NR_shutdown
59 #undef __NR_socket
60 #undef __NR_socketpair
61 #endif
62
63 #ifdef L_accept
__NC(accept)64 static int __NC(accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
65 {
66 # ifdef __NR_accept
67 return INLINE_SYSCALL(accept, 3, sockfd, addr, addrlen);
68 # elif defined(__NR_socketcall)
69 unsigned long args[3];
70
71 args[0] = sockfd;
72 args[1] = (unsigned long) addr;
73 args[2] = (unsigned long) addrlen;
74
75 return __socketcall(SYS_ACCEPT, args);
76 # endif
77 }
78 CANCELLABLE_SYSCALL(int, accept, (int sockfd, struct sockaddr *addr, socklen_t *addrlen),
79 (sockfd, addr, addrlen))
lt_libc_hidden(accept)80 lt_libc_hidden(accept)
81 #endif
82
83 #ifdef L_accept4
84 static int __NC(accept4)(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags)
85 {
86 # ifdef __NR_accept4
87 return INLINE_SYSCALL(accept4, 4, fd, addr, addrlen, flags);
88 # elif defined(__NR_socketcall)
89 unsigned long args[4];
90
91 args[0] = fd;
92 args[1] = (unsigned long) addr;
93 args[2] = (unsigned long) addrlen;
94 args[3] = flags;
95
96 return __socketcall(SYS_ACCEPT4, args);
97 #endif
98 }
99 CANCELLABLE_SYSCALL(int, accept4, (int fd, struct sockaddr *addr, socklen_t *addrlen, int flags),
100 (fd, addr, addrlen, flags))
lt_libc_hidden(accept4)101 lt_libc_hidden(accept4)
102 #endif
103
104 #ifdef L_bind
105 int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
106 {
107 # ifdef __NR_bind
108 return INLINE_SYSCALL(bind, 3, sockfd, myaddr, addrlen);
109 # elif defined(__NR_socketcall)
110 unsigned long args[3];
111
112 args[0] = sockfd;
113 args[1] = (unsigned long) myaddr;
114 args[2] = addrlen;
115 return __socketcall(SYS_BIND, args);
116 # endif
117 }
libc_hidden_def(bind)118 libc_hidden_def(bind)
119 #endif
120
121 #ifdef L_connect
122 static int __NC(connect)(int sockfd, const struct sockaddr *saddr, socklen_t addrlen)
123 {
124 # ifdef __NR_connect
125 return INLINE_SYSCALL(connect, 3, sockfd, saddr, addrlen);
126 # elif defined(__NR_socketcall)
127 unsigned long args[3];
128
129 args[0] = sockfd;
130 args[1] = (unsigned long) saddr;
131 args[2] = addrlen;
132 return __socketcall(SYS_CONNECT, args);
133 # endif
134 }
135 CANCELLABLE_SYSCALL(int, connect, (int sockfd, const struct sockaddr *saddr, socklen_t addrlen),
136 (sockfd, saddr, addrlen))
lt_libc_hidden(connect)137 lt_libc_hidden(connect)
138 #endif
139
140 #ifdef L_getpeername
141 int getpeername(int sockfd, struct sockaddr *addr, socklen_t *paddrlen)
142 {
143 # ifdef __NR_getpeername
144 return INLINE_SYSCALL(getpeername, 3, sockfd, addr, paddrlen);
145 # elif defined(__NR_socketcall)
146 unsigned long args[3];
147
148 args[0] = sockfd;
149 args[1] = (unsigned long) addr;
150 args[2] = (unsigned long) paddrlen;
151 return __socketcall(SYS_GETPEERNAME, args);
152 # endif
153 }
154 #endif
155
156 #ifdef L_getsockname
getsockname(int sockfd,struct sockaddr * addr,socklen_t * paddrlen)157 int getsockname(int sockfd, struct sockaddr *addr, socklen_t * paddrlen)
158 {
159 # ifdef __NR_getsockname
160 return INLINE_SYSCALL(getsockname, 3, sockfd, addr, paddrlen);
161 # elif defined(__NR_socketcall)
162 unsigned long args[3];
163
164 args[0] = sockfd;
165 args[1] = (unsigned long) addr;
166 args[2] = (unsigned long) paddrlen;
167 return __socketcall(SYS_GETSOCKNAME, args);
168 # endif
169 }
libc_hidden_def(getsockname)170 libc_hidden_def(getsockname)
171 #endif
172
173 #ifdef L_getsockopt
174 int getsockopt(int fd, int level, int optname, void *optval,
175 socklen_t *optlen)
176 {
177 # ifdef __NR_getsockopt
178 return INLINE_SYSCALL(getsockopt, 5, fd, level, optname, optval, optlen);
179 # elif defined(__NR_socketcall)
180 unsigned long args[5];
181
182 args[0] = fd;
183 args[1] = level;
184 args[2] = optname;
185 args[3] = (unsigned long) optval;
186 args[4] = (unsigned long) optlen;
187 return (__socketcall(SYS_GETSOCKOPT, args));
188 # endif
189 }
190 #endif
191
192 #ifdef L_listen
listen(int sockfd,int backlog)193 int listen(int sockfd, int backlog)
194 {
195 # ifdef __NR_listen
196 return INLINE_SYSCALL(listen, 2, sockfd, backlog);
197 # elif defined(__NR_socketcall)
198 unsigned long args[2];
199
200 args[0] = sockfd;
201 args[1] = backlog;
202 return __socketcall(SYS_LISTEN, args);
203 # endif
204 }
libc_hidden_def(listen)205 libc_hidden_def(listen)
206 #endif
207
208 #ifdef L_recv
209 static ssize_t __NC(recv)(int sockfd, void *buffer, size_t len, int flags)
210 {
211 # ifdef __NR_recv
212 return (ssize_t)INLINE_SYSCALL(recv, 4, sockfd, buffer, len, flags);
213 # elif defined __NR_recvfrom && defined _syscall6
214 return __NC(recvfrom)(sockfd, buffer, len, flags, NULL, NULL);
215 # elif defined(__NR_socketcall)
216 unsigned long args[4];
217
218 args[0] = sockfd;
219 args[1] = (unsigned long) buffer;
220 args[2] = len;
221 args[3] = flags;
222 return (ssize_t)__socketcall(SYS_RECV, args);
223 # endif
224 }
225 CANCELLABLE_SYSCALL(ssize_t, recv, (int sockfd, void *buffer, size_t len, int flags),
226 (sockfd, buffer, len, flags))
lt_libc_hidden(recv)227 lt_libc_hidden(recv)
228 #endif
229
230 #ifdef L_recvfrom
231 ssize_t __NC(recvfrom)(int sockfd, void *buffer, size_t len, int flags,
232 struct sockaddr *to, socklen_t *tolen)
233 {
234 # if defined __NR_recvfrom && defined _syscall6
235 return (ssize_t)INLINE_SYSCALL(recvfrom, 6, sockfd, buffer, len,
236 flags, to, tolen);
237 # elif defined(__NR_socketcall)
238 unsigned long args[6];
239
240 args[0] = sockfd;
241 args[1] = (unsigned long) buffer;
242 args[2] = len;
243 args[3] = flags;
244 args[4] = (unsigned long) to;
245 args[5] = (unsigned long) tolen;
246 return (ssize_t)__socketcall(SYS_RECVFROM, args);
247 # endif
248 }
249 CANCELLABLE_SYSCALL(ssize_t, recvfrom, (int sockfd, void *buffer, size_t len,
250 int flags, struct sockaddr *to, socklen_t *tolen),
251 (sockfd, buffer, len, flags, to, tolen))
lt_libc_hidden(recvfrom)252 lt_libc_hidden(recvfrom)
253 #endif
254
255 #ifdef L_recvmsg
256 static ssize_t __NC(recvmsg)(int sockfd, struct msghdr *msg, int flags)
257 {
258 # ifdef __NR_recvmsg
259 return (ssize_t)INLINE_SYSCALL(recvmsg, 3, sockfd, msg, flags);
260 # elif defined(__NR_socketcall)
261 unsigned long args[3];
262
263 args[0] = sockfd;
264 args[1] = (unsigned long) msg;
265 args[2] = flags;
266 return (ssize_t)__socketcall(SYS_RECVMSG, args);
267 # endif
268 }
269 CANCELLABLE_SYSCALL(ssize_t, recvmsg, (int sockfd, struct msghdr *msg, int flags),
270 (sockfd, msg, flags))
lt_libc_hidden(recvmsg)271 lt_libc_hidden(recvmsg)
272 #endif
273
274 #ifdef L_recvmmsg
275 #ifdef __ASSUME_RECVMMSG_SYSCALL
276 static ssize_t __NC(recvmmsg)(int sockfd, struct mmsghdr *msg, size_t vlen,
277 int flags, struct timespec *tmo)
278 {
279 # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_recvmmsg_time64)
280 return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg, vlen, flags, TO_TS64_P(tmo));
281 # elif defined(__NR_recvmmsg)
282 return (ssize_t)INLINE_SYSCALL(recvmmsg, 5, sockfd, msg, vlen, flags, tmo);
283 # elif __NR_socketcall
284 unsigned long args[5];
285
286 args[0] = sockfd;
287 args[1] = (unsigned long) msg;
288 args[2] = vlen;
289 args[3] = flags;
290 args[4] = (unsigned long) tmo;
291 return (ssize_t)__socketcall(SYS_RECVMMSG, args);
292 # endif
293 }
294 CANCELLABLE_SYSCALL(ssize_t, recvmmsg,
295 (int sockfd, struct mmsghdr *msg, size_t vlen, int flags,
296 struct timespec *tmo),
297 (sockfd, msg, vlen, flags, tmo))
lt_libc_hidden(recvmmsg)298 lt_libc_hidden(recvmmsg)
299 #endif
300 #endif
301
302 #ifdef L_send
303 static ssize_t __NC(send)(int sockfd, const void *buffer, size_t len, int flags)
304 {
305 # ifdef __NR_send
306 return (ssize_t)INLINE_SYSCALL(send, 4, sockfd, buffer, len, flags);
307 # elif defined __NR_sendto && defined _syscall6
308 return __NC(sendto)(sockfd, buffer, len, flags, NULL, 0);
309 # elif defined(__NR_socketcall)
310 unsigned long args[4];
311
312 args[0] = sockfd;
313 args[1] = (unsigned long) buffer;
314 args[2] = len;
315 args[3] = flags;
316 return (ssize_t)__socketcall(SYS_SEND, args);
317 # endif
318 }
319 CANCELLABLE_SYSCALL(ssize_t, send, (int sockfd, const void *buffer, size_t len, int flags),
320 (sockfd, buffer, len, flags))
lt_libc_hidden(send)321 lt_libc_hidden(send)
322 #endif
323
324 #ifdef L_sendmsg
325 static ssize_t __NC(sendmsg)(int sockfd, const struct msghdr *msg, int flags)
326 {
327 # ifdef __NR_sendmsg
328 return (ssize_t)INLINE_SYSCALL(sendmsg, 3, sockfd, msg, flags);
329 # elif defined(__NR_socketcall)
330 unsigned long args[3];
331
332 args[0] = sockfd;
333 args[1] = (unsigned long) msg;
334 args[2] = flags;
335 return (ssize_t)__socketcall(SYS_SENDMSG, args);
336 # endif
337 }
338 CANCELLABLE_SYSCALL(ssize_t, sendmsg, (int sockfd, const struct msghdr *msg, int flags),
339 (sockfd, msg, flags))
lt_libc_hidden(sendmsg)340 lt_libc_hidden(sendmsg)
341 #endif
342
343 #ifdef L_sendmmsg
344 #ifdef __ASSUME_SENDMMSG_SYSCALL
345 static ssize_t __NC(sendmmsg)(int sockfd, struct mmsghdr *msg, size_t vlen,
346 int flags)
347 {
348 # ifdef __NR_sendmmsg
349 return (ssize_t)INLINE_SYSCALL(sendmmsg, 4, sockfd, msg, vlen, flags);
350 # elif __NR_socketcall
351 unsigned long args[4];
352
353 args[0] = sockfd;
354 args[1] = (unsigned long) msg;
355 args[2] = vlen;
356 args[3] = flags;
357 return (ssize_t)__socketcall(SYS_SENDMMSG, args);
358 # endif
359 }
360 CANCELLABLE_SYSCALL(ssize_t, sendmmsg,
361 (int sockfd, struct mmsghdr *msg, size_t vlen, int flags),
362 (sockfd, msg, vlen, flags))
lt_libc_hidden(sendmmsg)363 lt_libc_hidden(sendmmsg)
364 #endif
365 #endif
366
367 #ifdef L_sendto
368 ssize_t __NC(sendto)(int sockfd, const void *buffer, size_t len, int flags,
369 const struct sockaddr *to, socklen_t tolen)
370 {
371 # if defined __NR_sendto && defined _syscall6
372 return (ssize_t)INLINE_SYSCALL(sendto, 6, sockfd, buffer, len, flags, to, tolen);
373 # elif defined(__NR_socketcall)
374 unsigned long args[6];
375
376 args[0] = sockfd;
377 args[1] = (unsigned long) buffer;
378 args[2] = len;
379 args[3] = flags;
380 args[4] = (unsigned long) to;
381 args[5] = tolen;
382 return (ssize_t)__socketcall(SYS_SENDTO, args);
383 # endif
384 }
385 CANCELLABLE_SYSCALL(ssize_t, sendto, (int sockfd, const void *buffer, size_t len,
386 int flags, const struct sockaddr *to, socklen_t tolen),
387 (sockfd, buffer, len, flags, to, tolen))
lt_libc_hidden(sendto)388 lt_libc_hidden(sendto)
389 #endif
390
391 #ifdef L_setsockopt
392 int setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
393 {
394 # ifdef __NR_setsockopt
395 return INLINE_SYSCALL(setsockopt, 5, fd, level, optname, optval, optlen);
396 # elif defined(__NR_socketcall)
397 unsigned long args[5];
398
399 args[0] = fd;
400 args[1] = level;
401 args[2] = optname;
402 args[3] = (unsigned long) optval;
403 args[4] = optlen;
404 return __socketcall(SYS_SETSOCKOPT, args);
405 # endif
406 }
libc_hidden_def(setsockopt)407 libc_hidden_def(setsockopt)
408 #endif
409
410 #ifdef L_shutdown
411 int shutdown(int sockfd, int how)
412 {
413 # ifdef __NR_shutdown
414 return INLINE_SYSCALL(shutdown, 2, sockfd, how);
415 # elif defined(__NR_socketcall)
416 unsigned long args[2];
417
418 args[0] = sockfd;
419 args[1] = how;
420 return __socketcall(SYS_SHUTDOWN, args);
421 # endif
422 }
423 #endif
424
425 #ifdef L_socket
socket(int family,int type,int protocol)426 int socket(int family, int type, int protocol)
427 {
428 # ifdef __NR_socket
429 return INLINE_SYSCALL(socket, 3, family, type, protocol);
430 # elif defined(__NR_socketcall)
431 unsigned long args[3];
432
433 args[0] = family;
434 args[1] = type;
435 args[2] = (unsigned long) protocol;
436 return __socketcall(SYS_SOCKET, args);
437 # endif
438 }
libc_hidden_def(socket)439 libc_hidden_def(socket)
440 #endif
441
442 #ifdef L_socketpair
443 int socketpair(int family, int type, int protocol, int sockvec[2])
444 {
445 # ifdef __NR_socketpair
446 return INLINE_SYSCALL(socketpair, 4, family, type, protocol, sockvec);
447 # elif defined(__NR_socketcall)
448 unsigned long args[4];
449
450 args[0] = family;
451 args[1] = type;
452 args[2] = protocol;
453 args[3] = (unsigned long) sockvec;
454 return __socketcall(SYS_SOCKETPAIR, args);
455 # endif
456 }
457 #endif
458