Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial import of libisns, contributed to the NetBSD Foundation by

Wasabi Systems, Inc.

libisns(3) is an implementation of the iSNS protocol as defined in
IETF RFC 4171, exporting an API that simplifies Internet Storage Name
Service (iSNS) client implementations.
  • Loading branch information...
commit 5ef3cc9f304bbe48c8a3a3c9203782b63153c135 1 parent 37d11a4
agc authored
View
16 lib/libisns/Makefile
@@ -0,0 +1,16 @@
+# $NetBSD: Makefile,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $
+
+.include <bsd.own.mk>
+
+LIB= isns
+SRCS= isns.c isns_pdu.c isns_socketio.c isns_task.c isns_thread.c
+SRCS+= isns_util.c isns_fileio.c
+
+MAN= isns.3
+
+INCS= isns.h isns_defs.h
+INCSDIR=/usr/include
+
+WARNS= 4
+
+.include <bsd.lib.mk>
View
203 lib/libisns/isns.3
@@ -0,0 +1,203 @@
+.\" $NetBSD: isns.3,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $
+.\"
+.\" Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Wasabi Systems, Inc.
+.\"
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+.Dd October 1, 2009
+.Dt ISNS 3
+.Os
+.Sh NAME
+.Nm isns
+.Nd iSNS protocol support library
+.Sh LIBRARY
+.Lb libisns
+.Sh SYNOPSIS
+.In isns.h
+.Ft int
+.Fn isns_init "ISNS_HANDLE *h" "int is_server"
+.Ft void
+.Fn isns_stop "ISNS_HANDLE h"
+.Ft int
+.Fn isns_add_servercon "ISNS_HANDLE h" "int fd" "struct addrinfo *ai"
+.Ft int
+.Fn isns_init_reg_refresh "ISNS_HANDLE h" "const char *node" "int interval"
+.Ft ISNS_TRANS
+.Fn isns_new_trans "ISNS_HANDLE h" "uint16_t func_id" "uint16_t pdu_flags"
+.Ft int
+.Fn isns_add_tlv "ISNS_TRANS t" "uint32_t tag" "int data_len" "const void *data_p"
+.Ft int
+.Fn isns_add_string "ISNS_TRANS t" "uint32_t tag" "const char *s"
+.Ft int
+.Fn isns_send_trans "ISNS_TRANS t" "const struct timespec *timeout_p" "uint32_t *status_p"
+.Ft int
+.Fn isns_get_tlv "ISNS_TRANS t" "int which_tlv" "uint32_t *tag_p" "int data_len_p" "void **data_pp"
+.Ft void
+.Fn isns_free_trans "ISNS_TRANS t"
+.Sh DESCRIPTION
+The
+.Nm
+library exports an API that simplifies Internet Storage Name
+Service (iSNS) client implementations.
+The API defines a transactional model in support of:
+.Pp
+.Bl -bullet -width 3n -offset indent -compact
+.It
+generating iSNS messages composed of iSNS attributes expressed in
+Tag-Length-Value (TLV) data format
+.It
+submitting iSNS Protocol (iSNSP) messages
+.It
+optionally waiting for iSNSP responses
+.El
+.Pp
+.Nm
+does not currently support receipt of iSNS Heartbeat messages, State Change
+Notification (SCN) messages, or Entity Status Inquiry (ESI) messages.
+.Sh INITILAIZATION
+An iSNS client that uses
+.Nm
+must call
+.Fn isns_init
+to initialize the iSNS environment.
+This call will create a thread to handle client-server communication, and
+as such should only be called when thread creation is appropriate (such
+as after a daemonized program forks).
+.Pp
+The value passed as 'is_server' is used to set iSNSP message format Flags
+"Sender is the iSNS client" (bit position 16) and "Sender is the iSNS server"
+(bit position 17).
+For now the value 0 (zero) should be passed for
+'is_server'.
+The value returned in 'h' should be considered opaque by the caller.
+This value is passed unchanged to
+.Fn isns_add_servercon ,
+.Fn isns_init_reg_refresh ,
+.Fn isns_stop ,
+and
+.Fn isns_new_trans .
+.Pp
+.Fn isns_stop
+should be called when the iSNS environment is no longer needed.
+This call will kill any threads created by
+.Fn isns_init .
+.Sh CONFIGURATION
+Following initialization,
+.Fn isns_add_servercon
+should be used to make the iSNS environment aware of the iSNS
+server to which iSNSP queries and requests are to be sent.
+This routine should not be called by a program acting as an iSNS server.
+.Pp
+A connected TCP socket descriptor is passed as parameter 'fd'.
+Parameter 'ai' is the address of the remote TCP endpoint.
+It is included so that reconnection may be attempted by
+.Nm
+in the event that the TCP connection is broken.
+.Pp
+Certain iSNS servers will limit registration lifetimes, and will
+refresh registrations after any request from a given iSNS entity.
+The
+.Fn isns_init_reg_refresh
+function offers a way for
+.Nm
+to refresh registrations on behalf of the iSNS client.
+.Pp
+Parameter 'node' is the "iSCSI Name" attribute used for the periodic queries.
+It should be the name of an iSCSI node within the registered iSNS entity.
+The desired refresh interval, in seconds, is passed in parameter 'interval'.
+.Sh TRANSACTIONS
+.Fn isns_new_trans
+creates new iSNS transactions.
+.Pp
+Parameter 'func_id' is used as the iSNSP message id.
+Parameter 'pdu_flags' is used to set iSNSP message format Flags and is
+exposed to allow callers to set flag "Replace flag" (bit position 19).
+This provides callers with a way
+to specify whether a Device Attribute Registration Request is intended to
+update or replace an existing registration. This is currently the only use
+defined for parameter 'pdu_flags'.
+.Pp
+Once a new transaction has been created, callers can specify iSNS attributes
+used for registration and query requests.
+TLV data may be added using either
+.Fn isns_add_tlv
+or
+.Fn isns_add_string .
+.Pp
+Parameter 'tag' is the iSNS Tag corresponding to the attribute being added.
+Parameter 'data_len' is the length of the attribute value.
+Parameter 'data_p' references the attribute value.
+The caller does not need to handle iSNS attribute 4-byte alignment requirements.
+This is handled by the iSNS environment on behalf of the caller.
+.Fn isns_add_string
+may be used if the attribute value is a NUL terminated C string.
+.Pp
+Once a transaction has been populated with any required TLV data,
+.Fn isns_send_trans
+can be used to submit an iSNSP registration or query message.
+.Pp
+Callers that submit iSNSP query messages may need to wait for returned data.
+.Fn isns_send_trans
+supports bounded waits.
+Successful waits, those that do not time out, return the iSNSP response
+status code received in the iSNSP response message.
+If a wait does time out, the value of 'status_p' is undefined.
+Callers that do not need to wait for returned data can simply
+pass NULL for parameter 'timeout_p'.
+Callers should set parameter 'status_p' to NULL if not waiting.
+.Pp
+.Fn isns_get_tlv
+is used to retrieve TLV data returned in a transaction.
+The first call to
+.Fn isns_get_tlv
+should pass the value ISNS_TLV_FIRST for parameter 'which_tlv'.
+Each subsequent TLV can be retrieved by passing in ISNS_TLV_NEXT in
+place of ISNS_TLV_FIRST.
+.Pp
+When a caller is done with a transaction, having submitted either a
+registration or a query message and retrieved any returned TLV data,
+.Fn isns_free_trans()
+should be used to release resources used by the transaction.
+.Sh RETURN VALUES
+.Fn isns_init ,
+.Fn isns_add_servercon ,
+.Fn isns_init_reg_refresh ,
+.Fn isns_add_tlv ,
+.Fn isns_add_string ,
+and
+.Fn isns_send_trans
+return 0 on success, or -1 on failure.
+.Fn isns_new_trans
+returns 0 on success, or ISNS_INVALID_TRANS on failure.
+.Fn isns_get_tlv
+returns 0 on success, or ENOENT if there are no TLVs yo retrieve.
+.Sh HISTORY
+.Nm
+first appeared in
+.Nx 6.0 .
+The
+.Nm
+implementation was contributed to the NetBSD Foundation
+by Wasabi Systems, Inc.
View
239 lib/libisns/isns.c
@@ -0,0 +1,239 @@
+/* $NetBSD: isns.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $ */
+
+/*-
+ * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Wasabi Systems, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: isns.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $");
+
+/*
+ * isns.c
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/poll.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "isns.h"
+#include "isns_config.h"
+
+
+
+/*
+ * isns_init()
+ */
+int
+isns_init(ISNS_HANDLE *isns_handle_p, int is_server)
+{
+ struct isns_config_s *cfg_p;
+ int rval;
+
+ *isns_handle_p = NULL;
+
+ if ((cfg_p = isns_new_config()) == NULL) {
+ DBG("isns_init: error on isns_new_config()\n");
+ return ENOMEM;
+ }
+
+ cfg_p->is_server = is_server;
+ cfg_p->curtask_p = NULL;
+
+ if ((rval = pipe(cfg_p->pipe_fds)) != 0) {
+ DBG("isns_init: error on wepe_sys_pipe()\n");
+ isns_destroy_config(cfg_p);
+ return rval;
+ }
+
+ if ((cfg_p->kq = kqueue()) == -1) {
+ DBG("isns_init: error on kqueue()\n");
+ isns_destroy_config(cfg_p);
+ return -1;
+ }
+
+ rval = isns_change_kevent_list(cfg_p, (uintptr_t)cfg_p->pipe_fds[0],
+ EVFILT_READ, EV_ADD | EV_ENABLE, (int64_t)0,
+ (intptr_t)isns_kevent_pipe);
+ if (rval == -1) {
+ DBG("isns_init: error on isns_change_kevent_list() "
+ "for isns_kevent_pipe\n");
+ isns_destroy_config(cfg_p);
+ return rval;
+ }
+
+ isns_init_buffer_pool();
+ rval = isns_add_buffer_pool(ISNS_BUF_SIZE, ISNS_BUF_COUNT);
+ if (rval != 0) {
+ DBG("isns_init: error on isns_init_buffer_pool()\n");
+ isns_destroy_config(cfg_p);
+ return rval;
+ }
+ rval = isns_add_buffer_pool((int)ISNS_SMALL_BUF_SIZE, ISNS_SMALL_BUF_COUNT);
+ if (rval != 0) {
+ DBG("isns_init: error on isns_init_buffer_pool() [small]\n");
+ isns_destroy_config(cfg_p);
+ isns_destroy_buffer_pool();
+ return rval;
+ }
+
+ if ((rval = isns_thread_create(cfg_p)) != 0) {
+ DBG("isns_init: error on isns_thread_create()\n");
+ isns_destroy_config(cfg_p);
+ isns_destroy_buffer_pool();
+ return rval;
+ }
+
+ *isns_handle_p = (ISNS_HANDLE)cfg_p;
+
+ return 0;
+}
+
+
+/*
+ * isns_add_servercon()
+ */
+int
+isns_add_servercon(ISNS_HANDLE isns_handle, int fd, struct addrinfo *ai)
+{
+ struct isns_config_s *cfg_p;
+ struct isns_task_s *task_p;
+ struct addrinfo *ai_p;
+ size_t len;
+
+ if (isns_handle == ISNS_INVALID_HANDLE)
+ return EINVAL;
+
+ cfg_p = (struct isns_config_s *)isns_handle;
+
+ ai_p = (struct addrinfo *)isns_malloc(sizeof(struct addrinfo));
+ if (ai_p == NULL)
+ return ENOMEM;
+
+ ai_p->ai_flags = ai->ai_flags;
+ ai_p->ai_family = ai->ai_family;
+ ai_p->ai_socktype = ai->ai_socktype;
+ ai_p->ai_protocol = ai->ai_protocol;
+ ai_p->ai_addrlen = ai->ai_addrlen;
+ if (ai->ai_canonname != NULL) {
+ len = strlen(ai->ai_canonname);
+ ai_p->ai_canonname = (char *)isns_malloc(len + 1);
+ if (ai_p->ai_canonname == NULL) {
+ isns_free(ai_p);
+ return ENOMEM;
+ }
+ memset(ai_p->ai_canonname, '\0', len + 1);
+ strncpy(ai_p->ai_canonname, ai->ai_canonname, len);
+ } else
+ ai_p->ai_canonname = NULL;
+ if (ai->ai_addr != NULL) {
+ ai_p->ai_addr = (struct sockaddr *)isns_malloc(ai_p->
+ ai_addrlen);
+ if (ai_p->ai_addr == NULL) {
+ if (ai_p->ai_canonname != NULL)
+ isns_free(ai_p->ai_canonname);
+ isns_free(ai_p);
+ return ENOMEM;
+ }
+ memcpy(ai_p->ai_addr, ai->ai_addr, ai_p->ai_addrlen);
+ } else
+ ai_p->ai_addr = NULL;
+ ai_p->ai_next = NULL;
+
+ /* Build task and kick off task processing */
+ task_p = isns_new_task(cfg_p, ISNS_TASK_INIT_SOCKET_IO, 1);
+ task_p->var.init_socket_io.sd = fd;
+ task_p->var.init_socket_io.ai_p = ai_p;
+
+ isns_taskq_insert_head(cfg_p, task_p);
+ isns_issue_cmd(cfg_p, ISNS_CMD_PROCESS_TASKQ);
+ isns_wait_task(task_p, NULL);
+
+ return 0;
+}
+
+
+/*
+ * isns_init_reg_refresh()
+ */
+int
+isns_init_reg_refresh(ISNS_HANDLE isns_handle, const char *node, int interval)
+{
+ struct isns_config_s *cfg_p;
+ struct isns_task_s *task_p;
+ struct isns_refresh_s *ref_p;
+
+ if (isns_handle == ISNS_INVALID_HANDLE)
+ return EINVAL;
+
+ /* Build INIT_REFRESH task with info provided. */
+ cfg_p = (struct isns_config_s *)isns_handle;
+ task_p = isns_new_task(cfg_p, ISNS_TASK_INIT_REFRESH, 0);
+ if (task_p == NULL)
+ return ENOMEM;
+
+ ref_p = (struct isns_refresh_s *)
+ isns_malloc(sizeof(struct isns_refresh_s));
+ if (ref_p == NULL) {
+ isns_free_task(task_p);
+ return ENOMEM;
+ }
+
+ (void) snprintf(ref_p->node, sizeof(ref_p->node), "%.*s",
+ (int)sizeof(ref_p->node)-1, node);
+ ref_p->interval = interval;
+ ref_p->trans_p = NULL;
+ task_p->var.init_refresh.ref_p = ref_p;
+
+ isns_taskq_insert_tail(cfg_p, task_p);
+ isns_issue_cmd(cfg_p, ISNS_CMD_PROCESS_TASKQ);
+
+ return 0;
+}
+
+
+/*
+ * isns_stop()
+ */
+void isns_stop(ISNS_HANDLE isns_handle)
+{
+ struct isns_config_s *cfg_p = (struct isns_config_s *)isns_handle;
+
+ DBG("isns_stop: entered\n");
+
+ isns_issue_cmd(cfg_p, ISNS_CMD_STOP);
+
+ isns_thread_destroy(cfg_p);
+ isns_destroy_config(cfg_p);
+ isns_destroy_buffer_pool();
+}
View
67 lib/libisns/isns.h
@@ -0,0 +1,67 @@
+/* $NetBSD: isns.h,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $ */
+
+/*-
+ * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Wasabi Systems, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * isns.h
+ */
+
+#ifndef _ISNS_H_
+#define _ISNS_H_
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <netdb.h>
+#include <stdlib.h>
+
+typedef void (*ISNS_HANDLE);
+typedef void (*ISNS_TRANS);
+
+#define ISNS_INVALID_HANDLE (ISNS_HANDLE)NULL
+#define ISNS_INVALID_TRANS (ISNS_TRANS)NULL
+
+#define ISNS_TLV_FIRST 0
+#define ISNS_TLV_NEXT 1
+
+int isns_init(ISNS_HANDLE *, int);
+int isns_add_servercon(ISNS_HANDLE, int, struct addrinfo *);
+int isns_init_reg_refresh(ISNS_HANDLE, const char *, int);
+void isns_stop(ISNS_HANDLE);
+
+ISNS_TRANS isns_new_trans(ISNS_HANDLE, uint16_t, uint16_t);
+void isns_free_trans(ISNS_TRANS);
+int isns_send_trans(ISNS_TRANS, const struct timespec *, uint32_t *);
+int isns_add_tlv(ISNS_TRANS, uint32_t, int, const void *);
+int isns_get_tlv(ISNS_TRANS, int, uint32_t *, int *, void **);
+
+int isns_add_string(ISNS_TRANS, uint32_t, const char *);
+
+#endif /* !_ISNS_H_ */
View
86 lib/libisns/isns_config.h
@@ -0,0 +1,86 @@
+/* $NetBSD: isns_config.h,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $ */
+
+/*-
+ * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Wasabi Systems, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+/*
+ * isns_config.h
+ */
+
+#ifndef _ISNS_CONFIG_H_
+#define _ISNS_CONFIG_H_
+
+#ifdef ISNS_DEBUG
+#define DBG(...) do { printf(__VA_ARGS__); } while (/* CONSTCOND */0)
+#else
+#define DBG(...) do {} while (/* CONSTCOND */ 0)
+#endif
+
+#include "isns_fileio.h"
+#include "isns_pdu.h"
+#include "isns_socketio.h"
+#include "isns_thread.h"
+#include "isns_task.h"
+#include "isns_util.h"
+
+enum {
+ _ISNS_MUTEXATTR_TYPEMASK = 0x0000000f,
+ ISNS_MUTEX_TYPE_NORMAL = 0,
+ ISNS_MUTEX_TYPE_ERRORCHECK = 1,
+ ISNS_MUTEX_TYPE_RECURSIVE = 2,
+ ISNS_MUTEX_TYPE_ERRORABORT = 3
+};
+
+struct isns_config_s {
+ int kq;
+ int pipe_fds[2];
+
+ pthread_t *control_thread_p;
+
+ isns_socket_t sd;
+ int sd_connected;
+ struct addrinfo *ai_p;
+ struct isns_pdu_s *pdu_in_p;
+
+ pthread_mutex_t taskq_mutex;
+ struct isns_task_s *curtask_p;
+ SIMPLEQ_HEAD(isns_taskq_head_s, isns_task_s) taskq_head;
+
+ pthread_mutex_t trans_mutex;
+
+ int is_server;
+
+ struct isns_refresh_s *refresh_p;
+};
+
+#define isns_is_socket_init_done(_cfg_p) \
+ ((_cfg_p) == NULL ? 0 \
+ : (((struct isns_config_s *)(_cfg_p))->ai_p != NULL))
+
+
+#endif /* !_ISNS_CONFIG_H_ */
View
197 lib/libisns/isns_defs.h
@@ -0,0 +1,197 @@
+/* $NetBSD: isns_defs.h,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $ */
+
+/*-
+ * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Wasabi Systems, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _ISNS_DEFS_H_
+#define _ISNS_DEFS_H_
+
+/*
+ * enum of iSNS Registration, query, and response types
+ */
+
+typedef enum {
+ isnsp_DevAttrReg = 1,
+ isnsp_DevAttrQry,
+ isnsp_DevGetNext,
+ isnsp_DevDereg,
+ isnsp_SCNReg,
+ isnsp_SCNDereg,
+ isnsp_SCNEvent,
+ isnsp_SCN,
+ isnsp_DDReg,
+ isnsp_DDDereg,
+ isnsp_DDSReg,
+ isnsp_DDSDereg,
+ isnsp_ESI,
+ isnsp_Heartbeat, /* 0x000e */
+
+ /* Next few are iFCP only */
+ isnsp_RqstDomId = 0x0011,
+ isnsp_RlseDomId,
+ isnsp_GetDomId,
+
+ isnsp_DevAttrRegRsp = 0x8001,
+ isnsp_DevAttrQryRsp,
+ isnsp_DevGetNextRsp,
+ isnsp_DevDeregRsp,
+ isnsp_SCNregRsp,
+ isnsp_SCNDeregRsp,
+ isnsp_SCNeventRsp,
+ isnsp_SCNRsp,
+ isnsp_DDRegRsp,
+ isnsp_DDDeregRsp,
+ isnsp_DDSRegRsp,
+ isnsp_DDSDeregRsp,
+ isnsp_ESIRsp, /* 0x800d */
+
+ /* Next few are iFCP only */
+ isnsp_RqstDomIdRsp = 0x8011,
+ isnsp_RlseDomIdRsp,
+ isnsp_GetDomIdRsp
+} isnsp_func_id_t;
+
+/*
+ * enum of iSNS tag types
+ */
+
+typedef enum { /* Len Reg Key Query Key Val */
+ isnst_Delimiter = 0, /* 0 N/A N/A 0 */
+ isnst_EID, /* 4-256 1 1|2|16&17|32|64 1 */
+ isnst_EntProtocol, /* 4 1 1|2|16&17|32|64 2 */
+ isnst_MgtIPAddr, /* 16 1 1|2|16&17|32|64 3 */
+ isnst_Timestamp, /* 8 -- 1|2|16&17|32|64 4 */
+ isnst_ProtVersRange, /* 4 1 1|2|16&17|32|64 5 */
+ isnst_RegPeriod, /* 4 1 1|2|16&17|32|64 6 */
+ isnst_EntityIndex, /* 4 1 1|2|16&17|32|64 7 */
+ isnst_EntityNextIndex, /* 8 1 1|2|16&17|32|64 8 */
+ /* */
+ isnst_EntISAKMP_P1= 11, /* var 1 1|2|16&17|32|64 11 */
+ isnst_Certificate, /* var 1 1|2|16&17|32|64 12 */
+ /* */
+ isnst_PortalIPAddr= 16, /* 16 1 1|2|16&17|32|64 16 */
+ isnst_PortalPort, /* 4 1 1|2|16&17|32|64 17 */
+ isnst_SymbName, /* 4-256 16&17 1|16&17|32|64 18 */
+ isnst_ESIIntval, /* 4 16&17 1|16&17|32|64 19 */
+ isnst_ESIPort, /* 4 16&17 1|16&17|32|64 20 */
+ /* */
+ isnst_PortalIndex=22, /* 4 16&17 1|16&17|32|64 22 */
+ isnst_SCNPort, /* 4 16&17 1|16&17|32|64 23 */
+ isnst_PortalNextIndex, /* 4 -- 1|16&17|32|64 24 */
+ /* */
+ isnst_PortalSecBmap=27, /* 4 16&17 1|16&17|32|64 27 */
+ isnst_PortalISAKMP_P1, /* var 16&17 1|16&17|32|64 28 */
+ isnst_PortalISAKMP_P2, /* var 16&17 1|16&17|32|64 29 */
+ /* */
+ isnst_PortalCert = 31, /* var 16&17 1|16&17|32|64 31 */
+ isnst_iSCSIName, /* 4-224 1 1|16&17|32|33 32 */
+ isnst_iSCSINodeType, /* 4 32 1|16&17|32 33 */
+ isnst_iSCSIAlias, /* 4-256 32 1|16&17|32 34 */
+ isnst_iSCSISCNBmap, /* 4 32 1|16&17|32 35 */
+ isnst_iSCSINodeIndex, /* 4 32 1|16&17|32 36 */
+ isnst_WWNNToken, /* 8 32 1|16&17|32 37 */
+ isnst_iSCSINodeNextIdx, /* 4 -- 1|16&17|32 38 */
+ /* */
+ isnst_iSCSIAuthMethod=42,/* var 32 1|16&17|32 42 */
+ isnst_iSCSINodeCert, /* var 32 1|16&17|32 43 */
+ /* */
+ isnst_PGiSCSIName=48, /* 4-224 32|16&17 1|16&17|32|52 48 */
+ isnst_PGPortIPAddr, /* 16 32|16&17 1|16&17|32|52 49 */
+ isnst_PGPortIPPort, /* 4 32|16&17 1|16&17|32|52 50 */
+ isnst_PGTag, /* 4 32|16&17 1|16&17|32|52 51 */
+ isnst_PGIndex, /* 4 32|16&17 1|16&17|32|52 52 */
+ isnst_PGNextIndex, /* 4 -- 1|16&17|32|52 53 */
+ /* */
+ isnst_FCPortNameWWPN=64,/* 8 1 1|16&17|64|66|96|128
+ 64 */
+ isnst_FCPortID, /* 4 64 1|16&17|64 65 */
+ isnst_FCPortType, /* 4 64 1|16&17|64 66 */
+ isnst_FCSymbPortName, /* 4-256 64 1|16&17|64 67 */
+ isnst_FCFabricPortName, /* 8 64 1|16&17|64 68 */
+ isnst_FCHardAddr, /* 4 64 1|16&17|64 69 */
+ isnst_FCPortIPAddr, /* 16 64 1|16&17|64 70 */
+ isnst_FCClassOService, /* 4 64 1|16&17|64 71 */
+ isnst_FC4Types, /* 32 64 1|16&17|64 72 */
+ isnst_FC4Descr, /* 4-256 64 1|16&17|64 73 */
+ isnst_FC4Features, /* 128 64 1|16&17|64 74 */
+ isnst_iFCPSCNBmap, /* 4 64 1|16&17|64 75 */
+ isnst_iFCPPortRole, /* 4 64 1|16&17|64 76 */
+ isnst_PermPortName, /* 8 -- 1|16&17|64 77 */
+ /* */
+ isnst_PortCert = 83, /* var 64 1|16&17|64 83 */
+ /* */
+ isnst_FC4TypeCode = 95, /* 4 -- 1|16&17|64 95 */
+ isnst_FCNodeNameWWNN, /* 8 64 1|16&17|64|96 96 */
+ isnst_SymbNodeName, /* 4-256 96 64|96 97 */
+ isnst_NodeIPAddr, /* 16 96 64|96 98 */
+ isnst_NodeIPA, /* 8 96 64|96 99 */
+ isnst_NodeCert, /* var 96 64|96 100 */
+ isnst_ProxyiSCSIName, /* 4-256 96 64|96 101 */
+ /* Note: above really should be 4-224
+ * in the iSNS spec, but isn't */
+ /* */
+ isnst_SwitchName = 128, /* 8 128 128 128 */
+ isnst_PrefID, /* 4 128 128 129 */
+ isnst_AssignedID, /* 4 128 128 130 */
+ isnst_VirtFabricID, /* 4-256 128 128 131 */
+ /* */
+ isnst_iSNSSrvrVndOUI=256,/* 4 -- SOURCE Attr 256 */
+ /* */
+ isnst_DDS_ID=2049, /* 4 2049 1|32|64|2049|2065
+ 2049 */
+ isnst_DDS_SymName, /* 4-256 2049 2049 2050 */
+ isnst_DDS_Status, /* 4 2049 2049 2051 */
+ isnst_DDS_Next_ID, /* 4 -- 2049 2052 */
+ /* */
+ isnst_DD_ID = 2065, /* 4 2049 1|32|64|2049|2065
+ 2065 */
+ isnst_DD_SymName, /* 4-256 2065 2065 2066 */
+ isnst_DD_iSCSIIndex, /* 4 2065 2065 2067 */
+ isnst_DD_iSCSIName, /* 4-224 2065 2065 2068 */
+ isnst_DD_iFCPNode, /* 8 2065 2065 2069 */
+ isnst_DD_PortIndex, /* 4 2065 2065 2070 */
+ isnst_DD_PortIPAddr, /* 16 2065 2065 2071 */
+ isnst_DD_PortPort, /* 4 2065 2065 2072 */
+ isnst_DD_Features=2078, /* 4 2065 2065 2078 */
+ isnst_DD_Next_ID /* 4 -- 2065 2079 */
+} isnst_tag_type_t;
+
+/*
+ * iSNS PDU header flags
+ */
+
+#define ISNS_FLAG_FIRST_PDU (0x0400)
+#define ISNS_FLAG_LAST_PDU (0x0800)
+#define ISNS_FLAG_REPLACE_REG (0x1000)
+#define ISNS_FLAG_AUTH (0x2000)
+#define ISNS_FLAG_SND_SERVER (0x4000)
+#define ISNS_FLAG_SND_CLIENT (0x8000)
+
+
+#endif /* _ISNS_DEFS_H_ */
View
76 lib/libisns/isns_fileio.c
@@ -0,0 +1,76 @@
+/* $NetBSD: isns_fileio.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $ */
+
+/*-
+ * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Wasabi Systems, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: isns_fileio.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $");
+
+#include "isns.h"
+#include "isns_config.h"
+
+/*
+ * isns_file_writev()
+ */
+ssize_t
+isns_file_writev(int fd, const struct iovec *iov, int iovcnt)
+{
+ ssize_t rval;
+#if HAVE_WEPE
+ int error;
+
+ error = wepe_sys_writev(fd, iov, iovcnt, &rval);
+ if (error)
+ rval = -1;
+#else
+ rval = writev(fd, iov, iovcnt);
+#endif
+
+ return rval;
+}
+
+/*
+ * isns_file_readv()
+ */
+ssize_t
+isns_file_readv(int fd, const struct iovec *iov, int iovcnt)
+{
+ ssize_t rval;
+#if HAVE_WEPE
+ int error;
+
+ error = wepe_sys_readv(fd, iov, iovcnt, &rval);
+ if (error)
+ rval = -1;
+#else
+ rval = readv(fd, iov, iovcnt);
+#endif
+
+ return rval;
+}
View
47 lib/libisns/isns_fileio.h
@@ -0,0 +1,47 @@
+/* $NetBSD: isns_fileio.h,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $ */
+
+/*-
+ * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Wasabi Systems, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * isns_fileio.h
+ */
+
+#ifndef _ISNS_FILEIO_H
+#define _ISNS_FILEIO_H
+
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+extern ssize_t isns_file_writev(int, const struct iovec *, int);
+extern ssize_t isns_file_readv(int, const struct iovec *, int);
+
+
+#endif /* !_ISNS_FILEIO_H */
View
1,334 lib/libisns/isns_pdu.c
@@ -0,0 +1,1334 @@
+/* $NetBSD: isns_pdu.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $ */
+
+/*-
+ * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Wasabi Systems, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * isns_pdu.c
+ */
+
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: isns_pdu.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $");
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "isns.h"
+#include "isns_config.h"
+
+
+/*
+ * Local function prototypes.
+ */
+static struct isns_buffer_list_s *isns_lookup_buffer_list(int);
+
+static struct isns_pdu_s *isns_init_pdu(struct isns_buffer_s *,
+ struct isns_config_s *, uint16_t, uint16_t, uint16_t);
+static int isns_add_pdu_payload_data(struct isns_trans_s *, const void *, int);
+static void isns_get_tlv_info_advance(struct isns_get_tlv_info_s *);
+static int isns_get_tlv_uint32(struct isns_get_tlv_info_s *, uint32_t *);
+static int isns_get_tlv_data(struct isns_get_tlv_info_s *, int, void **);
+
+static void isns_add_pdu_list(struct isns_pdu_s **, struct isns_pdu_s *);
+static struct isns_buffer_s *isns_get_pdu_head_buffer(struct isns_pdu_s *);
+#if 0
+static struct isns_buffer_s *isns_get_pdu_tail_buffer(struct isns_pdu_s *);
+#endif
+static struct isns_buffer_s *isns_get_pdu_active_buffer(struct isns_pdu_s *);
+
+static uint32_t isns_get_next_trans_id(void);
+
+/*
+ * Buffer pool structures and global (static) var.
+ */
+struct isns_buffer_list_s {
+ int buf_size;
+ int alloc_count;
+ struct isns_buffer_s *head;
+ struct isns_buffer_list_s *next;
+};
+
+struct isns_buffer_pool_s {
+ int active;
+ struct isns_buffer_list_s *list_p;
+ pthread_mutex_t mutex;
+};
+
+static struct isns_buffer_pool_s G_buffer_pool;
+
+
+/*
+ * isns_init_buffer_pool - initialize buffer pool for use
+ */
+void
+isns_init_buffer_pool()
+{
+ pthread_mutexattr_t mutexattr;
+
+ DBG("isns_init_buffer_pool: entered\n");
+
+ assert(!G_buffer_pool.active);
+
+ pthread_mutexattr_init(&mutexattr);
+ pthread_mutexattr_settype(&mutexattr, ISNS_MUTEX_TYPE_NORMAL);
+ pthread_mutex_init(&G_buffer_pool.mutex, &mutexattr);
+
+ G_buffer_pool.active = 1;
+}
+
+
+/*
+ * isns_lookup_buffer_list - locates the pool buffer list for the buf_size
+ * specified.
+ *
+ * Returns: pointer to list in pool containing buf_size buffers
+ * NULL if no list for size indicated exists
+ */
+static struct isns_buffer_list_s *
+isns_lookup_buffer_list(int buf_size)
+{
+ struct isns_buffer_list_s *list_p;
+
+ /*
+ * WARNING: G_buffer_pool.mutex MUST already be locked.
+ */
+
+ list_p = G_buffer_pool.list_p;
+ while (list_p != NULL) {
+ if (list_p->buf_size == buf_size)
+ break;
+ list_p = list_p->next;
+ }
+
+ return list_p;
+}
+
+
+/*
+ * isns_add_buffer_pool - allocates buffers of in pool
+ *
+ * If a list containing buf_size buffers already exists in pool, additional
+ * buffers are added (allocated) to the list.
+ */
+int
+isns_add_buffer_pool(int buf_size, int count)
+{
+ struct isns_buffer_list_s *list_p, *p, *p_next;
+ struct isns_buffer_s *buf_p;
+ int n;
+
+ DBG("isns_add_buffer_pool: buf_size=%d, count=%d\n", buf_size, count);
+
+ assert(G_buffer_pool.active);
+
+ /* Make our buffer lengths always a multiple of 4. */
+ buf_size = (buf_size + 0x03) & ~0x03;
+
+ /*
+ * Lookup existing list for size specified. If no exists, allocate
+ * a new list and initialize.
+ */
+ pthread_mutex_lock(&G_buffer_pool.mutex);
+ list_p = isns_lookup_buffer_list(buf_size);
+ if (list_p == NULL) {
+ pthread_mutex_unlock(&G_buffer_pool.mutex);
+ list_p = (struct isns_buffer_list_s *)
+ isns_malloc(sizeof(struct isns_buffer_list_s));
+ if (list_p == NULL) {
+ DBG("isns_add_buffer_pool: error on isns_malloc()\n");
+ return ENOMEM;
+ }
+ list_p->buf_size = buf_size;
+ list_p->alloc_count = 0;
+ list_p->head = NULL;
+ }
+
+ /* If this is a new list, insert into pool in buf_size order. */
+ if (list_p->alloc_count == 0) {
+ pthread_mutex_lock(&G_buffer_pool.mutex);
+ if (G_buffer_pool.list_p == NULL) {
+ G_buffer_pool.list_p = list_p;
+ list_p->next = NULL;
+ } else if (G_buffer_pool.list_p->buf_size > buf_size) {
+ list_p->next = G_buffer_pool.list_p;
+ G_buffer_pool.list_p = list_p;
+ } else {
+ p = G_buffer_pool.list_p;
+ while (p->next != NULL) {
+ p_next = p->next;
+ if (p_next->buf_size > buf_size) {
+ p->next = list_p;
+ list_p->next = p_next;
+ break;
+ }
+ p = p->next;
+ }
+ if (p->next == NULL) {
+ p->next = list_p;
+ list_p->next = NULL;
+ }
+ }
+ }
+
+ /* Allocate (possibly additional) buffers for list. */
+ for (n = 0; n < count; n++) {
+ buf_p = (struct isns_buffer_s *)
+ isns_malloc(buf_size + sizeof(struct isns_buffer_s));
+ if (buf_p == NULL)
+ break;
+ buf_p->next = list_p->head;
+ list_p->head = buf_p;
+ }
+ list_p->alloc_count += n;
+ pthread_mutex_unlock(&G_buffer_pool.mutex);
+
+ DBG("isns_init_buffer_pool: %d %d-byte buffers allocated\n",
+ n, buf_size);
+
+ return (n > 0 ? 0 : ENOMEM);
+}
+
+
+/*
+ * isns_destroy_buffer_pool - destroys previously allocated buffer pool
+ */
+void
+isns_destroy_buffer_pool(void)
+{
+ struct isns_buffer_list_s *list_p;
+ struct isns_buffer_s *buf_p;
+#ifdef ISNS_DEBUG
+ char dbg_buffer[1024] = { 0 };
+#endif
+
+ DBG("isns_destroy_buffer_pool: entered\n");
+
+ assert(G_buffer_pool.active);
+
+ pthread_mutex_lock(&G_buffer_pool.mutex);
+ while (G_buffer_pool.list_p != NULL) {
+ list_p = G_buffer_pool.list_p;
+ while (list_p->head != NULL) {
+ buf_p = list_p->head;
+ list_p->head = buf_p->next;
+ list_p->alloc_count--;
+ isns_free(buf_p);
+ }
+#ifdef ISNS_DEBUG
+ if (list_p->alloc_count > 0) {
+ snprintf(&dbg_buffer[(int) strlen(dbg_buffer)],
+ (sizeof(dbg_buffer) - strlen(dbg_buffer)),
+ "isns_destroy_buffer_pool: "
+ "%d %d-byte buffer(s) not freed\n",
+ list_p->alloc_count, list_p->buf_size);
+ }
+#endif
+ G_buffer_pool.list_p = list_p->next;
+ isns_free(list_p);
+ }
+ G_buffer_pool.active = 0;
+
+ pthread_mutex_unlock(&G_buffer_pool.mutex);
+ pthread_mutex_destroy(&G_buffer_pool.mutex);
+
+ DBG(dbg_buffer);
+}
+
+
+/*
+ * isns_new_buffer - allocates a new ISNS buffer
+ *
+ * Typically, the buffer is returned from the pool, but if no free buffers
+ * are available in the pool, or a buf size larger than the largest pool buffer
+ * size is requested, a normal malloc is used to allocate the buffer. The
+ * buffer type is recorded so that a subsequent isns_free_buffer will correctly
+ * free the buffer or return it to the pool.
+ */
+struct isns_buffer_s *
+isns_new_buffer(int buf_size)
+{
+ struct isns_buffer_list_s *list_p;
+ struct isns_buffer_s *buf_p;
+ int buf_type;
+
+ if (buf_size == 0)
+ buf_size = ISNS_BUF_SIZE;
+ buf_p = NULL;
+
+ pthread_mutex_lock(&G_buffer_pool.mutex);
+ list_p = G_buffer_pool.list_p;
+ while (list_p != NULL) {
+ if ((list_p->head != NULL)
+ && (list_p->buf_size >= buf_size)) {
+ buf_p = list_p->head;
+ list_p->head = buf_p->next;
+ buf_size = list_p->buf_size;
+ buf_type = ISNS_BUF_POOL;
+ break;
+ }
+ list_p = list_p->next;
+ }
+ pthread_mutex_unlock(&G_buffer_pool.mutex);
+
+ if (buf_p == NULL) {
+ buf_p = (struct isns_buffer_s *)isns_malloc(
+ buf_size + sizeof(struct isns_buffer_s));
+ buf_type = ISNS_BUF_MALLOC;
+ }
+
+ if (buf_p != NULL)
+ ISNS_INIT_BUFFER(buf_p, buf_size, buf_type);
+
+ DBG("isns_new_buffer: %p (buf_size=%d, type=%d)\n", buf_p, buf_size,
+ buf_type);
+
+ return buf_p;
+}
+
+
+/*
+ * isns_free_buffer - free a ISNS buffer
+ */
+void
+isns_free_buffer(struct isns_buffer_s *buf_p)
+{
+ struct isns_buffer_list_s *list_p;
+
+ DBG("isns_free_buffer: %p (type=%d, alloc_len=%d)\n",
+ buf_p, (buf_p == NULL ? 0 : buf_p->buf_type),
+ (buf_p == NULL ? 0 : buf_p->alloc_len));
+
+ if (buf_p != NULL) {
+ switch (buf_p->buf_type) {
+ case ISNS_BUF_POOL:
+ /* Return buffer to proper pool list. */
+ pthread_mutex_lock(&G_buffer_pool.mutex);
+ list_p = isns_lookup_buffer_list((int)buf_p->alloc_len);
+ if (list_p != NULL) {
+ buf_p->next = list_p->head;
+ list_p->head = buf_p;
+ }
+ pthread_mutex_unlock(&G_buffer_pool.mutex);
+ break;
+ case ISNS_BUF_MALLOC:
+ /* Malloc allocated buf, so free normally. */
+ isns_free(buf_p);
+ break;
+ case ISNS_BUF_STATIC:
+ /* Static buf with no allocation, so do nothing here. */
+ break;
+ }
+ }
+}
+
+
+/*
+ * isns_new_trans - create a new ISNS transaction
+ */
+ISNS_TRANS
+isns_new_trans(ISNS_HANDLE isns_handle, uint16_t func_id, uint16_t pdu_flags)
+{
+ struct isns_trans_s *trans_p;
+ struct isns_pdu_s *pdu_p;
+ struct isns_buffer_s *buf_p;
+
+ if (isns_handle == ISNS_INVALID_HANDLE) {
+ DBG("isns_new_trans: error - handle=%p\n", isns_handle);
+ return ISNS_INVALID_TRANS;
+ }
+
+ buf_p = isns_new_buffer((int)sizeof(struct isns_trans_s));
+ if (buf_p == NULL) {
+ DBG("isns_new_trans: error on isns_new_buffer()\n");
+ return ISNS_INVALID_TRANS;
+ }
+
+ trans_p = (struct isns_trans_s *)isns_buffer_data(buf_p, 0);
+ trans_p->id = isns_get_next_trans_id();
+ trans_p->func_id = func_id;
+ trans_p->flags = 0;
+ trans_p->cfg_p = (struct isns_config_s *)isns_handle;
+ trans_p->pdu_req_list = NULL;
+ trans_p->pdu_rsp_list = NULL;
+ trans_p->disconnect_cnt = 0;
+
+ trans_p->get_tlv_info.pdu_p = NULL;
+ trans_p->get_tlv_info.buf_p = NULL;
+ trans_p->get_tlv_info.extra_buf_list = NULL;
+ trans_p->get_tlv_info.buf_ofs = 0;
+
+ buf_p->cur_len = sizeof(struct isns_trans_s);
+
+ /*
+ * Mask off all but the AUTH and possibly REPLACE_REG pdu flags. Then,
+ * set the appropriate server/client sender flag. The first/last PDU
+ * flags will be set when the PDU is sent.
+ */
+ if (func_id == isnsp_DevAttrReg)
+ pdu_flags &= (ISNS_FLAG_AUTH | ISNS_FLAG_REPLACE_REG);
+ else
+ pdu_flags &= ISNS_FLAG_AUTH;
+
+ if (trans_p->cfg_p->is_server)
+ pdu_flags |= ISNS_FLAG_SND_SERVER;
+ else
+ pdu_flags |= ISNS_FLAG_SND_CLIENT;
+
+ pdu_p = isns_new_pdu(trans_p->cfg_p, trans_p->id, func_id, pdu_flags);
+ if (pdu_p == NULL) {
+ DBG("isns_new_trans: error on isns_new_pdu()\n");
+ isns_free_buffer(buf_p);
+ return ISNS_INVALID_TRANS;
+ }
+
+ isns_add_pdu_request((ISNS_TRANS)trans_p, pdu_p);
+
+ DBG("isns_new_trans: %p\n", trans_p);
+
+ return (ISNS_TRANS)trans_p;
+}
+
+
+/*
+ * isns_free_trans - free ISNS transaction created with isns_new_trans
+ */
+void
+isns_free_trans(ISNS_TRANS trans)
+{
+ struct isns_trans_s *trans_p;
+ struct isns_pdu_s *pdu_p;
+ struct isns_buffer_s *buf_p, *free_buf_p;
+ uint32_t trans_flags;
+
+ DBG("isns_free_trans: %p\n", trans);
+
+ if (trans != ISNS_INVALID_TRANS) {
+ trans_p = (struct isns_trans_s *)trans;
+
+ trans_flags = isns_set_trans_flags(trans_p,
+ ISNS_TRANSF_FREE_WHEN_COMPLETE);
+
+ if ((trans_flags & ISNS_TRANSF_COMPLETE) == 0) {
+ DBG("isns_free_trans: deferred - trans not complete\n");
+ return;
+ }
+
+ DBG("isns_free_trans: pdu_req_list=%p\n",
+ trans_p->pdu_req_list);
+ while ((pdu_p = trans_p->pdu_req_list) != NULL) {
+ trans_p->pdu_req_list = pdu_p->next;
+ isns_free_pdu(pdu_p);
+ }
+ DBG("isns_free_trans: pdu_rsp_list=%p\n",
+ trans_p->pdu_rsp_list);
+ while ((pdu_p = trans_p->pdu_rsp_list) != NULL) {
+ trans_p->pdu_rsp_list = pdu_p->next;
+ isns_free_pdu(pdu_p);
+ }
+ DBG("isns_free_trans: extra_buf_list=%p\n",
+ trans_p->get_tlv_info.extra_buf_list);
+ buf_p = trans_p->get_tlv_info.extra_buf_list;
+ while (buf_p != NULL) {
+ free_buf_p = buf_p;
+ buf_p = buf_p->next;
+ isns_free_buffer(free_buf_p);
+ }
+
+ DBG("isns_free_trans: freeing base trans buffer\n");
+ buf_p = ((struct isns_buffer_s *)(void *)(trans_p))-1;
+ isns_free_buffer(buf_p);
+ }
+}
+
+
+/*
+ * isns_send_trans - send ISNS transaction PDU(s) and optionally wait
+ *
+ * If a successful wait occurs (i.e., the transaction completes without
+ * a timeout), then the response PDU status is place in *status_p. For
+ * all other cases, the data returned in *status_p is undefined.
+ *
+ */
+int
+isns_send_trans(ISNS_TRANS trans, const struct timespec *timeout_p,
+ uint32_t *status_p)
+{
+ struct isns_trans_s *trans_p;
+ struct isns_pdu_s *pdu_p;
+ int rval;
+
+ trans_p = (struct isns_trans_s *)trans;
+
+ DBG("isns_send_trans: trans_p=%p, timeout_p=%p\n", trans_p, timeout_p);
+
+ if (status_p != NULL)
+ *status_p = 0;
+
+ if (!isns_is_socket_init_done(trans_p->cfg_p)) {
+ DBG("isns_send_trans: socket not initialized\n");
+ isns_complete_trans(trans_p);
+ return EINVAL;
+ }
+
+ if ((pdu_p = isns_get_pdu_request(trans)) == NULL) {
+ DBG("isns_send_trans: no request PDU\n");
+ return EINVAL;
+ }
+
+ /* Set the FIRST_PDU flag in the first PDU. */
+ pdu_p->hdr.flags |= ISNS_FLAG_FIRST_PDU;
+
+ /* Set our PDU sequence numbers for the PDU chain. */
+ while (pdu_p->next != NULL) {
+ pdu_p->next->hdr.seq_id = pdu_p->hdr.seq_id + 1;
+ pdu_p = pdu_p->next;
+ }
+
+ /* Set the LAST_PDU flag in the last PDU. */
+ pdu_p->hdr.flags |= ISNS_FLAG_LAST_PDU;
+
+ rval = isns_send_pdu(trans, isns_get_pdu_request(trans), timeout_p);
+ if ((rval == 0) && (status_p != NULL))
+ isns_get_pdu_response_status(trans, status_p);
+
+ return rval;
+}
+
+
+
+void
+isns_complete_trans(struct isns_trans_s *trans_p)
+{
+ uint32_t flags;
+
+ DBG("isns_complete_trans: trans_p=%p\n", trans_p);
+
+ flags = isns_set_trans_flags(trans_p, ISNS_TRANSF_COMPLETE);
+
+ if ((flags & ISNS_TRANSF_FREE_WHEN_COMPLETE) != 0)
+ isns_free_trans(trans_p);
+}
+
+
+int
+isns_abort_trans(struct isns_config_s *cfg_p, uint16_t trans_id)
+{
+ struct isns_task_s *task_p;
+
+ /* First, look at current task. */
+ if (((task_p = cfg_p->curtask_p) != NULL)
+ && (task_p->task_type == ISNS_TASK_SEND_PDU)
+ && (task_p->var.send_pdu.trans_p->id == trans_id)) {
+ isns_complete_trans(task_p->var.send_pdu.trans_p);
+ isns_end_task(task_p);
+ return 0;
+ }
+
+ /* If not current task, look in task queue. */
+ task_p = isns_taskq_remove_trans(cfg_p, trans_id);
+ if (task_p) {
+ isns_complete_trans(task_p->var.send_pdu.trans_p);
+ isns_end_task(task_p);
+ return 0;
+ }
+
+ return EINVAL;
+}
+
+/*
+ * isns_add_string - add a TLV which is a C string
+ *
+ * Wrapper around isns_add_tlv()
+ */
+int
+isns_add_string(ISNS_TRANS trans, uint32_t tag, const char *s)
+{
+ /* Add string, including required NULL. */
+ return isns_add_tlv(trans, tag, (int)strlen(s)+1, s);
+}
+
+
+/*
+ * isns_add_tlv - adds a TLV to an existing transaction
+ */
+int
+isns_add_tlv(ISNS_TRANS trans, uint32_t tag, int data_len, const void *data_p)
+{
+ struct isns_trans_s *trans_p;
+ uint8_t tlv_buf[ISNS_TLV_HDR_SIZE];
+ int rval;
+
+ DBG("isns_add_tlv: trans=%p, tag=%d, data_len=%d, data_p=%p\n",
+ trans, tag, data_len, data_p);
+
+ if (trans == ISNS_INVALID_TRANS) {
+ DBG("isns_add_tlv: error - trans=%p\n", trans);
+ return EINVAL;
+ }
+
+ if ((data_len > 0) && (data_p == NULL)) {
+ DBG("isns_add_tlv: error data_len=%d, data_p=%p\n",
+ data_len, data_p);
+ return EINVAL;
+ }
+
+ /* Set tag, length in header buffer and add to PDU payload data. */
+ trans_p = (struct isns_trans_s *)trans;
+ ISNS_TLV_SET_TAG(tlv_buf, tag);
+ ISNS_TLV_SET_LEN(tlv_buf, ISNS_PAD4_LEN(data_len));
+ rval = isns_add_pdu_payload_data(trans_p, tlv_buf, ISNS_TLV_HDR_SIZE);
+
+ /* If header added okay, add value portion to PDU payload data. */
+ if ((rval == 0) && (data_len > 0))
+ rval = isns_add_pdu_payload_data(trans_p, data_p, data_len);
+
+ return rval;
+}
+
+
+/*
+ * isns_get_tlv - get TLV value from response PDU for transaction
+ *
+ * returns:
+ * 0 - success
+ * ENOENT - no (more) TLVs in this transaction
+ * EINVAL - invalid arg
+ * EPERM - operation not permitted - transaction not complete
+ * ENOMEM - could not allocate storage for spanning TLV data
+ */
+int
+isns_get_tlv(ISNS_TRANS trans, int which_tlv, uint32_t *tag_p, int *data_len_p,
+ void **data_pp)
+{
+ struct isns_trans_s *trans_p;
+ struct isns_get_tlv_info_s *info_p;
+ struct isns_pdu_s *pdu_p;
+ int rval;
+
+ if (trans == ISNS_INVALID_TRANS) {
+ DBG("isns_get_tlv: error - trans=%p\n", trans);
+ return EINVAL;
+ }
+
+ trans_p = (struct isns_trans_s *)trans;
+ if ((isns_get_trans_flags(trans_p) & ISNS_TRANSF_COMPLETE) == 0) {
+ DBG("isns_get_tlv: error - trans not complete\n");
+ return EPERM;
+ }
+
+ /* Get response PDU for this transaction. */
+ pdu_p = isns_get_pdu_response(trans_p);
+ if (pdu_p == NULL) {
+ DBG("isns_get_tlv: error - no response PDU in transaction\n");
+ return EINVAL;
+ }
+
+ if (pdu_p->payload_p->cur_len == 0) {
+ DBG("isns_get_tlv: error - zero length PDU payload\n");
+ return EINVAL;
+ }
+
+ /* If get_tlv_info unset, treat ISNS_TLV_NEXT as ISNS_TLV_FIRST. */
+ info_p = &trans_p->get_tlv_info;
+ if ((which_tlv == ISNS_TLV_NEXT) && (info_p->pdu_p == NULL))
+ which_tlv = ISNS_TLV_FIRST;
+
+ /*!!! make sure PDU uses TLVs here */
+
+ switch (which_tlv) {
+ case ISNS_TLV_NEXT:
+ /* For next TLV, nothing to do here - use get_tlv_info as-is. */
+ break;
+
+ case ISNS_TLV_FIRST:
+ /* For first TLV, reset get_tlv_info. */
+ info_p->pdu_p = pdu_p;
+ info_p->buf_p = isns_get_pdu_head_buffer(pdu_p);
+ info_p->buf_ofs = 4;
+ break;
+
+ default:
+ DBG("isns_get_tlv: invalid arg (which_tlv=%d)\n", which_tlv);
+ return EINVAL;
+ }
+
+ /*
+ * Get the type, length, and data (value) for the TLV. The get calls
+ * below will advance the pointers in get_tlv_info_s *info_p. Note that
+ * if the get of the TAG type fails, ENOENT is returned indicating that
+ * no more TLVs exist for this request PDU.
+ */
+ if ((rval = isns_get_tlv_uint32(info_p, tag_p)) != 0) {
+ DBG("isns_get_tlv: error on isns_get_tlv_uint32() tag\n");
+ return ENOENT;
+ }
+
+ if ((rval = isns_get_tlv_uint32(info_p, (uint32_t *)data_len_p)) != 0) {
+ DBG("isns_get_tlv: error on isns_get_tlv_uint32() data len\n");
+ return rval;
+ }
+
+ rval = isns_get_tlv_data(info_p, *data_len_p, data_pp);
+ if (rval != 0) {
+ DBG("isns_get_tlv: error on isns_get_tlv_data()\n");
+ return rval;
+ }
+
+ return 0;
+}
+
+
+/*
+ * isns_set_trans_flags - sets flag bit(s) in transaction flags member
+ */
+uint32_t
+isns_set_trans_flags(struct isns_trans_s *trans_p, uint32_t flags)
+{
+ pthread_mutex_lock(&trans_p->cfg_p->trans_mutex);
+ trans_p->flags |= flags;
+ flags = trans_p->flags;
+ pthread_mutex_unlock(&trans_p->cfg_p->trans_mutex);
+
+ return flags;
+}
+
+
+/*
+ * isns_add_pdu_request - adds PDU to transaction request PDU list
+ */
+void
+isns_add_pdu_request(struct isns_trans_s *trans_p, struct isns_pdu_s *pdu_p)
+{
+ DBG("isns_add_pdu_request: trans_p=%p, pdu_p=%p\n", trans_p, pdu_p);
+
+ isns_add_pdu_list(&trans_p->pdu_req_list, pdu_p);
+}
+
+
+/*
+ * isns_add_pdu_response - adds PDU to transaction response PDU list
+ */
+void
+isns_add_pdu_response(struct isns_trans_s *trans_p, struct isns_pdu_s *pdu_p)
+{
+ DBG("isns_add_pdu_response: trans_p=%p, pdu_p=%p\n", trans_p, pdu_p);
+
+ isns_add_pdu_list(&trans_p->pdu_rsp_list, pdu_p);
+}
+
+
+/*
+ * isns_get_pdu_request_tail - returns last PDU in request PDU chain
+ */
+struct isns_pdu_s *
+isns_get_pdu_request_tail(struct isns_trans_s *trans_p)
+{
+ struct isns_pdu_s *pdu_p;
+
+ if ((pdu_p = isns_get_pdu_request(trans_p)) != NULL) {
+ while (pdu_p->next != NULL)
+ pdu_p = pdu_p->next;
+ }
+
+ return pdu_p;
+}
+
+
+/*
+ * isns_new_pdu - allocates a new PDU and assigns funtion ID and flags
+ */
+struct isns_pdu_s *
+isns_new_pdu(struct isns_config_s *cfg_p, uint16_t trans_id, uint16_t func_id,
+ uint16_t flags)
+{
+ struct isns_buffer_s *buf_p;
+
+ /*
+ * Allocate a buffer at least large enough for our isns_pdu_s struct
+ * and the embedded isns_buffer_s struct for the PDU payload data and 4
+ * bytes of actual payload data.
+ */
+ buf_p = isns_new_buffer(/* CONSTCOND */(int)MAX(ISNS_BUF_SIZE,
+ sizeof(struct isns_pdu_s) + sizeof(struct isns_buffer_s) + 4));
+ if (buf_p == NULL) {
+ DBG("isns_new_pdu: error on isns_new_buffer()\n");
+ return NULL;
+ }
+
+ return isns_init_pdu(buf_p, cfg_p, trans_id, func_id, flags);
+}
+
+
+/*
+ * isns_free_pdu - frees a PDU and all associated buffers
+ */
+void
+isns_free_pdu(struct isns_pdu_s *pdu_p)
+{
+ struct isns_buffer_s *buf_p, *free_buf_p;
+
+ DBG("isns_free_pdu: %p\n", pdu_p);
+
+ if (pdu_p != NULL) {
+ /* Free all payload buffers. */
+ buf_p = pdu_p->payload_p;
+ while (buf_p != NULL) {
+ free_buf_p = buf_p;
+ buf_p = buf_p->next;
+ isns_free_buffer(free_buf_p);
+ }
+ /*
+ * Get a pointer to the ISNS buffer in which this PDU is
+ * contained, and then free it.
+ */
+ buf_p = ((struct isns_buffer_s *)(void *)(pdu_p))-1 ;
+ isns_free_buffer(buf_p);
+ }
+}
+
+
+/*
+ * isns_send_pdu - initiates the send PDU task
+ */
+int
+isns_send_pdu(ISNS_TRANS trans, struct isns_pdu_s *pdu_p,
+ const struct timespec *timeout_p)
+{
+ struct isns_trans_s *trans_p;
+ struct isns_task_s* task_p;
+ int rval;
+
+ if (trans == ISNS_INVALID_TRANS) {
+ DBG("isns_send_pdu: error - trans=%p\n", trans);
+ return EINVAL;
+ }
+
+ if (pdu_p == NULL) {
+ DBG("isns_send_pdu: error - pdu_p=%p\n", pdu_p);
+ return EINVAL;
+ }
+
+ trans_p = (struct isns_trans_s *)trans;
+
+ /* Build SEND_PDU task, insert on queue and issue command. */
+ task_p = isns_new_task(pdu_p->cfg_p, ISNS_TASK_SEND_PDU,
+ (timeout_p != NULL));
+ task_p->var.send_pdu.trans_p = trans_p;
+ task_p->var.send_pdu.pdu_p = pdu_p;
+
+ isns_taskq_insert_tail(pdu_p->cfg_p, task_p);
+
+ isns_issue_cmd(pdu_p->cfg_p, ISNS_CMD_PROCESS_TASKQ);
+
+ if (timeout_p == NULL)
+ rval = 0;
+ else {
+ rval = isns_wait_task(task_p, timeout_p);
+ if (rval == ETIMEDOUT) {
+ DBG("isns_send_pdu: "
+ "timeout on isns_wait_task() trans_id=%d\n",
+ trans_p->id);
+
+ isns_issue_cmd_with_data(task_p->cfg_p,
+ ISNS_CMD_ABORT_TRANS, (void *)&trans_p->id,
+ (int)sizeof(trans_p->id));
+ }
+ }
+
+ return rval;
+}
+
+
+/*
+ * isns_init_pdu - initialize ISNS buffer to be a PDU
+ */
+static struct isns_pdu_s *
+isns_init_pdu(struct isns_buffer_s *buf_p, struct isns_config_s *cfg_p,
+ uint16_t trans_id, uint16_t func_id, uint16_t flags)
+{
+ struct isns_pdu_s *pdu_p;
+
+ /* The config and buffer pointers must be valid here. */
+ assert(cfg_p != NULL);
+ assert(buf_p != NULL);
+
+ /* The PDU starts at offset 0 for the ISNS buffer data. */
+ pdu_p = isns_buffer_data(buf_p, 0);
+ buf_p->cur_len = sizeof(struct isns_pdu_s);
+
+ /* Assign PDU members. */
+ pdu_p->cfg_p = cfg_p;
+ pdu_p->hdr.isnsp_version = ISNSP_VERSION;
+ pdu_p->hdr.func_id = func_id;
+ pdu_p->hdr.payload_len = 0;
+ pdu_p->hdr.flags = flags;
+ pdu_p->hdr.trans_id = trans_id;
+ pdu_p->hdr.seq_id = 0;
+ pdu_p->byteorder_host = 1;
+ pdu_p->next = NULL;
+
+ /*
+ * The PDU payload buffer starts after the PDU struct portion in the
+ * ISNS buffer passed in to this function. So, assign the payload_p
+ * pointer accordingly, and then init the buffer with the proper length
+ * and ISNS_BUF_STATIC type.
+ */
+ pdu_p->payload_p = (struct isns_buffer_s *)
+ isns_buffer_data(buf_p, buf_p->cur_len);
+ ISNS_INIT_BUFFER(pdu_p->payload_p, (unsigned)(buf_p->alloc_len -
+ sizeof(struct isns_pdu_s) - sizeof(struct isns_buffer_s)),
+ ISNS_BUF_STATIC);
+
+ DBG("isns_init_pdu: %p\n", pdu_p);
+
+ return pdu_p;
+}
+
+
+/*
+ * isns_add_pdu_payload_data - add data to PDU payload
+ */
+static int
+isns_add_pdu_payload_data(struct isns_trans_s *trans_p, const void *data_p,
+ int len)
+{
+ struct isns_pdu_s *pdu_p, *new_pdu_p;
+ struct isns_buffer_s *buf_p, *new_buf_p;
+ const uint8_t *src_p;
+ uint8_t *dst_p;
+ int pad_bytes;
+
+ /* Get the request PDU for this transaction. */
+ if ((pdu_p = isns_get_pdu_request_tail(trans_p)) == NULL) {
+ DBG("isns_add_pdu_payload_data: no request PDU\n");
+ return EINVAL;
+ }
+ /* Get the active buffer for this PDU (where data should be copied). */
+ buf_p = isns_get_pdu_active_buffer(pdu_p);
+
+ /* Set up source and destination pointers. Calculate pad bytes. */
+ src_p = data_p;
+ dst_p = isns_buffer_data(buf_p, buf_p->cur_len);
+ pad_bytes = ISNS_PAD4_BYTES(len);
+
+ /*
+ * Move data from source to PDU buffer(s), allocated new pdus and
+ * buffers as necessary to accomodate the data.
+ */
+ while (len--) {
+ /* If at max for one PDU payload, add a new PDU. */
+ if (pdu_p->hdr.payload_len == ISNS_MAX_PDU_PAYLOAD) {
+ new_pdu_p = isns_new_pdu(trans_p->cfg_p,
+ trans_p->id, trans_p->func_id, pdu_p->hdr.flags);
+ if (new_pdu_p == NULL)
+ return ENOMEM;
+ isns_add_pdu_request(trans_p, new_pdu_p);
+ pdu_p = new_pdu_p;
+ buf_p = pdu_p->payload_p;
+ dst_p = isns_buffer_data(buf_p, 0);
+ }
+ /* If at end of current buffer, add a new buffer. */
+ if (buf_p->cur_len == buf_p->alloc_len) {
+ if (buf_p->next != NULL)
+ buf_p = buf_p->next;
+ else {
+ new_buf_p = isns_new_buffer(0);
+ if (new_buf_p == NULL)
+ return ENOMEM;
+ buf_p->next = new_buf_p;
+ buf_p = new_buf_p;
+ }
+ dst_p = isns_buffer_data(buf_p, 0);
+ }
+ pdu_p->hdr.payload_len++;
+ buf_p->cur_len++;
+ *dst_p++ = *src_p++;
+ }
+
+ /*
+ * Since the buffer alloc length is always a multiple of 4, we are
+ * guaranteed to have enough room for the pad bytes.
+ */
+ if (pad_bytes > 0) {
+ pdu_p->hdr.payload_len += pad_bytes;
+ buf_p->cur_len += pad_bytes;
+ while (pad_bytes--)
+ *dst_p++ = 0;
+ }
+
+ return 0;
+}
+
+
+/*
+ * isns_get_tlv_info_advance - advances pdu/buffer pointers if at end of
+ * current buffer.
+ */
+static void
+isns_get_tlv_info_advance(struct isns_get_tlv_info_s *info_p)
+{
+ if ((info_p->buf_p != NULL) &&
+ (info_p->buf_ofs == (int)info_p->buf_p->cur_len)) {
+ info_p->buf_p = info_p->buf_p->next;
+ info_p->buf_ofs = 0;
+ }
+
+ if ((info_p->buf_p == NULL) && (info_p->pdu_p->next != NULL)) {
+ info_p->pdu_p = info_p->pdu_p->next;
+ info_p->buf_p = isns_get_pdu_head_buffer(info_p->pdu_p);
+ info_p->buf_ofs = 0;
+ }
+}
+
+
+/*
+ * isns_get_tlv_uint32 - retrieve host-ordered uint32_t from PDU buffer at
+ * starting offset and adjusts isns_get_tlv_info
+ * pointers accordingly.
+ */
+static int
+isns_get_tlv_uint32(struct isns_get_tlv_info_s *info_p, uint32_t *uint32_p)
+{
+ /* Advance to next buffer/pdu (if necessary). */
+ isns_get_tlv_info_advance(info_p);
+
+ if ((info_p->buf_p == NULL) ||
+ ((info_p->buf_ofs + 4) > (int)info_p->buf_p->cur_len)) {
+ DBG("isns_get_tlv_uint32: end of buffer reached\n");
+ return EFAULT;
+ }
+
+ *uint32_p = ntohl(*(uint32_t *)isns_buffer_data(info_p->buf_p,
+ info_p->buf_ofs));
+ info_p->buf_ofs += 4;
+
+ return 0;
+}
+
+
+/*
+ * isns_get_tlv_data - retrieves data from PDU buffer at starting offset
+ * for TLV data contained in specified isns_get_tlv_info.
+ */
+static int
+isns_get_tlv_data(struct isns_get_tlv_info_s *info_p, int data_len,
+ void **data_pp)
+{
+ struct isns_buffer_s *extra_buf_p;
+ struct isns_get_tlv_info_s gti;
+ uint8_t *data_p, *extra_data_p;
+ int bytes_remaining, cbytes;
+
+ /* First, NULL return data pointer. */
+ *data_pp = NULL;
+
+ /* Advance to next buffer/pdu (if necessary). */
+ isns_get_tlv_info_advance(info_p);
+
+ /* Make sure we have a current get tlv info buffer. */
+ if (info_p->buf_p == NULL) {
+ DBG("isns_get_tlv_data: no next buffer\n");
+ return EFAULT;
+ }
+
+ /* Get pointer into buffer where desired TLV resides. */
+ data_p = isns_buffer_data(info_p->buf_p, info_p->buf_ofs);
+
+ /* TLV data completely resides in current buffer. */
+ if ((info_p->buf_ofs + data_len) <= (int)info_p->buf_p->cur_len) {
+ info_p->buf_ofs += data_len;
+ *data_pp = data_p;
+ return 0;
+ }
+
+ /*
+ * TLV data extends into next buffer so an "extra" buffer is allocated
+ * that is large enough to hold the entire data value. The extra buffer
+ * is added to the transaction's extra buffer list so we can free it
+ * when the transaction is freed.
+ */
+
+ if ((extra_buf_p = isns_new_buffer(data_len)) == NULL) {
+ DBG("isns_get_tlv_data: error on isns_new_buffer()\n");
+ return ENOMEM;
+ }
+ if (info_p->extra_buf_list == NULL)
+ info_p->extra_buf_list = extra_buf_p;
+ else {
+ extra_buf_p->next = info_p->extra_buf_list;
+ info_p->extra_buf_list = extra_buf_p;
+ }
+
+ /* Setup to copy data bytes out to extra buffer. */
+ gti = *info_p;
+ extra_data_p = isns_buffer_data(extra_buf_p, 0);
+ bytes_remaining = data_len;
+
+ while (bytes_remaining > 0) {
+ /*
+ * Advance to next buffer/pdu (if necessary), using local copy
+ * of the get_tlv_info structure.
+ */
+ isns_get_tlv_info_advance(&gti);
+ if (gti.buf_p == NULL) {
+ DBG("isns_get_tlv_data: no next buffer\n");
+ return EFAULT;
+ }
+
+ data_p = isns_buffer_data(gti.buf_p, gti.buf_ofs);
+
+ cbytes = MIN(bytes_remaining, ((int)gti.buf_p->cur_len - gti.buf_ofs));
+ bytes_remaining -= cbytes;
+ gti.buf_ofs += cbytes;
+ while (cbytes--)
+ *extra_data_p++ = *data_p++;
+ }
+
+ /* Update isns_get_tlv_info with our local copy. */
+ *info_p = gti;
+
+ /* Assign return data pointer. */
+ *data_pp = isns_buffer_data(extra_buf_p, 0);
+
+ return 0;
+}
+
+
+/*
+ * isns_get_pdu_response_status - returns status in PDU response
+ *
+ * Returns: 0 - success
+ * EPERM - operation not permitted, trans not complete
+ * EINVAL - invalid trans PDU response/payload
+ */
+int
+isns_get_pdu_response_status(struct isns_trans_s *trans_p, uint32_t *status_p)
+{
+ struct isns_pdu_s *pdu_p;
+
+ if ((isns_get_trans_flags(trans_p) & ISNS_TRANSF_COMPLETE) == 0)
+ return EPERM;
+
+ pdu_p = isns_get_pdu_response(trans_p);
+ if ((pdu_p == NULL)
+ || (pdu_p->payload_p == NULL)
+ || (pdu_p->payload_p->cur_len < 4))
+ return EINVAL;
+
+ *status_p = htonl(*(uint32_t *)isns_buffer_data(pdu_p->payload_p, 0));
+
+ return 0;
+}
+
+
+/*
+ * isns_add_pdu_list - adds pdu to specified pdu list
+ */
+static void
+isns_add_pdu_list(struct isns_pdu_s **list_pp, struct isns_pdu_s *pdu_p)
+{
+ struct isns_pdu_s *p, *p_prev;
+
+
+ if (*list_pp == NULL) {
+ *list_pp = pdu_p;
+ pdu_p->next = NULL;
+ return;
+ }
+
+ p = *list_pp;
+ while (p != NULL) {
+ if (pdu_p->hdr.seq_id < p->hdr.seq_id) {
+ if (p == *list_pp) {
+ *list_pp = pdu_p;
+ pdu_p->next = p;
+ } else {
+ p_prev = *list_pp;
+ while (p_prev->next != p)
+ p_prev = p_prev->next;
+ p_prev->next = pdu_p;
+ pdu_p->next = p;
+ }
+
+ return;
+ }
+ p = p->next;
+ }
+
+ /* pdu_p->hdr.seq_id > hdr.seq_id of all list elements */
+ p = *list_pp;
+ while (p->next != NULL)
+ p = p->next;
+ p->next = pdu_p;
+ pdu_p->next = NULL;
+}
+
+
+/*
+ * isns_get_pdu_head_buffer - returns PDU payload head buffer
+ */
+static struct isns_buffer_s *
+isns_get_pdu_head_buffer(struct isns_pdu_s *pdu_p)
+{
+ return pdu_p->payload_p;
+}
+
+
+#if 0
+/*
+ * isns_get_pdu_tail_buffer - returns PDU payload tail buffer
+ */
+static struct isns_buffer_s *
+isns_get_pdu_tail_buffer(struct isns_pdu_s *pdu_p)
+{
+ struct isns_buffer_s *buf_p;
+
+ buf_p = pdu_p->payload_p;
+ if (buf_p != NULL)
+ while (buf_p->next != NULL) buf_p = buf_p->next;
+
+ return buf_p;
+}
+#endif
+
+
+/*
+ * isns_get_pdu_active_buffer - returns PDU payload "active buffer where the
+ * next TLV/data should be written
+ */
+static struct isns_buffer_s *
+isns_get_pdu_active_buffer(struct isns_pdu_s *pdu_p)
+{
+ struct isns_buffer_s *buf_p;
+
+ buf_p = pdu_p->payload_p;
+ while ((buf_p->next != NULL) && (buf_p->cur_len == buf_p->alloc_len)) {
+ buf_p = buf_p->next;
+ }
+
+ return buf_p;
+}
+
+
+/*
+ * isns_get_next_trans_id - returns next ISNS transaction ID to use
+ */
+static uint32_t
+isns_get_next_trans_id(void)
+{
+ static int trans_id = 1;
+
+ return trans_id++;
+}
+
+
+#ifdef ISNS_DEBUG
+/*
+ * isns_dump_pdu - dumps PDU contents
+ */
+void
+isns_dump_pdu(struct isns_pdu_s *pdu_p)
+{
+ int n, pos;
+ struct isns_buffer_s *buf_p;
+ uint8_t *p;
+ char text[17];
+
+ if (pdu_p == NULL) {
+ DBG("isns_dump_pdu: pdu_p is NULL\n");
+ return;
+ }
+
+ DBG("pdu header:\n");
+ if (pdu_p->byteorder_host) {
+ DBG("ver=0x%04X, func=%d(%s), len=%d, flags=0x%04X, trans=%d, "
+ "seq=%d\n",
+ pdu_p->hdr.isnsp_version,
+ pdu_p->hdr.func_id & ~0x8000,
+ (pdu_p->hdr.func_id & 0x8000 ? "rsp" : "req"),
+ pdu_p->hdr.payload_len,
+ pdu_p->hdr.flags,
+ pdu_p->hdr.trans_id,
+ pdu_p->hdr.seq_id);
+ } else {
+ DBG("ver=0x%04X, func=%d(%s), len=%d, flags=0x%04X, trans=%d, "
+ "seq=%d\n",
+ isns_ntohs(pdu_p->hdr.isnsp_version),
+ isns_ntohs(pdu_p->hdr.func_id) & ~0x8000,
+ (pdu_p->hdr.func_id & 0x0080 ? "rsp" : "req"),
+ isns_ntohs(pdu_p->hdr.payload_len),
+ isns_ntohs(pdu_p->hdr.flags),
+ isns_ntohs(pdu_p->hdr.trans_id),
+ isns_ntohs(pdu_p->hdr.seq_id));
+ }
+
+ DBG("pdu buffers:\n");
+ buf_p = pdu_p->payload_p;
+ while (buf_p != NULL) {
+ DBG("[%p]: alloc_len=%d, cur_len=%d\n",
+ buf_p, buf_p->alloc_len, buf_p->cur_len);
+ buf_p = buf_p->next;
+ }
+
+ DBG("pdu payload:\n");
+ buf_p = pdu_p->payload_p;
+ if (buf_p == NULL) {
+ DBG("<none>\n");
+ return;
+ }
+
+ pos = 0;
+ memset(text, 0, 17);
+ while (buf_p != NULL) {
+ p = isns_buffer_data(buf_p, 0);
+ for (n = 0; n < buf_p->cur_len; n++) {
+ DBG("%02X ", *p);
+ text[pos] = (isprint(*p) ? *p : '.');
+ pos++;
+ p++;
+
+ if ((pos % 16) == 0) {
+ DBG(" %s\n", text);
+ memset(text, 0, 17);
+ pos = 0;
+ }
+ }
+ buf_p = buf_p->next;
+ }
+
+ if ((pos % 16) != 0)
+ DBG("%*c %s\n", (16 - (pos % 16)) * 3, ' ', text);
+}
+#endif /* ISNS_DEBUG */
View
222 lib/libisns/isns_pdu.h
@@ -0,0 +1,222 @@
+/* $NetBSD: isns_pdu.h,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $ */
+
+/*-
+ * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Wasabi Systems, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * isns_pdu.h
+ */
+
+#ifndef _ISNS_PDU_H_
+#define _ISNS_PDU_H_
+
+#include <pthread.h>
+
+#include "isns_defs.h"
+
+#define ISNSP_VERSION (0x0001)
+
+/*
+ * Max PDU payload length (MUST be <= 65532 and a multiple of 4).
+ */
+#define ISNS_MAX_PDU_PAYLOAD 65532
+
+/*
+ * ISNS buffer pool defines.
+ */
+#define ISNS_BUF_SIZE 1024
+#define ISNS_BUF_COUNT 32
+
+#define ISNS_SMALL_BUF_SIZE \
+ (/* CONSTCOND */MAX(sizeof(struct isns_task_s), sizeof(struct isns_trans_s)))
+#define ISNS_SMALL_BUF_COUNT 32
+
+#define ISNS_BUF_POOL 1
+#define ISNS_BUF_MALLOC 2
+#define ISNS_BUF_STATIC 3
+
+/*
+ * ISNS_INIT_BUFFER - initialize buffer (pointer) provided as an isns_buffer_s,
+ * setting the length and type specified, and initializing
+ * other members to appropriate values.
+ */
+#define ISNS_INIT_BUFFER(_bufp, _len, _type) \
+ do if ((_bufp) != NULL) { \
+ ((struct isns_buffer_s *)(_bufp))->cur_len = 0; \
+ ((struct isns_buffer_s *)(_bufp))->alloc_len = (_len); \
+ ((struct isns_buffer_s *)(_bufp))->alloc_len &= ~0x03; \
+ ((struct isns_buffer_s *)(_bufp))->buf_type = (_type); \
+ ((struct isns_buffer_s *)(_bufp))->next = NULL; \
+ } while (/* CONSTCOND */0)
+
+
+/*
+ * ISNS buffer struct - used for trans, pdu, payload allocations in libisns.
+ */
+struct isns_buffer_s {
+ uint32_t cur_len;
+ uint32_t alloc_len;
+ int buf_type;
+
+ struct isns_buffer_s *next;
+};
+
+#define isns_buffer_data(_bufp, _ofs) \
+ (void *)(((uint8_t *)(void *)(_bufp+1))+(_ofs))
+
+void isns_init_buffer_pool(void);
+int isns_add_buffer_pool(int, int);
+void isns_destroy_buffer_pool(void);
+struct isns_buffer_s *isns_new_buffer(int);
+void isns_free_buffer(struct isns_buffer_s *);
+
+
+
+/*
+ * TLV buffer access/manipulation-related macros.
+ */
+#define ISNS_TLV_HDR_SIZE 8
+
+#define ISNS_PAD4_LEN(n) (uint32_t)(((n)+3) & ~0x03)
+#define ISNS_PAD4_BYTES(n) ((4 - ((n) & 0x03)) & 0x03)
+
+#define ISNS_TLV_TAG_REF(_buf) \
+ (*(uint32_t *)(void *)(_buf))
+#define ISNS_TLV_GET_TAG(_buf) \
+ isns_ntohl(ISNS_TLV_TAG_REF(_buf))
+#define ISNS_TLV_SET_TAG(_buf, _tag) \
+ do { \
+ ISNS_TLV_TAG_REF(_buf) = isns_htonl(_tag); \
+ } while (/* CONSTCOND */0)
+
+#define ISNS_TLV_LEN_REF(_buf) \
+ (*(uint32_t *)(void *)((uint8_t *)(_buf)+4))
+#define ISNS_TLV_GET_LEN(_buf) \
+ isns_ntohl(ISNS_TLV_LEN_REF(_buf))
+#define ISNS_TLV_SET_LEN(_buf, _len) \
+ do { \
+ ISNS_TLV_LEN_REF(_buf) = isns_htonl(_len); \
+ } while (/* CONSTCOND */0)
+
+#define ISNS_TLV_DATA_PTR(_buf) \
+ ((void *)((uint8_t *)(_buf)+8))
+
+
+/*
+ * ISNS transaction and PDU structs.
+ */
+
+#define ISNS_TRANSF_COMPLETE 0x000000001
+#define ISNS_TRANSF_FREE_WHEN_COMPLETE 0x000000002
+
+
+struct isns_refresh_s {
+ char node[225];
+ int interval;
+
+ struct isns_trans_s *trans_p;
+};
+
+struct isns_get_tlv_info_s {
+ struct isns_pdu_s *pdu_p;
+ struct isns_buffer_s *buf_p;
+ struct isns_buffer_s *extra_buf_list;
+ int buf_ofs;
+};
+
+struct isns_trans_s {
+ uint16_t id;
+ uint16_t func_id;
+ uint32_t flags;
+ struct isns_config_s *cfg_p;
+
+ struct isns_get_tlv_info_s get_tlv_info;
+
+ struct isns_pdu_s *pdu_req_list;
+ struct isns_pdu_s *pdu_rsp_list;
+
+ uint16_t disconnect_cnt;
+};
+
+struct isns_pdu_hdr_s {
+ uint16_t isnsp_version __attribute__ ((packed));
+ uint16_t func_id __attribute__ ((packed));
+ uint16_t payload_len __attribute__ ((packed));
+ uint16_t flags __attribute__ ((packed));
+ uint16_t trans_id __attribute__ ((packed));
+ uint16_t seq_id __attribute__ ((packed));
+};
+
+struct isns_pdu_s {
+ struct isns_config_s *cfg_p;
+ struct isns_pdu_hdr_s hdr;
+ int byteorder_host;
+ struct isns_buffer_s *payload_p;
+ struct isns_pdu_s *next;
+};
+
+
+#define isns_get_pdu_request(_trans) \
+ (((_trans) == ISNS_INVALID_TRANS) \
+ ? NULL : ((struct isns_trans_s *)(_trans))->pdu_req_list)
+
+#define isns_get_pdu_response(_trans) \
+ (((_trans) == ISNS_INVALID_TRANS) \
+ ? NULL : ((struct isns_trans_s *)(_trans))->pdu_rsp_list)
+
+#define isns_get_next_pdu(_pdu) \
+ (((_pdu) == NULL) ? NULL : ((struct isns_pdu_s *)(_pdu))->next)
+
+#define isns_get_trans_flags(_trans) \
+ isns_set_trans_flags((_trans), 0)
+
+
+void isns_complete_trans(struct isns_trans_s *);
+int isns_abort_trans(struct isns_config_s *, uint16_t);
+
+uint32_t isns_set_trans_flags(struct isns_trans_s *, uint32_t);
+void isns_add_pdu_request(struct isns_trans_s *, struct isns_pdu_s *);
+void isns_add_pdu_response(struct isns_trans_s *, struct isns_pdu_s *);
+struct isns_pdu_s *isns_get_pdu_request_tail(struct isns_trans_s *);
+int isns_get_pdu_response_status(struct isns_trans_s *, uint32_t *);
+
+struct isns_pdu_s *isns_new_pdu(struct isns_config_s *, uint16_t, uint16_t,
+ uint16_t);
+void isns_free_pdu(struct isns_pdu_s *);
+int isns_send_pdu(ISNS_TRANS, struct isns_pdu_s *, const struct timespec *);
+
+#ifdef ISNS_DEBUG
+#define DUMP_PDU(_pdu) isns_dump_pdu(_pdu)
+void isns_dump_pdu(struct isns_pdu_s *);
+#else
+#define DUMP_PDU(_pdu)
+#endif
+
+
+#endif /* !_ISNS_PDU_H_ */
View
102 lib/libisns/isns_socketio.c
@@ -0,0 +1,102 @@
+/* $NetBSD: isns_socketio.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $ */
+
+/*-
+ * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Wasabi Systems, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: isns_socketio.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $");
+
+
+/*
+ * isns_socketio.c
+ */
+
+#include "isns.h"
+#include "isns_config.h"
+
+#include <unistd.h>
+
+
+/*
+ * isns_socket_create()
+ */
+int
+isns_socket_create(isns_socket_t *s, int domain, int type)
+{
+#if HAVE_WEPE
+ return (wepe_sys_socket(domain, type, 0, s));
+#else
+ return *s = socket(domain, type, 0);
+#endif
+}
+
+/*
+ * isns_socket_connect()
+ */
+int
+isns_socket_connect(isns_socket_t s, const struct sockaddr *name, socklen_t
+ namelen)
+{
+#if HAVE_WEPE
+ return (wepe_sys_connect(s, name, namelen));
+#else
+ return connect(s, name, namelen);
+#endif
+}
+
+/*
+ * isns_socket_close()
+ */
+int
+isns_socket_close(isns_socket_t s)
+{
+#if HAVE_WEPE
+ return wepe_sys_close(s);
+#else
+ return close(s);
+#endif
+}