blob: 14c19a90b2b01feb690e4891ebe7e18489ba16c2 [file] [log] [blame]
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, see <http://www.gnu.org/licenses/>.
14 */
15
16#include "qemu/osdep.h"
17
18#include <sys/signalfd.h>
19#include <linux/unistd.h>
20#include <linux/audit.h>
21#ifdef CONFIG_INOTIFY
22#include <sys/inotify.h>
23#endif
24#include <linux/netlink.h>
25#ifdef CONFIG_RTNETLINK
26#include <linux/rtnetlink.h>
27#include <linux/if_bridge.h>
28#endif
29#include "qemu.h"
Peter Maydell3b249d22021-09-08 16:44:03 +010030#include "user-internals.h"
Laurent Vivierf7e6a402018-08-24 00:22:15 +020031#include "fd-trans.h"
Peter Maydell2113aed2021-09-08 16:43:59 +010032#include "signal-common.h"
Laurent Vivierf7e6a402018-08-24 00:22:15 +020033
34enum {
35 QEMU_IFLA_BR_UNSPEC,
36 QEMU_IFLA_BR_FORWARD_DELAY,
37 QEMU_IFLA_BR_HELLO_TIME,
38 QEMU_IFLA_BR_MAX_AGE,
39 QEMU_IFLA_BR_AGEING_TIME,
40 QEMU_IFLA_BR_STP_STATE,
41 QEMU_IFLA_BR_PRIORITY,
42 QEMU_IFLA_BR_VLAN_FILTERING,
43 QEMU_IFLA_BR_VLAN_PROTOCOL,
44 QEMU_IFLA_BR_GROUP_FWD_MASK,
45 QEMU_IFLA_BR_ROOT_ID,
46 QEMU_IFLA_BR_BRIDGE_ID,
47 QEMU_IFLA_BR_ROOT_PORT,
48 QEMU_IFLA_BR_ROOT_PATH_COST,
49 QEMU_IFLA_BR_TOPOLOGY_CHANGE,
50 QEMU_IFLA_BR_TOPOLOGY_CHANGE_DETECTED,
51 QEMU_IFLA_BR_HELLO_TIMER,
52 QEMU_IFLA_BR_TCN_TIMER,
53 QEMU_IFLA_BR_TOPOLOGY_CHANGE_TIMER,
54 QEMU_IFLA_BR_GC_TIMER,
55 QEMU_IFLA_BR_GROUP_ADDR,
56 QEMU_IFLA_BR_FDB_FLUSH,
57 QEMU_IFLA_BR_MCAST_ROUTER,
58 QEMU_IFLA_BR_MCAST_SNOOPING,
59 QEMU_IFLA_BR_MCAST_QUERY_USE_IFADDR,
60 QEMU_IFLA_BR_MCAST_QUERIER,
61 QEMU_IFLA_BR_MCAST_HASH_ELASTICITY,
62 QEMU_IFLA_BR_MCAST_HASH_MAX,
63 QEMU_IFLA_BR_MCAST_LAST_MEMBER_CNT,
64 QEMU_IFLA_BR_MCAST_STARTUP_QUERY_CNT,
65 QEMU_IFLA_BR_MCAST_LAST_MEMBER_INTVL,
66 QEMU_IFLA_BR_MCAST_MEMBERSHIP_INTVL,
67 QEMU_IFLA_BR_MCAST_QUERIER_INTVL,
68 QEMU_IFLA_BR_MCAST_QUERY_INTVL,
69 QEMU_IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
70 QEMU_IFLA_BR_MCAST_STARTUP_QUERY_INTVL,
71 QEMU_IFLA_BR_NF_CALL_IPTABLES,
72 QEMU_IFLA_BR_NF_CALL_IP6TABLES,
73 QEMU_IFLA_BR_NF_CALL_ARPTABLES,
74 QEMU_IFLA_BR_VLAN_DEFAULT_PVID,
75 QEMU_IFLA_BR_PAD,
76 QEMU_IFLA_BR_VLAN_STATS_ENABLED,
77 QEMU_IFLA_BR_MCAST_STATS_ENABLED,
78 QEMU_IFLA_BR_MCAST_IGMP_VERSION,
79 QEMU_IFLA_BR_MCAST_MLD_VERSION,
Laurent Vivier61b463f2019-03-06 21:09:25 +010080 QEMU_IFLA_BR_VLAN_STATS_PER_PORT,
81 QEMU_IFLA_BR_MULTI_BOOLOPT,
Laurent Vivierf7e6a402018-08-24 00:22:15 +020082 QEMU___IFLA_BR_MAX,
83};
84
85enum {
86 QEMU_IFLA_UNSPEC,
87 QEMU_IFLA_ADDRESS,
88 QEMU_IFLA_BROADCAST,
89 QEMU_IFLA_IFNAME,
90 QEMU_IFLA_MTU,
91 QEMU_IFLA_LINK,
92 QEMU_IFLA_QDISC,
93 QEMU_IFLA_STATS,
94 QEMU_IFLA_COST,
95 QEMU_IFLA_PRIORITY,
96 QEMU_IFLA_MASTER,
97 QEMU_IFLA_WIRELESS,
98 QEMU_IFLA_PROTINFO,
99 QEMU_IFLA_TXQLEN,
100 QEMU_IFLA_MAP,
101 QEMU_IFLA_WEIGHT,
102 QEMU_IFLA_OPERSTATE,
103 QEMU_IFLA_LINKMODE,
104 QEMU_IFLA_LINKINFO,
105 QEMU_IFLA_NET_NS_PID,
106 QEMU_IFLA_IFALIAS,
107 QEMU_IFLA_NUM_VF,
108 QEMU_IFLA_VFINFO_LIST,
109 QEMU_IFLA_STATS64,
110 QEMU_IFLA_VF_PORTS,
111 QEMU_IFLA_PORT_SELF,
112 QEMU_IFLA_AF_SPEC,
113 QEMU_IFLA_GROUP,
114 QEMU_IFLA_NET_NS_FD,
115 QEMU_IFLA_EXT_MASK,
116 QEMU_IFLA_PROMISCUITY,
117 QEMU_IFLA_NUM_TX_QUEUES,
118 QEMU_IFLA_NUM_RX_QUEUES,
119 QEMU_IFLA_CARRIER,
120 QEMU_IFLA_PHYS_PORT_ID,
121 QEMU_IFLA_CARRIER_CHANGES,
122 QEMU_IFLA_PHYS_SWITCH_ID,
123 QEMU_IFLA_LINK_NETNSID,
124 QEMU_IFLA_PHYS_PORT_NAME,
125 QEMU_IFLA_PROTO_DOWN,
126 QEMU_IFLA_GSO_MAX_SEGS,
127 QEMU_IFLA_GSO_MAX_SIZE,
128 QEMU_IFLA_PAD,
129 QEMU_IFLA_XDP,
130 QEMU_IFLA_EVENT,
131 QEMU_IFLA_NEW_NETNSID,
132 QEMU_IFLA_IF_NETNSID,
133 QEMU_IFLA_CARRIER_UP_COUNT,
134 QEMU_IFLA_CARRIER_DOWN_COUNT,
135 QEMU_IFLA_NEW_IFINDEX,
Laurent Vivier0f5faca2019-02-06 20:32:11 +0100136 QEMU_IFLA_MIN_MTU,
137 QEMU_IFLA_MAX_MTU,
Laurent Vivierd9679ee2020-07-09 09:23:31 +0200138 QEMU_IFLA_PROP_LIST,
139 QEMU_IFLA_ALT_IFNAME,
140 QEMU_IFLA_PERM_ADDRESS,
Laurent Vivier312aef92021-12-19 16:45:12 +0100141 QEMU_IFLA_PROTO_DOWN_REASON,
142 QEMU_IFLA_PARENT_DEV_NAME,
143 QEMU_IFLA_PARENT_DEV_BUS_NAME,
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200144 QEMU___IFLA_MAX
145};
146
147enum {
148 QEMU_IFLA_BRPORT_UNSPEC,
149 QEMU_IFLA_BRPORT_STATE,
150 QEMU_IFLA_BRPORT_PRIORITY,
151 QEMU_IFLA_BRPORT_COST,
152 QEMU_IFLA_BRPORT_MODE,
153 QEMU_IFLA_BRPORT_GUARD,
154 QEMU_IFLA_BRPORT_PROTECT,
155 QEMU_IFLA_BRPORT_FAST_LEAVE,
156 QEMU_IFLA_BRPORT_LEARNING,
157 QEMU_IFLA_BRPORT_UNICAST_FLOOD,
158 QEMU_IFLA_BRPORT_PROXYARP,
159 QEMU_IFLA_BRPORT_LEARNING_SYNC,
160 QEMU_IFLA_BRPORT_PROXYARP_WIFI,
161 QEMU_IFLA_BRPORT_ROOT_ID,
162 QEMU_IFLA_BRPORT_BRIDGE_ID,
163 QEMU_IFLA_BRPORT_DESIGNATED_PORT,
164 QEMU_IFLA_BRPORT_DESIGNATED_COST,
165 QEMU_IFLA_BRPORT_ID,
166 QEMU_IFLA_BRPORT_NO,
167 QEMU_IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
168 QEMU_IFLA_BRPORT_CONFIG_PENDING,
169 QEMU_IFLA_BRPORT_MESSAGE_AGE_TIMER,
170 QEMU_IFLA_BRPORT_FORWARD_DELAY_TIMER,
171 QEMU_IFLA_BRPORT_HOLD_TIMER,
172 QEMU_IFLA_BRPORT_FLUSH,
173 QEMU_IFLA_BRPORT_MULTICAST_ROUTER,
174 QEMU_IFLA_BRPORT_PAD,
175 QEMU_IFLA_BRPORT_MCAST_FLOOD,
176 QEMU_IFLA_BRPORT_MCAST_TO_UCAST,
177 QEMU_IFLA_BRPORT_VLAN_TUNNEL,
178 QEMU_IFLA_BRPORT_BCAST_FLOOD,
179 QEMU_IFLA_BRPORT_GROUP_FWD_MASK,
180 QEMU_IFLA_BRPORT_NEIGH_SUPPRESS,
Laurent Vivier0f5faca2019-02-06 20:32:11 +0100181 QEMU_IFLA_BRPORT_ISOLATED,
182 QEMU_IFLA_BRPORT_BACKUP_PORT,
Laurent Vivier5351f402020-11-17 12:19:05 +0100183 QEMU_IFLA_BRPORT_MRP_RING_OPEN,
184 QEMU_IFLA_BRPORT_MRP_IN_OPEN,
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200185 QEMU___IFLA_BRPORT_MAX
186};
187
188enum {
189 QEMU_IFLA_TUN_UNSPEC,
190 QEMU_IFLA_TUN_OWNER,
191 QEMU_IFLA_TUN_GROUP,
192 QEMU_IFLA_TUN_TYPE,
193 QEMU_IFLA_TUN_PI,
194 QEMU_IFLA_TUN_VNET_HDR,
195 QEMU_IFLA_TUN_PERSIST,
196 QEMU_IFLA_TUN_MULTI_QUEUE,
197 QEMU_IFLA_TUN_NUM_QUEUES,
198 QEMU_IFLA_TUN_NUM_DISABLED_QUEUES,
199 QEMU___IFLA_TUN_MAX,
200};
201
202enum {
203 QEMU_IFLA_INFO_UNSPEC,
204 QEMU_IFLA_INFO_KIND,
205 QEMU_IFLA_INFO_DATA,
206 QEMU_IFLA_INFO_XSTATS,
207 QEMU_IFLA_INFO_SLAVE_KIND,
208 QEMU_IFLA_INFO_SLAVE_DATA,
209 QEMU___IFLA_INFO_MAX,
210};
211
212enum {
213 QEMU_IFLA_INET_UNSPEC,
214 QEMU_IFLA_INET_CONF,
215 QEMU___IFLA_INET_MAX,
216};
217
218enum {
219 QEMU_IFLA_INET6_UNSPEC,
220 QEMU_IFLA_INET6_FLAGS,
221 QEMU_IFLA_INET6_CONF,
222 QEMU_IFLA_INET6_STATS,
223 QEMU_IFLA_INET6_MCAST,
224 QEMU_IFLA_INET6_CACHEINFO,
225 QEMU_IFLA_INET6_ICMP6STATS,
226 QEMU_IFLA_INET6_TOKEN,
227 QEMU_IFLA_INET6_ADDR_GEN_MODE,
228 QEMU___IFLA_INET6_MAX
229};
230
231enum {
232 QEMU_IFLA_XDP_UNSPEC,
233 QEMU_IFLA_XDP_FD,
234 QEMU_IFLA_XDP_ATTACHED,
235 QEMU_IFLA_XDP_FLAGS,
236 QEMU_IFLA_XDP_PROG_ID,
237 QEMU___IFLA_XDP_MAX,
238};
239
240enum {
241 QEMU_RTA_UNSPEC,
242 QEMU_RTA_DST,
243 QEMU_RTA_SRC,
244 QEMU_RTA_IIF,
245 QEMU_RTA_OIF,
246 QEMU_RTA_GATEWAY,
247 QEMU_RTA_PRIORITY,
248 QEMU_RTA_PREFSRC,
249 QEMU_RTA_METRICS,
250 QEMU_RTA_MULTIPATH,
251 QEMU_RTA_PROTOINFO, /* no longer used */
252 QEMU_RTA_FLOW,
253 QEMU_RTA_CACHEINFO,
254 QEMU_RTA_SESSION, /* no longer used */
255 QEMU_RTA_MP_ALGO, /* no longer used */
256 QEMU_RTA_TABLE,
257 QEMU_RTA_MARK,
258 QEMU_RTA_MFC_STATS,
259 QEMU_RTA_VIA,
260 QEMU_RTA_NEWDST,
261 QEMU_RTA_PREF,
262 QEMU_RTA_ENCAP_TYPE,
263 QEMU_RTA_ENCAP,
264 QEMU_RTA_EXPIRES,
265 QEMU_RTA_PAD,
266 QEMU_RTA_UID,
267 QEMU_RTA_TTL_PROPAGATE,
268 QEMU_RTA_IP_PROTO,
269 QEMU_RTA_SPORT,
270 QEMU_RTA_DPORT,
271 QEMU___RTA_MAX
272};
273
274TargetFdTrans **target_fd_trans;
Owen Andersonc0933642021-07-01 22:12:55 +0000275QemuMutex target_fd_trans_lock;
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200276unsigned int target_fd_max;
277
278static void tswap_nlmsghdr(struct nlmsghdr *nlh)
279{
280 nlh->nlmsg_len = tswap32(nlh->nlmsg_len);
281 nlh->nlmsg_type = tswap16(nlh->nlmsg_type);
282 nlh->nlmsg_flags = tswap16(nlh->nlmsg_flags);
283 nlh->nlmsg_seq = tswap32(nlh->nlmsg_seq);
284 nlh->nlmsg_pid = tswap32(nlh->nlmsg_pid);
285}
286
287static abi_long host_to_target_for_each_nlmsg(struct nlmsghdr *nlh,
288 size_t len,
289 abi_long (*host_to_target_nlmsg)
290 (struct nlmsghdr *))
291{
292 uint32_t nlmsg_len;
Shu-Chun Weng1645fb52019-10-17 17:19:20 -0700293 uint32_t aligned_nlmsg_len;
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200294 abi_long ret;
295
296 while (len > sizeof(struct nlmsghdr)) {
297
298 nlmsg_len = nlh->nlmsg_len;
299 if (nlmsg_len < sizeof(struct nlmsghdr) ||
300 nlmsg_len > len) {
301 break;
302 }
303
304 switch (nlh->nlmsg_type) {
305 case NLMSG_DONE:
306 tswap_nlmsghdr(nlh);
307 return 0;
308 case NLMSG_NOOP:
309 break;
310 case NLMSG_ERROR:
311 {
312 struct nlmsgerr *e = NLMSG_DATA(nlh);
313 e->error = tswap32(e->error);
314 tswap_nlmsghdr(&e->msg);
315 tswap_nlmsghdr(nlh);
316 return 0;
317 }
318 default:
319 ret = host_to_target_nlmsg(nlh);
320 if (ret < 0) {
321 tswap_nlmsghdr(nlh);
322 return ret;
323 }
324 break;
325 }
326 tswap_nlmsghdr(nlh);
Shu-Chun Weng1645fb52019-10-17 17:19:20 -0700327
328 aligned_nlmsg_len = NLMSG_ALIGN(nlmsg_len);
329 if (aligned_nlmsg_len >= len) {
330 break;
331 }
332 len -= aligned_nlmsg_len;
333 nlh = (struct nlmsghdr *)(((char*)nlh) + aligned_nlmsg_len);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200334 }
335 return 0;
336}
337
338static abi_long target_to_host_for_each_nlmsg(struct nlmsghdr *nlh,
339 size_t len,
340 abi_long (*target_to_host_nlmsg)
341 (struct nlmsghdr *))
342{
Shu-Chun Weng1645fb52019-10-17 17:19:20 -0700343 uint32_t aligned_nlmsg_len;
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200344 int ret;
345
346 while (len > sizeof(struct nlmsghdr)) {
347 if (tswap32(nlh->nlmsg_len) < sizeof(struct nlmsghdr) ||
348 tswap32(nlh->nlmsg_len) > len) {
349 break;
350 }
351 tswap_nlmsghdr(nlh);
352 switch (nlh->nlmsg_type) {
353 case NLMSG_DONE:
354 return 0;
355 case NLMSG_NOOP:
356 break;
357 case NLMSG_ERROR:
358 {
359 struct nlmsgerr *e = NLMSG_DATA(nlh);
360 e->error = tswap32(e->error);
361 tswap_nlmsghdr(&e->msg);
362 return 0;
363 }
364 default:
365 ret = target_to_host_nlmsg(nlh);
366 if (ret < 0) {
367 return ret;
368 }
369 }
Shu-Chun Weng1645fb52019-10-17 17:19:20 -0700370
371 aligned_nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len);
372 if (aligned_nlmsg_len >= len) {
373 break;
374 }
375 len -= aligned_nlmsg_len;
376 nlh = (struct nlmsghdr *)(((char *)nlh) + aligned_nlmsg_len);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200377 }
378 return 0;
379}
380
381#ifdef CONFIG_RTNETLINK
382static abi_long host_to_target_for_each_nlattr(struct nlattr *nlattr,
383 size_t len, void *context,
384 abi_long (*host_to_target_nlattr)
385 (struct nlattr *,
386 void *context))
387{
388 unsigned short nla_len;
Shu-Chun Weng1645fb52019-10-17 17:19:20 -0700389 unsigned short aligned_nla_len;
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200390 abi_long ret;
391
392 while (len > sizeof(struct nlattr)) {
393 nla_len = nlattr->nla_len;
394 if (nla_len < sizeof(struct nlattr) ||
395 nla_len > len) {
396 break;
397 }
398 ret = host_to_target_nlattr(nlattr, context);
399 nlattr->nla_len = tswap16(nlattr->nla_len);
400 nlattr->nla_type = tswap16(nlattr->nla_type);
401 if (ret < 0) {
402 return ret;
403 }
Shu-Chun Weng1645fb52019-10-17 17:19:20 -0700404
405 aligned_nla_len = NLA_ALIGN(nla_len);
406 if (aligned_nla_len >= len) {
407 break;
408 }
409 len -= aligned_nla_len;
410 nlattr = (struct nlattr *)(((char *)nlattr) + aligned_nla_len);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200411 }
412 return 0;
413}
414
415static abi_long host_to_target_for_each_rtattr(struct rtattr *rtattr,
416 size_t len,
417 abi_long (*host_to_target_rtattr)
418 (struct rtattr *))
419{
420 unsigned short rta_len;
Shu-Chun Weng1645fb52019-10-17 17:19:20 -0700421 unsigned short aligned_rta_len;
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200422 abi_long ret;
423
424 while (len > sizeof(struct rtattr)) {
425 rta_len = rtattr->rta_len;
426 if (rta_len < sizeof(struct rtattr) ||
427 rta_len > len) {
428 break;
429 }
430 ret = host_to_target_rtattr(rtattr);
431 rtattr->rta_len = tswap16(rtattr->rta_len);
432 rtattr->rta_type = tswap16(rtattr->rta_type);
433 if (ret < 0) {
434 return ret;
435 }
Shu-Chun Weng1645fb52019-10-17 17:19:20 -0700436
437 aligned_rta_len = RTA_ALIGN(rta_len);
438 if (aligned_rta_len >= len) {
439 break;
440 }
441 len -= aligned_rta_len;
442 rtattr = (struct rtattr *)(((char *)rtattr) + aligned_rta_len);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200443 }
444 return 0;
445}
446
447#define NLA_DATA(nla) ((void *)((char *)(nla)) + NLA_HDRLEN)
448
449static abi_long host_to_target_data_bridge_nlattr(struct nlattr *nlattr,
450 void *context)
451{
452 uint16_t *u16;
453 uint32_t *u32;
454 uint64_t *u64;
455
456 switch (nlattr->nla_type) {
457 /* no data */
458 case QEMU_IFLA_BR_FDB_FLUSH:
459 break;
460 /* binary */
461 case QEMU_IFLA_BR_GROUP_ADDR:
462 break;
463 /* uint8_t */
464 case QEMU_IFLA_BR_VLAN_FILTERING:
465 case QEMU_IFLA_BR_TOPOLOGY_CHANGE:
466 case QEMU_IFLA_BR_TOPOLOGY_CHANGE_DETECTED:
467 case QEMU_IFLA_BR_MCAST_ROUTER:
468 case QEMU_IFLA_BR_MCAST_SNOOPING:
469 case QEMU_IFLA_BR_MCAST_QUERY_USE_IFADDR:
470 case QEMU_IFLA_BR_MCAST_QUERIER:
471 case QEMU_IFLA_BR_NF_CALL_IPTABLES:
472 case QEMU_IFLA_BR_NF_CALL_IP6TABLES:
473 case QEMU_IFLA_BR_NF_CALL_ARPTABLES:
474 case QEMU_IFLA_BR_VLAN_STATS_ENABLED:
475 case QEMU_IFLA_BR_MCAST_STATS_ENABLED:
476 case QEMU_IFLA_BR_MCAST_IGMP_VERSION:
477 case QEMU_IFLA_BR_MCAST_MLD_VERSION:
Laurent Vivier61b463f2019-03-06 21:09:25 +0100478 case QEMU_IFLA_BR_VLAN_STATS_PER_PORT:
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200479 break;
480 /* uint16_t */
481 case QEMU_IFLA_BR_PRIORITY:
482 case QEMU_IFLA_BR_VLAN_PROTOCOL:
483 case QEMU_IFLA_BR_GROUP_FWD_MASK:
484 case QEMU_IFLA_BR_ROOT_PORT:
485 case QEMU_IFLA_BR_VLAN_DEFAULT_PVID:
486 u16 = NLA_DATA(nlattr);
487 *u16 = tswap16(*u16);
488 break;
489 /* uint32_t */
490 case QEMU_IFLA_BR_FORWARD_DELAY:
491 case QEMU_IFLA_BR_HELLO_TIME:
492 case QEMU_IFLA_BR_MAX_AGE:
493 case QEMU_IFLA_BR_AGEING_TIME:
494 case QEMU_IFLA_BR_STP_STATE:
495 case QEMU_IFLA_BR_ROOT_PATH_COST:
496 case QEMU_IFLA_BR_MCAST_HASH_ELASTICITY:
497 case QEMU_IFLA_BR_MCAST_HASH_MAX:
498 case QEMU_IFLA_BR_MCAST_LAST_MEMBER_CNT:
499 case QEMU_IFLA_BR_MCAST_STARTUP_QUERY_CNT:
500 u32 = NLA_DATA(nlattr);
501 *u32 = tswap32(*u32);
502 break;
503 /* uint64_t */
504 case QEMU_IFLA_BR_HELLO_TIMER:
505 case QEMU_IFLA_BR_TCN_TIMER:
506 case QEMU_IFLA_BR_GC_TIMER:
507 case QEMU_IFLA_BR_TOPOLOGY_CHANGE_TIMER:
508 case QEMU_IFLA_BR_MCAST_LAST_MEMBER_INTVL:
509 case QEMU_IFLA_BR_MCAST_MEMBERSHIP_INTVL:
510 case QEMU_IFLA_BR_MCAST_QUERIER_INTVL:
511 case QEMU_IFLA_BR_MCAST_QUERY_INTVL:
512 case QEMU_IFLA_BR_MCAST_QUERY_RESPONSE_INTVL:
513 case QEMU_IFLA_BR_MCAST_STARTUP_QUERY_INTVL:
514 u64 = NLA_DATA(nlattr);
515 *u64 = tswap64(*u64);
516 break;
517 /* ifla_bridge_id: uin8_t[] */
518 case QEMU_IFLA_BR_ROOT_ID:
519 case QEMU_IFLA_BR_BRIDGE_ID:
520 break;
Laurent Vivier01154f72019-06-26 17:08:55 +0200521 /* br_boolopt_multi { uint32_t, uint32_t } */
522 case QEMU_IFLA_BR_MULTI_BOOLOPT:
523 u32 = NLA_DATA(nlattr);
524 u32[0] = tswap32(u32[0]); /* optval */
525 u32[1] = tswap32(u32[1]); /* optmask */
526 break;
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200527 default:
Josh Kunz39be5352020-02-03 18:54:13 -0800528 qemu_log_mask(LOG_UNIMP, "Unknown QEMU_IFLA_BR type %d\n",
529 nlattr->nla_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200530 break;
531 }
532 return 0;
533}
534
535static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr,
536 void *context)
537{
538 uint16_t *u16;
539 uint32_t *u32;
540 uint64_t *u64;
541
542 switch (nlattr->nla_type) {
543 /* uint8_t */
544 case QEMU_IFLA_BRPORT_STATE:
545 case QEMU_IFLA_BRPORT_MODE:
546 case QEMU_IFLA_BRPORT_GUARD:
547 case QEMU_IFLA_BRPORT_PROTECT:
548 case QEMU_IFLA_BRPORT_FAST_LEAVE:
549 case QEMU_IFLA_BRPORT_LEARNING:
550 case QEMU_IFLA_BRPORT_UNICAST_FLOOD:
551 case QEMU_IFLA_BRPORT_PROXYARP:
552 case QEMU_IFLA_BRPORT_LEARNING_SYNC:
553 case QEMU_IFLA_BRPORT_PROXYARP_WIFI:
554 case QEMU_IFLA_BRPORT_TOPOLOGY_CHANGE_ACK:
555 case QEMU_IFLA_BRPORT_CONFIG_PENDING:
556 case QEMU_IFLA_BRPORT_MULTICAST_ROUTER:
557 case QEMU_IFLA_BRPORT_MCAST_FLOOD:
558 case QEMU_IFLA_BRPORT_MCAST_TO_UCAST:
559 case QEMU_IFLA_BRPORT_VLAN_TUNNEL:
560 case QEMU_IFLA_BRPORT_BCAST_FLOOD:
561 case QEMU_IFLA_BRPORT_NEIGH_SUPPRESS:
Laurent Vivier0f5faca2019-02-06 20:32:11 +0100562 case QEMU_IFLA_BRPORT_ISOLATED:
Laurent Vivier5351f402020-11-17 12:19:05 +0100563 case QEMU_IFLA_BRPORT_MRP_RING_OPEN:
564 case QEMU_IFLA_BRPORT_MRP_IN_OPEN:
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200565 break;
566 /* uint16_t */
567 case QEMU_IFLA_BRPORT_PRIORITY:
568 case QEMU_IFLA_BRPORT_DESIGNATED_PORT:
569 case QEMU_IFLA_BRPORT_DESIGNATED_COST:
570 case QEMU_IFLA_BRPORT_ID:
571 case QEMU_IFLA_BRPORT_NO:
572 case QEMU_IFLA_BRPORT_GROUP_FWD_MASK:
573 u16 = NLA_DATA(nlattr);
574 *u16 = tswap16(*u16);
575 break;
576 /* uin32_t */
577 case QEMU_IFLA_BRPORT_COST:
Laurent Vivier0f5faca2019-02-06 20:32:11 +0100578 case QEMU_IFLA_BRPORT_BACKUP_PORT:
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200579 u32 = NLA_DATA(nlattr);
580 *u32 = tswap32(*u32);
581 break;
582 /* uint64_t */
583 case QEMU_IFLA_BRPORT_MESSAGE_AGE_TIMER:
584 case QEMU_IFLA_BRPORT_FORWARD_DELAY_TIMER:
585 case QEMU_IFLA_BRPORT_HOLD_TIMER:
586 u64 = NLA_DATA(nlattr);
587 *u64 = tswap64(*u64);
588 break;
589 /* ifla_bridge_id: uint8_t[] */
590 case QEMU_IFLA_BRPORT_ROOT_ID:
591 case QEMU_IFLA_BRPORT_BRIDGE_ID:
592 break;
593 default:
Josh Kunz39be5352020-02-03 18:54:13 -0800594 qemu_log_mask(LOG_UNIMP, "Unknown QEMU_IFLA_BRPORT type %d\n",
595 nlattr->nla_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200596 break;
597 }
598 return 0;
599}
600
601static abi_long host_to_target_data_tun_nlattr(struct nlattr *nlattr,
602 void *context)
603{
604 uint32_t *u32;
605
606 switch (nlattr->nla_type) {
607 /* uint8_t */
608 case QEMU_IFLA_TUN_TYPE:
609 case QEMU_IFLA_TUN_PI:
610 case QEMU_IFLA_TUN_VNET_HDR:
611 case QEMU_IFLA_TUN_PERSIST:
612 case QEMU_IFLA_TUN_MULTI_QUEUE:
613 break;
614 /* uint32_t */
615 case QEMU_IFLA_TUN_NUM_QUEUES:
616 case QEMU_IFLA_TUN_NUM_DISABLED_QUEUES:
617 case QEMU_IFLA_TUN_OWNER:
618 case QEMU_IFLA_TUN_GROUP:
619 u32 = NLA_DATA(nlattr);
620 *u32 = tswap32(*u32);
621 break;
622 default:
Josh Kunz39be5352020-02-03 18:54:13 -0800623 qemu_log_mask(LOG_UNIMP, "Unknown QEMU_IFLA_TUN type %d\n",
624 nlattr->nla_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200625 break;
626 }
627 return 0;
628}
629
630struct linkinfo_context {
631 int len;
632 char *name;
633 int slave_len;
634 char *slave_name;
635};
636
637static abi_long host_to_target_data_linkinfo_nlattr(struct nlattr *nlattr,
638 void *context)
639{
640 struct linkinfo_context *li_context = context;
641
642 switch (nlattr->nla_type) {
643 /* string */
644 case QEMU_IFLA_INFO_KIND:
645 li_context->name = NLA_DATA(nlattr);
646 li_context->len = nlattr->nla_len - NLA_HDRLEN;
647 break;
648 case QEMU_IFLA_INFO_SLAVE_KIND:
649 li_context->slave_name = NLA_DATA(nlattr);
650 li_context->slave_len = nlattr->nla_len - NLA_HDRLEN;
651 break;
652 /* stats */
653 case QEMU_IFLA_INFO_XSTATS:
654 /* FIXME: only used by CAN */
655 break;
656 /* nested */
657 case QEMU_IFLA_INFO_DATA:
658 if (strncmp(li_context->name, "bridge",
659 li_context->len) == 0) {
660 return host_to_target_for_each_nlattr(NLA_DATA(nlattr),
661 nlattr->nla_len,
662 NULL,
663 host_to_target_data_bridge_nlattr);
664 } else if (strncmp(li_context->name, "tun",
665 li_context->len) == 0) {
666 return host_to_target_for_each_nlattr(NLA_DATA(nlattr),
667 nlattr->nla_len,
668 NULL,
669 host_to_target_data_tun_nlattr);
670 } else {
Josh Kunz39be5352020-02-03 18:54:13 -0800671 qemu_log_mask(LOG_UNIMP, "Unknown QEMU_IFLA_INFO_KIND %s\n",
672 li_context->name);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200673 }
674 break;
675 case QEMU_IFLA_INFO_SLAVE_DATA:
676 if (strncmp(li_context->slave_name, "bridge",
677 li_context->slave_len) == 0) {
678 return host_to_target_for_each_nlattr(NLA_DATA(nlattr),
679 nlattr->nla_len,
680 NULL,
681 host_to_target_slave_data_bridge_nlattr);
682 } else {
Josh Kunz39be5352020-02-03 18:54:13 -0800683 qemu_log_mask(LOG_UNIMP, "Unknown QEMU_IFLA_INFO_SLAVE_KIND %s\n",
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200684 li_context->slave_name);
685 }
686 break;
687 default:
Josh Kunz39be5352020-02-03 18:54:13 -0800688 qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA_INFO type: %d\n",
689 nlattr->nla_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200690 break;
691 }
692
693 return 0;
694}
695
696static abi_long host_to_target_data_inet_nlattr(struct nlattr *nlattr,
697 void *context)
698{
699 uint32_t *u32;
700 int i;
701
702 switch (nlattr->nla_type) {
703 case QEMU_IFLA_INET_CONF:
704 u32 = NLA_DATA(nlattr);
705 for (i = 0; i < (nlattr->nla_len - NLA_HDRLEN) / sizeof(*u32);
706 i++) {
707 u32[i] = tswap32(u32[i]);
708 }
709 break;
710 default:
Josh Kunz39be5352020-02-03 18:54:13 -0800711 qemu_log_mask(LOG_UNIMP, "Unknown host AF_INET type: %d\n",
712 nlattr->nla_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200713 }
714 return 0;
715}
716
717static abi_long host_to_target_data_inet6_nlattr(struct nlattr *nlattr,
718 void *context)
719{
720 uint32_t *u32;
721 uint64_t *u64;
722 struct ifla_cacheinfo *ci;
723 int i;
724
725 switch (nlattr->nla_type) {
726 /* binaries */
727 case QEMU_IFLA_INET6_TOKEN:
728 break;
729 /* uint8_t */
730 case QEMU_IFLA_INET6_ADDR_GEN_MODE:
731 break;
732 /* uint32_t */
733 case QEMU_IFLA_INET6_FLAGS:
734 u32 = NLA_DATA(nlattr);
735 *u32 = tswap32(*u32);
736 break;
737 /* uint32_t[] */
738 case QEMU_IFLA_INET6_CONF:
739 u32 = NLA_DATA(nlattr);
740 for (i = 0; i < (nlattr->nla_len - NLA_HDRLEN) / sizeof(*u32);
741 i++) {
742 u32[i] = tswap32(u32[i]);
743 }
744 break;
745 /* ifla_cacheinfo */
746 case QEMU_IFLA_INET6_CACHEINFO:
747 ci = NLA_DATA(nlattr);
748 ci->max_reasm_len = tswap32(ci->max_reasm_len);
749 ci->tstamp = tswap32(ci->tstamp);
750 ci->reachable_time = tswap32(ci->reachable_time);
751 ci->retrans_time = tswap32(ci->retrans_time);
752 break;
753 /* uint64_t[] */
754 case QEMU_IFLA_INET6_STATS:
755 case QEMU_IFLA_INET6_ICMP6STATS:
756 u64 = NLA_DATA(nlattr);
757 for (i = 0; i < (nlattr->nla_len - NLA_HDRLEN) / sizeof(*u64);
758 i++) {
759 u64[i] = tswap64(u64[i]);
760 }
761 break;
762 default:
Josh Kunz39be5352020-02-03 18:54:13 -0800763 qemu_log_mask(LOG_UNIMP, "Unknown host AF_INET6 type: %d\n",
764 nlattr->nla_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200765 }
766 return 0;
767}
768
769static abi_long host_to_target_data_spec_nlattr(struct nlattr *nlattr,
770 void *context)
771{
772 switch (nlattr->nla_type) {
773 case AF_INET:
774 return host_to_target_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len,
775 NULL,
776 host_to_target_data_inet_nlattr);
777 case AF_INET6:
778 return host_to_target_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len,
779 NULL,
780 host_to_target_data_inet6_nlattr);
781 default:
Josh Kunz39be5352020-02-03 18:54:13 -0800782 qemu_log_mask(LOG_UNIMP, "Unknown host AF_SPEC type: %d\n",
783 nlattr->nla_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200784 break;
785 }
786 return 0;
787}
788
789static abi_long host_to_target_data_xdp_nlattr(struct nlattr *nlattr,
790 void *context)
791{
792 uint32_t *u32;
793
794 switch (nlattr->nla_type) {
795 /* uint8_t */
796 case QEMU_IFLA_XDP_ATTACHED:
797 break;
798 /* uint32_t */
799 case QEMU_IFLA_XDP_PROG_ID:
800 u32 = NLA_DATA(nlattr);
801 *u32 = tswap32(*u32);
802 break;
803 default:
Josh Kunz39be5352020-02-03 18:54:13 -0800804 qemu_log_mask(
805 LOG_UNIMP, "Unknown host XDP type: %d\n", nlattr->nla_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200806 break;
807 }
808 return 0;
809}
810
811static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
812{
813 uint32_t *u32;
814 struct rtnl_link_stats *st;
815 struct rtnl_link_stats64 *st64;
816 struct rtnl_link_ifmap *map;
817 struct linkinfo_context li_context;
818
819 switch (rtattr->rta_type) {
820 /* binary stream */
821 case QEMU_IFLA_ADDRESS:
822 case QEMU_IFLA_BROADCAST:
Laurent Vivierd9679ee2020-07-09 09:23:31 +0200823 case QEMU_IFLA_PERM_ADDRESS:
Laurent Vivier312aef92021-12-19 16:45:12 +0100824 case QEMU_IFLA_PHYS_PORT_ID:
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200825 /* string */
826 case QEMU_IFLA_IFNAME:
827 case QEMU_IFLA_QDISC:
Laurent Vivier312aef92021-12-19 16:45:12 +0100828 case QEMU_IFLA_PARENT_DEV_NAME:
829 case QEMU_IFLA_PARENT_DEV_BUS_NAME:
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200830 break;
831 /* uin8_t */
832 case QEMU_IFLA_OPERSTATE:
833 case QEMU_IFLA_LINKMODE:
834 case QEMU_IFLA_CARRIER:
835 case QEMU_IFLA_PROTO_DOWN:
836 break;
837 /* uint32_t */
838 case QEMU_IFLA_MTU:
839 case QEMU_IFLA_LINK:
840 case QEMU_IFLA_WEIGHT:
841 case QEMU_IFLA_TXQLEN:
842 case QEMU_IFLA_CARRIER_CHANGES:
843 case QEMU_IFLA_NUM_RX_QUEUES:
844 case QEMU_IFLA_NUM_TX_QUEUES:
845 case QEMU_IFLA_PROMISCUITY:
846 case QEMU_IFLA_EXT_MASK:
847 case QEMU_IFLA_LINK_NETNSID:
848 case QEMU_IFLA_GROUP:
849 case QEMU_IFLA_MASTER:
850 case QEMU_IFLA_NUM_VF:
851 case QEMU_IFLA_GSO_MAX_SEGS:
852 case QEMU_IFLA_GSO_MAX_SIZE:
853 case QEMU_IFLA_CARRIER_UP_COUNT:
854 case QEMU_IFLA_CARRIER_DOWN_COUNT:
Laurent Vivier0f5faca2019-02-06 20:32:11 +0100855 case QEMU_IFLA_MIN_MTU:
856 case QEMU_IFLA_MAX_MTU:
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200857 u32 = RTA_DATA(rtattr);
858 *u32 = tswap32(*u32);
859 break;
860 /* struct rtnl_link_stats */
861 case QEMU_IFLA_STATS:
862 st = RTA_DATA(rtattr);
863 st->rx_packets = tswap32(st->rx_packets);
864 st->tx_packets = tswap32(st->tx_packets);
865 st->rx_bytes = tswap32(st->rx_bytes);
866 st->tx_bytes = tswap32(st->tx_bytes);
867 st->rx_errors = tswap32(st->rx_errors);
868 st->tx_errors = tswap32(st->tx_errors);
869 st->rx_dropped = tswap32(st->rx_dropped);
870 st->tx_dropped = tswap32(st->tx_dropped);
871 st->multicast = tswap32(st->multicast);
872 st->collisions = tswap32(st->collisions);
873
874 /* detailed rx_errors: */
875 st->rx_length_errors = tswap32(st->rx_length_errors);
876 st->rx_over_errors = tswap32(st->rx_over_errors);
877 st->rx_crc_errors = tswap32(st->rx_crc_errors);
878 st->rx_frame_errors = tswap32(st->rx_frame_errors);
879 st->rx_fifo_errors = tswap32(st->rx_fifo_errors);
880 st->rx_missed_errors = tswap32(st->rx_missed_errors);
881
882 /* detailed tx_errors */
883 st->tx_aborted_errors = tswap32(st->tx_aborted_errors);
884 st->tx_carrier_errors = tswap32(st->tx_carrier_errors);
885 st->tx_fifo_errors = tswap32(st->tx_fifo_errors);
886 st->tx_heartbeat_errors = tswap32(st->tx_heartbeat_errors);
887 st->tx_window_errors = tswap32(st->tx_window_errors);
888
889 /* for cslip etc */
890 st->rx_compressed = tswap32(st->rx_compressed);
891 st->tx_compressed = tswap32(st->tx_compressed);
892 break;
893 /* struct rtnl_link_stats64 */
894 case QEMU_IFLA_STATS64:
895 st64 = RTA_DATA(rtattr);
896 st64->rx_packets = tswap64(st64->rx_packets);
897 st64->tx_packets = tswap64(st64->tx_packets);
898 st64->rx_bytes = tswap64(st64->rx_bytes);
899 st64->tx_bytes = tswap64(st64->tx_bytes);
900 st64->rx_errors = tswap64(st64->rx_errors);
901 st64->tx_errors = tswap64(st64->tx_errors);
902 st64->rx_dropped = tswap64(st64->rx_dropped);
903 st64->tx_dropped = tswap64(st64->tx_dropped);
904 st64->multicast = tswap64(st64->multicast);
905 st64->collisions = tswap64(st64->collisions);
906
907 /* detailed rx_errors: */
908 st64->rx_length_errors = tswap64(st64->rx_length_errors);
909 st64->rx_over_errors = tswap64(st64->rx_over_errors);
910 st64->rx_crc_errors = tswap64(st64->rx_crc_errors);
911 st64->rx_frame_errors = tswap64(st64->rx_frame_errors);
912 st64->rx_fifo_errors = tswap64(st64->rx_fifo_errors);
913 st64->rx_missed_errors = tswap64(st64->rx_missed_errors);
914
915 /* detailed tx_errors */
916 st64->tx_aborted_errors = tswap64(st64->tx_aborted_errors);
917 st64->tx_carrier_errors = tswap64(st64->tx_carrier_errors);
918 st64->tx_fifo_errors = tswap64(st64->tx_fifo_errors);
919 st64->tx_heartbeat_errors = tswap64(st64->tx_heartbeat_errors);
920 st64->tx_window_errors = tswap64(st64->tx_window_errors);
921
922 /* for cslip etc */
923 st64->rx_compressed = tswap64(st64->rx_compressed);
924 st64->tx_compressed = tswap64(st64->tx_compressed);
925 break;
926 /* struct rtnl_link_ifmap */
927 case QEMU_IFLA_MAP:
928 map = RTA_DATA(rtattr);
929 map->mem_start = tswap64(map->mem_start);
930 map->mem_end = tswap64(map->mem_end);
931 map->base_addr = tswap64(map->base_addr);
932 map->irq = tswap16(map->irq);
933 break;
934 /* nested */
935 case QEMU_IFLA_LINKINFO:
936 memset(&li_context, 0, sizeof(li_context));
937 return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
938 &li_context,
939 host_to_target_data_linkinfo_nlattr);
940 case QEMU_IFLA_AF_SPEC:
941 return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
942 NULL,
943 host_to_target_data_spec_nlattr);
944 case QEMU_IFLA_XDP:
945 return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
946 NULL,
947 host_to_target_data_xdp_nlattr);
948 default:
Josh Kunz39be5352020-02-03 18:54:13 -0800949 qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA type: %d\n",
950 rtattr->rta_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200951 break;
952 }
953 return 0;
954}
955
956static abi_long host_to_target_data_addr_rtattr(struct rtattr *rtattr)
957{
958 uint32_t *u32;
959 struct ifa_cacheinfo *ci;
960
961 switch (rtattr->rta_type) {
962 /* binary: depends on family type */
963 case IFA_ADDRESS:
964 case IFA_LOCAL:
965 break;
966 /* string */
967 case IFA_LABEL:
968 break;
969 /* u32 */
970 case IFA_FLAGS:
971 case IFA_BROADCAST:
972 u32 = RTA_DATA(rtattr);
973 *u32 = tswap32(*u32);
974 break;
975 /* struct ifa_cacheinfo */
976 case IFA_CACHEINFO:
977 ci = RTA_DATA(rtattr);
978 ci->ifa_prefered = tswap32(ci->ifa_prefered);
979 ci->ifa_valid = tswap32(ci->ifa_valid);
980 ci->cstamp = tswap32(ci->cstamp);
981 ci->tstamp = tswap32(ci->tstamp);
982 break;
983 default:
Josh Kunz39be5352020-02-03 18:54:13 -0800984 qemu_log_mask(
985 LOG_UNIMP, "Unknown host IFA type: %d\n", rtattr->rta_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200986 break;
987 }
988 return 0;
989}
990
991static abi_long host_to_target_data_route_rtattr(struct rtattr *rtattr)
992{
993 uint32_t *u32;
994 struct rta_cacheinfo *ci;
995
996 switch (rtattr->rta_type) {
997 /* binary: depends on family type */
998 case QEMU_RTA_GATEWAY:
999 case QEMU_RTA_DST:
1000 case QEMU_RTA_PREFSRC:
1001 break;
1002 /* u8 */
1003 case QEMU_RTA_PREF:
1004 break;
1005 /* u32 */
1006 case QEMU_RTA_PRIORITY:
1007 case QEMU_RTA_TABLE:
1008 case QEMU_RTA_OIF:
1009 u32 = RTA_DATA(rtattr);
1010 *u32 = tswap32(*u32);
1011 break;
1012 /* struct rta_cacheinfo */
1013 case QEMU_RTA_CACHEINFO:
1014 ci = RTA_DATA(rtattr);
1015 ci->rta_clntref = tswap32(ci->rta_clntref);
1016 ci->rta_lastuse = tswap32(ci->rta_lastuse);
1017 ci->rta_expires = tswap32(ci->rta_expires);
1018 ci->rta_error = tswap32(ci->rta_error);
1019 ci->rta_used = tswap32(ci->rta_used);
1020#if defined(RTNETLINK_HAVE_PEERINFO)
1021 ci->rta_id = tswap32(ci->rta_id);
1022 ci->rta_ts = tswap32(ci->rta_ts);
1023 ci->rta_tsage = tswap32(ci->rta_tsage);
1024#endif
1025 break;
1026 default:
Josh Kunz39be5352020-02-03 18:54:13 -08001027 qemu_log_mask(
1028 LOG_UNIMP, "Unknown host RTA type: %d\n", rtattr->rta_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001029 break;
1030 }
1031 return 0;
1032}
1033
1034static abi_long host_to_target_link_rtattr(struct rtattr *rtattr,
1035 uint32_t rtattr_len)
1036{
1037 return host_to_target_for_each_rtattr(rtattr, rtattr_len,
1038 host_to_target_data_link_rtattr);
1039}
1040
1041static abi_long host_to_target_addr_rtattr(struct rtattr *rtattr,
1042 uint32_t rtattr_len)
1043{
1044 return host_to_target_for_each_rtattr(rtattr, rtattr_len,
1045 host_to_target_data_addr_rtattr);
1046}
1047
1048static abi_long host_to_target_route_rtattr(struct rtattr *rtattr,
1049 uint32_t rtattr_len)
1050{
1051 return host_to_target_for_each_rtattr(rtattr, rtattr_len,
1052 host_to_target_data_route_rtattr);
1053}
1054
1055static abi_long host_to_target_data_route(struct nlmsghdr *nlh)
1056{
1057 uint32_t nlmsg_len;
1058 struct ifinfomsg *ifi;
1059 struct ifaddrmsg *ifa;
1060 struct rtmsg *rtm;
1061
1062 nlmsg_len = nlh->nlmsg_len;
1063 switch (nlh->nlmsg_type) {
1064 case RTM_NEWLINK:
1065 case RTM_DELLINK:
1066 case RTM_GETLINK:
1067 if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifi))) {
1068 ifi = NLMSG_DATA(nlh);
1069 ifi->ifi_type = tswap16(ifi->ifi_type);
1070 ifi->ifi_index = tswap32(ifi->ifi_index);
1071 ifi->ifi_flags = tswap32(ifi->ifi_flags);
1072 ifi->ifi_change = tswap32(ifi->ifi_change);
1073 host_to_target_link_rtattr(IFLA_RTA(ifi),
1074 nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));
1075 }
1076 break;
1077 case RTM_NEWADDR:
1078 case RTM_DELADDR:
1079 case RTM_GETADDR:
1080 if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifa))) {
1081 ifa = NLMSG_DATA(nlh);
1082 ifa->ifa_index = tswap32(ifa->ifa_index);
1083 host_to_target_addr_rtattr(IFA_RTA(ifa),
1084 nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
1085 }
1086 break;
1087 case RTM_NEWROUTE:
1088 case RTM_DELROUTE:
1089 case RTM_GETROUTE:
1090 if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*rtm))) {
1091 rtm = NLMSG_DATA(nlh);
1092 rtm->rtm_flags = tswap32(rtm->rtm_flags);
1093 host_to_target_route_rtattr(RTM_RTA(rtm),
1094 nlmsg_len - NLMSG_LENGTH(sizeof(*rtm)));
1095 }
1096 break;
1097 default:
1098 return -TARGET_EINVAL;
1099 }
1100 return 0;
1101}
1102
1103static inline abi_long host_to_target_nlmsg_route(struct nlmsghdr *nlh,
1104 size_t len)
1105{
1106 return host_to_target_for_each_nlmsg(nlh, len, host_to_target_data_route);
1107}
1108
1109static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr,
1110 size_t len,
1111 abi_long (*target_to_host_rtattr)
1112 (struct rtattr *))
1113{
Shu-Chun Weng1645fb52019-10-17 17:19:20 -07001114 unsigned short aligned_rta_len;
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001115 abi_long ret;
1116
1117 while (len >= sizeof(struct rtattr)) {
1118 if (tswap16(rtattr->rta_len) < sizeof(struct rtattr) ||
1119 tswap16(rtattr->rta_len) > len) {
1120 break;
1121 }
1122 rtattr->rta_len = tswap16(rtattr->rta_len);
1123 rtattr->rta_type = tswap16(rtattr->rta_type);
1124 ret = target_to_host_rtattr(rtattr);
1125 if (ret < 0) {
1126 return ret;
1127 }
Shu-Chun Weng1645fb52019-10-17 17:19:20 -07001128
1129 aligned_rta_len = RTA_ALIGN(rtattr->rta_len);
1130 if (aligned_rta_len >= len) {
1131 break;
1132 }
1133 len -= aligned_rta_len;
1134 rtattr = (struct rtattr *)(((char *)rtattr) + aligned_rta_len);
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001135 }
1136 return 0;
1137}
1138
1139static abi_long target_to_host_data_link_rtattr(struct rtattr *rtattr)
1140{
Laurent Vivier5351f402020-11-17 12:19:05 +01001141 uint32_t *u32;
1142
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001143 switch (rtattr->rta_type) {
Laurent Vivier5351f402020-11-17 12:19:05 +01001144 /* uint32_t */
1145 case QEMU_IFLA_EXT_MASK:
1146 u32 = RTA_DATA(rtattr);
1147 *u32 = tswap32(*u32);
1148 break;
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001149 default:
Josh Kunz39be5352020-02-03 18:54:13 -08001150 qemu_log_mask(LOG_UNIMP, "Unknown target QEMU_IFLA type: %d\n",
1151 rtattr->rta_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001152 break;
1153 }
1154 return 0;
1155}
1156
1157static abi_long target_to_host_data_addr_rtattr(struct rtattr *rtattr)
1158{
1159 switch (rtattr->rta_type) {
1160 /* binary: depends on family type */
1161 case IFA_LOCAL:
1162 case IFA_ADDRESS:
1163 break;
1164 default:
Josh Kunz39be5352020-02-03 18:54:13 -08001165 qemu_log_mask(LOG_UNIMP, "Unknown target IFA type: %d\n",
1166 rtattr->rta_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001167 break;
1168 }
1169 return 0;
1170}
1171
1172static abi_long target_to_host_data_route_rtattr(struct rtattr *rtattr)
1173{
1174 uint32_t *u32;
1175 switch (rtattr->rta_type) {
1176 /* binary: depends on family type */
1177 case QEMU_RTA_DST:
1178 case QEMU_RTA_SRC:
1179 case QEMU_RTA_GATEWAY:
1180 break;
1181 /* u32 */
1182 case QEMU_RTA_PRIORITY:
Laurent Vivierf5366122020-11-16 17:36:22 +01001183 case QEMU_RTA_TABLE:
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001184 case QEMU_RTA_OIF:
1185 u32 = RTA_DATA(rtattr);
1186 *u32 = tswap32(*u32);
1187 break;
1188 default:
Josh Kunz39be5352020-02-03 18:54:13 -08001189 qemu_log_mask(LOG_UNIMP, "Unknown target RTA type: %d\n",
1190 rtattr->rta_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001191 break;
1192 }
1193 return 0;
1194}
1195
1196static void target_to_host_link_rtattr(struct rtattr *rtattr,
1197 uint32_t rtattr_len)
1198{
1199 target_to_host_for_each_rtattr(rtattr, rtattr_len,
1200 target_to_host_data_link_rtattr);
1201}
1202
1203static void target_to_host_addr_rtattr(struct rtattr *rtattr,
1204 uint32_t rtattr_len)
1205{
1206 target_to_host_for_each_rtattr(rtattr, rtattr_len,
1207 target_to_host_data_addr_rtattr);
1208}
1209
1210static void target_to_host_route_rtattr(struct rtattr *rtattr,
1211 uint32_t rtattr_len)
1212{
1213 target_to_host_for_each_rtattr(rtattr, rtattr_len,
1214 target_to_host_data_route_rtattr);
1215}
1216
1217static abi_long target_to_host_data_route(struct nlmsghdr *nlh)
1218{
1219 struct ifinfomsg *ifi;
1220 struct ifaddrmsg *ifa;
1221 struct rtmsg *rtm;
1222
1223 switch (nlh->nlmsg_type) {
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001224 case RTM_NEWLINK:
1225 case RTM_DELLINK:
Laurent Vivier65b261a2020-07-09 09:23:32 +02001226 case RTM_SETLINK:
Laurent Vivierf5366122020-11-16 17:36:22 +01001227 case RTM_GETLINK:
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001228 if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifi))) {
1229 ifi = NLMSG_DATA(nlh);
1230 ifi->ifi_type = tswap16(ifi->ifi_type);
1231 ifi->ifi_index = tswap32(ifi->ifi_index);
1232 ifi->ifi_flags = tswap32(ifi->ifi_flags);
1233 ifi->ifi_change = tswap32(ifi->ifi_change);
1234 target_to_host_link_rtattr(IFLA_RTA(ifi), nlh->nlmsg_len -
1235 NLMSG_LENGTH(sizeof(*ifi)));
1236 }
1237 break;
1238 case RTM_GETADDR:
1239 case RTM_NEWADDR:
1240 case RTM_DELADDR:
1241 if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifa))) {
1242 ifa = NLMSG_DATA(nlh);
1243 ifa->ifa_index = tswap32(ifa->ifa_index);
1244 target_to_host_addr_rtattr(IFA_RTA(ifa), nlh->nlmsg_len -
1245 NLMSG_LENGTH(sizeof(*ifa)));
1246 }
1247 break;
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001248 case RTM_NEWROUTE:
1249 case RTM_DELROUTE:
Laurent Vivierf5366122020-11-16 17:36:22 +01001250 case RTM_GETROUTE:
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001251 if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*rtm))) {
1252 rtm = NLMSG_DATA(nlh);
1253 rtm->rtm_flags = tswap32(rtm->rtm_flags);
1254 target_to_host_route_rtattr(RTM_RTA(rtm), nlh->nlmsg_len -
1255 NLMSG_LENGTH(sizeof(*rtm)));
1256 }
1257 break;
1258 default:
1259 return -TARGET_EOPNOTSUPP;
1260 }
1261 return 0;
1262}
1263
1264static abi_long target_to_host_nlmsg_route(struct nlmsghdr *nlh, size_t len)
1265{
1266 return target_to_host_for_each_nlmsg(nlh, len, target_to_host_data_route);
1267}
1268#endif /* CONFIG_RTNETLINK */
1269
1270static abi_long host_to_target_data_audit(struct nlmsghdr *nlh)
1271{
1272 switch (nlh->nlmsg_type) {
1273 default:
Josh Kunz39be5352020-02-03 18:54:13 -08001274 qemu_log_mask(LOG_UNIMP, "Unknown host audit message type %d\n",
1275 nlh->nlmsg_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001276 return -TARGET_EINVAL;
1277 }
1278 return 0;
1279}
1280
1281static inline abi_long host_to_target_nlmsg_audit(struct nlmsghdr *nlh,
1282 size_t len)
1283{
1284 return host_to_target_for_each_nlmsg(nlh, len, host_to_target_data_audit);
1285}
1286
1287static abi_long target_to_host_data_audit(struct nlmsghdr *nlh)
1288{
1289 switch (nlh->nlmsg_type) {
1290 case AUDIT_USER:
1291 case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
1292 case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
1293 break;
1294 default:
Josh Kunz39be5352020-02-03 18:54:13 -08001295 qemu_log_mask(LOG_UNIMP, "Unknown target audit message type %d\n",
1296 nlh->nlmsg_type);
Laurent Vivierf7e6a402018-08-24 00:22:15 +02001297 return -TARGET_EINVAL;
1298 }
1299
1300 return 0;
1301}
1302
1303static abi_long target_to_host_nlmsg_audit(struct nlmsghdr *nlh, size_t len)
1304{
1305 return target_to_host_for_each_nlmsg(nlh, len, target_to_host_data_audit);
1306}
1307
1308static abi_long packet_target_to_host_sockaddr(void *host_addr,
1309 abi_ulong target_addr,
1310 socklen_t len)
1311{
1312 struct sockaddr *addr = host_addr;
1313 struct target_sockaddr *target_saddr;
1314
1315 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1316 if (!target_saddr) {
1317 return -TARGET_EFAULT;
1318 }
1319
1320 memcpy(addr, target_saddr, len);
1321 addr->sa_family = tswap16(target_saddr->sa_family);
1322 /* spkt_protocol is big-endian */
1323
1324 unlock_user(target_saddr, target_addr, 0);
1325 return 0;
1326}
1327
1328TargetFdTrans target_packet_trans = {
1329 .target_to_host_addr = packet_target_to_host_sockaddr,
1330};
1331
1332#ifdef CONFIG_RTNETLINK
1333static abi_long netlink_route_target_to_host(void *buf, size_t len)
1334{
1335 abi_long ret;
1336
1337 ret = target_to_host_nlmsg_route(buf, len);
1338 if (ret < 0) {
1339 return ret;
1340 }
1341
1342 return len;
1343}
1344
1345static abi_long netlink_route_host_to_target(void *buf, size_t len)
1346{
1347 abi_long ret;
1348
1349 ret = host_to_target_nlmsg_route(buf, len);
1350 if (ret < 0) {
1351 return ret;
1352 }
1353
1354 return len;
1355}
1356
1357TargetFdTrans target_netlink_route_trans = {
1358 .target_to_host_data = netlink_route_target_to_host,
1359 .host_to_target_data = netlink_route_host_to_target,
1360};
1361#endif /* CONFIG_RTNETLINK */
1362
1363static abi_long netlink_audit_target_to_host(void *buf, size_t len)
1364{
1365 abi_long ret;
1366
1367 ret = target_to_host_nlmsg_audit(buf, len);
1368 if (ret < 0) {
1369 return ret;
1370 }
1371
1372 return len;
1373}
1374
1375static abi_long netlink_audit_host_to_target(void *buf, size_t len)
1376{
1377 abi_long ret;
1378
1379 ret = host_to_target_nlmsg_audit(buf, len);
1380 if (ret < 0) {
1381 return ret;
1382 }
1383
1384 return len;
1385}
1386
1387TargetFdTrans target_netlink_audit_trans = {
1388 .target_to_host_data = netlink_audit_target_to_host,
1389 .host_to_target_data = netlink_audit_host_to_target,
1390};
1391
1392/* signalfd siginfo conversion */
1393
1394static void
1395host_to_target_signalfd_siginfo(struct signalfd_siginfo *tinfo,
1396 const struct signalfd_siginfo *info)
1397{
1398 int sig = host_to_target_signal(info->ssi_signo);
1399
1400 /* linux/signalfd.h defines a ssi_addr_lsb
1401 * not defined in sys/signalfd.h but used by some kernels
1402 */
1403
1404#ifdef BUS_MCEERR_AO
1405 if (tinfo->ssi_signo == SIGBUS &&
1406 (tinfo->ssi_code == BUS_MCEERR_AR ||
1407 tinfo->ssi_code == BUS_MCEERR_AO)) {
1408 uint16_t *ssi_addr_lsb = (uint16_t *)(&info->ssi_addr + 1);
1409 uint16_t *tssi_addr_lsb = (uint16_t *)(&tinfo->ssi_addr + 1);
1410 *tssi_addr_lsb = tswap16(*ssi_addr_lsb);
1411 }
1412#endif
1413
1414 tinfo->ssi_signo = tswap32(sig);
1415 tinfo->ssi_errno = tswap32(tinfo->ssi_errno);
1416 tinfo->ssi_code = tswap32(info->ssi_code);
1417 tinfo->ssi_pid = tswap32(info->ssi_pid);
1418 tinfo->ssi_uid = tswap32(info->ssi_uid);
1419 tinfo->ssi_fd = tswap32(info->ssi_fd);
1420 tinfo->ssi_tid = tswap32(info->ssi_tid);
1421 tinfo->ssi_band = tswap32(info->ssi_band);
1422 tinfo->ssi_overrun = tswap32(info->ssi_overrun);
1423 tinfo->ssi_trapno = tswap32(info->ssi_trapno);
1424 tinfo->ssi_status = tswap32(info->ssi_status);
1425 tinfo->ssi_int = tswap32(info->ssi_int);
1426 tinfo->ssi_ptr = tswap64(info->ssi_ptr);
1427 tinfo->ssi_utime = tswap64(info->ssi_utime);
1428 tinfo->ssi_stime = tswap64(info->ssi_stime);
1429 tinfo->ssi_addr = tswap64(info->ssi_addr);
1430}
1431
1432static abi_long host_to_target_data_signalfd(void *buf, size_t len)
1433{
1434 int i;
1435
1436 for (i = 0; i < len; i += sizeof(struct signalfd_siginfo)) {
1437 host_to_target_signalfd_siginfo(buf + i, buf + i);
1438 }
1439
1440 return len;
1441}
1442
1443TargetFdTrans target_signalfd_trans = {
1444 .host_to_target_data = host_to_target_data_signalfd,
1445};
1446
1447static abi_long swap_data_eventfd(void *buf, size_t len)
1448{
1449 uint64_t *counter = buf;
1450 int i;
1451
1452 if (len < sizeof(uint64_t)) {
1453 return -EINVAL;
1454 }
1455
1456 for (i = 0; i < len; i += sizeof(uint64_t)) {
1457 *counter = tswap64(*counter);
1458 counter++;
1459 }
1460
1461 return len;
1462}
1463
1464TargetFdTrans target_eventfd_trans = {
1465 .host_to_target_data = swap_data_eventfd,
1466 .target_to_host_data = swap_data_eventfd,
1467};
1468
1469#if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \
1470 (defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \
1471 defined(__NR_inotify_init1))
1472static abi_long host_to_target_data_inotify(void *buf, size_t len)
1473{
1474 struct inotify_event *ev;
1475 int i;
1476 uint32_t name_len;
1477
1478 for (i = 0; i < len; i += sizeof(struct inotify_event) + name_len) {
1479 ev = (struct inotify_event *)((char *)buf + i);
1480 name_len = ev->len;
1481
1482 ev->wd = tswap32(ev->wd);
1483 ev->mask = tswap32(ev->mask);
1484 ev->cookie = tswap32(ev->cookie);
1485 ev->len = tswap32(name_len);
1486 }
1487
1488 return len;
1489}
1490
1491TargetFdTrans target_inotify_trans = {
1492 .host_to_target_data = host_to_target_data_inotify,
1493};
1494#endif