Factor out the buffer code and use it elsewhere
authorBernd Petrovitsch <bernd@firmix.at>
Sun, 9 Nov 2008 23:48:19 +0000 (00:48 +0100)
committerBernd Petrovitsch <bernd@firmix.at>
Sun, 9 Nov 2008 23:48:19 +0000 (00:48 +0100)
We factor out the code of the auto-expanding buffer from the txtinfo plugin
into the core (and a few functions ....).
We use that for the config-file generation and while we are at it,
we clean it up.
And we use it in the httpinfo plugin.
This saves a few KB in the olsrd, httpinfo and txtinfo plugin.

lib/httpinfo/src/admin_interface.c
lib/httpinfo/src/admin_interface.h
lib/httpinfo/src/olsrd_httpinfo.c
lib/httpinfo/src/olsrd_httpinfo.h
lib/txtinfo/src/olsrd_txtinfo.c
src/cfgparser/cfgfile_gen.c
src/common/autobuf.c [new file with mode: 0644]
src/common/autobuf.h [new file with mode: 0644]
src/olsr_cfg.h
src/unix/ifnet.c

index 68d4232..c506923 100644 (file)
@@ -63,67 +63,66 @@ static const char admin_basic_setting_float[] = "<td><strong>%s</strong></td><td
 static const char admin_basic_setting_string[] = "<td><strong>%s</strong></td><td><input type=\"text\" name=\"%s\" maxlength=\"%d\" class=\"input_text\" value=\"%s\"></td>\n";
 
 
