reserve merge conflicts from latest sf.net pull
[olsrd.git] / lib / txtinfo / src / olsrd_txtinfo.c
index e0013e4..94d7855 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * The olsr.org Optimized Link-State Routing daemon(olsrd)
- * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+ * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
  *                     includes code by Bruno Randolf
  *                     includes code by Andreas Lopatic
  *                     includes code by Sven-Ola Tuecke
@@ -40,7 +40,6 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: olsrd_txtinfo.c,v 1.5 2007/04/28 19:58:49 bernd67 Exp $
  */
 
 /*
@@ -65,6 +64,7 @@
 #include <unistd.h>
 #include <errno.h>
 
+#include "ipcalc.h"
 #include "olsr.h"
 #include "olsr_types.h"
 #include "neighbor_table.h"
@@ -75,6 +75,7 @@
 #include "mid_set.h"
 #include "link_set.h"
 #include "socket_parser.h"
+#include "net_olsr.h"
 
 #include "olsrd_txtinfo.h"
 #include "olsrd_plugin.h"
@@ -92,33 +93,36 @@ static int ipc_socket_up;
 
 
 /* IPC initialization function */
-static int
-plugin_ipc_init(void);
+static int plugin_ipc_init(void);
+
+static void send_info(int send_what);
 
-static void 
-send_info(int neighonly);
+static void ipc_action(int);
 
-static void
-ipc_action(int);
+static void ipc_print_neigh(void);
 
-static void
-ipc_print_neigh_link(void);
+static void ipc_print_link(void);
 
-static void
-ipc_print_routes(void);
+static void ipc_print_routes(void);
 
-static void
-ipc_print_topology(void);
+static void ipc_print_topology(void);
 
-static void
-ipc_print_hna(void);
+static void ipc_print_hna(void);
 
-static void
-ipc_print_mid(void);
+static void ipc_print_mid(void);
 
 #define TXT_IPC_BUFSIZE 256
-static int 
-ipc_sendf(const char* format, ...) __attribute__((format(printf, 1, 2)));
+
+#define SIW_ALL 0
+#define SIW_NEIGH 1
+#define SIW_LINK 2
+#define SIW_ROUTE 3
+#define SIW_HNA 4
+#define SIW_MID 5
+#define SIW_TOPO 6
+#define SIW_NEIGHLINK 7
+
+static int ipc_sendf(const char* format, ...) __attribute__((format(printf, 1, 2)));
 
 /**
  *Do initialization here
@@ -129,23 +133,22 @@ ipc_sendf(const char* format, ...) __attribute__((format(printf, 1, 2)));
 int
 olsrd_plugin_init(void)
 {
-  /* Initial IPC value */
-  ipc_open = 0;
-  ipc_socket_up = 0;
+    /* Initial IPC value */
+    ipc_open = 0;
+    ipc_socket_up = 0;
 
-  plugin_ipc_init();
-  return 1;
+    plugin_ipc_init();
+    return 1;
 }
 
 
 /**
  * destructor - called at unload
  */
-void
-olsr_plugin_exit(void)
+void olsr_plugin_exit(void)
 {
-  if(ipc_open)
-    close(ipc_socket);
+    if(ipc_open)
+        close(ipc_socket);
 }
 
 
