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.
This commit is contained in:
agc 2011-01-16 01:22:50 +00:00
parent d31dbd7578
commit dc2ecebec9
19 changed files with 4229 additions and 0 deletions

16
lib/libisns/Makefile Normal file
View File

@ -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>

203
lib/libisns/isns.3 Normal file
View File

@ -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.

239
lib/libisns/isns.c Normal file
View File

@ -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();
}

67
lib/libisns/isns.h Normal file
View File

@ -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_ */

86
lib/libisns/isns_config.h Normal file
View File

@ -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_ */

197
lib/libisns/isns_defs.h Normal file
View File

@ -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_ */

76
lib/libisns/isns_fileio.c Normal file
View File

@ -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;
}

47
lib/libisns/isns_fileio.h Normal file
View File

@ -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 */

1334
lib/libisns/isns_pdu.c Normal file

File diff suppressed because it is too large Load Diff

222
lib/libisns/isns_pdu.h Normal file
View File

@ -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_ */

102
lib/libisns/isns_socketio.c Normal file
View File

@ -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
}
/*
* isns_socket_writev()
*/
ssize_t
isns_socket_writev(isns_socket_t s, const struct iovec *iov, int iovcnt)
{
return isns_file_writev(s, iov, iovcnt);
}
/*
* isns_socket_readv()
*/
ssize_t
isns_socket_readv(isns_socket_t s, const struct iovec *iov, int iovcnt)
{
return isns_file_readv(s, iov, iovcnt);
}

View File

@ -0,0 +1,56 @@
/* $NetBSD: isns_socketio.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_socketio.h
*/
#ifndef _ISNS_SOCKETIO_H
#define _ISNS_SOCKETIO_H
#include <sys/socket.h>
#include <netinet/in.h>
typedef int isns_socket_t;
struct isns_srv_addr_s {
struct sockaddr_in serv;
socklen_t namelen;
};
extern int isns_socket_create(isns_socket_t *, int, int);
extern int isns_socket_connect(isns_socket_t, const struct sockaddr *,
socklen_t);
extern int isns_socket_close(isns_socket_t);
extern ssize_t isns_socket_writev(isns_socket_t, const struct iovec *, int);
extern ssize_t isns_socket_readv(isns_socket_t, const struct iovec *, int);
#endif /* !_ISNS_SOCKETIO_H */

520
lib/libisns/isns_task.c Normal file
View File

