19#include "nl-default.h"
21#include <linux/if_tunnel.h>
23#include <netlink/netlink.h>
24#include <netlink/attr.h>
25#include <netlink/utils.h>
26#include <netlink/object.h>
27#include <netlink/route/rtnl.h>
28#include <netlink/route/link/ipgre.h>
32#include "nl-aux-route/nl-route.h"
34#define IPGRE_ATTR_LINK (1 << 0)
35#define IPGRE_ATTR_IFLAGS (1 << 1)
36#define IPGRE_ATTR_OFLAGS (1 << 2)
37#define IPGRE_ATTR_IKEY (1 << 3)
38#define IPGRE_ATTR_OKEY (1 << 4)
39#define IPGRE_ATTR_LOCAL (1 << 5)
40#define IPGRE_ATTR_REMOTE (1 << 6)
41#define IPGRE_ATTR_TTL (1 << 7)
42#define IPGRE_ATTR_TOS (1 << 8)
43#define IPGRE_ATTR_PMTUDISC (1 << 9)
44#define IPGRE_ATTR_FWMARK (1 << 10)
62static struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
63 [IFLA_GRE_LINK] = { .type =
NLA_U32 },
64 [IFLA_GRE_IFLAGS] = { .type =
NLA_U16 },
65 [IFLA_GRE_OFLAGS] = { .type =
NLA_U16 },
66 [IFLA_GRE_IKEY] = { .type =
NLA_U32 },
67 [IFLA_GRE_OKEY] = { .type =
NLA_U32 },
68 [IFLA_GRE_LOCAL] = { .type =
NLA_U32 },
69 [IFLA_GRE_REMOTE] = { .type =
NLA_U32 },
70 [IFLA_GRE_TTL] = { .type =
NLA_U8 },
71 [IFLA_GRE_TOS] = { .type =
NLA_U8 },
72 [IFLA_GRE_PMTUDISC] = { .type =
NLA_U8 },
73 [IFLA_GRE_FWMARK] = { .type =
NLA_U32 },
76static int ipgre_alloc(
struct rtnl_link *link)
81 memset(link->l_info, 0,
sizeof(*ipgre));
83 ipgre = calloc(1,
sizeof(*ipgre));
93static int ipgre_parse(
struct rtnl_link *link,
struct nlattr *data,
94 struct nlattr *xstats)
96 struct nlattr *tb[IFLA_GRE_MAX + 1];
100 NL_DBG(3,
"Parsing IPGRE link info\n");
106 err = ipgre_alloc(link);
110 ipgre = link->l_info;
112 if (tb[IFLA_GRE_LINK]) {
114 ipgre->ipgre_mask |= IPGRE_ATTR_LINK;
117 if (tb[IFLA_GRE_IFLAGS]) {
119 ipgre->ipgre_mask |= IPGRE_ATTR_IFLAGS;
122 if (tb[IFLA_GRE_OFLAGS]) {
124 ipgre->ipgre_mask |= IPGRE_ATTR_OFLAGS;
127 if (tb[IFLA_GRE_IKEY]) {
129 ipgre->ipgre_mask |= IPGRE_ATTR_IKEY;
132 if (tb[IFLA_GRE_OKEY]) {
134 ipgre->ipgre_mask |= IPGRE_ATTR_OKEY;
137 if (tb[IFLA_GRE_LOCAL]) {
139 ipgre->ipgre_mask |= IPGRE_ATTR_LOCAL;
142 if (tb[IFLA_GRE_REMOTE]) {
144 ipgre->ipgre_mask |= IPGRE_ATTR_REMOTE;
147 if (tb[IFLA_GRE_TTL]) {
149 ipgre->ipgre_mask |= IPGRE_ATTR_TTL;
152 if (tb[IFLA_GRE_TOS]) {
154 ipgre->ipgre_mask |= IPGRE_ATTR_TOS;
157 if (tb[IFLA_GRE_PMTUDISC]) {
158 ipgre->pmtudisc =
nla_get_u8(tb[IFLA_GRE_PMTUDISC]);
159 ipgre->ipgre_mask |= IPGRE_ATTR_PMTUDISC;
162 if (tb[IFLA_GRE_FWMARK]) {
164 ipgre->ipgre_mask |= IPGRE_ATTR_FWMARK;
173static int ipgre_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
182 if (ipgre->ipgre_mask & IPGRE_ATTR_LINK)
185 if (ipgre->ipgre_mask & IPGRE_ATTR_IFLAGS)
188 if (ipgre->ipgre_mask & IPGRE_ATTR_OFLAGS)
191 if (ipgre->ipgre_mask & IPGRE_ATTR_IKEY)
194 if (ipgre->ipgre_mask & IPGRE_ATTR_OKEY)
197 if (ipgre->ipgre_mask & IPGRE_ATTR_LOCAL)
200 if (ipgre->ipgre_mask & IPGRE_ATTR_REMOTE)
203 if (ipgre->ipgre_mask & IPGRE_ATTR_TTL)
206 if (ipgre->ipgre_mask & IPGRE_ATTR_TOS)
209 if (ipgre->ipgre_mask & IPGRE_ATTR_PMTUDISC)
210 NLA_PUT_U8(msg, IFLA_GRE_PMTUDISC, ipgre->pmtudisc);
212 if (ipgre->ipgre_mask & IPGRE_ATTR_FWMARK)
222static void ipgre_free(
struct rtnl_link *link)
232 nl_dump(p,
"ipgre : %s", link->l_name);
238 char addr[INET_ADDRSTRLEN];
240 if (ipgre->ipgre_mask & IPGRE_ATTR_LINK) {
241 _nl_auto_rtnl_link
struct rtnl_link *parent = NULL;
247 parent = link_lookup(link->ce_cache, ipgre->link);
252 nl_dump_line(p,
"%s\n", name);
254 nl_dump_line(p,
"%u\n", ipgre->link);
257 if (ipgre->ipgre_mask & IPGRE_ATTR_IFLAGS) {
259 nl_dump_line(p,
"%x\n", ipgre->iflags);
262 if (ipgre->ipgre_mask & IPGRE_ATTR_OFLAGS) {
264 nl_dump_line(p,
"%x\n", ipgre->oflags);
267 if (ipgre->ipgre_mask & IPGRE_ATTR_IKEY) {
269 nl_dump_line(p,
"%x\n", ipgre->ikey);
272 if (ipgre->ipgre_mask & IPGRE_ATTR_OKEY) {
274 nl_dump_line(p,
"%x\n", ipgre->okey);
277 if (ipgre->ipgre_mask & IPGRE_ATTR_LOCAL) {
279 _nl_inet_ntop4(ipgre->local, addr);
280 nl_dump_line(p,
"%s\n", addr);
283 if (ipgre->ipgre_mask & IPGRE_ATTR_REMOTE) {
285 _nl_inet_ntop4(ipgre->remote, addr);
286 nl_dump_line(p,
"%s\n", addr);
289 if (ipgre->ipgre_mask & IPGRE_ATTR_TTL) {
291 nl_dump_line(p,
"%u\n", ipgre->ttl);
294 if (ipgre->ipgre_mask & IPGRE_ATTR_TOS) {
296 nl_dump_line(p,
"%u\n", ipgre->tos);
299 if (ipgre->ipgre_mask & IPGRE_ATTR_PMTUDISC) {
301 nl_dump_line(p,
"enabled (%#x)\n", ipgre->pmtudisc);
304 if (ipgre->ipgre_mask & IPGRE_ATTR_FWMARK) {
306 nl_dump_line(p,
"%x\n", ipgre->fwmark);
312 struct ipgre_info *ipgre_dst, *ipgre_src = src->l_info;
321 ipgre_dst = dst->l_info;
323 if (!ipgre_dst || !ipgre_src)
326 memcpy(ipgre_dst, ipgre_src,
sizeof(
struct ipgre_info));
333 struct ipgre_info *ipgre_dst, *ipgre_src = src->l_info;
342 ipgre_dst = dst->l_info;
344 if (!ipgre_dst || !ipgre_src)
347 memcpy(ipgre_dst, ipgre_src,
sizeof(
struct ipgre_info));
354 .io_alloc = ipgre_alloc,
355 .io_parse = ipgre_parse,
360 .io_clone = ipgre_clone,
361 .io_put_attrs = ipgre_put_attrs,
362 .io_free = ipgre_free,
367 .io_alloc = ipgre_alloc,
368 .io_parse = ipgre_parse,
373 .io_clone = ipgretap_clone,
374 .io_put_attrs = ipgre_put_attrs,
375 .io_free = ipgre_free,
378#define IS_IPGRE_LINK_ASSERT(link) \
379 if ((link)->l_info_ops != &ipgre_info_ops && \
380 (link)->l_info_ops != &ipgretap_info_ops) { \
381 APPBUG("Link is not a ipgre link. set type \"gre/gretap\" first.");\
382 return -NLE_OPNOTSUPP; \
385struct rtnl_link *rtnl_link_ipgre_alloc(
void)
411 return link->l_info_ops && !strcmp(link->l_info_ops->
io_name,
"gre");
427 link = rtnl_link_ipgre_alloc();
440struct rtnl_link *rtnl_link_ipgretap_alloc(
void)
466 return link->l_info_ops && !strcmp(link->l_info_ops->
io_name,
"gretap");
481 link = rtnl_link_ipgretap_alloc();
505 IS_IPGRE_LINK_ASSERT(link);
508 ipgre->ipgre_mask |= IPGRE_ATTR_LINK;
523 IS_IPGRE_LINK_ASSERT(link);
539 IS_IPGRE_LINK_ASSERT(link);
541 ipgre->iflags = iflags;
542 ipgre->ipgre_mask |= IPGRE_ATTR_IFLAGS;
557 IS_IPGRE_LINK_ASSERT(link);
559 return ipgre->iflags;
573 IS_IPGRE_LINK_ASSERT(link);
575 ipgre->oflags = oflags;
576 ipgre->ipgre_mask |= IPGRE_ATTR_OFLAGS;
591 IS_IPGRE_LINK_ASSERT(link);
593 return ipgre->oflags;
607 IS_IPGRE_LINK_ASSERT(link);
610 ipgre->ipgre_mask |= IPGRE_ATTR_IKEY;
625 IS_IPGRE_LINK_ASSERT(link);
641 IS_IPGRE_LINK_ASSERT(link);
644 ipgre->ipgre_mask |= IPGRE_ATTR_OKEY;
659 IS_IPGRE_LINK_ASSERT(link);
675 IS_IPGRE_LINK_ASSERT(link);
678 ipgre->ipgre_mask |= IPGRE_ATTR_LOCAL;
693 IS_IPGRE_LINK_ASSERT(link);
709 IS_IPGRE_LINK_ASSERT(link);
711 ipgre->remote = remote;
712 ipgre->ipgre_mask |= IPGRE_ATTR_REMOTE;
727 IS_IPGRE_LINK_ASSERT(link);
729 return ipgre->remote;
743 IS_IPGRE_LINK_ASSERT(link);
746 ipgre->ipgre_mask |= IPGRE_ATTR_TTL;
761 IS_IPGRE_LINK_ASSERT(link);
777 IS_IPGRE_LINK_ASSERT(link);
780 ipgre->ipgre_mask |= IPGRE_ATTR_TOS;
795 IS_IPGRE_LINK_ASSERT(link);
811 IS_IPGRE_LINK_ASSERT(link);
813 ipgre->pmtudisc = pmtudisc;
814 ipgre->ipgre_mask |= IPGRE_ATTR_PMTUDISC;
829 IS_IPGRE_LINK_ASSERT(link);
831 return ipgre->pmtudisc;
836uint8_t rtnl_link_get_pmtudisc(
struct rtnl_link *link);
838uint8_t rtnl_link_get_pmtudisc(
struct rtnl_link *link)
856 IS_IPGRE_LINK_ASSERT(link);
858 ipgre->fwmark = fwmark;
859 ipgre->ipgre_mask |= IPGRE_ATTR_FWMARK;
875 IS_IPGRE_LINK_ASSERT(link);
877 if (!(ipgre->ipgre_mask & IPGRE_ATTR_FWMARK))
880 *fwmark = ipgre->fwmark;
885static void _nl_init ipgre_init(
void)
891static void _nl_exit ipgre_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_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.
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.
uint32_t rtnl_link_ipgre_get_link(struct rtnl_link *link)
Get IPGRE tunnel interface index.
int rtnl_link_ipgre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
Get IPGRE tunnel fwmark.
int rtnl_link_ipgre_set_oflags(struct rtnl_link *link, uint16_t oflags)
Set IPGRE tunnel set oflags.
int rtnl_link_ipgretap_add(struct nl_sock *sk, const char *name)
Create a new IPGRETAP tunnel device.
int rtnl_link_ipgre_set_okey(struct rtnl_link *link, uint32_t okey)
Set IPGRE tunnel set okey.
int rtnl_link_is_ipgretap(struct rtnl_link *link)
Check if link is a IPGRETAP link.
uint16_t rtnl_link_ipgre_get_iflags(struct rtnl_link *link)
Get IPGRE tunnel iflags.
uint8_t rtnl_link_ipgre_get_tos(struct rtnl_link *link)
Get IPGRE tunnel tos.
uint8_t rtnl_link_ipgre_get_ttl(struct rtnl_link *link)
Set IPGRE tunnel ttl.
int rtnl_link_ipgre_set_local(struct rtnl_link *link, uint32_t addr)
Set IPGRE tunnel local address.
int rtnl_link_ipgre_set_link(struct rtnl_link *link, uint32_t index)
Set IPGRE tunnel interface index.
uint8_t rtnl_link_ipgre_get_pmtudisc(struct rtnl_link *link)
Get IPGRE path MTU discovery.
int rtnl_link_is_ipgre(struct rtnl_link *link)
Check if link is a IPGRE link.
int rtnl_link_ipgre_set_remote(struct rtnl_link *link, uint32_t remote)
Set IPGRE tunnel remote address.
int rtnl_link_ipgre_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc)
Set IPGRE tunnel path MTU discovery.
uint32_t rtnl_link_ipgre_get_ikey(struct rtnl_link *link)
Get IPGRE tunnel ikey.
uint32_t rtnl_link_ipgre_get_remote(struct rtnl_link *link)
Get IPGRE tunnel remote address.
int rtnl_link_ipgre_add(struct nl_sock *sk, const char *name)
Create a new IPGRE tunnel device.
int rtnl_link_ipgre_set_iflags(struct rtnl_link *link, uint16_t iflags)
Set IPGRE tunnel set iflags.
int rtnl_link_ipgre_set_tos(struct rtnl_link *link, uint8_t tos)
Set IPGRE tunnel tos.
uint16_t rtnl_link_ipgre_get_oflags(struct rtnl_link *link)
Get IPGRE tunnel oflags.
int rtnl_link_ipgre_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
Set IPGRE tunnel fwmark.
uint32_t rtnl_link_ipgre_get_okey(struct rtnl_link *link)
Get IPGRE tunnel okey.
uint32_t rtnl_link_ipgre_get_local(struct rtnl_link *link)
Get IPGRE tunnel local address.
int rtnl_link_ipgre_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IPGRE tunnel ttl.
int rtnl_link_ipgre_set_ikey(struct rtnl_link *link, uint32_t ikey)
Set IPGRE tunnel set 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)
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.
Available operations to modules implementing a link info type.
char * io_name
Name of link info type, must match name on kernel side.