]> git.proxmox.com Git - mirror_frr.git/blame - lib/ipaddr.h
*: manual SPDX License ID conversions
[mirror_frr.git] / lib / ipaddr.h
CommitLineData
482c0fb0 1/*
2 * IP address structure (for generic IPv4 or IPv6 address)
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
4 *
5 * This file is part of FRR.
6 *
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#ifndef __IPADDR_H__
24#define __IPADDR_H__
25
26#include <zebra.h>
27
31f937fb
SM
28#include "lib/log.h"
29
5e244469
RW
30#ifdef __cplusplus
31extern "C" {
32#endif
33
482c0fb0 34/*
35 * Generic IP address - union of IPv4 and IPv6 address.
36 */
d62a17ae 37enum ipaddr_type_t {
713de9e3
DL
38 IPADDR_NONE = AF_UNSPEC,
39 IPADDR_V4 = AF_INET,
40 IPADDR_V6 = AF_INET6,
482c0fb0 41};
42
d62a17ae 43struct ipaddr {
44 enum ipaddr_type_t ipa_type;
45 union {
d7c0a89a 46 uint8_t addr;
d62a17ae 47 struct in_addr _v4_addr;
48 struct in6_addr _v6_addr;
49 } ip;
482c0fb0 50#define ipaddr_v4 ip._v4_addr
51#define ipaddr_v6 ip._v6_addr
7fb9d20f 52};
482c0fb0 53
54#define IS_IPADDR_NONE(p) ((p)->ipa_type == IPADDR_NONE)
55#define IS_IPADDR_V4(p) ((p)->ipa_type == IPADDR_V4)
56#define IS_IPADDR_V6(p) ((p)->ipa_type == IPADDR_V6)
57
58#define SET_IPADDR_V4(p) (p)->ipa_type = IPADDR_V4
59#define SET_IPADDR_V6(p) (p)->ipa_type = IPADDR_V6
60
4f838de4 61#define IPADDRSZ(p) \
2fff50ec 62 (IS_IPADDR_V4((p)) ? sizeof(struct in_addr) : sizeof(struct in6_addr))
4f838de4 63
c1657d26
PG
64#define IPADDR_STRING_SIZE 46
65
31f937fb
SM
66static inline int ipaddr_family(const struct ipaddr *ip)
67{
68 switch (ip->ipa_type) {
69 case IPADDR_V4:
70 return AF_INET;
71 case IPADDR_V6:
72 return AF_INET6;
bde30e78 73 case IPADDR_NONE:
31f937fb
SM
74 return AF_UNSPEC;
75 }
bde30e78
DS
76
77 assert(!"Reached end of function where we should never hit");
31f937fb
SM
78}
79
d62a17ae 80static inline int str2ipaddr(const char *str, struct ipaddr *ip)
482c0fb0 81{
d62a17ae 82 int ret;
482c0fb0 83
d62a17ae 84 memset(ip, 0, sizeof(struct ipaddr));
482c0fb0 85
d62a17ae 86 ret = inet_pton(AF_INET, str, &ip->ipaddr_v4);
87 if (ret > 0) /* Valid IPv4 address. */
88 {
89 ip->ipa_type = IPADDR_V4;
90 return 0;
91 }
92 ret = inet_pton(AF_INET6, str, &ip->ipaddr_v6);
93 if (ret > 0) /* Valid IPv6 address. */
94 {
95 ip->ipa_type = IPADDR_V6;
96 return 0;
97 }
482c0fb0 98
d62a17ae 99 return -1;
482c0fb0 100}
101
24774285 102static inline char *ipaddr2str(const struct ipaddr *ip, char *buf, int size)
482c0fb0 103{
d62a17ae 104 buf[0] = '\0';
713de9e3
DL
105 if (ip)
106 inet_ntop(ip->ipa_type, &ip->ip.addr, buf, size);
d62a17ae 107 return buf;
482c0fb0 108}
1ec31309 109
92d6f769
K
110#define IS_MAPPED_IPV6(A) \
111 ((A)->s6_addr32[0] == 0x00000000 \
112 ? ((A)->s6_addr32[1] == 0x00000000 \
113 ? (ntohl((A)->s6_addr32[2]) == 0xFFFF ? 1 : 0) \
114 : 0) \
115 : 0)
116
bfd498f0 117/*
118 * Convert IPv4 address to IPv4-mapped IPv6 address which is of the
119 * form ::FFFF:<IPv4 address> (RFC 4291). This IPv6 address can then
120 * be used to represent the IPv4 address, wherever only an IPv6 address
121 * is required.
122 */
1ec31309 123static inline void ipv4_to_ipv4_mapped_ipv6(struct in6_addr *in6,
124 struct in_addr in)
125{
d7c0a89a 126 uint32_t addr_type = htonl(0xFFFF);
55828363 127
1ec31309 128 memset(in6, 0, sizeof(struct in6_addr));
129 memcpy((char *)in6 + 8, &addr_type, sizeof(addr_type));
130 memcpy((char *)in6 + 12, &in, sizeof(struct in_addr));
131}
132
f50dc5e6
MK
133/*
134 * convert an ipv4 mapped ipv6 address back to ipv4 address
135 */
e4a1ec74 136static inline void ipv4_mapped_ipv6_to_ipv4(const struct in6_addr *in6,
f50dc5e6
MK
137 struct in_addr *in)
138{
139 memset(in, 0, sizeof(struct in_addr));
140 memcpy(in, (char *)in6 + 12, sizeof(struct in_addr));
141}
142
598b0dfc
SM
143/*
144 * generic ordering comparison between IP addresses
145 */
146static inline int ipaddr_cmp(const struct ipaddr *a, const struct ipaddr *b)
147{
148 uint32_t va, vb;
149 va = a->ipa_type;
150 vb = b->ipa_type;
151 if (va != vb)
152 return (va < vb) ? -1 : 1;
153 switch (a->ipa_type) {
154 case IPADDR_V4:
155 va = ntohl(a->ipaddr_v4.s_addr);
156 vb = ntohl(b->ipaddr_v4.s_addr);
157 if (va != vb)
158 return (va < vb) ? -1 : 1;
159 return 0;
160 case IPADDR_V6:
161 return memcmp((void *)&a->ipaddr_v6, (void *)&b->ipaddr_v6,
162 sizeof(a->ipaddr_v6));
bde30e78 163 case IPADDR_NONE:
598b0dfc
SM
164 return 0;
165 }
bde30e78
DS
166
167 assert(!"Reached end of function we should never hit");
598b0dfc
SM
168}
169
860e740b
IR
170static inline bool ipaddr_is_zero(const struct ipaddr *ip)
171{
172 switch (ip->ipa_type) {
173 case IPADDR_NONE:
174 return true;
175 case IPADDR_V4:
176 return ip->ipaddr_v4.s_addr == INADDR_ANY;
177 case IPADDR_V6:
178 return IN6_IS_ADDR_UNSPECIFIED(&ip->ipaddr_v6);
179 }
180 return true;
181}
182
dc5d0186
DL
183#ifdef _FRR_ATTRIBUTE_PRINTFRR
184#pragma FRR printfrr_ext "%pIA" (struct ipaddr *)
185#endif
186
5e244469
RW
187#ifdef __cplusplus
188}
189#endif
190
482c0fb0 191#endif /* __IPADDR_H__ */