Included fixes and changes from change I16970c3dedd9071c970523a478fbf35e009d13ef
as commented by Jan Olszak and Rafal Krypa
refer to https://review.tizen.org/gerrit/#/c/44086/ for details
Removed const qualifiers on method return types.
Removed unused parameters from method definitions.
Change-Id: Ic03f4b35cdb476005749d2c93a413a83c09490fd
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
PROJECT (nether)
INCLUDE (FindPkgConfig)
-SET (CMAKE_CXX_FLAGS "-std=c++11")
+IF (CMAKE_BUILD_TYPE MATCHES DEBUG)
+ SET (CMAKE_CXX_FLAGS "-g -Wall -Wextra -std=c++11")
+ELSE ()
+ SET (CMAKE_CXX_FLAGS "-O3 -fomit-frame-pointer -std=c++11")
+ENDIF (CMAKE_BUILD_TYPE MATCHES DEBUG)
+
SET (CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
IF (NOT DEFINED SYSCONF_INSTALL_DIR)
ENDIF (NOT DEFINED SYSCONF_INSTALL_DIR)
IF (NOT DEFINED SYSTEMD_UNIT_DIR)
- SET(SYSTEMD_UNIT_DIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system")
+ SET(SYSTEMD_UNIT_DIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system")
ENDIF (NOT DEFINED SYSTEMD_UNIT_DIR)
ADD_SUBDIRECTORY (src)
#include "logger/backend.hpp"
-namespace logger {
+namespace logger
+{
-class FileBackend : public LogBackend {
-public:
- FileBackend(const std::string &filePath) : mfilePath(filePath) {}
- void log(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func,
- const std::string& message) override;
-private:
- std::string mfilePath;
-};
+ class FileBackend : public LogBackend
+ {
+ public:
+ FileBackend(const std::string &filePath) : mfilePath(filePath) {}
+ void log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message) override;
+ private:
+ std::string mfilePath;
+ };
} // namespace logger
#include "logger/backend.hpp"
-namespace logger {
+namespace logger
+{
-/**
- * systemd journal logging backend
- */
-class SystemdJournalBackend : public LogBackend {
-public:
- void log(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func,
- const std::string& message) override;
-};
+ /**
+ * systemd journal logging backend
+ */
+ class SystemdJournalBackend : public LogBackend
+ {
+ public:
+ void log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message) override;
+ };
} // namespace logger
#include "logger/backend.hpp"
-namespace logger {
+namespace logger
+{
-/**
- * Null logging backend
- */
-class NullLogger : public LogBackend {
-public:
- void log(LogLevel /*logLevel*/,
- const std::string& /*file*/,
- const unsigned int& /*line*/,
- const std::string& /*func*/,
- const std::string& /*message*/) override {}
-};
+ /**
+ * Null logging backend
+ */
+ class NullLogger : public LogBackend
+ {
+ public:
+ void log(LogLevel /*logLevel*/,
+ const std::string& /*file*/,
+ const unsigned int& /*line*/,
+ const std::string& /*func*/,
+ const std::string& /*message*/) override {}
+ };
} // namespace logger
#include "logger/backend.hpp"
-namespace logger {
+namespace logger
+{
-/**
- * Stderr logging backend
- */
-class StderrBackend : public LogBackend {
-public:
- StderrBackend(const bool _useColours=true) : useColours(_useColours) {}
- void log(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func,
- const std::string& message) override;
-private:
- bool useColours;
-};
+ /**
+ * Stderr logging backend
+ */
+ class StderrBackend : public LogBackend
+ {
+ public:
+ StderrBackend(const bool _useColours=true) : useColours(_useColours) {}
+ void log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message) override;
+ private:
+ bool useColours;
+ };
} // namespace logger
#include "logger/backend.hpp"
-namespace logger {
+namespace logger
+{
-class SyslogBackend : public LogBackend {
-public:
- void log(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func,
- const std::string& message) override;
-};
+ class SyslogBackend : public LogBackend
+ {
+ public:
+ void log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message) override;
+ };
} // namespace logger
#include <string>
-namespace logger {
-
-/**
- * Abstract class for logger
- */
-class LogBackend {
-public:
- virtual void log(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func,
- const std::string& message) = 0;
- virtual ~LogBackend() {}
-};
+namespace logger
+{
+
+ /**
+ * Abstract class for logger
+ */
+ class LogBackend
+ {
+ public:
+ virtual void log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message) = 0;
+ virtual ~LogBackend() {}
+ };
} // namespace logger
#include <string>
-namespace logger {
-
-enum class Color : unsigned int {
- DEFAULT = 0,
- BLACK = 90,
- RED = 91,
- GREEN = 92,
- YELLOW = 93,
- BLUE = 94,
- MAGENTA = 95,
- CYAN = 96,
- WHITE = 97
-};
-
-enum class Attributes : unsigned int {
- DEFAULT = 0,
- BOLD = 1
-};
-
-std::string getConsoleEscapeSequence(Attributes attr, Color color);
+namespace logger
+{
+
+ enum class Color : unsigned int
+ {
+ DEFAULT = 0,
+ BLACK = 90,
+ RED = 91,
+ GREEN = 92,
+ YELLOW = 93,
+ BLUE = 94,
+ MAGENTA = 95,
+ CYAN = 96,
+ WHITE = 97
+ };
+
+ enum class Attributes : unsigned int
+ {
+ DEFAULT = 0,
+ BOLD = 1
+ };
+
+ std::string getConsoleEscapeSequence(Attributes attr, Color color);
} // namespace logger
#include <string>
-namespace logger {
-
-class LogFormatter {
-public:
- static unsigned int getCurrentThread(void);
- static std::string getCurrentTime(void);
- static std::string getConsoleColor(LogLevel logLevel);
- static std::string getDefaultConsoleColor(void);
- static std::string stripProjectDir(const std::string& file,
- const std::string& rootDir);
- static std::string getHeader(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func);
-};
+namespace logger
+{
+
+ class LogFormatter
+ {
+ public:
+ static unsigned int getCurrentThread(void);
+ static std::string getCurrentTime(void);
+ static std::string getConsoleColor(LogLevel logLevel);
+ static std::string getDefaultConsoleColor(void);
+ static std::string stripProjectDir(const std::string& file,
+ const std::string& rootDir);
+ static std::string getHeader(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func);
+ };
} // namespace logger
#include <string>
-namespace logger {
-
-enum class LogLevel {
- TRACE,
- DEBUG,
- INFO,
- WARN,
- ERROR,
- HELP
-};
-
-/**
- * @param logLevel LogLevel
- * @return std::sting representation of the LogLevel value
- */
-std::string toString(const LogLevel logLevel);
-
-/**
- * @param level string representation of log level
- * @return parsed LogLevel value
- */
-LogLevel parseLogLevel(const std::string& level);
+namespace logger
+{
+
+ enum class LogLevel
+ {
+ TRACE,
+ DEBUG,
+ INFO,
+ WARN,
+ ERROR,
+ HELP
+ };
+
+ /**
+ * @param logLevel LogLevel
+ * @return std::sting representation of the LogLevel value
+ */
+ std::string toString(const LogLevel logLevel);
+
+ /**
+ * @param level string representation of log level
+ * @return parsed LogLevel value
+ */
+ LogLevel parseLogLevel(const std::string& level);
} // namespace logger
#include <string>
#include <sstream>
-namespace logger {
-
-class SStreamWrapper
+namespace logger
{
-public:
- operator std::string() const;
- template <typename T>
- SStreamWrapper& operator<<(const T& b)
- {
- this->mSStream << b;
- return *this;
- }
+ class SStreamWrapper
+ {
+ public:
+ operator std::string() const;
-private:
- std::ostringstream mSStream;
-};
+ template <typename T>
+ SStreamWrapper& operator<<(const T& b)
+ {
+ this->mSStream << b;
+ return *this;
+ }
-/**
- * Class specifically for scope debug logging. Should be used at the beggining of a scope.
- * Constructor marks scope enterance, destructor marks scope leave.
- */
-class LoggerScope
-{
-public:
- LoggerScope(const std::string& file,
- const unsigned int line,
- const std::string& func,
- const std::string& message,
- const std::string& rootDir);
- ~LoggerScope();
+ private:
+ std::ostringstream mSStream;
+ };
+
+ /**
+ * Class specifically for scope debug logging. Should be used at the beggining of a scope.
+ * Constructor marks scope enterance, destructor marks scope leave.
+ */
+ class LoggerScope
+ {
+ public:
+ LoggerScope(const std::string& file,
+ const unsigned int line,
+ const std::string& func,
+ const std::string& message,
+ const std::string& rootDir);
+ ~LoggerScope();
-private:
- const std::string mFile;
- const unsigned int mLine;
- const std::string mFunc;
- const std::string mMessage;
- const std::string mRootDir;
-};
+ private:
+ const std::string mFile;
+ const unsigned int mLine;
+ const std::string mFunc;
+ const std::string mMessage;
+ const std::string mRootDir;
+ };
} // namespace logger
#define PROJECT_SOURCE_DIR ""
#endif
-namespace logger {
+namespace logger
+{
-class LogBackend;
+ class LogBackend;
-class Logger {
-public:
- static void logMessage(LogLevel logLevel,
- const std::string& message,
- const std::string& file,
- const unsigned int line,
- const std::string& func,
- const std::string& rootDir);
+ class Logger
+ {
+ public:
+ static void logMessage(LogLevel logLevel,
+ const std::string& message,
+ const std::string& file,
+ const unsigned int line,
+ const std::string& func,
+ const std::string& rootDir);
- static void setLogLevel(const LogLevel level);
- static void setLogLevel(const std::string& level);
- static LogLevel getLogLevel(void);
- static void setLogBackend(LogBackend* pBackend);
-};
+ static void setLogLevel(const LogLevel level);
+ static void setLogLevel(const std::string& level);
+ static LogLevel getLogLevel(void);
+ static void setLogBackend(LogBackend* pBackend);
+ };
} // namespace logger
static const std::string cynaraErrorCodeToString(int cynaraErrorCode)
{
- char errorString[512];
- int ret;
+ char errorString[512];
+ int ret;
- if ((ret = cynara_strerror(cynaraErrorCode, errorString, 512)) == CYNARA_API_SUCCESS)
- return (std::string(errorString, strlen(errorString)));
- else
- return ("Failed to get error string representation, code="+ret);
+ if((ret = cynara_strerror(cynaraErrorCode, errorString, 512)) == CYNARA_API_SUCCESS)
+ return (std::string(errorString, strlen(errorString)));
+ else
+ return ("Failed to get error string representation, code="+ret);
}
class NetherManager;
class NetherCynaraBackend : public NetherPolicyBackend
{
- public:
- NetherCynaraBackend(const NetherConfig &netherConfig);
- ~NetherCynaraBackend();
- const bool initialize();
- const bool isValid();
- const bool enqueueVerdict (const NetherPacket &packet);
- const bool processEvents();
- const int getDescriptor();
- const NetherDescriptorStatus getDescriptorStatus();
- void setCynaraDescriptor(const int _currentCynaraDescriptor, const NetherDescriptorStatus _currentCynaraDescriptorStatus);
- void setCynaraVerdict(cynara_check_id checkId, int cynaraResult);
- static void statusCallback(int oldFd, int newFd, cynara_async_status status, void *data);
- static void checkCallback(cynara_check_id check_id, cynara_async_call_cause cause, int response, void *data);
+ public:
+ NetherCynaraBackend(const NetherConfig &netherConfig);
+ ~NetherCynaraBackend();
+ bool initialize();
+ bool enqueueVerdict(const NetherPacket &packet);
+ bool processEvents();
+ int getDescriptor();
+ NetherDescriptorStatus getDescriptorStatus();
+ void setCynaraDescriptor(const int _currentCynaraDescriptor, const NetherDescriptorStatus _currentCynaraDescriptorStatus);
+ void setCynaraVerdict(cynara_check_id checkId, int cynaraResult);
+ static void statusCallback(int oldFd, int newFd, cynara_async_status status, void *data);
+ static void checkCallback(cynara_check_id check_id, cynara_async_call_cause cause, int response, void *data);
- private:
- cynara_async *cynaraContext;
- NetherDescriptorStatus currentCynaraDescriptorStatus;
- int currentCynaraDescriptor;
- std::vector<u_int32_t> responseQueue;
- int cynaraLastResult;
+ private:
+ cynara_async *cynaraContext;
+ NetherDescriptorStatus currentCynaraDescriptorStatus;
+ int currentCynaraDescriptor;
+ std::vector<u_int32_t> responseQueue;
+ int cynaraLastResult;
};
#endif // HAVE_CYNARA
bool runAsDaemon()
{
- pid_t pid = fork();
+ pid_t pid = fork();
- if (pid == -1)
- return (false);
- else if (pid != 0)
- exit (0);
+ if(pid == -1)
+ return (false);
+ else
+ if(pid != 0)
+ exit(0);
- if (setsid() == -1)
- return (false);
+ if(setsid() == -1)
+ return (false);
- /* Catch, ignore and handle signals */
- signal(SIGCHLD, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
+ /* Catch, ignore and handle signals */
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
- pid = fork();
+ pid = fork();
- /*
- * Fork a second child and exit immediately to prevent zombies. This
- * causes the second child process to be orphaned, making the init
- * process responsible for its cleanup. And, since the first child is
- * a session leader without a controlling terminal, it's possible for
- * it to acquire one by opening a terminal in the future (System V-
- * based systems). This second fork guarantees that the child is no
- * longer a session leader, preventing the daemon from ever acquiring
- * a controlling terminal.
- */
- if (pid == -1)
- return (false);
- else if (pid != 0)
- exit(0);
+ /*
+ * Fork a second child and exit immediately to prevent zombies. This
+ * causes the second child process to be orphaned, making the init
+ * process responsible for its cleanup. And, since the first child is
+ * a session leader without a controlling terminal, it's possible for
+ * it to acquire one by opening a terminal in the future (System V-
+ * based systems). This second fork guarantees that the child is no
+ * longer a session leader, preventing the daemon from ever acquiring
+ * a controlling terminal.
+ */
+ if(pid == -1)
+ return (false);
+ else
+ if(pid != 0)
+ exit(0);
- if (chdir("/") == -1)
- return (false);
+ if(chdir("/") == -1)
+ return (false);
- umask(0);
+ umask(0);
- /** Close all open file descriptors */
- for (int x = sysconf(_SC_OPEN_MAX); x>0; x--)
- {
- close (x);
- }
+ /** Close all open file descriptors */
+ for(int x = sysconf(_SC_OPEN_MAX); x>0; x--)
+ {
+ close(x);
+ }
- if (open("/dev/null",O_RDONLY) == -1)
- return (false);
+ if(open("/dev/null",O_RDONLY) == -1)
+ return (false);
- if (open("/dev/null",O_WRONLY) == -1)
- return (false);
+ if(open("/dev/null",O_WRONLY) == -1)
+ return (false);
- if (open("/dev/null",O_RDWR) == -1)
- return (false);
+ if(open("/dev/null",O_RDWR) == -1)
+ return (false);
- return (true);
+ return (true);
}
class NetherDummyBackend : public NetherPolicyBackend
{
- public:
- NetherDummyBackend(const NetherConfig &netherConfig)
- : NetherPolicyBackend(netherConfig) {}
- ~NetherDummyBackend() {}
-
- const bool isValid()
- {
- return (true);
- }
-
- const bool initialize()
- {
- return (true);
- }
-
- const bool enqueueVerdict(const NetherPacket &packet)
- {
- return (castVerdict (packet, netherConfig.defaultVerdict));
- }
-
- const bool processEvents()
- {
- return (true);
- }
+ public:
+ NetherDummyBackend(const NetherConfig &netherConfig)
+ : NetherPolicyBackend(netherConfig) {}
+ ~NetherDummyBackend() {}
+
+ bool initialize()
+ {
+ return (true);
+ }
+
+ bool enqueueVerdict(const NetherPacket &packet)
+ {
+ return (castVerdict(packet, netherConfig.defaultVerdict));
+ }
+
+ bool processEvents()
+ {
+ return (true);
+ }
};
#endif
enum PolicyFileTokens
{
- uidT,
- gidT,
- secctxT,
- verdictT
+ uidToken,
+ gidToken,
+ secctxToken,
+ verdictToken
};
struct PolicyEntry
{
- uid_t uid;
- gid_t gid;
- std::string securityContext;
- NetherVerdict verdict;
+ uid_t uid;
+ gid_t gid;
+ std::string securityContext;
+ NetherVerdict verdict;
};
static const std::string dumpPolicyEntry(const PolicyEntry &entry)
{
- std::stringstream stream;
- stream << "UID=";
- if (entry.uid == NETHER_INVALID_UID) stream << "*"; else stream << entry.uid;
- stream << " GID=";
- if (entry.gid == NETHER_INVALID_GID) stream << "*"; else stream << entry.gid;
- stream << " SECCTX=";
- if (entry.securityContext.empty()) stream << "*"; else stream << entry.securityContext;
- stream << " VERDICT=";
- stream << verdictToString(entry.verdict);
+ std::stringstream stream;
+ stream << "UID=";
+ if(entry.uid == NETHER_INVALID_UID)
+ stream << "*";
+ else
+ stream << entry.uid;
+ stream << " GID=";
+ if(entry.gid == NETHER_INVALID_GID)
+ stream << "*";
+ else stream << entry.gid;
+ stream << " SECCTX=";
+ if(entry.securityContext.empty())
+ stream << "*";
+ else
+ stream << entry.securityContext;
+ stream << " VERDICT=";
+ stream << verdictToString(entry.verdict);
- return (stream.str());
+ return (stream.str());
}
class NetherFileBackend : public NetherPolicyBackend
{
- public:
- NetherFileBackend(const NetherConfig &netherConfig);
- ~NetherFileBackend();
- const bool isValid();
- const bool initialize();
- const bool reload();
- const bool enqueueVerdict(const NetherPacket &packet);
- const bool parsePolicyFile(std::ifstream &policyFile);
- const bool processEvents() { return (true); }
- std::vector<std::string> split(const std::string &str, const std::string &delim);
- private:
- std::vector<PolicyEntry> policy;
+ public:
+ NetherFileBackend(const NetherConfig &netherConfig);
+ ~NetherFileBackend();
+ bool initialize();
+ bool reload();
+ bool enqueueVerdict(const NetherPacket &packet);
+ bool parsePolicyFile(std::ifstream &policyFile);
+ bool processEvents() { return (true); }
+ std::vector<std::string> split(const std::string &str, const std::string &delim);
+ private:
+ std::vector<PolicyEntry> policy;
};
#endif
class NetherManager : public NetherVerdictListener, public NetherProcessedPacketListener
{
- public:
- NetherManager(const NetherConfig &_netherConfig);
- ~NetherManager();
- const bool initialize();
- const bool process();
- NetherConfig &getConfig();
- static NetherPolicyBackend *getPolicyBackend(const NetherConfig &netherConfig, const bool primary = true);
- bool verdictCast (const u_int32_t packetId, const NetherVerdict verdict);
- void packetReceived (const NetherPacket &packet);
- const bool restoreRules();
+ public:
+ NetherManager(const NetherConfig &_netherConfig);
+ ~NetherManager();
+ bool initialize();
+ bool process();
+ NetherConfig &getConfig();
+ static NetherPolicyBackend *getPolicyBackend(const NetherConfig &netherConfig, const bool primary = true);
+ bool verdictCast(const u_int32_t packetId, const NetherVerdict verdict);
+ void packetReceived(const NetherPacket &packet);
+ bool restoreRules();
- private:
- static const bool isCommandAvailable(const std::string &command);
- void handleSignal();
- const bool handleNetlinkpacket();
- void setupSelectSockets(fd_set &watchedReadDescriptorsSet, fd_set &watchedWriteDescriptorsSet, struct timeval &timeoutSpecification);
- std::unique_ptr <NetherPolicyBackend> netherPrimaryPolicyBackend;
- std::unique_ptr <NetherPolicyBackend> netherBackupPolicyBackend;
- std::unique_ptr <NetherPolicyBackend> netherFallbackPolicyBackend;
- std::unique_ptr <NetherNetlink> netherNetlink;
- NetherConfig netherConfig;
- int netlinkDescriptor;
- int backendDescriptor;
- int signalDescriptor;
+ private:
+ static bool isCommandAvailable(const std::string &command);
+ void handleSignal();
+ bool handleNetlinkpacket();
+ void setupSelectSockets(fd_set &watchedReadDescriptorsSet, fd_set &watchedWriteDescriptorsSet, struct timeval &timeoutSpecification);
+ std::unique_ptr <NetherPolicyBackend> netherPrimaryPolicyBackend;
+ std::unique_ptr <NetherPolicyBackend> netherBackupPolicyBackend;
+ std::unique_ptr <NetherPolicyBackend> netherFallbackPolicyBackend;
+ std::unique_ptr <NetherNetlink> netherNetlink;
+ NetherConfig netherConfig;
+ int netlinkDescriptor;
+ int backendDescriptor;
+ int signalDescriptor;
#ifdef HAVE_AUDIT
- int auditDescriptor;
+ int auditDescriptor;
#endif // HAVE_AUDIT
- sigset_t signalMask;
+ sigset_t signalMask;
};
#endif
* @brief netlink handler class for nether
*/
-#ifndef NETHER_NETLINK_H\r
-#define NETHER_NETLINK_H\r
-\r
-#include "nether_Types.h"\r
+#ifndef NETHER_NETLINK_H
+#define NETHER_NETLINK_H
+
+#include "nether_Types.h"
#include "nether_Utils.h"
-\r
-class NetherManager;\r
-\r
-class NetherNetlink : public NetherPacketProcessor\r
-{\r
- public:\r
- NetherNetlink(NetherConfig &netherConfig);\r
- ~NetherNetlink();\r
- const bool initialize();
- const bool reload();\r
- static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data);
- const bool processPacket (char *packetBuffer, const int packetReadSize);
- void setVerdict(const u_int32_t packetId, const NetherVerdict verdict);
- int getDescriptor();\r
- const bool isValid();
-\r
- protected:
- NetherPacket *processedPacket;
-\r
- private:\r
- struct nfq_q_handle *queueHandle;\r
- struct nfq_handle *nfqHandle;
- struct nlif_handle *nlif;\r
- int fd;\r
- uint32_t queue;\r
-};\r
-\r
-#endif // NETLINK_H_INCLUDED\r
+
+class NetherManager;
+
+class NetherNetlink : public NetherPacketProcessor
+{
+ public:
+ NetherNetlink(NetherConfig &netherConfig);
+ ~NetherNetlink();
+ bool initialize();
+ bool reload();
+ static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data);
+ bool processPacket(char *packetBuffer, const int packetReadSize);
+ void setVerdict(const u_int32_t packetId, const NetherVerdict verdict);
+ int getDescriptor();
+
+ protected:
+ NetherPacket *processedPacket;
+
+ private:
+ struct nfq_q_handle *queueHandle;
+ struct nfq_handle *nfqHandle;
+ struct nlif_handle *nlif;
+ uint32_t queue;
+};
+
+#endif // NETLINK_H_INCLUDED
class NetherPolicyBackend : public NetherVerdictCaster
{
- public:
- NetherPolicyBackend(const NetherConfig &_netherConfig) : netherConfig(_netherConfig) {}
- virtual ~NetherPolicyBackend() {}
- virtual const bool enqueueVerdict (const NetherPacket &packet) = 0;
- virtual const bool initialize() = 0;
- virtual const bool reload() { return (true); };
- virtual const bool isValid() = 0;
- virtual const int getDescriptor() { return (-1); }
- virtual const NetherDescriptorStatus getDescriptorStatus() { return (NetherDescriptorStatus::unknownStatus); }
- virtual const bool processEvents() = 0;
+ public:
+ NetherPolicyBackend(const NetherConfig &_netherConfig) : netherConfig(_netherConfig) {}
+ virtual ~NetherPolicyBackend() {}
+ virtual bool enqueueVerdict(const NetherPacket &packet) = 0;
+ virtual bool initialize() = 0;
+ virtual bool reload()
+ {
+ return (true);
+ };
+ virtual int getDescriptor()
+ {
+ return (-1);
+ }
+ virtual NetherDescriptorStatus getDescriptorStatus()
+ {
+ return (NetherDescriptorStatus::unknownStatus);
+ }
+ virtual bool processEvents() = 0;
- protected:
- NetherConfig netherConfig;
+ protected:
+ NetherConfig netherConfig;
};
#endif
#include <getopt.h>
#include <assert.h>
#include <netinet/in.h>
+#include <netdb.h>
+#include <linux/types.h>
#include <sys/signalfd.h>
#include <linux/types.h>
#include <linux/netfilter.h>
#if defined(HAVE_AUDIT)
- #include <libaudit.h>
+#include <libaudit.h>
#endif // HAVE_AUDIT
#include <libnetfilter_queue/libnetfilter_queue.h>
#include "logger/backend-syslog.hpp"
#if defined(HAVE_SYSTEMD_JOURNAL)
- #include "logger/backend-journal.hpp"
+#include "logger/backend-journal.hpp"
#endif // HAVE_SYSTEMD_JOURNAL
#if defined(HAVE_CYNARA)
- #define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::cynaraBackend
- #define NETHER_BACKUP_BACKEND NetherPolicyBackendType::fileBackend
+#define NETHER_PRIMARY_BACKEND NetherPolicyBackendType::cynaraBackend
+#define NETHER_BACKUP_BACKEND NetherPolicyBackendType::fileBackend
#else
- #define NETHER_PRIMARY_BACKEND fileBackend
- #define NETHER_BACKUP_BACKEND dummyBackend
+#define NETHER_PRIMARY_BACKEND fileBackend
+#define NETHER_BACKUP_BACKEND dummyBackend
#endif // HAVE_CYNARA
#define NETHER_DEFAULT_VERDICT NetherVerdict::allowAndLog
#define NETHER_LOG_BACKEND NetherLogBackendType::stderrBackend
#define NETHER_IPTABLES_RESTORE_PATH "/usr/sbin/iptables-restore"
#ifndef NETHER_RULES_PATH
- #define NETHER_RULES_PATH "/etc/nether/nether.rules"
+#define NETHER_RULES_PATH "/etc/nether/nether.rules"
#endif // NETHER_RULES_PATH
#ifndef NETHER_POLICY_FILE
- #define NETHER_POLICY_FILE "/etc/nether/nether.policy"
+#define NETHER_POLICY_FILE "/etc/nether/nether.policy"
#endif // NETHER_POLICY_FILE
enum class NetherPolicyBackendType : std::uint8_t
{
- cynaraBackend,
- fileBackend,
- dummyBackend
+ cynaraBackend,
+ fileBackend,
+ dummyBackend
};
enum class NetherLogBackendType : std::uint8_t
{
- stderrBackend,
- syslogBackend,
- journalBackend,
- logfileBackend,
- nullBackend
+ stderrBackend,
+ syslogBackend,
+ journalBackend,
+ logfileBackend,
+ nullBackend
};
enum class NetherVerdict : std::uint8_t
{
- allow,
- allowAndLog,
- deny,
- noVerdictYet
+ allow,
+ allowAndLog,
+ deny,
+ noVerdictYet
};
enum class NetherDescriptorStatus : std::uint8_t
{
- readOnly,
- writeOnly,
- readWrite,
- unknownStatus
+ readOnly,
+ writeOnly,
+ readWrite,
+ unknownStatus
};
enum class NetherTransportType : std::uint8_t
{
- TCP,
- UDP,
- ICMP,
- IGMP,
- unknownTransportType
+ TCP,
+ UDP,
+ ICMP,
+ IGMP,
+ unknownTransportType
};
enum class NetherProtocolType : std::uint8_t
{
- IPv4,
- IPv6,
- unknownProtocolType
+ IPv4,
+ IPv6,
+ unknownProtocolType
};
struct NetherPacket
{
- u_int32_t id;
- std::string securityContext;
- uid_t uid;
- gid_t gid;
- pid_t pid;
- NetherTransportType transportType;
- NetherProtocolType protocolType;
- char localAddress[NETHER_NETWORK_ADDR_LEN];
- int localPort;
- char remoteAddress[NETHER_NETWORK_ADDR_LEN];
- int remotePort;
+ uid_t uid;
+ u_int32_t id;
+ std::string securityContext;
+ int remotePort;
+ int localPort;
+ gid_t gid;
+ pid_t pid;
+ char localAddress[NETHER_NETWORK_ADDR_LEN];
+ char remoteAddress[NETHER_NETWORK_ADDR_LEN];
+ NetherTransportType transportType;
+ NetherProtocolType protocolType;
};
struct NetherConfig
{
- NetherVerdict defaultVerdict = NETHER_DEFAULT_VERDICT;
- NetherPolicyBackendType primaryBackendType = NETHER_PRIMARY_BACKEND;
- NetherPolicyBackendType backupBackendType = NETHER_BACKUP_BACKEND;
- NetherLogBackendType logBackend = NETHER_LOG_BACKEND;
- int primaryBackendRetries = 3;
- int backupBackendRetries = 3;
- int debugMode = 0;
- int daemonMode = 0;
- int queueNumber = 0;
- std::string backupBackendArgs = NETHER_POLICY_FILE;
- std::string primaryBackendArgs;
- std::string logBackendArgs;
- std::string rulesPath = NETHER_RULES_PATH;
- std::string iptablesRestorePath = NETHER_IPTABLES_RESTORE_PATH;
- uint8_t markDeny = NETLINK_DROP_MARK;
- uint8_t markAllowAndLog = NETLINK_ALLOWLOG_MARK;
- int enableAudit = 0;
- int noRules = 0;
+ NetherVerdict defaultVerdict = NETHER_DEFAULT_VERDICT;
+ NetherPolicyBackendType primaryBackendType = NETHER_PRIMARY_BACKEND;
+ NetherPolicyBackendType backupBackendType = NETHER_BACKUP_BACKEND;
+ NetherLogBackendType logBackend = NETHER_LOG_BACKEND;
+ uint8_t markDeny = NETLINK_DROP_MARK;
+ uint8_t markAllowAndLog = NETLINK_ALLOWLOG_MARK;
+ int primaryBackendRetries = 3;
+ int backupBackendRetries = 3;
+ int debugMode = 0;
+ int daemonMode = 0;
+ int queueNumber = 0;
+ int enableAudit = 0;
+ int noRules = 0;
+ std::string backupBackendArgs = NETHER_POLICY_FILE;
+ std::string primaryBackendArgs;
+ std::string logBackendArgs;
+ std::string rulesPath = NETHER_RULES_PATH;
+ std::string iptablesRestorePath = NETHER_IPTABLES_RESTORE_PATH;
};
class NetherVerdictListener
{
- public:
- virtual bool verdictCast (const u_int32_t packetId, const NetherVerdict verdict) = 0;
+ public:
+ virtual bool verdictCast(const u_int32_t packetId, const NetherVerdict verdict) = 0;
};
class NetherVerdictCaster
{
- public:
- NetherVerdictCaster() : verdictListener(nullptr) {}
- virtual ~NetherVerdictCaster() {}
-
- void setListener(NetherVerdictListener *listenerToSet)
- {
- verdictListener = listenerToSet;
- }
-
- bool castVerdict (const NetherPacket &packet, const NetherVerdict verdict)
- {
- if (verdictListener)
- return (verdictListener->verdictCast(packet.id, verdict));
- return (false);
- }
-
- bool castVerdict (const u_int32_t packetId, const NetherVerdict verdict)
- {
- if (verdictListener)
- return (verdictListener->verdictCast(packetId, verdict));
- return (false);
- }
-
- protected:
- NetherVerdictListener *verdictListener;
+ public:
+ NetherVerdictCaster() : verdictListener(nullptr) {}
+ virtual ~NetherVerdictCaster() {}
+
+ void setListener(NetherVerdictListener *listenerToSet)
+ {
+ verdictListener = listenerToSet;
+ }
+
+ bool castVerdict(const NetherPacket &packet, const NetherVerdict verdict)
+ {
+ if(verdictListener)
+ return (verdictListener->verdictCast(packet.id, verdict));
+ return (false);
+ }
+
+ bool castVerdict(const u_int32_t packetId, const NetherVerdict verdict)
+ {
+ if(verdictListener)
+ return (verdictListener->verdictCast(packetId, verdict));
+ return (false);
+ }
+
+ protected:
+ NetherVerdictListener *verdictListener;
};
class NetherProcessedPacketListener
{
- public:
- virtual void packetReceived (const NetherPacket &packet) = 0;
+ public:
+ virtual void packetReceived(const NetherPacket &packet) = 0;
};
class NetherPacketProcessor
{
- public:
- NetherPacketProcessor(NetherConfig &_netherConfig) : netherConfig(_netherConfig), packetListener(nullptr) {}
- virtual ~NetherPacketProcessor() {}
- virtual const bool reload() { return (true); }
- void setListener(NetherProcessedPacketListener *listenerToSet)
- {
- packetListener = listenerToSet;
- }
-
- void processNetherPacket (NetherPacket packetInfoToWrite)
- {
- if (packetListener) packetListener->packetReceived(packetInfoToWrite);
- }
-
- virtual void setVerdict(const NetherPacket &packet, const NetherVerdict verdict) {}
- protected:
- NetherProcessedPacketListener *packetListener;
- NetherConfig netherConfig;
+ public:
+ NetherPacketProcessor(NetherConfig &_netherConfig)
+ : packetListener(nullptr), netherConfig(_netherConfig) {}
+ virtual ~NetherPacketProcessor() {}
+ virtual bool reload()
+ {
+ return (true);
+ }
+ void setListener(NetherProcessedPacketListener *listenerToSet)
+ {
+ packetListener = listenerToSet;
+ }
+
+ void processNetherPacket(NetherPacket packetInfoToWrite)
+ {
+ if(packetListener) packetListener->packetReceived(packetInfoToWrite);
+ }
+
+ virtual void setVerdict(const u_int32_t packetId, const NetherVerdict verdict) = 0;
+
+ protected:
+ NetherProcessedPacketListener *packetListener;
+ NetherConfig netherConfig;
};
#endif
* @brief utility functions
*/
-
#ifndef NETHER_UTILS_H
#define NETHER_UTILS_H
+
#include "nether_Types.h"
void decodePacket(NetherPacket &packet, unsigned char *payload);
void decodeIPv4Packet(NetherPacket &packet, unsigned char *payload);
void decodeIPv6Packet(NetherPacket &packet, unsigned char *payload);
void decodeTcp(NetherPacket &packet, unsigned char *payload);
void decodeUdp(NetherPacket &packet, unsigned char *payload);
-const std::string ipAddressToString(const char *src, enum NetherProtocolType type);
+std::string ipAddressToString(const char *src, enum NetherProtocolType type);
-template <typename Type>
-inline void deleteAndZero (Type& pointer) { delete pointer; pointer = nullptr; }
-
-static const NetherVerdict stringToVerdict (char *verdictAsString)
+static NetherVerdict stringToVerdict(char *verdictAsString)
{
- if (verdictAsString)
- {
- if (strncasecmp (verdictAsString, "allow_log", 9) == 0)
- return (NetherVerdict::allowAndLog);
- if (strncasecmp (verdictAsString, "allow", 6) == 0)
- return (NetherVerdict::allow);
- if (strncasecmp (verdictAsString, "deny", 4) == 0)
- return (NetherVerdict::deny);
- }
- return (NetherVerdict::allowAndLog);
+ if(verdictAsString)
+ {
+ if(strncasecmp(verdictAsString, "allow_log", 9) == 0)
+ return (NetherVerdict::allowAndLog);
+ if(strncasecmp(verdictAsString, "allow", 6) == 0)
+ return (NetherVerdict::allow);
+ if(strncasecmp(verdictAsString, "deny", 4) == 0)
+ return (NetherVerdict::deny);
+ }
+ return (NetherVerdict::allowAndLog);
}
-static const NetherPolicyBackendType stringToBackendType (char *backendAsString)
+static NetherPolicyBackendType stringToBackendType(char *backendAsString)
{
- if (strcasecmp (backendAsString, "cynara") == 0)
- return (NetherPolicyBackendType::cynaraBackend);
- if (strcasecmp (backendAsString, "file") == 0)
- return (NetherPolicyBackendType::fileBackend);
- if (strcasecmp (backendAsString, "dummy") == 0)
- return (NetherPolicyBackendType::dummyBackend);
-
- return (NetherPolicyBackendType::dummyBackend);
+ if(strcasecmp(backendAsString, "cynara") == 0)
+ return (NetherPolicyBackendType::cynaraBackend);
+ if(strcasecmp(backendAsString, "file") == 0)
+ return (NetherPolicyBackendType::fileBackend);
+ if(strcasecmp(backendAsString, "dummy") == 0)
+ return (NetherPolicyBackendType::dummyBackend);
+
+ return (NetherPolicyBackendType::dummyBackend);
}
-static const NetherLogBackendType stringToLogBackendType(char *backendAsString)
+static NetherLogBackendType stringToLogBackendType(char *backendAsString)
{
- if (strcasecmp (backendAsString, "stderr") == 0)
- return (NetherLogBackendType::stderrBackend);
- if (strcasecmp (backendAsString, "syslog") == 0)
- return (NetherLogBackendType::syslogBackend);
- if (strcasecmp (backendAsString, "journal") == 0)
- return (NetherLogBackendType::journalBackend);
- if (strcasecmp (backendAsString, "file") == 0)
- return (NetherLogBackendType::logfileBackend);
- if (strcasecmp (backendAsString, "null") == 0)
- return (NetherLogBackendType::nullBackend);
-
- return (NetherLogBackendType::nullBackend);
+ if(strcasecmp(backendAsString, "stderr") == 0)
+ return (NetherLogBackendType::stderrBackend);
+ if(strcasecmp(backendAsString, "syslog") == 0)
+ return (NetherLogBackendType::syslogBackend);
+ if(strcasecmp(backendAsString, "journal") == 0)
+ return (NetherLogBackendType::journalBackend);
+ if(strcasecmp(backendAsString, "file") == 0)
+ return (NetherLogBackendType::logfileBackend);
+ if(strcasecmp(backendAsString, "null") == 0)
+ return (NetherLogBackendType::nullBackend);
+
+ return (NetherLogBackendType::nullBackend);
}
-static const std::string logBackendTypeToString(const NetherLogBackendType backendType)
+static std::string logBackendTypeToString(const NetherLogBackendType backendType)
{
- switch (backendType)
- {
- case NetherLogBackendType::stderrBackend:
- return ("stderr");
- case NetherLogBackendType::syslogBackend:
- return ("syslog");
- case NetherLogBackendType::journalBackend:
- return ("journal");
- case NetherLogBackendType::logfileBackend:
- return ("file");
- case NetherLogBackendType::nullBackend:
- return ("null");
- }
- return ("null");
+ switch(backendType)
+ {
+ case NetherLogBackendType::stderrBackend:
+ return ("stderr");
+ case NetherLogBackendType::syslogBackend:
+ return ("syslog");
+ case NetherLogBackendType::journalBackend:
+ return ("journal");
+ case NetherLogBackendType::logfileBackend:
+ return ("file");
+ case NetherLogBackendType::nullBackend:
+ return ("null");
+ }
+ return ("null");
}
-static const std::string backendTypeToString (const NetherPolicyBackendType backendType)
+static std::string backendTypeToString(const NetherPolicyBackendType backendType)
{
- switch (backendType)
- {
- case NetherPolicyBackendType::cynaraBackend:
- return ("cynara");
- case NetherPolicyBackendType::fileBackend:
- return ("file");
- case NetherPolicyBackendType::dummyBackend:
- default:
- return ("dummy");
- }
+ switch(backendType)
+ {
+ case NetherPolicyBackendType::cynaraBackend:
+ return ("cynara");
+ case NetherPolicyBackendType::fileBackend:
+ return ("file");
+ case NetherPolicyBackendType::dummyBackend:
+ default:
+ return ("dummy");
+ }
}
-static const std::string verdictToString (const NetherVerdict verdict)
+static std::string verdictToString(const NetherVerdict verdict)
{
- switch (verdict)
- {
- case NetherVerdict::allow:
- return ("ALLOW");
- case NetherVerdict::allowAndLog:
- return ("ALLOW_LOG");
- case NetherVerdict::deny:
- return ("DENY");
- }
+ switch(verdict)
+ {
+ case NetherVerdict::allow:
+ return ("ALLOW");
+ case NetherVerdict::allowAndLog:
+ return ("ALLOW_LOG");
+ case NetherVerdict::deny:
+ return ("DENY");
+ case NetherVerdict::noVerdictYet:
+ return ("NO_VERDICT_YET");
+ }
+ return ("NO_VERDICT_YET");
}
-static const std::string transportToString(const NetherTransportType transportType)
+static std::string transportToString(const NetherTransportType transportType)
{
- switch (transportType)
- {
- case NetherTransportType::TCP:
- return ("TCP");
- case NetherTransportType::UDP:
- return ("UDP");
- case NetherTransportType::ICMP:
- return ("ICMP");
- case NetherTransportType::IGMP:
- return ("IGMP");
- case NetherTransportType::unknownTransportType:
- default:
- return ("UNKNOWN");
- }
+ switch(transportType)
+ {
+ case NetherTransportType::TCP:
+ return ("TCP");
+ case NetherTransportType::UDP:
+ return ("UDP");
+ case NetherTransportType::ICMP:
+ return ("ICMP");
+ case NetherTransportType::IGMP:
+ return ("IGMP");
+ case NetherTransportType::unknownTransportType:
+ default:
+ return ("UNKNOWN");
+ }
}
-static const std::string protocolToString(const NetherProtocolType protocolType)
+static std::string protocolToString(const NetherProtocolType protocolType)
{
- switch (protocolType)
- {
- case NetherProtocolType::IPv4:
- return ("IPv4");
- case NetherProtocolType::IPv6:
- return ("IPv6");
- default:
- return ("UNKNOWN");
- }
+ switch(protocolType)
+ {
+ case NetherProtocolType::IPv4:
+ return ("IPv4");
+ case NetherProtocolType::IPv6:
+ return ("IPv6");
+ default:
+ return ("UNKNOWN");
+ }
}
-static const std::string packetToString (const NetherPacket &packet)
+static std::string packetToString(const NetherPacket &packet)
{
- std::stringstream stream;
- stream << "ID=";
- stream << packet.id;
- stream << " SECCTX=";
- stream << packet.securityContext;
- stream << " UID=";
- stream << packet.uid;
- stream << " PROTO=";
- stream << protocolToString(packet.protocolType);
- stream << " TRANSPORT=";
- stream << transportToString(packet.transportType);
- stream << " SADDR=";
- stream << ipAddressToString(&packet.localAddress[0], packet.protocolType);
- stream << ":";
- stream << packet.localPort;
- stream << " DADDR=";
- stream << ipAddressToString(&packet.remoteAddress[0], packet.protocolType);
- stream << ":";
- stream << packet.remotePort;
- return (stream.str());
+ std::stringstream stream;
+ stream << "ID=";
+ stream << packet.id;
+ stream << " SECCTX=";
+ stream << packet.securityContext;
+ stream << " UID=";
+ stream << packet.uid;
+ stream << " GID=";
+ stream << packet.gid;
+ stream << " PROTO=";
+ stream << protocolToString(packet.protocolType);
+ stream << " TRANSPORT=";
+ stream << transportToString(packet.transportType);
+ stream << " SADDR=";
+ stream << ipAddressToString(&packet.localAddress[0], packet.protocolType);
+ stream << ":";
+ stream << packet.localPort;
+ stream << " DADDR=";
+ stream << ipAddressToString(&packet.remoteAddress[0], packet.protocolType);
+ stream << ":";
+ stream << packet.remotePort;
+ return (stream.str());
}
template<typename ... Args>
-std::string stringFormat( const char* format, Args ... args )
+std::string stringFormat(const char* format, Args ... args)
{
- size_t size = snprintf( nullptr, 0, format, args ... ) + 1; // Extra space for '\0'
- std::unique_ptr<char[]> buf( new char[ size ] );
- snprintf( buf.get(), size, format, args ... );
- return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
+ size_t size = snprintf(nullptr, 0, format, args ...) + 1; // Extra space for '\0'
+ std::unique_ptr<char[]> buf(new char[ size ]);
+ snprintf(buf.get(), size, format, args ...);
+ return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
}
-#endif
+
+#endif // NETHER_UTILS_H
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<CodeBlocks_project_file>
- <FileVersion major="1" minor="6" />
- <Project>
- <Option title="nether" />
- <Option pch_mode="2" />
- <Option compiler="gcc" />
- <MakeCommands>
- <Build command="$make root@guest make all -C devel/nether" />
- <CompileFile command="$make -f $makefile $file" />
- <Clean command="$make -f $makefile clean$target" />
- <DistClean command="$make -f $makefile distclean$target" />
- <AskRebuildNeeded command="$make -q -f $makefile $target" />
- <SilentBuild command="$make root@guest make all -C devel/nether > $(CMD_NULL)" />
- </MakeCommands>
- <Build>
- <Target title="Debug">
- <Option output="obj/nether" prefix_auto="1" extension_auto="1" />
- <Option working_dir="obj" />
- <Option object_output="obj/Debug/" />
- <Option type="0" />
- <Option compiler="gcc" />
- <Option parameters="-B /etc/nether/nether.policy -l stderr -a 1" />
- <Compiler>
- <Add option="-std=c++11" />
- <Add option="-Wfatal-errors" />
- <Add option="-Wextra" />
- <Add option="-Wall" />
- <Add option="-g" />
- <Add option="-DHAVE_CYNARA" />
- <Add option="-D_DEBUG" />
- <Add option="-DHAVE_AUDIT" />
- <Add directory="include" />
- <Add directory="/usr/local/include/cynara" />
- </Compiler>
- <Linker>
- <Add library="libnetfilter_queue" />
- <Add library="libnfnetlink" />
- <Add library="libcynara-client-async" />
- <Add library="libcynara-commons" />
- <Add library="libaudit" />
- <Add directory="/usr/local/lib" />
- </Linker>
- <MakeCommands>
- <Build command="$make root@guest make all -C devel/nether" />
- <CompileFile command="$make -f $makefile $file" />
- <Clean command="$make root@guest make clean -C devel/nether" />
- <DistClean command="$make -f $makefile distclean$target" />
- <AskRebuildNeeded command="$make -q -f $makefile $target" />
- <SilentBuild command="$make root@guest make all -C devel/nether > $(CMD_NULL)" />
- </MakeCommands>
- </Target>
- <Target title="Release">
- <Option output="bin/Release/nether" prefix_auto="1" extension_auto="1" />
- <Option object_output="obj/Release/" />
- <Option type="1" />
- <Option compiler="gcc" />
- <Compiler>
- <Add option="-O2" />
- <Add option="-std=c++11" />
- </Compiler>
- <Linker>
- <Add option="-s" />
- </Linker>
- </Target>
- </Build>
- <Compiler>
- <Add option="-fomit-frame-pointer" />
- <Add option="-std=c++11" />
- <Add option="-w" />
- <Add option="-fexceptions" />
- <Add option="-fPIC" />
- </Compiler>
- <Unit filename="CMakeLists.txt" />
- <Unit filename="cmake/Findaudit.cmake" />
- <Unit filename="conf/CMakeLists.txt" />
- <Unit filename="conf/nether.policy" />
- <Unit filename="conf/nether.rules" />
- <Unit filename="conf/systemd/nether.service.in" />
- <Unit filename="include/logger/backend-file.hpp" />
- <Unit filename="include/logger/backend-journal.hpp" />
- <Unit filename="include/logger/backend-null.hpp" />
- <Unit filename="include/logger/backend-stderr.hpp" />
- <Unit filename="include/logger/backend-syslog.hpp" />
- <Unit filename="include/logger/backend.hpp" />
- <Unit filename="include/logger/ccolor.hpp" />
- <Unit filename="include/logger/config.hpp" />
- <Unit filename="include/logger/formatter.hpp" />
- <Unit filename="include/logger/level.hpp" />
- <Unit filename="include/logger/logger-scope.hpp" />
- <Unit filename="include/logger/logger.hpp" />
- <Unit filename="include/nether_CynaraBackend.h" />
- <Unit filename="include/nether_Daemon.h" />
- <Unit filename="include/nether_DummyBackend.h" />
- <Unit filename="include/nether_FileBackend.h" />
- <Unit filename="include/nether_Manager.h" />
- <Unit filename="include/nether_Netlink.h" />
- <Unit filename="include/nether_PolicyBackend.h" />
- <Unit filename="include/nether_Types.h" />
- <Unit filename="include/nether_Utils.h" />
- <Unit filename="packaging/nether.manifest" />
- <Unit filename="packaging/nether.spec" />
- <Unit filename="src/CMakeLists.txt" />
- <Unit filename="src/logger/backend-file.cpp" />
- <Unit filename="src/logger/backend-journal.cpp" />
- <Unit filename="src/logger/backend-stderr.cpp" />
- <Unit filename="src/logger/backend-syslog.cpp" />
- <Unit filename="src/logger/ccolor.cpp" />
- <Unit filename="src/logger/formatter.cpp" />
- <Unit filename="src/logger/level.cpp" />
- <Unit filename="src/logger/logger-scope.cpp" />
- <Unit filename="src/logger/logger.cpp" />
- <Unit filename="src/nether_CynaraBackend.cpp" />
- <Unit filename="src/nether_FileBackend.cpp" />
- <Unit filename="src/nether_Main.cpp" />
- <Unit filename="src/nether_Manager.cpp" />
- <Unit filename="src/nether_Netlink.cpp" />
- <Unit filename="src/nether_NetworkUtils.cpp" />
- <Extensions>
- <envvars />
- <code_completion />
- <debugger>
- <search_path add="/root/devel/nether/" />
- <search_path add="/root/devel/nether/src" />
- <search_path add="/root/devel/nether/include" />
- </debugger>
- <lib_finder disable_auto="1" />
- </Extensions>
- </Project>
-</CodeBlocks_project_file>
Name: nether
-Epoch: 1
Version: 0.0.1
Release: 0
Source0: %{name}-%{version}.tar.gz
Group: Security/Other
Summary: Daemon for enforcing network privileges
BuildRequires: cmake
-BuildRequires: pkgconfig(glib-2.0)
BuildRequires: libnetfilter_queue-devel
BuildRequires: pkgconfig(cynara-client-async)
Requires: iptables
%files
%defattr(644,root,root,755)
-%attr(755,root,root) %{_bindir}/nether
+%caps(cap_sys_admin,cap_mac_override=ei) %attr(755,root,root) %{_bindir}/nether
%dir %{_sysconfdir}/nether
%config %{_sysconfdir}/nether/nether.policy
%config %{_sysconfdir}/nether/nether.rules
-DBIN_INSTALL_DIR=%{_bindir} \
-DSYSCONF_INSTALL_DIR=%{_sysconfdir}
-make -k %{?jobs:-j%jobs}
+make %{?_smp_mflags}
%install
%make_install
%post
# Refresh systemd services list after installation
+systemctl daemon-reload || :
if [ $1 == 1 ]; then
- systemctl daemon-reload || :
+ systemctl start nether.service || :
+fi
+if [ $1 == 2 ]; then
+ systemct restart nether.service || :
fi
-# set needed caps on the binary to allow restart without loosing them
-setcap CAP_SYS_ADMIN,CAP_MAC_OVERRIDE+ei %{_bindir}/nether
%preun
# Stop the service before uninstall
${SYSTEMD_INCLUDE_DIRS}
)
-TARGET_LINK_LIBRARIES (nether
+TARGET_LINK_LIBRARIES (nether
${CYNARA_LIBRARIES}
${NETFILTER_LIBRARIES}
${SYSTEMD_LIBRARIES}
)
ADD_DEFINITIONS (-DNETHER_RULES_PATH="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules"
- -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules"
+ -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules"
)
INSTALL (TARGETS nether RUNTIME DESTINATION bin)
#include <fstream>
-namespace logger {
-
-void FileBackend::log(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func,
- const std::string& message)
+namespace logger
{
- std::ofstream out(mfilePath, std::ios::app);
- out << LogFormatter::getHeader(logLevel, file, line, func);
- out << message;
- out << std::endl;
-}
+
+ void FileBackend::log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message)
+ {
+ std::ofstream out(mfilePath, std::ios::app);
+ out << LogFormatter::getHeader(logLevel, file, line, func);
+ out << message;
+ out << std::endl;
+ }
} // namespace logger
#define SD_JOURNAL_SUPPRESS_LOCATION
#include <systemd/sd-journal.h>
-namespace logger {
+namespace logger
+{
-namespace {
+ namespace
+ {
-inline int toJournalPriority(LogLevel logLevel)
-{
- switch (logLevel) {
- case LogLevel::ERROR:
- return LOG_ERR; // 3
- case LogLevel::WARN:
- return LOG_WARNING; // 4
- case LogLevel::INFO:
- return LOG_INFO; // 6
- case LogLevel::DEBUG:
- return LOG_DEBUG; // 7
- case LogLevel::TRACE:
- return LOG_DEBUG; // 7
- case LogLevel::HELP:
- return LOG_DEBUG; // 7
- default:
- return LOG_DEBUG; // 7
- }
-}
+ inline int toJournalPriority(LogLevel logLevel)
+ {
+ switch(logLevel)
+ {
+ case LogLevel::ERROR:
+ return LOG_ERR; // 3
+ case LogLevel::WARN:
+ return LOG_WARNING; // 4
+ case LogLevel::INFO:
+ return LOG_INFO; // 6
+ case LogLevel::DEBUG:
+ return LOG_DEBUG; // 7
+ case LogLevel::TRACE:
+ return LOG_DEBUG; // 7
+ case LogLevel::HELP:
+ return LOG_DEBUG; // 7
+ default:
+ return LOG_DEBUG; // 7
+ }
+ }
-} // namespace
+ } // namespace
-void SystemdJournalBackend::log(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func,
- const std::string& message)
-{
- sd_journal_send("PRIORITY=%d", toJournalPriority(logLevel),
- "CODE_FILE=%s", file.c_str(),
- "CODE_LINE=%d", line,
- "CODE_FUNC=%s", func.c_str(),
- "MESSAGE=%s", message.c_str(),
- NULL);
-}
+ void SystemdJournalBackend::log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message)
+ {
+ sd_journal_send("PRIORITY=%d", toJournalPriority(logLevel),
+ "CODE_FILE=%s", file.c_str(),
+ "CODE_LINE=%d", line,
+ "CODE_FUNC=%s", func.c_str(),
+ "MESSAGE=%s", message.c_str(),
+ NULL);
+ }
} // namespace logger
#endif // HAVE_SYSTEMD_JOURNAL
#include "logger/formatter.hpp"
#if defined(HAVE_BOOST)
- #include <boost/tokenizer.hpp>
+#include <boost/tokenizer.hpp>
#endif
-namespace logger {
-
-void StderrBackend::log(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func,
- const std::string& message)
+namespace logger
{
+
+ void StderrBackend::log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message)
+ {
#if defined(HAVE_BOOST)
- typedef boost::char_separator<char> charSeparator;
- typedef boost::tokenizer<charSeparator> tokenizer;
+ typedef boost::char_separator<char> charSeparator;
+ typedef boost::tokenizer<charSeparator> tokenizer;
- // example log string
- // 06:52:35.123 [ERROR] src/util/fs.cpp:43 readFileContent: /file/file.txt is missing
+ // example log string
+ // 06:52:35.123 [ERROR] src/util/fs.cpp:43 readFileContent: /file/file.txt is missing
- const std::string logColor = LogFormatter::getConsoleColor(logLevel);
- const std::string defaultColor = LogFormatter::getDefaultConsoleColor();
- const std::string header = LogFormatter::getHeader(logLevel, file, line, func);
- tokenizer tokens(message, charSeparator("\n"));
- for (const auto& messageLine : tokens) {
- if (!messageLine.empty()) {
- fprintf(stderr,
- "%s%s %s%s\n",
- useColours ? logColor.c_str() : "",
- header.c_str(),
- messageLine.c_str(),
- useColours ? defaultColor.c_str() : "");
- }
- }
+ const std::string logColor = LogFormatter::getConsoleColor(logLevel);
+ const std::string defaultColor = LogFormatter::getDefaultConsoleColor();
+ const std::string header = LogFormatter::getHeader(logLevel, file, line, func);
+ tokenizer tokens(message, charSeparator("\n"));
+ for(const auto& messageLine : tokens)
+ {
+ if(!messageLine.empty())
+ {
+ fprintf(stderr,
+ "%s%s %s%s\n",
+ useColours ? logColor.c_str() : "",
+ header.c_str(),
+ messageLine.c_str(),
+ useColours ? defaultColor.c_str() : "");
+ }
+ }
#else
- fprintf (stderr, "%s %s\n", LogFormatter::getHeader(logLevel, file, line, func).c_str(), message.c_str());
+ fprintf(stderr, "%s %s\n", LogFormatter::getHeader(logLevel, file, line, func).c_str(), message.c_str());
#endif
-}
+ }
} // namespace logger
#include <syslog.h>
#include <sstream>
-namespace logger {
+namespace logger
+{
-namespace {
+ namespace
+ {
-inline int toSyslogPriority(LogLevel logLevel)
-{
- switch (logLevel) {
- case LogLevel::ERROR:
- return LOG_ERR; // 3
- case LogLevel::WARN:
- return LOG_WARNING; // 4
- case LogLevel::INFO:
- return LOG_INFO; // 6
- case LogLevel::DEBUG:
- return LOG_DEBUG; // 7
- case LogLevel::TRACE:
- return LOG_DEBUG; // 7
- case LogLevel::HELP:
- return LOG_DEBUG; // 7
- default:
- return LOG_DEBUG; // 7
- }
-}
+ inline int toSyslogPriority(LogLevel logLevel)
+ {
+ switch(logLevel)
+ {
+ case LogLevel::ERROR:
+ return LOG_ERR; // 3
+ case LogLevel::WARN:
+ return LOG_WARNING; // 4
+ case LogLevel::INFO:
+ return LOG_INFO; // 6
+ case LogLevel::DEBUG:
+ return LOG_DEBUG; // 7
+ case LogLevel::TRACE:
+ return LOG_DEBUG; // 7
+ case LogLevel::HELP:
+ return LOG_DEBUG; // 7
+ default:
+ return LOG_DEBUG; // 7
+ }
+ }
-} // namespace
+ } // namespace
-void SyslogBackend::log(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func,
- const std::string& message)
-{
- syslog(toSyslogPriority(logLevel), "%s %s", LogFormatter::getHeader(logLevel, file, line, func).c_str(), message.c_str());
-}
+ void SyslogBackend::log(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func,
+ const std::string& message)
+ {
+ syslog(toSyslogPriority(logLevel), "%s %s", LogFormatter::getHeader(logLevel, file, line, func).c_str(), message.c_str());
+ }
} // namespace logger
#include <stdio.h>
-namespace logger {
-
-std::string getConsoleEscapeSequence(Attributes attr, Color color)
+namespace logger
{
- char command[10];
- // Command is the control command to the terminal
- snprintf(command, sizeof(command), "%c[%u;%um", 0x1B, (unsigned int)attr, (unsigned int)color);
- return std::string(command);
-}
+ std::string getConsoleEscapeSequence(Attributes attr, Color color)
+ {
+ char command[10];
+
+ // Command is the control command to the terminal
+ snprintf(command, sizeof(command), "%c[%u;%um", 0x1B, (unsigned int)attr, (unsigned int)color);
+ return std::string(command);
+ }
} // namespace logger
#include <thread>
#include <atomic>
-namespace logger {
-
-namespace {
-
-const int TIME_COLUMN_LENGTH = 12;
-const int SEVERITY_COLUMN_LENGTH = 8;
-const int THREAD_COLUMN_LENGTH = 3;
-const int FILE_COLUMN_LENGTH = 60;
-
-std::atomic<unsigned int> gNextThreadId(1);
-thread_local unsigned int gThisThreadId(0);
-
-} // namespace
-
-unsigned int LogFormatter::getCurrentThread(void)
-{
- unsigned int id = gThisThreadId;
- if (id == 0) {
- gThisThreadId = id = gNextThreadId++;
- }
-
- return id;
-}
-
-std::string LogFormatter::getCurrentTime(void)
-{
- char time[TIME_COLUMN_LENGTH + 1];
- struct timeval tv;
- gettimeofday(&tv, NULL);
- struct tm* tm = localtime(&tv.tv_sec);
- snprintf(time,
- sizeof(time),
- "%02d:%02d:%02d.%03d",
- tm->tm_hour,
- tm->tm_min,
- tm->tm_sec,
- int(tv.tv_usec / 1000));
-
- return std::string(time);
-}
-
-std::string LogFormatter::getConsoleColor(LogLevel logLevel)
+namespace logger
{
- switch (logLevel) {
- case LogLevel::ERROR:
- return getConsoleEscapeSequence(Attributes::BOLD, Color::RED);
- case LogLevel::WARN:
- return getConsoleEscapeSequence(Attributes::BOLD, Color::YELLOW);
- case LogLevel::INFO:
- return getConsoleEscapeSequence(Attributes::BOLD, Color::BLUE);
- case LogLevel::DEBUG:
- return getConsoleEscapeSequence(Attributes::DEFAULT, Color::GREEN);
- case LogLevel::TRACE:
- return getConsoleEscapeSequence(Attributes::DEFAULT, Color::BLACK);
- case LogLevel::HELP:
- return getConsoleEscapeSequence(Attributes::BOLD, Color::MAGENTA);
- default:
- return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT);
- }
-}
-
-std::string LogFormatter::getDefaultConsoleColor(void)
-{
- return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT);
-}
-std::string LogFormatter::stripProjectDir(const std::string& file,
- const std::string& rootDir)
-{
- // If rootdir is empty then return full name
- if (rootDir.empty()) {
- return file;
- }
- const std::string sourceDir = rootDir + "/";
- // If file does not belong to rootDir then also return full name
- if (0 != file.compare(0, sourceDir.size(), sourceDir)) {
- return file;
- }
- return file.substr(sourceDir.size());
-}
-
-std::string LogFormatter::getHeader(LogLevel logLevel,
- const std::string& file,
- const unsigned int& line,
- const std::string& func)
-{
- std::ostringstream logLine;
- logLine << getCurrentTime() << ' '
- << std::left << std::setw(SEVERITY_COLUMN_LENGTH) << '[' + toString(logLevel) + ']'
- << std::right << std::setw(THREAD_COLUMN_LENGTH) << getCurrentThread() << ": "
- << std::left << std::setw(FILE_COLUMN_LENGTH)
- << file + ':' + std::to_string(line) + ' ' + func + ':';
- return logLine.str();
-}
+ namespace
+ {
+
+ const int TIME_COLUMN_LENGTH = 12;
+ const int SEVERITY_COLUMN_LENGTH = 8;
+ const int THREAD_COLUMN_LENGTH = 3;
+ const int FILE_COLUMN_LENGTH = 60;
+
+ std::atomic<unsigned int> gNextThreadId(1);
+ thread_local unsigned int gThisThreadId(0);
+
+ } // namespace
+
+ unsigned int LogFormatter::getCurrentThread(void)
+ {
+ unsigned int id = gThisThreadId;
+ if(id == 0)
+ {
+ gThisThreadId = id = gNextThreadId++;
+ }
+
+ return id;
+ }
+
+ std::string LogFormatter::getCurrentTime(void)
+ {
+ char time[TIME_COLUMN_LENGTH + 1];
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ struct tm* tm = localtime(&tv.tv_sec);
+ snprintf(time,
+ sizeof(time),
+ "%02d:%02d:%02d.%03d",
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec,
+ int(tv.tv_usec / 1000));
+
+ return std::string(time);
+ }
+
+ std::string LogFormatter::getConsoleColor(LogLevel logLevel)
+ {
+ switch(logLevel)
+ {
+ case LogLevel::ERROR:
+ return getConsoleEscapeSequence(Attributes::BOLD, Color::RED);
+ case LogLevel::WARN:
+ return getConsoleEscapeSequence(Attributes::BOLD, Color::YELLOW);
+ case LogLevel::INFO:
+ return getConsoleEscapeSequence(Attributes::BOLD, Color::BLUE);
+ case LogLevel::DEBUG:
+ return getConsoleEscapeSequence(Attributes::DEFAULT, Color::GREEN);
+ case LogLevel::TRACE:
+ return getConsoleEscapeSequence(Attributes::DEFAULT, Color::BLACK);
+ case LogLevel::HELP:
+ return getConsoleEscapeSequence(Attributes::BOLD, Color::MAGENTA);
+ default:
+ return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT);
+ }
+ }
+
+ std::string LogFormatter::getDefaultConsoleColor(void)
+ {
+ return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT);
+ }
+
+ std::string LogFormatter::stripProjectDir(const std::string& file,
+ const std::string& rootDir)
+ {
+ // If rootdir is empty then return full name
+ if(rootDir.empty())
+ {
+ return file;
+ }
+ const std::string sourceDir = rootDir + "/";
+ // If file does not belong to rootDir then also return full name
+ if(0 != file.compare(0, sourceDir.size(), sourceDir))
+ {
+ return file;
+ }
+ return file.substr(sourceDir.size());
+ }
+
+ std::string LogFormatter::getHeader(LogLevel logLevel,
+ const std::string& file,
+ const unsigned int& line,
+ const std::string& func)
+ {
+ std::ostringstream logLine;
+ logLine << getCurrentTime() << ' '
+ << std::left << std::setw(SEVERITY_COLUMN_LENGTH) << '[' + toString(logLevel) + ']'
+ << std::right << std::setw(THREAD_COLUMN_LENGTH) << getCurrentThread() << ": "
+ << std::left << std::setw(FILE_COLUMN_LENGTH)
+ << file + ':' + std::to_string(line) + ' ' + func + ':';
+ return logLine.str();
+ }
} // namespace logger
#include <stdexcept>
#if defined(HAVE_BOOST)
- #include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string.hpp>
-namespace logger {
-
-LogLevel parseLogLevel(const std::string& level)
+namespace logger
{
- if (boost::iequals(level, "ERROR")) {
- return LogLevel::ERROR;
- } else if (boost::iequals(level, "WARN")) {
- return LogLevel::WARN;
- } else if (boost::iequals(level, "INFO")) {
- return LogLevel::INFO;
- } else if (boost::iequals(level, "DEBUG")) {
- return LogLevel::DEBUG;
- } else if (boost::iequals(level, "TRACE")) {
- return LogLevel::TRACE;
- } else if (boost::iequals(level, "HELP")) {
- return LogLevel::HELP;
- } else {
- throw std::runtime_error("Invalid LogLevel to parse");
- }
-}
+
+ LogLevel parseLogLevel(const std::string& level)
+ {
+ if(boost::iequals(level, "ERROR"))
+ {
+ return LogLevel::ERROR;
+ }
+ else
+ if(boost::iequals(level, "WARN"))
+ {
+ return LogLevel::WARN;
+ }
+ else
+ if(boost::iequals(level, "INFO"))
+ {
+ return LogLevel::INFO;
+ }
+ else
+ if(boost::iequals(level, "DEBUG"))
+ {
+ return LogLevel::DEBUG;
+ }
+ else
+ if(boost::iequals(level, "TRACE"))
+ {
+ return LogLevel::TRACE;
+ }
+ else
+ if(boost::iequals(level, "HELP"))
+ {
+ return LogLevel::HELP;
+ }
+ else
+ {
+ throw std::runtime_error("Invalid LogLevel to parse");
+ }
+ }
#else
#include <string.h>
-namespace logger {
-
-LogLevel parseLogLevel(const std::string& level)
+namespace logger
{
- if (strcmp(level.c_str(), "ERROR")) {
- return LogLevel::ERROR;
- } else if (strcmp(level.c_str(), "WARN") == 0) {
- return LogLevel::WARN;
- } else if (strcmp(level.c_str(), "INFO") == 0) {
- return LogLevel::INFO;
- } else if (strcmp(level.c_str(), "DEBUG") == 0) {
- return LogLevel::DEBUG;
- } else if (strcmp(level.c_str(), "TRACE") == 0) {
- return LogLevel::TRACE;
- } else if (strcmp(level.c_str(), "HELP") == 0) {
- return LogLevel::HELP;
- } else {
- throw std::runtime_error("Invalid LogLevel to parse");
- }
-}
+
+ LogLevel parseLogLevel(const std::string& level)
+ {
+ if(strcmp(level.c_str(), "ERROR"))
+ {
+ return LogLevel::ERROR;
+ }
+ else
+ if(strcmp(level.c_str(), "WARN") == 0)
+ {
+ return LogLevel::WARN;
+ }
+ else
+ if(strcmp(level.c_str(), "INFO") == 0)
+ {
+ return LogLevel::INFO;
+ }
+ else
+ if(strcmp(level.c_str(), "DEBUG") == 0)
+ {
+ return LogLevel::DEBUG;
+ }
+ else
+ if(strcmp(level.c_str(), "TRACE") == 0)
+ {
+ return LogLevel::TRACE;
+ }
+ else
+ if(strcmp(level.c_str(), "HELP") == 0)
+ {
+ return LogLevel::HELP;
+ }
+ else
+ {
+ throw std::runtime_error("Invalid LogLevel to parse");
+ }
+ }
#endif
-std::string toString(const LogLevel logLevel)
-{
- switch (logLevel) {
- case LogLevel::ERROR:
- return "ERROR";
- case LogLevel::WARN:
- return "WARN";
- case LogLevel::INFO:
- return "INFO";
- case LogLevel::DEBUG:
- return "DEBUG";
- case LogLevel::TRACE:
- return "TRACE";
- case LogLevel::HELP:
- return "HELP";
- default:
- return "UNKNOWN";
- }
-}
+ std::string toString(const LogLevel logLevel)
+ {
+ switch(logLevel)
+ {
+ case LogLevel::ERROR:
+ return "ERROR";
+ case LogLevel::WARN:
+ return "WARN";
+ case LogLevel::INFO:
+ return "INFO";
+ case LogLevel::DEBUG:
+ return "DEBUG";
+ case LogLevel::TRACE:
+ return "TRACE";
+ case LogLevel::HELP:
+ return "HELP";
+ default:
+ return "UNKNOWN";
+ }
+ }
} // namespace logger
+
#include "logger/logger-scope.hpp"
#include "logger/logger.hpp"
-namespace logger {
-
-SStreamWrapper::operator std::string() const
+namespace logger
{
- return mSStream.str();
-}
-LoggerScope::LoggerScope(const std::string& file,
- const unsigned int line,
- const std::string& func,
- const std::string& message,
- const std::string& rootDir):
- mFile(file),
- mLine(line),
- mFunc(func),
- mMessage(message),
- mRootDir(rootDir)
-{
- if (logger::Logger::getLogLevel() <= logger::LogLevel::TRACE) {
- logger::Logger::logMessage(logger::LogLevel::TRACE, "Entering: " + mMessage,
- mFile, mLine, mFunc, mRootDir);
- }
-}
+ SStreamWrapper::operator std::string() const
+ {
+ return mSStream.str();
+ }
-LoggerScope::~LoggerScope()
-{
- if (logger::Logger::getLogLevel() <= logger::LogLevel::TRACE) {
- logger::Logger::logMessage(logger::LogLevel::TRACE, "Leaving: " + mMessage,
- mFile, mLine, mFunc, mRootDir);
- }
-}
+ LoggerScope::LoggerScope(const std::string& file,
+ const unsigned int line,
+ const std::string& func,
+ const std::string& message,
+ const std::string& rootDir):
+ mFile(file),
+ mLine(line),
+ mFunc(func),
+ mMessage(message),
+ mRootDir(rootDir)
+ {
+ if(logger::Logger::getLogLevel() <= logger::LogLevel::TRACE)
+ {
+ logger::Logger::logMessage(logger::LogLevel::TRACE, "Entering: " + mMessage,
+ mFile, mLine, mFunc, mRootDir);
+ }
+ }
+
+ LoggerScope::~LoggerScope()
+ {
+ if(logger::Logger::getLogLevel() <= logger::LogLevel::TRACE)
+ {
+ logger::Logger::logMessage(logger::LogLevel::TRACE, "Leaving: " + mMessage,
+ mFile, mLine, mFunc, mRootDir);
+ }
+ }
} // namespace logger
#include <memory>
#include <mutex>
-namespace logger {
+namespace logger
+{
-namespace {
+ namespace
+ {
-volatile LogLevel gLogLevel = LogLevel::DEBUG;
-std::unique_ptr<LogBackend> gLogBackendPtr(new NullLogger());
-std::mutex gLogMutex;
+ volatile LogLevel gLogLevel = LogLevel::DEBUG;
+ std::unique_ptr<LogBackend> gLogBackendPtr(new NullLogger());
+ std::mutex gLogMutex;
-} // namespace
+ } // namespace
-void Logger::logMessage(LogLevel logLevel,
- const std::string& message,
- const std::string& file,
- const unsigned int line,
- const std::string& func,
- const std::string& rootDir)
-{
- std::string sfile = LogFormatter::stripProjectDir(file, rootDir);
- std::unique_lock<std::mutex> lock(gLogMutex);
- gLogBackendPtr->log(logLevel, sfile, line, func, message);
-}
+ void Logger::logMessage(LogLevel logLevel,
+ const std::string& message,
+ const std::string& file,
+ const unsigned int line,
+ const std::string& func,
+ const std::string& rootDir)
+ {
+ std::string sfile = LogFormatter::stripProjectDir(file, rootDir);
+ std::unique_lock<std::mutex> lock(gLogMutex);
+ gLogBackendPtr->log(logLevel, sfile, line, func, message);
+ }
-void Logger::setLogLevel(const LogLevel level)
-{
- gLogLevel = level;
-}
+ void Logger::setLogLevel(const LogLevel level)
+ {
+ gLogLevel = level;
+ }
-void Logger::setLogLevel(const std::string& level)
-{
- gLogLevel = parseLogLevel(level);
-}
+ void Logger::setLogLevel(const std::string& level)
+ {
+ gLogLevel = parseLogLevel(level);
+ }
-LogLevel Logger::getLogLevel(void)
-{
- return gLogLevel;
-}
+ LogLevel Logger::getLogLevel(void)
+ {
+ return gLogLevel;
+ }
-void Logger::setLogBackend(LogBackend* pBackend)
-{
- std::unique_lock<std::mutex> lock(gLogMutex);
- gLogBackendPtr.reset(pBackend);
-}
+ void Logger::setLogBackend(LogBackend* pBackend)
+ {
+ std::unique_lock<std::mutex> lock(gLogMutex);
+ gLogBackendPtr.reset(pBackend);
+ }
} // namespace logger
#ifdef HAVE_CYNARA
NetherCynaraBackend::NetherCynaraBackend(const NetherConfig &netherConfig)
- : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(0),
- cynaraLastResult(CYNARA_API_UNKNOWN_ERROR)
+ : NetherPolicyBackend(netherConfig), currentCynaraDescriptor(0),
+ cynaraLastResult(CYNARA_API_UNKNOWN_ERROR)
{
- responseQueue.reserve(1024);
+ responseQueue.reserve(1024);
}
NetherCynaraBackend::~NetherCynaraBackend()
{
}
-const bool NetherCynaraBackend::initialize()
+bool NetherCynaraBackend::initialize()
{
- cynaraLastResult = cynara_async_initialize(&cynaraContext, NULL, &statusCallback, this);
- if (cynaraLastResult != CYNARA_API_SUCCESS)
- {
- LOGE("Failed to initialize cynara client " << cynaraErrorCodeToString(cynaraLastResult));
- return (false);
- }
-
- return (true);
+ cynaraLastResult = cynara_async_initialize(&cynaraContext, NULL, &statusCallback, this);
+ if(cynaraLastResult != CYNARA_API_SUCCESS)
+ {
+ LOGE("Failed to initialize cynara client " << cynaraErrorCodeToString(cynaraLastResult));
+ return (false);
+ }
+
+ return (true);
}
-void NetherCynaraBackend::statusCallback(int oldFd, int newFd, cynara_async_status status, void *data)
+void NetherCynaraBackend::statusCallback(int , int newFd, cynara_async_status status, void *data)
{
- NetherCynaraBackend *backend = static_cast<NetherCynaraBackend *>(data);
+ NetherCynaraBackend *backend = static_cast<NetherCynaraBackend *>(data);
- if (status == CYNARA_STATUS_FOR_READ)
- backend->setCynaraDescriptor(newFd, NetherDescriptorStatus::readOnly);
+ if(status == CYNARA_STATUS_FOR_READ)
+ backend->setCynaraDescriptor(newFd, NetherDescriptorStatus::readOnly);
- if (status == CYNARA_STATUS_FOR_RW)
- backend->setCynaraDescriptor(newFd, NetherDescriptorStatus::readWrite);
+ if(status == CYNARA_STATUS_FOR_RW)
+ backend->setCynaraDescriptor(newFd, NetherDescriptorStatus::readWrite);
}
void NetherCynaraBackend::checkCallback(cynara_check_id check_id,
- cynara_async_call_cause cause,
- int response,
- void *data)
+ cynara_async_call_cause cause,
+ int response,
+ void *data)
{
- NetherCynaraBackend *backend = static_cast<NetherCynaraBackend *>(data);
+ NetherCynaraBackend *backend = static_cast<NetherCynaraBackend *>(data);
- if (cause == CYNARA_CALL_CAUSE_ANSWER)
- backend->setCynaraVerdict (check_id, response);
- else
- LOGI("unknown reason for call cause="<< cause <<" response="<< response);
+ if(cause == CYNARA_CALL_CAUSE_ANSWER)
+ backend->setCynaraVerdict(check_id, response);
+ else
+ LOGI("unknown reason for call cause="<< cause <<" response="<< response);
}
-const bool NetherCynaraBackend::enqueueVerdict (const NetherPacket &packet)
+bool NetherCynaraBackend::enqueueVerdict(const NetherPacket &packet)
{
- char user[NETHER_MAX_USER_LEN];
- cynara_check_id checkId;
-
- snprintf (user, sizeof(user), "%d", packet.uid);
-
- cynaraLastResult = cynara_async_check_cache(cynaraContext, packet.securityContext.c_str(), "", user, NETHER_CYNARA_INTERNET_PRIVILEGE);
-
- LOGD ("cynara_async_check_cache ctx=" << packet.securityContext.c_str() << " user=" << user << " privilege=" << NETHER_CYNARA_INTERNET_PRIVILEGE);
-
- switch (cynaraLastResult)
- {
- case CYNARA_API_ACCESS_ALLOWED:
- LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str());
- return (castVerdict(packet, NetherVerdict::allow));
-
- case CYNARA_API_ACCESS_DENIED:
- LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str());
- return (castVerdict(packet, NetherVerdict::deny));
-
- case CYNARA_API_CACHE_MISS:
- cynaraLastResult = cynara_async_create_request(cynaraContext,
- packet.securityContext.c_str(),
- "",
- user,
- NETHER_CYNARA_INTERNET_PRIVILEGE,
- &checkId,
- &checkCallback,
- this);
- if (cynaraLastResult == CYNARA_API_SUCCESS)
- {
- responseQueue[checkId] = packet.id;
-
- return (true);
- }
- else if (cynaraLastResult == CYNARA_API_SERVICE_NOT_AVAILABLE)
- {
- LOGW("Cynara offline, fall back to another backend");
- return (false);
- }
- else
- {
- LOGW("Error on cynara request create after CYNARA_API_CACHE_MISS " << cynaraErrorCodeToString(cynaraLastResult));
- return (false);
- }
-
- default:
- LOGW("Error on cynara request create unhandled result from cynara_async_check_cache "<<cynaraErrorCodeToString(cynaraLastResult));
- return (false);
- }
-
- return (true);
+ cynara_check_id checkId;
+
+ cynaraLastResult = cynara_async_check_cache(cynaraContext, packet.securityContext.c_str(), "", std::to_string(packet.uid).c_str(), NETHER_CYNARA_INTERNET_PRIVILEGE);
+
+ LOGD("cynara_async_check_cache ctx=" << packet.securityContext.c_str() << " user=" << std::to_string(packet.uid).c_str() << " privilege=" << NETHER_CYNARA_INTERNET_PRIVILEGE);
+
+ switch(cynaraLastResult)
+ {
+ case CYNARA_API_ACCESS_ALLOWED:
+ LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str());
+ return (castVerdict(packet, NetherVerdict::allow));
+
+ case CYNARA_API_ACCESS_DENIED:
+ LOGD(cynaraErrorCodeToString(cynaraLastResult).c_str());
+ return (castVerdict(packet, NetherVerdict::deny));
+
+ case CYNARA_API_CACHE_MISS:
+ cynaraLastResult = cynara_async_create_request(cynaraContext,
+ packet.securityContext.c_str(),
+ "",
+ std::to_string(packet.uid).c_str(),
+ NETHER_CYNARA_INTERNET_PRIVILEGE,
+ &checkId,
+ &checkCallback,
+ this);
+ if(cynaraLastResult == CYNARA_API_SUCCESS)
+ {
+ responseQueue[checkId] = packet.id;
+
+ return (true);
+ }
+ else
+ if(cynaraLastResult == CYNARA_API_SERVICE_NOT_AVAILABLE)
+ {
+ LOGW("Cynara offline, fall back to another backend");
+ return (false);
+ }
+ else
+ {
+ LOGW("Error on cynara request create after CYNARA_API_CACHE_MISS " << cynaraErrorCodeToString(cynaraLastResult));
+ return (false);
+ }
+
+ default:
+ LOGW("Error on cynara request create unhandled result from cynara_async_check_cache "<<cynaraErrorCodeToString(cynaraLastResult));
+ return (false);
+ }
+
+ return (true);
}
void NetherCynaraBackend::setCynaraVerdict(cynara_check_id checkId, int cynaraResult)
{
- u_int32_t packetId = 0;
- if ((packetId = responseQueue[checkId]) >= 0)
- {
- responseQueue[checkId] = -1;
+ u_int32_t packetId = 0;
+ if((packetId = responseQueue[checkId]) >= 0)
+ {
+ responseQueue[checkId] = -1;
- if (cynaraResult == CYNARA_API_ACCESS_ALLOWED)
- castVerdict (packetId, NetherVerdict::allow);
- else
- castVerdict (packetId, NetherVerdict::deny);
+ if(cynaraResult == CYNARA_API_ACCESS_ALLOWED)
+ castVerdict(packetId, NetherVerdict::allow);
+ else
+ castVerdict(packetId, NetherVerdict::deny);
- return;
- }
+ return;
+ }
- LOGW("checkId=" << checkId << " has no assosiated packetId");
+ LOGW("checkId=" << checkId << " has no assosiated packetId");
}
-const bool NetherCynaraBackend::isValid()
+int NetherCynaraBackend::getDescriptor()
{
- return ((cynaraLastResult == CYNARA_API_SUCCESS ? true : false) && cynaraContext);
+ return (currentCynaraDescriptor);
}
-const int NetherCynaraBackend::getDescriptor()
+NetherDescriptorStatus NetherCynaraBackend::getDescriptorStatus()
{
- return (currentCynaraDescriptor);
-}
-
-const NetherDescriptorStatus NetherCynaraBackend::getDescriptorStatus()
-{
- return (currentCynaraDescriptorStatus);
+ return (currentCynaraDescriptorStatus);
}
void NetherCynaraBackend::setCynaraDescriptor(const int _currentCynaraDescriptor, const NetherDescriptorStatus _currentCynaraDescriptorStatus)
{
- currentCynaraDescriptorStatus = _currentCynaraDescriptorStatus;
- currentCynaraDescriptor = _currentCynaraDescriptor;
+ currentCynaraDescriptorStatus = _currentCynaraDescriptorStatus;
+ currentCynaraDescriptor = _currentCynaraDescriptor;
}
-const bool NetherCynaraBackend::processEvents()
+bool NetherCynaraBackend::processEvents()
{
- int ret = cynara_async_process(cynaraContext);
+ int ret = cynara_async_process(cynaraContext);
- if (ret == CYNARA_API_SUCCESS)
- return (true);
+ if(ret == CYNARA_API_SUCCESS)
+ return (true);
- LOGW("cynara_async_process failed " << cynaraErrorCodeToString(ret));
- return (false);
+ LOGW("cynara_async_process failed " << cynaraErrorCodeToString(ret));
+ return (false);
}
#endif
#include "nether_FileBackend.h"
-NetherFileBackend::NetherFileBackend (const NetherConfig &netherConfig)
- : NetherPolicyBackend(netherConfig)
+NetherFileBackend::NetherFileBackend(const NetherConfig &netherConfig)
+ : NetherPolicyBackend(netherConfig)
{
}
{
}
-const bool NetherFileBackend::isValid()
+bool NetherFileBackend::initialize()
{
- return (true);
-}
-
-const bool NetherFileBackend::initialize()
-{
- std::ifstream policyFile;
- policyFile.open (netherConfig.backupBackendArgs, std::ifstream::in);
+ std::ifstream policyFile;
+ policyFile.open(netherConfig.backupBackendArgs, std::ifstream::in);
- if (!policyFile)
- {
- LOGE("Can't open policy file at: " << netherConfig.backupBackendArgs);
- return (false);
- }
+ if(!policyFile)
+ {
+ LOGE("Can't open policy file at: " << netherConfig.backupBackendArgs);
+ return (false);
+ }
- return (parsePolicyFile(policyFile));
+ return (parsePolicyFile(policyFile));
}
-const bool NetherFileBackend::reload()
+bool NetherFileBackend::reload()
{
- return (initialize());
+ return (initialize());
}
-const bool NetherFileBackend::enqueueVerdict(const NetherPacket &packet)
+bool NetherFileBackend::enqueueVerdict(const NetherPacket &packet)
{
- for (auto &policyIterator : policy)
- {
- if (
- ( (policyIterator.uid == packet.uid) || policyIterator.uid == NETHER_INVALID_UID ) &&
- ( (policyIterator.gid == packet.gid) || policyIterator.gid == NETHER_INVALID_GID ) &&
- ( (policyIterator.securityContext == packet.securityContext) || policyIterator.securityContext.empty() )
- )
- {
- LOGD("policy match " << dumpPolicyEntry(policyIterator));
- return (castVerdict(packet, policyIterator.verdict));
- }
- }
-
- return (castVerdict(packet, netherConfig.defaultVerdict));
+ for(auto &policyIterator : policy)
+ {
+ if(
+ ((policyIterator.uid == packet.uid) || policyIterator.uid == NETHER_INVALID_UID) &&
+ ((policyIterator.gid == packet.gid) || policyIterator.gid == NETHER_INVALID_GID) &&
+ ((policyIterator.securityContext == packet.securityContext) || policyIterator.securityContext.empty())
+ )
+ {
+ LOGD("policy match " << dumpPolicyEntry(policyIterator));
+ return (castVerdict(packet, policyIterator.verdict));
+ }
+ }
+
+ return (castVerdict(packet, netherConfig.defaultVerdict));
}
-const bool NetherFileBackend::parsePolicyFile(std::ifstream &policyFile)
+bool NetherFileBackend::parsePolicyFile(std::ifstream &policyFile)
{
- std::string line;
- std::vector<std::string> tokens;
- policy.clear();
-
- while (!policyFile.eof())
- {
- getline(policyFile, line);
- if (line[0] == '#' || line.empty() || !line.find(NETHER_POLICY_CREDS_DELIM, 0))
- continue;
-
- tokens = split (line, NETHER_POLICY_CREDS_DELIM);
-
- if (tokens.size() > 0)
- {
- PolicyEntry entry { tokens[uidT].empty() ? NETHER_INVALID_UID : (uid_t)strtol(tokens[uidT].c_str(), NULL, 10), /* uid */
- tokens[gidT].empty() ? NETHER_INVALID_GID : (gid_t)strtol(tokens[gidT].c_str(), NULL, 10), /* gid */
- tokens[secctxT], /* security context */
- stringToVerdict((char *)tokens[verdictT].c_str()) /* verdict */
- };
-
- LOGD("\t"<<dumpPolicyEntry(entry).c_str());
- policy.push_back(entry);
- }
- }
-
- return (true);
+ std::string line;
+ std::vector<std::string> tokens;
+ policy.clear();
+
+ while(!policyFile.eof())
+ {
+ getline(policyFile, line);
+ if(line[0] == '#' || line.empty() || !line.find(NETHER_POLICY_CREDS_DELIM, 0))
+ continue;
+
+ tokens = split(line, NETHER_POLICY_CREDS_DELIM);
+
+ if(tokens.size() > 0)
+ {
+ PolicyEntry entry { tokens[PolicyFileTokens::uidToken].empty() ?
+ NETHER_INVALID_UID :
+ (uid_t)strtol(tokens[PolicyFileTokens::uidToken].c_str(), NULL, 10),
+ tokens[PolicyFileTokens::gidToken].empty() ?
+ NETHER_INVALID_GID :
+ (gid_t)strtol(tokens[PolicyFileTokens::gidToken].c_str(), NULL, 10),
+ tokens[PolicyFileTokens::secctxToken],
+ stringToVerdict((char *)tokens[PolicyFileTokens::verdictToken].c_str())
+ };
+
+ LOGD("\t"<<dumpPolicyEntry(entry).c_str());
+ policy.push_back(entry);
+ }
+ }
+
+ return (true);
}
std::vector<std::string> NetherFileBackend::split(const std::string &str, const std::string &delim)
{
- std::vector<std::string> tokens;
- size_t start = 0, end = 0;
+ std::vector<std::string> tokens;
+ size_t start = 0, end = 0;
- while (end != std::string::npos)
- {
- end = str.find(delim, start);
+ while(end != std::string::npos)
+ {
+ end = str.find(delim, start);
- // If at end, use length=maxLength. Else use length=end-start.
- tokens.push_back(str.substr(start, (end == std::string::npos) ? std::string::npos : end - start));
+ // If at end, use length=maxLength. Else use length=end-start.
+ tokens.push_back(str.substr(start, (end == std::string::npos) ? std::string::npos : end - start));
- // If at end, use start=maxSize. Else use start=end+delimiter.
- start = ((end > (std::string::npos - delim.size())) ? std::string::npos : end + delim.size());
- }
+ // If at end, use start=maxSize. Else use start=end+delimiter.
+ start = ((end > (std::string::npos - delim.size())) ? std::string::npos : end + delim.size());
+ }
- return (tokens);
+ return (tokens);
}
int main(int argc, char *argv[])
{
- int optionIndex, c;
- struct NetherConfig netherConfig;
+ int optionIndex, c;
+ struct NetherConfig netherConfig;
- static struct option longOptions[] =
- {
- #if defined(HAVE_AUDIT)
- {"enable-audit", no_argument, &netherConfig.enableAudit, 0},
+ static struct option longOptions[] =
+ {
+#if defined(HAVE_AUDIT)
+ {"enable-audit", no_argument, &netherConfig.enableAudit, 0},
#endif
- {"daemon", no_argument, &netherConfig.daemonMode, 0},
- {"no-rules", no_argument, &netherConfig.noRules, 0},
- {"log", required_argument, 0, 'l'},
- {"log-args", required_argument, 0, 'L'},
- {"default-verdict", required_argument, 0, 'V'},
- {"primary-backend", required_argument, 0, 'p'},
- {"primary-backend-args", required_argument, 0, 'P'},
- {"backup-backend", required_argument, 0, 'b'},
- {"backup-backend-args", required_argument, 0, 'B'},
- {"queue-num", required_argument, 0, 'q'},
- {"mark-deny", required_argument, 0, 'm'},
- {"mark-allow-log", required_argument, 0, 'M'},
- {"rules-path", required_argument, 0, 'r'},
- {"iptables-restore-path", required_argument, 0, 'i'},
- {"help", no_argument, 0, 'h'},
- {0, 0, 0, 0}
- };
-
- while (1)
- {
- c = getopt_long (argc, argv, ":daxl:L:V:p:P:b:B:q:m:M:a:r:i:h", longOptions, &optionIndex);
-
- if (c == -1)
- break;
-
- switch (c)
- {
- case 0:
- break;
-
- case 'd':
- netherConfig.daemonMode = 1;
- break;
- case 'x':
- netherConfig.noRules = 1;
- break;
-
- #if defined(HAVE_AUDIT)
- case 'a':
- netherConfig.enableAudit = 1;
- break;
+ {"daemon", no_argument, &netherConfig.daemonMode, 0},
+ {"no-rules", no_argument, &netherConfig.noRules, 0},
+ {"log", required_argument, 0, 'l'},
+ {"log-args", required_argument, 0, 'L'},
+ {"default-verdict", required_argument, 0, 'V'},
+ {"primary-backend", required_argument, 0, 'p'},
+ {"primary-backend-args", required_argument, 0, 'P'},
+ {"backup-backend", required_argument, 0, 'b'},
+ {"backup-backend-args", required_argument, 0, 'B'},
+ {"queue-num", required_argument, 0, 'q'},
+ {"mark-deny", required_argument, 0, 'm'},
+ {"mark-allow-log", required_argument, 0, 'M'},
+ {"rules-path", required_argument, 0, 'r'},
+ {"iptables-restore-path", required_argument, 0, 'i'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ while(1)
+ {
+ c = getopt_long(argc, argv, ":daxl:L:V:p:P:b:B:q:m:M:a:r:i:h", longOptions, &optionIndex);
+
+ if(c == -1)
+ break;
+
+ switch(c)
+ {
+ case 0:
+ break;
+
+ case 'd':
+ netherConfig.daemonMode = 1;
+ break;
+ case 'x':
+ netherConfig.noRules = 1;
+ break;
+
+#if defined(HAVE_AUDIT)
+ case 'a':
+ netherConfig.enableAudit = 1;
+ break;
#endif
- case 'l':
- netherConfig.logBackend = stringToLogBackendType(optarg);
- break;
-
- case 'L':
- netherConfig.logBackendArgs = optarg;
- break;
-
- case 'V':
- netherConfig.defaultVerdict = stringToVerdict (optarg);
- break;
-
- case 'p':
- netherConfig.primaryBackendType = stringToBackendType (optarg);
- break;
-
- case 'P':
- netherConfig.primaryBackendArgs = optarg;
- break;
-
- case 'b':
- netherConfig.backupBackendType = stringToBackendType (optarg);
- break;
-
- case 'B':
- netherConfig.backupBackendArgs = optarg;
- break;
-
- case 'q':
- if (atoi(optarg) < 0 || atoi(optarg) >= 65535)
- {
- cerr << "Queue number is invalid (must be >= 0 and < 65535): " << atoi(optarg);
- exit (1);
- }
- netherConfig.queueNumber = atoi(optarg);
- break;
-
- case 'm':
- if (atoi(optarg) <= 0 || atoi(optarg) >= 255)
- {
- cerr << "Packet mark for DENY is invalid (must be > 0 and < 255): " << atoi(optarg);
- exit (1);
- }
- netherConfig.markDeny = atoi(optarg);
- break;
-
- case 'M':
- if (atoi(optarg) <= 0 || atoi(optarg) >= 255)
- {
- cerr << "Packet mark for ALLOW_LOG is invalid (must be > 0 and < 255): " << atoi(optarg);
- exit (1);
- }
- netherConfig.markAllowAndLog = atoi(optarg);
- break;
-
- case 'r':
- netherConfig.rulesPath = optarg;
- break;
-
- case 'i':
- netherConfig.iptablesRestorePath = optarg;
- break;
-
- case 'h':
- showHelp (argv[0]);
- exit (1);
- }
- }
- switch (netherConfig.logBackend)
- {
- case NetherLogBackendType::stderrBackend:
- logger::Logger::setLogBackend (new logger::StderrBackend(false));
- break;
- case NetherLogBackendType::syslogBackend:
- logger::Logger::setLogBackend (new logger::SyslogBackend());
- break;
- case NetherLogBackendType::logfileBackend:
- logger::Logger::setLogBackend (new logger::FileBackend(netherConfig.logBackendArgs));
- break;
+ case 'l':
+ netherConfig.logBackend = stringToLogBackendType(optarg);
+ break;
+
+ case 'L':
+ netherConfig.logBackendArgs = optarg;
+ break;
+
+ case 'V':
+ netherConfig.defaultVerdict = stringToVerdict(optarg);
+ break;
+
+ case 'p':
+ netherConfig.primaryBackendType = stringToBackendType(optarg);
+ break;
+
+ case 'P':
+ netherConfig.primaryBackendArgs = optarg;
+ break;
+
+ case 'b':
+ netherConfig.backupBackendType = stringToBackendType(optarg);
+ break;
+
+ case 'B':
+ netherConfig.backupBackendArgs = optarg;
+ break;
+
+ case 'q':
+ if(atoi(optarg) < 0 || atoi(optarg) >= 65535)
+ {
+ cerr << "Queue number is invalid (must be >= 0 and < 65535): " << atoi(optarg);
+ exit(1);
+ }
+ netherConfig.queueNumber = atoi(optarg);
+ break;
+
+ case 'm':
+ if(atoi(optarg) <= 0 || atoi(optarg) >= 255)
+ {
+ cerr << "Packet mark for DENY is invalid (must be > 0 and < 255): " << atoi(optarg);
+ exit(1);
+ }
+ netherConfig.markDeny = atoi(optarg);
+ break;
+
+ case 'M':
+ if(atoi(optarg) <= 0 || atoi(optarg) >= 255)
+ {
+ cerr << "Packet mark for ALLOW_LOG is invalid (must be > 0 and < 255): " << atoi(optarg);
+ exit(1);
+ }
+ netherConfig.markAllowAndLog = atoi(optarg);
+ break;
+
+ case 'r':
+ netherConfig.rulesPath = optarg;
+ break;
+
+ case 'i':
+ netherConfig.iptablesRestorePath = optarg;
+ break;
+
+ case 'h':
+ showHelp(argv[0]);
+ exit(1);
+ }
+ }
+ switch(netherConfig.logBackend)
+ {
+ case NetherLogBackendType::stderrBackend:
+ logger::Logger::setLogBackend(new logger::StderrBackend(false));
+ break;
+ case NetherLogBackendType::syslogBackend:
+ logger::Logger::setLogBackend(new logger::SyslogBackend());
+ break;
+ case NetherLogBackendType::logfileBackend:
+ logger::Logger::setLogBackend(new logger::FileBackend(netherConfig.logBackendArgs));
+ break;
#if defined(HAVE_SYSTEMD_JOURNAL)
- case NetherLogBackendType::journalBackend:
- logger::Logger::setLogBackend (new logger::SystemdJournalBackend());
- break;
+ case NetherLogBackendType::journalBackend:
+ logger::Logger::setLogBackend(new logger::SystemdJournalBackend());
+ break;
#endif
- default:
- logger::Logger::setLogBackend (new logger::StderrBackend(false));
- break;
- }
+ default:
+ logger::Logger::setLogBackend(new logger::StderrBackend(false));
+ break;
+ }
- LOGD("NETHER OPTIONS:"
+ LOGD("NETHER OPTIONS:"
#if defined(_DEBUG)
- << " debug"
+ << " debug"
#endif
- << " daemon=" << netherConfig.daemonMode
- << " queue=" << netherConfig.queueNumber);
- LOGD("primary-backend=" << backendTypeToString (netherConfig.primaryBackendType)
- << " primary-backend-args=" << netherConfig.primaryBackendArgs);
- LOGD("backup-backend=" << backendTypeToString (netherConfig.backupBackendType)
- << " backup-backend-args=" << netherConfig.backupBackendArgs);
- LOGD("default-verdict=" << verdictToString(netherConfig.defaultVerdict)
- << " mark-deny=" << (int)netherConfig.markDeny
- << " mark-allow-log=" << (int)netherConfig.markAllowAndLog);
- LOGD("log-backend=" << logBackendTypeToString(netherConfig.logBackend)
- << " log-backend-args=" << netherConfig.logBackendArgs);
- LOGD("enable-audit=" << (netherConfig.enableAudit ? "yes" : "no")
- << " rules-path=" << netherConfig.rulesPath);
- LOGD("no-rules=" << (netherConfig.noRules ? "yes" : "no")
- << " iptables-restore-path=" << netherConfig.iptablesRestorePath);
-
- NetherManager manager (netherConfig);
-
- if (!manager.initialize())
- {
- LOGE("NetherManager failed to initialize, exiting");
- return (1);
- }
-
- if (netherConfig.daemonMode)
- {
- if (!runAsDaemon())
- {
- LOGE("Failed to run as daemon: " << strerror(errno));
- exit (1);
- }
- }
-
- manager.process();
-
- return (0);
+ << " daemon=" << netherConfig.daemonMode
+ << " queue=" << netherConfig.queueNumber);
+ LOGD("primary-backend=" << backendTypeToString(netherConfig.primaryBackendType)
+ << " primary-backend-args=" << netherConfig.primaryBackendArgs);
+ LOGD("backup-backend=" << backendTypeToString(netherConfig.backupBackendType)
+ << " backup-backend-args=" << netherConfig.backupBackendArgs);
+ LOGD("default-verdict=" << verdictToString(netherConfig.defaultVerdict)
+ << " mark-deny=" << (int)netherConfig.markDeny
+ << " mark-allow-log=" << (int)netherConfig.markAllowAndLog);
+ LOGD("log-backend=" << logBackendTypeToString(netherConfig.logBackend)
+ << " log-backend-args=" << netherConfig.logBackendArgs);
+ LOGD("enable-audit=" << (netherConfig.enableAudit ? "yes" : "no")
+ << " rules-path=" << netherConfig.rulesPath);
+ LOGD("no-rules=" << (netherConfig.noRules ? "yes" : "no")
+ << " iptables-restore-path=" << netherConfig.iptablesRestorePath);
+
+ NetherManager manager(netherConfig);
+
+ if(!manager.initialize())
+ {
+ LOGE("NetherManager failed to initialize, exiting");
+ return (1);
+ }
+
+ if(netherConfig.daemonMode)
+ {
+ if(!runAsDaemon())
+ {
+ LOGE("Failed to run as daemon: " << strerror(errno));
+ exit(1);
+ }
+ }
+
+ manager.process();
+
+ return (0);
}
void showHelp(char *arg)
{
- cout<< "Usage:\t"<< arg << " [OPTIONS]\n\n";
- cout<< " -d,--daemon\t\t\t\tRun as daemon in the background (default:no)\n";
- cout<< " -x,--no-rules\t\t\t\tDon't load iptables rules on start (default:no)\n";
- cout<< " -l,--log=<backend>\t\t\tSet logging backend STDERR,SYSLOG";
+ cout<< "Usage:\t"<< arg << " [OPTIONS]\n\n";
+ cout<< " -d,--daemon\t\t\t\tRun as daemon in the background (default:no)\n";
+ cout<< " -x,--no-rules\t\t\t\tDon't load iptables rules on start (default:no)\n";
+ cout<< " -l,--log=<backend>\t\t\tSet logging backend STDERR,SYSLOG";
#if defined(HAVE_SYSTEMD_JOURNAL)
- cout << ",JOURNAL\n";
+ cout << ",JOURNAL\n";
#endif
- cout<< "(default:"<< logBackendTypeToString(NETHER_LOG_BACKEND) << ")\n";
- cout<< " -L,--log-args=<arguments>\t\tSet logging backend arguments\n";
- cout<< " -V,--verdict=<verdict>\t\tWhat verdict to cast when policy backend is not available\n\t\t\t\t\tACCEPT,ALLOW_LOG,DENY (default:"<<verdictToString(NETHER_DEFAULT_VERDICT)<<")\n";
- cout<< " -p,--primary-backend=<module>\t\tPrimary policy backend\n\t\t\t\t\t";
+ cout<< "(default:"<< logBackendTypeToString(NETHER_LOG_BACKEND) << ")\n";
+ cout<< " -L,--log-args=<arguments>\t\tSet logging backend arguments\n";
+ cout<< " -V,--verdict=<verdict>\t\tWhat verdict to cast when policy backend is not available\n\t\t\t\t\tACCEPT,ALLOW_LOG,DENY (default:"<<verdictToString(NETHER_DEFAULT_VERDICT)<<")\n";
+ cout<< " -p,--primary-backend=<module>\t\tPrimary policy backend\n\t\t\t\t\t";
#if defined(HAVE_CYNARA)
- cout << "CYNARA";
+ cout << "CYNARA";
#endif
- cout<< ",FILE,NONE (defualt:"<< backendTypeToString(NETHER_PRIMARY_BACKEND)<<")\n";
- cout<< " -P,--primary-backend-args=<arguments>\tPrimary policy backend arguments\n";
- cout<< " -b,--backup-backend=<module>\t\tBackup policy backend\n\t\t\t\t\t";
+ cout<< ",FILE,NONE (defualt:"<< backendTypeToString(NETHER_PRIMARY_BACKEND)<<")\n";
+ cout<< " -P,--primary-backend-args=<arguments>\tPrimary policy backend arguments\n";
+ cout<< " -b,--backup-backend=<module>\t\tBackup policy backend\n\t\t\t\t\t";
#if defined(HAVE_CYNARA)
- cout<< "CYNARA";
+ cout<< "CYNARA";
#endif
- cout<< ",FILE,NONE (defualt:"<< backendTypeToString(NETHER_BACKUP_BACKEND)<< ")\n";
- cout<< " -B,--backup-backend-args=<arguments>\tBackup policy backend arguments (default:" << NETHER_POLICY_FILE << ")\n";
- cout<< " -q,--queue-num=<queue number>\t\tNFQUEUE queue number to use for receiving packets\n";
- cout<< " -m,--mark-deny=<mark>\t\t\tPacket mark to use for DENY verdicts (default:"<< NETLINK_DROP_MARK << ")\n";
- cout<< " -M,--mark-allow-log=<mark>\t\tPacket mark to use for ALLOW_LOG verdicts (default:" << NETLINK_ALLOWLOG_MARK << ")\n";
+ cout<< ",FILE,NONE (defualt:"<< backendTypeToString(NETHER_BACKUP_BACKEND)<< ")\n";
+ cout<< " -B,--backup-backend-args=<arguments>\tBackup policy backend arguments (default:" << NETHER_POLICY_FILE << ")\n";
+ cout<< " -q,--queue-num=<queue number>\t\tNFQUEUE queue number to use for receiving packets\n";
+ cout<< " -m,--mark-deny=<mark>\t\t\tPacket mark to use for DENY verdicts (default:"<< NETLINK_DROP_MARK << ")\n";
+ cout<< " -M,--mark-allow-log=<mark>\t\tPacket mark to use for ALLOW_LOG verdicts (default:" << NETLINK_ALLOWLOG_MARK << ")\n";
#if defined(HAVE_AUDIT)
- cout<< " -a,--enable-audit\t\t\tEnable the auditing subsystem (default: no)\n";
+ cout<< " -a,--enable-audit\t\t\tEnable the auditing subsystem (default: no)\n";
#endif
- cout<< " -r,--rules-path=<path>\t\tPath to iptables rules file (default:" << NETHER_RULES_PATH << ")\n";
- cout<< " -i,--iptables-restore-path=<path>\tPath to iptables-restore command (default:" << NETHER_IPTABLES_RESTORE_PATH << ")\n";
- cout<< " -h,--help\t\t\t\tshow help information\n";
+ cout<< " -r,--rules-path=<path>\t\tPath to iptables rules file (default:" << NETHER_RULES_PATH << ")\n";
+ cout<< " -i,--iptables-restore-path=<path>\tPath to iptables-restore command (default:" << NETHER_IPTABLES_RESTORE_PATH << ")\n";
+ cout<< " -h,--help\t\t\t\tshow help information\n";
}
#include "nether_DummyBackend.h"
NetherManager::NetherManager(const NetherConfig &_netherConfig)
- : netherConfig(_netherConfig),
- netherPrimaryPolicyBackend(nullptr),
- netherBackupPolicyBackend(nullptr),
- netherFallbackPolicyBackend(nullptr)
+ : netherPrimaryPolicyBackend(nullptr),
+ netherBackupPolicyBackend(nullptr),
+ netherFallbackPolicyBackend(nullptr),
+ netherConfig(_netherConfig)
{
- netherNetlink = std::unique_ptr<NetherNetlink> (new NetherNetlink(netherConfig));
- netherNetlink->setListener (this);
+ netherNetlink = std::unique_ptr<NetherNetlink> (new NetherNetlink(netherConfig));
+ netherNetlink->setListener(this);
- netherPrimaryPolicyBackend = std::unique_ptr<NetherPolicyBackend> (getPolicyBackend (netherConfig));
- netherPrimaryPolicyBackend->setListener (this);
+ netherPrimaryPolicyBackend = std::unique_ptr<NetherPolicyBackend> (getPolicyBackend(netherConfig));
+ netherPrimaryPolicyBackend->setListener(this);
- netherBackupPolicyBackend = std::unique_ptr<NetherPolicyBackend> (getPolicyBackend (netherConfig, false));
- netherBackupPolicyBackend->setListener (this);
+ netherBackupPolicyBackend = std::unique_ptr<NetherPolicyBackend> (getPolicyBackend(netherConfig, false));
+ netherBackupPolicyBackend->setListener(this);
- netherFallbackPolicyBackend = std::unique_ptr<NetherPolicyBackend> (new NetherDummyBackend(netherConfig));
+ netherFallbackPolicyBackend = std::unique_ptr<NetherPolicyBackend> (new NetherDummyBackend(netherConfig));
}
NetherManager::~NetherManager()
{
- close (signalDescriptor);
+ close(signalDescriptor);
}
-const bool NetherManager::initialize()
+bool NetherManager::initialize()
{
- sigemptyset(&signalMask);
- sigaddset(&signalMask, SIGHUP);
-
- if (sigprocmask(SIG_BLOCK, &signalMask, NULL) == -1)
- {
- LOGE("Failed to block signals sigprocmask()");
- return (false);
- }
-
- signalDescriptor = signalfd(-1, &signalMask, 0);
- if (signalDescriptor == -1)
- {
- LOGE("Failed acquire signalfd descriptor");
- return (false);
- }
-
- if (netherConfig.noRules == 0 && restoreRules() == false)
- {
- LOGE("Failed to setup iptables rules");
- return (false);
- }
+ sigemptyset(&signalMask);
+ sigaddset(&signalMask, SIGHUP);
+
+ if(sigprocmask(SIG_BLOCK, &signalMask, NULL) == -1)
+ {
+ LOGE("Failed to block signals sigprocmask()");
+ return (false);
+ }
+
+ signalDescriptor = signalfd(-1, &signalMask, 0);
+ if(signalDescriptor == -1)
+ {
+ LOGE("Failed acquire signalfd descriptor");
+ return (false);
+ }
+
+ if(netherConfig.noRules == 0 && restoreRules() == false)
+ {
+ LOGE("Failed to setup iptables rules");
+ return (false);
+ }
#ifdef HAVE_AUDIT
- if (netherConfig.enableAudit)
- {
- if ( (auditDescriptor = audit_open ()) == -1)
- {
- LOGE("Failed to open an audit netlink socket: " << strerror(errno));
- return (false);
- }
-
- if (audit_set_enabled (auditDescriptor, 1) <= 0)
- {
- LOGE("Failed to enable auditing: " << strerror(errno));
- return (false);
- }
- else
- {
- LOGD("Auditing enabled");
- }
- }
+ if(netherConfig.enableAudit)
+ {
+ if((auditDescriptor = audit_open()) == -1)
+ {
+ LOGE("Failed to open an audit netlink socket: " << strerror(errno));
+ return (false);
+ }
+
+ if(audit_set_enabled(auditDescriptor, 1) <= 0)
+ {
+ LOGE("Failed to enable auditing: " << strerror(errno));
+ return (false);
+ }
+ else
+ {
+ LOGD("Auditing enabled");
+ }
+ }
#endif // HAVE_AUDIT
- if (!netherNetlink->initialize())
- {
- LOGE("Failed to initialize netlink subsystem, exiting");
- return (false);
- }
-
- if (!netherPrimaryPolicyBackend->initialize())
- {
- LOGE("Failed to initialize primary policy backend, exiting");
- return (false);
- }
-
- if (!netherBackupPolicyBackend->initialize())
- {
- LOGE("Failed to initialize backup backend, exiting");
- return (false);
- }
-
- if ((netlinkDescriptor = netherNetlink->getDescriptor()) == -1)
- {
- LOGE("Netlink subsystem did not return a valid descriptor, exiting");
- return (false);
- }
-
- if ((backendDescriptor = netherPrimaryPolicyBackend->getDescriptor()) == -1)
- {
- LOGI("Policy backend does not provide descriptor for select()");
- }
- return (true);
+ if(!netherNetlink->initialize())
+ {
+ LOGE("Failed to initialize netlink subsystem, exiting");
+ return (false);
+ }
+
+ if(!netherPrimaryPolicyBackend->initialize())
+ {
+ LOGE("Failed to initialize primary policy backend, exiting");
+ return (false);
+ }
+
+ if(!netherBackupPolicyBackend->initialize())
+ {
+ LOGE("Failed to initialize backup backend, exiting");
+ return (false);
+ }
+
+ if((netlinkDescriptor = netherNetlink->getDescriptor()) == -1)
+ {
+ LOGE("Netlink subsystem did not return a valid descriptor, exiting");
+ return (false);
+ }
+
+ if((backendDescriptor = netherPrimaryPolicyBackend->getDescriptor()) == -1)
+ {
+ LOGI("Policy backend does not provide descriptor for select()");
+ }
+ return (true);
}
-const bool NetherManager::process()
-{\r
- fd_set watchedReadDescriptorsSet, watchedWriteDescriptorsSet;\r
- struct timeval timeoutSpecification;\r
-\r
- for (;;)\r
- {\r
- setupSelectSockets (watchedReadDescriptorsSet, watchedWriteDescriptorsSet, timeoutSpecification);
-\r
- if (select (FD_SETSIZE, &watchedReadDescriptorsSet, &watchedWriteDescriptorsSet, NULL, &timeoutSpecification) < 0)\r
- {\r
- LOGE("select error " << strerror(errno));\r
- return (false);\r
- }\r
-
- if (FD_ISSET(signalDescriptor, &watchedReadDescriptorsSet))
- {
- handleSignal();
- }\r
- if (FD_ISSET(netlinkDescriptor, &watchedReadDescriptorsSet))\r
- {
- if (!handleNetlinkpacket())
- break;\r
- }
- else if (FD_ISSET(backendDescriptor, &watchedReadDescriptorsSet) || FD_ISSET(backendDescriptor, &watchedWriteDescriptorsSet))
- {
- netherPrimaryPolicyBackend->processEvents();
- }
- else
- {
- LOGD("select() timeout");
- }
- }
+bool NetherManager::process()
+{
+ fd_set watchedReadDescriptorsSet, watchedWriteDescriptorsSet;
+ struct timeval timeoutSpecification;
+
+ for(;;)
+ {
+ setupSelectSockets(watchedReadDescriptorsSet, watchedWriteDescriptorsSet, timeoutSpecification);
+
+ if(select(FD_SETSIZE, &watchedReadDescriptorsSet, &watchedWriteDescriptorsSet, NULL, &timeoutSpecification) < 0)
+ {
+ LOGE("select error " << strerror(errno));
+ return (false);
+ }
+
+ if(FD_ISSET(signalDescriptor, &watchedReadDescriptorsSet))
+ {
+ handleSignal();
+ }
+ if(FD_ISSET(netlinkDescriptor, &watchedReadDescriptorsSet))
+ {
+ if(!handleNetlinkpacket())
+ break;
+ }
+ else
+ if(FD_ISSET(backendDescriptor, &watchedReadDescriptorsSet) || FD_ISSET(backendDescriptor, &watchedWriteDescriptorsSet))
+ {
+ netherPrimaryPolicyBackend->processEvents();
+ }
+ else
+ {
+ LOGD("select() timeout");
+ }
+ }
+
+ return (true);
}
void NetherManager::handleSignal()
{
- LOGD("received signal");
- ssize_t signalRead;
- struct signalfd_siginfo signalfdSignalInfo;
-
- signalRead = read (signalDescriptor, &signalfdSignalInfo, sizeof(struct signalfd_siginfo));
-
- if (signalRead != sizeof(struct signalfd_siginfo))
- {
- LOGW("Received incomplete signal information, ignore");
- return;
- }
-
- if (signalfdSignalInfo.ssi_signo == SIGHUP)
- {
- LOGI("SIGHUP received, reloading");
- if (!netherPrimaryPolicyBackend->reload())
- LOGW("primary backend failed to reload");
- if (!netherBackupPolicyBackend->reload())
- LOGW("backup backend failed to reload");
- if (!netherNetlink->reload())
- LOGW("netlink failed to reload");
- }
+ LOGD("received signal");
+ ssize_t signalRead;
+ struct signalfd_siginfo signalfdSignalInfo;
+
+ signalRead = read(signalDescriptor, &signalfdSignalInfo, sizeof(struct signalfd_siginfo));
+
+ if(signalRead != sizeof(struct signalfd_siginfo))
+ {
+ LOGW("Received incomplete signal information, ignore");
+ return;
+ }
+
+ if(signalfdSignalInfo.ssi_signo == SIGHUP)
+ {
+ LOGI("SIGHUP received, reloading");
+ if(!netherPrimaryPolicyBackend->reload())
+ LOGW("primary backend failed to reload");
+ if(!netherBackupPolicyBackend->reload())
+ LOGW("backup backend failed to reload");
+ if(!netherNetlink->reload())
+ LOGW("netlink failed to reload");
+ }
}
-const bool NetherManager::handleNetlinkpacket()
+bool NetherManager::handleNetlinkpacket()
{
- LOGD("netlink descriptor active");
- int packetReadSize;
- NetherPacket receivedPacket;
- char packetBuffer[NETHER_PACKET_BUFFER_SIZE] __attribute__ ((aligned));
-
- /* some data arrives on netlink, read it */\r
- if ((packetReadSize = recv(netlinkDescriptor, packetBuffer, sizeof(packetBuffer), 0)) >= 0)\r
- {
- /* try to process the packet using netfilter_queue library, fetch packet info
- needed for making a decision about it */\r
- if (netherNetlink->processPacket (packetBuffer, packetReadSize))
- {
- return (true);
- }
- else
- {
- /* if we can't process the incoming packets, it's bad. Let's exit now */
- LOGE("Failed to process netlink received packet, refusing to continue");
- return (false);
- }\r
- }
-\r
- if (packetReadSize < 0 && errno == ENOBUFS)\r
- {\r
- LOGI("NetherManager::process losing packets! [bad things might happen]");\r
- return (true);\r
- }\r
-\r
- LOGE("NetherManager::process recv failed " << strerror(errno));\r
- return (false);
+ LOGD("netlink descriptor active");
+ int packetReadSize;
+ NetherPacket receivedPacket;
+ char packetBuffer[NETHER_PACKET_BUFFER_SIZE] __attribute__((aligned));
+
+ /* some data arrives on netlink, read it */
+ if((packetReadSize = recv(netlinkDescriptor, packetBuffer, sizeof(packetBuffer), 0)) >= 0)
+ {
+ /* try to process the packet using netfilter_queue library, fetch packet info
+ needed for making a decision about it */
+ if(netherNetlink->processPacket(packetBuffer, packetReadSize))
+ {
+ return (true);
+ }
+ else
+ {
+ /* if we can't process the incoming packets, it's bad. Let's exit now */
+ LOGE("Failed to process netlink received packet, refusing to continue");
+ return (false);
+ }
+ }
+
+ if(packetReadSize < 0 && errno == ENOBUFS)
+ {
+ LOGI("NetherManager::process losing packets! [bad things might happen]");
+ return (true);
+ }
+
+ LOGE("NetherManager::process recv failed " << strerror(errno));
+ return (false);
}
void NetherManager::setupSelectSockets(fd_set &watchedReadDescriptorsSet, fd_set &watchedWriteDescriptorsSet, struct timeval &timeoutSpecification)
{
- FD_ZERO (&watchedReadDescriptorsSet);
- FD_ZERO (&watchedWriteDescriptorsSet);
-
- /* Always listen for signals */
- FD_SET (signalDescriptor, &watchedReadDescriptorsSet);
-
- if ((netlinkDescriptor = netherNetlink->getDescriptor()) >= 0)
- {\r
- FD_SET(netlinkDescriptor, &watchedReadDescriptorsSet);
- }
-
- if ((backendDescriptor = netherPrimaryPolicyBackend->getDescriptor()) >= 0)
- {
- if (netherPrimaryPolicyBackend->getDescriptorStatus() == NetherDescriptorStatus::readOnly)
- {
- FD_SET(backendDescriptor, &watchedReadDescriptorsSet);
- }
- else if (netherPrimaryPolicyBackend->getDescriptorStatus() == NetherDescriptorStatus::readWrite)
- {
- FD_SET(backendDescriptor, &watchedReadDescriptorsSet);
- FD_SET(backendDescriptor, &watchedWriteDescriptorsSet);
- }
- }
-\r
- timeoutSpecification.tv_sec = 240;\r
- timeoutSpecification.tv_usec = 0;
+ FD_ZERO(&watchedReadDescriptorsSet);
+ FD_ZERO(&watchedWriteDescriptorsSet);
+
+ /* Always listen for signals */
+ FD_SET(signalDescriptor, &watchedReadDescriptorsSet);
+
+ if((netlinkDescriptor = netherNetlink->getDescriptor()) >= 0)
+ {
+ FD_SET(netlinkDescriptor, &watchedReadDescriptorsSet);
+ }
+
+ if((backendDescriptor = netherPrimaryPolicyBackend->getDescriptor()) >= 0)
+ {
+ if(netherPrimaryPolicyBackend->getDescriptorStatus() == NetherDescriptorStatus::readOnly)
+ {
+ FD_SET(backendDescriptor, &watchedReadDescriptorsSet);
+ }
+ else
+ if(netherPrimaryPolicyBackend->getDescriptorStatus() == NetherDescriptorStatus::readWrite)
+ {
+ FD_SET(backendDescriptor, &watchedReadDescriptorsSet);
+ FD_SET(backendDescriptor, &watchedWriteDescriptorsSet);
+ }
+ }
+
+ timeoutSpecification.tv_sec = 240;
+ timeoutSpecification.tv_usec = 0;
}
NetherConfig &NetherManager::getConfig()
{
- return (netherConfig);
+ return (netherConfig);
}
NetherPolicyBackend *NetherManager::getPolicyBackend(const NetherConfig &netherConfig, const bool primary)
{
- switch (primary ? netherConfig.primaryBackendType : netherConfig.backupBackendType)
- {
- case NetherPolicyBackendType::cynaraBackend:
+ switch(primary ? netherConfig.primaryBackendType : netherConfig.backupBackendType)
+ {
+ case NetherPolicyBackendType::cynaraBackend:
#ifdef HAVE_CYNARA
- return new NetherCynaraBackend(netherConfig);
+ return new NetherCynaraBackend(netherConfig);
#else
- return new NetherDummyBackend(netherConfig);
+ return new NetherDummyBackend(netherConfig);
#endif
- case NetherPolicyBackendType::fileBackend:
- return new NetherFileBackend(netherConfig);
- case NetherPolicyBackendType::dummyBackend:
- default:
- return new NetherDummyBackend(netherConfig);
- }
+ case NetherPolicyBackendType::fileBackend:
+ return new NetherFileBackend(netherConfig);
+ case NetherPolicyBackendType::dummyBackend:
+ default:
+ return new NetherDummyBackend(netherConfig);
+ }
}
-bool NetherManager::verdictCast (const u_int32_t packetId, const NetherVerdict verdict)
+bool NetherManager::verdictCast(const u_int32_t packetId, const NetherVerdict verdict)
{
- if (netherNetlink)
- {
- netherNetlink->setVerdict(packetId, verdict);
- }
- else
- {
- LOGE("Netlink subsystem is invalid, can't decide on packet");
- return (false);
- }
-
- return (true);
+ if(netherNetlink)
+ {
+ netherNetlink->setVerdict(packetId, verdict);
+ }
+ else
+ {
+ LOGE("Netlink subsystem is invalid, can't decide on packet");
+ return (false);
+ }
+
+ return (true);
}
-void NetherManager::packetReceived (const NetherPacket &packet)
+void NetherManager::packetReceived(const NetherPacket &packet)
{
- LOGD(packetToString(packet).c_str());
-
- if (netherPrimaryPolicyBackend && netherPrimaryPolicyBackend->enqueueVerdict (packet))
- {
- LOGD("Primary policy accepted packet");
- return;
- }
-
- if (netherBackupPolicyBackend && netherBackupPolicyBackend->enqueueVerdict (packet))
- {
- LOGI("Primary policy backend failed, using backup policy backend");
- return;
- }
-
- /* In this situation no policy backend wants to deal with this packet
- there propably isn't any rule in either of them
-
- we need to make a generic decision based on whatever is hard-coded
- or passed as a parameter to the service */
- LOGW("All policy backends failed, using DUMMY backend");
- netherFallbackPolicyBackend->enqueueVerdict (packet);
+ LOGD(packetToString(packet).c_str());
+
+ if(netherPrimaryPolicyBackend && netherPrimaryPolicyBackend->enqueueVerdict(packet))
+ {
+ LOGD("Primary policy accepted packet");
+ return;
+ }
+
+ if(netherBackupPolicyBackend && netherBackupPolicyBackend->enqueueVerdict(packet))
+ {
+ LOGI("Primary policy backend failed, using backup policy backend");
+ return;
+ }
+
+ /* In this situation no policy backend wants to deal with this packet
+ there propably isn't any rule in either of them
+
+ we need to make a generic decision based on whatever is hard-coded
+ or passed as a parameter to the service */
+ LOGW("All policy backends failed, using DUMMY backend");
+ netherFallbackPolicyBackend->enqueueVerdict(packet);
}
-const bool NetherManager::restoreRules()
+bool NetherManager::restoreRules()
{
- if (!isCommandAvailable(netherConfig.iptablesRestorePath))
- {
- return (false);
- }
-
- std::stringstream cmdline;
- cmdline << netherConfig.iptablesRestorePath;
- cmdline << " ";
- cmdline << netherConfig.rulesPath;
-
- if (system (cmdline.str().c_str()))
- {
- LOGE("system() failed for: " << cmdline.str());
- return (false);
- }
-
- LOGD("iptables-restore succeeded with rules from: " << netherConfig.rulesPath);
- return (true);
+ if(!isCommandAvailable(netherConfig.iptablesRestorePath))
+ {
+ return (false);
+ }
+
+ std::stringstream cmdline;
+ cmdline << netherConfig.iptablesRestorePath;
+ cmdline << " ";
+ cmdline << netherConfig.rulesPath;
+
+ if(system(cmdline.str().c_str()))
+ {
+ LOGE("system() failed for: " << cmdline.str());
+ return (false);
+ }
+
+ LOGD("iptables-restore succeeded with rules from: " << netherConfig.rulesPath);
+ return (true);
}
-const bool NetherManager::isCommandAvailable(const std::string &command)
+bool NetherManager::isCommandAvailable(const std::string &command)
{
- struct stat iptablesRestoreStat;
+ struct stat iptablesRestoreStat;
- if (stat(command.c_str(), &iptablesRestoreStat) == 0)
- {
- if (! iptablesRestoreStat.st_mode & S_IXUSR)
- {
- LOGE("Execute bit is not set for owner on:" << command);
- return (false);
- }
+ if(stat(command.c_str(), &iptablesRestoreStat) == 0)
+ {
+ if(! iptablesRestoreStat.st_mode & S_IXUSR)
+ {
+ LOGE("Execute bit is not set for owner on:" << command);
+ return (false);
+ }
- return (true);
- }
+ return (true);
+ }
- LOGE("Failed to stat command at: " << command << " error: " << strerror(errno));
- return (false);
+ LOGE("Failed to stat command at: " << command << " error: " << strerror(errno));
+ return (false);
}
* @brief netlink handler class for nether
*/
-#include "nether_Netlink.h"\r
-\r
-NetherNetlink::NetherNetlink(NetherConfig &netherConfig)\r
- : nfqHandle(nullptr), queueHandle(nullptr), nlif(nullptr),
- queue(netherConfig.queueNumber),
- NetherPacketProcessor(netherConfig)\r
-{\r
-}\r
-\r
-NetherNetlink::~NetherNetlink()\r
+#include "nether_Netlink.h"
+
+NetherNetlink::NetherNetlink(NetherConfig &netherConfig)
+ : NetherPacketProcessor(netherConfig), queueHandle(nullptr), nfqHandle(nullptr), nlif(nullptr), queue(netherConfig.queueNumber)
+{
+}
+
+NetherNetlink::~NetherNetlink()
{
- if (queueHandle) nfq_destroy_queue(queueHandle);\r
- if (nfqHandle) nfq_close(nfqHandle);\r
-}\r
-\r
-const bool NetherNetlink::initialize()\r
-{\r
- nfqHandle = nfq_open();\r
-\r
- if (!nfqHandle)\r
- {\r
- LOGE("Error during nfq_open()");\r
- return (false);\r
- }\r
-\r
- if (nfq_unbind_pf(nfqHandle, AF_INET) < 0)\r
- {\r
- LOGE("Error during nfq_unbind_pf() (no permission?)");\r
- return (false);\r
- }\r
-\r
- if (nfq_bind_pf(nfqHandle, AF_INET) < 0)\r
- {\r
- LOGE("Error during nfq_bind_pf()");\r
- return (false);\r
- }\r
-\r
- queueHandle = nfq_create_queue(nfqHandle, queue, &callback, this);
-\r
- if (!queueHandle)\r
- {\r
- LOGE("Error during nfq_create_queue()");\r
- return (false);\r
- }\r
-
- if (nfq_set_queue_flags(queueHandle, NFQA_CFG_F_SECCTX, NFQA_CFG_F_SECCTX))\r
- LOGI("This kernel version does not allow to retrieve security context");
-\r
- if (nfq_set_mode(queueHandle, NFQNL_COPY_PACKET, 0xffff) < 0)\r
- {\r
- LOGE("Can't set packet_copy mode");\r
- nfq_destroy_queue (queueHandle);\r
- return (false);\r
- }\r
-\r
- if (nfq_set_queue_flags(queueHandle, NFQA_CFG_F_UID_GID, NFQA_CFG_F_UID_GID))\r
- {\r
- LOGE("This kernel version does not allow to retrieve process UID/GID");\r
- nfq_destroy_queue (queueHandle);\r
- return (false);\r
- }\r
-
- nlif = nlif_open();
- if (!nlif)
- LOGI("Failed to initialize NLIF subsystem, interface information won't be available");
-\r
- return (true);\r
-}\r
+ if(queueHandle) nfq_destroy_queue(queueHandle);
+ if(nfqHandle) nfq_close(nfqHandle);
+}
+
+bool NetherNetlink::initialize()
+{
+ nfqHandle = nfq_open();
+
+ if(!nfqHandle)
+ {
+ LOGE("Error during nfq_open()");
+ return (false);
+ }
+
+ if(nfq_unbind_pf(nfqHandle, AF_INET) < 0)
+ {
+ LOGE("Error during nfq_unbind_pf() (no permission?)");
+ return (false);
+ }
+
+ if(nfq_bind_pf(nfqHandle, AF_INET) < 0)
+ {
+ LOGE("Error during nfq_bind_pf()");
+ return (false);
+ }
+
+ queueHandle = nfq_create_queue(nfqHandle, queue, &callback, this);
+
+ if(!queueHandle)
+ {
+ LOGE("Error during nfq_create_queue()");
+ return (false);
+ }
+
+ if(nfq_set_queue_flags(queueHandle, NFQA_CFG_F_SECCTX, NFQA_CFG_F_SECCTX))
+ LOGI("This kernel version does not allow to retrieve security context");
+
+ if(nfq_set_mode(queueHandle, NFQNL_COPY_META, 0xffff) < 0)
+ {
+ LOGE("Can't set packet_copy mode");
+ nfq_destroy_queue(queueHandle);
+ return (false);
+ }
+
+ if(nfq_set_queue_flags(queueHandle, NFQA_CFG_F_UID_GID, NFQA_CFG_F_UID_GID))
+ {
+ LOGE("This kernel version does not allow to retrieve process UID/GID");
+ nfq_destroy_queue(queueHandle);
+ return (false);
+ }
+
+ nlif = nlif_open();
+ if(!nlif)
+ LOGI("Failed to initialize NLIF subsystem, interface information won't be available");
+
+ return (true);
+}
int NetherNetlink::getDescriptor()
{
- if (nfqHandle)
- return (nfq_fd(nfqHandle));
- else
- LOGE("nfq not initialized");
+ if(nfqHandle)
+ return (nfq_fd(nfqHandle));
+ else
+ LOGE("nfq not initialized");
+ return (-1);
}
-const bool NetherNetlink::processPacket (char *packetBuffer, const int packetReadSize)
+bool NetherNetlink::processPacket(char *packetBuffer, const int packetReadSize)
{
- if (nfq_handle_packet (nfqHandle, packetBuffer, packetReadSize))
- {
- LOGE("nfq_handle_packet failed");
- return (false);
- }
+ if(nfq_handle_packet(nfqHandle, packetBuffer, packetReadSize))
+ {
+ LOGE("nfq_handle_packet failed");
+ return (false);
+ }
- return (true);
+ return (true);
}
-\r
-int NetherNetlink::callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data)\r
+
+int NetherNetlink::callback(struct nfq_q_handle *, struct nfgenmsg *, struct nfq_data *nfa, void *data)
{
- NetherNetlink *me = static_cast<NetherNetlink *>(data);
- NetherPacket packet;
- unsigned char *secctx;
- int secctxSize = 0;
- struct nfqnl_msg_packet_hdr *ph;
- unsigned char *payload;
-\r
- if ((ph = nfq_get_msg_packet_hdr(nfa)))
- {
- packet.id = ntohl(ph->packet_id);
- }
- else
- {
- LOGI("Failed to get packet id");
- return (1);
- }
-\r
- if (nfq_get_uid(nfa, &packet.uid) == 0)
- LOGW("Failed to get uid for packet id=" << packet.id);
-\r
- nfq_get_gid(nfa, &packet.gid);
-\r
- secctxSize = nfq_get_secctx(nfa, &secctx);
-
- if (secctxSize > 0)
- packet.securityContext = std::string ((char *)secctx, secctxSize);
- else
- LOGD("Failed to get security context for packet id=" << packet.id);
-
- if (nfq_get_payload(nfa, &payload) > 0)
- decodePacket(packet, payload);
-
- me->processNetherPacket (packet); /* this call if from the NetherPacketProcessor class */\r
-\r
- return (0);\r
-}\r
-\r
-const bool NetherNetlink::isValid()\r
-{\r
- return (nfqHandle && queueHandle);\r
+ NetherNetlink *me = static_cast<NetherNetlink *>(data);
+ NetherPacket packet;
+ unsigned char *secctx;
+ int secctxSize = 0;
+ struct nfqnl_msg_packet_hdr *ph;
+ unsigned char *payload;
+
+ if((ph = nfq_get_msg_packet_hdr(nfa)))
+ {
+ packet.id = ntohl(ph->packet_id);
+ }
+ else
+ {
+ LOGI("Failed to get packet id");
+ return (1);
+ }
+
+ if(nfq_get_uid(nfa, &packet.uid) == 0)
+ LOGW("Failed to get uid for packet id=" << packet.id);
+
+ nfq_get_gid(nfa, &packet.gid);
+
+ secctxSize = nfq_get_secctx(nfa, &secctx);
+
+ if(secctxSize > 0)
+ packet.securityContext = std::string((char *)secctx, secctxSize);
+ else
+ LOGD("Failed to get security context for packet id=" << packet.id);
+
+ if(nfq_get_payload(nfa, &payload) > 0)
+ decodePacket(packet, payload);
+
+ me->processNetherPacket(packet); /* this call if from the NetherPacketProcessor class */
+
+ return (0);
}
void NetherNetlink::setVerdict(const u_int32_t packetId, const NetherVerdict verdict)
{
- int ret = 0;
- LOGD("id=" << packetId << " verdict=" << verdictToString(verdict));
-
- if (verdict == NetherVerdict::allow)
- ret = nfq_set_verdict (queueHandle, packetId, NF_ACCEPT, 0, NULL);
- if (verdict == NetherVerdict::deny)
- ret = nfq_set_verdict2 (queueHandle, packetId, NF_ACCEPT, netherConfig.markDeny, 0, NULL);
- if (verdict == NetherVerdict::allowAndLog)
- ret = nfq_set_verdict2 (queueHandle, packetId, NF_ACCEPT, netherConfig.markAllowAndLog, 0, NULL);
-
- if (ret == -1)
- LOGW("can't set verdict for packetId=" << packetId);
+ int ret = 0;
+ LOGD("id=" << packetId << " verdict=" << verdictToString(verdict));
+
+ if(verdict == NetherVerdict::allow)
+ ret = nfq_set_verdict(queueHandle, packetId, NF_ACCEPT, 0, NULL);
+ if(verdict == NetherVerdict::deny)
+ ret = nfq_set_verdict2(queueHandle, packetId, NF_ACCEPT, netherConfig.markDeny, 0, NULL);
+ if(verdict == NetherVerdict::allowAndLog)
+ ret = nfq_set_verdict2(queueHandle, packetId, NF_ACCEPT, netherConfig.markAllowAndLog, 0, NULL);
+
+ if(ret == -1)
+ LOGW("can't set verdict for packetId=" << packetId);
}
-const bool NetherNetlink::reload()
+bool NetherNetlink::reload()
{
- return (true);
+ return (true);
}
* @brief Network utility functions for nether
*/
-#include <netdb.h>
-#include <linux/types.h>
#include "nether_Utils.h"
#define IP_PROTOCOL_UDP (0x11)
void decodePacket(NetherPacket &packet, unsigned char *payload)
{
- uint8_t ipVersion = (payload[0] >> 4) & 0x0F;
-
- switch(ipVersion)
- {
- case 4:
- packet.protocolType = NetherProtocolType::IPv4;
- decodeIPv4Packet(packet, payload);
- break;
- case 6:
- packet.protocolType = NetherProtocolType::IPv6;
- decodeIPv6Packet(packet, payload);
- break;
- default:
- packet.transportType = NetherTransportType::unknownTransportType;
- packet.protocolType = NetherProtocolType::unknownProtocolType;
- break;
- }
+ uint8_t ipVersion = (payload[0] >> 4) & 0x0F;
+
+ switch(ipVersion)
+ {
+ case 4:
+ packet.protocolType = NetherProtocolType::IPv4;
+ decodeIPv4Packet(packet, payload);
+ break;
+ case 6:
+ packet.protocolType = NetherProtocolType::IPv6;
+ decodeIPv6Packet(packet, payload);
+ break;
+ default:
+ packet.transportType = NetherTransportType::unknownTransportType;
+ packet.protocolType = NetherProtocolType::unknownProtocolType;
+ break;
+ }
}
void decodeIPv6Packet(NetherPacket &packet, unsigned char *payload)
{
- const uint16_t startOfIpPayload = 40;
- uint8_t nextProto;
-
- memcpy(packet.localAddress, &payload[8], NETHER_NETWORK_IPV6_ADDR_LEN);
- memcpy(packet.remoteAddress, &payload[24], NETHER_NETWORK_IPV6_ADDR_LEN);
-
- nextProto = payload[6];
-
- switch(nextProto)
- {
- case IP_PROTOCOL_UDP:
- packet.transportType = NetherTransportType::UDP;
- decodeUdp(packet, &payload[startOfIpPayload]);
- break;
- case IP_PROTOCOL_TCP:
- packet.transportType = NetherTransportType::TCP;
- decodeTcp(packet, &payload[startOfIpPayload]);
- break;
- case IP_PROTOCOL_ICMP:
- packet.transportType = NetherTransportType::ICMP;
- break;
- case IP_PROTOCOL_IGMP:
- packet.transportType = NetherTransportType::IGMP;
- break;
- default:
- packet.transportType = NetherTransportType::unknownTransportType;
- break;
- }
+ const uint16_t startOfIpPayload = 40;
+ uint8_t nextProto;
+
+ memcpy(packet.localAddress, &payload[8], NETHER_NETWORK_IPV6_ADDR_LEN);
+ memcpy(packet.remoteAddress, &payload[24], NETHER_NETWORK_IPV6_ADDR_LEN);
+
+ nextProto = payload[6];
+
+ switch(nextProto)
+ {
+ case IPPROTO_UDP:
+ packet.transportType = NetherTransportType::UDP;
+ decodeUdp(packet, &payload[startOfIpPayload]);
+ break;
+ case IPPROTO_TCP:
+ packet.transportType = NetherTransportType::TCP;
+ decodeTcp(packet, &payload[startOfIpPayload]);
+ break;
+ case IPPROTO_ICMP:
+ packet.transportType = NetherTransportType::ICMP;
+ break;
+ case IPPROTO_IGMP:
+ packet.transportType = NetherTransportType::IGMP;
+ break;
+ default:
+ packet.transportType = NetherTransportType::unknownTransportType;
+ break;
+ }
}
void decodeIPv4Packet(NetherPacket &packet, unsigned char *payload)
{
- uint16_t startOfIpPayload = 0;
- uint8_t nextProto;
-
- startOfIpPayload = (payload[0]&0x0F) << 2;
-
- memcpy(packet.localAddress, &payload[12], NETHER_NETWORK_IPV4_ADDR_LEN);
- memcpy(packet.remoteAddress, &payload[16], NETHER_NETWORK_IPV4_ADDR_LEN);
-
- nextProto = payload[9];
-
- switch(nextProto)
- {
- case IP_PROTOCOL_UDP:
- packet.transportType = NetherTransportType::UDP;
- decodeUdp(packet, &payload[startOfIpPayload]);
- break;
- case IP_PROTOCOL_TCP:
- packet.transportType = NetherTransportType::TCP;
- decodeTcp(packet, &payload[startOfIpPayload]);
- break;
- case IP_PROTOCOL_ICMP:
- packet.transportType = NetherTransportType::ICMP;
- break;
- case IP_PROTOCOL_IGMP:
- packet.transportType = NetherTransportType::IGMP;
- default:
- packet.transportType = NetherTransportType::unknownTransportType;
- break;
- }
+ uint16_t startOfIpPayload = 0;
+ uint8_t nextProto;
+
+ startOfIpPayload = (payload[0]&0x0F) << 2;
+
+ memcpy(packet.localAddress, &payload[12], NETHER_NETWORK_IPV4_ADDR_LEN);
+ memcpy(packet.remoteAddress, &payload[16], NETHER_NETWORK_IPV4_ADDR_LEN);
+
+ nextProto = payload[9];
+
+ switch(nextProto)
+ {
+ case IPPROTO_UDP:
+ packet.transportType = NetherTransportType::UDP;
+ decodeUdp(packet, &payload[startOfIpPayload]);
+ break;
+ case IPPROTO_TCP:
+ packet.transportType = NetherTransportType::TCP;
+ decodeTcp(packet, &payload[startOfIpPayload]);
+ break;
+ case IPPROTO_ICMP:
+ packet.transportType = NetherTransportType::ICMP;
+ break;
+ case IPPROTO_IGMP:
+ packet.transportType = NetherTransportType::IGMP;
+ default:
+ packet.transportType = NetherTransportType::unknownTransportType;
+ break;
+ }
}
void decodeTcp(NetherPacket &packet, unsigned char *payload)
{
- packet.localPort = ntohs(*(unsigned short*) &payload[0]);
- packet.remotePort = ntohs(*(unsigned short*) &payload[2]);
+ packet.localPort = ntohs(*(unsigned short*) &payload[0]);
+ packet.remotePort = ntohs(*(unsigned short*) &payload[2]);
}
void decodeUdp(NetherPacket &packet, unsigned char *payload)
{
- packet.localPort = ntohs(*(unsigned short*) &payload[0]);
- packet.remotePort = ntohs(*(unsigned short*) &payload[2]);
+ packet.localPort = ntohs(*(unsigned short*) &payload[0]);
+ packet.remotePort = ntohs(*(unsigned short*) &payload[2]);
}
-const std::string ipAddressToString(const char *src, enum NetherProtocolType type)
+std::string ipAddressToString(const char *src, enum NetherProtocolType type)
{
- switch(type)
- {
- case NetherProtocolType::IPv4:
- return (stringFormat("%u.%u.%u.%u", src[0]&0xff,src[1]&0xff,src[2]&0xff,src[3]&0xff));
- case NetherProtocolType::IPv6:
- return (stringFormat("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
- ntohs(*(uint16_t*) &src[0]), ntohs(*(uint16_t*) &src[2]),
- ntohs(*(uint16_t*) &src[4]), ntohs(*(uint16_t*) &src[6]),
- ntohs(*(uint16_t*) &src[8]), ntohs(*(uint16_t*) &src[10]),
- ntohs(*(uint16_t*) &src[12]), ntohs(*(uint16_t*) &src[14])));
- default:
- return ("(unknown)");
- }
+ switch(type)
+ {
+ case NetherProtocolType::IPv4:
+ return (stringFormat("%u.%u.%u.%u", src[0]&0xff,src[1]&0xff,src[2]&0xff,src[3]&0xff));
+ case NetherProtocolType::IPv6:
+ return (stringFormat("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+ ntohs(*(uint16_t*) &src[0]), ntohs(*(uint16_t*) &src[2]),
+ ntohs(*(uint16_t*) &src[4]), ntohs(*(uint16_t*) &src[6]),
+ ntohs(*(uint16_t*) &src[8]), ntohs(*(uint16_t*) &src[10]),
+ ntohs(*(uint16_t*) &src[12]), ntohs(*(uint16_t*) &src[14])));
+ default:
+ return ("(unknown)");
+ }
}