--- embedaddon/quagga/ospfd/ospf_packet.c 2012/10/09 09:22:29 1.1.1.3 +++ embedaddon/quagga/ospfd/ospf_packet.c 2016/11/02 10:09:12 1.1.1.5 @@ -323,7 +323,7 @@ ospf_packet_max (struct ospf_interface *oi) return max; } - + static int ospf_check_md5_digest (struct ospf_interface *oi, struct ospf_header *ospfh) { @@ -383,7 +383,7 @@ 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]; + unsigned char digest[OSPF_AUTH_MD5_SIZE] = {0}; MD5_CTX ctx; void *ibuf; u_int32_t t; @@ -410,7 +410,7 @@ ospf_make_md5_digest (struct ospf_interface *oi, struc /* Get MD5 Authentication key from auth_key list. */ if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt))) - auth_key = (const u_int8_t *) ""; + auth_key = (const u_int8_t *) digest; else { ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt))); @@ -438,7 +438,7 @@ ospf_make_md5_digest (struct ospf_interface *oi, struc return OSPF_AUTH_MD5_SIZE; } - + static int ospf_ls_req_timer (struct thread *thread) { @@ -644,8 +644,8 @@ ospf_write (struct thread *thread) struct listnode *node; #ifdef WANT_OSPF_WRITE_FRAGMENT static u_int16_t ipid = 0; -#endif /* WANT_OSPF_WRITE_FRAGMENT */ u_int16_t maxdatasize; +#endif /* WANT_OSPF_WRITE_FRAGMENT */ #define OSPF_WRITE_IPHL_SHIFT 2 ospf->t_write = NULL; @@ -659,7 +659,6 @@ ospf_write (struct thread *thread) /* seed ipid static with low order bits of time */ if (ipid == 0) ipid = (time(NULL) & 0xffff); -#endif /* WANT_OSPF_WRITE_FRAGMENT */ /* convenience - max OSPF data per packet, * and reliability - not more data, than our @@ -667,6 +666,7 @@ ospf_write (struct thread *thread) */ maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) - sizeof (struct ip); +#endif /* WANT_OSPF_WRITE_FRAGMENT */ /* Get one packet from queue. */ op = ospf_fifo_head (oi->obuf); @@ -789,6 +789,9 @@ ospf_write (struct thread *thread) /* Now delete packet from queue. */ ospf_packet_delete (oi); + /* Move this interface to the tail of write_q to + serve everyone in a round robin fashion */ + listnode_move_to_tail (ospf->oi_write_q, node); if (ospf_fifo_head (oi->obuf) == NULL) { oi->on_write_q = 0; @@ -891,7 +894,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, } #endif /* REJECT_IF_TBIT_ON */ -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE) && CHECK_FLAG (hello->options, OSPF_OPTION_O)) { @@ -907,7 +909,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, 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 */ @@ -1059,7 +1060,6 @@ ospf_db_desc_proc (struct stream *s, struct ospf_inter return; } -#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsah->type) && ! CHECK_FLAG (nbr->options, OSPF_OPTION_O)) { @@ -1067,14 +1067,11 @@ ospf_db_desc_proc (struct stream *s, struct ospf_inter 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) @@ -1245,7 +1242,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospf } #endif /* REJECT_IF_TBIT_ON */ -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (dd->options, OSPF_OPTION_O) && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { @@ -1255,7 +1251,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospf */ UNSET_FLAG (dd->options, OSPF_OPTION_O); } -#endif /* HAVE_OPAQUE_LSA */ /* Add event to thread. */ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); @@ -1320,7 +1315,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospf /* This is where the real Options are saved */ nbr->options = dd->options; -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { if (IS_DEBUG_OSPF_EVENT) @@ -1338,7 +1332,6 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospf /* This situation is undesirable, but not a real error. */ } } -#endif /* HAVE_OPAQUE_LSA */ OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone); @@ -1590,7 +1583,7 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc /* Validate the LSA's LS checksum. */ sum = lsah->checksum; - if (sum != ospf_lsa_checksum (lsah)) + if (! ospf_lsa_checksum_valid (lsah)) { /* (bug #685) more details in a one-line message make it possible * to identify problem source on the one hand and to have a better @@ -1616,7 +1609,6 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc 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 @@ -1648,7 +1640,6 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc 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 (); @@ -1658,14 +1649,12 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc 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; @@ -1676,7 +1665,7 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc if (IS_DEBUG_OSPF_EVENT) zlog_debug("LSA[Type%d:%s]: %p new LSA created with Link State Update", - lsa->data->type, inet_ntoa (lsa->data->id), lsa); + lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa); listnode_add (lsas, lsa); } @@ -1698,7 +1687,7 @@ ospf_upd_list_clean (struct list *lsas) /* OSPF Link State Update message read -- RFC2328 Section 13. */ static void -ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, +ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh, struct stream *s, struct ospf_interface *oi, u_int16_t size) { struct ospf_neighbor *nbr; @@ -1740,28 +1729,18 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh */ lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size); -#ifdef HAVE_OPAQUE_LSA - /* - * 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. - */ - /* XXX: Why is this Opaque specific? Either our core code is deficient - * and this should be fixed generally, or Opaque is inventing strawman - * problems */ - ospf_opaque_adjust_lsreq (nbr, lsas); -#endif /* HAVE_OPAQUE_LSA */ - #define DISCARD_LSA(L,N) {\ if (IS_DEBUG_OSPF_EVENT) \ - zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \ + zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p" \ + " Type-%d", N, (void *)lsa, (int) lsa->data->type); \ ospf_lsa_discard (L); \ continue; } - /* Process each LSA received in the one packet. */ + /* Process each LSA received in the one packet. + * + * Numbers in parentheses, e.g. (1), (2), etc., and the corresponding + * text below are from the steps in RFC 2328, Section 13. + */ for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa)) { struct ospf_lsa *ls_ret, *current; @@ -1785,11 +1764,11 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh listnode_delete (lsas, lsa); /* We don't need it in list anymore */ - /* Validate Checksum - Done above by ospf_ls_upd_list_lsa() */ + /* (1) Validate Checksum - Done above by ospf_ls_upd_list_lsa() */ - /* LSA Type - Done above by ospf_ls_upd_list_lsa() */ + /* (2) LSA Type - Done above by ospf_ls_upd_list_lsa() */ - /* Do not take in AS External LSAs if we are a stub or NSSA. */ + /* (3) 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 */ @@ -1817,29 +1796,51 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh DISCARD_LSA (lsa,2); } + /* VU229804: Router-LSA Adv-ID must be equal to LS-ID */ + if (lsa->data->type == OSPF_ROUTER_LSA) + if (!IPV4_ADDR_SAME(&lsa->data->id, &lsa->data->adv_router)) + { + char buf1[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + char buf3[INET_ADDRSTRLEN]; + + zlog_err("Incoming Router-LSA from %s with " + "Adv-ID[%s] != LS-ID[%s]", + 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)); + zlog_err("OSPF domain compromised by attack or corruption. " + "Verify correct operation of -ALL- OSPF routers."); + DISCARD_LSA (lsa, 0); + } + /* 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 + /* (4) 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. */ + then take the following actions: */ if (IS_LSA_MAXAGE (lsa) && !current && - (ospf_nbr_count (oi, NSM_Exchange) + - ospf_nbr_count (oi, NSM_Loading)) == 0) + ospf_check_nbr_status(oi->ospf)) { - /* Response Link State Acknowledgment. */ + /* (4a) Response Link State Acknowledgment. */ ospf_ls_ack_send (nbr, lsa); - /* Discard LSA. */ - zlog_info ("Link State Update[%s]: LS age is equal to MaxAge.", - dump_lsa_key(lsa)); + /* (4b) Discard LSA. */ + if (IS_DEBUG_OSPF (lsa, LSA)) + { + zlog_debug ("Link State Update[%s]: LS age is equal to MaxAge.", + dump_lsa_key(lsa)); + } DISCARD_LSA (lsa, 3); } -#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsa->data->type) && IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id)) { @@ -1887,10 +1888,9 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh 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 + * router ID is changed. 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. @@ -1915,7 +1915,7 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh ospf_lsa_flush_area(lsa,out_if->area); if(IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d", - lsa, (int) lsa->data->type); + (void *)lsa, (int) lsa->data->type); ospf_lsa_discard (lsa); Flag = 1; } @@ -1929,7 +1929,9 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh /* (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. */ + the database copy the following steps must be performed. + (The sub steps from RFC 2328 section 13 step (5) will be performed in + ospf_flood() ) */ if (current == NULL || (ret = ospf_lsa_more_recent (current, lsa)) < 0) @@ -2026,7 +2028,7 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh quagga_gettime (QUAGGA_CLK_MONOTONIC, &now); if (tv_cmp (tv_sub (now, current->tv_orig), - int2tv (OSPF_MIN_LS_ARRIVAL)) >= 0) + msec2tv (ospf->min_ls_arrival)) >= 0) /* Trap NSSA type later.*/ ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT); DISCARD_LSA (lsa, 8); @@ -2089,30 +2091,23 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh lsr = ospf_ls_retransmit_lookup (nbr, lsa); - if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum) - { -#ifdef HAVE_OPAQUE_LSA - if (IS_OPAQUE_LSA (lsr->data->type)) - ospf_opaque_ls_ack_received (nbr, lsr); -#endif /* HAVE_OPAQUE_LSA */ + if (lsr != NULL && ospf_lsa_more_recent (lsr, lsa) == 0) + ospf_ls_retransmit_delete (nbr, lsr); - ospf_ls_retransmit_delete (nbr, lsr); - } - lsa->data = NULL; ospf_lsa_discard (lsa); } return; } - + static struct stream * ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf) { int ret; struct ip *iph; u_int16_t ip_len; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; struct iovec iov; /* Header and data both require alignment. */ char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())]; @@ -2468,7 +2463,6 @@ ospf_lsa_examin (struct lsa_header * lsah, const u_int case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: /* RFC2328 A.4.4, LSA header + 4 bytes followed by N>=1 4-bytes TOS blocks */ -#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: @@ -2476,7 +2470,6 @@ ospf_lsa_examin (struct lsa_header * lsah, const u_int * data) padded to 32-bit alignment." This is considered equivalent * to 4-byte alignment of all other LSA types, see OSPF-ALIGNMENT.txt * file for the detailed analysis of this passage. */ -#endif ret = lsalen % 4 ? MSG_NG : MSG_OK; break; default: @@ -2919,7 +2912,7 @@ ospf_read (struct thread *thread) ospf_ls_req (iph, ospfh, ibuf, oi, length); break; case OSPF_MSG_LS_UPD: - ospf_ls_upd (iph, ospfh, ibuf, oi, length); + ospf_ls_upd (ospf, iph, ospfh, ibuf, oi, length); break; case OSPF_MSG_LS_ACK: ospf_ls_ack (iph, ospfh, ibuf, oi, length); @@ -3107,25 +3100,8 @@ ospf_make_db_desc (struct ospf_interface *oi, struct o /* Set Options. */ options = OPTIONS (oi); -#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) - { - 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 */ + SET_FLAG (options, OSPF_OPTION_O); stream_putc (s, options); /* DD flags */ @@ -3150,7 +3126,6 @@ ospf_make_db_desc (struct ospf_interface *oi, struct o 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))) { @@ -3159,7 +3134,6 @@ ospf_make_db_desc (struct ospf_interface *oi, struct o ospf_lsdb_delete (lsdb, lsa); continue; } -#endif /* HAVE_OPAQUE_LSA */ if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD)) { @@ -3295,7 +3269,7 @@ ospf_make_ls_upd (struct ospf_interface *oi, struct li u_int16_t ls_age; if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_make_ls_upd: List Iteration"); + zlog_debug ("ospf_make_ls_upd: List Iteration %d", count); lsa = listgetdata (node); @@ -3701,7 +3675,8 @@ ospf_ls_upd_queue_send (struct ospf_interface *oi, str u_int16_t length = OSPF_HEADER_SIZE; if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr)); + zlog_debug ("listcount = %d, [%s]dst %s", listcount (update), IF_NAME(oi), + inet_ntoa(addr)); op = ospf_ls_upd_packet_new (update, oi); @@ -3823,6 +3798,8 @@ ospf_ls_upd_send (struct ospf_neighbor *nbr, struct li if (rn->info == NULL) rn->info = list_new (); + else + route_unlock_node (rn); for (ALL_LIST_ELEMENTS_RO (update, node, lsa)) listnode_add (rn->info, ospf_lsa_lock (lsa)); /* oi->ls_upd_queue */