public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
blob fbd821913d8b94bfe3e37952eb968af1c7007b46 2510 bytes (raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
 
// SPDX-License-Identifier: GPL-2.0-or-later

/* PASST - Plug A Simple Socket Transport
 *  for qemu/UNIX domain socket mode
 *
 * PASTA - Pack A Subtle Tap Abstraction
 *  for network namespace/tap device mode
 *
 * arp.c - ARP implementation
 *
 * Copyright (c) 2020-2021 Red Hat GmbH
 * Author: Stefano Brivio <sbrivio@redhat.com>
 */

#include <arpa/inet.h>
#include <limits.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/if_ether.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include "util.h"
#include "log.h"
#include "arp.h"
#include "dhcp.h"
#include "passt.h"
#include "tap.h"
#include "netlink.h"

/**
 * arp() - Check if this is a supported ARP message, reply as needed
 * @c:		Execution context
 * @p:		Packet pool, single packet with Ethernet buffer
 *
 * Return: 1 if handled, -1 on failure
 */
int arp(const struct ctx *c, const struct pool *p)
{
	union inany_addr translated;
	union inany_addr addr;
	unsigned char swap[4];
	struct ethhdr *eh;
	struct arphdr *ah;
	struct arpmsg *am;
	size_t l2len;

	eh = packet_get(p, 0, 0,			 sizeof(*eh), NULL);
	ah = packet_get(p, 0, sizeof(*eh),		 sizeof(*ah), NULL);
	am = packet_get(p, 0, sizeof(*eh) + sizeof(*ah), sizeof(*am), NULL);

	if (!eh || !ah || !am)
		return -1;

	if (ah->ar_hrd != htons(ARPHRD_ETHER)	||
	    ah->ar_pro != htons(ETH_P_IP)	||
	    ah->ar_hln != ETH_ALEN		||
	    ah->ar_pln != 4			||
	    ah->ar_op  != htons(ARPOP_REQUEST))
		return 1;

	/* Discard announcements, but not 0.0.0.0 "probes" */
	if (memcmp(am->sip, &in4addr_any, sizeof(am->sip)) &&
	    !memcmp(am->sip, am->tip, sizeof(am->sip)))
		return 1;

	/* Don't resolve the guest's assigned address, either. */
	if (!memcmp(am->tip, &c->ip4.addr, sizeof(am->tip)))
		return 1;

	ah->ar_op = htons(ARPOP_REPLY);
	memcpy(am->tha,		am->sha,	sizeof(am->tha));
	memcpy(am->sha,		c->our_tap_mac,	sizeof(am->sha));

	/* If remote host on local network - respond with its mac address */
	inany_from_af(&addr, AF_INET, am->tip);
	nat_outbound(c, &addr, &translated);
	if (!memcmp(&addr, &translated, sizeof(addr)))
		nl_mac_get(nl_sock, &addr, am->sha);

	memcpy(swap,		am->tip,	sizeof(am->tip));
	memcpy(am->tip,		am->sip,	sizeof(am->tip));
	memcpy(am->sip,		swap,		sizeof(am->sip));

	l2len = sizeof(*eh) + sizeof(*ah) + sizeof(*am);
	memcpy(eh->h_dest,	eh->h_source,	sizeof(eh->h_dest));
	memcpy(eh->h_source,	c->our_tap_mac,	sizeof(eh->h_source));

	tap_send_single(c, eh, l2len);

	return 1;
}

debug log:

solving fbd8219 ...
found fbd8219 in https://archives.passt.top/passt-dev/20250607011151.3290866-3-jmaloy@redhat.com/
found fc482bb in https://passt.top/passt
preparing index
index prepared:
100644 fc482bbd9938cf571055792b1a44cb35915b465d	arp.c

applying [1/1] https://archives.passt.top/passt-dev/20250607011151.3290866-3-jmaloy@redhat.com/
diff --git a/arp.c b/arp.c
index fc482bb..fbd8219 100644

Checking patch arp.c...
Applied patch arp.c cleanly.

index at:
100644 fbd821913d8b94bfe3e37952eb968af1c7007b46	arp.c

Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).