|
- //////////////////////////////////////////////////////////////////////
- // IP traffic analyzer - data objects
- // Written by Jonathan A. Foster <ChipMaster@YeOlPiShack.net>
- // Started April 23rd, 2021
- // Copyright JF Possibilities, Inc. All rights reserved.
- //////////////////////////////////////////////////////////////////////
- #include <arpa/inet.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdexcept>
- #include <iostream>
- #include "data.h"
-
-
-
- //////////////////////////////////////////////////////////////////////
- // Utils
- //////////////////////////////////////////////////////////////////////
-
- std::string ipv6opt(const std::string &addr) {
- in6_addr buf;
- char s[256];
-
- if(inet_pton(AF_INET6, addr.c_str(), &buf)<1) throw
- std::runtime_error("ipv6opt: inet_pton() says '"+addr+"' is not a valid IPv6 address");
- if(!inet_ntop(AF_INET6, &buf, s, 255)) throw // should never happen
- std::runtime_error("ipv6opt: inet_ntop() refused to convert the address back");
- return std::string(s);
- }
-
-
-
- int addr_wild_comp(const std::string &str1, const std::string &str2) {
- int spre1=0, spre2=0;
-
- if(str1=="*" || str2=="*") return 0;
- if(str1!="" && (str1.end()[-1]=='.' || str1.end()[-1]==':')) spre1=str1.size();
- if(str2!="" && (str2.end()[-1]=='.' || str2.end()[-1]==':')) spre2=str2.size();
- if(spre2>spre1) spre1=spre2;
- if(spre1) return strncmp(str1.c_str(), str2.c_str(), spre1);
- else if(str1<str2) return -1;
- else if(str1>str2) return 1;
- return 0;
- }
-
-
-
- //////////////////////////////////////////////////////////////////////
- // Conn
- //////////////////////////////////////////////////////////////////////
-
- void Conn::clear() {
- us = them = name = protocol = "";
- in=false;
- us_port = them_port = 0;
- }
-
-
-
- void Conn::compact() {
- if(us.find(':')!=us.npos) us=ipv6opt(us);
- if(them.find(':')!=us.npos) them=ipv6opt(them);
- }
-
-
-
- void Conn::swap() {
- std::string s;
- int x;
-
- s = us;
- us = them;
- them =s;
-
- x = us_port;
- us_port = them_port;
- them_port = x;
-
- in=!in;
- }
-
-
-
- Conn &Conn::operator=(const Splits &sp) {
- int x;
-
- clear();
- for(x=0; x<sp.count; x++) {
- if(!strncmp(sp.fields[x], "SRC=", 4)) {
- us = sp.fields[x]+4;
- continue;
- }
- if(!strncmp(sp.fields[x], "DST=", 4)) {
- them = sp.fields[x]+4;
- continue;
- }
- if(!strncmp(sp.fields[x], "SPT=", 4)) {
- us_port = atoi(sp.fields[x]+4);
- continue;
- }
- if(!strncmp(sp.fields[x], "DPT=", 4)) {
- them_port = atoi(sp.fields[x]+4);
- continue;
- }
- if(!strncmp(sp.fields[x], "TYPE=", 5) && protocol=="ICMP") {
- us_port = them_port = atoi(sp.fields[x]+5);
- continue;
- }
- if(!strncmp(sp.fields[x], "PROTO=", 6))
- protocol = sp.fields[x]+6;
- }
- }
-
-
-
- // TODO: does < > have any actual meaning in this context?
- int Conn::cmp(const Conn >r) const {
- int r;
-
- if(r = addr_wild_comp(us, gtr.us)) return r;
- // TODO: auto-wildcard port based on in?
- if(us_port && gtr.us_port) { // 0 = no comparison wildcard
- if(us_port<gtr.us_port) return -1;
- if(us_port>gtr.us_port) return 1;
- }
- if(r = addr_wild_comp(them, gtr.them)) return r;
- if(them_port && gtr.them_port) { // 0 = no comparison wildcard
- if(them_port<gtr.them_port) return -1;
- if(them_port>gtr.them_port) return 1;
- }
- // TODO: do we want to consider the name?
- if(name!="*" && gtr.name!="*") {
- if(name<gtr.name) return -1;
- if(name>gtr.name) return 1;
- }
- if(protocol<gtr.protocol) return -1;
- if(protocol>gtr.protocol) return 1;
- if(in<gtr.in) return -1;
- if(in>gtr.in) return 1;
- return 0;
- }
-
-
-
- std::ostream &operator<<(std::ostream &out, const Conn &c) {
- out << c.us
- << ( c.in ? " <- " : " -> " )
- << c.them
- << " " << c.protocol
- << "[" << ( c.in ? c.us_port : c.them_port ) << "] "
- << c.name;
- return out;
- }
-
-
-
- const Splits &operator>>(const Splits &tsv, Conn &conn) {
- if(tsv.count<7) throw std::runtime_error("Conn=TSV: too few columns");
- conn.clear();
- conn.us = tsv[0];
- conn.us_port = atoi(tsv.fields[1]);
- conn.them = tsv[2];
- conn.them_port = atoi(tsv.fields[3]);
- conn.name = tsv[4];
- conn.protocol = tsv[5];
- conn.in = tsv[6]=="1";
- return tsv;
- }
-
-
-
- //////////////////////////////////////////////////////////////////////
- // ConnList
- //////////////////////////////////////////////////////////////////////
-
- int ConnList::find(Conn &needle) {
- int r;
-
- for(r=0; r<size(); r++) if((*this)[r]==needle) return r;
- return -1;
- }
|