back to topotato report
topotato coverage report
Current view: top level - lib - ipaddr.h (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 6 53 11.3 %
Date: 2023-11-16 17:19:14 Functions: 1 10 10.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * IP address structure (for generic IPv4 or IPv6 address)
       4             :  * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
       5             :  */
       6             : 
       7             : #ifndef __IPADDR_H__
       8             : #define __IPADDR_H__
       9             : 
      10             : #include <zebra.h>
      11             : 
      12             : #include "lib/log.h"
      13             : 
      14             : #ifdef __cplusplus
      15             : extern "C" {
      16             : #endif
      17             : 
      18             : /*
      19             :  * Generic IP address - union of IPv4 and IPv6 address.
      20             :  */
      21             : enum ipaddr_type_t {
      22             :         IPADDR_NONE = AF_UNSPEC,
      23             :         IPADDR_V4 = AF_INET,
      24             :         IPADDR_V6 = AF_INET6,
      25             : };
      26             : 
      27             : struct ipaddr {
      28             :         enum ipaddr_type_t ipa_type;
      29             :         union {
      30             :                 uint8_t addr;
      31             :                 uint8_t addrbytes[16];
      32             :                 struct in_addr _v4_addr;
      33             :                 struct in6_addr _v6_addr;
      34             :         } ip;
      35             : #define ipaddr_v4 ip._v4_addr
      36             : #define ipaddr_v6 ip._v6_addr
      37             : };
      38             : 
      39             : #define IS_IPADDR_NONE(p) ((p)->ipa_type == IPADDR_NONE)
      40             : #define IS_IPADDR_V4(p)   ((p)->ipa_type == IPADDR_V4)
      41             : #define IS_IPADDR_V6(p)   ((p)->ipa_type == IPADDR_V6)
      42             : 
      43             : #define SET_IPADDR_V4(p)  (p)->ipa_type = IPADDR_V4
      44             : #define SET_IPADDR_V6(p)  (p)->ipa_type = IPADDR_V6
      45             : 
      46             : #define IPADDRSZ(p)                                                            \
      47             :         (IS_IPADDR_V4((p)) ? sizeof(struct in_addr) : sizeof(struct in6_addr))
      48             : 
      49             : #define IPADDR_STRING_SIZE 46
      50             : 
      51           0 : static inline int ipaddr_family(const struct ipaddr *ip)
      52             : {
      53           0 :         switch (ip->ipa_type) {
      54             :         case IPADDR_V4:
      55             :                 return AF_INET;
      56           0 :         case IPADDR_V6:
      57           0 :                 return AF_INET6;
      58           0 :         case IPADDR_NONE:
      59           0 :                 return AF_UNSPEC;
      60             :         }
      61             : 
      62           0 :         assert(!"Reached end of function where we should never hit");
      63             : }
      64             : 
      65           0 : static inline int str2ipaddr(const char *str, struct ipaddr *ip)
      66             : {
      67           0 :         int ret;
      68             : 
      69           0 :         memset(ip, 0, sizeof(struct ipaddr));
      70             : 
      71           0 :         ret = inet_pton(AF_INET, str, &ip->ipaddr_v4);
      72           0 :         if (ret > 0) /* Valid IPv4 address. */
      73             :         {
      74           0 :                 ip->ipa_type = IPADDR_V4;
      75           0 :                 return 0;
      76             :         }
      77           0 :         ret = inet_pton(AF_INET6, str, &ip->ipaddr_v6);
      78           0 :         if (ret > 0) /* Valid IPv6 address. */
      79             :         {
      80           0 :                 ip->ipa_type = IPADDR_V6;
      81           0 :                 return 0;
      82             :         }
      83             : 
      84             :         return -1;
      85             : }
      86             : 
      87           0 : static inline char *ipaddr2str(const struct ipaddr *ip, char *buf, int size)
      88             : {
      89           0 :         buf[0] = '\0';
      90           0 :         if (ip)
      91           0 :                 inet_ntop(ip->ipa_type, &ip->ip.addr, buf, size);
      92           0 :         return buf;
      93             : }
      94             : 
      95             : #define IS_MAPPED_IPV6(A)                                                      \
      96             :         ((A)->s6_addr32[0] == 0x00000000                                       \
      97             :                  ? ((A)->s6_addr32[1] == 0x00000000                            \
      98             :                             ? (ntohl((A)->s6_addr32[2]) == 0xFFFF ? 1 : 0)     \
      99             :                             : 0)                                               \
     100             :                  : 0)
     101             : 
     102             : /*
     103             :  * Convert IPv4 address to IPv4-mapped IPv6 address which is of the
     104             :  * form ::FFFF:<IPv4 address> (RFC 4291). This IPv6 address can then
     105             :  * be used to represent the IPv4 address, wherever only an IPv6 address
     106             :  * is required.
     107             :  */
     108           0 : static inline void ipv4_to_ipv4_mapped_ipv6(struct in6_addr *in6,
     109             :                                             struct in_addr in)
     110             : {
     111           0 :         uint32_t addr_type = htonl(0xFFFF);
     112             : 
     113           0 :         memset(in6, 0, sizeof(struct in6_addr));
     114           0 :         memcpy((char *)in6 + 8, &addr_type, sizeof(addr_type));
     115           0 :         memcpy((char *)in6 + 12, &in, sizeof(struct in_addr));
     116             : }
     117             : 
     118             : /*
     119             :  * convert an ipv4 mapped ipv6 address back to ipv4 address
     120             :  */
     121           0 : static inline void ipv4_mapped_ipv6_to_ipv4(const struct in6_addr *in6,
     122             :                                             struct in_addr *in)
     123             : {
     124           0 :         memset(in, 0, sizeof(struct in_addr));
     125           0 :         memcpy(in, (char *)in6 + 12, sizeof(struct in_addr));
     126           0 : }
     127             : 
     128             : /*
     129             :  * generic ordering comparison between IP addresses
     130             :  */
     131          34 : static inline int ipaddr_cmp(const struct ipaddr *a, const struct ipaddr *b)
     132             : {
     133          34 :         uint32_t va, vb;
     134          34 :         va = a->ipa_type;
     135          34 :         vb = b->ipa_type;
     136          34 :         if (va != vb)
     137           0 :                 return (va < vb) ? -1 : 1;
     138          34 :         switch (a->ipa_type) {
     139           0 :         case IPADDR_V4:
     140           0 :                 va = ntohl(a->ipaddr_v4.s_addr);
     141           0 :                 vb = ntohl(b->ipaddr_v4.s_addr);
     142           0 :                 if (va != vb)
     143           0 :                         return (va < vb) ? -1 : 1;
     144             :                 return 0;
     145           0 :         case IPADDR_V6:
     146           0 :                 return memcmp((void *)&a->ipaddr_v6, (void *)&b->ipaddr_v6,
     147             :                               sizeof(a->ipaddr_v6));
     148             :         case IPADDR_NONE:
     149             :                 return 0;
     150             :         }
     151             : 
     152           0 :         assert(!"Reached end of function we should never hit");
     153             : }
     154             : 
     155           0 : static inline bool ipaddr_is_zero(const struct ipaddr *ip)
     156             : {
     157           0 :         switch (ip->ipa_type) {
     158             :         case IPADDR_NONE:
     159             :                 return true;
     160           0 :         case IPADDR_V4:
     161           0 :                 return ip->ipaddr_v4.s_addr == INADDR_ANY;
     162           0 :         case IPADDR_V6:
     163           0 :                 return IN6_IS_ADDR_UNSPECIFIED(&ip->ipaddr_v6);
     164             :         }
     165             :         return true;
     166             : }
     167             : 
     168             : #ifdef _FRR_ATTRIBUTE_PRINTFRR
     169             : #pragma FRR printfrr_ext "%pIA"  (struct ipaddr *)
     170             : #endif
     171             : 
     172             : #ifdef __cplusplus
     173             : }
     174             : #endif
     175             : 
     176             : #endif /* __IPADDR_H__ */

Generated by: LCOV version v1.16-topotato