diff --git a/proto/rip/packets.c b/proto/rip/packets.c index d8b04317..da6ff2c8 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 0f7f77ac..fb212a9b 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) @@ -1161,6 +1169,20 @@ rip_start(struct proto *P) return PS_UP; } +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) { @@ -1302,8 +1324,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; @@ -1329,6 +1355,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 d7ed7033..24d4e025 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);