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;
44 static 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 },
53 static 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;
70 static 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;
125 static 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)
159 static void ip6vti_free(
struct rtnl_link *link)
169 nl_dump(p,
"ip6vti : %s", link->l_name);
175 char *name, addr[INET6_ADDRSTRLEN];
177 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_LINK) {
181 nl_dump_line(p,
"%s\n", name);
183 nl_dump_line(p,
"%u\n", ip6vti->link);
186 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_IKEY) {
188 nl_dump_line(p,
"%x\n",ip6vti->ikey);
191 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_OKEY) {
193 nl_dump_line(p,
"%x\n", ip6vti->okey);
196 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_LOCAL) {
198 if(inet_ntop(AF_INET6, &ip6vti->local, addr,
sizeof(addr)))
199 nl_dump_line(p,
"%s\n", addr);
201 nl_dump_line(p,
"%#x\n", ip6vti->local);
204 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_REMOTE) {
206 if(inet_ntop(AF_INET6, &ip6vti->remote, addr,
sizeof(addr)))
207 nl_dump_line(p,
"%s\n", addr);
209 nl_dump_line(p,
"%#x\n", ip6vti->remote);
212 if (ip6vti->ip6vti_mask & IP6VTI_ATTR_FWMARK) {
214 nl_dump_line(p,
"%x\n", ip6vti->fwmark);
220 struct ip6vti_info *ip6vti_dst, *ip6vti_src = src->l_info;
229 ip6vti_dst = dst->l_info;
231 if (!ip6vti_dst || !ip6vti_src)
234 memcpy(ip6vti_dst, ip6vti_src,
sizeof(
struct ip6vti_info));
239 static struct rtnl_link_info_ops ip6vti_info_ops = {
241 .io_alloc = ip6vti_alloc,
242 .io_parse = ip6vti_parse,
247 .io_clone = ip6vti_clone,
248 .io_put_attrs = ip6vti_put_attrs,
249 .io_free = ip6vti_free,
252 #define IS_IP6VTI_LINK_ASSERT(link) \
253 if ((link)->l_info_ops != &ip6vti_info_ops) { \
254 APPBUG("Link is not a ip6vti link. set type \"vti6\" first."); \
255 return -NLE_OPNOTSUPP; \
258 #define HAS_IP6VTI_ATTR_ASSERT(ip6vti,attr) \
259 if (!((ip6vti)->ip6vti_mask & (attr))) \
262 struct rtnl_link *rtnl_link_ip6vti_alloc(
void)
288 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
"vti6");
303 link = rtnl_link_ip6vti_alloc();
326 IS_IP6VTI_LINK_ASSERT(link);
328 ip6vti->link = index;
329 ip6vti->ip6vti_mask |= IP6VTI_ATTR_LINK;
345 IS_IP6VTI_LINK_ASSERT(link);
347 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_LINK);
349 *index = ip6vti->link;
365 IS_IP6VTI_LINK_ASSERT(link);
368 ip6vti->ip6vti_mask |= IP6VTI_ATTR_IKEY;
384 IS_IP6VTI_LINK_ASSERT(link);
386 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_IKEY);
388 *ikey = ip6vti->ikey;
404 IS_IP6VTI_LINK_ASSERT(link);
407 ip6vti->ip6vti_mask |= IP6VTI_ATTR_OKEY;
423 IS_IP6VTI_LINK_ASSERT(link);
425 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_OKEY);
427 *okey = ip6vti->okey;
443 IS_IP6VTI_LINK_ASSERT(link);
445 memcpy(&ip6vti->local, local,
sizeof(
struct in6_addr));
446 ip6vti->ip6vti_mask |= IP6VTI_ATTR_LOCAL;
462 IS_IP6VTI_LINK_ASSERT(link);
464 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_LOCAL);
466 memcpy(local, &ip6vti->local,
sizeof(
struct in6_addr));
482 IS_IP6VTI_LINK_ASSERT(link);
484 memcpy(&ip6vti->remote, remote,
sizeof(
struct in6_addr));
485 ip6vti->ip6vti_mask |= IP6VTI_ATTR_REMOTE;
501 IS_IP6VTI_LINK_ASSERT(link);
503 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_REMOTE);
505 memcpy(remote, &ip6vti->remote,
sizeof(
struct in6_addr));
521 IS_IP6VTI_LINK_ASSERT(link);
523 ip6vti->fwmark = fwmark;
524 ip6vti->ip6vti_mask |= IP6VTI_ATTR_FWMARK;
540 IS_IP6VTI_LINK_ASSERT(link);
542 HAS_IP6VTI_ATTR_ASSERT(ip6vti, IP6VTI_ATTR_FWMARK);
544 *fwmark = ip6vti->fwmark;
549 static void __init ip6vti_init(
void)
554 static 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.
char * rtnl_link_get_name(struct rtnl_link *link)
Return name of link object.
void rtnl_link_set_name(struct rtnl_link *link, const char *name)
Set 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.
struct rtnl_link * rtnl_link_alloc(void)
Allocate 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.