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

Generated by: LCOV version 1.15