public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
blob 44677ad15b93d82223a43f1cb1199bac1fdf4463 2877 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
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
 
// 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"

/**
 * ignore_arp() - Check if we should ignore this ARP message
 * @c:		Execution context
 * @ah:		ARP header
 * @am:		ARP message
 *
 * Return: true if the ARP message should be ignored, false otherwise
 */
static bool ignore_arp(const struct ctx *c,
		       const struct arphdr *ah, const struct arpmsg *am)
{
	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 true;

	/* 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 true;

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

	return false;
}

/**
 * arp() - Check if this is a supported ARP message, reply as needed
 * @c:		Execution context
 * @data:	Single packet with Ethernet buffer
 *
 * Return: 1 if handled, -1 on failure
 */
int arp(const struct ctx *c, struct iov_tail *data)
{
	struct {
		struct ethhdr eh;
		struct arphdr ah;
		struct arpmsg am;
	} __attribute__((__packed__)) resp;
	struct arphdr ah_storage;
	struct ethhdr eh_storage;
	struct arpmsg am_storage;
	const struct ethhdr *eh;
	const struct arphdr *ah;
	const struct arpmsg *am;

	eh = IOV_REMOVE_HEADER(data, eh_storage);
	ah = IOV_REMOVE_HEADER(data, ah_storage);
	am = IOV_REMOVE_HEADER(data, am_storage);
	if (!eh || !ah || !am)
		return -1;

	if (ignore_arp(c, ah, am))
		return 1;

	/* Ethernet header */
	resp.eh.h_proto = htons(ETH_P_ARP);
	memcpy(resp.eh.h_dest, eh->h_source, sizeof(resp.eh.h_dest));
	memcpy(resp.eh.h_source, c->our_tap_mac, sizeof(resp.eh.h_source));

	/* ARP header */
	resp.ah.ar_op = htons(ARPOP_REPLY);
	resp.ah.ar_hrd = ah->ar_hrd;
	resp.ah.ar_pro = ah->ar_pro;
	resp.ah.ar_hln = ah->ar_hln;
	resp.ah.ar_pln = ah->ar_pln;

	/* ARP message */
	memcpy(resp.am.sha,		c->our_tap_mac,	sizeof(resp.am.sha));
	memcpy(resp.am.sip,		am->tip,	sizeof(resp.am.sip));
	memcpy(resp.am.tha,		am->sha,	sizeof(resp.am.tha));
	memcpy(resp.am.tip,		am->sip,	sizeof(resp.am.tip));

	tap_send_single(c, &resp, sizeof(resp));

	return 1;
}

debug log:

solving 44677ad15b93 ...
found 44677ad15b93 in https://archives.passt.top/passt-dev/20250623110635.1478625-24-lvivier@redhat.com/
found 8b97df633e70 in https://archives.passt.top/passt-dev/20250623110635.1478625-23-lvivier@redhat.com/
found b3ac42082841 in https://archives.passt.top/passt-dev/20250623110635.1478625-9-lvivier@redhat.com/
found 9f1fedeafec0 in https://archives.passt.top/passt-dev/20250623110635.1478625-3-lvivier@redhat.com/
found fc482bbd9938 in https://passt.top/passt
preparing index
index prepared:
100644 fc482bbd9938cf571055792b1a44cb35915b465d	arp.c

applying [1/4] https://archives.passt.top/passt-dev/20250623110635.1478625-3-lvivier@redhat.com/
diff --git a/arp.c b/arp.c
index fc482bbd9938..9f1fedeafec0 100644


applying [2/4] https://archives.passt.top/passt-dev/20250623110635.1478625-9-lvivier@redhat.com/
diff --git a/arp.c b/arp.c
index 9f1fedeafec0..b3ac42082841 100644


applying [3/4] https://archives.passt.top/passt-dev/20250623110635.1478625-23-lvivier@redhat.com/
diff --git a/arp.c b/arp.c
index b3ac42082841..8b97df633e70 100644


applying [4/4] https://archives.passt.top/passt-dev/20250623110635.1478625-24-lvivier@redhat.com/
diff --git a/arp.c b/arp.c
index 8b97df633e70..44677ad15b93 100644

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

index at:
100644 44677ad15b93d82223a43f1cb1199bac1fdf4463	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).