+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* OSPF Sending and Receiving OSPF Packets.
* Copyright (C) 1999, 2000 Toshiaki Takada
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "monotime.h"
-#include "thread.h"
+#include "event.h"
#include "memory.h"
#include "linklist.h"
#include "prefix.h"
#include "ospfd/ospf_network.h"
#include "ospfd/ospf_interface.h"
#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_abr.h"
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_lsdb.h"
ck = ospf_crypt_key_lookup(OSPF_IF_PARAM(oi, auth_crypt),
ospfh->u.crypt.key_id);
if (ck == NULL) {
- flog_warn(EC_OSPF_MD5, "interface %s: ospf_check_md5 no key %d",
- IF_NAME(oi), ospfh->u.crypt.key_id);
+ flog_warn(
+ EC_OSPF_MD5,
+ "interface %s: ospf_check_md5 no key %d, Router-ID: %pI4",
+ IF_NAME(oi), ospfh->u.crypt.key_id, &ospfh->router_id);
return 0;
}
&& ntohl(nbr->crypt_seqnum) > ntohl(ospfh->u.crypt.crypt_seqnum)) {
flog_warn(
EC_OSPF_MD5,
- "interface %s: ospf_check_md5 bad sequence %d (expect %d)",
+ "interface %s: ospf_check_md5 bad sequence %d (expect %d), Router-ID: %pI4",
IF_NAME(oi), ntohl(ospfh->u.crypt.crypt_seqnum),
- ntohl(nbr->crypt_seqnum));
+ ntohl(nbr->crypt_seqnum), &ospfh->router_id);
return 0;
}
/* compare the two */
if (memcmp((caddr_t)ospfh + length, digest, OSPF_AUTH_MD5_SIZE)) {
- flog_warn(EC_OSPF_MD5,
- "interface %s: ospf_check_md5 checksum mismatch",
- IF_NAME(oi));
+ flog_warn(
+ EC_OSPF_MD5,
+ "interface %s: ospf_check_md5 checksum mismatch, Router-ID: %pI4",
+ IF_NAME(oi), &ospfh->router_id);
return 0;
}
if (stream_get_endp(op->s) != op->length)
/* XXX size_t */
- flog_warn(EC_OSPF_MD5,
- "%s: length mismatch stream %lu ospf_packet %u",
- __func__, (unsigned long)stream_get_endp(op->s),
- op->length);
+ flog_warn(
+ EC_OSPF_MD5,
+ "%s: length mismatch stream %lu ospf_packet %u, Router-ID %pI4",
+ __func__, (unsigned long)stream_get_endp(op->s),
+ op->length, &ospfh->router_id);
return OSPF_AUTH_MD5_SIZE;
}
-static void ospf_ls_req_timer(struct thread *thread)
+static void ospf_ls_req_timer(struct event *thread)
{
struct ospf_neighbor *nbr;
void ospf_ls_req_event(struct ospf_neighbor *nbr)
{
THREAD_OFF(nbr->t_ls_req);
- thread_add_event(master, ospf_ls_req_timer, nbr, 0, &nbr->t_ls_req);
+ event_add_event(master, ospf_ls_req_timer, nbr, 0, &nbr->t_ls_req);
}
/* Cyclic timer function. Fist registered in ospf_nbr_new () in
ospf_neighbor.c */
-void ospf_ls_upd_timer(struct thread *thread)
+void ospf_ls_upd_timer(struct event *thread)
{
struct ospf_neighbor *nbr;
OSPF_NSM_TIMER_ON(nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
}
-void ospf_ls_ack_timer(struct thread *thread)
+void ospf_ls_ack_timer(struct event *thread)
{
struct ospf_interface *oi;
}
#endif /* WANT_OSPF_WRITE_FRAGMENT */
-static void ospf_write(struct thread *thread)
+static void ospf_write(struct event *thread)
{
struct ospf *ospf = THREAD_ARG(thread);
struct ospf_interface *oi;
/* If packets still remain in queue, call write thread. */
if (!list_isempty(ospf->oi_write_q))
- thread_add_write(master, ospf_write, ospf, ospf->fd,
- &ospf->t_write);
+ event_add_write(master, ospf_write, ospf, ospf->fd,
+ &ospf->t_write);
}
/* OSPF Hello message read -- RFC2328 Section 10.5. */
/* Compare Router Dead Interval. */
if (OSPF_IF_PARAM(oi, v_wait) != ntohl(hello->dead_interval)) {
- flog_warn(EC_OSPF_PACKET,
- "Packet %pI4 [Hello:RECV]: RouterDeadInterval mismatch (expected %u, but received %u).",
- &ospfh->router_id,
- OSPF_IF_PARAM(oi, v_wait),
- ntohl(hello->dead_interval));
+ flog_warn(
+ EC_OSPF_PACKET,
+ "Packet %pI4 [Hello:RECV]: RouterDeadInterval mismatch on %s (expected %u, but received %u).",
+ &ospfh->router_id, IF_NAME(oi),
+ OSPF_IF_PARAM(oi, v_wait), ntohl(hello->dead_interval));
return;
}
!= ntohs(hello->hello_interval)) {
flog_warn(
EC_OSPF_PACKET,
- "Packet %pI4 [Hello:RECV]: HelloInterval mismatch (expected %u, but received %u).",
- &ospfh->router_id,
+ "Packet %pI4 [Hello:RECV]: HelloInterval mismatch on %s (expected %u, but received %u).",
+ &ospfh->router_id, IF_NAME(oi),
OSPF_IF_PARAM(oi, v_hello),
ntohs(hello->hello_interval));
return;
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("Packet %pI4 [Hello:RECV]: Options %s vrf %s",
- &ospfh->router_id,
+ zlog_debug("Packet %pI4 [Hello:RECV]: Options on %s %s vrf %s",
+ &ospfh->router_id, IF_NAME(oi),
ospf_options_dump(hello->options),
ospf_vrf_id_to_name(oi->ospf->vrf_id));
* relationship.
*/
flog_warn(EC_OSPF_PACKET,
- "Packet %pI4 [Hello:RECV]: T-bit on, drop it.",
- &ospfh->router_id);
+ "Packet %pI4 [Hello:RECV]: T-bit ON on %s, drop it.",
+ &ospfh->router_id, IF_NAME(oi));
return;
}
#endif /* REJECT_IF_TBIT_ON */
* the bit should be set in DD packet only.
*/
flog_warn(EC_OSPF_PACKET,
- "Packet %pI4 [Hello:RECV]: O-bit abuse?",
- &ospfh->router_id);
+ "Packet %pI4 [Hello:RECV]: O-bit abuse? on %s",
+ &ospfh->router_id, IF_NAME(oi));
#ifdef STRICT_OBIT_USAGE_CHECK
return; /* Reject this packet. */
#else /* STRICT_OBIT_USAGE_CHECK */
if (IS_OPAQUE_LSA(lsah->type)
&& !CHECK_FLAG(nbr->options, OSPF_OPTION_O)) {
flog_warn(EC_OSPF_PACKET,
- "LSA[Type%d:%pI4]: Opaque capability mismatch?",
- lsah->type, &lsah->id);
+ "LSA[Type%d:%pI4] from %pI4: Opaque capability mismatch?",
+ lsah->type, &lsah->id, &lsah->adv_router);
OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch);
return;
}
continue;
}
} else if (IS_OPAQUE_LSA(lsah->type)) {
- flog_warn(EC_OSPF_PACKET,
- "LSA[Type%d:%pI4]: Opaque capability mismatch?",
- lsah->type, &lsah->id);
+ flog_warn(
+ EC_OSPF_PACKET,
+ "LSA[Type%d:%pI4] from %pI4: Opaque capability mismatch?",
+ lsah->type, &lsah->id, &lsah->adv_router);
continue;
}
if (ospf_flood(oi->ospf, nbr, current, lsa)
< 0) /* Trap NSSA later. */
DISCARD_LSA(lsa, 5);
+
+ /* GR: check for network topology change. */
+ if (ospf->gr_info.restart_in_progress &&
+ ((lsa->data->type == OSPF_ROUTER_LSA ||
+ lsa->data->type == OSPF_NETWORK_LSA)))
+ ospf_gr_check_lsdb_consistency(oi->ospf,
+ oi->area);
+
continue;
}
assert(listcount(lsas) == 0);
list_delete(&lsas);
-
- if (ospf->gr_info.restart_in_progress)
- ospf_gr_check_lsdb_consistency(oi->ospf, oi->area);
}
/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV))
flog_warn(
EC_OSPF_PACKET,
- "interface %s: auth-type mismatch, local %s, rcvd Null",
+ "interface %s: auth-type mismatch, local %s, rcvd Null, Router-ID %pI4",
IF_NAME(oi),
lookup_msg(ospf_auth_type_str,
- iface_auth_type, NULL));
+ iface_auth_type, NULL),
+ &ospfh->router_id);
return 0;
}
if (!ospf_check_sum(ospfh)) {
if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV))
flog_warn(
EC_OSPF_PACKET,
- "interface %s: auth-type mismatch, local %s, rcvd Simple",
+ "interface %s: auth-type mismatch, local %s, rcvd Simple, Router-ID %pI4",
IF_NAME(oi),
lookup_msg(ospf_auth_type_str,
- iface_auth_type, NULL));
+ iface_auth_type, NULL),
+ &ospfh->router_id);
return 0;
}
if (memcmp(OSPF_IF_PARAM(oi, auth_simple), ospfh->u.auth_data,
OSPF_AUTH_SIMPLE_SIZE)) {
if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV))
- flog_warn(EC_OSPF_PACKET,
- "interface %s: Simple auth failed",
- IF_NAME(oi));
+ flog_warn(
+ EC_OSPF_PACKET,
+ "interface %s: Simple auth failed, Router-ID %pI4",
+ IF_NAME(oi), &ospfh->router_id);
return 0;
}
if (!ospf_check_sum(ospfh)) {
if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV))
flog_warn(
EC_OSPF_PACKET,
- "interface %s: auth-type mismatch, local %s, rcvd Cryptographic",
+ "interface %s: auth-type mismatch, local %s, rcvd Cryptographic, Router-ID %pI4",
IF_NAME(oi),
lookup_msg(ospf_auth_type_str,
- iface_auth_type, NULL));
+ iface_auth_type, NULL),
+ &ospfh->router_id);
return 0;
}
if (ospfh->checksum) {
if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV))
flog_warn(
EC_OSPF_PACKET,
- "interface %s: OSPF header checksum is not 0",
- IF_NAME(oi));
+ "interface %s: OSPF header checksum is not 0, Router-ID %pI4",
+ IF_NAME(oi), &ospfh->router_id);
return 0;
}
/* only MD5 crypto method can pass ospf_packet_examin() */
bug? */
!ospf_check_md5_digest(oi, ospfh)) {
if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV))
- flog_warn(EC_OSPF_MD5,
- "interface %s: MD5 auth failed",
- IF_NAME(oi));
+ flog_warn(
+ EC_OSPF_MD5,
+ "interface %s: MD5 auth failed, Router-ID %pI4",
+ IF_NAME(oi), &ospfh->router_id);
return 0;
}
return 1;
if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV))
flog_warn(
EC_OSPF_PACKET,
- "interface %s: invalid packet auth-type (%02x)",
- IF_NAME(oi), pkt_auth_type);
+ "interface %s: invalid packet auth-type (%02x), Router-ID %pI4",
+ IF_NAME(oi), pkt_auth_type, &ospfh->router_id);
return 0;
}
}
}
/* Starting point of packet process function. */
-void ospf_read(struct thread *thread)
+void ospf_read(struct event *thread)
{
struct ospf *ospf;
int32_t count = 0;
ospf = THREAD_ARG(thread);
/* prepare for next packet. */
- thread_add_read(master, ospf_read, ospf, ospf->fd, &ospf->t_read);
+ event_add_read(master, ospf_read, ospf, ospf->fd, &ospf->t_read);
while (count < ospf->write_oi_count) {
count++;
else
stream_putw(s, 0); /* hello-interval of 0 for fast-hellos */
+ /* Check if flood-reduction is enabled,
+ * if yes set the DC bit in the options.
+ */
+ if (OSPF_FR_CONFIG(oi->ospf, oi->area))
+ SET_FLAG(OPTIONS(oi), OSPF_OPTION_DC);
+ else if (CHECK_FLAG(OPTIONS(oi), OSPF_OPTION_DC))
+ UNSET_FLAG(OPTIONS(oi), OSPF_OPTION_DC);
+
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: options: %x, int: %s", __func__, OPTIONS(oi),
IF_NAME(oi));
options = OPTIONS(oi);
if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE))
SET_FLAG(options, OSPF_OPTION_O);
+ if (OSPF_FR_CONFIG(oi->ospf, oi->area))
+ SET_FLAG(options, OSPF_OPTION_DC);
stream_putc(s, options);
/* DD flags */
ospf_hello_send_sub(oi, nbr_nbma->addr.s_addr);
}
-void ospf_poll_timer(struct thread *thread)
+void ospf_poll_timer(struct event *thread)
{
struct ospf_nbr_nbma *nbr_nbma;
}
-void ospf_hello_reply_timer(struct thread *thread)
+void ospf_hello_reply_timer(struct event *thread)
{
struct ospf_neighbor *nbr;
ospf_packet_add(oi, op);
/* Call ospf_write() right away to send ospf packets to neighbors */
if (send_lsupd_now) {
- struct thread os_packet_thd;
+ struct event os_packet_thd;
os_packet_thd.arg = (void *)oi->ospf;
if (oi->on_write_q == 0) {
}
}
-static void ospf_ls_upd_send_queue_event(struct thread *thread)
+static void ospf_ls_upd_send_queue_event(struct event *thread)
{
struct ospf_interface *oi = THREAD_ARG(thread);
struct route_node *rn;
"%s: update lists not cleared, %d nodes to try again, raising new event",
__func__, again);
oi->t_ls_upd_event = NULL;
- thread_add_event(master, ospf_ls_upd_send_queue_event, oi, 0,
- &oi->t_ls_upd_event);
+ event_add_event(master, ospf_ls_upd_send_queue_event, oi, 0,
+ &oi->t_ls_upd_event);
}
if (IS_DEBUG_OSPF_EVENT)
rn->p.u.prefix4, 1);
}
} else
- thread_add_event(master, ospf_ls_upd_send_queue_event, oi, 0,
- &oi->t_ls_upd_event);
+ event_add_event(master, ospf_ls_upd_send_queue_event, oi, 0,
+ &oi->t_ls_upd_event);
}
static void ospf_ls_ack_send_list(struct ospf_interface *oi, struct list *ack,
OSPF_ISM_WRITE_ON(oi->ospf);
}
-static void ospf_ls_ack_send_event(struct thread *thread)
+static void ospf_ls_ack_send_event(struct event *thread)
{
struct ospf_interface *oi = THREAD_ARG(thread);
listnode_add(oi->ls_ack_direct.ls_ack, ospf_lsa_lock(lsa));
- thread_add_event(master, ospf_ls_ack_send_event, oi, 0,
- &oi->t_ls_ack_direct);
+ event_add_event(master, ospf_ls_ack_send_event, oi, 0,
+ &oi->t_ls_ack_direct);
}
/* Send Link State Acknowledgment delayed. */