1 /* 2 * Copyright (c) 2017 JingPiao Chen <chenjingpiao (at) gmail.com> 3 * Copyright (c) 2017-2018 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_decl_codes.h" 47 #include "xlat/smc_diag_attrs.h" 48 #include "xlat/smc_diag_extended_flags.h" 49 #include "xlat/smc_diag_mode.h" 50 #include "xlat/smc_link_group_roles.h" 51 #include "xlat/smc_states.h" 52 #include "xlat/sock_shutdown_flags.h" 53 54 DECL_NETLINK_DIAG_DECODER(decode_smc_diag_req) 55 { 56 struct smc_diag_req req = { .diag_family = family }; 57 const size_t offset = sizeof(req.diag_family); 58 59 PRINT_FIELD_XVAL("{", req, diag_family, addrfams, "AF_???"); 60 tprints(", "); 61 if (len >= sizeof(req)) { 62 if (!umoven_or_printaddr(tcp, addr + offset, 63 sizeof(req) - offset, 64 (void *) &req + offset)) { 65 PRINT_FIELD_FLAGS("", req, diag_ext, 66 smc_diag_extended_flags, 67 "1<<SMC_DIAG_\?\?\?-1"); 68 /* 69 * AF_SMC protocol family socket handler 70 * keeping the AF_INET sock address. 71 */ 72 PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id, AF_INET); 73 } 74 } else 75 tprints("..."); 76 tprints("}"); 77 } 78 79 static void 80 print_smc_diag_cursor(const struct smc_diag_cursor *const cursor) 81 { 82 PRINT_FIELD_U("{", *cursor, reserved); 83 PRINT_FIELD_U(", ", *cursor, wrap); 84 PRINT_FIELD_U(", ", *cursor, count); 85 tprints("}"); 86 } 87 88 # define PRINT_FIELD_SMC_DIAG_CURSOR(prefix_, where_, field_) \ 89 do { \ 90 tprintf("%s%s=", (prefix_), #field_); \ 91 print_smc_diag_cursor(&(where_).field_); \ 92 } while (0) 93 94 static bool 95 decode_smc_diag_conninfo(struct tcb *const tcp, 96 const kernel_ulong_t addr, 97 const unsigned int len, 98 const void *const opaque_data) 99 { 100 struct smc_diag_conninfo cinfo; 101 102 if (len < sizeof(cinfo)) 103 return false; 104 if (umove_or_printaddr(tcp, addr, &cinfo)) 105 return true; 106 107 PRINT_FIELD_U("{", cinfo, token); 108 PRINT_FIELD_U(", ", cinfo, sndbuf_size); 109 PRINT_FIELD_U(", ", cinfo, rmbe_size); 110 PRINT_FIELD_U(", ", cinfo, peer_rmbe_size); 111 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, rx_prod); 112 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, rx_cons); 113 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_prod); 114 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_cons); 115 PRINT_FIELD_0X(", ", cinfo, rx_prod_flags); 116 PRINT_FIELD_0X(", ", cinfo, rx_conn_state_flags); 117 PRINT_FIELD_0X(", ", cinfo, tx_prod_flags); 118 PRINT_FIELD_0X(", ", cinfo, tx_conn_state_flags); 119 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_prep); 120 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_sent); 121 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_fin); 122 tprints("}"); 123 124 return true; 125 } 126 127 static bool 128 decode_smc_diag_lgrinfo(struct tcb *const tcp, 129 const kernel_ulong_t addr, 130 const unsigned int len, 131 const void *const opaque_data) 132 { 133 struct smc_diag_lgrinfo linfo; 134 135 if (len < sizeof(linfo)) 136 return false; 137 if (umove_or_printaddr(tcp, addr, &linfo)) 138 return true; 139 140 tprints("{lnk[0]={"); 141 PRINT_FIELD_U("", linfo.lnk[0], link_id); 142 PRINT_FIELD_CSTRING(", ", linfo.lnk[0], ibname); 143 PRINT_FIELD_U(", ", linfo.lnk[0], ibport); 144 PRINT_FIELD_CSTRING(", ", linfo.lnk[0], gid); 145 PRINT_FIELD_CSTRING(", ", linfo.lnk[0], peer_gid); 146 PRINT_FIELD_XVAL("}, ", linfo, role, smc_link_group_roles, "SMC_???"); 147 tprints("}"); 148 149 return true; 150 } 151 152 static bool 153 decode_smc_diag_shutdown(struct tcb *const tcp, 154 const kernel_ulong_t addr, 155 const unsigned int len, 156 const void *const opaque_data) 157 { 158 const struct decode_nla_xlat_opts opts = { 159 ARRSZ_PAIR(sock_shutdown_flags), "???_SHUTDOWN", 160 .size = 1, 161 }; 162 163 return decode_nla_flags(tcp, addr, len, &opts); 164 } 165 166 static bool 167 decode_smc_diag_dmbinfo(struct tcb *const tcp, 168 const kernel_ulong_t addr, 169 const unsigned int len, 170 const void *const opaque_data) 171 { 172 struct smcd_diag_dmbinfo dinfo; 173 174 if (len < sizeof(dinfo)) 175 return false; 176 if (umove_or_printaddr(tcp, addr, &dinfo)) 177 return true; 178 179 PRINT_FIELD_U("{", dinfo, linkid); 180 PRINT_FIELD_X(", ", dinfo, peer_gid); 181 PRINT_FIELD_X(", ", dinfo, my_gid); 182 PRINT_FIELD_X(", ", dinfo, token); 183 PRINT_FIELD_X(", ", dinfo, peer_token); 184 tprints("}"); 185 186 return true; 187 } 188 static bool 189 decode_smc_diag_fallback(struct tcb *const tcp, 190 const kernel_ulong_t addr, 191 const unsigned int len, 192 const void *const opaque_data) 193 { 194 struct smc_diag_fallback fb; 195 196 if (len < sizeof(fb)) 197 return false; 198 if (umove_or_printaddr(tcp, addr, &fb)) 199 return true; 200 201 /* 202 * We print them verbose since they are defined in a non-UAPI header, 203 * net/smc/smc_clc.h 204 */ 205 tprints("{reason="); 206 printxval_search_ex(smc_decl_codes, fb.reason, 207 "SMC_CLC_DECL_???", XLAT_STYLE_VERBOSE); 208 tprints(", peer_diagnosis="); 209 printxval_search_ex(smc_decl_codes, fb.peer_diagnosis, 210 "SMC_CLC_DECL_???", XLAT_STYLE_VERBOSE); 211 tprints("}"); 212 213 return true; 214 } 215 216 static const nla_decoder_t smc_diag_msg_nla_decoders[] = { 217 [SMC_DIAG_CONNINFO] = decode_smc_diag_conninfo, 218 [SMC_DIAG_LGRINFO] = decode_smc_diag_lgrinfo, 219 [SMC_DIAG_SHUTDOWN] = decode_smc_diag_shutdown, 220 [SMC_DIAG_DMBINFO] = decode_smc_diag_dmbinfo, 221 [SMC_DIAG_FALLBACK] = decode_smc_diag_fallback, 222 }; 223 224 DECL_NETLINK_DIAG_DECODER(decode_smc_diag_msg) 225 { 226 struct smc_diag_msg msg = { .diag_family = family }; 227 size_t offset = sizeof(msg.diag_family); 228 bool decode_nla = false; 229 230 PRINT_FIELD_XVAL("{", msg, diag_family, addrfams, "AF_???"); 231 tprints(", "); 232 if (len >= sizeof(msg)) { 233 if (!umoven_or_printaddr(tcp, addr + offset, 234 sizeof(msg) - offset, 235 (void *) &msg + offset)) { 236 PRINT_FIELD_XVAL("", msg, diag_state, 237 smc_states, "SMC_???"); 238 PRINT_FIELD_XVAL_INDEX(", ", msg, diag_fallback, 239 smc_diag_mode, 240 "SMC_DIAG_MODE_???"); 241 PRINT_FIELD_U(", ", msg, diag_shutdown); 242 /* 243 * AF_SMC protocol family socket handler 244 * keeping the AF_INET sock address. 245 */ 246 PRINT_FIELD_INET_DIAG_SOCKID(", ", msg, id, AF_INET); 247 PRINT_FIELD_U(", ", msg, diag_uid); 248 PRINT_FIELD_U(", ", msg, diag_inode); 249 decode_nla = true; 250 } 251 } else 252 tprints("..."); 253 tprints("}"); 254 255 offset = NLMSG_ALIGN(sizeof(msg)); 256 if (decode_nla && len > offset) { 257 tprints(", "); 258 decode_nlattr(tcp, addr + offset, len - offset, 259 smc_diag_attrs, "SMC_DIAG_???", 260 smc_diag_msg_nla_decoders, 261 ARRAY_SIZE(smc_diag_msg_nla_decoders), NULL); 262 } 263 } 264