@@ -153,346 +156,323 @@ olsr_plugin_exit(void)
 static int
 plugin_ipc_init(void)
 {
-  struct sockaddr_in sin;
-  olsr_u32_t yes = 1;
-
-  /* Init ipc socket */
-  if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
-    {
+    struct sockaddr_storage sst;
+    struct sockaddr_in *sin;
+    struct sockaddr_in6 *sin6;
+    olsr_u32_t yes = 1;
+    socklen_t addrlen;
+
+    /* Init ipc socket */
+    if ((ipc_socket = socket(olsr_cnf->ip_version, SOCK_STREAM, 0)) == -1) {
 #ifndef NODEBUG
-      olsr_printf(1, "(TXTINFO) socket()=%s\n", strerror(errno));
+        olsr_printf(1, "(TXTINFO) socket()=%s\n", strerror(errno));
 #endif
-      return 0;
-    }
-  else
-    {
-      if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) 
-      {
+        return 0;
+    } else {
+        if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
 #ifndef NODEBUG
-       olsr_printf(1, "(TXTINFO) setsockopt()=%s\n", strerror(errno));
+            olsr_printf(1, "(TXTINFO) setsockopt()=%s\n", strerror(errno));
 #endif
-       return 0;
-      }
+            return 0;
+        }
 
 #if defined __FreeBSD__ && defined SO_NOSIGPIPE
-      if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) 
-      {
-       perror("SO_REUSEADDR failed");
-       return 0;
-      }
+        if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) {
+            perror("SO_REUSEADDR failed");
+            return 0;
+        }
 #endif
-
-      /* Bind the socket */
-      
-      /* complete the socket structure */
-      memset(&sin, 0, sizeof(sin));
-      sin.sin_family = AF_INET;
-      sin.sin_addr.s_addr = INADDR_ANY;
-      sin.sin_port = htons(ipc_port);
+        /* Bind the socket */
+
+        /* complete the socket structure */
+        memset(&sst, 0, sizeof(sst));
+        if (olsr_cnf->ip_version == AF_INET) {
+           sin = (struct sockaddr_in *)&sst;
+           sin->sin_family = AF_INET;
+           addrlen = sizeof(struct sockaddr_in);
+#ifdef SIN6_LEN
+           sin->sin_len = addrlen;
+#endif
+           sin->sin_addr.s_addr = INADDR_ANY;
+           sin->sin_port = htons(ipc_port);
+        } else {
+           sin6 = (struct sockaddr_in6 *)&sst;
+           sin6->sin6_family = AF_INET6;
+           addrlen = sizeof(struct sockaddr_in6);
+#ifdef SIN6_LEN
+           sin6->sin6_len = addrlen;
+#endif
+           sin6->sin6_addr = in6addr_any;
+           sin6->sin6_port = htons(ipc_port);
+        }
       
-      /* bind the socket to the port number */
-      if (bind(ipc_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
-       {
+        /* bind the socket to the port number */
+        if (bind(ipc_socket, (struct sockaddr *) &sst, addrlen) == -1) {
 #ifndef NODEBUG
-         olsr_printf(1, "(TXTINFO) bind()=%s\n", strerror(errno));
+            olsr_printf(1, "(TXTINFO) bind()=%s\n", strerror(errno));
 #endif
-         return 0;
-       }
-      
-      /* show that we are willing to listen */
-      if (listen(ipc_socket, 1) == -1) 
-       {
+            return 0;
+        }
+
+        /* show that we are willing to listen */
+        if (listen(ipc_socket, 1) == -1) {
 #ifndef NODEBUG
-         olsr_printf(1, "(TXTINFO) listen()=%s\n", strerror(errno));
+            olsr_printf(1, "(TXTINFO) listen()=%s\n", strerror(errno));
 #endif
-         return 0;
-       }
-       
-      /* Register with olsrd */
-      add_olsr_socket(ipc_socket, &ipc_action);
+            return 0;
+        }
 
+        /* Register with olsrd */
+        add_olsr_socket(ipc_socket, &ipc_action);
+        
 #ifndef NODEBUG
-      olsr_printf(2, "(TXTINFO) listening on port %d\n",ipc_port);
+        olsr_printf(2, "(TXTINFO) listening on port %d\n",ipc_port);
 #endif
-      ipc_socket_up = 1;
+        ipc_socket_up = 1;
     }
-
-  return 1;
+    return 1;
 }
 
 
