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