Implements MRTdump feature.

This commit is contained in:
Ondrej Zajicek 2010-01-03 12:17:52 +01:00
parent 610bb3cff0
commit cf31112f0d
19 changed files with 300 additions and 42 deletions

View file

@ -75,6 +75,7 @@ config_alloc(byte *name)
linpool *l = lp_new(p, 4080); linpool *l = lp_new(p, 4080);
struct config *c = lp_allocz(l, sizeof(struct config)); struct config *c = lp_allocz(l, sizeof(struct config));
c->mrtdump_file = -1; /* Hack, this should be sysdep-specific */
c->pool = p; c->pool = p;
cfg_mem = c->mem = l; cfg_mem = c->mem = l;
c->file_name = cfg_strdup(name); c->file_name = cfg_strdup(name);

View file

@ -20,12 +20,15 @@ struct config {
list protos; /* Configured protocol instances (struct proto_config) */ list protos; /* Configured protocol instances (struct proto_config) */
list tables; /* Configured routing tables (struct rtable_config) */ list tables; /* Configured routing tables (struct rtable_config) */
list logfiles; /* Configured log fils (sysdep) */ 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 */ struct rtable_config *master_rtc; /* Configuration of master routing table */
u32 router_id; /* Our Router ID */ u32 router_id; /* Our Router ID */
ip_addr listen_bgp_addr; /* Listening BGP socket should use this address */ 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) */ 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 */ 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 */ int cli_debug; /* Tracing of CLI connections and commands */
char *err_msg; /* Parser error message */ char *err_msg; /* Parser error message */
int err_lino; /* Line containing error */ int err_lino; /* Line containing error */

View file

@ -238,6 +238,14 @@ protocol rip {
logging of connects and disconnects, 2 and higher for logging of logging of connects and disconnects, 2 and higher for logging of
all client commands). Default: 0. 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 <tag>filter <m/name local variables/{ <m/commands/ }</tag> Define a filter. You can learn more about filters
in the following chapter. 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/events/ for events internal to the protocol and
<cf/packets/ for packets sent and received by the protocol. Default: off. <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 <tag>mrtdump all|off|{ states, messages }</tag>
router id for a given protocol. Default: uses global router id.
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> <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/. 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/.

View file

@ -11,6 +11,7 @@
#include "lib/endian.h" #include "lib/endian.h"
#include "lib/bitops.h" #include "lib/bitops.h"
#include "lib/unaligned.h"
#ifdef DEBUGGING #ifdef DEBUGGING
@ -63,6 +64,7 @@ typedef u32 ip_addr;
/* ipa_pxlen() requires that x != y */ /* ipa_pxlen() requires that x != y */
#define ipa_pxlen(x, y) ipv4_pxlen(_I(x), _I(y)) #define ipa_pxlen(x, y) ipv4_pxlen(_I(x), _I(y))
#define ipa_getbit(x, y) (_I(x) & (0x80000000 >> (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) #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); 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 #define IP_PREC_INTERNET_CONTROL 0xc0

View file

