]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_flowspec_vty.c
bgpd: Fix peer determination from parent for imported routes
[mirror_frr.git] / bgpd / bgp_flowspec_vty.c
1 /* BGP FlowSpec VTY
2 * Copyright (C) 2018 6WIND
3 *
4 * FRRouting is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2, or (at your option) any
7 * later version.
8 *
9 * FRRouting is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <zebra.h>
20 #include "command.h"
21
22 #include "bgpd/bgpd.h"
23 #include "bgpd/bgp_table.h"
24 #include "bgpd/bgp_attr.h"
25 #include "bgpd/bgp_ecommunity.h"
26 #include "bgpd/bgp_vty.h"
27 #include "bgpd/bgp_route.h"
28 #include "bgpd/bgp_aspath.h"
29 #include "bgpd/bgp_flowspec.h"
30 #include "bgpd/bgp_flowspec_util.h"
31 #include "bgpd/bgp_flowspec_private.h"
32 #include "bgpd/bgp_debug.h"
33
34 /* Local Structures and variables declarations
35 * This code block hosts the struct declared that host the flowspec rules
36 * as well as some structure used to convert to stringx
37 */
38
39 static const struct message bgp_flowspec_display_large[] = {
40 {FLOWSPEC_DEST_PREFIX, "Destination Address"},
41 {FLOWSPEC_SRC_PREFIX, "Source Address"},
42 {FLOWSPEC_IP_PROTOCOL, "IP Protocol"},
43 {FLOWSPEC_PORT, "Port"},
44 {FLOWSPEC_DEST_PORT, "Destination Port"},
45 {FLOWSPEC_SRC_PORT, "Source Port"},
46 {FLOWSPEC_ICMP_TYPE, "ICMP Type"},
47 {FLOWSPEC_ICMP_CODE, "ICMP Code"},
48 {FLOWSPEC_TCP_FLAGS, "TCP Flags"},
49 {FLOWSPEC_PKT_LEN, "Packet Length"},
50 {FLOWSPEC_DSCP, "DSCP field"},
51 {FLOWSPEC_FRAGMENT, "Packet Fragment"},
52 {0}
53 };
54
55 static const struct message bgp_flowspec_display_min[] = {
56 {FLOWSPEC_DEST_PREFIX, "to"},
57 {FLOWSPEC_SRC_PREFIX, "from"},
58 {FLOWSPEC_IP_PROTOCOL, "proto"},
59 {FLOWSPEC_PORT, "port"},
60 {FLOWSPEC_DEST_PORT, "dstp"},
61 {FLOWSPEC_SRC_PORT, "srcp"},
62 {FLOWSPEC_ICMP_TYPE, "type"},
63 {FLOWSPEC_ICMP_CODE, "code"},
64 {FLOWSPEC_TCP_FLAGS, "flags"},
65 {FLOWSPEC_PKT_LEN, "pktlen"},
66 {FLOWSPEC_DSCP, "dscp"},
67 {FLOWSPEC_FRAGMENT, "pktfrag"},
68 {0}
69 };
70
71 #define FS_STRING_UPDATE(count, ptr, format, remaining_len) do { \
72 int _len_written; \
73 \
74 if (((format) == NLRI_STRING_FORMAT_DEBUG) && (count)) {\
75 _len_written = snprintf((ptr), (remaining_len), \
76 ", "); \
77 (remaining_len) -= _len_written; \
78 (ptr) += _len_written; \
79 } else if (((format) == NLRI_STRING_FORMAT_MIN) \
80 && (count)) { \
81 _len_written = snprintf((ptr), (remaining_len), \
82 " "); \
83 (remaining_len) -= _len_written; \
84 (ptr) += _len_written; \
85 } \
86 count++; \
87 } while (0)
88
89 /* Parse FLOWSPEC NLRI
90 * passed return_string string has assumed length
91 * BGP_FLOWSPEC_STRING_DISPLAY_MAX
92 */
93 void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
94 char *return_string, int format,
95 json_object *json_path)
96 {
97 uint32_t offset = 0;
98 int type;
99 int ret = 0, error = 0;
100 char *ptr = return_string;
101 char local_string[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
102 int count = 0;
103 char extra[2] = "";
104 char pre_extra[2] = "";
105 const struct message *bgp_flowspec_display;
106 enum bgp_flowspec_util_nlri_t type_util;
107 int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
108 int len_written;
109
110 if (format == NLRI_STRING_FORMAT_LARGE) {
111 snprintf(pre_extra, sizeof(pre_extra), "\t");
112 snprintf(extra, sizeof(extra), "\n");
113 bgp_flowspec_display = bgp_flowspec_display_large;
114 } else
115 bgp_flowspec_display = bgp_flowspec_display_min;
116 /* if needed. type_util can be set to other values */
117 type_util = BGP_FLOWSPEC_RETURN_STRING;
118 error = 0;
119 while (offset < len-1 && error >= 0) {
120 type = nlri_content[offset];
121 offset++;
122 switch (type) {
123 case FLOWSPEC_DEST_PREFIX:
124 case FLOWSPEC_SRC_PREFIX:
125 ret = bgp_flowspec_ip_address(
126 type_util,
127 nlri_content+offset,
128 len - offset,
129 local_string, &error);
130 if (ret <= 0)
131 break;
132 if (json_path) {
133 json_object_string_add(json_path,
134 lookup_msg(bgp_flowspec_display, type, ""),
135 local_string);
136 break;
137 }
138 FS_STRING_UPDATE(count, ptr, format, len_string);
139 len_written = snprintf(ptr, len_string, "%s%s %s%s",
140 pre_extra,
141 lookup_msg(bgp_flowspec_display,
142 type, ""),
143 local_string, extra);
144 len_string -= len_written;
145 ptr += len_written;
146 break;
147 case FLOWSPEC_IP_PROTOCOL:
148 case FLOWSPEC_PORT:
149 case FLOWSPEC_DEST_PORT:
150 case FLOWSPEC_SRC_PORT:
151 case FLOWSPEC_ICMP_TYPE:
152 case FLOWSPEC_ICMP_CODE:
153 ret = bgp_flowspec_op_decode(type_util,
154 nlri_content+offset,
155 len - offset,
156 local_string, &error);
157 if (ret <= 0)
158 break;
159 if (json_path) {
160 json_object_string_add(json_path,
161 lookup_msg(bgp_flowspec_display, type, ""),
162 local_string);
163 break;
164 }
165 FS_STRING_UPDATE(count, ptr, format, len_string);
166 len_written = snprintf(ptr, len_string, "%s%s %s%s",
167 pre_extra,
168 lookup_msg(bgp_flowspec_display,
169 type, ""),
170 local_string, extra);
171 len_string -= len_written;
172 ptr += len_written;
173 break;
174 case FLOWSPEC_TCP_FLAGS:
175 ret = bgp_flowspec_tcpflags_decode(
176 type_util,
177 nlri_content+offset,
178 len - offset,
179 local_string, &error);
180 if (ret <= 0)
181 break;
182 if (json_path) {
183 json_object_string_add(json_path,
184 lookup_msg(bgp_flowspec_display,
185 type, ""),
186 local_string);
187 break;
188 }
189 FS_STRING_UPDATE(count, ptr, format, len_string);
190 len_written = snprintf(ptr, len_string, "%s%s %s%s",
191 pre_extra,
192 lookup_msg(bgp_flowspec_display,
193 type, ""),
194 local_string, extra);
195 len_string -= len_written;
196 ptr += len_written;
197 break;
198 case FLOWSPEC_PKT_LEN:
199 case FLOWSPEC_DSCP:
200 ret = bgp_flowspec_op_decode(
201 type_util,
202 nlri_content + offset,
203 len - offset, local_string,
204 &error);
205 if (ret <= 0)
206 break;
207 if (json_path) {
208 json_object_string_add(json_path,
209 lookup_msg(bgp_flowspec_display, type, ""),
210 local_string);
211 break;
212 }
213 FS_STRING_UPDATE(count, ptr, format, len_string);
214 len_written = snprintf(ptr, len_string, "%s%s %s%s",
215 pre_extra,
216 lookup_msg(bgp_flowspec_display,
217 type, ""),
218 local_string, extra);
219 len_string -= len_written;
220 ptr += len_written;
221 break;
222 case FLOWSPEC_FRAGMENT:
223 ret = bgp_flowspec_fragment_type_decode(
224 type_util,
225 nlri_content + offset,
226 len - offset, local_string,
227 &error);
228 if (ret <= 0)
229 break;
230 if (json_path) {
231 json_object_string_add(json_path,
232 lookup_msg(bgp_flowspec_display,
233 type, ""),
234 local_string);
235 break;
236 }
237 FS_STRING_UPDATE(count, ptr, format, len_string);
238 len_written = snprintf(ptr, len_string, "%s%s %s%s",
239 pre_extra,
240 lookup_msg(bgp_flowspec_display,
241 type, ""),
242 local_string, extra);
243 len_string -= len_written;
244 ptr += len_written;
245 break;
246 default:
247 error = -1;
248 break;
249 }
250 offset += ret;
251 }
252 }
253
254 void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
255 struct bgp_info *binfo,
256 int display, json_object *json_paths)
257 {
258 struct attr *attr;
259 char return_string[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
260 char *s;
261 json_object *json_nlri_path = NULL;
262 json_object *json_ecom_path = NULL;
263 json_object *json_time_path = NULL;
264 char timebuf[BGP_UPTIME_LEN];
265
266 /* Print prefix */
267 if (p != NULL) {
268 if (p->family != AF_FLOWSPEC)
269 return;
270 if (json_paths) {
271 if (display == NLRI_STRING_FORMAT_JSON)
272 json_nlri_path = json_object_new_object();
273 else
274 json_nlri_path = json_paths;
275 }
276 if (display == NLRI_STRING_FORMAT_LARGE)
277 vty_out(vty, "BGP flowspec entry: (flags 0x%x)\n",
278 binfo->flags);
279 bgp_fs_nlri_get_string((unsigned char *)
280 p->u.prefix_flowspec.ptr,
281 p->u.prefix_flowspec.prefixlen,
282 return_string,
283 display,
284 json_nlri_path);
285 if (display == NLRI_STRING_FORMAT_LARGE)
286 vty_out(vty, "%s", return_string);
287 else if (display == NLRI_STRING_FORMAT_DEBUG)
288 vty_out(vty, "%s", return_string);
289 else if (display == NLRI_STRING_FORMAT_MIN)
290 vty_out(vty, " %-30s", return_string);
291 else if (json_paths && display == NLRI_STRING_FORMAT_JSON)
292 json_object_array_add(json_paths, json_nlri_path);
293 }
294 if (!binfo)
295 return;
296 if (binfo->attr && binfo->attr->ecommunity) {
297 /* Print attribute */
298 attr = binfo->attr;
299 s = ecommunity_ecom2str(attr->ecommunity,
300 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
301 if (!s)
302 return;
303 if (display == NLRI_STRING_FORMAT_LARGE)
304 vty_out(vty, "\t%s\n", s);
305 else if (display == NLRI_STRING_FORMAT_MIN)
306 vty_out(vty, "%s", s);
307 else if (json_paths) {
308 json_ecom_path = json_object_new_object();
309 json_object_string_add(json_ecom_path,
310 "ecomlist", s);
311 if (display == NLRI_STRING_FORMAT_JSON)
312 json_object_array_add(json_paths,
313 json_ecom_path);
314 }
315 if (attr->nexthop.s_addr != 0 &&
316 display == NLRI_STRING_FORMAT_LARGE)
317 vty_out(vty, "\tNH %-16s\n", inet_ntoa(attr->nexthop));
318 XFREE(MTYPE_ECOMMUNITY_STR, s);
319 }
320 peer_uptime(binfo->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL);
321 if (display == NLRI_STRING_FORMAT_LARGE)
322 vty_out(vty, "\tup for %8s\n", timebuf);
323 else if (json_paths) {
324 json_time_path = json_object_new_object();
325 json_object_string_add(json_time_path,
326 "time", timebuf);
327 if (display == NLRI_STRING_FORMAT_JSON)
328 json_object_array_add(json_paths, json_time_path);
329 }
330
331 }
332
333 int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi,
334 struct bgp_table *table, enum bgp_show_type type,
335 void *output_arg, uint8_t use_json,
336 int is_last, unsigned long *output_cum,
337 unsigned long *total_cum)
338 {
339 struct bgp_info *ri;
340 struct bgp_node *rn;
341 unsigned long total_count = 0;
342 json_object *json_paths = NULL;
343 int display = NLRI_STRING_FORMAT_LARGE;
344
345 if (type != bgp_show_type_detail)
346 return CMD_SUCCESS;
347
348 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
349 if (rn->info == NULL)
350 continue;
351 if (use_json) {
352 json_paths = json_object_new_array();
353 display = NLRI_STRING_FORMAT_JSON;
354 }
355 for (ri = rn->info; ri; ri = ri->next) {
356 total_count++;
357 route_vty_out_flowspec(vty, &rn->p,
358 ri, display,
359 json_paths);
360
361 }
362 if (use_json) {
363 vty_out(vty, "%s\n",
364 json_object_to_json_string_ext(
365 json_paths,
366 JSON_C_TO_STRING_PRETTY));
367 json_object_free(json_paths);
368 json_paths = NULL;
369 }
370 }
371 if (total_count && !use_json)
372 vty_out(vty,
373 "\nDisplayed %ld flowspec entries\n",
374 total_count);
375 return CMD_SUCCESS;
376 }
377
378 DEFUN (debug_bgp_flowspec,
379 debug_bgp_flowspec_cmd,
380 "debug bgp flowspec",
381 DEBUG_STR
382 BGP_STR
383 "BGP allow flowspec debugging entries\n")
384 {
385 if (vty->node == CONFIG_NODE)
386 DEBUG_ON(flowspec, FLOWSPEC);
387 else {
388 TERM_DEBUG_ON(flowspec, FLOWSPEC);
389 vty_out(vty, "BGP flowspec debugging is on\n");
390 }
391 return CMD_SUCCESS;
392 }
393
394 DEFUN (no_debug_bgp_flowspec,
395 no_debug_bgp_flowspec_cmd,
396 "no debug bgp flowspec",
397 NO_STR
398 DEBUG_STR
399 BGP_STR
400 "BGP allow flowspec debugging entries\n")
401 {
402 if (vty->node == CONFIG_NODE)
403 DEBUG_OFF(flowspec, FLOWSPEC);
404 else {
405 TERM_DEBUG_OFF(flowspec, FLOWSPEC);
406 vty_out(vty, "BGP flowspec debugging is off\n");
407 }
408 return CMD_SUCCESS;
409 }
410
411 void bgp_flowspec_vty_init(void)
412 {
413 install_element(ENABLE_NODE, &debug_bgp_flowspec_cmd);
414 install_element(CONFIG_NODE, &debug_bgp_flowspec_cmd);
415 install_element(ENABLE_NODE, &no_debug_bgp_flowspec_cmd);
416 install_element(CONFIG_NODE, &no_debug_bgp_flowspec_cmd);
417 }