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/ip6gre.h>
23#include <netlink-private/route/link/api.h>
24#include <linux/if_tunnel.h>
26#define IP6GRE_ATTR_LINK (1 << 0)
27#define IP6GRE_ATTR_IFLAGS (1 << 1)
28#define IP6GRE_ATTR_OFLAGS (1 << 2)
29#define IP6GRE_ATTR_IKEY (1 << 3)
30#define IP6GRE_ATTR_OKEY (1 << 4)
31#define IP6GRE_ATTR_LOCAL (1 << 5)
32#define IP6GRE_ATTR_REMOTE (1 << 6)
33#define IP6GRE_ATTR_TTL (1 << 7)
34#define IP6GRE_ATTR_ENCAPLIMIT (1 << 8)
35#define IP6GRE_ATTR_FLOWINFO (1 << 9)
36#define IP6GRE_ATTR_FLAGS (1 << 10)
37#define IP6GRE_ATTR_FWMARK (1 << 11)
50 struct in6_addr local;
51 struct in6_addr remote;
56static struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
58 [IFLA_GRE_IFLAGS] = { .type =
NLA_U16 },
59 [IFLA_GRE_OFLAGS] = { .type =
NLA_U16 },
60 [IFLA_GRE_IKEY] = { .type =
NLA_U32 },
61 [IFLA_GRE_OKEY] = { .type =
NLA_U32 },
62 [IFLA_GRE_LOCAL] = { .minlen =
sizeof(
struct in6_addr) },
63 [IFLA_GRE_REMOTE] = { .minlen =
sizeof(
struct in6_addr) },
64 [IFLA_GRE_TTL] = { .type =
NLA_U8 },
65 [IFLA_GRE_ENCAP_LIMIT] = { .type =
NLA_U8 },
66 [IFLA_GRE_FLOWINFO] = { .type =
NLA_U32 },
67 [IFLA_GRE_FLAGS] = { .type =
NLA_U32 },
68 [IFLA_GRE_FWMARK] = { .type =
NLA_U32 },
71static int ip6gre_alloc(
struct rtnl_link *link)
76 memset(link->l_info, 0,
sizeof(*ip6gre));
78 ip6gre = calloc(1,
sizeof(*ip6gre));
82 link->l_info = ip6gre;
88static int ip6gre_parse(
struct rtnl_link *link,
struct nlattr *data,
89 struct nlattr *xstats)
91 struct nlattr *tb[IFLA_GRE_MAX + 1];
95 NL_DBG(3,
"Parsing IP6GRE link info\n");
101 err = ip6gre_alloc(link);
105 ip6gre = link->l_info;
107 if (tb[IFLA_GRE_LINK]) {
109 ip6gre->ip6gre_mask |= IP6GRE_ATTR_LINK;
112 if (tb[IFLA_GRE_IFLAGS]) {
114 ip6gre->ip6gre_mask |= IP6GRE_ATTR_IFLAGS;
117 if (tb[IFLA_GRE_OFLAGS]) {
119 ip6gre->ip6gre_mask |= IP6GRE_ATTR_OFLAGS;
122 if (tb[IFLA_GRE_IKEY]) {
124 ip6gre->ip6gre_mask |= IP6GRE_ATTR_IKEY;
127 if (tb[IFLA_GRE_OKEY]) {
129 ip6gre->ip6gre_mask |= IP6GRE_ATTR_OKEY;
132 if (tb[IFLA_GRE_LOCAL]) {
133 nla_memcpy(&ip6gre->local, tb[IFLA_GRE_LOCAL],
sizeof(
struct in6_addr));
134 ip6gre->ip6gre_mask |= IP6GRE_ATTR_LOCAL;
137 if (tb[IFLA_GRE_REMOTE]) {
138 nla_memcpy(&ip6gre->remote, tb[IFLA_GRE_REMOTE],
sizeof(
struct in6_addr));
139 ip6gre->ip6gre_mask |= IP6GRE_ATTR_REMOTE;
142 if (tb[IFLA_GRE_TTL]) {
144 ip6gre->ip6gre_mask |= IP6GRE_ATTR_TTL;
147 if (tb[IFLA_GRE_ENCAP_LIMIT]) {
148 ip6gre->encaplimit =
nla_get_u8(tb[IFLA_GRE_ENCAP_LIMIT]);
149 ip6gre->ip6gre_mask |= IP6GRE_ATTR_ENCAPLIMIT;
152 if (tb[IFLA_GRE_FLOWINFO]) {
153 ip6gre->flowinfo =
nla_get_u32(tb[IFLA_GRE_FLOWINFO]);
154 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLOWINFO;
157 if (tb[IFLA_GRE_FLAGS]) {
159 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLAGS;
162 if (tb[IFLA_GRE_FWMARK]) {
164 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FWMARK;
173static int ip6gre_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
182 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LINK)
185 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IFLAGS)
188 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OFLAGS)
191 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IKEY)
194 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OKEY)
197 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LOCAL)
198 NLA_PUT(msg, IFLA_GRE_LOCAL,
sizeof(
struct in6_addr), &ip6gre->local);
200 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_REMOTE)
201 NLA_PUT(msg, IFLA_GRE_REMOTE,
sizeof(
struct in6_addr), &ip6gre->remote);
203 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_TTL)
206 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_ENCAPLIMIT)
207 NLA_PUT_U8(msg, IFLA_GRE_ENCAP_LIMIT, ip6gre->encaplimit);
209 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLOWINFO)
210 NLA_PUT_U32(msg, IFLA_GRE_FLOWINFO, ip6gre->flowinfo);
212 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLAGS)
215 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FWMARK)
225static void ip6gre_free(
struct rtnl_link *link)
235 nl_dump(p,
"ip6gre : %s", link->l_name);
242 char addr[INET6_ADDRSTRLEN];
244 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LINK) {
248 nl_dump_line(p,
"%s\n", name);
250 nl_dump_line(p,
"%u\n", ip6gre->link);
253 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IFLAGS) {
255 nl_dump_line(p,
"%x\n", ip6gre->iflags);
258 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OFLAGS) {
260 nl_dump_line(p,
"%x\n", ip6gre->oflags);
263 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IKEY) {
265 nl_dump_line(p,
"%x\n",ip6gre->ikey);
268 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OKEY) {
270 nl_dump_line(p,
"%x\n", ip6gre->okey);
273 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LOCAL) {
275 nl_dump_line(p,
"%s\n",
276 _nl_inet_ntop(AF_INET6, &ip6gre->local, addr));
279 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_REMOTE) {
281 nl_dump_line(p,
"%s\n",
282 _nl_inet_ntop(AF_INET6, &ip6gre->remote, addr));
285 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_TTL) {
287 nl_dump_line(p,
"%u\n", ip6gre->ttl);
290 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_ENCAPLIMIT) {
292 nl_dump_line(p,
"%u\n", ip6gre->encaplimit);
295 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLOWINFO) {
297 nl_dump_line(p,
"%x\n", ip6gre->flowinfo);
300 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLAGS) {
302 nl_dump_line(p,
"%x\n", ip6gre->flags);
305 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FWMARK) {
307 nl_dump_line(p,
"%x\n", ip6gre->fwmark);
313 struct ip6gre_info *ip6gre_dst, *ip6gre_src = src->l_info;
322 ip6gre_dst = dst->l_info;
324 if (!ip6gre_dst || !ip6gre_src)
327 memcpy(ip6gre_dst, ip6gre_src,
sizeof(
struct ip6gre_info));
332static struct rtnl_link_info_ops ip6gre_info_ops = {
334 .io_alloc = ip6gre_alloc,
335 .io_parse = ip6gre_parse,
340 .io_clone = ip6gre_clone,
341 .io_put_attrs = ip6gre_put_attrs,
342 .io_free = ip6gre_free,
345#define IS_IP6GRE_LINK_ASSERT(link) \
346 if ((link)->l_info_ops != &ip6gre_info_ops) { \
347 APPBUG("Link is not a ip6gre link. set type \"ip6gre\" first.");\
348 return -NLE_OPNOTSUPP; \
351#define HAS_IP6GRE_ATTR_ASSERT(link,attr) \
352 if (!((link)->ip6gre_mask & (attr))) \
355struct rtnl_link *rtnl_link_ip6gre_alloc(
void)
381 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
"ip6gre");
397 link = rtnl_link_ip6gre_alloc();
421 IS_IP6GRE_LINK_ASSERT(link);
423 ip6gre->link = index;
424 ip6gre->ip6gre_mask |= IP6GRE_ATTR_LINK;
440 IS_IP6GRE_LINK_ASSERT(link);
442 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LINK);
444 *index = ip6gre->link;
460 IS_IP6GRE_LINK_ASSERT(link);
462 ip6gre->iflags = iflags;
463 ip6gre->ip6gre_mask |= IP6GRE_ATTR_IFLAGS;
479 IS_IP6GRE_LINK_ASSERT(link);
481 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IFLAGS);
483 *iflags = ip6gre->iflags;
499 IS_IP6GRE_LINK_ASSERT(link);
501 ip6gre->oflags = oflags;
502 ip6gre->ip6gre_mask |= IP6GRE_ATTR_OFLAGS;
518 IS_IP6GRE_LINK_ASSERT(link);
520 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OFLAGS);
522 *oflags = ip6gre->oflags;
538 IS_IP6GRE_LINK_ASSERT(link);
541 ip6gre->ip6gre_mask |= IP6GRE_ATTR_IKEY;
557 IS_IP6GRE_LINK_ASSERT(link);
559 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IKEY);
561 *ikey = ip6gre->ikey;
577 IS_IP6GRE_LINK_ASSERT(link);
580 ip6gre->ip6gre_mask |= IP6GRE_ATTR_OKEY;
596 IS_IP6GRE_LINK_ASSERT(link);
598 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OKEY);
600 *okey = ip6gre->okey;
616 IS_IP6GRE_LINK_ASSERT(link);
618 memcpy(&ip6gre->local, local,
sizeof(
struct in6_addr));
619 ip6gre->ip6gre_mask |= IP6GRE_ATTR_LOCAL;
635 IS_IP6GRE_LINK_ASSERT(link);
637 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LOCAL);
639 memcpy(local, &ip6gre->local,
sizeof(
struct in6_addr));
655 IS_IP6GRE_LINK_ASSERT(link);
657 memcpy(&ip6gre->remote, remote,
sizeof(
struct in6_addr));
658 ip6gre->ip6gre_mask |= IP6GRE_ATTR_REMOTE;
674 IS_IP6GRE_LINK_ASSERT(link);
676 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_REMOTE);
678 memcpy(remote, &ip6gre->remote,
sizeof(
struct in6_addr));
694 IS_IP6GRE_LINK_ASSERT(link);
697 ip6gre->ip6gre_mask |= IP6GRE_ATTR_TTL;
713 IS_IP6GRE_LINK_ASSERT(link);
715 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_TTL);
733 IS_IP6GRE_LINK_ASSERT(link);
735 ip6gre->encaplimit = encaplimit;
736 ip6gre->ip6gre_mask |= IP6GRE_ATTR_ENCAPLIMIT;
752 IS_IP6GRE_LINK_ASSERT(link);
754 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_ENCAPLIMIT);
756 *encaplimit = ip6gre->encaplimit;
772 IS_IP6GRE_LINK_ASSERT(link);
774 ip6gre->flowinfo = flowinfo;
775 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLOWINFO;
791 IS_IP6GRE_LINK_ASSERT(link);
793 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLOWINFO);
795 *flowinfo = ip6gre->flowinfo;
811 IS_IP6GRE_LINK_ASSERT(link);
813 ip6gre->flags = flags;
814 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLAGS;
830 IS_IP6GRE_LINK_ASSERT(link);
832 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLAGS);
834 *flags = ip6gre->flags;
850 IS_IP6GRE_LINK_ASSERT(link);
852 ip6gre->fwmark = fwmark;
853 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FWMARK;
869 IS_IP6GRE_LINK_ASSERT(link);
871 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FWMARK);
873 *fwmark = ip6gre->fwmark;
878static void __init ip6gre_init(
void)
883static void __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)
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.