diff options
Diffstat (limited to 'ospfd/ospf_packet.c')
| -rw-r--r-- | ospfd/ospf_packet.c | 504 |
1 files changed, 91 insertions, 413 deletions
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 552acfd6d3..60479ddcd1 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -41,6 +41,7 @@ #include "ospfd/ospf_errors.h" #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_gr.h" +#include "ospfd/ospf_auth.h" /* * OSPF Fragmentation / fragmented writes @@ -99,27 +100,6 @@ static const uint16_t ospf_lsa_minlen[] = { OSPF_OPAQUE_LSA_MIN_SIZE, /* OSPF_OPAQUE_AS_LSA */ }; -/* for ospf_check_auth() */ -static int ospf_check_sum(struct ospf_header *); - -/* OSPF authentication checking function */ -static 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; -} - static struct ospf_packet *ospf_packet_new(size_t size) { struct ospf_packet *new; @@ -258,8 +238,8 @@ static struct ospf_packet *ospf_packet_dup(struct ospf_packet *op) "ospf_packet_dup stream %lu ospf_packet %u size mismatch", (unsigned long)STREAM_SIZE(op->s), op->length); - /* Reserve space for MD5 authentication that may be added later. */ - new = ospf_packet_new(stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE); + /* Reserve space for MD5/HMAC SHA authentication that may be added later. */ + new = ospf_packet_new(stream_get_endp(op->s) + KEYCHAIN_MAX_HASH_SIZE); stream_copy(new->s, op->s); new->dst = op->dst; @@ -274,7 +254,7 @@ static 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; + auth = KEYCHAIN_MAX_HASH_SIZE; return auth; } @@ -290,155 +270,6 @@ static unsigned int ospf_packet_max(struct ospf_interface *oi) return max; } - -static int ospf_check_md5_digest(struct ospf_interface *oi, - struct ospf_header *ospfh) -{ -#ifdef CRYPTO_OPENSSL - EVP_MD_CTX *ctx; -#elif CRYPTO_INTERNAL - MD5_CTX ctx; -#endif - unsigned char digest[OSPF_AUTH_MD5_SIZE]; - struct crypt_key *ck; - struct ospf_neighbor *nbr; - uint16_t length = ntohs(ospfh->length); - - /* Get secret key. */ - ck = ospf_crypt_key_lookup(OSPF_IF_PARAM(oi, auth_crypt), - ospfh->u.crypt.key_id); - if (ck == NULL) { - flog_warn( - EC_OSPF_MD5, - "interface %s: ospf_check_md5 no key %d, Router-ID: %pI4", - IF_NAME(oi), ospfh->u.crypt.key_id, &ospfh->router_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)) { - flog_warn( - EC_OSPF_MD5, - "interface %s: ospf_check_md5 bad sequence %d (expect %d), Router-ID: %pI4", - IF_NAME(oi), ntohl(ospfh->u.crypt.crypt_seqnum), - ntohl(nbr->crypt_seqnum), &ospfh->router_id); - return 0; - } - - /* Generate a digest for the ospf packet - their digest + our digest. */ -#ifdef CRYPTO_OPENSSL - unsigned int md5_size = OSPF_AUTH_MD5_SIZE; - ctx = EVP_MD_CTX_new(); - EVP_DigestInit(ctx, EVP_md5()); - EVP_DigestUpdate(ctx, ospfh, length); - EVP_DigestUpdate(ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE); - EVP_DigestFinal(ctx, digest, &md5_size); - EVP_MD_CTX_free(ctx); -#elif CRYPTO_INTERNAL - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - MD5Update(&ctx, ospfh, length); - MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE); - MD5Final(digest, &ctx); -#endif - - /* compare the two */ - if (memcmp((caddr_t)ospfh + length, digest, OSPF_AUTH_MD5_SIZE)) { - flog_warn( - EC_OSPF_MD5, - "interface %s: ospf_check_md5 checksum mismatch, Router-ID: %pI4", - IF_NAME(oi), &ospfh->router_id); - 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. */ -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] = {0}; -#ifdef CRYPTO_OPENSSL - EVP_MD_CTX *ctx; -#elif CRYPTO_INTERNAL - MD5_CTX ctx; -#endif - void *ibuf; - uint32_t t; - struct crypt_key *ck; - const uint8_t *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. - - Note that frr_time /deliberately/ is not used here */ - t = (time(NULL) & 0xFFFFFFFF); - 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 = (const uint8_t *)digest; - else { - ck = listgetdata(listtail(OSPF_IF_PARAM(oi, auth_crypt))); - auth_key = ck->auth_key; - } - - /* Generate a digest for the entire packet + our secret key. */ -#ifdef CRYPTO_OPENSSL - unsigned int md5_size = OSPF_AUTH_MD5_SIZE; - ctx = EVP_MD_CTX_new(); - EVP_DigestInit(ctx, EVP_md5()); - EVP_DigestUpdate(ctx, ibuf, ntohs(ospfh->length)); - EVP_DigestUpdate(ctx, auth_key, OSPF_AUTH_MD5_SIZE); - EVP_DigestFinal(ctx, digest, &md5_size); - EVP_MD_CTX_free(ctx); -#elif CRYPTO_INTERNAL - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - MD5Update(&ctx, ibuf, ntohs(ospfh->length)); - MD5Update(&ctx, auth_key, OSPF_AUTH_MD5_SIZE); - MD5Final(digest, &ctx); -#endif - - /* 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. */ - op->length = ntohs(ospfh->length) + OSPF_AUTH_MD5_SIZE; - - if (stream_get_endp(op->s) != op->length) - /* XXX size_t */ - flog_warn( - EC_OSPF_MD5, - "%s: length mismatch stream %lu ospf_packet %u, Router-ID %pI4", - __func__, (unsigned long)stream_get_endp(op->s), - op->length, &ospfh->router_id); - - return OSPF_AUTH_MD5_SIZE; -} - - static void ospf_ls_req_timer(struct event *thread) { struct ospf_neighbor *nbr; @@ -677,7 +508,7 @@ static void ospf_write(struct event *thread) ospf_if_ipmulticast(fd, oi->address, oi->ifp->ifindex); /* Rewrite the md5 signature & update the seq */ - ospf_make_md5_digest(oi, op); + ospf_auth_make(oi, op); /* Retrieve OSPF packet type. */ stream_set_getp(op->s, 1); @@ -953,8 +784,9 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, } #endif /* REJECT_IF_TBIT_ON */ - if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) - && CHECK_FLAG(hello->options, OSPF_OPTION_O)) { + if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) && + OSPF_IF_PARAM(oi, opaque_capable) && + 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. @@ -1210,7 +1042,7 @@ static void ospf_db_desc_proc(struct stream *s, struct ospf_interface *oi, /* Neighbour has a more recent LSA, we must request it */ ospf_ls_request_add(nbr, new); - /* fallthru */ + fallthrough; case 0: /* If we have a copy of this LSA, it's either less * recent @@ -1362,8 +1194,9 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, } #endif /* REJECT_IF_TBIT_ON */ - if (CHECK_FLAG(dd->options, OSPF_OPTION_O) - && !CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { + if (CHECK_FLAG(dd->options, OSPF_OPTION_O) && + (!CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) || + !OSPF_IF_PARAM(oi, opaque_capable))) { /* * This node is not configured to handle O-bit, for now. * Clear it to ignore unsupported capability proposed by @@ -1398,7 +1231,7 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, through to case ExStart below. */ if (nbr->state != NSM_ExStart) break; - /* fallthru */ + fallthrough; case NSM_ExStart: /* Initial DBD */ if ((IS_SET_DD_ALL(dd->flags) == OSPF_DD_FLAG_ALL) @@ -1448,7 +1281,8 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, /* This is where the real Options are saved */ nbr->options = dd->options; - if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { + if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) && + OSPF_IF_PARAM(oi, opaque_capable)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( "Neighbor[%pI4] is %sOpaque-capable.", @@ -1652,12 +1486,8 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh, /* Packet overflows MTU size, send immediately. */ if (length + ntohs(find->data->length) > ospf_packet_max(oi)) { - if (oi->type == OSPF_IFTYPE_NBMA) - ospf_ls_upd_send(nbr, ls_upd, - OSPF_SEND_PACKET_DIRECT, 0); - else - ospf_ls_upd_send(nbr, ls_upd, - OSPF_SEND_PACKET_INDIRECT, 0); + ospf_ls_upd_send(nbr, ls_upd, + OSPF_SEND_PACKET_DIRECT, 0); /* Only remove list contents. Keep ls_upd. */ list_delete_all_node(ls_upd); @@ -1674,12 +1504,7 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh, /* 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, - 0); - else - ospf_ls_upd_send(nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT, - 0); + ospf_ls_upd_send(nbr, ls_upd, OSPF_SEND_PACKET_DIRECT, 0); list_delete(&ls_upd); } else @@ -1807,7 +1632,7 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr, case OSPF_OPAQUE_LINK_LSA: lsa->oi = oi; /* Remember incoming interface for flooding control. */ - /* Fallthrough */ + fallthrough; default: lsa->area = oi->area; break; @@ -2031,7 +1856,7 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph, if (current == NULL) { if (IS_DEBUG_OSPF_EVENT) zlog_debug( - "LSA[%s]: Previously originated Opaque-LSA,not found in the LSDB.", + "LSA[%s]: Previously originated Opaque-LSA, not found in the LSDB.", dump_lsa_key(lsa)); SET_FLAG(lsa->flags, OSPF_LSA_SELF); @@ -2473,142 +2298,6 @@ static int ospf_check_network_mask(struct ospf_interface *oi, return 0; } -/* Return 1, if the packet is properly authenticated and checksummed, - 0 otherwise. In particular, check that AuType header field is valid and - matches the locally configured AuType, and that D.5 requirements are met. */ -static int ospf_check_auth(struct ospf_interface *oi, struct ospf_header *ospfh) -{ - struct crypt_key *ck; - uint16_t iface_auth_type; - uint16_t pkt_auth_type = ntohs(ospfh->auth_type); - - switch (pkt_auth_type) { - case OSPF_AUTH_NULL: /* RFC2328 D.5.1 */ - if (OSPF_AUTH_NULL != (iface_auth_type = ospf_auth_type(oi))) { - if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) - flog_warn( - EC_OSPF_PACKET, - "interface %s: auth-type mismatch, local %s, rcvd Null, Router-ID %pI4", - IF_NAME(oi), - lookup_msg(ospf_auth_type_str, - iface_auth_type, NULL), - &ospfh->router_id); - return 0; - } - if (!ospf_check_sum(ospfh)) { - if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) - flog_warn( - EC_OSPF_PACKET, - "interface %s: Null auth OK, but checksum error, Router-ID %pI4", - IF_NAME(oi), - &ospfh->router_id); - return 0; - } - return 1; - case OSPF_AUTH_SIMPLE: /* RFC2328 D.5.2 */ - if (OSPF_AUTH_SIMPLE - != (iface_auth_type = ospf_auth_type(oi))) { - if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) - flog_warn( - EC_OSPF_PACKET, - "interface %s: auth-type mismatch, local %s, rcvd Simple, Router-ID %pI4", - IF_NAME(oi), - lookup_msg(ospf_auth_type_str, - iface_auth_type, NULL), - &ospfh->router_id); - return 0; - } - if (memcmp(OSPF_IF_PARAM(oi, auth_simple), ospfh->u.auth_data, - OSPF_AUTH_SIMPLE_SIZE)) { - if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) - flog_warn( - EC_OSPF_PACKET, - "interface %s: Simple auth failed, Router-ID %pI4", - IF_NAME(oi), &ospfh->router_id); - return 0; - } - if (!ospf_check_sum(ospfh)) { - if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) - flog_warn( - EC_OSPF_PACKET, - "interface %s: Simple auth OK, checksum error, Router-ID %pI4", - IF_NAME(oi), - &ospfh->router_id); - return 0; - } - return 1; - case OSPF_AUTH_CRYPTOGRAPHIC: /* RFC2328 D.5.3 */ - if (OSPF_AUTH_CRYPTOGRAPHIC - != (iface_auth_type = ospf_auth_type(oi))) { - if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) - flog_warn( - EC_OSPF_PACKET, - "interface %s: auth-type mismatch, local %s, rcvd Cryptographic, Router-ID %pI4", - IF_NAME(oi), - lookup_msg(ospf_auth_type_str, - iface_auth_type, NULL), - &ospfh->router_id); - return 0; - } - if (ospfh->checksum) { - if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) - flog_warn( - EC_OSPF_PACKET, - "interface %s: OSPF header checksum is not 0, Router-ID %pI4", - IF_NAME(oi), &ospfh->router_id); - return 0; - } - /* only MD5 crypto method can pass ospf_packet_examin() */ - if (NULL == (ck = listgetdata( - listtail(OSPF_IF_PARAM(oi, auth_crypt)))) - || ospfh->u.crypt.key_id != ck->key_id || - /* Condition above uses the last key ID on the list, - which is - different from what ospf_crypt_key_lookup() does. A - bug? */ - !ospf_check_md5_digest(oi, ospfh)) { - if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) - flog_warn( - EC_OSPF_MD5, - "interface %s: MD5 auth failed, Router-ID %pI4", - IF_NAME(oi), &ospfh->router_id); - return 0; - } - return 1; - default: - if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) - flog_warn( - EC_OSPF_PACKET, - "interface %s: invalid packet auth-type (%02x), Router-ID %pI4", - IF_NAME(oi), pkt_auth_type, &ospfh->router_id); - return 0; - } -} - -static int ospf_check_sum(struct ospf_header *ospfh) -{ - uint32_t ret; - uint16_t sum; - - /* 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(uint16_t)); - - /* calculate checksum. */ - ret = in_cksum(ospfh, ntohs(ospfh->length)); - - if (ret != sum) { - zlog_info("%s: checksum mismatch, my %X, his %X", __func__, ret, - sum); - return 0; - } - - return 1; -} - /* Verify, that given link/TOS records are properly sized/aligned and match Router-LSA "# links" and "# TOS" fields as specified in RFC2328 A.4.2. */ static unsigned ospf_router_lsa_links_examin(struct router_lsa_link *link, @@ -2832,14 +2521,14 @@ static unsigned ospf_packet_examin(struct ospf_header *oh, if (ntohs(oh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC) bytesauth = 0; else { - if (oh->u.crypt.auth_data_len != OSPF_AUTH_MD5_SIZE) { + if (oh->u.crypt.auth_data_len > KEYCHAIN_MAX_HASH_SIZE) { if (IS_DEBUG_OSPF_PACKET(0, RECV)) zlog_debug( "%s: unsupported crypto auth length (%u B)", __func__, oh->u.crypt.auth_data_len); return MSG_NG; } - bytesauth = OSPF_AUTH_MD5_SIZE; + bytesauth = oh->u.crypt.auth_data_len; } if (bytesdeclared + bytesauth > bytesonwire) { if (IS_DEBUG_OSPF_PACKET(0, RECV)) @@ -2950,7 +2639,7 @@ static int ospf_verify_header(struct stream *ibuf, struct ospf_interface *oi, /* Check authentication. The function handles logging actions, where * required. */ - if (!ospf_check_auth(oi, ospfh)) + if (!ospf_auth_check(oi, iph, ospfh)) return -1; return 0; @@ -3258,44 +2947,6 @@ static void ospf_make_header(int type, struct ospf_interface *oi, stream_forward_endp(s, OSPF_HEADER_SIZE); } -/* Make Authentication Data. */ -static 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 = 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; - } - /* 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. */ static void ospf_fill_header(struct ospf_interface *oi, struct stream *s, uint16_t length) @@ -3314,7 +2965,9 @@ static void ospf_fill_header(struct ospf_interface *oi, struct stream *s, ospfh->checksum = 0; /* Add Authentication Data. */ - ospf_make_auth(oi, ospfh); + oi->keychain = NULL; + oi->key = NULL; + ospf_auth_make_data(oi, ospfh); } static int ospf_make_hello(struct ospf_interface *oi, struct stream *s) @@ -3435,7 +3088,8 @@ static int ospf_make_db_desc(struct ospf_interface *oi, /* Set Options. */ options = OPTIONS(oi); - if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)) + if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) && + OSPF_IF_PARAM(oi, opaque_capable)) SET_FLAG(options, OSPF_OPTION_O); if (OSPF_FR_CONFIG(oi->ospf, oi->area)) SET_FLAG(options, OSPF_OPTION_DC); @@ -3682,6 +3336,16 @@ static void ospf_hello_send_sub(struct ospf_interface *oi, in_addr_t addr) struct ospf_packet *op; uint16_t length = OSPF_HEADER_SIZE; + /* Check if config is still being processed */ + if (event_is_scheduled(t_ospf_cfg)) { + if (IS_DEBUG_OSPF_PACKET(0, SEND)) + zlog_debug( + "Suppressing hello to %pI4 on %s during config load", + &(addr), IF_NAME(oi)); + + return; + } + op = ospf_packet_new(oi->ifp->mtu); /* Prepare OSPF common header. */ @@ -3731,17 +3395,19 @@ static void ospf_poll_send(struct ospf_nbr_nbma *nbr_nbma) if (OSPF_IF_PASSIVE_STATUS(oi) == 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 (oi->type == OSPF_IFTYPE_NBMA) { + if (PRIORITY(oi) == 0) + return; - if (nbr_nbma->priority == 0 && oi->state != ISM_DR - && oi->state != ISM_Backup) + if (nbr_nbma->priority == 0 && oi->state != ISM_DR && + oi->state != ISM_Backup) + return; + + } else if (oi->type != OSPF_IFTYPE_POINTOMULTIPOINT || + !oi->p2mp_non_broadcast) return; ospf_hello_send_sub(oi, nbr_nbma->addr.s_addr); @@ -3787,7 +3453,7 @@ void ospf_hello_send(struct ospf_interface *oi) if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE) return; - if (oi->type == OSPF_IFTYPE_NBMA) { + if (OSPF_IF_NON_BROADCAST(oi)) { struct ospf_neighbor *nbr; struct route_node *rn; @@ -3803,31 +3469,44 @@ void ospf_hello_send(struct ospf_interface *oi) continue; /* - * 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). + * Always send to all neighbors on Point-to-Multipoint + * non-braodcast networks. */ - if (PRIORITY(oi) == 0 && - IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) && - IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4)) - continue; + if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) + ospf_hello_send_sub(oi, nbr->address.u.prefix4 + .s_addr); + else { + /* + * 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 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 */ - ospf_hello_send_sub(oi, nbr->address.u.prefix4.s_addr); + /* if oi->state == Waiting, send + * hello to all neighbors */ + ospf_hello_send_sub(oi, nbr->address.u.prefix4 + .s_addr); + } } } else { /* Decide destination address. */ @@ -4040,9 +3719,8 @@ static struct ospf_packet *ospf_ls_upd_packet_new(struct list *update, return ospf_packet_new(size - sizeof(struct ip)); } -static void ospf_ls_upd_queue_send(struct ospf_interface *oi, - struct list *update, struct in_addr addr, - int send_lsupd_now) +void ospf_ls_upd_queue_send(struct ospf_interface *oi, struct list *update, + struct in_addr addr, int send_lsupd_now) { struct ospf_packet *op; uint16_t length = OSPF_HEADER_SIZE; @@ -4185,11 +3863,10 @@ void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag, else p.prefix.s_addr = htonl(OSPF_ALLDROUTERS); - if (oi->type == OSPF_IFTYPE_NBMA) { + if (OSPF_IF_NON_BROADCAST(oi)) { if (flag == OSPF_SEND_PACKET_INDIRECT) - flog_warn( - EC_OSPF_PACKET, - "* LS-Update is directly sent on NBMA network."); + flog_warn(EC_OSPF_PACKET, + "* LS-Update is directly sent on non-broadcast network."); if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix)) flog_warn(EC_OSPF_PACKET, "* LS-Update is sent to myself."); @@ -4247,7 +3924,8 @@ static void ospf_ls_ack_send_list(struct ospf_interface *oi, struct list *ack, /* Decide destination address. */ if (oi->type == OSPF_IFTYPE_POINTOPOINT || - oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) + (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT && + !oi->p2mp_non_broadcast)) op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS); else op->dst.s_addr = dst.s_addr; @@ -4299,7 +3977,7 @@ void ospf_ls_ack_send_delayed(struct ospf_interface *oi) 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) { + if (OSPF_IF_NON_BROADCAST(oi)) { struct ospf_neighbor *nbr; struct route_node *rn; |
