Commit cf31112f authored by Ondřej Zajíček's avatar Ondřej Zajíček

Implements MRTdump feature.

parent 610bb3cf
......@@ -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
......
......@@ -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:
......
/*
* 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
......@@ -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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment