diff options
Diffstat (limited to 'linux-user/fd-trans.c')
-rw-r--r-- | linux-user/fd-trans.c | 169 |
1 files changed, 160 insertions, 9 deletions
diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index c04a97c..f83d1f7 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -25,12 +25,32 @@ #ifdef CONFIG_RTNETLINK #include <linux/rtnetlink.h> #include <linux/if_bridge.h> +#include <linux/neighbour.h> #endif #include "qemu.h" #include "user-internals.h" #include "fd-trans.h" #include "signal-common.h" +#define NDM_RTA(r) ((struct rtattr*)(((char*)(r)) + \ + NLMSG_ALIGN(sizeof(struct ndmsg)))) + +enum { + QEMU_IFA_UNSPEC, + QEMU_IFA_ADDRESS, + QEMU_IFA_LOCAL, + QEMU_IFA_LABEL, + QEMU_IFA_BROADCAST, + QEMU_IFA_ANYCAST, + QEMU_IFA_CACHEINFO, + QEMU_IFA_MULTICAST, + QEMU_IFA_FLAGS, + QEMU_IFA_RT_PRIORITY, + QEMU_IFA_TARGET_NETNSID, + QEMU_IFA_PROTO, + QEMU__IFA__MAX, +}; + enum { QEMU_IFLA_BR_UNSPEC, QEMU_IFLA_BR_FORWARD_DELAY, @@ -141,6 +161,14 @@ enum { QEMU_IFLA_PROTO_DOWN_REASON, QEMU_IFLA_PARENT_DEV_NAME, QEMU_IFLA_PARENT_DEV_BUS_NAME, + QEMU_IFLA_GRO_MAX_SIZE, + QEMU_IFLA_TSO_MAX_SIZE, + QEMU_IFLA_TSO_MAX_SEGS, + QEMU_IFLA_ALLMULTI, + QEMU_IFLA_DEVLINK_PORT, + QEMU_IFLA_GSO_IPV4_MAX_SIZE, + QEMU_IFLA_GRO_IPV4_MAX_SIZE, + QEMU_IFLA_DPLL_PIN, QEMU___IFLA_MAX }; @@ -982,6 +1010,22 @@ static abi_long host_to_target_data_vfinfo_nlattr(struct nlattr *nlattr, return 0; } +static abi_long host_to_target_data_prop_nlattr(struct nlattr *nlattr, + void *context) +{ + switch (nlattr->nla_type) { + /* string */ + case QEMU_IFLA_ALT_IFNAME: + break; + default: + qemu_log_mask(LOG_UNIMP, "Unknown host PROP type: %d\n", + nlattr->nla_type); + break; + } + return 0; +} + + static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) { uint32_t *u32; @@ -990,7 +1034,7 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) struct rtnl_link_ifmap *map; struct linkinfo_context li_context; - switch (rtattr->rta_type) { + switch (rtattr->rta_type & NLA_TYPE_MASK) { /* binary stream */ case QEMU_IFLA_ADDRESS: case QEMU_IFLA_BROADCAST: @@ -1028,6 +1072,12 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) case QEMU_IFLA_CARRIER_DOWN_COUNT: case QEMU_IFLA_MIN_MTU: case QEMU_IFLA_MAX_MTU: + case QEMU_IFLA_GRO_MAX_SIZE: + case QEMU_IFLA_TSO_MAX_SIZE: + case QEMU_IFLA_TSO_MAX_SEGS: + case QEMU_IFLA_ALLMULTI: + case QEMU_IFLA_GSO_IPV4_MAX_SIZE: + case QEMU_IFLA_GRO_IPV4_MAX_SIZE: u32 = RTA_DATA(rtattr); *u32 = tswap32(*u32); break; @@ -1123,6 +1173,10 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len, NULL, host_to_target_data_vfinfo_nlattr); + case QEMU_IFLA_PROP_LIST: + return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len, + NULL, + host_to_target_data_prop_nlattr); default: qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA type: %d\n", rtattr->rta_type); @@ -1138,20 +1192,21 @@ static abi_long host_to_target_data_addr_rtattr(struct rtattr *rtattr) switch (rtattr->rta_type) { /* binary: depends on family type */ - case IFA_ADDRESS: - case IFA_LOCAL: + case QEMU_IFA_ADDRESS: + case QEMU_IFA_LOCAL: + case QEMU_IFA_PROTO: break; /* string */ - case IFA_LABEL: + case QEMU_IFA_LABEL: break; /* u32 */ - case IFA_FLAGS: - case IFA_BROADCAST: + case QEMU_IFA_FLAGS: + case QEMU_IFA_BROADCAST: u32 = RTA_DATA(rtattr); *u32 = tswap32(*u32); break; /* struct ifa_cacheinfo */ - case IFA_CACHEINFO: + case QEMU_IFA_CACHEINFO: ci = RTA_DATA(rtattr); ci->ifa_prefered = tswap32(ci->ifa_prefered); ci->ifa_valid = tswap32(ci->ifa_valid); @@ -1209,6 +1264,35 @@ static abi_long host_to_target_data_route_rtattr(struct rtattr *rtattr) return 0; } +static abi_long host_to_target_data_neigh_rtattr(struct rtattr *rtattr) +{ + struct nda_cacheinfo *ndac; + uint32_t *u32; + + switch (rtattr->rta_type) { + case NDA_UNSPEC: + case NDA_DST: + case NDA_LLADDR: + break; + case NDA_PROBES: + u32 = RTA_DATA(rtattr); + *u32 = tswap32(*u32); + break; + case NDA_CACHEINFO: + ndac = RTA_DATA(rtattr); + ndac->ndm_confirmed = tswap32(ndac->ndm_confirmed); + ndac->ndm_used = tswap32(ndac->ndm_used); + ndac->ndm_updated = tswap32(ndac->ndm_updated); + ndac->ndm_refcnt = tswap32(ndac->ndm_refcnt); + break; + default: + qemu_log_mask(LOG_UNIMP, "Unknown host to target NEIGH type: %d\n", + rtattr->rta_type); + break; + } + return 0; +} + static abi_long host_to_target_link_rtattr(struct rtattr *rtattr, uint32_t rtattr_len) { @@ -1230,12 +1314,20 @@ static abi_long host_to_target_route_rtattr(struct rtattr *rtattr, host_to_target_data_route_rtattr); } +static abi_long host_to_target_neigh_rtattr(struct rtattr *rtattr, + uint32_t rtattr_len) +{ + return host_to_target_for_each_rtattr(rtattr, rtattr_len, + host_to_target_data_neigh_rtattr); +} + static abi_long host_to_target_data_route(struct nlmsghdr *nlh) { uint32_t nlmsg_len; struct ifinfomsg *ifi; struct ifaddrmsg *ifa; struct rtmsg *rtm; + struct ndmsg *ndm; nlmsg_len = nlh->nlmsg_len; switch (nlh->nlmsg_type) { @@ -1262,6 +1354,17 @@ static abi_long host_to_target_data_route(struct nlmsghdr *nlh) nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); } break; + case RTM_NEWNEIGH: + case RTM_DELNEIGH: + case RTM_GETNEIGH: + if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ndm))) { + ndm = NLMSG_DATA(nlh); + ndm->ndm_ifindex = tswap32(ndm->ndm_ifindex); + ndm->ndm_state = tswap16(ndm->ndm_state); + host_to_target_neigh_rtattr(NDM_RTA(ndm), + nlmsg_len - NLMSG_LENGTH(sizeof(*ndm))); + } + break; case RTM_NEWROUTE: case RTM_DELROUTE: case RTM_GETROUTE: @@ -1398,8 +1501,8 @@ static abi_long target_to_host_data_addr_rtattr(struct rtattr *rtattr) { switch (rtattr->rta_type) { /* binary: depends on family type */ - case IFA_LOCAL: - case IFA_ADDRESS: + case QEMU_IFA_LOCAL: + case QEMU_IFA_ADDRESS: break; default: qemu_log_mask(LOG_UNIMP, "Unknown target IFA type: %d\n", @@ -1409,6 +1512,35 @@ static abi_long target_to_host_data_addr_rtattr(struct rtattr *rtattr) return 0; } +static abi_long target_to_host_data_neigh_rtattr(struct rtattr *rtattr) +{ + struct nda_cacheinfo *ndac; + uint32_t *u32; + + switch (rtattr->rta_type) { + case NDA_UNSPEC: + case NDA_DST: + case NDA_LLADDR: + break; + case NDA_PROBES: + u32 = RTA_DATA(rtattr); + *u32 = tswap32(*u32); + break; + case NDA_CACHEINFO: + ndac = RTA_DATA(rtattr); + ndac->ndm_confirmed = tswap32(ndac->ndm_confirmed); + ndac->ndm_used = tswap32(ndac->ndm_used); + ndac->ndm_updated = tswap32(ndac->ndm_updated); + ndac->ndm_refcnt = tswap32(ndac->ndm_refcnt); + break; + default: + qemu_log_mask(LOG_UNIMP, "Unknown target NEIGH type: %d\n", + rtattr->rta_type); + break; + } + return 0; +} + static abi_long target_to_host_data_route_rtattr(struct rtattr *rtattr) { uint32_t *u32; @@ -1447,6 +1579,13 @@ static void target_to_host_addr_rtattr(struct rtattr *rtattr, target_to_host_data_addr_rtattr); } +static void target_to_host_neigh_rtattr(struct rtattr *rtattr, + uint32_t rtattr_len) +{ + target_to_host_for_each_rtattr(rtattr, rtattr_len, + target_to_host_data_neigh_rtattr); +} + static void target_to_host_route_rtattr(struct rtattr *rtattr, uint32_t rtattr_len) { @@ -1459,6 +1598,7 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh) struct ifinfomsg *ifi; struct ifaddrmsg *ifa; struct rtmsg *rtm; + struct ndmsg *ndm; switch (nlh->nlmsg_type) { case RTM_NEWLINK: @@ -1485,6 +1625,17 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh) NLMSG_LENGTH(sizeof(*ifa))); } break; + case RTM_NEWNEIGH: + case RTM_DELNEIGH: + case RTM_GETNEIGH: + if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ndm))) { + ndm = NLMSG_DATA(nlh); + ndm->ndm_ifindex = tswap32(ndm->ndm_ifindex); + ndm->ndm_state = tswap16(ndm->ndm_state); + target_to_host_neigh_rtattr(NDM_RTA(ndm), nlh->nlmsg_len - + NLMSG_LENGTH(sizeof(*ndm))); + } + break; case RTM_NEWROUTE: case RTM_DELROUTE: case RTM_GETROUTE: |