ipvti.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*
  2. * lib/route/link/ipvti.c IPVTI 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 ipvti IPVTI
  14. * ipvti link module
  15. *
  16. * @details
  17. * \b Link Type Name: "ipvti"
  18. *
  19. * @route_doc{link_ipvti, IPVTI 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. #define IPVTI_ATTR_LINK (1 << 0)
  32. #define IPVTI_ATTR_IKEY (1 << 1)
  33. #define IPVTI_ATTR_OKEY (1 << 2)
  34. #define IPVTI_ATTR_LOCAL (1 << 3)
  35. #define IPVTI_ATTR_REMOTE (1 << 4)
  36. struct ipvti_info
  37. {
  38. uint32_t link;
  39. uint32_t ikey;
  40. uint32_t okey;
  41. uint32_t local;
  42. uint32_t remote;
  43. uint32_t ipvti_mask;
  44. };
  45. static struct nla_policy ipvti_policy[IFLA_GRE_MAX + 1] = {
  46. [IFLA_VTI_LINK] = { .type = NLA_U32 },
  47. [IFLA_VTI_IKEY] = { .type = NLA_U32 },
  48. [IFLA_VTI_OKEY] = { .type = NLA_U32 },
  49. [IFLA_VTI_LOCAL] = { .type = NLA_U32 },
  50. [IFLA_VTI_REMOTE] = { .type = NLA_U32 },
  51. };
  52. static int ipvti_alloc(struct rtnl_link *link)
  53. {
  54. struct ipvti_info *ipvti;
  55. ipvti = calloc(1, sizeof(*ipvti));
  56. if (!ipvti)
  57. return -NLE_NOMEM;
  58. link->l_info = ipvti;
  59. return 0;
  60. }
  61. static int ipvti_parse(struct rtnl_link *link, struct nlattr *data,
  62. struct nlattr *xstats)
  63. {
  64. struct nlattr *tb[IFLA_IPTUN_MAX + 1];
  65. struct ipvti_info *ipvti;
  66. int err;
  67. NL_DBG(3, "Parsing IPVTI link info");
  68. err = nla_parse_nested(tb, IFLA_GRE_MAX, data, ipvti_policy);
  69. if (err < 0)
  70. goto errout;
  71. err = ipvti_alloc(link);
  72. if (err < 0)
  73. goto errout;
  74. ipvti = link->l_info;
  75. if (tb[IFLA_VTI_LINK]) {
  76. ipvti->link = nla_get_u32(tb[IFLA_VTI_LINK]);
  77. ipvti->ipvti_mask |= IPVTI_ATTR_LINK;
  78. }
  79. if (tb[IFLA_VTI_IKEY]) {
  80. ipvti->ikey = nla_get_u32(tb[IFLA_VTI_IKEY]);
  81. ipvti->ipvti_mask |= IPVTI_ATTR_IKEY;
  82. }
  83. if (tb[IFLA_VTI_OKEY]) {
  84. ipvti->okey = nla_get_u32(tb[IFLA_VTI_OKEY]);
  85. ipvti->ipvti_mask |= IPVTI_ATTR_OKEY;
  86. }
  87. if (tb[IFLA_VTI_LOCAL]) {
  88. ipvti->local = nla_get_u32(tb[IFLA_VTI_LOCAL]);
  89. ipvti->ipvti_mask |= IPVTI_ATTR_LOCAL;
  90. }
  91. if (tb[IFLA_VTI_REMOTE]) {
  92. ipvti->remote = nla_get_u32(tb[IFLA_VTI_REMOTE]);
  93. ipvti->ipvti_mask |= IPVTI_ATTR_REMOTE;
  94. }
  95. err = 0;
  96. errout:
  97. return err;
  98. }
  99. static int ipvti_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
  100. {
  101. struct ipvti_info *ipvti = link->l_info;
  102. struct nlattr *data;
  103. data = nla_nest_start(msg, IFLA_INFO_DATA);
  104. if (!data)
  105. return -NLE_MSGSIZE;
  106. if (ipvti->ipvti_mask & IPVTI_ATTR_LINK)
  107. NLA_PUT_U32(msg, IFLA_VTI_LINK, ipvti->link);
  108. if (ipvti->ipvti_mask & IPVTI_ATTR_IKEY)
  109. NLA_PUT_U32(msg, IFLA_VTI_IKEY, ipvti->ikey);
  110. if (ipvti->ipvti_mask & IFLA_VTI_IKEY)
  111. NLA_PUT_U32(msg, IFLA_VTI_OKEY, ipvti->okey);
  112. if (ipvti->ipvti_mask & IPVTI_ATTR_LOCAL)
  113. NLA_PUT_U32(msg, IFLA_VTI_LOCAL, ipvti->local);
  114. if (ipvti->ipvti_mask & IPVTI_ATTR_REMOTE)
  115. NLA_PUT_U32(msg, IFLA_VTI_REMOTE, ipvti->remote);
  116. nla_nest_end(msg, data);
  117. nla_put_failure:
  118. return 0;
  119. }
  120. static void ipvti_free(struct rtnl_link *link)
  121. {
  122. struct ipvti_info *ipvti = link->l_info;
  123. free(ipvti);
  124. link->l_info = NULL;
  125. }
  126. static void ipvti_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
  127. {
  128. nl_dump(p, "ipvti : %s", link->l_name);
  129. }
  130. static void ipvti_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
  131. {
  132. struct ipvti_info *ipvti = link->l_info;
  133. char *name, addr[INET_ADDRSTRLEN];
  134. if (ipvti->ipvti_mask & IPVTI_ATTR_LINK) {
  135. nl_dump(p, " link ");
  136. name = rtnl_link_get_name(link);
  137. if (name)
  138. nl_dump_line(p, "%s\n", name);
  139. else
  140. nl_dump_line(p, "%u\n", ipvti->link);
  141. }
  142. if (ipvti->ipvti_mask & IPVTI_ATTR_IKEY) {
  143. nl_dump(p, " ikey ");
  144. nl_dump_line(p, "%x\n",ipvti->ikey);
  145. }
  146. if (ipvti->ipvti_mask & IPVTI_ATTR_OKEY) {
  147. nl_dump(p, " okey ");
  148. nl_dump_line(p, "%x\n", ipvti->okey);
  149. }
  150. if (ipvti->ipvti_mask & IPVTI_ATTR_LOCAL) {
  151. nl_dump(p, " local ");
  152. if(inet_ntop(AF_INET, &ipvti->local, addr, sizeof(addr)))
  153. nl_dump_line(p, "%s\n", addr);
  154. else
  155. nl_dump_line(p, "%#x\n", ntohs(ipvti->local));
  156. }
  157. if (ipvti->ipvti_mask & IPVTI_ATTR_REMOTE) {
  158. nl_dump(p, " remote ");
  159. if(inet_ntop(AF_INET, &ipvti->remote, addr, sizeof(addr)))
  160. nl_dump_line(p, "%s\n", addr);
  161. else
  162. nl_dump_line(p, "%#x\n", ntohs(ipvti->remote));
  163. }
  164. }
  165. static int ipvti_clone(struct rtnl_link *dst, struct rtnl_link *src)
  166. {
  167. struct ipvti_info *ipvti_dst, *ipvti_src = src->l_info;
  168. int err;
  169. dst->l_info = NULL;
  170. err = rtnl_link_set_type(dst, "vti");
  171. if (err < 0)
  172. return err;
  173. ipvti_dst = dst->l_info;
  174. if (!ipvti_dst || !ipvti_src)
  175. BUG();
  176. memcpy(ipvti_dst, ipvti_src, sizeof(struct ipvti_info));
  177. return 0;
  178. }
  179. static struct rtnl_link_info_ops ipvti_info_ops = {
  180. .io_name = "vti",
  181. .io_alloc = ipvti_alloc,
  182. .io_parse = ipvti_parse,
  183. .io_dump = {
  184. [NL_DUMP_LINE] = ipvti_dump_line,
  185. [NL_DUMP_DETAILS] = ipvti_dump_details,
  186. },
  187. .io_clone = ipvti_clone,
  188. .io_put_attrs = ipvti_put_attrs,
  189. .io_free = ipvti_free,
  190. };
  191. #define IS_IPVTI_LINK_ASSERT(link) \
  192. if ((link)->l_info_ops != &ipvti_info_ops) { \
  193. APPBUG("Link is not a ipvti link. set type \vti\" first."); \
  194. return -NLE_OPNOTSUPP; \
  195. }
  196. struct rtnl_link *rtnl_link_ipvti_alloc(void)
  197. {
  198. struct rtnl_link *link;
  199. int err;
  200. link = rtnl_link_alloc();
  201. if (!link)
  202. return NULL;
  203. err = rtnl_link_set_type(link, "vti");
  204. if (err < 0) {
  205. rtnl_link_put(link);
  206. return NULL;
  207. }
  208. return link;
  209. }
  210. /**
  211. * Check if link is a IPVTI link
  212. * @arg link Link object
  213. *
  214. * @return True if link is a IPVTI link, otherwise 0 is returned.
  215. */
  216. int rtnl_link_is_ipvti(struct rtnl_link *link)
  217. {
  218. return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vti");
  219. }
  220. /**
  221. * Create a new ipvti tunnel device
  222. * @arg sock netlink socket
  223. * @arg name name of the tunnel deviceL
  224. *
  225. * Creates a new ipvti tunnel device in the kernel
  226. * @return 0 on success or a negative error code
  227. */
  228. int rtnl_link_ipvti_add(struct nl_sock *sk, const char *name)
  229. {
  230. struct rtnl_link *link;
  231. int err;
  232. link = rtnl_link_ipvti_alloc();
  233. if (!link)
  234. return -NLE_NOMEM;
  235. if(name)
  236. rtnl_link_set_name(link, name);
  237. err = rtnl_link_add(sk, link, NLM_F_CREATE);
  238. rtnl_link_put(link);
  239. return err;
  240. }
  241. /**
  242. * Set IPVTI tunnel interface index
  243. * @arg link Link object
  244. * @arg index interface index
  245. *
  246. * @return 0 on success or a negative error code
  247. */
  248. int rtnl_link_ipvti_set_link(struct rtnl_link *link, uint32_t index)
  249. {
  250. struct ipvti_info *ipvti = link->l_info;
  251. IS_IPVTI_LINK_ASSERT(link);
  252. ipvti->link = index;
  253. ipvti->ipvti_mask |= IPVTI_ATTR_LINK;
  254. return 0;
  255. }
  256. /**
  257. * Get IPVTI tunnel interface index
  258. * @arg link Link object
  259. *
  260. * @return interface index
  261. */
  262. uint32_t rtnl_link_ipvti_get_link(struct rtnl_link *link)
  263. {
  264. struct ipvti_info *ipvti = link->l_info;
  265. IS_IPVTI_LINK_ASSERT(link);
  266. return ipvti->link;
  267. }
  268. /**
  269. * Set IPVTI tunnel set ikey
  270. * @arg link Link object
  271. * @arg ikey gre ikey
  272. *
  273. * @return 0 on success or a negative error code
  274. */
  275. int rtnl_link_ipvti_set_ikey(struct rtnl_link *link, uint32_t ikey)
  276. {
  277. struct ipvti_info *ipvti = link->l_info;
  278. IS_IPVTI_LINK_ASSERT(link);
  279. ipvti->ikey = ikey;
  280. ipvti->ipvti_mask |= IPVTI_ATTR_IKEY;
  281. return 0;
  282. }
  283. /**
  284. * Get IPVTI tunnel ikey
  285. * @arg link Link object
  286. *
  287. * @return ikey
  288. */
  289. uint32_t rtnl_link_ipvti_get_ikey(struct rtnl_link *link)
  290. {
  291. struct ipvti_info *ipvti = link->l_info;
  292. IS_IPVTI_LINK_ASSERT(link);
  293. return ipvti->ikey;
  294. }
  295. /**
  296. * Set IPVTI tunnel set okey
  297. * @arg link Link object
  298. * @arg okey gre okey
  299. *
  300. * @return 0 on success or a negative error code
  301. */
  302. int rtnl_link_ipvti_set_okey(struct rtnl_link *link, uint32_t okey)
  303. {
  304. struct ipvti_info *ipvti = link->l_info;
  305. IS_IPVTI_LINK_ASSERT(link);
  306. ipvti->okey = okey;
  307. ipvti->ipvti_mask |= IPVTI_ATTR_OKEY;
  308. return 0;
  309. }
  310. /**
  311. * Get IPVTI tunnel okey
  312. * @arg link Link object
  313. *
  314. * @return okey value
  315. */
  316. uint32_t rtnl_link_ipvti_get_okey(struct rtnl_link *link)
  317. {
  318. struct ipvti_info *ipvti = link->l_info;
  319. IS_IPVTI_LINK_ASSERT(link);
  320. return ipvti->okey;
  321. }
  322. /**
  323. * Set IPVTI tunnel local address
  324. * @arg link Link object
  325. * @arg addr local address
  326. *
  327. * @return 0 on success or a negative error code
  328. */
  329. int rtnl_link_ipvti_set_local(struct rtnl_link *link, uint32_t addr)
  330. {
  331. struct ipvti_info *ipvti = link->l_info;
  332. IS_IPVTI_LINK_ASSERT(link);
  333. ipvti->local = addr;
  334. ipvti->ipvti_mask |= IPVTI_ATTR_LOCAL;
  335. return 0;
  336. }
  337. /**
  338. * Get IPVTI tunnel local address
  339. * @arg link Link object
  340. *
  341. * @return local address
  342. */
  343. uint32_t rtnl_link_ipvti_get_local(struct rtnl_link *link)
  344. {
  345. struct ipvti_info *ipvti = link->l_info;
  346. IS_IPVTI_LINK_ASSERT(link);
  347. return ipvti->local;
  348. }
  349. /**
  350. * Set IPVTI tunnel remote address
  351. * @arg link Link object
  352. * @arg remote remote address
  353. *
  354. * @return 0 on success or a negative error code
  355. */
  356. int rtnl_link_ipvti_set_remote(struct rtnl_link *link, uint32_t remote)
  357. {
  358. struct ipvti_info *ipvti = link->l_info;
  359. IS_IPVTI_LINK_ASSERT(link);
  360. ipvti->remote = remote;
  361. ipvti->ipvti_mask |= IPVTI_ATTR_REMOTE;
  362. return 0;
  363. }
  364. /**
  365. * Get IPVTI tunnel remote address
  366. * @arg link Link object
  367. *
  368. * @return remote address on success or a negative error code
  369. */
  370. uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link)
  371. {
  372. struct ipvti_info *ipvti = link->l_info;
  373. IS_IPVTI_LINK_ASSERT(link);
  374. return ipvti->remote;
  375. }
  376. static void __init ipvti_init(void)
  377. {
  378. rtnl_link_register_info(&ipvti_info_ops);
  379. }
  380. static void __exit ipvti_exit(void)
  381. {
  382. rtnl_link_unregister_info(&ipvti_info_ops);
  383. }