ソースを参照

Testversion mit verbesserter Strukturierung.

Rind 6 年 前
コミット
5a3e120d9b

+ 25 - 10
QmlTest/main.qml

@@ -14,7 +14,7 @@ Window {
          y: 40
          color: "blue"
          font.pixelSize: 14
-         text: idItf.interfaces[0].ipAddress.address
+         text: idItf.interfaces[2].inet.stat.ipAddress.address
      }
 
     NetInterfaces {
@@ -22,10 +22,14 @@ Window {
 //        itfFilterName: "eth0"
         itfFilterAF: Interface.AF_Inet
         itfFilterMethod: Interface.IM_Static | Interface.IM_Manual
-        onSigError:
+        onError:
         {
             console.error(msg);
         }
+        onFilteredInterfacesChanged:
+        {
+            console.warn("Filtered Interfaces may have changed!");
+        }
     }
 
     MouseArea {
@@ -34,10 +38,9 @@ Window {
         {
             if(idItf.filteredInterfaces.length > 0)
             {
-                idItf.filteredInterfaces[0].ipAddress.address = "192.168.0.256";
-                idItf.filteredInterfaces[0].ipAddress.address = "155.18.2.156";
-                idItf.filteredInterfaces[0].ipAddress.b0 = 255;
-                console.log(idItf.filteredInterfaces[0].ipAddress.address);
+                idItf.filteredInterfaces[0].inet.stat.ipAddress.address = "155.18.2.156";
+                idItf.filteredInterfaces[0].inet.stat.ipAddress.b2 = 255;
+                console.log(idItf.filteredInterfaces[0].inet.stat.ipAddress.address);
             }
             else
             {
@@ -45,11 +48,23 @@ Window {
             }
 
             idItf.itfFilterMethod |= Interface.IM_Dhcp;
-//            idItf.itfFilterName = "eth1";
-            idItf.itfFilterMethod &= ~Interface.IM_Static;
+            idItf.itfFilterMethod &= ~Interface.IM_Manual;
+
+            var itfn = idItf.newInterface("test1", Interface.AF_Inet6, Interface.IM_Dhcp);
+            itfn.af = Interface.AF_Inet;
+            itfn.inet.stat.ipAddress.address = "192.168.3.24";
+            itfn.inet.stat.netMask.address = "255.255.254.0";
+            itfn.inet.stat.netPrefix = 22;
+            itfn.method = Interface.IM_Static;
+            itfn.inet.stat.gateway.b0 = 192;
+            itfn.inet.stat.gateway.b1 = 168;
+            itfn.inet.stat.gateway.b2 = 0;
+            itfn.inet.stat.gateway.b3 = 1;
+            itfn.inet.stat.dnsServer[0].address = "8.8.8.8";
+            itfn.inet.stat.dnsServer[1].address = "8.8.4.4";
 
-            idItf.filteredInterfaces[0].af = Interface.AF_Unknown;
-//            idItf.saveAs("/home/wrk/share/gfanet/libgfanet/res/testitf");
+//            idItf.removeInterface(itfn);
+            idItf.saveAs("/home/wrk/share/gfanet/libgfanet/res/testitf");
         }
     }
 }

+ 19 - 28
libgfanet/interfaces.cpp

@@ -7,10 +7,7 @@
 #define _ETC_NETWORK_INTERFACES			"/etc/network/interfaces"
 //#define _ETC_NETWORK_INTERFACES			"/home/wrk/share/gfanet/libgfanet/res/interfaces"
 
-#if 1
-#undef TRACE
-#define TRACE(...)						(void)0
-#endif
+unsigned long g_nItfID = 0;
 
 /////////////////////////////////////////////////////////////////////////////
 // iface block
@@ -300,7 +297,6 @@ bool ParseIncludes(const std::vector<std::string> &v, ITF_INCLUDE_LIST &inc)
 
 void ProcessIface(ETC_NETWORK_INTERFACES &eni)
 {
-	TRACE("%s - enter\n", __FUNCTION__);
 	for(auto iti = eni.ibl.begin(); iti != eni.ibl.end(); iti++)
 	{
 		ITF_IFACE_BLOCK &ib = *iti;
@@ -315,14 +311,12 @@ void ProcessIface(ETC_NETWORK_INTERFACES &eni)
 				ib.inet4s.netprefix = 24;
 		}
 	}
-	TRACE("%s - leave\n", __FUNCTION__);
 }
 
 /////////////////////////////////////////////////////////////////////////////
 
 void ProcessGroupMembers(ETC_NETWORK_INTERFACES &eni)
 {
-	TRACE("%s - enter\n", __FUNCTION__);
 	// remove double configuration names in a single group
 	for(auto cIt = eni.cgl.begin(); cIt != eni.cgl.end(); cIt++)
 	{
@@ -370,7 +364,6 @@ void ProcessGroupMembers(ETC_NETWORK_INTERFACES &eni)
 			}
 		}
 	}
-	TRACE("%s - leave\n", __FUNCTION__);
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -378,8 +371,6 @@ void ProcessGroupMembers(ETC_NETWORK_INTERFACES &eni)
 
 bool ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni, const char *pszPath)
 {
-	TRACE("%s\n", __FUNCTION__);
-
 	typedef enum ParseStates
 	{
 		PS_Root,
@@ -387,28 +378,19 @@ bool ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni, const char *pszPath)
 		PS_Mapping
 	}ParseStates;
 
-	TRACE("  initializing regex ...\n");
-
 	static const std::string strRegExComt = "^\\s*#.*";
 	static const std::string strRegExLine = "([^\\s]+)";
 	static const std::regex regc(strRegExComt, std::regex_constants::ECMAScript | std::regex_constants::optimize);
 	static const std::regex regl(strRegExLine, std::regex_constants::ECMAScript | std::regex_constants::optimize);
 	std::string buf;
 
-	TRACE("  complete.\n");
-
 	if(!pszPath)
 		pszPath = _ETC_NETWORK_INTERFACES;
