Subject: netmasks and IP
To: None <port-vax@netbsd.org>
From: Chuck McManis <cmcmanis@freegate.com>
List: port-vax
Date: 03/17/1999 17:01:32
Sigh. 

Having pissed on probably 80% of the code in rpc.bootparamd when I worked
at Sun we had this discussion a few times about what is and what isn't a
broadcast address.

This is the deal. 
	IP addresses have two parts
		Network Number
		Host Number
	IP addresses are 32 bits long
	The device used to separate the network number
	from the host number is called the net mask.

In the beginning the netmask was computer "automatically" using the first 8
bits of the  number like so:
000 - 127	"Class A - Netmask is 8 bits long, 0xff000000"
128 - 191	"Class B - Netmask is 16 bits long, 0xffff0000"
192 - 223	"Class C - Netmask is 24 bits long, 0xffffff00"
224 - 239	"Class D - Netmask netmask is 32 bits long"
240 - 247	"Class E - Reserved"
248 - 252	"Class F - Reserved"
253 - 254	"Class G - Reserved"
255		"Broadcast"

Now if you look at these 8 bit quantities in binary they are 
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff

So, without information to the contrary, you can compute the netmask
"algorithmically" by looking at the first byte of the address.

How Netmasks Are Used

Netmasks are used to separate the host and network numbers as follows:
	host = IP ADDRESS & ~NETMASK;
	network = IP ADDRESS & NETMASK;

There are two "special" hosts, these are called the broadcast addresses and
they were originally implemented, IIRC, as :
	host number 0 (old broadcast address)
	host number -1 (all ones, new broadcast address)
There was some dispute about this in the early 80's and at Sun we did both
some networks expected the host number to be all ones, others expected it
to be all 0. Now most everyone accepts both. (But the RFC states that all
ones is correct)

The IP layer in every TCP/IP implementation since 4.1BSD uses the IP
address of an interface and the netmask to determine whether or not it
should forward packets "up" the stack. Generally the code is something like:
	if (packet->ip_addr == my_addr) {
		process it
	} else if (packet->ip_addr == brdcst_addr) {
		process it
	} else
		dump it.

The exact algorithm is in src/sys/netinet/ip_input.c. 

The broadcast address is computed as 
	HOST IP & NETMASK | ~NETMASK

What Does it Mean For BOOTPARAMS?

What it means is this, in the absence of any other data, the default
netmask for an address 10.x.y.z is 0xff000000 (because it is a class A
address). The default broadcast address is then 10.255.255.255. _However_
if you set the netmask artificially (using ifconfig's netmask option for
example) to be a "class C" netmask (ie 255.255.255.0) then the broadcast
address on your class C network is 10.x.y.255.

Now the machine the is running bootparamd has gets a packet addressed to
10.255.255.255 and it is running with address 10.x.y.z and a netmask of
255.255.255.0. The server machine creates the broadcast address 10.x.y.255
based on the netmask, compares 10.255.255.255 to that and to 10.x.y.z,
since neither match it 
NEVER SENDS THE PACKET UP THE STACK. And bootparamd sits there mute.

Routers and Netmasks

Another area where netmasks are critical are in the routing tables. IP
routers use the netmask to determine whether or not to route a packet, and
when routing, where to route it. 

If a router has one interface configured with an address of 10.x.y.z and a
netmask of  255.255.255.0 and another interface configured with address
10.x.q.r and a netmask of 255.255.255.0, then routing works as follows:
	Take an incoming packets destination address, logically
	AND it with the netmask for the interface. Take the resulting
	network number and look it up in the routing table, if you find
	a match send it out on that interface, otherwise send it to the
	"default" route.

This is why it is very important for routers to know what the correct
netmasks are as well.

How can I fix my netboot problem?

Well, the easiest way to fix it is to change your netmask to be 255.0.0.0.
The only negative effect of this is that it destroys routability between
ethernet segments that are pretending they are class C networks since the
router will now send all packets to 10.anything out to the same interface. 

Alternatively, renumber to a class C private network 192.168.*.*, or
finally use a boot protocol that passes a netmask and an IP address.

--Chuck