ea5c25ff6b1a27772bda6b6b31602b7eeb0e9b66
[olsrd.git] / lib / httpinfo / src / olsrd_httpinfo.c
1 /*
2  * HTTP Info plugin for the olsr.org OLSR daemon
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  * $Id: olsrd_httpinfo.c,v 1.71 2007/07/15 21:09:37 bernd67 Exp $
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 <stdarg.h>
50 #include <unistd.h>
51 #include <errno.h>
52 #ifdef WIN32
53 #include <io.h>
54 #else
55 #include <netdb.h>
56 #endif
57
58 #include "olsr.h"
59 #include "olsr_cfg.h"
60 #include "interfaces.h"
61 #include "olsr_protocol.h"
62 #include "net_olsr.h"
63 #include "link_set.h"
64 #include "socket_parser.h"
65
66 #include "olsrd_httpinfo.h"
67 #include "admin_interface.h"
68 #include "html.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 #ifdef __FreeBSD__
83 #define OS "FreeBSD"
84 #endif
85
86 #ifndef OS
87 #define OS "Undefined"
88 #endif
89
90 static char copyright_string[] = "olsr.org HTTPINFO plugin Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org) All rights reserved.";
91
92 #define MAX_CLIENTS 3
93
94 #define MAX_HTTPREQ_SIZE (1024 * 10)
95
96 #define DEFAULT_TCP_PORT 1978
97
98 #define HTML_BUFSIZE (1024 * 400)
99
100 #define FRAMEWIDTH 800
101
102 #define ACTIVE_TAB "class=\"active\""
103
104 #define FILENREQ_MATCH(req, filename) \
105         !strcmp(req, filename) || \
106         (strlen(req) && !strcmp(&req[1], filename))
107
108 struct tab_entry
109 {
110   char *tab_label;
111   char *filename;
112   int(*build_body_cb)(char *, olsr_u32_t);
113   olsr_bool display_tab;
114 };
115
116 struct static_bin_file_entry
117 {
118   char *filename;
119   unsigned char *data;
120   unsigned int data_size;
121 };
122
123 struct static_txt_file_entry
124 {
125   char *filename;
126   const char **data;
127 };
128
129 struct dynamic_file_entry
130 {
131   char *filename;
132   int(*process_data_cb)(char *, olsr_u32_t, char *, olsr_u32_t);
133 };
134
135 static int get_http_socket(int);
136
137 static int build_tabs(char *, olsr_u32_t, int);
138
139 static void parse_http_request(int);
140
141 static int build_http_header(http_header_type, olsr_bool, olsr_u32_t, char *, olsr_u32_t);
142
143 static int build_frame(char *, char *, int, char *, olsr_u32_t, int(*frame_body_cb)(char *, olsr_u32_t));
144
145 static int build_routes_body(char *, olsr_u32_t);
146
147 static int build_config_body(char *, olsr_u32_t);
148
149 static int build_neigh_body(char *, olsr_u32_t);
150
151 static int build_topo_body(char *, olsr_u32_t);
152
153 static int build_hna_body(char *, olsr_u32_t);
154
155 static int build_mid_body(char *, olsr_u32_t);
156
157 static int build_nodes_body(char *, olsr_u32_t);
158
159 static int build_all_body(char *, olsr_u32_t);
160
161 static int build_about_body(char *, olsr_u32_t);
162
163 static int build_cfgfile_body(char *, olsr_u32_t);
164
165 static int check_allowed_ip(const struct allowed_net * const allowed_nets, const union olsr_ip_addr * const addr);
166
167 static int build_ip_txt(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link, const char * const ipstr, const char  * const maskstr);
168
169 static int build_ipaddr_link(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link, const union olsr_ip_addr * const ipaddr, const union hna_netmask * const mask);
170
171 static char *olsr_netmask_to_string(union hna_netmask *);
172
173 static ssize_t writen(int fd, const void *buf, size_t count);
174
175 static struct timeval start_time;
176 static struct http_stats stats;
177 static int client_sockets[MAX_CLIENTS];
178 static int curr_clients;
179 static int http_socket;
180
181 #if 0
182 int netsprintf(char *str, const char* format, ...) __attribute__((format(printf, 2, 3)));
183 static int netsprintf_direct = 0;
184 static int netsprintf_error = 0;
185 #define sprintf netsprintf
186 #define NETDIRECT
187 #endif
188
189 static const struct tab_entry tab_entries[] =
190   {
191     {"Configuration", "config", build_config_body, OLSR_TRUE},
192     {"Routes", "routes", build_routes_body, OLSR_TRUE},
193     {"Links/Topology", "nodes", build_nodes_body, OLSR_TRUE},
194     {"All", "all", build_all_body, OLSR_TRUE},
195 #ifdef ADMIN_INTERFACE
196     {"Admin", "admin", build_admin_body, OLSR_TRUE},
197 #endif
198     {"About", "about", build_about_body, OLSR_TRUE},
199     {"FOO", "cfgfile", build_cfgfile_body, OLSR_FALSE},
200     {NULL, NULL, NULL, OLSR_FALSE}
201   };
202
203 static const struct static_bin_file_entry static_bin_files[] =
204   {
205     {"favicon.ico", favicon_ico, 1406/*favicon_ico_len*/},
206     {"logo.gif", logo_gif, 2801/*logo_gif_len*/},
207     {"grayline.gif", grayline_gif, 43/*grayline_gif_len*/},
208     {NULL, NULL, 0}
209   };
210
211 static const struct static_txt_file_entry static_txt_files[] =
212   {
213     {"httpinfo.css", httpinfo_css},
214     {NULL, NULL}
215   };
216
217
218 static const struct dynamic_file_entry dynamic_files[] =
219   {
220 #ifdef ADMIN_INTERFACE
221     {"set_values", process_set_values},
222 #endif
223     {NULL, NULL}
224   };
225
226 /**
227  *Do initialization here
228  *
229  *This function is called by the my_init
230  *function in uolsrd_plugin.c
231  */
232 int
233 olsrd_plugin_init(void)
234 {
235   (void)copyright_string;
236   /* Get start time */
237   gettimeofday(&start_time, NULL);
238
239   curr_clients = 0;
240   /* set up HTTP socket */
241   http_socket = get_http_socket(http_port != 0 ? http_port :  DEFAULT_TCP_PORT);
242
243   if(http_socket < 0)
244     {
245       fprintf(stderr, "(HTTPINFO) could not initialize HTTP socket\n");
246       exit(0);
247     }
248
249   /* Register socket */
250   add_olsr_socket(http_socket, &parse_http_request);
251
252   return 1;
253 }
254
255 static int
256 get_http_socket(int port)
257 {
258   struct sockaddr_in sin;
259   olsr_u32_t yes = 1;
260   int s;
261
262   /* Init ipc socket */
263   if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
264     {
265       olsr_printf(1, "(HTTPINFO)socket %s\n", strerror(errno));
266       return -1;
267     }
268
269   if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) 
270     {
271       olsr_printf(1, "(HTTPINFO)SO_REUSEADDR failed %s\n", strerror(errno));
272       close(s);
273       return -1;
274     }
275
276
277
278   /* Bind the socket */
279   
280   /* complete the socket structure */
281   memset(&sin, 0, sizeof(sin));
282   sin.sin_family = AF_INET;
283   sin.sin_addr.s_addr = INADDR_ANY;
284   sin.sin_port = htons(port);
285   
286   /* bind the socket to the port number */
287   if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
288     {
289       olsr_printf(1, "(HTTPINFO) bind failed %s\n", strerror(errno));
290       close(s);
291       return -1;
292     }
293       
294   /* show that we are willing to listen */
295   if (listen(s, 1) == -1) 
296     {
297       olsr_printf(1, "(HTTPINFO) listen failed %s\n", strerror(errno));
298       close(s);
299       return -1;
300     }
301
302   return s;
303 }
304
305
306 /* Non reentrant - but we are not multithreaded anyway */
307 void
308 parse_http_request(int fd)
309 {
310   struct sockaddr_in pin;
311   socklen_t addrlen;
312   char *addr;  
313   char req[MAX_HTTPREQ_SIZE];
314   static char body[HTML_BUFSIZE];
315   char req_type[11];
316   char filename[251];
317   char http_version[11];
318   int c = 0, r = 1, size = 0;
319
320   if(curr_clients >= MAX_CLIENTS)
321     return;
322
323   curr_clients++;
324
325   addrlen = sizeof(struct sockaddr_in);
326   if ((client_sockets[curr_clients] = accept(fd, (struct sockaddr *)  &pin, &addrlen)) == -1)
327     {
328       olsr_printf(1, "(HTTPINFO) accept: %s\n", strerror(errno));
329       goto close_connection;
330     }
331
332   if(!check_allowed_ip(allowed_nets, (union olsr_ip_addr *)&pin.sin_addr.s_addr))
333     {
334       olsr_printf(1, "HTTP request from non-allowed host %s!\n", 
335                   olsr_ip_to_string((union olsr_ip_addr *)&pin.sin_addr.s_addr));
336       close(client_sockets[curr_clients]);
337     }
338
339   addr = inet_ntoa(pin.sin_addr);
340
341
342   memset(req, 0, MAX_HTTPREQ_SIZE);
343   memset(body, 0, 1024*10);
344
345   while((r = recv(client_sockets[curr_clients], &req[c], 1, 0)) > 0 && (c < (MAX_HTTPREQ_SIZE-1)))
346     {
347       c++;
348
349       if((c > 3 && !strcmp(&req[c-4], "\r\n\r\n")) ||
350          (c > 1 && !strcmp(&req[c-2], "\n\n")))
351         break;
352     }
353   
354   if(r < 0)
355     {
356       olsr_printf(1, "(HTTPINFO) Failed to recieve data from client!\n");
357       stats.err_hits++;
358       goto close_connection;
359     }
360   
361   /* Get the request */
362   if(sscanf(req, "%10s %250s %10s\n", req_type, filename, http_version) != 3)
363     {
364       /* Try without HTTP version */
365       if(sscanf(req, "%10s %250s\n", req_type, filename) != 2)
366         {
367           olsr_printf(1, "(HTTPINFO) Error parsing request %s!\n", req);
368           stats.err_hits++;
369           goto close_connection;
370         }
371     }
372   
373   
374   olsr_printf(1, "Request: %s\nfile: %s\nVersion: %s\n\n", req_type, filename, http_version);
375
376   if(!strcmp(req_type, "POST"))
377     {
378 #ifdef ADMIN_INTERFACE
379       int i = 0;
380       while(dynamic_files[i].filename)
381         {
382           printf("POST checking %s\n", dynamic_files[i].filename);
383           if(FILENREQ_MATCH(filename, dynamic_files[i].filename))
384             {
385               olsr_u32_t param_size;
386
387               stats.ok_hits++;
388
389               param_size = recv(client_sockets[curr_clients], req, MAX_HTTPREQ_SIZE-1, 0);
390
391               req[param_size] = '\0';
392               printf("Dynamic read %d bytes\n", param_size);
393               
394               //memcpy(body, dynamic_files[i].data, static_bin_files[i].data_size);
395               size += dynamic_files[i].process_data_cb(req, param_size, &body[size], sizeof(body)-size);
396               c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, MAX_HTTPREQ_SIZE);  
397               goto send_http_data;
398             }
399           i++;
400         }
401 #endif
402       /* We only support GET */
403       strcpy(body, HTTP_400_MSG);
404       stats.ill_hits++;
405       c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
406     }
407   else if(!strcmp(req_type, "GET"))
408     {
409       int i = 0;
410       int y = 0;
411
412       while(static_bin_files[i].filename)
413         {
414           if(FILENREQ_MATCH(filename, static_bin_files[i].filename))
415             break;
416           i++;
417         }
418       
419       if(static_bin_files[i].filename)
420         {
421           stats.ok_hits++;
422           memcpy(body, static_bin_files[i].data, static_bin_files[i].data_size);
423           size = static_bin_files[i].data_size;
424           c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, MAX_HTTPREQ_SIZE);  
425           goto send_http_data;
426         }
427
428       i = 0;
429
430       while(static_txt_files[i].filename)
431         {
432           if(FILENREQ_MATCH(filename, static_txt_files[i].filename))
433             break;
434           i++;
435         }
436       
437       if(static_txt_files[i].filename)
438         {
439           stats.ok_hits++;
440           y = 0;
441           while(static_txt_files[i].data[y])
442             {
443               size += sprintf(&body[size], static_txt_files[i].data[y]);
444               y++;
445             }
446
447           c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, MAX_HTTPREQ_SIZE);  
448           goto send_http_data;
449         }
450
451       i = 0;
452
453       if(strlen(filename) > 1)
454         {
455           while(tab_entries[i].filename)
456             {
457               if(FILENREQ_MATCH(filename, tab_entries[i].filename))
458                 break;
459               i++;
460             }
461         }
462
463       if(tab_entries[i].filename)
464         {
465 #ifdef NETDIRECT
466           c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, MAX_HTTPREQ_SIZE);
467           r = send(client_sockets[curr_clients], req, c, 0);   
468           if(r < 0)
469             {
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           y = 0;
477           while(http_ok_head[y])
478             {
479               size += sprintf(&body[size], http_ok_head[y]);
480               y++;
481             }
482           
483           size += build_tabs(&body[size], sizeof(body)-size, i);
484           size += build_frame("Current Routes", 
485                               "routes", 
486                               FRAMEWIDTH, 
487                               &body[size], 
488                               sizeof(body)-size, 
489                               tab_entries[i].build_body_cb);
490           
491           stats.ok_hits++;
492           
493           y = 0;
494           while(http_ok_tail[y])
495             {
496               size += sprintf(&body[size], http_ok_tail[y]);
497               y++;
498             }  
499           
500 #ifdef NETDIRECT
501           netsprintf_direct = 1;
502           goto close_connection;
503 #else
504           c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, MAX_HTTPREQ_SIZE);
505           
506           goto send_http_data;
507 #endif
508         }
509       
510       
511       stats.ill_hits++;
512       strcpy(body, HTTP_404_MSG);
513       c = build_http_header(HTTP_BAD_FILE, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
514     }
515   else
516     {
517       /* We only support GET */
518       strcpy(body, HTTP_400_MSG);
519       stats.ill_hits++;
520       c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
521     }
522
523  send_http_data:
524   
525   r = writen(client_sockets[curr_clients], req, c);   
526   if(r < 0)
527     {
528       olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
529       goto close_connection;
530     }
531
532   r = writen(client_sockets[curr_clients], body, size);
533   if(r < 0)
534     {
535       olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
536       goto close_connection;
537     }
538
539  close_connection:
540   close(client_sockets[curr_clients]);
541   curr_clients--;
542
543 }
544
545
546 int
547 build_http_header(http_header_type type, 
548                   olsr_bool is_html, 
549                   olsr_u32_t msgsize, 
550                   char *buf, 
551                   olsr_u32_t bufsize)
552 {
553   time_t currtime;
554   const char *h;
555   int size;
556
557   switch(type) {
558   case(HTTP_BAD_REQ):
559       h = HTTP_400;
560       break;
561   case(HTTP_BAD_FILE):
562       h = HTTP_404;
563       break;
564   default:
565       /* Defaults to OK */
566       h = HTTP_200;
567       break;
568   }
569   size = snprintf(buf, bufsize, "%s", h);
570
571   /* Date */
572   time(&currtime);
573   size += strftime(&buf[size], bufsize-size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
574   
575   /* Server version */
576   size += snprintf(&buf[size], bufsize-size, "Server: %s %s %s\r\n", PLUGIN_NAME, PLUGIN_VERSION, HTTP_VERSION);
577
578   /* connection-type */
579   size += snprintf(&buf[size], bufsize-size, "Connection: closed\r\n");
580
581   /* MIME type */
582   size += snprintf(&buf[size], bufsize-size, "Content-type: text/%s\r\n", is_html ? "html" : "plain");
583
584   /* Content length */
585   if(msgsize > 0) {
586       size += snprintf(&buf[size], bufsize-size, "Content-length: %i\r\n", msgsize);
587   }
588
589   /* Cache-control 
590    * No caching dynamic pages
591    */
592   size += snprintf(&buf[size], bufsize-size, "Cache-Control: no-cache\r\n");
593
594   if(!is_html) {
595     size += snprintf(&buf[size], bufsize-size, "Accept-Ranges: bytes\r\n");
596   }
597   /* End header */
598   size += snprintf(&buf[size], bufsize-size, "\r\n");
599   
600   olsr_printf(1, "HEADER:\n%s", buf);
601
602   return size;
603 }
604
605
606
607 static int build_tabs(char *buf, const olsr_u32_t bufsize, int active)
608 {
609   int size = 0, i = 0, tabs = 0;
610
611   while(strcmp(html_tabs[i], "<!-- TAB ELEMENTS -->"))
612     {
613       size += snprintf(&buf[size], bufsize-size, html_tabs[i]);
614       i++;
615     }
616
617   i++;
618
619   for(tabs = 0; tab_entries[tabs].tab_label; tabs++)
620     {
621       if(!tab_entries[tabs].display_tab)
622         continue;
623
624       if(tabs == active)
625         size += snprintf(&buf[size], bufsize-size, 
626                         html_tabs[i], 
627                         tab_entries[tabs].filename, 
628                         ACTIVE_TAB, 
629                         tab_entries[tabs].tab_label);
630       else
631         size += snprintf(&buf[size], bufsize-size, 
632                         html_tabs[i], 
633                         tab_entries[tabs].filename, 
634                         " ", 
635                         tab_entries[tabs].tab_label);
636     }
637   
638   i++;      
639   while(html_tabs[i])
640     {
641       size += snprintf(&buf[size], bufsize-size, html_tabs[i]);
642       i++;
643     }
644   
645   return size;
646 }
647
648
649 /*
650  * destructor - called at unload
651  */
652 void
653 olsr_plugin_exit(void)
654 {
655   if(http_socket)
656     close(http_socket);
657 }
658
659
660 static int build_frame(char *title __attribute__((unused)), 
661                        char *link __attribute__((unused)), 
662                        int width __attribute__((unused)),
663                        char *buf,
664                        olsr_u32_t bufsize, 
665                        int(*frame_body_cb)(char *, olsr_u32_t))
666 {
667   int i = 0, size = 0;
668
669   while(http_frame[i])
670     {
671       if(!strcmp(http_frame[i], "<!-- BODY -->"))
672         size += frame_body_cb(&buf[size], bufsize-size);
673       else
674         size += snprintf(&buf[size], bufsize-size, "%s", http_frame[i]);      
675
676       i++;
677     }
678
679   return size;
680 }
681
682 static int build_ip_txt(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link, const char * const ipstr, const char  * const maskstr)
683 {
684   int size = 0;
685   if (want_link && maskstr == NULL) { /* Print the link only if there is not netmask */
686     size += snprintf(&buf[size],
687                      bufsize-size,
688                      "<a href=\"http://%s:%d/all\">",
689                      ipstr,
690                      http_port);
691   }
692   size += snprintf(&buf[size], bufsize-size, "%s", ipstr);
693   if (maskstr) {
694     size += snprintf(&buf[size], bufsize-size, "/%s", maskstr);
695   }
696   if (want_link && maskstr == NULL) { /* Print the link only if there is not netmask */
697     size += snprintf(&buf[size], bufsize-size, "</a>");
698   }
699   return size;
700 }
701
702 static int build_ipaddr_link(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link, const union olsr_ip_addr * const ipaddr, const union hna_netmask * const mask)
703 {
704   int size = 0;
705   char maskbuf[32];
706   char *maskstr;
707   const struct hostent * const hp =
708 #ifndef WIN32
709                                     resolve_ip_addresses ? gethostbyaddr(ipaddr, olsr_cnf->ipsize, olsr_cnf->ip_version) :
710 #endif
711                                         NULL;
712   if (mask != NULL) {
713     if (olsr_cnf->ip_version == AF_INET) {
714       if (mask->v4 == ~0U) {
715         maskstr = NULL;
716       } else {
717         struct in_addr in;
718         in.s_addr = mask->v4;
719         snprintf(maskbuf, sizeof(maskbuf), "%s", inet_ntoa(in));
720         maskstr = maskbuf;
721       }
722     } else {
723       snprintf(maskbuf, sizeof(maskbuf), "%d", mask->v6);
724       maskstr = maskbuf;
725     }
726   } else {
727     maskstr =  NULL;
728   }
729   size += snprintf(&buf[size], bufsize-size, "<td>");
730   size += build_ip_txt(&buf[size], bufsize-size, want_link, olsr_ip_to_string(ipaddr), maskstr);
731   size += snprintf(&buf[size], bufsize-size, "</td>");
732   if (resolve_ip_addresses) {
733     if (hp) {
734       size += snprintf(&buf[size], bufsize-size, "<td>(");
735       size += build_ip_txt(&buf[size], bufsize-size, want_link, hp->h_name, NULL);
736       size += snprintf(&buf[size], bufsize-size, ")</td>");
737     } else {
738       size += snprintf(&buf[size], bufsize-size, "<td/>");
739     }
740   }
741   return size;
742 }
743 #define build_ipaddr_with_link(buf, bufsize, ipaddr, mask) build_ipaddr_link((buf), (bufsize), OLSR_TRUE, (ipaddr), (mask))
744 #define build_ipaddr_no_link(buf, bufsize, ipaddr, mask)   build_ipaddr_link((buf), (bufsize), OLSR_FALSE, (ipaddr), (mask))
745
746
747 static int build_route(char *buf, olsr_u32_t bufsize, const struct rt_entry * const route, const char * const title, const int print_netmask)
748 {
749   int size = 0;
750   size += snprintf(&buf[size], bufsize-size, "<tr>");
751   size += build_ipaddr_with_link(&buf[size], bufsize-size, &route->rt_dst, print_netmask ? &route->rt_mask : NULL);
752   size += build_ipaddr_with_link(&buf[size], bufsize-size, &route->rt_router, NULL);
753
754   size += snprintf(&buf[size], bufsize-size, "<td align=\"center\">%d</td>", route->rt_metric);
755   if (olsr_cnf->lq_level > 0) {
756     size += snprintf(&buf[size], bufsize-size, "<td align=\"center\">%.2f</td>", route->rt_etx);
757   }
758   size += snprintf(&buf[size], bufsize-size, "<td align=\"center\">%s</td><td>%s</td></tr>\n", route->rt_if->int_name, title);
759   return size;
760 }
761
762 static int build_routes_body(char *buf, olsr_u32_t bufsize)
763 {
764   int size = 0, index;
765   struct rt_entry *routes;
766
767   size += snprintf(&buf[size], bufsize-size, "<h2>OLSR routes in kernel</h2>\n");
768
769   size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\"><tr><th%1$s>Destination</th><th%1$s>Gateway</th><th>Metric</th>",
770                   resolve_ip_addresses ? " colspan=\"2\"" : "");
771   if (olsr_cnf->lq_level > 0)
772     size += snprintf(&buf[size], bufsize-size, "<th>ETX</th>");
773   size += snprintf(&buf[size], bufsize-size, "<th>Interface</th><th>Type</th></tr>\n");
774
775   /* Neighbors */
776   for(index = 0;index < HASHSIZE;index++) {
777     for(routes = routingtable[index].next; routes != &routingtable[index]; routes = routes->next) {
778       size += build_route(&buf[size], bufsize-size, routes, "HOST", OLSR_FALSE);
779     }
780   }
781
782   /* HNA */
783   for(index = 0;index < HASHSIZE;index++) {
784     for(routes = hna_routes[index].next; routes != &hna_routes[index];routes = routes->next) {
785       size += build_route(&buf[size], bufsize-size, routes, "HNA", OLSR_TRUE);
786     }
787   }
788
789   size += snprintf(&buf[size], bufsize-size, "</table>\n");
790
791   return size;
792 }
793
794 static int build_config_body(char *buf, olsr_u32_t bufsize)
795 {
796     char systime[100];
797     time_t currtime;
798     int size = 0;
799     struct olsr_if *ifs;
800     struct plugin_entry *pentry;
801     struct plugin_param *pparam;
802     struct timeval now, uptime;
803     int hours, mins, days;
804
805     gettimeofday(&now, NULL);
806     timersub(&now, &start_time, &uptime);
807     days = uptime.tv_sec/86400;
808     uptime.tv_sec -= days*86400;
809     hours = uptime.tv_sec/3600;
810     uptime.tv_sec -= hours*3600;
811     mins = uptime.tv_sec/60;
812     uptime.tv_sec -= mins*60;
813
814     time(&currtime);
815     strftime(systime, 100, "System time: <i>%a, %d %b %Y %H:%M:%S</i><br>", localtime(&currtime));
816
817
818     size += snprintf(&buf[size], bufsize-size, "OS: %s\n<br>", OS);
819
820     size += snprintf(&buf[size], bufsize-size, "%s\n", systime);
821
822     if(days)
823       size += snprintf(&buf[size], bufsize-size, "Olsrd uptime: <i>%d day(s) %02d hours %02d minutes %02d seconds</i><br>\n", days, hours, mins, (int)uptime.tv_sec);
824     else
825       size += snprintf(&buf[size], bufsize-size, "Olsrd uptime: <i>%02d hours %02d minutes %02d seconds</i><br>\n", hours, mins, (int)uptime.tv_sec);
826
827     size += snprintf(&buf[size], bufsize-size, "HTTP stats(ok/dyn/error/illegal): <i>%d/%d/%d/%d</i><br>\n", stats.ok_hits, stats.dyn_hits, stats.err_hits, stats.ill_hits);
828
829     size += snprintf(&buf[size], bufsize-size, "Click <a href=\"/cfgfile\">here</a> to <i>generate a configuration file for this node</i>.\n");
830
831     size += snprintf(&buf[size], bufsize-size, "<h2>Variables</h2>\n");
832
833     size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=0>\n<tr>");
834
835     size += snprintf(&buf[size], bufsize-size, "<td>Main address: <b>%s</b></td>\n", olsr_ip_to_string(&olsr_cnf->main_addr));
836     
837     size += snprintf(&buf[size], bufsize-size, "<td>IP version: %d</td>\n", olsr_cnf->ip_version == AF_INET ? 4 : 6);
838
839     size += snprintf(&buf[size], bufsize-size, "<td>Debug level: %d</td>\n", olsr_cnf->debug_level);
840
841     size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
842
843     size += snprintf(&buf[size], bufsize-size, "<td>Pollrate: %0.2f</td>\n", olsr_cnf->pollrate);
844     size += snprintf(&buf[size], bufsize-size, "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
845     size += snprintf(&buf[size], bufsize-size, "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
846
847
848     size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
849
850     size += snprintf(&buf[size], bufsize-size, "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
851
852     size += snprintf(&buf[size], bufsize-size, "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
853
854     size += snprintf(&buf[size], bufsize-size, "<td>Willingness: %d %s</td>\n", olsr_cnf->willingness, olsr_cnf->willingness_auto ? "(auto)" : "");
855     
856     size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
857
858     if (olsr_cnf->lq_level == 0)
859       {
860         size += snprintf(&buf[size], bufsize-size, "<td>Hysteresis: %s</td>\n", olsr_cnf->use_hysteresis ? "Enabled" : "Disabled");
861         if (olsr_cnf->use_hysteresis)
862           {
863             size += snprintf(&buf[size], bufsize-size, "<td>Hyst scaling: %0.2f</td>\n", olsr_cnf->hysteresis_param.scaling);
864             size += snprintf(&buf[size], bufsize-size, "<td>Hyst lower/upper: %0.2f/%0.2f</td>\n", olsr_cnf->hysteresis_param.thr_low, olsr_cnf->hysteresis_param.thr_high);
865           }
866       }
867
868     size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
869
870     size += snprintf(&buf[size], bufsize-size, "<td>LQ extension: %s</td>\n", olsr_cnf->lq_level ? "Enabled" : "Disabled");
871     if (olsr_cnf->lq_level)
872       {
873         size += snprintf(&buf[size], bufsize-size, "<td>LQ level: %d</td>\n", olsr_cnf->lq_level);
874         size += snprintf(&buf[size], bufsize-size, "<td>LQ winsize: %d</td>\n", olsr_cnf->lq_wsize);
875       }
876
877     size += snprintf(&buf[size], bufsize-size, "</tr></table>\n");
878
879     size += snprintf(&buf[size], bufsize-size, "<h2>Interfaces</h2>\n");
880
881
882     size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=0>\n");
883
884
885     for(ifs = olsr_cnf->interfaces; ifs; ifs = ifs->next)
886       {
887         struct interface *rifs = ifs->interf;
888
889         size += snprintf(&buf[size], bufsize-size, "<tr><th colspan=3>%s</th>\n", ifs->name);
890         if(!rifs)
891           {
892             size += snprintf(&buf[size], bufsize-size, "<tr><td colspan=3>Status: DOWN</td></tr>\n");
893             continue;
894           }
895         
896         if(olsr_cnf->ip_version == AF_INET)
897           {
898             size += snprintf(&buf[size], bufsize-size, "<tr><td>IP: %s</td>\n", 
899                             sockaddr_to_string(&rifs->int_addr));
900             size += snprintf(&buf[size], bufsize-size, "<td>MASK: %s</td>\n", 
901                             sockaddr_to_string(&rifs->int_netmask));
902             size += snprintf(&buf[size], bufsize-size, "<td>BCAST: %s</td></tr>\n",
903                             sockaddr_to_string(&rifs->int_broadaddr));
904             size += snprintf(&buf[size], bufsize-size, "<tr><td>MTU: %d</td>\n", rifs->int_mtu);
905             size += snprintf(&buf[size], bufsize-size, "<td>WLAN: %s</td>\n", rifs->is_wireless ? "Yes" : "No");
906             size += snprintf(&buf[size], bufsize-size, "<td>STATUS: UP</td></tr>\n");
907           }
908         else
909           {
910             size += snprintf(&buf[size], bufsize-size, "<tr><td>IP: %s</td>\n", olsr_ip_to_string((union olsr_ip_addr *)&rifs->int6_addr.sin6_addr));
911             size += snprintf(&buf[size], bufsize-size, "<td>MCAST: %s</td>\n", olsr_ip_to_string((union olsr_ip_addr *)&rifs->int6_multaddr.sin6_addr));
912             size += snprintf(&buf[size], bufsize-size, "<td></td></tr>\n");
913             size += snprintf(&buf[size], bufsize-size, "<tr><td>MTU: %d</td>\n", rifs->int_mtu);
914             size += snprintf(&buf[size], bufsize-size, "<td>WLAN: %s</td>\n", rifs->is_wireless ? "Yes" : "No");
915             size += snprintf(&buf[size], bufsize-size, "<td>STATUS: UP</td></tr>\n");
916           }         
917       }
918
919     size += snprintf(&buf[size], bufsize-size, "</table>\n");
920
921     if(olsr_cnf->allow_no_interfaces)
922       size += snprintf(&buf[size], bufsize-size, "<i>Olsrd is configured to run even if no interfaces are available</i><br>\n");
923     else
924       size += snprintf(&buf[size], bufsize-size, "<i>Olsrd is configured to halt if no interfaces are available</i><br>\n");
925
926     size += snprintf(&buf[size], bufsize-size, "<h2>Plugins</h2>\n");
927
928     size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=0><tr><th>Name</th><th>Parameters</th></tr>\n");
929
930     for(pentry = olsr_cnf->plugins; pentry; pentry = pentry->next)
931       {
932         size += snprintf(&buf[size], bufsize-size, "<tr><td>%s</td>\n", pentry->name);
933
934         size += snprintf(&buf[size], bufsize-size, "<td><select>\n");
935         size += snprintf(&buf[size], bufsize-size, "<option>KEY, VALUE</option>\n");
936
937         for(pparam = pentry->params; pparam; pparam = pparam->next)
938           {
939             size += snprintf(&buf[size], bufsize-size, "<option>\"%s\", \"%s\"</option>\n",
940                             pparam->key,
941                             pparam->value);
942           }
943         size += snprintf(&buf[size], bufsize-size, "</select></td></tr>\n");
944
945       }
946
947     size += snprintf(&buf[size], bufsize-size, "</table>\n");
948
949
950     if((olsr_cnf->ip_version == AF_INET) && (olsr_cnf->hna4_entries))
951       {
952         struct hna4_entry *hna4;
953         
954         size += snprintf(&buf[size], bufsize-size, "<h2>Announced HNA entries</h2>\n");
955         size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Network</th><th>Netmask</th></tr>\n");
956         
957         for(hna4 = olsr_cnf->hna4_entries; hna4; hna4 = hna4->next)
958           {
959             size += snprintf(&buf[size], bufsize-size, "<tr><td>%s</td><td>%s</td></tr>\n", 
960                             olsr_ip_to_string((union olsr_ip_addr *)&hna4->net),
961                             olsr_ip_to_string((union olsr_ip_addr *)&hna4->netmask));
962           }
963         
964         size += snprintf(&buf[size], bufsize-size, "</table>\n");
965       } 
966    else if((olsr_cnf->ip_version == AF_INET6) && (olsr_cnf->hna6_entries))
967       {
968         struct hna6_entry *hna6;
969         
970         size += snprintf(&buf[size], bufsize-size, "<h2>Announced HNA entries</h2>\n");
971         size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Network</th><th>Prefix length</th></tr>\n");
972         
973         for(hna6 = olsr_cnf->hna6_entries; hna6; hna6 = hna6->next)
974           {
975             size += snprintf(&buf[size], bufsize-size, "<tr><td>%s</td><td>%d</td></tr>\n", 
976                             olsr_ip_to_string((union olsr_ip_addr *)&hna6->net),
977                             hna6->prefix_len);
978           }
979         
980         size += snprintf(&buf[size], bufsize-size, "</table>\n");
981       }
982     
983
984     return size;
985 }
986
987
988
989 static int build_neigh_body(char *buf, olsr_u32_t bufsize)
990 {
991   struct neighbor_entry *neigh;
992   struct neighbor_2_list_entry *list_2;
993   struct link_entry *link = NULL;
994   int size = 0, index, thop_cnt;
995
996   size += snprintf(&buf[size], bufsize-size, "<h2>Links</h2>\n");
997   size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Local IP</th><th>Remote IP</th><th>Hysteresis</th>\n");
998   if (olsr_cnf->lq_level > 0)
999     size += snprintf(&buf[size], bufsize-size, "<th>LinkQuality</th><th>lost</th><th>total</th><th>NLQ</th><th>ETX</th>\n");
1000   size += snprintf(&buf[size], bufsize-size, "</tr>\n");
1001
1002   /* Link set */
1003   link = link_set;
1004     while(link)
1005       {
1006         size += snprintf(&buf[size], bufsize-size, "<tr>");
1007         size += build_ipaddr_no_link(&buf[size], bufsize, &link->local_iface_addr, NULL);
1008         size += build_ipaddr_with_link(&buf[size], bufsize, &link->neighbor_iface_addr, NULL);
1009         size += snprintf(&buf[size], bufsize-size,
1010                        "<td align=\"right\">%0.2f</td>",
1011                        link->L_link_quality);
1012         if (olsr_cnf->lq_level > 0)
1013           {
1014             size += snprintf(&buf[size], bufsize-size,
1015                            "<td align=\"right\">%0.2f</td>"
1016                            "<td>%d</td>"
1017                            "<td>%d</td>"
1018                            "<td align=\"right\">%0.2f</td>"
1019                            "<td align=\"right\">%0.2f</td></tr>\n",
1020                            link->loss_link_quality,
1021                            link->lost_packets, 
1022                            link->total_packets,
1023                            link->neigh_link_quality, 
1024                            (link->loss_link_quality * link->neigh_link_quality) ? 1.0 / (link->loss_link_quality * link->neigh_link_quality) : 0.0);
1025           }
1026         size += snprintf(&buf[size], bufsize-size, "</tr>\n");
1027
1028         link = link->next;
1029       }
1030
1031   size += snprintf(&buf[size], bufsize-size, "</table>\n");
1032
1033   size += snprintf(&buf[size], bufsize-size, "<h2>Neighbors</h2>\n");
1034   size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>IP address</th><th>SYM</th><th>MPR</th><th>MPRS</th><th>Willingness</th><th>2 Hop Neighbors</th></tr>\n");
1035   /* Neighbors */
1036   for(index=0;index<HASHSIZE;index++)
1037     {
1038       for(neigh = neighbortable[index].next;
1039           neigh != &neighbortable[index];
1040           neigh = neigh->next)
1041         {
1042           size += snprintf(&buf[size], bufsize-size, "<tr>");
1043           size += build_ipaddr_with_link(&buf[size], bufsize, &neigh->neighbor_main_addr, NULL);
1044           size += snprintf(&buf[size], bufsize-size, 
1045                           "<td>%s</td>"
1046                           "<td>%s</td>"
1047                           "<td>%s</td>"
1048                           "<td>%d</td>", 
1049                           (neigh->status == SYM) ? "YES" : "NO",
1050                           neigh->is_mpr ? "YES" : "NO",
1051                           olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO",
1052                           neigh->willingness);
1053
1054           size += snprintf(&buf[size], bufsize-size, "<td><select>\n");
1055           size += snprintf(&buf[size], bufsize-size, "<option>IP ADDRESS</option>\n");
1056
1057           thop_cnt = 0;
1058
1059           for(list_2 = neigh->neighbor_2_list.next;
1060               list_2 != &neigh->neighbor_2_list;
1061               list_2 = list_2->next)
1062             {
1063               size += snprintf(&buf[size], bufsize-size, "<option>%s</option>", olsr_ip_to_string(&list_2->neighbor_2->neighbor_2_addr));
1064               thop_cnt ++;
1065             }
1066           size += snprintf(&buf[size], bufsize-size, "</select> (%d)</td></tr>\n", thop_cnt);
1067
1068         }
1069     }
1070
1071   size += snprintf(&buf[size], bufsize-size, "</table>\n");
1072
1073   return size;
1074 }
1075
1076 static int build_topo_body(char *buf, olsr_u32_t bufsize)
1077 {
1078   int size = 0;
1079   olsr_u8_t index;
1080   struct tc_entry *entry;
1081   struct topo_dst *dst_entry;
1082
1083
1084   size += snprintf(&buf[size], bufsize-size, "<h2>Topology entries</h2>\n<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Destination IP</th><th>Last Hop IP</th>");
1085   if (olsr_cnf->lq_level > 0)
1086     size += snprintf(&buf[size], bufsize-size, "<th>LQ</th><th>ILQ</th><th>ETX</th>");
1087   size += snprintf(&buf[size], bufsize-size, "</tr>\n");
1088
1089
1090   /* Topology */  
1091   for(index=0;index<HASHSIZE;index++)
1092     {
1093       /* For all TC entries */
1094       entry = tc_table[index].next;
1095       while(entry != &tc_table[index])
1096         {
1097           /* For all destination entries of that TC entry */
1098           dst_entry = entry->destinations.next;
1099           while(dst_entry != &entry->destinations)
1100             {
1101               size += snprintf(&buf[size], bufsize-size, "<tr>");
1102               size += build_ipaddr_with_link(&buf[size], bufsize, &dst_entry->T_dest_addr, NULL);
1103               size += build_ipaddr_with_link(&buf[size], bufsize, &entry->T_last_addr, NULL);
1104               if (olsr_cnf->lq_level > 0)
1105                 {
1106                   const double d = dst_entry->link_quality * dst_entry->inverse_link_quality;
1107                   size += snprintf(&buf[size], bufsize-size,
1108                                  "<td align=\"right\">%0.2f</td>"
1109                                  "<td align=\"right\">%0.2f</td>"
1110                                  "<td align=\"right\">%0.2f</td>\n",
1111                                  dst_entry->link_quality,
1112                                  dst_entry->inverse_link_quality,
1113                                  d ? 1.0 / d : 0.0);
1114                 }
1115               size += snprintf(&buf[size], bufsize-size, "</tr>\n");
1116
1117               dst_entry = dst_entry->next;
1118             }
1119           entry = entry->next;
1120         }
1121     }
1122
1123   size += snprintf(&buf[size], bufsize-size, "</table>\n");
1124
1125   return size;
1126 }
1127
1128 static int build_hna_body(char *buf, olsr_u32_t bufsize)
1129 {
1130   int size;
1131   olsr_u8_t index;
1132   struct hna_entry *tmp_hna;
1133   struct hna_net *tmp_net;
1134
1135   size = 0;
1136
1137   size += snprintf(&buf[size], bufsize-size, "<h2>HNA entries</h2>\n<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Network</th><th>Netmask</th><th>Gateway</th></tr>\n");
1138
1139   /* HNA entries */
1140   for(index=0;index<HASHSIZE;index++)
1141     {
1142       tmp_hna = hna_set[index].next;
1143       /* Check all entrys */
1144       while(tmp_hna != &hna_set[index])
1145         {
1146           /* Check all networks */
1147           tmp_net = tmp_hna->networks.next;
1148               
1149           while(tmp_net != &tmp_hna->networks)
1150             {
1151               size += snprintf(&buf[size], bufsize-size, "<tr>");
1152               size += build_ipaddr_no_link(&buf[size], bufsize, &tmp_net->A_network_addr, NULL);
1153               size += snprintf(&buf[size], bufsize-size, "<td>%s</td>",
1154                               olsr_netmask_to_string(&tmp_net->A_netmask));
1155               size += build_ipaddr_with_link(&buf[size], bufsize, &tmp_hna->A_gateway_addr, NULL);
1156               tmp_net = tmp_net->next;
1157             }
1158               
1159           tmp_hna = tmp_hna->next;
1160         }
1161     }
1162
1163   size += snprintf(&buf[size], bufsize-size, "</table>\n");
1164
1165   return size;
1166 }
1167
1168
1169 static int build_mid_body(char *buf, olsr_u32_t bufsize)
1170 {
1171   int size = 0;
1172   olsr_u8_t index;
1173
1174   size += snprintf(&buf[size], bufsize-size, "<h2>MID entries</h2>\n<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Main Address</th><th>Aliases</th></tr>\n");
1175   
1176   /* MID */  
1177   for(index = 0;index < HASHSIZE; index++)
1178     {
1179       struct mid_entry *entry = mid_set[index].next;
1180       while(entry != &mid_set[index])
1181         {
1182           int mid_cnt;
1183           struct mid_address *alias;
1184           size += snprintf(&buf[size], bufsize-size, "<tr>");
1185           size += build_ipaddr_with_link(&buf[size], bufsize, &entry->main_addr, NULL);
1186           size += snprintf(&buf[size], bufsize-size, "<td><select>\n<option>IP ADDRESS</option>\n");
1187
1188           alias = entry->aliases;
1189           mid_cnt = 0;
1190           while(alias)
1191             {
1192               size += snprintf(&buf[size], bufsize-size, "<option>%s</option>\n", olsr_ip_to_string(&alias->alias));
1193               mid_cnt++;
1194               alias = alias->next_alias;
1195             }
1196           size += snprintf(&buf[size], bufsize-size, "</select> (%d)</td></tr>\n", mid_cnt);
1197           entry = entry->next;
1198         }
1199     }
1200
1201   size += snprintf(&buf[size], bufsize-size, "</table>\n");
1202   return size;
1203 }
1204
1205
1206 static int build_nodes_body(char *buf, olsr_u32_t bufsize)
1207 {
1208   int size = 0;
1209
1210   size += build_neigh_body(&buf[size], bufsize-size);
1211   size += build_topo_body(&buf[size], bufsize-size);
1212   size += build_hna_body(&buf[size], bufsize-size);
1213   size += build_mid_body(&buf[size], bufsize-size);
1214
1215   return size;
1216 }
1217
1218 static int build_all_body(char *buf, olsr_u32_t bufsize)
1219 {
1220   int size = 0;
1221
1222   size += build_config_body(&buf[size], bufsize-size);
1223   size += build_routes_body(&buf[size], bufsize-size);
1224   size += build_neigh_body(&buf[size], bufsize-size);
1225   size += build_topo_body(&buf[size], bufsize-size);
1226   size += build_hna_body(&buf[size], bufsize-size);
1227   size += build_mid_body(&buf[size], bufsize-size);
1228
1229   return size;
1230 }
1231
1232
1233 static int build_about_body(char *buf, olsr_u32_t bufsize)
1234 {
1235   int size = 0, i = 0;
1236
1237   while(about_frame[i]) {
1238       size += snprintf(&buf[size], bufsize-size, about_frame[i]);
1239       i++;
1240   }
1241   return size;
1242 }
1243
1244 static int build_cfgfile_body(char *buf, olsr_u32_t bufsize)
1245 {
1246   int size = 0, i = 0;
1247
1248   while(cfgfile_body[i] && strcmp(cfgfile_body[i], "<!-- CFGFILE -->")) {
1249       size += snprintf(&buf[size], bufsize-size, cfgfile_body[i]);
1250       i++;
1251   }
1252
1253 #ifdef NETDIRECT
1254   {
1255         /* Hack to make netdirect stuff work with
1256            olsrd_write_cnf_buf
1257         */
1258         char tmpBuf[10000];
1259         size = olsrd_write_cnf_buf(olsr_cnf, tmpBuf, 10000);
1260         snprintf(&buf[size], bufsize-size, tmpBuf);
1261   }
1262 #else
1263   size += olsrd_write_cnf_buf(olsr_cnf, &buf[size], bufsize-size);
1264 #endif
1265   
1266   if(size < 0) {
1267       size = sprintf(&buf[0], "ERROR GENERATING CONFIGFILE!\n");
1268   }
1269
1270   i++;
1271   while(cfgfile_body[i]) {
1272       size += snprintf(&buf[size], bufsize-size, cfgfile_body[i]);
1273       i++;
1274   }
1275   printf("RETURNING %d\n", size);
1276   return size;
1277 }
1278
1279 static int check_allowed_ip(const struct allowed_net * const allowed_nets, const union olsr_ip_addr * const addr)
1280 {
1281     const struct allowed_net *alln;
1282     for (alln = allowed_nets; alln != NULL; alln = alln->next) {
1283         if((addr->v4 & alln->mask.v4) == (alln->net.v4 & alln->mask.v4)) {
1284             return 1;
1285         }
1286     }
1287     return 0;
1288 }
1289
1290
1291
1292 /**
1293  *This function is just as bad as the previous one :-(
1294  */
1295 static char *olsr_netmask_to_string(union hna_netmask *mask)
1296 {
1297   char *ret;
1298   if(olsr_cnf->ip_version == AF_INET) {
1299       struct in_addr in;
1300       in.s_addr = mask->v4;
1301       ret = inet_ntoa(in);
1302   } else {
1303       static char netmask[5];
1304       /* IPv6 */
1305       snprintf(netmask, sizeof(netmask), "%d", mask->v6);
1306       ret = netmask;
1307   }
1308   return ret;
1309 }
1310
1311
1312 #if 0
1313 /*
1314  * In a bigger mesh, there are probs with the fixed
1315  * bufsize. Because the Content-Length header is
1316  * optional, the sprintf() is changed to a more
1317  * scalable solution here.
1318  */
1319  
1320 int netsprintf(char *str, const char* format, ...)
1321 {
1322         va_list arg;
1323         int rv;
1324         va_start(arg, format);
1325         rv = vsprintf(str, format, arg);
1326         va_end(arg);
1327         if (0 != netsprintf_direct) {
1328                 if (0 == netsprintf_error) {
1329                         if (0 > send(client_sockets[curr_clients], str, rv, 0)) {
1330                                 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
1331                                 netsprintf_error = 1;
1332                         }
1333                 }
1334                 return 0;
1335         }
1336         return rv;
1337 }
1338 #endif
1339
1340 static ssize_t writen(int fd, const void *buf, size_t count)
1341 {
1342     size_t bytes_left = count;
1343     const char *p = buf;
1344     while (bytes_left > 0) {
1345         const ssize_t written = write(fd, p, bytes_left);
1346         if (written == -1)  { /* error */
1347             if (errno == EINTR ) {
1348                 continue;
1349             }
1350             return -1;
1351         }
1352         /* We wrote something */
1353         bytes_left -= written;
1354         p += written;
1355     }
1356     return count;
1357 }