-
-	TRACE("  file path: %s\n", pszPath);
 		
 	eni._reset();
 
-	TRACE("  reading file ...\n");
-
 	if(ReadFile(pszPath, buf) > 0)
 	{
-		TRACE("  success.\n");
 		ParseStates ps = PS_Root;
 		std::string line;
 		std::istringstream iss(buf);
@@ -421,12 +403,9 @@ bool ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni, const char *pszPath)
         while(!(stm >> std::ws).eof())
 		{
 			if(std::getline(stm, line).fail())
-			{
-				TRACE("%s: failed to read stream!\n", __FUNCTION__);
 				return false;
-			}
+
 			trim(line);
-			TRACE("%zu\n", line.size());
 
 			if(!line.empty())
 			{
@@ -476,7 +455,6 @@ bool ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni, const char *pszPath)
 				else
 				{
 					eni.unparsed.push_back(line);
-					TRACE("%d - %s\n", ps, line.c_str());
 				}
 			}
 		}
@@ -485,10 +463,6 @@ bool ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni, const char *pszPath)
 		ProcessGroupMembers(eni);
 		return true;
 	}
-	else
-	{
-		TRACE("  error!\n");
-	}
 
 	return false;
 }
@@ -678,3 +652,20 @@ bool WriteEtcNetworkInterfaces(const ETC_NETWORK_INTERFACES &eni, const char *ps
 
 	return false;
 }
+
+bool RemoveInterfaceBlock(ETC_NETWORK_INTERFACES &eni, unsigned long id)
+{
+	for(auto iti = eni.ibl.begin(); iti != eni.ibl.end(); iti++)
+	{
+		ITF_IFACE_BLOCK &ib = *iti;
+		
+		if(ib.id == id)
+		{
+			eni.ibl.erase(iti);
+			ProcessGroupMembers(eni);
+			return true;
+		}
+	}
+
+	return false;
+}

+ 7 - 0
libgfanet/interfaces.h

@@ -29,6 +29,10 @@
 /////////////////////////////////////////////////////////////////////////////
 // interfaces.h - Declarations:
 
+extern unsigned long g_nItfID;
+
+/////////////////////////////////////////////////////////////////////////////
+
 typedef struct _ITF_CONFIG_GROUP
 {
 	_ITF_CONFIG_GROUP(){_reset();}
@@ -152,7 +156,9 @@ typedef struct _ITF_IFACE_BLOCK
 		inet4s._reset();
 		inet4d._reset();
 		inet4m._reset();
+		id = ++g_nItfID;
 	}
+	unsigned long id;
 	std::string cfgName;
 	IfaceProtos proto;
 	IfaceMethods method;
@@ -222,6 +228,7 @@ void ProcessIface(ETC_NETWORK_INTERFACES &eni);
 void ProcessGroupMembers(ETC_NETWORK_INTERFACES &eni);
 bool ParseEtcNetworkInterfaces(ETC_NETWORK_INTERFACES &eni, const char *pszPath = NULL);
 bool WriteEtcNetworkInterfaces(const ETC_NETWORK_INTERFACES &eni, const char *pszPath = NULL);
+bool RemoveInterfaceBlock(ETC_NETWORK_INTERFACES &eni, unsigned long id);
 
 /////////////////////////////////////////////////////////////////////////////
 #endif	//	!defined(AGD_INTERFACES_H__0F16A7C6_9054_4BBB_8A10_EAE00ED4EE9C__INCLUDED_)

+ 290 - 131
qtplugin/netinterfaces.cpp

@@ -1,11 +1,6 @@
 #include "netinterfaces.h"
 #include "../debug.h"
 
-#if 1
-#undef TRACE
-#define TRACE(...)					(void)0
-#endif
-
 #ifndef _countof
 #define _countof(a)					(sizeof(a) / sizeof(*a))
 #endif	//	_countof
@@ -34,7 +29,7 @@ static unsigned int _BitCount(T n)
 template<typename T>
 static int _BitNumber(T n)
 {
-	if(!_IsPowerOf2(n))
+	if(!n || !_IsPowerOf2(n))
 		return -1;
 	int count = 0;
 	while(n)
@@ -42,14 +37,29 @@ static int _BitNumber(T n)
 		count++;
 		n >>= 1;
 	}
-	return count;
+	return count - 1;
+}
+
+static int _Mask2Prefix(const struct in_addr &in)
+{
+	return _BitCount(in.s_addr);
 }
 
+static in_addr_t _Prefix2Mask(int prefix)
+{
+	return htonl(~((1 << (32 - prefix)) - 1));
+}
+
+static bool _IsValidNetmask(const struct in_addr &in)
+{
+	return _IsPowerOf2(~ntohl(in.s_addr) + 1);
+}
+
+/////////////////////////////////////////////////////////////////////////////
 
 #define _FLAG_TO_ENUM(f)		(_BitNumber(f))
 #define _ENUM_TO_FLAG(e)		(0x00000001 << e)
 
-/////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
 
 NetInterfaces::NetInterfaces(QObject *pParent) : QObject(pParent)
@@ -58,43 +68,37 @@ NetInterfaces::NetInterfaces(QObject *pParent) : QObject(pParent)
 	m_itfFilterAF		= Interface::AF_Unknown;
 	m_itfFilterMethod	= Interface::IM_Unknown;
 	m_itfFilterName.clear();
-	TRACE("%s\n", __FUNCTION__);
 }
 
 NetInterfaces::~NetInterfaces(void)
 {
 	reset();
-	TRACE("%s\n", __FUNCTION__);
 }
 
 void NetInterfaces::classBegin()
 {
-	TRACE("%s\n", __FUNCTION__);
 	if(!initialize())
 	{
-		TRACE("initialize failed!\n");
 		emitError("NetInterfaces::initialize failed!");
 	}
 }
 
 void NetInterfaces::componentComplete()
 {
-	TRACE("%s\n", __FUNCTION__);
 }
 
 void NetInterfaces::reset(void)
 {
 	Interface *pItf;
-	TRACE("%s\n", __FUNCTION__);
-	
+
     for(int i = 0; i < m_interfaces.count(); i++)
     {
         if((pItf = m_interfaces.at(i)))
         	delete pItf;
     }
     m_interfaces.clear();
-	emit interfaces_Changed();
-
+	emit interfacesChanged();
+	emit filteredInterfacesChanged();
 	m_eni._reset();
 }
 
