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
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdint.h>
14 #include <net/if.h>
15 #include "test_nlattr.h"
16 #include <sys/socket.h>
17 #include <linux/filter.h>
18 #include <linux/packet_diag.h>
19 #include <linux/rtnetlink.h>
20 #include <linux/sock_diag.h>
21
22 static void
23 init_packet_diag_msg(struct nlmsghdr *const nlh, const unsigned int msg_len)
24 {
25 SET_STRUCT(struct nlmsghdr, nlh,
26 .nlmsg_len = msg_len,
27 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
28 .nlmsg_flags = NLM_F_DUMP
29 );
30
31 struct packet_diag_msg *const msg = NLMSG_DATA(nlh);
32 SET_STRUCT(struct packet_diag_msg, msg,
33 .pdiag_family = AF_PACKET,
34 .pdiag_type = SOCK_STREAM,
35 .pdiag_num = 3,
36 );
37 }
38
39 static void
40 print_packet_diag_msg(const unsigned int msg_len)
41 {
42 printf("{nlmsg_len=%u, nlmsg_type=SOCK_DIAG_BY_FAMILY"
43 ", nlmsg_flags=NLM_F_DUMP, nlmsg_seq=0, nlmsg_pid=0}"
44 ", {pdiag_family=AF_PACKET"
45 ", pdiag_type=SOCK_STREAM, pdiag_num=ETH_P_ALL"
46 ", pdiag_ino=0, pdiag_cookie=[0, 0]}",
47 msg_len);
48 }
49
50 static void
51 print_packet_diag_mclist(const struct packet_diag_mclist *const dml, size_t i)
52 {
53 printf("{pdmc_index=" IFINDEX_LO_STR);
54 printf(", ");
55 PRINT_FIELD_U(*dml, pdmc_count);
56 printf(", ");
57 PRINT_FIELD_U(*dml, pdmc_type);
58 printf(", ");
59 PRINT_FIELD_U(*dml, pdmc_alen);
60 printf(", pdmc_addr=");
61 print_quoted_hex(dml->pdmc_addr, dml->pdmc_alen);
62 printf("}");
63 }
64
65 static const struct sock_filter filter[] = {
66 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, SKF_AD_OFF+SKF_AD_PKTTYPE),
67 BPF_STMT(BPF_RET|BPF_K, 0x2a)
68 };
69
70 static void
71 print_sock_filter(const struct sock_filter *const f, size_t i)
72 {
73 if (f == filter)
74 printf("BPF_STMT(BPF_LD|BPF_B|BPF_ABS"
75 ", SKF_AD_OFF+SKF_AD_PKTTYPE)");
76 else
77 printf("BPF_STMT(BPF_RET|BPF_K, 0x2a)");
78 }
79
80 int
81 main(void)
82 {
83 skip_if_unavailable("/proc/self/fd/");
84
85 struct packet_diag_info pinfo = {
86 .pdi_index = ifindex_lo(),
87 .pdi_version = 2,
88 .pdi_reserve = 0xcfaacdaf,
89 .pdi_copy_thresh = 0xdabacdaf,
90 .pdi_tstamp = 0xeafbaadf,
91 .pdi_flags = PDI_RUNNING
92 };
93 const struct packet_diag_mclist dml[] = {
94 {
95 .pdmc_index = ifindex_lo(),
96 .pdmc_count = 0xabcdaefc,
97 .pdmc_type = 0xcdaf,
98 .pdmc_alen = 4,
99 .pdmc_addr = "1234"
100 },
101 {
102 .pdmc_index = ifindex_lo(),
103 .pdmc_count = 0xdaefeafc,
104 .pdmc_type = 0xadef,
105 .pdmc_alen = 4,
106 .pdmc_addr = "5678"
107 }
108 };
109 static const struct packet_diag_ring pdr = {
110 .pdr_block_size = 0xabcdafed,
111 .pdr_block_nr = 0xbcadefae,
112 .pdr_frame_size = 0xcabdfeac,
113 .pdr_frame_nr = 0xdeaeadef,
114 .pdr_retire_tmo = 0xedbafeac,
115 .pdr_sizeof_priv = 0xfeadeacd,
116 .pdr_features = 0xadebadea
117 };
118
119 int fd = create_nl_socket(NETLINK_SOCK_DIAG);
120 const unsigned int hdrlen = sizeof(struct packet_diag_msg);
121 void *const nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen),
122 NLA_HDRLEN + sizeof(dml));
123
124 static char pattern[4096];
125 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
126
127 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
128 init_packet_diag_msg, print_packet_diag_msg,
129 PACKET_DIAG_INFO, pattern, pinfo,
130 printf("{pdi_index=%s", IFINDEX_LO_STR);
131 printf(", pdi_version=TPACKET_V3");
132 printf(", ");
133 PRINT_FIELD_U(pinfo, pdi_reserve);
134 printf(", ");
135 PRINT_FIELD_U(pinfo, pdi_copy_thresh);
136 printf(", ");
137 PRINT_FIELD_U(pinfo, pdi_tstamp);
138 printf(", pdi_flags=PDI_RUNNING}"));
139
140 TEST_NLATTR_ARRAY(fd, nlh0, hdrlen,
141 init_packet_diag_msg, print_packet_diag_msg,
142 PACKET_DIAG_MCLIST, pattern, dml,
143 print_packet_diag_mclist);
144
145 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen,
146 init_packet_diag_msg, print_packet_diag_msg,
147 PACKET_DIAG_RX_RING, pattern, pdr,
148 printf("{");
149 PRINT_FIELD_U(pdr, pdr_block_size);
150 printf(", ");
151 PRINT_FIELD_U(pdr, pdr_block_nr);
152 printf(", ");
153 PRINT_FIELD_U(pdr, pdr_frame_size);
154 printf(", ");
155 PRINT_FIELD_U(pdr, pdr_frame_nr);
156 printf(", ");
157 PRINT_FIELD_U(pdr, pdr_retire_tmo);
158 printf(", ");
159 PRINT_FIELD_U(pdr, pdr_sizeof_priv);
160 printf(", ");
161 PRINT_FIELD_U(pdr, pdr_features);
162 printf("}"));
163
164 TEST_NLATTR_ARRAY(fd, nlh0, hdrlen,
165 init_packet_diag_msg, print_packet_diag_msg,
166 PACKET_DIAG_FILTER, pattern, filter,
167 print_sock_filter);
168
169 printf("+++ exited with 0 +++\n");
170 return 0;
171 }