ip6tnl.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /*
  2. * lib/route/link/ip6tnl.c IP6TNL Link Info
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation version 2.1
  7. * of the License.
  8. *
  9. * Copyright (c) 2014 Susant Sahani <susant@redhat.com>
  10. */
  11. /**
  12. * @ingroup link
  13. * @defgroup ip6tnl IP6TNL
  14. * ip6tnl link module
  15. *
  16. * @details
  17. * \b Link Type Name: "ip6tnl"
  18. *
  19. * @route_doc{link_ip6tnl, IP6TNL Documentation}
  20. *
  21. * @{
  22. */
  23. #include <netlink-private/netlink.h>
  24. #include <netlink/netlink.h>
  25. #include <netlink/attr.h>
  26. #include <netlink/utils.h>
  27. #include <netlink/object.h>
  28. #include <netlink/route/rtnl.h>
  29. #include <netlink-private/route/link/api.h>
  30. #include <linux/if_tunnel.h>
  31. #include <netinet/in.h>
  32. #define IP6_TNL_ATTR_LINK (1 << 0)
  33. #define IP6_TNL_ATTR_LOCAL (1 << 1)
  34. #define IP6_TNL_ATTR_REMOTE (1 << 2)
  35. #define IP6_TNL_ATTR_TTL (1 << 3)
  36. #define IP6_TNL_ATTR_TOS (1 << 4)
  37. #define IP6_TNL_ATTR_ENCAPLIMIT (1 << 5)
  38. #define IP6_TNL_ATTR_FLAGS (1 << 6)
  39. #define IP6_TNL_ATTR_PROTO (1 << 7)
  40. #define IP6_TNL_ATTR_FLOWINFO (1 << 8)
  41. struct ip6_tnl_info
  42. {
  43. uint8_t ttl;
  44. uint8_t tos;
  45. uint8_t encap_limit;
  46. uint8_t proto;
  47. uint32_t flags;
  48. uint32_t link;
  49. uint32_t flowinfo;
  50. struct in6_addr local;
  51. struct in6_addr remote;
  52. uint32_t ip6_tnl_mask;
  53. };
  54. static struct nla_policy ip6_tnl_policy[IFLA_IPTUN_MAX + 1] = {
  55. [IFLA_IPTUN_LINK] = { .type = NLA_U32 },
  56. [IFLA_IPTUN_LOCAL] = { .minlen = sizeof(struct in6_addr) },
  57. [IFLA_IPTUN_REMOTE] = { .minlen = sizeof(struct in6_addr) },
  58. [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
  59. [IFLA_IPTUN_TOS] = { .type = NLA_U8 },
  60. [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 },
  61. [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 },
  62. [IFLA_IPTUN_FLAGS] = { .type = NLA_U32 },
  63. [IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
  64. };
  65. static int ip6_tnl_alloc(struct rtnl_link *link)
  66. {
  67. struct ip6_tnl_info *ip6_tnl;
  68. ip6_tnl = calloc(1, sizeof(*ip6_tnl));
  69. if (!ip6_tnl)
  70. return -NLE_NOMEM;
  71. link->l_info = ip6_tnl;
  72. return 0;
  73. }
  74. static int ip6_tnl_parse(struct rtnl_link *link, struct nlattr *data,
  75. struct nlattr *xstats)
  76. {
  77. struct nlattr *tb[IFLA_IPTUN_MAX + 1];
  78. struct ip6_tnl_info *ip6_tnl;
  79. int err;
  80. NL_DBG(3, "Parsing IP6_TNL link info");
  81. err = nla_parse_nested(tb, IFLA_IPTUN_MAX, data, ip6_tnl_policy);
  82. if (err < 0)
  83. goto errout;
  84. err = ip6_tnl_alloc(link);
  85. if (err < 0)
  86. goto errout;
  87. ip6_tnl = link->l_info;
  88. if (tb[IFLA_IPTUN_LINK]) {
  89. ip6_tnl->link = nla_get_u32(tb[IFLA_IPTUN_LINK]);
  90. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LINK;
  91. }
  92. if (tb[IFLA_IPTUN_LOCAL]) {
  93. nla_memcpy(&ip6_tnl->local, tb[IFLA_IPTUN_LOCAL], sizeof(struct in6_addr));
  94. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LOCAL;
  95. }
  96. if (tb[IFLA_IPTUN_REMOTE]) {
  97. nla_memcpy(&ip6_tnl->remote, tb[IFLA_IPTUN_REMOTE], sizeof(struct in6_addr));
  98. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_REMOTE;
  99. }
  100. if (tb[IFLA_IPTUN_TTL]) {
  101. ip6_tnl->ttl = nla_get_u8(tb[IFLA_IPTUN_TTL]);
  102. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TTL;
  103. }
  104. if (tb[IFLA_IPTUN_TOS]) {
  105. ip6_tnl->tos = nla_get_u8(tb[IFLA_IPTUN_TOS]);
  106. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TOS;
  107. }
  108. if (tb[IFLA_IPTUN_ENCAP_LIMIT]) {
  109. ip6_tnl->encap_limit = nla_get_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]);
  110. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_ENCAPLIMIT;
  111. }
  112. if (tb[IFLA_IPTUN_FLAGS]) {
  113. ip6_tnl->flags = nla_get_u32(tb[IFLA_IPTUN_FLAGS]);
  114. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLAGS;
  115. }
  116. if (tb[IFLA_IPTUN_FLOWINFO]) {
  117. ip6_tnl->flowinfo = nla_get_u32(tb[IFLA_IPTUN_FLOWINFO]);
  118. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLOWINFO;
  119. }
  120. if (tb[IFLA_IPTUN_PROTO]) {
  121. ip6_tnl->proto = nla_get_u8(tb[IFLA_IPTUN_PROTO]);
  122. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_PROTO;
  123. }
  124. err = 0;
  125. errout:
  126. return err;
  127. }
  128. static int ip6_tnl_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
  129. {
  130. struct ip6_tnl_info *ip6_tnl = link->l_info;
  131. struct nlattr *data;
  132. data = nla_nest_start(msg, IFLA_INFO_DATA);
  133. if (!data)
  134. return -NLE_MSGSIZE;
  135. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LINK)
  136. NLA_PUT_U32(msg, IFLA_IPTUN_LINK, ip6_tnl->link);
  137. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LOCAL)
  138. NLA_PUT(msg, IFLA_IPTUN_LOCAL, sizeof(struct in6_addr), &ip6_tnl->local);
  139. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_REMOTE)
  140. NLA_PUT(msg, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr), &ip6_tnl->remote);
  141. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TTL)
  142. NLA_PUT_U8(msg, IFLA_IPTUN_TTL, ip6_tnl->ttl);
  143. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TOS)
  144. NLA_PUT_U8(msg, IFLA_IPTUN_TOS, ip6_tnl->tos);
  145. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_ENCAPLIMIT)
  146. NLA_PUT_U8(msg, IFLA_IPTUN_ENCAP_LIMIT, ip6_tnl->encap_limit);
  147. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLAGS)
  148. NLA_PUT_U32(msg, IFLA_IPTUN_FLAGS, ip6_tnl->flags);
  149. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLOWINFO)
  150. NLA_PUT_U32(msg, IFLA_IPTUN_FLOWINFO, ip6_tnl->flowinfo);
  151. /* kernel crashes if this attribure is missing temporary fix */
  152. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_PROTO)
  153. NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, ip6_tnl->proto);
  154. else
  155. NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, 0);
  156. nla_nest_end(msg, data);
  157. nla_put_failure:
  158. return 0;
  159. }
  160. static void ip6_tnl_free(struct rtnl_link *link)
  161. {
  162. struct ip6_tnl_info *ip6_tnl = link->l_info;
  163. free(ip6_tnl);
  164. link->l_info = NULL;
  165. }
  166. static void ip6_tnl_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
  167. {
  168. nl_dump(p, "ip6_tnl : %s", link->l_name);
  169. }
  170. static void ip6_tnl_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
  171. {
  172. struct ip6_tnl_info *ip6_tnl = link->l_info;
  173. char *name, addr[INET6_ADDRSTRLEN];
  174. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LINK) {
  175. nl_dump(p, " link ");
  176. name = rtnl_link_get_name(link);
  177. if (name)
  178. nl_dump_line(p, "%s\n", name);
  179. else
  180. nl_dump_line(p, "%u\n", ip6_tnl->link);
  181. }
  182. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LOCAL) {
  183. nl_dump(p, " local ");
  184. if(inet_ntop(AF_INET6, &ip6_tnl->local, addr, INET6_ADDRSTRLEN))
  185. nl_dump_line(p, "%s\n", addr);
  186. else
  187. nl_dump_line(p, "%#x\n", ip6_tnl->local);
  188. }
  189. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_REMOTE) {
  190. nl_dump(p, " remote ");
  191. if(inet_ntop(AF_INET6, &ip6_tnl->remote, addr, INET6_ADDRSTRLEN))
  192. nl_dump_line(p, "%s\n", addr);
  193. else
  194. nl_dump_line(p, "%#x\n", ip6_tnl->remote);
  195. }
  196. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TTL) {
  197. nl_dump(p, " ttl ");
  198. nl_dump_line(p, "%d\n", ip6_tnl->ttl);
  199. }
  200. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TOS) {
  201. nl_dump(p, " tos ");
  202. nl_dump_line(p, "%d\n", ip6_tnl->tos);
  203. }
  204. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_ENCAPLIMIT) {
  205. nl_dump(p, " encaplimit ");
  206. nl_dump_line(p, "%d\n", ip6_tnl->encap_limit);
  207. }
  208. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLAGS) {
  209. nl_dump(p, " flags ");
  210. nl_dump_line(p, " (%x)\n", ip6_tnl->flags);
  211. }
  212. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLOWINFO) {
  213. nl_dump(p, " flowinfo ");
  214. nl_dump_line(p, " (%x)\n", ip6_tnl->flowinfo);
  215. }
  216. if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_PROTO) {
  217. nl_dump(p, " proto ");
  218. nl_dump_line(p, " (%x)\n", ip6_tnl->proto);
  219. }
  220. }
  221. static int ip6_tnl_clone(struct rtnl_link *dst, struct rtnl_link *src)
  222. {
  223. struct ip6_tnl_info *ip6_tnl_dst, *ip6_tnl_src = src->l_info;
  224. int err;
  225. dst->l_info = NULL;
  226. err = rtnl_link_set_type(dst, "ip6tnl");
  227. if (err < 0)
  228. return err;
  229. ip6_tnl_dst = dst->l_info;
  230. if (!ip6_tnl_dst || !ip6_tnl_src)
  231. BUG();
  232. memcpy(ip6_tnl_dst, ip6_tnl_src, sizeof(struct ip6_tnl_info));
  233. return 0;
  234. }
  235. static struct rtnl_link_info_ops ip6_tnl_info_ops = {
  236. .io_name = "ip6tnl",
  237. .io_alloc = ip6_tnl_alloc,
  238. .io_parse = ip6_tnl_parse,
  239. .io_dump = {
  240. [NL_DUMP_LINE] = ip6_tnl_dump_line,
  241. [NL_DUMP_DETAILS] = ip6_tnl_dump_details,
  242. },
  243. .io_clone = ip6_tnl_clone,
  244. .io_put_attrs = ip6_tnl_put_attrs,
  245. .io_free = ip6_tnl_free,
  246. };
  247. #define IS_IP6_TNL_LINK_ASSERT(link)\
  248. if ((link)->l_info_ops != &ip6_tnl_info_ops) {\
  249. APPBUG("Link is not a ip6_tnl link. set type \"ip6tnl\" first.");\
  250. return -NLE_OPNOTSUPP;\
  251. }
  252. struct rtnl_link *rtnl_link_ip6_tnl_alloc(void)
  253. {
  254. struct rtnl_link *link;
  255. int err;
  256. link = rtnl_link_alloc();
  257. if (!link)
  258. return NULL;
  259. err = rtnl_link_set_type(link, "ip6tnl");
  260. if (err < 0) {
  261. rtnl_link_put(link);
  262. return NULL;
  263. }
  264. return link;
  265. }
  266. /**
  267. * Check if link is a IP6_TNL link
  268. * @arg link Link object
  269. *
  270. * @return True if link is a IP6_TNL link, otherwise false is returned.
  271. */
  272. int rtnl_link_is_ip6_tnl(struct rtnl_link *link)
  273. {
  274. return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ip6tnl");
  275. }
  276. /**
  277. * Create a new ip6_tnl tunnel device
  278. * @arg sock netlink socket
  279. * @arg name name of the tunnel device
  280. *
  281. * Creates a new ip6_tnl tunnel device in the kernel
  282. * @return 0 on success or a negative error code
  283. */
  284. int rtnl_link_ip6_tnl_add(struct nl_sock *sk, const char *name)
  285. {
  286. struct rtnl_link *link;
  287. int err;
  288. link = rtnl_link_ip6_tnl_alloc();
  289. if (!link)
  290. return -NLE_NOMEM;
  291. if(name)
  292. rtnl_link_set_name(link, name);
  293. err = rtnl_link_add(sk, link, NLM_F_CREATE);
  294. rtnl_link_put(link);
  295. return err;
  296. }
  297. /**
  298. * Set IP6_TNL tunnel interface index
  299. * @arg link Link object
  300. * @arg index interface index
  301. *
  302. * @return 0 on success or a negative error code
  303. */
  304. int rtnl_link_ip6_tnl_set_link(struct rtnl_link *link, uint32_t index)
  305. {
  306. struct ip6_tnl_info *ip6_tnl = link->l_info;
  307. IS_IP6_TNL_LINK_ASSERT(link);
  308. ip6_tnl->link = index;
  309. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LINK;
  310. return 0;
  311. }
  312. /**
  313. * Get IP6_TNL tunnel interface index
  314. * @arg link Link object
  315. *
  316. * @return interface index value
  317. */
  318. uint32_t rtnl_link_ip6_tnl_get_link(struct rtnl_link *link)
  319. {
  320. struct ip6_tnl_info *ip6_tnl = link->l_info;
  321. IS_IP6_TNL_LINK_ASSERT(link);
  322. return ip6_tnl->link;
  323. }
  324. /**
  325. * Set IP6_TNL tunnel local address
  326. * @arg link Link object
  327. * @arg addr local address
  328. *
  329. * @return 0 on success or a negative error code
  330. */
  331. int rtnl_link_ip6_tnl_set_local(struct rtnl_link *link, struct in6_addr *addr)
  332. {
  333. struct ip6_tnl_info *ip6_tnl = link->l_info;
  334. IS_IP6_TNL_LINK_ASSERT(link);
  335. memcpy(&ip6_tnl->local, addr, sizeof(struct in6_addr));
  336. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LOCAL;
  337. return 0;
  338. }
  339. /**
  340. * Get IP6_TNL tunnel local address
  341. * @arg link Link object
  342. *
  343. * @return 0 on success or a negative error code
  344. */
  345. int rtnl_link_ip6_tnl_get_local(struct rtnl_link *link, struct in6_addr *addr)
  346. {
  347. struct ip6_tnl_info *ip6_tnl = link->l_info;
  348. IS_IP6_TNL_LINK_ASSERT(link);
  349. memcpy(addr, &ip6_tnl->local, sizeof(struct in6_addr));
  350. return 0;
  351. }
  352. /**
  353. * Set IP6_TNL tunnel remote address
  354. * @arg link Link object
  355. * @arg remote remote address
  356. *
  357. * @return 0 on success or a negative error code
  358. */
  359. int rtnl_link_ip6_tnl_set_remote(struct rtnl_link *link, struct in6_addr *addr)
  360. {
  361. struct ip6_tnl_info *ip6_tnl = link->l_info;
  362. IS_IP6_TNL_LINK_ASSERT(link);
  363. memcpy(&ip6_tnl->remote, addr, sizeof(struct in6_addr));
  364. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_REMOTE;
  365. return 0;
  366. }
  367. /**
  368. * Get IP6_TNL tunnel remote address
  369. * @arg link Link object
  370. *
  371. * @return 0 on success or a negative error code
  372. */
  373. int rtnl_link_ip6_tnl_get_remote(struct rtnl_link *link, struct in6_addr *addr)
  374. {
  375. struct ip6_tnl_info *ip6_tnl = link->l_info;
  376. IS_IP6_TNL_LINK_ASSERT(link);
  377. memcpy(addr, &ip6_tnl->remote, sizeof(struct in6_addr));
  378. return 0;
  379. }
  380. /**
  381. * Set IP6_TNL tunnel ttl
  382. * @arg link Link object
  383. * @arg ttl tunnel ttl
  384. *
  385. * @return 0 on success or a negative error code
  386. */
  387. int rtnl_link_ip6_tnl_set_ttl(struct rtnl_link *link, uint8_t ttl)
  388. {
  389. struct ip6_tnl_info *ip6_tnl = link->l_info;
  390. IS_IP6_TNL_LINK_ASSERT(link);
  391. ip6_tnl->ttl = ttl;
  392. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TTL;
  393. return 0;
  394. }
  395. /**
  396. * Get IP6_TNL tunnel ttl
  397. * @arg link Link object
  398. *
  399. * @return ttl value
  400. */
  401. uint8_t rtnl_link_ip6_tnl_get_ttl(struct rtnl_link *link)
  402. {
  403. struct ip6_tnl_info *ip6_tnl = link->l_info;
  404. IS_IP6_TNL_LINK_ASSERT(link);
  405. return ip6_tnl->ttl;
  406. }
  407. /**
  408. * Set IP6_TNL tunnel tos
  409. * @arg link Link object
  410. * @arg tos tunnel tos
  411. *
  412. * @return 0 on success or a negative error code
  413. */
  414. int rtnl_link_ip6_tnl_set_tos(struct rtnl_link *link, uint8_t tos)
  415. {
  416. struct ip6_tnl_info *ip6_tnl = link->l_info;
  417. IS_IP6_TNL_LINK_ASSERT(link);
  418. ip6_tnl->tos = tos;
  419. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TOS;
  420. return 0;
  421. }
  422. /**
  423. * Get IP6_TNL tunnel tos
  424. * @arg link Link object
  425. *
  426. * @return tos value
  427. */
  428. uint8_t rtnl_link_ip6_tnl_get_tos(struct rtnl_link *link)
  429. {
  430. struct ip6_tnl_info *ip6_tnl = link->l_info;
  431. IS_IP6_TNL_LINK_ASSERT(link);
  432. return ip6_tnl->tos;
  433. }
  434. /**
  435. * Set IP6_TNL tunnel encap limit
  436. * @arg link Link object
  437. * @arg encap_limit encaplimit value
  438. *
  439. * @return 0 on success or a negative error code
  440. */
  441. int rtnl_link_ip6_tnl_set_encaplimit(struct rtnl_link *link, uint8_t encap_limit)
  442. {
  443. struct ip6_tnl_info *ip6_tnl = link->l_info;
  444. IS_IP6_TNL_LINK_ASSERT(link);
  445. ip6_tnl->encap_limit = encap_limit;
  446. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_ENCAPLIMIT;
  447. return 0;
  448. }
  449. /**
  450. * Get IP6_TNL encaplimit
  451. * @arg link Link object
  452. *
  453. * @return encaplimit value
  454. */
  455. uint8_t rtnl_link_ip6_tnl_get_encaplimit(struct rtnl_link *link)
  456. {
  457. struct ip6_tnl_info *ip6_tnl = link->l_info;
  458. IS_IP6_TNL_LINK_ASSERT(link);
  459. return ip6_tnl->encap_limit;
  460. }
  461. /**
  462. * Set IP6_TNL tunnel flowinfo
  463. * @arg link Link object
  464. * @arg flowinfo flowinfo value
  465. *
  466. * @return 0 on success or a negative error code
  467. */
  468. int rtnl_link_ip6_tnl_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo)
  469. {
  470. struct ip6_tnl_info *ip6_tnl = link->l_info;
  471. IS_IP6_TNL_LINK_ASSERT(link);
  472. ip6_tnl->flowinfo = flowinfo;
  473. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLOWINFO;
  474. return 0;
  475. }
  476. /**
  477. * Get IP6_TNL flowinfo
  478. * @arg link Link object
  479. *
  480. * @return flowinfo value
  481. */
  482. uint32_t rtnl_link_ip6_tnl_get_flowinfo(struct rtnl_link *link)
  483. {
  484. struct ip6_tnl_info *ip6_tnl = link->l_info;
  485. IS_IP6_TNL_LINK_ASSERT(link);
  486. return ip6_tnl->flowinfo;
  487. }
  488. /**
  489. * Set IP6_TNL tunnel flags
  490. * @arg link Link object
  491. * @arg flags tunnel flags
  492. *
  493. * @return 0 on success or a negative error code
  494. */
  495. int rtnl_link_ip6_tnl_set_flags(struct rtnl_link *link, uint32_t flags)
  496. {
  497. struct ip6_tnl_info *ip6_tnl = link->l_info;
  498. IS_IP6_TNL_LINK_ASSERT(link);
  499. ip6_tnl->flags = flags;
  500. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLAGS;
  501. return 0;
  502. }
  503. /**
  504. * Get IP6_TNL path flags
  505. * @arg link Link object
  506. *
  507. * @return flags value
  508. */
  509. uint32_t rtnl_link_ip6_tnl_get_flags(struct rtnl_link *link)
  510. {
  511. struct ip6_tnl_info *ip6_tnl = link->l_info;
  512. IS_IP6_TNL_LINK_ASSERT(link);
  513. return ip6_tnl->flags;
  514. }
  515. /**
  516. * Set IP6_TNL tunnel proto
  517. * @arg link Link object
  518. * @arg proto tunnel proto
  519. *
  520. * @return 0 on success or a negative error code
  521. */
  522. int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto)
  523. {
  524. struct ip6_tnl_info *ip6_tnl = link->l_info;
  525. IS_IP6_TNL_LINK_ASSERT(link);
  526. ip6_tnl->proto = proto;
  527. ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_PROTO;
  528. return 0;
  529. }
  530. /**
  531. * Get IP6_TNL proto
  532. * @arg link Link object
  533. *
  534. * @return proto value
  535. */
  536. uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link)
  537. {
  538. struct ip6_tnl_info *ip6_tnl = link->l_info;
  539. IS_IP6_TNL_LINK_ASSERT(link);
  540. return ip6_tnl->proto;
  541. }
  542. static void __init ip6_tnl_init(void)
  543. {
  544. rtnl_link_register_info(&ip6_tnl_info_ops);
  545. }
  546. static void __exit ip6_tnl_exit(void)
  547. {
  548. rtnl_link_unregister_info(&ip6_tnl_info_ops);
  549. }