[mod.protocols.tcp-ip] subnet bug fixes under 4.2

smoot@POP.UTEXAS.EDU (Smoot Carl-Mitchell) (10/28/85)

I discovered a botch in my subnet implementation which I posted
about a month ago. I've updated the sources whcih are available
in ~ftp/pub/subnet.tar on sally.utexas.edu (formerly ut-sally.arpa).

In addition I added a sanity check to allow hosts with non-zero
subnets to coexist with hosts with subnet 0 on the same network.
The pertinent code changes are in if_subenable (in if_ether.c) and
in if_loop.c. (which is where the botch is).

The botch which I overlooked is in loattach (in if_loop.c).  Change
the following line:

        sin->sin_addr.s_addr = 0xff000000;

to:
        sin->sin_addr.s_addr = htonl(0xff000000);

The error is obvious and dumb.

Here is a listing of the latest version of if_subenable with the
sanity check added:

/* determine if target address is on an interface with arp subnet routing
 * enabled
 */
if_subenable(itaddr, sinterface)
struct in_addr itaddr;
struct ifnet *sinterface;
{
        struct route ro;
        struct sockaddr_in *sin;
        struct sockaddr wildcard;
        extern struct ifnet *if_ifonnetof();
 
        /* target address is on a local network */
        if (in_localaddr(itaddr)) {
                int net;
                struct ifnet *interface;
 
                net = in_netof(itaddr);
                /* sanity check - don't match if target is on the same
                 * interface the arp request came from */
                if (sinterface != NULL && net == sinterface->if_net)
                        return(0);
                interface = if_ifonnetof(net);
                if (interface == NULL) { /* this should never happen */
printf("subenable - interface not found for net - %x\n", net);
                        return(0);
                }
                return(interface->if_flags & IFF_SUBARP);
        }
        /* if target is not local then
         * look in routing table for the interface to use
         */
        sin = (struct sockaddr_in *)(&ro.ro_dst);
        sin->sin_family = AF_INET;
        sin->sin_addr = itaddr;
        ro.ro_rt = NULL;
        (void) rtalloc(&ro);
        if (ro.ro_rt != NULL
            && ((struct sockaddr_in *)(&ro.ro_rt->rt_dst))->sin_addr.s_addr != 0
            && ro.ro_rt->rt_ifp->if_flags & IFF_SUBARP
            && sinterface != ro.ro_rt->rt_ifp)
                return(1);
        return(0);
}