Skip to content

Commit ed73437

Browse files
committed
Merge tag 'linux-user-fix-gupnp-pull-request' of https://github.com/hdeller/qemu-hppa into staging
linux-user: Add support for various missing netlink sockopt entries Add missing sockopt calls and thus fix building the debian gupnp package in a chroot. This fixes debian bug report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1044651 Signed-off-by: Helge Deller <deller@gmx.de> # -----BEGIN PGP SIGNATURE----- # # iHUEABYKAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCZ5OPdwAKCRD3ErUQojoP # X9EWAP0ZvoDehmNzgWMlUpWT+d4O06kMsrDsi+tRddUUSJgp4wEAuuycr4go4b9b # 6xLDLr81C7MFEGsztGcRVhPwVdDJxAU= # =Lw8U # -----END PGP SIGNATURE----- # gpg: Signature made Fri 24 Jan 2025 08:02:47 EST # gpg: using EDDSA key BCE9123E1AD29F07C049BBDEF712B510A23A0F5F # gpg: Good signature from "Helge Deller <deller@gmx.de>" [unknown] # gpg: aka "Helge Deller <deller@kernel.org>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 4544 8228 2CD9 10DB EF3D 25F8 3E5F 3D04 A7A2 4603 # Subkey fingerprint: BCE9 123E 1AD2 9F07 C049 BBDE F712 B510 A23A 0F5F * tag 'linux-user-fix-gupnp-pull-request' of https://github.com/hdeller/qemu-hppa: linux-user: netlink: Add missing QEMU_IFLA entries linux-user: netlink: add netlink neighbour emulation linux-user: netlink: Add emulation of IP_MULTICAST_IF linux-user: netlink: Add IP_PKTINFO cmsg parsing linux-user: Use unique error messages for cmsg parsing linux-user: netlink: Add missing IFA_PROTO to host_to_target_data_addr_rtattr() Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2 parents 8f9cb50 + 3719acc commit ed73437

File tree

3 files changed

+192
-17
lines changed

3 files changed

+192
-17
lines changed

linux-user/fd-trans.c

Lines changed: 160 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,32 @@
2525
#ifdef CONFIG_RTNETLINK
2626
#include <linux/rtnetlink.h>
2727
#include <linux/if_bridge.h>
28+
#include <linux/neighbour.h>
2829
#endif
2930
#include "qemu.h"
3031
#include "user-internals.h"
3132
#include "fd-trans.h"
3233
#include "signal-common.h"
3334

