summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deleted_files/usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.c (renamed from usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.c)0
-rw-r--r--deleted_files/usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.h (renamed from usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.h)0
-rw-r--r--deleted_files/usr/src/cmd/cmd-inet/sbin/dhcpagent/inc.flg (renamed from usr/src/cmd/cmd-inet/sbin/dhcpagent/inc.flg)0
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/Makefile21
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/README30
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/README.v69
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c15
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/bound.c12
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.c295
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h14
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.c90
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.h2
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c113
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/select.c96
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/states.c64
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/states.h8
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/in.routed/defs.h4
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/in.routed/output.c73
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/in.routed/rdisc.c29
-rw-r--r--usr/src/uts/common/inet/ip.h12
-rw-r--r--usr/src/uts/common/inet/ip/icmp.c13
-rw-r--r--usr/src/uts/common/inet/ip/icmp_opt_data.c3
-rw-r--r--usr/src/uts/common/inet/ip/ip.c415
-rw-r--r--usr/src/uts/common/inet/ip/ip_if.c18
-rw-r--r--usr/src/uts/common/inet/ip/ip_opt_data.c6
-rw-r--r--usr/src/uts/common/inet/ip_impl.h1
-rw-r--r--usr/src/uts/common/inet/ipclassifier.h3
-rw-r--r--usr/src/uts/common/inet/rawip_impl.h1
-rw-r--r--usr/src/uts/common/inet/tcp/tcp.c2
-rw-r--r--usr/src/uts/common/inet/udp/udp.c12
-rw-r--r--usr/src/uts/common/inet/udp/udp_opt_data.c5
-rw-r--r--usr/src/uts/common/inet/udp_impl.h1
-rw-r--r--usr/src/uts/common/netinet/in.h12
33 files changed, 609 insertions, 770 deletions
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.c b/deleted_files/usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.c
index 0099600ec3..0099600ec3 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.c
+++ b/deleted_files/usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.c
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.h b/deleted_files/usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.h
index cb8276c204..cb8276c204 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.h
+++ b/deleted_files/usr/src/cmd/cmd-inet/sbin/dhcpagent/dlpi_io.h
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/inc.flg b/deleted_files/usr/src/cmd/cmd-inet/sbin/dhcpagent/inc.flg
index a456cbaede..a456cbaede 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/inc.flg
+++ b/deleted_files/usr/src/cmd/cmd-inet/sbin/dhcpagent/inc.flg
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/Makefile b/usr/src/cmd/cmd-inet/sbin/dhcpagent/Makefile
index 24f8535619..5bc7b56a2b 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/Makefile
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/Makefile
@@ -29,26 +29,21 @@ PROG = dhcpagent
ROOTFS_PROG = $(PROG)
DEFAULTFILES = dhcpagent.dfl
-LOCOBJS = adopt.o agent.o async.o bound.o class_id.o defaults.o \
- dlpi_io.o inform.o init_reboot.o interface.o ipc_action.o \
- packet.o release.o renew.o request.o script_handler.o select.o \
- states.o util.o
-COMDIR = $(SRC)/common/net/dhcp
-COMOBJS = ipv4_sum.o udp_sum.o
+OBJS = adopt.o agent.o async.o bound.o class_id.o defaults.o inform.o \
+ init_reboot.o interface.o ipc_action.o packet.o release.o renew.o \
+ request.o script_handler.o select.o states.o util.o
include ../../../Makefile.cmd
-OBJS = $(COMOBJS) $(LOCOBJS)
-SRCS = $(COMOBJS:%.o=$(COMDIR)/%.c) $(LOCOBJS:%.o=%.c)
-
-POFILES = $(LOCOBJS:%.o=%.po)
+SRCS = $(OBJS:%.o=%.c)
+POFILES = $(OBJS:%.o=%.po)
XGETFLAGS += -a -x dhcpagent.xcl
#
# to compile a debug version, do a `make COPTFLAG="-g -XO0"'
#
-CPPFLAGS += -I$(COMDIR) -D_XOPEN_SOURCE=500 -D__EXTENSIONS__
+CPPFLAGS += -D_XOPEN_SOURCE=500 -D__EXTENSIONS__
LDLIBS += -lxnet -lnvpair -ldhcpagent -ldhcputil -linetutil -ldevinfo -ldlpi
# Disable warnings that affect all XPG applications.
@@ -64,10 +59,6 @@ $(PROG): $(OBJS)
$(LINK.c) -o $@ $(OBJS) $(LDLIBS)
$(POST_PROCESS)
-%.o: $(COMDIR)/%.c
- $(COMPILE.c) $(OUTPUT_OPTION) $<
- $(POST_PROCESS_O)
-
$(POFILE): $(POFILES)
$(RM) $@; $(CAT) $(POFILES) > $@; $(RM) $(POFILES)
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/README b/usr/src/cmd/cmd-inet/sbin/dhcpagent/README
index 92794d0ca3..749ec9a665 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/README
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/README
@@ -81,8 +81,8 @@ up into three groups:
difference between this and the first group is that the
interfaces exported from these files do not operate on
an "object", but rather perform a specific task. Examples
- include "dlpi_io.c", which provides a useful interface
- to DLPI-related i/o operations.
+ include "defaults.c", which provides a useful interface
+ to /etc/default/dhcpagent file operations.
OVERVIEW
========
@@ -306,9 +306,7 @@ init_pkt(), the add_pkt_opt*() functions are used to add options to
the DHCP packet. Finally, send_pkt() and send_pkt_v6() can be used to
transmit the packet to a given IP address.
-The send_pkt() function is actually quite complicated; for one, it
-must internally use either DLPI or sockets depending on the machine
-state; for another, it handles the details of packet timeout and
+The send_pkt() function handles the details of packet timeout and
retransmission. The last argument to send_pkt() is a pointer to a
"stop function." If this argument is passed as NULL, then the packet
will only be sent once (it won't be retransmitted). Otherwise, before
@@ -325,24 +323,20 @@ action.
The recv_pkt() function is simpler but still complicated by the fact
that one may want to receive several different types of packets at
-once and in different ways (DLPI or sockets). The caller registers an
-event handler on the file descriptor, and then calls recv_pkt() to
-read in the packet along with meta information about the message (the
-sender and interface identifier).
-
+once. The caller registers an event handler on the file descriptor,
+and then calls recv_pkt() to read in the packet along with meta
+information about the message (the sender and interface identifier).
+
For IPv6, packet reception is done with a single socket, using
IPV6_PKTINFO to determine the actual destination address and receiving
interface. Packets are then matched against the state machines on the
given interface through the transaction ID.
-The same facility exists for inbound IPv4 packets, but because there's
-no IP_PKTINFO processing on output yet in Solaris, and because IPv4
-still relies on DLPI, DHCP packets are handled on a per-LIF (when
-bound) and per-PIF (when unbound) basis. Eventually, when IP_PKTINFO
-is available for IPv4, the per-LIF sockets can go away. If it ever
-becomes possible to send and receive IP packets without having an IP
-address configured on an interface, then the DLPI streams can go as
-well.
+For IPv4, due to oddities in the DHCP specification (discussed in
+PSARC/2007/571), a special IP_DHCPINIT_IF socket option must be used
+to allow unicast DHCP traffic to be received on an interface during
+lease acquisition. Since the IP_DHCPINIT_IF socket option can only
+enable one interface at a time, one socket must be used per interface.
Time
----
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/README.v6 b/usr/src/cmd/cmd-inet/sbin/dhcpagent/README.v6
index 72c3490bd9..a52fe3e6b9 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/README.v6
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/README.v6
@@ -22,6 +22,15 @@ Use is subject to license terms.
ident "%Z%%M% %I% %E% SMI"
+
+** PLEASE NOTE:
+**
+** This document discusses aspects of the DHCPv4 client design that have
+** since changed (e.g., DLPI is no longer used). However, since those
+** aspects affected the DHCPv6 design, the discussion has been left for
+** historical record.
+
+
DHCPv6 Client Low-Level Design
Introduction
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c
index 12fda6da80..d1d4756867 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c
@@ -1163,6 +1163,7 @@ check_lif(dhcp_lif_t *lif, const struct ifa_msghdr *ifam, int msglen)
lif->lif_name);
lif_mark_decline(lif, "duplicate address");
close_ip_lif(lif);
+ (void) open_ip_lif(lif, INADDR_ANY);
}
dad_wait = lif->lif_dad_wait;
@@ -1404,20 +1405,8 @@ rtsock_event(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg)
* remove them from the list. Any leases that become empty are
* also removed as part of the decline-generation process.
*/
- if (dsmp->dsm_lif_down != 0) {
- /*
- * We need to switch back to PRE_BOUND state so that
- * send_pkt_internal() uses DLPI instead of sockets.
- * Our logical interface has already been torn down by
- * the kernel, and thus we can't send DHCPDECLINE by
- * way of regular IP. (Unless we're adopting -- allow
- * the grandparent to be handled as expected.)
- */
- if (oldstate != ADOPTING) {
- (void) set_smach_state(dsmp, PRE_BOUND);
- }
+ if (dsmp->dsm_lif_down != 0)
send_declines(dsmp);
- }
if (dsmp->dsm_leases == NULL) {
dsmp->dsm_bad_offers++;
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/bound.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/bound.c
index 26dd80d2c4..0de123a571 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/bound.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/bound.c
@@ -337,7 +337,7 @@ dhcp_bound_complete(dhcp_smach_t *dsmp)
*/
if (dsmp->dsm_isv6) {
(void) set_smach_state(dsmp, BOUND);
- dhcpmsg(MSG_DEBUG, "configure_bound: bound %s",
+ dhcpmsg(MSG_DEBUG, "dhcp_bound_complete: bound %s",
dsmp->dsm_name);
(void) script_start(dsmp, EVENT_BOUND6, bound_event_cb, NULL,
NULL);
@@ -363,7 +363,7 @@ dhcp_bound_complete(dhcp_smach_t *dsmp)
dsmp->dsm_nrouters = router_list->len / sizeof (ipaddr_t);
dsmp->dsm_routers = malloc(router_list->len);
if (dsmp->dsm_routers == NULL) {
- dhcpmsg(MSG_ERR, "configure_bound: cannot allocate "
+ dhcpmsg(MSG_ERR, "dhcp_bound_complete: cannot allocate "
"default router list, ignoring default routers");
dsmp->dsm_nrouters = 0;
}
@@ -376,8 +376,8 @@ dhcp_bound_complete(dhcp_smach_t *dsmp)
if (!add_default_route(lif->lif_pif->pif_index,
&dsmp->dsm_routers[i])) {
- dhcpmsg(MSG_ERR, "configure_bound: cannot add "
- "default router %s on %s", inet_ntoa(
+ dhcpmsg(MSG_ERR, "dhcp_bound_complete: cannot "
+ "add default router %s on %s", inet_ntoa(
dsmp->dsm_routers[i]), dsmp->dsm_name);
dsmp->dsm_routers[i].s_addr = htonl(INADDR_ANY);
continue;
@@ -391,12 +391,12 @@ dhcp_bound_complete(dhcp_smach_t *dsmp)
oldstate = dsmp->dsm_state;
if (!set_smach_state(dsmp, BOUND)) {
dhcpmsg(MSG_ERR,
- "configure_bound: cannot set bound state on %s",
+ "dhcp_bound_complete: cannot set bound state on %s",
dsmp->dsm_name);
return;
}
- dhcpmsg(MSG_DEBUG, "configure_bound: bound %s", dsmp->dsm_name);
+ dhcpmsg(MSG_DEBUG, "dhcp_bound_complete: bound %s", dsmp->dsm_name);
/*
* We're now committed to this binding, so if it came from BOOTP, set
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.c
index 0dd2893cf7..fb706c77e1 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.c
@@ -41,12 +41,10 @@
#include <arpa/inet.h>
#include <dhcpmsg.h>
#include <dhcp_inittab.h>
-#include <stropts.h>
#include "agent.h"
#include "interface.h"
#include "util.h"
-#include "dlpi_io.h"
#include "packet.h"
#include "states.h"
@@ -80,6 +78,7 @@ insert_pif(const char *pname, boolean_t isv6, int *error)
{
dhcp_pif_t *pif;
struct lifreq lifr;
+ dlpi_handle_t dh = NULL;
if ((pif = calloc(1, sizeof (*pif))) == NULL) {
dhcpmsg(MSG_ERR, "insert_pif: cannot allocate pif entry for "
@@ -89,8 +88,6 @@ insert_pif(const char *pname, boolean_t isv6, int *error)
}
pif->pif_isv6 = isv6;
- pif->pif_dlpi_hd = NULL;
- pif->pif_dlpi_id = -1;
pif->pif_hold_count = 1;
pif->pif_running = B_TRUE;
@@ -104,17 +101,14 @@ insert_pif(const char *pname, boolean_t isv6, int *error)
/* We do not use DLPI with DHCPv6 */
if (!isv6) {
int rc;
- dlpi_handle_t dh;
dlpi_info_t dlinfo;
/*
* Do the allocations necessary for IPv4 DHCP.
*
* 1. open the interface using DLPI
- * 2. get the interface max SDU
- * 3. get the interface hardware type and hardware length
- * 4. get the interface hardware address
- * 5. get the interface hardware broadcast address
+ * 2. get the interface hardware type and hardware length
+ * 3. get the interface hardware address
*/
/* step 1 */
@@ -124,7 +118,6 @@ insert_pif(const char *pname, boolean_t isv6, int *error)
*error = DHCP_IPC_E_INVIF;
goto failure;
}
- pif->pif_dlpi_hd = dh;
if ((rc = dlpi_bind(dh, ETHERTYPE_IP, NULL)) != DLPI_SUCCESS) {
dhcpmsg(MSG_ERROR, "insert_pif: dlpi_bind: %s",
@@ -134,7 +127,7 @@ insert_pif(const char *pname, boolean_t isv6, int *error)
}
/* step 2 */
- rc = dlpi_info(pif->pif_dlpi_hd, &dlinfo, 0);
+ rc = dlpi_info(dh, &dlinfo, 0);
if (rc != DLPI_SUCCESS) {
dhcpmsg(MSG_ERROR, "insert_pif: dlpi_info: %s",
dlpi_strerror(rc));
@@ -142,25 +135,13 @@ insert_pif(const char *pname, boolean_t isv6, int *error)
goto failure;
}
- pif->pif_max = dlinfo.di_max_sdu;
- if (pif->pif_max < DHCP_DEF_MAX_SIZE) {
- dhcpmsg(MSG_ERROR, "insert_pif: %s does not have a "
- "large enough maximum SDU to support DHCP "
- "(%u < %u)", pname, pif->pif_max,
- DHCP_DEF_MAX_SIZE);
- *error = DHCP_IPC_E_INVIF;
- goto failure;
- }
-
- /* step 3 */
pif->pif_hwtype = dlpi_arptype(dlinfo.di_mactype);
pif->pif_hwlen = dlinfo.di_physaddrlen;
- dhcpmsg(MSG_DEBUG, "insert_pif: %s: sdumax %u, hwtype %d, "
- "hwlen %d", pname, pif->pif_max, pif->pif_hwtype,
- pif->pif_hwlen);
+ dhcpmsg(MSG_DEBUG, "insert_pif: %s: hwtype %d, hwlen %d",
+ pname, pif->pif_hwtype, pif->pif_hwlen);
- /* step 4 */
+ /* step 3 */
if (pif->pif_hwlen > 0) {
pif->pif_hwaddr = malloc(pif->pif_hwlen);
if (pif->pif_hwaddr == NULL) {
@@ -169,29 +150,12 @@ insert_pif(const char *pname, boolean_t isv6, int *error)
*error = DHCP_IPC_E_MEMORY;
goto failure;
}
+ (void) memcpy(pif->pif_hwaddr, dlinfo.di_physaddr,
+ pif->pif_hwlen);
}
- (void) memcpy(pif->pif_hwaddr, dlinfo.di_physaddr,
- pif->pif_hwlen);
-
- /*
- * step 5
- * Some media types has no broadcast address.
- */
- if ((pif->pif_dlen = dlinfo.di_bcastaddrlen) != 0) {
- pif->pif_daddr = malloc(pif->pif_dlen);
- if (pif->pif_daddr == NULL) {
- dhcpmsg(MSG_ERR, "insert_pif: cannot allocate "
- "pif_daddr for %s", pname);
- *error = DHCP_IPC_E_MEMORY;
- goto failure;
- }
- }
- (void) memcpy(pif->pif_daddr, dlinfo.di_bcastaddr,
- pif->pif_dlen);
-
- /* Close the DLPI stream until actually needed */
- close_dlpi_pif(pif);
+ dlpi_close(dh);
+ dh = NULL;
}
/*
@@ -202,20 +166,34 @@ insert_pif(const char *pname, boolean_t isv6, int *error)
(void) strlcpy(lifr.lifr_name, pname, LIFNAMSIZ);
if (ioctl(isv6 ? v6_sock_fd : v4_sock_fd, SIOCGLIFINDEX, &lifr) == -1) {
- if (errno == ENXIO)
- *error = DHCP_IPC_E_INVIF;
- else
- *error = DHCP_IPC_E_INT;
+ *error = (errno == ENXIO) ? DHCP_IPC_E_INVIF : DHCP_IPC_E_INT;
dhcpmsg(MSG_ERR, "insert_pif: SIOCGLIFINDEX for %s", pname);
goto failure;
}
pif->pif_index = lifr.lifr_index;
+ if (ioctl(isv6 ? v6_sock_fd : v4_sock_fd, SIOCGLIFMTU, &lifr) == -1) {
+ *error = (errno == ENXIO) ? DHCP_IPC_E_INVIF : DHCP_IPC_E_INT;
+ dhcpmsg(MSG_ERR, "insert_pif: SIOCGLIFMTU for %s", pname);
+ goto failure;
+ }
+ pif->pif_max = lifr.lifr_mtu;
+
+ if (pif->pif_max < DHCP_DEF_MAX_SIZE) {
+ dhcpmsg(MSG_ERROR, "insert_pif: MTU of %s is too small to "
+ "support DHCP (%u < %u)", pname, pif->pif_max,
+ DHCP_DEF_MAX_SIZE);
+ *error = DHCP_IPC_E_INVIF;
+ goto failure;
+ }
+
insque(pif, isv6 ? &v6root : &v4root);
return (pif);
failure:
+ if (dh != NULL)
+ dlpi_close(dh);
release_pif(pif);
return (NULL);
}
@@ -256,10 +234,7 @@ release_pif(dhcp_pif_t *pif)
pif->pif_name);
remque(pif);
- pif->pif_dlpi_count = 1;
- close_dlpi_pif(pif);
free(pif->pif_hwaddr);
- free(pif->pif_daddr);
free(pif);
} else {
dhcpmsg(MSG_DEBUG2, "release_pif: hold count on %s: %u",
@@ -343,80 +318,9 @@ lookup_pif_by_name(const char *pname, boolean_t isv6)
}
/*
- * open_dlpi_pif(): register the use of DLPI I/O by a LIF on a PIF, opening
- * the connection if necessary.
- *
- * input: dhcp_pif_t *: the physical interface on which to use DLPI
- * output: boolean_t: B_TRUE on success, B_FALSE on failure.
- */
-
-boolean_t
-open_dlpi_pif(dhcp_pif_t *pif)
-{
- int rc;
- dlpi_handle_t dh;
-
- if (pif->pif_dlpi_hd == NULL) {
- if ((rc = dlpi_open(pif->pif_name, &dh, 0)) != DLPI_SUCCESS) {
- dhcpmsg(MSG_ERROR, "open_dlpi_pif: dlpi_open: %s",
- dlpi_strerror(rc));
- return (B_FALSE);
- }
-
- if ((rc = dlpi_bind(dh, ETHERTYPE_IP, NULL)) != DLPI_SUCCESS) {
- dhcpmsg(MSG_ERROR, "open_dlpi_pif: dlpi_bind: %s",
- dlpi_strerror(rc));
- dlpi_close(dh);
- return (B_FALSE);
- }
-
- if (!(set_packet_filter(dh, dhcp_filter, NULL, "DHCP"))) {
- dlpi_close(dh);
- return (B_FALSE);
- }
- pif->pif_dlpi_id = iu_register_event(eh, dlpi_fd(dh), POLLIN,
- dhcp_collect_dlpi, pif);
- if (pif->pif_dlpi_id == -1) {
- dlpi_close(dh);
- return (B_FALSE);
- }
-
- pif->pif_dlpi_hd = dh;
- }
- pif->pif_dlpi_count++;
- return (B_TRUE);
-}
-
-/*
- * close_dlpi_pif(): unregister the use of DLPI I/O by a LIF on a PIF, closing
- * the connection if this was the last user.
- *
- * input: dhcp_pif_t *: the physical interface on which we're using DLPI
- * output: none
- */
-
-void
-close_dlpi_pif(dhcp_pif_t *pif)
-{
- if (pif->pif_dlpi_count > 1) {
- pif->pif_dlpi_count--;
- return;
- }
- pif->pif_dlpi_count = 0;
- if (pif->pif_dlpi_id != -1) {
- (void) iu_unregister_event(eh, pif->pif_dlpi_id, NULL);
- pif->pif_dlpi_id = -1;
- }
- if (pif->pif_dlpi_hd != NULL) {
- dlpi_close(pif->pif_dlpi_hd);
- pif->pif_dlpi_hd = NULL;
- }
-}
-
-/*
* pif_status(): update the physical interface up/down status.
*
- * input: dhcp_pif_t *: the physical interface on which we're using DLPI
+ * input: dhcp_pif_t *: the physical interface to be updated
* boolean_t: B_TRUE if the interface is going up
* output: none
*/
@@ -478,7 +382,7 @@ insert_lif(dhcp_pif_t *pif, const char *lname, int *error)
}
lif->lif_sock_ip_fd = -1;
- lif->lif_acknak_id = -1;
+ lif->lif_packet_id = -1;
lif->lif_iaid_id = -1;
lif->lif_hold_count = 1;
lif->lif_pif = pif;
@@ -729,6 +633,8 @@ checkaddr(const dhcp_lif_t *lif, int ioccmd, const in6_addr_t *addr,
boolean_t isv6;
int fd;
struct lifreq lifr;
+ char abuf1[INET6_ADDRSTRLEN];
+ char abuf2[INET6_ADDRSTRLEN];
(void) memset(&lifr, 0, sizeof (struct lifreq));
(void) strlcpy(lifr.lifr_name, lif->lif_name, LIFNAMSIZ);
@@ -748,32 +654,27 @@ checkaddr(const dhcp_lif_t *lif, int ioccmd, const in6_addr_t *addr,
} else if (isv6) {
struct sockaddr_in6 *sin6 =
(struct sockaddr_in6 *)&lifr.lifr_addr;
- char abuf1[INET6_ADDRSTRLEN];
- char abuf2[INET6_ADDRSTRLEN];
if (!IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, addr)) {
dhcpmsg(MSG_WARNING,
- "checkaddr: expected %s %s on %s, have %s",
- aname, inet_ntop(AF_INET6, &sin6->sin6_addr, abuf1,
- sizeof (abuf1)), lif->lif_name,
- inet_ntop(AF_INET6, addr, abuf2, sizeof (abuf2)));
+ "checkaddr: expected %s %s on %s, have %s", aname,
+ inet_ntop(AF_INET6, addr, abuf1, sizeof (abuf1)),
+ lif->lif_name, inet_ntop(AF_INET6, &sin6->sin6_addr,
+ abuf2, sizeof (abuf2)));
return (B_FALSE);
}
} else {
struct sockaddr_in *sinp =
(struct sockaddr_in *)&lifr.lifr_addr;
ipaddr_t v4addr;
- char abuf1[INET_ADDRSTRLEN];
- char abuf2[INET_ADDRSTRLEN];
IN6_V4MAPPED_TO_IPADDR(addr, v4addr);
if (sinp->sin_addr.s_addr != v4addr) {
dhcpmsg(MSG_WARNING,
- "checkaddr: expected %s %s on %s, have %s",
- aname, inet_ntop(AF_INET, &sinp->sin_addr, abuf1,
- sizeof (abuf1)), lif->lif_name,
- inet_ntop(AF_INET, &v4addr, abuf2,
- sizeof (abuf2)));
+ "checkaddr: expected %s %s on %s, have %s", aname,
+ inet_ntop(AF_INET, &v4addr, abuf1, sizeof (abuf1)),
+ lif->lif_name, inet_ntop(AF_INET, &sinp->sin_addr,
+ abuf2, sizeof (abuf2)));
return (B_FALSE);
}
}
@@ -896,11 +797,12 @@ verify_lif(const dhcp_lif_t *lif)
* unplumb_lif().
*
* input: dhcp_lif_t *: the interface to canonize
+ * boolean_t: only canonize lif if it's under DHCP control
* output: none
*/
static void
-canonize_lif(dhcp_lif_t *lif)
+canonize_lif(dhcp_lif_t *lif, boolean_t dhcponly)
{
boolean_t isv6;
int fd;
@@ -934,8 +836,7 @@ canonize_lif(dhcp_lif_t *lif)
return;
}
- /* Should not happen */
- if (!(lifr.lifr_flags & IFF_DHCPRUNNING)) {
+ if (dhcponly && !(lifr.lifr_flags & IFF_DHCPRUNNING)) {
dhcpmsg(MSG_INFO,
"canonize_lif: cannot clear %s; flags are %llx",
lif->lif_name, lifr.lifr_flags);
@@ -1117,7 +1018,7 @@ unplumb_lif(dhcp_lif_t *lif)
* just canonize it and remove it from the lease.
*/
if ((dlp = lif->lif_lease) != NULL && dlp->dl_smach->dsm_lif == lif) {
- canonize_lif(lif);
+ canonize_lif(lif, B_TRUE);
cancel_lif_timers(lif);
if (lif->lif_declined != NULL) {
dlp->dl_smach->dsm_lif_down--;
@@ -1349,12 +1250,17 @@ clear_lif_deprecated(dhcp_lif_t *lif)
* open_ip_lif(): open up an IP socket for I/O on a given LIF (v4 only).
*
* input: dhcp_lif_t *: the logical interface to operate on
+ * in_addr_t: the address the socket will be bound to (in hbo)
* output: boolean_t: B_TRUE if the socket was opened successfully.
*/
boolean_t
-open_ip_lif(dhcp_lif_t *lif)
+open_ip_lif(dhcp_lif_t *lif, in_addr_t addr_hbo)
{
+ const char *errmsg;
+ struct lifreq lifr;
+ int on = 1;
+
if (lif->lif_sock_ip_fd != -1) {
dhcpmsg(MSG_WARNING, "open_ip_lif: socket already open on %s",
lif->lif_name);
@@ -1363,27 +1269,90 @@ open_ip_lif(dhcp_lif_t *lif)
lif->lif_sock_ip_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (lif->lif_sock_ip_fd == -1) {
- dhcpmsg(MSG_ERR, "open_ip_lif: cannot create v4 socket on %s",
- lif->lif_name);
- return (B_FALSE);
+ errmsg = "cannot create v4 socket";
+ goto failure;
}
- if (!bind_sock(lif->lif_sock_ip_fd, IPPORT_BOOTPC,
- ntohl(lif->lif_addr))) {
- dhcpmsg(MSG_ERR, "open_ip_lif: cannot bind v4 socket on %s",
- lif->lif_name);
- return (B_FALSE);
+ if (!bind_sock(lif->lif_sock_ip_fd, IPPORT_BOOTPC, addr_hbo)) {
+ errmsg = "cannot bind v4 socket";
+ goto failure;
}
- lif->lif_acknak_id = iu_register_event(eh, lif->lif_sock_ip_fd, POLLIN,
- dhcp_acknak_lif, lif);
- if (lif->lif_acknak_id == -1) {
- dhcpmsg(MSG_WARNING, "open_ip_lif: cannot register to "
- "receive IP unicast");
- close_ip_lif(lif);
- return (B_FALSE);
+ /*
+ * If we bound to INADDR_ANY, we have no IFF_UP source address to use.
+ * Thus, enable IP_UNSPEC_SRC so that we can send packets with an
+ * unspecified (0.0.0.0) address. Also, enable IP_DHCPINIT_IF so that
+ * the IP module will accept unicast DHCP traffic regardless of the IP
+ * address it's sent to. (We'll then figure out which packets are
+ * ours based on the xid.)
+ */
+ if (addr_hbo == INADDR_ANY) {
+ if (setsockopt(lif->lif_sock_ip_fd, IPPROTO_IP, IP_UNSPEC_SRC,
+ &on, sizeof (int)) == -1) {
+ errmsg = "cannot set IP_UNSPEC_SRC";
+ goto failure;
+ }
+
+ if (setsockopt(lif->lif_sock_ip_fd, IPPROTO_IP, IP_DHCPINIT_IF,
+ &lif->lif_pif->pif_index, sizeof (int)) == -1) {
+ errmsg = "cannot set IP_DHCPINIT_IF";
+ goto failure;
+ }
}
+
+ if (setsockopt(lif->lif_sock_ip_fd, IPPROTO_IP, IP_BOUND_IF,
+ &lif->lif_pif->pif_index, sizeof (int)) == -1) {
+ errmsg = "cannot set IP_BOUND_IF";
+ goto failure;
+ }
+
+ /*
+ * Make sure at least one lif on the interface we used in IP_BOUND_IF
+ * is IFF_UP so that we can send and receive IP packets.
+ */
+ (void) strlcpy(lifr.lifr_name, lif->lif_name, LIFNAMSIZ);
+ if (ioctl(v4_sock_fd, SIOCGLIFFLAGS, &lifr) == -1) {
+ errmsg = "cannot get interface flags";
+ goto failure;
+ }
+
+ if (!(lifr.lifr_flags & IFF_UP)) {
+ /*
+ * Start from a clean slate.
+ */
+ canonize_lif(lif, B_FALSE);
+
+ lifr.lifr_flags |= IFF_UP;
+ if (ioctl(v4_sock_fd, SIOCSLIFFLAGS, &lifr) == -1) {
+ errmsg = "cannot bring up";
+ goto failure;
+ }
+
+ /*
+ * When bringing 0.0.0.0 IFF_UP, the kernel changes the
+ * netmask to 255.0.0.0, so re-fetch our expected netmask.
+ */
+ if (ioctl(v4_sock_fd, SIOCGLIFNETMASK, &lifr) == -1) {
+ errmsg = "cannot get netmask";
+ goto failure;
+ }
+
+ lif->lif_netmask =
+ ((struct sockaddr_in *)&lifr.lifr_addr)->sin_addr.s_addr;
+ }
+
+ lif->lif_packet_id = iu_register_event(eh, lif->lif_sock_ip_fd, POLLIN,
+ dhcp_packet_lif, lif);
+ if (lif->lif_packet_id == -1) {
+ errmsg = "cannot register to receive DHCP packets";
+ goto failure;
+ }
+
return (B_TRUE);
+failure:
+ dhcpmsg(MSG_ERR, "open_ip_lif: %s: %s", lif->lif_name, errmsg);
+ close_ip_lif(lif);
+ return (B_FALSE);
}
/*
@@ -1396,9 +1365,9 @@ open_ip_lif(dhcp_lif_t *lif)
void
close_ip_lif(dhcp_lif_t *lif)
{
- if (lif->lif_acknak_id != -1) {
- (void) iu_unregister_event(eh, lif->lif_acknak_id, NULL);
- lif->lif_acknak_id = -1;
+ if (lif->lif_packet_id != -1) {
+ (void) iu_unregister_event(eh, lif->lif_packet_id, NULL);
+ lif->lif_packet_id = -1;
}
if (lif->lif_sock_ip_fd != -1) {
(void) close(lif->lif_sock_ip_fd);
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h b/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h
index 585ff7d41e..f68e849ec9 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h
@@ -47,7 +47,6 @@ extern "C" {
#include <netinet/dhcp.h>
#include <dhcpagent_ipc.h>
#include <libinetutil.h>
-#include <libdlpi.h>
#include "common.h"
#include "util.h"
@@ -65,14 +64,7 @@ struct dhcp_pif_s {
uchar_t pif_hwtype; /* type of link-layer */
boolean_t pif_isv6;
boolean_t pif_running; /* interface is running */
- dlpi_handle_t pif_dlpi_hd; /* dlpi handle */
- int pif_dlpi_count;
- iu_event_id_t pif_dlpi_id; /* event id for ack/nak/offer */
uint_t pif_hold_count; /* reference count */
-
- uchar_t *pif_daddr; /* our L2 destination address */
- uchar_t pif_dlen; /* our L2 destination address len */
-
char pif_name[LIFNAMSIZ];
};
@@ -84,7 +76,7 @@ struct dhcp_lif_s {
dhcp_lease_t *lif_lease; /* backpointer to lease holding LIF */
uint64_t lif_flags; /* Interface flags (IFF_*) */
int lif_sock_ip_fd; /* Bound to addr.BOOTPC for src addr */
- iu_event_id_t lif_acknak_id; /* event acknak id */
+ iu_event_id_t lif_packet_id; /* event packet id */
uint_t lif_max; /* maximum IP message size */
uint_t lif_hold_count; /* reference count */
boolean_t lif_dad_wait; /* waiting for DAD resolution */
@@ -177,8 +169,6 @@ void release_pif(dhcp_pif_t *);
dhcp_pif_t *lookup_pif_by_index(uint_t, boolean_t);
dhcp_pif_t *lookup_pif_by_uindex(uint16_t, dhcp_pif_t *, boolean_t);
dhcp_pif_t *lookup_pif_by_name(const char *, boolean_t);
-boolean_t open_dlpi_pif(dhcp_pif_t *);
-void close_dlpi_pif(dhcp_pif_t *);
void pif_status(dhcp_pif_t *, boolean_t);
dhcp_lif_t *insert_lif(dhcp_pif_t *, const char *, int *);
@@ -193,7 +183,7 @@ dhcp_lif_t *attach_lif(const char *, boolean_t, int *);
int set_lif_dhcp(dhcp_lif_t *, boolean_t);
void set_lif_deprecated(dhcp_lif_t *);
boolean_t clear_lif_deprecated(dhcp_lif_t *);
-boolean_t open_ip_lif(dhcp_lif_t *);
+boolean_t open_ip_lif(dhcp_lif_t *, in_addr_t);
void close_ip_lif(dhcp_lif_t *);
void lif_mark_decline(dhcp_lif_t *, const char *);
boolean_t schedule_lif_timer(dhcp_lif_t *, dhcp_timer_t *,
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.c
index 071fc6566d..8a32b55ea5 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.c
@@ -46,7 +46,6 @@
#include "agent.h"
#include "packet.h"
#include "util.h"
-#include "dlpi_io.h"
int v6_sock_fd = -1;
int v4_sock_fd = -1;
@@ -157,19 +156,18 @@ pkt_get_xid(const PKT *pkt, boolean_t isv6)
dhcp_pkt_t *
init_pkt(dhcp_smach_t *dsmp, uchar_t type)
{
- uint_t mtu;
dhcp_pkt_t *dpkt = &dsmp->dsm_send_pkt;
dhcp_lif_t *lif = dsmp->dsm_lif;
dhcp_pif_t *pif = lif->lif_pif;
+ uint_t mtu = lif->lif_max;
uint32_t xid;
boolean_t isv6;
- mtu = dsmp->dsm_using_dlpi ? pif->pif_max : lif->lif_max;
dpkt->pkt_isv6 = isv6 = pif->pif_isv6;
/*
- * since multiple dhcp leases may be maintained over the same dlpi
- * device (e.g. "hme0" and "hme0:1"), make sure the xid is unique.
+ * Since multiple dhcp leases may be maintained over the same pif
+ * (e.g. "hme0" and "hme0:1"), make sure the xid is unique.
*
* Note that transaction ID zero is intentionally never assigned.
* That's used to represent "no ID." Also note that transaction IDs
@@ -250,14 +248,12 @@ init_pkt(dhcp_smach_t *dsmp, uchar_t type)
* thus server can not unicast the reply. Per
* RFC 2131 4.4.1, client can set this bit in
* DISCOVER/REQUEST. If the client is already
- * in BOUND/REBINDING/RENEWING state, do not set
- * this bit, as it can respond to unicast responses
- * from server using the 'ciaddr' address.
+ * in a bound state, do not set this bit, as it
+ * can respond to unicast responses from server
+ * using the 'ciaddr' address.
*/
- if (type == DISCOVER ||
- (type == REQUEST && dsmp->dsm_state != RENEWING &&
- dsmp->dsm_state != REBINDING &&
- dsmp->dsm_state != BOUND))
+ if (type == DISCOVER || (type == REQUEST &&
+ !is_bound_state(dsmp->dsm_state)))
v4->flags = htons(BCAST_MASK);
}
@@ -804,7 +800,6 @@ send_pkt_internal(dhcp_smach_t *dsmp)
{
ssize_t n_bytes;
dhcp_lif_t *lif = dsmp->dsm_lif;
- dhcp_pif_t *pif = lif->lif_pif;
dhcp_pkt_t *dpkt = &dsmp->dsm_send_pkt;
uchar_t ptype = pkt_send_type(dpkt);
const char *pkt_name;
@@ -813,6 +808,7 @@ send_pkt_internal(dhcp_smach_t *dsmp)
struct cmsghdr *cmsg;
struct in6_pktinfo *ipi6;
boolean_t ismcast;
+ int msgtype;
/*
* Timer should not be running at the point we go to send a packet.
@@ -985,27 +981,19 @@ send_pkt_internal(dhcp_smach_t *dsmp)
n_bytes = sendmsg(v6_sock_fd, &msg, 0);
} else {
- if (dsmp->dsm_using_dlpi) {
- n_bytes = dlpi_sendto(pif->pif_dlpi_hd, dpkt->pkt,
- dpkt->pkt_cur_len, &dsmp->dsm_send_dest.v4,
- pif->pif_daddr, pif->pif_dlen);
- /* dlpi_sendto calls putmsg */
- if (n_bytes == 0)
- n_bytes = dpkt->pkt_cur_len;
- } else {
- n_bytes = sendto(lif->lif_sock_ip_fd, dpkt->pkt,
- dpkt->pkt_cur_len, 0,
- (struct sockaddr *)&dsmp->dsm_send_dest.v4,
- sizeof (struct sockaddr_in));
- }
+ n_bytes = sendto(lif->lif_sock_ip_fd, dpkt->pkt,
+ dpkt->pkt_cur_len, 0,
+ (struct sockaddr *)&dsmp->dsm_send_dest.v4,
+ sizeof (struct sockaddr_in));
}
if (n_bytes != dpkt->pkt_cur_len) {
+ msgtype = (n_bytes == -1) ? MSG_ERR : MSG_WARNING;
if (dsmp->dsm_retrans_timer == -1)
- dhcpmsg(MSG_WARNING, "send_pkt_internal: cannot send "
+ dhcpmsg(msgtype, "send_pkt_internal: cannot send "
"%s packet to server", pkt_name);
else
- dhcpmsg(MSG_WARNING, "send_pkt_internal: cannot send "
+ dhcpmsg(msgtype, "send_pkt_internal: cannot send "
"%s packet to server (will retry in %u seconds)",
pkt_name, dsmp->dsm_send_timeout / MILLISEC);
return (B_FALSE);
@@ -1319,16 +1307,14 @@ sock_recvpkt(int fd, PKT_LIST *plp)
/*
* recv_pkt(): receives a single DHCP packet on a given file descriptor.
*
- * input: int: if not using dlpi, the file descriptor to receive the packet
+ * input: int: the file descriptor to receive the packet from
* int: the maximum packet size to allow
* boolean_t: B_TRUE for IPv6
- * boolean_t: B_TRUE if using DLPI
- * void *: if using DLPI, structure that has DLPI handle
* output: PKT_LIST *: the received packet
*/
PKT_LIST *
-recv_pkt(int fd, int mtu, boolean_t isv6, boolean_t isdlpi, dhcp_pif_t *arg)
+recv_pkt(int fd, int mtu, boolean_t isv6)
{
PKT_LIST *plp;
ssize_t retval;
@@ -1339,41 +1325,21 @@ recv_pkt(int fd, int mtu, boolean_t isv6, boolean_t isdlpi, dhcp_pif_t *arg)
return (NULL);
}
- if (isv6) {
- retval = sock_recvpkt(fd, plp);
-
- if (retval == -1) {
- dhcpmsg(MSG_ERR,
- "recv_pkt: recvfrom v6 failed, dropped");
- goto failure;
- }
+ retval = sock_recvpkt(fd, plp);
+ if (retval == -1) {
+ dhcpmsg(MSG_ERR, "recv_pkt: recvfrom v%d failed, dropped",
+ isv6 ? 6 : 4);
+ goto failure;
+ }
- plp->len = retval;
+ plp->len = retval;
+ if (isv6) {
if (retval < sizeof (dhcpv6_message_t)) {
dhcpmsg(MSG_WARNING, "recv_pkt: runt message");
goto failure;
}
} else {
- if (isdlpi) {
- dhcp_pif_t *pif = arg;
-
- retval = dlpi_recvfrom(pif->pif_dlpi_hd, plp->pkt, mtu,
- (struct sockaddr_in *)&plp->pktfrom,
- (struct sockaddr_in *)&plp->pktto);
- } else {
- retval = sock_recvpkt(fd, plp);
- }
-
- if (retval == -1) {
- dhcpmsg(MSG_ERR,
- "recv_pkt: %srecvfrom v4 failed, dropped",
- isdlpi ? "dlpi_" : "");
- goto failure;
- }
-
- plp->len = retval;
-
switch (dhcp_options_scan(plp, B_TRUE)) {
case DHCP_WRONG_MSG_TYPE:
@@ -1576,7 +1542,7 @@ dhcp_ip_default(void)
return (B_FALSE);
}
- if (iu_register_event(eh, v4_sock_fd, POLLIN, dhcp_acknak_common,
+ if (iu_register_event(eh, v4_sock_fd, POLLIN, dhcp_acknak_global,
NULL) == -1) {
dhcpmsg(MSG_WARNING, "dhcp_ip_default: cannot register to "
"receive IPv4 broadcasts");
@@ -1603,7 +1569,7 @@ dhcp_ip_default(void)
return (B_FALSE);
}
- if (iu_register_event(eh, v6_sock_fd, POLLIN, dhcp_acknak_common,
+ if (iu_register_event(eh, v6_sock_fd, POLLIN, dhcp_acknak_global,
NULL) == -1) {
dhcpmsg(MSG_WARNING, "dhcp_ip_default: cannot register to "
"receive IPv6 packets");
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.h b/usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.h
index 1556dced35..0ec64c4117 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.h
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.h
@@ -130,7 +130,7 @@ void *add_pkt_prl(dhcp_pkt_t *, dhcp_smach_t *);
boolean_t add_pkt_lif(dhcp_pkt_t *, dhcp_lif_t *, int, const char *);
void stop_pkt_retransmission(dhcp_smach_t *);
void retransmit_now(dhcp_smach_t *);
-PKT_LIST *recv_pkt(int, int, boolean_t, boolean_t, dhcp_pif_t *);
+PKT_LIST *recv_pkt(int, int, boolean_t);
boolean_t pkt_v4_match(uchar_t, dhcp_message_type_t);
void pkt_smach_enqueue(dhcp_smach_t *, PKT_LIST *);
boolean_t send_pkt(dhcp_smach_t *, dhcp_pkt_t *, in_addr_t,
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c
index 2206ca4b23..9782d1480c 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c
@@ -372,7 +372,7 @@ compute_points_v6(const PKT_LIST *pkt, const dhcp_smach_t *dsmp)
/*
* Look through the packet contents. Valid packets must have our
* client ID and a server ID, which has already been checked by
- * dhcp_acknak_lif. Bonus points for each option.
+ * dhcp_packet_lif. Bonus points for each option.
*/
/* One point for having a valid message. */
@@ -959,7 +959,7 @@ accept_v6_message(dhcp_smach_t *dsmp, PKT_LIST *plp, const char *pname,
}
/*
- * dhcp_acknak_common(): Processes reception of an ACK or NAK packet on the
+ * dhcp_acknak_global(): Processes reception of an ACK or NAK packet on the
* global socket -- broadcast packets for IPv4, all
* packets for DHCPv6.
*
@@ -973,7 +973,7 @@ accept_v6_message(dhcp_smach_t *dsmp, PKT_LIST *plp, const char *pname,
/* ARGSUSED */
void
-dhcp_acknak_common(iu_eh_t *ehp, int fd, short events, iu_event_id_t id,
+dhcp_acknak_global(iu_eh_t *ehp, int fd, short events, iu_event_id_t id,
void *arg)
{
PKT_LIST *plp;
@@ -983,14 +983,18 @@ dhcp_acknak_common(iu_eh_t *ehp, int fd, short events, iu_event_id_t id,
uint_t xid;
dhcp_smach_t *dsmp;
boolean_t isv6 = (fd == v6_sock_fd);
+ struct sockaddr_in sin;
+ const char *reason;
+ size_t sinlen = sizeof (sin);
+ int sock;
- plp = recv_pkt(fd, get_max_mtu(isv6), isv6, B_FALSE, NULL);
+ plp = recv_pkt(fd, get_max_mtu(isv6), isv6);
if (plp == NULL)
return;
pif = lookup_pif_by_index(plp->ifindex, isv6);
if (pif == NULL) {
- dhcpmsg(MSG_VERBOSE, "dhcp_acknak_common: ignored packet "
+ dhcpmsg(MSG_VERBOSE, "dhcp_acknak_global: ignored packet "
"received on v%d ifIndex %d", isv6 ? 6 : 4, plp->ifindex);
free_pkt_entry(plp);
return;
@@ -998,33 +1002,45 @@ dhcp_acknak_common(iu_eh_t *ehp, int fd, short events, iu_event_id_t id,
recv_type = pkt_recv_type(plp);
pname = pkt_type_to_string(recv_type, isv6);
- if (!isv6 && !pkt_v4_match(recv_type, DHCP_PACK|DHCP_PNAK)) {
- dhcpmsg(MSG_VERBOSE, "dhcp_acknak_common: ignored %s packet "
- "received via broadcast on %s", pname, pif->pif_name);
- free_pkt_entry(plp);
- return;
- }
/*
- * Find the corresponding state machine not using DLPI.
+ * Find the corresponding state machine.
*
* Note that DHCPv6 Reconfigure would be special: it's not the reply to
* any transaction, and thus we would need to search on transaction ID
- * zero (all state machines) to find the match. However, Reconfigure
+ * zero (all state machines) to find the match. However, Reconfigure
* is not yet supported.
*/
xid = pkt_get_xid(plp->pkt, isv6);
+ if (!isv6 && !pkt_v4_match(recv_type, DHCP_PACK|DHCP_PNAK)) {
+ reason = "not ACK or NAK";
+ goto drop;
+ }
+
for (dsmp = lookup_smach_by_xid(xid, NULL, isv6); dsmp != NULL;
dsmp = lookup_smach_by_xid(xid, dsmp, isv6)) {
if (dsmp->dsm_lif->lif_pif == pif)
break;
}
- if (dsmp == NULL || dsmp->dsm_using_dlpi) {
- dhcpmsg(MSG_VERBOSE, "dhcp_acknak_common: ignored %s packet "
- "received via broadcast %s; %s", pname, pif->pif_name,
- dsmp == NULL ? "unknown state machine" : "not using DLPI");
- free_pkt_entry(plp);
- return;
+
+ if (dsmp == NULL) {
+ reason = "unknown state machine";
+ goto drop;
+ }
+
+ /*
+ * For IPv4, most packets will be handled by dhcp_packet_lif(). The
+ * only exceptions are broadcast packets sent when lif_sock_ip_fd has
+ * bound to something other than INADDR_ANY.
+ */
+ if (!isv6) {
+ sock = dsmp->dsm_lif->lif_sock_ip_fd;
+
+ if (getsockname(sock, (struct sockaddr *)&sin, &sinlen) != -1 &&
+ sin.sin_addr.s_addr == INADDR_ANY) {
+ reason = "handled by lif_sock_ip_fd";
+ goto drop;
+ }
}
/*
@@ -1035,6 +1051,12 @@ dhcp_acknak_common(iu_eh_t *ehp, int fd, short events, iu_event_id_t id,
accept_v6_message(dsmp, plp, pname, recv_type);
else
accept_v4_acknak(dsmp, plp);
+ return;
+drop:
+ dhcpmsg(MSG_VERBOSE, "dhcp_acknak_global: ignored v%d %s packet for %s "
+ "received on global socket: %s", isv6 ? 6 : 4, pname, pif->pif_name,
+ reason);
+ free_pkt_entry(plp);
}
/*
@@ -1062,11 +1084,11 @@ request_failed(dhcp_smach_t *dsmp)
}
/*
- * dhcp_acknak_lif(): Processes reception of an ACK or NAK packet on a given
- * logical interface for IPv4 (only).
+ * dhcp_packet_lif(): Processes reception of an ACK, NAK, or OFFER packet on
+ * a given logical interface for IPv4 (only).
*
* input: iu_eh_t *: unused
- * int: the global file descriptor the ACK/NAK arrived on
+ * int: the file descriptor the packet arrived on
* short: unused
* iu_event_id_t: the id of this event callback with the handler
* void *: pointer to logical interface receiving message
@@ -1075,7 +1097,7 @@ request_failed(dhcp_smach_t *dsmp)
/* ARGSUSED */
void
-dhcp_acknak_lif(iu_eh_t *ehp, int fd, short events, iu_event_id_t id,
+dhcp_packet_lif(iu_eh_t *ehp, int fd, short events, iu_event_id_t id,
void *arg)
{
dhcp_lif_t *lif = arg;
@@ -1085,21 +1107,22 @@ dhcp_acknak_lif(iu_eh_t *ehp, int fd, short events, iu_event_id_t id,
uint_t xid;
dhcp_smach_t *dsmp;
- if ((plp = recv_pkt(fd, lif->lif_max, B_FALSE, B_FALSE, NULL)) == NULL)
+ if ((plp = recv_pkt(fd, lif->lif_max, B_FALSE)) == NULL)
return;
recv_type = pkt_recv_type(plp);
pname = pkt_type_to_string(recv_type, B_FALSE);
- if (!pkt_v4_match(recv_type, DHCP_PACK | DHCP_PNAK)) {
- dhcpmsg(MSG_VERBOSE, "dhcp_acknak_lif: ignored v4 %s packet "
+ if (!pkt_v4_match(recv_type,
+ DHCP_PACK | DHCP_PNAK | DHCP_PUNTYPED | DHCP_POFFER)) {
+ dhcpmsg(MSG_VERBOSE, "dhcp_packet_lif: ignored v4 %s packet "
"received via LIF %s", pname, lif->lif_name);
free_pkt_entry(plp);
return;
}
/*
- * Find the corresponding state machine not using DLPI.
+ * Find the corresponding state machine.
*/
xid = pkt_get_xid(plp->pkt, B_FALSE);
for (dsmp = lookup_smach_by_xid(xid, NULL, B_FALSE); dsmp != NULL;
@@ -1107,19 +1130,31 @@ dhcp_acknak_lif(iu_eh_t *ehp, int fd, short events, iu_event_id_t id,
if (dsmp->dsm_lif == lif)
break;
}
- if (dsmp == NULL || dsmp->dsm_using_dlpi) {
- dhcpmsg(MSG_VERBOSE, "dhcp_acknak_lif: ignored %s packet xid "
- "%x received via LIF %s; %s", pname, xid, lif->lif_name,
- dsmp == NULL ? "unknown state machine" : "not using DLPI");
- free_pkt_entry(plp);
- return;
- }
- /*
- * We've got a packet; make sure it's acceptable and cancel the REQUEST
- * retransmissions.
- */
- accept_v4_acknak(dsmp, plp);
+ if (dsmp == NULL)
+ goto drop;
+
+ if (pkt_v4_match(recv_type, DHCP_PACK|DHCP_PNAK)) {
+ /*
+ * We've got an ACK/NAK; make sure it's acceptable and cancel
+ * the REQUEST retransmissions.
+ */
+ accept_v4_acknak(dsmp, plp);
+ } else {
+ if (is_bound_state(dsmp->dsm_state))
+ goto drop;
+ /*
+ * Must be an OFFER or a BOOTP message: enqueue it for later
+ * processing by select_best().
+ */
+ pkt_smach_enqueue(dsmp, plp);
+ }
+ return;
+drop:
+ dhcpmsg(MSG_VERBOSE, "dhcp_packet_lif: ignored %s packet xid "
+ "%x received via LIF %s; %s", pname, xid, lif->lif_name,
+ dsmp == NULL ? "unknown state machine" : "bound");
+ free_pkt_entry(plp);
}
/*
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/select.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/select.c
index d0ebdb0a6e..de3a21e8f8 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/select.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/select.c
@@ -235,102 +235,6 @@ failed:
}
/*
- * dhcp_collect_dlpi(): collects incoming OFFERs, ACKs, and NAKs via DLPI.
- *
- * input: iu_eh_t *: unused
- * int: unused
- * short: unused
- * iu_event_id_t: the id of this event callback with the handler
- * void *: the physical interface that received the message
- * output: void
- */
-
-/* ARGSUSED */
-void
-dhcp_collect_dlpi(iu_eh_t *eh, int fd, short events, iu_event_id_t id,
- void *arg)
-{
- dhcp_pif_t *pif = arg;
- PKT_LIST *plp;
- uchar_t recv_type;
- const char *pname;
- dhcp_smach_t *dsmp;
- uint_t xid;
-
- if ((plp = recv_pkt(fd, pif->pif_max, B_FALSE, B_TRUE, pif)) == NULL)
- return;
-
- recv_type = pkt_recv_type(plp);
- pname = pkt_type_to_string(recv_type, B_FALSE);
-
- /*
- * DHCP_PUNTYPED messages are BOOTP server responses.
- */
- if (!pkt_v4_match(recv_type,
- DHCP_PACK | DHCP_PNAK | DHCP_POFFER | DHCP_PUNTYPED)) {
- dhcpmsg(MSG_VERBOSE, "dhcp_collect_dlpi: ignored %s packet "
- "received via DLPI on %s", pname, pif->pif_name);
- free_pkt_entry(plp);
- return;
- }
-
- /*
- * Loop through the state machines that match on XID to find one that's
- * interested in this offer. If there are none, then discard.
- */
- xid = pkt_get_xid(plp->pkt, B_FALSE);
- for (dsmp = lookup_smach_by_xid(xid, NULL, B_FALSE); dsmp != NULL;
- dsmp = lookup_smach_by_xid(xid, dsmp, B_FALSE)) {
-
- /*
- * Find state machine on correct interface.
- */
- if (dsmp->dsm_lif->lif_pif == pif)
- break;
- }
-
- if (dsmp == NULL) {
- dhcpmsg(MSG_VERBOSE, "dhcp_collect_dlpi: no matching state "
- "machine for %s packet XID %#x received via DLPI on %s",
- pname, xid, pif->pif_name);
- free_pkt_entry(plp);
- return;
- }
-
- /*
- * Ignore state machines that aren't looking for DLPI messages.
- */
- if (!dsmp->dsm_using_dlpi) {
- dhcpmsg(MSG_VERBOSE, "dhcp_collect_dlpi: ignore state "
- "machine for %s packet XID %#x received via DLPI on %s",
- pname, xid, pif->pif_name);
- free_pkt_entry(plp);
- return;
- }
-
- /* See also accept_v[46]_message; account for processed packets. */
- dsmp->dsm_received++;
-
- if (pkt_v4_match(recv_type, DHCP_PACK)) {
- if (!dhcp_bound(dsmp, plp)) {
- dhcpmsg(MSG_WARNING, "dhcp_collect_dlpi: dhcp_bound "
- "failed for %s", dsmp->dsm_name);
- dhcp_restart(dsmp);
- return;
- }
- dhcpmsg(MSG_VERBOSE, "dhcp_collect_dlpi: %s on %s",
- pname, dsmp->dsm_name);
- } else if (pkt_v4_match(recv_type, DHCP_PNAK)) {
- dhcpmsg(MSG_VERBOSE, "dhcp_collect_dlpi: %s on %s",
- pname, dsmp->dsm_name);
- free_pkt_entry(plp);
- dhcp_restart(dsmp);
- } else {
- pkt_smach_enqueue(dsmp, plp);
- }
-}
-
-/*
* stop_selecting(): decides when to stop retransmitting DISCOVERs -- only when
* abandoning the state machine. For DHCPv6, this timer may
* go off before the offer wait timer. If so, then this is a
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.c
index c26e6c07b2..63e134fc8f 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.c
@@ -149,18 +149,16 @@ insert_smach(dhcp_lif_t *lif, int *error)
&dsmp->dsm_server);
/*
- * With IPv4 DHCP, we start off doing our I/O via DLPI, so open
- * that up now.
+ * With IPv4 DHCP, we use a socket per lif.
*/
- if (!open_dlpi_pif(lif->lif_pif)) {
- dhcpmsg(MSG_ERR, "unable to open DLPI for %s",
+ if (!open_ip_lif(lif, INADDR_ANY)) {
+ dhcpmsg(MSG_ERR, "unable to open socket for %s",
lif->lif_name);
/* This will also dispose of the LIF */
release_smach(dsmp);
*error = DHCP_IPC_E_SOCKET;
return (NULL);
}
- dsmp->dsm_using_dlpi = B_TRUE;
}
dsmp->dsm_retrans_timer = -1;
dsmp->dsm_offer_timer = -1;
@@ -657,6 +655,20 @@ finished_smach(dhcp_smach_t *dsmp, int error)
}
/*
+ * is_bound_state(): checks if a state indicates the client is bound
+ *
+ * input: DHCPSTATE: the state to check
+ * output: boolean_t: B_TRUE if the state is bound, B_FALSE if not
+ */
+
+boolean_t
+is_bound_state(DHCPSTATE state)
+{
+ return (state == BOUND || state == REBINDING || state == INFORMATION ||
+ state == RELEASING || state == INFORM_SENT || state == RENEWING);
+}
+
+/*
* set_smach_state(): changes state and updates I/O
*
* input: dhcp_smach_t *: the state machine to change
@@ -667,35 +679,33 @@ finished_smach(dhcp_smach_t *dsmp, int error)
boolean_t
set_smach_state(dhcp_smach_t *dsmp, DHCPSTATE state)
{
- if (dsmp->dsm_state != state) {
- boolean_t is_bound;
+ dhcp_lif_t *lif = dsmp->dsm_lif;
+ if (dsmp->dsm_state != state) {
dhcpmsg(MSG_DEBUG,
"set_smach_state: changing from %s to %s on %s",
dhcp_state_to_string(dsmp->dsm_state),
dhcp_state_to_string(state), dsmp->dsm_name);
+ /*
+ * For IPv4, when we're in a bound state our socket must be
+ * bound to our address. Otherwise, our socket must be bound
+ * to INADDR_ANY. For IPv6, no such change is necessary.
+ */
if (!dsmp->dsm_isv6) {
- /*
- * When we're in a bound state for IPv4, we receive our
- * packets through our LIF. Otherwise, we receive them
- * through DLPI. Make sure the right one is connected.
- * For IPv6, no such change is necessary.
- */
- is_bound = (state == BOUND || state == REBINDING ||
- state == RENEWING || state == RELEASING ||
- state == INFORM_SENT || state == INFORMATION);
- if (dsmp->dsm_using_dlpi && is_bound) {
- if (!open_ip_lif(dsmp->dsm_lif))
- return (B_FALSE);
- dsmp->dsm_using_dlpi = B_FALSE;
- close_dlpi_pif(dsmp->dsm_lif->lif_pif);
- }
- if (!dsmp->dsm_using_dlpi && !is_bound) {
- if (!open_dlpi_pif(dsmp->dsm_lif->lif_pif))
- return (B_FALSE);
- dsmp->dsm_using_dlpi = B_TRUE;
- close_ip_lif(dsmp->dsm_lif);
+ if (is_bound_state(dsmp->dsm_state)) {
+ if (!is_bound_state(state)) {
+ close_ip_lif(lif);
+ if (!open_ip_lif(lif, INADDR_ANY))
+ return (B_FALSE);
+ }
+ } else {
+ if (is_bound_state(state)) {
+ close_ip_lif(lif);
+ if (!open_ip_lif(lif,
+ ntohl(lif->lif_addr)))
+ return (B_FALSE);
+ }
}
}
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.h b/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.h
index 02209ce243..c36232264e 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.h
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.h
@@ -72,8 +72,6 @@ struct dhcp_smach_s {
uint_t dsm_lif_wait; /* LIFs waiting on DAD */
uint_t dsm_lif_down; /* LIFs failed */
- boolean_t dsm_using_dlpi;
-
/*
* each state machine can have at most one pending asynchronous
* action, which is represented in a `struct async_action'.
@@ -258,9 +256,8 @@ struct dhcp_lease_s {
};
/* The IU event callback functions */
-iu_eh_callback_t dhcp_acknak_common;
-iu_eh_callback_t dhcp_acknak_lif;
-iu_eh_callback_t dhcp_collect_dlpi;
+iu_eh_callback_t dhcp_acknak_global;
+iu_eh_callback_t dhcp_packet_lif;
/* Common state-machine related routines throughout dhcpagent */
boolean_t dhcp_adopt(void);
@@ -311,6 +308,7 @@ boolean_t schedule_smach_timer(dhcp_smach_t *, int, uint32_t,
void cancel_offer_timer(dhcp_smach_t *);
void discard_default_routes(dhcp_smach_t *);
void remove_default_routes(dhcp_smach_t *);
+boolean_t is_bound_state(DHCPSTATE);
/* Lease-related support functions in states.c */
dhcp_lease_t *insert_lease(dhcp_smach_t *);
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/defs.h b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/defs.h
index 5b3ba902cd..2467b7cd58 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/defs.h
+++ b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 1983, 1988, 1993
@@ -801,6 +801,8 @@ extern void end_md5_auth(struct ws_buf *, struct auth *);
extern void rip_mcast_on(struct interface *);
extern void rip_mcast_off(struct interface *);
extern void trace_dump();
+extern int sendtoif(int, const void *, uint_t, uint_t, struct sockaddr_in *,
+ uint_t);
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/output.c b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/output.c
index ae212db11b..c4dd637efd 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/output.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/output.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 1983, 1988, 1993
@@ -40,6 +40,7 @@
#include "defs.h"
#include <md5.h>
+#include <alloca.h>
uint_t update_seqno;
@@ -109,7 +110,6 @@ output(enum output_type type,
int res;
int ifindex;
struct in_addr addr;
- static int rip_sock_ifindex;
sin = *dst;
if (sin.sin_port == 0)
@@ -148,22 +148,12 @@ output(enum output_type type,
}
/*
- * Note that we intentionally reset IP_XMIT_IF to zero if
- * we're doing multicast. The kernel ignores IP_MULTICAST_IF
- * if IP_XMIT_IF is set, and we can't deal with alias source
- * addresses without it.
+ * IP_PKTINFO overrides IP_MULTICAST_IF, so we don't set ifindex
+ * for multicast traffic.
*/
ifindex = (type != OUT_MULTICAST && type != OUT_QUERY &&
ifp != NULL && ifp->int_phys != NULL) ?
ifp->int_phys->phyi_index : 0;
- if (rip_sock_ifindex != ifindex) {
- if (setsockopt(rip_sock, IPPROTO_IP, IP_XMIT_IF, &ifindex,
- sizeof (ifindex)) == -1) {
- LOGERR("setsockopt(rip_sock, IP_XMIT_IF)");
- return (-1);
- }
- rip_sock_ifindex = ifindex;
- }
if (rip_sock_interface != ifp) {
/*
@@ -186,10 +176,8 @@ output(enum output_type type,
trace_rip(msg, "to", &sin, ifp, buf, size);
- res = sendto(rip_sock, buf, size, flags,
- (struct sockaddr *)&sin, sizeof (sin));
- if (res < 0 &&
- (ifp == NULL || !(ifp->int_state & IS_BROKE))) {
+ res = sendtoif(rip_sock, buf, size, flags, &sin, ifindex);
+ if (res < 0 && (ifp == NULL || !(ifp->int_state & IS_BROKE))) {
writelog(LOG_WARNING, "%s sendto(%s%s%s.%d): %s", msg,
ifp != NULL ? ifp->int_name : "",
ifp != NULL ? ", " : "",
@@ -201,6 +189,55 @@ output(enum output_type type,
return (res);
}
+/*
+ * Semantically identical to sendto(), but sends the message through a
+ * specific interface (if ifindex is non-zero) using IP_PKTINFO.
+ */
+int
+sendtoif(int fd, const void *buf, uint_t bufsize, uint_t flags,
+ struct sockaddr_in *sinp, uint_t ifindex)
+{
+ struct iovec iov;
+ struct msghdr msg;
+ struct cmsghdr *cmsgp;
+ struct in_pktinfo *ipip;
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = bufsize;
+
+ (void) memset(&msg, 0, sizeof (struct msghdr));
+ msg.msg_name = (struct sockaddr *)sinp;
+ msg.msg_namelen = sizeof (struct sockaddr_in);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ if (ifindex != 0) {
+ /*
+ * We can't precisely predict the alignment padding we'll
+ * need, so we allocate the maximum alignment and then
+ * use CMSG_NXTHDR() to fix it up at the end.
+ */
+ msg.msg_controllen = sizeof (*cmsgp) + _MAX_ALIGNMENT +
+ sizeof (*ipip) + _MAX_ALIGNMENT + sizeof (*cmsgp);
+ msg.msg_control = alloca(msg.msg_controllen);
+
+ cmsgp = CMSG_FIRSTHDR(&msg);
+ ipip = (void *)CMSG_DATA(cmsgp);
+ (void) memset(ipip, 0, sizeof (struct in_pktinfo));
+ ipip->ipi_ifindex = ifindex;
+ cmsgp->cmsg_len = (caddr_t)(ipip + 1) - (caddr_t)cmsgp;
+ cmsgp->cmsg_type = IP_PKTINFO;
+ cmsgp->cmsg_level = IPPROTO_IP;
+
+ /*
+ * Correct the control message length.
+ */
+ cmsgp = CMSG_NXTHDR(&msg, cmsgp);
+ msg.msg_controllen = (caddr_t)cmsgp - (caddr_t)msg.msg_control;
+ }
+
+ return (sendmsg(fd, &msg, flags));
+}
/*
* Find the first key for a packet to send.
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/rdisc.c b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/rdisc.c
index 6e572ccc41..d7325b3393 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/rdisc.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/rdisc.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 1995
@@ -663,9 +663,9 @@ rdisc_sort(void)
new_drp->dr_life > drp->dr_life))))) ||
((new_st & IS_SICK) &&
!(drp->dr_ifp->int_state & IS_SICK))) {
- new_drp = drp;
- new_st = drp->dr_ifp->int_state;
- new_pref = drp->dr_pref;
+ new_drp = drp;
+ new_st = drp->dr_ifp->int_state;
+ new_pref = drp->dr_pref;
}
}
@@ -1010,7 +1010,7 @@ send_rdisc(union ad_u *p,
struct sockaddr_in sin;
int flags = 0;
const char *msg;
- int ifindex;
+ int ifindex = 0;
struct in_addr addr;
/*
@@ -1052,15 +1052,11 @@ send_rdisc(union ad_u *p,
if (rdisc_sock < 0)
get_rdisc_sock();
+ /* select the right interface. */
+ ifindex = (type != mcast && ifp->int_phys != NULL) ?
+ ifp->int_phys->phyi_index : 0;
+
if (rdisc_sock_interface != ifp) {
- /* select the right interface. */
- ifindex = (type != mcast && ifp->int_phys != NULL) ?
- ifp->int_phys->phyi_index : 0;
- if (setsockopt(rdisc_sock, IPPROTO_IP, IP_XMIT_IF, &ifindex,
- sizeof (ifindex)) == -1) {
- LOGERR("setsockopt(rdisc_sock, IP_XMIT_IF)");
- return;
- }
/*
* For multicast, we have to choose the source
* address. This is either the local address
@@ -1070,7 +1066,7 @@ send_rdisc(union ad_u *p,
ifp->int_dstaddr : ifp->int_addr;
if (type == mcast &&
setsockopt(rdisc_sock, IPPROTO_IP, IP_MULTICAST_IF, &addr,
- sizeof (addr)) == -1) {
+ sizeof (addr)) == -1) {
LOGERR("setsockopt(rdisc_sock, IP_MULTICAST_IF)");
return;
}
@@ -1079,8 +1075,7 @@ send_rdisc(union ad_u *p,
trace_rdisc(msg, ifp->int_addr, sin.sin_addr.s_addr, ifp, p, p_size);
- if (0 > sendto(rdisc_sock, p, p_size, flags,
- (struct sockaddr *)&sin, sizeof (sin))) {
+ if (0 > sendtoif(rdisc_sock, p, p_size, flags, &sin, ifindex)) {
if (!(ifp->int_state & IS_BROKE))
writelog(LOG_WARNING, "sendto(%s%s%s): %s",
ifp->int_name, ", ",
@@ -1294,7 +1289,7 @@ read_d(void)
cc = recvmsg(rdisc_sock, &msg, 0);
if (cc <= 0) {
if (cc < 0 && errno != EWOULDBLOCK)
- LOGERR("recvmsg(rdisc_sock)");
+ LOGERR("recvmsg(rdisc_sock)");
break;
}
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h
index 9e828964a4..05e121a37c 100644
--- a/usr/src/uts/common/inet/ip.h
+++ b/usr/src/uts/common/inet/ip.h
@@ -622,9 +622,9 @@ typedef struct ip_m_s {
#define IRE_MARK_HIDDEN 0x0004 /* Typically Used by in.mpathd */
/*
- * ire with IRE_MARK_NOADD is created in ip_newroute_ipif, when outgoing
- * interface is specified by IP_XMIT_IF socket option. This ire is not
- * added in IRE_CACHE.
+ * An IRE with IRE_MARK_NOADD is created in ip_newroute_ipif when the outgoing
+ * interface is specified by e.g. IP_PKTINFO. The IRE is not added to the IRE
+ * cache table.
*/
#define IRE_MARK_NOADD 0x0008 /* Mark not to add ire in cache */
@@ -1031,7 +1031,6 @@ typedef struct conn_s conn_t;
* ipc_acking_unbind conn_acking_unbind
* ipc_pad_to_bit_31 conn_pad_to_bit_31
*
- * ipc_xmit_if_ill conn_xmit_if_ill
* ipc_nofailover_ill conn_nofailover_ill
*
* ipc_proto conn_proto
@@ -1048,7 +1047,6 @@ typedef struct conn_s conn_t;
* ipc_multicast_ill conn_multicast_ill
* ipc_orig_bound_ifindex conn_orig_bound_ifindex
* ipc_orig_multicast_ifindex conn_orig_multicast_ifindex
- * ipc_orig_xmit_ifindex conn_orig_xmit_ifindex
* ipc_drain_next conn_drain_next
* ipc_drain_prev conn_drain_prev
* ipc_idl conn_idl
@@ -1842,7 +1840,7 @@ typedef struct ill_s {
ill_arp_closing : 1,
ill_arp_bringup_pending : 1,
- ill_mtu_userspecified : 1, /* SIOCSLNKINFO has set the mtu */
+ ill_mtu_userspecified : 1, /* SIOCSLIFLNKINFO has set the mtu */
ill_arp_extend : 1, /* ARP has DAD extensions */
ill_pad_bit_31 : 25;
@@ -1962,6 +1960,7 @@ typedef struct ill_s {
boolean_t ill_trace_disable; /* True when alloc fails */
zoneid_t ill_zoneid;
ip_stack_t *ill_ipst; /* Corresponds to a netstack_hold */
+ uint32_t ill_dhcpinit; /* IP_DHCPINIT_IFs for ill */
} ill_t;
/*
@@ -2063,6 +2062,7 @@ typedef struct ill_s {
* ill_nce_cnt ill_lock ill_lock
* ill_trace ill_lock ill_lock
* ill_usesrc_grp_next ill_g_usesrc_lock ill_g_usesrc_lock
+ * ill_dhcpinit atomics atomics
*/
/*
diff --git a/usr/src/uts/common/inet/ip/icmp.c b/usr/src/uts/common/inet/ip/icmp.c
index e8e8c0a7c5..8cf74a2366 100644
--- a/usr/src/uts/common/inet/ip/icmp.c
+++ b/usr/src/uts/common/inet/ip/icmp.c
@@ -1766,9 +1766,6 @@ icmp_opt_get_locked(queue_t *q, int level, int name, uchar_t *ptr)
case IP_UNSPEC_SRC:
*ptr = icmp->icmp_unspec_source;
break; /* goto sizeof (int) option return */
- case IP_XMIT_IF:
- *i1 = icmp->icmp_xmit_if;
- break; /* goto sizeof (int) option return */
case IP_RECVIF:
*ptr = icmp->icmp_recvif;
break; /* goto sizeof (int) option return */
@@ -1956,8 +1953,7 @@ icmp_opt_get_locked(queue_t *q, int level, int name, uchar_t *ptr)
return (0);
return (ip_fill_mtuinfo(&icmp->icmp_v6dst, 0,
- (struct ip6_mtuinfo *)ptr,
- is->is_netstack));
+ (struct ip6_mtuinfo *)ptr, is->is_netstack));
case IPV6_TCLASS:
if (ipp->ipp_fields & IPPF_TCLASS)
*i1 = ipp->ipp_tclass;
@@ -2317,10 +2313,6 @@ icmp_opt_set_locked(queue_t *q, uint_t optset_context, int level, int name,
if (!checkonly)
icmp->icmp_unspec_source = onoff;
break;
- case IP_XMIT_IF:
- if (!checkonly)
- icmp->icmp_xmit_if = *i1;
- break;
case IP_RECVIF:
if (!checkonly)
icmp->icmp_recvif = onoff;
@@ -5539,8 +5531,7 @@ icmp_unitdata_opt_process(queue_t *q, mblk_t *mp, int *errorp,
void
icmp_ddi_init(void)
{
- icmp_max_optsize =
- optcom_max_optsize(icmp_opt_obj.odb_opt_des_arr,
+ icmp_max_optsize = optcom_max_optsize(icmp_opt_obj.odb_opt_des_arr,
icmp_opt_obj.odb_opt_arr_cnt);
/*
diff --git a/usr/src/uts/common/inet/ip/icmp_opt_data.c b/usr/src/uts/common/inet/ip/icmp_opt_data.c
index b4a20417ad..49952d9166 100644
--- a/usr/src/uts/common/inet/ip/icmp_opt_data.c
+++ b/usr/src/uts/common/inet/ip/icmp_opt_data.c
@@ -140,9 +140,6 @@ opdes_t icmp_opt_arr[] = {
{ IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_PASSNEXT,
sizeof (int), 0 /* no ifindex */ },
-{ IP_XMIT_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_PASSNEXT,
- sizeof (int), 0 /* no ifindex */ },
-
{ IP_DONTFAILOVER_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_PASSNEXT,
sizeof (struct in_addr), 0 /* not initialized */ },
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index 05b22eacf3..5eee449379 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -1294,7 +1294,9 @@ ip_ioctl_cmd_t ip_ndx_ioctl_table[] = {
/* 181 */ { SIOCSIPMSFILTER, sizeof (struct ip_msfilter), IPI_WR,
MSFILT_CMD, ip_sioctl_msfilter, NULL },
/* 182 */ { SIOCSIPMPFAILBACK, sizeof (int), IPI_PRIV, MISC_CMD,
- ip_sioctl_set_ipmpfailback, NULL }
+ ip_sioctl_set_ipmpfailback, NULL },
+ /* SIOCSENABLESDP is handled by SDP */
+ /* 183 */ { IPI_DONTCARE /* SIOCSENABLESDP */, 0, 0, 0, NULL, NULL },
};
int ip_ndx_ioctl_count = sizeof (ip_ndx_ioctl_table) / sizeof (ip_ioctl_cmd_t);
@@ -5526,6 +5528,11 @@ ip_quiesce_conn(conn_t *connp)
drain_cleanup_reqd = B_TRUE;
if (connp->conn_oper_pending_ill != NULL)
conn_ioctl_cleanup_reqd = B_TRUE;
+ if (connp->conn_dhcpinit_ill != NULL) {
+ ASSERT(connp->conn_dhcpinit_ill->ill_dhcpinit != 0);
+ atomic_dec_32(&connp->conn_dhcpinit_ill->ill_dhcpinit);
+ connp->conn_dhcpinit_ill = NULL;
+ }
if (connp->conn_ilg_inuse != 0)
ilg_cleanup_reqd = B_TRUE;
mutex_exit(&connp->conn_lock);
@@ -7792,6 +7799,7 @@ ip_newroute(queue_t *q, mblk_t *mp, ipaddr_t dst, conn_t *connp,
MULTIRT_CACHEGW | MULTIRT_USESTAMP | MULTIRT_SETSTAMP;
boolean_t multirt_is_resolvable;
boolean_t multirt_resolve_next;
+ boolean_t unspec_src;
boolean_t do_attach_ill = B_FALSE;
boolean_t ip_nexthop = B_FALSE;
tsol_ire_gw_secattr_t *attrp = NULL;
@@ -8200,7 +8208,11 @@ ip_newroute(queue_t *q, mblk_t *mp, ipaddr_t dst, conn_t *connp,
src_ipif = ipif_lookup_addr(sire->ire_src_addr, NULL,
zoneid, NULL, NULL, NULL, NULL, ipst);
}
- if (src_ipif == NULL) {
+
+ unspec_src = (connp != NULL && connp->conn_unspec_src);
+
+ if (src_ipif == NULL &&
+ (!unspec_src || ipha->ipha_src != INADDR_ANY)) {
ire_marks |= IRE_MARK_USESRC_CHECK;
if ((dst_ill->ill_group != NULL) ||
(ire->ire_ipif->ipif_flags & IPIF_DEPRECATED) ||
@@ -8257,10 +8269,9 @@ ip_newroute(queue_t *q, mblk_t *mp, ipaddr_t dst, conn_t *connp,
* NOTE : ip_newroute_v6 does not have this piece of code as
* it uses ip6i to store this information.
*/
- if (ipha->ipha_src == INADDR_ANY &&
- (connp == NULL || !connp->conn_unspec_src)) {
+ if (ipha->ipha_src == INADDR_ANY && !unspec_src)
ipha->ipha_src = src_ipif->ipif_src_addr;
- }
+
if (ip_debug > 3) {
/* ip2dbg */
pr_addr_dbg("ip_newroute: first hop %s\n",
@@ -8963,7 +8974,7 @@ ip_opt_info_t zero_info;
* ip_rput_forward_multicast whenever we need to send
* out a packet to a destination address for which we do not have specific
* routing information. It is used when the packet will be sent out
- * on a specific interface. It is also called by ip_wput() when IP_XMIT_IF
+ * on a specific interface. It is also called by ip_wput() when IP_BOUND_IF
* socket option is set or icmp error message wants to go out on a particular
* interface for a unicast packet.
*
@@ -9005,6 +9016,7 @@ ip_newroute_ipif(queue_t *q, mblk_t *mp, ipif_t *ipif, ipaddr_t dst,
ire_t *fire = NULL;
mblk_t *copy_mp = NULL;
boolean_t multirt_resolve_next;
+ boolean_t unspec_src;
ipaddr_t ipha_dst;
ip_stack_t *ipst = ipif->ipif_ill->ill_ipst;
@@ -9105,14 +9117,6 @@ ip_newroute_ipif(queue_t *q, mblk_t *mp, ipif_t *ipif, ipaddr_t dst,
ASSERT(dst_ill == attach_ill);
} else {
/*
- * If this is set by IP_XMIT_IF, then make sure that
- * ipif is pointing to the same ill as the IP_XMIT_IF
- * specified ill.
- */
- ASSERT((connp == NULL) ||
- (connp->conn_xmit_if_ill == NULL) ||
- (connp->conn_xmit_if_ill == ipif->ipif_ill));
- /*
* If the interface belongs to an interface group,
* make sure the next possible interface in the group
* is used. This encourages load spreading among
@@ -9163,10 +9167,15 @@ ip_newroute_ipif(queue_t *q, mblk_t *mp, ipif_t *ipif, ipaddr_t dst,
src_ipif = ipif_lookup_addr(fire->ire_src_addr, NULL,
zoneid, NULL, NULL, NULL, NULL, ipst);
}
- if (((ipif->ipif_flags & IPIF_DEPRECATED) ||
+
+ unspec_src = (connp != NULL && connp->conn_unspec_src);
+
+ if (((!ipif->ipif_isv6 && ipif->ipif_lcl_addr == INADDR_ANY) ||
+ (ipif->ipif_flags & (IPIF_DEPRECATED|IPIF_UP)) != IPIF_UP ||
(connp != NULL && ipif->ipif_zoneid != zoneid &&
ipif->ipif_zoneid != ALL_ZONES)) &&
- (src_ipif == NULL)) {
+ (src_ipif == NULL) &&
+ (!unspec_src || ipha->ipha_src != INADDR_ANY)) {
src_ipif = ipif_select_source(dst_ill, dst, zoneid);
if (src_ipif == NULL) {
if (ip_debug > 2) {
@@ -9192,19 +9201,17 @@ ip_newroute_ipif(queue_t *q, mblk_t *mp, ipif_t *ipif, ipaddr_t dst,
* Assign a source address while we have the conn.
* We can't have ip_wput_ire pick a source address when the
* packet returns from arp since conn_unspec_src might be set
- * and we loose the conn when going through arp.
+ * and we lose the conn when going through arp.
*/
- if (ipha->ipha_src == INADDR_ANY &&
- (connp == NULL || !connp->conn_unspec_src)) {
+ if (ipha->ipha_src == INADDR_ANY && !unspec_src)
ipha->ipha_src = src_ipif->ipif_src_addr;
- }
/*
- * In the case of IP_XMIT_IF, it is possible that the
- * outgoing interface does not have an interface ire.
+ * In the case of IP_BOUND_IF and IP_PKTINFO, it is possible
+ * that the outgoing interface does not have an interface ire.
*/
if (CLASSD(ipha_dst) && (connp == NULL ||
- connp->conn_xmit_if_ill == NULL) &&
+ connp->conn_outgoing_ill == NULL) &&
infop->ip_opt_ill_index == 0) {
/* ipif_to_ire returns an held ire */
ire = ipif_to_ire(ipif);
@@ -9250,12 +9257,12 @@ ip_newroute_ipif(queue_t *q, mblk_t *mp, ipif_t *ipif, ipaddr_t dst,
}
} else {
ASSERT((connp == NULL) ||
- (connp->conn_xmit_if_ill != NULL) ||
+ (connp->conn_outgoing_ill != NULL) ||
(connp->conn_dontroute) ||
infop->ip_opt_ill_index != 0);
/*
* The only ways we can come here are:
- * 1) IP_XMIT_IF socket option is set
+ * 1) IP_BOUND_IF socket option is set
* 2) SO_DONTROUTE socket option is set
* 3) IP_PKTINFO option is passed in as ancillary data.
* In all cases, the new ire will not be added
@@ -10493,19 +10500,6 @@ setit:
0 : ifindex;
break;
- case IP_XMIT_IF:
- /*
- * Similar to IP_BOUND_IF, but this only
- * determines the outgoing interface for
- * unicast packets. Also no IRE_CACHE entry
- * is added for the destination of the
- * outgoing packets.
- */
- connp->conn_xmit_if_ill = ill;
- connp->conn_orig_xmit_ifindex = (ill == NULL) ?
- 0 : ifindex;
- break;
-
case IP_MULTICAST_IF:
/*
* This option is an internal special. The socket
@@ -10530,6 +10524,26 @@ setit:
}
}
break;
+
+ case IP_DHCPINIT_IF:
+ if (connp->conn_dhcpinit_ill != NULL) {
+ /*
+ * We've locked the conn so conn_cleanup_ill()
+ * cannot clear conn_dhcpinit_ill -- so it's
+ * safe to access the ill.
+ */
+ ill_t *oill = connp->conn_dhcpinit_ill;
+
+ ASSERT(oill->ill_dhcpinit != 0);
+ atomic_dec_32(&oill->ill_dhcpinit);
+ connp->conn_dhcpinit_ill = NULL;
+ }
+
+ if (ill != NULL) {
+ connp->conn_dhcpinit_ill = ill;
+ atomic_inc_32(&ill->ill_dhcpinit);
+ }
+ break;
}
} else {
switch (option) {
@@ -11048,7 +11062,7 @@ ip_opt_set(queue_t *q, uint_t optset_context, int level, int name,
*outlenp = inlen;
return (0);
case IP_BOUND_IF:
- case IP_XMIT_IF:
+ case IP_DHCPINIT_IF:
error = ip_opt_set_ill(connp, *i1, B_FALSE, checkonly,
level, name, first_mp);
if (error != 0)
@@ -15003,11 +15017,12 @@ ip_input(ill_t *ill, ill_rx_ring_t *ip_ring, mblk_t *mp_chain,
* o no options in the packet
* o not a RSVP packet
* o not a multicast packet
+ * o ill not in IP_DHCPINIT_IF mode
*/
if (!is_system_labeled() &&
!ipst->ips_ip_cgtp_filter && ipp_action_count == 0 &&
opt_len == 0 && ipha->ipha_protocol != IPPROTO_RSVP &&
- !ll_multicast && !CLASSD(dst)) {
+ !ll_multicast && !CLASSD(dst) && ill->ill_dhcpinit == 0) {
if (ire == NULL)
ire = ire_cache_lookup(dst, ALL_ZONES, NULL,
ipst);
@@ -15031,6 +15046,31 @@ ip_input(ill_t *ill, ill_rx_ring_t *ip_ring, mblk_t *mp_chain,
ire = NULL;
}
+ /*
+ * Brutal hack for DHCPv4 unicast: RFC2131 allows a DHCP
+ * server to unicast DHCP packets to a DHCP client using the
+ * IP address it is offering to the client. This can be
+ * disabled through the "broadcast bit", but not all DHCP
+ * servers honor that bit. Therefore, to interoperate with as
+ * many DHCP servers as possible, the DHCP client allows the
+ * server to unicast, but we treat those packets as broadcast
+ * here. Note that we don't rewrite the packet itself since
+ * (a) that would mess up the checksums and (b) the DHCP
+ * client conn is bound to INADDR_ANY so ip_fanout_udp() will
+ * hand it the packet regardless.
+ */
+ if (ill->ill_dhcpinit != 0 &&
+ IS_SIMPLE_IPH(ipha) && ipha->ipha_protocol == IPPROTO_UDP &&
+ MBLKL(mp) > sizeof (ipha_t) + sizeof (udpha_t)) {
+ udpha_t *udpha = (udpha_t *)&ipha[1];
+
+ if (ntohs(udpha->uha_dst_port) == IPPORT_BOOTPC) {
+ DTRACE_PROBE2(ip4__dhcpinit__pkt, ill_t *, ill,
+ mblk_t *, mp);
+ dst = INADDR_BROADCAST;
+ }
+ }
+
/* Full-blown slow path */
if (opt_len != 0) {
if (len != 0)
@@ -19988,7 +20028,7 @@ ip_output_options(void *arg, mblk_t *mp, void *arg2, int caller,
int match_flags;
ill_t *attach_ill = NULL;
/* Bind to IPIF_NOFAILOVER ill etc. */
- ill_t *xmit_ill = NULL; /* IP_XMIT_IF etc. */
+ ill_t *xmit_ill = NULL; /* IP_PKTINFO etc. */
ipif_t *dst_ipif;
boolean_t multirt_need_resolve = B_FALSE;
mblk_t *copy_mp = NULL;
@@ -20109,11 +20149,11 @@ ip_output_options(void *arg, mblk_t *mp, void *arg2, int caller,
}
/*
- * IP_DONTFAILOVER_IF and IP_XMIT_IF have precedence over
- * ill index passed in IP_PKTINFO.
+ * IP_DONTFAILOVER_IF and IP_BOUND_IF have precedence over ill index
+ * passed in IP_PKTINFO.
*/
if (infop->ip_opt_ill_index != 0 &&
- connp->conn_xmit_if_ill == NULL &&
+ connp->conn_outgoing_ill == NULL &&
connp->conn_nofailover_ill == NULL) {
xmit_ill = ill_lookup_on_ifindex(
@@ -20178,6 +20218,15 @@ ip_output_options(void *arg, mblk_t *mp, void *arg2, int caller,
}
}
+ /* If IP_BOUND_IF has been set, use that ill. */
+ if (connp->conn_outgoing_ill != NULL) {
+ xmit_ill = conn_get_held_ill(connp,
+ &connp->conn_outgoing_ill, &err);
+ if (err == ILL_LOOKUP_FAILED)
+ goto drop_pkt;
+
+ goto send_from_ill;
+ }
/* is packet multicast? */
if (CLASSD(dst))
@@ -20187,74 +20236,39 @@ ip_output_options(void *arg, mblk_t *mp, void *arg2, int caller,
* If xmit_ill is set above due to index passed in ip_pkt_info. It
* takes precedence over conn_dontroute and conn_nexthop_set
*/
- if (xmit_ill != NULL) {
+ if (xmit_ill != NULL)
goto send_from_ill;
- }
- if ((connp->conn_dontroute) || (connp->conn_xmit_if_ill != NULL) ||
- (connp->conn_nexthop_set)) {
+ if (connp->conn_dontroute || connp->conn_nexthop_set) {
/*
- * If the destination is a broadcast or a loopback
- * address, SO_DONTROUTE, IP_XMIT_IF and IP_NEXTHOP go
- * through the standard path. But in the case of local
- * destination only SO_DONTROUTE and IP_NEXTHOP go through
- * the standard path not IP_XMIT_IF.
+ * If the destination is a broadcast, local, or loopback
+ * address, SO_DONTROUTE and IP_NEXTHOP go through the
+ * standard path.
*/
ire = ire_cache_lookup(dst, zoneid, MBLK_GETLABEL(mp), ipst);
- if ((ire == NULL) || ((ire->ire_type != IRE_BROADCAST) &&
- (ire->ire_type != IRE_LOOPBACK))) {
- if ((connp->conn_dontroute ||
- connp->conn_nexthop_set) && (ire != NULL) &&
- (ire->ire_type == IRE_LOCAL))
- goto standard_path;
-
+ if ((ire == NULL) || (ire->ire_type &
+ (IRE_BROADCAST | IRE_LOCAL | IRE_LOOPBACK)) == 0) {
if (ire != NULL) {
ire_refrele(ire);
/* No more access to ire */
ire = NULL;
}
/*
- * bypass routing checks and go directly to
- * interface.
+ * bypass routing checks and go directly to interface.
*/
- if (connp->conn_dontroute) {
+ if (connp->conn_dontroute)
goto dontroute;
- } else if (connp->conn_nexthop_set) {
- ip_nexthop = B_TRUE;
- nexthop_addr = connp->conn_nexthop_v4;
- goto send_from_ill;
- }
- /*
- * If IP_XMIT_IF socket option is set,
- * then we allow unicast and multicast
- * packets to go through the ill. It is
- * quite possible that the destination
- * is not in the ire cache table and we
- * do not want to go to ip_newroute()
- * instead we call ip_newroute_ipif.
- */
- xmit_ill = conn_get_held_ill(connp,
- &connp->conn_xmit_if_ill, &err);
- if (err == ILL_LOOKUP_FAILED) {
- BUMP_MIB(&ipst->ips_ip_mib,
- ipIfStatsOutDiscards);
- if (attach_ill != NULL)
- ill_refrele(attach_ill);
- if (need_decref)
- CONN_DEC_REF(connp);
- freemsg(first_mp);
- return;
- }
+ ASSERT(connp->conn_nexthop_set);
+ ip_nexthop = B_TRUE;
+ nexthop_addr = connp->conn_nexthop_v4;
goto send_from_ill;
}
-standard_path:
+
/* Must be a broadcast, a loopback or a local ire */
- if (ire != NULL) {
- ire_refrele(ire);
- /* No more access to ire */
- ire = NULL;
- }
+ ire_refrele(ire);
+ /* No more access to ire */
+ ire = NULL;
}
if (attach_ill != NULL)
@@ -20819,17 +20833,16 @@ multicast:
ntohl(dst), ill->ill_name));
} else {
/*
- * The order of precedence is IP_XMIT_IF, IP_PKTINFO
- * and IP_MULTICAST_IF.
- * Block comment above this function explains the
- * locking mechanism used here
+ * The order of precedence is IP_BOUND_IF, IP_PKTINFO
+ * and IP_MULTICAST_IF. The block comment above this
+ * function explains the locking mechanism used here.
*/
if (xmit_ill == NULL) {
xmit_ill = conn_get_held_ill(connp,
- &connp->conn_xmit_if_ill, &err);
+ &connp->conn_outgoing_ill, &err);
if (err == ILL_LOOKUP_FAILED) {
ip1dbg(("ip_wput: No ill for "
- "IP_XMIT_IF\n"));
+ "IP_BOUND_IF\n"));
BUMP_MIB(&ipst->ips_ip_mib,
ipIfStatsOutNoRoutes);
goto drop_pkt;
@@ -20851,7 +20864,7 @@ multicast:
ipif = ipif_get_next_ipif(NULL, xmit_ill);
if (ipif == NULL) {
ip1dbg(("ip_wput: No ipif for "
- "IP_XMIT_IF\n"));
+ "xmit_ill\n"));
BUMP_MIB(&ipst->ips_ip_mib,
ipIfStatsOutNoRoutes);
goto drop_pkt;
@@ -20994,7 +21007,7 @@ multicast:
dst = ipif->ipif_lcl_addr;
/*
- * If IP_XMIT_IF is set, we branch out to ip_newroute_ipif.
+ * If xmit_ill is set, we branch out to ip_newroute_ipif.
* We don't need to lookup ire in ctable as the packet
* needs to be sent to the destination through the specified
* ill irrespective of ires in the cache table.
@@ -21095,54 +21108,39 @@ dontroute:
* connectivity.
*/
ipha->ipha_ttl = 1;
- /*
- * If IP_XMIT_IF is also set (conn_xmit_if_ill != NULL)
- * along with SO_DONTROUTE, higher precedence is
- * given to IP_XMIT_IF and the IP_XMIT_IF ipif is used.
- */
- if (connp->conn_xmit_if_ill == NULL) {
- /* If suitable ipif not found, drop packet */
- dst_ipif = ipif_lookup_onlink_addr(dst, zoneid,
- ipst);
- if (dst_ipif == NULL) {
- ip1dbg(("ip_wput: no route for "
- "dst using SO_DONTROUTE\n"));
- BUMP_MIB(&ipst->ips_ip_mib,
- ipIfStatsOutNoRoutes);
- mp->b_prev = mp->b_next = NULL;
- if (first_mp == NULL)
- first_mp = mp;
- goto drop_pkt;
- } else {
- /*
- * If suitable ipif has been found, set
- * xmit_ill to the corresponding
- * ipif_ill because we'll be following
- * the IP_XMIT_IF logic.
- */
- ASSERT(xmit_ill == NULL);
- xmit_ill = dst_ipif->ipif_ill;
- mutex_enter(&xmit_ill->ill_lock);
- if (!ILL_CAN_LOOKUP(xmit_ill)) {
- mutex_exit(&xmit_ill->ill_lock);
- xmit_ill = NULL;
- ipif_refrele(dst_ipif);
- ip1dbg(("ip_wput: no route for"
- " dst using"
- " SO_DONTROUTE\n"));
- BUMP_MIB(&ipst->ips_ip_mib,
- ipIfStatsOutNoRoutes);
- mp->b_prev = mp->b_next = NULL;
- if (first_mp == NULL)
- first_mp = mp;
- goto drop_pkt;
- }
- ill_refhold_locked(xmit_ill);
+
+ /* If suitable ipif not found, drop packet */
+ dst_ipif = ipif_lookup_onlink_addr(dst, zoneid, ipst);
+ if (dst_ipif == NULL) {
+noroute:
+ ip1dbg(("ip_wput: no route for dst using"
+ " SO_DONTROUTE\n"));
+ BUMP_MIB(&ipst->ips_ip_mib,
+ ipIfStatsOutNoRoutes);
+ mp->b_prev = mp->b_next = NULL;
+ if (first_mp == NULL)
+ first_mp = mp;
+ goto drop_pkt;
+ } else {
+ /*
+ * If suitable ipif has been found, set
+ * xmit_ill to the corresponding
+ * ipif_ill because we'll be using the
+ * send_from_ill logic below.
+ */
+ ASSERT(xmit_ill == NULL);
+ xmit_ill = dst_ipif->ipif_ill;
+ mutex_enter(&xmit_ill->ill_lock);
+ if (!ILL_CAN_LOOKUP(xmit_ill)) {
mutex_exit(&xmit_ill->ill_lock);
+ xmit_ill = NULL;
ipif_refrele(dst_ipif);
+ goto noroute;
}
+ ill_refhold_locked(xmit_ill);
+ mutex_exit(&xmit_ill->ill_lock);
+ ipif_refrele(dst_ipif);
}
-
}
/*
* If we are bound to IPIF_NOFAILOVER address, look for
@@ -21170,84 +21168,64 @@ send_from_ill:
ire = ire_ctable_lookup(dst, 0, 0, attach_ipif,
zoneid, MBLK_GETLABEL(mp), match_flags, ipst);
ipif_refrele(attach_ipif);
- } else if (xmit_ill != NULL || (connp != NULL &&
- connp->conn_xmit_if_ill != NULL)) {
+ } else if (xmit_ill != NULL) {
+ ipif_t *ipif;
+
/*
* Mark this packet as originated locally
*/
mp->b_prev = mp->b_next = NULL;
+
/*
- * xmit_ill could be NULL if SO_DONTROUTE
- * is also set.
+ * Could be SO_DONTROUTE case also.
+ * Verify that at least one ipif is up on the ill.
*/
- if (xmit_ill == NULL) {
- xmit_ill = conn_get_held_ill(connp,
- &connp->conn_xmit_if_ill, &err);
- if (err == ILL_LOOKUP_FAILED) {
- BUMP_MIB(&ipst->ips_ip_mib,
- ipIfStatsOutDiscards);
- if (need_decref)
- CONN_DEC_REF(connp);
- freemsg(first_mp);
- return;
- }
- if (xmit_ill == NULL) {
- if (connp->conn_dontroute)
- goto dontroute;
- goto send_from_ill;
- }
+ if (xmit_ill->ill_ipif_up_count == 0) {
+ ip1dbg(("ip_output: xmit_ill %s is down\n",
+ xmit_ill->ill_name));
+ goto drop_pkt;
}
+
+ ipif = ipif_get_next_ipif(NULL, xmit_ill);
+ if (ipif == NULL) {
+ ip1dbg(("ip_output: xmit_ill %s NULL ipif\n",
+ xmit_ill->ill_name));
+ goto drop_pkt;
+ }
+
/*
- * Could be SO_DONTROUTE case also.
- * check at least one interface is UP as
- * specified by this ILL
+ * Look for a ire that is part of the group,
+ * if found use it else call ip_newroute_ipif.
+ * IPCL_ZONEID is not used for matching because
+ * IP_ALLZONES option is valid only when the
+ * ill is accessible from all zones i.e has a
+ * valid ipif in all zones.
*/
- if (xmit_ill->ill_ipif_up_count > 0) {
- ipif_t *ipif;
-
- ipif = ipif_get_next_ipif(NULL, xmit_ill);
- if (ipif == NULL) {
- ip1dbg(("ip_output: "
- "xmit_ill NULL ipif\n"));
- goto drop_pkt;
- }
- /*
- * Look for a ire that is part of the group,
- * if found use it else call ip_newroute_ipif.
- * IPCL_ZONEID is not used for matching because
- * IP_ALLZONES option is valid only when the
- * ill is accessible from all zones i.e has a
- * valid ipif in all zones.
- */
- match_flags = MATCH_IRE_ILL_GROUP |
- MATCH_IRE_SECATTR;
- ire = ire_ctable_lookup(dst, 0, 0, ipif, zoneid,
- MBLK_GETLABEL(mp), match_flags, ipst);
- /*
- * If an ire exists use it or else create
- * an ire but don't add it to the cache.
- * Adding an ire may cause issues with
- * asymmetric routing.
- * In case of multiroute always act as if
- * ire does not exist.
- */
- if (ire == NULL ||
- ire->ire_flags & RTF_MULTIRT) {
- if (ire != NULL)
- ire_refrele(ire);
- ip_newroute_ipif(q, first_mp, ipif,
- dst, connp, 0, zoneid, infop);
- ipif_refrele(ipif);
- ip1dbg(("ip_wput: ip_unicast_if\n"));
- ill_refrele(xmit_ill);
- if (need_decref)
- CONN_DEC_REF(connp);
- return;
- }
+ match_flags = MATCH_IRE_ILL_GROUP | MATCH_IRE_SECATTR;
+ ire = ire_ctable_lookup(dst, 0, 0, ipif, zoneid,
+ MBLK_GETLABEL(mp), match_flags, ipst);
+ /*
+ * If an ire exists use it or else create
+ * an ire but don't add it to the cache.
+ * Adding an ire may cause issues with
+ * asymmetric routing.
+ * In case of multiroute always act as if
+ * ire does not exist.
+ */
+ if (ire == NULL || ire->ire_flags & RTF_MULTIRT) {
+ if (ire != NULL)
+ ire_refrele(ire);
+ ip_newroute_ipif(q, first_mp, ipif,
+ dst, connp, 0, zoneid, infop);
ipif_refrele(ipif);
- } else {
- goto drop_pkt;
+ ip1dbg(("ip_output: xmit_ill via %s\n",
+ xmit_ill->ill_name));
+ ill_refrele(xmit_ill);
+ if (need_decref)
+ CONN_DEC_REF(connp);
+ return;
}
+ ipif_refrele(ipif);
} else if (ip_nexthop || (connp != NULL &&
(connp->conn_nexthop_set)) && !ignore_nexthop) {
if (!ip_nexthop) {
@@ -21458,7 +21436,7 @@ ip_wput(queue_t *q, mblk_t *mp)
*
* The following rules must be observed when accessing any ipif or ill
* that has been cached in the conn. Typically conn_nofailover_ill,
- * conn_xmit_if_ill, conn_multicast_ipif and conn_multicast_ill.
+ * conn_outgoing_ill, conn_multicast_ipif and conn_multicast_ill.
*
* Access: The ipif or ill pointed to from the conn can be accessed under
* the protection of the conn_lock or after it has been refheld under the
@@ -22020,11 +21998,10 @@ ip_wput_ire(queue_t *q, mblk_t *mp, ire_t *ire, conn_t *connp, int caller,
}
/*
- * conn_outgoing_ill is used only in the broadcast loop.
+ * conn_outgoing_ill variable is used only in the broadcast loop.
* for performance we don't grab the mutexs in the fastpath
*/
if ((connp != NULL) &&
- (connp->conn_xmit_if_ill == NULL) &&
(ire->ire_type == IRE_BROADCAST) &&
((connp->conn_nofailover_ill != NULL) ||
(connp->conn_outgoing_ill != NULL))) {
@@ -22611,8 +22588,8 @@ broadcast:
rw_exit(&ire->ire_bucket->irb_lock);
/* Did not find a matching ill */
ip1dbg(("ip_wput_ire: broadcast with no "
- "matching IP_BOUND_IF ill %s\n",
- conn_outgoing_ill->ill_name));
+ "matching IP_BOUND_IF ill %s dst %x\n",
+ conn_outgoing_ill->ill_name, dst));
freemsg(first_mp);
if (ire != NULL)
ire_refrele(ire);
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index 4673bde903..c9703c3664 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -1526,8 +1526,11 @@ conn_cleanup_ill(conn_t *connp, caddr_t arg)
connp->conn_outgoing_pill = NULL;
if (connp->conn_nofailover_ill == ill)
connp->conn_nofailover_ill = NULL;
- if (connp->conn_xmit_if_ill == ill)
- connp->conn_xmit_if_ill = NULL;
+ if (connp->conn_dhcpinit_ill == ill) {
+ connp->conn_dhcpinit_ill = NULL;
+ ASSERT(ill->ill_dhcpinit != 0);
+ atomic_dec_32(&ill->ill_dhcpinit);
+ }
if (connp->conn_ire_cache != NULL) {
ire = connp->conn_ire_cache;
/*
@@ -16610,11 +16613,6 @@ conn_move(conn_t *connp, caddr_t arg)
connp->conn_multicast_ill = connm->cm_to_ill;
}
- /* Change IP_XMIT_IF associations */
- if ((connp->conn_xmit_if_ill == from_ill) &&
- (ifindex == 0 || connp->conn_orig_xmit_ifindex == ifindex)) {
- connp->conn_xmit_if_ill = to_ill;
- }
/*
* Change the ilg_ill to point to the new one. This assumes
* ilm_move_v6 has moved the ilms to new_ill and the driver
@@ -20216,8 +20214,7 @@ ipif_up_done(ipif_t *ipif)
/*
* Create any necessary broadcast IREs.
*/
- if ((ipif->ipif_subnet != INADDR_ANY) &&
- (ipif->ipif_flags & IPIF_BROADCAST))
+ if (ipif->ipif_flags & IPIF_BROADCAST)
irep = ipif_create_bcast_ires(ipif, irep);
ASSERT(!MUTEX_HELD(&ipif->ipif_ill->ill_lock));
@@ -21712,9 +21709,6 @@ conn_change_ifindex(conn_t *connp, caddr_t arg)
if (connp->conn_orig_multicast_ifindex == old_ifindex)
connp->conn_orig_multicast_ifindex = new_ifindex;
- if (connp->conn_orig_xmit_ifindex == old_ifindex)
- connp->conn_orig_xmit_ifindex = new_ifindex;
-
for (i = connp->conn_ilg_inuse - 1; i >= 0; i--) {
ilg = &connp->conn_ilg[i];
if (ilg->ilg_orig_ifindex == old_ifindex)
diff --git a/usr/src/uts/common/inet/ip/ip_opt_data.c b/usr/src/uts/common/inet/ip/ip_opt_data.c
index 5bdea67f2a..3df66ece60 100644
--- a/usr/src/uts/common/inet/ip/ip_opt_data.c
+++ b/usr/src/uts/common/inet/ip/ip_opt_data.c
@@ -119,12 +119,12 @@ opdes_t ip_opt_arr[] = {
{ IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
sizeof (int), 0 /* no ifindex */ },
-{ IP_XMIT_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
- sizeof (int), 0 /* no ifindex */ },
-
{ IP_DONTFAILOVER_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
sizeof (struct in_addr), 0 /* not initialized */ },
+{ IP_DHCPINIT_IF, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, 0,
+ sizeof (int), 0 },
+
{ IP_UNSPEC_SRC, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0,
sizeof (int), 0 },
diff --git a/usr/src/uts/common/inet/ip_impl.h b/usr/src/uts/common/inet/ip_impl.h
index 8cb4bc9b3c..6c4d5f41aa 100644
--- a/usr/src/uts/common/inet/ip_impl.h
+++ b/usr/src/uts/common/inet/ip_impl.h
@@ -395,7 +395,6 @@ typedef struct ip_lso_info_s {
((connp)->conn_dontroute == 0 && /* SO_DONTROUTE */ \
!((connp)->conn_nexthop_set) && /* IP_NEXTHOP */ \
(connp)->conn_nofailover_ill == NULL && /* IPIF_NOFAILOVER */ \
- (connp)->conn_xmit_if_ill == NULL && /* IP_XMIT_IF */ \
(connp)->conn_outgoing_pill == NULL && /* IP{V6}_BOUND_PIF */ \
(connp)->conn_outgoing_ill == NULL) /* IP{V6}_BOUND_IF */
diff --git a/usr/src/uts/common/inet/ipclassifier.h b/usr/src/uts/common/inet/ipclassifier.h
index 3a6a15cf6f..a80d8077b0 100644
--- a/usr/src/uts/common/inet/ipclassifier.h
+++ b/usr/src/uts/common/inet/ipclassifier.h
@@ -226,8 +226,8 @@ struct conn_s {
conn_lso_ok : 1; /* LSO is usable */
- ill_t *conn_xmit_if_ill; /* Outbound ill */
ill_t *conn_nofailover_ill; /* Failover ill */
+ ill_t *conn_dhcpinit_ill; /* IP_DHCPINIT_IF */
ipsec_latch_t *conn_latch; /* latched state */
ill_t *conn_outgoing_ill; /* IP{,V6}_BOUND_IF */
edesc_spf conn_send; /* Pointer to send routine */
@@ -285,7 +285,6 @@ struct conn_s {
int conn_orig_bound_ifindex; /* BOUND_IF before MOVE */
int conn_orig_multicast_ifindex;
/* IPv6 MC IF before MOVE */
- int conn_orig_xmit_ifindex; /* IP_XMIT_IF before move */
struct conn_s *conn_drain_next; /* Next conn in drain list */
struct conn_s *conn_drain_prev; /* Prev conn in drain list */
idl_t *conn_idl; /* Ptr to the drain list head */
diff --git a/usr/src/uts/common/inet/rawip_impl.h b/usr/src/uts/common/inet/rawip_impl.h
index 58f29e8a3c..20c316123b 100644
--- a/usr/src/uts/common/inet/rawip_impl.h
+++ b/usr/src/uts/common/inet/rawip_impl.h
@@ -95,7 +95,6 @@ typedef struct icmp_s {
uint8_t icmp_multicast_ttl; /* IP*_MULTICAST_TTL/HOPS */
ipaddr_t icmp_multicast_if_addr; /* IP_MULTICAST_IF option */
uint_t icmp_multicast_if_index; /* IPV6_MULTICAST_IF option */
- int icmp_xmit_if; /* IP_XMIT_IF option */
int icmp_bound_if; /* IP*_BOUND_IF option */
/* Written to only once at the time of opening the endpoint */
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index 2d77bd0033..fe38e6b31f 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -18622,7 +18622,7 @@ tcp_zcopy_check(tcp_t *tcp)
(connp->conn_flags & IPCL_CHECK_POLICY) == 0 &&
connp->conn_dontroute == 0 &&
!connp->conn_nexthop_set &&
- connp->conn_xmit_if_ill == NULL &&
+ connp->conn_outgoing_ill == NULL &&
connp->conn_nofailover_ill == NULL &&
do_tcpzcopy == 1) {
/*
diff --git a/usr/src/uts/common/inet/udp/udp.c b/usr/src/uts/common/inet/udp/udp.c
index 5347af5826..f7a8dc26d8 100644
--- a/usr/src/uts/common/inet/udp/udp.c
+++ b/usr/src/uts/common/inet/udp/udp.c
@@ -2666,6 +2666,8 @@ udp_opt_get_locked(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
case IP_TTL:
*i1 = (int)udp->udp_ttl;
break; /* goto sizeof (int) option return */
+ case IP_DHCPINIT_IF:
+ return (-EINVAL);
case IP_NEXTHOP:
case IP_RECVPKTINFO:
/*
@@ -2725,9 +2727,6 @@ udp_opt_get_locked(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
case IP_UNSPEC_SRC:
*i1 = udp->udp_unspec_source;
break; /* goto sizeof (int) option return */
- case IP_XMIT_IF:
- *i1 = udp->udp_xmit_if;
- break; /* goto sizeof (int) option return */
default:
return (-1);
}
@@ -3259,6 +3258,7 @@ udp_opt_set_locked(queue_t *q, uint_t optset_context, int level,
case MCAST_LEAVE_SOURCE_GROUP:
case IP_SEC_OPT:
case IP_NEXTHOP:
+ case IP_DHCPINIT_IF:
/*
* "soft" error (negative)
* option not handled at this level
@@ -3273,10 +3273,6 @@ udp_opt_set_locked(queue_t *q, uint_t optset_context, int level,
if (!checkonly)
udp->udp_unspec_source = onoff;
break;
- case IP_XMIT_IF:
- if (!checkonly)
- udp->udp_xmit_if = *i1;
- break;
default:
*outlenp = 0;
return (EINVAL);
@@ -5994,7 +5990,7 @@ udp_output_v4(conn_t *connp, mblk_t *mp, ipaddr_t v4dst, uint16_t port,
if ((connp->conn_flags & IPCL_CHECK_POLICY) != 0 ||
CONN_OUTBOUND_POLICY_PRESENT(connp, ipss) ||
- connp->conn_dontroute || connp->conn_xmit_if_ill != NULL ||
+ connp->conn_dontroute ||
connp->conn_nofailover_ill != NULL ||
connp->conn_outgoing_ill != NULL || optinfo.ip_opt_flags != 0 ||
optinfo.ip_opt_ill_index != 0 ||
diff --git a/usr/src/uts/common/inet/udp/udp_opt_data.c b/usr/src/uts/common/inet/udp/udp_opt_data.c
index 07cc9e638f..9c7121fba6 100644
--- a/usr/src/uts/common/inet/udp/udp_opt_data.c
+++ b/usr/src/uts/common/inet/udp/udp_opt_data.c
@@ -131,12 +131,13 @@ opdes_t udp_opt_arr[] = {
{ IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_PASSNEXT,
sizeof (int), 0 /* no ifindex */ },
-{ IP_XMIT_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_PASSNEXT,
- sizeof (int), 0 /* no ifindex */ },
{ IP_DONTFAILOVER_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_PASSNEXT,
sizeof (struct in_addr), 0 /* not initialized */ },
+{ IP_DHCPINIT_IF, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT,
+ sizeof (int), 0 },
+
{ IP_UNSPEC_SRC, IPPROTO_IP, OA_R, OA_RW, OP_RAW, OP_PASSNEXT,
sizeof (int), 0 },
diff --git a/usr/src/uts/common/inet/udp_impl.h b/usr/src/uts/common/inet/udp_impl.h
index a77b605088..131bf3ed81 100644
--- a/usr/src/uts/common/inet/udp_impl.h
+++ b/usr/src/uts/common/inet/udp_impl.h
@@ -296,7 +296,6 @@ typedef struct udp_s {
ipaddr_t udp_multicast_if_addr; /* IP_MULTICAST_IF option */
uint_t udp_multicast_if_index; /* IPV6_MULTICAST_IF option */
int udp_bound_if; /* IP*_BOUND_IF option */
- int udp_xmit_if; /* IP_XMIT_IF option */
/* Written to only once at the time of opening the endpoint */
conn_t *udp_connp;
diff --git a/usr/src/uts/common/netinet/in.h b/usr/src/uts/common/netinet/in.h
index f46c9753d2..122b19b2c9 100644
--- a/usr/src/uts/common/netinet/in.h
+++ b/usr/src/uts/common/netinet/in.h
@@ -910,13 +910,9 @@ typedef struct ipsec_req {
* SunOS private (potentially not portable) IP_ option names
*/
#define IP_BOUND_IF 0x41 /* bind socket to an ifindex */
-#define IP_UNSPEC_SRC 0x42 /* use unspecified source address */
-/*
- * IP_XMIT_IF is used to send unicast/multicast packets through the specified
- * interface without looking at the routing table entries.
- * This is a Sun private interface.
- */
-#define IP_XMIT_IF 0x43 /* use specified outgoing interface */
+#define IP_UNSPEC_SRC 0x42 /* use unspecified source address */
+/* UNUSED 0x43 was IP_XMIT_IF -- can be reused */
+
/*
* IP_DONTFAILOVER_IF option is used to indicate that outbound unicast and
* multicast packets go through the specified interface, no load spreading,
@@ -925,6 +921,8 @@ typedef struct ipsec_req {
*/
#define IP_DONTFAILOVER_IF 0x44
+#define IP_DHCPINIT_IF 0x45 /* accept all unicast DHCP traffic */
+
/*
* Option values and names (when !_XPG5) shared with <xti_inet.h>
*/