Fix ipcalc.h for bsd
[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 "socket_parser.h"
64 #include "ipcalc.h"
65 #include "lq_plugin.h"
66 #include "common/autobuf.h"
67
68 #include "olsrd_httpinfo.h"
69 #include "admin_interface.h"
70 #include "gfx.h"
71
72 #ifdef OS
73 #undef OS
74 #endif
75
76 #ifdef WIN32
77 #define close(x) closesocket(x)
78 #define OS "Windows"
79 #endif
80 #ifdef linux
81 #define OS "GNU/Linux"
82 #endif
83 #if defined __FreeBSD__ || defined __FreeBSD_kernel__
84 #define OS "FreeBSD"
85 #endif
86
87 #ifndef OS
88 #define OS "Undefined"
89 #endif
90
91 static char copyright_string[] __attribute__ ((unused)) =
92   "olsr.org HTTPINFO plugin Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
93
94 #define MAX_CLIENTS 3
95
96 #define MAX_HTTPREQ_SIZE (1024 * 10)
97
98 #define DEFAULT_TCP_PORT 1978
99
100 #define HTML_BUFSIZE (1024 * 4000)
101
102 #define FRAMEWIDTH (resolve_ip_addresses ? 900 : 800)
103
104 #define FILENREQ_MATCH(req, filename) \
105         !strcmp(req, filename) || \
106         (strlen(req) && !strcmp(&req[1], filename))
107
108 static const char httpinfo_css[] =
109   "#A {text-decoration: none}\n" "TH{text-align: left}\n" "H1, H3, TD, TH {font-family: Helvetica; font-size: 80%}\n"
110   "h2\n {\nfont-family: Helvetica;\n font-size: 14px;text-align: center;\n"
111   "line-height: 16px;\ntext-decoration: none;\nborder: 1px solid #ccc;\n" "margin: 5px;\nbackground: #ececec;\n}\n"
112   "hr\n{\nborder: none;\npadding: 1px;\nbackground: url(grayline.gif) repeat-x bottom;\n}\n"
113   "#maintable\n{\nmargin: 0px;\npadding: 5px;\nborder-left: 1px solid #ccc;\n"
114   "border-right: 1px solid #ccc;\nborder-bottom: 1px solid #ccc;\n}\n"
115   "#footer\n{\nfont-size: 10px;\nline-height: 14px;\ntext-decoration: none;\ncolor: #666;\n}\n"
116   "#hdr\n{\nfont-size: 14px;\ntext-align: center;\nline-height: 16px;\n" "text-decoration: none;\nborder: 1px solid #ccc;\n"
117   "margin: 5px;\nbackground: #ececec;\n}\n"
118   "#container\n{\nwidth: 1000px;\npadding: 30px;\nborder: 1px solid #ccc;\nbackground: #fff;\n}\n"
119   "#tabnav\n{\nheight: 20px;\nmargin: 0;\npadding-left: 10px;\n" "background: url(grayline.gif) repeat-x bottom;\n}\n"
120   "#tabnav li\n{\nmargin: 0;\npadding: 0;\ndisplay: inline;\nlist-style-type: none;\n}\n"
121   "#tabnav a:link, #tabnav a:visited\n{\nfloat: left;\nbackground: #ececec;\n"
122   "font-size: 12px;\nline-height: 14px;\nfont-weight: bold;\npadding: 2px 10px 2px 10px;\n"
123   "margin-right: 4px;\nborder: 1px solid #ccc;\ntext-decoration: none;\ncolor: #777;\n}\n"
124   "#tabnav a:link.active, #tabnav a:visited.active\n{\nborder-bottom: 1px solid #fff;\n" "background: #ffffff;\ncolor: #000;\n}\n"
125   "#tabnav a:hover\n{\nbackground: #777777;\ncolor: #ffffff;\n}\n"
126   ".input_text\n{\nbackground: #E5E5E5;\nmargin-left: 5px; margin-top: 0px;\n"
127   "text-align: left;\n\nwidth: 100px;\npadding: 0px;\ncolor: #000000;\n"
128   "text-decoration: none;\nfont-family: verdana;\nfont-size: 12px;\n" "border: 1px solid #ccc;\n}\n"
129   ".input_button\n{\nbackground: #B5D1EE;\nmargin-left: 5px;\nmargin-top: 0px;\n"
130   "text-align: center;\nwidth: 120px;\npadding: 0px;\ncolor: #000000;\n"
131   "text-decoration: none;\nfont-family: verdana;\nfont-size: 12px;\n" "border: 1px solid #000;\n}\n";
132
133 typedef void (*build_body_callback) (struct autobuf *);
134
135 struct tab_entry {
136   const char *tab_label;
137   const char *filename;
138   build_body_callback build_body_cb;
139   bool display_tab;
140 };
141
142 struct static_bin_file_entry {
143   const char *filename;
144   unsigned char *data;
145   unsigned int data_size;
146 };
147
148 struct static_txt_file_entry {
149   const char *filename;
150   const char *data;
151 };
152
153 struct dynamic_file_entry {
154   const char *filename;
155   int (*process_data_cb) (char *, uint32_t, char *, uint32_t);
156 };
157
158 static int get_http_socket(int);
159
160 static void build_tabs(struct autobuf *, int);
161
162 static void parse_http_request(int);
163
164 static int build_http_header(http_header_type, bool, uint32_t, char *, uint32_t);
165
166 static void build_frame(struct autobuf *, const char *, const char *, int, build_body_callback frame_body_cb);
167
168 static void build_routes_body(struct autobuf *);
169
170 static void build_config_body(struct autobuf *);
171
172 static void build_neigh_body(struct autobuf *);
173
174 static void build_topo_body(struct autobuf *);
175
176 static void build_mid_body(struct autobuf *);
177
178 static void build_nodes_body(struct autobuf *);
179
180 static void build_all_body(struct autobuf *);
181
182 static void build_about_body(struct autobuf *);
183
184 static void build_cfgfile_body(struct autobuf *);
185
186 static int check_allowed_ip(const struct allowed_net *const allowed_nets, const union olsr_ip_addr *const addr);
187
188 static void build_ip_txt(struct autobuf *, const bool want_link, const char *const ipaddrstr, const int prefix_len);
189
190 static void build_ipaddr_link(struct autobuf *, const bool want_link, const union olsr_ip_addr *const ipaddr,
191                              const int prefix_len);
192 static void section_title(struct autobuf *, const char *title);
193
194 static void httpinfo_write_data(void *foo);
195
196 static struct timeval start_time;
197 static struct http_stats stats;
198 static int http_socket;
199
200 static char *outbuffer[MAX_CLIENTS];
201 static size_t outbuffer_size[MAX_CLIENTS];
202 static size_t outbuffer_written[MAX_CLIENTS];
203 static int outbuffer_socket[MAX_CLIENTS];
204 static int outbuffer_count;
205
206 static struct timer_entry *writetimer_entry;
207
208 #if 0
209 int netsprintf(char *str, const char *format, ...) __attribute__ ((format(printf, 2, 3)));
210 static int netsprintf_direct = 0;
211 static int netsprintf_error = 0;
212 #define sprintf netsprintf
213 #define NETDIRECT
214 #endif
215
216 static const struct tab_entry tab_entries[] = {
217   {"Configuration", "config", build_config_body, true},
218   {"Routes", "routes", build_routes_body, true},
219   {"Links/Topology", "nodes", build_nodes_body, true},
220   {"All", "all", build_all_body, true},
221 #ifdef ADMIN_INTERFACE
222   {"Admin", "admin", build_admin_body, true},
223 #endif
224   {"About", "about", build_about_body, true},
225   {"FOO", "cfgfile", build_cfgfile_body, false},
226   {NULL, NULL, NULL, false}
227 };
228
229 static const struct static_bin_file_entry static_bin_files[] = {
230   {"favicon.ico", favicon_ico, sizeof(favicon_ico)}
231   ,
232   {"logo.gif", logo_gif, sizeof(logo_gif)}
233   ,
234   {"grayline.gif", grayline_gif, sizeof(grayline_gif)}
235   ,
236   {NULL, NULL, 0}
237 };
238
239 static const struct static_txt_file_entry static_txt_files[] = {
240   {"httpinfo.css", httpinfo_css},
241   {NULL, NULL}
242 };
243
244 static const struct dynamic_file_entry dynamic_files[] = {
245 #ifdef ADMIN_INTERFACE
246   {"set_values", process_set_values},
247 #endif
248   {NULL, NULL}
249 };
250
251 static int
252 get_http_socket(int port)
253 {
254   struct sockaddr_in sock_in;
255   uint32_t yes = 1;
256
257   /* Init ipc socket */
258   int s = socket(AF_INET, SOCK_STREAM, 0);
259   if (s == -1) {
260     olsr_printf(1, "(HTTPINFO)socket %s\n", strerror(errno));
261     return -1;
262   }
263
264   if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
265     olsr_printf(1, "(HTTPINFO)SO_REUSEADDR failed %s\n", strerror(errno));
266     close(s);
267     return -1;
268   }
269
270   /* Bind the socket */
271
272   /* complete the socket structure */
273   memset(&sock_in, 0, sizeof(sock_in));
274   sock_in.sin_family = AF_INET;
275   sock_in.sin_addr.s_addr = httpinfo_listen_ip.v4.s_addr;
276   sock_in.sin_port = htons(port);
277
278   /* bind the socket to the port number */
279   if (bind(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) == -1) {
280     olsr_printf(1, "(HTTPINFO) bind failed %s\n", strerror(errno));
281     close(s);
282     return -1;
283   }
284
285   /* show that we are willing to listen */
286   if (listen(s, 1) == -1) {
287     olsr_printf(1, "(HTTPINFO) listen failed %s\n", strerror(errno));
288     close(s);
289     return -1;
290   }
291
292   return s;
293 }
294
295 /**
296  *Do initialization here
297  *
298  *This function is called by the my_init
299  *function in uolsrd_plugin.c
300  */
301 int
302 olsrd_plugin_init(void)
303 {
304   /* Get start time */
305   gettimeofday(&start_time, NULL);
306
307   /* set up HTTP socket */
308   http_socket = get_http_socket(http_port != 0 ? http_port : DEFAULT_TCP_PORT);
309
310   if (http_socket < 0) {
311     fprintf(stderr, "(HTTPINFO) could not initialize HTTP socket\n");
312     exit(0);
313   }
314
315   /* Register socket */
316   add_olsr_socket(http_socket, &parse_http_request);
317
318   return 1;
319 }
320
321 /* Non reentrant - but we are not multithreaded anyway */
322 void
323 parse_http_request(int fd)
324 {
325   struct sockaddr_in pin;
326   struct autobuf body_abuf = { 0, 0, NULL };
327   socklen_t addrlen;
328   char *addr;
329   char header_buf[MAX_HTTPREQ_SIZE];
330   char req_type[11];
331   char filename[251];
332   char http_version[11];
333   int client_socket;
334   size_t header_length = 0;
335   size_t c = 0;
336   int r = 1;
337 #ifdef linux
338   struct timeval timeout = { 0, 200 };
339 #endif
340
341   if (outbuffer_count >= MAX_CLIENTS) {
342     olsr_printf(1, "(HTTPINFO) maximum number of connection reached\n");
343     return;
344   }
345
346   addrlen = sizeof(struct sockaddr_in);
347   client_socket = accept(fd, (struct sockaddr *)&pin, &addrlen);
348   if (client_socket == -1) {
349     olsr_printf(1, "(HTTPINFO) accept: %s\n", strerror(errno));
350     goto close_connection;
351   }
352
353 #ifdef linux
354   if (setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
355     olsr_printf(1, "(HTTPINFO)SO_RCVTIMEO failed %s\n", strerror(errno));
356     goto close_connection;
357   }
358
359   if (setsockopt(client_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
360     olsr_printf(1, "(HTTPINFO)SO_SNDTIMEO failed %s\n", strerror(errno));
361     goto close_connection;
362   }
363 #endif
364   if (!check_allowed_ip(allowed_nets, (union olsr_ip_addr *)&pin.sin_addr.s_addr)) {
365     struct ipaddr_str strbuf;
366     olsr_printf(0, "HTTP request from non-allowed host %s!\n",
367                 olsr_ip_to_string(&strbuf, (union olsr_ip_addr *)&pin.sin_addr.s_addr));
368     goto close_connection;
369   }
370
371   addr = inet_ntoa(pin.sin_addr);
372
373   memset(header_buf, 0, sizeof(header_buf));
374
375   while ((r = recv(client_socket, &header_buf[c], 1, 0)) > 0 && (c < sizeof(header_buf) - 1)) {
376     c++;
377
378     if ((c > 3 && !strcmp(&header_buf[c - 4], "\r\n\r\n")) || (c > 1 && !strcmp(&header_buf[c - 2], "\n\n")))
379       break;
380   }
381
382   if (r < 0) {
383     olsr_printf(1, "(HTTPINFO) Failed to recieve data from client!\n");
384     stats.err_hits++;
385     goto close_connection;
386   }
387
388   /* Get the request */
389   if (sscanf(header_buf, "%10s %250s %10s\n", req_type, filename, http_version) != 3) {
390     /* Try without HTTP version */
391     if (sscanf(header_buf, "%10s %250s\n", req_type, filename) != 2) {
392       olsr_printf(1, "(HTTPINFO) Error parsing request %s!\n", header_buf);
393       stats.err_hits++;
394       goto close_connection;
395     }
396   }
397
398   olsr_printf(1, "Request: %s\nfile: %s\nVersion: %s\n\n", req_type, filename, http_version);
399   abuf_init(&body_abuf, 102400);
400
401   if (!strcmp(req_type, "POST")) {
402 #ifdef ADMIN_INTERFACE
403     int i = 0;
404     while (dynamic_files[i].filename) {
405       printf("POST checking %s\n", dynamic_files[i].filename);
406       if (FILENREQ_MATCH(filename, dynamic_files[i].filename)) {
407         uint32_t param_size;
408
409         stats.ok_hits++;
410
411         param_size = recv(client_sockets[curr_clients], header_buf, sizeof(header_buf) - 1, 0);
412
413         header_buf[param_size] = '\0';
414         printf("Dynamic read %d bytes\n", param_size);
415
416         //memcpy(body, dynamic_files[i].data, static_bin_files[i].data_size);
417         body_length += dynamic_files[i].process_data_cb(header_buf, param_size, &body_buf[body_length], sizeof(body_buf) - body_length);
418         header_length = build_http_header(HTTP_OK, true, body_length, header_buf, sizeof(header_buf));
419         goto send_http_data;
420       }
421       i++;
422     }
423 #endif
424     /* We only support GET */
425     abuf_puts(&body_abuf, HTTP_400_MSG);
426     stats.ill_hits++;
427     header_length = build_http_header(HTTP_BAD_REQ, true, body_abuf.len, header_buf, sizeof(header_buf));
428   } else if (!strcmp(req_type, "GET")) {
429     int i = 0;
430
431     for (i = 0; static_bin_files[i].filename; i++) {
432       if (FILENREQ_MATCH(filename, static_bin_files[i].filename)) {
433         break;
434       }
435     }
436
437     if (static_bin_files[i].filename) {
438       stats.ok_hits++;
439       abuf_memcpy(&body_abuf, static_bin_files[i].data, static_bin_files[i].data_size);
440       header_length = build_http_header(HTTP_OK, false, body_abuf.len, header_buf, sizeof(header_buf));
441       goto send_http_data;
442     }
443
444     i = 0;
445     while (static_txt_files[i].filename) {
446       if (FILENREQ_MATCH(filename, static_txt_files[i].filename)) {
447         break;
448       }
449       i++;
450     }
451
452     if (static_txt_files[i].filename) {
453       stats.ok_hits++;
454       abuf_puts(&body_abuf, static_txt_files[i].data);
455       header_length = build_http_header(HTTP_OK, false, body_abuf.len, header_buf, sizeof(header_buf));
456       goto send_http_data;
457     }
458
459     i = 0;
460     if (strlen(filename) > 1) {
461       while (tab_entries[i].filename) {
462         if (FILENREQ_MATCH(filename, tab_entries[i].filename)) {
463           break;
464         }
465         i++;
466       }
467     }
468
469     if (tab_entries[i].filename) {
470 #ifdef NETDIRECT
471       header_length = build_http_header(HTTP_OK, true, body_length, header_buf, sizeof(header_buf));
472       r = send(client_sockets[curr_clients], header_buf, header_length, 0);
473       if (r < 0) {
474         olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
475         goto close_connection;
476       }
477       netsprintf_error = 0;
478       netsprintf_direct = 1;
479 #endif
480       abuf_appendf(&body_abuf,
481                  "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" "<head>\n"
482                  "<meta http-equiv=\"Content-type\" content=\"text/html; charset=ISO-8859-1\">\n"
483                  "<title>olsr.org httpinfo plugin</title>\n" "<link rel=\"icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
484                  "<link rel=\"shortcut icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
485                  "<link rel=\"stylesheet\" type=\"text/css\" href=\"httpinfo.css\">\n" "</head>\n"
486                  "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
487                  "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
488                  "<tbody><tr bgcolor=\"#ffffff\">\n" "<td align=\"left\" height=\"69\" valign=\"middle\" width=\"80%%\">\n"
489                  "<font color=\"black\" face=\"timesroman\" size=\"6\">&nbsp;&nbsp;&nbsp;<a href=\"http://www.olsr.org/\">olsr.org OLSR daemon</a></font></td>\n"
490                  "<td height=\"69\" valign=\"middle\" width=\"20%%\">\n"
491                  "<a href=\"http://www.olsr.org/\"><img border=\"0\" src=\"/logo.gif\" alt=\"olsrd logo\"></a></td>\n" "</tr>\n"
492                  "</tbody>\n" "</table>\n", FRAMEWIDTH);
493
494       build_tabs(&body_abuf, i);
495       build_frame(&body_abuf, "Current Routes", "routes", FRAMEWIDTH, tab_entries[i].build_body_cb);
496
497       stats.ok_hits++;
498
499       abuf_appendf(&body_abuf,
500                  "</table>\n" "<div id=\"footer\">\n" "<center>\n" "(C)2005 Andreas T&oslash;nnesen<br/>\n"
501                  "<a href=\"http://www.olsr.org/\">http://www.olsr.org</a>\n" "</center>\n" "</div>\n" "</body>\n" "</html>\n");
502
503 #ifdef NETDIRECT
504       netsprintf_direct = 1;
505       goto close_connection;
506 #else
507       header_length = build_http_header(HTTP_OK, true, body_abuf.len, header_buf, sizeof(header_buf));
508       goto send_http_data;
509 #endif
510     }
511
512     stats.ill_hits++;
513     abuf_puts(&body_abuf, HTTP_404_MSG);
514     header_length = build_http_header(HTTP_BAD_FILE, true, body_abuf.len, header_buf, sizeof(header_buf));
515   } else {
516     /* We only support GET */
517     abuf_puts(&body_abuf, HTTP_404_MSG);
518     stats.ill_hits++;
519     header_length = build_http_header(HTTP_BAD_REQ, true, body_abuf.len, header_buf, sizeof(header_buf));
520   }
521
522 send_http_data:
523   if (header_length + body_abuf.len > 0) {
524     outbuffer[outbuffer_count] = olsr_malloc(header_length + body_abuf.len, "http output buffer");
525     outbuffer_size[outbuffer_count] = header_length + body_abuf.len;
526     outbuffer_written[outbuffer_count] = 0;
527     outbuffer_socket[outbuffer_count] = client_socket;
528
529     memcpy(outbuffer[outbuffer_count], header_buf, header_length);
530     if (body_abuf.len > 0) {
531       memcpy((outbuffer[outbuffer_count]) + header_length, body_abuf.buf, body_abuf.len);
532     }
533     outbuffer_count++;
534
535     if (outbuffer_count == 1) {
536       writetimer_entry = olsr_start_timer(100, 0, OLSR_TIMER_PERIODIC, &httpinfo_write_data, NULL, 0);
537     }
538   }
539   abuf_free(&body_abuf);
540   return;
541
542 close_connection:
543   abuf_free(&body_abuf);
544   close(client_socket);
545 }
546
547 static void
548 httpinfo_write_data(void *foo __attribute__ ((unused))) {
549   fd_set set;
550   int result, i, j, max;
551   struct timeval tv;
552
553   FD_ZERO(&set);
554   max = 0;
555   for (i=0; i<outbuffer_count; i++) {
556     FD_SET(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 */
741   const int print_link = want_link && (prefix_len == -1 || prefix_len == olsr_cnf->maxplen);
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",
857              FIBM_FLAT == olsr_cnf->fib_metric ? CFG_FIBM_FLAT : FIBM_CORRECT ==
858              olsr_cnf->fib_metric ? CFG_FIBM_CORRECT : CFG_FIBM_APPROX);
859
860   abuf_puts(abuf, "</tr>\n<tr>\n");
861
862   abuf_appendf(abuf, "<td>Pollrate: %0.2f</td>\n", olsr_cnf->pollrate);
863   abuf_appendf(abuf, "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
864   abuf_appendf(abuf, "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
865   abuf_appendf(abuf, "<td>NAT threshold: %f</td>\n", olsr_cnf->lq_nat_thresh);
866
867   abuf_puts(abuf, "</tr>\n<tr>\n");
868
869   abuf_appendf(abuf, "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
870   abuf_appendf(abuf, "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
871   abuf_appendf(abuf, "<td>RtTable: 0x%04x/%d</td>\n", olsr_cnf->rttable, olsr_cnf->rttable);
872   abuf_appendf(abuf, "<td>RtTableDefault: 0x%04x/%d</td>\n", olsr_cnf->rttable_default,
873              olsr_cnf->rttable_default);
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
1143   {
1144     /* Hack to make netdirect stuff work with
1145        olsrd_write_cnf_buf
1146      */
1147     char tmpBuf[10000];
1148     int size;
1149     size = olsrd_write_cnf_buf(olsr_cnf, tmpBuf, 10000);
1150     if (size < 0) {
1151       abuf_puts(abuf, "ERROR GENERATING CONFIGFILE!\n");
1152     }
1153     else {
1154       abuf_puts(abuf, tmpBuf);
1155     }
1156   }
1157
1158   abuf_puts(abuf, "</pre>\n<hr/>\n");
1159
1160 #if 0
1161   printf("RETURNING %d\n", size);
1162 #endif
1163 }
1164
1165 static int
1166 check_allowed_ip(const struct allowed_net *const my_allowed_nets, const union olsr_ip_addr *const addr)
1167 {
1168   const struct allowed_net *alln;
1169   for (alln = my_allowed_nets; alln != NULL; alln = alln->next) {
1170     if ((addr->v4.s_addr & alln->mask.v4.s_addr) == (alln->net.v4.s_addr & alln->mask.v4.s_addr)) {
1171       return 1;
1172     }
1173   }
1174   return 0;
1175 }
1176
1177 #if 0
1178
1179 /*
1180  * In a bigger mesh, there are probs with the fixed
1181  * bufsize. Because the Content-Length header is
1182  * optional, the sprintf() is changed to a more
1183  * scalable solution here.
1184  */
1185
1186 int
1187 netsprintf(char *str, const char *format, ...)
1188 {
1189   va_list arg;
1190   int rv;
1191   va_start(arg, format);
1192   rv = vsprintf(str, format, arg);
1193   va_end(arg);
1194   if (0 != netsprintf_direct) {
1195     if (0 == netsprintf_error) {
1196       if (0 > send(client_sockets[curr_clients], str, rv, 0)) {
1197         olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
1198         netsprintf_error = 1;
1199       }
1200     }
1201     return 0;
1202   }
1203   return rv;
1204 }
1205 #endif
1206
1207 /*
1208  * Local Variables:
1209  * c-basic-offset: 2
1210  * indent-tabs-mode: nil
1211  * End:
1212  */