components/isc-dhcp/patches/002-dhcp_broadcast_offer_bug.patch
author zihao.zhu@oracle.com <zihao.zhu@oracle.com>
Tue, 18 Oct 2016 14:50:09 -0700
changeset 7123 b650e07ff9f6
parent 5709 42ebc732084b
permissions -rw-r--r--
24750381 python-ldap missing dependencies on pyasn1, pyasn1-modules

This patch file was developed in-house to fix a Solaris specific bug. We are
working with upstream, but it is unclear at this point whether or not they are
going to accept it. This is a highly visible bug which many customers have
encountered.

--- old/common/socket.c	Tue Mar  1 19:45:19 2016
+++ new/common/socket.c	Tue Mar  1 19:45:18 2016
@@ -39,6 +39,9 @@
 #include <sys/ioctl.h>
 #include <sys/uio.h>
 #include <sys/uio.h>
+#if defined (sun)
+#include <sys/ethernet.h>
+#endif
 
 #if defined(sun) && defined(USE_V4_PKTINFO)
 #include <sys/sysmacros.h>
@@ -87,6 +90,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. */
 
@@ -337,6 +367,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,
@@ -353,6 +386,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",
@@ -1088,7 +1124,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/includes/dhcpd.h	Tue Mar  1 19:45:19 2016
+++ new/includes/dhcpd.h	Tue Mar  1 19:45:18 2016
@@ -1354,6 +1354,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
@@ -2563,6 +2566,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	Tue Mar  1 19:45:19 2016
+++ new/relay/dhcrelay.c	Tue Mar  1 19:45:18 2016
@@ -653,6 +653,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/server/bootp.c	Tue Mar  1 19:45:19 2016
+++ new/server/bootp.c	Tue Mar  1 19:45:18 2016
@@ -410,7 +410,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 Mar  1 19:45:19 2016
+++ new/server/dhcp.c	Tue Mar  1 19:45:18 2016
@@ -30,6 +30,8 @@
 #include <errno.h>
 #include <limits.h>
 #include <sys/time.h>
+#include <sys/sockio.h>
+#include <sys/ioccom.h>
 
 static void maybe_return_agent_options(struct packet *packet,
 				       struct option_state *options);
@@ -3745,7 +3747,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;
@@ -3767,7 +3774,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;
 }