Commit f8f1f469 authored by Jaap Keuter's avatar Jaap Keuter Committed by David S. Miller

[IPV4]: Calculate default broadcast even when using SIOCSIGNETMASK.

While getting hands-on with netkit (www.netkit.org), a networking
simulation environment based on UML, it struck me that ifconfig wasn't
capable of calculating the proper broadcast address for a subnetted
interface. Some browsing through newsgroups and on the Debian package
site (nettools), showed that this leads to misconfigured interfaces and
a couple of bugreports on ifconfig.

Digging a bit deeper revealed that it actually is an issue with
SIOIFNETMASK. Once you bring up an interface with SIOIFADDR, a classfull
netmask and broadcast address is set (if applicable for the type of
interface), in order to get a properly configured interface. But if you
subnet the network using SIOIFNETMASK no proper broadcast address is
set. So you always have to calculate it yourself, obviously leading to
configuration errors.

This patch takes care of this. First of all it doesn't change
existing functionality, eg. a command like 'ifconfig eth0 192.168.1.1
netmask 255.255.255.240 broadcast 192.168.1.0' still works. But if you
omit the broadcast address, a proper 'all ones' broadcast address for the
subnet is set. 'ifconfig eth0 192.168.1.1 netmask 255.255.255.240' gives
you 'eth0 inet addr:192.168.1.1 Bcast:192.168.1.15 Mask:255.255.255.240'
and this should solve some real life problems.
Signed-off-by: default avatarJaap Keuter <jaap.keuter@xs4all.nl>
Signed-off-by: default avatarDavid S. Miller <davem@redhat.com>
parent a98c957a
......@@ -699,6 +699,20 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
inet_del_ifa(in_dev, ifap, 0);
ifa->ifa_mask = sin->sin_addr.s_addr;
ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
/* See if current broadcast address matches
* with current netmask, then recalculate
* the broadcast address. Otherwise it's a
* funny address, so don't touch it since
* the user seems to know what (s)he's doing...
*/
if ((dev->flags & IFF_BROADCAST) &&
(ifa->ifa_prefixlen < 31) &&
(ifa->ifa_broadcast ==
(ifa->ifa_local|~ifa->ifa_mask))) {
ifa->ifa_broadcast = (ifa->ifa_local |
~sin->sin_addr.s_addr);
}
inet_insert_ifa(ifa);
}
break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment