06067822cb77d66725306b89413db61afe265bcd
[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 static const struct dynamic_file_entry dynamic_files[] = {
244 #ifdef ADMIN_INTERFACE
245   {"set_values", process_set_values},
246 #endif
247   {NULL, NULL}
248 };
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 *addr;
328   char header_buf[MAX_HTTPREQ_SIZE];
329   char req_type[11];
330   char filename[251];
331   char http_version[11];
332   int client_socket;
333   size_t header_length = 0;
334   size_t c = 0;
335   int r = 1;
336 #ifdef linux
337   struct timeval timeout = { 0, 200 };
338 #endif
339
340   if (outbuffer_count >= MAX_CLIENTS) {
341     olsr_printf(1, "(HTTPINFO) maximum number of connection reached\n");
342     return;
343   }
344
345   addrlen = sizeof(struct sockaddr_in);
346   client_socket = accept(fd, (struct sockaddr *)&pin, &addrlen);
347   if (client_socket == -1) {
348     olsr_printf(1, "(HTTPINFO) accept: %s\n", strerror(errno));
349     goto close_connection;
350   }
351
352 #ifdef linux
353   if (setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
354     olsr_printf(1, "(HTTPINFO)SO_RCVTIMEO failed %s\n", strerror(errno));
355     goto close_connection;
356   }
357
358   if (setsockopt(client_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
359     olsr_printf(1, "(HTTPINFO)SO_SNDTIMEO failed %s\n", strerror(errno));
360     goto close_connection;
361   }
362 #endif
363   if (!check_allowed_ip(allowed_nets, (union olsr_ip_addr *)&pin.sin_addr.s_addr)) {
364     struct ipaddr_str strbuf;
365     olsr_printf(0, "HTTP request from non-allowed host %s!\n",
366                 olsr_ip_to_string(&strbuf, (union olsr_ip_addr *)&pin.sin_addr.s_addr));
367     goto close_connection;
368   }
369
370   addr = inet_ntoa(pin.sin_addr);
371
372   memset(header_buf, 0, sizeof(header_buf));
373
374   while ((r = recv(client_socket, &header_buf[c], 1, 0)) > 0 && (c < sizeof(header_buf) - 1)) {
375     c++;
376
377     if ((c > 3 && !strcmp(&header_buf[c - 4], "\r\n\r\n")) || (c > 1 && !strcmp(&header_buf[c - 2], "\n\n")))
378       break;
379   }
380
381   if (r < 0) {
382     olsr_printf(1, "(HTTPINFO) Failed to recieve data from client!\n");
383     stats.err_hits++;
384     goto close_connection;
385   }
386
387   /* Get the request */
388   if (sscanf(header_buf, "%10s %250s %10s\n", req_type, filename, http_version) != 3) {
389     /* Try without HTTP version */
390     if (sscanf(header_buf, "%10s %250s\n", req_type, filename) != 2) {
391       olsr_printf(1, "(HTTPINFO) Error parsing request %s!\n", header_buf);
392       stats.err_hits++;
393       goto close_connection;
394     }
395   }
396
397   olsr_printf(1, "Request: %s\nfile: %s\nVersion: %s\n\n", req_type, filename, http_version);
398   abuf_init(&body_abuf, 102400);
399
400   if (!strcmp(req_type, "POST")) {
401 #ifdef ADMIN_INTERFACE
402     int i = 0;
403     while (dynamic_files[i].filename) {
404       printf("POST checking %s\n", dynamic_files[i].filename);
405       if (FILENREQ_MATCH(filename, dynamic_files[i].filename)) {
406         uint32_t param_size;
407
408         stats.ok_hits++;
409
410         param_size = recv(client_sockets[curr_clients], header_buf, sizeof(header_buf) - 1, 0);
411
412         header_buf[param_size] = '\0';
413         printf("Dynamic read %d bytes\n", param_size);
414
415         //memcpy(body, dynamic_files[i].data, static_bin_files[i].data_size);
416         body_length += dynamic_files[i].process_data_cb(header_buf, param_size, &body_buf[body_length], sizeof(body_buf) - body_length);
417         header_length = build_http_header(HTTP_OK, true, body_length, header_buf, sizeof(header_buf));
418         goto send_http_data;
419       }
420       i++;
421     }
422 #endif
423     /* We only support GET */
424     abuf_puts(&body_abuf, HTTP_400_MSG);
425     stats.ill_hits++;
426     header_length = build_http_header(HTTP_BAD_REQ, true, body_abuf.len, header_buf, sizeof(header_buf));
427   } else if (!strcmp(req_type, "GET")) {
428     int i = 0;
429
430     for (i = 0; static_bin_files[i].filename; i++) {
431       if (FILENREQ_MATCH(filename, static_bin_files[i].filename)) {
432         break;
433       }
434     }
435
436     if (static_bin_files[i].filename) {
437       stats.ok_hits++;
438       abuf_memcpy(&body_abuf, static_bin_files[i].data, static_bin_files[i].data_size);
439       header_length = build_http_header(HTTP_OK, false, body_abuf.len, header_buf, sizeof(header_buf));
440       goto send_http_data;
441     }
442
443     i = 0;
444     while (static_txt_files[i].filename) {
445       if (FILENREQ_MATCH(filename, static_txt_files[i].filename)) {
446         break;
447       }
448       i++;
449     }
450
451     if (static_txt_files[i].filename) {
452       stats.ok_hits++;
453       abuf_puts(&body_abuf, static_txt_files[i].data);
454       header_length = build_http_header(HTTP_OK, false, body_abuf.len, header_buf, sizeof(header_buf));
455       goto send_http_data;
456     }
457
458     i = 0;
459     if (strlen(filename) > 1) {
460       while (tab_entries[i].filename) {
461         if (FILENREQ_MATCH(filename, tab_entries[i].filename)) {
462           break;
463         }
464         i++;
465       }
466     }
467
468     if (tab_entries[i].filename) {
469 #ifdef NETDIRECT
470       header_length = build_http_header(HTTP_OK, true, body_length, header_buf, sizeof(header_buf));
471       r = send(client_sockets[curr_clients], header_buf, header_length, 0);
472       if (r < 0) {
473         olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
474         goto close_connection;
475       }
476       netsprintf_error = 0;
477       netsprintf_direct = 1;
478 #endif
479       abuf_appendf(&body_abuf,
480                  "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" "<head>\n"
481                  "<meta http-equiv=\"Content-type\" content=\"text/html; charset=ISO-8859-1\">\n"
482                  "<title>olsr.org httpinfo plugin</title>\n" "<link rel=\"icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
483                  "<link rel=\"shortcut icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
484                  "<link rel=\"stylesheet\" type=\"text/css\" href=\"httpinfo.css\">\n" "</head>\n"
485                  "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
486                  "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
487                  "<tbody><tr bgcolor=\"#ffffff\">\n" "<td align=\"left\" height=\"69\" valign=\"middle\" width=\"80%%\">\n"
488                  "<font color=\"black\" face=\"timesroman\" size=\"6\">&nbsp;&nbsp;&nbsp;<a href=\"http://www.olsr.org/\">olsr.org OLSR daemon</a></font></td>\n"
489                  "<td height=\"69\" valign=\"middle\" width=\"20%%\">\n"
490                  "<a href=\"http://www.olsr.org/\"><img border=\"0\" src=\"/logo.gif\" alt=\"olsrd logo\"></a></td>\n" "</tr>\n"
491                  "</tbody>\n" "</table>\n", FRAMEWIDTH);
492
493       build_tabs(&body_abuf, i);
494       build_frame(&body_abuf, "Current Routes", "routes", FRAMEWIDTH, tab_entries[i].build_body_cb);
495
496       stats.ok_hits++;
497
498       abuf_appendf(&body_abuf,
499                  "</table>\n" "<div id=\"footer\">\n" "<center>\n" "(C)2005 Andreas T&oslash;nnesen<br/>\n"
500                  "<a href=\"http://www.olsr.org/\">http://www.olsr.org</a>\n" "</center>\n" "</div>\n" "</body>\n" "</html>\n");
501
502 #ifdef NETDIRECT
503       netsprintf_direct = 1;
504       goto close_connection;
505 #else
506       header_length = build_http_header(HTTP_OK, true, body_abuf.len, header_buf, sizeof(header_buf));
507       goto send_http_data;
508 #endif
509     }
510
511     stats.ill_hits++;
512     abuf_puts(&body_abuf, HTTP_404_MSG);
513     header_length = build_http_header(HTTP_BAD_FILE, true, body_abuf.len, header_buf, sizeof(header_buf));
514   } else {
515     /* We only support GET */
516     abuf_puts(&body_abuf, HTTP_404_MSG);
517     stats.ill_hits++;
518     header_length = build_http_header(HTTP_BAD_REQ, true, body_abuf.len, header_buf, sizeof(header_buf));
519   }
520
521 send_http_data:
522   if (header_length + body_abuf.len > 0) {
523     outbuffer[outbuffer_count] = olsr_malloc(header_length + body_abuf.len, "http output buffer");
524     outbuffer_size[outbuffer_count] = header_length + body_abuf.len;
525     outbuffer_written[outbuffer_count] = 0;
526     outbuffer_socket[outbuffer_count] = client_socket;
527
528     memcpy(outbuffer[outbuffer_count], header_buf, header_length);
529     if (body_abuf.len > 0) {
530       memcpy((outbuffer[outbuffer_count]) + header_length, body_abuf.buf, body_abuf.len);
531     }
532     outbuffer_count++;
533
534     if (outbuffer_count == 1) {
535       writetimer_entry = olsr_start_timer(100, 0, OLSR_TIMER_PERIODIC, &httpinfo_write_data, NULL, 0);
536     }
537   }
538   abuf_free(&body_abuf);
539   return;
540
541 close_connection:
542   abuf_free(&body_abuf);
543   close(client_socket);
544 }
545
546 static void
547 httpinfo_write_data(void *foo __attribute__ ((unused))) {
548   fd_set set;
549   int result, i, j, max;
550   struct timeval tv;
551
552   FD_ZERO(&set);
553   max = 0;
554   for (i=0; i<outbuffer_count; i++) {
555     /* prevent warning in win32 */
556     FD_SET((unsigned int)outbuffer_socket[i], &set);
557     if (outbuffer_socket[i] > max) {
558       max = outbuffer_socket[i];
559     }
560   }
561
562   tv.tv_sec = 0;
563   tv.tv_usec = 0;
564
565   result = select(max + 1, NULL, &set, NULL, &tv);
566   if (result <= 0) {
567     return;
568   }
569
570   for (i=0; i<outbuffer_count; i++) {
571     if (FD_ISSET(outbuffer_socket[i], &set)) {
572       result = write(outbuffer_socket[i], outbuffer[i] + outbuffer_written[i], outbuffer_size[i] - outbuffer_written[i]);
573       if (result > 0) {
574         outbuffer_written[i] += result;
575       }
576
577       if (result <= 0 || outbuffer_written[i] == outbuffer_size[i]) {
578         /* close this socket and cleanup*/
579         close(outbuffer_socket[i]);
580         free (outbuffer[i]);
581
582         for (j=i+1; j<outbuffer_count; j++) {
583           outbuffer[j-1] = outbuffer[j];
584           outbuffer_size[j-1] = outbuffer_size[j];
585           outbuffer_socket[j-1] = outbuffer_socket[j];
586           outbuffer_written[j-1] = outbuffer_written[j];
587         }
588         outbuffer_count--;
589       }
590     }
591   }
592   if (outbuffer_count == 0) {
593     olsr_stop_timer(writetimer_entry);
594   }
595 }
596
597 int
598 build_http_header(http_header_type type, bool is_html, uint32_t msgsize, char *buf, uint32_t bufsize)
599 {
600   time_t currtime;
601   const char *h;
602   int size;
603
604   switch (type) {
605   case HTTP_BAD_REQ:
606     h = HTTP_400;
607     break;
608   case HTTP_BAD_FILE:
609     h = HTTP_404;
610     break;
611   default:
612     /* Defaults to OK */
613     h = HTTP_200;
614     break;
615   }
616   size = snprintf(buf, bufsize, "%s", h);
617
618   /* Date */
619   time(&currtime);
620   size += strftime(&buf[size], bufsize - size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
621
622   /* Server version */
623   size += snprintf(&buf[size], bufsize - size, "Server: %s %s %s\r\n", PLUGIN_NAME, PLUGIN_VERSION, HTTP_VERSION);
624
625   /* connection-type */
626   size += snprintf(&buf[size], bufsize - size, "Connection: closed\r\n");
627
628   /* MIME type */
629   size += snprintf(&buf[size], bufsize - size, "Content-type: text/%s\r\n", is_html ? "html" : "plain");
630
631   /* Content length */
632   if (msgsize > 0) {
633     size += snprintf(&buf[size], bufsize - size, "Content-length: %i\r\n", msgsize);
634   }
635
636   /* Cache-control
637    * No caching dynamic pages
638    */
639   size += snprintf(&buf[size], bufsize - size, "Cache-Control: no-cache\r\n");
640
641   if (!is_html) {
642     size += snprintf(&buf[size], bufsize - size, "Accept-Ranges: bytes\r\n");
643   }
644   /* End header */
645   size += snprintf(&buf[size], bufsize - size, "\r\n");
646
647   olsr_printf(1, "HEADER:\n%s", buf);
648
649   return size;
650 }
651
652 static void
653 build_tabs(struct autobuf *abuf, int active)
654 {
655   int tabs = 0;
656
657   abuf_appendf(abuf,
658       "<table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
659       "<tr bgcolor=\"#ffffff\"><td>\n" "<ul id=\"tabnav\">\n", FRAMEWIDTH);
660   for (tabs = 0; tab_entries[tabs].tab_label; tabs++) {
661     if (!tab_entries[tabs].display_tab) {
662       continue;
663     }
664     abuf_appendf(abuf, "<li><a href=\"%s\"%s>%s</a></li>\n", tab_entries[tabs].filename,
665                tabs == active ? " class=\"active\"" : "", tab_entries[tabs].tab_label);
666   }
667   abuf_appendf(abuf, "</ul>\n" "</td></tr>\n" "<tr><td>\n");
668 }
669
670 /*
671  * destructor - called at unload
672  */
673 void
674 olsr_plugin_exit(void)
675 {
676   struct allowed_net *a, *next;
677   if (http_socket >= 0) {
678     CLOSE(http_socket);
679   }
680
681   for (a = allowed_nets; a != NULL; a = next) {
682     next = a->next;
683
684     free(a);
685   }
686 }
687
688 static void
689 section_title(struct autobuf *abuf, const char *title)
690 {
691   abuf_appendf(abuf,
692                   "<h2>%s</h2>\n" "<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n",
693                   title);
694 }
695
696 static void
697 build_frame(struct autobuf *abuf, const char *title __attribute__ ((unused)), const char *the_link
698             __attribute__ ((unused)), int width __attribute__ ((unused)), build_body_callback frame_body_cb)
699 {
700   abuf_puts(abuf, "<div id=\"maintable\">\n");
701   frame_body_cb(abuf);
702   abuf_puts(abuf, "</div>\n");
703 }
704
705 static void
706 fmt_href(struct autobuf *abuf, const char *const ipaddr)
707 {
708   abuf_appendf(abuf, "<a href=\"http://%s:%d/all\">", ipaddr, http_port);
709 }
710
711 static void
712 build_ip_txt(struct autobuf *abuf, const bool print_link, const char *const ipaddrstr, const int prefix_len)
713 {
714   if (print_link) {
715     fmt_href(abuf, ipaddrstr);
716   }
717
718   abuf_puts(abuf, ipaddrstr);
719   /* print ip address or ip prefix ? */
720   if (prefix_len != -1 && prefix_len != olsr_cnf->maxplen) {
721     abuf_appendf(abuf, "/%d", prefix_len);
722   }
723
724   if (print_link) {             /* Print the link only if there is no prefix_len */
725     abuf_puts(abuf, "</a>");
726   }
727 }
728
729 static void
730 build_ipaddr_link(struct autobuf *abuf, const bool want_link, const union olsr_ip_addr *const ipaddr,
731                   const int prefix_len)
732 {
733   struct ipaddr_str ipaddrstr;
734   const struct hostent *const hp =
735 #ifndef WIN32
736     resolve_ip_addresses ? gethostbyaddr(ipaddr, olsr_cnf->ipsize,
737                                          olsr_cnf->ip_version) :
738 #endif
739     NULL;
740   /* Print the link only if there is no prefix_len and ip_version is AF_INET */
741   const int print_link = want_link && (prefix_len == -1 || prefix_len == olsr_cnf->maxplen) && (olsr_cnf->ip_version == AF_INET);
742   olsr_ip_to_string(&ipaddrstr, ipaddr);
743
744   abuf_puts(abuf, "<td>");
745   build_ip_txt(abuf, print_link, ipaddrstr.buf, prefix_len);
746   abuf_puts(abuf, "</td>");
747
748   if (resolve_ip_addresses) {
749     if (hp) {
750       abuf_puts(abuf, "<td>(");
751       if (print_link) {
752         fmt_href(abuf, ipaddrstr.buf);
753       }
754       abuf_puts(abuf, hp->h_name);
755       if (print_link) {
756         abuf_puts(abuf, "</a>");
757       }
758       abuf_puts(abuf, ")</td>");
759     } else {
760       abuf_puts(abuf, "<td/>");
761     }
762   }
763 }
764
765 #define build_ipaddr_with_link(buf, ipaddr, plen) \
766           build_ipaddr_link((buf), true, (ipaddr), (plen))
767 #define build_ipaddr_no_link(buf, ipaddr, plen) \
768           build_ipaddr_link((buf), false, (ipaddr), (plen))
769
770 static void
771 build_route(struct autobuf *abuf, const struct rt_entry *rt)
772 {
773   struct lqtextbuffer lqbuffer;
774
775   abuf_puts(abuf, "<tr>");
776   build_ipaddr_with_link(abuf, &rt->rt_dst.prefix, rt->rt_dst.prefix_len);
777   build_ipaddr_with_link(abuf, &rt->rt_best->rtp_nexthop.gateway, -1);
778
779   abuf_appendf(abuf, "<td>%d</td>", rt->rt_best->rtp_metric.hops);
780   abuf_appendf(abuf, "<td>%s</td>",
781              get_linkcost_text(rt->rt_best->rtp_metric.cost, true, &lqbuffer));
782   abuf_appendf(abuf, "<td>%s</td></tr>\n",
783              if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
784 }
785
786 static void
787 build_routes_body(struct autobuf *abuf)
788 {
789   struct rt_entry *rt;
790   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
791   section_title(abuf, "OLSR Routes in Kernel");
792   abuf_appendf(abuf,
793              "<tr><th%s>Destination</th><th%s>Gateway</th><th>Metric</th><th>ETX</th><th>Interface</th></tr>\n",
794              colspan, colspan);
795
796   /* Walk the route table */
797   OLSR_FOR_ALL_RT_ENTRIES(rt) {
798     build_route(abuf, rt);
799   } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
800
801   abuf_puts(abuf, "</table>\n");
802 }
803
804 static void
805 build_config_body(struct autobuf *abuf)
806 {
807   const struct olsr_if *ifs;
808   const struct plugin_entry *pentry;
809   const struct plugin_param *pparam;
810   struct ipaddr_str mainaddrbuf;
811
812   abuf_appendf(abuf, "Version: %s (built on %s on %s)\n<br>", olsrd_version, build_date, build_host);
813   abuf_appendf(abuf, "OS: %s\n<br>", OS);
814
815   {
816     const time_t currtime = time(NULL);
817
818     abuf_strftime(abuf, "System time: <em>%a, %d %b %Y %H:%M:%S</em><br>",
819                             localtime(&currtime));
820   }
821
822   {
823     struct timeval now, uptime;
824     int hours, mins, days;
825     gettimeofday(&now, NULL);
826     timersub(&now, &start_time, &uptime);
827
828     days = uptime.tv_sec / 86400;
829     uptime.tv_sec %= 86400;
830     hours = uptime.tv_sec / 3600;
831     uptime.tv_sec %= 3600;
832     mins = uptime.tv_sec / 60;
833     uptime.tv_sec %= 60;
834
835     abuf_puts(abuf, "Olsrd uptime: <em>");
836     if (days) {
837       abuf_appendf(abuf, "%d day(s) ", days);
838     }
839     abuf_appendf(abuf, "%02d hours %02d minutes %02d seconds</em><br/>\n", hours, mins, (int)uptime.tv_sec);
840   }
841
842   abuf_appendf(abuf, "HTTP stats(ok/dyn/error/illegal): <em>%d/%d/%d/%d</em><br>\n", stats.ok_hits,
843              stats.dyn_hits, stats.err_hits, stats.ill_hits);
844
845   abuf_puts(abuf,
846              "Click <a href=\"/cfgfile\">here</a> to <em>generate a configuration file for this node</em>.\n");
847
848   abuf_puts(abuf, "<h2>Variables</h2>\n");
849
850   abuf_puts(abuf, "<table width=\"100%%\" border=\"0\">\n<tr>");
851
852   abuf_appendf(abuf, "<td>Main address: <strong>%s</strong></td>\n",
853              olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
854   abuf_appendf(abuf, "<td>IP version: %d</td>\n", olsr_cnf->ip_version == AF_INET ? 4 : 6);
855   abuf_appendf(abuf, "<td>Debug level: %d</td>\n", olsr_cnf->debug_level);
856   abuf_appendf(abuf, "<td>FIB Metrics: %s</td>\n", FIB_METRIC_TXT[olsr_cnf->fib_metric]);
857
858   abuf_puts(abuf, "</tr>\n<tr>\n");
859
860   abuf_appendf(abuf, "<td>Pollrate: %0.2f</td>\n", olsr_cnf->pollrate);
861   abuf_appendf(abuf, "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
862   abuf_appendf(abuf, "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
863   abuf_appendf(abuf, "<td>NAT threshold: %f</td>\n", olsr_cnf->lq_nat_thresh);
864
865   abuf_puts(abuf, "</tr>\n<tr>\n");
866
867   abuf_appendf(abuf, "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
868   abuf_appendf(abuf, "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
869   abuf_appendf(abuf, "<td>RtTable: 0x%04x/%d</td>\n", olsr_cnf->rt_table, olsr_cnf->rt_table);
870   abuf_appendf(abuf, "<td>RtTableDefault: 0x%04x/%d</td>\n", olsr_cnf->rt_table_default,
871              olsr_cnf->rt_table_default);
872   abuf_appendf(abuf, "<td>RtTableTunnel: 0x%04x/%d</td>\n", olsr_cnf->rt_table_tunnel,
873              olsr_cnf->rt_table_tunnel);
874   abuf_appendf(abuf, "<td>Willingness: %d %s</td>\n", olsr_cnf->willingness,
875              olsr_cnf->willingness_auto ? "(auto)" : "");
876
877   if (olsr_cnf->lq_level == 0) {
878     abuf_appendf(abuf, "</tr>\n<tr>\n" "<td>Hysteresis: %s</td>\n",
879                olsr_cnf->use_hysteresis ? "Enabled" : "Disabled");
880     if (olsr_cnf->use_hysteresis) {
881       abuf_appendf(abuf, "<td>Hyst scaling: %0.2f</td>\n", olsr_cnf->hysteresis_param.scaling);
882       abuf_appendf(abuf, "<td>Hyst lower/upper: %0.2f/%0.2f</td>\n", olsr_cnf->hysteresis_param.thr_low,
883                  olsr_cnf->hysteresis_param.thr_high);
884     }
885   }
886
887   abuf_appendf(abuf, "</tr>\n<tr>\n" "<td>LQ extension: %s</td>\n",
888              olsr_cnf->lq_level ? "Enabled" : "Disabled");
889   if (olsr_cnf->lq_level) {
890     abuf_appendf(abuf, "<td>LQ level: %d</td>\n" "<td>LQ aging: %f</td>\n", olsr_cnf->lq_level,
891                olsr_cnf->lq_aging);
892   }
893   abuf_puts(abuf, "</tr></table>\n");
894
895   abuf_puts(abuf, "<h2>Interfaces</h2>\n");
896   abuf_puts(abuf, "<table width=\"100%%\" border=\"0\">\n");
897   for (ifs = olsr_cnf->interfaces; ifs != NULL; ifs = ifs->next) {
898     const struct interface *const rifs = ifs->interf;
899     abuf_appendf(abuf, "<tr><th colspan=\"3\">%s</th>\n", ifs->name);
900     if (!rifs) {
901       abuf_puts(abuf, "<tr><td colspan=\"3\">Status: DOWN</td></tr>\n");
902       continue;
903     }
904
905     if (olsr_cnf->ip_version == AF_INET) {
906       struct ipaddr_str addrbuf, maskbuf, bcastbuf;
907       abuf_appendf(abuf, "<tr>\n" "<td>IP: %s</td>\n" "<td>MASK: %s</td>\n" "<td>BCAST: %s</td>\n" "</tr>\n",
908                  ip4_to_string(&addrbuf, rifs->int_addr.sin_addr), ip4_to_string(&maskbuf, rifs->int_netmask.sin_addr),
909                  ip4_to_string(&bcastbuf, rifs->int_broadaddr.sin_addr));
910     } else {
911       struct ipaddr_str addrbuf, maskbuf;
912       abuf_appendf(abuf, "<tr>\n" "<td>IP: %s</td>\n" "<td>MCAST: %s</td>\n" "<td></td>\n" "</tr>\n",
913                  ip6_to_string(&addrbuf, &rifs->int6_addr.sin6_addr), ip6_to_string(&maskbuf, &rifs->int6_multaddr.sin6_addr));
914     }
915     abuf_appendf(abuf, "<tr>\n" "<td>MTU: %d</td>\n" "<td>WLAN: %s</td>\n" "<td>STATUS: UP</td>\n" "</tr>\n",
916                rifs->int_mtu, rifs->is_wireless ? "Yes" : "No");
917   }
918   abuf_puts(abuf, "</table>\n");
919
920   abuf_appendf(abuf, "<em>Olsrd is configured to %s if no interfaces are available</em><br>\n",
921              olsr_cnf->allow_no_interfaces ? "run even" : "halt");
922
923   abuf_puts(abuf, "<h2>Plugins</h2>\n");
924   abuf_puts(abuf, "<table width=\"100%%\" border=\"0\"><tr><th>Name</th><th>Parameters</th></tr>\n");
925   for (pentry = olsr_cnf->plugins; pentry; pentry = pentry->next) {
926     abuf_appendf(abuf, "<tr><td>%s</td>\n" "<td><select>\n" "<option>KEY, VALUE</option>\n", pentry->name);
927
928     for (pparam = pentry->params; pparam; pparam = pparam->next) {
929       abuf_appendf(abuf, "<option>\"%s\", \"%s\"</option>\n", pparam->key, pparam->value);
930     }
931     abuf_puts(abuf, "</select></td></tr>\n");
932
933   }
934   abuf_puts(abuf, "</table>\n");
935
936   section_title(abuf, "Announced HNA entries");
937   if (olsr_cnf->hna_entries) {
938     struct ip_prefix_list *hna;
939     abuf_puts(abuf, "<tr><th>Network</th></tr>\n");
940     for (hna = olsr_cnf->hna_entries; hna; hna = hna->next) {
941       struct ipaddr_str netbuf;
942       abuf_appendf(abuf, "<tr><td>%s/%d</td></tr>\n", olsr_ip_to_string(&netbuf, &hna->net.prefix),
943                  hna->net.prefix_len);
944     }
945   } else {
946     abuf_puts(abuf, "<tr><td></td></tr>\n");
947   }
948   abuf_puts(abuf, "</table>\n");
949 }
950
951 static void
952 build_neigh_body(struct autobuf *abuf)
953 {
954   struct neighbor_entry *neigh;
955   struct link_entry *the_link = NULL;
956   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
957
958   section_title(abuf, "Links");
959
960   abuf_appendf(abuf,
961              "<tr><th%s>Local IP</th><th%s>Remote IP</th><th>Hysteresis</th>",
962              colspan, colspan);
963   if (olsr_cnf->lq_level > 0) {
964     abuf_puts(abuf, "<th>LinkCost</th>");
965   }
966   abuf_puts(abuf, "</tr>\n");
967
968   /* Link set */
969   OLSR_FOR_ALL_LINK_ENTRIES(the_link) {
970     abuf_puts(abuf, "<tr>");
971     build_ipaddr_with_link(abuf, &the_link->local_iface_addr, -1);
972     build_ipaddr_with_link(abuf, &the_link->neighbor_iface_addr, -1);
973     abuf_appendf(abuf, "<td>%0.2f</td>", the_link->L_link_quality);
974     if (olsr_cnf->lq_level > 0) {
975       struct lqtextbuffer lqbuffer1, lqbuffer2;
976       abuf_appendf(abuf, "<td>(%s) %s</td>", get_link_entry_text(the_link, '/', &lqbuffer1),
977                  get_linkcost_text(the_link->linkcost, false, &lqbuffer2));
978     }
979     abuf_puts(abuf, "</tr>\n");
980   } OLSR_FOR_ALL_LINK_ENTRIES_END(the_link);
981
982   abuf_puts(abuf, "</table>\n");
983
984   section_title(abuf, "Neighbors");
985   abuf_appendf(abuf,
986              "<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",
987              colspan);
988   /* Neighbors */
989   OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
990
991     struct neighbor_2_list_entry *list_2;
992     int thop_cnt;
993     abuf_puts(abuf, "<tr>");
994     build_ipaddr_with_link(abuf, &neigh->neighbor_main_addr, -1);
995     abuf_appendf(abuf,
996                "<td>%s</td>" "<td>%s</td>" "<td>%s</td>"
997                "<td>%d</td>", (neigh->status == SYM) ? "YES" : "NO", neigh->is_mpr ? "YES" : "NO",
998                olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO", neigh->willingness);
999
1000     abuf_puts(abuf, "<td><select>\n" "<option>IP ADDRESS</option>\n");
1001
1002     for (list_2 = neigh->neighbor_2_list.next, thop_cnt = 0; list_2 != &neigh->neighbor_2_list; list_2 = list_2->next, thop_cnt++) {
1003       struct ipaddr_str strbuf;
1004       abuf_appendf(abuf, "<option>%s</option>\n",
1005                  olsr_ip_to_string(&strbuf, &list_2->neighbor_2->neighbor_2_addr));
1006     }
1007     abuf_appendf(abuf, "</select> (%d)</td></tr>\n", thop_cnt);
1008   } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
1009
1010   abuf_puts(abuf, "</table>\n");
1011 }
1012
1013 static void
1014 build_topo_body(struct autobuf *abuf)
1015 {
1016   struct tc_entry *tc;
1017   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
1018
1019   section_title(abuf, "Topology Entries");
1020   abuf_appendf(abuf, "<tr><th%s>Destination IP</th><th%s>Last Hop IP</th>",
1021              colspan, colspan);
1022   if (olsr_cnf->lq_level > 0) {
1023     abuf_puts(abuf, "<th>Linkcost</th>");
1024   }
1025   abuf_puts(abuf, "</tr>\n");
1026
1027   OLSR_FOR_ALL_TC_ENTRIES(tc) {
1028     struct tc_edge_entry *tc_edge;
1029     OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
1030       if (tc_edge->edge_inv) {
1031         abuf_puts(abuf, "<tr>");
1032         build_ipaddr_with_link(abuf, &tc_edge->T_dest_addr, -1);
1033         build_ipaddr_with_link(abuf, &tc->addr, -1);
1034         if (olsr_cnf->lq_level > 0) {
1035           struct lqtextbuffer lqbuffer1, lqbuffer2;
1036           abuf_appendf(abuf, "<td>(%s) %s</td>\n",
1037                      get_tc_edge_entry_text(tc_edge, '/', &lqbuffer1), get_linkcost_text(tc_edge->cost, false, &lqbuffer2));
1038         }
1039         abuf_puts(abuf, "</tr>\n");
1040       }
1041     } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
1042   } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
1043
1044   abuf_puts(abuf, "</table>\n");
1045 }
1046
1047 static void
1048 build_mid_body(struct autobuf *abuf)
1049 {
1050   int idx;
1051   const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
1052
1053   section_title(abuf, "MID Entries");
1054   abuf_appendf(abuf, "<tr><th%s>Main Address</th><th>Aliases</th></tr>\n", colspan);
1055
1056   /* MID */
1057   for (idx = 0; idx < HASHSIZE; idx++) {
1058     struct mid_entry *entry;
1059     for (entry = mid_set[idx].next; entry != &mid_set[idx]; entry = entry->next) {
1060       int mid_cnt;
1061       struct mid_address *alias;
1062       abuf_puts(abuf, "<tr>");
1063       build_ipaddr_with_link(abuf, &entry->main_addr, -1);
1064       abuf_puts(abuf, "<td><select>\n<option>IP ADDRESS</option>\n");
1065
1066       for (mid_cnt = 0, alias = entry->aliases; alias != NULL; alias = alias->next_alias, mid_cnt++) {
1067         struct ipaddr_str strbuf;
1068         abuf_appendf(abuf, "<option>%s</option>\n", olsr_ip_to_string(&strbuf, &alias->alias));
1069       }
1070       abuf_appendf(abuf, "</select> (%d)</td></tr>\n", mid_cnt);
1071     }
1072   }
1073
1074   abuf_puts(abuf, "</table>\n");
1075 }
1076
1077 static void
1078 build_nodes_body(struct autobuf *abuf)
1079 {
1080   build_neigh_body(abuf);
1081   build_topo_body(abuf);
1082   build_mid_body(abuf);
1083 }
1084
1085 static void
1086 build_all_body(struct autobuf *abuf)
1087 {
1088   build_config_body(abuf);
1089   build_routes_body(abuf);
1090   build_neigh_body(abuf);
1091   build_topo_body(abuf);
1092   build_mid_body(abuf);
1093 }
1094
1095 static void
1096 build_about_body(struct autobuf *abuf)
1097 {
1098   abuf_appendf(abuf,
1099                   "<strong>" PLUGIN_NAME " version " PLUGIN_VERSION "</strong><br/>\n" "by Andreas T&oslash;nnesen (C)2005.<br/>\n"
1100                   "Compiled "
1101 #ifdef ADMIN_INTERFACE
1102                   "<em>with experimental admin interface</em> "
1103 #endif
1104                   "%s at %s<hr/>\n" "This plugin implements a HTTP server that supplies\n"
1105                   "the client with various dynamic web pages representing\n"
1106                   "the current olsrd status.<br/>The different pages include:\n"
1107                   "<ul>\n<li><strong>Configuration</strong> - This page displays information\n"
1108                   "about the current olsrd configuration. This includes various\n"
1109                   "olsr settings such as IP version, MID/TC redundancy, hysteresis\n"
1110                   "etc. Information about the current status of the interfaces on\n"
1111                   "which olsrd is configured to run is also displayed. Loaded olsrd\n"
1112                   "plugins are shown with their plugin parameters. Finally all local\n"
1113                   "HNA entries are shown. These are the networks that the local host\n"
1114                   "will anounce itself as a gateway to.</li>\n"
1115                   "<li><strong>Routes</strong> - This page displays all routes currently set in\n"
1116                   "the kernel <em>by olsrd</em>. The type of route is also displayed(host\n" "or HNA).</li>\n"
1117                   "<li><strong>Links/Topology</strong> - This page displays all information about\n"
1118                   "links, neighbors, topology, MID and HNA entries.</li>\n"
1119                   "<li><strong>All</strong> - Here all the previous pages are displayed as one.\n"
1120                   "This is to make all information available as easy as possible(for example\n"
1121                   "for a script) and using as few resources as possible.</li>\n"
1122 #ifdef ADMIN_INTERFACE
1123                   "<li><strong>Admin</strong> - This page is highly experimental(and unsecure)!\n"
1124                   "As of now it is not working at all but it provides a impression of\n"
1125                   "the future possibilities of httpinfo. This is to be a interface to\n"
1126                   "changing olsrd settings in realtime. These settings include various\n"
1127                   "\"basic\" settings and local HNA settings.</li>\n"
1128 #endif
1129                   "<li><strong>About</strong> - this help page.</li>\n</ul>" "<hr/>\n" "Send questions or comments to\n"
1130                   "<a href=\"mailto:olsr-users@olsr.org\">olsr-users@olsr.org</a> or\n"
1131                   "<a href=\"mailto:andreto-at-olsr.org\">andreto-at-olsr.org</a><br/>\n"
1132                   "Official olsrd homepage: <a href=\"http://www.olsr.org/\">http://www.olsr.org</a><br/>\n", build_date,
1133                   build_host);
1134 }
1135
1136 static void
1137 build_cfgfile_body(struct autobuf *abuf)
1138 {
1139   abuf_puts(abuf,
1140              "\n\n" "<strong>This is a automatically generated configuration\n"
1141              "file based on the current olsrd configuration of this node.<br/>\n" "<hr/>\n" "<pre>\n");
1142   olsrd_write_cnf_autobuf(abuf, olsr_cnf);
1143
1144   abuf_puts(abuf, "</pre>\n<hr/>\n");
1145
1146 #if 0
1147   printf("RETURNING %d\n", size);
1148 #endif
1149 }
1150
1151 static int
1152 check_allowed_ip(const struct allowed_net *const my_allowed_nets, const union olsr_ip_addr *const addr)
1153 {
1154   const struct allowed_net *alln;
1155   for (alln = my_allowed_nets; alln != NULL; alln = alln->next) {
1156     if ((addr->v4.s_addr & alln->mask.v4.s_addr) == (alln->net.v4.s_addr & alln->mask.v4.s_addr)) {
1157       return 1;
1158     }
1159   }
1160   return 0;
1161 }
1162
1163 #if 0
1164
1165 /*
1166  * In a bigger mesh, there are probs with the fixed
1167  * bufsize. Because the Content-Length header is
1168  * optional, the sprintf() is changed to a more
1169  * scalable solution here.
1170  */
1171
1172 int
1173 netsprintf(char *str, const char *format, ...)
1174 {
1175   va_list arg;
1176   int rv;
1177   va_start(arg, format);
1178   rv = vsprintf(str, format, arg);
1179   va_end(arg);
1180   if (0 != netsprintf_direct) {
1181     if (0 == netsprintf_error) {
1182       if (0 > send(client_sockets[curr_clients], str, rv, 0)) {
1183         olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
1184         netsprintf_error = 1;
1185       }
1186     }
1187     return 0;
1188   }
1189   return rv;
1190 }
1191 #endif
1192
1193 /*
1194  * Local Variables:
1195  * c-basic-offset: 2
1196  * indent-tabs-mode: nil
1197  * End:
1198  */