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