#include "stream.h"
#include "log.h"
#include "sockopt.h"
-#include "md5-gnu.h"
+#include "checksum.h"
+#include "md5.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_network.h"
#include "ospfd/ospf_flood.h"
#include "ospfd/ospf_dump.h"
-static void ospf_ls_ack_send_list (struct ospf_interface *, struct list *,
- struct in_addr);
-
/* Packet Type String. */
const char *ospf_packet_type_str[] =
{
"Link State Acknowledgment",
};
-extern int in_cksum (void *ptr, int nbytes);
-
/* OSPF authentication checking function */
-int
+static int
ospf_auth_type (struct ospf_interface *oi)
{
int auth_type;
}
-/* forward output pointer. */
-void
-ospf_output_forward (struct stream *s, int size)
-{
- s->putp += size;
-}
-
struct ospf_packet *
ospf_packet_new (size_t size)
{
fifo->count++;
}
+/* Add new packet to head of fifo. */
+static void
+ospf_fifo_push_head (struct ospf_fifo *fifo, struct ospf_packet *op)
+{
+ op->next = fifo->head;
+
+ if (fifo->tail == NULL)
+ fifo->tail = op;
+
+ fifo->head = op;
+
+ fifo->count++;
+}
+
/* Delete first packet from fifo. */
struct ospf_packet *
ospf_fifo_pop (struct ospf_fifo *fifo)
void
ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
{
+ if (!oi->obuf)
+ {
+ zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
+ "destination %s) called with NULL obuf, ignoring "
+ "(please report this bug)!\n",
+ IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
+ ospf_packet_type_str[stream_getc_from(op->s, 1)],
+ inet_ntoa (op->dst));
+ return;
+ }
+
/* Add packet to end of queue. */
ospf_fifo_push (oi->obuf, op);
/* ospf_fifo_debug (oi->obuf); */
}
+static void
+ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op)
+{
+ if (!oi->obuf)
+ {
+ zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
+ "destination %s) called with NULL obuf, ignoring "
+ "(please report this bug)!\n",
+ IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
+ ospf_packet_type_str[stream_getc_from(op->s, 1)],
+ inet_ntoa (op->dst));
+ return;
+ }
+
+ /* Add packet to head of queue. */
+ ospf_fifo_push_head (oi->obuf, op);
+
+ /* Debug of packet fifo*/
+ /* ospf_fifo_debug (oi->obuf); */
+}
+
void
ospf_packet_delete (struct ospf_interface *oi)
{
ospf_packet_free (op);
}
-struct stream *
-ospf_stream_copy (struct stream *new, struct stream *s)
-{
- new->endp = s->endp;
- new->putp = s->putp;
- new->getp = s->getp;
-
- memcpy (new->data, s->data, stream_get_endp (s));
-
- return new;
-}
-
struct ospf_packet *
ospf_packet_dup (struct ospf_packet *op)
{
struct ospf_packet *new;
if (stream_get_endp(op->s) != op->length)
- zlog_warn ("ospf_packet_dup stream %ld ospf_packet %d size mismatch",
- STREAM_SIZE(op->s), op->length);
+ /* XXX size_t */
+ zlog_warn ("ospf_packet_dup stream %lu ospf_packet %u size mismatch",
+ (u_long)STREAM_SIZE(op->s), op->length);
/* Reserve space for MD5 authentication that may be added later. */
new = ospf_packet_new (stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE);
- ospf_stream_copy (new->s, op->s);
+ stream_copy (new->s, op->s);
new->dst = op->dst;
new->length = op->length;
return new;
}
-unsigned int
+/* XXX inline */
+static inline unsigned int
+ospf_packet_authspace (struct ospf_interface *oi)
+{
+ int auth = 0;
+
+ if ( ospf_auth_type (oi) == OSPF_AUTH_CRYPTOGRAPHIC)
+ auth = OSPF_AUTH_MD5_SIZE;
+
+ return auth;
+}
+
+static unsigned int
ospf_packet_max (struct ospf_interface *oi)
{
int max;
- if ( ospf_auth_type (oi) == OSPF_AUTH_CRYPTOGRAPHIC)
- max = oi->ifp->mtu - OSPF_AUTH_MD5_SIZE;
- else
- max = oi->ifp->mtu;
-
+ max = oi->ifp->mtu - ospf_packet_authspace(oi);
+
max -= (OSPF_HEADER_SIZE + sizeof (struct ip));
return max;
}
\f
-int
+static int
ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
u_int16_t length)
{
unsigned char *ibuf;
- struct md5_ctx ctx;
+ MD5_CTX ctx;
unsigned char digest[OSPF_AUTH_MD5_SIZE];
unsigned char *pdigest;
struct crypt_key *ck;
}
/* Generate a digest for the ospf packet - their digest + our digest. */
- md5_init_ctx (&ctx);
- md5_process_bytes (ibuf, length, &ctx);
- md5_process_bytes (ck->auth_key, OSPF_AUTH_MD5_SIZE, &ctx);
- md5_finish_ctx (&ctx, digest);
+ memset(&ctx, 0, sizeof(ctx));
+ MD5Init(&ctx);
+ MD5Update(&ctx, ibuf, length);
+ MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE);
+ MD5Final(digest, &ctx);
/* compare the two */
if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
/* This function is called from ospf_write(), it will detect the
authentication scheme and if it is MD5, it will change the sequence
and update the MD5 digest. */
-int
+static int
ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
{
struct ospf_header *ospfh;
unsigned char digest[OSPF_AUTH_MD5_SIZE];
- struct md5_ctx ctx;
+ MD5_CTX ctx;
void *ibuf;
- unsigned long oldputp;
u_int32_t t;
struct crypt_key *ck;
- char *auth_key;
+ const u_int8_t *auth_key;
ibuf = STREAM_DATA (op->s);
ospfh = (struct ospf_header *) ibuf;
return 0;
/* We do this here so when we dup a packet, we don't have to
- waste CPU rewriting other headers. */
+ waste CPU rewriting other headers.
+
+ Note that quagga_time /deliberately/ is not used here */
t = (time(NULL) & 0xFFFFFFFF);
- oi->crypt_seqnum = ( t > oi->crypt_seqnum ? t : oi->crypt_seqnum++);
+ if (t > oi->crypt_seqnum)
+ oi->crypt_seqnum = t;
+ else
+ oi->crypt_seqnum++;
+
ospfh->u.crypt.crypt_seqnum = htonl (oi->crypt_seqnum);
/* Get MD5 Authentication key from auth_key list. */
if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
- auth_key = (char *) "";
+ auth_key = (const u_int8_t *) "";
else
{
- ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
- auth_key = (char *) ck->auth_key;
+ ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
+ auth_key = ck->auth_key;
}
/* Generate a digest for the entire packet + our secret key. */
- md5_init_ctx (&ctx);
- md5_process_bytes (ibuf, ntohs (ospfh->length), &ctx);
- md5_process_bytes (auth_key, OSPF_AUTH_MD5_SIZE, &ctx);
- md5_finish_ctx (&ctx, digest);
+ memset(&ctx, 0, sizeof(ctx));
+ MD5Init(&ctx);
+ MD5Update(&ctx, ibuf, ntohs (ospfh->length));
+ MD5Update(&ctx, auth_key, OSPF_AUTH_MD5_SIZE);
+ MD5Final(digest, &ctx);
/* Append md5 digest to the end of the stream. */
- oldputp = stream_get_putp (op->s);
- stream_set_putp (op->s, ntohs (ospfh->length));
stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE);
- stream_set_putp (op->s, oldputp);
/* We do *NOT* increment the OSPF header length. */
op->length = ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE;
if (stream_get_endp(op->s) != op->length)
- zlog_warn("ospf_make_md5_digest: length mismatch stream %ld ospf_packet %d", stream_get_endp(op->s), op->length);
+ /* XXX size_t */
+ zlog_warn("ospf_make_md5_digest: length mismatch stream %lu ospf_packet %u",
+ (u_long)stream_get_endp(op->s), op->length);
return OSPF_AUTH_MD5_SIZE;
}
\f
-int
+static int
ospf_ls_req_timer (struct thread *thread)
{
struct ospf_neighbor *nbr;
struct list *update;
struct ospf_lsdb *lsdb;
int i;
- struct timeval now;
int retransmit_interval;
- gettimeofday (&now, NULL);
retransmit_interval = OSPF_IF_PARAM (nbr->oi, retransmit_interval);
lsdb = &nbr->ls_rxmt;
fired. This is a small tweak to what is in the RFC,
but it will cut out out a lot of retransmit traffic
- MAG */
- if (tv_cmp (tv_sub (now, lsa->tv_recv),
+ if (tv_cmp (tv_sub (recent_relative_time (), lsa->tv_recv),
int2tv (retransmit_interval)) >= 0)
listnode_add (update, rn->info);
}
}
#ifdef WANT_OSPF_WRITE_FRAGMENT
-void
+static void
ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph,
struct msghdr *msg, unsigned int maxdatasize,
unsigned int mtu, int flags, u_char type)
if (ret < 0)
zlog_warn ("*** ospf_write_frags: sendmsg failed to %s,"
- " id %d, off %d, len %d failed with %s",
- inet_ntoa (iph->ip_dst),
- iph->ip_id,
- iph->ip_off,
- iph->ip_len,
- strerror (errno));
+ " id %d, off %d, len %d, mtu %u failed with %s",
+ inet_ntoa (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_info ("ospf_write_frags: sent id %d, off %d, len %d to %s\n",
+ zlog_debug ("ospf_write_frags: sent id %d, off %d, len %d to %s\n",
iph->ip_id, iph->ip_off, iph->ip_len,
inet_ntoa (iph->ip_dst));
if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
{
- zlog_info ("-----------------IP Header Dump----------------------");
+ zlog_debug ("-----------------IP Header Dump----------------------");
ospf_ip_header_dump (iph);
- zlog_info ("-----------------------------------------------------");
+ zlog_debug ("-----------------------------------------------------");
}
}
iph->ip_off += offset;
- stream_forward (op->s, iovp->iov_len);
+ stream_forward_getp (op->s, iovp->iov_len);
iovp->iov_base = STREAM_PNT (op->s);
}
}
#endif /* WANT_OSPF_WRITE_FRAGMENT */
-int
+static int
ospf_write (struct thread *thread)
{
struct ospf *ospf = THREAD_ARG (thread);
node = listhead (ospf->oi_write_q);
assert (node);
- oi = getdata (node);
+ oi = listgetdata (node);
assert (oi);
#ifdef WANT_OSPF_WRITE_FRAGMENT
ipid = (time(NULL) & 0xffff);
#endif /* WANT_OSPF_WRITE_FRAGMENT */
- /* convenience - max OSPF data per packet */
- maxdatasize = oi->ifp->mtu - sizeof (struct ip);
+ /* convenience - max OSPF data per packet,
+ * and reliability - not more data, than our
+ * socket can accept
+ */
+ maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) -
+ sizeof (struct ip);
/* Get one packet from queue. */
op = ospf_fifo_head (oi->obuf);
memset (&sa_dst, 0, sizeof (sa_dst));
sa_dst.sin_family = AF_INET;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
sa_dst.sin_len = sizeof(sa_dst);
-#endif /* HAVE_SIN_LEN */
+#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
sa_dst.sin_addr = op->dst;
sa_dst.sin_port = htons (0);
iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
+#if defined(__DragonFly__)
+ /*
+ * DragonFly's raw socket expects ip_len/ip_off in network byte order.
+ */
+ iph.ip_len = htons(iph.ip_len);
+#endif
+
#ifdef WANT_OSPF_WRITE_FRAGMENT
/* XXX-MT: not thread-safe at all..
* XXX: this presumes this is only programme sending OSPF packets
sockopt_iphdrincl_swab_systoh (&iph);
if (ret < 0)
- zlog_warn ("*** sendmsg in ospf_write to %s failed with %s",
- inet_ntoa (iph.ip_dst), strerror (errno));
+ zlog_warn ("*** sendmsg in ospf_write failed to %s, "
+ "id %d, off %d, len %d, interface %s, mtu %u: %s",
+ inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
+ oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
/* Show debug sending packet. */
if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
{
if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
{
- zlog_info ("-----------------------------------------------------");
+ zlog_debug ("-----------------------------------------------------");
ospf_ip_header_dump (&iph);
stream_set_getp (op->s, 0);
ospf_packet_dump (op->s);
}
- zlog_info ("%s sent to [%s] via [%s].",
+ zlog_debug ("%s sent to [%s] via [%s].",
ospf_packet_type_str[type], inet_ntoa (op->dst),
IF_NAME (oi));
if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
- zlog_info ("-----------------------------------------------------");
+ zlog_debug ("-----------------------------------------------------");
}
/* Now delete packet from queue. */
}
/* OSPF Hello message read -- RFC2328 Section 10.5. */
-void
+static void
ospf_hello (struct ip *iph, struct ospf_header *ospfh,
struct stream * s, struct ospf_interface *oi, int size)
{
{
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
{
- zlog_info ("ospf_header[%s/%s]: selforiginated, "
+ zlog_debug ("ospf_header[%s/%s]: selforiginated, "
"dropping.",
ospf_packet_type_str[ospfh->type],
inet_ntoa (iph->ip_src));
return;
}
- /* If incoming interface is passive one, ignore Hello. */
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) {
- zlog_info ("Packet %s [HELLO:RECV]: oi is passive",
- inet_ntoa (ospfh->router_id));
- return;
- }
-
/* get neighbor prefix. */
p.family = AF_INET;
p.prefixlen = ip_masklen (hello->network_mask);
&& oi->type != OSPF_IFTYPE_VIRTUALLINK)
if (oi->address->prefixlen != p.prefixlen)
{
- zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch.",
- inet_ntoa (ospfh->router_id));
+ zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch on %s (configured prefix length is %d, but hello packet indicates %d).",
+ inet_ntoa(ospfh->router_id), IF_NAME(oi),
+ (int)oi->address->prefixlen, (int)p.prefixlen);
return;
}
- /* Compare Hello Interval. */
- if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
- {
- zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch.",
- inet_ntoa (ospfh->router_id));
- return;
- }
-
/* Compare Router Dead Interval. */
if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval))
{
- zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch.",
- inet_ntoa (ospfh->router_id));
+ zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch "
+ "(expected %u, but received %u).",
+ inet_ntoa(ospfh->router_id),
+ OSPF_IF_PARAM(oi, v_wait), ntohl(hello->dead_interval));
return;
}
+ /* Compare Hello Interval - ignored if fast-hellos are set. */
+ if (OSPF_IF_PARAM (oi, fast_hello) == 0)
+ {
+ if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
+ {
+ zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch "
+ "(expected %u, but received %u).",
+ inet_ntoa(ospfh->router_id),
+ OSPF_IF_PARAM(oi, v_hello), ntohs(hello->hello_interval));
+ return;
+ }
+ }
+
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("Packet %s [Hello:RECV]: Options %s",
+ zlog_debug ("Packet %s [Hello:RECV]: Options %s",
inet_ntoa (ospfh->router_id),
ospf_options_dump (hello->options));
return;
}
if (IS_DEBUG_OSPF_NSSA)
- zlog_info ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id));
+ zlog_debug ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id));
}
else
/* The setting of the E-bit found in the Hello Packet's Options
if (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) !=
CHECK_FLAG (hello->options, OSPF_OPTION_E))
{
- zlog_warn ("Packet[Hello:RECV]: my options: %x, his options %x",
- OPTIONS (oi), hello->options);
+ zlog_warn ("Packet %s [Hello:RECV]: my options: %x, his options %x",
+ inet_ntoa(ospfh->router_id), OPTIONS (oi), hello->options);
return;
}
old_state = nbr->state;
/* Add event to thread. */
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
/* RFC2328 Section 9.5.1
If the router is not eligible to become Designated Router,
if (oi->type == OSPF_IFTYPE_NBMA &&
(old_state == NSM_Down || old_state == NSM_Attempt))
{
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
nbr->priority = hello->priority;
nbr->d_router = hello->d_router;
nbr->bd_router = hello->bd_router;
if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors,
size - OSPF_HELLO_MIN_SIZE))
{
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_TwoWayReceived);
nbr->options |= hello->options;
}
else
{
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
/* Set neighbor information. */
nbr->priority = hello->priority;
nbr->d_router = hello->d_router;
}
/* Save DD flags/options/Seqnum received. */
-void
+static void
ospf_db_desc_save_current (struct ospf_neighbor *nbr,
struct ospf_db_desc *dd)
{
struct ospf_lsa *new, *find;
struct lsa_header *lsah;
- stream_forward (s, OSPF_DB_DESC_MIN_SIZE);
+ stream_forward_getp (s, OSPF_DB_DESC_MIN_SIZE);
for (size -= OSPF_DB_DESC_MIN_SIZE;
size >= OSPF_LSA_HEADER_SIZE; size -= OSPF_LSA_HEADER_SIZE)
{
lsah = (struct lsa_header *) STREAM_PNT (s);
- stream_forward (s, OSPF_LSA_HEADER_SIZE);
+ stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
/* Unknown LS type. */
if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
{
- zlog_warn ("Pakcet [DD:RECV]: Unknown LS type %d.", lsah->type);
+ zlog_warn ("Packet [DD:RECV]: Unknown LS type %d.", lsah->type);
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
return;
}
/* Lookup received LSA, then add LS request list. */
find = ospf_lsa_lookup_by_header (oi->area, lsah);
- if (!find || ospf_lsa_more_recent (find, new) < 0)
- {
- ospf_ls_request_add (nbr, new);
- ospf_lsa_discard (new);
- }
- else
- {
- /* Received LSA is not recent. */
- if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("Packet [DD:RECV]: LSA received Type %d, "
- "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
- ospf_lsa_discard (new);
- continue;
- }
+
+ /* ospf_lsa_more_recent is fine with NULL pointers */
+ switch (ospf_lsa_more_recent (find, new))
+ {
+ case -1:
+ /* Neighbour has a more recent LSA, we must request it */
+ ospf_ls_request_add (nbr, new);
+ case 0:
+ /* If we have a copy of this LSA, it's either less recent
+ * and we're requesting it from neighbour (the case above), or
+ * it's as recent and we both have same copy (this case).
+ *
+ * In neither of these two cases is there any point in
+ * describing our copy of the LSA to the neighbour in a
+ * DB-Summary packet, if we're still intending to do so.
+ *
+ * See: draft-ogier-ospf-dbex-opt-00.txt, describing the
+ * backward compatible optimisation to OSPF DB Exchange /
+ * DB Description process implemented here.
+ */
+ if (find)
+ ospf_lsdb_delete (&nbr->db_sum, find);
+ ospf_lsa_discard (new);
+ break;
+ default:
+ /* We have the more recent copy, nothing specific to do:
+ * - no need to request neighbours stale copy
+ * - must leave DB summary list copy alone
+ */
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("Packet [DD:RECV]: LSA received Type %d, "
+ "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
+ ospf_lsa_discard (new);
+ }
}
/* Master */
if (IS_SET_DD_MS (nbr->dd_flags))
{
nbr->dd_seqnum++;
- /* Entire DD packet sent. */
+
+ /* Both sides have no More, then we're done with Exchange */
if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
else
- /* Send new DD packet. */
ospf_db_desc_send (nbr);
}
/* Slave */
{
nbr->dd_seqnum = ntohl (dd->dd_seqnum);
- /* When master's more flags is not set. */
- if (!IS_SET_DD_M (dd->flags) && ospf_db_summary_isempty (nbr))
- {
- nbr->dd_flags &= ~(OSPF_DD_FLAG_M);
- OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
- }
-
- /* Send DD pakcet in reply. */
+ /* Send DD packet in reply.
+ *
+ * Must be done to acknowledge the Master's DD, regardless of
+ * whether we have more LSAs ourselves to describe.
+ *
+ * This function will clear the 'More' bit, if after this DD
+ * we have no more LSAs to describe to the master..
+ */
ospf_db_desc_send (nbr);
+
+ /* Slave can raise ExchangeDone now, if master is also done */
+ if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
}
-
+
/* Save received neighbor values from DD. */
ospf_db_desc_save_current (nbr, dd);
}
-int
+static int
ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr)
{
/* Is DD duplicated? */
}
/* OSPF Database Description message read -- RFC2328 Section 10.6. */
-void
+static void
ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
struct stream *s, struct ospf_interface *oi, u_int16_t size)
{
}
/* Check MTU. */
- if (ntohs (dd->mtu) > oi->ifp->mtu)
+ if ((OSPF_IF_PARAM (oi, mtu_ignore) == 0) &&
+ (ntohs (dd->mtu) > oi->ifp->mtu))
{
- zlog_warn ("Packet[DD]: MTU is larger than [%s]'s MTU", IF_NAME (oi));
+ zlog_warn ("Packet[DD]: Neighbor %s MTU %u is larger than [%s]'s MTU %u",
+ inet_ntoa (nbr->router_id), ntohs (dd->mtu),
+ IF_NAME (oi), oi->ifp->mtu);
return;
}
&& (!CHECK_FLAG (dd->options, OSPF_OPTION_NP)) )
{
if (IS_DEBUG_OSPF_EVENT)
- zlog_notice ("Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options",
+ zlog_debug ("Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options",
inet_ntoa (nbr->router_id) );
SET_FLAG (dd->options, OSPF_OPTION_NP);
}
}
#endif /* HAVE_OPAQUE_LSA */
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Process DD packet by neighbor status. */
switch (nbr->state)
{
case NSM_Down:
case NSM_Attempt:
case NSM_TwoWay:
- zlog_warn ("Packet[DD]: Neighbor state is %s, packet discarded.",
+ zlog_warn ("Packet[DD]: Neighbor %s state is %s, packet discarded.",
+ inet_ntoa(nbr->router_id),
LOOKUP (ospf_nsm_state_msg, nbr->state));
break;
case NSM_Init:
if (IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) > 0)
{
/* We're Slave---obey */
- zlog_warn ("Packet[DD]: Negotiation done (Slave).");
+ zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Slave).",
+ inet_ntoa(nbr->router_id));
nbr->dd_seqnum = ntohl (dd->dd_seqnum);
- nbr->dd_flags &= ~(OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I); /* Reset I/MS */
+
+ /* Reset I/MS */
+ UNSET_FLAG (nbr->dd_flags, (OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I));
}
else
{
/* We're Master, ignore the initial DBD from Slave */
- zlog_warn ("Packet[DD]: Initial DBD from Slave, ignoring.");
+ zlog_info ("Packet[DD]: Neighbor %s: Initial DBD from Slave, "
+ "ignoring.", inet_ntoa(nbr->router_id));
break;
}
}
ntohl (dd->dd_seqnum) == nbr->dd_seqnum &&
IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) < 0)
{
- zlog_warn ("Packet[DD]: Negotiation done (Master).");
- nbr->dd_flags &= ~OSPF_DD_FLAG_I;
+ zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Master).",
+ inet_ntoa(nbr->router_id));
+ /* Reset I, leaving MS */
+ UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_I);
}
else
{
- zlog_warn ("Packet[DD]: Negotiation fails.");
+ zlog_warn ("Packet[DD]: Neighbor %s Negotiation fails.",
+ inet_ntoa(nbr->router_id));
break;
}
if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
{
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("Neighbor[%s] is %sOpaque-capable.",
+ zlog_debug ("Neighbor[%s] is %sOpaque-capable.",
inet_ntoa (nbr->router_id),
CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT ");
if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O)
&& IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))
{
- zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; Opaque-LSAs cannot be reliably advertised in this network.", inet_ntoa (nbr->router_id));
+ zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; "
+ "Opaque-LSAs cannot be reliably advertised "
+ "in this network.",
+ inet_ntoa (nbr->router_id));
/* This situation is undesirable, but not a real error. */
}
}
{
if (IS_SET_DD_MS (nbr->dd_flags))
/* Master: discard duplicated DD packet. */
- zlog_warn ("Packet[DD] (Master): packet duplicated.");
+ zlog_info ("Packet[DD] (Master): Neighbor %s packet duplicated.",
+ inet_ntoa (nbr->router_id));
else
/* Slave: cause to retransmit the last Database Description. */
{
- zlog_warn ("Packet[DD] [Slave]: packet duplicated.");
+ zlog_info ("Packet[DD] [Slave]: Neighbor %s packet duplicated.",
+ inet_ntoa (nbr->router_id));
ospf_db_desc_resend (nbr);
}
break;
/* Check Master/Slave bit mismatch */
if (IS_SET_DD_MS (dd->flags) != IS_SET_DD_MS (nbr->last_recv.flags))
{
- zlog_warn ("Packet[DD]: MS-bit mismatch.");
+ zlog_warn ("Packet[DD]: Neighbor %s MS-bit mismatch.",
+ inet_ntoa(nbr->router_id));
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",
- dd->flags, nbr->dd_flags);
+ zlog_debug ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",
+ dd->flags, nbr->dd_flags);
break;
}
/* Check initialize bit is set. */
if (IS_SET_DD_I (dd->flags))
{
- zlog_warn ("Packet[DD]: I-bit set.");
+ zlog_info ("Packet[DD]: Neighbor %s I-bit set.",
+ inet_ntoa(nbr->router_id));
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
break;
}
/* Save the new options for debugging */
nbr->options = dd->options;
#endif /* ORIGINAL_CODING */
- zlog_warn ("Packet[DD]: options mismatch.");
+ zlog_warn ("Packet[DD]: Neighbor %s options mismatch.",
+ inet_ntoa(nbr->router_id));
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
break;
}
(!IS_SET_DD_MS (nbr->dd_flags) &&
ntohl (dd->dd_seqnum) != nbr->dd_seqnum + 1))
{
- zlog_warn ("Pakcet[DD]: sequence number mismatch.");
+ zlog_warn ("Packet[DD]: Neighbor %s sequence number mismatch.",
+ inet_ntoa(nbr->router_id));
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
break;
}
if (IS_SET_DD_MS (nbr->dd_flags))
{
/* Master should discard duplicate DD packet. */
- zlog_warn ("Pakcet[DD]: duplicated, packet discarded.");
+ zlog_info ("Packet[DD]: Neighbor %s duplicated, "
+ "packet discarded.",
+ inet_ntoa(nbr->router_id));
break;
}
else
{
struct timeval t, now;
- gettimeofday (&now, NULL);
+ quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
t = tv_sub (now, nbr->last_send_ts);
if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0)
{
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
break;
default:
- zlog_warn ("Packet[DD]: NSM illegal status.");
+ zlog_warn ("Packet[DD]: Neighbor %s NSM illegal status %u.",
+ inet_ntoa(nbr->router_id), nbr->state);
break;
}
}
#define OSPF_LSA_KEY_SIZE 12 /* type(4) + id(4) + ar(4) */
/* OSPF Link State Request Read -- RFC2328 Section 10.7. */
-void
+static void
ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
struct stream *s, struct ospf_interface *oi, u_int16_t size)
{
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Neighbor State should be Exchange or later. */
if (nbr->state != NSM_Exchange &&
nbr->state != NSM_Loading &&
nbr->state != NSM_Full)
{
- zlog_warn ("Link State Request: Neighbor state is %s, packet discarded.",
+ zlog_warn ("Link State Request received from %s: "
+ "Neighbor state is %s, packet discarded.",
+ inet_ntoa (ospfh->router_id),
LOOKUP (ospf_nsm_state_msg, nbr->state));
return;
}
return;
}
- /* Packet overflows MTU size, send immediatly. */
- if (length + ntohs (find->data->length) > OSPF_PACKET_MAX (oi))
+ /* Packet overflows MTU size, send immediately. */
+ if (length + ntohs (find->data->length) > ospf_packet_max (oi))
{
if (oi->type == OSPF_IFTYPE_NBMA)
ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */
for (; size >= OSPF_LSA_HEADER_SIZE && count > 0;
- size -= length, stream_forward (s, length), count--)
+ size -= length, stream_forward_getp (s, length), count--)
{
lsah = (struct lsa_header *) STREAM_PNT (s);
length = ntohs (lsah->length);
&& nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
{
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id));
+ zlog_debug ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id));
continue;
}
}
memcpy (lsa->data, lsah, length);
if (IS_DEBUG_OSPF_EVENT)
- zlog_info("LSA[Type%d:%s]: %p new LSA created with Link State Update",
+ zlog_debug("LSA[Type%d:%s]: %p new LSA created with Link State Update",
lsa->data->type, inet_ntoa (lsa->data->id), lsa);
listnode_add (lsas, lsa);
}
}
/* Cleanup Update list. */
-void
+static void
ospf_upd_list_clean (struct list *lsas)
{
- struct listnode *node;
+ struct listnode *node, *nnode;
struct ospf_lsa *lsa;
- for (node = listhead (lsas); node; nextnode (node))
- if ((lsa = getdata (node)) != NULL)
- ospf_lsa_discard (lsa);
+ for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
+ ospf_lsa_discard (lsa);
list_delete (lsas);
}
/* OSPF Link State Update message read -- RFC2328 Section 13. */
-void
+static void
ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
struct stream *s, struct ospf_interface *oi, u_int16_t size)
{
struct ospf_neighbor *nbr;
struct list *lsas;
-#ifdef HAVE_OPAQUE_LSA
- struct list *mylsa_acks, *mylsa_upds;
-#endif /* HAVE_OPAQUE_LSA */
- struct listnode *node, *next;
+ struct listnode *node, *nnode;
struct ospf_lsa *lsa = NULL;
/* unsigned long ls_req_found = 0; */
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Check neighbor state. */
if (nbr->state < NSM_Exchange)
{
- zlog_warn ("Link State Update: Neighbor[%s] state is less than Exchange",
- inet_ntoa (ospfh->router_id));
+ zlog_warn ("Link State Update: "
+ "Neighbor[%s] state %s is less than Exchange",
+ inet_ntoa (ospfh->router_id),
+ LOOKUP(ospf_nsm_state_msg, nbr->state));
return;
}
lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);
#ifdef HAVE_OPAQUE_LSA
- /*
- * Prepare two kinds of lists to clean up unwanted self-originated
- * Opaque-LSAs from the routing domain as soon as possible.
- */
- mylsa_acks = list_new (); /* Let the sender cease retransmission. */
- mylsa_upds = list_new (); /* Flush target LSAs if necessary. */
-
/*
* If self-originated Opaque-LSAs that have flooded before restart
* are contained in the received LSUpd message, corresponding LSReq
* updating for the same LSA would take place alternately, this trick
* must be done before entering to the loop below.
*/
+ /* XXX: Why is this Opaque specific? Either our core code is deficient
+ * and this should be fixed generally, or Opaque is inventing strawman
+ * problems */
ospf_opaque_adjust_lsreq (nbr, lsas);
#endif /* HAVE_OPAQUE_LSA */
#define DISCARD_LSA(L,N) {\
if (IS_DEBUG_OSPF_EVENT) \
- zlog_info ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \
+ zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \
ospf_lsa_discard (L); \
continue; }
/* Process each LSA received in the one packet. */
- for (node = listhead (lsas); node; node = next)
+ for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
{
struct ospf_lsa *ls_ret, *current;
int ret = 1;
- next = node->next;
-
- lsa = getdata (node);
-
if (IS_DEBUG_OSPF_NSSA)
{
char buf1[INET_ADDRSTRLEN];
char buf2[INET_ADDRSTRLEN];
char buf3[INET_ADDRSTRLEN];
- zlog_info("LSA Type-%d from %s, ID: %s, ADV: %s",
+ zlog_debug("LSA Type-%d from %s, ID: %s, ADV: %s",
lsa->data->type,
inet_ntop (AF_INET, &ospfh->router_id,
buf1, INET_ADDRSTRLEN),
/* Reject from STUB or NSSA */
if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
{
- DISCARD_LSA (lsa, 1);
if (IS_DEBUG_OSPF_NSSA)
- zlog_info("Incoming External LSA Discarded: We are NSSA/STUB Area");
+ zlog_debug("Incoming External LSA Discarded: We are NSSA/STUB Area");
+ DISCARD_LSA (lsa, 1);
}
if (lsa->data->type == OSPF_AS_NSSA_LSA)
if (nbr->oi->area->external_routing != OSPF_AREA_NSSA)
{
- DISCARD_LSA (lsa,2);
if (IS_DEBUG_OSPF_NSSA)
- zlog_info("Incoming NSSA LSA Discarded: Not NSSA Area");
+ zlog_debug("Incoming NSSA LSA Discarded: Not NSSA Area");
+ DISCARD_LSA (lsa,2);
}
/* Find the LSA in the current database. */
ospf_ls_ack_send (nbr, lsa);
/* Discard LSA. */
- zlog_warn ("Link State Update: LS age is equal to MaxAge.");
+ zlog_info ("Link State Update[%s]: LS age is equal to MaxAge.",
+ dump_lsa_key(lsa));
DISCARD_LSA (lsa, 3);
}
* Otherwise, the LSA instance remains in the routing domain
* until its age reaches to MaxAge.
*/
+ /* XXX: We should deal with this for *ALL* LSAs, not just opaque */
if (current == NULL)
{
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("LSA[%s]: Previously originated Opaque-LSA, not found in the LSDB.", dump_lsa_key (lsa));
+ zlog_debug ("LSA[%s]: Previously originated Opaque-LSA,"
+ "not found in the LSDB.", dump_lsa_key (lsa));
SET_FLAG (lsa->flags, OSPF_LSA_SELF);
- listnode_add (mylsa_upds, ospf_lsa_dup (lsa));
- listnode_add (mylsa_acks, ospf_lsa_lock (lsa));
+
+ ospf_opaque_self_originated_lsa_received (nbr, lsa);
+ ospf_ls_ack_send (nbr, lsa);
+
continue;
}
}
#endif /* HAVE_OPAQUE_LSA */
+
/* It might be happen that received LSA is self-originated network LSA, but
* router ID is cahnged. So, we should check if LSA is a network-LSA whose
* Link State ID is one of the router's own IP interface addresses but whose
if(lsa->data->type == OSPF_NETWORK_LSA)
{
- struct listnode *oi_node;
+ struct listnode *oinode, *oinnode;
+ struct ospf_interface *out_if;
int Flag = 0;
- for(oi_node = listhead(oi->ospf->oiflist); oi_node; oi_node = nextnode(oi_node))
+ for (ALL_LIST_ELEMENTS (oi->ospf->oiflist, oinode, oinnode, out_if))
{
- struct ospf_interface *out_if = getdata(oi_node);
if(out_if == NULL)
break;
{
ospf_lsa_flush_area(lsa,out_if->area);
if(IS_DEBUG_OSPF_EVENT)
- zlog_info ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d",
+ zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d",
lsa, (int) lsa->data->type);
ospf_lsa_discard (lsa);
Flag = 1;
if (ospf_ls_request_lookup (nbr, lsa))
{
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
- zlog_warn ("LSA instance exists on Link state request list");
+ zlog_warn("LSA[%s] instance exists on Link state request list",
+ dump_lsa_key(lsa));
/* Clean list of LSAs. */
ospf_upd_list_clean (lsas);
/* this lsa is not on lsas list already. */
ospf_lsa_discard (lsa);
-#ifdef HAVE_OPAQUE_LSA
- list_delete (mylsa_acks);
- list_delete (mylsa_upds);
-#endif /* HAVE_OPAQUE_LSA */
return;
}
{
struct timeval now;
- gettimeofday (&now, NULL);
+ quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
if (tv_cmp (tv_sub (now, current->tv_orig),
- int2tv (OSPF_MIN_LS_ARRIVAL)) > 0)
+ int2tv (OSPF_MIN_LS_ARRIVAL)) >= 0)
/* Trap NSSA type later.*/
ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
DISCARD_LSA (lsa, 8);
}
}
}
-
-#ifdef HAVE_OPAQUE_LSA
- /*
- * Now that previously originated Opaque-LSAs those which not yet
- * installed into LSDB are captured, take several steps to clear
- * them completely from the routing domain, before proceeding to
- * origination for the current target Opaque-LSAs.
- */
- while (listcount (mylsa_acks) > 0)
- ospf_ls_ack_send_list (oi, mylsa_acks, nbr->address.u.prefix4);
-
- if (listcount (mylsa_upds) > 0)
- ospf_opaque_self_originated_lsa_received (nbr, mylsa_upds);
-
- list_delete (mylsa_upds);
- list_delete (mylsa_acks);
-#endif /* HAVE_OPAQUE_LSA */
+#undef DISCARD_LSA
assert (listcount (lsas) == 0);
list_delete (lsas);
}
/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
-void
+static void
ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
struct stream *s, struct ospf_interface *oi, u_int16_t size)
{
struct ospf_neighbor *nbr;
-#ifdef HAVE_OPAQUE_LSA
- struct list *opaque_acks;
-#endif /* HAVE_OPAQUE_LSA */
-
+
/* increment statistics. */
oi->ls_ack_in++;
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
if (nbr->state < NSM_Exchange)
{
- zlog_warn ("Link State Acknowledgment: State is less than Exchange.");
+ zlog_warn ("Link State Acknowledgment: "
+ "Neighbor[%s] state %s is less than Exchange",
+ inet_ntoa (ospfh->router_id),
+ LOOKUP(ospf_nsm_state_msg, nbr->state));
return;
}
-
-#ifdef HAVE_OPAQUE_LSA
- opaque_acks = list_new ();
-#endif /* HAVE_OPAQUE_LSA */
-
+
while (size >= OSPF_LSA_HEADER_SIZE)
{
struct ospf_lsa *lsa, *lsr;
/* lsah = (struct lsa_header *) STREAM_PNT (s); */
size -= OSPF_LSA_HEADER_SIZE;
- stream_forward (s, OSPF_LSA_HEADER_SIZE);
+ stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA)
{
if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
{
#ifdef HAVE_OPAQUE_LSA
- /* Keep this LSA entry for later reference. */
if (IS_OPAQUE_LSA (lsr->data->type))
- listnode_add (opaque_acks, ospf_lsa_dup (lsr));
+ ospf_opaque_ls_ack_received (nbr, lsr);
#endif /* HAVE_OPAQUE_LSA */
ospf_ls_retransmit_delete (nbr, lsr);
ospf_lsa_discard (lsa);
}
-#ifdef HAVE_OPAQUE_LSA
- if (listcount (opaque_acks) > 0)
- ospf_opaque_ls_ack_received (nbr, opaque_acks);
-
- list_delete (opaque_acks);
return;
-#endif /* HAVE_OPAQUE_LSA */
}
\f
-struct stream *
-ospf_recv_packet (int fd, struct interface **ifp)
+static struct stream *
+ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)
{
int ret;
- struct ip iph;
+ struct ip *iph;
u_int16_t ip_len;
- struct stream *ibuf;
unsigned int ifindex = 0;
struct iovec iov;
-#if defined(CMSG_SPACE)
/* Header and data both require alignment. */
char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
-#else
- char buff [sizeof (struct cmsghdr) + SOPT_SIZE_CMSG_IFINDEX_IPV4()];
-#endif
struct msghdr msgh;
memset (&msgh, 0, sizeof (struct msghdr));
msgh.msg_control = (caddr_t) buff;
msgh.msg_controllen = sizeof (buff);
- ret = recvfrom (fd, (void *)&iph, sizeof (iph), MSG_PEEK, NULL, 0);
-
- if (ret != sizeof (iph))
+ ret = stream_recvmsg (ibuf, fd, &msgh, 0, OSPF_MAX_PACKET_SIZE+1);
+ if (ret < 0)
{
- zlog_warn ("ospf_recv_packet packet smaller than ip header");
+ zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
+ return NULL;
+ }
+ if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */
+ {
+ zlog_warn("ospf_recv_packet: discarding runt packet of length %d "
+ "(ip header size is %u)",
+ ret, (u_int)sizeof(iph));
return NULL;
}
- sockopt_iphdrincl_swab_systoh (&iph);
+ /* Note that there should not be alignment problems with this assignment
+ because this is at the beginning of the stream data buffer. */
+ iph = (struct ip *) STREAM_DATA(ibuf);
+ sockopt_iphdrincl_swab_systoh (iph);
- ip_len = iph.ip_len;
+ ip_len = iph->ip_len;
#if !defined(GNU_LINUX) && (OpenBSD < 200311)
/*
*
* For more details, see <netinet/ip_input.c>.
*/
- ip_len = ip_len + (iph.ip_hl << 2);
+ ip_len = ip_len + (iph->ip_hl << 2);
#endif
- ibuf = stream_new (ip_len);
- iov.iov_base = STREAM_DATA (ibuf);
- iov.iov_len = ip_len;
- ret = recvmsg (fd, &msgh, 0);
-
+#if defined(__DragonFly__)
+ /*
+ * in DragonFly's raw socket, ip_len/ip_off are read
+ * in network byte order.
+ * As OpenBSD < 200311 adjust ip_len to strip IP header size!
+ */
+ ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2);
+#endif
+
ifindex = getsockopt_ifindex (AF_INET, &msgh);
*ifp = if_lookup_by_index (ifindex);
if (ret != ip_len)
{
- zlog_warn ("ospf_recv_packet short read. "
- "ip_len %d bytes read %d", ip_len, ret);
- stream_free (ibuf);
+ zlog_warn ("ospf_recv_packet read length mismatch: ip_len is %d, "
+ "but recvmsg returned %d", ip_len, ret);
return NULL;
}
return ibuf;
}
-struct ospf_interface *
+static struct ospf_interface *
ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
struct ip *iph, struct ospf_header *ospfh)
{
iph->ip_dst)) == NULL)
return NULL;
- for (node = listhead (ospf->vlinks); node; nextnode (node))
+ for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
{
- if ((vl_data = getdata (node)) == NULL)
- continue;
-
vl_area = ospf_area_lookup_by_area_id (ospf, vl_data->vl_area_id);
if (!vl_area)
continue;
IPV4_ADDR_SAME (&vl_data->vl_peer, &ospfh->router_id))
{
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("associating packet with %s",
+ zlog_debug ("associating packet with %s",
IF_NAME (vl_data->vl_oi));
if (! CHECK_FLAG (vl_data->vl_oi->ifp->flags, IFF_UP))
{
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("This VL is not up yet, sorry");
+ zlog_debug ("This VL is not up yet, sorry");
return NULL;
}
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("couldn't find any VL to associate the packet with");
+ zlog_debug ("couldn't find any VL to associate the packet with");
return NULL;
}
-int
+static inline int
ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
{
/* Check match the Area ID of the receiving interface. */
/* Unbound socket will accept any Raw IP packets if proto is matched.
To prevent it, compare src IP address and i/f address with masking
i/f network mask. */
-int
+static int
ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
{
struct in_addr mask, me, him;
return 0;
}
-int
+static int
ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
struct ospf_header *ospfh)
{
ret = 0;
break;
case OSPF_AUTH_CRYPTOGRAPHIC:
- if ((ck = getdata (OSPF_IF_PARAM (oi,auth_crypt)->tail)) == NULL)
+ if ((ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) == NULL)
{
ret = 0;
break;
return ret;
}
-int
+static int
ospf_check_sum (struct ospf_header *ospfh)
{
u_int32_t ret;
u_int16_t sum;
- int in_cksum (void *ptr, int nbytes);
/* clear auth_data for checksum. */
memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
}
/* OSPF Header verification. */
-int
+static int
ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
struct ip *iph, struct ospf_header *ospfh)
{
/* Check authentication. */
if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
{
- zlog_warn ("interface %s: ospf_read authentication type mismatch.",
- IF_NAME (oi));
+ zlog_warn ("interface %s: auth-type mismatch, local %d, rcvd %d",
+ IF_NAME (oi), ospf_auth_type (oi), ntohs (ospfh->auth_type));
return -1;
}
/* first of all get interface pointer. */
ospf = THREAD_ARG (thread);
- ospf->t_read = NULL;
+
+ /* prepare for next packet. */
+ ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
/* read OSPF packet. */
- ibuf = ospf_recv_packet (ospf->fd, &ifp);
- if (ibuf == NULL)
+ stream_reset(ospf->ibuf);
+ if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
return -1;
+ /* Note that there should not be alignment problems with this assignment
+ because this is at the beginning of the stream data buffer. */
iph = (struct ip *) STREAM_DATA (ibuf);
- sockopt_iphdrincl_swab_systoh (iph);
+ /* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */
- /* openbsd lacks IP_RECVIF */
-#if !(defined(IP_PKTINFO) || defined(IP_RECVIF))
if (ifp == NULL)
+ /* Handle cases where the platform does not support retrieving the ifindex,
+ and also platforms (such as Solaris 8) that claim to support ifindex
+ retrieval but do not. */
ifp = if_lookup_address (iph->ip_src);
-#endif /* !((defined(IP_PKTINFO) || defined(IP_RECVIF)) */
if (ifp == NULL)
- {
- stream_free (ibuf);
- return 0;
- }
-
- /* prepare for next packet. */
- ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
+ return 0;
/* IP Header dump. */
if (IS_DEBUG_OSPF_PACKET(0, RECV))
{
if (IS_DEBUG_OSPF_PACKET (0, RECV))
{
- zlog_info ("ospf_read[%s]: Dropping self-originated packet",
+ zlog_debug ("ospf_read[%s]: Dropping self-originated packet",
inet_ntoa (iph->ip_src));
}
- stream_free (ibuf);
return 0;
}
/* Adjust size to message length. */
- stream_forward (ibuf, iph->ip_hl * 4);
+ stream_forward_getp (ibuf, iph->ip_hl * 4);
/* Get ospf packet header. */
ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
/* associate packet with ospf interface */
- oi = ospf_if_lookup_recv_if (ospf, iph->ip_src);
+ oi = ospf_if_lookup_recv_if (ospf, iph->ip_src, ifp);
+
+ /* If incoming interface is passive one, ignore it. */
+ if (oi && OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
+ {
+ char buf[3][INET_ADDRSTRLEN];
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("ignoring packet from router %s sent to %s, "
+ "received on a passive interface, %s",
+ inet_ntop(AF_INET, &ospfh->router_id, buf[0], sizeof(buf[0])),
+ inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
+ inet_ntop(AF_INET, &oi->address->u.prefix4,
+ buf[2], sizeof(buf[2])));
+
+ if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
+ {
+ /* Try to fix multicast membership.
+ * Some OS:es may have problems in this area,
+ * make sure it is removed.
+ */
+ OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
+ ospf_if_set_multicast(oi);
+ }
+ return 0;
+ }
+
/* if no local ospf_interface,
* or header area is backbone but ospf_interface is not
{
if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)
{
- zlog_warn ("Packet from [%s] received on link %s"
- " but no ospf_interface",
- inet_ntoa (iph->ip_src), ifp->name);
- stream_free (ibuf);
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("Packet from [%s] received on link %s"
+ " but no ospf_interface",
+ inet_ntoa (iph->ip_src), ifp->name);
return 0;
}
}
-
+
/* else it must be a local ospf interface, check it was received on
* correct link
*/
else if (oi->ifp != ifp)
{
- zlog_warn ("Packet from [%s] received on wrong link %s",
- inet_ntoa (iph->ip_src), ifp->name);
- stream_free (ibuf);
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_warn ("Packet from [%s] received on wrong link %s",
+ inet_ntoa (iph->ip_src), ifp->name);
+ return 0;
+ }
+ else if (oi->state == ISM_Down)
+ {
+ char buf[2][INET_ADDRSTRLEN];
+ zlog_warn ("Ignoring packet from %s to %s received on interface that is "
+ "down [%s]; interface flags are %s",
+ inet_ntop(AF_INET, &iph->ip_src, buf[0], sizeof(buf[0])),
+ inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
+ ifp->name, if_flag_dump(ifp->flags));
+ /* Fix multicast memberships? */
+ if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
+ OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
+ else if (iph->ip_dst.s_addr == htonl(OSPF_ALLDROUTERS))
+ OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
+ if (oi->multicast_memberships)
+ ospf_if_set_multicast(oi);
return 0;
}
if (iph->ip_dst.s_addr == htonl (OSPF_ALLDROUTERS)
&& (oi->state != ISM_DR && oi->state != ISM_Backup))
{
- zlog_info ("Packet for AllDRouters from [%s] via [%s] (ISM: %s)",
+ zlog_warn ("Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)",
inet_ntoa (iph->ip_src), IF_NAME (oi),
LOOKUP (ospf_ism_state_msg, oi->state));
- stream_free (ibuf);
+ /* Try to fix multicast membership. */
+ SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
+ ospf_if_set_multicast(oi);
return 0;
}
{
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
{
- zlog_info ("-----------------------------------------------------");
+ zlog_debug ("-----------------------------------------------------");
ospf_packet_dump (ibuf);
}
- zlog_info ("%s received from [%s] via [%s]",
+ zlog_debug ("%s received from [%s] via [%s]",
ospf_packet_type_str[ospfh->type],
inet_ntoa (ospfh->router_id), IF_NAME (oi));
- zlog_info (" src [%s],", inet_ntoa (iph->ip_src));
- zlog_info (" dst [%s]", inet_ntoa (iph->ip_dst));
+ zlog_debug (" src [%s],", inet_ntoa (iph->ip_src));
+ zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst));
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
- zlog_info ("-----------------------------------------------------");
+ zlog_debug ("-----------------------------------------------------");
}
/* Some header verification. */
{
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
{
- zlog_info ("ospf_read[%s/%s]: Header check failed, "
+ zlog_debug ("ospf_read[%s/%s]: Header check failed, "
"dropping.",
ospf_packet_type_str[ospfh->type],
inet_ntoa (iph->ip_src));
}
- stream_free (ibuf);
return ret;
}
- stream_forward (ibuf, OSPF_HEADER_SIZE);
+ stream_forward_getp (ibuf, OSPF_HEADER_SIZE);
/* Adjust size to message length. */
length = ntohs (ospfh->length) - OSPF_HEADER_SIZE;
break;
}
- stream_free (ibuf);
return 0;
}
/* Make OSPF header. */
-void
+static void
ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
{
struct ospf_header *ospfh;
memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
- ospf_output_forward (s, OSPF_HEADER_SIZE);
+ stream_forward_endp (s, OSPF_HEADER_SIZE);
}
/* Make Authentication Data. */
-int
+static int
ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
{
struct crypt_key *ck;
}
else
{
- ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
+ ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
ospfh->u.crypt.zero = 0;
ospfh->u.crypt.key_id = ck->key_id;
ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
}
/* Fill rest of OSPF header. */
-void
+static void
ospf_fill_header (struct ospf_interface *oi,
struct stream *s, u_int16_t length)
{
ospf_make_auth (oi, ospfh);
}
-int
+static int
ospf_make_hello (struct ospf_interface *oi, struct stream *s)
{
struct ospf_neighbor *nbr;
stream_put_ipv4 (s, mask.s_addr);
/* Set Hello Interval. */
- stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
+ if (OSPF_IF_PARAM (oi, fast_hello) == 0)
+ stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
+ else
+ stream_putw (s, 0); /* hello-interval of 0 for fast-hellos */
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("make_hello: options: %x, int: %s",
+ zlog_debug ("make_hello: options: %x, int: %s",
OPTIONS(oi), IF_NAME (oi));
/* Set Options. */
/* Set Designated Router. */
stream_put_ipv4 (s, DR (oi).s_addr);
- p = s->putp;
+ p = stream_get_endp (s);
/* Set Backup Designated Router. */
stream_put_ipv4 (s, BDR (oi).s_addr);
/* Let neighbor generate BackupSeen. */
if (flag == 1)
- {
- stream_set_putp (s, p);
- stream_put_ipv4 (s, 0);
- }
+ stream_putl_at (s, p, 0); /* ipv4 address, normally */
return length;
}
-int
+static int
ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
struct stream *s)
{
#endif /* HAVE_OPAQUE_LSA */
stream_putc (s, options);
- /* Keep pointer to flags. */
- pp = stream_get_putp (s);
+ /* DD flags */
+ pp = stream_get_endp (s);
stream_putc (s, nbr->dd_flags);
/* Set DD Sequence Number. */
stream_putl (s, nbr->dd_seqnum);
+ /* shortcut unneeded walk of (empty) summary LSDBs */
if (ospf_db_summary_isempty (nbr))
- {
- if (nbr->state >= NSM_Exchange)
- {
- nbr->dd_flags &= ~OSPF_DD_FLAG_M;
- /* Set DD flags again */
- stream_set_putp (s, pp);
- stream_putc (s, nbr->dd_flags);
- }
- return length;
- }
+ goto empty;
/* Describe LSA Header from Database Summary List. */
lsdb = &nbr->db_sum;
u_int16_t ls_age;
/* DD packet overflows interface MTU. */
- if (length + OSPF_LSA_HEADER_SIZE > OSPF_PACKET_MAX (oi))
+ if (length + OSPF_LSA_HEADER_SIZE > ospf_packet_max (oi))
break;
/* Keep pointer to LS age. */
lsah = (struct lsa_header *) (STREAM_DATA (s) +
- stream_get_putp (s));
+ stream_get_endp (s));
/* Proceed stream pointer. */
stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
}
}
+ /* Update 'More' bit */
+ if (ospf_db_summary_isempty (nbr))
+ {
+empty:
+ if (nbr->state >= NSM_Exchange)
+ {
+ UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_M);
+ /* Rewrite DD flags */
+ stream_putc_at (s, pp, nbr->dd_flags);
+ }
+ else
+ {
+ assert (IS_SET_DD_M(nbr->dd_flags));
+ }
+ }
return length;
}
-int
+static int
ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
unsigned long delta, struct ospf_neighbor *nbr,
struct ospf_lsa *lsa)
oi = nbr->oi;
/* LS Request packet overflows interface MTU. */
- if (*length + delta > OSPF_PACKET_MAX(oi))
+ if (*length + delta > ospf_packet_max(oi))
return 0;
stream_putl (s, lsa->data->type);
stream_put_ipv4 (s, lsa->data->id.s_addr);
stream_put_ipv4 (s, lsa->data->adv_router.s_addr);
- ospf_lsa_unlock (nbr->ls_req_last);
+ ospf_lsa_unlock (&nbr->ls_req_last);
nbr->ls_req_last = ospf_lsa_lock (lsa);
*length += 12;
return 1;
}
-int
+static int
ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s)
{
struct ospf_lsa *lsa;
u_int16_t length = OSPF_LS_REQ_MIN_SIZE;
- unsigned long delta = stream_get_putp(s)+12;
+ unsigned long delta = stream_get_endp(s)+12;
struct route_table *table;
struct route_node *rn;
int i;
return length;
}
-int
+static int
ls_age_increment (struct ospf_lsa *lsa, int delay)
{
int age;
return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age);
}
-int
+static int
ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream *s)
{
struct ospf_lsa *lsa;
struct listnode *node;
- u_int16_t length = OSPF_LS_UPD_MIN_SIZE;
- unsigned long delta = stream_get_putp (s);
+ u_int16_t length = 0;
+ unsigned int size_noauth;
+ unsigned long delta = stream_get_endp (s);
unsigned long pp;
int count = 0;
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("ospf_make_ls_upd: Start");
+ zlog_debug ("ospf_make_ls_upd: Start");
+
+ pp = stream_get_endp (s);
+ stream_forward_endp (s, OSPF_LS_UPD_MIN_SIZE);
+ length += OSPF_LS_UPD_MIN_SIZE;
- pp = stream_get_putp (s);
- ospf_output_forward (s, OSPF_LS_UPD_MIN_SIZE);
+ /* Calculate amount of packet usable for data. */
+ size_noauth = stream_get_size(s) - ospf_packet_authspace(oi);
while ((node = listhead (update)) != NULL)
{
u_int16_t ls_age;
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("ospf_make_ls_upd: List Iteration");
+ zlog_debug ("ospf_make_ls_upd: List Iteration");
+
+ lsa = listgetdata (node);
- lsa = getdata (node);
- assert (lsa);
assert (lsa->data);
/* Will it fit? */
- if (length + delta + ntohs (lsa->data->length) > stream_get_size (s))
+ if (length + delta + ntohs (lsa->data->length) > size_noauth)
break;
/* Keep pointer to LS age. */
- lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_putp (s));
+ lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_endp (s));
/* Put LSA to Link State Request. */
stream_put (s, lsa->data, ntohs (lsa->data->length));
count++;
list_delete_node (update, node);
- ospf_lsa_unlock (lsa);
+ ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
}
/* Now set #LSAs. */
- stream_set_putp (s, pp);
- stream_putl (s, count);
-
- stream_set_putp (s, s->endp);
+ stream_putl_at (s, pp, count);
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("ospf_make_ls_upd: Stop");
+ zlog_debug ("ospf_make_ls_upd: Stop");
return length;
}
-int
+static int
ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
{
- struct list *rm_list;
- struct listnode *node;
+ struct listnode *node, *nnode;
u_int16_t length = OSPF_LS_ACK_MIN_SIZE;
- unsigned long delta = stream_get_putp(s) + 24;
+ unsigned long delta = stream_get_endp(s) + 24;
struct ospf_lsa *lsa;
- rm_list = list_new ();
-
- for (node = listhead (ack); node; nextnode (node))
+ for (ALL_LIST_ELEMENTS (ack, node, nnode, lsa))
{
- lsa = getdata (node);
assert (lsa);
- if (length + delta > OSPF_PACKET_MAX (oi))
+ if (length + delta > ospf_packet_max (oi))
break;
stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
length += OSPF_LSA_HEADER_SIZE;
- listnode_add (rm_list, lsa);
- }
-
- /* Remove LSA from LS-Ack list. */
- for (node = listhead (rm_list); node; nextnode (node))
- {
- lsa = (struct ospf_lsa *) getdata (node);
-
listnode_delete (ack, lsa);
- ospf_lsa_unlock (lsa);
+ ospf_lsa_unlock (&lsa); /* oi->ls_ack_direct.ls_ack */
}
- list_delete (rm_list);
-
return length;
}
-void
-ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
+static void
+ospf_hello_send_sub (struct ospf_interface *oi, in_addr_t addr)
{
struct ospf_packet *op;
u_int16_t length = OSPF_HEADER_SIZE;
/* Set packet length. */
op->length = length;
- op->dst.s_addr = addr->s_addr;
+ op->dst.s_addr = addr;
- /* Add packet to the interface output queue. */
- ospf_packet_add (oi, op);
+ /* Add packet to the top of the interface output queue, so that they
+ * can't get delayed by things like long queues of LS Update packets
+ */
+ ospf_packet_add_top (oi, op);
/* Hook thread to write packet. */
OSPF_ISM_WRITE_ON (oi->ospf);
}
-void
+static void
ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
{
struct ospf_interface *oi;
assert(oi);
/* If this is passive interface, do not send OSPF Hello. */
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+ if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
return;
if (oi->type != OSPF_IFTYPE_NBMA)
&& oi->state != ISM_DR && oi->state != ISM_Backup)
return;
- ospf_hello_send_sub (oi, &nbr_nbma->addr);
+ ospf_hello_send_sub (oi, nbr_nbma->addr.s_addr);
}
int
nbr_nbma->t_poll = NULL;
if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
- zlog (NULL, LOG_INFO, "NSM[%s:%s]: Timer (Poll timer expire)",
+ zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Poll timer expire)",
IF_NAME (nbr_nbma->oi), inet_ntoa (nbr_nbma->addr));
ospf_poll_send (nbr_nbma);
assert (nbr->oi);
if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
- zlog (NULL, LOG_INFO, "NSM[%s:%s]: Timer (hello-reply timer expire)",
+ zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)",
IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
- ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4);
+ ospf_hello_send_sub (nbr->oi, nbr->address.u.prefix4.s_addr);
return 0;
}
void
ospf_hello_send (struct ospf_interface *oi)
{
- struct ospf_packet *op;
- u_int16_t length = OSPF_HEADER_SIZE;
-
/* If this is passive interface, do not send OSPF Hello. */
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+ if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
return;
- op = ospf_packet_new (oi->ifp->mtu);
-
- /* Prepare OSPF common header. */
- ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
-
- /* Prepare OSPF Hello body. */
- length += ospf_make_hello (oi, op->s);
-
- /* Fill OSPF header. */
- ospf_fill_header (oi, op->s, length);
-
- /* Set packet length. */
- op->length = length;
-
if (oi->type == OSPF_IFTYPE_NBMA)
{
struct ospf_neighbor *nbr;
if (nbr->priority == 0 && oi->state == ISM_DROther)
continue;
/* if oi->state == Waiting, send hello to all neighbors */
- {
- struct ospf_packet *op_dup;
-
- op_dup = ospf_packet_dup(op);
- op_dup->dst = nbr->address.u.prefix4;
-
- /* Add packet to the interface output queue. */
- ospf_packet_add (oi, op_dup);
-
- OSPF_ISM_WRITE_ON (oi->ospf);
- }
-
+ ospf_hello_send_sub (oi, nbr->address.u.prefix4.s_addr);
}
- ospf_packet_free (op);
}
else
{
/* Decide destination address. */
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
- op->dst.s_addr = oi->vl_data->peer_addr.s_addr;
- else
- op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
-
- /* Add packet to the interface output queue. */
- ospf_packet_add (oi, op);
-
- /* Hook thread to write packet. */
- OSPF_ISM_WRITE_ON (oi->ospf);
+ ospf_hello_send_sub (oi, oi->vl_data->peer_addr.s_addr);
+ else
+ ospf_hello_send_sub (oi, htonl (OSPF_ALLSPFROUTERS));
}
}
op->length = length;
/* Decide destination address. */
- op->dst = nbr->address.u.prefix4;
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+ else
+ op->dst = nbr->address.u.prefix4;
/* Add packet to the interface output queue. */
ospf_packet_add (oi, op);
if (nbr->last_send)
ospf_packet_free (nbr->last_send);
nbr->last_send = ospf_packet_dup (op);
- gettimeofday (&nbr->last_send_ts, NULL);
+ quagga_gettime (QUAGGA_CLK_MONOTONIC, &nbr->last_send_ts);
}
/* Re-send Database Description. */
op->length = length;
/* Decide destination address. */
- op->dst = nbr->address.u.prefix4;
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+ else
+ op->dst = nbr->address.u.prefix4;
/* Add packet to the interface output queue. */
ospf_packet_add (oi, op);
size_t size;
static char warned = 0;
- ln = listhead (update);
- lsa = getdata (ln);
- assert (lsa);
+ lsa = listgetdata((ln = listhead (update)));
assert (lsa->data);
if ((OSPF_LS_UPD_MIN_SIZE + ntohs (lsa->data->length))
}
if (IS_DEBUG_OSPF_PACKET (0, SEND))
- zlog_warn ("ospf_ls_upd_packet_new: oversized LSA id:%s,"
+ zlog_debug ("ospf_ls_upd_packet_new: oversized LSA id:%s,"
" %d bytes originated by %s, will be fragmented!",
inet_ntoa (lsa->data->id),
ntohs (lsa->data->length),
return NULL;
}
- return ospf_packet_new (size);
+ /* IP header is built up separately by ospf_write(). This means, that we must
+ * reduce the "affordable" size just calculated by length of an IP header.
+ * This makes sure, that even if we manage to fill the payload with LSA data
+ * completely, the final packet (our data plus IP header) still fits into
+ * outgoing interface MTU. This correction isn't really meaningful for an
+ * oversized LSA, but for consistency the correction is done for both cases.
+ *
+ * P.S. OSPF_MAX_PACKET_SIZE above already includes IP header size
+ */
+ return ospf_packet_new (size - sizeof (struct ip));
}
static void
u_int16_t length = OSPF_HEADER_SIZE;
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));
+ zlog_debug ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));
op = ospf_ls_upd_packet_new (update, oi);
op->length = length;
/* Decide destination address. */
- op->dst.s_addr = addr.s_addr;
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+ else
+ op->dst.s_addr = addr.s_addr;
/* Add packet to the interface output queue. */
ospf_packet_add (oi, op);
oi->t_ls_upd_event = NULL;
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("ospf_ls_upd_send_queue start");
+ zlog_debug ("ospf_ls_upd_send_queue start");
for (rn = route_top (oi->ls_upd_queue); rn; rn = rnext)
{
if (again != 0)
{
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("ospf_ls_upd_send_queue: update lists not cleared,"
+ zlog_debug ("ospf_ls_upd_send_queue: update lists not cleared,"
" %d nodes to try again, raising new event", again);
oi->t_ls_upd_event =
thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("ospf_ls_upd_send_queue stop");
+ zlog_debug ("ospf_ls_upd_send_queue stop");
return 0;
}
ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
{
struct ospf_interface *oi;
+ struct ospf_lsa *lsa;
struct prefix_ipv4 p;
struct route_node *rn;
- struct listnode *n;
+ struct listnode *node;
oi = nbr->oi;
/* Decide destination address. */
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
p.prefix = oi->vl_data->peer_addr;
+ else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
else if (flag == OSPF_SEND_PACKET_DIRECT)
p.prefix = nbr->address.u.prefix4;
else if (oi->state == ISM_DR || oi->state == ISM_Backup)
p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
- else if ((oi->type == OSPF_IFTYPE_POINTOPOINT)
- && (flag == OSPF_SEND_PACKET_INDIRECT))
- p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
else
if (rn->info == NULL)
rn->info = list_new ();
- for (n = listhead (update); n; nextnode (n))
- listnode_add (rn->info, ospf_lsa_lock (getdata (n)));
+ for (ALL_LIST_ELEMENTS_RO (update, node, lsa))
+ listnode_add (rn->info, ospf_lsa_lock (lsa)); /* oi->ls_upd_queue */
if (oi->t_ls_upd_event == NULL)
oi->t_ls_upd_event =