Browse Source

show addresses as items of associated link

Fabian Peter Hammerle 7 years ago
parent
commit
e250b43753
8 changed files with 67 additions and 28 deletions
  1. 9 7
      README.md
  2. 15 4
      address.h
  3. 1 2
      inet6_address.h
  4. 2 3
      inet_address.h
  5. 2 0
      link.cpp
  6. 3 0
      link.h
  7. 27 0
      list.h
  8. 8 12
      main.cpp

+ 9 - 7
README.md

@@ -18,22 +18,24 @@ links:
   broadcast: 00:00:00:00:00:00
   mtu: 65536
   operstate: unknown
+  addresses:
+    - 127.0.0.1
 - ifname: eth0
   address: 11:22:33:44:55:66
   broadcast: ff:ff:ff:ff:ff:ff
   mtu: 1500
-  operstate: down
+  operstate: up
+  addresses:
+    - 192.168.2.101
+    - fe80::1322:33ff:fe44:5566
 - ifname: wlan0
   address: 77:88:99:00:aa:bb
   broadcast: ff:ff:ff:ff:ff:ff
   mtu: 1500
   operstate: up
-addresses:
-- 127.0.0.1
-- 192.168.2.101
-- 192.168.20.11
-- fe80::1322:33ff:fe44:5566
-- fe80::7588:99ff:fe00:aabb
+  addresses:
+    - 192.168.20.11
+    - fe80::7588:99ff:fe00:aabb
 
 ```
 

+ 15 - 4
address.h

@@ -12,6 +12,10 @@
 #include <ostream>         // std::ostream
 
 class Address : public YamlObject {
+public:
+  unsigned int ifindex;
+
+private:
   unsigned char family;
   union {
     InetAddress inet_addr;
@@ -19,12 +23,19 @@ class Address : public YamlObject {
   };
 
 public:
-  Address() : family(AF_UNSPEC) {}
-
-  Address &operator=(const ifaddrmsg *msg) {
+  Address(const ifaddrmsg *msg) {
+    /*
+    struct ifaddrmsg {
+        unsigned char ifa_family;    // Address type
+        unsigned char ifa_prefixlen; // Prefixlength of address
+        unsigned char ifa_flags;     // Address flags
+        unsigned char ifa_scope;     // Address scope
+        int           ifa_index;     // Interface index
+    };
+    */
+    ifindex = msg->ifa_index;
     family = msg->ifa_family;
     assert(family == AF_INET || family == AF_INET6);
-    return *this;
   }
 
   // typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);

+ 1 - 2
inet6_address.h

@@ -8,9 +8,8 @@
 #include <cassert>         // assert
 #include <cstring>         // memcpy
 #include <libmnl/libmnl.h> // mnl_attr_*
-#include <linux/in6.h>     // struct in6_addr
 #include <linux/netlink.h> // struct nlattr
-#include <netinet/in.h>    // INET6_ADDRSTRLEN
+#include <netinet/in.h>    // INET6_ADDRSTRLEN, struct in6_addr
 #include <ostream>         // std::ostream
 
 /*

+ 2 - 3
inet_address.h

@@ -8,9 +8,8 @@
 #include <cassert>         // assert
 #include <cstring>         // memcpy
 #include <libmnl/libmnl.h> // mnl_attr_*
-#include <linux/in.h>      // struct in_addr_t
 #include <linux/netlink.h> // struct nlattr
-#include <netinet/in.h>    // INET_ADDRSTRLEN
+#include <netinet/in.h>    // INET_ADDRSTRLEN, struct in_addr
 #include <ostream>         // std::ostream
 
 /*
@@ -20,7 +19,7 @@ class may not have any virtual member due to:
 */
 
 class InetAddress { // : public YamlObject {
-  unsigned char bytes[sizeof(in_addr_t)];
+  unsigned char bytes[sizeof(in_addr)];
 
 public:
   InetAddress &operator=(const nlattr *attr) {

+ 2 - 0
link.cpp

@@ -57,4 +57,6 @@ void Link::write_yaml(std::ostream &stream,
   stream << indent << "mtu: " << mtu << "\n";
   stream << indent << "operstate: ";
   operstate.write_yaml(stream);
+  stream << indent << "addresses: ";
+  addresses.write_yaml(stream, indent_level + 2);
 }

+ 3 - 0
link.h

@@ -1,8 +1,10 @@
 #ifndef _IPYML_LINK_H
 #define _IPYML_LINK_H
 
+#include "address.h"
 #include "hardware_address.h"
 #include "operstate.h"
+#include "list.h"
 #include "yaml.h"
 
 #include <linux/netlink.h>
@@ -13,6 +15,7 @@
 class Link : public YamlObject {
 public:
   unsigned int index;
+  list<Address> addresses;
 
 private:
   std::string ifname;

+ 27 - 0
list.h

@@ -0,0 +1,27 @@
+#ifndef _IPYML_LIST_H
+#define _IPYML_LIST_H
+
+#include "yaml.h"
+
+#include <list>    // std::list
+#include <ostream> // std::ostream
+#include <string>  // std::string
+
+template <class T> class list : public std::list<T>, YamlObject {
+public:
+  void write_yaml(std::ostream &stream,
+                  const yaml_indent_level_t indent_level = 0) const {
+    if (this->empty()) {
+      stream << "[]";
+    } else {
+      const std::string indent(indent_level, ' ');
+      stream << "\n";
+      for (auto it = this->begin(); it != this->end(); it++) {
+        stream << indent << "- ";
+        it->write_yaml(stream, indent_level + 2);
+      }
+    }
+  }
+};
+
+#endif

+ 8 - 12
main.cpp

@@ -45,14 +45,14 @@ void mnl_read_links(const mnl_socket *nl, vector<Link> *links) {
 }
 
 static int address_cb(const struct nlmsghdr *nlh, void *data) {
-  vector<Address> *addrs = (vector<Address> *)data;
-  addrs->emplace_back();
-  addrs->back() = (const ifaddrmsg *)mnl_nlmsg_get_payload(nlh);
-  mnl_attr_parse(nlh, sizeof(ifaddrmsg), Address::mnl_attr_cb, &addrs->back());
+  vector<Link> *links = (vector<Link> *)data;
+  Address addr((const ifaddrmsg *)mnl_nlmsg_get_payload(nlh));
+  mnl_attr_parse(nlh, sizeof(ifaddrmsg), Address::mnl_attr_cb, &addr);
+  links->at(addr.ifindex - 1).addresses.push_back(addr);
   return MNL_CB_OK;
 }
 
-void mnl_read_addresses(const mnl_socket *nl, vector<Address> *addrs) {
+void mnl_add_addresses(const mnl_socket *nl, vector<Link> *links) {
   char msgbuf[MNL_SOCKET_BUFFER_SIZE];
   nlmsghdr *nlh = mnl_nlmsg_put_header(msgbuf);
   nlh->nlmsg_type = RTM_GETADDR;
@@ -60,7 +60,7 @@ void mnl_read_addresses(const mnl_socket *nl, vector<Address> *addrs) {
   rtgenmsg *rt = (rtgenmsg *)mnl_nlmsg_put_extra_header(nlh, sizeof(rtgenmsg));
   rt->rtgen_family = AF_UNSPEC;
   assert(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) > 0);
-  mnl_recv_run_cb_all(nl, msgbuf, sizeof(msgbuf), address_cb, addrs);
+  mnl_recv_run_cb_all(nl, msgbuf, sizeof(msgbuf), address_cb, links);
 }
 
 int main(int argc, char *argv[]) {
@@ -70,15 +70,11 @@ int main(int argc, char *argv[]) {
 
   vector<Link> links;
   mnl_read_links(nl, &links);
+  mnl_add_addresses(nl, &links);
   std::cout << "links: ";
   links.write_yaml(std::cout);
-
-  vector<Address> addrs;
-  mnl_read_addresses(nl, &addrs);
-  std::cout << "addresses: ";
-  addrs.write_yaml(std::cout);
-
   std::cout << std::endl;
+
   mnl_socket_close(nl);
   return EXIT_SUCCESS;
 }