diff options
Diffstat (limited to 'usr/src/lib/libinetutil')
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; +} |