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