diff options
| author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
|---|---|---|
| committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
| commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
| tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libipmp | |
| download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz | |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libipmp')
21 files changed, 2252 insertions, 0 deletions
diff --git a/usr/src/lib/libipmp/Makefile b/usr/src/lib/libipmp/Makefile new file mode 100644 index 0000000000..596c39e922 --- /dev/null +++ b/usr/src/lib/libipmp/Makefile @@ -0,0 +1,66 @@ +# +# 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. +# +# 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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include $(SRC)/lib/Makefile.lib + +HDRS = ipmp.h ipmp_mpathd.h ipmp_query.h ipmp_query_impl.h +HDRDIR = common +SUBDIRS = $(MACH) + +POFILE = libipmp.po +MSGFILES = common/ipmp.c +XGETFLAGS = -a + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +all clean clobber install: spec .WAIT $(SUBDIRS) + +lint: $(SUBDIRS) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(POFILE): $(MSGFILES) + $(BUILDPO.msgfiles) + +_msg: $(MSGDOMAINPOFILE) + +$(SUBDIRS) spec: FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include $(SRC)/Makefile.msg.targ +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/libipmp/Makefile.com b/usr/src/lib/libipmp/Makefile.com new file mode 100644 index 0000000000..5bce4ce86e --- /dev/null +++ b/usr/src/lib/libipmp/Makefile.com @@ -0,0 +1,52 @@ +# +# 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. +# +# 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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +LIBRARY = libipmp.a +VERS = .1 +OBJECTS = ipmp_query.o ipmp_mpathd.o ipmp.o + +include ../../Makefile.lib + +LIBS = $(DYNLIB) $(LINTLIB) +$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) +LDLIBS += -lsocket -lc + +SRCDIR = ../common +MAPDIR = ../spec/$(TRANSMACH) +SPECMAPFILE = $(MAPDIR)/mapfile + +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -I$(SRCDIR) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include ../../Makefile.targ diff --git a/usr/src/lib/libipmp/common/ipmp.c b/usr/src/lib/libipmp/common/ipmp.c new file mode 100644 index 0000000000..b9a7984889 --- /dev/null +++ b/usr/src/lib/libipmp/common/ipmp.c @@ -0,0 +1,114 @@ +/* + * 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. + * + * 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 2003 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). + */ + +#include <assert.h> +#include <stdlib.h> +#include <locale.h> +#include <unistd.h> + +#include "ipmp_impl.h" + +/* + * Allocate a handle and store it in `*handlep' upon success. Returns an IPMP + * error code. + */ +int +ipmp_open(ipmp_handle_t *handlep) +{ + ipmp_state_t *statep; + + statep = malloc(sizeof (ipmp_state_t)); + if (statep == NULL) + return (IPMP_ENOMEM); + + statep->st_fd = -1; + statep->st_snap = NULL; + statep->st_magic = IPMP_MAGIC; + + *handlep = statep; + return (IPMP_SUCCESS); +} + +/* + * Destroy the IPMP handle named by `handle'. + */ +void +ipmp_close(ipmp_handle_t handle) +{ + ipmp_state_t *statep = handle; + + /* + * If this assertion triggers, someone called ipmp_close() twice in + * a row or stomped on us. + */ + assert(statep->st_magic == IPMP_MAGIC); + + /* + * If this assertion triggers, something's gone wrong internally. + */ + assert(statep->st_fd == -1); + + if (statep->st_snap != NULL) + ipmp_snap_free(statep->st_snap); + + statep->st_magic = 0; + free(statep); +} + +/* + * Error messages; must be in the same order as the codes in <ipmp.h> + */ +static char *errmsgs[IPMP_NERR] = { + "operation succeeded", /* 0 IPMP_SUCCESS */ + "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 */ + "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 */ +}; + +/* + * Return a string describing the IPMP error code named by `error'. + */ +const char * +ipmp_errmsg(int error) +{ + if (error >= IPMP_NERR || error < 0) + return (dgettext(TEXT_DOMAIN, "<unknown error>")); + + return (dgettext(TEXT_DOMAIN, errmsgs[error])); +} diff --git a/usr/src/lib/libipmp/common/ipmp.h b/usr/src/lib/libipmp/common/ipmp.h new file mode 100644 index 0000000000..0112615a84 --- /dev/null +++ b/usr/src/lib/libipmp/common/ipmp.h @@ -0,0 +1,73 @@ +/* + * 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. + * + * 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 2002 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. + * + * These interfaces may only be used within ON or after signing a contract + * with ON. For documentation, refer to PSARC/2002/615. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/sysevent/ipmp.h> + +/* + * IPMP library error codes. + */ +enum { + IPMP_SUCCESS, /* operation succeeded */ + 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_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_NERR /* number of error codes */ +}; + +typedef struct ipmp_state *ipmp_handle_t; + +extern int ipmp_open(ipmp_handle_t *); +extern void ipmp_close(ipmp_handle_t); +extern const char *ipmp_errmsg(int); + +#ifdef __cplusplus +} +#endif + +#endif /* _IPMP_H */ diff --git a/usr/src/lib/libipmp/common/ipmp_impl.h b/usr/src/lib/libipmp/common/ipmp_impl.h new file mode 100644 index 0000000000..3e7e90b43f --- /dev/null +++ b/usr/src/lib/libipmp/common/ipmp_impl.h @@ -0,0 +1,58 @@ +/* + * 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. + * + * 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 2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _IPMP_IMPL_H +#define _IPMP_IMPL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <ipmp.h> +#include <ipmp_query_impl.h> + +/* + * Implementation-private definitions for the IPMP library. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Private IPMP state structure. + */ +typedef struct ipmp_state { + uint32_t st_magic; /* magic tag */ + int st_fd; /* socket to in.mpathd */ + ipmp_snap_t *st_snap; /* current snapshot, if any */ +} ipmp_state_t; + +#define IPMP_MAGIC 0x49504D50 /* "IPMP" */ + +#ifdef __cplusplus +} +#endif + +#endif /* _IPMP_IMPL_H */ diff --git a/usr/src/lib/libipmp/common/ipmp_mpathd.c b/usr/src/lib/libipmp/common/ipmp_mpathd.c new file mode 100644 index 0000000000..ee1d35de33 --- /dev/null +++ b/usr/src/lib/libipmp/common/ipmp_mpathd.c @@ -0,0 +1,267 @@ +/* + * 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. + * + * 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 2002 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). + * + * These routines are not intended for use outside of libipmp. + */ + +#include <alloca.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <poll.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <sys/types.h> + +#include "ipmp.h" +#include "ipmp_mpathd.h" + +/* + * Connect to the multipathing daemon. Returns an IPMP error code; upon + * success, `fdp' points to the newly opened socket. + */ +int +ipmp_connect(int *fdp) +{ + int fd; + int error; + int on = 1; + int flags; + struct sockaddr_in sin; + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + 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 (setsockopt(fd, IPPROTO_TCP, TCP_ANONPRIVBIND, &on, + sizeof (on)) == -1) + goto fail; + + /* + * Bind to a privileged port chosen by the kernel. + */ + (void) memset(&sin, 0, sizeof (struct sockaddr_in)); + sin.sin_port = htons(0); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(fd, (struct sockaddr *)&sin, sizeof (sin)) == -1) + goto fail; + + /* + * Attempt to connect to in.mpathd. + */ + sin.sin_port = htons(MPATHD_PORT); + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (connect(fd, (struct sockaddr *)&sin, sizeof (sin)) == -1) { + if (errno == ECONNREFUSED) { + (void) close(fd); + return (IPMP_ENOMPATHD); + } + goto fail; + } + + /* + * Kick the socket into nonblocking mode. + */ + flags = fcntl(fd, F_GETFL, 0); + if (flags != -1) + (void) fcntl(fd, F_SETFL, flags | O_NONBLOCK); + + *fdp = fd; + return (IPMP_SUCCESS); +fail: + error = errno; + (void) close(fd); + errno = error; + return (IPMP_FAILURE); +} + +/* + * Read the TLV triplet from descriptor `fd' and store its type, length and + * value in `*typep', `*lenp', and `*valuep' respectively, before the current + * time becomes `endtp'. The buffer pointed to by `*valuep' will be + * dynamically allocated. Returns an IPMP error code. + */ +int +ipmp_readtlv(int fd, ipmp_infotype_t *typep, size_t *lenp, void **valuep, + const struct timeval *endtp) +{ + int retval; + void *value; + + retval = ipmp_read(fd, typep, sizeof (*typep), endtp); + if (retval != IPMP_SUCCESS) + return (retval); + + retval = ipmp_read(fd, lenp, sizeof (*lenp), endtp); + if (retval != IPMP_SUCCESS) + return (retval); + + value = malloc(*lenp); + if (value == NULL) { + /* + * Even though we cannot allocate space for the value, we + * still slurp it off so the input stream doesn't get left + * in a weird place. + */ + value = alloca(*lenp); + (void) ipmp_read(fd, value, *lenp, endtp); + return (IPMP_ENOMEM); + } + + retval = ipmp_read(fd, value, *lenp, endtp); + if (retval != IPMP_SUCCESS) { + free(value); + return (retval); + } + + *valuep = value; + return (IPMP_SUCCESS); +} + +/* + * Write `buflen' bytes from `buffer' to open file `fd'. Returns IPMP_SUCCESS + * if all requested bytes were written, or an error code if not. + */ +int +ipmp_write(int fd, const void *buffer, size_t buflen) +{ + size_t nwritten; + ssize_t nbytes; + const char *buf = buffer; + + for (nwritten = 0; nwritten < buflen; nwritten += nbytes) { + nbytes = write(fd, &buf[nwritten], buflen - nwritten); + if (nbytes == -1) + return (IPMP_FAILURE); + if (nbytes == 0) { + errno = EIO; + return (IPMP_FAILURE); + } + } + + assert(nwritten == buflen); + return (IPMP_SUCCESS); +} + +/* + * Write the TLV triplet named by `type', `len' and `value' to file descriptor + * `fd'. Returns an IPMP error code. + */ +int +ipmp_writetlv(int fd, ipmp_infotype_t type, size_t len, void *value) +{ + int retval; + + retval = ipmp_write(fd, &type, sizeof (type)); + if (retval != IPMP_SUCCESS) + return (retval); + + retval = ipmp_write(fd, &len, sizeof (len)); + if (retval != IPMP_SUCCESS) + return (retval); + + return (ipmp_write(fd, value, len)); +} + +/* + * Attempt to read `buflen' worth of bytes from `fd' into the buffer pointed + * to by `buf' before the current time becomes `endtp'; a `endtp' of NULL + * means forever. Returns an IPMP error code. + */ +int +ipmp_read(int fd, void *buffer, size_t buflen, const struct timeval *endtp) +{ + int retval; + int timeleft = -1; + struct timeval curtime; + ssize_t nbytes = 0; /* total bytes processed */ + ssize_t prbytes; /* per-round bytes processed */ + struct pollfd pfd; + + while (nbytes < buflen) { + /* + * If a timeout was specified, then compute the amount of time + * left before timing out. + */ + if (endtp != NULL) { + if (gettimeofday(&curtime, NULL) == -1) + break; + + timeleft = (endtp->tv_sec - curtime.tv_sec) * MILLISEC; + timeleft += (endtp->tv_usec - curtime.tv_usec) / 1000; + + /* + * If we should've already timed out, then just + * have poll() return immediately. + */ + if (timeleft < 0) + timeleft = 0; + } + + pfd.fd = fd; + pfd.events = POLLIN; + + /* + * Wait for data to come in or for the timeout to fire. + */ + retval = poll(&pfd, 1, timeleft); + if (retval <= 0) { + if (retval == 0) + errno = ETIME; + break; + } + + /* + * Descriptor is ready; have at it. + */ + prbytes = read(fd, (caddr_t)buffer + nbytes, buflen - nbytes); + if (prbytes <= 0) { + if (prbytes == -1 && errno == EINTR) + continue; + break; + } + nbytes += prbytes; + } + + return (nbytes == buflen ? IPMP_SUCCESS : IPMP_FAILURE); +} diff --git a/usr/src/lib/libipmp/common/ipmp_mpathd.h b/usr/src/lib/libipmp/common/ipmp_mpathd.h new file mode 100644 index 0000000000..61ae71b78f --- /dev/null +++ b/usr/src/lib/libipmp/common/ipmp_mpathd.h @@ -0,0 +1,174 @@ +/* + * 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. + * + * 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 1999-2002 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! + */ + +#include <sys/types.h> +#include <sys/socket.h> /* needed for <net/if.h> */ +#include <net/if.h> /* needed for LIFNAMSIZ */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MPATHD_PORT 5999 +#define MPATHD_PATH "/usr/lib/inet/in.mpathd" + +/* + * Supported commands. + */ +enum { + MI_PING = 0, /* sanity test */ + 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_NCMD /* total number of commands */ +}; + +/* + * Types of information which can be requested and received (except for + * IPMP_IFLIST, which can only be received). + */ +typedef enum { + IPMP_GROUPLIST = 1, + IPMP_GROUPINFO = 2, + IPMP_IFINFO = 3, + IPMP_IFLIST = 4, + IPMP_SNAP = 5 +} ipmp_infotype_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. + */ +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; + +/* + * Interface undo-offline request; `miu_uname' is the interface to + * undo-offline. + */ +typedef struct mi_undo_offline { + uint32_t miu_command; + char miu_ifname[LIFNAMSIZ]; +} 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. + */ +typedef struct mi_query { + uint32_t miq_command; + ipmp_infotype_t miq_inforeq; + union { + char miqu_ifname[LIFNAMSIZ]; + char miqu_grname[LIFGRNAMSIZ]; + } miq_infodata; +} mi_query_t; +#define miq_ifname miq_infodata.miqu_ifname +#define miq_grname miq_infodata.miqu_grname + +/* + * Union of all commands. Can be used to estimate the maximum buffer size + * requirement for receiving any command. + */ +union mi_commands { + uint32_t mi_command; + mi_offline_t mi_ocmd; + mi_undo_offline_t mi_ucmd; + mi_setoindex_t mi_scmd; + mi_query_t mi_qcmd; +}; + +/* + * Result structure returned by in.mpathd. + */ +typedef struct mi_result { + uint32_t me_sys_error; /* System error (errno.h) */ + 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 */ +}; + +extern int ipmp_connect(int *); +extern int ipmp_read(int, void *, size_t, const struct timeval *); +extern int ipmp_write(int, const void *, size_t); +extern int ipmp_writetlv(int, ipmp_infotype_t, size_t, void *); +extern int ipmp_readtlv(int, ipmp_infotype_t *, size_t *, void **, + const struct timeval *); + +#ifdef __cplusplus +} +#endif + +#endif /* _IPMP_MPATHD_H */ diff --git a/usr/src/lib/libipmp/common/ipmp_query.c b/usr/src/lib/libipmp/common/ipmp_query.c new file mode 100644 index 0000000000..8a7dc7ee69 --- /dev/null +++ b/usr/src/lib/libipmp/common/ipmp_query.c @@ -0,0 +1,755 @@ +/* + * 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. + * + * 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 2002 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). + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> + +#include "ipmp_impl.h" +#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_grouplist_t *ipmp_grouplist_clone(ipmp_grouplist_t *); +static ipmp_groupinfo_t *ipmp_groupinfo_clone(ipmp_groupinfo_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 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); + +/* + * Using `statep', send a query request for `type' to in.mpathd, and if + * necessary wait until at least `endtp' for a response. Returns an IPMP + * error code. If successful, the caller may then read additional query + * information through ipmp_readinfo(), and must eventually call + * ipmp_querydone() to complete the query operation. Only one query may be + * outstanding on a given `statep' at a time. + */ +static int +ipmp_sendquery(ipmp_state_t *statep, ipmp_infotype_t type, const char *name, + struct timeval *endtp) +{ + mi_query_t query; + mi_result_t result; + int retval; + + query.miq_command = MI_QUERY; + query.miq_inforeq = type; + + switch (type) { + case IPMP_GROUPINFO: + (void) strlcpy(query.miq_grname, name, LIFGRNAMSIZ); + break; + + case IPMP_IFINFO: + (void) strlcpy(query.miq_ifname, name, LIFNAMSIZ); + break; + + case IPMP_GROUPLIST: + case IPMP_SNAP: + break; + + default: + assert(0); + } + + if (gettimeofday(endtp, NULL) == -1) + return (IPMP_FAILURE); + + endtp->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, &query, sizeof (query)); + if (retval != IPMP_SUCCESS) + return (ipmp_querydone(statep, retval)); + + retval = ipmp_read(statep->st_fd, &result, sizeof (result), endtp); + if (retval != IPMP_SUCCESS) + return (ipmp_querydone(statep, retval)); + + if (result.me_mpathd_error != IPMP_SUCCESS) + return (ipmp_querydone(statep, result.me_mpathd_error)); + + return (IPMP_SUCCESS); +} + +/* + * Using `statep', read a query response of type `infotype' into a dynamically + * allocated buffer pointed to by `*infop', before the current time becomes + * `endtp'. Returns an IPMP error code. + */ +static int +ipmp_readinfo(ipmp_state_t *statep, ipmp_infotype_t infotype, void **infop, + const struct timeval *endtp) +{ + int retval; + size_t len; + ipmp_infotype_t type; + + retval = ipmp_readtlv(statep->st_fd, &type, &len, infop, endtp); + if (retval != IPMP_SUCCESS) + return (retval); + + if (type != infotype || !ipmp_checktlv(type, len, *infop)) { + free(*infop); + return (IPMP_EPROTO); + } + + 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'. + */ +static int +ipmp_querydone(ipmp_state_t *statep, int retval) +{ + int error = errno; + + (void) close(statep->st_fd); + statep->st_fd = -1; + errno = error; + return (retval); +} + +/* + * Using `handle', get the group list and store the results in a dynamically + * allocated buffer pointed to by `*grlistpp'. Returns an IPMP error code. + */ +int +ipmp_getgrouplist(ipmp_handle_t handle, ipmp_grouplist_t **grlistpp) +{ + ipmp_state_t *statep = handle; + struct timeval end; + int retval; + + if (statep->st_snap != NULL) { + *grlistpp = ipmp_grouplist_clone(statep->st_snap->sn_grlistp); + return (*grlistpp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); + } + + retval = ipmp_sendquery(statep, IPMP_GROUPLIST, NULL, &end); + if (retval != IPMP_SUCCESS) + return (retval); + + retval = ipmp_readinfo(statep, IPMP_GROUPLIST, (void **)grlistpp, &end); + return (ipmp_querydone(statep, retval)); +} + +/* + * Free the group list pointed to by `grlistp'. + */ +void +ipmp_freegrouplist(ipmp_grouplist_t *grlistp) +{ + free(grlistp); +} + +/* + * Using `handle', get the group information associated with group `name' and + * store the results in a dynamically allocated buffer pointed to by + * `*grinfopp'. Returns an IPMP error code. + */ +int +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; + + if (statep->st_snap != NULL) { + grinfop = ipmp_snap_getgroupinfo(statep->st_snap, name); + if (grinfop == NULL) + return (IPMP_EUNKGROUP); + + *grinfopp = ipmp_groupinfo_clone(grinfop); + return (*grinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); + } + + retval = ipmp_sendquery(statep, IPMP_GROUPINFO, name, &end); + if (retval != IPMP_SUCCESS) + return (retval); + + retval = ipmp_readinfo(statep, IPMP_GROUPINFO, (void **)grinfopp, &end); + if (retval != IPMP_SUCCESS) + return (ipmp_querydone(statep, retval)); + + retval = ipmp_readinfo(statep, IPMP_IFLIST, (void **)&iflistp, &end); + if (retval != IPMP_SUCCESS) + free(*grinfopp); + else + (*grinfopp)->gr_iflistp = iflistp; + + return (ipmp_querydone(statep, retval)); +} + +/* + * Free the group information pointed to by `grinfop'. + */ +void +ipmp_freegroupinfo(ipmp_groupinfo_t *grinfop) +{ + free(grinfop->gr_iflistp); + free(grinfop); +} + +/* + * Using `handle', get the interface information associated with interface + * `name' and store the results in a dynamically allocated buffer pointed to + * by `*ifinfopp'. Returns an IPMP error code. + */ +int +ipmp_getifinfo(ipmp_handle_t handle, const char *name, ipmp_ifinfo_t **ifinfopp) +{ + ipmp_state_t *statep = handle; + ipmp_ifinfo_t *ifinfop; + int retval; + struct timeval end; + + if (statep->st_snap != NULL) { + ifinfop = ipmp_snap_getifinfo(statep->st_snap, name); + if (ifinfop == NULL) + return (IPMP_EUNKIF); + + *ifinfopp = ipmp_ifinfo_clone(ifinfop); + return (*ifinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); + } + + retval = ipmp_sendquery(statep, IPMP_IFINFO, name, &end); + if (retval != IPMP_SUCCESS) + return (retval); + + retval = ipmp_readinfo(statep, IPMP_IFINFO, (void **)ifinfopp, &end); + return (ipmp_querydone(statep, retval)); +} + +/* + * Free the interface information pointed to by `ifinfop'. + */ +void +ipmp_freeifinfo(ipmp_ifinfo_t *ifinfop) +{ + free(ifinfop); +} + +/* + * Check if `buf' has a NUL byte in its first `bufsize' bytes. + */ +static boolean_t +hasnulbyte(const char *buf, size_t bufsize) +{ + while (bufsize-- > 0) { + if (buf[bufsize] == '\0') + return (B_TRUE); + } + return (B_FALSE); +} + +/* + * Check that the TLV triplet named by `type', `len' and `value' is correctly + * formed. + */ +static boolean_t +ipmp_checktlv(ipmp_infotype_t type, size_t len, void *value) +{ + ipmp_iflist_t *iflistp; + ipmp_ifinfo_t *ifinfop; + ipmp_grouplist_t *grlistp; + ipmp_groupinfo_t *grinfop; + unsigned int i; + + switch (type) { + case IPMP_IFLIST: + iflistp = (ipmp_iflist_t *)value; + if (len < IPMP_IFLIST_MINSIZE || + len < IPMP_IFLIST_SIZE(iflistp->il_nif)) + return (B_FALSE); + + for (i = 0; i < iflistp->il_nif; i++) + if (!hasnulbyte(iflistp->il_ifs[i], LIFNAMSIZ)) + return (B_FALSE); + break; + + case IPMP_IFINFO: + ifinfop = (ipmp_ifinfo_t *)value; + if (len != sizeof (ipmp_ifinfo_t)) + return (B_FALSE); + + if (!hasnulbyte(ifinfop->if_name, LIFNAMSIZ) || + !hasnulbyte(ifinfop->if_group, LIFGRNAMSIZ)) + return (B_FALSE); + break; + + case IPMP_GROUPLIST: + grlistp = (ipmp_grouplist_t *)value; + if (len < IPMP_GROUPLIST_MINSIZE || + len < IPMP_GROUPLIST_SIZE(grlistp->gl_ngroup)) + return (B_FALSE); + + for (i = 0; i < grlistp->gl_ngroup; i++) + if (!hasnulbyte(grlistp->gl_groups[i], LIFGRNAMSIZ)) + return (B_FALSE); + break; + + case IPMP_GROUPINFO: + grinfop = (ipmp_groupinfo_t *)value; + if (len != sizeof (ipmp_groupinfo_t)) + return (B_FALSE); + + if (!hasnulbyte(grinfop->gr_name, LIFGRNAMSIZ)) + return (B_FALSE); + break; + + case IPMP_SNAP: + if (len != sizeof (ipmp_snap_t)) + return (B_FALSE); + break; + + default: + return (B_FALSE); + } + + return (B_TRUE); +} + +/* + * 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. + */ +ipmp_grouplist_t * +ipmp_grouplist_create(uint64_t sig, unsigned int ngroup, + char (*groups)[LIFGRNAMSIZ]) +{ + unsigned int i; + ipmp_grouplist_t *grlistp; + + grlistp = malloc(IPMP_GROUPLIST_SIZE(ngroup)); + if (grlistp == NULL) + return (NULL); + + grlistp->gl_sig = sig; + grlistp->gl_ngroup = ngroup; + for (i = 0; i < ngroup; i++) + (void) strlcpy(grlistp->gl_groups[i], groups[i], LIFGRNAMSIZ); + + return (grlistp); +} + +/* + * Clone the group list named by `grlistp'. Returns a pointer to the clone on + * success, or NULL on failure. + */ +ipmp_grouplist_t * +ipmp_grouplist_clone(ipmp_grouplist_t *grlistp) +{ + return (ipmp_grouplist_create(grlistp->gl_sig, grlistp->gl_ngroup, + grlistp->gl_groups)); +} + +/* + * 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. + */ +ipmp_ifinfo_t * +ipmp_ifinfo_create(const char *name, const char *group, ipmp_if_state_t state, + ipmp_if_type_t type) +{ + ipmp_ifinfo_t *ifinfop; + + ifinfop = malloc(sizeof (ipmp_ifinfo_t)); + if (ifinfop == NULL) + return (NULL); + + (void) strlcpy(ifinfop->if_name, name, LIFNAMSIZ); + (void) strlcpy(ifinfop->if_group, group, LIFGRNAMSIZ); + ifinfop->if_state = state; + ifinfop->if_type = type; + + return (ifinfop); +} + +/* + * Clone the interface information named by `ifinfop'. Returns a pointer to + * the clone on success, or NULL on failure. + */ +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)); +} + +/* + * Create a group named `name' with signature `sig', in state `state', and + * with the `nif' interfaces named by `ifs' as members. 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_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); + 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); + + return (grinfop); +} + +/* + * Clone the group information named by `grinfop'. Returns a pointer to + * the clone on success, or NULL on failure. + */ +ipmp_groupinfo_t * +ipmp_groupinfo_clone(ipmp_groupinfo_t *grinfop) +{ + return (ipmp_groupinfo_create(grinfop->gr_name, grinfop->gr_sig, + grinfop->gr_state, grinfop->gr_iflistp->il_nif, + grinfop->gr_iflistp->il_ifs)); +} + +/* + * Set the query context associated with `handle' to `qcontext', which must be + * either IPMP_QCONTEXT_LIVE or IPMP_QCONTEXT_SNAP. Upon success, any + * previous snapshot associated with `handle' is discarded. Returns an IPMP + * error code. + */ +int +ipmp_setqcontext(ipmp_handle_t handle, ipmp_qcontext_t qcontext) +{ + ipmp_state_t *statep = handle; + ipmp_snap_t *snap; + int retval; + + switch (qcontext) { + case IPMP_QCONTEXT_LIVE: + snap = NULL; + break; + + case IPMP_QCONTEXT_SNAP: + retval = ipmp_snap_take(statep, &snap); + if (retval != IPMP_SUCCESS) + return (retval); + break; + + default: + return (IPMP_EINVAL); + } + + if (statep->st_snap != NULL) + ipmp_snap_free(statep->st_snap); + statep->st_snap = snap; + + return (IPMP_SUCCESS); +} + +/* + * Create an empty snapshot. Returns a pointer to the snapshot on success, + * or NULL on failure. + */ +ipmp_snap_t * +ipmp_snap_create(void) +{ + ipmp_snap_t *snap; + + snap = malloc(sizeof (ipmp_snap_t)); + if (snap == NULL) + return (NULL); + + snap->sn_grlistp = NULL; + snap->sn_grinfolistp = NULL; + snap->sn_ifinfolistp = NULL; + snap->sn_ngroup = 0; + snap->sn_nif = 0; + + return (snap); +} + +/* + * Free all of the resources associated with snapshot `snap'. + */ +void +ipmp_snap_free(ipmp_snap_t *snap) +{ + ipmp_ifinfolist_t *iflp, *ifnext; + ipmp_groupinfolist_t *grlp, *grnext; + + ipmp_freegrouplist(snap->sn_grlistp); + + for (grlp = snap->sn_grinfolistp; grlp != NULL; grlp = grnext) { + grnext = grlp->grl_next; + ipmp_freegroupinfo(grlp->grl_grinfop); + free(grlp); + } + + for (iflp = snap->sn_ifinfolistp; iflp != NULL; iflp = ifnext) { + ifnext = iflp->ifl_next; + ipmp_freeifinfo(iflp->ifl_ifinfop); + free(iflp); + } + + free(snap); +} + +/* + * Add the group information in `grinfop' to the snapshot named by `snap'. + * Returns an IPMP error code. + */ +int +ipmp_snap_addgroupinfo(ipmp_snap_t *snap, ipmp_groupinfo_t *grinfop) +{ + ipmp_groupinfolist_t *grlp; + + /* + * If the information for this group is already in the snapshot, + * in.mpathd is broken. + */ + if (ipmp_snap_getgroupinfo(snap, grinfop->gr_name) != NULL) + return (IPMP_EPROTO); + + grlp = malloc(sizeof (ipmp_groupinfolist_t)); + if (grlp == NULL) + return (IPMP_ENOMEM); + + grlp->grl_grinfop = grinfop; + grlp->grl_next = snap->sn_grinfolistp; + snap->sn_grinfolistp = grlp; + snap->sn_ngroup++; + + return (IPMP_SUCCESS); +} + +/* + * Add the interface information in `ifinfop' to the snapshot named by `snap'. + * Returns an IPMP error code. + */ +int +ipmp_snap_addifinfo(ipmp_snap_t *snap, ipmp_ifinfo_t *ifinfop) +{ + ipmp_ifinfolist_t *iflp; + + /* + * If the information for this interface is already in the snapshot, + * in.mpathd is broken. + */ + if (ipmp_snap_getifinfo(snap, ifinfop->if_name) != NULL) + return (IPMP_EPROTO); + + iflp = malloc(sizeof (ipmp_ifinfolist_t)); + if (iflp == NULL) + return (IPMP_ENOMEM); + + iflp->ifl_ifinfop = ifinfop; + iflp->ifl_next = snap->sn_ifinfolistp; + snap->sn_ifinfolistp = iflp; + snap->sn_nif++; + + 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. + */ +static ipmp_groupinfo_t * +ipmp_snap_getgroupinfo(ipmp_snap_t *snap, const char *name) +{ + ipmp_groupinfolist_t *grlp; + + for (grlp = snap->sn_grinfolistp; grlp != NULL; grlp = grlp->grl_next) { + if (strcmp(grlp->grl_grinfop->gr_name, name) == 0) + break; + } + + return (grlp != NULL ? grlp->grl_grinfop : NULL); +} + +/* + * Retrieve the information for the interface `name' in snapshot `snap'. + * Returns a pointer to the interface information on success, or NULL on + * failure. + */ +static ipmp_ifinfo_t * +ipmp_snap_getifinfo(ipmp_snap_t *snap, const char *name) +{ + ipmp_ifinfolist_t *iflp; + + for (iflp = snap->sn_ifinfolistp; iflp != NULL; iflp = iflp->ifl_next) { + if (strcmp(iflp->ifl_ifinfop->if_name, name) == 0) + break; + } + + return (iflp != NULL ? iflp->ifl_ifinfop : 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. + */ +static int +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; + struct timeval end; + + snap = ipmp_snap_create(); + if (snap == NULL) + return (IPMP_ENOMEM); + + retval = ipmp_sendquery(statep, IPMP_SNAP, NULL, &end); + if (retval != IPMP_SUCCESS) { + ipmp_snap_free(snap); + return (retval); + } + + retval = ipmp_readinfo(statep, IPMP_SNAP, (void **)&osnap, &end); + if (retval != IPMP_SUCCESS) { + ipmp_snap_free(snap); + return (ipmp_querydone(statep, retval)); + } + + /* + * 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). + */ + do { + infop = NULL; + retval = ipmp_readtlv(statep->st_fd, &type, &len, &infop, &end); + if (retval != IPMP_SUCCESS) + goto fail; + + if (!ipmp_checktlv(type, len, infop)) { + retval = IPMP_EPROTO; + goto fail; + } + + switch (type) { + case IPMP_GROUPLIST: + if (snap->sn_grlistp != NULL) { + retval = IPMP_EPROTO; + break; + } + snap->sn_grlistp = infop; + break; + + case IPMP_IFINFO: + if (snap->sn_nif == osnap->sn_nif) { + retval = IPMP_EPROTO; + break; + } + retval = ipmp_snap_addifinfo(snap, infop); + break; + + case IPMP_GROUPINFO: + if (snap->sn_ngroup == osnap->sn_ngroup) { + retval = IPMP_EPROTO; + break; + } + + /* + * An IPMP_IFLIST TLV always follows the + * IPMP_GROUPINFO TLV; read it in. + */ + retval = ipmp_readinfo(statep, IPMP_IFLIST, + (void **)&iflistp, &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); + break; + + default: + retval = IPMP_EPROTO; + break; + } +fail: + if (retval != IPMP_SUCCESS) { + free(infop); + free(osnap); + ipmp_snap_free(snap); + return (ipmp_querydone(statep, retval)); + } + } while (snap->sn_grlistp == NULL || snap->sn_nif < osnap->sn_nif || + snap->sn_ngroup < osnap->sn_ngroup); + + free(osnap); + *snapp = snap; + return (ipmp_querydone(statep, IPMP_SUCCESS)); +} diff --git a/usr/src/lib/libipmp/common/ipmp_query.h b/usr/src/lib/libipmp/common/ipmp_query.h new file mode 100644 index 0000000000..d92554887a --- /dev/null +++ b/usr/src/lib/libipmp/common/ipmp_query.h @@ -0,0 +1,108 @@ +/* + * 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. + * + * 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 2002 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 */ +#include <ipmp.h> + +/* + * 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. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Data type describing a list of IPMP groups. + */ +typedef struct ipmp_grouplist { + uint64_t gl_sig; + unsigned int gl_ngroup; + 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) + +/* + * Data type describing a list of interfaces. + */ +typedef struct ipmp_iflist { + unsigned int il_nif; + 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) + +/* + * Data type describing the state of an IPMP group. + */ +typedef struct ipmp_groupinfo { + char gr_name[LIFGRNAMSIZ]; + uint64_t gr_sig; + ipmp_group_state_t gr_state; + ipmp_iflist_t *gr_iflistp; +} ipmp_groupinfo_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; +} ipmp_ifinfo_t; + +typedef enum { + IPMP_QCONTEXT_LIVE, + IPMP_QCONTEXT_SNAP +} ipmp_qcontext_t; + +extern int ipmp_setqcontext(ipmp_handle_t, ipmp_qcontext_t); +extern int ipmp_getgrouplist(ipmp_handle_t, ipmp_grouplist_t **); +extern void ipmp_freegrouplist(ipmp_grouplist_t *); +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 *); + +#ifdef __cplusplus +} +#endif + +#endif /* _IPMP_QUERY_H */ diff --git a/usr/src/lib/libipmp/common/ipmp_query_impl.h b/usr/src/lib/libipmp/common/ipmp_query_impl.h new file mode 100644 index 0000000000..03ecb5cd84 --- /dev/null +++ b/usr/src/lib/libipmp/common/ipmp_query_impl.h @@ -0,0 +1,93 @@ +/* + * 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. + * + * 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 2002 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> + +/* + * Private IPMP query interfaces and structures. + * + * These are *only* for use by in.mpathd and libipmp itself. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * List of ipmp_groupinfo_t structures. + */ +typedef struct ipmp_groupinfolist { + struct ipmp_groupinfolist *grl_next; + ipmp_groupinfo_t *grl_grinfop; +} ipmp_groupinfolist_t; + +/* + * List of ipmp_ifinfo_t structures. + */ +typedef struct ipmp_ifinfolist { + struct ipmp_ifinfolist *ifl_next; + ipmp_ifinfo_t *ifl_ifinfop; +} ipmp_ifinfolist_t; + +/* + * Snapshot of IPMP state. + */ +typedef struct ipmp_snap { + ipmp_grouplist_t *sn_grlistp; + ipmp_groupinfolist_t *sn_grinfolistp; + ipmp_ifinfolist_t *sn_ifinfolistp; + unsigned int sn_ngroup; + unsigned int sn_nif; +} ipmp_snap_t; + +/* + * Snapshot-related routines. + */ +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_addgroupinfo(ipmp_snap_t *, ipmp_groupinfo_t *); + +/* + * IPMP structure creation 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]); +extern ipmp_grouplist_t *ipmp_grouplist_create(uint64_t, unsigned int, + char (*)[LIFGRNAMSIZ]); + +#ifdef __cplusplus +} +#endif + +#endif /* _IPMP_QUERY_IMPL_H */ diff --git a/usr/src/lib/libipmp/common/llib-lipmp b/usr/src/lib/libipmp/common/llib-lipmp new file mode 100644 index 0000000000..a16011745a --- /dev/null +++ b/usr/src/lib/libipmp/common/llib-lipmp @@ -0,0 +1,34 @@ +/* + * 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. + * + * 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 2002 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_mpathd.h> +#include <ipmp_query_impl.h> diff --git a/usr/src/lib/libipmp/i386/Makefile b/usr/src/lib/libipmp/i386/Makefile new file mode 100644 index 0000000000..0c05212571 --- /dev/null +++ b/usr/src/lib/libipmp/i386/Makefile @@ -0,0 +1,31 @@ +# +# 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. +# +# 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 2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libipmp/sparc/Makefile b/usr/src/lib/libipmp/sparc/Makefile new file mode 100644 index 0000000000..0c05212571 --- /dev/null +++ b/usr/src/lib/libipmp/sparc/Makefile @@ -0,0 +1,31 @@ +# +# 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. +# +# 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 2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libipmp/spec/Makefile b/usr/src/lib/libipmp/spec/Makefile new file mode 100644 index 0000000000..5df87a9a92 --- /dev/null +++ b/usr/src/lib/libipmp/spec/Makefile @@ -0,0 +1,29 @@ +# +# 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. +# +# 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 2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/lib/libipmp/spec/Makefile.targ b/usr/src/lib/libipmp/spec/Makefile.targ new file mode 100644 index 0000000000..48aa2df3e3 --- /dev/null +++ b/usr/src/lib/libipmp/spec/Makefile.targ @@ -0,0 +1,32 @@ +# +# 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. +# +# 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 2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +LIBRARY = libipmp.a +VERS = .1 +OBJECTS = ipmp.o +SPECCPP = diff --git a/usr/src/lib/libipmp/spec/amd64/Makefile b/usr/src/lib/libipmp/spec/amd64/Makefile new file mode 100644 index 0000000000..4ee7613aaf --- /dev/null +++ b/usr/src/lib/libipmp/spec/amd64/Makefile @@ -0,0 +1,32 @@ +# +# 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. +# +# 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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +.KEEP_STATE: + +all clean clobber install lint: + @echo "Nothing to $@ on amd64" diff --git a/usr/src/lib/libipmp/spec/i386/Makefile b/usr/src/lib/libipmp/spec/i386/Makefile new file mode 100644 index 0000000000..01df11b35b --- /dev/null +++ b/usr/src/lib/libipmp/spec/i386/Makefile @@ -0,0 +1,35 @@ +# +# 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. +# +# 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 2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +.KEEP_STATE: + +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libipmp/spec/ipmp.spec b/usr/src/lib/libipmp/spec/ipmp.spec new file mode 100644 index 0000000000..d2cb5c473e --- /dev/null +++ b/usr/src/lib/libipmp/spec/ipmp.spec @@ -0,0 +1,159 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# 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. +# +# 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 +# +# ident "%Z%%M% %I% %E% SMI" +# + +function ipmp_open +include <ipmp.h> +declaration int ipmp_open(ipmp_handle_t *handlep); +version SUNWprivate_1.1 +end + +function ipmp_close +include <ipmp.h> +declaration void ipmp_close(ipmp_handle_t handle); +version SUNWprivate_1.1 +end + +function ipmp_errmsg +include <ipmp.h> +declaration const char *ipmp_errmsg(int error); +version SUNWprivate_1.1 +end + +function ipmp_setqcontext +include <ipmp_query.h> +declaration int ipmp_setqcontext(ipmp_handle_t handle, \ + ipmp_qcontext_t qcontext); +version SUNWprivate_1.1 +end + +function ipmp_getgrouplist +include <ipmp_query.h> +declaration int ipmp_getgrouplist(ipmp_handle_t handle, \ + ipmp_grouplist_t **grlistpp); +version SUNWprivate_1.1 +end + +function ipmp_freegrouplist +include <ipmp_query.h> +declaration void ipmp_freegrouplist(ipmp_grouplist_t *grlistp); +version SUNWprivate_1.1 +end + +function ipmp_getgroupinfo +include <ipmp_query.h> +declaration int ipmp_getgroupinfo(ipmp_handle_t handle, \ + const char *grname, ipmp_groupinfo_t **grinfopp); +version SUNWprivate_1.1 +end + +function ipmp_freegroupinfo +include <ipmp_query.h> +declaration void ipmp_freegroupinfo(ipmp_groupinfo_t *grinfop); +version SUNWprivate_1.1 +end + +function ipmp_getifinfo +include <ipmp_query.h> +declaration int ipmp_getifinfo(ipmp_handle_t handle, const char *ifname, \ + ipmp_ifinfo_t **ifinfopp); +version SUNWprivate_1.1 +end + +function ipmp_freeifinfo +include <ipmp_query.h> +declaration void ipmp_freeifinfo(ipmp_ifinfo_t *ifinfop); +version SUNWprivate_1.1 +end + +function ipmp_ifinfo_create +include <ipmp_query_impl.h> +declaration ipmp_ifinfo_t *ipmp_ifinfo_create(const char *name, \ + const char *group, ipmp_if_state_t state, \ + ipmp_if_type_t type) +version SUNWprivate_1.1 +end + +function ipmp_groupinfo_create +include <ipmp_query_impl.h> +declaration ipmp_groupinfo_t *ipmp_groupinfo_create(const char *name, \ + uint64_t sig, ipmp_group_state_t state, unsigned int nif, \ + char (*ifs)[LIFNAMSIZ]) +version SUNWprivate_1.1 +end + +function ipmp_grouplist_create +include <ipmp_query_impl.h> +declaration ipmp_grouplist_t *ipmp_grouplist_create(uint64_t sig, \ + unsigned int ngroup, char (*groups)[LIFGRNAMSIZ]) +version SUNWprivate_1.1 +end + +function ipmp_snap_free +include <ipmp_query_impl.h> +declaration void ipmp_snap_free(ipmp_snap_t *) +version SUNWprivate_1.1 +end + +function ipmp_snap_create +include <ipmp_query_impl.h> +declaration ipmp_snap_t *ipmp_snap_create(void) +version SUNWprivate_1.1 +end + +function ipmp_snap_addgroupinfo +include <ipmp_query_impl.h> +declaration int ipmp_snap_addgroupinfo(ipmp_snap_t *snap, \ + ipmp_groupinfo_t *grinfop) +version SUNWprivate_1.1 +end + +function ipmp_snap_addifinfo +include <ipmp_query_impl.h> +declaration int ipmp_snap_addifinfo(ipmp_snap_t *snap, \ + ipmp_ifinfo_t *ifinfop) +version SUNWprivate_1.1 +end + +function ipmp_read +include <ipmp_mpathd.h> +declaration int ipmp_read(int fd, void *buffer, size_t buflen, \ + const struct timeval *endtp) +version SUNWprivate_1.1 +end + +function ipmp_write +include <ipmp_mpathd.h> +declaration int ipmp_write(int fd, const void *buffer, size_t buflen) +version SUNWprivate_1.1 +end + +function ipmp_writetlv +include <ipmp_mpathd.h> +declaration int ipmp_writetlv(int fd, ipmp_infotype_t type, size_t len, \ + void *value) +version SUNWprivate_1.1 +end diff --git a/usr/src/lib/libipmp/spec/sparc/Makefile b/usr/src/lib/libipmp/spec/sparc/Makefile new file mode 100644 index 0000000000..01df11b35b --- /dev/null +++ b/usr/src/lib/libipmp/spec/sparc/Makefile @@ -0,0 +1,35 @@ +# +# 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. +# +# 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 2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +.KEEP_STATE: + +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libipmp/spec/sparcv9/Makefile b/usr/src/lib/libipmp/spec/sparcv9/Makefile new file mode 100644 index 0000000000..4f53c7c87f --- /dev/null +++ b/usr/src/lib/libipmp/spec/sparcv9/Makefile @@ -0,0 +1,32 @@ +# +# 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. +# +# 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 2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +.KEEP_STATE: + +all clean clobber install lint: + @echo "Nothing to $@ on sparcv9" diff --git a/usr/src/lib/libipmp/spec/versions b/usr/src/lib/libipmp/spec/versions new file mode 100644 index 0000000000..3fc6f92d2d --- /dev/null +++ b/usr/src/lib/libipmp/spec/versions @@ -0,0 +1,42 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# 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. +# +# 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 +# +# ident "%Z%%M% %I% %E% SMI" +# + +sparc { + SUNWprivate_1.1; +} + +sparcv9 { + SUNWprivate_1.1; +} + +i386 { + SUNWprivate_1.1; +} + +amd64 { + SUNWprivate_1.1; +} |
