]> granicus.if.org Git - strace/blob - nlattr.c
netlink_sock_diag: print inet_diag_sockid.idiag_if as an interface index
[strace] / nlattr.c
1 /*
2  * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3  * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4  * Copyright (c) 2016-2017 The strace developers.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "defs.h"
31 #include "netlink.h"
32 #include "nlattr.h"
33
34 static bool
35 fetch_nlattr(struct tcb *const tcp, struct nlattr *const nlattr,
36              const kernel_ulong_t addr, const kernel_ulong_t len)
37 {
38         if (len < sizeof(struct nlattr)) {
39                 printstrn(tcp, addr, len);
40                 return false;
41         }
42
43         if (umove_or_printaddr(tcp, addr, nlattr))
44                 return false;
45
46         return true;
47 }
48
49 static void
50 print_nlattr(const struct nlattr *const nla,
51              const struct xlat *const table,
52              const char *const dflt)
53 {
54         tprintf("{nla_len=%u, nla_type=", nla->nla_len);
55         if (nla->nla_type & NLA_F_NESTED)
56                 tprints("NLA_F_NESTED|");
57         if (nla->nla_type & NLA_F_NET_BYTEORDER)
58                 tprints("NLA_F_NET_BYTEORDER|");
59         printxval(table, nla->nla_type & NLA_TYPE_MASK, dflt);
60         tprints("}");
61 }
62
63 static void
64 decode_nlattr_with_data(struct tcb *const tcp,
65                         const struct nlattr *const nla,
66                         const kernel_ulong_t addr,
67                         const kernel_ulong_t len,
68                         const struct xlat *const table,
69                         const char *const dflt,
70                         const nla_decoder_t *const decoders,
71                         const unsigned int size,
72                         const void *const opaque_data)
73 {
74         const unsigned int nla_len = nla->nla_len > len ? len : nla->nla_len;
75
76         if (nla_len > NLA_HDRLEN)
77                 tprints("{");
78
79         print_nlattr(nla, table, dflt);
80
81         if (nla_len > NLA_HDRLEN) {
82                 tprints(", ");
83                 if (!decoders
84                     || nla->nla_type >= size
85                     || !decoders[nla->nla_type]
86                     || !decoders[nla->nla_type](tcp, addr + NLA_HDRLEN,
87                                                 nla_len - NLA_HDRLEN,
88                                                 opaque_data))
89                         printstrn(tcp, addr + NLA_HDRLEN, len - NLA_HDRLEN);
90                 tprints("}");
91         }
92 }
93
94 void
95 decode_nlattr(struct tcb *const tcp,
96               kernel_ulong_t addr,
97               kernel_ulong_t len,
98               const struct xlat *const table,
99               const char *const dflt,
100               const nla_decoder_t *const decoders,
101               const unsigned int size,
102               const void *const opaque_data)
103 {
104         struct nlattr nla;
105         bool print_array = false;
106         unsigned int elt;
107
108         for (elt = 0; fetch_nlattr(tcp, &nla, addr, len); elt++) {
109                 if (abbrev(tcp) && elt == max_strlen) {
110                         tprints("...");
111                         break;
112                 }
113
114                 const unsigned long nla_len = NLA_ALIGN(nla.nla_len);
115                 kernel_ulong_t next_addr = 0;
116                 kernel_ulong_t next_len = 0;
117
118                 if (nla.nla_len >= NLA_HDRLEN) {
119                         next_len = (len >= nla_len) ? len - nla_len : 0;
120
121                         if (next_len && addr + nla_len > addr)
122                                 next_addr = addr + nla_len;
123                 }
124
125                 if (!print_array && next_addr) {
126                         tprints("[");
127                         print_array = true;
128                 }
129
130                 decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt,
131                                         decoders, size, opaque_data);
132
133                 if (!next_addr)
134                         break;
135
136                 tprints(", ");
137                 addr = next_addr;
138                 len = next_len;
139         }
140
141         if (print_array) {
142                 tprints("]");
143         }
144 }
145
146 bool
147 decode_nla_str(struct tcb *const tcp,
148                const kernel_ulong_t addr,
149                const kernel_ulong_t len,
150                const void *const opaque_data)
151 {
152         printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
153
154         return true;
155 }
156
157 bool
158 decode_nla_strn(struct tcb *const tcp,
159                 const kernel_ulong_t addr,
160                 const kernel_ulong_t len,
161                 const void *const opaque_data)
162 {
163         printstrn(tcp, addr, len);
164
165         return true;
166 }
167
168 #define DECODE_NLA_INTEGER(name, type, fmt)             \
169 bool                                                    \
170 decode_nla_ ## name(struct tcb *const tcp,              \
171                     const kernel_ulong_t addr,          \
172                     const kernel_ulong_t len,           \
173                     const void *const opaque_data)      \
174 {                                                       \
175         type num;                                       \
176                                                         \
177         if (len < sizeof(num))                          \
178                 return false;                           \
179         if (!umove_or_printaddr(tcp, addr, &num))       \
180                 tprintf(fmt, num);                      \
181         return true;                                    \
182 }
183
184 DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
185 DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
186 DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)
187 DECODE_NLA_INTEGER(u64, uint64_t, "%" PRIu64)
188 DECODE_NLA_INTEGER(s8, int8_t, "%" PRId8)
189 DECODE_NLA_INTEGER(s16, int16_t, "%" PRId16)
190 DECODE_NLA_INTEGER(s32, int32_t, "%" PRId32)
191 DECODE_NLA_INTEGER(s64, int64_t, "%" PRId64)