-static void
-ipc_action(int fd)
+static void ipc_action(int fd)
 {
-  struct sockaddr_in pin;
-  socklen_t addrlen;
-  char *addr;  
+    struct sockaddr_storage pin;
+    struct sockaddr_in *sin4;
+    struct sockaddr_in6 *sin6;
+    char addr[INET6_ADDRSTRLEN];
+    fd_set rfds;
+    struct timeval tv;
+    int send_what = 0;
 
-  addrlen = sizeof(struct sockaddr_in);
+    socklen_t addrlen = sizeof(struct sockaddr_storage);
 
-  if(ipc_open)
-    return;
+    if(ipc_open)
+        return;
 
-  if ((ipc_connection = accept(fd, (struct sockaddr *)  &pin, &addrlen)) == -1)
-    {
+    if ((ipc_connection = accept(fd, (struct sockaddr *)  &pin, &addrlen)) == -1) {
 #ifndef NODEBUG
-      olsr_printf(1, "(TXTINFO) accept()=%s\n", strerror(errno));
+        olsr_printf(1, "(TXTINFO) accept()=%s\n", strerror(errno));
 #endif
-      exit(1);
+        return;
     }
-  else
-    {
-      fd_set rfds;
-      struct timeval tv = {0,0};
-      int neighonly = 0;
-
-      addr = inet_ntoa(pin.sin_addr);
-      if(ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.s_addr))
-       {
-         olsr_printf(1, "(TXTINFO) From host(%s) not allowed!\n", addr);
-         close(ipc_connection);
-         return;
-       }
-      else
-       {
-      ipc_open = 1;
+
+    tv.tv_sec = tv.tv_usec = 0;
+    if (olsr_cnf->ip_version == AF_INET) {
+        sin4 = (struct sockaddr_in *)&pin;
+        if (inet_ntop(olsr_cnf->ip_version, &sin4->sin_addr, addr,
+           INET6_ADDRSTRLEN) == NULL)
+             addr[0] = '\0';
+        if (!ip4equal(&sin4->sin_addr, &ipc_accept_ip.v4)) {
+            olsr_printf(1, "(TXTINFO) From host(%s) not allowed!\n", addr);
+            close(ipc_connection);
+            return;
+        }
+    } else {
+        sin6 = (struct sockaddr_in6 *)&pin;
+        if (inet_ntop(olsr_cnf->ip_version, &sin6->sin6_addr, addr,
+           INET6_ADDRSTRLEN) == NULL)
+             addr[0] = '\0';
+       /* Use in6addr_any (::) in olsr.conf to allow anybody. */
+        if (!ip6equal(&in6addr_any, &ipc_accept_ip.v6) &&
+           !ip6equal(&sin6->sin6_addr, &ipc_accept_ip.v6)) {
+            olsr_printf(1, "(TXTINFO) From host(%s) not allowed!\n", addr);
+            close(ipc_connection);
+            return;
+        }
+    }
+    ipc_open = 1;
 #ifndef NODEBUG
-      olsr_printf(2, "(TXTINFO) Connect from %s\n",addr);
+    olsr_printf(2, "(TXTINFO) Connect from %s\n",addr);
 #endif
       
-      /* purge read buffer to prevent blocking on linux*/
-      FD_ZERO(&rfds);
-      FD_SET(ipc_connection, &rfds);
-      if(select(ipc_connection+1, &rfds, NULL, NULL, &tv)) {
+    /* purge read buffer to prevent blocking on linux*/
+    FD_ZERO(&rfds);
+    FD_SET((unsigned int)ipc_connection, &rfds); /* Win32 needs the cast here */
+    if(0 <= select(ipc_connection+1, &rfds, NULL, NULL, &tv)) {
         char requ[128];
-        ssize_t s = recv(ipc_connection, &requ, sizeof(requ), 0);
+        ssize_t s = recv(ipc_connection, (void*)&requ, sizeof(requ), 0); /* Win32 needs the cast here */
         if (0 < s) {
-          requ[s] = 0;
-          /* To print out neighbours only on the Freifunk Status
-           * page the normal output is somewhat lengthy. The
-           * header parsing is sufficient for standard wget.
-           */
-          neighonly = (0 != strstr(requ, "/neighbours"));
+            requ[s] = 0;
+            /* To print out neighbours only on the Freifunk Status
+             * page the normal output is somewhat lengthy. The
+             * header parsing is sufficient for standard wget.
+             */
+            if (0 != strstr(requ, "/neighbours")) send_what=SIW_NEIGHLINK;
+            else if (0 != strstr(requ, "/neigh")) send_what=SIW_NEIGH;
+            else if (0 != strstr(requ, "/link")) send_what=SIW_LINK;
+            else if (0 != strstr(requ, "/route")) send_what=SIW_ROUTE;
+            else if (0 != strstr(requ, "/hna")) send_what=SIW_HNA;
+            else if (0 != strstr(requ, "/mid")) send_what=SIW_MID;
+            else if (0 != strstr(requ, "/topo")) send_what=SIW_TOPO;
         }
-      }
+    }
 
-      send_info(neighonly);
+       send_info(send_what);
          
-      close(ipc_connection);
-      ipc_open = 0;
-    }
-  }
+    close(ipc_connection);
+    ipc_open = 0;
 }
 
