From cf31112f0d7618464097f71228f84bd534f1bc0f Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Sun, 3 Jan 2010 12:17:52 +0100 Subject: [PATCH] Implements MRTdump feature. --- conf/conf.c | 1 + conf/conf.h | 5 +- doc/bird.sgml | 26 ++++++++++- lib/ipv4.h | 7 +++ lib/ipv6.h | 11 +++++ nest/config.Y | 36 +++++++++++++-- nest/mrtdump.h | 27 +++++++++++ nest/proto.c | 10 +++- nest/protocol.h | 15 ++++-- proto/bgp/bgp.c | 29 +++++++++--- proto/bgp/bgp.h | 8 ++++ proto/bgp/packets.c | 105 +++++++++++++++++++++++++++++++++++++----- proto/ospf/iface.c | 9 ++-- proto/ospf/neighbor.c | 6 +-- proto/ospf/ospf.c | 4 +- proto/ospf/topology.c | 6 ++- sysdep/unix/config.Y | 14 ++++++ sysdep/unix/io.c | 9 +++- sysdep/unix/log.c | 14 ++++++ 19 files changed, 300 insertions(+), 42 deletions(-) create mode 100644 nest/mrtdump.h diff --git a/conf/conf.c b/conf/conf.c index eeffd4a8..7ffe8d13 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -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); diff --git a/conf/conf.h b/conf/conf.h index 951dde3c..f8ab7131 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -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 */ diff --git a/doc/bird.sgml b/doc/bird.sgml index 53d87b6b..0eb476d5 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -238,6 +238,14 @@ protocol rip { logging of connects and disconnects, 2 and higher for logging of all client commands). Default: 0. + mrtdump " + Set MRTdump file name. This option must be specified to allow MRTdump feature. + Default: no dump file. + + mrtdump protocols all|off|{ states, messages } + Set global defaults of MRTdump options. See filter Define a filter. You can learn more about filters in the following chapter. @@ -301,8 +309,22 @@ to zero to disable it. An empty is equivalent to router id This option can be used to override global - router id for a given protocol. Default: uses global router id. + mrtdump all|off|{ states, messages } + + 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 router id This option can be used + to override global router id for a given protocol. Default: + uses global router id. import all | none | filter Specify a filter to be used for filtering routes coming from the protocol to the routing table. > (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 diff --git a/lib/ipv6.h b/lib/ipv6.h index 53888ff0..e15c57af 100644 --- a/lib/ipv6.h +++ b/lib/ipv6.h @@ -14,6 +14,7 @@ #include #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 diff --git a/nest/config.Y b/nest/config.Y index dbb10ada..11f0a9b2 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -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 rtable %type optsym %type r_args -%type echo_mask echo_size debug_mask debug_list debug_flag export_or_preexport +%type echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport %type 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, | \"\" | all, [[Reload protoco CF_CLI(RELOAD OUT, proto_patt, | \"\" | 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, ( | | 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, ( | | 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, ( | | all) (all | off | { states | messages }), [[Control protocol debugging via MRTdump format]]) +{ proto_debug($2, 1, $3); } ; proto_patt: diff --git a/nest/mrtdump.h b/nest/mrtdump.h new file mode 100644 index 00000000..8638804a --- /dev/null +++ b/nest/mrtdump.h @@ -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 + diff --git a/nest/proto.c b/nest/proto.c index 4f352a6f..9f0311f6 100644 --- a/nest/proto.c +++ b/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) diff --git a/nest/protocol.h b/nest/protocol.h index 21a1c1b4..5a69b33b 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -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 */ diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 3cbcb6d7..215dc817 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -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); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 7cbd6557..24d69741 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -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 diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 91b47927..03cc4ee0 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -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); diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 8db086ec..e514a5d5 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -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) { diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index ba8d7b98..0411d48e 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -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 diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 9ebef6b7..232803d7 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -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) diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 3ca5e774..870c0bc2 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -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; diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y index 1917fe68..46c5862b 100644 --- a/sysdep/unix/config.Y +++ b/sysdep/unix/config.Y @@ -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] [\"\"], [[Reload configuration]]) diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index cd5c5db7..74612acd 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -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)) { diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c index eb083099..dad0c5db 100644 --- a/sysdep/unix/log.c +++ b/sysdep/unix/log.c @@ -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); +}