2002-12-13 21:15:29 +01:00
|
|
|
|
/*
|
|
|
|
|
* 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 GNU Zebra; see the file COPYING. If not, write to the Free
|
|
|
|
|
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
|
* 02111-1307, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
|
|
#include "thread.h"
|
|
|
|
|
#include "memory.h"
|
|
|
|
|
#include "linklist.h"
|
|
|
|
|
#include "prefix.h"
|
|
|
|
|
#include "if.h"
|
|
|
|
|
#include "table.h"
|
|
|
|
|
#include "sockunion.h"
|
|
|
|
|
#include "stream.h"
|
|
|
|
|
#include "log.h"
|
2004-07-23 17:13:48 +02:00
|
|
|
|
#include "sockopt.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
#include "md5-gnu.h"
|
|
|
|
|
|
|
|
|
|
#include "ospfd/ospfd.h"
|
|
|
|
|
#include "ospfd/ospf_network.h"
|
|
|
|
|
#include "ospfd/ospf_interface.h"
|
|
|
|
|
#include "ospfd/ospf_ism.h"
|
|
|
|
|
#include "ospfd/ospf_asbr.h"
|
|
|
|
|
#include "ospfd/ospf_lsa.h"
|
|
|
|
|
#include "ospfd/ospf_lsdb.h"
|
|
|
|
|
#include "ospfd/ospf_neighbor.h"
|
|
|
|
|
#include "ospfd/ospf_nsm.h"
|
|
|
|
|
#include "ospfd/ospf_packet.h"
|
|
|
|
|
#include "ospfd/ospf_spf.h"
|
|
|
|
|
#include "ospfd/ospf_flood.h"
|
|
|
|
|
#include "ospfd/ospf_dump.h"
|
|
|
|
|
|
2004-09-23 21:18:23 +02:00
|
|
|
|
static void ospf_ls_ack_send_list (struct ospf_interface *, struct list *,
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct in_addr);
|
|
|
|
|
|
|
|
|
|
/* Packet Type String. */
|
2004-10-08 10:17:22 +02:00
|
|
|
|
const char *ospf_packet_type_str[] =
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
"unknown",
|
|
|
|
|
"Hello",
|
|
|
|
|
"Database Description",
|
|
|
|
|
"Link State Request",
|
|
|
|
|
"Link State Update",
|
|
|
|
|
"Link State Acknowledgment",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extern int in_cksum (void *ptr, int nbytes);
|
|
|
|
|
|
|
|
|
|
/* OSPF authentication checking function */
|
|
|
|
|
int
|
|
|
|
|
ospf_auth_type (struct ospf_interface *oi)
|
|
|
|
|
{
|
|
|
|
|
int auth_type;
|
|
|
|
|
|
|
|
|
|
if (OSPF_IF_PARAM (oi, auth_type) == OSPF_AUTH_NOTSET)
|
|
|
|
|
auth_type = oi->area->auth_type;
|
|
|
|
|
else
|
|
|
|
|
auth_type = OSPF_IF_PARAM (oi, auth_type);
|
|
|
|
|
|
|
|
|
|
/* Handle case where MD5 key list is not configured aka Cisco */
|
|
|
|
|
if (auth_type == OSPF_AUTH_CRYPTOGRAPHIC &&
|
|
|
|
|
list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
|
|
|
|
|
return OSPF_AUTH_NULL;
|
|
|
|
|
|
|
|
|
|
return auth_type;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ospf_packet *
|
|
|
|
|
ospf_packet_new (size_t size)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_packet *new;
|
|
|
|
|
|
|
|
|
|
new = XCALLOC (MTYPE_OSPF_PACKET, sizeof (struct ospf_packet));
|
|
|
|
|
new->s = stream_new (size);
|
|
|
|
|
|
|
|
|
|
return new;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ospf_packet_free (struct ospf_packet *op)
|
|
|
|
|
{
|
|
|
|
|
if (op->s)
|
|
|
|
|
stream_free (op->s);
|
|
|
|
|
|
|
|
|
|
XFREE (MTYPE_OSPF_PACKET, op);
|
|
|
|
|
|
|
|
|
|
op = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ospf_fifo *
|
|
|
|
|
ospf_fifo_new ()
|
|
|
|
|
{
|
|
|
|
|
struct ospf_fifo *new;
|
|
|
|
|
|
|
|
|
|
new = XCALLOC (MTYPE_OSPF_FIFO, sizeof (struct ospf_fifo));
|
|
|
|
|
return new;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add new packet to fifo. */
|
|
|
|
|
void
|
|
|
|
|
ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
|
|
|
|
|
{
|
|
|
|
|
if (fifo->tail)
|
|
|
|
|
fifo->tail->next = op;
|
|
|
|
|
else
|
|
|
|
|
fifo->head = op;
|
|
|
|
|
|
|
|
|
|
fifo->tail = op;
|
|
|
|
|
|
|
|
|
|
fifo->count++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Delete first packet from fifo. */
|
|
|
|
|
struct ospf_packet *
|
|
|
|
|
ospf_fifo_pop (struct ospf_fifo *fifo)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_packet *op;
|
|
|
|
|
|
|
|
|
|
op = fifo->head;
|
|
|
|
|
|
|
|
|
|
if (op)
|
|
|
|
|
{
|
|
|
|
|
fifo->head = op->next;
|
|
|
|
|
|
|
|
|
|
if (fifo->head == NULL)
|
|
|
|
|
fifo->tail = NULL;
|
|
|
|
|
|
|
|
|
|
fifo->count--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return op;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return first fifo entry. */
|
|
|
|
|
struct ospf_packet *
|
|
|
|
|
ospf_fifo_head (struct ospf_fifo *fifo)
|
|
|
|
|
{
|
|
|
|
|
return fifo->head;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Flush ospf packet fifo. */
|
|
|
|
|
void
|
|
|
|
|
ospf_fifo_flush (struct ospf_fifo *fifo)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_packet *op;
|
|
|
|
|
struct ospf_packet *next;
|
|
|
|
|
|
|
|
|
|
for (op = fifo->head; op; op = next)
|
|
|
|
|
{
|
|
|
|
|
next = op->next;
|
|
|
|
|
ospf_packet_free (op);
|
|
|
|
|
}
|
|
|
|
|
fifo->head = fifo->tail = NULL;
|
|
|
|
|
fifo->count = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Free ospf packet fifo. */
|
|
|
|
|
void
|
|
|
|
|
ospf_fifo_free (struct ospf_fifo *fifo)
|
|
|
|
|
{
|
|
|
|
|
ospf_fifo_flush (fifo);
|
|
|
|
|
|
|
|
|
|
XFREE (MTYPE_OSPF_FIFO, fifo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
|
|
|
|
|
{
|
2005-01-29 16:52:07 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
/* Add packet to end of queue. */
|
|
|
|
|
ospf_fifo_push (oi->obuf, op);
|
|
|
|
|
|
|
|
|
|
/* Debug of packet fifo*/
|
|
|
|
|
/* ospf_fifo_debug (oi->obuf); */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ospf_packet_delete (struct ospf_interface *oi)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_packet *op;
|
|
|
|
|
|
|
|
|
|
op = ospf_fifo_pop (oi->obuf);
|
|
|
|
|
|
|
|
|
|
if (op)
|
|
|
|
|
ospf_packet_free (op);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct stream *
|
|
|
|
|
ospf_stream_copy (struct stream *new, struct stream *s)
|
|
|
|
|
{
|
|
|
|
|
new->endp = s->endp;
|
|
|
|
|
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;
|
|
|
|
|
|
2003-02-03 19:40:56 +01:00
|
|
|
|
if (stream_get_endp(op->s) != op->length)
|
|
|
|
|
zlog_warn ("ospf_packet_dup stream %ld ospf_packet %d size mismatch",
|
2002-12-13 21:56:48 +01:00
|
|
|
|
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);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
ospf_stream_copy (new->s, op->s);
|
|
|
|
|
|
|
|
|
|
new->dst = op->dst;
|
|
|
|
|
new->length = op->length;
|
|
|
|
|
|
|
|
|
|
return new;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-10 15:20:43 +01:00
|
|
|
|
/* XXX 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;
|
|
|
|
|
}
|
|
|
|
|
|
2004-10-11 13:00:30 +02:00
|
|
|
|
unsigned int
|
2002-12-13 21:15:29 +01:00
|
|
|
|
ospf_packet_max (struct ospf_interface *oi)
|
|
|
|
|
{
|
|
|
|
|
int max;
|
|
|
|
|
|
2005-01-10 15:20:43 +01:00
|
|
|
|
max = oi->ifp->mtu - ospf_packet_authspace(oi);
|
|
|
|
|
|
2004-09-12 16:21:37 +02:00
|
|
|
|
max -= (OSPF_HEADER_SIZE + sizeof (struct ip));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
return max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
|
|
|
|
|
u_int16_t length)
|
|
|
|
|
{
|
2004-10-11 13:00:30 +02:00
|
|
|
|
unsigned char *ibuf;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct md5_ctx ctx;
|
|
|
|
|
unsigned char digest[OSPF_AUTH_MD5_SIZE];
|
|
|
|
|
unsigned char *pdigest;
|
|
|
|
|
struct crypt_key *ck;
|
|
|
|
|
struct ospf_header *ospfh;
|
|
|
|
|
struct ospf_neighbor *nbr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ibuf = STREAM_PNT (s);
|
|
|
|
|
ospfh = (struct ospf_header *) ibuf;
|
|
|
|
|
|
|
|
|
|
/* Get pointer to the end of the packet. */
|
|
|
|
|
pdigest = ibuf + length;
|
|
|
|
|
|
|
|
|
|
/* Get secret key. */
|
|
|
|
|
ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt),
|
|
|
|
|
ospfh->u.crypt.key_id);
|
|
|
|
|
if (ck == NULL)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("interface %s: ospf_check_md5 no key %d",
|
|
|
|
|
IF_NAME (oi), ospfh->u.crypt.key_id);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check crypto seqnum. */
|
|
|
|
|
nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id);
|
|
|
|
|
|
|
|
|
|
if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(ospfh->u.crypt.crypt_seqnum))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("interface %s: ospf_check_md5 bad sequence %d (expect %d)",
|
|
|
|
|
IF_NAME (oi),
|
|
|
|
|
ntohl(ospfh->u.crypt.crypt_seqnum),
|
|
|
|
|
ntohl(nbr->crypt_seqnum));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
|
|
/* compare the two */
|
|
|
|
|
if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("interface %s: ospf_check_md5 checksum mismatch",
|
|
|
|
|
IF_NAME (oi));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* save neighbor's crypt_seqnum */
|
|
|
|
|
if (nbr)
|
|
|
|
|
nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
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;
|
|
|
|
|
void *ibuf;
|
2002-12-13 21:55:25 +01:00
|
|
|
|
u_int32_t t;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct crypt_key *ck;
|
|
|
|
|
char *auth_key;
|
|
|
|
|
|
|
|
|
|
ibuf = STREAM_DATA (op->s);
|
|
|
|
|
ospfh = (struct ospf_header *) ibuf;
|
|
|
|
|
|
|
|
|
|
if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* We do this here so when we dup a packet, we don't have to
|
|
|
|
|
waste CPU rewriting other headers. */
|
2002-12-13 21:55:25 +01:00
|
|
|
|
t = (time(NULL) & 0xFFFFFFFF);
|
|
|
|
|
oi->crypt_seqnum = ( t > oi->crypt_seqnum ? t : oi->crypt_seqnum++);
|
|
|
|
|
ospfh->u.crypt.crypt_seqnum = htonl (oi->crypt_seqnum);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Get MD5 Authentication key from auth_key list. */
|
|
|
|
|
if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
|
2004-10-08 10:17:22 +02:00
|
|
|
|
auth_key = (char *) "";
|
2002-12-13 21:15:29 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
|
2004-09-26 18:09:34 +02:00
|
|
|
|
auth_key = (char *) ck->auth_key;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
|
|
/* Append md5 digest to the end of the stream. */
|
|
|
|
|
stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE);
|
|
|
|
|
|
|
|
|
|
/* We do *NOT* increment the OSPF header length. */
|
2002-12-13 21:56:48 +01:00
|
|
|
|
op->length = ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE;
|
|
|
|
|
|
2003-02-03 19:40:56 +01:00
|
|
|
|
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);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
return OSPF_AUTH_MD5_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_ls_req_timer (struct thread *thread)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_neighbor *nbr;
|
|
|
|
|
|
|
|
|
|
nbr = THREAD_ARG (thread);
|
|
|
|
|
nbr->t_ls_req = NULL;
|
|
|
|
|
|
|
|
|
|
/* Send Link State Request. */
|
|
|
|
|
if (ospf_ls_request_count (nbr))
|
|
|
|
|
ospf_ls_req_send (nbr);
|
|
|
|
|
|
|
|
|
|
/* Set Link State Request retransmission timer. */
|
|
|
|
|
OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ospf_ls_req_event (struct ospf_neighbor *nbr)
|
|
|
|
|
{
|
|
|
|
|
if (nbr->t_ls_req)
|
|
|
|
|
{
|
|
|
|
|
thread_cancel (nbr->t_ls_req);
|
|
|
|
|
nbr->t_ls_req = NULL;
|
|
|
|
|
}
|
|
|
|
|
nbr->t_ls_req = thread_add_event (master, ospf_ls_req_timer, nbr, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Cyclic timer function. Fist registered in ospf_nbr_new () in
|
|
|
|
|
ospf_neighbor.c */
|
|
|
|
|
int
|
|
|
|
|
ospf_ls_upd_timer (struct thread *thread)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_neighbor *nbr;
|
|
|
|
|
|
|
|
|
|
nbr = THREAD_ARG (thread);
|
|
|
|
|
nbr->t_ls_upd = NULL;
|
|
|
|
|
|
|
|
|
|
/* Send Link State Update. */
|
|
|
|
|
if (ospf_ls_retransmit_count (nbr) > 0)
|
|
|
|
|
{
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct list *update;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
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;
|
|
|
|
|
update = list_new ();
|
|
|
|
|
|
|
|
|
|
for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
|
|
|
|
|
{
|
|
|
|
|
struct route_table *table = lsdb->type[i].db;
|
|
|
|
|
struct route_node *rn;
|
|
|
|
|
|
|
|
|
|
for (rn = route_top (table); rn; rn = route_next (rn))
|
|
|
|
|
{
|
|
|
|
|
struct ospf_lsa *lsa;
|
|
|
|
|
|
|
|
|
|
if ((lsa = rn->info) != NULL)
|
|
|
|
|
/* Don't retransmit an LSA if we received it within
|
|
|
|
|
the last RxmtInterval seconds - this is to allow the
|
|
|
|
|
neighbour a chance to acknowledge the LSA as it may
|
|
|
|
|
have ben just received before the retransmit timer
|
|
|
|
|
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),
|
|
|
|
|
int2tv (retransmit_interval)) >= 0)
|
|
|
|
|
listnode_add (update, rn->info);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (listcount (update) > 0)
|
|
|
|
|
ospf_ls_upd_send (nbr, update, OSPF_SEND_PACKET_DIRECT);
|
|
|
|
|
list_delete (update);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set LS Update retransmission timer. */
|
|
|
|
|
OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_ls_ack_timer (struct thread *thread)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *oi;
|
|
|
|
|
|
|
|
|
|
oi = THREAD_ARG (thread);
|
|
|
|
|
oi->t_ls_ack = NULL;
|
|
|
|
|
|
|
|
|
|
/* Send Link State Acknowledgment. */
|
|
|
|
|
if (listcount (oi->ls_ack) > 0)
|
|
|
|
|
ospf_ls_ack_send_delayed (oi);
|
|
|
|
|
|
|
|
|
|
/* Set LS Ack timer. */
|
|
|
|
|
OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-24 10:07:54 +02:00
|
|
|
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
|
|
|
|
void
|
2004-09-27 14:56:30 +02:00
|
|
|
|
ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph,
|
2004-11-02 21:26:45 +01:00
|
|
|
|
struct msghdr *msg, unsigned int maxdatasize,
|
2004-10-31 12:24:51 +01:00
|
|
|
|
unsigned int mtu, int flags, u_char type)
|
2004-09-24 10:07:54 +02:00
|
|
|
|
{
|
|
|
|
|
#define OSPF_WRITE_FRAG_SHIFT 3
|
2004-09-27 14:56:30 +02:00
|
|
|
|
u_int16_t offset;
|
2004-11-02 21:26:45 +01:00
|
|
|
|
struct iovec *iovp;
|
2004-09-27 14:56:30 +02:00
|
|
|
|
int ret;
|
2004-09-24 10:07:54 +02:00
|
|
|
|
|
|
|
|
|
assert ( op->length == stream_get_endp(op->s) );
|
2004-11-02 21:26:45 +01:00
|
|
|
|
assert (msg->msg_iovlen == 2);
|
2004-09-24 10:07:54 +02:00
|
|
|
|
|
|
|
|
|
/* we can but try.
|
|
|
|
|
*
|
|
|
|
|
* SunOS, BSD and BSD derived kernels likely will clear ip_id, as
|
|
|
|
|
* well as the IP_MF flag, making this all quite pointless.
|
|
|
|
|
*
|
|
|
|
|
* However, for a system on which IP_MF is left alone, and ip_id left
|
|
|
|
|
* alone or else which sets same ip_id for each fragment this might
|
|
|
|
|
* work, eg linux.
|
|
|
|
|
*
|
|
|
|
|
* XXX-TODO: It would be much nicer to have the kernel's use their
|
|
|
|
|
* existing fragmentation support to do this for us. Bugs/RFEs need to
|
|
|
|
|
* be raised against the various kernels.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* set More Frag */
|
|
|
|
|
iph->ip_off |= IP_MF;
|
|
|
|
|
|
|
|
|
|
/* ip frag offset is expressed in units of 8byte words */
|
|
|
|
|
offset = maxdatasize >> OSPF_WRITE_FRAG_SHIFT;
|
|
|
|
|
|
2004-11-02 21:26:45 +01:00
|
|
|
|
iovp = &msg->msg_iov[1];
|
|
|
|
|
|
2004-09-24 10:07:54 +02:00
|
|
|
|
while ( (stream_get_endp(op->s) - stream_get_getp (op->s))
|
|
|
|
|
> maxdatasize )
|
|
|
|
|
{
|
|
|
|
|
/* data length of this frag is to next offset value */
|
2004-11-02 21:26:45 +01:00
|
|
|
|
iovp->iov_len = offset << OSPF_WRITE_FRAG_SHIFT;
|
|
|
|
|
iph->ip_len = iovp->iov_len + sizeof (struct ip);
|
2004-09-27 14:56:30 +02:00
|
|
|
|
assert (iph->ip_len <= mtu);
|
2004-09-24 10:07:54 +02:00
|
|
|
|
|
2004-10-05 16:38:29 +02:00
|
|
|
|
sockopt_iphdrincl_swab_htosys (iph);
|
2004-09-24 10:07:54 +02:00
|
|
|
|
|
2004-09-27 14:56:30 +02:00
|
|
|
|
ret = sendmsg (fd, msg, flags);
|
2004-09-24 10:07:54 +02:00
|
|
|
|
|
2004-10-05 16:38:29 +02:00
|
|
|
|
sockopt_iphdrincl_swab_systoh (iph);
|
2004-09-24 10:07:54 +02:00
|
|
|
|
|
|
|
|
|
if (ret < 0)
|
2004-10-31 12:24:51 +01:00
|
|
|
|
zlog_warn ("*** ospf_write_frags: sendmsg failed to %s,"
|
2004-09-24 10:07:54 +02:00
|
|
|
|
" id %d, off %d, len %d failed with %s",
|
|
|
|
|
inet_ntoa (iph->ip_dst),
|
|
|
|
|
iph->ip_id,
|
|
|
|
|
iph->ip_off,
|
|
|
|
|
iph->ip_len,
|
2004-11-20 03:06:59 +01:00
|
|
|
|
safe_strerror (errno));
|
2004-09-24 10:07:54 +02:00
|
|
|
|
|
2004-10-31 12:24:51 +01:00
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
|
|
|
|
|
{
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_write_frags: sent id %d, off %d, len %d to %s\n",
|
2004-10-31 12:24:51 +01:00
|
|
|
|
iph->ip_id, iph->ip_off, iph->ip_len,
|
|
|
|
|
inet_ntoa (iph->ip_dst));
|
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
|
|
|
|
|
{
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("-----------------IP Header Dump----------------------");
|
2004-10-31 12:24:51 +01:00
|
|
|
|
ospf_ip_header_dump (iph);
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("-----------------------------------------------------");
|
2004-10-31 12:24:51 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-24 10:07:54 +02:00
|
|
|
|
iph->ip_off += offset;
|
2005-02-09 16:51:56 +01:00
|
|
|
|
stream_forward_getp (op->s, iovp->iov_len);
|
2004-11-02 21:26:45 +01:00
|
|
|
|
iovp->iov_base = STREAM_PNT (op->s);
|
2004-09-24 10:07:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* setup for final fragment */
|
2004-11-02 21:26:45 +01:00
|
|
|
|
iovp->iov_len = stream_get_endp(op->s) - stream_get_getp (op->s);
|
|
|
|
|
iph->ip_len = iovp->iov_len + sizeof (struct ip);
|
2004-09-24 10:07:54 +02:00
|
|
|
|
iph->ip_off &= (~IP_MF);
|
|
|
|
|
}
|
|
|
|
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
int
|
|
|
|
|
ospf_write (struct thread *thread)
|
|
|
|
|
{
|
2003-03-25 06:07:42 +01:00
|
|
|
|
struct ospf *ospf = THREAD_ARG (thread);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct ospf_interface *oi;
|
|
|
|
|
struct ospf_packet *op;
|
|
|
|
|
struct sockaddr_in sa_dst;
|
|
|
|
|
struct ip iph;
|
|
|
|
|
struct msghdr msg;
|
2004-11-02 21:26:45 +01:00
|
|
|
|
struct iovec iov[2];
|
2003-03-25 06:07:42 +01:00
|
|
|
|
u_char type;
|
|
|
|
|
int ret;
|
|
|
|
|
int flags = 0;
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct listnode *node;
|
2004-09-24 10:07:54 +02:00
|
|
|
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
2004-09-12 16:21:37 +02:00
|
|
|
|
static u_int16_t ipid = 0;
|
2004-09-24 10:07:54 +02:00
|
|
|
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
2004-09-27 14:56:30 +02:00
|
|
|
|
u_int16_t maxdatasize;
|
2004-09-12 16:21:37 +02:00
|
|
|
|
#define OSPF_WRITE_IPHL_SHIFT 2
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2003-03-25 06:07:42 +01:00
|
|
|
|
ospf->t_write = NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2003-03-25 06:07:42 +01:00
|
|
|
|
node = listhead (ospf->oi_write_q);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
assert (node);
|
|
|
|
|
oi = getdata (node);
|
|
|
|
|
assert (oi);
|
2004-09-24 10:07:54 +02:00
|
|
|
|
|
|
|
|
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
2004-09-12 16:21:37 +02:00
|
|
|
|
/* seed ipid static with low order bits of time */
|
|
|
|
|
if (ipid == 0)
|
|
|
|
|
ipid = (time(NULL) & 0xffff);
|
2004-09-24 10:07:54 +02:00
|
|
|
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
|
|
|
|
|
2004-09-12 16:21:37 +02:00
|
|
|
|
/* convenience - max OSPF data per packet */
|
|
|
|
|
maxdatasize = oi->ifp->mtu - sizeof (struct ip);
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
/* Get one packet from queue. */
|
|
|
|
|
op = ospf_fifo_head (oi->obuf);
|
|
|
|
|
assert (op);
|
|
|
|
|
assert (op->length >= OSPF_HEADER_SIZE);
|
|
|
|
|
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS)
|
|
|
|
|
|| op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
|
2004-09-12 16:21:37 +02:00
|
|
|
|
ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex);
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
/* Rewrite the md5 signature & update the seq */
|
|
|
|
|
ospf_make_md5_digest (oi, op);
|
|
|
|
|
|
2004-10-31 12:24:51 +01:00
|
|
|
|
/* Retrieve OSPF packet type. */
|
|
|
|
|
stream_set_getp (op->s, 1);
|
|
|
|
|
type = stream_getc (op->s);
|
|
|
|
|
|
2004-09-12 16:21:37 +02:00
|
|
|
|
/* reset get pointer */
|
|
|
|
|
stream_set_getp (op->s, 0);
|
|
|
|
|
|
|
|
|
|
memset (&iph, 0, sizeof (struct ip));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
memset (&sa_dst, 0, sizeof (sa_dst));
|
2004-09-12 16:21:37 +02:00
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
sa_dst.sin_family = AF_INET;
|
|
|
|
|
#ifdef HAVE_SIN_LEN
|
|
|
|
|
sa_dst.sin_len = sizeof(sa_dst);
|
|
|
|
|
#endif /* HAVE_SIN_LEN */
|
|
|
|
|
sa_dst.sin_addr = op->dst;
|
|
|
|
|
sa_dst.sin_port = htons (0);
|
|
|
|
|
|
|
|
|
|
/* Set DONTROUTE flag if dst is unicast. */
|
|
|
|
|
if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
|
|
|
|
|
if (!IN_MULTICAST (htonl (op->dst.s_addr)))
|
|
|
|
|
flags = MSG_DONTROUTE;
|
|
|
|
|
|
2004-09-12 16:21:37 +02:00
|
|
|
|
iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT;
|
|
|
|
|
/* it'd be very strange for header to not be 4byte-word aligned but.. */
|
2004-10-11 13:00:30 +02:00
|
|
|
|
if ( sizeof (struct ip)
|
|
|
|
|
> (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) )
|
2004-09-12 16:21:37 +02:00
|
|
|
|
iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
iph.ip_v = IPVERSION;
|
2003-03-25 06:07:42 +01:00
|
|
|
|
iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
|
2004-09-12 16:21:37 +02:00
|
|
|
|
iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
|
|
|
|
|
|
2004-09-24 10:07:54 +02:00
|
|
|
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
2004-09-12 16:21:37 +02:00
|
|
|
|
/* XXX-MT: not thread-safe at all..
|
|
|
|
|
* XXX: this presumes this is only programme sending OSPF packets
|
|
|
|
|
* otherwise, no guarantee ipid will be unique
|
|
|
|
|
*/
|
|
|
|
|
iph.ip_id = ++ipid;
|
2004-09-24 10:07:54 +02:00
|
|
|
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
iph.ip_off = 0;
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
|
|
|
|
iph.ip_ttl = OSPF_VL_IP_TTL;
|
|
|
|
|
else
|
|
|
|
|
iph.ip_ttl = OSPF_IP_TTL;
|
|
|
|
|
iph.ip_p = IPPROTO_OSPFIGP;
|
|
|
|
|
iph.ip_sum = 0;
|
|
|
|
|
iph.ip_src.s_addr = oi->address->u.prefix4.s_addr;
|
|
|
|
|
iph.ip_dst.s_addr = op->dst.s_addr;
|
|
|
|
|
|
|
|
|
|
memset (&msg, 0, sizeof (msg));
|
2004-09-27 09:27:13 +02:00
|
|
|
|
msg.msg_name = (caddr_t) &sa_dst;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
msg.msg_namelen = sizeof (sa_dst);
|
|
|
|
|
msg.msg_iov = iov;
|
|
|
|
|
msg.msg_iovlen = 2;
|
|
|
|
|
iov[0].iov_base = (char*)&iph;
|
2004-09-12 16:21:37 +02:00
|
|
|
|
iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT;
|
|
|
|
|
iov[1].iov_base = STREAM_PNT (op->s);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
iov[1].iov_len = op->length;
|
2004-09-12 16:21:37 +02:00
|
|
|
|
|
|
|
|
|
/* Sadly we can not rely on kernels to fragment packets because of either
|
|
|
|
|
* IP_HDRINCL and/or multicast destination being set.
|
|
|
|
|
*/
|
2004-09-24 10:07:54 +02:00
|
|
|
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
2004-09-12 16:21:37 +02:00
|
|
|
|
if ( op->length > maxdatasize )
|
2004-11-02 21:26:45 +01:00
|
|
|
|
ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize,
|
|
|
|
|
oi->ifp->mtu, flags, type);
|
2004-09-24 10:07:54 +02:00
|
|
|
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2004-09-12 16:21:37 +02:00
|
|
|
|
/* send final fragment (could be first) */
|
2004-10-05 16:38:29 +02:00
|
|
|
|
sockopt_iphdrincl_swab_htosys (&iph);
|
2003-03-25 06:07:42 +01:00
|
|
|
|
ret = sendmsg (ospf->fd, &msg, flags);
|
2004-10-11 12:11:25 +02:00
|
|
|
|
sockopt_iphdrincl_swab_systoh (&iph);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
if (ret < 0)
|
2005-02-09 16:35:50 +01:00
|
|
|
|
zlog_warn ("*** sendmsg in ospf_write failed to %s, "
|
|
|
|
|
"id %d, off %d, len %d: %s",
|
|
|
|
|
inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
|
|
|
|
|
safe_strerror (errno));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Show debug sending packet. */
|
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
|
|
|
|
|
{
|
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
|
|
|
|
|
{
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("-----------------------------------------------------");
|
2004-10-31 12:24:51 +01:00
|
|
|
|
ospf_ip_header_dump (&iph);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
stream_set_getp (op->s, 0);
|
|
|
|
|
ospf_packet_dump (op->s);
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("%s sent to [%s] via [%s].",
|
2002-12-13 21:15:29 +01:00
|
|
|
|
ospf_packet_type_str[type], inet_ntoa (op->dst),
|
|
|
|
|
IF_NAME (oi));
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("-----------------------------------------------------");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now delete packet from queue. */
|
|
|
|
|
ospf_packet_delete (oi);
|
|
|
|
|
|
|
|
|
|
if (ospf_fifo_head (oi->obuf) == NULL)
|
|
|
|
|
{
|
|
|
|
|
oi->on_write_q = 0;
|
2003-03-25 06:07:42 +01:00
|
|
|
|
list_delete_node (ospf->oi_write_q, node);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If packets still remain in queue, call write thread. */
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (!list_isempty (ospf->oi_write_q))
|
|
|
|
|
ospf->t_write =
|
|
|
|
|
thread_add_write (master, ospf_write, ospf, ospf->fd);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* OSPF Hello message read -- RFC2328 Section 10.5. */
|
|
|
|
|
void
|
|
|
|
|
ospf_hello (struct ip *iph, struct ospf_header *ospfh,
|
|
|
|
|
struct stream * s, struct ospf_interface *oi, int size)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_hello *hello;
|
|
|
|
|
struct ospf_neighbor *nbr;
|
|
|
|
|
int old_state;
|
2004-05-05 17:27:15 +02:00
|
|
|
|
struct prefix p;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* increment statistics. */
|
|
|
|
|
oi->hello_in++;
|
|
|
|
|
|
|
|
|
|
hello = (struct ospf_hello *) STREAM_PNT (s);
|
|
|
|
|
|
|
|
|
|
/* If Hello is myself, silently discard. */
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (IPV4_ADDR_SAME (&ospfh->router_id, &oi->ospf->router_id))
|
2003-09-29 14:42:39 +02:00
|
|
|
|
{
|
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
|
|
|
|
|
{
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_header[%s/%s]: selforiginated, "
|
2003-09-29 14:42:39 +02:00
|
|
|
|
"dropping.",
|
|
|
|
|
ospf_packet_type_str[ospfh->type],
|
|
|
|
|
inet_ntoa (iph->ip_src));
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* If incoming interface is passive one, ignore Hello. */
|
2002-12-13 22:44:27 +01:00
|
|
|
|
if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) {
|
2005-02-08 16:37:30 +01:00
|
|
|
|
char buf[3][INET_ADDRSTRLEN];
|
|
|
|
|
zlog_warn("Warning: ignoring HELLO from router %s sent to %s; we "
|
|
|
|
|
"should not receive hellos on 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. */
|
|
|
|
|
SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
|
|
|
|
|
ospf_if_set_multicast(oi);
|
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
return;
|
2002-12-13 22:44:27 +01:00
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* get neighbor prefix. */
|
|
|
|
|
p.family = AF_INET;
|
|
|
|
|
p.prefixlen = ip_masklen (hello->network_mask);
|
|
|
|
|
p.u.prefix4 = iph->ip_src;
|
|
|
|
|
|
|
|
|
|
/* Compare network mask. */
|
|
|
|
|
/* Checking is ignored for Point-to-Point and Virtual link. */
|
|
|
|
|
if (oi->type != OSPF_IFTYPE_POINTOPOINT
|
|
|
|
|
&& oi->type != OSPF_IFTYPE_VIRTUALLINK)
|
|
|
|
|
if (oi->address->prefixlen != p.prefixlen)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch.",
|
|
|
|
|
inet_ntoa (ospfh->router_id));
|
|
|
|
|
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));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("Packet %s [Hello:RECV]: Options %s",
|
2002-12-13 21:15:29 +01:00
|
|
|
|
inet_ntoa (ospfh->router_id),
|
|
|
|
|
ospf_options_dump (hello->options));
|
|
|
|
|
|
|
|
|
|
/* Compare options. */
|
|
|
|
|
#define REJECT_IF_TBIT_ON 1 /* XXX */
|
|
|
|
|
#ifdef REJECT_IF_TBIT_ON
|
|
|
|
|
if (CHECK_FLAG (hello->options, OSPF_OPTION_T))
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* This router does not support non-zero TOS.
|
|
|
|
|
* Drop this Hello packet not to establish neighbor relationship.
|
|
|
|
|
*/
|
|
|
|
|
zlog_warn ("Packet %s [Hello:RECV]: T-bit on, drop it.",
|
|
|
|
|
inet_ntoa (ospfh->router_id));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif /* REJECT_IF_TBIT_ON */
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
&& CHECK_FLAG (hello->options, OSPF_OPTION_O))
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* This router does know the correct usage of O-bit
|
|
|
|
|
* the bit should be set in DD packet only.
|
|
|
|
|
*/
|
|
|
|
|
zlog_warn ("Packet %s [Hello:RECV]: O-bit abuse?",
|
|
|
|
|
inet_ntoa (ospfh->router_id));
|
|
|
|
|
#ifdef STRICT_OBIT_USAGE_CHECK
|
|
|
|
|
return; /* Reject this packet. */
|
|
|
|
|
#else /* STRICT_OBIT_USAGE_CHECK */
|
|
|
|
|
UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */
|
|
|
|
|
#endif /* STRICT_OBIT_USAGE_CHECK */
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
/* new for NSSA is to ensure that NP is on and E is off */
|
|
|
|
|
|
|
|
|
|
if (oi->area->external_routing == OSPF_AREA_NSSA)
|
|
|
|
|
{
|
|
|
|
|
if (! (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_NP)
|
|
|
|
|
&& CHECK_FLAG (hello->options, OSPF_OPTION_NP)
|
|
|
|
|
&& ! CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E)
|
|
|
|
|
&& ! CHECK_FLAG (hello->options, OSPF_OPTION_E)))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("NSSA-Packet-%s[Hello:RECV]: my options: %x, his options %x", inet_ntoa (ospfh->router_id), OPTIONS (oi), hello->options);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (IS_DEBUG_OSPF_NSSA)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
/* The setting of the E-bit found in the Hello Packet's Options
|
|
|
|
|
field must match this area's ExternalRoutingCapability A
|
|
|
|
|
mismatch causes processing to stop and the packet to be
|
|
|
|
|
dropped. The setting of the rest of the bits in the Hello
|
|
|
|
|
Packet's Options field should be ignored. */
|
|
|
|
|
if (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) !=
|
|
|
|
|
CHECK_FLAG (hello->options, OSPF_OPTION_E))
|
|
|
|
|
{
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn ("Packet %s [Hello:RECV]: my options: %x, his options %x",
|
|
|
|
|
inet_ntoa(ospfh->router_id), OPTIONS (oi), hello->options);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-05 17:27:15 +02:00
|
|
|
|
/* get neighbour struct */
|
|
|
|
|
nbr = ospf_nbr_get (oi, ospfh, iph, &p);
|
|
|
|
|
|
|
|
|
|
/* neighbour must be valid, ospf_nbr_get creates if none existed */
|
|
|
|
|
assert (nbr);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
old_state = nbr->state;
|
|
|
|
|
|
|
|
|
|
/* Add event to thread. */
|
|
|
|
|
OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived);
|
|
|
|
|
|
|
|
|
|
/* RFC2328 Section 9.5.1
|
|
|
|
|
If the router is not eligible to become Designated Router,
|
|
|
|
|
(snip) It must also send an Hello Packet in reply to an
|
|
|
|
|
Hello Packet received from any eligible neighbor (other than
|
|
|
|
|
the current Designated Router and Backup Designated Router). */
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_NBMA)
|
|
|
|
|
if (PRIORITY(oi) == 0 && hello->priority > 0
|
|
|
|
|
&& IPV4_ADDR_CMP(&DR(oi), &iph->ip_src)
|
|
|
|
|
&& IPV4_ADDR_CMP(&BDR(oi), &iph->ip_src))
|
|
|
|
|
OSPF_NSM_TIMER_ON (nbr->t_hello_reply, ospf_hello_reply_timer,
|
|
|
|
|
OSPF_HELLO_REPLY_DELAY);
|
|
|
|
|
|
|
|
|
|
/* on NBMA network type, it happens to receive bidirectional Hello packet
|
|
|
|
|
without advance 1-Way Received event.
|
|
|
|
|
To avoid incorrect DR-seletion, raise 1-Way Received event.*/
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_NBMA &&
|
|
|
|
|
(old_state == NSM_Down || old_state == NSM_Attempt))
|
|
|
|
|
{
|
|
|
|
|
OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
|
|
|
|
|
nbr->priority = hello->priority;
|
|
|
|
|
nbr->d_router = hello->d_router;
|
|
|
|
|
nbr->bd_router = hello->bd_router;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors,
|
2002-12-13 21:15:29 +01:00
|
|
|
|
size - OSPF_HELLO_MIN_SIZE))
|
|
|
|
|
{
|
|
|
|
|
OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
|
|
|
|
|
nbr->options |= hello->options;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
|
|
|
|
|
/* Set neighbor information. */
|
|
|
|
|
nbr->priority = hello->priority;
|
|
|
|
|
nbr->d_router = hello->d_router;
|
|
|
|
|
nbr->bd_router = hello->bd_router;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If neighbor itself declares DR and no BDR exists,
|
|
|
|
|
cause event BackupSeen */
|
|
|
|
|
if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router))
|
|
|
|
|
if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting)
|
|
|
|
|
OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
|
|
|
|
|
|
|
|
|
|
/* neighbor itself declares BDR. */
|
|
|
|
|
if (oi->state == ISM_Waiting &&
|
|
|
|
|
IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router))
|
|
|
|
|
OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
|
|
|
|
|
|
|
|
|
|
/* had not previously. */
|
|
|
|
|
if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) &&
|
|
|
|
|
IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) ||
|
|
|
|
|
(IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) &&
|
|
|
|
|
IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router)))
|
|
|
|
|
OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
|
|
|
|
|
|
|
|
|
|
/* had not previously. */
|
|
|
|
|
if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) &&
|
|
|
|
|
IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) ||
|
|
|
|
|
(IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) &&
|
|
|
|
|
IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router)))
|
|
|
|
|
OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
|
|
|
|
|
|
|
|
|
|
/* Neighbor priority check. */
|
|
|
|
|
if (nbr->priority >= 0 && nbr->priority != hello->priority)
|
|
|
|
|
OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
|
|
|
|
|
|
|
|
|
|
/* Set neighbor information. */
|
|
|
|
|
nbr->priority = hello->priority;
|
|
|
|
|
nbr->d_router = hello->d_router;
|
|
|
|
|
nbr->bd_router = hello->bd_router;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Save DD flags/options/Seqnum received. */
|
|
|
|
|
void
|
|
|
|
|
ospf_db_desc_save_current (struct ospf_neighbor *nbr,
|
|
|
|
|
struct ospf_db_desc *dd)
|
|
|
|
|
{
|
|
|
|
|
nbr->last_recv.flags = dd->flags;
|
|
|
|
|
nbr->last_recv.options = dd->options;
|
|
|
|
|
nbr->last_recv.dd_seqnum = ntohl (dd->dd_seqnum);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Process rest of DD packet. */
|
|
|
|
|
static void
|
|
|
|
|
ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi,
|
|
|
|
|
struct ospf_neighbor *nbr, struct ospf_db_desc *dd,
|
|
|
|
|
u_int16_t size)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_lsa *new, *find;
|
|
|
|
|
struct lsa_header *lsah;
|
|
|
|
|
|
2005-02-09 16:51:56 +01:00
|
|
|
|
stream_forward_getp (s, OSPF_DB_DESC_MIN_SIZE);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
for (size -= OSPF_DB_DESC_MIN_SIZE;
|
|
|
|
|
size >= OSPF_LSA_HEADER_SIZE; size -= OSPF_LSA_HEADER_SIZE)
|
|
|
|
|
{
|
|
|
|
|
lsah = (struct lsa_header *) STREAM_PNT (s);
|
2005-02-09 16:51:56 +01:00
|
|
|
|
stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Unknown LS type. */
|
|
|
|
|
if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
|
|
|
|
|
{
|
2004-11-30 23:38:43 +01:00
|
|
|
|
zlog_warn ("Packet [DD:RECV]: Unknown LS type %d.", lsah->type);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
|
|
|
|
if (IS_OPAQUE_LSA (lsah->type)
|
|
|
|
|
&& ! CHECK_FLAG (nbr->options, OSPF_OPTION_O))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
|
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
switch (lsah->type)
|
|
|
|
|
{
|
|
|
|
|
case OSPF_AS_EXTERNAL_LSA:
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
|
|
|
|
case OSPF_OPAQUE_AS_LSA:
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
/* Check for stub area. Reject if AS-External from stub but
|
|
|
|
|
allow if from NSSA. */
|
|
|
|
|
if (oi->area->external_routing == OSPF_AREA_STUB)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("Packet [DD:RECV]: LSA[Type%d:%s] from %s area.",
|
|
|
|
|
lsah->type, inet_ntoa (lsah->id),
|
|
|
|
|
(oi->area->external_routing == OSPF_AREA_STUB) ?\
|
|
|
|
|
"STUB" : "NSSA");
|
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create LS-request object. */
|
|
|
|
|
new = ospf_ls_request_new (lsah);
|
|
|
|
|
|
|
|
|
|
/* 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)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("Packet [DD:RECV]: LSA received Type %d, "
|
2002-12-13 21:15:29 +01:00
|
|
|
|
"ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
|
|
|
|
|
ospf_lsa_discard (new);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Master */
|
|
|
|
|
if (IS_SET_DD_MS (nbr->dd_flags))
|
|
|
|
|
{
|
|
|
|
|
nbr->dd_seqnum++;
|
|
|
|
|
/* Entire DD packet sent. */
|
|
|
|
|
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 */
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2004-11-30 23:38:43 +01:00
|
|
|
|
/* Send DD packet in reply. */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
ospf_db_desc_send (nbr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Save received neighbor values from DD. */
|
|
|
|
|
ospf_db_desc_save_current (nbr, dd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr)
|
|
|
|
|
{
|
|
|
|
|
/* Is DD duplicated? */
|
|
|
|
|
if (dd->options == nbr->last_recv.options &&
|
|
|
|
|
dd->flags == nbr->last_recv.flags &&
|
|
|
|
|
dd->dd_seqnum == htonl (nbr->last_recv.dd_seqnum))
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* OSPF Database Description message read -- RFC2328 Section 10.6. */
|
2004-12-11 19:00:06 +01:00
|
|
|
|
static void
|
2002-12-13 21:15:29 +01:00
|
|
|
|
ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
|
|
|
|
|
struct stream *s, struct ospf_interface *oi, u_int16_t size)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_db_desc *dd;
|
|
|
|
|
struct ospf_neighbor *nbr;
|
|
|
|
|
|
|
|
|
|
/* Increment statistics. */
|
|
|
|
|
oi->db_desc_in++;
|
|
|
|
|
|
|
|
|
|
dd = (struct ospf_db_desc *) STREAM_PNT (s);
|
2003-06-19 02:26:34 +02:00
|
|
|
|
|
2004-05-05 17:27:15 +02:00
|
|
|
|
nbr = ospf_nbr_lookup (oi, iph, ospfh);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
if (nbr == NULL)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("Packet[DD]: Unknown Neighbor %s",
|
|
|
|
|
inet_ntoa (ospfh->router_id));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check MTU. */
|
|
|
|
|
if (ntohs (dd->mtu) > oi->ifp->mtu)
|
|
|
|
|
{
|
2004-12-11 19:00:06 +01:00
|
|
|
|
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);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-19 02:26:34 +02:00
|
|
|
|
/*
|
|
|
|
|
* XXX HACK by Hasso Tepper. Setting N/P bit in NSSA area DD packets is not
|
|
|
|
|
* required. In fact at least JunOS sends DD packets with P bit clear.
|
|
|
|
|
* Until proper solution is developped, this hack should help.
|
|
|
|
|
*
|
|
|
|
|
* Update: According to the RFCs, N bit is specified /only/ for Hello
|
|
|
|
|
* options, unfortunately its use in DD options is not specified. Hence some
|
|
|
|
|
* implementations follow E-bit semantics and set it in DD options, and some
|
|
|
|
|
* treat it as unspecified and hence follow the directive "default for
|
|
|
|
|
* options is clear", ie unset.
|
|
|
|
|
*
|
|
|
|
|
* Reset the flag, as ospfd follows E-bit semantics.
|
|
|
|
|
*/
|
|
|
|
|
if ( (oi->area->external_routing == OSPF_AREA_NSSA)
|
|
|
|
|
&& (CHECK_FLAG (nbr->options, OSPF_OPTION_NP))
|
|
|
|
|
&& (!CHECK_FLAG (dd->options, OSPF_OPTION_NP)) )
|
|
|
|
|
{
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-03 17:43:24 +01:00
|
|
|
|
zlog_debug ("Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options",
|
2003-06-19 02:26:34 +02:00
|
|
|
|
inet_ntoa (nbr->router_id) );
|
|
|
|
|
SET_FLAG (dd->options, OSPF_OPTION_NP);
|
|
|
|
|
}
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
#ifdef REJECT_IF_TBIT_ON
|
|
|
|
|
if (CHECK_FLAG (dd->options, OSPF_OPTION_T))
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* In Hello protocol, optional capability must have checked
|
|
|
|
|
* to prevent this T-bit enabled router be my neighbor.
|
|
|
|
|
*/
|
|
|
|
|
zlog_warn ("Packet[DD]: Neighbor %s: T-bit on?", inet_ntoa (nbr->router_id));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif /* REJECT_IF_TBIT_ON */
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
|
|
|
|
if (CHECK_FLAG (dd->options, OSPF_OPTION_O)
|
2003-03-25 06:07:42 +01:00
|
|
|
|
&& !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* This node is not configured to handle O-bit, for now.
|
|
|
|
|
* Clear it to ignore unsupported capability proposed by neighbor.
|
|
|
|
|
*/
|
|
|
|
|
UNSET_FLAG (dd->options, OSPF_OPTION_O);
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
/* Process DD packet by neighbor status. */
|
|
|
|
|
switch (nbr->state)
|
|
|
|
|
{
|
|
|
|
|
case NSM_Down:
|
|
|
|
|
case NSM_Attempt:
|
|
|
|
|
case NSM_TwoWay:
|
2004-11-30 23:38:43 +01:00
|
|
|
|
zlog_warn ("Packet[DD]: Neighbor %s state is %s, packet discarded.",
|
2004-12-11 19:00:06 +01:00
|
|
|
|
inet_ntoa(nbr->router_id),
|
2002-12-13 21:15:29 +01:00
|
|
|
|
LOOKUP (ospf_nsm_state_msg, nbr->state));
|
|
|
|
|
break;
|
|
|
|
|
case NSM_Init:
|
|
|
|
|
OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
|
|
|
|
|
/* If the new state is ExStart, the processing of the current
|
|
|
|
|
packet should then continue in this new state by falling
|
|
|
|
|
through to case ExStart below. */
|
|
|
|
|
if (nbr->state != NSM_ExStart)
|
|
|
|
|
break;
|
|
|
|
|
case NSM_ExStart:
|
|
|
|
|
/* Initial DBD */
|
|
|
|
|
if ((IS_SET_DD_ALL (dd->flags) == OSPF_DD_FLAG_ALL) &&
|
|
|
|
|
(size == OSPF_DB_DESC_MIN_SIZE))
|
|
|
|
|
{
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) > 0)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
/* We're Slave---obey */
|
2004-12-29 22:04:48 +01:00
|
|
|
|
zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Slave).",
|
2004-12-11 19:00:06 +01:00
|
|
|
|
inet_ntoa(nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
nbr->dd_seqnum = ntohl (dd->dd_seqnum);
|
|
|
|
|
nbr->dd_flags &= ~(OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I); /* Reset I/MS */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* We're Master, ignore the initial DBD from Slave */
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn ("Packet[DD]: Neighbor %s: Initial DBD from Slave, "
|
|
|
|
|
"ignoring.", inet_ntoa(nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Ack from the Slave */
|
|
|
|
|
else if (!IS_SET_DD_MS (dd->flags) && !IS_SET_DD_I (dd->flags) &&
|
|
|
|
|
ntohl (dd->dd_seqnum) == nbr->dd_seqnum &&
|
2003-03-25 06:07:42 +01:00
|
|
|
|
IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) < 0)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
2004-12-29 22:04:48 +01:00
|
|
|
|
zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Master).",
|
2004-12-11 19:00:06 +01:00
|
|
|
|
inet_ntoa(nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
nbr->dd_flags &= ~OSPF_DD_FLAG_I;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn ("Packet[DD]: Neighbor %s Negotiation fails.",
|
|
|
|
|
inet_ntoa(nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This is where the real Options are saved */
|
|
|
|
|
nbr->options = dd->options;
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("Neighbor[%s] is %sOpaque-capable.",
|
2002-12-13 21:15:29 +01:00
|
|
|
|
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));
|
|
|
|
|
/* This situation is undesirable, but not a real error. */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone);
|
|
|
|
|
|
|
|
|
|
/* continue processing rest of packet. */
|
|
|
|
|
ospf_db_desc_proc (s, oi, nbr, dd, size);
|
|
|
|
|
break;
|
|
|
|
|
case NSM_Exchange:
|
|
|
|
|
if (ospf_db_desc_is_dup (dd, nbr))
|
|
|
|
|
{
|
|
|
|
|
if (IS_SET_DD_MS (nbr->dd_flags))
|
|
|
|
|
/* Master: discard duplicated DD packet. */
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn ("Packet[DD] (Master): Neighbor %s packet duplicated.",
|
|
|
|
|
inet_ntoa (nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
else
|
|
|
|
|
/* Slave: cause to retransmit the last Database Description. */
|
|
|
|
|
{
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn ("Packet[DD] [Slave]: Neighbor %s packet duplicated.",
|
|
|
|
|
inet_ntoa (nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
ospf_db_desc_resend (nbr);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Otherwise DD packet should be checked. */
|
|
|
|
|
/* Check Master/Slave bit mismatch */
|
|
|
|
|
if (IS_SET_DD_MS (dd->flags) != IS_SET_DD_MS (nbr->last_recv.flags))
|
|
|
|
|
{
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn ("Packet[DD]: Neighbor %s MS-bit mismatch.",
|
|
|
|
|
inet_ntoa(nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",
|
2004-12-11 19:00:06 +01:00
|
|
|
|
dd->flags, nbr->dd_flags);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check initialize bit is set. */
|
|
|
|
|
if (IS_SET_DD_I (dd->flags))
|
|
|
|
|
{
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn ("Packet[DD]: Neighbor %s I-bit set.",
|
|
|
|
|
inet_ntoa(nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check DD Options. */
|
|
|
|
|
if (dd->options != nbr->options)
|
|
|
|
|
{
|
|
|
|
|
#ifdef ORIGINAL_CODING
|
|
|
|
|
/* Save the new options for debugging */
|
|
|
|
|
nbr->options = dd->options;
|
|
|
|
|
#endif /* ORIGINAL_CODING */
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn ("Packet[DD]: Neighbor %s options mismatch.",
|
|
|
|
|
inet_ntoa(nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check DD sequence number. */
|
|
|
|
|
if ((IS_SET_DD_MS (nbr->dd_flags) &&
|
|
|
|
|
ntohl (dd->dd_seqnum) != nbr->dd_seqnum) ||
|
|
|
|
|
(!IS_SET_DD_MS (nbr->dd_flags) &&
|
|
|
|
|
ntohl (dd->dd_seqnum) != nbr->dd_seqnum + 1))
|
|
|
|
|
{
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn ("Packet[DD]: Neighbor %s sequence number mismatch.",
|
|
|
|
|
inet_ntoa(nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Continue processing rest of packet. */
|
|
|
|
|
ospf_db_desc_proc (s, oi, nbr, dd, size);
|
|
|
|
|
break;
|
|
|
|
|
case NSM_Loading:
|
|
|
|
|
case NSM_Full:
|
|
|
|
|
if (ospf_db_desc_is_dup (dd, nbr))
|
|
|
|
|
{
|
|
|
|
|
if (IS_SET_DD_MS (nbr->dd_flags))
|
|
|
|
|
{
|
|
|
|
|
/* Master should discard duplicate DD packet. */
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn("Packet[DD]: Neighbor %s duplicated, packet discarded.",
|
|
|
|
|
inet_ntoa(nbr->router_id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
struct timeval t, now;
|
|
|
|
|
gettimeofday (&now, NULL);
|
|
|
|
|
t = tv_sub (now, nbr->last_send_ts);
|
|
|
|
|
if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0)
|
|
|
|
|
{
|
|
|
|
|
/* In states Loading and Full the slave must resend
|
|
|
|
|
its last Database Description packet in response to
|
|
|
|
|
duplicate Database Description packets received
|
|
|
|
|
from the master. For this reason the slave must
|
|
|
|
|
wait RouterDeadInterval seconds before freeing the
|
|
|
|
|
last Database Description packet. Reception of a
|
|
|
|
|
Database Description packet from the master after
|
|
|
|
|
this interval will generate a SeqNumberMismatch
|
|
|
|
|
neighbor event. RFC2328 Section 10.8 */
|
|
|
|
|
ospf_db_desc_resend (nbr);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn ("Packet[DD]: Neighbor %s NSM illegal status %u.",
|
|
|
|
|
inet_ntoa(nbr->router_id), nbr->state);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define OSPF_LSA_KEY_SIZE 12 /* type(4) + id(4) + ar(4) */
|
|
|
|
|
|
|
|
|
|
/* OSPF Link State Request Read -- RFC2328 Section 10.7. */
|
|
|
|
|
void
|
|
|
|
|
ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
|
|
|
|
|
struct stream *s, struct ospf_interface *oi, u_int16_t size)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_neighbor *nbr;
|
|
|
|
|
u_int32_t ls_type;
|
|
|
|
|
struct in_addr ls_id;
|
|
|
|
|
struct in_addr adv_router;
|
|
|
|
|
struct ospf_lsa *find;
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct list *ls_upd;
|
2004-10-11 13:00:30 +02:00
|
|
|
|
unsigned int length;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Increment statistics. */
|
|
|
|
|
oi->ls_req_in++;
|
|
|
|
|
|
2004-05-05 17:27:15 +02:00
|
|
|
|
nbr = ospf_nbr_lookup (oi, iph, ospfh);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
if (nbr == NULL)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("Link State Request: Unknown Neighbor %s.",
|
|
|
|
|
inet_ntoa (ospfh->router_id));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Neighbor State should be Exchange or later. */
|
|
|
|
|
if (nbr->state != NSM_Exchange &&
|
|
|
|
|
nbr->state != NSM_Loading &&
|
|
|
|
|
nbr->state != NSM_Full)
|
|
|
|
|
{
|
2004-11-30 23:38:43 +01:00
|
|
|
|
zlog_warn ("Link State Request received from %s: "
|
|
|
|
|
"Neighbor state is %s, packet discarded.",
|
|
|
|
|
inet_ntoa (ospfh->router_id),
|
2002-12-13 21:15:29 +01:00
|
|
|
|
LOOKUP (ospf_nsm_state_msg, nbr->state));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Send Link State Update for ALL requested LSAs. */
|
|
|
|
|
ls_upd = list_new ();
|
|
|
|
|
length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
|
|
|
|
|
|
|
|
|
|
while (size >= OSPF_LSA_KEY_SIZE)
|
|
|
|
|
{
|
|
|
|
|
/* Get one slice of Link State Request. */
|
|
|
|
|
ls_type = stream_getl (s);
|
|
|
|
|
ls_id.s_addr = stream_get_ipv4 (s);
|
|
|
|
|
adv_router.s_addr = stream_get_ipv4 (s);
|
|
|
|
|
|
|
|
|
|
/* Verify LSA type. */
|
|
|
|
|
if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA)
|
|
|
|
|
{
|
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
|
|
|
|
|
list_delete (ls_upd);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Search proper LSA in LSDB. */
|
|
|
|
|
find = ospf_lsa_lookup (oi->area, ls_type, ls_id, adv_router);
|
|
|
|
|
if (find == NULL)
|
|
|
|
|
{
|
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
|
|
|
|
|
list_delete (ls_upd);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-10 15:20:43 +01:00
|
|
|
|
/* Packet overflows MTU size, send immediately. */
|
|
|
|
|
if (length + ntohs (find->data->length) > ospf_packet_max (oi))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_NBMA)
|
|
|
|
|
ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
|
|
|
|
|
else
|
|
|
|
|
ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
|
|
|
|
|
|
|
|
|
|
/* Only remove list contents. Keep ls_upd. */
|
|
|
|
|
list_delete_all_node (ls_upd);
|
|
|
|
|
|
|
|
|
|
length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Append LSA to update list. */
|
|
|
|
|
listnode_add (ls_upd, find);
|
|
|
|
|
length += ntohs (find->data->length);
|
|
|
|
|
|
|
|
|
|
size -= OSPF_LSA_KEY_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Send rest of Link State Update. */
|
|
|
|
|
if (listcount (ls_upd) > 0)
|
|
|
|
|
{
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_NBMA)
|
|
|
|
|
ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
|
|
|
|
|
else
|
|
|
|
|
ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
|
|
|
|
|
|
|
|
|
|
list_delete (ls_upd);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
list_free (ls_upd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get the list of LSAs from Link State Update packet.
|
|
|
|
|
And process some validation -- RFC2328 Section 13. (1)-(2). */
|
2004-09-23 21:18:23 +02:00
|
|
|
|
static struct list *
|
2002-12-13 21:15:29 +01:00
|
|
|
|
ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,
|
|
|
|
|
struct ospf_interface *oi, size_t size)
|
|
|
|
|
{
|
|
|
|
|
u_int16_t count, sum;
|
|
|
|
|
u_int32_t length;
|
|
|
|
|
struct lsa_header *lsah;
|
|
|
|
|
struct ospf_lsa *lsa;
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct list *lsas;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
lsas = list_new ();
|
|
|
|
|
|
|
|
|
|
count = stream_getl (s);
|
|
|
|
|
size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */
|
|
|
|
|
|
|
|
|
|
for (; size >= OSPF_LSA_HEADER_SIZE && count > 0;
|
2005-02-09 16:51:56 +01:00
|
|
|
|
size -= length, stream_forward_getp (s, length), count--)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
lsah = (struct lsa_header *) STREAM_PNT (s);
|
|
|
|
|
length = ntohs (lsah->length);
|
|
|
|
|
|
|
|
|
|
if (length > size)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("Link State Update: LSA length exceeds packet size.");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Validate the LSA's LS checksum. */
|
|
|
|
|
sum = lsah->checksum;
|
|
|
|
|
if (sum != ospf_lsa_checksum (lsah))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("Link State Update: LSA checksum error %x, %x.",
|
|
|
|
|
sum, lsah->checksum);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Examine the LSA's LS type. */
|
|
|
|
|
if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("Link State Update: Unknown LS type %d", lsah->type);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* What if the received LSA's age is greater than MaxAge?
|
|
|
|
|
* Treat it as a MaxAge case -- endo.
|
|
|
|
|
*/
|
|
|
|
|
if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE)
|
|
|
|
|
lsah->ls_age = htons (OSPF_LSA_MAXAGE);
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
|
|
|
|
if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
|
|
|
|
|
{
|
|
|
|
|
#ifdef STRICT_OBIT_USAGE_CHECK
|
|
|
|
|
if ((IS_OPAQUE_LSA(lsah->type) &&
|
|
|
|
|
! CHECK_FLAG (lsah->options, OSPF_OPTION_O))
|
|
|
|
|
|| (! IS_OPAQUE_LSA(lsah->type) &&
|
|
|
|
|
CHECK_FLAG (lsah->options, OSPF_OPTION_O)))
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* This neighbor must know the exact usage of O-bit;
|
|
|
|
|
* the bit will be set in Type-9,10,11 LSAs only.
|
|
|
|
|
*/
|
|
|
|
|
zlog_warn ("LSA[Type%d:%s]: O-bit abuse?", lsah->type, inet_ntoa (lsah->id));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
#endif /* STRICT_OBIT_USAGE_CHECK */
|
|
|
|
|
|
|
|
|
|
/* Do not take in AS External Opaque-LSAs if we are a stub. */
|
|
|
|
|
if (lsah->type == OSPF_OPAQUE_AS_LSA
|
|
|
|
|
&& nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
|
|
|
|
|
{
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (IS_OPAQUE_LSA(lsah->type))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
/* Create OSPF LSA instance. */
|
|
|
|
|
lsa = ospf_lsa_new ();
|
|
|
|
|
|
|
|
|
|
/* We may wish to put some error checking if type NSSA comes in
|
|
|
|
|
and area not in NSSA mode */
|
|
|
|
|
switch (lsah->type)
|
|
|
|
|
{
|
|
|
|
|
case OSPF_AS_EXTERNAL_LSA:
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
|
|
|
|
case OSPF_OPAQUE_AS_LSA:
|
|
|
|
|
lsa->area = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case OSPF_OPAQUE_LINK_LSA:
|
|
|
|
|
lsa->oi = oi; /* Remember incoming interface for flooding control. */
|
|
|
|
|
/* Fallthrough */
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
default:
|
|
|
|
|
lsa->area = oi->area;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lsa->data = ospf_lsa_data_new (length);
|
|
|
|
|
memcpy (lsa->data, lsah, length);
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug("LSA[Type%d:%s]: %p new LSA created with Link State Update",
|
2002-12-13 21:15:29 +01:00
|
|
|
|
lsa->data->type, inet_ntoa (lsa->data->id), lsa);
|
|
|
|
|
listnode_add (lsas, lsa);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return lsas;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Cleanup Update list. */
|
|
|
|
|
void
|
2004-09-23 21:18:23 +02:00
|
|
|
|
ospf_upd_list_clean (struct list *lsas)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct listnode *node;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct ospf_lsa *lsa;
|
|
|
|
|
|
|
|
|
|
for (node = listhead (lsas); node; nextnode (node))
|
|
|
|
|
if ((lsa = getdata (node)) != NULL)
|
|
|
|
|
ospf_lsa_discard (lsa);
|
|
|
|
|
|
|
|
|
|
list_delete (lsas);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* OSPF Link State Update message read -- RFC2328 Section 13. */
|
|
|
|
|
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;
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct list *lsas;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct list *mylsa_acks, *mylsa_upds;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct listnode *node, *next;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct ospf_lsa *lsa = NULL;
|
|
|
|
|
/* unsigned long ls_req_found = 0; */
|
|
|
|
|
|
|
|
|
|
/* Dis-assemble the stream, update each entry, re-encapsulate for flooding */
|
|
|
|
|
|
|
|
|
|
/* Increment statistics. */
|
|
|
|
|
oi->ls_upd_in++;
|
|
|
|
|
|
|
|
|
|
/* Check neighbor. */
|
2004-05-05 17:27:15 +02:00
|
|
|
|
nbr = ospf_nbr_lookup (oi, iph, ospfh);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
if (nbr == NULL)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("Link State Update: Unknown Neighbor %s on int: %s",
|
|
|
|
|
inet_ntoa (ospfh->router_id), IF_NAME (oi));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check neighbor state. */
|
|
|
|
|
if (nbr->state < NSM_Exchange)
|
|
|
|
|
{
|
2004-12-11 19:00:06 +01:00
|
|
|
|
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));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get list of LSAs from Link State Update packet. - Also perorms Stages
|
|
|
|
|
* 1 (validate LSA checksum) and 2 (check for LSA consistent type)
|
|
|
|
|
* of section 13.
|
|
|
|
|
*/
|
|
|
|
|
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
|
|
|
|
|
* messages to be sent may have to be modified.
|
|
|
|
|
* To eliminate possible race conditions such that flushing and normal
|
|
|
|
|
* updating for the same LSA would take place alternately, this trick
|
|
|
|
|
* must be done before entering to the loop below.
|
|
|
|
|
*/
|
|
|
|
|
ospf_opaque_adjust_lsreq (nbr, lsas);
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
#define DISCARD_LSA(L,N) {\
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT) \
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \
|
2002-12-13 21:15:29 +01:00
|
|
|
|
ospf_lsa_discard (L); \
|
|
|
|
|
continue; }
|
|
|
|
|
|
|
|
|
|
/* Process each LSA received in the one packet. */
|
|
|
|
|
for (node = listhead (lsas); node; node = next)
|
|
|
|
|
{
|
|
|
|
|
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];
|
|
|
|
|
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug("LSA Type-%d from %s, ID: %s, ADV: %s",
|
2002-12-13 21:15:29 +01:00
|
|
|
|
lsa->data->type,
|
|
|
|
|
inet_ntop (AF_INET, &ospfh->router_id,
|
|
|
|
|
buf1, INET_ADDRSTRLEN),
|
|
|
|
|
inet_ntop (AF_INET, &lsa->data->id,
|
|
|
|
|
buf2, INET_ADDRSTRLEN),
|
|
|
|
|
inet_ntop (AF_INET, &lsa->data->adv_router,
|
|
|
|
|
buf3, INET_ADDRSTRLEN));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
listnode_delete (lsas, lsa); /* We don't need it in list anymore */
|
|
|
|
|
|
|
|
|
|
/* Validate Checksum - Done above by ospf_ls_upd_list_lsa() */
|
|
|
|
|
|
|
|
|
|
/* LSA Type - Done above by ospf_ls_upd_list_lsa() */
|
|
|
|
|
|
|
|
|
|
/* Do not take in AS External LSAs if we are a stub or NSSA. */
|
|
|
|
|
|
|
|
|
|
/* Do not take in AS NSSA if this neighbor and we are not NSSA */
|
|
|
|
|
|
|
|
|
|
/* Do take in Type-7's if we are an NSSA */
|
|
|
|
|
|
|
|
|
|
/* If we are also an ABR, later translate them to a Type-5 packet */
|
|
|
|
|
|
|
|
|
|
/* Later, an NSSA Re-fresh can Re-fresh Type-7's and an ABR will
|
|
|
|
|
translate them to a separate Type-5 packet. */
|
|
|
|
|
|
|
|
|
|
if (lsa->data->type == OSPF_AS_EXTERNAL_LSA)
|
|
|
|
|
/* Reject from STUB or NSSA */
|
|
|
|
|
if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
|
|
|
|
|
{
|
|
|
|
|
DISCARD_LSA (lsa, 1);
|
|
|
|
|
if (IS_DEBUG_OSPF_NSSA)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug("Incoming External LSA Discarded: We are NSSA/STUB Area");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug("Incoming NSSA LSA Discarded: Not NSSA Area");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find the LSA in the current database. */
|
|
|
|
|
|
|
|
|
|
current = ospf_lsa_lookup_by_header (oi->area, lsa->data);
|
|
|
|
|
|
|
|
|
|
/* If the LSA's LS age is equal to MaxAge, and there is currently
|
|
|
|
|
no instance of the LSA in the router's link state database,
|
|
|
|
|
and none of router's neighbors are in states Exchange or Loading,
|
|
|
|
|
then take the following actions. */
|
|
|
|
|
|
|
|
|
|
if (IS_LSA_MAXAGE (lsa) && !current &&
|
2003-03-25 06:07:42 +01:00
|
|
|
|
(ospf_nbr_count (oi, NSM_Exchange) +
|
|
|
|
|
ospf_nbr_count (oi, NSM_Loading)) == 0)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
/* Response Link State Acknowledgment. */
|
|
|
|
|
ospf_ls_ack_send (nbr, lsa);
|
|
|
|
|
|
|
|
|
|
/* Discard LSA. */
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn("Link State Update[%s]: LS age is equal to MaxAge.",
|
|
|
|
|
dump_lsa_key(lsa));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
DISCARD_LSA (lsa, 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
|
|
|
|
if (IS_OPAQUE_LSA (lsa->data->type)
|
2003-03-25 06:07:42 +01:00
|
|
|
|
&& IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Even if initial flushing seems to be completed, there might
|
|
|
|
|
* be a case that self-originated LSA with MaxAge still remain
|
|
|
|
|
* in the routing domain.
|
|
|
|
|
* Just send an LSAck message to cease retransmission.
|
|
|
|
|
*/
|
|
|
|
|
if (IS_LSA_MAXAGE (lsa))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("LSA[%s]: Boomerang effect?", dump_lsa_key (lsa));
|
|
|
|
|
ospf_ls_ack_send (nbr, lsa);
|
|
|
|
|
ospf_lsa_discard (lsa);
|
|
|
|
|
|
|
|
|
|
if (current != NULL && ! IS_LSA_MAXAGE (current))
|
|
|
|
|
ospf_opaque_lsa_refresh_schedule (current);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If an instance of self-originated Opaque-LSA is not found
|
|
|
|
|
* in the LSDB, there are some possible cases here.
|
|
|
|
|
*
|
|
|
|
|
* 1) This node lost opaque-capability after restart.
|
|
|
|
|
* 2) Else, a part of opaque-type is no more supported.
|
|
|
|
|
* 3) Else, a part of opaque-id is no more supported.
|
|
|
|
|
*
|
|
|
|
|
* Anyway, it is still this node's responsibility to flush it.
|
|
|
|
|
* Otherwise, the LSA instance remains in the routing domain
|
|
|
|
|
* until its age reaches to MaxAge.
|
|
|
|
|
*/
|
|
|
|
|
if (current == NULL)
|
|
|
|
|
{
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("LSA[%s]: Previously originated Opaque-LSA, not found in the LSDB.", dump_lsa_key (lsa));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
SET_FLAG (lsa->flags, OSPF_LSA_SELF);
|
|
|
|
|
listnode_add (mylsa_upds, ospf_lsa_dup (lsa));
|
|
|
|
|
listnode_add (mylsa_acks, ospf_lsa_lock (lsa));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
2004-02-11 22:10:19 +01:00
|
|
|
|
/* 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
|
|
|
|
|
* Advertising Router is not equal to the router's own Router ID
|
|
|
|
|
* According to RFC 2328 12.4.2 and 13.4 this LSA should be flushed.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if(lsa->data->type == OSPF_NETWORK_LSA)
|
|
|
|
|
{
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct listnode *oi_node;
|
2004-02-11 22:10:19 +01:00
|
|
|
|
int Flag = 0;
|
|
|
|
|
|
|
|
|
|
for(oi_node = listhead(oi->ospf->oiflist); oi_node; oi_node = nextnode(oi_node))
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *out_if = getdata(oi_node);
|
|
|
|
|
if(out_if == NULL)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if((IPV4_ADDR_SAME(&out_if->address->u.prefix4, &lsa->data->id)) &&
|
|
|
|
|
(!(IPV4_ADDR_SAME(&oi->ospf->router_id, &lsa->data->adv_router))))
|
|
|
|
|
{
|
|
|
|
|
if(out_if->network_lsa_self)
|
|
|
|
|
{
|
|
|
|
|
ospf_lsa_flush_area(lsa,out_if->area);
|
|
|
|
|
if(IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d",
|
2004-02-11 22:10:19 +01:00
|
|
|
|
lsa, (int) lsa->data->type);
|
|
|
|
|
ospf_lsa_discard (lsa);
|
|
|
|
|
Flag = 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(Flag)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* (5) Find the instance of this LSA that is currently contained
|
|
|
|
|
in the router's link state database. If there is no
|
|
|
|
|
database copy, or the received LSA is more recent than
|
|
|
|
|
the database copy the following steps must be performed. */
|
|
|
|
|
|
|
|
|
|
if (current == NULL ||
|
|
|
|
|
(ret = ospf_lsa_more_recent (current, lsa)) < 0)
|
|
|
|
|
{
|
|
|
|
|
/* Actual flooding procedure. */
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (ospf_flood (oi->ospf, nbr, current, lsa) < 0) /* Trap NSSA later. */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
DISCARD_LSA (lsa, 4);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* (6) Else, If there is an instance of the LSA on the sending
|
|
|
|
|
neighbor's Link state request list, an error has occurred in
|
|
|
|
|
the Database Exchange process. In this case, restart the
|
|
|
|
|
Database Exchange process by generating the neighbor event
|
|
|
|
|
BadLSReq for the sending neighbor and stop processing the
|
|
|
|
|
Link State Update packet. */
|
|
|
|
|
|
|
|
|
|
if (ospf_ls_request_lookup (nbr, lsa))
|
|
|
|
|
{
|
|
|
|
|
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
|
2004-12-11 19:00:06 +01:00
|
|
|
|
zlog_warn("LSA[%s] instance exists on Link state request list",
|
|
|
|
|
dump_lsa_key(lsa));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If the received LSA is the same instance as the database copy
|
|
|
|
|
(i.e., neither one is more recent) the following two steps
|
|
|
|
|
should be performed: */
|
|
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
|
{
|
|
|
|
|
/* If the LSA is listed in the Link state retransmission list
|
|
|
|
|
for the receiving adjacency, the router itself is expecting
|
|
|
|
|
an acknowledgment for this LSA. The router should treat the
|
|
|
|
|
received LSA as an acknowledgment by removing the LSA from
|
|
|
|
|
the Link state retransmission list. This is termed an
|
|
|
|
|
"implied acknowledgment". */
|
|
|
|
|
|
|
|
|
|
ls_ret = ospf_ls_retransmit_lookup (nbr, lsa);
|
|
|
|
|
|
|
|
|
|
if (ls_ret != NULL)
|
|
|
|
|
{
|
|
|
|
|
ospf_ls_retransmit_delete (nbr, ls_ret);
|
|
|
|
|
|
|
|
|
|
/* Delayed acknowledgment sent if advertisement received
|
|
|
|
|
from Designated Router, otherwise do nothing. */
|
|
|
|
|
if (oi->state == ISM_Backup)
|
|
|
|
|
if (NBR_IS_DR (nbr))
|
|
|
|
|
listnode_add (oi->ls_ack, ospf_lsa_lock (lsa));
|
|
|
|
|
|
|
|
|
|
DISCARD_LSA (lsa, 5);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
/* Acknowledge the receipt of the LSA by sending a
|
|
|
|
|
Link State Acknowledgment packet back out the receiving
|
|
|
|
|
interface. */
|
|
|
|
|
{
|
|
|
|
|
ospf_ls_ack_send (nbr, lsa);
|
|
|
|
|
DISCARD_LSA (lsa, 6);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The database copy is more recent. If the database copy
|
|
|
|
|
has LS age equal to MaxAge and LS sequence number equal to
|
|
|
|
|
MaxSequenceNumber, simply discard the received LSA without
|
|
|
|
|
acknowledging it. (In this case, the LSA's LS sequence number is
|
|
|
|
|
wrapping, and the MaxSequenceNumber LSA must be completely
|
|
|
|
|
flushed before any new LSA instance can be introduced). */
|
|
|
|
|
|
|
|
|
|
else if (ret > 0) /* Database copy is more recent */
|
|
|
|
|
{
|
|
|
|
|
if (IS_LSA_MAXAGE (current) &&
|
|
|
|
|
current->data->ls_seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER))
|
|
|
|
|
{
|
|
|
|
|
DISCARD_LSA (lsa, 7);
|
|
|
|
|
}
|
|
|
|
|
/* Otherwise, as long as the database copy has not been sent in a
|
|
|
|
|
Link State Update within the last MinLSArrival seconds, send the
|
|
|
|
|
database copy back to the sending neighbor, encapsulated within
|
|
|
|
|
a Link State Update Packet. The Link State Update Packet should
|
|
|
|
|
be sent directly to the neighbor. In so doing, do not put the
|
|
|
|
|
database copy of the LSA on the neighbor's link state
|
|
|
|
|
retransmission list, and do not acknowledge the received (less
|
|
|
|
|
recent) LSA instance. */
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
struct timeval now;
|
|
|
|
|
|
|
|
|
|
gettimeofday (&now, NULL);
|
|
|
|
|
|
|
|
|
|
if (tv_cmp (tv_sub (now, current->tv_orig),
|
|
|
|
|
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);
|
2003-03-28 01:43:48 +01:00
|
|
|
|
list_delete (mylsa_acks);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
assert (listcount (lsas) == 0);
|
|
|
|
|
list_delete (lsas);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
|
|
|
|
|
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
|
2004-09-24 10:01:38 +02:00
|
|
|
|
struct list *opaque_acks;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
/* increment statistics. */
|
|
|
|
|
oi->ls_ack_in++;
|
|
|
|
|
|
2004-05-05 17:27:15 +02:00
|
|
|
|
nbr = ospf_nbr_lookup (oi, iph, ospfh);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
if (nbr == NULL)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("Link State Acknowledgment: Unknown Neighbor %s.",
|
|
|
|
|
inet_ntoa (ospfh->router_id));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nbr->state < NSM_Exchange)
|
|
|
|
|
{
|
2004-12-11 19:00:06 +01:00
|
|
|
|
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));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
|
|
|
|
opaque_acks = list_new ();
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
while (size >= OSPF_LSA_HEADER_SIZE)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_lsa *lsa, *lsr;
|
|
|
|
|
|
|
|
|
|
lsa = ospf_lsa_new ();
|
|
|
|
|
lsa->data = (struct lsa_header *) STREAM_PNT (s);
|
|
|
|
|
|
|
|
|
|
/* lsah = (struct lsa_header *) STREAM_PNT (s); */
|
|
|
|
|
size -= OSPF_LSA_HEADER_SIZE;
|
2005-02-09 16:51:56 +01:00
|
|
|
|
stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA)
|
|
|
|
|
{
|
|
|
|
|
lsa->data = NULL;
|
|
|
|
|
ospf_lsa_discard (lsa);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lsr = ospf_ls_retransmit_lookup (nbr, 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));
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
ospf_ls_retransmit_delete (nbr, lsr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lsa->data = NULL;
|
|
|
|
|
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 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct stream *
|
|
|
|
|
ospf_recv_packet (int fd, struct interface **ifp)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
struct ip iph;
|
|
|
|
|
u_int16_t ip_len;
|
|
|
|
|
struct stream *ibuf;
|
|
|
|
|
unsigned int ifindex = 0;
|
|
|
|
|
struct iovec iov;
|
2004-08-26 15:14:07 +02:00
|
|
|
|
/* Header and data both require alignment. */
|
2004-08-26 15:19:40 +02:00
|
|
|
|
char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
|
2004-07-23 17:13:48 +02:00
|
|
|
|
struct msghdr msgh;
|
|
|
|
|
|
2004-09-27 09:27:13 +02:00
|
|
|
|
memset (&msgh, 0, sizeof (struct msghdr));
|
2004-07-23 17:13:48 +02:00
|
|
|
|
msgh.msg_iov = &iov;
|
|
|
|
|
msgh.msg_iovlen = 1;
|
|
|
|
|
msgh.msg_control = (caddr_t) buff;
|
|
|
|
|
msgh.msg_controllen = sizeof (buff);
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
ret = recvfrom (fd, (void *)&iph, sizeof (iph), MSG_PEEK, NULL, 0);
|
|
|
|
|
|
|
|
|
|
if (ret != sizeof (iph))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("ospf_recv_packet packet smaller than ip header");
|
2004-12-29 21:12:59 +01:00
|
|
|
|
/* XXX: We peeked, and thus perhaps should discard this packet. */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2004-10-05 16:38:29 +02:00
|
|
|
|
|
|
|
|
|
sockopt_iphdrincl_swab_systoh (&iph);
|
|
|
|
|
|
2004-10-11 12:11:25 +02:00
|
|
|
|
ip_len = iph.ip_len;
|
|
|
|
|
|
2003-12-08 11:34:54 +01:00
|
|
|
|
#if !defined(GNU_LINUX) && (OpenBSD < 200311)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
/*
|
|
|
|
|
* Kernel network code touches incoming IP header parameters,
|
|
|
|
|
* before protocol specific processing.
|
|
|
|
|
*
|
|
|
|
|
* 1) Convert byteorder to host representation.
|
|
|
|
|
* --> ip_len, ip_id, ip_off
|
|
|
|
|
*
|
|
|
|
|
* 2) Adjust ip_len to strip IP header size!
|
|
|
|
|
* --> If user process receives entire IP packet via RAW
|
|
|
|
|
* socket, it must consider adding IP header size to
|
|
|
|
|
* the "ip_len" field of "ip" structure.
|
|
|
|
|
*
|
|
|
|
|
* For more details, see <netinet/ip_input.c>.
|
|
|
|
|
*/
|
|
|
|
|
ip_len = ip_len + (iph.ip_hl << 2);
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-02-14 Paul Jakma <paul.jakma@sun.com>
* ospf_packet.c: (ospf_recv_packet) use stream_recvmsg.
2005-02-11 Hasso Tepper <hasso at quagga.net>
* ospf_lsdb.c: Fix sum of checksums calculation.
2005-02-09 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_write) If sendmsg fails, give more info in the
error message.
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_interface.h: Reduce structure padding by putting new u_char
field multicast_memberships in a better spot (grouped with
other u_char fields type and state).
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_interface.h: Improve passive_interface comment. Add new
multicast_memberships bitmask to struct ospf_interface to track
active multicast subscriptions. Declare new function
ospf_if_set_multicast.
* ospf_interface.c: (ospf_if_set_multicast) New function to configure
multicast memberships properly based on the current
multicast_memberships status and the current values of the
ospf_interface state, type, and passive_interface status.
(ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is
now handled by ism_change_state's call to ospf_if_set_multicast).
(ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now
handled by ism_change_state).
* ospf_ism.c: (ospf_dr_election) Remove logic to join or leave
the DRouters multicast group (now handled by ism_change_state's call
to ospf_if_set_multicast).
(ism_change_state) Add call to ospf_if_set_multicast to change
multicast memberships as necessary to reflect the new interface state.
* ospf_packet.c: (ospf_hello) When a Hello packet is received on a
passive interface: 1. Increase the severity of the error message
from LOG_INFO to LOG_WARNING; 2. Add more information to the error
message (packet destination address and interface address);
and 3. If the packet was sent to ospf-all-routers, then try
to fix the multicast group memberships.
(ospf_read) When a packet is received on an interface whose state
is ISM_Down, enhance the warning message to show the packet
destination address, and try to update/fix the multicast group
memberships if the packet was sent to a multicast address.
When a packet is received for ospf-designated-routers, but the
current interface state is not DR or BDR, then increase the
severity level of the error message from LOG_INFO to LOG_WARNING,
and try to fix the multicast group memberships.
* ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for
any ospf interface that may have changed from active to passive.
(no_ospf_passive_interface) Call ospf_if_set_multicast for
any ospf interface that may have changed from passive to active.
(show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (various) Remove unneeded stream_set_putp abuse.
2005-02-02 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_read) Fix bug: must check for state ISM_Down,
not for event ISM_InterfaceDown. And improve the message by
adding the interface flags.
2005-01-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_network.c: (ospf_sock_init) Save errno before calling
ospfd_privs.change.
2005-01-29 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_packet_add) If oi->obuf is NULL, print
an error message and return.
(ospf_read) If the interface state is ISM_InterfaceDown, issue
a warning message and ignore the packet.
2005-01-10 Greg Troxel <gdt@fnord.ir.bbn.com>
* ospf_packet.h: Remove commented out definition of
OSPF_MAX_PACKET; neither it or the uncommented one are used any more.
* ospf_packet.c (ospf_make_ls_upd): Leave room for authentication
when deciding if an update will fit.
(ospf_packet_authspace): Factor out calculation of size required
for authentication.
(ospf_make_db_desc): Use ospf_max_packet, not OSPF_MAX_PACKET.
Don't confuse readers that there is a macro.
2004-12-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_network.c: Improve all setsockopt error messages to give detailed
information on the arguments.
2004-12-29 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_db_desc) Reduce severity of "Negotiation done"
messages from LOG_WARNING to LOG_INFO, since this seems to be
normal.
2004-12-29 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_read) Always look up the interface if
ospf_recv_packet returns NULL ifp, since some platforms such
as Solaris 8 appear to support ifindex retrieval but don't.
2004-12-22 Hasso Tepper <hasso at quagga.net>
* ospf_dump.c: Show debug configuration in vtysh.
* ospf_vty.c: Fix "show ip ospf" output. Router can't be elected in
any case if it's configured as "translate-never".
* ospf_lsdb.[ch]: New function to calculate sum of checksums.
* ospf_vty.c: Bugfix to show really number of AS external LSAs, not
number of all LSAs with AS scope, this includes opaque as LSAs as
well, show this number separately. Show numbers and sums of
checksums for each type of LSAs.
* ospf_lsa.c: Calculate checksum before putting LSA into database.
2004-12-15 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_interface.h: Declare new function ospf_default_iftype.
* ospf_interface.c: (ospf_default_iftype) New function to centralize
this logic in one place.
* ospf_zebra.c: (ospf_interface_add) Use new function
ospf_default_iftype.
* ospf_vty.c: (no_ip_ospf_network,config_write_interface) Fix logic
by using new function ospf_default_iftype.
2004-12-11 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_db_desc) Should be static, not global.
(ospf_hello,ospf_db_desc,ospf_ls_upd,ospf_ls_ack) Improve warning
messages to include identifying information (e.g. router id).
* ospf_nsm.c: (nsm_change_state) Improve info message to include
router id and state names.
2004-12-09 Greg Troxel <gdt@fnord.ir.bbn.com>
* ospf_apiserver.c (ospf_apiserver_term): Obtain struct
ospf_apiserver * from listnode. Remove unused variables. Follows
suggestion from Jay Fenlason.
2004-12-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* *.c: Change level of debug messages to LOG_DEBUG.
2004-12-07 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_main.c: (main) The 2nd argument to openzlog has been removed.
2004-12-03 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_db_desc) Reduce priority on a debug message
from LOG_NOTICE to LOG_DEBUG.
2004-12-03 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_main.c: (sigint) Use zlog_notice for termination message.
(main) Issue a startup announcement using zlog_notice.
2004-11-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_db_desc_proc) Fix spelling of packet in warning
message and in comment.
(ospf_db_desc) Warning message that a packet is being discarded
should give the router id of the packet source. Fix spelling
of packet in two warning messages.
(ospf_ls_req) Warning message that a link state request is being
discarded should give the router id of the neighbor that sent it.
2004-11-26 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_main.c: Remove #include "debug.h" (was not being used, and
lib/debug.h has now been deleted).
2004-11-25 Hasso Tepper <hasso at quagga.net>
* ospf_main.c: Make group to run as configurable.
2004-11-15 Greg Troxel <gdt@fnord.ir.bbn.com>
* ospf_packet.c (ospf_recv_packet): Assume CMSG_SPACE is present
and works (lib/zebra.h provides if OS doesn't).
2004-11-15 Paul Jakma <paul@dishone.st>
* ospf_{apiserver,te}.c: ospf_lsa_free's should be ospf_lsa_unlock.
2004-11-12 Paul Jakma <paul@dishone.st>
* ospf_ia.c: (process_summary_lsa) Only an ABR has any reason to
ignore stub area summary default. Even so it seems a strange
check, add a comment to that effect.
2004-11-04 Paul Jakma <paul@dishone.st>
* ospfd.c: (ospf_network_match_iface) revert to previous network
statement match behaviour.
2004-11-02 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_write_frags) remove iov arg, msg already points
to it. Add convenience pointer to msg->msg_iov[1], and use this,
fixing the unfortunate borkenness introduced in moving of this code
to a function.
(ospf_write) remove iovp and fix up call to previous.
(ospf_ls_upd_packet_new) cast size to long int - unfortunately
glibc's size_t format modifier is not portable.
2004-10-31 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_write_frags) Add debug output
(ospf_write) set type early, so we can pass it to
ospf_write_frags.
(ospf_ls_upd_packet_new) print size in debug output when too large
packet is encountered.
* ospf_zebra.c: (ospf_distribute_list_update_timer) Ugly misuse of
THREAD_ARG to store an integer, but it should at least use same
same type to retrieve the value. Assert value is sane.
2004-10-22 Paul Jakma <paul@dishone.st>
* ospf_network.c: (ospf_sock_init) call neutral setsock_ifindex()
function.
* ospf_packet.c: (ospf_read) manually look up ifindex
if system could not have returned one, eg openbsd, thanks to Rivo
Nurges for highlighting problem and fix.
Change setsockopt_pktinfo to setsockopt_ifindex.
2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
* ospf_snmp.c: (ospf_snmp_if_update) Fix logic to handle PtP links
with dedicated subnets properly.
* ospf_lsa.c: (lsa_link_ptop_set) ditto.
* ospfd.c: (ospf_network_match_iface) ditto.
(ospf_network_run) ditto.
* ospf_interface.c: (ospf_if_is_configured) ditto.
(ospf_if_lookup_by_prefix) ditto.
(ospf_if_lookup_recv_if) ditto.
* ospf_vty.c: (show_ip_ospf_interface_sub) Display the peer or
broadcast address if present.
2004-10-13 Hasso Tepper <hasso at quagga.net>
* ospf_main.c: Unbreak compilation with ospfapi disabled.
* ospf_snmp.c: Remove defaults used to initialize smux connection to
snmpd. Connection is initialized only if smux peer is configured.
2004-10-12 Hasso Tepper <hasso at quagga.net>
* ospf_main.c, ospf_opaque.c: Unbreak ospfclient compilation - move
static variable from ospf_main.c into ospf_opaque.c.
2004-10-11 Hasso Tepper <hasso at quagga.net>
* ospf_main.c, ospf_opaque.c: Disable ospfapi init by default. New
command line switch to enable it.
2004-10-11 Paul Jakma <paul@dishone.st>
* ospf_dump.c: (ospf_ip_header_dump) Assume header is in host order
remove ntohs that should have dissappeared. Take struct ip
as argument, caller has to know there's an IP header at start of
stream anyway.
* ospf_dump.h: update declaration of ospf_ip_header_dump.
* ospf_packet.c: (ospf_write) correct call to
sockopt_iphdrincl_swab_htosys which was munging the header.
(ospf_recv_packet) ip_len is needed for old OpenBSD fixup.
(ospf_read) sockopt_iphdrincl_swab_systoh ip header as soon as
we have it.
* (global) Const char update and signed/unsigned fixes.
* (various headers) size defines should be unsigned.
* ospf_interface.h: remove duplicated defines, include the
authoritative header - though, these defines should probably
be moved to a dedicated header, or ospfd.h.
* ospf_lsa.h: (struct lsa) ls_seqnum should be unsigned.
* ospf_packet.c: (ospf_write) cast result of shift to unsigned.
2004-10-08 Hasso Tepper <hasso at quagga.net>
* *.[c|h]: Fix compiler warnings: make some strings const, signed ->
unsigned, remove unused variables etc.
2004-10-07 Greg Troxel <gdt@claude.ir.bbn.com>
* ospf_apiserver.c (ospf_apiserver_unregister_opaque_type): Don't
use of variable names 'node' and 'nextnode' to avoid possible
conflict with list macros. Move variable declaration inside for
loop after a statement to top of function.
2004-10-07 Paul Jakma <paul@dishone.st>
* ospf_snmp.c: Missed list typedef update
* ospf_dump.c: Include sockopt.h for header swab functions.
2004-10-05 Paul Jakma <paul@dishone.st>
* ospf_packet.c: replace ospf_swap_iph_to... with
sockopt_iphdrincl_swab_...
2004-10-03 James R. Leu <jleu at mindspring.com>
* ospf_zebra.c: Read router id related messages from zebra daemon.
Schedule router-id update thread if it's changed.
* ospfd.c: Remove own router-id selection function. Use router id from
zebra daemon if it isn't manually overriden in configuration.
2004-09-27 Paul Jakma <paul@dishone.st>
* ospf_dump.c: (ospf_ip_header_dump) Use HAVE_IP_HDRINCL_BSD_ORDER
Apply to offset too. Print ip_cksum, lets not worry about
possible 2.0.37 compile problems.
* ospf_packet.c: (ospf_swap_iph_to{n,h}) Use
HAVE_IP_HDRINCL_BSD_ORDER.
(ospf_recv_packet) ditto.
(ospf_write) Fixup iov argument to ospf_write_frags.
(struct msghdr).msg_name is caddr_t on most platforms.
(ospf_recv_packet) ditto. And msg_flags is not always there
memset struct then set fields we care about rather than
initialise all fields individually.
2004-09-26 Hasso Tepper <hasso at quagga.net>
* ospf_abr.c, ospf_dump.c, ospf_lsa.c, ospf_packet.c, ospf_vty.c,
ospf_zebra.c: Fix compiler warnings.
2004-09-24 Paul Jakma <paul@dishone.st>
* ospf_apiserver.{c,h}: lists typedef removal cleanup.
update some list loops to LIST_LOOP. some miscellaneous indent
fixups.
(ospf_apiserver_unregister_opaque_type) fix listnode_delete of
referenced node in loop.
(ospf_apiserver_term) loops calling ospf_apiserver_free, which
deletes referenced nodes from apiserver_list, fixed.
* ospf_interface.h: lists typedef removal cleanup.
* ospf_opaque.{c,h}: lists typedef removal cleanup. update some list
loops to LIST_LOOP. miscellaneous style and indent fixups.
* ospf_te.{c,h}: ditto
* ospf_packet.c: lists typedef removal cleanup.
(ospf_write) ifdef fragmentation support. move actual
fragmentation out to a new, similarly ifdefed, function.
(ospf_write_frags) fragmented write support, moved from previous.
2004-09-23 Hasso Tepper <hasso at quagga.net>
* *.[c|h]: list -> struct list *, listnode -> struct listnode *.
2004-09-12 Paul Jakma <paul@dishone.st>
* ospf_packet.c: Fix bugzilla #107
(ospf_packet_max) get rid of the magic 88 constant
(ospf_swab_iph_ton) new function. set ip header to network order,
taking BSDisms into account.
(ospf_swab_iph_toh) the inverse.
(ospf_write) Add support for IP fragmentation, will only work on
linux though, other kernels make it impossible. get rid of the
magic 4 constant.
(ospf_make_ls_upd) Bound check to end of stream, not to
interface mtu.
(ospf_ls_upd_packet_new) New function, allocate upd packet
taking oversized LSAs into account.
(ospf_ls_upd_queue_send) use ospf_ls_upd_packet_new to allocate,
rather than statically allocating mtu sized packet buffer, which
actually was wrong - it didnt take ip header into account, which
should not be included in packet buffer.
(ospf_ls_upd_send_queue_event) minor tweaks and remove
TODO comment.
2004-08-31 David Wiggins <dwiggins@bbn.com>
* ospf_spf.c (ospf_spf_calculate): Many more comments and debug
print statements. New function ospf_vertex_dump used in debugging.
2004-08-31 David Wiggins <dwiggins@bbn.com>
* ospf_spf.h (struct vertex): Comments for flags and structure members.
2004-08-31 David Wiggins <dwiggins@bbn.com>
* ospf_route.c: When finding an alternate route, log cost as well.
2004-08-31 David Wiggins <dwiggins@bbn.com>
* ospf_interface.c (ospf_lookup_if_params): Initialize af in
struct prefix allocated on stack.
2004-08-31 David Wiggins <dwiggins@bbn.com>
* ospf_packet.c (ospf_ls_ack_send_delayed): In p2mp mode, send
acks to AllSPFRouters, rather than All-DR.
2004-08-27 Hasso Tepper <hasso at quagga.net>
* ospf_vty.c: Don't print ospf network type under interface only
if interface is in broadcast mode and interface type really is
broadcast. Fixes Bugzilla #108.
2004-08-27 David Wiggins <dwiggins@bbn.com>
* ospf_spf.c (ospf_nexthop_calculation): Initialize address family
in on-stack struct prefix_ipv4. Fixes point-to-multipoint SPF
calculation.
2004-08-26 Greg Troxel <gdt@fnord.ir.bbn.com>
* ospf_packet.c (ospf_recv_packet): adjust size declaration of
buffer used to get interface index so that it compiles on other
than Linux and includes the required alignment space. Probably
this was only working on sparc/sparc64 because most of
sockaddr_dl was not being written.
2004-08-19 Paul Jakma <paul@dishone.st>
* ospf_packet.c: update to match sockopt renames.
2004-08-04 Paul Jakma <paul@dishone.st>
* ospf_spf.c: (ospf_spf_consider_nexthop) Add comment about issue.
Compare only against list head - all nexthops must be same cost
anyway, fixes a reference-listnode-after-delete bug noted by
Kir Kostuchenko.
(ospf_nexthop_calculation) Use ospf_spf_consider_nexthop for all
candidates attached to root.
2004-07-27 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_ls_upd_send_queue_event) fix thinko from
last fix for ospfd wedging due to oversize LSAs: dont list loop on
ospf_ls_upd_queue_send() - guaranteed segfault.
2004-07-27 Paul Jakma <paul@dishone.st>
* ospf_opaque.c: (ospf_opaque_lsa_flush_schedule) do not NULL out
the LSA as then free_opaque_info_per_id() can never unlock (and
free) the LSA. Reported by Gunnar Stigen.
2004-07-23 Paul Jakma <paul@dishone.st>
* ospf_network.c: Replace PKTINFO/RECVIF with call to
setsockopt_pktinfo
* ospf_packet.c: Use getsockopt_pktinfo_ifindex and
SOPT_SIZE_CMSG_PKTINFO_IPV4.
2004-07-14 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_ls_upd_send_queue_event) Partial fix for
problem reported by Peter Frost amongst others, where function
will spin indefinitely if update list contains LSAs greater than
MTU-headers or other condition leading to update list never being
cleared. Problem of what to do with these LSAs remains.
(ospf_make_ls_upd) add comment about large LSA problem,
indentation cleanup.
2004-07-01 Greg Troxel <gdt@fnord.ir.bbn.com>
* Makefile.am (lib_LTLIBRARIES): make libospf shared
2004-06-30 Greg Troxel <gdt@poblano.ir.bbn.com>
* Makefile.am: Add shlib support.
2004-06-10 Hasso Tepper <hasso@estpak.ee>
* *: Removed ifdefs HAVE_NSSA.
2004-06-06 Paul Jakma <paul@dishone.st>
* ospf_dump.c,ospf_lsa.c: Fix typos of merge of previous.
ospf_flood.c: (ospf_process_self_originated_lsa) fix zlog format
2004-05-31 Sagun Shakya <sagun.shakya@sun.com>
* ospf_dump.c: (ospf_lsa_header_dump) LOOKUP can return null if
index is out of range.
ospf_flood.c: endianness fix
ospf_lsa.c: Missing ntohl's on (struct lsa *)->data->ls_seqnum
in various places.
2004-05-10 Hasso Tepper <hasso@estpak.ee>
* ospf_zebra.c, ospfd.c: Move ospf_prefix_list_update() function
to ospf_zebra.c from ospfd.c and add redistribution updates if
route-map is used in redistribution.
* ospf_main.c: Remove now useless call to ospf_init().
2004-05-08 Paul Jakma <paul@dishone.st>
* ospf_zebra.c: Sync with lib/zclient changes
2004-05-05 Paul Jakma <paul@dishone.st>
* ospf_network.c: (ospf_sock_init) Check whether IP_HDRINCL is
defined. Warn at compile and runtime. Use
IPTOS_PREC_INTERNETCONTROL otherwise.
* ospf_packet.c: (ospf_associate_packet_vl) cleanup, move
some of the checks up to ospf_read, return either a
virtual link oi, or NULL.
(ospf_read) Cleanup, make it responsible for checks. Remove
the nbr lookup - moved to ospf_neighbor. Adjust all nbr
lookups to use new wrappers exported by ospf_neighbor.
* ospf_neighbor.h: Add ospf_neigbour_get and ospf_nbr_lookup.
* ospf_neighbor.c: (ospf_neigbour_get) Index ospf_interface
neighbour table by router-id for virtual-link ospf_interfaces,
not by peer_addr (which breaks for asymmetric vlinks)
(ospf_nbr_lookup) add a wrapper for nbr lookups to deal with
above.
* ospf_interface.c: (ospf_vl_set_params) Catch changes of interface
address for either end of a virtual-link, and hence potential cost
changes.
2004-04-22 Hasso Tepper <hasso@estpak.ee>
* ospf_zebra.c: Don't ignore reject/bh routes, it's the only way
to "summarize" routes in ASBR at the moment.
2004-04-20 Hasso Tepper <hasso@estpak.ee>
* ospfd.c: Unset NP flag if area is going to be normal or stub.
Fixes UNH OSPF_NSSA.1.2a comment.
* ospf_abr.c: Originate default into stub/nssa area even if
summaries are disabled.
* ospf_zebra.c: Don't attempt to redistribute 127.0.0.0/8.
2004-04-19 Hasso Tepper <hasso@estpak.ee>
* ospf_vty.c: Don't warn that export- and import-list can't be
configured to backbone area if they are applied and are working
fine.
2004-02-19 Sowmini Varadhan <sowmini.varadhan@sun.com>
* ospf_packet.c: Don't drop packets in Solaris x86.
[quagga-dev 1005].
2004-03-18 Amir Guindehi <amir@datacore.ch>
* ospf_opaque.c: Attempt to correct the incorrect behavior of
Quagga's ospfd in the special situation that a node's opaque
capability has changed as "ON -> OFF -> ON". [quagga-dev 843].
2004-02-19 Sowmini Varadhan <sowmini.varadhan@sun.com>
* ospf_abr.c: (ospf_abr_update_aggregate) UNH 3.12b,c, address range
should be configured with the highest cost path within the range,
not lowest.
2004-02-17 Paul Jakma <paul@dishone.st>
* ospf_zebra.c: (ospf_interface_delete) Do not delete the interface
params, nor the interface structure, if an interface delete
message is received from zebra.
* ospf_interface.c: (ospf_if_delete_hook) Delete the interface
params and interface, ie that which was previously removed in
(ospf_interface_delete) above.
2004-02-11 Hasso Tepper <hasso@estpak.ee>
* ospf_interface.c, ospf_zebra.c: Don't attempt to read path->oi->ifp
if oi doesn't exist any more.
2004-02-11 Vadim Suraev <vadim.suraev@terayon.com>
* ospf_packet.c (ospf_ls_upd): Router should flush received network
LSA if it was originated with older router-id ([zebra 14710] #6).
2003-12-08 Mattias Amnefelt <mattiasa@kth.se>
* ospf_packet.c: (ospf_recv_packet) OpenBSD now leaves iph.ip_len
network byte order.
2003-12-05 Greg Troxel <gdt@poblano.ir.bbn.com>
* ospfd.c (ospf_network_match_iface): Rewrite code for clarity
while trying not to change semantics. Add ifdefed-out code to
avoid matching ppp interfaces whose destination address does not
also match the prefix under consideration, to help out people with
problems due to as-yet-unfixed bugs with p2p interfaces coming and
going.
2003-07-25 kamatchi soundaram <kamatchi@tdd.sj.nec.com>
* ospf_packet.c (ospf_ls_upd_send_queue_event): get next route
node in body of the loop to avoid chance that route node
is unlocked and deleted before the next iteration tries to
get next route node.
2003-05-24 Kenji Yabuuchi
* ospf_interface.c(ospf_if_lookup_recv_if): Use the most specific
match for interface lookup.
2003-05-18 Hasso Tepper <hasso@estpak.ee>
* ospf_vty.c: Show NSSA LSA route info in "show ip ospf database"
output
2003-05-16 Hasso Tepper <hasso@estpak.ee>
* ospf_lsa.c: Fix handling of NSSA
2003-04-23 Hasso Tepper <hasso@estpak.ee>
* ospf_vty.c: fix "router xxx" node commands in vtysh
2003-04-19 Hasso Tepper <hasso@estpak.ee>
* {ospf_abr,ospfd}.c: area id's DECIMAL -> ADDRESS
* ospf_routemap.c: sync daemon's route-map commands to have same
syntax.
2003-04-19 Sergey Vyshnevetskiy <serg@vostok.net>
* ospf_packet.c: Add missing param to zlog
* ospf_flood.c: remove unused vars
2003-04-17 Denis Ovsienko <zebra@pilot.org.ua>
* ospf_interface.c: fix incorrect memset
2003-04-10 Amir Guindehi <amir@datacore.ch>
* ospf_lsa.[ch]: opaque LSA fix, use ospf_lookup.
2003-04-03 David Watson <dwatson@eecs.umich.edu>
* ospf_lsa.c: byte order fix
2002-03-17 Amir Guindehi <amir@datacore.ch>
* ospf_apiserver.[ch]: Merge Ralph Keller's OSPFAPI support.
* ospf_api.[ch]: Merge Ralph Keller's OSPFAPI support.
* ospfclient: OSPFAPI demonstration client.
2003-01-23 Masahiko Endo <endo@suri.co.jp>
* ospf_ism.c: NSM event schedule bug fix.
2002-10-30 Greg Troxel <gdt@ir.bbn.com>
* ospf_packet.c (ospf_make_md5_digest): MD5 length fix.
2002-10-23 endo@suri.co.jp (Masahiko Endo)
* ospf_opaque.c: Update Opaque LSA patch.
2002-10-23 Ralph Keller <keller@tik.ee.ethz.ch>
* ospf_vty.c (show_ip_ospf_database): Fix CLI parse.
2002-10-23 Juris Kalnins <juris@mt.lv>
* ospf_interface.c (ospf_if_stream_unset): When write queue
becomes empty stop write timer.
2002-10-10 Greg Troxel <gdt@ir.bbn.com>
* ospf_packet.c (ospf_check_md5_digest): Change >= to > to make it
conform to RFC.
2002-07-07 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* zebra-0.93 released.
2002-06-19 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospf_spf.c (ospf_nexthop_calculation): Add NULL set to oi and
check of l2. Reported by: Daniel Drown <dan-zebra@drown.org>
(ospf_lsa_has_link): LSA Length calculation fix. Reported by:
Paul Jakma <paulj@alphyra.ie>.
* ospfd.c (ospf_if_update): Fix nextnode reference bug. Reported
by: juris@mt.lv.
2002-01-21 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospfd.c: Merge [zebra 11445] Masahiko ENDO's Opaque-LSA support.
2001-08-27 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_interface.c (ospf_add_to_if): Use /32 address to register
OSPF interface information.
(ospf_delete_from_if): Likewise.
* ospf_zebra.c (ospf_interface_address_delete): Likewise.
2001-08-23 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospf_zebra.c (ospf_redistribute_unset): When redistribute type
is OSPF, do not unset redistribute flag.
2001-08-19 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* zebra-0.92a released.
2001-08-15 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* zebra-0.92 released.
2001-08-12 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospfd.c (ospf_config_write): auto-cost reference-bandwidth
configuration display.
2001-07-24 David Watson <dwatson@eecs.umich.edu>
* ospf_spf.c (ospf_spf_next): Modify ospf_vertex_add_parent to
check for an existing link before connecting the parent and child.
ospf_nexthop_calculation is also modified to check for duplicate
entries when copying from the parent. Finally, ospf_spf_next
removes duplicates when it merges two equal cost candidates.
2001-07-23 itojun@iijlab.net
* ospfd.c (show_ip_ospf_neighbor): Check ospf_top before use it
[zebra 8549].
2001-07-23 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospf_packet.c (ospf_write): Remove defined(__OpenBSD__) to make
it work on OpenBSD.
2001-06-26 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_zebra.c (config_write_ospf_default_metric): Display
default-metric configuration.
2001-06-18 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospf_ia.h (OSPF_EXAMINE_SUMMARIES_ALL): Remove old macros.
2001-05-28 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospf_snmp.c (ospfIfEntry): Fix interface lookup bug to avoid
crush.
(ospfIfMetricEntry): Likewise.
2001-03-18 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_packet.c (ospf_read): Fix typo. Reported by: "Jen B
Lin'Kova" <jen@stack.net>.
2001-03-15 Gleb Natapov <gleb@nbase.co.il>
* ospf_interface.c (ip_ospf_network): Set interface parameter.
(interface_config_write): Add check for OSPF_IFTYPE_LOOPBACK.
* ospf_zebra.c (ospf_interface_add): Set interface parameter.
2001-02-21 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_packet.c (ospf_recv_packet): Solaris also need to add
(iph.ip_hl << 2) to iph.ip_len.
2001-02-09 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospfd.h (OSPF_LS_REFRESH_TIME): Fix OSPF_LS_REFRESH_TIME value.
Suggested by: David Watson <dwatson@eecs.umich.edu>.
* ospf_zebra.c (zebra_init): Remove zebra node.
* ospfd.c (ospf_area_range_set): Function name is changed from
ospf_ara_range_cmd.
(ospf_area_range_unset): New function which separated from DEFUN.
New commands are added:
"no area A.B.C.D range A.B.C.D/M advertise"
"no area <0-4294967295> range A.B.C.D/M advertise"
"no area A.B.C.D range A.B.C.D/M not-advertise"
"no area <0-4294967295> range A.B.C.D/M not-advertise"
* ospf_lsa.c (ospf_lsa_more_recent): Fix previous change.
2001-02-08 Matthew Grant <grantma@anathoth.gen.nz>
* ospf_network.c (ospf_if_add_allspfrouters): Use
setsockopt_multicast_ipv4.
(ospf_if_drop_allspfrouters): Likewise.
* ospf_lsa.c (ospf_router_lsa_install): Add rt_recalc flag.
(ospf_network_lsa_install): Likewise.
(ospf_summary_lsa_install): Likewise.
(ospf_summary_asbr_lsa_install): Likewise.
(ospf_external_lsa_install): Likewise.
(ospf_lsa_install): Call ospf_lsa_different to check this LSA is
new one or not.
2001-02-08 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_zebra.c (ospf_interface_delete): Do not free interface
structure when ospfd receive interface delete message to support
pseudo interface.
2001-02-01 Dick Glasspool <dick@ipinfusion.com>
* ospfd.c (area_range_notadvertise): Change area range "suppress"
command to "not-advertise".
* ospfd.h (OSPF_LS_REFRESH_TIME): Change OSPF_LS_REFRESH_TIME from
1800 to 60.
* ospf_abr.c (ospf_abr_update_aggregate): When update_aggregate is
updating the area-range, the lowest cost is now saved.
* ospf_lsa.c (ospf_lsa_more_recent): Routing to compare sequence
numbers rather than creating overflow during calculation.
2001-02-01 Kunihiro Ishiguro <kunihiro@zebra.org>
* zebra-0.91 is released.
2001-01-31 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_packet.c (ospf_db_desc_proc): Do not continue process when
NSM_SeqNumberMismatch is scheduled.
(ospf_ls_req): Free ls_upd when return from this function.
(ospf_ls_upd_timer): When update list is empty do not call
ospf_ls_upd_send(). Suggested by: endo@suri.co.jp (Masahiko
Endo).
2001-01-26 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_lsa.c (ospf_maxage_flood): Flood LSA when it reaches
MaxAge. RFC2328 Section 14.
(ospf_maxage_lsa_remover): Call above function during removing
MaxAge LSA.
2001-01-26 Dick Glasspool <dick@ipinfusion.com>
* ospf_flood.c (ospf_flood_through_as): Function is updated for
NSSA Translations now done at ospf_abr.c with no change in P-bit.
* ospf_lsa.c (ospf_get_nssa_ip): Get 1st IP connection for Forward
Addr.
(ospf_install_flood_nssa): Leave Type-7 LSA at Lock Count = 2.
* ospf_ase.c (ospf_ase_calculate_route): Add debug codes.
* ospf_abr.c (ospf_abr_translate_nssa): Recalculate LSA checksum.
* ospf_packet.h (OSPF_SEND_PACKET_LOOP): Added for test packet.
* ospf_dump.c (ospf_lsa_type_msg): Add OSPF_GROUP_MEMBER_LSA and
OSPF_AS_NSSA_LSA.
* ospfd.c (data_injection): Function to inject LSA. This is
debugging command.
2001-01-11 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_route.c (ospf_route_match_same): Remove function.
(ospf_route_match_same_new): Renamed to ospf_route_match_same.
* ospf_zebra.c (ospf_interface_address_delete): Add check for
oi->address. Suggested by Matthew Grant
<grantma@anathoth.gen.nz>.
(ospf_zebra_add): Remove function.
(ospf_zebra_add_multipath): Rename to ospf_zebra_add.
* ospf_interface.c: Remove HAVE_IF_PSEUDO part.
* ospf_zebra.c: Likewise.
2001-01-10 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_ase.c: Remove OLD_RIB part.
* ospf_route.c: Likewise.
* zebra-0.90 is released.
* ospf_packet.c (ospf_recv_packet): Use ip_len adjestment code to
NetBSD.
2001-01-09 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_route.c (ospf_route_delete): Use
ospf_zebra_delete_multipath.
2001-01-09 Matthew Grant <grantma@anathoth.gen.nz>
* ospf_interface.c (ospf_if_cleanup): Function name is renamed
from ospf_if_free(). Rewrite whole procudure to support primary
address deletion.
* ospf_zebra.c (ospf_interface_address_delete): Add primary
address deletion process.
2001-01-09 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_packet.c (ospf_recv_packet): OpenBSD has same ip_len
treatment like FreeBSD.
2001-01-09 endo@suri.co.jp (Masahiko Endo)
* ospf_packet.c (ospf_recv_packet): FreeBSD kernel network code
strips IP header size from receiving IP Packet. So we adjust
ip_len to whole IP packet size by adding IP header size.
2001-01-08 endo@suri.co.jp (Masahiko Endo)
* ospf_network.c (ospf_serv_sock): When socket() is failed return
2005-02-15 00:48:42 +01:00
|
|
|
|
if ( (ibuf = stream_new (ip_len)) == NULL)
|
|
|
|
|
return NULL;
|
2005-02-15 11:10:55 +01:00
|
|
|
|
iov.iov_base = STREAM_DATA (ibuf);
|
|
|
|
|
iov.iov_len = ip_len;
|
2005-02-14 Paul Jakma <paul.jakma@sun.com>
* ospf_packet.c: (ospf_recv_packet) use stream_recvmsg.
2005-02-11 Hasso Tepper <hasso at quagga.net>
* ospf_lsdb.c: Fix sum of checksums calculation.
2005-02-09 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_write) If sendmsg fails, give more info in the
error message.
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_interface.h: Reduce structure padding by putting new u_char
field multicast_memberships in a better spot (grouped with
other u_char fields type and state).
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_interface.h: Improve passive_interface comment. Add new
multicast_memberships bitmask to struct ospf_interface to track
active multicast subscriptions. Declare new function
ospf_if_set_multicast.
* ospf_interface.c: (ospf_if_set_multicast) New function to configure
multicast memberships properly based on the current
multicast_memberships status and the current values of the
ospf_interface state, type, and passive_interface status.
(ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is
now handled by ism_change_state's call to ospf_if_set_multicast).
(ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now
handled by ism_change_state).
* ospf_ism.c: (ospf_dr_election) Remove logic to join or leave
the DRouters multicast group (now handled by ism_change_state's call
to ospf_if_set_multicast).
(ism_change_state) Add call to ospf_if_set_multicast to change
multicast memberships as necessary to reflect the new interface state.
* ospf_packet.c: (ospf_hello) When a Hello packet is received on a
passive interface: 1. Increase the severity of the error message
from LOG_INFO to LOG_WARNING; 2. Add more information to the error
message (packet destination address and interface address);
and 3. If the packet was sent to ospf-all-routers, then try
to fix the multicast group memberships.
(ospf_read) When a packet is received on an interface whose state
is ISM_Down, enhance the warning message to show the packet
destination address, and try to update/fix the multicast group
memberships if the packet was sent to a multicast address.
When a packet is received for ospf-designated-routers, but the
current interface state is not DR or BDR, then increase the
severity level of the error message from LOG_INFO to LOG_WARNING,
and try to fix the multicast group memberships.
* ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for
any ospf interface that may have changed from active to passive.
(no_ospf_passive_interface) Call ospf_if_set_multicast for
any ospf interface that may have changed from passive to active.
(show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (various) Remove unneeded stream_set_putp abuse.
2005-02-02 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_read) Fix bug: must check for state ISM_Down,
not for event ISM_InterfaceDown. And improve the message by
adding the interface flags.
2005-01-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_network.c: (ospf_sock_init) Save errno before calling
ospfd_privs.change.
2005-01-29 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_packet_add) If oi->obuf is NULL, print
an error message and return.
(ospf_read) If the interface state is ISM_InterfaceDown, issue
a warning message and ignore the packet.
2005-01-10 Greg Troxel <gdt@fnord.ir.bbn.com>
* ospf_packet.h: Remove commented out definition of
OSPF_MAX_PACKET; neither it or the uncommented one are used any more.
* ospf_packet.c (ospf_make_ls_upd): Leave room for authentication
when deciding if an update will fit.
(ospf_packet_authspace): Factor out calculation of size required
for authentication.
(ospf_make_db_desc): Use ospf_max_packet, not OSPF_MAX_PACKET.
Don't confuse readers that there is a macro.
2004-12-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_network.c: Improve all setsockopt error messages to give detailed
information on the arguments.
2004-12-29 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_db_desc) Reduce severity of "Negotiation done"
messages from LOG_WARNING to LOG_INFO, since this seems to be
normal.
2004-12-29 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_read) Always look up the interface if
ospf_recv_packet returns NULL ifp, since some platforms such
as Solaris 8 appear to support ifindex retrieval but don't.
2004-12-22 Hasso Tepper <hasso at quagga.net>
* ospf_dump.c: Show debug configuration in vtysh.
* ospf_vty.c: Fix "show ip ospf" output. Router can't be elected in
any case if it's configured as "translate-never".
* ospf_lsdb.[ch]: New function to calculate sum of checksums.
* ospf_vty.c: Bugfix to show really number of AS external LSAs, not
number of all LSAs with AS scope, this includes opaque as LSAs as
well, show this number separately. Show numbers and sums of
checksums for each type of LSAs.
* ospf_lsa.c: Calculate checksum before putting LSA into database.
2004-12-15 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_interface.h: Declare new function ospf_default_iftype.
* ospf_interface.c: (ospf_default_iftype) New function to centralize
this logic in one place.
* ospf_zebra.c: (ospf_interface_add) Use new function
ospf_default_iftype.
* ospf_vty.c: (no_ip_ospf_network,config_write_interface) Fix logic
by using new function ospf_default_iftype.
2004-12-11 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_db_desc) Should be static, not global.
(ospf_hello,ospf_db_desc,ospf_ls_upd,ospf_ls_ack) Improve warning
messages to include identifying information (e.g. router id).
* ospf_nsm.c: (nsm_change_state) Improve info message to include
router id and state names.
2004-12-09 Greg Troxel <gdt@fnord.ir.bbn.com>
* ospf_apiserver.c (ospf_apiserver_term): Obtain struct
ospf_apiserver * from listnode. Remove unused variables. Follows
suggestion from Jay Fenlason.
2004-12-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* *.c: Change level of debug messages to LOG_DEBUG.
2004-12-07 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_main.c: (main) The 2nd argument to openzlog has been removed.
2004-12-03 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_db_desc) Reduce priority on a debug message
from LOG_NOTICE to LOG_DEBUG.
2004-12-03 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_main.c: (sigint) Use zlog_notice for termination message.
(main) Issue a startup announcement using zlog_notice.
2004-11-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_packet.c: (ospf_db_desc_proc) Fix spelling of packet in warning
message and in comment.
(ospf_db_desc) Warning message that a packet is being discarded
should give the router id of the packet source. Fix spelling
of packet in two warning messages.
(ospf_ls_req) Warning message that a link state request is being
discarded should give the router id of the neighbor that sent it.
2004-11-26 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospf_main.c: Remove #include "debug.h" (was not being used, and
lib/debug.h has now been deleted).
2004-11-25 Hasso Tepper <hasso at quagga.net>
* ospf_main.c: Make group to run as configurable.
2004-11-15 Greg Troxel <gdt@fnord.ir.bbn.com>
* ospf_packet.c (ospf_recv_packet): Assume CMSG_SPACE is present
and works (lib/zebra.h provides if OS doesn't).
2004-11-15 Paul Jakma <paul@dishone.st>
* ospf_{apiserver,te}.c: ospf_lsa_free's should be ospf_lsa_unlock.
2004-11-12 Paul Jakma <paul@dishone.st>
* ospf_ia.c: (process_summary_lsa) Only an ABR has any reason to
ignore stub area summary default. Even so it seems a strange
check, add a comment to that effect.
2004-11-04 Paul Jakma <paul@dishone.st>
* ospfd.c: (ospf_network_match_iface) revert to previous network
statement match behaviour.
2004-11-02 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_write_frags) remove iov arg, msg already points
to it. Add convenience pointer to msg->msg_iov[1], and use this,
fixing the unfortunate borkenness introduced in moving of this code
to a function.
(ospf_write) remove iovp and fix up call to previous.
(ospf_ls_upd_packet_new) cast size to long int - unfortunately
glibc's size_t format modifier is not portable.
2004-10-31 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_write_frags) Add debug output
(ospf_write) set type early, so we can pass it to
ospf_write_frags.
(ospf_ls_upd_packet_new) print size in debug output when too large
packet is encountered.
* ospf_zebra.c: (ospf_distribute_list_update_timer) Ugly misuse of
THREAD_ARG to store an integer, but it should at least use same
same type to retrieve the value. Assert value is sane.
2004-10-22 Paul Jakma <paul@dishone.st>
* ospf_network.c: (ospf_sock_init) call neutral setsock_ifindex()
function.
* ospf_packet.c: (ospf_read) manually look up ifindex
if system could not have returned one, eg openbsd, thanks to Rivo
Nurges for highlighting problem and fix.
Change setsockopt_pktinfo to setsockopt_ifindex.
2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
* ospf_snmp.c: (ospf_snmp_if_update) Fix logic to handle PtP links
with dedicated subnets properly.
* ospf_lsa.c: (lsa_link_ptop_set) ditto.
* ospfd.c: (ospf_network_match_iface) ditto.
(ospf_network_run) ditto.
* ospf_interface.c: (ospf_if_is_configured) ditto.
(ospf_if_lookup_by_prefix) ditto.
(ospf_if_lookup_recv_if) ditto.
* ospf_vty.c: (show_ip_ospf_interface_sub) Display the peer or
broadcast address if present.
2004-10-13 Hasso Tepper <hasso at quagga.net>
* ospf_main.c: Unbreak compilation with ospfapi disabled.
* ospf_snmp.c: Remove defaults used to initialize smux connection to
snmpd. Connection is initialized only if smux peer is configured.
2004-10-12 Hasso Tepper <hasso at quagga.net>
* ospf_main.c, ospf_opaque.c: Unbreak ospfclient compilation - move
static variable from ospf_main.c into ospf_opaque.c.
2004-10-11 Hasso Tepper <hasso at quagga.net>
* ospf_main.c, ospf_opaque.c: Disable ospfapi init by default. New
command line switch to enable it.
2004-10-11 Paul Jakma <paul@dishone.st>
* ospf_dump.c: (ospf_ip_header_dump) Assume header is in host order
remove ntohs that should have dissappeared. Take struct ip
as argument, caller has to know there's an IP header at start of
stream anyway.
* ospf_dump.h: update declaration of ospf_ip_header_dump.
* ospf_packet.c: (ospf_write) correct call to
sockopt_iphdrincl_swab_htosys which was munging the header.
(ospf_recv_packet) ip_len is needed for old OpenBSD fixup.
(ospf_read) sockopt_iphdrincl_swab_systoh ip header as soon as
we have it.
* (global) Const char update and signed/unsigned fixes.
* (various headers) size defines should be unsigned.
* ospf_interface.h: remove duplicated defines, include the
authoritative header - though, these defines should probably
be moved to a dedicated header, or ospfd.h.
* ospf_lsa.h: (struct lsa) ls_seqnum should be unsigned.
* ospf_packet.c: (ospf_write) cast result of shift to unsigned.
2004-10-08 Hasso Tepper <hasso at quagga.net>
* *.[c|h]: Fix compiler warnings: make some strings const, signed ->
unsigned, remove unused variables etc.
2004-10-07 Greg Troxel <gdt@claude.ir.bbn.com>
* ospf_apiserver.c (ospf_apiserver_unregister_opaque_type): Don't
use of variable names 'node' and 'nextnode' to avoid possible
conflict with list macros. Move variable declaration inside for
loop after a statement to top of function.
2004-10-07 Paul Jakma <paul@dishone.st>
* ospf_snmp.c: Missed list typedef update
* ospf_dump.c: Include sockopt.h for header swab functions.
2004-10-05 Paul Jakma <paul@dishone.st>
* ospf_packet.c: replace ospf_swap_iph_to... with
sockopt_iphdrincl_swab_...
2004-10-03 James R. Leu <jleu at mindspring.com>
* ospf_zebra.c: Read router id related messages from zebra daemon.
Schedule router-id update thread if it's changed.
* ospfd.c: Remove own router-id selection function. Use router id from
zebra daemon if it isn't manually overriden in configuration.
2004-09-27 Paul Jakma <paul@dishone.st>
* ospf_dump.c: (ospf_ip_header_dump) Use HAVE_IP_HDRINCL_BSD_ORDER
Apply to offset too. Print ip_cksum, lets not worry about
possible 2.0.37 compile problems.
* ospf_packet.c: (ospf_swap_iph_to{n,h}) Use
HAVE_IP_HDRINCL_BSD_ORDER.
(ospf_recv_packet) ditto.
(ospf_write) Fixup iov argument to ospf_write_frags.
(struct msghdr).msg_name is caddr_t on most platforms.
(ospf_recv_packet) ditto. And msg_flags is not always there
memset struct then set fields we care about rather than
initialise all fields individually.
2004-09-26 Hasso Tepper <hasso at quagga.net>
* ospf_abr.c, ospf_dump.c, ospf_lsa.c, ospf_packet.c, ospf_vty.c,
ospf_zebra.c: Fix compiler warnings.
2004-09-24 Paul Jakma <paul@dishone.st>
* ospf_apiserver.{c,h}: lists typedef removal cleanup.
update some list loops to LIST_LOOP. some miscellaneous indent
fixups.
(ospf_apiserver_unregister_opaque_type) fix listnode_delete of
referenced node in loop.
(ospf_apiserver_term) loops calling ospf_apiserver_free, which
deletes referenced nodes from apiserver_list, fixed.
* ospf_interface.h: lists typedef removal cleanup.
* ospf_opaque.{c,h}: lists typedef removal cleanup. update some list
loops to LIST_LOOP. miscellaneous style and indent fixups.
* ospf_te.{c,h}: ditto
* ospf_packet.c: lists typedef removal cleanup.
(ospf_write) ifdef fragmentation support. move actual
fragmentation out to a new, similarly ifdefed, function.
(ospf_write_frags) fragmented write support, moved from previous.
2004-09-23 Hasso Tepper <hasso at quagga.net>
* *.[c|h]: list -> struct list *, listnode -> struct listnode *.
2004-09-12 Paul Jakma <paul@dishone.st>
* ospf_packet.c: Fix bugzilla #107
(ospf_packet_max) get rid of the magic 88 constant
(ospf_swab_iph_ton) new function. set ip header to network order,
taking BSDisms into account.
(ospf_swab_iph_toh) the inverse.
(ospf_write) Add support for IP fragmentation, will only work on
linux though, other kernels make it impossible. get rid of the
magic 4 constant.
(ospf_make_ls_upd) Bound check to end of stream, not to
interface mtu.
(ospf_ls_upd_packet_new) New function, allocate upd packet
taking oversized LSAs into account.
(ospf_ls_upd_queue_send) use ospf_ls_upd_packet_new to allocate,
rather than statically allocating mtu sized packet buffer, which
actually was wrong - it didnt take ip header into account, which
should not be included in packet buffer.
(ospf_ls_upd_send_queue_event) minor tweaks and remove
TODO comment.
2004-08-31 David Wiggins <dwiggins@bbn.com>
* ospf_spf.c (ospf_spf_calculate): Many more comments and debug
print statements. New function ospf_vertex_dump used in debugging.
2004-08-31 David Wiggins <dwiggins@bbn.com>
* ospf_spf.h (struct vertex): Comments for flags and structure members.
2004-08-31 David Wiggins <dwiggins@bbn.com>
* ospf_route.c: When finding an alternate route, log cost as well.
2004-08-31 David Wiggins <dwiggins@bbn.com>
* ospf_interface.c (ospf_lookup_if_params): Initialize af in
struct prefix allocated on stack.
2004-08-31 David Wiggins <dwiggins@bbn.com>
* ospf_packet.c (ospf_ls_ack_send_delayed): In p2mp mode, send
acks to AllSPFRouters, rather than All-DR.
2004-08-27 Hasso Tepper <hasso at quagga.net>
* ospf_vty.c: Don't print ospf network type under interface only
if interface is in broadcast mode and interface type really is
broadcast. Fixes Bugzilla #108.
2004-08-27 David Wiggins <dwiggins@bbn.com>
* ospf_spf.c (ospf_nexthop_calculation): Initialize address family
in on-stack struct prefix_ipv4. Fixes point-to-multipoint SPF
calculation.
2004-08-26 Greg Troxel <gdt@fnord.ir.bbn.com>
* ospf_packet.c (ospf_recv_packet): adjust size declaration of
buffer used to get interface index so that it compiles on other
than Linux and includes the required alignment space. Probably
this was only working on sparc/sparc64 because most of
sockaddr_dl was not being written.
2004-08-19 Paul Jakma <paul@dishone.st>
* ospf_packet.c: update to match sockopt renames.
2004-08-04 Paul Jakma <paul@dishone.st>
* ospf_spf.c: (ospf_spf_consider_nexthop) Add comment about issue.
Compare only against list head - all nexthops must be same cost
anyway, fixes a reference-listnode-after-delete bug noted by
Kir Kostuchenko.
(ospf_nexthop_calculation) Use ospf_spf_consider_nexthop for all
candidates attached to root.
2004-07-27 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_ls_upd_send_queue_event) fix thinko from
last fix for ospfd wedging due to oversize LSAs: dont list loop on
ospf_ls_upd_queue_send() - guaranteed segfault.
2004-07-27 Paul Jakma <paul@dishone.st>
* ospf_opaque.c: (ospf_opaque_lsa_flush_schedule) do not NULL out
the LSA as then free_opaque_info_per_id() can never unlock (and
free) the LSA. Reported by Gunnar Stigen.
2004-07-23 Paul Jakma <paul@dishone.st>
* ospf_network.c: Replace PKTINFO/RECVIF with call to
setsockopt_pktinfo
* ospf_packet.c: Use getsockopt_pktinfo_ifindex and
SOPT_SIZE_CMSG_PKTINFO_IPV4.
2004-07-14 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_ls_upd_send_queue_event) Partial fix for
problem reported by Peter Frost amongst others, where function
will spin indefinitely if update list contains LSAs greater than
MTU-headers or other condition leading to update list never being
cleared. Problem of what to do with these LSAs remains.
(ospf_make_ls_upd) add comment about large LSA problem,
indentation cleanup.
2004-07-01 Greg Troxel <gdt@fnord.ir.bbn.com>
* Makefile.am (lib_LTLIBRARIES): make libospf shared
2004-06-30 Greg Troxel <gdt@poblano.ir.bbn.com>
* Makefile.am: Add shlib support.
2004-06-10 Hasso Tepper <hasso@estpak.ee>
* *: Removed ifdefs HAVE_NSSA.
2004-06-06 Paul Jakma <paul@dishone.st>
* ospf_dump.c,ospf_lsa.c: Fix typos of merge of previous.
ospf_flood.c: (ospf_process_self_originated_lsa) fix zlog format
2004-05-31 Sagun Shakya <sagun.shakya@sun.com>
* ospf_dump.c: (ospf_lsa_header_dump) LOOKUP can return null if
index is out of range.
ospf_flood.c: endianness fix
ospf_lsa.c: Missing ntohl's on (struct lsa *)->data->ls_seqnum
in various places.
2004-05-10 Hasso Tepper <hasso@estpak.ee>
* ospf_zebra.c, ospfd.c: Move ospf_prefix_list_update() function
to ospf_zebra.c from ospfd.c and add redistribution updates if
route-map is used in redistribution.
* ospf_main.c: Remove now useless call to ospf_init().
2004-05-08 Paul Jakma <paul@dishone.st>
* ospf_zebra.c: Sync with lib/zclient changes
2004-05-05 Paul Jakma <paul@dishone.st>
* ospf_network.c: (ospf_sock_init) Check whether IP_HDRINCL is
defined. Warn at compile and runtime. Use
IPTOS_PREC_INTERNETCONTROL otherwise.
* ospf_packet.c: (ospf_associate_packet_vl) cleanup, move
some of the checks up to ospf_read, return either a
virtual link oi, or NULL.
(ospf_read) Cleanup, make it responsible for checks. Remove
the nbr lookup - moved to ospf_neighbor. Adjust all nbr
lookups to use new wrappers exported by ospf_neighbor.
* ospf_neighbor.h: Add ospf_neigbour_get and ospf_nbr_lookup.
* ospf_neighbor.c: (ospf_neigbour_get) Index ospf_interface
neighbour table by router-id for virtual-link ospf_interfaces,
not by peer_addr (which breaks for asymmetric vlinks)
(ospf_nbr_lookup) add a wrapper for nbr lookups to deal with
above.
* ospf_interface.c: (ospf_vl_set_params) Catch changes of interface
address for either end of a virtual-link, and hence potential cost
changes.
2004-04-22 Hasso Tepper <hasso@estpak.ee>
* ospf_zebra.c: Don't ignore reject/bh routes, it's the only way
to "summarize" routes in ASBR at the moment.
2004-04-20 Hasso Tepper <hasso@estpak.ee>
* ospfd.c: Unset NP flag if area is going to be normal or stub.
Fixes UNH OSPF_NSSA.1.2a comment.
* ospf_abr.c: Originate default into stub/nssa area even if
summaries are disabled.
* ospf_zebra.c: Don't attempt to redistribute 127.0.0.0/8.
2004-04-19 Hasso Tepper <hasso@estpak.ee>
* ospf_vty.c: Don't warn that export- and import-list can't be
configured to backbone area if they are applied and are working
fine.
2004-02-19 Sowmini Varadhan <sowmini.varadhan@sun.com>
* ospf_packet.c: Don't drop packets in Solaris x86.
[quagga-dev 1005].
2004-03-18 Amir Guindehi <amir@datacore.ch>
* ospf_opaque.c: Attempt to correct the incorrect behavior of
Quagga's ospfd in the special situation that a node's opaque
capability has changed as "ON -> OFF -> ON". [quagga-dev 843].
2004-02-19 Sowmini Varadhan <sowmini.varadhan@sun.com>
* ospf_abr.c: (ospf_abr_update_aggregate) UNH 3.12b,c, address range
should be configured with the highest cost path within the range,
not lowest.
2004-02-17 Paul Jakma <paul@dishone.st>
* ospf_zebra.c: (ospf_interface_delete) Do not delete the interface
params, nor the interface structure, if an interface delete
message is received from zebra.
* ospf_interface.c: (ospf_if_delete_hook) Delete the interface
params and interface, ie that which was previously removed in
(ospf_interface_delete) above.
2004-02-11 Hasso Tepper <hasso@estpak.ee>
* ospf_interface.c, ospf_zebra.c: Don't attempt to read path->oi->ifp
if oi doesn't exist any more.
2004-02-11 Vadim Suraev <vadim.suraev@terayon.com>
* ospf_packet.c (ospf_ls_upd): Router should flush received network
LSA if it was originated with older router-id ([zebra 14710] #6).
2003-12-08 Mattias Amnefelt <mattiasa@kth.se>
* ospf_packet.c: (ospf_recv_packet) OpenBSD now leaves iph.ip_len
network byte order.
2003-12-05 Greg Troxel <gdt@poblano.ir.bbn.com>
* ospfd.c (ospf_network_match_iface): Rewrite code for clarity
while trying not to change semantics. Add ifdefed-out code to
avoid matching ppp interfaces whose destination address does not
also match the prefix under consideration, to help out people with
problems due to as-yet-unfixed bugs with p2p interfaces coming and
going.
2003-07-25 kamatchi soundaram <kamatchi@tdd.sj.nec.com>
* ospf_packet.c (ospf_ls_upd_send_queue_event): get next route
node in body of the loop to avoid chance that route node
is unlocked and deleted before the next iteration tries to
get next route node.
2003-05-24 Kenji Yabuuchi
* ospf_interface.c(ospf_if_lookup_recv_if): Use the most specific
match for interface lookup.
2003-05-18 Hasso Tepper <hasso@estpak.ee>
* ospf_vty.c: Show NSSA LSA route info in "show ip ospf database"
output
2003-05-16 Hasso Tepper <hasso@estpak.ee>
* ospf_lsa.c: Fix handling of NSSA
2003-04-23 Hasso Tepper <hasso@estpak.ee>
* ospf_vty.c: fix "router xxx" node commands in vtysh
2003-04-19 Hasso Tepper <hasso@estpak.ee>
* {ospf_abr,ospfd}.c: area id's DECIMAL -> ADDRESS
* ospf_routemap.c: sync daemon's route-map commands to have same
syntax.
2003-04-19 Sergey Vyshnevetskiy <serg@vostok.net>
* ospf_packet.c: Add missing param to zlog
* ospf_flood.c: remove unused vars
2003-04-17 Denis Ovsienko <zebra@pilot.org.ua>
* ospf_interface.c: fix incorrect memset
2003-04-10 Amir Guindehi <amir@datacore.ch>
* ospf_lsa.[ch]: opaque LSA fix, use ospf_lookup.
2003-04-03 David Watson <dwatson@eecs.umich.edu>
* ospf_lsa.c: byte order fix
2002-03-17 Amir Guindehi <amir@datacore.ch>
* ospf_apiserver.[ch]: Merge Ralph Keller's OSPFAPI support.
* ospf_api.[ch]: Merge Ralph Keller's OSPFAPI support.
* ospfclient: OSPFAPI demonstration client.
2003-01-23 Masahiko Endo <endo@suri.co.jp>
* ospf_ism.c: NSM event schedule bug fix.
2002-10-30 Greg Troxel <gdt@ir.bbn.com>
* ospf_packet.c (ospf_make_md5_digest): MD5 length fix.
2002-10-23 endo@suri.co.jp (Masahiko Endo)
* ospf_opaque.c: Update Opaque LSA patch.
2002-10-23 Ralph Keller <keller@tik.ee.ethz.ch>
* ospf_vty.c (show_ip_ospf_database): Fix CLI parse.
2002-10-23 Juris Kalnins <juris@mt.lv>
* ospf_interface.c (ospf_if_stream_unset): When write queue
becomes empty stop write timer.
2002-10-10 Greg Troxel <gdt@ir.bbn.com>
* ospf_packet.c (ospf_check_md5_digest): Change >= to > to make it
conform to RFC.
2002-07-07 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* zebra-0.93 released.
2002-06-19 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospf_spf.c (ospf_nexthop_calculation): Add NULL set to oi and
check of l2. Reported by: Daniel Drown <dan-zebra@drown.org>
(ospf_lsa_has_link): LSA Length calculation fix. Reported by:
Paul Jakma <paulj@alphyra.ie>.
* ospfd.c (ospf_if_update): Fix nextnode reference bug. Reported
by: juris@mt.lv.
2002-01-21 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospfd.c: Merge [zebra 11445] Masahiko ENDO's Opaque-LSA support.
2001-08-27 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_interface.c (ospf_add_to_if): Use /32 address to register
OSPF interface information.
(ospf_delete_from_if): Likewise.
* ospf_zebra.c (ospf_interface_address_delete): Likewise.
2001-08-23 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospf_zebra.c (ospf_redistribute_unset): When redistribute type
is OSPF, do not unset redistribute flag.
2001-08-19 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* zebra-0.92a released.
2001-08-15 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* zebra-0.92 released.
2001-08-12 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospfd.c (ospf_config_write): auto-cost reference-bandwidth
configuration display.
2001-07-24 David Watson <dwatson@eecs.umich.edu>
* ospf_spf.c (ospf_spf_next): Modify ospf_vertex_add_parent to
check for an existing link before connecting the parent and child.
ospf_nexthop_calculation is also modified to check for duplicate
entries when copying from the parent. Finally, ospf_spf_next
removes duplicates when it merges two equal cost candidates.
2001-07-23 itojun@iijlab.net
* ospfd.c (show_ip_ospf_neighbor): Check ospf_top before use it
[zebra 8549].
2001-07-23 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospf_packet.c (ospf_write): Remove defined(__OpenBSD__) to make
it work on OpenBSD.
2001-06-26 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_zebra.c (config_write_ospf_default_metric): Display
default-metric configuration.
2001-06-18 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospf_ia.h (OSPF_EXAMINE_SUMMARIES_ALL): Remove old macros.
2001-05-28 Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* ospf_snmp.c (ospfIfEntry): Fix interface lookup bug to avoid
crush.
(ospfIfMetricEntry): Likewise.
2001-03-18 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_packet.c (ospf_read): Fix typo. Reported by: "Jen B
Lin'Kova" <jen@stack.net>.
2001-03-15 Gleb Natapov <gleb@nbase.co.il>
* ospf_interface.c (ip_ospf_network): Set interface parameter.
(interface_config_write): Add check for OSPF_IFTYPE_LOOPBACK.
* ospf_zebra.c (ospf_interface_add): Set interface parameter.
2001-02-21 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_packet.c (ospf_recv_packet): Solaris also need to add
(iph.ip_hl << 2) to iph.ip_len.
2001-02-09 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospfd.h (OSPF_LS_REFRESH_TIME): Fix OSPF_LS_REFRESH_TIME value.
Suggested by: David Watson <dwatson@eecs.umich.edu>.
* ospf_zebra.c (zebra_init): Remove zebra node.
* ospfd.c (ospf_area_range_set): Function name is changed from
ospf_ara_range_cmd.
(ospf_area_range_unset): New function which separated from DEFUN.
New commands are added:
"no area A.B.C.D range A.B.C.D/M advertise"
"no area <0-4294967295> range A.B.C.D/M advertise"
"no area A.B.C.D range A.B.C.D/M not-advertise"
"no area <0-4294967295> range A.B.C.D/M not-advertise"
* ospf_lsa.c (ospf_lsa_more_recent): Fix previous change.
2001-02-08 Matthew Grant <grantma@anathoth.gen.nz>
* ospf_network.c (ospf_if_add_allspfrouters): Use
setsockopt_multicast_ipv4.
(ospf_if_drop_allspfrouters): Likewise.
* ospf_lsa.c (ospf_router_lsa_install): Add rt_recalc flag.
(ospf_network_lsa_install): Likewise.
(ospf_summary_lsa_install): Likewise.
(ospf_summary_asbr_lsa_install): Likewise.
(ospf_external_lsa_install): Likewise.
(ospf_lsa_install): Call ospf_lsa_different to check this LSA is
new one or not.
2001-02-08 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_zebra.c (ospf_interface_delete): Do not free interface
structure when ospfd receive interface delete message to support
pseudo interface.
2001-02-01 Dick Glasspool <dick@ipinfusion.com>
* ospfd.c (area_range_notadvertise): Change area range "suppress"
command to "not-advertise".
* ospfd.h (OSPF_LS_REFRESH_TIME): Change OSPF_LS_REFRESH_TIME from
1800 to 60.
* ospf_abr.c (ospf_abr_update_aggregate): When update_aggregate is
updating the area-range, the lowest cost is now saved.
* ospf_lsa.c (ospf_lsa_more_recent): Routing to compare sequence
numbers rather than creating overflow during calculation.
2001-02-01 Kunihiro Ishiguro <kunihiro@zebra.org>
* zebra-0.91 is released.
2001-01-31 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_packet.c (ospf_db_desc_proc): Do not continue process when
NSM_SeqNumberMismatch is scheduled.
(ospf_ls_req): Free ls_upd when return from this function.
(ospf_ls_upd_timer): When update list is empty do not call
ospf_ls_upd_send(). Suggested by: endo@suri.co.jp (Masahiko
Endo).
2001-01-26 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_lsa.c (ospf_maxage_flood): Flood LSA when it reaches
MaxAge. RFC2328 Section 14.
(ospf_maxage_lsa_remover): Call above function during removing
MaxAge LSA.
2001-01-26 Dick Glasspool <dick@ipinfusion.com>
* ospf_flood.c (ospf_flood_through_as): Function is updated for
NSSA Translations now done at ospf_abr.c with no change in P-bit.
* ospf_lsa.c (ospf_get_nssa_ip): Get 1st IP connection for Forward
Addr.
(ospf_install_flood_nssa): Leave Type-7 LSA at Lock Count = 2.
* ospf_ase.c (ospf_ase_calculate_route): Add debug codes.
* ospf_abr.c (ospf_abr_translate_nssa): Recalculate LSA checksum.
* ospf_packet.h (OSPF_SEND_PACKET_LOOP): Added for test packet.
* ospf_dump.c (ospf_lsa_type_msg): Add OSPF_GROUP_MEMBER_LSA and
OSPF_AS_NSSA_LSA.
* ospfd.c (data_injection): Function to inject LSA. This is
debugging command.
2001-01-11 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_route.c (ospf_route_match_same): Remove function.
(ospf_route_match_same_new): Renamed to ospf_route_match_same.
* ospf_zebra.c (ospf_interface_address_delete): Add check for
oi->address. Suggested by Matthew Grant
<grantma@anathoth.gen.nz>.
(ospf_zebra_add): Remove function.
(ospf_zebra_add_multipath): Rename to ospf_zebra_add.
* ospf_interface.c: Remove HAVE_IF_PSEUDO part.
* ospf_zebra.c: Likewise.
2001-01-10 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_ase.c: Remove OLD_RIB part.
* ospf_route.c: Likewise.
* zebra-0.90 is released.
* ospf_packet.c (ospf_recv_packet): Use ip_len adjestment code to
NetBSD.
2001-01-09 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_route.c (ospf_route_delete): Use
ospf_zebra_delete_multipath.
2001-01-09 Matthew Grant <grantma@anathoth.gen.nz>
* ospf_interface.c (ospf_if_cleanup): Function name is renamed
from ospf_if_free(). Rewrite whole procudure to support primary
address deletion.
* ospf_zebra.c (ospf_interface_address_delete): Add primary
address deletion process.
2001-01-09 Kunihiro Ishiguro <kunihiro@zebra.org>
* ospf_packet.c (ospf_recv_packet): OpenBSD has same ip_len
treatment like FreeBSD.
2001-01-09 endo@suri.co.jp (Masahiko Endo)
* ospf_packet.c (ospf_recv_packet): FreeBSD kernel network code
strips IP header size from receiving IP Packet. So we adjust
ip_len to whole IP packet size by adding IP header size.
2001-01-08 endo@suri.co.jp (Masahiko Endo)
* ospf_network.c (ospf_serv_sock): When socket() is failed return
2005-02-15 00:48:42 +01:00
|
|
|
|
|
|
|
|
|
ret = stream_recvmsg (ibuf, fd, &msgh, 0, ip_len);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2004-08-19 06:43:43 +02:00
|
|
|
|
ifindex = getsockopt_ifindex (AF_INET, &msgh);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
*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);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ospf_interface *
|
2004-05-05 17:27:15 +02:00
|
|
|
|
ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct ip *iph, struct ospf_header *ospfh)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *rcv_oi;
|
|
|
|
|
struct ospf_vl_data *vl_data;
|
|
|
|
|
struct ospf_area *vl_area;
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct listnode *node;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
if (IN_MULTICAST (ntohl (iph->ip_dst.s_addr)) ||
|
|
|
|
|
!OSPF_IS_AREA_BACKBONE (ospfh))
|
2004-05-05 17:27:15 +02:00
|
|
|
|
return NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2004-05-05 17:27:15 +02:00
|
|
|
|
/* look for local OSPF interface matching the destination
|
|
|
|
|
* to determine Area ID. We presume therefore the destination address
|
|
|
|
|
* is unique, or at least (for "unnumbered" links), not used in other
|
|
|
|
|
* areas
|
|
|
|
|
*/
|
|
|
|
|
if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, NULL,
|
|
|
|
|
iph->ip_dst)) == NULL)
|
|
|
|
|
return NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2003-04-04 04:44:16 +02:00
|
|
|
|
for (node = listhead (ospf->vlinks); node; nextnode (node))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
if ((vl_data = getdata (node)) == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
2003-04-04 04:44:16 +02:00
|
|
|
|
vl_area = ospf_area_lookup_by_area_id (ospf, vl_data->vl_area_id);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
if (!vl_area)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (OSPF_AREA_SAME (&vl_area, &rcv_oi->area) &&
|
|
|
|
|
IPV4_ADDR_SAME (&vl_data->vl_peer, &ospfh->router_id))
|
|
|
|
|
{
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("associating packet with %s",
|
2002-12-13 21:15:29 +01:00
|
|
|
|
IF_NAME (vl_data->vl_oi));
|
|
|
|
|
if (! CHECK_FLAG (vl_data->vl_oi->ifp->flags, IFF_UP))
|
|
|
|
|
{
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("This VL is not up yet, sorry");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return vl_data->vl_oi;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("couldn't find any VL to associate the packet with");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2004-05-05 17:27:15 +02:00
|
|
|
|
return NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
|
|
|
|
|
{
|
|
|
|
|
/* Check match the Area ID of the receiving interface. */
|
|
|
|
|
if (OSPF_AREA_SAME (&oi->area, &ospfh))
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
|
|
|
|
|
{
|
|
|
|
|
struct in_addr mask, me, him;
|
|
|
|
|
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
|
|
|
|
|
oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
masklen2ip (oi->address->prefixlen, &mask);
|
|
|
|
|
|
|
|
|
|
me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
|
|
|
|
|
him.s_addr = ip_src.s_addr & mask.s_addr;
|
|
|
|
|
|
|
|
|
|
if (IPV4_ADDR_SAME (&me, &him))
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
|
|
|
|
|
struct ospf_header *ospfh)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
struct crypt_key *ck;
|
|
|
|
|
|
|
|
|
|
switch (ntohs (ospfh->auth_type))
|
|
|
|
|
{
|
|
|
|
|
case OSPF_AUTH_NULL:
|
|
|
|
|
ret = 1;
|
|
|
|
|
break;
|
|
|
|
|
case OSPF_AUTH_SIMPLE:
|
|
|
|
|
if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
|
|
|
|
|
ret = 1;
|
|
|
|
|
else
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
case OSPF_AUTH_CRYPTOGRAPHIC:
|
|
|
|
|
if ((ck = getdata (OSPF_IF_PARAM (oi,auth_crypt)->tail)) == NULL)
|
|
|
|
|
{
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This is very basic, the digest processing is elsewhere */
|
|
|
|
|
if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE &&
|
|
|
|
|
ospfh->u.crypt.key_id == ck->key_id &&
|
|
|
|
|
ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf))
|
|
|
|
|
ret = 1;
|
|
|
|
|
else
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ret = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
/* keep checksum and clear. */
|
|
|
|
|
sum = ospfh->checksum;
|
|
|
|
|
memset (&ospfh->checksum, 0, sizeof (u_int16_t));
|
|
|
|
|
|
|
|
|
|
/* calculate checksum. */
|
|
|
|
|
ret = in_cksum (ospfh, ntohs (ospfh->length));
|
|
|
|
|
|
|
|
|
|
if (ret != sum)
|
|
|
|
|
{
|
|
|
|
|
zlog_info ("ospf_check_sum(): checksum mismatch, my %X, his %X",
|
|
|
|
|
ret, sum);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* OSPF Header verification. */
|
|
|
|
|
int
|
|
|
|
|
ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
|
|
|
|
|
struct ip *iph, struct ospf_header *ospfh)
|
|
|
|
|
{
|
|
|
|
|
/* check version. */
|
|
|
|
|
if (ospfh->version != OSPF_VERSION)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("interface %s: ospf_read version number mismatch.",
|
|
|
|
|
IF_NAME (oi));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check Area ID. */
|
|
|
|
|
if (!ospf_check_area_id (oi, ospfh))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("interface %s: ospf_read invalid Area ID %s.",
|
|
|
|
|
IF_NAME (oi), inet_ntoa (ospfh->area_id));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check network mask, Silently discarded. */
|
|
|
|
|
if (! ospf_check_network_mask (oi, iph->ip_src))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("interface %s: ospf_read network address is not same [%s]",
|
|
|
|
|
IF_NAME (oi), inet_ntoa (iph->ip_src));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check authentication. */
|
|
|
|
|
if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("interface %s: ospf_read authentication type mismatch.",
|
|
|
|
|
IF_NAME (oi));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! ospf_check_auth (oi, ibuf, ospfh))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("interface %s: ospf_read authentication failed.",
|
|
|
|
|
IF_NAME (oi));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if check sum is invalid, packet is discarded. */
|
|
|
|
|
if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
|
|
|
|
|
{
|
|
|
|
|
if (! ospf_check_sum (ospfh))
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("interface %s: ospf_read packet checksum error %s",
|
|
|
|
|
IF_NAME (oi), inet_ntoa (ospfh->router_id));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (ospfh->checksum != 0)
|
|
|
|
|
return -1;
|
|
|
|
|
if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("interface %s: ospf_read md5 authentication failed.",
|
|
|
|
|
IF_NAME (oi));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Starting point of packet process function. */
|
|
|
|
|
int
|
|
|
|
|
ospf_read (struct thread *thread)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
struct stream *ibuf;
|
2003-03-25 06:07:42 +01:00
|
|
|
|
struct ospf *ospf;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct ospf_interface *oi;
|
|
|
|
|
struct ip *iph;
|
|
|
|
|
struct ospf_header *ospfh;
|
|
|
|
|
u_int16_t length;
|
|
|
|
|
struct interface *ifp;
|
|
|
|
|
|
|
|
|
|
/* first of all get interface pointer. */
|
2003-03-25 06:07:42 +01:00
|
|
|
|
ospf = THREAD_ARG (thread);
|
|
|
|
|
ospf->t_read = NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* read OSPF packet. */
|
2003-03-25 06:07:42 +01:00
|
|
|
|
ibuf = ospf_recv_packet (ospf->fd, &ifp);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
if (ibuf == NULL)
|
|
|
|
|
return -1;
|
|
|
|
|
|
2004-10-22 19:00:38 +02:00
|
|
|
|
iph = (struct ip *) STREAM_DATA (ibuf);
|
|
|
|
|
sockopt_iphdrincl_swab_systoh (iph);
|
|
|
|
|
|
2004-10-22 14:05:17 +02:00
|
|
|
|
if (ifp == NULL)
|
2004-12-29 21:41:26 +01:00
|
|
|
|
/* 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. */
|
2004-10-22 14:05:17 +02:00
|
|
|
|
ifp = if_lookup_address (iph->ip_src);
|
|
|
|
|
|
2004-05-05 17:27:15 +02:00
|
|
|
|
if (ifp == NULL)
|
|
|
|
|
{
|
|
|
|
|
stream_free (ibuf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2004-10-11 12:11:25 +02:00
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
/* prepare for next packet. */
|
2003-03-25 06:07:42 +01:00
|
|
|
|
ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* IP Header dump. */
|
2003-02-13 23:04:01 +01:00
|
|
|
|
if (IS_DEBUG_OSPF_PACKET(0, RECV))
|
2004-10-11 12:11:25 +02:00
|
|
|
|
ospf_ip_header_dump (iph);
|
2003-01-27 13:00:55 +01:00
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
/* Self-originated packet should be discarded silently. */
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (ospf_if_lookup_by_local_addr (ospf, NULL, iph->ip_src))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
2003-09-29 14:42:39 +02:00
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (0, RECV))
|
|
|
|
|
{
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_read[%s]: Dropping self-originated packet",
|
2003-09-29 14:42:39 +02:00
|
|
|
|
inet_ntoa (iph->ip_src));
|
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
stream_free (ibuf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Adjust size to message length. */
|
2005-02-09 16:51:56 +01:00
|
|
|
|
stream_forward_getp (ibuf, iph->ip_hl * 4);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Get ospf packet header. */
|
|
|
|
|
ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
|
|
|
|
|
|
|
|
|
|
/* associate packet with ospf interface */
|
2003-03-25 06:07:42 +01:00
|
|
|
|
oi = ospf_if_lookup_recv_if (ospf, iph->ip_src);
|
2004-05-05 17:27:15 +02:00
|
|
|
|
|
|
|
|
|
/* if no local ospf_interface,
|
|
|
|
|
* or header area is backbone but ospf_interface is not
|
|
|
|
|
* check for VLINK interface
|
|
|
|
|
*/
|
|
|
|
|
if ( (oi == NULL) ||
|
|
|
|
|
(OSPF_IS_AREA_ID_BACKBONE(ospfh->area_id)
|
|
|
|
|
&& !OSPF_IS_AREA_ID_BACKBONE(oi->area->area_id))
|
|
|
|
|
)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
2004-05-05 17:27:15 +02:00
|
|
|
|
if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)
|
2003-09-29 14:42:39 +02:00
|
|
|
|
{
|
2004-05-05 17:27:15 +02:00
|
|
|
|
zlog_warn ("Packet from [%s] received on link %s"
|
|
|
|
|
" but no ospf_interface",
|
|
|
|
|
inet_ntoa (iph->ip_src), ifp->name);
|
|
|
|
|
stream_free (ibuf);
|
|
|
|
|
return 0;
|
2003-09-29 14:42:39 +02:00
|
|
|
|
}
|
2004-05-05 17:27:15 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
stream_free (ibuf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2005-02-02 19:38:48 +01:00
|
|
|
|
else if (oi->state == ISM_Down)
|
2005-01-29 16:52:07 +01:00
|
|
|
|
{
|
2005-02-08 16:37:30 +01:00
|
|
|
|
char buf[2][INET_ADDRSTRLEN];
|
|
|
|
|
zlog_warn ("Ignoring packet from %s to %s received on interface that is "
|
2005-02-02 19:38:48 +01:00
|
|
|
|
"down [%s]; interface flags are %s",
|
2005-02-08 16:37:30 +01:00
|
|
|
|
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));
|
2005-01-29 16:52:07 +01:00
|
|
|
|
stream_free (ibuf);
|
2005-02-08 16:37:30 +01:00
|
|
|
|
/* Fix multicast memberships? */
|
|
|
|
|
if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
|
|
|
|
|
SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
|
|
|
|
|
else if (iph->ip_dst.s_addr == htonl(OSPF_ALLDROUTERS))
|
|
|
|
|
SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
|
|
|
|
|
if (oi->multicast_memberships)
|
|
|
|
|
ospf_if_set_multicast(oi);
|
2005-01-29 16:52:07 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If the received packet is destined for AllDRouters, the packet
|
|
|
|
|
* should be accepted only if the received ospf interface state is
|
|
|
|
|
* either DR or Backup -- endo.
|
|
|
|
|
*/
|
|
|
|
|
if (iph->ip_dst.s_addr == htonl (OSPF_ALLDROUTERS)
|
|
|
|
|
&& (oi->state != ISM_DR && oi->state != ISM_Backup))
|
|
|
|
|
{
|
2005-02-08 16:37:30 +01:00
|
|
|
|
zlog_warn ("Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)",
|
2002-12-13 21:15:29 +01:00
|
|
|
|
inet_ntoa (iph->ip_src), IF_NAME (oi),
|
|
|
|
|
LOOKUP (ospf_ism_state_msg, oi->state));
|
|
|
|
|
stream_free (ibuf);
|
2005-02-08 16:37:30 +01:00
|
|
|
|
/* Try to fix multicast membership. */
|
|
|
|
|
SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
|
|
|
|
|
ospf_if_set_multicast(oi);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Show debug receiving packet. */
|
2003-04-08 10:51:58 +02:00
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
|
|
|
|
|
{
|
2002-12-13 21:15:29 +01:00
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
|
2003-04-08 10:51:58 +02:00
|
|
|
|
{
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("-----------------------------------------------------");
|
2003-04-08 10:51:58 +02:00
|
|
|
|
ospf_packet_dump (ibuf);
|
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("%s received from [%s] via [%s]",
|
2003-04-08 10:51:58 +02:00
|
|
|
|
ospf_packet_type_str[ospfh->type],
|
|
|
|
|
inet_ntoa (ospfh->router_id), IF_NAME (oi));
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug (" src [%s],", inet_ntoa (iph->ip_src));
|
|
|
|
|
zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("-----------------------------------------------------");
|
2003-04-08 10:51:58 +02:00
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Some header verification. */
|
|
|
|
|
ret = ospf_verify_header (ibuf, oi, iph, ospfh);
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
{
|
2003-09-29 14:42:39 +02:00
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
|
|
|
|
|
{
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_read[%s/%s]: Header check failed, "
|
2003-09-29 14:42:39 +02:00
|
|
|
|
"dropping.",
|
|
|
|
|
ospf_packet_type_str[ospfh->type],
|
|
|
|
|
inet_ntoa (iph->ip_src));
|
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
stream_free (ibuf);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-09 16:51:56 +01:00
|
|
|
|
stream_forward_getp (ibuf, OSPF_HEADER_SIZE);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Adjust size to message length. */
|
|
|
|
|
length = ntohs (ospfh->length) - OSPF_HEADER_SIZE;
|
|
|
|
|
|
|
|
|
|
/* Read rest of the packet and call each sort of packet routine. */
|
|
|
|
|
switch (ospfh->type)
|
|
|
|
|
{
|
|
|
|
|
case OSPF_MSG_HELLO:
|
|
|
|
|
ospf_hello (iph, ospfh, ibuf, oi, length);
|
|
|
|
|
break;
|
|
|
|
|
case OSPF_MSG_DB_DESC:
|
|
|
|
|
ospf_db_desc (iph, ospfh, ibuf, oi, length);
|
|
|
|
|
break;
|
|
|
|
|
case OSPF_MSG_LS_REQ:
|
|
|
|
|
ospf_ls_req (iph, ospfh, ibuf, oi, length);
|
|
|
|
|
break;
|
|
|
|
|
case OSPF_MSG_LS_UPD:
|
|
|
|
|
ospf_ls_upd (iph, ospfh, ibuf, oi, length);
|
|
|
|
|
break;
|
|
|
|
|
case OSPF_MSG_LS_ACK:
|
|
|
|
|
ospf_ls_ack (iph, ospfh, ibuf, oi, length);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
zlog (NULL, LOG_WARNING,
|
|
|
|
|
"interface %s: OSPF packet header type %d is illegal",
|
|
|
|
|
IF_NAME (oi), ospfh->type);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stream_free (ibuf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Make OSPF header. */
|
|
|
|
|
void
|
|
|
|
|
ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_header *ospfh;
|
|
|
|
|
|
|
|
|
|
ospfh = (struct ospf_header *) STREAM_DATA (s);
|
|
|
|
|
|
|
|
|
|
ospfh->version = (u_char) OSPF_VERSION;
|
|
|
|
|
ospfh->type = (u_char) type;
|
|
|
|
|
|
2003-03-25 06:07:42 +01:00
|
|
|
|
ospfh->router_id = oi->ospf->router_id;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
ospfh->checksum = 0;
|
|
|
|
|
ospfh->area_id = oi->area->area_id;
|
|
|
|
|
ospfh->auth_type = htons (ospf_auth_type (oi));
|
|
|
|
|
|
|
|
|
|
memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
|
|
|
|
|
|
2005-02-09 16:51:56 +01:00
|
|
|
|
stream_forward_endp (s, OSPF_HEADER_SIZE);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Make Authentication Data. */
|
|
|
|
|
int
|
|
|
|
|
ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
|
|
|
|
|
{
|
|
|
|
|
struct crypt_key *ck;
|
|
|
|
|
|
|
|
|
|
switch (ospf_auth_type (oi))
|
|
|
|
|
{
|
|
|
|
|
case OSPF_AUTH_NULL:
|
|
|
|
|
/* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
|
|
|
|
|
break;
|
|
|
|
|
case OSPF_AUTH_SIMPLE:
|
|
|
|
|
memcpy (ospfh->u.auth_data, OSPF_IF_PARAM (oi, auth_simple),
|
|
|
|
|
OSPF_AUTH_SIMPLE_SIZE);
|
|
|
|
|
break;
|
|
|
|
|
case OSPF_AUTH_CRYPTOGRAPHIC:
|
|
|
|
|
/* If key is not set, then set 0. */
|
|
|
|
|
if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
|
|
|
|
|
{
|
|
|
|
|
ospfh->u.crypt.zero = 0;
|
|
|
|
|
ospfh->u.crypt.key_id = 0;
|
|
|
|
|
ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
|
|
|
|
|
ospfh->u.crypt.zero = 0;
|
|
|
|
|
ospfh->u.crypt.key_id = ck->key_id;
|
|
|
|
|
ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
|
|
|
|
|
}
|
|
|
|
|
/* note: the seq is done in ospf_make_md5_digest() */
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Fill rest of OSPF header. */
|
|
|
|
|
void
|
|
|
|
|
ospf_fill_header (struct ospf_interface *oi,
|
|
|
|
|
struct stream *s, u_int16_t length)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_header *ospfh;
|
|
|
|
|
|
|
|
|
|
ospfh = (struct ospf_header *) STREAM_DATA (s);
|
|
|
|
|
|
|
|
|
|
/* Fill length. */
|
|
|
|
|
ospfh->length = htons (length);
|
|
|
|
|
|
|
|
|
|
/* Calculate checksum. */
|
|
|
|
|
if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
|
|
|
|
|
ospfh->checksum = in_cksum (ospfh, length);
|
|
|
|
|
else
|
|
|
|
|
ospfh->checksum = 0;
|
|
|
|
|
|
|
|
|
|
/* Add Authentication Data. */
|
|
|
|
|
ospf_make_auth (oi, ospfh);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_make_hello (struct ospf_interface *oi, struct stream *s)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_neighbor *nbr;
|
|
|
|
|
struct route_node *rn;
|
|
|
|
|
u_int16_t length = OSPF_HELLO_MIN_SIZE;
|
|
|
|
|
struct in_addr mask;
|
|
|
|
|
unsigned long p;
|
|
|
|
|
int flag = 0;
|
|
|
|
|
|
|
|
|
|
/* Set netmask of interface. */
|
|
|
|
|
if (oi->type != OSPF_IFTYPE_POINTOPOINT &&
|
|
|
|
|
oi->type != OSPF_IFTYPE_VIRTUALLINK)
|
|
|
|
|
masklen2ip (oi->address->prefixlen, &mask);
|
|
|
|
|
else
|
|
|
|
|
memset ((char *) &mask, 0, sizeof (struct in_addr));
|
|
|
|
|
stream_put_ipv4 (s, mask.s_addr);
|
|
|
|
|
|
|
|
|
|
/* Set Hello Interval. */
|
|
|
|
|
stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("make_hello: options: %x, int: %s",
|
2002-12-13 21:15:29 +01:00
|
|
|
|
OPTIONS(oi), IF_NAME (oi));
|
|
|
|
|
|
|
|
|
|
/* Set Options. */
|
|
|
|
|
stream_putc (s, OPTIONS (oi));
|
|
|
|
|
|
|
|
|
|
/* Set Router Priority. */
|
|
|
|
|
stream_putc (s, PRIORITY (oi));
|
|
|
|
|
|
|
|
|
|
/* Set Router Dead Interval. */
|
|
|
|
|
stream_putl (s, OSPF_IF_PARAM (oi, v_wait));
|
|
|
|
|
|
|
|
|
|
/* Set Designated Router. */
|
|
|
|
|
stream_put_ipv4 (s, DR (oi).s_addr);
|
|
|
|
|
|
2005-02-09 16:51:56 +01:00
|
|
|
|
p = stream_get_endp (s);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Set Backup Designated Router. */
|
|
|
|
|
stream_put_ipv4 (s, BDR (oi).s_addr);
|
|
|
|
|
|
|
|
|
|
/* Add neighbor seen. */
|
|
|
|
|
for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if ((nbr = rn->info))
|
|
|
|
|
if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */
|
|
|
|
|
if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */
|
|
|
|
|
if (nbr->state != NSM_Down) /* This is myself for DR election. */
|
|
|
|
|
if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
/* Check neighbor is sane? */
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (nbr->d_router.s_addr != 0
|
|
|
|
|
&& IPV4_ADDR_SAME (&nbr->d_router, &oi->address->u.prefix4)
|
|
|
|
|
&& IPV4_ADDR_SAME (&nbr->bd_router, &oi->address->u.prefix4))
|
|
|
|
|
flag = 1;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
stream_put_ipv4 (s, nbr->router_id.s_addr);
|
|
|
|
|
length += 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Let neighbor generate BackupSeen. */
|
|
|
|
|
if (flag == 1)
|
2005-02-08 12:29:41 +01:00
|
|
|
|
stream_putl_at (s, p, 0); /* ipv4 address, normally */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
|
|
|
|
|
struct stream *s)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_lsa *lsa;
|
|
|
|
|
u_int16_t length = OSPF_DB_DESC_MIN_SIZE;
|
|
|
|
|
u_char options;
|
|
|
|
|
unsigned long pp;
|
|
|
|
|
int i;
|
|
|
|
|
struct ospf_lsdb *lsdb;
|
|
|
|
|
|
|
|
|
|
/* Set Interface MTU. */
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
|
|
|
|
stream_putw (s, 0);
|
|
|
|
|
else
|
|
|
|
|
stream_putw (s, oi->ifp->mtu);
|
|
|
|
|
|
|
|
|
|
/* Set Options. */
|
|
|
|
|
options = OPTIONS (oi);
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
2003-03-25 06:07:42 +01:00
|
|
|
|
if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
if (IS_SET_DD_I (nbr->dd_flags)
|
|
|
|
|
|| CHECK_FLAG (nbr->options, OSPF_OPTION_O))
|
|
|
|
|
/*
|
|
|
|
|
* Set O-bit in the outgoing DD packet for capablity negotiation,
|
|
|
|
|
* if one of following case is applicable.
|
|
|
|
|
*
|
|
|
|
|
* 1) WaitTimer expiration event triggered the neighbor state to
|
|
|
|
|
* change to Exstart, but no (valid) DD packet has received
|
|
|
|
|
* from the neighbor yet.
|
|
|
|
|
*
|
|
|
|
|
* 2) At least one DD packet with O-bit on has received from the
|
|
|
|
|
* neighbor.
|
|
|
|
|
*/
|
|
|
|
|
SET_FLAG (options, OSPF_OPTION_O);
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
stream_putc (s, options);
|
|
|
|
|
|
|
|
|
|
/* Keep pointer to flags. */
|
2005-02-09 16:51:56 +01:00
|
|
|
|
pp = stream_get_endp (s);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
stream_putc (s, nbr->dd_flags);
|
|
|
|
|
|
|
|
|
|
/* Set DD Sequence Number. */
|
|
|
|
|
stream_putl (s, nbr->dd_seqnum);
|
|
|
|
|
|
|
|
|
|
if (ospf_db_summary_isempty (nbr))
|
|
|
|
|
{
|
|
|
|
|
if (nbr->state >= NSM_Exchange)
|
|
|
|
|
{
|
|
|
|
|
nbr->dd_flags &= ~OSPF_DD_FLAG_M;
|
|
|
|
|
/* Set DD flags again */
|
2005-02-08 12:29:41 +01:00
|
|
|
|
stream_putc_at (s, pp, nbr->dd_flags);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Describe LSA Header from Database Summary List. */
|
|
|
|
|
lsdb = &nbr->db_sum;
|
|
|
|
|
|
|
|
|
|
for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
|
|
|
|
|
{
|
|
|
|
|
struct route_table *table = lsdb->type[i].db;
|
|
|
|
|
struct route_node *rn;
|
|
|
|
|
|
|
|
|
|
for (rn = route_top (table); rn; rn = route_next (rn))
|
|
|
|
|
if ((lsa = rn->info) != NULL)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_OPAQUE_LSA
|
|
|
|
|
if (IS_OPAQUE_LSA (lsa->data->type)
|
|
|
|
|
&& (! CHECK_FLAG (options, OSPF_OPTION_O)))
|
|
|
|
|
{
|
|
|
|
|
/* Suppress advertising opaque-informations. */
|
|
|
|
|
/* Remove LSA from DB summary list. */
|
|
|
|
|
ospf_lsdb_delete (lsdb, lsa);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_OPAQUE_LSA */
|
|
|
|
|
|
|
|
|
|
if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
|
|
|
|
|
{
|
|
|
|
|
struct lsa_header *lsah;
|
|
|
|
|
u_int16_t ls_age;
|
|
|
|
|
|
|
|
|
|
/* DD packet overflows interface MTU. */
|
2005-01-10 15:20:43 +01:00
|
|
|
|
if (length + OSPF_LSA_HEADER_SIZE > ospf_packet_max (oi))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* Keep pointer to LS age. */
|
|
|
|
|
lsah = (struct lsa_header *) (STREAM_DATA (s) +
|
2005-02-09 16:51:56 +01:00
|
|
|
|
stream_get_endp (s));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Proceed stream pointer. */
|
|
|
|
|
stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
|
|
|
|
|
length += OSPF_LSA_HEADER_SIZE;
|
|
|
|
|
|
|
|
|
|
/* Set LS age. */
|
|
|
|
|
ls_age = LS_AGE (lsa);
|
|
|
|
|
lsah->ls_age = htons (ls_age);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Remove LSA from DB summary list. */
|
|
|
|
|
ospf_lsdb_delete (lsdb, lsa);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
|
|
|
|
|
unsigned long delta, struct ospf_neighbor *nbr,
|
|
|
|
|
struct ospf_lsa *lsa)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *oi;
|
|
|
|
|
|
|
|
|
|
oi = nbr->oi;
|
|
|
|
|
|
|
|
|
|
/* LS Request packet overflows interface MTU. */
|
2005-01-10 15:20:43 +01:00
|
|
|
|
if (*length + delta > ospf_packet_max(oi))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
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);
|
|
|
|
|
nbr->ls_req_last = ospf_lsa_lock (lsa);
|
|
|
|
|
|
|
|
|
|
*length += 12;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2005-02-09 16:51:56 +01:00
|
|
|
|
unsigned long delta = stream_get_endp(s)+12;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct route_table *table;
|
|
|
|
|
struct route_node *rn;
|
|
|
|
|
int i;
|
|
|
|
|
struct ospf_lsdb *lsdb;
|
|
|
|
|
|
|
|
|
|
lsdb = &nbr->ls_req;
|
|
|
|
|
|
|
|
|
|
for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
|
|
|
|
|
{
|
|
|
|
|
table = lsdb->type[i].db;
|
|
|
|
|
for (rn = route_top (table); rn; rn = route_next (rn))
|
|
|
|
|
if ((lsa = (rn->info)) != NULL)
|
|
|
|
|
if (ospf_make_ls_req_func (s, &length, delta, nbr, lsa) == 0)
|
|
|
|
|
{
|
|
|
|
|
route_unlock_node (rn);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ls_age_increment (struct ospf_lsa *lsa, int delay)
|
|
|
|
|
{
|
|
|
|
|
int age;
|
|
|
|
|
|
|
|
|
|
age = IS_LSA_MAXAGE (lsa) ? OSPF_LSA_MAXAGE : LS_AGE (lsa) + delay;
|
|
|
|
|
|
|
|
|
|
return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-09-23 21:18:23 +02:00
|
|
|
|
ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream *s)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
struct ospf_lsa *lsa;
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct listnode *node;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
u_int16_t length = OSPF_LS_UPD_MIN_SIZE;
|
2005-01-10 15:20:43 +01:00
|
|
|
|
unsigned int size_noauth;
|
2005-02-09 16:51:56 +01:00
|
|
|
|
unsigned long delta = stream_get_endp (s);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
unsigned long pp;
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_make_ls_upd: Start");
|
2004-07-14 22:50:36 +02:00
|
|
|
|
|
2005-02-09 16:51:56 +01:00
|
|
|
|
pp = stream_get_endp (s);
|
|
|
|
|
stream_forward_endp (s, OSPF_LS_UPD_MIN_SIZE);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2005-01-10 15:20:43 +01:00
|
|
|
|
/* Calculate amount of packet usable for data. */
|
|
|
|
|
size_noauth = stream_get_size(s) - ospf_packet_authspace(oi);
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
while ((node = listhead (update)) != NULL)
|
|
|
|
|
{
|
|
|
|
|
struct lsa_header *lsah;
|
|
|
|
|
u_int16_t ls_age;
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_make_ls_upd: List Iteration");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
lsa = getdata (node);
|
|
|
|
|
assert (lsa);
|
|
|
|
|
assert (lsa->data);
|
|
|
|
|
|
2004-09-12 16:21:37 +02:00
|
|
|
|
/* Will it fit? */
|
2005-01-10 15:20:43 +01:00
|
|
|
|
if (length + delta + ntohs (lsa->data->length) > size_noauth)
|
2004-07-14 22:50:36 +02:00
|
|
|
|
break;
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
/* Keep pointer to LS age. */
|
2005-02-09 16:51:56 +01:00
|
|
|
|
lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_endp (s));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Put LSA to Link State Request. */
|
|
|
|
|
stream_put (s, lsa->data, ntohs (lsa->data->length));
|
|
|
|
|
|
|
|
|
|
/* Set LS age. */
|
|
|
|
|
/* each hop must increment an lsa_age by transmit_delay
|
|
|
|
|
of OSPF interface */
|
|
|
|
|
ls_age = ls_age_increment (lsa, OSPF_IF_PARAM (oi, transmit_delay));
|
|
|
|
|
lsah->ls_age = htons (ls_age);
|
|
|
|
|
|
|
|
|
|
length += ntohs (lsa->data->length);
|
|
|
|
|
count++;
|
|
|
|
|
|
|
|
|
|
list_delete_node (update, node);
|
|
|
|
|
ospf_lsa_unlock (lsa);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now set #LSAs. */
|
2005-02-08 12:29:41 +01:00
|
|
|
|
stream_putl_at (s, pp, count);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_make_ls_upd: Stop");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-09-23 21:18:23 +02:00
|
|
|
|
ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct list *rm_list;
|
|
|
|
|
struct listnode *node;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
u_int16_t length = OSPF_LS_ACK_MIN_SIZE;
|
2005-02-09 16:51:56 +01:00
|
|
|
|
unsigned long delta = stream_get_endp(s) + 24;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct ospf_lsa *lsa;
|
|
|
|
|
|
|
|
|
|
rm_list = list_new ();
|
|
|
|
|
|
|
|
|
|
for (node = listhead (ack); node; nextnode (node))
|
|
|
|
|
{
|
|
|
|
|
lsa = getdata (node);
|
|
|
|
|
assert (lsa);
|
|
|
|
|
|
2005-01-10 15:20:43 +01:00
|
|
|
|
if (length + delta > ospf_packet_max (oi))
|
2002-12-13 21:15:29 +01:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list_delete (rm_list);
|
|
|
|
|
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_packet *op;
|
|
|
|
|
u_int16_t length = OSPF_HEADER_SIZE;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
op->dst.s_addr = addr->s_addr;
|
|
|
|
|
|
|
|
|
|
/* Add packet to the interface output queue. */
|
|
|
|
|
ospf_packet_add (oi, op);
|
|
|
|
|
|
|
|
|
|
/* Hook thread to write packet. */
|
2003-04-04 04:44:16 +02:00
|
|
|
|
OSPF_ISM_WRITE_ON (oi->ospf);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *oi;
|
|
|
|
|
|
|
|
|
|
oi = nbr_nbma->oi;
|
|
|
|
|
assert(oi);
|
|
|
|
|
|
|
|
|
|
/* If this is passive interface, do not send OSPF Hello. */
|
|
|
|
|
if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (oi->type != OSPF_IFTYPE_NBMA)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (PRIORITY(oi) == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (nbr_nbma->priority == 0
|
|
|
|
|
&& oi->state != ISM_DR && oi->state != ISM_Backup)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ospf_hello_send_sub (oi, &nbr_nbma->addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_poll_timer (struct thread *thread)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_nbr_nbma *nbr_nbma;
|
|
|
|
|
|
|
|
|
|
nbr_nbma = THREAD_ARG (thread);
|
|
|
|
|
nbr_nbma->t_poll = NULL;
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Poll timer expire)",
|
2002-12-13 21:15:29 +01:00
|
|
|
|
IF_NAME (nbr_nbma->oi), inet_ntoa (nbr_nbma->addr));
|
|
|
|
|
|
|
|
|
|
ospf_poll_send (nbr_nbma);
|
|
|
|
|
|
|
|
|
|
if (nbr_nbma->v_poll > 0)
|
|
|
|
|
OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
|
|
|
|
|
nbr_nbma->v_poll);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ospf_hello_reply_timer (struct thread *thread)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_neighbor *nbr;
|
|
|
|
|
|
|
|
|
|
nbr = THREAD_ARG (thread);
|
|
|
|
|
nbr->t_hello_reply = NULL;
|
|
|
|
|
|
|
|
|
|
assert (nbr->oi);
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)",
|
2002-12-13 21:15:29 +01:00
|
|
|
|
IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
|
|
|
|
|
|
|
|
|
|
ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Send OSPF Hello. */
|
|
|
|
|
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)
|
|
|
|
|
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;
|
|
|
|
|
struct route_node *rn;
|
|
|
|
|
|
|
|
|
|
for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
|
|
|
|
|
if ((nbr = rn->info))
|
|
|
|
|
if (nbr != oi->nbr_self)
|
|
|
|
|
if (nbr->state != NSM_Down)
|
|
|
|
|
{
|
|
|
|
|
/* RFC 2328 Section 9.5.1
|
|
|
|
|
If the router is not eligible to become Designated Router,
|
|
|
|
|
it must periodically send Hello Packets to both the
|
|
|
|
|
Designated Router and the Backup Designated Router (if they
|
|
|
|
|
exist). */
|
|
|
|
|
if (PRIORITY(oi) == 0 &&
|
|
|
|
|
IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
|
|
|
|
|
IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* If the router is eligible to become Designated Router, it
|
|
|
|
|
must periodically send Hello Packets to all neighbors that
|
|
|
|
|
are also eligible. In addition, if the router is itself the
|
|
|
|
|
Designated Router or Backup Designated Router, it must also
|
|
|
|
|
send periodic Hello Packets to all other neighbors. */
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2003-04-04 04:44:16 +02:00
|
|
|
|
OSPF_ISM_WRITE_ON (oi->ospf);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
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. */
|
2003-04-04 04:44:16 +02:00
|
|
|
|
OSPF_ISM_WRITE_ON (oi->ospf);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Send OSPF Database Description. */
|
|
|
|
|
void
|
|
|
|
|
ospf_db_desc_send (struct ospf_neighbor *nbr)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *oi;
|
|
|
|
|
struct ospf_packet *op;
|
|
|
|
|
u_int16_t length = OSPF_HEADER_SIZE;
|
|
|
|
|
|
|
|
|
|
oi = nbr->oi;
|
|
|
|
|
op = ospf_packet_new (oi->ifp->mtu);
|
|
|
|
|
|
|
|
|
|
/* Prepare OSPF common header. */
|
|
|
|
|
ospf_make_header (OSPF_MSG_DB_DESC, oi, op->s);
|
|
|
|
|
|
|
|
|
|
/* Prepare OSPF Database Description body. */
|
|
|
|
|
length += ospf_make_db_desc (oi, nbr, op->s);
|
|
|
|
|
|
|
|
|
|
/* Fill OSPF header. */
|
|
|
|
|
ospf_fill_header (oi, op->s, length);
|
|
|
|
|
|
|
|
|
|
/* Set packet length. */
|
|
|
|
|
op->length = length;
|
|
|
|
|
|
|
|
|
|
/* Decide destination address. */
|
|
|
|
|
op->dst = nbr->address.u.prefix4;
|
|
|
|
|
|
|
|
|
|
/* Add packet to the interface output queue. */
|
|
|
|
|
ospf_packet_add (oi, op);
|
|
|
|
|
|
|
|
|
|
/* Hook thread to write packet. */
|
2003-04-04 04:44:16 +02:00
|
|
|
|
OSPF_ISM_WRITE_ON (oi->ospf);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Remove old DD packet, then copy new one and keep in neighbor structure. */
|
|
|
|
|
if (nbr->last_send)
|
|
|
|
|
ospf_packet_free (nbr->last_send);
|
|
|
|
|
nbr->last_send = ospf_packet_dup (op);
|
|
|
|
|
gettimeofday (&nbr->last_send_ts, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Re-send Database Description. */
|
|
|
|
|
void
|
|
|
|
|
ospf_db_desc_resend (struct ospf_neighbor *nbr)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *oi;
|
|
|
|
|
|
|
|
|
|
oi = nbr->oi;
|
|
|
|
|
|
|
|
|
|
/* Add packet to the interface output queue. */
|
|
|
|
|
ospf_packet_add (oi, ospf_packet_dup (nbr->last_send));
|
|
|
|
|
|
|
|
|
|
/* Hook thread to write packet. */
|
2003-04-04 04:44:16 +02:00
|
|
|
|
OSPF_ISM_WRITE_ON (oi->ospf);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Send Link State Request. */
|
|
|
|
|
void
|
|
|
|
|
ospf_ls_req_send (struct ospf_neighbor *nbr)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *oi;
|
|
|
|
|
struct ospf_packet *op;
|
|
|
|
|
u_int16_t length = OSPF_HEADER_SIZE;
|
|
|
|
|
|
|
|
|
|
oi = nbr->oi;
|
|
|
|
|
op = ospf_packet_new (oi->ifp->mtu);
|
|
|
|
|
|
|
|
|
|
/* Prepare OSPF common header. */
|
|
|
|
|
ospf_make_header (OSPF_MSG_LS_REQ, oi, op->s);
|
|
|
|
|
|
|
|
|
|
/* Prepare OSPF Link State Request body. */
|
|
|
|
|
length += ospf_make_ls_req (nbr, op->s);
|
|
|
|
|
if (length == OSPF_HEADER_SIZE)
|
|
|
|
|
{
|
|
|
|
|
ospf_packet_free (op);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Fill OSPF header. */
|
|
|
|
|
ospf_fill_header (oi, op->s, length);
|
|
|
|
|
|
|
|
|
|
/* Set packet length. */
|
|
|
|
|
op->length = length;
|
|
|
|
|
|
|
|
|
|
/* Decide destination address. */
|
|
|
|
|
op->dst = nbr->address.u.prefix4;
|
|
|
|
|
|
|
|
|
|
/* Add packet to the interface output queue. */
|
|
|
|
|
ospf_packet_add (oi, op);
|
|
|
|
|
|
|
|
|
|
/* Hook thread to write packet. */
|
2003-04-04 04:44:16 +02:00
|
|
|
|
OSPF_ISM_WRITE_ON (oi->ospf);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Add Link State Request Retransmission Timer. */
|
|
|
|
|
OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Send Link State Update with an LSA. */
|
|
|
|
|
void
|
|
|
|
|
ospf_ls_upd_send_lsa (struct ospf_neighbor *nbr, struct ospf_lsa *lsa,
|
|
|
|
|
int flag)
|
|
|
|
|
{
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct list *update;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
update = list_new ();
|
|
|
|
|
|
|
|
|
|
listnode_add (update, lsa);
|
|
|
|
|
ospf_ls_upd_send (nbr, update, flag);
|
|
|
|
|
|
|
|
|
|
list_delete (update);
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-12 16:21:37 +02:00
|
|
|
|
/* Determine size for packet. Must be at least big enough to accomodate next
|
|
|
|
|
* LSA on list, which may be bigger than MTU size.
|
|
|
|
|
*
|
|
|
|
|
* Return pointer to new ospf_packet
|
|
|
|
|
* NULL if we can not allocate, eg because LSA is bigger than imposed limit
|
|
|
|
|
* on packet sizes (in which case offending LSA is deleted from update list)
|
|
|
|
|
*/
|
|
|
|
|
static struct ospf_packet *
|
|
|
|
|
ospf_ls_upd_packet_new (struct list *update, struct ospf_interface *oi)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_lsa *lsa;
|
|
|
|
|
struct listnode *ln;
|
|
|
|
|
size_t size;
|
|
|
|
|
static char warned = 0;
|
|
|
|
|
|
|
|
|
|
ln = listhead (update);
|
|
|
|
|
lsa = getdata (ln);
|
|
|
|
|
assert (lsa);
|
|
|
|
|
assert (lsa->data);
|
|
|
|
|
|
|
|
|
|
if ((OSPF_LS_UPD_MIN_SIZE + ntohs (lsa->data->length))
|
|
|
|
|
> ospf_packet_max (oi))
|
|
|
|
|
{
|
|
|
|
|
if (!warned)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("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 ..'");
|
|
|
|
|
warned = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_PACKET (0, SEND))
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_ls_upd_packet_new: oversized LSA id:%s,"
|
2004-09-12 16:21:37 +02:00
|
|
|
|
" %d bytes originated by %s, will be fragmented!",
|
|
|
|
|
inet_ntoa (lsa->data->id),
|
|
|
|
|
ntohs (lsa->data->length),
|
|
|
|
|
inet_ntoa (lsa->data->adv_router));
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Allocate just enough to fit this LSA only, to avoid including other
|
|
|
|
|
* LSAs in fragmented LSA Updates.
|
|
|
|
|
*/
|
|
|
|
|
size = ntohs (lsa->data->length) + (oi->ifp->mtu - ospf_packet_max (oi))
|
|
|
|
|
+ OSPF_LS_UPD_MIN_SIZE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
size = oi->ifp->mtu;
|
|
|
|
|
|
2005-01-10 15:20:43 +01:00
|
|
|
|
/* XXX Should this be - sizeof(struct ip)?? -gdt */
|
2004-09-12 16:21:37 +02:00
|
|
|
|
if (size > OSPF_MAX_PACKET_SIZE)
|
|
|
|
|
{
|
|
|
|
|
zlog_warn ("ospf_ls_upd_packet_new: oversized LSA id:%s too big,"
|
2004-10-31 19:01:13 +01:00
|
|
|
|
" %d bytes, packet size %ld, dropping it completely."
|
2004-09-12 16:21:37 +02:00
|
|
|
|
" OSPF routing is broken!",
|
2004-10-31 12:24:51 +01:00
|
|
|
|
inet_ntoa (lsa->data->id), ntohs (lsa->data->length),
|
2004-11-02 21:26:45 +01:00
|
|
|
|
(long int) size);
|
2004-09-12 16:21:37 +02:00
|
|
|
|
list_delete_node (update, ln);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ospf_packet_new (size);
|
|
|
|
|
}
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
static void
|
2004-09-23 21:18:23 +02:00
|
|
|
|
ospf_ls_upd_queue_send (struct ospf_interface *oi, struct list *update,
|
2002-12-13 21:15:29 +01:00
|
|
|
|
struct in_addr addr)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_packet *op;
|
|
|
|
|
u_int16_t length = OSPF_HEADER_SIZE;
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));
|
2004-09-12 16:21:37 +02:00
|
|
|
|
|
|
|
|
|
op = ospf_ls_upd_packet_new (update, oi);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
/* Prepare OSPF common header. */
|
|
|
|
|
ospf_make_header (OSPF_MSG_LS_UPD, oi, op->s);
|
|
|
|
|
|
2004-07-14 22:50:36 +02:00
|
|
|
|
/* Prepare OSPF Link State Update body.
|
|
|
|
|
* Includes Type-7 translation.
|
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
|
length += ospf_make_ls_upd (oi, update, op->s);
|
|
|
|
|
|
|
|
|
|
/* Fill OSPF header. */
|
|
|
|
|
ospf_fill_header (oi, op->s, length);
|
|
|
|
|
|
|
|
|
|
/* Set packet length. */
|
|
|
|
|
op->length = length;
|
|
|
|
|
|
|
|
|
|
/* Decide destination address. */
|
|
|
|
|
op->dst.s_addr = addr.s_addr;
|
|
|
|
|
|
|
|
|
|
/* Add packet to the interface output queue. */
|
|
|
|
|
ospf_packet_add (oi, op);
|
|
|
|
|
|
|
|
|
|
/* Hook thread to write packet. */
|
2003-04-04 04:44:16 +02:00
|
|
|
|
OSPF_ISM_WRITE_ON (oi->ospf);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
ospf_ls_upd_send_queue_event (struct thread *thread)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *oi = THREAD_ARG(thread);
|
|
|
|
|
struct route_node *rn;
|
2003-07-25 01:22:57 +02:00
|
|
|
|
struct route_node *rnext;
|
2004-07-14 22:50:36 +02:00
|
|
|
|
struct list *update;
|
2004-09-12 16:21:37 +02:00
|
|
|
|
char again = 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
oi->t_ls_upd_event = NULL;
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_ls_upd_send_queue start");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2003-07-25 01:22:57 +02:00
|
|
|
|
for (rn = route_top (oi->ls_upd_queue); rn; rn = rnext)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
2003-07-25 01:22:57 +02:00
|
|
|
|
rnext = route_next (rn);
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
if (rn->info == NULL)
|
2003-07-25 01:22:57 +02:00
|
|
|
|
continue;
|
2004-09-12 16:21:37 +02:00
|
|
|
|
|
|
|
|
|
update = (struct list *)rn->info;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2004-07-27 19:40:44 +02:00
|
|
|
|
ospf_ls_upd_queue_send (oi, update, rn->p.u.prefix4);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
2004-09-12 16:21:37 +02:00
|
|
|
|
/* list might not be empty. */
|
2004-07-14 22:50:36 +02:00
|
|
|
|
if (listcount(update) == 0)
|
|
|
|
|
{
|
|
|
|
|
list_delete (rn->info);
|
|
|
|
|
rn->info = NULL;
|
|
|
|
|
route_unlock_node (rn);
|
|
|
|
|
}
|
|
|
|
|
else
|
2004-09-12 16:21:37 +02:00
|
|
|
|
again = 1;
|
2004-07-14 22:50:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (again != 0)
|
|
|
|
|
{
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_ls_upd_send_queue: update lists not cleared,"
|
2004-07-14 22:50:36 +02:00
|
|
|
|
" %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);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
|
zlog_debug ("ospf_ls_upd_send_queue stop");
|
2004-07-14 22:50:36 +02:00
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2004-09-23 21:18:23 +02:00
|
|
|
|
ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *oi;
|
|
|
|
|
struct prefix_ipv4 p;
|
|
|
|
|
struct route_node *rn;
|
2004-09-23 21:18:23 +02:00
|
|
|
|
struct listnode *n;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
|
|
oi = nbr->oi;
|
|
|
|
|
|
|
|
|
|
p.family = AF_INET;
|
|
|
|
|
p.prefixlen = IPV4_MAX_BITLEN;
|
|
|
|
|
|
|
|
|
|
/* Decide destination address. */
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
|
|
|
|
p.prefix = oi->vl_data->peer_addr;
|
|
|
|
|
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);
|
2002-12-13 21:59:45 +01:00
|
|
|
|
else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
|
|
|
|
|
p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
else
|
|
|
|
|
p.prefix.s_addr = htonl (OSPF_ALLDROUTERS);
|
|
|
|
|
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_NBMA)
|
|
|
|
|
{
|
|
|
|
|
if (flag == OSPF_SEND_PACKET_INDIRECT)
|
|
|
|
|
zlog_warn ("* LS-Update is directly sent on NBMA network.");
|
|
|
|
|
if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix.s_addr))
|
|
|
|
|
zlog_warn ("* LS-Update is sent to myself.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rn = route_node_get (oi->ls_upd_queue, (struct prefix *) &p);
|
|
|
|
|
|
|
|
|
|
if (rn->info == NULL)
|
|
|
|
|
rn->info = list_new ();
|
|
|
|
|
|
|
|
|
|
for (n = listhead (update); n; nextnode (n))
|
|
|
|
|
listnode_add (rn->info, ospf_lsa_lock (getdata (n)));
|
|
|
|
|
|
|
|
|
|
if (oi->t_ls_upd_event == NULL)
|
|
|
|
|
oi->t_ls_upd_event =
|
|
|
|
|
thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2004-09-23 21:18:23 +02:00
|
|
|
|
ospf_ls_ack_send_list (struct ospf_interface *oi, struct list *ack,
|
|
|
|
|
struct in_addr dst)
|
2002-12-13 21:15:29 +01:00
|
|
|
|
{
|
|
|
|
|
struct ospf_packet *op;
|
|
|
|
|
u_int16_t length = OSPF_HEADER_SIZE;
|
|
|
|
|
|
|
|
|
|
op = ospf_packet_new (oi->ifp->mtu);
|
|
|
|
|
|
|
|
|
|
/* Prepare OSPF common header. */
|
|
|
|
|
ospf_make_header (OSPF_MSG_LS_ACK, oi, op->s);
|
|
|
|
|
|
|
|
|
|
/* Prepare OSPF Link State Acknowledgment body. */
|
|
|
|
|
length += ospf_make_ls_ack (oi, ack, op->s);
|
|
|
|
|
|
|
|
|
|
/* Fill OSPF header. */
|
|
|
|
|
ospf_fill_header (oi, op->s, length);
|
|
|
|
|
|
|
|
|
|
/* Set packet length. */
|
|
|
|
|
op->length = length;
|
|
|
|
|
|
|
|
|
|
/* Set destination IP address. */
|
|
|
|
|
op->dst = dst;
|
|
|
|
|
|
|
|
|
|
/* Add packet to the interface output queue. */
|
|
|
|
|
ospf_packet_add (oi, op);
|
|
|
|
|
|
|
|
|
|
/* Hook thread to write packet. */
|
2003-04-04 04:44:16 +02:00
|
|
|
|
OSPF_ISM_WRITE_ON (oi->ospf);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
ospf_ls_ack_send_event (struct thread *thread)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *oi = THREAD_ARG (thread);
|
|
|
|
|
|
|
|
|
|
oi->t_ls_ack_direct = NULL;
|
|
|
|
|
|
|
|
|
|
while (listcount (oi->ls_ack_direct.ls_ack))
|
|
|
|
|
ospf_ls_ack_send_list (oi, oi->ls_ack_direct.ls_ack,
|
|
|
|
|
oi->ls_ack_direct.dst);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_interface *oi = nbr->oi;
|
|
|
|
|
|
|
|
|
|
if (listcount (oi->ls_ack_direct.ls_ack) == 0)
|
|
|
|
|
oi->ls_ack_direct.dst = nbr->address.u.prefix4;
|
|
|
|
|
|
|
|
|
|
listnode_add (oi->ls_ack_direct.ls_ack, ospf_lsa_lock (lsa));
|
|
|
|
|
|
|
|
|
|
if (oi->t_ls_ack_direct == NULL)
|
|
|
|
|
oi->t_ls_ack_direct =
|
|
|
|
|
thread_add_event (master, ospf_ls_ack_send_event, oi, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Send Link State Acknowledgment delayed. */
|
|
|
|
|
void
|
|
|
|
|
ospf_ls_ack_send_delayed (struct ospf_interface *oi)
|
|
|
|
|
{
|
|
|
|
|
struct in_addr dst;
|
|
|
|
|
|
|
|
|
|
/* Decide destination address. */
|
|
|
|
|
/* RFC2328 Section 13.5 On non-broadcast
|
|
|
|
|
networks, delayed Link State Acknowledgment packets must be
|
|
|
|
|
unicast separately over each adjacency (i.e., neighbor whose
|
|
|
|
|
state is >= Exchange). */
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_NBMA)
|
|
|
|
|
{
|
|
|
|
|
struct ospf_neighbor *nbr;
|
|
|
|
|
struct route_node *rn;
|
|
|
|
|
|
|
|
|
|
for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
|
|
|
|
|
if ((nbr = rn->info) != NULL)
|
|
|
|
|
if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
|
|
|
|
|
while (listcount (oi->ls_ack))
|
|
|
|
|
ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->address.u.prefix4);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
|
|
|
|
dst.s_addr = oi->vl_data->peer_addr.s_addr;
|
|
|
|
|
else if (oi->state == ISM_DR || oi->state == ISM_Backup)
|
|
|
|
|
dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
|
|
|
|
|
else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
|
|
|
|
|
dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
|
2004-08-31 19:28:41 +02:00
|
|
|
|
else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
|
|
|
|
|
dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
else
|
|
|
|
|
dst.s_addr = htonl (OSPF_ALLDROUTERS);
|
|
|
|
|
|
|
|
|
|
while (listcount (oi->ls_ack))
|
|
|
|
|
ospf_ls_ack_send_list (oi, oi->ls_ack, dst);
|
|
|
|
|
}
|