xref: /qemu/linux-user/fd-trans.c (revision 2fe8ed6f)
1f7e6a401SLaurent Vivier /*
2f7e6a401SLaurent Vivier  *  This program is free software; you can redistribute it and/or modify
3f7e6a401SLaurent Vivier  *  it under the terms of the GNU General Public License as published by
4f7e6a401SLaurent Vivier  *  the Free Software Foundation; either version 2 of the License, or
5f7e6a401SLaurent Vivier  *  (at your option) any later version.
6f7e6a401SLaurent Vivier  *
7f7e6a401SLaurent Vivier  *  This program is distributed in the hope that it will be useful,
8f7e6a401SLaurent Vivier  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9f7e6a401SLaurent Vivier  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10f7e6a401SLaurent Vivier  *  GNU General Public License for more details.
11f7e6a401SLaurent Vivier  *
12f7e6a401SLaurent Vivier  *  You should have received a copy of the GNU General Public License
13f7e6a401SLaurent Vivier  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
14f7e6a401SLaurent Vivier  */
15f7e6a401SLaurent Vivier 
16f7e6a401SLaurent Vivier #include "qemu/osdep.h"
17f7e6a401SLaurent Vivier 
18f7e6a401SLaurent Vivier #include <sys/signalfd.h>
19f7e6a401SLaurent Vivier #include <linux/unistd.h>
20f7e6a401SLaurent Vivier #include <linux/audit.h>
21f7e6a401SLaurent Vivier #ifdef CONFIG_INOTIFY
22f7e6a401SLaurent Vivier #include <sys/inotify.h>
23f7e6a401SLaurent Vivier #endif
24f7e6a401SLaurent Vivier #include <linux/netlink.h>
25f7e6a401SLaurent Vivier #ifdef CONFIG_RTNETLINK
26f7e6a401SLaurent Vivier #include <linux/rtnetlink.h>
27f7e6a401SLaurent Vivier #include <linux/if_bridge.h>
28f7e6a401SLaurent Vivier #endif
29f7e6a401SLaurent Vivier #include "qemu.h"
303b249d26SPeter Maydell #include "user-internals.h"
31f7e6a401SLaurent Vivier #include "fd-trans.h"
322113aed6SPeter Maydell #include "signal-common.h"
33f7e6a401SLaurent Vivier 
34f7e6a401SLaurent Vivier enum {
35f7e6a401SLaurent Vivier     QEMU_IFLA_BR_UNSPEC,
36f7e6a401SLaurent Vivier     QEMU_IFLA_BR_FORWARD_DELAY,
37f7e6a401SLaurent Vivier     QEMU_IFLA_BR_HELLO_TIME,
38f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MAX_AGE,
39f7e6a401SLaurent Vivier     QEMU_IFLA_BR_AGEING_TIME,
40f7e6a401SLaurent Vivier     QEMU_IFLA_BR_STP_STATE,
41f7e6a401SLaurent Vivier     QEMU_IFLA_BR_PRIORITY,
42f7e6a401SLaurent Vivier     QEMU_IFLA_BR_VLAN_FILTERING,
43f7e6a401SLaurent Vivier     QEMU_IFLA_BR_VLAN_PROTOCOL,
44f7e6a401SLaurent Vivier     QEMU_IFLA_BR_GROUP_FWD_MASK,
45f7e6a401SLaurent Vivier     QEMU_IFLA_BR_ROOT_ID,
46f7e6a401SLaurent Vivier     QEMU_IFLA_BR_BRIDGE_ID,
47f7e6a401SLaurent Vivier     QEMU_IFLA_BR_ROOT_PORT,
48f7e6a401SLaurent Vivier     QEMU_IFLA_BR_ROOT_PATH_COST,
49f7e6a401SLaurent Vivier     QEMU_IFLA_BR_TOPOLOGY_CHANGE,
50f7e6a401SLaurent Vivier     QEMU_IFLA_BR_TOPOLOGY_CHANGE_DETECTED,
51f7e6a401SLaurent Vivier     QEMU_IFLA_BR_HELLO_TIMER,
52f7e6a401SLaurent Vivier     QEMU_IFLA_BR_TCN_TIMER,
53f7e6a401SLaurent Vivier     QEMU_IFLA_BR_TOPOLOGY_CHANGE_TIMER,
54f7e6a401SLaurent Vivier     QEMU_IFLA_BR_GC_TIMER,
55f7e6a401SLaurent Vivier     QEMU_IFLA_BR_GROUP_ADDR,
56f7e6a401SLaurent Vivier     QEMU_IFLA_BR_FDB_FLUSH,
57f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_ROUTER,
58f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_SNOOPING,
59f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_QUERY_USE_IFADDR,
60f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_QUERIER,
61f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_HASH_ELASTICITY,
62f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_HASH_MAX,
63f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_LAST_MEMBER_CNT,
64f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_STARTUP_QUERY_CNT,
65f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_LAST_MEMBER_INTVL,
66f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_MEMBERSHIP_INTVL,
67f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_QUERIER_INTVL,
68f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_QUERY_INTVL,
69f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
70f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_STARTUP_QUERY_INTVL,
71f7e6a401SLaurent Vivier     QEMU_IFLA_BR_NF_CALL_IPTABLES,
72f7e6a401SLaurent Vivier     QEMU_IFLA_BR_NF_CALL_IP6TABLES,
73f7e6a401SLaurent Vivier     QEMU_IFLA_BR_NF_CALL_ARPTABLES,
74f7e6a401SLaurent Vivier     QEMU_IFLA_BR_VLAN_DEFAULT_PVID,
75f7e6a401SLaurent Vivier     QEMU_IFLA_BR_PAD,
76f7e6a401SLaurent Vivier     QEMU_IFLA_BR_VLAN_STATS_ENABLED,
77f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_STATS_ENABLED,
78f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_IGMP_VERSION,
79f7e6a401SLaurent Vivier     QEMU_IFLA_BR_MCAST_MLD_VERSION,
8061b463fbSLaurent Vivier     QEMU_IFLA_BR_VLAN_STATS_PER_PORT,
8161b463fbSLaurent Vivier     QEMU_IFLA_BR_MULTI_BOOLOPT,
82f7e6a401SLaurent Vivier     QEMU___IFLA_BR_MAX,
83f7e6a401SLaurent Vivier };
84f7e6a401SLaurent Vivier 
85f7e6a401SLaurent Vivier enum {
86f7e6a401SLaurent Vivier     QEMU_IFLA_UNSPEC,
87f7e6a401SLaurent Vivier     QEMU_IFLA_ADDRESS,
88f7e6a401SLaurent Vivier     QEMU_IFLA_BROADCAST,
89f7e6a401SLaurent Vivier     QEMU_IFLA_IFNAME,
90f7e6a401SLaurent Vivier     QEMU_IFLA_MTU,
91f7e6a401SLaurent Vivier     QEMU_IFLA_LINK,
92f7e6a401SLaurent Vivier     QEMU_IFLA_QDISC,
93f7e6a401SLaurent Vivier     QEMU_IFLA_STATS,
94f7e6a401SLaurent Vivier     QEMU_IFLA_COST,
95f7e6a401SLaurent Vivier     QEMU_IFLA_PRIORITY,
96f7e6a401SLaurent Vivier     QEMU_IFLA_MASTER,
97f7e6a401SLaurent Vivier     QEMU_IFLA_WIRELESS,
98f7e6a401SLaurent Vivier     QEMU_IFLA_PROTINFO,
99f7e6a401SLaurent Vivier     QEMU_IFLA_TXQLEN,
100f7e6a401SLaurent Vivier     QEMU_IFLA_MAP,
101f7e6a401SLaurent Vivier     QEMU_IFLA_WEIGHT,
102f7e6a401SLaurent Vivier     QEMU_IFLA_OPERSTATE,
103f7e6a401SLaurent Vivier     QEMU_IFLA_LINKMODE,
104f7e6a401SLaurent Vivier     QEMU_IFLA_LINKINFO,
105f7e6a401SLaurent Vivier     QEMU_IFLA_NET_NS_PID,
106f7e6a401SLaurent Vivier     QEMU_IFLA_IFALIAS,
107f7e6a401SLaurent Vivier     QEMU_IFLA_NUM_VF,
108f7e6a401SLaurent Vivier     QEMU_IFLA_VFINFO_LIST,
109f7e6a401SLaurent Vivier     QEMU_IFLA_STATS64,
110f7e6a401SLaurent Vivier     QEMU_IFLA_VF_PORTS,
111f7e6a401SLaurent Vivier     QEMU_IFLA_PORT_SELF,
112f7e6a401SLaurent Vivier     QEMU_IFLA_AF_SPEC,
113f7e6a401SLaurent Vivier     QEMU_IFLA_GROUP,
114f7e6a401SLaurent Vivier     QEMU_IFLA_NET_NS_FD,
115f7e6a401SLaurent Vivier     QEMU_IFLA_EXT_MASK,
116f7e6a401SLaurent Vivier     QEMU_IFLA_PROMISCUITY,
117f7e6a401SLaurent Vivier     QEMU_IFLA_NUM_TX_QUEUES,
118f7e6a401SLaurent Vivier     QEMU_IFLA_NUM_RX_QUEUES,
119f7e6a401SLaurent Vivier     QEMU_IFLA_CARRIER,
120f7e6a401SLaurent Vivier     QEMU_IFLA_PHYS_PORT_ID,
121f7e6a401SLaurent Vivier     QEMU_IFLA_CARRIER_CHANGES,
122f7e6a401SLaurent Vivier     QEMU_IFLA_PHYS_SWITCH_ID,
123f7e6a401SLaurent Vivier     QEMU_IFLA_LINK_NETNSID,
124f7e6a401SLaurent Vivier     QEMU_IFLA_PHYS_PORT_NAME,
125f7e6a401SLaurent Vivier     QEMU_IFLA_PROTO_DOWN,
126f7e6a401SLaurent Vivier     QEMU_IFLA_GSO_MAX_SEGS,
127f7e6a401SLaurent Vivier     QEMU_IFLA_GSO_MAX_SIZE,
128f7e6a401SLaurent Vivier     QEMU_IFLA_PAD,
129f7e6a401SLaurent Vivier     QEMU_IFLA_XDP,
130f7e6a401SLaurent Vivier     QEMU_IFLA_EVENT,
131f7e6a401SLaurent Vivier     QEMU_IFLA_NEW_NETNSID,
132f7e6a401SLaurent Vivier     QEMU_IFLA_IF_NETNSID,
133f7e6a401SLaurent Vivier     QEMU_IFLA_CARRIER_UP_COUNT,
134f7e6a401SLaurent Vivier     QEMU_IFLA_CARRIER_DOWN_COUNT,
135f7e6a401SLaurent Vivier     QEMU_IFLA_NEW_IFINDEX,
1360f5faca7SLaurent Vivier     QEMU_IFLA_MIN_MTU,
1370f5faca7SLaurent Vivier     QEMU_IFLA_MAX_MTU,
138d9679ee5SLaurent Vivier     QEMU_IFLA_PROP_LIST,
139d9679ee5SLaurent Vivier     QEMU_IFLA_ALT_IFNAME,
140d9679ee5SLaurent Vivier     QEMU_IFLA_PERM_ADDRESS,
141312aef98SLaurent Vivier     QEMU_IFLA_PROTO_DOWN_REASON,
142312aef98SLaurent Vivier     QEMU_IFLA_PARENT_DEV_NAME,
143312aef98SLaurent Vivier     QEMU_IFLA_PARENT_DEV_BUS_NAME,
144f7e6a401SLaurent Vivier     QEMU___IFLA_MAX
145f7e6a401SLaurent Vivier };
146f7e6a401SLaurent Vivier 
147f7e6a401SLaurent Vivier enum {
148f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_UNSPEC,
149f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_STATE,
150f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_PRIORITY,
151f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_COST,
152f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_MODE,
153f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_GUARD,
154f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_PROTECT,
155f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_FAST_LEAVE,
156f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_LEARNING,
157f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_UNICAST_FLOOD,
158f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_PROXYARP,
159f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_LEARNING_SYNC,
160f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_PROXYARP_WIFI,
161f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_ROOT_ID,
162f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_BRIDGE_ID,
163f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_DESIGNATED_PORT,
164f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_DESIGNATED_COST,
165f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_ID,
166f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_NO,
167f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
168f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_CONFIG_PENDING,
169f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_MESSAGE_AGE_TIMER,
170f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_FORWARD_DELAY_TIMER,
171f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_HOLD_TIMER,
172f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_FLUSH,
173f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_MULTICAST_ROUTER,
174f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_PAD,
175f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_MCAST_FLOOD,
176f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_MCAST_TO_UCAST,
177f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_VLAN_TUNNEL,
178f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_BCAST_FLOOD,
179f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_GROUP_FWD_MASK,
180f7e6a401SLaurent Vivier     QEMU_IFLA_BRPORT_NEIGH_SUPPRESS,
1810f5faca7SLaurent Vivier     QEMU_IFLA_BRPORT_ISOLATED,
1820f5faca7SLaurent Vivier     QEMU_IFLA_BRPORT_BACKUP_PORT,
1835351f407SLaurent Vivier     QEMU_IFLA_BRPORT_MRP_RING_OPEN,
1845351f407SLaurent Vivier     QEMU_IFLA_BRPORT_MRP_IN_OPEN,
185f0effdbcSLaurent Vivier     QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT,
186f0effdbcSLaurent Vivier     QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
187f7e6a401SLaurent Vivier     QEMU___IFLA_BRPORT_MAX
188f7e6a401SLaurent Vivier };
189f7e6a401SLaurent Vivier 
190f7e6a401SLaurent Vivier enum {
191f7e6a401SLaurent Vivier     QEMU_IFLA_TUN_UNSPEC,
192f7e6a401SLaurent Vivier     QEMU_IFLA_TUN_OWNER,
193f7e6a401SLaurent Vivier     QEMU_IFLA_TUN_GROUP,
194f7e6a401SLaurent Vivier     QEMU_IFLA_TUN_TYPE,
195f7e6a401SLaurent Vivier     QEMU_IFLA_TUN_PI,
196f7e6a401SLaurent Vivier     QEMU_IFLA_TUN_VNET_HDR,
197f7e6a401SLaurent Vivier     QEMU_IFLA_TUN_PERSIST,
198f7e6a401SLaurent Vivier     QEMU_IFLA_TUN_MULTI_QUEUE,
199f7e6a401SLaurent Vivier     QEMU_IFLA_TUN_NUM_QUEUES,
200f7e6a401SLaurent Vivier     QEMU_IFLA_TUN_NUM_DISABLED_QUEUES,
201f7e6a401SLaurent Vivier     QEMU___IFLA_TUN_MAX,
202f7e6a401SLaurent Vivier };
203f7e6a401SLaurent Vivier 
204f7e6a401SLaurent Vivier enum {
205f7e6a401SLaurent Vivier     QEMU_IFLA_INFO_UNSPEC,
206f7e6a401SLaurent Vivier     QEMU_IFLA_INFO_KIND,
207f7e6a401SLaurent Vivier     QEMU_IFLA_INFO_DATA,
208f7e6a401SLaurent Vivier     QEMU_IFLA_INFO_XSTATS,
209f7e6a401SLaurent Vivier     QEMU_IFLA_INFO_SLAVE_KIND,
210f7e6a401SLaurent Vivier     QEMU_IFLA_INFO_SLAVE_DATA,
211f7e6a401SLaurent Vivier     QEMU___IFLA_INFO_MAX,
212f7e6a401SLaurent Vivier };
213f7e6a401SLaurent Vivier 
214f7e6a401SLaurent Vivier enum {
215f7e6a401SLaurent Vivier     QEMU_IFLA_INET_UNSPEC,
216f7e6a401SLaurent Vivier     QEMU_IFLA_INET_CONF,
217f7e6a401SLaurent Vivier     QEMU___IFLA_INET_MAX,
218f7e6a401SLaurent Vivier };
219f7e6a401SLaurent Vivier 
220f7e6a401SLaurent Vivier enum {
221f7e6a401SLaurent Vivier     QEMU_IFLA_INET6_UNSPEC,
222f7e6a401SLaurent Vivier     QEMU_IFLA_INET6_FLAGS,
223f7e6a401SLaurent Vivier     QEMU_IFLA_INET6_CONF,
224f7e6a401SLaurent Vivier     QEMU_IFLA_INET6_STATS,
225f7e6a401SLaurent Vivier     QEMU_IFLA_INET6_MCAST,
226f7e6a401SLaurent Vivier     QEMU_IFLA_INET6_CACHEINFO,
227f7e6a401SLaurent Vivier     QEMU_IFLA_INET6_ICMP6STATS,
228f7e6a401SLaurent Vivier     QEMU_IFLA_INET6_TOKEN,
229f7e6a401SLaurent Vivier     QEMU_IFLA_INET6_ADDR_GEN_MODE,
230f7e6a401SLaurent Vivier     QEMU___IFLA_INET6_MAX
231f7e6a401SLaurent Vivier };
232f7e6a401SLaurent Vivier 
233f7e6a401SLaurent Vivier enum {
234f7e6a401SLaurent Vivier     QEMU_IFLA_XDP_UNSPEC,
235f7e6a401SLaurent Vivier     QEMU_IFLA_XDP_FD,
236f7e6a401SLaurent Vivier     QEMU_IFLA_XDP_ATTACHED,
237f7e6a401SLaurent Vivier     QEMU_IFLA_XDP_FLAGS,
238f7e6a401SLaurent Vivier     QEMU_IFLA_XDP_PROG_ID,
239f7e6a401SLaurent Vivier     QEMU___IFLA_XDP_MAX,
240f7e6a401SLaurent Vivier };
241f7e6a401SLaurent Vivier 
242f7e6a401SLaurent Vivier enum {
243f7e6a401SLaurent Vivier     QEMU_RTA_UNSPEC,
244f7e6a401SLaurent Vivier     QEMU_RTA_DST,
245f7e6a401SLaurent Vivier     QEMU_RTA_SRC,
246f7e6a401SLaurent Vivier     QEMU_RTA_IIF,
247f7e6a401SLaurent Vivier     QEMU_RTA_OIF,
248f7e6a401SLaurent Vivier     QEMU_RTA_GATEWAY,
249f7e6a401SLaurent Vivier     QEMU_RTA_PRIORITY,
250f7e6a401SLaurent Vivier     QEMU_RTA_PREFSRC,
251f7e6a401SLaurent Vivier     QEMU_RTA_METRICS,
252f7e6a401SLaurent Vivier     QEMU_RTA_MULTIPATH,
253f7e6a401SLaurent Vivier     QEMU_RTA_PROTOINFO, /* no longer used */
254f7e6a401SLaurent Vivier     QEMU_RTA_FLOW,
255f7e6a401SLaurent Vivier     QEMU_RTA_CACHEINFO,
256f7e6a401SLaurent Vivier     QEMU_RTA_SESSION, /* no longer used */
257f7e6a401SLaurent Vivier     QEMU_RTA_MP_ALGO, /* no longer used */
258f7e6a401SLaurent Vivier     QEMU_RTA_TABLE,
259f7e6a401SLaurent Vivier     QEMU_RTA_MARK,
260f7e6a401SLaurent Vivier     QEMU_RTA_MFC_STATS,
261f7e6a401SLaurent Vivier     QEMU_RTA_VIA,
262f7e6a401SLaurent Vivier     QEMU_RTA_NEWDST,
263f7e6a401SLaurent Vivier     QEMU_RTA_PREF,
264f7e6a401SLaurent Vivier     QEMU_RTA_ENCAP_TYPE,
265f7e6a401SLaurent Vivier     QEMU_RTA_ENCAP,
266f7e6a401SLaurent Vivier     QEMU_RTA_EXPIRES,
267f7e6a401SLaurent Vivier     QEMU_RTA_PAD,
268f7e6a401SLaurent Vivier     QEMU_RTA_UID,
269f7e6a401SLaurent Vivier     QEMU_RTA_TTL_PROPAGATE,
270f7e6a401SLaurent Vivier     QEMU_RTA_IP_PROTO,
271f7e6a401SLaurent Vivier     QEMU_RTA_SPORT,
272f7e6a401SLaurent Vivier     QEMU_RTA_DPORT,
273f7e6a401SLaurent Vivier     QEMU___RTA_MAX
274f7e6a401SLaurent Vivier };
275f7e6a401SLaurent Vivier 
276a9947867SLaurent Vivier enum {
277a9947867SLaurent Vivier     QEMU_IFLA_VF_STATS_RX_PACKETS,
278a9947867SLaurent Vivier     QEMU_IFLA_VF_STATS_TX_PACKETS,
279a9947867SLaurent Vivier     QEMU_IFLA_VF_STATS_RX_BYTES,
280a9947867SLaurent Vivier     QEMU_IFLA_VF_STATS_TX_BYTES,
281a9947867SLaurent Vivier     QEMU_IFLA_VF_STATS_BROADCAST,
282a9947867SLaurent Vivier     QEMU_IFLA_VF_STATS_MULTICAST,
283a9947867SLaurent Vivier     QEMU_IFLA_VF_STATS_PAD,
284a9947867SLaurent Vivier     QEMU_IFLA_VF_STATS_RX_DROPPED,
285a9947867SLaurent Vivier     QEMU_IFLA_VF_STATS_TX_DROPPED,
286a9947867SLaurent Vivier     QEMU__IFLA_VF_STATS_MAX,
287a9947867SLaurent Vivier };
288a9947867SLaurent Vivier 
289a9947867SLaurent Vivier enum {
290a9947867SLaurent Vivier     QEMU_IFLA_VF_UNSPEC,
291a9947867SLaurent Vivier     QEMU_IFLA_VF_MAC,
292a9947867SLaurent Vivier     QEMU_IFLA_VF_VLAN,
293a9947867SLaurent Vivier     QEMU_IFLA_VF_TX_RATE,
294a9947867SLaurent Vivier     QEMU_IFLA_VF_SPOOFCHK,
295a9947867SLaurent Vivier     QEMU_IFLA_VF_LINK_STATE,
296a9947867SLaurent Vivier     QEMU_IFLA_VF_RATE,
297a9947867SLaurent Vivier     QEMU_IFLA_VF_RSS_QUERY_EN,
298a9947867SLaurent Vivier     QEMU_IFLA_VF_STATS,
299a9947867SLaurent Vivier     QEMU_IFLA_VF_TRUST,
300a9947867SLaurent Vivier     QEMU_IFLA_VF_IB_NODE_GUID,
301a9947867SLaurent Vivier     QEMU_IFLA_VF_IB_PORT_GUID,
302a9947867SLaurent Vivier     QEMU_IFLA_VF_VLAN_LIST,
303a9947867SLaurent Vivier     QEMU_IFLA_VF_BROADCAST,
304a9947867SLaurent Vivier     QEMU__IFLA_VF_MAX,
305a9947867SLaurent Vivier };
306a9947867SLaurent Vivier 
307f7e6a401SLaurent Vivier TargetFdTrans **target_fd_trans;
308c093364fSOwen Anderson QemuMutex target_fd_trans_lock;
309f7e6a401SLaurent Vivier unsigned int target_fd_max;
310f7e6a401SLaurent Vivier 
tswap_nlmsghdr(struct nlmsghdr * nlh)311f7e6a401SLaurent Vivier static void tswap_nlmsghdr(struct nlmsghdr *nlh)
312f7e6a401SLaurent Vivier {
313f7e6a401SLaurent Vivier     nlh->nlmsg_len = tswap32(nlh->nlmsg_len);
314f7e6a401SLaurent Vivier     nlh->nlmsg_type = tswap16(nlh->nlmsg_type);
315f7e6a401SLaurent Vivier     nlh->nlmsg_flags = tswap16(nlh->nlmsg_flags);
316f7e6a401SLaurent Vivier     nlh->nlmsg_seq = tswap32(nlh->nlmsg_seq);
317f7e6a401SLaurent Vivier     nlh->nlmsg_pid = tswap32(nlh->nlmsg_pid);
318f7e6a401SLaurent Vivier }
319f7e6a401SLaurent Vivier 
host_to_target_for_each_nlmsg(struct nlmsghdr * nlh,size_t len,abi_long (* host_to_target_nlmsg)(struct nlmsghdr *))320f7e6a401SLaurent Vivier static abi_long host_to_target_for_each_nlmsg(struct nlmsghdr *nlh,
321f7e6a401SLaurent Vivier                                               size_t len,
322f7e6a401SLaurent Vivier                                               abi_long (*host_to_target_nlmsg)
323f7e6a401SLaurent Vivier                                                        (struct nlmsghdr *))
324f7e6a401SLaurent Vivier {
325f7e6a401SLaurent Vivier     uint32_t nlmsg_len;
3261645fb5aSShu-Chun Weng     uint32_t aligned_nlmsg_len;
327f7e6a401SLaurent Vivier     abi_long ret;
328f7e6a401SLaurent Vivier 
329f7e6a401SLaurent Vivier     while (len > sizeof(struct nlmsghdr)) {
330f7e6a401SLaurent Vivier 
331f7e6a401SLaurent Vivier         nlmsg_len = nlh->nlmsg_len;
332f7e6a401SLaurent Vivier         if (nlmsg_len < sizeof(struct nlmsghdr) ||
333f7e6a401SLaurent Vivier             nlmsg_len > len) {
334f7e6a401SLaurent Vivier             break;
335f7e6a401SLaurent Vivier         }
336f7e6a401SLaurent Vivier 
337f7e6a401SLaurent Vivier         switch (nlh->nlmsg_type) {
338f7e6a401SLaurent Vivier         case NLMSG_DONE:
339f7e6a401SLaurent Vivier             tswap_nlmsghdr(nlh);
340f7e6a401SLaurent Vivier             return 0;
341f7e6a401SLaurent Vivier         case NLMSG_NOOP:
342f7e6a401SLaurent Vivier             break;
343f7e6a401SLaurent Vivier         case NLMSG_ERROR:
344f7e6a401SLaurent Vivier         {
345f7e6a401SLaurent Vivier             struct nlmsgerr *e = NLMSG_DATA(nlh);
346f7e6a401SLaurent Vivier             e->error = tswap32(e->error);
347f7e6a401SLaurent Vivier             tswap_nlmsghdr(&e->msg);
348f7e6a401SLaurent Vivier             tswap_nlmsghdr(nlh);
349f7e6a401SLaurent Vivier             return 0;
350f7e6a401SLaurent Vivier         }
351f7e6a401SLaurent Vivier         default:
352f7e6a401SLaurent Vivier             ret = host_to_target_nlmsg(nlh);
353f7e6a401SLaurent Vivier             if (ret < 0) {
354f7e6a401SLaurent Vivier                 tswap_nlmsghdr(nlh);
355f7e6a401SLaurent Vivier                 return ret;
356f7e6a401SLaurent Vivier             }
357f7e6a401SLaurent Vivier             break;
358f7e6a401SLaurent Vivier         }
359f7e6a401SLaurent Vivier         tswap_nlmsghdr(nlh);
3601645fb5aSShu-Chun Weng 
3611645fb5aSShu-Chun Weng         aligned_nlmsg_len = NLMSG_ALIGN(nlmsg_len);
3621645fb5aSShu-Chun Weng         if (aligned_nlmsg_len >= len) {
3631645fb5aSShu-Chun Weng             break;
3641645fb5aSShu-Chun Weng         }
3651645fb5aSShu-Chun Weng         len -= aligned_nlmsg_len;
3661645fb5aSShu-Chun Weng         nlh = (struct nlmsghdr *)(((char*)nlh) + aligned_nlmsg_len);
367f7e6a401SLaurent Vivier     }
368f7e6a401SLaurent Vivier     return 0;
369f7e6a401SLaurent Vivier }
370f7e6a401SLaurent Vivier 
target_to_host_for_each_nlmsg(struct nlmsghdr * nlh,size_t len,abi_long (* target_to_host_nlmsg)(struct nlmsghdr *))371f7e6a401SLaurent Vivier static abi_long target_to_host_for_each_nlmsg(struct nlmsghdr *nlh,
372f7e6a401SLaurent Vivier                                               size_t len,
373f7e6a401SLaurent Vivier                                               abi_long (*target_to_host_nlmsg)
374f7e6a401SLaurent Vivier                                                        (struct nlmsghdr *))
375f7e6a401SLaurent Vivier {
3761645fb5aSShu-Chun Weng     uint32_t aligned_nlmsg_len;
377f7e6a401SLaurent Vivier     int ret;
378f7e6a401SLaurent Vivier 
379f7e6a401SLaurent Vivier     while (len > sizeof(struct nlmsghdr)) {
380f7e6a401SLaurent Vivier         if (tswap32(nlh->nlmsg_len) < sizeof(struct nlmsghdr) ||
381f7e6a401SLaurent Vivier             tswap32(nlh->nlmsg_len) > len) {
382f7e6a401SLaurent Vivier             break;
383f7e6a401SLaurent Vivier         }
384f7e6a401SLaurent Vivier         tswap_nlmsghdr(nlh);
385f7e6a401SLaurent Vivier         switch (nlh->nlmsg_type) {
386f7e6a401SLaurent Vivier         case NLMSG_DONE:
387f7e6a401SLaurent Vivier             return 0;
388f7e6a401SLaurent Vivier         case NLMSG_NOOP:
389f7e6a401SLaurent Vivier             break;
390f7e6a401SLaurent Vivier         case NLMSG_ERROR:
391f7e6a401SLaurent Vivier         {
392f7e6a401SLaurent Vivier             struct nlmsgerr *e = NLMSG_DATA(nlh);
393f7e6a401SLaurent Vivier             e->error = tswap32(e->error);
394f7e6a401SLaurent Vivier             tswap_nlmsghdr(&e->msg);
395f7e6a401SLaurent Vivier             return 0;
396f7e6a401SLaurent Vivier         }
397f7e6a401SLaurent Vivier         default:
398f7e6a401SLaurent Vivier             ret = target_to_host_nlmsg(nlh);
399f7e6a401SLaurent Vivier             if (ret < 0) {
400f7e6a401SLaurent Vivier                 return ret;
401f7e6a401SLaurent Vivier             }
402f7e6a401SLaurent Vivier         }
4031645fb5aSShu-Chun Weng 
4041645fb5aSShu-Chun Weng         aligned_nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len);
4051645fb5aSShu-Chun Weng         if (aligned_nlmsg_len >= len) {
4061645fb5aSShu-Chun Weng             break;
4071645fb5aSShu-Chun Weng         }
4081645fb5aSShu-Chun Weng         len -= aligned_nlmsg_len;
4091645fb5aSShu-Chun Weng         nlh = (struct nlmsghdr *)(((char *)nlh) + aligned_nlmsg_len);
410f7e6a401SLaurent Vivier     }
411f7e6a401SLaurent Vivier     return 0;
412f7e6a401SLaurent Vivier }
413f7e6a401SLaurent Vivier 
414f7e6a401SLaurent Vivier #ifdef CONFIG_RTNETLINK
host_to_target_for_each_nlattr(struct nlattr * nlattr,size_t len,void * context,abi_long (* host_to_target_nlattr)(struct nlattr *,void * context))415f7e6a401SLaurent Vivier static abi_long host_to_target_for_each_nlattr(struct nlattr *nlattr,
416f7e6a401SLaurent Vivier                                                size_t len, void *context,
417f7e6a401SLaurent Vivier                                                abi_long (*host_to_target_nlattr)
418f7e6a401SLaurent Vivier                                                         (struct nlattr *,
419f7e6a401SLaurent Vivier                                                          void *context))
420f7e6a401SLaurent Vivier {
421f7e6a401SLaurent Vivier     unsigned short nla_len;
4221645fb5aSShu-Chun Weng     unsigned short aligned_nla_len;
423f7e6a401SLaurent Vivier     abi_long ret;
424f7e6a401SLaurent Vivier 
425f7e6a401SLaurent Vivier     while (len > sizeof(struct nlattr)) {
426f7e6a401SLaurent Vivier         nla_len = nlattr->nla_len;
427f7e6a401SLaurent Vivier         if (nla_len < sizeof(struct nlattr) ||
428f7e6a401SLaurent Vivier             nla_len > len) {
429f7e6a401SLaurent Vivier             break;
430f7e6a401SLaurent Vivier         }
431f7e6a401SLaurent Vivier         ret = host_to_target_nlattr(nlattr, context);
432f7e6a401SLaurent Vivier         nlattr->nla_len = tswap16(nlattr->nla_len);
433f7e6a401SLaurent Vivier         nlattr->nla_type = tswap16(nlattr->nla_type);
434f7e6a401SLaurent Vivier         if (ret < 0) {
435f7e6a401SLaurent Vivier             return ret;
436f7e6a401SLaurent Vivier         }
4371645fb5aSShu-Chun Weng 
4381645fb5aSShu-Chun Weng         aligned_nla_len = NLA_ALIGN(nla_len);
4391645fb5aSShu-Chun Weng         if (aligned_nla_len >= len) {
4401645fb5aSShu-Chun Weng             break;
4411645fb5aSShu-Chun Weng         }
4421645fb5aSShu-Chun Weng         len -= aligned_nla_len;
4431645fb5aSShu-Chun Weng         nlattr = (struct nlattr *)(((char *)nlattr) + aligned_nla_len);
444f7e6a401SLaurent Vivier     }
445f7e6a401SLaurent Vivier     return 0;
446f7e6a401SLaurent Vivier }
447f7e6a401SLaurent Vivier 
host_to_target_for_each_rtattr(struct rtattr * rtattr,size_t len,abi_long (* host_to_target_rtattr)(struct rtattr *))448f7e6a401SLaurent Vivier static abi_long host_to_target_for_each_rtattr(struct rtattr *rtattr,
449f7e6a401SLaurent Vivier                                                size_t len,
450f7e6a401SLaurent Vivier                                                abi_long (*host_to_target_rtattr)
451f7e6a401SLaurent Vivier                                                         (struct rtattr *))
452f7e6a401SLaurent Vivier {
453f7e6a401SLaurent Vivier     unsigned short rta_len;
4541645fb5aSShu-Chun Weng     unsigned short aligned_rta_len;
455f7e6a401SLaurent Vivier     abi_long ret;
456f7e6a401SLaurent Vivier 
457f7e6a401SLaurent Vivier     while (len > sizeof(struct rtattr)) {
458f7e6a401SLaurent Vivier         rta_len = rtattr->rta_len;
459f7e6a401SLaurent Vivier         if (rta_len < sizeof(struct rtattr) ||
460f7e6a401SLaurent Vivier             rta_len > len) {
461f7e6a401SLaurent Vivier             break;
462f7e6a401SLaurent Vivier         }
463f7e6a401SLaurent Vivier         ret = host_to_target_rtattr(rtattr);
464f7e6a401SLaurent Vivier         rtattr->rta_len = tswap16(rtattr->rta_len);
465f7e6a401SLaurent Vivier         rtattr->rta_type = tswap16(rtattr->rta_type);
466f7e6a401SLaurent Vivier         if (ret < 0) {
467f7e6a401SLaurent Vivier             return ret;
468f7e6a401SLaurent Vivier         }
4691645fb5aSShu-Chun Weng 
4701645fb5aSShu-Chun Weng         aligned_rta_len = RTA_ALIGN(rta_len);
4711645fb5aSShu-Chun Weng         if (aligned_rta_len >= len) {
4721645fb5aSShu-Chun Weng             break;
4731645fb5aSShu-Chun Weng         }
4741645fb5aSShu-Chun Weng         len -= aligned_rta_len;
4751645fb5aSShu-Chun Weng         rtattr = (struct rtattr *)(((char *)rtattr) + aligned_rta_len);
476f7e6a401SLaurent Vivier     }
477f7e6a401SLaurent Vivier     return 0;
478f7e6a401SLaurent Vivier }
479f7e6a401SLaurent Vivier 
480f7e6a401SLaurent Vivier #define NLA_DATA(nla) ((void *)((char *)(nla)) + NLA_HDRLEN)
481f7e6a401SLaurent Vivier 
host_to_target_data_bridge_nlattr(struct nlattr * nlattr,void * context)482f7e6a401SLaurent Vivier static abi_long host_to_target_data_bridge_nlattr(struct nlattr *nlattr,
483f7e6a401SLaurent Vivier                                                   void *context)
484f7e6a401SLaurent Vivier {
485f7e6a401SLaurent Vivier     uint16_t *u16;
486f7e6a401SLaurent Vivier     uint32_t *u32;
487f7e6a401SLaurent Vivier     uint64_t *u64;
488f7e6a401SLaurent Vivier 
489f7e6a401SLaurent Vivier     switch (nlattr->nla_type) {
490f7e6a401SLaurent Vivier     /* no data */
491f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_FDB_FLUSH:
492f7e6a401SLaurent Vivier         break;
493f7e6a401SLaurent Vivier     /* binary */
494f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_GROUP_ADDR:
495f7e6a401SLaurent Vivier         break;
496f7e6a401SLaurent Vivier     /* uint8_t */
497f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_VLAN_FILTERING:
498f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_TOPOLOGY_CHANGE:
499f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_TOPOLOGY_CHANGE_DETECTED:
500f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_ROUTER:
501f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_SNOOPING:
502f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_QUERY_USE_IFADDR:
503f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_QUERIER:
504f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_NF_CALL_IPTABLES:
505f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_NF_CALL_IP6TABLES:
506f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_NF_CALL_ARPTABLES:
507f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_VLAN_STATS_ENABLED:
508f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_STATS_ENABLED:
509f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_IGMP_VERSION:
510f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_MLD_VERSION:
51161b463fbSLaurent Vivier     case QEMU_IFLA_BR_VLAN_STATS_PER_PORT:
512f7e6a401SLaurent Vivier         break;
513f7e6a401SLaurent Vivier     /* uint16_t */
514f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_PRIORITY:
515f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_VLAN_PROTOCOL:
516f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_GROUP_FWD_MASK:
517f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_ROOT_PORT:
518f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_VLAN_DEFAULT_PVID:
519f7e6a401SLaurent Vivier         u16 = NLA_DATA(nlattr);
520f7e6a401SLaurent Vivier         *u16 = tswap16(*u16);
521f7e6a401SLaurent Vivier         break;
522f7e6a401SLaurent Vivier     /* uint32_t */
523f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_FORWARD_DELAY:
524f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_HELLO_TIME:
525f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MAX_AGE:
526f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_AGEING_TIME:
527f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_STP_STATE:
528f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_ROOT_PATH_COST:
529f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_HASH_ELASTICITY:
530f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_HASH_MAX:
531f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_LAST_MEMBER_CNT:
532f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_STARTUP_QUERY_CNT:
533f7e6a401SLaurent Vivier         u32 = NLA_DATA(nlattr);
534f7e6a401SLaurent Vivier         *u32 = tswap32(*u32);
535f7e6a401SLaurent Vivier         break;
536f7e6a401SLaurent Vivier     /* uint64_t */
537f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_HELLO_TIMER:
538f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_TCN_TIMER:
539f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_GC_TIMER:
540f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_TOPOLOGY_CHANGE_TIMER:
541f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_LAST_MEMBER_INTVL:
542f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_MEMBERSHIP_INTVL:
543f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_QUERIER_INTVL:
544f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_QUERY_INTVL:
545f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_QUERY_RESPONSE_INTVL:
546f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_MCAST_STARTUP_QUERY_INTVL:
547f7e6a401SLaurent Vivier         u64 = NLA_DATA(nlattr);
548f7e6a401SLaurent Vivier         *u64 = tswap64(*u64);
549f7e6a401SLaurent Vivier         break;
550f7e6a401SLaurent Vivier     /* ifla_bridge_id: uin8_t[] */
551f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_ROOT_ID:
552f7e6a401SLaurent Vivier     case QEMU_IFLA_BR_BRIDGE_ID:
553f7e6a401SLaurent Vivier         break;
55401154f79SLaurent Vivier     /* br_boolopt_multi { uint32_t, uint32_t } */
55501154f79SLaurent Vivier     case QEMU_IFLA_BR_MULTI_BOOLOPT:
55601154f79SLaurent Vivier         u32 = NLA_DATA(nlattr);
55701154f79SLaurent Vivier         u32[0] = tswap32(u32[0]); /* optval */
55801154f79SLaurent Vivier         u32[1] = tswap32(u32[1]); /* optmask */
55901154f79SLaurent Vivier         break;
560f7e6a401SLaurent Vivier     default:
56139be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown QEMU_IFLA_BR type %d\n",
56239be5350SJosh Kunz                       nlattr->nla_type);
563f7e6a401SLaurent Vivier         break;
564f7e6a401SLaurent Vivier     }
565f7e6a401SLaurent Vivier     return 0;
566f7e6a401SLaurent Vivier }
567f7e6a401SLaurent Vivier 
host_to_target_slave_data_bridge_nlattr(struct nlattr * nlattr,void * context)568f7e6a401SLaurent Vivier static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr,
569f7e6a401SLaurent Vivier                                                         void *context)
570f7e6a401SLaurent Vivier {
571f7e6a401SLaurent Vivier     uint16_t *u16;
572f7e6a401SLaurent Vivier     uint32_t *u32;
573f7e6a401SLaurent Vivier     uint64_t *u64;
574f7e6a401SLaurent Vivier 
575f7e6a401SLaurent Vivier     switch (nlattr->nla_type) {
576f7e6a401SLaurent Vivier     /* uint8_t */
577f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_STATE:
578f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_MODE:
579f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_GUARD:
580f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_PROTECT:
581f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_FAST_LEAVE:
582f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_LEARNING:
583f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_UNICAST_FLOOD:
584f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_PROXYARP:
585f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_LEARNING_SYNC:
586f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_PROXYARP_WIFI:
587f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_TOPOLOGY_CHANGE_ACK:
588f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_CONFIG_PENDING:
589f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_MULTICAST_ROUTER:
590f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_MCAST_FLOOD:
591f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_MCAST_TO_UCAST:
592f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_VLAN_TUNNEL:
593f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_BCAST_FLOOD:
594f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_NEIGH_SUPPRESS:
5950f5faca7SLaurent Vivier     case QEMU_IFLA_BRPORT_ISOLATED:
5965351f407SLaurent Vivier     case QEMU_IFLA_BRPORT_MRP_RING_OPEN:
5975351f407SLaurent Vivier     case QEMU_IFLA_BRPORT_MRP_IN_OPEN:
598f7e6a401SLaurent Vivier         break;
599f7e6a401SLaurent Vivier     /* uint16_t */
600f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_PRIORITY:
601f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_DESIGNATED_PORT:
602f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_DESIGNATED_COST:
603f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_ID:
604f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_NO:
605f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_GROUP_FWD_MASK:
606f7e6a401SLaurent Vivier         u16 = NLA_DATA(nlattr);
607f7e6a401SLaurent Vivier         *u16 = tswap16(*u16);
608f7e6a401SLaurent Vivier         break;
609f7e6a401SLaurent Vivier     /* uin32_t */
610f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_COST:
6110f5faca7SLaurent Vivier     case QEMU_IFLA_BRPORT_BACKUP_PORT:
612f0effdbcSLaurent Vivier     case QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT:
613f0effdbcSLaurent Vivier     case QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_CNT:
614f7e6a401SLaurent Vivier         u32 = NLA_DATA(nlattr);
615f7e6a401SLaurent Vivier         *u32 = tswap32(*u32);
616f7e6a401SLaurent Vivier         break;
617f7e6a401SLaurent Vivier     /* uint64_t */
618f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_MESSAGE_AGE_TIMER:
619f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_FORWARD_DELAY_TIMER:
620f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_HOLD_TIMER:
621f7e6a401SLaurent Vivier         u64 = NLA_DATA(nlattr);
622f7e6a401SLaurent Vivier         *u64 = tswap64(*u64);
623f7e6a401SLaurent Vivier         break;
624f7e6a401SLaurent Vivier     /* ifla_bridge_id: uint8_t[] */
625f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_ROOT_ID:
626f7e6a401SLaurent Vivier     case QEMU_IFLA_BRPORT_BRIDGE_ID:
627f7e6a401SLaurent Vivier         break;
628f7e6a401SLaurent Vivier     default:
62939be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown QEMU_IFLA_BRPORT type %d\n",
63039be5350SJosh Kunz                       nlattr->nla_type);
631f7e6a401SLaurent Vivier         break;
632f7e6a401SLaurent Vivier     }
633f7e6a401SLaurent Vivier     return 0;
634f7e6a401SLaurent Vivier }
635f7e6a401SLaurent Vivier 
host_to_target_data_tun_nlattr(struct nlattr * nlattr,void * context)636f7e6a401SLaurent Vivier static abi_long host_to_target_data_tun_nlattr(struct nlattr *nlattr,
637f7e6a401SLaurent Vivier                                                   void *context)
638f7e6a401SLaurent Vivier {
639f7e6a401SLaurent Vivier     uint32_t *u32;
640f7e6a401SLaurent Vivier 
641f7e6a401SLaurent Vivier     switch (nlattr->nla_type) {
642f7e6a401SLaurent Vivier     /* uint8_t */
643f7e6a401SLaurent Vivier     case QEMU_IFLA_TUN_TYPE:
644f7e6a401SLaurent Vivier     case QEMU_IFLA_TUN_PI:
645f7e6a401SLaurent Vivier     case QEMU_IFLA_TUN_VNET_HDR:
646f7e6a401SLaurent Vivier     case QEMU_IFLA_TUN_PERSIST:
647f7e6a401SLaurent Vivier     case QEMU_IFLA_TUN_MULTI_QUEUE:
648f7e6a401SLaurent Vivier         break;
649f7e6a401SLaurent Vivier     /* uint32_t */
650f7e6a401SLaurent Vivier     case QEMU_IFLA_TUN_NUM_QUEUES:
651f7e6a401SLaurent Vivier     case QEMU_IFLA_TUN_NUM_DISABLED_QUEUES:
652f7e6a401SLaurent Vivier     case QEMU_IFLA_TUN_OWNER:
653f7e6a401SLaurent Vivier     case QEMU_IFLA_TUN_GROUP:
654f7e6a401SLaurent Vivier         u32 = NLA_DATA(nlattr);
655f7e6a401SLaurent Vivier         *u32 = tswap32(*u32);
656f7e6a401SLaurent Vivier         break;
657f7e6a401SLaurent Vivier     default:
65839be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown QEMU_IFLA_TUN type %d\n",
65939be5350SJosh Kunz                       nlattr->nla_type);
660f7e6a401SLaurent Vivier         break;
661f7e6a401SLaurent Vivier     }
662f7e6a401SLaurent Vivier     return 0;
663f7e6a401SLaurent Vivier }
664f7e6a401SLaurent Vivier 
665f7e6a401SLaurent Vivier struct linkinfo_context {
666f7e6a401SLaurent Vivier     int len;
667f7e6a401SLaurent Vivier     char *name;
668f7e6a401SLaurent Vivier     int slave_len;
669f7e6a401SLaurent Vivier     char *slave_name;
670f7e6a401SLaurent Vivier };
671f7e6a401SLaurent Vivier 
host_to_target_data_linkinfo_nlattr(struct nlattr * nlattr,void * context)672f7e6a401SLaurent Vivier static abi_long host_to_target_data_linkinfo_nlattr(struct nlattr *nlattr,
673f7e6a401SLaurent Vivier                                                     void *context)
674f7e6a401SLaurent Vivier {
675f7e6a401SLaurent Vivier     struct linkinfo_context *li_context = context;
676f7e6a401SLaurent Vivier 
677f7e6a401SLaurent Vivier     switch (nlattr->nla_type) {
678f7e6a401SLaurent Vivier     /* string */
679f7e6a401SLaurent Vivier     case QEMU_IFLA_INFO_KIND:
680f7e6a401SLaurent Vivier         li_context->name = NLA_DATA(nlattr);
681f7e6a401SLaurent Vivier         li_context->len = nlattr->nla_len - NLA_HDRLEN;
682f7e6a401SLaurent Vivier         break;
683f7e6a401SLaurent Vivier     case QEMU_IFLA_INFO_SLAVE_KIND:
684f7e6a401SLaurent Vivier         li_context->slave_name = NLA_DATA(nlattr);
685f7e6a401SLaurent Vivier         li_context->slave_len = nlattr->nla_len - NLA_HDRLEN;
686f7e6a401SLaurent Vivier         break;
687f7e6a401SLaurent Vivier     /* stats */
688f7e6a401SLaurent Vivier     case QEMU_IFLA_INFO_XSTATS:
689f7e6a401SLaurent Vivier         /* FIXME: only used by CAN */
690f7e6a401SLaurent Vivier         break;
691f7e6a401SLaurent Vivier     /* nested */
692f7e6a401SLaurent Vivier     case QEMU_IFLA_INFO_DATA:
693f7e6a401SLaurent Vivier         if (strncmp(li_context->name, "bridge",
694f7e6a401SLaurent Vivier                     li_context->len) == 0) {
695f7e6a401SLaurent Vivier             return host_to_target_for_each_nlattr(NLA_DATA(nlattr),
696f7e6a401SLaurent Vivier                                                   nlattr->nla_len,
697f7e6a401SLaurent Vivier                                                   NULL,
698f7e6a401SLaurent Vivier                                              host_to_target_data_bridge_nlattr);
699f7e6a401SLaurent Vivier         } else if (strncmp(li_context->name, "tun",
700f7e6a401SLaurent Vivier                     li_context->len) == 0) {
701f7e6a401SLaurent Vivier             return host_to_target_for_each_nlattr(NLA_DATA(nlattr),
702f7e6a401SLaurent Vivier                                                   nlattr->nla_len,
703f7e6a401SLaurent Vivier                                                   NULL,
704f7e6a401SLaurent Vivier                                                 host_to_target_data_tun_nlattr);
705f7e6a401SLaurent Vivier         } else {
70639be5350SJosh Kunz             qemu_log_mask(LOG_UNIMP, "Unknown QEMU_IFLA_INFO_KIND %s\n",
70739be5350SJosh Kunz                           li_context->name);
708f7e6a401SLaurent Vivier         }
709f7e6a401SLaurent Vivier         break;
710f7e6a401SLaurent Vivier     case QEMU_IFLA_INFO_SLAVE_DATA:
711f7e6a401SLaurent Vivier         if (strncmp(li_context->slave_name, "bridge",
712f7e6a401SLaurent Vivier                     li_context->slave_len) == 0) {
713f7e6a401SLaurent Vivier             return host_to_target_for_each_nlattr(NLA_DATA(nlattr),
714f7e6a401SLaurent Vivier                                                   nlattr->nla_len,
715f7e6a401SLaurent Vivier                                                   NULL,
716f7e6a401SLaurent Vivier                                        host_to_target_slave_data_bridge_nlattr);
717f7e6a401SLaurent Vivier         } else {
71839be5350SJosh Kunz             qemu_log_mask(LOG_UNIMP, "Unknown QEMU_IFLA_INFO_SLAVE_KIND %s\n",
719f7e6a401SLaurent Vivier                      li_context->slave_name);
720f7e6a401SLaurent Vivier         }
721f7e6a401SLaurent Vivier         break;
722f7e6a401SLaurent Vivier     default:
72339be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA_INFO type: %d\n",
72439be5350SJosh Kunz                       nlattr->nla_type);
725f7e6a401SLaurent Vivier         break;
726f7e6a401SLaurent Vivier     }
727f7e6a401SLaurent Vivier 
728f7e6a401SLaurent Vivier     return 0;
729f7e6a401SLaurent Vivier }
730f7e6a401SLaurent Vivier 
host_to_target_data_inet_nlattr(struct nlattr * nlattr,void * context)731f7e6a401SLaurent Vivier static abi_long host_to_target_data_inet_nlattr(struct nlattr *nlattr,
732f7e6a401SLaurent Vivier                                                 void *context)
733f7e6a401SLaurent Vivier {
734f7e6a401SLaurent Vivier     uint32_t *u32;
735f7e6a401SLaurent Vivier     int i;
736f7e6a401SLaurent Vivier 
737f7e6a401SLaurent Vivier     switch (nlattr->nla_type) {
738f7e6a401SLaurent Vivier     case QEMU_IFLA_INET_CONF:
739f7e6a401SLaurent Vivier         u32 = NLA_DATA(nlattr);
740f7e6a401SLaurent Vivier         for (i = 0; i < (nlattr->nla_len - NLA_HDRLEN) / sizeof(*u32);
741f7e6a401SLaurent Vivier              i++) {
742f7e6a401SLaurent Vivier             u32[i] = tswap32(u32[i]);
743f7e6a401SLaurent Vivier         }
744f7e6a401SLaurent Vivier         break;
745f7e6a401SLaurent Vivier     default:
74639be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown host AF_INET type: %d\n",
74739be5350SJosh Kunz                       nlattr->nla_type);
748f7e6a401SLaurent Vivier     }
749f7e6a401SLaurent Vivier     return 0;
750f7e6a401SLaurent Vivier }
751f7e6a401SLaurent Vivier 
host_to_target_data_inet6_nlattr(struct nlattr * nlattr,void * context)752f7e6a401SLaurent Vivier static abi_long host_to_target_data_inet6_nlattr(struct nlattr *nlattr,
753f7e6a401SLaurent Vivier                                                 void *context)
754f7e6a401SLaurent Vivier {
755f7e6a401SLaurent Vivier     uint32_t *u32;
756f7e6a401SLaurent Vivier     uint64_t *u64;
757f7e6a401SLaurent Vivier     struct ifla_cacheinfo *ci;
758f7e6a401SLaurent Vivier     int i;
759f7e6a401SLaurent Vivier 
760f7e6a401SLaurent Vivier     switch (nlattr->nla_type) {
761f7e6a401SLaurent Vivier     /* binaries */
762f7e6a401SLaurent Vivier     case QEMU_IFLA_INET6_TOKEN:
763f7e6a401SLaurent Vivier         break;
764f7e6a401SLaurent Vivier     /* uint8_t */
765f7e6a401SLaurent Vivier     case QEMU_IFLA_INET6_ADDR_GEN_MODE:
766f7e6a401SLaurent Vivier         break;
767f7e6a401SLaurent Vivier     /* uint32_t */
768f7e6a401SLaurent Vivier     case QEMU_IFLA_INET6_FLAGS:
769f7e6a401SLaurent Vivier         u32 = NLA_DATA(nlattr);
770f7e6a401SLaurent Vivier         *u32 = tswap32(*u32);
771f7e6a401SLaurent Vivier         break;
772f7e6a401SLaurent Vivier     /* uint32_t[] */
773f7e6a401SLaurent Vivier     case QEMU_IFLA_INET6_CONF:
774f7e6a401SLaurent Vivier         u32 = NLA_DATA(nlattr);
775f7e6a401SLaurent Vivier         for (i = 0; i < (nlattr->nla_len - NLA_HDRLEN) / sizeof(*u32);
776f7e6a401SLaurent Vivier              i++) {
777f7e6a401SLaurent Vivier             u32[i] = tswap32(u32[i]);
778f7e6a401SLaurent Vivier         }
779f7e6a401SLaurent Vivier         break;
780f7e6a401SLaurent Vivier     /* ifla_cacheinfo */
781f7e6a401SLaurent Vivier     case QEMU_IFLA_INET6_CACHEINFO:
782f7e6a401SLaurent Vivier         ci = NLA_DATA(nlattr);
783f7e6a401SLaurent Vivier         ci->max_reasm_len = tswap32(ci->max_reasm_len);
784f7e6a401SLaurent Vivier         ci->tstamp = tswap32(ci->tstamp);
785f7e6a401SLaurent Vivier         ci->reachable_time = tswap32(ci->reachable_time);
786f7e6a401SLaurent Vivier         ci->retrans_time = tswap32(ci->retrans_time);
787f7e6a401SLaurent Vivier         break;
788f7e6a401SLaurent Vivier     /* uint64_t[] */
789f7e6a401SLaurent Vivier     case QEMU_IFLA_INET6_STATS:
790f7e6a401SLaurent Vivier     case QEMU_IFLA_INET6_ICMP6STATS:
791f7e6a401SLaurent Vivier         u64 = NLA_DATA(nlattr);
792f7e6a401SLaurent Vivier         for (i = 0; i < (nlattr->nla_len - NLA_HDRLEN) / sizeof(*u64);
793f7e6a401SLaurent Vivier              i++) {
794f7e6a401SLaurent Vivier             u64[i] = tswap64(u64[i]);
795f7e6a401SLaurent Vivier         }
796f7e6a401SLaurent Vivier         break;
797f7e6a401SLaurent Vivier     default:
79839be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown host AF_INET6 type: %d\n",
79939be5350SJosh Kunz                       nlattr->nla_type);
800f7e6a401SLaurent Vivier     }
801f7e6a401SLaurent Vivier     return 0;
802f7e6a401SLaurent Vivier }
803f7e6a401SLaurent Vivier 
host_to_target_data_spec_nlattr(struct nlattr * nlattr,void * context)804f7e6a401SLaurent Vivier static abi_long host_to_target_data_spec_nlattr(struct nlattr *nlattr,
805f7e6a401SLaurent Vivier                                                     void *context)
806f7e6a401SLaurent Vivier {
807f7e6a401SLaurent Vivier     switch (nlattr->nla_type) {
808f7e6a401SLaurent Vivier     case AF_INET:
809f7e6a401SLaurent Vivier         return host_to_target_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len,
810f7e6a401SLaurent Vivier                                               NULL,
811f7e6a401SLaurent Vivier                                              host_to_target_data_inet_nlattr);
812f7e6a401SLaurent Vivier     case AF_INET6:
813f7e6a401SLaurent Vivier         return host_to_target_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len,
814f7e6a401SLaurent Vivier                                               NULL,
815f7e6a401SLaurent Vivier                                              host_to_target_data_inet6_nlattr);
816f7e6a401SLaurent Vivier     default:
81739be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown host AF_SPEC type: %d\n",
81839be5350SJosh Kunz                       nlattr->nla_type);
819f7e6a401SLaurent Vivier         break;
820f7e6a401SLaurent Vivier     }
821f7e6a401SLaurent Vivier     return 0;
822f7e6a401SLaurent Vivier }
823f7e6a401SLaurent Vivier 
host_to_target_data_xdp_nlattr(struct nlattr * nlattr,void * context)824f7e6a401SLaurent Vivier static abi_long host_to_target_data_xdp_nlattr(struct nlattr *nlattr,
825f7e6a401SLaurent Vivier                                                void *context)
826f7e6a401SLaurent Vivier {
827f7e6a401SLaurent Vivier     uint32_t *u32;
828f7e6a401SLaurent Vivier 
829f7e6a401SLaurent Vivier     switch (nlattr->nla_type) {
830f7e6a401SLaurent Vivier     /* uint8_t */
831f7e6a401SLaurent Vivier     case QEMU_IFLA_XDP_ATTACHED:
832f7e6a401SLaurent Vivier         break;
833f7e6a401SLaurent Vivier     /* uint32_t */
834f7e6a401SLaurent Vivier     case QEMU_IFLA_XDP_PROG_ID:
835f7e6a401SLaurent Vivier         u32 = NLA_DATA(nlattr);
836f7e6a401SLaurent Vivier         *u32 = tswap32(*u32);
837f7e6a401SLaurent Vivier         break;
838f7e6a401SLaurent Vivier     default:
83939be5350SJosh Kunz         qemu_log_mask(
84039be5350SJosh Kunz             LOG_UNIMP, "Unknown host XDP type: %d\n", nlattr->nla_type);
841f7e6a401SLaurent Vivier         break;
842f7e6a401SLaurent Vivier     }
843f7e6a401SLaurent Vivier     return 0;
844f7e6a401SLaurent Vivier }
845f7e6a401SLaurent Vivier 
host_to_target_data_vlan_list_nlattr(struct nlattr * nlattr,void * context)846a9947867SLaurent Vivier static abi_long host_to_target_data_vlan_list_nlattr(struct nlattr *nlattr,
847a9947867SLaurent Vivier                                                      void *context)
848a9947867SLaurent Vivier {
849a9947867SLaurent Vivier     struct ifla_vf_vlan_info *vlan_info;
850a9947867SLaurent Vivier 
851a9947867SLaurent Vivier     switch (nlattr->nla_type) {
852a9947867SLaurent Vivier     /* struct ifla_vf_vlan_info */
853a9947867SLaurent Vivier     case IFLA_VF_VLAN_INFO:
854a9947867SLaurent Vivier         vlan_info = NLA_DATA(nlattr);
855a9947867SLaurent Vivier         vlan_info->vf = tswap32(vlan_info->vf);
856a9947867SLaurent Vivier         vlan_info->vlan = tswap32(vlan_info->vlan);
857a9947867SLaurent Vivier         vlan_info->qos = tswap32(vlan_info->qos);
858a9947867SLaurent Vivier         break;
859a9947867SLaurent Vivier     default:
860a9947867SLaurent Vivier         qemu_log_mask(LOG_UNIMP, "Unknown host VLAN LIST type: %d\n",
861a9947867SLaurent Vivier                       nlattr->nla_type);
862a9947867SLaurent Vivier         break;
863a9947867SLaurent Vivier     }
864a9947867SLaurent Vivier     return 0;
865a9947867SLaurent Vivier }
866a9947867SLaurent Vivier 
host_to_target_data_vf_stats_nlattr(struct nlattr * nlattr,void * context)867a9947867SLaurent Vivier static abi_long host_to_target_data_vf_stats_nlattr(struct nlattr *nlattr,
868a9947867SLaurent Vivier                                                     void *context)
869a9947867SLaurent Vivier {
870a9947867SLaurent Vivier     uint64_t *u64;
871a9947867SLaurent Vivier 
872a9947867SLaurent Vivier     switch (nlattr->nla_type) {
873a9947867SLaurent Vivier     /* uint64_t */
874a9947867SLaurent Vivier     case QEMU_IFLA_VF_STATS_RX_PACKETS:
875a9947867SLaurent Vivier     case QEMU_IFLA_VF_STATS_TX_PACKETS:
876a9947867SLaurent Vivier     case QEMU_IFLA_VF_STATS_RX_BYTES:
877a9947867SLaurent Vivier     case QEMU_IFLA_VF_STATS_TX_BYTES:
878a9947867SLaurent Vivier     case QEMU_IFLA_VF_STATS_BROADCAST:
879a9947867SLaurent Vivier     case QEMU_IFLA_VF_STATS_MULTICAST:
880a9947867SLaurent Vivier     case QEMU_IFLA_VF_STATS_PAD:
881a9947867SLaurent Vivier     case QEMU_IFLA_VF_STATS_RX_DROPPED:
882a9947867SLaurent Vivier     case QEMU_IFLA_VF_STATS_TX_DROPPED:
883a9947867SLaurent Vivier         u64 = NLA_DATA(nlattr);
884a9947867SLaurent Vivier         *u64 = tswap64(*u64);
885a9947867SLaurent Vivier         break;
886a9947867SLaurent Vivier     default:
887a9947867SLaurent Vivier         qemu_log_mask(LOG_UNIMP, "Unknown host VF STATS type: %d\n",
888a9947867SLaurent Vivier                       nlattr->nla_type);
889a9947867SLaurent Vivier         break;
890a9947867SLaurent Vivier     }
891a9947867SLaurent Vivier     return 0;
892a9947867SLaurent Vivier }
893a9947867SLaurent Vivier 
host_to_target_data_vfinfo_nlattr(struct nlattr * nlattr,void * context)894a9947867SLaurent Vivier static abi_long host_to_target_data_vfinfo_nlattr(struct nlattr *nlattr,
895a9947867SLaurent Vivier                                                   void *context)
896a9947867SLaurent Vivier {
897a9947867SLaurent Vivier     struct ifla_vf_mac *mac;
898a9947867SLaurent Vivier     struct ifla_vf_vlan *vlan;
899a9947867SLaurent Vivier     struct ifla_vf_vlan_info *vlan_info;
900a9947867SLaurent Vivier     struct ifla_vf_spoofchk *spoofchk;
901a9947867SLaurent Vivier     struct ifla_vf_rate *rate;
902a9947867SLaurent Vivier     struct ifla_vf_link_state *link_state;
903a9947867SLaurent Vivier     struct ifla_vf_rss_query_en *rss_query_en;
904a9947867SLaurent Vivier     struct ifla_vf_trust *trust;
905a9947867SLaurent Vivier     struct ifla_vf_guid *guid;
906a9947867SLaurent Vivier 
907a9947867SLaurent Vivier     switch (nlattr->nla_type) {
908a9947867SLaurent Vivier     /* struct ifla_vf_mac */
909a9947867SLaurent Vivier     case QEMU_IFLA_VF_MAC:
910a9947867SLaurent Vivier         mac = NLA_DATA(nlattr);
911a9947867SLaurent Vivier         mac->vf = tswap32(mac->vf);
912a9947867SLaurent Vivier         break;
913a9947867SLaurent Vivier     /* struct ifla_vf_broadcast */
914a9947867SLaurent Vivier     case QEMU_IFLA_VF_BROADCAST:
915a9947867SLaurent Vivier         break;
916a9947867SLaurent Vivier     /* struct struct ifla_vf_vlan */
917a9947867SLaurent Vivier     case QEMU_IFLA_VF_VLAN:
918a9947867SLaurent Vivier         vlan = NLA_DATA(nlattr);
919a9947867SLaurent Vivier         vlan->vf = tswap32(vlan->vf);
920a9947867SLaurent Vivier         vlan->vlan = tswap32(vlan->vlan);
921a9947867SLaurent Vivier         vlan->qos = tswap32(vlan->qos);
922a9947867SLaurent Vivier         break;
923a9947867SLaurent Vivier     /* struct ifla_vf_vlan_info */
924a9947867SLaurent Vivier     case QEMU_IFLA_VF_TX_RATE:
925a9947867SLaurent Vivier         vlan_info = NLA_DATA(nlattr);
926a9947867SLaurent Vivier         vlan_info->vf = tswap32(vlan_info->vf);
927a9947867SLaurent Vivier         vlan_info->vlan = tswap32(vlan_info->vlan);
928a9947867SLaurent Vivier         vlan_info->qos = tswap32(vlan_info->qos);
929a9947867SLaurent Vivier         break;
930a9947867SLaurent Vivier     /* struct ifla_vf_spoofchk */
931a9947867SLaurent Vivier     case QEMU_IFLA_VF_SPOOFCHK:
932a9947867SLaurent Vivier         spoofchk = NLA_DATA(nlattr);
933a9947867SLaurent Vivier         spoofchk->vf = tswap32(spoofchk->vf);
934a9947867SLaurent Vivier         spoofchk->setting = tswap32(spoofchk->setting);
935a9947867SLaurent Vivier         break;
936a9947867SLaurent Vivier     /* struct ifla_vf_rate */
937a9947867SLaurent Vivier     case QEMU_IFLA_VF_RATE:
938a9947867SLaurent Vivier         rate = NLA_DATA(nlattr);
939a9947867SLaurent Vivier         rate->vf = tswap32(rate->vf);
940a9947867SLaurent Vivier         rate->min_tx_rate = tswap32(rate->min_tx_rate);
941a9947867SLaurent Vivier         rate->max_tx_rate = tswap32(rate->max_tx_rate);
942a9947867SLaurent Vivier         break;
943a9947867SLaurent Vivier     /* struct ifla_vf_link_state */
944a9947867SLaurent Vivier     case QEMU_IFLA_VF_LINK_STATE:
945a9947867SLaurent Vivier         link_state = NLA_DATA(nlattr);
946a9947867SLaurent Vivier         link_state->vf = tswap32(link_state->vf);
947a9947867SLaurent Vivier         link_state->link_state = tswap32(link_state->link_state);
948a9947867SLaurent Vivier         break;
949a9947867SLaurent Vivier     /* struct ifla_vf_rss_query_en */
950a9947867SLaurent Vivier     case QEMU_IFLA_VF_RSS_QUERY_EN:
951a9947867SLaurent Vivier         rss_query_en = NLA_DATA(nlattr);
952a9947867SLaurent Vivier         rss_query_en->vf = tswap32(rss_query_en->vf);
953a9947867SLaurent Vivier         rss_query_en->setting = tswap32(rss_query_en->setting);
954a9947867SLaurent Vivier         break;
955a9947867SLaurent Vivier     /* struct ifla_vf_trust */
956a9947867SLaurent Vivier     case QEMU_IFLA_VF_TRUST:
957a9947867SLaurent Vivier         trust = NLA_DATA(nlattr);
958a9947867SLaurent Vivier         trust->vf = tswap32(trust->vf);
959a9947867SLaurent Vivier         trust->setting = tswap32(trust->setting);
960a9947867SLaurent Vivier         break;
961a9947867SLaurent Vivier     /* struct ifla_vf_guid  */
962a9947867SLaurent Vivier     case QEMU_IFLA_VF_IB_NODE_GUID:
963a9947867SLaurent Vivier     case QEMU_IFLA_VF_IB_PORT_GUID:
964a9947867SLaurent Vivier         guid = NLA_DATA(nlattr);
965a9947867SLaurent Vivier         guid->vf = tswap32(guid->vf);
966a9947867SLaurent Vivier         guid->guid = tswap32(guid->guid);
967a9947867SLaurent Vivier         break;
968a9947867SLaurent Vivier     /* nested */
969a9947867SLaurent Vivier     case QEMU_IFLA_VF_VLAN_LIST:
970a9947867SLaurent Vivier         return host_to_target_for_each_nlattr(RTA_DATA(nlattr), nlattr->nla_len,
971a9947867SLaurent Vivier                                               NULL,
972a9947867SLaurent Vivier                                           host_to_target_data_vlan_list_nlattr);
973a9947867SLaurent Vivier     case QEMU_IFLA_VF_STATS:
974a9947867SLaurent Vivier         return host_to_target_for_each_nlattr(RTA_DATA(nlattr), nlattr->nla_len,
975a9947867SLaurent Vivier                                               NULL,
976a9947867SLaurent Vivier                                            host_to_target_data_vf_stats_nlattr);
977a9947867SLaurent Vivier     default:
978a9947867SLaurent Vivier         qemu_log_mask(LOG_UNIMP, "Unknown host VFINFO type: %d\n",
979a9947867SLaurent Vivier                       nlattr->nla_type);
980a9947867SLaurent Vivier         break;
981a9947867SLaurent Vivier     }
982a9947867SLaurent Vivier     return 0;
983a9947867SLaurent Vivier }
984a9947867SLaurent Vivier 
host_to_target_data_link_rtattr(struct rtattr * rtattr)985f7e6a401SLaurent Vivier static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
986f7e6a401SLaurent Vivier {
987f7e6a401SLaurent Vivier     uint32_t *u32;
988f7e6a401SLaurent Vivier     struct rtnl_link_stats *st;
989f7e6a401SLaurent Vivier     struct rtnl_link_stats64 *st64;
990f7e6a401SLaurent Vivier     struct rtnl_link_ifmap *map;
991f7e6a401SLaurent Vivier     struct linkinfo_context li_context;
992f7e6a401SLaurent Vivier 
993f7e6a401SLaurent Vivier     switch (rtattr->rta_type) {
994f7e6a401SLaurent Vivier     /* binary stream */
995f7e6a401SLaurent Vivier     case QEMU_IFLA_ADDRESS:
996f7e6a401SLaurent Vivier     case QEMU_IFLA_BROADCAST:
997d9679ee5SLaurent Vivier     case QEMU_IFLA_PERM_ADDRESS:
998312aef98SLaurent Vivier     case QEMU_IFLA_PHYS_PORT_ID:
999f7e6a401SLaurent Vivier     /* string */
1000f7e6a401SLaurent Vivier     case QEMU_IFLA_IFNAME:
1001f7e6a401SLaurent Vivier     case QEMU_IFLA_QDISC:
1002312aef98SLaurent Vivier     case QEMU_IFLA_PARENT_DEV_NAME:
1003312aef98SLaurent Vivier     case QEMU_IFLA_PARENT_DEV_BUS_NAME:
1004f7e6a401SLaurent Vivier         break;
1005f7e6a401SLaurent Vivier     /* uin8_t */
1006f7e6a401SLaurent Vivier     case QEMU_IFLA_OPERSTATE:
1007f7e6a401SLaurent Vivier     case QEMU_IFLA_LINKMODE:
1008f7e6a401SLaurent Vivier     case QEMU_IFLA_CARRIER:
1009f7e6a401SLaurent Vivier     case QEMU_IFLA_PROTO_DOWN:
1010f7e6a401SLaurent Vivier         break;
1011f7e6a401SLaurent Vivier     /* uint32_t */
1012f7e6a401SLaurent Vivier     case QEMU_IFLA_MTU:
1013f7e6a401SLaurent Vivier     case QEMU_IFLA_LINK:
1014f7e6a401SLaurent Vivier     case QEMU_IFLA_WEIGHT:
1015f7e6a401SLaurent Vivier     case QEMU_IFLA_TXQLEN:
1016f7e6a401SLaurent Vivier     case QEMU_IFLA_CARRIER_CHANGES:
1017f7e6a401SLaurent Vivier     case QEMU_IFLA_NUM_RX_QUEUES:
1018f7e6a401SLaurent Vivier     case QEMU_IFLA_NUM_TX_QUEUES:
1019f7e6a401SLaurent Vivier     case QEMU_IFLA_PROMISCUITY:
1020f7e6a401SLaurent Vivier     case QEMU_IFLA_EXT_MASK:
1021f7e6a401SLaurent Vivier     case QEMU_IFLA_LINK_NETNSID:
1022f7e6a401SLaurent Vivier     case QEMU_IFLA_GROUP:
1023f7e6a401SLaurent Vivier     case QEMU_IFLA_MASTER:
1024f7e6a401SLaurent Vivier     case QEMU_IFLA_NUM_VF:
1025f7e6a401SLaurent Vivier     case QEMU_IFLA_GSO_MAX_SEGS:
1026f7e6a401SLaurent Vivier     case QEMU_IFLA_GSO_MAX_SIZE:
1027f7e6a401SLaurent Vivier     case QEMU_IFLA_CARRIER_UP_COUNT:
1028f7e6a401SLaurent Vivier     case QEMU_IFLA_CARRIER_DOWN_COUNT:
10290f5faca7SLaurent Vivier     case QEMU_IFLA_MIN_MTU:
10300f5faca7SLaurent Vivier     case QEMU_IFLA_MAX_MTU:
1031f7e6a401SLaurent Vivier         u32 = RTA_DATA(rtattr);
1032f7e6a401SLaurent Vivier         *u32 = tswap32(*u32);
1033f7e6a401SLaurent Vivier         break;
1034f7e6a401SLaurent Vivier     /* struct rtnl_link_stats */
1035f7e6a401SLaurent Vivier     case QEMU_IFLA_STATS:
1036f7e6a401SLaurent Vivier         st = RTA_DATA(rtattr);
1037f7e6a401SLaurent Vivier         st->rx_packets = tswap32(st->rx_packets);
1038f7e6a401SLaurent Vivier         st->tx_packets = tswap32(st->tx_packets);
1039f7e6a401SLaurent Vivier         st->rx_bytes = tswap32(st->rx_bytes);
1040f7e6a401SLaurent Vivier         st->tx_bytes = tswap32(st->tx_bytes);
1041f7e6a401SLaurent Vivier         st->rx_errors = tswap32(st->rx_errors);
1042f7e6a401SLaurent Vivier         st->tx_errors = tswap32(st->tx_errors);
1043f7e6a401SLaurent Vivier         st->rx_dropped = tswap32(st->rx_dropped);
1044f7e6a401SLaurent Vivier         st->tx_dropped = tswap32(st->tx_dropped);
1045f7e6a401SLaurent Vivier         st->multicast = tswap32(st->multicast);
1046f7e6a401SLaurent Vivier         st->collisions = tswap32(st->collisions);
1047f7e6a401SLaurent Vivier 
1048f7e6a401SLaurent Vivier         /* detailed rx_errors: */
1049f7e6a401SLaurent Vivier         st->rx_length_errors = tswap32(st->rx_length_errors);
1050f7e6a401SLaurent Vivier         st->rx_over_errors = tswap32(st->rx_over_errors);
1051f7e6a401SLaurent Vivier         st->rx_crc_errors = tswap32(st->rx_crc_errors);
1052f7e6a401SLaurent Vivier         st->rx_frame_errors = tswap32(st->rx_frame_errors);
1053f7e6a401SLaurent Vivier         st->rx_fifo_errors = tswap32(st->rx_fifo_errors);
1054f7e6a401SLaurent Vivier         st->rx_missed_errors = tswap32(st->rx_missed_errors);
1055f7e6a401SLaurent Vivier 
1056f7e6a401SLaurent Vivier         /* detailed tx_errors */
1057f7e6a401SLaurent Vivier         st->tx_aborted_errors = tswap32(st->tx_aborted_errors);
1058f7e6a401SLaurent Vivier         st->tx_carrier_errors = tswap32(st->tx_carrier_errors);
1059f7e6a401SLaurent Vivier         st->tx_fifo_errors = tswap32(st->tx_fifo_errors);
1060f7e6a401SLaurent Vivier         st->tx_heartbeat_errors = tswap32(st->tx_heartbeat_errors);
1061f7e6a401SLaurent Vivier         st->tx_window_errors = tswap32(st->tx_window_errors);
1062f7e6a401SLaurent Vivier 
1063f7e6a401SLaurent Vivier         /* for cslip etc */
1064f7e6a401SLaurent Vivier         st->rx_compressed = tswap32(st->rx_compressed);
1065f7e6a401SLaurent Vivier         st->tx_compressed = tswap32(st->tx_compressed);
1066f7e6a401SLaurent Vivier         break;
1067f7e6a401SLaurent Vivier     /* struct rtnl_link_stats64 */
1068f7e6a401SLaurent Vivier     case QEMU_IFLA_STATS64:
1069f7e6a401SLaurent Vivier         st64 = RTA_DATA(rtattr);
1070f7e6a401SLaurent Vivier         st64->rx_packets = tswap64(st64->rx_packets);
1071f7e6a401SLaurent Vivier         st64->tx_packets = tswap64(st64->tx_packets);
1072f7e6a401SLaurent Vivier         st64->rx_bytes = tswap64(st64->rx_bytes);
1073f7e6a401SLaurent Vivier         st64->tx_bytes = tswap64(st64->tx_bytes);
1074f7e6a401SLaurent Vivier         st64->rx_errors = tswap64(st64->rx_errors);
1075f7e6a401SLaurent Vivier         st64->tx_errors = tswap64(st64->tx_errors);
1076f7e6a401SLaurent Vivier         st64->rx_dropped = tswap64(st64->rx_dropped);
1077f7e6a401SLaurent Vivier         st64->tx_dropped = tswap64(st64->tx_dropped);
1078f7e6a401SLaurent Vivier         st64->multicast = tswap64(st64->multicast);
1079f7e6a401SLaurent Vivier         st64->collisions = tswap64(st64->collisions);
1080f7e6a401SLaurent Vivier 
1081f7e6a401SLaurent Vivier         /* detailed rx_errors: */
1082f7e6a401SLaurent Vivier         st64->rx_length_errors = tswap64(st64->rx_length_errors);
1083f7e6a401SLaurent Vivier         st64->rx_over_errors = tswap64(st64->rx_over_errors);
1084f7e6a401SLaurent Vivier         st64->rx_crc_errors = tswap64(st64->rx_crc_errors);
1085f7e6a401SLaurent Vivier         st64->rx_frame_errors = tswap64(st64->rx_frame_errors);
1086f7e6a401SLaurent Vivier         st64->rx_fifo_errors = tswap64(st64->rx_fifo_errors);
1087f7e6a401SLaurent Vivier         st64->rx_missed_errors = tswap64(st64->rx_missed_errors);
1088f7e6a401SLaurent Vivier 
1089f7e6a401SLaurent Vivier         /* detailed tx_errors */
1090f7e6a401SLaurent Vivier         st64->tx_aborted_errors = tswap64(st64->tx_aborted_errors);
1091f7e6a401SLaurent Vivier         st64->tx_carrier_errors = tswap64(st64->tx_carrier_errors);
1092f7e6a401SLaurent Vivier         st64->tx_fifo_errors = tswap64(st64->tx_fifo_errors);
1093f7e6a401SLaurent Vivier         st64->tx_heartbeat_errors = tswap64(st64->tx_heartbeat_errors);
1094f7e6a401SLaurent Vivier         st64->tx_window_errors = tswap64(st64->tx_window_errors);
1095f7e6a401SLaurent Vivier 
1096f7e6a401SLaurent Vivier         /* for cslip etc */
1097f7e6a401SLaurent Vivier         st64->rx_compressed = tswap64(st64->rx_compressed);
1098f7e6a401SLaurent Vivier         st64->tx_compressed = tswap64(st64->tx_compressed);
1099f7e6a401SLaurent Vivier         break;
1100f7e6a401SLaurent Vivier     /* struct rtnl_link_ifmap */
1101f7e6a401SLaurent Vivier     case QEMU_IFLA_MAP:
1102f7e6a401SLaurent Vivier         map = RTA_DATA(rtattr);
1103f7e6a401SLaurent Vivier         map->mem_start = tswap64(map->mem_start);
1104f7e6a401SLaurent Vivier         map->mem_end = tswap64(map->mem_end);
1105f7e6a401SLaurent Vivier         map->base_addr = tswap64(map->base_addr);
1106f7e6a401SLaurent Vivier         map->irq = tswap16(map->irq);
1107f7e6a401SLaurent Vivier         break;
1108f7e6a401SLaurent Vivier     /* nested */
1109f7e6a401SLaurent Vivier     case QEMU_IFLA_LINKINFO:
1110f7e6a401SLaurent Vivier         memset(&li_context, 0, sizeof(li_context));
1111f7e6a401SLaurent Vivier         return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
1112f7e6a401SLaurent Vivier                                               &li_context,
1113f7e6a401SLaurent Vivier                                            host_to_target_data_linkinfo_nlattr);
1114f7e6a401SLaurent Vivier     case QEMU_IFLA_AF_SPEC:
1115f7e6a401SLaurent Vivier         return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
1116f7e6a401SLaurent Vivier                                               NULL,
1117f7e6a401SLaurent Vivier                                              host_to_target_data_spec_nlattr);
1118f7e6a401SLaurent Vivier     case QEMU_IFLA_XDP:
1119f7e6a401SLaurent Vivier         return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
1120f7e6a401SLaurent Vivier                                               NULL,
1121f7e6a401SLaurent Vivier                                                 host_to_target_data_xdp_nlattr);
1122a9947867SLaurent Vivier     case QEMU_IFLA_VFINFO_LIST:
1123a9947867SLaurent Vivier         return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
1124a9947867SLaurent Vivier                                               NULL,
1125a9947867SLaurent Vivier                                              host_to_target_data_vfinfo_nlattr);
1126f7e6a401SLaurent Vivier     default:
112739be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA type: %d\n",
112839be5350SJosh Kunz                       rtattr->rta_type);
1129f7e6a401SLaurent Vivier         break;
1130f7e6a401SLaurent Vivier     }
1131f7e6a401SLaurent Vivier     return 0;
1132f7e6a401SLaurent Vivier }
1133f7e6a401SLaurent Vivier 
host_to_target_data_addr_rtattr(struct rtattr * rtattr)1134f7e6a401SLaurent Vivier static abi_long host_to_target_data_addr_rtattr(struct rtattr *rtattr)
1135f7e6a401SLaurent Vivier {
1136f7e6a401SLaurent Vivier     uint32_t *u32;
1137f7e6a401SLaurent Vivier     struct ifa_cacheinfo *ci;
1138f7e6a401SLaurent Vivier 
1139f7e6a401SLaurent Vivier     switch (rtattr->rta_type) {
1140f7e6a401SLaurent Vivier     /* binary: depends on family type */
1141f7e6a401SLaurent Vivier     case IFA_ADDRESS:
1142f7e6a401SLaurent Vivier     case IFA_LOCAL:
1143f7e6a401SLaurent Vivier         break;
1144f7e6a401SLaurent Vivier     /* string */
1145f7e6a401SLaurent Vivier     case IFA_LABEL:
1146f7e6a401SLaurent Vivier         break;
1147f7e6a401SLaurent Vivier     /* u32 */
1148f7e6a401SLaurent Vivier     case IFA_FLAGS:
1149f7e6a401SLaurent Vivier     case IFA_BROADCAST:
1150f7e6a401SLaurent Vivier         u32 = RTA_DATA(rtattr);
1151f7e6a401SLaurent Vivier         *u32 = tswap32(*u32);
1152f7e6a401SLaurent Vivier         break;
1153f7e6a401SLaurent Vivier     /* struct ifa_cacheinfo */
1154f7e6a401SLaurent Vivier     case IFA_CACHEINFO:
1155f7e6a401SLaurent Vivier         ci = RTA_DATA(rtattr);
1156f7e6a401SLaurent Vivier         ci->ifa_prefered = tswap32(ci->ifa_prefered);
1157f7e6a401SLaurent Vivier         ci->ifa_valid = tswap32(ci->ifa_valid);
1158f7e6a401SLaurent Vivier         ci->cstamp = tswap32(ci->cstamp);
1159f7e6a401SLaurent Vivier         ci->tstamp = tswap32(ci->tstamp);
1160f7e6a401SLaurent Vivier         break;
1161f7e6a401SLaurent Vivier     default:
116239be5350SJosh Kunz         qemu_log_mask(
116339be5350SJosh Kunz             LOG_UNIMP, "Unknown host IFA type: %d\n", rtattr->rta_type);
1164f7e6a401SLaurent Vivier         break;
1165f7e6a401SLaurent Vivier     }
1166f7e6a401SLaurent Vivier     return 0;
1167f7e6a401SLaurent Vivier }
1168f7e6a401SLaurent Vivier 
host_to_target_data_route_rtattr(struct rtattr * rtattr)1169f7e6a401SLaurent Vivier static abi_long host_to_target_data_route_rtattr(struct rtattr *rtattr)
1170f7e6a401SLaurent Vivier {
1171f7e6a401SLaurent Vivier     uint32_t *u32;
1172f7e6a401SLaurent Vivier     struct rta_cacheinfo *ci;
1173f7e6a401SLaurent Vivier 
1174f7e6a401SLaurent Vivier     switch (rtattr->rta_type) {
1175f7e6a401SLaurent Vivier     /* binary: depends on family type */
1176f7e6a401SLaurent Vivier     case QEMU_RTA_GATEWAY:
1177f7e6a401SLaurent Vivier     case QEMU_RTA_DST:
1178f7e6a401SLaurent Vivier     case QEMU_RTA_PREFSRC:
1179f7e6a401SLaurent Vivier         break;
1180f7e6a401SLaurent Vivier     /* u8 */
1181f7e6a401SLaurent Vivier     case QEMU_RTA_PREF:
1182f7e6a401SLaurent Vivier         break;
1183f7e6a401SLaurent Vivier     /* u32 */
1184f7e6a401SLaurent Vivier     case QEMU_RTA_PRIORITY:
1185f7e6a401SLaurent Vivier     case QEMU_RTA_TABLE:
1186f7e6a401SLaurent Vivier     case QEMU_RTA_OIF:
1187f7e6a401SLaurent Vivier         u32 = RTA_DATA(rtattr);
1188f7e6a401SLaurent Vivier         *u32 = tswap32(*u32);
1189f7e6a401SLaurent Vivier         break;
1190f7e6a401SLaurent Vivier     /* struct rta_cacheinfo */
1191f7e6a401SLaurent Vivier     case QEMU_RTA_CACHEINFO:
1192f7e6a401SLaurent Vivier         ci = RTA_DATA(rtattr);
1193f7e6a401SLaurent Vivier         ci->rta_clntref = tswap32(ci->rta_clntref);
1194f7e6a401SLaurent Vivier         ci->rta_lastuse = tswap32(ci->rta_lastuse);
1195f7e6a401SLaurent Vivier         ci->rta_expires = tswap32(ci->rta_expires);
1196f7e6a401SLaurent Vivier         ci->rta_error = tswap32(ci->rta_error);
1197f7e6a401SLaurent Vivier         ci->rta_used = tswap32(ci->rta_used);
1198f7e6a401SLaurent Vivier #if defined(RTNETLINK_HAVE_PEERINFO)
1199f7e6a401SLaurent Vivier         ci->rta_id = tswap32(ci->rta_id);
1200f7e6a401SLaurent Vivier         ci->rta_ts = tswap32(ci->rta_ts);
1201f7e6a401SLaurent Vivier         ci->rta_tsage = tswap32(ci->rta_tsage);
1202f7e6a401SLaurent Vivier #endif
1203f7e6a401SLaurent Vivier         break;
1204f7e6a401SLaurent Vivier     default:
120539be5350SJosh Kunz         qemu_log_mask(
120639be5350SJosh Kunz             LOG_UNIMP, "Unknown host RTA type: %d\n", rtattr->rta_type);
1207f7e6a401SLaurent Vivier         break;
1208f7e6a401SLaurent Vivier     }
1209f7e6a401SLaurent Vivier     return 0;
1210f7e6a401SLaurent Vivier }
1211f7e6a401SLaurent Vivier 
host_to_target_link_rtattr(struct rtattr * rtattr,uint32_t rtattr_len)1212f7e6a401SLaurent Vivier static abi_long host_to_target_link_rtattr(struct rtattr *rtattr,
1213f7e6a401SLaurent Vivier                                          uint32_t rtattr_len)
1214f7e6a401SLaurent Vivier {
1215f7e6a401SLaurent Vivier     return host_to_target_for_each_rtattr(rtattr, rtattr_len,
1216f7e6a401SLaurent Vivier                                           host_to_target_data_link_rtattr);
1217f7e6a401SLaurent Vivier }
1218f7e6a401SLaurent Vivier 
host_to_target_addr_rtattr(struct rtattr * rtattr,uint32_t rtattr_len)1219f7e6a401SLaurent Vivier static abi_long host_to_target_addr_rtattr(struct rtattr *rtattr,
1220f7e6a401SLaurent Vivier                                          uint32_t rtattr_len)
1221f7e6a401SLaurent Vivier {
1222f7e6a401SLaurent Vivier     return host_to_target_for_each_rtattr(rtattr, rtattr_len,
1223f7e6a401SLaurent Vivier                                           host_to_target_data_addr_rtattr);
1224f7e6a401SLaurent Vivier }
1225f7e6a401SLaurent Vivier 
host_to_target_route_rtattr(struct rtattr * rtattr,uint32_t rtattr_len)1226f7e6a401SLaurent Vivier static abi_long host_to_target_route_rtattr(struct rtattr *rtattr,
1227f7e6a401SLaurent Vivier                                          uint32_t rtattr_len)
1228f7e6a401SLaurent Vivier {
1229f7e6a401SLaurent Vivier     return host_to_target_for_each_rtattr(rtattr, rtattr_len,
1230f7e6a401SLaurent Vivier                                           host_to_target_data_route_rtattr);
1231f7e6a401SLaurent Vivier }
1232f7e6a401SLaurent Vivier 
host_to_target_data_route(struct nlmsghdr * nlh)1233f7e6a401SLaurent Vivier static abi_long host_to_target_data_route(struct nlmsghdr *nlh)
1234f7e6a401SLaurent Vivier {
1235f7e6a401SLaurent Vivier     uint32_t nlmsg_len;
1236f7e6a401SLaurent Vivier     struct ifinfomsg *ifi;
1237f7e6a401SLaurent Vivier     struct ifaddrmsg *ifa;
1238f7e6a401SLaurent Vivier     struct rtmsg *rtm;
1239f7e6a401SLaurent Vivier 
1240f7e6a401SLaurent Vivier     nlmsg_len = nlh->nlmsg_len;
1241f7e6a401SLaurent Vivier     switch (nlh->nlmsg_type) {
1242f7e6a401SLaurent Vivier     case RTM_NEWLINK:
1243f7e6a401SLaurent Vivier     case RTM_DELLINK:
1244f7e6a401SLaurent Vivier     case RTM_GETLINK:
1245f7e6a401SLaurent Vivier         if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifi))) {
1246f7e6a401SLaurent Vivier             ifi = NLMSG_DATA(nlh);
1247f7e6a401SLaurent Vivier             ifi->ifi_type = tswap16(ifi->ifi_type);
1248f7e6a401SLaurent Vivier             ifi->ifi_index = tswap32(ifi->ifi_index);
1249f7e6a401SLaurent Vivier             ifi->ifi_flags = tswap32(ifi->ifi_flags);
1250f7e6a401SLaurent Vivier             ifi->ifi_change = tswap32(ifi->ifi_change);
1251f7e6a401SLaurent Vivier             host_to_target_link_rtattr(IFLA_RTA(ifi),
1252f7e6a401SLaurent Vivier                                        nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));
1253f7e6a401SLaurent Vivier         }
1254f7e6a401SLaurent Vivier         break;
1255f7e6a401SLaurent Vivier     case RTM_NEWADDR:
1256f7e6a401SLaurent Vivier     case RTM_DELADDR:
1257f7e6a401SLaurent Vivier     case RTM_GETADDR:
1258f7e6a401SLaurent Vivier         if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifa))) {
1259f7e6a401SLaurent Vivier             ifa = NLMSG_DATA(nlh);
1260f7e6a401SLaurent Vivier             ifa->ifa_index = tswap32(ifa->ifa_index);
1261f7e6a401SLaurent Vivier             host_to_target_addr_rtattr(IFA_RTA(ifa),
1262f7e6a401SLaurent Vivier                                        nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
1263f7e6a401SLaurent Vivier         }
1264f7e6a401SLaurent Vivier         break;
1265f7e6a401SLaurent Vivier     case RTM_NEWROUTE:
1266f7e6a401SLaurent Vivier     case RTM_DELROUTE:
1267f7e6a401SLaurent Vivier     case RTM_GETROUTE:
1268f7e6a401SLaurent Vivier         if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*rtm))) {
1269f7e6a401SLaurent Vivier             rtm = NLMSG_DATA(nlh);
1270f7e6a401SLaurent Vivier             rtm->rtm_flags = tswap32(rtm->rtm_flags);
1271f7e6a401SLaurent Vivier             host_to_target_route_rtattr(RTM_RTA(rtm),
1272f7e6a401SLaurent Vivier                                         nlmsg_len - NLMSG_LENGTH(sizeof(*rtm)));
1273f7e6a401SLaurent Vivier         }
1274f7e6a401SLaurent Vivier         break;
1275f7e6a401SLaurent Vivier     default:
1276f7e6a401SLaurent Vivier         return -TARGET_EINVAL;
1277f7e6a401SLaurent Vivier     }
1278f7e6a401SLaurent Vivier     return 0;
1279f7e6a401SLaurent Vivier }
1280f7e6a401SLaurent Vivier 
host_to_target_nlmsg_route(struct nlmsghdr * nlh,size_t len)1281f7e6a401SLaurent Vivier static inline abi_long host_to_target_nlmsg_route(struct nlmsghdr *nlh,
1282f7e6a401SLaurent Vivier                                                   size_t len)
1283f7e6a401SLaurent Vivier {
1284f7e6a401SLaurent Vivier     return host_to_target_for_each_nlmsg(nlh, len, host_to_target_data_route);
1285f7e6a401SLaurent Vivier }
1286f7e6a401SLaurent Vivier 
target_to_host_for_each_nlattr(struct nlattr * nlattr,size_t len,abi_long (* target_to_host_nlattr)(struct nlattr *))1287fa2229dbSMathis Marion static abi_long target_to_host_for_each_nlattr(struct nlattr *nlattr,
1288fa2229dbSMathis Marion                                                size_t len,
1289fa2229dbSMathis Marion                                                abi_long (*target_to_host_nlattr)
1290fa2229dbSMathis Marion                                                         (struct nlattr *))
1291fa2229dbSMathis Marion {
1292fa2229dbSMathis Marion     unsigned short aligned_nla_len;
1293fa2229dbSMathis Marion     abi_long ret;
1294fa2229dbSMathis Marion 
1295fa2229dbSMathis Marion     while (len > sizeof(struct nlattr)) {
1296fa2229dbSMathis Marion         if (tswap16(nlattr->nla_len) < sizeof(struct rtattr) ||
1297fa2229dbSMathis Marion             tswap16(nlattr->nla_len) > len) {
1298fa2229dbSMathis Marion             break;
1299fa2229dbSMathis Marion         }
1300fa2229dbSMathis Marion         nlattr->nla_len = tswap16(nlattr->nla_len);
1301fa2229dbSMathis Marion         nlattr->nla_type = tswap16(nlattr->nla_type);
1302fa2229dbSMathis Marion         ret = target_to_host_nlattr(nlattr);
1303fa2229dbSMathis Marion         if (ret < 0) {
1304fa2229dbSMathis Marion             return ret;
1305fa2229dbSMathis Marion         }
1306fa2229dbSMathis Marion 
1307fa2229dbSMathis Marion         aligned_nla_len = NLA_ALIGN(nlattr->nla_len);
1308fa2229dbSMathis Marion         if (aligned_nla_len >= len) {
1309fa2229dbSMathis Marion             break;
1310fa2229dbSMathis Marion         }
1311fa2229dbSMathis Marion         len -= aligned_nla_len;
1312fa2229dbSMathis Marion         nlattr = (struct nlattr *)(((char *)nlattr) + aligned_nla_len);
1313fa2229dbSMathis Marion     }
1314fa2229dbSMathis Marion     return 0;
1315fa2229dbSMathis Marion }
1316fa2229dbSMathis Marion 
target_to_host_data_inet6_nlattr(struct nlattr * nlattr)1317fa2229dbSMathis Marion static abi_long target_to_host_data_inet6_nlattr(struct nlattr *nlattr)
1318fa2229dbSMathis Marion {
1319fa2229dbSMathis Marion     switch (nlattr->nla_type) {
1320fa2229dbSMathis Marion     /* uint8_t */
1321fa2229dbSMathis Marion     case QEMU_IFLA_INET6_ADDR_GEN_MODE:
1322fa2229dbSMathis Marion         break;
1323fa2229dbSMathis Marion     default:
1324fa2229dbSMathis Marion         qemu_log_mask(LOG_UNIMP, "Unknown target AF_INET6 type: %d\n",
1325fa2229dbSMathis Marion                       nlattr->nla_type);
1326fa2229dbSMathis Marion     }
1327fa2229dbSMathis Marion     return 0;
1328fa2229dbSMathis Marion }
1329fa2229dbSMathis Marion 
target_to_host_for_each_rtattr(struct rtattr * rtattr,size_t len,abi_long (* target_to_host_rtattr)(struct rtattr *))1330f7e6a401SLaurent Vivier static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr,
1331f7e6a401SLaurent Vivier                                                size_t len,
1332f7e6a401SLaurent Vivier                                                abi_long (*target_to_host_rtattr)
1333f7e6a401SLaurent Vivier                                                         (struct rtattr *))
1334f7e6a401SLaurent Vivier {
13351645fb5aSShu-Chun Weng     unsigned short aligned_rta_len;
1336f7e6a401SLaurent Vivier     abi_long ret;
1337f7e6a401SLaurent Vivier 
1338f7e6a401SLaurent Vivier     while (len >= sizeof(struct rtattr)) {
1339f7e6a401SLaurent Vivier         if (tswap16(rtattr->rta_len) < sizeof(struct rtattr) ||
1340f7e6a401SLaurent Vivier             tswap16(rtattr->rta_len) > len) {
1341f7e6a401SLaurent Vivier             break;
1342f7e6a401SLaurent Vivier         }
1343f7e6a401SLaurent Vivier         rtattr->rta_len = tswap16(rtattr->rta_len);
1344f7e6a401SLaurent Vivier         rtattr->rta_type = tswap16(rtattr->rta_type);
1345f7e6a401SLaurent Vivier         ret = target_to_host_rtattr(rtattr);
1346f7e6a401SLaurent Vivier         if (ret < 0) {
1347f7e6a401SLaurent Vivier             return ret;
1348f7e6a401SLaurent Vivier         }
13491645fb5aSShu-Chun Weng 
13501645fb5aSShu-Chun Weng         aligned_rta_len = RTA_ALIGN(rtattr->rta_len);
13511645fb5aSShu-Chun Weng         if (aligned_rta_len >= len) {
13521645fb5aSShu-Chun Weng             break;
13531645fb5aSShu-Chun Weng         }
13541645fb5aSShu-Chun Weng         len -= aligned_rta_len;
13551645fb5aSShu-Chun Weng         rtattr = (struct rtattr *)(((char *)rtattr) + aligned_rta_len);
1356f7e6a401SLaurent Vivier     }
1357f7e6a401SLaurent Vivier     return 0;
1358f7e6a401SLaurent Vivier }
1359f7e6a401SLaurent Vivier 
target_to_host_data_spec_nlattr(struct nlattr * nlattr)1360fa2229dbSMathis Marion static abi_long target_to_host_data_spec_nlattr(struct nlattr *nlattr)
1361fa2229dbSMathis Marion {
1362*2fe8ed6fSMathis Marion     switch (nlattr->nla_type & NLA_TYPE_MASK) {
1363fa2229dbSMathis Marion     case AF_INET6:
1364fa2229dbSMathis Marion         return target_to_host_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len,
1365fa2229dbSMathis Marion                                               target_to_host_data_inet6_nlattr);
1366fa2229dbSMathis Marion     default:
1367fa2229dbSMathis Marion         qemu_log_mask(LOG_UNIMP, "Unknown target AF_SPEC type: %d\n",
1368fa2229dbSMathis Marion                       nlattr->nla_type);
1369fa2229dbSMathis Marion         break;
1370fa2229dbSMathis Marion     }
1371fa2229dbSMathis Marion     return 0;
1372fa2229dbSMathis Marion }
1373fa2229dbSMathis Marion 
target_to_host_data_link_rtattr(struct rtattr * rtattr)1374f7e6a401SLaurent Vivier static abi_long target_to_host_data_link_rtattr(struct rtattr *rtattr)
1375f7e6a401SLaurent Vivier {
13765351f407SLaurent Vivier     uint32_t *u32;
13775351f407SLaurent Vivier 
1378*2fe8ed6fSMathis Marion     switch (rtattr->rta_type & NLA_TYPE_MASK) {
13795351f407SLaurent Vivier     /* uint32_t */
1380fa2229dbSMathis Marion     case QEMU_IFLA_MTU:
1381fa2229dbSMathis Marion     case QEMU_IFLA_TXQLEN:
13825351f407SLaurent Vivier     case QEMU_IFLA_EXT_MASK:
13835351f407SLaurent Vivier         u32 = RTA_DATA(rtattr);
13845351f407SLaurent Vivier         *u32 = tswap32(*u32);
13855351f407SLaurent Vivier         break;
1386fa2229dbSMathis Marion     case QEMU_IFLA_AF_SPEC:
1387fa2229dbSMathis Marion         return target_to_host_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
1388fa2229dbSMathis Marion                                               target_to_host_data_spec_nlattr);
1389f7e6a401SLaurent Vivier     default:
139039be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown target QEMU_IFLA type: %d\n",
139139be5350SJosh Kunz                       rtattr->rta_type);
1392f7e6a401SLaurent Vivier         break;
1393f7e6a401SLaurent Vivier     }
1394f7e6a401SLaurent Vivier     return 0;
1395f7e6a401SLaurent Vivier }
1396f7e6a401SLaurent Vivier 
target_to_host_data_addr_rtattr(struct rtattr * rtattr)1397f7e6a401SLaurent Vivier static abi_long target_to_host_data_addr_rtattr(struct rtattr *rtattr)
1398f7e6a401SLaurent Vivier {
1399f7e6a401SLaurent Vivier     switch (rtattr->rta_type) {
1400f7e6a401SLaurent Vivier     /* binary: depends on family type */
1401f7e6a401SLaurent Vivier     case IFA_LOCAL:
1402f7e6a401SLaurent Vivier     case IFA_ADDRESS:
1403f7e6a401SLaurent Vivier         break;
1404f7e6a401SLaurent Vivier     default:
140539be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown target IFA type: %d\n",
140639be5350SJosh Kunz                       rtattr->rta_type);
1407f7e6a401SLaurent Vivier         break;
1408f7e6a401SLaurent Vivier     }
1409f7e6a401SLaurent Vivier     return 0;
1410f7e6a401SLaurent Vivier }
1411f7e6a401SLaurent Vivier 
target_to_host_data_route_rtattr(struct rtattr * rtattr)1412f7e6a401SLaurent Vivier static abi_long target_to_host_data_route_rtattr(struct rtattr *rtattr)
1413f7e6a401SLaurent Vivier {
1414f7e6a401SLaurent Vivier     uint32_t *u32;
1415f7e6a401SLaurent Vivier     switch (rtattr->rta_type) {
1416f7e6a401SLaurent Vivier     /* binary: depends on family type */
1417f7e6a401SLaurent Vivier     case QEMU_RTA_DST:
1418f7e6a401SLaurent Vivier     case QEMU_RTA_SRC:
1419f7e6a401SLaurent Vivier     case QEMU_RTA_GATEWAY:
1420f7e6a401SLaurent Vivier         break;
1421f7e6a401SLaurent Vivier     /* u32 */
1422f7e6a401SLaurent Vivier     case QEMU_RTA_PRIORITY:
1423f536612dSLaurent Vivier     case QEMU_RTA_TABLE:
1424f7e6a401SLaurent Vivier     case QEMU_RTA_OIF:
1425f7e6a401SLaurent Vivier         u32 = RTA_DATA(rtattr);
1426f7e6a401SLaurent Vivier         *u32 = tswap32(*u32);
1427f7e6a401SLaurent Vivier         break;
1428f7e6a401SLaurent Vivier     default:
142939be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown target RTA type: %d\n",
143039be5350SJosh Kunz                       rtattr->rta_type);
1431f7e6a401SLaurent Vivier         break;
1432f7e6a401SLaurent Vivier     }
1433f7e6a401SLaurent Vivier     return 0;
1434f7e6a401SLaurent Vivier }
1435f7e6a401SLaurent Vivier 
target_to_host_link_rtattr(struct rtattr * rtattr,uint32_t rtattr_len)1436f7e6a401SLaurent Vivier static void target_to_host_link_rtattr(struct rtattr *rtattr,
1437f7e6a401SLaurent Vivier                                        uint32_t rtattr_len)
1438f7e6a401SLaurent Vivier {
1439f7e6a401SLaurent Vivier     target_to_host_for_each_rtattr(rtattr, rtattr_len,
1440f7e6a401SLaurent Vivier                                    target_to_host_data_link_rtattr);
1441f7e6a401SLaurent Vivier }
1442f7e6a401SLaurent Vivier 
target_to_host_addr_rtattr(struct rtattr * rtattr,uint32_t rtattr_len)1443f7e6a401SLaurent Vivier static void target_to_host_addr_rtattr(struct rtattr *rtattr,
1444f7e6a401SLaurent Vivier                                      uint32_t rtattr_len)
1445f7e6a401SLaurent Vivier {
1446f7e6a401SLaurent Vivier     target_to_host_for_each_rtattr(rtattr, rtattr_len,
1447f7e6a401SLaurent Vivier                                    target_to_host_data_addr_rtattr);
1448f7e6a401SLaurent Vivier }
1449f7e6a401SLaurent Vivier 
target_to_host_route_rtattr(struct rtattr * rtattr,uint32_t rtattr_len)1450f7e6a401SLaurent Vivier static void target_to_host_route_rtattr(struct rtattr *rtattr,
1451f7e6a401SLaurent Vivier                                      uint32_t rtattr_len)
1452f7e6a401SLaurent Vivier {
1453f7e6a401SLaurent Vivier     target_to_host_for_each_rtattr(rtattr, rtattr_len,
1454f7e6a401SLaurent Vivier                                    target_to_host_data_route_rtattr);
1455f7e6a401SLaurent Vivier }
1456f7e6a401SLaurent Vivier 
target_to_host_data_route(struct nlmsghdr * nlh)1457f7e6a401SLaurent Vivier static abi_long target_to_host_data_route(struct nlmsghdr *nlh)
1458f7e6a401SLaurent Vivier {
1459f7e6a401SLaurent Vivier     struct ifinfomsg *ifi;
1460f7e6a401SLaurent Vivier     struct ifaddrmsg *ifa;
1461f7e6a401SLaurent Vivier     struct rtmsg *rtm;
1462f7e6a401SLaurent Vivier 
1463f7e6a401SLaurent Vivier     switch (nlh->nlmsg_type) {
1464f7e6a401SLaurent Vivier     case RTM_NEWLINK:
1465f7e6a401SLaurent Vivier     case RTM_DELLINK:
146665b261a6SLaurent Vivier     case RTM_SETLINK:
1467f536612dSLaurent Vivier     case RTM_GETLINK:
1468f7e6a401SLaurent Vivier         if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifi))) {
1469f7e6a401SLaurent Vivier             ifi = NLMSG_DATA(nlh);
1470f7e6a401SLaurent Vivier             ifi->ifi_type = tswap16(ifi->ifi_type);
1471f7e6a401SLaurent Vivier             ifi->ifi_index = tswap32(ifi->ifi_index);
1472f7e6a401SLaurent Vivier             ifi->ifi_flags = tswap32(ifi->ifi_flags);
1473f7e6a401SLaurent Vivier             ifi->ifi_change = tswap32(ifi->ifi_change);
1474f7e6a401SLaurent Vivier             target_to_host_link_rtattr(IFLA_RTA(ifi), nlh->nlmsg_len -
1475f7e6a401SLaurent Vivier                                        NLMSG_LENGTH(sizeof(*ifi)));
1476f7e6a401SLaurent Vivier         }
1477f7e6a401SLaurent Vivier         break;
1478f7e6a401SLaurent Vivier     case RTM_GETADDR:
1479f7e6a401SLaurent Vivier     case RTM_NEWADDR:
1480f7e6a401SLaurent Vivier     case RTM_DELADDR:
1481f7e6a401SLaurent Vivier         if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifa))) {
1482f7e6a401SLaurent Vivier             ifa = NLMSG_DATA(nlh);
1483f7e6a401SLaurent Vivier             ifa->ifa_index = tswap32(ifa->ifa_index);
1484f7e6a401SLaurent Vivier             target_to_host_addr_rtattr(IFA_RTA(ifa), nlh->nlmsg_len -
1485f7e6a401SLaurent Vivier                                        NLMSG_LENGTH(sizeof(*ifa)));
1486f7e6a401SLaurent Vivier         }
1487f7e6a401SLaurent Vivier         break;
1488f7e6a401SLaurent Vivier     case RTM_NEWROUTE:
1489f7e6a401SLaurent Vivier     case RTM_DELROUTE:
1490f536612dSLaurent Vivier     case RTM_GETROUTE:
1491f7e6a401SLaurent Vivier         if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*rtm))) {
1492f7e6a401SLaurent Vivier             rtm = NLMSG_DATA(nlh);
1493f7e6a401SLaurent Vivier             rtm->rtm_flags = tswap32(rtm->rtm_flags);
1494f7e6a401SLaurent Vivier             target_to_host_route_rtattr(RTM_RTA(rtm), nlh->nlmsg_len -
1495f7e6a401SLaurent Vivier                                         NLMSG_LENGTH(sizeof(*rtm)));
1496f7e6a401SLaurent Vivier         }
1497f7e6a401SLaurent Vivier         break;
1498f7e6a401SLaurent Vivier     default:
1499f7e6a401SLaurent Vivier         return -TARGET_EOPNOTSUPP;
1500f7e6a401SLaurent Vivier     }
1501f7e6a401SLaurent Vivier     return 0;
1502f7e6a401SLaurent Vivier }
1503f7e6a401SLaurent Vivier 
target_to_host_nlmsg_route(struct nlmsghdr * nlh,size_t len)1504f7e6a401SLaurent Vivier static abi_long target_to_host_nlmsg_route(struct nlmsghdr *nlh, size_t len)
1505f7e6a401SLaurent Vivier {
1506f7e6a401SLaurent Vivier     return target_to_host_for_each_nlmsg(nlh, len, target_to_host_data_route);
1507f7e6a401SLaurent Vivier }
1508f7e6a401SLaurent Vivier #endif /* CONFIG_RTNETLINK */
1509f7e6a401SLaurent Vivier 
host_to_target_data_audit(struct nlmsghdr * nlh)1510f7e6a401SLaurent Vivier static abi_long host_to_target_data_audit(struct nlmsghdr *nlh)
1511f7e6a401SLaurent Vivier {
1512f7e6a401SLaurent Vivier     switch (nlh->nlmsg_type) {
1513f7e6a401SLaurent Vivier     default:
151439be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown host audit message type %d\n",
1515f7e6a401SLaurent Vivier                       nlh->nlmsg_type);
1516f7e6a401SLaurent Vivier         return -TARGET_EINVAL;
1517f7e6a401SLaurent Vivier     }
1518f7e6a401SLaurent Vivier     return 0;
1519f7e6a401SLaurent Vivier }
1520f7e6a401SLaurent Vivier 
host_to_target_nlmsg_audit(struct nlmsghdr * nlh,size_t len)1521f7e6a401SLaurent Vivier static inline abi_long host_to_target_nlmsg_audit(struct nlmsghdr *nlh,
1522f7e6a401SLaurent Vivier                                                   size_t len)
1523f7e6a401SLaurent Vivier {
1524f7e6a401SLaurent Vivier     return host_to_target_for_each_nlmsg(nlh, len, host_to_target_data_audit);
1525f7e6a401SLaurent Vivier }
1526f7e6a401SLaurent Vivier 
target_to_host_data_audit(struct nlmsghdr * nlh)1527f7e6a401SLaurent Vivier static abi_long target_to_host_data_audit(struct nlmsghdr *nlh)
1528f7e6a401SLaurent Vivier {
1529f7e6a401SLaurent Vivier     switch (nlh->nlmsg_type) {
1530f7e6a401SLaurent Vivier     case AUDIT_USER:
1531f7e6a401SLaurent Vivier     case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
1532f7e6a401SLaurent Vivier     case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
1533f7e6a401SLaurent Vivier         break;
1534f7e6a401SLaurent Vivier     default:
153539be5350SJosh Kunz         qemu_log_mask(LOG_UNIMP, "Unknown target audit message type %d\n",
1536f7e6a401SLaurent Vivier                       nlh->nlmsg_type);
1537f7e6a401SLaurent Vivier         return -TARGET_EINVAL;
1538f7e6a401SLaurent Vivier     }
1539f7e6a401SLaurent Vivier 
1540f7e6a401SLaurent Vivier     return 0;
1541f7e6a401SLaurent Vivier }
1542f7e6a401SLaurent Vivier 
target_to_host_nlmsg_audit(struct nlmsghdr * nlh,size_t len)1543f7e6a401SLaurent Vivier static abi_long target_to_host_nlmsg_audit(struct nlmsghdr *nlh, size_t len)
1544f7e6a401SLaurent Vivier {
1545f7e6a401SLaurent Vivier     return target_to_host_for_each_nlmsg(nlh, len, target_to_host_data_audit);
1546f7e6a401SLaurent Vivier }
1547f7e6a401SLaurent Vivier 
packet_target_to_host_sockaddr(void * host_addr,abi_ulong target_addr,socklen_t len)1548f7e6a401SLaurent Vivier static abi_long packet_target_to_host_sockaddr(void *host_addr,
1549f7e6a401SLaurent Vivier                                                abi_ulong target_addr,
1550f7e6a401SLaurent Vivier                                                socklen_t len)
1551f7e6a401SLaurent Vivier {
1552f7e6a401SLaurent Vivier     struct sockaddr *addr = host_addr;
1553f7e6a401SLaurent Vivier     struct target_sockaddr *target_saddr;
1554f7e6a401SLaurent Vivier 
1555f7e6a401SLaurent Vivier     target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1556f7e6a401SLaurent Vivier     if (!target_saddr) {
1557f7e6a401SLaurent Vivier         return -TARGET_EFAULT;
1558f7e6a401SLaurent Vivier     }
1559f7e6a401SLaurent Vivier 
1560f7e6a401SLaurent Vivier     memcpy(addr, target_saddr, len);
1561f7e6a401SLaurent Vivier     addr->sa_family = tswap16(target_saddr->sa_family);
1562f7e6a401SLaurent Vivier     /* spkt_protocol is big-endian */
1563f7e6a401SLaurent Vivier 
1564f7e6a401SLaurent Vivier     unlock_user(target_saddr, target_addr, 0);
1565f7e6a401SLaurent Vivier     return 0;
1566f7e6a401SLaurent Vivier }
1567f7e6a401SLaurent Vivier 
1568f7e6a401SLaurent Vivier TargetFdTrans target_packet_trans = {
1569f7e6a401SLaurent Vivier     .target_to_host_addr = packet_target_to_host_sockaddr,
1570f7e6a401SLaurent Vivier };
1571f7e6a401SLaurent Vivier 
1572f7e6a401SLaurent Vivier #ifdef CONFIG_RTNETLINK
netlink_route_target_to_host(void * buf,size_t len)1573f7e6a401SLaurent Vivier static abi_long netlink_route_target_to_host(void *buf, size_t len)
1574f7e6a401SLaurent Vivier {
1575f7e6a401SLaurent Vivier     abi_long ret;
1576f7e6a401SLaurent Vivier 
1577f7e6a401SLaurent Vivier     ret = target_to_host_nlmsg_route(buf, len);
1578f7e6a401SLaurent Vivier     if (ret < 0) {
1579f7e6a401SLaurent Vivier         return ret;
1580f7e6a401SLaurent Vivier     }
1581f7e6a401SLaurent Vivier 
1582f7e6a401SLaurent Vivier     return len;
1583f7e6a401SLaurent Vivier }
1584f7e6a401SLaurent Vivier 
netlink_route_host_to_target(void * buf,size_t len)1585f7e6a401SLaurent Vivier static abi_long netlink_route_host_to_target(void *buf, size_t len)
1586f7e6a401SLaurent Vivier {
1587f7e6a401SLaurent Vivier     abi_long ret;
1588f7e6a401SLaurent Vivier 
1589f7e6a401SLaurent Vivier     ret = host_to_target_nlmsg_route(buf, len);
1590f7e6a401SLaurent Vivier     if (ret < 0) {
1591f7e6a401SLaurent Vivier         return ret;
1592f7e6a401SLaurent Vivier     }
1593f7e6a401SLaurent Vivier 
1594f7e6a401SLaurent Vivier     return len;
1595f7e6a401SLaurent Vivier }
1596f7e6a401SLaurent Vivier 
1597f7e6a401SLaurent Vivier TargetFdTrans target_netlink_route_trans = {
1598f7e6a401SLaurent Vivier     .target_to_host_data = netlink_route_target_to_host,
1599f7e6a401SLaurent Vivier     .host_to_target_data = netlink_route_host_to_target,
1600f7e6a401SLaurent Vivier };
1601f7e6a401SLaurent Vivier #endif /* CONFIG_RTNETLINK */
1602f7e6a401SLaurent Vivier 
netlink_audit_target_to_host(void * buf,size_t len)1603f7e6a401SLaurent Vivier static abi_long netlink_audit_target_to_host(void *buf, size_t len)
1604f7e6a401SLaurent Vivier {
1605f7e6a401SLaurent Vivier     abi_long ret;
1606f7e6a401SLaurent Vivier 
1607f7e6a401SLaurent Vivier     ret = target_to_host_nlmsg_audit(buf, len);
1608f7e6a401SLaurent Vivier     if (ret < 0) {
1609f7e6a401SLaurent Vivier         return ret;
1610f7e6a401SLaurent Vivier     }
1611f7e6a401SLaurent Vivier 
1612f7e6a401SLaurent Vivier     return len;
1613f7e6a401SLaurent Vivier }
1614f7e6a401SLaurent Vivier 
netlink_audit_host_to_target(void * buf,size_t len)1615f7e6a401SLaurent Vivier static abi_long netlink_audit_host_to_target(void *buf, size_t len)
1616f7e6a401SLaurent Vivier {
1617f7e6a401SLaurent Vivier     abi_long ret;
1618f7e6a401SLaurent Vivier 
1619f7e6a401SLaurent Vivier     ret = host_to_target_nlmsg_audit(buf, len);
1620f7e6a401SLaurent Vivier     if (ret < 0) {
1621f7e6a401SLaurent Vivier         return ret;
1622f7e6a401SLaurent Vivier     }
1623f7e6a401SLaurent Vivier 
1624f7e6a401SLaurent Vivier     return len;
1625f7e6a401SLaurent Vivier }
1626f7e6a401SLaurent Vivier 
1627f7e6a401SLaurent Vivier TargetFdTrans target_netlink_audit_trans = {
1628f7e6a401SLaurent Vivier     .target_to_host_data = netlink_audit_target_to_host,
1629f7e6a401SLaurent Vivier     .host_to_target_data = netlink_audit_host_to_target,
1630f7e6a401SLaurent Vivier };
1631f7e6a401SLaurent Vivier 
1632f7e6a401SLaurent Vivier /* signalfd siginfo conversion */
1633f7e6a401SLaurent Vivier 
1634f7e6a401SLaurent Vivier static void
host_to_target_signalfd_siginfo(struct signalfd_siginfo * tinfo,const struct signalfd_siginfo * info)1635f7e6a401SLaurent Vivier host_to_target_signalfd_siginfo(struct signalfd_siginfo *tinfo,
1636f7e6a401SLaurent Vivier                                 const struct signalfd_siginfo *info)
1637f7e6a401SLaurent Vivier {
1638f7e6a401SLaurent Vivier     int sig = host_to_target_signal(info->ssi_signo);
1639f7e6a401SLaurent Vivier 
1640f7e6a401SLaurent Vivier     /* linux/signalfd.h defines a ssi_addr_lsb
1641f7e6a401SLaurent Vivier      * not defined in sys/signalfd.h but used by some kernels
1642f7e6a401SLaurent Vivier      */
1643f7e6a401SLaurent Vivier 
1644f7e6a401SLaurent Vivier #ifdef BUS_MCEERR_AO
1645f7e6a401SLaurent Vivier     if (tinfo->ssi_signo == SIGBUS &&
1646f7e6a401SLaurent Vivier         (tinfo->ssi_code == BUS_MCEERR_AR ||
1647f7e6a401SLaurent Vivier          tinfo->ssi_code == BUS_MCEERR_AO)) {
1648f7e6a401SLaurent Vivier         uint16_t *ssi_addr_lsb = (uint16_t *)(&info->ssi_addr + 1);
1649f7e6a401SLaurent Vivier         uint16_t *tssi_addr_lsb = (uint16_t *)(&tinfo->ssi_addr + 1);
1650f7e6a401SLaurent Vivier         *tssi_addr_lsb = tswap16(*ssi_addr_lsb);
1651f7e6a401SLaurent Vivier     }
1652f7e6a401SLaurent Vivier #endif
1653f7e6a401SLaurent Vivier 
1654f7e6a401SLaurent Vivier     tinfo->ssi_signo = tswap32(sig);
1655f7e6a401SLaurent Vivier     tinfo->ssi_errno = tswap32(tinfo->ssi_errno);
1656f7e6a401SLaurent Vivier     tinfo->ssi_code = tswap32(info->ssi_code);
1657f7e6a401SLaurent Vivier     tinfo->ssi_pid = tswap32(info->ssi_pid);
1658f7e6a401SLaurent Vivier     tinfo->ssi_uid = tswap32(info->ssi_uid);
1659f7e6a401SLaurent Vivier     tinfo->ssi_fd = tswap32(info->ssi_fd);
1660f7e6a401SLaurent Vivier     tinfo->ssi_tid = tswap32(info->ssi_tid);
1661f7e6a401SLaurent Vivier     tinfo->ssi_band = tswap32(info->ssi_band);
1662f7e6a401SLaurent Vivier     tinfo->ssi_overrun = tswap32(info->ssi_overrun);
1663f7e6a401SLaurent Vivier     tinfo->ssi_trapno = tswap32(info->ssi_trapno);
1664f7e6a401SLaurent Vivier     tinfo->ssi_status = tswap32(info->ssi_status);
1665f7e6a401SLaurent Vivier     tinfo->ssi_int = tswap32(info->ssi_int);
1666f7e6a401SLaurent Vivier     tinfo->ssi_ptr = tswap64(info->ssi_ptr);
1667f7e6a401SLaurent Vivier     tinfo->ssi_utime = tswap64(info->ssi_utime);
1668f7e6a401SLaurent Vivier     tinfo->ssi_stime = tswap64(info->ssi_stime);
1669f7e6a401SLaurent Vivier     tinfo->ssi_addr = tswap64(info->ssi_addr);
1670f7e6a401SLaurent Vivier }
1671f7e6a401SLaurent Vivier 
host_to_target_data_signalfd(void * buf,size_t len)1672f7e6a401SLaurent Vivier static abi_long host_to_target_data_signalfd(void *buf, size_t len)
1673f7e6a401SLaurent Vivier {
1674f7e6a401SLaurent Vivier     int i;
1675f7e6a401SLaurent Vivier 
1676f7e6a401SLaurent Vivier     for (i = 0; i < len; i += sizeof(struct signalfd_siginfo)) {
1677f7e6a401SLaurent Vivier         host_to_target_signalfd_siginfo(buf + i, buf + i);
1678f7e6a401SLaurent Vivier     }
1679f7e6a401SLaurent Vivier 
1680f7e6a401SLaurent Vivier     return len;
1681f7e6a401SLaurent Vivier }
1682f7e6a401SLaurent Vivier 
1683f7e6a401SLaurent Vivier TargetFdTrans target_signalfd_trans = {
1684f7e6a401SLaurent Vivier     .host_to_target_data = host_to_target_data_signalfd,
1685f7e6a401SLaurent Vivier };
1686f7e6a401SLaurent Vivier 
swap_data_u64(void * buf,size_t len)1687d759a62bSMathis Marion static abi_long swap_data_u64(void *buf, size_t len)
1688f7e6a401SLaurent Vivier {
1689f7e6a401SLaurent Vivier     uint64_t *counter = buf;
1690f7e6a401SLaurent Vivier     int i;
1691f7e6a401SLaurent Vivier 
1692f7e6a401SLaurent Vivier     if (len < sizeof(uint64_t)) {
1693f7e6a401SLaurent Vivier         return -EINVAL;
1694f7e6a401SLaurent Vivier     }
1695f7e6a401SLaurent Vivier 
1696f7e6a401SLaurent Vivier     for (i = 0; i < len; i += sizeof(uint64_t)) {
1697f7e6a401SLaurent Vivier         *counter = tswap64(*counter);
1698f7e6a401SLaurent Vivier         counter++;
1699f7e6a401SLaurent Vivier     }
1700f7e6a401SLaurent Vivier 
1701f7e6a401SLaurent Vivier     return len;
1702f7e6a401SLaurent Vivier }
1703f7e6a401SLaurent Vivier 
1704f7e6a401SLaurent Vivier TargetFdTrans target_eventfd_trans = {
1705d759a62bSMathis Marion     .host_to_target_data = swap_data_u64,
1706d759a62bSMathis Marion     .target_to_host_data = swap_data_u64,
1707d759a62bSMathis Marion };
1708d759a62bSMathis Marion 
1709d759a62bSMathis Marion TargetFdTrans target_timerfd_trans = {
1710d759a62bSMathis Marion     .host_to_target_data = swap_data_u64,
1711f7e6a401SLaurent Vivier };
1712f7e6a401SLaurent Vivier 
171333f53ac5SPaul Brook #if defined(CONFIG_INOTIFY) && (defined(TARGET_NR_inotify_init) || \
171433f53ac5SPaul Brook         defined(TARGET_NR_inotify_init1))
host_to_target_data_inotify(void * buf,size_t len)1715f7e6a401SLaurent Vivier static abi_long host_to_target_data_inotify(void *buf, size_t len)
1716f7e6a401SLaurent Vivier {
1717f7e6a401SLaurent Vivier     struct inotify_event *ev;
1718f7e6a401SLaurent Vivier     int i;
1719f7e6a401SLaurent Vivier     uint32_t name_len;
1720f7e6a401SLaurent Vivier 
1721f7e6a401SLaurent Vivier     for (i = 0; i < len; i += sizeof(struct inotify_event) + name_len) {
1722f7e6a401SLaurent Vivier         ev = (struct inotify_event *)((char *)buf + i);
1723f7e6a401SLaurent Vivier         name_len = ev->len;
1724f7e6a401SLaurent Vivier 
1725f7e6a401SLaurent Vivier         ev->wd = tswap32(ev->wd);
1726f7e6a401SLaurent Vivier         ev->mask = tswap32(ev->mask);
1727f7e6a401SLaurent Vivier         ev->cookie = tswap32(ev->cookie);
1728f7e6a401SLaurent Vivier         ev->len = tswap32(name_len);
1729f7e6a401SLaurent Vivier     }
1730f7e6a401SLaurent Vivier 
1731f7e6a401SLaurent Vivier     return len;
1732f7e6a401SLaurent Vivier }
1733f7e6a401SLaurent Vivier 
1734f7e6a401SLaurent Vivier TargetFdTrans target_inotify_trans = {
1735f7e6a401SLaurent Vivier     .host_to_target_data = host_to_target_data_inotify,
1736f7e6a401SLaurent Vivier };
1737f7e6a401SLaurent Vivier #endif
1738