@ -0,0 +1,520 @@
/* $NetBSD: isns_task.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_task.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $");
/*
* isns_task.c
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "isns.h"
#include "isns_config.h"
static struct iovec write_buf[2 + (ISNS_MAX_PDU_PAYLOAD / ISNS_BUF_SIZE) +
((ISNS_MAX_PDU_PAYLOAD % ISNS_BUF_SIZE) != 0)];
static isns_task_handler isns_task_discover_server;
static isns_task_handler isns_task_reconnect_server;
static isns_task_handler isns_task_send_pdu;
static isns_task_handler isns_task_init_socket_io;
static isns_task_handler isns_task_init_refresh;
void
isns_run_task(struct isns_task_s *task_p)
{
static isns_task_handler *task_dispatch_table[ISNS_NUM_TASKS] = {
isns_task_discover_server,
isns_task_reconnect_server,
isns_task_send_pdu,
isns_task_init_socket_io,
isns_task_init_refresh
};
DBG("isns_run_task: task_type=%d\n", task_p->task_type);
if (task_p->task_type < ARRAY_ELEMS(task_dispatch_table))
task_dispatch_table[task_p->task_type](task_p);
else
DBG("isns_run_task: unknown task type=%d\n", task_p->task_type);
}
int
isns_wait_task(struct isns_task_s *task_p, const struct timespec *timeout_p)
{
struct timeval tv_now;
struct timespec ts_abstime;
int rval;
DBG("isns_wait_task: waitable=%d\n", task_p->waitable);
if (!task_p->waitable)
return EPERM;
pthread_mutex_lock(&task_p->wait_mutex);
if (timeout_p == NULL) {
rval = pthread_cond_wait(&task_p->wait_condvar,
&task_p->wait_mutex);
} else {
gettimeofday(&tv_now, NULL);
TIMEVAL_TO_TIMESPEC(&tv_now, &ts_abstime);
timespecadd(&ts_abstime, timeout_p, &ts_abstime);
rval = pthread_cond_timedwait(&task_p->wait_condvar,
&task_p->wait_mutex, &ts_abstime);
}
pthread_mutex_unlock(&task_p->wait_mutex);
isns_free_task(task_p);
DBG("isns_wait_task: wait done (rval=%d)\n", rval);
return rval;
}
void
isns_end_task(struct isns_task_s *task_p)
{
DBG("isns_end_task: %p\n", task_p);
if (task_p == task_p->cfg_p->curtask_p)
task_p->cfg_p->curtask_p = NULL;
if (task_p->waitable)
pthread_cond_signal(&task_p->wait_condvar);
isns_free_task(task_p);
}
static void
isns_task_discover_server(struct isns_task_s *task_p)
{
/* discover server here */
DBG("isns_task_discover_server: entered\n");
isns_end_task(task_p);
}
/*
* isns_task_reconnect_server()
*/
static void
isns_task_reconnect_server(struct isns_task_s *task_p)
{
struct addrinfo *ai_p;
int rv;
DBG("isns_task_reconnect_server: entered\n");
ai_p = task_p->var.reconnect_server.ai_p;
rv = isns_socket_create(&(task_p->cfg_p->sd), ai_p->ai_family,
ai_p->ai_socktype);
if (rv != 0)
return;
rv = isns_socket_connect(task_p->cfg_p->sd, ai_p->ai_addr,
ai_p->ai_addrlen);
if (rv != 0) {
/* Add ISNS_EVT_TIMER_RECON to kqueue */
rv = isns_change_kevent_list(task_p->cfg_p,
(uintptr_t)ISNS_EVT_TIMER_RECON, EVFILT_TIMER, EV_ADD,
(int64_t)ISNS_EVT_TIMER_RECON_PERIOD_MS,
(intptr_t)isns_kevent_timer_recon);
if (rv == -1)
DBG("isns_task_reconnect_server: error on "
"isns_change_kevent_list(1)\n");
} else {
task_p->cfg_p->sd_connected = 1;
/* Add cfg_p->sd to kqueue */
rv = isns_change_kevent_list(task_p->cfg_p,
(uintptr_t)(task_p->cfg_p->sd), EVFILT_READ,
EV_ADD | EV_CLEAR, (int64_t)0,
(intptr_t)isns_kevent_socket);
if (rv == -1)
DBG("isns_task_reconnect_server: error on "
"isns_change_kevent_lists(2)\n");
isns_end_task(task_p);
}
}
/*
* isns_task_send_pdu()
*
* We send all of the pdu's associated with transaction task_p->trans_p here.
*
* Assumptions:
* (1) task_p->trans_p->pdu_req_list is an ordered (seq_id) list of
* related (trans_id), appropriately sized pdus to be sent. The first
* pdu has flag ISNS_FLAG_FIRST_PDU set and the last pdu has flag
* ISNS_FLAG_LAST_PDU set.
*/
static void
isns_task_send_pdu(struct isns_task_s *task_p)
{
struct iovec *iovp;
struct isns_config_s *cfg_p;
struct isns_pdu_s *pdu_p; /* points to first pdu in pdu_req_list */
struct isns_buffer_s *buf_p;
ssize_t bytes_written;
ssize_t count;
size_t bytes_to_write;
int iovcnt, cur_iovec;
char *ptr;
DBG("isns_task_send_pdu: entered\n");
cfg_p = task_p->cfg_p;
pdu_p = task_p->var.send_pdu.pdu_p;
while (pdu_p != NULL) {
/* adjust byte order if necessary */
if (pdu_p->byteorder_host) {
pdu_p->hdr.isnsp_version = isns_htons(pdu_p->hdr.
isnsp_version);
pdu_p->hdr.func_id = isns_htons(pdu_p->hdr.func_id);
pdu_p->hdr.payload_len = isns_htons(pdu_p->hdr.
payload_len);
pdu_p->hdr.flags = isns_htons(pdu_p->hdr.flags);
pdu_p->hdr.trans_id = isns_htons(pdu_p->hdr.trans_id);
pdu_p->hdr.seq_id = isns_htons(pdu_p->hdr.seq_id);
pdu_p->byteorder_host = 0;
}
DUMP_PDU(pdu_p);
/* send PDU via socket here */
write_buf[0].iov_base = &(pdu_p->hdr);
write_buf[0].iov_len = sizeof(pdu_p->hdr);
bytes_to_write = write_buf[0].iov_len;
iovcnt = 1;
buf_p = pdu_p->payload_p;
while (buf_p != NULL) {
write_buf[iovcnt].iov_base = isns_buffer_data(buf_p,0);
write_buf[iovcnt].iov_len = buf_p->cur_len;
bytes_to_write += write_buf[iovcnt].iov_len;
iovcnt++;
buf_p = buf_p->next;
}
/* iovcnt and bytes_to_write are initialized */
cur_iovec = 0;
buf_p = ((struct isns_buffer_s *)(void *)pdu_p) - 1;
do {
iovp = &(write_buf[cur_iovec]);
bytes_written = isns_socket_writev(cfg_p->sd, iovp,
iovcnt);
if (bytes_written == -1) {
DBG("isns_task_send_pdu: error on "
"isns_socket_writev\n");
isns_socket_close(cfg_p->sd);
cfg_p->sd_connected = 0;
isns_process_connection_loss(cfg_p);
if (cfg_p->pdu_in_p != NULL) {
isns_free_pdu(cfg_p->pdu_in_p);
cfg_p->pdu_in_p = NULL;
}
break;
}
if (bytes_written < (ssize_t)bytes_to_write) {
count = bytes_written;
while (buf_p != NULL) { /* -OR- while (1) */
if ((unsigned)count >= write_buf[
cur_iovec].iov_len) {
count -= write_buf[cur_iovec].
iov_len;
if (cur_iovec == 0)
buf_p = pdu_p->
payload_p;
else
buf_p = buf_p->next;
cur_iovec++;
iovcnt--;
if (count == 0) {
/* Do another write */
break;
} else {
/* Look at new iovec */
continue;
}
} else {
write_buf[cur_iovec].iov_len -=
count;
ptr = (char *) write_buf[cur_iovec].iov_base;
ptr += count;
write_buf[cur_iovec].iov_base = ptr;
/* Do another write */
break;
}
}
}
bytes_to_write -= bytes_written;
} while (bytes_to_write);
pdu_p = pdu_p->next;
}
if (!task_p->waitable) {
isns_complete_trans(task_p->var.send_pdu.trans_p);
isns_end_task(task_p);
}
}
/*
* isns_task_init_socket_io()
*/
static void
isns_task_init_socket_io(struct isns_task_s *task_p)
{
struct isns_config_s *cfg_p;
int rv;
DBG("isns_task_init_socket_io: entered\n");
cfg_p = task_p->cfg_p;
if (cfg_p->sd_connected) {
isns_socket_close(cfg_p->sd);
cfg_p->sd_connected = 0;
/* We may have received part of an unsolicited/duplicate pdu */
if (cfg_p->pdu_in_p != NULL) {
isns_free_pdu(cfg_p->pdu_in_p);
cfg_p->pdu_in_p = NULL;
}
}
/* May have an allocated 'struct addrinfo', whether connected or not */
if (cfg_p->ai_p != NULL) {
isns_free(cfg_p->ai_p);
cfg_p->ai_p = NULL;
}
cfg_p->sd = task_p->var.init_socket_io.sd;
cfg_p->ai_p = task_p->var.init_socket_io.ai_p;
cfg_p->sd_connected = 1;
/* Add cfg_p->sd to kqueue */
rv = isns_change_kevent_list(cfg_p, (uintptr_t)cfg_p->sd,
EVFILT_READ, EV_ADD | EV_CLEAR, (int64_t)0,
(intptr_t)isns_kevent_socket);
if (rv == -1)
DBG("isns_task_init_socket_io: error on "
"isns_change_kevent_list\n");
isns_end_task(task_p);
}
/*
* isns_task_init_refresh(struct isns_task_s *task_p)
*/
static void
isns_task_init_refresh(struct isns_task_s *task_p)
{
struct isns_config_s *cfg_p;
int rval;
DBG("isns_task_init_refresh: entered\n");
/* Free any previous refresh info. */
cfg_p = task_p->cfg_p;
if (cfg_p->refresh_p != NULL) {
if (cfg_p->refresh_p->trans_p != NULL)
isns_free_trans(cfg_p->refresh_p->trans_p);
isns_free(cfg_p->refresh_p);
}
/* Assign new refresh info into config struct. */
cfg_p->refresh_p = task_p->var.init_refresh.ref_p;
cfg_p->refresh_p->trans_p = NULL;
/* Setup (or change) kevent timer for reg refresh. */
rval = isns_change_kevent_list(cfg_p,
(uintptr_t)ISNS_EVT_TIMER_REFRESH, EVFILT_TIMER,
EV_ADD | EV_ENABLE, (int64_t)cfg_p->refresh_p->interval * 1000,
(intptr_t)isns_kevent_timer_refresh);
if (rval == -1) {
DBG("isns_task_init_refresh: "
"error on isns_change_kevent_list()\n");
}
isns_end_task(task_p);
}
struct isns_task_s *
isns_new_task(struct isns_config_s *cfg_p, uint8_t task_type, int waitable)
{
struct isns_buffer_s *buf_p;
struct isns_task_s *task_p;
pthread_mutexattr_t mutexattr;
pthread_condattr_t condattr;
task_p = NULL;
buf_p = isns_new_buffer((int)sizeof(struct isns_task_s));
if (buf_p) {
task_p = (struct isns_task_s *)isns_buffer_data(buf_p, 0);
task_p->cfg_p = cfg_p;
task_p->task_type = task_type;
task_p->waitable = waitable;
if (waitable) {
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_settype(&mutexattr,
ISNS_MUTEX_TYPE_NORMAL);
pthread_mutex_init(&task_p->wait_mutex, &mutexattr);
pthread_condattr_init(&condattr);
pthread_cond_init(&task_p->wait_condvar, &condattr);
task_p->wait_ref_count = 2;
}
}
DBG("isns_new_task: %p, waitable=%d\n", task_p, waitable);
return task_p;
}
void
isns_free_task(struct isns_task_s *task_p)
{
struct isns_buffer_s *buf_p;
int ref_count;
DBG("isns_free_task: %p\n", task_p);
if (task_p->waitable) {
pthread_mutex_lock(&task_p->wait_mutex);
ref_count = --task_p->wait_ref_count;
pthread_mutex_unlock(&task_p->wait_mutex);
if (ref_count > 0) {
DBG("isns_free_task: ref_count > 0, no free done\n");
return;
}
pthread_mutex_destroy(&task_p->wait_mutex);
pthread_cond_destroy(&task_p->wait_condvar);
}
buf_p = ((struct isns_buffer_s *)(void *)(task_p))-1;
isns_free_buffer(buf_p);
}
void
isns_taskq_insert_head(struct isns_config_s *cfg_p,
struct isns_task_s *task_p)
{
pthread_mutex_lock(&cfg_p->taskq_mutex);
SIMPLEQ_INSERT_HEAD(&cfg_p->taskq_head, task_p, taskq_entry);
pthread_mutex_unlock(&cfg_p->taskq_mutex);
DBG("isns_taskq_insert_head: %p\n", task_p);
}
void
isns_taskq_insert_tail(struct isns_config_s *cfg_p,
struct isns_task_s *task_p)
{
pthread_mutex_lock(&cfg_p->taskq_mutex);
SIMPLEQ_INSERT_TAIL(&cfg_p->taskq_head, task_p, taskq_entry);
pthread_mutex_unlock(&cfg_p->taskq_mutex);
DBG("isns_taskq_insert_tail: %p\n", task_p);
}
struct isns_task_s *
isns_taskq_remove(struct isns_config_s *cfg_p)
{
struct isns_task_s *task_p = NULL;
pthread_mutex_lock(&cfg_p->taskq_mutex);
if ((task_p = SIMPLEQ_FIRST(&cfg_p->taskq_head)) != NULL)
SIMPLEQ_REMOVE_HEAD(&cfg_p->taskq_head, taskq_entry);
pthread_mutex_unlock(&cfg_p->taskq_mutex);
DBG("isns_taskq_remove: %p\n", task_p);
return task_p;
}
struct isns_task_s *
isns_taskq_remove_trans(struct isns_config_s *cfg_p, uint16_t trans_id)
{
struct isns_task_s *task_p;
int trans_found;
trans_found = 0;
pthread_mutex_lock(&cfg_p->taskq_mutex);
SIMPLEQ_FOREACH(task_p, &cfg_p->taskq_head, taskq_entry) {
if ((task_p->task_type == ISNS_TASK_SEND_PDU)
&& (task_p->var.send_pdu.trans_p->id == trans_id)) {
trans_found = 1;
break;
}
}
if (trans_found) {
SIMPLEQ_REMOVE(&cfg_p->taskq_head, task_p, isns_task_s,
taskq_entry);
}
pthread_mutex_unlock(&cfg_p->taskq_mutex);
return (trans_found ? task_p : NULL);
}

97
lib/libisns/isns_task.h Normal file
View File

@ -0,0 +1,97 @@
/* $NetBSD: isns_task.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_task.h
*/
#ifndef _ISNS_TASK_H_
#define _ISNS_TASK_H_
#include <sys/event.h>
#define ISNS_TASK_DISCOVER_SERVER 0
#define ISNS_TASK_RECONNECT_SERVER 1
#define ISNS_TASK_SEND_PDU 2
#define ISNS_TASK_INIT_SOCKET_IO 3
#define ISNS_TASK_INIT_REFRESH 4
#define ISNS_NUM_TASKS 5
union isns_task_var_u {
struct {
struct isns_trans_s *trans_p;
struct isns_pdu_s *pdu_p;
} send_pdu;
struct {
struct addrinfo *ai_p;
} reconnect_server;
struct {
isns_socket_t sd;
struct addrinfo *ai_p;
} init_socket_io;
struct {
struct isns_refresh_s *ref_p;
} init_refresh;
void *data_p;
};
struct isns_task_s {
uint8_t task_type;
struct isns_config_s *cfg_p;
union isns_task_var_u var;
int waitable;
pthread_mutex_t wait_mutex;
pthread_cond_t wait_condvar;
int wait_ref_count;
SIMPLEQ_ENTRY(isns_task_s) taskq_entry;
};
typedef void (isns_task_handler)(struct isns_task_s *);
void isns_run_task(struct isns_task_s *);
void isns_end_task(struct isns_task_s *);
int isns_wait_task(struct isns_task_s *, const struct timespec *);
struct isns_task_s *isns_new_task(struct isns_config_s *, uint8_t, int);
void isns_free_task(struct isns_task_s *);
void isns_taskq_insert_tail(struct isns_config_s *, struct isns_task_s *);
void isns_taskq_insert_head(struct isns_config_s *, struct isns_task_s *);
struct isns_task_s *isns_taskq_remove(struct isns_config_s *);
struct isns_task_s *isns_taskq_remove_trans(struct isns_config_s *, uint16_t);
#endif /* !_ISNS_TASK_H_ */

