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