diff --git a/include/ulib/net/client/redis.h b/include/ulib/net/client/redis.h index c40a7a2a..7bbe4c69 100644 --- a/include/ulib/net/client/redis.h +++ b/include/ulib/net/client/redis.h @@ -65,10 +65,10 @@ typedef void (*vPFcscs)(const UString&,const UString&); class UREDISClusterMaster; -class U_EXPORT UREDISClient_Base : public UClient_Base, UEventFd { +class U_EXPORT UREDISClient_Base : public UClient_Base { public: - ~UREDISClient_Base(); + ~UREDISClient_Base() { U_TRACE_DTOR(0, UREDISClient_Base); } // RESPONSE @@ -787,22 +787,6 @@ public: (withPayloads ? U_CONSTANT_SIZE("WITHPAYLOADS") : 0), "WITHPAYLOADS")); } - // define method VIRTUAL of class UEventFd - -#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__) - virtual int handlerRead() U_DECL_FINAL; -#endif - - virtual void handlerDelete() - { - U_TRACE_NO_PARAM(0, "UREDISClient_Base::handlerDelete()") - - U_INTERNAL_DUMP("UREDISClient_Base::handlerDelete() -> client = %p", this); - U_INTERNAL_DUMP("UEventFd::fd = %d", UEventFd::fd) - - UEventFd::fd = -1; - } - #if defined(U_STDCPP_ENABLE) && defined(DEBUG) const char* dump(bool reset) const; #endif @@ -814,8 +798,6 @@ protected: static ptrdiff_t diff; static UREDISClient_Base* pthis; - static UHashMap* pchannelCallbackMap; - UREDISClient_Base() : UClient_Base(U_NULLPTR) { U_TRACE_CTOR(0, UREDISClient_Base, "") @@ -999,7 +981,7 @@ private: #if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__) -class UREDISClusterClient : public UREDISClient { +class U_EXPORT UREDISClusterClient : public UREDISClient, public UEventFd { public: enum class ClientType : uint8_t { @@ -1012,9 +994,23 @@ public: const ClientType type; UREDISClusterMaster *master; - //virtual void handlerDelete() U_DECL_FINAL; + virtual int handlerRead() U_DECL_FINAL; + + virtual void handlerDelete() U_DECL_FINAL + { + U_TRACE_NO_PARAM(0, "UREDISClusterClient::handlerDelete()") + + U_INTERNAL_DUMP("UREDISClusterClient::handlerDelete() -> client = %p", this); + U_INTERNAL_DUMP("UEventFd::fd = %d", UEventFd::fd) + + UEventFd::fd = -1; + } UREDISClusterClient(UREDISClusterMaster *_master, const ClientType _type) : UREDISClient(), type(_type), master(_master) {} + +#if defined(U_STDCPP_ENABLE) && defined(DEBUG) + const char* dump(bool _reset) const { return UREDISClient_Base::dump(_reset); } +#endif }; struct RedisClusterNode { @@ -1057,6 +1053,7 @@ private: UREDISClusterClient *subscriptionClient; UREDISClusterClient *managementClient; UHashMap *clusterNodes; + UHashMap* pchannelCallbackMap; static uint16_t hashslotForKey(UStringType&& hashableKey) {return u_crc16(U_STRING_TO_PARAM(hashableKey)) % 16384;} @@ -1071,7 +1068,7 @@ private: return workingNode->client; } } - + return U_NULLPTR; // never reached } @@ -1082,7 +1079,7 @@ private: RedisClusterNode* workingNode = (RedisClusterNode *)(node->elem); if (ip == workingNode->ipAddress) return workingNode->client; - } + } return U_NULLPTR; // never reached } @@ -1098,6 +1095,10 @@ private: template UREDISClusterClient* sendToCluster(uint16_t hashslot, UStringType&& pipeline, UREDISClusterClient* workingClient) { + U_TRACE_NO_PARAM(0, "UREDISClusterMaster::sendToCluster"); + + U_DUMP("pipeline = %.*s", pipeline.size(), pipeline.data()); + ClusterError error; retry: @@ -1116,7 +1117,6 @@ private: { case ClusterError::moved: { - // U_DUMP("(D) calling calculateNodeMap"); calculateNodeMap(); workingClient = clientForHashslot(hashslot); break; @@ -1152,7 +1152,7 @@ private: return sendToCluster(hashslot, std::forward(pipeline), clientForHashslot(hashslot)); } -public: + public: U_MEMORY_TEST U_MEMORY_ALLOCATOR @@ -1191,7 +1191,9 @@ public: ~UREDISClusterMaster() { U_DELETE(subscriptionClient); + U_DELETE(managementClient); if (clusterNodes) U_DELETE(clusterNodes); + if (pchannelCallbackMap) U_DELETE(pchannelCallbackMap); } #if defined(DEBUG) @@ -1202,6 +1204,9 @@ public: class UCompileTimeRESPEncoder : public UCompileTimeStringFormatter { private: +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-parameter" + template static constexpr auto generateSegments(StringClass format, size_t& outputCount, std::tuple&& workingCommand, T&& t, Ts&&... ts) { @@ -1253,6 +1258,7 @@ private: } } } +#pragma GCC diagnostic pop template static size_t encode_impl(size_t writePosition, UString& workingString, Ts&&... ts) @@ -1361,6 +1367,8 @@ public: pipeline.append(command); spans.emplace_back(commandCount, UREDISClusterMaster::hashslotForKey(std::forward(hashableKey)), beginning, pipeline.size(), spans.size()); + + U_DUMP("appended, %.*s", pipeline.size() - beginning, pipeline.data()); } template @@ -1373,6 +1381,8 @@ public: size_t commandCount = UCompileTimeRESPEncoder::encode_add(pipeline, std::forward(ts)...); spans.emplace_back(commandCount, UREDISClusterMaster::hashslotForKey(std::forward(hashableKey)), beginning, pipeline.size(), spans.size()); + + U_DUMP("appended, %.*s", pipeline.size() - beginning, pipeline.data()); } AnonymousClusterPipeline() : pipeline(300U) {} diff --git a/include/ulib/string.h b/include/ulib/string.h index 922895e2..c7251fab 100644 --- a/include/ulib/string.h +++ b/include/ulib/string.h @@ -2648,6 +2648,8 @@ public: long strtol( bool check_for_suffix = false) const { return rep->strtol( check_for_suffix); } unsigned long strtoul(bool check_for_suffix = false) const { return rep->strtoul(check_for_suffix); } + static UString humanReadableByteCountBin(int64_t bytes); + // UTF8 <--> ISO Latin 1 static UString toUTF8(const unsigned char* t, uint32_t tlen) diff --git a/src/ulib/net/client/redis.cpp b/src/ulib/net/client/redis.cpp index c275ee30..615aaf03 100644 --- a/src/ulib/net/client/redis.cpp +++ b/src/ulib/net/client/redis.cpp @@ -16,20 +16,8 @@ uint32_t UREDISClient_Base::start; ptrdiff_t UREDISClient_Base::diff; -UHashMap* UREDISClient_Base::pchannelCallbackMap; UREDISClient_Base* UREDISClient_Base::pthis; -UREDISClient_Base::~UREDISClient_Base() -{ - U_TRACE_DTOR(0, UREDISClient_Base) - - if (pchannelCallbackMap) - { - U_DELETE(pchannelCallbackMap) - pchannelCallbackMap = U_NULLPTR; - } -} - // Connect to REDIS server void UREDISClient_Base::init() @@ -439,13 +427,13 @@ bool UREDISClient_Base::deleteKeys(const char* pattern, uint32_t len) // Delete #if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__) // this is called for subscribed channels -int UREDISClient_Base::handlerRead() +int UREDISClusterClient::handlerRead() { // BytesRead(100) = "*3\r\n$7\r\nmessage\r\n$19\r\n{ABC}.trafficSignal\r\n$1\r\n1\r\n*3\r\n$7\r\nmessage\r\n$19\r\n{DEF}.trafficSignal\r\n$1\r\n1\r\n" - U_TRACE_NO_PARAM(0, "UREDISClient_Base::handlerRead()") + U_TRACE_NO_PARAM(0, "UREDISClusterClient::handlerRead()") - if ((clear(), UClient_Base::response.setEmpty(), UClient_Base::readResponse(U_SINGLE_READ))) + if ((clear(), response.setEmpty(), readResponse(U_SINGLE_READ))) { processResponse(); @@ -457,7 +445,7 @@ int UREDISClient_Base::handlerRead() { if (vitem[index] == "message"_ctv) { - vPFcscs callback = (vPFcscs)pchannelCallbackMap->at(vitem[index + 1]); + vPFcscs callback = (vPFcscs)(master->pchannelCallbackMap->at(vitem[index + 1])); if (callback) callback(vitem[index + 1], vitem[index + 2]); } } @@ -468,8 +456,6 @@ int UREDISClient_Base::handlerRead() ClusterError UREDISClusterMaster::checkResponseForClusterErrors(const UString& response, size_t offset) { - U_TRACE_NO_PARAM(0, "checkResponseForClusterErrors()") - // all of these errors are very rare, and only occur in the midst of cluster topology changes // -MOVED 3999 127.0.0.1:6381 => the hashslot has been moved to another master node @@ -500,8 +486,6 @@ void UREDISClusterMaster::calculateNodeMap() UString& response = managementClient->response; - U_WARNING("CLUSTER SLOTS response = %.*s", response.size(), response.data()); - uint16_t lowHashSlot; uint16_t highHashSlot; UString compositeAddress(50U); @@ -588,6 +572,8 @@ bool UREDISClusterMaster::connect(const char* host, unsigned int _port) { U_TRACE(0, "UREDISClusterMaster::connect(%S,%u)", host, _port) + managementClient->UEventFd::op_mask |= EPOLLET; + if (managementClient->connect(host, _port)) { calculateNodeMap(); @@ -597,19 +583,14 @@ bool UREDISClusterMaster::connect(const char* host, unsigned int _port) if (randomNode) { subscriptionClient->connect(randomNode->ipAddress.c_str(), randomNode->port); - - U_INTERNAL_ASSERT_EQUALS(UREDISClient_Base::pchannelCallbackMap, U_NULLPTR) - U_NEW(UHashMap, UREDISClient_Base::pchannelCallbackMap, UHashMap()); + U_NEW(UHashMap, pchannelCallbackMap, UHashMap()); subscriptionClient->UEventFd::fd = subscriptionClient->getFd(); - subscriptionClient->UEventFd::op_mask |= EPOLLET; - U_DUMP("subscriptionClient = %p", subscriptionClient); - UServer_Base::addHandlerEvent(subscriptionClient); - + U_RETURN(true); } } @@ -621,16 +602,20 @@ void UREDISClusterMaster::clusterUnsubscribe(const UString& channel) // unregist { U_TRACE(0, "UREDISClusterMaster::clusterUnsubscribe(%V)", channel.rep) - subscriptionClient->sendRequest(U_CTV_TO_PARAM("UNSUBSCRIBE "_ctv), channel); - (void)subscriptionClient->pchannelCallbackMap->erase(channel); + UCompileTimeRESPEncoder::encode<"UNSUBSCRIBE {}"_ctv>(subscriptionClient->response, channel); + subscriptionClient->sendRequest(subscriptionClient->response); + (void)pchannelCallbackMap->erase(channel); } void UREDISClusterMaster::clusterSubscribe(const UString& channel, vPFcscs callback) // register the callback for messages published to the given channels { U_TRACE(0, "UREDISClusterMaster::clusterSubscribe(%V,%p)", channel.rep, callback) - subscriptionClient->sendRequest(U_CTV_TO_PARAM("SUBSCRIBE "_ctv), channel); - subscriptionClient->pchannelCallbackMap->insert(channel, (const void*)callback); + UCompileTimeRESPEncoder::encode<"SUBSCRIBE {}"_ctv>(subscriptionClient->response, channel); + subscriptionClient->sendRequest(subscriptionClient->response); + + UString channelCopy(U_STRING_TO_PARAM(channel)); + pchannelCallbackMap->insert(channelCopy, (const void*)callback); } static void getNextCommandResponse(const UString& string, size_t& marker) diff --git a/src/ulib/net/server/plugin/usp/fortune.h b/src/ulib/net/server/plugin/usp/fortune.h index 917ff4f2..17917125 100644 --- a/src/ulib/net/server/plugin/usp/fortune.h +++ b/src/ulib/net/server/plugin/usp/fortune.h @@ -17,13 +17,6 @@ class U_EXPORT Fortune { public: - // Check for memory error - U_MEMORY_TEST - - // Allocator e Deallocator - U_MEMORY_ALLOCATOR - U_MEMORY_DEALLOCATOR - uint32_t id; UString message; @@ -40,8 +33,6 @@ public: Fortune(const Fortune& f) : id(f.id), message(f.message) { U_TRACE_CTOR(5, Fortune, "%p", &f) - - U_MEMORY_TEST_COPY(f) } ~Fortune() @@ -159,7 +150,7 @@ public: { u_put_unalignedp64(ptr, U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')); u_put_unalignedp64(ptr+8, U_MULTICHAR_CONSTANT64('L','e','n','g','t','h',':',' ')); - u_put_unalignedp64(ptr+16, U_MULTICHAR_CONSTANT64('1','2','2','7','\r','\n','C','o')); + u_put_unalignedp64(ptr+16, U_MULTICHAR_CONSTANT64('x','x','x','x','\r','\n','C','o')); u_put_unalignedp64(ptr+24, U_MULTICHAR_CONSTANT64('n','t','e','n','t','-','T','y')); u_put_unalignedp64(ptr+32, U_MULTICHAR_CONSTANT64('p','e',':',' ','t','e','x','t')); u_put_unalignedp64(ptr+40, U_MULTICHAR_CONSTANT64('/','h','t','m','l',';',' ','c')); @@ -180,13 +171,11 @@ public: u_put_unalignedp64(ptr+160, U_MULTICHAR_CONSTANT64('<','/','t','h','>','<','/','t')); u_put_unalignedp16(ptr+168, U_MULTICHAR_CONSTANT16('r','>')); - pwbuffer = ptr + U_CONSTANT_SIZE("Content-Length: 1227\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n" + pwbuffer = ptr + U_CONSTANT_SIZE("Content-Length: xxxx\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n" "Fortunes"); } U_INTERNAL_ASSERT_EQUALS(u_get_unalignedp64(UClientImage_Base::wbuffer->data()), U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')) - - UClientImage_Base::wbuffer->size_adjust_constant(U_CONSTANT_SIZE("Content-Length: 1227\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n") + 1227); } static void endQuery() @@ -203,6 +192,7 @@ public: pvfortune->sort(Fortune::cmp_obj); char* ptr = pwbuffer; + uint32_t content_length = U_CONSTANT_SIZE("Fortunes
idmessage
"); for (uint32_t sz, i = 0, n = pvfortune->size(); i < n; ++i) { @@ -228,6 +218,17 @@ public: u_put_unalignedp64(ptr, U_MULTICHAR_CONSTANT64('<','/','t','a','b','l','e','>')); u_put_unalignedp64(ptr+8, U_MULTICHAR_CONSTANT64('<','/','b','o','d','y','>','<')); u_put_unalignedp64(ptr+16, U_MULTICHAR_CONSTANT64('/','h','t','m','l','>','\0','\0')); + + content_length += (ptr - pwbuffer) + U_CONSTANT_SIZE("
idmessage
"); + + U_INTERNAL_ASSERT_EQUALS(content_length, 1227) + + ptr = pwbuffer - U_CONSTANT_SIZE("xxxx\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n" + "Fortunes"); + + (void) u_num2str32(content_length, ptr); + + UClientImage_Base::wbuffer->size_adjust_constant(U_CONSTANT_SIZE("Content-Length: xxxx\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n") + content_length); } static void doQuery(vPF handlerQuery) @@ -246,10 +247,7 @@ public: # ifdef U_STATIC_ORM_DRIVER_PGSQL U_INTERNAL_DUMP("UServer_Base::handler_db2 = %p", UServer_Base::handler_db2) - if (UServer_Base::handler_db2 == U_NULLPTR) - { - U_NEW(UEventDB, UServer_Base::handler_db2, UEventDB); - } + if (UServer_Base::handler_db2 == U_NULLPTR) UServer_Base::handler_db2 = new UEventDB(); # endif } @@ -257,15 +255,15 @@ public: { U_TRACE_NO_PARAM(5, "Fortune::handlerFork()") - U_NEW_STRING(pmessage, UString(101U)); + pmessage = new UString(101U); - U_NEW(UVector, pvfortune, UVector); + pvfortune = new UVector(); Fortune* elem; for (uint32_t i = 0; i < 13; ++i) { - U_NEW(Fortune, elem, Fortune(i+1)); + elem = new Fortune(i+1); pvfortune->push(elem); } @@ -277,7 +275,7 @@ public: if (psql_fortune == U_NULLPTR) { - U_NEW(UOrmSession, psql_fortune, UOrmSession(U_CONSTANT_TO_PARAM("fortune"))); + psql_fortune = new UOrmSession(U_CONSTANT_TO_PARAM("fortune")); if (psql_fortune->isReady() == false) { @@ -290,7 +288,7 @@ public: return; } - U_NEW(UOrmStatement, pstmt_fortune, UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune"))); + pstmt_fortune = new UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune")); handlerFork(); @@ -313,33 +311,33 @@ public: } #ifdef DEBUG - static void handlerEnd() - { - U_TRACE_NO_PARAM(5, "Fortune::handlerEnd()") + static void handlerEnd() + { + U_TRACE_NO_PARAM(5, "Fortune::handlerEnd()") - U_INTERNAL_ASSERT_POINTER(pmessage) - U_INTERNAL_ASSERT_POINTER(pvfortune) + U_INTERNAL_ASSERT_POINTER(pmessage) + U_INTERNAL_ASSERT_POINTER(pvfortune) - U_DELETE(pmessage) - U_DELETE(pvfortune) - } + U_DELETE(pmessage) + U_DELETE(pvfortune) + } - static void handlerEndSql() - { - U_TRACE_NO_PARAM(5, "Fortune::handlerEndSql()") + static void handlerEndSql() + { + U_TRACE_NO_PARAM(5, "Fortune::handlerEndSql()") - if (pstmt_fortune) - { - handlerEnd(); + if (pstmt_fortune) + { + handlerEnd(); - U_DELETE(psql_fortune) - U_DELETE(pstmt_fortune) + U_DELETE(psql_fortune) + U_DELETE(pstmt_fortune) - pstmt_fortune = U_NULLPTR; - } - } + pstmt_fortune = U_NULLPTR; + } + } - const char* dump(bool breset) const; + const char* dump(bool breset) const; #endif private: diff --git a/src/ulib/net/server/plugin/usp/json.usp b/src/ulib/net/server/plugin/usp/json.usp index 6f91f537..9afe75ae 100644 --- a/src/ulib/net/server/plugin/usp/json.usp +++ b/src/ulib/net/server/plugin/usp/json.usp @@ -26,14 +26,14 @@ if (u_get_unalignedp64(pwbuffer+44) != U_MULTICHAR_CONSTANT64('n','/','j','s','o { u_put_unalignedp64(pwbuffer, U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')); u_put_unalignedp64(pwbuffer+8, U_MULTICHAR_CONSTANT64('L','e','n','g','t','h',':',' ')); - u_put_unalignedp32(pwbuffer+16, U_MULTICHAR_CONSTANT32('2','7','\r','\n')); + u_put_unalignedp32(pwbuffer+16, U_MULTICHAR_CONSTANT32('x','x','\r','\n')); u_put_unalignedp64(pwbuffer+20, U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')); u_put_unalignedp64(pwbuffer+28, U_MULTICHAR_CONSTANT64('T','y','p','e',':',' ','a','p')); u_put_unalignedp64(pwbuffer+36, U_MULTICHAR_CONSTANT64('p','l','i','c','a','t','i','o')); u_put_unalignedp64(pwbuffer+44, U_MULTICHAR_CONSTANT64('n','/','j','s','o','n','\r','\n')); u_put_unalignedp16(pwbuffer+52, U_MULTICHAR_CONSTANT16('\r','\n')); - ptr = pwbuffer + U_CONSTANT_SIZE("Content-Length: 27\r\nContent-Type: application/json\r\n\r\n"); + ptr = pwbuffer + U_CONSTANT_SIZE("Content-Length: xx\r\nContent-Type: application/json\r\n\r\n"); } U_INTERNAL_ASSERT_EQUALS(u_get_unalignedp64(UClientImage_Base::wbuffer->data()), U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')) @@ -42,5 +42,11 @@ UValue::pstringify = ptr; UValue(*pkey, *pvalue).stringify(); -UClientImage_Base::wbuffer->size_adjust_constant(U_CONSTANT_SIZE("Content-Length: 27\r\nContent-Type: application/json\r\n\r\n") + 27); +uint32_t content_length = (UValue::pstringify - ptr); + +U_INTERNAL_ASSERT_EQUALS(content_length, 27) + +(void) u_num2str32(content_length, ptr - U_CONSTANT_SIZE("xx\r\nContent-Type: application/json\r\n\r\n")); + +UClientImage_Base::wbuffer->size_adjust_constant(U_CONSTANT_SIZE("Content-Length: xx\r\nContent-Type: application/json\r\n\r\n") + content_length); --> diff --git a/src/ulib/string.cpp b/src/ulib/string.cpp index 49fbf9f4..44f88578 100644 --- a/src/ulib/string.cpp +++ b/src/ulib/string.cpp @@ -1902,6 +1902,24 @@ long double UStringRep::strtold() const } #endif +UString UString::humanReadableByteCountBin(int64_t bytes) +{ + U_TRACE(0, "UString::humanReadableByteCountBin(%lld)", bytes) + + UString result(32U); + int64_t b = (bytes == LONG_MIN ? LONG_MAX : llabs(bytes)); + + if (b < 1024L) result.snprintf(U_CONSTANT_TO_PARAM("%lld B"), bytes); + else if (b <= (0xfffccccccccccccL >> 40)) result.snprintf(U_CONSTANT_TO_PARAM("%.1f KiB"), bytes / 0x1p10); + else if (b <= (0xfffccccccccccccL >> 30)) result.snprintf(U_CONSTANT_TO_PARAM("%.1f MiB"), bytes / 0x1p20); + else if (b <= (0xfffccccccccccccL >> 20)) result.snprintf(U_CONSTANT_TO_PARAM("%.1f GiB"), bytes / 0x1p30); + else if (b <= (0xfffccccccccccccL >> 10)) result.snprintf(U_CONSTANT_TO_PARAM("%.1f TiB"), bytes / 0x1p40); + else if (b <= 0xfffccccccccccccL) result.snprintf(U_CONSTANT_TO_PARAM("%.1f PiB"), (bytes >> 10) / 0x1p40); + else result.snprintf(U_CONSTANT_TO_PARAM("%.1f EiB"), (bytes >> 20) / 0x1p40); + + U_RETURN_STRING(result); +} + // UTF8 <--> ISO Latin 1 UStringRep* UStringRep::fromUTF8(const unsigned char* s, uint32_t n) diff --git a/src/ulib/utility/semaphore.cpp b/src/ulib/utility/semaphore.cpp index 5bdf549f..55c96975 100644 --- a/src/ulib/utility/semaphore.cpp +++ b/src/ulib/utility/semaphore.cpp @@ -17,7 +17,8 @@ #include #ifdef U_LINUX -U_DUMP_KERNEL_VERSION(LINUX_VERSION_CODE) +// socket already dumps this +//U_DUMP_KERNEL_VERSION(LINUX_VERSION_CODE) #endif USemaphore* USemaphore::first; diff --git a/src/ulib/utility/websocket.cpp b/src/ulib/utility/websocket.cpp index 4285b215..ef92724d 100644 --- a/src/ulib/utility/websocket.cpp +++ b/src/ulib/utility/websocket.cpp @@ -617,8 +617,13 @@ bool UWebSocket::sendData(const bool isServer, USocket* socket, int type, const */ uint8_t opcode, masking_key[4]; + + U_DUMP("len = %lu", len); + // 0xffff == 65535 uint32_t header_length = (len > 125U ? 2U : 0) + (len > 0xffff ? 8U : 0); + U_DUMP("header_length = %lu", header_length); + if (isServer) header_length += 2U; else { @@ -628,8 +633,12 @@ bool UWebSocket::sendData(const bool isServer, USocket* socket, int type, const uint32_t ncount = header_length + len; - UString tmp(ncount), compressed; - unsigned char* header = (unsigned char*)tmp.data(); + // 1 MB + static UString buffer(1048576U); + buffer.setEmpty(); + buffer.reserve(ncount); + + unsigned char* header = (unsigned char*)buffer.data(); switch (type) { @@ -643,6 +652,8 @@ bool UWebSocket::sendData(const bool isServer, USocket* socket, int type, const opcode = U_WS_OPCODE_TEXT; # ifdef USE_LIBBROTLI + UString compressed; + if (compressed = UStringExt::brotli(data, len, (U_PARALLELIZATION_CHILD ? BROTLI_MAX_QUALITY : UHTTP::brotli_level_for_dynamic_content))) { opcode = U_WS_OPCODE_BROTLI; @@ -685,7 +696,7 @@ bool UWebSocket::sendData(const bool isServer, USocket* socket, int type, const case 4: { header[1] = 126; - u_put_unalignedp16(header+2, htons(len)); + u_put_unalignedp16(header+2, htons((uint16_t)len)); break; } case 12: @@ -721,6 +732,7 @@ bool UWebSocket::sendData(const bool isServer, USocket* socket, int type, const default: break; // never reached } + switch (header_length) { // server @@ -728,10 +740,7 @@ bool UWebSocket::sendData(const bool isServer, USocket* socket, int type, const case 4: case 12: { - for (uint32_t i = 0; i < len; ++i) - { - header[2+i] = data[i]; - } + memcpy(header + header_length, data, len); break; } // client @@ -739,9 +748,10 @@ bool UWebSocket::sendData(const bool isServer, USocket* socket, int type, const case 8: case 16: { + // we should SIMD this for (uint32_t i = 0; i < len; ++i) { - header[6+i] = (data[i] ^ masking_key[i % 4]) & 0xff; + header[header_length + i] = (data[i] ^ masking_key[i % 4]) & 0xff; } break; } diff --git a/tests/examples/FrameworkBenchmarks.sh b/tests/examples/FrameworkBenchmarks.sh index dbdaf873..55a2ad54 100755 --- a/tests/examples/FrameworkBenchmarks.sh +++ b/tests/examples/FrameworkBenchmarks.sh @@ -45,9 +45,9 @@ export ORM_DRIVER ORM_OPTION UMEMPOOL # ---------------------------------------------------------------------------------------------------------------------------------------------------------- # JSON # ---------------------------------------------------------------------------------------------------------------------------------------------------------- -#UMEMPOOL="237,0,0,49,273,-15,-14,-20,36" -#sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg -#sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg + UMEMPOOL="237,0,0,49,273,-15,-14,-20,36" + sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg + sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg # ---------------------------------------------------------------------------------------------------------------------------------------------------------- #Running 15s test @ http://localhost:8080/json # 4 threads and 256 connections @@ -69,11 +69,11 @@ export ORM_DRIVER ORM_OPTION UMEMPOOL #ORM_OPTION="host=localhost dbname=../db/hello_world" #ORM_DRIVER="mysql" #ORM_OPTION="host=localhost user=benchmarkdbuser password=benchmarkdbpass character-set=utf8 dbname=hello_world" - ORM_DRIVER="pgsql" - ORM_OPTION="host=localhost user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world" - UMEMPOOL="581,0,0,66,16416,-7,-20,-23,31" - sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET -2|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg - sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg +#ORM_DRIVER="pgsql" +#ORM_OPTION="host=localhost user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world" +#UMEMPOOL="581,0,0,66,16416,-7,-20,-23,31" +#sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET -2|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg +#sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg # ---------------------------------------------------------------------------------------------------------------------------------------------------------- #Running 15s test @ http://localhost:8080/cached_worlds?queries=20 # 4 threads and 256 connections diff --git a/tests/examples/TSA/tsaserial b/tests/examples/TSA/tsaserial index dbb43c1c..942535c5 100644 --- a/tests/examples/TSA/tsaserial +++ b/tests/examples/TSA/tsaserial @@ -1 +1 @@ -06D4 +06E9 diff --git a/tests/examples/benchmark/FrameworkBenchmarks/ULib/src/fortune.h b/tests/examples/benchmark/FrameworkBenchmarks/ULib/src/fortune.h index 3e57387a..b23ab280 100644 --- a/tests/examples/benchmark/FrameworkBenchmarks/ULib/src/fortune.h +++ b/tests/examples/benchmark/FrameworkBenchmarks/ULib/src/fortune.h @@ -33,8 +33,6 @@ public: Fortune(const Fortune& f) : id(f.id), message(f.message) { U_TRACE_CTOR(5, Fortune, "%p", &f) - - U_MEMORY_TEST_COPY(f) } ~Fortune() @@ -152,7 +150,7 @@ public: { u_put_unalignedp64(ptr, U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')); u_put_unalignedp64(ptr+8, U_MULTICHAR_CONSTANT64('L','e','n','g','t','h',':',' ')); - u_put_unalignedp64(ptr+16, U_MULTICHAR_CONSTANT64('1','2','2','7','\r','\n','C','o')); + u_put_unalignedp64(ptr+16, U_MULTICHAR_CONSTANT64('x','x','x','x','\r','\n','C','o')); u_put_unalignedp64(ptr+24, U_MULTICHAR_CONSTANT64('n','t','e','n','t','-','T','y')); u_put_unalignedp64(ptr+32, U_MULTICHAR_CONSTANT64('p','e',':',' ','t','e','x','t')); u_put_unalignedp64(ptr+40, U_MULTICHAR_CONSTANT64('/','h','t','m','l',';',' ','c')); @@ -173,13 +171,11 @@ public: u_put_unalignedp64(ptr+160, U_MULTICHAR_CONSTANT64('<','/','t','h','>','<','/','t')); u_put_unalignedp16(ptr+168, U_MULTICHAR_CONSTANT16('r','>')); - pwbuffer = ptr + U_CONSTANT_SIZE("Content-Length: 1227\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n" + pwbuffer = ptr + U_CONSTANT_SIZE("Content-Length: xxxx\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n" "Fortunes
idmessage
"); } U_INTERNAL_ASSERT_EQUALS(u_get_unalignedp64(UClientImage_Base::wbuffer->data()), U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')) - - UClientImage_Base::wbuffer->size_adjust_constant(U_CONSTANT_SIZE("Content-Length: 1227\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n") + 1227); } static void endQuery() @@ -196,6 +192,7 @@ public: pvfortune->sort(Fortune::cmp_obj); char* ptr = pwbuffer; + uint32_t content_length = U_CONSTANT_SIZE("Fortunes
idmessage
"); for (uint32_t sz, i = 0, n = pvfortune->size(); i < n; ++i) { @@ -221,6 +218,17 @@ public: u_put_unalignedp64(ptr, U_MULTICHAR_CONSTANT64('<','/','t','a','b','l','e','>')); u_put_unalignedp64(ptr+8, U_MULTICHAR_CONSTANT64('<','/','b','o','d','y','>','<')); u_put_unalignedp64(ptr+16, U_MULTICHAR_CONSTANT64('/','h','t','m','l','>','\0','\0')); + + content_length += (ptr - pwbuffer) + U_CONSTANT_SIZE("
idmessage
"); + + U_INTERNAL_ASSERT_EQUALS(content_length, 1227) + + ptr = pwbuffer - U_CONSTANT_SIZE("xxxx\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n" + "Fortunes"); + + (void) u_num2str32(content_length, ptr); + + UClientImage_Base::wbuffer->size_adjust_constant(U_CONSTANT_SIZE("Content-Length: xxxx\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n") + content_length); } static void doQuery(vPF handlerQuery) @@ -239,10 +247,7 @@ public: # ifdef U_STATIC_ORM_DRIVER_PGSQL U_INTERNAL_DUMP("UServer_Base::handler_db2 = %p", UServer_Base::handler_db2) - if (UServer_Base::handler_db2 == U_NULLPTR) - { - U_NEW(UEventDB, UServer_Base::handler_db2, UEventDB); - } + if (UServer_Base::handler_db2 == U_NULLPTR) UServer_Base::handler_db2 = new UEventDB(); # endif } @@ -250,15 +255,15 @@ public: { U_TRACE_NO_PARAM(5, "Fortune::handlerFork()") - U_NEW_STRING(pmessage, UString(101U)); + pmessage = new UString(101U); - U_NEW(UVector, pvfortune, UVector); + pvfortune = new UVector(); Fortune* elem; for (uint32_t i = 0; i < 13; ++i) { - U_NEW(Fortune, elem, Fortune(i+1)); + elem = new Fortune(i+1); pvfortune->push(elem); } @@ -270,7 +275,7 @@ public: if (psql_fortune == U_NULLPTR) { - U_NEW(UOrmSession, psql_fortune, UOrmSession(U_CONSTANT_TO_PARAM("fortune"))); + psql_fortune = new UOrmSession(U_CONSTANT_TO_PARAM("fortune")); if (psql_fortune->isReady() == false) { @@ -283,7 +288,7 @@ public: return; } - U_NEW(UOrmStatement, pstmt_fortune, UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune"))); + pstmt_fortune = new UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune")); handlerFork(); diff --git a/tests/examples/benchmark/FrameworkBenchmarks/ULib/src/json.usp b/tests/examples/benchmark/FrameworkBenchmarks/ULib/src/json.usp index 6f91f537..9afe75ae 100644 --- a/tests/examples/benchmark/FrameworkBenchmarks/ULib/src/json.usp +++ b/tests/examples/benchmark/FrameworkBenchmarks/ULib/src/json.usp @@ -26,14 +26,14 @@ if (u_get_unalignedp64(pwbuffer+44) != U_MULTICHAR_CONSTANT64('n','/','j','s','o { u_put_unalignedp64(pwbuffer, U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')); u_put_unalignedp64(pwbuffer+8, U_MULTICHAR_CONSTANT64('L','e','n','g','t','h',':',' ')); - u_put_unalignedp32(pwbuffer+16, U_MULTICHAR_CONSTANT32('2','7','\r','\n')); + u_put_unalignedp32(pwbuffer+16, U_MULTICHAR_CONSTANT32('x','x','\r','\n')); u_put_unalignedp64(pwbuffer+20, U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')); u_put_unalignedp64(pwbuffer+28, U_MULTICHAR_CONSTANT64('T','y','p','e',':',' ','a','p')); u_put_unalignedp64(pwbuffer+36, U_MULTICHAR_CONSTANT64('p','l','i','c','a','t','i','o')); u_put_unalignedp64(pwbuffer+44, U_MULTICHAR_CONSTANT64('n','/','j','s','o','n','\r','\n')); u_put_unalignedp16(pwbuffer+52, U_MULTICHAR_CONSTANT16('\r','\n')); - ptr = pwbuffer + U_CONSTANT_SIZE("Content-Length: 27\r\nContent-Type: application/json\r\n\r\n"); + ptr = pwbuffer + U_CONSTANT_SIZE("Content-Length: xx\r\nContent-Type: application/json\r\n\r\n"); } U_INTERNAL_ASSERT_EQUALS(u_get_unalignedp64(UClientImage_Base::wbuffer->data()), U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')) @@ -42,5 +42,11 @@ UValue::pstringify = ptr; UValue(*pkey, *pvalue).stringify(); -UClientImage_Base::wbuffer->size_adjust_constant(U_CONSTANT_SIZE("Content-Length: 27\r\nContent-Type: application/json\r\n\r\n") + 27); +uint32_t content_length = (UValue::pstringify - ptr); + +U_INTERNAL_ASSERT_EQUALS(content_length, 27) + +(void) u_num2str32(content_length, ptr - U_CONSTANT_SIZE("xx\r\nContent-Type: application/json\r\n\r\n")); + +UClientImage_Base::wbuffer->size_adjust_constant(U_CONSTANT_SIZE("Content-Length: xx\r\nContent-Type: application/json\r\n\r\n") + content_length); --> diff --git a/tests/examples/benchmark/FrameworkBenchmarks/fbenchmark.cfg b/tests/examples/benchmark/FrameworkBenchmarks/fbenchmark.cfg index 930c8fcd..1d341a93 100644 --- a/tests/examples/benchmark/FrameworkBenchmarks/fbenchmark.cfg +++ b/tests/examples/benchmark/FrameworkBenchmarks/fbenchmark.cfg @@ -2,7 +2,7 @@ userver { PORT 8080 PREFORK_CHILD 4 - TCP_LINGER_SET -2 + TCP_LINGER_SET 0 LISTEN_BACKLOG 256 DOCUMENT_ROOT benchmark/FrameworkBenchmarks/ULib/www PID_FILE ../userver_tcp.pid diff --git a/tests/examples/nocat/firewall/nodog.fw b/tests/examples/nocat/firewall/nodog.fw index 4fd36398..923279f3 100644 --- a/tests/examples/nocat/firewall/nodog.fw +++ b/tests/examples/nocat/firewall/nodog.fw @@ -2,70 +2,82 @@ # nodog.fw -networkMatchIface_do() { - awk -f - $* </dev/null; then - #ip addr show dev $iface | awk '/inet/{print $2}' | while read ip; do - ip route show | grep "dev $iface " | awk '{print $1}' | while read ip; do - networkMatchIface_do $net $ip - match=$? - if [ $match -eq 1 -o $match -eq 2 ]; then - exit 1 - fi - done - match=$? - else - #ifconfig $iface | awk '/inet/{i=$2;n=$4;gsub("^[^:]*:","",i);gsub("^[^:]*:","",n);print i" "n}' | while read ip nm; do - route | awk '{if($8=="$iface"){print $1" "$3}}' | while read ip nm; do - networkMatchIface_do $net $ip $nm - if [ $match -eq 1 -o $match -eq 2 ]; then - exit 1 - fi - done - match=$? - fi - return $match + if(found==0)exit(1); + printf("%04x%04x\t%04x%04x\t%s\n",rshift(cnetaddr,16),and(cnetaddr,0xffff),rshift(cnetmask,16),and(cnetmask,0xffff),cnetwork); + exit(0); +}' /dev/null - $IPTABLES -t filter -F NoCat - $IPTABLES -t filter -A NoCat -p tcp -m conntrack --ctstate INVALID -j DROP || $IPTABLES -t filter -A NoCat -p tcp -m state --state INVALID -j DROP - for ifacein in $InternalDevice; do - for ifaceout in $ExternalDevice; do - $IPTABLES -t filter -D FORWARD -i $ifacein -o $ifaceout -j NoCat 2>/dev/null - $IPTABLES -t filter -D FORWARD -i $ifaceout -o $ifacein -j NoCat 2>/dev/null - $IPTABLES -t filter -A FORWARD -i $ifacein -o $ifaceout -j NoCat - $IPTABLES -t filter -A FORWARD -i $ifaceout -o $ifacein -j NoCat - done - done - - if [ "$BlockRFC1918" = 1 ]; then - $IPTABLES -t filter -N NoCat_RFC1918 2>/dev/null - $IPTABLES -t filter -F NoCat_RFC1918 - for net in $FullPrivateNetwork; do - $IPTABLES -t filter -A NoCat_RFC1918 -d $net -j ACCEPT - done - $IPTABLES -t filter -A NoCat_RFC1918 -d 10.0.0.0/8 -j RETURN - $IPTABLES -t filter -A NoCat_RFC1918 -d 172.16.0.0/12 -j RETURN - $IPTABLES -t filter -A NoCat_RFC1918 -d 192.168.0.0/16 -j RETURN - $IPTABLES -t filter -A NoCat_RFC1918 -d 127.0.0.0/8 -j RETURN - $IPTABLES -t filter -A NoCat_RFC1918 -j ACCEPT - fi - - $IPTABLES -t filter -N NoCat_Ports 2>/dev/null - $IPTABLES -t filter -F NoCat_Ports - $IPTABLES -t filter -D NoCat -j NoCat_Ports 2>/dev/null - $IPTABLES -t filter -A NoCat -j NoCat_Ports - - $IPTABLES -t filter -N NoCat_Inbound 2>/dev/null - $IPTABLES -t filter -F NoCat_Inbound - $IPTABLES -t filter -D NoCat -j NoCat_Inbound 2>/dev/null - $IPTABLES -t filter -A NoCat -j NoCat_Inbound - - $IPTABLES -t nat -N NoCat_Capture 2>/dev/null - $IPTABLES -t nat -F NoCat_Capture - $IPTABLES -t nat -D PREROUTING -j NoCat_Capture 2>/dev/null - $IPTABLES -t nat -A PREROUTING -j NoCat_Capture - - $IPTABLES -t nat -N NoCat_NAT 2>/dev/null - $IPTABLES -t nat -F NoCat_NAT - - # Only nat if we're not routing - - $IPTABLES -t nat -D POSTROUTING -j NoCat_NAT 2>/dev/null - [ $RouteOnly -gt 0 ] || $IPTABLES -t nat -A POSTROUTING -j NoCat_NAT - - $IPTABLES -t mangle -N NoCat 2>/dev/null - $IPTABLES -t mangle -F NoCat - $IPTABLES -t mangle -N NoCat_Permit 2>/dev/null - $IPTABLES -t mangle -F NoCat_Permit - $IPTABLES -t mangle -D PREROUTING -j NoCat 2>/dev/null - $IPTABLES -t mangle -A PREROUTING -j NoCat - - if [ $MembersOnly -gt 0 ]; then - classes="1 2" + # First mark for unauthorized after mark for authorized + # BEGIN ND_m_pre + $IPTABLES -t mangle -N ND_m_pre && \ + $IPTABLES -t mangle -A ND_m_pre -j MARK --set-mark 4 || exit 2 + if [ "$EnableIpset" = 1 ]; then + if [ "$EnableIpsetAuth" = "bitmap:ip,mac" ]; then + $IPSET create ND_s_permit_in_1 list:set && \ + $IPSET create ND_s_permit_in_2 list:set && \ + $IPSET create ND_s_permit_in_3 list:set || exit 2 + for net in $LocalNetwork; do + networkMatchIface $net ifacein netid + [ $? -eq 0 ] || exit 1 + $IPSET create ND_s_permit_in_1_$netid bitmap:ip,mac range $net && \ + $IPSET add ND_s_permit_in_1 ND_s_permit_in_1_$netid && \ + $IPSET create ND_s_permit_in_2_$netid bitmap:ip,mac range $net && \ + $IPSET add ND_s_permit_in_2 ND_s_permit_in_2_$netid && \ + $IPSET create ND_s_permit_in_3_$netid bitmap:ip,mac range $net && \ + $IPSET add ND_s_permit_in_3 ND_s_permit_in_3_$netid || exit 2 + done + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_1 src,src -j MARK --set-mark 1 && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_2 src,src -j MARK --set-mark 2 && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_3 src,src -j MARK --set-mark 3 || exit 2 + elif [ "$EnableIpsetAuth" = "hash:ip,mac" ]; then + $IPSET create ND_s_permit_in_1 hash:ip,mac && \ + $IPSET create ND_s_permit_in_2 hash:ip,mac && \ + $IPSET create ND_s_permit_in_3 hash:ip,mac && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_1 src,src -j MARK --set-mark 1 && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_2 src,src -j MARK --set-mark 2 && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_3 src,src -j MARK --set-mark 3 || exit 2 + elif [ "$EnableIpsetAuth" = "hash:ip" ]; then + $IPSET create ND_s_permit_in_1 hash:ip && \ + $IPSET create ND_s_permit_in_2 hash:ip && \ + $IPSET create ND_s_permit_in_3 hash:ip && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_1 src -j MARK --set-mark 1 && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_2 src -j MARK --set-mark 2 && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_3 src -j MARK --set-mark 3 || exit 2 + else + $IPSET create ND_s_permit_in_1 hash:mac && \ + $IPSET create ND_s_permit_in_2 hash:mac && \ + $IPSET create ND_s_permit_in_3 hash:mac && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_1 src -j MARK --set-mark 1 && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_2 src -j MARK --set-mark 2 && \ + $IPTABLES -t mangle -A ND_m_pre -m set --match-set ND_s_permit_in_3 src -j MARK --set-mark 3 || exit 2 + fi else - classes="1 2 3" + $IPTABLES -t mangle -N ND_m_permit_in && + $IPTABLES -t mangle -A ND_m_pre -j ND_m_permit_in || exit 2 fi + # END ND_m_pre - # Handle tagged traffic. The current service classes by fwmark are: - # ----------------------------------------------------------------- - # 1: Owner - # 2: Co-op - # 3: Public - # 4: Free - # ----------------------------------------------------------------- - for iface in $InternalDevice; do - ifaceinout=0 - for ifaceout in $ExternalDevice; do - if [ "$iface" == "$ifaceout" ]; then - ifaceinout=1 - fi - done + # Allow web hosts and traffic to portal, also manage DNS traffic + # BEGIN ND_n_notify + if [ "$EnableIpset" != 1 ]; then + $IPTABLES -t nat -N ND_n_notify || exit 2 + fi + # END ND_n_notify - for net in $LocalNetwork; do - networkMatchIface $iface $net - [ $? -eq 1 ] || continue - - # check se evitare il mascheramento del traffico verso portale autorizzativo - if [ "$AvoidMasqueradeAuthServiceIP" = "1" ]; then - for ifaceout in $MasqueradeDevice; do - $nat -o $ifaceout -s $net -d $AuthServiceIP -j RETURN - done - fi - - for fwmark in $classes; do - # Only forward tagged traffic per class - if [ "$BlockRFC1918" = 1 ]; then - $fwd -i $iface -s $net -m mark --mark $fwmark -j NoCat_RFC1918 - else - $fwd -i $iface -s $net -m mark --mark $fwmark -j ACCEPT - fi - - # Masquerade permitted connections. - for ifaceout in $MasqueradeDevice; do - $nat -o $ifaceout -s $net -m mark --mark $fwmark -j MASQUERADE - done - done - if [ $MembersOnly -gt 0 ]; then - for ifaceout in $MasqueradeDevice; do - $nat -o $ifaceout -s $net -m mark --mark 3 -j MASQUERADE - done - fi - - # Allow web traffic to the specified hosts, and don't capture connections intended for them - open_fw "$AuthServiceIP $1 $AllowedWebHosts" - - # Accept forward and back traffic to/from DNSAddr - if [ "$DNSAddr" ]; then - dns_item="" - for dns in $DNSAddr; do - $fwd -o $iface -d $net -s $dns -j ACCEPT - - for prot in tcp udp; do - $fwd -i $iface -s $net -d $dns -p $prot --dport 53 -j ACCEPT - $nat -p $prot -s $net -d $dns --dport 53 -j MASQUERADE - - # allow authenticated DNS traffic through this server. - $redirect -i $iface -m mark --mark 4 -p $prot --dport 53 -s $net -d $dns -j RETURN - done - dns_item=$dns - done - # Force unauthenticated DNS traffic through this server. - # Of course, only the first rule of this type will match. - # But it's easier to leave them all in ATM. - for prot in tcp udp; do - $redirect -i $iface -m mark --mark 4 -p $prot --dport 53 -s $net -j DNAT --to-destination $dns_item:53 - done - else - for prot in tcp udp; do - $redirect -i $iface -m mark --mark 4 -p $prot --dport 53 -s $net -j REDIRECT --to-port 53 - done - fi - for prot in tcp udp; do - $redirect -i $iface -d $FullPrivateNetwork -p $prot --dport 53 -s $net -j REDIRECT --to-port 53 - done - - if [ "$ifaceinout" == "1" ]; then - # Set packets from internal devices to fw mark 4, or 'denied', by default. - $mangle -i $iface -s $net -j MARK --set-mark 4 - $mangle -i $iface -j NoCat_Permit - fi - done - - if [ "$ifaceinout" != "1" ]; then - # Set packets from internal devices to fw mark 4, or 'denied', by default - $mangle -i $iface -j MARK --set-mark 4 - $mangle -i $iface -j NoCat_Permit + # BEGIN ND_n_pre + $IPTABLES -t nat -N ND_n_pre || exit 2 + if [ "$EnableIpset" = 1 ]; then + $IPSET create ND_s_allow_http hash:net && \ + $IPTABLES -t nat -A ND_n_pre -p tcp -m multiport --dports 80,443 -m set --match-set ND_s_allow_http dst -j RETURN || exit 2 + fi + for host in $AuthServiceIP $1 $AllowedWebHosts; do + if [ "$EnableIpset" = 1 ]; then + # Non torna errore per supportare nell'elenco lo stesso IP + $IPSET add ND_s_allow_http $host + else + #for port in 80 443; do + # $IPTABLES -t nat -A ND_n_pre -d $host -p tcp --dport $port -j RETURN + #done + $IPTABLES -t nat -A ND_n_pre -p tcp -m multiport --dports 80,443 -d $host -j RETURN || exit 2 fi done - - # Redirect outbound non-auth web traffic to the local gateway process except to windowsupdate.microsoft.com, which is broken. - # If MembersOnly is active, then redirect public class as well - # - #if [ $MembersOnly -gt 0 ]; then - # nonauth="3 4" - #else - nonauth="4" - #fi - - for iface in $InternalDevice; do - for mark in $nonauth; do - $redirect -m mark --mark $mark -i $iface -p tcp --dport 80 -j REDIRECT --to-port $GatewayPort + if [ "$EnableIpset" = 1 ]; then + $IPSET create ND_s_notify hash:ip && \ + $IPTABLES -t nat -A ND_n_pre -p tcp --dport 80 -m mark ! --mark 4 -m set --match-set ND_s_notify src -j REDIRECT --to-port $ProxyPort || exit 2 + else + $IPTABLES -t nat -A ND_n_pre -j ND_n_notify || exit 2 + fi + if [ "$DNSAddr" ]; then + if [ "$EnableIpset" = 1 ]; then + $IPSET create ND_s_allow_dns hash:ip && \ + $IPTABLES -t nat -A ND_n_pre -p udp --dport 53 -m mark --mark 4 -m set --match-set ND_s_allow_dns dst -j RETURN && \ + $IPTABLES -t nat -A ND_n_pre -p tcp --dport 53 -m mark --mark 4 -m set --match-set ND_s_allow_dns dst -j RETURN || exit 2 + fi + for dns in $DNSAddr; do + if [ "$EnableIpset" = 1 ]; then + $IPSET add ND_s_allow_dns $dns + else + $IPTABLES -t nat -A ND_n_pre -p udp --dport 53 -m mark --mark 4 -d $dns -j RETURN && \ + $IPTABLES -t nat -A ND_n_pre -p tcp --dport 53 -m mark --mark 4 -d $dns -j RETURN || exit 2 + fi + if [ -z "$dns_item" ]; then + dns_item=$dns + fi done - done + # Force unauthenticated DNS traffic through fist server. + # Of course, only the first rule of this type will match. + # But it's easier to leave them all in ATM. + for prot in tcp udp; do + $IPTABLES -t nat -A ND_n_pre -p $prot --dport 53 -m mark --mark 4 -j DNAT --to-destination $dns_item:53 && \ + $IPTABLES -t nat -A ND_n_pre -p $prot --dport 53 -d $FullPrivateNetwork -j DNAT --to-destination $dns_item:53 || exit 2 + done + else + for prot in tcp udp; do + $IPTABLES -t nat -A ND_n_pre -p $prot --dport 53 -m mark --mark 4 -j REDIRECT --to-port 53 && \ + $IPTABLES -t nat -A ND_n_pre -p $prot --dport 53 -d $FullPrivateNetwork -j REDIRECT --to-port 53 || exit 2 + done + fi + $IPTABLES -t nat -A ND_n_pre -p tcp --dport 80 -m mark --mark 4 -j REDIRECT --to-port $GatewayPort || exit 2 + # END ND_n_pre + + # Accept authorized IP + # BEGIN ND_f_permit_ou + if [ "$EnableIpset" = 1 ]; then + $IPSET create ND_s_permit_ou hash:ip || exit 2 + else + $IPTABLES -t filter -N ND_f_permit_ou || exit 2 + fi + # END ND_f_permit_ou + + # Filter allowed or denied traffic for authorized and not autorized from external devices and networks + # BEGIN ND_f_fwd_ou + $IPTABLES -t filter -N ND_f_fwd_ou || exit 2 + if [ "$EnableIpset" = 1 ]; then + $IPTABLES -t filter -A ND_f_fwd_ou -m set --match-set ND_s_permit_ou dst -j ACCEPT || exit 2 + else + $IPTABLES -t filter -A ND_f_fwd_ou -j ND_f_permit_ou || exit 2 + fi + if [ "$EnableIpset" = 1 ]; then + $IPTABLES -t filter -A ND_f_fwd_ou -p tcp -m multiport --sports 80,443 -m set --match-set ND_s_allow_http src -j ACCEPT || exit 2 + else + for host in $AuthServiceIP $1 $AllowedWebHosts; do + #for port in 80 443; do + # $IPTABLES -t filter -A ND_f_fwd_ou -d $host -p tcp --dport $port -j ACCPET + #done + $IPTABLES -t filter -A ND_f_fwd_ou -p tcp -m multiport --sports 80,443 -s $host -j ACCEPT || exit 2 + done + fi + if [ "$DNSAddr" ]; then + if [ "$EnableIpset" = 1 ]; then + $IPTABLES -t filter -A ND_f_fwd_ou -m set --match-set ND_s_allow_dns src -j ACCEPT || exit 2 + else + for dns in $DNSAddr; do + $IPTABLES -t filter -A ND_f_fwd_ou -s $dns -j ACCEPT || exit 2 + done + fi + fi + $IPTABLES -t filter -A ND_f_fwd_ou -j DROP || exit 2 + # END ND_f_fwd_ou + + # Block RFC1918 traffic + # BEGIN ND_f_RFC1918 + if [ "$BlockRFC1918" = 1 ]; then + $IPTABLES -t filter -N ND_f_RFC1918 + for net in $FullPrivateNetwork; do + $IPTABLES -t filter -A ND_f_RFC1918 -d $net -j ACCEPT || exit 2 + done + $IPTABLES -t filter -A ND_f_RFC1918 -d 10.0.0.0/8 -j RETURN && \ + $IPTABLES -t filter -A ND_f_RFC1918 -d 172.16.0.0/12 -j RETURN && \ + $IPTABLES -t filter -A ND_f_RFC1918 -d 192.168.0.0/16 -j RETURN && \ + $IPTABLES -t filter -A ND_f_RFC1918 -d 127.0.0.0/8 -j RETURN && \ + $IPTABLES -t filter -A ND_f_RFC1918 -j ACCEPT || exit 2 + fi + # END ND_f_RFC1918 # Lock down more ports for public users, if specified. Port restrictions are not applied to co-op and owner class users - # # There are two philosophies in restricting access: - # # That Which Is Not Specifically Permitted Is Denied # That Which Is Not Specifically Denied Is Permitted - # # If "IncludePorts" is defined, the default policy will be to deny all traffic, and only allow the ports mentioned # If "ExcludePorts" is defined, the default policy will be to allow all traffic, except to the ports mentioned - # # If both are defined, ExcludePorts will be ignored, and the default policy # will be to deny all traffic, allowing everything in IncludePorts, and issue a warning - + # BEGIN ND_f_ports if [ "$IncludePorts" ]; then if [ "$ExcludePorts" ]; then echo "WARNING: ExcludePorts and IncludePorts are both defined" echo "Ignoring 'ExcludePorts'. Please check your configuration" fi - # Enable all ports in IncludePorts - for iface in $InternalDevice; do - for port in $IncludePorts; do - $ports -p tcp -i $iface --dport $port -m mark --mark 3 -j ACCEPT - $ports -p udp -i $iface --dport $port -m mark --mark 3 -j ACCEPT - done - - # Always permit access to the GatewayPort (or we can't logout) - $ports -p tcp -i $iface --dport $GatewayPort -j ACCEPT - $ports -p udp -i $iface --dport $GatewayPort -j ACCEPT - - # ...and disable access to the rest - $ports -p tcp -i $iface -m mark --mark 3 -j DROP - $ports -p udp -i $iface -m mark --mark 3 -j DROP - - # supporto anti DoS sul captive portal - if [ $DosPrevention -gt 0 ]; then - $local -p tcp -i $iface --dport $GatewayPort -m state --state NEW -m recent --set --name NoCat - $local -p tcp -i $iface --dport $GatewayPort -m state --state NEW -m recent --update --name NoCat \ - --seconds $DosTimeInterval --hitcount `expr $DosAllowTries + 1` -j DROP - fi + $IPTABLES -t filter -N ND_f_ports || exit 2 + for port in $IncludePorts; do + $IPTABLES -t filter -A ND_f_ports -p tcp --dport $port -j ACCEPT && \ + $IPTABLES -t filter -A ND_f_ports -p udp --dport $port -j ACCEPT || exit 2 done + $IPTABLES -t filter -A ND_f_ports -p tcp -j DROP && \ + $IPTABLES -t filter -A ND_f_ports -p udp -j DROP || exit 2 + elif [ "$ExcludePorts" ]; then - # If ExcludePorts has entries, simply deny access to them - for iface in $InternalDevice; do - for port in $ExcludePorts; do - $ports -p tcp -i $iface --dport $port -m mark --mark 3 -j DROP - $ports -p udp -i $iface --dport $port -m mark --mark 3 -j DROP - done + $IPTABLES -t filter -N ND_f_ports || exit 2 + for port in $ExcludePorts; do + $IPTABLES -t filter -A ND_f_ports -p tcp --dport $port -j DROP && \ + $IPTABLES -t filter -A ND_f_ports -p udp --dport $port -j DROP || exit 2 done fi + # END ND_f_ports - # Disable access on the external to GatewayPort from anything but the AuthServiceIP + # Filter allowed or denied traffic for authorized and not autorized from internal devices and networks + # BEGIN ND_f_fwd_in + $IPTABLES -t filter -N ND_f_fwd_in || exit 2 + $IPTABLES -t filter -A ND_f_fwd_in -p tcp -m state --state INVALID -j DROP + if [ "$BlockRFC1918" = 1 ]; then + $IPTABLES -t filter -A ND_f_fwd_in -m mark --mark 2 -j ND_f_RFC1918 || exit 2 + else + $IPTABLES -t filter -A ND_f_fwd_in -m mark --mark 2 -j ACCEPT || exit 2 + fi + if [ "$EnableIpset" = 1 ]; then + $IPTABLES -t filter -A ND_f_fwd_in -p tcp -m multiport --dports 80,443 -m set --match-set ND_s_allow_http dst -j ACCEPT || exit 2 + else + for host in $AuthServiceIP $1 $AllowedWebHosts; do + #for port in 80 443; do + # $IPTABLES -t filter -A ND_f_fwd_in -d $host -p tcp --dport $port -j ACCPET + #done + $IPTABLES -t filter -A ND_f_fwd_in -p tcp -m multiport --dports 80,443 -d $host -j ACCEPT || exit 2 + done + fi + if [ "$DNSAddr" ]; then + if [ "$EnableIpset" = 1 ]; then + $IPTABLES -t filter -A ND_f_fwd_in -p udp --dport 53 -m set --match-set ND_s_allow_dns dst -j ACCEPT && \ + $IPTABLES -t filter -A ND_f_fwd_in -p tcp --dport 53 -m set --match-set ND_s_allow_dns dst -j ACCEPT || exit 2 + else + for dns in $DNSAddr; do + $IPTABLES -t filter -A ND_f_fwd_in -p tcp --dport 53 -d $dns -j ACCEPT && \ + $IPTABLES -t filter -A ND_f_fwd_in -p udp --dport 53 -d $dns -j ACCEPT || exit 2 + done + fi + fi + if [ -n "$IncludePorts" -o -n "$ExcludePorts" ]; then + $IPTABLES -t filter -A ND_f_fwd_in -m mark --mark 3 -j ND_f_ports || exit 2 + fi + $IPTABLES -t filter -A ND_f_fwd_in -j DROP || exit 2 + # END ND_f_fwd_in + + # Filter input traffic for captive + # BEGIN ND_f_in + $IPTABLES -t filter -N ND_f_in || exit 2 for src in $AuthServiceIP; do for ifaceout in $ExternalDevice; do - $fwd -i $ifaceout ! -s $src -p tcp --dport $GatewayPort -j DROP + $IPTABLES -t filter -A ND_f_in -i $ifaceout ! -s $src -p tcp --dport $GatewayPort -j DROP || exit 2 done done + # supporto anti DoS sul captive portal + if [ $DosPrevention -gt 0 ]; then + for ifacein in $InternalDevice; do + $IPTABLES -t filter -A ND_f_in -p tcp -i $ifacein --dport $GatewayPort -m state --state NEW -m recent --set --name NoDog && \ + $IPTABLES -t filter -A ND_f_in -p tcp -i $ifacein --dport $GatewayPort -m state --state NEW -m recent --update --name NoDog \ + --seconds $DosTimeInterval --hitcount `expr $DosAllowTries + 1` -j DROP || exit 2 + done + fi + # END ND_f_in - # Filter policy - $fwd -j DROP - + # Account traffic + # BEGIN ND_m_acc_in ND_m_acc_ou + $IPTABLES -t mangle -N ND_m_acc_in && \ + $IPTABLES -t mangle -N ND_m_acc_ou || exit 2 # -------------------------------------------------------------------------------------------------------------------------------------------------- # Automatically sets the proper value of MSS (Maximum Segment Size) of TCP SYN packets that the firewall sees of all outgoing packets. # -------------------------------------------------------------------------------------------------------------------------------------------------- @@ -399,111 +437,192 @@ initialize_fw() { # The --clamp-mss-to-pmtu automatically sets the MSS to the proper value, hence you don't need to explicitly set it. It is automatically set to PMTU # (Path Maximum Transfer Unit) minus 40 bytes, which should be a reasonable value for most applications. # -------------------------------------------------------------------------------------------------------------------------------------------------- - if [ $MaxSegmentSize -gt 0 ]; then for iface in $ExternalDevice; do - $IPTABLES -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o $iface -j TCPMSS --clamp-mss-to-pmtu + $IPTABLES -t mangle -A ND_m_acc_ou -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu || exit 2 done fi - - # Account traffic - $IPTABLES -t mangle -N AccountIn 2>/dev/null - $IPTABLES -t mangle -F AccountIn - $IPTABLES -t mangle -N AccountOu 2>/dev/null - $IPTABLES -t mangle -F AccountOu - - for iface in $InternalDevice; do - $IPTABLES -t mangle -D POSTROUTING -o $iface -j AccountIn 2>/dev/null - $IPTABLES -t mangle -A POSTROUTING -o $iface -j AccountIn + if [ "$EnableIpset" = 1 ]; then + $IPTABLES -t mangle -A ND_m_acc_in -m set --match-set ND_s_allow_http src -j RETURN && \ + $IPTABLES -t mangle -A ND_m_acc_ou -m set --match-set ND_s_allow_http dst -j RETURN || exit 2 + else + for host in $AuthServiceIP $1 $AllowedWebHosts; do + $IPTABLES -t mangle -A ND_m_acc_in -s "$host" -j RETURN && \ + $IPTABLES -t mangle -A ND_m_acc_ou -d "$host" -j RETURN || exit 2 + done + fi + for net in $LocalNetwork; do + $IPTABLES -t mangle -A ND_m_acc_in -s "$net" -j RETURN && \ + $IPTABLES -t mangle -A ND_m_acc_in -j ACCOUNT --addr "$net" --tname "$net" && \ + $IPTABLES -t mangle -A ND_m_acc_ou -d "$net" -j RETURN && \ + $IPTABLES -t mangle -A ND_m_acc_ou -j ACCOUNT --addr "$net" --tname "$net" || exit 2 done + # END ND_m_acc_in ND_m_acc_ou - for iface in $ExternalDevice; do - $IPTABLES -t mangle -D POSTROUTING -o $iface -j AccountOu 2>/dev/null - $IPTABLES -t mangle -A POSTROUTING -o $iface -j AccountOu - done + # Masquering + # BEGIN ND_n_post + $IPTABLES -t nat -N ND_n_post || exit 2 + if [ "$AvoidMasqueradeAuthServiceIP" = "1" ]; then + $IPTABLES -t nat -A ND_n_post -d $AuthServiceIP -j RETURN || exit 2 + fi + $IPTABLES -t nat -A ND_n_post -j MASQUERADE || exit 2 + # END ND_n_post - for srv in "$AuthServiceIP"; do - $IPTABLES -t mangle -A AccountIn -s "$srv" -j RETURN - $IPTABLES -t mangle -A AccountOu -d "$srv" -j RETURN - done + $IPTABLES -t filter -A INPUT -j ND_f_in || exit 2 for net in $LocalNetwork; do - $IPTABLES -t mangle -A AccountIn -s "$net" -j RETURN - $IPTABLES -t mangle -A AccountOu -d "$net" -j RETURN - $IPTABLES -t mangle -A AccountIn -j ACCOUNT --addr "$net" --tname "$net" - $IPTABLES -t mangle -A AccountOu -j ACCOUNT --addr "$net" --tname "$net" + networkMatchIface $net ifacein + [ $? -eq 0 ] || exit 1 + + ifaceinout=0 + for ifaceout in $ExternalDevice; do + if [ "$ifacein" = "$ifaceout" ]; then + ifaceinout=1 + fi + done + + if [ "$ifaceinout" == "1" ]; then + for ifaceout in $ExternalDevice; do + $IPTABLES -t filter -A FORWARD -i $ifacein -s $net -o $ifaceout -j ND_f_fwd_in && \ + $IPTABLES -t filter -A FORWARD -i $ifaceout -d $net -o $ifacein -j ND_f_fwd_ou && \ + $IPTABLES -t mangle -A POSTROUTING -o $ifaceout -s $net -j ND_m_acc_ou || exit 2 + done + $IPTABLES -t mangle -A PREROUTING -i $ifacein -s $net -j ND_m_pre && \ + $IPTABLES -t nat -A PREROUTING -i $ifacein -s $net -j ND_n_pre && \ + $IPTABLES -t mangle -A POSTROUTING -o $ifacein -d $net -j ND_m_acc_in || exit 2 + else + for ifaceout in $ExternalDevice; do + $IPTABLES -t filter -A FORWARD -i $ifacein -o $ifaceout -j ND_f_fwd_in && \ + $IPTABLES -t filter -A FORWARD -i $ifaceout -o $ifacein -j ND_f_fwd_ou && \ + $IPTABLES -t mangle -A POSTROUTING -o $ifaceout -s $net -j ND_m_acc_ou || exit 2 + done + $IPTABLES -t mangle -A PREROUTING -i $ifacein -j ND_m_pre && \ + $IPTABLES -t nat -A PREROUTING -i $ifacein -j ND_n_pre && \ + $IPTABLES -t mangle -A POSTROUTING -o $ifacein -j ND_m_acc_in || exit 2 + fi + if [ $RouteOnly -eq 0 ]; then + for ifacemsq in $MasqueradeDevice; do + $IPTABLES -t nat -A POSTROUTING -o $ifacemsq -s $net -j ND_n_post || exit 2 + done + fi done + # -------------------------------------------------------------------------- [ -S /tmp/evfwdsock ] && /usr/sbin/fwevhandler i # Bandwidth limits # -------------------------------------------------------------------------- - [ $EnableBandwidthLimits -gt 0 ] || return + if [ $EnableBandwidthLimits -gt 0 ]; then - if [ $IMQdisabled -eq 0 ]; then - extra_modules=ipt_IMQ - fi - if [ $IFBdisabled -eq 0 ]; then - extra_modules="ifb em_u32 act_connmark act_mirred sch_ingress" - fi + if [ $IMQdisabled -eq 0 ]; then + extra_modules=ipt_IMQ + fi + if [ $IFBdisabled -eq 0 ]; then + extra_modules="ifb em_u32 act_connmark act_mirred sch_ingress" + fi - loadKernelModules "xt_CONNMARK xt_CLASSIFY sch_red sch_sfq sch_hfsc cls_basic cls_fw cls_u32 $extra_modules" + loadKernelModules "xt_CONNMARK xt_CLASSIFY sch_red sch_sfq sch_hfsc cls_basic cls_fw cls_u32 $extra_modules" - if [ ${UploadRate} -gt 0 ]; then - for ifaceq in ${IQdevice}; do - [ $IMQdisabled -eq 0 -o $IFBdisabled -eq 0 ] && ifconfig ${ifaceq} up txqueuelen 5 - tc qdisc del dev ${ifaceq} root - tc qdisc add dev ${ifaceq} root handle 1: hfsc default 10 - tc class add dev ${ifaceq} parent 1: classid 1:1 hfsc sc rate ${UploadRate}kbit ul rate ${UploadRate}kbit + if [ ${UploadRate} -gt 0 ]; then + for ifaceq in ${IQdevice}; do + [ $IMQdisabled -eq 0 -o $IFBdisabled -eq 0 ] && ifconfig ${ifaceq} up txqueuelen 5 + tc qdisc del dev ${ifaceq} root + tc qdisc add dev ${ifaceq} root handle 1: hfsc default 10 + tc class add dev ${ifaceq} parent 1: classid 1:1 hfsc sc rate ${UploadRate}kbit ul rate ${UploadRate}kbit + echo "${ReservedClass}:${ReservedPriority}:${ReservedAverageRate}:${ReservedPacketSize}:${ReservedDelay}:${ReservedRatio}" | awk \ + -v device="${ifaceq}" \ + -v linespeed="${UploadRate}" \ + -f firewall/tcrules.awk \ + | while read CMD; do $CMD; done + tc filter del dev ${ifaceq} parent 1: protocol ip pref 1 fw + done + fi + + for ifacein in $InternalDevice; do + if [ ${UploadRate} -gt 0 ]; then + if [ $IMQdisabled -eq 0 ]; then + for ifaceq in ${IQdevice}; do + $IPTABLES -t mangle -D PREROUTING -i $ifacein -j IMQ --todev ${ifaceq:3:1} + $IPTABLES -t mangle -I PREROUTING 1 -i $ifacein -j IMQ --todev ${ifaceq:3:1} + done + fi + fi + ifconfig $ifacein up txqueuelen 5 + tc qdisc del dev $ifacein root + tc qdisc add dev $ifacein root handle 1: hfsc default 10 + tc class add dev $ifacein parent 1: classid 1:1 hfsc sc rate ${DownloadRate}kbit ul rate ${DownloadRate}kbit echo "${ReservedClass}:${ReservedPriority}:${ReservedAverageRate}:${ReservedPacketSize}:${ReservedDelay}:${ReservedRatio}" | awk \ - -v device="${ifaceq}" \ - -v linespeed="${UploadRate}" \ + -v device="$ifacein" \ + -v linespeed="${DownloadRate}" \ -f firewall/tcrules.awk \ | while read CMD; do $CMD; done - tc filter del dev ${ifaceq} parent 1: protocol ip pref 1 fw + tc filter del dev $ifacein parent 1: protocol ip pref 1 fw + if [ ${UploadRate} -gt 0 ]; then + if [ $IFBdisabled -eq 0 ]; then + tc qdisc add dev $ifacein handle ffff: ingress + for ifaceq in ${IQdevice}; do + tc filter add dev $ifacein parent ffff: protocol ip prio 1 u32 \ + match u32 0 0 flowid 1:1 \ + action connmark \ + action mirred egress redirect dev ${ifaceq} + done + fi + fi done + # -------------------------------------------------------------------------- fi - for ifacein in $InternalDevice; do - if [ ${UploadRate} -gt 0 ]; then - if [ $IMQdisabled -eq 0 ]; then - for ifaceq in ${IQdevice}; do - $IPTABLES -t mangle -D PREROUTING -i $ifacein -j IMQ --todev ${ifaceq:3:1} - $IPTABLES -t mangle -I PREROUTING 1 -i $ifacein -j IMQ --todev ${ifaceq:3:1} - done - fi - fi - ifconfig $ifacein up txqueuelen 5 - tc qdisc del dev $ifacein root - tc qdisc add dev $ifacein root handle 1: hfsc default 10 - tc class add dev $ifacein parent 1: classid 1:1 hfsc sc rate ${DownloadRate}kbit ul rate ${DownloadRate}kbit - echo "${ReservedClass}:${ReservedPriority}:${ReservedAverageRate}:${ReservedPacketSize}:${ReservedDelay}:${ReservedRatio}" | awk \ - -v device="$ifacein" \ - -v linespeed="${DownloadRate}" \ - -f firewall/tcrules.awk \ - | while read CMD; do $CMD; done - tc filter del dev $ifacein parent 1: protocol ip pref 1 fw - if [ ${UploadRate} -gt 0 ]; then - if [ $IFBdisabled -eq 0 ]; then - tc qdisc add dev $ifacein handle ffff: ingress - for ifaceq in ${IQdevice}; do - tc filter add dev $ifacein parent ffff: protocol ip prio 1 u32 \ - match u32 0 0 flowid 1:1 \ - action connmark \ - action mirred egress redirect dev ${ifaceq} - done - fi - fi - done - # -------------------------------------------------------------------------- + ( + echo RouteOnly=$RouteOnly + echo DNSAddr=$DNSAddr + echo IncludePorts=$IncludePorts + echo ExcludePorts=$ExcludePorts + echo AllowedWebHosts=$AllowedWebHosts + echo ExternalDevice=$ExternalDevice + echo InternalDevice=$InternalDevice + echo LocalNetwork=$LocalNetwork + echo GatewayPort=$GatewayPort + echo ProxyPort=$ProxyPort + echo AuthServiceIP=$AuthServiceIP + echo MembersOnly=$MembersOnly + echo MaxSegmentSize=$MaxSegmentSize + echo MasqueradeDevice=$MasqueradeDevice + echo AvoidMasqueradeAuthServiceIP=$AvoidMasqueradeAuthServiceIP + echo IMQdevice=$IMQdevice + echo IFBdevice=$IFBdevice + echo UploadRate=$UploadRate + echo DownloadRate=$DownloadRate + echo UserDelay=$UserDelay + echo UserPriority=$UserPriority + echo UserUploadRate=$UserUploadRate + echo UserPacketSize=$UserPacketSize + echo UserAverageRate=$UserAverageRate + echo UserDownloadRate=$UserDownloadRate + echo ReservedRatio=$ReservedRatio + echo ReservedClass=$ReservedClass + echo ReservedDelay=$ReservedDelay + echo ReservedPriority=$ReservedPriority + echo ReservedPacketSize=$ReservedPacketSize + echo ReservedAverageRate=$ReservedAverageRate + echo EnableBandwidthLimits=$EnableBandwidthLimits + echo FullPrivateNetwork=$FullPrivateNetwork + echo BlockRFC1918=$BlockRFC1918 + echo EnableIpset=$EnableIpset + echo EnableIpsetAuth=$EnableIpsetAuth + echo DosPrevention=$DosPrevention + echo DosAllowTries=$DosAllowTries + echo DosTimeInterval=$DosTimeInterval + ) > /tmp/nodog_fw.cur.env } access_fw() { cmd=$1 - mac=$2 - mac=`echo $2 | tr '[A-Z]' '[a-z]'` + mac=`tr '[A-Z]' '[a-z]' </dev/null + # ----------------------------------------------------------------------------------------------------- fi - # ----------------------------------------------------------------------------------------------------- - # this command often give this message 'iptables: Bad rule (does a matching rule exist in that chain?)' - # ----------------------------------------------------------------------------------------------------- - $IPTABLES -t filter -D NoCat_Inbound -d $ip -j ACCEPT 2>/dev/null - # ----------------------------------------------------------------------------------------------------- - if [ $EnableBandwidthLimits -gt 0 ]; then clearQoS $Ip $Netmask fi fi - # Mark outbound traffic from this node. - if [ "$mac" == "00:00:00:00:00:00" ]; then - if [ -z "$7" -o "$7" = "$ifacein" ]; then - $IPTABLES -t mangle $cmd NoCat_Permit -s $ip -j MARK --set-mark $mark + if [ "$EnableIpset" = 1 ]; then + if [ "$cmd" = "-A" ]; then + ipsetcmd=add + else + ipsetcmd=del fi + if [ "$EnableIpsetAuth" = "bitmap:ip,mac" ]; then + if [ "$action" = "deny" ]; then + networkMatchIP $ip "$LocalNetwork" netid + [ $? -eq 0 ] || exit 1 + $IPSET del -exist ND_s_notify $ip + fi + $IPSET $ipsetcmd "ND_s_permit_in_${mark}_$netid" $ip,$mac || exit 2 + elif [ "$EnableIpsetAuth" = "hash:ip,mac" ]; then + $IPSET $ipsetcmd "ND_s_permit_in_$mark" $ip,$mac || exit 2 + elif [ "$EnableIpsetAuth" = "hash:ip" ]; then + $IPSET $ipsetcmd "ND_s_permit_in_$mark" $ip || exit 2 + else + $IPSET $ipsetcmd "ND_s_permit_in_$mark" $mac || exit 2 + fi + $IPSET $ipsetcmd ND_s_permit_ou $ip else - if [ -z "$7" -o "$7" = "$ifacein" ]; then - $IPTABLES -t mangle $cmd NoCat_Permit -s $ip -m mac --mac-source $mac -j MARK --set-mark $mark + # Mark outbound traffic from this node. + if [ "$mac" == "00:00:00:00:00:00" ]; then + if [ -z "$7" -o "$7" = "$ifacein" ]; then + $IPTABLES -t mangle $cmd ND_m_permit_in -s $ip -j MARK --set-mark $mark || exit 2 + fi + else + if [ -z "$7" -o "$7" = "$ifacein" ]; then + $IPTABLES -t mangle $cmd ND_m_permit_in -s $ip -m mac --mac-source $mac -j MARK --set-mark $mark || exit 2 + fi fi + + # Mark inbound traffic to this node. + $IPTABLES -t filter $cmd ND_f_permit_ou -d $ip -j ACCEPT || exit 2 fi - # Mark inbound traffic to this node. - $IPTABLES -t filter $cmd NoCat_Inbound -d $ip -j ACCEPT + if [ -x /usr/sbin/wifi-disassoc.sh -a "$mac" != "00:00:00:00:00:00" -a "$action" = "deny" ]; then + /usr/sbin/wifi-disassoc.sh "$mac" + fi if [ $EnableBandwidthLimits -gt 0 ]; then if [ "$action" = "deny" ]; then @@ -710,7 +879,10 @@ access_fw_check() { # (CMD) (MAC) (IP) (Class) (UserDownloadRate) (UserUploadRate) # ------------------------------------------------------------ # cmd=$1 - mac=`echo $2 | tr '[A-Z]' '[a-z]'` + mac=`tr '[A-Z]' '[a-z]' < /tmp/nodog_fw.$action } +notify_fw() { + cmd=$1 + mac=`tr '[A-Z]' '[a-z]' </dev/null [ $EnableBandwidthLimits -gt 0 ] || return @@ -817,33 +1034,14 @@ clear_fw() { reset_fw() { - $IPTABLES -t filter -D FORWARD -j NoCat 2>/dev/null - $IPTABLES -t nat -D PREROUTING -j NoCat_Capture 2>/dev/null + $IPTABLES -t filter -D FORWARD -j ND_f_fwd 2>/dev/null + $IPTABLES -t nat -D PREROUTING -j ND_n_pre 2>/dev/null if [ $RouteOnly -eq 0 ]; then - $IPTABLES -t nat -D POSTROUTING -j NoCat_NAT 2>/dev/null + $IPTABLES -t nat -D POSTROUTING -j ND_n_post 2>/dev/null fi - $IPTABLES -t mangle -D PREROUTING -j NoCat 2>/dev/null -} - -open_fw() { - - # $1 host list - - if [ "$1" ]; then - for host in $1; do - for port in 80 443; do - for ifaceout in $MasqueradeDevice; do - $nat -o $ifaceout -s $net -d $host -p tcp --dport $port -j MASQUERADE - done - - $redirect -s $net -d $host -p tcp --dport $port -j RETURN - $fwd -s $net -d $host -p tcp --dport $port -j ACCEPT - $fwd -d $net -s $host -p tcp --sport $port -j ACCEPT - done - done - fi + $IPTABLES -t mangle -D PREROUTING -j ND_m_pre 2>/dev/null } check_arp() { @@ -867,26 +1065,47 @@ do_cmd() { IPTABLES="echo iptables" fi - fwd="$IPTABLES -t filter -A NoCat" - ports="$IPTABLES -t filter -A NoCat_Ports" - local="$IPTABLES -t filter -A NoCat_LocalPorts" - nat="$IPTABLES -t nat -A NoCat_NAT" - redirect="$IPTABLES -t nat -A NoCat_Capture" - mangle="$IPTABLES -t mangle -A NoCat" + if [ -x /usr/sbin/ipset ]; then + IPSET=/usr/sbin/ipset + else + IPSET="echo ipset" + fi + + if [ "$1" != "initialize" -a -r /tmp/nodog_fw.cur.env ]; then + source /tmp/nodog_fw.cur.env + fi case "$1" in - arp) shift; check_arp "$@" ;; # (IP) - deny) shift; access_fw "-D" "$@" ;; # (CMD) (MAC) (IP) (Class) -# deny) shift; access_fw_check "-D" "$@" ;; # (CMD) (MAC) (IP) (Class) - clear) shift; clear_fw "$@" ;; - reset) shift; reset_fw "$@" ;; - permit) shift; access_fw "-A" "$@" ;; # (CMD) (MAC) (IP) (Class) (UserDownloadRate) (UserUploadRate) -# permit) shift; access_fw_check "-A" "$@" ;; # (CMD) (MAC) (IP) (Class) (UserDownloadRate) (UserUploadRate) - initialize) shift; initialize_fw "$1" ;; + arp) shift; check_arp "$@" ;; # (IP) + clear) shift; clear_fw "$@" ;; + reset) shift; reset_fw "$@" ;; + permit) shift; access_fw "-A" "$@" ;; # (CMD) (MAC) (IP) (Class) (UserDownloadRate) (UserUploadRate) +# permit) shift; access_fw_check "-A" "$@" ;; # (CMD) (MAC) (IP) (Class) (UserDownloadRate) (UserUploadRate) + deny) shift; access_fw "-D" "$@" ;; # (CMD) (MAC) (IP) (Class) +# deny) shift; access_fw_check "-D" "$@" ;; # (CMD) (MAC) (IP) (Class) + notify) shift; notify_fw "-A" "$@" ;; # (CMD) (MAC) (IP) + notified) shift; notify_fw "-D" "$@" ;; # (CMD) (MAC) (IP) + initialize) shift; initialize_fw "$1" ;; openlist) - $IPTABLES -t mangle -L NoCat_Permit -n | awk '/MARK set 0x2/{printf("%s\n", $4)}' | sort -u; -# $IPTABLES -t mangle -L NoCat_Permit -n | awk '/MARK set 0x2/{printf("%s\n", $4)}' | sort -u | tee /tmp/nodog_fw.lst; + if [ "$EnableIpset" = 1 ]; then + if [ "$EnableIpsetAuth" = "bitmap:ip,mac" ]; then + for net in $LocalNetwork; do + networkMatchIface $net ifacein netid + [ $? -eq 0 ] || exit 1 + $IPSET $ipsetcmd "ND_s_permit_in_2_$netid" + done + elif [ "$EnableIpsetAuth" = "hash:ip,mac" ]; then + $IPSET list "ND_s_permit_in_2" + elif [ "$EnableIpsetAuth" = "hash:ip" ]; then + $IPSET list "ND_s_permit_in_2" + else + $IPSET list "ND_s_permit_in_2" + fi + else + $IPTABLES -t mangle -L NoCat_Permit -n | awk '/MARK set 0x2/{printf("%s\n", $4)}' | sort -u; +# $IPTABLES -t mangle -L NoCat_Permit -n | awk '/MARK set 0x2/{printf("%s\n", $4)}' | sort -u | tee /tmp/nodog_fw.lst; + fi ;; esac } @@ -895,7 +1114,7 @@ do_cmd() { #----------------------------------- export RouteOnly MasqueradeDevice DNSAddr IncludePorts ExcludePorts AllowedWebHosts ExternalDevice \ - InternalDevice LocalNetwork GatewayPort AuthServiceIP MembersOnly MaxSegmentSize IPTABLES \ + InternalDevice LocalNetwork GatewayPort ProxyPort AuthServiceIP MembersOnly MaxSegmentSize IPTABLES \ EnableBandwidthLimits IMQdevice IFBdevice UserDelay UserPriority UserUploadRate UserPacketSize \ UserAverageRate UserDownloadRate UploadRate DownloadRate ReservedRatio ReservedClass ReservedDelay \ ReservedPriority ReservedAverageRate ReservedPacketSize DosPrevention DosAllowTries DosTimeInterval \ @@ -910,74 +1129,82 @@ export RouteOnly MasqueradeDevice DNSAddr IncludePorts ExcludePorts AllowedWebHo # ------------------------------------------------------------ # --------------------------------------------------------------------------------------------------------------------------------------------------- -# RouteOnly Required only if you DO NOT want your gateway to act as a NAT. Give this only if you're running a strictly routed -# network, and don't need the gateway to enable NAT for you +# RouteOnly Required only if you DO NOT want your gateway to act as a NAT. Give this only if you're running a strictly routed +# network, and don't need the gateway to enable NAT for you # -# DNSAddr *If* you choose not to run DNS on your internal network, specify the address(es) of one or more domain name server -# on the Internet that wireless clients can use to get out. Should be the same DNS that your DHCP server hands out +# DNSAddr *If* you choose not to run DNS on your internal network, specify the address(es) of one or more domain name server +# on the Internet that wireless clients can use to get out. Should be the same DNS that your DHCP server hands out # -# IncludePorts Specify TCP ports to allow access to when public class users login. All others will be denied +# IncludePorts Specify TCP ports to allow access to when public class users login. All others will be denied # -# ExcludePorts Specify TCP ports to denied access to when public class users login. All others will be allowed. Note that you should -# use either IncludePorts or ExcludePorts, but not both. If neither is specified, access is granted to all ports to public class users. -# You should *always* exclude port 25, unless you want to run an portal for wanton spam sending. Users should have their -# own way of sending mail. It sucks, but that's the way it is. Comment this out *only if* you're using IncludePorts instead +# ExcludePorts Specify TCP ports to denied access to when public class users login. All others will be allowed. Note that you +# should use either IncludePorts or ExcludePorts, but not both. If neither is specified, access is granted to all ports +# to public class users. You should *always* exclude port 25, unless you want to run an portal for wanton spam sending. +# Users should have their own way of sending mail. It sucks, but that's the way it is. Comment this out *only if* +# you're using IncludePorts instead # -# AllowedWebHosts List any domains that you would like to allow web access (TCP port 80 and 443) BEFORE logging in (this is the -# pre-'skip' stage, so be careful about what you allow +# AllowedWebHosts List any domains that you would like to allow web access (TCP port 80 and 443) BEFORE logging in (this is thei +# pre-'skip' stage, so be careful about what you allow # -# ExternalDevice The interface connected to the Internet. Usually 'eth0' or 'eth1' under Linux, or maybe even 'ppp0' if you're running PPP or PPPoE +# ExternalDevice The interface connected to the Internet. Usually 'eth0' or 'eth1' under Linux, or maybe even 'ppp0' if you're running +# PPP or PPPoE # -# InternalDevice Required if and only if your machine has more than two network interfaces. Must be set to the interface connected to your local -# network, normally your wireless card +# InternalDevice Required if and only if your machine has more than two network interfaces. Must be set to the interface connected to +# your local network, normally your wireless card # -# LocalNetwork Must be set to the network address and net mask of your internal network. You can use the number of bits in the netmask -# (e.g. /16, /24, etc.) or the full x.x.x.x specification +# LocalNetwork Must be set to the network address and net mask of your internal network. You can use the number of bits in the +# netmask (e.g. /16, /24, etc.) or the full x.x.x.x specification # -# GatewayPort The TCP port to bind the gateway service to. 5280 is de-facto standard for NoCatAuth. Change this only if you absolutely need to +# GatewayPort The TCP port to bind the gateway service to. 5280 is de-facto standard for NoCatAuth. Change this only if you +# absolutely need to # -# AuthServiceIP The address of your authentication service. You must use an IP address if DNS resolution isn't available at gateway startup +# ProxyPort The TCP port to bind the proxy service to. If not defined is set to GatewayPort # -# MembersOnly Give this if you want to disable public access (i.e. unauthenticated 'skip' button access). You'll also want to -# point AuthServiceIP somewhere that doesn't include a skip button (likeat your own Auth server) +# AuthServiceIP The address of your authentication service. You must use an IP address if DNS resolution isn't available at gateway +# startup # -# MaxSegmentSize Give this if you want to reduce MTU +# MembersOnly Give this if you want to disable public access (i.e. unauthenticated 'skip' button access). You'll also want to +# point AuthServiceIP somewhere that doesn't include a skip button (likeat your own Auth server) # -# MasqueradeDevice maschera il traffico verso il device -# AvoidMasqueradeAuthServiceIP evita di mascherare il traffico verso portale autorizzativo +# MaxSegmentSize Give this if you want to reduce MTU +# MasqueradeDevice maschera il traffico verso il device +# AvoidMasqueradeAuthServiceIP evita di mascherare il traffico verso portale autorizzativo # --------------------------------------------------------------------------------------------------------------------------------------------------- RouteOnly=${RouteOnly:-0} MembersOnly=${MembersOnly:-1} GatewayPort=${GatewayPort:-5280} +ProxyPort=${ProxyPort:-$GatewayPort} MaxSegmentSize=${MaxSegmentSize:-1} AvoidMasqueradeAuthServiceIP=${AvoidMasqueradeAuthServiceIP:-0} # --------------------------------------------------------------------------------------------------------------------------------------------------- # Gestione dei limiti sulla banda per gli utenti # --------------------------------------------------------------------------------------------------------------------------------------------------- -# IMQdevice IMQ device per la gestione del bitrate in upload -# IFBdevice IFB device per la gestione del bitrate in upload -# UploadRate Upload bit rate per le interfacce interne (in Kbits) -# DownloadRate Download bit rate per le interfacce interne (in Kbits) -# UserDelay delay accettabile per il traffico utente (default 100, in millisecondi) -# UserPriority priorita' del traffico degli utenti (default 5) -# UserUploadRate Bit rate in upload di default per gli utenti (in Kbits) -# UserPacketSize dimensione massima del pacchetto sull'interfaccia (default 1500, in bytes) -# UserAverageRate rate medio per il traffico (default 10) +# IMQdevice IMQ device per la gestione del bitrate in upload +# IFBdevice IFB device per la gestione del bitrate in upload +# UploadRate Upload bit rate per le interfacce interne (in Kbits) +# DownloadRate Download bit rate per le interfacce interne (in Kbits) +# UserDelay delay accettabile per il traffico utente (default 100, in millisecondi) +# UserPriority priorita' del traffico degli utenti (default 5) +# UserUploadRate Bit rate in upload di default per gli utenti (in Kbits) +# UserPacketSize dimensione massima del pacchetto sull'interfaccia (default 1500, in bytes) +# UserAverageRate rate medio per il traffico (default 10) # UserDownloadRate Bit rate in download di default per gli utenti (in Kbits) # ReservedRatio percentuale di banda riservata # ReservedClass classId da utilizzare per il qos (default 1) # ReservedDelay delay accettabile per il traffico riservato (default 200, in millisecondi) # ReservedPriority priorita' per il traffico riservato (default 1, bassa priorita') # ReservedPacketSize dimensione massima del pacchetto sull'interfaccia (default 1500, in bytes) -# ReservedAverageRate rate medio per il traffico riservato atto al dimensionamento dei parametri di coda (default 1) -# EnableBandwidthLimits abilita la gestione dei limiti sulla banda per gli utenti -# FullPrivateNetwork la rete privata utilizzata internamente -# BlockRFC1918 blocca il travvico verso le reti private +# ReservedAverageRate rate medio per il traffico riservato atto al dimensionamento dei parametri di coda (default 1) +# EnableBandwidthLimits abilita la gestione dei limiti sulla banda per gli utenti +# FullPrivateNetwork la rete privata utilizzata internamente +# BlockRFC1918 blocca il travvico verso le reti private +# EnableIpset utilizza ipset per ottimizzazioni +# EnableIpsetAuth modalita di autorizzazione sui pacchetti sorgenti: "bitmap:ip,mac", "hash:ip", "hash:ip,mac", "hash:mac" default "bitmap:ip,mac" # # DosPrevention abilita il supporto anti DoS sul captive portal (da impostare ad 1 per attivare il supporto) # DosAllowTries numero massimo di connessioni consentite nella finestra temporale -# DosTimeInterval finestra temporale in cui osservare il numero di connessioni per IP +# DosTimeInterval finestra temporale in cui osservare il numero di connessioni per IP # --------------------------------------------------------------------------------------------------------------------------------------------------- IFBdevice=${IFBdevice:-ifb0} UploadRate=${UploadRate:-10240} @@ -995,14 +1222,16 @@ ReservedPriority=${ReservedPriority:-1} ReservedPacketSize=${ReservedPacketSize:-1500} ReservedAverageRate=${ReservedAverageRate:-1} EnableBandwidthLimits=${EnableBandwidthLimits:-0} -FullPrivateNetwork=${FullPrivateNetwork:-192.168.0.0/16} +FullPrivateNetwork=${FullPrivateNetwork:-172.16.0.0/12} BlockRFC1918=${BlockRFC1918:-1} +EnableIpset=${EnableIpset:-0} +EnableIpsetAuth=${EnableIpsetAuth:-bitmap:ip,mac} DosPrevention=${DosPrevention:-0} DosAllowTries=${DosAllowTries:-5} DosTimeInterval=${DosTimeInterval:-60} -# ( +# { # echo "ENVIRONMENT:" # echo "-----------------------------------------------------------" # env @@ -1013,4 +1242,6 @@ DosTimeInterval=${DosTimeInterval:-60} do_cmd "$@" # set +x # echo "-----------------------------------------------------------" -# ) 2>/tmp/nodog_fw.$$ >&2 +# } 2>/tmp/nodog_fw.$$ >&2 + +exit 0 diff --git a/tests/examples/nocat/firewall/nodog.fw.old b/tests/examples/nocat/firewall/nodog.fw.old new file mode 100644 index 00000000..4fd36398 --- /dev/null +++ b/tests/examples/nocat/firewall/nodog.fw.old @@ -0,0 +1,1016 @@ +#!/bin/sh + +# nodog.fw + +networkMatchIface_do() { + awk -f - $* </dev/null; then + #ip addr show dev $iface | awk '/inet/{print $2}' | while read ip; do + ip route show | grep "dev $iface " | awk '{print $1}' | while read ip; do + networkMatchIface_do $net $ip + match=$? + if [ $match -eq 1 -o $match -eq 2 ]; then + exit 1 + fi + done + match=$? + else + #ifconfig $iface | awk '/inet/{i=$2;n=$4;gsub("^[^:]*:","",i);gsub("^[^:]*:","",n);print i" "n}' | while read ip nm; do + route | awk '{if($8=="$iface"){print $1" "$3}}' | while read ip nm; do + networkMatchIface_do $net $ip $nm + if [ $match -eq 1 -o $match -eq 2 ]; then + exit 1 + fi + done + match=$? + fi + return $match +} + +loadKernelModules() { + + for module in $1; do + lsmod | grep $module >/dev/null 2>&1 + if [ $? -ne 0 ]; then + insmod $module 2>/dev/null + fi + done +} + +clearQoS() { + + # 1 => Ip + # 2 => Netmask + + for ifaceq in $IQdevice; do + tc -p filter show dev ${ifaceq} | awk -v "i=$1/$2" ' + /^ /{ t=t $0; next } + { if(t && index(t,i) && match(t," pref [0-9]+ ")){ print substr(t,RSTART+6,RLENGTH-7) }; t=$0 } + END { if(t && index(t,i) && match(t," pref [0-9]+ ")){ print substr(t,RSTART+6,RLENGTH-7) } } + ' | while read UserClass; do + if [ -n "${UserClass}" ]; then + if [ ${UploadRate} -gt 0 ]; then + tc filter del dev ${ifaceq} parent 1: pref ${UserClass} protocol ip u32 match ip src $1/$2 classid 1:${UserClass}0 + echo "${UserClass}:1:1:1:1:1" | awk \ + -v device="${ifaceq}" \ + -v linespeed="${UploadRate}" \ + -f firewall/tcrules.awk \ + | sed 's/ add / del /g' | sed 'x;1!H;$!d;x' | while read CMD; do $CMD; done + fi + for ifacein in $InternalDevice; do + tc filter del dev $ifacein parent 1: pref ${UserClass} protocol ip u32 match ip dst $1/$2 classid 1:${UserClass}0 + echo "${UserClass}:1:1:1:1:1" | awk \ + -v device="$ifacein" \ + -v linespeed="${DownloadRate}" \ + -f firewall/tcrules.awk \ + | sed 's/ add / del /g' | sed 'x;1!H;$!d;x' | while read CMD; do $CMD; done + done + fi + done + done +} + +checkDeviceUpload() { + + if [ -z "$IMQdevice" ]; then + IMQdisabled=1 + else + IMQdisabled=0 + IQdevice=$IMQdevice + fi + if [ -z "$IFBdevice" ]; then + IFBdisabled=1 + else + IFBdisabled=0 + IQdevice=$IFBdevice + fi + if [ -z "$IQdevice" ]; then + IQdevice=$ExternalDevice + fi +} + +#----------------------------------- +# START FUNCTION +#----------------------------------- +initialize_fw() { + + #--------------------------------------------------------------- + # Enable IP routing. Required if your firewall is protecting a + # network, NAT included + #--------------------------------------------------------------- + echo "1" > /proc/sys/net/ipv4/ip_forward + #--------------------------------------------------------------- + # Disable routing triangulation. Respond to queries out + # the same interface, not another. Helps to maintain state + # Also protects against IP spoofing + #--------------------------------------------------------------- + echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter + + # Load all the kernel modules we need + loadKernelModules "ipt_TOS xt_mac ipt_ACCOUNT" + + clear_fw + + # Flush all user-defined chains + + $IPTABLES -t filter -N NoCat 2>/dev/null + $IPTABLES -t filter -F NoCat + $IPTABLES -t filter -A NoCat -p tcp -m conntrack --ctstate INVALID -j DROP || $IPTABLES -t filter -A NoCat -p tcp -m state --state INVALID -j DROP + for ifacein in $InternalDevice; do + for ifaceout in $ExternalDevice; do + $IPTABLES -t filter -D FORWARD -i $ifacein -o $ifaceout -j NoCat 2>/dev/null + $IPTABLES -t filter -D FORWARD -i $ifaceout -o $ifacein -j NoCat 2>/dev/null + $IPTABLES -t filter -A FORWARD -i $ifacein -o $ifaceout -j NoCat + $IPTABLES -t filter -A FORWARD -i $ifaceout -o $ifacein -j NoCat + done + done + + if [ "$BlockRFC1918" = 1 ]; then + $IPTABLES -t filter -N NoCat_RFC1918 2>/dev/null + $IPTABLES -t filter -F NoCat_RFC1918 + for net in $FullPrivateNetwork; do + $IPTABLES -t filter -A NoCat_RFC1918 -d $net -j ACCEPT + done + $IPTABLES -t filter -A NoCat_RFC1918 -d 10.0.0.0/8 -j RETURN + $IPTABLES -t filter -A NoCat_RFC1918 -d 172.16.0.0/12 -j RETURN + $IPTABLES -t filter -A NoCat_RFC1918 -d 192.168.0.0/16 -j RETURN + $IPTABLES -t filter -A NoCat_RFC1918 -d 127.0.0.0/8 -j RETURN + $IPTABLES -t filter -A NoCat_RFC1918 -j ACCEPT + fi + + $IPTABLES -t filter -N NoCat_Ports 2>/dev/null + $IPTABLES -t filter -F NoCat_Ports + $IPTABLES -t filter -D NoCat -j NoCat_Ports 2>/dev/null + $IPTABLES -t filter -A NoCat -j NoCat_Ports + + $IPTABLES -t filter -N NoCat_Inbound 2>/dev/null + $IPTABLES -t filter -F NoCat_Inbound + $IPTABLES -t filter -D NoCat -j NoCat_Inbound 2>/dev/null + $IPTABLES -t filter -A NoCat -j NoCat_Inbound + + $IPTABLES -t nat -N NoCat_Capture 2>/dev/null + $IPTABLES -t nat -F NoCat_Capture + $IPTABLES -t nat -D PREROUTING -j NoCat_Capture 2>/dev/null + $IPTABLES -t nat -A PREROUTING -j NoCat_Capture + + $IPTABLES -t nat -N NoCat_NAT 2>/dev/null + $IPTABLES -t nat -F NoCat_NAT + + # Only nat if we're not routing + + $IPTABLES -t nat -D POSTROUTING -j NoCat_NAT 2>/dev/null + [ $RouteOnly -gt 0 ] || $IPTABLES -t nat -A POSTROUTING -j NoCat_NAT + + $IPTABLES -t mangle -N NoCat 2>/dev/null + $IPTABLES -t mangle -F NoCat + $IPTABLES -t mangle -N NoCat_Permit 2>/dev/null + $IPTABLES -t mangle -F NoCat_Permit + $IPTABLES -t mangle -D PREROUTING -j NoCat 2>/dev/null + $IPTABLES -t mangle -A PREROUTING -j NoCat + + if [ $MembersOnly -gt 0 ]; then + classes="1 2" + else + classes="1 2 3" + fi + + # Handle tagged traffic. The current service classes by fwmark are: + # ----------------------------------------------------------------- + # 1: Owner + # 2: Co-op + # 3: Public + # 4: Free + # ----------------------------------------------------------------- + for iface in $InternalDevice; do + ifaceinout=0 + for ifaceout in $ExternalDevice; do + if [ "$iface" == "$ifaceout" ]; then + ifaceinout=1 + fi + done + + for net in $LocalNetwork; do + networkMatchIface $iface $net + [ $? -eq 1 ] || continue + + # check se evitare il mascheramento del traffico verso portale autorizzativo + if [ "$AvoidMasqueradeAuthServiceIP" = "1" ]; then + for ifaceout in $MasqueradeDevice; do + $nat -o $ifaceout -s $net -d $AuthServiceIP -j RETURN + done + fi + + for fwmark in $classes; do + # Only forward tagged traffic per class + if [ "$BlockRFC1918" = 1 ]; then + $fwd -i $iface -s $net -m mark --mark $fwmark -j NoCat_RFC1918 + else + $fwd -i $iface -s $net -m mark --mark $fwmark -j ACCEPT + fi + + # Masquerade permitted connections. + for ifaceout in $MasqueradeDevice; do + $nat -o $ifaceout -s $net -m mark --mark $fwmark -j MASQUERADE + done + done + if [ $MembersOnly -gt 0 ]; then + for ifaceout in $MasqueradeDevice; do + $nat -o $ifaceout -s $net -m mark --mark 3 -j MASQUERADE + done + fi + + # Allow web traffic to the specified hosts, and don't capture connections intended for them + open_fw "$AuthServiceIP $1 $AllowedWebHosts" + + # Accept forward and back traffic to/from DNSAddr + if [ "$DNSAddr" ]; then + dns_item="" + for dns in $DNSAddr; do + $fwd -o $iface -d $net -s $dns -j ACCEPT + + for prot in tcp udp; do + $fwd -i $iface -s $net -d $dns -p $prot --dport 53 -j ACCEPT + $nat -p $prot -s $net -d $dns --dport 53 -j MASQUERADE + + # allow authenticated DNS traffic through this server. + $redirect -i $iface -m mark --mark 4 -p $prot --dport 53 -s $net -d $dns -j RETURN + done + dns_item=$dns + done + # Force unauthenticated DNS traffic through this server. + # Of course, only the first rule of this type will match. + # But it's easier to leave them all in ATM. + for prot in tcp udp; do + $redirect -i $iface -m mark --mark 4 -p $prot --dport 53 -s $net -j DNAT --to-destination $dns_item:53 + done + else + for prot in tcp udp; do + $redirect -i $iface -m mark --mark 4 -p $prot --dport 53 -s $net -j REDIRECT --to-port 53 + done + fi + for prot in tcp udp; do + $redirect -i $iface -d $FullPrivateNetwork -p $prot --dport 53 -s $net -j REDIRECT --to-port 53 + done + + if [ "$ifaceinout" == "1" ]; then + # Set packets from internal devices to fw mark 4, or 'denied', by default. + $mangle -i $iface -s $net -j MARK --set-mark 4 + $mangle -i $iface -j NoCat_Permit + fi + done + + if [ "$ifaceinout" != "1" ]; then + # Set packets from internal devices to fw mark 4, or 'denied', by default + $mangle -i $iface -j MARK --set-mark 4 + $mangle -i $iface -j NoCat_Permit + fi + done + + # Redirect outbound non-auth web traffic to the local gateway process except to windowsupdate.microsoft.com, which is broken. + # If MembersOnly is active, then redirect public class as well + # + #if [ $MembersOnly -gt 0 ]; then + # nonauth="3 4" + #else + nonauth="4" + #fi + + for iface in $InternalDevice; do + for mark in $nonauth; do + $redirect -m mark --mark $mark -i $iface -p tcp --dport 80 -j REDIRECT --to-port $GatewayPort + done + done + + # Lock down more ports for public users, if specified. Port restrictions are not applied to co-op and owner class users + # + # There are two philosophies in restricting access: + # + # That Which Is Not Specifically Permitted Is Denied + # That Which Is Not Specifically Denied Is Permitted + # + # If "IncludePorts" is defined, the default policy will be to deny all traffic, and only allow the ports mentioned + # If "ExcludePorts" is defined, the default policy will be to allow all traffic, except to the ports mentioned + # + # If both are defined, ExcludePorts will be ignored, and the default policy + # will be to deny all traffic, allowing everything in IncludePorts, and issue a warning + + if [ "$IncludePorts" ]; then + if [ "$ExcludePorts" ]; then + echo "WARNING: ExcludePorts and IncludePorts are both defined" + echo "Ignoring 'ExcludePorts'. Please check your configuration" + fi + + # Enable all ports in IncludePorts + for iface in $InternalDevice; do + for port in $IncludePorts; do + $ports -p tcp -i $iface --dport $port -m mark --mark 3 -j ACCEPT + $ports -p udp -i $iface --dport $port -m mark --mark 3 -j ACCEPT + done + + # Always permit access to the GatewayPort (or we can't logout) + $ports -p tcp -i $iface --dport $GatewayPort -j ACCEPT + $ports -p udp -i $iface --dport $GatewayPort -j ACCEPT + + # ...and disable access to the rest + $ports -p tcp -i $iface -m mark --mark 3 -j DROP + $ports -p udp -i $iface -m mark --mark 3 -j DROP + + # supporto anti DoS sul captive portal + if [ $DosPrevention -gt 0 ]; then + $local -p tcp -i $iface --dport $GatewayPort -m state --state NEW -m recent --set --name NoCat + $local -p tcp -i $iface --dport $GatewayPort -m state --state NEW -m recent --update --name NoCat \ + --seconds $DosTimeInterval --hitcount `expr $DosAllowTries + 1` -j DROP + fi + done + + elif [ "$ExcludePorts" ]; then + # If ExcludePorts has entries, simply deny access to them + for iface in $InternalDevice; do + for port in $ExcludePorts; do + $ports -p tcp -i $iface --dport $port -m mark --mark 3 -j DROP + $ports -p udp -i $iface --dport $port -m mark --mark 3 -j DROP + done + done + fi + + # Disable access on the external to GatewayPort from anything but the AuthServiceIP + for src in $AuthServiceIP; do + for ifaceout in $ExternalDevice; do + $fwd -i $ifaceout ! -s $src -p tcp --dport $GatewayPort -j DROP + done + done + + # Filter policy + $fwd -j DROP + + # -------------------------------------------------------------------------------------------------------------------------------------------------- + # Automatically sets the proper value of MSS (Maximum Segment Size) of TCP SYN packets that the firewall sees of all outgoing packets. + # -------------------------------------------------------------------------------------------------------------------------------------------------- + # The MSS value is used to control the maximum size of packets for specific connections. Under normal circumstances, this means the size of + # the MTU (Maximum Transfer Unit) value, minus 40 bytes. This is used to overcome some ISP's and servers that block ICMP fragmentation needed + # packets, which can result in really weird problems which can mainly be described such that everything works perfectly from your firewall/router, + # but your local hosts behind the firewall can't exchange large packets. This could mean such things as mail servers being able to send small mails, + # but not large ones, web browsers that connect but then hang with no data received, and ssh connecting properly, but scp hangs after the initial + # handshake. In other words, everything that uses any large packets will be unable to work. + # -------------------------------------------------------------------------------------------------------------------------------------------------- + # Normal MTU for ethernet is 1500 bytes, therefore minus 40 bytes MSS is 1460 bytes. MSS only has to be set properly in the SYN packet. + # -------------------------------------------------------------------------------------------------------------------------------------------------- + # The --clamp-mss-to-pmtu automatically sets the MSS to the proper value, hence you don't need to explicitly set it. It is automatically set to PMTU + # (Path Maximum Transfer Unit) minus 40 bytes, which should be a reasonable value for most applications. + # -------------------------------------------------------------------------------------------------------------------------------------------------- + + if [ $MaxSegmentSize -gt 0 ]; then + for iface in $ExternalDevice; do + $IPTABLES -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o $iface -j TCPMSS --clamp-mss-to-pmtu + done + fi + + # Account traffic + $IPTABLES -t mangle -N AccountIn 2>/dev/null + $IPTABLES -t mangle -F AccountIn + $IPTABLES -t mangle -N AccountOu 2>/dev/null + $IPTABLES -t mangle -F AccountOu + + for iface in $InternalDevice; do + $IPTABLES -t mangle -D POSTROUTING -o $iface -j AccountIn 2>/dev/null + $IPTABLES -t mangle -A POSTROUTING -o $iface -j AccountIn + done + + for iface in $ExternalDevice; do + $IPTABLES -t mangle -D POSTROUTING -o $iface -j AccountOu 2>/dev/null + $IPTABLES -t mangle -A POSTROUTING -o $iface -j AccountOu + done + + for srv in "$AuthServiceIP"; do + $IPTABLES -t mangle -A AccountIn -s "$srv" -j RETURN + $IPTABLES -t mangle -A AccountOu -d "$srv" -j RETURN + done + + for net in $LocalNetwork; do + $IPTABLES -t mangle -A AccountIn -s "$net" -j RETURN + $IPTABLES -t mangle -A AccountOu -d "$net" -j RETURN + $IPTABLES -t mangle -A AccountIn -j ACCOUNT --addr "$net" --tname "$net" + $IPTABLES -t mangle -A AccountOu -j ACCOUNT --addr "$net" --tname "$net" + done + # -------------------------------------------------------------------------- + + [ -S /tmp/evfwdsock ] && /usr/sbin/fwevhandler i + + # Bandwidth limits + # -------------------------------------------------------------------------- + [ $EnableBandwidthLimits -gt 0 ] || return + + if [ $IMQdisabled -eq 0 ]; then + extra_modules=ipt_IMQ + fi + if [ $IFBdisabled -eq 0 ]; then + extra_modules="ifb em_u32 act_connmark act_mirred sch_ingress" + fi + + loadKernelModules "xt_CONNMARK xt_CLASSIFY sch_red sch_sfq sch_hfsc cls_basic cls_fw cls_u32 $extra_modules" + + if [ ${UploadRate} -gt 0 ]; then + for ifaceq in ${IQdevice}; do + [ $IMQdisabled -eq 0 -o $IFBdisabled -eq 0 ] && ifconfig ${ifaceq} up txqueuelen 5 + tc qdisc del dev ${ifaceq} root + tc qdisc add dev ${ifaceq} root handle 1: hfsc default 10 + tc class add dev ${ifaceq} parent 1: classid 1:1 hfsc sc rate ${UploadRate}kbit ul rate ${UploadRate}kbit + echo "${ReservedClass}:${ReservedPriority}:${ReservedAverageRate}:${ReservedPacketSize}:${ReservedDelay}:${ReservedRatio}" | awk \ + -v device="${ifaceq}" \ + -v linespeed="${UploadRate}" \ + -f firewall/tcrules.awk \ + | while read CMD; do $CMD; done + tc filter del dev ${ifaceq} parent 1: protocol ip pref 1 fw + done + fi + + for ifacein in $InternalDevice; do + if [ ${UploadRate} -gt 0 ]; then + if [ $IMQdisabled -eq 0 ]; then + for ifaceq in ${IQdevice}; do + $IPTABLES -t mangle -D PREROUTING -i $ifacein -j IMQ --todev ${ifaceq:3:1} + $IPTABLES -t mangle -I PREROUTING 1 -i $ifacein -j IMQ --todev ${ifaceq:3:1} + done + fi + fi + ifconfig $ifacein up txqueuelen 5 + tc qdisc del dev $ifacein root + tc qdisc add dev $ifacein root handle 1: hfsc default 10 + tc class add dev $ifacein parent 1: classid 1:1 hfsc sc rate ${DownloadRate}kbit ul rate ${DownloadRate}kbit + echo "${ReservedClass}:${ReservedPriority}:${ReservedAverageRate}:${ReservedPacketSize}:${ReservedDelay}:${ReservedRatio}" | awk \ + -v device="$ifacein" \ + -v linespeed="${DownloadRate}" \ + -f firewall/tcrules.awk \ + | while read CMD; do $CMD; done + tc filter del dev $ifacein parent 1: protocol ip pref 1 fw + if [ ${UploadRate} -gt 0 ]; then + if [ $IFBdisabled -eq 0 ]; then + tc qdisc add dev $ifacein handle ffff: ingress + for ifaceq in ${IQdevice}; do + tc filter add dev $ifacein parent ffff: protocol ip prio 1 u32 \ + match u32 0 0 flowid 1:1 \ + action connmark \ + action mirred egress redirect dev ${ifaceq} + done + fi + fi + done + # -------------------------------------------------------------------------- +} + +access_fw() { + + cmd=$1 + mac=$2 + mac=`echo $2 | tr '[A-Z]' '[a-z]'` + ip=$3 + class=$4 + + if [ -z "$class" ]; then + class=Public + fi + + if [ "$class" = "Owner" ]; then + mark=1 + elif [ "$class" = "Member" ]; then + mark=2 + elif [ "$class" = "Public" ]; then + mark=3 + else + echo "FATAL: Bad class: $class!" + exit 1 + fi + + local action="" + + if [ "$cmd" = "-A" ]; then + action="permit" + else + action="deny" + fi + + # Bandwidth limits + # -------------------------------------------------------------------------- + Ip="" + Netmask="" + UserUploadRatio=0 + UserDownloadRatio=0 + + if [ $EnableBandwidthLimits -gt 0 ]; then + + Ip=`echo $ip | sed 's!/.*!!'` + Netmask=`echo $ip | sed 's!^.*/!!'` + + if [ "$Ip" = "$Netmask" ]; then + Netmask=32 + fi + + checkDeviceUpload + + if [ "$action" = "permit" ]; then + if [ $5 -ne 0 ]; then + UserDownloadRate = $5 + fi + if [ $6 -ne 0 ]; then + UserUploadRate = $6 + fi + + UserUploadRatio=$(( $UserUploadRate * 100 / ${UploadRate} )) + UserDownloadRatio=$(( $UserDownloadRate * 100 / ${DownloadRate} )) + + if [ $UserUploadRatio -gt 100 ]; then + UserUploadRatio=100 + fi + if [ $UserDownloadRatio -gt 100 ]; then + UserDownloadRatio=100 + fi + fi + fi + + if [ "$action" = "permit" ]; then + tFOUND=0 + tDIRTY=0 + tFOUNDMARK="" + + # restituisce MAC + mark + $IPTABLES -t mangle -n -L NoCat_Permit | \ + awk -v i=$ip '/[ \t]MAC /{if($4==i){print tolower($7) " " $10};next } {if($4==i){print "00:00:00:00:00:00 " $8 }}' | \ + while read tMAC tMARK; + do + if [ "$tMAC" == "00:00:00:00:00:00" ]; then + if [ "$mac" == "00:00:00:00:00:00" ]; then + tFOUND=1 + tFOUNDMARK=$tMARK + else + tDIRTY=1 + $IPTABLES -t mangle -D NoCat_Permit -s $ip -j MARK --set-mark $tMARK + fi + else + if [ "$tMAC" == "$mac" ]; then + tFOUND=1 + tFOUNDMARK=$tMARK + else + tDIRTY=1 + $IPTABLES -t mangle -D NoCat_Permit -s $ip -m mac --mac-source $tMAC -j MARK --set-mark $tMARK + fi + fi + done + + [ $tDIRTY -eq 0 -a $tFOUND -eq 1 ] && return + + if [ $tFOUND -eq 1 ]; then + if [ "$mac" == "00:00:00:00:00:00" ]; then + $IPTABLES -t mangle -D NoCat_Permit -s $ip -j MARK --set-mark $tFOUNDMARK + else + $IPTABLES -t mangle -D NoCat_Permit -s $ip -m mac --mac-source $mac -j MARK --set-mark $tFOUNDMARK + fi + fi + + # ----------------------------------------------------------------------------------------------------- + # this command often give this message 'iptables: Bad rule (does a matching rule exist in that chain?)' + # ----------------------------------------------------------------------------------------------------- + $IPTABLES -t filter -D NoCat_Inbound -d $ip -j ACCEPT 2>/dev/null + # ----------------------------------------------------------------------------------------------------- + + if [ $EnableBandwidthLimits -gt 0 ]; then + clearQoS $Ip $Netmask + fi + fi + + # Mark outbound traffic from this node. + if [ "$mac" == "00:00:00:00:00:00" ]; then + if [ -z "$7" -o "$7" = "$ifacein" ]; then + $IPTABLES -t mangle $cmd NoCat_Permit -s $ip -j MARK --set-mark $mark + fi + else + if [ -z "$7" -o "$7" = "$ifacein" ]; then + $IPTABLES -t mangle $cmd NoCat_Permit -s $ip -m mac --mac-source $mac -j MARK --set-mark $mark + fi + fi + + # Mark inbound traffic to this node. + $IPTABLES -t filter $cmd NoCat_Inbound -d $ip -j ACCEPT + + if [ $EnableBandwidthLimits -gt 0 ]; then + if [ "$action" = "deny" ]; then + clearQoS $Ip $Netmask + else + for ifacein in $InternalDevice; do + UserClass=`tc filter show dev $ifacein | awk \ + -v base=11 \ + 'BEGIN{ + n=0 + } + / flowid /{ + sub("^1:","",$NF) + sub("0$","",$NF) + a[n++]=$NF+0 + } + END{ + isort(a,j) + i=0 + if(a[i]>base){ + p = base + } else { + while(a[i]+1>=a[i+1]&&ihold){ + j-- + A[j+1]=A[j] + } + A[j]=hold + } + }'` + break + done + + if [ ${UserUploadRatio} -gt 0 ]; then + for ifaceq in ${IQdevice}; do + echo "${UserClass}:${UserPriority}:${UserAverageRate}:${UserPacketSize}:${UserDelay}:${UserUploadRatio}" | awk \ + -v device="${ifaceq}" \ + -v linespeed="${UploadRate}" \ + -f firewall/tcrules.awk \ + | while read CMD; do $CMD; done + tc filter del dev ${ifaceq} parent 1: protocol ip pref ${UserClass} fw + tc filter add dev ${ifaceq} parent 1: pref ${UserClass} protocol ip u32 match ip src $Ip/$Netmask classid 1:${UserClass}0 + done + fi + + if [ ${UserDownloadRatio} -gt 0 ]; then + for ifacein in $InternalDevice; do + echo "${UserClass}:${UserPriority}:${UserAverageRate}:${UserPacketSize}:${UserDelay}:${UserDownloadRatio}" | awk \ + -v device="$ifacein" \ + -v linespeed="${DownloadRate}" \ + -f firewall/tcrules.awk \ + | while read CMD; do $CMD; done + tc filter del dev $ifacein parent 1: protocol ip pref ${UserClass} fw + tc filter add dev $ifacein parent 1: pref ${UserClass} protocol ip u32 match ip dst $Ip/$Netmask classid 1:${UserClass}0 + done + fi + fi + fi + + [ -S /tmp/evfwdsock ] && /usr/sbin/fwevhandler "$action" "$mac" "$ip" +} + +access_fw_check() { + +# ------------------------------------------------------------ +# (CMD) (MAC) (IP) (Class) (UserDownloadRate) (UserUploadRate) +# ------------------------------------------------------------ +# cmd=$1 + mac=`echo $2 | tr '[A-Z]' '[a-z]'` + ip=$3 +# class=$4 +# UserDownloadRate=$5 +# UserUploadRate=$6 +# ------------------------------------------------------------ + + local action="" + + if [ "$1" = "-A" ]; then + action="permit" + else + action="deny" + fi + + local i=1 + + while [ $i -le 2 ] + do + access_fw $1 $mac $ip $4 $5 $6 + + # check + + fail=0 + count=`$IPTABLES -t mangle -L NoCat_Permit -n | grep -c $ip`; + + if [ $count -gt 0 ]; then + if [ "$action" = "deny" ]; then + fail=1 + fi + else + if [ "$action" = "permit" ]; then + fail=1 + fi + fi + + if [ $fail -eq 0 ]; then + return + fi + + i=`expr $i + 1` + done + + echo "$ip $mac" > /tmp/nodog_fw.$action +} + +clear_fw() { + + #$IPTABLES -F + #$IPTABLES -t nat -F + #$IPTABLES -t mangle -F + #$IPTABLES -t filter -F + #$IPTABLES -t nat -X + #$IPTABLES -t mangle -X + #$IPTABLES -t filter -X + + $IPTABLES -t filter -F FORWARD + $IPTABLES -t filter -F NoCat + $IPTABLES -t filter -F NoCat_RFC1918 + $IPTABLES -t filter -F NoCat_Inbound + $IPTABLES -t filter -F NoCat_Ports + $IPTABLES -t filter -X NoCat + $IPTABLES -t filter -X NoCat_RFC1918 + $IPTABLES -t filter -X NoCat_Inbound + $IPTABLES -t filter -X NoCat_Ports + + $IPTABLES -t nat -D PREROUTING -j NoCat_Capture + $IPTABLES -t nat -D POSTROUTING -j NoCat_NAT + $IPTABLES -t nat -F NoCat_Capture + $IPTABLES -t nat -F NoCat_NAT + $IPTABLES -t nat -X NoCat_Capture + $IPTABLES -t nat -X NoCat_NAT + + $IPTABLES -t mangle -D PREROUTING -j NoCat + $IPTABLES -t mangle -L POSTROUTING -v | awk '/Accoun/{system("'$IPTABLES' -t mangle -D POSTROUTING -o " $7 " -j " $3);}' + $IPTABLES -t mangle -L POSTROUTING -v | awk '/TCPMSS/{system("'$IPTABLES' -t mangle -D POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o " $7 " -j TCPMSS --clamp-mss-to-pmtu");}' + $IPTABLES -t mangle -F AccountIn + $IPTABLES -t mangle -F AccountOu + $IPTABLES -t mangle -F NoCat + $IPTABLES -t mangle -F NoCat_Permit + $IPTABLES -t mangle -X AccountIn + $IPTABLES -t mangle -X AccountOu + $IPTABLES -t mangle -X NoCat + $IPTABLES -t mangle -X NoCat_Permit + + [ $EnableBandwidthLimits -gt 0 ] || return + + if [ -f /etc/init.d/qos ]; then + /etc/init.d/qos enabled && /etc/init.d/qos stop + fi + + checkDeviceUpload + + if [ ${UploadRate} -gt 0 ]; then + tc qdisc del dev ${IQdevice} root + fi + for ifacein in $InternalDevice; do + tc qdisc del dev $ifacein root + done + + if [ -f /etc/init.d/qos ]; then + /etc/init.d/qos enabled && /etc/init.d/qos start + fi +} + +reset_fw() { + + $IPTABLES -t filter -D FORWARD -j NoCat 2>/dev/null + $IPTABLES -t nat -D PREROUTING -j NoCat_Capture 2>/dev/null + + if [ $RouteOnly -eq 0 ]; then + $IPTABLES -t nat -D POSTROUTING -j NoCat_NAT 2>/dev/null + fi + + $IPTABLES -t mangle -D PREROUTING -j NoCat 2>/dev/null +} + +open_fw() { + + # $1 host list + + if [ "$1" ]; then + for host in $1; do + for port in 80 443; do + for ifaceout in $MasqueradeDevice; do + $nat -o $ifaceout -s $net -d $host -p tcp --dport $port -j MASQUERADE + done + + $redirect -s $net -d $host -p tcp --dport $port -j RETURN + $fwd -s $net -d $host -p tcp --dport $port -j ACCEPT + $fwd -d $net -s $host -p tcp --sport $port -j ACCEPT + done + done + fi +} + +check_arp() { + + for iface in $InternalDevice; do + arping -q -c 1 -I $iface $1 + done + + egrep -q "^$1 " /proc/$$/net/arp + + exit $? +} + +do_cmd() { + + # Note: your PATH is inherited from the gateway process + + if [ -x /usr/sbin/iptables ]; then + IPTABLES=/usr/sbin/iptables + else + IPTABLES="echo iptables" + fi + + fwd="$IPTABLES -t filter -A NoCat" + ports="$IPTABLES -t filter -A NoCat_Ports" + local="$IPTABLES -t filter -A NoCat_LocalPorts" + nat="$IPTABLES -t nat -A NoCat_NAT" + redirect="$IPTABLES -t nat -A NoCat_Capture" + mangle="$IPTABLES -t mangle -A NoCat" + + case "$1" in + arp) shift; check_arp "$@" ;; # (IP) + deny) shift; access_fw "-D" "$@" ;; # (CMD) (MAC) (IP) (Class) +# deny) shift; access_fw_check "-D" "$@" ;; # (CMD) (MAC) (IP) (Class) + clear) shift; clear_fw "$@" ;; + reset) shift; reset_fw "$@" ;; + permit) shift; access_fw "-A" "$@" ;; # (CMD) (MAC) (IP) (Class) (UserDownloadRate) (UserUploadRate) +# permit) shift; access_fw_check "-A" "$@" ;; # (CMD) (MAC) (IP) (Class) (UserDownloadRate) (UserUploadRate) + initialize) shift; initialize_fw "$1" ;; + + openlist) + $IPTABLES -t mangle -L NoCat_Permit -n | awk '/MARK set 0x2/{printf("%s\n", $4)}' | sort -u; +# $IPTABLES -t mangle -L NoCat_Permit -n | awk '/MARK set 0x2/{printf("%s\n", $4)}' | sort -u | tee /tmp/nodog_fw.lst; + ;; + esac +} +#----------------------------------- +# END FUNCTION +#----------------------------------- + +export RouteOnly MasqueradeDevice DNSAddr IncludePorts ExcludePorts AllowedWebHosts ExternalDevice \ + InternalDevice LocalNetwork GatewayPort AuthServiceIP MembersOnly MaxSegmentSize IPTABLES \ + EnableBandwidthLimits IMQdevice IFBdevice UserDelay UserPriority UserUploadRate UserPacketSize \ + UserAverageRate UserDownloadRate UploadRate DownloadRate ReservedRatio ReservedClass ReservedDelay \ + ReservedPriority ReservedAverageRate ReservedPacketSize DosPrevention DosAllowTries DosTimeInterval \ + IMQdisabled IFBdisabled IQdevice AvoidMasqueradeAuthServiceIP + +# ------------------------------------------------------------ +# load eventuale script configuration (NON piace a Ghivizzani) +# ------------------------------------------------------------ +# if [ -n "$FW_CONF" -a -s "$FW_CONF" ]; then +# . $FW_CONF +# fi +# ------------------------------------------------------------ + +# --------------------------------------------------------------------------------------------------------------------------------------------------- +# RouteOnly Required only if you DO NOT want your gateway to act as a NAT. Give this only if you're running a strictly routed +# network, and don't need the gateway to enable NAT for you +# +# DNSAddr *If* you choose not to run DNS on your internal network, specify the address(es) of one or more domain name server +# on the Internet that wireless clients can use to get out. Should be the same DNS that your DHCP server hands out +# +# IncludePorts Specify TCP ports to allow access to when public class users login. All others will be denied +# +# ExcludePorts Specify TCP ports to denied access to when public class users login. All others will be allowed. Note that you should +# use either IncludePorts or ExcludePorts, but not both. If neither is specified, access is granted to all ports to public class users. +# You should *always* exclude port 25, unless you want to run an portal for wanton spam sending. Users should have their +# own way of sending mail. It sucks, but that's the way it is. Comment this out *only if* you're using IncludePorts instead +# +# AllowedWebHosts List any domains that you would like to allow web access (TCP port 80 and 443) BEFORE logging in (this is the +# pre-'skip' stage, so be careful about what you allow +# +# ExternalDevice The interface connected to the Internet. Usually 'eth0' or 'eth1' under Linux, or maybe even 'ppp0' if you're running PPP or PPPoE +# +# InternalDevice Required if and only if your machine has more than two network interfaces. Must be set to the interface connected to your local +# network, normally your wireless card +# +# LocalNetwork Must be set to the network address and net mask of your internal network. You can use the number of bits in the netmask +# (e.g. /16, /24, etc.) or the full x.x.x.x specification +# +# GatewayPort The TCP port to bind the gateway service to. 5280 is de-facto standard for NoCatAuth. Change this only if you absolutely need to +# +# AuthServiceIP The address of your authentication service. You must use an IP address if DNS resolution isn't available at gateway startup +# +# MembersOnly Give this if you want to disable public access (i.e. unauthenticated 'skip' button access). You'll also want to +# point AuthServiceIP somewhere that doesn't include a skip button (likeat your own Auth server) +# +# MaxSegmentSize Give this if you want to reduce MTU +# +# MasqueradeDevice maschera il traffico verso il device +# AvoidMasqueradeAuthServiceIP evita di mascherare il traffico verso portale autorizzativo +# --------------------------------------------------------------------------------------------------------------------------------------------------- +RouteOnly=${RouteOnly:-0} +MembersOnly=${MembersOnly:-1} +GatewayPort=${GatewayPort:-5280} +MaxSegmentSize=${MaxSegmentSize:-1} +AvoidMasqueradeAuthServiceIP=${AvoidMasqueradeAuthServiceIP:-0} + +# --------------------------------------------------------------------------------------------------------------------------------------------------- +# Gestione dei limiti sulla banda per gli utenti +# --------------------------------------------------------------------------------------------------------------------------------------------------- +# IMQdevice IMQ device per la gestione del bitrate in upload +# IFBdevice IFB device per la gestione del bitrate in upload +# UploadRate Upload bit rate per le interfacce interne (in Kbits) +# DownloadRate Download bit rate per le interfacce interne (in Kbits) +# UserDelay delay accettabile per il traffico utente (default 100, in millisecondi) +# UserPriority priorita' del traffico degli utenti (default 5) +# UserUploadRate Bit rate in upload di default per gli utenti (in Kbits) +# UserPacketSize dimensione massima del pacchetto sull'interfaccia (default 1500, in bytes) +# UserAverageRate rate medio per il traffico (default 10) +# UserDownloadRate Bit rate in download di default per gli utenti (in Kbits) +# ReservedRatio percentuale di banda riservata +# ReservedClass classId da utilizzare per il qos (default 1) +# ReservedDelay delay accettabile per il traffico riservato (default 200, in millisecondi) +# ReservedPriority priorita' per il traffico riservato (default 1, bassa priorita') +# ReservedPacketSize dimensione massima del pacchetto sull'interfaccia (default 1500, in bytes) +# ReservedAverageRate rate medio per il traffico riservato atto al dimensionamento dei parametri di coda (default 1) +# EnableBandwidthLimits abilita la gestione dei limiti sulla banda per gli utenti +# FullPrivateNetwork la rete privata utilizzata internamente +# BlockRFC1918 blocca il travvico verso le reti private +# +# DosPrevention abilita il supporto anti DoS sul captive portal (da impostare ad 1 per attivare il supporto) +# DosAllowTries numero massimo di connessioni consentite nella finestra temporale +# DosTimeInterval finestra temporale in cui osservare il numero di connessioni per IP +# --------------------------------------------------------------------------------------------------------------------------------------------------- +IFBdevice=${IFBdevice:-ifb0} +UploadRate=${UploadRate:-10240} +DownloadRate=${DownloadRate:-10240} +UserDelay=${UserDelay:-100} +UserPriority=${UserPriority:-5} +UserUploadRate=${UserUploadRate:-1024} +UserPacketSize=${UserPacketSize:-1500} +UserAverageRate=${UserAverageRate:-10} +UserDownloadRate=${UserDownloadRate:-10240} +ReservedRatio=${ReservedRatio:-10} +ReservedClass=${ReservedClass:-1} +ReservedDelay=${ReservedDelay:-200} +ReservedPriority=${ReservedPriority:-1} +ReservedPacketSize=${ReservedPacketSize:-1500} +ReservedAverageRate=${ReservedAverageRate:-1} +EnableBandwidthLimits=${EnableBandwidthLimits:-0} +FullPrivateNetwork=${FullPrivateNetwork:-192.168.0.0/16} +BlockRFC1918=${BlockRFC1918:-1} + +DosPrevention=${DosPrevention:-0} +DosAllowTries=${DosAllowTries:-5} +DosTimeInterval=${DosTimeInterval:-60} + +# ( +# echo "ENVIRONMENT:" +# echo "-----------------------------------------------------------" +# env +# echo "-----------------------------------------------------------" +# echo "STDERR:" +# echo "-----------------------------------------------------------" +# set -x +do_cmd "$@" +# set +x +# echo "-----------------------------------------------------------" +# ) 2>/tmp/nodog_fw.$$ >&2 diff --git a/tests/ulib/test_string.cpp b/tests/ulib/test_string.cpp index 7b018840..78abd612 100644 --- a/tests/ulib/test_string.cpp +++ b/tests/ulib/test_string.cpp @@ -1501,6 +1501,10 @@ U_EXPORT main(int argc, char* argv[]) U_TRACE(5, "main(%d)", argc) + UString byte_count = UString::humanReadableByteCountBin(U_STRING_MAX_SIZE); + + U_ASSERT( byte_count == U_STRING_FROM_CONSTANT("4.0 GiB") ) + #if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) UString token = U_STRING_FROM_CONSTANT("a"), firstname = U_STRING_FROM_CONSTANT("Victor"),
idmessage