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