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 "tests.h" 30 #include <sys/socket.h> 31 32 #ifndef AF_SMC 33 # define AF_SMC 43 34 #endif 35 36 #include <stdio.h> 37 #include <string.h> 38 #include <stdint.h> 39 #include <arpa/inet.h> 40 #include "test_nlattr.h" 41 #include <linux/rtnetlink.h> 42 #include <linux/smc_diag.h> 43 #include <linux/sock_diag.h> 44 45 #ifndef SMC_CLNT 46 # define SMC_CLNT 0 47 #endif 48 #ifndef SMC_ACTIVE 49 # define SMC_ACTIVE 1 50 #endif 51 52 static const char address[] = "12.34.56.78"; 53 54 static void 55 init_smc_diag_msg(struct nlmsghdr *const nlh, const unsigned int msg_len) 56 { 57 SET_STRUCT(struct nlmsghdr, nlh, 58 .nlmsg_len = msg_len, 59 .nlmsg_type = SOCK_DIAG_BY_FAMILY, 60 .nlmsg_flags = NLM_F_DUMP 61 ); 62 63 struct smc_diag_msg *const msg = NLMSG_DATA(nlh); 64 SET_STRUCT(struct smc_diag_msg, msg, 65 .diag_family = AF_SMC, 66 .diag_state = SMC_ACTIVE 67 ); 68 69 if (!inet_pton(AF_INET, address, msg->id.idiag_src) || 70 !inet_pton(AF_INET, address, msg->id.idiag_dst)) 71 perror_msg_and_skip("inet_pton"); 72 } 73 74 static void 75 print_smc_diag_msg(const unsigned int msg_len) 76 { 77 printf("{len=%u, type=SOCK_DIAG_BY_FAMILY" 78 ", flags=NLM_F_DUMP, seq=0, pid=0}" 79 ", {diag_family=AF_SMC, diag_state=SMC_ACTIVE" 80 ", diag_fallback=SMC_DIAG_MODE_SMCR, diag_shutdown=0" 81 ", id={idiag_sport=htons(0), idiag_dport=htons(0)" 82 ", idiag_src=inet_addr(\"%s\")" 83 ", idiag_dst=inet_addr(\"%s\")" 84 ", idiag_if=0, idiag_cookie=[0, 0]}" 85 ", diag_uid=0, diag_inode=0}", 86 msg_len, address, address); 87 } 88 89 #define PRINT_FIELD_SMC_DIAG_CURSOR(prefix_, where_, field_) \ 90 do { \ 91 printf("%s%s=", (prefix_), #field_); \ 92 PRINT_FIELD_U("{", (where_).field_, reserved); \ 93 PRINT_FIELD_U(", ", (where_).field_, wrap); \ 94 PRINT_FIELD_U(", ", (where_).field_, count); \ 95 printf("}"); \ 96 } while (0) 97 98 int main(void) 99 { 100 skip_if_unavailable("/proc/self/fd/"); 101 102 static const struct smc_diag_conninfo cinfo = { 103 .token = 0xabcdefac, 104 .sndbuf_size = 0xbcdaefad, 105 .rmbe_size = 0xcdbaefab, 106 .peer_rmbe_size = 0xdbcdedaf, 107 .rx_prod = { 108 .reserved = 0xabc1, 109 .wrap = 0xbca1, 110 .count = 0xcdedbad1 111 }, 112 .rx_cons = { 113 .reserved = 0xabc2, 114 .wrap = 0xbca2, 115 .count = 0xcdedbad2 116 }, 117 .tx_prod = { 118 .reserved = 0xabc3, 119 .wrap = 0xbca3, 120 .count = 0xcdedbad3 121 }, 122 .tx_cons = { 123 .reserved = 0xabc4, 124 .wrap = 0xbca4, 125 .count = 0xcdedbad4 126 }, 127 .rx_prod_flags = 0xff, 128 .rx_conn_state_flags = 0xff, 129 .tx_prod_flags = 0xff, 130 .tx_conn_state_flags = 0xff, 131 .tx_prep = { 132 .reserved = 0xabc5, 133 .wrap = 0xbca5, 134 .count = 0xcdedbad5 135 }, 136 .tx_sent = { 137 .reserved = 0xabc6, 138 .wrap = 0xbca6, 139 .count = 0xcdedbad6 140 }, 141 .tx_fin = { 142 .reserved = 0xabc7, 143 .wrap = 0xbca7, 144 .count = 0xcdedbad7 145 } 146 }; 147 static const struct smc_diag_lgrinfo linfo = { 148 .lnk[0] = { 149 .link_id = 0xaf, 150 .ibport = 0xfa, 151 .ibname = "123", 152 .gid = "456", 153 .peer_gid = "789" 154 }, 155 .role = SMC_CLNT 156 }; 157 static const struct smcd_diag_dmbinfo dinfo = { 158 .linkid = 0xdeadc0de, 159 .peer_gid = 0xbefeededbadc0dedULL, 160 .my_gid = 0xdeec0dedfacebeefULL, 161 .token = 0xcafedecaffeedeedULL, 162 .peer_token = 0xfeedfacebeeff00dULL, 163 }; 164 static const struct smc_diag_fallback fb1 = { 165 .reason = 0, 166 .peer_diagnosis = 0x03020000, 167 }; 168 static const struct smc_diag_fallback fb2 = { 169 .reason = 0x03060000, 170 .peer_diagnosis = 0x99999999, 171 }; 172 static uint8_t sd1 = 0x23; 173 static uint8_t sd2 = 0x40; 174 175 int fd = create_nl_socket(NETLINK_SOCK_DIAG); 176 const unsigned int hdrlen = sizeof(struct smc_diag_msg); 177 void *const nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), 178 NLA_HDRLEN + 179 MAX(sizeof(cinfo), sizeof(linfo))); 180 181 static char pattern[4096]; 182 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1); 183 184 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 185 init_smc_diag_msg, print_smc_diag_msg, 186 SMC_DIAG_SHUTDOWN, pattern, sd1, 187 printf("RCV_SHUTDOWN|SEND_SHUTDOWN|0x20")); 188 189 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 190 init_smc_diag_msg, print_smc_diag_msg, 191 SMC_DIAG_SHUTDOWN, pattern, sd2, 192 printf("0x40 /* ???_SHUTDOWN */")); 193 194 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 195 init_smc_diag_msg, print_smc_diag_msg, 196 SMC_DIAG_CONNINFO, pattern, cinfo, 197 PRINT_FIELD_U("{", cinfo, token); 198 PRINT_FIELD_U(", ", cinfo, sndbuf_size); 199 PRINT_FIELD_U(", ", cinfo, rmbe_size); 200 PRINT_FIELD_U(", ", cinfo, peer_rmbe_size); 201 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, rx_prod); 202 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, rx_cons); 203 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_prod); 204 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_cons); 205 printf(", rx_prod_flags=0xff"); 206 printf(", rx_conn_state_flags=0xff"); 207 printf(", tx_prod_flags=0xff"); 208 printf(", tx_conn_state_flags=0xff"); 209 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_prep); 210 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_sent); 211 PRINT_FIELD_SMC_DIAG_CURSOR(", ", cinfo, tx_fin); 212 printf("}")); 213 214 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 215 init_smc_diag_msg, print_smc_diag_msg, 216 SMC_DIAG_LGRINFO, pattern, linfo, 217 PRINT_FIELD_U("{lnk[0]={", linfo.lnk[0], link_id); 218 printf(", ibname=\"%s\"", linfo.lnk[0].ibname); 219 PRINT_FIELD_U(", ", linfo.lnk[0], ibport); 220 printf(", gid=\"%s\"", linfo.lnk[0].gid); 221 printf(", peer_gid=\"%s\"}", linfo.lnk[0].peer_gid); 222 printf(", role=SMC_CLNT}")); 223 224 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 225 init_smc_diag_msg, print_smc_diag_msg, 226 SMC_DIAG_DMBINFO, pattern, dinfo, 227 PRINT_FIELD_U("{", dinfo, linkid); 228 PRINT_FIELD_X(", ", dinfo, peer_gid); 229 PRINT_FIELD_X(", ", dinfo, my_gid); 230 PRINT_FIELD_X(", ", dinfo, token); 231 PRINT_FIELD_X(", ", dinfo, peer_token); 232 printf("}")); 233 234 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 235 init_smc_diag_msg, print_smc_diag_msg, 236 SMC_DIAG_FALLBACK, pattern, fb1, 237 printf("{reason=0 /* SMC_CLC_DECL_??? */"); 238 printf(", peer_diagnosis=0x3020000" 239 " /* SMC_CLC_DECL_IPSEC */}")); 240 241 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 242 init_smc_diag_msg, print_smc_diag_msg, 243 SMC_DIAG_FALLBACK, pattern, fb2, 244 printf("{reason=0x3060000" 245 " /* SMC_CLC_DECL_OPTUNSUPP */"); 246 printf(", peer_diagnosis=0x99999999" 247 " /* SMC_CLC_DECL_??? */}")); 248 249 printf("+++ exited with 0 +++\n"); 250 return 0; 251 } 252