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