549
lib/libisns/isns_thread.c Normal file
View File

@ -0,0 +1,549 @@
/* $NetBSD: isns_thread.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_thread.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $");
/*
* isns_thread.c
*/
#include <sys/types.h>
#include <unistd.h>
#include "isns.h"
#include "isns_config.h"
#include "isns_defs.h"
static struct iovec read_buf[2 + (ISNS_MAX_PDU_PAYLOAD / ISNS_BUF_SIZE) +
((ISNS_MAX_PDU_PAYLOAD % ISNS_BUF_SIZE) != 0)];
static struct isns_task_s *isns_get_next_task(struct isns_config_s *);
/*
* isns_control_thread()
*/
void *
isns_control_thread(void *arg)
{
struct isns_config_s *cfg_p = (struct isns_config_s *)arg;
struct kevent evt_chgs[5], *evt_p;
int n, nevents;
isns_kevent_handler *evt_handler_p;
int run_thread;
run_thread = 1;
while (run_thread) {
/* if no task outstanding, check queue here and send PDU */
while ((cfg_p->curtask_p == NULL)
&& ((cfg_p->curtask_p = isns_get_next_task(cfg_p)) != NULL))
isns_run_task(cfg_p->curtask_p);
nevents = kevent(cfg_p->kq, NULL, 0, evt_chgs,
ARRAY_ELEMS(evt_chgs), NULL);
DBG("isns_control_thread: kevent() nevents=%d\n", nevents);
for (n = 0, evt_p = evt_chgs; n < nevents; n++, evt_p++) {
DBG("event[%d] - data=%d\n", n, (int)evt_p->data);
evt_handler_p = (void *)evt_p->udata;
run_thread = (evt_handler_p(evt_p, cfg_p) == 0);
}
}
return 0;
}
/*
* isns_get_next_task()
*/
static struct isns_task_s *
isns_get_next_task(struct isns_config_s *cfg_p)
{
struct isns_task_s *task_p = NULL;
DBG("isns_get_next_task: entered\n");
task_p = isns_taskq_remove(cfg_p);
if (cfg_p->sd_connected)
return task_p;
else {
if (task_p == NULL)
return NULL;
else {
if (task_p->task_type != ISNS_TASK_INIT_SOCKET_IO) {
isns_taskq_insert_head(cfg_p, task_p);
task_p = isns_new_task(cfg_p,
ISNS_TASK_RECONNECT_SERVER, 0);
task_p->var.reconnect_server.ai_p = cfg_p->ai_p;
}
return task_p;
}
}
}
/*
* isns_kevent_pipe()
*/
int
isns_kevent_pipe(struct kevent* evt_p, struct isns_config_s *cfg_p)
{
uint8_t cmd_type;
int force_isns_stop;
uint16_t trans_id;
ssize_t rbytes;
int pipe_nbytes;
force_isns_stop = 0;
pipe_nbytes = (int)evt_p->data;
while (pipe_nbytes > 0) {
rbytes = read(cfg_p->pipe_fds[0], &cmd_type,
sizeof(cmd_type));
if (rbytes < 0) {
DBG("isns_kevent_pipe: error on wepe_sys_read\n");
/*?? should we break here? */
continue;
}
pipe_nbytes -= (int)rbytes;
switch (cmd_type) {
case ISNS_CMD_PROCESS_TASKQ:
DBG("isns_kevent_pipe: ISNS_CMD_PROCESS_TASKQ\n");
break;
case ISNS_CMD_ABORT_TRANS:
DBG("isns_kevent_pipe: ISNS_CMD_ABORT_TRANS\n");
rbytes = read(cfg_p->pipe_fds[0], &trans_id,
sizeof(trans_id));
if ((rbytes < 0) && (rbytes == sizeof(trans_id)))
isns_abort_trans(cfg_p, trans_id);
else
DBG("isns_kevent_pipe: "
"error reading trans id\n");
pipe_nbytes -= (int)rbytes;
break;
case ISNS_CMD_STOP:
DBG("isns_kevent_pipe: ISNS_CMD_STOP\n");
force_isns_stop = 1;
pipe_nbytes = 0;
break;
default:
DBG("isns_kevent_pipe: unknown command (cmd=%d)\n",
cmd_type);
break;
}
}
return (force_isns_stop ? 1 : 0);
}
/*
* isns_is_trans_complete()
*/
static int
isns_is_trans_complete(struct isns_trans_s *trans_p)
{
struct isns_pdu_s *pdu_p;
uint16_t count;
pdu_p = trans_p->pdu_rsp_list;
count = 0;
while (pdu_p->next != NULL) {
if (pdu_p->hdr.seq_id != count++) return 0;
pdu_p = pdu_p->next;
}
if ((pdu_p->hdr.seq_id != count) ||
!(pdu_p->hdr.flags & ISNS_FLAG_LAST_PDU))
return 0;
return 1;
}
/*
* isns_is_valid_resp()
*/
static int
isns_is_valid_resp(struct isns_trans_s *trans_p, struct isns_pdu_s *pdu_p)
{
struct isns_pdu_s *curpdu_p;
if (pdu_p->hdr.trans_id != trans_p->id)
return 0;
if (pdu_p->hdr.func_id != (trans_p->func_id | 0x8000))
return 0;
curpdu_p = trans_p->pdu_rsp_list;
while (curpdu_p != NULL) {
if (curpdu_p->hdr.seq_id == pdu_p->hdr.seq_id) return 0;
curpdu_p = curpdu_p->next;
}
return 1;
}
/*
* isns_process_in_pdu()
*/
static void
isns_process_in_pdu(struct isns_config_s *cfg_p)
{
struct isns_task_s *curtask_p;
struct isns_trans_s *trans_p;
DBG("isns_process_in_pdu: entered\n");
if ((curtask_p = cfg_p->curtask_p) == NULL)
isns_free_pdu(cfg_p->pdu_in_p);
else if ((trans_p = curtask_p->var.send_pdu.trans_p) == NULL)
isns_free_pdu(cfg_p->pdu_in_p);
else if (!isns_is_valid_resp(trans_p, cfg_p->pdu_in_p))
isns_free_pdu(cfg_p->pdu_in_p);
else {
isns_add_pdu_response(trans_p, cfg_p->pdu_in_p);
if (isns_is_trans_complete(trans_p)) {
isns_complete_trans(trans_p);
isns_end_task(curtask_p);
}
}
cfg_p->pdu_in_p = NULL;
}
/*
* isns_kevent_socket()
*/
int
isns_kevent_socket(struct kevent *evt_p, struct isns_config_s *cfg_p)
{
struct iovec *iovp;
struct isns_buffer_s *curbuf_p, *newbuf_p;
struct isns_pdu_s *pdu_p;
int64_t bavail; /* bytes available in socket buffer */
uint32_t cur_len, buf_len, unread_len, rd_len, b_len;
ssize_t rv;
uint16_t payload_len;
int iovcnt, more, transport_evt;
DBG("isns_kevent_socket: entered\n");
transport_evt = 0;
bavail = evt_p->data;
iovp = read_buf;
more = (bavail > 0);
while (more) {
if (cfg_p->pdu_in_p == NULL) {
/*
* Try to form a valid pdu by starting with the hdr.
* If there isn't enough data in the socket buffer
* to form a full hdr, just return.
*
* Once we have read in our hdr, allocate all buffers
* needed.
*/
if (bavail < (int64_t)sizeof(struct isns_pdu_hdr_s))
return 0;
/* Form a placeholder pdu */
pdu_p = isns_new_pdu(cfg_p, 0, 0, 0);
/* Read the header into our placeholder pdu */
read_buf[0].iov_base = &(pdu_p->hdr);
read_buf[0].iov_len = sizeof(struct isns_pdu_hdr_s);
iovcnt = 1;
iovp = read_buf;
rv = isns_socket_readv(cfg_p->sd, iovp, iovcnt);
if ((rv == 0) || (rv == -1)) {
DBG("isns_kevent_socket: isns_socket_readv(1) "
"returned %d\n", rv);
transport_evt = 1;
break;
}
bavail -= sizeof(struct isns_pdu_hdr_s);
/*
* ToDo: read until sizeof(struct isns_pdu_hdr_s) has
* been read in. This statement should be
*
* bavail -= rv;
*/
/* adjust byte order */
pdu_p->hdr.isnsp_version = isns_ntohs(pdu_p->hdr.
isnsp_version);
pdu_p->hdr.func_id = isns_ntohs(pdu_p->hdr.func_id);
pdu_p->hdr.payload_len = isns_ntohs(pdu_p->hdr.
payload_len);
pdu_p->hdr.flags = isns_ntohs(pdu_p->hdr.flags);
pdu_p->hdr.trans_id = isns_ntohs(pdu_p->hdr.trans_id);
pdu_p->hdr.seq_id = isns_ntohs(pdu_p->hdr.seq_id);
pdu_p->byteorder_host = 1;
/* Try to sense early whether we might have garbage */
if (pdu_p->hdr.isnsp_version != ISNSP_VERSION) {
DBG("isns_kevent_socket: pdu_p->hdr."
"isnsp_version != ISNSP_VERSION\n");
isns_free_pdu(pdu_p);
transport_evt = 1;
break;
}
/* Allocate all the necessary payload buffers */
payload_len = pdu_p->hdr.payload_len;
curbuf_p = pdu_p->payload_p;
buf_len = 0;
while (buf_len + curbuf_p->alloc_len < payload_len) {
buf_len += curbuf_p->alloc_len;
newbuf_p = isns_new_buffer(0);
curbuf_p->next = newbuf_p;
curbuf_p = newbuf_p;
}
curbuf_p->next = NULL;
/* Hold on to our placeholder pdu */
cfg_p->pdu_in_p = pdu_p;
more = (bavail > 0) ? 1 : 0;
} else if (bavail > 0) {
/*
* Fill in the pdu payload data.
*
* If we can fill it all in now
* -AND- it corresponds to the active transaction
* then add the pdu to the transaction's
* pdu_rsp_list
* -AND- it does not correspond to the active
* transaction (or there is no active
* transaction) then drop it on the floor.
* We may not be able to fill it all in now.
* -EITHER WAY- fill in as much payload data now
* as we can.
*/
/* Refer to our placeholder pdu */
pdu_p = cfg_p->pdu_in_p;
/* How much payload data has been filled in? */
cur_len = 0;
curbuf_p = pdu_p->payload_p;
while (curbuf_p->cur_len == curbuf_p->alloc_len) {
cur_len += curbuf_p->cur_len;
curbuf_p = curbuf_p->next;
}
cur_len += curbuf_p->cur_len;
/* How much payload data is left to be filled in? */
unread_len = pdu_p->hdr.payload_len - cur_len;
/* Read as much remaining payload data as possible */
iovcnt = 0;
while (curbuf_p->next != NULL) {
read_buf[iovcnt].iov_base = isns_buffer_data(
curbuf_p, curbuf_p->cur_len);
read_buf[iovcnt].iov_len = curbuf_p->alloc_len -
curbuf_p->cur_len;
iovcnt++;
curbuf_p = curbuf_p->next;
}
read_buf[iovcnt].iov_base = isns_buffer_data(curbuf_p,
curbuf_p->cur_len);
read_buf[iovcnt].iov_len = unread_len;
iovcnt++;
rv = isns_socket_readv(cfg_p->sd, iovp, iovcnt);
if ((rv == 0) || (rv == -1)) {
DBG("isns_kevent_socket: isns_socket_readv(2) "
"returned %d\n",rv);
isns_free_pdu(cfg_p->pdu_in_p);
cfg_p->pdu_in_p = NULL;
transport_evt = 1;
break;
}
/* Update cur_len in buffers that newly have data */
curbuf_p = pdu_p->payload_p;
while (curbuf_p->cur_len == curbuf_p->alloc_len)
curbuf_p = curbuf_p->next;
rd_len = (uint32_t)rv;
do {
b_len = curbuf_p->alloc_len - curbuf_p->cur_len;
if (rd_len > b_len) {
curbuf_p->cur_len = curbuf_p->alloc_len;
rd_len -= b_len;
} else {
curbuf_p->cur_len += rd_len;
break;
}
curbuf_p = curbuf_p->next;
} while (curbuf_p != NULL);
bavail -= rv;
if (rv == (int)unread_len)
isns_process_in_pdu(cfg_p);
more = (bavail > (int64_t)sizeof(struct isns_pdu_hdr_s)) ? 1 : 0;
}
}
transport_evt |= (evt_p->flags & EV_EOF);
if (transport_evt) {
DBG("isns_kevent_socket: processing transport event\n");
isns_socket_close(cfg_p->sd);
cfg_p->sd_connected = 0;
if (cfg_p->curtask_p != NULL)
isns_process_connection_loss(cfg_p);
if (cfg_p->pdu_in_p != NULL) {
isns_free_pdu(cfg_p->pdu_in_p);
cfg_p->pdu_in_p = NULL;
}
}
return 0;
}
/* ARGSUSED */
/*
* isns_kevent_timer_recon()
*/
int
isns_kevent_timer_recon(struct kevent *evt_p, struct isns_config_s *cfg_p)
{
int rv;
DBG("isns_kevent_timer_recon: entered\n");
rv = isns_socket_create(&(cfg_p->sd), cfg_p->ai_p->ai_family,
cfg_p->ai_p->ai_socktype);
if (rv != 0)
return 0;
rv = isns_socket_connect(cfg_p->sd, cfg_p->ai_p->ai_addr,
cfg_p->ai_p->ai_addrlen);
if (rv == 0) {
/* Remove ISNS_EVT_TIMER_RECON from kqueue */
rv = isns_change_kevent_list(cfg_p,
(uintptr_t)ISNS_EVT_TIMER_RECON, EVFILT_TIMER, EV_DELETE,
(int64_t)0, (intptr_t)0);
if (rv == -1)
DBG("isns_kevent_timer_recon: error on "
"isns_change_kevent_list(1)\n");
cfg_p->sd_connected = 1;
/* Add cfg_p->sd to kqueue */
rv = isns_change_kevent_list(cfg_p, (uintptr_t)cfg_p->sd,
EVFILT_READ, EV_ADD | EV_CLEAR, (int64_t)0,
(intptr_t)isns_kevent_socket);
if (rv == -1)
DBG("isns_kevent_timer_recon: error on "
"isns_change_kevent_list(2)\n");
isns_end_task(cfg_p->curtask_p);
}
return 0;
}
/* ARGSUSED */
/*
* isns_kevent_timer_refresh
*/
int
isns_kevent_timer_refresh(struct kevent* evt_p, struct isns_config_s *cfg_p)
{
struct isns_refresh_s *ref_p;
ISNS_TRANS trans;
uint32_t status;
int rval;
DBG("isns_kevent_timer_refresh: entered\n");
/* If refresh info pointer NULL, or no name assigned, just return. */
ref_p = cfg_p->refresh_p;
if ((ref_p == NULL) || (ref_p->node[0] == '\0'))
return 0;
if (ref_p->trans_p != NULL) {
/* If the previous refresh trans is not complete, return. */
rval = isns_get_pdu_response_status(ref_p->trans_p, &status);
if (rval == EPERM) {
DBG("isns_kevent_timer_refresh: "
"prev refresh trans not complete\n");
return 0;
}
/* Free previous refresh trans. */
isns_free_trans(ref_p->trans_p);
ref_p->trans_p = NULL;
}
/* Build new refresh transaction and send it. */
trans = isns_new_trans((ISNS_HANDLE)cfg_p, isnsp_DevAttrQry, 0);
if (trans == ISNS_INVALID_TRANS) {
DBG("isns_kevent_timer_refresh: error on isns_new_trans()\n");
return 0;
}
ref_p->trans_p = (struct isns_trans_s *)trans;
/* First we add our source attribute */
isns_add_string(trans, isnst_iSCSIName, ref_p->node);
/* Now add our message attribute */
isns_add_string(trans, isnst_iSCSIName, ref_p->node);
isns_add_tlv(trans, isnst_Delimiter, 0, NULL);
/* and finally the operating attributes */
isns_add_tlv(trans, isnst_EID, 0, NULL);
isns_send_trans(trans, NULL, NULL);
return 0;
}

