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 "dhcp_binding.h" 17518678f8Sopenharmony_ci#include <securec.h> 18518678f8Sopenharmony_ci#include <stdint.h> 19518678f8Sopenharmony_ci#include <stdlib.h> 20518678f8Sopenharmony_ci#include <string.h> 21518678f8Sopenharmony_ci#include <time.h> 22518678f8Sopenharmony_ci#include "address_utils.h" 23518678f8Sopenharmony_ci#include "common_util.h" 24518678f8Sopenharmony_ci#include "dhcp_s_define.h" 25518678f8Sopenharmony_ci#include "dhcp_logger.h" 26518678f8Sopenharmony_ci 27518678f8Sopenharmony_ciDEFINE_DHCPLOG_DHCP_LABEL("DhcpServerBinding"); 28518678f8Sopenharmony_ci 29518678f8Sopenharmony_ci#define PENDING_INTERVAL_MAX_TIME 1200 30518678f8Sopenharmony_ci#define PENDING_INTERVAL_LEVEL0 3 31518678f8Sopenharmony_ci#define PENDING_INTERVAL_LEVEL1 10 32518678f8Sopenharmony_ci#define PENDING_INTERVAL_LEVEL2 30 33518678f8Sopenharmony_ci#define PENDING_MIN_WAITING_TIMES 1 34518678f8Sopenharmony_ci#define PENDING_INTERVAL_LEVEL1_TIMES 2 35518678f8Sopenharmony_ci#define PENDING_INTERVAL_LEVEL2_TIMES 5 36518678f8Sopenharmony_ci 37518678f8Sopenharmony_ciuint64_t NextPendingInterval(uint64_t pendingInterval) 38518678f8Sopenharmony_ci{ 39518678f8Sopenharmony_ci uint64_t next = pendingInterval; 40518678f8Sopenharmony_ci if (next < PENDING_INTERVAL_LEVEL0) { 41518678f8Sopenharmony_ci next += PENDING_MIN_WAITING_TIMES; 42518678f8Sopenharmony_ci } else if (next < PENDING_INTERVAL_LEVEL1) { 43518678f8Sopenharmony_ci next += PENDING_INTERVAL_LEVEL1_TIMES; 44518678f8Sopenharmony_ci } else if (next < PENDING_INTERVAL_LEVEL2) { 45518678f8Sopenharmony_ci next += PENDING_INTERVAL_LEVEL2_TIMES; 46518678f8Sopenharmony_ci } else { 47518678f8Sopenharmony_ci next = PENDING_INTERVAL_MAX_TIME; 48518678f8Sopenharmony_ci } 49518678f8Sopenharmony_ci return next; 50518678f8Sopenharmony_ci} 51518678f8Sopenharmony_ci 52518678f8Sopenharmony_ciint IsExpire(AddressBinding *binding) 53518678f8Sopenharmony_ci{ 54518678f8Sopenharmony_ci if (!binding) { 55518678f8Sopenharmony_ci DHCP_LOGE("binding is null."); 56518678f8Sopenharmony_ci return DHCP_FALSE; 57518678f8Sopenharmony_ci } 58518678f8Sopenharmony_ci uint64_t leaseTime = binding->leaseTime; 59518678f8Sopenharmony_ci if (!leaseTime) { 60518678f8Sopenharmony_ci leaseTime = DHCP_LEASE_TIME; 61518678f8Sopenharmony_ci } 62518678f8Sopenharmony_ci uint64_t expireIn = binding->expireIn; 63518678f8Sopenharmony_ci if (binding->bindingStatus == BIND_PENDING) { 64518678f8Sopenharmony_ci expireIn = binding->pendingTime + leaseTime; 65518678f8Sopenharmony_ci } else if (binding->bindingStatus == BIND_ASSOCIATED) { 66518678f8Sopenharmony_ci expireIn = binding->bindingTime + leaseTime; 67518678f8Sopenharmony_ci } 68518678f8Sopenharmony_ci uint64_t curr = Tmspsec(); 69518678f8Sopenharmony_ci if (curr > expireIn) { 70518678f8Sopenharmony_ci binding->bindingStatus = BIND_EXPIRED; 71518678f8Sopenharmony_ci return DHCP_TRUE; 72518678f8Sopenharmony_ci } 73518678f8Sopenharmony_ci return DHCP_FALSE; 74518678f8Sopenharmony_ci} 75518678f8Sopenharmony_ci 76518678f8Sopenharmony_ci#define BINDING_MAC_ADDR_POS 0 77518678f8Sopenharmony_ci#define BINDING_IP_ADDR_POS 1 78518678f8Sopenharmony_ci#define BINDING_LEASE_TIME_POS 2 79518678f8Sopenharmony_ci#define BINDING_BINDING_TIME_POS 3 80518678f8Sopenharmony_ci#define BINDING_PENDING_TIME_POS 4 81518678f8Sopenharmony_ci#define BINDING_PENDING_INTERVAL_POS 5 82518678f8Sopenharmony_ci#define BINDING_BINDING_MODE_POS 6 83518678f8Sopenharmony_ci#define BINDING_BINDING_STATUS_POS 7 84518678f8Sopenharmony_ci#define BINDING_DEVICE_NAME_POS 8 85518678f8Sopenharmony_ci#define BINDING_STRING_SIZE 8 86518678f8Sopenharmony_ci#define BINDING_STRING_MAX_SIZE 9 87518678f8Sopenharmony_ci 88518678f8Sopenharmony_ciint WriteAddressBinding(const AddressBinding *binding, char *out, uint32_t size) 89518678f8Sopenharmony_ci{ 90518678f8Sopenharmony_ci if (!binding || !out) { 91518678f8Sopenharmony_ci return RET_FAILED; 92518678f8Sopenharmony_ci } 93518678f8Sopenharmony_ci const char *mac = ParseStrMac(binding->chaddr, sizeof(binding->chaddr)); 94518678f8Sopenharmony_ci const char *ip = ParseStrIp(binding->ipAddress); 95518678f8Sopenharmony_ci if (mac == nullptr || ip == nullptr) { 96518678f8Sopenharmony_ci return RET_FAILED; 97518678f8Sopenharmony_ci } 98518678f8Sopenharmony_ci if (snprintf_s(out, size, size - 1, "%s %s %llu %llu %llu %llu %d %d %s", mac, ip, binding->leaseTime, 99518678f8Sopenharmony_ci binding->bindingTime, binding->pendingTime, binding->pendingInterval, binding->bindingMode, 100518678f8Sopenharmony_ci binding->bindingStatus, binding->deviceName) < 0) { 101518678f8Sopenharmony_ci return RET_FAILED; 102518678f8Sopenharmony_ci } 103518678f8Sopenharmony_ci return RET_SUCCESS; 104518678f8Sopenharmony_ci} 105518678f8Sopenharmony_ci 106518678f8Sopenharmony_cistatic void ReleaseStrings(char **strs) 107518678f8Sopenharmony_ci{ 108518678f8Sopenharmony_ci if (strs == nullptr) { 109518678f8Sopenharmony_ci return; 110518678f8Sopenharmony_ci } 111518678f8Sopenharmony_ci int i = 0; 112518678f8Sopenharmony_ci while (strs[i] != nullptr) { 113518678f8Sopenharmony_ci free(strs[i]); 114518678f8Sopenharmony_ci strs[i] = nullptr; 115518678f8Sopenharmony_ci ++i; 116518678f8Sopenharmony_ci } 117518678f8Sopenharmony_ci free(strs); 118518678f8Sopenharmony_ci strs = nullptr; 119518678f8Sopenharmony_ci return; 120518678f8Sopenharmony_ci} 121518678f8Sopenharmony_ci 122518678f8Sopenharmony_cistatic char **SplitString(const char *buf, const char *split) 123518678f8Sopenharmony_ci{ 124518678f8Sopenharmony_ci const char *pos = buf; 125518678f8Sopenharmony_ci const char *p = nullptr; 126518678f8Sopenharmony_ci size_t len = strlen(split); 127518678f8Sopenharmony_ci int num = 0; 128518678f8Sopenharmony_ci while ((p = strstr(pos, split)) != nullptr) { 129518678f8Sopenharmony_ci if (p != pos) { 130518678f8Sopenharmony_ci ++num; 131518678f8Sopenharmony_ci } 132518678f8Sopenharmony_ci pos = p + len; 133518678f8Sopenharmony_ci } 134518678f8Sopenharmony_ci if (*pos != '\0') { 135518678f8Sopenharmony_ci ++num; 136518678f8Sopenharmony_ci } 137518678f8Sopenharmony_ci if (num == 0) { 138518678f8Sopenharmony_ci return nullptr; 139518678f8Sopenharmony_ci } 140518678f8Sopenharmony_ci char **strs = (char **)calloc(num + 1, sizeof(char *)); 141518678f8Sopenharmony_ci if (strs == nullptr) { 142518678f8Sopenharmony_ci return nullptr; 143518678f8Sopenharmony_ci } 144518678f8Sopenharmony_ci pos = buf; 145518678f8Sopenharmony_ci num = 0; 146518678f8Sopenharmony_ci while ((p = strstr(pos, split)) != nullptr) { 147518678f8Sopenharmony_ci if (p != pos) { 148518678f8Sopenharmony_ci size_t strLen = p - pos + 1; 149518678f8Sopenharmony_ci strs[num] = (char *)calloc(strLen, sizeof(char)); 150518678f8Sopenharmony_ci if (strs[num] == nullptr || strncpy_s(strs[num], strLen, pos, p - pos) != EOK) { 151518678f8Sopenharmony_ci ReleaseStrings(strs); 152518678f8Sopenharmony_ci return nullptr; 153518678f8Sopenharmony_ci } 154518678f8Sopenharmony_ci ++num; 155518678f8Sopenharmony_ci } 156518678f8Sopenharmony_ci pos = p + len; 157518678f8Sopenharmony_ci } 158518678f8Sopenharmony_ci if (*pos != '\0') { 159518678f8Sopenharmony_ci size_t strLen = strlen(pos) + 1; 160518678f8Sopenharmony_ci strs[num] = (char *)calloc(strLen, sizeof(char)); 161518678f8Sopenharmony_ci if (strs[num] == nullptr || strncpy_s(strs[num], strLen, pos, strlen(pos)) != EOK) { 162518678f8Sopenharmony_ci ReleaseStrings(strs); 163518678f8Sopenharmony_ci return nullptr; 164518678f8Sopenharmony_ci } 165518678f8Sopenharmony_ci } 166518678f8Sopenharmony_ci return strs; 167518678f8Sopenharmony_ci} 168518678f8Sopenharmony_ci 169518678f8Sopenharmony_ciint ParseAddressBinding(AddressBinding *binding, const char *buf) 170518678f8Sopenharmony_ci{ 171518678f8Sopenharmony_ci uint64_t curr = Tmspsec(); 172518678f8Sopenharmony_ci char **strs = SplitString(buf, " "); 173518678f8Sopenharmony_ci if (strs == nullptr) { 174518678f8Sopenharmony_ci return -1; 175518678f8Sopenharmony_ci } 176518678f8Sopenharmony_ci int num = 0; 177518678f8Sopenharmony_ci while (strs[num] != nullptr) { 178518678f8Sopenharmony_ci ++num; 179518678f8Sopenharmony_ci } 180518678f8Sopenharmony_ci int ret = -1; 181518678f8Sopenharmony_ci do { 182518678f8Sopenharmony_ci if (num < BINDING_STRING_SIZE) { 183518678f8Sopenharmony_ci break; 184518678f8Sopenharmony_ci } 185518678f8Sopenharmony_ci ParseMacAddress(strs[BINDING_MAC_ADDR_POS], binding->chaddr); 186518678f8Sopenharmony_ci binding->ipAddress = ParseIpAddr(strs[BINDING_IP_ADDR_POS]); 187518678f8Sopenharmony_ci binding->leaseTime = atol(strs[BINDING_LEASE_TIME_POS]); 188518678f8Sopenharmony_ci binding->bindingTime = atol(strs[BINDING_BINDING_TIME_POS]); 189518678f8Sopenharmony_ci binding->pendingTime = atol(strs[BINDING_PENDING_TIME_POS]); 190518678f8Sopenharmony_ci if (binding->bindingTime && binding->bindingTime < binding->pendingTime) { 191518678f8Sopenharmony_ci break; 192518678f8Sopenharmony_ci } 193518678f8Sopenharmony_ci if (binding->pendingTime > curr) { /* if pending time over than current system time */ 194518678f8Sopenharmony_ci binding->bindingTime = binding->bindingTime - binding->pendingTime + curr; 195518678f8Sopenharmony_ci binding->pendingTime = curr; 196518678f8Sopenharmony_ci } 197518678f8Sopenharmony_ci binding->pendingInterval = atol(strs[BINDING_PENDING_INTERVAL_POS]); 198518678f8Sopenharmony_ci binding->bindingMode = atoi(strs[BINDING_BINDING_MODE_POS]); 199518678f8Sopenharmony_ci binding->bindingStatus = atoi(strs[BINDING_BINDING_STATUS_POS]); 200518678f8Sopenharmony_ci if (binding->bindingStatus == BIND_ASSOCIATED) { 201518678f8Sopenharmony_ci binding->expireIn = binding->bindingTime + binding->leaseTime; 202518678f8Sopenharmony_ci } 203518678f8Sopenharmony_ci if (num >= BINDING_STRING_MAX_SIZE) { 204518678f8Sopenharmony_ci ParseHostName(strs[BINDING_DEVICE_NAME_POS], binding->deviceName); 205518678f8Sopenharmony_ci DHCP_LOGI("ParseHostName deviceName:%{public}s", binding->deviceName); 206518678f8Sopenharmony_ci } 207518678f8Sopenharmony_ci ret += 1; /* set ret = 0 */ 208518678f8Sopenharmony_ci } while (0); 209518678f8Sopenharmony_ci ReleaseStrings(strs); 210518678f8Sopenharmony_ci return ret; 211518678f8Sopenharmony_ci} 212