sit.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. /*
  2. * lib/route/link/sit.c SIT 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 sit SIT
  14. * sit link module
  15. *
  16. * @details
  17. * \b Link Type Name: "sit"
  18. *
  19. * @route_doc{link_sit, SIT 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 SIT_ATTR_LINK (1 << 0)
  32. #define SIT_ATTR_LOCAL (1 << 1)
  33. #define SIT_ATTR_REMOTE (1 << 2)
  34. #define SIT_ATTR_TTL (1 << 3)
  35. #define SIT_ATTR_TOS (1 << 4)
  36. #define SIT_ATTR_PMTUDISC (1 << 5)
  37. #define SIT_ATTR_FLAGS (1 << 6)
  38. #define SIT_ATTR_PROTO (1 << 7)
  39. struct sit_info
  40. {
  41. uint8_t ttl;
  42. uint8_t tos;
  43. uint8_t pmtudisc;
  44. uint8_t proto;
  45. uint16_t flags;
  46. uint32_t link;
  47. uint32_t local;
  48. uint32_t remote;
  49. uint32_t sit_mask;
  50. };
  51. static struct nla_policy sit_policy[IFLA_IPTUN_MAX + 1] = {
  52. [IFLA_IPTUN_LINK] = { .type = NLA_U32 },
  53. [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 },
  54. [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 },
  55. [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
  56. [IFLA_IPTUN_TOS] = { .type = NLA_U8 },
  57. [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
  58. [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 },
  59. [IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
  60. };
  61. static int sit_alloc(struct rtnl_link *link)
  62. {
  63. struct sit_info *sit;
  64. sit = calloc(1, sizeof(*sit));
  65. if (!sit)
  66. return -NLE_NOMEM;
  67. link->l_info = sit;
  68. return 0;
  69. }
  70. static int sit_parse(struct rtnl_link *link, struct nlattr *data,
  71. struct nlattr *xstats)
  72. {
  73. struct nlattr *tb[IFLA_IPTUN_MAX + 1];
  74. struct sit_info *sit;
  75. int err;
  76. NL_DBG(3, "Parsing SIT link info");
  77. err = nla_parse_nested(tb, IFLA_IPTUN_MAX, data, sit_policy);
  78. if (err < 0)
  79. goto errout;
  80. err = sit_alloc(link);
  81. if (err < 0)
  82. goto errout;
  83. sit = link->l_info;
  84. if (tb[IFLA_IPTUN_LINK]) {
  85. sit->link = nla_get_u32(tb[IFLA_IPTUN_LINK]);
  86. sit->sit_mask |= SIT_ATTR_LINK;
  87. }
  88. if (tb[IFLA_IPTUN_LOCAL]) {
  89. sit->local = nla_get_u32(tb[IFLA_IPTUN_LOCAL]);
  90. sit->sit_mask |= SIT_ATTR_LOCAL;
  91. }
  92. if (tb[IFLA_IPTUN_REMOTE]) {
  93. sit->remote = nla_get_u32(tb[IFLA_IPTUN_REMOTE]);
  94. sit->sit_mask |= SIT_ATTR_REMOTE;
  95. }
  96. if (tb[IFLA_IPTUN_TTL]) {
  97. sit->ttl = nla_get_u8(tb[IFLA_IPTUN_TTL]);
  98. sit->sit_mask |= SIT_ATTR_TTL;
  99. }
  100. if (tb[IFLA_IPTUN_TOS]) {
  101. sit->tos = nla_get_u8(tb[IFLA_IPTUN_TOS]);
  102. sit->sit_mask |= SIT_ATTR_TOS;
  103. }
  104. if (tb[IFLA_IPTUN_PMTUDISC]) {
  105. sit->pmtudisc = nla_get_u8(tb[IFLA_IPTUN_PMTUDISC]);
  106. sit->sit_mask |= SIT_ATTR_PMTUDISC;
  107. }
  108. if (tb[IFLA_IPTUN_FLAGS]) {
  109. sit->flags = nla_get_u16(tb[IFLA_IPTUN_FLAGS]);
  110. sit->sit_mask |= SIT_ATTR_FLAGS;
  111. }
  112. if (tb[IFLA_IPTUN_PROTO]) {
  113. sit->proto = nla_get_u8(tb[IFLA_IPTUN_PROTO]);
  114. sit->sit_mask |= SIT_ATTR_PROTO;
  115. }
  116. err = 0;
  117. errout:
  118. return err;
  119. }
  120. static int sit_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
  121. {
  122. struct sit_info *sit = link->l_info;
  123. struct nlattr *data;
  124. data = nla_nest_start(msg, IFLA_INFO_DATA);
  125. if (!data)
  126. return -NLE_MSGSIZE;
  127. if (sit->sit_mask & SIT_ATTR_LINK)
  128. NLA_PUT_U32(msg, IFLA_IPTUN_LINK, sit->link);
  129. if (sit->sit_mask & SIT_ATTR_LOCAL)
  130. NLA_PUT_U32(msg, IFLA_IPTUN_LOCAL, sit->local);
  131. if (sit->sit_mask & SIT_ATTR_REMOTE)
  132. NLA_PUT_U32(msg, IFLA_IPTUN_REMOTE, sit->remote);
  133. if (sit->sit_mask & SIT_ATTR_TTL)
  134. NLA_PUT_U8(msg, IFLA_IPTUN_TTL, sit->ttl);
  135. if (sit->sit_mask & SIT_ATTR_TOS)
  136. NLA_PUT_U8(msg, IFLA_IPTUN_TOS, sit->tos);
  137. if (sit->sit_mask & SIT_ATTR_PMTUDISC)
  138. NLA_PUT_U8(msg, IFLA_IPTUN_PMTUDISC, sit->pmtudisc);
  139. if (sit->sit_mask & SIT_ATTR_FLAGS)
  140. NLA_PUT_U16(msg, IFLA_IPTUN_FLAGS, sit->flags);
  141. if (sit->sit_mask & SIT_ATTR_PROTO)
  142. NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, sit->proto);
  143. nla_nest_end(msg, data);
  144. nla_put_failure:
  145. return 0;
  146. }
  147. static void sit_free(struct rtnl_link *link)
  148. {
  149. struct sit_info *sit = link->l_info;
  150. free(sit);
  151. link->l_info = NULL;
  152. }
  153. static void sit_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
  154. {
  155. nl_dump(p, "sit : %s", link->l_name);
  156. }
  157. static void sit_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
  158. {
  159. struct sit_info *sit = link->l_info;
  160. char *name, addr[INET_ADDRSTRLEN];
  161. if (sit->sit_mask & SIT_ATTR_LINK) {
  162. nl_dump(p, " link ");
  163. name = rtnl_link_get_name(link);
  164. if (name)
  165. nl_dump_line(p, "%s\n", name);
  166. else
  167. nl_dump_line(p, "%u\n", sit->link);
  168. }
  169. if (sit->sit_mask & SIT_ATTR_LOCAL) {
  170. nl_dump(p, " local ");
  171. if(inet_ntop(AF_INET, &sit->local, addr, sizeof(addr)))
  172. nl_dump_line(p, "%s\n", addr);
  173. else
  174. nl_dump_line(p, "%#x\n", ntohs(sit->local));
  175. }
  176. if (sit->sit_mask & SIT_ATTR_REMOTE) {
  177. nl_dump(p, " remote ");
  178. if(inet_ntop(AF_INET, &sit->remote, addr, sizeof(addr)))
  179. nl_dump_line(p, "%s\n", addr);
  180. else
  181. nl_dump_line(p, "%#x\n", ntohs(sit->remote));
  182. }
  183. if (sit->sit_mask & SIT_ATTR_TTL) {
  184. nl_dump(p, " ttl ");
  185. nl_dump_line(p, "%u\n", sit->ttl);
  186. }
  187. if (sit->sit_mask & SIT_ATTR_TOS) {
  188. nl_dump(p, " tos ");
  189. nl_dump_line(p, "%u\n", sit->tos);
  190. }
  191. if (sit->sit_mask & SIT_ATTR_FLAGS) {
  192. nl_dump(p, " flags ");
  193. nl_dump_line(p, " (%x)\n", sit->flags);
  194. }
  195. if (sit->sit_mask & SIT_ATTR_PROTO) {
  196. nl_dump(p, " proto ");
  197. nl_dump_line(p, " (%x)\n", sit->proto);
  198. }
  199. }
  200. static int sit_clone(struct rtnl_link *dst, struct rtnl_link *src)
  201. {
  202. struct sit_info *sit_dst, *sit_src = src->l_info;
  203. int err;
  204. dst->l_info = NULL;
  205. err = rtnl_link_set_type(dst, "sit");
  206. if (err < 0)
  207. return err;
  208. sit_dst = dst->l_info;
  209. if (!sit_dst || !sit_src)
  210. return -NLE_NOMEM;
  211. memcpy(sit_dst, sit_src, sizeof(struct sit_info));
  212. return 0;
  213. }
  214. static struct rtnl_link_info_ops sit_info_ops = {
  215. .io_name = "sit",
  216. .io_alloc = sit_alloc,
  217. .io_parse = sit_parse,
  218. .io_dump = {
  219. [NL_DUMP_LINE] = sit_dump_line,
  220. [NL_DUMP_DETAILS] = sit_dump_details,
  221. },
  222. .io_clone = sit_clone,
  223. .io_put_attrs = sit_put_attrs,
  224. .io_free = sit_free,
  225. };
  226. #define IS_SIT_LINK_ASSERT(link) \
  227. if ((link)->l_info_ops != &sit_info_ops) { \
  228. APPBUG("Link is not a sit link. set type \"sit\" first."); \
  229. return -NLE_OPNOTSUPP; \
  230. }
  231. struct rtnl_link *rtnl_link_sit_alloc(void)
  232. {
  233. struct rtnl_link *link;
  234. int err;
  235. link = rtnl_link_alloc();
  236. if (!link)
  237. return NULL;
  238. err = rtnl_link_set_type(link, "sit");
  239. if (err < 0) {
  240. rtnl_link_put(link);
  241. return NULL;
  242. }
  243. return link;
  244. }
  245. /**
  246. * Check if link is a SIT link
  247. * @arg link Link object
  248. *
  249. * @return True if link is a SIT link, otherwise false is returned.
  250. */
  251. int rtnl_link_is_sit(struct rtnl_link *link)
  252. {
  253. return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "sit");
  254. }
  255. /**
  256. * Create a new sit tunnel device
  257. * @arg sock netlink socket
  258. * @arg name name of the tunnel device
  259. *
  260. * Creates a new sit tunnel device in the kernel
  261. * @return 0 on success or a negative error code
  262. */
  263. int rtnl_link_sit_add(struct nl_sock *sk, const char *name)
  264. {
  265. struct rtnl_link *link;
  266. int err;
  267. link = rtnl_link_sit_alloc();
  268. if (!link)
  269. return -NLE_NOMEM;
  270. if(name)
  271. rtnl_link_set_name(link, name);
  272. err = rtnl_link_add(sk, link, NLM_F_CREATE);
  273. rtnl_link_put(link);
  274. return err;
  275. }
  276. /**
  277. * Set SIT tunnel interface index
  278. * @arg link Link object
  279. * @arg index interface index
  280. *
  281. * @return 0 on success or a negative error code
  282. */
  283. int rtnl_link_sit_set_link(struct rtnl_link *link, uint32_t index)
  284. {
  285. struct sit_info *sit = link->l_info;
  286. IS_SIT_LINK_ASSERT(link);
  287. sit->link = index;
  288. sit->sit_mask |= SIT_ATTR_LINK;
  289. return 0;
  290. }
  291. /**
  292. * Get SIT tunnel interface index
  293. * @arg link Link object
  294. *
  295. * @return interface index value
  296. */
  297. uint32_t rtnl_link_sit_get_link(struct rtnl_link *link)
  298. {
  299. struct sit_info *sit = link->l_info;
  300. IS_SIT_LINK_ASSERT(link);
  301. return sit->link;
  302. }
  303. /**
  304. * Set SIT tunnel local address
  305. * @arg link Link object
  306. * @arg addr local address
  307. *
  308. * @return 0 on success or a negative error code
  309. */
  310. int rtnl_link_sit_set_local(struct rtnl_link *link, uint32_t addr)
  311. {
  312. struct sit_info *sit = link->l_info;
  313. IS_SIT_LINK_ASSERT(link);
  314. sit->local = addr;
  315. sit->sit_mask |= SIT_ATTR_LOCAL;
  316. return 0;
  317. }
  318. /**
  319. * Get SIT tunnel local address
  320. * @arg link Link object
  321. *
  322. * @return local address value
  323. */
  324. uint32_t rtnl_link_sit_get_local(struct rtnl_link *link)
  325. {
  326. struct sit_info *sit = link->l_info;
  327. IS_SIT_LINK_ASSERT(link);
  328. return sit->local;
  329. }
  330. /**
  331. * Set SIT tunnel remote address
  332. * @arg link Link object
  333. * @arg remote remote address
  334. *
  335. * @return 0 on success or a negative error code
  336. */
  337. int rtnl_link_sit_set_remote(struct rtnl_link *link, uint32_t addr)
  338. {
  339. struct sit_info *sit = link->l_info;
  340. IS_SIT_LINK_ASSERT(link);
  341. sit->remote = addr;
  342. sit->sit_mask |= SIT_ATTR_REMOTE;
  343. return 0;
  344. }
  345. /**
  346. * Get SIT tunnel remote address
  347. * @arg link Link object
  348. *
  349. * @return remote address
  350. */
  351. uint32_t rtnl_link_sit_get_remote(struct rtnl_link *link)
  352. {
  353. struct sit_info *sit = link->l_info;
  354. IS_SIT_LINK_ASSERT(link);
  355. return sit->remote;
  356. }
  357. /**
  358. * Set SIT tunnel ttl
  359. * @arg link Link object
  360. * @arg ttl tunnel ttl
  361. *
  362. * @return 0 on success or a negative error code
  363. */
  364. int rtnl_link_sit_set_ttl(struct rtnl_link *link, uint8_t ttl)
  365. {
  366. struct sit_info *sit = link->l_info;
  367. IS_SIT_LINK_ASSERT(link);
  368. sit->ttl = ttl;
  369. sit->sit_mask |= SIT_ATTR_TTL;
  370. return 0;
  371. }
  372. /**
  373. * Get SIT tunnel ttl
  374. * @arg link Link object
  375. *
  376. * @return ttl value
  377. */
  378. uint8_t rtnl_link_sit_get_ttl(struct rtnl_link *link)
  379. {
  380. struct sit_info *sit = link->l_info;
  381. IS_SIT_LINK_ASSERT(link);
  382. return sit->ttl;
  383. }
  384. /**
  385. * Set SIT tunnel tos
  386. * @arg link Link object
  387. * @arg tos tunnel tos
  388. *
  389. * @return 0 on success or a negative error code
  390. */
  391. int rtnl_link_sit_set_tos(struct rtnl_link *link, uint8_t tos)
  392. {
  393. struct sit_info *sit = link->l_info;
  394. IS_SIT_LINK_ASSERT(link);
  395. sit->tos = tos;
  396. sit->sit_mask |= SIT_ATTR_TOS;
  397. return 0;
  398. }
  399. /**
  400. * Get SIT tunnel tos
  401. * @arg link Link object
  402. *
  403. * @return tos value
  404. */
  405. uint8_t rtnl_link_sit_get_tos(struct rtnl_link *link)
  406. {
  407. struct sit_info *sit = link->l_info;
  408. IS_SIT_LINK_ASSERT(link);
  409. return sit->tos;
  410. }
  411. /**
  412. * Set SIT tunnel path MTU discovery
  413. * @arg link Link object
  414. * @arg pmtudisc path MTU discovery
  415. *
  416. * @return 0 on success or a negative error code
  417. */
  418. int rtnl_link_sit_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc)
  419. {
  420. struct sit_info *sit = link->l_info;
  421. IS_SIT_LINK_ASSERT(link);
  422. sit->pmtudisc = pmtudisc;
  423. sit->sit_mask |= SIT_ATTR_PMTUDISC;
  424. return 0;
  425. }
  426. /**
  427. * Get SIT path MTU discovery
  428. * @arg link Link object
  429. *
  430. * @return pmtudisc value
  431. */
  432. uint8_t rtnl_link_sit_get_pmtudisc(struct rtnl_link *link)
  433. {
  434. struct sit_info *sit = link->l_info;
  435. IS_SIT_LINK_ASSERT(link);
  436. return sit->pmtudisc;
  437. }
  438. /**
  439. * Set SIT tunnel flags
  440. * @arg link Link object
  441. * @arg flags tunnel flags
  442. *
  443. * @return 0 on success or a negative error code
  444. */
  445. int rtnl_link_sit_set_flags(struct rtnl_link *link, uint16_t flags)
  446. {
  447. struct sit_info *sit = link->l_info;
  448. IS_SIT_LINK_ASSERT(link);
  449. sit->flags = flags;
  450. sit->sit_mask |= SIT_ATTR_FLAGS;
  451. return 0;
  452. }
  453. /**
  454. * Get SIT path flags
  455. * @arg link Link object
  456. *
  457. * @return flags value
  458. */
  459. uint16_t rtnl_link_sit_get_flags(struct rtnl_link *link)
  460. {
  461. struct sit_info *sit = link->l_info;
  462. IS_SIT_LINK_ASSERT(link);
  463. return sit->flags;
  464. }
  465. /**
  466. * Set SIT tunnel proto
  467. * @arg link Link object
  468. * @arg proto tunnel proto
  469. *
  470. * @return 0 on success or a negative error code
  471. */
  472. int rtnl_link_sit_set_proto(struct rtnl_link *link, uint8_t proto)
  473. {
  474. struct sit_info *sit = link->l_info;
  475. IS_SIT_LINK_ASSERT(link);
  476. sit->proto = proto;
  477. sit->sit_mask |= SIT_ATTR_PROTO;
  478. return 0;
  479. }
  480. /**
  481. * Get SIT proto
  482. * @arg link Link object
  483. *
  484. * @return proto value
  485. */
  486. uint8_t rtnl_link_sit_get_proto(struct rtnl_link *link)
  487. {
  488. struct sit_info *sit = link->l_info;
  489. IS_SIT_LINK_ASSERT(link);
  490. return sit->proto;
  491. }
  492. static void __init sit_init(void)
  493. {
  494. rtnl_link_register_info(&sit_info_ops);
  495. }
  496. static void __exit sit_exit(void)
  497. {
  498. rtnl_link_unregister_info(&sit_info_ops);
  499. }