]> git.stg.codes - stg.git/blobdiff - projects/stargazer/plugins/capture/divert_freebsd/divert_cap.cpp
Move projects back into subfolder.
[stg.git] / projects / stargazer / plugins / capture / divert_freebsd / divert_cap.cpp
diff --git a/projects/stargazer/plugins/capture/divert_freebsd/divert_cap.cpp b/projects/stargazer/plugins/capture/divert_freebsd/divert_cap.cpp
new file mode 100644 (file)
index 0000000..2898468
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ *    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+* Author : Boris Mikhailenko <stg34@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.13 $
+$Date: 2010/09/10 06:43:03 $
+*/
+
+#include "divert_cap.h"
+
+#include "stg/traffcounter.h"
+#include "stg/raw_ip_packet.h"
+#include "stg/common.h"
+
+#include <algorithm>
+#include <vector>
+
+#include <cstdio>
+#include <cstring>
+#include <cerrno>
+#include <cstdlib>
+#include <csignal>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#define BUFF_LEN (16384) /* max mtu -> lo=16436  TODO why?*/
+
+//-----------------------------------------------------------------------------
+struct DIVERT_DATA {
+int sock;
+short int port;
+char iface[10];
+};
+//-----------------------------------------------------------------------------
+pollfd pollddiv;
+DIVERT_DATA cddiv;  //capture data
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static DIVERT_CAP plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string DIVERT_CAP::GetVersion() const
+{
+return "cap_divert v.1.0";
+}
+//-----------------------------------------------------------------------------
+DIVERT_CAP::DIVERT_CAP()
+    : port(0),
+      disableForwarding(false),
+      nonstop(false),
+      isRunning(false),
+      traffCnt(NULL),
+      logger(STG::PluginLogger::get("cap_divert"))
+{
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::Start()
+{
+if (isRunning)
+    return 0;
+
+if (DivertCapOpen() < 0)
+    {
+    errorStr = "Cannot open socket!";
+    printfd(__FILE__, "Cannot open socket\n");
+    return -1;
+    }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+    {
+    errorStr = "Cannot create thread.";
+    logger("Cannot create thread.");
+    printfd(__FILE__, "Cannot create thread\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::Stop()
+{
+if (!isRunning)
+    return 0;
+
+DivertCapClose();
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25; i++)
+    {
+    if (!isRunning)
+        break;
+
+    struct timespec ts = {0, 200000000};
+    nanosleep(&ts, NULL);
+    }
+
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+    {
+    if (pthread_kill(thread, SIGINT))
+        {
+        errorStr = "Cannot kill thread.";
+        logger("Cannot send signal to thread.");
+        printfd(__FILE__, "Cannot kill thread\n");
+        return -1;
+        }
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * DIVERT_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+DIVERT_CAP * dc = static_cast<DIVERT_CAP *>(d);
+dc->isRunning = true;
+
+char buffer[STG::packetSize + 14];
+while (dc->nonstop)
+    {
+    STG::RawPacket rp;
+    dc->DivertCapRead(buffer, sizeof(buffer), NULL);
+
+    if (buffer[12] != 0x8)
+        continue;
+
+    memcpy(&rp.rawPacket, &buffer[14], STG::packetSize);
+
+    dc->traffCnt->process(rp);
+    }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapOpen()
+{
+memset(&pollddiv, 0, sizeof(pollddiv));
+memset(&cddiv, 0, sizeof(DIVERT_DATA));
+
+strcpy(cddiv.iface, "foo");
+cddiv.port = port;
+
+DivertCapOpen(0);
+pollddiv.events = POLLIN;
+pollddiv.fd = cddiv.sock;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapOpen(int)
+{
+int ret;
+cddiv.sock = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+if (cddiv.sock < 0)
+    {
+    errorStr = "Create divert socket error.";
+    logger("Cannot create a socket: %s", strerror(errno));
+    printfd(__FILE__, "Cannot create divert socket\n");
+    return -1;
+    }
+
+struct sockaddr_in divAddr;
+
+memset(&divAddr, 0, sizeof(divAddr));
+
+divAddr.sin_family = AF_INET;
+divAddr.sin_port = htons(cddiv.port);
+divAddr.sin_addr.s_addr = INADDR_ANY;
+
+ret = bind(cddiv.sock, (struct sockaddr *)&divAddr, sizeof(divAddr));
+
+if (ret < 0)
+    {
+    errorStr = "Bind divert socket error.";
+    logger("Cannot bind the scoket: %s", strerror(errno));
+    printfd(__FILE__, "Cannot bind divert socket\n");
+    return -1;
+    }
+
+return cddiv.sock;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface)
+{
+poll(&pollddiv, 1, -1);
+
+if (pollddiv.revents & POLLIN)
+    {
+    DivertCapRead(b, blen, iface, 0);
+    pollddiv.revents = 0;
+    return 0;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface, int)
+{
+static char buf[BUFF_LEN];
+static struct sockaddr_in divertaddr;
+static int bytes;
+static socklen_t divertaddrSize = sizeof(divertaddr);
+
+if ((bytes = recvfrom (cddiv.sock, buf, BUFF_LEN,
+                       0, (struct sockaddr*) &divertaddr, &divertaddrSize)) > 50)
+    {
+    memcpy(b + 14, buf, blen - 14);
+    b[12] = 0x8;
+
+    if (iface)
+        *iface = cddiv.iface;
+
+    if (!disableForwarding)
+        {
+        if (sendto(cddiv.sock, buf, bytes, 0, (struct sockaddr*)&divertaddr, divertaddrSize) < 0)
+            logger("sendto error: %s", strerror(errno));
+        }
+    }
+else
+    {
+    if (bytes < 0)
+        logger("recvfrom error: %s", strerror(errno));
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapClose()
+{
+close(cddiv.sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::ParseSettings()
+{
+int p;
+STG::ParamValue pv;
+std::vector<STG::ParamValue>::const_iterator pvi;
+
+pv.param = "Port";
+pvi = std::find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
+if (pvi == settings.moduleParams.end() || pvi->value.empty())
+    {
+    p = 15701;
+    }
+else if (ParseIntInRange(pvi->value[0], 1, 65535, &p))
+    {
+    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+    return -1;
+    }
+
+port = p;
+
+bool d = false;
+pv.param = "DisableForwarding";
+pvi = std::find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
+if (pvi == settings.moduleParams.end() || pvi->value.empty())
+    {
+    disableForwarding = false;
+    }
+else if (ParseYesNo(pvi->value[0], &d))
+    {
+    errorStr = "Cannot parse parameter \'DisableForwarding\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'DisableForwarding'\n");
+    return -1;
+    }
+
+disableForwarding = d;
+
+return 0;
+}
+//-----------------------------------------------------------------------------