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