]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_rd.c
Merge pull request #806 from dwalton76/bgpd-set-ipv4-vpn-nexthop
[mirror_frr.git] / bgpd / bgp_rd.c
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
31 #include "bgpd/bgpd.h"
32 #include "bgpd/bgp_rd.h"
33 #include "bgpd/bgp_attr.h"
34
35 #if ENABLE_BGP_VNC
36 #include "bgpd/rfapi/rfapi_backend.h"
37 #endif
38
39 u_int16_t
40 decode_rd_type (u_char *pnt)
41 {
42 u_int16_t v;
43
44 v = ((u_int16_t) *pnt++ << 8);
45 #if ENABLE_BGP_VNC
46 /*
47 * VNC L2 stores LHI in lower byte, so omit it
48 */
49 if (v != RD_TYPE_VNC_ETH)
50 v |= (u_int16_t) *pnt;
51 #else /* duplicate code for clarity */
52 v |= (u_int16_t) *pnt;
53 #endif
54 return v;
55 }
56
57 void
58 encode_rd_type (u_int16_t v, u_char *pnt)
59 {
60 *((u_int16_t *)pnt) = htons(v);
61 }
62
63 /* type == RD_TYPE_AS */
64 void
65 decode_rd_as (u_char *pnt, struct rd_as *rd_as)
66 {
67 rd_as->as = (u_int16_t) *pnt++ << 8;
68 rd_as->as |= (u_int16_t) *pnt++;
69
70 rd_as->val = ((u_int32_t) *pnt++ << 24);
71 rd_as->val |= ((u_int32_t) *pnt++ << 16);
72 rd_as->val |= ((u_int32_t) *pnt++ << 8);
73 rd_as->val |= (u_int32_t) *pnt;
74 }
75
76 /* type == RD_TYPE_AS4 */
77 void
78 decode_rd_as4 (u_char *pnt, struct rd_as *rd_as)
79 {
80 rd_as->as = (u_int32_t) *pnt++ << 24;
81 rd_as->as |= (u_int32_t) *pnt++ << 16;
82 rd_as->as |= (u_int32_t) *pnt++ << 8;
83 rd_as->as |= (u_int32_t) *pnt++;
84
85 rd_as->val = ((u_int16_t) *pnt++ << 8);
86 rd_as->val |= (u_int16_t) *pnt;
87 }
88
89 /* type == RD_TYPE_IP */
90 void
91 decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
92 {
93 memcpy (&rd_ip->ip, pnt, 4);
94 pnt += 4;
95
96 rd_ip->val = ((u_int16_t) *pnt++ << 8);
97 rd_ip->val |= (u_int16_t) *pnt;
98 }
99
100 #if ENABLE_BGP_VNC
101 /* type == RD_TYPE_VNC_ETH */
102 void
103 decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth)
104 {
105 rd_vnc_eth->type = RD_TYPE_VNC_ETH;
106 rd_vnc_eth->local_nve_id = pnt[1];
107 memcpy (rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN);
108 }
109 #endif
110
111 int
112 str2prefix_rd (const char *str, struct prefix_rd *prd)
113 {
114 int ret; /* ret of called functions */
115 int lret; /* local ret, of this func */
116 char *p;
117 char *p2;
118 struct stream *s = NULL;
119 char *half = NULL;
120 struct in_addr addr;
121
122 s = stream_new (8);
123
124 prd->family = AF_UNSPEC;
125 prd->prefixlen = 64;
126
127 lret = 0;
128 p = strchr (str, ':');
129 if (! p)
130 goto out;
131
132 if (! all_digit (p + 1))
133 goto out;
134
135 half = XMALLOC (MTYPE_TMP, (p - str) + 1);
136 memcpy (half, str, (p - str));
137 half[p - str] = '\0';
138
139 p2 = strchr (str, '.');
140
141 if (! p2)
142 {
143 unsigned long as_val;
144
145 if (! all_digit (half))
146 goto out;
147
148 as_val = atol(half);
149 if (as_val > 0xffff)
150 {
151 stream_putw (s, RD_TYPE_AS4);
152 stream_putl (s, as_val);
153 stream_putw (s, atol (p + 1));
154 }
155 else
156 {
157 stream_putw (s, RD_TYPE_AS);
158 stream_putw (s, as_val);
159 stream_putl (s, atol (p + 1));
160 }
161 }
162 else
163 {
164 ret = inet_aton (half, &addr);
165 if (! ret)
166 goto out;
167
168 stream_putw (s, RD_TYPE_IP);
169 stream_put_in_addr (s, &addr);
170 stream_putw (s, atol (p + 1));
171 }
172 memcpy (prd->val, s->data, 8);
173 lret = 1;
174
175 out:
176 if (s)
177 stream_free (s);
178 if (half)
179 XFREE(MTYPE_TMP, half);
180 return lret;
181 }
182
183 char *
184 prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
185 {
186 u_char *pnt;
187 u_int16_t type;
188 struct rd_as rd_as;
189 struct rd_ip rd_ip;
190
191 if (size < RD_ADDRSTRLEN)
192 return NULL;
193
194 pnt = prd->val;
195
196 type = decode_rd_type (pnt);
197
198 if (type == RD_TYPE_AS)
199 {
200 decode_rd_as (pnt + 2, &rd_as);
201 snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
202 return buf;
203 }
204 else if (type == RD_TYPE_AS4)
205 {
206 decode_rd_as4 (pnt + 2, &rd_as);
207 snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
208 return buf;
209 }
210 else if (type == RD_TYPE_IP)
211 {
212 decode_rd_ip (pnt + 2, &rd_ip);
213 snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
214 return buf;
215 }
216 #if ENABLE_BGP_VNC
217 else if (type == RD_TYPE_VNC_ETH)
218 {
219 snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
220 *(pnt+1), /* LHI */
221 *(pnt+2), /* MAC[0] */
222 *(pnt+3),
223 *(pnt+4),
224 *(pnt+5),
225 *(pnt+6),
226 *(pnt+7));
227
228 return buf;
229 }
230 #endif
231 return NULL;
232 }