@@ -1868,6 +1868,7 @@ static inline void net_if_addr_init(struct net_if_addr *ifaddr,
18681868 uint32_t vlifetime )
18691869{
18701870 ifaddr -> is_used = true;
1871+ ifaddr -> is_added = true;
18711872 ifaddr -> is_temporary = false;
18721873 ifaddr -> address .family = AF_INET6 ;
18731874 ifaddr -> addr_type = addr_type ;
@@ -1906,6 +1907,17 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
19061907
19071908 ifaddr = ipv6_addr_find (iface , addr );
19081909 if (ifaddr ) {
1910+ /* Address already exists, just return it but update ref count
1911+ * if it was not updated. This could happen if the address was
1912+ * added and then removed but for example an active connection
1913+ * was still using it. In this case we must update the ref count
1914+ * so that the address is not removed if the connection is closed.
1915+ */
1916+ if (!ifaddr -> is_added ) {
1917+ atomic_inc (& ifaddr -> atomic_ref );
1918+ ifaddr -> is_added = true;
1919+ }
1920+
19091921 goto out ;
19101922 }
19111923
@@ -1963,6 +1975,7 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
19631975
19641976bool net_if_ipv6_addr_rm (struct net_if * iface , const struct in6_addr * addr )
19651977{
1978+ struct net_if_addr * ifaddr ;
19661979 struct net_if_ipv6 * ipv6 ;
19671980 bool result = true;
19681981 int ret ;
@@ -1977,11 +1990,12 @@ bool net_if_ipv6_addr_rm(struct net_if *iface, const struct in6_addr *addr)
19771990 goto out ;
19781991 }
19791992
1980- ret = net_if_addr_unref (iface , AF_INET6 , addr );
1993+ ret = net_if_addr_unref (iface , AF_INET6 , addr , & ifaddr );
19811994 if (ret > 0 ) {
19821995 NET_DBG ("Address %s still in use (ref %d)" ,
19831996 net_sprint_ipv6_addr (addr ), ret );
19841997 result = false;
1998+ ifaddr -> is_added = false;
19851999 goto out ;
19862000 } else if (ret < 0 ) {
19872001 NET_DBG ("Address %s not found (%d)" ,
@@ -4265,6 +4279,17 @@ struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface,
42654279 ifaddr = ipv4_addr_find (iface , addr );
42664280 if (ifaddr ) {
42674281 /* TODO: should set addr_type/vlifetime */
4282+ /* Address already exists, just return it but update ref count
4283+ * if it was not updated. This could happen if the address was
4284+ * added and then removed but for example an active connection
4285+ * was still using it. In this case we must update the ref count
4286+ * so that the address is not removed if the connection is closed.
4287+ */
4288+ if (!ifaddr -> is_added ) {
4289+ atomic_inc (& ifaddr -> atomic_ref );
4290+ ifaddr -> is_added = true;
4291+ }
4292+
42684293 goto out ;
42694294 }
42704295
@@ -4287,6 +4312,7 @@ struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface,
42874312
42884313 if (ifaddr ) {
42894314 ifaddr -> is_used = true;
4315+ ifaddr -> is_added = true;
42904316 ifaddr -> address .family = AF_INET ;
42914317 ifaddr -> address .in_addr .s4_addr32 [0 ] =
42924318 addr -> s4_addr32 [0 ];
@@ -4331,6 +4357,7 @@ struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface,
43314357
43324358bool net_if_ipv4_addr_rm (struct net_if * iface , const struct in_addr * addr )
43334359{
4360+ struct net_if_addr * ifaddr ;
43344361 struct net_if_ipv4 * ipv4 ;
43354362 bool result = true;
43364363 int ret ;
@@ -4345,11 +4372,12 @@ bool net_if_ipv4_addr_rm(struct net_if *iface, const struct in_addr *addr)
43454372 goto out ;
43464373 }
43474374
4348- ret = net_if_addr_unref (iface , AF_INET , addr );
4375+ ret = net_if_addr_unref (iface , AF_INET , addr , & ifaddr );
43494376 if (ret > 0 ) {
43504377 NET_DBG ("Address %s still in use (ref %d)" ,
43514378 net_sprint_ipv4_addr (addr ), ret );
43524379 result = false;
4380+ ifaddr -> is_added = false;
43534381 goto out ;
43544382 } else if (ret < 0 ) {
43554383 NET_DBG ("Address %s not found (%d)" ,
@@ -4973,11 +5001,13 @@ struct net_if_addr *net_if_addr_ref(struct net_if *iface,
49735001int net_if_addr_unref_debug (struct net_if * iface ,
49745002 sa_family_t family ,
49755003 const void * addr ,
5004+ struct net_if_addr * * ret_ifaddr ,
49765005 const char * caller , int line )
49775006#else
49785007int net_if_addr_unref (struct net_if * iface ,
49795008 sa_family_t family ,
4980- const void * addr )
5009+ const void * addr ,
5010+ struct net_if_addr * * ret_ifaddr )
49815011#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
49825012{
49835013 struct net_if_addr * ifaddr ;
@@ -5031,6 +5061,10 @@ int net_if_addr_unref(struct net_if *iface,
50315061#endif
50325062
50335063 if (ref > 1 ) {
5064+ if (ret_ifaddr ) {
5065+ * ret_ifaddr = ifaddr ;
5066+ }
5067+
50345068 return ref - 1 ;
50355069 }
50365070
0 commit comments