]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* BGP-4 dump routine |
2 | Copyright (C) 1999 Kunihiro Ishiguro | |
3 | ||
4 | This file is part of GNU Zebra. | |
5 | ||
6 | GNU Zebra is free software; you can redistribute it and/or modify it | |
7 | under the terms of the GNU General Public License as published by the | |
8 | Free Software Foundation; either version 2, or (at your option) any | |
9 | later version. | |
10 | ||
11 | GNU Zebra is distributed in the hope that it will be useful, but | |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU Zebra; see the file COPYING. If not, write to the Free | |
18 | Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
19 | 02111-1307, USA. */ | |
20 | ||
21 | #include <zebra.h> | |
22 | ||
23 | #include "log.h" | |
24 | #include "stream.h" | |
25 | #include "sockunion.h" | |
26 | #include "command.h" | |
27 | #include "prefix.h" | |
28 | #include "thread.h" | |
29 | #include "bgpd/bgp_table.h" | |
30 | ||
31 | #include "bgpd/bgpd.h" | |
32 | #include "bgpd/bgp_route.h" | |
33 | #include "bgpd/bgp_attr.h" | |
34 | #include "bgpd/bgp_dump.h" | |
35 | \f | |
36 | enum bgp_dump_type | |
37 | { | |
38 | BGP_DUMP_ALL, | |
39 | BGP_DUMP_UPDATES, | |
40 | BGP_DUMP_ROUTES | |
41 | }; | |
42 | ||
43 | enum MRT_MSG_TYPES { | |
44 | MSG_NULL, | |
45 | MSG_START, /* sender is starting up */ | |
46 | MSG_DIE, /* receiver should shut down */ | |
47 | MSG_I_AM_DEAD, /* sender is shutting down */ | |
48 | MSG_PEER_DOWN, /* sender's peer is down */ | |
49 | MSG_PROTOCOL_BGP, /* msg is a BGP packet */ | |
50 | MSG_PROTOCOL_RIP, /* msg is a RIP packet */ | |
51 | MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */ | |
52 | MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */ | |
53 | MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */ | |
54 | MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */ | |
55 | MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */ | |
56 | MSG_TABLE_DUMP /* routing table dump */ | |
57 | }; | |
58 | ||
1f8ae70b | 59 | static int bgp_dump_interval_func (struct thread *); |
60 | ||
718e3744 | 61 | struct bgp_dump |
62 | { | |
63 | enum bgp_dump_type type; | |
64 | ||
65 | char *filename; | |
66 | ||
67 | FILE *fp; | |
68 | ||
69 | unsigned int interval; | |
70 | ||
71 | char *interval_str; | |
72 | ||
73 | struct thread *t_interval; | |
74 | }; | |
75 | ||
76 | /* BGP packet dump output buffer. */ | |
77 | struct stream *bgp_dump_obuf; | |
78 | ||
79 | /* BGP dump strucuture for 'dump bgp all' */ | |
80 | struct bgp_dump bgp_dump_all; | |
81 | ||
82 | /* BGP dump structure for 'dump bgp updates' */ | |
83 | struct bgp_dump bgp_dump_updates; | |
84 | ||
85 | /* BGP dump structure for 'dump bgp routes' */ | |
86 | struct bgp_dump bgp_dump_routes; | |
87 | ||
88 | /* Dump whole BGP table is very heavy process. */ | |
89 | struct thread *t_bgp_dump_routes; | |
90 | \f | |
91 | /* Some define for BGP packet dump. */ | |
94f2b392 | 92 | static FILE * |
718e3744 | 93 | bgp_dump_open_file (struct bgp_dump *bgp_dump) |
94 | { | |
95 | int ret; | |
96 | time_t clock; | |
97 | struct tm *tm; | |
98 | char fullpath[MAXPATHLEN]; | |
99 | char realpath[MAXPATHLEN]; | |
aa593d5e | 100 | mode_t oldumask; |
718e3744 | 101 | |
102 | time (&clock); | |
103 | tm = localtime (&clock); | |
104 | ||
105 | if (bgp_dump->filename[0] != DIRECTORY_SEP) | |
106 | { | |
107 | sprintf (fullpath, "%s/%s", vty_get_cwd (), bgp_dump->filename); | |
108 | ret = strftime (realpath, MAXPATHLEN, fullpath, tm); | |
109 | } | |
110 | else | |
111 | ret = strftime (realpath, MAXPATHLEN, bgp_dump->filename, tm); | |
112 | ||
113 | if (ret == 0) | |
114 | { | |
115 | zlog_warn ("bgp_dump_open_file: strftime error"); | |
116 | return NULL; | |
117 | } | |
118 | ||
119 | if (bgp_dump->fp) | |
120 | fclose (bgp_dump->fp); | |
121 | ||
122 | ||
aa593d5e | 123 | oldumask = umask(0777 & ~LOGFILE_MASK); |
718e3744 | 124 | bgp_dump->fp = fopen (realpath, "w"); |
125 | ||
126 | if (bgp_dump->fp == NULL) | |
aa593d5e | 127 | { |
128 | umask(oldumask); | |
129 | return NULL; | |
130 | } | |
131 | umask(oldumask); | |
718e3744 | 132 | |
133 | return bgp_dump->fp; | |
134 | } | |
135 | ||
94f2b392 | 136 | static int |
718e3744 | 137 | bgp_dump_interval_add (struct bgp_dump *bgp_dump, int interval) |
138 | { | |
9834cd0f | 139 | int interval2, secs_into_day; |
140 | time_t t; | |
141 | struct tm *tm; | |
718e3744 | 142 | |
fba3d22b | 143 | if (interval > 0 ) |
9834cd0f | 144 | { |
145 | if ((interval < 86400) && ((86400 % interval) == 0)) | |
146 | { | |
147 | (void) time(&t); | |
148 | tm = localtime(&t); | |
149 | secs_into_day = tm->tm_sec + 60*tm->tm_min + 60*60*tm->tm_hour; | |
150 | interval2 = interval - secs_into_day % interval; | |
151 | if(interval2 == 0) interval2 = interval; | |
152 | } | |
153 | else | |
154 | { | |
155 | interval2 = interval; | |
156 | } | |
157 | bgp_dump->t_interval = thread_add_timer (master, bgp_dump_interval_func, | |
158 | bgp_dump, interval2); | |
159 | } | |
fba3d22b | 160 | else |
9834cd0f | 161 | { |
162 | bgp_dump->t_interval = thread_add_event (master, bgp_dump_interval_func, | |
163 | bgp_dump, 0); | |
164 | } | |
fba3d22b | 165 | |
718e3744 | 166 | return 0; |
167 | } | |
168 | ||
169 | /* Dump common header. */ | |
94f2b392 | 170 | static void |
718e3744 | 171 | bgp_dump_header (struct stream *obuf, int type, int subtype) |
172 | { | |
173 | time_t now; | |
174 | ||
175 | /* Set header. */ | |
176 | time (&now); | |
177 | ||
178 | /* Put dump packet header. */ | |
179 | stream_putl (obuf, now); | |
180 | stream_putw (obuf, type); | |
181 | stream_putw (obuf, subtype); | |
182 | ||
183 | stream_putl (obuf, 0); /* len */ | |
184 | } | |
185 | ||
94f2b392 | 186 | static void |
718e3744 | 187 | bgp_dump_set_size (struct stream *s, int type) |
188 | { | |
9985f83c | 189 | stream_putl_at (s, 8, stream_get_endp (s) - BGP_DUMP_HEADER_SIZE); |
718e3744 | 190 | } |
191 | ||
94f2b392 | 192 | static void |
718e3744 | 193 | bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi, |
194 | int type, unsigned int seq) | |
195 | { | |
196 | struct stream *obuf; | |
197 | struct attr *attr; | |
198 | struct peer *peer; | |
199 | int plen; | |
200 | int safi = 0; | |
201 | ||
202 | /* Make dump stream. */ | |
203 | obuf = bgp_dump_obuf; | |
204 | stream_reset (obuf); | |
205 | ||
206 | attr = info->attr; | |
207 | peer = info->peer; | |
208 | ||
209 | /* We support MRT's old format. */ | |
210 | if (type == MSG_TABLE_DUMP) | |
211 | { | |
212 | bgp_dump_header (obuf, MSG_TABLE_DUMP, afi); | |
213 | stream_putw (obuf, 0); /* View # */ | |
214 | stream_putw (obuf, seq); /* Sequence number. */ | |
215 | } | |
216 | else | |
217 | { | |
218 | bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY); | |
219 | ||
220 | stream_putl (obuf, info->uptime); /* Time Last Change */ | |
221 | stream_putw (obuf, afi); /* Address Family */ | |
222 | stream_putc (obuf, safi); /* SAFI */ | |
223 | } | |
224 | ||
225 | if (afi == AFI_IP) | |
226 | { | |
227 | if (type == MSG_TABLE_DUMP) | |
228 | { | |
229 | /* Prefix */ | |
230 | stream_put_in_addr (obuf, &p->u.prefix4); | |
231 | stream_putc (obuf, p->prefixlen); | |
232 | ||
233 | /* Status */ | |
234 | stream_putc (obuf, 1); | |
235 | ||
236 | /* Originated */ | |
237 | stream_putl (obuf, info->uptime); | |
238 | ||
239 | /* Peer's IP address */ | |
240 | stream_put_in_addr (obuf, &peer->su.sin.sin_addr); | |
241 | ||
242 | /* Peer's AS number. */ | |
243 | stream_putw (obuf, peer->as); | |
244 | ||
245 | /* Dump attribute. */ | |
1302bdc7 | 246 | bgp_dump_routes_attr (obuf, attr, p); |
718e3744 | 247 | } |
248 | else | |
249 | { | |
250 | /* Next-Hop-Len */ | |
251 | stream_putc (obuf, IPV4_MAX_BYTELEN); | |
252 | stream_put_in_addr (obuf, &attr->nexthop); | |
253 | stream_putc (obuf, p->prefixlen); | |
254 | plen = PSIZE (p->prefixlen); | |
255 | stream_put (obuf, &p->u.prefix4, plen); | |
1302bdc7 | 256 | bgp_dump_routes_attr (obuf, attr, p); |
718e3744 | 257 | } |
258 | } | |
259 | #ifdef HAVE_IPV6 | |
260 | else if (afi == AFI_IP6) | |
261 | { | |
262 | if (type == MSG_TABLE_DUMP) | |
263 | { | |
264 | /* Prefix */ | |
265 | stream_write (obuf, (u_char *)&p->u.prefix6, IPV6_MAX_BYTELEN); | |
266 | stream_putc (obuf, p->prefixlen); | |
267 | ||
268 | /* Status */ | |
269 | stream_putc (obuf, 1); | |
270 | ||
271 | /* Originated */ | |
272 | stream_putl (obuf, info->uptime); | |
273 | ||
274 | /* Peer's IP address */ | |
275 | stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr, | |
276 | IPV6_MAX_BYTELEN); | |
277 | ||
278 | /* Peer's AS number. */ | |
279 | stream_putw (obuf, peer->as); | |
280 | ||
281 | /* Dump attribute. */ | |
a384592f | 282 | bgp_dump_routes_attr (obuf, attr, p); |
718e3744 | 283 | } |
284 | else | |
285 | { | |
286 | ; | |
287 | } | |
288 | } | |
289 | #endif /* HAVE_IPV6 */ | |
290 | ||
291 | /* Set length. */ | |
292 | bgp_dump_set_size (obuf, type); | |
293 | ||
9985f83c | 294 | fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp); |
718e3744 | 295 | fflush (bgp_dump_routes.fp); |
296 | } | |
297 | ||
298 | /* Runs under child process. */ | |
94f2b392 | 299 | static void |
718e3744 | 300 | bgp_dump_routes_func (int afi) |
301 | { | |
302 | struct stream *obuf; | |
303 | struct bgp_node *rn; | |
304 | struct bgp_info *info; | |
305 | struct bgp *bgp; | |
306 | struct bgp_table *table; | |
307 | unsigned int seq = 0; | |
308 | ||
309 | obuf = bgp_dump_obuf; | |
310 | ||
311 | bgp = bgp_get_default (); | |
312 | if (!bgp) | |
313 | return; | |
314 | ||
315 | if (bgp_dump_routes.fp == NULL) | |
316 | return; | |
317 | ||
318 | /* Walk down each BGP route. */ | |
319 | table = bgp->rib[afi][SAFI_UNICAST]; | |
320 | ||
321 | for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) | |
322 | for (info = rn->info; info; info = info->next) | |
323 | bgp_dump_routes_entry (&rn->p, info, afi, MSG_TABLE_DUMP, seq++); | |
324 | } | |
325 | ||
94f2b392 | 326 | static int |
718e3744 | 327 | bgp_dump_interval_func (struct thread *t) |
328 | { | |
329 | struct bgp_dump *bgp_dump; | |
718e3744 | 330 | bgp_dump = THREAD_ARG (t); |
331 | bgp_dump->t_interval = NULL; | |
332 | ||
9834cd0f | 333 | /* Reschedule dump even if file couldn't be opened this time... */ |
334 | if (bgp_dump_open_file (bgp_dump) != NULL) | |
718e3744 | 335 | { |
9834cd0f | 336 | /* In case of bgp_dump_routes, we need special route dump function. */ |
337 | if (bgp_dump->type == BGP_DUMP_ROUTES) | |
338 | { | |
339 | bgp_dump_routes_func (AFI_IP); | |
a384592f | 340 | #ifdef HAVE_IPV6 |
9834cd0f | 341 | bgp_dump_routes_func (AFI_IP6); |
a384592f | 342 | #endif /* HAVE_IPV6 */ |
9834cd0f | 343 | /* Close the file now. For a RIB dump there's no point in leaving |
344 | * it open until the next scheduled dump starts. */ | |
345 | fclose(bgp_dump->fp); bgp_dump->fp = NULL; | |
346 | } | |
718e3744 | 347 | } |
348 | ||
fba3d22b | 349 | /* if interval is set reschedule */ |
350 | if (bgp_dump->interval > 0) | |
351 | bgp_dump_interval_add (bgp_dump, bgp_dump->interval); | |
352 | ||
718e3744 | 353 | return 0; |
354 | } | |
355 | ||
356 | /* Dump common information. */ | |
94f2b392 | 357 | static void |
718e3744 | 358 | bgp_dump_common (struct stream *obuf, struct peer *peer) |
359 | { | |
360 | char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | |
361 | ||
362 | /* Source AS number and Destination AS number. */ | |
363 | stream_putw (obuf, peer->as); | |
364 | stream_putw (obuf, peer->local_as); | |
365 | ||
a384592f | 366 | if (peer->su.sa.sa_family == AF_INET) |
718e3744 | 367 | { |
368 | stream_putw (obuf, peer->ifindex); | |
369 | stream_putw (obuf, AFI_IP); | |
370 | ||
371 | stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN); | |
372 | ||
373 | if (peer->su_local) | |
374 | stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN); | |
375 | else | |
376 | stream_put (obuf, empty, IPV4_MAX_BYTELEN); | |
377 | } | |
378 | #ifdef HAVE_IPV6 | |
a384592f | 379 | else if (peer->su.sa.sa_family == AF_INET6) |
718e3744 | 380 | { |
381 | /* Interface Index and Address family. */ | |
382 | stream_putw (obuf, peer->ifindex); | |
383 | stream_putw (obuf, AFI_IP6); | |
384 | ||
385 | /* Source IP Address and Destination IP Address. */ | |
386 | stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN); | |
387 | ||
388 | if (peer->su_local) | |
389 | stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN); | |
390 | else | |
391 | stream_put (obuf, empty, IPV6_MAX_BYTELEN); | |
392 | } | |
393 | #endif /* HAVE_IPV6 */ | |
394 | } | |
395 | ||
396 | /* Dump BGP status change. */ | |
397 | void | |
398 | bgp_dump_state (struct peer *peer, int status_old, int status_new) | |
399 | { | |
400 | struct stream *obuf; | |
401 | ||
402 | /* If dump file pointer is disabled return immediately. */ | |
403 | if (bgp_dump_all.fp == NULL) | |
404 | return; | |
405 | ||
406 | /* Make dump stream. */ | |
407 | obuf = bgp_dump_obuf; | |
408 | stream_reset (obuf); | |
409 | ||
410 | bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE); | |
411 | bgp_dump_common (obuf, peer); | |
412 | ||
413 | stream_putw (obuf, status_old); | |
414 | stream_putw (obuf, status_new); | |
415 | ||
416 | /* Set length. */ | |
417 | bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP); | |
418 | ||
419 | /* Write to the stream. */ | |
9985f83c | 420 | fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp); |
718e3744 | 421 | fflush (bgp_dump_all.fp); |
422 | } | |
423 | ||
94f2b392 | 424 | static void |
718e3744 | 425 | bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer, |
426 | struct stream *packet) | |
427 | { | |
428 | struct stream *obuf; | |
429 | ||
430 | /* If dump file pointer is disabled return immediately. */ | |
431 | if (bgp_dump->fp == NULL) | |
432 | return; | |
433 | ||
434 | /* Make dump stream. */ | |
435 | obuf = bgp_dump_obuf; | |
436 | stream_reset (obuf); | |
437 | ||
438 | /* Dump header and common part. */ | |
439 | bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE); | |
440 | bgp_dump_common (obuf, peer); | |
441 | ||
442 | /* Packet contents. */ | |
443 | stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet)); | |
444 | ||
445 | /* Set length. */ | |
446 | bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP); | |
447 | ||
448 | /* Write to the stream. */ | |
9985f83c | 449 | fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump->fp); |
718e3744 | 450 | fflush (bgp_dump->fp); |
451 | } | |
452 | ||
453 | /* Called from bgp_packet.c when BGP packet is received. */ | |
454 | void | |
455 | bgp_dump_packet (struct peer *peer, int type, struct stream *packet) | |
456 | { | |
457 | /* bgp_dump_all. */ | |
458 | bgp_dump_packet_func (&bgp_dump_all, peer, packet); | |
459 | ||
460 | /* bgp_dump_updates. */ | |
461 | if (type == BGP_MSG_UPDATE) | |
462 | bgp_dump_packet_func (&bgp_dump_updates, peer, packet); | |
463 | } | |
464 | \f | |
94f2b392 | 465 | static unsigned int |
fd79ac91 | 466 | bgp_dump_parse_time (const char *str) |
718e3744 | 467 | { |
468 | int i; | |
469 | int len; | |
470 | int seen_h; | |
471 | int seen_m; | |
472 | int time; | |
473 | unsigned int total; | |
474 | ||
475 | time = 0; | |
476 | total = 0; | |
477 | seen_h = 0; | |
478 | seen_m = 0; | |
479 | len = strlen (str); | |
480 | ||
481 | for (i = 0; i < len; i++) | |
482 | { | |
483 | if (isdigit ((int) str[i])) | |
484 | { | |
485 | time *= 10; | |
486 | time += str[i] - '0'; | |
487 | } | |
488 | else if (str[i] == 'H' || str[i] == 'h') | |
489 | { | |
490 | if (seen_h) | |
491 | return 0; | |
492 | if (seen_m) | |
493 | return 0; | |
494 | total += time * 60 *60; | |
495 | time = 0; | |
496 | seen_h = 1; | |
497 | } | |
498 | else if (str[i] == 'M' || str[i] == 'm') | |
499 | { | |
500 | if (seen_m) | |
501 | return 0; | |
502 | total += time * 60; | |
503 | time = 0; | |
504 | seen_h = 1; | |
505 | } | |
506 | else | |
507 | return 0; | |
508 | } | |
509 | return total + time; | |
510 | } | |
511 | ||
94f2b392 | 512 | static int |
718e3744 | 513 | bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump, int type, |
fd79ac91 | 514 | const char *path, const char *interval_str) |
718e3744 | 515 | { |
fba3d22b | 516 | unsigned int interval; |
517 | ||
718e3744 | 518 | if (interval_str) |
519 | { | |
fba3d22b | 520 | |
718e3744 | 521 | /* Check interval string. */ |
522 | interval = bgp_dump_parse_time (interval_str); | |
523 | if (interval == 0) | |
524 | { | |
525 | vty_out (vty, "Malformed interval string%s", VTY_NEWLINE); | |
526 | return CMD_WARNING; | |
527 | } | |
528 | /* Set interval. */ | |
529 | bgp_dump->interval = interval; | |
530 | if (bgp_dump->interval_str) | |
531 | free (bgp_dump->interval_str); | |
532 | bgp_dump->interval_str = strdup (interval_str); | |
fba3d22b | 533 | |
718e3744 | 534 | } |
fba3d22b | 535 | else |
536 | { | |
537 | interval = 0; | |
538 | } | |
539 | ||
540 | /* Create interval thread. */ | |
541 | bgp_dump_interval_add (bgp_dump, interval); | |
718e3744 | 542 | |
543 | /* Set type. */ | |
544 | bgp_dump->type = type; | |
545 | ||
546 | /* Set file name. */ | |
547 | if (bgp_dump->filename) | |
548 | free (bgp_dump->filename); | |
549 | bgp_dump->filename = strdup (path); | |
550 | ||
551 | /* This should be called when interval is expired. */ | |
552 | bgp_dump_open_file (bgp_dump); | |
553 | ||
554 | return CMD_SUCCESS; | |
555 | } | |
556 | ||
94f2b392 | 557 | static int |
718e3744 | 558 | bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump) |
559 | { | |
560 | /* Set file name. */ | |
561 | if (bgp_dump->filename) | |
562 | { | |
563 | free (bgp_dump->filename); | |
564 | bgp_dump->filename = NULL; | |
565 | } | |
566 | ||
567 | /* This should be called when interval is expired. */ | |
568 | if (bgp_dump->fp) | |
569 | { | |
570 | fclose (bgp_dump->fp); | |
571 | bgp_dump->fp = NULL; | |
572 | } | |
573 | ||
574 | /* Create interval thread. */ | |
575 | if (bgp_dump->t_interval) | |
576 | { | |
577 | thread_cancel (bgp_dump->t_interval); | |
578 | bgp_dump->t_interval = NULL; | |
579 | } | |
580 | ||
581 | bgp_dump->interval = 0; | |
582 | ||
583 | if (bgp_dump->interval_str) | |
584 | { | |
585 | free (bgp_dump->interval_str); | |
586 | bgp_dump->interval_str = NULL; | |
587 | } | |
588 | ||
589 | ||
590 | return CMD_SUCCESS; | |
591 | } | |
592 | ||
593 | DEFUN (dump_bgp_all, | |
594 | dump_bgp_all_cmd, | |
595 | "dump bgp all PATH", | |
596 | "Dump packet\n" | |
597 | "BGP packet dump\n" | |
598 | "Dump all BGP packets\n" | |
599 | "Output filename\n") | |
600 | { | |
601 | return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], NULL); | |
602 | } | |
603 | ||
604 | DEFUN (dump_bgp_all_interval, | |
605 | dump_bgp_all_interval_cmd, | |
606 | "dump bgp all PATH INTERVAL", | |
607 | "Dump packet\n" | |
608 | "BGP packet dump\n" | |
609 | "Dump all BGP packets\n" | |
610 | "Output filename\n" | |
611 | "Interval of output\n") | |
612 | { | |
613 | return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], argv[1]); | |
614 | } | |
615 | ||
616 | DEFUN (no_dump_bgp_all, | |
617 | no_dump_bgp_all_cmd, | |
618 | "no dump bgp all [PATH] [INTERVAL]", | |
619 | NO_STR | |
620 | "Dump packet\n" | |
621 | "BGP packet dump\n" | |
622 | "Dump all BGP packets\n") | |
623 | { | |
624 | return bgp_dump_unset (vty, &bgp_dump_all); | |
625 | } | |
626 | ||
627 | DEFUN (dump_bgp_updates, | |
628 | dump_bgp_updates_cmd, | |
629 | "dump bgp updates PATH", | |
630 | "Dump packet\n" | |
631 | "BGP packet dump\n" | |
632 | "Dump BGP updates only\n" | |
633 | "Output filename\n") | |
634 | { | |
635 | return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], NULL); | |
636 | } | |
637 | ||
638 | DEFUN (dump_bgp_updates_interval, | |
639 | dump_bgp_updates_interval_cmd, | |
640 | "dump bgp updates PATH INTERVAL", | |
641 | "Dump packet\n" | |
642 | "BGP packet dump\n" | |
643 | "Dump BGP updates only\n" | |
644 | "Output filename\n" | |
645 | "Interval of output\n") | |
646 | { | |
647 | return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], argv[1]); | |
648 | } | |
649 | ||
650 | DEFUN (no_dump_bgp_updates, | |
651 | no_dump_bgp_updates_cmd, | |
652 | "no dump bgp updates [PATH] [INTERVAL]", | |
653 | NO_STR | |
654 | "Dump packet\n" | |
655 | "BGP packet dump\n" | |
656 | "Dump BGP updates only\n") | |
657 | { | |
658 | return bgp_dump_unset (vty, &bgp_dump_updates); | |
659 | } | |
660 | ||
661 | DEFUN (dump_bgp_routes, | |
662 | dump_bgp_routes_cmd, | |
663 | "dump bgp routes-mrt PATH", | |
664 | "Dump packet\n" | |
665 | "BGP packet dump\n" | |
666 | "Dump whole BGP routing table\n" | |
667 | "Output filename\n") | |
668 | { | |
669 | return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], NULL); | |
670 | } | |
671 | ||
672 | DEFUN (dump_bgp_routes_interval, | |
673 | dump_bgp_routes_interval_cmd, | |
674 | "dump bgp routes-mrt PATH INTERVAL", | |
675 | "Dump packet\n" | |
676 | "BGP packet dump\n" | |
677 | "Dump whole BGP routing table\n" | |
678 | "Output filename\n" | |
679 | "Interval of output\n") | |
680 | { | |
681 | return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], argv[1]); | |
682 | } | |
683 | ||
684 | DEFUN (no_dump_bgp_routes, | |
685 | no_dump_bgp_routes_cmd, | |
686 | "no dump bgp routes-mrt [PATH] [INTERVAL]", | |
687 | NO_STR | |
688 | "Dump packet\n" | |
689 | "BGP packet dump\n" | |
690 | "Dump whole BGP routing table\n") | |
691 | { | |
692 | return bgp_dump_unset (vty, &bgp_dump_routes); | |
693 | } | |
694 | ||
695 | /* BGP node structure. */ | |
696 | struct cmd_node bgp_dump_node = | |
697 | { | |
698 | DUMP_NODE, | |
699 | "", | |
501ba490 | 700 | 1 |
718e3744 | 701 | }; |
702 | ||
703 | #if 0 | |
704 | char * | |
705 | config_time2str (unsigned int interval) | |
706 | { | |
707 | static char buf[BUFSIZ]; | |
708 | ||
709 | buf[0] = '\0'; | |
710 | ||
711 | if (interval / 3600) | |
712 | { | |
713 | sprintf (buf, "%dh", interval / 3600); | |
714 | interval %= 3600; | |
715 | } | |
716 | if (interval / 60) | |
717 | { | |
718 | sprintf (buf + strlen (buf), "%dm", interval /60); | |
719 | interval %= 60; | |
720 | } | |
721 | if (interval) | |
722 | { | |
723 | sprintf (buf + strlen (buf), "%d", interval); | |
724 | } | |
725 | return buf; | |
726 | } | |
727 | #endif | |
728 | ||
94f2b392 | 729 | static int |
718e3744 | 730 | config_write_bgp_dump (struct vty *vty) |
731 | { | |
732 | if (bgp_dump_all.filename) | |
733 | { | |
734 | if (bgp_dump_all.interval_str) | |
735 | vty_out (vty, "dump bgp all %s %s%s", | |
736 | bgp_dump_all.filename, bgp_dump_all.interval_str, | |
737 | VTY_NEWLINE); | |
738 | else | |
739 | vty_out (vty, "dump bgp all %s%s", | |
740 | bgp_dump_all.filename, VTY_NEWLINE); | |
741 | } | |
742 | if (bgp_dump_updates.filename) | |
743 | { | |
744 | if (bgp_dump_updates.interval_str) | |
745 | vty_out (vty, "dump bgp updates %s %s%s", | |
746 | bgp_dump_updates.filename, bgp_dump_updates.interval_str, | |
747 | VTY_NEWLINE); | |
748 | else | |
749 | vty_out (vty, "dump bgp updates %s%s", | |
750 | bgp_dump_updates.filename, VTY_NEWLINE); | |
751 | } | |
752 | if (bgp_dump_routes.filename) | |
753 | { | |
754 | if (bgp_dump_routes.interval_str) | |
755 | vty_out (vty, "dump bgp routes-mrt %s %s%s", | |
756 | bgp_dump_routes.filename, bgp_dump_routes.interval_str, | |
757 | VTY_NEWLINE); | |
758 | else | |
759 | vty_out (vty, "dump bgp routes-mrt %s%s", | |
760 | bgp_dump_routes.filename, VTY_NEWLINE); | |
761 | } | |
762 | return 0; | |
763 | } | |
764 | \f | |
765 | /* Initialize BGP packet dump functionality. */ | |
766 | void | |
94f2b392 | 767 | bgp_dump_init (void) |
718e3744 | 768 | { |
769 | memset (&bgp_dump_all, 0, sizeof (struct bgp_dump)); | |
770 | memset (&bgp_dump_updates, 0, sizeof (struct bgp_dump)); | |
771 | memset (&bgp_dump_routes, 0, sizeof (struct bgp_dump)); | |
772 | ||
9834cd0f | 773 | bgp_dump_obuf = stream_new (BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER |
774 | + BGP_DUMP_HEADER_SIZE); | |
718e3744 | 775 | |
776 | install_node (&bgp_dump_node, config_write_bgp_dump); | |
777 | ||
778 | install_element (CONFIG_NODE, &dump_bgp_all_cmd); | |
779 | install_element (CONFIG_NODE, &dump_bgp_all_interval_cmd); | |
780 | install_element (CONFIG_NODE, &no_dump_bgp_all_cmd); | |
781 | install_element (CONFIG_NODE, &dump_bgp_updates_cmd); | |
782 | install_element (CONFIG_NODE, &dump_bgp_updates_interval_cmd); | |
783 | install_element (CONFIG_NODE, &no_dump_bgp_updates_cmd); | |
784 | install_element (CONFIG_NODE, &dump_bgp_routes_cmd); | |
785 | install_element (CONFIG_NODE, &dump_bgp_routes_interval_cmd); | |
786 | install_element (CONFIG_NODE, &no_dump_bgp_routes_cmd); | |
787 | } |