static void decode_inet_diag_hostcond(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len) { struct inet_diag_hostcond cond; if (len < sizeof(cond)) { printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); return; } if (umove_or_printaddr(tcp, addr, &cond)) return; PRINT_FIELD_XVAL("{", cond, family, addrfams, "AF_???"); PRINT_FIELD_U(", ", cond, prefix_len); PRINT_FIELD_U(", ", cond, port); if (len > sizeof(cond)) { tprints(", "); decode_inet_addr(tcp, addr + sizeof(cond), len - sizeof(cond), cond.family, "addr"); } tprints("}"); }
static bool decode_gnet_stats_queue(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_GNET_STATS_QUEUE struct gnet_stats_queue qstats; if (len < sizeof(qstats)) return false; else if (!umove_or_printaddr(tcp, addr, &qstats)) { PRINT_FIELD_U("{", qstats, qlen); PRINT_FIELD_U(", ", qstats, backlog); PRINT_FIELD_U(", ", qstats, drops); PRINT_FIELD_U(", ", qstats, requeues); PRINT_FIELD_U(", ", qstats, overlimits); tprints("}"); } return true; #else return false; #endif }
static bool decode_ifla_inet6_cacheinfo(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct { uint32_t max_reasm_len; uint32_t tstamp; uint32_t reachable_time; uint32_t retrans_time; } ci; if (len < sizeof(ci)) return false; else if (!umove_or_printaddr(tcp, addr, &ci)) { PRINT_FIELD_U("{", ci, max_reasm_len); PRINT_FIELD_U(", ", ci, tstamp); PRINT_FIELD_U(", ", ci, reachable_time); PRINT_FIELD_U(", ", ci, retrans_time); tprints("}"); } return true; }
int main(void) { skip_if_unavailable("/proc/self/fd/"); const int fd = create_nl_socket(NETLINK_ROUTE); void *nlh0 = tail_alloc(NLMSG_SPACE(hdrlen)); static char pattern[4096]; fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1); const uint32_t num = 0xabacdbcd; TEST_NESTED_NLATTR_OBJECT(fd, nlh0, hdrlen, init_ifinfomsg, print_ifinfomsg, IFLA_PORT_VF, pattern, num, printf("%u", num)); #ifdef HAVE_STRUCT_IFLA_PORT_VSI static const struct ifla_port_vsi vsi = { .vsi_mgr_id = 0xab, .vsi_type_id = "abc", .vsi_type_version = 0xef }; TEST_NESTED_NLATTR_OBJECT(fd, nlh0, hdrlen, init_ifinfomsg, print_ifinfomsg, IFLA_PORT_VSI_TYPE, pattern, vsi, PRINT_FIELD_U("{", vsi, vsi_mgr_id); printf(", vsi_type_id=\"\\x61\\x62\\x63\""); PRINT_FIELD_U(", ", vsi, vsi_type_version); printf("}")); #endif puts("+++ exited with 0 +++"); return 0; }
static void print_inet_diag_bc_op(const struct inet_diag_bc_op *const op) { PRINT_FIELD_XVAL("{", *op, code, inet_diag_bytecodes, "INET_DIAG_BC_???"); PRINT_FIELD_U(", ", *op, yes); PRINT_FIELD_U(", ", *op, no); tprints("}"); }
void print_xquota_stat(int rc, void *ptr, void *arg) { struct fs_quota_stat *qs = ptr; long out_arg = (long) arg; if (((rc != 0) && out_arg) || (out_arg > 1)) { printf("%p", qs); return; } PRINT_FIELD_D("{", qs, qs_version); # if VERBOSE printf(", qs_flags="); printflags(xfs_quota_flags, qs->qs_flags, "XFS_QUOTA_???"); PRINT_FIELD_U(", qs_uquota={", &qs->qs_uquota, qfs_ino); PRINT_FIELD_U(", ", &qs->qs_uquota, qfs_nblks); PRINT_FIELD_U(", ", &qs->qs_uquota, qfs_nextents); PRINT_FIELD_U("}, qs_gquota={", &qs->qs_gquota, qfs_ino); PRINT_FIELD_U(", ", &qs->qs_gquota, qfs_nblks); PRINT_FIELD_U(", ", &qs->qs_gquota, qfs_nextents); PRINT_FIELD_U("}, ", qs, qs_incoredqs); PRINT_FIELD_D(", ", qs, qs_btimelimit); PRINT_FIELD_D(", ", qs, qs_itimelimit); PRINT_FIELD_D(", ", qs, qs_rtbtimelimit); PRINT_FIELD_U(", ", qs, qs_bwarnlimit); PRINT_FIELD_U(", ", qs, qs_iwarnlimit); # else printf(", ..."); # endif /* !VERBOSE */ printf("}"); }
static void print_packet_diag_mclist(const struct packet_diag_mclist *const dml, size_t i) { printf("{pdmc_index=" IFINDEX_LO_STR); PRINT_FIELD_U(", ", *dml, pdmc_count); PRINT_FIELD_U(", ", *dml, pdmc_type); PRINT_FIELD_U(", ", *dml, pdmc_alen); printf(", pdmc_addr="); print_quoted_hex(dml->pdmc_addr, dml->pdmc_alen); printf("}"); }
int main(void) { skip_if_unavailable("/proc/self/fd/"); const int fd = create_nl_socket(NETLINK_ROUTE); const unsigned int hdrlen = sizeof(struct ndmsg); void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), NLA_HDRLEN + sizeof(struct nda_cacheinfo)); static char pattern[4096]; fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1); const unsigned int nla_type = 0xffff & NLA_TYPE_MASK; char nla_type_str[256]; sprintf(nla_type_str, "%#x /* NDA_??? */", nla_type); TEST_NLATTR_(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg, nla_type, nla_type_str, 4, pattern, 4, print_quoted_hex(pattern, 4)); TEST_NLATTR(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg, NDA_DST, 4, pattern, 4, print_quoted_hex(pattern, 4)); static const struct nda_cacheinfo ci = { .ndm_confirmed = 0xabcdedad, .ndm_used = 0xbcdaedad, .ndm_updated = 0xcdbadeda, .ndm_refcnt = 0xdeadbeda }; TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg, NDA_CACHEINFO, pattern, ci, PRINT_FIELD_U("{", ci, ndm_confirmed); PRINT_FIELD_U(", ", ci, ndm_used); PRINT_FIELD_U(", ", ci, ndm_updated); PRINT_FIELD_U(", ", ci, ndm_refcnt); printf("}")); const uint16_t port = 0xabcd; TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg, NDA_PORT, pattern, port, printf("htons(%u)", ntohs(port))); puts("+++ exited with 0 +++"); return 0; }
static bool decode_tc_stats(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct tc_stats st; const unsigned int sizeof_tc_stats = offsetofend(struct tc_stats, backlog); if (len < sizeof_tc_stats) return false; else if (!umoven_or_printaddr(tcp, addr, sizeof_tc_stats, &st)) { PRINT_FIELD_U("{", st, bytes); PRINT_FIELD_U(", ", st, packets); PRINT_FIELD_U(", ", st, drops); PRINT_FIELD_U(", ", st, overlimits); PRINT_FIELD_U(", ", st, bps); PRINT_FIELD_U(", ", st, pps); PRINT_FIELD_U(", ", st, qlen); PRINT_FIELD_U(", ", st, backlog); tprints("}"); } return true; }
static void test_inet_diag_bc_s_cond(const int fd) { static const struct inet_diag_bc_op op = { .code = INET_DIAG_BC_S_COND, }; static const struct inet_diag_hostcond cond = { .family = AF_UNSPEC, .prefix_len = 0xad, .port = 0xadfa }; char buf[sizeof(op) + sizeof(cond)]; memcpy(buf, &op, sizeof(op)); const unsigned int plen = sizeof(cond) - 1 > DEFAULT_STRLEN ? sizeof(op) + DEFAULT_STRLEN : sizeof(buf) - 1; memcpy(buf + sizeof(op), &pattern, sizeof(cond)); TEST_NLATTR(fd, nlh0, hdrlen, init_inet_diag_req_v2, print_inet_diag_req_v2, INET_DIAG_REQ_BYTECODE, plen, buf, plen, print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); print_quoted_hex(buf + sizeof(op), plen - sizeof(op)); printf("}")); TEST_NLATTR(fd, nlh0, hdrlen, init_inet_diag_req_v2, print_inet_diag_req_v2, INET_DIAG_REQ_BYTECODE, sizeof(buf), buf, sizeof(buf) - 1, print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); printf("%p}", RTA_DATA(TEST_NLATTR_nla) + sizeof(op))); memcpy(buf + sizeof(op), &cond, sizeof(cond)); TEST_NLATTR(fd, nlh0, hdrlen, init_inet_diag_req_v2, print_inet_diag_req_v2, INET_DIAG_REQ_BYTECODE, sizeof(buf), buf, sizeof(buf), print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); printf("{family=AF_UNSPEC"); PRINT_FIELD_U(", ", cond, prefix_len); PRINT_FIELD_U(", ", cond, port); printf("}}")); } static void print_inet_diag_hostcond(const char *const family) { printf("{family=%s, prefix_len=0, port=0, ", family); }
static void decode_inet_diag_markcond(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len) { struct inet_diag_markcond markcond; if (len < sizeof(markcond)) printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); else if (!umove_or_printaddr(tcp, addr, &markcond)) { PRINT_FIELD_U("{", markcond, mark); PRINT_FIELD_U(", ", markcond, mask); tprints("}"); } }
bool decode_netlink_selinux(struct tcb *const tcp, const struct nlmsghdr *const nlmsghdr, const kernel_ulong_t addr, const unsigned int len) { switch (nlmsghdr->nlmsg_type) { case SELNL_MSG_SETENFORCE: { struct selnl_msg_setenforce msg; if (len < sizeof(msg)) printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); else if (!umove_or_printaddr(tcp, addr, &msg)) { PRINT_FIELD_D("{", msg, val); tprints("}"); } break; } case SELNL_MSG_POLICYLOAD: { struct selnl_msg_policyload msg; if (len < sizeof(msg)) printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); else if (!umove_or_printaddr(tcp, addr, &msg)) { PRINT_FIELD_U("{", msg, seqno); tprints("}"); } break; } default: return false; } return true; }
static bool print_packet_diag_mclist(struct tcb *const tcp, void *const elem_buf, const size_t elem_size, void *const opaque_data) { struct packet_diag_mclist *dml = elem_buf; uint16_t alen = dml->pdmc_alen > sizeof(dml->pdmc_addr) ? sizeof(dml->pdmc_addr) : dml->pdmc_alen; PRINT_FIELD_IFINDEX("{", *dml, pdmc_index); PRINT_FIELD_U(", ", *dml, pdmc_count); PRINT_FIELD_U(", ", *dml, pdmc_type); PRINT_FIELD_U(", ", *dml, pdmc_alen); PRINT_FIELD_STRING(", ", *dml, pdmc_addr, alen, QUOTE_FORCE_HEX); tprints("}"); return true; }
static bool decode_unix_diag_rqlen(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct unix_diag_rqlen rql; if (len < sizeof(rql)) return false; if (umove_or_printaddr(tcp, addr, &rql)) return true; PRINT_FIELD_U("{", rql, udiag_rqueue); PRINT_FIELD_U(", ", rql, udiag_wqueue); tprints("}"); return true; }
static void decode_inet_diag_req_compat(struct tcb *const tcp, const struct nlmsghdr *const nlmsghdr, const uint8_t family, const kernel_ulong_t addr, const unsigned int len) { struct inet_diag_req req = { .idiag_family = family }; size_t offset = sizeof(req.idiag_family); bool decode_nla = false; PRINT_FIELD_XVAL("{", req, idiag_family, addrfams, "AF_???"); tprints(", "); if (len >= sizeof(req)) { if (!umoven_or_printaddr(tcp, addr + offset, sizeof(req) - offset, (char *) &req + offset)) { PRINT_FIELD_U("", req, idiag_src_len); PRINT_FIELD_U(", ", req, idiag_dst_len); PRINT_FIELD_FLAGS(", ", req, idiag_ext, inet_diag_extended_flags, "1<<INET_DIAG_\?\?\?-1"); PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id, req.idiag_family); PRINT_FIELD_FLAGS(", ", req, idiag_states, tcp_state_flags, "1<<TCP_???"); PRINT_FIELD_U(", ", req, idiag_dbs); decode_nla = true; } } else tprints("..."); tprints("}"); offset = NLMSG_ALIGN(sizeof(req)); if (decode_nla && len > offset) { tprints(", "); decode_nlattr(tcp, addr + offset, len - offset, inet_diag_req_attrs, "INET_DIAG_REQ_???", inet_diag_req_nla_decoders, ARRAY_SIZE(inet_diag_req_nla_decoders), NULL); } }
static bool decode_tcpvegas_info(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct tcpvegas_info vegas; if (len < sizeof(vegas)) return false; if (umove_or_printaddr(tcp, addr, &vegas)) return true; PRINT_FIELD_U("{", vegas, tcpv_enabled); PRINT_FIELD_U(", ", vegas, tcpv_rttcnt); PRINT_FIELD_U(", ", vegas, tcpv_rtt); PRINT_FIELD_U(", ", vegas, tcpv_minrtt); tprints("}"); return true; }
static bool decode_inet_diag_meminfo(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct inet_diag_meminfo minfo; if (len < sizeof(minfo)) return false; if (umove_or_printaddr(tcp, addr, &minfo)) return true; PRINT_FIELD_U("{", minfo, idiag_rmem); PRINT_FIELD_U(", ", minfo, idiag_wmem); PRINT_FIELD_U(", ", minfo, idiag_fmem); PRINT_FIELD_U(", ", minfo, idiag_tmem); tprints("}"); return true; }
static bool decode_netlink_diag_ring(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct netlink_diag_ring ndr; if (len < sizeof(ndr)) return false; if (umove_or_printaddr(tcp, addr, &ndr)) return true; PRINT_FIELD_U("{", ndr, ndr_block_size); PRINT_FIELD_U(", ", ndr, ndr_block_nr); PRINT_FIELD_U(", ", ndr, ndr_frame_size); PRINT_FIELD_U(", ", ndr, ndr_frame_nr); tprints("}"); return true; }
bool decode_nla_linkinfo_xstats_can(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct strace_can_device_stats { uint32_t bus_error; uint32_t error_warning; uint32_t error_passive; uint32_t bus_off; uint32_t arbitration_lost; uint32_t restarts; } st; const unsigned int def_size = sizeof(st); const unsigned int size = (len >= def_size) ? def_size : 0; if (!size) return false; if (umoven_or_printaddr(tcp, addr, size, &st)) return true; PRINT_FIELD_U("{", st, bus_error); PRINT_FIELD_U(", ", st, error_warning); PRINT_FIELD_U(", ", st, error_passive); PRINT_FIELD_U(", ", st, bus_off); PRINT_FIELD_U(", ", st, arbitration_lost); PRINT_FIELD_U(", ", st, restarts); tprints("}"); return true; }
static bool decode_tc_sizespec(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_TC_SIZESPEC struct tc_sizespec s; if (len < sizeof(s)) return false; else if (!umove_or_printaddr(tcp, addr, &s)) { PRINT_FIELD_U("{", s, cell_log); PRINT_FIELD_U(", ", s, size_log); PRINT_FIELD_D(", ", s, cell_align); PRINT_FIELD_D(", ", s, overhead); PRINT_FIELD_U(", ", s, linklayer); PRINT_FIELD_U(", ", s, mpu); PRINT_FIELD_U(", ", s, mtu); PRINT_FIELD_U(", ", s, tsize); tprints("}"); } return true; #else return false; #endif }
static bool decode_tcp_bbr_info(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct tcp_bbr_info bbr; if (len < sizeof(bbr)) return false; if (umove_or_printaddr(tcp, addr, &bbr)) return true; PRINT_FIELD_X("{", bbr, bbr_bw_lo); PRINT_FIELD_X(", ", bbr, bbr_bw_hi); PRINT_FIELD_U(", ", bbr, bbr_min_rtt); PRINT_FIELD_U(", ", bbr, bbr_pacing_gain); PRINT_FIELD_U(", ", bbr, bbr_cwnd_gain); tprints("}"); return true; }
static bool decode_tcp_dctcp_info(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct tcp_dctcp_info dctcp; if (len < sizeof(dctcp)) return false; if (umove_or_printaddr(tcp, addr, &dctcp)) return true; PRINT_FIELD_U("{", dctcp, dctcp_enabled); PRINT_FIELD_U(", ", dctcp, dctcp_ce_state); PRINT_FIELD_U(", ", dctcp, dctcp_alpha); PRINT_FIELD_U(", ", dctcp, dctcp_ab_ecn); PRINT_FIELD_U(", ", dctcp, dctcp_ab_tot); tprints("}"); return true; }
static void test_inet_diag_bc_op(const int fd) { static const struct inet_diag_bc_op op = { .code = INET_DIAG_BC_S_COND, .yes = 0xaf, .no = 0xafcd }; TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, init_inet_diag_req_v2, print_inet_diag_req_v2, INET_DIAG_REQ_BYTECODE, pattern, op, printf("{code=INET_DIAG_BC_S_COND"); PRINT_FIELD_U(", ", op, yes); PRINT_FIELD_U(", ", op, no); printf("}")); } static void print_inet_diag_bc_op(const char *const code) { printf("{{code=%s, yes=0, no=0}, ", code); }
static bool decode_gnet_stats_rate_est64(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_GNET_STATS_RATE_EST64 struct gnet_stats_rate_est64 est; if (len < sizeof(est)) return false; else if (!umove_or_printaddr(tcp, addr, &est)) { PRINT_FIELD_U("{", est, bps); PRINT_FIELD_U(", ", est, pps); tprints("}"); } return true; #else return false; #endif }
static bool decode_gnet_stats_basic(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_GNET_STATS_BASIC struct gnet_stats_basic sb; const unsigned int sizeof_st_basic = offsetofend(struct gnet_stats_basic, packets); if (len < sizeof_st_basic) return false; else if (!umoven_or_printaddr(tcp, addr, sizeof_st_basic, &sb)) { PRINT_FIELD_U("{", sb, bytes); PRINT_FIELD_U(", ", sb, packets); tprints("}"); } return true; #else return false; #endif }
static bool decode_rtnl_link_ifmap(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct rtnl_link_ifmap map; const unsigned int sizeof_ifmap = offsetofend(struct rtnl_link_ifmap, port); if (len < sizeof_ifmap) return false; else if (!umoven_or_printaddr(tcp, addr, sizeof_ifmap, &map)) { PRINT_FIELD_X("{", map, mem_start); PRINT_FIELD_X(", ", map, mem_end); PRINT_FIELD_X(", ", map, base_addr); PRINT_FIELD_U(", ", map, irq); PRINT_FIELD_U(", ", map, dma); PRINT_FIELD_U(", ", map, port); tprints("}"); } return true; }
static bool decode_ifla_port_vsi(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_IFLA_PORT_VSI struct ifla_port_vsi vsi; if (len < sizeof(vsi)) return false; else if (!umove_or_printaddr(tcp, addr, &vsi)) { PRINT_FIELD_U("{", vsi, vsi_mgr_id); PRINT_FIELD_STRING(", ", vsi, vsi_type_id, sizeof(vsi.vsi_type_id), QUOTE_FORCE_HEX); PRINT_FIELD_U(", ", vsi, vsi_type_version); tprints("}"); } return true; #else return false; #endif }
static bool decode_packet_diag_info(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct packet_diag_info pinfo; if (len < sizeof(pinfo)) return false; if (umove_or_printaddr(tcp, addr, &pinfo)) return true; PRINT_FIELD_U("{", pinfo, pdi_index); PRINT_FIELD_U(", ", pinfo, pdi_version); PRINT_FIELD_U(", ", pinfo, pdi_reserve); PRINT_FIELD_U(", ", pinfo, pdi_copy_thresh); PRINT_FIELD_U(", ", pinfo, pdi_tstamp); PRINT_FIELD_FLAGS(", ", pinfo, pdi_flags, packet_diag_info_flags, "PDI_???"); tprints("}"); return true; }
static bool decode_tc_estimator(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct tc_estimator est; if (len < sizeof(est)) return false; else if (!umove_or_printaddr(tcp, addr, &est)) { PRINT_FIELD_D("{", est, interval); PRINT_FIELD_U(", ", est, ewma_log); tprints("}"); } return true; }
static bool decode_unix_diag_vfs(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct unix_diag_vfs uv; if (len < sizeof(uv)) return false; if (umove_or_printaddr(tcp, addr, &uv)) return true; PRINT_FIELD_DEV("{", uv, udiag_vfs_dev); PRINT_FIELD_U(", ", uv, udiag_vfs_ino); tprints("}"); return true; }