25 #include <netlink-private/netlink.h> 26 #include <netlink/netlink.h> 27 #include <netlink/attr.h> 28 #include <netlink/utils.h> 29 #include <netlink/object.h> 30 #include <netlink/route/rtnl.h> 31 #include <netlink/route/link/ipgre.h> 32 #include <netlink-private/route/link/api.h> 33 #include <linux/if_tunnel.h> 35 #define IPGRE_ATTR_LINK (1 << 0) 36 #define IPGRE_ATTR_IFLAGS (1 << 1) 37 #define IPGRE_ATTR_OFLAGS (1 << 2) 38 #define IPGRE_ATTR_IKEY (1 << 3) 39 #define IPGRE_ATTR_OKEY (1 << 4) 40 #define IPGRE_ATTR_LOCAL (1 << 5) 41 #define IPGRE_ATTR_REMOTE (1 << 6) 42 #define IPGRE_ATTR_TTL (1 << 7) 43 #define IPGRE_ATTR_TOS (1 << 8) 44 #define IPGRE_ATTR_PMTUDISC (1 << 9) 61 static 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 },
74 static int ipgre_alloc(
struct rtnl_link *link)
79 memset(link->l_info, 0,
sizeof(*ipgre));
81 ipgre = calloc(1,
sizeof(*ipgre));
91 static int ipgre_parse(
struct rtnl_link *link,
struct nlattr *data,
92 struct nlattr *xstats)
94 struct nlattr *tb[IFLA_GRE_MAX + 1];
98 NL_DBG(3,
"Parsing IPGRE link info\n");
104 err = ipgre_alloc(link);
108 ipgre = link->l_info;
110 if (tb[IFLA_GRE_LINK]) {
112 ipgre->ipgre_mask |= IPGRE_ATTR_LINK;
115 if (tb[IFLA_GRE_IFLAGS]) {
117 ipgre->ipgre_mask |= IPGRE_ATTR_IFLAGS;
120 if (tb[IFLA_GRE_OFLAGS]) {
122 ipgre->ipgre_mask |= IPGRE_ATTR_OFLAGS;
125 if (tb[IFLA_GRE_IKEY]) {
127 ipgre->ipgre_mask |= IPGRE_ATTR_IKEY;
130 if (tb[IFLA_GRE_OKEY]) {
132 ipgre->ipgre_mask |= IPGRE_ATTR_OKEY;
135 if (tb[IFLA_GRE_LOCAL]) {
137 ipgre->ipgre_mask |= IPGRE_ATTR_LOCAL;
140 if (tb[IFLA_GRE_REMOTE]) {
142 ipgre->ipgre_mask |= IPGRE_ATTR_REMOTE;
145 if (tb[IFLA_GRE_TTL]) {
147 ipgre->ipgre_mask |= IPGRE_ATTR_TTL;
150 if (tb[IFLA_GRE_TOS]) {
152 ipgre->ipgre_mask |= IPGRE_ATTR_TOS;
155 if (tb[IFLA_GRE_PMTUDISC]) {
156 ipgre->pmtudisc =
nla_get_u8(tb[IFLA_GRE_PMTUDISC]);
157 ipgre->ipgre_mask |= IPGRE_ATTR_PMTUDISC;
166 static int ipgre_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
175 if (ipgre->ipgre_mask & IPGRE_ATTR_LINK)
178 if (ipgre->ipgre_mask & IFLA_GRE_IFLAGS)
181 if (ipgre->ipgre_mask & IFLA_GRE_OFLAGS)
184 if (ipgre->ipgre_mask & IPGRE_ATTR_IKEY)
187 if (ipgre->ipgre_mask & IPGRE_ATTR_OKEY)
190 if (ipgre->ipgre_mask & IPGRE_ATTR_LOCAL)
193 if (ipgre->ipgre_mask & IPGRE_ATTR_REMOTE)
196 if (ipgre->ipgre_mask & IPGRE_ATTR_TTL)
199 if (ipgre->ipgre_mask & IPGRE_ATTR_TOS)
202 if (ipgre->ipgre_mask & IPGRE_ATTR_PMTUDISC)
203 NLA_PUT_U8(msg, IFLA_GRE_PMTUDISC, ipgre->pmtudisc);
212 static void ipgre_free(
struct rtnl_link *link)
222 nl_dump(p,
"ipgre : %s", link->l_name);
228 char *name, addr[INET_ADDRSTRLEN];
231 if (ipgre->ipgre_mask & IPGRE_ATTR_LINK) {
235 parent = link_lookup(link->ce_cache, ipgre->link);
240 nl_dump_line(p,
"%s\n", name);
242 nl_dump_line(p,
"%u\n", ipgre->link);
245 if (ipgre->ipgre_mask & IPGRE_ATTR_IFLAGS) {
247 nl_dump_line(p,
"%x\n", ipgre->iflags);
250 if (ipgre->ipgre_mask & IPGRE_ATTR_OFLAGS) {
252 nl_dump_line(p,
"%x\n", ipgre->oflags);
255 if (ipgre->ipgre_mask & IPGRE_ATTR_IKEY) {
257 nl_dump_line(p,
"%x\n",ipgre->ikey);
260 if (ipgre->ipgre_mask & IPGRE_ATTR_OKEY) {
262 nl_dump_line(p,
"%x\n", ipgre->okey);
265 if (ipgre->ipgre_mask & IPGRE_ATTR_LOCAL) {
267 if(inet_ntop(AF_INET, &ipgre->local, addr,
sizeof(addr)))
268 nl_dump_line(p,
"%s\n", addr);
270 nl_dump_line(p,
"%#x\n", ntohs(ipgre->local));
273 if (ipgre->ipgre_mask & IPGRE_ATTR_REMOTE) {
275 if(inet_ntop(AF_INET, &ipgre->remote, addr,
sizeof(addr)))
276 nl_dump_line(p,
"%s\n", addr);
278 nl_dump_line(p,
"%#x\n", ntohs(ipgre->remote));
281 if (ipgre->ipgre_mask & IPGRE_ATTR_TTL) {
283 nl_dump_line(p,
"%u\n", ipgre->ttl);
286 if (ipgre->ipgre_mask & IPGRE_ATTR_TOS) {
288 nl_dump_line(p,
"%u\n", ipgre->tos);
291 if (ipgre->ipgre_mask & IPGRE_ATTR_PMTUDISC) {
293 nl_dump_line(p,
"enabled (%#x)\n", ipgre->pmtudisc);
299 struct ipgre_info *ipgre_dst, *ipgre_src = src->l_info;
308 ipgre_dst = dst->l_info;
310 if (!ipgre_dst || !ipgre_src)
313 memcpy(ipgre_dst, ipgre_src,
sizeof(
struct ipgre_info));
320 struct ipgre_info *ipgre_dst, *ipgre_src = src->l_info;
329 ipgre_dst = dst->l_info;
331 if (!ipgre_dst || !ipgre_src)
334 memcpy(ipgre_dst, ipgre_src,
sizeof(
struct ipgre_info));
339 static struct rtnl_link_info_ops ipgre_info_ops = {
341 .io_alloc = ipgre_alloc,
342 .io_parse = ipgre_parse,
347 .io_clone = ipgre_clone,
348 .io_put_attrs = ipgre_put_attrs,
349 .io_free = ipgre_free,
352 static struct rtnl_link_info_ops ipgretap_info_ops = {
354 .io_alloc = ipgre_alloc,
355 .io_parse = ipgre_parse,
360 .io_clone = ipgretap_clone,
361 .io_put_attrs = ipgre_put_attrs,
362 .io_free = ipgre_free,
365 #define IS_IPGRE_LINK_ASSERT(link) \ 366 if ((link)->l_info_ops != &ipgre_info_ops && \ 367 (link)->l_info_ops != &ipgretap_info_ops) { \ 368 APPBUG("Link is not a ipgre link. set type \"gre/gretap\" first.");\ 369 return -NLE_OPNOTSUPP; \ 372 struct rtnl_link *rtnl_link_ipgre_alloc(
void)
398 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
"gre");
414 link = rtnl_link_ipgre_alloc();
427 struct rtnl_link *rtnl_link_ipgretap_alloc(
void)
453 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
"gretap");
468 link = rtnl_link_ipgretap_alloc();
492 IS_IPGRE_LINK_ASSERT(link);
495 ipgre->ipgre_mask |= IPGRE_ATTR_LINK;
510 IS_IPGRE_LINK_ASSERT(link);
526 IS_IPGRE_LINK_ASSERT(link);
528 ipgre->iflags = iflags;
529 ipgre->ipgre_mask |= IPGRE_ATTR_IFLAGS;
544 IS_IPGRE_LINK_ASSERT(link);
546 return ipgre->iflags;
560 IS_IPGRE_LINK_ASSERT(link);
562 ipgre->oflags = oflags;
563 ipgre->ipgre_mask |= IPGRE_ATTR_OFLAGS;
578 IS_IPGRE_LINK_ASSERT(link);
580 return ipgre->oflags;
594 IS_IPGRE_LINK_ASSERT(link);
597 ipgre->ipgre_mask |= IPGRE_ATTR_IKEY;
612 IS_IPGRE_LINK_ASSERT(link);
628 IS_IPGRE_LINK_ASSERT(link);
631 ipgre->ipgre_mask |= IPGRE_ATTR_OKEY;
646 IS_IPGRE_LINK_ASSERT(link);
662 IS_IPGRE_LINK_ASSERT(link);
665 ipgre->ipgre_mask |= IPGRE_ATTR_LOCAL;
680 IS_IPGRE_LINK_ASSERT(link);
696 IS_IPGRE_LINK_ASSERT(link);
698 ipgre->remote = remote;
699 ipgre->ipgre_mask |= IPGRE_ATTR_REMOTE;
714 IS_IPGRE_LINK_ASSERT(link);
716 return ipgre->remote;
730 IS_IPGRE_LINK_ASSERT(link);
733 ipgre->ipgre_mask |= IPGRE_ATTR_TTL;
748 IS_IPGRE_LINK_ASSERT(link);
764 IS_IPGRE_LINK_ASSERT(link);
767 ipgre->ipgre_mask |= IPGRE_ATTR_TOS;
782 IS_IPGRE_LINK_ASSERT(link);
798 IS_IPGRE_LINK_ASSERT(link);
800 ipgre->pmtudisc = pmtudisc;
801 ipgre->ipgre_mask |= IPGRE_ATTR_PMTUDISC;
816 IS_IPGRE_LINK_ASSERT(link);
818 return ipgre->pmtudisc;
823 uint8_t rtnl_link_get_pmtudisc(
struct rtnl_link *link);
825 uint8_t rtnl_link_get_pmtudisc(
struct rtnl_link *link)
832 static void __init ipgre_init(
void)
838 static void __exit ipgre_exit(
void)
Dump object briefly on one line.
uint8_t rtnl_link_ipgre_get_ttl(struct rtnl_link *link)
Set IPGRE tunnel ttl.
int rtnl_link_is_ipgre(struct rtnl_link *link)
Check if link is a IPGRE link.
int rtnl_link_ipgre_set_tos(struct rtnl_link *link, uint8_t tos)
Set IPGRE tunnel tos.
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_ipgretap_add(struct nl_sock *sk, const char *name)
Create a new IPGRETAP tunnel device.
Attribute validation policy.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
int rtnl_link_ipgre_set_link(struct rtnl_link *link, uint32_t index)
Set IPGRE tunnel interface index.
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
uint32_t rtnl_link_ipgre_get_ikey(struct rtnl_link *link)
Get IPGRE tunnel ikey.
uint32_t rtnl_link_ipgre_get_link(struct rtnl_link *link)
Get IPGRE tunnel interface index.
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
uint8_t rtnl_link_ipgre_get_tos(struct rtnl_link *link)
Get IPGRE tunnel tos.
int rtnl_link_ipgre_set_iflags(struct rtnl_link *link, uint16_t iflags)
Set IPGRE tunnel set iflags.
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
uint16_t rtnl_link_ipgre_get_oflags(struct rtnl_link *link)
Get IPGRE tunnel oflags.
int rtnl_link_is_ipgretap(struct rtnl_link *link)
Check if link is a IPGRETAP link.
Dump all attributes but no statistics.
char * rtnl_link_get_name(struct rtnl_link *link)
Return name of link object.
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of 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.
uint32_t rtnl_link_ipgre_get_local(struct rtnl_link *link)
Get IPGRE tunnel local address.
uint8_t rtnl_link_ipgre_get_pmtudisc(struct rtnl_link *link)
Get IPGRE path MTU discovery.
void rtnl_link_set_name(struct rtnl_link *link, const char *name)
Set name of link object.
int rtnl_link_ipgre_set_local(struct rtnl_link *link, uint32_t addr)
Set IPGRE tunnel local address.
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
uint32_t rtnl_link_ipgre_get_okey(struct rtnl_link *link)
Get IPGRE tunnel okey.
int rtnl_link_ipgre_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc)
Set IPGRE tunnel path MTU discovery.
int rtnl_link_ipgre_add(struct nl_sock *sk, const char *name)
Create a new IPGRE tunnel device.
uint32_t rtnl_link_ipgre_get_remote(struct rtnl_link *link)
Get IPGRE tunnel remote address.
int rtnl_link_ipgre_set_okey(struct rtnl_link *link, uint32_t okey)
Set IPGRE tunnel set okey.
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
Unregister operations for a link info type.
uint16_t type
Type of attribute or NLA_UNSPEC.
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
uint16_t rtnl_link_ipgre_get_iflags(struct rtnl_link *link)
Get IPGRE tunnel iflags.
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
int rtnl_link_ipgre_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IPGRE tunnel ttl.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
void rtnl_link_put(struct rtnl_link *link)
Return a link object reference.
int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags)
Add virtual link.
int rtnl_link_ipgre_set_remote(struct rtnl_link *link, uint32_t remote)
Set IPGRE tunnel remote address.
int rtnl_link_ipgre_set_oflags(struct rtnl_link *link, uint16_t oflags)
Set IPGRE tunnel set oflags.
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.