1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2021 Intel Corporation. All rights reserved. 3 * Copyright (C) 2024 Samsung Electronics Co., Ltd. 4 * All rights reserved. 5 */ 6 7 #include "spdk/stdinc.h" 8 #include "spdk/net.h" 9 10 int 11 spdk_net_get_interface_name(const char *ip, char *ifc, size_t len) 12 { 13 struct ifaddrs *addrs, *iap; 14 struct sockaddr_in *sa; 15 char buf[32]; 16 int rc = -ENODEV; 17 18 getifaddrs(&addrs); 19 for (iap = addrs; iap != NULL; iap = iap->ifa_next) { 20 if (!(iap->ifa_addr && (iap->ifa_flags & IFF_UP) && iap->ifa_addr->sa_family == AF_INET)) { 21 continue; 22 } 23 sa = (struct sockaddr_in *)(iap->ifa_addr); 24 inet_ntop(iap->ifa_addr->sa_family, &sa->sin_addr, buf, sizeof(buf)); 25 if (strcmp(ip, buf) != 0) { 26 continue; 27 } 28 if (strnlen(iap->ifa_name, len) == len) { 29 rc = -ENOMEM; 30 goto ret; 31 } 32 snprintf(ifc, len, "%s", iap->ifa_name); 33 rc = 0; 34 break; 35 } 36 ret: 37 freeifaddrs(addrs); 38 return rc; 39 } 40 41 int 42 spdk_net_get_address_string(struct sockaddr *sa, char *addr, size_t len) 43 { 44 const char *result = NULL; 45 46 if (sa == NULL || addr == NULL) { 47 return -1; 48 } 49 50 switch (sa->sa_family) { 51 case AF_INET: 52 result = inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), 53 addr, len); 54 break; 55 case AF_INET6: 56 result = inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), 57 addr, len); 58 break; 59 default: 60 break; 61 } 62 63 if (result != NULL) { 64 return 0; 65 } else { 66 return -errno; 67 } 68 } 69 70 bool 71 spdk_net_is_loopback(int fd) 72 { 73 struct ifaddrs *addrs, *tmp; 74 struct sockaddr_storage sa = {}; 75 socklen_t salen; 76 struct ifreq ifr = {}; 77 char ip_addr[256], ip_addr_tmp[256]; 78 int rc; 79 bool is_loopback = false; 80 81 salen = sizeof(sa); 82 rc = getsockname(fd, (struct sockaddr *)&sa, &salen); 83 if (rc != 0) { 84 return is_loopback; 85 } 86 87 memset(ip_addr, 0, sizeof(ip_addr)); 88 rc = spdk_net_get_address_string((struct sockaddr *)&sa, ip_addr, sizeof(ip_addr)); 89 if (rc != 0) { 90 return is_loopback; 91 } 92 93 getifaddrs(&addrs); 94 for (tmp = addrs; tmp != NULL; tmp = tmp->ifa_next) { 95 if (tmp->ifa_addr && (tmp->ifa_flags & IFF_UP) && 96 (tmp->ifa_addr->sa_family == sa.ss_family)) { 97 memset(ip_addr_tmp, 0, sizeof(ip_addr_tmp)); 98 rc = spdk_net_get_address_string(tmp->ifa_addr, ip_addr_tmp, sizeof(ip_addr_tmp)); 99 if (rc != 0) { 100 continue; 101 } 102 103 if (strncmp(ip_addr, ip_addr_tmp, sizeof(ip_addr)) == 0) { 104 memcpy(ifr.ifr_name, tmp->ifa_name, sizeof(ifr.ifr_name)); 105 ioctl(fd, SIOCGIFFLAGS, &ifr); 106 if (ifr.ifr_flags & IFF_LOOPBACK) { 107 is_loopback = true; 108 } 109 goto end; 110 } 111 } 112 } 113 114 end: 115 freeifaddrs(addrs); 116 return is_loopback; 117 } 118