Skip to content

Commit 9515a2e

Browse files
dsaherndavem330
authored andcommitted
net/ipv4: Allow send to local broadcast from a socket bound to a VRF
Message sends to the local broadcast address (255.255.255.255) require uc_index or sk_bound_dev_if to be set to an egress device. However, responses or only received if the socket is bound to the device. This is overly constraining for processes running in an L3 domain. This patch allows a socket bound to the VRF device to send to the local broadcast address by using IP_UNICAST_IF to set the egress interface with packet receipt handled by the VRF binding. Similar to IP_MULTICAST_IF, relax the constraint on setting IP_UNICAST_IF if a socket is bound to an L3 master device. In this case allow uc_index to be set to an enslaved if sk_bound_dev_if is an L3 master device and is the master device for the ifindex. In udp and raw sendmsg, allow uc_index to override the oif if uc_index master device is oif (ie., the oif is an L3 master and the index is an L3 slave). Signed-off-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f8a23d8 commit 9515a2e

File tree

3 files changed

+33
-3
lines changed

3 files changed

+33
-3
lines changed

net/ipv4/ip_sockglue.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
808808
{
809809
struct net_device *dev = NULL;
810810
int ifindex;
811+
int midx;
811812

812813
if (optlen != sizeof(int))
813814
goto e_inval;
@@ -823,10 +824,13 @@ static int do_ip_setsockopt(struct sock *sk, int level,
823824
err = -EADDRNOTAVAIL;
824825
if (!dev)
825826
break;
827+
828+
midx = l3mdev_master_ifindex(dev);
826829
dev_put(dev);
827830

828831
err = -EINVAL;
829-
if (sk->sk_bound_dev_if)
832+
if (sk->sk_bound_dev_if &&
833+
(!midx || midx != sk->sk_bound_dev_if))
830834
break;
831835

832836
inet->uc_index = ifindex;

net/ipv4/raw.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,8 +617,21 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
617617
ipc.oif = inet->mc_index;
618618
if (!saddr)
619619
saddr = inet->mc_addr;
620-
} else if (!ipc.oif)
620+
} else if (!ipc.oif) {
621621
ipc.oif = inet->uc_index;
622+
} else if (ipv4_is_lbcast(daddr) && inet->uc_index) {
623+
/* oif is set, packet is to local broadcast and
624+
* and uc_index is set. oif is most likely set
625+
* by sk_bound_dev_if. If uc_index != oif check if the
626+
* oif is an L3 master and uc_index is an L3 slave.
627+
* If so, we want to allow the send using the uc_index.
628+
*/
629+
if (ipc.oif != inet->uc_index &&
630+
ipc.oif == l3mdev_master_ifindex_by_index(sock_net(sk),
631+
inet->uc_index)) {
632+
ipc.oif = inet->uc_index;
633+
}
634+
}
622635

623636
flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
624637
RT_SCOPE_UNIVERSE,

net/ipv4/udp.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,8 +977,21 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
977977
if (!saddr)
978978
saddr = inet->mc_addr;
979979
connected = 0;
980-
} else if (!ipc.oif)
980+
} else if (!ipc.oif) {
981981
ipc.oif = inet->uc_index;
982+
} else if (ipv4_is_lbcast(daddr) && inet->uc_index) {
983+
/* oif is set, packet is to local broadcast and
984+
* and uc_index is set. oif is most likely set
985+
* by sk_bound_dev_if. If uc_index != oif check if the
986+
* oif is an L3 master and uc_index is an L3 slave.
987+
* If so, we want to allow the send using the uc_index.
988+
*/
989+
if (ipc.oif != inet->uc_index &&
990+
ipc.oif == l3mdev_master_ifindex_by_index(sock_net(sk),
991+
inet->uc_index)) {
992+
ipc.oif = inet->uc_index;
993+
}
994+
}
982995

983996
if (connected)
984997
rt = (struct rtable *)sk_dst_check(sk, 0);

0 commit comments

Comments
 (0)