3 * HTTP Info plugin for the olsr.org OLSR daemon
4 * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of olsr.org, olsrd nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * Visit http://www.olsr.org for more information.
36 * If you find this software useful feel free to make a donation
37 * to the project. For more information see the website or contact
38 * the copyright holders.
43 * Dynamic linked library for the olsr.org olsr daemon
59 #include "interfaces.h"
60 #include "olsr_protocol.h"
64 #include "lq_plugin.h"
65 #include "common/autobuf.h"
67 #include <pud/src/receiver.h>
68 #include <pud/src/pud.h>
69 #include <nmea/info.h>
70 #include <nmea/sentence.h>
71 #endif /* HTTPINFO_PUD */
73 #include "olsrd_httpinfo.h"
74 #include "admin_interface.h"
82 #define close(x) closesocket(x)
86 #define OS "GNU/Linux"
87 #endif /* __linux__ */
88 #if defined __FreeBSD__ || defined __FreeBSD_kernel__
90 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ */
93 #define OS "Undefined"
96 static char copyright_string[] __attribute__ ((unused)) =
97 "olsr.org HTTPINFO plugin Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
101 #define MAX_HTTPREQ_SIZE (1024 * 10)
103 #define DEFAULT_TCP_PORT 1978
105 #define HTML_BUFSIZE (1024 * 4000)
107 #define FRAMEWIDTH (resolve_ip_addresses ? 900 : 800)
109 #define FILENREQ_MATCH(req, filename) \
110 !strcmp(req, filename) || \
111 (strlen(req) && !strcmp(&req[1], filename))
113 static const char httpinfo_css[] =
114 "#A {text-decoration: none}\n" "TH{text-align: left}\n" "H1, H3, TD, TH {font-family: Helvetica; font-size: 80%}\n"
115 "h2\n {\nfont-family: Helvetica;\n font-size: 14px;text-align: center;\n"
116 "line-height: 16px;\ntext-decoration: none;\nborder: 1px solid #ccc;\n" "margin: 5px;\nbackground: #ececec;\n}\n"
117 "hr\n{\nborder: none;\npadding: 1px;\nbackground: url(grayline.gif) repeat-x bottom;\n}\n"
118 "#maintable\n{\nmargin: 0px;\npadding: 5px;\nborder-left: 1px solid #ccc;\n"
119 "border-right: 1px solid #ccc;\nborder-bottom: 1px solid #ccc;\n}\n"
120 "#footer\n{\nfont-size: 10px;\nline-height: 14px;\ntext-decoration: none;\ncolor: #666;\n}\n"
121 "#hdr\n{\nfont-size: 14px;\ntext-align: center;\nline-height: 16px;\n" "text-decoration: none;\nborder: 1px solid #ccc;\n"
122 "margin: 5px;\nbackground: #ececec;\n}\n"
123 "#container\n{\nwidth: 1000px;\npadding: 30px;\nborder: 1px solid #ccc;\nbackground: #fff;\n}\n"
124 "#tabnav\n{\nheight: 20px;\nmargin: 0;\npadding-left: 10px;\n" "background: url(grayline.gif) repeat-x bottom;\n}\n"
125 "#tabnav li\n{\nmargin: 0;\npadding: 0;\ndisplay: inline;\nlist-style-type: none;\n}\n"
126 "#tabnav a:link, #tabnav a:visited\n{\nfloat: left;\nbackground: #ececec;\n"
127 "font-size: 12px;\nline-height: 14px;\nfont-weight: bold;\npadding: 2px 10px 2px 10px;\n"
128 "margin-right: 4px;\nborder: 1px solid #ccc;\ntext-decoration: none;\ncolor: #777;\n}\n"
129 "#tabnav a:link.active, #tabnav a:visited.active\n{\nborder-bottom: 1px solid #fff;\n" "background: #ffffff;\ncolor: #000;\n}\n"
130 "#tabnav a:hover\n{\nbackground: #777777;\ncolor: #ffffff;\n}\n"
131 ".input_text\n{\nbackground: #E5E5E5;\nmargin-left: 5px; margin-top: 0px;\n"
132 "text-align: left;\n\nwidth: 100px;\npadding: 0px;\ncolor: #000000;\n"
133 "text-decoration: none;\nfont-family: verdana;\nfont-size: 12px;\n" "border: 1px solid #ccc;\n}\n"
134 ".input_button\n{\nbackground: #B5D1EE;\nmargin-left: 5px;\nmargin-top: 0px;\n"
135 "text-align: center;\nwidth: 120px;\npadding: 0px;\ncolor: #000000;\n"
136 "text-decoration: none;\nfont-family: verdana;\nfont-size: 12px;\n" "border: 1px solid #000;\n}\n";
138 typedef void (*build_body_callback) (struct autobuf *);
141 const char *tab_label;
142 const char *filename;
143 build_body_callback build_body_cb;
147 struct static_bin_file_entry {
148 const char *filename;
150 unsigned int data_size;
153 struct static_txt_file_entry {
154 const char *filename;
158 struct dynamic_file_entry {
159 const char *filename;
160 int (*process_data_cb) (char *, uint32_t, char *, uint32_t);
163 static int get_http_socket(int);
165 static void build_tabs(struct autobuf *, int);
167 static void parse_http_request(int fd, void *, unsigned int);
169 static int build_http_header(http_header_type, bool, uint32_t, char *, uint32_t);
171 static void build_frame(struct autobuf *, const char *, const char *, int, build_body_callback frame_body_cb);
173 static void build_routes_body(struct autobuf *);
175 static void build_config_body(struct autobuf *);
177 static void build_neigh_body(struct autobuf *);
179 static void build_topo_body(struct autobuf *);
181 static void build_mid_body(struct autobuf *);
183 static void build_nodes_body(struct autobuf *);
185 static void build_all_body(struct autobuf *);
188 static void build_pud_body(struct autobuf *);
189 #endif /* HTTPINFO_PUD */
191 static void build_about_body(struct autobuf *);
193 static void build_cfgfile_body(struct autobuf *);
195 static int check_allowed_ip(const struct allowed_net *const /*allowed_nets*/, const union olsr_ip_addr *const /*addr*/);
197 static void build_ip_txt(struct autobuf *, const bool want_link, const char *const ipaddrstr, const int prefix_len);
199 static void build_ipaddr_link(struct autobuf *, const bool want_link, const union olsr_ip_addr *const ipaddr,
200 const int prefix_len);
201 static void section_title(struct autobuf *, const char *title);
203 static void httpinfo_write_data(void *foo);
205 static struct timeval start_time;
206 static struct http_stats stats;
207 static int http_socket;
209 static char *outbuffer[MAX_CLIENTS];
210 static size_t outbuffer_size[MAX_CLIENTS];
211 static size_t outbuffer_written[MAX_CLIENTS];
212 static int outbuffer_socket[MAX_CLIENTS];
213 static int outbuffer_count;
215 static struct timer_entry *writetimer_entry;
217 static const struct tab_entry tab_entries[] = {
218 {"Configuration", "config", build_config_body, true},
219 {"Routes", "routes", build_routes_body, true},
220 {"Links/Topology", "nodes", build_nodes_body, true},
222 {"Position", "position", build_pud_body, true},
223 #endif /* HTTPINFO_PUD */
224 {"All", "all", build_all_body, true},
225 #ifdef ADMIN_INTERFACE
226 {"Admin", "admin", build_admin_body, true},
227 #endif /* ADMIN_INTERFACE */
228 {"About", "about", build_about_body, true},
229 {"FOO", "cfgfile", build_cfgfile_body, false},
230 {NULL, NULL, NULL, false}
233 static const struct static_bin_file_entry static_bin_files[] = {
234 {"favicon.ico", favicon_ico, sizeof(favicon_ico)}
236 {"logo.gif", logo_gif, sizeof(logo_gif)}
238 {"grayline.gif", grayline_gif, sizeof(grayline_gif)}
243 static const struct static_txt_file_entry static_txt_files[] = {
244 {"httpinfo.css", httpinfo_css},
248 #ifdef ADMIN_INTERFACE
249 static const struct dynamic_file_entry dynamic_files[] = {
250 {"set_values", process_set_values},
253 #endif /* ADMIN_INTERFACE */
256 get_http_socket(int port)
258 struct sockaddr_in sock_in;
261 /* Init ipc socket */
262 int s = socket(AF_INET, SOCK_STREAM, 0);
264 olsr_printf(1, "(HTTPINFO)socket %s\n", strerror(errno));
268 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
269 olsr_printf(1, "(HTTPINFO)SO_REUSEADDR failed %s\n", strerror(errno));
274 /* Bind the socket */
276 /* complete the socket structure */
277 memset(&sock_in, 0, sizeof(sock_in));
278 sock_in.sin_family = AF_INET;
279 sock_in.sin_addr.s_addr = httpinfo_listen_ip.v4.s_addr;
280 sock_in.sin_port = htons(port);
282 /* bind the socket to the port number */
283 if (bind(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) == -1) {
284 olsr_printf(1, "(HTTPINFO) bind failed %s\n", strerror(errno));
289 /* show that we are willing to listen */
290 if (listen(s, 1) == -1) {
291 olsr_printf(1, "(HTTPINFO) listen failed %s\n", strerror(errno));
300 *Do initialization here
302 *This function is called by the my_init
303 *function in uolsrd_plugin.c
306 olsrd_plugin_init(void)
309 gettimeofday(&start_time, NULL);
311 /* set up HTTP socket */
312 http_socket = get_http_socket(http_port != 0 ? http_port : DEFAULT_TCP_PORT);
314 if (http_socket < 0) {
315 fprintf(stderr, "(HTTPINFO) could not initialize HTTP socket\n");
319 /* Register socket */
320 add_olsr_socket(http_socket, &parse_http_request, NULL, NULL, SP_PR_READ);
325 /* Non reentrant - but we are not multithreaded anyway */
327 parse_http_request(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
329 struct sockaddr_in pin;
330 struct autobuf body_abuf = { 0, 0, NULL };
332 char header_buf[MAX_HTTPREQ_SIZE];
335 char http_version[11];
337 size_t header_length = 0;
341 struct timeval timeout = { 0, 200 };
342 #endif /* __linux__ */
344 if (outbuffer_count >= MAX_CLIENTS) {
345 olsr_printf(1, "(HTTPINFO) maximum number of connection reached\n");
349 addrlen = sizeof(struct sockaddr_in);
350 client_socket = accept(fd, (struct sockaddr *)&pin, &addrlen);
351 if (client_socket == -1) {
352 olsr_printf(1, "(HTTPINFO) accept: %s\n", strerror(errno));
353 goto close_connection;
357 if (setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
358 olsr_printf(1, "(HTTPINFO)SO_RCVTIMEO failed %s\n", strerror(errno));
359 goto close_connection;
362 if (setsockopt(client_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
363 olsr_printf(1, "(HTTPINFO)SO_SNDTIMEO failed %s\n", strerror(errno));
364 goto close_connection;
366 #endif /* __linux__ */
367 if (!check_allowed_ip(allowed_nets, (union olsr_ip_addr *)&pin.sin_addr.s_addr)) {
368 struct ipaddr_str strbuf;
369 olsr_printf(0, "HTTP request from non-allowed host %s!\n",
370 olsr_ip_to_string(&strbuf, (union olsr_ip_addr *)&pin.sin_addr.s_addr));
371 goto close_connection;
374 memset(header_buf, 0, sizeof(header_buf));
376 while ((r = recv(client_socket, &header_buf[c], 1, 0)) > 0 && (c < sizeof(header_buf) - 1)) {
379 if ((c > 3 && !strcmp(&header_buf[c - 4], "\r\n\r\n")) || (c > 1 && !strcmp(&header_buf[c - 2], "\n\n")))
384 olsr_printf(1, "(HTTPINFO) Failed to receive data from client!\n");
386 goto close_connection;
389 /* Get the request */
390 if (sscanf(header_buf, "%10s %250s %10s\n", req_type, filename, http_version) != 3) {
391 /* Try without HTTP version */
392 if (sscanf(header_buf, "%10s %250s\n", req_type, filename) != 2) {
393 olsr_printf(1, "(HTTPINFO) Error parsing request %s!\n", header_buf);
395 goto close_connection;
399 olsr_printf(1, "Request: %s\nfile: %s\nVersion: %s\n\n", req_type, filename, http_version);
400 abuf_init(&body_abuf, 102400);
402 if (!strcmp(req_type, "POST")) {
403 #ifdef ADMIN_INTERFACE
405 while (dynamic_files[i].filename) {
406 printf("POST checking %s\n", dynamic_files[i].filename);
407 if (FILENREQ_MATCH(filename, dynamic_files[i].filename)) {
412 param_size = recv(client_sockets[curr_clients], header_buf, sizeof(header_buf) - 1, 0);
414 header_buf[param_size] = '\0';
415 printf("Dynamic read %d bytes\n", param_size);
417 //memcpy(body, dynamic_files[i].data, static_bin_files[i].data_size);
418 body_length += dynamic_files[i].process_data_cb(header_buf, param_size, &body_buf[body_length], sizeof(body_buf) - body_length);
419 header_length = build_http_header(HTTP_OK, true, body_length, header_buf, sizeof(header_buf));
424 #endif /* ADMIN_INTERFACE */
425 /* We only support GET */
426 abuf_puts(&body_abuf, HTTP_400_MSG);
428 header_length = build_http_header(HTTP_BAD_REQ, true, body_abuf.len, header_buf, sizeof(header_buf));
429 } else if (!strcmp(req_type, "GET")) {
432 for (i = 0; static_bin_files[i].filename; i++) {
433 if (FILENREQ_MATCH(filename, static_bin_files[i].filename)) {
438 if (static_bin_files[i].filename) {
440 abuf_memcpy(&body_abuf, static_bin_files[i].data, static_bin_files[i].data_size);
441 header_length = build_http_header(HTTP_OK, false, body_abuf.len, header_buf, sizeof(header_buf));
446 while (static_txt_files[i].filename) {
447 if (FILENREQ_MATCH(filename, static_txt_files[i].filename)) {
453 if (static_txt_files[i].filename) {
455 abuf_puts(&body_abuf, static_txt_files[i].data);
456 header_length = build_http_header(HTTP_OK, false, body_abuf.len, header_buf, sizeof(header_buf));
461 if (strlen(filename) > 1) {
462 while (tab_entries[i].filename) {
463 if (FILENREQ_MATCH(filename, tab_entries[i].filename)) {
470 if (tab_entries[i].filename) {
472 header_length = build_http_header(HTTP_OK, true, body_length, header_buf, sizeof(header_buf));
473 r = send(client_sockets[curr_clients], header_buf, header_length, 0);
475 olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
476 goto close_connection;
478 netsprintf_error = 0;
479 netsprintf_direct = 1;
480 #endif /* NETDIRECT */
481 abuf_appendf(&body_abuf,
482 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" "<head>\n"
483 "<meta http-equiv=\"Content-type\" content=\"text/html; charset=ISO-8859-1\">\n"
484 "<title>olsr.org httpinfo plugin</title>\n" "<link rel=\"icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
485 "<link rel=\"shortcut icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
486 "<link rel=\"stylesheet\" type=\"text/css\" href=\"httpinfo.css\">\n" "</head>\n"
487 "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
488 "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
489 "<tbody><tr bgcolor=\"#ffffff\">\n" "<td align=\"left\" height=\"69\" valign=\"middle\" width=\"80%%\">\n"
490 "<font color=\"black\" face=\"timesroman\" size=\"6\"> <a href=\"http://www.olsr.org/\">olsr.org OLSR daemon</a></font></td>\n"
491 "<td height=\"69\" valign=\"middle\" width=\"20%%\">\n"
492 "<a href=\"http://www.olsr.org/\"><img border=\"0\" src=\"/logo.gif\" alt=\"olsrd logo\"></a></td>\n" "</tr>\n"
493 "</tbody>\n" "</table>\n", FRAMEWIDTH);
495 build_tabs(&body_abuf, i);
496 build_frame(&body_abuf, "Current Routes", "routes", FRAMEWIDTH, tab_entries[i].build_body_cb);
500 abuf_appendf(&body_abuf,
501 "</table>\n" "<div id=\"footer\">\n" "<center>\n" "(C)2005 Andreas Tønnesen<br/>\n"
502 "<a href=\"http://www.olsr.org/\">http://www.olsr.org</a>\n" "</center>\n" "</div>\n" "</body>\n" "</html>\n");
505 netsprintf_direct = 1;
506 goto close_connection;
507 #else /* NETDIRECT */
508 header_length = build_http_header(HTTP_OK, true, body_abuf.len, header_buf, sizeof(header_buf));
510 #endif /* NETDIRECT */
514 abuf_puts(&body_abuf, HTTP_404_MSG);
515 header_length = build_http_header(HTTP_BAD_FILE, true, body_abuf.len, header_buf, sizeof(header_buf));
517 /* We only support GET */
518 abuf_puts(&body_abuf, HTTP_404_MSG);
520 header_length = build_http_header(HTTP_BAD_REQ, true, body_abuf.len, header_buf, sizeof(header_buf));
524 if (header_length + body_abuf.len > 0) {
525 outbuffer[outbuffer_count] = olsr_malloc(header_length + body_abuf.len, "http output buffer");
526 outbuffer_size[outbuffer_count] = header_length + body_abuf.len;
527 outbuffer_written[outbuffer_count] = 0;
528 outbuffer_socket[outbuffer_count] = client_socket;
530 memcpy(outbuffer[outbuffer_count], header_buf, header_length);
531 if (body_abuf.len > 0) {
532 memcpy((outbuffer[outbuffer_count]) + header_length, body_abuf.buf, body_abuf.len);
536 if (outbuffer_count == 1) {
537 writetimer_entry = olsr_start_timer(100, 0, OLSR_TIMER_PERIODIC, &httpinfo_write_data, NULL, 0);
540 abuf_free(&body_abuf);
542 * client_socket is stored in outbuffer_socket[outbuffer_count] and closed
543 * by the httpinfo_write_data timer callback, so don't close it here
548 abuf_free(&body_abuf);
549 if (client_socket >= 0) {
550 close(client_socket);
555 httpinfo_write_data(void *foo __attribute__ ((unused))) {
557 int result, i, j, max;
562 for (i=0; i<outbuffer_count; i++) {
563 /* prevent warning in win32 */
564 FD_SET((unsigned int)outbuffer_socket[i], &set);
565 if (outbuffer_socket[i] > max) {
566 max = outbuffer_socket[i];
573 result = select(max + 1, NULL, &set, NULL, &tv);
578 for (i=0; i<outbuffer_count; i++) {
579 if (FD_ISSET(outbuffer_socket[i], &set)) {
580 result = write(outbuffer_socket[i], outbuffer[i] + outbuffer_written[i], outbuffer_size[i] - outbuffer_written[i]);
582 outbuffer_written[i] += result;
585 if (result <= 0 || outbuffer_written[i] == outbuffer_size[i]) {
586 /* close this socket and cleanup*/
587 close(outbuffer_socket[i]);
590 for (j=i+1; j<outbuffer_count; j++) {
591 outbuffer[j-1] = outbuffer[j];
592 outbuffer_size[j-1] = outbuffer_size[j];
593 outbuffer_socket[j-1] = outbuffer_socket[j];
594 outbuffer_written[j-1] = outbuffer_written[j];
600 if (outbuffer_count == 0) {
601 olsr_stop_timer(writetimer_entry);
606 build_http_header(http_header_type type, bool is_html, uint32_t msgsize, char *buf, uint32_t bufsize)
624 size = snprintf(buf, bufsize, "%s", h);
628 size += strftime(&buf[size], bufsize - size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
631 size += snprintf(&buf[size], bufsize - size, "Server: %s %s %s\r\n", PLUGIN_NAME, PLUGIN_VERSION, HTTP_VERSION);
633 /* connection-type */
634 size += snprintf(&buf[size], bufsize - size, "Connection: closed\r\n");
637 size += snprintf(&buf[size], bufsize - size, "Content-type: text/%s\r\n", is_html ? "html" : "plain");
641 size += snprintf(&buf[size], bufsize - size, "Content-length: %i\r\n", msgsize);
645 * No caching dynamic pages
647 size += snprintf(&buf[size], bufsize - size, "Cache-Control: no-cache\r\n");
650 size += snprintf(&buf[size], bufsize - size, "Accept-Ranges: bytes\r\n");
653 size += snprintf(&buf[size], bufsize - size, "\r\n");
655 olsr_printf(1, "HEADER:\n%s", buf);
661 build_tabs(struct autobuf *abuf, int active)
666 "<table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
667 "<tr bgcolor=\"#ffffff\"><td>\n" "<ul id=\"tabnav\">\n", FRAMEWIDTH);
668 for (tabs = 0; tab_entries[tabs].tab_label; tabs++) {
669 if (!tab_entries[tabs].display_tab) {
672 abuf_appendf(abuf, "<li><a href=\"%s\"%s>%s</a></li>\n", tab_entries[tabs].filename,
673 tabs == active ? " class=\"active\"" : "", tab_entries[tabs].tab_label);
675 abuf_appendf(abuf, "</ul>\n" "</td></tr>\n" "<tr><td>\n");
679 * destructor - called at unload
682 olsr_plugin_exit(void)
684 struct allowed_net *a, *next;
685 if (http_socket >= 0) {
689 for (a = allowed_nets; a != NULL; a = next) {
697 section_title(struct autobuf *abuf, const char *title)
700 "<h2>%s</h2>\n" "<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n",
705 build_frame(struct autobuf *abuf, const char *title __attribute__ ((unused)), const char *the_link
706 __attribute__ ((unused)), int width __attribute__ ((unused)), build_body_callback frame_body_cb)
708 abuf_puts(abuf, "<div id=\"maintable\">\n");
710 abuf_puts(abuf, "</div>\n");
714 fmt_href(struct autobuf *abuf, const char *const ipaddr)
716 abuf_appendf(abuf, "<a href=\"http://%s:%d/all\">", ipaddr, http_port);
720 build_ip_txt(struct autobuf *abuf, const bool print_link, const char *const ipaddrstr, const int prefix_len)
723 fmt_href(abuf, ipaddrstr);
726 abuf_puts(abuf, ipaddrstr);
727 /* print ip address or ip prefix ? */
728 if (prefix_len != -1 && prefix_len != olsr_cnf->maxplen) {
729 abuf_appendf(abuf, "/%d", prefix_len);
732 if (print_link) { /* Print the link only if there is no prefix_len */
733 abuf_puts(abuf, "</a>");
738 build_ipaddr_link(struct autobuf *abuf, const bool want_link, const union olsr_ip_addr *const ipaddr,
739 const int prefix_len)
741 struct ipaddr_str ipaddrstr;
742 const struct hostent *const hp =
744 resolve_ip_addresses ? gethostbyaddr((const void *)ipaddr, olsr_cnf->ipsize,
745 olsr_cnf->ip_version) :
748 /* Print the link only if there is no prefix_len and ip_version is AF_INET */
749 const int print_link = want_link && (prefix_len == -1 || prefix_len == olsr_cnf->maxplen) && (olsr_cnf->ip_version == AF_INET);
750 olsr_ip_to_string(&ipaddrstr, ipaddr);
752 abuf_puts(abuf, "<td>");
753 build_ip_txt(abuf, print_link, ipaddrstr.buf, prefix_len);
754 abuf_puts(abuf, "</td>");
756 if (resolve_ip_addresses) {
758 abuf_puts(abuf, "<td>(");
760 fmt_href(abuf, ipaddrstr.buf);
762 abuf_puts(abuf, hp->h_name);
764 abuf_puts(abuf, "</a>");
766 abuf_puts(abuf, ")</td>");
768 abuf_puts(abuf, "<td/>");
773 #define build_ipaddr_with_link(buf, ipaddr, plen) \
774 build_ipaddr_link((buf), true, (ipaddr), (plen))
775 #define build_ipaddr_no_link(buf, ipaddr, plen) \
776 build_ipaddr_link((buf), false, (ipaddr), (plen))
779 build_route(struct autobuf *abuf, const struct rt_entry *rt)
781 struct lqtextbuffer lqbuffer;
783 abuf_puts(abuf, "<tr>");
784 build_ipaddr_with_link(abuf, &rt->rt_dst.prefix, rt->rt_dst.prefix_len);
785 build_ipaddr_with_link(abuf, &rt->rt_best->rtp_nexthop.gateway, -1);
787 abuf_appendf(abuf, "<td>%d</td>", rt->rt_best->rtp_metric.hops);
788 abuf_appendf(abuf, "<td>%s</td>",
789 get_linkcost_text(rt->rt_best->rtp_metric.cost, true, &lqbuffer));
790 abuf_appendf(abuf, "<td>%s</td></tr>\n",
791 if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
795 build_routes_body(struct autobuf *abuf)
798 const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
799 section_title(abuf, "OLSR Routes in Kernel");
801 "<tr><th%s>Destination</th><th%s>Gateway</th><th>Metric</th><th>ETX</th><th>Interface</th></tr>\n",
804 /* Walk the route table */
805 OLSR_FOR_ALL_RT_ENTRIES(rt) {
806 build_route(abuf, rt);
807 } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
809 abuf_puts(abuf, "</table>\n");
813 build_config_body(struct autobuf *abuf)
815 const struct olsr_if *ifs;
816 const struct plugin_entry *pentry;
817 const struct plugin_param *pparam;
818 struct ipaddr_str mainaddrbuf;
820 abuf_appendf(abuf, "Version: %s (built on %s on %s)\n<br>", olsrd_version, build_date, build_host);
821 abuf_appendf(abuf, "OS: %s\n<br>", OS);
824 const time_t currtime = time(NULL);
826 abuf_strftime(abuf, "System time: <em>%a, %d %b %Y %H:%M:%S</em><br>",
827 localtime(&currtime));
831 struct timeval now, uptime;
832 int hours, mins, days;
833 gettimeofday(&now, NULL);
834 timersub(&now, &start_time, &uptime);
836 days = uptime.tv_sec / 86400;
837 uptime.tv_sec %= 86400;
838 hours = uptime.tv_sec / 3600;
839 uptime.tv_sec %= 3600;
840 mins = uptime.tv_sec / 60;
843 abuf_puts(abuf, "Olsrd uptime: <em>");
845 abuf_appendf(abuf, "%d day(s) ", days);
847 abuf_appendf(abuf, "%02d hours %02d minutes %02d seconds</em><br/>\n", hours, mins, (int)uptime.tv_sec);
850 abuf_appendf(abuf, "HTTP stats(ok/dyn/error/illegal): <em>%d/%d/%d/%d</em><br>\n", stats.ok_hits,
851 stats.dyn_hits, stats.err_hits, stats.ill_hits);
854 "Click <a href=\"/cfgfile\">here</a> to <em>generate a configuration file for this node</em>.\n");
856 abuf_puts(abuf, "<h2>Variables</h2>\n");
858 abuf_puts(abuf, "<table width=\"100%%\" border=\"0\">\n<tr>");
860 abuf_appendf(abuf, "<td>Main address: <strong>%s</strong></td>\n",
861 olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
862 abuf_appendf(abuf, "<td>IP version: %d</td>\n", olsr_cnf->ip_version == AF_INET ? 4 : 6);
863 abuf_appendf(abuf, "<td>Debug level: %d</td>\n", olsr_cnf->debug_level);
864 abuf_appendf(abuf, "<td>FIB Metrics: %s</td>\n", FIB_METRIC_TXT[olsr_cnf->fib_metric]);
866 abuf_puts(abuf, "</tr>\n<tr>\n");
868 abuf_appendf(abuf, "<td>Pollrate: %0.2f</td>\n", (double)olsr_cnf->pollrate);
869 abuf_appendf(abuf, "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
870 abuf_appendf(abuf, "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
871 abuf_appendf(abuf, "<td>NAT threshold: %f</td>\n", (double)olsr_cnf->lq_nat_thresh);
873 abuf_puts(abuf, "</tr>\n<tr>\n");
875 abuf_appendf(abuf, "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
876 abuf_appendf(abuf, "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
877 abuf_appendf(abuf, "<td>RtTable: 0x%04x/%d</td>\n", olsr_cnf->rt_table, olsr_cnf->rt_table);
878 abuf_appendf(abuf, "<td>RtTableDefault: 0x%04x/%d</td>\n", olsr_cnf->rt_table_default,
879 olsr_cnf->rt_table_default);
880 abuf_appendf(abuf, "<td>RtTableTunnel: 0x%04x/%d</td>\n", olsr_cnf->rt_table_tunnel,
881 olsr_cnf->rt_table_tunnel);
882 abuf_appendf(abuf, "<td>Willingness: %d %s</td>\n", olsr_cnf->willingness,
883 olsr_cnf->willingness_auto ? "(auto)" : "");
885 if (olsr_cnf->lq_level == 0) {
886 abuf_appendf(abuf, "</tr>\n<tr>\n" "<td>Hysteresis: %s</td>\n",
887 olsr_cnf->use_hysteresis ? "Enabled" : "Disabled");
888 if (olsr_cnf->use_hysteresis) {
889 abuf_appendf(abuf, "<td>Hyst scaling: %0.2f</td>\n", (double)olsr_cnf->hysteresis_param.scaling);
890 abuf_appendf(abuf, "<td>Hyst lower/upper: %0.2f/%0.2f</td>\n", (double)olsr_cnf->hysteresis_param.thr_low,
891 (double)olsr_cnf->hysteresis_param.thr_high);
895 abuf_appendf(abuf, "</tr>\n<tr>\n" "<td>LQ extension: %s</td>\n",
896 olsr_cnf->lq_level ? "Enabled" : "Disabled");
897 if (olsr_cnf->lq_level) {
898 abuf_appendf(abuf, "<td>LQ level: %d</td>\n" "<td>LQ aging: %f</td>\n", olsr_cnf->lq_level,
899 (double)olsr_cnf->lq_aging);
901 abuf_puts(abuf, "</tr></table>\n");
903 abuf_puts(abuf, "<h2>Interfaces</h2>\n");
904 abuf_puts(abuf, "<table width=\"100%%\" border=\"0\">\n");
905 for (ifs = olsr_cnf->interfaces; ifs != NULL; ifs = ifs->next) {
906 const struct interface *const rifs = ifs->interf;
907 abuf_appendf(abuf, "<tr><th colspan=\"3\">%s</th>\n", ifs->name);
909 abuf_puts(abuf, "<tr><td colspan=\"3\">Status: DOWN</td></tr>\n");
913 if (olsr_cnf->ip_version == AF_INET) {
914 struct ipaddr_str addrbuf, maskbuf, bcastbuf;
915 abuf_appendf(abuf, "<tr>\n" "<td>IP: %s</td>\n" "<td>MASK: %s</td>\n" "<td>BCAST: %s</td>\n" "</tr>\n",
916 ip4_to_string(&addrbuf, rifs->int_addr.sin_addr), ip4_to_string(&maskbuf, rifs->int_netmask.sin_addr),
917 ip4_to_string(&bcastbuf, rifs->int_broadaddr.sin_addr));
919 struct ipaddr_str addrbuf, maskbuf;
920 abuf_appendf(abuf, "<tr>\n" "<td>IP: %s</td>\n" "<td>MCAST: %s</td>\n" "<td></td>\n" "</tr>\n",
921 ip6_to_string(&addrbuf, &rifs->int6_addr.sin6_addr), ip6_to_string(&maskbuf, &rifs->int6_multaddr.sin6_addr));
923 abuf_appendf(abuf, "<tr>\n" "<td>MTU: %d</td>\n" "<td>WLAN: %s</td>\n" "<td>STATUS: UP</td>\n" "</tr>\n",
924 rifs->int_mtu, rifs->is_wireless ? "Yes" : "No");
926 abuf_puts(abuf, "</table>\n");
928 abuf_appendf(abuf, "<em>Olsrd is configured to %s if no interfaces are available</em><br>\n",
929 olsr_cnf->allow_no_interfaces ? "run even" : "halt");
931 abuf_puts(abuf, "<h2>Plugins</h2>\n");
932 abuf_puts(abuf, "<table width=\"100%%\" border=\"0\"><tr><th>Name</th><th>Parameters</th></tr>\n");
933 for (pentry = olsr_cnf->plugins; pentry; pentry = pentry->next) {
934 abuf_appendf(abuf, "<tr><td>%s</td>\n" "<td><select>\n" "<option>KEY, VALUE</option>\n", pentry->name);
936 for (pparam = pentry->params; pparam; pparam = pparam->next) {
937 abuf_appendf(abuf, "<option>\"%s\", \"%s\"</option>\n", pparam->key, pparam->value);
939 abuf_puts(abuf, "</select></td></tr>\n");
942 abuf_puts(abuf, "</table>\n");
944 section_title(abuf, "Announced HNA entries");
945 if (olsr_cnf->hna_entries) {
946 struct ip_prefix_list *hna;
947 abuf_puts(abuf, "<tr><th>Network</th></tr>\n");
948 for (hna = olsr_cnf->hna_entries; hna; hna = hna->next) {
949 struct ipaddr_str netbuf;
950 abuf_appendf(abuf, "<tr><td>%s/%d</td></tr>\n", olsr_ip_to_string(&netbuf, &hna->net.prefix),
951 hna->net.prefix_len);
954 abuf_puts(abuf, "<tr><td></td></tr>\n");
956 abuf_puts(abuf, "</table>\n");
960 build_neigh_body(struct autobuf *abuf)
962 struct neighbor_entry *neigh;
963 struct link_entry *the_link = NULL;
964 const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
966 section_title(abuf, "Links");
969 "<tr><th%s>Local IP</th><th%s>Remote IP</th><th>Hysteresis</th>",
971 if (olsr_cnf->lq_level > 0) {
972 abuf_puts(abuf, "<th>LinkCost</th>");
974 abuf_puts(abuf, "</tr>\n");
977 OLSR_FOR_ALL_LINK_ENTRIES(the_link) {
978 abuf_puts(abuf, "<tr>");
979 build_ipaddr_with_link(abuf, &the_link->local_iface_addr, -1);
980 build_ipaddr_with_link(abuf, &the_link->neighbor_iface_addr, -1);
981 abuf_appendf(abuf, "<td>%0.2f</td>", (double)the_link->L_link_quality);
982 if (olsr_cnf->lq_level > 0) {
983 struct lqtextbuffer lqbuffer1, lqbuffer2;
984 abuf_appendf(abuf, "<td>(%s) %s</td>", get_link_entry_text(the_link, '/', &lqbuffer1),
985 get_linkcost_text(the_link->linkcost, false, &lqbuffer2));
987 abuf_puts(abuf, "</tr>\n");
988 } OLSR_FOR_ALL_LINK_ENTRIES_END(the_link);
990 abuf_puts(abuf, "</table>\n");
992 section_title(abuf, "Neighbors");
994 "<tr><th%s>IP Address</th><th>SYM</th><th>MPR</th><th>MPRS</th><th>Willingness</th><th>2 Hop Neighbors</th></tr>\n",
997 OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
999 struct neighbor_2_list_entry *list_2;
1001 abuf_puts(abuf, "<tr>");
1002 build_ipaddr_with_link(abuf, &neigh->neighbor_main_addr, -1);
1004 "<td>%s</td>" "<td>%s</td>" "<td>%s</td>"
1005 "<td>%d</td>", (neigh->status == SYM) ? "YES" : "NO", neigh->is_mpr ? "YES" : "NO",
1006 olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO", neigh->willingness);
1008 abuf_puts(abuf, "<td><select>\n" "<option>IP ADDRESS</option>\n");
1010 for (list_2 = neigh->neighbor_2_list.next, thop_cnt = 0; list_2 != &neigh->neighbor_2_list; list_2 = list_2->next, thop_cnt++) {
1011 struct ipaddr_str strbuf;
1012 abuf_appendf(abuf, "<option>%s</option>\n",
1013 olsr_ip_to_string(&strbuf, &list_2->neighbor_2->neighbor_2_addr));
1015 abuf_appendf(abuf, "</select> (%d)</td></tr>\n", thop_cnt);
1016 } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
1018 abuf_puts(abuf, "</table>\n");
1022 build_topo_body(struct autobuf *abuf)
1024 struct tc_entry *tc;
1025 const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
1027 section_title(abuf, "Topology Entries");
1028 abuf_appendf(abuf, "<tr><th%s>Destination IP</th><th%s>Last Hop IP</th>",
1030 if (olsr_cnf->lq_level > 0) {
1031 abuf_puts(abuf, "<th>Linkcost</th>");
1033 abuf_puts(abuf, "</tr>\n");
1035 OLSR_FOR_ALL_TC_ENTRIES(tc) {
1036 struct tc_edge_entry *tc_edge;
1037 OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
1038 if (tc_edge->edge_inv) {
1039 abuf_puts(abuf, "<tr>");
1040 build_ipaddr_with_link(abuf, &tc_edge->T_dest_addr, -1);
1041 build_ipaddr_with_link(abuf, &tc->addr, -1);
1042 if (olsr_cnf->lq_level > 0) {
1043 struct lqtextbuffer lqbuffer1, lqbuffer2;
1044 abuf_appendf(abuf, "<td>(%s) %s</td>\n",
1045 get_tc_edge_entry_text(tc_edge, '/', &lqbuffer1), get_linkcost_text(tc_edge->cost, false, &lqbuffer2));
1047 abuf_puts(abuf, "</tr>\n");
1049 } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
1050 } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
1052 abuf_puts(abuf, "</table>\n");
1056 build_mid_body(struct autobuf *abuf)
1059 const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
1061 section_title(abuf, "MID Entries");
1062 abuf_appendf(abuf, "<tr><th%s>Main Address</th><th>Aliases</th></tr>\n", colspan);
1065 for (idx = 0; idx < HASHSIZE; idx++) {
1066 struct mid_entry *entry;
1067 for (entry = mid_set[idx].next; entry != &mid_set[idx]; entry = entry->next) {
1069 struct mid_address *alias;
1070 abuf_puts(abuf, "<tr>");
1071 build_ipaddr_with_link(abuf, &entry->main_addr, -1);
1072 abuf_puts(abuf, "<td><select>\n<option>IP ADDRESS</option>\n");
1074 for (mid_cnt = 0, alias = entry->aliases; alias != NULL; alias = alias->next_alias, mid_cnt++) {
1075 struct ipaddr_str strbuf;
1076 abuf_appendf(abuf, "<option>%s</option>\n", olsr_ip_to_string(&strbuf, &alias->alias));
1078 abuf_appendf(abuf, "</select> (%d)</td></tr>\n", mid_cnt);
1082 abuf_puts(abuf, "</table>\n");
1086 build_nodes_body(struct autobuf *abuf)
1088 build_neigh_body(abuf);
1089 build_topo_body(abuf);
1090 build_mid_body(abuf);
1094 build_all_body(struct autobuf *abuf)
1096 build_config_body(abuf);
1097 build_routes_body(abuf);
1098 build_neigh_body(abuf);
1099 build_topo_body(abuf);
1100 build_mid_body(abuf);
1102 build_pud_body(abuf);
1103 #endif /* HTTPINFO_PUD */
1108 * Determine if a nmeaINFO structure has a certain field.
1109 * We need this function locally because nmealib might not be loaded.
1111 * @param present the presence field
1112 * @param fieldName use a name from nmeaINFO_FIELD
1113 * @return a boolean, true when the structure has the requested field
1115 static inline bool nmea_INFO_has_field_local(uint32_t present, nmeaINFO_FIELD fieldName) {
1116 return ((present & fieldName) != 0);
1119 static const char * NA_STRING = "N.A.";
1120 static const char * SAT_INUSE_COLOR = "lime";
1121 static const char * SAT_NOTINUSE_COLOR = "red";
1123 static void build_pud_body(struct autobuf *abuf) {
1124 TransmitGpsInformation * txGpsInfo = olsr_cnf->pud_position;
1126 char nodeIdString[256];
1130 abuf_puts(abuf, "<h2>Position</h2>");
1133 abuf_puts(abuf, "<p><b>" PUD_PLUGIN_ABBR " plugin not loaded</b></p>\n");
1137 nodeId = (char *) txGpsInfo->nodeId;
1139 if (!nodeId || !strlen(nodeId)) {
1140 inet_ntop(olsr_cnf->ip_version, &olsr_cnf->main_addr, &nodeIdString[0], sizeof(nodeIdString));
1141 nodeId = nodeIdString;
1144 /* start of table */
1146 "<p><table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n"
1147 "<tr><th>Parameter</th><th> </th><th>Unit</th><th> </th><th>Value</th></tr>\n"
1152 "<tr><td>Name</td><td></td><td></td><td></td><td id=\"nodeId\">%s</td></tr>\n",
1157 abuf_puts(abuf, "<tr><td>Date / Time</td><td></td><td>UTC</td><td></td><td id=\"utc\">");
1158 datePresent = nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, UTCDATE);
1159 timePresent = nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, UTCTIME);
1160 if (datePresent || timePresent) {
1162 abuf_appendf(abuf, "%04d%02d%02d",
1163 txGpsInfo->txPosition.nmeaInfo.utc.year + 1900,
1164 txGpsInfo->txPosition.nmeaInfo.utc.mon,
1165 txGpsInfo->txPosition.nmeaInfo.utc.day);
1167 if (datePresent && timePresent) {
1168 abuf_puts(abuf, " ");
1171 abuf_appendf(abuf, "%02d:%02d:%02d.%02d",
1172 txGpsInfo->txPosition.nmeaInfo.utc.hour,
1173 txGpsInfo->txPosition.nmeaInfo.utc.min,
1174 txGpsInfo->txPosition.nmeaInfo.utc.sec,
1175 txGpsInfo->txPosition.nmeaInfo.utc.hsec);
1178 abuf_puts(abuf, NA_STRING);
1180 abuf_puts(abuf, "</td></tr>\n");
1183 abuf_puts(abuf, "<tr><td>Input Sentences</td><td></td><td></td><td></td><td id=\"smask\">");
1184 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, SMASK)
1185 && (txGpsInfo->txPosition.nmeaInfo.smask != GPNON)) {
1186 const int id[] = { GPGGA, GPGSA, GPGSV, GPRMC, GPVTG, GPNON };
1187 const char * ids[] = { "GPGGA", "GPGSA", "GPGSV", "GPRMC", "GPVTG" };
1188 bool printed = false;
1191 while (id[i] != GPNON) {
1192 if (txGpsInfo->txPosition.nmeaInfo.smask & id[i]) {
1194 abuf_puts(abuf, " ");
1195 abuf_puts(abuf, ids[i]);
1201 abuf_puts(abuf, NA_STRING);
1203 abuf_puts(abuf, "</td></tr>\n");
1206 abuf_puts(abuf, "<tr><td>Signal Strength</td><td></td><td></td><td></td><td id=\"sig\">");
1207 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, SIG)) {
1209 switch (txGpsInfo->txPosition.nmeaInfo.sig) {
1222 case NMEA_SIG_RTKIN:
1223 s = "Real Time Kinematic";
1225 case NMEA_SIG_FLRTK:
1228 case NMEA_SIG_ESTIM:
1229 s = "Estimated (Dead Reckoning)";
1232 s = "Manual Input Mode";
1235 s = "Simulation Mode";
1241 abuf_appendf(abuf, "%s (%d)", s, txGpsInfo->txPosition.nmeaInfo.sig);
1243 abuf_puts(abuf, NA_STRING);
1245 abuf_puts(abuf, "</td></tr>\n");
1248 abuf_puts(abuf, "<tr><td>Fix</td><td></td><td></td><td></td><td id=\"fix\">");
1249 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, FIX)) {
1251 switch (txGpsInfo->txPosition.nmeaInfo.fix) {
1265 abuf_appendf(abuf, "%s (%d)", s, txGpsInfo->txPosition.nmeaInfo.fix);
1267 abuf_puts(abuf, NA_STRING);
1269 abuf_puts(abuf, "</td></tr>\n");
1272 abuf_puts(abuf, "<tr><td>PDOP</td><td></td><td></td><td></td><td id=\"pdop\">");
1273 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, PDOP)) {
1274 abuf_appendf(abuf, "%f", txGpsInfo->txPosition.nmeaInfo.PDOP);
1276 abuf_puts(abuf, NA_STRING);
1278 abuf_puts(abuf, "</td></tr>\n");
1281 abuf_puts(abuf, "<tr><td>HDOP</td><td></td><td></td><td></td><td id=\"hdop\">");
1282 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, HDOP)) {
1283 abuf_appendf(abuf, "%f", txGpsInfo->txPosition.nmeaInfo.HDOP);
1285 abuf_puts(abuf, NA_STRING);
1287 abuf_puts(abuf, "</td></tr>\n");
1290 abuf_puts(abuf, "<tr><td>VDOP</td><td></td><td></td><td></td><td id=\"vdop\">");
1291 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, VDOP)) {
1292 abuf_appendf(abuf, "%f", txGpsInfo->txPosition.nmeaInfo.VDOP);
1294 abuf_puts(abuf, NA_STRING);
1296 abuf_puts(abuf, "</td></tr>\n");
1299 abuf_puts(abuf, "<tr><td>Latitude</td><td></td><td>degrees</td><td></td><td id=\"lat\">");
1300 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, LAT)) {
1301 abuf_appendf(abuf, "%f", txGpsInfo->txPosition.nmeaInfo.lat);
1303 abuf_puts(abuf, NA_STRING);
1305 abuf_puts(abuf, "</td></tr>\n");
1308 abuf_puts(abuf, "<tr><td>Longitude</td><td></td><td>degrees</td><td></td><td id=\"lon\">");
1309 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, LON)) {
1310 abuf_appendf(abuf, "%f", txGpsInfo->txPosition.nmeaInfo.lon);
1312 abuf_puts(abuf, NA_STRING);
1314 abuf_puts(abuf, "</td></tr>\n");
1317 abuf_puts(abuf, "<tr><td>Elevation</td><td></td><td>m</td><td></td><td id=\"elv\">");
1318 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, ELV)) {
1319 abuf_appendf(abuf, "%f", txGpsInfo->txPosition.nmeaInfo.elv);
1321 abuf_puts(abuf, NA_STRING);
1323 abuf_puts(abuf, "</td></tr>\n");
1326 abuf_puts(abuf, "<tr><td>Speed</td><td></td><td>kph</td><td></td><td id=\"speed\">");
1327 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, SPEED)) {
1328 abuf_appendf(abuf, "%f", txGpsInfo->txPosition.nmeaInfo.speed);
1330 abuf_puts(abuf, NA_STRING);
1332 abuf_puts(abuf, "</td></tr>\n");
1335 abuf_puts(abuf, "<tr><td>Track</td><td></td><td>degrees</td><td></td><td id=\"track\">");
1336 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, TRACK)) {
1337 abuf_appendf(abuf, "%f", txGpsInfo->txPosition.nmeaInfo.track);
1339 abuf_puts(abuf, NA_STRING);
1341 abuf_puts(abuf, "</td></tr>\n");
1344 abuf_puts(abuf, "<tr><td>Magnetic Track</td><td></td><td>degrees</td><td></td><td id=\"mtrack\">");
1345 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, MTRACK)) {
1346 abuf_appendf(abuf, "%f", txGpsInfo->txPosition.nmeaInfo.mtrack);
1348 abuf_puts(abuf, NA_STRING);
1350 abuf_puts(abuf, "</td></tr>\n");
1353 abuf_puts(abuf, "<tr><td>Magnetic Variation</td><td></td><td>degrees</td><td></td><td id=\"magvar\">");
1354 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, MAGVAR)) {
1355 abuf_appendf(abuf, "%f", txGpsInfo->txPosition.nmeaInfo.magvar);
1357 abuf_puts(abuf, NA_STRING);
1359 abuf_puts(abuf, "</td></tr>\n");
1362 abuf_puts(abuf, "</table></p>\n");
1365 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, SATINVIEW)) {
1368 abuf_puts(abuf, "<p>\n");
1369 abuf_puts(abuf, "Satellite Infomation:\n");
1370 abuf_puts(abuf, "<table border=\"1\" cellpadding=\"2\" cellspacing=\"0\" id=\"satinfo\">\n");
1371 abuf_puts(abuf, "<tbody align=\"center\">\n");
1373 "<tr><th>ID</th><th>In Use</th><th>Elevation (degrees)</th><th>Azimuth (degrees)</th><th>Signal (dB)</th></tr>\n");
1375 if (txGpsInfo->txPosition.nmeaInfo.satinfo.inview) {
1377 for (satIndex = 0; satIndex < NMEA_MAXSAT; satIndex++) {
1378 nmeaSATELLITE * sat = &txGpsInfo->txPosition.nmeaInfo.satinfo.sat[satIndex];
1381 const char * inuseStr;
1383 if (!nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, SATINUSE)) {
1384 inuseStr = NA_STRING;
1387 for (inuseIndex = 0; inuseIndex < NMEA_MAXSAT; inuseIndex++) {
1388 if (txGpsInfo->txPosition.nmeaInfo.satinfo.in_use[inuseIndex] == sat->id) {
1400 abuf_appendf(abuf, "<tr><td>%02d</td><td bgcolor=\"%s\">%s</td><td>%02d</td><td>%03d</td><td>%02d</td></tr>\n",
1401 sat->id, inuse ? SAT_INUSE_COLOR : SAT_NOTINUSE_COLOR, inuseStr, sat->elv, sat->azimuth, sat->sig);
1408 abuf_puts(abuf, "<tr><td colspan=\"5\">none</td></tr>\n");
1411 abuf_puts(abuf, "</tbody></table>\n");
1412 abuf_puts(abuf, "</p>\n");
1415 /* add Google Maps and OpenStreetMap links when we have both lat and lon */
1416 if (nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, LAT)
1417 && nmea_INFO_has_field_local(txGpsInfo->txPosition.nmeaInfo.present, LON)) {
1418 const char * c = nodeId;
1422 "<a href=\"http://maps.google.com/maps?q=%f,+%f+%%28",
1423 txGpsInfo->txPosition.nmeaInfo.lat,
1424 txGpsInfo->txPosition.nmeaInfo.lon
1427 while (*c != '\0') {
1428 if (*c == ' ' || *c == '\t') {
1429 abuf_puts(abuf, "+");
1431 abuf_appendf(abuf, "%c", *c);
1436 abuf_puts(abuf, "%29&iwloc=A\">Show on Google Maps</a></p>\n");
1440 "<a href=\"http://www.openstreetmap.org/index.html?mlat=%f&mlon=%f&zoom=15&layers=M\">Show on OpenStreetMap</a></p>\n",
1441 txGpsInfo->txPosition.nmeaInfo.lat,
1442 txGpsInfo->txPosition.nmeaInfo.lon
1446 #endif /* HTTPINFO_PUD */
1449 build_about_body(struct autobuf *abuf)
1452 "<strong>" PLUGIN_NAME " version " PLUGIN_VERSION "</strong><br/>\n" "by Andreas Tønnesen (C)2005.<br/>\n"
1454 #ifdef ADMIN_INTERFACE
1455 "<em>with experimental admin interface</em> "
1456 #endif /* ADMIN_INTERFACE */
1457 "%s at %s<hr/>\n" "This plugin implements a HTTP server that supplies\n"
1458 "the client with various dynamic web pages representing\n"
1459 "the current olsrd status.<br/>The different pages include:\n"
1460 "<ul>\n<li><strong>Configuration</strong> - This page displays information\n"
1461 "about the current olsrd configuration. This includes various\n"
1462 "olsr settings such as IP version, MID/TC redundancy, hysteresis\n"
1463 "etc. Information about the current status of the interfaces on\n"
1464 "which olsrd is configured to run is also displayed. Loaded olsrd\n"
1465 "plugins are shown with their plugin parameters. Finally all local\n"
1466 "HNA entries are shown. These are the networks that the local host\n"
1467 "will anounce itself as a gateway to.</li>\n"
1468 "<li><strong>Routes</strong> - This page displays all routes currently set in\n"
1469 "the kernel <em>by olsrd</em>. The type of route is also displayed(host\n" "or HNA).</li>\n"
1470 "<li><strong>Links/Topology</strong> - This page displays all information about\n"
1471 "links, neighbors, topology, MID and HNA entries.</li>\n"
1472 "<li><strong>All</strong> - Here all the previous pages are displayed as one.\n"
1473 "This is to make all information available as easy as possible(for example\n"
1474 "for a script) and using as few resources as possible.</li>\n"
1475 #ifdef ADMIN_INTERFACE
1476 "<li><strong>Admin</strong> - This page is highly experimental(and unsecure)!\n"
1477 "As of now it is not working at all but it provides a impression of\n"
1478 "the future possibilities of httpinfo. This is to be a interface to\n"
1479 "changing olsrd settings in realtime. These settings include various\n"
1480 "\"basic\" settings and local HNA settings.</li>\n"
1481 #endif /* ADMIN_INTERFACE */
1482 "<li><strong>About</strong> - this help page.</li>\n</ul>" "<hr/>\n" "Send questions or comments to\n"
1483 "<a href=\"mailto:olsr-users@olsr.org\">olsr-users@olsr.org</a> or\n"
1484 "<a href=\"mailto:andreto-at-olsr.org\">andreto-at-olsr.org</a><br/>\n"
1485 "Official olsrd homepage: <a href=\"http://www.olsr.org/\">http://www.olsr.org</a><br/>\n", build_date,
1490 build_cfgfile_body(struct autobuf *abuf)
1493 "\n\n" "<strong>This is a automatically generated configuration\n"
1494 "file based on the current olsrd configuration of this node.<br/>\n" "<hr/>\n" "<pre>\n");
1495 olsrd_write_cnf_autobuf(abuf, olsr_cnf);
1497 abuf_puts(abuf, "</pre>\n<hr/>\n");
1501 check_allowed_ip(const struct allowed_net *const my_allowed_nets, const union olsr_ip_addr *const addr)
1503 const struct allowed_net *alln;
1504 for (alln = my_allowed_nets; alln != NULL; alln = alln->next) {
1505 if (ip_in_net(addr, &alln->prefix)) {
1515 * indent-tabs-mode: nil