2 * HTTP Info plugin for the olsr.org OLSR daemon
3 * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
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.
33 * Visit http://www.olsr.org for more information.
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.
39 * $Id: olsrd_httpinfo.c,v 1.34 2005/01/03 20:12:49 kattemat Exp $
43 * Dynamic linked library for the olsr.org olsr daemon
46 #include "olsrd_httpinfo.h"
57 #define close(x) closesocket(x)
62 #define MAX_HTTPREQ_SIZE 1024 * 10
64 #define DEFAULT_TCP_PORT 8080
66 #define HTML_BUFSIZE 1024*50
68 #define FRAMEWIDTH 800
70 #define ACTIVE_TAB "class=\"active\""
72 #define FILENREQ_MATCH(req, filename) \
73 !strcmp(req, filename) || \
74 (strlen(req) && !strcmp(&req[1], filename))
80 int(*build_body_cb)(char *, olsr_u32_t);
83 struct static_bin_file_entry
87 unsigned int data_size;
90 struct static_txt_file_entry
100 build_tabs(char *, int);
103 parse_http_request(int);
106 build_http_header(http_header_type, olsr_bool, olsr_u32_t, char *, olsr_u32_t);
109 build_frame(char *, char *, int, char *, olsr_u32_t, int(*frame_body_cb)(char *, olsr_u32_t));
112 build_routes_body(char *, olsr_u32_t);
115 build_config_body(char *, olsr_u32_t);
118 build_neigh_body(char *, olsr_u32_t);
121 build_topo_body(char *, olsr_u32_t);
124 build_hna_body(char *, olsr_u32_t);
127 build_mid_body(char *, olsr_u32_t);
130 build_nodes_body(char *, olsr_u32_t);
133 build_all_body(char *, olsr_u32_t);
136 build_about_body(char *, olsr_u32_t);
139 sockaddr_to_string(struct sockaddr *);
142 check_allowed_ip(union olsr_ip_addr *);
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;
152 struct tab_entry tab_entries[] =
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},
162 struct static_bin_file_entry static_bin_files[] =
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*/},
170 struct static_txt_file_entry static_txt_files[] =
172 {"httpinfo.css", httpinfo_css},
177 *Do initialization here
179 *This function is called by the my_init
180 *function in uolsrd_plugin.c
186 gettimeofday(&start_time, NULL);
189 /* set up HTTP socket */
190 http_socket = get_http_socket(http_port != 0 ? http_port : DEFAULT_TCP_PORT);
194 fprintf(stderr, "(HTTPINFO) could not initialize HTTP socket\n");
198 /* Register socket */
199 add_olsr_socket(http_socket, &parse_http_request);
205 get_http_socket(int port)
207 struct sockaddr_in sin;
211 /* Init ipc socket */
212 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
214 olsr_printf(1, "(HTTPINFO)socket %s\n", strerror(errno));
218 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0)
220 olsr_printf(1, "(HTTPINFO)SO_REUSEADDR failed %s\n", strerror(errno));
225 /* Bind the socket */
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);
233 /* bind the socket to the port number */
234 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1)
236 olsr_printf(1, "(HTTPINFO) bind failed %s\n", strerror(errno));
240 /* show that we are willing to listen */
241 if (listen(s, 1) == -1)
243 olsr_printf(1, "(HTTPINFO) listen failed %s\n", strerror(errno));
251 /* Non reentrant - but we are not multithreaded anyway */
253 parse_http_request(int fd)
255 struct sockaddr_in pin;
258 char req[MAX_HTTPREQ_SIZE];
259 static char body[HTML_BUFSIZE];
262 char http_version[11];
263 int c = 0, r = 1, size = 0;
265 addrlen = sizeof(struct sockaddr_in);
267 if(curr_clients >= MAX_CLIENTS)
272 if ((client_sockets[curr_clients] = accept(fd, (struct sockaddr *) &pin, &addrlen)) == -1)
274 olsr_printf(1, "(HTTPINFO) accept: %s\n", strerror(errno));
275 goto close_connection;
278 if(!check_allowed_ip((union olsr_ip_addr *)&pin.sin_addr.s_addr))
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]);
285 addr = inet_ntoa(pin.sin_addr);
288 memset(req, 0, MAX_HTTPREQ_SIZE);
289 memset(body, 0, 1024*10);
291 while((r = recv(client_sockets[curr_clients], &req[c], 1, 0)) > 0 && (c < (MAX_HTTPREQ_SIZE-1)))
295 if((c > 3 && !strcmp(&req[c-4], "\r\n\r\n")) ||
296 (c > 1 && !strcmp(&req[c-2], "\n\n")))
302 olsr_printf(1, "(HTTPINFO) Failed to recieve data from client!\n");
304 goto close_connection;
307 /* Get the request */
308 if(sscanf(req, "%10s %250s %10s\n", req_type, filename, http_version) != 3)
310 /* Try without HTTP version */
311 if(sscanf(req, "%10s %250s\n", req_type, filename) != 2)
313 olsr_printf(1, "(HTTPINFO) Error parsing request %s!\n", req);
315 goto close_connection;
320 olsr_printf(1, "Request: %s\nfile: %s\nVersion: %s\n\n", req_type, filename, http_version);
322 if(strcmp(req_type, "GET"))
324 /* We only support GET */
325 strcpy(body, HTTP_400_MSG);
327 c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
334 while(static_bin_files[i].filename)
336 if(FILENREQ_MATCH(filename, static_bin_files[i].filename))
341 if(static_bin_files[i].filename)
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);
352 while(static_txt_files[i].filename)
354 if(FILENREQ_MATCH(filename, static_txt_files[i].filename))
359 if(static_txt_files[i].filename)
363 while(static_txt_files[i].data[y])
365 size += sprintf(&body[size], static_txt_files[i].data[y]);
369 c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, MAX_HTTPREQ_SIZE);
375 if(strlen(filename) > 1)
377 while(tab_entries[i].filename)
379 if(FILENREQ_MATCH(filename, tab_entries[i].filename))
385 if(tab_entries[i].filename)
388 while(http_ok_head[y])
390 size += sprintf(&body[size], http_ok_head[y]);
394 size += build_tabs(&body[size], i);
395 size += build_frame("Current Routes",
400 tab_entries[i].build_body_cb);
405 while(http_ok_tail[y])
407 size += sprintf(&body[size], http_ok_tail[y]);
411 c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, MAX_HTTPREQ_SIZE);
418 strcpy(body, HTTP_404_MSG);
419 c = build_http_header(HTTP_BAD_FILE, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
424 r = send(client_sockets[curr_clients], req, c, 0);
427 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
428 goto close_connection;
431 r = send(client_sockets[curr_clients], body, size, 0);
434 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
435 goto close_connection;
439 close(client_sockets[curr_clients]);
446 build_http_header(http_header_type type,
456 memset(buf, 0, bufsize);
461 memcpy(buf, HTTP_400, strlen(HTTP_400));
464 memcpy(buf, HTTP_404, strlen(HTTP_404));
468 memcpy(buf, HTTP_200, strlen(HTTP_200));
476 strftime(timestr, 45, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", gmtime(&currtime));
477 strcat(buf, timestr);
481 strcat(buf, "Server: " PLUGIN_NAME " " PLUGIN_VERSION " " HTTP_VERSION "\r\n");
483 /* connection-type */
484 strcat(buf,"Connection: closed\r\n");
488 strcat(buf, "Content-type: text/html\r\n");
490 strcat(buf, "Content-type: text/plain\r\n");
495 sprintf(tmp, "Content-length: %i\r\n", size);
501 * No caching dynamic pages
503 strcat(buf, "Cache-Control: no-cache\r\n");
506 strcat(buf, "Accept-Ranges: bytes\r\n");
511 olsr_printf(1, "HEADER:\n%s", buf);
520 build_tabs(char *buf, int active)
522 int size = 0, i = 0, tabs = 0;
524 while(strcmp(html_tabs[i], "<!-- TAB ELEMENTS -->"))
526 size += sprintf(&buf[size], html_tabs[i]);
532 while(tab_entries[tabs].tab_label)
535 size += sprintf(&buf[size],
537 tab_entries[tabs].filename,
539 tab_entries[tabs].tab_label);
541 size += sprintf(&buf[size],
543 tab_entries[tabs].filename,
545 tab_entries[tabs].tab_label);
552 size += sprintf(&buf[size], html_tabs[i]);
561 * destructor - called at unload
571 /* Mulitpurpose funtion */
573 plugin_io(int cmd, void *data, size_t size)
588 build_frame(char *title,
593 int(*frame_body_cb)(char *, olsr_u32_t))
599 if(!strcmp(http_frame[i], "<!-- BODY -->"))
600 size += frame_body_cb(&buf[size], bufsize - size);
602 size += sprintf(&buf[size], http_frame[i]);
613 build_routes_body(char *buf, olsr_u32_t bufsize)
616 struct rt_entry *routes;
618 size += sprintf(&buf[size], "<h2>OLSR routes in kernel</h2>\n");
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");
623 for(index = 0;index < HASHSIZE;index++)
625 for(routes = host_routes[index].next;
626 routes != &host_routes[index];
627 routes = routes->next)
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),
633 routes->rt_if->int_name);
638 for(index = 0;index < HASHSIZE;index++)
640 for(routes = hna_routes[index].next;
641 routes != &hna_routes[index];
642 routes = routes->next)
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),
648 routes->rt_if->int_name);
652 size += sprintf(&buf[size], "</table>\n");
658 build_config_body(char *buf, olsr_u32_t bufsize)
664 struct plugin_entry *pentry;
665 struct plugin_param *pparam;
666 struct timeval now, uptime;
667 int hours, mins, days;
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;
679 strftime(systime, 100, "System time: <i>%a, %d %b %Y %H:%M:%S</i><br>", gmtime(&currtime));
682 size += sprintf(&buf[size], "%s\n", systime);
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);
687 size += sprintf(&buf[size], "Olsrd uptime: <i>%02d hours %02d minutes %02d seconds</i><br>\n", hours, mins, (int)uptime.tv_sec);
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);
691 size += sprintf(&buf[size], "<h2>Variables</h2>\n");
693 size += sprintf(&buf[size], "<table width=\"100%%\" border=0>\n<tr>");
695 size += sprintf(&buf[size], "<td>Main address: <b>%s</b></td>\n", olsr_ip_to_string(main_addr));
697 size += sprintf(&buf[size], "<td>IP version: %d</td>\n", cfg->ip_version == AF_INET ? 4 : 6);
699 size += sprintf(&buf[size], "<td>Debug level: %d</td>\n", cfg->debug_level);
701 size += sprintf(&buf[size], "</tr>\n<tr>\n");
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);
708 size += sprintf(&buf[size], "</tr>\n<tr>\n");
710 size += sprintf(&buf[size], "<td>TOS: 0x%04x</td>\n", cfg->tos);
712 size += sprintf(&buf[size], "<td>Willingness: %d %s</td>\n", cfg->willingness, cfg->willingness_auto ? "(auto)" : "");
714 size += sprintf(&buf[size], "</tr>\n<tr>\n");
716 size += sprintf(&buf[size], "<td>Hysteresis: %s</td>\n", cfg->use_hysteresis ? "Enabled" : "Disabled");
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);
721 size += sprintf(&buf[size], "</tr>\n<tr>\n");
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");
728 size += sprintf(&buf[size], "</tr></table>\n");
730 size += sprintf(&buf[size], "<h2>Interfaces</h2>\n");
733 size += sprintf(&buf[size], "<table width=\"100%%\" border=0>\n");
736 for(ifs = cfg->interfaces; ifs; ifs = ifs->next)
738 struct interface *rifs = ifs->interf;
740 size += sprintf(&buf[size], "<tr><th colspan=3>%s</th>\n", ifs->name);
743 size += sprintf(&buf[size], "<tr><td colspan=3>Status: DOWN</td></tr>\n");
747 if(cfg->ip_version == AF_INET)
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");
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");
771 size += sprintf(&buf[size], "</table>\n");
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");
776 size += sprintf(&buf[size], "<i>Olsrd is configured to halt if no interfaces are available</i><br>\n");
778 size += sprintf(&buf[size], "<h2>Plugins</h2>\n");
780 size += sprintf(&buf[size], "<table width=\"100%%\" border=0><tr><th>Name</th><th>Parameters</th></tr>\n");
782 for(pentry = cfg->plugins; pentry; pentry = pentry->next)
784 size += sprintf(&buf[size], "<tr><td>%s</td>\n", pentry->name);
786 size += sprintf(&buf[size], "<td><select>\n");
787 size += sprintf(&buf[size], "<option>KEY, VALUE</option>\n");
789 for(pparam = pentry->params; pparam; pparam = pparam->next)
791 size += sprintf(&buf[size], "<option>\"%s\", \"%s\"</option>\n",
795 size += sprintf(&buf[size], "</select></td></tr>\n");
799 size += sprintf(&buf[size], "</table>\n");
802 if((cfg->ip_version == AF_INET) && (cfg->hna4_entries))
804 struct hna4_entry *hna4;
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");
809 for(hna4 = cfg->hna4_entries; hna4; hna4 = hna4->next)
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));
816 size += sprintf(&buf[size], "</table>\n");
818 else if((cfg->ip_version == AF_INET6) && (cfg->hna6_entries))
820 struct hna6_entry *hna6;
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");
825 for(hna6 = cfg->hna6_entries; hna6; hna6 = hna6->next)
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),
832 size += sprintf(&buf[size], "</table>\n");
842 build_neigh_body(char *buf, olsr_u32_t bufsize)
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;
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");
853 if(olsr_plugin_io(GETD__LINK_SET, &link, sizeof(link)) && link)
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,
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);
871 size += sprintf(&buf[size], "</table>\n");
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");
876 for(index=0;index<HASHSIZE;index++)
878 for(neigh = neighbortable[index].next;
879 neigh != &neighbortable[index];
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")
892 size += sprintf(&buf[size], "<td><select>\n");
893 size += sprintf(&buf[size], "<option>IP ADDRESS</option>\n");
897 for(list_2 = neigh->neighbor_2_list.next;
898 list_2 != &neigh->neighbor_2_list;
899 list_2 = list_2->next)
901 size += sprintf(&buf[size], "<option>%s</option>\n", olsr_ip_to_string(&list_2->neighbor_2->neighbor_2_addr));
904 size += sprintf(&buf[size], "</select> (%d)</td></tr>\n", thop_cnt);
909 size += sprintf(&buf[size], "</table>\n");
917 build_topo_body(char *buf, olsr_u32_t bufsize)
921 struct tc_entry *entry;
922 struct topo_dst *dst_entry;
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");
929 for(index=0;index<HASHSIZE;index++)
931 /* For all TC entries */
932 entry = tc_table[index].next;
933 while(entry != &tc_table[index])
935 /* For all destination entries of that TC entry */
936 dst_entry = entry->destinations.next;
937 while(dst_entry != &entry->destinations)
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);
946 dst_entry = dst_entry->next;
952 size += sprintf(&buf[size], "</table>\n");
960 build_hna_body(char *buf, olsr_u32_t bufsize)
964 struct hna_entry *tmp_hna;
965 struct hna_net *tmp_net;
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");
972 for(index=0;index<HASHSIZE;index++)
974 tmp_hna = hna_set[index].next;
975 /* Check all entrys */
976 while(tmp_hna != &hna_set[index])
978 /* Check all networks */
979 tmp_net = tmp_hna->networks.next;
981 while(tmp_net != &tmp_hna->networks)
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;
990 tmp_hna = tmp_hna->next;
994 size += sprintf(&buf[size], "</table>\n");
1001 build_mid_body(char *buf, olsr_u32_t bufsize)
1005 struct mid_entry *entry;
1006 struct addresses *alias;
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");
1011 for(index=0;index<HASHSIZE;index++)
1013 entry = mid_set[index].next;
1014 while(entry != &mid_set[index])
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");
1019 alias = entry->aliases;
1022 size += sprintf(&buf[size], "<option>%s</option>\n", olsr_ip_to_string(&alias->address));
1023 alias = alias->next;
1025 size += sprintf(&buf[size], "</select>\n");
1027 size += sprintf(&buf[size], "</tr>\n");
1028 entry = entry->next;
1032 size += sprintf(&buf[size], "</table>\n");
1041 build_nodes_body(char *buf, olsr_u32_t bufsize)
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);
1054 build_all_body(char *buf, olsr_u32_t bufsize)
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);
1070 build_about_body(char *buf, olsr_u32_t bufsize)
1072 int size = 0, i = 0;
1074 while(about_frame[i])
1076 size += sprintf(&buf[size], about_frame[i]);
1083 check_allowed_ip(union olsr_ip_addr *addr)
1085 struct allowed_host *allh = allowed_hosts;
1086 struct allowed_net *alln = allowed_nets;
1088 if(addr->v4 == ntohl(INADDR_LOOPBACK))
1094 if(addr->v4 == allh->host.v4)
1102 if((addr->v4 & alln->mask.v4) == (alln->net.v4 & alln->mask.v4))
1112 *Converts a olsr_ip_addr to a string
1113 *Goes for both IPv4 and IPv6
1115 *@param the IP to convert
1116 *@return a pointer to a static string buffer
1117 *representing the address in "dots and numbers"
1121 olsr_ip_to_string(union olsr_ip_addr *addr)
1123 static int index = 0;
1124 static char buff[4][100];
1128 if(ipversion == AF_INET)
1131 ret = inet_ntoa(in);
1136 ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
1139 strncpy(buff[index], ret, 100);
1143 index = (index + 1) & 3;
1152 *This function is just as bad as the previous one :-(
1155 olsr_netmask_to_string(union hna_netmask *mask)
1159 static char netmask[5];
1161 if(ipversion == AF_INET)
1163 in.s_addr = mask->v4;
1164 ret = inet_ntoa(in);
1171 sprintf(netmask, "%d", mask->v6);
1182 sockaddr_to_string(struct sockaddr *address_to_convert)
1184 struct sockaddr_in *address;
1186 address=(struct sockaddr_in *)address_to_convert;
1187 return(inet_ntoa(address->sin_addr));