@@ -102,21 +106,17 @@ bool NetInterfaces::initialize(void)
 {
 	bool bRet;
 	reset();
-	TRACE("%s\n", __FUNCTION__);
 
     if((bRet = ::ParseEtcNetworkInterfaces(m_eni)))
 	{
-		TRACE("ParseEtcNetworkInterfaces success.\n");
-
 		for(auto it = m_eni.ibl.begin(); it != m_eni.ibl.end(); it++)
 		{
 			ITF_IFACE_BLOCK &ibl = *it;
-			TRACE("  appending interface ...\n");
-			m_interfaces.append(new Interface(ibl, static_cast<const Emitter&>(*this), this));
-			TRACE("  interface appended.\n");
+			m_interfaces.append(new Interface(ibl, static_cast<const NotificationSink&>(*this), this));
 		}
 
-		emit interfaces_Changed();
+		emit interfacesChanged();
+		emit filteredInterfacesChanged();
 	}
 
 	return bRet;
@@ -142,52 +142,32 @@ void NetInterfaces::emitError(const char *pszFormatStr, ...) const
 	va_start(args, pszFormatStr);
 	QString qs = QString::vasprintf(pszFormatStr, args);
 	va_end (args);
-    emit sigError(qs);
+    emit error(qs);
 }
 
-/*QVariantList NetInterfaces::getInterface(const QString &itfName)
+void NetInterfaces::filterPropertyChanged(void) const
 {
-	QVariantList list;
-    list.clear();
-
-	if(m_eni.ibl.size() > 0)
-	{
-	    for(int i = 0; i < m_interfaces.count(); i++)
-		{
-	        Interface *pi = m_interfaces.at(i);
-			const ITF_IFACE_BLOCK &ibl = pi->getIface();
-
-			if(	itfName == ibl.cfgName.c_str() &&
-				ibl.proto == IFP_Inet &&
-				(ibl.method == IFM_Static || ibl.method == IFM_Dhcp))
-			{
-				QVariant var = QVariant::fromValue(pi);
-				list.append(var);
-			}
-		}
-	}
-
-	return list;
-}*/
+	emit filteredInterfacesChanged();
+}
 
-QVariant NetInterfaces::newInterface(QString name, int af, int method)
+Interface* NetInterfaces::newInterface(QString name, int af, int method)
 {
 	if(name.isNull() || name.isEmpty())
 	{
 		emitError("Invalid or empty interface name!");
-		return QVariant();
+		return NULL;
 	}
-	
+
 	if(!_IsPowerOf2(af) || (af <= Interface::AF_Unknown) || (af >= Interface::AF_Invalid))
 	{
 		emitError("Invalid address family: %d!", af);
-		return QVariant();
+		return NULL;
 	}
 
 	if(!_IsPowerOf2(method) || (method <= Interface::IM_Unknown) || (method >= Interface::IM_Invalid))
 	{
 		emitError("Invalid method: %d!", method);
-		return QVariant();
+		return NULL;
 	}
 
 	m_eni.ibl.emplace_back();
@@ -195,10 +175,37 @@ QVariant NetInterfaces::newInterface(QString name, int af, int method)
     rib.cfgName = name.toStdString();
 	rib.proto = (IfaceProtos)_FLAG_TO_ENUM(af);
 	rib.method = (IfaceMethods)_FLAG_TO_ENUM(method);
-	Interface *pi = new Interface(rib, static_cast<const Emitter&>(*this), this);
+	Interface *pi = new Interface(rib, static_cast<const NotificationSink&>(*this), this);
 	m_interfaces.append(pi);
-	emit interfaces_Changed();
-	return QVariant::fromValue(pi);
+	emit interfacesChanged();
+	emit filteredInterfacesChanged();
+	return pi;
+}
+
+void NetInterfaces::removeInterface(Interface *pi)
+{
+	if(!pi)
+	{
+		emitError("%s: Attempt to remove invalid interface!", __FUNCTION__);
+		return;
+	}
+
+    unsigned long id = pi->getID();
+
+    for(int i = 0; i < m_interfaces.count(); i++)
+	{
+        Interface *pil = m_interfaces.at(i);
+
+        if(pil->getID() == id)
+        {
+        	m_interfaces.removeAt(i);
+			emit interfacesChanged();
+			emit filteredInterfacesChanged();
+			delete pil;
+			::RemoveInterfaceBlock(m_eni, id);
+			break;
+        }
+    }
 }
 
 QQmlListProperty<Interface> NetInterfaces::interfaces(void)
@@ -231,15 +238,15 @@ const QString& NetInterfaces::itfFilterName(void) const
 	return m_itfFilterName;
 }
 
-void NetInterfaces::set_itfFilterName(const QString &val)
+void NetInterfaces::setItfFilterName(const QString &val)
 {
 	if(val != m_itfFilterName)
 	{
 		m_itfFilterName = val;
-		emit itfFilterName_Changed(m_itfFilterName);
-		emit filteredInterfaces_Changed();
+		emit itfFilterNameChanged(m_itfFilterName);
+		emit filteredInterfacesChanged();
 	}
-	TRACE("%s\n", __FUNCTION__);
+
 }
 
 int NetInterfaces::itfFilterAF(void) const
@@ -247,9 +254,9 @@ int NetInterfaces::itfFilterAF(void) const
 	return m_itfFilterAF;
 }
 
