summaryrefslogtreecommitdiff
path: root/usr/src/lib/libipmp/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libipmp/common')
-rw-r--r--usr/src/lib/libipmp/common/ipmp.c20
-rw-r--r--usr/src/lib/libipmp/common/ipmp.h12
-rw-r--r--usr/src/lib/libipmp/common/ipmp_admin.c104
-rw-r--r--usr/src/lib/libipmp/common/ipmp_admin.h50
-rw-r--r--usr/src/lib/libipmp/common/ipmp_mpathd.c26
-rw-r--r--usr/src/lib/libipmp/common/ipmp_mpathd.h81
-rw-r--r--usr/src/lib/libipmp/common/ipmp_query.c498
-rw-r--r--usr/src/lib/libipmp/common/ipmp_query.h112
-rw-r--r--usr/src/lib/libipmp/common/ipmp_query_impl.h41
-rw-r--r--usr/src/lib/libipmp/common/llib-lipmp10
-rw-r--r--usr/src/lib/libipmp/common/mapfile-vers13
11 files changed, 779 insertions, 188 deletions
diff --git a/usr/src/lib/libipmp/common/ipmp.c b/usr/src/lib/libipmp/common/ipmp.c
index b9a7984889..cf9c3c7c3c 100644
--- a/usr/src/lib/libipmp/common/ipmp.c
+++ b/usr/src/lib/libipmp/common/ipmp.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 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"
-
/*
* IPMP general interfaces (PSARC/2002/615).
*/
@@ -34,6 +31,8 @@
#include <stdlib.h>
#include <locale.h>
#include <unistd.h>
+#include <string.h>
+#include <errno.h>
#include "ipmp_impl.h"
@@ -92,13 +91,15 @@ static char *errmsgs[IPMP_NERR] = {
"operation failed", /* 1 IPMP_FAILURE */
"minimum failover redundancy not met", /* 2 IPMP_EMINRED */
"failback disabled", /* 3 IPMP_EFBDISABLED */
- "unable to completely fail back", /* 4 IPMP_EFBPARTIAL */
+ "unknown IPMP data address", /* 4 IPMP_EUNKADDR */
"invalid argument", /* 5 IPMP_EINVAL */
"out of memory", /* 6 IPMP_ENOMEM */
"cannot contact in.mpathd", /* 7 IPMP_ENOMPATHD */
"unknown IPMP group", /* 8 IPMP_EUNKGROUP */
"interface is not using IPMP", /* 9 IPMP_EUNKIF */
- "unable to communicate with in.mpathd" /* 10 IPMP_EPROTO */
+ "unable to communicate with in.mpathd", /* 10 IPMP_EPROTO */
+ "interface has duplicate hardware address"
+ /* 11 IPMP_EHWADDRDUP */
};
/*
@@ -110,5 +111,8 @@ ipmp_errmsg(int error)
if (error >= IPMP_NERR || error < 0)
return (dgettext(TEXT_DOMAIN, "<unknown error>"));
+ if (error == IPMP_FAILURE)
+ return (strerror(errno));
+
return (dgettext(TEXT_DOMAIN, errmsgs[error]));
}
diff --git a/usr/src/lib/libipmp/common/ipmp.h b/usr/src/lib/libipmp/common/ipmp.h
index 0112615a84..2ca0a9b2b9 100644
--- a/usr/src/lib/libipmp/common/ipmp.h
+++ b/usr/src/lib/libipmp/common/ipmp.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _IPMP_H
#define _IPMP_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* General IPMP-related definitions and functions.
*
@@ -50,13 +47,14 @@ enum {
IPMP_FAILURE, /* operation failed (check errno) */
IPMP_EMINRED, /* minimum failover redundancy not met */
IPMP_EFBDISABLED, /* failback disabled */
- IPMP_EFBPARTIAL, /* unable to completely fail back */
+ IPMP_EUNKADDR, /* unknown IPMP data address */
IPMP_EINVAL, /* invalid argument */
IPMP_ENOMEM, /* out of memory */
IPMP_ENOMPATHD, /* cannot contact in.mpathd */
IPMP_EUNKGROUP, /* unknown IPMP group */
IPMP_EUNKIF, /* interface is not using IPMP */
IPMP_EPROTO, /* unable to communicate with in.mpathd */
+ IPMP_EHWADDRDUP, /* interface has duplicate hardware address */
IPMP_NERR /* number of error codes */
};
diff --git a/usr/src/lib/libipmp/common/ipmp_admin.c b/usr/src/lib/libipmp/common/ipmp_admin.c
new file mode 100644
index 0000000000..8a282f5286
--- /dev/null
+++ b/usr/src/lib/libipmp/common/ipmp_admin.c
@@ -0,0 +1,104 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * IPMP administrative interfaces (see PSARC/2007/272).
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "ipmp_impl.h"
+#include "ipmp_mpathd.h"
+#include "ipmp_admin.h"
+
+static int
+ipmp_command(ipmp_handle_t handle, const void *req, uint_t reqsize)
+{
+ ipmp_state_t *statep = (ipmp_state_t *)handle;
+ mi_result_t result;
+ struct timeval end;
+ int save_errno;
+ int retval;
+
+ if (gettimeofday(&end, NULL) == -1)
+ return (IPMP_FAILURE);
+ end.tv_sec += IPMP_REQTIMEOUT;
+
+ assert(statep->st_fd == -1);
+ retval = ipmp_connect(&statep->st_fd);
+ if (retval != IPMP_SUCCESS)
+ return (retval);
+
+ retval = ipmp_write(statep->st_fd, req, reqsize);
+ if (retval != IPMP_SUCCESS)
+ goto out;
+
+ retval = ipmp_read(statep->st_fd, &result, sizeof (result), &end);
+ if (retval != IPMP_SUCCESS)
+ goto out;
+
+ errno = result.me_sys_error;
+ retval = result.me_mpathd_error;
+out:
+ save_errno = errno;
+ (void) close(statep->st_fd);
+ statep->st_fd = -1;
+ errno = save_errno;
+ return (retval);
+}
+
+int
+ipmp_offline(ipmp_handle_t handle, const char *ifname, uint_t minred)
+{
+ mi_offline_t mio;
+
+ mio.mio_command = MI_OFFLINE;
+ mio.mio_min_redundancy = minred;
+ (void) strlcpy(mio.mio_ifname, ifname, LIFNAMSIZ);
+ return (ipmp_command(handle, &mio, sizeof (mio)));
+}
+
+int
+ipmp_undo_offline(ipmp_handle_t handle, const char *ifname)
+{
+ mi_undo_offline_t miu;
+
+ miu.miu_command = MI_UNDO_OFFLINE;
+ (void) strlcpy(miu.miu_ifname, ifname, LIFNAMSIZ);
+ return (ipmp_command(handle, &miu, sizeof (miu)));
+}
+
+int
+ipmp_ping_daemon(ipmp_handle_t handle)
+{
+ mi_ping_t mip;
+
+ mip.mip_command = MI_PING;
+ return (ipmp_command(handle, &mip, sizeof (mip)));
+}
diff --git a/usr/src/lib/libipmp/common/ipmp_admin.h b/usr/src/lib/libipmp/common/ipmp_admin.h
new file mode 100644
index 0000000000..fa0986f7fa
--- /dev/null
+++ b/usr/src/lib/libipmp/common/ipmp_admin.h
@@ -0,0 +1,50 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _IPMP_ADMIN_H
+#define _IPMP_ADMIN_H
+
+#include <ipmp.h>
+#include <sys/types.h>
+
+/*
+ * IPMP administrative interfaces.
+ *
+ * These interfaces may only be used within ON or after signing a contract
+ * with ON. For documentation, refer to PSARC/2007/272.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ipmp_offline(ipmp_handle_t, const char *, uint_t);
+extern int ipmp_undo_offline(ipmp_handle_t, const char *);
+extern int ipmp_ping_daemon(ipmp_handle_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _IPMP_ADMIN_H */
diff --git a/usr/src/lib/libipmp/common/ipmp_mpathd.c b/usr/src/lib/libipmp/common/ipmp_mpathd.c
index ee1d35de33..e24de71017 100644
--- a/usr/src/lib/libipmp/common/ipmp_mpathd.c
+++ b/usr/src/lib/libipmp/common/ipmp_mpathd.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -18,14 +17,11 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
- */
-/*
- * Copyright 2002 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"
-
/*
* Low-level interfaces for communicating with in.mpathd(1M).
*
@@ -66,16 +62,16 @@ ipmp_connect(int *fdp)
return (IPMP_FAILURE);
/*
- * Enable TCP_ANONPRIVBIND so the kernel will choose our source port.
- * Since we're using loopback sockets, requiring use of privileged
- * source ports is sufficient for security.
+ * If we have sufficient privilege, enable TCP_ANONPRIVBIND so the
+ * kernel will choose a privileged source port (since in.mpathd only
+ * accepts requests on loopback, this is sufficient for security).
+ * If not, drive on since MI_QUERY and MI_PING commands are allowed
+ * from non-privileged ports.
*/
- if (setsockopt(fd, IPPROTO_TCP, TCP_ANONPRIVBIND, &on,
- sizeof (on)) == -1)
- goto fail;
+ (void) setsockopt(fd, IPPROTO_TCP, TCP_ANONPRIVBIND, &on, sizeof (on));
/*
- * Bind to a privileged port chosen by the kernel.
+ * Bind to a port chosen by the kernel.
*/
(void) memset(&sin, 0, sizeof (struct sockaddr_in));
sin.sin_port = htons(0);
diff --git a/usr/src/lib/libipmp/common/ipmp_mpathd.h b/usr/src/lib/libipmp/common/ipmp_mpathd.h
index 61ae71b78f..7df3b4fd92 100644
--- a/usr/src/lib/libipmp/common/ipmp_mpathd.h
+++ b/usr/src/lib/libipmp/common/ipmp_mpathd.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -18,26 +17,17 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
- */
-/*
- * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _IPMP_MPATHD_H
#define _IPMP_MPATHD_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Definitions for the messaging protocol between in.mpathd and libipmp.
- * This interface is loosely documented in PSARC/2000/306.
- *
- * PLEASE NOTE: Although this interface is officially consolidation-private,
- * we will be reclassifying it as project-private in the future, and
- * transitioning any existing consumers to use higher-level libipmp routines.
- *
- * Put another way: treat this as if it was project-private!
+ * This interface is project-private to the IPMP subsystem.
*/
#include <sys/types.h>
@@ -49,33 +39,41 @@ extern "C" {
#endif
#define MPATHD_PORT 5999
-#define MPATHD_PATH "/usr/lib/inet/in.mpathd"
+#define MPATHD_PATH "/lib/inet/in.mpathd"
/*
* Supported commands.
*/
enum {
- MI_PING = 0, /* sanity test */
+ MI_PING = 0, /* ping in.mpathd */
MI_OFFLINE = 1, /* offline the interface */
MI_UNDO_OFFLINE = 2, /* undo the offline */
- MI_SETOINDEX = 3, /* set original interface index */
- MI_QUERY = 4, /* query ipmp-related information */
+ MI_QUERY = 3, /* query ipmp-related information */
MI_NCMD /* total number of commands */
};
/*
* Types of information which can be requested and received (except for
- * IPMP_IFLIST, which can only be received).
+ * IPMP_IFLIST and IPMP_ADDRLIST, which can only be received).
*/
typedef enum {
IPMP_GROUPLIST = 1,
IPMP_GROUPINFO = 2,
IPMP_IFINFO = 3,
IPMP_IFLIST = 4,
- IPMP_SNAP = 5
+ IPMP_SNAP = 5,
+ IPMP_ADDRLIST = 6,
+ IPMP_ADDRINFO = 7
} ipmp_infotype_t;
/*
+ * Daemon ping request.
+ */
+typedef struct mi_ping {
+ uint32_t mip_command;
+} mi_ping_t;
+
+/*
* Interface offline request; `mio_ifname' is the interface to offline;
* `mio_min_redundancy' is the minimum amount of usable interfaces after
* offline that must exist for the operation to succeed.
@@ -83,7 +81,6 @@ typedef enum {
typedef struct mi_offline {
uint32_t mio_command;
char mio_ifname[LIFNAMSIZ];
- char mio_move_to_if[LIFNAMSIZ]; /* currently unused */
uint32_t mio_min_redundancy;
} mi_offline_t;
@@ -97,24 +94,12 @@ typedef struct mi_undo_offline {
} mi_undo_offline_t;
/*
- * Set original interface index request: `mis_lifname' is the name of the
- * logical interface that is having its index reset; `mis_new_pifname' is the
- * name of the interface whose index will be associated with `mis_lifname';
- * `mis_iftype' is the interface type.
- */
-typedef struct mi_setoindex {
- uint32_t mis_command;
- char mis_lifname[LIFNAMSIZ];
- char mis_new_pifname[LIFNAMSIZ];
- uint32_t mis_iftype;
-} mi_setoindex_t;
-
-/*
* Retrieve IPMP-related information: `miq_inforeq' is the type of information
- * being request (see above for the list of types). If the request is for
- * either IPMP_GROUPINFO or IPMP_IFINFO, then either `miq_grname' or
- * `miq_ifname' should be set (respectively) to indicate the name of the
- * group or interface to retrieve the information for.
+ * being request (see above for the list of types). If the request type is
+ * IPMP_GROUPINFO, then `miq_grname' indicates the group. If the request type
+ * is IPMP_IFINFO, then `miq_ifname' indicates the interface. If the request
+ * type is IPMP_ADDRINFO then `miq_grname' indicates the group and `miq_addr'
+ * indicates the address.
*/
typedef struct mi_query {
uint32_t miq_command;
@@ -123,6 +108,7 @@ typedef struct mi_query {
char miqu_ifname[LIFNAMSIZ];
char miqu_grname[LIFGRNAMSIZ];
} miq_infodata;
+ struct sockaddr_storage miq_addr;
} mi_query_t;
#define miq_ifname miq_infodata.miqu_ifname
#define miq_grname miq_infodata.miqu_grname
@@ -132,10 +118,10 @@ typedef struct mi_query {
* requirement for receiving any command.
*/
union mi_commands {
- uint32_t mi_command;
+ uint32_t mi_command;
+ mi_ping_t mi_pcmd;
mi_offline_t mi_ocmd;
mi_undo_offline_t mi_ucmd;
- mi_setoindex_t mi_scmd;
mi_query_t mi_qcmd;
};
@@ -147,18 +133,7 @@ typedef struct mi_result {
uint32_t me_mpathd_error; /* Mpathd error */
} mi_result_t;
-/*
- * Legacy values for me_mpathd_error; the daemon now returns the IPMP
- * error codes defined in <ipmp.h>, which are compatible with these error
- * codes. These will be removed in the future.
- */
-enum {
- MPATHD_SUCCESS = 0, /* operation succeeded */
- MPATHD_SYS_ERROR = 1, /* check me_sys_error for the errno */
- MPATHD_MIN_RED_ERROR = 2, /* minimum redundancy not met */
- MPATHD_FAILBACK_DISABLED = 3, /* failback administratively disabled */
- MPATHD_FAILBACK_PARTIAL = 4 /* unable to completely failback */
-};
+#define IPMP_REQTIMEOUT 5 /* seconds */
extern int ipmp_connect(int *);
extern int ipmp_read(int, void *, size_t, const struct timeval *);
diff --git a/usr/src/lib/libipmp/common/ipmp_query.c b/usr/src/lib/libipmp/common/ipmp_query.c
index 8a7dc7ee69..a0af2da578 100644
--- a/usr/src/lib/libipmp/common/ipmp_query.c
+++ b/usr/src/lib/libipmp/common/ipmp_query.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -18,20 +17,18 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
- */
-/*
- * Copyright 2002 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"
-
/*
- * IPMP query interfaces (PSARC/2002/615).
+ * IPMP query interfaces (see PSARC/2002/615 and PSARC/2007/272).
*/
#include <assert.h>
#include <errno.h>
+#include <libinetutil.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
@@ -41,13 +38,19 @@
#include "ipmp_mpathd.h"
#include "ipmp_query_impl.h"
-#define IPMP_REQTIMEOUT 5 /* seconds */
-
static ipmp_ifinfo_t *ipmp_ifinfo_clone(ipmp_ifinfo_t *);
+static ipmp_addrinfo_t *ipmp_addrinfo_clone(ipmp_addrinfo_t *);
+static ipmp_addrlist_t *ipmp_addrlist_clone(ipmp_addrlist_t *);
static ipmp_grouplist_t *ipmp_grouplist_clone(ipmp_grouplist_t *);
static ipmp_groupinfo_t *ipmp_groupinfo_clone(ipmp_groupinfo_t *);
+static ipmp_iflist_t *ipmp_iflist_create(uint_t, char (*)[LIFNAMSIZ]);
+static void ipmp_freeiflist(ipmp_iflist_t *);
+static ipmp_addrlist_t *ipmp_addrlist_create(uint_t, struct sockaddr_storage *);
+static void ipmp_freeaddrlist(ipmp_addrlist_t *);
static ipmp_groupinfo_t *ipmp_snap_getgroupinfo(ipmp_snap_t *, const char *);
static ipmp_ifinfo_t *ipmp_snap_getifinfo(ipmp_snap_t *, const char *);
+static ipmp_addrinfo_t *ipmp_snap_getaddrinfo(ipmp_snap_t *, const char *,
+ struct sockaddr_storage *);
static int ipmp_snap_take(ipmp_state_t *, ipmp_snap_t **);
static boolean_t ipmp_checktlv(ipmp_infotype_t, size_t, void *);
static int ipmp_querydone(ipmp_state_t *, int);
@@ -62,7 +65,7 @@ static int ipmp_querydone(ipmp_state_t *, int);
*/
static int
ipmp_sendquery(ipmp_state_t *statep, ipmp_infotype_t type, const char *name,
- struct timeval *endtp)
+ const void *addr, struct timeval *endtp)
{
mi_query_t query;
mi_result_t result;
@@ -72,6 +75,11 @@ ipmp_sendquery(ipmp_state_t *statep, ipmp_infotype_t type, const char *name,
query.miq_inforeq = type;
switch (type) {
+ case IPMP_ADDRINFO:
+ (void) strlcpy(query.miq_grname, name, LIFGRNAMSIZ);
+ query.miq_addr = *(struct sockaddr_storage *)addr;
+ break;
+
case IPMP_GROUPINFO:
(void) strlcpy(query.miq_grname, name, LIFGRNAMSIZ);
break;
@@ -138,6 +146,61 @@ ipmp_readinfo(ipmp_state_t *statep, ipmp_infotype_t infotype, void **infop,
}
/*
+ * Using `statep', read in the remaining IPMP group information TLVs from
+ * in.mpathd into `grinfop' before the current time becomes `endtp'. Returns
+ * an IPMP error code. On failure, `grinfop' will have its original contents.
+ */
+static int
+ipmp_readgroupinfo_lists(ipmp_state_t *statep, ipmp_groupinfo_t *grinfop,
+ const struct timeval *endtp)
+{
+ int retval;
+ ipmp_iflist_t *iflistp;
+ ipmp_addrlist_t *adlistp;
+
+ retval = ipmp_readinfo(statep, IPMP_IFLIST, (void **)&iflistp, endtp);
+ if (retval != IPMP_SUCCESS)
+ return (retval);
+
+ retval = ipmp_readinfo(statep, IPMP_ADDRLIST, (void **)&adlistp, endtp);
+ if (retval != IPMP_SUCCESS) {
+ ipmp_freeiflist(iflistp);
+ return (retval);
+ }
+
+ grinfop->gr_iflistp = iflistp;
+ grinfop->gr_adlistp = adlistp;
+ return (IPMP_SUCCESS);
+}
+
+/*
+ * Using `statep', read in the remaining IPMP interface information TLVs from
+ * in.mpathd into `ifinfop' before the current time becomes `endtp'. Returns
+ * an IPMP error code. On failure, `ifinfop' will have its original contents.
+ */
+static int
+ipmp_readifinfo_lists(ipmp_state_t *statep, ipmp_ifinfo_t *ifinfop,
+ const struct timeval *endtp)
+{
+ int retval;
+ ipmp_addrlist_t *tlist4p, *tlist6p;
+
+ retval = ipmp_readinfo(statep, IPMP_ADDRLIST, (void **)&tlist4p, endtp);
+ if (retval != IPMP_SUCCESS)
+ return (retval);
+
+ retval = ipmp_readinfo(statep, IPMP_ADDRLIST, (void **)&tlist6p, endtp);
+ if (retval != IPMP_SUCCESS) {
+ ipmp_freeaddrlist(tlist4p);
+ return (retval);
+ }
+
+ ifinfop->if_targinfo4.it_targlistp = tlist4p;
+ ifinfop->if_targinfo6.it_targlistp = tlist6p;
+ return (IPMP_SUCCESS);
+}
+
+/*
* Complete the query operation started in ipmp_sendquery(). The interface is
* designed to be easy to use in the `return' statement of a function, and
* thus returns the passed in `retval' and preserves `errno'.
@@ -169,7 +232,7 @@ ipmp_getgrouplist(ipmp_handle_t handle, ipmp_grouplist_t **grlistpp)
return (*grlistpp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM);
}
- retval = ipmp_sendquery(statep, IPMP_GROUPLIST, NULL, &end);
+ retval = ipmp_sendquery(statep, IPMP_GROUPLIST, NULL, NULL, &end);
if (retval != IPMP_SUCCESS)
return (retval);
@@ -196,7 +259,6 @@ ipmp_getgroupinfo(ipmp_handle_t handle, const char *name,
ipmp_groupinfo_t **grinfopp)
{
ipmp_state_t *statep = handle;
- ipmp_iflist_t *iflistp;
int retval;
struct timeval end;
ipmp_groupinfo_t *grinfop;
@@ -210,7 +272,7 @@ ipmp_getgroupinfo(ipmp_handle_t handle, const char *name,
return (*grinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM);
}
- retval = ipmp_sendquery(statep, IPMP_GROUPINFO, name, &end);
+ retval = ipmp_sendquery(statep, IPMP_GROUPINFO, name, NULL, &end);
if (retval != IPMP_SUCCESS)
return (retval);
@@ -218,11 +280,9 @@ ipmp_getgroupinfo(ipmp_handle_t handle, const char *name,
if (retval != IPMP_SUCCESS)
return (ipmp_querydone(statep, retval));
- retval = ipmp_readinfo(statep, IPMP_IFLIST, (void **)&iflistp, &end);
+ retval = ipmp_readgroupinfo_lists(statep, *grinfopp, &end);
if (retval != IPMP_SUCCESS)
free(*grinfopp);
- else
- (*grinfopp)->gr_iflistp = iflistp;
return (ipmp_querydone(statep, retval));
}
@@ -233,7 +293,8 @@ ipmp_getgroupinfo(ipmp_handle_t handle, const char *name,
void
ipmp_freegroupinfo(ipmp_groupinfo_t *grinfop)
{
- free(grinfop->gr_iflistp);
+ ipmp_freeaddrlist(grinfop->gr_adlistp);
+ ipmp_freeiflist(grinfop->gr_iflistp);
free(grinfop);
}
@@ -259,11 +320,18 @@ ipmp_getifinfo(ipmp_handle_t handle, const char *name, ipmp_ifinfo_t **ifinfopp)
return (*ifinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM);
}
- retval = ipmp_sendquery(statep, IPMP_IFINFO, name, &end);
+ retval = ipmp_sendquery(statep, IPMP_IFINFO, name, NULL, &end);
if (retval != IPMP_SUCCESS)
return (retval);
retval = ipmp_readinfo(statep, IPMP_IFINFO, (void **)ifinfopp, &end);
+ if (retval != IPMP_SUCCESS)
+ return (ipmp_querydone(statep, retval));
+
+ retval = ipmp_readifinfo_lists(statep, *ifinfopp, &end);
+ if (retval != IPMP_SUCCESS)
+ free(*ifinfopp);
+
return (ipmp_querydone(statep, retval));
}
@@ -273,10 +341,52 @@ ipmp_getifinfo(ipmp_handle_t handle, const char *name, ipmp_ifinfo_t **ifinfopp)
void
ipmp_freeifinfo(ipmp_ifinfo_t *ifinfop)
{
+ ipmp_freeaddrlist(ifinfop->if_targinfo4.it_targlistp);
+ ipmp_freeaddrlist(ifinfop->if_targinfo6.it_targlistp);
free(ifinfop);
}
/*
+ * Using `handle', get the address information associated with address `addrp'
+ * on group `grname' and store the results in a dynamically allocated buffer
+ * pointed to by `*adinfopp'. Returns an IPMP error code.
+ */
+int
+ipmp_getaddrinfo(ipmp_handle_t handle, const char *grname,
+ struct sockaddr_storage *addrp, ipmp_addrinfo_t **adinfopp)
+{
+ ipmp_state_t *statep = handle;
+ ipmp_addrinfo_t *adinfop;
+ int retval;
+ struct timeval end;
+
+ if (statep->st_snap != NULL) {
+ adinfop = ipmp_snap_getaddrinfo(statep->st_snap, grname, addrp);
+ if (adinfop == NULL)
+ return (IPMP_EUNKADDR);
+
+ *adinfopp = ipmp_addrinfo_clone(adinfop);
+ return (*adinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM);
+ }
+
+ retval = ipmp_sendquery(statep, IPMP_ADDRINFO, grname, addrp, &end);
+ if (retval != IPMP_SUCCESS)
+ return (retval);
+
+ retval = ipmp_readinfo(statep, IPMP_ADDRINFO, (void **)adinfopp, &end);
+ return (ipmp_querydone(statep, retval));
+}
+
+/*
+ * Free the address information pointed to by `adinfop'.
+ */
+void
+ipmp_freeaddrinfo(ipmp_addrinfo_t *adinfop)
+{
+ free(adinfop);
+}
+
+/*
* Check if `buf' has a NUL byte in its first `bufsize' bytes.
*/
static boolean_t
@@ -300,12 +410,25 @@ ipmp_checktlv(ipmp_infotype_t type, size_t len, void *value)
ipmp_ifinfo_t *ifinfop;
ipmp_grouplist_t *grlistp;
ipmp_groupinfo_t *grinfop;
+ ipmp_addrlist_t *adlistp;
unsigned int i;
switch (type) {
+ case IPMP_ADDRINFO:
+ if (len != sizeof (ipmp_addrinfo_t))
+ return (B_FALSE);
+ break;
+
+ case IPMP_ADDRLIST:
+ adlistp = (ipmp_addrlist_t *)value;
+ if (len < IPMP_ADDRLIST_SIZE(0) ||
+ len < IPMP_ADDRLIST_SIZE(adlistp->al_naddr))
+ return (B_FALSE);
+ break;
+
case IPMP_IFLIST:
iflistp = (ipmp_iflist_t *)value;
- if (len < IPMP_IFLIST_MINSIZE ||
+ if (len < IPMP_IFLIST_SIZE(0) ||
len < IPMP_IFLIST_SIZE(iflistp->il_nif))
return (B_FALSE);
@@ -326,7 +449,7 @@ ipmp_checktlv(ipmp_infotype_t type, size_t len, void *value)
case IPMP_GROUPLIST:
grlistp = (ipmp_grouplist_t *)value;
- if (len < IPMP_GROUPLIST_MINSIZE ||
+ if (len < IPMP_GROUPLIST_SIZE(0) ||
len < IPMP_GROUPLIST_SIZE(grlistp->gl_ngroup))
return (B_FALSE);
@@ -357,9 +480,8 @@ ipmp_checktlv(ipmp_infotype_t type, size_t len, void *value)
}
/*
- * Create a group list with signature `sig' containing `ngroup' groups named
- * by `groups'. Returns a pointer to the new group list on success, or NULL
- * on failure.
+ * Create a group list; arguments match ipmp_grouplist_t fields. Returns a
+ * pointer to the new group list on success, or NULL on failure.
*/
ipmp_grouplist_t *
ipmp_grouplist_create(uint64_t sig, unsigned int ngroup,
@@ -392,13 +514,80 @@ ipmp_grouplist_clone(ipmp_grouplist_t *grlistp)
}
/*
- * Create an interface information structure for interface `name' and
- * associate `group', `state' and `type' with it. Returns a pointer to the
- * interface information on success, or NULL on failure.
+ * Create target information; arguments match ipmp_targinfo_t fields. Returns
+ * a pointer to the new target info on success, or NULL on failure.
+ */
+ipmp_targinfo_t *
+ipmp_targinfo_create(const char *name, struct sockaddr_storage *testaddrp,
+ ipmp_if_targmode_t targmode, uint_t ntarg, struct sockaddr_storage *targs)
+{
+ ipmp_targinfo_t *targinfop;
+
+ targinfop = malloc(sizeof (ipmp_targinfo_t));
+ if (targinfop == NULL)
+ return (NULL);
+
+ targinfop->it_testaddr = *testaddrp;
+ targinfop->it_targmode = targmode;
+ targinfop->it_targlistp = ipmp_addrlist_create(ntarg, targs);
+ if (targinfop->it_targlistp == NULL) {
+ ipmp_freetarginfo(targinfop);
+ return (NULL);
+ }
+ (void) strlcpy(targinfop->it_name, name, LIFNAMSIZ);
+
+ return (targinfop);
+}
+
+/*
+ * Free the target information pointed to by `targinfop'.
+ */
+void
+ipmp_freetarginfo(ipmp_targinfo_t *targinfop)
+{
+ free(targinfop->it_targlistp);
+ free(targinfop);
+}
+
+/*
+ * Create an interface list; arguments match ipmp_iflist_t fields. Returns a
+ * pointer to the new interface list on success, or NULL on failure.
+ */
+static ipmp_iflist_t *
+ipmp_iflist_create(uint_t nif, char (*ifs)[LIFNAMSIZ])
+{
+ unsigned int i;
+ ipmp_iflist_t *iflistp;
+
+ iflistp = malloc(IPMP_IFLIST_SIZE(nif));
+ if (iflistp == NULL)
+ return (NULL);
+
+ iflistp->il_nif = nif;
+ for (i = 0; i < nif; i++)
+ (void) strlcpy(iflistp->il_ifs[i], ifs[i], LIFNAMSIZ);
+
+ return (iflistp);
+}
+
+/*
+ * Free the interface list pointed to by `iflistp'.
+ */
+static void
+ipmp_freeiflist(ipmp_iflist_t *iflistp)
+{
+ free(iflistp);
+}
+
+/*
+ * Create an interface; arguments match ipmp_ifinfo_t fields. Returns a
+ * pointer to the new interface on success, or NULL on failure.
*/
ipmp_ifinfo_t *
ipmp_ifinfo_create(const char *name, const char *group, ipmp_if_state_t state,
- ipmp_if_type_t type)
+ ipmp_if_type_t type, ipmp_if_linkstate_t linkstate,
+ ipmp_if_probestate_t probestate, ipmp_if_flags_t flags,
+ ipmp_targinfo_t *targinfo4p, ipmp_targinfo_t *targinfo6p)
{
ipmp_ifinfo_t *ifinfop;
@@ -408,8 +597,25 @@ ipmp_ifinfo_create(const char *name, const char *group, ipmp_if_state_t state,
(void) strlcpy(ifinfop->if_name, name, LIFNAMSIZ);
(void) strlcpy(ifinfop->if_group, group, LIFGRNAMSIZ);
- ifinfop->if_state = state;
- ifinfop->if_type = type;
+
+ ifinfop->if_state = state;
+ ifinfop->if_type = type;
+ ifinfop->if_linkstate = linkstate;
+ ifinfop->if_probestate = probestate;
+ ifinfop->if_flags = flags;
+ ifinfop->if_targinfo4 = *targinfo4p;
+ ifinfop->if_targinfo6 = *targinfo6p;
+
+ ifinfop->if_targinfo4.it_targlistp =
+ ipmp_addrlist_clone(targinfo4p->it_targlistp);
+ ifinfop->if_targinfo6.it_targlistp =
+ ipmp_addrlist_clone(targinfo6p->it_targlistp);
+
+ if (ifinfop->if_targinfo4.it_targlistp == NULL ||
+ ifinfop->if_targinfo6.it_targlistp == NULL) {
+ ipmp_freeifinfo(ifinfop);
+ return (NULL);
+ }
return (ifinfop);
}
@@ -422,40 +628,41 @@ ipmp_ifinfo_t *
ipmp_ifinfo_clone(ipmp_ifinfo_t *ifinfop)
{
return (ipmp_ifinfo_create(ifinfop->if_name, ifinfop->if_group,
- ifinfop->if_state, ifinfop->if_type));
+ ifinfop->if_state, ifinfop->if_type, ifinfop->if_linkstate,
+ ifinfop->if_probestate, ifinfop->if_flags, &ifinfop->if_targinfo4,
+ &ifinfop->if_targinfo6));
}
/*
- * Create a group named `name' with signature `sig', in state `state', and
- * with the `nif' interfaces named by `ifs' as members. Returns a pointer
+ * Create a group; arguments match ipmp_groupinfo_t fields. Returns a pointer
* to the new group on success, or NULL on failure.
*/
ipmp_groupinfo_t *
-ipmp_groupinfo_create(const char *name, uint64_t sig, ipmp_group_state_t state,
- unsigned int nif, char (*ifs)[LIFNAMSIZ])
+ipmp_groupinfo_create(const char *name, uint64_t sig, uint_t fdt,
+ ipmp_group_state_t state, uint_t nif, char (*ifs)[LIFNAMSIZ],
+ const char *grifname, const char *m4ifname, const char *m6ifname,
+ const char *bcifname, uint_t naddr, struct sockaddr_storage *addrs)
{
ipmp_groupinfo_t *grinfop;
- ipmp_iflist_t *iflistp;
- unsigned int i;
grinfop = malloc(sizeof (ipmp_groupinfo_t));
if (grinfop == NULL)
return (NULL);
- iflistp = malloc(IPMP_IFLIST_SIZE(nif));
- if (iflistp == NULL) {
- free(grinfop);
+ grinfop->gr_sig = sig;
+ grinfop->gr_fdt = fdt;
+ grinfop->gr_state = state;
+ grinfop->gr_iflistp = ipmp_iflist_create(nif, ifs);
+ grinfop->gr_adlistp = ipmp_addrlist_create(naddr, addrs);
+ if (grinfop->gr_iflistp == NULL || grinfop->gr_adlistp == NULL) {
+ ipmp_freegroupinfo(grinfop);
return (NULL);
}
-
- grinfop->gr_sig = sig;
- grinfop->gr_state = state;
- grinfop->gr_iflistp = iflistp;
(void) strlcpy(grinfop->gr_name, name, LIFGRNAMSIZ);
-
- iflistp->il_nif = nif;
- for (i = 0; i < nif; i++)
- (void) strlcpy(iflistp->il_ifs[i], ifs[i], LIFNAMSIZ);
+ (void) strlcpy(grinfop->gr_ifname, grifname, LIFNAMSIZ);
+ (void) strlcpy(grinfop->gr_m4ifname, m4ifname, LIFNAMSIZ);
+ (void) strlcpy(grinfop->gr_m6ifname, m6ifname, LIFNAMSIZ);
+ (void) strlcpy(grinfop->gr_bcifname, bcifname, LIFNAMSIZ);
return (grinfop);
}
@@ -467,9 +674,86 @@ ipmp_groupinfo_create(const char *name, uint64_t sig, ipmp_group_state_t state,
ipmp_groupinfo_t *
ipmp_groupinfo_clone(ipmp_groupinfo_t *grinfop)
{
+ ipmp_addrlist_t *adlistp = grinfop->gr_adlistp;
+
return (ipmp_groupinfo_create(grinfop->gr_name, grinfop->gr_sig,
- grinfop->gr_state, grinfop->gr_iflistp->il_nif,
- grinfop->gr_iflistp->il_ifs));
+ grinfop->gr_fdt, grinfop->gr_state, grinfop->gr_iflistp->il_nif,
+ grinfop->gr_iflistp->il_ifs, grinfop->gr_ifname,
+ grinfop->gr_m4ifname, grinfop->gr_m6ifname, grinfop->gr_bcifname,
+ adlistp->al_naddr, adlistp->al_addrs));
+}
+
+/*
+ * Create an address list; arguments match ipmp_addrlist_t fields. Returns
+ * a pointer to the new address list on success, or NULL on failure.
+ */
+static ipmp_addrlist_t *
+ipmp_addrlist_create(uint_t naddr, struct sockaddr_storage *addrs)
+{
+ unsigned int i;
+ ipmp_addrlist_t *adlistp;
+
+ adlistp = malloc(IPMP_ADDRLIST_SIZE(naddr));
+ if (adlistp == NULL)
+ return (NULL);
+
+ adlistp->al_naddr = naddr;
+ for (i = 0; i < naddr; i++)
+ adlistp->al_addrs[i] = addrs[i];
+
+ return (adlistp);
+}
+
+/*
+ * Clone the address list named by `adlistp'. Returns a pointer to the clone
+ * on success, or NULL on failure.
+ */
+static ipmp_addrlist_t *
+ipmp_addrlist_clone(ipmp_addrlist_t *adlistp)
+{
+ return (ipmp_addrlist_create(adlistp->al_naddr, adlistp->al_addrs));
+}
+
+/*
+ * Free the address list pointed to by `adlistp'.
+ */
+static void
+ipmp_freeaddrlist(ipmp_addrlist_t *adlistp)
+{
+ free(adlistp);
+}
+
+/*
+ * Create an address; arguments match ipmp_addrinfo_t fields. Returns a
+ * pointer to the new address on success, or NULL on failure.
+ */
+ipmp_addrinfo_t *
+ipmp_addrinfo_create(struct sockaddr_storage *addrp, ipmp_addr_state_t state,
+ const char *group, const char *binding)
+{
+ ipmp_addrinfo_t *adinfop;
+
+ adinfop = malloc(sizeof (ipmp_addrinfo_t));
+ if (adinfop == NULL)
+ return (NULL);
+
+ adinfop->ad_addr = *addrp;
+ adinfop->ad_state = state;
+ (void) strlcpy(adinfop->ad_group, group, LIFGRNAMSIZ);
+ (void) strlcpy(adinfop->ad_binding, binding, LIFNAMSIZ);
+
+ return (adinfop);
+}
+
+/*
+ * Clone the address information named by `adinfop'. Returns a pointer to
+ * the clone on success, or NULL on failure.
+ */
+ipmp_addrinfo_t *
+ipmp_addrinfo_clone(ipmp_addrinfo_t *adinfop)
+{
+ return (ipmp_addrinfo_create(&adinfop->ad_addr, adinfop->ad_state,
+ adinfop->ad_group, adinfop->ad_binding));
}
/*
@@ -523,8 +807,10 @@ ipmp_snap_create(void)
snap->sn_grlistp = NULL;
snap->sn_grinfolistp = NULL;
snap->sn_ifinfolistp = NULL;
+ snap->sn_adinfolistp = NULL;
snap->sn_ngroup = 0;
snap->sn_nif = 0;
+ snap->sn_naddr = 0;
return (snap);
}
@@ -536,6 +822,7 @@ void
ipmp_snap_free(ipmp_snap_t *snap)
{
ipmp_ifinfolist_t *iflp, *ifnext;
+ ipmp_addrinfolist_t *adlp, *adnext;
ipmp_groupinfolist_t *grlp, *grnext;
ipmp_freegrouplist(snap->sn_grlistp);
@@ -552,6 +839,12 @@ ipmp_snap_free(ipmp_snap_t *snap)
free(iflp);
}
+ for (adlp = snap->sn_adinfolistp; adlp != NULL; adlp = adnext) {
+ adnext = adlp->adl_next;
+ ipmp_freeaddrinfo(adlp->adl_adinfop);
+ free(adlp);
+ }
+
free(snap);
}
@@ -612,6 +905,34 @@ ipmp_snap_addifinfo(ipmp_snap_t *snap, ipmp_ifinfo_t *ifinfop)
}
/*
+ * Add the address information in `adinfop' to the snapshot named by `snap'.
+ * Returns an IPMP error code.
+ */
+int
+ipmp_snap_addaddrinfo(ipmp_snap_t *snap, ipmp_addrinfo_t *adinfop)
+{
+ ipmp_addrinfolist_t *adlp;
+
+ /*
+ * Any duplicate addresses should've already been weeded by in.mpathd.
+ */
+ if (ipmp_snap_getaddrinfo(snap, adinfop->ad_group,
+ &adinfop->ad_addr) != NULL)
+ return (IPMP_EPROTO);
+
+ adlp = malloc(sizeof (ipmp_addrinfolist_t));
+ if (adlp == NULL)
+ return (IPMP_ENOMEM);
+
+ adlp->adl_adinfop = adinfop;
+ adlp->adl_next = snap->sn_adinfolistp;
+ snap->sn_adinfolistp = adlp;
+ snap->sn_naddr++;
+
+ return (IPMP_SUCCESS);
+}
+
+/*
* Retrieve the information for the group `name' in snapshot `snap'.
* Returns a pointer to the group information on success, or NULL on failure.
*/
@@ -647,6 +968,26 @@ ipmp_snap_getifinfo(ipmp_snap_t *snap, const char *name)
}
/*
+ * Retrieve the information for the address `addrp' on group `grname' in
+ * snapshot `snap'. Returns a pointer to the address information on success,
+ * or NULL on failure.
+ */
+static ipmp_addrinfo_t *
+ipmp_snap_getaddrinfo(ipmp_snap_t *snap, const char *grname,
+ struct sockaddr_storage *addrp)
+{
+ ipmp_addrinfolist_t *adlp;
+
+ for (adlp = snap->sn_adinfolistp; adlp != NULL; adlp = adlp->adl_next) {
+ if (strcmp(grname, adlp->adl_adinfop->ad_group) == 0 &&
+ sockaddrcmp(addrp, &adlp->adl_adinfop->ad_addr))
+ break;
+ }
+
+ return (adlp != NULL ? adlp->adl_adinfop : NULL);
+}
+
+/*
* Using `statep', take a snapshot of the IPMP subsystem and if successful
* return it in a dynamically allocated snapshot pointed to by `*snapp'.
* Returns an IPMP error code.
@@ -656,7 +997,6 @@ ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp)
{
ipmp_snap_t *snap, *osnap;
ipmp_infotype_t type;
- ipmp_iflist_t *iflistp;
int retval;
size_t len;
void *infop;
@@ -666,7 +1006,7 @@ ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp)
if (snap == NULL)
return (IPMP_ENOMEM);
- retval = ipmp_sendquery(statep, IPMP_SNAP, NULL, &end);
+ retval = ipmp_sendquery(statep, IPMP_SNAP, NULL, NULL, &end);
if (retval != IPMP_SUCCESS) {
ipmp_snap_free(snap);
return (retval);
@@ -679,12 +1019,11 @@ ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp)
}
/*
- * Using the information in the passed `osnap' snapshot, build up our
- * own snapshot. If we receive more than one grouplist, or more than
- * the expected number of interfaces or groups, then bail out. Note
- * that there's only so much we can do to check that the information
- * sent by in.mpathd makes sense. We know there will always be at
- * least one TLV (IPMP_GROUPLIST).
+ * Using the information in the `osnap' snapshot, build up our own
+ * snapshot. We know there will always be at least one TLV (for
+ * IPMP_GROUPLIST). If we receive anything illogical (e.g., more than
+ * the expected number of interfaces), then bail out. However, to a
+ * large extent we have to trust the information sent by in.mpathd.
*/
do {
infop = NULL;
@@ -711,7 +1050,32 @@ ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp)
retval = IPMP_EPROTO;
break;
}
+
+ /*
+ * Read in V4 and V6 targlist TLVs that follow.
+ */
+ retval = ipmp_readifinfo_lists(statep, infop, &end);
+ if (retval != IPMP_SUCCESS)
+ break;
+
retval = ipmp_snap_addifinfo(snap, infop);
+ if (retval != IPMP_SUCCESS) {
+ ipmp_freeifinfo(infop);
+ infop = NULL;
+ }
+ break;
+
+ case IPMP_ADDRINFO:
+ if (snap->sn_naddr == osnap->sn_naddr) {
+ retval = IPMP_EPROTO;
+ break;
+ }
+
+ retval = ipmp_snap_addaddrinfo(snap, infop);
+ /*
+ * NOTE: since we didn't call ipmp_read*info_lists(),
+ * no need to use ipmp_freeaddrinfo() on failure.
+ */
break;
case IPMP_GROUPINFO:
@@ -721,18 +1085,17 @@ ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp)
}
/*
- * An IPMP_IFLIST TLV always follows the
- * IPMP_GROUPINFO TLV; read it in.
+ * Read in IPMP groupinfo list TLVs that follow.
*/
- retval = ipmp_readinfo(statep, IPMP_IFLIST,
- (void **)&iflistp, &end);
+ retval = ipmp_readgroupinfo_lists(statep, infop, &end);
if (retval != IPMP_SUCCESS)
break;
- ((ipmp_groupinfo_t *)infop)->gr_iflistp = iflistp;
retval = ipmp_snap_addgroupinfo(snap, infop);
- if (retval != IPMP_SUCCESS)
- free(iflistp);
+ if (retval != IPMP_SUCCESS) {
+ ipmp_freegroupinfo(infop);
+ infop = NULL;
+ }
break;
default:
@@ -747,7 +1110,8 @@ fail:
return (ipmp_querydone(statep, retval));
}
} while (snap->sn_grlistp == NULL || snap->sn_nif < osnap->sn_nif ||
- snap->sn_ngroup < osnap->sn_ngroup);
+ snap->sn_ngroup < osnap->sn_ngroup ||
+ snap->sn_naddr < osnap->sn_naddr);
free(osnap);
*snapp = snap;
diff --git a/usr/src/lib/libipmp/common/ipmp_query.h b/usr/src/lib/libipmp/common/ipmp_query.h
index d92554887a..160f561dd2 100644
--- a/usr/src/lib/libipmp/common/ipmp_query.h
+++ b/usr/src/lib/libipmp/common/ipmp_query.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -18,17 +17,14 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
- */
-/*
- * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _IPMP_QUERY_H
#define _IPMP_QUERY_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/socket.h> /* needed by <net/if.h> */
#include <net/if.h> /* for LIF*NAMSIZ */
@@ -38,7 +34,7 @@
* IPMP query interfaces.
*
* These interfaces may only be used within ON or after signing a contract
- * with ON. For documentation, refer to PSARC/2002/615.
+ * with ON. For documentation, refer to PSARC/2002/615 and PSARC/2007/272.
*/
#ifdef __cplusplus
@@ -46,6 +42,43 @@ extern "C" {
#endif
/*
+ * Assorted enumerations used in the data types described below.
+ */
+typedef enum ipmp_if_probestate {
+ IPMP_PROBE_OK, /* probes detect no problems */
+ IPMP_PROBE_FAILED, /* probes detect failure */
+ IPMP_PROBE_UNKNOWN, /* probe detection unavailable */
+ IPMP_PROBE_DISABLED /* probe detection disabled */
+} ipmp_if_probestate_t;
+
+typedef enum ipmp_if_linkstate {
+ IPMP_LINK_UP, /* link detects up */
+ IPMP_LINK_DOWN, /* link detects down */
+ IPMP_LINK_UNKNOWN /* link detection unavailable */
+} ipmp_if_linkstate_t;
+
+typedef enum ipmp_if_flags {
+ IPMP_IFFLAG_INACTIVE = 0x1,
+ IPMP_IFFLAG_HWADDRDUP = 0x2,
+ IPMP_IFFLAG_ACTIVE = 0x4,
+ IPMP_IFFLAG_DOWN = 0x8
+} ipmp_if_flags_t;
+
+typedef enum ipmp_addr_state {
+ IPMP_ADDR_UP, /* address is up */
+ IPMP_ADDR_DOWN /* address is down */
+} ipmp_addr_state_t;
+
+typedef enum ipmp_if_targmode {
+ IPMP_TARG_DISABLED, /* use of targets is disabled */
+ IPMP_TARG_ROUTES, /* route-learned targets */
+ IPMP_TARG_MULTICAST /* multicast-learned targets */
+} ipmp_if_targmode_t;
+
+#define IPMP_LIST_SIZE(listtype, elsize, nel) \
+ ((sizeof (ipmp_ ## listtype ## _t) - (elsize)) + ((nel) * (elsize)))
+
+/*
* Data type describing a list of IPMP groups.
*/
typedef struct ipmp_grouplist {
@@ -54,8 +87,8 @@ typedef struct ipmp_grouplist {
char gl_groups[1][LIFGRNAMSIZ];
} ipmp_grouplist_t;
-#define IPMP_GROUPLIST_MINSIZE (sizeof (ipmp_grouplist_t) - LIFGRNAMSIZ)
-#define IPMP_GROUPLIST_SIZE(ngr) (IPMP_GROUPLIST_MINSIZE + (ngr) * LIFGRNAMSIZ)
+#define IPMP_GROUPLIST_SIZE(ngr) \
+ IPMP_LIST_SIZE(grouplist, LIFGRNAMSIZ, ngr)
/*
* Data type describing a list of interfaces.
@@ -65,8 +98,19 @@ typedef struct ipmp_iflist {
char il_ifs[1][LIFNAMSIZ];
} ipmp_iflist_t;
-#define IPMP_IFLIST_MINSIZE (sizeof (ipmp_iflist_t) - LIFNAMSIZ)
-#define IPMP_IFLIST_SIZE(nif) (IPMP_IFLIST_MINSIZE + (nif) * LIFNAMSIZ)
+#define IPMP_IFLIST_SIZE(nif) \
+ IPMP_LIST_SIZE(iflist, LIFNAMSIZ, nif)
+
+/*
+ * Data type describing a list of addresses.
+ */
+typedef struct ipmp_addrlist {
+ unsigned int al_naddr;
+ struct sockaddr_storage al_addrs[1];
+} ipmp_addrlist_t;
+
+#define IPMP_ADDRLIST_SIZE(naddr) \
+ IPMP_LIST_SIZE(addrlist, sizeof (struct sockaddr_storage), naddr)
/*
* Data type describing the state of an IPMP group.
@@ -76,18 +120,49 @@ typedef struct ipmp_groupinfo {
uint64_t gr_sig;
ipmp_group_state_t gr_state;
ipmp_iflist_t *gr_iflistp;
+ ipmp_addrlist_t *gr_adlistp;
+ char gr_ifname[LIFNAMSIZ];
+ char gr_m4ifname[LIFNAMSIZ];
+ char gr_m6ifname[LIFNAMSIZ];
+ char gr_bcifname[LIFNAMSIZ];
+ unsigned int gr_fdt;
} ipmp_groupinfo_t;
/*
+ * Data type describing IPMP target information for a particular interface.
+ */
+typedef struct ipmp_targinfo {
+ char it_name[LIFNAMSIZ];
+ struct sockaddr_storage it_testaddr;
+ ipmp_if_targmode_t it_targmode;
+ ipmp_addrlist_t *it_targlistp;
+} ipmp_targinfo_t;
+
+/*
* Data type describing the IPMP-related state of an interface.
*/
typedef struct ipmp_ifinfo {
- char if_name[LIFNAMSIZ];
- char if_group[LIFGRNAMSIZ];
- ipmp_if_state_t if_state;
- ipmp_if_type_t if_type;
+ char if_name[LIFNAMSIZ];
+ char if_group[LIFGRNAMSIZ];
+ ipmp_if_state_t if_state;
+ ipmp_if_type_t if_type;
+ ipmp_if_linkstate_t if_linkstate;
+ ipmp_if_probestate_t if_probestate;
+ ipmp_if_flags_t if_flags;
+ ipmp_targinfo_t if_targinfo4;
+ ipmp_targinfo_t if_targinfo6;
} ipmp_ifinfo_t;
+/*
+ * Data type describing an IPMP data address.
+ */
+typedef struct ipmp_addrinfo {
+ struct sockaddr_storage ad_addr;
+ ipmp_addr_state_t ad_state;
+ char ad_group[LIFGRNAMSIZ];
+ char ad_binding[LIFNAMSIZ];
+} ipmp_addrinfo_t;
+
typedef enum {
IPMP_QCONTEXT_LIVE,
IPMP_QCONTEXT_SNAP
@@ -100,6 +175,9 @@ extern int ipmp_getgroupinfo(ipmp_handle_t, const char *, ipmp_groupinfo_t **);
extern void ipmp_freegroupinfo(ipmp_groupinfo_t *);
extern int ipmp_getifinfo(ipmp_handle_t, const char *, ipmp_ifinfo_t **);
extern void ipmp_freeifinfo(ipmp_ifinfo_t *);
+extern int ipmp_getaddrinfo(ipmp_handle_t, const char *,
+ struct sockaddr_storage *, ipmp_addrinfo_t **);
+extern void ipmp_freeaddrinfo(ipmp_addrinfo_t *);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libipmp/common/ipmp_query_impl.h b/usr/src/lib/libipmp/common/ipmp_query_impl.h
index 03ecb5cd84..6ac5c3ca27 100644
--- a/usr/src/lib/libipmp/common/ipmp_query_impl.h
+++ b/usr/src/lib/libipmp/common/ipmp_query_impl.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -18,17 +17,14 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
- */
-/*
- * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _IPMP_QUERY_IMPL_H
#define _IPMP_QUERY_IMPL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <ipmp_query.h>
/*
@@ -58,14 +54,24 @@ typedef struct ipmp_ifinfolist {
} ipmp_ifinfolist_t;
/*
+ * List of ipmp_addrinfo_t structures.
+ */
+typedef struct ipmp_addrinfolist {
+ struct ipmp_addrinfolist *adl_next;
+ ipmp_addrinfo_t *adl_adinfop;
+} ipmp_addrinfolist_t;
+
+/*
* Snapshot of IPMP state.
*/
typedef struct ipmp_snap {
ipmp_grouplist_t *sn_grlistp;
ipmp_groupinfolist_t *sn_grinfolistp;
ipmp_ifinfolist_t *sn_ifinfolistp;
+ ipmp_addrinfolist_t *sn_adinfolistp;
unsigned int sn_ngroup;
unsigned int sn_nif;
+ unsigned int sn_naddr;
} ipmp_snap_t;
/*
@@ -74,17 +80,28 @@ typedef struct ipmp_snap {
extern ipmp_snap_t *ipmp_snap_create(void);
extern void ipmp_snap_free(ipmp_snap_t *);
extern int ipmp_snap_addifinfo(ipmp_snap_t *, ipmp_ifinfo_t *);
+extern int ipmp_snap_addaddrinfo(ipmp_snap_t *, ipmp_addrinfo_t *);
extern int ipmp_snap_addgroupinfo(ipmp_snap_t *, ipmp_groupinfo_t *);
/*
- * IPMP structure creation routines.
+ * IPMP structure creation/destruction routines.
*/
extern ipmp_ifinfo_t *ipmp_ifinfo_create(const char *, const char *,
- ipmp_if_state_t, ipmp_if_type_t);
-extern ipmp_groupinfo_t *ipmp_groupinfo_create(const char *, uint64_t,
- ipmp_group_state_t, unsigned int, char (*)[LIFNAMSIZ]);
+ ipmp_if_state_t, ipmp_if_type_t, ipmp_if_linkstate_t, ipmp_if_probestate_t,
+ ipmp_if_flags_t, ipmp_targinfo_t *, ipmp_targinfo_t *);
+extern ipmp_groupinfo_t *ipmp_groupinfo_create(const char *, uint64_t, uint_t,
+ ipmp_group_state_t, uint_t, char (*)[LIFNAMSIZ], const char *,
+ const char *, const char *, const char *, uint_t,
+ struct sockaddr_storage *);
extern ipmp_grouplist_t *ipmp_grouplist_create(uint64_t, unsigned int,
char (*)[LIFGRNAMSIZ]);
+extern ipmp_addrinfo_t *ipmp_addrinfo_create(struct sockaddr_storage *,
+ ipmp_addr_state_t, const char *, const char *);
+extern ipmp_targinfo_t *ipmp_targinfo_create(const char *,
+ struct sockaddr_storage *, ipmp_if_targmode_t, uint_t,
+ struct sockaddr_storage *);
+extern void ipmp_freetarginfo(ipmp_targinfo_t *);
+
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libipmp/common/llib-lipmp b/usr/src/lib/libipmp/common/llib-lipmp
index a16011745a..a22eec5d66 100644
--- a/usr/src/lib/libipmp/common/llib-lipmp
+++ b/usr/src/lib/libipmp/common/llib-lipmp
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,15 +19,14 @@
* CDDL HEADER END
*/
/*
- * Copyright 2002 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"
-
/* LINTLIBRARY */
/* PROTOLIB1 */
#include <ipmp.h>
+#include <ipmp_admin.h>
#include <ipmp_mpathd.h>
#include <ipmp_query_impl.h>
diff --git a/usr/src/lib/libipmp/common/mapfile-vers b/usr/src/lib/libipmp/common/mapfile-vers
index a4052bfcd3..8c93248338 100644
--- a/usr/src/lib/libipmp/common/mapfile-vers
+++ b/usr/src/lib/libipmp/common/mapfile-vers
@@ -19,32 +19,39 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
SUNWprivate_1.1 {
global:
+ ipmp_addrinfo_create;
ipmp_close;
ipmp_errmsg;
+ ipmp_freeaddrinfo;
ipmp_freegroupinfo;
ipmp_freegrouplist;
ipmp_freeifinfo;
+ ipmp_freetarginfo;
+ ipmp_getaddrinfo;
ipmp_getgroupinfo;
ipmp_getgrouplist;
ipmp_getifinfo;
ipmp_groupinfo_create;
ipmp_grouplist_create;
ipmp_ifinfo_create;
+ ipmp_offline;
ipmp_open;
+ ipmp_ping_daemon;
ipmp_read;
ipmp_setqcontext;
+ ipmp_snap_addaddrinfo;
ipmp_snap_addgroupinfo;
ipmp_snap_addifinfo;
ipmp_snap_create;
ipmp_snap_free;
+ ipmp_targinfo_create;
+ ipmp_undo_offline;
ipmp_write;
ipmp_writetlv;
local: