veth.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * lib/route/link/veth.c Virtual Ethernet
  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) 2013 Cong Wang <xiyou.wangcong@gmail.com>
  10. */
  11. /**
  12. * @ingroup link
  13. * @defgroup veth VETH
  14. * Virtual Ethernet
  15. *
  16. * @details
  17. * \b Link Type Name: "veth"
  18. *
  19. * @route_doc{link_veth, VETH 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 <netlink/route/link/veth.h>
  31. #include <linux/if_link.h>
  32. static struct nla_policy veth_policy[VETH_INFO_MAX+1] = {
  33. [VETH_INFO_PEER] = { .minlen = sizeof(struct ifinfomsg) },
  34. };
  35. static int veth_parse(struct rtnl_link *link, struct nlattr *data,
  36. struct nlattr *xstats)
  37. {
  38. struct nlattr *tb[VETH_INFO_MAX+1];
  39. struct nlattr *peer_tb[IFLA_MAX + 1];
  40. struct rtnl_link *peer = link->l_info;
  41. int err;
  42. NL_DBG(3, "Parsing veth link info");
  43. if ((err = nla_parse_nested(tb, VETH_INFO_MAX, data, veth_policy)) < 0)
  44. goto errout;
  45. if (tb[VETH_INFO_PEER]) {
  46. struct nlattr *nla_peer;
  47. struct ifinfomsg *ifi;
  48. nla_peer = tb[VETH_INFO_PEER];
  49. ifi = nla_data(nla_peer);
  50. peer->l_family = ifi->ifi_family;
  51. peer->l_arptype = ifi->ifi_type;
  52. peer->l_index = ifi->ifi_index;
  53. peer->l_flags = ifi->ifi_flags;
  54. peer->l_change = ifi->ifi_change;
  55. err = nla_parse(peer_tb, IFLA_MAX,
  56. nla_data(nla_peer) + sizeof(struct ifinfomsg),
  57. nla_len(nla_peer) - sizeof(struct ifinfomsg),
  58. rtln_link_policy);
  59. if (err < 0)
  60. goto errout;
  61. err = rtnl_link_info_parse(peer, peer_tb);
  62. if (err < 0)
  63. goto errout;
  64. }
  65. err = 0;
  66. errout:
  67. return err;
  68. }
  69. static void veth_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
  70. {
  71. }
  72. static void veth_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
  73. {
  74. struct rtnl_link *peer = link->l_info;
  75. char *name;
  76. name = rtnl_link_get_name(peer);
  77. nl_dump(p, " peer ");
  78. if (name)
  79. nl_dump_line(p, "%s\n", name);
  80. else
  81. nl_dump_line(p, "%u\n", peer->l_index);
  82. }
  83. static int veth_clone(struct rtnl_link *dst, struct rtnl_link *src)
  84. {
  85. struct rtnl_link *dst_peer = NULL, *src_peer = src->l_info;
  86. /* we are calling nl_object_clone() recursively, this should
  87. * happen only once */
  88. if (src_peer) {
  89. src_peer->l_info = NULL;
  90. dst_peer = (struct rtnl_link *)nl_object_clone(OBJ_CAST(src_peer));
  91. if (!dst_peer)
  92. return -NLE_NOMEM;
  93. src_peer->l_info = src;
  94. dst_peer->l_info = dst;
  95. }
  96. dst->l_info = dst_peer;
  97. return 0;
  98. }
  99. static int veth_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
  100. {
  101. struct rtnl_link *peer = link->l_info;
  102. struct ifinfomsg ifi;
  103. struct nlattr *data, *info_peer;
  104. memset(&ifi, 0, sizeof ifi);
  105. ifi.ifi_family = peer->l_family;
  106. ifi.ifi_type = peer->l_arptype;
  107. ifi.ifi_index = peer->l_index;
  108. ifi.ifi_flags = peer->l_flags;
  109. ifi.ifi_change = peer->l_change;
  110. if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
  111. return -NLE_MSGSIZE;
  112. if (!(info_peer = nla_nest_start(msg, VETH_INFO_PEER)))
  113. return -NLE_MSGSIZE;
  114. if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
  115. return -NLE_MSGSIZE;
  116. rtnl_link_fill_info(msg, peer);
  117. nla_nest_end(msg, info_peer);
  118. nla_nest_end(msg, data);
  119. return 0;
  120. }
  121. static int veth_alloc(struct rtnl_link *link)
  122. {
  123. struct rtnl_link *peer;
  124. int err;
  125. /* return early if we are in recursion */
  126. if (link->l_info)
  127. return 0;
  128. if (!(peer = rtnl_link_alloc()))
  129. return -NLE_NOMEM;
  130. /* We don't need to hold a reference here, as link and
  131. * its peer should always be freed together.
  132. */
  133. peer->l_info = link;
  134. if ((err = rtnl_link_set_type(peer, "veth")) < 0) {
  135. rtnl_link_put(peer);
  136. return err;
  137. }
  138. link->l_info = peer;
  139. return 0;
  140. }
  141. static void veth_free(struct rtnl_link *link)
  142. {
  143. struct rtnl_link *peer = link->l_info;
  144. if (peer) {
  145. link->l_info = NULL;
  146. /* avoid calling this recursively */
  147. peer->l_info = NULL;
  148. rtnl_link_put(peer);
  149. }
  150. /* the caller should finally free link */
  151. }
  152. static struct rtnl_link_info_ops veth_info_ops = {
  153. .io_name = "veth",
  154. .io_parse = veth_parse,
  155. .io_dump = {
  156. [NL_DUMP_LINE] = veth_dump_line,
  157. [NL_DUMP_DETAILS] = veth_dump_details,
  158. },
  159. .io_alloc = veth_alloc,
  160. .io_clone = veth_clone,
  161. .io_put_attrs = veth_put_attrs,
  162. .io_free = veth_free,
  163. };
  164. /** @cond SKIP */
  165. #define IS_VETH_LINK_ASSERT(link) \
  166. if ((link)->l_info_ops != &veth_info_ops) { \
  167. APPBUG("Link is not a veth link. set type \"veth\" first."); \
  168. return NULL; \
  169. }
  170. /** @endcond */
  171. /**
  172. * @name VETH Object
  173. * @{
  174. */
  175. /**
  176. * Allocate link object of type veth
  177. *
  178. * @return Allocated link object or NULL.
  179. */
  180. struct rtnl_link *rtnl_link_veth_alloc(void)
  181. {
  182. struct rtnl_link *link;
  183. int err;
  184. if (!(link = rtnl_link_alloc()))
  185. return NULL;
  186. if ((err = rtnl_link_set_type(link, "veth")) < 0) {
  187. rtnl_link_put(link);
  188. return NULL;
  189. }
  190. return link;
  191. }
  192. /**
  193. * Get the peer link of a veth link
  194. *
  195. * @return the peer link object.
  196. */
  197. struct rtnl_link *rtnl_link_veth_get_peer(struct rtnl_link *link)
  198. {
  199. IS_VETH_LINK_ASSERT(link);
  200. nl_object_get(OBJ_CAST(link->l_info));
  201. return link->l_info;
  202. }
  203. /**
  204. * Release a veth link and its peer
  205. *
  206. */
  207. void rtnl_link_veth_release(struct rtnl_link *link)
  208. {
  209. veth_free(link);
  210. rtnl_link_put(link);
  211. }
  212. /**
  213. * Check if link is a veth link
  214. * @arg link Link object
  215. *
  216. * @return True if link is a veth link, otherwise false is returned.
  217. */
  218. int rtnl_link_is_veth(struct rtnl_link *link)
  219. {
  220. return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "veth");
  221. }
  222. /**
  223. * Create a new kernel veth device
  224. * @arg sock netlink socket
  225. * @arg name name of the veth device or NULL
  226. * @arg peer_name name of its peer or NULL
  227. * @arg pid pid of the process in the new netns
  228. *
  229. * Creates a new veth device pair in the kernel and move the peer
  230. * to the network namespace where the process is. If no name is
  231. * provided, the kernel will automatically pick a name of the
  232. * form "veth%d" (e.g. veth0, veth1, etc.)
  233. *
  234. * @return 0 on success or a negative error code
  235. */
  236. int rtnl_link_veth_add(struct nl_sock *sock, const char *name,
  237. const char *peer_name, pid_t pid)
  238. {
  239. struct rtnl_link *link, *peer;
  240. int err = -NLE_NOMEM;
  241. if (!(link = rtnl_link_veth_alloc()))
  242. return -NLE_NOMEM;
  243. peer = link->l_info;
  244. if (name && peer_name) {
  245. rtnl_link_set_name(link, name);
  246. rtnl_link_set_name(peer, peer_name);
  247. }
  248. rtnl_link_set_ns_pid(peer, pid);
  249. err = rtnl_link_add(sock, link, NLM_F_CREATE | NLM_F_EXCL);
  250. rtnl_link_put(link);
  251. return err;
  252. }
  253. /** @} */
  254. static void __init veth_init(void)
  255. {
  256. rtnl_link_register_info(&veth_info_ops);
  257. }
  258. static void __exit veth_exit(void)
  259. {
  260. rtnl_link_unregister_info(&veth_info_ops);
  261. }
  262. /** @} */