summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
Diffstat (limited to 'proto')
-rw-r--r--proto/bgp/bgp.c75
-rw-r--r--proto/bgp/bgp.h2
-rw-r--r--proto/bgp/config.Y6
-rw-r--r--proto/bgp/packets.c6
-rw-r--r--proto/ospf/config.Y26
-rw-r--r--proto/ospf/hello.c2
-rw-r--r--proto/ospf/iface.c44
-rw-r--r--proto/ospf/lsack.c8
-rw-r--r--proto/ospf/lsupd.c6
-rw-r--r--proto/ospf/ospf.c6
-rw-r--r--proto/ospf/ospf.h12
-rw-r--r--proto/ospf/packet.c5
-rw-r--r--proto/ospf/packet.h2
-rw-r--r--proto/ospf/topology.c6
-rw-r--r--proto/pipe/pipe.c45
-rw-r--r--proto/radv/config.Y126
-rw-r--r--proto/radv/packets.c181
-rw-r--r--proto/radv/radv.c4
-rw-r--r--proto/radv/radv.h31
-rw-r--r--proto/rip/rip.c5
20 files changed, 500 insertions, 98 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index d59b4308..0b52dedc 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -542,22 +542,6 @@ bgp_active(struct bgp_proto *p)
bgp_start_timer(conn->connect_retry_timer, delay);
}
-int
-bgp_apply_limits(struct bgp_proto *p)
-{
- if (p->cf->route_limit && (p->p.stats.imp_routes > p->cf->route_limit))
- {
- log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name);
- bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED);
- bgp_update_startup_delay(p);
- bgp_stop(p, 1); // Errcode 6, 1 - max number of prefixes reached
- return -1;
- }
-
- return 0;
-}
-
-
/**
* bgp_connect - initiate an outgoing connection
* @p: BGP instance
@@ -864,28 +848,58 @@ bgp_start(struct proto *P)
return PS_START;
}
+extern int proto_restart;
+
static int
bgp_shutdown(struct proto *P)
{
struct bgp_proto *p = (struct bgp_proto *) P;
- unsigned subcode;
+ unsigned subcode = 0;
BGP_TRACE(D_EVENTS, "Shutdown requested");
- bgp_store_error(p, NULL, BE_MAN_DOWN, 0);
- if (P->reconfiguring)
+ switch (P->down_code)
{
- if (P->cf_new)
- subcode = 6; // Errcode 6, 6 - other configuration change
+ case PDC_CF_REMOVE:
+ case PDC_CF_DISABLE:
+ subcode = 3; // Errcode 6, 3 - peer de-configured
+ break;
+
+ case PDC_CF_RESTART:
+ subcode = 6; // Errcode 6, 6 - other configuration change
+ break;
+
+ case PDC_CMD_DISABLE:
+ subcode = 2; // Errcode 6, 2 - administrative shutdown
+ break;
+
+ case PDC_CMD_RESTART:
+ subcode = 4; // Errcode 6, 4 - administrative reset
+ break;
+
+ case PDC_IN_LIMIT_HIT:
+ subcode = 1; // Errcode 6, 1 - max number of prefixes reached
+ /* log message for compatibility */
+ log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name);
+ goto limit;
+
+ case PDC_OUT_LIMIT_HIT:
+ subcode = proto_restart ? 4 : 2; // Administrative reset or shutdown
+
+ limit:
+ bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED);
+ if (proto_restart)
+ bgp_update_startup_delay(p);
else
- subcode = 3; // Errcode 6, 3 - peer de-configured
+ p->startup_delay = 0;
+ goto done;
}
- else
- subcode = 2; // Errcode 6, 2 - administrative shutdown
+ bgp_store_error(p, NULL, BE_MAN_DOWN, 0);
p->startup_delay = 0;
- bgp_stop(p, subcode);
+ done:
+ bgp_stop(p, subcode);
return p->p.proto_state;
}
@@ -972,6 +986,10 @@ bgp_check_config(struct bgp_config *c)
if (!c->gw_mode)
c->gw_mode = (c->multihop || internal) ? GW_RECURSIVE : GW_DIRECT;
+ /* Disable after error incompatible with restart limit action */
+ if (c->c.in_limit && (c->c.in_limit->action == PLA_RESTART) && c->disable_after_error)
+ c->c.in_limit->action = PLA_DISABLE;
+
if ((c->gw_mode == GW_RECURSIVE) && c->c.table->sorted)
cf_error("BGP in recursive mode prohibits sorted table");
@@ -1128,9 +1146,6 @@ bgp_get_status(struct proto *P, byte *buf)
bsprintf(buf, "%-14s%s%s", bgp_state_dsc(p), err1, err2);
}
-static inline bird_clock_t tm_remains(timer *t)
-{ return t->expires ? t->expires - now : 0; }
-
static void
bgp_show_proto_info(struct proto *P)
{
@@ -1170,9 +1185,9 @@ bgp_show_proto_info(struct proto *P)
p->rs_client ? " route-server" : "",
p->as4_session ? " AS4" : "");
cli_msg(-1006, " Source address: %I", p->source_addr);
- if (p->cf->route_limit)
+ if (P->cf->in_limit)
cli_msg(-1006, " Route limit: %d/%d",
- p->p.stats.imp_routes, p->cf->route_limit);
+ p->p.stats.imp_routes, P->cf->in_limit->limit);
cli_msg(-1006, " Hold timer: %d/%d",
tm_remains(c->hold_timer), c->hold_time);
cli_msg(-1006, " Keepalive timer: %d/%d",
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 87734425..c3adf254 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -40,7 +40,6 @@ struct bgp_config {
int rr_client; /* Whether neighbor is RR client of me */
int rs_client; /* Whether neighbor is RS client of me */
int advertise_ipv4; /* Whether we should add IPv4 capability advertisement to OPEN message */
- u32 route_limit; /* Number of routes that may be imported, 0 means disable limit */
int passive; /* Do not initiate outgoing connection */
int interpret_communities; /* Hardwired handling of well-known communities */
int secondary; /* Accept also non-best routes (i.e. RA_ACCEPTED) */
@@ -153,7 +152,6 @@ 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);
void bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code);
-int bgp_apply_limits(struct bgp_proto *p);
void bgp_stop(struct bgp_proto *p, unsigned subcode);
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index f9a5be65..8b80d7fd 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -99,7 +99,11 @@ bgp_proto:
| bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
| bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; }
| bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; }
- | bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; }
+ | bgp_proto ROUTE LIMIT expr ';' {
+ this_proto->in_limit = cfg_allocz(sizeof(struct proto_limit));
+ this_proto->in_limit->limit = $4;
+ this_proto->in_limit->action = PLA_RESTART;
+ }
| bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
| bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
| bgp_proto SECONDARY bool ';' { BGP_CFG->secondary = $3; }
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index d3e9b6a1..cfa37fb5 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -915,9 +915,6 @@ bgp_do_rx_update(struct bgp_conn *conn,
if (n = net_find(p->p.table, prefix, pxlen))
rte_update(p->p.table, n, &p->p, &p->p, NULL);
}
-
- if (bgp_apply_limits(p) < 0)
- goto done;
}
done:
@@ -1034,9 +1031,6 @@ bgp_do_rx_update(struct bgp_conn *conn,
if (n = net_find(p->p.table, prefix, pxlen))
rte_update(p->p.table, n, &p->p, &p->p, NULL);
}
-
- if (bgp_apply_limits(p) < 0)
- goto done;
}
}
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index 38e59886..67b0785f 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -107,7 +107,17 @@ static inline void
check_defcost(int cost)
{
if ((cost <= 0) || (cost >= LSINFINITY))
- cf_error("Default cost must be in range 1-%d", LSINFINITY);
+ cf_error("Default cost must be in range 1-%d", LSINFINITY-1);
+}
+
+static inline void
+set_instance_id(unsigned id)
+{
+#ifdef OSPFv3
+ OSPF_PATT->instance_id = id;
+#else
+ cf_error("Instance ID requires OSPFv3");
+#endif
}
CF_DECLS
@@ -120,7 +130,7 @@ CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK)
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
-CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF)
+CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL)
%type <t> opttext
%type <ld> lsadb_args
@@ -218,8 +228,8 @@ ospf_stubnet_item:
;
ospf_vlink:
- ospf_vlink_start '{' ospf_vlink_opts '}' { ospf_iface_finish(); }
- | ospf_vlink_start { ospf_iface_finish(); }
+ ospf_vlink_start ospf_instance_id '{' ospf_vlink_opts '}' { ospf_iface_finish(); }
+ | ospf_vlink_start ospf_instance_id { ospf_iface_finish(); }
;
ospf_vlink_opts:
@@ -277,6 +287,7 @@ ospf_iface_item:
| TYPE PTP { OSPF_PATT->type = OSPF_IT_PTP ; }
| TYPE POINTOMULTIPOINT { OSPF_PATT->type = OSPF_IT_PTMP ; }
| TYPE PTMP { OSPF_PATT->type = OSPF_IT_PTMP ; }
+ | REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (OSPF_VERSION != 2) cf_error("Real broadcast option requires OSPFv2"); }
| TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
| PRIORITY expr { OSPF_PATT->priority = $2 ; if (($2<0) || ($2>255)) cf_error("Priority must be in range 0-255"); }
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
@@ -364,6 +375,11 @@ ospf_iface_start:
}
;
+ospf_instance_id:
+ /* empty */
+ | INSTANCE expr { set_instance_id($2); }
+ ;
+
ospf_iface_opts:
/* empty */
| ospf_iface_opts ospf_iface_item ';'
@@ -375,7 +391,7 @@ ospf_iface_opt_list:
;
ospf_iface:
- ospf_iface_start iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); }
+ ospf_iface_start iface_patt_list ospf_instance_id ospf_iface_opt_list { ospf_iface_finish(); }
;
opttext:
diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c
index d04cb54c..f9ba28f6 100644
--- a/proto/ospf/hello.c
+++ b/proto/ospf/hello.c
@@ -303,7 +303,7 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
{
case OSPF_IT_BCAST:
case OSPF_IT_PTP:
- ospf_send_to(ifa, AllSPFRouters);
+ ospf_send_to_all(ifa);
break;
case OSPF_IT_NBMA:
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 405e49df..a6a0c6c1 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -120,13 +120,24 @@ ospf_sk_open(struct ospf_iface *ifa)
sk->saddr = ifa->addr->ip;
if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))
{
- sk->ttl = 1; /* Hack, this will affect just multicast packets */
+ if (ifa->cf->real_bcast)
+ {
+ ifa->all_routers = ifa->addr->brd;
+
+ if (sk_set_broadcast(sk, 1) < 0)
+ goto err;
+ }
+ else
+ {
+ ifa->all_routers = AllSPFRouters;
+ sk->ttl = 1; /* Hack, this will affect just multicast packets */
- if (sk_setup_multicast(sk) < 0)
- goto err;
+ if (sk_setup_multicast(sk) < 0)
+ goto err;
- if (sk_join_group(sk, AllSPFRouters) < 0)
- goto err;
+ if (sk_join_group(sk, ifa->all_routers) < 0)
+ goto err;
+ }
}
ifa->sk = sk;
@@ -265,7 +276,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
- if ((ifa->type == OSPF_IT_BCAST) && ifa->sk)
+ if ((ifa->type == OSPF_IT_BCAST) && !ifa->cf->real_bcast && ifa->sk)
{
if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
ospf_sk_join_dr(ifa);
@@ -536,6 +547,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
/* Check validity of interface type */
int old_type = ifa->type;
+ u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST;
#ifdef OSPFv2
if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
@@ -545,10 +557,10 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
ifa->type = OSPF_IT_PTMP;
#endif
- if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & IF_MULTICAST))
+ if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag))
ifa->type = OSPF_IT_NBMA;
- if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & IF_MULTICAST))
+ if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & if_multi_flag))
ifa->type = OSPF_IT_PTMP;
if (ifa->type != old_type)
@@ -628,6 +640,9 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
if (ifa->stub != new_stub)
return 0;
+ if (new->real_bcast != ifa->cf->real_bcast)
+ return 0;
+
ifa->cf = new;
ifa->marked = 0;
@@ -1099,11 +1114,15 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
void
ospf_iface_info(struct ospf_iface *ifa)
{
- char *strict = "";
+ char *more = "";
if (ifa->strictnbma &&
((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)))
- strict = "(strict)";
+ more = " (strict)";
+
+ if (ifa->cf->real_bcast &&
+ ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP)))
+ more = " (real)";
if (ifa->type == OSPF_IT_VLINK)
{
@@ -1124,11 +1143,10 @@ ospf_iface_info(struct ospf_iface *ifa)
#else /* OSPFv3 */
cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id);
#endif
- cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict);
+ cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
}
- cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state],
- ifa->stub ? "(stub)" : "");
+ cli_msg(-1015, "\tState: %s%s", ospf_is[ifa->state], ifa->stub ? " (stub)" : "");
cli_msg(-1015, "\tPriority: %u", ifa->priority);
cli_msg(-1015, "\tCost: %u", ifa->cost);
if (ifa->oa->po->ecmp)
diff --git a/proto/ospf/lsack.c b/proto/ospf/lsack.c
index 53422e53..00c50caf 100644
--- a/proto/ospf/lsack.c
+++ b/proto/ospf/lsack.c
@@ -97,7 +97,9 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
if (ifa->type == OSPF_IT_BCAST)
{
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
- ospf_send_to(ifa, AllSPFRouters);
+ ospf_send_to_all(ifa);
+ else if (ifa->cf->real_bcast)
+ ospf_send_to_bdr(ifa);
else
ospf_send_to(ifa, AllDRouters);
}
@@ -124,7 +126,9 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
if (ifa->type == OSPF_IT_BCAST)
{
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
- ospf_send_to(ifa, AllSPFRouters);
+ ospf_send_to_all(ifa);
+ else if (ifa->cf->real_bcast)
+ ospf_send_to_bdr(ifa);
else
ospf_send_to(ifa, AllDRouters);
}
diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c
index 325a8d00..f71c72d1 100644
--- a/proto/ospf/lsupd.c
+++ b/proto/ospf/lsupd.c
@@ -314,7 +314,9 @@ ospf_lsupd_flood(struct proto_ospf *po,
{
case OSPF_IT_BCAST:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
- ospf_send_to(ifa, AllSPFRouters);
+ ospf_send_to_all(ifa);
+ else if (ifa->cf->real_bcast)
+ ospf_send_to_bdr(ifa);
else
ospf_send_to(ifa, AllDRouters);
break;
@@ -327,7 +329,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
break;
case OSPF_IT_PTP:
- ospf_send_to(ifa, AllSPFRouters);
+ ospf_send_to_all(ifa);
break;
case OSPF_IT_PTMP:
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index 9872faf2..ef7b0363 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -1145,16 +1145,16 @@ show_lsa_sum_net(struct top_hash_entry *he)
static inline void
show_lsa_sum_rt(struct top_hash_entry *he)
{
- u32 dst_rid, options;
+ u32 dst_rid;
#ifdef OSPFv2
struct ospf_lsa_sum *ls = he->lsa_body;
dst_rid = he->lsa.id;
- options = 0;
+ // options = 0;
#else /* OSPFv3 */
struct ospf_lsa_sum_rt *ls = he->lsa_body;
dst_rid = ls->drid;
- options = ls->options & OPTIONS_MASK;
+ // options = ls->options & OPTIONS_MASK;
#endif
cli_msg(-1016, "\t\txrouter %R metric %u", dst_rid, ls->metric);
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index 96da9aa7..3bffaf91 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -205,6 +205,7 @@ struct ospf_iface
bird_clock_t csn_use; /* Last time when packet with that CSN was sent */
#endif
+ ip_addr all_routers; /* */
ip_addr drip; /* Designated router */
ip_addr bdrip; /* Backup DR */
u32 drid;
@@ -790,22 +791,23 @@ struct ospf_iface_patt
u32 deadc;
u32 deadint;
u32 inftransdelay;
- u32 priority;
- u32 strictnbma;
list nbma_list;
+ u32 priority;
u32 voa;
u32 vid;
u16 rxbuf;
- u8 check_link;
- u8 ecmp_weight;
#define OSPF_RXBUF_NORMAL 0
#define OSPF_RXBUF_LARGE 1
#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
- u32 autype; /* Not really used in OSPFv3 */
+ u16 autype; /* Not really used in OSPFv3 */
#define OSPF_AUTH_NONE 0
#define OSPF_AUTH_SIMPLE 1
#define OSPF_AUTH_CRYPT 2
#define OSPF_AUTH_CRYPT_SIZE 16
+ u8 strictnbma;
+ u8 check_link;
+ u8 ecmp_weight;
+ u8 real_bcast; /* Not really used in OSPFv3 */
#ifdef OSPFv2
list *passwords;
diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c
index 7a26967f..241a58f7 100644
--- a/proto/ospf/packet.c
+++ b/proto/ospf/packet.c
@@ -273,7 +273,7 @@ ospf_rx_hook(sock *sk, int size)
int src_local, dst_local UNUSED, dst_mcast;
src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
- dst_mcast = ipa_equal(sk->laddr, AllSPFRouters) || ipa_equal(sk->laddr, AllDRouters);
+ dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, AllDRouters);
#ifdef OSPFv2
/* First, we eliminate packets with strange address combinations.
@@ -287,6 +287,9 @@ ospf_rx_hook(sock *sk, int size)
if (!dst_mcast && !dst_local)
return 1;
+ /* Ignore my own broadcast packets */
+ if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
+ return 1;
#else /* OSPFv3 */
/* In OSPFv3, src_local and dst_local mean link-local.
diff --git a/proto/ospf/packet.h b/proto/ospf/packet.h
index c0185b9c..fbcb4288 100644
--- a/proto/ospf/packet.h
+++ b/proto/ospf/packet.h
@@ -19,6 +19,8 @@ void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
void ospf_send_to_bdr(struct ospf_iface *ifa);
void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
+static inline void ospf_send_to_all(struct ospf_iface *ifa) { ospf_send_to(ifa, ifa->all_routers); }
+
static inline void * ospf_tx_buffer(struct ospf_iface *ifa) { return ifa->sk->tbuf; }
static inline unsigned
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 604c8ea7..7e9bad50 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -798,7 +798,7 @@ originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric)
body = originate_sum_net_lsa_body(po, &lsa.length, fn, metric);
lsasum_calculate(&lsa, body);
- en = lsa_install_new(po, &lsa, dom, body);
+ lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
}
@@ -835,7 +835,7 @@ originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32
body = originate_sum_rt_lsa_body(po, &lsa.length, lsa.id, metric, options);
lsasum_calculate(&lsa, body);
- en = lsa_install_new(po, &lsa, dom, body);
+ lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
}
@@ -1117,7 +1117,7 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src,
if (src)
fn->x1 = src;
- en = lsa_install_new(po, &lsa, dom, body);
+ lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
if (po->ebit == 0)
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index 36b06d43..6099d284 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -24,9 +24,10 @@
* rte_update(), an import filter in ahook 2 is called. When a new
* route is announced in the peer table, an export filter in ahook2
* and an import filter in ahook 1 are used. Oviously, there is no
- * need in filtering the same route twice, so both import filters
- * are set to accept, while user configured 'import' and 'export'
- * filters are used as export filters in ahooks 2 and 1.
+ * need in filtering the same route twice, so both import filters are
+ * set to accept, while user configured 'import' and 'export' filters
+ * are used as export filters in ahooks 2 and 1. Route limits are
+ * handled similarly, but on the import side of ahooks.
*/
#undef LOCAL_DEBUG
@@ -116,6 +117,8 @@ pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpo
static int
pipe_reload_routes(struct proto *P)
{
+ struct pipe_proto *p = (struct pipe_proto *) P;
+
/*
* Because the pipe protocol feeds routes from both routing tables
* together, both directions are reloaded during refeed and 'reload
@@ -123,6 +126,10 @@ pipe_reload_routes(struct proto *P)
* request refeed when 'reload in' command is used.
*/
proto_request_feeding(P);
+
+ proto_reset_limit(P->main_ahook->in_limit);
+ proto_reset_limit(p->peer_ahook->in_limit);
+
return 1;
}
@@ -146,6 +153,7 @@ pipe_init(struct proto_config *C)
static int
pipe_start(struct proto *P)
{
+ struct pipe_config *cf = (struct pipe_config *) P->cf;
struct pipe_proto *p = (struct pipe_proto *) P;
/* Lock both tables, unlock is handled in pipe_cleanup() */
@@ -155,10 +163,15 @@ pipe_start(struct proto *P)
/* Going directly to PS_UP - prepare for feeding,
connect the protocol to both routing tables */
- P->main_ahook = proto_add_announce_hook(P, P->table,
- FILTER_ACCEPT, P->cf->out_filter, &P->stats);
- p->peer_ahook = proto_add_announce_hook(P, p->peer_table,
- FILTER_ACCEPT, P->cf->in_filter, &p->peer_stats);
+ P->main_ahook = proto_add_announce_hook(P, P->table, &P->stats);
+ P->main_ahook->out_filter = cf->c.out_filter;
+ P->main_ahook->in_limit = cf->c.in_limit;
+ proto_reset_limit(P->main_ahook->in_limit);
+
+ p->peer_ahook = proto_add_announce_hook(P, p->peer_table, &p->peer_stats);
+ p->peer_ahook->out_filter = cf->c.in_filter;
+ p->peer_ahook->in_limit = cf->c.out_limit;
+ proto_reset_limit(p->peer_ahook->in_limit);
return PS_UP;
}
@@ -204,10 +217,16 @@ pipe_reconfigure(struct proto *P, struct proto_config *new)
/* Update output filters in ahooks */
if (P->main_ahook)
- P->main_ahook->out_filter = new->out_filter;
+ {
+ P->main_ahook->out_filter = new->out_filter;
+ P->main_ahook->in_limit = new->in_limit;
+ }
if (p->peer_ahook)
- p->peer_ahook->out_filter = new->in_filter;
+ {
+ p->peer_ahook->out_filter = new->in_filter;
+ p->peer_ahook->in_limit = new->out_limit;
+ }
if ((P->proto_state != PS_UP) || (proto_reconfig_type == RECONFIG_SOFT))
return 1;
@@ -283,12 +302,16 @@ static void
pipe_show_proto_info(struct proto *P)
{
struct pipe_proto *p = (struct pipe_proto *) P;
+ struct pipe_config *cf = (struct pipe_config *) P->cf;
// cli_msg(-1006, " Table: %s", P->table->name);
// cli_msg(-1006, " Peer table: %s", p->peer_table->name);
cli_msg(-1006, " Preference: %d", P->preference);
- cli_msg(-1006, " Input filter: %s", filter_name(P->cf->in_filter));
- cli_msg(-1006, " Output filter: %s", filter_name(P->cf->out_filter));
+ cli_msg(-1006, " Input filter: %s", filter_name(cf->c.in_filter));
+ cli_msg(-1006, " Output filter: %s", filter_name(cf->c.out_filter));
+
+ proto_show_limit(cf->c.in_limit, "Import limit:");
+ proto_show_limit(cf->c.out_limit, "Export limit:");
if (P->proto_state != PS_DOWN)
pipe_show_stats(p);
diff --git a/proto/radv/config.Y b/proto/radv/config.Y
index 495d9a05..abccd2c7 100644
--- a/proto/radv/config.Y
+++ b/proto/radv/config.Y
@@ -14,32 +14,45 @@ CF_DEFINES
#define RADV_CFG ((struct radv_config *) this_proto)
#define RADV_IFACE ((struct radv_iface_config *) this_ipatt)
#define RADV_PREFIX this_radv_prefix
+#define RADV_RDNSS (&this_radv_rdnss)
+#define RADV_DNSSL (&this_radv_dnssl)
static struct radv_prefix_config *this_radv_prefix;
+static struct radv_rdnss_config this_radv_rdnss;
+static struct radv_dnssl_config this_radv_dnssl;
+static list radv_dns_list; /* Used by radv_rdnss and radv_dnssl */
+static u8 radv_mult_val; /* Used by radv_mult for second return value */
+
CF_DECLS
CF_KEYWORDS(RADV, PREFIX, INTERFACE, MIN, MAX, RA, DELAY, INTERVAL,
MANAGED, OTHER, CONFIG, LINK, MTU, REACHABLE, TIME, RETRANS,
- TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED,
- LIFETIME, SKIP, ONLINK, AUTONOMOUS)
+ TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED, MULT,
+ LIFETIME, SKIP, ONLINK, AUTONOMOUS, RDNSS, DNSSL, NS, DOMAIN,
+ LOCAL)
+%type<i> radv_mult
CF_GRAMMAR
-CF_ADDTO(proto, radv_proto '}')
+CF_ADDTO(proto, radv_proto)
radv_proto_start: proto_start RADV
{
this_proto = proto_config_new(&proto_radv, sizeof(struct radv_config), $1);
init_list(&RADV_CFG->patt_list);
init_list(&RADV_CFG->pref_list);
+ init_list(&RADV_CFG->rdnss_list);
+ init_list(&RADV_CFG->dnssl_list);
};
radv_proto_item:
proto_item
- | PREFIX radv_prefix { add_tail(&RADV_CFG->pref_list, NODE this_radv_prefix); }
| INTERFACE radv_iface
+ | PREFIX radv_prefix { add_tail(&RADV_CFG->pref_list, NODE this_radv_prefix); }
+ | RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_CFG->rdnss_list, &radv_dns_list); }
+ | DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_CFG->dnssl_list, &radv_dns_list); }
;
radv_proto_opts:
@@ -48,7 +61,7 @@ radv_proto_opts:
;
radv_proto:
- radv_proto_start proto_name '{' radv_proto_opts;
+ radv_proto_start proto_name '{' radv_proto_opts '}';
radv_iface_start:
@@ -57,6 +70,8 @@ radv_iface_start:
add_tail(&RADV_CFG->patt_list, NODE this_ipatt);
init_list(&this_ipatt->ipn_list);
init_list(&RADV_IFACE->pref_list);
+ init_list(&RADV_IFACE->rdnss_list);
+ init_list(&RADV_IFACE->dnssl_list);
RADV_IFACE->min_ra_int = -1; /* undefined */
RADV_IFACE->max_ra_int = DEFAULT_MAX_RA_INT;
@@ -77,6 +92,10 @@ radv_iface_item:
| CURRENT HOP LIMIT expr { RADV_IFACE->current_hop_limit = $4; if (($4 < 0) || ($4 > 255)) cf_error("Current hop limit must be in range 0-255"); }
| DEFAULT LIFETIME expr { RADV_IFACE->default_lifetime = $3; if (($3 < 0) || ($3 > 9000)) cf_error("Default lifetime must be in range 0-9000"); }
| PREFIX radv_prefix { add_tail(&RADV_IFACE->pref_list, NODE this_radv_prefix); }
+ | RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_IFACE->rdnss_list, &radv_dns_list); }
+ | DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_IFACE->dnssl_list, &radv_dns_list); }
+ | RDNSS LOCAL bool { RADV_IFACE->rdnss_local = $3; }
+ | DNSSL LOCAL bool { RADV_IFACE->dnssl_local = $3; }
;
radv_iface_finish:
@@ -152,6 +171,103 @@ radv_prefix:
radv_prefix_start radv_prefix_opt_list radv_prefix_finish;
+
+radv_rdnss_node: ipa
+{
+ struct radv_rdnss_config *cf = cfg_allocz(sizeof(struct radv_rdnss_config));
+ add_tail(&radv_dns_list, NODE cf);
+
+ cf->server = $1;
+ cf->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
+};
+
+radv_rdnss_start:
+{
+ RADV_RDNSS->lifetime = 0;
+ RADV_RDNSS->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
+};
+
+radv_rdnss_item:
+ | NS radv_rdnss_node
+ | LIFETIME radv_mult { RADV_RDNSS->lifetime = $2; RADV_RDNSS->lifetime_mult = radv_mult_val; }
+ ;
+
+radv_rdnss_finish:
+{
+ if (EMPTY_LIST(radv_dns_list))
+ cf_error("No nameserver in RDNSS section");
+
+ struct radv_rdnss_config *cf;
+ WALK_LIST(cf, radv_dns_list)
+ {
+ cf->lifetime = RADV_RDNSS->lifetime;
+ cf->lifetime_mult = RADV_RDNSS->lifetime_mult;
+ }
+};
+
+radv_rdnss_opts:
+ /* empty */
+ | radv_rdnss_opts radv_rdnss_item ';'
+ ;
+
+radv_rdnss:
+ radv_rdnss_node
+ | '{' radv_rdnss_start radv_rdnss_opts '}' radv_rdnss_finish
+ ;
+
+
+radv_dnssl_node: TEXT
+{
+ struct radv_dnssl_config *cf = cfg_allocz(sizeof(struct radv_dnssl_config));
+ add_tail(&radv_dns_list, NODE cf);
+
+ cf->domain = $1;
+ cf->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
+
+ if (radv_process_domain(cf) < 0)
+ cf_error("Invalid domain dame");
+};
+
+radv_dnssl_start:
+{
+ RADV_DNSSL->lifetime = 0;
+ RADV_DNSSL->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
+};
+
+radv_dnssl_item:
+ | DOMAIN radv_dnssl_node
+ | LIFETIME radv_mult { RADV_DNSSL->lifetime = $2; RADV_DNSSL->lifetime_mult = radv_mult_val; }
+ ;
+
+radv_dnssl_finish:
+{
+ if (EMPTY_LIST(radv_dns_list))
+ cf_error("No domain in DNSSL section");
+
+ struct radv_dnssl_config *cf;
+ WALK_LIST(cf, radv_dns_list)
+ {
+ cf->lifetime = RADV_DNSSL->lifetime;
+ cf->lifetime_mult = RADV_DNSSL->lifetime_mult;
+ }
+};
+
+radv_dnssl_opts:
+ /* empty */
+ | radv_dnssl_opts radv_dnssl_item ';'
+ ;
+
+radv_dnssl:
+ radv_dnssl_node
+ | '{' radv_dnssl_start radv_dnssl_opts '}' radv_dnssl_finish
+ ;
+
+
+radv_mult:
+ expr { $$ = $1; radv_mult_val = 0; }
+ | MULT expr { $$ = 0; radv_mult_val = $2; if (($2 < 1) || ($2 > 254)) cf_error("Multiplier must be in range 1-254"); }
+ ;
+
CF_CODE
CF_END
diff --git a/proto/radv/packets.c b/proto/radv/packets.c
index ac59ce94..6fdfcaa3 100644
--- a/proto/radv/packets.c
+++ b/proto/radv/packets.c
@@ -24,8 +24,10 @@ struct radv_ra_packet
#define OPT_RA_MANAGED 0x80
#define OPT_RA_OTHER_CFG 0x40
-#define OPT_PREFIX 3
-#define OPT_MTU 5
+#define OPT_PREFIX 3
+#define OPT_MTU 5
+#define OPT_RDNSS 25
+#define OPT_DNSSL 31
struct radv_opt_prefix
{
@@ -50,6 +52,25 @@ struct radv_opt_mtu
u32 mtu;
};
+struct radv_opt_rdnss
+{
+ u8 type;
+ u8 length;
+ u16 reserved;
+ u32 lifetime;
+ ip_addr servers[];
+};
+
+struct radv_opt_dnssl
+{
+ u8 type;
+ u8 length;
+ u16 reserved;
+ u32 lifetime;
+ char domain[];
+};
+
+
static struct radv_prefix_config default_prefix = {
.onlink = 1,
.autonomous = 1,
@@ -57,6 +78,7 @@ static struct radv_prefix_config default_prefix = {
.preferred_lifetime = DEFAULT_PREFERRED_LIFETIME
};
+
static struct radv_prefix_config *
radv_prefix_match(struct radv_iface *ifa, struct ifa *a)
{
@@ -78,10 +100,146 @@ radv_prefix_match(struct radv_iface *ifa, struct ifa *a)
return &default_prefix;
}
+static int
+radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *bufend)
+{
+ struct radv_rdnss_config *rcf = HEAD(*rdnss_list);
+
+ while(NODE_VALID(rcf))
+ {
+ struct radv_rdnss_config *rcf_base = rcf;
+ struct radv_opt_rdnss *op = (void *) *buf;
+ int max_i = (bufend - *buf - sizeof(struct radv_opt_rdnss)) / sizeof(ip_addr);
+ int i = 0;
+
+ if (max_i < 1)
+ goto too_much;
+
+ op->type = OPT_RDNSS;
+ op->reserved = 0;
+
+ if (rcf->lifetime_mult)
+ op->lifetime = htonl(rcf->lifetime_mult * ifa->cf->max_ra_int);
+ else
+ op->lifetime = htonl(rcf->lifetime);
+
+ while(NODE_VALID(rcf) &&
+ (rcf->lifetime == rcf_base->lifetime) &&
+ (rcf->lifetime_mult == rcf_base->lifetime_mult))
+ {
+ if (i >= max_i)
+ goto too_much;
+
+ op->servers[i] = rcf->server;
+ ipa_hton(op->servers[i]);
+ i++;
+
+ rcf = NODE_NEXT(rcf);
+ }
+
+ op->length = 1+2*i;
+ *buf += 8 * op->length;
+ }
+
+ return 0;
+
+ too_much:
+ log(L_WARN "%s: Too many RA options on interface %s",
+ ifa->ra->p.name, ifa->iface->name);
+ return -1;
+}
+
+int
+radv_process_domain(struct radv_dnssl_config *cf)
+{
+ /* Format of domain in search list is <size> <label> <size> <label> ... 0 */
+
+ char *dom = cf->domain;
+ char *dom_end = dom; /* Just to */
+ u8 *dlen_save = &cf->dlen_first;
+ int len;
+
+ while (dom_end)
+ {
+ dom_end = strchr(dom, '.');
+ len = dom_end ? (dom_end - dom) : strlen(dom);
+
+ if (len < 1 || len > 63)
+ return -1;
+
+ *dlen_save = len;
+ dlen_save = (u8 *) dom_end;
+
+ dom += len + 1;
+ }
+
+ len = dom - cf->domain;
+ if (len > 254)
+ return -1;
+
+ cf->dlen_all = len;
+
+ return 0;
+}
+
+static int
+radv_prepare_dnssl(struct radv_iface *ifa, list *dnssl_list, char **buf, char *bufend)
+{
+ struct radv_dnssl_config *dcf = HEAD(*dnssl_list);
+
+ while(NODE_VALID(dcf))
+ {
+ struct radv_dnssl_config *dcf_base = dcf;
+ struct radv_opt_dnssl *op = (void *) *buf;
+ int bsize = bufend - *buf - sizeof(struct radv_opt_dnssl);
+ int bpos = 0;
+
+ if (bsize < 0)
+ goto too_much;
+
+ bsize = bsize & ~7; /* Round down to multiples of 8 */
+
+ op->type = OPT_DNSSL;
+ op->reserved = 0;
+
+ if (dcf->lifetime_mult)
+ op->lifetime = htonl(dcf->lifetime_mult * ifa->cf->max_ra_int);
+ else
+ op->lifetime = htonl(dcf->lifetime);
+
+ while(NODE_VALID(dcf) &&
+ (dcf->lifetime == dcf_base->lifetime) &&
+ (dcf->lifetime_mult == dcf_base->lifetime_mult))
+ {
+ if (bpos + dcf->dlen_all + 1 > bsize)
+ goto too_much;
+
+ op->domain[bpos++] = dcf->dlen_first;
+ memcpy(op->domain + bpos, dcf->domain, dcf->dlen_all);
+ bpos += dcf->dlen_all;
+
+ dcf = NODE_NEXT(dcf);
+ }
+
+ int blen = (bpos + 7) / 8;
+ bzero(op->domain + bpos, 8 * blen - bpos);
+ op->length = 1 + blen;
+ *buf += 8 * op->length;
+ }
+
+ return 0;
+
+ too_much:
+ log(L_WARN "%s: Too many RA options on interface %s",
+ ifa->ra->p.name, ifa->iface->name);
+ return -1;
+}
+
static void
radv_prepare_ra(struct radv_iface *ifa)
{
struct proto_radv *ra = ifa->ra;
+ struct radv_config *cf = (struct radv_config *) (ra->p.cf);
char *buf = ifa->sk->tbuf;
char *bufstart = buf;
@@ -121,7 +279,7 @@ radv_prepare_ra(struct radv_iface *ifa)
if (buf + sizeof(struct radv_opt_prefix) > bufend)
{
log(L_WARN "%s: Too many prefixes on interface %s", ra->p.name, ifa->iface->name);
- break;
+ goto done;
}
struct radv_opt_prefix *op = (void *) buf;
@@ -137,7 +295,22 @@ radv_prepare_ra(struct radv_iface *ifa)
ipa_hton(op->prefix);
buf += sizeof(*op);
}
-
+
+ if (! ifa->cf->rdnss_local)
+ if (radv_prepare_rdnss(ifa, &cf->rdnss_list, &buf, bufend) < 0)
+ goto done;
+
+ if (radv_prepare_rdnss(ifa, &ifa->cf->rdnss_list, &buf, bufend) < 0)
+ goto done;
+
+ if (! ifa->cf->dnssl_local)
+ if (radv_prepare_dnssl(ifa, &cf->dnssl_list, &buf, bufend) < 0)
+ goto done;
+
+ if (radv_prepare_dnssl(ifa, &ifa->cf->dnssl_list, &buf, bufend) < 0)
+ goto done;
+
+ done:
ifa->plen = buf - bufstart;
}
diff --git a/proto/radv/radv.c b/proto/radv/radv.c
index d6fc8da5..5e7296a3 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -29,6 +29,10 @@
* radv_iface_notify(), which processes asynchronous events (specified
* by RA_EV_* codes), and radv_timer(), which triggers sending RAs and
* computes the next timeout.
+ *
+ * Supported standards:
+ * - RFC 4861 - main RA standard
+ * - RFC 6106 - DNS extensions (RDDNS, DNSSL)
*/
static void
diff --git a/proto/radv/radv.h b/proto/radv/radv.h
index 12bfe42e..48af8c00 100644
--- a/proto/radv/radv.h
+++ b/proto/radv/radv.h
@@ -42,24 +42,33 @@
#define DEFAULT_VALID_LIFETIME 86400
#define DEFAULT_PREFERRED_LIFETIME 14400
+#define DEFAULT_DNS_LIFETIME_MULT 3
+
struct radv_config
{
struct proto_config c;
list patt_list; /* List of iface configs (struct radv_iface_config) */
list pref_list; /* Global list of prefix configs (struct radv_prefix_config) */
+ list rdnss_list; /* Global list of RDNSS configs (struct radv_rdnss_config) */
+ list dnssl_list; /* Global list of DNSSL configs (struct radv_dnssl_config) */
};
struct radv_iface_config
{
struct iface_patt i;
list pref_list; /* Local list of prefix configs (struct radv_prefix_config) */
+ list rdnss_list; /* Local list of RDNSS configs (struct radv_rdnss_config) */
+ list dnssl_list; /* Local list of DNSSL configs (struct radv_dnssl_config) */
u32 min_ra_int; /* Standard options from RFC 4261 */
u32 max_ra_int;
u32 min_delay;
- u8 managed;
+ u8 rdnss_local; /* Global list is not used for RDNSS */
+ u8 dnssl_local; /* Global list is not used for DNSSL */
+
+ u8 managed; /* Standard options from RFC 4261 */
u8 other_config;
u32 link_mtu;
u32 reachable_time;
@@ -81,6 +90,25 @@ struct radv_prefix_config
u32 preferred_lifetime;
};
+struct radv_rdnss_config
+{
+ node n;
+ u32 lifetime; /* Valid if lifetime_mult is 0 */
+ u16 lifetime_mult; /* Lifetime specified as multiple of max_ra_int */
+ ip_addr server; /* IP address of recursive DNS server */
+};
+
+struct radv_dnssl_config
+{
+ node n;
+ u32 lifetime; /* Valid if lifetime_mult is 0 */
+ u16 lifetime_mult; /* Lifetime specified as multiple of max_ra_int */
+ u8 dlen_first; /* Length of first label in domain */
+ u8 dlen_all; /* Both dlen_ filled in radv_process_domain() */
+ char *domain; /* Domain for DNS search list, in processed form */
+};
+
+
struct proto_radv
{
struct proto p;
@@ -123,6 +151,7 @@ struct radv_iface
void radv_iface_notify(struct radv_iface *ifa, int event);
/* packets.c */
+int radv_process_domain(struct radv_dnssl_config *cf);
void radv_send_ra(struct radv_iface *ifa, int shutdown);
int radv_sk_open(struct radv_iface *ifa);
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index b41c3f8d..281296a5 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -624,7 +624,6 @@ rip_dump(struct proto *p)
int i;
node *w;
struct rip_interface *rif;
- i = 0;
CHK_MAGIC;
WALK_LIST( w, P->connections ) {
@@ -995,8 +994,8 @@ static int
rip_get_attr(eattr *a, byte *buf, int buflen UNUSED)
{
switch (a->id) {
- case EA_RIP_METRIC: buf += bsprintf( buf, "metric: %d", a->u.data ); return GA_FULL;
- case EA_RIP_TAG: buf += bsprintf( buf, "tag: %d", a->u.data ); return GA_FULL;
+ case EA_RIP_METRIC: bsprintf( buf, "metric: %d", a->u.data ); return GA_FULL;
+ case EA_RIP_TAG: bsprintf( buf, "tag: %d", a->u.data ); return GA_FULL;
default: return GA_UNKNOWN;
}
}