public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
426d2a6419884f1b393a3342fd5a6d6068004d48 blob 3523 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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
 
// 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
 *
 * PESTO - Programmable Extensible Socket Translation Orchestrator
 *  front-end for passt(1) and pasta(1) forwarding configuration
 *
 * inany.c - Types and helpers for handling addresses which could be
 *           IPv6 or IPv4 (encoded as IPv4-mapped IPv6 addresses)
 *
 * Copyright Red Hat
 * Author: David Gibson <david@gibson.dropbear.id.au>
 */

#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#include "util.h"
#include "ip.h"
#include "siphash.h"
#include "inany.h"
#include "fwd.h"

const union inany_addr inany_loopback4 = INANY_INIT4(IN4ADDR_LOOPBACK_INIT);
const union inany_addr inany_any4 = INANY_INIT4(IN4ADDR_ANY_INIT);

/** inany_matches - Do two addresses match?
 * @a, @b:	IPv[46] addresses (NULL for 0.0.0.0 & ::)
 *
 * Return: true if they match, false otherwise
 *
 * Addresses match themselves, but also unspecified addresses of the same
 * family.
 */
bool inany_matches(const union inany_addr *a, const union inany_addr *b)
{
	if (!a || !b)
		return true;

	if (inany_is_unspecified(a) || inany_is_unspecified(b))
		return !!inany_v4(a) == !!inany_v4(b);

	return inany_equals(a, b);
}

/** inany_ntop - Convert an IPv[46] address to text format
 * @src:	IPv[46] address (NULL for unspecified)
 * @dst:	output buffer, minimum INANY_ADDRSTRLEN bytes
 * @size:	size of buffer at @dst
 *
 * Return: on success, a non-null pointer to @dst, NULL on failure
 */
const char *inany_ntop(const union inany_addr *src, char *dst, socklen_t size)
{
	const struct in_addr *v4;

	if (!src)
		return strncpy(dst, "*", size);

	if ((v4 = inany_v4(src)))
		return inet_ntop(AF_INET, v4, dst, size);

	return inet_ntop(AF_INET6, &src->a6, dst, size);
}

/** inany_pton - Parse an IPv[46] address from text format
 * @src:	IPv[46] address
 * @dst:	output buffer, filled with parsed address
 *
 * Return: on success, 1, if no parseable address is found, 0
 */
int inany_pton(const char *src, union inany_addr *dst)
{
	if (inet_pton(AF_INET, src, &dst->v4mapped.a4)) {
		memset(&dst->v4mapped.zero, 0, sizeof(dst->v4mapped.zero));
		memset(&dst->v4mapped.one, 0xff, sizeof(dst->v4mapped.one));
		return 1;
	}

	if (inet_pton(AF_INET6, src, &dst->a6))
		return 1;

	return 0;
}

/**
 * inany_prefix_pton() - Parse an IPv[46] address with prefix length
 * @src:	IPv[46] address and prefix length string in CIDR format
 * @dst:	Output buffer, filled with parsed address
 * @prefix_len:	Prefix length, to be filled in IPv6 format
 *
 * Return: 1 on success, 0 if no parseable address or prefix is found
 */
int inany_prefix_pton(const char *src, union inany_addr *dst,
		      uint8_t *prefix_len)
{
	char astr[INANY_ADDRSTRLEN] = { 0 };
	size_t alen = strcspn(src, "/");
	const char *pstr = &src[alen + 1];
	unsigned long plen;
	char *end;

	if (alen >= INANY_ADDRSTRLEN)
		return 0;

	if (src[alen] != '/')
		return 0;

	strncpy(astr, src, alen);

	/* Read prefix length */
	errno = 0;
	plen = strtoul(pstr, &end, 10);
	if (errno || *end || plen > 128)
		return 0;

	/* Read address */
	if (inet_pton(AF_INET6, astr, dst)) {
		if (inany_v4(dst) && plen < 96)
			return 0;
		*prefix_len = plen;
		return 1;
	}

	if (inany_pton(astr, dst)) {
		if (plen > 32)
			return 0;
		*prefix_len = plen + 96;
		return 1;
	}

	return 0;
}
debug log:

solving 426d2a64 ...
found 426d2a64 in https://archives.passt.top/passt-dev/20260319061157.1983818-12-david@gibson.dropbear.id.au/
found 2a586ed1 in https://passt.top/passt
preparing index
index prepared:
100644 2a586ed11193c07160b67a37d6780ef414be7be7	inany.c

applying [1/1] https://archives.passt.top/passt-dev/20260319061157.1983818-12-david@gibson.dropbear.id.au/
diff --git a/inany.c b/inany.c
index 2a586ed1..426d2a64 100644

Checking patch inany.c...
Applied patch inany.c cleanly.

index at:
100644 426d2a6419884f1b393a3342fd5a6d6068004d48	inany.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).