]> granicus.if.org Git - strace/blob - netlink_smc_diag.c
Decode AF_SMC netlink messages unconditionally
[strace] / netlink_smc_diag.c
1 /*
2  * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
3  * Copyright (c) 2017 The strace developers.
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
32 #ifndef AF_SMC
33 # define XLAT_MACROS_ONLY
34 # include "xlat/addrfams.h"
35 # undef XLAT_MACROS_ONLY
36 #endif
37
38 #include "netlink.h"
39 #include "netlink_sock_diag.h"
40 #include "nlattr.h"
41 #include "print_fields.h"
42
43 #include <arpa/inet.h>
44 #include <linux/smc_diag.h>
45
46 #include "xlat/smc_diag_attrs.h"
47 #include "xlat/smc_diag_extended_flags.h"
48 #include "xlat/smc_link_group_roles.h"
49 #include "xlat/smc_states.h"
50
51 DECL_NETLINK_DIAG_DECODER(decode_smc_diag_req)
52 {
53         struct smc_diag_req req = { .diag_family = family };
54         const size_t offset = sizeof(req.diag_family);
55
56         PRINT_FIELD_XVAL("{", req, diag_family, addrfams, "AF_???");
57         tprints(", ");
58         if (len >= sizeof(req)) {
59                 if (!umoven_or_printaddr(tcp, addr + offset,
60                                          sizeof(req) - offset,
61                                          (void *) &req + offset)) {
62                         PRINT_FIELD_FLAGS("", req, diag_ext,
63                                           smc_diag_extended_flags,
64                                           "1<<SMC_DIAG_\?\?\?-1");
65                         /*
66                          * AF_SMC protocol family socket handler
67                          * keeping the AF_INET sock address.
68                          */
69                         PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id, AF_INET);
70                 }
71         } else
72                 tprints("...");
73         tprints("}");
74 }
75
76 static void
77 print_smc_diag_cursor(const struct smc_diag_cursor *const cursor)
78 {
79         PRINT_FIELD_U("{", *cursor, reserved);
80         PRINT_FIELD_U(", ", *cursor, wrap);
81         PRINT_FIELD_U(", ", *cursor, count);
82         tprints("}");
83 }
84
85 # define PRINT_FIELD_SMC_DIAG_CURSOR(prefix_, where_, field_)           \
86         do {                                                            \
87                 tprintf("%s%s=", (prefix_), #field_);                   \
88                 print_smc_diag_cursor(&(where_).field_);                \
89         } while (0)
90
91 static bool
92 decode_smc_diag_conninfo(struct tcb *const tcp,
93                          const kernel_ulong_t addr,
94                          const unsigned int len,
95                          const void *const opaque_data)
96 {
97         struct smc_diag_conninfo cinfo;
98
99         if (len < sizeof(cinfo))
100                 return false;
101         if (umove_or_printaddr(tcp, addr, &cinfo))
102                 return true;
103
104         PRINT_FIELD_U("{", cinfo, token);
105         PRINT_FIELD_U(", ", cinfo, sndbuf_size);
106         PRINT_FIELD_U(", ", cinfo, rmbe_size);
107         PRINT_FIELD_U(", ", cinfo, peer_rmbe_size);
108         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, rx_prod);
109         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, rx_cons);
110         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_prod);
111         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_cons);
112         PRINT_FIELD_0X(", ", cinfo, rx_prod_flags);
113         PRINT_FIELD_0X(", ", cinfo, rx_conn_state_flags);
114         PRINT_FIELD_0X(", ", cinfo, tx_prod_flags);
115         PRINT_FIELD_0X(", ", cinfo, tx_conn_state_flags);
116         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_prep);
117         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_sent);
118         PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_fin);
119         tprints("}");
120
121         return true;
122 }
123
124 static bool
125 decode_smc_diag_lgrinfo(struct tcb *const tcp,
126                         const kernel_ulong_t addr,
127                         const unsigned int len,
128                         const void *const opaque_data)
129 {
130         struct smc_diag_lgrinfo linfo;
131
132         if (len < sizeof(linfo))
133                 return false;
134         if (umove_or_printaddr(tcp, addr, &linfo))
135                 return true;
136
137         tprints("{lnk[0]={");
138         PRINT_FIELD_U("", linfo.lnk[0], link_id);
139         PRINT_FIELD_CSTRING(", ", linfo.lnk[0], ibname);
140         PRINT_FIELD_U(", ", linfo.lnk[0], ibport);
141         PRINT_FIELD_CSTRING(", ", linfo.lnk[0], gid);
142         PRINT_FIELD_CSTRING(", ", linfo.lnk[0], peer_gid);
143         PRINT_FIELD_XVAL("}, ", linfo, role, smc_link_group_roles, "SMC_???");
144         tprints("}");
145
146         return true;
147 }
148
149 static const nla_decoder_t smc_diag_msg_nla_decoders[] = {
150         [SMC_DIAG_CONNINFO]     = decode_smc_diag_conninfo,
151         [SMC_DIAG_LGRINFO]      = decode_smc_diag_lgrinfo,
152         [SMC_DIAG_SHUTDOWN]     = decode_nla_u8
153 };
154
155 DECL_NETLINK_DIAG_DECODER(decode_smc_diag_msg)
156 {
157         struct smc_diag_msg msg = { .diag_family = family };
158         size_t offset = sizeof(msg.diag_family);
159         bool decode_nla = false;
160
161         PRINT_FIELD_XVAL("{", msg, diag_family, addrfams, "AF_???");
162         tprints(", ");
163         if (len >= sizeof(msg)) {
164                 if (!umoven_or_printaddr(tcp, addr + offset,
165                                          sizeof(msg) - offset,
166                                          (void *) &msg + offset)) {
167                         PRINT_FIELD_XVAL("", msg, diag_state,
168                                          smc_states, "SMC_???");
169                         PRINT_FIELD_U(", ", msg, diag_fallback);
170                         PRINT_FIELD_U(", ", msg, diag_shutdown);
171                         /*
172                          * AF_SMC protocol family socket handler
173                          * keeping the AF_INET sock address.
174                          */
175                         PRINT_FIELD_INET_DIAG_SOCKID(", ", msg, id, AF_INET);
176                         PRINT_FIELD_U(", ", msg, diag_uid);
177                         PRINT_FIELD_U(", ", msg, diag_inode);
178                         decode_nla = true;
179                 }
180         } else
181                 tprints("...");
182         tprints("}");
183
184         offset = NLMSG_ALIGN(sizeof(msg));
185         if (decode_nla && len > offset) {
186                 tprints(", ");
187                 decode_nlattr(tcp, addr + offset, len - offset,
188                               smc_diag_attrs, "SMC_DIAG_???",
189                               smc_diag_msg_nla_decoders,
190                               ARRAY_SIZE(smc_diag_msg_nla_decoders), NULL);
191         }
192 }