diff --git a/Makefile b/Makefile index c51018f9..ce1ad51f 100644 --- a/Makefile +++ b/Makefile @@ -130,6 +130,8 @@ doxygen: .PHONY: deps .PHONY: doxygen .PHONY: dist +.PHONY: last-dist .PHONY: api .PHONY: api_client .PHONY: mk_obj_dir +.PHONY: install diff --git a/Makefile.homebrew b/Makefile.homebrew index 688fdaea..64301c02 100644 --- a/Makefile.homebrew +++ b/Makefile.homebrew @@ -1,7 +1,7 @@ # root directory holding homebrew BREWROOT = /usr/local BOOSTROOT = ${BREWROOT}/opt/boost -SSLROOT = ${BREWROOT}/opt/libressl +SSLROOT = ${BREWROOT}/opt/openssl@1.1 UPNPROOT = ${BREWROOT}/opt/miniupnpc CXXFLAGS = ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include @@ -41,9 +41,14 @@ ifeq ($(USE_AVX),1) CXXFLAGS += -mavx endif - -# Disabled, since it will be the default make rule. I think its better -# to define the default rule in Makefile and not Makefile. - torkel -#install: all -# test -d ${PREFIX} || mkdir -p ${PREFIX}/ -# cp -r i2p ${PREFIX}/ +install: all + install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd + install -m 755 ${I2PD} ${PREFIX}/bin/ + install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd + @cp -R contrib/certificates ${PREFIX}/share/i2pd/ + install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd + @gzip debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1 + @ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/ + @ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf + @ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt + @ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf \ No newline at end of file diff --git a/Makefile.linux b/Makefile.linux index b9a740ad..cb376e77 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -21,8 +21,10 @@ else ifeq ($(shell expr match ${CXXVER} "4\.6"),3) # = 4.6 NEEDED_CXXFLAGS += -std=c++0x else ifeq ($(shell expr match ${CXXVER} "[5-7]\.[0-9]"),3) # gcc >= 5.0 NEEDED_CXXFLAGS += -std=c++11 + LDLIBS = -latomic else ifeq ($(shell expr match ${CXXVER} "[7-8]"),1) # gcc 7 ubuntu or gcc 8 arch NEEDED_CXXFLAGS += -std=c++11 + LDLIBS = -latomic else # not supported $(error Compiler too old) endif @@ -34,7 +36,7 @@ ifeq ($(USE_STATIC),yes) # Using 'getaddrinfo' in statically linked applications requires at runtime # the shared libraries from the glibc version used for linking LIBDIR := /usr/lib - LDLIBS = $(LIBDIR)/libboost_system.a + LDLIBS += $(LIBDIR)/libboost_system.a LDLIBS += $(LIBDIR)/libboost_date_time.a LDLIBS += $(LIBDIR)/libboost_filesystem.a LDLIBS += $(LIBDIR)/libboost_program_options.a @@ -44,7 +46,7 @@ ifeq ($(USE_STATIC),yes) LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt -ldl USE_AESNI := no else - LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread + LDLIBS += -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread endif # UPNP Support (miniupnpc 1.5 and higher) diff --git a/Makefile.osx b/Makefile.osx index 13376040..d673d3ef 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -1,7 +1,7 @@ CXX = clang++ CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX INCFLAGS = -I/usr/local/include -LDFLAGS := ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib +LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib ifeq ($(USE_STATIC),yes) LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread @@ -28,17 +28,3 @@ endif ifeq ($(USE_AVX),1) CXXFLAGS += -mavx endif - -# Disabled, since it will be the default make rule. I think its better -# to define the default rule in Makefile and not Makefile. - torkel -install-brew: all - install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd - install -m 755 ${I2PD} ${PREFIX}/bin/ - install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd - @cp -R contrib/certificates ${PREFIX}/share/i2pd/ - install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd - @gzip debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1 - @ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/ - @ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf - @ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt - @ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf diff --git a/android/assets/i2pd.conf b/android/assets/i2pd.conf index cf113da2..bc2f7a3a 100644 --- a/android/assets/i2pd.conf +++ b/android/assets/i2pd.conf @@ -1,5 +1,5 @@ ## Configuration file for a typical i2pd user -## See https://i2pd.readthedocs.org/en/latest/configuration.html +## See https://i2pd.readthedocs.io/en/latest/user-guide/configuration/ ## for more options you can use in this file. #logfile = /sdcard/i2pd/i2pd.log diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 123df754..92abf496 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -1,5 +1,5 @@ ## Configuration file for a typical i2pd user -## See https://i2pd.readthedocs.org/en/latest/configuration.html +## See https://i2pd.readthedocs.io/en/latest/user-guide/configuration/ ## for more options you can use in this file. ## Lines that begin with "## " try to explain what's going on. Lines diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 43f1def9..30d00d76 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -266,6 +266,10 @@ namespace crypto # define LEGACY_OPENSSL 1 #else # define LEGACY_OPENSSL 0 +# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 +# define OPENSSL_EDDSA 1 +# define OPENSSL_X25519 1 +# endif #endif #if LEGACY_OPENSSL diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 58f928b4..6a319115 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -41,6 +41,9 @@ namespace transport delete[] m_SessionRequestBuffer; delete[] m_SessionCreatedBuffer; delete[] m_SessionConfirmedBuffer; +#if OPENSSL_X25519 + EVP_PKEY_free (m_EphemeralPkey); +#endif } void NTCP2Establisher::MixKey (const uint8_t * inputKeyMaterial, uint8_t * derived) @@ -119,7 +122,18 @@ namespace transport // x25519 between remote pub and priv uint8_t inputKeyMaterial[32]; - i2p::crypto::GetEd25519 ()->ScalarMul (GetRemotePub (), GetPriv (), inputKeyMaterial, m_Ctx); +#if OPENSSL_X25519 + auto pctx = EVP_PKEY_CTX_new (m_EphemeralPkey, NULL); + EVP_PKEY_derive_init (pctx); + auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, GetRemotePub (), 32); + EVP_PKEY_derive_set_peer (pctx, pkey); + size_t len = 32; + EVP_PKEY_derive (pctx, inputKeyMaterial, &len); + EVP_PKEY_free (pkey); + EVP_PKEY_CTX_free (pctx); +#else + i2p::crypto::GetEd25519 ()->ScalarMul (GetRemotePub (), GetPriv (), inputKeyMaterial, m_Ctx); +#endif MixKey (inputKeyMaterial, m_K); } @@ -149,8 +163,21 @@ namespace transport void NTCP2Establisher::CreateEphemeralKey () { +#if OPENSSL_X25519 + m_EphemeralPkey = nullptr; + EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL); + EVP_PKEY_keygen_init (pctx); + EVP_PKEY_keygen (pctx, &m_EphemeralPkey); + EVP_PKEY_CTX_free (pctx); + // TODO: remove, after switch to m_EphemeralPkey + size_t len = 32; + EVP_PKEY_get_raw_public_key (m_EphemeralPkey, m_EphemeralPublicKey, &len); + len = 32; + EVP_PKEY_get_raw_private_key (m_EphemeralPkey, m_EphemeralPrivateKey, &len); +#else RAND_bytes (m_EphemeralPrivateKey, 32); i2p::crypto::GetEd25519 ()->ScalarMulB (m_EphemeralPrivateKey, m_EphemeralPublicKey, m_Ctx); +#endif } void NTCP2Establisher::CreateSessionRequestMessage () @@ -1179,6 +1206,8 @@ namespace transport else { LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetSocket ().remote_endpoint ()); + if (conn->GetSocket ().local_endpoint ().protocol () == boost::asio::ip::tcp::v6()) // ipv6 + context.UpdateNTCP2V6Address (conn->GetSocket ().local_endpoint ().address ()); conn->ClientLogin (); } } diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 2b6748ab..10874abb 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "util.h" #include "RouterInfo.h" @@ -110,6 +111,9 @@ namespace transport BN_CTX * m_Ctx; uint8_t m_EphemeralPrivateKey[32], m_EphemeralPublicKey[32], m_RemoteEphemeralPublicKey[32]; // x25519 +#if OPENSSL_X25519 + EVP_PKEY * m_EphemeralPkey; +#endif uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[33] /*ck*/, m_K[32] /*k*/; i2p::data::IdentHash m_RemoteIdentHash; uint16_t m3p2Len; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index a3d33113..6ad3d159 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -453,6 +453,39 @@ namespace i2p UpdateRouterInfo (); } + void RouterContext::UpdateNTCP2V6Address (const boost::asio::ip::address& host) + { + bool updated = false, found = false; + int port = 0; + auto& addresses = m_RouterInfo.GetAddresses (); + for (auto& addr: addresses) + { + if (addr->IsPublishedNTCP2 ()) + { + if (addr->host.is_v6 ()) + { + if (addr->host != host) + { + addr->host = host; + updated = true; + } + found = true; + break; + } + else + port = addr->port; // NTCP2 v4 + } + } + + if (!found && port) // we have found NTCP2 v4 but not v6 + { + m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port); + updated = true; + } + if (updated) + UpdateRouterInfo (); + } + void RouterContext::UpdateStats () { if (m_IsFloodfill) diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index f1a62c5a..3f3a18c5 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -100,6 +100,7 @@ namespace i2p void SetSupportsV4 (bool supportsV4); void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session + void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from NTCP2 session void UpdateStats (); void CleanupDestination (); // garlic destination diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 79a70462..b8bc5c11 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -696,17 +696,17 @@ namespace data m_Caps |= eSSUIntroducer; } - void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv) + void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host, int port) { - for (const auto& it: *m_Addresses) // don't insert one more NTCP2 - if (it->ntcp2) return; auto addr = std::make_shared
(); - addr->port = 0; + addr->host = host; + addr->port = port; addr->transportStyle = eTransportNTCP; addr->cost = 3; addr->date = 0; addr->ntcp2.reset (new NTCP2Ext ()); addr->ntcp2->isNTCP2Only = true; // NTCP2 only address + if (port) addr->ntcp2->isPublished = true; memcpy (addr->ntcp2->staticKey, staticKey, 32); memcpy (addr->ntcp2->iv, iv, 16); m_Addresses->push_back(std::move(addr)); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 47a5d680..f66a73fa 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -117,7 +117,8 @@ namespace data bool operator==(const Address& other) const { - return transportStyle == other.transportStyle && host == other.host && port == other.port; + return transportStyle == other.transportStyle && IsNTCP2 () == other.IsNTCP2 () && + host == other.host && port == other.port; } bool operator!=(const Address& other) const @@ -150,7 +151,7 @@ namespace data void AddNTCPAddress (const char * host, int port); void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0); - void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv); + void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0); bool AddIntroducer (const Introducer& introducer); bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e); void SetProperty (const std::string& key, const std::string& value); // called from RouterContext only diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index baa265bc..f5164e9f 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -6,6 +6,26 @@ namespace i2p { namespace crypto { +#if OPENSSL_EDDSA + EDDSA25519Verifier::EDDSA25519Verifier (const uint8_t * signingKey) + { + m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32); + m_MDCtx = EVP_MD_CTX_create (); + EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); + } + + EDDSA25519Verifier::~EDDSA25519Verifier () + { + EVP_MD_CTX_destroy (m_MDCtx); + EVP_PKEY_free (m_Pkey); + } + + bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const + { + return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len); + } + +#else EDDSA25519Verifier::EDDSA25519Verifier (const uint8_t * signingKey) { memcpy (m_PublicKeyEncoded, signingKey, EDDSA25519_PUBLIC_KEY_LENGTH); @@ -14,6 +34,10 @@ namespace crypto BN_CTX_free (ctx); } + EDDSA25519Verifier::~EDDSA25519Verifier () + { + } + bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { uint8_t digest[64]; @@ -26,7 +50,30 @@ namespace crypto return GetEd25519 ()->Verify (m_PublicKey, digest, signature); } +#endif +#if OPENSSL_EDDSA + EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey) + { + m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32); + // TODO: check public key + m_MDCtx = EVP_MD_CTX_create (); + EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); + } + + EDDSA25519Signer::~EDDSA25519Signer () + { + EVP_MD_CTX_destroy (m_MDCtx); + EVP_PKEY_free (m_Pkey); + } + + void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const + { + size_t l = 64; + EVP_DigestSign (m_MDCtx, signature, &l, buf, len); + } + +#else EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey) { // expand key @@ -47,10 +94,15 @@ namespace crypto BN_CTX_free (ctx); } + EDDSA25519Signer::~EDDSA25519Signer () + { + } + void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const { GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature); } +#endif } } diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index 8b30a8e8..7f5a53b9 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -367,6 +367,8 @@ namespace crypto public: EDDSA25519Verifier (const uint8_t * signingKey); + ~EDDSA25519Verifier (); + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const; size_t GetPublicKeyLen () const { return EDDSA25519_PUBLIC_KEY_LENGTH; }; @@ -374,8 +376,13 @@ namespace crypto private: +#if OPENSSL_EDDSA + EVP_PKEY * m_Pkey; + EVP_MD_CTX * m_MDCtx; +#else EDDSAPoint m_PublicKey; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; +#endif }; class EDDSA25519Signer: public Signer @@ -384,20 +391,41 @@ namespace crypto EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr); // we pass signingPublicKey to check if it matches private key + ~EDDSA25519Signer (); + void Sign (const uint8_t * buf, int len, uint8_t * signature) const; - const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; +#if !OPENSSL_EDDSA + const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation +#endif private: - +#if OPENSSL_EDDSA + EVP_PKEY * m_Pkey; + EVP_MD_CTX * m_MDCtx; +#else uint8_t m_ExpandedPrivateKey[64]; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; +#endif }; inline void CreateEDDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { +#if OPENSSL_EDDSA + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_ED25519, NULL); + EVP_PKEY_keygen_init (pctx); + EVP_PKEY_keygen (pctx, &pkey); + EVP_PKEY_CTX_free (pctx); + size_t len = EDDSA25519_PUBLIC_KEY_LENGTH; + EVP_PKEY_get_raw_public_key (pkey, signingPublicKey, &len); + len = EDDSA25519_PRIVATE_KEY_LENGTH; + EVP_PKEY_get_raw_private_key (pkey, signingPrivateKey, &len); + EVP_PKEY_free (pkey); +#else RAND_bytes (signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH); EDDSA25519Signer signer (signingPrivateKey); memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH); +#endif } diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index bca0e25b..30ae7172 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -741,7 +741,7 @@ namespace client std::string response; uint8_t recv_buf[4096]; bool end = false; - int numAttempts = 5; + int numAttempts = 0; while (!end) { stream->AsyncReceive (boost::asio::buffer (recv_buf, 4096), @@ -755,7 +755,8 @@ namespace client }, SUBSCRIPTION_REQUEST_TIMEOUT); std::unique_lock l(newDataReceivedMutex); - if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT)) == std::cv_status::timeout) + // wait 1 more second + if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT + 1)) == std::cv_status::timeout) { LogPrint (eLogError, "Addressbook: subscriptions request timeout expired"); numAttempts++; diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index b40c2832..b58677c8 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -500,7 +500,8 @@ namespace client if (type == I2P_TUNNELS_SECTION_TYPE_SOCKS) { // socks proxy - auto tun = std::make_shared(name, address, port, false, "", destinationPort, localDestination); + std::string outproxy = section.second.get("outproxy", ""); + auto tun = std::make_shared(name, address, port, !outproxy.empty(), outproxy, destinationPort, localDestination); clientTunnel = tun; clientEndpoint = tun->GetLocalEndpoint (); } diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 953af1cd..dde6e675 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -46,7 +46,7 @@ namespace client const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n"; const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n"; const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n"; - const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=INVALID_KEY_NOT_FOUND NAME=%s\n"; + const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=KEY_NOT_FOUND NAME=%s\n"; const char SAM_PARAM_MIN[] = "MIN"; const char SAM_PARAM_MAX[] = "MAX"; const char SAM_PARAM_STYLE[] = "STYLE";