Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sock.c 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
  3. * Copyright (c) 1996-2018 The strace developers.
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: LGPL-2.1-or-later
  7. */
  8. #include "defs.h"
  9. #include "print_fields.h"
  10. #include <sys/socket.h>
  11. #if defined ALPHA || defined SH || defined SH64
  12. # include <linux/ioctl.h>
  13. #endif
  14. #include <linux/sockios.h>
  15. #include <arpa/inet.h>
  16. #include <net/if.h>
  17. #include DEF_MPERS_TYPE(struct_ifconf)
  18. #include DEF_MPERS_TYPE(struct_ifreq)
  19. typedef struct ifconf struct_ifconf;
  20. typedef struct ifreq struct_ifreq;
  21. #include MPERS_DEFS
  22. #include "xlat/iffflags.h"
  23. #define XLAT_MACROS_ONLY
  24. #include "xlat/arp_hardware_types.h"
  25. #undef XLAT_MACROS_ONLY
  26. static void
  27. print_ifname(const char *ifname)
  28. {
  29. print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED);
  30. }
  31. static void
  32. print_ifreq(struct tcb *const tcp, const unsigned int code,
  33. const kernel_ulong_t arg, const struct_ifreq *const ifr)
  34. {
  35. switch (code) {
  36. case SIOCSIFADDR:
  37. case SIOCGIFADDR:
  38. PRINT_FIELD_SOCKADDR("", *ifr, ifr_addr);
  39. break;
  40. case SIOCSIFDSTADDR:
  41. case SIOCGIFDSTADDR:
  42. PRINT_FIELD_SOCKADDR("", *ifr, ifr_dstaddr);
  43. break;
  44. case SIOCSIFBRDADDR:
  45. case SIOCGIFBRDADDR:
  46. PRINT_FIELD_SOCKADDR("", *ifr, ifr_broadaddr);
  47. break;
  48. case SIOCSIFNETMASK:
  49. case SIOCGIFNETMASK:
  50. PRINT_FIELD_SOCKADDR("", *ifr, ifr_netmask);
  51. break;
  52. case SIOCSIFHWADDR:
  53. case SIOCGIFHWADDR: {
  54. PRINT_FIELD_XVAL("ifr_hwaddr={", ifr->ifr_hwaddr, sa_family,
  55. arp_hardware_types, "ARPHRD_???");
  56. PRINT_FIELD_HWADDR_SZ(", ", ifr->ifr_hwaddr, sa_data,
  57. sizeof(ifr->ifr_hwaddr.sa_data),
  58. ifr->ifr_hwaddr.sa_family);
  59. tprints("}");
  60. break;
  61. }
  62. case SIOCSIFFLAGS:
  63. case SIOCGIFFLAGS:
  64. tprints("ifr_flags=");
  65. printflags(iffflags, (unsigned short) ifr->ifr_flags, "IFF_???");
  66. break;
  67. case SIOCSIFMETRIC:
  68. case SIOCGIFMETRIC:
  69. tprintf("ifr_metric=%d", ifr->ifr_metric);
  70. break;
  71. case SIOCSIFMTU:
  72. case SIOCGIFMTU:
  73. tprintf("ifr_mtu=%d", ifr->ifr_mtu);
  74. break;
  75. case SIOCSIFSLAVE:
  76. case SIOCGIFSLAVE:
  77. tprints("ifr_slave=");
  78. print_ifname(ifr->ifr_slave);
  79. break;
  80. case SIOCSIFTXQLEN:
  81. case SIOCGIFTXQLEN:
  82. tprintf("ifr_qlen=%d", ifr->ifr_qlen);
  83. break;
  84. case SIOCSIFMAP:
  85. case SIOCGIFMAP:
  86. tprintf("ifr_map={mem_start=%#" PRI_klx ", "
  87. "mem_end=%#" PRI_klx ", base_addr=%#x, "
  88. "irq=%u, dma=%u, port=%u}",
  89. (kernel_ulong_t) ifr->ifr_map.mem_start,
  90. (kernel_ulong_t) ifr->ifr_map.mem_end,
  91. (unsigned) ifr->ifr_map.base_addr,
  92. (unsigned) ifr->ifr_map.irq,
  93. (unsigned) ifr->ifr_map.dma,
  94. (unsigned) ifr->ifr_map.port);
  95. break;
  96. }
  97. }
  98. static unsigned int
  99. print_ifc_len(int len)
  100. {
  101. const unsigned int n = (unsigned int) len / sizeof(struct_ifreq);
  102. if (len < 0 || n * sizeof(struct_ifreq) != (unsigned int) len)
  103. tprintf("%d", len);
  104. else
  105. tprintf("%u * sizeof(struct ifreq)", n);
  106. return n;
  107. }
  108. static bool
  109. print_ifconf_ifreq(struct tcb *tcp, void *elem_buf, size_t elem_size,
  110. void *dummy)
  111. {
  112. struct_ifreq *ifr = elem_buf;
  113. tprints("{ifr_name=");
  114. print_ifname(ifr->ifr_name);
  115. PRINT_FIELD_SOCKADDR(", ", *ifr, ifr_addr);
  116. tprints("}");
  117. return true;
  118. }
  119. /*
  120. * There are two different modes of operation:
  121. *
  122. * - Get buffer size. In this case, the callee sets ifc_buf to NULL,
  123. * and the kernel returns the buffer size in ifc_len.
  124. * - Get actual data. In this case, the callee specifies the buffer address
  125. * in ifc_buf and its size in ifc_len. The kernel fills the buffer with
  126. * the data, and its amount is returned in ifc_len.
  127. *
  128. * Note that, technically, the whole struct ifconf is overwritten,
  129. * so ifc_buf could be different on exit, but current ioctl handler
  130. * implementation does not touch it.
  131. */
  132. static int
  133. decode_ifconf(struct tcb *const tcp, const kernel_ulong_t addr)
  134. {
  135. struct_ifconf *entering_ifc = NULL;
  136. struct_ifconf *ifc =
  137. entering(tcp) ? malloc(sizeof(*ifc)) : alloca(sizeof(*ifc));
  138. if (exiting(tcp)) {
  139. entering_ifc = get_tcb_priv_data(tcp);
  140. if (!entering_ifc) {
  141. error_func_msg("where is my ifconf?");
  142. return 0;
  143. }
  144. }
  145. if (!ifc || umove(tcp, addr, ifc) < 0) {
  146. if (entering(tcp)) {
  147. free(ifc);
  148. tprints(", ");
  149. printaddr(addr);
  150. } else {
  151. /*
  152. * We failed to fetch the structure on exiting syscall,
  153. * print whatever was fetched on entering syscall.
  154. */
  155. if (!entering_ifc->ifc_buf)
  156. print_ifc_len(entering_ifc->ifc_len);
  157. tprints(", ifc_buf=");
  158. printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
  159. tprints("}");
  160. }
  161. return RVAL_IOCTL_DECODED;
  162. }
  163. if (entering(tcp)) {
  164. tprints(", {ifc_len=");
  165. if (ifc->ifc_buf)
  166. print_ifc_len(ifc->ifc_len);
  167. set_tcb_priv_data(tcp, ifc, free);
  168. return 0;
  169. }
  170. /* exiting */
  171. if (entering_ifc->ifc_buf && (entering_ifc->ifc_len != ifc->ifc_len))
  172. tprints(" => ");
  173. if (!entering_ifc->ifc_buf || (entering_ifc->ifc_len != ifc->ifc_len))
  174. print_ifc_len(ifc->ifc_len);
  175. tprints(", ifc_buf=");
  176. if (!entering_ifc->ifc_buf || syserror(tcp)) {
  177. printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
  178. if (entering_ifc->ifc_buf != ifc->ifc_buf) {
  179. tprints(" => ");
  180. printaddr(ptr_to_kulong(ifc->ifc_buf));
  181. }
  182. } else {
  183. struct_ifreq ifr;
  184. print_array(tcp, ptr_to_kulong(ifc->ifc_buf),
  185. ifc->ifc_len / sizeof(struct_ifreq),
  186. &ifr, sizeof(ifr),
  187. tfetch_mem, print_ifconf_ifreq, NULL);
  188. }
  189. tprints("}");
  190. return RVAL_IOCTL_DECODED;
  191. }
  192. MPERS_PRINTER_DECL(int, sock_ioctl,
  193. struct tcb *tcp, const unsigned int code,
  194. const kernel_ulong_t arg)
  195. {
  196. struct_ifreq ifr;
  197. switch (code) {
  198. case SIOCGIFCONF:
  199. return decode_ifconf(tcp, arg);
  200. #ifdef SIOCBRADDBR
  201. case SIOCBRADDBR:
  202. case SIOCBRDELBR:
  203. tprints(", ");
  204. printstr(tcp, arg);
  205. break;
  206. #endif
  207. #ifdef FIOSETOWN
  208. case FIOSETOWN:
  209. #endif
  210. #ifdef SIOCSPGRP
  211. case SIOCSPGRP:
  212. #endif
  213. tprints(", ");
  214. printnum_int(tcp, arg, "%d");
  215. break;
  216. #ifdef FIOGETOWN
  217. case FIOGETOWN:
  218. #endif
  219. #ifdef SIOCGPGRP
  220. case SIOCGPGRP:
  221. #endif
  222. #ifdef SIOCATMARK
  223. case SIOCATMARK:
  224. #endif
  225. if (entering(tcp))
  226. return 0;
  227. tprints(", ");
  228. printnum_int(tcp, arg, "%d");
  229. break;
  230. #ifdef SIOCBRADDIF
  231. case SIOCBRADDIF:
  232. #endif
  233. #ifdef SIOCBRDELIF
  234. case SIOCBRDELIF:
  235. #endif
  236. /* no arguments */
  237. break;
  238. case SIOCSIFNAME:
  239. case SIOCSIFADDR:
  240. case SIOCSIFDSTADDR:
  241. case SIOCSIFBRDADDR:
  242. case SIOCSIFNETMASK:
  243. case SIOCSIFFLAGS:
  244. case SIOCSIFMETRIC:
  245. case SIOCSIFMTU:
  246. case SIOCSIFSLAVE:
  247. case SIOCSIFHWADDR:
  248. case SIOCSIFTXQLEN:
  249. case SIOCSIFMAP:
  250. tprints(", ");
  251. if (umove_or_printaddr(tcp, arg, &ifr))
  252. break;
  253. tprints("{ifr_name=");
  254. print_ifname(ifr.ifr_name);
  255. tprints(", ");
  256. if (code == SIOCSIFNAME) {
  257. tprints("ifr_newname=");
  258. print_ifname(ifr.ifr_newname);
  259. } else {
  260. print_ifreq(tcp, code, arg, &ifr);
  261. }
  262. tprints("}");
  263. break;
  264. case SIOCGIFNAME:
  265. case SIOCGIFINDEX:
  266. case SIOCGIFADDR:
  267. case SIOCGIFDSTADDR:
  268. case SIOCGIFBRDADDR:
  269. case SIOCGIFNETMASK:
  270. case SIOCGIFFLAGS:
  271. case SIOCGIFMETRIC:
  272. case SIOCGIFMTU:
  273. case SIOCGIFSLAVE:
  274. case SIOCGIFHWADDR:
  275. case SIOCGIFTXQLEN:
  276. case SIOCGIFMAP:
  277. if (entering(tcp)) {
  278. tprints(", ");
  279. if (umove_or_printaddr(tcp, arg, &ifr))
  280. break;
  281. if (SIOCGIFNAME == code) {
  282. tprintf("{ifr_index=%d", ifr.ifr_ifindex);
  283. } else {
  284. tprints("{ifr_name=");
  285. print_ifname(ifr.ifr_name);
  286. }
  287. return 0;
  288. } else {
  289. if (syserror(tcp)) {
  290. tprints("}");
  291. break;
  292. }
  293. tprints(", ");
  294. if (umove(tcp, arg, &ifr) < 0) {
  295. tprints("???}");
  296. break;
  297. }
  298. if (SIOCGIFNAME == code) {
  299. tprints("ifr_name=");
  300. print_ifname(ifr.ifr_name);
  301. } else {
  302. print_ifreq(tcp, code, arg, &ifr);
  303. }
  304. tprints("}");
  305. break;
  306. }
  307. default:
  308. return RVAL_DECODED;
  309. }
  310. return RVAL_IOCTL_DECODED;
  311. }