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
12 #ifdef __NR_socketcall
13 /* Various socketcall numbers */
14 #define SYS_SOCKET 1
15 #define SYS_BIND 2
16 #define SYS_CONNECT 3
17 #define SYS_LISTEN 4
18 #define SYS_ACCEPT 5
19 #define SYS_GETSOCKNAME 6
20 #define SYS_GETPEERNAME 7
21 #define SYS_SOCKETPAIR 8
22 #define SYS_SEND 9
23 #define SYS_RECV 10
24 #define SYS_SENDTO 11
25 #define SYS_RECVFROM 12
26 #define SYS_SHUTDOWN 13
27 #define SYS_SETSOCKOPT 14
28 #define SYS_GETSOCKOPT 15
29 #define SYS_SENDMSG 16
30 #define SYS_RECVMSG 17
31 #define SYS_ACCEPT4 18
32 #endif
33
34 #ifdef L_accept
__NC(accept)35 static int __NC(accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
36 {
37 # ifdef __NR_accept
38 return INLINE_SYSCALL(accept, 3, sockfd, addr, addrlen);
39 # else
40 unsigned long args[3];
41
42 args[0] = sockfd;
43 args[1] = (unsigned long) addr;
44 args[2] = (unsigned long) addrlen;
45
46 return __socketcall(SYS_ACCEPT, args);
47 # endif
48 }
49 CANCELLABLE_SYSCALL(int, accept, (int sockfd, struct sockaddr *addr, socklen_t *addrlen),
50 (sockfd, addr, addrlen))
lt_libc_hidden(accept)51 lt_libc_hidden(accept)
52 #endif
53
54 #ifdef L_accept4
55 #ifdef __NR_accept4
56 # define __NR___sys_accept4 __NR_accept4
57 static _syscall4(int, __sys_accept4, int, fd, struct sockaddr *, addr, socklen_t *, addrlen, int, flags)
58 int accept4(int fd, struct sockaddr *addr, socklen_t * addrlen, int flags)
59 {
60 if (SINGLE_THREAD_P)
61 return __sys_accept4(fd, addr, addrlen, flags);
62 #ifdef __UCLIBC_HAS_THREADS_NATIVE__
63 else {
64 int oldtype = LIBC_CANCEL_ASYNC ();
65 int result = __sys_accept4(fd, addr, addrlen, flags);
66 LIBC_CANCEL_RESET (oldtype);
67 return result;
68 }
69 #endif
70 }
71 #elif defined(__NR_socketcall)
72 int accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags)
73 {
74 unsigned long args[4];
75
76 args[0] = fd;
77 args[1] = (unsigned long) addr;
78 args[2] = (unsigned long) addrlen;
79 args[3] = flags;
80 if (SINGLE_THREAD_P)
81 return __socketcall(SYS_ACCEPT4, args);
82 #ifdef __UCLIBC_HAS_THREADS_NATIVE__
83 else {
84 int oldtype = LIBC_CANCEL_ASYNC ();
85 int result = __socketcall(SYS_ACCEPT4, args);
86 LIBC_CANCEL_RESET (oldtype);
87 return result;
88 }
89 #endif
90 }
91 #endif
92 #endif
93
94 #ifdef L_bind
bind(int sockfd,const struct sockaddr * myaddr,socklen_t addrlen)95 int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
96 {
97 # ifdef __NR_bind
98 return INLINE_SYSCALL(bind, 3, sockfd, myaddr, addrlen);
99 # else
100 unsigned long args[3];
101
102 args[0] = sockfd;
103 args[1] = (unsigned long) myaddr;
104 args[2] = addrlen;
105 return __socketcall(SYS_BIND, args);
106 # endif
107 }
libc_hidden_def(bind)108 libc_hidden_def(bind)
109 #endif
110
111 #ifdef L_connect
112 static int __NC(connect)(int sockfd, const struct sockaddr *saddr, socklen_t addrlen)
113 {
114 # ifdef __NR_connect
115 return INLINE_SYSCALL(connect, 3, sockfd, saddr, addrlen);
116 # else
117 unsigned long args[3];
118
119 args[0] = sockfd;
120 args[1] = (unsigned long) saddr;
121 args[2] = addrlen;
122 return __socketcall(SYS_CONNECT, args);
123 # endif
124 }
125 CANCELLABLE_SYSCALL(int, connect, (int sockfd, const struct sockaddr *saddr, socklen_t addrlen),
126 (sockfd, saddr, addrlen))
lt_libc_hidden(connect)127 lt_libc_hidden(connect)
128 #endif
129
130 #ifdef L_getpeername
131 int getpeername(int sockfd, struct sockaddr *addr, socklen_t *paddrlen)
132 {
133 # ifdef __NR_getpeername
134 return INLINE_SYSCALL(getpeername, 3, sockfd, addr, paddrlen);
135 # else
136 unsigned long args[3];
137
138 args[0] = sockfd;
139 args[1] = (unsigned long) addr;
140 args[2] = (unsigned long) paddrlen;
141 return __socketcall(SYS_GETPEERNAME, args);
142 # endif
143 }
144 #endif
145
146 #ifdef L_getsockname
getsockname(int sockfd,struct sockaddr * addr,socklen_t * paddrlen)147 int getsockname(int sockfd, struct sockaddr *addr, socklen_t * paddrlen)
148 {
149 # ifdef __NR_getsockname
150 return INLINE_SYSCALL(getsockname, 3, sockfd, addr, paddrlen);
151 # else
152 unsigned long args[3];
153
154 args[0] = sockfd;
155 args[1] = (unsigned long) addr;
156 args[2] = (unsigned long) paddrlen;
157 return __socketcall(SYS_GETSOCKNAME, args);
158 # endif
159 }
libc_hidden_def(getsockname)160 libc_hidden_def(getsockname)
161 #endif
162
163 #ifdef L_getsockopt
164 int getsockopt(int fd, int level, int optname, void *optval,
165 socklen_t *optlen)
166 {
167 # ifdef __NR_getsockopt
168 return INLINE_SYSCALL(getsockopt, 5, fd, level, optname, optval, optlen);
169 # else
170 unsigned long args[5];
171
172 args[0] = fd;
173 args[1] = level;
174 args[2] = optname;
175 args[3] = (unsigned long) optval;
176 args[4] = (unsigned long) optlen;
177 return (__socketcall(SYS_GETSOCKOPT, args));
178 # endif
179 }
180 #endif
181
182 #ifdef L_listen
listen(int sockfd,int backlog)183 int listen(int sockfd, int backlog)
184 {
185 # ifdef __NR_listen
186 return INLINE_SYSCALL(listen, 2, sockfd, backlog);
187 # else
188 unsigned long args[2];
189
190 args[0] = sockfd;
191 args[1] = backlog;
192 return __socketcall(SYS_LISTEN, args);
193 # endif
194 }
libc_hidden_def(listen)195 libc_hidden_def(listen)
196 #endif
197
198 #ifdef L_recv
199 static ssize_t __NC(recv)(int sockfd, void *buffer, size_t len, int flags)
200 {
201 # ifdef __NR_recv
202 return (ssize_t)INLINE_SYSCALL(recv, 4, sockfd, buffer, len, flags);
203 # elif defined __NR_recvfrom && defined _syscall6
204 return __NC(recvfrom)(sockfd, buffer, len, flags, NULL, NULL);
205 # else
206 unsigned long args[4];
207
208 args[0] = sockfd;
209 args[1] = (unsigned long) buffer;
210 args[2] = len;
211 args[3] = flags;
212 return (ssize_t)__socketcall(SYS_RECV, args);
213 # endif
214 }
215 CANCELLABLE_SYSCALL(ssize_t, recv, (int sockfd, void *buffer, size_t len, int flags),
216 (sockfd, buffer, len, flags))
lt_libc_hidden(recv)217 lt_libc_hidden(recv)
218 #endif
219
220 #ifdef L_recvfrom
221 ssize_t __NC(recvfrom)(int sockfd, void *buffer, size_t len, int flags,
222 struct sockaddr *to, socklen_t *tolen)
223 {
224 # if defined __NR_recvfrom && defined _syscall6
225 return (ssize_t)INLINE_SYSCALL(recvfrom, 6, sockfd, buffer, len,
226 flags, to, tolen);
227 # else
228 unsigned long args[6];
229
230 args[0] = sockfd;
231 args[1] = (unsigned long) buffer;
232 args[2] = len;
233 args[3] = flags;
234 args[4] = (unsigned long) to;
235 args[5] = (unsigned long) tolen;
236 return (ssize_t)__socketcall(SYS_RECVFROM, args);
237 # endif
238 }
239 CANCELLABLE_SYSCALL(ssize_t, recvfrom, (int sockfd, void *buffer, size_t len,
240 int flags, struct sockaddr *to, socklen_t *tolen),
241 (sockfd, buffer, len, flags, to, tolen))
lt_libc_hidden(recvfrom)242 lt_libc_hidden(recvfrom)
243 #endif
244
245 #ifdef L_recvmsg
246 static ssize_t __NC(recvmsg)(int sockfd, struct msghdr *msg, int flags)
247 {
248 # ifdef __NR_recvmsg
249 return (ssize_t)INLINE_SYSCALL(recvmsg, 3, sockfd, msg, flags);
250 # else
251 unsigned long args[3];
252
253 args[0] = sockfd;
254 args[1] = (unsigned long) msg;
255 args[2] = flags;
256 return (ssize_t)__socketcall(SYS_RECVMSG, args);
257 # endif
258 }
259 CANCELLABLE_SYSCALL(ssize_t, recvmsg, (int sockfd, struct msghdr *msg, int flags),
260 (sockfd, msg, flags))
lt_libc_hidden(recvmsg)261 lt_libc_hidden(recvmsg)
262 #endif
263
264 #ifdef L_send
265 static ssize_t __NC(send)(int sockfd, const void *buffer, size_t len, int flags)
266 {
267 # ifdef __NR_send
268 return (ssize_t)INLINE_SYSCALL(send, 4, sockfd, buffer, len, flags);
269 # elif defined __NR_sendto && defined _syscall6
270 return __NC(sendto)(sockfd, buffer, len, flags, NULL, 0);
271 # else
272 unsigned long args[4];
273
274 args[0] = sockfd;
275 args[1] = (unsigned long) buffer;
276 args[2] = len;
277 args[3] = flags;
278 return (ssize_t)__socketcall(SYS_SEND, args);
279 # endif
280 }
281 CANCELLABLE_SYSCALL(ssize_t, send, (int sockfd, const void *buffer, size_t len, int flags),
282 (sockfd, buffer, len, flags))
lt_libc_hidden(send)283 lt_libc_hidden(send)
284 #endif
285
286 #ifdef L_sendmsg
287 static ssize_t __NC(sendmsg)(int sockfd, const struct msghdr *msg, int flags)
288 {
289 # ifdef __NR_sendmsg
290 return (ssize_t)INLINE_SYSCALL(sendmsg, 3, sockfd, msg, flags);
291 # else
292 unsigned long args[3];
293
294 args[0] = sockfd;
295 args[1] = (unsigned long) msg;
296 args[2] = flags;
297 return (ssize_t)__socketcall(SYS_SENDMSG, args);
298 # endif
299 }
300 CANCELLABLE_SYSCALL(ssize_t, sendmsg, (int sockfd, const struct msghdr *msg, int flags),
301 (sockfd, msg, flags))
lt_libc_hidden(sendmsg)302 lt_libc_hidden(sendmsg)
303 #endif
304
305 #ifdef L_sendto
306 ssize_t __NC(sendto)(int sockfd, const void *buffer, size_t len, int flags,
307 const struct sockaddr *to, socklen_t tolen)
308 {
309 # if defined __NR_sendto && defined _syscall6
310 return (ssize_t)INLINE_SYSCALL(sendto, 6, sockfd, buffer, len, flags, to, tolen);
311 # else
312 unsigned long args[6];
313
314 args[0] = sockfd;
315 args[1] = (unsigned long) buffer;
316 args[2] = len;
317 args[3] = flags;
318 args[4] = (unsigned long) to;
319 args[5] = tolen;
320 return (ssize_t)__socketcall(SYS_SENDTO, args);
321 # endif
322 }
323 CANCELLABLE_SYSCALL(ssize_t, sendto, (int sockfd, const void *buffer, size_t len,
324 int flags, const struct sockaddr *to, socklen_t tolen),
325 (sockfd, buffer, len, flags, to, tolen))
lt_libc_hidden(sendto)326 lt_libc_hidden(sendto)
327 #endif
328
329 #ifdef L_setsockopt
330 int setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
331 {
332 # ifdef __NR_setsockopt
333 return INLINE_SYSCALL(setsockopt, 5, fd, level, optname, optval, optlen);
334 # else
335 unsigned long args[5];
336
337 args[0] = fd;
338 args[1] = level;
339 args[2] = optname;
340 args[3] = (unsigned long) optval;
341 args[4] = optlen;
342 return __socketcall(SYS_SETSOCKOPT, args);
343 # endif
344 }
libc_hidden_def(setsockopt)345 libc_hidden_def(setsockopt)
346 #endif
347
348 #ifdef L_shutdown
349 int shutdown(int sockfd, int how)
350 {
351 # ifdef __NR_shutdown
352 return INLINE_SYSCALL(shutdown, 2, sockfd, how);
353 # else
354 unsigned long args[2];
355
356 args[0] = sockfd;
357 args[1] = how;
358 return __socketcall(SYS_SHUTDOWN, args);
359 # endif
360 }
361 #endif
362
363 #ifdef L_socket
socket(int family,int type,int protocol)364 int socket(int family, int type, int protocol)
365 {
366 # ifdef __NR_socket
367 return INLINE_SYSCALL(socket, 3, family, type, protocol);
368 # else
369 unsigned long args[3];
370
371 args[0] = family;
372 args[1] = type;
373 args[2] = (unsigned long) protocol;
374 return __socketcall(SYS_SOCKET, args);
375 # endif
376 }
libc_hidden_def(socket)377 libc_hidden_def(socket)
378 #endif
379
380 #ifdef L_socketpair
381 int socketpair(int family, int type, int protocol, int sockvec[2])
382 {
383 # ifdef __NR_socketpair
384 return INLINE_SYSCALL(socketpair, 4, family, type, protocol, sockvec);
385 # else
386 unsigned long args[4];
387
388 args[0] = family;
389 args[1] = type;
390 args[2] = protocol;
391 args[3] = (unsigned long) sockvec;
392 return __socketcall(SYS_SOCKETPAIR, args);
393 # endif
394 }
395 #endif
396