IpfixReceiverDtlsSctpIpV4(int port, const std::string ipAddr = "",
	    const std::string &certificateChainFile = "", const std::string &privateKeyFile = "",
	    const std::string &caFile = "", const std::string &caPath = "",
	    const std::set<string> &peerFqdns = std::set<string>(), const uint32_t buffer = 0) {
	    THROWEXCEPTION("DTLS over SCTP not supported!");
	}
Esempio n. 2
0
IDSLoadbalancerCfg::IDSLoadbalancerCfg(XMLElement* elem)
	: CfgHelper<IDSLoadbalancer, IDSLoadbalancerCfg>(elem, "IDSLoadbalancer"),
	selector(NULL),
	updateInterval(0)
{
	if (!elem) return;

	XMLNode::XMLSet<XMLElement*> set = elem->getElementChildren();
	for (XMLNode::XMLSet<XMLElement*>::iterator it = set.begin(); it != set.end(); it++) {
		XMLElement* e = *it;

		if (e->matches("updateinterval")) {
			updateInterval = getInt("updateinterval", 0, e);
		} else if (e->matches("PacketSelector")) {
			XMLAttribute *a = e->getAttribute("type");
			if (!a)
				THROWEXCEPTION("no PacketSelector specified");
			string _selector = a->getValue();

			if (_selector == "HashPacketSelector") {
				if (!selector) {
					selector = new HashPacketSelector();
				} else
					THROWEXCEPTION("IDSLoadBalancerCfg: multiple packet selectors specified! This is not allowed.");
			} else if (_selector == "IpPacketSelector") {
				msg(MSG_DEBUG, "IpPacketSelector");
				XMLNode::XMLSet<XMLElement*> set = e->getElementChildren();
				for (XMLNode::XMLSet<XMLElement*>::iterator it = set.begin(); it != set.end(); it++) {
					XMLElement* e = *it;
					if (e->matches("DestinationIp")){
						XMLAttribute *a = e->getAttribute("queueno");
						if (!a)
							THROWEXCEPTION("No queue number specified");
						int queueno = 0;
						std::string tmp = a->getValue();
						try {
							queueno = boost::lexical_cast<int>(tmp);
						}catch (boost::bad_lexical_cast &){
							THROWEXCEPTION("bad value for queue number: %s", tmp.c_str());
						}
						std::string ip = e->getFirstText();
						dst[parseIp(ip)] = queueno;
					}else if (e->matches("SourceIp")){
						XMLElement* e = *it;
						XMLAttribute *a = e->getAttribute("queueno");
						if (!a)
							THROWEXCEPTION("No queue number specified");
						int queueno = 0;
						std::string tmp = a->getValue();
						try {
							queueno = boost::lexical_cast<int>(tmp);
						}catch (boost::bad_lexical_cast &){
							THROWEXCEPTION("bad value for queue number: %s", tmp.c_str());
						}
						std::string ip = e->getFirstText();
						src[parseIp(ip)] = queueno;
					}
				}
				if (!selector) {
					selector = new IpPacketSelector();
					if (src.empty() && dst.empty())
						THROWEXCEPTION("IDSLoadBalancerCfg: packet selector IpPacketSelector was defined, but no source or destination IPs!");
				} else
					THROWEXCEPTION("IDSLoadBalancerCfg: multiple packet selectors specified! This is not allowed.");

			} else if (_selector == "PriorityPacketSelector") {
				float startprio = getDouble("startPriority", 1.0, e);
				uint32_t minmontime = getInt("minimumMonitoringTime", 10000, e);
				uint32_t maxspeed = getInt("maxSpeed", 0, e);
				list<PriorityNetConfig> config;
				list<WeightModifierConfig> weightmods;
				XMLNode::XMLSet<XMLElement*> set = e->getElementChildren();
				for (XMLNode::XMLSet<XMLElement*>::iterator it = set.begin(); it != set.end(); it++) {
					XMLElement* e = *it;
					if (e->matches("networks")) {
						XMLNode::XMLSet<XMLElement*> netset = e->getElementChildren();
						for (XMLNode::XMLSet<XMLElement*>::iterator nit = netset.begin(); nit != netset.end(); nit++) {
							XMLElement* e = *nit;
							if (e->matches("network")) {
								XMLAttribute* a = e->getAttribute("address");
								if (!a) THROWEXCEPTION("IDSLoadBalancerCfg: no attribute 'address' in configuration element 'network'!");
								string cidr = a->getFirstText();
								size_t pos = cidr.find("/");
								string ip = cidr.substr(0, pos);
								string sbits = cidr.substr(pos+1);
								int maskbits = atoi(sbits.c_str());
								if (maskbits<0 || maskbits>32)
									THROWEXCEPTION("IDSLoadBalancerCfg: attribute 'address' has invalid number of mask bits in configuration (%s)!", sbits.c_str());
								in_addr_t ipaddr = inet_addr(ip.c_str());
								if (ipaddr==(in_addr_t)-1)
									THROWEXCEPTION("IDSLoadBalancerCfg: attribute 'address' has invalid ip subnet in configuration (%s)!", ip.c_str());
								a = e->getAttribute("weight");
								if (!a) THROWEXCEPTION("IDSLoadBalancerCfg: no attribute 'weight' in configuration element 'network'!");
								char* res;
								float weight = strtof(a->getFirstText().c_str(), &res);
								if (weight<=0 || res==a->getFirstText().c_str())
									THROWEXCEPTION("IDSLoadBalancerCfg: attribute 'weight' in configuration element 'network' contains invalid value (%s)!", a->getFirstText().c_str());
								config.push_back(PriorityNetConfig(ntohl((uint32_t)ipaddr), ((1<<(32-maskbits))-1)^0xFFFFFFFF, maskbits, weight));
							}
						}
					}
					if (e->matches("weightModifiers")) {
						XMLNode::XMLSet<XMLElement*> netset = e->getElementChildren();
						for (XMLNode::XMLSet<XMLElement*>::iterator nit = netset.begin(); nit != netset.end(); nit++) {
							XMLElement* e = *nit;
							if (e->matches("traffic")) {
								XMLAttribute* a = e->getAttribute("quantile");
								if (!a) THROWEXCEPTION("IDSLoadBalancerCfg: no attribute 'quantile' in configuration element 'traffic'!");
								char* res;
								float quantile = strtof(a->getFirstText().c_str(), &res);
								if (quantile<=0 || quantile>1 || res==a->getFirstText().c_str())
									THROWEXCEPTION("IDSLoadBalancerCfg: attribute 'quantile' is not in expected range (0<x<=1): %s", a->getFirstText().c_str());
								a = e->getAttribute("weightModifier");
								if (!a) THROWEXCEPTION("IDSLoadBalancerCfg: no attribute 'weightModifier' in configuration element 'traffic'!");
								float weightmod = strtof(a->getFirstText().c_str(), &res);
								if (weightmod<=0 || res==a->getFirstText().c_str())
									THROWEXCEPTION("IDSLoadBalancerCfg: attribute 'weightModifier' is not in expected range (0<x): %s", a->getFirstText().c_str());
								weightmods.push_back(WeightModifierConfig(quantile, weightmod));
							}
						}
					}
				}

				if (!selector) {
					struct timeval tv;
					tv.tv_sec = minmontime/1000;
					tv.tv_usec = (minmontime%1000)*1000;

					// sort the network configuration by decreasing maskbits
					config.sort(compareDecrMask);
					selector = new PriorityPacketSelector(config, startprio, tv, maxspeed, weightmods);
				} else
					THROWEXCEPTION("IDSLoadBalancerCfg: multiple packet selectors specified! This is not allowed.");
			} else {
				THROWEXCEPTION("Invalid selector: %s", _selector.c_str());
			}
		}
	}
	if (!selector)
		THROWEXCEPTION("IDSLoadBalancerCfg: No packet selector specified, this is compulsory");
}
AnonPrimitive* AnonModule::createPrimitive(AnonMethod::Method m, const std::string& parameter, std::vector<map_info> mapping)
{
	AnonPrimitive* ret = 0;
	char buffer[32];
	char c;

	bool isHex = isHexString(parameter);

	switch (m) {
	case AnonMethod::HashSha1:
		ret = new AnonHashSha1();
		break;
	case AnonMethod::BytewiseHashSha1:
		ret = new AnonBytewiseHashSha1();
		break;
	case AnonMethod::ContinuousChar:
		ret = new AnonContinuousChar();
		break;
	case AnonMethod::Randomize:
		ret = new AnonRandomize();
		break;
	case AnonMethod::Shuffle:
		ret = new AnonShuffle();
		break;
	case AnonMethod::Whitenoise:
		ret = new AnonWhitenoise(atoi(parameter.c_str()));
		break;
	case AnonMethod::HashHmacSha1:
		ret = new AnonHashHmacSha1(parameter);
		break;
	case AnonMethod::BytewiseHashHmacSha1:
		ret = new AnonBytewiseHashHmacSha1(parameter);
		break;
	case AnonMethod::ConstOverwrite:
		if (parameter.size() != 1 || (isHex && parameter.size() != 4)) {
			THROWEXCEPTION("AnonConstOverwrite only uses one character as key");
		}
		c = parameter.c_str()[0];
		if (isHex) {
			if (convHexToBinary(parameter, &c, 1)!=1) {
				THROWEXCEPTION("Failed to convert hexadecimal key parameter '%s' to binary (one byte required)!", parameter.c_str());
			}
		}
		ret = new AnonConstOverwrite(parameter.c_str()[0]);
		break;
	case AnonMethod::CryptoPan:
		if (parameter.length()!=32)
			if (isHex && parameter.length() != 66)
				THROWEXCEPTION("CryptoPAN key *MUST* have exactly 32 characters!");

		if (isHex) {
			if (convHexToBinary(parameter, buffer, 32)!=32) {
				THROWEXCEPTION("Failed to convert hexadecimal key parameter '%s' to binary (32 bytes required)!", parameter.c_str());
			}
		} else {
			memcpy(buffer, parameter.c_str(), 32);
		}
		ret = new AnonCryptoPan(buffer);
		break;
    case AnonMethod::CryptoPanPrefix:
        if (parameter.length()!=32)
            if (isHex && parameter.length() != 66)
                THROWEXCEPTION("CryptoPAN key *MUST* have exactly 32 characters!");

        if (isHex) {
            if (convHexToBinary(parameter, buffer, 32)!=32) {
                THROWEXCEPTION("Failed to convert hexadecimal key parameter '%s' to binary (32 bytes required)!", parameter.c_str());
            }
        } else {
            memcpy(buffer, parameter.c_str(), 32);
        }
        ret = new AnonCryptoPanPrefix(buffer, mapping);
        break;
	default:
		msg(MSG_FATAL, "AnonPrimitive number %i is unknown", m);
		THROWEXCEPTION("AnonPrimitive number %i is unknown", m);
	}

	return ret;
}
Esempio n. 4
0
/**
 * Takes an IPFIX record, and tries to create a single packet for the record (two packets if it is bidirectional)
 * Payload of the packet is contained in the FPA payload field of the flow
 * This is done by using two prepared buffers that contain a UDP and TCP header stack (tcpHeader and udpHeader)
 * ATTENTION: checksums are not calculated at all, as well as other TCP header fields that are connection specific
 */
