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>
33#define IPGRE_ATTR_LINK (1 << 0)
34#define IPGRE_ATTR_IFLAGS (1 << 1)
35#define IPGRE_ATTR_OFLAGS (1 << 2)
36#define IPGRE_ATTR_IKEY (1 << 3)
37#define IPGRE_ATTR_OKEY (1 << 4)
38#define IPGRE_ATTR_LOCAL (1 << 5)
39#define IPGRE_ATTR_REMOTE (1 << 6)
40#define IPGRE_ATTR_TTL (1 << 7)
41#define IPGRE_ATTR_TOS (1 << 8)
42#define IPGRE_ATTR_PMTUDISC (1 << 9)
43#define IPGRE_ATTR_FWMARK (1 << 10)
61static struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
63 [IFLA_GRE_IFLAGS] = { .type =
NLA_U16 },
64 [IFLA_GRE_OFLAGS] = { .type =
NLA_U16 },
65 [IFLA_GRE_IKEY] = { .type =
NLA_U32 },
66 [IFLA_GRE_OKEY] = { .type =
NLA_U32 },
67 [IFLA_GRE_LOCAL] = { .type =
NLA_U32 },
68 [IFLA_GRE_REMOTE] = { .type =
NLA_U32 },
69 [IFLA_GRE_TTL] = { .type =
NLA_U8 },
70 [IFLA_GRE_TOS] = { .type =
NLA_U8 },
71 [IFLA_GRE_PMTUDISC] = { .type =
NLA_U8 },
72 [IFLA_GRE_FWMARK] = { .type =
NLA_U32 },
75static int ipgre_alloc(
struct rtnl_link *link)
80 memset(link->l_info, 0,
sizeof(*ipgre));
82 ipgre = calloc(1,
sizeof(*ipgre));
92static int ipgre_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 IPGRE link info\n");
105 err = ipgre_alloc(link);
109 ipgre = link->l_info;
111 if (tb[IFLA_GRE_LINK]) {
113 ipgre->ipgre_mask |= IPGRE_ATTR_LINK;
116 if (tb[IFLA_GRE_IFLAGS]) {
118 ipgre->ipgre_mask |= IPGRE_ATTR_IFLAGS;
121 if (tb[IFLA_GRE_OFLAGS]) {
123 ipgre->ipgre_mask |= IPGRE_ATTR_OFLAGS;
126 if (tb[IFLA_GRE_IKEY]) {
128 ipgre->ipgre_mask |= IPGRE_ATTR_IKEY;
131 if (tb[IFLA_GRE_OKEY]) {
133 ipgre->ipgre_mask |= IPGRE_ATTR_OKEY;
136 if (tb[IFLA_GRE_LOCAL]) {
138 ipgre->ipgre_mask |= IPGRE_ATTR_LOCAL;
141 if (tb[IFLA_GRE_REMOTE]) {
143 ipgre->ipgre_mask |= IPGRE_ATTR_REMOTE;
146 if (tb[IFLA_GRE_TTL]) {
148 ipgre->ipgre_mask |= IPGRE_ATTR_TTL;
151 if (tb[IFLA_GRE_TOS]) {
153 ipgre->ipgre_mask |= IPGRE_ATTR_TOS;
156 if (tb[IFLA_GRE_PMTUDISC]) {
157 ipgre->pmtudisc =
nla_get_u8(tb[IFLA_GRE_PMTUDISC]);
158 ipgre->ipgre_mask |= IPGRE_ATTR_PMTUDISC;
161 if (tb[IFLA_GRE_FWMARK]) {
163 ipgre->ipgre_mask |= IPGRE_ATTR_FWMARK;
172static int ipgre_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
181 if (ipgre->ipgre_mask & IPGRE_ATTR_LINK)
184 if (ipgre->ipgre_mask & IFLA_GRE_IFLAGS)
187 if (ipgre->ipgre_mask & IFLA_GRE_OFLAGS)
190 if (ipgre->ipgre_mask & IPGRE_ATTR_IKEY)
193 if (ipgre->ipgre_mask & IPGRE_ATTR_OKEY)
196 if (ipgre->ipgre_mask & IPGRE_ATTR_LOCAL)
199 if (ipgre->ipgre_mask & IPGRE_ATTR_REMOTE)
202 if (ipgre->ipgre_mask & IPGRE_ATTR_TTL)
205 if (ipgre->ipgre_mask & IPGRE_ATTR_TOS)
208 if (ipgre->ipgre_mask & IPGRE_ATTR_PMTUDISC)
209 NLA_PUT_U8(msg, IFLA_GRE_PMTUDISC, ipgre->pmtudisc);
211 if (ipgre->ipgre_mask & IPGRE_ATTR_FWMARK)
221static void ipgre_free(
struct rtnl_link *link)
231 nl_dump(p,
"ipgre : %s", link->l_name);
237 char *name, addr[INET_ADDRSTRLEN];
240 if (ipgre->ipgre_mask & IPGRE_ATTR_LINK) {
244 parent = link_lookup(link->ce_cache, ipgre->link);
249 nl_dump_line(p,
"%s\n", name);
251 nl_dump_line(p,
"%u\n", ipgre->link);
254 if (ipgre->ipgre_mask & IPGRE_ATTR_IFLAGS) {
256 nl_dump_line(p,
"%x\n", ipgre->iflags);
259 if (ipgre->ipgre_mask & IPGRE_ATTR_OFLAGS) {
261 nl_dump_line(p,
"%x\n", ipgre->oflags);
264 if (ipgre->ipgre_mask & IPGRE_ATTR_IKEY) {
266 nl_dump_line(p,
"%x\n",ipgre->ikey);
269 if (ipgre->ipgre_mask & IPGRE_ATTR_OKEY) {
271 nl_dump_line(p,
"%x\n", ipgre->okey);
274 if (ipgre->ipgre_mask & IPGRE_ATTR_LOCAL) {
276 if(inet_ntop(AF_INET, &ipgre->local, addr,
sizeof(addr)))
277 nl_dump_line(p,
"%s\n", addr);
279 nl_dump_line(p,
"%#x\n", ntohs(ipgre->local));
282 if (ipgre->ipgre_mask & IPGRE_ATTR_REMOTE) {
284 if(inet_ntop(AF_INET, &ipgre->remote, addr,
sizeof(addr)))
285 nl_dump_line(p,
"%s\n", addr);
287 nl_dump_line(p,
"%#x\n", ntohs(ipgre->remote));
290 if (ipgre->ipgre_mask & IPGRE_ATTR_TTL) {
292 nl_dump_line(p,
"%u\n", ipgre->ttl);
295 if (ipgre->ipgre_mask & IPGRE_ATTR_TOS) {
297 nl_dump_line(p,
"%u\n", ipgre->tos);
300 if (ipgre->ipgre_mask & IPGRE_ATTR_PMTUDISC) {
302 nl_dump_line(p,
"enabled (%#x)\n", ipgre->pmtudisc);
305 if (ipgre->ipgre_mask & IPGRE_ATTR_FWMARK) {
307 nl_dump_line(p,
"%x\n", ipgre->fwmark);
313 struct ipgre_info *ipgre_dst, *ipgre_src = src->l_info;
322 ipgre_dst = dst->l_info;
324 if (!ipgre_dst || !ipgre_src)
327 memcpy(ipgre_dst, ipgre_src,
sizeof(
struct ipgre_info));
334 struct ipgre_info *ipgre_dst, *ipgre_src = src->l_info;
343 ipgre_dst = dst->l_info;
345 if (!ipgre_dst || !ipgre_src)
348 memcpy(ipgre_dst, ipgre_src,
sizeof(
struct ipgre_info));
355 .io_alloc = ipgre_alloc,
356 .io_parse = ipgre_parse,
361 .io_clone = ipgre_clone,
362 .io_put_attrs = ipgre_put_attrs,
363 .io_free = ipgre_free,
368 .io_alloc = ipgre_alloc,
369 .io_parse = ipgre_parse,
374 .io_clone = ipgretap_clone,
375 .io_put_attrs = ipgre_put_attrs,
376 .io_free = ipgre_free,
379#define IS_IPGRE_LINK_ASSERT(link) \
380 if ((link)->l_info_ops != &ipgre_info_ops && \
381 (link)->l_info_ops != &ipgretap_info_ops) { \
382 APPBUG("Link is not a ipgre link. set type \"gre/gretap\" first.");\
383 return -NLE_OPNOTSUPP; \
386struct rtnl_link *rtnl_link_ipgre_alloc(
void)
412 return link->l_info_ops && !strcmp(link->l_info_ops->
io_name,
"gre");
428 link = rtnl_link_ipgre_alloc();
441struct rtnl_link *rtnl_link_ipgretap_alloc(
void)
467 return link->l_info_ops && !strcmp(link->l_info_ops->
io_name,
"gretap");
482 link = rtnl_link_ipgretap_alloc();
506 IS_IPGRE_LINK_ASSERT(link);
509 ipgre->ipgre_mask |= IPGRE_ATTR_LINK;
524 IS_IPGRE_LINK_ASSERT(link);
540 IS_IPGRE_LINK_ASSERT(link);
542 ipgre->iflags = iflags;
543 ipgre->ipgre_mask |= IPGRE_ATTR_IFLAGS;
558 IS_IPGRE_LINK_ASSERT(link);
560 return ipgre->iflags;
574 IS_IPGRE_LINK_ASSERT(link);
576 ipgre->oflags = oflags;
577 ipgre->ipgre_mask |= IPGRE_ATTR_OFLAGS;
592 IS_IPGRE_LINK_ASSERT(link);
594 return ipgre->oflags;
608 IS_IPGRE_LINK_ASSERT(link);
611 ipgre->ipgre_mask |= IPGRE_ATTR_IKEY;
626 IS_IPGRE_LINK_ASSERT(link);
642 IS_IPGRE_LINK_ASSERT(link);
645 ipgre->ipgre_mask |= IPGRE_ATTR_OKEY;
660 IS_IPGRE_LINK_ASSERT(link);
676 IS_IPGRE_LINK_ASSERT(link);
679 ipgre->ipgre_mask |= IPGRE_ATTR_LOCAL;
694 IS_IPGRE_LINK_ASSERT(link);
710 IS_IPGRE_LINK_ASSERT(link);
712 ipgre->remote = remote;
713 ipgre->ipgre_mask |= IPGRE_ATTR_REMOTE;
728 IS_IPGRE_LINK_ASSERT(link);
730 return ipgre->remote;
744 IS_IPGRE_LINK_ASSERT(link);
747 ipgre->ipgre_mask |= IPGRE_ATTR_TTL;
762 IS_IPGRE_LINK_ASSERT(link);
778 IS_IPGRE_LINK_ASSERT(link);
781 ipgre->ipgre_mask |= IPGRE_ATTR_TOS;
796 IS_IPGRE_LINK_ASSERT(link);
812 IS_IPGRE_LINK_ASSERT(link);
814 ipgre->pmtudisc = pmtudisc;
815 ipgre->ipgre_mask |= IPGRE_ATTR_PMTUDISC;
830 IS_IPGRE_LINK_ASSERT(link);
832 return ipgre->pmtudisc;
837uint8_t rtnl_link_get_pmtudisc(
struct rtnl_link *link);
839uint8_t rtnl_link_get_pmtudisc(
struct rtnl_link *link)
857 IS_IPGRE_LINK_ASSERT(link);
859 ipgre->fwmark = fwmark;
860 ipgre->ipgre_mask |= IPGRE_ATTR_FWMARK;
876 IS_IPGRE_LINK_ASSERT(link);
878 if (!(ipgre->ipgre_mask & IPGRE_ATTR_FWMARK))
881 *fwmark = ipgre->fwmark;
886static void _nl_init ipgre_init(
void)
892static 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.
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.