summaryrefslogtreecommitdiff
path: root/proto/rip
diff options
context:
space:
mode:
Diffstat (limited to 'proto/rip')
-rw-r--r--proto/rip/packets.c19
-rw-r--r--proto/rip/rip.c33
-rw-r--r--proto/rip/rip.h3
3 files changed, 51 insertions, 4 deletions
diff --git a/proto/rip/packets.c b/proto/rip/packets.c
index 8de691af..9c3bd7a3 100644
--- a/proto/rip/packets.c
+++ b/proto/rip/packets.c
@@ -780,6 +780,25 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
}
}
+int
+rip_send_flush(struct rip_proto *p, struct rip_iface *ifa)
+{
+ /* Caller should handle cleanup of pending response */
+ if (ifa->tx_pending)
+ return 0;
+
+ struct rip_packet *pkt = rip_tx_buffer(ifa);
+
+ rip_fill_header(ifa, pkt, RIP_CMD_UPDATE_RESPONSE);
+ rip_fill_update_hdr(pkt, 1, ifa->tx_seqnum);
+
+ /* We suppose that iface is going down, so we do not expect ACK */
+ ifa->tx_seqnum++;
+
+ TRACE(D_PACKETS, "Sending response via %s", ifa->iface->name);
+ return rip_send_to(p, ifa, pkt, rip_pkt_hdrlen(ifa), ifa->tx_addr);
+}
+
static int
rip_send_ack(struct rip_proto *p, struct rip_iface *ifa, uint flush, uint seqnum)
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 80e8d082..25ee16fd 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -550,9 +550,15 @@ rip_iface_stop(struct rip_iface *ifa)
ifa->next_triggered = 0;
ifa->want_triggered = 0;
+ if (ifa->tx_pending)
+ ifa->tx_seqnum++;
+
ifa->tx_pending = 0;
ifa->req_pending = 0;
+ if (ifa->cf->demand_circuit)
+ rip_send_flush(p, ifa);
+
WALK_LIST_FIRST(n, ifa->neigh_list)
rip_remove_neighbor(p, n);
@@ -710,7 +716,8 @@ rip_reconfigure_iface(struct rip_proto *p, struct rip_iface *ifa, struct rip_ifa
(new->port != old->port) ||
(new->tx_tos != old->tx_tos) ||
(new->tx_priority != old->tx_priority) ||
- (new->ttl_security != old->ttl_security))
+ (new->ttl_security != old->ttl_security) ||
+ (new->demand_circuit != old->demand_circuit))
return 0;
TRACE(D_EVENTS, "Reconfiguring interface %s", ifa->iface->name);
@@ -719,7 +726,8 @@ rip_reconfigure_iface(struct rip_proto *p, struct rip_iface *ifa, struct rip_ifa
rip_iface_update_buffers(ifa);
- if (ifa->next_regular > (current_time() + new->update_time))
+ if ((! ifa->cf->demand_circuit) &&
+ (ifa->next_regular > (current_time() + new->update_time)))
ifa->next_regular = current_time() + (random() % new->update_time) + 100 MS;
if (new->check_link != old->check_link)
@@ -1131,6 +1139,20 @@ rip_start(struct proto *P)
}
static int
+rip_shutdown(struct proto *P)
+{
+ struct rip_proto *p = (void *) P;
+
+ TRACE(D_EVENTS, "Shutdown requested");
+
+ struct rip_iface *ifa;
+ WALK_LIST(ifa, p->iface_list)
+ rip_iface_stop(ifa);
+
+ return PS_DOWN;
+}
+
+static int
rip_reconfigure(struct proto *P, struct proto_config *CF)
{
struct rip_proto *p = (void *) P;
@@ -1271,8 +1293,12 @@ rip_dump(struct proto *P)
FIB_WALK(&p->rtable, struct rip_entry, en)
{
debug("RIP: entry #%d: %N via %I dev %s valid %d metric %d age %t\n",
- i++, en->n.addr, en->next_hop, en->iface->name,
+ i++, en->n.addr, en->next_hop, en->iface ? en->iface->name : "(null)",
en->valid, en->metric, current_time() - en->changed);
+
+ for (struct rip_rte *e = en->routes; e; e = e->next)
+ debug("RIP: via %I metric %d expires %t\n",
+ e->next_hop, e->metric, e->expires - current_time());
}
FIB_WALK_END;
@@ -1298,6 +1324,7 @@ struct protocol proto_rip = {
.init = rip_init,
.dump = rip_dump,
.start = rip_start,
+ .shutdown = rip_shutdown,
.reconfigure = rip_reconfigure,
.get_route_info = rip_get_route_info,
.get_attr = rip_get_attr
diff --git a/proto/rip/rip.h b/proto/rip/rip.h
index bf597350..76294624 100644
--- a/proto/rip/rip.h
+++ b/proto/rip/rip.h
@@ -162,7 +162,7 @@ struct rip_entry
u8 valid; /* Entry validity state (RIP_ENTRY_*) */
u8 metric; /* Outgoing route metric */
u16 tag; /* Outgoing route tag */
- struct iface *from; /* Outgoing route from, NULL if from proto */
+ struct iface *from; /* Outgoing route from, NULL if from proto */
struct iface *iface; /* Outgoing route iface (for next hop) */
ip_addr next_hop; /* Outgoing route next hop */
@@ -227,6 +227,7 @@ void rip_show_neighbors(struct proto *P, char *iff);
/* packets.c */
void rip_send_request(struct rip_proto *p, struct rip_iface *ifa);
void rip_send_table(struct rip_proto *p, struct rip_iface *ifa, ip_addr addr, btime changed);
+int rip_send_flush(struct rip_proto *p, struct rip_iface *ifa);
void rip_rxmt_timeout(timer *t);
int rip_open_socket(struct rip_iface *ifa);