LCOV - code coverage report
Current view: top level - lib/util - net.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 82 118 69.5 %
Date: 2024-07-12 14:01:26 Functions: 4 4 100.0 %

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

Generated by: LCOV version 1.15