]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_rd.c
Merge pull request #12780 from opensourcerouting/spdx-license-id
[mirror_frr.git] / bgpd / bgp_rd.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP RD definitions for BGP-based VPNs (IP/EVPN)
3 * -- brought over from bgpd/bgp_mplsvpn.c
4 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
5 */
6
7 #include <zebra.h>
8 #include "command.h"
9 #include "log.h"
10 #include "prefix.h"
11 #include "memory.h"
12 #include "stream.h"
13 #include "filter.h"
14 #include "frrstr.h"
15
16 #include "lib/printfrr.h"
17
18 #include "bgpd/bgpd.h"
19 #include "bgpd/bgp_rd.h"
20 #include "bgpd/bgp_attr.h"
21
22 #ifdef ENABLE_BGP_VNC
23 #include "bgpd/rfapi/rfapi_backend.h"
24 #endif
25
26 uint16_t decode_rd_type(const uint8_t *pnt)
27 {
28 uint16_t v;
29
30 v = ((uint16_t)*pnt++ << 8);
31 #ifdef ENABLE_BGP_VNC
32 /*
33 * VNC L2 stores LHI in lower byte, so omit it
34 */
35 if (v != RD_TYPE_VNC_ETH)
36 v |= (uint16_t)*pnt;
37 #else /* duplicate code for clarity */
38 v |= (uint16_t)*pnt;
39 #endif
40 return v;
41 }
42
43 void encode_rd_type(uint16_t v, uint8_t *pnt)
44 {
45 *((uint16_t *)pnt) = htons(v);
46 }
47
48 /* type == RD_TYPE_AS */
49 void decode_rd_as(const uint8_t *pnt, struct rd_as *rd_as)
50 {
51 rd_as->as = (uint16_t)*pnt++ << 8;
52 rd_as->as |= (uint16_t)*pnt++;
53 ptr_get_be32(pnt, &rd_as->val);
54 }
55
56 /* type == RD_TYPE_AS4 */
57 void decode_rd_as4(const uint8_t *pnt, struct rd_as *rd_as)
58 {
59 pnt = ptr_get_be32(pnt, &rd_as->as);
60 rd_as->val = ((uint16_t)*pnt++ << 8);
61 rd_as->val |= (uint16_t)*pnt;
62 }
63
64 /* type == RD_TYPE_IP */
65 void decode_rd_ip(const uint8_t *pnt, struct rd_ip *rd_ip)
66 {
67 memcpy(&rd_ip->ip, pnt, 4);
68 pnt += 4;
69
70 rd_ip->val = ((uint16_t)*pnt++ << 8);
71 rd_ip->val |= (uint16_t)*pnt;
72 }
73
74 #ifdef ENABLE_BGP_VNC
75 /* type == RD_TYPE_VNC_ETH */
76 void decode_rd_vnc_eth(const uint8_t *pnt, struct rd_vnc_eth *rd_vnc_eth)
77 {
78 rd_vnc_eth->type = RD_TYPE_VNC_ETH;
79 rd_vnc_eth->local_nve_id = pnt[1];
80 memcpy(rd_vnc_eth->macaddr.octet, pnt + 2, ETH_ALEN);
81 }
82 #endif
83
84 int str2prefix_rd(const char *str, struct prefix_rd *prd)
85 {
86 int ret = 0;
87 char *p;
88 char *p2;
89 struct stream *s = NULL;
90 char *half = NULL;
91 struct in_addr addr;
92
93 prd->family = AF_UNSPEC;
94 prd->prefixlen = 64;
95
96 p = strchr(str, ':');
97 if (!p)
98 goto out;
99
100 if (!all_digit(p + 1))
101 goto out;
102
103 s = stream_new(RD_BYTES);
104
105 half = XMALLOC(MTYPE_TMP, (p - str) + 1);
106 memcpy(half, str, (p - str));
107 half[p - str] = '\0';
108
109 p2 = strchr(str, '.');
110
111 if (!p2) {
112 unsigned long as_val;
113
114 if (!all_digit(half))
115 goto out;
116
117 as_val = atol(half);
118 if (as_val > 0xffff) {
119 stream_putw(s, RD_TYPE_AS4);
120 stream_putl(s, as_val);
121 stream_putw(s, atol(p + 1));
122 } else {
123 stream_putw(s, RD_TYPE_AS);
124 stream_putw(s, as_val);
125 stream_putl(s, atol(p + 1));
126 }
127 } else {
128 if (!inet_aton(half, &addr))
129 goto out;
130
131 stream_putw(s, RD_TYPE_IP);
132 stream_put_in_addr(s, &addr);
133 stream_putw(s, atol(p + 1));
134 }
135 memcpy(prd->val, s->data, 8);
136 ret = 1;
137
138 out:
139 if (s)
140 stream_free(s);
141 XFREE(MTYPE_TMP, half);
142 return ret;
143 }
144
145 char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size)
146 {
147 const uint8_t *pnt;
148 uint16_t type;
149 struct rd_as rd_as;
150 struct rd_ip rd_ip;
151
152 assert(size >= RD_ADDRSTRLEN);
153
154 pnt = prd->val;
155
156 type = decode_rd_type(pnt);
157
158 if (type == RD_TYPE_AS) {
159 decode_rd_as(pnt + 2, &rd_as);
160 snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val);
161 return buf;
162 } else if (type == RD_TYPE_AS4) {
163 decode_rd_as4(pnt + 2, &rd_as);
164 snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val);
165 return buf;
166 } else if (type == RD_TYPE_IP) {
167 decode_rd_ip(pnt + 2, &rd_ip);
168 snprintfrr(buf, size, "%pI4:%hu", &rd_ip.ip, rd_ip.val);
169 return buf;
170 }
171 #ifdef ENABLE_BGP_VNC
172 else if (type == RD_TYPE_VNC_ETH) {
173 snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
174 *(pnt + 1), /* LHI */
175 *(pnt + 2), /* MAC[0] */
176 *(pnt + 3), *(pnt + 4), *(pnt + 5), *(pnt + 6),
177 *(pnt + 7));
178
179 return buf;
180 }
181 #endif
182
183 snprintf(buf, size, "Unknown Type: %d", type);
184 return buf;
185 }
186
187 void form_auto_rd(struct in_addr router_id,
188 uint16_t rd_id,
189 struct prefix_rd *prd)
190 {
191 char buf[100];
192
193 prd->family = AF_UNSPEC;
194 prd->prefixlen = 64;
195 snprintfrr(buf, sizeof(buf), "%pI4:%hu", &router_id, rd_id);
196 (void)str2prefix_rd(buf, prd);
197 }
198
199 printfrr_ext_autoreg_p("RD", printfrr_prd);
200 static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea,
201 const void *ptr)
202 {
203 char rd_buf[RD_ADDRSTRLEN];
204
205 if (!ptr)
206 return bputs(buf, "(null)");
207
208 prefix_rd2str(ptr, rd_buf, sizeof(rd_buf));
209
210 return bputs(buf, rd_buf);
211 }