]> granicus.if.org Git - strace/blob - nlattr.c
netlink: add a basic netlink attribute parser of AF_PACKET diag
[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
33 static bool
34 fetch_nlattr(struct tcb *const tcp, struct nlattr *const nlattr,
35              const kernel_ulong_t addr, const kernel_ulong_t len)
36 {
37         if (len < sizeof(struct nlattr)) {
38                 printstrn(tcp, addr, len);
39                 return false;
40         }
41
42         if (umove_or_printaddr(tcp, addr, nlattr))
43                 return false;
44
45         return true;
46 }
47
48 static void
49 print_nlattr(const struct nlattr *const nla,
50              const struct xlat *const table,
51              const char *const dflt)
52 {
53         tprintf("{nla_len=%u, nla_type=", nla->nla_len);
54         if (nla->nla_type & NLA_F_NESTED)
55                 tprints("NLA_F_NESTED|");
56         if (nla->nla_type & NLA_F_NET_BYTEORDER)
57                 tprints("NLA_F_NET_BYTEORDER|");
58         printxval(table, nla->nla_type & NLA_TYPE_MASK, dflt);
59         tprints("}");
60 }
61
62 static void
63 decode_nlattr_with_data(struct tcb *tcp,
64                         const struct nlattr *const nla,
65                         kernel_ulong_t addr,
66                         kernel_ulong_t len,
67                         const struct xlat *const table,
68                         const char *const dflt)
69 {
70         const unsigned int nla_len = nla->nla_len > len ? len : nla->nla_len;
71
72         if (nla_len > NLA_HDRLEN)
73                 tprints("{");
74
75         print_nlattr(nla, table, dflt);
76
77         if (nla_len > NLA_HDRLEN) {
78                 tprints(", ");
79                 printstrn(tcp, addr + NLA_HDRLEN, nla_len - NLA_HDRLEN);
80                 tprints("}");
81         }
82 }
83
84 void
85 decode_nlattr(struct tcb *const tcp,
86               kernel_ulong_t addr,
87               kernel_ulong_t len,
88               const struct xlat *const table,
89               const char *const dflt)
90 {
91         struct nlattr nla;
92         bool print_array = false;
93         unsigned int elt;
94
95         for (elt = 0; fetch_nlattr(tcp, &nla, addr, len); elt++) {
96                 if (abbrev(tcp) && elt == max_strlen) {
97                         tprints("...");
98                         break;
99                 }
100
101                 const unsigned long nla_len = NLA_ALIGN(nla.nla_len);
102                 kernel_ulong_t next_addr = 0;
103                 kernel_ulong_t next_len = 0;
104
105                 if (nla.nla_len >= NLA_HDRLEN) {
106                         next_len = (len >= nla_len) ? len - nla_len : 0;
107
108                         if (next_len && addr + nla_len > addr)
109                                 next_addr = addr + nla_len;
110                 }
111
112                 if (!print_array && next_addr) {
113                         tprints("[");
114                         print_array = true;
115                 }
116
117                 decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt);
118
119                 if (!next_addr)
120                         break;
121
122                 tprints(", ");
123                 addr = next_addr;
124                 len = next_len;
125         }
126
127         if (print_array) {
128                 tprints("]");
129         }
130 }