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