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