@ -14,6 +14,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include "lib/string.h" #include "lib/string.h"
#include "lib/bitops.h" #include "lib/bitops.h"
#include "lib/unaligned.h"
typedef struct ipv6_addr { typedef struct ipv6_addr {
u32 addr[4]; u32 addr[4];
@ -68,6 +69,7 @@ typedef struct ipv6_addr {
/* ipa_pxlen() requires that x != y */ /* ipa_pxlen() requires that x != y */
#define ipa_pxlen(x, y) ipv6_pxlen(x, y) #define ipa_pxlen(x, y) ipv6_pxlen(x, y)
#define ipa_getbit(x, y) ipv6_getbit(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) #define ipa_absolutize(x,y) ipv6_absolutize(x,y)
/* In IPv6, SOCK_RAW does not return packet header */ /* 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]); 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 * RFC 1883 defines packet precendece, but RFC 2460 replaces it
* by generic Traffic Class ID with no defined semantics. Better * by generic Traffic Class ID with no defined semantics. Better

View file

@ -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(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE) CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE)
CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION) 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, CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE) 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 <r> rtable
%type <s> optsym %type <s> optsym
%type <ra> r_args %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 %type <t> proto_patt
CF_GRAMMAR CF_GRAMMAR
@ -138,6 +138,7 @@ proto_item:
} }
| DISABLED bool { this_proto->disabled = $2; } | DISABLED bool { this_proto->disabled = $2; }
| DEBUG debug_mask { this_proto->debug = $2; } | DEBUG debug_mask { this_proto->debug = $2; }
| MRTDUMP mrtdump_mask { this_proto->mrtdump = $2; }
| IMPORT imexport { this_proto->in_filter = $2; } | IMPORT imexport { this_proto->in_filter = $2; }
| EXPORT imexport { this_proto->out_filter = $2; } | EXPORT imexport { this_proto->out_filter = $2; }
| TABLE rtable { this_proto->table = $2; } | TABLE rtable { this_proto->table = $2; }
@ -166,6 +167,8 @@ debug_default:
| DEBUG COMMANDS expr { new_config->cli_debug = $3; } | DEBUG COMMANDS expr { new_config->cli_debug = $3; }
; ;
/* MRTDUMP PROTOCOLS is in systep/unix/config.Y */
/* Interface patterns */ /* Interface patterns */
iface_patt_node_init: iface_patt_node_init:
@ -251,6 +254,24 @@ debug_flag:
| PACKETS { $$ = D_PACKETS; } | 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 lists */
password_list: 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)]]) CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]])
{ proto_xxable($3, XX_RELOAD_OUT); } ; { proto_xxable($3, XX_RELOAD_OUT); } ;
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging]]) 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]]) 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, $3); } { 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: proto_patt:

27
nest/mrtdump.h Normal file
View 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

View file

@ -111,6 +111,7 @@ proto_new(struct proto_config *c, unsigned size)
p->cf = c; p->cf = c;
p->debug = c->debug; p->debug = c->debug;
p->mrtdump = c->mrtdump;
p->name = c->name; p->name = c->name;
p->preference = c->preference; p->preference = c->preference;
p->disabled = c->disabled; p->disabled = c->disabled;
@ -201,6 +202,7 @@ proto_config_new(struct protocol *pr, unsigned size)
c->out_filter = FILTER_REJECT; c->out_filter = FILTER_REJECT;
c->table = c->global->master_rtc; c->table = c->global->master_rtc;
c->debug = new_config->proto_default_debug; c->debug = new_config->proto_default_debug;
c->mrtdump = new_config->proto_default_mrtdump;
return c; 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 */ /* Generic attributes match, try converting them and then ask the protocol */
p->debug = nc->debug; p->debug = nc->debug;
p->mrtdump = nc->mrtdump;
if (p->proto->reconfigure && p->proto->reconfigure(p, nc)) if (p->proto->reconfigure && p->proto->reconfigure(p, nc))
{ {
DBG("\t%s: same\n", oc->name); DBG("\t%s: same\n", oc->name);
@ -901,14 +904,17 @@ proto_xxable(char *pattern, int xx)
} }
void void
proto_debug(char *pattern, unsigned int mask) proto_debug(char *pattern, int which, unsigned int mask)
{ {
int cnt = 0; int cnt = 0;
WALK_PROTO_LIST(p) WALK_PROTO_LIST(p)
if (patmatch(pattern, p->name)) if (patmatch(pattern, p->name))
{ {
cnt++; cnt++;
if (which == 0)
p->debug = mask; p->debug = mask;
else
p->mrtdump = mask;
} }
WALK_PROTO_LIST_END; WALK_PROTO_LIST_END;
if (!cnt) if (!cnt)

View file

@ -82,7 +82,8 @@ struct proto_config {
struct proto *proto; /* Instance we've created */ struct proto *proto; /* Instance we've created */
char *name; char *name;
char *dsc; 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 */ u32 router_id; /* Protocol specific router ID */
struct rtable_config *table; /* Table we're attached to */ struct rtable_config *table; /* Table we're attached to */
struct filter *in_filter, *out_filter; /* Attached filters */ struct filter *in_filter, *out_filter; /* Attached filters */
@ -125,7 +126,8 @@ struct proto {
struct event *attn; /* "Pay attention" event */ struct event *attn; /* "Pay attention" event */
char *name; /* Name of this instance (== cf->name) */ 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 */ unsigned preference; /* Default route preference */
int min_scope; /* Minimal route scope accepted */ int min_scope; /* Minimal route scope accepted */
unsigned accept_ra_types; /* Which types of route announcements are accepted (RA_OPTIMAL or RA_ANY) */ 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); void proto_show(struct symbol *, int);
struct proto *proto_get_named(struct symbol *, struct protocol *); struct proto *proto_get_named(struct symbol *, struct protocol *);
void proto_xxable(char *, int); void proto_xxable(char *, int);
void proto_debug(char *, unsigned int); void proto_debug(char *, int, unsigned int);
#define XX_DISABLE 0 #define XX_DISABLE 0
#define XX_ENABLE 1 #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_EVENTS 16 /* Protocol events */
#define D_PACKETS 32 /* Packets sent/received */ #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 * Known unique protocol instances as referenced by config routines
*/ */

View file

@ -313,6 +313,22 @@ bgp_stop(struct bgp_proto *p, unsigned subcode)
ev_schedule(p->event); 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 void
bgp_conn_enter_established_state(struct bgp_conn *conn) 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_class = 0;
p->last_error_code = 0; p->last_error_code = 0;
bgp_attr_init(conn->bgp); bgp_attr_init(conn->bgp);
conn->state = BS_ESTABLISHED; bgp_conn_set_state(conn, BS_ESTABLISHED);
proto_notify_state(&p->p, PS_UP); 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; struct bgp_proto *p = conn->bgp;
int os = conn->state; int os = conn->state;
conn->state = BS_CLOSE; bgp_conn_set_state(conn, BS_CLOSE);
tm_stop(conn->hold_timer); tm_stop(conn->hold_timer);
tm_stop(conn->keepalive_timer); tm_stop(conn->keepalive_timer);
conn->sk->rx_hook = NULL; conn->sk->rx_hook = NULL;
@ -361,7 +377,7 @@ bgp_conn_enter_idle_state(struct bgp_conn *conn)
int os = conn->state; int os = conn->state;
bgp_close_conn(conn); bgp_close_conn(conn);
conn->state = BS_IDLE; bgp_conn_set_state(conn, BS_IDLE);
ev_schedule(p->event); ev_schedule(p->event);
if (os == BS_ESTABLISHED) if (os == BS_ESTABLISHED)
@ -374,13 +390,14 @@ bgp_send_open(struct bgp_conn *conn)
conn->start_state = conn->bgp->start_state; conn->start_state = conn->bgp->start_state;
conn->want_as4_support = conn->bgp->cf->enable_as4 && (conn->start_state != BSS_CONNECT_NOCAP); 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->peer_as4_support = 0; // Default value, possibly changed by receiving capability.
conn->advertised_as = 0;
DBG("BGP: Sending open\n"); DBG("BGP: Sending open\n");
conn->sk->rx_hook = bgp_rx; conn->sk->rx_hook = bgp_rx;
conn->sk->tx_hook = bgp_tx; conn->sk->tx_hook = bgp_tx;
tm_stop(conn->connect_retry_timer); tm_stop(conn->connect_retry_timer);
bgp_schedule_packet(conn, PKT_OPEN); 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); 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_TRACE(D_EVENTS, "Connect delayed by %d seconds", delay);
bgp_setup_conn(p, conn); bgp_setup_conn(p, conn);
conn->state = BS_ACTIVE; bgp_conn_set_state(conn, BS_ACTIVE);
bgp_start_timer(conn->connect_retry_timer, delay); 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_TRACE(D_EVENTS, "Connecting to %I from local address %I", s->daddr, s->saddr);
bgp_setup_conn(p, conn); bgp_setup_conn(p, conn);
bgp_setup_sk(p, conn, s); bgp_setup_sk(p, conn, s);
conn->state = BS_CONNECT; bgp_conn_set_state(conn, BS_CONNECT);
if (sk_open(s)) if (sk_open(s))
{ {
bgp_sock_err(s, 0); bgp_sock_err(s, 0);

View file

@ -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_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len);
void bgp_close_conn(struct bgp_conn *c); void bgp_close_conn(struct bgp_conn *c);
void bgp_update_startup_delay(struct bgp_proto *p); 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_established_state(struct bgp_conn *conn);
void bgp_conn_enter_close_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); 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 */ /* 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_schedule_packet(struct bgp_conn *conn, int type);
void bgp_kick_tx(void *vconn); void bgp_kick_tx(void *vconn);
void bgp_tx(struct birdsock *sk); 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_IPV4 1
#define BGP_AF_IPV6 2 #define BGP_AF_IPV6 2
#ifdef IPV6
#define BGP_AF BGP_AF_IPV6
#else
#define BGP_AF BGP_AF_IPV4
#endif
#endif #endif

View file

@ -13,6 +13,7 @@
#include "nest/protocol.h" #include "nest/protocol.h"
#include "nest/route.h" #include "nest/route.h"
#include "nest/attrs.h" #include "nest/attrs.h"
#include "nest/mrtdump.h"
#include "conf/conf.h" #include "conf/conf.h"
#include "lib/unaligned.h" #include "lib/unaligned.h"
#include "lib/socket.h" #include "lib/socket.h"
@ -23,6 +24,84 @@
static struct rate_limit rl_rcv_update, rl_snd_update; 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 * static byte *
bgp_create_notification(struct bgp_conn *conn, byte *buf) 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; struct bgp_proto *p = conn->bgp;
BGP_TRACE(D_PACKETS, "Sending ROUTE-REFRESH"); BGP_TRACE(D_PACKETS, "Sending ROUTE-REFRESH");
#ifdef IPV6 *buf++ = 0;
*buf++ = 0; /* AFI IPv6 */ *buf++ = BGP_AF;
*buf++ = BGP_AF_IPV6;
#else
*buf++ = 0; /* AFI IPv4 */
*buf++ = BGP_AF_IPV4;
#endif
*buf++ = 0; /* RFU */ *buf++ = 0; /* RFU */
*buf++ = 1; /* and SAFI 1 */ *buf++ = 1; /* and SAFI 1 */
return buf; return buf;
@ -552,12 +626,13 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
switch (opt[0]) switch (opt[0])
{ {
case 2: case 2: /* Route refresh capability, RFC 2918 */
if (cl != 0) if (cl != 0)
goto err; goto err;
conn->peer_refresh_support = 1; conn->peer_refresh_support = 1;
break; break;
case 65:
case 65: /* AS4 capability, RFC 4893 */
if (cl != 4) if (cl != 4)
goto err; goto err;
conn->peer_as4_support = 1; 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_schedule_packet(conn, PKT_KEEPALIVE);
bgp_start_timer(conn->hold_timer, conn->hold_time); 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 { \ #define DECODE_PREFIX(pp, ll) do { \
@ -1160,8 +1235,14 @@ bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, int len)
static void static void
bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len) bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
{ {
DBG("BGP: Got packet %02x (%d bytes)\n", pkt[18], len); byte type = pkt[18];
switch (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_OPEN: return bgp_rx_open(conn, pkt, len);
case PKT_UPDATE: return bgp_rx_update(conn, pkt, len); case PKT_UPDATE: return bgp_rx_update(conn, pkt, len);

View file

@ -151,11 +151,14 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
{ {
if ((ifa->type != OSPF_IT_NBMA) && (ifa->ioprob == OSPF_I_OK) && if ((ifa->type != OSPF_IT_NBMA) && (ifa->ioprob == OSPF_I_OK) &&
((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))) ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)))
{
if (!ifa->dr_up == 0)
{ {
/* FIXME some error handing ? */ /* FIXME some error handing ? */
sk_join_group(ifa->sk, AllDRouters); sk_join_group(ifa->sk, AllDRouters);
ifa->dr_up = 1; ifa->dr_up = 1;
} }
}
else if (ifa->dr_up) else if (ifa->dr_up)
{ {
sk_leave_group(ifa->sk, AllDRouters); sk_leave_group(ifa->sk, AllDRouters);

View file

@ -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)) if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_VLINK))
pos = "ptp "; pos = "ptp ";
cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-1I\t%-10s", n->rid, n->priority, cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
ospf_ns[n->state], pos, etime, n->ip, ospf_ns[n->state], pos, etime,
(ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name)); (ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name), n->ip);
} }
static void static void

View file

@ -917,8 +917,8 @@ ospf_sh_neigh(struct proto *p, char *iff)
} }
cli_msg(-1013, "%s:", p->name); cli_msg(-1013, "%s:", p->name);
cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-12s\t%-10s", "Router ID", "Pri", cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-10s %-12s", "Router ID", "Pri",
" State", "DTime", "Router IP", "Interface"); " State", "DTime", "Interface", "Router IP");
WALK_LIST(ifa, po->iface_list) WALK_LIST(ifa, po->iface_list)
if ((iff == NULL) || patmatch(iff, ifa->iface->name)) if ((iff == NULL) || patmatch(iff, ifa->iface->name))
WALK_LIST(n, ifa->neigh_list) WALK_LIST(n, ifa->neigh_list)

