diff options
author | Murray Stokely <murray@FreeBSD.org> | 2003-01-16 07:29:37 +0000 |
---|---|---|
committer | Murray Stokely <murray@FreeBSD.org> | 2003-01-16 07:29:37 +0000 |
commit | fc7a955609d8bbe1b61b5fc9fba3c823cbbccb33 (patch) | |
tree | ea481c8bf358c65b9cd0ed0bb908b886c4cd7949 | |
parent | 1888ca53cd979688dbf270a71b3ea974a434a7ad (diff) | |
parent | e00b76de5662182104104e14ae84311d5f6baa3a (diff) | |
download | src-fc7a955609d8bbe1b61b5fc9fba3c823cbbccb33.tar.gz src-fc7a955609d8bbe1b61b5fc9fba3c823cbbccb33.zip |
This commit was generated by cvs2svn to compensate for changes in r109365,
which included commits to RCS files with non-trunk default branches.
Notes
Notes:
svn path=/head/; revision=109366
-rw-r--r-- | contrib/isc-dhcp/dhcpctl/Makefile.dist | 106 | ||||
-rw-r--r-- | contrib/isc-dhcp/dhcpctl/callback.c | 179 | ||||
-rw-r--r-- | contrib/isc-dhcp/dhcpctl/cltest.c | 188 | ||||
-rw-r--r-- | contrib/isc-dhcp/dhcpctl/dhcpctl.3 | 470 | ||||
-rw-r--r-- | contrib/isc-dhcp/dhcpctl/dhcpctl.c | 599 | ||||
-rw-r--r-- | contrib/isc-dhcp/dhcpctl/dhcpctl.h | 134 | ||||
-rw-r--r-- | contrib/isc-dhcp/dhcpctl/omshell.1 | 341 | ||||
-rw-r--r-- | contrib/isc-dhcp/dhcpctl/omshell.c | 728 | ||||
-rw-r--r-- | contrib/isc-dhcp/dhcpctl/remote.c | 371 |
9 files changed, 3116 insertions, 0 deletions
diff --git a/contrib/isc-dhcp/dhcpctl/Makefile.dist b/contrib/isc-dhcp/dhcpctl/Makefile.dist new file mode 100644 index 000000000000..093dcbb38b17 --- /dev/null +++ b/contrib/isc-dhcp/dhcpctl/Makefile.dist @@ -0,0 +1,106 @@ +# Makefile.dist +# +# Copyright (c) 1996-2002 Internet Software Consortium. +# Use is subject to license terms which appear in the file named +# ISC-LICENSE that should have accompanied this file when you +# received it. If a file named ISC-LICENSE did not accompany this +# file, or you are not sure the one you have is correct, you may +# obtain an applicable copy of the license at: +# +# http://www.isc.org/isc-license-1.0.html. +# +# This file is part of the ISC DHCP distribution. The documentation +# associated with this file is listed in the file DOCUMENTATION, +# included in the top-level directory of this release. +# +# Support and other services are available for ISC products - see +# http://www.isc.org for more information. +# + +CATMANPAGES = dhcpctl.cat3 omshell.cat1 +SEDMANPAGES = dhcpctl.man3 omshell.man1 +SRC = dhcpctl.c callback.c remote.c +OBJ = dhcpctl.o callback.o remote.o +MAN = dhcpctl.3 omshell.1 +HDRS = dhcpctl.h + +INCLUDES = $(BINDINC) -I$(TOP)/includes +CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) +DHCPCTLLIBS = libdhcpctl.a ../common/libdhcp.a $(BINDLIB) \ + ../omapip/libomapi.a ../dst/libdst.a + +all: libdhcpctl.a omshell cltest $(CATMANPAGES) + +omshell: omshell.o $(DHCPCTLLIBS) + $(CC) $(DEBUG) $(LFLAGS) -o omshell omshell.o $(DHCPCTLLIBS) $(LIBS) + +cltest: cltest.o $(DHCPCTLLIBS) + $(CC) $(DEBUG) $(LFLAGS) -o cltest cltest.o $(DHCPCTLLIBS) $(LIBS) + +libdhcpctl.a: $(OBJ) + rm -f libdhcpctl.a + ar cruv libdhcpctl.a $(OBJ) + $(RANLIB) libdhcpctl.a + +install: all $(CATMANPAGES) + for dir in $(LIBDIR) $(LIBMANDIR) $(INCDIR) $(USRMANDIR) \ + $(USERBINDIR); do \ + foo=""; \ + for bar in `echo $(DESTDIR)$${dir} |tr / ' '`; do \ + foo=$${foo}/$$bar; \ + if [ ! -d $$foo ]; then \ + mkdir $$foo; \ + chmod 755 $$foo; \ + fi; \ + done; \ + done + $(INSTALL) libdhcpctl.a $(DESTDIR)$(LIBDIR) + $(CHMOD) 644 $(DESTDIR)$(LIBDIR)/libdhcpctl.a + $(INSTALL) dhcpctl.h $(DESTDIR)$(INCDIR) + $(CHMOD) 644 $(DESTDIR)$(INCDIR)/dhcpctl.h + for man in $(MAN); do \ + prefix=`echo $$man |sed -e 's/\.[0-9]$$//'`; \ + suffix=`echo $$man |sed -e 's/.*\.\([0-9]\)$$/\1/'`; \ + $(MANINSTALL) $(MANFROM) $${prefix}.$(MANCAT)$${suffix} $(MANTO) \ + $(DESTDIR)$(LIBMANDIR)/$${prefix}$(LIBMANEXT); \ + done + $(INSTALL) omshell $(DESTDIR)$(USERBINDIR) + $(CHMOD) 755 $(DESTDIR)$(USERBINDIR)/omshell + $(MANINSTALL) $(MANFROM) omshell.$(MANCAT)1 $(MANTO) \ + $(DESTDIR)$(USRMANDIR)/omshell$(USRMANEXT) + +depend: + $(MKDEP) $(INCLUDES) $(PREDEFINES) $(SRC) + +clean: + -rm -f $(OBJ) test.o svtest cltest.o cltest + +realclean: clean + -rm -f libdhcpctl.a *~ $(CATMANPAGES) $(SEDMANPAGES) + +distclean: realclean + -rm -f Makefile + +links: + @for foo in $(SRC) $(MAN) omshell.c cltest.c $(HDRS); do \ + if [ ! -b $$foo ]; then \ + rm -f $$foo; \ + fi; \ + ln -s $(TOP)/dhcpctl/$$foo $$foo; \ + done + +dhcpctl.cat3: dhcpctl.man3 + nroff -man dhcpctl.man3 >dhcpctl.cat3 + +dhcpctl.man3: dhcpctl.3 + sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \ + -e "s#RUNDIR#$(VARRUN)#g" < dhcpctl.3 >dhcpctl.man3 + +omshell.cat1: omshell.man1 + nroff -man omshell.man1 >omshell.cat1 + +omshell.man1: omshell.1 + sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \ + -e "s#RUNDIR#$(VARRUN)#g" < omshell.1 >omshell.man1 + +# Dependencies (semi-automatically-generated) diff --git a/contrib/isc-dhcp/dhcpctl/callback.c b/contrib/isc-dhcp/dhcpctl/callback.c new file mode 100644 index 000000000000..af1364c19171 --- /dev/null +++ b/contrib/isc-dhcp/dhcpctl/callback.c @@ -0,0 +1,179 @@ +/* callback.c + + The dhcpctl callback object. */ + +/* + * Copyright (c) 1999-2002 Internet Software Consortium. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The Internet Software Consortium nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This software has been written for the Internet Software Consortium + * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. + * To learn more about the Internet Software Consortium, see + * ``http://www.isc.org/''. To learn more about Vixie Enterprises, + * see ``http://www.vix.com''. To learn more about Nominum, Inc., see + * ``http://www.nominum.com''. + */ + +#include <omapip/omapip_p.h> +#include "dhcpctl.h" + +/* dhcpctl_set_callback + + synchronous, with asynchronous aftereffect + handle is some object upon which some kind of process has been + started - e.g., an open, an update or a refresh. + data is an anonymous pointer containing some information that + the callback will use to figure out what event completed. + return value of 0 means callback was successfully set, a nonzero + status code is returned otherwise. + Upon completion of whatever task is in process, the callback + will be passed the handle to the object, a status code + indicating what happened, and the anonymous pointer passed to */ + +dhcpctl_status dhcpctl_set_callback (dhcpctl_handle h, void *data, + void (*func) (dhcpctl_handle, + dhcpctl_status, void *)) +{ + dhcpctl_callback_object_t *callback; + omapi_object_t *inner; + isc_result_t status; + + callback = dmalloc (sizeof *callback, MDL); + if (!callback) + return ISC_R_NOMEMORY; + + /* Tie the callback object to the innermost object in the chain. */ + for (inner = h; inner -> inner; inner = inner -> inner) + ; + omapi_object_reference (&inner -> inner, + (omapi_object_t *)callback, MDL); + omapi_object_reference ((omapi_object_t **)&callback -> outer, + inner, MDL); + + /* Save the actual handle pointer we were passed for the callback. */ + omapi_object_reference (&callback -> object, h, MDL); + callback -> data = data; + callback -> callback = func; + + return ISC_R_SUCCESS; +} + +/* Callback methods (not meant to be called directly) */ + +isc_result_t dhcpctl_callback_set_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_typed_data_t *value) +{ + if (h -> type != dhcpctl_callback_type) + return ISC_R_INVALIDARG; + + if (h -> inner && h -> inner -> type -> set_value) + return (*(h -> inner -> type -> set_value)) + (h -> inner, id, name, value); + return ISC_R_NOTFOUND; +} + +isc_result_t dhcpctl_callback_get_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_value_t **value) +{ + if (h -> type != dhcpctl_callback_type) + return ISC_R_INVALIDARG; + + if (h -> inner && h -> inner -> type -> get_value) + return (*(h -> inner -> type -> get_value)) + (h -> inner, id, name, value); + return ISC_R_NOTFOUND; +} + +isc_result_t dhcpctl_callback_signal_handler (omapi_object_t *o, + const char *name, va_list ap) +{ + dhcpctl_callback_object_t *p; + isc_result_t waitstatus; + + if (o -> type != dhcpctl_callback_type) + return ISC_R_INVALIDARG; + p = (dhcpctl_callback_object_t *)o; + + /* Not a signal we recognize? */ + if (strcmp (name, "ready")) { + if (p -> inner && p -> inner -> type -> signal_handler) + return (*(p -> inner -> type -> signal_handler)) + (p -> inner, name, ap); + return ISC_R_NOTFOUND; + } + + if (p -> object -> type == dhcpctl_remote_type) { + waitstatus = (((dhcpctl_remote_object_t *) + (p -> object)) -> waitstatus); + } else + waitstatus = ISC_R_SUCCESS; + + /* Do the callback. */ + if (p -> callback) + (*(p -> callback)) (p -> object, waitstatus, p -> data); + + return ISC_R_SUCCESS; +} + +isc_result_t dhcpctl_callback_destroy (omapi_object_t *h, + const char *file, int line) +{ + dhcpctl_callback_object_t *p; + if (h -> type != dhcpctl_callback_type) + return ISC_R_INVALIDARG; + p = (dhcpctl_callback_object_t *)h; + if (p -> handle) + omapi_object_dereference ((omapi_object_t **)&p -> handle, + file, line); + return ISC_R_SUCCESS; +} + +/* Write all the published values associated with the object through the + specified connection. */ + +isc_result_t dhcpctl_callback_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *p) +{ + int i; + + if (p -> type != dhcpctl_callback_type) + return ISC_R_INVALIDARG; + + if (p -> inner && p -> inner -> type -> stuff_values) + return (*(p -> inner -> type -> stuff_values)) (c, id, + p -> inner); + return ISC_R_SUCCESS; +} + diff --git a/contrib/isc-dhcp/dhcpctl/cltest.c b/contrib/isc-dhcp/dhcpctl/cltest.c new file mode 100644 index 000000000000..e38574f1b8a8 --- /dev/null +++ b/contrib/isc-dhcp/dhcpctl/cltest.c @@ -0,0 +1,188 @@ +/* cltest.c + + Example program that uses the dhcpctl library. */ + +/* Copyright (C) 2000-2002 Internet Software Consortium + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The Internet Software Consortium nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This software was contributed to the Internet Software Consortium + * by Brian Murrell. + */ + +#include <time.h> +#include <sys/time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <isc-dhcp/result.h> +#include "dhcpctl.h" + +int main (int, char **); + +enum modes { up, down, undefined }; + +static void usage (char *s) { + fprintf (stderr, + "Usage: %s [-n <username>] [-p <password>] [-a <algorithm>]" + "(-u | -d) <if>\n", s); + exit (1); +} + +int main (argc, argv) + int argc; + char **argv; +{ + isc_result_t status, waitstatus; + dhcpctl_handle authenticator; + dhcpctl_handle connection; + dhcpctl_handle host_handle, group_handle, interface_handle; + dhcpctl_data_string cid; + dhcpctl_data_string result, groupname, identifier; + int i; + int mode = undefined; + const char *interface = 0; + const char *action; + + for (i = 1; i < argc; i++) { + if (!strcmp (argv[i], "-u")) { + mode = up; + } else if (!strcmp (argv [i], "-d")) { + mode = down; + } else if (argv[i][0] == '-') { + usage(argv[0]); + } else { + interface = argv[i]; + } + } + + if (!interface) + usage(argv[0]); + if (mode == undefined) + usage(argv[0]); + + status = dhcpctl_initialize (); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_initialize: %s\n", + isc_result_totext (status)); + exit (1); + } + + authenticator = dhcpctl_null_handle; + connection = dhcpctl_null_handle; + + status = dhcpctl_connect (&connection, "127.0.0.1", 7911, + authenticator); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_connect: %s\n", + isc_result_totext (status)); + exit (1); + } + + interface_handle = dhcpctl_null_handle; + status = dhcpctl_new_object (&interface_handle, + connection, "interface"); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_new_object: %s\n", + isc_result_totext (status)); + exit (1); + } + + status = dhcpctl_set_string_value (interface_handle, + interface, "name"); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_set_value: %s\n", + isc_result_totext (status)); + exit (1); + } + + if (mode == up) { + /* "up" the interface */ + printf ("upping interface %s\n", interface); + action = "create"; + status = dhcpctl_open_object (interface_handle, connection, + DHCPCTL_CREATE | DHCPCTL_EXCL); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_open_object: %s\n", + isc_result_totext (status)); + exit (1); + } + } else { + /* down the interface */ + printf ("downing interface %s\n", interface); + action = "remove"; + status = dhcpctl_open_object (interface_handle, connection, 0); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_open_object: %s\n", + isc_result_totext (status)); + exit (1); + } + status = dhcpctl_wait_for_completion (interface_handle, + &waitstatus); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_wait_for_completion: %s\n", + isc_result_totext (status)); + exit (1); + } + if (waitstatus != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_wait_for_completion: %s\n", + isc_result_totext (waitstatus)); + exit (1); + } + status = dhcpctl_object_remove (connection, interface_handle); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_open_object: %s\n", + isc_result_totext (status)); + exit (1); + } + } + + status = dhcpctl_wait_for_completion (interface_handle, &waitstatus); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_wait_for_completion: %s\n", + isc_result_totext (status)); + exit (1); + } + if (waitstatus != ISC_R_SUCCESS) { + fprintf (stderr, "interface object %s: %s\n", action, + isc_result_totext (waitstatus)); + exit (1); + } + + memset (&result, 0, sizeof result); + status = dhcpctl_get_value (&result, interface_handle, "state"); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_get_value: %s\n", + isc_result_totext (status)); + exit (1); + } + + exit (0); +} diff --git a/contrib/isc-dhcp/dhcpctl/dhcpctl.3 b/contrib/isc-dhcp/dhcpctl/dhcpctl.3 new file mode 100644 index 000000000000..8ab7918f8c34 --- /dev/null +++ b/contrib/isc-dhcp/dhcpctl/dhcpctl.3 @@ -0,0 +1,470 @@ +.\" -*- nroff -*- +.\" +.\" Project: DHCP +.\" File: dhcpctl.3 +.\" RCSId: $Id: dhcpctl.3,v 1.3.2.1 2001/06/26 18:35:35 mellon Exp $ +.\" +.\" Copyright (C) 2000 Nominum, Inc. +.\" +.\" Description: dhcpctl man page. +.\" +.\" +.Dd Nov 15, 2000 +.Dt DHCPCTL 3 +.Os DHCP 3 +.ds vT DHCP Programmer's Manual +.\" +.\" +.\" +.Sh NAME +.Nm dhcpctl_initialize +.Nd dhcpctl library initialization. +.\" +.\" +.\" +.Sh SYNOPSIS +.Fd #include <dhcpctl/dhcpctl.h> +.Fd +.Ft dhcpctl_status +.Fo dhcpctl_initialize +.Fa void +.Fc +.\" +.Ft dhcpctl_status +.Fo dhcpctl_connect +.Fa "dhcpctl_handle *cxn" +.Fa "const char *host" +.Fa "int port" +.Fa "dhcpctl_handle auth" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_wait_for_completion +.Fa "dhcpctl_handle object" +.Fa "dhcpctl_status *status" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_get_value +.Fa "dhcpctl_data_string *value" +.Fa "dhcpctl_handle object" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_get_boolean +.Fa "int *value" +.Fa "dhcpctl_handle object" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_set_value +.Fa "dhcpctl_handle object" +.Fa "dhcpctl_data_string value" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_set_string_value +.Fa "dhcpctl_handle object" +.Fa "const char *value" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_set_boolean_value +.Fa "dhcpctl_handle object" +.Fa "int value" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_set_int_value +.Fa "dhcpctl_handle object" +.Fa "int value" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_object_update +.Fa "dhcpctl_handle connection" +.Fa "dhcpctl_handle object" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_object_refresh +.Fa "dhcpctl_handle connection" +.Fa "dhcpctl_handle object" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_object_remove +.Fa "dhcpctl_handle connection" +.Fa "dhcpctl_handle object" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_set_callback +.Fa "dhcpctl_handle object" +.Fa "void *data" +.Fa "void (*function) (dhcpctl_handle, dhcpctl_status, void *)" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_new_authenticator +.Fa "dhcpctl_handle *object" +.Fa "const char *name" +.Fa "const char *algorithm" +.Fa "const char *secret" +.Fa "unsigned secret_len" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_new_object +.Fa "dhcpctl_handle *object" +.Fa "dhcpctl_handle connection" +.Fa "const char *object_type" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_open_object +.Fa "dhcpctl_handle object" +.Fa "dhcpctl_handle connection" +.Fa "int flags" +.Fc +.\" +.\" +.\" +.Ft isc_result_t +.Fo omapi_data_string_new +.Fa dhcpctl_data_string *data +.Fa unsigned int length +.Fa const char *filename, +.Fa int lineno +.Fc +.\" +.\" +.\" +.Ft isc_result_t +.Fo dhcpctl_data_string_dereference +.Fa "dhcpctl_data_string *" +.Fa "const char *" +.Fa "int" +.Fc +.Sh DESCRIPTION +The dhcpctl set of functions provide an API that can be used to communicate +with and manipulate a running ISC DHCP server. All functions return a value of +.Dv isc_result_t . +The return values reflects the result of operations to local data +structures. If an operation fails on the server for any reason, then the error +result will be returned through the +second parameter of the +.Fn dhcpctl_wait_for_completion +call. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_initialize +sets up the data structures the library needs to do its work. This function +must be called once before any other. +.Pp +.Fn dhcpctl_connect +opens a connection to the DHCP server at the given host and port. If an +authenticator has been created for the connection, then it is given as the 4th +argument. On a successful return the address pointed at by the first +argument will have a new connection object assigned to it. +.Pp +For example: +.Bd -literal -offset indent +s = dhcpctl_connect(&cxn, "127.0.0.1", 7911, NULL); +.Ed +.Pp +connects to the DHCP server on the localhost via port 7911 (the standard +OMAPI port). No authentication is used for the connection. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_wait_for_completion +flushes a pending message to the server and waits for the response. The result +of the request as processed on the server is returned via the second +parameter. +.Bd -literal -offset indent +s = dhcpctl_wait_for_completion(cxn, &wv); +if (s != ISC_R_SUCCESS) + local_failure(s); +else if (wv != ISC_R_SUCCESS) + server_failure(wc); +.Ed +.Pp +The call to +.Fn dhcpctl_wait_for_completion +won't return until the remote message processing completes or the connection +to the server is lost. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_get_value +extracts a value of an attribute from the handle. The value can be of any +length and is treated as a sequence of bytes. The handle must have been +created first with +.Fn dhcpctl_new_object +and opened with +.Fn dhcpctl_open_object . +The value is returned via the parameter named +.Dq value . +The last parameter is the name of attribute to retrieve. +.Bd -literal -offset indent +dhcpctl_data_string value = NULL; +dhcpctl_handle lease; +time_t thetime; + +s = dhcpctl_get_value (&value, lease, "ends"); +assert(s == ISC_R_SUCCESS && value->len == sizeof(thetime)); +memcpy(&thetime, value->value, value->len); +.Ed +.\" +.\" +.\" +.Pp +.Fn dhcpctl_get_boolean +extracts a boolean valued attribute from the object handle. +.\" +.\" +.\" +.Pp +The +.Fn dhcpctl_set_value , +.Fn dhcpctl_set_string_value , +.Fn dhcpctl_set_boolean_value , +and +.Fn dhcpctl_set_int_value +functions all set a value on the object handle. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_object_update +function queues a request for +all the changes made to the object handle be be sent to the remote +for processing. The changes made to the atributes on the handle will be +applied to remote object if permitted. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_object_refresh +queues up a request for a fresh copy of all the attribute values to be sent +from the remote to +refresh the values in the local object handle. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_object_remove +queues a request for the removal on the server of the object referenced by the +handle. +.\" +.\" +.\" +.Pp +The +.Fn dhcpctl_set_callback +function sets up a user-defined function to be called when an event completes +on the given object handle. This is needed for asynchronous handling of +events, versus the synchronous handling given by +.Fn dhcpctl_wait_for_completion . +When the function is called the first parameter is the object the event +arrived for, the second is the status of the message that was processed, the +third is the same value as the second parameter given to +.Fn dhcpctl_set_callback . +.\" +.\" +.\" +.Pp +The +.Fn dhcpctl_new_authenticator +creates a new authenticator object to be used for signing the messages +that cross over the network. The +.Dq name , +.Dq algorithm , +and +.Dq secret +values must all match what the server uses and are defined in its +configuration file. The created object is returned through the first parameter +and must be used as the 4th parameter to +.Fn dhcpctl_connect . +.\" +.\" +.\" +.Pp +.Fn dhcpctl_new_object +creates a local handle for an object on the the server. The +.Dq object_type +parameter is the ascii name of the type of object being accessed. e.g. +.Qq lease . +This function only sets up local data structures, it does not queue any +messages +to be sent to the remote side, +.Fn dhcpctl_open_object +does that. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_open_object +builds and queues the request to the remote side. This function is used with +handle created via +.Fn dhcpctl_new_object . +The flags argument is a bit mask with the following values available for +setting: +.Bl -tag -offset indent -width 20 +.It DHCPCTL_CREATE +if the object does not exist then the remote will create it +.It DHCPCTL_UPDATE +update the object on the remote side using the +attributes already set in the handle. +.It DHCPCTL_EXCL +return and error if the object exists and DHCPCTL_CREATE +was also specified +.El +.\" +.\" +.\" +.Pp +The +.Fn omapi_data_string_new +function allocates a new +.Ft dhcpctl_data_string +object. The data string will be large enough to hold +.Dq length +bytes of data. The +.Dq file +and +.Dq lineno +arguments are the source file location the call is made from, typically by +using the +.Dv __FILE__ +and +.Dv __LINE__ +macros or the +.Dv MDL +macro defined in +. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_data_string_dereference +deallocates a data string created by +.Fn omapi_data_string_new . +The memory for the object won't be freed until the last reference is +released. +.Sh EXAMPLES +.Pp +The following program will connect to the DHCP server running on the local +host and will get the details of the existing lease for IP address +10.0.0.101. It will then print out the time the lease is due to expire. Note +that most error checking has been ommitted for brevity. +.Bd -literal -offset indent +#include <stdarg.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <stdio.h> +#include <netinet/in.h> + +#include <isc/result.h> +#include <dhcpctl/dhcpctl.h> + +int main (int argc, char **argv) { + dhcpctl_data_string ipaddrstring = NULL; + dhcpctl_data_string value = NULL; + dhcpctl_handle connection = NULL; + dhcpctl_handle lease = NULL; + isc_result_t waitstatus; + struct in_addr convaddr; + time_t thetime; + + dhcpctl_initialize (); + + dhcpctl_connect (&connection, "127.0.0.1", + 7911, 0); + + dhcpctl_new_object (&lease, connection, + "lease"); + + memset (&ipaddrstring, 0, sizeof + ipaddrstring); + + inet_pton(AF_INET, "10.0.0.101", + &convaddr); + + omapi_data_string_new (&ipaddrstring, + 4, MDL); + memcpy(ipaddrstring->value, &convaddr.s_addr, 4); + + dhcpctl_set_value (lease, ipaddrstring, + "ip-address"); + + dhcpctl_open_object (lease, connection, 0); + + dhcpctl_wait_for_completion (lease, + &waitstatus); + if (waitstatus != ISC_R_SUCCESS) { + /* server not authoritative */ + exit (0); + } + + dhcpctl_data_string_dereference(&ipaddrstring, + MDL); + + dhcpctl_get_value (&value, lease, "ends"); + + memcpy(&thetime, value->value, value->len); + + dhcpctl_data_string_dereference(&value, MDL); + + fprintf (stdout, "ending time is %s", + ctime(&thetime)); +} +.Ed +.Sh SEE ALSO +.SH SEE ALSO +omapi(3), omshell(3), dhcpd(8), dhclient(8), dhcpd.conf(5), dhclient.conf(5). +.SH AUTHOR +.B dhcpctl +was written by Ted Lemon of Nominum, Inc. Information about Nominum +and support contracts for DHCP and BIND can be found at +.B http://www.nominum.com. This preliminary documentation was +written by James Brister of Nominum, Inc. diff --git a/contrib/isc-dhcp/dhcpctl/dhcpctl.c b/contrib/isc-dhcp/dhcpctl/dhcpctl.c new file mode 100644 index 000000000000..2cb43034b043 --- /dev/null +++ b/contrib/isc-dhcp/dhcpctl/dhcpctl.c @@ -0,0 +1,599 @@ +/* dhcpctl.c + + Subroutines providing general support for objects. */ + +/* + * Copyright (c) 1999-2002 Internet Software Consortium. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The Internet Software Consortium nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This software has been written for the Internet Software Consortium + * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. + * To learn more about the Internet Software Consortium, see + * ``http://www.isc.org/''. To learn more about Vixie Enterprises, + * see ``http://www.vix.com''. To learn more about Nominum, Inc., see + * ``http://www.nominum.com''. + */ + +#include <omapip/omapip_p.h> +#include "dhcpctl.h" + +omapi_object_type_t *dhcpctl_callback_type; +omapi_object_type_t *dhcpctl_remote_type; + +/* dhcpctl_initialize () + + Must be called before any other dhcpctl function. */ + +dhcpctl_status dhcpctl_initialize () +{ + isc_result_t status; + + status = omapi_init(); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_object_type_register (&dhcpctl_callback_type, + "dhcpctl-callback", + dhcpctl_callback_set_value, + dhcpctl_callback_get_value, + dhcpctl_callback_destroy, + dhcpctl_callback_signal_handler, + dhcpctl_callback_stuff_values, + 0, 0, 0, 0, 0, 0, + sizeof + (dhcpctl_callback_object_t), 0, + RC_MISC); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_object_type_register (&dhcpctl_remote_type, + "dhcpctl-remote", + dhcpctl_remote_set_value, + dhcpctl_remote_get_value, + dhcpctl_remote_destroy, + dhcpctl_remote_signal_handler, + dhcpctl_remote_stuff_values, + 0, 0, 0, 0, 0, 0, + sizeof (dhcpctl_remote_object_t), + 0, RC_MISC); + if (status != ISC_R_SUCCESS) + return status; + + return ISC_R_SUCCESS; +} + +/* dhcpctl_connect + + synchronous + returns nonzero status code if it didn't connect, zero otherwise + stores connection handle through connection, which can be used + for subsequent access to the specified server. + server_name is the name of the server, and port is the TCP + port on which it is listening. + authinfo is the handle to an object containing authentication + information. */ + +dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection, + const char *server_name, int port, + dhcpctl_handle authinfo) +{ + isc_result_t status; + dhcpctl_status waitstatus; + + status = omapi_generic_new (connection, MDL); + if (status != ISC_R_SUCCESS) { + return status; + } + + status = omapi_protocol_connect (*connection, server_name, + (unsigned)port, authinfo); + if (status == ISC_R_SUCCESS) + return status; + if (status != ISC_R_INCOMPLETE) { + omapi_object_dereference (connection, MDL); + return status; + } + + status = omapi_wait_for_completion (*connection, 0); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (connection, MDL); + return status; + } + + return status; +} + +/* dhcpctl_wait_for_completion + + synchronous + returns zero if the callback completes, a nonzero status if + there was some problem relating to the wait operation. The + status of the queued request will be stored through s, and + will also be either zero for success or nonzero for some kind + of failure. Never returns until completion or until the + connection to the server is lost. This performs the same + function as dhcpctl_set_callback and the subsequent callback, + for programs that want to do inline execution instead of using + callbacks. */ + +dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h, + dhcpctl_status *s) +{ + isc_result_t status; + status = omapi_wait_for_completion (h, 0); + if (status != ISC_R_SUCCESS) + return status; + if (h -> type == dhcpctl_remote_type) + *s = ((dhcpctl_remote_object_t *)h) -> waitstatus; + return ISC_R_SUCCESS; +} + +/* dhcpctl_get_value + + synchronous + returns zero if the call succeeded, a nonzero status code if + it didn't. + result is the address of an empty data string (initialized + with bzero or cleared with data_string_forget). On + successful completion, the addressed data string will contain + the value that was fetched. + dhcpctl_handle refers to some dhcpctl item + value_name refers to some value related to that item - e.g., + for a handle associated with a completed host lookup, value + could be one of "hardware-address", "dhcp-client-identifier", + "known" or "client-hostname". */ + +dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *result, + dhcpctl_handle h, const char *value_name) +{ + isc_result_t status; + omapi_value_t *tv = (omapi_value_t *)0; + omapi_data_string_t *value = (omapi_data_string_t *)0; + unsigned len; + int ip; + + status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv); + if (status != ISC_R_SUCCESS) + return status; + + switch (tv -> value -> type) { + case omapi_datatype_int: + len = sizeof (int); + break; + + case omapi_datatype_string: + case omapi_datatype_data: + len = tv -> value -> u.buffer.len; + break; + + case omapi_datatype_object: + len = sizeof (omapi_handle_t); + break; + + default: + omapi_typed_data_dereference (&tv -> value, MDL); + return ISC_R_UNEXPECTED; + } + + status = omapi_data_string_new (result, len, MDL); + if (status != ISC_R_SUCCESS) { + omapi_typed_data_dereference (&tv -> value, MDL); + return status; + } + + switch (tv -> value -> type) { + case omapi_datatype_int: + ip = htonl (tv -> value -> u.integer); + memcpy ((*result) -> value, &ip, sizeof ip); + break; + + case omapi_datatype_string: + case omapi_datatype_data: + memcpy ((*result) -> value, + tv -> value -> u.buffer.value, + tv -> value -> u.buffer.len); + break; + + case omapi_datatype_object: + ip = htonl (tv -> value -> u.object -> handle); + memcpy ((*result) -> value, &ip, sizeof ip); + break; + } + + omapi_value_dereference (&tv, MDL); + return ISC_R_SUCCESS; +} + +/* dhcpctl_get_boolean + + like dhcpctl_get_value, but more convenient for boolean + values, since no data_string needs to be dealt with. */ + +dhcpctl_status dhcpctl_get_boolean (int *result, + dhcpctl_handle h, const char *value_name) +{ + isc_result_t status; + dhcpctl_data_string data = (dhcpctl_data_string)0; + int rv; + + status = dhcpctl_get_value (&data, h, value_name); + if (status != ISC_R_SUCCESS) + return status; + if (data -> len != sizeof rv) { + omapi_data_string_dereference (&data, MDL); + return ISC_R_UNEXPECTED; + } + memcpy (&rv, data -> value, sizeof rv); + *result = ntohl (rv); + return ISC_R_SUCCESS; +} + +/* dhcpctl_set_value + + Sets a value on an object referred to by a dhcpctl_handle. + The opposite of dhcpctl_get_value. Does not update the + server - just sets the value on the handle. */ + +dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, dhcpctl_data_string value, + const char *value_name) +{ + isc_result_t status; + omapi_typed_data_t *tv = (omapi_typed_data_t *)0; + omapi_data_string_t *name = (omapi_data_string_t *)0; + int len; + + status = omapi_data_string_new (&name, strlen (value_name), MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, strlen (value_name)); + + status = omapi_typed_data_new (MDL, &tv, omapi_datatype_data, + value -> len); + if (status != ISC_R_SUCCESS) { + omapi_data_string_dereference (&name, MDL); + return status; + } + memcpy (tv -> u.buffer.value, value -> value, value -> len); + + status = omapi_set_value (h, (omapi_object_t *)0, name, tv); + omapi_data_string_dereference (&name, MDL); + omapi_typed_data_dereference (&tv, MDL); + return status; +} + +/* dhcpctl_set_string_value + + Sets a NUL-terminated ASCII value on an object referred to by + a dhcpctl_handle. like dhcpctl_set_value, but saves the + trouble of creating a data_string for a NUL-terminated string. + Does not update the server - just sets the value on the handle. */ + +dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, const char *value, + const char *value_name) +{ + isc_result_t status; + omapi_typed_data_t *tv = (omapi_typed_data_t *)0; + omapi_data_string_t *name = (omapi_data_string_t *)0; + int len; + + status = omapi_data_string_new (&name, strlen (value_name), MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, strlen (value_name)); + + status = omapi_typed_data_new (MDL, &tv, omapi_datatype_string, value); + if (status != ISC_R_SUCCESS) { + omapi_data_string_dereference (&name, MDL); + return status; + } + + status = omapi_set_value (h, (omapi_object_t *)0, name, tv); + omapi_data_string_dereference (&name, MDL); + omapi_typed_data_dereference (&tv, MDL); + return status; +} + +/* dhcpctl_set_buffer_value + + Sets a value on an object referred to by a dhcpctl_handle. like + dhcpctl_set_value, but saves the trouble of creating a data_string + for string for which we have a buffer and length. Does not update + the server - just sets the value on the handle. */ + +dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h, + const char *value, unsigned len, + const char *value_name) +{ + isc_result_t status; + omapi_typed_data_t *tv = (omapi_typed_data_t *)0; + omapi_data_string_t *name = (omapi_data_string_t *)0; + unsigned ll; + + ll = strlen (value_name); + status = omapi_data_string_new (&name, ll, MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, ll); + + status = omapi_typed_data_new (MDL, &tv, + omapi_datatype_data, len, value); + if (status != ISC_R_SUCCESS) { + omapi_data_string_dereference (&name, MDL); + return status; + } + memcpy (tv -> u.buffer.value, value, len); + + status = omapi_set_value (h, (omapi_object_t *)0, name, tv); + omapi_data_string_dereference (&name, MDL); + omapi_typed_data_dereference (&tv, MDL); + return status; +} + +/* dhcpctl_set_null_value + + Sets a null value on an object referred to by a dhcpctl_handle. */ + +dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle h, + const char *value_name) +{ + isc_result_t status; + omapi_data_string_t *name = (omapi_data_string_t *)0; + unsigned ll; + + ll = strlen (value_name); + status = omapi_data_string_new (&name, ll, MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, ll); + + status = omapi_set_value (h, (omapi_object_t *)0, name, + (omapi_typed_data_t *)0); + omapi_data_string_dereference (&name, MDL); + return status; +} + +/* dhcpctl_set_boolean_value + + Sets a boolean value on an object - like dhcpctl_set_value, + only more convenient for booleans. */ + +dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle h, int value, + const char *value_name) +{ + isc_result_t status; + omapi_typed_data_t *tv = (omapi_typed_data_t *)0; + omapi_data_string_t *name = (omapi_data_string_t *)0; + int len; + + status = omapi_data_string_new (&name, strlen (value_name), MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, strlen (value_name)); + + status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value); + if (status != ISC_R_SUCCESS) { + omapi_data_string_dereference (&name, MDL); + return status; + } + + status = omapi_set_value (h, (omapi_object_t *)0, name, tv); + omapi_data_string_dereference (&name, MDL); + omapi_typed_data_dereference (&tv, MDL); + return status; +} + +/* dhcpctl_set_int_value + + Sets a boolean value on an object - like dhcpctl_set_value, + only more convenient for booleans. */ + +dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle h, int value, + const char *value_name) +{ + isc_result_t status; + omapi_typed_data_t *tv = (omapi_typed_data_t *)0; + omapi_data_string_t *name = (omapi_data_string_t *)0; + int len; + + status = omapi_data_string_new (&name, strlen (value_name), MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, strlen (value_name)); + + status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value); + if (status != ISC_R_SUCCESS) { + omapi_data_string_dereference (&name, MDL); + return status; + } + + status = omapi_set_value (h, (omapi_object_t *)0, name, tv); + omapi_data_string_dereference (&name, MDL); + omapi_typed_data_dereference (&tv, MDL); + return status; +} + +/* dhcpctl_object_update + + Queues an update on the object referenced by the handle (there + can't be any other work in progress on the handle). An + update means local parameters will be sent to the server. */ + +dhcpctl_status dhcpctl_object_update (dhcpctl_handle connection, + dhcpctl_handle h) +{ + isc_result_t status; + omapi_object_t *message = (omapi_object_t *)0; + dhcpctl_remote_object_t *ro; + + if (h -> type != dhcpctl_remote_type) + return ISC_R_INVALIDARG; + ro = (dhcpctl_remote_object_t *)h; + + status = omapi_message_new (&message, MDL); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + status = omapi_set_int_value (message, (omapi_object_t *)0, + "op", OMAPI_OP_UPDATE); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + status = omapi_set_object_value (message, (omapi_object_t *)0, + "object", h); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + status = omapi_set_int_value (message, (omapi_object_t *)0, "handle", + (int)(ro -> remote_handle)); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + omapi_message_register (message); + status = omapi_protocol_send_message (connection -> outer, + (omapi_object_t *)0, + message, (omapi_object_t *)0); + omapi_object_dereference (&message, MDL); + return status; +} + +/* Requests a refresh on the object referenced by the handle (there + can't be any other work in progress on the handle). A + refresh means local parameters are updated from the server. */ + +dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle connection, + dhcpctl_handle h) +{ + isc_result_t status; + omapi_object_t *message = (omapi_object_t *)0; + dhcpctl_remote_object_t *ro; + + if (h -> type != dhcpctl_remote_type) + return ISC_R_INVALIDARG; + ro = (dhcpctl_remote_object_t *)h; + + status = omapi_message_new (&message, MDL); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + status = omapi_set_int_value (message, (omapi_object_t *)0, + "op", OMAPI_OP_REFRESH); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + status = omapi_set_int_value (message, (omapi_object_t *)0, + "handle", (int)(ro -> remote_handle)); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + omapi_message_register (message); + status = omapi_protocol_send_message (connection -> outer, + (omapi_object_t *)0, + message, (omapi_object_t *)0); + + /* We don't want to send the contents of the object down the + wire, but we do need to reference it so that we know what + to do with the update. */ + status = omapi_set_object_value (message, (omapi_object_t *)0, + "object", h); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + omapi_object_dereference (&message, MDL); + return status; +} + +/* Requests the removal of the object referenced by the handle (there + can't be any other work in progress on the handle). A + removal means that all searchable references to the object on the + server are deleted. */ + +dhcpctl_status dhcpctl_object_remove (dhcpctl_handle connection, + dhcpctl_handle h) +{ + isc_result_t status; + omapi_object_t *message = (omapi_object_t *)0; + dhcpctl_remote_object_t *ro; + + if (h -> type != dhcpctl_remote_type) + return ISC_R_INVALIDARG; + ro = (dhcpctl_remote_object_t *)h; + + status = omapi_message_new (&message, MDL); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + status = omapi_set_int_value (message, (omapi_object_t *)0, + "op", OMAPI_OP_DELETE); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + status = omapi_set_int_value (message, (omapi_object_t *)0, "handle", + (int)(ro -> remote_handle)); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + status = omapi_set_object_value (message, (omapi_object_t *)0, + "notify-object", h); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + omapi_message_register (message); + status = omapi_protocol_send_message (connection -> outer, + (omapi_object_t *)0, + message, (omapi_object_t *)0); + omapi_object_dereference (&message, MDL); + return status; +} + +isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *vp, + const char *file, int line) +{ + return omapi_data_string_dereference (vp, file, line); +} diff --git a/contrib/isc-dhcp/dhcpctl/dhcpctl.h b/contrib/isc-dhcp/dhcpctl/dhcpctl.h new file mode 100644 index 000000000000..0956f6542b3d --- /dev/null +++ b/contrib/isc-dhcp/dhcpctl/dhcpctl.h @@ -0,0 +1,134 @@ +/* dhcpctl.h + + Subroutines providing general support for objects. */ + +/* + * Copyright (c) 1999-2002 Internet Software Consortium. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The Internet Software Consortium nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This software has been written for the Internet Software Consortium + * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. + * To learn more about the Internet Software Consortium, see + * ``http://www.isc.org/''. To learn more about Vixie Enterprises, + * see ``http://www.vix.com''. To learn more about Nominum, Inc., see + * ``http://www.nominum.com''. + */ + +#ifndef _DHCPCTL_H_ +#define _DHCPCTL_H_ + +#include <omapip/omapip.h> + +typedef isc_result_t dhcpctl_status; +typedef omapi_object_t *dhcpctl_handle; +typedef omapi_data_string_t *dhcpctl_data_string; + +#define dhcpctl_null_handle ((dhcpctl_handle) 0) + +#define DHCPCTL_CREATE OMAPI_CREATE +#define DHCPCTL_UPDATE OMAPI_UPDATE +#define DHCPCTL_EXCL OMAPI_EXCL + +typedef struct { + OMAPI_OBJECT_PREAMBLE; + omapi_object_t *object; + void *data; + void (*callback) (dhcpctl_handle, dhcpctl_status, void *); +} dhcpctl_callback_object_t; + +typedef struct { + OMAPI_OBJECT_PREAMBLE; + omapi_typed_data_t *rtype; + isc_result_t waitstatus; + omapi_typed_data_t *message; + omapi_handle_t remote_handle; +} dhcpctl_remote_object_t; + +extern omapi_object_type_t *dhcpctl_callback_type; +extern omapi_object_type_t *dhcpctl_remote_type; + +dhcpctl_status dhcpctl_initialize (void); +dhcpctl_status dhcpctl_connect (dhcpctl_handle *, + const char *, int, dhcpctl_handle); +dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle, dhcpctl_status *); +dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *, + dhcpctl_handle, const char *); +dhcpctl_status dhcpctl_get_boolean (int *, dhcpctl_handle, const char *); +dhcpctl_status dhcpctl_set_value (dhcpctl_handle, + dhcpctl_data_string, const char *); +dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle, const char *, + const char *); +dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle, + const char *, unsigned, const char *); +dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle, const char *); +dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle, int, const char *); +dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle, int, const char *); +dhcpctl_status dhcpctl_object_update (dhcpctl_handle, dhcpctl_handle); +dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle, dhcpctl_handle); +dhcpctl_status dhcpctl_object_remove (dhcpctl_handle, dhcpctl_handle); + +dhcpctl_status dhcpctl_set_callback (dhcpctl_handle, void *, + void (*) (dhcpctl_handle, + dhcpctl_status, void *)); +isc_result_t dhcpctl_callback_set_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_typed_data_t *); +isc_result_t dhcpctl_callback_get_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_value_t **); +isc_result_t dhcpctl_callback_destroy (omapi_object_t *, const char *, int); +isc_result_t dhcpctl_callback_signal_handler (omapi_object_t *, + const char *, va_list); +isc_result_t dhcpctl_callback_stuff_values (omapi_object_t *, + omapi_object_t *, + omapi_object_t *); + +dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *, + const char *, const char *, + const unsigned char *, unsigned); + +dhcpctl_status dhcpctl_open_object (dhcpctl_handle, dhcpctl_handle, int); +dhcpctl_status dhcpctl_new_object (dhcpctl_handle *, + dhcpctl_handle, const char *); +isc_result_t dhcpctl_remote_set_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_typed_data_t *); +isc_result_t dhcpctl_remote_get_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_value_t **); +isc_result_t dhcpctl_remote_destroy (omapi_object_t *, const char *, int); +isc_result_t dhcpctl_remote_signal_handler (omapi_object_t *, + const char *, va_list); +isc_result_t dhcpctl_remote_stuff_values (omapi_object_t *, + omapi_object_t *, + omapi_object_t *); +isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *, + const char *, int); +#endif /* _DHCPCTL_H_ */ diff --git a/contrib/isc-dhcp/dhcpctl/omshell.1 b/contrib/isc-dhcp/dhcpctl/omshell.1 new file mode 100644 index 000000000000..6ac23f3c5e61 --- /dev/null +++ b/contrib/isc-dhcp/dhcpctl/omshell.1 @@ -0,0 +1,341 @@ +.\" omshell.1 +.\" +.\" Copyright (c) 2001-2002 Internet Software Consortium. +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of The Internet Software Consortium nor the names +.\" of its contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +.\" DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR +.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" This software has been written for the Internet Software Consortium +.\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. +.\" To learn more about the Internet Software Consortium, see +.\" ``http://www.isc.org/''. To learn more about Vixie Enterprises, +.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see +.\" ``http://www.nominum.com''. +.TH omshell 1 +.SH NAME +omshell - OMAPI Command Shell +.SH SYNOPSIS +.B omshell +.SH DESCRIPTION +The OMAPI Command Shell, omshell, provides an interactive way to connect to, +query, and possibly change, the ISC DHCP Server's state via OMAPI, the Object +Management API. By using OMAPI and omshell, you do not have to stop, make +changes, and then restart the DHCP server, but can make the changes +while the server is running. Omshell provides a way of accessing +OMAPI. +.PP +OMAPI is simply a communications mechanism that allows you to +manipulate objects. In order to actually \fIuse\fR omshell, you +.I must +understand what objects are available and how to use them. +Documentation for OMAPI objects can be found in the documentation for +the server that provides them - for example, in the \fBdhcpd(1)\fR +manual page and the \fBdhclient(1)\fR manual page. +.SH CONTRIBUTIONS +.PP +This software is free software. At various times its development has +been underwritten by various organizations, including the ISC and +Vixie Enterprises. The development of 3.0 has been funded almost +entirely by Nominum, Inc. +.PP +At this point development is being shepherded by Ted Lemon, and hosted +by the ISC, but the future of this project depends on you. If you +have features you want, please consider implementing them. +.SH LOCAL AND REMOTE OBJECTS +.PP +Throughout this document, there are references to local and remote objects. +Local objects are ones created in omshell with the \fBnew\fR command. Remote +objects are ones on the server: leases, hosts, and groups that the DHCP +server knows about. Local and remote objects are associated together to +enable viewing and modification of object attributes. Also, new remote +objects can be created to match local objects. +.SH OPENING A CONNECTION +.PP +omshell is started from the command line. Once omshell is started, there are +several commands that can be issued: +.PP +.B server \fIaddress\fR +.RS 0.5i +where address is the IP address of the DHCP server to connect to. If this is +not specified, the default server is 127.0.0.1 (localhost). +.RE +.PP +.B port \fInumber\fR +.RS 0.5i +where number is the port that OMAPI listens on. By default, this is 7911. +.RE +.PP +.B key \fIname secret\fR +.RS 0.5i +This specifies the TSIG key to use to authenticate the OMAPI transactions. +\fIname\fR is the name of a key defined in \fIdhcpd.conf\fR with the +\fBomapi-key\fR statement. The \fIsecret\fR is the secret generated from +\fBdnssec-keygen\fR or another key generation program. +.RE +.PP +.B connect +.RS 0.5i +This starts the OMAPI connection to the server as specified by the \fIserver\fR +statement. +.SH CREATING LOCAL OBJECTS +.PP +Any object defined in OMAPI can be created, queried, and/or modified. The +object types available to OMAPI are defined in \fBdhcpd(8)\fR and +\fBdhclient\fR. When using omshell, objects are first defined locally, +manipulated as desired, and then associated with an object on the server. +Only one object can be manipulated at a time. To create a local object, use +.PP +.B new \fIobject-type\fR +.RS 0.5i +\fIobject-type\fR is one of group, host, or lease. +.RE +.PP +At this point, you now have an object that you can set properties on. For +example, if a new lease object was created with \fInew lease\fR, any of a +lease's attributes can be set as follows: +.PP +.B set \fIattribute-name = value\fR +.RS 0.5i +\fBAttribute names are defined in \fBdhcpd(8)\fR and \fBdhclient(8)\fR. +Values should be quoted if they are strings. So, to set a lease's IP address, +you would do the following: +\fB set ip-address = 192.168.4.50\fR +.SH ASSOCIATING LOCAL AND REMOTE OBJECTS +.PP +At this point, you can query the server for information about this lease, by +.PP +.B open +.PP +Now, the local lease object you created and set the IP address for is associated +with the corresponding lease object on the DHCP server. All of the lease +attributes from the DHCP server are now also the attributes on the local +object, and will be shown in omshell. +.SH VIEWING A REMOTE OBJECT +.PP +To query a lease of address 192.168.4.50, and find out its attributes, after +connecting to the server, take the following steps: +.PP +.B new "lease" +.PP +This creates a new local lease object. +.PP +.B set ip-address = 192.168.4.50 +.PP +This sets the \fIlocal\fR object's IP address to be 192.168.4.50 +.PP +.B open +.PP +Now, if a lease with that IP address exists, you will see all the information +the DHCP server has about that particular lease. Any data that isn't readily +printable text will show up in colon-separated hexadecimal values. In this +example, output back from the server for the entire transaction might look +like this: +.nf +.sp 1 +> new "lease" +obj: lease +> set ip-address = 192.168.4.50 +obj: lease +ip-address = c0:a8:04:32 +> open +obj: lease +ip-address = c0:a8:04:32 +state = 00:00:00:02 +dhcp-client-identifier = 01:00:10:a4:b2:36:2c +client-hostname = "wendelina" +subnet = 00:00:00:06 +pool = 00:00:00:07 +hardware-address = 00:10:a4:b2:36:2c +hardware-type = 00:00:00:01 +ends = dc:d9:0d:3b +starts = 5c:9f:04:3b +tstp = 00:00:00:00 +tsfp = 00:00:00:00 +cltt = 00:00:00:00 +.fi +.PP +As you can see here, the IP address is represented in hexadecimal, as are the +starting and ending times of the lease. +.SH MODIFYING A REMOTE OBJECT +.PP +Attributes of remote objects are updated by using the \fBset\fR command as +before, and then issuing an \fBupdate\fR command. The \fBset\fR command sets +the attributes on the current local object, and the \fBupdate\fR command +pushes those changes out to the server. +.PP +Continuing with the previous example, if a \fBset client-hostname = +"something-else"\fR was issued, followed by an \fBupdate\fR command, the +output would look about like this: +.nf +.sp 1 +> set client-hostname = "something-else" +obj: lease +ip-address = c0:a8:04:32 +state = 00:00:00:02 +dhcp-client-identifier = 01:00:10:a4:b2:36:2c +client-hostname = "something-else" +subnet = 00:00:00:06 +pool = 00:00:00:07 +hardware-address = 00:10:a4:b2:36:2c +hardware-type = 00:00:00:01 +ends = dc:d9:0d:3b +starts = 5c:9f:04:3b +tstp = 00:00:00:00 +tsfp = 00:00:00:00 +cltt = 00:00:00:00 +> update +obj: lease +ip-address = c0:a8:04:32 +state = 00:00:00:02 +dhcp-client-identifier = 01:00:10:a4:b2:36:2c +client-hostname = "something-else" +subnet = 00:00:00:06 +pool = 00:00:00:07 +hardware-address = 00:10:a4:b2:36:2c +hardware-type = 00:00:00:01 +ends = dc:d9:0d:3b +starts = 5c:9f:04:3b +tstp = 00:00:00:00 +tsfp = 00:00:00:00 +cltt = 00:00:00:00 +.fi +.SH NEW REMOTE OBJECTS +.PP +New remote objects are created much in the same way that existing server +objects are modified. Create a local object using \fBnew\fR, set the +attributes as you'd wish them to be, and then create the remote object with +the same properties by using +.PP +.B create +.PP +Now a new object exists on the DHCP server which matches the properties that +you gave your local object. Objects created via OMAPI are saved into the +dhcpd.leases file. +.PP +For example, if a new host with the IP address of 192.168.4.40 needs to be +created it would be done as follows: +.nf +.sp 1 +> new host +obj: host +> set name = "some-host" +obj: host +name = "some-host" +> set hardware-address = 00:80:c7:84:b1:94 +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +> set hardware-type = 1 +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 1 +> set ip-address = 192.168.4.40 +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 1 +ip-address = c0:a8:04:28 +> create +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 00:00:00:01 +ip-address = c0:a8:04:28 +> +.fi +.PP +Your dhcpd.leases file would then have an entry like this in it: +.nf +.sp 1 +host some-host { + dynamic; + hardware ethernet 00:80:c7:84:b1:94; + fixed-address 192.168.4.40; +} +.fi +.PP +The \fIdynamic;\fR line is to denote that this host entry did not come from +dhcpd.conf, but was created dynamically via OMAPI. +.SH RESETTING ATTRIBUTES +.PP +If you want to remove an attribute from an object, you can do this with the +\fBunset\fR command. Once you have unset an attribute, you must use the +\fBupdate\fR command to update the remote object. So, if the host "some-host" +from the previous example will not have a static IP address anymore, the +commands in omshell would look like this: +.nf +.sp 1 +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 00:00:00:01 +ip-address = c0:a8:04:28 +> unset ip-address +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 00:00:00:01 +ip-address = <null> +> +.fi +.SH REFRESHING OBJECTS +.PP +A local object may be refreshed with the current remote object properties +using the \fBrefresh\fR command. This is useful for object that change +periodically, like leases, to see if they have been updated. This isn't +particularly useful for hosts. +.SH DELETING OBJECTS +.PP +Any remote object that can be created can also be destroyed. This is done by +creating a new local object, setting attributes, associating the local and +remote object using \fBopen\fI, and then using the \fBremove\fR command. +If the host "some-host" from before was created in error, this could be +corrected as follows: +.nf +.sp 1 +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 00:00:00:01 +ip-address = c0:a8:04:28 +> remove +obj: <null> +> +.fi +.SH HELP +.PP +The \fBhelp\fR command will print out all of the commands available in +omshell, with some syntax pointers. +.SH SEE ALSO +dhcpctl(3), omapi(3), dhcpd(8), dhclient(8), dhcpd.conf(5), dhclient.conf(5). +.SH AUTHOR +.B omshell +was written by Ted Lemon of Nominum, Inc. Information about Nominum +and support contracts for DHCP and BIND can be found at +.B http://www.nominum.com. This preliminary documentation was +written by Wendy Verschoor of Nominum, Inc., while she was testing +omshell. diff --git a/contrib/isc-dhcp/dhcpctl/omshell.c b/contrib/isc-dhcp/dhcpctl/omshell.c new file mode 100644 index 000000000000..345faaf3d5b5 --- /dev/null +++ b/contrib/isc-dhcp/dhcpctl/omshell.c @@ -0,0 +1,728 @@ +/* omshell.c + + Examine and modify omapi objects. */ + +/* + * Copyright (c) 2001-2002 Internet Software Consortium. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The Internet Software Consortium nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This software has been written for the Internet Software Consortium + * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. + * To learn more about the Internet Software Consortium, see + * ``http://www.isc.org/''. To learn more about Vixie Enterprises, + * see ``http://www.vix.com''. To learn more about Nominum, Inc., see + * ``http://www.nominum.com''. + */ + +#include <time.h> +#include <sys/time.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <isc-dhcp/result.h> +#include "dhcpctl.h" +#include "dhcpd.h" + +/* Fixups */ +isc_result_t find_class (struct class **c, const char *n, const char *f, int l) +{ + return 0; +} +int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag) +{ + return 0; +} +void dhcp (struct packet *packet) { } +void bootp (struct packet *packet) { } +int check_collection (struct packet *p, struct lease *l, struct collection *c) +{ + return 0; +} +void classify (struct packet *packet, struct class *class) { } + +static void usage (char *s) { + fprintf (stderr, "Usage: %s\n", s); + exit (1); +} + +static void check (isc_result_t status, const char *func) { + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "%s: %s\n", func, isc_result_totext (status)); + exit (1); + } +} + +int main (int argc, char **argv, char **envp) +{ + isc_result_t status, waitstatus; + dhcpctl_handle connection; + dhcpctl_handle authenticator; + dhcpctl_handle oh; + dhcpctl_data_string cid, ip_addr; + dhcpctl_data_string result, groupname, identifier; + struct data_string secret; + const char *name = 0, *algorithm = "hmac-md5"; + int i, j; + int port = 7911; + const char *server = "127.0.0.1"; + struct parse *cfile; + enum dhcp_token token; + const char *val; + char *s; + char buf[1024]; + char s1[1024]; + int connected = 0; + + for (i = 1; i < argc; i++) { + usage(argv[0]); + } + + /* Initially, log errors to stderr as well as to syslogd. */ +#ifdef SYSLOG_4_2 + openlog ("omshell", LOG_NDELAY); + log_priority = DHCPD_LOG_FACILITY; +#else + openlog ("omshell", LOG_NDELAY, DHCPD_LOG_FACILITY); +#endif + status = dhcpctl_initialize (); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_initialize: %s\n", + isc_result_totext (status)); + exit (1); + } + + memset (&oh, 0, sizeof oh); + + do { + if (!connected) { + } else if (oh == NULL) { + printf ("obj: <null>\n"); + } else { + dhcpctl_remote_object_t *r = (dhcpctl_remote_object_t *)oh; + omapi_generic_object_t *g = + (omapi_generic_object_t *)(r -> inner); + + printf ("obj: "); + + if (r -> rtype -> type != omapi_datatype_string) { + printf ("?\n"); + } else { + printf ("%.*s\n", + (int)(r -> rtype -> u . buffer . len), + r -> rtype -> u . buffer . value); + } + + for (i = 0; i < g -> nvalues; i++) { + omapi_value_t *v = g -> values [i]; + + if (!g -> values [i]) + continue; + + printf ("%.*s = ", (int)v -> name -> len, + v -> name -> value); + + if (!v -> value) { + printf ("<null>\n"); + continue; + } + switch (v -> value -> type) { + case omapi_datatype_int: + printf ("%d\n", + v -> value -> u . integer); + break; + + case omapi_datatype_string: + printf ("\"%.*s\"\n", + (int) v -> value -> u.buffer.len, + v -> value -> u.buffer.value); + break; + + case omapi_datatype_data: + printf ("%s\n", + print_hex_1 (v -> value -> u.buffer.len, + v -> value -> u.buffer.value, + 60)); + break; + + case omapi_datatype_object: + printf ("<obj>\n"); + break; + } + } + } + + fputs ("> ", stdout); + fflush (stdout); + if (fgets (buf, sizeof(buf), stdin) == NULL) + break; + + status = new_parse (&cfile, 0, buf, strlen(buf), "<STDIN>", 1); + check(status, "new_parse()"); + + token = next_token (&val, (unsigned *)0, cfile); + switch (token) { + default: + parse_warn (cfile, "unknown token: %s", val); + skip_to_semi (cfile); + break; + + case END_OF_FILE: + case EOL: + break; + + case TOKEN_HELP: + case '?': + printf ("Commands:\n"); + printf (" port <server omapi port>\n"); + printf (" server <server address>\n"); + printf (" key <key name> <key value>\n"); + printf (" connect\n"); + printf (" new <object-type>\n"); + printf (" set <name> = <value>\n"); + printf (" create\n"); + printf (" open\n"); + printf (" update\n"); + printf (" unset <name>\n"); + printf (" refresh\n"); + printf (" remove\n"); + skip_to_semi (cfile); + break; + + case PORT: + token = next_token (&val, (unsigned *)0, cfile); + if (is_identifier (token)) { + struct servent *se; + se = getservbyname (val, "tcp"); + if (se) + port = ntohs (se -> s_port); + else { + printf ("unknown service name: %s\n", val); + break; + } + } else if (token == NUMBER) { + port = atoi (val); + } else { + skip_to_semi (cfile); + printf ("usage: port <port>\n"); + break; + } + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: port <server>\n"); + skip_to_semi (cfile); + break; + } + break; + + case SERVER: + token = next_token (&val, (unsigned *)0, cfile); + if (token == NUMBER) { + int alen = (sizeof buf) - 1; + int len; + + s = &buf [0]; + len = strlen (val); + if (len + 1 > alen) { + baddq: + printf ("usage: server <server>\n"); + skip_to_semi (cfile); + break; + } strcpy (buf, val); + s += len; + token = next_token (&val, (unsigned *)0, cfile); + if (token != DOT) + goto baddq; + *s++ = '.'; + token = next_token (&val, (unsigned *)0, cfile); + if (token != NUMBER) + goto baddq; + len = strlen (val); + if (len + 1 > alen) + goto baddq; + strcpy (s, val); + s += len; + token = next_token (&val, (unsigned *)0, cfile); + if (token != DOT) + goto baddq; + *s++ = '.'; + token = next_token (&val, (unsigned *)0, cfile); + if (token != NUMBER) + goto baddq; + len = strlen (val); + if (len + 1 > alen) + goto baddq; + strcpy (s, val); + s += len; + token = next_token (&val, (unsigned *)0, cfile); + if (token != DOT) + goto baddq; + *s++ = '.'; + token = next_token (&val, (unsigned *)0, cfile); + if (token != NUMBER) + goto baddq; + len = strlen (val); + if (len + 1 > alen) + goto baddq; + strcpy (s, val); + val = &buf [0]; + } else if (is_identifier (token)) { + /* Use val directly. */ + } else { + printf ("usage: server <server>\n"); + skip_to_semi (cfile); + break; + } + + s = dmalloc (strlen (val) + 1, MDL); + if (!server) { + printf ("no memory to store server name.\n"); + skip_to_semi (cfile); + break; + } + strcpy (s, val); + server = s; + + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: server <server>\n"); + skip_to_semi (cfile); + break; + } + break; + + case KEY: + token = next_token (&val, (unsigned *)0, cfile); + if (!is_identifier (token)) { + printf ("usage: key <name> <value>\n"); + skip_to_semi (cfile); + break; + } + s = dmalloc (strlen (val) + 1, MDL); + if (!s) { + printf ("no memory for key name.\n"); + skip_to_semi (cfile); + break; + } + strcpy (s, val); + name = s; + memset (&secret, 0, sizeof secret); + if (!parse_base64 (&secret, cfile)) { + skip_to_semi (cfile); + break; + } + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: key <name> <secret>\n"); + skip_to_semi (cfile); + break; + } + break; + + case CONNECT: + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: connect\n"); + skip_to_semi (cfile); + break; + } + + authenticator = dhcpctl_null_handle; + + if (name) { + status = dhcpctl_new_authenticator (&authenticator, + name, algorithm, + secret.data, + secret.len); + + if (status != ISC_R_SUCCESS) { + fprintf (stderr, + "Cannot create authenticator: %s\n", + isc_result_totext (status)); + break; + } + } + + memset (&connection, 0, sizeof connection); + status = dhcpctl_connect (&connection, + server, port, authenticator); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_connect: %s\n", + isc_result_totext (status)); + break; + } + connected = 1; + break; + + case TOKEN_NEW: + token = next_token (&val, (unsigned *)0, cfile); + if ((!is_identifier (token) && token != STRING)) { + printf ("usage: new <object-type>\n"); + break; + } + + if (oh) { + printf ("an object is already open.\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + + status = dhcpctl_new_object (&oh, connection, val); + if (status != ISC_R_SUCCESS) { + printf ("can't create object: %s\n", + isc_result_totext (status)); + break; + } + + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: new <object-type>\n"); + skip_to_semi (cfile); + break; + } + break; + + case TOKEN_CLOSE: + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: close\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + + if (!oh) { + printf ("not open.\n"); + skip_to_semi (cfile); + break; + } + omapi_object_dereference (&oh, MDL); + + break; + + case TOKEN_SET: + token = next_token (&val, (unsigned *)0, cfile); + + if ((!is_identifier (token) && token != STRING)) { + set_usage: + printf ("usage: set <name> = <value>\n"); + skip_to_semi (cfile); + break; + } + + if (oh == NULL) { + printf ("no open object.\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + + s1[0] = '\0'; + strncat (s1, val, sizeof(s1)-1); + + token = next_token (&val, (unsigned *)0, cfile); + if (token != EQUAL) + goto set_usage; + + token = next_token (&val, (unsigned *)0, cfile); + switch (token) { + case STRING: + dhcpctl_set_string_value (oh, val, s1); + token = next_token (&val, (unsigned *)0, cfile); + break; + + case NUMBER: + strcpy (buf, val); + token = peek_token (&val, (unsigned *)0, cfile); + /* Colon-seperated hex list? */ + if (token == COLON) + goto cshl; + else if (token == DOT) { + s = buf; + val = buf; + do { + int intval = atoi (val); + dotiszero: + if (intval > 255) { + parse_warn (cfile, + "dotted octet > 255: %s", + val); + skip_to_semi (cfile); + goto badnum; + } + *s++ = intval; + token = next_token (&val, + (unsigned *)0, cfile); + if (token != DOT) + break; + /* DOT is zero. */ + while ((token = next_token (&val, + (unsigned *)0, cfile)) == DOT) + *s++ = 0; + } while (token == NUMBER); + dhcpctl_set_data_value (oh, buf, + (unsigned)(s - buf), + s1); + break; + } + dhcpctl_set_int_value (oh, atoi (buf), s1); + token = next_token (&val, (unsigned *)0, cfile); + badnum: + break; + + case NUMBER_OR_NAME: + strcpy (buf, val); + cshl: + s = buf; + val = buf; + do { + convert_num (cfile, (unsigned char *)s, + val, 16, 8); + ++s; + token = next_token (&val, + (unsigned *)0, cfile); + if (token != COLON) + break; + token = next_token (&val, + (unsigned *)0, cfile); + } while (token == NUMBER || + token == NUMBER_OR_NAME); + dhcpctl_set_data_value (oh, buf, + (unsigned)(s - buf), s1); + break; + + default: + printf ("invalid value.\n"); + skip_to_semi (cfile); + } + + if (token != END_OF_FILE && token != EOL) + goto set_usage; + break; + + case UNSET: + token = next_token (&val, (unsigned *)0, cfile); + + if ((!is_identifier (token) && token != STRING)) { + unset_usage: + printf ("usage: unset <name>\n"); + skip_to_semi (cfile); + break; + } + + if (!oh) { + printf ("no open object.\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + + s1[0] = '\0'; + strncat (s1, val, sizeof(s1)-1); + + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) + goto unset_usage; + + dhcpctl_set_null_value (oh, s1); + break; + + + case TOKEN_CREATE: + case TOKEN_OPEN: + i = token; + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: %s\n", val); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + + if (!oh) { + printf ("you must make a new object first!\n"); + skip_to_semi (cfile); + break; + } + + if (i == TOKEN_CREATE) + i = DHCPCTL_CREATE | DHCPCTL_EXCL; + else + i = 0; + + status = dhcpctl_open_object (oh, connection, i); + if (status == ISC_R_SUCCESS) + status = dhcpctl_wait_for_completion + (oh, &waitstatus); + if (status == ISC_R_SUCCESS) + status = waitstatus; + if (status != ISC_R_SUCCESS) { + printf ("can't open object: %s\n", + isc_result_totext (status)); + break; + } + + break; + + case UPDATE: + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: %s\n", val); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + + if (!oh) { + printf ("you haven't opened an object yet!\n"); + skip_to_semi (cfile); + break; + } + + status = dhcpctl_object_update(connection, oh); + if (status == ISC_R_SUCCESS) + status = dhcpctl_wait_for_completion + (oh, &waitstatus); + if (status == ISC_R_SUCCESS) + status = waitstatus; + if (status != ISC_R_SUCCESS) { + printf ("can't update object: %s\n", + isc_result_totext (status)); + break; + } + + break; + + case REMOVE: + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: remove\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + break; + } + + if (!oh) { + printf ("no object.\n"); + break; + } + + status = dhcpctl_object_remove(connection, oh); + if (status == ISC_R_SUCCESS) + status = dhcpctl_wait_for_completion + (oh, &waitstatus); + if (status == ISC_R_SUCCESS) + status = waitstatus; + if (status != ISC_R_SUCCESS) { + printf ("can't destroy object: %s\n", + isc_result_totext (status)); + break; + } + omapi_object_dereference (&oh, MDL); + break; + + case REFRESH: + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: refresh\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + break; + } + + if (!oh) { + printf ("no object.\n"); + break; + } + + status = dhcpctl_object_refresh(connection, oh); + if (status == ISC_R_SUCCESS) + status = dhcpctl_wait_for_completion + (oh, &waitstatus); + if (status == ISC_R_SUCCESS) + status = waitstatus; + if (status != ISC_R_SUCCESS) { + printf ("can't refresh object: %s\n", + isc_result_totext (status)); + break; + } + + break; + } + } while (1); + + exit (0); +} + +/* Sigh */ +isc_result_t dhcp_set_control_state (control_object_state_t oldstate, + control_object_state_t newstate) +{ + return ISC_R_SUCCESS; +} diff --git a/contrib/isc-dhcp/dhcpctl/remote.c b/contrib/isc-dhcp/dhcpctl/remote.c new file mode 100644 index 000000000000..f888ac24f9fd --- /dev/null +++ b/contrib/isc-dhcp/dhcpctl/remote.c @@ -0,0 +1,371 @@ +/* remote.c + + The dhcpctl remote object. */ + +/* + * Copyright (c) 1999-2003 Internet Software Consortium. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The Internet Software Consortium nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This software has been written for the Internet Software Consortium + * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. + * To learn more about the Internet Software Consortium, see + * ``http://www.isc.org/''. To learn more about Vixie Enterprises, + * see ``http://www.vix.com''. To learn more about Nominum, Inc., see + * ``http://www.nominum.com''. + */ + +#include <omapip/omapip_p.h> +#include "dhcpctl.h" + +/* dhcpctl_new_authenticator + + synchronous - creates an authenticator object. + returns nonzero status code if the object couldn't be created + stores handle to authenticator through h if successful, and returns zero. + name is the authenticator name (NUL-terminated string). + algorithm is the NUL-terminated string name of the algorithm to use + (currently, only "hmac-md5" is supported). + secret and secret_len is the key secret. */ + +dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *h, + const char *name, + const char *algorithm, + const unsigned char *secret, + unsigned secret_len) +{ + struct auth_key *key = (struct auth_key *)0; + isc_result_t status; + + status = omapi_auth_key_new (&key, MDL); + if (status != ISC_R_SUCCESS) + return status; + + key -> name = dmalloc (strlen (name) + 1, MDL); + if (!key -> name) { + omapi_auth_key_dereference (&key, MDL); + return ISC_R_NOMEMORY; + } + strcpy (key -> name, name); + + /* If the algorithm name isn't an FQDN, tack on the + .SIG-ALG.REG.NET. domain. */ + if (strchr (algorithm, '.') == 0) { + static char add[] = ".SIG-ALG.REG.INT."; + key -> algorithm = dmalloc (strlen (algorithm) + + sizeof (add), MDL); + if (!key -> algorithm) { + omapi_auth_key_dereference (&key, MDL); + return ISC_R_NOMEMORY; + } + strcpy (key -> algorithm, algorithm); + strcat (key -> algorithm, add); + } else { + key -> algorithm = dmalloc (strlen (algorithm) + 1, MDL); + if (!key -> algorithm) { + omapi_auth_key_dereference (&key, MDL); + return ISC_R_NOMEMORY; + } + strcpy (key -> algorithm, algorithm); + } + + status = omapi_data_string_new (&key -> key, secret_len, MDL); + if (status != ISC_R_SUCCESS) { + omapi_auth_key_dereference (&key, MDL); + return status; + } + memcpy (key -> key -> value, secret, secret_len); + key -> key -> len = secret_len; + + *h = (dhcpctl_handle) key; + return ISC_R_SUCCESS; +} + + +/* dhcpctl_new_object + + synchronous - creates a local handle for a host entry. + returns nonzero status code if the local host entry couldn't + be created + stores handle to host through h if successful, and returns zero. + object_type is a pointer to a NUL-terminated string containing + the ascii name of the type of object being accessed - e.g., "host" */ + +dhcpctl_status dhcpctl_new_object (dhcpctl_handle *h, + dhcpctl_handle connection, + const char *object_type) +{ + dhcpctl_remote_object_t *m; + omapi_object_t *g; + isc_result_t status; + + m = (dhcpctl_remote_object_t *)0; + status = omapi_object_allocate ((omapi_object_t **)&m, + dhcpctl_remote_type, 0, MDL); + if (status != ISC_R_SUCCESS) + return status; + + g = (omapi_object_t *)0; + status = omapi_generic_new (&g, MDL); + if (status != ISC_R_SUCCESS) { + dfree (m, MDL); + return status; + } + status = omapi_object_reference (&m -> inner, g, MDL); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference ((omapi_object_t **)&m, MDL); + omapi_object_dereference (&g, MDL); + return status; + } + status = omapi_object_reference (&g -> outer, + (omapi_object_t *)m, MDL); + + if (status != ISC_R_SUCCESS) { + omapi_object_dereference ((omapi_object_t **)&m, MDL); + omapi_object_dereference (&g, MDL); + return status; + } + + status = omapi_typed_data_new (MDL, &m -> rtype, + omapi_datatype_string, + object_type); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference ((omapi_object_t **)&m, MDL); + omapi_object_dereference (&g, MDL); + return status; + } + + status = omapi_object_reference (h, (omapi_object_t *)m, MDL); + omapi_object_dereference ((omapi_object_t **)&m, MDL); + omapi_object_dereference (&g, MDL); + if (status != ISC_R_SUCCESS) + return status; + + return status; +} + +/* asynchronous - just queues the request + returns nonzero status code if open couldn't be queued + returns zero if open was queued + h is a handle to an object created by dhcpctl_new_object + connection is a connection to a DHCP server + flags include: + DHCPCTL_CREATE - if the object doesn't exist, create it + DHCPCTL_UPDATE - update the object on the server using the + attached parameters + DHCPCTL_EXCL - error if the object exists and DHCPCTL_CREATE + was also specified */ + +dhcpctl_status dhcpctl_open_object (dhcpctl_handle h, + dhcpctl_handle connection, + int flags) +{ + isc_result_t status; + omapi_object_t *message = (omapi_object_t *)0; + dhcpctl_remote_object_t *remote; + + if (h -> type != dhcpctl_remote_type) + return ISC_R_INVALIDARG; + remote = (dhcpctl_remote_object_t *)h; + + status = omapi_message_new (&message, MDL); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_set_int_value (message, (omapi_object_t *)0, + "op", OMAPI_OP_OPEN); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + status = omapi_set_object_value (message, (omapi_object_t *)0, + "object", h); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + if (flags & DHCPCTL_CREATE) { + status = omapi_set_boolean_value (message, (omapi_object_t *)0, + "create", 1); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + } + if (flags & DHCPCTL_UPDATE) { + status = omapi_set_boolean_value (message, (omapi_object_t *)0, + "update", 1); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + } + if (flags & DHCPCTL_EXCL) { + status = omapi_set_boolean_value (message, (omapi_object_t *)0, + "exclusive", 1); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + } + + if (remote -> rtype) { + status = omapi_set_value_str (message, (omapi_object_t *)0, + "type", remote -> rtype); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + } + + status = omapi_message_register (message); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + status = omapi_protocol_send_message (connection -> outer, + (omapi_object_t *)0, + message, (omapi_object_t *)0); + + if (status != ISC_R_SUCCESS) + omapi_message_unregister (message); + + omapi_object_dereference (&message, MDL); + return status; +} + +/* Callback methods (not meant to be called directly) */ + +isc_result_t dhcpctl_remote_set_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_typed_data_t *value) +{ + dhcpctl_remote_object_t *ro; + unsigned long rh; + isc_result_t status; + + if (h -> type != dhcpctl_remote_type) + return ISC_R_INVALIDARG; + ro = (dhcpctl_remote_object_t *)h; + + if (!omapi_ds_strcmp (name, "remote-handle")) { + status = omapi_get_int_value (&rh, value); + if (status == ISC_R_SUCCESS) + ro -> remote_handle = rh; + return status; + } + + if (h -> inner && h -> inner -> type -> set_value) + return (*(h -> inner -> type -> set_value)) + (h -> inner, id, name, value); + return ISC_R_NOTFOUND; +} + +isc_result_t dhcpctl_remote_get_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_value_t **value) +{ + if (h -> type != dhcpctl_remote_type) + return ISC_R_INVALIDARG; + + if (h -> inner && h -> inner -> type -> get_value) + return (*(h -> inner -> type -> get_value)) + (h -> inner, id, name, value); + return ISC_R_NOTFOUND; +} + +isc_result_t dhcpctl_remote_signal_handler (omapi_object_t *o, + const char *name, va_list ap) +{ + dhcpctl_remote_object_t *p; + omapi_typed_data_t *tv; + + if (o -> type != dhcpctl_remote_type) + return ISC_R_INVALIDARG; + p = (dhcpctl_remote_object_t *)o; + + if (!strcmp (name, "updated")) { + p -> waitstatus = ISC_R_SUCCESS; + if (o -> inner -> type == omapi_type_generic) + omapi_generic_clear_flags (o -> inner); + return omapi_signal_in (o -> inner, "ready"); + } + if (!strcmp (name, "status")) { + p -> waitstatus = va_arg (ap, isc_result_t); + if (p -> message) + omapi_typed_data_dereference (&p -> message, MDL); + tv = va_arg (ap, omapi_typed_data_t *); + if (tv) + omapi_typed_data_reference (&p -> message, tv, MDL); + return omapi_signal_in (o -> inner, "ready"); + } + + if (p -> inner && p -> inner -> type -> signal_handler) + return (*(p -> inner -> type -> signal_handler)) + (p -> inner, name, ap); + + return ISC_R_SUCCESS; +} + +isc_result_t dhcpctl_remote_destroy (omapi_object_t *h, + const char *file, int line) +{ + dhcpctl_remote_object_t *p; + if (h -> type != dhcpctl_remote_type) + return ISC_R_INVALIDARG; + p = (dhcpctl_remote_object_t *)h; + if (p -> handle) + omapi_object_dereference ((omapi_object_t **)&p -> handle, + file, line); + if (p -> rtype) + omapi_typed_data_dereference ((omapi_typed_data_t **)&p->rtype, + file, line); + return ISC_R_SUCCESS; +} + +/* Write all the published values associated with the object through the + specified connection. */ + +isc_result_t dhcpctl_remote_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *p) +{ + int i; + + if (p -> type != dhcpctl_remote_type) + return ISC_R_INVALIDARG; + + if (p -> inner && p -> inner -> type -> stuff_values) + return (*(p -> inner -> type -> stuff_values)) (c, id, + p -> inner); + return ISC_R_SUCCESS; +} + |