From cc9a83155dde604020b4b4b4ad2926d5924b1375 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 20 Jan 2025 22:22:31 +0100 Subject: [PATCH] linux-user: netlink: add netlink neighbour emulation Fixes various warnings in the testsuite while building gupnp: gssdp-net-DEBUG: Failed to send netlink message: Operation not supported gupnp-context-DEBUG: Mismatch between host header and host IP (example.com, expected: 127.0.0.1) gupnp-context-DEBUG: Mismatch between host header and host port (80, expected 4711) gupnp-context-DEBUG: Mismatch between host header and host IP (192.168.1.2, expected: 127.0.0.1) gupnp-context-DEBUG: Mismatch between host header and host IP (fe80::01, expected: 127.0.0.1) gupnp-context-DEBUG: Mismatch between host header and host port (80, expected 4711) gupnp-context-DEBUG: Failed to parse HOST header from request: Invalid IPv6 address ?[fe80::01%1]? in URI gupnp-context-DEBUG: Failed to parse HOST header from request: Invalid IPv6 address ?[fe80::01%eth0]? in URI gupnp-context-DEBUG: Failed to parse HOST header from request: Could not parse port ?:1? in URI gupnp-context-DEBUG: Mismatch between host header and host IP (example.com, expected: ::1) gupnp-context-DEBUG: Mismatch between host header and host port (80, expected 4711) gupnp-context-DEBUG: Mismatch between host header and host IP (example.com, expected: ::1) gupnp-context-DEBUG: Mismatch between host header and host port (80, expected 4711) gupnp-context-DEBUG: Mismatch between host header and host IP (example.com, expected: ::1) Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier --- linux-user/fd-trans.c | 100 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index 2e714c8e56..621e2248b4 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -25,12 +25,16 @@ #ifdef CONFIG_RTNETLINK #include #include +#include #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, @@ -1226,6 +1230,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) { @@ -1247,12 +1280,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) { @@ -1279,6 +1320,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: @@ -1426,6 +1478,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; @@ -1464,6 +1545,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) { @@ -1476,6 +1564,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: @@ -1502,6 +1591,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: -- 2.30.2