passt/ip.h
David Gibson 97e8b33f87 netlink: Ignore routes to link-local addresses for selecting interface
Since f919dc7a4b ("conf, netlink: Don't require a default route to
start"), and since 639fdf06ed ("netlink: Fix selection of template
interface") less buggily, we haven't required a default route on the host
in order to operate.  Instead, if we lack a default route we'll pick an
interface with any route, as long as there's only one such interface.  If
there's more than one, we don't have a good criterion to pick, so we give
up with an informational message.

Paul Holzinger pointed out that this code considers it ambiguous even if
all but one of the interfaces has only routes to link-local addresses
(fe80::/10).  A route to link-local addresses isn't really useful from
pasta's point of view, so ignore them instead.  This removes a misleading
message in many cases, and a spurious failure in some cases.

Suggested-by: Paul Holzinger <pholzing@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
2024-04-05 16:59:08 +02:00

95 lines
2.4 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright (c) 2021 Red Hat GmbH
* Author: Stefano Brivio <sbrivio@redhat.com>
*/
#ifndef IP_H
#define IP_H
#include <netinet/ip.h>
#include <netinet/ip6.h>
#define IN4_IS_ADDR_UNSPECIFIED(a) \
(((struct in_addr *)(a))->s_addr == htonl_constant(INADDR_ANY))
#define IN4_IS_ADDR_BROADCAST(a) \
(((struct in_addr *)(a))->s_addr == htonl_constant(INADDR_BROADCAST))
#define IN4_IS_ADDR_LOOPBACK(a) \
(ntohl(((struct in_addr *)(a))->s_addr) >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET)
#define IN4_IS_ADDR_MULTICAST(a) \
(IN_MULTICAST(ntohl(((struct in_addr *)(a))->s_addr)))
#define IN4_ARE_ADDR_EQUAL(a, b) \
(((struct in_addr *)(a))->s_addr == ((struct in_addr *)b)->s_addr)
#define IN4ADDR_LOOPBACK_INIT \
{ .s_addr = htonl_constant(INADDR_LOOPBACK) }
#define IN4ADDR_ANY_INIT \
{ .s_addr = htonl_constant(INADDR_ANY) }
#define IN4_IS_ADDR_LINKLOCAL(a) \
((ntohl(((struct in_addr *)(a))->s_addr) >> 16) == 0xa9fe)
#define IN4_IS_PREFIX_LINKLOCAL(a, len) \
((len) >= 16 && IN4_IS_ADDR_LINKLOCAL(a))
#define L2_BUF_IP4_INIT(proto) \
{ \
.version = 4, \
.ihl = 5, \
.tos = 0, \
.tot_len = 0, \
.id = 0, \
.frag_off = 0, \
.ttl = 0xff, \
.protocol = (proto), \
.saddr = 0, \
.daddr = 0, \
}
#define L2_BUF_IP4_PSUM(proto) ((uint32_t)htons_constant(0x4500) + \
(uint32_t)htons(0xff00 | (proto)))
#define IN6_IS_PREFIX_LINKLOCAL(a, len) \
((len) >= 10 && IN6_IS_ADDR_LINKLOCAL(a))
#define L2_BUF_IP6_INIT(proto) \
{ \
.priority = 0, \
.version = 6, \
.flow_lbl = { 0 }, \
.payload_len = 0, \
.nexthdr = (proto), \
.hop_limit = 255, \
.saddr = IN6ADDR_ANY_INIT, \
.daddr = IN6ADDR_ANY_INIT, \
}
struct ipv6hdr {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#if __BYTE_ORDER == __BIG_ENDIAN
uint8_t version:4,
priority:4;
#else
uint8_t priority:4,
version:4;
#endif
#pragma GCC diagnostic pop
uint8_t flow_lbl[3];
uint16_t payload_len;
uint8_t nexthdr;
uint8_t hop_limit;
struct in6_addr saddr;
struct in6_addr daddr;
};
struct ipv6_opt_hdr {
uint8_t nexthdr;
uint8_t hdrlen;
/*
* TLV encoded option data follows.
*/
} __attribute__((packed)); /* required for some archs */
char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *proto,
size_t *dlen);
#endif /* IP_H */