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;
56 static 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 },
71 static 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;
88 static 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;
173 static 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)
225 static void ip6gre_free(
struct rtnl_link *link)
235 nl_dump(p,
"ip6gre : %s", link->l_name);
241 char *name, addr[INET6_ADDRSTRLEN];
243 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LINK) {
247 nl_dump_line(p,
"%s\n", name);
249 nl_dump_line(p,
"%u\n", ip6gre->link);
252 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IFLAGS) {
254 nl_dump_line(p,
"%x\n", ip6gre->iflags);
257 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OFLAGS) {
259 nl_dump_line(p,
"%x\n", ip6gre->oflags);
262 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IKEY) {
264 nl_dump_line(p,
"%x\n",ip6gre->ikey);
267 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OKEY) {
269 nl_dump_line(p,
"%x\n", ip6gre->okey);
272 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LOCAL) {
274 if(inet_ntop(AF_INET6, &ip6gre->local, addr,
sizeof(addr)))
275 nl_dump_line(p,
"%s\n", addr);
277 nl_dump_line(p,
"%#x\n", ip6gre->local);
280 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_REMOTE) {
282 if(inet_ntop(AF_INET6, &ip6gre->remote, addr,
sizeof(addr)))
283 nl_dump_line(p,
"%s\n", addr);
285 nl_dump_line(p,
"%#x\n", ip6gre->remote);
288 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_TTL) {
290 nl_dump_line(p,
"%u\n", ip6gre->ttl);
293 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_ENCAPLIMIT) {
295 nl_dump_line(p,
"%u\n", ip6gre->encaplimit);
298 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLOWINFO) {
300 nl_dump_line(p,
"%x\n", ip6gre->flowinfo);
303 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLAGS) {
305 nl_dump_line(p,
"%x\n", ip6gre->flags);
308 if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FWMARK) {
310 nl_dump_line(p,
"%x\n", ip6gre->fwmark);
316 struct ip6gre_info *ip6gre_dst, *ip6gre_src = src->l_info;
325 ip6gre_dst = dst->l_info;
327 if (!ip6gre_dst || !ip6gre_src)
330 memcpy(ip6gre_dst, ip6gre_src,
sizeof(
struct ip6gre_info));
335 static struct rtnl_link_info_ops ip6gre_info_ops = {
337 .io_alloc = ip6gre_alloc,
338 .io_parse = ip6gre_parse,
343 .io_clone = ip6gre_clone,
344 .io_put_attrs = ip6gre_put_attrs,
345 .io_free = ip6gre_free,
348 #define IS_IP6GRE_LINK_ASSERT(link) \
349 if ((link)->l_info_ops != &ip6gre_info_ops) { \
350 APPBUG("Link is not a ip6gre link. set type \"ip6gre\" first.");\
351 return -NLE_OPNOTSUPP; \
354 #define HAS_IP6GRE_ATTR_ASSERT(link,attr) \
355 if (!((link)->ip6gre_mask & (attr))) \
358 struct rtnl_link *rtnl_link_ip6gre_alloc(
void)
384 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
"ip6gre");
400 link = rtnl_link_ip6gre_alloc();
424 IS_IP6GRE_LINK_ASSERT(link);
426 ip6gre->link = index;
427 ip6gre->ip6gre_mask |= IP6GRE_ATTR_LINK;
443 IS_IP6GRE_LINK_ASSERT(link);
445 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LINK);
447 *index = ip6gre->link;
463 IS_IP6GRE_LINK_ASSERT(link);
465 ip6gre->iflags = iflags;
466 ip6gre->ip6gre_mask |= IP6GRE_ATTR_IFLAGS;
482 IS_IP6GRE_LINK_ASSERT(link);
484 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IFLAGS);
486 *iflags = ip6gre->iflags;
502 IS_IP6GRE_LINK_ASSERT(link);
504 ip6gre->oflags = oflags;
505 ip6gre->ip6gre_mask |= IP6GRE_ATTR_OFLAGS;
521 IS_IP6GRE_LINK_ASSERT(link);
523 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OFLAGS);
525 *oflags = ip6gre->oflags;
541 IS_IP6GRE_LINK_ASSERT(link);
544 ip6gre->ip6gre_mask |= IP6GRE_ATTR_IKEY;
560 IS_IP6GRE_LINK_ASSERT(link);
562 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IKEY);
564 *ikey = ip6gre->ikey;
580 IS_IP6GRE_LINK_ASSERT(link);
583 ip6gre->ip6gre_mask |= IP6GRE_ATTR_OKEY;
599 IS_IP6GRE_LINK_ASSERT(link);
601 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OKEY);
603 *okey = ip6gre->okey;
619 IS_IP6GRE_LINK_ASSERT(link);
621 memcpy(&ip6gre->local, local,
sizeof(
struct in6_addr));
622 ip6gre->ip6gre_mask |= IP6GRE_ATTR_LOCAL;
638 IS_IP6GRE_LINK_ASSERT(link);
640 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LOCAL);
642 memcpy(local, &ip6gre->local,
sizeof(
struct in6_addr));
658 IS_IP6GRE_LINK_ASSERT(link);
660 memcpy(&ip6gre->remote, remote,
sizeof(
struct in6_addr));
661 ip6gre->ip6gre_mask |= IP6GRE_ATTR_REMOTE;
677 IS_IP6GRE_LINK_ASSERT(link);
679 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_REMOTE);
681 memcpy(remote, &ip6gre->remote,
sizeof(
struct in6_addr));
697 IS_IP6GRE_LINK_ASSERT(link);
700 ip6gre->ip6gre_mask |= IP6GRE_ATTR_TTL;
716 IS_IP6GRE_LINK_ASSERT(link);
718 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_TTL);
736 IS_IP6GRE_LINK_ASSERT(link);
738 ip6gre->encaplimit = encaplimit;
739 ip6gre->ip6gre_mask |= IP6GRE_ATTR_ENCAPLIMIT;
755 IS_IP6GRE_LINK_ASSERT(link);
757 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_ENCAPLIMIT);
759 *encaplimit = ip6gre->encaplimit;
775 IS_IP6GRE_LINK_ASSERT(link);
777 ip6gre->flowinfo = flowinfo;
778 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLOWINFO;
794 IS_IP6GRE_LINK_ASSERT(link);
796 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLOWINFO);
798 *flowinfo = ip6gre->flowinfo;
814 IS_IP6GRE_LINK_ASSERT(link);
816 ip6gre->flags = flags;
817 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLAGS;
833 IS_IP6GRE_LINK_ASSERT(link);
835 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLAGS);
837 *flags = ip6gre->flags;
853 IS_IP6GRE_LINK_ASSERT(link);
855 ip6gre->fwmark = fwmark;
856 ip6gre->ip6gre_mask |= IP6GRE_ATTR_FWMARK;
872 IS_IP6GRE_LINK_ASSERT(link);
874 HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FWMARK);
876 *fwmark = ip6gre->fwmark;
881 static void __init ip6gre_init(
void)
886 static 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.
char * rtnl_link_get_name(struct rtnl_link *link)
Return name of link object.
void rtnl_link_set_name(struct rtnl_link *link, const char *name)
Set 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.
struct rtnl_link * rtnl_link_alloc(void)
Allocate 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.