60
lib/libisns/isns_thread.h Normal file
View File

@ -0,0 +1,60 @@
/* $NetBSD: isns_thread.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_thread.h
*/
#ifndef _ISNS_THREAD_H
#define _ISNS_THREAD_H
#include <sys/event.h>
#include <pthread.h>
#define ISNS_CMD_STOP 1
#define ISNS_CMD_PROCESS_TASKQ 2
#define ISNS_CMD_ABORT_TRANS 3
#define ISNS_EVT_TIMER_REFRESH 1
#define ISNS_EVT_TIMER_RECON 2
#define ISNS_EVT_TIMER_RECON_PERIOD_MS 1000
#define ISNS_THREAD_MAX_NAMELEN 128
typedef int (isns_kevent_handler)(struct kevent *, struct isns_config_s *);
extern void *isns_control_thread(void *arg);
extern isns_kevent_handler isns_kevent_pipe;
extern isns_kevent_handler isns_kevent_socket;
extern isns_kevent_handler isns_kevent_timer_recon;
extern isns_kevent_handler isns_kevent_timer_refresh;
#endif /* !_ISNS_THREAD_H */

286
lib/libisns/isns_util.c Normal file
View File

@ -0,0 +1,286 @@
/* $NetBSD: isns_util.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_util.c
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: isns_util.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $");
#include <sys/types.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include "isns.h"
#include "isns_config.h"
#define ISNS_MAX_DISCONNECTS_PER_TRANS 3
int
isns_issue_cmd(struct isns_config_s *cfg_p, uint8_t cmd_type)
{
return (int)write(cfg_p->pipe_fds[1], &cmd_type, 1);
}
int
isns_issue_cmd_with_data(struct isns_config_s *cfg_p, uint8_t cmd_type,
uint8_t *data_p, int data_len)
{
struct iovec iov[2];
iov[0].iov_base = &cmd_type;
iov[0].iov_len = 1;
iov[1].iov_base = data_p;
iov[1].iov_len = data_len;
return (int)isns_file_writev(cfg_p->pipe_fds[1], iov, 2);
}
int
isns_change_kevent_list(struct isns_config_s *cfg_p,
uintptr_t ident, uint32_t filter, uint32_t flags, int64_t data, intptr_t udata)
{
struct kevent evt;
EV_SET(&evt, ident, filter, flags, 0, data, udata);
return kevent(cfg_p->kq, &evt, 1, NULL, 0, NULL);
}
struct isns_config_s *
isns_new_config()
{
struct isns_config_s *cfg_p;
pthread_mutexattr_t mutexattr;
cfg_p = (struct isns_config_s *)
isns_malloc(sizeof(struct isns_config_s));
if (cfg_p == NULL) {
DBG("isns_new_config: error on isns_malloc() [1]\n");
return NULL;
}
cfg_p->kq = -1;
cfg_p->pipe_fds[0] = -1;
cfg_p->pipe_fds[1] = -1;
cfg_p->curtask_p = NULL;
cfg_p->sd_connected = 0;
cfg_p->ai_p = NULL;
cfg_p->pdu_in_p = NULL;
cfg_p->refresh_p = NULL;
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_settype(&mutexattr, ISNS_MUTEX_TYPE_NORMAL);
if (pthread_mutex_init(&cfg_p->taskq_mutex, &mutexattr) != 0) {
DBG("isns_new_config: error on pthread_mutex_init() [1]\n");
isns_free(cfg_p);
return NULL;
}
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_settype(&mutexattr, ISNS_MUTEX_TYPE_NORMAL);
if (pthread_mutex_init(&cfg_p->trans_mutex, &mutexattr) != 0) {
DBG("isns_new_config: error on pthread_mutex_init() [2]\n");
pthread_mutex_destroy(&cfg_p->taskq_mutex);
isns_free(cfg_p);
return NULL;
}
SIMPLEQ_INIT(&cfg_p->taskq_head);
cfg_p->control_thread_p = (pthread_t *)isns_malloc(sizeof(pthread_t));
if (cfg_p->control_thread_p == NULL) {
DBG("isns_new_config: error on isns_malloc() [1]\n");
isns_destroy_config(cfg_p);
return NULL;
}
return cfg_p;
}
void
isns_destroy_config(struct isns_config_s *cfg_p)
{
struct isns_task_s *task_p;
if (cfg_p != NULL) {
if (cfg_p->kq != -1)
close(cfg_p->kq);
if (cfg_p->pipe_fds[0] != -1)
close(cfg_p->pipe_fds[0]);
if (cfg_p->pipe_fds[1] != -1)
close(cfg_p->pipe_fds[1]);
if (cfg_p->control_thread_p != NULL)
isns_free(cfg_p->control_thread_p);
if (cfg_p->refresh_p != NULL) {
if (cfg_p->refresh_p->trans_p != NULL)
isns_free_trans(cfg_p->refresh_p->trans_p);
isns_free(cfg_p->refresh_p);
}
/* Free the current task, if necessary. */
if ((task_p = cfg_p->curtask_p) != NULL) {
if (task_p->task_type == ISNS_TASK_SEND_PDU)
isns_complete_trans(task_p->var.send_pdu.trans_p);
isns_free_task(task_p);
}
/* Empty the task queue of any pending tasks and free them. */
while ((task_p = isns_taskq_remove(cfg_p)) != NULL) {
if (task_p->task_type == ISNS_TASK_SEND_PDU)
isns_complete_trans(task_p->var.send_pdu.trans_p);
isns_free_task(task_p);
}
pthread_mutex_destroy(&cfg_p->taskq_mutex);
pthread_mutex_destroy(&cfg_p->trans_mutex);
if (cfg_p->ai_p != NULL) {
if (cfg_p->ai_p->ai_canonname != NULL)
isns_free(cfg_p->ai_p->ai_canonname);
if (cfg_p->ai_p->ai_addr != NULL)
isns_free(cfg_p->ai_p->ai_addr);
isns_free(cfg_p->ai_p);
}
isns_free(cfg_p);
}
}
/*
* isns_thread_create()
*/
int
isns_thread_create(struct isns_config_s *cfg_p)
{
char namebuf[ISNS_THREAD_MAX_NAMELEN];
int error;
pthread_attr_t attr;
DBG("isns_thread_create: entered\n");
strcpy(namebuf, "isns_control");
error = pthread_attr_init(&attr);
if (error != 0) {
DBG("isns_thread_create: error on pthread_threadattr_init\n");
return error;
}
error = pthread_attr_setname_np(&attr, namebuf, NULL);
if (error != 0) {
DBG("isns_thread_create: "
"error on pthread_threadattr_setname\n");
pthread_attr_destroy(&attr);
return error;
}
error = pthread_create(cfg_p->control_thread_p,
&attr, isns_control_thread, cfg_p);
pthread_attr_destroy(&attr);
if (error != 0) {
DBG("isns_thread_create: error on pthread_thread_create\n");
return error;
}
return error;
}
/*
* isns_thread_destroy()
*/
void
isns_thread_destroy(struct isns_config_s *cfg_p)
{
int error;
void *rv;
DBG("isns_thread_destroy: entered\n");
if ((cfg_p == NULL) || (cfg_p->control_thread_p == NULL))
return;
DBG("isns_thread_destroy: about to wait (join) on thread\n");
error = pthread_join(*cfg_p->control_thread_p, &rv);
if (error) {
DBG("isns_thread_destroy: error on pthread_thread_join\n");
return;
}
DBG("isns_thread_destroy: done waiting on thread\n");
}
/*
*
*/
void
isns_process_connection_loss(struct isns_config_s *cfg_p)
{
struct isns_trans_s *trans_p;
struct isns_pdu_s *pdu_p, *free_pdu_p;
DBG("isns_process_connection_loss: entered\n");
if (cfg_p->curtask_p != NULL) {
trans_p = cfg_p->curtask_p->var.send_pdu.trans_p;
if (trans_p->disconnect_cnt == ISNS_MAX_DISCONNECTS_PER_TRANS) {
isns_complete_trans(trans_p);
isns_end_task(cfg_p->curtask_p);
if (cfg_p->pdu_in_p != NULL) {
isns_free_pdu(cfg_p->pdu_in_p);
cfg_p->pdu_in_p = NULL;
}
} else {
trans_p->disconnect_cnt++;
if (trans_p->pdu_rsp_list != NULL) {
pdu_p = trans_p->pdu_rsp_list;
while (pdu_p != NULL) {
free_pdu_p = pdu_p;
pdu_p = pdu_p->next;
isns_free_pdu(free_pdu_p);
}
}
isns_taskq_insert_head(cfg_p, cfg_p->curtask_p);
cfg_p->curtask_p = NULL;
isns_issue_cmd(cfg_p, ISNS_CMD_PROCESS_TASKQ);
}
}
}

67
lib/libisns/isns_util.h Normal file
View File

@ -0,0 +1,67 @@
/* $NetBSD: isns_util.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_util.h
*/
#ifndef _ISNS_UTIL_H_
#define _ISNS_UTIL_H_
#define isns_ntohs ntohs
#define isns_htons htons
#define isns_ntohl ntohl
#define isns_htonl htonl
#define isns_malloc malloc
#define isns_free free
#define ARRAY_ELEMS(a) (sizeof(a)/sizeof((a)[0]))
int isns_issue_cmd(struct isns_config_s *, uint8_t);
int isns_issue_cmd_with_data(struct isns_config_s *, uint8_t,
uint8_t *, int);
int isns_change_kevent_list(struct isns_config_s *,
uintptr_t, uint32_t, uint32_t, int64_t,
intptr_t);
struct isns_config_s *isns_new_config(void);
void isns_destroy_config(struct isns_config_s *);
int isns_thread_create(struct isns_config_s *);
void isns_thread_destroy(struct isns_config_s *);
void isns_process_connection_loss(struct isns_config_s *);
#endif /* !_ISNS_UTIL_H_ */

View File

@ -0,0 +1,5 @@
# $NetBSD: shlib_version,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $
#
#
major=0
minor=0