+// 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 "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"
if (stream_get_endp(op->s) != op->length)
/* XXX size_t */
- flog_warn(
- EC_OSPF_MD5,
- "ospf_make_md5_digest: length mismatch stream %lu ospf_packet %u",
- (unsigned long)stream_get_endp(op->s), op->length);
+ flog_warn(EC_OSPF_MD5,
+ "%s: length mismatch stream %lu ospf_packet %u",
+ __func__, (unsigned long)stream_get_endp(op->s),
+ op->length);
return OSPF_AUTH_MD5_SIZE;
}
if (ret < 0)
flog_err(
EC_LIB_SOCKET,
- "*** ospf_write_frags: sendmsg failed to %pI4, id %d, off %d, len %d, mtu %u failed with %s",
- &iph->ip_dst, iph->ip_id, iph->ip_off,
+ "*** %s: sendmsg failed to %pI4, id %d, off %d, len %d, mtu %u failed with %s",
+ __func__, &iph->ip_dst, iph->ip_id, iph->ip_off,
iph->ip_len, mtu, safe_strerror(errno));
if (IS_DEBUG_OSPF_PACKET(type - 1, SEND)) {
- zlog_debug(
- "ospf_write_frags: sent id %d, off %d, len %d to %pI4",
- iph->ip_id, iph->ip_off, iph->ip_len,
- &iph->ip_dst);
+ zlog_debug("%s: sent id %d, off %d, len %d to %pI4",
+ __func__, iph->ip_id, iph->ip_off,
+ iph->ip_len, &iph->ip_dst);
}
iph->ip_off += offset;
if (ospf->fd < 0 || ospf->oi_running == 0) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_write failed to send, fd %d, instance %u",
- ospf->fd, ospf->oi_running);
+ zlog_debug("%s failed to send, fd %d, instance %u",
+ __func__, ospf->fd, ospf->oi_running);
return;
}
sockopt_iphdrincl_swab_systoh(&iph);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_write to %pI4, id %d, off %d, len %d, interface %s, mtu %u:",
- &iph.ip_dst, iph.ip_id, iph.ip_off,
+ "%s to %pI4, id %d, off %d, len %d, interface %s, mtu %u:",
+ __func__, &iph.ip_dst, iph.ip_id, iph.ip_off,
iph.ip_len, oi->ifp->name, oi->ifp->mtu);
/* sendmsg will return EPERM if firewall is blocking sending.
if (ret < 0 && errno != EPERM)
flog_err(
EC_LIB_SOCKET,
- "*** sendmsg in ospf_write failed to %pI4, id %d, off %d, len %d, interface %s, mtu %u: %s",
- &iph.ip_dst, iph.ip_id, iph.ip_off,
+ "*** sendmsg in %s failed to %pI4, id %d, off %d, len %d, interface %s, mtu %u: %s",
+ __func__, &iph.ip_dst, iph.ip_id, iph.ip_off,
iph.ip_len, oi->ifp->name, oi->ifp->mtu,
safe_strerror(errno));
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;
}
break;
}
+ if (length < OSPF_LSA_HEADER_SIZE) {
+ flog_warn(EC_OSPF_PACKET,
+ "Link State Update: LSA length too small.");
+ break;
+ }
+
/* Validate the LSA's LS checksum. */
sum = lsah->checksum;
if (!ospf_lsa_checksum_valid(lsah)) {
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 ((unsigned int)ret < sizeof(struct ip)) {
flog_warn(
EC_OSPF_PACKET,
- "ospf_recv_packet: discarding runt packet of length %d (ip header size is %u)",
- ret, (unsigned int)sizeof(iph));
+ "%s: discarding runt packet of length %d (ip header size is %u)",
+ __func__, ret, (unsigned int)sizeof(iph));
return NULL;
}
if (ret != ip_len) {
flog_warn(
EC_OSPF_PACKET,
- "ospf_recv_packet read length mismatch: ip_len is %d, but recvmsg returned %d",
- ip_len, ret);
+ "%s read length mismatch: ip_len is %d, but recvmsg returned %d",
+ __func__, ip_len, ret);
return NULL;
}
ret = in_cksum(ospfh, ntohs(ospfh->length));
if (ret != sum) {
- zlog_info("ospf_check_sum(): checksum mismatch, my %X, his %X",
- ret, sum);
+ zlog_info("%s: checksum mismatch, my %X, his %X", __func__, ret,
+ sum);
return 0;
}
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("make_hello: options: %x, int: %s", OPTIONS(oi),
+ zlog_debug("%s: options: %x, int: %s", __func__, OPTIONS(oi),
IF_NAME(oi));
/* Set Options. */
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 */
int count = 0;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_make_ls_upd: Start");
+ zlog_debug("%s: Start", __func__);
pp = stream_get_endp(s);
stream_forward_endp(s, OSPF_LS_UPD_MIN_SIZE);
stream_putl_at(s, pp, count);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_make_ls_upd: Stop");
+ zlog_debug("%s: Stop", __func__);
return length;
}
if (!warned) {
flog_warn(
EC_OSPF_LARGE_LSA,
- "ospf_ls_upd_packet_new: oversized LSA encountered!will need to fragment. Not optimal. Try divide up your network with areas. Use 'debug ospf packet send' to see details, or look at 'show ip ospf database ..'");
+ "%s: oversized LSA encountered!will need to fragment. Not optimal. Try divide up your network with areas. Use 'debug ospf packet send' to see details, or look at 'show ip ospf database ..'",
+ __func__);
warned = 1;
}
if (IS_DEBUG_OSPF_PACKET(0, SEND))
zlog_debug(
- "ospf_ls_upd_packet_new: oversized LSA id:%pI4, %d bytes originated by %pI4, will be fragmented!",
- &lsa->data->id,
+ "%s: oversized LSA id:%pI4, %d bytes originated by %pI4, will be fragmented!",
+ __func__, &lsa->data->id,
ntohs(lsa->data->length),
&lsa->data->adv_router);
size = oi->ifp->mtu;
if (size > OSPF_MAX_PACKET_SIZE) {
- flog_warn(EC_OSPF_LARGE_LSA,
- "ospf_ls_upd_packet_new: oversized LSA id:%pI4 too big, %d bytes, packet size %ld, dropping it completely. OSPF routing is broken!",
- &lsa->data->id, ntohs(lsa->data->length),
- (long int)size);
+ flog_warn(
+ EC_OSPF_LARGE_LSA,
+ "%s: oversized LSA id:%pI4 too big, %d bytes, packet size %ld, dropping it completely. OSPF routing is broken!",
+ __func__, &lsa->data->id, ntohs(lsa->data->length),
+ (long int)size);
list_delete_node(update, ln);
return NULL;
}
oi->t_ls_upd_event = NULL;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_ls_upd_send_queue start");
+ zlog_debug("%s start", __func__);
for (rn = route_top(oi->ls_upd_queue); rn; rn = rnext) {
rnext = route_next(rn);
if (again != 0) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_ls_upd_send_queue: update lists not cleared, %d nodes to try again, raising new event",
- again);
+ "%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);
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_ls_upd_send_queue stop");
+ zlog_debug("%s stop", __func__);
}
void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag,
op->length = length;
/* Decide destination address. */
- if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
+ oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS);
else
op->dst.s_addr = dst.s_addr;