35+
#define NDM_RTA(r) ((struct rtattr*)(((char*)(r)) + \
36+
NLMSG_ALIGN(sizeof(struct ndmsg))))
37+
38+
enum {
39+
QEMU_IFA_UNSPEC,
40+
QEMU_IFA_ADDRESS,
41+
QEMU_IFA_LOCAL,
42+
QEMU_IFA_LABEL,
43+
QEMU_IFA_BROADCAST,
44+
QEMU_IFA_ANYCAST,
45+
QEMU_IFA_CACHEINFO,
46+
QEMU_IFA_MULTICAST,
47+
QEMU_IFA_FLAGS,
48+
QEMU_IFA_RT_PRIORITY,
49+
QEMU_IFA_TARGET_NETNSID,
50+
QEMU_IFA_PROTO,
51+
QEMU__IFA__MAX,
52+
};
53+
3454
enum {
3555
QEMU_IFLA_BR_UNSPEC,
3656
QEMU_IFLA_BR_FORWARD_DELAY,
@@ -141,6 +161,14 @@ enum {
141161
QEMU_IFLA_PROTO_DOWN_REASON,
142162
QEMU_IFLA_PARENT_DEV_NAME,
143163
QEMU_IFLA_PARENT_DEV_BUS_NAME,
164+
QEMU_IFLA_GRO_MAX_SIZE,
165+
QEMU_IFLA_TSO_MAX_SIZE,
166+
QEMU_IFLA_TSO_MAX_SEGS,
167+
QEMU_IFLA_ALLMULTI,
168+
QEMU_IFLA_DEVLINK_PORT,
169+
QEMU_IFLA_GSO_IPV4_MAX_SIZE,
170+
QEMU_IFLA_GRO_IPV4_MAX_SIZE,
171+
QEMU_IFLA_DPLL_PIN,
144172
QEMU___IFLA_MAX
145173
};
146174

@@ -982,6 +1010,22 @@ static abi_long host_to_target_data_vfinfo_nlattr(struct nlattr *nlattr,
9821010
return 0;
9831011
}
9841012

1013+
static abi_long host_to_target_data_prop_nlattr(struct nlattr *nlattr,
1014+
void *context)
1015+
{
1016+
switch (nlattr->nla_type) {
1017+
/* string */
1018+
case QEMU_IFLA_ALT_IFNAME:
1019+
break;
1020+
default:
1021+
qemu_log_mask(LOG_UNIMP, "Unknown host PROP type: %d\n",
1022+
nlattr->nla_type);
1023+
break;
1024+
}
1025+
return 0;
1026+
}
1027+
1028+
9851029
static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
9861030
{
9871031
uint32_t *u32;
@@ -990,7 +1034,7 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
9901034
struct rtnl_link_ifmap *map;
9911035
struct linkinfo_context li_context;
9921036

993-
switch (rtattr->rta_type) {
1037+
switch (rtattr->rta_type & NLA_TYPE_MASK) {
9941038
/* binary stream */
9951039
case QEMU_IFLA_ADDRESS:
9961040
case QEMU_IFLA_BROADCAST:
@@ -1028,6 +1072,12 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
10281072
case QEMU_IFLA_CARRIER_DOWN_COUNT:
10291073
case QEMU_IFLA_MIN_MTU:
10301074
case QEMU_IFLA_MAX_MTU:
1075+
case QEMU_IFLA_GRO_MAX_SIZE:
1076+
case QEMU_IFLA_TSO_MAX_SIZE:
1077+
case QEMU_IFLA_TSO_MAX_SEGS:
1078+
case QEMU_IFLA_ALLMULTI:
1079+
case QEMU_IFLA_GSO_IPV4_MAX_SIZE:
1080+
case QEMU_IFLA_GRO_IPV4_MAX_SIZE:
10311081
u32 = RTA_DATA(rtattr);
10321082
*u32 = tswap32(*u32);
10331083
break;
@@ -1123,6 +1173,10 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
11231173
return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
11241174
NULL,
11251175
host_to_target_data_vfinfo_nlattr);
1176+
case QEMU_IFLA_PROP_LIST:
1177+
return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
1178+
NULL,
1179+
host_to_target_data_prop_nlattr);
11261180
default:
11271181
qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA type: %d\n",
11281182
rtattr->rta_type);
@@ -1138,20 +1192,21 @@ static abi_long host_to_target_data_addr_rtattr(struct rtattr *rtattr)
11381192

11391193
switch (rtattr->rta_type) {
11401194
/* binary: depends on family type */
1141-
case IFA_ADDRESS:
1142-
case IFA_LOCAL:
1195+
case QEMU_IFA_ADDRESS:
1196+
case QEMU_IFA_LOCAL:
1197+
case QEMU_IFA_PROTO:
11431198
break;
11441199
/* string */
1145-
case IFA_LABEL:
1200+
case QEMU_IFA_LABEL:
11461201
break;
11471202
/* u32 */
1148-
case IFA_FLAGS:
1149-
case IFA_BROADCAST:
1203+
case QEMU_IFA_FLAGS:
1204+
case QEMU_IFA_BROADCAST:
11501205
u32 = RTA_DATA(rtattr);
11511206
*u32 = tswap32(*u32);
11521207
break;
11531208
/* struct ifa_cacheinfo */
1154-
case IFA_CACHEINFO:
1209+
case QEMU_IFA_CACHEINFO:
11551210
ci = RTA_DATA(rtattr);
11561211
ci->ifa_prefered = tswap32(ci->ifa_prefered);
11571212
ci->ifa_valid = tswap32(ci->ifa_valid);
@@ -1209,6 +1264,35 @@ static abi_long host_to_target_data_route_rtattr(struct rtattr *rtattr)
12091264
return 0;
12101265
}
12111266

1267+
static abi_long host_to_target_data_neigh_rtattr(struct rtattr *rtattr)
1268+
{
1269+
struct nda_cacheinfo *ndac;
1270+
uint32_t *u32;
1271+
1272+
switch (rtattr->rta_type) {
1273+
case NDA_UNSPEC:
1274+
case NDA_DST:
1275+
case NDA_LLADDR:
1276+
break;
1277+
case NDA_PROBES:
1278+
u32 = RTA_DATA(rtattr);
1279+
*u32 = tswap32(*u32);
1280+
break;
1281+
case NDA_CACHEINFO:
1282+
ndac = RTA_DATA(rtattr);
1283+
ndac->ndm_confirmed = tswap32(ndac->ndm_confirmed);
1284+
ndac->ndm_used = tswap32(ndac->ndm_used);
1285+
ndac->ndm_updated = tswap32(ndac->ndm_updated);
1286+
ndac->ndm_refcnt = tswap32(ndac->ndm_refcnt);
1287+
break;
1288+
default:
1289+
qemu_log_mask(LOG_UNIMP, "Unknown host to target NEIGH type: %d\n",
1290+
rtattr->rta_type);
1291+
break;
1292+
}
1293+
return 0;
1294+
}
1295+
12121296
static abi_long host_to_target_link_rtattr(struct rtattr *rtattr,
12131297
uint32_t rtattr_len)
12141298
{
@@ -1230,12 +1314,20 @@ static abi_long host_to_target_route_rtattr(struct rtattr *rtattr,
12301314
host_to_target_data_route_rtattr);
12311315
}
12321316

1317+
static abi_long host_to_target_neigh_rtattr(struct rtattr *rtattr,
1318+
uint32_t rtattr_len)
1319+
{
1320+
return host_to_target_for_each_rtattr(rtattr, rtattr_len,
1321+
host_to_target_data_neigh_rtattr);
1322+
}
1323+
12331324
static abi_long host_to_target_data_route(struct nlmsghdr *nlh)
12341325
{
12351326
uint32_t nlmsg_len;
12361327
struct ifinfomsg *ifi;
12371328
struct ifaddrmsg *ifa;
12381329
struct rtmsg *rtm;
1330+
struct ndmsg *ndm;
12391331

12401332
nlmsg_len = nlh->nlmsg_len;
12411333
switch (nlh->nlmsg_type) {
@@ -1262,6 +1354,17 @@ static abi_long host_to_target_data_route(struct nlmsghdr *nlh)
12621354
nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
12631355
}
12641356
break;
1357+
case RTM_NEWNEIGH:
1358+
case RTM_DELNEIGH:
1359+
case RTM_GETNEIGH:
1360+
if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ndm))) {
1361+
ndm = NLMSG_DATA(nlh);
1362+
ndm->ndm_ifindex = tswap32(ndm->ndm_ifindex);
1363+
ndm->ndm_state = tswap16(ndm->ndm_state);
1364+
host_to_target_neigh_rtattr(NDM_RTA(ndm),
1365+
nlmsg_len - NLMSG_LENGTH(sizeof(*ndm)));
1366+
}
1367+
break;
12651368
case RTM_NEWROUTE:
12661369
case RTM_DELROUTE:
12671370
case RTM_GETROUTE:
@@ -1398,8 +1501,8 @@ static abi_long target_to_host_data_addr_rtattr(struct rtattr *rtattr)
13981501
{
13991502
switch (rtattr->rta_type) {
14001503
/* binary: depends on family type */
1401-
case IFA_LOCAL:
1402-
case IFA_ADDRESS:
1504+
case QEMU_IFA_LOCAL:
1505+
case QEMU_IFA_ADDRESS:
14031506
break;
14041507
default:
14051508
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)
14091512
return 0;
14101513
}
14111514

