1/* 2 * Copyright (C) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include "dhcp_function.h" 16#include <arpa/inet.h> 17#include <time.h> 18#include <string.h> 19#include <sys/types.h> 20#include <sys/stat.h> 21#include <fcntl.h> 22#include <stdlib.h> 23#include <sys/socket.h> 24#include <unistd.h> 25#include <ifaddrs.h> 26#include <netdb.h> 27#include <net/if.h> 28#include <stdio.h> 29#include <errno.h> 30#include <netinet/in.h> 31#include <sys/ioctl.h> 32#include "securec.h" 33#include "dhcp_client_def.h" 34#include "dhcp_logger.h" 35 36DEFINE_DHCPLOG_DHCP_LABEL("DhcpFunction"); 37 38bool Ip4StrConToInt(const char *strIp, uint32_t *uIp, bool bHost) 39{ 40 if ((strIp == NULL) || (strlen(strIp) == 0)) { 41 DHCP_LOGE("Ip4StrConToInt failed, strIp == NULL or \"\"!"); 42 return false; 43 } 44 45 struct in_addr addr4; 46 int nRet = inet_pton(AF_INET, strIp, &addr4); 47 if (nRet != 1) { 48 DHCP_LOGE("Ip4StrConToInt strIp:%{private}s failed, inet_pton nRet:%{public}d!", strIp, nRet); 49 if (nRet == 0) { 50 DHCP_LOGE("Ip4StrConToInt strIp:%{private}s not in presentation format!", strIp); 51 } else { 52 DHCP_LOGE("Ip4StrConToInt strIp:%{private}s inet_pton does not contain a valid address family!", strIp); 53 } 54 return false; 55 } 56 57 if (bHost) { 58 *uIp = ntohl(addr4.s_addr); 59 } else { 60 *uIp = addr4.s_addr; 61 } 62 63 return true; 64} 65 66std::string Ip4IntConvertToStr(uint32_t ip, bool host) 67{ 68 char bufIp4[INET_ADDRSTRLEN] = {0}; 69 struct in_addr addr4; 70 if (host) { 71 addr4.s_addr = htonl(ip); 72 } else { 73 addr4.s_addr = ip; 74 } 75 76 std::string strIp = ""; 77 if (inet_ntop(AF_INET, &addr4, bufIp4, INET_ADDRSTRLEN) == nullptr) { 78 DHCP_LOGE("Ip4IntConvertToStr uIp:%{private}u failed, inet_ntop nullptr!", ip); 79 } else { 80 strIp = bufIp4; 81 DHCP_LOGI("Ip4IntConvertToStr uIp:%{private}u -> strIp:%{private}s.", ip, strIp.c_str()); 82 } 83 84 return strIp; 85} 86 87bool Ip6StrConToChar(const char *strIp, uint8_t chIp[], size_t chlen) 88{ 89 if ((strIp == NULL) || (strlen(strIp) == 0)) { 90 DHCP_LOGE("Ip6StrConToChar failed, strIp == NULL or \"\"!"); 91 return false; 92 } 93 94 struct in6_addr addr6; 95 if (memset_s(&addr6, sizeof(addr6), 0, sizeof(addr6)) != EOK) { 96 return false; 97 } 98 int nRet = inet_pton(AF_INET6, strIp, &addr6); 99 if (nRet != 1) { 100 DHCP_LOGE("Ip6StrConToChar strIp:%{private}s failed, inet_pton nRet:%{public}d!", strIp, nRet); 101 if (nRet == 0) { 102 DHCP_LOGE("Ip6StrConToChar strIp:%{private}s not in presentation format!", strIp); 103 } else { 104 DHCP_LOGE("Ip6StrConToChar strIp:%{private}s inet_pton does not contain a valid address family!", strIp); 105 } 106 return false; 107 } 108 109 DHCP_LOGI("Ip6StrConToChar strIp:%{private}s -> ", strIp); 110 for (size_t i = 0; (i < chlen) && (i < sizeof(addr6.s6_addr)); i++) { 111 DHCP_LOGI("Ip6StrConToChar addr6.s6_addr: %{private}zu - %{private}02x", i, addr6.s6_addr[i]); 112 chIp[i] = addr6.s6_addr[i]; 113 } 114 115 return true; 116} 117 118const char *MacChConToMacStr(const unsigned char *pChMac, size_t chLen, char *pStrMac, size_t strLen) 119{ 120 if ((pChMac == NULL) || (chLen == 0)) { 121 DHCP_LOGE("MacChConToMacStr failed, pChMac == NULL or chLen == 0!"); 122 return NULL; 123 } 124 125 if ((pStrMac == NULL) || (strLen < (chLen * MAC_ADDR_CHAR_NUM))) { 126 DHCP_LOGE("MacChConToMacStr failed, pStrMac == NULL or strLen:%{public}d error!", (int)strLen); 127 return NULL; 128 } 129 130 const unsigned char *pSrc = pChMac; 131 const unsigned char *pSrcEnd = pSrc + chLen; 132 char *pDest = pStrMac; 133 for (; pSrc < pSrcEnd; pSrc++) { 134 /* The first character of pStrMac starts with a letter, not ':'. */ 135 if (pSrc != pChMac) { 136 *(pDest++) = ':'; 137 } 138 pDest += snprintf_s(pDest, MAC_ADDR_CHAR_NUM, MAC_ADDR_CHAR_NUM - 1, "%.2x", *pSrc); 139 } 140 /* The last character of pStrMac ends with '\0'. */ 141 *(pDest++) = '\0'; 142 return pStrMac; 143} 144 145int GetLocalInterface(const char *ifname, int *ifindex, unsigned char *hwaddr, uint32_t *ifaddr4) 146{ 147 if ((ifname == NULL) || (strlen(ifname) == 0) || hwaddr == NULL) { 148 DHCP_LOGE("GetLocalInterface() failed, ifname == NULL or hwaddr is NULL"); 149 return DHCP_OPT_FAILED; 150 } 151 152 int fd; 153 struct ifreq iface; 154 struct sockaddr_in *pSockIn = NULL; 155 156 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 157 DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, socket err:%{public}d!", ifname, errno); 158 return DHCP_OPT_FAILED; 159 } 160 161 if (memset_s(&iface, sizeof(iface), 0, sizeof(iface)) != EOK) { 162 DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, memset_s error!", ifname); 163 close(fd); 164 return DHCP_OPT_FAILED; 165 } 166 if (strncpy_s(iface.ifr_name, sizeof(iface.ifr_name), ifname, strlen(ifname)) != EOK) { 167 DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, strncpy_s error!", ifname); 168 close(fd); 169 return DHCP_OPT_FAILED; 170 } 171 172 if (ioctl(fd, SIOCGIFINDEX, &iface) != 0) { 173 DHCP_LOGE("GetLocalInterface() %{public}s failed, SIOCGIFINDEX err:%{public}d!", ifname, errno); 174 close(fd); 175 return DHCP_OPT_FAILED; 176 } 177 *ifindex = iface.ifr_ifindex; 178 179 if (ioctl(fd, SIOCGIFHWADDR, &iface) != 0) { 180 DHCP_LOGE("GetLocalInterface() %{public}s failed, SIOCGIFHWADDR err:%{public}d!", ifname, errno); 181 close(fd); 182 return DHCP_OPT_FAILED; 183 } 184 if (memcpy_s(hwaddr, MAC_ADDR_LEN, iface.ifr_hwaddr.sa_data, MAC_ADDR_LEN) != EOK) { 185 DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, memcpy_s error!", ifname); 186 close(fd); 187 return DHCP_OPT_FAILED; 188 } 189 190 if (ifaddr4 != NULL) { 191 if (ioctl(fd, SIOCGIFADDR, &iface) < 0) { 192 DHCP_LOGE("GetLocalInterface() %{public}s failed, SIOCGIFADDR err:%{public}d!", ifname, errno); 193 close(fd); 194 return DHCP_OPT_FAILED; 195 } 196 pSockIn = (struct sockaddr_in *)&iface.ifr_addr; 197 *ifaddr4 = pSockIn->sin_addr.s_addr; 198 } 199 close(fd); 200 return DHCP_OPT_SUCCESS; 201} 202 203int GetLocalIp(const char *ifname, uint32_t *ifaddr4) 204{ 205 if ((ifname == NULL) || (strlen(ifname) == 0)) { 206 DHCP_LOGE("GetLocalIp() failed, ifname == NULL or \"\"!"); 207 return DHCP_OPT_FAILED; 208 } 209 210 struct ifaddrs *ifaddr = NULL; 211 struct ifaddrs *ifa = NULL; 212 int family, s; 213 char strIp[NI_MAXHOST]; 214 215 if (getifaddrs(&ifaddr) == -1) { 216 DHCP_LOGE("GetLocalIp() ifname:%{public}s failed, getifaddrs error:%{public}d!", ifname, errno); 217 return DHCP_OPT_FAILED; 218 } 219 220 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { 221 if (strcmp(ifa->ifa_name, ifname) != 0) { 222 continue; 223 } 224 225 if (ifa->ifa_addr == NULL) { 226 DHCP_LOGE("GetLocalIp() ifname:%{public}s failed, ifa->ifa_addr == NULL!", ifname); 227 continue; 228 } 229 230 family = ifa->ifa_addr->sa_family; 231 if ((family != AF_INET) && (family != AF_INET6)) { 232 continue; 233 } 234 235 if (memset_s(strIp, sizeof(strIp), 0, sizeof(strIp)) != EOK) { 236 return DHCP_OPT_FAILED; 237 } 238 s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), 239 strIp, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); 240 if (s != 0) { 241 DHCP_LOGE("GetLocalIp() %{public}s failed, getnameinfo error:%{public}s!", ifname, gai_strerror(s)); 242 return DHCP_OPT_FAILED; 243 } 244 245 /* Output all ip with ifa_name is ifname and family is AF_INET or AF_INET6. */ 246 if (family == AF_INET) { 247 uint32_t hostIp = 0; 248 if (!Ip4StrConToInt(strIp, &hostIp, true)) { 249 DHCP_LOGE("GetLocalIp() %{public}s failed, Ip4StrConToInt strIp:%{private}s error!", ifname, strIp); 250 return DHCP_OPT_FAILED; 251 } 252 DHCP_LOGI("GetLocalIp() %{public}s, AF_INET str:%{private}s -> host:%{private}u.", ifname, strIp, hostIp); 253 *ifaddr4 = hostIp; 254 } else { 255 DHCP_LOGI("GetLocalIp() %{public}s, AF_INET6 strIp:%{private}s.", ifname, strIp); 256 } 257 } 258 259 freeifaddrs(ifaddr); 260 return DHCP_OPT_SUCCESS; 261} 262 263int SetIpOrMask(const char *ifname, int fd, uint32_t netAddr, unsigned long cmd) 264{ 265 struct ifreq ifr; 266 struct sockaddr_in sin; 267 if (memset_s(&ifr, sizeof(struct ifreq), 0, sizeof(struct ifreq)) != EOK) { 268 DHCP_LOGE("SetIpOrMask() failed, memset_s ifr error!"); 269 return DHCP_OPT_FAILED; 270 } 271 272 if (strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifname, strlen(ifname)) != EOK) { 273 DHCP_LOGE("SetIpOrMask() %{public}s failed, , strncpy_s ifr.ifr_name error!", ifname); 274 return DHCP_OPT_FAILED; 275 } 276 277 if (memset_s(&sin, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in)) != EOK) { 278 DHCP_LOGE("SetIpOrMask() failed, memset_s sin error!"); 279 return DHCP_OPT_FAILED; 280 } 281 sin.sin_family = AF_INET; 282 sin.sin_addr.s_addr = netAddr; 283 if (memcpy_s(&ifr.ifr_addr, sizeof(ifr.ifr_addr), &sin, sizeof(struct sockaddr)) != EOK) { 284 DHCP_LOGE("SetIpOrMask() failed, memcpy_s ifr.ifr_addr error!"); 285 return DHCP_OPT_FAILED; 286 } 287 288 if (ioctl(fd, cmd, &ifr) < 0) { 289 DHCP_LOGE("SetIpOrMask() %{public}s failed!", ifname); 290 return DHCP_OPT_FAILED; 291 } 292 return DHCP_OPT_SUCCESS; 293} 294 295int SetLocalInterface(const char *ifname, uint32_t ipAddr, uint32_t netMask) 296{ 297 if ((ifname == NULL) || (strlen(ifname) == 0)) { 298 DHCP_LOGE("SetLocalInterface() failed, ifname == NULL or \"\"!"); 299 return DHCP_OPT_FAILED; 300 } 301 302 int fd = socket(AF_INET, SOCK_DGRAM, 0); 303 if (fd < 0) { 304 DHCP_LOGE("SetLocalInterface() ifname:%{public}s failed, socket error:%{public}d!", ifname, errno); 305 return DHCP_OPT_FAILED; 306 } 307 308 if (SetIpOrMask(ifname, fd, ipAddr, SIOCSIFADDR) != DHCP_OPT_SUCCESS) { 309 close(fd); 310 return DHCP_OPT_FAILED; 311 } 312 313 if (SetIpOrMask(ifname, fd, netMask, SIOCSIFNETMASK) != DHCP_OPT_SUCCESS) { 314 close(fd); 315 return DHCP_OPT_FAILED; 316 } 317 close(fd); 318 return DHCP_OPT_SUCCESS; 319} 320 321int InitPidfile(const char *pidDir, const char *pidFile, pid_t pid) 322{ 323 if ((pidDir == NULL) || (strlen(pidDir) == 0) || (pidFile == NULL) || (strlen(pidFile) == 0)) { 324 DHCP_LOGE("InitPidfile() failed, pidDir or pidFile == NULL or \"\"!"); 325 return DHCP_OPT_FAILED; 326 } 327 DHCP_LOGI("InitPidfile() pidDir:%{public}s, pidFile:%{public}s.", pidDir, pidFile); 328 unlink(pidFile); 329 330 int fd; 331 if ((fd = open(pidFile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) { 332 DHCP_LOGE("InitPidfile() failed, open pidFile:%{public}s error:%{public}d!", pidFile, errno); 333 return DHCP_OPT_FAILED; 334 } 335 336 char buf[PID_MAX_LEN] = {0}; 337 if (snprintf_s(buf, PID_MAX_LEN, PID_MAX_LEN - 1, "%d", pid) < 0) { 338 DHCP_LOGE("InitPidfile() pidFile:%{public}s failed, snprintf_s error:%{public}d!", pidFile, errno); 339 close(fd); 340 return DHCP_OPT_FAILED; 341 } 342 ssize_t bytes; 343 if ((bytes = write(fd, buf, strlen(buf))) <= 0) { 344 DHCP_LOGE("InitPidfile() failed, write pidFile:%{public}s error:%{public}d, bytes:%{public}zd!", 345 pidFile, errno, bytes); 346 close(fd); 347 return DHCP_OPT_FAILED; 348 } 349 DHCP_LOGI("InitPidfile() buf:%{public}s write pidFile:%{public}s, bytes:%{public}zd!", buf, pidFile, bytes); 350 close(fd); 351 352 if (chdir(pidDir) != 0) { 353 DHCP_LOGE("InitPidfile() failed, chdir pidDir:%{public}s error:%{public}d!", pidDir, errno); 354 return DHCP_OPT_FAILED; 355 } 356 357 /* Set default permissions for the specified client process id files and directories. */ 358 umask(DEFAULT_UMASK); 359 360 /* Change attribs to the specified client process id files: 644 (user=rw, group=r, other=r). */ 361 chmod(pidFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 362 363 return DHCP_OPT_SUCCESS; 364} 365 366pid_t GetPID(const char *pidFile) 367{ 368 /* Check pidFile is or not exists. */ 369 struct stat sb; 370 if (stat(pidFile, &sb) != 0) { 371 DHCP_LOGW("GetPID() pidFile:%{public}s stat error:%{public}d!", pidFile, errno); 372 return -1; 373 } 374 DHCP_LOGI("GetPID() pidFile:%{public}s stat st_size:%{public}d.", pidFile, (int)sb.st_size); 375 376 int fd; 377 if ((fd = open(pidFile, O_RDONLY)) < 0) { 378 DHCP_LOGE("GetPID() failed, open pidFile:%{public}s error!", pidFile); 379 return -1; 380 } 381 382 lseek(fd, 0, SEEK_SET); 383 384 char buf[PID_MAX_LEN] = {0}; 385 if (sb.st_size > PID_MAX_LEN) { 386 DHCP_LOGE("GetPID() invalid length, size:%{public}d", (int)sb.st_size); 387 return -1; 388 } 389 ssize_t bytes; 390 if ((bytes = read(fd, buf, sb.st_size)) < 0) { 391 DHCP_LOGE("GetPID() failed, read pidFile:%{public}s error, bytes:%{public}zd!", pidFile, bytes); 392 close(fd); 393 return -1; 394 } 395 DHCP_LOGI("GetPID() read pidFile:%{public}s, buf:%{public}s, bytes:%{public}zd.", pidFile, buf, bytes); 396 close(fd); 397 398 return atoi(buf); 399} 400 401int CreateDirs(const char *dirs, int mode) 402{ 403 if ((dirs == NULL) || (strlen(dirs) == 0) || (strlen(dirs) >= DIR_MAX_LEN)) { 404 DHCP_LOGE("CreateDirs() dirs:%{public}s error!", dirs); 405 return DHCP_OPT_FAILED; 406 } 407 408 int nSrcLen = (int)strlen(dirs); 409 char strDir[DIR_MAX_LEN] = {0}; 410 if (strncpy_s(strDir, sizeof(strDir), dirs, strlen(dirs)) != EOK) { 411 DHCP_LOGE("CreateDirs() strncpy_s dirs:%{public}s failed!", dirs); 412 return DHCP_OPT_FAILED; 413 } 414 if (strDir[nSrcLen - 1] != '/') { 415 if (nSrcLen == (DIR_MAX_LEN - 1)) { 416 DHCP_LOGE("CreateDirs() dirs:%{public}s len:%{public}d error!", dirs, nSrcLen); 417 return DHCP_OPT_FAILED; 418 } 419 if (strcat_s(strDir, sizeof(strDir), "/") != EOK) { 420 DHCP_LOGE("CreateDirs() strcat_s strDir:%{public}s failed!", strDir); 421 return DHCP_OPT_FAILED; 422 } 423 nSrcLen++; 424 } 425 426 int i = (strDir[0] == '/') ? 1 : 0; 427 for (; i <= nSrcLen - 1; i++) { 428 if (strDir[i] == '/') { 429 strDir[i] = 0; 430 if ((access(strDir, F_OK) != 0) && (mkdir(strDir, mode) != 0)) { 431 DHCP_LOGE("CreateDirs() mkdir %{public}s %{public}.4o failed:%{public}d!", strDir, mode, errno); 432 return DHCP_OPT_FAILED; 433 } 434 strDir[i] = '/'; 435 } 436 } 437 DHCP_LOGI("CreateDirs() %{public}s %{public}.4o success.", dirs, mode); 438 return DHCP_OPT_SUCCESS; 439} 440