Subject: Arp with netmasks breaks route-to-interface cloning hack
To: None <tech-kern@NetBSD.ORG, tech-net@NetBSD.ORG>
From: Jonathan Stone <jonathan@dsg.stanford.edu>
List: tech-kern
Date: 03/25/1996 05:46:53
The patch below makes arp with subnet masks work for me.  It disables
the kernel backaward-compatibility glue in if_ether.c. arp_rtrequest(O
is too clever; if it sees a request which looks like a manually-added
route-to-interface, which arp_rtrequest() thinks should have
RTF_CLONING on, but doesn't, it adds it.

The  "natural" way to send a routing message for an arp entry
with a subnet mask looks like an old-style route-to-interface.

Now, is the  compatibility  really still useful? Do people really
run old versions of routed or gated?  Or is this needed to deal with
people who add manual routes to interfaces?

If the non-cloned compatibility is still needed, then we could add
another hack that (piling Ossa upon Pelion), before checking
for and turning on cloning, tests for routes with  RTF_HOST that
have a not-all-ones subnet mask, and if so, turn off RTF_HOST
and turn on cloning.  (Gag.)  Unless anyone has a better idea?

Anyway, if anyone knows whether or not the compatibility is necessary,
please let me know and I'll send this as a PR.  Meanwhile, feel
free to play with it :-).



*** src/sys/netinet/if_ether.c.DIST	Wed Feb 14 04:36:47 1996
--- src/sys/netinet/if_ether.c	Mon Mar 25 04:55:09 1996
***************
*** 172,180 ****
--- 172,182 ----
  		 * such as older version of routed or gated might provide,
  		 * restore cloning bit.
  		 */
+ #if 0 /* XXX  Don't do this anymore, it breaks ARP with subnet masks */
  		if ((rt->rt_flags & RTF_HOST) == 0 &&
  		    SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
  			rt->rt_flags |= RTF_CLONING;
+ #endif
  		if (rt->rt_flags & RTF_CLONING) {
  			/*
  			 * Case 1: This route should come from a route to iface.
*** src/usr.sbin/arp/arp.c.DIST	Fri Oct 13 20:51:30 1995
--- src/usr.sbin/arp/arp.c	Mon Mar 25 05:31:30 1996
***************
*** 173,182 ****
  		err(1, "socket");
  }
  
! struct	sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}};
  struct	sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
  struct	sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
  int	expire_time, flags, export_only, doing_proxy, found_entry;
  struct	{
  	struct	rt_msghdr m_rtm;
  	char	m_space[512];
--- 173,185 ----
  		err(1, "socket");
  }
  
! struct	sockaddr_in so_defaultmask = {8, AF_INET, 0, {  0xffffffff}};
! struct	sockaddr_in so_mask;
  struct	sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
  struct	sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
  int	expire_time, flags, export_only, doing_proxy, found_entry;
+ int	doing_mask;
+ 
  struct	{
  	struct	rt_msghdr m_rtm;
  	char	m_space[512];
***************
*** 205,210 ****
--- 208,215 ----
  	argv += 2;
  	sdl_m = blank_sdl;		/* struct copy */
  	sin_m = blank_sin;		/* struct copy */
+ 	so_mask = so_defaultmask;	/* struct copy */
+ 
  	if (getinetaddr(host, &sin->sin_addr) == -1)
  		return (1);
  	ea = (u_char *)LLADDR(&sdl_m);
***************
*** 220,230 ****
--- 225,244 ----
  		else if (strncmp(argv[0], "pub", 3) == 0) {
  			flags |= RTF_ANNOUNCE;
  			doing_proxy = SIN_PROXY;
+ 		} else if (strncmp(argv[0], "mask", 4) == 0 ||
+ 			   strncmp(argv[0], "netm", 4) == 0) {
+ 			argv++; argc--;
+ 			if (argc < 1)
+ 				usage();
+ 		  	getinetaddr(argv[0], &so_mask.sin_addr);
+ 			doing_mask = 1;
  		} else if (strncmp(argv[0], "trail", 5) == 0) {
  			(void)printf(
  			    "%s: Sending trailers is no longer supported\n",
  			     host);
  		}
+ 		else
+ 			usage();
  		argv++;
  	}
  tryagain:
***************
*** 410,416 ****
  			if (sin->sin_addr.s_addr == 0xffffffff)
  				(void)printf(" published");
  			if (sin->sin_len != 8)
! 				(void)printf("(wierd)");
  		}
  		(void)printf("\n");
  	}
--- 424,430 ----
  			if (sin->sin_addr.s_addr == 0xffffffff)
  				(void)printf(" published");
  			if (sin->sin_len != 8)
! 				(void)printf("(weird)");
  		}
  		(void)printf("\n");
  	}
***************
*** 449,455 ****
  	(void)fprintf(stderr, "usage: arp [-n] -a\n");
  	(void)fprintf(stderr, "usage: arp -d hostname\n");
  	(void)fprintf(stderr,
! 	    "usage: arp -s hostname ether_addr [temp] [pub]\n");
  	(void)fprintf(stderr, "usage: arp -f filename\n");
  	exit(1);
  }
--- 463,469 ----
  	(void)fprintf(stderr, "usage: arp [-n] -a\n");
  	(void)fprintf(stderr, "usage: arp -d hostname\n");
  	(void)fprintf(stderr,
! 	    "usage: arp -s hostname ether_addr [temp] [pub] [netmask mask]\n");
  	(void)fprintf(stderr, "usage: arp -f filename\n");
  	exit(1);
  }
***************
*** 492,497 ****
--- 506,517 ----
  				rtm->rtm_flags &= ~RTF_HOST;
  			}
  		}
+ 		if (doing_mask) {
+ 			rtm->rtm_addrs |= RTA_NETMASK;
+ 			rtm->rtm_flags &= ~RTF_HOST;
+ 		}
+ 		
+ 
  		/* FALLTHROUGH */
  	case RTM_GET:
  		rtm->rtm_addrs |= RTA_DST;