reserve merge conflicts from latest sf.net pull
[olsrd.git] / lib / txtinfo / src / olsrd_txtinfo.c
index a8582eb..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.7 2007/07/15 19:29:37 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"
@@ -94,11 +95,13 @@ static int ipc_socket_up;
 /* IPC initialization function */
 static int plugin_ipc_init(void);
 
-static void  send_info(int neighonly);
+static void send_info(int send_what);
 
 static void ipc_action(int);
 
-static void ipc_print_neigh_link(void);
+static void ipc_print_neigh(void);
+
+static void ipc_print_link(void);
 
 static void ipc_print_routes(void);
 
@@ -109,6 +112,16 @@ static void ipc_print_hna(void);
 static void ipc_print_mid(void);
 
 #define TXT_IPC_BUFSIZE 256
+
+#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)));
 
 /**
@@ -143,11 +156,14 @@ void olsr_plugin_exit(void)
 static int
 plugin_ipc_init(void)
 {
-    struct sockaddr_in sin;
+    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(AF_INET, SOCK_STREAM, 0)) == -1) {
+    if ((ipc_socket = socket(olsr_cnf->ip_version, SOCK_STREAM, 0)) == -1) {
 #ifndef NODEBUG
         olsr_printf(1, "(TXTINFO) socket()=%s\n", strerror(errno));
 #endif
@@ -169,13 +185,29 @@ plugin_ipc_init(void)
         /* 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);
+        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) {
+        if (bind(ipc_socket, (struct sockaddr *) &sst, addrlen) == -1) {
 #ifndef NODEBUG
             olsr_printf(1, "(TXTINFO) bind()=%s\n", strerror(errno));
 #endif
@@ -204,13 +236,15 @@ plugin_ipc_init(void)
 
 static void ipc_action(int fd)
 {
-    struct sockaddr_in pin;
-    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 neighonly = 0;
+    int send_what = 0;
 
-    socklen_t addrlen = sizeof(struct sockaddr_in);
+    socklen_t addrlen = sizeof(struct sockaddr_storage);
 
     if(ipc_open)
         return;
@@ -223,11 +257,28 @@ static void ipc_action(int fd)
     }
 
     tv.tv_sec = tv.tv_usec = 0;
-    addr = inet_ntoa(pin.sin_addr);
-    if (ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.v4)) {
-        olsr_printf(1, "(TXTINFO) From host(%s) not allowed!\n", addr);
-        close(ipc_connection);
-        return;
+    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
@@ -237,7 +288,7 @@ static void ipc_action(int fd)
     /* purge read buffer to prevent blocking on linux*/
     FD_ZERO(&rfds);
     FD_SET((unsigned int)ipc_connection, &rfds); /* Win32 needs the cast here */
-    if(select(ipc_connection+1, &rfds, NULL, NULL, &tv)) {
+    if(0 <= select(ipc_connection+1, &rfds, NULL, NULL, &tv)) {
         char requ[128];
         ssize_t s = recv(ipc_connection, (void*)&requ, sizeof(requ), 0); /* Win32 needs the cast here */
         if (0 < s) {
@@ -246,39 +297,29 @@ static void ipc_action(int fd)
              * page the normal output is somewhat lengthy. The
              * header parsing is sufficient for standard wget.
              */
-            neighonly = (0 != strstr(requ, "/neighbours"));
+            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;
 }
 
-static void ipc_print_neigh_link(void)
+static void ipc_print_neigh(void)
 {
+    struct ipaddr_str buf1;
     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 */
@@ -287,7 +328,7 @@ static void ipc_print_neigh_link(void)
             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),
+                      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",
@@ -298,7 +339,7 @@ static void ipc_print_neigh_link(void)
                 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));
+                    //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);
@@ -307,39 +348,51 @@ static void ipc_print_neigh_link(void)
     ipc_sendf("\n");
 }
 
-static void ipc_print_routes(void)
+static void ipc_print_link(void)
 {
-    int size = 0, index;
-    struct rt_entry *routes;
+    struct ipaddr_str buf1, buf2;
+    struct link_entry *link = NULL;
 
-    ipc_sendf("Table: Routes\nDestination\tGateway\tMetric\tETX\tInterface\tType\n");
+    ipc_sendf("Table: Links\nLocal IP\tremote IP\tHysteresis\tLinkQuality\tlost\ttotal\tNLQ\tETX\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);
-       }
-    }
+    /* 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);
 
-    /* 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);
-       }
+    ipc_sendf("\n");
+}
+
+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");
 
@@ -347,90 +400,74 @@ static void ipc_print_routes(void)
 
 static void ipc_print_topology(void)
 {
-    int index;
-    struct tc_entry *entry;
-    struct topo_dst *dst_entry;
-
+    struct tc_entry *tc;
+    
     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;
-       }
-    }
+    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)
 {
     int size;
-    olsr_u8_t index;
-    struct hna_entry *tmp_hna;
-    struct hna_net *tmp_net;
-    struct hna4_entry *hna4;
-    struct hna6_entry *hna6;
+    int index;
+    struct ip_prefix_list *hna;
 
     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));
+    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));
+        }
     }
 
     /* HNA entries */
     for(index = 0; index < HASHSIZE; index++) {
-        tmp_hna = hna_set[index].next;
+        struct hna_entry *tmp_hna;
         /* Check all entrys */
-        while(tmp_hna != &hna_set[index]) {
+        for (tmp_hna = hna_set[index].next; tmp_hna != &hna_set[index]; tmp_hna = tmp_hna->next) {
             /* 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;
+            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)
@@ -447,14 +484,15 @@ static void ipc_print_mid(void)
         entry = mid_set[index].next;
         
         while( entry != &mid_set[index] ) {
-            ipc_sendf( olsr_ip_to_string( &entry->main_addr ) );
+            struct ipaddr_str buf;
+            ipc_sendf( olsr_ip_to_string(&buf,  &entry->main_addr ) );
             alias = entry->aliases;
             is_first = 1;
 
             while( alias ) {
                 ipc_sendf( "%s%s",
                            ( is_first ? "\t" : ";" ),
-                           olsr_ip_to_string( &alias->alias )
+                           olsr_ip_to_string(&buf,  &alias->alias )
                            );
 
                 alias = alias->next_alias;
@@ -468,7 +506,7 @@ static void ipc_print_mid(void)
 }
 
 
-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");
@@ -477,19 +515,21 @@ static void  send_info(int neighonly)
     /* Print tables to IPC socket */
        
     /* links + Neighbors */
-    ipc_print_neigh_link();
+    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();
+    if ((send_what==SIW_ALL)||(send_what==SIW_TOPO)) ipc_print_topology();
        
     /* hna */
-    if (!neighonly) ipc_print_hna();
+    if ((send_what==SIW_ALL)||(send_what==SIW_HNA)) ipc_print_hna();
 
     /* mid */
-    if (!neighonly) ipc_print_mid();
+    if ((send_what==SIW_ALL)||(send_what==SIW_MID)) ipc_print_mid();
 
     /* routes */
-    if (!neighonly) ipc_print_routes();
+    if ((send_what==SIW_ALL)||(send_what==SIW_ROUTE)) ipc_print_routes();
 }
 
 /*