Removed superfluous maxplen config var
[olsrd.git] / lib / httpinfo / src / olsrd_httpinfo.c
1 /*
2  * HTTP Info plugin for the olsr.org OLSR daemon
3  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 /*
42  * Dynamic linked library for the olsr.org olsr daemon
43  */
44
45 #include "olsrd_httpinfo.h"
46 #include "admin_interface.h"
47 #include "gfx.h"
48
49 #include "olsr.h"
50 #include "olsr_cfg.h"
51 #include "interfaces.h"
52 #include "olsr_protocol.h"
53 #include "net_olsr.h"
54 #include "link_set.h"
55 #include "ipcalc.h"
56 #include "lq_plugin.h"
57 #include "olsr_cfg_gen.h"
58 #include "common/string.h"
59 #include "olsr_ip_prefix_list.h"
60
61 #include <stdio.h>
62 #include <string.h>
63 #include <stdlib.h>
64 #include <stdarg.h>
65 #include <unistd.h>
66 #include <errno.h>
67 #ifdef WIN32
68 #include <io.h>
69 #else
70 #include <netdb.h>
71 #endif
72
73 #ifdef OS
74 #undef OS
75 #endif
76
77 #ifdef WIN32
78 #define OS "Windows"
79 #endif
80 #ifdef linux
81 #define OS "GNU/Linux"
82 #endif
83 #ifdef __FreeBSD__
84 #define OS "FreeBSD"
85 #endif
86
87 #ifndef OS
88 #define OS "Undefined"
89 #endif
90
91 static char copyright_string[] __attribute__((unused)) = "olsr.org HTTPINFO plugin Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
92
93 #define MAX_CLIENTS 3
94
95 #define MAX_HTTPREQ_SIZE (1024 * 10)
96
97 #define DEFAULT_TCP_PORT 1978
98
99 #define HTML_BUFSIZE (1024 * 4000)
100
101 #define FRAMEWIDTH (resolve_ip_addresses ? 900 : 800)
102
103 #define FILENREQ_MATCH(req, filename) \
104         !strcmp(req, filename) || \
105         (strlen(req) && !strcmp(&req[1], filename))
106
107 static const char httpinfo_css[] =
108   "#A{text-decoration:none}\n"
109   "TH{text-align:left}\n"
110   "H1,H3,TD,TH{font-family:Helvetica;font-size:80%}\n"
111   "h2{font-family:Helvetica; font-size:14px;text-align:center;line-height:16px;"
112   "text-decoration:none;border:1px solid #ccc;margin:5px;background:#ececec;}\n"
113   "hr{border:none;padding:1px;background:url(grayline.gif) repeat-x bottom;}\n"
114   "#maintable{margin:0px;padding:5px;border-left:1px solid #ccc;"
115   "border-right:1px solid #ccc;border-bottom:1px solid #ccc;}\n"
116   "#footer{font-size:10px;line-height:14px;text-decoration:none;color:#666;}\n"
117   "#hdr{font-size:14px;text-align:center;line-height:16px;text-decoration:none;"
118   "border:1px solid #ccc;margin:5px;background:#ececec;}\n"
119   "#container{width:1000px;padding:30px;border:1px solid #ccc;background:#fff;}\n"
120   "#tabnav{height:20px;margin:0;padding-left:10px;"
121   "background:url(grayline.gif) repeat-x bottom;}\n"
122   "#tabnav li{margin:0;padding:0;display:inline;list-style-type:none;}\n"
123   "#tabnav a:link,#tabnav a:visited{float:left;background:#ececec;font-size:12px;"
124   "line-height:14px;font-weight:bold;padding:2px 10px 2px 10px;margin-right:4px;"
125   "border:1px solid #ccc;text-decoration:none;color:#777;}\n"
126   "#tabnav a:link.active,#tabnav a:visited.active{border-bottom:1px solid #fff;"
127   "background:#ffffff;color:#000;}\n"
128   "#tabnav a:hover{background:#777777;color:#ffffff;}\n"
129   ".input_text{background:#E5E5E5;margin-left:5px; margin-top:0px;text-align:left;"
130   "width:100px;padding:0px;color:#000;text-decoration:none;font-family:verdana;"
131   "font-size:12px;border:1px solid #ccc;}\n"
132   ".input_button{background:#B5D1EE;margin-left:5px;margin-top:0px;text-align:center;"
133   "width:120px;padding:0px;color:#000;text-decoration:none;font-family:verdana;"
134   "font-size:12px;border:1px solid #000;}\n";
135
136 typedef void (*build_body_callback)(struct autobuf *abuf);
137
138 struct tab_entry {
139   const char *tab_label;
140   const char *filename;
141   build_body_callback build_body_cb;
142   bool display_tab;
143 };
144
145 struct static_bin_file_entry {
146   const char *filename;
147   unsigned char *data;
148   unsigned int data_size;
149 };
150
151 struct static_txt_file_entry {
152   const char *filename;
153   const char *data;
154 };
155
156 #if ADMIN_INTERFACE
157 struct dynamic_file_entry {
158   const char *filename;
159   process_data_func process_data_cb;
160 };
161 #endif
162
163 static int get_http_socket(int);
164
165 static void build_tabs(struct autobuf *abuf, int);
166
167 static void parse_http_request(int, void *, unsigned int flags);
168
169 static void build_http_header(struct autobuf *abuf, http_header_type, bool, uint32_t);
170
171 static void build_frame(struct autobuf *abuf, build_body_callback frame_body_cb);
172
173 static void build_routes_body(struct autobuf *abuf);
174
175 static void build_config_body(struct autobuf *abuf);
176
177 static void build_neigh_body(struct autobuf *abuf);
178
179 static void build_topo_body(struct autobuf *abuf);
180
181 static void build_mid_body(struct autobuf *abuf);
182
183 static void build_nodes_body(struct autobuf *abuf);
184
185 static void build_all_body(struct autobuf *abuf);
186
187 static void build_about_body(struct autobuf *abuf);
188
189 static void build_cfgfile_body(struct autobuf *abuf);
190
191 static void build_ip_txt(struct autobuf *abuf, const bool want_link,
192                          const char * const ipaddrstr, const int prefix_len);
193
194 static void build_ipaddr_link(struct autobuf *abuf, const bool want_link,
195                               const union olsr_ip_addr * const ipaddr,
196                               const int prefix_len);
197 static void section_title(struct autobuf *abuf, const char *title);
198
199 static ssize_t writen(int fd, const void *buf, size_t count);
200
201 static struct timeval start_time;
202 static struct http_stats stats;
203 static int client_sockets[MAX_CLIENTS];
204 static int curr_clients;
205 static int http_socket;
206
207 #if 0
208 int netsprintf(char *str, const char* format, ...) __attribute__((format(printf, 2, 3)));
209 static int netsprintf_direct = 0;
210 static int netsprintf_error = 0;
211 #define sprintf netsprintf
212 #define NETDIRECT
213 #endif
214
215 static const struct tab_entry tab_entries[] = {
216     {"Configuration",  "config",  build_config_body,  true},
217     {"Routes",         "routes",  build_routes_body,  true},
218     {"Links/Topology", "nodes",   build_nodes_body,   true},
219     {"All",            "all",     build_all_body,     true},
220 #if ADMIN_INTERFACE
221     {"Admin",          "admin",   build_admin_body,   true},
222 #endif
223     {"About",          "about",   build_about_body,   true},
224     {"FOO",            "cfgfile", build_cfgfile_body, false},
225     {NULL,             NULL,      NULL,               false}
226 };
227
228 static const struct static_bin_file_entry static_bin_files[] = {
229     {"favicon.ico",  favicon_ico, sizeof(favicon_ico)},
230     {"logo.gif",     logo_gif, sizeof(logo_gif)},
231     {"grayline.gif", grayline_gif, sizeof(grayline_gif)},
232     {NULL, NULL, 0}
233 };
234
235 static const struct static_txt_file_entry static_txt_files[] = {
236     {"httpinfo.css", httpinfo_css},
237     {NULL, NULL}
238 };
239
240
241 #if ADMIN_INTERFACE
242 static const struct dynamic_file_entry dynamic_files[] = {
243     {"set_values", process_set_values},
244     {NULL, NULL}
245 };
246 #endif
247
248
249 static int
250 get_http_socket(int port)
251 {
252   struct sockaddr_storage sst;
253   uint32_t yes = 1;
254   socklen_t addrlen;
255
256   /* Init ipc socket */
257   int s = socket(olsr_cnf->ip_version, SOCK_STREAM, 0);
258   if (s == -1) {
259 #ifndef NODEBUG
260     OLSR_PRINTF(1, "(HTTPINFO)socket %s\n", strerror(errno));
261 #endif
262     return -1;
263   }
264
265   if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
266 #ifndef NODEBUG
267     OLSR_PRINTF(1, "(HTTPINFO)SO_REUSEADDR failed %s\n", strerror(errno));
268 #endif
269     CLOSESOCKET(s);
270     return -1;
271   }
272
273   /* Bind the socket */
274
275   /* complete the socket structure */
276   memset(&sst, 0, sizeof(sst));
277   if (olsr_cnf->ip_version == AF_INET) {
278       struct sockaddr_in *addr4 = (struct sockaddr_in *)&sst;
279       addr4->sin_family = AF_INET;
280       addrlen = sizeof(*addr4);
281 #ifdef SIN6_LEN
282       addr4->sin_len = addrlen;
283 #endif
284       addr4->sin_addr.s_addr = INADDR_ANY;
285       addr4->sin_port = htons(port);
286   } else {
287       struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&sst;
288       addr6->sin6_family = AF_INET6;
289       addrlen = sizeof(*addr6);
290 #ifdef SIN6_LEN
291       addr6->sin6_len = addrlen;
292 #endif
293       addr6->sin6_addr = in6addr_any;
294       addr6->sin6_port = htons(port);
295   }
296
297   /* bind the socket to the port number */
298   if (bind(s, (struct sockaddr *)&sst, addrlen) == -1) {
299 #ifndef NODEBUG
300     OLSR_PRINTF(1, "(HTTPINFO) bind failed %s\n", strerror(errno));
301 #endif
302     CLOSESOCKET(s);
303     return -1;
304   }
305
306   /* show that we are willing to listen */
307   if (listen(s, 1) == -1) {
308 #ifndef NODEBUG
309     OLSR_PRINTF(1, "(HTTPINFO) listen failed %s\n", strerror(errno));
310 #endif
311     CLOSESOCKET(s);
312     return -1;
313   }
314
315   return s;
316 }
317
318 /**
319  *Do initialization here
320  *
321  *This function is called by the my_init
322  *function in olsrd_plugin.c
323  */
324 int
325 olsrd_plugin_init(void)
326 {
327   /* Get start time */
328   gettimeofday(&start_time, NULL);
329
330   curr_clients = 0;
331   /* set up HTTP socket */
332   http_socket = get_http_socket(http_port != 0 ? http_port :  DEFAULT_TCP_PORT);
333
334   if (http_socket < 0) {
335     fprintf(stderr, "(HTTPINFO) could not initialize HTTP socket\n");
336     exit(0);
337   }
338
339   /* always allow localhost */
340   if (olsr_cnf->ip_version == AF_INET) {
341     union olsr_ip_addr ip;
342
343     ip.v4.s_addr = ntohl(INADDR_LOOPBACK);
344     ip_acl_add(&allowed_nets, &ip, 32, false);
345   } else {
346     ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_loopback, 128, false);
347     ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_v4mapped_loopback, 128, false);
348   }
349
350   /* Register socket */
351   add_olsr_socket(http_socket, &parse_http_request, NULL, NULL, SP_PR_READ);
352
353   return 1;
354 }
355
356 /* Non reentrant - but we are not multithreaded anyway */
357 static void
358 parse_http_request(int fd, void *data __attribute__((unused)), unsigned int flags __attribute__((unused)))
359 {
360   struct sockaddr_storage pin;
361   socklen_t addrlen;
362   union olsr_ip_addr *ipaddr;
363   char req[MAX_HTTPREQ_SIZE];
364   //static char body[HTML_BUFSIZE];
365   struct autobuf body, header;
366   char req_type[11];
367   char filename[251];
368   char http_version[11];
369   unsigned int c = 0;
370   int r = 1 /*, size = 0 */;
371
372   abuf_init(&body, 0);
373   abuf_init(&header, 0);
374
375   if (curr_clients >= MAX_CLIENTS) {
376     return;
377   }
378   curr_clients++;
379
380   addrlen = sizeof(pin);
381   client_sockets[curr_clients] = accept(fd, (struct sockaddr *)&pin, &addrlen);
382   if (client_sockets[curr_clients] == -1) {
383 #ifndef NODEBUG
384     OLSR_PRINTF(1, "(HTTPINFO) accept: %s\n", strerror(errno));
385 #endif
386     goto close_connection;
387   }
388
389   if(((struct sockaddr *)&pin)->sa_family != olsr_cnf->ip_version) {
390 #ifndef NODEBUG
391     OLSR_PRINTF(1, "(HTTPINFO) Connection with wrong IP version?!\n");
392 #endif
393     goto close_connection;
394   }
395
396   if(olsr_cnf->ip_version == AF_INET) {
397     struct sockaddr_in *addr4 = (struct sockaddr_in *)&pin;
398     ipaddr = (union olsr_ip_addr *)&addr4->sin_addr;
399   } else {
400     struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pin;
401     ipaddr = (union olsr_ip_addr *)&addr6->sin6_addr;
402   }
403
404   if (!ip_acl_acceptable(&allowed_nets, ipaddr)) {
405     struct ipaddr_str strbuf;
406     OLSR_PRINTF(0, "HTTP request from non-allowed host %s!\n",
407                 olsr_ip_to_string(&strbuf, ipaddr));
408     goto close_connection;
409   }
410
411   memset(req, 0, sizeof(req));
412   //memset(body, 0, sizeof(body));
413
414   while ((r = recv(client_sockets[curr_clients], &req[c], 1, 0)) > 0 && (c < sizeof(req)-1)) {
415       c++;
416
417       if ((c > 3 && !strcmp(&req[c-4], "\r\n\r\n")) ||
418          (c > 1 && !strcmp(&req[c-2], "\n\n")))
419           break;
420   }
421
422   if (r < 0) {
423     OLSR_PRINTF(1, "(HTTPINFO) Failed to recieve data from client!\n");
424     stats.err_hits++;
425     goto close_connection;
426   }
427
428   /* Get the request */
429   if (sscanf(req, "%10s %250s %10s\n", req_type, filename, http_version) != 3) {
430     /* Try without HTTP version */
431     if (sscanf(req, "%10s %250s\n", req_type, filename) != 2) {
432       OLSR_PRINTF(1, "(HTTPINFO) Error parsing request %s!\n", req);
433       stats.err_hits++;
434       goto close_connection;
435     }
436   }
437
438   OLSR_PRINTF(1, "Request: %s\nfile: %s\nVersion: %s\n\n", req_type, filename, http_version);
439
440   if (!strcmp(req_type, "POST")) {
441 #if ADMIN_INTERFACE
442     int i = 0;
443     while (dynamic_files[i].filename) {
444         printf("POST checking %s\n", dynamic_files[i].filename);
445         if (FILENREQ_MATCH(filename, dynamic_files[i].filename)) {
446             uint32_t param_size;
447
448             stats.ok_hits++;
449
450             param_size = recv(client_sockets[curr_clients], req, sizeof(req)-1, 0);
451
452             req[param_size] = '\0';
453             printf("Dynamic read %d bytes\n", param_size);
454
455             //memcpy(body, dynamic_files[i].data, static_bin_files[i].data_size);
456             //size += dynamic_files[i].process_data_cb(req, param_size, &body[size], sizeof(body)-size);
457             dynamic_files[i].process_data_cb(req, param_size, &body);
458
459             build_http_header(&header, HTTP_OK, true, body.len);
460             goto send_http_data;
461         }
462         i++;
463     }
464 #endif
465     /* We only support GET */
466     //strscpy(body, HTTP_400_MSG, sizeof(body));
467     abuf_puts(&body, HTTP_400_MSG);
468     stats.ill_hits++;
469     build_http_header(&header, HTTP_BAD_REQ, true, body.len);
470   } else if (!strcmp(req_type, "GET")) {
471     int i = 0;
472
473     for (i = 0; static_bin_files[i].filename; i++) {
474         if (FILENREQ_MATCH(filename, static_bin_files[i].filename)) {
475             break;
476         }
477     }
478
479     if (static_bin_files[i].filename) {
480       stats.ok_hits++;
481       //memcpy(body, static_bin_files[i].data, static_bin_files[i].data_size);
482       abuf_memcpy(&body, static_bin_files[i].data, static_bin_files[i].data_size);
483       //size = static_bin_files[i].data_size;
484       build_http_header(&header, HTTP_OK, false, body.len);
485       goto send_http_data;
486     }
487
488     i = 0;
489     while (static_txt_files[i].filename)        {
490       if (FILENREQ_MATCH(filename, static_txt_files[i].filename)) {
491         break;
492       }
493       i++;
494     }
495
496     if (static_txt_files[i].filename) {
497       stats.ok_hits++;
498
499       //size += snprintf(&body[size], sizeof(body)-size, "%s", static_txt_files[i].data);
500       abuf_puts(&body, static_txt_files[i].data);
501
502       build_http_header(&header, HTTP_OK, false, body.len);
503       goto send_http_data;
504     }
505
506     i = 0;
507     if (strlen(filename) > 1) {
508       while (tab_entries[i].filename) {
509         if (FILENREQ_MATCH(filename, tab_entries[i].filename)) {
510           break;
511         }
512         i++;
513       }
514     }
515
516     if (tab_entries[i].filename) {
517 #ifdef NETDIRECT
518       build_http_header(&header, HTTP_OK, true);
519       r = send(client_sockets[curr_clients], req, c, 0);
520       if (r < 0) {
521         OLSR_PRINTF(1, "(HTTPINFO) Failed sending data to client!\n");
522         goto close_connection;
523       }
524       netsprintf_error = 0;
525       netsprintf_direct = 1;
526 #endif
527       abuf_appendf(&body,
528                        "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
529                        "<head>\n"
530                        "<meta http-equiv=\"Content-type\" content=\"text/html; charset=ISO-8859-1\">\n"
531                        "<title>olsr.org httpinfo plugin</title>\n"
532                        "<link rel=\"icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
533                        "<link rel=\"shortcut icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
534                        "<link rel=\"stylesheet\" type=\"text/css\" href=\"httpinfo.css\">\n"
535                        "</head>\n"
536                        "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
537                        "<table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
538                        "<tbody><tr bgcolor=\"#ffffff\">\n"
539                        "<td align=\"left\" height=\"69\" valign=\"middle\" width=\"80%%\">\n"
540                        "<font color=\"black\" face=\"timesroman\" size=\"6\">&nbsp;&nbsp;&nbsp;<a href=\"http://www.olsr.org/\">olsr.org OLSR daemon</a></font></td>\n"
541                        "<td align=\"right\" height=\"69\" valign=\"middle\" width=\"20%%\">\n"
542                        "<a href=\"http://www.olsr.org/\"><img border=\"0\" src=\"/logo.gif\" alt=\"olsrd logo\"></a></td>\n"
543                        "</tr>\n"
544                        "</tbody>\n"
545                        "</table>\n",
546                        FRAMEWIDTH);
547
548       build_tabs(&body, i);
549       build_frame(&body,
550                   tab_entries[i].build_body_cb);
551
552       stats.ok_hits++;
553
554       abuf_appendf(&body,
555                        "</table>\n"
556                        "<div id=\"footer\">\n"
557                        "<center>\n"
558                        "(C)2005 Andreas T&oslash;nnesen<br/>\n"
559                        "<a href=\"http://www.olsr.org/\">http://www.olsr.org</a>\n"
560                        "</center>\n"
561                        "</div>\n"
562                        "</body>\n"
563                        "</html>\n");
564
565 #ifdef NETDIRECT
566       netsprintf_direct = 1;
567       goto close_connection;
568 #else
569       build_http_header(&header, HTTP_OK, true, body.len);
570       goto send_http_data;
571 #endif
572     }
573
574
575     stats.ill_hits++;
576     //strscpy(body, HTTP_404_MSG, sizeof(body));
577     abuf_puts(&body, HTTP_404_MSG);
578     build_http_header(&header, HTTP_BAD_FILE, true, body.len);
579   } else {
580     /* We only support GET */
581     //strscpy(body, HTTP_400_MSG, sizeof(body));
582     abuf_puts(&body, HTTP_400_MSG);
583     stats.ill_hits++;
584     build_http_header(&header, HTTP_BAD_REQ, true, body.len);
585   }
586
587  send_http_data:
588
589   r = writen(client_sockets[curr_clients], header.buf, header.len);
590   if (r < 0) {
591       OLSR_PRINTF(1, "(HTTPINFO) Failed sending data to client!\n");
592       goto close_connection;
593   }
594
595   r = writen(client_sockets[curr_clients], body.buf, body.len);
596   if (r < 0) {
597       OLSR_PRINTF(1, "(HTTPINFO) Failed sending data to client!\n");
598       goto close_connection;
599   }
600
601  close_connection:
602   abuf_free(&body);
603   abuf_free(&header);
604   CLOSESOCKET(client_sockets[curr_clients]);
605   curr_clients--;
606 }
607
608
609 void
610 build_http_header(struct autobuf *abuf,
611                   http_header_type type,
612                   bool is_html,
613                   uint32_t msgsize)
614 {
615   time_t currtime;
616   const char *h;
617
618   switch(type) {
619   case HTTP_BAD_REQ:
620       h = HTTP_400;
621       break;
622   case HTTP_BAD_FILE:
623       h = HTTP_404;
624       break;
625   default:
626       /* Defaults to OK */
627       h = HTTP_200;
628       break;
629   }
630   abuf_puts(abuf, h);
631
632   /* Date */
633   time(&currtime);
634   abuf_strftime(abuf, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
635
636   /* Server version */
637   abuf_appendf(abuf, "Server: %s %s %s\r\n", PLUGIN_NAME, PLUGIN_VERSION, HTTP_VERSION);
638
639   /* connection-type */
640   abuf_puts(abuf, "Connection: closed\r\n");
641
642   /* MIME type */
643   abuf_appendf(abuf, "Content-type: text/%s\r\n", is_html ? "html" : "plain");
644
645   /* Content length */
646   if (msgsize > 0) {
647       abuf_appendf(abuf, "Content-length: %u\r\n", msgsize);
648   }
649
650   /* Cache-control
651    * No caching dynamic pages
652    */
653   abuf_puts(abuf, "Cache-Control: no-cache\r\n");
654
655   if (!is_html) {
656     abuf_puts(abuf, "Accept-Ranges: bytes\r\n");
657   }
658   /* End header */
659   abuf_puts(abuf, "\r\n");
660
661   OLSR_PRINTF(1, "HEADER:\n%s", abuf->buf);
662 }
663
664
665 static void build_tabs(struct autobuf *abuf, int active)
666 {
667   int tabs;
668
669   abuf_appendf(abuf,
670                   "<table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
671                   "<tr bgcolor=\"#ffffff\"><td>\n"
672                   "<ul id=\"tabnav\">\n",
673                   FRAMEWIDTH);
674   for (tabs = 0; tab_entries[tabs].tab_label; tabs++) {
675     if (!tab_entries[tabs].display_tab) {
676       continue;
677     }
678     abuf_appendf(abuf,
679                     "<li><a href=\"%s\"%s>%s</a></li>\n",
680                     tab_entries[tabs].filename,
681                     tabs == active ? " class=\"active\"" : "",
682                     tab_entries[tabs].tab_label);
683   }
684   abuf_appendf(abuf,
685                   "</ul>\n"
686                   "</td></tr>\n"
687                   "<tr><td>\n");
688 }
689
690
691 /*
692  * destructor - called at unload
693  */
694 void
695 olsr_plugin_exit(void)
696 {
697   ip_acl_flush(&allowed_nets);
698
699   if (http_socket >= 0) {
700     CLOSESOCKET(http_socket);
701   }
702 }
703
704
705 static void section_title(struct autobuf *abuf, const char *title)
706 {
707   abuf_appendf(abuf,
708                   "<h2>%s</h2>\n"
709                   "<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n", title);
710 }
711
712 static void build_frame(struct autobuf *abuf,
713                         build_body_callback frame_body_cb)
714 {
715   abuf_puts(abuf, "<div id=\"maintable\">\n");
716   frame_body_cb(abuf);
717   abuf_puts(abuf, "</div>\n");
718 }
719
720 static void fmt_href(struct autobuf *abuf,
721                     const char * const ipaddr)
722 {
723   abuf_appendf(abuf, "<a href=\"http://%s:%d/all\">", ipaddr, http_port);
724 }
725
726 static void build_ip_txt(struct autobuf *abuf,
727                          const bool print_link,
728                          const char * const ipaddrstr,
729                          const int prefix_len)
730 {
731   if (print_link) {
732     fmt_href(abuf, ipaddrstr);
733   }
734
735   abuf_puts(abuf, ipaddrstr);
736   /* print ip address or ip prefix ? */
737   if (prefix_len != -1 && prefix_len != 8 * (int)olsr_cnf->ipsize) {
738     abuf_appendf(abuf, "/%d", prefix_len);
739   }
740
741   if (print_link) { /* Print the link only if there is no prefix_len */
742     abuf_puts(abuf, "</a>");
743   }
744 }
745
746 static void build_ipaddr_link(struct autobuf *abuf,
747                               const bool want_link,
748                               const union olsr_ip_addr * const ipaddr,
749                               const int prefix_len)
750 {
751   struct ipaddr_str ipaddrstr;
752   const struct hostent * const hp =
753 #ifndef WIN32
754       resolve_ip_addresses ? gethostbyaddr(ipaddr, olsr_cnf->ipsize, olsr_cnf->ip_version) :
755 #endif
756       NULL;
757   /* Print the link only if there is no prefix_len */
758   const int print_link = want_link && (prefix_len == -1 || prefix_len == 8 * (int)olsr_cnf->ipsize);
759   olsr_ip_to_string(&ipaddrstr, ipaddr);
760
761   abuf_puts(abuf, "<td>");
762   build_ip_txt(abuf, print_link, ipaddrstr.buf, prefix_len);
763   abuf_puts(abuf, "</td>");
764
765   if (resolve_ip_addresses) {
766     if (hp) {
767       abuf_puts(abuf, "<td>(");
768       if (print_link) {
769         fmt_href(abuf, ipaddrstr.buf);
770       }
771       abuf_puts(abuf, hp->h_name);
772       if (print_link) {
773         abuf_puts(abuf, "</a>");
774       }
775       abuf_puts(abuf, ")</td>");
776     } else {
777       abuf_puts(abuf, "<td/>");
778     }
779   }
780 }
781
782 #define build_ipaddr_with_link(abuf, ipaddr, plen) \
783           build_ipaddr_link((abuf), true, (ipaddr), (plen))
784 #define build_ipaddr_no_link(abuf, ipaddr, plen) \
785           build_ipaddr_link((abuf), false, (ipaddr), (plen))
786
787 static void build_route(struct autobuf *abuf, const struct rt_entry * rt)
788 {
789   struct lqtextbuffer lqbuffer;
790
791   abuf_puts(abuf, "<tr>");
792   build_ipaddr_with_link(abuf,
793                          &rt->rt_dst.prefix,
794                          rt->rt_dst.prefix_len);
795   build_ipaddr_with_link(abuf,
796                          &rt->rt_best->rtp_nexthop.gateway,
797                          -1);
798
799   abuf_appendf(abuf,
800                   "<td align=\"center\">%u</td>",
801                   rt->rt_best->rtp_metric.hops);
802   abuf_appendf(abuf,
803                   "<td align=\"right\">%s</td>",
804                   get_linkcost_text(rt->rt_best->rtp_metric.cost, true, &lqbuffer));
805   abuf_appendf(abuf,
806                   "<td align=\"center\">%s</td></tr>\n",
807                   rt->rt_best->rtp_nexthop.interface ? rt->rt_best->rtp_nexthop.interface->int_name : "[null]");
808 }
809
810 static void build_routes_body(struct autobuf *abuf)
811 {
812   struct rt_entry *rt;
813   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
814   section_title(abuf, "OLSR Routes in Kernel");
815   abuf_appendf(abuf,
816                   "<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",
817                   colspan, colspan);
818
819   /* Walk the route table */
820   OLSR_FOR_ALL_RT_ENTRIES(rt) {
821       build_route(abuf, rt);
822   } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
823
824   abuf_puts(abuf, "</table>\n");
825 }
826
827 static void build_config_body(struct autobuf *abuf)
828 {
829   const struct olsr_if_config *ifs;
830   const struct plugin_entry *pentry;
831   const struct plugin_param *pparam;
832   struct ipaddr_str mainaddrbuf;
833
834   abuf_appendf(abuf,
835                   "Version: %s (built on %s on %s)\n<br>OS: %s\n<br>",
836                   olsrd_version, build_date, build_host, OS);
837   {
838     const time_t currtime = time(NULL);
839     abuf_strftime(abuf, "System time: <em>%a, %d %b %Y %H:%M:%S</em><br>", localtime(&currtime));
840   }
841
842   {
843     struct timeval now, uptime;
844     int hours, mins, days;
845     gettimeofday(&now, NULL);
846     timersub(&now, &start_time, &uptime);
847
848     days = uptime.tv_sec/86400;
849     uptime.tv_sec %= 86400;
850     hours = uptime.tv_sec/3600;
851     uptime.tv_sec %= 3600;
852     mins = uptime.tv_sec/60;
853     uptime.tv_sec %= 60;
854
855     abuf_puts(abuf, "Olsrd uptime: <em>");
856     if (days) {
857       abuf_appendf(abuf, "%d day(s) ", days);
858     }
859     abuf_appendf(abuf, "%02d hours %02d minutes %02d seconds</em><br/>\n", hours, mins, (int)uptime.tv_sec);
860   }
861
862   abuf_appendf(abuf, "HTTP stats(ok/dyn/error/illegal): <em>%u/%u/%u/%u</em><br>\n", stats.ok_hits, stats.dyn_hits, stats.err_hits, stats.ill_hits);
863
864   abuf_appendf(abuf, "Click <a href=\"/cfgfile\">here</a> to <em>generate a configuration file for this node</em>.\n");
865
866   abuf_puts(abuf, "<h2>Variables</h2>\n");
867
868   abuf_puts(abuf, "<table width=\"100%%\" border=\"0\">\n<tr>");
869
870   abuf_appendf(abuf, "<td>Main address: <strong>%s</strong></td>\n", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
871   abuf_appendf(abuf, "<td>IP version: %d</td>\n", olsr_cnf->ip_version == AF_INET ? 4 : 6);
872   abuf_appendf(abuf, "<td>Debug level: %d</td>\n", olsr_cnf->debug_level);
873   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);
874
875   abuf_puts(abuf, "</tr>\n<tr>\n");
876
877   abuf_appendf(abuf, "<td>Pollrate: %0.2f</td>\n", conv_pollrate_to_secs(olsr_cnf->pollrate));
878   abuf_appendf(abuf, "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
879   abuf_appendf(abuf, "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
880   abuf_appendf(abuf, "<td>NAT threshold: %f</td>\n", olsr_cnf->lq_nat_thresh);
881
882   abuf_puts(abuf, "</tr>\n<tr>\n");
883
884   abuf_appendf(abuf, "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
885   abuf_appendf(abuf, "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
886   abuf_appendf(abuf, "<td>RtTable: 0x%04x/%d</td>\n", olsr_cnf->rttable, olsr_cnf->rttable);
887   abuf_appendf(abuf, "<td>RtTableDefault: 0x%04x/%d</td>\n", olsr_cnf->rttable_default, olsr_cnf->rttable_default);
888   abuf_appendf(abuf, "<td>Willingness: %d %s</td>\n", olsr_cnf->willingness, olsr_cnf->willingness_auto ? "(auto)" : "");
889
890   abuf_puts(abuf, "</tr></table>\n");
891
892   abuf_puts(abuf, "<h2>Interfaces</h2>\n");
893   abuf_puts(abuf, "<table width=\"100%%\" border=\"0\">\n");
894   for (ifs = olsr_cnf->if_configs; ifs != NULL; ifs = ifs->next) {
895     const struct interface * const rifs = ifs->interf;
896     abuf_appendf(abuf, "<tr><th colspan=\"3\">%s</th>\n", ifs->name);
897     if (!rifs) {
898       abuf_puts(abuf, "<tr><td colspan=\"3\">Status: DOWN</td></tr>\n");
899       continue;
900     }
901
902     if (olsr_cnf->ip_version == AF_INET) {
903       struct ipaddr_str addrbuf, maskbuf, bcastbuf;
904       abuf_appendf(abuf,
905                       "<tr>\n"
906                       "<td>IP: %s</td>\n"
907                       "<td>MASK: %s</td>\n"
908                       "<td>BCAST: %s</td>\n"
909                       "</tr>\n",
910                       ip4_to_string(&addrbuf, rifs->int_addr.sin_addr),
911                       ip4_to_string(&maskbuf, rifs->int_netmask.sin_addr),
912                       ip4_to_string(&bcastbuf, rifs->int_broadaddr.sin_addr));
913     } else {
914       struct ipaddr_str addrbuf, maskbuf;
915       abuf_appendf(abuf,
916                       "<tr>\n"
917                       "<td>IP: %s</td>\n"
918                       "<td>MCAST: %s</td>\n"
919                       "<td></td>\n"
920                       "</tr>\n",
921                       ip6_to_string(&addrbuf, &rifs->int6_addr.sin6_addr),
922                       ip6_to_string(&maskbuf, &rifs->int6_multaddr.sin6_addr));
923     }
924     abuf_appendf(abuf,
925                     "<tr>\n"
926                     "<td>MTU: %d</td>\n"
927                     "<td>WLAN: %s</td>\n"
928                     "<td>STATUS: UP</td>\n"
929                     "</tr>\n",
930                     rifs->int_mtu,
931                     rifs->is_wireless ? "Yes" : "No");
932   }
933   abuf_puts(abuf, "</table>\n");
934
935   abuf_appendf(abuf,
936                   "<em>Olsrd is configured to %s if no interfaces are available</em><br>\n",
937                   olsr_cnf->allow_no_interfaces ? "run even" : "halt");
938
939   abuf_puts(abuf, "<h2>Plugins</h2>\n");
940   abuf_puts(abuf, "<table width=\"100%%\" border=\"0\"><tr><th>Name</th><th>Parameters</th></tr>\n");
941   for (pentry = olsr_cnf->plugins; pentry; pentry = pentry->next) {
942     abuf_appendf(abuf,
943                     "<tr><td>%s</td>\n"
944                     "<td><select>\n"
945                     "<option>KEY, VALUE</option>\n",
946                     pentry->name);
947
948     for (pparam = pentry->params; pparam; pparam = pparam->next) {
949       abuf_appendf(abuf, "<option>\"%s\", \"%s\"</option>\n", pparam->key, pparam->value);
950     }
951     abuf_puts(abuf, "</select></td></tr>\n");
952
953   }
954   abuf_puts(abuf, "</table>\n");
955
956   section_title(abuf, "Announced HNA entries");
957   if (list_is_empty(&olsr_cnf->hna_entries)) {
958     struct ip_prefix_entry *hna;
959     abuf_puts(abuf, "<tr><th>Network</th></tr>\n");
960     OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, hna) {
961       struct ipprefix_str netbuf;
962       abuf_appendf(abuf,
963                       "<tr><td>%s</td></tr>\n",
964                       olsr_ip_prefix_to_string(&netbuf, &hna->net));
965     } OLSR_FOR_ALL_IPPREFIX_ENTRIES_END()
966   } else {
967     abuf_puts(abuf, "<tr><td></td></tr>\n");
968   }
969   abuf_puts(abuf, "</table>\n");
970 }
971
972 static void build_neigh_body(struct autobuf *abuf)
973 {
974   struct neighbor_entry *neigh;
975   struct link_entry *lnk;
976   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
977
978   section_title(abuf, "Links");
979
980   abuf_appendf(abuf,
981                    "<tr><th align=\"center\"%s>Local IP</th><th align=\"center\"%s>Remote IP</th>", colspan, colspan);
982   abuf_puts(abuf,
983                    "<th align=\"right\">LinkCost</th>");
984   abuf_puts(abuf, "</tr>\n");
985
986   /* Link set */
987   OLSR_FOR_ALL_LINK_ENTRIES(lnk) {
988     struct lqtextbuffer lqbuffer1, lqbuffer2;
989     abuf_puts(abuf, "<tr>");
990     build_ipaddr_with_link(abuf, &lnk->local_iface_addr, -1);
991     build_ipaddr_with_link(abuf, &lnk->neighbor_iface_addr, -1);
992     abuf_appendf(abuf,
993                      "<td align=\"right\">(%s) %s</td>",
994                      get_link_entry_text(lnk, '/', &lqbuffer1),
995                      get_linkcost_text(lnk->linkcost, false, &lqbuffer2));
996     abuf_puts(abuf, "</tr>\n");
997   } OLSR_FOR_ALL_LINK_ENTRIES_END(lnk);
998
999   abuf_puts(abuf, "</table>\n");
1000
1001   section_title(abuf, "Neighbors");
1002   abuf_appendf(abuf,
1003                    "<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);
1004   /* Neighbors */
1005   OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
1006     struct neighbor_2_list_entry *list_2;
1007     int thop_cnt;
1008     abuf_puts(abuf, "<tr>");
1009     build_ipaddr_with_link(abuf, &neigh->neighbor_main_addr, -1);
1010     abuf_appendf(abuf,
1011                      "<td align=\"center\">%s</td>"
1012                      "<td align=\"center\">%s</td>"
1013                      "<td align=\"center\">%s</td>"
1014                      "<td align=\"center\">%d</td>",
1015                      (neigh->status == SYM) ? "YES" : "NO",
1016                      neigh->is_mpr ? "YES" : "NO",
1017                      olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO",
1018                      neigh->willingness);
1019
1020     abuf_puts(abuf, "<td><select>\n"
1021                      "<option>IP ADDRESS</option>\n");
1022
1023
1024     for (list_2 = neigh->neighbor_2_list.next, thop_cnt = 0;
1025          list_2 != &neigh->neighbor_2_list;
1026          list_2 = list_2->next, thop_cnt++) {
1027       struct ipaddr_str strbuf;
1028       abuf_appendf(abuf, "<option>%s</option>\n",
1029                        olsr_ip_to_string(&strbuf, &list_2->neighbor_2->neighbor_2_addr));
1030     }
1031     abuf_appendf(abuf, "</select> (%d)</td></tr>\n", thop_cnt);
1032   } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
1033
1034   abuf_puts(abuf, "</table>\n");
1035 }
1036
1037 static void build_topo_body(struct autobuf *abuf)
1038 {
1039   struct tc_entry *tc;
1040   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
1041
1042   section_title(abuf, "Topology Entries");
1043   abuf_appendf(abuf, "<tr><th align=\"center\"%s>Destination IP</th><th align=\"center\"%s>Last Hop IP</th>", colspan, colspan);
1044   abuf_puts(abuf, "<th colspan=\"3\" align=\"right\">Linkcost</th>");
1045   abuf_puts(abuf, "</tr>\n");
1046
1047   OLSR_FOR_ALL_TC_ENTRIES(tc) {
1048       struct tc_edge_entry *tc_edge;
1049       OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
1050         if (tc_edge->edge_inv)  {
1051           struct lqtextbuffer lqbuffer1, lqbuffer2;
1052           abuf_puts(abuf, "<tr>");
1053           build_ipaddr_with_link(abuf, &tc_edge->T_dest_addr, -1);
1054           build_ipaddr_with_link(abuf, &tc->addr, -1);
1055           abuf_appendf(abuf,
1056                              "<td align=\"right\">(%s)</td><td>&nbsp;</td><td align=\"left\">%s</td>\n",
1057                              get_tc_edge_entry_text(tc_edge, '/', &lqbuffer1),
1058                              get_linkcost_text(tc_edge->cost, false, &lqbuffer2));
1059           abuf_puts(abuf, "</tr>\n");
1060         }
1061       } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
1062   } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
1063
1064   abuf_puts(abuf, "</table>\n");
1065 }
1066
1067 static void build_mid_body(struct autobuf *abuf)
1068 {
1069   struct tc_entry *tc;
1070   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
1071
1072   section_title(abuf, "MID Entries");
1073   abuf_appendf(abuf,
1074                   "<tr><th align=\"center\"%s>Main Address</th><th>Aliases</th></tr>\n", colspan);
1075
1076   /* MID */
1077   OLSR_FOR_ALL_TC_ENTRIES(tc) {
1078     struct mid_entry *alias;
1079     abuf_puts(abuf, "<tr>");
1080     build_ipaddr_with_link(abuf, &tc->addr, -1);
1081     abuf_puts(abuf, "<td><select>\n<option>IP ADDRESS</option>\n");
1082
1083     OLSR_FOR_ALL_TC_MID_ENTRIES(tc, alias) {
1084       struct ipaddr_str strbuf;
1085       abuf_appendf(abuf, "<option>%s</option>\n",
1086                        olsr_ip_to_string(&strbuf, &alias->mid_alias_addr));
1087     } OLSR_FOR_ALL_TC_MID_ENTRIES_END(tc, alias);
1088     abuf_appendf(abuf, "</select> (%u)</td></tr>\n", tc->mid_tree.count);
1089   } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
1090
1091   abuf_puts(abuf, "</table>\n");
1092 }
1093
1094
1095 static void build_nodes_body(struct autobuf *abuf)
1096 {
1097   build_neigh_body(abuf);
1098   build_topo_body(abuf);
1099   build_mid_body(abuf);
1100 }
1101
1102 static void build_all_body(struct autobuf *abuf)
1103 {
1104   build_config_body(abuf);
1105   build_routes_body(abuf);
1106   build_nodes_body(abuf);
1107 }
1108
1109
1110 static void build_about_body(struct autobuf *abuf)
1111 {
1112   abuf_appendf(abuf,
1113                   "<strong>" PLUGIN_NAME " version " PLUGIN_VERSION "</strong><br/>\n"
1114                   "by Andreas T&oslash;nnesen (C)2005.<br/>\n"
1115                   "Compiled "
1116 #if ADMIN_INTERFACE
1117                            "<em>with experimental admin interface</em> "
1118 #endif
1119                                                                       "%s at %s<hr/>\n"
1120                   "This plugin implements a HTTP server that supplies\n"
1121                   "the client with various dynamic web pages representing\n"
1122                   "the current olsrd status.<br/>The different pages include:\n"
1123                   "<ul>\n<li><strong>Configuration</strong> - This page displays information\n"
1124                   "about the current olsrd configuration. This includes various\n"
1125                   "olsr settings such as IP version, MID/TC redundancy, hysteresis\n"
1126                   "etc. Information about the current status of the interfaces on\n"
1127                   "which olsrd is configured to run is also displayed. Loaded olsrd\n"
1128                   "plugins are shown with their plugin parameters. Finally all local\n"
1129                   "HNA entries are shown. These are the networks that the local host\n"
1130                   "will anounce itself as a gateway to.</li>\n"
1131                   "<li><strong>Routes</strong> - This page displays all routes currently set in\n"
1132                   "the kernel <em>by olsrd</em>. The type of route is also displayed(host\n"
1133                   "or HNA).</li>\n"
1134                   "<li><strong>Links/Topology</strong> - This page displays all information about\n"
1135                   "links, neighbors, topology, MID and HNA entries.</li>\n"
1136                   "<li><strong>All</strong> - Here all the previous pages are displayed as one.\n"
1137                   "This is to make all information available as easy as possible(for example\n"
1138                   "for a script) and using as few resources as possible.</li>\n"
1139 #if ADMIN_INTERFACE
1140                   "<li><strong>Admin</strong> - This page is highly experimental(and unsecure)!\n"
1141                   "As of now it is not working at all but it provides a impression of\n"
1142                   "the future possibilities of httpinfo. This is to be a interface to\n"
1143                   "changing olsrd settings in realtime. These settings include various\n"
1144                   "\"basic\" settings and local HNA settings.</li>\n"
1145 #endif
1146                   "<li><strong>About</strong> - this help page.</li>\n</ul>"
1147                   "<hr/>\n"
1148                   "Send questions or comments to\n"
1149                   "<a href=\"mailto:olsr-users@olsr.org\">olsr-users@olsr.org</a> or\n"
1150                   "<a href=\"mailto:andreto-at-olsr.org\">andreto-at-olsr.org</a><br/>\n"
1151                   "Official olsrd homepage: <a href=\"http://www.olsr.org/\">http://www.olsr.org</a><br/>\n",
1152                   build_date, build_host);
1153 }
1154
1155 static void build_cfgfile_body(struct autobuf *abuf)
1156 {
1157   abuf_puts(abuf,
1158                    "\n\n"
1159                    "<strong>This is an automatically generated configuration\n"
1160                    "file based on the current olsrd configuration of this node.</strong><br/>\n"
1161                    "<hr/>\n"
1162                    "<pre>\n");
1163
1164 #ifdef NETDIRECT
1165   {
1166         /* Hack to make netdirect stuff work with
1167            olsr_write_cnf_buf
1168         */
1169         char tmpBuf[10000];
1170         size = olsr_write_cnf_buf(olsr_cnf, true, tmpBuf, 10000);
1171         snprintf(&buf[size], bufsize-size, tmpBuf);
1172   }
1173 #else
1174   olsr_write_cnf_buf(abuf, olsr_cnf, true);
1175 #endif
1176
1177   abuf_puts(abuf, "</pre>\n<hr/>\n");
1178
1179 #if 0
1180   printf("RETURNING %d\n", size);
1181 #endif
1182 }
1183 #if 0
1184 /*
1185  * In a bigger mesh, there are probs with the fixed
1186  * bufsize. Because the Content-Length header is
1187  * optional, the sprintf() is changed to a more
1188  * scalable solution here.
1189  */
1190
1191 int netsprintf(char *str, const char* format, ...)
1192 {
1193         va_list arg;
1194         int rv;
1195         va_start(arg, format);
1196         rv = vsprintf(str, format, arg);
1197         va_end(arg);
1198         if (0 != netsprintf_direct) {
1199                 if (0 == netsprintf_error) {
1200                         if (0 > send(client_sockets[curr_clients], str, rv, 0)) {
1201                                 OLSR_PRINTF(1, "(HTTPINFO) Failed sending data to client!\n");
1202                                 netsprintf_error = 1;
1203                         }
1204                 }
1205                 return 0;
1206         }
1207         return rv;
1208 }
1209 #endif
1210
1211 static ssize_t writen(int fd, const void *buf, size_t count)
1212 {
1213     size_t bytes_left = count;
1214     const char *p = buf;
1215     while (bytes_left > 0) {
1216         const ssize_t written = write(fd, p, bytes_left);
1217         if (written == -1)  { /* error */
1218             if (errno == EINTR ) {
1219                 continue;
1220             }
1221             return -1;
1222         }
1223         /* We wrote something */
1224         bytes_left -= written;
1225         p += written;
1226     }
1227     return count;
1228 }
1229
1230 /*
1231  * Local Variables:
1232  * c-basic-offset: 2
1233  * indent-tabs-mode: nil
1234  * End:
1235  */