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