main.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include "address.h"
  2. #include "hardware_address.h"
  3. #include "link.h"
  4. #include "vector.h"
  5. #include <cassert>
  6. #include <cstdlib>
  7. #include <iostream>
  8. #include <libmnl/libmnl.h>
  9. #include <linux/if_addr.h>
  10. #include <linux/netlink.h>
  11. #include <linux/rtnetlink.h>
  12. // https://netfilter.org/projects/libmnl/doxygen/html/modules.html
  13. void mnl_recv_run_cb_all(const mnl_socket *nl, void *buf, size_t bufsiz,
  14. mnl_cb_t cb_data, void *data) {
  15. unsigned int nlpid = mnl_socket_get_portid(nl);
  16. ssize_t numbytes = mnl_socket_recvfrom(nl, buf, bufsiz);
  17. while (numbytes > 0) {
  18. if (mnl_cb_run(buf, numbytes, 0, nlpid, cb_data, data) <= MNL_CB_STOP) {
  19. break;
  20. }
  21. numbytes = mnl_socket_recvfrom(nl, buf, bufsiz);
  22. }
  23. assert(numbytes != -1);
  24. }
  25. int link_cb(const nlmsghdr *nlh, void *data) {
  26. vector<Link> *links = (vector<Link> *)data;
  27. links->emplace_back();
  28. mnl_attr_parse(nlh, sizeof(ifinfomsg), Link::mnl_attr_cb, &links->back());
  29. return MNL_CB_OK;
  30. }
  31. void mnl_read_links(const mnl_socket *nl, vector<Link> *links) {
  32. uint8_t msgbuf[MNL_SOCKET_BUFFER_SIZE];
  33. nlmsghdr *nlh = mnl_nlmsg_put_header(msgbuf);
  34. nlh->nlmsg_type = RTM_GETLINK;
  35. nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
  36. mnl_nlmsg_put_extra_header(nlh, sizeof(rtgenmsg));
  37. assert(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) > 0);
  38. mnl_recv_run_cb_all(nl, msgbuf, sizeof(msgbuf), link_cb, links);
  39. }
  40. static int address_cb(const struct nlmsghdr *nlh, void *data) {
  41. vector<Address> *addrs = (vector<Address> *)data;
  42. addrs->emplace_back();
  43. addrs->back() = (const ifaddrmsg *)mnl_nlmsg_get_payload(nlh);
  44. mnl_attr_parse(nlh, sizeof(ifaddrmsg), Address::mnl_attr_cb, &addrs->back());
  45. return MNL_CB_OK;
  46. }
  47. void mnl_read_addresses(const mnl_socket *nl, vector<Address> *addrs) {
  48. char msgbuf[MNL_SOCKET_BUFFER_SIZE];
  49. nlmsghdr *nlh = mnl_nlmsg_put_header(msgbuf);
  50. nlh->nlmsg_type = RTM_GETADDR;
  51. nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
  52. rtgenmsg *rt = (rtgenmsg *)mnl_nlmsg_put_extra_header(nlh, sizeof(rtgenmsg));
  53. rt->rtgen_family = AF_UNSPEC;
  54. assert(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) > 0);
  55. mnl_recv_run_cb_all(nl, msgbuf, sizeof(msgbuf), address_cb, addrs);
  56. }
  57. int main(int argc, char *argv[]) {
  58. mnl_socket *nl = mnl_socket_open(NETLINK_ROUTE);
  59. assert(nl);
  60. assert(mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) == 0);
  61. vector<Link> links;
  62. mnl_read_links(nl, &links);
  63. std::cout << "links: ";
  64. links.write_yaml(std::cout);
  65. vector<Address> addrs;
  66. mnl_read_addresses(nl, &addrs);
  67. std::cout << "addresses: ";
  68. addrs.write_yaml(std::cout);
  69. std::cout << std::endl;
  70. mnl_socket_close(nl);
  71. return EXIT_SUCCESS;
  72. }