1515+
static abi_long target_to_host_data_neigh_rtattr(struct rtattr *rtattr)
1516+
{
1517+
struct nda_cacheinfo *ndac;
1518+
uint32_t *u32;
1519+
1520+
switch (rtattr->rta_type) {
1521+
case NDA_UNSPEC:
1522+
case NDA_DST:
1523+
case NDA_LLADDR:
1524+
break;
1525+
case NDA_PROBES:
1526+
u32 = RTA_DATA(rtattr);
1527+
*u32 = tswap32(*u32);
1528+
break;
1529+
case NDA_CACHEINFO:
1530+
ndac = RTA_DATA(rtattr);
1531+
ndac->ndm_confirmed = tswap32(ndac->ndm_confirmed);
1532+
ndac->ndm_used = tswap32(ndac->ndm_used);
1533+
ndac->ndm_updated = tswap32(ndac->ndm_updated);
1534+
ndac->ndm_refcnt = tswap32(ndac->ndm_refcnt);
1535+
break;
1536+
default:
1537+
qemu_log_mask(LOG_UNIMP, "Unknown target NEIGH type: %d\n",
1538+
rtattr->rta_type);
1539+
break;
1540+
}
1541+
return 0;
1542+
}
1543+
14121544
static abi_long target_to_host_data_route_rtattr(struct rtattr *rtattr)
14131545
{
14141546
uint32_t *u32;
@@ -1447,6 +1579,13 @@ static void target_to_host_addr_rtattr(struct rtattr *rtattr,
14471579
target_to_host_data_addr_rtattr);
14481580
}
14491581

1582+
static void target_to_host_neigh_rtattr(struct rtattr *rtattr,
1583+
uint32_t rtattr_len)
1584+
{
1585+
target_to_host_for_each_rtattr(rtattr, rtattr_len,
1586+
target_to_host_data_neigh_rtattr);
1587+
}
1588+
14501589
static void target_to_host_route_rtattr(struct rtattr *rtattr,
14511590
uint32_t rtattr_len)
14521591
{
@@ -1459,6 +1598,7 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh)
14591598
struct ifinfomsg *ifi;
14601599
struct ifaddrmsg *ifa;
14611600
struct rtmsg *rtm;
1601+
struct ndmsg *ndm;
14621602

14631603
switch (nlh->nlmsg_type) {
14641604
case RTM_NEWLINK:
@@ -1485,6 +1625,17 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh)
14851625
NLMSG_LENGTH(sizeof(*ifa)));
14861626
}
14871627
break;
1628+
case RTM_NEWNEIGH:
1629+
case RTM_DELNEIGH:
1630+
case RTM_GETNEIGH:
1631+
if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ndm))) {
1632+
ndm = NLMSG_DATA(nlh);
1633+
ndm->ndm_ifindex = tswap32(ndm->ndm_ifindex);
1634+
ndm->ndm_state = tswap16(ndm->ndm_state);
1635+
target_to_host_neigh_rtattr(NDM_RTA(ndm), nlh->nlmsg_len -
1636+
NLMSG_LENGTH(sizeof(*ndm)));
1637+
}
1638+
break;
14881639
case RTM_NEWROUTE:
14891640
case RTM_DELROUTE:
14901641
case RTM_GETROUTE:

linux-user/syscall.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,7 +1827,7 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
18271827
*dst = tswap32(*dst);
18281828
}
18291829
} else {
1830-
qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
1830+
qemu_log_mask(LOG_UNIMP, "Unsupported target ancillary data: %d/%d\n",
18311831
cmsg->cmsg_level, cmsg->cmsg_type);
18321832
memcpy(data, target_data, len);
18331833
}
@@ -1998,6 +1998,16 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
19981998
(void *) &errh->offender, sizeof(errh->offender));
19991999
break;
20002000
}
2001+
case IP_PKTINFO:
2002+
{
2003+
struct in_pktinfo *pkti = data;
2004+
struct target_in_pktinfo *target_pi = target_data;
2005+
2006+
__put_user(pkti->ipi_ifindex, &target_pi->ipi_ifindex);
2007+
target_pi->ipi_spec_dst.s_addr = pkti->ipi_spec_dst.s_addr;
2008+
target_pi->ipi_addr.s_addr = pkti->ipi_addr.s_addr;
2009+
break;
2010+
}
20012011
default:
20022012
goto unimplemented;
20032013
}
@@ -2049,7 +2059,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
20492059

20502060
default:
20512061
unimplemented:
2052-
qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
2062+
qemu_log_mask(LOG_UNIMP, "Unsupported host ancillary data: %d/%d\n",
20532063
cmsg->cmsg_level, cmsg->cmsg_type);
20542064
memcpy(target_data, data, MIN(len, tgt_len));
20552065
if (tgt_len > len) {
@@ -2120,16 +2130,23 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
21202130
}
21212131
ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
21222132
break;
2133+
case IP_MULTICAST_IF:
21232134
case IP_ADD_MEMBERSHIP:
21242135
case IP_DROP_MEMBERSHIP:
21252136
{
21262137
struct ip_mreqn ip_mreq;
21272138
struct target_ip_mreqn *target_smreqn;
2139+
int min_size;
21282140

21292141
QEMU_BUILD_BUG_ON(sizeof(struct ip_mreq) !=
21302142
sizeof(struct target_ip_mreq));
21312143

2132-
if (optlen < sizeof (struct target_ip_mreq) ||
2144+
if (optname == IP_MULTICAST_IF) {
2145+
min_size = sizeof(struct in_addr);
2146+
} else {
2147+
min_size = sizeof(struct target_ip_mreq);
2148+
}
2149+
if (optlen < min_size ||
21332150
optlen > sizeof (struct target_ip_mreqn)) {
21342151
return -TARGET_EINVAL;
21352152
}
@@ -2139,13 +2156,14 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
21392156
return -TARGET_EFAULT;
21402157
}
21412158
ip_mreq.imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
2142-
ip_mreq.imr_address.s_addr = target_smreqn->imr_address.s_addr;
2143-
if (optlen == sizeof(struct target_ip_mreqn)) {
2144-
ip_mreq.imr_ifindex = tswapal(target_smreqn->imr_ifindex);
2145-
optlen = sizeof(struct ip_mreqn);
2159+
if (optlen >= sizeof(struct target_ip_mreq)) {
2160+
ip_mreq.imr_address.s_addr = target_smreqn->imr_address.s_addr;
2161+
if (optlen >= sizeof(struct target_ip_mreqn)) {
2162+
__put_user(target_smreqn->imr_ifindex, &ip_mreq.imr_ifindex);
2163+
optlen = sizeof(struct ip_mreqn);
2164+
}
21462165
}
21472166
unlock_user(target_smreqn, optval_addr, 0);
2148-
21492167
ret = get_errno(setsockopt(sockfd, level, optname, &ip_mreq, optlen));
21502168
break;
21512169
}

linux-user/syscall_defs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2622,6 +2622,12 @@ struct target_ucred {
26222622
abi_uint gid;
26232623
};
26242624

2625+
struct target_in_pktinfo {
2626+
abi_int ipi_ifindex;
2627+
struct target_in_addr ipi_spec_dst;
2628+
struct target_in_addr ipi_addr;
2629+
};
2630+
26252631
typedef abi_int target_timer_t;
26262632

26272633
#define TARGET_SIGEV_MAX_SIZE 64

0 commit comments

Comments
 (0)