5#include <linux/lwtunnel.h>
6#include <linux-private/linux/if_tunnel.h>
8#include <netlink/route/nexthop.h>
10#include "nexthop-encap.h"
11#include "nl-aux-core/nl-core.h"
12#include "nl-aux-route/nl-route.h"
30 nl_dump(dp,
"id %llu ", (
unsigned long long)encap_info->id);
39 nl_dump(dp,
"tc %u ", encap_info->tc);
41 if (encap_info->hoplimit)
42 nl_dump(dp,
"hoplimit %u ", encap_info->hoplimit);
44 if (encap_info->flags) {
45 if (encap_info->flags & TUNNEL_KEY)
47 if (encap_info->flags & TUNNEL_CSUM)
49 if (encap_info->flags & TUNNEL_SEQ)
54static int ip6_encap_build_msg(
struct nl_msg *msg,
void *priv)
59 NLA_PUT_U64(msg, LWTUNNEL_IP6_ID, htonll(encap_info->id));
64 NLA_PUT_U8(msg, LWTUNNEL_IP6_TC, encap_info->tc);
65 if (encap_info->hoplimit)
66 NLA_PUT_U8(msg, LWTUNNEL_IP6_HOPLIMIT, encap_info->hoplimit);
67 if (encap_info->flags)
68 NLA_PUT_U16(msg, LWTUNNEL_IP6_FLAGS, encap_info->flags);
76static void ip6_encap_destructor(
void *priv)
84static void *ip6_encap_clone(
void *priv)
92 clone = calloc(1,
sizeof(*clone));
101 clone->hoplimit = src->hoplimit;
102 clone->flags = src->flags;
107static struct nla_policy ip6_encap_policy[LWTUNNEL_IP6_MAX + 1] = {
108 [LWTUNNEL_IP6_ID] = { .type =
NLA_U64 },
109 [LWTUNNEL_IP6_DST] = { .type = NLA_BINARY, .minlen = 16, .maxlen = 16 },
110 [LWTUNNEL_IP6_SRC] = { .type = NLA_BINARY, .minlen = 16, .maxlen = 16 },
111 [LWTUNNEL_IP6_HOPLIMIT] = { .type =
NLA_U8 },
112 [LWTUNNEL_IP6_TC] = { .type =
NLA_U8 },
113 [LWTUNNEL_IP6_FLAGS] = { .type =
NLA_U16 },
116static int ip6_encap_parse_msg(
struct nlattr *nla,
119 _nl_auto_rtnl_nh_encap
struct rtnl_nh_encap *nh_encap = NULL;
120 _nl_auto_nl_addr
struct nl_addr *dst = NULL;
121 _nl_auto_nl_addr
struct nl_addr *src = NULL;
122 struct nlattr *tb[LWTUNNEL_IP6_MAX + 1];
125 uint8_t hoplimit = 0;
133 if (!tb[LWTUNNEL_IP6_DST])
140 if (tb[LWTUNNEL_IP6_SRC]) {
146 if (tb[LWTUNNEL_IP6_HOPLIMIT])
147 hoplimit =
nla_get_u8(tb[LWTUNNEL_IP6_HOPLIMIT]);
149 if (tb[LWTUNNEL_IP6_TC])
152 if (tb[LWTUNNEL_IP6_ID])
155 if (tb[LWTUNNEL_IP6_FLAGS])
158 nh_encap = rtnl_nh_encap_alloc();
162 err = rtnl_nh_encap_ip6(nh_encap, dst);
167 err = rtnl_nh_set_encap_ip6_src(nh_encap, src);
173 err = rtnl_nh_set_encap_ip6_id(nh_encap,
id);
179 err = rtnl_nh_set_encap_ip6_hoplimit(nh_encap, hoplimit);
185 err = rtnl_nh_set_encap_ip6_tc(nh_encap, tc);
191 err = rtnl_nh_set_encap_ip6_flags(nh_encap, flags);
196 *encap_out = _nl_steal_pointer(&nh_encap);
201static int ip6_encap_compare(
void *_a,
void *_b)
207 diff |= (a->tc != b->tc);
208 diff |= (a->hoplimit != b->hoplimit);
209 diff |= (a->flags != b->flags);
210 diff |= (a->id != b->id);
218 .encap_type = LWTUNNEL_ENCAP_IP6,
219 .build_msg = ip6_encap_build_msg,
220 .parse_msg = ip6_encap_parse_msg,
221 .compare = ip6_encap_compare,
222 .clone = ip6_encap_clone,
223 .dump = ip6_encap_dump,
224 .destructor = ip6_encap_destructor,
227int rtnl_nh_encap_ip6(
struct rtnl_nh_encap *nh_encap,
struct nl_addr *dst)
231 if (!dst || !nh_encap)
236 ip6_encap = calloc(1,
sizeof(*ip6_encap));
242 nh_encap->priv = ip6_encap;
243 nh_encap->ops = &ip6_encap_ops;
251 nh_encap, LWTUNNEL_ENCAP_IP6);
254struct nl_addr *rtnl_nh_get_encap_ip6_dst(
struct rtnl_nh_encap *nh_encap)
258 ip6_encap = nh_encap_get_ip6(nh_encap);
262 return ip6_encap->dst;
269 struct nl_addr *old_src;
271 ip6_encap = nh_encap_get_ip6(nh_encap);
277 old_src = ip6_encap->src;
281 ip6_encap->src = NULL;
288struct nl_addr *rtnl_nh_get_encap_ip6_src(
struct rtnl_nh_encap *nh_encap)
292 ip6_encap = nh_encap_get_ip6(nh_encap);
296 return ip6_encap->src;
299int rtnl_nh_set_encap_ip6_tc(
struct rtnl_nh_encap *nh_encap, uint8_t tc)
303 ip6_encap = nh_encap_get_ip6(nh_encap);
315 ip6_encap = nh_encap_get_ip6(nh_encap);
319 return ip6_encap->tc;
322int rtnl_nh_set_encap_ip6_hoplimit(
struct rtnl_nh_encap *nh_encap,
327 ip6_encap = nh_encap_get_ip6(nh_encap);
331 ip6_encap->hoplimit = hoplimit;
335int rtnl_nh_get_encap_ip6_hoplimit(
struct rtnl_nh_encap *nh_encap)
339 ip6_encap = nh_encap_get_ip6(nh_encap);
343 return ip6_encap->hoplimit;
346int rtnl_nh_set_encap_ip6_flags(
struct rtnl_nh_encap *nh_encap, uint16_t flags)
350 ip6_encap = nh_encap_get_ip6(nh_encap);
354 ip6_encap->flags = flags;
358int rtnl_nh_get_encap_ip6_flags(
struct rtnl_nh_encap *nh_encap)
362 ip6_encap = nh_encap_get_ip6(nh_encap);
366 return ip6_encap->flags;
369int rtnl_nh_set_encap_ip6_id(
struct rtnl_nh_encap *nh_encap, uint64_t
id)
373 ip6_encap = nh_encap_get_ip6(nh_encap);
382uint64_t rtnl_nh_get_encap_ip6_id(
struct rtnl_nh_encap *nh_encap)
386 ip6_encap = nh_encap_get_ip6(nh_encap);
390 return ip6_encap->id;
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
uint64_t nla_get_u64(const struct nlattr *nla)
Return payload of u64 attribute.
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
#define NLA_PUT_U64(msg, attrtype, value)
Add 64 bit integer attribute to netlink message.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Attribute validation policy.