[mod.protocols.tcp-ip] subnetting on Suns

HEDRICK@RED.RUTGERS.EDU (Charles Hedrick) (08/11/86)

Simple-minded subnetting is very easy to do.  It requires slight
changes to in.h and in.c.  You can use in.c from any 4.2 system.  Sun's
is not special.  In addition, inet_lnaof and inet_netof need to be
fixed in a handful of utilities.  We did this without sources.
Sun claims that they are not doing subnetting because it will break
some of the extra-cost networking options, which they get from 3rd
parties and don't have source to.  I find that hard to believe, since
such code should call common kernel routines to do all routing
computations.  But it wouldn't be the first time programmers wrote
code that did something they shouldn't, so I can't judge for sure.
Here is a copy of a message I sent to somebody else.  Unfortunately,
our changes may be a bit too simple-minded.  In trying to keep the
number of changes to a minimum, I suspect we have missed some
utilities.  Any utilities that broadcasts may have to be changed.
E.g. rwho and routed.  We don't use those.  Ideally route and
netstat should also be changed.  If you have source, you can just fix
inet_lnaof and inet_netof in the C library and reload everything.
(The patches are the same as to in_lnaof and in_netof, shown below.)

When you do this, you should also set ipforwarding to 0 on every
machine on your net.  You can do this in adb:
  cp /vmunix /vmunix.OLD
  adb -w /vmunix
  ipforwarding/W 0
  ^D
Make sure the /W is upper case.  It should say 1 --> 0.  The subnet
patch may introduce disagreements as to what the broadcast address
is.  This can cause chaos.  Turning off forwarding, except on actual
gateways, can make things a lot better.  They actual gateways
should have some repair work done to in_forward, so that they
don't forward packets with bogus broadcast addresses.  I suggest
throwing away any packet that matches your class B address, and
whose low-order byte is 0 or 255.  Also any address whose first
byte is 127 or 255.  But others have done more work on this than I
and probably have better filters.

You need to decide what you want your broadcast address to be.  4.2 and
the Sun kernel use the convention that the broadcast address uses a host
number of 0.  The newest convention, implemented in 4.3, uses a host
number of -1, i.e. 255. The standards were only changed recently, so
must vendors have not caught up.  Consider our network, which is a class
B network, 128.6.  On subnet 4, there are the following possible
broadcast addresses:
  128.6.0.0	- used by 4.2
  128.6.4.0	- used by 4.2 if you install subnets
  128.6.255.255 - used by 4.3, I think
  128.6.4.255   - used by 4.3 with subnets turned on, I think
  255.255.255.255 - not used by any, but recognized by Sun and 4.3
When you enable subnets, the subnet number becomes in effect part
of your network number.  Thus the network number is 128.6.x, not
just 128.6.  So the broadcast address ends up having the subnet
number as part of it.

Now, the problem is that the Suns are set up such that every machine
on the network, including non-Suns, must agree on the broadcast
address.  Otherwise there will be chaos and your network will be
flooded with spurious packets, causing all of your machines to become
unusable.  By far the simplest approach is to use a broadcast address
of 128.6.4.0.  The standards documents, and I think 4.3, all do imply
that the subnet number should be included in the broadcast address.
128.6.4.255 would in fact be better, but it is harder to do without
source, and is going to cause trouble until everybody updates to the
new conventions (possibly including changes to the Sun ROM's).
Nevertheless, we decided to use 128.6.0.0.  We don't have as much
control over the network as I would like, and I was worried that
somebody would put up standard (non-subnet) Sun software on some
machine without talking to me.  Thus it seemed safer to use a subnet
address that would be compatible with unmodified software.  This patch
is possible, but not easy, without source.

I believe the following instructions will suffice to allow the 128.6.4.0
type broadcast address without source.  A patch to use 128.6.0.0
type broadcast address is a bit more complex.

It is easiest to do this patch by using a source version of the module
in.c.  I am including the change to in.h and in.c. MYSUBNET and possibly
the masks in in.h.  However if you change the masks, some of the binary
patches may not work.

Anyway, here is what to do:
  Use this version of in.c and in.h in building your kernel.  I
	trust you know enough about building it to make this work
	without more detailed instructions.
  There are patches to umount and ypbind necessary.  If you have
	source, just make the same patches as in in.c to the
	library routines inet_netof and inet_lnaof in libc.a,
	and rebuild umount and ypbind.  If you don't, the following
	will give reasonable approximations.  They treat all 
	addresses as class C.  Since umount and ypbind should only
	be seeing packets from a local host, that is a reasonable
	approximation.  This is for version 3.0.
		change 660e to 602c at the following address

				sun 3		sun 2
		umount		3f5a		3f72
		ypbind		3b42		3b42

	It is critical to update /etc/umount on *every* client
	at the same time.
  There are patches to boot necessary.  If you have source,
	you need to patch in_lnaof and in_broadaddr in the obvious
	way.  If not, then again we have an approximation based
	on the assumption that boot is only going to deal with
	local hosts.  In /tftpboot, change  ndboot.sun[23].pub[01]:

					    sun3	sun2
		change 660a to 6024 at	   5514		5662
		change 6610 to 6650 at	   5558		56a6

	In /pub/boot, make the corresponding changes, except
	that the addresses are 90000 (hex) higher.  You may have
	to do installboot, or patch other copies of boot,
	depending upon your machines and configurations.  If you
	have source, you will need to change in_lnaof and
	some name like in_isbroadcast.

Here are the changes to in.c

....

in_netof(in)
	struct in_addr in;
{
	register u_long i = ntohl(in.s_addr);

/* 6 SUBNET hack */
	if ((i & SUBNETMASK) == MYSUBNET)
	        return (((i)&SUBNETNET) >> SUBNETSHIFT);
/* end SUBNET hack */
	if (IN_CLASSA(i))
		return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);

...

in_lnaof(in)
	struct in_addr in;
{
	register u_long i = ntohl(in.s_addr);

/* 6 SUBNET hack */
	if ((i & SUBNETMASK) == MYSUBNET)
	        return ((i)&SUBNETHOST);
/* end SUBNET hack */
	if (IN_CLASSA(i))
		return ((i)&IN_CLASSA_HOST);

In in.h, add the following.  Use your own net number for MYSUBNET.

/* 6 subnet - this implementation hardwires the parameters here
 * instead of using settable masks, etc., as 4.3 does */
#define MYSUBNET  0x80060000
#define SUBNETMASK  0xffff0000
#define SUBNETNET 0xffffff00
#define SUBNETSHIFT 8
#define SUBNETHOST 0x000000ff
-------