19#include <netlink-private/netlink.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/ipgre.h>
26#include <netlink-private/route/link/api.h>
27#include <linux/if_tunnel.h>
29#define IPGRE_ATTR_LINK (1 << 0)
30#define IPGRE_ATTR_IFLAGS (1 << 1)
31#define IPGRE_ATTR_OFLAGS (1 << 2)
32#define IPGRE_ATTR_IKEY (1 << 3)
33#define IPGRE_ATTR_OKEY (1 << 4)
34#define IPGRE_ATTR_LOCAL (1 << 5)
35#define IPGRE_ATTR_REMOTE (1 << 6)
36#define IPGRE_ATTR_TTL (1 << 7)
37#define IPGRE_ATTR_TOS (1 << 8)
38#define IPGRE_ATTR_PMTUDISC (1 << 9)
39#define IPGRE_ATTR_FWMARK (1 << 10)
57static struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
59 [IFLA_GRE_IFLAGS] = { .type =
NLA_U16 },
60 [IFLA_GRE_OFLAGS] = { .type =
NLA_U16 },
61 [IFLA_GRE_IKEY] = { .type =
NLA_U32 },
62 [IFLA_GRE_OKEY] = { .type =
NLA_U32 },
63 [IFLA_GRE_LOCAL] = { .type =
NLA_U32 },
64 [IFLA_GRE_REMOTE] = { .type =
NLA_U32 },
65 [IFLA_GRE_TTL] = { .type =
NLA_U8 },
66 [IFLA_GRE_TOS] = { .type =
NLA_U8 },
67 [IFLA_GRE_PMTUDISC] = { .type =
NLA_U8 },
68 [IFLA_GRE_FWMARK] = { .type =
NLA_U32 },
71static int ipgre_alloc(
struct rtnl_link *link)
76 memset(link->l_info, 0,
sizeof(*ipgre));
78 ipgre = calloc(1,
sizeof(*ipgre));
88static int ipgre_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 IPGRE link info\n");
101 err = ipgre_alloc(link);
105 ipgre = link->l_info;
107 if (tb[IFLA_GRE_LINK]) {
109 ipgre->ipgre_mask |= IPGRE_ATTR_LINK;
112 if (tb[IFLA_GRE_IFLAGS]) {
114 ipgre->ipgre_mask |= IPGRE_ATTR_IFLAGS;
117 if (tb[IFLA_GRE_OFLAGS]) {
119 ipgre->ipgre_mask |= IPGRE_ATTR_OFLAGS;
122 if (tb[IFLA_GRE_IKEY]) {
124 ipgre->ipgre_mask |= IPGRE_ATTR_IKEY;
127 if (tb[IFLA_GRE_OKEY]) {
129 ipgre->ipgre_mask |= IPGRE_ATTR_OKEY;
132 if (tb[IFLA_GRE_LOCAL]) {
134 ipgre->ipgre_mask |= IPGRE_ATTR_LOCAL;
137 if (tb[IFLA_GRE_REMOTE]) {
139 ipgre->ipgre_mask |= IPGRE_ATTR_REMOTE;
142 if (tb[IFLA_GRE_TTL]) {
144 ipgre->ipgre_mask |= IPGRE_ATTR_TTL;
147 if (tb[IFLA_GRE_TOS]) {
149 ipgre->ipgre_mask |= IPGRE_ATTR_TOS;
152 if (tb[IFLA_GRE_PMTUDISC]) {
153 ipgre->pmtudisc =
nla_get_u8(tb[IFLA_GRE_PMTUDISC]);
154 ipgre->ipgre_mask |= IPGRE_ATTR_PMTUDISC;
157 if (tb[IFLA_GRE_FWMARK]) {
159 ipgre->ipgre_mask |= IPGRE_ATTR_FWMARK;
168static int ipgre_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
177 if (ipgre->ipgre_mask & IPGRE_ATTR_LINK)
180 if (ipgre->ipgre_mask & IFLA_GRE_IFLAGS)
183 if (ipgre->ipgre_mask & IFLA_GRE_OFLAGS)
186 if (ipgre->ipgre_mask & IPGRE_ATTR_IKEY)
189 if (ipgre->ipgre_mask & IPGRE_ATTR_OKEY)
192 if (ipgre->ipgre_mask & IPGRE_ATTR_LOCAL)
195 if (ipgre->ipgre_mask & IPGRE_ATTR_REMOTE)
198 if (ipgre->ipgre_mask & IPGRE_ATTR_TTL)
201 if (ipgre->ipgre_mask & IPGRE_ATTR_TOS)
204 if (ipgre->ipgre_mask & IPGRE_ATTR_PMTUDISC)
205 NLA_PUT_U8(msg, IFLA_GRE_PMTUDISC, ipgre->pmtudisc);
207 if (ipgre->ipgre_mask & IPGRE_ATTR_FWMARK)
217static void ipgre_free(
struct rtnl_link *link)
227 nl_dump(p,
"ipgre : %s", link->l_name);
233 char *name, addr[INET_ADDRSTRLEN];
236 if (ipgre->ipgre_mask & IPGRE_ATTR_LINK) {
240 parent = link_lookup(link->ce_cache, ipgre->link);
245 nl_dump_line(p,
"%s\n", name);
247 nl_dump_line(p,
"%u\n", ipgre->link);
250 if (ipgre->ipgre_mask & IPGRE_ATTR_IFLAGS) {
252 nl_dump_line(p,
"%x\n", ipgre->iflags);
255 if (ipgre->ipgre_mask & IPGRE_ATTR_OFLAGS) {
257 nl_dump_line(p,
"%x\n", ipgre->oflags);
260 if (ipgre->ipgre_mask & IPGRE_ATTR_IKEY) {
262 nl_dump_line(p,
"%x\n",ipgre->ikey);
265 if (ipgre->ipgre_mask & IPGRE_ATTR_OKEY) {
267 nl_dump_line(p,
"%x\n", ipgre->okey);
270 if (ipgre->ipgre_mask & IPGRE_ATTR_LOCAL) {
272 if(inet_ntop(AF_INET, &ipgre->local, addr,
sizeof(addr)))
273 nl_dump_line(p,
"%s\n", addr);
275 nl_dump_line(p,
"%#x\n", ntohs(ipgre->local));
278 if (ipgre->ipgre_mask & IPGRE_ATTR_REMOTE) {
280 if(inet_ntop(AF_INET, &ipgre->remote, addr,
sizeof(addr)))
281 nl_dump_line(p,
"%s\n", addr);
283 nl_dump_line(p,
"%#x\n", ntohs(ipgre->remote));
286 if (ipgre->ipgre_mask & IPGRE_ATTR_TTL) {
288 nl_dump_line(p,
"%u\n", ipgre->ttl);
291 if (ipgre->ipgre_mask & IPGRE_ATTR_TOS) {
293 nl_dump_line(p,
"%u\n", ipgre->tos);
296 if (ipgre->ipgre_mask & IPGRE_ATTR_PMTUDISC) {
298 nl_dump_line(p,
"enabled (%#x)\n", ipgre->pmtudisc);
301 if (ipgre->ipgre_mask & IPGRE_ATTR_FWMARK) {
303 nl_dump_line(p,
"%x\n", ipgre->fwmark);
309 struct ipgre_info *ipgre_dst, *ipgre_src = src->l_info;
318 ipgre_dst = dst->l_info;
320 if (!ipgre_dst || !ipgre_src)
323 memcpy(ipgre_dst, ipgre_src,
sizeof(
struct ipgre_info));
330 struct ipgre_info *ipgre_dst, *ipgre_src = src->l_info;
339 ipgre_dst = dst->l_info;
341 if (!ipgre_dst || !ipgre_src)
344 memcpy(ipgre_dst, ipgre_src,
sizeof(
struct ipgre_info));
349static struct rtnl_link_info_ops ipgre_info_ops = {
351 .io_alloc = ipgre_alloc,
352 .io_parse = ipgre_parse,
357 .io_clone = ipgre_clone,
358 .io_put_attrs = ipgre_put_attrs,
359 .io_free = ipgre_free,
362static struct rtnl_link_info_ops ipgretap_info_ops = {
364 .io_alloc = ipgre_alloc,
365 .io_parse = ipgre_parse,
370 .io_clone = ipgretap_clone,
371 .io_put_attrs = ipgre_put_attrs,
372 .io_free = ipgre_free,
375#define IS_IPGRE_LINK_ASSERT(link) \
376 if ((link)->l_info_ops != &ipgre_info_ops && \
377 (link)->l_info_ops != &ipgretap_info_ops) { \
378 APPBUG("Link is not a ipgre link. set type \"gre/gretap\" first.");\
379 return -NLE_OPNOTSUPP; \
382struct rtnl_link *rtnl_link_ipgre_alloc(
void)
408 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
"gre");
424 link = rtnl_link_ipgre_alloc();
437struct rtnl_link *rtnl_link_ipgretap_alloc(
void)
463 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
"gretap");
478 link = rtnl_link_ipgretap_alloc();
502 IS_IPGRE_LINK_ASSERT(link);
505 ipgre->ipgre_mask |= IPGRE_ATTR_LINK;
520 IS_IPGRE_LINK_ASSERT(link);
536 IS_IPGRE_LINK_ASSERT(link);
538 ipgre->iflags = iflags;
539 ipgre->ipgre_mask |= IPGRE_ATTR_IFLAGS;
554 IS_IPGRE_LINK_ASSERT(link);
556 return ipgre->iflags;
570 IS_IPGRE_LINK_ASSERT(link);
572 ipgre->oflags = oflags;
573 ipgre->ipgre_mask |= IPGRE_ATTR_OFLAGS;
588 IS_IPGRE_LINK_ASSERT(link);
590 return ipgre->oflags;
604 IS_IPGRE_LINK_ASSERT(link);
607 ipgre->ipgre_mask |= IPGRE_ATTR_IKEY;
622 IS_IPGRE_LINK_ASSERT(link);
638 IS_IPGRE_LINK_ASSERT(link);
641 ipgre->ipgre_mask |= IPGRE_ATTR_OKEY;
656 IS_IPGRE_LINK_ASSERT(link);
672 IS_IPGRE_LINK_ASSERT(link);
675 ipgre->ipgre_mask |= IPGRE_ATTR_LOCAL;
690 IS_IPGRE_LINK_ASSERT(link);
706 IS_IPGRE_LINK_ASSERT(link);
708 ipgre->remote = remote;
709 ipgre->ipgre_mask |= IPGRE_ATTR_REMOTE;
724 IS_IPGRE_LINK_ASSERT(link);
726 return ipgre->remote;
740 IS_IPGRE_LINK_ASSERT(link);
743 ipgre->ipgre_mask |= IPGRE_ATTR_TTL;
758 IS_IPGRE_LINK_ASSERT(link);
774 IS_IPGRE_LINK_ASSERT(link);
777 ipgre->ipgre_mask |= IPGRE_ATTR_TOS;
792 IS_IPGRE_LINK_ASSERT(link);
808 IS_IPGRE_LINK_ASSERT(link);
810 ipgre->pmtudisc = pmtudisc;
811 ipgre->ipgre_mask |= IPGRE_ATTR_PMTUDISC;
826 IS_IPGRE_LINK_ASSERT(link);
828 return ipgre->pmtudisc;
833uint8_t rtnl_link_get_pmtudisc(
struct rtnl_link *link);
835uint8_t rtnl_link_get_pmtudisc(
struct rtnl_link *link)
853 IS_IPGRE_LINK_ASSERT(link);
855 ipgre->fwmark = fwmark;
856 ipgre->ipgre_mask |= IPGRE_ATTR_FWMARK;
872 IS_IPGRE_LINK_ASSERT(link);
874 if (!(ipgre->ipgre_mask & IPGRE_ATTR_FWMARK))
877 *fwmark = ipgre->fwmark;
882static void __init ipgre_init(
void)
888static void __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)
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.