blob: bdede498479f870220f8e8d3d0038860240a42e4 [file]
/* SPDX-License-Identifier: BSD-3-Clause */
#include "slirp.h"
static unsigned int replies;
static slirp_ssize_t send_packet(const void *buf, size_t len, void *opaque)
{
const struct ethhdr *eth = buf;
if (eth->h_proto == htons(ETH_P_ARP)) {
replies++;
}
return len;
}
static SlirpCb callbacks = { .send_packet = send_packet };
static void arp_request(Slirp *s, struct in_addr target)
{
uint8_t packet[sizeof(struct ethhdr) + sizeof(struct slirp_arphdr)] = { 0 };
struct ethhdr *eth = (struct ethhdr *)packet;
struct slirp_arphdr *arp = (struct slirp_arphdr *)(eth + 1);
memset(eth->h_dest, 0xff, ETH_ALEN);
eth->h_source[0] = 0x52;
eth->h_source[5] = 1;
eth->h_proto = htons(ETH_P_ARP);
arp->ar_hrd = htons(1);
arp->ar_pro = htons(ETH_P_IP);
arp->ar_hln = ETH_ALEN;
arp->ar_pln = 4;
arp->ar_op = htons(ARPOP_REQUEST);
memcpy(arp->ar_sha, eth->h_source, ETH_ALEN);
arp->ar_sip = htonl(0x0a00020f);
arp->ar_tip = target.s_addr;
slirp_input(s, packet, sizeof(packet));
}
int main(void)
{
struct ip4_lomap entries[] = {
{ .loaddr.s_addr = htonl(0x7f000002), .vaddr.s_addr = htonl(0x0a000304) },
{ .loaddr.s_addr = htonl(0x7f000003), .vaddr.s_addr = htonl(0x0a000404) },
};
struct ip4_lomap_desc map = { entries, G_N_ELEMENTS(entries) };
SlirpConfig cfg = {
.version = SLIRP_CONFIG_VERSION_MAX,
.in_enabled = true,
.vnetwork.s_addr = htonl(0x0a000000),
.vnetmask.s_addr = htonl(0xffff0000),
.vhost.s_addr = htonl(0x0a000002),
.loopback_map = &map,
};
Slirp *s = slirp_new(&cfg, &callbacks, NULL);
struct socket so = { .slirp = s };
struct sockaddr_storage storage = { .ss_family = AF_INET };
struct sockaddr_in *addr = (struct sockaddr_in *)&storage;
g_assert_nonnull(s);
g_assert_true(s->loopback_map != entries);
for (unsigned int i = 0; i < G_N_ELEMENTS(entries); i++) {
so.so_faddr = entries[i].vaddr;
addr->sin_addr = so.so_faddr;
g_assert_cmpint(sotranslate_out(&so, &storage), ==, 0);
g_assert_cmphex(addr->sin_addr.s_addr, ==, entries[i].loaddr.s_addr);
arp_request(s, entries[i].vaddr);
}
g_assert_cmpuint(replies, ==, 2);
so.so_faddr.s_addr = htonl(0x0a000504);
addr->sin_addr = so.so_faddr;
g_assert_cmpint(sotranslate_out(&so, &storage), ==, 0);
g_assert_cmphex(addr->sin_addr.s_addr, ==, so.so_faddr.s_addr);
arp_request(s, so.so_faddr);
g_assert_cmpuint(replies, ==, 2);
slirp_cleanup(s);
cfg.disable_host_loopback = true;
s = slirp_new(&cfg, &callbacks, NULL);
g_assert_cmpuint(s->loopback_map_len, ==, 0);
arp_request(s, entries[0].vaddr);
g_assert_cmpuint(replies, ==, 2);
slirp_cleanup(s);
cfg.version = 6;
s = slirp_new(&cfg, &callbacks, NULL);
g_assert_cmpuint(s->loopback_map_len, ==, 0);
slirp_cleanup(s);
return 0;
}