diff options
Diffstat (limited to 'zebra/rtadv.c')
-rw-r--r-- | zebra/rtadv.c | 83 |
1 files changed, 75 insertions, 8 deletions
diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 9450f9a9..8660f733 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -402,14 +402,83 @@ rtadv_process_solicit (struct interface *ifp) } static void -rtadv_process_advert (void) +rtadv_process_advert (u_char *msg, unsigned int len, struct interface *ifp, + struct sockaddr_in6 *addr) { - zlog_info ("Router advertisement received"); + struct nd_router_advert *radvert; + char addr_str[INET6_ADDRSTRLEN]; + struct zebra_if *zif; + + zif = ifp->info; + + inet_ntop (AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN); + + zlog_info ("Router advertisement received on %s from : %s", ifp->name, addr_str); + + if (len < sizeof(struct nd_router_advert)) { + zlog_warn("received icmpv6 RA packet with invalid length (%d) from %s", + len, addr_str); + return; + } + if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { + zlog_warn("received icmpv6 RA packet with non-linklocal source address from %s", + addr_str); + return; + } + + radvert = (struct nd_router_advert *) msg; + + if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) && + (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit)) + { + zlog_warn("our AdvCurHopLimit on %s doesn't agree with %s", + ifp->name, addr_str); + } + + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) && + !zif->rtadv.AdvManagedFlag) + { + zlog_warn("our AdvManagedFlag on %s doesn't agree with %s", + ifp->name, addr_str); + } + + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) && + !zif->rtadv.AdvOtherConfigFlag) + { + zlog_warn("our AdvOtherConfigFlag on %s doesn't agree with %s", + ifp->name, addr_str); + } + + if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) && + (ntohl(radvert->nd_ra_reachable) != zif->rtadv.AdvReachableTime)) + { + zlog_warn("our AdvReachableTime on %s doesn't agree with %s", + ifp->name, addr_str); + } + + if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) && + (ntohl(radvert->nd_ra_retransmit) != (unsigned int)zif->rtadv.AdvRetransTimer)) + { + zlog_warn("our AdvRetransTimer on %s doesn't agree with %s", + ifp->name, addr_str); + } + + /* Currently supporting only P2P links, so any new RA source address is + considered as the replacement of the previously learnt Link-Local address. + As per the RFC, lifetime zero is to be considered a delete */ + if (ntohs(radvert->nd_ra_router_lifetime)) + nbr_connected_replacement_add_ipv6(ifp, &addr->sin6_addr, 128); + else + nbr_connected_delete_ipv6(ifp, &addr->sin6_addr, 128); + + return; } + static void -rtadv_process_packet (u_char *buf, unsigned int len, ifindex_t ifindex, - int hoplimit, vrf_id_t vrf_id) +rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, + int hoplimit, vrf_id_t vrf_id, + struct sockaddr_in6 *from) { struct icmp6_hdr *icmph; struct interface *ifp; @@ -460,7 +529,7 @@ rtadv_process_packet (u_char *buf, unsigned int len, ifindex_t ifindex, if (icmph->icmp6_type == ND_ROUTER_SOLICIT) rtadv_process_solicit (ifp); else if (icmph->icmp6_type == ND_ROUTER_ADVERT) - rtadv_process_advert (); + rtadv_process_advert (buf, len, ifp, from); return; } @@ -490,7 +559,7 @@ rtadv_read (struct thread *thread) return len; } - rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, zvrf->vrf_id); + rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, zvrf->vrf_id, &from); return 0; } @@ -1539,8 +1608,6 @@ rtadv_config_write (struct vty *vty, struct interface *ifp) { if (zif->rtadv.AdvSendAdvertisements) vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE); - else - vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE); } |