-int
-build_admin_body(char *buf, olsr_u32_t bufsize __attribute__((unused)))
+void
+build_admin_body(struct autobuf *abuf)
 {
-  int size = 0;
-  size += snprintf(&buf[size], bufsize-size,
+  abuf_puts(abuf,
                   "<strong>Administrator interface</strong><hr>\n"
                   "<h2>Change basic settings</h2>\n"
                   "<form action=\"set_values\" method=\"post\">\n"
                   "<table width=\"100%%\">\n");
 
-  size += snprintf(&buf[size], bufsize-size, "<tr>\n");
+  abuf_puts(abuf, "<tr>\n");
 
-  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_int,
+  abuf_appendf(abuf, admin_basic_setting_int,
                  "Debug level:", "debug_level", 2, olsr_cnf->debug_level);
-  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_float,
+  abuf_appendf(abuf, admin_basic_setting_float,
                   "Pollrate:", "pollrate", 4, conv_pollrate_to_secs(olsr_cnf->pollrate));
-  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_string,
+  abuf_appendf(abuf, admin_basic_setting_string,
                  "TOS:", "tos", 6, "TBD");
 
-  size += snprintf(&buf[size], bufsize-size, "</tr>\n"
+  abuf_puts(abuf, "</tr>\n"
                                              "<tr>\n");
 
-  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_int,
+  abuf_appendf(abuf, admin_basic_setting_int,
                  "TC redundancy:", "tc_redundancy", 1, olsr_cnf->tc_redundancy);
-  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_int,
+  abuf_appendf(abuf, admin_basic_setting_int,
                  "MPR coverage:", "mpr_coverage", 1, olsr_cnf->mpr_coverage);
-  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_int,
+  abuf_appendf(abuf, admin_basic_setting_int,
                  "Willingness:", "willingness", 1, olsr_cnf->willingness);
 
-  size += snprintf(&buf[size], bufsize-size, "</tr>\n"
+  abuf_puts(abuf, "</tr>\n"
                                              "<tr>\n");
 
   if(olsr_cnf->use_hysteresis) {
-    size += snprintf(&buf[size], bufsize-size, admin_basic_setting_float,
+    abuf_appendf(abuf, admin_basic_setting_float,
                      "Hyst scaling:", "hyst_scaling", 4, olsr_cnf->hysteresis_param.scaling);
 
-    size += snprintf(&buf[size], bufsize-size, admin_basic_setting_float,
+    abuf_appendf(abuf, admin_basic_setting_float,
                      "Lower thr:", "hyst_lower", 4, olsr_cnf->hysteresis_param.thr_low);
-    size += snprintf(&buf[size], bufsize-size, admin_basic_setting_float,
+    abuf_appendf(abuf, admin_basic_setting_float,
                      "Upper thr:", "hyst_upper", 4, olsr_cnf->hysteresis_param.thr_high);
   } else {
-    size += snprintf(&buf[size], bufsize-size, "<td>Hysteresis disabled</td>\n");
+    abuf_puts(abuf, "<td>Hysteresis disabled</td>\n");
   }
 
-  size += snprintf(&buf[size], bufsize-size, "</tr>\n"
+  abuf_puts(abuf, "</tr>\n"
                                              "<tr>\n");
   
   if(olsr_cnf->lq_level) {
-    size += snprintf(&buf[size], bufsize-size, admin_basic_setting_int,
+    abuf_appendf(abuf, admin_basic_setting_int,
                      "LQ level:", "lq_level", 1, olsr_cnf->lq_level);
-    size += snprintf(&buf[size], bufsize-size, admin_basic_setting_float,
+    abuf_appendf(abuf, admin_basic_setting_float,
                      "LQ aging:", "lq_aging", 2, olsr_cnf->lq_aging);
   } else {
-    size += snprintf(&buf[size], bufsize-size, "<td>LQ disabled</td>\n");
+    abuf_puts(abuf, "<td>LQ disabled</td>\n");
   }
 
-  size += snprintf(&buf[size], bufsize-size, "</tr>\n"
+  abuf_puts(abuf, "</tr>\n"
                                              "<tr>\n");
-  size += snprintf(&buf[size], bufsize-size, "</tr>\n");
+  abuf_puts(abuf, "</tr>\n");
   
-  size += snprintf(&buf[size], bufsize-size
+  abuf_puts(abuf
                   "</table>\n<br>\n"
                   "<center><input type=\"submit\" value=\"Submit\" class=\"input_button\">\n"
                   "<input type=\"reset\" value=\"Reset\" class=\"input_button\"></center>\n"
@@ -145,7 +144,7 @@ build_admin_body(char *buf, olsr_u32_t bufsize __attribute__((unused)))
     for(hna = olsr_cnf->hna_entries; hna; hna = hna->next) {
       struct ipaddr_str netbuf;
       olsr_ip_to_string(&netbuf, &hna->net.prefix);
-      size += snprintf(&buf[size], bufsize-size,
+      abuf_appendf(abuf,
                        "<tr><td halign=\"middle\"><input type=\"checkbox\" name=\"del_hna%s*%d\" class=\"input_checkbox\"></td><td>%s</td><td>%d</td></tr>\n",
                        netbuf.buf,
                        hna->net.prefix_len,
@@ -153,11 +152,10 @@ build_admin_body(char *buf, olsr_u32_t bufsize __attribute__((unused)))
                        hna->net.prefix_len);
     }
   }
-  size += snprintf(&buf[size], bufsize-size,
+  abuf_puts(abuf,
                   "</table>\n<br>\n"
                   "<center><input type=\"submit\" value=\"Delete selected\" class=\"input_button\"></center>\n"
                   "</form>\n");
-  return size;
 }
 
 
@@ -348,49 +346,54 @@ process_param(char *key, char *value)
 }
 
 int
-process_set_values(char *data, olsr_u32_t data_size, char *buf, olsr_u32_t bufsize __attribute__((unused)))
+process_set_values(char *data, olsr_u32_t data_size, struct autobuf *abuf)
 {
-  int size = 0;
-  int val_start, key_start;
+  int val_start = 0, key_start = 0;
   olsr_u32_t i;
 
-  size += sprintf(buf, "<html>\n<head><title>olsr.org httpinfo plugin</title></head>\n<body>\n");
-
-  key_start = 0;
-  val_start = 0;
-
-  for(i = 0; i < data_size; i++)
-    {
-      if(data[i] == '=')
-       {
-         data[i] = '\0';
-         val_start = i + 1;
-       }
-
-      if(data[i] == '&')
-       {
-         data[i] = '\0';
-         if(!process_param(&data[key_start], &data[val_start]))
-           {
-             size += snprintf(&buf[size], bufsize-size, "<h2>FAILED PROCESSING!</h2><br>Key: %s Value: %s<br>\n", 
-                             &data[key_start], &data[val_start]);
-             return -1;
-           }
-
-         key_start = i + 1;
-       }
-    }  
+  abuf_puts(abuf,
+           "<html>\n"
+           "<head><title>olsr.org httpinfo plugin</title></head>\n"
+           "<body>\n");
+
+  for (i = 0; i < data_size; i++) {
+    switch (data[i]) {
+    case '=':
+      data[i] = '\0';
+      val_start = i + 1;
+      break;
+
+    case '&':
+      data[i] = '\0';
+      if (!process_param(&data[key_start], &data[val_start])) {
+       abuf_appendf(abuf,
+                    "<h2>FAILED PROCESSING!</h2><br>Key: %s Value: %s<br>\n", 
+                    &data[key_start], &data[val_start]);
+       return -1;
+      }
 
-  if(!process_param(&data[key_start], &data[val_start]))
-    {
-      size += snprintf(&buf[size], bufsize-size, "<b>FAILED PROCESSING!</b><br>Key: %s Value: %s<br>\n", 
-                     &data[key_start], &data[val_start]);
-      return -1;
+      key_start = i + 1;
+      break;
     }
+  }  
 
-  size += snprintf(&buf[size], bufsize-size, "<h2>UPDATE SUCESSFULL!</h2><br>Press BACK and RELOAD in your browser to return to the plugin<br>\n</body>\n</html>\n");
-  size += snprintf(&buf[size], bufsize-size, "\n</body>\n</html>\n");
+  if (!process_param(&data[key_start], &data[val_start])) {
+    abuf_appendf(abuf,
+                "<b>FAILED PROCESSING!</b><br>Key: %s Value: %s<br>\n", 
+                &data[key_start], &data[val_start]);
+    return -1;
+  }
 
-  return size;
+  abuf_puts(abuf,
+           "<h2>UPDATE SUCESSFULL!</h2><br>Press BACK and RELOAD in your browser to return to the plugin<br>\n"
+           "</body>\n"
+           "</html>\n");
+  return 0;
 }
 #endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
index ccc35ae..8715d8c 100644 (file)
 #define ADMIN_INTERFACE_H
 
 #include "olsr_types.h"
+#include "common/autobuf.h"
 
-int
-build_admin_body(char *, olsr_u32_t);
+void
+build_admin_body(struct autobuf *abuf);
 
 int
-process_set_values(char*, olsr_u32_t, char *, olsr_u32_t);
+process_set_values(char*, olsr_u32_t, struct autobuf *abuf);
 
 int
 process_param(char *, char *);
@@ -61,3 +62,9 @@ process_param(char *, char *);
 #endif
 
 #endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
index 041dee2..f496445 100644 (file)
  * Dynamic linked library for the olsr.org olsr daemon
  */
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#ifdef WIN32
-#include <io.h>
-#else
-#include <netdb.h>
-#endif
+#include "olsrd_httpinfo.h"
+#include "admin_interface.h"
+#include "gfx.h"
 
 #include "olsr.h"
 #include "olsr_cfg.h"
 #include "link_set.h"
 #include "ipcalc.h"
 #include "lq_plugin.h"
+
 #include "common/string.h"
 
-#include "olsrd_httpinfo.h"
-#include "admin_interface.h"
-#include "gfx.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef WIN32
+#include <io.h>
+#else
+#include <netdb.h>
+#endif
 
 #ifdef OS
 #undef OS
@@ -132,74 +134,70 @@ static const char httpinfo_css[] =
   "width:120px;padding:0px;color:#000;text-decoration:none;font-family:verdana;"
   "font-size:12px;border:1px solid #000;}\n";
 
-typedef int(*build_body_callback)(char *, olsr_u32_t);
+typedef void (*build_body_callback)(struct autobuf *abuf);
 
-struct tab_entry
-{
+struct tab_entry {
   const char *tab_label;
   const char *filename;
   build_body_callback build_body_cb;
   olsr_bool display_tab;
 };
 
-struct static_bin_file_entry
-{
+struct static_bin_file_entry {
   const char *filename;
   unsigned char *data;
   unsigned int data_size;
 };
 
-struct static_txt_file_entry
-{
+struct static_txt_file_entry {
   const char *filename;
   const char *data;
 };
 
 #if ADMIN_INTERFACE
-struct dynamic_file_entry
-{
+struct dynamic_file_entry {
   const char *filename;
-  int(*process_data_cb)(char *, olsr_u32_t, char *, olsr_u32_t);
+  process_data_func process_data_cb;
 };
 #endif
 
 static int get_http_socket(int);
 
-static int build_tabs(char *, olsr_u32_t, int);
+static void build_tabs(struct autobuf *abuf, int);
 
 static void parse_http_request(int, void *, unsigned int flags);
 
-static int build_http_header(http_header_type, olsr_bool, olsr_u32_t, char *, olsr_u32_t);
+static void build_http_header(struct autobuf *abuf, http_header_type, olsr_bool, olsr_u32_t);
 
-static int build_frame(char *, olsr_u32_t, const char *, const char *, int, build_body_callback frame_body_cb);
+static void build_frame(struct autobuf *abuf, build_body_callback frame_body_cb);
 
-static int build_routes_body(char *, olsr_u32_t);
+static void build_routes_body(struct autobuf *abuf);
 
-static int build_config_body(char *, olsr_u32_t);
+static void build_config_body(struct autobuf *abuf);
 
-static int build_neigh_body(char *, olsr_u32_t);
+static void build_neigh_body(struct autobuf *abuf);
 
-static int build_topo_body(char *, olsr_u32_t);
+static void build_topo_body(struct autobuf *abuf);
 
-static int build_mid_body(char *, olsr_u32_t);
+static void build_mid_body(struct autobuf *abuf);
 
-static int build_nodes_body(char *, olsr_u32_t);
+static void build_nodes_body(struct autobuf *abuf);
 
-static int build_all_body(char *, olsr_u32_t);
+static void build_all_body(struct autobuf *abuf);
 
-static int build_about_body(char *, olsr_u32_t);
+static void build_about_body(struct autobuf *abuf);
 
-static int build_cfgfile_body(char *, olsr_u32_t);
+static void build_cfgfile_body(struct autobuf *abuf);
 
 static int check_allowed_ip(const struct allowed_net * const all_nets, const union olsr_ip_addr * const addr);
 
-static int build_ip_txt(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link,
-                        const char * const ipaddrstr, const int prefix_len);
+static void build_ip_txt(struct autobuf *abuf, const olsr_bool want_link,
+                        const char * const ipaddrstr, const int prefix_len);
 
-static int build_ipaddr_link(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link,
-                             const union olsr_ip_addr * const ipaddr,
-                             const int prefix_len);
-static int section_title(char *buf, olsr_u32_t bufsize, const char *title);
+static void build_ipaddr_link(struct autobuf *abuf, const olsr_bool want_link,
+                             const union olsr_ip_addr * const ipaddr,
+                             const int prefix_len);
+static void section_title(struct autobuf *abuf, const char *title);
 
 static ssize_t writen(int fd, const void *buf, size_t count);
 
@@ -329,20 +327,21 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
   struct sockaddr_in pin;
   socklen_t addrlen;
   char req[MAX_HTTPREQ_SIZE];
-  static char body[HTML_BUFSIZE];
+  //static char body[HTML_BUFSIZE];
+  struct autobuf body, header;
   char req_type[11];
   char filename[251];
   char http_version[11];
   unsigned int c = 0;
-  int r = 1, size = 0;
+  int r = 1 /*, size = 0 */;
 
   if (curr_clients >= MAX_CLIENTS) {
     return;
   }
   curr_clients++;
 
-  addrlen = sizeof(struct sockaddr_in);
-  client_sockets[curr_clients] = accept(fd, (struct sockaddr *)  &pin, &addrlen);
+  addrlen = sizeof(pin);
+  client_sockets[curr_clients] = accept(fd, (struct sockaddr *)&pin, &addrlen);
   if (client_sockets[curr_clients] == -1) {
     olsr_printf(1, "(HTTPINFO) accept: %s\n", strerror(errno));
     goto close_connection;
@@ -356,7 +355,9 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
   }
 
   memset(req, 0, sizeof(req));
-  memset(body, 0, sizeof(body));
+  //memset(body, 0, sizeof(body));
+  abuf_init(&body, 0);
+  abuf_init(&header, 0);
 
   while ((r = recv(client_sockets[curr_clients], &req[c], 1, 0)) > 0 && (c < sizeof(req)-1)) {
       c++;
@@ -400,17 +401,20 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
             printf("Dynamic read %d bytes\n", param_size);
        
             //memcpy(body, dynamic_files[i].data, static_bin_files[i].data_size);
-            size += dynamic_files[i].process_data_cb(req, param_size, &body[size], sizeof(body)-size);
-            c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, sizeof(req));
+            //size += dynamic_files[i].process_data_cb(req, param_size, &body[size], sizeof(body)-size);
+           dynamic_files[i].process_data_cb(req, param_size, &body);
+
+            build_http_header(&header, HTTP_OK, OLSR_TRUE, body.len);
             goto send_http_data;
         }
         i++;
     }
 #endif
     /* We only support GET */
-    strscpy(body, HTTP_400_MSG, sizeof(body));
+    //strscpy(body, HTTP_400_MSG, sizeof(body));
+    abuf_puts(&body, HTTP_400_MSG);
     stats.ill_hits++;
-    c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, sizeof(req));
+    build_http_header(&header, HTTP_BAD_REQ, OLSR_TRUE, body.len);
   } else if (!strcmp(req_type, "GET")) {
     int i = 0;
 
@@ -422,9 +426,10 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
 
     if (static_bin_files[i].filename) {
       stats.ok_hits++;
-      memcpy(body, static_bin_files[i].data, static_bin_files[i].data_size);
-      size = static_bin_files[i].data_size;
-      c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, sizeof(req));
+      //memcpy(body, static_bin_files[i].data, static_bin_files[i].data_size);
+      abuf_memcpy(&body, static_bin_files[i].data, static_bin_files[i].data_size);
+      //size = static_bin_files[i].data_size;
+      build_http_header(&header, HTTP_OK, OLSR_FALSE, body.len);
       goto send_http_data;
     }
 
@@ -438,8 +443,11 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
 
     if (static_txt_files[i].filename) {
       stats.ok_hits++;
-      size += snprintf(&body[size], sizeof(body)-size, "%s", static_txt_files[i].data);
-      c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, sizeof(req));
+
+      //size += snprintf(&body[size], sizeof(body)-size, "%s", static_txt_files[i].data);
+      abuf_puts(&body, static_txt_files[i].data);
+
+      build_http_header(&header, HTTP_OK, OLSR_FALSE, body.len);
       goto send_http_data;
     }
 
@@ -455,7 +463,7 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
 
     if (tab_entries[i].filename) {
 #ifdef NETDIRECT
-      c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, sizeof(req));
+      build_http_header(&header, HTTP_OK, OLSR_TRUE);
       r = send(client_sockets[curr_clients], req, c, 0);
       if (r < 0) {
         olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
@@ -464,7 +472,7 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
       netsprintf_error = 0;
       netsprintf_direct = 1;
 #endif
-      size += snprintf(&body[size], sizeof(body)-size,
+      abuf_appendf(&body,
                        "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
                        "<head>\n"
                        "<meta http-equiv=\"Content-type\" content=\"text/html; charset=ISO-8859-1\">\n"
@@ -485,17 +493,13 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
                        "</table>\n",
                        FRAMEWIDTH);
        
-      size += build_tabs(&body[size], sizeof(body)-size, i);
-      size += build_frame(&body[size],
-                          sizeof(body)-size,
-                          "Current Routes",
-                          "routes",
-                          FRAMEWIDTH,
-                          tab_entries[i].build_body_cb);
+      build_tabs(&body, i);
+      build_frame(&body,
+                 tab_entries[i].build_body_cb);
        
       stats.ok_hits++;
 
-      size += snprintf(&body[size], sizeof(body)-size,
+      abuf_appendf(&body,
                        "</table>\n"
                        "<div id=\"footer\">\n"
                        "<center>\n"
@@ -510,53 +514,54 @@ parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flag
       netsprintf_direct = 1;
       goto close_connection;
 #else
-      c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, sizeof(req));
+      build_http_header(&header, HTTP_OK, OLSR_TRUE, body.len);
       goto send_http_data;
 #endif
     }
 
 
     stats.ill_hits++;
-    strscpy(body, HTTP_404_MSG, sizeof(body));
-    c = build_http_header(HTTP_BAD_FILE, OLSR_TRUE, strlen(body), req, sizeof(req));
+    //strscpy(body, HTTP_404_MSG, sizeof(body));
+    abuf_puts(&body, HTTP_404_MSG);
+    build_http_header(&header, HTTP_BAD_FILE, OLSR_TRUE, body.len);
   } else {
     /* We only support GET */
-    strscpy(body, HTTP_400_MSG, sizeof(body));
+    //strscpy(body, HTTP_400_MSG, sizeof(body));
+    abuf_puts(&body, HTTP_400_MSG);
     stats.ill_hits++;
-    c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, sizeof(req));
+    build_http_header(&header, HTTP_BAD_REQ, OLSR_TRUE, body.len);
   }
 
  send_http_data:
 
-  r = writen(client_sockets[curr_clients], req, c);
+  r = writen(client_sockets[curr_clients], header.buf, header.len);
   if (r < 0) {
       olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
       goto close_connection;
   }
 
-  r = writen(client_sockets[curr_clients], body, size);
+  r = writen(client_sockets[curr_clients], body.buf, body.len);
   if (r < 0) {
       olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
       goto close_connection;
   }
 
  close_connection:
+  abuf_free(&body);
+  abuf_free(&header);
   close(client_sockets[curr_clients]);
   curr_clients--;
-
 }
 
 
-int
-build_http_header(http_header_type type,
+void
+build_http_header(struct autobuf *abuf,
+                 http_header_type type,
                  olsr_bool is_html,
-                 olsr_u32_t msgsize,
-                 char *buf,
-                 olsr_u32_t bufsize)
+                 olsr_u32_t msgsize)
 {
   time_t currtime;
   const char *h;
-  int size;
 
   switch(type) {
   case HTTP_BAD_REQ:
@@ -570,68 +575,64 @@ build_http_header(http_header_type type,
       h = HTTP_200;
       break;
   }
-  size = snprintf(buf, bufsize, "%s", h);
+  abuf_puts(abuf, h);
 
   /* Date */
   time(&currtime);
-  size += strftime(&buf[size], bufsize-size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
+  abuf_strftime(abuf, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
 
   /* Server version */
-  size += snprintf(&buf[size], bufsize-size, "Server: %s %s %s\r\n", PLUGIN_NAME, PLUGIN_VERSION, HTTP_VERSION);
+  abuf_appendf(abuf, "Server: %s %s %s\r\n", PLUGIN_NAME, PLUGIN_VERSION, HTTP_VERSION);
 
   /* connection-type */
-  size += snprintf(&buf[size], bufsize-size, "Connection: closed\r\n");
+  abuf_puts(abuf, "Connection: closed\r\n");
 
   /* MIME type */
-  size += snprintf(&buf[size], bufsize-size, "Content-type: text/%s\r\n", is_html ? "html" : "plain");
+  abuf_appendf(abuf, "Content-type: text/%s\r\n", is_html ? "html" : "plain");
 
   /* Content length */
   if (msgsize > 0) {
-      size += snprintf(&buf[size], bufsize-size, "Content-length: %i\r\n", msgsize);
+      abuf_appendf(abuf, "Content-length: %i\r\n", msgsize);
   }
 
   /* Cache-control
    * No caching dynamic pages
    */
-  size += snprintf(&buf[size], bufsize-size, "Cache-Control: no-cache\r\n");
+  abuf_puts(abuf, "Cache-Control: no-cache\r\n");
 
   if (!is_html) {
-    size += snprintf(&buf[size], bufsize-size, "Accept-Ranges: bytes\r\n");
+    abuf_puts(abuf, "Accept-Ranges: bytes\r\n");
   }
   /* End header */
-  size += snprintf(&buf[size], bufsize-size, "\r\n");
-
-  olsr_printf(1, "HEADER:\n%s", buf);
+  abuf_puts(abuf, "\r\n");
 
-  return size;
+  olsr_printf(1, "HEADER:\n%s", abuf->buf);
 }
 
 
-
-static int build_tabs(char *buf, const olsr_u32_t bufsize, int active)
+static void build_tabs(struct autobuf *abuf, int active)
 {
-  int size = 0, tabs = 0;
+  int tabs;
 
-  size += snprintf(&buf[size], bufsize-size,
-                   "<table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
-                   "<tr bgcolor=\"#ffffff\"><td>\n"
-                   "<ul id=\"tabnav\">\n",
-                   FRAMEWIDTH);
+  abuf_appendf(abuf,
+                 "<table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
+                 "<tr bgcolor=\"#ffffff\"><td>\n"
+                 "<ul id=\"tabnav\">\n",
+                 FRAMEWIDTH);
   for (tabs = 0; tab_entries[tabs].tab_label; tabs++) {
     if (!tab_entries[tabs].display_tab) {
       continue;
     }
-    size += snprintf(&buf[size], bufsize-size,
-                     "<li><a href=\"%s\"%s>%s</a></li>\n",
-                     tab_entries[tabs].filename,
-                     tabs == active ? " class=\"active\"" : "",
-                     tab_entries[tabs].tab_label);
+    abuf_appendf(abuf,
+                   "<li><a href=\"%s\"%s>%s</a></li>\n",
+                   tab_entries[tabs].filename,
+                   tabs == active ? " class=\"active\"" : "",
+                   tab_entries[tabs].tab_label);
   }
-  size += snprintf(&buf[size], bufsize-size,
-                   "</ul>\n"
-                   "</td></tr>\n"
-                   "<tr><td>\n");
-  return size;
+  abuf_appendf(abuf,
+                 "</ul>\n"
+                 "</td></tr>\n"
+                 "<tr><td>\n");
 }
 
 
@@ -647,64 +648,52 @@ olsr_plugin_exit(void)
 }
 
 
-static int section_title(char *buf, olsr_u32_t bufsize, const char *title)
+static void section_title(struct autobuf *abuf, const char *title)
 {
-  return snprintf(buf, bufsize,
+  abuf_appendf(abuf,
                   "<h2>%s</h2>\n"
                   "<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n", title);
 }
 
-static int build_frame(char *buf,
-                       olsr_u32_t bufsize,
-                       const char *title __attribute__((unused)),
-                       const char *lnk __attribute__((unused)),
-                       int width __attribute__((unused)),
-                       build_body_callback frame_body_cb)
+static void build_frame(struct autobuf *abuf,
+                       build_body_callback frame_body_cb)
 {
-  int size = 0;
-  size += snprintf(&buf[size], bufsize-size, "<div id=\"maintable\">\n");
-  size += frame_body_cb(&buf[size], bufsize-size);
-  size += snprintf(&buf[size], bufsize-size, "</div>\n");
-  return size;
+  abuf_puts(abuf, "<div id=\"maintable\">\n");
+  frame_body_cb(abuf);
+  abuf_puts(abuf, "</div>\n");
 }
 
-static int fmt_href(char *buf,
-                    const olsr_u32_t bufsize,
+static void fmt_href(struct autobuf *abuf,
                     const char * const ipaddr)
 {
-  return snprintf(buf, bufsize, "<a href=\"http://%s:%d/all\">", ipaddr, http_port);
+  abuf_appendf(abuf, "<a href=\"http://%s:%d/all\">", ipaddr, http_port);
 }
 
-static int build_ip_txt(char *buf,
-                        const olsr_u32_t bufsize,
-                        const olsr_bool print_link,
-                        const char * const ipaddrstr,
-                        const int prefix_len)
+static void build_ip_txt(struct autobuf *abuf,
+                        const olsr_bool print_link,
+                        const char * const ipaddrstr,
+                        const int prefix_len)
 {
-  int size = 0;
-
   if (print_link) {
-    size += fmt_href(&buf[size], bufsize-size, ipaddrstr);
+    fmt_href(abuf, ipaddrstr);
   }
 
-  size += snprintf(&buf[size], bufsize-size, "%s", ipaddrstr);
+  abuf_puts(abuf, ipaddrstr);
   /* print ip address or ip prefix ? */
   if (prefix_len != -1 && prefix_len != olsr_cnf->maxplen) {
-      size += snprintf(&buf[size], bufsize-size, "/%d", prefix_len);
+    abuf_appendf(abuf, "/%d", prefix_len);
   }
 
   if (print_link) { /* Print the link only if there is no prefix_len */
-    size += snprintf(&buf[size], bufsize-size, "</a>");
+    abuf_puts(abuf, "</a>");
   }
-  return size;
 }
 
-static int build_ipaddr_link(char *buf, const olsr_u32_t bufsize,
-                             const olsr_bool want_link,
-                             const union olsr_ip_addr * const ipaddr,
-                             const int prefix_len)
+static void build_ipaddr_link(struct autobuf *abuf,
+                             const olsr_bool want_link,
+                             const union olsr_ip_addr * const ipaddr,
+                             const int prefix_len)
 {
-  int size = 0;
   struct ipaddr_str ipaddrstr;
   const struct hostent * const hp =
 #ifndef WIN32
@@ -715,293 +704,279 @@ static int build_ipaddr_link(char *buf, const olsr_u32_t bufsize,
   const int print_link = want_link && (prefix_len == -1 || prefix_len == olsr_cnf->maxplen);
   olsr_ip_to_string(&ipaddrstr, ipaddr);
 
-  size += snprintf(&buf[size], bufsize-size, "<td>");
-  size += build_ip_txt(&buf[size], bufsize-size, print_link, ipaddrstr.buf, prefix_len);
-  size += snprintf(&buf[size], bufsize-size, "</td>");
+  abuf_puts(abuf, "<td>");
+  build_ip_txt(abuf, print_link, ipaddrstr.buf, prefix_len);
+  abuf_puts(abuf, "</td>");
 
   if (resolve_ip_addresses) {
     if (hp) {
-      size += snprintf(&buf[size], bufsize-size, "<td>(");
+      abuf_puts(abuf, "<td>(");
       if (print_link) {
-        size += fmt_href(&buf[size], bufsize-size, ipaddrstr.buf);
+        fmt_href(abuf, ipaddrstr.buf);
       }
-      size += snprintf(&buf[size], bufsize-size, "%s", hp->h_name);
+      abuf_puts(abuf, hp->h_name);
       if (print_link) {
-        size += snprintf(&buf[size], bufsize-size, "</a>");
+        abuf_puts(abuf, "</a>");
       }
-      size += snprintf(&buf[size], bufsize-size, ")</td>");
+      abuf_puts(abuf, ")</td>");
     } else {
-      size += snprintf(&buf[size], bufsize-size, "<td/>");
+      abuf_puts(abuf, "<td/>");
     }
   }
-  return size;
 }
 
-#define build_ipaddr_with_link(buf, bufsize, ipaddr, plen) \
-          build_ipaddr_link((buf), (bufsize), OLSR_TRUE, (ipaddr), (plen))
-#define build_ipaddr_no_link(buf, bufsize, ipaddr, plen) \
-          build_ipaddr_link((buf), (bufsize), OLSR_FALSE, (ipaddr), (plen))
+#define build_ipaddr_with_link(abuf, ipaddr, plen) \
+          build_ipaddr_link((abuf), OLSR_TRUE, (ipaddr), (plen))
+#define build_ipaddr_no_link(abuf, ipaddr, plen) \
+          build_ipaddr_link((abuf), OLSR_FALSE, (ipaddr), (plen))
 
-static int build_route(char *buf, olsr_u32_t bufsize, const struct rt_entry * rt)
+static void build_route(struct autobuf *abuf, const struct rt_entry * rt)
 {
-  int size = 0;
   struct lqtextbuffer lqbuffer;
   
-  size += snprintf(&buf[size], bufsize-size, "<tr>");
-  size += build_ipaddr_with_link(&buf[size], bufsize-size,
-                                 &rt->rt_dst.prefix,
-                                 rt->rt_dst.prefix_len);
-  size += build_ipaddr_with_link(&buf[size], bufsize-size,
-                                 &rt->rt_best->rtp_nexthop.gateway,
-                                 -1);
-
-  size += snprintf(&buf[size], bufsize-size,
-                   "<td align=\"center\">%d</td>",
-                   rt->rt_best->rtp_metric.hops);
-  size += snprintf(&buf[size], bufsize-size,
-                   "<td align=\"right\">%s</td>",
-                   get_linkcost_text(rt->rt_best->rtp_metric.cost, OLSR_TRUE, &lqbuffer));
-  size += snprintf(&buf[size], bufsize-size,
-                   "<td align=\"center\">%s</td></tr>\n",
-                   if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
-  return size;
+  abuf_puts(abuf, "<tr>");
+  build_ipaddr_with_link(abuf,
+                        &rt->rt_dst.prefix,
+                        rt->rt_dst.prefix_len);
+  build_ipaddr_with_link(abuf,
+                        &rt->rt_best->rtp_nexthop.gateway,
+                        -1);
+
+  abuf_appendf(abuf,
+                 "<td align=\"center\">%d</td>",
+                 rt->rt_best->rtp_metric.hops);
+  abuf_appendf(abuf,
+                 "<td align=\"right\">%s</td>",
+                 get_linkcost_text(rt->rt_best->rtp_metric.cost, OLSR_TRUE, &lqbuffer));
+  abuf_appendf(abuf,
+                 "<td align=\"center\">%s</td></tr>\n",
+                 if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
 }
 
-static int build_routes_body(char *buf, olsr_u32_t bufsize)
+static void build_routes_body(struct autobuf *abuf)
 {
-  int size = 0;
   struct rt_entry *rt;
   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
-  size += section_title(&buf[size], bufsize-size, "OLSR Routes in Kernel");
-  size += snprintf(&buf[size], bufsize-size, "<tr><th align=\"center\"%s>Destination</th><th align=\"center\"%s>Gateway</th><th align=\"right\">Metric</th><th align=\"right\">ETX</th><th align=\"right\">Interface</th></tr>\n", colspan, colspan);
+  section_title(abuf, "OLSR Routes in Kernel");
+  abuf_appendf(abuf,
+                 "<tr><th align=\"center\"%s>Destination</th><th align=\"center\"%s>Gateway</th><th align=\"right\">Metric</th><th align=\"right\">ETX</th><th align=\"right\">Interface</th></tr>\n",
+                 colspan, colspan);
 
   /* Walk the route table */
   OLSR_FOR_ALL_RT_ENTRIES(rt) {
-      size += build_route(&buf[size], bufsize-size, rt);
+      build_route(abuf, rt);
   } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
 
-  size += snprintf(&buf[size], bufsize-size, "</table>\n");
-
-  return size;
+  abuf_puts(abuf, "</table>\n");
 }
 
-static int build_config_body(char *buf, olsr_u32_t bufsize)
+static void build_config_body(struct autobuf *abuf)
 {
-    int size = 0;
-    const struct olsr_if *ifs;
-    const struct plugin_entry *pentry;
-    const struct plugin_param *pparam;
-    struct ipaddr_str mainaddrbuf;
-
-    size += snprintf(&buf[size], bufsize-size, "Version: %s (built on %s on %s)\n<br>", olsrd_version, build_date, build_host);
-    size += snprintf(&buf[size], bufsize-size, "OS: %s\n<br>", OS);
-
-    {
-      const time_t currtime = time(NULL);
-      const int rc = strftime(&buf[size], bufsize-size, "System time: <em>%a, %d %b %Y %H:%M:%S</em><br>", localtime(&currtime));
-      if (rc > 0) {
-        size += rc;
-      }
-    }
+  const struct olsr_if *ifs;
+  const struct plugin_entry *pentry;
+  const struct plugin_param *pparam;
+  struct ipaddr_str mainaddrbuf;
+
+  abuf_appendf(abuf,
+                 "Version: %s (built on %s on %s)\n<br>OS: %s\n<br>",
+                 olsrd_version, build_date, build_host, OS);
+  {
+    const time_t currtime = time(NULL);
+    abuf_strftime(abuf, "System time: <em>%a, %d %b %Y %H:%M:%S</em><br>", localtime(&currtime));
+  }
 
-    {
-      struct timeval now, uptime;
-      int hours, mins, days;
-      gettimeofday(&now, NULL);
-      timersub(&now, &start_time, &uptime);
-
-      days = uptime.tv_sec/86400;
-      uptime.tv_sec %= 86400;
-      hours = uptime.tv_sec/3600;
-      uptime.tv_sec %= 3600;
-      mins = uptime.tv_sec/60;
-      uptime.tv_sec %= 60;
-
-      size += snprintf(&buf[size], bufsize-size, "Olsrd uptime: <em>");
-      if (days) {
-        size += snprintf(&buf[size], bufsize-size, "%d day(s) ", days);
-      }
-      size += snprintf(&buf[size], bufsize-size, "%02d hours %02d minutes %02d seconds</em><br/>\n", hours, mins, (int)uptime.tv_sec);
+  {
+    struct timeval now, uptime;
+    int hours, mins, days;
+    gettimeofday(&now, NULL);
+    timersub(&now, &start_time, &uptime);
+
+    days = uptime.tv_sec/86400;
+    uptime.tv_sec %= 86400;
+    hours = uptime.tv_sec/3600;
+    uptime.tv_sec %= 3600;
+    mins = uptime.tv_sec/60;
+    uptime.tv_sec %= 60;
+
+    abuf_puts(abuf, "Olsrd uptime: <em>");
+    if (days) {
+      abuf_appendf(abuf, "%d day(s) ", days);
     }
+    abuf_appendf(abuf, "%02d hours %02d minutes %02d seconds</em><br/>\n", hours, mins, (int)uptime.tv_sec);
+  }
 
-    size += snprintf(&buf[size], bufsize-size, "HTTP stats(ok/dyn/error/illegal): <em>%d/%d/%d/%d</em><br>\n", stats.ok_hits, stats.dyn_hits, stats.err_hits, stats.ill_hits);
-
-    size += snprintf(&buf[size], bufsize-size, "Click <a href=\"/cfgfile\">here</a> to <em>generate a configuration file for this node</em>.\n");
+  abuf_appendf(abuf, "HTTP stats(ok/dyn/error/illegal): <em>%d/%d/%d/%d</em><br>\n", stats.ok_hits, stats.dyn_hits, stats.err_hits, stats.ill_hits);
 
-    size += snprintf(&buf[size], bufsize-size, "<h2>Variables</h2>\n");
+  abuf_appendf(abuf, "Click <a href=\"/cfgfile\">here</a> to <em>generate a configuration file for this node</em>.\n");
 
-    size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=\"0\">\n<tr>");
+  abuf_puts(abuf, "<h2>Variables</h2>\n");
 
-    size += snprintf(&buf[size], bufsize-size, "<td>Main address: <strong>%s</strong></td>\n", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
-    size += snprintf(&buf[size], bufsize-size, "<td>IP version: %d</td>\n", olsr_cnf->ip_version == AF_INET ? 4 : 6);
-    size += snprintf(&buf[size], bufsize-size, "<td>Debug level: %d</td>\n", olsr_cnf->debug_level);
-    size += snprintf(&buf[size], bufsize-size, "<td>FIB Metrics: %s</td>\n", FIBM_FLAT == olsr_cnf->fib_metric ? CFG_FIBM_FLAT : FIBM_CORRECT == olsr_cnf->fib_metric ? CFG_FIBM_CORRECT : CFG_FIBM_APPROX);
+  abuf_puts(abuf, "<table width=\"100%%\" border=\"0\">\n<tr>");
 
-    size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
+  abuf_appendf(abuf, "<td>Main address: <strong>%s</strong></td>\n", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
+  abuf_appendf(abuf, "<td>IP version: %d</td>\n", olsr_cnf->ip_version == AF_INET ? 4 : 6);
+  abuf_appendf(abuf, "<td>Debug level: %d</td>\n", olsr_cnf->debug_level);
+  abuf_appendf(abuf, "<td>FIB Metrics: %s</td>\n", FIBM_FLAT == olsr_cnf->fib_metric ? CFG_FIBM_FLAT : FIBM_CORRECT == olsr_cnf->fib_metric ? CFG_FIBM_CORRECT : CFG_FIBM_APPROX);
+                 
+  abuf_puts(abuf, "</tr>\n<tr>\n");
 
-    size += snprintf(&buf[size], bufsize-size, "<td>Pollrate: %0.2f</td>\n", conv_pollrate_to_secs(olsr_cnf->pollrate));
-    size += snprintf(&buf[size], bufsize-size, "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
-    size += snprintf(&buf[size], bufsize-size, "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
-    size += snprintf(&buf[size], bufsize-size, "<td>NAT threshold: %f</td>\n", olsr_cnf->lq_nat_thresh);
+  abuf_appendf(abuf, "<td>Pollrate: %0.2f</td>\n", conv_pollrate_to_secs(olsr_cnf->pollrate));
+  abuf_appendf(abuf, "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
+  abuf_appendf(abuf, "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
+  abuf_appendf(abuf, "<td>NAT threshold: %f</td>\n", olsr_cnf->lq_nat_thresh);
 
-    size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
+  abuf_puts(abuf, "</tr>\n<tr>\n");
 
-    size += snprintf(&buf[size], bufsize-size, "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
-    size += snprintf(&buf[size], bufsize-size, "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
-    size += snprintf(&buf[size], bufsize-size, "<td>RtTable: 0x%04x/%d</td>\n", olsr_cnf->rttable, olsr_cnf->rttable);
-    size += snprintf(&buf[size], bufsize-size, "<td>RtTableDefault: 0x%04x/%d</td>\n", olsr_cnf->rttable_default, olsr_cnf->rttable_default);
-    size += snprintf(&buf[size], bufsize-size, "<td>Willingness: %d %s</td>\n", olsr_cnf->willingness, olsr_cnf->willingness_auto ? "(auto)" : "");
+  abuf_appendf(abuf, "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
+  abuf_appendf(abuf, "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
+  abuf_appendf(abuf, "<td>RtTable: 0x%04x/%d</td>\n", olsr_cnf->rttable, olsr_cnf->rttable);
+  abuf_appendf(abuf, "<td>RtTableDefault: 0x%04x/%d</td>\n", olsr_cnf->rttable_default, olsr_cnf->rttable_default);
+  abuf_appendf(abuf, "<td>Willingness: %d %s</td>\n", olsr_cnf->willingness, olsr_cnf->willingness_auto ? "(auto)" : "");
 
-    if (olsr_cnf->lq_level == 0) {
-      size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n"
-                                                  "<td>Hysteresis: %s</td>\n", olsr_cnf->use_hysteresis ? "Enabled" : "Disabled");
-      if (olsr_cnf->use_hysteresis) {
-        size += snprintf(&buf[size], bufsize-size, "<td>Hyst scaling: %0.2f</td>\n", olsr_cnf->hysteresis_param.scaling);
-        size += snprintf(&buf[size], bufsize-size, "<td>Hyst lower/upper: %0.2f/%0.2f</td>\n", olsr_cnf->hysteresis_param.thr_low, olsr_cnf->hysteresis_param.thr_high);
-      }
+  if (olsr_cnf->lq_level == 0) {
+    abuf_appendf(abuf, "</tr>\n<tr>\n"
+                   "<td>Hysteresis: %s</td>\n", olsr_cnf->use_hysteresis ? "Enabled" : "Disabled");
+    if (olsr_cnf->use_hysteresis) {
+      abuf_appendf(abuf, "<td>Hyst scaling: %0.2f</td>\n", olsr_cnf->hysteresis_param.scaling);
+      abuf_appendf(abuf, "<td>Hyst lower/upper: %0.2f/%0.2f</td>\n", olsr_cnf->hysteresis_param.thr_low, olsr_cnf->hysteresis_param.thr_high);
     }
+  }
 
-    size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n"
-                                               "<td>LQ extension: %s</td>\n", olsr_cnf->lq_level ? "Enabled" : "Disabled");
-    if (olsr_cnf->lq_level) {
-      size += snprintf(&buf[size], bufsize-size,
-                       "<td>LQ level: %d</td>\n"
-                       "<td>LQ aging: %f</td>\n",
-                       olsr_cnf->lq_level,
-                       olsr_cnf->lq_aging);
+  abuf_appendf(abuf, "</tr>\n<tr>\n"
+                 "<td>LQ extension: %s</td>\n", olsr_cnf->lq_level ? "Enabled" : "Disabled");
+  if (olsr_cnf->lq_level) {
+    abuf_appendf(abuf,
+                   "<td>LQ level: %d</td>\n"
+                   "<td>LQ aging: %f</td>\n",
+                   olsr_cnf->lq_level,
+                   olsr_cnf->lq_aging);
+  }
+  abuf_puts(abuf, "</tr></table>\n");
+
+  abuf_puts(abuf, "<h2>Interfaces</h2>\n");
+  abuf_puts(abuf, "<table width=\"100%%\" border=\"0\">\n");
+  for (ifs = olsr_cnf->interfaces; ifs != NULL; ifs = ifs->next) {
+    const struct interface * const rifs = ifs->interf;
+    abuf_appendf(abuf, "<tr><th colspan=\"3\">%s</th>\n", ifs->name);
+    if (!rifs) {
+      abuf_puts(abuf, "<tr><td colspan=\"3\">Status: DOWN</td></tr>\n");
+      continue;
     }
-    size += snprintf(&buf[size], bufsize-size, "</tr></table>\n");
-
-    size += snprintf(&buf[size], bufsize-size, "<h2>Interfaces</h2>\n");
-    size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=\"0\">\n");
-    for (ifs = olsr_cnf->interfaces; ifs != NULL; ifs = ifs->next) {
-       const struct interface * const rifs = ifs->interf;
-       size += snprintf(&buf[size], bufsize-size, "<tr><th colspan=\"3\">%s</th>\n", ifs->name);
-       if (!rifs) {
-         size += snprintf(&buf[size], bufsize-size, "<tr><td colspan=\"3\">Status: DOWN</td></tr>\n");
-          continue;
-        }
 
-       if (olsr_cnf->ip_version == AF_INET) {
-          struct ipaddr_str addrbuf, maskbuf, bcastbuf;
-         size += snprintf(&buf[size], bufsize-size,
-                           "<tr>\n"
-                           "<td>IP: %s</td>\n"
-                           "<td>MASK: %s</td>\n"
-                           "<td>BCAST: %s</td>\n"
-                           "</tr>\n",
-                           ip4_to_string(&addrbuf, rifs->int_addr.sin_addr),
-                           ip4_to_string(&maskbuf, rifs->int_netmask.sin_addr),
-                           ip4_to_string(&bcastbuf, rifs->int_broadaddr.sin_addr));
-       } else {
-          struct ipaddr_str addrbuf, maskbuf;
-         size += snprintf(&buf[size], bufsize-size,
-                           "<tr>\n"
-                           "<td>IP: %s</td>\n"
-                           "<td>MCAST: %s</td>\n"
-                           "<td></td>\n"
-                           "</tr>\n",
-                           ip6_to_string(&addrbuf, &rifs->int6_addr.sin6_addr),
-                           ip6_to_string(&maskbuf, &rifs->int6_multaddr.sin6_addr));
-        }      
-        size += snprintf(&buf[size], bufsize-size,
-                         "<tr>\n"
-                         "<td>MTU: %d</td>\n"
-                         "<td>WLAN: %s</td>\n"
-                         "<td>STATUS: UP</td>\n"
-                         "</tr>\n",
-                         rifs->int_mtu,
-                         rifs->is_wireless ? "Yes" : "No");
+    if (olsr_cnf->ip_version == AF_INET) {
+      struct ipaddr_str addrbuf, maskbuf, bcastbuf;
+      abuf_appendf(abuf,
+                     "<tr>\n"
+                     "<td>IP: %s</td>\n"
+                     "<td>MASK: %s</td>\n"
+                     "<td>BCAST: %s</td>\n"
+                     "</tr>\n",
+                     ip4_to_string(&addrbuf, rifs->int_addr.sin_addr),
+                     ip4_to_string(&maskbuf, rifs->int_netmask.sin_addr),
+                     ip4_to_string(&bcastbuf, rifs->int_broadaddr.sin_addr));
+    } else {
+      struct ipaddr_str addrbuf, maskbuf;
+      abuf_appendf(abuf,
+                     "<tr>\n"
+                     "<td>IP: %s</td>\n"
+                     "<td>MCAST: %s</td>\n"
+                     "<td></td>\n"
+                     "</tr>\n",
+                     ip6_to_string(&addrbuf, &rifs->int6_addr.sin6_addr),
+                     ip6_to_string(&maskbuf, &rifs->int6_multaddr.sin6_addr));
     }
-    size += snprintf(&buf[size], bufsize-size, "</table>\n");
-
-    size += snprintf(&buf[size], bufsize-size,
-                     "<em>Olsrd is configured to %s if no interfaces are available</em><br>\n",
-                     olsr_cnf->allow_no_interfaces ? "run even" : "halt");
-
-    size += snprintf(&buf[size], bufsize-size, "<h2>Plugins</h2>\n");
-    size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=\"0\"><tr><th>Name</th><th>Parameters</th></tr>\n");
-    for (pentry = olsr_cnf->plugins; pentry; pentry = pentry->next)
-      {
-       size += snprintf(&buf[size], bufsize-size,
-                         "<tr><td>%s</td>\n"
-                         "<td><select>\n"
-                         "<option>KEY, VALUE</option>\n",
-                         pentry->name);
-
-       for (pparam = pentry->params; pparam; pparam = pparam->next)
-         {
-           size += snprintf(&buf[size], bufsize-size, "<option>\"%s\", \"%s\"</option>\n", pparam->key, pparam->value);
-         }
-       size += snprintf(&buf[size], bufsize-size, "</select></td></tr>\n");
+    abuf_appendf(abuf,
+                   "<tr>\n"
+                   "<td>MTU: %d</td>\n"
+                   "<td>WLAN: %s</td>\n"
+                   "<td>STATUS: UP</td>\n"
+                   "</tr>\n",
+                   rifs->int_mtu,
+                   rifs->is_wireless ? "Yes" : "No");
+  }
+  abuf_puts(abuf, "</table>\n");
+
+  abuf_appendf(abuf,
+                 "<em>Olsrd is configured to %s if no interfaces are available</em><br>\n",
+                 olsr_cnf->allow_no_interfaces ? "run even" : "halt");
+
+  abuf_puts(abuf, "<h2>Plugins</h2>\n");
+  abuf_puts(abuf, "<table width=\"100%%\" border=\"0\"><tr><th>Name</th><th>Parameters</th></tr>\n");
+  for (pentry = olsr_cnf->plugins; pentry; pentry = pentry->next) {
+    abuf_appendf(abuf,
+                   "<tr><td>%s</td>\n"
+                   "<td><select>\n"
+                   "<option>KEY, VALUE</option>\n",
+                   pentry->name);
+
+    for (pparam = pentry->params; pparam; pparam = pparam->next) {
+      abuf_appendf(abuf, "<option>\"%s\", \"%s\"</option>\n", pparam->key, pparam->value);
+    }
+    abuf_puts(abuf, "</select></td></tr>\n");
 
-      }
-    size += snprintf(&buf[size], bufsize-size, "</table>\n");
-
-    size += section_title(&buf[size], bufsize-size, "Announced HNA entries");
-    if (olsr_cnf->hna_entries) {
-      struct ip_prefix_list *hna;
-      size += snprintf(&buf[size], bufsize-size, "<tr><th>Network</th></tr>\n");
-      for (hna = olsr_cnf->hna_entries; hna; hna = hna->next) {
-        struct ipprefix_str netbuf;
-        size += snprintf(&buf[size], bufsize-size,
-                         "<tr><td>%s</td></tr>\n",
-                         olsr_ip_prefix_to_string(&netbuf, &hna->net));
-      }
-    } else {
-      size += snprintf(&buf[size], bufsize-size, "<tr><td></td></tr>\n");
+  }
+  abuf_puts(abuf, "</table>\n");
+
+  section_title(abuf, "Announced HNA entries");
+  if (olsr_cnf->hna_entries) {
+    struct ip_prefix_list *hna;
+    abuf_puts(abuf, "<tr><th>Network</th></tr>\n");
+    for (hna = olsr_cnf->hna_entries; hna; hna = hna->next) {
+      struct ipprefix_str netbuf;
+      abuf_appendf(abuf,
+                     "<tr><td>%s</td></tr>\n",
+                     olsr_ip_prefix_to_string(&netbuf, &hna->net));
     }
-    size += snprintf(&buf[size], bufsize-size, "</table>\n");
-    return size;
+  } else {
+    abuf_puts(abuf, "<tr><td></td></tr>\n");
+  }
+  abuf_puts(abuf, "</table>\n");
 }
 
-
-
-static int build_neigh_body(char *buf, olsr_u32_t bufsize)
+static void build_neigh_body(struct autobuf *abuf)
 {
   struct neighbor_entry *neigh;
   struct link_entry *lnk;
-  int size = 0;
   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
 
-  size += section_title(&buf[size], bufsize-size, "Links");
+  section_title(abuf, "Links");
 
-  size += snprintf(&buf[size], bufsize-size,
+  abuf_appendf(abuf,
                    "<tr><th align=\"center\"%s>Local IP</th><th align=\"center\"%s>Remote IP</th><th align=\"right\">Hysteresis</th>", colspan, colspan);
   if (olsr_cnf->lq_level > 0) {
-    size += snprintf(&buf[size], bufsize-size,
+    abuf_puts(abuf,
                      "<th align=\"right\">LinkCost</th>");
   }
-  size += snprintf(&buf[size], bufsize-size, "</tr>\n");
+  abuf_puts(abuf, "</tr>\n");
 
   /* Link set */
   OLSR_FOR_ALL_LINK_ENTRIES(lnk) {
-    size += snprintf(&buf[size], bufsize-size, "<tr>");
-    size += build_ipaddr_with_link(&buf[size], bufsize, &lnk->local_iface_addr, -1);
-    size += build_ipaddr_with_link(&buf[size], bufsize, &lnk->neighbor_iface_addr, -1);
-    size += snprintf(&buf[size], bufsize-size, "<td align=\"right\">%0.2f</td>", lnk->L_link_quality);
+    abuf_puts(abuf, "<tr>");
+    build_ipaddr_with_link(abuf, &lnk->local_iface_addr, -1);
+    build_ipaddr_with_link(abuf, &lnk->neighbor_iface_addr, -1);
+    abuf_appendf(abuf, "<td align=\"right\">%0.2f</td>", lnk->L_link_quality);
     if (olsr_cnf->lq_level > 0) {
       struct lqtextbuffer lqbuffer1, lqbuffer2;
-      size += snprintf(&buf[size], bufsize-size,
+      abuf_appendf(abuf,
                        "<td align=\"right\">(%s) %s</td>",
                        get_link_entry_text(lnk, '/', &lqbuffer1),
                        get_linkcost_text(lnk->linkcost, OLSR_FALSE, &lqbuffer2));
     }
-    size += snprintf(&buf[size], bufsize-size, "</tr>\n");
+    abuf_puts(abuf, "</tr>\n");
   } OLSR_FOR_ALL_LINK_ENTRIES_END(lnk);
 
-  size += snprintf(&buf[size], bufsize-size, "</table>\n");
+  abuf_puts(abuf, "</table>\n");
 
-  size += section_title(&buf[size], bufsize-size, "Neighbors");
-  size += snprintf(&buf[size], bufsize-size,
+  section_title(abuf, "Neighbors");
+  abuf_appendf(abuf,
                    "<tr><th align=\"center\"%s>IP Address</th><th align=\"center\">SYM</th><th align=\"center\">MPR</th><th align=\"center\">MPRS</th><th align=\"center\">Willingness</th><th>2 Hop Neighbors</th></tr>\n", colspan);
   /* Neighbors */
   OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
     struct neighbor_2_list_entry *list_2;
     int thop_cnt;
-    size += snprintf(&buf[size], bufsize-size, "<tr>");
-    size += build_ipaddr_with_link(&buf[size], bufsize, &neigh->neighbor_main_addr, -1);
-    size += snprintf(&buf[size], bufsize-size,
+    abuf_puts(abuf, "<tr>");
+    build_ipaddr_with_link(abuf, &neigh->neighbor_main_addr, -1);
+    abuf_appendf(abuf,
                      "<td align=\"center\">%s</td>"
                      "<td align=\"center\">%s</td>"
                      "<td align=\"center\">%s</td>"
@@ -1011,7 +986,7 @@ static int build_neigh_body(char *buf, olsr_u32_t bufsize)
                      olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO",
                      neigh->willingness);
 
-    size += snprintf(&buf[size], bufsize-size, "<td><select>\n"
+    abuf_puts(abuf, "<td><select>\n"
                      "<option>IP ADDRESS</option>\n");
 
 
@@ -1019,106 +994,95 @@ static int build_neigh_body(char *buf, olsr_u32_t bufsize)
          list_2 != &neigh->neighbor_2_list;
          list_2 = list_2->next, thop_cnt++) {
       struct ipaddr_str strbuf;
-      size += snprintf(&buf[size], bufsize-size, "<option>%s</option>\n",
+      abuf_appendf(abuf, "<option>%s</option>\n",
                        olsr_ip_to_string(&strbuf, &list_2->neighbor_2->neighbor_2_addr));
     }
-    size += snprintf(&buf[size], bufsize-size, "</select> (%d)</td></tr>\n", thop_cnt);
+    abuf_appendf(abuf, "</select> (%d)</td></tr>\n", thop_cnt);
   } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
 
-  size += snprintf(&buf[size], bufsize-size, "</table>\n");
-  return size;
+  abuf_puts(abuf, "</table>\n");
 }
 
-static int build_topo_body(char *buf, olsr_u32_t bufsize)
+static void build_topo_body(struct autobuf *abuf)
 {
-  int size = 0;
   struct tc_entry *tc;
   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
 
-  size += section_title(&buf[size], bufsize-size, "Topology Entries");
-  size += snprintf(&buf[size], bufsize-size, "<tr><th align=\"center\"%s>Destination IP</th><th align=\"center\"%s>Last Hop IP</th>", colspan, colspan);
+  section_title(abuf, "Topology Entries");
+  abuf_appendf(abuf, "<tr><th align=\"center\"%s>Destination IP</th><th align=\"center\"%s>Last Hop IP</th>", colspan, colspan);
   if (olsr_cnf->lq_level > 0) {
-    size += snprintf(&buf[size], bufsize-size, "<th colspan=\"3\" align=\"right\">Linkcost</th>");
+    abuf_puts(abuf, "<th colspan=\"3\" align=\"right\">Linkcost</th>");
   }
-  size += snprintf(&buf[size], bufsize-size, "</tr>\n");
+  abuf_puts(abuf, "</tr>\n");
 
   OLSR_FOR_ALL_TC_ENTRIES(tc) {
       struct tc_edge_entry *tc_edge;
       OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
        if (tc_edge->edge_inv)  {
-          size += snprintf(&buf[size], bufsize-size, "<tr>");
-          size += build_ipaddr_with_link(&buf[size], bufsize, &tc_edge->T_dest_addr, -1);
-          size += build_ipaddr_with_link(&buf[size], bufsize, &tc->addr, -1);
+          abuf_puts(abuf, "<tr>");
+          build_ipaddr_with_link(abuf, &tc_edge->T_dest_addr, -1);
+          build_ipaddr_with_link(abuf, &tc->addr, -1);
           if (olsr_cnf->lq_level > 0) {
             struct lqtextbuffer lqbuffer1, lqbuffer2;
-           size += snprintf(&buf[size], bufsize-size,
+           abuf_appendf(abuf,
                             "<td align=\"right\">(%s)</td><td>&nbsp;</td><td align=\"left\">%s</td>\n",
                             get_tc_edge_entry_text(tc_edge, '/', &lqbuffer1),
                             get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer2));
           }
-          size += snprintf(&buf[size], bufsize-size, "</tr>\n");
+          abuf_puts(abuf, "</tr>\n");
        }
       } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
   } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
 
-  size += snprintf(&buf[size], bufsize-size, "</table>\n");
-
-  return size;
+  abuf_puts(abuf, "</table>\n");
 }
 
-static int build_mid_body(char *buf, olsr_u32_t bufsize)
+static void build_mid_body(struct autobuf *abuf)
 {
-  int size = 0;
   struct tc_entry *tc;
   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
 
-  size += section_title(&buf[size], bufsize-size, "MID Entries");
-  size += snprintf(&buf[size], bufsize-size,
-                   "<tr><th align=\"center\"%s>Main Address</th><th>Aliases</th></tr>\n", colspan);
+  section_title(abuf, "MID Entries");
+  abuf_appendf(abuf,
+                 "<tr><th align=\"center\"%s>Main Address</th><th>Aliases</th></tr>\n", colspan);
 
   /* MID */
   OLSR_FOR_ALL_TC_ENTRIES(tc) {
     struct mid_entry *alias;
-    size += snprintf(&buf[size], bufsize-size, "<tr>");
-    size += build_ipaddr_with_link(&buf[size], bufsize, &tc->addr, -1);
-    size += snprintf(&buf[size], bufsize-size, "<td><select>\n<option>IP ADDRESS</option>\n");
+    abuf_puts(abuf, "<tr>");
+    build_ipaddr_with_link(abuf, &tc->addr, -1);
+    abuf_puts(abuf, "<td><select>\n<option>IP ADDRESS</option>\n");
 
     OLSR_FOR_ALL_TC_MID_ENTRIES(tc, alias) {
       struct ipaddr_str strbuf;
-      size += snprintf(&buf[size], bufsize-size, "<option>%s</option>\n",
+      abuf_appendf(abuf, "<option>%s</option>\n",
                       olsr_ip_to_string(&strbuf, &alias->mid_alias_addr));
     } OLSR_FOR_ALL_TC_MID_ENTRIES_END(tc, alias);
-    size += snprintf(&buf[size], bufsize-size, "</select> (%d)</td></tr>\n",
-                    tc->mid_tree.count);
+    abuf_appendf(abuf, "</select> (%d)</td></tr>\n", tc->mid_tree.count);
   } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
 
-  size += snprintf(&buf[size], bufsize-size, "</table>\n");
-  return size;
+  abuf_puts(abuf, "</table>\n");
 }
 
 
-static int build_nodes_body(char *buf, olsr_u32_t bufsize)
+static void build_nodes_body(struct autobuf *abuf)
 {
-  int size = 0;
-  size += build_neigh_body(&buf[size], bufsize-size);
-  size += build_topo_body(&buf[size], bufsize-size);
-  size += build_mid_body(&buf[size], bufsize-size);
-  return size;
+  build_neigh_body(abuf);
+  build_topo_body(abuf);
+  build_mid_body(abuf);
 }
 
-static int build_all_body(char *buf, olsr_u32_t bufsize)
+static void build_all_body(struct autobuf *abuf)
 {
-  int size = 0;
-  size += build_config_body(&buf[size], bufsize-size);
-  size += build_routes_body(&buf[size], bufsize-size);
-  size += build_nodes_body(&buf[size], bufsize-size);
-  return size;
+  build_config_body(abuf);
+  build_routes_body(abuf);
+  build_nodes_body(abuf);
 }
 
 
-static int build_about_body(char *buf, olsr_u32_t bufsize)
+static void build_about_body(struct autobuf *abuf)
 {
-  return snprintf(buf, bufsize,
+  abuf_appendf(abuf,
                   "<strong>" PLUGIN_NAME " version " PLUGIN_VERSION "</strong><br/>\n"
                   "by Andreas T&oslash;nnesen (C)2005.<br/>\n"
                   "Compiled "
@@ -1161,11 +1125,9 @@ static int build_about_body(char *buf, olsr_u32_t bufsize)
                   build_date, build_host);
 }
 
-static int build_cfgfile_body(char *buf, olsr_u32_t bufsize)
+static void build_cfgfile_body(struct autobuf *abuf)
 {
-  int size = 0;
-
-  size += snprintf(&buf[size], bufsize-size,
+  abuf_puts(abuf,
                    "\n\n"
                    "<strong>This is an automatically generated configuration\n"
                    "file based on the current olsrd configuration of this node.</strong><br/>\n"
@@ -1182,19 +1144,14 @@ static int build_cfgfile_body(char *buf, olsr_u32_t bufsize)
         snprintf(&buf[size], bufsize-size, tmpBuf);
   }
 #else
-  size += olsrd_write_cnf_buf(olsr_cnf, OLSR_TRUE, &buf[size], bufsize-size);
+  olsrd_write_cnf_buf(abuf, olsr_cnf, OLSR_TRUE);
 #endif
 
-  if (size < 0) {
-    size = snprintf(buf, size, "ERROR GENERATING CONFIGFILE!\n");
-  }
-
-  size += snprintf(&buf[size], bufsize-size, "</pre>\n<hr/>\n");
+  abuf_puts(abuf, "</pre>\n<hr/>\n");
 
 #if 0
   printf("RETURNING %d\n", size);
 #endif
-  return size;
 }
 
 static int check_allowed_ip(const struct allowed_net * const all_nets, const union olsr_ip_addr * const addr)
index a9a13c6..8394dad 100644 (file)
@@ -47,6 +47,7 @@
 
 #include "olsrd_plugin.h"
 #include "plugin_util.h"
+#include "common/autobuf.h"
 
 
 #define HTTP_VERSION "HTTP/1.1"
@@ -60,6 +61,8 @@
 #define HTTP_400_MSG "<html><h1>400 - ERROR</h1><hr><i>" PLUGIN_NAME " version " PLUGIN_VERSION  "</i></html>"
 #define HTTP_404_MSG "<html><h1>404 - ERROR, no such file</h1><hr>This server does not support file requests!<br><br><i>" PLUGIN_NAME " version " PLUGIN_VERSION  "</i></html>"
 
+typedef int (*process_data_func)(char*, olsr_u32_t, struct autobuf *abuf);
+
 
 typedef enum {
     HTTP_BAD_REQ,
@@ -75,8 +78,6 @@ struct http_stats {
     olsr_u32_t ill_hits;
 };
 
-extern struct olsrd_config *olsr_cfg;
-
 /* Destructor function */
 void olsr_plugin_exit(void);
 void olsr_plugin_exit(void);
index 88cc492..9c9bfd9 100644 (file)
@@ -45,7 +45,6 @@
 /*
  * Dynamic linked library for the olsr.org olsr daemon
  */
 #include "olsrd_txtinfo.h"
 #include "olsr.h"
 #include "ipcalc.h"
@@ -58,8 +57,9 @@
 #include "routing_table.h"
 #include "log.h"
 
+#include "common/autobuf.h"
+
 #include <errno.h>
-#include <stdarg.h>
 #include <unistd.h>
 #include <fcntl.h>
 
 #endif
 
 
-#define RESPCHUNK      4096
 struct ipc_conn {
-    int resplen;
-    int respsize;
+    struct autobuf resp;
     int respstart;
-    char *resp;
     int requlen;
     char requ[256];
 };
@@ -93,7 +90,7 @@ struct ipc_conn {
 static int ipc_socket = -1;
 
 
-static void conn_destroy(struct ipc_conn *conn);
+static void conn_destroy(struct ipc_conn *);
 
 static int set_nonblocking(int);
 
@@ -117,12 +114,11 @@ static int ipc_print_routes(struct ipc_conn *);
 
 static int ipc_print_topology(struct ipc_conn *);
 
+static int ipc_print_hna_entry(struct autobuf *, const struct olsr_ip_prefix *, const union olsr_ip_addr *);
 static int ipc_print_hna(struct ipc_conn *);
 
 static int ipc_print_mid(struct ipc_conn *);
 
-static int ipc_sendf(struct ipc_conn *, const char *, ...) __attribute__((format(printf, 2, 3)));
-
 #define isprefix(str, pre) (strncmp((str), (pre), strlen(pre)) == 0)
 
 #define SIW_NEIGH      (1 << 0)
@@ -131,7 +127,6 @@ static int ipc_sendf(struct ipc_conn *, const char *, ...) __attribute__((format
 #define SIW_HNA                (1 << 3)
 #define SIW_MID                (1 << 4)
 #define SIW_TOPO       (1 << 5)
-#define SIW_NEIGHLINK  (SIW_LINK|SIW_NEIGH)
 #define SIW_ALL                (SIW_NEIGH|SIW_LINK|SIW_ROUTE|SIW_HNA|SIW_MID|SIW_TOPO)
 
 /**
@@ -185,7 +180,7 @@ olsrd_plugin_init(void)
     if (olsr_cnf->ip_version == AF_INET) {
         struct sockaddr_in *addr4 = (struct sockaddr_in *)&sst;
         addr4->sin_family = AF_INET;
-        addrlen = sizeof(struct sockaddr_in);
+        addrlen = sizeof(*addr4);
 #ifdef SIN6_LEN
         addr4->sin_len = addrlen;
 #endif
@@ -194,7 +189,7 @@ olsrd_plugin_init(void)
     } else {
         struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&sst;
         addr6->sin6_family = AF_INET6;
-        addrlen = sizeof(struct sockaddr_in6);
+        addrlen = sizeof(*addr6);
 #ifdef SIN6_LEN
         addr6->sin6_len = addrlen;
 #endif
@@ -203,7 +198,7 @@ olsrd_plugin_init(void)
     }
       
     /* bind the socket to the port number */
-    if (bind(ipc_socket, (struct sockaddr *) &sst, addrlen) == -1) {
+    if (bind(ipc_socket, (struct sockaddr *)&sst, addrlen) == -1) {
 #ifndef NODEBUG
         olsr_printf(1, "(TXTINFO) bind()=%s\n", strerror(errno));
 #endif
@@ -232,14 +227,14 @@ olsrd_plugin_init(void)
 /* destroy the connection */
 static void conn_destroy(struct ipc_conn *conn)
 {
-    free(conn->resp);
+    free(conn->resp.buf);
     free(conn);
 }
 
 static void kill_connection(int fd, struct ipc_conn *conn)
 {
     remove_olsr_socket(fd, NULL, &ipc_http);
-    close(fd);
+    CLOSE(fd);
     conn_destroy(conn);
 }
 
@@ -291,7 +286,7 @@ static void ipc_action(int fd, void *data __attribute__((unused)), unsigned int
         }
         if (!ip4equal(&addr4->sin_addr, &ipc_accept_ip.v4)) {
             olsr_printf(1, "(TXTINFO) From host(%s) not allowed!\n", addr);
-            close(ipc_connection);
+            CLOSE(ipc_connection);
             return;
         }
     } else {
@@ -303,7 +298,7 @@ static void ipc_action(int fd, void *data __attribute__((unused)), unsigned int
         if (!ip6equal(&in6addr_any, &ipc_accept_ip.v6) &&
            !ip6equal(&addr6->sin6_addr, &ipc_accept_ip.v6)) {
             olsr_printf(1, "(TXTINFO) From host(%s) not allowed!\n", addr);
-            close(ipc_connection);
+            CLOSE(ipc_connection);
             return;
         }
     }
@@ -313,29 +308,20 @@ static void ipc_action(int fd, void *data __attribute__((unused)), unsigned int
     
     /* make the fd non-blocking */
     if (set_nonblocking(ipc_connection) < 0) {
-        close(ipc_connection);
+        CLOSE(ipc_connection);
         return;
     }
 
     conn = malloc(sizeof(*conn));
     if (conn == NULL) {
         olsr_syslog(OLSR_LOG_ERR, "(TXTINFO) Out of memory!");
-        close(ipc_connection);
+        CLOSE(ipc_connection);
         return;
     }
     conn->requlen = 0;
     *conn->requ = '\0';
-    conn->resplen = 0;
     conn->respstart = 0;
-    conn->respsize = RESPCHUNK;
-    conn->resp = malloc(conn->respsize);
-    if (conn->resp == NULL) {
-        olsr_syslog(OLSR_LOG_ERR, "(TXTINFO) Out of memory!");
-        close(ipc_connection);
-        free(conn);
-        return;
-    }
-    *conn->resp = '\0';
+    abuf_init(&conn->resp, 1000);
     add_olsr_socket(ipc_connection, NULL, &ipc_http, conn, SP_IMM_READ);
 }
 
@@ -349,7 +335,7 @@ static void ipc_http_read_dummy(int fd, struct ipc_conn *conn)
     } while (bytes_read > 0);
     if (bytes_read == 0) {
         /* EOF */
-        if (conn->respstart < conn->resplen && conn->resplen > 0) {
+        if (conn->respstart < conn->resp.len && conn->resp.len > 0) {
             disable_olsr_socket(fd, NULL, &ipc_http, SP_IMM_READ);
             conn->requlen = -1;
             return;
@@ -384,7 +370,7 @@ static void ipc_http_read(int fd, struct ipc_conn *conn)
         /* we didn't get all. Wait for more data. */
         return;
     }
-    if (isprefix(p, "/neighbours")) send_what=SIW_NEIGHLINK;
+    if (isprefix(p, "/neighbours")) send_what=SIW_LINK|SIW_NEIGH;
     else if (isprefix(p, "/neigh")) send_what=SIW_NEIGH;
     else if (isprefix(p, "/link")) send_what=SIW_LINK;
     else if (isprefix(p, "/route")) send_what=SIW_ROUTE;
@@ -402,7 +388,7 @@ static void ipc_http_read(int fd, struct ipc_conn *conn)
 
 static void ipc_http_write(int fd, struct ipc_conn *conn)
 {
-    ssize_t bytes_written = write(fd, conn->resp+conn->respstart, conn->resplen-conn->respstart);
+    ssize_t bytes_written = write(fd, conn->resp.buf+conn->respstart, conn->resp.len-conn->respstart);
     if (bytes_written < 0) {
         if (errno == EINTR || errno == EAGAIN) {
             return;
@@ -412,7 +398,7 @@ static void ipc_http_write(int fd, struct ipc_conn *conn)
         return;
     }
     conn->respstart += bytes_written;
-    if (conn->respstart >= conn->resplen) {
+    if (conn->respstart >= conn->resp.len) {
         /* we are done. */
         if (conn->requlen < 0) {
             /* we are completely done. */
@@ -429,7 +415,7 @@ static void ipc_http(int fd, void *data, unsigned int flags)
 {
     struct ipc_conn *conn = data;
     if ((flags & SP_IMM_READ) != 0) {
-        if (conn->resplen > 0) {
+        if (conn->resp.len > 0) {
             ipc_http_read_dummy(fd, conn);
         } else {
             ipc_http_read(fd, conn);
@@ -445,7 +431,7 @@ static int ipc_print_neigh(struct ipc_conn *conn)
 {
     struct neighbor_entry *neigh;
 
-    if (ipc_sendf(conn, "Table: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWill.\t2 Hop Neighbors\n") < 0) {
+    if (abuf_appendf(&conn->resp, "Table: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWill.\t2 Hop Neighbors\n") < 0) {
         return -1;
     }
 
@@ -459,18 +445,18 @@ static int ipc_print_neigh(struct ipc_conn *conn)
              list_2 = list_2->next) {
             thop_cnt++;
         }
-        if (ipc_sendf(conn,
-                      "%s\t%s\t%s\t%s\t%d\t%d\n",
-                      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) {
+        if (abuf_appendf(&conn->resp,
+                            "%s\t%s\t%s\t%s\t%d\t%d\n",
+                            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) {
             return -1;
         }
     } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
-    if (ipc_sendf(conn, "\n") < 0) {
+    if (abuf_appendf(&conn->resp, "\n") < 0) {
         return -1;
     }
     return 0;
@@ -480,7 +466,7 @@ static int ipc_print_link(struct ipc_conn *conn)
 {
     struct link_entry *lnk;
 
-    if (ipc_sendf(conn, "Table: Links\nLocal IP\tRemote IP\tHyst.\tLQ\tNLQ\tCost\n") < 0) {
+    if (abuf_appendf(&conn->resp, "Table: Links\nLocal IP\tRemote IP\tHyst.\tLQ\tNLQ\tCost\n") < 0) {
         return -1;
     }
 
@@ -488,18 +474,18 @@ static int ipc_print_link(struct ipc_conn *conn)
     OLSR_FOR_ALL_LINK_ENTRIES(lnk) {
         struct ipaddr_str buf1, buf2;
         struct lqtextbuffer lqbuffer1, lqbuffer2;
-       if (ipc_sendf(conn,
-                      "%s\t%s\t%0.2f\t%s\t%s\t\n",
-                      olsr_ip_to_string(&buf1, &lnk->local_iface_addr),
-                      olsr_ip_to_string(&buf2, &lnk->neighbor_iface_addr),
-                      lnk->L_link_quality, 
-                      get_link_entry_text(lnk, '\t', &lqbuffer1),
-                      get_linkcost_text(lnk->linkcost, OLSR_FALSE, &lqbuffer2)) < 0) {
+       if (abuf_appendf(&conn->resp,
+                            "%s\t%s\t%0.2f\t%s\t%s\t\n",
+                            olsr_ip_to_string(&buf1, &lnk->local_iface_addr),
+                            olsr_ip_to_string(&buf2, &lnk->neighbor_iface_addr),
+                            lnk->L_link_quality, 
+                            get_link_entry_text(lnk, '\t', &lqbuffer1),
+                            get_linkcost_text(lnk->linkcost, OLSR_FALSE, &lqbuffer2)) < 0) {
             return -1;
         }
     } OLSR_FOR_ALL_LINK_ENTRIES_END(lnk);
 
-    if (ipc_sendf(conn, "\n") < 0) {
+    if (abuf_appendf(&conn->resp, "\n") < 0) {
         return -1;
     }
     return 0;
@@ -509,7 +495,7 @@ static int ipc_print_routes(struct ipc_conn *conn)
 {
     struct rt_entry *rt;
     
-    if (ipc_sendf(conn, "Table: Routes\nDestination\tGateway IP\tMetric\tETX\tInterface\n") < 0) {
+    if (abuf_appendf(&conn->resp, "Table: Routes\nDestination\tGateway IP\tMetric\tETX\tInterface\n") < 0) {
         return -1;
     }
 
@@ -518,18 +504,18 @@ static int ipc_print_routes(struct ipc_conn *conn)
         struct ipaddr_str buf;
         struct ipprefix_str prefixstr;
         struct lqtextbuffer lqbuffer;
-        if (ipc_sendf(conn,
-                      "%s\t%s\t%d\t%s\t%s\t\n",
-                      olsr_ip_prefix_to_string(&prefixstr, &rt->rt_dst),
-                      olsr_ip_to_string(&buf, &rt->rt_best->rtp_nexthop.gateway),
-                      rt->rt_best->rtp_metric.hops,
-                      get_linkcost_text(rt->rt_best->rtp_metric.cost, OLSR_TRUE, &lqbuffer),
-                      if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index)) < 0) {
+        if (abuf_appendf(&conn->resp,
+                            "%s\t%s\t%d\t%s\t%s\t\n",
+                            olsr_ip_prefix_to_string(&prefixstr, &rt->rt_dst),
+                            olsr_ip_to_string(&buf, &rt->rt_best->rtp_nexthop.gateway),
+                            rt->rt_best->rtp_metric.hops,
+                            get_linkcost_text(rt->rt_best->rtp_metric.cost, OLSR_TRUE, &lqbuffer),
+                            if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index)) < 0) {
             return -1;
         }
     } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
 
-    if (ipc_sendf(conn, "\n") < 0) {
+    if (abuf_appendf(&conn->resp, "\n") < 0) {
         return -1;
     }
     return 0;
@@ -539,7 +525,7 @@ static int ipc_print_topology(struct ipc_conn *conn)
 {
     struct tc_entry *tc;
     
-    if (ipc_sendf(conn, "Table: Topology\nDest. IP\tLast hop IP\tLQ\tNLQ\tCost\n") < 0) {
+    if (abuf_appendf(&conn->resp, "Table: Topology\nDest. IP\tLast hop IP\tLQ\tNLQ\tCost\n") < 0) {
         return -1;
     }
 
@@ -547,44 +533,51 @@ static int ipc_print_topology(struct ipc_conn *conn)
     OLSR_FOR_ALL_TC_ENTRIES(tc) {
         struct tc_edge_entry *tc_edge;
         OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
-               if (tc_edge->edge_inv)  {
-            struct ipaddr_str dstbuf, addrbuf;
-            struct lqtextbuffer lqbuffer1, lqbuffer2;
-            if (ipc_sendf(conn,
-                          "%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), 
-                          get_tc_edge_entry_text(tc_edge, '\t', &lqbuffer1),
-                          get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer2)) < 0) {
-                return -1;
+            if (tc_edge->edge_inv)  {
+                struct ipaddr_str dstbuf, addrbuf;
+                struct lqtextbuffer lqbuffer1, lqbuffer2;
+                if (abuf_appendf(&conn->resp,
+                                    "%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), 
+                                    get_tc_edge_entry_text(tc_edge, '\t', &lqbuffer1),
+                                    get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer2)) < 0) {
+                    return -1;
+                }
             }
-               }
         } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
     } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
 
-    if (ipc_sendf(conn, "\n") < 0) {
+    if (abuf_appendf(&conn->resp, "\n") < 0) {
         return -1;
     }
     return 0;
 }
 
+static int ipc_print_hna_entry(struct autobuf *autobuf,
+                               const struct olsr_ip_prefix *hna_prefix,
+                               const union olsr_ip_addr *ipaddr)
+{
+    struct ipaddr_str mainaddrbuf;
+    struct ipprefix_str addrbuf;
+    return abuf_appendf(autobuf,
+                           "%s\t%s\n",
+                           olsr_ip_prefix_to_string(&addrbuf, hna_prefix),
+                           olsr_ip_to_string(&mainaddrbuf, ipaddr));
+}
+
 static int ipc_print_hna(struct ipc_conn *conn)
 {
     const struct ip_prefix_list *hna;
     struct tc_entry *tc;
-    struct ipaddr_str mainaddrbuf;
-    struct ipprefix_str addrbuf;
 
-    if (ipc_sendf(conn, "Table: HNA\nDestination\tGateway\n") < 0) {
+    if (abuf_appendf(&conn->resp, "Table: HNA\nDestination\tGateway\n") < 0) {
         return -1;
     }
 
     /* Announced HNA entries */
     for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
-        if (ipc_sendf(conn,
-                      "%s\t%s\n",
-                      olsr_ip_prefix_to_string(&addrbuf, &hna->net),
-                      olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr)) < 0) {
+        if (ipc_print_hna_entry(&conn->resp, &hna->net, &olsr_cnf->main_addr) < 0) {
             return -1;
         }
     }
@@ -594,16 +587,13 @@ static int ipc_print_hna(struct ipc_conn *conn)
         struct hna_net *tmp_net;
         /* Check all networks */
         OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, tmp_net) {
-            if (ipc_sendf(conn,
-                          "%s\t%s\n",
-                          olsr_ip_prefix_to_string(&addrbuf, &tmp_net->hna_prefix),
-                          olsr_ip_to_string(&mainaddrbuf, &tc->addr)) < 0) {
+            if (ipc_print_hna_entry(&conn->resp, &tmp_net->hna_prefix, &tc->addr) < 0) {
                 return -1;
             }
         } OLSR_FOR_ALL_TC_HNA_ENTRIES_END(tc, tmp_net);
     } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
 
-    if (ipc_sendf(conn, "\n") < 0) {
+    if (abuf_appendf(&conn->resp, "\n") < 0) {
         return -1;
     }
     return 0;
@@ -613,7 +603,7 @@ static int ipc_print_mid(struct ipc_conn *conn)
 {
     struct tc_entry *tc;
 
-    if (ipc_sendf(conn, "Table: MID\nIP address\tAliases\n") < 0) {
+    if (abuf_appendf(&conn->resp, "Table: MID\nIP address\tAliases\n") < 0) {
         return -1;
     }
 
@@ -622,21 +612,24 @@ static int ipc_print_mid(struct ipc_conn *conn)
         struct ipaddr_str buf;
         struct mid_entry *alias;
         char sep = '\t';
-        if (ipc_sendf(conn, "%s",  olsr_ip_to_string(&buf,  &tc->addr)) < 0) {
+        if (abuf_puts(&conn->resp,  olsr_ip_to_string(&buf, &tc->addr)) < 0) {
             return -1;
         }
 
         OLSR_FOR_ALL_TC_MID_ENTRIES(tc, alias) {
-            if (ipc_sendf(conn, "%c%s", sep, olsr_ip_to_string(&buf, &alias->mid_alias_addr)) < 0) {
+            if (abuf_appendf(&conn->resp,
+                                "%c%s",
+                                sep,
+                                olsr_ip_to_string(&buf, &alias->mid_alias_addr)) < 0) {
                 return -1;
             }
             sep = ';';
         }  OLSR_FOR_ALL_TC_MID_ENTRIES_END(tc, alias);
-        if (ipc_sendf(conn, "\n") < 0) {
+        if (abuf_appendf(&conn->resp, "\n") < 0) {
             return -1;
         }
     } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
-    if (ipc_sendf(conn, "\n") < 0) {
+    if (abuf_appendf(&conn->resp, "\n") < 0) {
         return -1;
     }
     return 0;
@@ -647,9 +640,9 @@ static int send_info(struct ipc_conn *conn, int send_what)
     int rv;
 
     /* Print minimal http header */
-    if (ipc_sendf(conn,
-                  "HTTP/1.0 200 OK\n"
-                  "Content-type: text/plain\n\n") < 0) {
+    if (abuf_appendf(&conn->resp,
+                        "HTTP/1.0 200 OK\n"
+                        "Content-type: text/plain\n\n") < 0) {
         return -1;
     }
  
@@ -657,15 +650,11 @@ static int send_info(struct ipc_conn *conn, int send_what)
        
     rv = 0;
      /* links + Neighbors */
-    if ((send_what & (SIW_NEIGHLINK|SIW_LINK)) != 0) {
-        if (ipc_print_link(conn) < 0) {
-            rv = -1;
-        }
+    if ((send_what & SIW_LINK) != 0 && ipc_print_link(conn) < 0) {
+        rv = -1;
     }
-    if ((send_what & (SIW_NEIGHLINK|SIW_NEIGH)) != 0) {
-        if (ipc_print_neigh(conn) < 0) {
-            rv = -1;
-        }
+    if ((send_what & SIW_NEIGH) != 0 && ipc_print_neigh(conn) < 0) {
+        rv = -1;
     }
      /* topology */
     if ((send_what & SIW_TOPO) != 0) {
@@ -687,41 +676,6 @@ static int send_info(struct ipc_conn *conn, int send_what)
 }
 
 /*
- * In a bigger mesh, there are probs with the fixed
- * bufsize. Because the Content-Length header is
- * optional, the sprintf() is changed to a more
- * scalable solution here.
- */ 
-static int ipc_sendf(struct ipc_conn *conn, const char* format, ...)
-{
-    va_list arg, arg2;
-    int rv;
-#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __MacOSX__
-#define flags 0
-#else
-#define flags MSG_NOSIGNAL
-#endif
-    va_start(arg, format);
-    va_copy(arg2, arg);
-    rv = vsnprintf(conn->resp+conn->resplen, conn->respsize-conn->resplen, format, arg);
-    va_end(arg);
-    if (conn->resplen + rv >= conn->respsize) {
-        char *p;
-        conn->respsize += RESPCHUNK;
-        p = realloc(conn->resp, conn->respsize);
-        if (p == NULL) {
-            olsr_syslog(OLSR_LOG_ERR, "(TXTINFO) Out of memory!");
-            return -1;
-        }
-        conn->resp = p;
-        vsnprintf(conn->resp+conn->resplen, conn->respsize-conn->resplen, format, arg2);
-    }
-    va_end(arg2);
-    conn->resplen += rv;
-    return 0;
-}
-
-/*
  * Local Variables:
  * mode: c
  * style: linux
index 9a58610..87496c7 100644 (file)
@@ -39,6 +39,7 @@
  */
 
 #include "olsrd_conf.h"
+#include "../olsr_cfg.h"
 #include "../ipcalc.h"
 #include "../net_olsr.h"
 
 int
 olsrd_write_cnf(const struct olsrd_config *cnf, const char *fname)
 {
-  char buf[10000];
+  struct autobuf abuf;
   FILE *fd = fopen(fname, "w");
-  if(fd == NULL) {
+  if (fd == NULL) {
     fprintf(stderr, "Could not open file %s for writing\n%s\n", fname, strerror(errno));
     return -1;
   }
 
   printf("Writing config to file \"%s\".... ", fname);
 
-  olsrd_write_cnf_buf(cnf, OLSR_FALSE, buf, sizeof(buf));
-  fputs(buf, fd);
+  abuf_init(&abuf, 0);
+  olsrd_write_cnf_buf(&abuf, cnf, OLSR_FALSE);
+  fputs(abuf.buf, fd);
 
+  abuf_free(&abuf);
   fclose(fd);
   printf("DONE\n");
 
   return 1;
 }
 
-#define MAX_LINESIZE 250
-
-#define WRITE_TO_BUF(fmt, args...)                                      \
-    do {                                                                \
-        if((bufsize - size) < MAX_LINESIZE) {                           \
-            return -1;                                                  \
-        }                                                               \
-        size += snprintf(&buf[size], MAX_LINESIZE, fmt, ##args);        \
-    } while (0)
-
-int
-olsrd_write_cnf_buf(const struct olsrd_config *cnf, olsr_bool write_more_comments, char *buf, olsr_u32_t bufsize)
+static INLINE void append_float(struct autobuf *abuf, const char *name, float val, float deflt, olsr_bool first)
 {
-  struct ip_prefix_list   *h  = cnf->hna_entries;
-  struct olsr_if           *in = cnf->interfaces;
-  struct plugin_entry      *pe = cnf->plugins;
-  struct plugin_param      *pp;
-  struct ip_prefix_list    *ie = cnf->ipc_nets;
-  struct olsr_lq_mult      *mult;
-
-  int size = 0;
-
-  char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
-
-  if (buf == NULL || bufsize < MAX_LINESIZE) {
-      return -1;
+  if (val != deflt) {
+    abuf_appendf(abuf, "    %s\t%0.2f\n", name, val);
+  } else if (first) {
+    abuf_appendf(abuf, "    #%s\t%0.2f\n", name, val);
   }
+}
 
-  WRITE_TO_BUF("#\n# Configuration file for %s\n# automatically generated by olsrd-cnf parser v.  %s\n#\n\n", olsrd_version, PARSER_VERSION);
+void
+olsrd_write_cnf_buf(struct autobuf *abuf, const struct olsrd_config *cnf, olsr_bool write_more_comments)
+{
+  char ipv6_buf[INET6_ADDRSTRLEN];             /* buffer for IPv6 inet_ntop */
+
+  abuf_appendf(abuf, "#\n"
+                        "# Configuration file for %s\n"
+                        "# automatically generated by olsrd-cnf parser v.  %s\n"
+                        "#\n\n", olsrd_version, PARSER_VERSION);
 
   /* Debug level */
-  WRITE_TO_BUF("# Debug level(0-9)\n# If set to 0 the daemon runs in the background\n\nDebugLevel\t%d\n\n", cnf->debug_level);
+  abuf_appendf(abuf, "# Debug level(0-9)\n"
+                        "# If set to 0 the daemon runs in the background\n"
+                        "DebugLevel\t%d\n\n", cnf->debug_level);
 
   /* IP version */
-  WRITE_TO_BUF("# IP version to use (4 or 6)\n\nIpVersion\t%d\n\n", cnf->ip_version == AF_INET ? 4 : 6);
+  abuf_appendf(abuf, "# IP version to use (4 or 6)\n"
+                        "IpVersion\t%d\n\n", cnf->ip_version == AF_INET ? 4 : 6);
 
   /* FIB Metric */
-  WRITE_TO_BUF("# FIBMetric (\"%s\", \"%s\", or \"%s\")\n\nFIBMetric\t\"%s\"\n\n", CFG_FIBM_FLAT, CFG_FIBM_CORRECT, CFG_FIBM_APPROX,
-    FIBM_FLAT == cnf->fib_metric ? CFG_FIBM_FLAT : FIBM_CORRECT == cnf->fib_metric ? CFG_FIBM_CORRECT : CFG_FIBM_APPROX);
+  abuf_appendf(abuf, "# FIBMetric (\"%s\", \"%s\", or \"%s\")\n"
+                        "FIBMetric\t\"%s\"\n\n",
+                        CFG_FIBM_FLAT, CFG_FIBM_CORRECT, CFG_FIBM_APPROX,
+                        FIBM_FLAT == cnf->fib_metric ? CFG_FIBM_FLAT : FIBM_CORRECT == cnf->fib_metric ? CFG_FIBM_CORRECT : CFG_FIBM_APPROX);
 
   /* HNA IPv4/IPv6 */
-  WRITE_TO_BUF("# HNA IPv%d routes\n# syntax: netaddr/prefix\n\nHna%d {\n", cnf->ip_version == AF_INET ? 4 : 6, cnf->ip_version == AF_INET ? 4 : 6);
-  while(h) {
-    struct ipprefix_str strbuf;
-    WRITE_TO_BUF("    %s\n", olsr_ip_prefix_to_string(&strbuf, &h->net));
-    h = h->next;
+  abuf_appendf(abuf, "# HNA IPv%d routes\n"
+                        "# syntax: netaddr/prefix\n"
+                        "Hna%d {\n", cnf->ip_version == AF_INET ? 4 : 6, cnf->ip_version == AF_INET ? 4 : 6);
+  if (cnf->hna_entries) {
+    struct ip_prefix_list *h;
+    for (h  = cnf->hna_entries; h != NULL; h = h->next) {
+      struct ipprefix_str strbuf;
+      abuf_appendf(abuf, "    %s\n", olsr_ip_prefix_to_string(&strbuf, &h->net));
+    }
   }
-  WRITE_TO_BUF("}\n\n");
+  abuf_appendf(abuf, "}\n\n");
 
   /* No interfaces */
-  WRITE_TO_BUF("# Should olsrd keep on running even if there are\n# no interfaces available? This is a good idea\n# for a PCMCIA/USB hotswap environment.\n# \"yes\" OR \"no\"\n\nAllowNoInt\t");
-  if(cnf->allow_no_interfaces)
-    WRITE_TO_BUF("yes\n\n");
-  else
-    WRITE_TO_BUF("no\n\n");
+  abuf_appendf(abuf, "# Should olsrd keep on running even if there are\n"
+                        "# no interfaces available? This is a good idea\n"
+                        "# for a PCMCIA/USB hotswap environment.\n"
+                        "# \"yes\" OR \"no\"\n"
+                        "AllowNoInt\t%s\n\n", cnf->allow_no_interfaces ? "yes" : "no");
 
   /* TOS */
-  WRITE_TO_BUF("# TOS(type of service) to use. Default is 16\n\n");
-  WRITE_TO_BUF("TosValue\t%d\n\n", cnf->tos);
+  abuf_appendf(abuf, "# TOS(type of service) to use. Default is 16\n"
+                         "TosValue\t%d\n\n", cnf->tos);
 
   /* RtTable */
-  WRITE_TO_BUF("# Policy Routing Table to use. Default is 254\n\n");
-  WRITE_TO_BUF("RtTable\t\t%d\n\n", cnf->rttable);
+  abuf_appendf(abuf, "# Policy Routing Table to use. Default is 254\n"
+                        "RtTable\t\t%d\n\n", cnf->rttable);
 
   /* RtTableDefault */
-  WRITE_TO_BUF("# Policy Routing Table to use for the default Route. Default is 0 (Take the same table as specified by RtTable)\n\n");
-  WRITE_TO_BUF("RtTableDefault\t\t%d\n\n", cnf->rttable_default);
+  abuf_appendf(abuf, "# Policy Routing Table to use for the default Route. Default is 0 (Take the same table as specified by RtTable)\n"
+                        "RtTableDefault\t\t%d\n\n", cnf->rttable_default);
 
   /* Willingness */
-  WRITE_TO_BUF("# The fixed willingness to use(0-7)\n# If not set willingness will be calculated\n# dynammically based on battery/power status\n\n");
-  if(cnf->willingness_auto)
-    WRITE_TO_BUF("#Willingness\t4\n\n");
-  else
-    WRITE_TO_BUF("Willingness\t%d\n\n", cnf->willingness);
+  abuf_appendf(abuf, "# The fixed willingness to use(0-7)\n"
+                        "# If not set willingness will be calculated\n"
+                        "# dynammically based on battery/power status\n"
+                        "%sWillingness\t%d\n\n", cnf->willingness_auto ? "#" : "", cnf->willingness_auto ? 4 : cnf->willingness);
 
   /* IPC */
-  WRITE_TO_BUF("# Allow processes like the GUI front-end\n# to connect to the daemon.\n\n");
-  WRITE_TO_BUF("IpcConnect {\n");
-  WRITE_TO_BUF("    MaxConnections\t%d\n", cnf->ipc_connections);
-
-  while (ie) {
-    if (ie->net.prefix_len == olsr_cnf->maxplen) {
-      struct ipaddr_str strbuf;
-      WRITE_TO_BUF("    Host\t\t%s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
-    } else {
-      struct ipprefix_str strbuf;
-      WRITE_TO_BUF("    Net\t\t\t%s\n", olsr_ip_prefix_to_string(&strbuf, &ie->net));
+  abuf_appendf(abuf, "# Allow processes like the GUI front-end\n"
+                        "# to connect to the daemon.\n"
+                        "IpcConnect {\n"
+                        "    MaxConnections\t%d\n", cnf->ipc_connections);
+
+  if (cnf->ipc_nets) {
+    struct ip_prefix_list *ie;
+    for (ie = cnf->ipc_nets; ie != NULL; ie = ie->next) {
+      if (ie->net.prefix_len == olsr_cnf->maxplen) {
+        struct ipaddr_str strbuf;
+        abuf_appendf(abuf, "    Host\t\t%s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
+      } else {
+        struct ipprefix_str strbuf;
+        abuf_appendf(abuf, "    Net\t\t\t%s\n", olsr_ip_prefix_to_string(&strbuf, &ie->net));
+      }
     }
-    ie = ie->next;
   }
 
-  WRITE_TO_BUF("}\n\n");
+  abuf_appendf(abuf, "}\n");
 
   /* Hysteresis */
-  WRITE_TO_BUF("# Hysteresis adds more robustness to the\n# link sensing.\n# Used by default. 'yes' or 'no'\n\n");
-
-  if(cnf->use_hysteresis)
-    {
-      WRITE_TO_BUF("UseHysteresis\tyes\n\n");
-      WRITE_TO_BUF("# Hysteresis parameters\n# Do not alter these unless you know \n# what you are doing!\n# Set to auto by default. Allowed\n# values are floating point values\n# in the interval 0,1\n# THR_LOW must always be lower than\n# THR_HIGH!!\n\n");
-      WRITE_TO_BUF("HystScaling\t%0.2f\n", cnf->hysteresis_param.scaling);
-      WRITE_TO_BUF("HystThrHigh\t%0.2f\n", cnf->hysteresis_param.thr_high);
-      WRITE_TO_BUF("HystThrLow\t%0.2f\n\n", cnf->hysteresis_param.thr_low);
-    }
-  else
-    {
-      WRITE_TO_BUF("UseHysteresis\tno\n\n");
-      WRITE_TO_BUF("# Hysteresis parameters\n# Do not alter these unless you know \n# what you are doing!\n# Set to auto by default. Allowed\n# values are floating point values\n# in the interval 0,1\n# THR_LOW must always be lower than\n# THR_HIGH!!\n\n");
-      WRITE_TO_BUF("#HystScaling\t%0.2f\n", cnf->hysteresis_param.scaling);
-      WRITE_TO_BUF("#HystThrHigh\t%0.2f\n", cnf->hysteresis_param.thr_high);
-      WRITE_TO_BUF("#HystThrLow\t%0.2f\n\n", cnf->hysteresis_param.thr_low);
-    }
+  abuf_appendf(abuf, "# Hysteresis adds more robustness to the\n"
+                        "# link sensing.\n"
+                        "# Used by default. 'yes' or 'no'\n"
+                        "UseHysteresis\t%s\n\n", cnf->use_hysteresis ? "yes" : "no");
+
+  abuf_appendf(abuf, "# Hysteresis parameters\n"
+                        "# Do not alter these unless you know \n"
+                        "# what you are doing!\n"
+                        "# Set to auto by default. Allowed\n"
+                        "# values are floating point values\n"
+                        "# in the interval 0,1\n"
+                        "# THR_LOW must always be lower than\n"
+                        "# THR_HIGH!!\n"
+                        "%sHystScaling\t%0.2f\n"
+                        "%sHystThrHigh\t%0.2f\n"
+                        "%sHystThrLow\t%0.2f\n\n",
+                        cnf->use_hysteresis ? "#" : "", cnf->hysteresis_param.scaling,
+                        cnf->use_hysteresis ? "#" : "", cnf->hysteresis_param.thr_high,
+                        cnf->use_hysteresis ? "#" : "", cnf->hysteresis_param.thr_low);
 
   /* Pollrate */
-  WRITE_TO_BUF("# Polling rate in seconds(float).\n# Auto uses default value 0.05 sec\n\n");
-  WRITE_TO_BUF("Pollrate\t%0.2f\n", conv_pollrate_to_secs(cnf->pollrate));
+  abuf_appendf(abuf, "# Polling rate in seconds(float).\n"
+                        "# Auto uses default value 0.05 sec\n"
+                        "Pollrate\t%0.2f\n", conv_pollrate_to_secs(cnf->pollrate));
 
   /* NIC Changes Pollrate */
-  WRITE_TO_BUF("# Interval to poll network interfaces for configuration\n# changes. Defaults to 2.5 seconds\n");
-  WRITE_TO_BUF("NicChgsPollInt\t%0.2f\n", cnf->nic_chgs_pollrate);
+  abuf_appendf(abuf, "# Interval to poll network interfaces for configuration\n"
+                        "# changes. Defaults to 2.5 seconds\n"
+                        "NicChgsPollInt\t%0.2f\n", cnf->nic_chgs_pollrate);
 
   /* TC redundancy */
-  WRITE_TO_BUF("# TC redundancy\n# Specifies how much neighbor info should\n# be sent in TC messages\n# Possible values are:\n# 0 - only send MPR selectors\n# 1 - send MPR selectors and MPRs\n# 2 - send all neighbors\n#\n# defaults to 0\n\n");
-  WRITE_TO_BUF("TcRedundancy\t%d\n\n", cnf->tc_redundancy);
+  abuf_appendf(abuf, "# TC redundancy\n"
+                        "# Specifies how much neighbor info should\n"
+                        "# be sent in TC messages\n"
+                        "# Possible values are:\n"
+                        "# 0 - only send MPR selectors\n"
+                        "# 1 - send MPR selectors and MPRs\n"
+                        "# 2 - send all neighbors\n"
+                        "# defaults to 0\n"
+                        "TcRedundancy\t%d\n\n", cnf->tc_redundancy);
 
   /* MPR coverage */
-  WRITE_TO_BUF("# MPR coverage\n# Specifies how many MPRs a node should\n# try select to reach every 2 hop neighbor\n# Can be set to any integer >0\n# defaults to 1\n\n");
-
-  WRITE_TO_BUF("MprCoverage\t%d\n\n", cnf->mpr_coverage);
-
-  WRITE_TO_BUF("# Link quality level\n# 0 = do not use link quality\n# 1 = use link quality for MPR selection\n# 2 = use link quality for MPR selection and routing\n\n");
-  WRITE_TO_BUF("LinkQualityLevel\t%d\n\n", cnf->lq_level);
-
-  WRITE_TO_BUF("# Fish Eye algorithm\n# 0 = do not use fish eye\n# 1 = use fish eye\n\n");
-  WRITE_TO_BUF("LinkQualityFishEye\t%d\n\n", cnf->lq_fish);
-
-  if (NULL != cnf->lq_algorithm)
-  {
-    WRITE_TO_BUF("# Link quality algorithm (if LinkQualityLevel > 0)\n# etx_fpm (hello loss, fixed point math)\n# etx_float (hello loss, floating point)\n# etx_ff (packet loss for freifunk compat)\n\n");
-    WRITE_TO_BUF("LinkQualityAlgorithm\t\"%s\"\n\n", cnf->lq_algorithm);
+  abuf_appendf(abuf, "# MPR coverage\n"
+                        "# Specifies how many MPRs a node should\n"
+                        "# try select to reach every 2 hop neighbor\n"
+                        "# Can be set to any integer >0\n"
+                        "# defaults to 1\n"
+                        "MprCoverage\t%d\n\n", cnf->mpr_coverage);
+
+  abuf_appendf(abuf, "# Link quality level\n"
+                        "# 0 = do not use link quality\n"
+                        "# 1 = use link quality for MPR selection\n"
+                        "# 2 = use link quality for MPR selection and routing\n"
+                        "LinkQualityLevel\t%d\n\n", cnf->lq_level);
+
+  abuf_appendf(abuf, "# Fish Eye algorithm\n"
+                        "# 0 = do not use fish eye\n"
+                        "# 1 = use fish eye\n"
+                        "LinkQualityFishEye\t%d\n\n", cnf->lq_fish);
+
+  if (cnf->lq_algorithm != NULL) {
+    abuf_appendf(abuf, "# Link quality algorithm (if LinkQualityLevel > 0)\n"
+                          "# etx_fpm (hello loss, fixed point math)\n"
+                          "# etx_float (hello loss, floating point)\n"
+                          "# etx_ff (packet loss for freifunk compat)\n"
+                          "LinkQualityAlgorithm\t\"%s\"\n\n", cnf->lq_algorithm);
   }
 
-  WRITE_TO_BUF("# Link quality aging factor\n\n");
-  WRITE_TO_BUF("LinkQualityAging\t%f\n\n", cnf->lq_aging);
+  abuf_appendf(abuf, "# Link quality aging factor\n"
+                        "LinkQualityAging\t%f\n\n", cnf->lq_aging);
 
-  WRITE_TO_BUF("# NAT threshold\n\n");
-  WRITE_TO_BUF("NatThreshold\t%f\n\n", cnf->lq_nat_thresh);
+  abuf_appendf(abuf, "# NAT threshold\n"
+                        "NatThreshold\t%f\n\n", cnf->lq_nat_thresh);
 
-  WRITE_TO_BUF("# Clear screen when printing debug output?\n\n");
-  WRITE_TO_BUF("ClearScreen\t%s\n\n", cnf->clear_screen ? "yes" : "no");
+  abuf_appendf(abuf, "# Clear screen when printing debug output?\n"
+                        "ClearScreen\t%s\n\n", cnf->clear_screen ? "yes" : "no");
 
   /* Plugins */
-  WRITE_TO_BUF("# Olsrd plugins to load\n# This must be the absolute path to the file\n# or the loader will use the following scheme:\n");
-  WRITE_TO_BUF("# - Try the paths in the LD_LIBRARY_PATH \n#   environment variable.\n# - The list of libraries cached in /etc/ld.so.cache\n# - /lib, followed by /usr/lib\n\n");
-  if(pe)
-    {
-      while(pe)
-       {
-         WRITE_TO_BUF("LoadPlugin \"%s\" {\n", pe->name);
-          pp = pe->params;
-          while(pp)
-            {
-              WRITE_TO_BUF("    PlParam \"%s\"\t\"%s\"\n", pp->key, pp->value);
-              pp = pp->next;
-            }
-         WRITE_TO_BUF("}\n");
-         pe = pe->next;
-       }
+  abuf_appendf(abuf, "# Olsrd plugins to load\n"
+                        "# This must be the absolute path to the file\n"
+                        "# or the loader will use the following scheme:\n"
+                        "# - Try the paths in the LD_LIBRARY_PATH \n"
+                        "#   environment variable.\n"
+                        "# - The list of libraries cached in /etc/ld.so.cache\n"
+                        "# - /lib, followed by /usr/lib\n\n");
+  if (cnf->plugins) {
+    struct plugin_entry *pe;
+    for (pe = cnf->plugins; pe != NULL; pe = pe->next) {
+      struct plugin_param  *pp;
+      abuf_appendf(abuf, "LoadPlugin \"%s\" {\n", pe->name);
+      for (pp = pe->params; pp != NULL; pp = pp->next) {
+        abuf_appendf(abuf, "    PlParam \"%s\"\t\"%s\"\n", pp->key, pp->value);
+      }
+      abuf_appendf(abuf, "}\n");
     }
-  WRITE_TO_BUF("\n");
-
-  
-  
+  }
+  abuf_appendf(abuf, "\n");
 
   /* Interfaces */
-  WRITE_TO_BUF("# Interfaces\n# Multiple interfaces with the same configuration\n# can shar the same config block. Just list the\n# interfaces(e.g. Interface \"eth0\" \"eth2\"\n\n");
+  abuf_appendf(abuf, "# Interfaces\n"
+                        "# Multiple interfaces with the same configuration\n"
+                        "# can shar the same config block. Just list the\n"
+                        "# interfaces(e.g. Interface \"eth0\" \"eth2\"\n");
   /* Interfaces */
-  if(in)
-    {
-      olsr_bool first = write_more_comments;
-      while(in)
-       {
-         WRITE_TO_BUF("Interface \"%s\" {\n", in->name);
-
-          if(first)
-            WRITE_TO_BUF("    # IPv4 broadcast address to use. The\n    # one usefull example would be 255.255.255.255\n    # If not defined the broadcastaddress\n    # every card is configured with is used\n\n");
-
-
-         if(in->cnf->ipv4_broadcast.v4.s_addr)
-           {
-             WRITE_TO_BUF("    Ip4Broadcast\t%s\n", inet_ntoa(in->cnf->ipv4_broadcast.v4));
-           }
-         else
-           {
-             if(first)
-               WRITE_TO_BUF("    #Ip4Broadcast\t255.255.255.255\n");
-           }
-         
-          if(first) WRITE_TO_BUF("\n");
-
-          if(first)
-             WRITE_TO_BUF("    # IPv6 address scope to use.\n    # Must be 'site-local' or 'global'\n\n");
-         if(in->cnf->ipv6_addrtype)
-           WRITE_TO_BUF("    Ip6AddrType \tsite-local\n");
-         else
-           WRITE_TO_BUF("    Ip6AddrType \tglobal\n");
-
-          if(first) WRITE_TO_BUF("\n");
-
-          if(first)
-           WRITE_TO_BUF("    # IPv6 multicast address to use when\n    # using site-local addresses.\n    # If not defined, ff05::15 is used\n");
-         WRITE_TO_BUF("    Ip6MulticastSite\t%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
-          if(first) WRITE_TO_BUF("\n");
-          if(first)
-           WRITE_TO_BUF("    # IPv6 multicast address to use when\n    # using global addresses\n    # If not defined, ff0e::1 is used\n");
-         WRITE_TO_BUF("    Ip6MulticastGlobal\t%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
-          if(first) WRITE_TO_BUF("\n");
-  
-         
-          WRITE_TO_BUF("    # Olsrd can autodetect changes in\n    # interface configurations. Enabled by default\n    # turn off to save CPU.\n    AutoDetectChanges: %s\n", in->cnf->autodetect_chg ? "yes" : "no");
-
-          if(first)
-            WRITE_TO_BUF("    # Emission and validity intervals.\n    # If not defined, RFC proposed values will\n    # in most cases be used.\n\n");
-         
-         
-         if(in->cnf->hello_params.emission_interval != HELLO_INTERVAL)
-           WRITE_TO_BUF("    HelloInterval\t%0.2f\n", in->cnf->hello_params.emission_interval);
-          else if(first)
-           WRITE_TO_BUF("    #HelloInterval\t%0.2f\n", in->cnf->hello_params.emission_interval);
-         if(in->cnf->hello_params.validity_time != NEIGHB_HOLD_TIME)
-           WRITE_TO_BUF("    HelloValidityTime\t%0.2f\n", in->cnf->hello_params.validity_time);
-          else if(first)
-           WRITE_TO_BUF("    #HelloValidityTime\t%0.2f\n", in->cnf->hello_params.validity_time);
-         if(in->cnf->tc_params.emission_interval != TC_INTERVAL)
-           WRITE_TO_BUF("    TcInterval\t\t%0.2f\n", in->cnf->tc_params.emission_interval);
-          else if(first)
-           WRITE_TO_BUF("    #TcInterval\t\t%0.2f\n", in->cnf->tc_params.emission_interval);
-         if(in->cnf->tc_params.validity_time != TOP_HOLD_TIME)
-           WRITE_TO_BUF("    TcValidityTime\t%0.2f\n", in->cnf->tc_params.validity_time);
-          else if(first)
-           WRITE_TO_BUF("    #TcValidityTime\t%0.2f\n", in->cnf->tc_params.validity_time);
-         if(in->cnf->mid_params.emission_interval != MID_INTERVAL)
-           WRITE_TO_BUF("    MidInterval\t\t%0.2f\n", in->cnf->mid_params.emission_interval);
-          else if(first)
-           WRITE_TO_BUF("    #MidInterval\t%0.2f\n", in->cnf->mid_params.emission_interval);
-         if(in->cnf->mid_params.validity_time != MID_HOLD_TIME)
-           WRITE_TO_BUF("    MidValidityTime\t%0.2f\n", in->cnf->mid_params.validity_time);
-          else if(first)
-           WRITE_TO_BUF("    #MidValidityTime\t%0.2f\n", in->cnf->mid_params.validity_time);
-         if(in->cnf->hna_params.emission_interval != HNA_INTERVAL)
-           WRITE_TO_BUF("    HnaInterval\t\t%0.2f\n", in->cnf->hna_params.emission_interval);
-          else if(first)
-           WRITE_TO_BUF("    #HnaInterval\t%0.2f\n", in->cnf->hna_params.emission_interval);
-         if(in->cnf->hna_params.validity_time != HNA_HOLD_TIME)
-           WRITE_TO_BUF("    HnaValidityTime\t%0.2f\n", in->cnf->hna_params.validity_time);      
-          else if(first)
-           WRITE_TO_BUF("    #HnaValidityTime\t%0.2f\n", in->cnf->hna_params.validity_time);     
-         
-          mult = in->cnf->lq_mult;
-
-          if (mult == NULL)
-           {
-              if(first)
-               WRITE_TO_BUF("    #LinkQualityMult\tdefault 1.0\n");
-           }
-          else
-           {
-             while (mult != NULL)
-               {
-                 WRITE_TO_BUF("    LinkQualityMult\t%s %0.2f\n", inet_ntop(cnf->ip_version, &mult->addr, ipv6_buf, sizeof(ipv6_buf)), (float)(mult->value) / 65536.0);
-                 mult = mult->next;
-               }
-           }
-
-         if(first)
-           {
-             WRITE_TO_BUF("    # When multiple links exist between hosts\n");
-             WRITE_TO_BUF("    # the weight of interface is used to determine\n");
-             WRITE_TO_BUF("    # the link to use. Normally the weight is\n");
-             WRITE_TO_BUF("    # automatically calculated by olsrd based\n");
-             WRITE_TO_BUF("    # on the characteristics of the interface,\n");
-             WRITE_TO_BUF("    # but here you can specify a fixed value.\n");
-             WRITE_TO_BUF("    # Olsrd will choose links with the lowest value.\n");
-             WRITE_TO_BUF("    # Note:\n");
-             WRITE_TO_BUF("    # Interface weight is used only when LinkQualityLevel is 0.\n");
-             WRITE_TO_BUF("    # For any other value of LinkQualityLevel, the interface ETX\n");
-             WRITE_TO_BUF("    # value is used instead.\n\n");
-            }
-         if(in->cnf->weight.fixed)
-           {
-             WRITE_TO_BUF("    Weight\t %d\n\n", in->cnf->weight.value);
-           }
-         else
-           {
-              if(first)
-                       WRITE_TO_BUF("    #Weight\t 0\n\n");
-           }
-
-         
-         WRITE_TO_BUF("}\n\n");
-         in = in->next;
-         first = OLSR_FALSE;
-       }
-
+  if (cnf->interfaces) {
+    struct olsr_if *in;
+    olsr_bool first;
+    for (in = cnf->interfaces, first = write_more_comments;
+         in != NULL;
+         in = in->next, first = OLSR_FALSE)        {
+      abuf_appendf(abuf, "Interface \"%s\" {\n", in->name);
+
+      if (first) {
+        abuf_appendf(abuf, "    # IPv4 broadcast address to use. The\n"
+                              "    # one usefull example would be 255.255.255.255\n"
+                              "    # If not defined the broadcastaddress\n"
+                              "    # every card is configured with is used\n\n");
+      }
+
+      if (in->cnf->ipv4_broadcast.v4.s_addr) {
+        abuf_appendf(abuf, "    Ip4Broadcast\t%s\n", inet_ntoa(in->cnf->ipv4_broadcast.v4));
+      } else if (first) {
+        abuf_appendf(abuf, "    #Ip4Broadcast\t255.255.255.255\n");
+      }
+          
+      if (first) {
+        abuf_appendf(abuf, "\n    # IPv6 address scope to use.\n"
+                              "    # Must be 'site-local' or 'global'\n\n");
+      }
+      abuf_appendf(abuf, "    Ip6AddrType \t%s\n", in->cnf->ipv6_addrtype ? "site-local" : "global");
+
+      if (first) {
+        abuf_appendf(abuf, "\n"
+                              "    # IPv6 multicast address to use when\n"
+                              "    # using site-local addresses.\n"
+                              "    # If not defined, ff05::15 is used\n");
+      }
+      abuf_appendf(abuf, "    Ip6MulticastSite\t%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
+      if (first) {
+        abuf_appendf(abuf, "\n    # IPv6 multicast address to use when\n"
+                              "    # using global addresses\n"
+                              "    # If not defined, ff0e::1 is used\n");
+      }
+      abuf_appendf(abuf, "    Ip6MulticastGlobal\t%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
+      if (first) {
+        abuf_appendf(abuf, "\n");
+      }
+      abuf_appendf(abuf, "    # Olsrd can autodetect changes in\n"
+                            "    # interface configurations. Enabled by default\n"
+                            "    # turn off to save CPU.\n"
+                            "    AutoDetectChanges: %s\n", in->cnf->autodetect_chg ? "yes" : "no");
+
+      if (first) {
+        abuf_appendf(abuf, "    # Emission and validity intervals.\n"
+                              "    # If not defined, RFC proposed values will\n"
+                              "    # in most cases be used.\n\n");
+      }
+      append_float(abuf, "HelloInterval", in->cnf->hello_params.emission_interval, HELLO_INTERVAL, first);
+      append_float(abuf, "HelloValidityTime", in->cnf->hello_params.validity_time, NEIGHB_HOLD_TIME, first);
+      append_float(abuf, "TcInterval", in->cnf->tc_params.emission_interval, TC_INTERVAL, first);
+      append_float(abuf, "TcValidityTime", in->cnf->tc_params.validity_time, TOP_HOLD_TIME, first);
+      append_float(abuf, "MidValidityTime", in->cnf->mid_params.validity_time, MID_HOLD_TIME, first);
+      append_float(abuf, "HnaInterval", in->cnf->hna_params.emission_interval, HNA_INTERVAL, first);
+      append_float(abuf, "HnaValidityTime", in->cnf->hna_params.validity_time, HNA_HOLD_TIME, first);
+      if (in->cnf->lq_mult == NULL) {
+        if (first) {
+          abuf_appendf(abuf, "    #LinkQualityMult\tdefault 1.0\n");
+        }
+      } else {
+        struct olsr_lq_mult *mult;
+        for (mult = in->cnf->lq_mult; mult != NULL; mult = mult->next) {
+          abuf_appendf(abuf, "    LinkQualityMult\t%s %0.2f\n", inet_ntop(cnf->ip_version, &mult->addr, ipv6_buf, sizeof(ipv6_buf)), (float)mult->value / 65536.0);
+        }
+      }
+
+      if (first) {
+        abuf_appendf(abuf, "    # When multiple links exist between hosts\n"
+                              "    # the weight of interface is used to determine\n"
+                              "    # the link to use. Normally the weight is\n"
+                              "    # automatically calculated by olsrd based\n"
+                              "    # on the characteristics of the interface,\n"
+                              "    # but here you can specify a fixed value.\n"
+                              "    # Olsrd will choose links with the lowest value.\n"
+                              "    # Note:\n"
+                              "    # Interface weight is used only when LinkQualityLevel is 0.\n"
+                              "    # For any other value of LinkQualityLevel, the interface ETX\n"
+                              "    # value is used instead.\n\n");
+      }
+      if (in->cnf->weight.fixed) {
+        abuf_appendf(abuf, "    Weight\t %d\n", in->cnf->weight.value);
+      } else if (first) {
+        abuf_appendf(abuf, "    #Weight\t 0\n");
+      }
+
+      abuf_appendf(abuf, "}\n\n");
     }
-
-
-  WRITE_TO_BUF("\n# END AUTOGENERATED CONFIG\n");
-
-  return size;
+  }
+  abuf_appendf(abuf, "\n# END AUTOGENERATED CONFIG\n");
 }
 
 /*
diff --git a/src/common/autobuf.c b/src/common/autobuf.c
new file mode 100644 (file)
index 0000000..42152ea
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas T√łnnesen(bernd@firmix.at)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright 
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in 
+ *   the documentation and/or other materials provided with the 
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+#include "common/autobuf.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+
+static int autobuf_enlarge(struct autobuf *autobuf, int new_size);
+
+
+int abuf_init(struct autobuf *autobuf, int initial_size)
+{
+    autobuf->len = 0;
+    if (initial_size <= 0) {
+        autobuf->size = 0;
+        autobuf->buf = NULL;
+        return 0;
+    }
+    autobuf->size = ((initial_size + AUTOBUFCHUNK + 1) / AUTOBUFCHUNK) * AUTOBUFCHUNK;
+    autobuf->buf = malloc(autobuf->size);
+    if (autobuf->buf == NULL) {
+        autobuf->size = 0;
+        return  -1;
+    } 
+    *autobuf->buf = '\0';
+    return 0;
+}
+
+void abuf_free(struct autobuf *autobuf)
+{
+    free(autobuf->buf);
+    autobuf->buf = NULL;
+    autobuf->len = 0;
+    autobuf->size = 0;
+}
+
+static int autobuf_enlarge(struct autobuf *autobuf, int new_size)
+{
+    if (new_size >= autobuf->size) {
+        char *p;
+        do {
+            autobuf->size += AUTOBUFCHUNK;
+        } while (new_size >= autobuf->size);
+        p = realloc(autobuf->buf, autobuf->size);
+        if (p == NULL) {
+#ifdef WIN32
+           WSASetLastError(ENOMEM);
+#else
+            errno = ENOMEM;
+#endif
+            return -1;
+        }
+        autobuf->buf = p;
+    }
+    return 0;
+}
+
+int abuf_vappendf(struct autobuf *autobuf, const char *format, va_list ap)
+{
+    int rc;
+    int min_size;
+    va_list ap2;
+    va_copy(ap2, ap);
+    rc = vsnprintf(autobuf->buf+autobuf->len, autobuf->size-autobuf->len, format, ap);
+    min_size = autobuf->len + rc;
+    if (min_size >= autobuf->size) {
+        if (autobuf_enlarge(autobuf, min_size) < 0) {
+            autobuf->buf[autobuf->len] = '\0';
+            return -1;
+        }
+        vsnprintf(autobuf->buf+autobuf->len, autobuf->size-autobuf->len, format, ap2);
+    }
+    va_end(ap2);
+    autobuf->len = min_size;
+    return 0;
+}
+
+int abuf_appendf(struct autobuf *autobuf, const char *fmt, ...)
+{
+    int rv;
+    va_list ap;
+    va_start(ap, fmt);
+    rv = abuf_vappendf(autobuf, fmt, ap);
+    va_end(ap);
+    return rv;
+}
+
+int abuf_puts(struct autobuf *autobuf, const char *s)
+{
+    int len = strlen(s);
+    if (autobuf_enlarge(autobuf, autobuf->len + len + 1) < 0) {
+        return -1;
+    }
+    strcpy(autobuf->buf+autobuf->len, s);
+    autobuf->len += len;
+    return len;
+}
+
+int abuf_strftime(struct autobuf *autobuf, const char *format, const struct tm *tm)
+{
+    int rc = strftime(autobuf->buf+autobuf->len, autobuf->size-autobuf->len, format, tm);
+    if (rc == 0) {
+        /* we had an error! Probably the buffer too small. */
+        if (autobuf_enlarge(autobuf, autobuf->size+AUTOBUFCHUNK) < 0) {
+            autobuf->buf[autobuf->len] = '\0';
+            return -1;
+        }
+        rc = strftime(autobuf->buf+autobuf->len, autobuf->size-autobuf->len, format, tm);
+    }
+    autobuf->len += rc;
+    return rc;
+}
+
+int abuf_memcpy(struct autobuf *autobuf, const void *p, const unsigned int len)
+{
+    if (autobuf_enlarge(autobuf, autobuf->len + len) < 0) {
+        return -1;
+    }
+    memcpy(autobuf->buf+autobuf->len, p, len);
+    autobuf->len += len;
+    return len;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/common/autobuf.h b/src/common/autobuf.h
new file mode 100644 (file)
index 0000000..08ce416
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas T√łnnesen(bernd@firmix.at)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright 
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in 
+ *   the documentation and/or other materials provided with the 
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+#ifndef _COMMON_AUTOBUF_H
+#define _COMMON_AUTOBUF_H
+
+#include <stdarg.h>
+#include <time.h>
+
+#define AUTOBUFCHUNK   4096
+struct autobuf {
+    int size;
+    int len;
+    char *buf;
+};
+
+int  abuf_init(struct autobuf *autobuf, int initial_size);
+void abuf_free(struct autobuf *autobuf);
+int  abuf_vappendf(struct autobuf *autobuf, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0)));
+int  abuf_appendf(struct autobuf *autobuf, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
+int  abuf_puts(struct autobuf *autobuf, const char *s);
+int  abuf_strftime(struct autobuf *autobuf, const char *format, const struct tm *tm);
+int  abuf_memcpy(struct autobuf *autobuf, const void *p, const unsigned int len);
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index b9e867d..a9bbddf 100644 (file)
@@ -43,6 +43,7 @@
 #define _OLSRD_CFGPARSER_H
 
 #include "olsr_types.h"
+#include "common/autobuf.h"
 
 #ifndef LINUX_POLICY_ROUTING
 #if defined linux
@@ -282,7 +283,7 @@ void olsrd_print_cnf(const struct olsrd_config *);
 
 int olsrd_write_cnf(const struct olsrd_config *, const char *);
 
-  int olsrd_write_cnf_buf(const struct olsrd_config *, olsr_bool, char *, olsr_u32_t);
+void olsrd_write_cnf_buf(struct autobuf *, const struct olsrd_config *, olsr_bool);
 
 void init_default_if_config(struct if_config_options *);
 
index bbf71c4..0bd9251 100644 (file)
@@ -519,19 +519,25 @@ int add_hemu_if (struct olsr_if *iface)
     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC,
                      HELLO_JITTER, OLSR_TIMER_PERIODIC,
                      olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello,
-                     ifp, hello_gen_timer_cookie->ci_id);
+                     ifp,
+                    hello_gen_timer_cookie->ci_id);
   ifp->tc_gen_timer =
     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC,
                      TC_JITTER, OLSR_TIMER_PERIODIC,
                      olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc,
-                     ifp, tc_gen_timer_cookie->ci_id);
+                     ifp,
+                    tc_gen_timer_cookie->ci_id);
   ifp->mid_gen_timer =
     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC,
-                     MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
+                     MID_JITTER, OLSR_TIMER_PERIODIC,
+                    &generate_mid,
+                    ifp,
                      mid_gen_timer_cookie->ci_id);
   ifp->hna_gen_timer =
     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC,
-                     HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
+                     HNA_JITTER, OLSR_TIMER_PERIODIC,
+                    &generate_hna,
+                    ifp,
                      hna_gen_timer_cookie->ci_id);
 
   /* Recalculate max topology hold time */
@@ -809,21 +815,31 @@ chk_if_up(struct olsr_if *iface, int debuglvl __attribute__((unused)))
    */
   ifp->hello_gen_timer =
     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC,
-                     HELLO_JITTER, OLSR_TIMER_PERIODIC,
+                     HELLO_JITTER,
+                    OLSR_TIMER_PERIODIC,
                      olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello,
-                     ifp, hello_gen_timer_cookie->ci_id);
+                     ifp,
+                    hello_gen_timer_cookie->ci_id);
   ifp->tc_gen_timer =
     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC,
-                     TC_JITTER, OLSR_TIMER_PERIODIC,
+                     TC_JITTER,
+                    OLSR_TIMER_PERIODIC,
                      olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc,
-                     ifp, tc_gen_timer_cookie->ci_id);
+                     ifp,
+                    tc_gen_timer_cookie->ci_id);
   ifp->mid_gen_timer =
     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC,
-                     MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
+                     MID_JITTER,
+                    OLSR_TIMER_PERIODIC,
+                    &generate_mid,
+                    ifp,
                      mid_gen_timer_cookie->ci_id);
   ifp->hna_gen_timer =
     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC,
-                     HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
+                     HNA_JITTER,
+                    OLSR_TIMER_PERIODIC,
+                    &generate_hna,
+                    ifp,
                      hna_gen_timer_cookie->ci_id);
 
   /* Recalculate max topology hold time */