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