* netlink_sock_diag.c: Include "xlat/inet_diag_bytecodes.h". (decode_inet_addr, decode_inet_diag_hostcond, print_inet_diag_bc_op, decode_inet_diag_markcond, decode_bytecode_data, decode_inet_diag_bc_op): New functions. (inet_diag_req_nla_decoders): New array. (decode_inet_diag_req_compat, decode_inet_diag_req_v2): Use it. * linux/inet_diag.h (inet_diag_bc_op, inet_diag_hostcond, inet_diag_markcond): New structures. (INET_DIAG_BC_*): New enum. * xlat/inet_diag_bytecodes.in: New file. --- linux/inet_diag.h | 32 ++++++++ netlink_sock_diag.c | 188 +++++++++++++++++++++++++++++++++++++++++++- xlat/inet_diag_bytecodes.in | 12 +++ 3 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 xlat/inet_diag_bytecodes.in
diff --git a/linux/inet_diag.h b/linux/inet_diag.h index 24302db..ec6356c 100644 --- a/linux/inet_diag.h +++ b/linux/inet_diag.h @@ -39,6 +39,38 @@ enum { INET_DIAG_REQ_BYTECODE, }; +struct inet_diag_bc_op { + unsigned char code; + unsigned char yes; + unsigned short no; +}; + +enum { + INET_DIAG_BC_NOP, + INET_DIAG_BC_JMP, + INET_DIAG_BC_S_GE, + INET_DIAG_BC_S_LE, + INET_DIAG_BC_D_GE, + INET_DIAG_BC_D_LE, + INET_DIAG_BC_AUTO, + INET_DIAG_BC_S_COND, + INET_DIAG_BC_D_COND, + INET_DIAG_BC_DEV_COND, /* u32 ifindex */ + INET_DIAG_BC_MARK_COND, +}; + +struct inet_diag_hostcond { + uint8_t family; + uint8_t prefix_len; + int port; + uint32_t addr[0]; +}; + +struct inet_diag_markcond { + uint32_t mark; + uint32_t mask; +}; + /* Info structure */ struct inet_diag_msg { uint8_t idiag_family; diff --git a/netlink_sock_diag.c b/netlink_sock_diag.c index 42860aa..29d61cb 100644 --- a/netlink_sock_diag.c +++ b/netlink_sock_diag.c @@ -43,6 +43,7 @@ #include <linux/unix_diag.h> #include "xlat/inet_diag_attrs.h" +#include "xlat/inet_diag_bytecodes.h" #include "xlat/inet_diag_extended_flags.h" #include "xlat/inet_diag_req_attrs.h" @@ -620,6 +621,187 @@ print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family) } static void +decode_inet_addr(struct tcb *const tcp, + const kernel_ulong_t addr, + const kernel_ulong_t len, + const int family) +{ + switch (family) { + case AF_INET: { + struct in_addr in_addr; + + if (len < sizeof(in_addr)) { + printstrn(tcp, addr, len); + break; + } + + if (umove_or_printaddr(tcp, addr, &in_addr)) + break; + + print_inet_addr(family, &in_addr.s_addr, + sizeof(in_addr.s_addr), "addr.s_addr"); + break; + } + case AF_INET6: { + struct in6_addr in6_addr; + + if (len < sizeof(in6_addr)) { + printstrn(tcp, addr, len); + break; + } + if (umove_or_printaddr(tcp, addr, &in6_addr)) + break; + + print_inet_addr(family, in6_addr.s6_addr, + sizeof(in6_addr.s6_addr),"addr.s6_addr"); + break; + } + default: + tprints("addr="); + printstrn(tcp, addr, len); + break; + } +} + +static void +decode_inet_diag_hostcond(struct tcb *const tcp, + const kernel_ulong_t addr, + const kernel_ulong_t 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); + } + tprints("}"); +} + +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("}"); +} + +static void +decode_inet_diag_markcond(struct tcb *const tcp, + const kernel_ulong_t addr, + const kernel_ulong_t len) +{ + struct inet_diag_markcond markcond; + + if (len < sizeof(markcond)) { + printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); + return; + } + if (umove_or_printaddr(tcp, addr, &markcond)) + return; + + PRINT_FIELD_U("{", markcond, mark); + PRINT_FIELD_U(", ", markcond, mask); + tprints("}"); +} + +static void +decode_bytecode_data(struct tcb *const tcp, + const kernel_ulong_t addr, + const kernel_ulong_t len, + const unsigned char code) +{ + switch (code) { + case INET_DIAG_BC_S_COND: + case INET_DIAG_BC_D_COND: + decode_inet_diag_hostcond(tcp, addr, len); + break; + case INET_DIAG_BC_DEV_COND: { + uint32_t ifindex; + + if (len < sizeof(ifindex)) { + printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); + break; + } + if (umove_or_printaddr(tcp, addr, &ifindex)) + break; + + tprintf("%" PRIu32, ifindex); + break; + } + case INET_DIAG_BC_S_GE: + case INET_DIAG_BC_S_LE: + case INET_DIAG_BC_D_GE: + case INET_DIAG_BC_D_LE: { + struct inet_diag_bc_op op; + + if (len < sizeof(op)) { + printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); + break; + } + if (umove_or_printaddr(tcp, addr, &op)) + break; + + print_inet_diag_bc_op(&op); + break; + } + case INET_DIAG_BC_MARK_COND: + decode_inet_diag_markcond(tcp, addr, len); + break; + case INET_DIAG_BC_AUTO: + case INET_DIAG_BC_JMP: + case INET_DIAG_BC_NOP: + default: + printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); + break; + } +} + +static bool +decode_inet_diag_bc_op(struct tcb *const tcp, + const kernel_ulong_t addr, + const kernel_ulong_t len, + const void *const opaque_data) +{ + struct inet_diag_bc_op op; + + if (len < sizeof(op)) + return false; + if (umove_or_printaddr(tcp, addr, &op)) + return true; + + if (len > sizeof(op)) + tprints("{"); + + print_inet_diag_bc_op(&op); + if (len > sizeof(op)) { + tprints(", "); + decode_bytecode_data(tcp, addr + sizeof(op), + len - sizeof(op), op.code); + tprints("}"); + } + + return true; +} + +static const nla_decoder_t inet_diag_req_nla_decoders[] = { + [INET_DIAG_REQ_BYTECODE] = decode_inet_diag_bc_op +}; + +static void decode_inet_diag_req_compat(struct tcb *const tcp, const struct nlmsghdr *const nlmsghdr, const uint8_t family, @@ -657,7 +839,8 @@ decode_inet_diag_req_compat(struct tcb *const tcp, tprints(", "); decode_nlattr(tcp, addr + offset, len - offset, inet_diag_req_attrs, "INET_DIAG_REQ_???", - NULL, 0, NULL); + inet_diag_req_nla_decoders, + ARRAY_SIZE(inet_diag_req_nla_decoders), NULL); } } @@ -698,7 +881,8 @@ decode_inet_diag_req_v2(struct tcb *const tcp, tprints(", "); decode_nlattr(tcp, addr + offset, len - offset, inet_diag_req_attrs, "INET_DIAG_REQ_???", - NULL, 0, NULL); + inet_diag_req_nla_decoders, + ARRAY_SIZE(inet_diag_req_nla_decoders), NULL); } } diff --git a/xlat/inet_diag_bytecodes.in b/xlat/inet_diag_bytecodes.in new file mode 100644 index 0000000..ccaf0da --- /dev/null +++ b/xlat/inet_diag_bytecodes.in @@ -0,0 +1,12 @@ +#unconditional +INET_DIAG_BC_NOP +INET_DIAG_BC_JMP +INET_DIAG_BC_S_GE +INET_DIAG_BC_S_LE +INET_DIAG_BC_D_GE +INET_DIAG_BC_D_LE +INET_DIAG_BC_AUTO +INET_DIAG_BC_S_COND +INET_DIAG_BC_D_COND +INET_DIAG_BC_DEV_COND +INET_DIAG_BC_MARK_COND -- 2.7.4 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel