net_switch: Use old packet construction with no shared secret

This falls through to using 239.255.86.86 as the multicast address and
excluding a shared secret hash, if no shared secret has been entered.

This restores compatibility with QEMU’s `-netdev dgram` mode, as
suggested by @richardg867.
This commit is contained in:
Mike Swanson
2026-02-10 22:22:00 -08:00
parent 08154d6e72
commit 752bed01ce

View File

@@ -81,6 +81,7 @@ typedef struct net_switch_t {
net_switch_hostaddr_t *hostaddrs;
uint16_t port_out;
uint8_t secret_enabled;
uint8_t secret_hash[32];
uint8_t promisc;
union {
@@ -197,10 +198,12 @@ net_switch_add_hostaddr(net_switch_t *netswitch, net_switch_sockaddr_t *addr, ne
}
/* Join IPv4 multicast group. */
struct ip_mreq mreq = {
.imr_multiaddr = { .s_addr = htonl(SWITCH_MULTICAST_GROUP) },
.imr_interface = { .s_addr = hostaddr->addr.sin.sin_addr.s_addr }
};
struct ip_mreq mreq = { .imr_interface = { .s_addr = hostaddr->addr.sin.sin_addr.s_addr } };
if (netswitch->secret_enabled)
mreq.imr_multiaddr.s_addr = htonl(SWITCH_MULTICAST_GROUP);
else
mreq.imr_multiaddr.s_addr = htonl(SWITCH_MULTICAST_GROUP + 0x600); // 239.255.86.86
if (setsockopt(netswitch->socket_rx, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq)) < 0) {
netswitch_log("Network Switch: could not join multicast group on interface %s\n", buf);
goto broadcast;
@@ -386,24 +389,34 @@ net_switch_thread(void *priv)
if (!(net_cards_conf[netswitch->card->card_num].link_state & NET_LINK_DOWN)) {
for (int i = 0; i < packets; i++) {
int orig_len = netswitch->pkt_tx_v[i].len;
int send_len = orig_len + sizeof(netswitch->secret_hash);
/* Build header with secret hash */
int send_len = orig_len;
uint8_t augmented[sizeof(netswitch->secret_hash) + NET_MAX_FRAME];
uint8_t *hdr = augmented;
memcpy(hdr, netswitch->secret_hash, sizeof(netswitch->secret_hash));
memcpy(augmented + sizeof(netswitch->secret_hash),
netswitch->pkt_tx_v[i].data, orig_len);
if (netswitch->secret_enabled) {
send_len = orig_len + sizeof(netswitch->secret_hash);
/* Build header with secret hash */
uint8_t *hdr = augmented;
memcpy(hdr, netswitch->secret_hash, sizeof(netswitch->secret_hash));
memcpy(augmented + sizeof(netswitch->secret_hash),
netswitch->pkt_tx_v[i].data, orig_len);
}
#define MAC_FORMAT "(%02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X)"
#define MAC_FORMAT_NOSECRET_ARGS(p) (p)[6], (p)[7], (p)[8], (p)[9], (p)[10], (p)[11], (p)[0], (p)[1], (p)[2], (p)[3], (p)[4], (p)[5]
#define MAC_FORMAT_ARGS(p) (p)[38], (p)[39], (p)[40], (p)[41], (p)[42], (p)[43], (p)[32], (p)[33], (p)[34], (p)[35], (p)[36], (p)[37]
netswitch_log("Network Switch: sending %d-byte packet " MAC_FORMAT "\n",
netswitch->pkt_tx_v[i].len, MAC_FORMAT_ARGS(netswitch->pkt_tx_v[i].data));
netswitch->pkt_tx_v[i].len,
netswitch->secret_enabled ? MAC_FORMAT_ARGS(netswitch->pkt_tx_v[i].data)
: MAC_FORMAT_NOSECRET_ARGS(netswitch->pkt_tx_v[i].data));
/* Send through all known host interfaces. */
for (net_switch_hostaddr_t *hostaddr = netswitch->hostaddrs; hostaddr; hostaddr = hostaddr->next)
sendto(hostaddr->socket_tx, augmented, send_len, 0,
&hostaddr->addr_tx.sa, sizeof(hostaddr->addr_tx.sa));
if (netswitch->secret_enabled)
sendto(hostaddr->socket_tx, (char *)augmented, send_len, 0,
&hostaddr->addr_tx.sa, sizeof(hostaddr->addr_tx.sa));
else
sendto(hostaddr->socket_tx, (char *)netswitch->pkt_tx_v[i].data,
send_len, 0, &hostaddr->addr_tx.sa, sizeof(hostaddr->addr_tx.sa));
}
}
netswitch->during_tx = 0;
@@ -426,24 +439,32 @@ net_switch_thread(void *priv)
}
if (pfd[NET_EVENT_RX].revents & POLLIN) {
#endif
len = recv(netswitch->socket_rx, (char *) netswitch->pkt.data, NET_MAX_FRAME + sizeof(netswitch->secret_hash), 0);
if (len < sizeof(netswitch->secret_hash) + 12) {
netswitch_log("Network Switch: recv error (%d)\n", len);
continue;
}
if (netswitch->secret_enabled) {
len = recv(netswitch->socket_rx, (char *) netswitch->pkt.data, NET_MAX_FRAME + sizeof(netswitch->secret_hash), 0);
if (len < sizeof(netswitch->secret_hash) + 12) {
netswitch_log("Network Switch: recv error (%d)\n", len);
continue;
}
if (memcmp(netswitch->pkt.data, netswitch->secret_hash, sizeof(netswitch->secret_hash)) != 0) {
/* This packet contains a different secret hash, ignore it. */
continue;
if (memcmp(netswitch->pkt.data, netswitch->secret_hash, sizeof(netswitch->secret_hash)) != 0) {
/* This packet contains a different secret hash, ignore it. */
continue;
} else {
memmove(netswitch->pkt.data,
netswitch->pkt.data + sizeof(netswitch->secret_hash),
len - sizeof(netswitch->secret_hash));
len = len - sizeof(netswitch->secret_hash);
netswitch->pkt.len = len;
}
} else {
memmove(netswitch->pkt.data,
netswitch->pkt.data + sizeof(netswitch->secret_hash),
len - sizeof(netswitch->secret_hash));
len = len - sizeof(netswitch->secret_hash);
netswitch->pkt.len = len;
len = recv(netswitch->socket_rx, (char *) netswitch->pkt.data, NET_MAX_FRAME, 0);
if (len < 12) {
netswitch_log("Network Switch: recv error (%d)\n", len);
continue;
}
}
if ((AS_U64(netswitch->pkt.data[6]) & le64_to_cpu(0xffffffffffffULL)) == netswitch->mac_addr_u64) {
if ((AS_U64(netswitch->pkt.data[netswitch->secret_enabled ? 38 : 6]) & le64_to_cpu(0xffffffffffffULL)) == netswitch->mac_addr_u64) {
/* A packet we've sent has looped back, drop it. */
} else if (!(net_cards_conf[netswitch->card->card_num].link_state & NET_LINK_DOWN) && (netswitch->promisc || /* promiscuous mode? */
(netswitch->pkt.data[0] & 1) || /* broadcast packet? */
@@ -482,10 +503,13 @@ net_switch_init(const netcard_t *card, const uint8_t *mac_addr, void *priv, char
netswitch->card = (netcard_t *) card;
netswitch->promisc = !!netcard->promisc_mode;
{
if (netcard->secret[0] != '\0') {
uint8_t temp[32];
net_switch_secret_hash((const uint8_t *)netcard->secret, (uint8_t *) temp);
memcpy(netswitch->secret_hash, temp, 32);
netswitch->secret_enabled = 1;
} else {
netswitch->secret_enabled = 0;
}
/* Initialize receive socket. */