diff options
Diffstat (limited to 'usr/src/lib/libipmp/common')
-rw-r--r-- | usr/src/lib/libipmp/common/ipmp.c | 20 | ||||
-rw-r--r-- | usr/src/lib/libipmp/common/ipmp.h | 12 | ||||
-rw-r--r-- | usr/src/lib/libipmp/common/ipmp_admin.c | 104 | ||||
-rw-r--r-- | usr/src/lib/libipmp/common/ipmp_admin.h | 50 | ||||
-rw-r--r-- | usr/src/lib/libipmp/common/ipmp_mpathd.c | 26 | ||||
-rw-r--r-- | usr/src/lib/libipmp/common/ipmp_mpathd.h | 81 | ||||
-rw-r--r-- | usr/src/lib/libipmp/common/ipmp_query.c | 498 | ||||
-rw-r--r-- | usr/src/lib/libipmp/common/ipmp_query.h | 112 | ||||
-rw-r--r-- | usr/src/lib/libipmp/common/ipmp_query_impl.h | 41 | ||||
-rw-r--r-- | usr/src/lib/libipmp/common/llib-lipmp | 10 | ||||
-rw-r--r-- | usr/src/lib/libipmp/common/mapfile-vers | 13 |
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: |