On Mon, Jul 11, 2016 at 12:54:59PM +0000, Fabien Siron wrote:
> Decode and print the type of the main netlink protocols.

JingPiao Chen, I've reworked Fabien's commits from your netlink branch
up to and including this one (52dc63cc "netlink: add type decoding")
for merge into master.  I've pushed them to ldv/netlink branch
and now waiting for a new version of your
"tests: add check for nlmsg_type decoding" commit to test these changes.

A few notes about Fabien's code that might be useful for your netlink efforts:

> @@ -96,7 +96,8 @@ print_iovec(struct tcb *tcp, void *elem_buf, size_t 
> elem_size, void *data)
>                               len = c->data_size;
>                       if (c->data_size != (kernel_ulong_t) -1)
>                               c->data_size -= len;
> -                     decode_netlink(tcp, iov[0], len);
> +                     decode_netlink(tcp, *(int *)c->optional_data,
> +                                    iov[0], len);
>                       break;
>               default:
>                       printaddr(iov[0]);
> @@ -354,7 +354,7 @@ print_struct_msghdr(struct tcb *tcp, const struct msghdr 
> *msg,
>       tprints(", msg_iov=");
>  
>       tprint_iov_upto(tcp, msg->msg_iovlen, ptr_to_kulong(msg->msg_iov),
> -                     decode, data_size, NULL);
> +                     decode, data_size, &tcp->u_arg[0]);
>       tprintf(", msg_iovlen=%" PRI_klu, (kernel_ulong_t) msg->msg_iovlen);
>  
>       decode_msg_control(tcp, ptr_to_kulong(msg->msg_control),

If sizeof(tcp->u_arg[0]) > sizeof(int), a wrong value will be passed to 
decode_netlink.

> @@ -29,9 +29,23 @@
>  
>  #include "defs.h"
>  #include <sys/socket.h>
> +#include <linux/audit.h>
> +#include <linux/inet_diag.h>
> +#include <linux/netfilter/nfnetlink.h>

linux/netfilter/nfnetlink.h was introduced in 2.6.14

> @@ -55,13 +69,62 @@ fetch_nlmsghdr(struct tcb *const tcp, struct nlmsghdr 
> *const nlmsghdr,
>  }
>  
>  static void
> -print_nlmsghdr(struct tcb *tcp, const struct nlmsghdr *const nlmsghdr)
> +decode_netlink_type(int type, int proto)
> +{
> +     if (type < NLMSG_MIN_TYPE) {
> +             printxval(netlink_types, type, "NLMSG_???");
> +     } else {
> +             const struct xlat *x;
> +             const char *dflt;
> +
> +             switch (proto) {
> +             case NETLINK_ROUTE:
> +                     x = netlink_route_types;
> +                     dflt = "RTM_???";
> +                     break;
> +             case NETLINK_SOCK_DIAG:
> +                     x = netlink_sock_diag_types;
> +                     dflt = "SOCK_DIAG_???";
> +                     break;
> +             case NETLINK_XFRM:
> +                     x = netlink_xfrm_types;
> +                     dflt = "XFRM_MSG_???";
> +                     break;
> +             case NETLINK_AUDIT:
> +                     x = netlink_audit_types;
> +                     dflt = "AUDIT_???";
> +                     break;
> +             case NETLINK_SELINUX:
> +                     x = netlink_selinux_types;
> +                     dflt = "SELNL_MSG_???";
> +                     break;
> +             case NETLINK_NETFILTER:
> +                     x = netlink_netfilter_ids;
> +                     dflt = "NFNL_SUBSYS_???";
> +                     break;
> +             default:
> +                     x = netlink_types;
> +                     dflt = "NLMSG_???";
> +             }
> +             if (proto == NETLINK_NETFILTER) {
> +                     tprints("{");
> +                     printxval(x, NFNL_SUBSYS_ID(type), dflt);
> +                     tprintf(", %d}", NFNL_MSG_TYPE(type));
> +             } else {
> +                     printxval(x, type, dflt);
> +             }
> +     }
> +}

Too much cut-n-paste in this switch statement.
I transformed it into a table:

static const struct {
        const struct xlat *const xlat;
        const char *const dflt;
} nlmsg_types[] = {
        [NETLINK_AUDIT] = { nl_audit_types, "AUDIT_???" },
        [NETLINK_ROUTE] = { nl_route_types, "RTM_???" },
        [NETLINK_SELINUX] = { nl_selinux_types, "SELNL_MSG_???" },
        [NETLINK_SOCK_DIAG] = { nl_sock_diag_types, "SOCK_DIAG_???" },
        [NETLINK_XFRM] = { nl_xfrm_types, "XFRM_MSG_???" }
};

if (family < ARRAY_SIZE(nlmsg_types)
    && nlmsg_types[family].xlat) {
        printxval(nlmsg_types[family].xlat, type, nlmsg_types[family].dflt);
} else {
        printxval(netlink_types, type, "NLMSG_???");
}

Well, not exactly into this because NETLINK_NETFILTER message types are not as
simple (even more complex than Fabien thought when he wrote this code).

> @@ -132,20 +196,21 @@ decode_payload(struct tcb *const tcp,
>  }
>  
>  static void
> -decode_nlmsghdr_with_payload(struct tcb *const tcp,
> +decode_nlmsghdr_with_payload(struct tcb *const tcp, int fd,
>                            const struct nlmsghdr *const nlmsghdr,
>                            const kernel_ulong_t addr,
>                            const kernel_ulong_t len)
>  {
>       tprints("{");
>  
> -     print_nlmsghdr(tcp, nlmsghdr);
> +     int proto = getfdnlproto(tcp, fd, netlink_protocols);
> +     print_nlmsghdr(tcp, nlmsghdr, proto);

getfdnlproto (get_fd_nl_family in my edition) is not cheap
(it invokes syscalls), needless calls should be avoided.


-- 
ldv

Attachment: signature.asc
Description: PGP signature

------------------------------------------------------------------------------
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

Reply via email to