From 6bd1efa3136edd570975d3bc4bf0b91018996133 Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Tue, 2 Sep 2014 01:23:57 +0200 Subject: [PATCH] decoding of IPv6 fixed --- src/remoteClient/clientContextImpl.cpp | 26 ++------------------------ src/server/responseHandlers.cpp | 13 +------------ src/utils/inetAddressUtil.cpp | 19 +++++++++++++++++++ src/utils/inetAddressUtil.h | 8 ++++++++ testApp/remote/testBeaconHandler.cpp | 17 ----------------- 5 files changed, 30 insertions(+), 53 deletions(-) diff --git a/src/remoteClient/clientContextImpl.cpp b/src/remoteClient/clientContextImpl.cpp index 27142c8..3de43f0 100644 --- a/src/remoteClient/clientContextImpl.cpp +++ b/src/remoteClient/clientContextImpl.cpp @@ -2700,20 +2700,9 @@ namespace epics { serverAddress.ia.sin_family = AF_INET; // 128-bit IPv6 address - /* - int8* byteAddress = new int8[16]; - for (int i = 0; i < 16; i++) - byteAddress[i] = payloadBuffer->getByte(); }; - */ - - // IPv4 compatible IPv6 address expected - // first 80-bit are 0 - if (payloadBuffer->getLong() != 0) return; - if (payloadBuffer->getShort() != 0) return; - if (payloadBuffer->getShort() != (int16)0xFFFF) return; + if (!decodeAsIPv6Address(payloadBuffer, &serverAddress)) return; // accept given address if explicitly specified by sender - serverAddress.ia.sin_addr.s_addr = htonl(payloadBuffer->getInt()); if (serverAddress.ia.sin_addr.s_addr == INADDR_ANY) serverAddress.ia.sin_addr = responseFrom->ia.sin_addr; @@ -2774,20 +2763,9 @@ namespace epics { serverAddress.ia.sin_family = AF_INET; // 128-bit IPv6 address - /* - int8* byteAddress = new int8[16]; - for (int i = 0; i < 16; i++) - byteAddress[i] = payloadBuffer->getByte(); }; - */ - - // IPv4 compatible IPv6 address expected - // first 80-bit are 0 - if (payloadBuffer->getLong() != 0) return; - if (payloadBuffer->getShort() != 0) return; - if (payloadBuffer->getShort() != (int16)0xFFFF) return; + if (!decodeAsIPv6Address(payloadBuffer, &serverAddress)) return; // accept given address if explicitly specified by sender - serverAddress.ia.sin_addr.s_addr = htonl(payloadBuffer->getInt()); if (serverAddress.ia.sin_addr.s_addr == INADDR_ANY) serverAddress.ia.sin_addr = responseFrom->ia.sin_addr; diff --git a/src/server/responseHandlers.cpp b/src/server/responseHandlers.cpp index 82708c1..a43c227 100644 --- a/src/server/responseHandlers.cpp +++ b/src/server/responseHandlers.cpp @@ -202,20 +202,9 @@ void ServerSearchHandler::handleResponse(osiSockAddr* responseFrom, responseAddress.ia.sin_family = AF_INET; // 128-bit IPv6 address - /* -int8 byteAddress[16]; -for (int i = 0; i < 16; i++) -byteAddress[i] = payloadBuffer->getByte(); - */ - - // IPv4 compatible IPv6 address expected - // first 80-bit are 0 - if (payloadBuffer->getLong() != 0) return; - if (payloadBuffer->getShort() != 0) return; - if (payloadBuffer->getShort() != (int16)0xFFFF) return; + if (!decodeAsIPv6Address(payloadBuffer, &responseAddress)) return; // accept given address if explicitly specified by sender - responseAddress.ia.sin_addr.s_addr = payloadBuffer->getInt(); if (responseAddress.ia.sin_addr.s_addr == INADDR_ANY) responseAddress.ia.sin_addr = responseFrom->ia.sin_addr; diff --git a/src/utils/inetAddressUtil.cpp b/src/utils/inetAddressUtil.cpp index 6810ec8..cef7390 100644 --- a/src/utils/inetAddressUtil.cpp +++ b/src/utils/inetAddressUtil.cpp @@ -64,6 +64,25 @@ void encodeAsIPv6Address(ByteBuffer* buffer, const osiSockAddr* address) { buffer->putByte((int8)(ipv4Addr&0xFF)); } +bool decodeAsIPv6Address(ByteBuffer* buffer, osiSockAddr* address) { + + // IPv4 compatible IPv6 address expected + // first 80-bit are 0 + if (buffer->getLong() != 0) return false; + if (buffer->getShort() != 0) return false; + if (buffer->getShort() != (int16)0xFFFF) return false; + + uint32_t ipv4Addr = + ((uint32_t)(buffer->getByte()&0xFF))<<24 | + ((uint32_t)(buffer->getByte()&0xFF))<<16 | + ((uint32_t)(buffer->getByte()&0xFF))<<8 | + ((uint32_t)(buffer->getByte()&0xFF)); + + address->ia.sin_addr.s_addr = htonl(ipv4Addr); + + return true; +} + bool isMulticastAddress(const osiSockAddr* address) { uint32_t ipv4Addr = ntohl(address->ia.sin_addr.s_addr); uint8_t msB = (uint8_t)((ipv4Addr>>24)&0xFF); diff --git a/src/utils/inetAddressUtil.h b/src/utils/inetAddressUtil.h index e6bfb32..57982af 100644 --- a/src/utils/inetAddressUtil.h +++ b/src/utils/inetAddressUtil.h @@ -49,6 +49,14 @@ namespace pvAccess { */ epicsShareFunc void encodeAsIPv6Address(epics::pvData::ByteBuffer* buffer, const osiSockAddr* address); + /** + * Decode IPv6 address (as IPv4 address). + * @param buffer byte-buffer where to get encoded data. + * @param address address where to decode. + * @return success status (true on success). + */ + epicsShareFunc bool decodeAsIPv6Address(epics::pvData::ByteBuffer* buffer, osiSockAddr* address); + /** * Check if an IPv4 address is a multicast address. * @param address IPv4 address to check. diff --git a/testApp/remote/testBeaconHandler.cpp b/testApp/remote/testBeaconHandler.cpp index 058e51b..ace4d8b 100644 --- a/testApp/remote/testBeaconHandler.cpp +++ b/testApp/remote/testBeaconHandler.cpp @@ -17,23 +17,6 @@ using namespace epics::pvAccess; using namespace epics::pvData; using namespace std; -void decodeFromIPv6Address(ByteBuffer* buffer, osiSockAddr* address) -{ - // IPv4 compatible IPv6 address - // first 80-bit are 0 - buffer->getLong(); - buffer->getShort(); - // next 16-bits are 1 - buffer->getShort(); - // following IPv4 address in big-endian (network) byte order - in_addr_t ipv4Addr = 0; - ipv4Addr |= (uint32)buffer->getByte() << 24; - ipv4Addr |= (uint32)buffer->getByte() << 16; - ipv4Addr |= (uint32)buffer->getByte() << 8; - ipv4Addr |= (uint32)buffer->getByte() << 0; - address->ia.sin_addr.s_addr = ipv4Addr; -} - class BeaconResponseHandler : public ResponseHandler { public: