diff --git a/share/man/man7/sysctl.7 b/share/man/man7/sysctl.7 index 53d959b4141..1a236d1e04e 100644 --- a/share/man/man7/sysctl.7 +++ b/share/man/man7/sysctl.7 @@ -1888,6 +1888,7 @@ The currently defined protocols and names are: .It ip6 maxfragpackets integer yes .It ip6 maxfrags integer yes .It ip6 neighborgcthresh integer yes +.It ip6 param_rt_msg integer yes .It ip6 redirect integer yes .It ip6 rr_prune integer yes .It ip6 use_deprecated integer yes @@ -2023,6 +2024,10 @@ The flag is provided basically for avoiding possible DoS attacks. Maximum number of entries in neighbor cache per interface. Set to negative to disable. The default value is 2048. +.It Li ip6.param_rt_msg +If set to 0, parameter changing routing message is suppressed. +If set to 1, parameter changing routing message is sent by RTM_NEWADDR. +Other values are undefined yet. .It Li ip6.redirect If set to 1, ICMPv6 redirects may be sent by the node. This option is ignored unless the node is routing IP packets, diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 9200150c568..92eee148dc3 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1065,6 +1065,9 @@ in6_update_ifa1(struct ifnet *ifp, struct in6_aliasreq *ifra, int dad_delay, was_tentative; struct in6_ifaddr *ia = iap ? *iap : NULL; char ip6buf[INET6_ADDRSTRLEN]; + bool addrmaskNotChanged = false; + bool send_rtm_newaddr = (ip6_param_rt_msg == 1); + int saved_flags; KASSERT((iap == NULL && psref == NULL) || (iap != NULL && psref != NULL)); @@ -1186,6 +1189,21 @@ in6_update_ifa1(struct ifnet *ifp, struct in6_aliasreq *ifra, return 0; /* there's nothing to do */ } +#define sin6eq(a, b) \ + ((a)->sin6_len == sizeof(struct sockaddr_in6) && \ + (b)->sin6_len == sizeof(struct sockaddr_in6) && \ + IN6_ARE_ADDR_EQUAL(&(a)->sin6_addr, &(b)->sin6_addr)) + + if (!send_rtm_newaddr) { + if (ia != NULL && + sin6eq(&ifra->ifra_addr, &ia->ia_addr) && + sin6eq(&ifra->ifra_prefixmask, &ia->ia_prefixmask)) { + addrmaskNotChanged = true; + saved_flags = ia->ia6_flags; /* check it later */ + } + } +#undef sin6eq + /* * If this is a new address, allocate a new ifaddr and link it * into chains. @@ -1291,6 +1309,17 @@ in6_update_ifa1(struct ifnet *ifp, struct in6_aliasreq *ifra, ia->ia6_lifetime.ia6t_preferred = time_uptime; } + if (!send_rtm_newaddr) { + /* + * We will not send RTM_NEWADDR if the only difference between + * ia and ifra is preferred/valid lifetimes, because it is not + * very useful for userland programs to be notified of that + * changes. + */ + if (addrmaskNotChanged && ia->ia6_flags == saved_flags) + return 0; + } + if (hostIsNew) { /* * We need a reference to ia before calling in6_ifinit. diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index da6dc661851..c215fe272a7 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -551,6 +551,7 @@ int ip6_mcast_pmtu = 0; /* enable pMTU discovery for multicast? */ int ip6_v6only = 1; int ip6_neighborgcthresh = 2048; /* Threshold # of NDP entries for GC */ int ip6_maxdynroutes = 4096; /* Max # of routes created via redirect */ +int ip6_param_rt_msg = 1; /* How to send parmeter changing rtm */ int ip6_keepfaith = 0; time_t ip6_log_time = 0; diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index e0db6596f89..33dfc54a637 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -1803,6 +1803,14 @@ sysctl_net_inet6_ip6_setup(struct sysctllog **clog) NULL, 1, &ip6_maxdynroutes, 0, CTL_NET, PF_INET6, IPPROTO_IPV6, CTL_CREATE, CTL_EOL); + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "param_rt_msg", + SYSCTL_DESCR("How to send parameter changing" + " routing message"), + NULL, 0, &ip6_param_rt_msg, 0, + CTL_NET, PF_INET6, IPPROTO_IPV6, + CTL_CREATE, CTL_EOL); } void diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h index 6508e67e8f0..a1b1449096d 100644 --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -257,6 +257,7 @@ extern int ip6_mcast_pmtu; /* enable pMTU discovery for multicast? */ extern int ip6_v6only; extern int ip6_neighborgcthresh; /* Threshold # of NDP entries for GC */ extern int ip6_maxdynroutes; /* Max # of routes created via redirect */ +extern int ip6_param_rt_msg; /* How to send parmeter changing rtm */ extern struct socket *ip6_mrouter; /* multicast routing daemon */