16#include <netlink-private/netlink.h>
17#include <netlink/netlink.h>
18#include <netlink/attr.h>
19#include <netlink/utils.h>
20#include <netlink/object.h>
21#include <netlink/route/rtnl.h>
22#include <netlink/route/link/ip6vti.h>
23#include <netlink-private/route/link/api.h>
24#include <linux/if_tunnel.h>
26#define IP6VTI_ATTR_LINK (1 << 0)
27#define IP6VTI_ATTR_IKEY (1 << 1)
28#define IP6VTI_ATTR_OKEY (1 << 2)
29#define IP6VTI_ATTR_LOCAL (1 << 3)
30#define IP6VTI_ATTR_REMOTE (1 << 4)
31#define IP6VTI_ATTR_FWMARK (1 << 5)
38 struct in6_addr local;
39 struct in6_addr remote;
44static struct nla_policy ip6vti_policy[IFLA_VTI_MAX + 1] = {
46 [IFLA_VTI_IKEY] = { .type =
NLA_U32 },
47 [IFLA_VTI_OKEY] = { .type =
NLA_U32 },
48 [IFLA_VTI_LOCAL] = { .minlen =
sizeof(
struct in6_addr) },
49 [IFLA_VTI_REMOTE] = { .minlen =
sizeof(
struct in6_addr) },
50 [IFLA_VTI_FWMARK] = { .type =
NLA_U32 },
53static int ip6vti_alloc(
struct rtnl_link *link)
58 memset(link->l_info, 0,
sizeof(*ip6vti));
60 ip6vti = calloc(1,
sizeof(*ip6vti));
64 link->l_info = ip6vti;
70static int ip6vti_parse(
struct rtnl_link *link,
struct nlattr *data,
71 struct nlattr *xstats)
73 struct nlattr *tb[IFLA_VTI_MAX + 1];
77 NL_DBG(3,
"Parsing IP6VTI link info\n");
83 err = ip6vti_alloc(link);
87 ip6vti = link->l_info;
89 if (tb[IFLA_VTI_LINK]) {
91 ip6vti->ip6vti_mask |= IP6VTI_ATTR_LINK;
94 if (tb[IFLA_VTI_IKEY]) {
96 ip6vti->ip6vti_mask |= IP6VTI_ATTR_IKEY;
99 if (tb[IFLA_VTI_OKEY]) {
101 ip6vti->ip6vti_mask |= IP6VTI_ATTR_OKEY;
104 if (tb[IFLA_VTI_LOCAL]) {
105 nla_memcpy(&ip6vti->local, tb[IFLA_VTI_LOCAL],
sizeof(
struct in6_addr));
106 ip6vti->ip6vti_mask |= IP6VTI_ATTR_LOCAL;
109 if (tb[IFLA_VTI_REMOTE]) {
110 nla_memcpy(&ip6vti->remote, tb[IFLA_VTI_REMOTE],
sizeof(
struct in6_addr));
111 ip6vti->ip6vti_mask |= IP6VTI_ATTR_REMOTE;
114 if (tb[IFLA_VTI_FWMARK]) {
116 ip6vti->ip6vti_mask |= IP6VTI_ATTR_FWMARK;
125static int ip6vti_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
134 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_LINK)
137 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_IKEY)
140 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_OKEY)
143 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_LOCAL)
144 NLA_PUT(msg, IFLA_VTI_LOCAL,
sizeof(
struct in6_addr), &ip6vti->local);
146 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_REMOTE)
147 NLA_PUT(msg, IFLA_VTI_REMOTE,
sizeof(
struct in6_addr), &ip6vti->remote);
149 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_FWMARK)
159static void ip6vti_free(
struct rtnl_link *link)
169 nl_dump(p,
"ip6vti : %s", link->l_name);
176 char addr[INET6_ADDRSTRLEN];
178 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_LINK) {
182 nl_dump_line(p,
"%s\n", name);
184 nl_dump_line(p,
"%u\n", ip6vti->link);
187 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_IKEY) {
189 nl_dump_line(p,
"%x\n",ip6vti->ikey);
192 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_OKEY) {
194 nl_dump_line(p,
"%x\n", ip6vti->okey);
197 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_LOCAL) {
199 nl_dump_line(p,
"%s\n",
200 _nl_inet_ntop(AF_INET6, &ip6vti->local, addr));
203 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_REMOTE) {
205 nl_dump_line(p,
"%s\n",
206 _nl_inet_ntop(AF_INET6, &ip6vti->remote, addr));
209 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_FWMARK) {
211 nl_dump_line(p,
"%x\n", ip6vti->fwmark);
217 struct ip6vti_info *ip6vti_dst, *ip6vti_src = src->l_info;
226 ip6vti_dst = dst->l_info;
228 if (!ip6vti_dst || !ip6vti_src)
231 memcpy(ip6vti_dst, ip6vti_src,
sizeof(
struct ip6vti_info));
236static struct rtnl_link_info_ops ip6vti_info_ops = {
238 .io_alloc = ip6vti_alloc,
239 .io_parse = ip6vti_parse,
244 .io_clone = ip6vti_clone,
245 .io_put_attrs = ip6vti_put_attrs,
246 .io_free = ip6vti_free,
249#define IS_IP6VTI_LINK_ASSERT(link) \
250 if ((link)->l_info_ops != &ip6vti_info_ops) { \
251 APPBUG("Link is not a ip6vti link. set type \"vti6\" first."); \
252 return -NLE_OPNOTSUPP; \
255#define HAS_IP6VTI_ATTR_ASSERT(ip6vti,attr) \
256 if (!((ip6vti)->ip6vti_mask & (attr))) \
259struct rtnl_link *rtnl_link_ip6vti_alloc(
void)
285 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
"vti6");
300 link = rtnl_link_ip6vti_alloc();
323 IS_IP6VTI_LINK_ASSERT(link);
325 ip6vti->link = index;
326 ip6vti->ip6vti_mask |= IP6VTI_ATTR_LINK;
342 IS_IP6VTI_LINK_ASSERT(link);
344 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_LINK);
346 *index = ip6vti->link;
362 IS_IP6VTI_LINK_ASSERT(link);
365 ip6vti->ip6vti_mask |= IP6VTI_ATTR_IKEY;
381 IS_IP6VTI_LINK_ASSERT(link);
383 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_IKEY);
385 *ikey = ip6vti->ikey;
401 IS_IP6VTI_LINK_ASSERT(link);
404 ip6vti->ip6vti_mask |= IP6VTI_ATTR_OKEY;
420 IS_IP6VTI_LINK_ASSERT(link);
422 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_OKEY);
424 *okey = ip6vti->okey;
440 IS_IP6VTI_LINK_ASSERT(link);
442 memcpy(&ip6vti->local, local,
sizeof(
struct in6_addr));
443 ip6vti->ip6vti_mask |= IP6VTI_ATTR_LOCAL;
459 IS_IP6VTI_LINK_ASSERT(link);
461 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_LOCAL);
463 memcpy(local, &ip6vti->local,
sizeof(
struct in6_addr));
479 IS_IP6VTI_LINK_ASSERT(link);
481 memcpy(&ip6vti->remote, remote,
sizeof(
struct in6_addr));
482 ip6vti->ip6vti_mask |= IP6VTI_ATTR_REMOTE;
498 IS_IP6VTI_LINK_ASSERT(link);
500 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_REMOTE);
502 memcpy(remote, &ip6vti->remote,
sizeof(
struct in6_addr));
518 IS_IP6VTI_LINK_ASSERT(link);
520 ip6vti->fwmark = fwmark;
521 ip6vti->ip6vti_mask |= IP6VTI_ATTR_FWMARK;
537 IS_IP6VTI_LINK_ASSERT(link);
539 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_FWMARK);
541 *fwmark = ip6vti->fwmark;
546static void __init ip6vti_init(
void)
551static void __exit ip6vti_exit(
void)
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
int rtnl_link_ip6vti_add(struct nl_sock *sk, const char *name)
Create a new vti6 tunnel device.
int rtnl_link_ip6vti_get_link(struct rtnl_link *link, uint32_t *index)
Get IP6VTI tunnel interface index.
int rtnl_link_ip6vti_get_local(struct rtnl_link *link, struct in6_addr *local)
Get IP6VTI tunnel local address.
int rtnl_link_ip6vti_set_link(struct rtnl_link *link, uint32_t index)
Set IP6VTI tunnel interface index.
int rtnl_link_ip6vti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
Get IP6VTI tunnel fwmark.
int rtnl_link_ip6vti_set_remote(struct rtnl_link *link, struct in6_addr *remote)
Set IP6VTI tunnel remote address.
int rtnl_link_ip6vti_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
Set IP6VTI tunnel fwmark.
int rtnl_link_is_ip6vti(struct rtnl_link *link)
Check if link is a IP6VTI link.
int rtnl_link_ip6vti_set_local(struct rtnl_link *link, struct in6_addr *local)
Set IP6VTI tunnel local address.
int rtnl_link_ip6vti_set_okey(struct rtnl_link *link, uint32_t okey)
Set IP6VTI tunnel set okey.
int rtnl_link_ip6vti_get_remote(struct rtnl_link *link, struct in6_addr *remote)
Get IP6VTI tunnel remote address.
int rtnl_link_ip6vti_get_okey(struct rtnl_link *link, uint32_t *okey)
Get IP6VTI tunnel okey.
int rtnl_link_ip6vti_set_ikey(struct rtnl_link *link, uint32_t ikey)
Set IP6VTI tunnel set ikey.
int rtnl_link_ip6vti_get_ikey(struct rtnl_link *link, uint32_t *ikey)
Get IP6VTI tunnel ikey.
int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
Register operations for a link info type.
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
Unregister operations for a link info type.
int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags)
Add virtual link.
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
void rtnl_link_set_name(struct rtnl_link *link, const char *name)
Set name of link object.
char * rtnl_link_get_name(struct rtnl_link *link)
Return name of link object.
void rtnl_link_put(struct rtnl_link *link)
Return a link object reference.
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
@ NL_DUMP_LINE
Dump object briefly on one line.
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Attribute validation policy.
uint16_t type
Type of attribute or NLA_UNSPEC.