diff options
Diffstat (limited to 'net/ipv4/raw.c')
| -rw-r--r-- | net/ipv4/raw.c | 18 | 
1 files changed, 16 insertions, 2 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 5e570aa9e43b..9b367fc48d7d 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -617,8 +617,21 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)  			ipc.oif = inet->mc_index;  		if (!saddr)  			saddr = inet->mc_addr; -	} else if (!ipc.oif) +	} else if (!ipc.oif) {  		ipc.oif = inet->uc_index; +	} else if (ipv4_is_lbcast(daddr) && inet->uc_index) { +		/* oif is set, packet is to local broadcast and +		 * and uc_index is set. oif is most likely set +		 * by sk_bound_dev_if. If uc_index != oif check if the +		 * oif is an L3 master and uc_index is an L3 slave. +		 * If so, we want to allow the send using the uc_index. +		 */ +		if (ipc.oif != inet->uc_index && +		    ipc.oif == l3mdev_master_ifindex_by_index(sock_net(sk), +							      inet->uc_index)) { +			ipc.oif = inet->uc_index; +		} +	}  	flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,  			   RT_SCOPE_UNIVERSE, @@ -977,6 +990,8 @@ struct proto raw_prot = {  	.hash		   = raw_hash_sk,  	.unhash		   = raw_unhash_sk,  	.obj_size	   = sizeof(struct raw_sock), +	.useroffset	   = offsetof(struct raw_sock, filter), +	.usersize	   = sizeof_field(struct raw_sock, filter),  	.h.raw_hash	   = &raw_v4_hashinfo,  #ifdef CONFIG_COMPAT  	.compat_setsockopt = compat_raw_setsockopt, @@ -1119,7 +1134,6 @@ static int raw_v4_seq_open(struct inode *inode, struct file *file)  }  static const struct file_operations raw_seq_fops = { -	.owner	 = THIS_MODULE,  	.open	 = raw_v4_seq_open,  	.read	 = seq_read,  	.llseek	 = seq_lseek,  |