1518678f8Sopenharmony_ci/* 2518678f8Sopenharmony_ci * Copyright (C) 2021-2022 Huawei Device Co., Ltd. 3518678f8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4518678f8Sopenharmony_ci * you may not use this file except in compliance with the License. 5518678f8Sopenharmony_ci * You may obtain a copy of the License at 6518678f8Sopenharmony_ci * 7518678f8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8518678f8Sopenharmony_ci * 9518678f8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10518678f8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11518678f8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12518678f8Sopenharmony_ci * See the License for the specific language governing permissions and 13518678f8Sopenharmony_ci * limitations under the License. 14518678f8Sopenharmony_ci */ 15518678f8Sopenharmony_ci 16518678f8Sopenharmony_ci#include "address_utils.h" 17518678f8Sopenharmony_ci#include <arpa/inet.h> 18518678f8Sopenharmony_ci#include <netinet/in.h> 19518678f8Sopenharmony_ci#include <securec.h> 20518678f8Sopenharmony_ci#include <string.h> 21518678f8Sopenharmony_ci#include <sys/socket.h> 22518678f8Sopenharmony_ci#include "dhcp_s_define.h" 23518678f8Sopenharmony_ci 24518678f8Sopenharmony_ci#define IPV4_ADDRESS_BITS 32 25518678f8Sopenharmony_ci#define BIT_MAX_VALUE 2 26518678f8Sopenharmony_ci#define IP_ADDRESS_LENGTH 4 27518678f8Sopenharmony_ci#define MAD_ADDR_BUF_SIZE 50 28518678f8Sopenharmony_ci#define MAC_STRING_SIZE 17 29518678f8Sopenharmony_ci#define IP_ADDRESS_STRING_LENGTH 64 30518678f8Sopenharmony_ci 31518678f8Sopenharmony_cienum MacAddressIndex { 32518678f8Sopenharmony_ci MAI_ZERO = 0, 33518678f8Sopenharmony_ci MAI_ONE = 1, 34518678f8Sopenharmony_ci MAI_TWO = 2, 35518678f8Sopenharmony_ci MAI_THREE = 3, 36518678f8Sopenharmony_ci MAI_FOUR = 4, 37518678f8Sopenharmony_ci MAI_FIVE = 5 38518678f8Sopenharmony_ci}; 39518678f8Sopenharmony_ci 40518678f8Sopenharmony_ciuint32_t NetworkAddress(uint32_t ip, uint32_t netmask) 41518678f8Sopenharmony_ci{ 42518678f8Sopenharmony_ci return (ip & netmask); 43518678f8Sopenharmony_ci} 44518678f8Sopenharmony_ci 45518678f8Sopenharmony_ciuint32_t FirstIpAddress(uint32_t ip, uint32_t netmask) 46518678f8Sopenharmony_ci{ 47518678f8Sopenharmony_ci uint32_t network = NetworkAddress(ip, netmask); 48518678f8Sopenharmony_ci uint32_t firstIp = htonl(network) + 1; 49518678f8Sopenharmony_ci return htonl(firstIp); 50518678f8Sopenharmony_ci} 51518678f8Sopenharmony_ci 52518678f8Sopenharmony_ciuint32_t NextIpAddress(uint32_t currIp, uint32_t netmask, uint32_t offset) 53518678f8Sopenharmony_ci{ 54518678f8Sopenharmony_ci uint32_t network = NetworkAddress(currIp, netmask); 55518678f8Sopenharmony_ci uint32_t broadcast = BroadCastAddress(currIp, netmask); 56518678f8Sopenharmony_ci uint32_t lastIp = LastIpAddress(currIp, netmask); 57518678f8Sopenharmony_ci uint32_t hostTotal = HostTotal(netmask); 58518678f8Sopenharmony_ci uint32_t next = offset; 59518678f8Sopenharmony_ci if (currIp == lastIp || currIp == broadcast) { 60518678f8Sopenharmony_ci return FirstIpAddress(currIp, netmask); 61518678f8Sopenharmony_ci } 62518678f8Sopenharmony_ci if (next > hostTotal && hostTotal > 0) { 63518678f8Sopenharmony_ci next = next % hostTotal; 64518678f8Sopenharmony_ci } 65518678f8Sopenharmony_ci uint32_t nextIp = htonl(currIp) + next + 1; 66518678f8Sopenharmony_ci if (next && nextIp > htonl(lastIp)) { 67518678f8Sopenharmony_ci nextIp = htonl(network) + (nextIp - htonl(lastIp)); 68518678f8Sopenharmony_ci } 69518678f8Sopenharmony_ci return htonl(nextIp); 70518678f8Sopenharmony_ci} 71518678f8Sopenharmony_ci 72518678f8Sopenharmony_ciuint32_t FirstNetIpAddress(uint32_t network) 73518678f8Sopenharmony_ci{ 74518678f8Sopenharmony_ci uint32_t firstIp = htonl(network) + 1; 75518678f8Sopenharmony_ci return htonl(firstIp); 76518678f8Sopenharmony_ci} 77518678f8Sopenharmony_ci 78518678f8Sopenharmony_ciuint32_t LastIpAddress(uint32_t ip, uint32_t netmask) 79518678f8Sopenharmony_ci{ 80518678f8Sopenharmony_ci uint32_t network = NetworkAddress(ip, netmask); 81518678f8Sopenharmony_ci uint32_t lastIp = htonl(network) + HostTotal(netmask); 82518678f8Sopenharmony_ci if (lastIp) { 83518678f8Sopenharmony_ci lastIp -= 1; 84518678f8Sopenharmony_ci } 85518678f8Sopenharmony_ci return htonl(lastIp); 86518678f8Sopenharmony_ci} 87518678f8Sopenharmony_ci 88518678f8Sopenharmony_ciint IpInNetwork(uint32_t ip, uint32_t network, uint32_t netmask) 89518678f8Sopenharmony_ci{ 90518678f8Sopenharmony_ci uint32_t firstNet = NetworkAddress(ip, netmask); 91518678f8Sopenharmony_ci uint32_t secondNet = NetworkAddress(network, netmask); 92518678f8Sopenharmony_ci 93518678f8Sopenharmony_ci uint32_t beginIp = FirstIpAddress(network, netmask); 94518678f8Sopenharmony_ci uint32_t broadCast = BroadCastAddress(network, netmask); 95518678f8Sopenharmony_ci 96518678f8Sopenharmony_ci if (firstNet == secondNet) { 97518678f8Sopenharmony_ci if (ip >= beginIp && ip <= broadCast) { 98518678f8Sopenharmony_ci return DHCP_TRUE; 99518678f8Sopenharmony_ci } 100518678f8Sopenharmony_ci } 101518678f8Sopenharmony_ci return DHCP_FALSE; 102518678f8Sopenharmony_ci} 103518678f8Sopenharmony_ci 104518678f8Sopenharmony_ciint IpInRange(uint32_t ip, uint32_t beginIp, uint32_t endIp, uint32_t netmask) 105518678f8Sopenharmony_ci{ 106518678f8Sopenharmony_ci uint32_t network = NetworkAddress(ip, netmask); 107518678f8Sopenharmony_ci uint32_t firstNet = NetworkAddress(beginIp, netmask); 108518678f8Sopenharmony_ci uint32_t secondNet = NetworkAddress(endIp, netmask); 109518678f8Sopenharmony_ci if (network != firstNet || firstNet != secondNet) { 110518678f8Sopenharmony_ci return 0; 111518678f8Sopenharmony_ci } 112518678f8Sopenharmony_ci if (ip >= beginIp && ip <= endIp) { 113518678f8Sopenharmony_ci return DHCP_TRUE; 114518678f8Sopenharmony_ci } 115518678f8Sopenharmony_ci return DHCP_FALSE; 116518678f8Sopenharmony_ci} 117518678f8Sopenharmony_ci 118518678f8Sopenharmony_ciuint32_t BroadCastAddress(uint32_t ip, uint32_t netmask) 119518678f8Sopenharmony_ci{ 120518678f8Sopenharmony_ci uint32_t network = NetworkAddress(ip, netmask); 121518678f8Sopenharmony_ci uint32_t broadcast = htonl(network) + HostTotal(netmask); 122518678f8Sopenharmony_ci return htonl(broadcast); 123518678f8Sopenharmony_ci} 124518678f8Sopenharmony_ci 125518678f8Sopenharmony_ciint NetworkBits(uint32_t netmask) 126518678f8Sopenharmony_ci{ 127518678f8Sopenharmony_ci int bits = 0; 128518678f8Sopenharmony_ci uint32_t net = htonl(netmask); 129518678f8Sopenharmony_ci for (size_t i = 0; i < IPV4_ADDRESS_BITS; i++) { 130518678f8Sopenharmony_ci if (net == 0) { 131518678f8Sopenharmony_ci break; 132518678f8Sopenharmony_ci } 133518678f8Sopenharmony_ci bits++; 134518678f8Sopenharmony_ci net <<= 1; 135518678f8Sopenharmony_ci } 136518678f8Sopenharmony_ci return bits; 137518678f8Sopenharmony_ci} 138518678f8Sopenharmony_ci 139518678f8Sopenharmony_ciuint32_t HostBits(uint32_t netmask) 140518678f8Sopenharmony_ci{ 141518678f8Sopenharmony_ci uint32_t bits = 0; 142518678f8Sopenharmony_ci uint32_t net = htonl(netmask); 143518678f8Sopenharmony_ci for (int i = IPV4_ADDRESS_BITS; i > 0; --i) { 144518678f8Sopenharmony_ci bits++; 145518678f8Sopenharmony_ci net >>= 1; 146518678f8Sopenharmony_ci if ((net & 1) != 0) { 147518678f8Sopenharmony_ci break; 148518678f8Sopenharmony_ci } 149518678f8Sopenharmony_ci } 150518678f8Sopenharmony_ci return bits; 151518678f8Sopenharmony_ci} 152518678f8Sopenharmony_ci 153518678f8Sopenharmony_ciuint32_t HostTotal(uint32_t netmask) 154518678f8Sopenharmony_ci{ 155518678f8Sopenharmony_ci uint32_t hostBits = HostBits(netmask); 156518678f8Sopenharmony_ci uint32_t total = 1; 157518678f8Sopenharmony_ci for (size_t i = 0; i < (size_t)hostBits; i++) { 158518678f8Sopenharmony_ci total *= BIT_MAX_VALUE; 159518678f8Sopenharmony_ci } 160518678f8Sopenharmony_ci total--; 161518678f8Sopenharmony_ci return total; 162518678f8Sopenharmony_ci} 163518678f8Sopenharmony_ci 164518678f8Sopenharmony_ciuint32_t ParseIpAddr(const char *strIp) 165518678f8Sopenharmony_ci{ 166518678f8Sopenharmony_ci struct in_addr inAddr; 167518678f8Sopenharmony_ci uint32_t ip = 0; 168518678f8Sopenharmony_ci int ret = inet_aton(strIp, &inAddr); 169518678f8Sopenharmony_ci if (ret != 0) { 170518678f8Sopenharmony_ci if (memcpy_s(&ip, sizeof(uint32_t), &inAddr, sizeof(struct in_addr)) != EOK) { 171518678f8Sopenharmony_ci return 0; 172518678f8Sopenharmony_ci } 173518678f8Sopenharmony_ci return ip; 174518678f8Sopenharmony_ci } 175518678f8Sopenharmony_ci return 0; 176518678f8Sopenharmony_ci} 177518678f8Sopenharmony_ci 178518678f8Sopenharmony_ciuint32_t ParseIpHtonl(const char *strIp) 179518678f8Sopenharmony_ci{ 180518678f8Sopenharmony_ci uint32_t ip = ParseIpAddr(strIp); 181518678f8Sopenharmony_ci return htonl(ip); 182518678f8Sopenharmony_ci} 183518678f8Sopenharmony_ci 184518678f8Sopenharmony_ciuint32_t ParseIp(const uint8_t *ipAddr) 185518678f8Sopenharmony_ci{ 186518678f8Sopenharmony_ci uint32_t ip = 0; 187518678f8Sopenharmony_ci if (memcpy_s(&ip, IP_ADDRESS_LENGTH, ipAddr, IP_ADDRESS_LENGTH) != EOK) { 188518678f8Sopenharmony_ci return 0; 189518678f8Sopenharmony_ci } 190518678f8Sopenharmony_ci return ip; 191518678f8Sopenharmony_ci} 192518678f8Sopenharmony_ci 193518678f8Sopenharmony_ciconst char *ParseStrIp(uint32_t ipAddr) 194518678f8Sopenharmony_ci{ 195518678f8Sopenharmony_ci static char strIpAddr[IP_ADDRESS_STRING_LENGTH] = {0}; 196518678f8Sopenharmony_ci struct in_addr inAddr; 197518678f8Sopenharmony_ci if (memcpy_s(&inAddr, sizeof(inAddr), &ipAddr, sizeof(ipAddr)) != EOK || 198518678f8Sopenharmony_ci memset_s(strIpAddr, sizeof(strIpAddr), 0, sizeof(strIpAddr)) != EOK) { 199518678f8Sopenharmony_ci return "0.0.0.0"; 200518678f8Sopenharmony_ci } 201518678f8Sopenharmony_ci if (inet_ntop(AF_INET, &inAddr, strIpAddr, sizeof(strIpAddr)) == NULL) { 202518678f8Sopenharmony_ci return "0.0.0.0"; 203518678f8Sopenharmony_ci } 204518678f8Sopenharmony_ci return strIpAddr; 205518678f8Sopenharmony_ci} 206518678f8Sopenharmony_ci 207518678f8Sopenharmony_cichar *ParseStrMac(const uint8_t *macAddr, size_t addrSize) 208518678f8Sopenharmony_ci{ 209518678f8Sopenharmony_ci static char strMacAddr[MAD_ADDR_BUF_SIZE] = {0}; 210518678f8Sopenharmony_ci if (!macAddr || addrSize < MAC_ADDR_LENGTH) { 211518678f8Sopenharmony_ci return 0; 212518678f8Sopenharmony_ci } 213518678f8Sopenharmony_ci if (memset_s(strMacAddr, MAD_ADDR_BUF_SIZE, '\0', sizeof(strMacAddr)) != EOK || 214518678f8Sopenharmony_ci sprintf_s(strMacAddr, MAD_ADDR_BUF_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", macAddr[MAI_ZERO], 215518678f8Sopenharmony_ci macAddr[MAI_ONE], macAddr[MAI_TWO], macAddr[MAI_THREE], macAddr[MAI_FOUR], macAddr[MAI_FIVE]) < 0) { 216518678f8Sopenharmony_ci return 0; 217518678f8Sopenharmony_ci } 218518678f8Sopenharmony_ci return strMacAddr; 219518678f8Sopenharmony_ci} 220518678f8Sopenharmony_ci 221518678f8Sopenharmony_cistatic int8_t IsValidHexCharAndConvert(char c) 222518678f8Sopenharmony_ci{ 223518678f8Sopenharmony_ci if (c >= '0' && c <= '9') { 224518678f8Sopenharmony_ci return c - '0'; 225518678f8Sopenharmony_ci } 226518678f8Sopenharmony_ci if (c >= 'a' && c <= 'f') { 227518678f8Sopenharmony_ci return c - 'a' + ('9' - '0' + 1); 228518678f8Sopenharmony_ci } 229518678f8Sopenharmony_ci if (c >= 'A' && c <= 'F') { 230518678f8Sopenharmony_ci return c - 'A' + ('9' - '0' + 1); 231518678f8Sopenharmony_ci } 232518678f8Sopenharmony_ci return -1; 233518678f8Sopenharmony_ci} 234518678f8Sopenharmony_ci 235518678f8Sopenharmony_ciint ParseMacAddress(const char *strMac, uint8_t macAddr[DHCP_HWADDR_LENGTH]) 236518678f8Sopenharmony_ci{ 237518678f8Sopenharmony_ci if (strMac == NULL || strlen(strMac) != MAC_STRING_SIZE) { 238518678f8Sopenharmony_ci return DHCP_FALSE; 239518678f8Sopenharmony_ci } 240518678f8Sopenharmony_ci size_t len = strlen(strMac); 241518678f8Sopenharmony_ci const int shiftNum = 4; 242518678f8Sopenharmony_ci const int macSpaceNum = 3; 243518678f8Sopenharmony_ci unsigned char tmp = 0; 244518678f8Sopenharmony_ci for (size_t i = 0, j = 0; i < len; ++i) { 245518678f8Sopenharmony_ci if (j == 0 || j == 1) { 246518678f8Sopenharmony_ci int8_t v = IsValidHexCharAndConvert(strMac[i]); 247518678f8Sopenharmony_ci if (v < 0) { 248518678f8Sopenharmony_ci return 0; 249518678f8Sopenharmony_ci } 250518678f8Sopenharmony_ci tmp <<= shiftNum; 251518678f8Sopenharmony_ci tmp |= static_cast<unsigned char>(v); 252518678f8Sopenharmony_ci ++j; 253518678f8Sopenharmony_ci } else { 254518678f8Sopenharmony_ci if (strMac[i] != ':') { 255518678f8Sopenharmony_ci return 0; 256518678f8Sopenharmony_ci } 257518678f8Sopenharmony_ci macAddr[i / macSpaceNum] = tmp; 258518678f8Sopenharmony_ci j = 0; 259518678f8Sopenharmony_ci tmp = 0; 260518678f8Sopenharmony_ci } 261518678f8Sopenharmony_ci } 262518678f8Sopenharmony_ci macAddr[MAC_STRING_SIZE / macSpaceNum] = tmp; 263518678f8Sopenharmony_ci return DHCP_TRUE; 264518678f8Sopenharmony_ci} 265518678f8Sopenharmony_ci 266518678f8Sopenharmony_ciuint32_t HostToNetwork(uint32_t host) 267518678f8Sopenharmony_ci{ 268518678f8Sopenharmony_ci return htonl(host); 269518678f8Sopenharmony_ci} 270518678f8Sopenharmony_ci 271518678f8Sopenharmony_ciuint32_t NetworkToHost(uint32_t network) 272518678f8Sopenharmony_ci{ 273518678f8Sopenharmony_ci return ntohl(network); 274518678f8Sopenharmony_ci} 275518678f8Sopenharmony_ci 276518678f8Sopenharmony_cichar *ParseLogMac(uint8_t macAddr[DHCP_HWADDR_LENGTH]) 277518678f8Sopenharmony_ci{ 278518678f8Sopenharmony_ci static char strLogMacAddr[MAD_ADDR_BUF_SIZE] = {0}; 279518678f8Sopenharmony_ci if (!macAddr) { 280518678f8Sopenharmony_ci return 0; 281518678f8Sopenharmony_ci } 282518678f8Sopenharmony_ci if (memset_s(strLogMacAddr, MAD_ADDR_BUF_SIZE, '\0', MAD_ADDR_BUF_SIZE) != EOK || 283518678f8Sopenharmony_ci sprintf_s(strLogMacAddr, MAD_ADDR_BUF_SIZE, "??:%02x:??:??:%02x:%02x", macAddr[NUM_ONE], macAddr[MAI_FOUR], 284518678f8Sopenharmony_ci macAddr[MAI_FIVE]) < 0) { 285518678f8Sopenharmony_ci return 0; 286518678f8Sopenharmony_ci } 287518678f8Sopenharmony_ci return strLogMacAddr; 288518678f8Sopenharmony_ci} 289518678f8Sopenharmony_ci 290518678f8Sopenharmony_ciint IsEmptyHWAddr(const uint8_t macAddr[DHCP_HWADDR_LENGTH]) 291518678f8Sopenharmony_ci{ 292518678f8Sopenharmony_ci for (int i = 0; i < MAC_ADDR_LENGTH; i++) { 293518678f8Sopenharmony_ci if (macAddr[i] != 0) { 294518678f8Sopenharmony_ci return DHCP_FALSE; 295518678f8Sopenharmony_ci } 296518678f8Sopenharmony_ci } 297518678f8Sopenharmony_ci return DHCP_TRUE; 298518678f8Sopenharmony_ci} 299518678f8Sopenharmony_ci 300518678f8Sopenharmony_ciint AddrEquels(const uint8_t firstAddr[DHCP_HWADDR_LENGTH], uint8_t secondAddr[DHCP_HWADDR_LENGTH], int addrLength) 301518678f8Sopenharmony_ci{ 302518678f8Sopenharmony_ci int len = addrLength; 303518678f8Sopenharmony_ci if (len > DHCP_HWADDR_LENGTH) { 304518678f8Sopenharmony_ci len = DHCP_HWADDR_LENGTH; 305518678f8Sopenharmony_ci } 306518678f8Sopenharmony_ci for (int i = 0; i < len; i++) { 307518678f8Sopenharmony_ci if ((firstAddr[i] != secondAddr[i])) { 308518678f8Sopenharmony_ci return DHCP_FALSE; 309518678f8Sopenharmony_ci } 310518678f8Sopenharmony_ci } 311518678f8Sopenharmony_ci return DHCP_TRUE; 312518678f8Sopenharmony_ci} 313518678f8Sopenharmony_ci 314518678f8Sopenharmony_ciint ParseHostName(const char *strHostName, char hostName[DHCP_BOOT_FILE_LENGTH]) 315518678f8Sopenharmony_ci{ 316518678f8Sopenharmony_ci if (strHostName == nullptr || hostName == nullptr) { 317518678f8Sopenharmony_ci return DHCP_FALSE; 318518678f8Sopenharmony_ci } 319518678f8Sopenharmony_ci if (memcpy_s(hostName, DHCP_BOOT_FILE_LENGTH, strHostName, strlen(strHostName)) != EOK) { 320518678f8Sopenharmony_ci return DHCP_FALSE; 321518678f8Sopenharmony_ci } 322518678f8Sopenharmony_ci return DHCP_TRUE; 323518678f8Sopenharmony_ci} 324