mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-17 08:38:42 +00:00
Implements MRTdump feature.
This commit is contained in:
parent
610bb3cff0
commit
cf31112f0d
@ -75,6 +75,7 @@ config_alloc(byte *name)
|
||||
linpool *l = lp_new(p, 4080);
|
||||
struct config *c = lp_allocz(l, sizeof(struct config));
|
||||
|
||||
c->mrtdump_file = -1; /* Hack, this should be sysdep-specific */
|
||||
c->pool = p;
|
||||
cfg_mem = c->mem = l;
|
||||
c->file_name = cfg_strdup(name);
|
||||
|
@ -20,12 +20,15 @@ struct config {
|
||||
list protos; /* Configured protocol instances (struct proto_config) */
|
||||
list tables; /* Configured routing tables (struct rtable_config) */
|
||||
list logfiles; /* Configured log fils (sysdep) */
|
||||
int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */
|
||||
struct rtable_config *master_rtc; /* Configuration of master routing table */
|
||||
|
||||
u32 router_id; /* Our Router ID */
|
||||
ip_addr listen_bgp_addr; /* Listening BGP socket should use this address */
|
||||
unsigned listen_bgp_port; /* Listening BGP socket should use this port (0 is default) */
|
||||
u32 listen_bgp_flags; /* Listening BGP socket should use these flags */
|
||||
unsigned int proto_default_debug; /* Default protocol debug mask */
|
||||
unsigned proto_default_debug; /* Default protocol debug mask */
|
||||
unsigned proto_default_mrtdump; /* Default protocol mrtdump mask */
|
||||
int cli_debug; /* Tracing of CLI connections and commands */
|
||||
char *err_msg; /* Parser error message */
|
||||
int err_lino; /* Line containing error */
|
||||
|
@ -238,6 +238,14 @@ protocol rip {
|
||||
logging of connects and disconnects, 2 and higher for logging of
|
||||
all client commands). Default: 0.
|
||||
|
||||
<tag>mrtdump "<m/filename/"</tag>
|
||||
Set MRTdump file name. This option must be specified to allow MRTdump feature.
|
||||
Default: no dump file.
|
||||
|
||||
<tag>mrtdump protocols all|off|{ states, messages }</tag>
|
||||
Set global defaults of MRTdump options. See <cf/mrtdump/ in the following section.
|
||||
Default: off.
|
||||
|
||||
<tag>filter <m/name local variables/{ <m/commands/ }</tag> Define a filter. You can learn more about filters
|
||||
in the following chapter.
|
||||
|
||||
@ -301,8 +309,22 @@ to zero to disable it. An empty <cf><m/switch/</cf> is equivalent to <cf/on/
|
||||
<cf/events/ for events internal to the protocol and
|
||||
<cf/packets/ for packets sent and received by the protocol. Default: off.
|
||||
|
||||
<tag>router id <m/IPv4 address/</tag> This option can be used to override global
|
||||
router id for a given protocol. Default: uses global router id.
|
||||
<tag>mrtdump all|off|{ states, messages }</tag>
|
||||
|
||||
Set protocol MRTdump flags. MRTdump is a standard binary
|
||||
format for logging information from routing protocols and
|
||||
daemons. These flags control what kind of information is
|
||||
logged from the protocol to the MRTdump file (which must be
|
||||
specified by global <cf/mrtdump/ option, see the previous
|
||||
section). Although these flags are similar to flags of
|
||||
<cf/debug/ option, their meaning is different and
|
||||
protocol-specific. For BGP protocol, <cf/states/ logs BGP
|
||||
state changes and <cf/messages/ logs received BGP messages.
|
||||
Other protocols does not support MRTdump yet.
|
||||
|
||||
<tag>router id <m/IPv4 address/</tag> This option can be used
|
||||
to override global router id for a given protocol. Default:
|
||||
uses global router id.
|
||||
|
||||
<tag>import all | none | filter <m/name/ | filter { <m/filter commands/ } | where <m/filter expression/</tag>
|
||||
Specify a filter to be used for filtering routes coming from the protocol to the routing table. <cf/all/ is shorthand for <cf/where true/ and <cf/none/ is shorthand for <cf/where false/. Default: <cf/all/.
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "lib/endian.h"
|
||||
#include "lib/bitops.h"
|
||||
#include "lib/unaligned.h"
|
||||
|
||||
#ifdef DEBUGGING
|
||||
|
||||
@ -63,6 +64,7 @@ typedef u32 ip_addr;
|
||||
/* ipa_pxlen() requires that x != y */
|
||||
#define ipa_pxlen(x, y) ipv4_pxlen(_I(x), _I(y))
|
||||
#define ipa_getbit(x, y) (_I(x) & (0x80000000 >> (y)))
|
||||
#define ipa_put_addr(x, y) ipv4_put_addr(x, y)
|
||||
|
||||
#define ip_skip_header(x, y) ipv4_skip_header(x, y)
|
||||
|
||||
@ -93,6 +95,11 @@ static inline u32 ipv4_pxlen(u32 a, u32 b)
|
||||
return 31 - u32_log2(a ^ b);
|
||||
}
|
||||
|
||||
static inline byte * ipv4_put_addr(byte *buf, ip_addr a)
|
||||
{
|
||||
put_u32(buf, _I(a));
|
||||
return buf+4;
|
||||
}
|
||||
|
||||
#define IP_PREC_INTERNET_CONTROL 0xc0
|
||||
|
||||
|
11
lib/ipv6.h
11
lib/ipv6.h
@ -14,6 +14,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include "lib/string.h"
|
||||
#include "lib/bitops.h"
|
||||
#include "lib/unaligned.h"
|
||||
|
||||
typedef struct ipv6_addr {
|
||||
u32 addr[4];
|
||||
@ -68,6 +69,7 @@ typedef struct ipv6_addr {
|
||||
/* ipa_pxlen() requires that x != y */
|
||||
#define ipa_pxlen(x, y) ipv6_pxlen(x, y)
|
||||
#define ipa_getbit(x, y) ipv6_getbit(x, y)
|
||||
#define ipa_put_addr(x, y) ipv6_put_addr(x, y)
|
||||
#define ipa_absolutize(x,y) ipv6_absolutize(x,y)
|
||||
|
||||
/* In IPv6, SOCK_RAW does not return packet header */
|
||||
@ -115,6 +117,15 @@ static inline u32 ipv6_pxlen(ip_addr a, ip_addr b)
|
||||
return 32 * i + 31 - u32_log2(a.addr[i] ^ b.addr[i]);
|
||||
}
|
||||
|
||||
static inline byte * ipv6_put_addr(byte *buf, ip_addr a)
|
||||
{
|
||||
put_u32(buf+0, _I0(a));
|
||||
put_u32(buf+4, _I1(a));
|
||||
put_u32(buf+8, _I2(a));
|
||||
put_u32(buf+12, _I3(a));
|
||||
return buf+16;
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 1883 defines packet precendece, but RFC 2460 replaces it
|
||||
* by generic Traffic Class ID with no defined semantics. Better
|
||||
|
@ -45,7 +45,7 @@ CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILT
|
||||
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
|
||||
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE)
|
||||
CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION)
|
||||
CF_KEYWORDS(RELOAD, IN, OUT)
|
||||
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES)
|
||||
|
||||
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
|
||||
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE)
|
||||
@ -58,7 +58,7 @@ CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT)
|
||||
%type <r> rtable
|
||||
%type <s> optsym
|
||||
%type <ra> r_args
|
||||
%type <i> echo_mask echo_size debug_mask debug_list debug_flag export_or_preexport
|
||||
%type <i> echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport
|
||||
%type <t> proto_patt
|
||||
|
||||
CF_GRAMMAR
|
||||
@ -138,6 +138,7 @@ proto_item:
|
||||
}
|
||||
| DISABLED bool { this_proto->disabled = $2; }
|
||||
| DEBUG debug_mask { this_proto->debug = $2; }
|
||||
| MRTDUMP mrtdump_mask { this_proto->mrtdump = $2; }
|
||||
| IMPORT imexport { this_proto->in_filter = $2; }
|
||||
| EXPORT imexport { this_proto->out_filter = $2; }
|
||||
| TABLE rtable { this_proto->table = $2; }
|
||||
@ -166,6 +167,8 @@ debug_default:
|
||||
| DEBUG COMMANDS expr { new_config->cli_debug = $3; }
|
||||
;
|
||||
|
||||
/* MRTDUMP PROTOCOLS is in systep/unix/config.Y */
|
||||
|
||||
/* Interface patterns */
|
||||
|
||||
iface_patt_node_init:
|
||||
@ -251,6 +254,24 @@ debug_flag:
|
||||
| PACKETS { $$ = D_PACKETS; }
|
||||
;
|
||||
|
||||
/* MRTDump flags */
|
||||
|
||||
mrtdump_mask:
|
||||
ALL { $$ = ~0; }
|
||||
| OFF { $$ = 0; }
|
||||
| '{' mrtdump_list '}' { $$ = $2; }
|
||||
;
|
||||
|
||||
mrtdump_list:
|
||||
mrtdump_flag
|
||||
| mrtdump_list ',' mrtdump_flag { $$ = $1 | $3; }
|
||||
;
|
||||
|
||||
mrtdump_flag:
|
||||
STATES { $$ = MD_STATES; }
|
||||
| MESSAGES { $$ = MD_MESSAGES; }
|
||||
;
|
||||
|
||||
/* Password lists */
|
||||
|
||||
password_list:
|
||||
@ -450,9 +471,14 @@ CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protoco
|
||||
CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]])
|
||||
{ proto_xxable($3, XX_RELOAD_OUT); } ;
|
||||
|
||||
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging]])
|
||||
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | events | packets }), [[Control protocol debugging]])
|
||||
{ proto_debug($2, $3); }
|
||||
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]])
|
||||
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | events | packets }), [[Control protocol debugging via BIRD logs]])
|
||||
{ proto_debug($2, 0, $3); }
|
||||
;
|
||||
|
||||
CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]])
|
||||
CF_CLI(MRTDUMP, proto_patt mrtdump_mask, (<protocol> | <pattern> | all) (all | off | { states | messages }), [[Control protocol debugging via MRTdump format]])
|
||||
{ proto_debug($2, 1, $3); }
|
||||
;
|
||||
|
||||
proto_patt:
|
||||
|
27
nest/mrtdump.h
Normal file
27
nest/mrtdump.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* BIRD -- Password handling
|
||||
*
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#ifndef MRTDUMP_H
|
||||
#define MRTDUMP_H
|
||||
#include "nest/protocol.h"
|
||||
|
||||
/* MRTDump values */
|
||||
|
||||
#define MRTDUMP_HDR_LENGTH 12
|
||||
|
||||
#define BGP4MP 16
|
||||
|
||||
#define BGP4MP_MESSAGE 1
|
||||
#define BGP4MP_MESSAGE_AS4 4
|
||||
#define BGP4MP_STATE_CHANGE_AS4 5
|
||||
|
||||
|
||||
/* implemented in sysdep */
|
||||
void mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len);
|
||||
|
||||
#endif
|
||||
|
10
nest/proto.c
10
nest/proto.c
@ -111,6 +111,7 @@ proto_new(struct proto_config *c, unsigned size)
|
||||
|
||||
p->cf = c;
|
||||
p->debug = c->debug;
|
||||
p->mrtdump = c->mrtdump;
|
||||
p->name = c->name;
|
||||
p->preference = c->preference;
|
||||
p->disabled = c->disabled;
|
||||
@ -201,6 +202,7 @@ proto_config_new(struct protocol *pr, unsigned size)
|
||||
c->out_filter = FILTER_REJECT;
|
||||
c->table = c->global->master_rtc;
|
||||
c->debug = new_config->proto_default_debug;
|
||||
c->mrtdump = new_config->proto_default_mrtdump;
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -325,6 +327,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty
|
||||
{
|
||||
/* Generic attributes match, try converting them and then ask the protocol */
|
||||
p->debug = nc->debug;
|
||||
p->mrtdump = nc->mrtdump;
|
||||
if (p->proto->reconfigure && p->proto->reconfigure(p, nc))
|
||||
{
|
||||
DBG("\t%s: same\n", oc->name);
|
||||
@ -901,14 +904,17 @@ proto_xxable(char *pattern, int xx)
|
||||
}
|
||||
|
||||
void
|
||||
proto_debug(char *pattern, unsigned int mask)
|
||||
proto_debug(char *pattern, int which, unsigned int mask)
|
||||
{
|
||||
int cnt = 0;
|
||||
WALK_PROTO_LIST(p)
|
||||
if (patmatch(pattern, p->name))
|
||||
{
|
||||
cnt++;
|
||||
p->debug = mask;
|
||||
if (which == 0)
|
||||
p->debug = mask;
|
||||
else
|
||||
p->mrtdump = mask;
|
||||
}
|
||||
WALK_PROTO_LIST_END;
|
||||
if (!cnt)
|
||||
|
@ -82,7 +82,8 @@ struct proto_config {
|
||||
struct proto *proto; /* Instance we've created */
|
||||
char *name;
|
||||
char *dsc;
|
||||
unsigned debug, preference, disabled; /* Generic parameters */
|
||||
u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */
|
||||
unsigned preference, disabled; /* Generic parameters */
|
||||
u32 router_id; /* Protocol specific router ID */
|
||||
struct rtable_config *table; /* Table we're attached to */
|
||||
struct filter *in_filter, *out_filter; /* Attached filters */
|
||||
@ -125,7 +126,8 @@ struct proto {
|
||||
struct event *attn; /* "Pay attention" event */
|
||||
|
||||
char *name; /* Name of this instance (== cf->name) */
|
||||
unsigned debug; /* Debugging flags */
|
||||
u32 debug; /* Debugging flags */
|
||||
u32 mrtdump; /* MRTDump flags */
|
||||
unsigned preference; /* Default route preference */
|
||||
int min_scope; /* Minimal route scope accepted */
|
||||
unsigned accept_ra_types; /* Which types of route announcements are accepted (RA_OPTIMAL or RA_ANY) */
|
||||
@ -199,7 +201,7 @@ void proto_request_feeding(struct proto *p);
|
||||
void proto_show(struct symbol *, int);
|
||||
struct proto *proto_get_named(struct symbol *, struct protocol *);
|
||||
void proto_xxable(char *, int);
|
||||
void proto_debug(char *, unsigned int);
|
||||
void proto_debug(char *, int, unsigned int);
|
||||
|
||||
#define XX_DISABLE 0
|
||||
#define XX_ENABLE 1
|
||||
@ -306,6 +308,13 @@ void proto_notify_state(struct proto *p, unsigned state);
|
||||
#define D_EVENTS 16 /* Protocol events */
|
||||
#define D_PACKETS 32 /* Packets sent/received */
|
||||
|
||||
/*
|
||||
* MRTDump flags
|
||||
*/
|
||||
|
||||
#define MD_STATES 1 /* Protocol state changes (BGP4MP_MESSAGE_AS4) */
|
||||
#define MD_MESSAGES 2 /* Protocol packets (BGP4MP_MESSAGE_AS4) */
|
||||
|
||||
/*
|
||||
* Known unique protocol instances as referenced by config routines
|
||||
*/
|
||||
|
@ -313,6 +313,22 @@ bgp_stop(struct bgp_proto *p, unsigned subcode)
|
||||
ev_schedule(p->event);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bgp_conn_set_state(struct bgp_conn *conn, unsigned new_state)
|
||||
{
|
||||
if (conn->bgp->p.mrtdump & MD_STATES)
|
||||
mrt_dump_bgp_state_change(conn, conn->state, new_state);
|
||||
|
||||
conn->state = new_state;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_conn_enter_openconfirm_state(struct bgp_conn *conn)
|
||||
{
|
||||
/* Really, most of the work is done in bgp_rx_open(). */
|
||||
bgp_conn_set_state(conn, BS_OPENCONFIRM);
|
||||
}
|
||||
|
||||
void
|
||||
bgp_conn_enter_established_state(struct bgp_conn *conn)
|
||||
{
|
||||
@ -325,7 +341,7 @@ bgp_conn_enter_established_state(struct bgp_conn *conn)
|
||||
p->last_error_class = 0;
|
||||
p->last_error_code = 0;
|
||||
bgp_attr_init(conn->bgp);
|
||||
conn->state = BS_ESTABLISHED;
|
||||
bgp_conn_set_state(conn, BS_ESTABLISHED);
|
||||
proto_notify_state(&p->p, PS_UP);
|
||||
}
|
||||
|
||||
@ -345,7 +361,7 @@ bgp_conn_enter_close_state(struct bgp_conn *conn)
|
||||
struct bgp_proto *p = conn->bgp;
|
||||
int os = conn->state;
|
||||
|
||||
conn->state = BS_CLOSE;
|
||||
bgp_conn_set_state(conn, BS_CLOSE);
|
||||
tm_stop(conn->hold_timer);
|
||||
tm_stop(conn->keepalive_timer);
|
||||
conn->sk->rx_hook = NULL;
|
||||
@ -361,7 +377,7 @@ bgp_conn_enter_idle_state(struct bgp_conn *conn)
|
||||
int os = conn->state;
|
||||
|
||||
bgp_close_conn(conn);
|
||||
conn->state = BS_IDLE;
|
||||
bgp_conn_set_state(conn, BS_IDLE);
|
||||
ev_schedule(p->event);
|
||||
|
||||
if (os == BS_ESTABLISHED)
|
||||
@ -374,13 +390,14 @@ bgp_send_open(struct bgp_conn *conn)
|
||||
conn->start_state = conn->bgp->start_state;
|
||||
conn->want_as4_support = conn->bgp->cf->enable_as4 && (conn->start_state != BSS_CONNECT_NOCAP);
|
||||
conn->peer_as4_support = 0; // Default value, possibly changed by receiving capability.
|
||||
conn->advertised_as = 0;
|
||||
|
||||
DBG("BGP: Sending open\n");
|
||||
conn->sk->rx_hook = bgp_rx;
|
||||
conn->sk->tx_hook = bgp_tx;
|
||||
tm_stop(conn->connect_retry_timer);
|
||||
bgp_schedule_packet(conn, PKT_OPEN);
|
||||
conn->state = BS_OPENSENT;
|
||||
bgp_conn_set_state(conn, BS_OPENSENT);
|
||||
bgp_start_timer(conn->hold_timer, conn->bgp->cf->initial_hold_time);
|
||||
}
|
||||
|
||||
@ -490,7 +507,7 @@ bgp_active(struct bgp_proto *p)
|
||||
|
||||
BGP_TRACE(D_EVENTS, "Connect delayed by %d seconds", delay);
|
||||
bgp_setup_conn(p, conn);
|
||||
conn->state = BS_ACTIVE;
|
||||
bgp_conn_set_state(conn, BS_ACTIVE);
|
||||
bgp_start_timer(conn->connect_retry_timer, delay);
|
||||
}
|
||||
|
||||
@ -539,7 +556,7 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
|
||||
BGP_TRACE(D_EVENTS, "Connecting to %I from local address %I", s->daddr, s->saddr);
|
||||
bgp_setup_conn(p, conn);
|
||||
bgp_setup_sk(p, conn, s);
|
||||
conn->state = BS_CONNECT;
|
||||
bgp_conn_set_state(conn, BS_CONNECT);
|
||||
if (sk_open(s))
|
||||
{
|
||||
bgp_sock_err(s, 0);
|
||||
|
@ -138,6 +138,7 @@ void bgp_check(struct bgp_config *c);
|
||||
void bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len);
|
||||
void bgp_close_conn(struct bgp_conn *c);
|
||||
void bgp_update_startup_delay(struct bgp_proto *p);
|
||||
void bgp_conn_enter_openconfirm_state(struct bgp_conn *conn);
|
||||
void bgp_conn_enter_established_state(struct bgp_conn *conn);
|
||||
void bgp_conn_enter_close_state(struct bgp_conn *conn);
|
||||
void bgp_conn_enter_idle_state(struct bgp_conn *conn);
|
||||
@ -189,6 +190,7 @@ inline static void bgp_attach_attr_ip(struct ea_list **to, struct linpool *pool,
|
||||
|
||||
/* packets.c */
|
||||
|
||||
void mrt_dump_bgp_state_change(struct bgp_conn *conn, unsigned old, unsigned new);
|
||||
void bgp_schedule_packet(struct bgp_conn *conn, int type);
|
||||
void bgp_kick_tx(void *vconn);
|
||||
void bgp_tx(struct birdsock *sk);
|
||||
@ -294,4 +296,10 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi
|
||||
#define BGP_AF_IPV4 1
|
||||
#define BGP_AF_IPV6 2
|
||||
|
||||
#ifdef IPV6
|
||||
#define BGP_AF BGP_AF_IPV6
|
||||
#else
|
||||
#define BGP_AF BGP_AF_IPV4
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "nest/protocol.h"
|
||||
#include "nest/route.h"
|
||||
#include "nest/attrs.h"
|
||||
#include "nest/mrtdump.h"
|
||||
#include "conf/conf.h"
|
||||
#include "lib/unaligned.h"
|
||||
#include "lib/socket.h"
|
||||
@ -23,6 +24,84 @@
|
||||
|
||||
static struct rate_limit rl_rcv_update, rl_snd_update;
|
||||
|
||||
/*
|
||||
* MRT Dump format is not semantically specified.
|
||||
* We will use these values in appropriate fields:
|
||||
*
|
||||
* Local AS, Remote AS - configured AS numbers for given BGP instance.
|
||||
* Local IP, Remote IP - IP addresses of the TCP connection (0 if no connection)
|
||||
*
|
||||
* We dump two kinds of MRT messages: STATE_CHANGE (for BGP state
|
||||
* changes) and MESSAGE (for received BGP messages).
|
||||
*
|
||||
* STATE_CHANGE uses always AS4 variant, but MESSAGE uses AS4 variant
|
||||
* only when AS4 session is established and even in that case MESSAGE
|
||||
* does not use AS4 variant for initial OPEN message. This strange
|
||||
* behavior is here for compatibility with Quagga and Bgpdump,
|
||||
*/
|
||||
|
||||
static byte *
|
||||
mrt_put_bgp4_hdr(byte *buf, struct bgp_conn *conn, int as4)
|
||||
{
|
||||
struct bgp_proto *p = conn->bgp;
|
||||
ip_addr local_addr;
|
||||
|
||||
if (as4)
|
||||
{
|
||||
put_u32(buf+0, p->remote_as);
|
||||
put_u32(buf+4, p->local_as);
|
||||
buf+=8;
|
||||
}
|
||||
else
|
||||
{
|
||||
put_u16(buf+0, (p->remote_as <= 0xFFFF) ? p->remote_as : AS_TRANS);
|
||||
put_u16(buf+2, (p->local_as <= 0xFFFF) ? p->local_as : AS_TRANS);
|
||||
buf+=4;
|
||||
}
|
||||
|
||||
put_u16(buf+0, p->neigh->iface->index);
|
||||
put_u16(buf+2, BGP_AF);
|
||||
buf+=4;
|
||||
buf = ipa_put_addr(buf, conn->sk ? conn->sk->daddr : IPA_NONE);
|
||||
buf = ipa_put_addr(buf, conn->sk ? conn->sk->saddr : IPA_NONE);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
mrt_dump_bgp_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
|
||||
{
|
||||
byte buf[BGP_MAX_PACKET_LENGTH + 128];
|
||||
byte *bp = buf + MRTDUMP_HDR_LENGTH;
|
||||
int as4 = conn->bgp->as4_session;
|
||||
|
||||
bp = mrt_put_bgp4_hdr(bp, conn, as4);
|
||||
memcpy(bp, pkt, len);
|
||||
bp += len;
|
||||
mrt_dump_message(&conn->bgp->p, BGP4MP, as4 ? BGP4MP_MESSAGE_AS4 : BGP4MP_MESSAGE,
|
||||
buf, bp-buf);
|
||||
}
|
||||
|
||||
static inline u16
|
||||
convert_state(unsigned state)
|
||||
{
|
||||
/* Convert state from our BS_* values to values used in MRTDump */
|
||||
return (state == BS_CLOSE) ? 1 : state + 1;
|
||||
}
|
||||
|
||||
void
|
||||
mrt_dump_bgp_state_change(struct bgp_conn *conn, unsigned old, unsigned new)
|
||||
{
|
||||
byte buf[128];
|
||||
byte *bp = buf + MRTDUMP_HDR_LENGTH;
|
||||
|
||||
bp = mrt_put_bgp4_hdr(bp, conn, 1);
|
||||
put_u16(bp+0, convert_state(old));
|
||||
put_u16(bp+2, convert_state(new));
|
||||
bp += 4;
|
||||
mrt_dump_message(&conn->bgp->p, BGP4MP, BGP4MP_STATE_CHANGE_AS4, buf, bp-buf);
|
||||
}
|
||||
|
||||
static byte *
|
||||
bgp_create_notification(struct bgp_conn *conn, byte *buf)
|
||||
{
|
||||
@ -403,13 +482,8 @@ bgp_create_route_refresh(struct bgp_conn *conn, byte *buf)
|
||||
struct bgp_proto *p = conn->bgp;
|
||||
BGP_TRACE(D_PACKETS, "Sending ROUTE-REFRESH");
|
||||
|
||||
#ifdef IPV6
|
||||
*buf++ = 0; /* AFI IPv6 */
|
||||
*buf++ = BGP_AF_IPV6;
|
||||
#else
|
||||
*buf++ = 0; /* AFI IPv4 */
|
||||
*buf++ = BGP_AF_IPV4;
|
||||
#endif
|
||||
*buf++ = 0;
|
||||
*buf++ = BGP_AF;
|
||||
*buf++ = 0; /* RFU */
|
||||
*buf++ = 1; /* and SAFI 1 */
|
||||
return buf;
|
||||
@ -552,12 +626,13 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
|
||||
|
||||
switch (opt[0])
|
||||
{
|
||||
case 2:
|
||||
case 2: /* Route refresh capability, RFC 2918 */
|
||||
if (cl != 0)
|
||||
goto err;
|
||||
conn->peer_refresh_support = 1;
|
||||
break;
|
||||
case 65:
|
||||
|
||||
case 65: /* AS4 capability, RFC 4893 */
|
||||
if (cl != 4)
|
||||
goto err;
|
||||
conn->peer_as4_support = 1;
|
||||
@ -709,7 +784,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
|
||||
|
||||
bgp_schedule_packet(conn, PKT_KEEPALIVE);
|
||||
bgp_start_timer(conn->hold_timer, conn->hold_time);
|
||||
conn->state = BS_OPENCONFIRM;
|
||||
bgp_conn_enter_openconfirm_state(conn);
|
||||
}
|
||||
|
||||
#define DECODE_PREFIX(pp, ll) do { \
|
||||
@ -1160,8 +1235,14 @@ bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, int len)
|
||||
static void
|
||||
bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
|
||||
{
|
||||
DBG("BGP: Got packet %02x (%d bytes)\n", pkt[18], len);
|
||||
switch (pkt[18])
|
||||
byte type = pkt[18];
|
||||
|
||||
DBG("BGP: Got packet %02x (%d bytes)\n", type, len);
|
||||
|
||||
if (conn->bgp->p.mrtdump & MD_MESSAGES)
|
||||
mrt_dump_bgp_packet(conn, pkt, len);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PKT_OPEN: return bgp_rx_open(conn, pkt, len);
|
||||
case PKT_UPDATE: return bgp_rx_update(conn, pkt, len);
|
||||
|
@ -152,9 +152,12 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
|
||||
if ((ifa->type != OSPF_IT_NBMA) && (ifa->ioprob == OSPF_I_OK) &&
|
||||
((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)))
|
||||
{
|
||||
/* FIXME some error handing ? */
|
||||
sk_join_group(ifa->sk, AllDRouters);
|
||||
ifa->dr_up = 1;
|
||||
if (!ifa->dr_up == 0)
|
||||
{
|
||||
/* FIXME some error handing ? */
|
||||
sk_join_group(ifa->sk, AllDRouters);
|
||||
ifa->dr_up = 1;
|
||||
}
|
||||
}
|
||||
else if (ifa->dr_up)
|
||||
{
|
||||
|
@ -623,9 +623,9 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
|
||||
if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_VLINK))
|
||||
pos = "ptp ";
|
||||
|
||||
cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-1I\t%-10s", n->rid, n->priority,
|
||||
ospf_ns[n->state], pos, etime, n->ip,
|
||||
(ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name));
|
||||
cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
|
||||
ospf_ns[n->state], pos, etime,
|
||||
(ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name), n->ip);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -917,8 +917,8 @@ ospf_sh_neigh(struct proto *p, char *iff)
|
||||
}
|
||||
|
||||
cli_msg(-1013, "%s:", p->name);
|
||||
cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-12s\t%-10s", "Router ID", "Pri",
|
||||
" State", "DTime", "Router IP", "Interface");
|
||||
cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-10s %-12s", "Router ID", "Pri",
|
||||
" State", "DTime", "Interface", "Router IP");
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
if ((iff == NULL) || patmatch(iff, ifa->iface->name))
|
||||
WALK_LIST(n, ifa->neigh_list)
|
||||
|
@ -433,9 +433,11 @@ originate_rt_lsa(struct ospf_area *oa)
|
||||
|
||||
#ifdef OSPFv2
|
||||
lsa.options = oa->options;
|
||||
#endif
|
||||
|
||||
lsa.id = po->router_id;
|
||||
#else /* OSPFv3 */
|
||||
lsa.id = 0;
|
||||
#endif
|
||||
|
||||
lsa.rt = po->router_id;
|
||||
lsa.sn = oa->rt ? (oa->rt->lsa.sn + 1) : LSA_INITSEQNO;
|
||||
u32 dom = oa->areaid;
|
||||
|
@ -63,6 +63,20 @@ log_cat:
|
||||
| BUG { $$ = L_BUG[0]; }
|
||||
;
|
||||
|
||||
|
||||
CF_ADDTO(conf, mrtdump_base)
|
||||
|
||||
mrtdump_base:
|
||||
MRTDUMP PROTOCOLS mrtdump_mask ';' { new_config->proto_default_mrtdump = $3; }
|
||||
| MRTDUMP TEXT ';' {
|
||||
FILE *f = tracked_fopen(new_config->pool, $2, "a");
|
||||
if (!f) cf_error("Unable to open MRTDump file '%s': %m", $2);
|
||||
new_config->mrtdump_file = fileno(f);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
|
||||
/* Unix specific commands */
|
||||
|
||||
CF_CLI_HELP(CONFIGURE, [soft] [\"<file>\"], [[Reload configuration]])
|
||||
|
@ -947,7 +947,14 @@ sk_passive_connected(sock *s, struct sockaddr *sa, int al, int type)
|
||||
t->rbsize = s->rbsize;
|
||||
t->tbsize = s->tbsize;
|
||||
if (type == SK_TCP)
|
||||
get_sockaddr((sockaddr *) sa, &t->daddr, &t->dport, 1);
|
||||
{
|
||||
sockaddr lsa;
|
||||
int lsa_len = sizeof(lsa);
|
||||
if (getsockname(fd, (struct sockaddr *) &lsa, &lsa_len) == 0)
|
||||
get_sockaddr(&lsa, &t->saddr, &t->sport, 1);
|
||||
|
||||
get_sockaddr((sockaddr *) sa, &t->daddr, &t->dport, 1);
|
||||
}
|
||||
sk_insert(t);
|
||||
if (err = sk_setup(t))
|
||||
{
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "nest/cli.h"
|
||||
#include "nest/mrtdump.h"
|
||||
#include "lib/string.h"
|
||||
#include "lib/lists.h"
|
||||
#include "lib/unix.h"
|
||||
@ -261,3 +262,16 @@ log_init_debug(char *f)
|
||||
if (dbgf)
|
||||
setvbuf(dbgf, NULL, _IONBF, 0);
|
||||
}
|
||||
|
||||
void
|
||||
mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len)
|
||||
{
|
||||
/* Prepare header */
|
||||
put_u32(buf+0, now_real);
|
||||
put_u16(buf+4, type);
|
||||
put_u16(buf+6, subtype);
|
||||
put_u32(buf+8, len - MRTDUMP_HDR_LENGTH);
|
||||
|
||||
if (p->cf->global->mrtdump_file != -1)
|
||||
write(p->cf->global->mrtdump_file, buf, len);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user