@@ -1907,6 +1907,7 @@ static inline void net_if_addr_init(struct net_if_addr *ifaddr,
19071907 uint32_t vlifetime )
19081908{
19091909 ifaddr -> is_used = true;
1910+ ifaddr -> is_added = true;
19101911 ifaddr -> is_temporary = false;
19111912 ifaddr -> address .family = AF_INET6 ;
19121913 ifaddr -> addr_type = addr_type ;
@@ -1945,6 +1946,17 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
19451946
19461947 ifaddr = ipv6_addr_find (iface , addr );
19471948 if (ifaddr ) {
1949+ /* Address already exists, just return it but update ref count
1950+ * if it was not updated. This could happen if the address was
1951+ * added and then removed but for example an active connection
1952+ * was still using it. In this case we must update the ref count
1953+ * so that the address is not removed if the connection is closed.
1954+ */
1955+ if (!ifaddr -> is_added ) {
1956+ atomic_inc (& ifaddr -> atomic_ref );
1957+ ifaddr -> is_added = true;
1958+ }
1959+
19481960 goto out ;
19491961 }
19501962
@@ -2002,6 +2014,7 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
20022014
20032015bool net_if_ipv6_addr_rm (struct net_if * iface , const struct in6_addr * addr )
20042016{
2017+ struct net_if_addr * ifaddr ;
20052018 struct net_if_ipv6 * ipv6 ;
20062019 bool result = true;
20072020 int ret ;
@@ -2016,11 +2029,12 @@ bool net_if_ipv6_addr_rm(struct net_if *iface, const struct in6_addr *addr)
20162029 goto out ;
20172030 }
20182031
2019- ret = net_if_addr_unref (iface , AF_INET6 , addr );
2032+ ret = net_if_addr_unref (iface , AF_INET6 , addr , & ifaddr );
20202033 if (ret > 0 ) {
20212034 NET_DBG ("Address %s still in use (ref %d)" ,
20222035 net_sprint_ipv6_addr (addr ), ret );
20232036 result = false;
2037+ ifaddr -> is_added = false;
20242038 goto out ;
20252039 } else if (ret < 0 ) {
20262040 NET_DBG ("Address %s not found (%d)" ,
@@ -4229,6 +4243,17 @@ struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface,
42294243 ifaddr = ipv4_addr_find (iface , addr );
42304244 if (ifaddr ) {
42314245 /* TODO: should set addr_type/vlifetime */
4246+ /* Address already exists, just return it but update ref count
4247+ * if it was not updated. This could happen if the address was
4248+ * added and then removed but for example an active connection
4249+ * was still using it. In this case we must update the ref count
4250+ * so that the address is not removed if the connection is closed.
4251+ */
4252+ if (!ifaddr -> is_added ) {
4253+ atomic_inc (& ifaddr -> atomic_ref );
4254+ ifaddr -> is_added = true;
4255+ }
4256+
42324257 goto out ;
42334258 }
42344259
@@ -4251,6 +4276,7 @@ struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface,
42514276
42524277 if (ifaddr ) {
42534278 ifaddr -> is_used = true;
4279+ ifaddr -> is_added = true;
42544280 ifaddr -> address .family = AF_INET ;
42554281 ifaddr -> address .in_addr .s4_addr32 [0 ] =
42564282 addr -> s4_addr32 [0 ];
@@ -4295,6 +4321,7 @@ struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface,
42954321
42964322bool net_if_ipv4_addr_rm (struct net_if * iface , const struct in_addr * addr )
42974323{
4324+ struct net_if_addr * ifaddr ;
42984325 struct net_if_ipv4 * ipv4 ;
42994326 bool result = true;
43004327 int ret ;
@@ -4309,11 +4336,12 @@ bool net_if_ipv4_addr_rm(struct net_if *iface, const struct in_addr *addr)
43094336 goto out ;
43104337 }
43114338
4312- ret = net_if_addr_unref (iface , AF_INET , addr );
4339+ ret = net_if_addr_unref (iface , AF_INET , addr , & ifaddr );
43134340 if (ret > 0 ) {
43144341 NET_DBG ("Address %s still in use (ref %d)" ,
43154342 net_sprint_ipv4_addr (addr ), ret );
43164343 result = false;
4344+ ifaddr -> is_added = false;
43174345 goto out ;
43184346 } else if (ret < 0 ) {
43194347 NET_DBG ("Address %s not found (%d)" ,
@@ -5048,11 +5076,13 @@ struct net_if_addr *net_if_addr_ref(struct net_if *iface,
50485076int net_if_addr_unref_debug (struct net_if * iface ,
50495077 sa_family_t family ,
50505078 const void * addr ,
5079+ struct net_if_addr * * ret_ifaddr ,
50515080 const char * caller , int line )
50525081#else
50535082int net_if_addr_unref (struct net_if * iface ,
50545083 sa_family_t family ,
5055- const void * addr )
5084+ const void * addr ,
5085+ struct net_if_addr * * ret_ifaddr )
50565086#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
50575087{
50585088 struct net_if_addr * ifaddr ;
@@ -5106,6 +5136,10 @@ int net_if_addr_unref(struct net_if *iface,
51065136#endif
51075137
51085138 if (ref > 1 ) {
5139+ if (ret_ifaddr ) {
5140+ * ret_ifaddr = ifaddr ;
5141+ }
5142+
51095143 return ref - 1 ;
51105144 }
51115145
0 commit comments