diff options
Diffstat (limited to 'usr/src/lib/libdhcpsvc/private/private.c')
| -rw-r--r-- | usr/src/lib/libdhcpsvc/private/private.c | 871 |
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; -} |
