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

Generated by: LCOV version 1.15