public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
blob d758f7ba284cad0fd4765c1a676f81341befc1e2 3903 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
 
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright Red Hat
 * Author: David Gibson <david@gibson.dropbear.id.au>
 *
 * inany.h - Types and helpers for handling addresses which could be
 *           IPv6 or IPv4 (encoded as IPv4-mapped IPv6 addresses)
 */

#ifndef INANY_H
#define INANY_H

/** union inany_addr - Represents either an IPv4 or IPv6 address
 * @a6:			Address as an IPv6 address, may be IPv4-mapped
 * @v4mapped.zero:	All zero-bits for an IPv4 address
 * @v4mapped.one:	All one-bits for an IPv4 address
 * @v4mapped.a4:	If @a6 is an IPv4 mapped address, the IPv4 address
 * @u64:		As an array of u64s (solely for hashing)
 *
 * @v4mapped and @u64 shouldn't be accessed except via helpers.
 */
union inany_addr {
	struct in6_addr a6;
	struct {
		uint8_t zero[10];
		uint8_t one[2];
		struct in_addr a4;
	} v4mapped;
	uint32_t u32[4];
};
static_assert(sizeof(union inany_addr) == sizeof(struct in6_addr),
	      "union inany_addr is larger than an IPv6 address");
static_assert(_Alignof(union inany_addr) == _Alignof(uint32_t),
	      "union inany_addr has unexpected alignment");

/** inany_v4 - Extract IPv4 address, if present, from IPv[46] address
 * @addr:	IPv4 or IPv6 address
 *
 * Return: IPv4 address if @addr is IPv4, NULL otherwise
 */
static inline struct in_addr *inany_v4(const union inany_addr *addr)
{
	if (!IN6_IS_ADDR_V4MAPPED(&addr->a6))
		return NULL;
	return (struct in_addr *)&addr->v4mapped.a4;
}

/** inany_equals - Compare two IPv[46] addresses
 * @a, @b:	IPv[46] addresses
 *
 * Return: true if @a and @b are the same address
 */
static inline bool inany_equals(const union inany_addr *a,
				const union inany_addr *b)
{
	return IN6_ARE_ADDR_EQUAL(&a->a6, &b->a6);
}

/** inany_is_loopback - Check if address is loopback
 * @a:		IPv[46] address
 *
 * Return: true if @a is either ::1 or in 127.0.0.1/8
 */
static inline bool inany_is_loopback(const union inany_addr *a)
{
	const struct in_addr *v4;

	return IN6_IS_ADDR_LOOPBACK(&a->a6) ||
		((v4 = inany_v4(a)) && IN4_IS_ADDR_LOOPBACK(v4));
}

/** inany_from_af - Set IPv[46] address from IPv4 or IPv6 address
 * @aa:		Pointer to store IPv[46] address
 * @af:		Address family of @addr
 * @addr:	struct in_addr (IPv4) or struct in6_addr (IPv6)
 */
static inline void inany_from_af(union inany_addr *aa,
				 sa_family_t af, const void *addr)
{
	if (af == AF_INET6) {
		aa->a6 = *((struct in6_addr *)addr);
	} else if (af == AF_INET) {
		memset(&aa->v4mapped.zero, 0, sizeof(aa->v4mapped.zero));
		memset(&aa->v4mapped.one, 0xff, sizeof(aa->v4mapped.one));
		aa->v4mapped.a4 = *((struct in_addr *)addr);
	} else {
		/* Not valid to call with other address families */
		ASSERT(0);
	}
}

/** inany_from_sockaddr - Extract IPv[46] address and port number from sockaddr
 * @aa:		Pointer to store IPv[46] address
 * @port:	Pointer to store port number, host order
 * @addr:	struct sockaddr_in (IPv4) or struct sockaddr_in6 (IPv6)
 */
static inline void inany_from_sockaddr(union inany_addr *aa, in_port_t *port,
				       const void *addr)
{
	const struct sockaddr *sa = (const struct sockaddr *)addr;

	if (sa->sa_family == AF_INET6) {
		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;

		inany_from_af(aa, AF_INET6, &sa6->sin6_addr);
		*port = ntohs(sa6->sin6_port);
	} else if (sa->sa_family == AF_INET) {
		struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;

		inany_from_af(aa, AF_INET, &sa4->sin_addr);
		*port = ntohs(sa4->sin_port);
	} else {
		/* Not valid to call with other address families */
		ASSERT(0);
	}
}

/** inany_siphash_feed- Fold IPv[46] address into an in-progress siphash
 * @state:	siphash state
 * @aa:		inany to hash
 */
static inline void inany_siphash_feed(struct siphash_state *state,
				      const union inany_addr *aa)
{
	siphash_feed(state, (uint64_t)aa->u32[0] << 32 | aa->u32[1]);
	siphash_feed(state, (uint64_t)aa->u32[2] << 32 | aa->u32[3]);
}

#endif /* INANY_H */

debug log:

solving d758f7ba ...
found d758f7ba in https://archives.passt.top/passt-dev/20240129043557.823451-6-david@gibson.dropbear.id.au/
found fe652ff7 in https://passt.top/passt
preparing index
index prepared:
100644 fe652ff7d2f6d6fa652a1d059a4536f2025842e0	inany.h

applying [1/1] https://archives.passt.top/passt-dev/20240129043557.823451-6-david@gibson.dropbear.id.au/
diff --git a/inany.h b/inany.h
index fe652ff7..d758f7ba 100644

Checking patch inany.h...
Applied patch inany.h cleanly.

index at:
100644 d758f7ba284cad0fd4765c1a676f81341befc1e2	inany.h

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).