Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3 : : * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions
8 : : * are met:
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. The name of the author may not be used to endorse or promote products
15 : : * derived from this software without specific prior written permission.
16 : : *
17 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 : : */
28 : :
29 : : #include "defs.h"
30 : : #include <sys/socket.h>
31 : : #include <linux/netlink.h>
32 : : #include "xlat/netlink_flags.h"
33 : : #include "xlat/netlink_types.h"
34 : :
35 : : /*
36 : : * Fetch a struct nlmsghdr from the given address.
37 : : */
38 : : static bool
39 : 250 : fetch_nlmsghdr(struct tcb *const tcp, struct nlmsghdr *const nlmsghdr,
40 : : const kernel_ulong_t addr, const kernel_ulong_t len)
41 : : {
42 [ + + ]: 250 : if (len < sizeof(struct nlmsghdr)) {
43 : 20 : printstrn(tcp, addr, len);
44 : 20 : return false;
45 : : }
46 : :
47 [ + + ]: 230 : if (umove_or_printaddr(tcp, addr, nlmsghdr))
48 : 15 : return false;
49 : :
50 : 215 : return true;
51 : : }
52 : :
53 : : static void
54 : 210 : print_nlmsghdr(struct tcb *tcp, const struct nlmsghdr *const nlmsghdr)
55 : : {
56 : : /* print the whole structure regardless of its nlmsg_len */
57 : :
58 : 210 : tprintf("{len=%u, type=", nlmsghdr->nlmsg_len);
59 : :
60 : 210 : printxval(netlink_types, nlmsghdr->nlmsg_type, "NLMSG_???");
61 : :
62 : 210 : tprints(", flags=");
63 : 210 : printflags(netlink_flags, nlmsghdr->nlmsg_flags, "NLM_F_???");
64 : :
65 : 210 : tprintf(", seq=%u, pid=%u}", nlmsghdr->nlmsg_seq,
66 : : nlmsghdr->nlmsg_pid);
67 : 210 : }
68 : :
69 : : static void
70 : 210 : decode_nlmsghdr_with_payload(struct tcb *const tcp,
71 : : const struct nlmsghdr *const nlmsghdr,
72 : : const kernel_ulong_t addr,
73 : : const kernel_ulong_t len)
74 : : {
75 : 210 : tprints("{");
76 : :
77 : 210 : print_nlmsghdr(tcp, nlmsghdr);
78 : :
79 : 210 : unsigned int nlmsg_len =
80 : 210 : nlmsghdr->nlmsg_len > len ? len : nlmsghdr->nlmsg_len;
81 [ + + ]: 210 : if (nlmsg_len > sizeof(struct nlmsghdr)) {
82 : 35 : tprints(", ");
83 : :
84 : 35 : printstrn(tcp, addr + sizeof(struct nlmsghdr),
85 : : nlmsg_len - sizeof(struct nlmsghdr));
86 : : }
87 : :
88 : 210 : tprints("}");
89 : 210 : }
90 : :
91 : : void
92 : 70 : decode_netlink(struct tcb *const tcp, kernel_ulong_t addr, kernel_ulong_t len)
93 : : {
94 : : struct nlmsghdr nlmsghdr;
95 : 70 : bool print_array = false;
96 : : unsigned int elt;
97 : :
98 [ + + ]: 250 : for (elt = 0; fetch_nlmsghdr(tcp, &nlmsghdr, addr, len); elt++) {
99 [ + - ][ + + ]: 215 : if (abbrev(tcp) && elt == max_strlen) {
100 : 5 : tprints("...");
101 : 5 : break;
102 : : }
103 : :
104 : 210 : unsigned int nlmsg_len = NLMSG_ALIGN(nlmsghdr.nlmsg_len);
105 : 210 : kernel_ulong_t next_addr = 0;
106 : 210 : kernel_ulong_t next_len = 0;
107 : :
108 [ + + ]: 210 : if (nlmsghdr.nlmsg_len >= sizeof(struct nlmsghdr)) {
109 [ + + ]: 200 : next_len = (len >= nlmsg_len) ? len - nlmsg_len : 0;
110 : :
111 [ + + ][ + - ]: 200 : if (next_len && addr + nlmsg_len > addr)
112 : 180 : next_addr = addr + nlmsg_len;
113 : : }
114 : :
115 [ + + ][ + + ]: 210 : if (!print_array && next_addr) {
116 : 25 : tprints("[");
117 : 25 : print_array = true;
118 : : }
119 : :
120 : 210 : decode_nlmsghdr_with_payload(tcp, &nlmsghdr, addr, len);
121 : :
122 [ + + ]: 210 : if (!next_addr)
123 : 30 : break;
124 : :
125 : 180 : tprints(", ");
126 : 180 : addr = next_addr;
127 : 180 : len = next_len;
128 : : }
129 : :
130 [ + + ]: 70 : if (print_array) {
131 : 25 : tprints("]");
132 : : }
133 : 70 : }
|