diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 17a6e46..f128106 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -866,6 +866,18 @@ conf/all/forwarding - BOOLEAN proxy_ndp - BOOLEAN Do proxy ndp. +nlnotify_on_addr_add - BOOLEAN + By default, netlink messages are not sent when an IPv6 address + is added if it is in tentative state. This makes it harder + for some user-space applications to function properly. To + ensure that a netlink message is always sent when an IPv6 addr + is added, regardless of the state of the address, set this value + to 1. For the old (default) behaviour, set this value to 0. + + If only certain interfaces should have this behaviour, leave the + 'all' config set to 0 and set the individual interface's value + to 1. + conf/interface/*: Change special settings per interface. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 134c8e5..3d0136a 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -157,6 +157,11 @@ struct ipv6_devconf { #endif __s32 proxy_ndp; __s32 accept_source_route; + __s32 nlnotify_on_addr_add; /* Always notify netlink on addr add, even if it is tentative. + * As currently implemented, this will often cause multiple netlink + * RTM_NEWADDR messages, as a new notification will be sent when + * the address becomes un-tentative. + */ #ifdef CONFIG_IPV6_OPTIMISTIC_DAD __s32 optimistic_dad; #endif @@ -190,6 +195,7 @@ enum { DEVCONF_PROXY_NDP, DEVCONF_OPTIMISTIC_DAD, DEVCONF_ACCEPT_SOURCE_ROUTE, + DEVCONF_NLNOTIFY_ON_ADDR_ADD, DEVCONF_MAX }; diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 5f1d1c8..8dbe468 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -579,6 +579,7 @@ enum { NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22, NET_IPV6_PROXY_NDP=23, NET_IPV6_ACCEPT_SOURCE_ROUTE=25, + NET_IPV6_NLNOTIFY_ON_ADDR_ADD=26, __NET_IPV6_MAX }; diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c index cb5fd21..37c8fab 100644 --- a/kernel/sysctl_check.c +++ b/kernel/sysctl_check.c @@ -495,6 +495,7 @@ static const struct trans_ctl_table trans_net_ipv6_conf_var_table[] = { { NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN, "accept_ra_rt_info_max_plen" }, { NET_IPV6_PROXY_NDP, "proxy_ndp" }, { NET_IPV6_ACCEPT_SOURCE_ROUTE, "accept_source_route" }, + { NET_IPV6_NLNOTIFY_ON_ADDR_ADD, "nlnotify_on_addr_add" }, {} }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e08955b..594496b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -185,6 +185,7 @@ struct ipv6_devconf ipv6_devconf __read_mostly = { #endif .proxy_ndp = 0, .accept_source_route = 0, /* we do not accept RH0 by default. */ + .nlnotify_on_addr_add = 0, /* by default, only notify when it becomes un-tentative */ }; static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { @@ -217,6 +218,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { #endif .proxy_ndp = 0, .accept_source_route = 0, /* we do not accept RH0 by default. */ + .nlnotify_on_addr_add = 0, /* by default, only notify when it becomes un-tentative */ }; /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ @@ -641,6 +643,13 @@ out2: ifa = ERR_PTR(err); } + /* Allow netlink notification of all addresses, regardless of flags. */ + if (ipv6_devconf.nlnotify_on_addr_add || idev->cnf.nlnotify_on_addr_add) { + if (!IS_ERR(ifa)) { + ipv6_ifa_notify(RTM_NEWADDR, ifa); + } + } + return ifa; out: write_unlock(&addrconf_hash_lock); @@ -3556,6 +3565,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, #ifdef CONFIG_IPV6_OPTIMISTIC_DAD array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad; #endif + array[DEVCONF_NLNOTIFY_ON_ADDR_ADD] = cnf->nlnotify_on_addr_add; } static inline size_t inet6_if_nlmsg_size(void) @@ -4094,6 +4104,15 @@ static struct addrconf_sysctl_table .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = NET_IPV6_NLNOTIFY_ON_ADDR_ADD, + .procname = "nlnotify_on_addr_add", + .data = &ipv6_devconf.nlnotify_on_addr_add, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + + }, #ifdef CONFIG_IPV6_OPTIMISTIC_DAD { .ctl_name = CTL_UNNUMBERED,