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.58 2006/01/07 08:17:43 kattemat Exp $
43 * Dynamic linked library for the olsr.org olsr daemon
55 #include "interfaces.h"
56 #include "olsr_protocol.h"
59 #include "socket_parser.h"
61 #include "olsrd_httpinfo.h"
62 #include "admin_interface.h"
71 #define close(x) closesocket(x)
75 #define OS "GNU/Linux"
82 #define OS "Undefined"
85 static char copyright_string[] = "olsr.org HTTPINFO plugin Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org) All rights reserved.";
89 #define MAX_HTTPREQ_SIZE 1024 * 10
91 #define DEFAULT_TCP_PORT 1978
93 #define HTML_BUFSIZE 1024*75
95 #define FRAMEWIDTH 800
97 #define ACTIVE_TAB "class=\"active\""
99 #define FILENREQ_MATCH(req, filename) \
100 !strcmp(req, filename) || \
101 (strlen(req) && !strcmp(&req[1], filename))
107 int(*build_body_cb)(char *, olsr_u32_t);
108 olsr_bool display_tab;
111 struct static_bin_file_entry
115 unsigned int data_size;
118 struct static_txt_file_entry
124 struct dynamic_file_entry
127 int(*process_data_cb)(char *, olsr_u32_t, char *, olsr_u32_t);
132 get_http_socket(int);
135 build_tabs(char *, int);
138 parse_http_request(int);
141 build_http_header(http_header_type, olsr_bool, olsr_u32_t, char *, olsr_u32_t);
144 build_frame(char *, char *, int, char *, olsr_u32_t, int(*frame_body_cb)(char *, olsr_u32_t));
147 build_routes_body(char *, olsr_u32_t);
150 build_config_body(char *, olsr_u32_t);
153 build_neigh_body(char *, olsr_u32_t);
156 build_topo_body(char *, olsr_u32_t);
159 build_hna_body(char *, olsr_u32_t);
162 build_mid_body(char *, olsr_u32_t);
165 build_nodes_body(char *, olsr_u32_t);
168 build_all_body(char *, olsr_u32_t);
171 build_about_body(char *, olsr_u32_t);
174 build_cfgfile_body(char *, olsr_u32_t);
178 sockaddr_to_string(struct sockaddr *);
181 check_allowed_ip(union olsr_ip_addr *);
184 get_copyright_string(void);
186 static struct timeval start_time;
187 static struct http_stats stats;
188 static int client_sockets[MAX_CLIENTS];
189 static int curr_clients;
190 static int http_socket;
192 int netsprintf(char *str, const char* format, ...);
193 static int netsprintf_direct = 0;
194 static int netsprintf_error = 0;
195 #define sprintf netsprintf
199 struct tab_entry tab_entries[] =
201 {"Configuration", "config", build_config_body, OLSR_TRUE},
202 {"Routes", "routes", build_routes_body, OLSR_TRUE},
203 {"Links/Topology", "nodes", build_nodes_body, OLSR_TRUE},
204 {"All", "all", build_all_body, OLSR_TRUE},
205 #ifdef ADMIN_INTERFACE
206 {"Admin", "admin", build_admin_body, OLSR_TRUE},
208 {"About", "about", build_about_body, OLSR_TRUE},
209 {"FOO", "cfgfile", build_cfgfile_body, OLSR_FALSE},
213 struct static_bin_file_entry static_bin_files[] =
215 {"favicon.ico", favicon_ico, 1406/*favicon_ico_len*/},
216 {"logo.gif", logo_gif, 2801/*logo_gif_len*/},
217 {"grayline.gif", grayline_gif, 43/*grayline_gif_len*/},
221 struct static_txt_file_entry static_txt_files[] =
223 {"httpinfo.css", httpinfo_css},
228 struct dynamic_file_entry dynamic_files[] =
230 #ifdef ADMIN_INTERFACE
231 {"set_values", process_set_values},
237 *Do initialization here
239 *This function is called by the my_init
240 *function in uolsrd_plugin.c
245 get_copyright_string();
247 gettimeofday(&start_time, NULL);
250 /* set up HTTP socket */
251 http_socket = get_http_socket(http_port != 0 ? http_port : DEFAULT_TCP_PORT);
255 fprintf(stderr, "(HTTPINFO) could not initialize HTTP socket\n");
259 /* Register socket */
260 add_olsr_socket(http_socket, &parse_http_request);
266 get_http_socket(int port)
268 struct sockaddr_in sin;
272 /* Init ipc socket */
273 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
275 olsr_printf(1, "(HTTPINFO)socket %s\n", strerror(errno));
279 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0)
281 olsr_printf(1, "(HTTPINFO)SO_REUSEADDR failed %s\n", strerror(errno));
288 /* Bind the socket */
290 /* complete the socket structure */
291 memset(&sin, 0, sizeof(sin));
292 sin.sin_family = AF_INET;
293 sin.sin_addr.s_addr = INADDR_ANY;
294 sin.sin_port = htons(port);
296 /* bind the socket to the port number */
297 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1)
299 olsr_printf(1, "(HTTPINFO) bind failed %s\n", strerror(errno));
303 /* show that we are willing to listen */
304 if (listen(s, 1) == -1)
306 olsr_printf(1, "(HTTPINFO) listen failed %s\n", strerror(errno));
314 /* Non reentrant - but we are not multithreaded anyway */
316 parse_http_request(int fd)
318 struct sockaddr_in pin;
321 char req[MAX_HTTPREQ_SIZE];
322 static char body[HTML_BUFSIZE];
325 char http_version[11];
326 int c = 0, r = 1, size = 0;
328 addrlen = sizeof(struct sockaddr_in);
330 if(curr_clients >= MAX_CLIENTS)
335 if ((client_sockets[curr_clients] = accept(fd, (struct sockaddr *) &pin, &addrlen)) == -1)
337 olsr_printf(1, "(HTTPINFO) accept: %s\n", strerror(errno));
338 goto close_connection;
341 if(!check_allowed_ip((union olsr_ip_addr *)&pin.sin_addr.s_addr))
343 olsr_printf(1, "HTTP request from non-allowed host %s!\n",
344 olsr_ip_to_string((union olsr_ip_addr *)&pin.sin_addr.s_addr));
345 close(client_sockets[curr_clients]);
348 addr = inet_ntoa(pin.sin_addr);
351 memset(req, 0, MAX_HTTPREQ_SIZE);
352 memset(body, 0, 1024*10);
354 while((r = recv(client_sockets[curr_clients], &req[c], 1, 0)) > 0 && (c < (MAX_HTTPREQ_SIZE-1)))
358 if((c > 3 && !strcmp(&req[c-4], "\r\n\r\n")) ||
359 (c > 1 && !strcmp(&req[c-2], "\n\n")))
365 olsr_printf(1, "(HTTPINFO) Failed to recieve data from client!\n");
367 goto close_connection;
370 /* Get the request */
371 if(sscanf(req, "%10s %250s %10s\n", req_type, filename, http_version) != 3)
373 /* Try without HTTP version */
374 if(sscanf(req, "%10s %250s\n", req_type, filename) != 2)
376 olsr_printf(1, "(HTTPINFO) Error parsing request %s!\n", req);
378 goto close_connection;
383 olsr_printf(1, "Request: %s\nfile: %s\nVersion: %s\n\n", req_type, filename, http_version);
385 if(!strcmp(req_type, "POST"))
387 #ifdef ADMIN_INTERFACE
389 while(dynamic_files[i].filename)
391 printf("POST checking %s\n", dynamic_files[i].filename);
392 if(FILENREQ_MATCH(filename, dynamic_files[i].filename))
394 olsr_u32_t param_size;
398 param_size = recv(client_sockets[curr_clients], req, MAX_HTTPREQ_SIZE-1, 0);
400 req[param_size] = '\0';
401 printf("Dynamic read %d bytes\n", param_size);
403 //memcpy(body, dynamic_files[i].data, static_bin_files[i].data_size);
404 size += dynamic_files[i].process_data_cb(req, param_size, &body[size], HTML_BUFSIZE - size);
405 c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, MAX_HTTPREQ_SIZE);
411 /* We only support GET */
412 strcpy(body, HTTP_400_MSG);
414 c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
416 else if(!strcmp(req_type, "GET"))
421 while(static_bin_files[i].filename)
423 if(FILENREQ_MATCH(filename, static_bin_files[i].filename))
428 if(static_bin_files[i].filename)
431 memcpy(body, static_bin_files[i].data, static_bin_files[i].data_size);
432 size = static_bin_files[i].data_size;
433 c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, MAX_HTTPREQ_SIZE);
439 while(static_txt_files[i].filename)
441 if(FILENREQ_MATCH(filename, static_txt_files[i].filename))
446 if(static_txt_files[i].filename)
450 while(static_txt_files[i].data[y])
452 size += sprintf(&body[size], static_txt_files[i].data[y]);
456 c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, MAX_HTTPREQ_SIZE);
462 if(strlen(filename) > 1)
464 while(tab_entries[i].filename)
466 if(FILENREQ_MATCH(filename, tab_entries[i].filename))
472 if(tab_entries[i].filename)
475 c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, MAX_HTTPREQ_SIZE);
476 r = send(client_sockets[curr_clients], req, c, 0);
479 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
480 goto close_connection;
482 netsprintf_error = 0;
483 netsprintf_direct = 1;
486 while(http_ok_head[y])
488 size += sprintf(&body[size], http_ok_head[y]);
492 size += build_tabs(&body[size], i);
493 size += build_frame("Current Routes",
498 tab_entries[i].build_body_cb);
503 while(http_ok_tail[y])
505 size += sprintf(&body[size], http_ok_tail[y]);
510 netsprintf_direct = 1;
511 goto close_connection;
513 c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, MAX_HTTPREQ_SIZE);
521 strcpy(body, HTTP_404_MSG);
522 c = build_http_header(HTTP_BAD_FILE, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
526 /* We only support GET */
527 strcpy(body, HTTP_400_MSG);
529 c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
534 r = send(client_sockets[curr_clients], req, c, 0);
537 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
538 goto close_connection;
541 r = send(client_sockets[curr_clients], body, size, 0);
544 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
545 goto close_connection;
549 close(client_sockets[curr_clients]);
556 build_http_header(http_header_type type,
566 memset(buf, 0, bufsize);
571 memcpy(buf, HTTP_400, strlen(HTTP_400));
574 memcpy(buf, HTTP_404, strlen(HTTP_404));
578 memcpy(buf, HTTP_200, strlen(HTTP_200));
586 strftime(timestr, 45, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
587 strcat(buf, timestr);
591 strcat(buf, "Server: " PLUGIN_NAME " " PLUGIN_VERSION " " HTTP_VERSION "\r\n");
593 /* connection-type */
594 strcat(buf,"Connection: closed\r\n");
598 strcat(buf, "Content-type: text/html\r\n");
600 strcat(buf, "Content-type: text/plain\r\n");
605 snprintf(tmp, sizeof(tmp), "Content-length: %i\r\n", size);
611 * No caching dynamic pages
613 strcat(buf, "Cache-Control: no-cache\r\n");
616 strcat(buf, "Accept-Ranges: bytes\r\n");
621 olsr_printf(1, "HEADER:\n%s", buf);
630 build_tabs(char *buf, int active)
632 int size = 0, i = 0, tabs = 0;
634 while(strcmp(html_tabs[i], "<!-- TAB ELEMENTS -->"))
636 size += sprintf(&buf[size], html_tabs[i]);
642 for(tabs = 0; tab_entries[tabs].tab_label; tabs++)
644 if(!tab_entries[tabs].display_tab)
648 size += sprintf(&buf[size],
650 tab_entries[tabs].filename,
652 tab_entries[tabs].tab_label);
654 size += sprintf(&buf[size],
656 tab_entries[tabs].filename,
658 tab_entries[tabs].tab_label);
664 size += sprintf(&buf[size], html_tabs[i]);
673 * destructor - called at unload
684 build_frame(char *title,
689 int(*frame_body_cb)(char *, olsr_u32_t))
695 if(!strcmp(http_frame[i], "<!-- BODY -->"))
696 size += frame_body_cb(&buf[size], bufsize - size);
698 size += sprintf(&buf[size], http_frame[i]);
709 build_routes_body(char *buf, olsr_u32_t bufsize)
712 struct rt_entry *routes;
714 size += sprintf(&buf[size], "<h2>OLSR routes in kernel</h2>\n");
716 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>ETX</th><th>Interface</th><th>Type</th></tr>\n");
719 for(index = 0;index < HASHSIZE;index++)
721 for(routes = routingtable[index].next;
722 routes != &routingtable[index];
723 routes = routes->next)
725 size += sprintf(&buf[size], "<tr><td>%s</td><td>%s</td><td>%d</td><td>%.2f</td><td>%s</td><td>HOST</td></tr>\n",
726 olsr_ip_to_string(&routes->rt_dst),
727 olsr_ip_to_string(&routes->rt_router),
730 routes->rt_if->int_name);
735 for(index = 0;index < HASHSIZE;index++)
737 for(routes = hna_routes[index].next;
738 routes != &hna_routes[index];
739 routes = routes->next)
741 size += sprintf(&buf[size], "<tr><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>HNA</td></tr>\n",
742 olsr_ip_to_string(&routes->rt_dst),
743 olsr_ip_to_string(&routes->rt_router),
745 routes->rt_if->int_name);
749 size += sprintf(&buf[size], "</table>\n");
755 build_config_body(char *buf, olsr_u32_t bufsize)
761 struct plugin_entry *pentry;
762 struct plugin_param *pparam;
763 struct timeval now, uptime;
764 int hours, mins, days;
766 gettimeofday(&now, NULL);
767 timersub(&now, &start_time, &uptime);
768 days = uptime.tv_sec/86400;
769 uptime.tv_sec -= days*86400;
770 hours = uptime.tv_sec/3600;
771 uptime.tv_sec -= hours*3600;
772 mins = uptime.tv_sec/60;
773 uptime.tv_sec -= mins*60;
776 strftime(systime, 100, "System time: <i>%a, %d %b %Y %H:%M:%S</i><br>", localtime(&currtime));
779 size += sprintf(&buf[size], "OS: %s\n<br>", OS);
781 size += sprintf(&buf[size], "%s\n", systime);
784 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);
786 size += sprintf(&buf[size], "Olsrd uptime: <i>%02d hours %02d minutes %02d seconds</i><br>\n", hours, mins, (int)uptime.tv_sec);
788 size += sprintf(&buf[size], "HTTP stats(ok/dyn/error/illegal): <i>%d/%d/%d/%d</i><br>\n", stats.ok_hits, stats.dyn_hits, stats.err_hits, stats.ill_hits);
790 size += sprintf(&buf[size], "Click <a href=\"/cfgfile\">here</a> to <i>generate a configuration file for this node</i>.\n");
792 size += sprintf(&buf[size], "<h2>Variables</h2>\n");
794 size += sprintf(&buf[size], "<table width=\"100%%\" border=0>\n<tr>");
796 size += sprintf(&buf[size], "<td>Main address: <b>%s</b></td>\n", olsr_ip_to_string(&olsr_cnf->main_addr));
798 size += sprintf(&buf[size], "<td>IP version: %d</td>\n", olsr_cnf->ip_version == AF_INET ? 4 : 6);
800 size += sprintf(&buf[size], "<td>Debug level: %d</td>\n", olsr_cnf->debug_level);
802 size += sprintf(&buf[size], "</tr>\n<tr>\n");
804 size += sprintf(&buf[size], "<td>Pollrate: %0.2f</td>\n", olsr_cnf->pollrate);
805 size += sprintf(&buf[size], "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
806 size += sprintf(&buf[size], "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
809 size += sprintf(&buf[size], "</tr>\n<tr>\n");
811 size += sprintf(&buf[size], "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
813 size += sprintf(&buf[size], "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
815 size += sprintf(&buf[size], "<td>Willingness: %d %s</td>\n", olsr_cnf->willingness, olsr_cnf->willingness_auto ? "(auto)" : "");
817 size += sprintf(&buf[size], "</tr>\n<tr>\n");
819 size += sprintf(&buf[size], "<td>Hysteresis: %s</td>\n", olsr_cnf->use_hysteresis ? "Enabled" : "Disabled");
821 size += sprintf(&buf[size], "<td>Hyst scaling: %0.2f</td>\n", olsr_cnf->hysteresis_param.scaling);
822 size += sprintf(&buf[size], "<td>Hyst lower/upper: %0.2f/%0.2f</td>\n", olsr_cnf->hysteresis_param.thr_low, olsr_cnf->hysteresis_param.thr_high);
824 size += sprintf(&buf[size], "</tr>\n<tr>\n");
826 size += sprintf(&buf[size], "<td>LQ extention: %s</td>\n", olsr_cnf->lq_level ? "Enabled" : "Disabled");
827 size += sprintf(&buf[size], "<td>LQ level: %d</td>\n", olsr_cnf->lq_level);
828 size += sprintf(&buf[size], "<td>LQ winsize: %d</td>\n", olsr_cnf->lq_wsize);
829 size += sprintf(&buf[size], "<td></td>\n");
831 size += sprintf(&buf[size], "</tr></table>\n");
833 size += sprintf(&buf[size], "<h2>Interfaces</h2>\n");
836 size += sprintf(&buf[size], "<table width=\"100%%\" border=0>\n");
839 for(ifs = olsr_cnf->interfaces; ifs; ifs = ifs->next)
841 struct interface *rifs = ifs->interf;
843 size += sprintf(&buf[size], "<tr><th colspan=3>%s</th>\n", ifs->name);
846 size += sprintf(&buf[size], "<tr><td colspan=3>Status: DOWN</td></tr>\n");
850 if(olsr_cnf->ip_version == AF_INET)
852 size += sprintf(&buf[size], "<tr><td>IP: %s</td>\n",
853 sockaddr_to_string(&rifs->int_addr));
854 size += sprintf(&buf[size], "<td>MASK: %s</td>\n",
855 sockaddr_to_string(&rifs->int_netmask));
856 size += sprintf(&buf[size], "<td>BCAST: %s</td></tr>\n",
857 sockaddr_to_string(&rifs->int_broadaddr));
858 size += sprintf(&buf[size], "<tr><td>MTU: %d</td>\n", rifs->int_mtu);
859 size += sprintf(&buf[size], "<td>WLAN: %s</td>\n", rifs->is_wireless ? "Yes" : "No");
860 size += sprintf(&buf[size], "<td>STATUS: UP</td></tr>\n");
864 size += sprintf(&buf[size], "<tr><td>IP: %s</td>\n", olsr_ip_to_string((union olsr_ip_addr *)&rifs->int6_addr.sin6_addr));
865 size += sprintf(&buf[size], "<td>MCAST: %s</td>\n", olsr_ip_to_string((union olsr_ip_addr *)&rifs->int6_multaddr.sin6_addr));
866 size += sprintf(&buf[size], "<td></td></tr>\n");
867 size += sprintf(&buf[size], "<tr><td>MTU: %d</td>\n", rifs->int_mtu);
868 size += sprintf(&buf[size], "<td>WLAN: %s</td>\n", rifs->is_wireless ? "Yes" : "No");
869 size += sprintf(&buf[size], "<td>STATUS: UP</td></tr>\n");
874 size += sprintf(&buf[size], "</table>\n");
876 if(olsr_cnf->allow_no_interfaces)
877 size += sprintf(&buf[size], "<i>Olsrd is configured to run even if no interfaces are available</i><br>\n");
879 size += sprintf(&buf[size], "<i>Olsrd is configured to halt if no interfaces are available</i><br>\n");
881 size += sprintf(&buf[size], "<h2>Plugins</h2>\n");
883 size += sprintf(&buf[size], "<table width=\"100%%\" border=0><tr><th>Name</th><th>Parameters</th></tr>\n");
885 for(pentry = olsr_cnf->plugins; pentry; pentry = pentry->next)
887 size += sprintf(&buf[size], "<tr><td>%s</td>\n", pentry->name);
889 size += sprintf(&buf[size], "<td><select>\n");
890 size += sprintf(&buf[size], "<option>KEY, VALUE</option>\n");
892 for(pparam = pentry->params; pparam; pparam = pparam->next)
894 size += sprintf(&buf[size], "<option>\"%s\", \"%s\"</option>\n",
898 size += sprintf(&buf[size], "</select></td></tr>\n");
902 size += sprintf(&buf[size], "</table>\n");
905 if((olsr_cnf->ip_version == AF_INET) && (olsr_cnf->hna4_entries))
907 struct hna4_entry *hna4;
909 size += sprintf(&buf[size], "<h2>Announced HNA entries</h2>\n");
910 size += sprintf(&buf[size], "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Network</th><th>Netmask</th></tr>\n");
912 for(hna4 = olsr_cnf->hna4_entries; hna4; hna4 = hna4->next)
914 size += sprintf(&buf[size], "<tr><td>%s</td><td>%s</td></tr>\n",
915 olsr_ip_to_string((union olsr_ip_addr *)&hna4->net),
916 olsr_ip_to_string((union olsr_ip_addr *)&hna4->netmask));
919 size += sprintf(&buf[size], "</table>\n");
921 else if((olsr_cnf->ip_version == AF_INET6) && (olsr_cnf->hna6_entries))
923 struct hna6_entry *hna6;
925 size += sprintf(&buf[size], "<h2>Announced HNA entries</h2>\n");
926 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");
928 for(hna6 = olsr_cnf->hna6_entries; hna6; hna6 = hna6->next)
930 size += sprintf(&buf[size], "<tr><td>%s</td><td>%d</td></tr>\n",
931 olsr_ip_to_string((union olsr_ip_addr *)&hna6->net),
935 size += sprintf(&buf[size], "</table>\n");
945 build_neigh_body(char *buf, olsr_u32_t bufsize)
947 struct neighbor_entry *neigh;
948 struct neighbor_2_list_entry *list_2;
949 struct link_entry *link = NULL;
950 int size = 0, index, thop_cnt;
952 size += sprintf(&buf[size], "<h2>Links</h2>\n");
953 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");
959 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",
960 olsr_ip_to_string(&link->local_iface_addr),
961 olsr_ip_to_string(&link->neighbor_iface_addr),
962 link->L_link_quality,
963 link->loss_link_quality,
966 link->neigh_link_quality,
967 (link->loss_link_quality * link->neigh_link_quality) ? 1.0 / (link->loss_link_quality * link->neigh_link_quality) : 0.0);
972 size += sprintf(&buf[size], "</table>\n");
974 size += sprintf(&buf[size], "<h2>Neighbors</h2>\n");
975 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");
977 for(index=0;index<HASHSIZE;index++)
979 for(neigh = neighbortable[index].next;
980 neigh != &neighbortable[index];
983 size += sprintf(&buf[size],
984 "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%d</td>",
985 olsr_ip_to_string(&neigh->neighbor_main_addr),
986 (neigh->status == SYM) ? "YES" : "NO",
987 neigh->is_mpr ? "YES" : "NO",
988 olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO",
991 size += sprintf(&buf[size], "<td><select>\n");
992 size += sprintf(&buf[size], "<option>IP ADDRESS</option>\n");
996 for(list_2 = neigh->neighbor_2_list.next;
997 list_2 != &neigh->neighbor_2_list;
998 list_2 = list_2->next)
1000 size += sprintf(&buf[size], "<option>%s</option>\n", olsr_ip_to_string(&list_2->neighbor_2->neighbor_2_addr));
1003 size += sprintf(&buf[size], "</select> (%d)</td></tr>\n", thop_cnt);
1008 size += sprintf(&buf[size], "</table>\n");
1016 build_topo_body(char *buf, olsr_u32_t bufsize)
1020 struct tc_entry *entry;
1021 struct topo_dst *dst_entry;
1024 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");
1028 for(index=0;index<HASHSIZE;index++)
1030 /* For all TC entries */
1031 entry = tc_table[index].next;
1032 while(entry != &tc_table[index])
1034 /* For all destination entries of that TC entry */
1035 dst_entry = entry->destinations.next;
1036 while(dst_entry != &entry->destinations)
1038 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",
1039 olsr_ip_to_string(&dst_entry->T_dest_addr),
1040 olsr_ip_to_string(&entry->T_last_addr),
1041 dst_entry->link_quality,
1042 dst_entry->inverse_link_quality,
1043 (dst_entry->link_quality * dst_entry->inverse_link_quality) ? 1.0 / (dst_entry->link_quality * dst_entry->inverse_link_quality) : 0.0);
1045 dst_entry = dst_entry->next;
1047 entry = entry->next;
1051 size += sprintf(&buf[size], "</table>\n");
1059 build_hna_body(char *buf, olsr_u32_t bufsize)
1063 struct hna_entry *tmp_hna;
1064 struct hna_net *tmp_net;
1068 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");
1071 for(index=0;index<HASHSIZE;index++)
1073 tmp_hna = hna_set[index].next;
1074 /* Check all entrys */
1075 while(tmp_hna != &hna_set[index])
1077 /* Check all networks */
1078 tmp_net = tmp_hna->networks.next;
1080 while(tmp_net != &tmp_hna->networks)
1082 size += sprintf(&buf[size], "<tr><td>%s</td>",
1083 olsr_ip_to_string(&tmp_net->A_network_addr));
1084 size += sprintf(&buf[size], "<td>%s</td>",
1085 olsr_netmask_to_string(&tmp_net->A_netmask));
1086 size += sprintf(&buf[size], "<td>%s</td></tr>\n",
1087 olsr_ip_to_string(&tmp_hna->A_gateway_addr));
1088 tmp_net = tmp_net->next;
1091 tmp_hna = tmp_hna->next;
1095 size += sprintf(&buf[size], "</table>\n");
1102 build_mid_body(char *buf, olsr_u32_t bufsize)
1106 struct mid_entry *entry;
1107 struct mid_address *alias;
1109 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");
1112 for(index=0;index<HASHSIZE;index++)
1114 entry = mid_set[index].next;
1115 while(entry != &mid_set[index])
1117 size += sprintf(&buf[size], "<tr><td>%s</td>\n", olsr_ip_to_string(&entry->main_addr));
1118 size += sprintf(&buf[size], "<td><select>\n<option>IP ADDRESS</option>\n");
1120 alias = entry->aliases;
1123 size += sprintf(&buf[size], "<option>%s</option>\n", olsr_ip_to_string(&alias->alias));
1124 alias = alias->next_alias;
1126 size += sprintf(&buf[size], "</select>\n");
1128 size += sprintf(&buf[size], "</tr>\n");
1129 entry = entry->next;
1133 size += sprintf(&buf[size], "</table>\n");
1142 build_nodes_body(char *buf, olsr_u32_t bufsize)
1146 size += build_neigh_body(buf, bufsize);
1147 size += build_topo_body(&buf[size], bufsize - size);
1148 size += build_hna_body(&buf[size], bufsize - size);
1149 size += build_mid_body(&buf[size], bufsize - size);
1155 build_all_body(char *buf, olsr_u32_t bufsize)
1159 size += build_config_body(&buf[size], bufsize);
1160 size += build_routes_body(&buf[size], bufsize - size);
1161 size += build_neigh_body(&buf[size], bufsize);
1162 size += build_topo_body(&buf[size], bufsize - size);
1163 size += build_hna_body(&buf[size], bufsize - size);
1164 size += build_mid_body(&buf[size], bufsize - size);
1171 build_about_body(char *buf, olsr_u32_t bufsize)
1173 int size = 0, i = 0;
1175 while(about_frame[i])
1177 size += sprintf(&buf[size], about_frame[i]);
1184 build_cfgfile_body(char *buf, olsr_u32_t bufsize)
1186 int size = 0, i = 0;
1188 while(cfgfile_body[i] && strcmp(cfgfile_body[i], "<!-- CFGFILE -->"))
1190 size += sprintf(&buf[size], cfgfile_body[i]);
1194 size += olsrd_write_cnf_buf(olsr_cnf, &buf[size], bufsize-size);
1198 size = sprintf(&buf[0], "ERROR GENERATING CONFIGFILE!\n");
1202 while(cfgfile_body[i])
1204 size += sprintf(&buf[size], cfgfile_body[i]);
1213 check_allowed_ip(union olsr_ip_addr *addr)
1215 struct allowed_host *allh = allowed_hosts;
1216 struct allowed_net *alln = allowed_nets;
1218 if(addr->v4 == ntohl(INADDR_LOOPBACK))
1224 if(addr->v4 == allh->host.v4)
1232 if((addr->v4 & alln->mask.v4) == (alln->net.v4 & alln->mask.v4))
1242 *This function is just as bad as the previous one :-(
1245 olsr_netmask_to_string(union hna_netmask *mask)
1249 static char netmask[5];
1251 if(olsr_cnf->ip_version == AF_INET)
1253 in.s_addr = mask->v4;
1254 ret = inet_ntoa(in);
1261 snprintf(netmask, sizeof(netmask), "%d", mask->v6);
1272 get_copyright_string()
1274 return copyright_string;
1278 * In a bigger mesh, there are probs with the fixed
1279 * bufsize. Because the Content-Length header is
1280 * optional, the sprintf() is changed to a more
1281 * scalable solution here.
1284 int netsprintf(char *str, const char* format, ...)
1288 va_start(arg, format);
1289 rv = vsprintf(str, format, arg);
1291 if (0 != netsprintf_direct) {
1292 if (0 == netsprintf_error) {
1293 if (0 > send(client_sockets[curr_clients], str, rv, 0)) {
1294 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
1295 netsprintf_error = 1;