diff --git a/zebra/interface.c b/zebra/interface.c index e4e80ec4e9..2e13cfd55c 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -158,6 +158,16 @@ static int if_zebra_new_hook(struct interface *ifp) rtadv->AdvReachableTime = 0; rtadv->AdvRetransTimer = 0; rtadv->AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT; + memset(&rtadv->lastadvcurhoplimit, 0, + sizeof(rtadv->lastadvcurhoplimit)); + memset(&rtadv->lastadvmanagedflag, 0, + sizeof(rtadv->lastadvmanagedflag)); + memset(&rtadv->lastadvotherconfigflag, 0, + sizeof(rtadv->lastadvotherconfigflag)); + memset(&rtadv->lastadvreachabletime, 0, + sizeof(rtadv->lastadvreachabletime)); + memset(&rtadv->lastadvretranstimer, 0, + sizeof(rtadv->lastadvretranstimer)); rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */ rtadv->HomeAgentPreference = 0; diff --git a/zebra/interface.h b/zebra/interface.h index 771398b547..413a67469a 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -81,6 +81,7 @@ struct rtadvconf { Default: false */ int AdvManagedFlag; + struct timeval lastadvmanagedflag; /* The true/false value to be placed in the "Other stateful @@ -89,6 +90,7 @@ struct rtadvconf { Default: false */ int AdvOtherConfigFlag; + struct timeval lastadvotherconfigflag; /* The value to be placed in MTU options sent by the router. A value of zero indicates that no MTU options are sent. @@ -105,6 +107,7 @@ struct rtadvconf { Default: 0 */ uint32_t AdvReachableTime; #define RTADV_MAX_REACHABLE_TIME 3600000 + struct timeval lastadvreachabletime; /* The value to be placed in the Retrans Timer field in the Router Advertisement messages sent by the router. The value zero means @@ -112,6 +115,7 @@ struct rtadvconf { Default: 0 */ int AdvRetransTimer; + struct timeval lastadvretranstimer; /* The default value to be placed in the Cur Hop Limit field in the Router Advertisement messages sent by the router. The value @@ -121,6 +125,8 @@ struct rtadvconf { Default: The value specified in the "Assigned Numbers" RFC [ASSIGNED] that was in effect at the time of implementation. */ int AdvCurHopLimit; + struct timeval lastadvcurhoplimit; + #define RTADV_DEFAULT_HOPLIMIT 64 /* 64 hops */ /* The value to be placed in the Router Lifetime field of Router diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 350b97cc5d..d64d563771 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -632,45 +632,66 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len, radvert = (struct nd_router_advert *)msg; - if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) - && (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit)) { +#define SIXHOUR2USEC (int64_t)6 * 60 * 60 * 1000000 + + if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) && + (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit) && + (monotime_since(&zif->rtadv.lastadvcurhoplimit, NULL) > + SIXHOUR2USEC || + zif->rtadv.lastadvcurhoplimit.tv_sec == 0)) { flog_warn( EC_ZEBRA_RA_PARAM_MISMATCH, "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s", ifp->name, ifp->ifindex, addr_str); + monotime(&zif->rtadv.lastadvcurhoplimit); } - if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) - && !zif->rtadv.AdvManagedFlag) { + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) && + !zif->rtadv.AdvManagedFlag && + (monotime_since(&zif->rtadv.lastadvmanagedflag, NULL) > + SIXHOUR2USEC || + zif->rtadv.lastadvmanagedflag.tv_sec == 0)) { flog_warn( EC_ZEBRA_RA_PARAM_MISMATCH, "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s", ifp->name, ifp->ifindex, addr_str); + monotime(&zif->rtadv.lastadvmanagedflag); } - if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) - && !zif->rtadv.AdvOtherConfigFlag) { + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) && + !zif->rtadv.AdvOtherConfigFlag && + (monotime_since(&zif->rtadv.lastadvotherconfigflag, NULL) > + SIXHOUR2USEC || + zif->rtadv.lastadvotherconfigflag.tv_sec == 0)) { flog_warn( EC_ZEBRA_RA_PARAM_MISMATCH, "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s", ifp->name, ifp->ifindex, addr_str); + monotime(&zif->rtadv.lastadvotherconfigflag); } - if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) - && (ntohl(radvert->nd_ra_reachable) - != zif->rtadv.AdvReachableTime)) { + if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) && + (ntohl(radvert->nd_ra_reachable) != zif->rtadv.AdvReachableTime) && + (monotime_since(&zif->rtadv.lastadvreachabletime, NULL) > + SIXHOUR2USEC || + zif->rtadv.lastadvreachabletime.tv_sec == 0)) { flog_warn( EC_ZEBRA_RA_PARAM_MISMATCH, "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s", ifp->name, ifp->ifindex, addr_str); + monotime(&zif->rtadv.lastadvreachabletime); } - if ((ntohl(radvert->nd_ra_retransmit) - != (unsigned int)zif->rtadv.AdvRetransTimer)) { + if ((ntohl(radvert->nd_ra_retransmit) != + (unsigned int)zif->rtadv.AdvRetransTimer) && + (monotime_since(&zif->rtadv.lastadvretranstimer, NULL) > + SIXHOUR2USEC || + zif->rtadv.lastadvretranstimer.tv_sec == 0)) { flog_warn( EC_ZEBRA_RA_PARAM_MISMATCH, "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s", ifp->name, ifp->ifindex, addr_str); + monotime(&zif->rtadv.lastadvretranstimer); } /* Create entry for neighbor if not known. */