فهرست منبع

Netzwerkmonitor hinzugefügt.

Rind 4 سال پیش
والد
کامیت
9c4df752e3
6فایلهای تغییر یافته به همراه586 افزوده شده و 19 حذف شده
  1. 1 6
      README.md
  2. 7 1
      gfanet.pro
  3. 491 0
      src/gfanetmon.cpp
  4. 78 0
      src/gfanetmon.h
  5. 6 0
      src/inet4d.h
  6. 3 12
      src/interfaces.h

+ 1 - 6
README.md

@@ -23,15 +23,10 @@ libgfanet.so (-lgfanet)
 
 * Funktionen zur Konfiguration der Datei /etc/network/interfaces
 * Funktionen zum Starten/Stoppen von Netzwerkinterfaces
+* Netzwerkmonitoring
 
 ---
 
 **Installation:**
 
 * Wird durch die [GfaLibs-Installers](https://gogs.reru.org/GfA/GfaLibs-Installers) mitinstalliert.
-
----
-
-## libnetinterfaces
-
-QML-Plugin. Kapselt die Funktionalität von **libgfanet** für QML-Anwendungen.

+ 7 - 1
gfanet.pro

@@ -7,6 +7,7 @@ CONFIG -= qt app_bundle
 
 SOURCES += \
     src/gfanet.cpp \
+    src/gfanetmon.cpp \
     src/interfaces.cpp \
     src/inet4s.cpp \
     src/inet4d.cpp \
@@ -15,6 +16,7 @@ SOURCES += \
 
 HEADERS += \
     src/gfanet.h \
+    src/gfanetmon.h \
     src/interfaces.h \
     src/inet4s.h \
     src/inet4d.h \
@@ -54,11 +56,13 @@ linux-g++ {
 	includes.extra += $$escape_expand(\\n\\t)-$(INSTALL_FILE) $$PWD/src/inet4s.h $(INSTALL_ROOT)$$includes.path
 	includes.extra += $$escape_expand(\\n\\t)-$(INSTALL_FILE) $$PWD/src/inet4d.h $(INSTALL_ROOT)$$includes.path
 	includes.extra += $$escape_expand(\\n\\t)-$(INSTALL_FILE) $$PWD/src/inet4m.h $(INSTALL_ROOT)$$includes.path
+	includes.extra += $$escape_expand(\\n\\t)-$(INSTALL_FILE) $$PWD/src/gfanetmon.h $(INSTALL_ROOT)$$includes.path
 	includes.uninstall += -$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/gfanet.h
 	includes.uninstall += $$escape_expand(\\n\\t)-$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/interfaces.h
 	includes.uninstall += $$escape_expand(\\n\\t)-$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/inet4s.h
 	includes.uninstall += $$escape_expand(\\n\\t)-$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/inet4d.h
 	includes.uninstall += $$escape_expand(\\n\\t)-$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/inet4m.h
+	includes.uninstall += $$escape_expand(\\n\\t)-$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/gfanetmon.h
 	INSTALLS += includes
 }
 
@@ -83,11 +87,13 @@ linux-buildroot-g++ {
 		includes.extra += $$escape_expand(\\n\\t)-$(INSTALL_FILE) $$PWD/src/inet4s.h $(INSTALL_ROOT)$$includes.path
 		includes.extra += $$escape_expand(\\n\\t)-$(INSTALL_FILE) $$PWD/src/inet4d.h $(INSTALL_ROOT)$$includes.path
 		includes.extra += $$escape_expand(\\n\\t)-$(INSTALL_FILE) $$PWD/src/inet4m.h $(INSTALL_ROOT)$$includes.path
+		includes.extra += $$escape_expand(\\n\\t)-$(INSTALL_FILE) $$PWD/src/gfanetmon.h $(INSTALL_ROOT)$$includes.path
 		includes.uninstall += -$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/gfanet.h
 		includes.uninstall += $$escape_expand(\\n\\t)-$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/interfaces.h
 		includes.uninstall += $$escape_expand(\\n\\t)-$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/inet4s.h
 		includes.uninstall += $$escape_expand(\\n\\t)-$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/inet4d.h
 		includes.uninstall += $$escape_expand(\\n\\t)-$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/inet4m.h
+		includes.uninstall += $$escape_expand(\\n\\t)-$(DEL_FILE) $(INSTALL_ROOT)$$includes.path/gfanetmon.h
 		INSTALLS += includes
 
 		itoolchain.target = install_toolchain
@@ -110,6 +116,6 @@ deploylib.commands += $$escape_expand(\\n\\t)@echo TARGET="$(TARGET)" >> deployt
 deploylib.commands += $$escape_expand(\\n\\t)@echo TARGET0="$(TARGET0)" >> deploytargets
 deploylib.commands += $$escape_expand(\\n\\t)@echo TARGET1="$(TARGET1)" >> deploytargets
 deploylib.commands += $$escape_expand(\\n\\t)@echo TARGET2="$(TARGET2)" >> deploytargets
-deploylib.commands += $$escape_expand(\\n\\t)@echo HEADERS="\\\"gfanet.h interfaces.h inet4s.h inet4d.h inet4m.h\\\"" >> deploytargets
+deploylib.commands += $$escape_expand(\\n\\t)@echo HEADERS="\\\"gfanet.h gfanetmon.h interfaces.h inet4s.h inet4d.h inet4m.h\\\"" >> deploytargets
 PRE_TARGETDEPS += deploylib
 QMAKE_EXTRA_TARGETS += deploylib

+ 491 - 0
src/gfanetmon.cpp

@@ -0,0 +1,491 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <poll.h>
+#include <signal.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include "gfanetmon.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define TRACE(...)					printf(__VA_ARGS__), fflush(stdout)
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define _THREAD_CMD_WAIT_COND		0
+#define _THREAD_CMD_EXIT			1
+#define _THREAD_CMD_CONTINUE		2
+
+/////////////////////////////////////////////////////////////////////////////
+
+static void _GetAttribs(struct rtattr *pIn, LPRT_ATTRIBUTE pOut, size_t nMaxOut, size_t nLen)
+{
+	memset(pOut, 0, sizeof(RT_ATTRIBUTE) * nMaxOut);
+
+	while(RTA_OK(pIn, nLen))
+	{
+		if((size_t)pIn->rta_type < nMaxOut)
+		{
+			pOut[pIn->rta_type].pat		= pIn;
+			pOut[pIn->rta_type].pData	= RTA_DATA(pIn);
+		}
+		pIn = RTA_NEXT(pIn, nLen);
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static int _BuildGetLinkMessage(struct nlmsghdr *pmh, unsigned short flags, unsigned int nSeq)
+{
+    pmh->nlmsg_type = RTM_GETLINK;
+	pmh->nlmsg_flags = NLM_F_REQUEST | flags;
+	pmh->nlmsg_seq = nSeq;
+	pmh->nlmsg_pid = getpid();
+
+	struct ifinfomsg *pim = (struct ifinfomsg*)NLMSG_DATA(pmh);
+	pim->ifi_family = AF_INET;
+	pim->ifi_change = 0xFFFFFFFF;
+
+	pmh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	return pmh->nlmsg_len;
+}
+
+static int _BuildGetAddrMessage(struct nlmsghdr *pmh, unsigned short flags, unsigned int nSeq)
+{
+    pmh->nlmsg_type = RTM_GETADDR;
+	pmh->nlmsg_flags = NLM_F_REQUEST | flags;
+	pmh->nlmsg_seq = nSeq;
+	pmh->nlmsg_pid = getpid();
+
+	struct ifaddrmsg *pam = (struct ifaddrmsg*)NLMSG_DATA(pmh);
+	pam->ifa_family = AF_INET;
+
+	pmh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+	return pmh->nlmsg_len;
+}
+
+static int _BuildGetRoute(struct nlmsghdr *pmh, unsigned short flags, unsigned int nSeq)
+{
+    pmh->nlmsg_type = RTM_GETROUTE;
+	pmh->nlmsg_flags = NLM_F_REQUEST | flags;
+	pmh->nlmsg_seq = nSeq;
+	pmh->nlmsg_pid = getpid();
+
+	struct rtmsg *prm = (struct rtmsg*)NLMSG_DATA(pmh);
+	prm->rtm_family = AF_INET;
+	prm->rtm_flags = RTM_F_NOTIFY;
+
+	pmh->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+	return pmh->nlmsg_len;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+CGfaNetMon::CGfaNetMon(void) :	m_fdNetlink(-1),
+								m_mtx(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP),
+								m_tCond(PTHREAD_COND_INITIALIZER),
+								m_fdReadPipe(m_fdPipe[0]),
+								m_fdWritePipe(m_fdPipe[1]),
+								m_bThreadRunning(false),
+								m_bWaitingCond(false),
+								m_pfnCallback(NULL),
+								m_pUserParam(NULL)
+{
+	m_fdReadPipe = m_fdWritePipe = -1;
+}
+
+CGfaNetMon::~CGfaNetMon(void)
+{
+	Close();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+bool CGfaNetMon::Init(void)
+{
+	struct sockaddr_nl sa;
+	memset(&sa, 0, sizeof(sa));
+	sa.nl_family = AF_NETLINK;
+	sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
+	
+	if(IsMonitorThreadContext())
+		return false;
+	else if(m_fdNetlink >= 0)
+		return true;
+
+	if(m_fdReadPipe >= 0)
+	{
+		close(m_fdReadPipe);
+		m_fdReadPipe = -1;
+	}
+	if(m_fdWritePipe >= 0)
+	{
+		close(m_fdWritePipe);
+		m_fdWritePipe = -1;
+	}
+
+	if((m_fdNetlink = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) >= 0)
+	{
+		if(bind(m_fdNetlink, (struct sockaddr*)&sa, sizeof(sa)) >= 0)
+		{
+			if(::pipe(m_fdPipe) >= 0)
+			{
+				if(m_thread.Create(&CGfaNetMon::MonitorThreadRoutine, reinterpret_cast<void*>(this)) >= 0)
+				{
+					while(!m_bThreadRunning)
+						::pthread_yield();
+				}
+				else
+				{
+					close(m_fdReadPipe);
+					close(m_fdWritePipe);
+					close(m_fdNetlink);
+					m_fdReadPipe = m_fdWritePipe = m_fdNetlink = -1;
+				}
+			}
+			else
+			{
+				close(m_fdNetlink);
+				m_fdNetlink = -1;
+			}
+		}
+		else
+		{
+			close(m_fdNetlink);
+			m_fdNetlink = -1;
+		}
+	}
+
+	return (m_fdNetlink >= 0);
+}
+
+void CGfaNetMon::Close(void)
+{
+	SignalMonitorThread(_THREAD_CMD_EXIT);
+	LockMutex();
+	if(m_fdNetlink >= 0)
+	{
+		close(m_fdNetlink);
+		m_fdNetlink = -1;
+	}
+	if(m_fdReadPipe >= 0)
+	{
+		close(m_fdReadPipe);
+		m_fdReadPipe = -1;
+	}
+	if(m_fdWritePipe >= 0)
+	{
+		close(m_fdWritePipe);
+		m_fdWritePipe = -1;
+	}
+	UnlockMutex();
+
+	if(!IsMonitorThreadContext())
+		m_thread.Join(NULL);
+}
+
+bool CGfaNetMon::StartMonitor(PFN_NETMON_CALLBACK pfnCb, void *pParam)
+{
+	if(IsMonitorThreadContext())
+		return false;
+
+	if(!pfnCb)
+	{
+		errno = EINVAL;
+		return false;
+	}
+
+	if(!SuspendMonitorThread())	// signal the monitor thread to enter the condition waiting state, while this thread gains ownership of the mutex
+		return false;
+	m_pfnCallback = pfnCb;
+	m_pUserParam = pParam;
+	ResumeMonitorThread();	// signal the monitor thread to leave the condition waiting state and to enter notification processing state
+	return RefreshMonitor();
+}
+
+bool CGfaNetMon::RefreshMonitor(void)
+{
+	if(IsMonitorThreadContext())
+		return false;
+
+	/////////////////////////////////////////////////////////////////////////
+
+	int nRet;
+	static unsigned int nSeq = 0;
+	char szBuf[2048] __attribute__ ((aligned(__alignof__(struct nlmsghdr))));
+	memset(szBuf, 0, sizeof(szBuf));
+	size_t nMsgLen = 0;
+	struct nlmsghdr *pmh = (struct nlmsghdr*)szBuf;
+
+	struct sockaddr_nl sa;
+	memset(&sa, 0, sizeof(sa));
+	sa.nl_family = AF_NETLINK;
+
+	struct iovec iov;
+	memset(&iov, 0, sizeof(iov));
+	struct msghdr msg = {&sa, sizeof(sa), &iov, 1, NULL, 0, 0};
+
+	/////////////////////////////////////////////////////////////////////////
+
+	nMsgLen = NLMSG_ALIGN(_BuildGetAddrMessage(pmh, NLM_F_ROOT, ++nSeq));
+	iov = {szBuf, nMsgLen};
+	if(!SuspendMonitorThread())	// signal the monitor thread to enter the condition waiting state, while this thread gains ownership of the mutex
+		return false;
+	nRet = sendmsg(m_fdNetlink, &msg, 0);	// send request
+	ResumeMonitorThread();	// signal the monitor thread to leave the condition waiting state and to enter notification processing state
+	
+	if(nRet <= 0)
+		return false;
+
+	// at this point the monitor thread has regained the ownership of the mutex and is processing notifications
+
+	nMsgLen = NLMSG_ALIGN(_BuildGetLinkMessage(pmh, NLM_F_ROOT, ++nSeq));
+	iov = {szBuf, nMsgLen};
+	if(!SuspendMonitorThread())	// signal the monitor thread to enter the condition waiting state, while this thread gains ownership of the mutex
+		return false;
+	nRet = sendmsg(m_fdNetlink, &msg, 0);	// send next request
+	ResumeMonitorThread();	// signal the monitor thread to leave the condition waiting state and to enter notification processing state
+
+	// at this point the monitor thread has regained the ownership of the mutex and is processing notifications
+
+	nMsgLen = NLMSG_ALIGN(_BuildGetRoute(pmh, NLM_F_ROOT, ++nSeq));
+	iov = {szBuf, nMsgLen};
+	if(!SuspendMonitorThread())	// signal the monitor thread to enter the condition waiting state, while this thread gains ownership of the mutex
+		return false;
+	nRet = sendmsg(m_fdNetlink, &msg, 0);	// send next request
+	ResumeMonitorThread();	// signal the monitor thread to leave the condition waiting state and to enter notification processing state
+
+	// at this point the monitor thread has regained the ownership of the mutex and is processing notifications
+
+	return nRet > 0;
+}
+
+bool CGfaNetMon::StopMonitor(void)
+{
+	return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CGfaNetMon::LockMutex(void)
+{
+	::pthread_mutex_lock(&m_mtx);
+}
+
+void CGfaNetMon::UnlockMutex(void)
+{
+	::pthread_mutex_unlock(&m_mtx);
+}
+
+void CGfaNetMon::WaitCondition(void)
+{
+	m_bWaitingCond = true;
+	::pthread_cond_wait(&m_tCond, &m_mtx);
+	m_bWaitingCond = false;
+}
+
+bool CGfaNetMon::SuspendMonitorThread(void)
+{
+	if(IsMonitorThreadContext())
+		return true;
+	if(SignalMonitorThread(_THREAD_CMD_WAIT_COND))
+	{
+		LockMutex();
+		return true;
+	}
+	return false;
+}
+
+void CGfaNetMon::ResumeMonitorThread(void)
+{
+	if(IsMonitorThreadContext())
+		return;
+	if(m_bWaitingCond)
+	{
+		::pthread_cond_signal(&m_tCond);
+		UnlockMutex();
+		while(m_bWaitingCond)
+			::pthread_yield();
+	}
+}
+
+bool CGfaNetMon::SignalMonitorThread(int sig)
+{
+	return write(m_fdWritePipe, &sig, sizeof(sig)) == sizeof(sig);
+}
+
+bool CGfaNetMon::IsMonitorThreadContext(void)
+{
+	return m_thread.GetID() == ::pthread_self();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void* CGfaNetMon::MonitorThreadRoutine(void *pParam)
+{
+	CGfaNetMon *pThis = reinterpret_cast<CGfaNetMon*>(pParam);
+	int ret;
+	bool bRun = true;
+	char buf[8192] __attribute__ ((aligned(__alignof__(struct nlmsghdr))));
+	struct pollfd pfd[2];
+	memset(pfd, 0, sizeof(pfd));
+	pfd[0].events = POLLIN;
+	pfd[1].events = POLLIN;
+
+	pThis->LockMutex();
+	pThis->m_bThreadRunning = true;
+
+	do
+	{
+		if((pThis->m_fdNetlink >= 0) && (pThis->m_fdReadPipe >= 0))
+		{
+			pfd[0].fd = pThis->m_fdReadPipe;
+			pfd[1].fd = pThis->m_fdNetlink;
+
+			if((ret = poll(pfd, 2, -1)) > 0)
+			{
+				if(pfd[1].revents & POLLIN)
+				{
+					int len;
+					struct iovec iov = { buf, sizeof(buf) };
+					struct sockaddr_nl sa;
+					struct msghdr msg;
+					struct nlmsghdr *pmh;
+					msg = {&sa, sizeof(sa), &iov, 1, NULL, 0, 0};
+
+					if((len = recvmsg(pThis->m_fdNetlink, &msg, 0)) >= 0)
+					{
+						for (pmh = (struct nlmsghdr *) buf; NLMSG_OK(pmh, len); pmh = NLMSG_NEXT(pmh, len))
+						{
+							switch(pmh->nlmsg_type)
+							{
+								case NLMSG_DONE:
+									break;
+
+								case NLMSG_ERROR:
+								{
+									struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(pmh);
+									if(pThis->m_pfnCallback)
+										(*pThis->m_pfnCallback)(pmh->nlmsg_type, err, NULL, 0, pThis->m_pUserParam);
+									break;
+								}
+
+								case RTM_NEWLINK:
+								{
+									RT_ATTRIBUTE atts[__IFLA_MAX];
+									struct ifinfomsg *ifm = (struct ifinfomsg*)NLMSG_DATA(pmh);
+									struct rtattr *rta = IFLA_RTA(ifm);
+									_GetAttribs(rta, atts, __IFLA_MAX, pmh->nlmsg_len - ((char*)rta - (char*)pmh));
+									if(pThis->m_pfnCallback)
+										(*pThis->m_pfnCallback)(pmh->nlmsg_type, ifm, atts, __IFLA_MAX, pThis->m_pUserParam);
+									break;
+								}
+
+								case RTM_DELLINK:
+								{
+									RT_ATTRIBUTE atts[__IFLA_MAX];
+									struct ifinfomsg *ifm = (struct ifinfomsg*)NLMSG_DATA(pmh);
+									struct rtattr *rta = IFLA_RTA(ifm);
+									_GetAttribs(rta, atts, __IFLA_MAX, pmh->nlmsg_len - ((char*)rta - (char*)pmh));
+									if(pThis->m_pfnCallback)
+										(*pThis->m_pfnCallback)(pmh->nlmsg_type, ifm, atts, __IFLA_MAX, pThis->m_pUserParam);
+									break;
+								}
+
+								case RTM_NEWADDR:
+								{
+									RT_ATTRIBUTE atts[__IFA_MAX];
+									struct ifaddrmsg *pam = (struct ifaddrmsg*)NLMSG_DATA(pmh);
+									struct rtattr *rtad = IFA_RTA(pam);
+									_GetAttribs(rtad, atts, __IFA_MAX, pmh->nlmsg_len - ((char*)rtad - (char*)pmh));
+									if(pThis->m_pfnCallback)
+										(*pThis->m_pfnCallback)(pmh->nlmsg_type, pam, atts, __IFA_MAX, pThis->m_pUserParam);
+									break;
+								}
+
+								case RTM_DELADDR:
+								{
+									RT_ATTRIBUTE atts[__IFA_MAX];
+									struct ifaddrmsg *pam = (struct ifaddrmsg*)NLMSG_DATA(pmh);
+									struct rtattr *rtad = IFA_RTA(pam);
+									_GetAttribs(rtad, atts, __IFA_MAX, pmh->nlmsg_len - ((char*)rtad - (char*)pmh));
+									if(pThis->m_pfnCallback)
+										(*pThis->m_pfnCallback)(pmh->nlmsg_type, pam, atts, __IFA_MAX, pThis->m_pUserParam);
+									break;
+								}
+								
+								case RTM_NEWROUTE:
+								{
+									RT_ATTRIBUTE atts[__RTA_MAX];
+									struct rtmsg *prm = (struct rtmsg*)NLMSG_DATA(pmh);
+									struct rtattr *rta = RTM_RTA(prm);
+									_GetAttribs(rta, atts, __RTA_MAX, pmh->nlmsg_len - ((char*)rta - (char*)pmh));
+									if(pThis->m_pfnCallback)
+										(*pThis->m_pfnCallback)(pmh->nlmsg_type, prm, atts, __RTA_MAX, pThis->m_pUserParam);
+									break;
+								}
+								
+								case RTM_DELROUTE:
+								{
+									RT_ATTRIBUTE atts[__RTA_MAX];
+									struct rtmsg *prm = (struct rtmsg*)NLMSG_DATA(pmh);
+									struct rtattr *rta = RTM_RTA(prm);
+									_GetAttribs(rta, atts, __RTA_MAX, pmh->nlmsg_len - ((char*)rta - (char*)pmh));
+									if(pThis->m_pfnCallback)
+										(*pThis->m_pfnCallback)(pmh->nlmsg_type, prm, atts, __RTA_MAX, pThis->m_pUserParam);
+									break;
+								}
+
+								default:
+									TRACE("MSG Type: Unknown\n");
+									break;
+							}
+						}
+					}
+				}
+
+				if(pfd[0].revents & POLLIN)
+				{
+					int cmd;
+					if((ret = read(pThis->m_fdReadPipe, &cmd, sizeof(cmd))) == sizeof(cmd))
+					{
+						switch(cmd)
+						{
+						case _THREAD_CMD_WAIT_COND:
+							pThis->WaitCondition();
+							break;
+						case _THREAD_CMD_CONTINUE:
+							break;
+						case _THREAD_CMD_EXIT:
+							bRun = false;
+							break;
+						}
+					}
+				}
+			}
+			else
+			{
+				bRun = false;
+			}
+		}
+		else
+		{
+			bRun = false;
+		}
+	}
+	while(bRun);
+
+	pThis->m_bThreadRunning = false;
+	pThis->UnlockMutex();
+
+	return NULL;
+}

+ 78 - 0
src/gfanetmon.h

@@ -0,0 +1,78 @@
+// gfanetmon.h :
+//
+
+#if !defined(AGD_GFANETMON_H__2AC24C70_D884_46D6_9176_5876AFAA0745__INCLUDED_)
+#define AGD_GFANETMON_H__2AC24C70_D884_46D6_9176_5876AFAA0745__INCLUDED_
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+/////////////////////////////////////////////////////////////////////////////
+#ifdef __cplusplus
+
+#include <atomic>
+#include <stdint.h>
+#include <gfa/thread.h>
+
+/////////////////////////////////////////////////////////////////////////////
+// gfanetmon.h - Declarations:
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef struct _RT_ATTRIBUTE
+{
+	struct rtattr *pat;
+	void *pData;
+}RT_ATTRIBUTE, *LPRT_ATTRIBUTE;
+typedef const RT_ATTRIBUTE *LPCRT_ATTRIBUTE;
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef void (*PFN_NETMON_CALLBACK)(unsigned int nEvtType/*, const char *pszIfName, const void *pAddr*/, const void *pData, LPCRT_ATTRIBUTE pAtts, size_t nMaxAtts, void *pParam);
+
+/////////////////////////////////////////////////////////////////////////////
+
+class CGfaNetMon
+{
+public:
+	CGfaNetMon(void);
+	~CGfaNetMon(void);
+
+	bool Init(void);
+	void Close(void);
+
+	bool StartMonitor(PFN_NETMON_CALLBACK pfnCb, void *pParam);
+	bool StopMonitor(void);
+	bool RefreshMonitor(void);
+
+private:
+	static void* MonitorThreadRoutine(void *pParam);
+	void LockMutex(void);
+	void UnlockMutex(void);
+	void WaitCondition(void);
+	bool SuspendMonitorThread(void);
+	void ResumeMonitorThread(void);
+	bool IsMonitorThreadContext(void);
+	bool SignalMonitorThread(int sig);
+
+private:
+	std::atomic_int m_fdNetlink;
+	CThread m_thread;
+	pthread_mutex_t m_mtx;
+	pthread_cond_t m_tCond;
+	int m_fdPipe[2];
+	int &m_fdReadPipe;
+	int &m_fdWritePipe;
+	std::atomic_bool m_bThreadRunning;
+	std::atomic_bool m_bWaitingCond;
+	PFN_NETMON_CALLBACK m_pfnCallback;
+	void *m_pUserParam;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+#endif	//	__cplusplus
+/////////////////////////////////////////////////////////////////////////////
+#endif	//	!defined(AGD_GFANETMON_H__2AC24C70_D884_46D6_9176_5876AFAA0745__INCLUDED_)

+ 6 - 0
src/inet4d.h

@@ -22,6 +22,9 @@ typedef struct _IFACE_INET_DHCP
 	_IFACE_INET_DHCP(){_reset();}
 	void _reset(void)
 	{
+		addr.s_addr = INADDR_ANY;
+		netmask.s_addr = INADDR_ANY;
+		netprefix = 0;
 		metric = -1;
 		leasehours = -1;
 		leasetime = -1;
@@ -30,6 +33,9 @@ typedef struct _IFACE_INET_DHCP
 		client.clear();
 		hwaddr.clear();
 	}
+    struct in_addr addr;	// dynamically assigned
+    struct in_addr netmask;	// dynamically assigned
+	unsigned int netprefix;	// dynamically assigned
 	int leasehours;			// Preferred lease time in hours
 	int leasetime;			// Preferred lease time in seconds
 	int metric;

+ 3 - 12
src/interfaces.h

@@ -159,6 +159,7 @@ typedef struct _ITF_IFACE_BLOCK
 		inet4d._reset();
 		inet4m._reset();
 		id = ++g_nItfID;
+		up = running = false;
 	}
 	unsigned long id;
 	std::string cfgName;
@@ -171,6 +172,8 @@ typedef struct _ITF_IFACE_BLOCK
 	IFACE_INET_STATIC inet4s;
 	IFACE_INET_DHCP inet4d;
 	IFACE_INET_MANUAL inet4m;
+	bool up;
+	bool running;
 }ITF_IFACE_BLOCK, *LPITF_IFACE_BLOCK;
 typedef const ITF_IFACE_BLOCK *LPCITF_IFACE_BLOCK;
 typedef std::list<ITF_IFACE_BLOCK> ITF_IFACE_BLOCK_LIST;
@@ -196,10 +199,6 @@ typedef struct _ITF_MAPPING_BLOCK
 	{
 		unparsed.clear();
 	}
-/*	void _copy(struct _ITF_MAPPING_BLOCK &target)
-	{
-		target.unparsed.assign(unparsed.begin(), unparsed.end());
-	}*/
 	std::vector<std::string> unparsed;
 }ITF_MAPPING_BLOCK, *LPITF_MAPPING_BLOCK;
 typedef const ITF_MAPPING_BLOCK *LPCITF_MAPPING_BLOCK;
@@ -220,14 +219,6 @@ typedef struct _ETC_NETWORK_INTERFACES
 		inc.clear();
 		unparsed.clear();
 	}
-/*	void _copy(struct _ETC_NETWORK_INTERFACES &target)
-	{
-		mbl._copy(target.mbl);
-		cgl._copy(target.cgl);
-		ibl._copy(target.ibl);
-		inc._copy(target.inc);
-		target.unparsed.assign(unparsed.begin(), unparsed.end());
-	}*/
 	ITF_MAPPING_BLOCK_LIST	mbl;
 	ITF_CONFIG_GROUP_LIST	cgl;
 	ITF_IFACE_BLOCK_LIST	ibl;