public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
blob b255e30b739d090df6f62b4a63ac1887c295d839 2869 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"

/**
 * accept_arp() - Check if we should accept this ARP message
 * @c:		Execution context
 * @ah:		ARP header
 * @am:		ARP message
 *
 * Return: true if the message is supported, false otherwise.
 */
static bool accept_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 (accept_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 b255e30b739d ...
found b255e30b739d in https://archives.passt.top/passt-dev/20250604130834.3868010-23-lvivier@redhat.com/
found 65f0f2627db6 in https://archives.passt.top/passt-dev/20250604130834.3868010-22-lvivier@redhat.com/
found 6617698f125b in https://archives.passt.top/passt-dev/20250604130834.3868010-8-lvivier@redhat.com/
found 721ff2d529b5 in https://archives.passt.top/passt-dev/20250604130834.3868010-2-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/20250604130834.3868010-2-lvivier@redhat.com/
diff --git a/arp.c b/arp.c
index fc482bbd9938..721ff2d529b5 100644


applying [2/4] https://archives.passt.top/passt-dev/20250604130834.3868010-8-lvivier@redhat.com/
diff --git a/arp.c b/arp.c
index 721ff2d529b5..6617698f125b 100644


applying [3/4] https://archives.passt.top/passt-dev/20250604130834.3868010-22-lvivier@redhat.com/
diff --git a/arp.c b/arp.c
index 6617698f125b..65f0f2627db6 100644


applying [4/4] https://archives.passt.top/passt-dev/20250604130834.3868010-23-lvivier@redhat.com/
diff --git a/arp.c b/arp.c
index 65f0f2627db6..b255e30b739d 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 b255e30b739d090df6f62b4a63ac1887c295d839	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).