View file

@ -433,9 +433,11 @@ originate_rt_lsa(struct ospf_area *oa)
#ifdef OSPFv2 #ifdef OSPFv2
lsa.options = oa->options; lsa.options = oa->options;
lsa.id = po->router_id;
#else /* OSPFv3 */
lsa.id = 0;
#endif #endif
lsa.id = po->router_id;
lsa.rt = po->router_id; lsa.rt = po->router_id;
lsa.sn = oa->rt ? (oa->rt->lsa.sn + 1) : LSA_INITSEQNO; lsa.sn = oa->rt ? (oa->rt->lsa.sn + 1) : LSA_INITSEQNO;
u32 dom = oa->areaid; u32 dom = oa->areaid;

View file

@ -63,6 +63,20 @@ log_cat:
| BUG { $$ = L_BUG[0]; } | 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 */ /* Unix specific commands */
CF_CLI_HELP(CONFIGURE, [soft] [\"<file>\"], [[Reload configuration]]) CF_CLI_HELP(CONFIGURE, [soft] [\"<file>\"], [[Reload configuration]])

View file

@ -947,7 +947,14 @@ sk_passive_connected(sock *s, struct sockaddr *sa, int al, int type)
t->rbsize = s->rbsize; t->rbsize = s->rbsize;
t->tbsize = s->tbsize; t->tbsize = s->tbsize;
if (type == SK_TCP) if (type == SK_TCP)
{
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); get_sockaddr((sockaddr *) sa, &t->daddr, &t->dport, 1);
}
sk_insert(t); sk_insert(t);
if (err = sk_setup(t)) if (err = sk_setup(t))
{ {

View file

@ -22,6 +22,7 @@
#include "nest/bird.h" #include "nest/bird.h"
#include "nest/cli.h" #include "nest/cli.h"
#include "nest/mrtdump.h"
#include "lib/string.h" #include "lib/string.h"
#include "lib/lists.h" #include "lib/lists.h"
#include "lib/unix.h" #include "lib/unix.h"
@ -261,3 +262,16 @@ log_init_debug(char *f)
if (dbgf) if (dbgf)
setvbuf(dbgf, NULL, _IONBF, 0); 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);
}