xref: /spdk/lib/util/net.c (revision 8b5c4be8b4096f1af6ece9df5cd8322550fc67fd)
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