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