⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipfix.cc

📁 网络流量采集及分析软件
💻 CC
字号:
/*! \file  ipfix.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:export data via ipfix$Id: ipfix.cc,v 1.2 2005/03/24 23:57:57 s_zander Exp $*/#include <sys/types.h>#include "stdincpp.h"#include "ConfigManager.h"#include "./ExportModule.h"#include "Rule.h"#include "ConfigParser.h"#include "ipfix.h"#include "ipfix_fields.h"#define MAX_CONN 16// defaultsconst int DEF_SOURCEID  = 12345;const string DEF_CHOST  = "localhost";const int DEF_PORT      = 6766;const int DEF_PROTO     = IPFIX_PROTO_TCP;const string DEF_MFILE  = DEF_SYSCONFDIR "/ipfix_mapping.txt";// list of templatestypedef map<string, ipfix_template_t*> templList_t;typedef map<string, ipfix_template_t*>::iterator templListIter_t; // map attributes by string to ipfix attribute numbertypedef map<string, unsigned short> attrMap_t;typedef map<string, unsigned short>::iterator attrMapIter_t;// per rule datatypedef struct {    ipfix_template_t *keyTmpl;    templList_t metricTmplList;    // connection    int conn;} exportRecord_t;typedef struct {    // ref counter    int ref;    // conn details    string chost;    int port, proto;    ipfix_t *ipfixh;} conn_t;// globalsint sourceid, proto;string mfile;attrMap_t attrMap;conn_t conns[MAX_CONN];// FIXME how to throw exceptions from inside the shared lib?void die(int code, char *fmt, ...){    va_list           args;    fprintf(stderr, "ipfix: ");    va_start(args, fmt);    vfprintf(stderr, fmt, args);    va_end(args);    fprintf(stderr, "\n");    exit(code);}// parse the attribute name to ipfix number mapppingvoid readMap(void){    int p1, p2;    string line;    ifstream in(mfile.c_str());        if (!in) {        die(1, "cannot access/read mapping file '%s'", mfile.c_str());    }    while (getline(in, line)) {        if ((line[0] != '#') && (!line.empty())) {            p1 = line.find_first_of(" \t");            p2 = line.find_first_not_of(" \t", p1);                     if ((p1 > 0) && (p2 > 0) && (p2 >= p1)) {                unsigned int num = atoi(line.substr(p2,line.length()-p2).c_str());                // look if this attribute exists                int c = 0;                int found = 0;                while (ipfix_fields[c].ftid != 0) {                    if (ipfix_fields[c].ftid == (int) num) {                        found = 1;                        break;                    }                    c++;                }                if (!found) {                    die(1, "no ipfix attribute with field id '%d' defined", num);                }                attrMap[line.substr(0, p1)] = num;            }        }    }#ifdef DEBUG2    for (attrMapIter_t i = attrMap.begin(); i != attrMap.end(); i++) {        cerr << i->first << "->" << i->second << endl;    }#endif}/* --------------------------- IPFIX xonnection functions ------------------- */void openConn(int conn, string chost, int port){    if (ipfix_open(&conns[conn].ipfixh, sourceid, IPFIX_VERSION_NF9) < 0) {        die(1, "ipfix_open() failed: %s", strerror(errno));    }        if (ipfix_add_collector(conns[conn].ipfixh, (char *) chost.c_str(), port, proto) < 0) {        die(1, "ipfix_add_collector() failed: %s", strerror(errno));    }        conns[conn].chost = chost;    conns[conn].port = port;    conns[conn].ref++; }void closeConn(int conn){      ipfix_close( conns[conn].ipfixh );    conns[conn].ref = 0;}void closeAllConn(){    for (int i=0; i<MAX_CONN; i++) {        if (conns[i].ref > 0) {            closeConn(i);        }    }}/* -------------------- initModule -------------------- */int initModule( ConfigManager *confMan ){    string sproto, chost;    int port;    if (!confMan->getValue("SourceID", "EXPORTER", "ipfix").empty()) {        sourceid = atoi(confMan->getValue("SourceID", "EXPORTER", "ipfix").c_str());    } else {        sourceid = DEF_SOURCEID;    }    if (!confMan->getValue("Collector", "EXPORTER", "ipfix").empty()) {        chost = confMan->getValue("Collector", "EXPORTER", "ipfix");    } else {        chost = DEF_CHOST;    }    if (!confMan->getValue("Port", "EXPORTER", "ipfix").empty()) {        port = atoi(confMan->getValue("Port", "EXPORTER", "ipfix").c_str());    } else {        port = DEF_PORT;    }    sproto = confMan->getValue("Protocol", "EXPORTER", "ipfix");    if (!sproto.empty()) {        if (sproto == "UDP") {            proto = IPFIX_PROTO_UDP;        } else if (sproto == "TCP") {            proto = IPFIX_PROTO_TCP;        }    } else {        proto = DEF_PROTO;    }    mfile = confMan->getValue("MappingFile", "EXPORTER", "ipfix");    if (mfile.empty()) {        mfile = DEF_MFILE;    }    // read ipfix attribute map    readMap();    // initalize connections    for (int i=0; i<MAX_CONN; i++) {        conns[i].ref = 0;    }    // open default connection    openConn(0, chost, port);    return 0;}/* -------------------- resetModule -------------------- */int resetModule(){    closeAllConn();        // open default connection    openConn(0, conns[0].chost, conns[0].port);    return 0;}/* -------------------- destroyModule -------------------- */int destroyModule(){    closeAllConn();    attrMap.clear();    return 0;}/* -------------------- initExportRec -------------------- */int initExportRec( configItemList_t conf, void **expRecord ){    string chost;    int port;    // mark that expRecord is first use    exportRecord_t *rec = new exportRecord_t;    rec->keyTmpl = NULL;    rec->conn = -1;    chost = conf.getValue("Collector");    if (chost.empty()) {        chost = conns[0].chost;    }    string portstr = conf.getValue("Port");    if (portstr.empty()) {        port = conns[0].port;    } else {        port = atoi(portstr.c_str());    }#ifdef DEBUG    cerr << "Trying " << chost << ":" << port << endl;#endif    // find and use existing connection    for (int i=0; i<MAX_CONN; i++) {        if ((conns[i].ref > 0) && (chost == conns[i].chost) && (port == conns[i].port)) {            conns[i].ref++;            rec->conn = i;#ifdef DEBUG            cerr << "ipfix: using connection: " << i << endl;#endif            break;        }    }    if (rec->conn < 0) {        // try open new connection        for (int i=0; i<MAX_CONN; i++) {            if (conns[i].ref == 0) {                openConn(i, chost, port);                rec->conn = i;#ifdef DEBUG                cerr << "ipfix: opening connection: " << i << endl;#endif                break;            }        }    }    if (rec->conn < 0) {        die(1, "can not open any more connections");    }    (exportRecord_t *) (*expRecord) = rec;        return 0;}/* -------------------- destroyExportRec -------------------- */int destroyExportRec( void *expRecord ){    exportRecord_t *rec = (exportRecord_t *)expRecord;    ipfix_release_template(rec->keyTmpl);    for (templListIter_t i = rec->metricTmplList.begin(); i != rec->metricTmplList.end(); i++) {        ipfix_release_template(i->second);    }        // decrement ref counter for connection    conns[rec->conn].ref--;    if (conns[rec->conn].ref == 0) {#ifdef DEBUG        cerr << "ipfix: Destroying connection: " << rec->conn << endl;#endif        // close        closeConn(rec->conn);    }        delete (exportRecord_t *) expRecord;        return 0;}/* -------------------- timeout -------------------- */int timeout( int id ){    // called by netmate if module has timers defined - in text_file module unused!    return 0;}/* ------------------- exportMetricData (local function) ------------------- */static int exportMetricData(exportRecord_t *rec, string taskName, string metricName,                             MetricData *mdata){    int nrows;    DataType_e type;    const char *exp_fields[64];    int types[64];    int lens[64];    int task_id;    const char *str;    unsigned int c, list;    int newFlow;    unsigned long long flowId;    mdata->initExport();    if (rec->keyTmpl == NULL) {        // create template for flow key                  // first flow id and task id        types[0] = IPFIX_FT_FLOWID;        lens[0] = 4;        types[1] = IPFIX_FT_TASKID;        lens[1] = 4;        c = 2;        while ((str = mdata->getNextFlowKeyLabel(&type)) != NULL) {            attrMapIter_t a = attrMap.find(str);            if (a != attrMap.end()) {                types[c] = a->second;                lens[c] = DataTypeSize[type];             } else {                die(1, "missing mapping for attribute '%s'", str);            }            c++;        }        if (ipfix_get_template_array(conns[rec->conn].ipfixh, &rec->keyTmpl, c, types, lens) < 0) {            die(1, "ipfix_get_template_array() failed to create flow key template: %s",                 strerror(errno));        }    }    list = 0;    while ((nrows = mdata->getNextList()) > 0) {        char buf[6];        ipfix_template_t *templ = NULL;        // find metric template for the metric and list        sprintf(buf, "%d", list);        string tmplID = metricName+string(buf);        templListIter_t t = rec->metricTmplList.find(tmplID);        if (t == rec->metricTmplList.end()) {            // create template for metric and list                       types[0] = IPFIX_FT_FLOWID;            lens[0] = 4;            c = 1;            while ((str = mdata->getNextFlowDataLabel(&type)) != NULL) {                attrMapIter_t a = attrMap.find(str);                if (a != attrMap.end()) {                    types[c] = a->second;                    lens[c] = DataTypeSize[type];                } else {                    die(1, "ipfix: missing mapping for attribute '%s'", str);                }                                  c++;            }            if (ipfix_get_template_array(conns[rec->conn].ipfixh, &templ, c, types, lens) < 0) {                die(1, "ipfix_get_template_array() failed to create metric template: %s",                     strerror(errno));            }            pair<templListIter_t, bool> res = rec->metricTmplList.insert(make_pair(tmplID, templ));        } else {            templ = t->second;        }        while ((nrows = mdata->getNextFlow(&flowId, &newFlow)) > -1) {            if (newFlow && (nrows > 0)) {                // export flow key                                // first flow id	        unsigned long truncFlowId = (unsigned long) flowId;                exp_fields[0] = (char *) &truncFlowId;                // second task id                // FIXME: change to string type                task_id = atoi(taskName.c_str());                exp_fields[1] = (char *) &task_id;                                // finally all flow key values                c = 2;                while((str = mdata->getNextFlowKey(&type)) != NULL) {                    if (c >= sizeof(exp_fields)/sizeof(exp_fields[0])) {                        die(1, "only %d fields supported per IPFIX record",                             sizeof(exp_fields)/sizeof(exp_fields[0]));                    }                    exp_fields[c] = str;                    c++;                }                                if (ipfix_export_array(conns[rec->conn].ipfixh, rec->keyTmpl, c, (void**) &exp_fields) < 0) {                    die(1, "ipfix_export() flow key failed: %s", strerror(errno));                }            }                        for (int i=0; i<nrows; i++) {                // export flow data                // first the flow number                exp_fields[0] = (char *) &flowId;                c = 1;                while ((str = mdata->getNextFlowDataRow(&type)) != NULL) {                    if (c >= sizeof(exp_fields)/sizeof(exp_fields[0])) {                        die(1, "only %d fields supported per IPFIX record",                             sizeof(exp_fields)/sizeof(exp_fields[0]));                    }                    exp_fields[c] = str;                     c++;                }                if (ipfix_export_array(conns[rec->conn].ipfixh, templ, c, (void**) &exp_fields) < 0) {                    die(1, "ipfix_export() metric data failed: %s", strerror(errno));                }            }        }        list++;    }    return 0;}/* -------------------- exportData (part of export API) -------------------- */int exportData( FlowRecord *frec, void *expData ) {    exportRecord_t *rec;    MetricData *mdata;    int result = 0;#ifdef PROFILING    unsigned long long ini = PerfTimer::readTSC();#endif    rec = (exportRecord_t *)expData;#ifdef DEBUG    cerr << "ipfix::exportData (rule='" << frec->getRuleName() << "')" << endl;#endif    // data from multiple packet proc modules can be in one FlowRecord    while ((mdata = frec->getNextData()) != NULL) {#ifdef DEBUG        cerr << "export from proc module: " << mdata->getModName() << endl;#endif        result += exportMetricData(rec, frec->getRuleName(), mdata->getModName(), mdata);    }    ipfix_export_flush(conns[rec->conn].ipfixh);    #ifdef PROFILING    {        unsigned long long end = PerfTimer::readTSC();        cerr << "ipfix::exportData took "             << PerfTimer::ticks2ns(end - ini)/1000             << " us" << endl;     }#endif    return result;}	char* getErrorMsg( int ){    return "200";}char* getModuleInfo( int i ){    return "201";}timers_t* getTimers(){    return NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -