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