From e4491ccd515030d7a9bb85cfb891d75a0cce0b53 Mon Sep 17 00:00:00 2001 From: Vadim Kurland Date: Sun, 14 Aug 2011 19:41:14 -0700 Subject: [PATCH] function InetAddr::isValidV4Netmask() checks that netmask represented by the object consists of a sequence of "1" bits, followed by the sequence of "0" bits and therefore does not have zeroes in the middle. added check to the Network object dialog to make sure user does not enter netmask with zeroes in the middle for the IPv4 network object. Netmasks like that are not supported by fwbuilder. see #2644 --- doc/ChangeLog | 11 +++++++ src/libfwbuilder/src/fwbuilder/InetAddr.cpp | 21 +++++++++++++ src/libfwbuilder/src/fwbuilder/InetAddr.h | 2 ++ src/libgui/NetworkDialog.cpp | 18 +++++++++++ .../InetAddrMaskTest/InetAddrMaskTest.cpp | 31 ++++++++++++++++++- 5 files changed, 82 insertions(+), 1 deletion(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 9d7004052..92bf6070e 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,16 @@ 2011-08-14 Vadim Kurland + * InetAddr.cpp (InetAddr::isValidV4Netmask): function + InetAddr::isValidV4Netmask() checks that netmask represented by + the object consists of a sequence of "1" bits, followed by the + sequence of "0" bits and therefore does not have zeroes in the + middle. + + * NetworkDialog.cpp (NetworkDialog::validate): added check to make + sure user does not enter netmask with zeroes in the middle for the + IPv4 network object. Netmasks like that are not supported by + fwbuilder. + * RuleSetView.cpp (RuleSetView::addColumnRelatedMenu): fixes #2643 "GUI crashes when user cuts a rule, then right-mouse click in any rule element of another" diff --git a/src/libfwbuilder/src/fwbuilder/InetAddr.cpp b/src/libfwbuilder/src/fwbuilder/InetAddr.cpp index c4e33a641..df71282de 100644 --- a/src/libfwbuilder/src/fwbuilder/InetAddr.cpp +++ b/src/libfwbuilder/src/fwbuilder/InetAddr.cpp @@ -155,6 +155,27 @@ void InetAddr::init_from_int(unsigned int len) } } +/* + * Netmask with "holes" is accepted by InetAddr, but we do not support + * it at this time. This function returns true if InetAddr object + * corresponds to an integer with a string of consequitive "1" bits + * and then string of consequtive "0" bits. The function only works + * for ipv4 addresses. + */ +bool InetAddr::isValidV4Netmask() +{ + assert(isV4()); + + unsigned int n = ntohl(ipv4.s_addr); + + while (n & 0x80000000) + { + n = n<<1; + } + + return (n == 0); +} + // uint128 is always in the host order void InetAddr::init_from_uint128(uint128 la) { diff --git a/src/libfwbuilder/src/fwbuilder/InetAddr.h b/src/libfwbuilder/src/fwbuilder/InetAddr.h index bab44621e..8260b7a59 100644 --- a/src/libfwbuilder/src/fwbuilder/InetAddr.h +++ b/src/libfwbuilder/src/fwbuilder/InetAddr.h @@ -110,6 +110,8 @@ class InetAddr return sizeof(ipv6) * 8; } + bool isValidV4Netmask(); + void init_from_uint128(uint128 int128a); uint128 to_uint128() const; diff --git a/src/libgui/NetworkDialog.cpp b/src/libgui/NetworkDialog.cpp index 9682a7c87..3596c43d9 100644 --- a/src/libgui/NetworkDialog.cpp +++ b/src/libgui/NetworkDialog.cpp @@ -178,6 +178,7 @@ void NetworkDialog::validate(bool *result) } InetAddr nm( m_dialog->netmask->text().toStdString() ); + if (nm.isAny()) { // permit netmask 0.0.0.0 if the address is also 0.0.0.0 @@ -200,6 +201,23 @@ void NetworkDialog::validate(bool *result) } } + if (!nm.isValidV4Netmask()) + { + *result = false; + if (QApplication::focusWidget() != NULL) + { + blockSignals(true); + // Do not allow netmask with zeroes inside. + QMessageBox::critical( + this, "Firewall Builder", + tr("Netmasks with zeroes in the middle are not supported"), + tr("&Continue"), 0, 0, + 0 ); + blockSignals(false); + } + return; + } + } catch (FWException &ex) { diff --git a/src/unit_tests/InetAddrMaskTest/InetAddrMaskTest.cpp b/src/unit_tests/InetAddrMaskTest/InetAddrMaskTest.cpp index c97d1afb8..708357dc8 100644 --- a/src/unit_tests/InetAddrMaskTest/InetAddrMaskTest.cpp +++ b/src/unit_tests/InetAddrMaskTest/InetAddrMaskTest.cpp @@ -71,6 +71,35 @@ void InetAddrMaskTest::testStringToInetAddr() sa1 = new InetAddr("1.0.0"); CPPUNIT_ASSERT_MESSAGE("1.0.0 -> " + sa1->toString(), sa1->toString() == "1.0.0.0"); + + sa1 = new InetAddr("255.255.255.255"); + CPPUNIT_ASSERT_MESSAGE("255.255.255.255 -> " + sa1->toString(), sa1->toString() == "255.255.255.255"); + CPPUNIT_ASSERT(sa1->isValidV4Netmask() == true); + + sa1 = new InetAddr("255.255.255.128"); + CPPUNIT_ASSERT_MESSAGE("255.255.255.128 -> " + sa1->toString(), sa1->toString() == "255.255.255.128"); + CPPUNIT_ASSERT(sa1->isValidV4Netmask() == true); + + sa1 = new InetAddr("255.255.255.0"); + CPPUNIT_ASSERT_MESSAGE("255.255.255.0 -> " + sa1->toString(), sa1->toString() == "255.255.255.0"); + CPPUNIT_ASSERT(sa1->isValidV4Netmask() == true); + + sa1 = new InetAddr("255.255.0.0"); + CPPUNIT_ASSERT_MESSAGE("255.255.0.0 -> " + sa1->toString(), sa1->toString() == "255.255.0.0"); + CPPUNIT_ASSERT(sa1->isValidV4Netmask() == true); + + sa1 = new InetAddr("255.0.0.0"); + CPPUNIT_ASSERT_MESSAGE("255.0.0.0 -> " + sa1->toString(), sa1->toString() == "255.0.0.0"); + CPPUNIT_ASSERT(sa1->isValidV4Netmask() == true); + + sa1 = new InetAddr("0.0.0.0"); + CPPUNIT_ASSERT_MESSAGE("0.0.0.0 -> " + sa1->toString(), sa1->toString() == "0.0.0.0"); + CPPUNIT_ASSERT(sa1->isValidV4Netmask() == true); + + sa1 = new InetAddr("255.0.255.0"); + CPPUNIT_ASSERT_MESSAGE("255.0.255.0 -> " + sa1->toString(), sa1->toString() == "255.0.255.0"); + CPPUNIT_ASSERT(sa1->isValidV4Netmask() == false); + } void InetAddrMaskTest::testStringToInetAddrExceptions() @@ -132,7 +161,7 @@ void InetAddrMaskTest::testStringToInetAddrMask() sa = a1->getAddressPtr()->toString(); CPPUNIT_ASSERT(sa=="0.0.0.0"); // 0.0.0.0/0.0.0.0 has maximum dimension (represents all possible addresses) - CPPUNIT_ASSERT(a1->dimension() == (1<<31)-1); + CPPUNIT_ASSERT(a1->dimension() == (((unsigned int)1)<<31)-1); InetAddrMask *a2 = new InetAddrMask(InetAddr("1.1.1.1"), InetAddr("255.255.255.0")); sa = a2->getAddressPtr()->toString();