Browse Source

show ipv4 addresses

Fabian Peter Hammerle 7 years ago
parent
commit
bb4327dbfc
3 changed files with 74 additions and 4 deletions
  1. 5 1
      README.md
  2. 42 0
      address.h
  3. 27 3
      main.cpp

+ 5 - 1
README.md

@@ -12,7 +12,7 @@ apt install libmnl-dev linux-libc-dev g++
 
 ```yaml
 $ ipyml
-
+links:
 - ifname: lo
   address: 00:00:00:00:00:00
   broadcast: 00:00:00:00:00:00
@@ -28,6 +28,10 @@ $ ipyml
   broadcast: ff:ff:ff:ff:ff:ff
   mtu: 1500
   operstate: up
+addresses:
+- 127.0.0.1
+- 192.168.2.101
+- 192.168.20.11
 
 ```
 

+ 42 - 0
address.h

@@ -0,0 +1,42 @@
+#ifndef _IPYML_ADDRESS_H
+#define _IPYML_ADDRESS_H
+
+#include "yaml.h"
+
+#include <arpa/inet.h>
+#include <cassert>
+#include <cstring>
+#include <libmnl/libmnl.h>
+#include <linux/if_addr.h>
+#include <linux/netlink.h>
+#include <netinet/in.h>
+#include <ostream>
+
+class Address : public YamlObject {
+public:
+  unsigned char address[sizeof(in_addr_t)];
+
+public:
+  // typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);
+  static int mnl_attr_cb(const nlattr *attr, void *data) {
+    Address *addr = (Address *)data;
+    // /usr/include/linux/if_addr.h
+    switch (mnl_attr_get_type(attr)) {
+    case IFA_ADDRESS:
+      assert(mnl_attr_validate(attr, MNL_TYPE_BINARY) == 0);
+      assert(mnl_attr_get_payload_len(attr) == sizeof(address));
+      memcpy(addr->address, mnl_attr_get_payload(attr), sizeof(address));
+      break;
+    }
+  }
+
+  void write_yaml(std::ostream &stream,
+                  const yaml_indent_level_t indent_level = 0) const {
+    // const std::string indent(indent_level, ' ');
+    char addr_str[INET_ADDRSTRLEN];
+    inet_ntop(AF_INET, address, addr_str, sizeof(addr_str));
+    stream << addr_str << '\n';
+  }
+};
+
+#endif

+ 27 - 3
main.cpp

@@ -1,3 +1,4 @@
+#include "address.h"
 #include "hardware_address.h"
 #include "link.h"
 #include "vector.h"
@@ -8,7 +9,6 @@
 #include <libmnl/libmnl.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
-#include <string>
 
 // https://netfilter.org/projects/libmnl/doxygen/html/modules.html
 
@@ -25,7 +25,7 @@ void mnl_recv_run_cb_all(const mnl_socket *nl, void *buf, size_t bufsiz,
   assert(numbytes != -1);
 }
 
-static int link_cb(const nlmsghdr *nlh, void *data) {
+int link_cb(const nlmsghdr *nlh, void *data) {
   vector<Link> *links = (vector<Link> *)data;
   links->emplace_back();
   mnl_attr_parse(nlh, sizeof(ifinfomsg), Link::mnl_attr_cb, &links->back());
@@ -42,6 +42,24 @@ void mnl_read_links(const mnl_socket *nl, vector<Link> *links) {
   mnl_recv_run_cb_all(nl, msgbuf, sizeof(msgbuf), link_cb, links);
 }
 
+static int address_cb(const struct nlmsghdr *nlh, void *data) {
+  vector<Address> *addrs = (vector<Address> *)data;
+  addrs->emplace_back();
+  mnl_attr_parse(nlh, sizeof(ifaddrmsg), Address::mnl_attr_cb, &addrs->back());
+  return MNL_CB_OK;
+}
+
+void mnl_read_addresses(const mnl_socket *nl, vector<Address> *addrs) {
+  char msgbuf[MNL_SOCKET_BUFFER_SIZE];
+  nlmsghdr *nlh = mnl_nlmsg_put_header(msgbuf);
+  nlh->nlmsg_type = RTM_GETADDR;
+  nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+  rtgenmsg *rt = (rtgenmsg *)mnl_nlmsg_put_extra_header(nlh, sizeof(rtgenmsg));
+  rt->rtgen_family = AF_INET;
+  assert(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) > 0);
+  mnl_recv_run_cb_all(nl, msgbuf, sizeof(msgbuf), address_cb, addrs);
+}
+
 int main(int argc, char *argv[]) {
   mnl_socket *nl = mnl_socket_open(NETLINK_ROUTE);
   assert(nl);
@@ -49,9 +67,15 @@ int main(int argc, char *argv[]) {
 
   vector<Link> links;
   mnl_read_links(nl, &links);
+  std::cout << "links: ";
   links.write_yaml(std::cout);
-  std::cout << std::endl;
 
+  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;
 }