00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "olsrd_httpinfo.h"
00047 #include "admin_interface.h"
00048 #include "gfx.h"
00049
00050 #include "olsr.h"
00051 #include "olsr_cfg.h"
00052 #include "interfaces.h"
00053 #include "olsr_protocol.h"
00054 #include "net_olsr.h"
00055 #include "link_set.h"
00056 #include "ipcalc.h"
00057 #include "lq_plugin.h"
00058 #include "olsr_cfg_gen.h"
00059 #include "common/string.h"
00060 #include "olsr_ip_prefix_list.h"
00061 #include "olsr_logging.h"
00062 #include "os_time.h"
00063 #include "os_net.h"
00064
00065 #include <stdio.h>
00066 #include <string.h>
00067 #include <stdlib.h>
00068 #include <unistd.h>
00069 #include <errno.h>
00070 #ifdef WIN32
00071 #include <io.h>
00072 #else
00073 #include <netdb.h>
00074 #endif
00075
00076 #ifdef OS
00077 #undef OS
00078 #endif
00079
00080 #ifdef WIN32
00081 #define OS "Windows"
00082 #endif
00083 #ifdef linux
00084 #define OS "GNU/Linux"
00085 #endif
00086 #ifdef __FreeBSD__
00087 #define OS "FreeBSD"
00088 #endif
00089
00090 #ifndef OS
00091 #define OS "Undefined"
00092 #endif
00093
00094 static char copyright_string[] __attribute__ ((unused)) =
00095 "olsr.org HTTPINFO plugin Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
00096
00097 #define MAX_CLIENTS 3
00098
00099 #define MAX_HTTPREQ_SIZE (1024 * 10)
00100
00101 #define DEFAULT_TCP_PORT 1978
00102
00103 #define HTML_BUFSIZE (1024 * 4000)
00104
00105 #define FRAMEWIDTH (resolve_ip_addresses ? 900 : 800)
00106
00107 #define FILENREQ_MATCH(req, filename) \
00108 !strcmp(req, filename) || \
00109 (strlen(req) && !strcmp(&req[1], filename))
00110
00111 static const char httpinfo_css[] =
00112 "#A{text-decoration:none}\n"
00113 "TH{text-align:left}\n"
00114 "H1,H3,TD,TH{font-family:Helvetica;font-size:80%}\n"
00115 "h2{font-family:Helvetica; font-size:14px;text-align:center;line-height:16px;"
00116 "text-decoration:none;border:1px solid #ccc;margin:5px;background:#ececec;}\n"
00117 "hr{border:none;padding:1px;background:url(grayline.gif) repeat-x bottom;}\n"
00118 "#maintable{margin:0px;padding:5px;border-left:1px solid #ccc;"
00119 "border-right:1px solid #ccc;border-bottom:1px solid #ccc;}\n"
00120 "#footer{font-size:10px;line-height:14px;text-decoration:none;color:#666;}\n"
00121 "#hdr{font-size:14px;text-align:center;line-height:16px;text-decoration:none;"
00122 "border:1px solid #ccc;margin:5px;background:#ececec;}\n"
00123 "#container{width:1000px;padding:30px;border:1px solid #ccc;background:#fff;}\n"
00124 "#tabnav{height:20px;margin:0;padding-left:10px;"
00125 "background:url(grayline.gif) repeat-x bottom;}\n"
00126 "#tabnav li{margin:0;padding:0;display:inline;list-style-type:none;}\n"
00127 "#tabnav a:link,#tabnav a:visited{float:left;background:#ececec;font-size:12px;"
00128 "line-height:14px;font-weight:bold;padding:2px 10px 2px 10px;margin-right:4px;"
00129 "border:1px solid #ccc;text-decoration:none;color:#777;}\n"
00130 "#tabnav a:link.active,#tabnav a:visited.active{border-bottom:1px solid #fff;"
00131 "background:#ffffff;color:#000;}\n"
00132 "#tabnav a:hover{background:#777777;color:#ffffff;}\n"
00133 ".input_text{background:#E5E5E5;margin-left:5px; margin-top:0px;text-align:left;"
00134 "width:100px;padding:0px;color:#000;text-decoration:none;font-family:verdana;"
00135 "font-size:12px;border:1px solid #ccc;}\n"
00136 ".input_button{background:#B5D1EE;margin-left:5px;margin-top:0px;text-align:center;"
00137 "width:120px;padding:0px;color:#000;text-decoration:none;font-family:verdana;" "font-size:12px;border:1px solid #000;}\n";
00138
00139 typedef void (*build_body_callback) (struct autobuf * abuf);
00140
00141 struct tab_entry {
00142 const char *tab_label;
00143 const char *filename;
00144 build_body_callback build_body_cb;
00145 bool display_tab;
00146 };
00147
00148 struct static_bin_file_entry {
00149 const char *filename;
00150 unsigned char *data;
00151 unsigned int data_size;
00152 };
00153
00154 struct static_txt_file_entry {
00155 const char *filename;
00156 const char *data;
00157 };
00158
00159 #if ADMIN_INTERFACE
00160 struct dynamic_file_entry {
00161 const char *filename;
00162 process_data_func process_data_cb;
00163 };
00164 #endif
00165
00166 static int get_http_socket(int);
00167
00168 static void build_tabs(struct autobuf *abuf, int);
00169
00170 static void parse_http_request(int, void *, unsigned int flags);
00171
00172 static void build_http_header(struct autobuf *abuf, http_header_type, bool, uint32_t);
00173
00174 static void build_frame(struct autobuf *abuf, build_body_callback frame_body_cb);
00175
00176 static void build_routes_body(struct autobuf *abuf);
00177
00178 static void build_config_body(struct autobuf *abuf);
00179
00180 static void build_neigh_body(struct autobuf *abuf);
00181
00182 static void build_topo_body(struct autobuf *abuf);
00183
00184 static void build_mid_body(struct autobuf *abuf);
00185
00186 static void build_nodes_body(struct autobuf *abuf);
00187
00188 static void build_all_body(struct autobuf *abuf);
00189
00190 static void build_about_body(struct autobuf *abuf);
00191
00192 static void build_cfgfile_body(struct autobuf *abuf);
00193
00194 static void build_ip_txt(struct autobuf *abuf, const bool want_link, const char *const ipaddrstr, const int prefix_len);
00195
00196 static void build_ipaddr_link(struct autobuf *abuf, const bool want_link,
00197 const union olsr_ip_addr *const ipaddr, const int prefix_len);
00198 static void section_title(struct autobuf *abuf, const char *title);
00199
00200 static ssize_t writen(int fd, const void *buf, size_t count);
00201
00202 static struct timeval start_time;
00203 static struct http_stats stats;
00204 static int client_sockets[MAX_CLIENTS];
00205 static int curr_clients;
00206 static int http_socket;
00207
00208 #if 0
00209 int netsprintf(char *str, const char *format, ...) __attribute__ ((format(printf, 2, 3)));
00210 static int netsprintf_direct = 0;
00211 static int netsprintf_error = 0;
00212 #define sprintf netsprintf
00213 #define NETDIRECT
00214 #endif
00215
00216 static const struct tab_entry tab_entries[] = {
00217 {"Configuration", "config", build_config_body, true},
00218 {"Routes", "routes", build_routes_body, true},
00219 {"Links/Topology", "nodes", build_nodes_body, true},
00220 {"All", "all", build_all_body, true},
00221 #if ADMIN_INTERFACE
00222 {"Admin", "admin", build_admin_body, true},
00223 #endif
00224 {"About", "about", build_about_body, true},
00225 {"FOO", "cfgfile", build_cfgfile_body, false},
00226 {NULL, NULL, NULL, false}
00227 };
00228
00229 static const struct static_bin_file_entry static_bin_files[] = {
00230 {"favicon.ico", favicon_ico, sizeof(favicon_ico)}
00231 ,
00232 {"logo.gif", logo_gif, sizeof(logo_gif)}
00233 ,
00234 {"grayline.gif", grayline_gif, sizeof(grayline_gif)}
00235 ,
00236 {NULL, NULL, 0}
00237 };
00238
00239 static const struct static_txt_file_entry static_txt_files[] = {
00240 {"httpinfo.css", httpinfo_css},
00241 {NULL, NULL}
00242 };
00243
00244
00245 #if ADMIN_INTERFACE
00246 static const struct dynamic_file_entry dynamic_files[] = {
00247 {"set_values", process_set_values},
00248 {NULL, NULL}
00249 };
00250 #endif
00251
00252
00253 static int
00254 get_http_socket(int port)
00255 {
00256 struct sockaddr_storage sst;
00257 uint32_t yes = 1;
00258 socklen_t addrlen;
00259
00260
00261 int s = socket(olsr_cnf->ip_version, SOCK_STREAM, 0);
00262 if (s == -1) {
00263 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO)socket %s\n", strerror(errno));
00264 return -1;
00265 }
00266
00267 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
00268 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO)SO_REUSEADDR failed %s\n", strerror(errno));
00269 os_close(s);
00270 return -1;
00271 }
00272
00273
00274
00275
00276 memset(&sst, 0, sizeof(sst));
00277 if (olsr_cnf->ip_version == AF_INET) {
00278 struct sockaddr_in *addr4 = (struct sockaddr_in *)&sst;
00279 addr4->sin_family = AF_INET;
00280 addrlen = sizeof(*addr4);
00281 #ifdef SIN6_LEN
00282 addr4->sin_len = addrlen;
00283 #endif
00284 addr4->sin_addr.s_addr = INADDR_ANY;
00285 addr4->sin_port = htons(port);
00286 } else {
00287 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&sst;
00288 addr6->sin6_family = AF_INET6;
00289 addrlen = sizeof(*addr6);
00290 #ifdef SIN6_LEN
00291 addr6->sin6_len = addrlen;
00292 #endif
00293 addr6->sin6_addr = in6addr_any;
00294 addr6->sin6_port = htons(port);
00295 }
00296
00297
00298 if (bind(s, (struct sockaddr *)&sst, addrlen) == -1) {
00299 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO) bind failed %s\n", strerror(errno));
00300 os_close(s);
00301 return -1;
00302 }
00303
00304
00305 if (listen(s, 1) == -1) {
00306 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO) listen failed %s\n", strerror(errno));
00307 os_close(s);
00308 return -1;
00309 }
00310
00311 return s;
00312 }
00313
00320 int
00321 olsrd_plugin_init(void)
00322 {
00323
00324 os_gettimeofday(&start_time, NULL);
00325
00326 curr_clients = 0;
00327
00328 http_socket = get_http_socket(http_port != 0 ? http_port : DEFAULT_TCP_PORT);
00329
00330 if (http_socket < 0) {
00331 OLSR_ERROR(LOG_PLUGINS, "(HTTPINFO) could not initialize HTTP socket\n");
00332 olsr_exit(1);
00333 }
00334
00335
00336 if (olsr_cnf->ip_version == AF_INET) {
00337 union olsr_ip_addr ip;
00338
00339 ip.v4.s_addr = ntohl(INADDR_LOOPBACK);
00340 ip_acl_add(&allowed_nets, &ip, 32, false);
00341 } else {
00342 ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_loopback, 128, false);
00343 ip_acl_add(&allowed_nets, (const union olsr_ip_addr *)&in6addr_v4mapped_loopback, 128, false);
00344 }
00345
00346
00347 if (NULL == olsr_socket_add(http_socket, &parse_http_request, NULL, OLSR_SOCKET_READ)) {
00348 OLSR_ERROR(LOG_PLUGINS, "(HTTPINFO) Could not register socket with scheduler\n");
00349 olsr_exit(1);
00350 }
00351
00352 return 1;
00353 }
00354
00355
00356 static void
00357 parse_http_request(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
00358 {
00359 struct sockaddr_storage pin;
00360 socklen_t addrlen;
00361 union olsr_ip_addr *ipaddr;
00362 char req[MAX_HTTPREQ_SIZE];
00363
00364 struct autobuf body, header;
00365 char req_type[11];
00366 char filename[251];
00367 char http_version[11];
00368 unsigned int c = 0;
00369 int r = 1 ;
00370
00371 abuf_init(&body, 0);
00372 abuf_init(&header, 0);
00373
00374 if (curr_clients >= MAX_CLIENTS) {
00375 return;
00376 }
00377 curr_clients++;
00378
00379 addrlen = sizeof(pin);
00380 client_sockets[curr_clients] = accept(fd, (struct sockaddr *)&pin, &addrlen);
00381 if (client_sockets[curr_clients] == -1) {
00382 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO) accept: %s\n", strerror(errno));
00383 goto close_connection;
00384 }
00385
00386 if (((struct sockaddr *)&pin)->sa_family != olsr_cnf->ip_version) {
00387 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO) Connection with wrong IP version?!\n");
00388 goto close_connection;
00389 }
00390
00391 if (olsr_cnf->ip_version == AF_INET) {
00392 struct sockaddr_in *addr4 = (struct sockaddr_in *)&pin;
00393 ipaddr = (union olsr_ip_addr *)&addr4->sin_addr;
00394 } else {
00395 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pin;
00396 ipaddr = (union olsr_ip_addr *)&addr6->sin6_addr;
00397 }
00398
00399 if (!ip_acl_acceptable(&allowed_nets, ipaddr, olsr_cnf->ip_version)) {
00400 #if !defined REMOVE_LOG_WARN
00401 struct ipaddr_str strbuf;
00402 #endif
00403 OLSR_WARN(LOG_PLUGINS, "HTTP request from non-allowed host %s!\n", olsr_ip_to_string(&strbuf, ipaddr));
00404 goto close_connection;
00405 }
00406
00407 memset(req, 0, sizeof(req));
00408
00409
00410 while ((r = recv(client_sockets[curr_clients], &req[c], 1, 0)) > 0 && (c < sizeof(req) - 1)) {
00411 c++;
00412
00413 if ((c > 3 && !strcmp(&req[c - 4], "\r\n\r\n")) || (c > 1 && !strcmp(&req[c - 2], "\n\n")))
00414 break;
00415 }
00416
00417 if (r < 0) {
00418 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO) Failed to recieve data from client!\n");
00419 stats.err_hits++;
00420 goto close_connection;
00421 }
00422
00423
00424 if (sscanf(req, "%10s %250s %10s\n", req_type, filename, http_version) != 3) {
00425
00426 if (sscanf(req, "%10s %250s\n", req_type, filename) != 2) {
00427 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO) Error parsing request %s!\n", req);
00428 stats.err_hits++;
00429 goto close_connection;
00430 }
00431 }
00432
00433 OLSR_DEBUG(LOG_PLUGINS, "Request: %s\nfile: %s\nVersion: %s\n\n", req_type, filename, http_version);
00434
00435 if (!strcmp(req_type, "POST")) {
00436 #if ADMIN_INTERFACE
00437 int i = 0;
00438 while (dynamic_files[i].filename) {
00439 OLSR_DEBUG(LOG_PLUGINS, "POST checking %s\n", dynamic_files[i].filename);
00440 if (FILENREQ_MATCH(filename, dynamic_files[i].filename)) {
00441 uint32_t param_size;
00442
00443 stats.ok_hits++;
00444
00445 param_size = recv(client_sockets[curr_clients], req, sizeof(req) - 1, 0);
00446
00447 req[param_size] = '\0';
00448 OLSR_DEBUG(LOG_PLUGINS, "Dynamic read %d bytes\n", param_size);
00449
00450
00451
00452 dynamic_files[i].process_data_cb(req, param_size, &body);
00453
00454 build_http_header(&header, HTTP_OK, true, body.len);
00455 goto send_http_data;
00456 }
00457 i++;
00458 }
00459 #endif
00460
00461 abuf_puts(&body, HTTP_400_MSG);
00462 stats.ill_hits++;
00463 build_http_header(&header, HTTP_BAD_REQ, true, body.len);
00464 } else if (!strcmp(req_type, "GET")) {
00465 int i = 0;
00466
00467 for (i = 0; static_bin_files[i].filename; i++) {
00468 if (FILENREQ_MATCH(filename, static_bin_files[i].filename)) {
00469 break;
00470 }
00471 }
00472
00473 if (static_bin_files[i].filename) {
00474 stats.ok_hits++;
00475
00476 abuf_memcpy(&body, static_bin_files[i].data, static_bin_files[i].data_size);
00477
00478 build_http_header(&header, HTTP_OK, false, body.len);
00479 goto send_http_data;
00480 }
00481
00482 i = 0;
00483 while (static_txt_files[i].filename) {
00484 if (FILENREQ_MATCH(filename, static_txt_files[i].filename)) {
00485 break;
00486 }
00487 i++;
00488 }
00489
00490 if (static_txt_files[i].filename) {
00491 stats.ok_hits++;
00492
00493
00494 abuf_puts(&body, static_txt_files[i].data);
00495
00496 build_http_header(&header, HTTP_OK, false, body.len);
00497 goto send_http_data;
00498 }
00499
00500 i = 0;
00501 if (strlen(filename) > 1) {
00502 while (tab_entries[i].filename) {
00503 if (FILENREQ_MATCH(filename, tab_entries[i].filename)) {
00504 break;
00505 }
00506 i++;
00507 }
00508 }
00509
00510 if (tab_entries[i].filename) {
00511 #ifdef NETDIRECT
00512 build_http_header(&header, HTTP_OK, true);
00513 r = send(client_sockets[curr_clients], req, c, 0);
00514 if (r < 0) {
00515 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO) Failed sending data to client!\n");
00516 goto close_connection;
00517 }
00518 netsprintf_error = 0;
00519 netsprintf_direct = 1;
00520 #endif
00521 abuf_appendf(&body,
00522 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
00523 "<head>\n"
00524 "<meta http-equiv=\"Content-type\" content=\"text/html; charset=ISO-8859-1\">\n"
00525 "<title>olsr.org httpinfo plugin</title>\n"
00526 "<link rel=\"icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
00527 "<link rel=\"shortcut icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
00528 "<link rel=\"stylesheet\" type=\"text/css\" href=\"httpinfo.css\">\n"
00529 "</head>\n"
00530 "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
00531 "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
00532 "<tbody><tr bgcolor=\"#ffffff\">\n"
00533 "<td height=\"69\" valign=\"middle\" width=\"80%%\">\n"
00534 "<font color=\"black\" face=\"timesroman\" size=\"6\"> <a href=\"http://www.olsr.org/\">olsr.org OLSR daemon</a></font></td>\n"
00535 "<td height=\"69\" valign=\"middle\" width=\"20%%\">\n"
00536 "<a href=\"http://www.olsr.org/\"><img border=\"0\" src=\"/logo.gif\" alt=\"olsrd logo\"></a></td>\n"
00537 "</tr>\n" "</tbody>\n" "</table>\n", FRAMEWIDTH);
00538
00539 build_tabs(&body, i);
00540 build_frame(&body, tab_entries[i].build_body_cb);
00541
00542 stats.ok_hits++;
00543
00544 abuf_appendf(&body,
00545 "</table>\n"
00546 "<div id=\"footer\">\n"
00547 "<center>\n"
00548 "(C)2005 Andreas Tønnesen<br/>\n"
00549 "<a href=\"http://www.olsr.org/\">http://www.olsr.org</a>\n" "</center>\n" "</div>\n" "</body>\n" "</html>\n");
00550
00551 #ifdef NETDIRECT
00552 netsprintf_direct = 1;
00553 goto close_connection;
00554 #else
00555 build_http_header(&header, HTTP_OK, true, body.len);
00556 goto send_http_data;
00557 #endif
00558 }
00559
00560
00561 stats.ill_hits++;
00562 abuf_puts(&body, HTTP_404_MSG);
00563 build_http_header(&header, HTTP_BAD_FILE, true, body.len);
00564 } else {
00565
00566 abuf_puts(&body, HTTP_400_MSG);
00567 stats.ill_hits++;
00568 build_http_header(&header, HTTP_BAD_REQ, true, body.len);
00569 }
00570
00571 send_http_data:
00572
00573 r = writen(client_sockets[curr_clients], header.buf, header.len);
00574 if (r < 0) {
00575 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO) Failed sending data to client!\n");
00576 goto close_connection;
00577 }
00578
00579 r = writen(client_sockets[curr_clients], body.buf, body.len);
00580 if (r < 0) {
00581 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO) Failed sending data to client!\n");
00582 goto close_connection;
00583 }
00584
00585 close_connection:
00586 abuf_free(&body);
00587 abuf_free(&header);
00588 os_close(client_sockets[curr_clients]);
00589 curr_clients--;
00590 }
00591
00592
00593 void
00594 build_http_header(struct autobuf *abuf, http_header_type type, bool is_html, uint32_t msgsize)
00595 {
00596 time_t currtime;
00597 const char *h;
00598
00599 switch (type) {
00600 case HTTP_BAD_REQ:
00601 h = HTTP_400;
00602 break;
00603 case HTTP_BAD_FILE:
00604 h = HTTP_404;
00605 break;
00606 default:
00607
00608 h = HTTP_200;
00609 break;
00610 }
00611 abuf_puts(abuf, h);
00612
00613
00614 time(&currtime);
00615 abuf_strftime(abuf, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
00616
00617
00618 abuf_appendf(abuf, "Server: %s %s %s\r\n", PLUGIN_NAME, PLUGIN_VERSION, HTTP_VERSION);
00619
00620
00621 abuf_puts(abuf, "Connection: closed\r\n");
00622
00623
00624 abuf_appendf(abuf, "Content-type: text/%s\r\n", is_html ? "html" : "plain");
00625
00626
00627 if (msgsize > 0) {
00628 abuf_appendf(abuf, "Content-length: %u\r\n", msgsize);
00629 }
00630
00631
00632
00633
00634 abuf_puts(abuf, "Cache-Control: no-cache\r\n");
00635
00636 if (!is_html) {
00637 abuf_puts(abuf, "Accept-Ranges: bytes\r\n");
00638 }
00639
00640 abuf_puts(abuf, "\r\n");
00641
00642 OLSR_DEBUG(LOG_PLUGINS, "HEADER:\n%s", abuf->buf);
00643 }
00644
00645
00646 static void
00647 build_tabs(struct autobuf *abuf, int active)
00648 {
00649 int tabs;
00650
00651 abuf_appendf(abuf,
00652 "<table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
00653 "<tr bgcolor=\"#ffffff\"><td>\n" "<ul id=\"tabnav\">\n", FRAMEWIDTH);
00654 for (tabs = 0; tab_entries[tabs].tab_label; tabs++) {
00655 if (!tab_entries[tabs].display_tab) {
00656 continue;
00657 }
00658 abuf_appendf(abuf,
00659 "<li><a href=\"%s\"%s>%s</a></li>\n",
00660 tab_entries[tabs].filename, tabs == active ? " class=\"active\"" : "", tab_entries[tabs].tab_label);
00661 }
00662 abuf_appendf(abuf, "</ul>\n" "</td></tr>\n" "<tr><td>\n");
00663 }
00664
00665
00666
00667
00668
00669 void
00670 olsr_plugin_exit(void)
00671 {
00672 ip_acl_flush(&allowed_nets);
00673
00674 if (http_socket >= 0) {
00675 os_close(http_socket);
00676 }
00677 }
00678
00679
00680 static void
00681 section_title(struct autobuf *abuf, const char *title)
00682 {
00683 abuf_appendf(abuf,
00684 "<h2>%s</h2>\n"
00685 "<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n", title);
00686 }
00687
00688 static void
00689 build_frame(struct autobuf *abuf, build_body_callback frame_body_cb)
00690 {
00691 abuf_puts(abuf, "<div id=\"maintable\">\n");
00692 frame_body_cb(abuf);
00693 abuf_puts(abuf, "</div>\n");
00694 }
00695
00696 static void
00697 fmt_href(struct autobuf *abuf, const char *const ipaddr)
00698 {
00699 abuf_appendf(abuf, "<a href=\"http://%s:%d/all\">", ipaddr, http_port);
00700 }
00701
00702 static void
00703 build_ip_txt(struct autobuf *abuf, const bool print_link, const char *const ipaddrstr, const int prefix_len)
00704 {
00705 if (print_link) {
00706 fmt_href(abuf, ipaddrstr);
00707 }
00708
00709 abuf_puts(abuf, ipaddrstr);
00710
00711 if (prefix_len != -1 && prefix_len != 8 * (int)olsr_cnf->ipsize) {
00712 abuf_appendf(abuf, "/%d", prefix_len);
00713 }
00714
00715 if (print_link) {
00716 abuf_puts(abuf, "</a>");
00717 }
00718 }
00719
00720 static void
00721 build_ipaddr_link(struct autobuf *abuf, const bool want_link, const union olsr_ip_addr *const ipaddr, const int prefix_len)
00722 {
00723 struct ipaddr_str ipaddrstr;
00724 const struct hostent *const hp =
00725 #ifndef WIN32
00726 resolve_ip_addresses ? gethostbyaddr(ipaddr, olsr_cnf->ipsize, olsr_cnf->ip_version) :
00727 #endif
00728 NULL;
00729
00730 const int print_link = want_link && (prefix_len == -1 || prefix_len == 8 * (int)olsr_cnf->ipsize);
00731 olsr_ip_to_string(&ipaddrstr, ipaddr);
00732
00733 abuf_puts(abuf, "<td>");
00734 build_ip_txt(abuf, print_link, ipaddrstr.buf, prefix_len);
00735 abuf_puts(abuf, "</td>");
00736
00737 if (resolve_ip_addresses) {
00738 if (hp) {
00739 abuf_puts(abuf, "<td>(");
00740 if (print_link) {
00741 fmt_href(abuf, ipaddrstr.buf);
00742 }
00743 abuf_puts(abuf, hp->h_name);
00744 if (print_link) {
00745 abuf_puts(abuf, "</a>");
00746 }
00747 abuf_puts(abuf, ")</td>");
00748 } else {
00749 abuf_puts(abuf, "<td/>");
00750 }
00751 }
00752 }
00753
00754 #define build_ipaddr_with_link(abuf, ipaddr, plen) \
00755 build_ipaddr_link((abuf), true, (ipaddr), (plen))
00756 #define build_ipaddr_no_link(abuf, ipaddr, plen) \
00757 build_ipaddr_link((abuf), false, (ipaddr), (plen))
00758
00759 static void
00760 build_route(struct autobuf *abuf, const struct rt_entry *rt)
00761 {
00762 char lqbuffer[LQTEXT_MAXLENGTH];
00763
00764 abuf_puts(abuf, "<tr>");
00765 build_ipaddr_with_link(abuf, &rt->rt_dst.prefix, rt->rt_dst.prefix_len);
00766 build_ipaddr_with_link(abuf, &rt->rt_best->rtp_nexthop.gateway, -1);
00767
00768 abuf_appendf(abuf, "<td>%u</td>", rt->rt_best->rtp_metric.hops);
00769 abuf_appendf(abuf, "<td>%s</td>", olsr_get_linkcost_text(rt->rt_best->rtp_metric.cost, true, lqbuffer, sizeof(lqbuffer)));
00770 abuf_appendf(abuf,
00771 "<td>%s</td></tr>\n", rt->rt_best->rtp_nexthop.interface ? rt->rt_best->rtp_nexthop.interface->int_name : "[null]");
00772 }
00773
00774 static void
00775 build_routes_body(struct autobuf *abuf)
00776 {
00777 struct rt_entry *rt, *iterator;
00778
00779 const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
00780 section_title(abuf, "OLSR Routes in Kernel");
00781 abuf_appendf(abuf,
00782 "<tr><th%s>Destination</th><th%s>Gateway</th><th>Metric</th><th>ETX</th><th>Interface</th></tr>\n",
00783 colspan, colspan);
00784
00785
00786 OLSR_FOR_ALL_RT_ENTRIES(rt, iterator) {
00787 build_route(abuf, rt);
00788 }
00789
00790 abuf_puts(abuf, "</table>\n");
00791 }
00792
00793 static void
00794 build_config_body(struct autobuf *abuf)
00795 {
00796 const struct olsr_if_config *ifs;
00797 const struct plugin_entry *pentry;
00798 const struct plugin_param *pparam;
00799 struct ipaddr_str mainaddrbuf;
00800 struct millitxt_buf tbuf;
00801
00802 abuf_appendf(abuf, "Version: %s (built on %s on %s)\n<br>OS: %s\n<br>", olsrd_version, build_date, build_host, OS);
00803 {
00804 const time_t currtime = time(NULL);
00805 abuf_strftime(abuf, "System time: <em>%a, %d %b %Y %H:%M:%S</em><br>", localtime(&currtime));
00806 }
00807
00808 {
00809 struct timeval now, uptime;
00810 int hours, mins, days;
00811 os_gettimeofday(&now, NULL);
00812 timersub(&now, &start_time, &uptime);
00813
00814 days = uptime.tv_sec / 86400;
00815 uptime.tv_sec %= 86400;
00816 hours = uptime.tv_sec / 3600;
00817 uptime.tv_sec %= 3600;
00818 mins = uptime.tv_sec / 60;
00819 uptime.tv_sec %= 60;
00820
00821 abuf_puts(abuf, "Olsrd uptime: <em>");
00822 if (days) {
00823 abuf_appendf(abuf, "%d day(s) ", days);
00824 }
00825 abuf_appendf(abuf, "%02d hours %02d minutes %02d seconds</em><br/>\n", hours, mins, (int)uptime.tv_sec);
00826 }
00827
00828 abuf_appendf(abuf, "HTTP stats(ok/dyn/error/illegal): <em>%u/%u/%u/%u</em><br>\n", stats.ok_hits, stats.dyn_hits, stats.err_hits,
00829 stats.ill_hits);
00830
00831 abuf_appendf(abuf, "Click <a href=\"/cfgfile\">here</a> to <em>generate a configuration file for this node</em>.\n");
00832
00833 abuf_puts(abuf, "<h2>Variables</h2>\n");
00834
00835 abuf_puts(abuf, "<table width=\"100%%\" border=\"0\">\n<tr>");
00836
00837 abuf_appendf(abuf, "<td>Main address: <strong>%s</strong></td>\n", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->router_id));
00838 abuf_appendf(abuf, "<td>IP version: %d</td>\n", olsr_cnf->ip_version == AF_INET ? 4 : 6);
00839
00840
00841 abuf_appendf(abuf, "<td></td>\n");
00842 abuf_appendf(abuf, "<td>FIB Metrics: %s</td>\n",
00843 FIBM_FLAT == olsr_cnf->fib_metric ? CFG_FIBM_FLAT : FIBM_CORRECT ==
00844 olsr_cnf->fib_metric ? CFG_FIBM_CORRECT : CFG_FIBM_APPROX);
00845
00846 abuf_puts(abuf, "</tr>\n<tr>\n");
00847
00848 abuf_appendf(abuf, "<td>Pollrate: %s</td>\n", olsr_clock_to_string(&tbuf, olsr_cnf->pollrate));
00849 abuf_appendf(abuf, "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
00850 abuf_appendf(abuf, "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
00851 abuf_appendf(abuf, "<td>NAT threshold: %s</td>\n", olsr_clock_to_string(&tbuf, olsr_cnf->lq_nat_thresh));
00852
00853 abuf_puts(abuf, "</tr>\n<tr>\n");
00854
00855 abuf_appendf(abuf, "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
00856 abuf_appendf(abuf, "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
00857 abuf_appendf(abuf, "<td>RtTable: 0x%04x/%d</td>\n", olsr_cnf->rt_table, olsr_cnf->rt_table);
00858 abuf_appendf(abuf, "<td>RtTableDefault: 0x%04x/%d</td>\n", olsr_cnf->rt_table_default, olsr_cnf->rt_table_default);
00859 abuf_appendf(abuf, "<td>Willingness: %d %s</td>\n", olsr_cnf->willingness, olsr_cnf->willingness_auto ? "(auto)" : "");
00860
00861 abuf_puts(abuf, "</tr></table>\n");
00862
00863 abuf_puts(abuf, "<h2>Interfaces</h2>\n");
00864 abuf_puts(abuf, "<table width=\"100%%\" border=\"0\">\n");
00865 for (ifs = olsr_cnf->if_configs; ifs != NULL; ifs = ifs->next) {
00866 const struct interface *const rifs = ifs->interf;
00867 struct ipaddr_str addrbuf, bcastbuf;
00868
00869 abuf_appendf(abuf, "<tr><th colspan=\"3\">%s</th>\n", ifs->name);
00870 if (!rifs) {
00871 abuf_puts(abuf, "<tr><td colspan=\"3\">Status: DOWN</td></tr>\n");
00872 continue;
00873 }
00874
00875 abuf_appendf(abuf,
00876 "<tr>\n"
00877 "<td>IP: %s</td>\n"
00878 "<td>MCAST: %s</td>\n"
00879 "<td></td>"
00880 "</tr>\n",
00881 olsr_sockaddr_to_string(&addrbuf, &rifs->int_src),
00882 olsr_sockaddr_to_string(&bcastbuf, &rifs->int_multicast));
00883 abuf_appendf(abuf,
00884 "<tr>\n"
00885 "<td>MTU: %d</td>\n"
00886 "<td>STATUS: UP</td>\n" "</tr>\n", rifs->int_mtu);
00887 }
00888 abuf_puts(abuf, "</table>\n");
00889
00890 abuf_appendf(abuf,
00891 "<em>Olsrd is configured to %s if no interfaces are available</em><br>\n",
00892 olsr_cnf->allow_no_interfaces ? "run even" : "halt");
00893
00894 abuf_puts(abuf, "<h2>Plugins</h2>\n");
00895 abuf_puts(abuf, "<table width=\"100%%\" border=\"0\"><tr><th>Name</th><th>Parameters</th></tr>\n");
00896 for (pentry = olsr_cnf->plugins; pentry; pentry = pentry->next) {
00897 abuf_appendf(abuf, "<tr><td>%s</td>\n" "<td><select>\n" "<option>KEY, VALUE</option>\n", pentry->name);
00898
00899 for (pparam = pentry->params; pparam; pparam = pparam->next) {
00900 abuf_appendf(abuf, "<option>\"%s\", \"%s\"</option>\n", pparam->key, pparam->value);
00901 }
00902 abuf_puts(abuf, "</select></td></tr>\n");
00903
00904 }
00905 abuf_puts(abuf, "</table>\n");
00906
00907 section_title(abuf, "Announced HNA entries");
00908 if (list_is_empty(&olsr_cnf->hna_entries)) {
00909 struct ip_prefix_entry *hna, *iterator;
00910
00911 abuf_puts(abuf, "<tr><th>Network</th></tr>\n");
00912 OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, hna, iterator) {
00913 struct ipprefix_str netbuf;
00914 abuf_appendf(abuf, "<tr><td>%s</td></tr>\n", olsr_ip_prefix_to_string(&netbuf, &hna->net));
00915 }
00916 } else {
00917 abuf_puts(abuf, "<tr><td></td></tr>\n");
00918 }
00919 abuf_puts(abuf, "</table>\n");
00920 }
00921
00922 static void
00923 build_neigh_body(struct autobuf *abuf)
00924 {
00925 struct nbr_entry *neigh, *neigh_iterator;
00926 struct link_entry *lnk, *lnk_iterator;
00927 size_t i;
00928 const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
00929
00930 section_title(abuf, "Links");
00931
00932 abuf_appendf(abuf, "<tr><th%s>Local IP</th><th%s>Remote IP</th>", colspan, colspan);
00933 for (i=1; i<olsr_get_linklabel_count(); i++) {
00934 abuf_appendf(abuf, "<th>%s</th>", olsr_get_linklabel(i));
00935 }
00936 abuf_puts(abuf, "<th>LinkCost</th>");
00937 abuf_puts(abuf, "</tr>\n");
00938
00939
00940 OLSR_FOR_ALL_LINK_ENTRIES(lnk, lnk_iterator) {
00941 char lqbuffer[LQTEXT_MAXLENGTH];
00942 abuf_puts(abuf, "<tr>");
00943 build_ipaddr_with_link(abuf, &lnk->local_iface_addr, -1);
00944 build_ipaddr_with_link(abuf, &lnk->neighbor_iface_addr, -1);
00945
00946 for (i=1; i<olsr_get_linklabel_count(); i++) {
00947 abuf_appendf(abuf, "<td>%s</td>", olsr_get_linkdata_text(lnk, i, lqbuffer, sizeof(lqbuffer)));
00948 }
00949 abuf_appendf(abuf, "<td>%s</td>", olsr_get_linkcost_text(lnk->linkcost, false, lqbuffer, sizeof(lqbuffer)));
00950 abuf_puts(abuf, "</tr>\n");
00951 }
00952
00953 abuf_puts(abuf, "</table>\n");
00954
00955 section_title(abuf, "Neighbors");
00956 abuf_appendf(abuf,
00957 "<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",
00958 colspan);
00959
00960 OLSR_FOR_ALL_NBR_ENTRIES(neigh, neigh_iterator) {
00961 struct nbr_con *connector, *con_iterator;
00962 int thop_cnt;
00963 abuf_puts(abuf, "<tr>");
00964 build_ipaddr_with_link(abuf, &neigh->nbr_addr, -1);
00965 abuf_appendf(abuf,
00966 "<td>%s</td>"
00967 "<td>%s</td>"
00968 "<td>%s</td>"
00969 "<td>%d</td>",
00970 neigh->is_sym ? "YES" : "NO",
00971 neigh->is_mpr ? "YES" : "NO",
00972 neigh->mprs_count > 0 ? "YES" : "NO",
00973 neigh->willingness);
00974
00975 abuf_puts(abuf, "<td><select>\n" "<option>IP ADDRESS</option>\n");
00976
00977 thop_cnt = 0;
00978 OLSR_FOR_ALL_NBR_CON_ENTRIES(neigh, connector, con_iterator) {
00979 struct ipaddr_str strbuf;
00980 abuf_appendf(abuf, "<option>%s</option>\n", olsr_ip_to_string(&strbuf, &connector->nbr2->nbr2_addr));
00981 thop_cnt++;
00982 }
00983 abuf_appendf(abuf, "</select> (%d)</td></tr>\n", thop_cnt);
00984 }
00985
00986 abuf_puts(abuf, "</table>\n");
00987 }
00988
00989 static void
00990 build_topo_body(struct autobuf *abuf)
00991 {
00992 struct tc_entry *tc, *tc_iterator;
00993 const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
00994
00995 section_title(abuf, "Topology Entries");
00996 abuf_appendf(abuf, "<tr><th%s>Destination IP</th><th%s>Last Hop IP</th>", colspan, colspan);
00997 abuf_puts(abuf, "<th colspan=\"3\">Linkcost</th>");
00998 abuf_puts(abuf, "</tr>\n");
00999
01000 OLSR_FOR_ALL_TC_ENTRIES(tc, tc_iterator) {
01001 struct tc_edge_entry *tc_edge, *edge_iterator;
01002 OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge, edge_iterator) {
01003 if (tc_edge->edge_inv) {
01004 char lqbuffer[LQTEXT_MAXLENGTH];
01005 abuf_puts(abuf, "<tr>");
01006 build_ipaddr_with_link(abuf, &tc_edge->T_dest_addr, -1);
01007 build_ipaddr_with_link(abuf, &tc->addr, -1);
01008 abuf_appendf(abuf, "<td colspan=\"3\">%s</td>\n",
01009 olsr_get_linkcost_text(tc_edge->cost, false, lqbuffer, sizeof(lqbuffer)));
01010 abuf_puts(abuf, "</tr>\n");
01011 }
01012 }
01013 }
01014
01015 abuf_puts(abuf, "</table>\n");
01016 }
01017
01018 static void
01019 build_mid_body(struct autobuf *abuf)
01020 {
01021 struct tc_entry *tc, *tc_iterator;
01022 const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
01023
01024 section_title(abuf, "MID Entries");
01025 abuf_appendf(abuf, "<tr><th%s>Main Address</th><th>Aliases</th></tr>\n", colspan);
01026
01027
01028 OLSR_FOR_ALL_TC_ENTRIES(tc, tc_iterator) {
01029 struct mid_entry *alias, *alias_iterator;
01030 abuf_puts(abuf, "<tr>");
01031 build_ipaddr_with_link(abuf, &tc->addr, -1);
01032 abuf_puts(abuf, "<td><select>\n<option>IP ADDRESS</option>\n");
01033
01034 OLSR_FOR_ALL_TC_MID_ENTRIES(tc, alias, alias_iterator) {
01035 struct ipaddr_str strbuf;
01036 abuf_appendf(abuf, "<option>%s</option>\n", olsr_ip_to_string(&strbuf, &alias->mid_alias_addr));
01037 }
01038 abuf_appendf(abuf, "</select> (%u)</td></tr>\n", tc->mid_tree.count);
01039 }
01040
01041 abuf_puts(abuf, "</table>\n");
01042 }
01043
01044
01045 static void
01046 build_nodes_body(struct autobuf *abuf)
01047 {
01048 build_neigh_body(abuf);
01049 build_topo_body(abuf);
01050 build_mid_body(abuf);
01051 }
01052
01053 static void
01054 build_all_body(struct autobuf *abuf)
01055 {
01056 build_config_body(abuf);
01057 build_routes_body(abuf);
01058 build_nodes_body(abuf);
01059 }
01060
01061
01062 static void
01063 build_about_body(struct autobuf *abuf)
01064 {
01065 abuf_appendf(abuf,
01066 "<strong>" PLUGIN_NAME " version " PLUGIN_VERSION "</strong><br/>\n"
01067 "by Andreas Tønnesen (C)2005.<br/>\n" "Compiled "
01068 #if ADMIN_INTERFACE
01069 "<em>with experimental admin interface</em> "
01070 #endif
01071 "%s at %s<hr/>\n"
01072 "This plugin implements a HTTP server that supplies\n"
01073 "the client with various dynamic web pages representing\n"
01074 "the current olsrd status.<br/>The different pages include:\n"
01075 "<ul>\n<li><strong>Configuration</strong> - This page displays information\n"
01076 "about the current olsrd configuration. This includes various\n"
01077 "olsr settings such as IP version, MID/TC redundancy, hysteresis\n"
01078 "etc. Information about the current status of the interfaces on\n"
01079 "which olsrd is configured to run is also displayed. Loaded olsrd\n"
01080 "plugins are shown with their plugin parameters. Finally all local\n"
01081 "HNA entries are shown. These are the networks that the local host\n"
01082 "will anounce itself as a gateway to.</li>\n"
01083 "<li><strong>Routes</strong> - This page displays all routes currently set in\n"
01084 "the kernel <em>by olsrd</em>. The type of route is also displayed(host\n"
01085 "or HNA).</li>\n"
01086 "<li><strong>Links/Topology</strong> - This page displays all information about\n"
01087 "links, neighbors, topology, MID and HNA entries.</li>\n"
01088 "<li><strong>All</strong> - Here all the previous pages are displayed as one.\n"
01089 "This is to make all information available as easy as possible(for example\n"
01090 "for a script) and using as few resources as possible.</li>\n"
01091 #if ADMIN_INTERFACE
01092 "<li><strong>Admin</strong> - This page is highly experimental(and unsecure)!\n"
01093 "As of now it is not working at all but it provides a impression of\n"
01094 "the future possibilities of httpinfo. This is to be a interface to\n"
01095 "changing olsrd settings in realtime. These settings include various\n"
01096 "\"basic\" settings and local HNA settings.</li>\n"
01097 #endif
01098 "<li><strong>About</strong> - this help page.</li>\n</ul>"
01099 "<hr/>\n"
01100 "Send questions or comments to\n"
01101 "<a href=\"mailto:olsr-users@olsr.org\">olsr-users@olsr.org</a> or\n"
01102 "<a href=\"mailto:andreto-at-olsr.org\">andreto-at-olsr.org</a><br/>\n"
01103 "Official olsrd homepage: <a href=\"http://www.olsr.org/\">http://www.olsr.org</a><br/>\n", build_date, build_host);
01104 }
01105
01106 static void
01107 build_cfgfile_body(struct autobuf *abuf)
01108 {
01109 abuf_puts(abuf,
01110 "\n\n"
01111 "<strong>This is an automatically generated configuration\n"
01112 "file based on the current olsrd configuration of this node.</strong><br/>\n" "<hr/>\n" "<pre>\n");
01113
01114 #ifdef NETDIRECT
01115 {
01116
01117
01118
01119 char tmpBuf[10000];
01120 size = olsr_write_cnf_buf(olsr_cnf, true, tmpBuf, 10000);
01121 snprintf(&buf[size], bufsize - size, tmpBuf);
01122 }
01123 #else
01124 olsr_write_cnf_buf(abuf, olsr_cnf, true);
01125 #endif
01126
01127 abuf_puts(abuf, "</pre>\n<hr/>\n");
01128 }
01129
01130 #if 0
01131
01132
01133
01134
01135
01136
01137
01138
01139 int
01140 netsprintf(char *str, const char *format, ...)
01141 {
01142 va_list arg;
01143 int rv;
01144 va_start(arg, format);
01145 rv = vsprintf(str, format, arg);
01146 va_end(arg);
01147 if (0 != netsprintf_direct) {
01148 if (0 == netsprintf_error) {
01149 if (0 > send(client_sockets[curr_clients], str, rv, 0)) {
01150 OLSR_WARN(LOG_PLUGINS, "(HTTPINFO) Failed sending data to client!\n");
01151 netsprintf_error = 1;
01152 }
01153 }
01154 return 0;
01155 }
01156 return rv;
01157 }
01158 #endif
01159
01160 static ssize_t
01161 writen(int fd, const void *buf, size_t count)
01162 {
01163 size_t bytes_left = count;
01164 const char *p = buf;
01165 while (bytes_left > 0) {
01166 const ssize_t written = write(fd, p, bytes_left);
01167 if (written == -1) {
01168 if (errno == EINTR) {
01169 continue;
01170 }
01171 return -1;
01172 }
01173
01174 bytes_left -= written;
01175 p += written;
01176 }
01177 return count;
01178 }
01179
01180
01181
01182
01183
01184
01185