From 23f20732159676c101b3383087b1016a0692d265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 11 Aug 2010 13:53:31 +0000 Subject: [PATCH] * Implemented SetToMask(), and added PrefixLength() method, mostly reusing code from ifconfig. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38026 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/net/NetworkAddress.h | 2 + src/kits/network/libnetapi/NetworkAddress.cpp | 89 ++++++++++++++++++- 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/headers/os/net/NetworkAddress.h b/headers/os/net/NetworkAddress.h index 3646aa4211..ef489a1811 100644 --- a/headers/os/net/NetworkAddress.h +++ b/headers/os/net/NetworkAddress.h @@ -82,6 +82,8 @@ public: bool IsSiteLocal() const; bool IsLocal() const; + ssize_t PrefixLength() const; + uint32 LinkLevelIndex() const; BString LinkLevelInterface() const; uint32 LinkLevelType() const; diff --git a/src/kits/network/libnetapi/NetworkAddress.cpp b/src/kits/network/libnetapi/NetworkAddress.cpp index e8f66b0260..796c11c075 100644 --- a/src/kits/network/libnetapi/NetworkAddress.cpp +++ b/src/kits/network/libnetapi/NetworkAddress.cpp @@ -423,8 +423,52 @@ BNetworkAddress::SetToLoopback() status_t BNetworkAddress::SetToMask(int family, uint32 prefixLength) { - // TODO: implement SetToMask() - return B_NOT_SUPPORTED; + switch (family) { + case AF_INET: + { + if (prefixLength > 32) + return B_BAD_VALUE; + + sockaddr_in& mask = (sockaddr_in&)fAddress; + memset(&fAddress, 0, sizeof(sockaddr_storage)); + mask.sin_family = AF_INET; + mask.sin_len = sizeof(sockaddr_in); + + uint32 hostMask = 0; + for (uint8 i = 32; i > 32 - prefixLength; i--) + hostMask |= 1 << (i - 1); + + mask.sin_addr.s_addr = htonl(hostMask); + break; + } + + case AF_INET6: + { + if (prefixLength > 128) + return B_BAD_VALUE; + + sockaddr_in6& mask = (sockaddr_in6&)fAddress; + memset(&fAddress, 0, sizeof(sockaddr_storage)); + mask.sin6_family = AF_INET6; + mask.sin6_len = sizeof(sockaddr_in6); + + for (uint8 i = 0; i < sizeof(in6_addr); i++, prefixLength -= 8) { + if (prefixLength < 8) { + mask.sin6_addr.s6_addr[i] + = (uint8)(0xff << (8 - prefixLength)); + break; + } + + mask.sin6_addr.s6_addr[i] = 0xff; + } + break; + } + + default: + return B_NOT_SUPPORTED; + } + + return B_OK; } @@ -709,6 +753,47 @@ BNetworkAddress::IsLocal() const } +ssize_t +BNetworkAddress::PrefixLength() const +{ + switch (fAddress.ss_family) { + case AF_INET: + { + sockaddr_in& mask = (sockaddr_in&)fAddress; + + ssize_t result = 0; + uint32 hostMask = ntohl(mask.sin_addr.s_addr); + for (uint8 i = 32; i > 0; i--) { + if ((hostMask & (1 << (i - 1))) == 0) + break; + result++; + } + + return result; + } + + case AF_INET6: + { + sockaddr_in6& mask = (sockaddr_in6&)fAddress; + + ssize_t result = 0; + for (uint8 i = 0; i < sizeof(in6_addr); i++) { + for (uint8 j = 0; j < 8; j++) { + if (!(mask.sin6_addr.s6_addr[i] & (1 << j))) + return result; + result++; + } + } + + return 128; + } + + default: + return B_NOT_SUPPORTED; + } +} + + uint32 BNetworkAddress::LinkLevelIndex() const {