16#include "nl-default.h"
18#include <linux/if_tunnel.h>
20#include <netlink/netlink.h>
21#include <netlink/attr.h>
22#include <netlink/utils.h>
23#include <netlink/object.h>
24#include <netlink/route/rtnl.h>
25#include <netlink/route/link/ip6gre.h>
30#define IP6GRE_ATTR_LINK (1 << 0)
31#define IP6GRE_ATTR_IFLAGS (1 << 1)
32#define IP6GRE_ATTR_OFLAGS (1 << 2)
33#define IP6GRE_ATTR_IKEY (1 << 3)
34#define IP6GRE_ATTR_OKEY (1 << 4)
35#define IP6GRE_ATTR_LOCAL (1 << 5)
36#define IP6GRE_ATTR_REMOTE (1 << 6)
37#define IP6GRE_ATTR_TTL (1 << 7)
38#define IP6GRE_ATTR_ENCAPLIMIT (1 << 8)
39#define IP6GRE_ATTR_FLOWINFO (1 << 9)
40#define IP6GRE_ATTR_FLAGS (1 << 10)
41#define IP6GRE_ATTR_FWMARK (1 << 11)
54 struct in6_addr local;
55 struct in6_addr remote;
60static struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
62 [IFLA_GRE_IFLAGS] = { .type =
NLA_U16 },
63 [IFLA_GRE_OFLAGS] = { .type =
NLA_U16 },
64 [IFLA_GRE_IKEY] = { .type =
NLA_U32 },
65 [IFLA_GRE_OKEY] = { .type =
NLA_U32 },
66 [IFLA_GRE_LOCAL] = { .minlen =
sizeof(
struct in6_addr) },
67 [IFLA_GRE_REMOTE] = { .minlen =
sizeof(
struct in6_addr) },
68 [IFLA_GRE_TTL] = { .type =
NLA_U8 },
69 [IFLA_GRE_ENCAP_LIMIT] = { .type =
NLA_U8 },
70 [IFLA_GRE_FLOWINFO] = { .type =
NLA_U32 },
71 [IFLA_GRE_FLAGS] = { .type =
NLA_U32 },
72 [IFLA_GRE_FWMARK] = { .type =
NLA_U32 },
75static int ip6gre_alloc(
struct rtnl_link *link)
80 memset(link->l_info, 0,
sizeof(*ip6gre));
82 ip6gre = calloc(1,
sizeof(*ip6gre));
86 link->l_info = ip6gre;
92static int ip6gre_parse(
struct rtnl_link *link,
struct nlattr *data,
93 struct nlattr *xstats)
95 struct nlattr *tb[IFLA_GRE_MAX + 1];
99 NL_DBG(3,
"Parsing IP6GRE link info\n");
105 err = ip6gre_alloc(link);
109 ip6gre = link->l_info;
111 if (tb[IFLA_GRE_LINK]) {
113 ip6gre->ip6gre_mask |= IP6GRE_ATTR_LINK;
116 if (tb[IFLA_GRE_IFLAGS]) {
118 ip6gre->ip6gre_mask |= IP6GRE_ATTR_IFLAGS;
121 if (tb[IFLA_GRE_OFLAGS]) {
123 ip6gre->ip6gre_mask |= IP6GRE_ATTR_OFLAGS;
126 if (tb[IFLA_GRE_IKEY]) {
128 ip6gre->ip6gre_mask |= IP6GRE_ATTR_IKEY;
131 if (tb[IFLA_GRE_OKEY]) {
133 ip6gre->ip6gre_mask |= IP6GRE_ATTR_OKEY;
136 if (tb[IFLA_GRE_LOCAL]) {
137 nla_memcpy(&ip6gre->local, tb[IFLA_GRE_LOCAL],
sizeof(
struct in6_addr));
138 ip6gre->ip6gre_mask |= IP6GRE_ATTR_LOCAL;
141 if (tb[IFLA_GRE_REMOTE]) {
142 nla_memcpy(&ip6gre->remote, tb[IFLA_GRE_REMOTE],
sizeof(
struct in6_addr));
143 ip6gre->ip6gre_mask |= IP6GRE_ATTR_REMOTE;
146 if (tb[IFLA_GRE_TTL]) {
148 ip6gre->ip6gre_mask |= IP6GRE_ATTR_TTL;
151 if (tb[IFLA_GRE_ENCAP_LIMIT]) {
152 ip6gre->encaplimit =
nla_get_u8(tb[IFLA_GRE_ENCAP_LIMIT]);
153 ip6gre->ip6gre_mask |= IP6GRE_ATTR_ENCAPLIMIT;
156 if (tb[IFLA_GRE_FLOWINFO]) {
157 ip6gre->flowinfo =
nla_get_u32(tb[IFLA_GRE_FLOWINFO]);
158 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLOWINFO;
161 if (tb[IFLA_GRE_FLAGS]) {
163 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLAGS;
166 if (tb[IFLA_GRE_FWMARK]) {
168 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FWMARK;
177static int ip6gre_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
186 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LINK)
189 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IFLAGS)
192 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OFLAGS)
195 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IKEY)
198 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OKEY)
201 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LOCAL)
202 NLA_PUT(msg, IFLA_GRE_LOCAL,
sizeof(
struct in6_addr), &ip6gre->local);
204 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_REMOTE)
205 NLA_PUT(msg, IFLA_GRE_REMOTE,
sizeof(
struct in6_addr), &ip6gre->remote);
207 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_TTL)
210 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_ENCAPLIMIT)
211 NLA_PUT_U8(msg, IFLA_GRE_ENCAP_LIMIT, ip6gre->encaplimit);
213 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLOWINFO)
214 NLA_PUT_U32(msg, IFLA_GRE_FLOWINFO, ip6gre->flowinfo);
216 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLAGS)
219 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FWMARK)
229static void ip6gre_free(
struct rtnl_link *link)
239 nl_dump(p,
"ip6gre : %s", link->l_name);
246 char addr[INET6_ADDRSTRLEN];
248 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LINK) {
252 nl_dump_line(p,
"%s\n", name);
254 nl_dump_line(p,
"%u\n", ip6gre->link);
257 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IFLAGS) {
259 nl_dump_line(p,
"%x\n", ip6gre->iflags);
262 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OFLAGS) {
264 nl_dump_line(p,
"%x\n", ip6gre->oflags);
267 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IKEY) {
269 nl_dump_line(p,
"%x\n",ip6gre->ikey);
272 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OKEY) {
274 nl_dump_line(p,
"%x\n", ip6gre->okey);
277 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LOCAL) {
279 nl_dump_line(p,
"%s\n",
280 _nl_inet_ntop(AF_INET6, &ip6gre->local, addr));
283 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_REMOTE) {
285 nl_dump_line(p,
"%s\n",
286 _nl_inet_ntop(AF_INET6, &ip6gre->remote, addr));
289 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_TTL) {
291 nl_dump_line(p,
"%u\n", ip6gre->ttl);
294 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_ENCAPLIMIT) {
296 nl_dump_line(p,
"%u\n", ip6gre->encaplimit);
299 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLOWINFO) {
301 nl_dump_line(p,
"%x\n", ip6gre->flowinfo);
304 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLAGS) {
306 nl_dump_line(p,
"%x\n", ip6gre->flags);
309 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FWMARK) {
311 nl_dump_line(p,
"%x\n", ip6gre->fwmark);
317 struct ip6gre_info *ip6gre_dst, *ip6gre_src = src->l_info;
326 ip6gre_dst = dst->l_info;
328 if (!ip6gre_dst || !ip6gre_src)
331 memcpy(ip6gre_dst, ip6gre_src,
sizeof(
struct ip6gre_info));
338 .io_alloc = ip6gre_alloc,
339 .io_parse = ip6gre_parse,
344 .io_clone = ip6gre_clone,
345 .io_put_attrs = ip6gre_put_attrs,
346 .io_free = ip6gre_free,
349#define IS_IP6GRE_LINK_ASSERT(link) \
350 if ((link)->l_info_ops != &ip6gre_info_ops) { \
351 APPBUG("Link is not a ip6gre link. set type \"ip6gre\" first.");\
352 return -NLE_OPNOTSUPP; \
355#define HAS_IP6GRE_ATTR_ASSERT(link,attr) \
356 if (!((link)->ip6gre_mask & (attr))) \
359struct rtnl_link *rtnl_link_ip6gre_alloc(
void)
385 return link->l_info_ops && !strcmp(link->l_info_ops->
io_name,
"ip6gre");
401 link = rtnl_link_ip6gre_alloc();
425 IS_IP6GRE_LINK_ASSERT(link);
427 ip6gre->link = index;
428 ip6gre->ip6gre_mask |= IP6GRE_ATTR_LINK;
444 IS_IP6GRE_LINK_ASSERT(link);
446 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LINK);
448 *index = ip6gre->link;
464 IS_IP6GRE_LINK_ASSERT(link);
466 ip6gre->iflags = iflags;
467 ip6gre->ip6gre_mask |= IP6GRE_ATTR_IFLAGS;
483 IS_IP6GRE_LINK_ASSERT(link);
485 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IFLAGS);
487 *iflags = ip6gre->iflags;
503 IS_IP6GRE_LINK_ASSERT(link);
505 ip6gre->oflags = oflags;
506 ip6gre->ip6gre_mask |= IP6GRE_ATTR_OFLAGS;
522 IS_IP6GRE_LINK_ASSERT(link);
524 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OFLAGS);
526 *oflags = ip6gre->oflags;
542 IS_IP6GRE_LINK_ASSERT(link);
545 ip6gre->ip6gre_mask |= IP6GRE_ATTR_IKEY;
561 IS_IP6GRE_LINK_ASSERT(link);
563 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IKEY);
565 *ikey = ip6gre->ikey;
581 IS_IP6GRE_LINK_ASSERT(link);
584 ip6gre->ip6gre_mask |= IP6GRE_ATTR_OKEY;
600 IS_IP6GRE_LINK_ASSERT(link);
602 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OKEY);
604 *okey = ip6gre->okey;
620 IS_IP6GRE_LINK_ASSERT(link);
622 memcpy(&ip6gre->local, local,
sizeof(
struct in6_addr));
623 ip6gre->ip6gre_mask |= IP6GRE_ATTR_LOCAL;
639 IS_IP6GRE_LINK_ASSERT(link);
641 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LOCAL);
643 memcpy(local, &ip6gre->local,
sizeof(
struct in6_addr));
659 IS_IP6GRE_LINK_ASSERT(link);
661 memcpy(&ip6gre->remote, remote,
sizeof(
struct in6_addr));
662 ip6gre->ip6gre_mask |= IP6GRE_ATTR_REMOTE;
678 IS_IP6GRE_LINK_ASSERT(link);
680 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_REMOTE);
682 memcpy(remote, &ip6gre->remote,
sizeof(
struct in6_addr));
698 IS_IP6GRE_LINK_ASSERT(link);
701 ip6gre->ip6gre_mask |= IP6GRE_ATTR_TTL;
717 IS_IP6GRE_LINK_ASSERT(link);
719 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_TTL);
737 IS_IP6GRE_LINK_ASSERT(link);
739 ip6gre->encaplimit = encaplimit;
740 ip6gre->ip6gre_mask |= IP6GRE_ATTR_ENCAPLIMIT;
756 IS_IP6GRE_LINK_ASSERT(link);
758 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_ENCAPLIMIT);
760 *encaplimit = ip6gre->encaplimit;
776 IS_IP6GRE_LINK_ASSERT(link);
778 ip6gre->flowinfo = flowinfo;
779 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLOWINFO;
795 IS_IP6GRE_LINK_ASSERT(link);
797 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLOWINFO);
799 *flowinfo = ip6gre->flowinfo;
815 IS_IP6GRE_LINK_ASSERT(link);
817 ip6gre->flags = flags;
818 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLAGS;
834 IS_IP6GRE_LINK_ASSERT(link);
836 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLAGS);
838 *flags = ip6gre->flags;
854 IS_IP6GRE_LINK_ASSERT(link);
856 ip6gre->fwmark = fwmark;
857 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FWMARK;
873 IS_IP6GRE_LINK_ASSERT(link);
875 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FWMARK);
877 *fwmark = ip6gre->fwmark;
882static void _nl_init ip6gre_init(
void)
887static void _nl_exit ip6gre_exit(
void)
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
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.
#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.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
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_ip6gre_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
Set IP6GRE tunnel fwmark.
int rtnl_link_ip6gre_set_flags(struct rtnl_link *link, uint32_t flags)
Set IP6GRE tunnel flags.
int rtnl_link_ip6gre_set_remote(struct rtnl_link *link, struct in6_addr *remote)
Set IP6GRE tunnel remote address.
int rtnl_link_ip6gre_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IP6GRE tunnel ttl.
int rtnl_link_ip6gre_get_oflags(struct rtnl_link *link, uint16_t *oflags)
Get IP6GRE tunnel oflags.
int rtnl_link_ip6gre_set_okey(struct rtnl_link *link, uint32_t okey)
Set IP6GRE tunnel set okey.
int rtnl_link_ip6gre_get_ttl(struct rtnl_link *link, uint8_t *ttl)
Set IP6GRE tunnel ttl.
int rtnl_link_ip6gre_set_iflags(struct rtnl_link *link, uint16_t iflags)
Set IP6GRE tunnel set iflags.
int rtnl_link_ip6gre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
Get IP6GRE tunnel fwmark.
int rtnl_link_ip6gre_set_link(struct rtnl_link *link, uint32_t index)
Set IP6GRE tunnel interface index.
int rtnl_link_ip6gre_get_ikey(struct rtnl_link *link, uint32_t *ikey)
Get IP6GRE tunnel ikey.
int rtnl_link_ip6gre_get_iflags(struct rtnl_link *link, uint16_t *iflags)
Get IP6GRE tunnel iflags.
int rtnl_link_ip6gre_get_flowinfo(struct rtnl_link *link, uint32_t *flowinfo)
Get IP6GRE flowinfo.
int rtnl_link_ip6gre_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo)
Set IP6GRE tunnel flowinfo.
int rtnl_link_ip6gre_set_encaplimit(struct rtnl_link *link, uint8_t encaplimit)
Set IP6GRE tunnel encap limit.
int rtnl_link_ip6gre_get_flags(struct rtnl_link *link, uint32_t *flags)
Get IP6GRE flags.
int rtnl_link_ip6gre_set_ikey(struct rtnl_link *link, uint32_t ikey)
Set IP6GRE tunnel set ikey.
int rtnl_link_ip6gre_set_local(struct rtnl_link *link, struct in6_addr *local)
Set IP6GRE tunnel local address.
int rtnl_link_ip6gre_get_link(struct rtnl_link *link, uint32_t *index)
Get IP6GRE tunnel interface index.
int rtnl_link_ip6gre_add(struct nl_sock *sk, const char *name)
Create a new IP6GRE tunnel device.
int rtnl_link_ip6gre_get_local(struct rtnl_link *link, struct in6_addr *local)
Get IP6GRE tunnel local address.
int rtnl_link_ip6gre_get_okey(struct rtnl_link *link, uint32_t *okey)
Get IP6GRE tunnel okey.
int rtnl_link_ip6gre_set_oflags(struct rtnl_link *link, uint16_t oflags)
Set IP6GRE tunnel set oflags.
int rtnl_link_ip6gre_get_encaplimit(struct rtnl_link *link, uint8_t *encaplimit)
Get IP6GRE tunnel encap limit.
int rtnl_link_is_ip6gre(struct rtnl_link *link)
Check if link is a IP6GRE link.
int rtnl_link_ip6gre_get_remote(struct rtnl_link *link, struct in6_addr *remote)
Get IP6GRE tunnel remote address.
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)
Release 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.
Available operations to modules implementing a link info type.
char * io_name
Name of link info type, must match name on kernel side.