17423148 ISC DHCP: DHCPOFFER is being offered as broadcast, not unicast
authorsritej.velaga@oracle.com <sritej.velaga@oracle.com>
Mon, 15 Feb 2016 11:37:48 -0800
changeset 5461 5241debe1312
parent 5460 efa9b775aa32
child 5463 245bdc05448a
17423148 ISC DHCP: DHCPOFFER is being offered as broadcast, not unicast
components/isc-dhcp/patches/004-dhcp_broadcast_offer_bug.patch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/isc-dhcp/patches/004-dhcp_broadcast_offer_bug.patch	Mon Feb 15 11:37:48 2016 -0800
@@ -0,0 +1,175 @@
+This patch file was developed in-house to fix a bug specific to solaris only.
+(Bug #17423148). We are working with upstream, but it is unclear at this point whether 
+they are going to accept it or not. This is a higly visible bug which many customers 
+have run into and it is very much desired that that this fix  makes it to S12.
+
+--- old/includes/dhcpd.h	Tue Nov 10 16:43:33 2015
++++ new/includes/dhcpd.h	Tue Nov 10 16:38:06 2015
+@@ -1150,6 +1150,9 @@
+ 	int configured;			/* If set to 1, interface has at least
+ 					 * one valid IP address.
+ 					 */
++#if defined (sun)
++	int set_arp_socket;		/* IOCTL socket to set entry in cache */
++#endif
+ 	u_int32_t flags;		/* Control flags... */
+ #define INTERFACE_REQUESTED 1
+ #define INTERFACE_AUTOMATIC 2
+@@ -2173,6 +2176,10 @@
+ 		       struct sockaddr_in6 *, struct hardware *);
+ #endif
+ 
++#if defined (sun)
++int setup_arp(struct interface_info *, struct in_addr, unsigned char *);
++#endif
++
+ #ifdef USE_SOCKET_SEND
+ void if_reinitialize_send (struct interface_info *);
+ void if_register_send (struct interface_info *);
+--- old/relay/dhcrelay.c	Thu Aug 23 12:23:54 2012
++++ new/relay/dhcrelay.c	Tue Nov 10 16:36:52 2015
+@@ -630,6 +630,13 @@
+ 			to.sin_addr = packet->yiaddr;
+ 			to.sin_port = remote_port;
+ 
++#if defined (sun)
++			if (setup_arp(out, packet->yiaddr, packet->chaddr)) {
++				log_error("do_relay4 : Set arp entry failed");
++				return;
++			}
++#endif	
++
+ 			/* and hardware address is not broadcast */
+ 			htop = &hto;
+ 		} else {
+--- old/common/socket.c	Thu Aug 23 12:23:53 2012
++++ new/common/socket.c	Tue Nov 10 16:33:30 2015
+@@ -46,6 +46,10 @@
+ #include <sys/uio.h>
+ #include <sys/uio.h>
+ #include <signal.h>
++#include <sys/types.h>
++#if defined (sun)
++#include <sys/ethernet.h>
++#endif
+ 
+ #if defined(sun) && defined(USE_V4_PKTINFO)
+ #include <sys/sysmacros.h>
+@@ -93,6 +97,33 @@
+ static int once = 0;
+ #endif /* !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK) */
+ 
++#if defined (sun)
++int
++setup_arp(struct interface_info *interface, struct in_addr ip_addr,
++	unsigned char *macaddr)
++{
++        struct xarpreq ar;
++        struct sockaddr_in *sin;
++
++	(void) memset(&ar, 0, sizeof (ar));
++        sin = (struct sockaddr_in *)&ar.xarp_pa;
++        sin->sin_family = AF_INET;
++	sin->sin_addr.s_addr = ip_addr.s_addr;
++
++	ar.xarp_ha.sdl_alen = ETHERADDRL;
++	(void) memcpy(LLADDR(&ar.xarp_ha), macaddr, ar.xarp_ha.sdl_alen); 
++	ar.xarp_ha.sdl_family = AF_LINK; 
++	if (ioctl(interface->set_arp_socket, SIOCSXARP, (caddr_t)&ar) < 0) {
++		log_error("setup_arp: ioctl error for IP %s MAC %s",
++		   inet_ntoa(ip_addr), ether_ntoa((const struct ether_addr *)
++		    macaddr));
++		return (1);
++	}
++        return (0);
++}
++#endif
++
++
+ /* Reinitializes the specified interface after an address change.   This
+    is not required for packet-filter APIs. */
+ 
+@@ -328,6 +359,9 @@
+ #else
+ 	info->wfdesc = info->rfdesc;
+ #endif
++#if defined(sun)
++	info->set_arp_socket = socket(AF_INET, SOCK_DGRAM, 0);
++#endif
+ 	if (!quiet_interface_discovery)
+ 		log_info ("Sending on   Socket/%s%s%s",
+ 		      info->name,
+@@ -344,6 +378,9 @@
+ 	close (info -> wfdesc);
+ #endif
+ 	info -> wfdesc = -1;
++#if defined (sun)
++	close (info -> set_arp_socket);
++#endif
+ 
+ 	if (!quiet_interface_discovery)
+ 		log_info ("Disabling output on Socket/%s%s%s",
+@@ -1006,7 +1043,11 @@
+ int can_unicast_without_arp (ip)
+ 	struct interface_info *ip;
+ {
++#if defined (sun)
++	return 1;
++#else
+ 	return 0;
++#endif
+ }
+ 
+ int can_receive_unicast_unconfigured (ip)
+--- old/server/bootp.c	Mon Aug 13 17:15:04 2012
++++ new/server/bootp.c	Tue Nov 10 15:23:38 2015
+@@ -408,7 +408,12 @@
+ 		   can_unicast_without_arp (packet -> interface)) {
+ 		to.sin_addr = raw.yiaddr;
+ 		to.sin_port = remote_port;
+-
++#if defined (__sun)
++                if (setup_arp(packet->interface, raw.yiaddr, raw.chaddr)) {
++                        log_error("bootp : Set arp entry failed");
++                        goto out;
++                }
++#endif
+ 	/* Otherwise, broadcast it on the local network. */
+ 	} else {
+ 		to.sin_addr = limited_broadcast;
+--- old/server/dhcp.c	Tue Nov 10 16:43:33 2015
++++ new/server/dhcp.c	Tue Nov 10 16:39:46 2015
+@@ -36,6 +36,8 @@
+ #include <errno.h>
+ #include <limits.h>
+ #include <sys/time.h>
++#include <sys/sockio.h>
++#include <sys/ioccom.h>
+ 
+ static void commit_leases_ackout(void *foo);
+ 
+@@ -3246,7 +3248,12 @@
+ 		   can_unicast_without_arp (state -> ip)) {
+ 		to.sin_addr = raw.yiaddr;
+ 		to.sin_port = remote_port;
+-
++#if defined (sun)
++		if (setup_arp(state->ip, raw.yiaddr, raw.chaddr)) {
++			log_error("dhcp_reply : Set arp entry failed");
++			goto err_out;
++		}
++#endif
+ 	/* Otherwise, broadcast it on the local network. */
+ 	} else {
+ 		to.sin_addr = limited_broadcast;
+@@ -3268,7 +3275,9 @@
+ 
+ 	/* Free all of the entries in the option_state structure
+ 	   now that we're done with them. */
+-
++#if defined (sun)
++err_out:
++#endif
+ 	free_lease_state (state, MDL);
+ 	lease -> state = (struct lease_state *)0;
+ }