📄 ctrlcomm.cc
字号:
/*!\file CtrlComm.cc Copyright 2003-2004 Fraunhofer Institute for Open Communication Systems (FOKUS), Berlin, Germany This file is part of Network Measurement and Accounting System (NETMATE). NETMATE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. NETMATE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this software; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USADescription:meter control interface$Id: CtrlComm.cc,v 1.1.1.1 2004/12/23 05:52:34 s_zander Exp $*/#include "Error.h"#include "Logger.h"#include "PerfTimer.h"#include "CtrlComm.h"#include "Meter.h"#include "Rule.h"#include "constants.h"CtrlComm *CtrlComm::s_instance = NULL;/* ------------------------- CtrlComm ------------------------- */CtrlComm::CtrlComm(ConfigManager *cnf, int threaded) : MeterComponent(cnf, "CtrlComm",threaded), portnum(0), flags(0){ int ret;#ifdef DEBUG log->dlog(ch, "Starting" );#endif portnum = DEF_PORT; // get port number from config manager if available string txt = cnf->getValue("ControlPort", "CONTROL"); if (txt != "") { portnum = atoi(txt.c_str()); } if (portnum <= 1024 || portnum > 65536) { throw Error("CtrlComm: illegal port number %d " "(must be 1023<x<65535)", portnum ); } log->log(ch, "listening on port number %d.", portnum); // set this *before* trying to start httpd s_instance = this; // register callback functions httpd_register_access_check (s_access_check); httpd_register_log_request (s_log_request); httpd_register_log_error (s_log_error); httpd_register_parse_request(s_parse_request); // init server#ifdef USE_SSL ret = httpd_init(portnum, "netmate", cnf->isTrue("UseSSL", "CONTROL"), CERT_FILE.c_str(), SSL_PASSWD, cnf->isTrue("UseIPv6", "CONTROL"));#else ret = httpd_init(portnum, "netmate", 0, NULL, NULL, cnf->isTrue("UseIPv6", "CONTROL"));#endif if (ret < 0) { throw Error("CtrlComm: cannot init communication facilities" ); } addFd(ret); // adds to accessList in CtrlComm all IP addr for hosts known by DNS checkHosts( cnf->getAccessList(), cnf->isTrue("UseIPv6", "CONTROL") ); if (cnf->isTrue("LogOnConnect", "CONTROL")) { flags |= LOG_CONNECT; } if (cnf->isTrue("LogMeterCommand", "CONTROL")) { flags |= LOG_COMMAND; } // load html/xsl files pcache.addPageFile("/", MAIN_PAGE_FILE ); pcache.addPageFile("/help", MAIN_PAGE_FILE ); pcache.addPageFile("/xsl/reply.xsl", XSL_PAGE_FILE ); // load reply template string line; ifstream in(REPLY_TEMPLATE.c_str()); if (!in) { throw Error("cannot access/read file '%s'", REPLY_TEMPLATE.c_str()); } while (getline(in, line)) { rtemplate += line; rtemplate += "\n"; }}/* ------------------------- ~CtrlComm ------------------------- */CtrlComm::~CtrlComm(){#ifdef DEBUG log->dlog(ch, "Shutdown" );#endif httpd_shutdown();}/* -------------------- accessCheck -------------------- */// this function is called either with host!=NULL OR user!=NULLint CtrlComm::accessCheck(char *host, char *user){ // FIXME ugly structure - both, hosts and users stored in one access list member#ifdef DEBUG if (host != NULL) { cerr << "checking access permission for host " << host << endl; } else if (user != NULL) { cerr << "checking access permission for user " << user << endl; }#endif configADListIter_t iter; // host check if (host != NULL) { for (iter = accessList.begin(); iter != accessList.end(); iter++) { if ((iter->type == "Host") && ((iter->value == "All") || (!strcmp(iter->resolve_addr.c_str(), host)))) { return ((iter->ad == ALLOW) ? 0 : -1); } } } // user check // FIXME no encrypted password support yet! if (user != NULL) { for (iter = accessList.begin(); iter != accessList.end(); iter++) { if ((iter->type == "User") && ((iter->value == "All") || (!strncmp(iter->value.c_str(), user, strlen(iter->value.c_str()))))) { return ((iter->ad == ALLOW) ? 0 : -1); } } } return -1; // no match found -> DENY}/* -------------------- checkHosts -------------------- */void CtrlComm::checkHosts( configADList_t &list, bool useIPv6 ){ int rc; configADItem_t entry; configADListIter_t iter; struct addrinfo ask, *tmp, *res = NULL; sethostent(1); memset(&ask,0,sizeof(ask)); ask.ai_socktype = SOCK_STREAM; ask.ai_flags = 0; for (iter = list.begin(); iter != list.end(); iter++) { if (iter->type == "Host") { if (iter->value == "All") { // always copy if host name == 'All' accessList.push_back(*iter); } else { // set timeout g_timeout = 0; alarm(2); // if hostname = 'localhost' valgrind reports // an uninitialized value error rc = getaddrinfo((iter->value).c_str(), NULL, &ask, &res); alarm(0); if (g_timeout) { freeaddrinfo(res); throw Error("check hosts on access list: DNS timeout"); } if (rc == 0) { configADItem_t entry = *iter; char host[65]; bool isIPv4addr; tmp = res; while(tmp) { if (getnameinfo(tmp->ai_addr, tmp->ai_addrlen, host, 64, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV) < 0) { freeaddrinfo(res); throw Error("getnameinfo"); } isIPv4addr = strchr(host, '.') && !strchr(host, ':'); // check every cobination of isIPv4addr (false/true) and useIPv6 (false/true) if (!useIPv6) { if (isIPv4addr) { // isv4addr && usev4listen entry.resolve_addr = host; accessList.push_back(entry); } else { // isv6addr && usev4listen log->wlog(ch, "ignoring allowed host with IPv6 address '%s' (only" " listening to IPv4 control connects)", host); } } else { if (isIPv4addr) { // isv4addr && usev6listen // add v4 address also in case that host has no v6 address (v4 fallback) entry.resolve_addr = host; accessList.push_back(entry);#ifdef DEBUG if (!entry.resolve_addr.empty()) { cerr << "adding allowed control host '" << entry.resolve_addr << "' to access list." << endl; }#endif // add IPv4 in IPv6 encapsulated address for access list entry.resolve_addr = string("::ffff:") + host; accessList.push_back(entry); } else { // isv6addr && usev6listen entry.resolve_addr = host; accessList.push_back(entry); } }#ifdef DEBUG if (!entry.resolve_addr.empty()) { cerr << "adding allowed control host '" << entry.resolve_addr << "' to access list." << endl; }#endif tmp = tmp->ai_next; } } else { log->wlog(ch, "removing unknown host '%s' from access list", (iter->value).c_str() ); } if (res != NULL) { freeaddrinfo(res); res = NULL; } } } else if (iter->type == "User") { // copy all 'User' items in list to accessList accessList.push_back(*iter); } else { // ignore all 'non-Host && non-User' items in list } }#ifdef DEBUG2 cerr << accessList;#endif endhostent();}/* -------------------- sendMsg -------------------- */string CtrlComm::xmlQuote(string s){ string res; for( string::iterator i = s.begin(); i != s.end(); i++ ) { switch (*i) { case '<': res.append( "<" ); break; case '>': res.append( ">" ); break; case '&': res.append( "&" ); break; /* case '\n': res.append( "<br/>" ); break; */ default: res.push_back(*i); } } return res;}void CtrlComm::sendMsg(string msg, struct REQUEST *req, fd_sets_t *fds, int quote){ string rep = rtemplate; rep.replace(rep.find("@STATUS@"), strlen("@STATUS@"), "OK"); rep.replace(rep.find("@MESSAGE@"), strlen("@MESSAGE@"), (quote) ? xmlQuote(msg) : msg);#ifdef DEBUG2 cerr << rep;#endif req->body = strdup(rep.c_str()); req->mime = "text/xml"; httpd_send_response(req, fds);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -