/* * connection.cpp * * Copyright (c) 2004-2006,2008 Arnout Engelen * * This program 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. * * This program 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 program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, *USA. * */ #include #include #ifdef __APPLE__ #include #elif __FreeBSD__ #include #else #include #endif #include "connection.h" #include "nethogs.h" #include "process.h" ConnList connections; extern Process *unknownudp; void PackList::add(Packet *p) { if (content == NULL) { content = new PackListNode(new Packet(*p)); return; } if (content->val->time.tv_sec == p->time.tv_sec) { content->val->len += p->len; return; } /* store copy of packet, so that original may be freed */ content = new PackListNode(new Packet(*p), content); } /* sums up the total bytes used and removes 'old' packets */ u_int64_t PackList::sumanddel(timeval t) { u_int64_t retval = 0; PackListNode *current = content; PackListNode *previous = NULL; while (current != NULL) { // std::cout << "Comparing " << current->val->time.tv_sec << " <= " << // t.tv_sec - PERIOD << endl; if (current->val->time.tv_sec <= t.tv_sec - PERIOD) { if (current == content) content = NULL; else if (previous != NULL) previous->next = NULL; delete current; return retval; } retval += current->val->len; previous = current; current = current->next; } return retval; } /* packet may be deleted by caller */ Connection::Connection(Packet *packet) { assert(packet != NULL); sent_packets = new PackList(); recv_packets = new PackList(); sumSent = 0; sumRecv = 0; if (DEBUG) { std::cout << "New connection, with package len " << packet->len << std::endl; } if (packet->Outgoing()) { sumSent += packet->len; sent_packets->add(packet); refpacket = new Packet(*packet); } else { sumRecv += packet->len; recv_packets->add(packet); refpacket = packet->newInverted(); } connections.insert(this); lastpacket = packet->time.tv_sec; if (DEBUG) std::cout << "New reference packet created at " << refpacket << std::endl; } Connection::~Connection() { if (DEBUG) std::cout << "Deleting connection" << std::endl; auto r = connections.equal_range(this); for (auto it = r.first; it != r.second; ++it) { if (*it == this) { connections.erase(it); break; } } /* refpacket is not a pointer to one of the packets in the lists * so deleted */ delete (refpacket); if (sent_packets != NULL) delete sent_packets; if (recv_packets != NULL) delete recv_packets; } /* the packet will be freed by the calling code */ void Connection::add(Packet *packet) { lastpacket = packet->time.tv_sec; if (packet->Outgoing()) { if (DEBUG) { std::cout << "Outgoing: " << packet->len << std::endl; } sumSent += packet->len; sent_packets->add(packet); } else { if (DEBUG) { std::cout << "Incoming: " << packet->len << std::endl; } sumRecv += packet->len; if (DEBUG) { std::cout << "sumRecv now: " << sumRecv << std::endl; } recv_packets->add(packet); } } Connection *findConnectionWithMatchingSource(Packet *packet, short int packettype) { assert(packet->Outgoing()); ConnList *connList = NULL; switch (packettype) { case IPPROTO_TCP: { connList = &connections; break; } case IPPROTO_UDP: { connList = &unknownudp->connections; break; } } Packet p = packet->onlySource(); auto it = connList->lower_bound(&p); /* the reference packet is always outgoing */ if (it != connList->end() && packet->matchSource((*it)->refpacket)) { return *it; } return NULL; } Connection *findConnectionWithMatchingRefpacketOrSource(Packet *packet, short int packettype) { ConnList *connList = NULL; switch (packettype) { case IPPROTO_TCP: { connList = &connections; break; } case IPPROTO_UDP: { connList = &unknownudp->connections; break; } } auto it = connList->lower_bound(packet); /* the reference packet is always *outgoing* */ if (it != connList->end() && packet->match((*it)->refpacket)) { return *it; } return findConnectionWithMatchingSource(packet, packettype); } /* * finds connection to which this packet belongs. * a packet belongs to a connection if it matches * to its reference packet */ Connection *findConnection(Packet *packet, short int packettype) { if (packet->Outgoing()) return findConnectionWithMatchingRefpacketOrSource(packet, packettype); else { Packet *invertedPacket = packet->newInverted(); Connection *result = findConnectionWithMatchingRefpacketOrSource(invertedPacket, packettype); delete invertedPacket; return result; } } /* * Connection::sumanddel * * sums up the total bytes used * and removes 'old' packets. * * Returns sum of sent packages (by address) * sum of received packages (by address) */ void Connection::sumanddel(timeval t, u_int64_t *recv, u_int64_t *sent) { (*sent) = (*recv) = 0; *sent = sent_packets->sumanddel(t); *recv = recv_packets->sumanddel(t); }