summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-inet/sbin
diff options
context:
space:
mode:
authormeem <Peter.Memishian@Sun.COM>2009-01-06 20:16:25 -0500
committermeem <Peter.Memishian@Sun.COM>2009-01-06 20:16:25 -0500
commite11c3f44f531fdff80941ce57c065d2ae861cefc (patch)
treee921e957d727a9596275a1119fd627ef2ecca47d /usr/src/cmd/cmd-inet/sbin
parent732675dd38771d280fdc276731344e9652071753 (diff)
downloadillumos-gate-e11c3f44f531fdff80941ce57c065d2ae861cefc.tar.gz
PSARC/2007/272 Project Clearview: IPMP Rearchitecture
PSARC/2008/773 IPQoS if_groupname Selector Removal PSARC/2009/001 Move in.mpathd into /lib/inet 6783149 Clearview IPMP Rearchitecture 4472956 libipmp should provide administrative interfaces 4494577 ipmp is opaque - there's no way to get current status 4509788 IPMP's usage of interface flags is not backward compatible 4509869 IPMP's address move mechanism needs to be transparent to applications 4531232 "in.rdiscd: sendto: Bad file number" seen during IPMP DR 4533876 new instances of interfaces under ipmp are generated with each dr/op 4699003 in.mpathd should squawk if interfaces in a group have the same hwaddr 4704937 SUNW_ip_rcm.so is sloppy with strings 4713308 IPMP shouldn't failover unconfigured logical interfaces 4785694 non-homogeneous IPMP group does not do failback 4850407 if_mpadm and IPMP DR failure 5015757 ip can panic with ASSERT(attach_ill == ipif->ipif_ill) failure 5086201 in.ndpd's phyint_reach_random() spews "SIOCSLIFLNKINFO Invalid argument" 6184000 routes cannot be created on failed interfaces 6246564 if_mpadm -r <ifname> doesn't bring up IPv6 link-local data address 6359058 SIOCLIFFAILBACK repeatedly fails with EAGAIN; in.mpathd fills logs 6359536 enabling STANDBY on an interface with no test address acts oddly 6378487 in.dhcpd doesn't work well in an IPMP setup 6462335 cannot offline to IPMP interfaces that have no probe targets 6516992 in.routed spews "Address already in use" during IPMP address move 6518460 ip_rcm`update_pif() must remain calm when logical interfaces disappear 6549957 failed IP interfaces at boot may go unreported 6591186 rpcbind can't deal with indirect calls if all addresses are deprecated 6667143 NCE_F_UNSOL_ADV broken 6698480 IGMP version not retained during IPMP failover 6726235 IPMP group failure can sometimes lead to an extra failover 6726645 in.routed skips DEPRECATED addresses even when no others exist 6738310 ip_ndp_recover() checks IPIF_CONDEMNED on the wrong ipif flags field 6739454 system panics at sdpib`sdp_rts_announce 6739531 IPv6 DAD doesn't work well with IPMP 6740719 in.mpathd may fail to switch to router target mode 6743260 ipif_resolver_up() can fail and leave ARP bringup pending 6746613 ip's DL_NOTE_SDU_SIZE logic mishandles ill_max_frag < ill_max_mtu 6748145 in.ndpd's IPv6 link-local hardware address mappings can go stale 6753560 ilg_delete_all() can race with ill_delete_tail() when ilg_ill changes 6755987 stillborn IFF_POINTOPOINT in.mpathd logic should be hauled out 6775126 SUBDIRS ipsecutils element does not in order be 6775811 NCEs can get stuck in ND_INCOMPLETE if ARP fails when IPMP is in-use 6777496 receive-side ILL_HCKSUM_CAPABLE checks look at the wrong ill 6781488 IPSQ timer restart logic can deadlock under stress 6781883 ip_ndp_find_solicitation() can be passed adverts, and has API issues 6784852 RPCIB, SDP, and RDS all break when vanity naming is used 6786048 IPv6 ND probes create IREs with incorrect source addresses 6786091 I_PLINK handling in IP must not request reentry via ipsq_try_enter() 6786711 IPQoS if_groupname selector needs to go 6787091 assertion failure in ipcl_conn_cleanup() due to non-NULL conn_ilg 6789235 INADDR_ANY ILMs can trigger an assertion failure in IPMP environments 6789502 ipif_resolver_up() calls after ipif_ndp_up() clobber ipif_addr_ready 6789718 ip6.tun0 cannot be plumbed in a non-global-zone post-6745288 6789732 libdlpi may get stuck in i_dlpi_strgetmsg() 6789870 ipif6_dup_recovery() may operate on a freed ipif, corrupting memory 6789874 ipnet_nicevent_cb() may call taskq_dispatch() on a bogus taskq 6790310 in.mpathd may core with "phyint_inst_timer: invalid state 4" --HG-- rename : usr/src/lib/libinetutil/common/inetutil4.c => usr/src/lib/libinetutil/common/inetutil.c rename : usr/src/uts/common/inet/vni/vni.c => usr/src/uts/common/inet/dlpistub/dlpistub.c rename : usr/src/uts/common/inet/vni/vni.conf => usr/src/uts/common/inet/dlpistub/dlpistub.conf rename : usr/src/uts/common/inet/vni/vni_impl.h => usr/src/uts/common/inet/dlpistub/dlpistub_impl.h rename : usr/src/uts/intel/vni/Makefile => usr/src/uts/intel/dlpistub/Makefile rename : usr/src/uts/sparc/vni/Makefile => usr/src/uts/sparc/dlpistub/Makefile
Diffstat (limited to 'usr/src/cmd/cmd-inet/sbin')
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c16
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/bound.c7
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.c206
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h9
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.c9
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c7
-rw-r--r--usr/src/cmd/cmd-inet/sbin/dhcpagent/states.c22
-rw-r--r--usr/src/cmd/cmd-inet/sbin/ifparse/ifparse.c5
8 files changed, 206 insertions, 75 deletions
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c
index 34bb772632..5a4779cfa5 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -133,6 +133,7 @@ main(int argc, char **argv)
boolean_t is_verbose;
int ipc_fd;
int c;
+ int aware = RTAW_UNDER_IPMP;
struct rlimit rl;
debug_level = df_get_int("", B_FALSE, DF_DEBUG_LEVEL);
@@ -301,6 +302,17 @@ main(int argc, char **argv)
dhcpmsg(MSG_ERR, "cannot open routing socket");
return (EXIT_FAILURE);
}
+
+ /*
+ * We're IPMP-aware and can manage IPMP test addresses, so issue
+ * RT_AWARE to get routing socket messages for interfaces under IPMP.
+ */
+ if (setsockopt(rtsock_fd, SOL_ROUTE, RT_AWARE, &aware,
+ sizeof (aware)) == -1) {
+ dhcpmsg(MSG_ERR, "cannot set RT_AWARE on routing socket");
+ return (EXIT_FAILURE);
+ }
+
if (iu_register_event(eh, rtsock_fd, POLLIN, rtsock_event, 0) == -1) {
dhcpmsg(MSG_ERR, "cannot register routing socket for messages");
return (EXIT_FAILURE);
@@ -1182,7 +1194,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);
+ (void) open_ip_lif(lif, INADDR_ANY, B_TRUE);
}
dad_wait = lif->lif_dad_wait;
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/bound.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/bound.c
index 4637ecc346..6cfce9f0a9 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/bound.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/bound.c
@@ -19,14 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* BOUND state of the DHCP client state machine.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
@@ -358,7 +356,8 @@ dhcp_bound_complete(dhcp_smach_t *dsmp)
lif = dsmp->dsm_lif;
if (router_list != NULL &&
(router_list->len % sizeof (ipaddr_t)) == 0 &&
- strchr(lif->lif_name, ':') == NULL) {
+ strchr(lif->lif_name, ':') == NULL &&
+ !lif->lif_pif->pif_under_ipmp) {
dsmp->dsm_nrouters = router_list->len / sizeof (ipaddr_t);
dsmp->dsm_routers = malloc(router_list->len);
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.c
index 0cfdad40e3..5d2d5fb99e 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -76,6 +76,7 @@ insert_pif(const char *pname, boolean_t isv6, int *error)
{
dhcp_pif_t *pif;
struct lifreq lifr;
+ lifgroupinfo_t lifgr;
dlpi_handle_t dh = NULL;
int fd = isv6 ? v6_sock_fd : v4_sock_fd;
@@ -127,12 +128,60 @@ insert_pif(const char *pname, boolean_t isv6, int *error)
}
/*
- * For IPv4, use DLPI to determine the hardware type, hardware
- * address, and hardware address length.
+ * Check if the pif is in an IPMP group. Interfaces using IPMP don't
+ * have dedicated hardware addresses, and get their hardware type from
+ * the SIOCGLIFGROUPINFO ioctl rather than DLPI.
*/
- if (!isv6) {
- int rc;
- dlpi_info_t dlinfo;
+ if (ioctl(fd, SIOCGLIFGROUPNAME, &lifr) == -1) {
+ *error = DHCP_IPC_E_INT;
+ dhcpmsg(MSG_ERR, "insert_pif: SIOCGLIFGROUPNAME for %s", pname);
+ goto failure;
+ }
+
+ if (lifr.lifr_groupname[0] != '\0') {
+ (void) strlcpy(lifgr.gi_grname, lifr.lifr_groupname,
+ LIFGRNAMSIZ);
+ if (ioctl(fd, SIOCGLIFGROUPINFO, &lifgr) == -1) {
+ *error = DHCP_IPC_E_INT;
+ dhcpmsg(MSG_ERR, "insert_pif: SIOCGLIFGROUPINFO for %s",
+ lifgr.gi_grname);
+ goto failure;
+ }
+
+ pif->pif_hwtype = dlpi_arptype(lifgr.gi_mactype);
+ pif->pif_under_ipmp = (strcmp(pname, lifgr.gi_grifname) != 0);
+ (void) strlcpy(pif->pif_grifname, lifgr.gi_grifname, LIFNAMSIZ);
+
+ /*
+ * For IPMP underlying interfaces, stash the interface index
+ * of the IPMP meta-interface; we'll use it to send/receive
+ * traffic. This is both necessary (since IP_BOUND_IF for
+ * non-unicast traffic won't work on underlying interfaces)
+ * and preferred (since a test address lease will be able to
+ * be maintained as long as another interface in the group is
+ * still functioning).
+ */
+ if (pif->pif_under_ipmp) {
+ (void) strlcpy(lifr.lifr_name, pif->pif_grifname,
+ LIFNAMSIZ);
+
+ if (ioctl(fd, SIOCGLIFINDEX, &lifr) == -1) {
+ *error = DHCP_IPC_E_INT;
+ dhcpmsg(MSG_ERR, "insert_pif: SIOCGLIFINDEX "
+ "for %s", lifr.lifr_name);
+ goto failure;
+ }
+ pif->pif_grindex = lifr.lifr_index;
+ }
+ }
+
+ /*
+ * For IPv4, if the hardware type is still unknown, use DLPI to
+ * determine it, the hardware address, and hardware address length.
+ */
+ if (!isv6 && pif->pif_hwtype == 0) {
+ int rc;
+ dlpi_info_t dlinfo;
if ((rc = dlpi_open(pname, &dh, 0)) != DLPI_SUCCESS) {
dhcpmsg(MSG_ERROR, "insert_pif: dlpi_open: %s",
@@ -661,11 +710,12 @@ verify_lif(const dhcp_lif_t *lif)
boolean_t isv6;
int fd;
struct lifreq lifr;
+ dhcp_pif_t *pif = lif->lif_pif;
(void) memset(&lifr, 0, sizeof (struct lifreq));
(void) strlcpy(lifr.lifr_name, lif->lif_name, LIFNAMSIZ);
- isv6 = lif->lif_pif->pif_isv6;
+ isv6 = pif->pif_isv6;
fd = isv6 ? v6_sock_fd : v4_sock_fd;
if (ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1) {
@@ -689,43 +739,41 @@ verify_lif(const dhcp_lif_t *lif)
}
/*
- * Special case: if the interface has gone down as a duplicate, then
- * this alone does _not_ mean that we're abandoning it just yet. Allow
- * the state machine to handle this normally by trying to get a new
- * lease.
- */
- if ((lifr.lifr_flags & (IFF_UP|IFF_DUPLICATE)) == IFF_DUPLICATE) {
- dhcpmsg(MSG_DEBUG, "verify_lif: duplicate address on %s",
- lif->lif_name);
- return (B_TRUE);
- }
-
- /*
- * If the user has torn down or started up the interface manually, then
- * abandon the lease.
- */
- if ((lif->lif_flags ^ lifr.lifr_flags) & IFF_UP) {
- dhcpmsg(MSG_DEBUG, "verify_lif: user has %s %s",
- lifr.lifr_flags & IFF_UP ? "started up" : "shut down",
- lif->lif_name);
- return (B_FALSE);
- }
-
- /*
* Check for delete and recreate.
*/
if (ioctl(fd, SIOCGLIFINDEX, &lifr) == -1) {
- dhcpmsg(MSG_ERR, "verify_lif: SIOCGLIFINDEX failed on %s",
- lif->lif_name);
+ if (errno != ENXIO) {
+ dhcpmsg(MSG_ERR, "verify_lif: SIOCGLIFINDEX failed "
+ "on %s", lif->lif_name);
+ }
return (B_FALSE);
}
- if (lifr.lifr_index != lif->lif_pif->pif_index) {
+ if (lifr.lifr_index != pif->pif_index) {
dhcpmsg(MSG_DEBUG,
"verify_lif: ifindex on %s changed: %u to %u",
- lif->lif_name, lif->lif_pif->pif_index, lifr.lifr_index);
+ lif->lif_name, pif->pif_index, lifr.lifr_index);
return (B_FALSE);
}
+ if (pif->pif_under_ipmp) {
+ (void) strlcpy(lifr.lifr_name, pif->pif_grifname, LIFNAMSIZ);
+
+ if (ioctl(fd, SIOCGLIFINDEX, &lifr) == -1) {
+ if (errno != ENXIO) {
+ dhcpmsg(MSG_ERR, "verify_lif: SIOCGLIFINDEX "
+ "failed on %s", lifr.lifr_name);
+ }
+ return (B_FALSE);
+ }
+
+ if (lifr.lifr_index != pif->pif_grindex) {
+ dhcpmsg(MSG_DEBUG, "verify_lif: IPMP group ifindex "
+ "on %s changed: %u to %u", lifr.lifr_name,
+ pif->pif_grindex, lifr.lifr_index);
+ return (B_FALSE);
+ }
+ }
+
/*
* If the IP address, netmask, or broadcast address have changed, or
* the interface has been unplumbed, then we act like there has been an
@@ -934,6 +982,13 @@ plumb_lif(dhcp_pif_t *pif, const in6_addr_t *addr)
lifr.lifr_name);
goto failure;
}
+
+ /*
+ * See comment in set_lif_dhcp().
+ */
+ if (pif->pif_under_ipmp && !(lifr.lifr_flags & IFF_NOFAILOVER))
+ lifr.lifr_flags |= IFF_NOFAILOVER | IFF_DEPRECATED;
+
lifr.lifr_flags |= IFF_UP | IFF_DHCPRUNNING;
if (ioctl(v6_sock_fd, SIOCSLIFFLAGS, &lifr) == -1) {
dhcpmsg(MSG_ERR, "plumb_lif: SIOCSLIFFLAGS %s",
@@ -1060,8 +1115,9 @@ set_lif_dhcp(dhcp_lif_t *lif, boolean_t is_adopting)
int fd;
int err;
struct lifreq lifr;
+ dhcp_pif_t *pif = lif->lif_pif;
- fd = lif->lif_pif->pif_isv6 ? v6_sock_fd : v4_sock_fd;
+ fd = pif->pif_isv6 ? v6_sock_fd : v4_sock_fd;
(void) strlcpy(lifr.lifr_name, lif->lif_name, LIFNAMSIZ);
@@ -1098,6 +1154,17 @@ set_lif_dhcp(dhcp_lif_t *lif, boolean_t is_adopting)
"set on %s", lif->lif_name);
}
} else {
+ /*
+ * If the lif is on an interface under IPMP, IFF_NOFAILOVER
+ * must be set or the kernel will prevent us from setting
+ * IFF_DHCPRUNNING (since the subsequent IFF_UP would lead to
+ * migration). We set IFF_DEPRECATED too since the kernel
+ * will set it automatically when setting IFF_NOFAILOVER,
+ * causing our lif_flags value to grow stale.
+ */
+ if (pif->pif_under_ipmp && !(lifr.lifr_flags & IFF_NOFAILOVER))
+ lifr.lifr_flags |= IFF_NOFAILOVER | IFF_DEPRECATED;
+
lifr.lifr_flags |= IFF_DHCPRUNNING;
if (ioctl(fd, SIOCSLIFFLAGS, &lifr) == -1) {
dhcpmsg(MSG_ERR, "set_lif_dhcp: SIOCSLIFFLAGS for %s",
@@ -1207,6 +1274,13 @@ clear_lif_deprecated(dhcp_lif_t *lif)
return (B_FALSE);
}
+ /*
+ * Don't try to clear IFF_DEPRECATED if this is a test address,
+ * since IPMP's use of IFF_DEPRECATED is not compatible with ours.
+ */
+ if (lifr.lifr_flags & IFF_NOFAILOVER)
+ return (B_TRUE);
+
if (!(lifr.lifr_flags & IFF_DEPRECATED))
return (B_TRUE);
@@ -1226,16 +1300,19 @@ clear_lif_deprecated(dhcp_lif_t *lif)
*
* input: dhcp_lif_t *: the logical interface to operate on
* in_addr_t: the address the socket will be bound to (in hbo)
+ * boolean_t: B_TRUE if the address should be brought up (if needed)
* output: boolean_t: B_TRUE if the socket was opened successfully.
*/
boolean_t
-open_ip_lif(dhcp_lif_t *lif, in_addr_t addr_hbo)
+open_ip_lif(dhcp_lif_t *lif, in_addr_t addr_hbo, boolean_t bringup)
{
const char *errmsg;
struct lifreq lifr;
int on = 1;
uchar_t ttl = 255;
+ uint32_t ifindex;
+ dhcp_pif_t *pif = lif->lif_pif;
if (lif->lif_sock_ip_fd != -1) {
dhcpmsg(MSG_WARNING, "open_ip_lif: socket already open on %s",
@@ -1270,7 +1347,7 @@ open_ip_lif(dhcp_lif_t *lif, in_addr_t addr_hbo)
}
if (setsockopt(lif->lif_sock_ip_fd, IPPROTO_IP, IP_DHCPINIT_IF,
- &lif->lif_pif->pif_index, sizeof (int)) == -1) {
+ &pif->pif_index, sizeof (int)) == -1) {
errmsg = "cannot set IP_DHCPINIT_IF";
goto failure;
}
@@ -1288,23 +1365,40 @@ open_ip_lif(dhcp_lif_t *lif, in_addr_t addr_hbo)
goto failure;
}
- if (setsockopt(lif->lif_sock_ip_fd, IPPROTO_IP, IP_BOUND_IF,
- &lif->lif_pif->pif_index, sizeof (int)) == -1) {
+ ifindex = pif->pif_under_ipmp ? pif->pif_grindex : pif->pif_index;
+ if (setsockopt(lif->lif_sock_ip_fd, IPPROTO_IP, IP_BOUND_IF, &ifindex,
+ 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)) {
+ /*
+ * If the lif is part of an interface under IPMP, IFF_NOFAILOVER must
+ * be set or the kernel will prevent us from setting IFF_DHCPRUNNING
+ * (since the subsequent IFF_UP would lead to migration). We set
+ * IFF_DEPRECATED too since the kernel will set it automatically when
+ * setting IFF_NOFAILOVER, causing our lif_flags value to grow stale.
+ */
+ if (pif->pif_under_ipmp && !(lifr.lifr_flags & IFF_NOFAILOVER)) {
+ lifr.lifr_flags |= IFF_NOFAILOVER | IFF_DEPRECATED;
+ if (ioctl(v4_sock_fd, SIOCSLIFFLAGS, &lifr) == -1) {
+ errmsg = "cannot set IFF_NOFAILOVER";
+ goto failure;
+ }
+ }
+ lif->lif_flags = lifr.lifr_flags;
+
+ /*
+ * If this is initial bringup, make sure the address we're acquiring a
+ * lease on is IFF_UP.
+ */
+ if (bringup && !(lifr.lifr_flags & IFF_UP)) {
/*
* Start from a clean slate.
*/
@@ -1330,6 +1424,30 @@ open_ip_lif(dhcp_lif_t *lif, in_addr_t addr_hbo)
((struct sockaddr_in *)&lifr.lifr_addr)->sin_addr.s_addr;
}
+ /*
+ * Usually, bringing up the address we're acquiring a lease on is
+ * sufficient to allow packets to be sent and received via the
+ * IP_BOUND_IF we did earlier. However, if we're acquiring a lease on
+ * an underlying IPMP interface, the group interface will be used for
+ * sending and receiving IP packets via IP_BOUND_IF. Thus, ensure at
+ * least one address on the group interface is IFF_UP.
+ */
+ if (bringup && pif->pif_under_ipmp) {
+ (void) strlcpy(lifr.lifr_name, pif->pif_grifname, LIFNAMSIZ);
+ if (ioctl(v4_sock_fd, SIOCGLIFFLAGS, &lifr) == -1) {
+ errmsg = "cannot get IPMP group interface flags";
+ goto failure;
+ }
+
+ if (!(lifr.lifr_flags & IFF_UP)) {
+ lifr.lifr_flags |= IFF_UP;
+ if (ioctl(v4_sock_fd, SIOCSLIFFLAGS, &lifr) == -1) {
+ errmsg = "cannot bring up IPMP group interface";
+ goto failure;
+ }
+ }
+ }
+
lif->lif_packet_id = iu_register_event(eh, lif->lif_sock_ip_fd, POLLIN,
dhcp_packet_lif, lif);
if (lif->lif_packet_id == -1) {
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h b/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h
index a59e3ea68d..46cf30bedb 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef INTERFACE_H
#define INTERFACE_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Interface.[ch] encapsulate all of the agent's knowledge of network
* interfaces from the DHCP agent's perspective. See interface.c for
@@ -66,6 +64,9 @@ struct dhcp_pif_s {
boolean_t pif_running; /* interface is running */
uint_t pif_hold_count; /* reference count */
char pif_name[LIFNAMSIZ];
+ char pif_grifname[LIFNAMSIZ];
+ uint32_t pif_grindex; /* interface index for pif_grifname */
+ boolean_t pif_under_ipmp; /* is an ipmp underlying interface */
};
struct dhcp_lif_s {
@@ -182,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 *, in_addr_t);
+boolean_t open_ip_lif(dhcp_lif_t *, in_addr_t, boolean_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 8a32b55ea5..a763530436 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/packet.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
@@ -970,7 +968,10 @@ send_pkt_internal(dhcp_smach_t *dsmp)
ipi6->ipi6_addr = lif->lif_v6addr;
else
ipi6->ipi6_addr = my_in6addr_any;
- ipi6->ipi6_ifindex = lif->lif_pif->pif_index;
+ if (lif->lif_pif->pif_under_ipmp)
+ ipi6->ipi6_ifindex = lif->lif_pif->pif_grindex;
+ else
+ ipi6->ipi6_ifindex = lif->lif_pif->pif_index;
cmsg->cmsg_len = (char *)(ipi6 + 1) - (char *)cmsg;
/*
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c
index a8c05de986..78da07aebf 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/request.c
@@ -19,14 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* REQUESTING state of the client state machine.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <string.h>
#include <search.h>
@@ -1008,7 +1006,8 @@ dhcp_acknak_global(iu_eh_t *ehp, int fd, short events, iu_event_id_t id,
for (dsmp = lookup_smach_by_xid(xid, NULL, isv6); dsmp != NULL;
dsmp = lookup_smach_by_xid(xid, dsmp, isv6)) {
pif = dsmp->dsm_lif->lif_pif;
- if (pif->pif_index == plp->ifindex)
+ if (pif->pif_index == plp->ifindex ||
+ pif->pif_under_ipmp && pif->pif_grindex == plp->ifindex)
break;
}
diff --git a/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.c b/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.c
index 9ae7fd7aba..852b428551 100644
--- a/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.c
+++ b/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.c
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* This module contains core functions for managing DHCP state machine
* instances.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <search.h>
#include <string.h>
@@ -151,7 +149,7 @@ insert_smach(dhcp_lif_t *lif, int *error)
/*
* With IPv4 DHCP, we use a socket per lif.
*/
- if (!open_ip_lif(lif, INADDR_ANY)) {
+ if (!open_ip_lif(lif, INADDR_ANY, B_TRUE)) {
dhcpmsg(MSG_ERR, "unable to open socket for %s",
lif->lif_name);
/* This will also dispose of the LIF */
@@ -696,14 +694,15 @@ set_smach_state(dhcp_smach_t *dsmp, DHCPSTATE state)
if (is_bound_state(dsmp->dsm_state)) {
if (!is_bound_state(state)) {
close_ip_lif(lif);
- if (!open_ip_lif(lif, INADDR_ANY))
+ if (!open_ip_lif(lif, INADDR_ANY,
+ B_FALSE))
return (B_FALSE);
}
} else {
if (is_bound_state(state)) {
close_ip_lif(lif);
if (!open_ip_lif(lif,
- ntohl(lif->lif_addr)))
+ ntohl(lif->lif_addr), B_FALSE))
return (B_FALSE);
}
}
@@ -952,11 +951,14 @@ no_specified_id:
* unable to parse it. We need to determine if a Client ID is required
* and, if so, generate one.
*
- * If it's IPv4 and not a logical interface, then we need to preserve
- * backward-compatibility by avoiding new-fangled DUID/IAID
- * construction.
+ * If it's IPv4, not in an IPMP group, and not a logical interface,
+ * then we need to preserve backward-compatibility by avoiding
+ * new-fangled DUID/IAID construction. (Note: even for IPMP test
+ * addresses, we construct a DUID/IAID since we may renew a lease for
+ * an IPMP test address on any functioning IP interface in the group.)
*/
- if (!pif->pif_isv6 && strchr(dsmp->dsm_name, ':') == NULL) {
+ if (!pif->pif_isv6 && pif->pif_grifname[0] == '\0' &&
+ strchr(dsmp->dsm_name, ':') == NULL) {
if (pif->pif_hwtype == ARPHRD_IB) {
/*
* This comes from the DHCP over IPoIB specification.
diff --git a/usr/src/cmd/cmd-inet/sbin/ifparse/ifparse.c b/usr/src/cmd/cmd-inet/sbin/ifparse/ifparse.c
index 47e1202b32..d73722cc55 100644
--- a/usr/src/cmd/cmd-inet/sbin/ifparse/ifparse.c
+++ b/usr/src/cmd/cmd-inet/sbin/ifparse/ifparse.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
@@ -8,8 +8,6 @@
* specifies the terms and conditions for redistribution.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Ifparse splits up an ifconfig command line, and was written for use
* with the networking boot scripts; see $SRC/cmd/svc/shell/net_include.sh
@@ -184,6 +182,7 @@ struct cmd {
{ "auto-revarp", 0, AF_INET, PARSEFIXED},
{ "plumb", 0, AF_ANY, PARSENOW },
{ "unplumb", 0, AF_ANY, PARSENOW },
+ { "ipmp", 0, AF_ANY, PARSELOG0 },
{ "subnet", NEXTARG, AF_ANY, 0 },
{ "token", NEXTARG, AF_INET6, PARSELOG0 },
{ "tsrc", NEXTARG, AF_ANY, PARSELOG0 },