#include "stream.h"
#include "log.h"
#include "sockopt.h"
-#include "md5-gnu.h"
+#include "checksum.h"
+#include "md5.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_network.h"
#include "ospfd/ospf_flood.h"
#include "ospfd/ospf_dump.h"
-static void ospf_ls_ack_send_list (struct ospf_interface *, struct list *,
- struct in_addr);
-
/* Packet Type String. */
const char *ospf_packet_type_str[] =
{
"Link State Acknowledgment",
};
-extern int in_cksum (void *ptr, int nbytes);
-
/* OSPF authentication checking function */
-int
+static int
ospf_auth_type (struct ospf_interface *oi)
{
int auth_type;
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)
{
/* Reserve space for MD5 authentication that may be added later. */
new = ospf_packet_new (stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE);
- ospf_stream_copy (new->s, op->s);
+ stream_copy (new->s, op->s);
new->dst = op->dst;
new->length = op->length;
}
/* XXX inline */
-unsigned int
+static inline unsigned int
ospf_packet_authspace (struct ospf_interface *oi)
{
int auth = 0;
return auth;
}
-unsigned int
+static unsigned int
ospf_packet_max (struct ospf_interface *oi)
{
int max;
}
\f
-int
+static int
ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
u_int16_t length)
{
unsigned char *ibuf;
- struct md5_ctx ctx;
+ MD5_CTX ctx;
unsigned char digest[OSPF_AUTH_MD5_SIZE];
unsigned char *pdigest;
struct crypt_key *ck;
}
/* Generate a digest for the ospf packet - their digest + our digest. */
- md5_init_ctx (&ctx);
- md5_process_bytes (ibuf, length, &ctx);
- md5_process_bytes (ck->auth_key, OSPF_AUTH_MD5_SIZE, &ctx);
- md5_finish_ctx (&ctx, digest);
+ memset(&ctx, 0, sizeof(ctx));
+ MD5Init(&ctx);
+ MD5Update(&ctx, ibuf, length);
+ MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE);
+ MD5Final(digest, &ctx);
/* compare the two */
if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
/* This function is called from ospf_write(), it will detect the
authentication scheme and if it is MD5, it will change the sequence
and update the MD5 digest. */
-int
+static int
ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
{
struct ospf_header *ospfh;
unsigned char digest[OSPF_AUTH_MD5_SIZE];
- struct md5_ctx ctx;
+ MD5_CTX ctx;
void *ibuf;
u_int32_t t;
struct crypt_key *ck;
- char *auth_key;
+ const u_int8_t *auth_key;
ibuf = STREAM_DATA (op->s);
ospfh = (struct ospf_header *) ibuf;
/* We do this here so when we dup a packet, we don't have to
waste CPU rewriting other headers. */
t = (time(NULL) & 0xFFFFFFFF);
- oi->crypt_seqnum = ( t > oi->crypt_seqnum ? t : oi->crypt_seqnum++);
+ if (t > oi->crypt_seqnum)
+ oi->crypt_seqnum = t;
+ else
+ oi->crypt_seqnum++;
+
ospfh->u.crypt.crypt_seqnum = htonl (oi->crypt_seqnum);
/* Get MD5 Authentication key from auth_key list. */
if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
- auth_key = (char *) "";
+ auth_key = (const u_int8_t *) "";
else
{
- ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
- auth_key = (char *) ck->auth_key;
+ ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
+ auth_key = ck->auth_key;
}
/* Generate a digest for the entire packet + our secret key. */
- md5_init_ctx (&ctx);
- md5_process_bytes (ibuf, ntohs (ospfh->length), &ctx);
- md5_process_bytes (auth_key, OSPF_AUTH_MD5_SIZE, &ctx);
- md5_finish_ctx (&ctx, digest);
+ memset(&ctx, 0, sizeof(ctx));
+ MD5Init(&ctx);
+ MD5Update(&ctx, ibuf, ntohs (ospfh->length));
+ MD5Update(&ctx, auth_key, OSPF_AUTH_MD5_SIZE);
+ MD5Final(digest, &ctx);
/* Append md5 digest to the end of the stream. */
stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE);
}
\f
-int
+static int
ospf_ls_req_timer (struct thread *thread)
{
struct ospf_neighbor *nbr;
struct list *update;
struct ospf_lsdb *lsdb;
int i;
- struct timeval now;
int retransmit_interval;
- gettimeofday (&now, NULL);
retransmit_interval = OSPF_IF_PARAM (nbr->oi, retransmit_interval);
lsdb = &nbr->ls_rxmt;
fired. This is a small tweak to what is in the RFC,
but it will cut out out a lot of retransmit traffic
- MAG */
- if (tv_cmp (tv_sub (now, lsa->tv_recv),
+ if (tv_cmp (tv_sub (recent_time, lsa->tv_recv),
int2tv (retransmit_interval)) >= 0)
listnode_add (update, rn->info);
}
}
#ifdef WANT_OSPF_WRITE_FRAGMENT
-void
+static void
ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph,
struct msghdr *msg, unsigned int maxdatasize,
unsigned int mtu, int flags, u_char type)
if (ret < 0)
zlog_warn ("*** ospf_write_frags: sendmsg failed to %s,"
- " id %d, off %d, len %d failed with %s",
- inet_ntoa (iph->ip_dst),
- iph->ip_id,
- iph->ip_off,
- iph->ip_len,
- safe_strerror (errno));
+ " id %d, off %d, len %d, mtu %u failed with %s",
+ inet_ntoa (iph->ip_dst),
+ iph->ip_id,
+ iph->ip_off,
+ iph->ip_len,
+ mtu,
+ safe_strerror (errno));
if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
{
}
#endif /* WANT_OSPF_WRITE_FRAGMENT */
-int
+static int
ospf_write (struct thread *thread)
{
struct ospf *ospf = THREAD_ARG (thread);
node = listhead (ospf->oi_write_q);
assert (node);
- oi = getdata (node);
+ oi = listgetdata (node);
assert (oi);
#ifdef WANT_OSPF_WRITE_FRAGMENT
if (ret < 0)
zlog_warn ("*** sendmsg in ospf_write failed to %s, "
- "id %d, off %d, len %d: %s",
+ "id %d, off %d, len %d, interface %s, mtu %u: %s",
inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
- safe_strerror (errno));
+ oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
/* Show debug sending packet. */
if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
}
/* OSPF Hello message read -- RFC2328 Section 10.5. */
-void
+static void
ospf_hello (struct ip *iph, struct ospf_header *ospfh,
struct stream * s, struct ospf_interface *oi, int size)
{
/* If incoming interface is passive one, ignore Hello. */
if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) {
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])));
+ zlog_debug ("ignoring HELLO from router %s sent to %s, "
+ "received on a passive interface, %s",
+ inet_ntop(AF_INET, &ospfh->router_id, buf[0], sizeof(buf[0])),
+ inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
+ inet_ntop(AF_INET, &oi->address->u.prefix4,
+ buf[2], sizeof(buf[2])));
if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
{
/* Try to fix multicast membership. */
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))
{
return;
}
+ /* Compare Hello Interval - ignored if fast-hellos are set. */
+ if (OSPF_IF_PARAM (oi, fast_hello) == 0)
+ {
+ if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
+ {
+ zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch.",
+ inet_ntoa (ospfh->router_id));
+ return;
+ }
+ }
+
if (IS_DEBUG_OSPF_EVENT)
zlog_debug ("Packet %s [Hello:RECV]: Options %s",
inet_ntoa (ospfh->router_id),
}
/* Save DD flags/options/Seqnum received. */
-void
+static void
ospf_db_desc_save_current (struct ospf_neighbor *nbr,
struct ospf_db_desc *dd)
{
ospf_db_desc_save_current (nbr, dd);
}
-int
+static int
ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr)
{
/* Is DD duplicated? */
}
/* Check MTU. */
- if (ntohs (dd->mtu) > oi->ifp->mtu)
+ if ((OSPF_IF_PARAM (oi, mtu_ignore) == 0) &&
+ (ntohs (dd->mtu) > oi->ifp->mtu))
{
zlog_warn ("Packet[DD]: Neighbor %s MTU %u is larger than [%s]'s MTU %u",
inet_ntoa (nbr->router_id), ntohs (dd->mtu),
else
{
/* We're Master, ignore the initial DBD from Slave */
- zlog_warn ("Packet[DD]: Neighbor %s: Initial DBD from Slave, "
+ zlog_info ("Packet[DD]: Neighbor %s: Initial DBD from Slave, "
"ignoring.", inet_ntoa(nbr->router_id));
break;
}
if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O)
&& IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))
{
- zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; Opaque-LSAs cannot be reliably advertised in this network.", inet_ntoa (nbr->router_id));
+ zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; "
+ "Opaque-LSAs cannot be reliably advertised "
+ "in this network.",
+ inet_ntoa (nbr->router_id));
/* This situation is undesirable, but not a real error. */
}
}
{
if (IS_SET_DD_MS (nbr->dd_flags))
/* Master: discard duplicated DD packet. */
- zlog_warn ("Packet[DD] (Master): Neighbor %s packet duplicated.",
+ zlog_info ("Packet[DD] (Master): Neighbor %s packet duplicated.",
inet_ntoa (nbr->router_id));
else
/* Slave: cause to retransmit the last Database Description. */
{
- zlog_warn ("Packet[DD] [Slave]: Neighbor %s packet duplicated.",
+ zlog_info ("Packet[DD] [Slave]: Neighbor %s packet duplicated.",
inet_ntoa (nbr->router_id));
ospf_db_desc_resend (nbr);
}
/* Check initialize bit is set. */
if (IS_SET_DD_I (dd->flags))
{
- zlog_warn ("Packet[DD]: Neighbor %s I-bit set.",
+ zlog_info ("Packet[DD]: Neighbor %s I-bit set.",
inet_ntoa(nbr->router_id));
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
break;
if (IS_SET_DD_MS (nbr->dd_flags))
{
/* Master should discard duplicate DD packet. */
- zlog_warn("Packet[DD]: Neighbor %s duplicated, packet discarded.",
+ zlog_info ("Packet[DD]: Neighbor %s duplicated, "
+ "packet discarded.",
inet_ntoa(nbr->router_id));
break;
}
#define OSPF_LSA_KEY_SIZE 12 /* type(4) + id(4) + ar(4) */
/* OSPF Link State Request Read -- RFC2328 Section 10.7. */
-void
+static void
ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
struct stream *s, struct ospf_interface *oi, u_int16_t size)
{
}
/* Cleanup Update list. */
-void
+static void
ospf_upd_list_clean (struct list *lsas)
{
- struct listnode *node;
+ struct listnode *node, *nnode;
struct ospf_lsa *lsa;
- for (node = listhead (lsas); node; nextnode (node))
- if ((lsa = getdata (node)) != NULL)
- ospf_lsa_discard (lsa);
+ for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
+ ospf_lsa_discard (lsa);
list_delete (lsas);
}
/* OSPF Link State Update message read -- RFC2328 Section 13. */
-void
+static void
ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
struct stream *s, struct ospf_interface *oi, u_int16_t size)
{
struct ospf_neighbor *nbr;
struct list *lsas;
-#ifdef HAVE_OPAQUE_LSA
- struct list *mylsa_acks, *mylsa_upds;
-#endif /* HAVE_OPAQUE_LSA */
- struct listnode *node, *next;
+ struct listnode *node, *nnode;
struct ospf_lsa *lsa = NULL;
/* unsigned long ls_req_found = 0; */
lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);
#ifdef HAVE_OPAQUE_LSA
- /*
- * Prepare two kinds of lists to clean up unwanted self-originated
- * Opaque-LSAs from the routing domain as soon as possible.
- */
- mylsa_acks = list_new (); /* Let the sender cease retransmission. */
- mylsa_upds = list_new (); /* Flush target LSAs if necessary. */
-
/*
* If self-originated Opaque-LSAs that have flooded before restart
* are contained in the received LSUpd message, corresponding LSReq
* updating for the same LSA would take place alternately, this trick
* must be done before entering to the loop below.
*/
+ /* XXX: Why is this Opaque specific? Either our core code is deficient
+ * and this should be fixed generally, or Opaque is inventing strawman
+ * problems */
ospf_opaque_adjust_lsreq (nbr, lsas);
#endif /* HAVE_OPAQUE_LSA */
continue; }
/* Process each LSA received in the one packet. */
- for (node = listhead (lsas); node; node = next)
+ for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
{
struct ospf_lsa *ls_ret, *current;
int ret = 1;
- next = node->next;
-
- lsa = getdata (node);
-
if (IS_DEBUG_OSPF_NSSA)
{
char buf1[INET_ADDRSTRLEN];
ospf_ls_ack_send (nbr, lsa);
/* Discard LSA. */
- zlog_warn("Link State Update[%s]: LS age is equal to MaxAge.",
- dump_lsa_key(lsa));
+ zlog_info ("Link State Update[%s]: LS age is equal to MaxAge.",
+ dump_lsa_key(lsa));
DISCARD_LSA (lsa, 3);
}
* Otherwise, the LSA instance remains in the routing domain
* until its age reaches to MaxAge.
*/
+ /* XXX: We should deal with this for *ALL* LSAs, not just opaque */
if (current == NULL)
{
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("LSA[%s]: Previously originated Opaque-LSA, not found in the LSDB.", dump_lsa_key (lsa));
+ zlog_debug ("LSA[%s]: Previously originated Opaque-LSA,"
+ "not found in the LSDB.", dump_lsa_key (lsa));
SET_FLAG (lsa->flags, OSPF_LSA_SELF);
- listnode_add (mylsa_upds, ospf_lsa_dup (lsa));
- listnode_add (mylsa_acks, ospf_lsa_lock (lsa));
+
+ ospf_opaque_self_originated_lsa_received (nbr, lsa);
+ ospf_ls_ack_send (nbr, lsa);
+
continue;
}
}
#endif /* HAVE_OPAQUE_LSA */
+
/* It might be happen that received LSA is self-originated network LSA, but
* router ID is cahnged. So, we should check if LSA is a network-LSA whose
* Link State ID is one of the router's own IP interface addresses but whose
if(lsa->data->type == OSPF_NETWORK_LSA)
{
- struct listnode *oi_node;
+ struct listnode *oinode, *oinnode;
+ struct ospf_interface *out_if;
int Flag = 0;
- for(oi_node = listhead(oi->ospf->oiflist); oi_node; oi_node = nextnode(oi_node))
+ for (ALL_LIST_ELEMENTS (oi->ospf->oiflist, oinode, oinnode, out_if))
{
- struct ospf_interface *out_if = getdata(oi_node);
if(out_if == NULL)
break;
ospf_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;
}
}
}
-#ifdef HAVE_OPAQUE_LSA
- /*
- * Now that previously originated Opaque-LSAs those which not yet
- * installed into LSDB are captured, take several steps to clear
- * them completely from the routing domain, before proceeding to
- * origination for the current target Opaque-LSAs.
- */
- while (listcount (mylsa_acks) > 0)
- ospf_ls_ack_send_list (oi, mylsa_acks, nbr->address.u.prefix4);
-
- if (listcount (mylsa_upds) > 0)
- ospf_opaque_self_originated_lsa_received (nbr, mylsa_upds);
-
- list_delete (mylsa_upds);
- list_delete (mylsa_acks);
-#endif /* HAVE_OPAQUE_LSA */
-
assert (listcount (lsas) == 0);
list_delete (lsas);
}
/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
-void
+static void
ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
struct stream *s, struct ospf_interface *oi, u_int16_t size)
{
struct ospf_neighbor *nbr;
-#ifdef HAVE_OPAQUE_LSA
- struct list *opaque_acks;
-#endif /* HAVE_OPAQUE_LSA */
-
+
/* increment statistics. */
oi->ls_ack_in++;
LOOKUP(ospf_nsm_state_msg, nbr->state));
return;
}
-
-#ifdef HAVE_OPAQUE_LSA
- opaque_acks = list_new ();
-#endif /* HAVE_OPAQUE_LSA */
-
+
while (size >= OSPF_LSA_HEADER_SIZE)
{
struct ospf_lsa *lsa, *lsr;
if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
{
#ifdef HAVE_OPAQUE_LSA
- /* Keep this LSA entry for later reference. */
if (IS_OPAQUE_LSA (lsr->data->type))
- listnode_add (opaque_acks, ospf_lsa_dup (lsr));
+ ospf_opaque_ls_ack_received (nbr, lsr);
#endif /* HAVE_OPAQUE_LSA */
ospf_ls_retransmit_delete (nbr, lsr);
ospf_lsa_discard (lsa);
}
-#ifdef HAVE_OPAQUE_LSA
- if (listcount (opaque_acks) > 0)
- ospf_opaque_ls_ack_received (nbr, opaque_acks);
-
- list_delete (opaque_acks);
return;
-#endif /* HAVE_OPAQUE_LSA */
}
\f
-struct stream *
-ospf_recv_packet (int fd, struct interface **ifp)
+static struct stream *
+ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)
{
int ret;
- struct ip iph;
+ struct ip *iph;
u_int16_t ip_len;
- struct stream *ibuf;
unsigned int ifindex = 0;
struct iovec iov;
/* Header and data both require alignment. */
msgh.msg_control = (caddr_t) buff;
msgh.msg_controllen = sizeof (buff);
- ret = recvfrom (fd, (void *)&iph, sizeof (iph), MSG_PEEK, NULL, 0);
-
- if (ret != sizeof (iph))
+ ret = stream_recvmsg (ibuf, fd, &msgh, 0, OSPF_MAX_PACKET_SIZE+1);
+ if (ret < 0)
{
- zlog_warn ("ospf_recv_packet packet smaller than ip header");
- /* XXX: We peeked, and thus perhaps should discard this packet. */
+ zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
+ return NULL;
+ }
+ if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */
+ {
+ zlog_warn("ospf_recv_packet: discarding runt packet of length %d "
+ "(ip header size is %u)",
+ ret, (u_int)sizeof(iph));
return NULL;
}
- sockopt_iphdrincl_swab_systoh (&iph);
+ /* Note that there should not be alignment problems with this assignment
+ because this is at the beginning of the stream data buffer. */
+ iph = (struct ip *) STREAM_DATA(ibuf);
+ sockopt_iphdrincl_swab_systoh (iph);
- ip_len = iph.ip_len;
+ ip_len = iph->ip_len;
#if !defined(GNU_LINUX) && (OpenBSD < 200311)
/*
*
* For more details, see <netinet/ip_input.c>.
*/
- ip_len = ip_len + (iph.ip_hl << 2);
+ ip_len = ip_len + (iph->ip_hl << 2);
#endif
- if ( (ibuf = stream_new (ip_len)) == NULL)
- return NULL;
- iov.iov_base = STREAM_DATA (ibuf);
- iov.iov_len = ip_len;
-
- ret = stream_recvmsg (ibuf, fd, &msgh, 0, ip_len);
-
ifindex = getsockopt_ifindex (AF_INET, &msgh);
*ifp = if_lookup_by_index (ifindex);
if (ret != ip_len)
{
- zlog_warn ("ospf_recv_packet short read. "
- "ip_len %d bytes read %d", ip_len, ret);
- stream_free (ibuf);
+ zlog_warn ("ospf_recv_packet read length mismatch: ip_len is %d, "
+ "but recvmsg returned %d", ip_len, ret);
return NULL;
}
return ibuf;
}
-struct ospf_interface *
+static struct ospf_interface *
ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
struct ip *iph, struct ospf_header *ospfh)
{
iph->ip_dst)) == NULL)
return NULL;
- for (node = listhead (ospf->vlinks); node; nextnode (node))
+ for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
{
- if ((vl_data = getdata (node)) == NULL)
- continue;
-
vl_area = ospf_area_lookup_by_area_id (ospf, vl_data->vl_area_id);
if (!vl_area)
continue;
return NULL;
}
-int
+static inline int
ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
{
/* Check match the Area ID of the receiving interface. */
/* Unbound socket will accept any Raw IP packets if proto is matched.
To prevent it, compare src IP address and i/f address with masking
i/f network mask. */
-int
+static int
ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
{
struct in_addr mask, me, him;
return 0;
}
-int
+static int
ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
struct ospf_header *ospfh)
{
ret = 0;
break;
case OSPF_AUTH_CRYPTOGRAPHIC:
- if ((ck = getdata (OSPF_IF_PARAM (oi,auth_crypt)->tail)) == NULL)
+ if ((ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) == NULL)
{
ret = 0;
break;
return ret;
}
-int
+static int
ospf_check_sum (struct ospf_header *ospfh)
{
u_int32_t ret;
u_int16_t sum;
- int in_cksum (void *ptr, int nbytes);
/* clear auth_data for checksum. */
memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
}
/* OSPF Header verification. */
-int
+static int
ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
struct ip *iph, struct ospf_header *ospfh)
{
/* Check authentication. */
if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
{
- zlog_warn ("interface %s: ospf_read authentication type mismatch.",
- IF_NAME (oi));
+ zlog_warn ("interface %s: auth-type mismatch, local %d, rcvd %d",
+ IF_NAME (oi), ospf_auth_type (oi), ntohs (ospfh->auth_type));
return -1;
}
/* first of all get interface pointer. */
ospf = THREAD_ARG (thread);
- ospf->t_read = NULL;
+
+ /* prepare for next packet. */
+ ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
/* read OSPF packet. */
- ibuf = ospf_recv_packet (ospf->fd, &ifp);
- if (ibuf == NULL)
+ stream_reset(ospf->ibuf);
+ if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
return -1;
+ /* Note that there should not be alignment problems with this assignment
+ because this is at the beginning of the stream data buffer. */
iph = (struct ip *) STREAM_DATA (ibuf);
- sockopt_iphdrincl_swab_systoh (iph);
+ /* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */
if (ifp == NULL)
/* Handle cases where the platform does not support retrieving the ifindex,
ifp = if_lookup_address (iph->ip_src);
if (ifp == NULL)
- {
- stream_free (ibuf);
- return 0;
- }
-
- /* prepare for next packet. */
- ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
+ return 0;
/* IP Header dump. */
if (IS_DEBUG_OSPF_PACKET(0, RECV))
zlog_debug ("ospf_read[%s]: Dropping self-originated packet",
inet_ntoa (iph->ip_src));
}
- stream_free (ibuf);
return 0;
}
{
if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)
{
- zlog_warn ("Packet from [%s] received on link %s"
+ zlog_debug ("Packet from [%s] received on link %s"
" but no ospf_interface",
inet_ntoa (iph->ip_src), ifp->name);
- stream_free (ibuf);
return 0;
}
}
{
zlog_warn ("Packet from [%s] received on wrong link %s",
inet_ntoa (iph->ip_src), ifp->name);
- stream_free (ibuf);
return 0;
}
else if (oi->state == ISM_Down)
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));
- stream_free (ibuf);
/* Fix multicast memberships? */
if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
zlog_warn ("Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)",
inet_ntoa (iph->ip_src), IF_NAME (oi),
LOOKUP (ospf_ism_state_msg, oi->state));
- stream_free (ibuf);
/* Try to fix multicast membership. */
SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
ospf_if_set_multicast(oi);
ospf_packet_type_str[ospfh->type],
inet_ntoa (iph->ip_src));
}
- stream_free (ibuf);
return ret;
}
break;
}
- stream_free (ibuf);
return 0;
}
/* Make OSPF header. */
-void
+static void
ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
{
struct ospf_header *ospfh;
}
/* Make Authentication Data. */
-int
+static int
ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
{
struct crypt_key *ck;
}
else
{
- ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
+ ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
ospfh->u.crypt.zero = 0;
ospfh->u.crypt.key_id = ck->key_id;
ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
}
/* Fill rest of OSPF header. */
-void
+static void
ospf_fill_header (struct ospf_interface *oi,
struct stream *s, u_int16_t length)
{
ospf_make_auth (oi, ospfh);
}
-int
+static int
ospf_make_hello (struct ospf_interface *oi, struct stream *s)
{
struct ospf_neighbor *nbr;
stream_put_ipv4 (s, mask.s_addr);
/* Set Hello Interval. */
- stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
+ if (OSPF_IF_PARAM (oi, fast_hello) == 0)
+ stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
+ else
+ stream_putw (s, 0); /* hello-interval of 0 for fast-hellos */
if (IS_DEBUG_OSPF_EVENT)
zlog_debug ("make_hello: options: %x, int: %s",
return length;
}
-int
+static int
ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
struct stream *s)
{
return length;
}
-int
+static int
ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
unsigned long delta, struct ospf_neighbor *nbr,
struct ospf_lsa *lsa)
return 1;
}
-int
+static int
ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s)
{
struct ospf_lsa *lsa;
return length;
}
-int
+static int
ls_age_increment (struct ospf_lsa *lsa, int delay)
{
int age;
return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age);
}
-int
+static int
ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream *s)
{
struct ospf_lsa *lsa;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug ("ospf_make_ls_upd: List Iteration");
- lsa = getdata (node);
- assert (lsa);
+ lsa = listgetdata (node);
+
assert (lsa->data);
/* Will it fit? */
return length;
}
-int
+static int
ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
{
struct list *rm_list;
rm_list = list_new ();
- for (node = listhead (ack); node; nextnode (node))
+ for (ALL_LIST_ELEMENTS_RO (ack, node, lsa))
{
- lsa = getdata (node);
+ lsa = listgetdata (node);
assert (lsa);
if (length + delta > ospf_packet_max (oi))
}
/* Remove LSA from LS-Ack list. */
- for (node = listhead (rm_list); node; nextnode (node))
+ /* XXX: this loop should be removed and the list move done in previous
+ * loop
+ */
+ for (ALL_LIST_ELEMENTS_RO (rm_list, node, lsa))
{
- lsa = (struct ospf_lsa *) getdata (node);
-
listnode_delete (ack, lsa);
ospf_lsa_unlock (lsa);
}
OSPF_ISM_WRITE_ON (oi->ospf);
}
-void
+static void
ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
{
struct ospf_interface *oi;
size_t size;
static char warned = 0;
- ln = listhead (update);
- lsa = getdata (ln);
- assert (lsa);
+ lsa = listgetdata((ln = listhead (update)));
assert (lsa->data);
if ((OSPF_LS_UPD_MIN_SIZE + ntohs (lsa->data->length))
ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
{
struct ospf_interface *oi;
+ struct ospf_lsa *lsa;
struct prefix_ipv4 p;
struct route_node *rn;
- struct listnode *n;
+ struct listnode *node;
oi = nbr->oi;
if (rn->info == NULL)
rn->info = list_new ();
- for (n = listhead (update); n; nextnode (n))
- listnode_add (rn->info, ospf_lsa_lock (getdata (n)));
+ for (ALL_LIST_ELEMENTS_RO (update, node, lsa))
+ {
+ ospf_lsa_lock (lsa);
+ listnode_add (rn->info, lsa);
+ }
if (oi->t_ls_upd_event == NULL)
oi->t_ls_upd_event =