mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-01-03 07:31:54 +00:00
Merge branch 'maarten' into mq-ordered
This commit is contained in:
commit
c217fe593a
@ -1094,8 +1094,10 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
|
||||
ADVANCE(pos, len, alen);
|
||||
}
|
||||
|
||||
#define FAIL(KEY) ({ STATS(KEY); goto fail; })
|
||||
|
||||
if (s->err_withdraw)
|
||||
goto withdraw;
|
||||
FAIL(bad_attribute);
|
||||
|
||||
/* If there is no reachability NLRI, we are finished */
|
||||
if (!s->ip_reach_len && !s->mp_reach_len)
|
||||
@ -1104,10 +1106,10 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
|
||||
|
||||
/* Handle missing mandatory attributes; RFC 7606 3 (d) */
|
||||
if (!BIT32_TEST(s->attrs_seen, BA_ORIGIN))
|
||||
{ REPORT(NO_MANDATORY, "ORIGIN"); goto withdraw; }
|
||||
{ REPORT(NO_MANDATORY, "ORIGIN"); FAIL(no_mandatory); }
|
||||
|
||||
if (!BIT32_TEST(s->attrs_seen, BA_AS_PATH))
|
||||
{ REPORT(NO_MANDATORY, "AS_PATH"); goto withdraw; }
|
||||
{ REPORT(NO_MANDATORY, "AS_PATH"); FAIL(no_mandatory); }
|
||||
|
||||
/* When receiving attributes from non-AS4-aware BGP speaker, we have to
|
||||
reconstruct AS_PATH and AGGREGATOR attributes; RFC 6793 4.2.3 */
|
||||
@ -1116,19 +1118,19 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
|
||||
|
||||
/* Reject routes with our ASN in AS_PATH attribute */
|
||||
if (bgp_as_path_loopy(p, attrs, p->local_as))
|
||||
goto withdraw;
|
||||
FAIL(loopy);
|
||||
|
||||
/* Reject routes with our Confederation ID in AS_PATH attribute; RFC 5065 4.0 */
|
||||
if ((p->public_as != p->local_as) && bgp_as_path_loopy(p, attrs, p->public_as))
|
||||
goto withdraw;
|
||||
FAIL(loopy);
|
||||
|
||||
/* Reject routes with our Router ID in ORIGINATOR_ID attribute; RFC 4456 8 */
|
||||
if (p->is_internal && bgp_originator_id_loopy(p, attrs))
|
||||
goto withdraw;
|
||||
FAIL(loopy);
|
||||
|
||||
/* Reject routes with our Cluster ID in CLUSTER_LIST attribute; RFC 4456 8 */
|
||||
if (p->rr_client && bgp_cluster_list_loopy(p, attrs))
|
||||
goto withdraw;
|
||||
FAIL(loopy);
|
||||
|
||||
/* If there is no local preference, define one */
|
||||
if (!BIT32_TEST(s->attrs_seen, BA_LOCAL_PREF))
|
||||
@ -1141,8 +1143,11 @@ framing_error:
|
||||
/* RFC 7606 4 - handle attribute framing errors */
|
||||
REPORT("Malformed attribute list - framing error (%u/%u) at %d",
|
||||
alen, len, (int) (pos - s->attrs));
|
||||
FAIL(bad_alist);
|
||||
|
||||
withdraw:
|
||||
#undef FAIL
|
||||
|
||||
fail:
|
||||
/* RFC 7606 5.2 - handle missing NLRI during errors */
|
||||
if (!s->ip_reach_len && !s->mp_reach_len)
|
||||
bgp_parse_error(s, 1);
|
||||
@ -2009,11 +2014,13 @@ bgp_get_attr(eattr *a, byte *buf, int buflen)
|
||||
void
|
||||
bgp_get_route_info(rte *e, byte *buf, ea_list *attrs)
|
||||
{
|
||||
struct bgp_proto *bgp = (void *) e->attrs->src->proto;
|
||||
eattr *p = ea_find(attrs, EA_CODE(EAP_BGP, BA_AS_PATH));
|
||||
eattr *o = ea_find(attrs, EA_CODE(EAP_BGP, BA_ORIGIN));
|
||||
u32 origas;
|
||||
|
||||
buf += bsprintf(buf, " (%d", e->pref);
|
||||
char c = bgp->is_internal ? 'I' : (bgp->is_interior ? 'C' : 'E');
|
||||
buf += bsprintf(buf, " %c (%d", c, e->pref);
|
||||
|
||||
if (e->u.bgp.suppressed)
|
||||
buf += bsprintf(buf, "-");
|
||||
|
@ -1328,6 +1328,8 @@ bgp_start(struct proto *P)
|
||||
p->source_addr = p->cf->local_ip;
|
||||
p->link_addr = IPA_NONE;
|
||||
|
||||
memset(&(p->stats), 0, sizeof(struct bgp_stats));
|
||||
|
||||
/* Lock all channels when in GR recovery mode */
|
||||
if (p->p.gr_recovery && p->cf->gr_mode)
|
||||
{
|
||||
@ -2104,6 +2106,15 @@ bgp_show_proto_info(struct proto *P)
|
||||
tm_remains(p->conn->keepalive_timer), p->conn->keepalive_time);
|
||||
}
|
||||
|
||||
struct bgp_stats *s = &p->stats;
|
||||
cli_msg(-1006, " Statistics:");
|
||||
cli_msg(-1006, " rx-open %u rx-update %u rx-notify %u rx-keepalive %u rx-refresh %u",
|
||||
s->rx_pkts[0], s->rx_pkts[1], s->rx_pkts[2], s->rx_pkts[3], s->rx_pkts[4]);
|
||||
cli_msg(-1006, " tx-open %u tx-update %u tx-notify %u tx-keepalive %u tx-refresh %u",
|
||||
s->tx_pkts[0], s->tx_pkts[1], s->tx_pkts[2], s->tx_pkts[3], s->tx_pkts[4]);
|
||||
cli_msg(-1006, " bad-alist %u bad-attribute %u bad-next-hop %u no-mandatory %u loopy %u",
|
||||
s->bad_alist, s->bad_attribute, s->bad_next_hop, s->no_mandatory, s->loopy);
|
||||
|
||||
if ((p->last_error_class != BE_NONE) &&
|
||||
(p->last_error_class != BE_MAN_DOWN))
|
||||
{
|
||||
@ -2120,6 +2131,9 @@ bgp_show_proto_info(struct proto *P)
|
||||
|
||||
if (c->c.channel_state == CS_UP)
|
||||
{
|
||||
cli_msg(-1006, " Enqueued updates: %u", c->bucket_hash.count);
|
||||
cli_msg(-1006, " Enqueued prefixes: %u", c->prefix_hash.count);
|
||||
|
||||
if (ipa_zero(c->link_addr))
|
||||
cli_msg(-1006, " BGP Next hop: %I", c->next_hop_addr);
|
||||
else
|
||||
|
@ -55,6 +55,8 @@ struct eattr;
|
||||
#define BGP_AF_FLOW4 BGP_AF( BGP_AFI_IPV4, BGP_SAFI_FLOW )
|
||||
#define BGP_AF_FLOW6 BGP_AF( BGP_AFI_IPV6, BGP_SAFI_FLOW )
|
||||
|
||||
#define BGP_PKT_TYPES 5 /* PKT_OPEN .. PKT_ROUTE_REFRESH */
|
||||
|
||||
|
||||
struct bgp_write_state;
|
||||
struct bgp_parse_state;
|
||||
@ -196,6 +198,14 @@ struct bgp_caps {
|
||||
#define WALK_AF_CAPS(caps,ac) \
|
||||
for (ac = caps->af_data; ac < &caps->af_data[caps->af_count]; ac++)
|
||||
|
||||
struct bgp_stats {
|
||||
uint rx_pkts[BGP_PKT_TYPES], tx_pkts[BGP_PKT_TYPES];
|
||||
uint bad_alist, bad_attribute, bad_next_hop, no_mandatory, loopy;
|
||||
};
|
||||
|
||||
#ifndef PARSER
|
||||
#define STATS(KEY) ({ p->stats.KEY++; })
|
||||
#endif
|
||||
|
||||
struct bgp_socket {
|
||||
node n; /* Node in global bgp_sockets */
|
||||
@ -254,6 +264,7 @@ struct bgp_proto {
|
||||
struct neighbor *neigh; /* Neighbor entry corresponding to remote ip, NULL if multihop */
|
||||
struct bgp_socket *sock; /* Shared listening socket */
|
||||
struct bfd_request *bfd_req; /* BFD request, if BFD is used */
|
||||
struct bgp_stats stats; /* Packet statistics */
|
||||
ip_addr source_addr; /* Local address used as an advertised next hop */
|
||||
ip_addr link_addr; /* Link-local version of source_addr */
|
||||
event *event; /* Event for respawning and shutting process */
|
||||
|
@ -2174,6 +2174,7 @@ bgp_rx_end_mark(struct bgp_parse_state *s, u32 afi)
|
||||
static inline void
|
||||
bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_list *ea, byte *nh, uint nh_len)
|
||||
{
|
||||
struct bgp_proto *p = s->proto;
|
||||
struct bgp_channel *c = bgp_get_channel(s->proto, afi);
|
||||
rta *a = NULL;
|
||||
|
||||
@ -2207,7 +2208,10 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
|
||||
|
||||
/* Handle withdraw during next hop decoding */
|
||||
if (s->err_withdraw)
|
||||
{
|
||||
STATS(bad_next_hop);
|
||||
a = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
c->desc->decode_nlri(s, nlri, len, a);
|
||||
@ -2446,6 +2450,7 @@ found:
|
||||
static inline int
|
||||
bgp_send(struct bgp_conn *conn, uint type, uint len)
|
||||
{
|
||||
struct bgp_proto *p = conn->bgp;
|
||||
sock *sk = conn->sk;
|
||||
byte *buf = sk->tbuf;
|
||||
|
||||
@ -2453,6 +2458,7 @@ bgp_send(struct bgp_conn *conn, uint type, uint len)
|
||||
put_u16(buf+16, len);
|
||||
buf[18] = type;
|
||||
|
||||
STATS(tx_pkts[type - 1]);
|
||||
return sk_send(sk, len);
|
||||
}
|
||||
|
||||
@ -2812,13 +2818,22 @@ bgp_rx_keepalive(struct bgp_conn *conn)
|
||||
static void
|
||||
bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
|
||||
{
|
||||
struct bgp_proto *p = conn->bgp;
|
||||
byte type = pkt[18];
|
||||
|
||||
DBG("BGP: Got packet %02x (%d bytes)\n", type, len);
|
||||
|
||||
if (conn->bgp->p.mrtdump & MD_MESSAGES)
|
||||
if (p->p.mrtdump & MD_MESSAGES)
|
||||
mrt_dump_bgp_packet(conn, pkt, len);
|
||||
|
||||
if (type < PKT_OPEN || type > PKT_ROUTE_REFRESH)
|
||||
{
|
||||
bgp_error(conn, 1, 3, pkt+18, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
STATS(rx_pkts[type - 1]);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PKT_OPEN: return bgp_rx_open(conn, pkt, len);
|
||||
@ -2826,7 +2841,6 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
|
||||
case PKT_NOTIFICATION: return bgp_rx_notification(conn, pkt, len);
|
||||
case PKT_KEEPALIVE: return bgp_rx_keepalive(conn);
|
||||
case PKT_ROUTE_REFRESH: return bgp_rx_route_refresh(conn, pkt, len);
|
||||
default: bgp_error(conn, 1, 3, pkt+18, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,6 +135,8 @@ stat_route:
|
||||
|
||||
stat_route_item:
|
||||
cmd { *this_srt_last_cmd = $1; this_srt_last_cmd = &($1->next); }
|
||||
| PREFERENCE expr ';' { this_srt->preference = $2; check_u16($2); }
|
||||
| DISTANCE expr ';' { this_srt->preference = $2; check_u16($2); }
|
||||
;
|
||||
|
||||
stat_route_opts:
|
||||
|
@ -53,7 +53,7 @@ static void
|
||||
static_announce_rte(struct static_proto *p, struct static_route *r)
|
||||
{
|
||||
rta *a = allocz(RTA_MAX_SIZE);
|
||||
a->src = p->p.main_source;
|
||||
a->src = rt_get_source(&p->p, r->preference);
|
||||
a->source = RTS_STATIC;
|
||||
a->scope = SCOPE_UNIVERSE;
|
||||
a->dest = r->dest;
|
||||
@ -101,11 +101,13 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
|
||||
/* We skip rta_lookup() here */
|
||||
rte *e = rte_get_temp(a);
|
||||
e->pflags = 0;
|
||||
e->pref = r->preference;
|
||||
|
||||
if (r->cmds)
|
||||
f_eval_rte(r->cmds, &e, static_lp);
|
||||
|
||||
rte_update(&p->p, r->net, e);
|
||||
e->pref = r->preference; /* Avoid preference from filter */
|
||||
rte_update2(p->p.main_channel, r->net, e, a->src);
|
||||
r->state = SRS_CLEAN;
|
||||
|
||||
if (r->cmds)
|
||||
@ -117,7 +119,7 @@ withdraw:
|
||||
if (r->state == SRS_DOWN)
|
||||
return;
|
||||
|
||||
rte_update(&p->p, r->net, NULL);
|
||||
rte_update2(p->p.main_channel, r->net, NULL, a->src);
|
||||
r->state = SRS_DOWN;
|
||||
}
|
||||
|
||||
@ -250,7 +252,7 @@ static void
|
||||
static_remove_rte(struct static_proto *p, struct static_route *r)
|
||||
{
|
||||
if (r->state)
|
||||
rte_update(&p->p, r->net, NULL);
|
||||
rte_update2(p->p.main_channel, r->net, NULL, rt_get_source(&p->p, r->preference));
|
||||
|
||||
static_reset_rte(p, r);
|
||||
}
|
||||
@ -380,8 +382,13 @@ static_postconfig(struct proto_config *CF)
|
||||
cc->table : cf->c.global->def_tables[NET_IP6];
|
||||
|
||||
WALK_LIST(r, cf->routes)
|
||||
{
|
||||
if (r->net && (r->net->type != CF->net_type))
|
||||
cf_error("Route %N incompatible with channel type", r->net);
|
||||
|
||||
if (!r->preference)
|
||||
r->preference = cc->preference;
|
||||
}
|
||||
}
|
||||
|
||||
static struct proto *
|
||||
@ -488,11 +495,17 @@ static_dump(struct proto *P)
|
||||
|
||||
#define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL )
|
||||
|
||||
static inline int srt_equal(struct static_route *a, struct static_route *b)
|
||||
{ return net_equal(a->net, b->net) && (a->preference == b->preference); }
|
||||
|
||||
static inline int srt_compare(struct static_route *a, struct static_route *b)
|
||||
{ return net_compare(a->net, b->net) ?: uint_cmp(a->preference, b->preference); }
|
||||
|
||||
static inline int
|
||||
static_cmp_rte(const void *X, const void *Y)
|
||||
{
|
||||
struct static_route *x = *(void **)X, *y = *(void **)Y;
|
||||
return net_compare(x->net, y->net);
|
||||
return srt_compare(x, y);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -521,7 +534,7 @@ static_reconfigure(struct proto *P, struct proto_config *CF)
|
||||
|
||||
/* Reconfigure initial matching sequence */
|
||||
for (or = HEAD(o->routes), nr = HEAD(n->routes);
|
||||
NODE_VALID(or) && NODE_VALID(nr) && net_equal(or->net, nr->net);
|
||||
NODE_VALID(or) && NODE_VALID(nr) && srt_equal(or, nr);
|
||||
or = NODE_NEXT(or), nr = NODE_NEXT(nr))
|
||||
static_reconfigure_rte(p, or, nr);
|
||||
|
||||
@ -552,7 +565,7 @@ static_reconfigure(struct proto *P, struct proto_config *CF)
|
||||
|
||||
while ((orpos < ornum) && (nrpos < nrnum))
|
||||
{
|
||||
int x = net_compare(orbuf[orpos]->net, nrbuf[nrpos]->net);
|
||||
int x = srt_compare(orbuf[orpos], nrbuf[nrpos]);
|
||||
if (x < 0)
|
||||
static_remove_rte(p, orbuf[orpos++]);
|
||||
else if (x > 0)
|
||||
|
@ -40,6 +40,7 @@ struct static_route {
|
||||
struct static_route *mp_head; /* First nexthop of this route */
|
||||
struct static_route *mp_next; /* Nexthops for multipath routes */
|
||||
struct f_inst *cmds; /* List of commands for setting attributes */
|
||||
u16 preference; /* Route preference */
|
||||
byte dest; /* Destination type (RTD_*) */
|
||||
byte state; /* State of route announcement (SRS_*) */
|
||||
byte active; /* Next hop is active (nbr/iface/BFD available) */
|
||||
|
@ -11,13 +11,16 @@ CF_HDR
|
||||
#include "sysdep/unix/unix.h"
|
||||
#include <stdio.h>
|
||||
|
||||
CF_DEFINES
|
||||
|
||||
static struct log_config *this_log;
|
||||
|
||||
CF_DECLS
|
||||
|
||||
CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT)
|
||||
CF_KEYWORDS(NAME, CONFIRM, UNDO, CHECK, TIMEOUT, DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING)
|
||||
|
||||
%type <i> log_mask log_mask_list log_cat cfg_timeout
|
||||
%type <g> log_file
|
||||
%type <t> cfg_name
|
||||
%type <tf> timeformat_which
|
||||
%type <t> syslog_name
|
||||
@ -26,11 +29,11 @@ CF_GRAMMAR
|
||||
|
||||
CF_ADDTO(conf, log_config)
|
||||
|
||||
log_config: LOG log_file log_mask ';' {
|
||||
struct log_config *c = cfg_allocz(sizeof(struct log_config));
|
||||
c->fh = $2;
|
||||
c->mask = $3;
|
||||
add_tail(&new_config->logfiles, &c->n);
|
||||
log_begin: { this_log = cfg_allocz(sizeof(struct log_config)); };
|
||||
|
||||
log_config: LOG log_begin log_file log_mask ';' {
|
||||
this_log->mask = $4;
|
||||
add_tail(&new_config->logfiles, &this_log->n);
|
||||
}
|
||||
;
|
||||
|
||||
@ -39,14 +42,21 @@ syslog_name:
|
||||
| { $$ = bird_name; }
|
||||
;
|
||||
|
||||
log_limit:
|
||||
/* empty */
|
||||
| expr text { this_log->limit = $1; this_log->backup = $2; }
|
||||
;
|
||||
|
||||
log_file:
|
||||
text {
|
||||
FILE *f = tracked_fopen(new_config->pool, $1, "a");
|
||||
if (!f) cf_error("Unable to open log file `%s': %m", $1);
|
||||
$$ = f;
|
||||
text log_limit {
|
||||
this_log->rf = rf_open(new_config->pool, $1, "a");
|
||||
if (!this_log->rf) cf_error("Unable to open log file '%s': %m", $1);
|
||||
this_log->fh = rf_file(this_log->rf);
|
||||
this_log->pos = -1;
|
||||
this_log->filename = $1;
|
||||
}
|
||||
| SYSLOG syslog_name { $$ = NULL; new_config->syslog_name = $2; }
|
||||
| STDERR { $$ = stderr; }
|
||||
| SYSLOG syslog_name { this_log->fh = NULL; new_config->syslog_name = $2; }
|
||||
| STDERR { this_log->fh = stderr; }
|
||||
;
|
||||
|
||||
log_mask:
|
||||
@ -77,9 +87,9 @@ 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");
|
||||
struct rfile *f = rf_open(new_config->pool, $2, "a");
|
||||
if (!f) cf_error("Unable to open MRTDump file '%s': %m", $2);
|
||||
new_config->mrtdump_file = fileno(f);
|
||||
new_config->mrtdump_file = rf_fileno(f);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
this to gen small latencies */
|
||||
#define MAX_RX_STEPS 4
|
||||
|
||||
|
||||
/*
|
||||
* Tracked Files
|
||||
*/
|
||||
@ -89,17 +90,29 @@ static struct resclass rf_class = {
|
||||
NULL
|
||||
};
|
||||
|
||||
void *
|
||||
tracked_fopen(pool *p, char *name, char *mode)
|
||||
struct rfile *
|
||||
rf_open(pool *p, char *name, char *mode)
|
||||
{
|
||||
FILE *f = fopen(name, mode);
|
||||
|
||||
if (f)
|
||||
{
|
||||
struct rfile *r = ralloc(p, &rf_class);
|
||||
r->f = f;
|
||||
}
|
||||
return f;
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
struct rfile *r = ralloc(p, &rf_class);
|
||||
r->f = f;
|
||||
return r;
|
||||
}
|
||||
|
||||
void *
|
||||
rf_file(struct rfile *f)
|
||||
{
|
||||
return f->f;
|
||||
}
|
||||
|
||||
int
|
||||
rf_fileno(struct rfile *f)
|
||||
{
|
||||
return fileno(f->f);
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
@ -86,6 +88,54 @@ static char *class_names[] = {
|
||||
"BUG"
|
||||
};
|
||||
|
||||
static inline off_t
|
||||
log_size(struct log_config *l)
|
||||
{
|
||||
struct stat st;
|
||||
return (!fstat(rf_fileno(l->rf), &st) && S_ISREG(st.st_mode)) ? st.st_size : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
log_close(struct log_config *l)
|
||||
{
|
||||
rfree(l->rf);
|
||||
l->rf = NULL;
|
||||
l->fh = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
log_open(struct log_config *l)
|
||||
{
|
||||
l->rf = rf_open(config->pool, l->filename, "a");
|
||||
if (!l->rf)
|
||||
{
|
||||
/* Well, we cannot do much in case of error as log is closed */
|
||||
l->mask = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
l->fh = rf_file(l->rf);
|
||||
l->pos = log_size(l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
log_rotate(struct log_config *l)
|
||||
{
|
||||
log_close(l);
|
||||
|
||||
/* If we cannot rename the logfile, we at least try to delete it
|
||||
in order to continue logging and not exceeding logfile size */
|
||||
if ((rename(l->filename, l->backup) < 0) &&
|
||||
(unlink(l->filename) < 0))
|
||||
{
|
||||
l->mask = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return log_open(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* log_commit - commit a log message
|
||||
@ -121,6 +171,22 @@ log_commit(int class, buffer *buf)
|
||||
{
|
||||
byte tbuf[TM_DATETIME_BUFFER_SIZE];
|
||||
tm_format_real_time(tbuf, config->tf_log.fmt1, current_real_time());
|
||||
|
||||
if (l->limit)
|
||||
{
|
||||
off_t msg_len = strlen(tbuf) + strlen(class_names[class]) +
|
||||
(buf->pos - buf->start) + 5;
|
||||
|
||||
if (l->pos < 0)
|
||||
l->pos = log_size(l);
|
||||
|
||||
if (l->pos + msg_len > l->limit)
|
||||
if (log_rotate(l) < 0)
|
||||
continue;
|
||||
|
||||
l->pos += msg_len;
|
||||
}
|
||||
|
||||
fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]);
|
||||
}
|
||||
fputs(buf->start, l->fh);
|
||||
@ -279,12 +345,26 @@ default_log_list(int debug, int init, char **syslog_name)
|
||||
}
|
||||
|
||||
void
|
||||
log_switch(int debug, list *l, char *new_syslog_name)
|
||||
log_switch(int debug, list *logs, char *new_syslog_name)
|
||||
{
|
||||
if (!l || EMPTY_LIST(*l))
|
||||
l = default_log_list(debug, !l, &new_syslog_name);
|
||||
struct log_config *l;
|
||||
|
||||
current_log_list = l;
|
||||
if (!logs || EMPTY_LIST(*logs))
|
||||
logs = default_log_list(debug, !logs, &new_syslog_name);
|
||||
|
||||
/* Close the logs to avoid pinning them on disk when deleted */
|
||||
if (current_log_list)
|
||||
WALK_LIST(l, *current_log_list)
|
||||
if (l->rf)
|
||||
log_close(l);
|
||||
|
||||
/* Reopen the logs, needed for 'configure undo' */
|
||||
if (logs)
|
||||
WALK_LIST(l, *logs)
|
||||
if (l->filename && !l->rf)
|
||||
log_open(l);
|
||||
|
||||
current_log_list = logs;
|
||||
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
if (current_syslog_name && new_syslog_name &&
|
||||
|
@ -14,6 +14,7 @@
|
||||
struct pool;
|
||||
struct iface;
|
||||
struct birdsock;
|
||||
struct rfile;
|
||||
|
||||
/* main.c */
|
||||
|
||||
@ -102,7 +103,9 @@ void io_init(void);
|
||||
void io_loop(void);
|
||||
void io_log_dump(void);
|
||||
int sk_open_unix(struct birdsock *s, char *name);
|
||||
void *tracked_fopen(struct pool *, char *name, char *mode);
|
||||
struct rfile *rf_open(struct pool *, char *name, char *mode);
|
||||
void *rf_file(struct rfile *f);
|
||||
int rf_fileno(struct rfile *f);
|
||||
void test_old_bird(char *path);
|
||||
|
||||
/* krt.c bits */
|
||||
@ -119,6 +122,11 @@ struct log_config {
|
||||
node n;
|
||||
uint mask; /* Classes to log */
|
||||
void *fh; /* FILE to log to, NULL=syslog */
|
||||
struct rfile *rf; /* Resource for log file */
|
||||
char *filename; /* Log filename */
|
||||
char *backup; /* Secondary filename (for log rotation) */
|
||||
off_t pos; /* Position/size of current log */
|
||||
off_t limit; /* Log size limit */
|
||||
int terminal_flag;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user