main.cpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #include "hardware_address.h"
  2. #include "vector.h"
  3. #include "yaml.h"
  4. #include <assert.h>
  5. #include <iostream>
  6. #include <libmnl/libmnl.h>
  7. #include <linux/if.h>
  8. #include <linux/rtnetlink.h>
  9. #include <string>
  10. // https://netfilter.org/projects/libmnl/doxygen/html/modules.html
  11. struct Link : public YamlObject {
  12. std::string ifname;
  13. HardwareAddress hwaddr, broadcast;
  14. void write_yaml(std::ostream &stream,
  15. const yaml_indent_level_t indent_level = 0) const {
  16. const std::string indent(indent_level, ' ');
  17. stream << "ifname: " + ifname + "\n";
  18. stream << indent + "hwaddr: ";
  19. hwaddr.write_yaml(stream);
  20. stream << "\n";
  21. stream << indent + "broadcast: ";
  22. broadcast.write_yaml(stream);
  23. stream << "\n";
  24. }
  25. };
  26. static int link_attr_cb(const nlattr *attr, void *data) {
  27. Link *link = (Link *)data;
  28. // /usr/include/linux/if_link.h
  29. switch (mnl_attr_get_type(attr)) {
  30. case IFLA_ADDRESS:
  31. link->hwaddr = attr;
  32. break;
  33. case IFLA_BROADCAST:
  34. link->broadcast = attr;
  35. break;
  36. case IFLA_IFNAME:
  37. link->ifname = mnl_attr_get_str(attr);
  38. break;
  39. }
  40. return MNL_CB_OK;
  41. }
  42. static int link_cb(const nlmsghdr *nlh, void *data) {
  43. vector<Link> *links = (vector<Link> *)data;
  44. links->emplace_back();
  45. mnl_attr_parse(nlh, sizeof(ifinfomsg), link_attr_cb, &links->back());
  46. return MNL_CB_OK;
  47. }
  48. int main(int argc, char *argv[]) {
  49. mnl_socket *nl = mnl_socket_open(NETLINK_ROUTE);
  50. assert(nl);
  51. assert(mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) == 0);
  52. unsigned int nlpid = mnl_socket_get_portid(nl);
  53. uint8_t msgbuf[MNL_SOCKET_BUFFER_SIZE];
  54. nlmsghdr *nlh = mnl_nlmsg_put_header(msgbuf);
  55. nlh->nlmsg_type = RTM_GETLINK;
  56. nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
  57. nlh->nlmsg_seq = 0;
  58. mnl_nlmsg_put_extra_header(nlh, sizeof(rtgenmsg));
  59. assert(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) > 0);
  60. vector<Link> links;
  61. size_t numbytes = mnl_socket_recvfrom(nl, msgbuf, sizeof(msgbuf));
  62. while (numbytes > 0) {
  63. if (mnl_cb_run(msgbuf, numbytes, nlh->nlmsg_seq, nlpid, link_cb, &links) <=
  64. MNL_CB_STOP) {
  65. break;
  66. } else {
  67. numbytes = mnl_socket_recvfrom(nl, msgbuf, sizeof(msgbuf));
  68. }
  69. }
  70. assert(numbytes != -1);
  71. links.write_yaml(std::cout);
  72. std::cout << std::endl;
  73. mnl_socket_close(nl);
  74. return EXIT_SUCCESS;
  75. }