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.

netlink_inet_diag.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
  3. * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
  4. * Copyright (c) 2017-2018 The strace developers.
  5. * All rights reserved.
  6. *
  7. * SPDX-License-Identifier: LGPL-2.1-or-later
  8. */
  9. #include "defs.h"
  10. #include "netlink.h"
  11. #include "netlink_sock_diag.h"
  12. #include "nlattr.h"
  13. #include "print_fields.h"
  14. #include <arpa/inet.h>
  15. #include <linux/sock_diag.h>
  16. #include <linux/inet_diag.h>
  17. #include "xlat/inet_diag_attrs.h"
  18. #include "xlat/inet_diag_bytecodes.h"
  19. #include "xlat/inet_diag_extended_flags.h"
  20. #include "xlat/inet_diag_req_attrs.h"
  21. #include "xlat/tcp_states.h"
  22. #include "xlat/tcp_state_flags.h"
  23. void
  24. print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
  25. {
  26. PRINT_FIELD_NET_PORT("{", *id, idiag_sport);
  27. PRINT_FIELD_NET_PORT(", ", *id, idiag_dport);
  28. PRINT_FIELD_INET_ADDR(", ", *id, idiag_src, family);
  29. PRINT_FIELD_INET_ADDR(", ", *id, idiag_dst, family);
  30. PRINT_FIELD_IFINDEX(", ", *id, idiag_if);
  31. PRINT_FIELD_COOKIE(", ", *id, idiag_cookie);
  32. tprints("}");
  33. }
  34. static void
  35. decode_inet_diag_hostcond(struct tcb *const tcp,
  36. const kernel_ulong_t addr,
  37. const unsigned int len)
  38. {
  39. struct inet_diag_hostcond cond;
  40. if (len < sizeof(cond)) {
  41. printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
  42. return;
  43. }
  44. if (umove_or_printaddr(tcp, addr, &cond))
  45. return;
  46. PRINT_FIELD_XVAL("{", cond, family, addrfams, "AF_???");
  47. PRINT_FIELD_U(", ", cond, prefix_len);
  48. PRINT_FIELD_U(", ", cond, port);
  49. if (len > sizeof(cond)) {
  50. tprints(", ");
  51. decode_inet_addr(tcp, addr + sizeof(cond),
  52. len - sizeof(cond), cond.family, "addr");
  53. }
  54. tprints("}");
  55. }
  56. static void
  57. print_inet_diag_bc_op(const struct inet_diag_bc_op *const op)
  58. {
  59. PRINT_FIELD_XVAL("{", *op, code, inet_diag_bytecodes,
  60. "INET_DIAG_BC_???");
  61. PRINT_FIELD_U(", ", *op, yes);
  62. PRINT_FIELD_U(", ", *op, no);
  63. tprints("}");
  64. }
  65. static void
  66. decode_inet_diag_markcond(struct tcb *const tcp,
  67. const kernel_ulong_t addr,
  68. const unsigned int len)
  69. {
  70. struct inet_diag_markcond markcond;
  71. if (len < sizeof(markcond))
  72. printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
  73. else if (!umove_or_printaddr(tcp, addr, &markcond)) {
  74. PRINT_FIELD_U("{", markcond, mark);
  75. PRINT_FIELD_U(", ", markcond, mask);
  76. tprints("}");
  77. }
  78. }
  79. static void
  80. decode_bytecode_data(struct tcb *const tcp,
  81. const kernel_ulong_t addr,
  82. const unsigned int len,
  83. const unsigned char code)
  84. {
  85. switch (code) {
  86. case INET_DIAG_BC_S_COND:
  87. case INET_DIAG_BC_D_COND:
  88. decode_inet_diag_hostcond(tcp, addr, len);
  89. break;
  90. case INET_DIAG_BC_DEV_COND: {
  91. uint32_t ifindex;
  92. if (len < sizeof(ifindex))
  93. printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
  94. else if (!umove_or_printaddr(tcp, addr, &ifindex))
  95. print_ifindex(ifindex);
  96. break;
  97. }
  98. case INET_DIAG_BC_S_GE:
  99. case INET_DIAG_BC_S_LE:
  100. case INET_DIAG_BC_D_GE:
  101. case INET_DIAG_BC_D_LE: {
  102. struct inet_diag_bc_op op;
  103. if (len < sizeof(op))
  104. printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
  105. else if (!umove_or_printaddr(tcp, addr, &op))
  106. print_inet_diag_bc_op(&op);
  107. break;
  108. }
  109. case INET_DIAG_BC_MARK_COND:
  110. decode_inet_diag_markcond(tcp, addr, len);
  111. break;
  112. case INET_DIAG_BC_AUTO:
  113. case INET_DIAG_BC_JMP:
  114. case INET_DIAG_BC_NOP:
  115. default:
  116. printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
  117. break;
  118. }
  119. }
  120. static bool
  121. decode_inet_diag_bc_op(struct tcb *const tcp,
  122. const kernel_ulong_t addr,
  123. const unsigned int len,
  124. const void *const opaque_data)
  125. {
  126. struct inet_diag_bc_op op;
  127. if (len < sizeof(op))
  128. return false;
  129. if (umove_or_printaddr(tcp, addr, &op))
  130. return true;
  131. if (len > sizeof(op))
  132. tprints("{");
  133. print_inet_diag_bc_op(&op);
  134. if (len > sizeof(op)) {
  135. tprints(", ");
  136. decode_bytecode_data(tcp, addr + sizeof(op),
  137. len - sizeof(op), op.code);
  138. tprints("}");
  139. }
  140. return true;
  141. }
  142. static const nla_decoder_t inet_diag_req_nla_decoders[] = {
  143. [INET_DIAG_REQ_BYTECODE] = decode_inet_diag_bc_op
  144. };
  145. static void
  146. decode_inet_diag_req_compat(struct tcb *const tcp,
  147. const struct nlmsghdr *const nlmsghdr,
  148. const uint8_t family,
  149. const kernel_ulong_t addr,
  150. const unsigned int len)
  151. {
  152. struct inet_diag_req req = { .idiag_family = family };
  153. size_t offset = sizeof(req.idiag_family);
  154. bool decode_nla = false;
  155. PRINT_FIELD_XVAL("{", req, idiag_family, addrfams, "AF_???");
  156. tprints(", ");
  157. if (len >= sizeof(req)) {
  158. if (!umoven_or_printaddr(tcp, addr + offset,
  159. sizeof(req) - offset,
  160. (char *) &req + offset)) {
  161. PRINT_FIELD_U("", req, idiag_src_len);
  162. PRINT_FIELD_U(", ", req, idiag_dst_len);
  163. PRINT_FIELD_FLAGS(", ", req, idiag_ext,
  164. inet_diag_extended_flags,
  165. "1<<INET_DIAG_\?\?\?-1");
  166. PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id,
  167. req.idiag_family);
  168. PRINT_FIELD_FLAGS(", ", req, idiag_states,
  169. tcp_state_flags, "1<<TCP_???");
  170. PRINT_FIELD_U(", ", req, idiag_dbs);
  171. decode_nla = true;
  172. }
  173. } else
  174. tprints("...");
  175. tprints("}");
  176. offset = NLMSG_ALIGN(sizeof(req));
  177. if (decode_nla && len > offset) {
  178. tprints(", ");
  179. decode_nlattr(tcp, addr + offset, len - offset,
  180. inet_diag_req_attrs, "INET_DIAG_REQ_???",
  181. inet_diag_req_nla_decoders,
  182. ARRAY_SIZE(inet_diag_req_nla_decoders), NULL);
  183. }
  184. }
  185. static void
  186. decode_inet_diag_req_v2(struct tcb *const tcp,
  187. const struct nlmsghdr *const nlmsghdr,
  188. const uint8_t family,
  189. const kernel_ulong_t addr,
  190. const unsigned int len)
  191. {
  192. struct inet_diag_req_v2 req = { .sdiag_family = family };
  193. size_t offset = sizeof(req.sdiag_family);
  194. bool decode_nla = false;
  195. PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
  196. tprints(", ");
  197. if (len >= sizeof(req)) {
  198. if (!umoven_or_printaddr(tcp, addr + offset,
  199. sizeof(req) - offset,
  200. (char *) &req + offset)) {
  201. PRINT_FIELD_XVAL("", req, sdiag_protocol,
  202. inet_protocols, "IPPROTO_???");
  203. PRINT_FIELD_FLAGS(", ", req, idiag_ext,
  204. inet_diag_extended_flags,
  205. "1<<INET_DIAG_\?\?\?-1");
  206. PRINT_FIELD_FLAGS(", ", req, idiag_states,
  207. tcp_state_flags, "1<<TCP_???");
  208. PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id,
  209. req.sdiag_family);
  210. decode_nla = true;
  211. }
  212. } else
  213. tprints("...");
  214. tprints("}");
  215. offset = NLMSG_ALIGN(sizeof(req));
  216. if (decode_nla && len > offset) {
  217. tprints(", ");
  218. decode_nlattr(tcp, addr + offset, len - offset,
  219. inet_diag_req_attrs, "INET_DIAG_REQ_???",
  220. inet_diag_req_nla_decoders,
  221. ARRAY_SIZE(inet_diag_req_nla_decoders), NULL);
  222. }
  223. }
  224. DECL_NETLINK_DIAG_DECODER(decode_inet_diag_req)
  225. {
  226. if (nlmsghdr->nlmsg_type == TCPDIAG_GETSOCK
  227. || nlmsghdr->nlmsg_type == DCCPDIAG_GETSOCK)
  228. decode_inet_diag_req_compat(tcp, nlmsghdr, family, addr, len);
  229. else
  230. decode_inet_diag_req_v2(tcp, nlmsghdr, family, addr, len);
  231. }
  232. static bool
  233. decode_inet_diag_meminfo(struct tcb *const tcp,
  234. const kernel_ulong_t addr,
  235. const unsigned int len,
  236. const void *const opaque_data)
  237. {
  238. struct inet_diag_meminfo minfo;
  239. if (len < sizeof(minfo))
  240. return false;
  241. if (umove_or_printaddr(tcp, addr, &minfo))
  242. return true;
  243. PRINT_FIELD_U("{", minfo, idiag_rmem);
  244. PRINT_FIELD_U(", ", minfo, idiag_wmem);
  245. PRINT_FIELD_U(", ", minfo, idiag_fmem);
  246. PRINT_FIELD_U(", ", minfo, idiag_tmem);
  247. tprints("}");
  248. return true;
  249. }
  250. static bool
  251. decode_tcpvegas_info(struct tcb *const tcp,
  252. const kernel_ulong_t addr,
  253. const unsigned int len,
  254. const void *const opaque_data)
  255. {
  256. struct tcpvegas_info vegas;
  257. if (len < sizeof(vegas))
  258. return false;
  259. if (umove_or_printaddr(tcp, addr, &vegas))
  260. return true;
  261. PRINT_FIELD_U("{", vegas, tcpv_enabled);
  262. PRINT_FIELD_U(", ", vegas, tcpv_rttcnt);
  263. PRINT_FIELD_U(", ", vegas, tcpv_rtt);
  264. PRINT_FIELD_U(", ", vegas, tcpv_minrtt);
  265. tprints("}");
  266. return true;
  267. }
  268. static bool
  269. decode_tcp_dctcp_info(struct tcb *const tcp,
  270. const kernel_ulong_t addr,
  271. const unsigned int len,
  272. const void *const opaque_data)
  273. {
  274. struct tcp_dctcp_info dctcp;
  275. if (len < sizeof(dctcp))
  276. return false;
  277. if (umove_or_printaddr(tcp, addr, &dctcp))
  278. return true;
  279. PRINT_FIELD_U("{", dctcp, dctcp_enabled);
  280. PRINT_FIELD_U(", ", dctcp, dctcp_ce_state);
  281. PRINT_FIELD_U(", ", dctcp, dctcp_alpha);
  282. PRINT_FIELD_U(", ", dctcp, dctcp_ab_ecn);
  283. PRINT_FIELD_U(", ", dctcp, dctcp_ab_tot);
  284. tprints("}");
  285. return true;
  286. }
  287. static bool
  288. decode_tcp_bbr_info(struct tcb *const tcp,
  289. const kernel_ulong_t addr,
  290. const unsigned int len,
  291. const void *const opaque_data)
  292. {
  293. struct tcp_bbr_info bbr;
  294. if (len < sizeof(bbr))
  295. return false;
  296. if (umove_or_printaddr(tcp, addr, &bbr))
  297. return true;
  298. PRINT_FIELD_X("{", bbr, bbr_bw_lo);
  299. PRINT_FIELD_X(", ", bbr, bbr_bw_hi);
  300. PRINT_FIELD_U(", ", bbr, bbr_min_rtt);
  301. PRINT_FIELD_U(", ", bbr, bbr_pacing_gain);
  302. PRINT_FIELD_U(", ", bbr, bbr_cwnd_gain);
  303. tprints("}");
  304. return true;
  305. }
  306. static const nla_decoder_t inet_diag_msg_nla_decoders[] = {
  307. [INET_DIAG_MEMINFO] = decode_inet_diag_meminfo,
  308. [INET_DIAG_INFO] = NULL, /* unimplemented */
  309. [INET_DIAG_VEGASINFO] = decode_tcpvegas_info,
  310. [INET_DIAG_CONG] = decode_nla_str,
  311. [INET_DIAG_TOS] = decode_nla_u8,
  312. [INET_DIAG_TCLASS] = decode_nla_u8,
  313. [INET_DIAG_SKMEMINFO] = decode_nla_meminfo,
  314. [INET_DIAG_SHUTDOWN] = decode_nla_u8,
  315. [INET_DIAG_DCTCPINFO] = decode_tcp_dctcp_info,
  316. [INET_DIAG_PROTOCOL] = decode_nla_u8,
  317. [INET_DIAG_SKV6ONLY] = decode_nla_u8,
  318. [INET_DIAG_LOCALS] = NULL, /* unimplemented */
  319. [INET_DIAG_PEERS] = NULL, /* unimplemented */
  320. [INET_DIAG_PAD] = NULL,
  321. [INET_DIAG_MARK] = decode_nla_u32,
  322. [INET_DIAG_BBRINFO] = decode_tcp_bbr_info,
  323. [INET_DIAG_CLASS_ID] = decode_nla_u32
  324. };
  325. DECL_NETLINK_DIAG_DECODER(decode_inet_diag_msg)
  326. {
  327. struct inet_diag_msg msg = { .idiag_family = family };
  328. size_t offset = sizeof(msg.idiag_family);
  329. bool decode_nla = false;
  330. PRINT_FIELD_XVAL("{", msg, idiag_family, addrfams, "AF_???");
  331. tprints(", ");
  332. if (len >= sizeof(msg)) {
  333. if (!umoven_or_printaddr(tcp, addr + offset,
  334. sizeof(msg) - offset,
  335. (char *) &msg + offset)) {
  336. PRINT_FIELD_XVAL("", msg, idiag_state,
  337. tcp_states, "TCP_???");
  338. PRINT_FIELD_U(", ", msg, idiag_timer);
  339. PRINT_FIELD_U(", ", msg, idiag_retrans);
  340. PRINT_FIELD_INET_DIAG_SOCKID(", ", msg, id,
  341. msg.idiag_family);
  342. PRINT_FIELD_U(", ", msg, idiag_expires);
  343. PRINT_FIELD_U(", ", msg, idiag_rqueue);
  344. PRINT_FIELD_U(", ", msg, idiag_wqueue);
  345. PRINT_FIELD_U(", ", msg, idiag_uid);
  346. PRINT_FIELD_U(", ", msg, idiag_inode);
  347. decode_nla = true;
  348. }
  349. } else
  350. tprints("...");
  351. tprints("}");
  352. offset = NLMSG_ALIGN(sizeof(msg));
  353. if (decode_nla && len > offset) {
  354. tprints(", ");
  355. decode_nlattr(tcp, addr + offset, len - offset,
  356. inet_diag_attrs, "INET_DIAG_???",
  357. inet_diag_msg_nla_decoders,
  358. ARRAY_SIZE(inet_diag_msg_nla_decoders), NULL);
  359. }
  360. }