LCOV - code coverage report
Current view: top level - lib/util - net.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 83 120 69.2 %
Date: 2024-12-06 08:20:53 Functions: 4 4 100.0 %

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

Generated by: LCOV version 1.15