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