-void NetInterfaces::set_itfFilterAF(int af)
+void NetInterfaces::setItfFilterAF(int af)
 {
-	TRACE("%s\n", __FUNCTION__);
+
 
 	if(af < Interface::AF_Unknown || af >= Interface::AF_Invalid)
 	{
@@ -260,8 +267,8 @@ void NetInterfaces::set_itfFilterAF(int af)
 	if(m_itfFilterAF != af)
 	{
 		m_itfFilterAF = af;
-		emit itfFilterAF_Changed(af);
-		emit filteredInterfaces_Changed();
+		emit itfFilterAFChanged(af);
+		emit filteredInterfacesChanged();
 	}
 }
 
@@ -270,9 +277,9 @@ int NetInterfaces::itfFilterMethod(void) const
 	return m_itfFilterMethod;
 }
 
-void NetInterfaces::set_itfFilterMethod(int method)
+void NetInterfaces::setItfFilterMethod(int method)
 {
-	TRACE("%s\n", __FUNCTION__);
+
 
 	if(method < Interface::IM_Unknown || method >= Interface::IM_Invalid)
 	{
@@ -283,41 +290,23 @@ void NetInterfaces::set_itfFilterMethod(int method)
 	if(m_itfFilterMethod != method)
 	{
 		m_itfFilterMethod = method;
-		emit itfFilterMethod_Changed(method);
-		emit filteredInterfaces_Changed();
+		emit itfFilterMethodChanged(method);
+		emit filteredInterfacesChanged();
 	}
 }
 
 /////////////////////////////////////////////////////////////////////////////
 
-Interface::Interface(ITF_IFACE_BLOCK &ifb, const Emitter &errHandler, QObject *pParent) : 	QObject(pParent),
-																							m_ifb(ifb),
-																							m_ipAddr(ifb.inet4s.addr, errHandler, this),
-																							m_netmask(ifb.inet4s.netmask, errHandler, this),
-																							m_gateway(ifb.inet4s.gate, errHandler, this),
-																							m_bcastAddr(ifb.inet4s.bcast, errHandler, this),
-																							m_ptpAddr(ifb.inet4s.pointopoint, errHandler, this),
-																							m_errHandler(errHandler)
+Interface::Interface(ITF_IFACE_BLOCK &ifb, const NotificationSink &notifyer, QObject *pParent) : 	QObject(pParent),
+																									m_ifb(ifb),
+																									m_inet(ifb, notifyer, this),
+																									m_rNotifyer(notifyer)
 {
 	setObjectName("Interface");
-	for(size_t i = 0; i < _countof(m_ifb.inet4s.namesvr); i++)
-	{
-		IPv4Address *addr = new IPv4Address(m_ifb.inet4s.namesvr[i], errHandler, this);
-		m_dnsList.append(addr);
-	}
-	TRACE("%s\n", __FUNCTION__);
 }
 
 Interface::~Interface(void)
 {
-	IPv4Address *addr;
-	
-    for(int i = 0; i < m_dnsList.count(); i++)
-    {
-        if((addr = m_dnsList.at(i)))
-        	delete addr;
-    }
-	TRACE("%s\n", __FUNCTION__);
 }
 
 QString Interface::name(void) const
@@ -332,68 +321,232 @@ QString Interface::afName(void) const
 
 int Interface::af(void) const
 {
-	return (int)m_ifb.proto;
+	return (int)_ENUM_TO_FLAG(m_ifb.proto);
 }
 
-void Interface::set_af(int af)
+void Interface::setAf(int af)
 {
 	if(!_IsPowerOf2(af) || (af < Interface::AF_Unknown) || (af >= Interface::AF_Invalid))
 	{
-		m_errHandler.emitError("Invalid address family: %d!", af);
+		m_rNotifyer.emitError("Invalid address family: %d!", af);
 		return;
 	}
 
-	if(m_ifb.proto != (IfaceProtos)_FLAG_TO_ENUM(af))
+	IfaceProtos proto = (IfaceProtos)_FLAG_TO_ENUM(af);
+
+	if(m_ifb.proto != proto)
 	{
-		m_ifb.proto = (IfaceProtos)_FLAG_TO_ENUM(af);
-		emit af_Changed(af);
-		emit afName_Changed();
+		m_ifb.proto = proto;
+		emit afChanged(af);
+		emit afNameChanged();
+		m_rNotifyer.filterPropertyChanged();
 	}
 }
 
-QString Interface::method(void) const
+QString Interface::methodName(void) const
 {
 	return ::GetIfaceMethodStr(m_ifb.method);
 }
 
-int Interface::itfMethod(void) const
+int Interface::method(void) const
+{
+	return (int)_ENUM_TO_FLAG(m_ifb.method);
+}
+
+void Interface::setMethod(int method)
+{
+	if(!_IsPowerOf2(method) || (method < Interface::IM_Unknown) || (method >= Interface::IM_Invalid))
+	{
+		m_rNotifyer.emitError("Invalid interface method: %d!", method);
+		return;
+	}
+
+	IfaceMethods meth = (IfaceMethods)_FLAG_TO_ENUM(method);
+
+	if(m_ifb.method != meth)
+	{
+		m_ifb.method = meth;
+		emit methodChanged(meth);
+		emit methodNameChanged();
+		m_rNotifyer.filterPropertyChanged();
+	}
+}
+
+Inet* Interface::inet(void)
 {
-	return (int)m_ifb.method;
+	return &m_inet;
 }
 
-IPv4Address* Interface::ipAddress(void)
+/////////////////////////////////////////////////////////////////////////////
+
+Inet::Inet(ITF_IFACE_BLOCK &ifb, const NotificationSink &notifyer, QObject *pParent) :	QObject(pParent),
+																						m_static(ifb.inet4s, notifyer, this),
+																						m_dhcp(ifb.inet4d, notifyer, this),
+																						m_rNotifyer(notifyer)
+{
+	setObjectName("Inet");
+}
+
+Inet::~Inet(void)
+{
+}
+
+Static* Inet::stat(void)
+{
+	return &m_static;
+}
+
+Dhcp* Inet::dhcp(void)
+{
+	return &m_dhcp;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+Static::Static(IFACE_INET_STATIC &itfs, const NotificationSink &notifyer, QObject *pParent) :	QObject(pParent),
+																								m_itfs(itfs),
+																								m_rNotifyer(notifyer),
+																								m_ipAddr(itfs.addr, notifyer, this),
+																								m_netmask(itfs.netmask, notifyer, this, _IsValidNetmask),
+																								m_gateway(itfs.gate, notifyer, this),
+																								m_bcastAddr(itfs.bcast, notifyer, this),
+																								m_ptpAddr(itfs.pointopoint, notifyer, this)
+{
+	setObjectName("Static");
+	for(size_t i = 0; i < _countof(m_itfs.namesvr); i++)
+	{
+		IPv4Address *addr = new IPv4Address(m_itfs.namesvr[i], notifyer, this);
+		m_dnsList.append(addr);
+	}
+	
+	QObject::connect(&m_netmask, SIGNAL(addressChanged(const QString&)), this, SLOT(netmaskChanged(const QString&)));
+}
+
+Static::~Static(void)
+{
+	IPv4Address *addr;
+
+    for(int i = 0; i < m_dnsList.count(); i++)
+    {
+        if((addr = m_dnsList.at(i)))
+        	delete addr;
+    }
+}
+
+IPv4Address* Static::ipAddress(void)
 {
 	return &m_ipAddr;
 }
 
-IPv4Address* Interface::netMask(void)
+IPv4Address* Static::netMask(void)
 {
 	return &m_netmask;
 }
 
-IPv4Address* Interface::gateway(void)
+IPv4Address* Static::gateway(void)
 {
 	return &m_gateway;
 }
 
-IPv4Address* Interface::bcastAddress(void)
+IPv4Address* Static::bcastAddress(void)
 {
 	return &m_bcastAddr;
 }
 
-IPv4Address* Interface::ptpAddress(void)
+IPv4Address* Static::ptpAddress(void)
 {
 	return &m_ptpAddr;
 }
 
-QQmlListProperty<IPv4Address> Interface::dnsServer(void)
+QQmlListProperty<IPv4Address> Static::dnsServer(void)
 {
 	return QQmlListProperty<IPv4Address>(this, m_dnsList);
 }
 
+int Static::metric(void) const
+{
+	return m_itfs.metric;
+}
+
+void Static::setMetric(int metric)
+{
+	if(m_itfs.metric != metric)
+	{
+		m_itfs.metric = metric;
+		emit metricChanged(metric);
+	}
+}
+
+int Static::mtu(void) const
+{
+	return m_itfs.mtu;
+}
+
+void Static::setMtu(int mtu)
+{
+	if(m_itfs.mtu != mtu)
+	{
+		m_itfs.mtu = mtu;
+		emit mtuChanged(mtu);
+	}
+}
+
+int Static::netPrefix(void) const
+{
+	return m_itfs.netprefix;
+}
+
+void Static::setNetPrefix(int netprefix)
+{
+	if(netprefix < 0 || netprefix > 32)
+	{
+		m_rNotifyer.emitError("Invalid net prefix: %d!", netprefix);
+		return;
+	}
+
+	if(m_itfs.netprefix != (unsigned int)netprefix)
+	{
+		struct in_addr in;
+		in.s_addr = _Prefix2Mask(netprefix);
+        m_netmask.setProperty("address", QVariant(inet_ntoa(in)));
+	}
+}
+
+void Static::netmaskChanged(const QString &mask)
+{
+	struct in_addr in;
+	std::string sa = mask.toStdString();
+
+	if(	inet_aton(sa.c_str(), &in) &&
+		_IsValidNetmask(in))
+	{
+		m_itfs.netprefix = _Mask2Prefix(in);
+		emit netPrefixChanged(m_itfs.netprefix);
+	}
+	else
+	{
+		m_rNotifyer.emitError("Invalid net mask: %s!", sa.c_str());
+        m_netmask.setProperty("address", QVariant("255.255.255.0"));
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+Dhcp::Dhcp(IFACE_INET_DHCP &itfd, const NotificationSink &notifyer, QObject *pParent) : QObject(pParent), m_itfd(itfd), m_rNotifyer(notifyer)
+{
+	setObjectName("Dhcp");
+}
+
+Dhcp::~Dhcp(void)
+{
+}
+
 /////////////////////////////////////////////////////////////////////////////
 
-IPv4Address::IPv4Address(struct in_addr &addr, const Emitter &errHandler, QObject *pParent) : QObject(pParent), m_addr(addr), m_errHandler(errHandler)
+IPv4Address::IPv4Address(struct in_addr &addr, const NotificationSink &notifyer, QObject *pParent, PFN_ADDRESS_VALIDATOR pfnAddrValidator) :	QObject(pParent),
+																																				m_addr(addr),
+																																				m_pfnAddrValidator(pfnAddrValidator),
+																																				m_rNotifyer(notifyer)
 {
 	setObjectName("IPv4Address");
 }
@@ -430,15 +583,21 @@ int IPv4Address::b3(void) const
 	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
 	return (int)pb[3];
 }
-    
-void IPv4Address::set_address(const QString &addr)
+
+void IPv4Address::setAddress(const QString &addr)
 {
 	struct in_addr newAddr, oldAddr;
 	std::string sa = addr.toStdString();
 
 	if(!inet_aton(sa.c_str(), &newAddr))
 	{
-		m_errHandler.emitError("Invalid IP address: '%s'!", sa.c_str());
+		m_rNotifyer.emitError("Invalid IP address: '%s'!", sa.c_str());
+		return;
+	}
+	
+	if(m_pfnAddrValidator && !(*m_pfnAddrValidator)(newAddr))
+	{
+		m_rNotifyer.emitError("Invalid address: '%s'!", sa.c_str());
 		return;
 	}
 
@@ -450,73 +609,73 @@ void IPv4Address::set_address(const QString &addr)
 		unsigned char *pb1 = (unsigned char*)&oldAddr.s_addr;
 		unsigned char *pb2 = (unsigned char*)&newAddr.s_addr;
 		if(pb1[0] != pb2[0])
-			emit b0_Changed(pb2[0]);
+			emit b0Changed(pb2[0]);
 		if(pb1[1] != pb2[1])
-			emit b1_Changed(pb2[1]);
+			emit b1Changed(pb2[1]);
 		if(pb1[2] != pb2[2])
-			emit b2_Changed(pb2[2]);
+			emit b2Changed(pb2[2]);
 		if(pb1[3] != pb2[3])
-			emit b3_Changed(pb2[3]);
-		emit address_Changed(address());
+			emit b3Changed(pb2[3]);
+		emit addressChanged(address());
 	}
 }
 
-void IPv4Address::set_b0(int b)
+void IPv4Address::setB0(int b)
 {
 	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
 	if(!_IS_VALID_BYTE_VALUE(b))
 	{
-		m_errHandler.emitError("Invalid IP address byte 0: '%d'!", b);
+		m_rNotifyer.emitError("Invalid IP address byte 0: '%d'!", b);
 		return;
 	}
 	if(b == (int)pb[0])
 		return;
 	pb[0] = (unsigned char)b;
-	emit b0_Changed(b);
-	emit address_Changed(address());
+	emit b0Changed(b);
+	emit addressChanged(address());
 }
 
-void IPv4Address::set_b1(int b)
+void IPv4Address::setB1(int b)
 {
 	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
 	if(!_IS_VALID_BYTE_VALUE(b))
 	{
-		m_errHandler.emitError("Invalid IP address byte 1: '%d'!", b);
+		m_rNotifyer.emitError("Invalid IP address byte 1: '%d'!", b);
 		return;
 	}
 	if(b == (int)pb[1])
 		return;
 	pb[1] = (unsigned char)b;
-	emit b1_Changed(b);
-	emit address_Changed(address());
+	emit b1Changed(b);
+	emit addressChanged(address());
 }
 
-void IPv4Address::set_b2(int b)
+void IPv4Address::setB2(int b)
 {
 	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
 	if(!_IS_VALID_BYTE_VALUE(b))
 	{
-		m_errHandler.emitError("Invalid IP address byte 2: '%d'!", b);
+		m_rNotifyer.emitError("Invalid IP address byte 2: '%d'!", b);
 		return;
 	}
 	if(b == (int)pb[2])
 		return;
 	pb[2] = (unsigned char)b;
-	emit b2_Changed(b);
-	emit address_Changed(address());
+	emit b2Changed(b);
+	emit addressChanged(address());
 }
 
-void IPv4Address::set_b3(int b)
+void IPv4Address::setB3(int b)
 {
 	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
 	if(!_IS_VALID_BYTE_VALUE(b))
 	{
-		m_errHandler.emitError("Invalid IP address byte 3: '%d'!", b);
+		m_rNotifyer.emitError("Invalid IP address byte 3: '%d'!", b);
 		return;
 	}
 	if(b == (int)pb[3])
 		return;
 	pb[3] = (unsigned char)b;
-	emit b3_Changed(b);
-	emit address_Changed(address());
+	emit b3Changed(b);
+	emit addressChanged(address());
 }

+ 146 - 88
qtplugin/netinterfaces.h

@@ -14,25 +14,29 @@
 /////////////////////////////////////////////////////////////////////////////
 // netinterfaces.h - Declarations:
 
-class Emitter
+class NotificationSink
 {
 public:
 	virtual void emitError(const char *pszFormatStr, ...) const	= 0;
+	virtual void filterPropertyChanged(void) const				= 0;
 };
 
 /////////////////////////////////////////////////////////////////////////////
 
+typedef bool (*PFN_ADDRESS_VALIDATOR)(const struct in_addr &addr);
+
 class IPv4Address : public QObject
 {
     Q_OBJECT
-    Q_PROPERTY(QString address READ address WRITE set_address NOTIFY address_Changed)
-    Q_PROPERTY(int b0 READ b0 WRITE set_b0 NOTIFY b0_Changed)
-    Q_PROPERTY(int b1 READ b1 WRITE set_b1 NOTIFY b1_Changed)
-    Q_PROPERTY(int b2 READ b2 WRITE set_b2 NOTIFY b2_Changed)
-    Q_PROPERTY(int b3 READ b3 WRITE set_b3 NOTIFY b3_Changed)
+    Q_PROPERTY(QString address READ address WRITE setAddress NOTIFY addressChanged)
+    Q_PROPERTY(int b0 READ b0 WRITE setB0 NOTIFY b0Changed)
+    Q_PROPERTY(int b1 READ b1 WRITE setB1 NOTIFY b1Changed)
+    Q_PROPERTY(int b2 READ b2 WRITE setB2 NOTIFY b2Changed)
+    Q_PROPERTY(int b3 READ b3 WRITE setB3 NOTIFY b3Changed)
+
 
 public:
-    explicit IPv4Address(struct in_addr &addr, const Emitter &errHandler, QObject *pParent = 0);
+    explicit IPv4Address(struct in_addr &addr, const NotificationSink &notifyer, QObject *pParent = 0, PFN_ADDRESS_VALIDATOR pfnAddrValidator = NULL);
     virtual ~IPv4Address(void);
 
 private:
@@ -42,86 +46,149 @@ private:
     int b2(void) const;
     int b3(void) const;
     
-    void set_address(const QString &addr);
-    void set_b0(int b);
-    void set_b1(int b);
-    void set_b2(int b);
-    void set_b3(int b);
+    void setAddress(const QString &addr);
+    void setB0(int b);
+    void setB1(int b);
+    void setB2(int b);
+    void setB3(int b);
 
 signals:
-	void address_Changed(const QString&);
-	void b0_Changed(int);
-	void b1_Changed(int);
-	void b2_Changed(int);
-	void b3_Changed(int);
+	void addressChanged(const QString&);
+	void b0Changed(int);
+	void b1Changed(int);
+	void b2Changed(int);
+	void b3Changed(int);
 
 private:
 	struct in_addr &m_addr;
-	const Emitter &m_errHandler;
+	PFN_ADDRESS_VALIDATOR m_pfnAddrValidator;
+	const NotificationSink &m_rNotifyer;
 };
 
 /////////////////////////////////////////////////////////////////////////////
 
-class Interface : public QObject
+class Static : public QObject
 {
     Q_OBJECT
-    Q_PROPERTY(QString name READ name CONSTANT)
-    Q_PROPERTY(QString afName READ afName NOTIFY afName_Changed)
-    Q_PROPERTY(int af READ af WRITE set_af NOTIFY af_Changed)
-    Q_PROPERTY(QString method READ method)
-    Q_PROPERTY(int itfMethod READ itfMethod)
-	// static
     Q_PROPERTY(IPv4Address* ipAddress READ ipAddress CONSTANT)
     Q_PROPERTY(IPv4Address* netMask READ netMask CONSTANT)
     Q_PROPERTY(IPv4Address* gateway READ gateway CONSTANT)
     Q_PROPERTY(IPv4Address* bcastAddress READ bcastAddress CONSTANT)
     Q_PROPERTY(IPv4Address* ptpAddress READ ptpAddress CONSTANT)
     Q_PROPERTY(QQmlListProperty<IPv4Address> dnsServer READ dnsServer CONSTANT)
-    // dhcp
+    Q_PROPERTY(int metric READ metric WRITE setMetric NOTIFY metricChanged)
+    Q_PROPERTY(int mtu READ mtu WRITE setMtu NOTIFY mtuChanged)
+    Q_PROPERTY(int netPrefix READ netPrefix WRITE setNetPrefix NOTIFY netPrefixChanged)
+
+public:
+    explicit Static(IFACE_INET_STATIC &itfs, const NotificationSink &notifyer, QObject *pParent = 0);
+    virtual ~Static(void);
+
+private:
+    IPv4Address* ipAddress(void);
+    IPv4Address* netMask(void);
+    IPv4Address* gateway(void);
+    IPv4Address* bcastAddress(void);
+    IPv4Address* ptpAddress(void);
+    QQmlListProperty<IPv4Address> dnsServer(void);
+    int metric(void) const;
+    void setMetric(int metric);
+    int mtu(void) const;
+    void setMtu(int mtu);
+    int netPrefix(void) const;
+    void setNetPrefix(int netprefix);
+
+private slots:
+    void netmaskChanged(const QString&);
+
+signals:
+	void metricChanged(int metric);
+	void mtuChanged(int mtu);
+	void netPrefixChanged(unsigned int netprefix);
+
+private:
+	IFACE_INET_STATIC &m_itfs;
+	const NotificationSink &m_rNotifyer;
+	IPv4Address m_ipAddr;
+	IPv4Address m_netmask;
+	IPv4Address m_gateway;
+	IPv4Address m_bcastAddr;
+	IPv4Address m_ptpAddr;
+	QList<IPv4Address*> m_dnsList;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class Dhcp : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit Dhcp(IFACE_INET_DHCP &itfd, const NotificationSink &notifyer, QObject *pParent = 0);
+    virtual ~Dhcp(void);
+
+private:
+	IFACE_INET_DHCP &m_itfd;
+	const NotificationSink &m_rNotifyer;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class Inet : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(Static* stat READ stat CONSTANT)
+    Q_PROPERTY(Dhcp* dhcp READ dhcp CONSTANT)
 
 public:
-    explicit Interface(ITF_IFACE_BLOCK &ifb, const Emitter &errHandler, QObject *pParent = 0);
+    explicit Inet(ITF_IFACE_BLOCK &ifb, const NotificationSink &notifyer, QObject *pParent = 0);
+    virtual ~Inet(void);
+
+private:
+    Static* stat(void);
+    Dhcp* dhcp(void);
+
+private:
+    Static m_static;
+    Dhcp m_dhcp;
+	const NotificationSink &m_rNotifyer;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class Interface : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(QString name READ name CONSTANT)
+    Q_PROPERTY(QString afName READ afName NOTIFY afNameChanged)
+    Q_PROPERTY(int af READ af WRITE setAf NOTIFY afChanged)
+    Q_PROPERTY(QString methodName READ methodName NOTIFY methodNameChanged)
+    Q_PROPERTY(int method READ method WRITE setMethod NOTIFY methodChanged)
+    Q_PROPERTY(Inet* inet READ inet CONSTANT)
+
+public:
+    explicit Interface(ITF_IFACE_BLOCK &ifb, const NotificationSink &notifyer, QObject *pParent = 0);
     virtual ~Interface(void);
 
     inline const ITF_IFACE_BLOCK & getIface(void) const {
     	return m_ifb;}
+    
+    inline unsigned long getID(void) const {
+    	return m_ifb.id;}
 
 	enum AddressFamily
 	{
-#if 0
-		AF_Unknown = -1,
-		AF_Inet,
-		AF_Inet6,
-		AF_Ipx,
-		AF_Can,
-		AF_Invalid
-#else
 		AF_Unknown	= 0,
 		AF_Inet		= 0x0001,
 		AF_Inet6	= 0x0002,
 		AF_Ipx		= 0x0004,
 		AF_Can		= 0x0008,
 		AF_Invalid	= 0x0010
-#endif
 	};
 	Q_ENUMS(AddressFamily)
 
 	enum ItfMethod
 	{
-#if 0
-		IM_Unknown	= -1,
-		IM_Static,
-		IM_Dhcp,
-		IM_Manual,
-		IM_BootP,
-		IM_Tunnel,
-		IM_Ppp,
-		IM_WvDial,
-		IM_IpV4ll,
-		IM_Loopback,
-		IM_Auto,
-		IM_Invalid
-#else
 		IM_Unknown	= 0,
 		IM_Static	= 0x0001,
 		IM_Dhcp		= 0x0002,
@@ -134,7 +201,6 @@ public:
 		IM_Loopback	= 0x0100,
 		IM_Auto		= 0x0200,
 		IM_Invalid	= 0x0400
-#endif
 	};
 	Q_ENUMS(ItfMethod)
 
@@ -142,42 +208,35 @@ private:
     QString name(void) const;
     QString afName(void) const;
     int af(void) const;
-    void set_af(int af);
-    QString method(void) const;
-    int itfMethod(void) const;
-    IPv4Address* ipAddress(void);
-    IPv4Address* netMask(void);
-    IPv4Address* gateway(void);
-    IPv4Address* bcastAddress(void);
-    IPv4Address* ptpAddress(void);
-    QQmlListProperty<IPv4Address> dnsServer(void);
+    void setAf(int af);
+    QString methodName(void) const;
+    int method(void) const;
+    void setMethod(int method);
+    Inet* inet(void);
 
 signals:
-	void afName_Changed(void);
-	void af_Changed(int af);
+	void afNameChanged(void);
+	void afChanged(int af);
+	void methodNameChanged(void);
+	void methodChanged(int method);
 
 private:
 	ITF_IFACE_BLOCK &m_ifb;
-	IPv4Address m_ipAddr;
-	IPv4Address m_netmask;
-	IPv4Address m_gateway;
-	IPv4Address m_bcastAddr;
-	IPv4Address m_ptpAddr;
-	QList<IPv4Address*> m_dnsList;
-	const Emitter &m_errHandler;
+	Inet m_inet;
+	const NotificationSink &m_rNotifyer;
 };
 
 /////////////////////////////////////////////////////////////////////////////
 
-class NetInterfaces : public QObject, public QQmlParserStatus, public Emitter
+class NetInterfaces : public QObject, public QQmlParserStatus, public NotificationSink
 {
     Q_OBJECT
     Q_INTERFACES(QQmlParserStatus)
-    Q_PROPERTY(QQmlListProperty<Interface> interfaces READ interfaces NOTIFY interfaces_Changed)
-    Q_PROPERTY(QQmlListProperty<Interface> filteredInterfaces READ filteredInterfaces NOTIFY filteredInterfaces_Changed)
-    Q_PROPERTY(QString itfFilterName READ itfFilterName WRITE set_itfFilterName NOTIFY itfFilterName_Changed)
-    Q_PROPERTY(int itfFilterAF READ itfFilterAF WRITE set_itfFilterAF NOTIFY itfFilterAF_Changed)
-    Q_PROPERTY(int itfFilterMethod READ itfFilterMethod WRITE set_itfFilterMethod NOTIFY itfFilterMethod_Changed)
+    Q_PROPERTY(QQmlListProperty<Interface> interfaces READ interfaces NOTIFY interfacesChanged)
+    Q_PROPERTY(QQmlListProperty<Interface> filteredInterfaces READ filteredInterfaces NOTIFY filteredInterfacesChanged)
+    Q_PROPERTY(QString itfFilterName READ itfFilterName WRITE setItfFilterName NOTIFY itfFilterNameChanged)
+    Q_PROPERTY(int itfFilterAF READ itfFilterAF WRITE setItfFilterAF NOTIFY itfFilterAFChanged)
+    Q_PROPERTY(int itfFilterMethod READ itfFilterMethod WRITE setItfFilterMethod NOTIFY itfFilterMethodChanged)
 
 public:
     explicit NetInterfaces(QObject *pParent = 0);
@@ -188,32 +247,31 @@ public:
 	Q_INVOKABLE bool initialize(void);
 	Q_INVOKABLE bool save(void);
 	Q_INVOKABLE bool saveAs(const QString &path);
-//	Q_INVOKABLE QVariantList getInterface(const QString &itfName);
-	Q_INVOKABLE QVariant newInterface(QString name, int af, int method);
+	Q_INVOKABLE Interface* newInterface(QString name, int af, int method);
+	Q_INVOKABLE void removeInterface(Interface *pi);
 
 	virtual void classBegin();
 	virtual void componentComplete();
 	virtual void emitError(const char *pszFormatStr, ...) const;
+	virtual void filterPropertyChanged(void) const;
 
 signals:
-	void interfaces_Changed(void);
-	void filteredInterfaces_Changed(void);
-	void itfFilterName_Changed(const QString &val);
-	void itfFilterAF_Changed(int af);
-	void itfFilterMethod_Changed(int method);
+	void interfacesChanged(void) const;
+	void filteredInterfacesChanged(void) const;
+	void itfFilterNameChanged(const QString &val) const;
+	void itfFilterAFChanged(int af) const;
+	void itfFilterMethodChanged(int method) const;
+	void error(QString msg) const;
 
 private:
 	QQmlListProperty<Interface> interfaces(void);
 	QQmlListProperty<Interface> filteredInterfaces(void);
 	const QString& itfFilterName(void) const;
-	void set_itfFilterName(const QString &val);
+	void setItfFilterName(const QString &val);
 	int itfFilterAF(void) const;
-	void set_itfFilterAF(int nval);
+	void setItfFilterAF(int nval);
 	int itfFilterMethod(void) const;
-	void set_itfFilterMethod(int method);
-
-signals:
-	void sigError(QString msg) const;
+	void setItfFilterMethod(int method);
 
 private:
 	ETC_NETWORK_INTERFACES m_eni;

+ 3 - 0
qtplugin/netinterfaces_plugin.cpp

@@ -7,5 +7,8 @@ void NetInterfacesPlugin::registerTypes(const char *uri)
     // gfa.plugins.qml.net
     qmlRegisterType<NetInterfaces>(uri, 1, 0, "NetInterfaces");
     qmlRegisterUncreatableType<Interface>(uri, 1, 0, "Interface", "return type only");
+    qmlRegisterUncreatableType<Inet>(uri, 1, 0, "Inet", "return type only");
+    qmlRegisterUncreatableType<Static>(uri, 1, 0, "Static", "return type only");
+    qmlRegisterUncreatableType<Dhcp>(uri, 1, 0, "Dhcp", "return type only");
     qmlRegisterUncreatableType<IPv4Address>(uri, 1, 0, "IPv4Address", "return type only");
 }