inany: Better helpers for using inany and specific family addrs together
This adds some extra inany helpers for comparing an inany address to addresses of a specific family (including special addresses), and building an inany from an IPv4 address (either statically or at runtime). Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
parent
7a832a8a0e
commit
a63199832a
3 changed files with 106 additions and 37 deletions
17
inany.c
17
inany.c
|
@ -17,21 +17,8 @@
|
||||||
#include "siphash.h"
|
#include "siphash.h"
|
||||||
#include "inany.h"
|
#include "inany.h"
|
||||||
|
|
||||||
const union inany_addr inany_loopback4 = {
|
const union inany_addr inany_loopback4 = INANY_INIT4(IN4ADDR_LOOPBACK_INIT);
|
||||||
.v4mapped = {
|
const union inany_addr inany_any4 = INANY_INIT4(IN4ADDR_ANY_INIT);
|
||||||
.zero = { 0 },
|
|
||||||
.one = { 0xff, 0xff, },
|
|
||||||
.a4 = IN4ADDR_LOOPBACK_INIT,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const union inany_addr inany_any4 = {
|
|
||||||
.v4mapped = {
|
|
||||||
.zero = { 0 },
|
|
||||||
.one = { 0xff, 0xff, },
|
|
||||||
.a4 = IN4ADDR_ANY_INIT,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/** inany_ntop - Convert an IPv[46] address to text format
|
/** inany_ntop - Convert an IPv[46] address to text format
|
||||||
* @src: IPv[46] address
|
* @src: IPv[46] address
|
||||||
|
|
97
inany.h
97
inany.h
|
@ -43,6 +43,17 @@ extern const union inany_addr inany_any4;
|
||||||
#define in4addr_loopback (inany_loopback4.v4mapped.a4)
|
#define in4addr_loopback (inany_loopback4.v4mapped.a4)
|
||||||
#define in4addr_any (inany_any4.v4mapped.a4)
|
#define in4addr_any (inany_any4.v4mapped.a4)
|
||||||
|
|
||||||
|
#define INANY_INIT4(a4init) { \
|
||||||
|
.v4mapped = { \
|
||||||
|
.zero = { 0 }, \
|
||||||
|
.one = { 0xff, 0xff }, \
|
||||||
|
.a4 = a4init, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define inany_from_v4(a4) \
|
||||||
|
((union inany_addr)INANY_INIT4((a4)))
|
||||||
|
|
||||||
/** union sockaddr_inany - Either a sockaddr_in or a sockaddr_in6
|
/** union sockaddr_inany - Either a sockaddr_in or a sockaddr_in6
|
||||||
* @sa_family: Address family, AF_INET or AF_INET6
|
* @sa_family: Address family, AF_INET or AF_INET6
|
||||||
* @sa: Plain struct sockaddr (useful to avoid casts)
|
* @sa: Plain struct sockaddr (useful to avoid casts)
|
||||||
|
@ -79,16 +90,84 @@ static inline bool inany_equals(const union inany_addr *a,
|
||||||
return IN6_ARE_ADDR_EQUAL(&a->a6, &b->a6);
|
return IN6_ARE_ADDR_EQUAL(&a->a6, &b->a6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** inany_equals4 - Compare an IPv[46] address to an IPv4 address
|
||||||
|
* @a: IPv[46] addresses
|
||||||
|
* @b: IPv4 address
|
||||||
|
*
|
||||||
|
* Return: true if @a and @b are the same address
|
||||||
|
*/
|
||||||
|
static inline bool inany_equals4(const union inany_addr *a,
|
||||||
|
const struct in_addr *b)
|
||||||
|
{
|
||||||
|
const struct in_addr *a4 = inany_v4(a);
|
||||||
|
|
||||||
|
return a4 && IN4_ARE_ADDR_EQUAL(a4, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** inany_equals6 - Compare an IPv[46] address to an IPv6 address
|
||||||
|
* @a: IPv[46] addresses
|
||||||
|
* @b: IPv6 address
|
||||||
|
*
|
||||||
|
* Return: true if @a and @b are the same address
|
||||||
|
*/
|
||||||
|
static inline bool inany_equals6(const union inany_addr *a,
|
||||||
|
const struct in6_addr *b)
|
||||||
|
{
|
||||||
|
return IN6_ARE_ADDR_EQUAL(&a->a6, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** inany_is_loopback4() - Check if address is IPv4 loopback
|
||||||
|
* @a: IPv[46] address
|
||||||
|
*
|
||||||
|
* Return: true if @a is in 127.0.0.1/8
|
||||||
|
*/
|
||||||
|
static inline bool inany_is_loopback4(const union inany_addr *a)
|
||||||
|
{
|
||||||
|
const struct in_addr *v4 = inany_v4(a);
|
||||||
|
|
||||||
|
return v4 && IN4_IS_ADDR_LOOPBACK(v4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** inany_is_loopback6() - Check if address is IPv6 loopback
|
||||||
|
* @a: IPv[46] address
|
||||||
|
*
|
||||||
|
* Return: true if @a is in ::1
|
||||||
|
*/
|
||||||
|
static inline bool inany_is_loopback6(const union inany_addr *a)
|
||||||
|
{
|
||||||
|
return IN6_IS_ADDR_LOOPBACK(&a->a6);
|
||||||
|
}
|
||||||
|
|
||||||
/** inany_is_loopback() - Check if address is loopback
|
/** inany_is_loopback() - Check if address is loopback
|
||||||
* @a: IPv[46] address
|
* @a: IPv[46] address
|
||||||
*
|
*
|
||||||
* Return: true if @a is either ::1 or in 127.0.0.1/8
|
* 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)
|
static inline bool inany_is_loopback(const union inany_addr *a)
|
||||||
|
{
|
||||||
|
return inany_is_loopback4(a) || inany_is_loopback6(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** inany_is_unspecified4() - Check if address is unspecified IPv4
|
||||||
|
* @a: IPv[46] address
|
||||||
|
*
|
||||||
|
* Return: true if @a is 0.0.0.0
|
||||||
|
*/
|
||||||
|
static inline bool inany_is_unspecified4(const union inany_addr *a)
|
||||||
{
|
{
|
||||||
const struct in_addr *v4 = inany_v4(a);
|
const struct in_addr *v4 = inany_v4(a);
|
||||||
|
|
||||||
return IN6_IS_ADDR_LOOPBACK(&a->a6) || (v4 && IN4_IS_ADDR_LOOPBACK(v4));
|
return v4 && IN4_IS_ADDR_UNSPECIFIED(v4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** inany_is_unspecified6() - Check if address is unspecified IPv6
|
||||||
|
* @a: IPv[46] address
|
||||||
|
*
|
||||||
|
* Return: true if @a is ::
|
||||||
|
*/
|
||||||
|
static inline bool inany_is_unspecified6(const union inany_addr *a)
|
||||||
|
{
|
||||||
|
return IN6_IS_ADDR_UNSPECIFIED(&a->a6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** inany_is_unspecified() - Check if address is unspecified
|
/** inany_is_unspecified() - Check if address is unspecified
|
||||||
|
@ -98,10 +177,20 @@ static inline bool inany_is_loopback(const union inany_addr *a)
|
||||||
*/
|
*/
|
||||||
static inline bool inany_is_unspecified(const union inany_addr *a)
|
static inline bool inany_is_unspecified(const union inany_addr *a)
|
||||||
{
|
{
|
||||||
const struct in_addr *v4 = inany_v4(a);
|
return inany_is_unspecified4(a) || inany_is_unspecified6(a);
|
||||||
|
}
|
||||||
|
|
||||||
return IN6_IS_ADDR_UNSPECIFIED(&a->a6) ||
|
/* FIXME: consider handling of IPv4 link-local addresses */
|
||||||
(v4 && IN4_IS_ADDR_UNSPECIFIED(v4));
|
|
||||||
|
/** inany_is_linklocal6() - Check if address is link-local IPv6
|
||||||
|
* @a: IPv[46] address
|
||||||
|
*
|
||||||
|
* Return: true if @a is in fe80::/10 (IPv6 link local unicast)
|
||||||
|
*/
|
||||||
|
/* cppcheck-suppress unusedFunction */
|
||||||
|
static inline bool inany_is_linklocal6(const union inany_addr *a)
|
||||||
|
{
|
||||||
|
return IN6_IS_ADDR_LINKLOCAL(&a->a6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** inany_is_multicast() - Check if address is multicast or broadcast
|
/** inany_is_multicast() - Check if address is multicast or broadcast
|
||||||
|
|
25
tcp.c
25
tcp.c
|
@ -2687,24 +2687,17 @@ static void tcp_connect_finish(struct ctx *c, struct tcp_tap_conn *conn)
|
||||||
*/
|
*/
|
||||||
static void tcp_snat_inbound(const struct ctx *c, union inany_addr *addr)
|
static void tcp_snat_inbound(const struct ctx *c, union inany_addr *addr)
|
||||||
{
|
{
|
||||||
struct in_addr *addr4 = inany_v4(addr);
|
if (inany_is_loopback4(addr) ||
|
||||||
|
inany_is_unspecified4(addr) ||
|
||||||
if (addr4) {
|
inany_equals4(addr, &c->ip4.addr_seen)) {
|
||||||
if (IN4_IS_ADDR_LOOPBACK(addr4) ||
|
*addr = inany_from_v4(c->ip4.gw);
|
||||||
IN4_IS_ADDR_UNSPECIFIED(addr4) ||
|
} else if (inany_is_loopback6(addr) ||
|
||||||
IN4_ARE_ADDR_EQUAL(addr4, &c->ip4.addr_seen))
|
inany_equals6(addr, &c->ip6.addr_seen) ||
|
||||||
*addr4 = c->ip4.gw;
|
inany_equals6(addr, &c->ip6.addr)) {
|
||||||
} else {
|
|
||||||
struct in6_addr *addr6 = &addr->a6;
|
|
||||||
|
|
||||||
if (IN6_IS_ADDR_LOOPBACK(addr6) ||
|
|
||||||
IN6_ARE_ADDR_EQUAL(addr6, &c->ip6.addr_seen) ||
|
|
||||||
IN6_ARE_ADDR_EQUAL(addr6, &c->ip6.addr)) {
|
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
|
if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
|
||||||
*addr6 = c->ip6.gw;
|
addr->a6 = c->ip6.gw;
|
||||||
else
|
else
|
||||||
*addr6 = c->ip6.addr_ll;
|
addr->a6 = c->ip6.addr_ll;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue