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