Re: [Openvpn-devel] [PATCH ovpn net 2/5] ovpn: reject duplicate peer VPN addresses

Ralf Lici <[email protected]>
Newsgroups net.sourceforge.lists.openvpn-devel
Message-ID <[email protected]>
On Fri, 14 Aug 2026 11:52:20 +0200, Sabrina Dubroca <[email protected]> wrote:
> 2026-07-29, 17:37:40 +0200, Ralf Lici wrote:
> > In MP mode, ovpn uses the peer VPN addresses as lookup keys for
> > selecting the peer that should receive an outgoing tunnel packet.
> > However, the netlink peer configuration path does not currently reject
> > duplicate VPN addresses.
> > 
> > If two peers are configured with the same VPN address, both can be
> > inserted in the VPN address hash table and lookups return whichever peer
> > is found first. This makes peer selection ambiguous and dependent on
> > hash insertion order.
> > 
> > Reject peer creation or update when the resulting VPN address is already
> > assigned to another peer. Ignore unspecified addresses because those are
> > not inserted in the VPN address hash tables.
>
> Maybe mention that it's a user-visible change of behavior, but it
> doesn't matter since that setup has never worked.
>
>

Will do.

> > @@ -522,22 +524,41 @@ int ovpn_nl_peer_set_doit(struct sk_buff *skb, struct genl_info *info)
> >  	rcu_read_unlock();
> >  
> >  	spin_lock_bh(&ovpn->lock);
> > -	ret = ovpn_nl_peer_modify(peer, info, attrs);
> > -	if (ret < 0) {
> > -		spin_unlock_bh(&ovpn->lock);
> > -		ovpn_peer_put(peer);
> > -		return ret;
> > +
> > +	vpn_addr4 = peer->vpn_addrs.ipv4;
> > +	vpn_addr6 = peer->vpn_addrs.ipv6;
> > +
> > +	if (attrs[OVPN_A_PEER_VPN_IPV4])
> > +		vpn_addr4.s_addr = nla_get_in_addr(attrs[OVPN_A_PEER_VPN_IPV4]);
> > +
> > +	if (attrs[OVPN_A_PEER_VPN_IPV6])
> > +		vpn_addr6 = nla_get_in6_addr(attrs[OVPN_A_PEER_VPN_IPV6]);
> > +
> > +	/* reject peer with conflicting VPN address */
> > +	if ((attrs[OVPN_A_PEER_VPN_IPV4] || attrs[OVPN_A_PEER_VPN_IPV6]) &&
> > +	    ovpn_peer_vpn_addr_conflict(ovpn, peer, &vpn_addr4, &vpn_addr6)) {
> > +		NL_SET_ERR_MSG_FMT_MOD(info->extack,
> > +				       "VPN IP is already assigned to another peer");
> > +		ret = -EADDRINUSE;
> > +		goto unlock;
> >  	}
>
> nit: maybe splitting conflict() into conflict{4,6}() would be a bit
> cleaner? passing addresses of 2 families feels kind of strange.
>
> 	if (attrs[OVPN_A_PEER_VPN_IPV4]) {
> 		struct in_addr vpn_addr4 = {
> 			.s_addr = nla_get_in_addr(attrs[OVPN_A_PEER_VPN_IPV4]),
> 		};
> 		if (ovpn_peer_vpn_addr_conflict4(ovpn, peer, &vpn_addr4))
> 			goto addr_conflict;
> 	}
>
>
> And then conflict* looks slightly nicer too:
>
> bool ovpn_peer_vpn_addr_conflict4(struct ovpn_priv *ovpn,
> 				  const struct ovpn_peer *peer,
> 				  const struct in_addr *addr)
> {
> 	struct ovpn_peer *tmp = NULL;
>
> 	lockdep_assert_held(&ovpn->lock);
>
> 	/* we don't hash INADDR_ANY, no conflict in that case */
> 	if (addr->s_addr != htonl(INADDR_ANY))
> 		tmp = ovpn_peer_get_by_vpn_addr4(ovpn, addr->s_addr);
>
> 	return tmp && tmp != peer;
> }
>

Yes, it's a nice refactoring. I'll apply it to v2.

-- 
Ralf Lici
Mandelbit Srl


_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.