address.h 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #ifndef _IPYML_ADDRESS_H
  2. #define _IPYML_ADDRESS_H
  3. #include "inet6_address.h"
  4. #include "inet_address.h"
  5. #include "yaml.h"
  6. #include <bits/socket.h> // AF_*
  7. #include <libmnl/libmnl.h> // mnl_attr_get_type
  8. #include <linux/if_addr.h> // struct ifaddrmsg
  9. #include <linux/netlink.h> // struct nlattr
  10. #include <ostream> // std::ostream
  11. // https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/ipaddress.c
  12. // print_addrinfo()
  13. class Address : public YamlObject {
  14. public:
  15. unsigned int ifindex;
  16. private:
  17. unsigned char family, prefixlen;
  18. union {
  19. InetAddress inet_addr;
  20. Inet6Address inet6_addr;
  21. };
  22. public:
  23. Address(const ifaddrmsg *msg) {
  24. /*
  25. struct ifaddrmsg {
  26. unsigned char ifa_family; // Address type
  27. unsigned char ifa_prefixlen; // Prefixlength of address
  28. unsigned char ifa_flags; // Address flags
  29. unsigned char ifa_scope; // Address scope
  30. int ifa_index; // Interface index
  31. };
  32. */
  33. ifindex = msg->ifa_index;
  34. family = msg->ifa_family;
  35. assert(family == AF_INET || family == AF_INET6);
  36. prefixlen = msg->ifa_prefixlen;
  37. }
  38. // typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);
  39. static int mnl_attr_cb(const nlattr *attr, void *data) {
  40. Address *addr = (Address *)data;
  41. assert(addr->family != AF_UNSPEC);
  42. // /usr/include/linux/if_addr.h
  43. switch (mnl_attr_get_type(attr)) {
  44. case IFA_ADDRESS:
  45. if (addr->family == AF_INET) {
  46. addr->inet_addr = attr;
  47. } else if (addr->family == AF_INET6) {
  48. addr->inet6_addr = attr;
  49. }
  50. break;
  51. }
  52. }
  53. void write_yaml(std::ostream &stream,
  54. const yaml_indent_level_t indent_level = 0) const {
  55. // const std::string indent(indent_level, ' ');
  56. if (family == AF_INET) {
  57. stream << inet_addr.format();
  58. } else if (family == AF_INET6) {
  59. stream << inet6_addr.format();
  60. }
  61. stream << '/' << (int)prefixlen << '\n';
  62. }
  63. };
  64. #endif