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.63 2007/04/20 14:06:18 bernd67 Exp $
43 * Dynamic linked library for the olsr.org olsr daemon
56 #include "interfaces.h"
57 #include "olsr_protocol.h"
60 #include "socket_parser.h"
62 #include "olsrd_httpinfo.h"
63 #include "admin_interface.h"
72 #define close(x) closesocket(x)
76 #define OS "GNU/Linux"
83 #define OS "Undefined"
86 static char copyright_string[] = "olsr.org HTTPINFO plugin Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org) All rights reserved.";
90 #define MAX_HTTPREQ_SIZE 1024 * 10
92 #define DEFAULT_TCP_PORT 1978
94 #define HTML_BUFSIZE 1024*75
96 #define FRAMEWIDTH 800
98 #define ACTIVE_TAB "class=\"active\""
100 #define FILENREQ_MATCH(req, filename) \
101 !strcmp(req, filename) || \
102 (strlen(req) && !strcmp(&req[1], filename))
108 int(*build_body_cb)(char *, olsr_u32_t);
109 olsr_bool display_tab;
112 struct static_bin_file_entry
116 unsigned int data_size;
119 struct static_txt_file_entry
125 struct dynamic_file_entry
128 int(*process_data_cb)(char *, olsr_u32_t, char *, olsr_u32_t);
133 get_http_socket(int);
136 build_tabs(char *, olsr_u32_t, int);
139 parse_http_request(int);
142 build_http_header(http_header_type, olsr_bool, olsr_u32_t, char *, olsr_u32_t);
145 build_frame(char *, char *, int, char *, olsr_u32_t, int(*frame_body_cb)(char *, olsr_u32_t));
148 build_routes_body(char *, olsr_u32_t);
151 build_config_body(char *, olsr_u32_t);
154 build_neigh_body(char *, olsr_u32_t);
157 build_topo_body(char *, olsr_u32_t);
160 build_hna_body(char *, olsr_u32_t);
163 build_mid_body(char *, olsr_u32_t);
166 build_nodes_body(char *, olsr_u32_t);
169 build_all_body(char *, olsr_u32_t);
172 build_about_body(char *, olsr_u32_t);
175 build_cfgfile_body(char *, olsr_u32_t);
179 sockaddr_to_string(struct sockaddr *);
182 check_allowed_ip(union olsr_ip_addr *);
186 build_ip_txt(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link, const char * const ipstr, const char * const maskstr);
188 build_ipaddr_link(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link, union olsr_ip_addr * const ipaddr, const union hna_netmask * const mask);
190 static ssize_t writen(int fd, const void *buf, size_t count);
192 static struct timeval start_time;
193 static struct http_stats stats;
194 static int client_sockets[MAX_CLIENTS];
195 static int curr_clients;
196 static int http_socket;
199 int netsprintf(char *str, const char* format, ...) __attribute__((format(printf, 2, 3)));
200 static int netsprintf_direct = 0;
201 static int netsprintf_error = 0;
202 #define sprintf netsprintf
206 static const struct tab_entry tab_entries[] =
208 {"Configuration", "config", build_config_body, OLSR_TRUE},
209 {"Routes", "routes", build_routes_body, OLSR_TRUE},
210 {"Links/Topology", "nodes", build_nodes_body, OLSR_TRUE},
211 {"All", "all", build_all_body, OLSR_TRUE},
212 #ifdef ADMIN_INTERFACE
213 {"Admin", "admin", build_admin_body, OLSR_TRUE},
215 {"About", "about", build_about_body, OLSR_TRUE},
216 {"FOO", "cfgfile", build_cfgfile_body, OLSR_FALSE},
217 {NULL, NULL, NULL, OLSR_FALSE}
220 static const struct static_bin_file_entry static_bin_files[] =
222 {"favicon.ico", favicon_ico, 1406/*favicon_ico_len*/},
223 {"logo.gif", logo_gif, 2801/*logo_gif_len*/},
224 {"grayline.gif", grayline_gif, 43/*grayline_gif_len*/},
228 static const struct static_txt_file_entry static_txt_files[] =
230 {"httpinfo.css", httpinfo_css},
235 static const struct dynamic_file_entry dynamic_files[] =
237 #ifdef ADMIN_INTERFACE
238 {"set_values", process_set_values},
244 *Do initialization here
246 *This function is called by the my_init
247 *function in uolsrd_plugin.c
250 olsrd_plugin_init(void)
252 (void)copyright_string;
254 gettimeofday(&start_time, NULL);
257 /* set up HTTP socket */
258 http_socket = get_http_socket(http_port != 0 ? http_port : DEFAULT_TCP_PORT);
262 fprintf(stderr, "(HTTPINFO) could not initialize HTTP socket\n");
266 /* Register socket */
267 add_olsr_socket(http_socket, &parse_http_request);
273 get_http_socket(int port)
275 struct sockaddr_in sin;
279 /* Init ipc socket */
280 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
282 olsr_printf(1, "(HTTPINFO)socket %s\n", strerror(errno));
286 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0)
288 olsr_printf(1, "(HTTPINFO)SO_REUSEADDR failed %s\n", strerror(errno));
295 /* Bind the socket */
297 /* complete the socket structure */
298 memset(&sin, 0, sizeof(sin));
299 sin.sin_family = AF_INET;
300 sin.sin_addr.s_addr = INADDR_ANY;
301 sin.sin_port = htons(port);
303 /* bind the socket to the port number */
304 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1)
306 olsr_printf(1, "(HTTPINFO) bind failed %s\n", strerror(errno));
311 /* show that we are willing to listen */
312 if (listen(s, 1) == -1)
314 olsr_printf(1, "(HTTPINFO) listen failed %s\n", strerror(errno));
323 /* Non reentrant - but we are not multithreaded anyway */
325 parse_http_request(int fd)
327 struct sockaddr_in pin;
330 char req[MAX_HTTPREQ_SIZE];
331 static char body[HTML_BUFSIZE];
334 char http_version[11];
335 int c = 0, r = 1, size = 0;
337 addrlen = sizeof(struct sockaddr_in);
339 if(curr_clients >= MAX_CLIENTS)
344 if ((client_sockets[curr_clients] = accept(fd, (struct sockaddr *) &pin, &addrlen)) == -1)
346 olsr_printf(1, "(HTTPINFO) accept: %s\n", strerror(errno));
347 goto close_connection;
350 if(!check_allowed_ip((union olsr_ip_addr *)&pin.sin_addr.s_addr))
352 olsr_printf(1, "HTTP request from non-allowed host %s!\n",
353 olsr_ip_to_string((union olsr_ip_addr *)&pin.sin_addr.s_addr));
354 close(client_sockets[curr_clients]);
357 addr = inet_ntoa(pin.sin_addr);
360 memset(req, 0, MAX_HTTPREQ_SIZE);
361 memset(body, 0, 1024*10);
363 while((r = recv(client_sockets[curr_clients], &req[c], 1, 0)) > 0 && (c < (MAX_HTTPREQ_SIZE-1)))
367 if((c > 3 && !strcmp(&req[c-4], "\r\n\r\n")) ||
368 (c > 1 && !strcmp(&req[c-2], "\n\n")))
374 olsr_printf(1, "(HTTPINFO) Failed to recieve data from client!\n");
376 goto close_connection;
379 /* Get the request */
380 if(sscanf(req, "%10s %250s %10s\n", req_type, filename, http_version) != 3)
382 /* Try without HTTP version */
383 if(sscanf(req, "%10s %250s\n", req_type, filename) != 2)
385 olsr_printf(1, "(HTTPINFO) Error parsing request %s!\n", req);
387 goto close_connection;
392 olsr_printf(1, "Request: %s\nfile: %s\nVersion: %s\n\n", req_type, filename, http_version);
394 if(!strcmp(req_type, "POST"))
396 #ifdef ADMIN_INTERFACE
398 while(dynamic_files[i].filename)
400 printf("POST checking %s\n", dynamic_files[i].filename);
401 if(FILENREQ_MATCH(filename, dynamic_files[i].filename))
403 olsr_u32_t param_size;
407 param_size = recv(client_sockets[curr_clients], req, MAX_HTTPREQ_SIZE-1, 0);
409 req[param_size] = '\0';
410 printf("Dynamic read %d bytes\n", param_size);
412 //memcpy(body, dynamic_files[i].data, static_bin_files[i].data_size);
413 size += dynamic_files[i].process_data_cb(req, param_size, &body[size], HTML_BUFSIZE-size);
414 c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, MAX_HTTPREQ_SIZE);
420 /* We only support GET */
421 strcpy(body, HTTP_400_MSG);
423 c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
425 else if(!strcmp(req_type, "GET"))
430 while(static_bin_files[i].filename)
432 if(FILENREQ_MATCH(filename, static_bin_files[i].filename))
437 if(static_bin_files[i].filename)
440 memcpy(body, static_bin_files[i].data, static_bin_files[i].data_size);
441 size = static_bin_files[i].data_size;
442 c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, MAX_HTTPREQ_SIZE);
448 while(static_txt_files[i].filename)
450 if(FILENREQ_MATCH(filename, static_txt_files[i].filename))
455 if(static_txt_files[i].filename)
459 while(static_txt_files[i].data[y])
461 size += sprintf(&body[size], static_txt_files[i].data[y]);
465 c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, MAX_HTTPREQ_SIZE);
471 if(strlen(filename) > 1)
473 while(tab_entries[i].filename)
475 if(FILENREQ_MATCH(filename, tab_entries[i].filename))
481 if(tab_entries[i].filename)
484 c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, MAX_HTTPREQ_SIZE);
485 r = send(client_sockets[curr_clients], req, c, 0);
488 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
489 goto close_connection;
491 netsprintf_error = 0;
492 netsprintf_direct = 1;
495 while(http_ok_head[y])
497 size += sprintf(&body[size], http_ok_head[y]);
501 size += build_tabs(&body[size], sizeof(body)-size, i);
502 size += build_frame("Current Routes",
507 tab_entries[i].build_body_cb);
512 while(http_ok_tail[y])
514 size += sprintf(&body[size], http_ok_tail[y]);
519 netsprintf_direct = 1;
520 goto close_connection;
522 c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, MAX_HTTPREQ_SIZE);
530 strcpy(body, HTTP_404_MSG);
531 c = build_http_header(HTTP_BAD_FILE, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
535 /* We only support GET */
536 strcpy(body, HTTP_400_MSG);
538 c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, MAX_HTTPREQ_SIZE);
543 r = writen(client_sockets[curr_clients], req, c);
546 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
547 goto close_connection;
550 r = writen(client_sockets[curr_clients], body, size);
553 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
554 goto close_connection;
558 close(client_sockets[curr_clients]);
565 build_http_header(http_header_type type,
587 size = snprintf(buf, bufsize, "%s", h);
591 size += strftime(&buf[size], bufsize-size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
594 size += snprintf(&buf[size], bufsize-size, "Server: %s %s %s\r\n", PLUGIN_NAME, PLUGIN_VERSION, HTTP_VERSION);
596 /* connection-type */
597 size += snprintf(&buf[size], bufsize-size, "Connection: closed\r\n");
600 size += snprintf(&buf[size], bufsize-size, "Content-type: text/%s\r\n", is_html ? "html" : "plain");
604 size += snprintf(&buf[size], bufsize-size, "Content-length: %i\r\n", msgsize);
608 * No caching dynamic pages
610 size += snprintf(&buf[size], bufsize-size, "Cache-Control: no-cache\r\n");
613 size += snprintf(&buf[size], bufsize-size, "Accept-Ranges: bytes\r\n");
616 size += snprintf(&buf[size], bufsize-size, "\r\n");
618 olsr_printf(1, "HEADER:\n%s", buf);
626 build_tabs(char *buf, const olsr_u32_t bufsize, int active)
628 int size = 0, i = 0, tabs = 0;
630 while(strcmp(html_tabs[i], "<!-- TAB ELEMENTS -->"))
632 size += snprintf(&buf[size], bufsize-size, html_tabs[i]);
638 for(tabs = 0; tab_entries[tabs].tab_label; tabs++)
640 if(!tab_entries[tabs].display_tab)
644 size += snprintf(&buf[size], bufsize-size,
646 tab_entries[tabs].filename,
648 tab_entries[tabs].tab_label);
650 size += snprintf(&buf[size], bufsize-size,
652 tab_entries[tabs].filename,
654 tab_entries[tabs].tab_label);
660 size += snprintf(&buf[size], bufsize-size, html_tabs[i]);
669 * destructor - called at unload
672 olsr_plugin_exit(void)
680 build_frame(char *title __attribute__((unused)),
681 char *link __attribute__((unused)),
682 int width __attribute__((unused)),
685 int(*frame_body_cb)(char *, olsr_u32_t))
691 if(!strcmp(http_frame[i], "<!-- BODY -->"))
692 size += frame_body_cb(&buf[size], bufsize-size);
694 size += snprintf(&buf[size], bufsize-size, http_frame[i]);
703 build_ip_txt(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link, const char * const ipstr, const char * const maskstr)
706 if (want_link && maskstr == NULL) { /* Print the link only if there is not netmask */
707 size += snprintf(&buf[size],
709 "<a href=\"http://%s:%d/all\">",
713 size += snprintf(&buf[size], bufsize-size, "%s", ipstr);
715 size += snprintf(&buf[size], bufsize-size, "/%s", maskstr);
717 if (want_link && maskstr == NULL) { /* Print the link only if there is not netmask */
718 size += snprintf(&buf[size], bufsize-size, "</a>");
724 build_ipaddr_link(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link, union olsr_ip_addr * const ipaddr, const union hna_netmask * const mask)
729 const struct hostent * const hp = resolve_ip_addresses ? gethostbyaddr(ipaddr, olsr_cnf->ipsize, olsr_cnf->ip_version) : NULL;
731 if (olsr_cnf->ip_version == AF_INET) {
732 if (mask->v4 == ~0U) {
736 in.s_addr = mask->v4;
737 snprintf(maskbuf, sizeof(maskbuf), "%s", inet_ntoa(in));
741 snprintf(maskbuf, sizeof(maskbuf), "%d", mask->v6);
747 size += snprintf(&buf[size], bufsize-size, "<td%s>", resolve_ip_addresses && hp ? "" : " colspan=\"2\"");
748 size += build_ip_txt(&buf[size], bufsize-size, want_link, olsr_ip_to_string(ipaddr), maskstr);
750 size += snprintf(&buf[size], bufsize-size, "</td><td>(");
751 size += build_ip_txt(&buf[size], bufsize-size, want_link, hp->h_name, NULL);
752 size += snprintf(&buf[size], bufsize-size, ")");
754 size += snprintf(&buf[size], bufsize-size, "</td>");
757 #define build_ipaddr_with_link(buf, bufsize, ipaddr, mask) build_ipaddr_link((buf), (bufsize), OLSR_TRUE, (ipaddr), (mask))
758 #define build_ipaddr_no_link(buf, bufsize, ipaddr, mask) build_ipaddr_link((buf), (bufsize), OLSR_FALSE, (ipaddr), (mask))
761 build_routes_body(char *buf, olsr_u32_t bufsize)
764 struct rt_entry *routes;
766 size += snprintf(&buf[size], bufsize-size, "<h2>OLSR routes in kernel</h2>\n");
768 size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\"><tr><th%s>Destination</th><th>Gateway</th><th>Metric</th>",
769 resolve_ip_addresses ? " colspan=\"2\"" : "");
770 if (olsr_cnf->lq_level > 0)
771 size += snprintf(&buf[size], bufsize-size, "<th>ETX</th>");
772 size += snprintf(&buf[size], bufsize-size, "<th>Interface</th><th>Type</th></tr>\n");
775 for(index = 0;index < HASHSIZE;index++)
777 for(routes = routingtable[index].next;
778 routes != &routingtable[index];
779 routes = routes->next)
781 size += snprintf(&buf[size], bufsize-size, "<tr>");
782 size += build_ipaddr_with_link(&buf[size], bufsize-size, &routes->rt_dst, NULL);
783 size += build_ipaddr_with_link(&buf[size], bufsize-size, &routes->rt_router, NULL);
785 size += snprintf(&buf[size], bufsize-size, "<td align=\"right\">%d</td>", routes->rt_metric);
786 if (olsr_cnf->lq_level > 0)
787 size += snprintf(&buf[size], bufsize-size, "<td align=\"right\">%.2f</td>", routes->rt_etx);
788 size += snprintf(&buf[size], bufsize-size,
790 "<td>HOST</td></tr>\n",
791 routes->rt_if->int_name);
796 for(index = 0;index < HASHSIZE;index++)
798 for(routes = hna_routes[index].next;
799 routes != &hna_routes[index];
800 routes = routes->next)
802 size += snprintf(&buf[size], bufsize-size, "<tr>");
803 size += build_ipaddr_with_link(&buf[size], bufsize-size, &routes->rt_dst, &routes->rt_mask);
804 size += build_ipaddr_with_link(&buf[size], bufsize-size, &routes->rt_router, NULL);
805 size += snprintf(&buf[size], bufsize-size,
806 "<td align=\"right\">%d</td>",
808 if (olsr_cnf->lq_level > 0)
809 size += snprintf(&buf[size], bufsize-size, "<td align=\"right\">%.2f</td>", routes->rt_etx);
810 size += snprintf(&buf[size], bufsize-size,
812 "<td>HNA</td></tr>\n",
813 routes->rt_if->int_name);
817 size += snprintf(&buf[size], bufsize-size, "</table>\n");
823 build_config_body(char *buf, olsr_u32_t bufsize)
829 struct plugin_entry *pentry;
830 struct plugin_param *pparam;
831 struct timeval now, uptime;
832 int hours, mins, days;
834 gettimeofday(&now, NULL);
835 timersub(&now, &start_time, &uptime);
836 days = uptime.tv_sec/86400;
837 uptime.tv_sec -= days*86400;
838 hours = uptime.tv_sec/3600;
839 uptime.tv_sec -= hours*3600;
840 mins = uptime.tv_sec/60;
841 uptime.tv_sec -= mins*60;
844 strftime(systime, 100, "System time: <i>%a, %d %b %Y %H:%M:%S</i><br>", localtime(&currtime));
847 size += snprintf(&buf[size], bufsize-size, "OS: %s\n<br>", OS);
849 size += snprintf(&buf[size], bufsize-size, "%s\n", systime);
852 size += snprintf(&buf[size], bufsize-size, "Olsrd uptime: <i>%d day(s) %02d hours %02d minutes %02d seconds</i><br>\n", days, hours, mins, (int)uptime.tv_sec);
854 size += snprintf(&buf[size], bufsize-size, "Olsrd uptime: <i>%02d hours %02d minutes %02d seconds</i><br>\n", hours, mins, (int)uptime.tv_sec);
856 size += snprintf(&buf[size], bufsize-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);
858 size += snprintf(&buf[size], bufsize-size, "Click <a href=\"/cfgfile\">here</a> to <i>generate a configuration file for this node</i>.\n");
860 size += snprintf(&buf[size], bufsize-size, "<h2>Variables</h2>\n");
862 size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=0>\n<tr>");
864 size += snprintf(&buf[size], bufsize-size, "<td>Main address: <b>%s</b></td>\n", olsr_ip_to_string(&olsr_cnf->main_addr));
866 size += snprintf(&buf[size], bufsize-size, "<td>IP version: %d</td>\n", olsr_cnf->ip_version == AF_INET ? 4 : 6);
868 size += snprintf(&buf[size], bufsize-size, "<td>Debug level: %d</td>\n", olsr_cnf->debug_level);
870 size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
872 size += snprintf(&buf[size], bufsize-size, "<td>Pollrate: %0.2f</td>\n", olsr_cnf->pollrate);
873 size += snprintf(&buf[size], bufsize-size, "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
874 size += snprintf(&buf[size], bufsize-size, "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
877 size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
879 size += snprintf(&buf[size], bufsize-size, "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
881 size += snprintf(&buf[size], bufsize-size, "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
883 size += snprintf(&buf[size], bufsize-size, "<td>Willingness: %d %s</td>\n", olsr_cnf->willingness, olsr_cnf->willingness_auto ? "(auto)" : "");
885 size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
887 if (olsr_cnf->lq_level == 0)
889 size += snprintf(&buf[size], bufsize-size, "<td>Hysteresis: %s</td>\n", olsr_cnf->use_hysteresis ? "Enabled" : "Disabled");
890 if (olsr_cnf->use_hysteresis)
892 size += snprintf(&buf[size], bufsize-size, "<td>Hyst scaling: %0.2f</td>\n", olsr_cnf->hysteresis_param.scaling);
893 size += snprintf(&buf[size], bufsize-size, "<td>Hyst lower/upper: %0.2f/%0.2f</td>\n", olsr_cnf->hysteresis_param.thr_low, olsr_cnf->hysteresis_param.thr_high);
897 size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
899 size += snprintf(&buf[size], bufsize-size, "<td>LQ extension: %s</td>\n", olsr_cnf->lq_level ? "Enabled" : "Disabled");
900 if (olsr_cnf->lq_level)
902 size += snprintf(&buf[size], bufsize-size, "<td>LQ level: %d</td>\n", olsr_cnf->lq_level);
903 size += snprintf(&buf[size], bufsize-size, "<td>LQ winsize: %d</td>\n", olsr_cnf->lq_wsize);
906 size += snprintf(&buf[size], bufsize-size, "</tr></table>\n");
908 size += snprintf(&buf[size], bufsize-size, "<h2>Interfaces</h2>\n");
911 size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=0>\n");
914 for(ifs = olsr_cnf->interfaces; ifs; ifs = ifs->next)
916 struct interface *rifs = ifs->interf;
918 size += snprintf(&buf[size], bufsize-size, "<tr><th colspan=3>%s</th>\n", ifs->name);
921 size += snprintf(&buf[size], bufsize-size, "<tr><td colspan=3>Status: DOWN</td></tr>\n");
925 if(olsr_cnf->ip_version == AF_INET)
927 size += snprintf(&buf[size], bufsize-size, "<tr><td>IP: %s</td>\n",
928 sockaddr_to_string(&rifs->int_addr));
929 size += snprintf(&buf[size], bufsize-size, "<td>MASK: %s</td>\n",
930 sockaddr_to_string(&rifs->int_netmask));
931 size += snprintf(&buf[size], bufsize-size, "<td>BCAST: %s</td></tr>\n",
932 sockaddr_to_string(&rifs->int_broadaddr));
933 size += snprintf(&buf[size], bufsize-size, "<tr><td>MTU: %d</td>\n", rifs->int_mtu);
934 size += snprintf(&buf[size], bufsize-size, "<td>WLAN: %s</td>\n", rifs->is_wireless ? "Yes" : "No");
935 size += snprintf(&buf[size], bufsize-size, "<td>STATUS: UP</td></tr>\n");
939 size += snprintf(&buf[size], bufsize-size, "<tr><td>IP: %s</td>\n", olsr_ip_to_string((union olsr_ip_addr *)&rifs->int6_addr.sin6_addr));
940 size += snprintf(&buf[size], bufsize-size, "<td>MCAST: %s</td>\n", olsr_ip_to_string((union olsr_ip_addr *)&rifs->int6_multaddr.sin6_addr));
941 size += snprintf(&buf[size], bufsize-size, "<td></td></tr>\n");
942 size += snprintf(&buf[size], bufsize-size, "<tr><td>MTU: %d</td>\n", rifs->int_mtu);
943 size += snprintf(&buf[size], bufsize-size, "<td>WLAN: %s</td>\n", rifs->is_wireless ? "Yes" : "No");
944 size += snprintf(&buf[size], bufsize-size, "<td>STATUS: UP</td></tr>\n");
948 size += snprintf(&buf[size], bufsize-size, "</table>\n");
950 if(olsr_cnf->allow_no_interfaces)
951 size += snprintf(&buf[size], bufsize-size, "<i>Olsrd is configured to run even if no interfaces are available</i><br>\n");
953 size += snprintf(&buf[size], bufsize-size, "<i>Olsrd is configured to halt if no interfaces are available</i><br>\n");
955 size += snprintf(&buf[size], bufsize-size, "<h2>Plugins</h2>\n");
957 size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=0><tr><th>Name</th><th>Parameters</th></tr>\n");
959 for(pentry = olsr_cnf->plugins; pentry; pentry = pentry->next)
961 size += snprintf(&buf[size], bufsize-size, "<tr><td>%s</td>\n", pentry->name);
963 size += snprintf(&buf[size], bufsize-size, "<td><select>\n");
964 size += snprintf(&buf[size], bufsize-size, "<option>KEY, VALUE</option>\n");
966 for(pparam = pentry->params; pparam; pparam = pparam->next)
968 size += snprintf(&buf[size], bufsize-size, "<option>\"%s\", \"%s\"</option>\n",
972 size += snprintf(&buf[size], bufsize-size, "</select></td></tr>\n");
976 size += snprintf(&buf[size], bufsize-size, "</table>\n");
979 if((olsr_cnf->ip_version == AF_INET) && (olsr_cnf->hna4_entries))
981 struct hna4_entry *hna4;
983 size += snprintf(&buf[size], bufsize-size, "<h2>Announced HNA entries</h2>\n");
984 size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Network</th><th>Netmask</th></tr>\n");
986 for(hna4 = olsr_cnf->hna4_entries; hna4; hna4 = hna4->next)
988 size += snprintf(&buf[size], bufsize-size, "<tr><td>%s</td><td>%s</td></tr>\n",
989 olsr_ip_to_string((union olsr_ip_addr *)&hna4->net),
990 olsr_ip_to_string((union olsr_ip_addr *)&hna4->netmask));
993 size += snprintf(&buf[size], bufsize-size, "</table>\n");
995 else if((olsr_cnf->ip_version == AF_INET6) && (olsr_cnf->hna6_entries))
997 struct hna6_entry *hna6;
999 size += snprintf(&buf[size], bufsize-size, "<h2>Announced HNA entries</h2>\n");
1000 size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Network</th><th>Prefix length</th></tr>\n");
1002 for(hna6 = olsr_cnf->hna6_entries; hna6; hna6 = hna6->next)
1004 size += snprintf(&buf[size], bufsize-size, "<tr><td>%s</td><td>%d</td></tr>\n",
1005 olsr_ip_to_string((union olsr_ip_addr *)&hna6->net),
1009 size += snprintf(&buf[size], bufsize-size, "</table>\n");
1019 build_neigh_body(char *buf, olsr_u32_t bufsize)
1021 struct neighbor_entry *neigh;
1022 struct neighbor_2_list_entry *list_2;
1023 struct link_entry *link = NULL;
1024 int size = 0, index, thop_cnt;
1026 size += snprintf(&buf[size], bufsize-size, "<h2>Links</h2>\n");
1027 size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Local IP</th><th>Remote IP</th><th>Hysteresis</th>\n");
1028 if (olsr_cnf->lq_level > 0)
1029 size += snprintf(&buf[size], bufsize-size, "<th>LinkQuality</th><th>lost</th><th>total</th><th>NLQ</th><th>ETX</th>\n");
1030 size += snprintf(&buf[size], bufsize-size, "</tr>\n");
1036 size += snprintf(&buf[size], bufsize-size, "<tr>");
1037 size += build_ipaddr_no_link(&buf[size], bufsize, &link->local_iface_addr, NULL);
1038 size += build_ipaddr_with_link(&buf[size], bufsize, &link->neighbor_iface_addr, NULL);
1039 size += snprintf(&buf[size], bufsize-size,
1040 "<td align=\"right\">%0.2f</td>",
1041 link->L_link_quality);
1042 if (olsr_cnf->lq_level > 0)
1044 size += snprintf(&buf[size], bufsize-size,
1045 "<td align=\"right\">%0.2f</td>"
1048 "<td align=\"right\">%0.2f</td>"
1049 "<td align=\"right\">%0.2f</td></tr>\n",
1050 link->loss_link_quality,
1052 link->total_packets,
1053 link->neigh_link_quality,
1054 (link->loss_link_quality * link->neigh_link_quality) ? 1.0 / (link->loss_link_quality * link->neigh_link_quality) : 0.0);
1056 size += snprintf(&buf[size], bufsize-size, "</tr>\n");
1061 size += snprintf(&buf[size], bufsize-size, "</table>\n");
1063 size += snprintf(&buf[size], bufsize-size, "<h2>Neighbors</h2>\n");
1064 size += snprintf(&buf[size], bufsize-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");
1066 for(index=0;index<HASHSIZE;index++)
1068 for(neigh = neighbortable[index].next;
1069 neigh != &neighbortable[index];
1070 neigh = neigh->next)
1072 size += snprintf(&buf[size], bufsize-size, "<tr>");
1073 size += build_ipaddr_with_link(&buf[size], bufsize, &neigh->neighbor_main_addr, NULL);
1074 size += snprintf(&buf[size], bufsize-size,
1079 (neigh->status == SYM) ? "YES" : "NO",
1080 neigh->is_mpr ? "YES" : "NO",
1081 olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO",
1082 neigh->willingness);
1084 size += snprintf(&buf[size], bufsize-size, "<td><select>\n");
1085 size += snprintf(&buf[size], bufsize-size, "<option>IP ADDRESS</option>\n");
1089 for(list_2 = neigh->neighbor_2_list.next;
1090 list_2 != &neigh->neighbor_2_list;
1091 list_2 = list_2->next)
1093 size += snprintf(&buf[size], bufsize-size, "<option>%s</option>", olsr_ip_to_string(&list_2->neighbor_2->neighbor_2_addr));
1096 size += snprintf(&buf[size], bufsize-size, "</select> (%d)</td></tr>\n", thop_cnt);
1101 size += snprintf(&buf[size], bufsize-size, "</table>\n");
1109 build_topo_body(char *buf, olsr_u32_t bufsize)
1113 struct tc_entry *entry;
1114 struct topo_dst *dst_entry;
1117 size += snprintf(&buf[size], bufsize-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>");
1118 if (olsr_cnf->lq_level > 0)
1119 size += snprintf(&buf[size], bufsize-size, "<th>LQ</th><th>ILQ</th><th>ETX</th>");
1120 size += snprintf(&buf[size], bufsize-size, "</tr>\n");
1124 for(index=0;index<HASHSIZE;index++)
1126 /* For all TC entries */
1127 entry = tc_table[index].next;
1128 while(entry != &tc_table[index])
1130 /* For all destination entries of that TC entry */
1131 dst_entry = entry->destinations.next;
1132 while(dst_entry != &entry->destinations)
1134 size += snprintf(&buf[size], bufsize-size, "<tr>");
1135 size += build_ipaddr_with_link(&buf[size], bufsize, &dst_entry->T_dest_addr, NULL);
1136 size += build_ipaddr_with_link(&buf[size], bufsize, &entry->T_last_addr, NULL);
1137 if (olsr_cnf->lq_level > 0)
1139 const double d = dst_entry->link_quality * dst_entry->inverse_link_quality;
1140 size += snprintf(&buf[size], bufsize-size,
1141 "<td align=\"right\">%0.2f</td>"
1142 "<td align=\"right\">%0.2f</td>"
1143 "<td align=\"right\">%0.2f</td>\n",
1144 dst_entry->link_quality,
1145 dst_entry->inverse_link_quality,
1148 size += snprintf(&buf[size], bufsize-size, "</tr>\n");
1150 dst_entry = dst_entry->next;
1152 entry = entry->next;
1156 size += snprintf(&buf[size], bufsize-size, "</table>\n");
1164 build_hna_body(char *buf, olsr_u32_t bufsize)
1168 struct hna_entry *tmp_hna;
1169 struct hna_net *tmp_net;
1173 size += snprintf(&buf[size], bufsize-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");
1176 for(index=0;index<HASHSIZE;index++)
1178 tmp_hna = hna_set[index].next;
1179 /* Check all entrys */
1180 while(tmp_hna != &hna_set[index])
1182 /* Check all networks */
1183 tmp_net = tmp_hna->networks.next;
1185 while(tmp_net != &tmp_hna->networks)
1187 size += snprintf(&buf[size], bufsize-size, "<tr>");
1188 size += build_ipaddr_no_link(&buf[size], bufsize, &tmp_net->A_network_addr, NULL);
1189 size += snprintf(&buf[size], bufsize-size, "<td>%s</td>",
1190 olsr_netmask_to_string(&tmp_net->A_netmask));
1191 size += build_ipaddr_with_link(&buf[size], bufsize, &tmp_hna->A_gateway_addr, NULL);
1192 tmp_net = tmp_net->next;
1195 tmp_hna = tmp_hna->next;
1199 size += snprintf(&buf[size], bufsize-size, "</table>\n");
1206 build_mid_body(char *buf, olsr_u32_t bufsize)
1211 size += snprintf(&buf[size], bufsize-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");
1214 for(index = 0;index < HASHSIZE; index++)
1216 struct mid_entry *entry = mid_set[index].next;
1217 while(entry != &mid_set[index])
1220 struct mid_address *alias;
1221 size += snprintf(&buf[size], bufsize-size, "<tr>");
1222 size += build_ipaddr_with_link(&buf[size], bufsize, &entry->main_addr, NULL);
1223 size += snprintf(&buf[size], bufsize-size, "<td><select>\n<option>IP ADDRESS</option>\n");
1225 alias = entry->aliases;
1229 size += snprintf(&buf[size], bufsize-size, "<option>%s</option>\n", olsr_ip_to_string(&alias->alias));
1231 alias = alias->next_alias;
1233 size += snprintf(&buf[size], bufsize-size, "</select> (%d)</td></tr>\n", mid_cnt);
1234 entry = entry->next;
1238 size += snprintf(&buf[size], bufsize-size, "</table>\n");
1244 build_nodes_body(char *buf, olsr_u32_t bufsize)
1248 size += build_neigh_body(&buf[size], bufsize-size);
1249 size += build_topo_body(&buf[size], bufsize-size);
1250 size += build_hna_body(&buf[size], bufsize-size);
1251 size += build_mid_body(&buf[size], bufsize-size);
1257 build_all_body(char *buf, olsr_u32_t bufsize)
1261 size += build_config_body(&buf[size], bufsize-size);
1262 size += build_routes_body(&buf[size], bufsize-size);
1263 size += build_neigh_body(&buf[size], bufsize-size);
1264 size += build_topo_body(&buf[size], bufsize-size);
1265 size += build_hna_body(&buf[size], bufsize-size);
1266 size += build_mid_body(&buf[size], bufsize-size);
1273 build_about_body(char *buf, olsr_u32_t bufsize)
1275 int size = 0, i = 0;
1277 while(about_frame[i]) {
1278 size += snprintf(&buf[size], bufsize-size, about_frame[i]);
1285 build_cfgfile_body(char *buf, olsr_u32_t bufsize)
1287 int size = 0, i = 0;
1289 while(cfgfile_body[i] && strcmp(cfgfile_body[i], "<!-- CFGFILE -->")) {
1290 size += snprintf(&buf[size], bufsize-size, cfgfile_body[i]);
1296 /* Hack to make netdirect stuff work with
1300 size = olsrd_write_cnf_buf(olsr_cnf, tmpBuf, 10000);
1301 snprintf(&buf[size], bufsize-size, tmpBuf);
1304 size += olsrd_write_cnf_buf(olsr_cnf, &buf[size], bufsize-size);
1308 size = sprintf(&buf[0], "ERROR GENERATING CONFIGFILE!\n");
1312 while(cfgfile_body[i]) {
1313 size += snprintf(&buf[size], bufsize-size, cfgfile_body[i]);
1316 printf("RETURNING %d\n", size);
1322 check_allowed_ip(union olsr_ip_addr *addr)
1324 struct allowed_host *allh = allowed_hosts;
1325 struct allowed_net *alln = allowed_nets;
1327 if(addr->v4 == ntohl(INADDR_LOOPBACK))
1333 if(addr->v4 == allh->host.v4)
1341 if((addr->v4 & alln->mask.v4) == (alln->net.v4 & alln->mask.v4))
1351 *This function is just as bad as the previous one :-(
1354 olsr_netmask_to_string(union hna_netmask *mask)
1357 if(olsr_cnf->ip_version == AF_INET) {
1359 in.s_addr = mask->v4;
1360 ret = inet_ntoa(in);
1362 static char netmask[5];
1364 snprintf(netmask, sizeof(netmask), "%d", mask->v6);
1373 * In a bigger mesh, there are probs with the fixed
1374 * bufsize. Because the Content-Length header is
1375 * optional, the sprintf() is changed to a more
1376 * scalable solution here.
1379 int netsprintf(char *str, const char* format, ...)
1383 va_start(arg, format);
1384 rv = vsprintf(str, format, arg);
1386 if (0 != netsprintf_direct) {
1387 if (0 == netsprintf_error) {
1388 if (0 > send(client_sockets[curr_clients], str, rv, 0)) {
1389 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
1390 netsprintf_error = 1;
1399 static ssize_t writen(int fd, const void *buf, size_t count)
1401 size_t bytes_left = count;
1402 const char *p = buf;
1403 while (bytes_left > 0) {
1404 const ssize_t written = write(fd, p, bytes_left);
1405 if (written == -1) { /* error */
1406 if (errno == EINTR ) {
1411 /* We wrote something */
1412 bytes_left -= written;