summaryrefslogtreecommitdiff
path: root/usr/src/lib/libinetutil
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libinetutil')
-rw-r--r--usr/src/lib/libinetutil/Makefile57
-rw-r--r--usr/src/lib/libinetutil/Makefile.com64
-rw-r--r--usr/src/lib/libinetutil/amd64/Makefile32
-rw-r--r--usr/src/lib/libinetutil/common/eh.c444
-rw-r--r--usr/src/lib/libinetutil/common/ifspec.c206
-rw-r--r--usr/src/lib/libinetutil/common/inetutil4.c68
-rw-r--r--usr/src/lib/libinetutil/common/libinetutil.h178
-rw-r--r--usr/src/lib/libinetutil/common/libinetutil_impl.h129
-rw-r--r--usr/src/lib/libinetutil/common/llib-linetutil32
-rw-r--r--usr/src/lib/libinetutil/common/tq.c438
-rw-r--r--usr/src/lib/libinetutil/i386/Makefile30
-rw-r--r--usr/src/lib/libinetutil/sparc/Makefile31
-rw-r--r--usr/src/lib/libinetutil/sparcv9/Makefile32
-rw-r--r--usr/src/lib/libinetutil/spec/Makefile30
-rw-r--r--usr/src/lib/libinetutil/spec/Makefile.targ35
-rw-r--r--usr/src/lib/libinetutil/spec/amd64/Makefile44
-rw-r--r--usr/src/lib/libinetutil/spec/i386/Makefile44
-rw-r--r--usr/src/lib/libinetutil/spec/inetutil.spec155
-rw-r--r--usr/src/lib/libinetutil/spec/sparc/Makefile44
-rw-r--r--usr/src/lib/libinetutil/spec/sparcv9/Makefile45
-rw-r--r--usr/src/lib/libinetutil/spec/versions39
21 files changed, 2177 insertions, 0 deletions
diff --git a/usr/src/lib/libinetutil/Makefile b/usr/src/lib/libinetutil/Makefile
new file mode 100644
index 0000000000..0d6e0903b8
--- /dev/null
+++ b/usr/src/lib/libinetutil/Makefile
@@ -0,0 +1,57 @@
+#
+# 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 ../Makefile.lib
+
+HDRS = libinetutil.h
+HDRDIR = common
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+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)
+
+$(SUBDIRS) spec: FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/lib/libinetutil/Makefile.com b/usr/src/lib/libinetutil/Makefile.com
new file mode 100644
index 0000000000..0606c1dcff
--- /dev/null
+++ b/usr/src/lib/libinetutil/Makefile.com
@@ -0,0 +1,64 @@
+#
+# 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 = libinetutil.a
+VERS = .1
+OBJECTS = octet.o inetutil4.o ifspec.o eh.o tq.o
+
+include ../../Makefile.lib
+
+# install this library in the root filesystem
+include ../../Makefile.rootfs
+
+LIBS = $(DYNLIB) $(LINTLIB)
+
+SRCS = $(COMDIR)/octet.c $(SRCDIR)/inetutil4.c \
+ $(SRCDIR)/ifspec.c $(SRCDIR)/eh.c $(SRCDIR)/tq.c
+
+$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
+LDLIBS += -lsocket -lc
+
+SRCDIR = ../common
+COMDIR = $(SRC)/common/net/dhcp
+MAPDIR = ../spec/$(TRANSMACH)
+SPECMAPFILE = $(MAPDIR)/mapfile
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -I$(SRCDIR)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+pics/%.o: $(COMDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/libinetutil/amd64/Makefile b/usr/src/lib/libinetutil/amd64/Makefile
new file mode 100644
index 0000000000..cb39a2beff
--- /dev/null
+++ b/usr/src/lib/libinetutil/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"
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libinetutil/common/eh.c b/usr/src/lib/libinetutil/common/eh.c
new file mode 100644
index 0000000000..9f47d6292e
--- /dev/null
+++ b/usr/src/lib/libinetutil/common/eh.c
@@ -0,0 +1,444 @@
+/*
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stropts.h> /* INFTIM */
+
+#include <libinetutil.h>
+#include "libinetutil_impl.h"
+
+static int grow_fds(iu_eh_t *, int);
+
+/*
+ * signal_to_eh[] is pretty much useless, since the event handler is
+ * really a singleton (we pass iu_eh_t *'s around to maintain an
+ * abstraction, not to allow multiple event handlers to exist). we
+ * need some way to get back our event handler in post_signal(),
+ * and since the signal model is too lame to provide opaque pointers,
+ * we have to resort to global variables.
+ */
+
+static iu_eh_t *signal_to_eh[NSIG];
+
+/*
+ * iu_eh_create(): creates, initializes, and returns an event handler for use
+ *
+ * input: void
+ * output: iu_eh_t *: the new event handler
+ */
+
+iu_eh_t *
+iu_eh_create(void)
+{
+ iu_eh_t *eh = malloc(sizeof (iu_eh_t));
+ int sig;
+
+ if (eh == NULL)
+ return (NULL);
+
+ eh->iueh_pollfds = NULL;
+ eh->iueh_events = NULL;
+ eh->iueh_shutdown = NULL;
+ eh->iueh_num_fds = 0;
+ eh->iueh_stop = B_FALSE;
+ eh->iueh_reason = 0;
+ eh->iueh_shutdown_arg = NULL;
+
+ (void) sigemptyset(&eh->iueh_sig_regset);
+ for (sig = 0; sig < NSIG; sig++) {
+ eh->iueh_sig_info[sig].iues_pending = B_FALSE;
+ eh->iueh_sig_info[sig].iues_handler = NULL;
+ eh->iueh_sig_info[sig].iues_data = NULL;
+ }
+
+ return (eh);
+}
+
+/*
+ * iu_eh_destroy(): destroys an existing event handler
+ *
+ * input: iu_eh_t *: the event handler to destroy
+ * output: void
+ * notes: it is assumed all events related to this eh have been unregistered
+ * prior to calling iu_eh_destroy()
+ */
+
+void
+iu_eh_destroy(iu_eh_t *eh)
+{
+ int sig;
+
+ for (sig = 0; sig < NSIG; sig++)
+ if (signal_to_eh[sig] == eh)
+ (void) iu_eh_unregister_signal(eh, sig, NULL);
+
+ free(eh->iueh_pollfds);
+ free(eh->iueh_events);
+ free(eh);
+}
+
+/*
+ * iu_stop_handling_events(): informs the event handler to stop handling events
+ *
+ * input: iu_eh_t *: the event handler to stop.
+ * unsigned int: the (user-defined) reason why
+ * iu_eh_shutdown_t *: the shutdown callback. if it is NULL,
+ * the event handler will stop right away;
+ * otherwise, the event handler will not
+ * stop until the callback returns B_TRUE
+ * void *: data for the shutdown callback. it may be NULL
+ * output: void
+ * notes: the event handler in question must be in iu_handle_events()
+ */
+
+void
+iu_stop_handling_events(iu_eh_t *eh, unsigned int reason,
+ iu_eh_shutdown_t *shutdown, void *arg)
+{
+ eh->iueh_stop = B_TRUE;
+ eh->iueh_reason = reason;
+ eh->iueh_shutdown = shutdown;
+ eh->iueh_shutdown_arg = arg;
+}
+
+/*
+ * grow_fds(): grows the internal file descriptor set used by the event
+ * handler
+ *
+ * input: iu_eh_t *: the event handler whose descriptor set needs to be grown
+ * int: the new total number of descriptors needed in the set
+ * output: int: zero on failure, success otherwise
+ */
+
+static int
+grow_fds(iu_eh_t *eh, int total_fds)
+{
+ unsigned int i;
+ struct pollfd *new_pollfds;
+ iu_event_node_t *new_events;
+
+ if (total_fds <= eh->iueh_num_fds)
+ return (1);
+
+ new_pollfds = realloc(eh->iueh_pollfds,
+ total_fds * sizeof (struct pollfd));
+ if (new_pollfds == NULL)
+ return (0);
+
+ eh->iueh_pollfds = new_pollfds;
+
+ new_events = realloc(eh->iueh_events,
+ total_fds * sizeof (iu_event_node_t));
+ if (new_events == NULL) {
+
+ /*
+ * yow. one realloc failed, but the other succeeded.
+ * we will just leave the descriptor size at the
+ * original size. if the caller tries again, then the
+ * first realloc() will do nothing since the requested
+ * number of descriptors is already allocated.
+ */
+
+ return (0);
+ }
+
+ for (i = eh->iueh_num_fds; i < total_fds; i++)
+ eh->iueh_pollfds[i].fd = -1;
+
+ eh->iueh_events = new_events;
+ eh->iueh_num_fds = total_fds;
+ return (1);
+}
+
+/*
+ * when increasing the file descriptor set size, how much to increase by:
+ */
+
+#define EH_FD_SLACK 10
+
+/*
+ * iu_register_event(): adds an event to the set managed by an event handler
+ *
+ * input: iu_eh_t *: the event handler to add the event to
+ * int: the descriptor on which to listen for events. must be
+ * a descriptor which has not yet been registered.
+ * short: the events to listen for on that descriptor
+ * iu_eh_callback_t: the callback to execute when the event happens
+ * void *: the argument to pass to the callback function
+ * output: iu_event_id_t: -1 on failure, the new event id otherwise
+ */
+
+iu_event_id_t
+iu_register_event(iu_eh_t *eh, int fd, short events, iu_eh_callback_t *callback,
+ void *arg)
+{
+ if (eh->iueh_num_fds <= fd)
+ if (grow_fds(eh, fd + EH_FD_SLACK) == 0)
+ return (-1);
+
+ /*
+ * the current implementation uses the file descriptor itself
+ * as the iu_event_id_t, since we know the kernel's gonna be
+ * pretty smart about managing file descriptors and we know
+ * that they're per-process unique. however, it does mean
+ * that the same descriptor cannot be registered multiple
+ * times for different callbacks depending on its events. if
+ * this behavior is desired, either use dup(2) to get a unique
+ * descriptor, or demultiplex in the callback function based
+ * on `events'.
+ */
+
+ if (eh->iueh_pollfds[fd].fd != -1)
+ return (-1);
+
+ eh->iueh_pollfds[fd].fd = fd;
+ eh->iueh_pollfds[fd].events = events;
+ eh->iueh_events[fd].iuen_callback = callback;
+ eh->iueh_events[fd].iuen_arg = arg;
+
+ return (fd);
+}
+
+/*
+ * iu_unregister_event(): removes an event from the set managed by an event
+ * handler
+ *
+ * input: iu_eh_t *: the event handler to remove the event from
+ * iu_event_id_t: the event to remove (from iu_register_event())
+ * void **: if non-NULL, will be set to point to the argument passed
+ * into iu_register_event()
+ * output: int: zero on failure, success otherwise
+ */
+
+int
+iu_unregister_event(iu_eh_t *eh, iu_event_id_t event_id, void **arg)
+{
+ if (event_id < 0 || event_id >= eh->iueh_num_fds ||
+ eh->iueh_pollfds[event_id].fd == -1)
+ return (0);
+
+ /*
+ * fringe condition: in case this event was about to be called
+ * back in iu_handle_events(), zero revents to prevent it.
+ * (having an unregistered event get called back could be
+ * disastrous depending on if `arg' is reference counted).
+ */
+
+ eh->iueh_pollfds[event_id].revents = 0;
+ eh->iueh_pollfds[event_id].fd = -1;
+ if (arg != NULL)
+ *arg = eh->iueh_events[event_id].iuen_arg;
+
+ return (1);
+}
+
+/*
+ * iu_handle_events(): begins handling events on an event handler
+ *
+ * input: iu_eh_t *: the event handler to begin event handling on
+ * tq_t *: a timer queue of timers to process while handling events
+ * (see timer_queue.h for details)
+ * output: int: the reason why we stopped, -1 if due to internal failure
+ */
+
+int
+iu_handle_events(iu_eh_t *eh, iu_tq_t *tq)
+{
+ int n_lit, timeout, sig, saved_errno;
+ unsigned int i;
+ sigset_t oset;
+
+ eh->iueh_stop = B_FALSE;
+ do {
+ timeout = tq ? iu_earliest_timer(tq) : INFTIM;
+
+ /*
+ * we only unblock registered signals around poll(); this
+ * way other parts of the code don't have to worry about
+ * restarting "non-restartable" system calls and so forth.
+ */
+
+ (void) sigprocmask(SIG_UNBLOCK, &eh->iueh_sig_regset, &oset);
+ n_lit = poll(eh->iueh_pollfds, eh->iueh_num_fds, timeout);
+ saved_errno = errno;
+ (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+
+ switch (n_lit) {
+
+ case -1:
+ if (saved_errno != EINTR)
+ return (-1);
+
+ for (sig = 0; sig < NSIG; sig++) {
+ if (eh->iueh_sig_info[sig].iues_pending) {
+ eh->iueh_sig_info[sig].iues_pending =
+ B_FALSE;
+ eh->iueh_sig_info[sig].iues_handler(eh,
+ sig,
+ eh->iueh_sig_info[sig].iues_data);
+ }
+ }
+
+ if (eh->iueh_shutdown != NULL)
+ break;
+
+ continue;
+
+ case 0:
+ /*
+ * timeout occurred. we must have a valid tq pointer
+ * since that's the only way a timeout can happen.
+ */
+
+ (void) iu_expire_timers(tq);
+ continue;
+
+ default:
+ break;
+ }
+
+ /* file descriptors are lit; call 'em back */
+
+ for (i = 0; i < eh->iueh_num_fds && n_lit > 0; i++) {
+
+ if (eh->iueh_pollfds[i].revents == 0)
+ continue;
+
+ n_lit--;
+
+ /*
+ * turn off any descriptors that have gone
+ * bad. shouldn't happen, but...
+ */
+
+ if (eh->iueh_pollfds[i].revents & (POLLNVAL|POLLERR)) {
+ /* TODO: issue a warning here - but how? */
+ (void) iu_unregister_event(eh, i, NULL);
+ continue;
+ }
+
+ eh->iueh_events[i].iuen_callback(eh, i,
+ eh->iueh_pollfds[i].revents, i,
+ eh->iueh_events[i].iuen_arg);
+ }
+
+ } while (eh->iueh_stop == B_FALSE || (eh->iueh_shutdown != NULL &&
+ eh->iueh_shutdown(eh, eh->iueh_shutdown_arg) == B_FALSE));
+
+ return (eh->iueh_reason);
+}
+
+/*
+ * post_signal(): posts a signal for later consumption in iu_handle_events()
+ *
+ * input: int: the signal that's been received
+ * output: void
+ */
+
+static void
+post_signal(int sig)
+{
+ if (signal_to_eh[sig] != NULL)
+ signal_to_eh[sig]->iueh_sig_info[sig].iues_pending = B_TRUE;
+}
+
+/*
+ * iu_eh_register_signal(): registers a signal handler with an event handler
+ *
+ * input: iu_eh_t *: the event handler to register the signal handler with
+ * int: the signal to register
+ * iu_eh_sighandler_t *: the signal handler to call back
+ * void *: the argument to pass to the signal handler function
+ * output: int: zero on failure, success otherwise
+ */
+
+int
+iu_eh_register_signal(iu_eh_t *eh, int sig, iu_eh_sighandler_t *handler,
+ void *data)
+{
+ struct sigaction act;
+
+ if (sig < 0 || sig >= NSIG || signal_to_eh[sig] != NULL)
+ return (0);
+
+ act.sa_flags = 0;
+ act.sa_handler = &post_signal;
+ (void) sigemptyset(&act.sa_mask);
+ (void) sigaddset(&act.sa_mask, sig); /* used for sigprocmask() */
+
+ if (sigaction(sig, &act, NULL) == -1)
+ return (0);
+
+ (void) sigprocmask(SIG_BLOCK, &act.sa_mask, NULL);
+
+ eh->iueh_sig_info[sig].iues_data = data;
+ eh->iueh_sig_info[sig].iues_handler = handler;
+ signal_to_eh[sig] = eh;
+
+ (void) sigaddset(&eh->iueh_sig_regset, sig);
+ return (0);
+}
+
+/*
+ * iu_eh_unregister_signal(): unregisters a signal handler from an event handler
+ *
+ * input: iu_eh_t *: the event handler to unregister the signal handler from
+ * int: the signal to unregister
+ * void **: if non-NULL, will be set to point to the argument passed
+ * into iu_eh_register_signal()
+ * output: int: zero on failure, success otherwise
+ */
+
+int
+iu_eh_unregister_signal(iu_eh_t *eh, int sig, void **datap)
+{
+ sigset_t set;
+
+ if (sig < 0 || sig >= NSIG || signal_to_eh[sig] != eh)
+ return (0);
+
+ if (signal(sig, SIG_DFL) == SIG_ERR)
+ return (0);
+
+ if (datap != NULL)
+ *datap = eh->iueh_sig_info[sig].iues_data;
+
+ (void) sigemptyset(&set);
+ (void) sigaddset(&set, sig);
+ (void) sigprocmask(SIG_UNBLOCK, &set, NULL);
+
+ eh->iueh_sig_info[sig].iues_data = NULL;
+ eh->iueh_sig_info[sig].iues_handler = NULL;
+ eh->iueh_sig_info[sig].iues_pending = B_FALSE;
+ signal_to_eh[sig] = NULL;
+
+ (void) sigdelset(&eh->iueh_sig_regset, sig);
+ return (1);
+}
diff --git a/usr/src/lib/libinetutil/common/ifspec.c b/usr/src/lib/libinetutil/common/ifspec.c
new file mode 100644
index 0000000000..58f7c5ae71
--- /dev/null
+++ b/usr/src/lib/libinetutil/common/ifspec.c
@@ -0,0 +1,206 @@
+/*
+ * 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 (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This file contains a routine used to validate a ifconfig-style interface
+ * specification
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <alloca.h>
+#include <errno.h>
+#include <string.h>
+#include <libinetutil.h>
+
+/*
+ * Given a token with a logical unit spec, return the logical unit converted
+ * to a uint_t.
+ *
+ * Returns: 0 for success, nonzero if an error occurred. errno is set if
+ * necessary.
+ */
+static int
+getlun(const char *bp, int bpsize, uint_t *lun)
+{
+ char *ep = (char *)&bp[bpsize - 1];
+ char *sp = strchr(bp, ':'), *tp;
+
+ /* A logical unit spec looks like: <token>:<unsigned int>\0 */
+ if (isdigit(*bp) || !isdigit(*ep) || sp == NULL ||
+ strchr(sp + 1, ':') != NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *sp++ = '\0';
+
+ /* Lun must be all digits */
+ for (tp = sp; tp < ep && isdigit(*tp); tp++)
+ /* Null body */;
+ if (tp != ep) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *lun = atoi(sp);
+ return (0);
+}
+
+/*
+ * Given a single token ending with a ppa spec, return the ppa spec converted
+ * to a uint_t.
+ *
+ * Returns: 0 for success, nonzero if an error occurred. errno is set if
+ * necessary.
+ */
+static int
+getppa(const char *bp, int bpsize, uint_t *ppa)
+{
+ char *ep = (char *)&bp[bpsize - 1];
+ char *tp;
+
+ if (isdigit(*bp) || !isdigit(*ep)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ for (tp = ep; tp >= bp && isdigit(*tp); tp--)
+ /* Null body */;
+
+ if (*tp == '.' || *tp == ':') {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *ppa = atoi(tp + 1);
+ return (0);
+}
+
+/*
+ * Given an ifconfig-style inet relative-path interface specification
+ * (e.g: hme0.foo.ip.udp:2), validate its form and decompose the contents
+ * into a dynamically allocated ifspec_t.
+ *
+ * Returns ifspec_t for success, NULL pointer if spec is malformed.
+ */
+boolean_t
+ifparse_ifspec(const char *ifname, ifspec_t *ifsp)
+{
+ char *mp, *ep, *lp, *tp;
+ char *ifnamecp;
+ size_t iflen;
+ boolean_t have_ppa = B_FALSE;
+
+ iflen = strlen(ifname);
+ if (iflen > LIFNAMSIZ) {
+ errno = EINVAL;
+ return (B_FALSE);
+ }
+
+ /* snag a copy we can modify */
+ ifnamecp = alloca(iflen + 1);
+ (void) strlcpy(ifnamecp, ifname, iflen + 1);
+
+ ifsp->ifsp_lunvalid = B_FALSE;
+
+ /*
+ * An interface name must have the format of:
+ * dev[ppa][.module[.module...][ppa]][:lun]
+ *
+ * where only one ppa may be specified e.g. ip0.foo.tun or ip.foo.tun0
+ *
+ * lun - logical unit number.
+ *
+ * Produce substrings for each grouping, starting first with modules,
+ * then lun, devname, and finally ppa.
+ */
+
+ /* Any modules? */
+ mp = strchr(ifnamecp, '.');
+
+ /* Any logical units? */
+ lp = strchr(ifnamecp, ':');
+
+ if (lp != NULL && mp != NULL && lp < mp) {
+ errno = EINVAL;
+ return (B_FALSE);
+ }
+
+ ifsp->ifsp_modcnt = 0;
+ if (mp != NULL) {
+ *mp++ = '\0';
+ if (lp != NULL)
+ *lp = '\0';
+ while (mp != NULL && ifsp->ifsp_modcnt <= IFSP_MAXMODS) {
+ if ((ep = strchr(mp, '.')) != NULL)
+ *ep++ = '\0';
+ (void) strlcpy(ifsp->ifsp_mods[ifsp->ifsp_modcnt++],
+ mp, LIFNAMSIZ);
+ mp = ep;
+ }
+ if (lp != NULL)
+ *lp = ':';
+ if (ifsp->ifsp_modcnt > IFSP_MAXMODS) {
+ errno = E2BIG;
+ return (B_FALSE);
+ }
+ }
+
+ if (lp != NULL) {
+ if (getlun(lp, strlen(lp), &ifsp->ifsp_lun) != 0)
+ return (B_FALSE);
+ ifsp->ifsp_lunvalid = B_TRUE;
+ }
+
+ (void) strlcpy(ifsp->ifsp_devnm, ifnamecp, LIFNAMSIZ);
+
+ /* Find ppa - has to be part of devname or part of last module name */
+ /* This should be changed to require the latter of the two */
+ if (getppa(ifsp->ifsp_devnm, strlen(ifsp->ifsp_devnm),
+ &ifsp->ifsp_ppa) == 0)
+ have_ppa = B_TRUE;
+ if (ifsp->ifsp_modcnt != 0 &&
+ getppa(ifsp->ifsp_mods[ifsp->ifsp_modcnt - 1],
+ strlen(ifsp->ifsp_mods[ifsp->ifsp_modcnt - 1]),
+ &ifsp->ifsp_ppa) == 0) {
+ if (!have_ppa)
+ have_ppa = B_TRUE;
+ else
+ return (B_FALSE); /* only one please */
+ }
+ if (!have_ppa)
+ return (B_FALSE);
+
+ /* strip the ppa off of the device name if present */
+ for (tp = &ifsp->ifsp_devnm[strlen(ifsp->ifsp_devnm) - 1];
+ tp >= ifsp->ifsp_devnm && isdigit(*tp); tp--)
+ *tp = '\0';
+
+ return (B_TRUE);
+}
diff --git a/usr/src/lib/libinetutil/common/inetutil4.c b/usr/src/lib/libinetutil/common/inetutil4.c
new file mode 100644
index 0000000000..2e564bb6fd
--- /dev/null
+++ b/usr/src/lib/libinetutil/common/inetutil4.c
@@ -0,0 +1,68 @@
+/*
+ * 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 (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <unistd.h>
+#include <netinet/in.h>
+#include <libinetutil.h>
+
+extern int getnetmaskbyaddr(const struct in_addr, struct in_addr *);
+
+/*
+ * Generic internet (v4) functions.
+ */
+
+/*
+ * Given a host-order address, calculate client's default net mask.
+ * Consult netmasks database to see if net is further subnetted.
+ * We'll only snag the first netmask that matches our criteria.
+ * We return the resultant netmask in host order.
+ */
+void
+get_netmask4(const struct in_addr *n_addrp, struct in_addr *s_addrp)
+{
+ struct in_addr hp, tp;
+
+ /*
+ * First check if VLSM is in use.
+ */
+ hp.s_addr = htonl(n_addrp->s_addr);
+ if (getnetmaskbyaddr(hp, &tp) == 0) {
+ s_addrp->s_addr = ntohl(tp.s_addr);
+ return;
+ }
+
+ /*
+ * Fall back on standard classed networks.
+ */
+ if (IN_CLASSA(n_addrp->s_addr))
+ s_addrp->s_addr = IN_CLASSA_NET;
+ else if (IN_CLASSB(n_addrp->s_addr))
+ s_addrp->s_addr = IN_CLASSB_NET;
+ else
+ s_addrp->s_addr = IN_CLASSC_NET;
+}
diff --git a/usr/src/lib/libinetutil/common/libinetutil.h b/usr/src/lib/libinetutil/common/libinetutil.h
new file mode 100644
index 0000000000..0213a23aa2
--- /dev/null
+++ b/usr/src/lib/libinetutil/common/libinetutil.h
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBINETUTIL_H
+#define _LIBINETUTIL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Contains SMI-private API for general internet functionality
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <netinet/inetutil.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+#if !defined(_KERNEL) && !defined(_BOOT)
+
+#define IFSP_MAXMODS 9 /* Max modules that can be pushed on if */
+
+typedef struct {
+ uint_t ifsp_ppa; /* Physical Point of Attachment */
+ uint_t ifsp_lun; /* Logical Unit number */
+ boolean_t ifsp_lunvalid; /* TRUE if lun is valid */
+ int ifsp_modcnt; /* Number of modules to be pushed */
+ char ifsp_devnm[LIFNAMSIZ]; /* only the device name */
+ char ifsp_mods[IFSP_MAXMODS][LIFNAMSIZ]; /* table of mods */
+} ifspec_t;
+
+extern boolean_t ifparse_ifspec(const char *, ifspec_t *);
+extern void get_netmask4(const struct in_addr *, struct in_addr *);
+
+/*
+ * Timer queues
+ *
+ * timer queues are a facility for managing timeouts in unix. in the
+ * event driven model, unix provides us with poll(2)/select(3C), which
+ * allow us to coordinate waiting on multiple descriptors with an
+ * optional timeout. however, often (as is the case with the DHCP
+ * agent), we want to manage multiple independent timeouts (say, one
+ * for waiting for an OFFER to come back from a server in response to
+ * a DISCOVER sent out on one interface, and another for waiting for
+ * the T1 time on another interface). timer queues allow us to do
+ * this in the event-driven model.
+ *
+ * note that timer queues do not in and of themselves provide the
+ * event driven model (for instance, there is no handle_events()
+ * routine). they merely provide the hooks to support multiple
+ * independent timeouts. this is done for both simplicity and
+ * applicability (for instance, while one approach would be to use
+ * this timer queue with poll(2), another one would be to use SIGALRM
+ * to wake up periodically, and then process all the expired timers.)
+ */
+
+typedef struct iu_timer_queue iu_tq_t;
+
+/*
+ * a iu_timer_id_t refers to a given timer. its value should not be
+ * interpreted by the interface consumer. it is a signed arithmetic
+ * type, and no valid iu_timer_id_t has the value `-1'.
+ */
+
+typedef int iu_timer_id_t;
+
+#define IU_TIMER_ID_MAX 1024 /* max number of concurrent timers */
+
+/*
+ * a iu_tq_callback_t is a function that is called back in response to a
+ * timer expiring. it may then carry out any necessary work,
+ * including rescheduling itself for callback or scheduling /
+ * cancelling other timers. the `void *' argument is the same value
+ * that was passed into iu_schedule_timer(), and if it is dynamically
+ * allocated, it is the callback's responsibility to know that, and to
+ * free it.
+ */
+
+typedef void iu_tq_callback_t(iu_tq_t *, void *);
+
+iu_tq_t *iu_tq_create(void);
+void iu_tq_destroy(iu_tq_t *);
+iu_timer_id_t iu_schedule_timer(iu_tq_t *, uint32_t, iu_tq_callback_t *,
+ void *);
+iu_timer_id_t iu_schedule_timer_ms(iu_tq_t *, uint64_t, iu_tq_callback_t *,
+ void *);
+int iu_adjust_timer(iu_tq_t *, iu_timer_id_t, uint32_t);
+int iu_cancel_timer(iu_tq_t *, iu_timer_id_t, void **);
+int iu_expire_timers(iu_tq_t *);
+int iu_earliest_timer(iu_tq_t *);
+
+/*
+ * Event Handler
+ *
+ * an event handler is an object-oriented "wrapper" for select(3C) /
+ * poll(2), aimed to make the event demultiplexing system calls easier
+ * to use and provide a generic reusable component. instead of
+ * applications directly using select(3C) / poll(2), they register
+ * events that should be received with the event handler, providing a
+ * callback function to call when the event occurs. they then call
+ * iu_handle_events() to wait and callback the registered functions
+ * when events occur. also called a `reactor'.
+ */
+
+typedef struct iu_event_handler iu_eh_t;
+
+/*
+ * an iu_event_id_t refers to a given event. its value should not be
+ * interpreted by the interface consumer. it is a signed arithmetic
+ * type, and no valid iu_event_id_t has the value `-1'.
+ */
+
+typedef int iu_event_id_t;
+
+/*
+ * an iu_eh_callback_t is a function that is called back in response to
+ * an event occurring. it may then carry out any work necessary in
+ * response to the event. it receives the file descriptor upon which
+ * the event occurred, a bit array of events that occurred (the same
+ * array used as the revents by poll(2)), and its context through the
+ * `void *' that was originally passed into iu_register_event().
+ *
+ * NOTE: the same descriptor may not be registered multiple times for
+ * different callbacks. if this behavior is desired, either use dup(2)
+ * to get a unique descriptor, or demultiplex in the callback function
+ * based on the events.
+ */
+
+typedef void iu_eh_callback_t(iu_eh_t *, int, short, iu_event_id_t, void *);
+typedef void iu_eh_sighandler_t(iu_eh_t *, int, void *);
+typedef boolean_t iu_eh_shutdown_t(iu_eh_t *, void *);
+
+iu_eh_t *iu_eh_create(void);
+void iu_eh_destroy(iu_eh_t *);
+iu_event_id_t iu_register_event(iu_eh_t *, int, short, iu_eh_callback_t *,
+ void *);
+int iu_unregister_event(iu_eh_t *, iu_event_id_t, void **);
+int iu_handle_events(iu_eh_t *, iu_tq_t *);
+void iu_stop_handling_events(iu_eh_t *, unsigned int,
+ iu_eh_shutdown_t *, void *);
+int iu_eh_register_signal(iu_eh_t *, int, iu_eh_sighandler_t *,
+ void *);
+int iu_eh_unregister_signal(iu_eh_t *, int, void **);
+
+#endif /* !defined(_KERNEL) && !defined(_BOOT) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_LIBINETUTIL_H */
diff --git a/usr/src/lib/libinetutil/common/libinetutil_impl.h b/usr/src/lib/libinetutil/common/libinetutil_impl.h
new file mode 100644
index 0000000000..268d584d1b
--- /dev/null
+++ b/usr/src/lib/libinetutil/common/libinetutil_impl.h
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBINETUTIL_IMPL_H
+#define _LIBINETUTIL_IMPL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Contains implementation-specific definitions for libinetutil.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <netinet/inetutil.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <sys/poll.h>
+#include <signal.h>
+#include <limits.h>
+
+/*
+ * timer queue implementation-specific artifacts which may change. A
+ * `iu_tq_t' is an incomplete type as far as the consumer of timer queues
+ * is concerned.
+ */
+
+typedef struct iu_timer_node {
+
+ struct iu_timer_node *iutn_prev;
+ struct iu_timer_node *iutn_next;
+ struct iu_timer_node *iutn_expire_next;
+ hrtime_t iutn_abs_timeout;
+ iu_timer_id_t iutn_timer_id;
+ iu_tq_callback_t *iutn_callback;
+ void *iutn_arg;
+ int iutn_pending_delete;
+
+} iu_timer_node_t;
+
+struct iu_timer_queue {
+ iu_timer_id_t iutq_next_timer_id;
+ iu_timer_node_t *iutq_head; /* in order of time-to-fire */
+ int iutq_in_expire; /* nonzero if in the expire function */
+ uchar_t iutq_timer_id_map[(IU_TIMER_ID_MAX + CHAR_BIT) /
+ CHAR_BIT];
+};
+
+/*
+ * event handler implementation-specific artifacts which may change. An
+ * `iu_eh_t' is an incomplete type as far as the consumer of event handlers is
+ * concerned.
+ */
+
+typedef struct iu_event_node {
+
+ iu_eh_callback_t *iuen_callback; /* callback to call */
+
+ void *iuen_arg; /* argument to pass to the */
+ /* callback */
+} iu_event_node_t;
+
+typedef struct iu_eh_sig_info {
+
+ boolean_t iues_pending; /* signal is currently */
+ /* pending */
+
+ iu_eh_sighandler_t *iues_handler; /* handler for a given signal */
+
+ void *iues_data; /* data to pass back to the */
+ /* handler */
+} iu_eh_sig_info_t;
+
+struct iu_event_handler {
+
+ struct pollfd *iueh_pollfds; /* array of pollfds */
+
+ iu_event_node_t *iueh_events; /* corresponding pollfd info */
+
+ unsigned int iueh_num_fds; /* number of pollfds/events */
+
+ boolean_t iueh_stop; /* true when done */
+
+ unsigned int iueh_reason; /* if stop is true, reason */
+
+ sigset_t iueh_sig_regset; /* registered signal */
+ /* set */
+
+ iu_eh_sig_info_t iueh_sig_info[NSIG]; /* signal handler */
+ /* information */
+
+ iu_eh_shutdown_t *iueh_shutdown; /* shutdown callback */
+
+ void *iueh_shutdown_arg; /* data for shutdown */
+ /* callback */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_LIBINETUTIL_IMPL_H */
diff --git a/usr/src/lib/libinetutil/common/llib-linetutil b/usr/src/lib/libinetutil/common/llib-linetutil
new file mode 100644
index 0000000000..5e87f60dea
--- /dev/null
+++ b/usr/src/lib/libinetutil/common/llib-linetutil
@@ -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 (c) 2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+#include <libinetutil.h>
diff --git a/usr/src/lib/libinetutil/common/tq.c b/usr/src/lib/libinetutil/common/tq.c
new file mode 100644
index 0000000000..78505462bd
--- /dev/null
+++ b/usr/src/lib/libinetutil/common/tq.c
@@ -0,0 +1,438 @@
+/*
+ * 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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/stropts.h> /* INFTIM */
+
+#include <libinetutil.h>
+#include "libinetutil_impl.h"
+
+static iu_timer_node_t *pending_delete_chain = NULL;
+
+static void destroy_timer(iu_tq_t *, iu_timer_node_t *);
+static iu_timer_id_t get_timer_id(iu_tq_t *);
+static void release_timer_id(iu_tq_t *, iu_timer_id_t);
+
+/*
+ * iu_tq_create(): creates, initializes and returns a timer queue for use
+ *
+ * input: void
+ * output: iu_tq_t *: the new timer queue
+ */
+
+iu_tq_t *
+iu_tq_create(void)
+{
+ return (calloc(1, sizeof (iu_tq_t)));
+}
+
+/*
+ * iu_tq_destroy(): destroys an existing timer queue
+ *
+ * input: iu_tq_t *: the timer queue to destroy
+ * output: void
+ */
+
+void
+iu_tq_destroy(iu_tq_t *tq)
+{
+ iu_timer_node_t *node, *next_node;
+
+ for (node = tq->iutq_head; node != NULL; node = next_node) {
+ next_node = node->iutn_next;
+ destroy_timer(tq, node);
+ }
+
+ free(tq);
+}
+
+/*
+ * insert_timer(): inserts a timer node into a tq's timer list
+ *
+ * input: iu_tq_t *: the timer queue
+ * iu_timer_node_t *: the timer node to insert into the list
+ * uint64_t: the number of milliseconds before this timer fires
+ * output: void
+ */
+
+static void
+insert_timer(iu_tq_t *tq, iu_timer_node_t *node, uint64_t msec)
+{
+ iu_timer_node_t *after = NULL;
+
+ /*
+ * find the node to insert this new node "after". we do this
+ * instead of the more intuitive "insert before" because with
+ * the insert before approach, a null `before' node pointer
+ * is overloaded in meaning (it could be null because there
+ * are no items in the list, or it could be null because this
+ * is the last item on the list, which are very different cases).
+ */
+
+ node->iutn_abs_timeout = gethrtime() + (msec * (NANOSEC / MILLISEC));
+
+ if (tq->iutq_head != NULL &&
+ tq->iutq_head->iutn_abs_timeout < node->iutn_abs_timeout)
+ for (after = tq->iutq_head; after->iutn_next != NULL;
+ after = after->iutn_next)
+ if (after->iutn_next->iutn_abs_timeout >
+ node->iutn_abs_timeout)
+ break;
+
+ node->iutn_next = after ? after->iutn_next : tq->iutq_head;
+ node->iutn_prev = after;
+ if (after == NULL)
+ tq->iutq_head = node;
+ else
+ after->iutn_next = node;
+
+ if (node->iutn_next != NULL)
+ node->iutn_next->iutn_prev = node;
+}
+
+/*
+ * remove_timer(): removes a timer node from the tq's timer list
+ *
+ * input: iu_tq_t *: the timer queue
+ * iu_timer_node_t *: the timer node to remove from the list
+ * output: void
+ */
+
+static void
+remove_timer(iu_tq_t *tq, iu_timer_node_t *node)
+{
+ if (node->iutn_next != NULL)
+ node->iutn_next->iutn_prev = node->iutn_prev;
+ if (node->iutn_prev != NULL)
+ node->iutn_prev->iutn_next = node->iutn_next;
+ else
+ tq->iutq_head = node->iutn_next;
+}
+
+/*
+ * destroy_timer(): destroy a timer node
+ *
+ * input: iu_tq_t *: the timer queue the timer node is associated with
+ * iu_timer_node_t *: the node to free
+ * output: void
+ */
+
+static void
+destroy_timer(iu_tq_t *tq, iu_timer_node_t *node)
+{
+ release_timer_id(tq, node->iutn_timer_id);
+
+ /*
+ * if we're in expire, don't delete the node yet, since it may
+ * still be referencing it (through the expire_next pointers)
+ */
+
+ if (tq->iutq_in_expire) {
+ node->iutn_pending_delete++;
+ node->iutn_next = pending_delete_chain;
+ pending_delete_chain = node;
+ } else
+ free(node);
+
+}
+
+/*
+ * iu_schedule_timer(): creates and inserts a timer in the tq's timer list
+ *
+ * input: iu_tq_t *: the timer queue
+ * uint32_t: the number of seconds before this timer fires
+ * iu_tq_callback_t *: the function to call when the timer fires
+ * void *: an argument to pass to the called back function
+ * output: iu_timer_id_t: the new timer's timer id on success, -1 on failure
+ */
+
+iu_timer_id_t
+iu_schedule_timer(iu_tq_t *tq, uint32_t sec, iu_tq_callback_t *callback,
+ void *arg)
+{
+ return (iu_schedule_timer_ms(tq, sec * MILLISEC, callback, arg));
+}
+
+/*
+ * iu_schedule_ms_timer(): creates and inserts a timer in the tq's timer list,
+ * using millisecond granularity
+ *
+ * input: iu_tq_t *: the timer queue
+ * uint64_t: the number of milliseconds before this timer fires
+ * iu_tq_callback_t *: the function to call when the timer fires
+ * void *: an argument to pass to the called back function
+ * output: iu_timer_id_t: the new timer's timer id on success, -1 on failure
+ */
+iu_timer_id_t
+iu_schedule_timer_ms(iu_tq_t *tq, uint64_t ms, iu_tq_callback_t *callback,
+ void *arg)
+{
+ iu_timer_node_t *node = calloc(1, sizeof (iu_timer_node_t));
+
+ if (node == NULL)
+ return (-1);
+
+ node->iutn_callback = callback;
+ node->iutn_arg = arg;
+ node->iutn_timer_id = get_timer_id(tq);
+ if (node->iutn_timer_id == -1) {
+ free(node);
+ return (-1);
+ }
+
+ insert_timer(tq, node, ms);
+
+ return (node->iutn_timer_id);
+}
+
+/*
+ * iu_cancel_timer(): cancels a pending timer from a timer queue's timer list
+ *
+ * input: iu_tq_t *: the timer queue
+ * iu_timer_id_t: the timer id returned from iu_schedule_timer
+ * void **: if non-NULL, a place to return the argument passed to
+ * iu_schedule_timer
+ * output: int: 1 on success, 0 on failure
+ */
+
+int
+iu_cancel_timer(iu_tq_t *tq, iu_timer_id_t timer_id, void **arg)
+{
+ iu_timer_node_t *node;
+
+ if (timer_id == -1)
+ return (0);
+
+ for (node = tq->iutq_head; node != NULL; node = node->iutn_next) {
+ if (node->iutn_timer_id == timer_id) {
+ if (arg != NULL)
+ *arg = node->iutn_arg;
+ remove_timer(tq, node);
+ destroy_timer(tq, node);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * iu_adjust_timer(): adjusts the fire time of a timer in the tq's timer list
+ *
+ * input: iu_tq_t *: the timer queue
+ * iu_timer_id_t: the timer id returned from iu_schedule_timer
+ * uint32_t: the number of seconds before this timer fires
+ * output: int: 1 on success, 0 on failure
+ */
+
+int
+iu_adjust_timer(iu_tq_t *tq, iu_timer_id_t timer_id, uint32_t sec)
+{
+ iu_timer_node_t *node;
+
+ if (timer_id == -1)
+ return (0);
+
+ for (node = tq->iutq_head; node != NULL; node = node->iutn_next) {
+ if (node->iutn_timer_id == timer_id) {
+ remove_timer(tq, node);
+ insert_timer(tq, node, sec * MILLISEC);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * iu_earliest_timer(): returns the time until the next timer fires on a tq
+ *
+ * input: iu_tq_t *: the timer queue
+ * output: int: the number of milliseconds until the next timer (up to
+ * a maximum value of INT_MAX), or INFTIM if no timers are pending.
+ */
+
+int
+iu_earliest_timer(iu_tq_t *tq)
+{
+ unsigned long long timeout_interval;
+ hrtime_t current_time = gethrtime();
+
+ if (tq->iutq_head == NULL)
+ return (INFTIM);
+
+ /*
+ * event might've already happened if we haven't gotten a chance to
+ * run in a while; return zero and pretend it just expired.
+ */
+
+ if (tq->iutq_head->iutn_abs_timeout <= current_time)
+ return (0);
+
+ /*
+ * since the timers are ordered in absolute time-to-fire, just
+ * subtract from the head of the list.
+ */
+
+ timeout_interval =
+ (tq->iutq_head->iutn_abs_timeout - current_time) / 1000000;
+
+ return (MIN(timeout_interval, INT_MAX));
+}
+
+/*
+ * iu_expire_timers(): expires all pending timers on a given timer queue
+ *
+ * input: iu_tq_t *: the timer queue
+ * output: int: the number of timers expired
+ */
+
+int
+iu_expire_timers(iu_tq_t *tq)
+{
+ iu_timer_node_t *node, *next_node;
+ int n_expired = 0;
+ hrtime_t current_time = gethrtime();
+
+ /*
+ * in_expire is in the iu_tq_t instead of being passed through as
+ * an argument to remove_timer() below since the callback
+ * function may call iu_cancel_timer() itself as well.
+ */
+
+ tq->iutq_in_expire++;
+
+ /*
+ * this function builds another linked list of timer nodes
+ * through `expire_next' because the normal linked list
+ * may be changed as a result of callbacks canceling and
+ * scheduling timeouts, and thus can't be trusted.
+ */
+
+ for (node = tq->iutq_head; node != NULL; node = node->iutn_next)
+ node->iutn_expire_next = node->iutn_next;
+
+ for (node = tq->iutq_head; node != NULL;
+ node = node->iutn_expire_next) {
+
+ if (node->iutn_abs_timeout > current_time)
+ break;
+
+ /*
+ * fringe condition: two timers fire at the "same
+ * time" (i.e., they're both scheduled called back in
+ * this loop) and one cancels the other. in this
+ * case, the timer which has already been "cancelled"
+ * should not be called back.
+ */
+
+ if (node->iutn_pending_delete)
+ continue;
+
+ /*
+ * we remove the timer before calling back the callback
+ * so that a callback which accidentally tries to cancel
+ * itself (through whatever means) doesn't succeed.
+ */
+
+ n_expired++;
+ remove_timer(tq, node);
+ destroy_timer(tq, node);
+ node->iutn_callback(tq, node->iutn_arg);
+ }
+
+ tq->iutq_in_expire--;
+
+ /*
+ * any cancels that took place whilst we were expiring timeouts
+ * ended up on the `pending_delete_chain'. delete them now
+ * that it's safe.
+ */
+
+ for (node = pending_delete_chain; node != NULL; node = next_node) {
+ next_node = node->iutn_next;
+ free(node);
+ }
+ pending_delete_chain = NULL;
+
+ return (n_expired);
+}
+
+/*
+ * get_timer_id(): allocates a timer id from the pool
+ *
+ * input: iu_tq_t *: the timer queue
+ * output: iu_timer_id_t: the allocated timer id, or -1 if none available
+ */
+
+static iu_timer_id_t
+get_timer_id(iu_tq_t *tq)
+{
+ unsigned int map_index;
+ unsigned char map_bit;
+ boolean_t have_wrapped = B_FALSE;
+
+ for (; ; tq->iutq_next_timer_id++) {
+
+ if (tq->iutq_next_timer_id >= IU_TIMER_ID_MAX) {
+ if (have_wrapped)
+ return (-1);
+
+ have_wrapped = B_TRUE;
+ tq->iutq_next_timer_id = 0;
+ }
+
+ map_index = tq->iutq_next_timer_id / CHAR_BIT;
+ map_bit = tq->iutq_next_timer_id % CHAR_BIT;
+
+ if ((tq->iutq_timer_id_map[map_index] & (1 << map_bit)) == 0)
+ break;
+ }
+
+ tq->iutq_timer_id_map[map_index] |= (1 << map_bit);
+ return (tq->iutq_next_timer_id++);
+}
+
+/*
+ * release_timer_id(): releases a timer id back into the pool
+ *
+ * input: iu_tq_t *: the timer queue
+ * iu_timer_id_t: the timer id to release
+ * output: void
+ */
+
+static void
+release_timer_id(iu_tq_t *tq, iu_timer_id_t timer_id)
+{
+ unsigned int map_index = timer_id / CHAR_BIT;
+ unsigned char map_bit = timer_id % CHAR_BIT;
+
+ tq->iutq_timer_id_map[map_index] &= ~(1 << map_bit);
+}
diff --git a/usr/src/lib/libinetutil/i386/Makefile b/usr/src/lib/libinetutil/i386/Makefile
new file mode 100644
index 0000000000..3fb883a3f8
--- /dev/null
+++ b/usr/src/lib/libinetutil/i386/Makefile
@@ -0,0 +1,30 @@
+#
+# 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 (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libinetutil/sparc/Makefile b/usr/src/lib/libinetutil/sparc/Makefile
new file mode 100644
index 0000000000..19a9e65a11
--- /dev/null
+++ b/usr/src/lib/libinetutil/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 (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libinetutil/sparcv9/Makefile b/usr/src/lib/libinetutil/sparcv9/Makefile
new file mode 100644
index 0000000000..87e9702141
--- /dev/null
+++ b/usr/src/lib/libinetutil/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 (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libinetutil/spec/Makefile b/usr/src/lib/libinetutil/spec/Makefile
new file mode 100644
index 0000000000..ca996b5cd4
--- /dev/null
+++ b/usr/src/lib/libinetutil/spec/Makefile
@@ -0,0 +1,30 @@
+#
+# 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 (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libinetutil/spec/Makefile
+
+include $(SRC)/lib/Makefile.spec.arch
diff --git a/usr/src/lib/libinetutil/spec/Makefile.targ b/usr/src/lib/libinetutil/spec/Makefile.targ
new file mode 100644
index 0000000000..dc5a1e2c9d
--- /dev/null
+++ b/usr/src/lib/libinetutil/spec/Makefile.targ
@@ -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 (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libinetutil/spec/Makefile.targ
+
+LIBRARY = libinetutil.a
+VERS = .1
+
+OBJECTS = inetutil.o
+
+SPECCPP = -I../..
diff --git a/usr/src/lib/libinetutil/spec/amd64/Makefile b/usr/src/lib/libinetutil/spec/amd64/Makefile
new file mode 100644
index 0000000000..fb532ef308
--- /dev/null
+++ b/usr/src/lib/libinetutil/spec/amd64/Makefile
@@ -0,0 +1,44 @@
+#
+# 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:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#amd64_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libinetutil/spec/i386/Makefile b/usr/src/lib/libinetutil/spec/i386/Makefile
new file mode 100644
index 0000000000..5998e7365a
--- /dev/null
+++ b/usr/src/lib/libinetutil/spec/i386/Makefile
@@ -0,0 +1,44 @@
+#
+# 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 (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libinetutil/spec/i386/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#i386_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libinetutil/spec/inetutil.spec b/usr/src/lib/libinetutil/spec/inetutil.spec
new file mode 100644
index 0000000000..33f4a27aff
--- /dev/null
+++ b/usr/src/lib/libinetutil/spec/inetutil.spec
@@ -0,0 +1,155 @@
+#
+# 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"
+#
+# lib/libinetutil/spec/inetutil.spec
+
+function octet_to_hexascii
+include <sys/types.h>
+include <netinet/in.h>
+include <libinetutil.h>
+declaration int octet_to_hexascii(const void *nump, uint_t nlen, \
+ char *bufp, uint_t *blen)
+version SUNWprivate_1.1
+end
+
+function hexascii_to_octet
+include <sys/types.h>
+include <netinet/in.h>
+include <libinetutil.h>
+declaration int hexascii_to_octet(const char *asp, uint_t alen, \
+ void *bufp, uint_t *blen)
+version SUNWprivate_1.1
+end
+
+function get_netmask4
+include <sys/types.h>
+include <netinet/in.h>
+include <libinetutil.h>
+declaration void get_netmask4(const struct in_addr *np, struct in_addr *sp)
+version SUNWprivate_1.1
+end
+
+function ifparse_ifspec
+include <libinetutil.h>
+declaration boolean_t ifparse_ifspec(const char *ifname, ifspec_t *ifsp)
+version SUNWprivate_1.1
+end
+
+function iu_tq_create
+include <libinetutil.h>
+declaration iu_tq_t *iu_tq_create(void)
+version SUNWprivate_1.1
+end
+
+function iu_tq_destroy
+include <libinetutil.h>
+declaration void iu_tq_destroy(iu_tq_t *tq)
+version SUNWprivate_1.1
+end
+
+function iu_schedule_timer
+include <libinetutil.h>
+declaration iu_timer_id_t iu_schedule_timer(iu_tq_t *tq, uint32_t sec, iu_tq_callback_t *callback, void *arg)
+version SUNWprivate_1.1
+end
+
+function iu_schedule_timer_ms
+include <libinetutil.h>
+declaration iu_timer_id_t iu_schedule_timer_ms(iu_tq_t *tq, uint64_t ms, iu_tq_callback_t *callback, void *arg)
+version SUNWprivate_1.1
+end
+
+function iu_adjust_timer
+include <libinetutil.h>
+declaration int iu_adjust_timer(iu_tq_t *tq, iu_timer_id_t timer_id, uint32_t sec)
+version SUNWprivate_1.1
+end
+
+function iu_cancel_timer
+include <libinetutil.h>
+declaration int iu_cancel_timer(iu_tq_t *tq, iu_timer_id_t timer_id, void **arg)
+version SUNWprivate_1.1
+end
+
+function iu_expire_timers
+include <libinetutil.h>
+declaration int iu_expire_timers(iu_tq_t *tq)
+version SUNWprivate_1.1
+end
+
+function iu_earliest_timer
+include <libinetutil.h>
+declaration int iu_earliest_timer(iu_tq_t *tq)
+version SUNWprivate_1.1
+end
+
+function iu_eh_create
+include <libinetutil.h>
+declaration iu_eh_t *iu_eh_create(void)
+version SUNWprivate_1.1
+end
+
+function iu_eh_destroy
+include <libinetutil.h>
+declaration void iu_eh_destroy(iu_eh_t *eh)
+version SUNWprivate_1.1
+end
+
+function iu_register_event
+include <libinetutil.h>
+declaration iu_event_id_t iu_register_event(iu_eh_t *eh, int fd, short events, iu_eh_callback_t *callback, void *arg)
+version SUNWprivate_1.1
+end
+
+function iu_unregister_event
+include <libinetutil.h>
+declaration int iu_unregister_event(iu_eh_t *eh, iu_event_id_t event_id, void **arg)
+version SUNWprivate_1.1
+end
+
+function iu_handle_events
+include <libinetutil.h>
+declaration int iu_handle_events(iu_eh_t *eh, iu_tq_t *tq)
+version SUNWprivate_1.1
+end
+
+function iu_stop_handling_events
+include <libinetutil.h>
+declaration void iu_stop_handling_events(iu_eh_t *eh, unsigned int reason)
+version SUNWprivate_1.1
+end
+
+function iu_eh_register_signal
+include <libinetutil.h>
+declaration int iu_eh_register_signal(iu_eh_t *eh, int sig, iu_eh_sighandler_t *handler, void *data)
+version SUNWprivate_1.1
+end
+
+function iu_eh_unregister_signal
+include <libinetutil.h>
+declaration int iu_eh_unregister_signal(iu_eh_t *eh, int sig, void **datap)
+version SUNWprivate_1.1
+end
diff --git a/usr/src/lib/libinetutil/spec/sparc/Makefile b/usr/src/lib/libinetutil/spec/sparc/Makefile
new file mode 100644
index 0000000000..e41e118fe4
--- /dev/null
+++ b/usr/src/lib/libinetutil/spec/sparc/Makefile
@@ -0,0 +1,44 @@
+#
+# 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 (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libinetutil/spec/sparc/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#sparc_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libinetutil/spec/sparcv9/Makefile b/usr/src/lib/libinetutil/spec/sparcv9/Makefile
new file mode 100644
index 0000000000..57683cf1ec
--- /dev/null
+++ b/usr/src/lib/libinetutil/spec/sparcv9/Makefile
@@ -0,0 +1,45 @@
+#
+# 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 (c) 2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libinetutil/spec/sparcv9/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#sparcv9_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libinetutil/spec/versions b/usr/src/lib/libinetutil/spec/versions
new file mode 100644
index 0000000000..22e0dd1104
--- /dev/null
+++ b/usr/src/lib/libinetutil/spec/versions
@@ -0,0 +1,39 @@
+#
+# 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;
+}