X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ospfd%2Fospf_packet.c;h=d6aca719862452271b25eabdcb1d1974f7874cc3;hb=c6371718f39dedd2a03010a9dc26a18d96abbe7f;hp=58369250cf4c8571591bdededf8c913a51ecc451;hpb=658b03a6bbb88357d841a99908d729e05e3b98c2;p=mirror_frr.git diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 58369250c..d6aca7198 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -32,7 +32,8 @@ #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" @@ -48,9 +49,6 @@ #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[] = { @@ -62,10 +60,8 @@ 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; @@ -214,17 +210,6 @@ ospf_packet_delete (struct ospf_interface *oi) ospf_packet_free (op); } -struct stream * -ospf_stream_copy (struct stream *new, struct stream *s) -{ - new->endp = s->endp; - new->getp = s->getp; - - memcpy (new->data, s->data, stream_get_endp (s)); - - return new; -} - struct ospf_packet * ospf_packet_dup (struct ospf_packet *op) { @@ -236,7 +221,7 @@ 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; @@ -245,7 +230,7 @@ ospf_packet_dup (struct ospf_packet *op) } /* XXX inline */ -unsigned int +static inline unsigned int ospf_packet_authspace (struct ospf_interface *oi) { int auth = 0; @@ -256,7 +241,7 @@ ospf_packet_authspace (struct ospf_interface *oi) return auth; } -unsigned int +static unsigned int ospf_packet_max (struct ospf_interface *oi) { int max; @@ -269,12 +254,12 @@ ospf_packet_max (struct ospf_interface *oi) } -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; @@ -311,10 +296,11 @@ ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s, } /* 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)) @@ -333,16 +319,16 @@ ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s, /* 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; @@ -353,23 +339,28 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op) /* 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); @@ -384,7 +375,7 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op) } -int +static int ospf_ls_req_timer (struct thread *thread) { struct ospf_neighbor *nbr; @@ -429,10 +420,8 @@ ospf_ls_upd_timer (struct thread *thread) 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; @@ -455,7 +444,7 @@ ospf_ls_upd_timer (struct thread *thread) 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); } @@ -491,7 +480,7 @@ ospf_ls_ack_timer (struct thread *thread) } #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) @@ -542,12 +531,13 @@ ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph, 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)) { @@ -574,7 +564,7 @@ ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph, } #endif /* WANT_OSPF_WRITE_FRAGMENT */ -int +static int ospf_write (struct thread *thread) { struct ospf *ospf = THREAD_ARG (thread); @@ -598,7 +588,7 @@ ospf_write (struct thread *thread) node = listhead (ospf->oi_write_q); assert (node); - oi = getdata (node); + oi = listgetdata (node); assert (oi); #ifdef WANT_OSPF_WRITE_FRAGMENT @@ -698,9 +688,9 @@ ospf_write (struct thread *thread) 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)) @@ -739,7 +729,7 @@ ospf_write (struct thread *thread) } /* 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) { @@ -769,12 +759,12 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, /* 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. */ @@ -800,14 +790,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, 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)) { @@ -816,6 +798,17 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, 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), @@ -971,7 +964,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, } /* Save DD flags/options/Seqnum received. */ -void +static void ospf_db_desc_save_current (struct ospf_neighbor *nbr, struct ospf_db_desc *dd) { @@ -1088,7 +1081,7 @@ ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi, 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? */ @@ -1122,7 +1115,8 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, } /* 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), @@ -1210,7 +1204,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, 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; } @@ -1245,7 +1239,10 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, 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. */ } } @@ -1261,12 +1258,12 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, { 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); } @@ -1289,7 +1286,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, /* 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; @@ -1330,7 +1327,8 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, 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; } @@ -1368,7 +1366,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, #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) { @@ -1586,30 +1584,26 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s, } /* 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; */ @@ -1644,13 +1638,6 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, 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 @@ -1659,6 +1646,9 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, * 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 */ @@ -1669,15 +1659,11 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, 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]; @@ -1745,8 +1731,8 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, 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); } @@ -1783,18 +1769,23 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, * 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 @@ -1804,12 +1795,12 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, 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; @@ -1863,10 +1854,6 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, 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; } @@ -1944,37 +1931,17 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, } } -#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++; @@ -1994,11 +1961,7 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh, 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; @@ -2022,9 +1985,8 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh, 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); @@ -2034,22 +1996,15 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh, 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) +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. */ @@ -2062,18 +2017,26 @@ ospf_recv_packet (int fd, struct interface **ifp) 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) /* @@ -2090,32 +2053,24 @@ ospf_recv_packet (int fd, struct interface **ifp) * * For more details, see . */ - 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) { @@ -2137,11 +2092,8 @@ ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp, 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; @@ -2169,7 +2121,7 @@ ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp, 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. */ @@ -2182,7 +2134,7 @@ ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh) /* 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; @@ -2202,7 +2154,7 @@ ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src) return 0; } -int +static int ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf, struct ospf_header *ospfh) { @@ -2221,7 +2173,7 @@ ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf, 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; @@ -2243,12 +2195,11 @@ ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf, 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); @@ -2271,7 +2222,7 @@ ospf_check_sum (struct ospf_header *ospfh) } /* OSPF Header verification. */ -int +static int ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi, struct ip *iph, struct ospf_header *ospfh) { @@ -2302,8 +2253,8 @@ ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi, /* 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; } @@ -2354,15 +2305,19 @@ ospf_read (struct thread *thread) /* 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, @@ -2371,13 +2326,7 @@ ospf_read (struct thread *thread) 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)) @@ -2391,7 +2340,6 @@ ospf_read (struct thread *thread) zlog_debug ("ospf_read[%s]: Dropping self-originated packet", inet_ntoa (iph->ip_src)); } - stream_free (ibuf); return 0; } @@ -2415,10 +2363,9 @@ ospf_read (struct thread *thread) { 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; } } @@ -2430,7 +2377,6 @@ ospf_read (struct thread *thread) { 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) @@ -2441,7 +2387,6 @@ ospf_read (struct thread *thread) 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); @@ -2463,7 +2408,6 @@ ospf_read (struct thread *thread) 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); @@ -2500,7 +2444,6 @@ ospf_read (struct thread *thread) ospf_packet_type_str[ospfh->type], inet_ntoa (iph->ip_src)); } - stream_free (ibuf); return ret; } @@ -2534,12 +2477,11 @@ ospf_read (struct thread *thread) 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; @@ -2561,7 +2503,7 @@ ospf_make_header (int type, struct ospf_interface *oi, struct stream *s) } /* Make Authentication Data. */ -int +static int ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh) { struct crypt_key *ck; @@ -2585,7 +2527,7 @@ ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh) } 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; @@ -2601,7 +2543,7 @@ ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh) } /* Fill rest of OSPF header. */ -void +static void ospf_fill_header (struct ospf_interface *oi, struct stream *s, u_int16_t length) { @@ -2622,7 +2564,7 @@ ospf_fill_header (struct ospf_interface *oi, ospf_make_auth (oi, ospfh); } -int +static int ospf_make_hello (struct ospf_interface *oi, struct stream *s) { struct ospf_neighbor *nbr; @@ -2641,7 +2583,10 @@ ospf_make_hello (struct ospf_interface *oi, struct stream *s) 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", @@ -2689,7 +2634,7 @@ ospf_make_hello (struct ospf_interface *oi, struct stream *s) return length; } -int +static int ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr, struct stream *s) { @@ -2800,7 +2745,7 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr, 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) @@ -2824,7 +2769,7 @@ ospf_make_ls_req_func (struct stream *s, u_int16_t *length, return 1; } -int +static int ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s) { struct ospf_lsa *lsa; @@ -2851,7 +2796,7 @@ ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s) return length; } -int +static int ls_age_increment (struct ospf_lsa *lsa, int delay) { int age; @@ -2861,7 +2806,7 @@ ls_age_increment (struct ospf_lsa *lsa, int delay) 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; @@ -2889,8 +2834,8 @@ ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream 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? */ @@ -2924,7 +2869,7 @@ ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream return length; } -int +static int ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s) { struct list *rm_list; @@ -2935,9 +2880,9 @@ ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s) 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)) @@ -2950,10 +2895,11 @@ ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s) } /* 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); } @@ -2992,7 +2938,7 @@ ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr) OSPF_ISM_WRITE_ON (oi->ospf); } -void +static void ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma) { struct ospf_interface *oi; @@ -3271,9 +3217,7 @@ ospf_ls_upd_packet_new (struct list *update, 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)) @@ -3411,9 +3355,10 @@ void 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; @@ -3448,8 +3393,11 @@ ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag) 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 =