back to topotato report
topotato coverage report
Current view: top level - lib - sockunion.c (source / functions) Hit Total Coverage
Test: test_bgp_disable_addpath_rx.py::BGPDisableAddpathRx Lines: 139 374 37.2 %
Date: 2023-02-24 18:37:08 Functions: 24 39 61.5 %

          Line data    Source code
       1             : /* Socket union related function.
       2             :  * Copyright (c) 1997, 98 Kunihiro Ishiguro
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "prefix.h"
      24             : #include "vty.h"
      25             : #include "sockunion.h"
      26             : #include "memory.h"
      27             : #include "log.h"
      28             : #include "jhash.h"
      29             : #include "lib_errors.h"
      30             : #include "printfrr.h"
      31             : 
      32          24 : DEFINE_MTYPE_STATIC(LIB, SOCKUNION, "Socket union");
      33             : 
      34           0 : const char *inet_sutop(const union sockunion *su, char *str)
      35             : {
      36           0 :         switch (su->sa.sa_family) {
      37           0 :         case AF_INET:
      38           0 :                 inet_ntop(AF_INET, &su->sin.sin_addr, str, INET_ADDRSTRLEN);
      39           0 :                 break;
      40           0 :         case AF_INET6:
      41           0 :                 inet_ntop(AF_INET6, &su->sin6.sin6_addr, str, INET6_ADDRSTRLEN);
      42           0 :                 break;
      43             :         }
      44           0 :         return str;
      45             : }
      46             : 
      47          40 : int str2sockunion(const char *str, union sockunion *su)
      48             : {
      49          40 :         int ret;
      50             : 
      51          40 :         if (str == NULL)
      52             :                 return -1;
      53             : 
      54          40 :         memset(su, 0, sizeof(union sockunion));
      55             : 
      56          40 :         ret = inet_pton(AF_INET, str, &su->sin.sin_addr);
      57          40 :         if (ret > 0) /* Valid IPv4 address format. */
      58             :         {
      59          40 :                 su->sin.sin_family = AF_INET;
      60             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
      61             :                 su->sin.sin_len = sizeof(struct sockaddr_in);
      62             : #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
      63          40 :                 return 0;
      64             :         }
      65           0 :         ret = inet_pton(AF_INET6, str, &su->sin6.sin6_addr);
      66           0 :         if (ret > 0) /* Valid IPv6 address format. */
      67             :         {
      68           0 :                 su->sin6.sin6_family = AF_INET6;
      69             : #ifdef SIN6_LEN
      70             :                 su->sin6.sin6_len = sizeof(struct sockaddr_in6);
      71             : #endif /* SIN6_LEN */
      72           0 :                 return 0;
      73             :         }
      74             :         return -1;
      75             : }
      76             : 
      77          10 : const char *sockunion2str(const union sockunion *su, char *buf, size_t len)
      78             : {
      79          10 :         switch (sockunion_family(su)) {
      80           0 :         case AF_UNSPEC:
      81           0 :                 snprintf(buf, len, "(unspec)");
      82           0 :                 return buf;
      83          10 :         case AF_INET:
      84          10 :                 return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len);
      85           0 :         case AF_INET6:
      86           0 :                 return inet_ntop(AF_INET6, &su->sin6.sin6_addr, buf, len);
      87             :         }
      88           0 :         snprintf(buf, len, "(af %d)", sockunion_family(su));
      89           0 :         return buf;
      90             : }
      91             : 
      92           0 : union sockunion *sockunion_str2su(const char *str)
      93             : {
      94           0 :         union sockunion *su = XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion));
      95             : 
      96           0 :         if (!str2sockunion(str, su))
      97             :                 return su;
      98             : 
      99           0 :         XFREE(MTYPE_SOCKUNION, su);
     100           0 :         return NULL;
     101             : }
     102             : 
     103             : /* Convert IPv4 compatible IPv6 address to IPv4 address. */
     104           4 : static void sockunion_normalise_mapped(union sockunion *su)
     105             : {
     106           4 :         struct sockaddr_in sin;
     107             : 
     108           4 :         if (su->sa.sa_family == AF_INET6
     109           0 :             && IN6_IS_ADDR_V4MAPPED(&su->sin6.sin6_addr)) {
     110           0 :                 memset(&sin, 0, sizeof(sin));
     111           0 :                 sin.sin_family = AF_INET;
     112           0 :                 sin.sin_port = su->sin6.sin6_port;
     113           0 :                 memcpy(&sin.sin_addr, ((char *)&su->sin6.sin6_addr) + 12, 4);
     114           0 :                 memcpy(su, &sin, sizeof(struct sockaddr_in));
     115             :         }
     116           4 : }
     117             : 
     118             : /* return sockunion structure : this function should be revised. */
     119           0 : static const char *sockunion_log(const union sockunion *su, char *buf,
     120             :                                  size_t len)
     121             : {
     122           0 :         switch (su->sa.sa_family) {
     123           0 :         case AF_INET:
     124           0 :                 return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len);
     125             : 
     126           0 :         case AF_INET6:
     127           0 :                 return inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, len);
     128             : 
     129           0 :         default:
     130           0 :                 snprintf(buf, len, "af_unknown %d ", su->sa.sa_family);
     131           0 :                 return buf;
     132             :         }
     133             : }
     134             : 
     135             : /* Return socket of sockunion. */
     136           4 : int sockunion_socket(const union sockunion *su)
     137             : {
     138           4 :         int sock;
     139             : 
     140           4 :         sock = socket(su->sa.sa_family, SOCK_STREAM, 0);
     141           4 :         if (sock < 0) {
     142           0 :                 char buf[SU_ADDRSTRLEN];
     143           0 :                 flog_err(EC_LIB_SOCKET, "Can't make socket for %s : %s",
     144             :                          sockunion_log(su, buf, SU_ADDRSTRLEN),
     145             :                          safe_strerror(errno));
     146           0 :                 return -1;
     147             :         }
     148             : 
     149             :         return sock;
     150             : }
     151             : 
     152             : /* Return accepted new socket file descriptor. */
     153           4 : int sockunion_accept(int sock, union sockunion *su)
     154             : {
     155           4 :         socklen_t len;
     156           4 :         int client_sock;
     157             : 
     158           4 :         len = sizeof(union sockunion);
     159           4 :         client_sock = accept(sock, (struct sockaddr *)su, &len);
     160             : 
     161           4 :         sockunion_normalise_mapped(su);
     162           4 :         return client_sock;
     163             : }
     164             : 
     165             : /* Return sizeof union sockunion.  */
     166           4 : int sockunion_sizeof(const union sockunion *su)
     167             : {
     168           4 :         int ret;
     169             : 
     170           4 :         ret = 0;
     171           4 :         switch (su->sa.sa_family) {
     172           4 :         case AF_INET:
     173           4 :                 ret = sizeof(struct sockaddr_in);
     174           4 :                 break;
     175           0 :         case AF_INET6:
     176           0 :                 ret = sizeof(struct sockaddr_in6);
     177           0 :                 break;
     178             :         }
     179           4 :         return ret;
     180             : }
     181             : 
     182             : /* Performs a non-blocking connect().  */
     183           4 : enum connect_result sockunion_connect(int fd, const union sockunion *peersu,
     184             :                                       unsigned short port, ifindex_t ifindex)
     185             : {
     186           4 :         int ret;
     187           4 :         union sockunion su;
     188             : 
     189           4 :         memcpy(&su, peersu, sizeof(union sockunion));
     190             : 
     191           4 :         switch (su.sa.sa_family) {
     192           4 :         case AF_INET:
     193           4 :                 su.sin.sin_port = port;
     194           4 :                 break;
     195           0 :         case AF_INET6:
     196           0 :                 su.sin6.sin6_port = port;
     197             : #ifdef KAME
     198             :                 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr) && ifindex) {
     199             :                         su.sin6.sin6_scope_id = ifindex;
     200             :                         SET_IN6_LINKLOCAL_IFINDEX(su.sin6.sin6_addr, ifindex);
     201             :                 }
     202             : #endif /* KAME */
     203           0 :                 break;
     204             :         }
     205             : 
     206             :         /* Call connect function. */
     207           4 :         ret = connect(fd, (struct sockaddr *)&su, sockunion_sizeof(&su));
     208             : 
     209             :         /* Immediate success */
     210           4 :         if (ret == 0)
     211             :                 return connect_success;
     212             : 
     213             :         /* If connect is in progress then return 1 else it's real error. */
     214           4 :         if (ret < 0) {
     215           4 :                 if (errno != EINPROGRESS) {
     216           0 :                         char str[SU_ADDRSTRLEN];
     217           0 :                         zlog_info("can't connect to %s fd %d : %s",
     218             :                                   sockunion_log(&su, str, sizeof(str)), fd,
     219             :                                   safe_strerror(errno));
     220           0 :                         return connect_error;
     221             :                 }
     222             :         }
     223             : 
     224             :         return connect_in_progress;
     225             : }
     226             : 
     227             : /* Make socket from sockunion union. */
     228           0 : int sockunion_stream_socket(union sockunion *su)
     229             : {
     230           0 :         int sock;
     231             : 
     232           0 :         if (su->sa.sa_family == 0)
     233           0 :                 su->sa.sa_family = AF_INET_UNION;
     234             : 
     235           0 :         sock = socket(su->sa.sa_family, SOCK_STREAM, 0);
     236             : 
     237           0 :         if (sock < 0)
     238           0 :                 flog_err(EC_LIB_SOCKET,
     239             :                          "can't make socket sockunion_stream_socket");
     240             : 
     241           0 :         return sock;
     242             : }
     243             : 
     244             : /* Bind socket to specified address. */
     245           0 : int sockunion_bind(int sock, union sockunion *su, unsigned short port,
     246             :                    union sockunion *su_addr)
     247             : {
     248           0 :         int size = 0;
     249           0 :         int ret;
     250             : 
     251           0 :         if (su->sa.sa_family == AF_INET) {
     252           0 :                 size = sizeof(struct sockaddr_in);
     253           0 :                 su->sin.sin_port = htons(port);
     254             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     255             :                 su->sin.sin_len = size;
     256             : #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
     257           0 :                 if (su_addr == NULL)
     258           0 :                         sockunion2ip(su) = htonl(INADDR_ANY);
     259           0 :         } else if (su->sa.sa_family == AF_INET6) {
     260           0 :                 size = sizeof(struct sockaddr_in6);
     261           0 :                 su->sin6.sin6_port = htons(port);
     262             : #ifdef SIN6_LEN
     263             :                 su->sin6.sin6_len = size;
     264             : #endif /* SIN6_LEN */
     265           0 :                 if (su_addr == NULL) {
     266             : #ifdef LINUX_IPV6
     267           0 :                         memset(&su->sin6.sin6_addr, 0, sizeof(struct in6_addr));
     268             : #else
     269             :                         su->sin6.sin6_addr = in6addr_any;
     270             : #endif /* LINUX_IPV6 */
     271             :                 }
     272             :         }
     273             : 
     274           0 :         ret = bind(sock, (struct sockaddr *)su, size);
     275           0 :         if (ret < 0) {
     276           0 :                 char buf[SU_ADDRSTRLEN];
     277           0 :                 flog_err(EC_LIB_SOCKET, "can't bind socket for %s : %s",
     278             :                          sockunion_log(su, buf, SU_ADDRSTRLEN),
     279             :                          safe_strerror(errno));
     280             :         }
     281             : 
     282           0 :         return ret;
     283             : }
     284             : 
     285          28 : int sockopt_reuseaddr(int sock)
     286             : {
     287          28 :         int ret;
     288          28 :         int on = 1;
     289             : 
     290          28 :         ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
     291             :                          sizeof(on));
     292          28 :         if (ret < 0) {
     293           0 :                 flog_err(
     294             :                         EC_LIB_SOCKET,
     295             :                         "can't set sockopt SO_REUSEADDR to socket %d errno=%d: %s",
     296             :                         sock, errno, safe_strerror(errno));
     297           0 :                 return -1;
     298             :         }
     299             :         return 0;
     300             : }
     301             : 
     302             : #ifdef SO_REUSEPORT
     303          28 : int sockopt_reuseport(int sock)
     304             : {
     305          28 :         int ret;
     306          28 :         int on = 1;
     307             : 
     308          28 :         ret = setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void *)&on,
     309             :                          sizeof(on));
     310          28 :         if (ret < 0) {
     311           0 :                 flog_err(EC_LIB_SOCKET,
     312             :                          "can't set sockopt SO_REUSEPORT to socket %d", sock);
     313           0 :                 return -1;
     314             :         }
     315             :         return 0;
     316             : }
     317             : #else
     318             : int sockopt_reuseport(int sock)
     319             : {
     320             :         return 0;
     321             : }
     322             : #endif /* 0 */
     323             : 
     324          16 : int sockopt_ttl(int family, int sock, int ttl)
     325             : {
     326          16 :         int ret;
     327             : 
     328             : #ifdef IP_TTL
     329          16 :         if (family == AF_INET) {
     330          12 :                 ret = setsockopt(sock, IPPROTO_IP, IP_TTL, (void *)&ttl,
     331             :                                  sizeof(int));
     332          12 :                 if (ret < 0) {
     333           0 :                         flog_err(EC_LIB_SOCKET,
     334             :                                  "can't set sockopt IP_TTL %d to socket %d",
     335             :                                  ttl, sock);
     336           0 :                         return -1;
     337             :                 }
     338             :                 return 0;
     339             :         }
     340             : #endif /* IP_TTL */
     341           4 :         if (family == AF_INET6) {
     342           4 :                 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
     343             :                                  (void *)&ttl, sizeof(int));
     344           4 :                 if (ret < 0) {
     345           0 :                         flog_err(
     346             :                                 EC_LIB_SOCKET,
     347             :                                 "can't set sockopt IPV6_UNICAST_HOPS %d to socket %d",
     348             :                                 ttl, sock);
     349           0 :                         return -1;
     350             :                 }
     351             :                 return 0;
     352             :         }
     353             :         return 0;
     354             : }
     355             : 
     356           0 : int sockopt_minttl(int family, int sock, int minttl)
     357             : {
     358             : #ifdef IP_MINTTL
     359           0 :         if (family == AF_INET) {
     360           0 :                 int ret = setsockopt(sock, IPPROTO_IP, IP_MINTTL, &minttl,
     361             :                                      sizeof(minttl));
     362           0 :                 if (ret < 0)
     363           0 :                         flog_err(
     364             :                                 EC_LIB_SOCKET,
     365             :                                 "can't set sockopt IP_MINTTL to %d on socket %d: %s",
     366             :                                 minttl, sock, safe_strerror(errno));
     367           0 :                 return ret;
     368             :         }
     369             : #endif /* IP_MINTTL */
     370             : #ifdef IPV6_MINHOPCOUNT
     371           0 :         if (family == AF_INET6) {
     372           0 :                 int ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MINHOPCOUNT,
     373             :                                      &minttl, sizeof(minttl));
     374           0 :                 if (ret < 0)
     375           0 :                         flog_err(
     376             :                                 EC_LIB_SOCKET,
     377             :                                 "can't set sockopt IPV6_MINHOPCOUNT to %d on socket %d: %s",
     378             :                                 minttl, sock, safe_strerror(errno));
     379           0 :                 return ret;
     380             :         }
     381             : #endif
     382             : 
     383           0 :         errno = EOPNOTSUPP;
     384           0 :         return -1;
     385             : }
     386             : 
     387          24 : int sockopt_v6only(int family, int sock)
     388             : {
     389          24 :         int ret, on = 1;
     390             : 
     391             : #ifdef IPV6_V6ONLY
     392          24 :         if (family == AF_INET6) {
     393          12 :                 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&on,
     394             :                                  sizeof(int));
     395          12 :                 if (ret < 0) {
     396           0 :                         flog_err(EC_LIB_SOCKET,
     397             :                                  "can't set sockopt IPV6_V6ONLY to socket %d",
     398             :                                  sock);
     399           0 :                         return -1;
     400             :                 }
     401             :                 return 0;
     402             :         }
     403             : #endif /* IPV6_V6ONLY */
     404             :         return 0;
     405             : }
     406             : 
     407             : /* If same family and same prefix return 1. */
     408          52 : int sockunion_same(const union sockunion *su1, const union sockunion *su2)
     409             : {
     410          52 :         int ret = 0;
     411             : 
     412          52 :         if (su1->sa.sa_family != su2->sa.sa_family)
     413             :                 return 0;
     414             : 
     415          52 :         switch (su1->sa.sa_family) {
     416          52 :         case AF_INET:
     417          52 :                 ret = memcmp(&su1->sin.sin_addr, &su2->sin.sin_addr,
     418             :                              sizeof(struct in_addr));
     419          52 :                 break;
     420           0 :         case AF_INET6:
     421           0 :                 ret = memcmp(&su1->sin6.sin6_addr, &su2->sin6.sin6_addr,
     422             :                              sizeof(struct in6_addr));
     423           0 :                 if ((ret == 0) && IN6_IS_ADDR_LINKLOCAL(&su1->sin6.sin6_addr)) {
     424             :                         /* compare interface indices */
     425           0 :                         if (su1->sin6.sin6_scope_id && su2->sin6.sin6_scope_id)
     426           0 :                                 ret = (su1->sin6.sin6_scope_id
     427             :                                        == su2->sin6.sin6_scope_id)
     428             :                                               ? 0
     429           0 :                                               : 1;
     430             :                 }
     431             :                 break;
     432             :         }
     433          52 :         if (ret == 0)
     434             :                 return 1;
     435             :         else
     436           0 :                 return 0;
     437             : }
     438             : 
     439          68 : unsigned int sockunion_hash(const union sockunion *su)
     440             : {
     441          68 :         switch (sockunion_family(su)) {
     442          68 :         case AF_INET:
     443          68 :                 return jhash_1word(su->sin.sin_addr.s_addr, 0);
     444           0 :         case AF_INET6:
     445           0 :                 return jhash2(su->sin6.sin6_addr.s6_addr32,
     446             :                               array_size(su->sin6.sin6_addr.s6_addr32), 0);
     447             :         }
     448             :         return 0;
     449             : }
     450             : 
     451           0 : size_t family2addrsize(int family)
     452             : {
     453           0 :         switch (family) {
     454             :         case AF_INET:
     455             :                 return sizeof(struct in_addr);
     456           0 :         case AF_INET6:
     457           0 :                 return sizeof(struct in6_addr);
     458             :         }
     459           0 :         return 0;
     460             : }
     461             : 
     462           0 : size_t sockunion_get_addrlen(const union sockunion *su)
     463             : {
     464           0 :         return family2addrsize(sockunion_family(su));
     465             : }
     466             : 
     467           0 : const uint8_t *sockunion_get_addr(const union sockunion *su)
     468             : {
     469           0 :         switch (sockunion_family(su)) {
     470           0 :         case AF_INET:
     471           0 :                 return (const uint8_t *)&su->sin.sin_addr.s_addr;
     472           0 :         case AF_INET6:
     473           0 :                 return (const uint8_t *)&su->sin6.sin6_addr;
     474             :         }
     475             :         return NULL;
     476             : }
     477             : 
     478           0 : void sockunion_set(union sockunion *su, int family, const uint8_t *addr,
     479             :                    size_t bytes)
     480             : {
     481           0 :         if (family2addrsize(family) != bytes)
     482             :                 return;
     483             : 
     484           0 :         sockunion_family(su) = family;
     485           0 :         switch (family) {
     486           0 :         case AF_INET:
     487           0 :                 memcpy(&su->sin.sin_addr.s_addr, addr, bytes);
     488           0 :                 break;
     489           0 :         case AF_INET6:
     490           0 :                 memcpy(&su->sin6.sin6_addr, addr, bytes);
     491           0 :                 break;
     492             :         }
     493             : }
     494             : 
     495             : /* After TCP connection is established.  Get local address and port. */
     496          17 : union sockunion *sockunion_getsockname(int fd)
     497             : {
     498          17 :         int ret;
     499          17 :         socklen_t len;
     500          17 :         union {
     501             :                 struct sockaddr sa;
     502             :                 struct sockaddr_in sin;
     503             :                 struct sockaddr_in6 sin6;
     504             :                 char tmp_buffer[128];
     505             :         } name;
     506          17 :         union sockunion *su;
     507             : 
     508          17 :         memset(&name, 0, sizeof(name));
     509          17 :         len = sizeof(name);
     510             : 
     511          17 :         ret = getsockname(fd, (struct sockaddr *)&name, &len);
     512          17 :         if (ret < 0) {
     513           0 :                 flog_err(EC_LIB_SOCKET,
     514             :                          "Can't get local address and port by getsockname: %s",
     515             :                          safe_strerror(errno));
     516           0 :                 return NULL;
     517             :         }
     518             : 
     519          17 :         if (name.sa.sa_family == AF_INET) {
     520          17 :                 su = XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion));
     521          17 :                 memcpy(su, &name, sizeof(struct sockaddr_in));
     522          17 :                 return su;
     523             :         }
     524           0 :         if (name.sa.sa_family == AF_INET6) {
     525           0 :                 su = XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion));
     526           0 :                 memcpy(su, &name, sizeof(struct sockaddr_in6));
     527           0 :                 sockunion_normalise_mapped(su);
     528           0 :                 return su;
     529             :         }
     530             : 
     531           0 :         flog_err(
     532             :                 EC_LIB_SOCKET,
     533             :                 "Unexpected AFI received(%d) for sockunion_getsockname call for fd: %d",
     534             :                 name.sa.sa_family, fd);
     535           0 :         return NULL;
     536             : }
     537             : 
     538             : /* After TCP connection is established.  Get remote address and port. */
     539          17 : union sockunion *sockunion_getpeername(int fd)
     540             : {
     541          17 :         int ret;
     542          17 :         socklen_t len;
     543          17 :         union {
     544             :                 struct sockaddr sa;
     545             :                 struct sockaddr_in sin;
     546             :                 struct sockaddr_in6 sin6;
     547             :                 char tmp_buffer[128];
     548             :         } name;
     549          17 :         union sockunion *su;
     550             : 
     551          17 :         memset(&name, 0, sizeof(name));
     552          17 :         len = sizeof(name);
     553          17 :         ret = getpeername(fd, (struct sockaddr *)&name, &len);
     554          17 :         if (ret < 0) {
     555           0 :                 flog_err(EC_LIB_SOCKET, "Can't get remote address and port: %s",
     556             :                          safe_strerror(errno));
     557           0 :                 return NULL;
     558             :         }
     559             : 
     560          17 :         if (name.sa.sa_family == AF_INET) {
     561          17 :                 su = XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion));
     562          17 :                 memcpy(su, &name, sizeof(struct sockaddr_in));
     563          17 :                 return su;
     564             :         }
     565           0 :         if (name.sa.sa_family == AF_INET6) {
     566           0 :                 su = XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion));
     567           0 :                 memcpy(su, &name, sizeof(struct sockaddr_in6));
     568           0 :                 sockunion_normalise_mapped(su);
     569           0 :                 return su;
     570             :         }
     571             : 
     572           0 :         flog_err(
     573             :                 EC_LIB_SOCKET,
     574             :                 "Unexpected AFI received(%d) for sockunion_getpeername call for fd: %d",
     575             :                 name.sa.sa_family, fd);
     576           0 :         return NULL;
     577             : }
     578             : 
     579             : /* Print sockunion structure */
     580             : static void __attribute__((unused)) sockunion_print(const union sockunion *su)
     581             : {
     582             :         if (su == NULL)
     583             :                 return;
     584             : 
     585             :         switch (su->sa.sa_family) {
     586             :         case AF_INET:
     587             :                 printf("%pI4\n", &su->sin.sin_addr);
     588             :                 break;
     589             :         case AF_INET6:
     590             :                 printf("%pI6\n", &su->sin6.sin6_addr);
     591             :                 break;
     592             : #ifdef AF_LINK
     593             :         case AF_LINK: {
     594             :                 struct sockaddr_dl *sdl;
     595             : 
     596             :                 sdl = (struct sockaddr_dl *)&(su->sa);
     597             :                 printf("link#%d\n", sdl->sdl_index);
     598             :         } break;
     599             : #endif /* AF_LINK */
     600             :         default:
     601             :                 printf("af_unknown %d\n", su->sa.sa_family);
     602             :                 break;
     603             :         }
     604             : }
     605             : 
     606           0 : int in6addr_cmp(const struct in6_addr *addr1, const struct in6_addr *addr2)
     607             : {
     608           0 :         unsigned int i;
     609           0 :         const uint8_t *p1, *p2;
     610             : 
     611           0 :         p1 = (const uint8_t *)addr1;
     612           0 :         p2 = (const uint8_t *)addr2;
     613             : 
     614           0 :         for (i = 0; i < sizeof(struct in6_addr); i++) {
     615           0 :                 if (p1[i] > p2[i])
     616             :                         return 1;
     617           0 :                 else if (p1[i] < p2[i])
     618             :                         return -1;
     619             :         }
     620             :         return 0;
     621             : }
     622             : 
     623          10 : int sockunion_cmp(const union sockunion *su1, const union sockunion *su2)
     624             : {
     625          10 :         if (su1->sa.sa_family > su2->sa.sa_family)
     626             :                 return 1;
     627          10 :         if (su1->sa.sa_family < su2->sa.sa_family)
     628             :                 return -1;
     629             : 
     630          10 :         if (su1->sa.sa_family == AF_INET) {
     631          10 :                 if (ntohl(sockunion2ip(su1)) == ntohl(sockunion2ip(su2)))
     632             :                         return 0;
     633           6 :                 if (ntohl(sockunion2ip(su1)) > ntohl(sockunion2ip(su2)))
     634             :                         return 1;
     635             :                 else
     636           2 :                         return -1;
     637             :         }
     638           0 :         if (su1->sa.sa_family == AF_INET6)
     639           0 :                 return in6addr_cmp(&su1->sin6.sin6_addr, &su2->sin6.sin6_addr);
     640             :         return 0;
     641             : }
     642             : 
     643             : /* Duplicate sockunion. */
     644           0 : union sockunion *sockunion_dup(const union sockunion *su)
     645             : {
     646           0 :         union sockunion *dup =
     647           0 :                 XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion));
     648           0 :         memcpy(dup, su, sizeof(union sockunion));
     649           0 :         return dup;
     650             : }
     651             : 
     652          34 : void sockunion_free(union sockunion *su)
     653             : {
     654          34 :         XFREE(MTYPE_SOCKUNION, su);
     655          34 : }
     656             : 
     657           8 : void sockunion_init(union sockunion *su)
     658             : {
     659           8 :         memset(su, 0, sizeof(union sockunion));
     660           8 : }
     661             : 
     662           8 : printfrr_ext_autoreg_p("SU", printfrr_psu);
     663           2 : static ssize_t printfrr_psu(struct fbuf *buf, struct printfrr_eargs *ea,
     664             :                             const void *ptr)
     665             : {
     666           2 :         const union sockunion *su = ptr;
     667           2 :         bool include_port = false, include_scope = false;
     668           2 :         bool endflags = false;
     669           2 :         ssize_t ret = 0;
     670           2 :         char cbuf[INET6_ADDRSTRLEN];
     671             : 
     672           2 :         if (!su)
     673           0 :                 return bputs(buf, "(null)");
     674             : 
     675           4 :         while (!endflags) {
     676           2 :                 switch (*ea->fmt) {
     677           0 :                 case 'p':
     678           0 :                         ea->fmt++;
     679           0 :                         include_port = true;
     680           0 :                         break;
     681           0 :                 case 's':
     682           0 :                         ea->fmt++;
     683           0 :                         include_scope = true;
     684           0 :                         break;
     685             :                 default:
     686             :                         endflags = true;
     687             :                         break;
     688             :                 }
     689             :         }
     690             : 
     691           2 :         switch (sockunion_family(su)) {
     692           0 :         case AF_UNSPEC:
     693           0 :                 ret += bputs(buf, "(unspec)");
     694           0 :                 break;
     695           2 :         case AF_INET:
     696           2 :                 inet_ntop(AF_INET, &su->sin.sin_addr, cbuf, sizeof(cbuf));
     697           2 :                 ret += bputs(buf, cbuf);
     698           2 :                 if (include_port)
     699           0 :                         ret += bprintfrr(buf, ":%d", ntohs(su->sin.sin_port));
     700             :                 break;
     701           0 :         case AF_INET6:
     702           0 :                 if (include_port)
     703           0 :                         ret += bputch(buf, '[');
     704           0 :                 inet_ntop(AF_INET6, &su->sin6.sin6_addr, cbuf, sizeof(cbuf));
     705           0 :                 ret += bputs(buf, cbuf);
     706           0 :                 if (include_scope && su->sin6.sin6_scope_id)
     707           0 :                         ret += bprintfrr(buf, "%%%u",
     708             :                                          (unsigned int)su->sin6.sin6_scope_id);
     709           0 :                 if (include_port)
     710           0 :                         ret += bprintfrr(buf, "]:%d",
     711           0 :                                          ntohs(su->sin6.sin6_port));
     712             :                 break;
     713           0 :         case AF_UNIX: {
     714           0 :                 int len;
     715             : #ifdef __linux__
     716           0 :                 if (su->sun.sun_path[0] == '\0' && su->sun.sun_path[1]) {
     717           0 :                         len = strnlen(su->sun.sun_path + 1,
     718             :                                       sizeof(su->sun.sun_path) - 1);
     719           0 :                         ret += bprintfrr(buf, "@%*pSE", len,
     720             :                                          su->sun.sun_path + 1);
     721           0 :                         break;
     722             :                 }
     723             : #endif
     724           0 :                 len = strnlen(su->sun.sun_path, sizeof(su->sun.sun_path));
     725           0 :                 ret += bprintfrr(buf, "%*pSE", len, su->sun.sun_path);
     726           0 :                 break;
     727             :         }
     728           0 :         default:
     729           0 :                 ret += bprintfrr(buf, "(af %d)", sockunion_family(su));
     730             :         }
     731             : 
     732             :         return ret;
     733             : }
     734             : 
     735           0 : int sockunion_is_null(const union sockunion *su)
     736             : {
     737           0 :         unsigned char null_s6_addr[16] = {0};
     738             : 
     739           0 :         switch (sockunion_family(su)) {
     740             :         case AF_UNSPEC:
     741             :                 return 1;
     742           0 :         case AF_INET:
     743           0 :                 return (su->sin.sin_addr.s_addr == 0);
     744           0 :         case AF_INET6:
     745           0 :                 return !memcmp(su->sin6.sin6_addr.s6_addr, null_s6_addr,
     746             :                                sizeof(null_s6_addr));
     747           0 :         default:
     748           0 :                 return 0;
     749             :         }
     750             : }
     751             : 
     752           8 : printfrr_ext_autoreg_i("PF", printfrr_pf);
     753           0 : static ssize_t printfrr_pf(struct fbuf *buf, struct printfrr_eargs *ea,
     754             :                            uintmax_t val)
     755             : {
     756           0 :         switch (val) {
     757           0 :         case AF_INET:
     758           0 :                 return bputs(buf, "AF_INET");
     759           0 :         case AF_INET6:
     760           0 :                 return bputs(buf, "AF_INET6");
     761           0 :         case AF_UNIX:
     762           0 :                 return bputs(buf, "AF_UNIX");
     763             : #ifdef AF_PACKET
     764           0 :         case AF_PACKET:
     765           0 :                 return bputs(buf, "AF_PACKET");
     766             : #endif
     767             : #ifdef AF_NETLINK
     768           0 :         case AF_NETLINK:
     769           0 :                 return bputs(buf, "AF_NETLINK");
     770             : #endif
     771             :         }
     772           0 :         return bprintfrr(buf, "AF_(%ju)", val);
     773             : }
     774             : 
     775           8 : printfrr_ext_autoreg_i("SO", printfrr_so);
     776           0 : static ssize_t printfrr_so(struct fbuf *buf, struct printfrr_eargs *ea,
     777             :                            uintmax_t val)
     778             : {
     779           0 :         switch (val) {
     780           0 :         case SOCK_STREAM:
     781           0 :                 return bputs(buf, "SOCK_STREAM");
     782           0 :         case SOCK_DGRAM:
     783           0 :                 return bputs(buf, "SOCK_DGRAM");
     784           0 :         case SOCK_SEQPACKET:
     785           0 :                 return bputs(buf, "SOCK_SEQPACKET");
     786             : #ifdef SOCK_RAW
     787           0 :         case SOCK_RAW:
     788           0 :                 return bputs(buf, "SOCK_RAW");
     789             : #endif
     790             : #ifdef SOCK_PACKET
     791           0 :         case SOCK_PACKET:
     792           0 :                 return bputs(buf, "SOCK_PACKET");
     793             : #endif
     794             :         }
     795           0 :         return bprintfrr(buf, "SOCK_(%ju)", val);
     796             : }

Generated by: LCOV version v1.16-topotato