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