-static void
-ipc_print_neigh_link(void)
+static void ipc_print_neigh(void)
 {
-  struct neighbor_entry *neigh;
-  struct neighbor_2_list_entry *list_2;
-  struct link_entry *link = NULL;
-  int index, thop_cnt;
-
-       ipc_sendf("Table: Links\nLocal IP\tremote IP\tHysteresis\tLinkQuality\tlost\ttotal\tNLQ\tETX\n");
-
-  /* Link set */
-  link = link_set;
-       while(link)
-       {
-       ipc_sendf( "%s\t%s\t%0.2f\t%0.2f\t%d\t%d\t%0.2f\t%0.2f\t\n",
-                       olsr_ip_to_string(&link->local_iface_addr),
-                       olsr_ip_to_string(&link->neighbor_iface_addr),
-                       link->L_link_quality, 
-                       link->loss_link_quality,
-                       link->lost_packets, 
-                       link->total_packets,
-                       link->neigh_link_quality, 
-                       (link->loss_link_quality * link->neigh_link_quality) ? 1.0 / (link->loss_link_quality * link->neigh_link_quality) : 0.0);
-               link = link->next;
-      }
-       ipc_sendf("\nTable: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWillingness\t2 Hop Neighbors\n");
-
-  /* Neighbors */
-  for(index=0;index<HASHSIZE;index++)
-    {
-      for(neigh = neighbortable[index].next;
-         neigh != &neighbortable[index];
-         neigh = neigh->next)
-       {
-               ipc_sendf( 
-                         "%s\t%s\t%s\t%s\t%d\t", 
-                         olsr_ip_to_string(&neigh->neighbor_main_addr),
-                         (neigh->status == SYM) ? "YES" : "NO",
-                         neigh->is_mpr ? "YES" : "NO",
-                         olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO",
-                         neigh->willingness);
-
-         thop_cnt = 0;
-
-         for(list_2 = neigh->neighbor_2_list.next;
-             list_2 != &neigh->neighbor_2_list;
-             list_2 = list_2->next)
-           {
-             //size += sprintf(&buf[size], "<option>%s</option>\n", olsr_ip_to_string(&list_2->neighbor_2->neighbor_2_addr));
-             thop_cnt ++;
-           }
-               ipc_sendf("%d\n", thop_cnt);
+    struct ipaddr_str buf1;
+    struct neighbor_entry *neigh;
+    struct neighbor_2_list_entry *list_2;
+    int index, thop_cnt;
+
+    ipc_sendf("\nTable: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWillingness\t2 Hop Neighbors\n");
+
+    /* Neighbors */
+    for(index = 0; index < HASHSIZE; index++) {
+        for(neigh = neighbortable[index].next;
+            neigh != &neighbortable[index];
+            neigh = neigh->next) {
+            ipc_sendf("%s\t%s\t%s\t%s\t%d\t", 
+                      olsr_ip_to_string(&buf1, &neigh->neighbor_main_addr),
+                      (neigh->status == SYM) ? "YES" : "NO",
+                      neigh->is_mpr ? "YES" : "NO",
+                      olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO",
+                      neigh->willingness);
+            thop_cnt = 0;
+
+            for(list_2 = neigh->neighbor_2_list.next;
+                list_2 != &neigh->neighbor_2_list;
+                list_2 = list_2->next)
+                {
+                    //size += sprintf(&buf[size], "<option>%s</option>\n", olsr_ip_to_string(&buf1, &list_2->neighbor_2->neighbor_2_addr));
+                    thop_cnt ++;
+                }
+            ipc_sendf("%d\n", thop_cnt);
        }
     }
-
-       ipc_sendf("\n");
+    ipc_sendf("\n");
 }
 
-
-static void
-ipc_print_routes(void)
+static void ipc_print_link(void)
 {
-  int size = 0, index;
-  struct rt_entry *routes;
-
-       ipc_sendf("Table: Routes\nDestination\tGateway\tMetric\tETX\tInterface\tType\n");
-
-  /* Neighbors */
-  for(index = 0;index < HASHSIZE;index++)
-    {
-      for(routes = routingtable[index].next;
-         routes != &routingtable[index];
-         routes = routes->next)
-       {
-               size = 0;
-               ipc_sendf( "%s\t%s\t%d\t%.2f\t%s\tHOST\n",
-                         olsr_ip_to_string(&routes->rt_dst),
-                         olsr_ip_to_string(&routes->rt_router),
-                         routes->rt_metric,
-                         routes->rt_etx,
-                         routes->rt_if->int_name);
-       }
-    }
+    struct ipaddr_str buf1, buf2;
+    struct link_entry *link = NULL;
+
+    ipc_sendf("Table: Links\nLocal IP\tremote IP\tHysteresis\tLinkQuality\tlost\ttotal\tNLQ\tETX\n");
+
+    /* Link set */
+    OLSR_FOR_ALL_LINK_ENTRIES(link) {
+       ipc_sendf( "%s\t%s\t%s\t%s\t%d\t%d\t%s\t%s\t\n",
+                   olsr_ip_to_string(&buf1, &link->local_iface_addr),
+                   olsr_ip_to_string(&buf2, &link->neighbor_iface_addr),
+                   fpmtoa(link->L_link_quality), 
+                   fpmtoa(link->loss_link_quality),
+                   link->lost_packets, 
+                   link->total_packets,
+                   fpmtoa(link->neigh_link_quality), 
+                   etxtoa(olsr_calc_link_etx(link)));
+    } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+
+    ipc_sendf("\n");
+}
 
-  /* HNA */
-  for(index = 0;index < HASHSIZE;index++)
-    {
-      for(routes = hna_routes[index].next;
-         routes != &hna_routes[index];
-         routes = routes->next)
-       {
-               ipc_sendf("%s\t%s\t%d\t%s\t\tHNA\n",
-                         olsr_ip_to_string(&routes->rt_dst),
-                         olsr_ip_to_string(&routes->rt_router),
-                         routes->rt_metric,
-                         routes->rt_if->int_name);
-       }
+static void ipc_print_routes(void)
+{
+    struct ipaddr_str buf1, buf2;
+    struct rt_entry *rt;
+    struct avl_node *rt_tree_node;
+
+    ipc_sendf("Table: Routes\nDestination\tGateway\tMetric\tETX\tInterface\n");
+
+    /* Walk the route table */
+    for (rt_tree_node = avl_walk_first(&routingtree);
+         rt_tree_node;
+         rt_tree_node = avl_walk_next(rt_tree_node)) {
+
+        rt = rt_tree_node->data;
+
+        ipc_sendf( "%s/%d\t%s\t%d\t%s\t%s\t\n",
+                   olsr_ip_to_string(&buf1, &rt->rt_dst.prefix),
+                   rt->rt_dst.prefix_len,
+                   olsr_ip_to_string(&buf2, &rt->rt_best->rtp_nexthop.gateway),
+                   rt->rt_best->rtp_metric.hops,
+                   etxtoa(rt->rt_best->rtp_metric.etx),
+                   if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
     }
-
-       ipc_sendf("\n");
+    ipc_sendf("\n");
 
 }
 
-static void
-ipc_print_topology(void)
+static void ipc_print_topology(void)
 {
-  olsr_u8_t index;
-  struct tc_entry *entry;
-  struct topo_dst *dst_entry;
-
-
-  ipc_sendf("Table: Topology\nDestination IP\tLast hop IP\tLQ\tILQ\tETX\n");
-
-  /* Topology */  
-  for(index=0;index<HASHSIZE;index++)
-    {
-      /* For all TC entries */
-      entry = tc_table[index].next;
-      while(entry != &tc_table[index])
-       {
-         /* For all destination entries of that TC entry */
-         dst_entry = entry->destinations.next;
-         while(dst_entry != &entry->destinations)
-           {
-                       ipc_sendf( "%s\t%s\t%0.2f\t%0.2f\t%0.2f\n", 
-                             olsr_ip_to_string(&dst_entry->T_dest_addr),
-                             olsr_ip_to_string(&entry->T_last_addr), 
-                             dst_entry->link_quality,
-                             dst_entry->inverse_link_quality,
-                             (dst_entry->link_quality * dst_entry->inverse_link_quality) ? 1.0 / (dst_entry->link_quality * dst_entry->inverse_link_quality) : 0.0);
-               
-             dst_entry = dst_entry->next;
-           }
-         entry = entry->next;
-       }
-    }
-
-  ipc_sendf("\n");
+    struct tc_entry *tc;
+    
+    ipc_sendf("Table: Topology\nDestination IP\tLast hop IP\tLQ\tILQ\tETX\n");
+
+    /* Topology */  
+    OLSR_FOR_ALL_TC_ENTRIES(tc) {
+        struct tc_edge_entry *tc_edge;
+        OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
+            struct ipaddr_str dstbuf, addrbuf;
+            ipc_sendf( "%s\t%s\t%s\t%s\t%s\n", 
+                       olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr),
+                       olsr_ip_to_string(&addrbuf, &tc->addr), 
+                       fpmtoa(tc_edge->link_quality),
+                       fpmtoa(tc_edge->inverse_link_quality),
+                       etxtoa(olsr_calc_tc_etx(tc_edge)));
+
+        } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+    } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
+
+    ipc_sendf("\n");
 }
 
-static void
-ipc_print_hna(void)
+static void ipc_print_hna(void)
 {
-  int size;
-  olsr_u8_t index;
-  struct hna_entry *tmp_hna;
-  struct hna_net *tmp_net;
-  struct hna4_entry *hna4;
-  struct hna6_entry *hna6;
-
-  size = 0;
-
-  ipc_sendf("Table: HNA\nNetwork\tNetmask\tGateway\n");
-
-  /* Announced HNA entries */
-       for(hna4 = olsr_cnf->hna4_entries; hna4; hna4 = hna4->next)
-         {
-                       ipc_sendf("%s\t%s\t%s\n",
-                         olsr_ip_to_string(&hna4->net),
-                         olsr_ip_to_string(&hna4->netmask),
-                               olsr_ip_to_string(&olsr_cnf->main_addr));
-         }
-       for(hna6 = olsr_cnf->hna6_entries; hna6; hna6 = hna6->next)
-         {
-                       ipc_sendf("%s\t%d\t%s\n",
-                         olsr_ip_to_string(&hna6->net),
-                               hna6->prefix_len,
-                       olsr_ip_to_string(&olsr_cnf->main_addr));
-               }
-
-  /* HNA entries */
-  for(index=0;index<HASHSIZE;index++)
-    {
-      tmp_hna = hna_set[index].next;
-      /* Check all entrys */
-      while(tmp_hna != &hna_set[index])
-       {
-         /* Check all networks */
-         tmp_net = tmp_hna->networks.next;
-             
-         while(tmp_net != &tmp_hna->networks)
-           {
-               if (AF_INET == olsr_cnf->ip_version) {
-                       ipc_sendf("%s\t%s\t%s\n",
-                               olsr_ip_to_string(&tmp_net->A_network_addr),
-                               olsr_ip_to_string((union olsr_ip_addr *)&tmp_net->A_netmask.v4),
-                               olsr_ip_to_string(&tmp_hna->A_gateway_addr));
-               }
-               else {
-                       ipc_sendf("%s\t%d\t%s\n",
-                               olsr_ip_to_string(&tmp_net->A_network_addr),
-                               tmp_net->A_netmask.v6,
-                               olsr_ip_to_string(&tmp_hna->A_gateway_addr));
-               }
-             tmp_net = tmp_net->next;
-           }
-             
-         tmp_hna = tmp_hna->next;
-       }
+    int size;
+    int index;
+    struct ip_prefix_list *hna;
+
+    size = 0;
+
+    ipc_sendf("Table: HNA\nNetwork\tNetmask\tGateway\n");
+
+    /* Announced HNA entries */
+    if (olsr_cnf->ip_version == AF_INET) {
+        for(hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
+            struct ipaddr_str addrbuf, mainaddrbuf;
+            ipc_sendf("%s\t%d\t%s\n",
+                      olsr_ip_to_string(&addrbuf, &hna->net.prefix),
+                      hna->net.prefix_len,
+                      olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
+        }
+    } else {
+        for(hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
+            struct ipaddr_str addrbuf, mainaddrbuf;
+            ipc_sendf("%s\t%d\t%s\n",
+                      olsr_ip_to_string(&addrbuf, &hna->net.prefix),
+                      hna->net.prefix_len,
+                      olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
+        }
     }
 
-       ipc_sendf("\n");
-
+    /* HNA entries */
+    for(index = 0; index < HASHSIZE; index++) {
+        struct hna_entry *tmp_hna;
+        /* Check all entrys */
+        for (tmp_hna = hna_set[index].next; tmp_hna != &hna_set[index]; tmp_hna = tmp_hna->next) {
+            /* Check all networks */
+            struct hna_net *tmp_net;
+            for (tmp_net = tmp_hna->networks.next; tmp_net != &tmp_hna->networks; tmp_net = tmp_net->next) {
+                struct ipaddr_str addrbuf, mainaddrbuf;
+                ipc_sendf("%s\t%d\t%s\n",
+                          olsr_ip_to_string(&addrbuf, &tmp_net->A_network_addr),
+                          tmp_net->prefixlen,
+                          olsr_ip_to_string(&mainaddrbuf, &tmp_hna->A_gateway_addr));
+            }
+       }
+    }
+    ipc_sendf("\n");
 }
 
-static void
-ipc_print_mid(void)
+static void ipc_print_mid(void)
 {
-    olsr_u8_t index;
+    int index;
     unsigned short is_first;
     struct mid_entry *entry;
     struct mid_address *alias;
@@ -500,60 +480,56 @@ ipc_print_mid(void)
     ipc_sendf("Table: MID\nIP\tAliases\n");
 
     /* MID */
-    for( index = 0; index < HASHSIZE; index++ )
-    {
+    for(index = 0; index < HASHSIZE; index++) {
         entry = mid_set[index].next;
-
-        while( entry != &mid_set[index] )
-        {
-            ipc_sendf( olsr_ip_to_string( &entry->main_addr ) );
+        
+        while( entry != &mid_set[index] ) {
+            struct ipaddr_str buf;
+            ipc_sendf( olsr_ip_to_string(&buf,  &entry->main_addr ) );
             alias = entry->aliases;
             is_first = 1;
 
-            while( alias )
-            {
+            while( alias ) {
                 ipc_sendf( "%s%s",
-                    ( is_first ? "\t" : ";" ),
-                    olsr_ip_to_string( &alias->alias )
-                );
+                           ( is_first ? "\t" : ";" ),
+                           olsr_ip_to_string(&buf,  &alias->alias )
+                           );
 
                 alias = alias->next_alias;
                 is_first = 0;
             }
-
             entry = entry->next;
             ipc_sendf("\n");
         }
     }
-
-       ipc_sendf("\n");
+    ipc_sendf("\n");
 }
 
 
-static void 
-send_info(int neighonly)
+static void  send_info(int send_what)
 {
-       
-       /* Print minimal http header */
-       ipc_sendf("HTTP/1.0 200 OK\n");
-       ipc_sendf("Content-type: text/plain\n\n");
+    /* Print minimal http header */
+    ipc_sendf("HTTP/1.0 200 OK\n");
+    ipc_sendf("Content-type: text/plain\n\n");
 
-       /* Print tables to IPC socket */
+    /* Print tables to IPC socket */
        
-       /* links + Neighbors */
-       ipc_print_neigh_link();
+    /* links + Neighbors */
+    if ((send_what==SIW_ALL)||(send_what==SIW_NEIGHLINK)||(send_what==SIW_LINK)) ipc_print_link();
+
+    if ((send_what==SIW_ALL)||(send_what==SIW_NEIGHLINK)||(send_what==SIW_NEIGH)) ipc_print_neigh();
        
-       /* topology */
-       if (!neighonly) ipc_print_topology();
+    /* topology */
+    if ((send_what==SIW_ALL)||(send_what==SIW_TOPO)) ipc_print_topology();
        
-       /* hna */
-       if (!neighonly) ipc_print_hna();
+    /* hna */
+    if ((send_what==SIW_ALL)||(send_what==SIW_HNA)) ipc_print_hna();
 
-       /* mid */
-       if (!neighonly) ipc_print_mid();
+    /* mid */
+    if ((send_what==SIW_ALL)||(send_what==SIW_MID)) ipc_print_mid();
 
-       /* routes */
-       if (!neighonly) ipc_print_routes();
+    /* routes */
+    if ((send_what==SIW_ALL)||(send_what==SIW_ROUTE)) ipc_print_routes();
 }
 
 /*
@@ -563,29 +539,37 @@ send_info(int neighonly)
  * scalable solution here.
  */
  
-static int 
-ipc_sendf(const char* format, ...)
+static int  ipc_sendf(const char* format, ...)
 {
-       char txtnetbuf[TXT_IPC_BUFSIZE];
+    char txtnetbuf[TXT_IPC_BUFSIZE];
 
-       va_list arg;
-       int rv;
+    va_list arg;
+    int rv;
 #if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __MacOSX__
-       int flags = 0;
+    int flags = 0;
 #else
-       int flags = MSG_NOSIGNAL;
+    int flags = MSG_NOSIGNAL;
 #endif
-       va_start(arg, format);
-       rv = vsnprintf(txtnetbuf, sizeof(txtnetbuf), format, arg);
-       va_end(arg);
-       if(ipc_socket_up) {
-               if (0 > send(ipc_connection, txtnetbuf, rv, flags)) {
+    va_start(arg, format);
+    rv = vsnprintf(txtnetbuf, sizeof(txtnetbuf), format, arg);
+    va_end(arg);
+    if(ipc_socket_up) {
+        if (0 > send(ipc_connection, txtnetbuf, rv, flags)) {
 #ifndef NODEBUG
-                       olsr_printf(1, "(TXTINFO) Failed sending data to client!\n");
+            olsr_printf(1, "(TXTINFO) Failed sending data to client!\n");
 #endif
-                       close(ipc_connection);
-                       return - 1;
-               }
-       }
-       return rv;
+            close(ipc_connection);
+            return - 1;
+        }
+    }
+    return rv;
 }
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */