Handle the case where there are several messages in the buffer. This is very useful to some protocols like SOCK_DIAG.
* netlink.c (nlmsg_fetch, nlmsg_next): New functions. (decode_netlink_msg): New function. (decode_netlink): Call decode_netlink_msg(). * tests/netlink_parsing.c (send_query): Adapt test. --- netlink.c | 85 +++++++++++++++++++++++++++++++++++++++++-------- tests/netlink_parsing.c | 19 ++++++++++- 2 files changed, 90 insertions(+), 14 deletions(-) diff --git a/netlink.c b/netlink.c index c43f6e7..e05e50c 100644 --- a/netlink.c +++ b/netlink.c @@ -31,34 +31,93 @@ #include "xlat/netlink_flags.h" #include "xlat/netlink_types.h" -void -decode_netlink(struct tcb *tcp, unsigned long addr, unsigned long size) -{ - struct nlmsghdr nlmsghdr; +/* since our target is not in the same process, here are some utils for nlmsg */ +static int +nlmsg_fetch(struct tcb *tcp, struct nlmsghdr *nlmsghdr, unsigned long addr, + unsigned long len) { + if (len < sizeof(struct nlmsghdr)) { + if (len != 0) + printstr(tcp, addr, len); + return 0; + } + + if (umove_or_printaddr(tcp, addr, nlmsghdr) == -1) + return 0; + + if (len < nlmsghdr->nlmsg_len) { + printstr(tcp, addr, len); + return 0; + } + + return 1; +} +static unsigned long +nlmsg_next(struct nlmsghdr *nlmsghdr, unsigned long addr, unsigned long *len) { + if (NLMSG_ALIGN(nlmsghdr->nlmsg_len) == 0 || + NLMSG_ALIGN(nlmsghdr->nlmsg_len) > *len) + return 0; + + *len -= NLMSG_ALIGN(nlmsghdr->nlmsg_len); + + if (addr + NLMSG_ALIGN(nlmsghdr->nlmsg_len) > addr) { + return addr + NLMSG_ALIGN(nlmsghdr->nlmsg_len); + } else { + *len = 0; + return 0; + } +} + +static void +decode_netlink_msg(struct tcb *tcp, struct nlmsghdr *nlmsghdr, + unsigned long addr, unsigned long size) +{ if (size < sizeof(struct nlmsghdr)) { printstr(tcp, addr, size); return; } - if (umove_or_printaddr(tcp, addr, &nlmsghdr)) - return; - tprintf("{{len=%u, type=", nlmsghdr.nlmsg_len); + tprintf("{{len=%u, type=", nlmsghdr->nlmsg_len); - printxval(netlink_types, nlmsghdr.nlmsg_type, "NLMSG_???"); + printxval(netlink_types, nlmsghdr->nlmsg_type, "NLMSG_???"); tprints(", flags="); - printflags(netlink_flags, nlmsghdr.nlmsg_flags, "NLM_F_???"); + printflags(netlink_flags, nlmsghdr->nlmsg_flags, "NLM_F_???"); /* manage get/new requests */ - tprintf(", seq=%u, pid=%u}", nlmsghdr.nlmsg_seq, - nlmsghdr.nlmsg_pid); + tprintf(", seq=%u, pid=%u}", nlmsghdr->nlmsg_seq, + nlmsghdr->nlmsg_pid); - if (size - sizeof(struct nlmsghdr) > 0) { + if (nlmsghdr->nlmsg_len - sizeof(struct nlmsghdr) > 0) { tprints(", "); printstr(tcp, addr + sizeof(struct nlmsghdr), - size - sizeof(struct nlmsghdr)); + nlmsghdr->nlmsg_len - sizeof(struct nlmsghdr)); } tprints("}"); } + +void +decode_netlink(struct tcb *tcp, unsigned long addr, unsigned long total_size) { + struct nlmsghdr nlmsghdr; + unsigned long elt, size = total_size; + int print_array = 0; + + for (elt = 0; nlmsg_fetch(tcp, &nlmsghdr, addr, size); + addr = nlmsg_next(&nlmsghdr, addr, &size), elt++) { + if (elt == max_strlen && abbrev(tcp)) { + tprints("..."); + break; + } + if (size != total_size) { + tprints(", "); + } else if (NLMSG_ALIGN(nlmsghdr.nlmsg_len) < total_size) { + print_array = 1; + tprints("["); + } + decode_netlink_msg(tcp, &nlmsghdr, addr, size); + } + if (print_array) { + tprints("]"); + } +} diff --git a/tests/netlink_parsing.c b/tests/netlink_parsing.c index 3e7c983..657b05d 100644 --- a/tests/netlink_parsing.c +++ b/tests/netlink_parsing.c @@ -43,7 +43,7 @@ static void send_query(const int fd) { - struct { + struct req { struct nlmsghdr nlh; char magic[4]; } req = { @@ -54,6 +54,14 @@ send_query(const int fd) }, .magic = "abcd" }; + struct { + struct req req1; + char padding[NLMSG_ALIGN(sizeof(req)) - sizeof(req)]; + struct req req2; + } reqs = { + .req1 = req, + .req2 = req + }; const void *const efault = tail_alloc(sizeof(struct nlmsghdr) - 1); @@ -90,6 +98,15 @@ send_query(const int fd) printf("sendto(%d, %p, %u, MSG_DONTWAIT, NULL, 0) = -1 " "EFAULT (%m)\n", fd, efault, (unsigned) sizeof(struct nlmsghdr)); + + sendto(fd, &reqs, sizeof(reqs), MSG_DONTWAIT, NULL, 0); + + printf("sendto(%d, [{{len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x" + ", seq=0, pid=0}, \"abcd\"}, {{len=%u, type=NLMSG_NOOP" + ", flags=NLM_F_REQUEST|0x%x, seq=0, pid=0}, \"abcd\"}], %u" + ", MSG_DONTWAIT, NULL, 0) = %u\n", fd, (unsigned) sizeof(req), + NLM_F_DUMP, (unsigned) sizeof(req), NLM_F_DUMP, + (unsigned) sizeof(reqs), (unsigned) sizeof(reqs)); } int main(void) -- 2.8.3 ------------------------------------------------------------------------------ Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San Francisco, CA to explore cutting-edge tech and listen to tech luminaries present their vision of the future. This family event has something for everyone, including kids. Get more information and register today. http://sdm.link/attshape _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel