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();