Преглед на файлове

QML-Wrapper für gfanet und Listmodel.

Rind преди 4 години
родител
ревизия
ef5e64cf93
променени са 7 файла, в които са добавени 2357 реда и са изтрити 2 реда
  1. 5 1
      README.md
  2. 2 1
      gfaqt.pro
  3. 6 0
      src/qappctrl.cpp
  4. 422 0
      src/qappctrl.h
  5. 1559 0
      src/qnetworkinfo.cpp
  6. 357 0
      src/qnetworkinfo.h
  7. 6 0
      src/qsysinfo.cpp

+ 5 - 1
README.md

@@ -5,7 +5,7 @@ Allgemeine Bibliothek für QML-Objekte und Objekte mit QT-Bindung, mit Ausnahme
 ---
 
 ***Version:***  
-libgfaqt.so.1.1.0  
+libgfaqt.so.1.2.0  
 
 ***SO-Name:***  
 libgfaqt.so.1
@@ -26,6 +26,7 @@ libgfaqt.so (-lgfaqt)
 * QML-Wrapper für Hotplug-Events.
 * QML-Wrapper für MySql-Info.
 * QML-Wrapper für Tiva/SPI-Info.
+* QML-Wrapper zur Netzwerk-Interface-Konfiguration.
 
 ---
 
@@ -40,4 +41,7 @@ libgfaqt.so (-lgfaqt)
 * **1.1.0**
 	* Q-App-Control-Funktion zum Beenden eines Prozesses im Zombie-State hinzugefügt.
 	* MySql-Info implementiert.
+
+* **1.2.0**
 	* Tiva/SPI-Info implementiert.
+	* Netzwerk-Interface-Konfiguration implementiert.

+ 2 - 1
gfaqt.pro

@@ -1,5 +1,5 @@
 TEMPLATE = lib
-VERSION = 1.1
+VERSION = 1.2
 QT += qml quick core
 CONFIG -= app_bundle
 CONFIG += c++11 shared thread
@@ -11,6 +11,7 @@ SOURCES += \
     src/qappctrl.cpp \
     src/qappinfo.cpp \
     src/qmysqlinfo.cpp \
+    src/qnetworkinfo.cpp \
     src/qsysinfo.cpp
 
 HEADERS += \

+ 6 - 0
src/qappctrl.cpp

@@ -105,6 +105,12 @@ void QGfaAppCtrl::RegisterQmlTypes(QQmlEngine &rEng, int nVerMajor, int nVerMino
 	qmlRegisterUncreatableType<QGfaMySqlSchemaModel>("com.gfa.ipc.appctrl", nVerMajor, nVerMinor, "QGfaMySqlSchemaModel", QStringLiteral("class not creatable in QML"));
 	qmlRegisterUncreatableType<QGfaMySqlInfo>("com.gfa.ipc.appctrl", nVerMajor, nVerMinor, "QGfaMySqlInfo", QStringLiteral("class not creatable in QML"));
 	qmlRegisterUncreatableType<QTivaInfo>("com.gfa.ipc.appctrl", nVerMajor, nVerMinor, "QTivaInfo", QStringLiteral("class not creatable in QML"));
+	qmlRegisterUncreatableType<QNetworkInterfaces>("com.gfa.ipc.appctrl", nVerMajor, nVerMinor, "QNetworkInterfaces", QStringLiteral("class not creatable in QML"));
+	qmlRegisterUncreatableType<QInterface>("com.gfa.ipc.appctrl", nVerMajor, nVerMinor, "QInterface", QStringLiteral("class not creatable in QML"));
+	qmlRegisterUncreatableType<QInet>("com.gfa.ipc.appctrl", nVerMajor, nVerMinor, "QInet", QStringLiteral("class not creatable in QML"));
+	qmlRegisterUncreatableType<QDhcp>("com.gfa.ipc.appctrl", nVerMajor, nVerMinor, "QDhcp", QStringLiteral("class not creatable in QML"));
+	qmlRegisterUncreatableType<QStatic>("com.gfa.ipc.appctrl", nVerMajor, nVerMinor, "QStatic", QStringLiteral("class not creatable in QML"));
+	qmlRegisterUncreatableType<QIPv4Address>("com.gfa.ipc.appctrl", nVerMajor, nVerMinor, "QIPv4Address", QStringLiteral("class not creatable in QML"));
 
 	rEng.rootContext()->setContextProperty(QStringLiteral("qGfaAppCtrl"), this);
 }

+ 422 - 0
src/qappctrl.h

@@ -13,6 +13,9 @@
 #include <vector>
 #include <gfa/gfaipc.h>
 #include <gfa/ipcpriv.h>
+#include <qqmlparserstatus.h>
+#include <gfa/mutex.h>
+#include <gfa/gfanet.h>
 
 #ifdef __cplusplus
 
@@ -239,6 +242,422 @@ private:
 
 /////////////////////////////////////////////////////////////////////////////
 
+class QInterface;
+
+class NotificationSink
+{
+public:
+	virtual void reportError(const char *pszFormatStr, ...)									= 0;
+	virtual void filterPropertyChanged(void) const											= 0;
+	virtual void selConfigChanged(QInterface* pi, unsigned int cfgOld, unsigned int cfgNew)	= 0;
+	virtual int getInterfaceSelConfig(QInterface &ri)										= 0;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef bool (*PFN_ADDRESS_VALIDATOR)(const struct in_addr &addr);
+
+class QIPv4Address : public QObject
+{
+    Q_OBJECT
+    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)
+    Q_PROPERTY(double addr READ addr WRITE setAddr NOTIFY addrChanged)
+
+
+public:
+    explicit QIPv4Address(struct in_addr &addr, NotificationSink &notifyer, QObject *pParent = 0, PFN_ADDRESS_VALIDATOR pfnAddrValidator = NULL);
+    virtual ~QIPv4Address(void);
+
+private:
+    QString address(void) const;
+    int b0(void) const;
+    int b1(void) const;
+    int b2(void) const;
+    int b3(void) const;
+    double addr(void) const;
+    
+    void setAddress(const QString &addr);
+    void setB0(int b);
+    void setB1(int b);
+    void setB2(int b);
+    void setB3(int b);
+    void setAddr(double val);
+
+signals:
+	void addressChanged(const QString&);
+	void b0Changed(int);
+	void b1Changed(int);
+	void b2Changed(int);
+	void b3Changed(int);
+	void addrChanged(double);
+
+private:
+	struct in_addr &m_addr;
+	PFN_ADDRESS_VALIDATOR m_pfnAddrValidator;
+	NotificationSink &m_rNotifyer;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class QStatic : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(QIPv4Address* ipAddress READ ipAddress CONSTANT)
+    Q_PROPERTY(QIPv4Address* netMask READ netMask CONSTANT)
+    Q_PROPERTY(QIPv4Address* gateway READ gateway CONSTANT)
+    Q_PROPERTY(QIPv4Address* bcastAddress READ bcastAddress CONSTANT)
+    Q_PROPERTY(QIPv4Address* ptpAddress READ ptpAddress CONSTANT)
+    Q_PROPERTY(QQmlListProperty<QIPv4Address> dnsServer READ dnsServer CONSTANT)
+    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 QStatic(IFACE_INET_STATIC &itfs, NotificationSink &notifyer, QObject *pParent = 0);
+    virtual ~QStatic(void);
+
+private:
+    QIPv4Address* ipAddress(void);
+    QIPv4Address* netMask(void);
+    QIPv4Address* gateway(void);
+    QIPv4Address* bcastAddress(void);
+    QIPv4Address* ptpAddress(void);
+    QQmlListProperty<QIPv4Address> 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;
+	NotificationSink &m_rNotifyer;
+	QIPv4Address m_ipAddr;
+	QIPv4Address m_netmask;
+	QIPv4Address m_gateway;
+	QIPv4Address m_bcastAddr;
+	QIPv4Address m_ptpAddr;
+	QList<QIPv4Address*> m_dnsList;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class QDhcp : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit QDhcp(IFACE_INET_DHCP &itfd, NotificationSink &notifyer, QObject *pParent = 0);
+    virtual ~QDhcp(void);
+
+private:
+	IFACE_INET_DHCP &m_itfd;
+	NotificationSink &m_rNotifyer;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class QInet : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(QStatic* stat READ stat CONSTANT)
+    Q_PROPERTY(QDhcp* dhcp READ dhcp CONSTANT)
+
+public:
+    explicit QInet(ITF_IFACE_BLOCK &ifb, NotificationSink &notifyer, QObject *pParent = 0);
+    virtual ~QInet(void);
+
+private:
+    QStatic* stat(void);
+    QDhcp* dhcp(void);
+
+private:
+    QStatic m_static;
+    QDhcp m_dhcp;
+	NotificationSink &m_rNotifyer;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class QInterface : 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(int selCfg READ selCfg WRITE setSelCfg NOTIFY selCfgChanged)
+    Q_PROPERTY(QInet* inet READ inet CONSTANT)
+
+public:
+    explicit QInterface(ITF_IFACE_BLOCK &ifb, NotificationSink &notifyer, QObject *pParent = 0);
+    virtual ~QInterface(void);
+
+    inline const ITF_IFACE_BLOCK & getIface(void) const {
+    	return m_ifb;}
+
+    inline ITF_IFACE_BLOCK & getIface(void){
+    	return m_ifb;}
+    
+    inline unsigned long getID(void) const {
+    	return m_ifb.id;}
+    
+    inline int getSelCfg(void) const {
+	    return m_selCfg;}
+    
+    inline const char * getName(void) const {
+	    return m_ifb.cfgName.c_str();}
+
+	enum AddressFamily
+	{
+		AF_Unknown	= 0,
+		AF_Inet		= 0x0001,
+		AF_Inet6	= 0x0002,
+		AF_Ipx		= 0x0004,
+		AF_Can		= 0x0008,
+		AF_Invalid	= 0x0010
+	};
+	Q_ENUMS(AddressFamily)
+
+	enum ItfMethod
+	{
+		IM_Unknown	= 0,
+		IM_Static	= 0x0001,
+		IM_Dhcp		= 0x0002,
+		IM_Manual	= 0x0004,
+		IM_BootP	= 0x0008,
+		IM_Tunnel	= 0x0010,
+		IM_Ppp		= 0x0020,
+		IM_WvDial	= 0x0040,
+		IM_IpV4ll	= 0x0080,
+		IM_Loopback	= 0x0100,
+		IM_Auto		= 0x0200,
+		IM_Invalid	= 0x0400
+	};
+	Q_ENUMS(ItfMethod)
+
+	enum SelConfig
+	{
+		SC_None			= 0,
+		SC_Auto			= 0x0001,
+		SC_AllowAuto	= 0x0002,
+		SC_AllowHotplug	= 0x0004,
+		SC_NoAutoDown	= 0x0008,
+		SC_NoScripts	= 0x0010,
+		SC_Invalid		= 0x0020
+	};
+	Q_ENUMS(SelConfig)
+
+private:
+    QString name(void) const;
+    QString afName(void) const;
+    int af(void) const;
+    void setAf(int af);
+    QString methodName(void) const;
+    int method(void) const;
+    void setMethod(int method);
+    int selCfg(void) const;
+    void setSelCfg(int cfg);
+    QInet* inet(void);
+
+signals:
+	void afNameChanged(void);
+	void afChanged(int af);
+	void methodNameChanged(void);
+	void methodChanged(int method);
+	void selCfgChanged(int cfg);
+
+private:
+	ITF_IFACE_BLOCK &m_ifb;
+	QInet m_inet;
+	NotificationSink &m_rNotifyer;
+	int m_selCfg;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class QGfaNetInterfacesSchemaTreeItem
+{
+public:
+	explicit QGfaNetInterfacesSchemaTreeItem(QGfaNetInterfacesSchemaTreeItem *pParentItem = NULL);
+	QGfaNetInterfacesSchemaTreeItem(const QVariant &name, const QVariant &data, const QVariant &dataF, QGfaNetInterfacesSchemaTreeItem *parentItem);
+	~QGfaNetInterfacesSchemaTreeItem(void);
+
+	void appendChild(QGfaNetInterfacesSchemaTreeItem *child);
+	void clear(void);
+
+	QGfaNetInterfacesSchemaTreeItem *child(int row);
+	QGfaNetInterfacesSchemaTreeItem *getChildItemByName(const char *pszName);
+	int childCount() const;
+	int columnCount() const;
+	QVariant data(int column) const;
+	int row() const;
+	QGfaNetInterfacesSchemaTreeItem *parentItem();
+	int compareValue(const QVariant &val) const;
+	bool updateValue(const QVariant &val, const QVariant &valF = QVariant());
+
+private:
+	QVector<QGfaNetInterfacesSchemaTreeItem*> m_childItems;
+	QVector<QVariant> m_itemData;
+	QGfaNetInterfacesSchemaTreeItem *m_parentItem;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class QGfaNetInterfacesSchemaModel : public QAbstractItemModel
+{
+    Q_OBJECT
+
+public:
+	typedef enum
+	{
+	    SMR_Name = Qt::UserRole,
+	    SMR_Info,
+	    SMR_InfoFormatted,
+	    SMR_Invalid
+	}SchemaModelRoles;
+
+public:
+	explicit QGfaNetInterfacesSchemaModel(QObject *pParent = NULL);
+	~QGfaNetInterfacesSchemaModel(void);
+
+	QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
+	Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
+	QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+	QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+	QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
+	int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+	int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+	QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE;
+
+	void setModelData(LPETC_NETWORK_INTERFACES pnif);
+	void clearAll(void);
+
+private:
+    QGfaNetInterfacesSchemaTreeItem *m_pRootItem;
+    QHash<int, QByteArray> m_roleNameMapping;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class QNetworkInterfaces :	public QObject,
+							public QQmlParserStatus,
+							public NotificationSink
+{
+    Q_OBJECT
+    Q_INTERFACES(QQmlParserStatus)
+    Q_PROPERTY(QQmlListProperty<QInterface> interfaces READ interfaces NOTIFY interfacesChanged)
+    Q_PROPERTY(QQmlListProperty<QInterface> 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)
+    Q_PROPERTY(bool ifUpDownInProgress READ ifUpDownInProgress CONSTANT)
+    Q_PROPERTY(QGfaNetInterfacesSchemaModel *schemaModel READ schemaModel CONSTANT)
+
+public:
+    explicit QNetworkInterfaces(QObject *pParent = 0);
+    virtual ~QNetworkInterfaces(void);
+
+	enum IfUpDownCtx
+	{
+		UDC_Start,
+		UDC_Stop,
+		UDC_Restart
+	};
+	Q_ENUMS(IfUpDownCtx)
+
+public:
+	Q_INVOKABLE void reset(void);
+	Q_INVOKABLE bool initialize(void);
+	Q_INVOKABLE bool save(void);
+	Q_INVOKABLE bool saveAs(const QString &path);
+	Q_INVOKABLE bool reload(void);
+	Q_INVOKABLE QInterface* newInterface(QString name, int af, int method);
+	Q_INVOKABLE void removeInterface(QInterface *pi);
+	Q_INVOKABLE bool startInterface(QInterface *pi);
+	Q_INVOKABLE bool stopInterface(QInterface *pi);
+	Q_INVOKABLE bool restartInterface(QInterface *pi);
+	Q_INVOKABLE bool cancelStartStopInterface(void);
+
+	void classBegin() Q_DECL_OVERRIDE;
+	void componentComplete() Q_DECL_OVERRIDE;
+	virtual void reportError(const char *pszFormatStr, ...);
+	virtual void filterPropertyChanged(void) const;
+	virtual void selConfigChanged(QInterface* pi, unsigned int cfgOld, unsigned int cfgNew);
+	virtual int getInterfaceSelConfig(QInterface &ri);
+	
+	inline pid_t GetIfUpDownPid(void) const {
+		return m_ifUpDownPid;}
+	
+	inline void SetIfUpDownPid(pid_t pid){
+		m_ifUpDownPid = pid;}
+	    
+	inline bool GetIfUpDownInProgress(void) const {
+		return m_bIfUpDownInProgress;}
+	    
+	inline void SetIfUpDownInProgress(bool bVal){
+		m_bIfUpDownInProgress = bVal;}
+	
+	bool SetInterlockedIfUpDownInProgress(void);
+
+signals:
+	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;
+	void ifUpDown(QString msg) const;
+	void ifUpDownCompleted(int ctx, int code) const;
+
+private:
+	QQmlListProperty<QInterface> interfaces(void);
+	QQmlListProperty<QInterface> filteredInterfaces(void);
+	const QString& itfFilterName(void) const;
+	void setItfFilterName(const QString &val);
+	int itfFilterAF(void) const;
+	void setItfFilterAF(int nval);
+	int itfFilterMethod(void) const;
+	void setItfFilterMethod(int method);
+	bool ifUpDownInProgress(void) const;
+
+    static void onIfUpDown(const char *pszMsg, void *pCtx);
+    static void onIfUpCompleted(int nExitCode, void *pCtx);
+    static void onIfDownCompleted(int nExitCode, void *pCtx);
+    static void onIfRestartCompleted(int nExitCode, void *pCtx);
+
+	QGfaNetInterfacesSchemaModel* schemaModel(void);
+
+private:
+	ETC_NETWORK_INTERFACES m_eni;
+	LPETC_NETWORK_INTERFACES m_pEniSave;
+	QList<QInterface*> m_interfaces;
+	QList<QInterface*> m_filteredInterfaces;
+	QString m_itfFilterName;
+	int m_itfFilterAF;
+	int m_itfFilterMethod;
+	bool m_bIfUpDownInProgress;
+	pid_t m_ifUpDownPid;
+	CLocalMutex m_mutex;
+	QGfaNetInterfacesSchemaModel m_netInterfacesSchemaModel;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
 class QTivaInfo : public QObject
 {
     Q_OBJECT
@@ -308,6 +727,7 @@ class QGfaSysInfo : public QObject
     Q_PROPERTY(QGfaStgDevList *stgDev READ stgDev CONSTANT)
     Q_PROPERTY(bool bootFromEmmc READ bootFromEmmc NOTIFY bootFromEmmcChanged)
     Q_PROPERTY(QTivaInfo *tivaInfo READ tivaInfo CONSTANT)
+    Q_PROPERTY(QNetworkInterfaces *netInterfaceInfo READ netInterfaceInfo CONSTANT)
 
 public:
 	explicit QGfaSysInfo(QObject *pParent = NULL);
@@ -332,6 +752,7 @@ private:
 	QGfaStgDevList* stgDev(void);
 	bool bootFromEmmc(void) const;
 	QTivaInfo* tivaInfo(void);
+	QNetworkInterfaces* netInterfaceInfo(void);
 
 public:
 	void setSysMemInfo(LPCGFA_APPCTRL_SYSMEM psm, bool bDoHeavyLoadUpdate = false);
@@ -380,6 +801,7 @@ private:
 	quint64 m_nMemCached;
 	QGfaStgDevList m_stgDevList;
 	QTivaInfo m_tivaInfo;
+	QNetworkInterfaces m_netInterfaces;
 	bool m_bootFromEmmc;
 };
 

+ 1559 - 0
src/qnetworkinfo.cpp

@@ -0,0 +1,1559 @@
+#include "qappctrl.h"
+//#include "helpers.h"
+#include "defines.h"
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _countof
+#define _countof(a)					(sizeof(a) / sizeof(*a))
+#endif	//	_countof
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef struct _SCHEMA_MODEL_ROLES
+{
+	int nRole;
+	const char *pszRoleName;
+}SCHEMA_MODEL_ROLES, *LPSCHEMA_MODEL_ROLES;
+typedef const SCHEMA_MODEL_ROLES *LPCSCHEMA_MODEL_ROLES;
+
+static const SCHEMA_MODEL_ROLES g_roles[] =
+{
+	{QGfaMySqlSchemaModel::SMR_Name,			"name"},
+	{QGfaMySqlSchemaModel::SMR_Info,			"infoRaw"},
+	{QGfaMySqlSchemaModel::SMR_InfoFormatted,	"infoFormatted"}
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef struct _IF_UPDOWN_CONTEXT
+{
+	QNetworkInterfaces *pThis;
+	QInterface *pi;
+	int ctx;
+}IF_UPDOWN_CONTEXT, *LPIF_UPDOWN_CONTEXT;
+typedef const IF_UPDOWN_CONTEXT *LPCIF_UPDOWN_CONTEXT;
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define _IS_VALID_BYTE_VALUE(b)		(((b) >= 0) && ((b) <= 255))
+
+
+template<typename T>
+static bool _IsPowerOf2(T x)
+{
+	return x && !(x & (x - 1));
+}
+
+template<typename T>
+static unsigned int _BitCount(T n)
+{
+	unsigned int count = 0;
+	while(n)
+	{
+		count++;
+		n &= (n - 1);
+	}
+	return count;
+}
+
+template<typename T>
+static int _BitNumber(T n)
+{
+	if(!n || !_IsPowerOf2(n))
+		return -1;
+	int count = 0;
+	while(n)
+	{
+		count++;
+		n >>= 1;
+	}
+	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)
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+
+QGfaNetInterfacesSchemaTreeItem::QGfaNetInterfacesSchemaTreeItem(QGfaNetInterfacesSchemaTreeItem *pParentItem) : m_parentItem(pParentItem)
+{
+}
+
+QGfaNetInterfacesSchemaTreeItem::QGfaNetInterfacesSchemaTreeItem(const QVariant &name, const QVariant &data, const QVariant &dataF, QGfaNetInterfacesSchemaTreeItem *pParentItem) : m_parentItem(pParentItem)
+{
+	m_itemData.append(name);
+	m_itemData.append(data);
+	m_itemData.append(dataF.isValid() ? dataF : data);
+}
+
+QGfaNetInterfacesSchemaTreeItem::~QGfaNetInterfacesSchemaTreeItem(void)
+{
+    qDeleteAll(m_childItems);
+}
+
+void QGfaNetInterfacesSchemaTreeItem::appendChild(QGfaNetInterfacesSchemaTreeItem *item)
+{
+    m_childItems.append(item);
+}
+
+void QGfaNetInterfacesSchemaTreeItem::clear(void)
+{
+    qDeleteAll(m_childItems);
+    m_childItems.clear();
+    m_itemData.clear();
+    m_parentItem = NULL;
+}
+
+QGfaNetInterfacesSchemaTreeItem *QGfaNetInterfacesSchemaTreeItem::child(int row)
+{
+    if (row < 0 || row >= m_childItems.size())
+        return NULL;
+    return m_childItems.at(row);
+}
+
+int QGfaNetInterfacesSchemaTreeItem::childCount() const
+{
+    return m_childItems.count();
+}
+
+int QGfaNetInterfacesSchemaTreeItem::columnCount() const
+{
+    return _countof(g_roles);
+}
+
+QVariant QGfaNetInterfacesSchemaTreeItem::data(int column) const
+{
+    if (column < 0 || column >= m_itemData.size())
+        return QVariant();
+    return m_itemData.at(column);
+}
+
+QGfaNetInterfacesSchemaTreeItem *QGfaNetInterfacesSchemaTreeItem::parentItem()
+{
+    return m_parentItem;
+}
+
+int QGfaNetInterfacesSchemaTreeItem::row() const
+{
+    if (m_parentItem)
+        return m_parentItem->m_childItems.indexOf(const_cast<QGfaNetInterfacesSchemaTreeItem*>(this));
+
+    return 0;
+}
+
+QGfaNetInterfacesSchemaTreeItem* QGfaNetInterfacesSchemaTreeItem::getChildItemByName(const char *pszName)
+{
+	for(QGfaNetInterfacesSchemaTreeItem* pItem : m_childItems)
+	{
+		QVariant name = pItem->data(0);
+
+		if(name.isValid())
+		{
+			if(name == QVariant(pszName))
+				return pItem;
+		}
+	}
+
+	return NULL;
+}
+
+int QGfaNetInterfacesSchemaTreeItem::compareValue(const QVariant &val) const
+{
+	if((m_itemData.size() >= 3) && val.isValid())
+	{
+		if(m_itemData[1].type() == val.type())
+			return !(m_itemData[1] == val);
+	}
+
+	return 1;
+}
+
+bool QGfaNetInterfacesSchemaTreeItem::updateValue(const QVariant &val, const QVariant &valF)
+{
+	bool bUpdated = false;
+
+	if(m_itemData.size() >= 3)
+	{
+		if(val.isValid())
+		{
+			if(m_itemData[1] != val)
+			{
+				m_itemData[1] = val;
+				bUpdated = true;
+			}
+
+			if(valF.isValid())
+			{
+				if(m_itemData[2] != valF)
+				{
+					m_itemData[2] = valF;
+					bUpdated = true;
+				}
+			}
+			else if(m_itemData[2] != val)
+			{
+				m_itemData[2] = val;
+				bUpdated = true;
+			}
+		}
+		else if(m_itemData[1].isValid() || m_itemData[2].isValid())
+		{
+			m_itemData[1] = QVariant();
+			m_itemData[2] = QVariant();
+			bUpdated = true;
+		}
+	}
+
+	return bUpdated;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+QGfaNetInterfacesSchemaModel::QGfaNetInterfacesSchemaModel(QObject *pParent) : QAbstractItemModel(pParent)
+{
+	m_pRootItem = new QGfaNetInterfacesSchemaTreeItem();
+
+	for(size_t i = 0; i < _countof(g_roles); ++i)
+	{
+		m_roleNameMapping[g_roles[i].nRole] = g_roles[i].pszRoleName;
+	}
+}
+
+QGfaNetInterfacesSchemaModel::~QGfaNetInterfacesSchemaModel(void)
+{
+	delete m_pRootItem;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void QGfaNetInterfacesSchemaModel::clearAll(void)
+{
+	beginResetModel();
+	m_pRootItem->clear();
+	endResetModel();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QVariant QGfaNetInterfacesSchemaModel::data(const QModelIndex &index, int role) const
+{
+	if(!index.isValid())
+		return QVariant();
+
+	if((role < SMR_Name) || (role >= SMR_Invalid))
+		return QVariant();
+
+	QGfaNetInterfacesSchemaTreeItem *item = static_cast<QGfaNetInterfacesSchemaTreeItem*>(index.internalPointer());
+	// Do not use index.column as shown in some examples!
+	return item->data(role - SMR_Name);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+Qt::ItemFlags QGfaNetInterfacesSchemaModel::flags(const QModelIndex &index) const
+{
+	if(!index.isValid())
+		return Qt::NoItemFlags;
+	return QAbstractItemModel::flags(index);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QVariant QGfaNetInterfacesSchemaModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+	if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
+		return m_pRootItem->data(section);
+	return QVariant();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QModelIndex QGfaNetInterfacesSchemaModel::index(int row, int column, const QModelIndex &parentIndex) const
+{
+	if(!hasIndex(row, column, parentIndex))
+		return QModelIndex();
+
+	QGfaNetInterfacesSchemaTreeItem *pParentItem;
+
+	if(!parentIndex.isValid())
+		pParentItem = m_pRootItem;
+	else
+		pParentItem = static_cast<QGfaNetInterfacesSchemaTreeItem*>(parentIndex.internalPointer());
+
+	QGfaNetInterfacesSchemaTreeItem *pChildItem = pParentItem->child(row);
+	if(pChildItem)
+		return createIndex(row, column, pChildItem);
+	return QModelIndex();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QModelIndex QGfaNetInterfacesSchemaModel::parent(const QModelIndex &index) const
+{
+	if (!index.isValid())
+		return QModelIndex();
+
+	QGfaNetInterfacesSchemaTreeItem *pChildItem = static_cast<QGfaNetInterfacesSchemaTreeItem*>(index.internalPointer());
+	QGfaNetInterfacesSchemaTreeItem *pParentItem = pChildItem->parentItem();
+
+	if (pParentItem == m_pRootItem)
+		return QModelIndex();
+
+	return createIndex(pParentItem->row(), 0, pParentItem);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int QGfaNetInterfacesSchemaModel::rowCount(const QModelIndex &parentIndex) const
+{
+	QGfaNetInterfacesSchemaTreeItem *pParentItem;
+	if (parentIndex.column() > 0)
+		return 0;
+
+	if (!parentIndex.isValid())
+		pParentItem = m_pRootItem;
+	else
+		pParentItem = static_cast<QGfaNetInterfacesSchemaTreeItem*>(parentIndex.internalPointer());
+
+	return pParentItem->childCount();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int QGfaNetInterfacesSchemaModel::columnCount(const QModelIndex &parentIndex) const
+{
+	if(parentIndex.isValid())
+		return static_cast<QGfaNetInterfacesSchemaTreeItem*>(parentIndex.internalPointer())->columnCount();
+	return m_pRootItem->columnCount();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QHash<int, QByteArray> QGfaNetInterfacesSchemaModel::roleNames() const
+{
+	return m_roleNameMapping;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void QGfaNetInterfacesSchemaModel::setModelData(LPETC_NETWORK_INTERFACES pnif)
+{
+	int i;
+	beginResetModel();
+	m_pRootItem->clear();
+
+	for(auto itfb = pnif->ibl.begin(); itfb != pnif->ibl.end(); ++itfb)
+	{
+		const ITF_IFACE_BLOCK &ifb = *itfb;
+		QGfaNetInterfacesSchemaTreeItem *pNiTi = new QGfaNetInterfacesSchemaTreeItem(ifb.cfgName.c_str(), (quint32)ifb.method, ::GetIfaceMethodStr(ifb.method), m_pRootItem);
+		
+		if(ifb.proto != IFP_Unknown)
+		{
+			const char *pszProto;
+			switch(ifb.proto)
+			{
+			case IFP_Inet:
+				pszProto = "IPv4";
+				break;
+			case IFP_Inet6:
+				pszProto = "IPv6";
+				break;
+			default:
+				pszProto = ::GetIfaceProtoStr(ifb.proto);
+				break;
+			}
+
+			QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Protocol", pszProto, QVariant(), pNiTi);
+			pNiTi->appendChild(pTmpTi);
+		}
+
+		if(!ifb.inherits.empty())
+		{
+			QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Inherits", ifb.inherits.c_str(), QVariant(), pNiTi);
+			pNiTi->appendChild(pTmpTi);
+		}
+
+		if(ifb.method == IFM_Static)
+		{
+			const IFACE_INET_STATIC &inet4s = ifb.inet4s;
+
+			if(inet4s.addr.s_addr != INADDR_ANY)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Address", (quint32)inet4s.addr.s_addr, ::inet_ntoa(inet4s.addr), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(inet4s.netmask.s_addr != INADDR_ANY)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Netmask", (quint32)inet4s.netmask.s_addr, ::inet_ntoa(inet4s.netmask), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(inet4s.gate.s_addr != INADDR_ANY)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Gateway", (quint32)inet4s.gate.s_addr, ::inet_ntoa(inet4s.gate), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(inet4s.bcast.s_addr != INADDR_ANY)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Broadcast", (quint32)inet4s.bcast.s_addr, ::inet_ntoa(inet4s.bcast), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(inet4s.pointopoint.s_addr != INADDR_ANY)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("PointToPoint", (quint32)inet4s.pointopoint.s_addr, ::inet_ntoa(inet4s.pointopoint), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			for(i = 0; i < (int)_countof(inet4s.namesvr); ++i)
+			{
+				if(inet4s.namesvr[i].s_addr)
+				{
+					char szName[32];
+					sprintf(szName, "DNS %d", i + 1);
+					QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem(szName, (quint32)inet4s.namesvr[i].s_addr, ::inet_ntoa(inet4s.namesvr[i]), pNiTi);
+					pNiTi->appendChild(pTmpTi);
+				}
+			}
+
+			if(inet4s.metric != -1)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Metric", (quint32)inet4s.metric, QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(inet4s.mtu != -1)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("MTU", (quint32)inet4s.mtu, QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(!inet4s.hwaddr.empty())
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("HW-Address", inet4s.hwaddr.c_str(), QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(!inet4s.scope.empty())
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("HW-Address", inet4s.scope.c_str(), QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			i = 0;
+			for(auto it = inet4s.dnss.begin(); it != inet4s.dnss.end(); ++it)
+			{
+				const std::string &s = *it;
+				if(!s.empty())
+				{
+					char szName[32];
+					sprintf(szName, "DNSS %d", i + 1);
+					QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem(szName, s.c_str(), QVariant(), pNiTi);
+					pNiTi->appendChild(pTmpTi);
+				}
+			}
+		}
+		else if(ifb.method == IFM_Dhcp)
+		{
+			const IFACE_INET_DHCP &inet4d = ifb.inet4d;
+
+			if(inet4d.leasetime != -1)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Lease time", (qint32)inet4d.leasetime, QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(inet4d.leasehours != -1)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Lease hours", (qint32)inet4d.leasehours, QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(inet4d.metric != -1)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Metric", (quint32)inet4d.metric, QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(!inet4d.hostname.empty())
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Hostname", inet4d.hostname.c_str(), QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(!inet4d.vendor.empty())
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Vendor", inet4d.vendor.c_str(), QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(!inet4d.client.empty())
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("Client", inet4d.client.c_str(), QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(!inet4d.hwaddr.empty())
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("HW-Address", inet4d.hwaddr.c_str(), QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+		}
+		else if(ifb.method == IFM_Manual)
+		{
+			const IFACE_INET_MANUAL &inet4m = ifb.inet4m;
+
+			if(inet4m.mtu != -1)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("MTU", (quint32)inet4m.mtu, QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+
+			if(!inet4m.hwaddr.empty())
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem("HW-Address", inet4m.hwaddr.c_str(), QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+		}
+
+		for(auto it = ifb.cmds.begin(); it != ifb.cmds.end(); ++it)
+		{
+			const IFACE_COMMAND &cmd = *it;
+			if(cmd.cmd != IFC_Unknown)
+			{
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem(::GetIfaceCommandsStr(cmd.cmd), cmd.args.c_str(), QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+		}
+
+		for(auto it = ifb.unparsed.begin(); it != ifb.unparsed.end(); ++it)
+		{
+			const std::string &s = *it;
+			if(!s.empty())
+			{
+				char szName[32];
+				sprintf(szName, "CMD %d", i + 1);
+				QGfaNetInterfacesSchemaTreeItem *pTmpTi = new QGfaNetInterfacesSchemaTreeItem(szName, s.c_str(), QVariant(), pNiTi);
+				pNiTi->appendChild(pTmpTi);
+			}
+		}
+
+		m_pRootItem->appendChild(pNiTi);
+	}
+
+	endResetModel();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+QNetworkInterfaces::QNetworkInterfaces(QObject *pParent) :	QObject(pParent),
+															m_pEniSave(NULL),
+															m_itfFilterAF(QInterface::AF_Unknown),
+															m_itfFilterMethod(QInterface::IM_Unknown),
+															m_bIfUpDownInProgress(false),
+															m_ifUpDownPid(-1)
+{
+	setObjectName("QNetworkInterfaces");
+	m_mutex.Create(true);
+	m_itfFilterName.clear();
+}
+
+QNetworkInterfaces::~QNetworkInterfaces(void)
+{
+	if(m_pEniSave)
+	{
+		delete m_pEniSave;
+		m_pEniSave = NULL;
+	}
+	reset();
+	m_mutex.Release();
+}
+
+void QNetworkInterfaces::classBegin()
+{
+}
+
+void QNetworkInterfaces::componentComplete()
+{
+}
+
+void QNetworkInterfaces::reset(void)
+{
+	QInterface *pItf;
+
+    for(int i = 0; i < m_interfaces.count(); i++)
+    {
+        if((pItf = m_interfaces.at(i)))
+        	delete pItf;
+    }
+    m_interfaces.clear();
+    m_netInterfacesSchemaModel.clearAll();
+	m_eni._reset();
+	emit interfacesChanged();
+	emit filteredInterfacesChanged();
+}
+
+bool QNetworkInterfaces::initialize(void)
+{
+	bool bRet;
+	reset();
+
+    if((bRet = ::ParseEtcNetworkInterfaces(m_eni)))
+	{
+		for(auto it = m_eni.ibl.begin(); it != m_eni.ibl.end(); it++)
+		{
+			ITF_IFACE_BLOCK &ibl = *it;
+			m_interfaces.append(new QInterface(ibl, static_cast<NotificationSink&>(*this), this));
+		}
+
+		m_netInterfacesSchemaModel.setModelData(&m_eni);
+
+		emit interfacesChanged();
+		emit filteredInterfacesChanged();
+	}
+
+	return bRet;
+}
+
+bool QNetworkInterfaces::save(void)
+{
+    m_netInterfacesSchemaModel.clearAll();
+	if(	::WriteEtcNetworkInterfaces(m_eni, NULL) &&
+		initialize())
+	{
+		m_netInterfacesSchemaModel.setModelData(&m_eni);
+		return true;
+	}
+	return false;
+}
+
+bool QNetworkInterfaces::saveAs(const QString &path)
+{
+	if(!path.length())
+		return false;
+	std::string p = path.toStdString();
+	const char *pszPath = p.c_str();
+	if(	::WriteEtcNetworkInterfaces(m_eni, pszPath) &&
+		initialize())
+	{
+		m_netInterfacesSchemaModel.setModelData(&m_eni);
+		return true;
+	}
+	return false;
+}
+
+bool QNetworkInterfaces::reload(void)
+{
+    m_netInterfacesSchemaModel.clearAll();
+	if(initialize())
+	{
+		m_netInterfacesSchemaModel.setModelData(&m_eni);
+	    return true;
+	}
+	return false;
+}
+
+void QNetworkInterfaces::reportError(const char *pszFormatStr, ...)
+{
+	va_list args;
+	va_start(args, pszFormatStr);
+	QString qs = QString::vasprintf(pszFormatStr, args);
+	va_end (args);
+	m_mutex.Lock();
+    emit error(qs);
+	m_mutex.Unlock();
+}
+
+void QNetworkInterfaces::filterPropertyChanged(void) const
+{
+	emit filteredInterfacesChanged();
+}
+
+void QNetworkInterfaces::selConfigChanged(QInterface* pi, unsigned int cfgOld, unsigned int cfgNew)
+{
+	unsigned long id	= pi->getID();
+	unsigned int diff	= cfgOld ^ cfgNew;
+	unsigned int add	= cfgNew & diff;
+	unsigned int rem	= cfgOld & diff;
+
+	for(int mask = QInterface::SC_Auto; mask < QInterface::SC_Invalid; mask <<= 1)
+	{
+		if(add & mask)
+			::AddInterfaceToCfgGroup(m_eni, id, (CfgGroup)_FLAG_TO_ENUM(mask));
+
+		if(rem & mask)
+			::RemoveInterfaceFromCfgGroup(m_eni, id, (CfgGroup)_FLAG_TO_ENUM(mask));
+	}
+}
+
+QInterface* QNetworkInterfaces::newInterface(QString name, int af, int method)
+{
+	if(name.isNull() || name.isEmpty())
+	{
+		reportError("Invalid or empty interface name!");
+		return NULL;
+	}
+
+	if(!_IsPowerOf2(af) || (af <= QInterface::AF_Unknown) || (af >= QInterface::AF_Invalid))
+	{
+		reportError("Invalid address family: %d!", af);
+		return NULL;
+	}
+
+	if(!_IsPowerOf2(method) || (method <= QInterface::IM_Unknown) || (method >= QInterface::IM_Invalid))
+	{
+		reportError("Invalid method: %d!", method);
+		return NULL;
+	}
+
+	m_eni.ibl.emplace_back();
+	ITF_IFACE_BLOCK &rib = m_eni.ibl.back();
+    rib.cfgName = name.toStdString();
+	rib.proto = (IfaceProtos)_FLAG_TO_ENUM(af);
+	rib.method = (IfaceMethods)_FLAG_TO_ENUM(method);
+	QInterface *pi = new QInterface(rib, static_cast<NotificationSink&>(*this), this);
+	m_interfaces.append(pi);
+	emit interfacesChanged();
+	emit filteredInterfacesChanged();
+	return pi;
+}
+
+void QNetworkInterfaces::removeInterface(QInterface *pi)
+{
+	if(!pi)
+	{
+		reportError("QNetworkInterfaces::removeInterface: An attempt was made to remove an invalid interface!");
+		return;
+	}
+
+	m_mutex.Lock();
+	if(GetIfUpDownInProgress())
+	{
+		m_mutex.Unlock();
+		reportError("QNetworkInterfaces::removeInterface: Interface start/stop in progress! Please try again later!");
+		return;
+	}
+	m_mutex.Unlock();
+
+    unsigned long id	= pi->getID();
+    int selCfg			= pi->getSelCfg();
+
+    for(int i = 0; i < m_interfaces.count(); i++)
+	{
+        QInterface *pil = m_interfaces.at(i);
+
+        if(pil->getID() == id)
+        {
+        	m_interfaces.removeAt(i);
+			emit interfacesChanged();
+			emit filteredInterfacesChanged();
+			delete pil;
+
+			for(int mask = QInterface::SC_Auto; mask < QInterface::SC_Invalid; mask <<= 1)
+			{
+				if(selCfg & mask)
+					::RemoveInterfaceFromCfgGroup(m_eni, id, (CfgGroup)_FLAG_TO_ENUM(mask));
+			}
+
+			::RemoveInterfaceBlock(m_eni, id);
+			break;
+        }
+    }
+}
+
+bool QNetworkInterfaces::SetInterlockedIfUpDownInProgress(void)
+{
+	m_mutex.Lock();
+	if(m_bIfUpDownInProgress)
+	{
+		m_mutex.Unlock();
+		return false;
+	}
+	m_bIfUpDownInProgress = true;
+	m_mutex.Unlock();
+	return true;
+}
+
+void QNetworkInterfaces::onIfUpDown(const char *pszMsg, void *pCtx)
+{
+	if(pCtx)
+	{
+		QNetworkInterfaces *pThis = static_cast<QNetworkInterfaces*>(pCtx);
+		pThis->m_mutex.Lock();
+		emit pThis->ifUpDown(pszMsg);
+		pThis->m_mutex.Unlock();
+	}
+}
+
+void QNetworkInterfaces::onIfUpCompleted(int nExitCode, void *pCtx)
+{
+	if(pCtx)
+	{
+		LPIF_UPDOWN_CONTEXT piudc = static_cast<LPIF_UPDOWN_CONTEXT>(pCtx);
+		piudc->pThis->m_mutex.Lock();
+		emit piudc->pThis->ifUpDownCompleted(piudc->ctx, nExitCode);
+		piudc->pThis->SetIfUpDownInProgress(false);
+		piudc->pThis->SetIfUpDownPid(-1);
+		piudc->pThis->m_mutex.Unlock();
+		delete piudc;
+	}
+}
+
+void QNetworkInterfaces::onIfDownCompleted(int nExitCode, void *pCtx)
+{
+	if(pCtx)
+	{
+		LPIF_UPDOWN_CONTEXT piudc = static_cast<LPIF_UPDOWN_CONTEXT>(pCtx);
+		piudc->pThis->m_mutex.Lock();
+		emit piudc->pThis->ifUpDownCompleted(piudc->ctx, nExitCode);
+		piudc->pThis->SetIfUpDownInProgress(false);
+		piudc->pThis->SetIfUpDownPid(-1);
+		piudc->pThis->m_mutex.Unlock();
+		delete piudc;
+	}
+}
+
+void QNetworkInterfaces::onIfRestartCompleted(int nExitCode, void *pCtx)
+{
+	if(pCtx)
+	{
+		LPIF_UPDOWN_CONTEXT piudc = static_cast<LPIF_UPDOWN_CONTEXT>(pCtx);
+
+		if(piudc->ctx == UDC_Stop && !nExitCode) // ifdown succeeded
+		{
+			int nRet;
+			piudc->ctx = UDC_Start;
+
+			if((nRet = ::IfUpAsync(piudc->pi->getName(), piudc->pThis->m_ifUpDownPid, &QNetworkInterfaces::onIfRestartCompleted, static_cast<void*>(piudc), &QNetworkInterfaces::onIfUpDown, static_cast<void*>(piudc->pThis))))
+			{
+				piudc->pThis->m_mutex.Lock();
+				piudc->pThis->reportError("QNetworkInterfaces::onIfRestartCompleted: IfUpAsync failed with code: %d", nRet);
+				emit piudc->pThis->ifUpDownCompleted(UDC_Restart, nRet);
+				piudc->pThis->SetIfUpDownPid(-1);
+				piudc->pThis->SetIfUpDownInProgress(false);
+				piudc->pThis->m_mutex.Unlock();
+				delete piudc;
+			}
+
+			return;
+		}
+
+		piudc->pThis->m_mutex.Lock();
+		emit piudc->pThis->ifUpDownCompleted(UDC_Restart, nExitCode);
+		piudc->pThis->SetIfUpDownPid(-1);
+		piudc->pThis->SetIfUpDownInProgress(false);
+		piudc->pThis->m_mutex.Unlock();
+		delete piudc;
+	}
+}
+
+bool QNetworkInterfaces::startInterface(QInterface *pi)
+{
+	if(!pi)
+	{
+		reportError("QNetworkInterfaces::stopInterface: Invalid interface!");
+		return false;
+	}
+
+	int nRet;
+
+	if(!SetInterlockedIfUpDownInProgress())
+	{
+		reportError("QNetworkInterfaces::startInterface: IfUp/Down already in progress!");
+		return false;
+	}
+
+	LPIF_UPDOWN_CONTEXT piudc = new IF_UPDOWN_CONTEXT;
+	piudc->pThis		= this;
+	piudc->pi			= pi;
+	piudc->ctx			= UDC_Start;
+
+	if((nRet = ::IfUpAsync(pi->getName(), m_ifUpDownPid, &QNetworkInterfaces::onIfUpCompleted, static_cast<void*>(piudc), &QNetworkInterfaces::onIfUpDown, static_cast<void*>(this))))
+	{
+		m_mutex.Lock();
+		reportError("QNetworkInterfaces::startInterface: IfUpAsync failed with code: %d", nRet);
+		emit ifUpDownCompleted(UDC_Start, -3);
+		SetIfUpDownInProgress(false);
+		SetIfUpDownPid(-1);
+		m_mutex.Unlock();
+		delete piudc;
+		return false;
+	}
+
+	return true;
+}
+
+bool QNetworkInterfaces::stopInterface(QInterface *pi)
+{
+	if(!pi)
+	{
+		reportError("QNetworkInterfaces::stopInterface: Invalid interface!");
+		return false;
+	}
+
+	int nRet;
+
+	if(!SetInterlockedIfUpDownInProgress())
+	{
+		reportError("QNetworkInterfaces::stopInterface: IfUp/Down already in progress!");
+		return false;
+	}
+
+	LPIF_UPDOWN_CONTEXT piudc = new IF_UPDOWN_CONTEXT;
+	piudc->pThis		= this;
+	piudc->pi			= pi;
+	piudc->ctx			= UDC_Stop;
+
+	if((nRet = ::IfDownAsync(pi->getName(), m_ifUpDownPid, &QNetworkInterfaces::onIfDownCompleted, static_cast<void*>(piudc), &QNetworkInterfaces::onIfUpDown, static_cast<void*>(this))))
+	{
+		m_mutex.Lock();
+		reportError("QNetworkInterfaces::stopInterface: IfDownAsync failed with code: %d", nRet);
+		emit ifUpDownCompleted(UDC_Stop, -3);
+		SetIfUpDownInProgress(false);
+		SetIfUpDownPid(-1);
+		m_mutex.Unlock();
+		delete piudc;
+		return false;
+	}
+
+	return true;
+}
+
+bool QNetworkInterfaces::restartInterface(QInterface *pi)
+{
+	if(!pi)
+	{
+		reportError("QNetworkInterfaces::restartInterface: Invalid interface!");
+		return false;
+	}
+
+	int nRet;
+
+	if(!SetInterlockedIfUpDownInProgress())
+	{
+		reportError("QNetworkInterfaces::restartInterface: IfUp/Down already in progress!");
+		return false;
+	}
+
+	LPIF_UPDOWN_CONTEXT piudc = new IF_UPDOWN_CONTEXT;
+	piudc->pThis		= this;
+	piudc->pi			= pi;
+	piudc->ctx			= UDC_Stop;
+
+	if((nRet = ::IfDownAsync(pi->getName(), m_ifUpDownPid, &QNetworkInterfaces::onIfRestartCompleted, static_cast<void*>(piudc), &QNetworkInterfaces::onIfUpDown, static_cast<void*>(this))))
+	{
+		m_mutex.Lock();
+		reportError("QNetworkInterfaces::restartInterface: IfDownAsync failed with code: %d", nRet);
+		emit ifUpDownCompleted(UDC_Restart, -3);
+		SetIfUpDownInProgress(false);
+		SetIfUpDownPid(-1);
+		m_mutex.Unlock();
+		delete piudc;
+		return false;
+	}
+
+	return true;
+}
+
+bool QNetworkInterfaces::cancelStartStopInterface(void)
+{
+	m_mutex.Lock();
+	pid_t pid = GetIfUpDownPid();
+	bool bCancel = GetIfUpDownInProgress() && (pid != -1);
+	if(bCancel)
+	{
+//		bCancel = !kill(-pid, SIGKILL);
+		bCancel = !system("killall -SIGTERM ifup");
+	}
+	m_mutex.Unlock();
+	return bCancel;
+}
+
+QQmlListProperty<QInterface> QNetworkInterfaces::interfaces(void)
+{
+	return QQmlListProperty<QInterface>(this, m_interfaces);
+}
+
+QQmlListProperty<QInterface> QNetworkInterfaces::filteredInterfaces(void)
+{
+	m_filteredInterfaces.clear();
+
+    for(int i = 0; i < m_interfaces.count(); i++)
+	{
+        QInterface *pi = m_interfaces.at(i);
+		const ITF_IFACE_BLOCK &ibl = pi->getIface();
+
+		if(	(m_itfFilterName.isNull() || m_itfFilterName.isEmpty() || (m_itfFilterName == ibl.cfgName.c_str())) &&
+			(_ENUM_TO_FLAG(ibl.proto) & m_itfFilterAF) &&
+			(_ENUM_TO_FLAG(ibl.method) & m_itfFilterMethod))
+		{
+			m_filteredInterfaces.append(pi);
+		}
+	}
+
+	return QQmlListProperty<QInterface>(this, m_filteredInterfaces);
+}
+
+const QString& QNetworkInterfaces::itfFilterName(void) const
+{
+	return m_itfFilterName;
+}
+
+void QNetworkInterfaces::setItfFilterName(const QString &val)
+{
+	if(val != m_itfFilterName)
+	{
+		m_itfFilterName = val;
+		emit itfFilterNameChanged(m_itfFilterName);
+		emit filteredInterfacesChanged();
+	}
+
+}
+
+int QNetworkInterfaces::itfFilterAF(void) const
+{
+	return m_itfFilterAF;
+}
+
+void QNetworkInterfaces::setItfFilterAF(int af)
+{
+
+
+	if(af < QInterface::AF_Unknown || af >= QInterface::AF_Invalid)
+	{
+		reportError("Invalid address family filter: %d!", af);
+		return;
+	}
+
+	if(m_itfFilterAF != af)
+	{
+		m_itfFilterAF = af;
+		emit itfFilterAFChanged(af);
+		emit filteredInterfacesChanged();
+	}
+}
+
+int QNetworkInterfaces::itfFilterMethod(void) const
+{
+	return m_itfFilterMethod;
+}
+
+void QNetworkInterfaces::setItfFilterMethod(int method)
+{
+	if(method < QInterface::IM_Unknown || method >= QInterface::IM_Invalid)
+	{
+		reportError("Invalid method filter: %d!", method);
+		return;
+	}
+
+	if(m_itfFilterMethod != method)
+	{
+		m_itfFilterMethod = method;
+		emit itfFilterMethodChanged(method);
+		emit filteredInterfacesChanged();
+	}
+}
+
+int QNetworkInterfaces::getInterfaceSelConfig(QInterface &ri)
+{
+	int mask = 0;
+
+	::EnumInterfaceCfgGroups(m_eni, ri.getID(),
+		[] (CfgGroup cg, void *pCtx) -> void
+		{
+			if(cg > CG_Unknown)
+			{
+				int *m = (int*)pCtx;
+				*m |= _ENUM_TO_FLAG(cg);
+			}
+		}, &mask);
+
+	return mask;
+}
+
+bool QNetworkInterfaces::ifUpDownInProgress(void) const
+{
+	return m_bIfUpDownInProgress;
+}
+
+QGfaNetInterfacesSchemaModel* QNetworkInterfaces::schemaModel(void)
+{
+	return &m_netInterfacesSchemaModel;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QInterface::QInterface(ITF_IFACE_BLOCK &ifb, NotificationSink &notifyer, QObject *pParent) : 	QObject(pParent),
+																								m_ifb(ifb),
+																								m_inet(ifb, notifyer, this),
+																								m_rNotifyer(notifyer),
+																								m_selCfg(notifyer.getInterfaceSelConfig(*this))
+{
+	setObjectName("QInterface");
+}
+
+QInterface::~QInterface(void)
+{
+}
+
+QString QInterface::name(void) const
+{
+	return QString::fromStdString(m_ifb.cfgName);
+}
+
+QString QInterface::afName(void) const
+{
+	return ::GetIfaceProtoStr(m_ifb.proto);
+}
+
+int QInterface::af(void) const
+{
+	return (int)_ENUM_TO_FLAG(m_ifb.proto);
+}
+
+void QInterface::setAf(int af)
+{
+	if(!_IsPowerOf2(af) || (af < QInterface::AF_Unknown) || (af >= QInterface::AF_Invalid))
+	{
+		m_rNotifyer.reportError("Invalid address family: %d!", af);
+		return;
+	}
+
+	IfaceProtos proto = (IfaceProtos)_FLAG_TO_ENUM(af);
+
+	if(m_ifb.proto != proto)
+	{
+		m_ifb.proto = proto;
+		emit afChanged(af);
+		emit afNameChanged();
+		m_rNotifyer.filterPropertyChanged();
+	}
+}
+
+QString QInterface::methodName(void) const
+{
+	return ::GetIfaceMethodStr(m_ifb.method);
+}
+
+int QInterface::method(void) const
+{
+	return (int)_ENUM_TO_FLAG(m_ifb.method);
+}
+
+void QInterface::setMethod(int method)
+{
+	if(!_IsPowerOf2(method) || (method < QInterface::IM_Unknown) || (method >= QInterface::IM_Invalid))
+	{
+		m_rNotifyer.reportError("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();
+	}
+}
+
+int QInterface::selCfg(void) const
+{
+	return m_selCfg;
+}
+
+void QInterface::setSelCfg(int cfg)
+{
+	if(cfg < SC_None || cfg >= SC_Invalid)
+	{
+		m_rNotifyer.reportError("Invalid start/selection configuration: 0x%X!", cfg);
+		return;
+	}
+
+	if(m_selCfg != cfg)
+	{
+		m_rNotifyer.selConfigChanged(this, m_selCfg, cfg);
+		m_selCfg = cfg;
+		emit selCfgChanged(cfg);
+	}
+
+}
+
+QInet* QInterface::inet(void)
+{
+	return &m_inet;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QInet::QInet(ITF_IFACE_BLOCK &ifb, NotificationSink &notifyer, QObject *pParent) :	QObject(pParent),
+																					m_static(ifb.inet4s, notifyer, this),
+																					m_dhcp(ifb.inet4d, notifyer, this),
+																					m_rNotifyer(notifyer)
+{
+	setObjectName("QInet");
+}
+
+QInet::~QInet(void)
+{
+}
+
+QStatic* QInet::stat(void)
+{
+	return &m_static;
+}
+
+QDhcp* QInet::dhcp(void)
+{
+	return &m_dhcp;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QStatic::QStatic(IFACE_INET_STATIC &itfs, 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("QStatic");
+	for(size_t i = 0; i < _countof(m_itfs.namesvr); i++)
+	{
+		QIPv4Address *addr = new QIPv4Address(m_itfs.namesvr[i], notifyer, this);
+		m_dnsList.append(addr);
+	}
+
+	QObject::connect(&m_netmask, SIGNAL(addressChanged(const QString&)), this, SLOT(netmaskChanged(const QString&)));
+}
+
+QStatic::~QStatic(void)
+{
+	QIPv4Address *addr;
+
+    for(int i = 0; i < m_dnsList.count(); i++)
+    {
+        if((addr = m_dnsList.at(i)))
+        	delete addr;
+    }
+}
+
+QIPv4Address* QStatic::ipAddress(void)
+{
+	return &m_ipAddr;
+}
+
+QIPv4Address* QStatic::netMask(void)
+{
+	return &m_netmask;
+}
+
+QIPv4Address* QStatic::gateway(void)
+{
+	return &m_gateway;
+}
+
+QIPv4Address* QStatic::bcastAddress(void)
+{
+	return &m_bcastAddr;
+}
+
+QIPv4Address* QStatic::ptpAddress(void)
+{
+	return &m_ptpAddr;
+}
+
+QQmlListProperty<QIPv4Address> QStatic::dnsServer(void)
+{
+	return QQmlListProperty<QIPv4Address>(this, m_dnsList);
+}
+
+int QStatic::metric(void) const
+{
+	return m_itfs.metric;
+}
+
+void QStatic::setMetric(int metric)
+{
+	if(m_itfs.metric != metric)
+	{
+		m_itfs.metric = metric;
+		emit metricChanged(metric);
+	}
+}
+
+int QStatic::mtu(void) const
+{
+	return m_itfs.mtu;
+}
+
+void QStatic::setMtu(int mtu)
+{
+	if(m_itfs.mtu != mtu)
+	{
+		m_itfs.mtu = mtu;
+		emit mtuChanged(mtu);
+	}
+}
+
+int QStatic::netPrefix(void) const
+{
+	return m_itfs.netprefix;
+}
+
+void QStatic::setNetPrefix(int netprefix)
+{
+	if(netprefix < 0 || netprefix > 32)
+	{
+		m_rNotifyer.reportError("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 QStatic::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.reportError("Invalid net mask: %s!", sa.c_str());
+        m_netmask.setProperty("address", QVariant("255.255.255.0"));
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QDhcp::QDhcp(IFACE_INET_DHCP &itfd, NotificationSink &notifyer, QObject *pParent) : QObject(pParent), m_itfd(itfd), m_rNotifyer(notifyer)
+{
+	setObjectName("QDhcp");
+}
+
+QDhcp::~QDhcp(void)
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QIPv4Address::QIPv4Address(struct in_addr &addr, NotificationSink &notifyer, QObject *pParent, PFN_ADDRESS_VALIDATOR pfnAddrValidator) :	QObject(pParent),
+																																			m_addr(addr),
+																																			m_pfnAddrValidator(pfnAddrValidator),
+																																			m_rNotifyer(notifyer)
+{
+	setObjectName("QIPv4Address");
+}
+
+QIPv4Address::~QIPv4Address(void)
+{
+}
+
+QString QIPv4Address::address(void) const
+{
+	return inet_ntoa(m_addr);
+}
+
+int QIPv4Address::b0(void) const
+{
+	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
+	return (int)pb[0];
+}
+
+int QIPv4Address::b1(void) const
+{
+	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
+	return (int)pb[1];
+}
+
+int QIPv4Address::b2(void) const
+{
+	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
+	return (int)pb[2];
+}
+
+int QIPv4Address::b3(void) const
+{
+	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
+	return (int)pb[3];
+}
+
+double QIPv4Address::addr(void) const
+{
+	return ntohl(m_addr.s_addr);
+}
+
+void QIPv4Address::setAddress(const QString &addr)
+{
+	struct in_addr newAddr, oldAddr;
+	std::string sa = addr.toStdString();
+
+	if(!inet_aton(sa.c_str(), &newAddr))
+	{
+		m_rNotifyer.reportError("Invalid IP address: '%s'!", sa.c_str());
+		return;
+	}
+
+	if(m_pfnAddrValidator && !(*m_pfnAddrValidator)(newAddr))
+	{
+		m_rNotifyer.reportError("Invalid address: '%s'!", sa.c_str());
+		return;
+	}
+
+	if(m_addr.s_addr != newAddr.s_addr)
+	{
+		oldAddr.s_addr = m_addr.s_addr;
+		m_addr.s_addr  = newAddr.s_addr;
+
+		unsigned char *pb1 = (unsigned char*)&oldAddr.s_addr;
+		unsigned char *pb2 = (unsigned char*)&newAddr.s_addr;
+		if(pb1[0] != pb2[0])
+			emit b0Changed(pb2[0]);
+		if(pb1[1] != pb2[1])
+			emit b1Changed(pb2[1]);
+		if(pb1[2] != pb2[2])
+			emit b2Changed(pb2[2]);
+		if(pb1[3] != pb2[3])
+			emit b3Changed(pb2[3]);
+		emit addressChanged(address());
+		emit addrChanged(m_addr.s_addr);
+	}
+}
+
+void QIPv4Address::setB0(int b)
+{
+	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
+	if(!_IS_VALID_BYTE_VALUE(b))
+	{
+		m_rNotifyer.reportError("Invalid IP address byte 0: '%d'!", b);
+		return;
+	}
+	if(b == (int)pb[0])
+		return;
+	pb[0] = (unsigned char)b;
+	emit b0Changed(b);
+	emit addressChanged(address());
+	emit addrChanged(m_addr.s_addr);
+}
+
+void QIPv4Address::setB1(int b)
+{
+	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
+	if(!_IS_VALID_BYTE_VALUE(b))
+	{
+		m_rNotifyer.reportError("Invalid IP address byte 1: '%d'!", b);
+		return;
+	}
+	if(b == (int)pb[1])
+		return;
+	pb[1] = (unsigned char)b;
+	emit b1Changed(b);
+	emit addressChanged(address());
+	emit addrChanged(m_addr.s_addr);
+}
+
+void QIPv4Address::setB2(int b)
+{
+	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
+	if(!_IS_VALID_BYTE_VALUE(b))
+	{
+		m_rNotifyer.reportError("Invalid IP address byte 2: '%d'!", b);
+		return;
+	}
+	if(b == (int)pb[2])
+		return;
+	pb[2] = (unsigned char)b;
+	emit b2Changed(b);
+	emit addressChanged(address());
+	emit addrChanged(m_addr.s_addr);
+}
+
+void QIPv4Address::setB3(int b)
+{
+	unsigned char *pb = (unsigned char*)&m_addr.s_addr;
+	if(!_IS_VALID_BYTE_VALUE(b))
+	{
+		m_rNotifyer.reportError("Invalid IP address byte 3: '%d'!", b);
+		return;
+	}
+	if(b == (int)pb[3])
+		return;
+	pb[3] = (unsigned char)b;
+	emit b3Changed(b);
+	emit addressChanged(address());
+	emit addrChanged(m_addr.s_addr);
+}
+
+void QIPv4Address::setAddr(double val)
+{
+	unsigned int addr = htonl((unsigned int)(int)val);
+	if(val > 0xFFFFFFFF)
+	{
+		m_rNotifyer.reportError("Invalid IP address: '%.f'!", val);
+		return;
+	}
+
+	if(m_addr.s_addr != addr)
+	{
+		struct in_addr oldAddr;
+		oldAddr.s_addr = m_addr.s_addr;
+		m_addr.s_addr = addr;
+		unsigned char *pb1 = (unsigned char*)&oldAddr.s_addr;
+		unsigned char *pb2 = (unsigned char*)&addr;
+		if(pb1[0] != pb2[0])
+			emit b0Changed(pb2[0]);
+		if(pb1[1] != pb2[1])
+			emit b1Changed(pb2[1]);
+		if(pb1[2] != pb2[2])
+			emit b2Changed(pb2[2]);
+		if(pb1[3] != pb2[3])
+			emit b3Changed(pb2[3]);
+		emit addressChanged(address());
+		emit addrChanged(m_addr.s_addr);
+	}
+}

+ 357 - 0
src/qnetworkinfo.h

@@ -0,0 +1,357 @@
+// qnetworkinfo.h :
+//
+
+#if !defined(AGD_QNETWORKINFO_H__B4EDEFD4_1301_4926_83C7_289080AC5492__INCLUDED_)
+#define AGD_QNETWORKINFO_H__B4EDEFD4_1301_4926_83C7_289080AC5492__INCLUDED_
+
+#include <vector>
+#include <QObject>
+#include <QList>
+#include <QQmlListProperty>
+#include <qqmlparserstatus.h>
+#include <gfa/mutex.h>
+#include <gfa/gfanet.h>
+
+/////////////////////////////////////////////////////////////////////////////
+// netinterfaces.h - Declarations:
+
+class Interface;
+
+class NotificationSink
+{
+public:
+	virtual void reportError(const char *pszFormatStr, ...)									= 0;
+	virtual void filterPropertyChanged(void) const											= 0;
+	virtual void selConfigChanged(Interface* pi, unsigned int cfgOld, unsigned int cfgNew)	= 0;
+	virtual int getInterfaceSelConfig(Interface &ri)										= 0;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef bool (*PFN_ADDRESS_VALIDATOR)(const struct in_addr &addr);
+
+class IPv4Address : public QObject
+{
+    Q_OBJECT
+    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, NotificationSink &notifyer, QObject *pParent = 0, PFN_ADDRESS_VALIDATOR pfnAddrValidator = NULL);
+    virtual ~IPv4Address(void);
+
+private:
+    QString address(void) const;
+    int b0(void) const;
+    int b1(void) const;
+    int b2(void) const;
+    int b3(void) const;
+    
+    void setAddress(const QString &addr);
+    void setB0(int b);
+    void setB1(int b);
+    void setB2(int b);
+    void setB3(int b);
+
+signals:
+	void addressChanged(const QString&);
+	void b0Changed(int);
+	void b1Changed(int);
+	void b2Changed(int);
+	void b3Changed(int);
+
+private:
+	struct in_addr &m_addr;
+	PFN_ADDRESS_VALIDATOR m_pfnAddrValidator;
+	NotificationSink &m_rNotifyer;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class Static : public QObject
+{
+    Q_OBJECT
+    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)
+    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, 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;
+	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, NotificationSink &notifyer, QObject *pParent = 0);
+    virtual ~Dhcp(void);
+
+private:
+	IFACE_INET_DHCP &m_itfd;
+	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 Inet(ITF_IFACE_BLOCK &ifb, NotificationSink &notifyer, QObject *pParent = 0);
+    virtual ~Inet(void);
+
+private:
+    Static* stat(void);
+    Dhcp* dhcp(void);
+
+private:
+    Static m_static;
+    Dhcp m_dhcp;
+	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(int selCfg READ selCfg WRITE setSelCfg NOTIFY selCfgChanged)
+    Q_PROPERTY(Inet* inet READ inet CONSTANT)
+
+public:
+    explicit Interface(ITF_IFACE_BLOCK &ifb, NotificationSink &notifyer, QObject *pParent = 0);
+    virtual ~Interface(void);
+
+    inline const ITF_IFACE_BLOCK & getIface(void) const {
+    	return m_ifb;}
+
+    inline ITF_IFACE_BLOCK & getIface(void){
+    	return m_ifb;}
+    
+    inline unsigned long getID(void) const {
+    	return m_ifb.id;}
+    
+    inline int getSelCfg(void) const {
+	    return m_selCfg;}
+    
+    inline const char * getName(void) const {
+	    return m_ifb.cfgName.c_str();}
+
+	enum AddressFamily
+	{
+		AF_Unknown	= 0,
+		AF_Inet		= 0x0001,
+		AF_Inet6	= 0x0002,
+		AF_Ipx		= 0x0004,
+		AF_Can		= 0x0008,
+		AF_Invalid	= 0x0010
+	};
+	Q_ENUMS(AddressFamily)
+
+	enum ItfMethod
+	{
+		IM_Unknown	= 0,
+		IM_Static	= 0x0001,
+		IM_Dhcp		= 0x0002,
+		IM_Manual	= 0x0004,
+		IM_BootP	= 0x0008,
+		IM_Tunnel	= 0x0010,
+		IM_Ppp		= 0x0020,
+		IM_WvDial	= 0x0040,
+		IM_IpV4ll	= 0x0080,
+		IM_Loopback	= 0x0100,
+		IM_Auto		= 0x0200,
+		IM_Invalid	= 0x0400
+	};
+	Q_ENUMS(ItfMethod)
+
+	enum SelConfig
+	{
+		SC_None			= 0,
+		SC_Auto			= 0x0001,
+		SC_AllowAuto	= 0x0002,
+		SC_AllowHotplug	= 0x0004,
+		SC_NoAutoDown	= 0x0008,
+		SC_NoScripts	= 0x0010,
+		SC_Invalid		= 0x0020
+	};
+	Q_ENUMS(SelConfig)
+
+private:
+    QString name(void) const;
+    QString afName(void) const;
+    int af(void) const;
+    void setAf(int af);
+    QString methodName(void) const;
+    int method(void) const;
+    void setMethod(int method);
+    int selCfg(void) const;
+    void setSelCfg(int cfg);
+    Inet* inet(void);
+
+signals:
+	void afNameChanged(void);
+	void afChanged(int af);
+	void methodNameChanged(void);
+	void methodChanged(int method);
+	void selCfgChanged(int cfg);
+
+private:
+	ITF_IFACE_BLOCK &m_ifb;
+	Inet m_inet;
+	NotificationSink &m_rNotifyer;
+	int m_selCfg;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+class NetInterfaces : public QObject, public QQmlParserStatus, public NotificationSink
+{
+    Q_OBJECT
+    Q_INTERFACES(QQmlParserStatus)
+    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)
+    Q_PROPERTY(bool ifUpDownInProgress READ ifUpDownInProgress CONSTANT)
+
+public:
+    explicit NetInterfaces(QObject *pParent = 0);
+    virtual ~NetInterfaces(void);
+
+	enum IfUpDownCtx
+	{
+		UDC_Start,
+		UDC_Stop,
+		UDC_Restart
+	};
+	Q_ENUMS(IfUpDownCtx)
+
+public:
+	Q_INVOKABLE void reset(void);
+	Q_INVOKABLE bool initialize(void);
+	Q_INVOKABLE bool save(void);
+	Q_INVOKABLE bool saveAs(const QString &path);
+	Q_INVOKABLE Interface* newInterface(QString name, int af, int method);
+	Q_INVOKABLE void removeInterface(Interface *pi);
+	Q_INVOKABLE bool startInterface(Interface *pi);
+	Q_INVOKABLE bool stopInterface(Interface *pi);
+	Q_INVOKABLE bool restartInterface(Interface *pi);
+	Q_INVOKABLE bool cancelStartStopInterface(void);
+
+	virtual void classBegin();
+	virtual void componentComplete();
+	virtual void reportError(const char *pszFormatStr, ...);
+	virtual void filterPropertyChanged(void) const;
+	virtual void selConfigChanged(Interface* pi, unsigned int cfgOld, unsigned int cfgNew);
+	virtual int getInterfaceSelConfig(Interface &ri);
+	
+	inline pid_t GetIfUpDownPid(void) const {
+		return m_ifUpDownPid;}
+	
+	inline void SetIfUpDownPid(pid_t pid){
+		m_ifUpDownPid = pid;}
+	    
+	inline bool GetIfUpDownInProgress(void) const {
+		return m_bIfUpDownInProgress;}
+	    
+	inline void SetIfUpDownInProgress(bool bVal){
+		m_bIfUpDownInProgress = bVal;}
+	
+	bool SetInterlockedIfUpDownInProgress(void);
+
+signals:
+	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;
+	void ifUpDown(QString msg) const;
+	void ifUpDownCompleted(int ctx, int code) const;
+
+private:
+	QQmlListProperty<Interface> interfaces(void);
+	QQmlListProperty<Interface> filteredInterfaces(void);
+	const QString& itfFilterName(void) const;
+	void setItfFilterName(const QString &val);
+	int itfFilterAF(void) const;
+	void setItfFilterAF(int nval);
+	int itfFilterMethod(void) const;
+	void setItfFilterMethod(int method);
+	bool ifUpDownInProgress(void) const;
+
+    static void onIfUpDown(const char *pszMsg, void *pCtx);
+    static void onIfUpCompleted(int nExitCode, void *pCtx);
+    static void onIfDownCompleted(int nExitCode, void *pCtx);
+    static void onIfRestartCompleted(int nExitCode, void *pCtx);
+
+private:
+	ETC_NETWORK_INTERFACES m_eni;
+	QList<Interface*> m_interfaces;
+	QList<Interface*> m_filteredInterfaces;
+	QString m_itfFilterName;
+	int m_itfFilterAF;
+	int m_itfFilterMethod;
+	bool m_bIfUpDownInProgress;
+	pid_t m_ifUpDownPid;
+	CLocalMutex m_mutex;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+#endif	//	!defined(AGD_QNETWORKINFO_H__B4EDEFD4_1301_4926_83C7_289080AC5492__INCLUDED_)

+ 6 - 0
src/qsysinfo.cpp

@@ -486,6 +486,7 @@ QGfaSysInfo::QGfaSysInfo(QObject *pParent) : 	QObject(pParent),
 												m_nMemCached(0),
 												m_bootFromEmmc(false)
 {
+	m_netInterfaces.initialize();
 }
 
 QGfaSysInfo::~QGfaSysInfo(void)
@@ -636,6 +637,11 @@ QTivaInfo* QGfaSysInfo::tivaInfo(void)
 	return &m_tivaInfo;
 }
 
+QNetworkInterfaces* QGfaSysInfo::netInterfaceInfo(void)
+{
+	return &m_netInterfaces;
+}
+
 bool QGfaSysInfo::bootFromEmmc(void) const
 {
 	return m_bootFromEmmc;