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:
parent
d31dbd7578
commit
dc2ecebec9
16
lib/libisns/Makefile
Normal file
16
lib/libisns/Makefile
Normal 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
203
lib/libisns/isns.3
Normal 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
239
lib/libisns/isns.c
Normal 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
67
lib/libisns/isns.h
Normal 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
86
lib/libisns/isns_config.h
Normal 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
197
lib/libisns/isns_defs.h
Normal 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
76
lib/libisns/isns_fileio.c
Normal 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
47
lib/libisns/isns_fileio.h
Normal 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
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
222
lib/libisns/isns_pdu.h
Normal 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
102
lib/libisns/isns_socketio.c
Normal 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);
|
||||
}
|
56
lib/libisns/isns_socketio.h
Normal file
56
lib/libisns/isns_socketio.h
Normal 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
520
lib/libisns/isns_task.c
Normal 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
97
lib/libisns/isns_task.h
Normal 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
549
lib/libisns/isns_thread.c
Normal 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
60
lib/libisns/isns_thread.h
Normal 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
286
lib/libisns/isns_util.c
Normal 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
67
lib/libisns/isns_util.h
Normal 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_ */
|
5
lib/libisns/shlib_version
Normal file
5
lib/libisns/shlib_version
Normal 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
|
Loading…
Reference in New Issue
Block a user