1 /*
2 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@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
31 #ifdef HAVE_STRUCT_BR_PORT_MSG
32
33 # include <stdio.h>
34 # include "test_nlattr.h"
35 # include <arpa/inet.h>
36 # include <linux/if_bridge.h>
37 # include <linux/rtnetlink.h>
38
39 # ifndef MDB_TEMPORARY
40 # define MDB_TEMPORARY 0
41 # endif
42 # ifndef MDBA_MDB_ENTRY_INFO
43 # define MDBA_MDB_ENTRY_INFO 1
44 # endif
45 # ifndef MDBA_MDB_EATTR_TIMER
46 # define MDBA_MDB_EATTR_TIMER 1
47 # endif
48
49 const unsigned int hdrlen = sizeof(struct br_port_msg);
50
51 static void
init_br_port_msg(struct nlmsghdr * const nlh,const unsigned int msg_len)52 init_br_port_msg(struct nlmsghdr *const nlh, const unsigned int msg_len)
53 {
54 unsigned int len = msg_len;
55
56 SET_STRUCT(struct nlmsghdr, nlh,
57 .nlmsg_len = len,
58 .nlmsg_type = RTM_GETMDB,
59 .nlmsg_flags = NLM_F_DUMP
60 );
61
62 struct br_port_msg *const msg = NLMSG_DATA(nlh);
63 SET_STRUCT(struct br_port_msg, msg,
64 .family = AF_UNIX,
65 .ifindex = ifindex_lo()
66 );
67
68 struct nlattr *nla = NLMSG_ATTR(nlh, sizeof(*msg));
69 len -= NLMSG_SPACE(hdrlen);
70 SET_STRUCT(struct nlattr, nla,
71 .nla_len = len,
72 .nla_type = MDBA_MDB
73 );
74
75 nla = nla + 1;
76 len -= NLA_HDRLEN;
77 SET_STRUCT(struct nlattr, nla,
78 .nla_len = len,
79 .nla_type = MDBA_MDB_ENTRY
80 );
81 }
82
83 static void
print_br_port_msg(const unsigned int msg_len)84 print_br_port_msg(const unsigned int msg_len)
85 {
86 printf("{len=%u, type=RTM_GETMDB, flags=NLM_F_DUMP"
87 ", seq=0, pid=0}, {family=AF_UNIX"
88 ", ifindex=" IFINDEX_LO_STR "}"
89 ", {{nla_len=%u, nla_type=MDBA_MDB}"
90 ", {{nla_len=%u, nla_type=MDBA_MDB_ENTRY}",
91 msg_len, msg_len - NLMSG_SPACE(hdrlen),
92 msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN);
93 }
94
95 int
main(void)96 main(void)
97 {
98 skip_if_unavailable("/proc/self/fd/");
99
100 const int fd = create_nl_socket(NETLINK_ROUTE);
101
102 void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), NLA_HDRLEN + 4
103 # ifdef HAVE_STRUCT_BR_MDB_ENTRY
104 - 4 + NLA_HDRLEN * 2 + sizeof(struct nlattr)
105 + sizeof(struct br_mdb_entry)
106 # endif
107 );
108
109 static char pattern[4096];
110 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
111
112 const unsigned int nla_type = 0xffff & NLA_TYPE_MASK;
113 char nla_type_str[256];
114 sprintf(nla_type_str, "%#x /* MDBA_MDB_ENTRY_??? */", nla_type);
115 TEST_NLATTR_(fd, nlh0 - NLA_HDRLEN * 2, hdrlen + NLA_HDRLEN * 2,
116 init_br_port_msg, print_br_port_msg,
117 nla_type, nla_type_str,
118 4, pattern, 4,
119 print_quoted_hex(pattern, 4);
120 printf("}}"));
121
122 # ifdef HAVE_STRUCT_BR_MDB_ENTRY
123 struct br_mdb_entry entry = {
124 .ifindex = ifindex_lo(),
125 .state = MDB_TEMPORARY,
126 # ifdef HAVE_STRUCT_BR_MDB_ENTRY_FLAGS
127 .flags = MDB_FLAGS_OFFLOAD,
128 # endif
129 # ifdef HAVE_STRUCT_BR_MDB_ENTRY_VID
130 .vid = 0xcdef,
131 # endif
132 .addr = {
133 .proto = htons(AF_UNSPEC)
134 }
135 };
136
137 memcpy(&entry.addr.u, pattern, sizeof(entry.addr.u));
138 TEST_NESTED_NLATTR_OBJECT_EX(fd, nlh0, hdrlen,
139 init_br_port_msg, print_br_port_msg,
140 MDBA_MDB_ENTRY_INFO, pattern, entry, 2,
141 printf("{ifindex=" IFINDEX_LO_STR);
142 printf(", state=MDB_TEMPORARY");
143 # ifdef HAVE_STRUCT_BR_MDB_ENTRY_FLAGS
144 printf(", flags=MDB_FLAGS_OFFLOAD");
145 # endif
146 # ifdef HAVE_STRUCT_BR_MDB_ENTRY_VID
147 PRINT_FIELD_U(", ", entry, vid);
148 # endif
149 printf(", addr={u=");
150 print_quoted_hex(&entry.addr.u,
151 sizeof(entry.addr.u));
152 printf(", proto=htons(AF_UNSPEC)}}"));
153
154 static const struct nlattr nla = {
155 .nla_len = sizeof(nla),
156 .nla_type = MDBA_MDB_EATTR_TIMER
157 };
158 char buf[NLMSG_ALIGN(sizeof(entry)) + sizeof(nla)];
159 memcpy(buf, &entry, sizeof(entry));
160 memcpy(buf + NLMSG_ALIGN(sizeof(entry)), &nla, sizeof(nla));
161 TEST_NLATTR(fd, nlh0 - NLA_HDRLEN * 2, hdrlen + NLA_HDRLEN * 2,
162 init_br_port_msg, print_br_port_msg,
163 MDBA_MDB_ENTRY_INFO, sizeof(buf), buf, sizeof(buf),
164 printf("{ifindex=" IFINDEX_LO_STR);
165 printf(", state=MDB_TEMPORARY");
166 # ifdef HAVE_STRUCT_BR_MDB_ENTRY_FLAGS
167 printf(", flags=MDB_FLAGS_OFFLOAD");
168 # endif
169 # ifdef HAVE_STRUCT_BR_MDB_ENTRY_VID
170 PRINT_FIELD_U(", ", entry, vid);
171 # endif
172 printf(", addr={u=");
173 print_quoted_hex(&entry.addr.u, sizeof(entry.addr.u));
174 printf(", proto=htons(AF_UNSPEC)}}"
175 ", {nla_len=%u, nla_type=MDBA_MDB_EATTR_TIMER}}}",
176 nla.nla_len));
177 # endif /* HAVE_STRUCT_BR_MDB_ENTRY */
178
179 puts("+++ exited with 0 +++");
180 return 0;
181 }
182
183 #else
184
185 SKIP_MAIN_UNDEFINED("HAVE_STRUCT_BR_PORT_MSG")
186
187 #endif
188