summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdhcpsvc/private/private.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libdhcpsvc/private/private.c')
-rw-r--r--usr/src/lib/libdhcpsvc/private/private.c871
1 files changed, 0 insertions, 871 deletions
diff --git a/usr/src/lib/libdhcpsvc/private/private.c b/usr/src/lib/libdhcpsvc/private/private.c
deleted file mode 100644
index 1045df04fe..0000000000
--- a/usr/src/lib/libdhcpsvc/private/private.c
+++ /dev/null
@@ -1,871 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2001 by Sun Microsystems, Inc.
- * All rights reserved.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This module contains the private layer API.
- */
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/param.h>
-#include <libelf.h>
-#include <gelf.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <dlfcn.h>
-#include <glob.h>
-#include <fcntl.h>
-#include <libinetutil.h>
-#include <dhcp_svc_public.h>
-#include <dhcp_svc_private.h>
-
-/*
- * Threading notes for private layer consumers:
- *
- * The handles returned from open_dd() may be shared across multiple
- * threads with no adverse side effects. However, it's up to that consumer
- * to ensure that all threads have finished using an instance before
- * closing the instance or removing the container it's referencing.
- * Phrased differently:
- *
- * * Consumers must ensure all threads sharing a handle are
- * finished before calling close_dd().
- *
- * * Consumers must ensure all threads referencing a container are
- * closed before calling remove_dd().
- */
-
-static boolean_t validate_dd_entry(dsvc_handle_t, const void *, boolean_t);
-static int synch_init(dsvc_handle_t, const char *, uint_t);
-static void synch_fini(dsvc_handle_t);
-
-/*
- * Order here should match the function array in <dhcp_svc_private.h>
- */
-static char *funcnames[] = {
- "status", "version", "mklocation",
- "list_dt", "open_dt", "close_dt", "remove_dt",
- "lookup_dt", "add_dt", "modify_dt", "delete_dt",
- "list_dn", "open_dn", "close_dn", "remove_dn",
- "lookup_dn", "add_dn", "modify_dn", "delete_dn"
-};
-
-extern dsvc_synch_ops_t dsvcd_synch_ops;
-
-/*
- * Retrieve the current version associated with the datastore named by
- * `resource' and store in `converp'. One might think we could do this via
- * a simple readlink(2), but on internal release builds $(ROOTLINKS)
- * installs using hardlinks, not symlinks. For this reason and to make it
- * harder for us to be fooled, we'll dredge up the actual soname through
- * ELF. Close your eyes, it's gonna get ugly.
- */
-static int
-get_conver(const char *resource, int *converp)
-{
- int elf_fd;
- int i;
- GElf_Shdr gelf_shdr;
- GElf_Dyn gelf_dyn;
- Elf_Scn *elf_scn = NULL;
- Elf *elf_file;
- Elf_Data *elf_data;
- char *soname = NULL;
- char path[MAXPATHLEN];
-
- (void) snprintf(path, sizeof (path), "%s%s/%s_%s.so", DHCP_CONFOPT_ROOT,
- DSVC_MODULE_DIR, DSVC_PUBLIC_PREFIX, resource);
-
- elf_fd = open(path, O_RDONLY);
- if (elf_fd == -1)
- return (DSVC_MODULE_ERR);
-
- if (elf_version(EV_CURRENT) == EV_NONE) {
- (void) close(elf_fd);
- return (DSVC_INTERNAL);
- }
-
- elf_file = elf_begin(elf_fd, ELF_C_READ, NULL);
- if (elf_file == NULL || elf_kind(elf_file) != ELF_K_ELF) {
- (void) close(elf_fd);
- return (DSVC_INTERNAL);
- }
-
- while ((elf_scn = elf_nextscn(elf_file, elf_scn)) != NULL) {
- if (gelf_getshdr(elf_scn, &gelf_shdr) == 0)
- continue;
-
- if (gelf_shdr.sh_type != SHT_DYNAMIC)
- continue;
-
- elf_data = elf_getdata(elf_scn, NULL);
- if (elf_data == NULL)
- continue;
-
- i = 0;
- do {
- (void) gelf_getdyn(elf_data, i++, &gelf_dyn);
- if (gelf_dyn.d_tag == DT_SONAME)
- soname = elf_strptr(elf_file, gelf_shdr.sh_link,
- gelf_dyn.d_un.d_ptr);
- } while (gelf_dyn.d_tag != DT_NULL && soname == NULL);
- }
- if (soname == NULL || sscanf(soname, "%*[^.].so.%d", converp) != 1) {
- (void) elf_end(elf_file);
- (void) close(elf_fd);
- return (DSVC_MODULE_ERR);
- }
- (void) elf_end(elf_file);
- (void) close(elf_fd);
-
- return (DSVC_SUCCESS);
-}
-
-/*
- * Unload a public datastore module.
- */
-static int
-unload_public_module(void **instance, dsvc_splapi_t *api)
-{
- static dsvc_splapi_t null_api;
-
- if (dlclose(*instance) != 0)
- return (DSVC_MODULE_UNLOAD_ERR);
-
- *instance = NULL;
- *api = null_api;
-
- return (DSVC_SUCCESS);
-}
-
-/*
- * Load public datastore module. Validates version of module. Returns
- * instance of opened module, and populates the api argument with the
- * function addresses exporting the API.
- */
-static int
-load_public_module(dsvc_datastore_t *ddp, void **instance, dsvc_splapi_t *api)
-{
- int i, v;
- dsvc_splfuncp_t configure;
- char path[MAXPATHLEN];
-
- (void) snprintf(path, sizeof (path), "%s%s/%s_%s.so", DHCP_CONFOPT_ROOT,
- DSVC_MODULE_DIR, DSVC_PUBLIC_PREFIX, ddp->d_resource);
-
- if (ddp->d_conver != DSVC_CUR_CONVER)
- (void) snprintf(path, sizeof (path), "%s.%d", path,
- ddp->d_conver);
-
- *instance = dlopen(path, RTLD_LAZY|RTLD_GROUP|RTLD_WORLD);
- if (*instance == NULL)
- return (DSVC_MODULE_LOAD_ERR);
-
- /*
- * No requirement to duplicate the names - we can always reference
- * the same set.
- */
- api->version = (dsvc_splfuncp_t)dlsym(*instance, "version");
- if (api->version == NULL || api->version(&v) != DSVC_SUCCESS ||
- v != DSVC_PUBLIC_VERSION) {
- (void) unload_public_module(instance, api);
- return (DSVC_MODULE_VERSION);
- }
-
- configure = (dsvc_splfuncp_t)dlsym(*instance, "configure");
- if (configure != NULL) {
- if (configure(ddp->d_config) != DSVC_SUCCESS) {
- (void) unload_public_module(instance, api);
- return (DSVC_MODULE_CFG_ERR);
- }
- }
-
- for (i = 0; i < DSVC_NSPLFUNCS; i++) {
- if ((((dsvc_splfuncp_t *)api)[i] =
- (dsvc_splfuncp_t)dlsym(*instance, funcnames[i])) == NULL) {
- (void) unload_public_module(instance, api);
- return (DSVC_MODULE_ERR);
- }
- }
-
- /*
- * Caller requested the current version; fill in what that current
- * version is.
- */
- if (ddp->d_conver == DSVC_CUR_CONVER) {
- int error;
- error = get_conver(ddp->d_resource, &ddp->d_conver);
- if (error != DSVC_SUCCESS) {
- (void) unload_public_module(instance, api);
- return (error);
- }
- }
-
- return (DSVC_SUCCESS);
-}
-
-/*
- * Return a dynamically-allocated null-terminated list of the available
- * modules stored in the module directory. A count of the available
- * modules is stored in the num argument. Caller is responsible for
- * freeing the list.
- */
-int
-enumerate_dd(char ***modules, int *nump)
-{
- int i, retval;
- char *ptr;
- glob_t globbuf;
- char globpat[MAXPATHLEN];
-
- if (modules == NULL || nump == NULL)
- return (DSVC_INVAL);
-
- (void) snprintf(globpat, sizeof (globpat), "%s%s/%s_*\\.so",
- DHCP_CONFOPT_ROOT, DSVC_MODULE_DIR, DSVC_PUBLIC_PREFIX);
-
- retval = glob(globpat, GLOB_NOSORT, NULL, &globbuf);
- if (retval != 0) {
- globfree(&globbuf);
- switch (retval) {
- case GLOB_NOMATCH:
- *nump = 0;
- *modules = NULL;
- return (DSVC_SUCCESS);
- case GLOB_NOSPACE:
- return (DSVC_NO_MEMORY);
- default:
- return (DSVC_INTERNAL);
- }
- }
-
- *modules = calloc(globbuf.gl_pathc, sizeof (char **));
- if (*modules == NULL) {
- globfree(&globbuf);
- return (DSVC_NO_MEMORY);
- }
-
- for (i = 0; i < globbuf.gl_pathc; i++) {
- ptr = strrchr(globbuf.gl_pathv[i], '/');
- if (ptr == NULL)
- ptr = globbuf.gl_pathv[i];
- else
- ptr++;
- (*modules)[i] = malloc(strlen(ptr) + 1);
- if ((*modules)[i] == NULL) {
- while (i--)
- free((*modules)[i]);
- free(modules);
- globfree(&globbuf);
- return (DSVC_NO_MEMORY);
- }
-
- (void) sscanf(ptr, "%*[^_]_%[^.]", (*modules)[i]);
- }
-
- globfree(&globbuf);
- *nump = i;
- return (DSVC_SUCCESS);
-}
-
-/*
- * Check the status of the underlying service supporting the data store.
- * Caller is responsible for freeing any dynamically allocated arguments.
- */
-int
-status_dd(dsvc_datastore_t *ddp)
-{
- void *instance;
- dsvc_splapi_t api;
- int error;
-
- error = load_public_module(ddp, &instance, &api);
- if (error != DSVC_SUCCESS)
- return (error);
-
- error = api.status(ddp->d_location);
-
- (void) unload_public_module(&instance, &api);
-
- return (error);
-}
-
-/*
- * Create within the data store the "location" where containers will be
- * stored.
- */
-int
-mklocation_dd(dsvc_datastore_t *ddp)
-{
- void *instance;
- dsvc_splapi_t api;
- int error;
-
- error = load_public_module(ddp, &instance, &api);
- if (error != DSVC_SUCCESS)
- return (error);
-
- error = api.mklocation(ddp->d_location);
-
- (void) unload_public_module(&instance, &api);
-
- return (error);
-}
-
-/*
- * Return a list of the current container objects of type 'type' located at
- * 'location' in listppp. Return the number of list elements in 'count'.
- */
-int
-list_dd(dsvc_datastore_t *ddp, dsvc_contype_t type, char ***listppp,
- uint_t *count)
-{
- void *instance;
- dsvc_splapi_t api;
- int error;
-
- error = load_public_module(ddp, &instance, &api);
- if (error != DSVC_SUCCESS)
- return (error);
-
- if (type == DSVC_DHCPTAB)
- error = api.list_dt(ddp->d_location, listppp, count);
- else
- error = api.list_dn(ddp->d_location, listppp, count);
-
- (void) unload_public_module(&instance, &api);
-
- return (error);
-}
-
-/*
- * Creates or opens the DHCP container of type called name within the
- * specific datastore referenced by ddp, and returns a handle to this
- * container in the handp argument. New containers are created with
- * the identity of the caller. Caller is responsible for freeing any
- * dynamically allocated arguments. The returned handle instance must
- * be released by calling close_dd().
- */
-int
-open_dd(dsvc_handle_t *handp, dsvc_datastore_t *ddp, dsvc_contype_t type,
- const char *name, uint_t flags)
-{
- int error;
- dsvc_handle_t hp;
-
- *handp = NULL;
-
- if (type == DSVC_DHCPNETWORK && name == NULL)
- return (DSVC_INVAL);
-
- if (flags & DSVC_CREATE && (flags & DSVC_WRITE) == 0)
- return (DSVC_INVAL);
-
- if ((hp = calloc(1, sizeof (struct dsvc_handle))) == NULL)
- return (DSVC_NO_MEMORY);
-
- if (type == DSVC_DHCPNETWORK) {
- hp->d_conid.c_net.s_addr = ntohl(inet_addr(name));
- if (hp->d_conid.c_net.s_addr == INADDR_BROADCAST) {
- free(hp);
- return (DSVC_INVAL);
- }
- get_netmask4(&hp->d_conid.c_net, &hp->d_conid.c_mask);
- }
-
- error = load_public_module(ddp, &hp->d_instance, &hp->d_api);
- if (error != DSVC_SUCCESS) {
- free(hp);
- return (error);
- }
-
- hp->d_type = type;
- hp->d_desc.d_conver = ddp->d_conver;
- hp->d_desc.d_resource = strdup(ddp->d_resource);
- hp->d_desc.d_location = strdup(ddp->d_location);
- if (hp->d_desc.d_resource == NULL || hp->d_desc.d_location == NULL) {
- error = DSVC_NO_MEMORY;
- goto error;
- }
-
- /*
- * Initialize the synchronization strategy (may not be any).
- */
- error = synch_init(hp, name, flags);
- if (error != DSVC_SUCCESS)
- goto error;
-
- if (type == DSVC_DHCPTAB)
- error = hp->d_api.open_dt(&hp->d_hand, ddp->d_location, flags);
- else
- error = hp->d_api.open_dn(&hp->d_hand, ddp->d_location, flags,
- &hp->d_conid.c_net, &hp->d_conid.c_mask);
-
- if (error != DSVC_SUCCESS) {
- if (hp->d_synch != NULL)
- synch_fini(hp);
- goto error;
- }
-
- *handp = hp;
- return (DSVC_SUCCESS);
-error:
- (void) unload_public_module(&hp->d_instance, &hp->d_api);
- free(hp->d_desc.d_resource);
- free(hp->d_desc.d_location);
- free(hp);
- return (error);
-}
-
-/*
- * Remove DHCP container called name of type within the specific datastore
- * referenced by ddp. Caller is responsible for freeing any dynamically
- * allocated arguments.
- */
-int
-remove_dd(dsvc_datastore_t *ddp, dsvc_contype_t type, const char *name)
-{
- void *instance;
- int error;
- dsvc_splapi_t api;
- struct in_addr ip, mask;
-
- if (type != DSVC_DHCPTAB) {
- if ((ip.s_addr = inet_addr(name)) == INADDR_BROADCAST)
- return (DSVC_INVAL);
- ip.s_addr = ntohl(ip.s_addr);
- get_netmask4(&ip, &mask);
- }
-
- error = load_public_module(ddp, &instance, &api);
- if (error != DSVC_SUCCESS)
- return (error);
-
- /* remove the DHCP container */
- if (type == DSVC_DHCPTAB)
- error = api.remove_dt(ddp->d_location);
- else
- error = api.remove_dn(ddp->d_location, &ip, &mask);
-
- (void) unload_public_module(&instance, &api);
-
- return (error);
-}
-
-/*
- * Delete the handle instance referenced by hand. Frees hand if the close
- * operation was successful. NOTE: Caller is responsible for synchronizing
- * multiple threads such that close_dd() is called when all consuming
- * threads have exited.
- */
-int
-close_dd(dsvc_handle_t *handp)
-{
- int error;
-
- if (handp == NULL || DSVC_HANDLE_INVAL(*handp))
- return (DSVC_INVAL);
-
- if ((*handp)->d_type == DSVC_DHCPTAB)
- error = (*handp)->d_api.close_dt(&((*handp)->d_hand));
- else
- error = (*handp)->d_api.close_dn(&((*handp)->d_hand));
-
- if (error == DSVC_SUCCESS) {
- error = unload_public_module(&(*handp)->d_instance,
- &(*handp)->d_api);
- if ((*handp)->d_synch != NULL)
- synch_fini(*handp);
- free((*handp)->d_desc.d_resource);
- free((*handp)->d_desc.d_location);
- free(*handp);
- *handp = NULL;
- }
-
- return (error);
-}
-
-/*
- * Searches hand container for records that match the query described by
- * the combination of query and targetp. If the partial field is true, then
- * lookup operations that have located some records but are unable to
- * complete entirely are allowed. The query argument consists of 2 fields,
- * each 16 bits long. The lower 16 bits selects which fields in the targetp
- * record are to be considered in the query. The upper 16 bits identifies
- * whether a particular field value must match (bit set) or not match (bit
- * clear). Unused bits in both 16 bit fields must be 0. The count argument
- * specifies the maximum number of matching records to return. A count
- * value of -1 requests that all matching records be returned. recordsp is
- * set to point to the resulting list of records; if recordsp is NULL then
- * no records are actually returned. Note that these records are
- * dynamically allocated, thus the caller is responsible for freeing them.
- * The number of records found is returned in nrecordsp; a value of 0 means
- * that no records matched the query.
- */
-int
-lookup_dd(dsvc_handle_t hand, boolean_t partial, uint_t query,
- int count, const void *targetp, void **recordsp, uint_t *nrecordsp)
-{
- uint_t mask = 0;
- int error;
- void *unlock_cookie;
- int (*lookup)();
-
- if (targetp == NULL || nrecordsp == NULL || DSVC_HANDLE_INVAL(hand))
- return (DSVC_INVAL);
-
- if (hand->d_type == DSVC_DHCPTAB) {
- mask = (uint_t)~DT_QALL;
- lookup = hand->d_api.lookup_dt;
- } else {
- mask = (uint_t)~DN_QALL;
- lookup = hand->d_api.lookup_dn;
- }
-
- /* validate query */
- if (((query & 0xffff) & mask) || ((query >> 16) & mask))
- return (DSVC_INVAL);
-
- /*
- * XXX: need to validate the `targetp' -- what a mess cuz only the
- * fields lit in `query' need to be valid.
- */
-
- if (hand->d_synch != NULL) {
- error = DSVC_SYNCH_RDLOCK(hand->d_synch, &unlock_cookie);
- if (error != DSVC_SUCCESS)
- return (error);
- }
-
- error = lookup(hand->d_hand, partial, query, count, targetp, recordsp,
- nrecordsp);
-
- if (hand->d_synch != NULL)
- (void) DSVC_SYNCH_UNLOCK(hand->d_synch, unlock_cookie);
-
- return (error);
-}
-
-/*
- * Frees the record pointed to by entryp.
- */
-void
-free_dd(dsvc_handle_t hand, void *entryp)
-{
- if (DSVC_HANDLE_INVAL(hand) || entryp == NULL)
- return;
-
- if (hand->d_type == DSVC_DHCPTAB)
- free_dtrec((dt_rec_t *)entryp);
- else
- free_dnrec((dn_rec_t *)entryp);
-}
-
-/*
- * Frees the list of records pointed to by listp.
- */
-void
-free_dd_list(dsvc_handle_t hand, void *listp)
-{
- if (DSVC_HANDLE_INVAL(hand) || listp == NULL)
- return;
-
- if (hand->d_type == DSVC_DHCPTAB)
- free_dtrec_list((dt_rec_list_t *)listp);
- else
- free_dnrec_list((dn_rec_list_t *)listp);
-}
-
-/*
- * Add the record newp to the DHCP container hand. newp's update signature
- * will be updated by the public layer module doing the update. Caller is
- * responsible for freeing newp if it was dynamically allocated.
- */
-int
-add_dd_entry(dsvc_handle_t hand, void *newp)
-{
- int error;
- void *unlock_cookie;
-
- if (DSVC_HANDLE_INVAL(hand))
- return (DSVC_INVAL);
-
- if (!validate_dd_entry(hand, newp, B_FALSE))
- return (DSVC_INVAL);
-
- if (hand->d_synch != NULL) {
- error = DSVC_SYNCH_WRLOCK(hand->d_synch, &unlock_cookie);
- if (error != DSVC_SUCCESS)
- return (error);
- }
-
- if (hand->d_type == DSVC_DHCPTAB)
- error = hand->d_api.add_dt(hand->d_hand, newp);
- else
- error = hand->d_api.add_dn(hand->d_hand, newp);
-
- if (hand->d_synch != NULL)
- (void) DSVC_SYNCH_UNLOCK(hand->d_synch, unlock_cookie);
-
- return (error);
-}
-
-/*
- * Modify the record origp with the record newp in the DHCP container hand.
- * newp's update signature will be updated by the public layer module doing
- * the update. Caller is responsible for freeing origp and/or newp if they
- * were dynamically allocated.
- */
-int
-modify_dd_entry(dsvc_handle_t hand, const void *origp, void *newp)
-{
- int error;
- void *unlock_cookie;
-
- if (DSVC_HANDLE_INVAL(hand))
- return (DSVC_INVAL);
-
- if (!validate_dd_entry(hand, origp, B_TRUE))
- return (DSVC_INVAL);
-
- if (!validate_dd_entry(hand, newp, B_FALSE))
- return (DSVC_INVAL);
-
- if (hand->d_synch != NULL) {
- error = DSVC_SYNCH_WRLOCK(hand->d_synch, &unlock_cookie);
- if (error != DSVC_SUCCESS)
- return (error);
- }
-
- if (hand->d_type == DSVC_DHCPTAB)
- error = hand->d_api.modify_dt(hand->d_hand, origp, newp);
- else
- error = hand->d_api.modify_dn(hand->d_hand, origp, newp);
-
- if (hand->d_synch != NULL)
- (void) DSVC_SYNCH_UNLOCK(hand->d_synch, unlock_cookie);
-
- return (error);
-}
-
-/*
- * Deletes the record referred to by entryp from the DHCP container hand.
- * Caller is responsible for freeing entryp if it was dynamically
- * allocated.
- */
-int
-delete_dd_entry(dsvc_handle_t hand, void *entryp)
-{
- int error;
- void *unlock_cookie;
-
- if (DSVC_HANDLE_INVAL(hand))
- return (DSVC_INVAL);
-
- if (!validate_dd_entry(hand, entryp, B_TRUE))
- return (DSVC_INVAL);
-
- if (hand->d_synch != NULL) {
- error = DSVC_SYNCH_WRLOCK(hand->d_synch, &unlock_cookie);
- if (error != DSVC_SUCCESS)
- return (error);
- }
-
- if (hand->d_type == DSVC_DHCPTAB)
- error = hand->d_api.delete_dt(hand->d_hand, entryp);
- else
- error = hand->d_api.delete_dn(hand->d_hand, entryp);
-
- if (hand->d_synch != NULL)
- (void) DSVC_SYNCH_UNLOCK(hand->d_synch, unlock_cookie);
-
- return (error);
-}
-
-/*
- * Validate that the DHCP network record `dn' is correctly formed; returns
- * B_TRUE if it is, B_FALSE if it's not. If `justkey' is set, then only
- * validate the key.
- */
-static boolean_t
-validate_dnrec(dsvc_handle_t hand, const dn_rec_t *dn, boolean_t justkey)
-{
- /* CIP must be on container's network */
- if (hand->d_conid.c_net.s_addr !=
- (dn->dn_cip.s_addr & hand->d_conid.c_mask.s_addr))
- return (B_FALSE);
-
- if (justkey)
- return (B_TRUE);
-
- if (dn->dn_cid_len < 1 || dn->dn_cid_len > DN_MAX_CID_LEN)
- return (B_FALSE);
-
- if ((dn->dn_flags & ~DN_FALL) != 0)
- return (B_FALSE);
-
- return (B_TRUE);
-}
-
-/*
- * Validate that the dhcptab record `dt' is correctly formed; returns
- * B_TRUE if it is, B_FALSE if it's not. If `justkey' is set, then only
- * validate the key.
- */
-/* ARGSUSED */
-static boolean_t
-validate_dtrec(dsvc_handle_t hand, const dt_rec_t *dt, boolean_t justkey)
-{
- return (dt->dt_type == DT_SYMBOL || dt->dt_type == DT_MACRO);
-}
-
-/*
- * Validate that a DHCP record of type `hand->d_type' is correctly formed;
- * returns B_TRUE if it is, B_FALSE if it's not. If `justkey' is set, then
- * only validate the key.
- */
-static boolean_t
-validate_dd_entry(dsvc_handle_t hand, const void *entryp, boolean_t justkey)
-{
- if (entryp == NULL)
- return (B_FALSE);
-
- if (hand->d_type == DSVC_DHCPTAB)
- return (validate_dtrec(hand, (dt_rec_t *)entryp, justkey));
- else if (hand->d_type == DSVC_DHCPNETWORK)
- return (validate_dnrec(hand, (dn_rec_t *)entryp, justkey));
-
- return (B_FALSE);
-}
-
-/*
- * Get the type of synchronization needed for this module and store in
- * `synchtypep'. Returns a DSVC_* code. This function is exported so that
- * dsvclockd(1M) can use it.
- */
-int
-module_synchtype(dsvc_datastore_t *ddp, dsvc_synchtype_t *synchtypep)
-{
- void *instance;
- dsvc_splapi_t api;
- dsvc_synchtype_t *dsvc_synchtypep;
-
- if (load_public_module(ddp, &instance, &api) != DSVC_SUCCESS)
- return (DSVC_INTERNAL);
-
- dsvc_synchtypep = dlsym(instance, "dsvc_synchtype");
- if (dsvc_synchtypep != NULL)
- *synchtypep = *dsvc_synchtypep;
- else
- *synchtypep = DSVC_SYNCH_NONE;
-
- (void) unload_public_module(&instance, &api);
-
- return (DSVC_SUCCESS);
-}
-
-/*
- * Initialize private-layer synchronization on handle `hand' for container
- * `conname'; `flags' is the same flags passed into open_dd(). If there's
- * no synchronization needed, always succeeds. Returns a DSVC_* code.
- */
-int
-synch_init(dsvc_handle_t hand, const char *conname, uint_t flags)
-{
- dsvc_synchtype_t synchtype;
- dsvc_synch_t *sp;
- int error;
- int (*mkloctoken)(const char *, char *, size_t);
-
- error = module_synchtype(&hand->d_desc, &synchtype);
- if (error != DSVC_SUCCESS)
- return (error);
-
- if (synchtype == DSVC_SYNCH_NONE)
- return (DSVC_SUCCESS);
-
- sp = malloc(sizeof (dsvc_synch_t));
- if (sp == NULL)
- return (DSVC_NO_MEMORY);
-
- sp->s_conname = strdup(conname);
- if (sp->s_conname == NULL) {
- free(sp);
- return (DSVC_NO_MEMORY);
- }
- sp->s_nonblock = flags & DSVC_NONBLOCK;
- sp->s_datastore = &hand->d_desc;
-
- mkloctoken = (int (*)())dlsym(hand->d_instance, "mkloctoken");
- if (mkloctoken == NULL) {
- (void) strlcpy(sp->s_loctoken, sp->s_datastore->d_location,
- sizeof (sp->s_loctoken));
- } else {
- error = mkloctoken(sp->s_datastore->d_location, sp->s_loctoken,
- sizeof (sp->s_loctoken));
- if (error != DSVC_SUCCESS) {
- free(sp->s_conname);
- free(sp);
- return (error);
- }
- }
-
- /*
- * The only synchtype supported is DSVC_SYNCH_DSVCD; if this
- * changes, we'll need to enhance this.
- */
- assert((synchtype & DSVC_SYNCH_STRATMASK) == DSVC_SYNCH_DSVCD);
- sp->s_ops = &dsvcd_synch_ops;
-
- error = DSVC_SYNCH_INIT(sp, synchtype & DSVC_SYNCH_FLAGMASK);
- if (error != DSVC_SUCCESS) {
- free(sp->s_conname);
- free(sp);
- return (error);
- }
-
- hand->d_synch = sp;
- return (DSVC_SUCCESS);
-}
-
-/*
- * Finish using private-layer synchronization on handle `hand'.
- */
-void
-synch_fini(dsvc_handle_t hand)
-{
- DSVC_SYNCH_FINI(hand->d_synch);
- free(hand->d_synch->s_conname);
- free(hand->d_synch);
- hand->d_synch = NULL;
-}