socketcalls.c 12 KB

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