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