Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2024 Samsung Electronics Co., Ltd.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : : #include "spdk/net.h"
8 : : #include "spdk/log.h"
9 : :
10 : : int
11 : 2306 : spdk_net_get_interface_name(const char *ip, char *ifc, size_t len)
12 : : {
13 : 67 : struct ifaddrs *addrs, *iap;
14 : : struct sockaddr_in *sa;
15 : 67 : char buf[32];
16 : 2306 : int rc = -ENODEV;
17 : :
18 : 2306 : getifaddrs(&addrs);
19 [ + - ]: 24221 : for (iap = addrs; iap != NULL; iap = iap->ifa_next) {
20 [ + - + + : 24221 : if (!(iap->ifa_addr && (iap->ifa_flags & IFF_UP) && iap->ifa_addr->sa_family == AF_INET)) {
+ + ]
21 : 15603 : continue;
22 : : }
23 : 8618 : sa = (struct sockaddr_in *)(iap->ifa_addr);
24 : 8618 : inet_ntop(iap->ifa_addr->sa_family, &sa->sin_addr, buf, sizeof(buf));
25 [ - + + + ]: 8618 : if (strcmp(ip, buf) != 0) {
26 : 6312 : continue;
27 : : }
28 [ - + - + ]: 2306 : if (strnlen(iap->ifa_name, len) == len) {
29 : 0 : return -ENOMEM;
30 : : }
31 : 2306 : snprintf(ifc, len, "%s", iap->ifa_name);
32 : 2306 : rc = 0;
33 : 2306 : break;
34 : : }
35 : 2306 : freeifaddrs(addrs);
36 : 2306 : return rc;
37 : : }
38 : :
39 : : int
40 : 46069 : spdk_net_get_address_string(struct sockaddr *sa, char *addr, size_t len)
41 : : {
42 : 46069 : const char *result = NULL;
43 : :
44 [ + - - + ]: 46069 : if (sa == NULL || addr == NULL) {
45 : 0 : return -1;
46 : : }
47 : :
48 [ + - - ]: 46069 : switch (sa->sa_family) {
49 : 46069 : case AF_INET:
50 : 46069 : result = inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
51 : : addr, len);
52 : 46069 : break;
53 : 0 : case AF_INET6:
54 : 0 : result = inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
55 : : addr, len);
56 : 0 : break;
57 : 0 : default:
58 : 0 : break;
59 : : }
60 : :
61 [ + - ]: 46069 : if (result != NULL) {
62 : 46069 : return 0;
63 : : } else {
64 : 0 : return -errno;
65 : : }
66 : : }
67 : :
68 : : bool
69 : 3227 : spdk_net_is_loopback(int fd)
70 : : {
71 : 132 : struct ifaddrs *addrs, *tmp;
72 : 3227 : struct sockaddr_storage sa = {};
73 : 132 : socklen_t salen;
74 : 3227 : struct ifreq ifr = {};
75 : 132 : char ip_addr[256], ip_addr_tmp[256];
76 : : int rc;
77 : 3227 : bool is_loopback = false;
78 : :
79 : 3227 : salen = sizeof(sa);
80 : 3227 : rc = getsockname(fd, (struct sockaddr *)&sa, &salen);
81 [ - + ]: 3227 : if (rc != 0) {
82 : 0 : return is_loopback;
83 : : }
84 : :
85 : 3227 : memset(ip_addr, 0, sizeof(ip_addr));
86 : 3227 : rc = spdk_net_get_address_string((struct sockaddr *)&sa, ip_addr, sizeof(ip_addr));
87 [ - + ]: 3227 : if (rc != 0) {
88 : 0 : return is_loopback;
89 : : }
90 : :
91 : 3227 : getifaddrs(&addrs);
92 [ + + ]: 31372 : for (tmp = addrs; tmp != NULL; tmp = tmp->ifa_next) {
93 [ + - + + ]: 31366 : if (tmp->ifa_addr && (tmp->ifa_flags & IFF_UP) &&
94 [ + + ]: 29950 : (tmp->ifa_addr->sa_family == sa.ss_family)) {
95 : 12886 : memset(ip_addr_tmp, 0, sizeof(ip_addr_tmp));
96 : 12886 : rc = spdk_net_get_address_string(tmp->ifa_addr, ip_addr_tmp, sizeof(ip_addr_tmp));
97 [ - + ]: 12886 : if (rc != 0) {
98 : 0 : continue;
99 : : }
100 : :
101 [ + + ]: 12886 : if (strncmp(ip_addr, ip_addr_tmp, sizeof(ip_addr)) == 0) {
102 : 3221 : memcpy(ifr.ifr_name, tmp->ifa_name, sizeof(ifr.ifr_name));
103 : 3221 : ioctl(fd, SIOCGIFFLAGS, &ifr);
104 [ + + ]: 3221 : if (ifr.ifr_flags & IFF_LOOPBACK) {
105 : 177 : is_loopback = true;
106 : : }
107 : 3221 : goto end;
108 : : }
109 : : }
110 : : }
111 : :
112 : 138 : end:
113 : 3227 : freeifaddrs(addrs);
114 : 3227 : return is_loopback;
115 : : }
116 : :
117 : : int
118 : 15042 : spdk_net_getaddr(int fd, char *saddr, int slen, uint16_t *sport,
119 : : char *caddr, int clen, uint16_t *cport)
120 : : {
121 : 239 : struct sockaddr_storage sa;
122 : 239 : int val;
123 : 239 : socklen_t len;
124 : : int rc;
125 : :
126 : 15042 : memset(&sa, 0, sizeof sa);
127 : 15042 : len = sizeof sa;
128 : 15042 : rc = getsockname(fd, (struct sockaddr *) &sa, &len);
129 [ - + ]: 15042 : if (rc != 0) {
130 : 0 : SPDK_ERRLOG("getsockname() failed (errno=%d)\n", errno);
131 : 0 : return -1;
132 : : }
133 : :
134 [ - + - ]: 15042 : switch (sa.ss_family) {
135 : 0 : case AF_UNIX:
136 : : /* Acceptable connection types that don't have IPs */
137 : 0 : return 0;
138 : 15042 : case AF_INET:
139 : : case AF_INET6:
140 : : /* Code below will get IP addresses */
141 : 15042 : break;
142 : 0 : default:
143 : : /* Unsupported socket family */
144 : 0 : return -1;
145 : : }
146 : :
147 [ + - ]: 15042 : if (saddr) {
148 : 15042 : rc = spdk_net_get_address_string((struct sockaddr *)&sa, saddr, slen);
149 [ - + ]: 15042 : if (rc != 0) {
150 : 0 : SPDK_ERRLOG("getnameinfo() failed (errno=%d)\n", rc);
151 : 0 : return -1;
152 : : }
153 : : }
154 : :
155 [ + + ]: 15042 : if (sport) {
156 [ + - ]: 13274 : if (sa.ss_family == AF_INET) {
157 : 13274 : *sport = ntohs(((struct sockaddr_in *) &sa)->sin_port);
158 [ # # ]: 0 : } else if (sa.ss_family == AF_INET6) {
159 : 0 : *sport = ntohs(((struct sockaddr_in6 *) &sa)->sin6_port);
160 : : }
161 : : }
162 : :
163 : 15042 : len = sizeof(val);
164 : 15042 : rc = getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &val, &len);
165 [ + - + + ]: 15042 : if (rc == 0 && val == 1) {
166 : : /* It is an error to getaddr for a peer address on a listen socket. */
167 [ + - - + ]: 8 : if (caddr != NULL || cport != NULL) {
168 : 0 : SPDK_ERRLOG("caddr, cport not valid on listen sockets\n");
169 : 0 : return -1;
170 : : }
171 : 8 : return 0;
172 : : }
173 : :
174 : 15034 : memset(&sa, 0, sizeof sa);
175 : 15034 : len = sizeof sa;
176 : 15034 : rc = getpeername(fd, (struct sockaddr *) &sa, &len);
177 [ - + ]: 15034 : if (rc != 0) {
178 : 0 : SPDK_ERRLOG("getpeername() failed (errno=%d)\n", errno);
179 : 0 : return -1;
180 : : }
181 : :
182 [ + + ]: 15034 : if (caddr) {
183 : 13825 : rc = spdk_net_get_address_string((struct sockaddr *)&sa, caddr, clen);
184 [ - + ]: 13825 : if (rc != 0) {
185 : 0 : SPDK_ERRLOG("getnameinfo() failed (errno=%d)\n", rc);
186 : 0 : return -1;
187 : : }
188 : : }
189 : :
190 [ + + ]: 15034 : if (cport) {
191 [ + - ]: 13274 : if (sa.ss_family == AF_INET) {
192 : 13274 : *cport = ntohs(((struct sockaddr_in *) &sa)->sin_port);
193 [ # # ]: 0 : } else if (sa.ss_family == AF_INET6) {
194 : 0 : *cport = ntohs(((struct sockaddr_in6 *) &sa)->sin6_port);
195 : : }
196 : : }
197 : :
198 : 15034 : return 0;
199 : : }
|