void FpaPcapExporter::onDataRecord(IpfixDataRecord* record)
{
	// only treat non-Options Data Records (although we cannot be sure that there is a Flow inside)
	if((record->templateInfo->setId != TemplateInfo::NetflowTemplate) 
		&& (record->templateInfo->setId != TemplateInfo::IpfixTemplate) 
		&& (record->templateInfo->setId != TemplateInfo::IpfixDataTemplate)) {
		record->removeReference();
		return;
	}
	
	Connection c(record);

	pcaprec_hdr_t pcaphdr;
	bzero(&pcaphdr, sizeof(pcaphdr));
	//pcaphdr.ts_sec = 0;	// FIXME: here we should use timestamp contained in IPFIX record
	//pcaphdr.ts_usec = 0 // see above!

	if (c.protocol==6) {
		uint16_t totlen = sizeof(tcpHeader)+c.srcPayloadLen;
		if (totlen>snaplen) totlen = snaplen;
		if (c.srcPayloadLen>0) {
			// copy normal direction
			tcpHeader.ip.tot_len = htons(totlen-sizeof(tcpHeader.ether));
			pcaphdr.incl_len = totlen;
			pcaphdr.orig_len = totlen;
			tcpHeader.ip.saddr = c.srcIP;
			tcpHeader.ip.daddr = c.dstIP;
			tcpHeader.tcp.source = c.srcPort;
			tcpHeader.tcp.dest = c.dstPort;
			if (fwrite(&pcaphdr, sizeof(pcaphdr), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write packet header to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
			if (fwrite(&tcpHeader, sizeof(tcpHeader), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write packet tcp header to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
			if (fwrite(c.srcPayload, totlen-sizeof(tcpHeader), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write tcp packet payload to file %s, error: %s", fileName.c_str(), strerror(errno));
			}

		}
		totlen = sizeof(tcpHeader)+c.dstPayloadLen;
		if (totlen>snaplen) totlen = snaplen;
		if (c.dstPayloadLen>0) {
			// copy reverse direction
			tcpHeader.ip.tot_len = htons(totlen-sizeof(tcpHeader.ether));
			pcaphdr.incl_len = totlen;
			pcaphdr.orig_len = totlen;
			tcpHeader.ip.saddr = c.dstIP;
			tcpHeader.ip.daddr = c.srcIP;
			tcpHeader.tcp.source = c.dstPort;
			tcpHeader.tcp.dest = c.srcPort;
			if (fwrite(&pcaphdr, sizeof(pcaphdr), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write packet header to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
			if (fwrite(&tcpHeader, sizeof(tcpHeader), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write packet tcp header to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
			if (fwrite(c.dstPayload, totlen-sizeof(tcpHeader), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write tcp packet payload to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
		}
	} else if (c.protocol==17) {
		uint16_t totlen = sizeof(udpHeader)+c.srcPayloadLen;
		if (totlen>snaplen) totlen = snaplen;
		if (c.srcPayloadLen>0) {
			// copy normal direction
			udpHeader.ip.tot_len = htons(totlen-sizeof(udpHeader.ether));
			pcaphdr.incl_len = totlen;
			pcaphdr.orig_len = totlen;
			udpHeader.ip.saddr = c.srcIP;
			udpHeader.ip.daddr = c.dstIP;
			udpHeader.udp.source = c.srcPort;
			udpHeader.udp.dest = c.dstPort;
			udpHeader.udp.len = htons(totlen-sizeof(udpHeader)+sizeof(udpHeader.udp));
			if (fwrite(&pcaphdr, sizeof(pcaphdr), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write packet header to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
			if (fwrite(&udpHeader, sizeof(udpHeader), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write packet udp header to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
			if (fwrite(c.srcPayload, totlen-sizeof(udpHeader), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write udp packet payload to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
		}
		totlen = sizeof(udpHeader)+c.dstPayloadLen;
		if (totlen>snaplen) totlen = snaplen;
		if (c.dstPayloadLen>0) {
			// copy reverse direction
			udpHeader.ip.tot_len = htons(totlen-sizeof(udpHeader.ether));
			pcaphdr.incl_len = totlen;
			pcaphdr.orig_len = totlen;
			udpHeader.ip.saddr = c.dstIP;
			udpHeader.ip.daddr = c.srcIP;
			udpHeader.udp.source = c.dstPort;
			udpHeader.udp.dest = c.srcPort;
			udpHeader.udp.len = htons(totlen-sizeof(udpHeader)+sizeof(udpHeader.udp));
			if (fwrite(&pcaphdr, sizeof(pcaphdr), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write packet header to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
			if (fwrite(&udpHeader, sizeof(udpHeader), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write packet udp header to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
			if (fwrite(c.dstPayload, totlen-sizeof(udpHeader), 1, pcapfile)!=1) {
				THROWEXCEPTION("FpaPcapExporter: Failed to write udp packet payload to file %s, error: %s", fileName.c_str(), strerror(errno));
			}
		}
	}
	record->removeReference();
}
/**
 * Starts the command given in 'cmd'
 * STDOUT and STDERR of 'cmd' may be redirected into a file, see
 * module_configuration.txt for details
 * */
int PCAPExporterMem::execCmd(std::string& cmd)
{
    int child_parent_pipe[2];
    char *command[64];
    int i=0;
    std::vector<std::string> tokens;
    parseCommandLine(cmd, tokens);
    for (std::vector<std::string>::iterator it = tokens.begin(); it!=tokens.end(); it++) {
        command[i++] = const_cast<char*>(it->c_str());
        if(i>62) THROWEXCEPTION("Argument list too long");
    }
    command[i] = (char*)NULL;

    if (pipe(child_parent_pipe)) {
        THROWEXCEPTION("pipe(child_parent_pipe) failed with error code %u (%s)", errno, strerror(errno));
    }

    /* Create a pipe, which allows communication between the child and the parent.
     * Writing an int value (e.g. errno) into child_parent_pipe[1]
     * will cause an exception in the parent process.
     * Throwing exceptions in the child *will not* terminate Vermont!
     */
    for (int i=0; i<2; i++) {
        int oldflags = fcntl (child_parent_pipe[i], F_GETFD, 0);
        if(-1 == oldflags)
            THROWEXCEPTION("fctnl: %s", strerror(errno));
        oldflags |= FD_CLOEXEC;
        if (-1 == fcntl (child_parent_pipe[i], F_SETFD, oldflags))
            THROWEXCEPTION("fctnl: %s", strerror(errno));
    }

    int pid = fork();
    if (pid == 0) {
        // child process
        close(child_parent_pipe[0]); // close read-end
        if (workingPath != "") {
            int res = chdir(workingPath.c_str());
            if (res != 0) {
                THROWEXCEPTION("failed to change to working path '%s'", workingPath.c_str());
                exit(1);
            }
        }
        redirectLogfile();

        if (execvp(command[0], command)<0) {
            if (write(child_parent_pipe[1], &errno, sizeof(int)) != sizeof(int))
                THROWEXCEPTION("exec failed"); //throw the exception only if we couldn't
            //tell the parent that sth. went wrong...
            exit(1);
        }
    } else if (pid > 0) {
        close(child_parent_pipe[1]);
        int buf;
        if (read(child_parent_pipe[0], &buf, sizeof(int)) == sizeof(int)) { //The child actually wrote errno into the pipe
            THROWEXCEPTION("An error occurred in the child: %s", strerror(buf));
        }
        close(child_parent_pipe[0]);

        return pid;
    } else {
        THROWEXCEPTION("fork() failed");
    }
    return -1;
}
/**
 * DTLS over SCTP specific listener function. This function is called by @c listenerThread()
 */
void IpfixReceiverDtlsSctpIpV4::run() {

    struct sockaddr_in clientAddress;
    socklen_t clientAddressLen = sizeof(struct sockaddr_in);

    int ret;
    int rfd;
    struct timespec timeOut;

    /* set a 400ms time-out on the pselect */
    timeOut.tv_sec = 0L;
    timeOut.tv_nsec = 400000000L;

    while(!exitFlag) {
	fd_set tmpreadfds = readfds;
	fd_set tmpwritefds = writefds;
	ret = pselect(maxfd + 1, &tmpreadfds, &tmpwritefds, NULL, &timeOut, NULL);
	if (ret == 0) {
	    /* Timeout */
	    continue;
	}
	if ((ret == -1) && (errno == EINTR)) {
	    DPRINTF("select() returned due to signal");
	    /* There was a signal... ignore */
	    continue;
	}
	if (ret < 0) {
	    msg(MSG_ERROR ,"select() returned with an error: %s",strerror(errno));
	    THROWEXCEPTION("IpfixReceiverDtlsSctpIpV4: terminating listener thread");
	    break;
	}
	DPRINTF("select() returned %d",ret);
	// looking for a new client to connect at listen_socket
	if (FD_ISSET(listen_socket, &tmpreadfds)){
	    rfd = accept(listen_socket, (struct sockaddr*)&clientAddress, &clientAddressLen);

	    if (rfd >= 0){
		if ( ! isHostAuthorized(&clientAddress.sin_addr,
			    sizeof(clientAddress.sin_addr))) {
		    /* Do not accept connections from unauthorized hosts. */
		    close(rfd);
		} else {
		    msg(MSG_DEBUG, "IpfixReceiverDtlsSctpIpV4: Client connected from %s:%d, FD=%d", inet_ntoa(clientAddress.sin_addr), ntohs(clientAddress.sin_port), rfd);
		    DtlsConnectionPtr conn = DtlsConnectionPtr( new DtlsConnection(*this,&clientAddress,rfd));
		    connections.insert(make_pair(rfd,conn));
		    update_maxfd();
		}
	    }else{
		msg(MSG_ERROR ,"accept() in ipfixReceiver failed");
		/* TODO: Don't throw an exception here. */
		THROWEXCEPTION("IpfixReceiverDtlsSctpIpV4: unable to accept new connection");
	    }
	}
	// check all connected sockets for new available data
	for (rfd = 0; rfd <= maxfd; ++rfd) {
	    if (rfd == listen_socket) continue;
	    if (FD_ISSET(rfd, &readfds) || FD_ISSET(rfd, &writefds)) {
		if (FD_ISSET(rfd, &readfds)) DPRINTF("descriptor %d is ready for reading",rfd);
		if (FD_ISSET(rfd, &writefds)) DPRINTF("descriptor %d is ready for writing",rfd);
		connections_map::iterator it = connections.find(rfd);
		if (it == connections.end()) {
		    /* This should not happend. */
		    msg(MSG_ERROR,"Can't find connection for file descriptor.");
		    FD_CLR(rfd,&readfds);
		    FD_CLR(rfd,&writefds);
		    continue;
		}
		ret = it->second->fdready();
		if (ret == 0) {
		    DPRINTF("fdready() returned 0. Deleting connection.");
		    remove_connection(rfd);
		    update_maxfd();
		}
	    }
	}
    }
    msg(MSG_DEBUG, "IpfixReceiverDtlsSctpIpV4: Exiting");
}
/** 
 * Does DTLS over SCTP/IPv4 specific initialization.
 * @param port Port to listen on
 */
IpfixReceiverDtlsSctpIpV4::IpfixReceiverDtlsSctpIpV4(int port, const std::string ipAddr,
	const std::string &certificateChainFile, const std::string &privateKeyFile,
	const std::string &caFile, const std::string &caPath,
	const std::set<string> &peerFqdnsParam)
    : IpfixReceiver(port),ssl_ctx(certificateChainFile,privateKeyFile,caFile,caPath,
	! peerFqdnsParam.empty()),listen_socket(-1),maxfd(0),
	peerFqdns(peerFqdnsParam), statReceivedPackets(0)
	 {
	
    struct sockaddr_in serverAddress;
    struct sctp_event_subscribe ses;
    int flags;

    /* FIXME: make error messages consistent with IpfixReceiverDtlsUdpIpV4 */

    try {
	listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
	if(listen_socket < 0) {
	    /* FIXME: should we use strerror_r? */
	    msg(MSG_FATAL, "socket creation failed: %s", strerror(errno));
	    THROWEXCEPTION("Cannot create IpfixReceiverDtlsSctpIpV4, socket creation failed: %s", strerror(errno));
	}
	/* set socket to non-blocking i/o */
	flags = fcntl(listen_socket,F_GETFL,0);
	flags |= O_NONBLOCK;
	if (fcntl(listen_socket,F_SETFL,flags)<0) {
	    THROWEXCEPTION("IPFIX: Failed to set socket to non-blocking i/o");
	}
	
	// if ipAddr set: Bind a specific IP address to our socket.
	// else: use wildcard address
	if(ipAddr.empty())
	    serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
	else
	    if ( ! inet_pton(AF_INET,ipAddr.c_str(),&serverAddress.sin_addr) ) {
		THROWEXCEPTION("IP address invalid.");
	    }
	
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_port = htons(port);
	if(bind(listen_socket, (struct sockaddr*)&serverAddress, 
	    sizeof(struct sockaddr_in)) < 0) {
	    msg(MSG_FATAL, "Cannot bind socket: %s", strerror(errno));
	    THROWEXCEPTION("Cannot create IpfixReceiverDtlsSctpIpV4 %s:%d",ipAddr.c_str(), port );
	}
	if(listen(listen_socket, SCTP_MAX_BACKLOG) < 0 ) {
	    msg(MSG_FATAL, "Can not listen socket: %s", strerror(errno));
	    THROWEXCEPTION("Cannot create IpfixReceiverDtlsSctpIpV4 %s:%d",ipAddr.c_str(), port );
	}
	msg(MSG_INFO, "SCTP Receiver listening on %s:%d, FD=%d", (ipAddr == "")?std::string("ALL").c_str() : ipAddr.c_str(), 
								port, 
								listen_socket);

	memset(&ses, 0, sizeof(ses));
	ses.sctp_data_io_event = 1;
	if ( setsockopt(listen_socket, IPPROTO_SCTP, SCTP_EVENTS, &ses, sizeof(ses))) {
	    msg(MSG_FATAL, "setsockopt() failed: %s", strerror(errno));
	    THROWEXCEPTION("Cannot create IpfixReceiverDtlsSctpIpV4 %s:%d",ipAddr.c_str(), port );
	}

	/* BIO_new_dgram_sctp sets the necessary socket options on listen_socket.
	 * This includes activating SCTP-AUTH and subscribing to all necessary events.
	 * We can delete this BIO right after because we're only calling it for the
	 * side effects on listen_socket. */
	BIO_free(BIO_new_dgram_sctp(listen_socket, BIO_NOCLOSE));

	FD_ZERO(&readfds);
	FD_ZERO(&writefds);
	FD_SET(listen_socket,&readfds);
	update_maxfd();

	/* TODO: Find out what this is? */
	SensorManager::getInstance().addSensor(this, "IpfixReceiverDtlsSctpIpV4", 0);

	msg(MSG_INFO, "DTLS over SCTP Receiver listening on %s:%d, FD=%d", (ipAddr == "")?std::string("ALL").c_str() : ipAddr.c_str(), 
								port, 
								listen_socket);
    } catch(...) {
	if (listen_socket>=0) {
	    close(listen_socket);
	    listen_socket = -1;
	}
	throw; // rethrow
    }
}
/**
 * SCTP specific listener function. This function is called by @c listenerThread()
 */
void IpfixReceiverSctpIpV4::run() {

	struct sockaddr_in clientAddress;
	socklen_t clientAddressLen;
	clientAddressLen = sizeof(struct sockaddr_in);
	
	fd_set fd_array; //all active filedescriptors
	int maxfd;
	
	FD_ZERO(&fd_array);
	FD_SET(listen_socket, &fd_array); // add listensocket
	maxfd = listen_socket;
	
	fd_set readfds;
	int ret;
	int rfd;
	
	
	while(!exit) {
		
		readfds = fd_array; // because select() changes readfds
		ret = select(maxfd + 1, &readfds, NULL, NULL, NULL); // check only for something to read
		if ((ret == -1) && (errno == EINTR)) {
			/* There was a signal... ignore */
			continue;
    		}
    		if (ret < 0) {
    			msg(MSG_ERROR ,"select() returned with an error");
			THROWEXCEPTION("IpfixReceiverSctpIpV4: terminating listener thread");
			break;
		}
		// looking for a new client to connect at listen_socket
		if (FD_ISSET(listen_socket, &readfds)){
			rfd = accept(listen_socket, (struct sockaddr*)&clientAddress, &clientAddressLen);
			
			if (rfd >= 0){
				FD_SET(rfd, &fd_array); // add new client to fd_array
				msg(MSG_DEBUG, "IpfixReceiverSctpIpV4: Client connected from %s:%d, FD=%d", inet_ntoa(clientAddress.sin_addr), ntohs(clientAddress.sin_port), rfd);
				if (rfd > maxfd){
					maxfd = rfd;
				}
			}else{
				msg(MSG_ERROR ,"accept() in ipfixReceiver failed");
				THROWEXCEPTION("IpfixReceiverSctpIpV4: unable to accept new connection");
			}
		}
// 		check all connected sockets for new available data
		for (rfd = listen_socket + 1; rfd <= maxfd; ++rfd) {
      			if (FD_ISSET(rfd, &readfds)) {
				boost::shared_array<uint8_t> data(new uint8_t[MAX_MSG_LEN]);
      				ret = recvfrom(rfd, data.get(), MAX_MSG_LEN, 0, 
      					(struct sockaddr*)&clientAddress, &clientAddressLen);
				if (ret == 0) { // shut down initiated
					FD_CLR(rfd, &fd_array); // delete dead client
					msg(MSG_DEBUG, "IpfixReceiverSctpIpV4: Client disconnected");
				}else{
					if (isHostAuthorized(&clientAddress.sin_addr,
					    sizeof(clientAddress.sin_addr))) {
						boost::shared_ptr<IpfixRecord::SourceID> sourceID(new IpfixRecord::SourceID);
		
						memcpy(sourceID->exporterAddress.ip, &clientAddress.sin_addr.s_addr, 4);
						sourceID->exporterAddress.len = 4;
						sourceID->exporterPort = ntohs(clientAddress.sin_port);
						sourceID->protocol = IPFIX_protocolIdentifier_SCTP;
						sourceID->receiverPort = receiverPort;
						sourceID->fileDescriptor = rfd;
						pthread_mutex_lock(&mutex);
						for (std::list<IpfixPacketProcessor*>::iterator i = packetProcessors.begin(); i != packetProcessors.end(); ++i) { 
							(*i)->processPacket(data, ret, sourceID);
						}
						pthread_mutex_unlock(&mutex);
					}
					else{
						msg(MSG_DEBUG, "packet from unauthorized host %s discarded", inet_ntoa(clientAddress.sin_addr));
					}
				}
      			}
      		}
	}
}
Esempio n. 9
0
void IpfixPayloadWriter::dumpEntry(Connection* conn)
{
	char filename[2][100];
	char idxpath[2][100];
	snprintf(filename[0], 100, "%s-%04llu-%s.%d-%s.%d", filenamePrefix.c_str(),
			(long long unsigned)connectionID, IPToString(conn->srcIP).c_str(), ntohs(conn->srcPort), IPToString(conn->dstIP).c_str(), ntohs(conn->dstPort));
	snprintf(filename[1], 100, "%s-%04llu-%s.%d-%s.%d", filenamePrefix.c_str(),
			(long long unsigned)connectionID, IPToString(conn->dstIP).c_str(), ntohs(conn->dstPort), IPToString(conn->srcIP).c_str(), ntohs(conn->srcPort));
	snprintf(idxpath[0], ARRAY_SIZE(idxpath[0]), "/%04llX", (long long unsigned)(connectionID>>16));
	snprintf(idxpath[1], ARRAY_SIZE(idxpath[1]), "/%02llX/", (long long unsigned)(connectionID>>8));
	connectionID++;

	// create paths, if needed
	struct stat s;
	string mkpath = path+string(idxpath[0]);
	if (stat(mkpath.c_str(), &s) != 0) {
		if (mkdir(mkpath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)!=0)
			THROWEXCEPTION("error while creating directory '%s': %s", mkpath.c_str(), strerror(errno));
	}
	mkpath += string(idxpath[1]);
	if (stat(mkpath.c_str(), &s) != 0) {
		if (mkdir(mkpath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)!=0)
			THROWEXCEPTION("error while creating directory '%s': %s", mkpath.c_str(), strerror(errno));
	}

	string filepayload[2] = { mkpath + string(filename[0]) + ".payload", mkpath + string(filename[1]) + ".payload" };
	string fileinfo = mkpath + string(filename[0]) + ".info";

	msg(MSG_VDEBUG, "writing files for connection %s", filename[0]);

	if (stat(filepayload[0].c_str(), &s) == 0 && !filewarningIssued) {
		msg(MSG_DIALOG, "files in IpfixPayloadWriter destination directory already present, overwriting ...");
		filewarningIssued = true;
	}
	// save payload in two files
	FILE* f;
	char buf[500];
	if (conn->srcPayload) {
		f = fopen(filepayload[0].c_str(), "w+");
		if (f == NULL) THROWEXCEPTION("failed to open file '%s', error: %s", filepayload[0].c_str(), strerror(errno));
		if (conn->srcPayloadLen && fwrite(conn->srcPayload, conn->srcPayloadLen, 1, f) != 1)
			THROWEXCEPTION("failed to write to file '%s', error: %s, 1", filepayload[0].c_str(), strerror(errno));
		if (fclose(f) != 0)
			THROWEXCEPTION("failed to close file '%s', error: %s, 2", filepayload[0].c_str(), strerror(errno));
	}
	if (conn->dstPayload) {
		f = fopen(filepayload[1].c_str(), "w+");
		if (f == NULL) THROWEXCEPTION("failed to open file '%s', error: %s", filepayload[1].c_str(), strerror(errno));
		if (conn->dstPayloadLen && fwrite(conn->dstPayload, conn->dstPayloadLen, 1, f) != 1)
			THROWEXCEPTION("failed to write to file '%s', error: %s, 3", filepayload[1].c_str(), strerror(errno));
		if (fclose(f) != 0)
			THROWEXCEPTION("failed to close file '%s', error: %s, 4", filepayload[1].c_str(), strerror(errno));
	}

	// save additional data
	f = fopen(fileinfo.c_str(), "w+");
	if (f == NULL) THROWEXCEPTION("failed to open file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "srcIP: %s\n", IPToString(conn->srcIP).c_str());
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "dstIP: %s\n", IPToString(conn->dstIP).c_str());
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "srcPort: %u\n", ntohs(conn->srcPort));
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "dstPort: %u\n", htons(conn->dstPort));
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "srcFlowTimes: %llu / %llu\n", (long long unsigned)conn->srcTimeStart, (long long unsigned)conn->srcTimeEnd);
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "revFlowTimes: %llu / %llu\n", (long long unsigned)conn->dstTimeStart, (long long unsigned)conn->dstTimeEnd);
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "srcOctets: %llu\n", (long long unsigned)htonll(conn->srcOctets));
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "revOctets: %llu\n", (long long unsigned)htonll(conn->dstOctets));
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "srcPackets: %llu\n", (long long unsigned)htonll(conn->srcPackets));
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "revPackets: %llu\n", (long long unsigned)htonll(conn->dstPackets));
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "protocol: %d\n", conn->protocol);
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "srcPayloadLen: %d\n", conn->srcPayloadLen);
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	snprintf(buf, 100, "dstPayloadLen: %d\n", conn->dstPayloadLen);
	if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));

	if (conn->srcPayload != 0) {
		snprintf(buf, 100, "nicePayload: ");
		if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
		if (conn->srcPayloadLen>0) {
			uint32_t buflen = (conn->srcPayloadLen > ARRAY_SIZE(buf) ? ARRAY_SIZE(buf) : conn->srcPayloadLen);
			memcpy(buf, conn->srcPayload, buflen);
			for (uint32_t i=0; i<buflen && i<conn->srcPayloadLen; i++) {
				if (!isprint(buf[i])) buf[i] = '.';
			}
			if (fwrite(buf, buflen, 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
		}
		if (fwrite("\n", 1, 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	}

	if (conn->dstPayload != 0) {
		snprintf(buf, 100, "revNicePayload: ");
		if (fwrite(buf, strnlen(buf, 100), 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
		if (conn->dstPayloadLen>0) {
			uint32_t buflen = (conn->dstPayloadLen > ARRAY_SIZE(buf) ? ARRAY_SIZE(buf) : conn->dstPayloadLen);
			memcpy(buf, conn->dstPayload, buflen);
			for (uint32_t i=0; i<buflen && i<conn->dstPayloadLen; i++) {
				if (!isprint(buf[i])) buf[i] = '.';
			}
			if (fwrite(buf, buflen, 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
		}
		if (fwrite("\n", 1, 1, f) != 1) THROWEXCEPTION("failed to write to file '%s', error: %s", fileinfo.c_str(), strerror(errno));
	}

	if (fclose(f) != 0) THROWEXCEPTION("failed to close file '%s', error: %s", fileinfo.c_str(), strerror(errno));
}
Esempio n. 10
0
void SensorManager::retrieveStatistics(bool ignoreshutdown)
{
	const char* xmlpre = "<vermont>\n\t<sensorData time=\"%s\" epochtime=\"%d.%03d\" host=\"%s\">\n";
	const char* xmlpost = "\t</sensorData>\n</vermont>\n";
	const char* xmlglobals = "\t\t<%s>%s</%s>\n";

	string lockfile = outputFilename + ".lock";
	bool haveGraphLock;

	// we must not wait for the graph lock, else there may be a race condition with
	// the ConfigManager
	while (! (haveGraphLock = graphIS->tryLockGraph())) {
		if (smExitFlag) break;
		timespec timeout = { 0, 200000 };
		nanosleep(&timeout, NULL);
	}

	if (!ignoreshutdown && smExitFlag) return;

	const char* openflags = (append ? "a" : "w");
	FILE* file = fopen(outputFilename.c_str(), openflags);
	if (!file) {
		THROWEXCEPTION("failed to reopen file %s", outputFilename.c_str());
		perror("error:");
	}

	timeval tvcurtime = unixtime();
	time_t curtime = tvcurtime.tv_sec;
	char curtimestr[100];
	ctime_r(&curtime, curtimestr);
	curtimestr[strlen(curtimestr)-1] = 0;
	fprintf(file, xmlpre, curtimestr, curtime, tvcurtime.tv_usec/1000, hostname);
	char text[100];
	snprintf(text, 100, "%u", static_cast<uint32_t>(getpid()));
	fprintf(file, xmlglobals, "pid", text, "pid");
	char lasttimestr[100];
	ctime_r(&lasttime, lasttimestr);
	lasttimestr[strlen(lasttimestr)-1] = 0;
	fprintf(file, xmlglobals, "lastTime", lasttimestr, "lastTime");

#if defined(__linux__)
	const char* xmlglobalsuint = "\t\t<%s>%u</%s>\n";
	ThreadCPUInterface::SystemInfo si = ThreadCPUInterface::getSystemInfo();

	fprintf(file, "\t\t<jiffyFrequency>%llu</jiffyFrequency>\n", (long long unsigned)hertzValue);
	fprintf(file, xmlglobalsuint, "processorAmount", si.noCPUs, "processorAmount");
	for (uint16_t i=0; i<si.sysJiffies.size(); i++) {
		double sysutil = (si.sysJiffies[i]-lastSystemInfo.sysJiffies[i])/(static_cast<double>(curtime)-lasttime)/hertzValue*100;
		double userutil = (si.userJiffies[i]-lastSystemInfo.userJiffies[i])/(static_cast<double>(curtime)-lasttime)/hertzValue*100;
		fprintf(file, "\t\t<processor id=\"%u\"><util type=\"system\">%.2f</util><util type=\"user\">%.2f</util></processor>\n",
				i, sysutil, userutil);
	}
	fprintf(file, "\t\t<memory><free type=\"bytes\">%llu</free><total type=\"bytes\">%llu</total></memory>\n",
			(long long unsigned)si.freeMemory, (long long unsigned)si.totalMemory);
	lastSystemInfo = si;
#endif

	//DPRINTF("*** sensor data at %s", ctime(&curtime));

	Graph* g = graphIS->getGraph();
	vector<CfgNode*> nodes = g->getNodes();
	vector<CfgNode*>::iterator iter = nodes.begin();
	while (iter != nodes.end()) {
		Cfg* cfg = (*iter)->getCfg();
		Sensor* s = cfg->getInstance();
		vector<uint32_t> nextids = cfg->getNext();
		writeSensorXML(file, s, cfg->getName().c_str(), cfg->getID(), true, curtime, lasttime, &nextids);

		iter++;
	}

	// iterate through all non-module sensors
	mutex.lock();
	list<SensorEntry>::const_iterator siter = sensors.begin();
	while (siter != sensors.end()) {
        //DPRINTFL(MSG_ERROR, "non-module cfg->getName()=%s, s=%u", siter->name.c_str(), siter->sensor);
		writeSensorXML(file, siter->sensor, siter->name.c_str(), siter->id, false, curtime, lasttime, NULL);
		siter++;
	}
	mutex.unlock();

	fprintf(file, "%s", xmlpost);
	fclose(file);

	if (haveGraphLock) graphIS->unlockGraph();
}
Esempio n. 11
0
bool Config::Init()
{
	// Default values, if they are not set under config.xml those will be used.
	// Section GFX
	m_vParserInfo.push_back( ParserData( "GFX", IS_SECTION, NULL ) );
	m_vParserInfo.push_back( ParserData( "WIDTH", IS_INTEGER, &m_iWidth ) );
	m_vParserInfo.push_back( ParserData( "HEIGHT", IS_INTEGER, &m_iHeight ) );
	m_vParserInfo.push_back( ParserData( "BPP", IS_INTEGER, &m_iBPP ) );
	m_vParserInfo.push_back( ParserData( "CURSOR", IS_INTEGER, &m_iCursor ) );
	m_vParserInfo.push_back( ParserData( "PERSPECTIVE", IS_INTEGER, &m_iPerspective ) );
	m_vParserInfo.push_back( ParserData( "FULLSCREEN", IS_INTEGER, &m_iStartFullScreen ) );
	m_vParserInfo.push_back( ParserData( "ROOF_FADE_TIME", IS_INTEGER, &m_iRoofFadeTime ) );
	m_vParserInfo.push_back( ParserData( "ROOF_FADE_ALPHA", IS_INTEGER, &m_iRoofFadeAlpha ) );
	m_vParserInfo.push_back( ParserData( "ZBUFFER_SIZE", IS_INTEGER, &m_iDepthBuffer ) );
	m_vParserInfo.push_back( ParserData( "MAXZOOM", IS_INTEGER, &m_iMaxZoom ) );
	m_vParserInfo.push_back( ParserData( "MAXANGLE", IS_INTEGER, &m_iMaxAngle ) );
	m_vParserInfo.push_back( ParserData( "VIEWDISTANCE", IS_INTEGER, &m_iViewDistance ) );
	m_vParserInfo.push_back( ParserData( "BRIGHTNESS", IS_INTEGER, &m_iBrightness ) );

	// Section UO
	m_vParserInfo.push_back( ParserData( "UO", IS_SECTION, NULL ) );
	m_vParserInfo.push_back( ParserData( "STARTX", IS_INTEGER, &m_iStartX ) );
	m_vParserInfo.push_back( ParserData( "STARTY", IS_INTEGER, &m_iStartY ) );
	m_vParserInfo.push_back( ParserData( "STARTZ", IS_INTEGER, &m_iStartZ ) );
	m_vParserInfo.push_back( ParserData( "MULPATH", IS_STRING, &m_sMulPath ) );
	// m_vParserInfo.push_back( ParserData( "COMPRESSED_MAP", IS_STRING, &m_sCompressedMap ) );
	m_vParserInfo.push_back( ParserData( "POPUP_MENU", IS_INTEGER, &m_iPopup ) );
	m_vParserInfo.push_back( ParserData( "AOS", IS_INTEGER, &m_iAOSToolTips ) );
	m_vParserInfo.push_back( ParserData( "CLIENT_IDENTIFICATION", IS_STRING, &m_sClientVersion ) );
	m_vParserInfo.push_back( ParserData( "USE_CLILOCS", IS_INTEGER, &m_iClilocs ) );
	m_vParserInfo.push_back( ParserData( "CLILOC_LANGUAGE", IS_STRING, &m_sClilocLang ) );
	m_vParserInfo.push_back( ParserData( "SPEECH_HUE", IS_INTEGER, &m_iSpeechHue ) );
	m_vParserInfo.push_back( ParserData( "AOSTOOLTIPS", IS_INTEGER, &m_iAOSToolTips ) );
    //Artix added speech.mul config option
    m_vParserInfo.push_back( ParserData( "USE_SPEECH", IS_INTEGER, &m_iSpeech ) );
	// Section NET
	m_vParserInfo.push_back( ParserData( "NET", IS_SECTION, NULL ) );
	m_vParserInfo.push_back( ParserData( "PORT", IS_INTEGER, &m_iServerPort ) );
	m_vParserInfo.push_back( ParserData( "SERVER", IS_STRING, &m_sServer ) );
	m_vParserInfo.push_back( ParserData( "LOGIN", IS_STRING, &m_sLogin ) );
	m_vParserInfo.push_back( ParserData( "PASSWORD", IS_STRING, &m_sPassword ) );
	m_vParserInfo.push_back( ParserData( "IS_SPHERE", IS_INTEGER, &m_iIsSphere ) );
	m_vParserInfo.push_back( ParserData( "IS_SPHERE55R", IS_INTEGER, &m_iIsSphere55R ) );
	m_vParserInfo.push_back( ParserData( "IS_POL", IS_INTEGER, &m_iIsPol ) );
	m_vParserInfo.push_back( ParserData( "IS_RUNUO", IS_INTEGER, &m_iIsRunUO ) );
	m_vParserInfo.push_back( ParserData( "IS_UOX3", IS_INTEGER, &m_iIsUox3 ) );
	m_vParserInfo.push_back( ParserData( "CLIENT_KEY", IS_INTEGER, &m_iClientKey ) );

	// Section Sound
	m_vParserInfo.push_back( ParserData( "SOUND", IS_SECTION, NULL ) );
	m_vParserInfo.push_back( ParserData( "MUSIC", IS_INTEGER, &m_iMusic ) );
	m_vParserInfo.push_back( ParserData( "SOUND", IS_INTEGER, &m_iSound ) );
	m_vParserInfo.push_back( ParserData( "FREQUENCY", IS_INTEGER, &m_iFrequency ) );
	m_vParserInfo.push_back( ParserData( "STEREO", IS_INTEGER, &m_iStereo ) );
	m_vParserInfo.push_back( ParserData( "CHUNKSIZE", IS_INTEGER, &m_iChunkSize ) );
	m_vParserInfo.push_back( ParserData( "MUSICVOLUME", IS_INTEGER, &m_iMusicVolume ) );
	m_vParserInfo.push_back( ParserData( "SOUNDVOLUME", IS_INTEGER, &m_iSoundVolume ) );
	m_vParserInfo.push_back( ParserData( "MP3", IS_INTEGER, &m_iMP3 ) );
	m_vParserInfo.push_back( ParserData( "FOOTSTEPS", IS_INTEGER, &m_iFootSteps ) );

	// Section Iris Client
	m_vParserInfo.push_back( ParserData( "IRIS", IS_SECTION, NULL ) );
	m_vParserInfo.push_back( ParserData( "SCRIPTS_PATH", IS_STRING, &m_sScriptPath ) );
	m_vParserInfo.push_back( ParserData( "MOUSEOVER_TIMER", IS_INTEGER, &m_iMouseMotionTimer ) );
	m_vParserInfo.push_back( ParserData( "", IS_END, NULL ) );


	// After adding to the vector our struct start filling it with actual values
	XML::Parser kParser;

	kParser.loadData( "./xml/config.xml" );
	XML::Node *kDocument = kParser.parseDocument();
	XML::Node *kConfig = kDocument->findNode( "CONFIG" );

	if ( !kConfig )
	{
		THROWEXCEPTION( "Could not find configuration node." );

		return false;
	}

	XML::Node *kValue = NULL, *kSection = NULL;
	// Read all values from config.xml
	for ( int i = 0; m_vParserInfo[i].iType != IS_END; i++ )
	{
		const ParserData &Data = m_vParserInfo[i];

		if ( Data.iType == IS_SECTION )
		{
			kSection = kConfig->findNode( Data.sName );
		}
		else
		{
			// If no section is loaded get from <config>
			kValue = kSection != NULL ? kSection->findNode( Data.sName ) : kConfig->findNode( Data.sName );

			if ( kValue != NULL )
			{
				if ( Data.iType == IS_BOOL )
				{
					*reinterpret_cast<bool *>( Data.pData ) = kValue->asBool();
				}
				else if ( Data.iType == IS_INTEGER )
				{
					*reinterpret_cast<int *>( Data.pData ) = kValue->asInteger();
				}
				else if ( Data.iType == IS_STRING )
				{
					*reinterpret_cast<std::string *>( Data.pData ) = kValue->asString();
				}
			}
		}
	}


	// Read Fonts bit of the file
	XML::Node *kFontSet = kConfig->findNode( "FONTSET" );

	if ( kFontSet )
	{
		int idx = 0;
		XML::Node *kFontNode = NULL;
		FontInfo kFontInfo;

		while ( ( kFontNode = kFontSet->findNode( "FONT", idx++ ) ) )
		{
			if ( !kFontNode->lookupAttribute( "ID", kFontInfo.iId ) )
			{
				continue;
			}

			if ( !kFontNode->lookupAttribute( "FILE", kFontInfo.sFileName ) )
			{
				continue;
			}

			if ( !kFontNode->lookupAttribute( "NAME", kFontInfo.sFontName ) )
			{
				continue;
			}

			if ( !kFontNode->lookupAttribute( "SIZE", kFontInfo.iSize ) )
			{
				continue;
			}

			if ( !kFontNode->lookupAttribute( "HUE",  kFontInfo.iHue ) )
			{
				continue;
			}

			FontManager::GetInstance()->AddTTFFont( kFontInfo.iId, kFontInfo.sFileName, kFontInfo.sFontName, kFontInfo.iSize, kFontInfo.iHue );
		}
	}


	// Depth Buffer
	if ( m_iDepthBuffer <= 0 )
	{
		m_iDepthBuffer = 16;
	}

	// View Distance
	if ( m_iViewDistance < 3 )
	{
		m_iViewDistance = 3;
	}

	// Max Zoom
	if ( m_iMaxZoom <= 0 )
	{
		m_iMaxZoom = 0;
	}

	// Max Angle
	if ( m_iMaxAngle < 10 )
	{
		m_iMaxAngle = 10;
	}

	// Max Angle
	if ( m_iMaxAngle > 90 )
	{
		m_iMaxAngle = 90;
	}

	// Fix Mul path if no / at the end
	if ( m_sMulPath.size() )
	{
		char cLastChar = m_sMulPath[m_sMulPath.length() - 1];

		if ( ( cLastChar != '/' ) && ( cLastChar != '\\' ) )
		{
			m_sMulPath += "/";
		}
	}

	return true;
}
/**
 * parses configuration and adjusts/creates module graph accordingly
 * afterwards all modules are started
 */
void ConfigManager::parseConfig(std::string fileName)
{
	lockGraph();
	Graph* oldGraph = graph;

	graph = new Graph();

	old_document = document;
	document = XMLDocument::parse_file(fileName);
	XMLElement* root = document->getRootNode();

	// consistency checks
	if (!root) {
		unlockGraph();
		THROWEXCEPTION("%s is an empty XML-Document!", fileName.c_str());
	}

	if (!root->matches("ipfixConfig")) {
		unlockGraph();
		THROWEXCEPTION("Root element does not match \"ipfixConfig\"."
			       " This is not a valid configuration file!");
	}

	/* process each root element node and add a new node (with its config
	 * attached to the node) to the graph
	 */
	XMLNode::XMLSet<XMLElement*> rootElements = root->getElementChildren();
	for (XMLNode::XMLSet<XMLElement*>::const_iterator it = rootElements.begin();
	     it != rootElements.end();
	     it++) {
		bool found = false;
		for (unsigned int i = 0; i < ARRAY_SIZE(configModules); i++) {
			if ((*it)->getName() == configModules[i]->getName()) {
				Cfg* cfg = configModules[i]->create(*it);

				// handle special modules
				SensorManagerCfg* smcfg = dynamic_cast<SensorManagerCfg*>(cfg);
				if (smcfg) {
					// SensorManager will not be connected to any modules, so its instance
					// needs to be started manually
					smcfg->setGraphIS(this);
					sensorManager = smcfg->getInstance();
				}

				graph->addNode(cfg);
				found = true;
			}
		}

		if (!found) {
			unlockGraph();
			msg(MSG_INFO, "Unknown cfg entry %s found", (*it)->getName().c_str());
		}
	}

	if (!oldGraph) { // this is the first config we have read
		Connector connector;
		graph->accept(&connector);
	} else {
		// first, connect the nodes on the new graph (but NOT the modules
		Connector connector(true, false);
		graph->accept(&connector);
		// now connect the modules reusing those from the old graph
		ReConnector reconnector(oldGraph);
		graph->accept(&reconnector);
	}

	// start the instances if not already running
	std::vector<CfgNode*> topoNodes = graph->topoSort();

	for (size_t i = 0; i < topoNodes.size(); i++) {
		Cfg* cfg = topoNodes[topoNodes.size() -1 -i]->getCfg();
		msg(MSG_INFO, "Starting module %s", cfg->getName().c_str());
		cfg->start(false);
	}

	if (old_document)
		delete old_document;

	// if there is an old graph, we did a reconfiguration. So now we have to delete the
	// old graph, but we can't delete the instances immediatly, because there is a small
	// chance that instances which got reused could still hold a reference to a instance we
	// want to delete right now.
	// => we use the deleter to delete the instances after a specific time has passed so we
	//    are safe that no-one holds a reference on the deleted modules anymore
	if (oldGraph)
		deleter.addGraph(oldGraph);

	unlockGraph();
}