Mercurial > illumos > illumos-gate
changeset 4348:f06efcce7faa
PSARC 2007/175 iSCSI Target iSNS
6415430 iSCSI target needs iSNS client support
line wrap: on
line diff
--- a/usr/src/cmd/iscsi/iscsitadm/main.c Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitadm/main.c Tue May 29 17:13:54 2007 -0700 @@ -122,6 +122,7 @@ {"radius-server", required_arg, 'r', "hostname[:port]"}, {"radius-secret", no_arg, 'P', NULL}, {"isns-access", required_arg, 'S', "enable/disable"}, + {"isns-server", required_arg, 's', "hostname[:port]"}, {"fast-write-ack", required_arg, 'f', "enable/disable"}, {"verbose", no_arg, 'v', NULL}, {"interval", required_arg, 'I', "seconds"}, @@ -220,7 +221,7 @@ {TPGT, MODIFY, "i", B_TRUE, NULL}, {TPGT, DELETE, "Ai", B_TRUE, NULL}, {TPGT, LIST, "v", B_FALSE, NULL}, - {ADMIN, MODIFY, "dHCRrPSf", B_TRUE, NULL}, + {ADMIN, MODIFY, "dHCRrPSsf", B_TRUE, NULL}, {STATS, SHOW, "vIN", B_FALSE, NULL}, }; @@ -359,8 +360,8 @@ static int formatErrString(tgt_node_t *node) { - int code = 0, - rtn = 0; + int code = 0; + int rtn = 0; char *msg = NULL; if (node == NULL) { @@ -679,9 +680,9 @@ char *first_str = NULL; tgt_node_t *node; cmdOptions_t *optionList = options; - char chapSecret[MAX_CHAP_SECRET_LEN], - olddir[MAXPATHLEN], - newdir[MAXPATHLEN]; + char chapSecret[MAX_CHAP_SECRET_LEN]; + char olddir[MAXPATHLEN]; + char newdir[MAXPATHLEN]; int secretLen = 0; int ret = 0; @@ -743,19 +744,19 @@ break; case 'R': /* radius access */ if (strcmp(optionList->optarg, - OPT_ENABLE) == 0) { + OPT_ENABLE) == 0) { tgt_buf_add(&first_str, XML_ELEMENT_RAD_ACCESS, OPT_TRUE); } else if (strcmp(optionList->optarg, - OPT_DISABLE) == 0) { + OPT_DISABLE) == 0) { tgt_buf_add(&first_str, XML_ELEMENT_RAD_ACCESS, OPT_FALSE); } else { (void) fprintf(stderr, "%s: %s\n", cmdName, gettext("Option value should be" - "enable/disable")); + "enable/disable")); free(first_str); return (1); } @@ -782,38 +783,42 @@ break; case 'S': /* iSNS access */ if (strcmp(optionList->optarg, - OPT_ENABLE) == 0) { + OPT_ENABLE) == 0) { tgt_buf_add(&first_str, XML_ELEMENT_ISNS_ACCESS, OPT_TRUE); } else if (strcmp(optionList->optarg, - OPT_DISABLE) == 0) { + OPT_DISABLE) == 0) { tgt_buf_add(&first_str, XML_ELEMENT_ISNS_ACCESS, OPT_FALSE); } else { (void) fprintf(stderr, "%s: %s\n", cmdName, gettext("Option value should be" - "enable/disable")); + "enable/disable")); free(first_str); return (1); } break; + case 's': /* iSNS server */ + tgt_buf_add(&first_str, XML_ELEMENT_ISNS_SERV, + optionList->optarg); + break; case 'f': /* fast write back */ if (strcmp(optionList->optarg, - OPT_ENABLE) == 0) { + OPT_ENABLE) == 0) { tgt_buf_add(&first_str, XML_ELEMENT_FAST, OPT_TRUE); } else if (strcmp(optionList->optarg, - OPT_DISABLE) == 0) { + OPT_DISABLE) == 0) { tgt_buf_add(&first_str, XML_ELEMENT_FAST, OPT_FALSE); } else { (void) fprintf(stderr, "%s: %s\n", cmdName, gettext("Option value should be" - "enable/disable")); + "enable/disable")); free(first_str); return (1); } @@ -1119,8 +1124,8 @@ (void) printf("%s%s: %s\n", dospace(3), gettext("Size"), number_to_scaled_string(buf, - strtoll(n4->x_value, - NULL, 0), 512, 1024)); + strtoll(n4->x_value, + NULL, 0), 512, 1024)); } else { (void) printf("%s%s: %s\n", dospace(3), gettext("Size"), gettext("unknown")); @@ -1168,7 +1173,7 @@ case 'v': verbose = True; tgt_buf_add(&first_str, - XML_ELEMENT_VERBOSE, OPT_TRUE); + XML_ELEMENT_VERBOSE, OPT_TRUE); break; default: @@ -1247,7 +1252,7 @@ case 'v': verbose = True; tgt_buf_add(&first_str, - XML_ELEMENT_VERBOSE, OPT_TRUE); + XML_ELEMENT_VERBOSE, OPT_TRUE); break; default: (void) fprintf(stderr, "%s: %c: %s\n", @@ -1376,6 +1381,10 @@ } else (void) printf("%s\n", gettext("Not set")); + n2 = tgt_node_next_child(n1, XML_ELEMENT_ISNS_SERV, NULL); + (void) printf("%s%s: %s\n", dospace(1), gettext("iSNS Server"), + n2 ? n2->x_value : gettext("Not set")); + n2 = tgt_node_next_child(n1, XML_ELEMENT_FAST, NULL); (void) printf("%s%s: ", dospace(1), gettext("Fast Write ACK")); if (n2) { @@ -1392,15 +1401,13 @@ static int showStats(int operandLen, char *operand[], cmdOptions_t *options) { - char *first_str = NULL, - scale_buf[16]; - tgt_node_t *node, - *n1; - int interval = -1, - count = -1, - header; - stat_delta_t cur_data, - *pd; + char *first_str = NULL; + char scale_buf[16]; + tgt_node_t *node, *n1; + int interval = -1; + int count = -1; + int header; + stat_delta_t cur_data, *pd; tgt_buf_add_tag(&first_str, "list", Tag_Start); tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start);
--- a/usr/src/cmd/iscsi/iscsitgtd/Makefile Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/Makefile Tue May 29 17:13:54 2007 -0700 @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -32,6 +32,7 @@ OBJS += iscsi_crc.o iscsi_ffp.o iscsi_login.o iscsi_sess.o radius.o OBJS += t10_sam.o t10_spc.o t10_sbc.o t10_raw_if.o t10_ssc.o t10_osd.o OBJS += util.o util_err.o util_ifname.o util_port.o util_queue.o +OBJS += isns_client.o isns.o POFILE= iscsitgtd.po POFILES = $(OBJS:%.o=%.po)
--- a/usr/src/cmd/iscsi/iscsitgtd/Makefile.com Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/Makefile.com Tue May 29 17:13:54 2007 -0700 @@ -32,6 +32,7 @@ OBJS += iscsi_crc.o iscsi_ffp.o iscsi_login.o iscsi_sess.o radius.o OBJS += t10_sam.o t10_spc.o t10_sbc.o t10_raw_if.o t10_ssc.o t10_osd.o OBJS += util.o util_err.o util_ifname.o util_port.o util_queue.o +OBJS += isns_client.o isns.o SRCS= $(OBJS:%.o=../%.c) $(COMMON_SRCS) include ../../../Makefile.cmd
--- a/usr/src/cmd/iscsi/iscsitgtd/errcode.h Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/errcode.h Tue May 29 17:13:54 2007 -0700 @@ -107,7 +107,10 @@ ERR_TAPE_NOT_SUPPORTED_IN_32BIT, ERR_INTERNAL_ERROR, ERR_BAD_CREDS, - ERR_NO_PERMISSION + ERR_NO_PERMISSION, + ERR_INVALID_ISNS_SRV, + ERR_ISNS_ERROR, + ERR_TPGT_NO_IPADDR } err_code_t; char *
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c Tue May 29 17:13:54 2007 -0700 @@ -31,6 +31,7 @@ #include <sys/types.h> #include <stdlib.h> #include <unistd.h> +#include <syslog.h> #include <sys/iscsi_protocol.h> #include <iscsitgt_impl.h> #include "queue.h" @@ -39,6 +40,7 @@ #include "iscsi_login.h" #include "utility.h" #include "target.h" +#include "isns_client.h" typedef enum auth_action { LOGIN_NO_AUTH, @@ -132,16 +134,16 @@ iscsi_login_rsp_hdr_t *rsp = NULL; Boolean_t rval = False; IscsiAuthClient *auth_client = NULL; - char *text = NULL, - *end = NULL, - *text_rsp = NULL, - debug[128]; - int debug_status = 0, - errcode = 0, - text_length = 0, - keytype = 0, - transit = 0, - rc = 0; + char *text = NULL; + char *end = NULL; + char *text_rsp = NULL; + char debug[128]; + int debug_status = 0; + int errcode = 0; + int text_length = 0; + int keytype = 0; + int transit = 0; + int rc = 0; auth_action_t auth_action = LOGIN_DROP; tgt_node_t *tnode = NULL; @@ -220,7 +222,7 @@ auth_client = (c->c_sess->sess_auth.auth_buffers && - c->c_sess->sess_auth.num_auth_buffers) ? + c->c_sess->sess_auth.num_auth_buffers) ? (IscsiAuthClient *) c->c_sess->sess_auth.auth_buffers[0].address : NULL; @@ -305,7 +307,7 @@ } if (iscsiAuthClientRecvTransitBit(auth_client, - transit) != iscsiAuthStatusNoError) { + transit) != iscsiAuthStatusNoError) { (void) snprintf(debug, sizeof (debug), "iscsi connection(%u) login failed - " "authentication transmit failed", c->c_num); @@ -340,13 +342,13 @@ (char *)iscsiAuthClientGetKeyName(keytype); if ((key) && (iscsi_find_key_value(key, text, end, - &value, &value_end))) { + &value, &value_end))) { (void) snprintf(debug, sizeof (debug), "%s=%s", key, value); queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug); if (iscsiAuthClientRecvKeyValue( - auth_client, keytype, value) + auth_client, keytype, value) != iscsiAuthStatusNoError) { (void) snprintf(debug, sizeof (debug), @@ -396,11 +398,9 @@ &debug_status); (void) snprintf(debug, sizeof (debug), "iscsi connection(%u) authentication failed (%s)", - c->c_num, - iscsiAuthClientDebugStatusToText( - debug_status)); - queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, - debug); + c->c_num, iscsiAuthClientDebugStatusToText( + debug_status)); + queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug); send_login_reject(c, &lh, (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) | @@ -603,7 +603,7 @@ if ((lh.flags & ISCSI_FLAG_LOGIN_TRANSIT) && (ISCSI_LOGIN_NEXT_STAGE(lh.flags) == - ISCSI_FULL_FEATURE_PHASE)) { + ISCSI_FULL_FEATURE_PHASE)) { conn_state(c, T5); @@ -718,7 +718,7 @@ &szIniAlias); if (tgt_find_value_str(xnInitiator, XML_ELEMENT_INAME, - &szIscsiName) == True) { + &szIscsiName) == True) { comp = strcmp(s->s_i_name, szIscsiName); free(szIscsiName); @@ -727,8 +727,8 @@ if (comp == 0) { if (tgt_find_value_str(xnInitiator, - XML_ELEMENT_CHAPNAME, - &szChapName) == True) { + XML_ELEMENT_CHAPNAME, + &szChapName) == True) { /*CSTYLED*/ (void) strcpy((char *)sess_auth->username_in, szChapName); @@ -736,8 +736,8 @@ } if (tgt_find_value_str(xnInitiator, - XML_ELEMENT_CHAPSECRET, - &szChapSecret) == True) { + XML_ELEMENT_CHAPSECRET, + &szChapSecret) == True) { /*CSTYLED*/ (void) strcpy((char *)sess_auth->password_in, szChapSecret); @@ -762,6 +762,15 @@ } /* + * If iSNS enabled set LOGIN_AUTH + */ + if (isns_enabled() == True) { + if (sess_auth->password_length_in == 0) + return (LOGIN_NO_AUTH); + return (LOGIN_AUTH); + } + + /* * If no acc_list for current target, transit. * If acc_list exists for the target, and * If the initiator not in the list, drop it. @@ -785,7 +794,7 @@ if (comp == 0) { if ((xnAcl = tgt_node_next(xnTarget, - XML_ELEMENT_ACLLIST, 0)) == NULL) { + XML_ELEMENT_ACLLIST, 0)) == NULL) { /* * No acl_list found, return True for no auth */ @@ -799,7 +808,7 @@ */ xnInitiator = NULL; while ((xnInitiator = tgt_node_next(xnAcl, - XML_ELEMENT_INIT, xnInitiator)) != NULL) { + XML_ELEMENT_INIT, xnInitiator)) != NULL) { if ((tgt_find_value_str(xnInitiator, XML_ELEMENT_INIT, &possible) == False) ||
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/iscsi/iscsitgtd/isns.c Tue May 29 17:13:54 2007 -0700 @@ -0,0 +1,573 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <syslog.h> +#include <ctype.h> +#include <pthread.h> +#include <netdb.h> +#include <libintl.h> +#include <errno.h> +#include <assert.h> +#include <sys/byteorder.h> + +#include "isns_protocol.h" +#include "isns_client.h" +#include "queue.h" + +extern target_queue_t *mgmtq; + +static uint16_t xid = 0; +static pthread_mutex_t xid_lock = PTHREAD_MUTEX_INITIALIZER; + +/* + * more than 1 processes can accessing get_xid + */ +static uint16_t +get_xid() +{ + uint16_t tmp; + + pthread_mutex_lock(&xid_lock); + tmp = xid++; + pthread_mutex_unlock(&xid_lock); + return (tmp); +} + +void +ntoh_tlv(isns_tlv_t *tlv) +{ + uint32_t val; + + tlv->attr_id = ntohl(tlv->attr_id); + tlv->attr_len = ntohl(tlv->attr_len); + + switch (tlv->attr_id) { + case ISNS_DELIMITER_ATTR_ID: + break; + case ISNS_ISCSI_NAME_ATTR_ID: + case ISNS_EID_ATTR_ID: + case ISNS_ISCSI_ALIAS_ATTR_ID: + case ISNS_PORTAL_NAME_ATTR_ID: + case ISNS_PG_ISCSI_NAME_ATTR_ID: + break; + + case ISNS_PORTAL_IP_ADDR_ATTR_ID: + case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: + bcopy(tlv->attr_value, &val, 4); + *tlv->attr_value = ntohl(val); + break; + + default: + switch (tlv->attr_len) { + case 4: + val = ntohl( + (uint32_t)(*tlv->attr_value)); + bcopy(&val, tlv->attr_value, 4); + break; + default: + break; + } + break; + } +} + +/* + * print_ntoh_tlv print network byte order tag-length-value attribute + */ +void +print_ntoh_tlv(isns_tlv_t *tlv) +{ + uint32_t tag, len, val, pf_type; + char buf[256]; + struct sockaddr_in6 sin6; + + tag = ntohl(tlv->attr_id); + len = ntohl(tlv->attr_len); + + if (len == 0) { + queue_prt(mgmtq, Q_ISNS_DBG, "Zero length tag: %d\n", tag); + return; + } + + switch (tag) { + case ISNS_DELIMITER_ATTR_ID: + break; + case ISNS_ISCSI_NAME_ATTR_ID: + case ISNS_EID_ATTR_ID: + case ISNS_ISCSI_ALIAS_ATTR_ID: + case ISNS_PORTAL_NAME_ATTR_ID: + case ISNS_PG_ISCSI_NAME_ATTR_ID: + queue_prt(mgmtq, Q_ISNS_DBG, + "Tag %d: Value: %s\n", tag, tlv->attr_value); + break; + + case ISNS_PORTAL_IP_ADDR_ATTR_ID: + case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: + bcopy(tlv->attr_value, &pf_type, 4); + pf_type = ntohl(pf_type); + pf_type = (pf_type == sizeof (in6_addr_t)) + ? PF_INET6 : PF_INET; + switch (pf_type) { + case PF_INET: + /* RFC2372 IPv4 mapped IPv6 address */ + if (inet_ntop(pf_type, + (void *)&tlv->attr_value[12], + buf, 256) == NULL) { + syslog(LOG_ERR, + "inet_ntop failed"); + break; + } + queue_prt(mgmtq, Q_ISNS_DBG, + "IP_ADDR %s\n", buf); + break; + case PF_INET6: + bcopy(tlv->attr_value, &sin6, + sizeof (struct sockaddr_in6)); + inet_ntop(pf_type, + (void *)&sin6.sin6_addr, + buf, 256); + break; + default: + queue_prt(mgmtq, Q_ISNS_DBG, + "unknown pf_type\n"); + break; + } + break; + + default: + switch (len) { + case 4: + bcopy(tlv->attr_value, &val, 4); + val = ntohl(val); + queue_prt(mgmtq, Q_ISNS_DBG, + "Tag: %d Value: %ld\n", tag, val); + break; + default: + break; + } + break; + } +} + +void +print_attr(isns_tlv_t *attr, void *pval, uint32_t ival) +{ + uint32_t tag = ntohl(attr->attr_id); + uint32_t len = ntohl(attr->attr_len); + uint32_t pf_type; + char buf[256]; + + queue_prt(mgmtq, Q_ISNS_DBG, "Tag: %d Length: %d\n", tag, len); + switch (tag) { + case ISNS_DELIMITER_ATTR_ID: + break; + + case ISNS_ISCSI_NAME_ATTR_ID: + case ISNS_EID_ATTR_ID: + case ISNS_ISCSI_ALIAS_ATTR_ID: + case ISNS_PORTAL_NAME_ATTR_ID: + case ISNS_PG_ISCSI_NAME_ATTR_ID: + if (len && pval != NULL) { + queue_prt(mgmtq, Q_ISNS_DBG, "Value: %s\n", + attr->attr_value); + } + break; + + case ISNS_PORTAL_IP_ADDR_ATTR_ID: + case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: + if (len) { + pf_type = (ival == sizeof (in6_addr_t)) + ? PF_INET6 : PF_INET; + inet_ntop(pf_type, pval, buf, 256); + queue_prt(mgmtq, Q_ISNS_DBG, "IP_ADDR %s\n", + buf); + } + break; + + default: + switch (len) { + case 4: + queue_prt(mgmtq, Q_ISNS_DBG, + "Value: %d\n", + ntohl(*attr->attr_value)); + break; + default: + break; + } + break; + } +} + +void +print_isns_hdr(isns_hdr_t *hdr) +{ + queue_prt(mgmtq, Q_ISNS_DBG, "hdr->version %d\n", hdr->version); + queue_prt(mgmtq, Q_ISNS_DBG, "hdr->func_id %x\n", hdr->func_id); + queue_prt(mgmtq, Q_ISNS_DBG, "hdr->pdu_len %d\n", hdr->pdu_len); + queue_prt(mgmtq, Q_ISNS_DBG, "hdr->flags %x\n", hdr->flags); + queue_prt(mgmtq, Q_ISNS_DBG, "hdr->xid %d\n", hdr->xid); + queue_prt(mgmtq, Q_ISNS_DBG, "hdr->seqid %d\n", hdr->seqid); +} + +void +ntoh_isns_hdr(isns_hdr_t *hdr) +{ + hdr->version = ntohs(hdr->version); + hdr->func_id = ntohs(hdr->func_id); + hdr->pdu_len = ntohs(hdr->pdu_len); + hdr->flags = ntohs(hdr->flags); + hdr->xid = ntohs(hdr->xid); + hdr->seqid = ntohs(hdr->seqid); +} + +int +isns_append_attr(isns_pdu_t *pdu, uint32_t tag, uint32_t len, + void *pval, uint32_t ival) +{ + uint32_t val; + uint32_t pad_len; + uint16_t pdu_len; + isns_tlv_t *attr; + char *tlv; + + if (pdu == NULL) { + syslog(LOG_ALERT, "NULL PDU\n"); + return (-1); + } + + /* get current pdu payload length */ + pdu_len = ntohs(pdu->payload_len); + + /* pad 4 bytes alignment */ + pad_len = PAD4(len); + + if ((pdu_len + pad_len) > MAX_PDU_PAYLOAD_SZ) { + syslog(LOG_ALERT, "Exceeded PDU size\n"); + return (-1); + } + + if ((attr = (isns_tlv_t *)malloc(ISNS_ATTR_SZ(pad_len))) == NULL) { + syslog(LOG_ALERT, "Malloc error"); + return (-1); + } + bzero(attr, ISNS_ATTR_SZ(pad_len)); + attr->attr_id = htonl(tag); + attr->attr_len = htonl(pad_len); + + switch (tag) { + case ISNS_DELIMITER_ATTR_ID: + break; + + case ISNS_ISCSI_NAME_ATTR_ID: + case ISNS_EID_ATTR_ID: + case ISNS_ISCSI_ALIAS_ATTR_ID: + case ISNS_PORTAL_NAME_ATTR_ID: + case ISNS_PG_ISCSI_NAME_ATTR_ID: + if (len && pval != NULL) { + bcopy(pval, attr->attr_value, len); + } + break; + + case ISNS_PORTAL_IP_ADDR_ATTR_ID: + case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: + if (len && ival == sizeof (in_addr_t)) { + /* IPv4 */ + attr->attr_value[10] = 0xFF; + attr->attr_value[11] = 0xFF; + bcopy(pval, ((attr->attr_value) + 12), ival); + } else if (len && ival == sizeof (in6_addr_t)) { + /* IPv6 */ + bcopy(pval, attr->attr_value, ival); + } + break; + + default: + switch (len) { + case 4: + val = htonl(ival); + bcopy(&val, attr->attr_value, 4); + break; + default: + break; + } + break; + } + + /* copy attribute to pdu */ + tlv = (char *)pdu + ISNSP_HEADER_SIZE + pdu_len; + bcopy(attr, tlv, ISNS_ATTR_SZ(pad_len)); + pdu->payload_len = htons(pdu_len + ISNS_ATTR_SZ(pad_len)); + + /* debug only */ + print_ntoh_tlv(attr); + + free(attr); + return (0); +} + +int +isns_create_pdu(uint16_t func_id, uint32_t flags, isns_pdu_t **pdu) +{ + size_t pdu_sz = MAX_PDU_SZ; + + if ((*pdu = (isns_pdu_t *)malloc(pdu_sz)) == NULL) { + syslog(LOG_ERR, "isns_create_pdu malloc failure"); + return (-1); + } + + bzero(*pdu, pdu_sz); + (*pdu)->payload_len = 0; + (*pdu)->seq = 0; + (*pdu)->xid = htons(get_xid()); + (*pdu)->version = htons((uint16_t)ISNSP_VERSION); + (*pdu)->func_id = htons((uint16_t)(func_id)); + (*pdu)->flags = htons((uint16_t)(flags | ISNS_FLAG_CLIENT | + ISNS_FLAG_FIRST_PDU | ISNS_FLAG_LAST_PDU)); + return (0); +} + +void +isns_free_pdu(void *pdu) +{ + free(pdu); +} + +/* + * Desc: Open connection to the isns server + * Args: isns server name or isns server ip-addr + * Return: -1 if open failed, descriptor to socket if open succeeded + */ +int +isns_open(char *server) +{ + struct addrinfo hints, *ai, *aip; + struct sockaddr *sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + size_t sa_len; + int so; + int ret; + + if (server == NULL) { + syslog(LOG_ERR, "ISNS server ID required"); + return (-1); + } + + bzero(&hints, sizeof (struct addrinfo)); + hints.ai_family = AF_UNSPEC; + if (getaddrinfo(server, NULL, NULL, &ai) != 0) { + syslog(LOG_ALERT, "ISNS server %s not found", server); + return (-1); + } + + aip = ai; + do { + so = socket(aip->ai_family, SOCK_STREAM, 0); + if (so != -1) { + sa_len = aip->ai_addrlen; + switch (aip->ai_family) { + case PF_INET: + bzero(&sin, + sizeof (struct sockaddr_in)); + sa = (struct sockaddr *)&sin; + bcopy(aip->ai_addr, sa, sa_len); + sin.sin_port = htons( + ISNS_DEFAULT_SERVER_PORT); + break; + case PF_INET6: + bzero(&sin6, + sizeof (struct sockaddr_in6)); + sa = (struct sockaddr *)&sin6; + bcopy(aip->ai_addr, sa, sa_len); + sin6.sin6_port = + htons(ISNS_DEFAULT_SERVER_PORT); + break; + default: + continue; + } + while (((ret = connect(so, sa, sa_len)) == -1) && + (errno == EINTR)) + ; + if (ret == 0) { + freeaddrinfo(ai); + return (so); + } else { + syslog(LOG_ALERT, "Connect failed"); + close(so); + } + } + } while ((aip = aip->ai_next) != NULL); + + if (ai != NULL) + freeaddrinfo(ai); + return (-1); +} + +void +isns_close(int so) +{ + if (so) { + close(so); + } +} + +/* + * isns_send allocated pdu, caller needs to free pdu when done processing + */ +int +isns_send(int so, isns_pdu_t *pdu) +{ + size_t len; + + assert(pdu != NULL); + + len = ISNSP_HEADER_SIZE + ntohs(pdu->payload_len); + if (send(so, pdu, len, 0) == -1) { + syslog(LOG_ALERT, "isns_send failure"); + return (-1); + } + return (0); +} + +/* + * Desc: isns_recv malloc memory for the isns response message, user needs + * to isns_free() memory after process the response message. The + * isns header is converted to host byte order, the remaining TLV + * attributes can be converted using ntoh_tlv() + */ +int +isns_recv(int so, isns_rsp_t **pdu) +{ + isns_hdr_t hdr, hdr1; + isns_rsp_t *rsp; + uint8_t *ptr; + size_t total_pdu_len; + int len; + uint16_t xid_x, func_id_x, seqid_x; + boolean_t done; + + *pdu = NULL; + total_pdu_len = 0; + seqid_x = 0; + done = FALSE; + + do { + /* read pdu header 1st */ + do { + len = recv(so, &hdr1, ISNSP_HEADER_SIZE, MSG_WAITALL); + } while ((len == -1) && (errno == EINTR)); + + if (len != ISNSP_HEADER_SIZE) { + syslog(LOG_ALERT, "isns_recv fail to read header"); + return (-1); + } + + /* normalize the pdu header for processing */ + bcopy(&hdr1, &hdr, sizeof (isns_hdr_t)); + ntoh_isns_hdr(&hdr); + + if (IS_1ST_PDU(hdr.flags)) { + if (hdr.seqid != 0) { + syslog(LOG_ALERT, "ISNS out of sequence"); + return (-1); + } + xid_x = hdr.xid; + func_id_x = hdr.func_id; + } + + if (IS_LAST_PDU(hdr.flags)) { + done = TRUE; + } + + /* verify seq, xid, func_id */ + if (seqid_x != hdr.seqid) { + syslog(LOG_ALERT, "ISNS out of sequence"); + return (-1); + } + if (xid_x != hdr.xid || func_id_x != hdr.func_id) { + syslog(LOG_ALERT, "Non matching xid or func_id"); + return (-1); + } + + ++seqid_x; /* next expected seqid */ + + /* malloc size + previous payload length */ + if ((ptr = malloc(ISNSP_HEADER_SIZE + hdr.pdu_len + + total_pdu_len)) == NULL) { + syslog(LOG_ALERT, "Malloc failure"); + return (-1); + } + bzero(ptr, ISNSP_HEADER_SIZE + hdr.pdu_len); + + if (hdr.seqid == 0) { + *pdu = (void *)ptr; + bcopy(&hdr1, ptr, ISNSP_HEADER_SIZE); + ptr += ISNSP_HEADER_SIZE; + if ((len = recv(so, ptr, hdr.pdu_len, MSG_WAITALL)) + != hdr.pdu_len) { + syslog(LOG_ERR, + "isns_recv fail to read 1st payload"); + free(*pdu); + *pdu = NULL; + return (-1); + } + } else { + /* merge the pdu */ + bcopy(*pdu, ptr, ISNSP_HEADER_SIZE + total_pdu_len); + free(*pdu); + *pdu = (void *)ptr; + ptr += (ISNSP_HEADER_SIZE + total_pdu_len); + if (recv(so, ptr, hdr.pdu_len, MSG_WAITALL) + != hdr.pdu_len) { + syslog(LOG_ERR, + "isns_recv fail to read payload"); + free(*pdu); + *pdu = NULL; + return (-1); + } + } + total_pdu_len += hdr.pdu_len; + + } while (done == FALSE); + + /* normalize the response status */ + rsp = (isns_rsp_t *)*pdu; + rsp->pdu_len = htons(total_pdu_len); + ntoh_isns_hdr((isns_hdr_t *)rsp); + + return (0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/iscsi/iscsitgtd/isns_client.c Tue May 29 17:13:54 2007 -0700 @@ -0,0 +1,1630 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <strings.h> +#include <syslog.h> +#include <netdb.h> +#include <pthread.h> +#include <signal.h> +#include <errno.h> +#include <netinet/in.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +#include <iscsitgt_impl.h> + +#include "isns_protocol.h" +#include "isns_client.h" +#include "target.h" +#include "queue.h" + + +typedef struct { + uint32_t pf_family; + uint32_t ip_len; + uint32_t ai_addrlen; + union { + in_addr_t in; + in6_addr_t in6; + } ip_adr; +} ip_t; + +#define ISNS_TGT_LOGOUT 54321 + +extern target_queue_t *mgmtq; + +/* + * Global + * Parameters for ESI/SCN processing. + * scn_port: ESI/SCN port to receive ISNS_ESI & ISNS_SCN messages + * isns_args: + * eid_ip: Entity IP info + */ +static int scn_port = 0; +static esi_scn_arg_t isns_args; +static ip_t eid_ip; +static int num_reg = 0; +static pthread_t scn_tid = 0; +static Boolean_t isns_shutdown = False; + +Boolean_t isns_initialized = False; +sema_t isns_sema; +target_queue_t *mgmtq = NULL; + +static int get_ip_addr(char *node, ip_t *sa); +static int isns_op_all(uint16_t); +static int append_tpgt(tgt_node_t *, isns_pdu_t *); +static void process_esi(int, isns_pdu_t *); +static void process_scn(int, isns_pdu_t *); +static void *esi_scn_thr(void *); +static int process_rsp(isns_pdu_t *, isns_rsp_t *); +static int isns_dev_attr_reg(int, tgt_node_t *, char *, char *); +static int isns_dev_attr_dereg(int, char *); +static int isns_scn_reg(int, char *); +static int isns_scn_dereg(int so, char *node); +static tgt_node_t *find_tgt_by_name(char *, char **); +static tgt_node_t *find_next_tgt(tgt_node_t *, char **); + +/* + * find_tgt_by_name searches DB by iscsi name or local name, if found + * returns tgt_node_t. iname needs to be free by caller. + */ +static tgt_node_t * +find_tgt_by_name(char *targ, char **iname) +{ + tgt_node_t *tgt = NULL; + + while ((tgt = tgt_node_next(targets_config, XML_ELEMENT_TARG, tgt)) + != NULL) { + if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname) + == FALSE) { + syslog(LOG_ALERT, "ISNS: Missing iscsi name\n"); + break; + } + /* match either iscsi name or local name */ + if (strcmp(targ, tgt->x_value) == 0 || + strcmp(targ, *iname) == 0) { + return (tgt); + } + free(*iname); + } + return (NULL); +} + +static tgt_node_t * +find_next_tgt(tgt_node_t *tgt, char **iname) +{ + while ((tgt = tgt_node_next(targets_config, XML_ELEMENT_TARG, tgt)) + != NULL) { + if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname) + == FALSE) { + continue; + } + return (tgt); + } + return (NULL); +} + +/* + * Find ip-addr associated with TPGT, don't send if no ip-addr is + * found for a TPGT + */ +static int +append_tpgt(tgt_node_t *tgt, isns_pdu_t *cmd) +{ + tgt_node_t *t, *x; + tgt_node_t *pgt = NULL; + tgt_node_t *ip = NULL; + tgt_node_t *tpgt = NULL; + ip_t eid; + + /* Always add the default TPGT (1) */ + isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID, ISNS_PG_TAG_SZ, NULL, 1); + if (isns_append_attr(cmd, ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, + eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr, + eid_ip.ip_len) != 0) { + return (-1); + } + if (isns_append_attr(cmd, ISNS_PG_PORTAL_PORT_ATTR_ID, + ISNS_PORT_SZ, NULL, iscsi_port) != 0) { + return (-1); + } + + /* Get the remainning TPGT-LIST */ + if ((t = tgt_node_next(tgt, XML_ELEMENT_TPGTLIST, NULL)) + != NULL) { + /* find tgpt from tpgt-list */ + while ((pgt = tgt_node_next(t, XML_ELEMENT_TPGT, pgt)) + != NULL) { + /* update isns only if TPGT contains ip_addr */ + while ((tpgt = tgt_node_next(main_config, + XML_ELEMENT_TPGT, tpgt)) != NULL) { + if (strcmp(pgt->x_value, tpgt->x_value) != 0) + continue; + if ((ip = tgt_node_next(tpgt, + XML_ELEMENT_IPADDR, NULL)) != NULL) + break; + } + if (tpgt == NULL || ip == NULL) + continue; + if (isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID, + ISNS_PG_TAG_SZ, NULL, + strtol(pgt->x_value, NULL, 0)) != 0) { + return (-1); + } + + /* get ip-addr & port */ + for (x = tpgt->x_child; x; x = x->x_sibling) { + get_ip_addr(x->x_value, &eid); + if (isns_append_attr(cmd, + ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, + eid.ai_addrlen, (void *)&eid.ip_adr, + eid.ip_len) != 0) { + return (-1); + } + if (isns_append_attr(cmd, + ISNS_PG_PORTAL_PORT_ATTR_ID, + ISNS_PORT_SZ, NULL, iscsi_port) != 0) { + return (-1); + } + } + } + } + + return (0); +} + +/* + * process_scn() + * -Added/Updated object: nop, initiator is verified during connect + * + * -Removed object: logout_targ if still connected + * + * RFC 4171 section 5.6.5.9 + * destination attribute is always the 1st attribute in the SCN message, + * then follows by SCN_BITMAP(35) & Source_Attribute(32) + */ +static void +process_scn(int so, isns_pdu_t *scn) +{ + uint8_t *ptr = scn->payload; + isns_tlv_t *tlv; + uint16_t len = scn->payload_len; + uint32_t done = 0; + uint32_t got_dest = 0; + uint32_t got_source = 0; + uint32_t bitmap = 0; + uint32_t got_bitmap = 0; + char dest[MAXNAMELEN]; + char source[MAXNAMELEN]; + + queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_SCN %u\n", len); + + if (len < TAG_LEN_SZ) { + syslog(LOG_ALERT, "ISNS SCN message error\n"); + return; + } + + while (done == 0) { + /* LINTED */ + tlv = (isns_tlv_t *)ptr; + tlv->attr_id = ntohl(tlv->attr_id); + tlv->attr_len = ntohl(tlv->attr_len); + queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_SCN %u %u\n", + tlv->attr_id, tlv->attr_len); + /* + * devAttrQry the source attribute, process if node_type + * is initiator + */ + switch (tlv->attr_id) { + case ISNS_ISCSI_NAME_ATTR_ID: + if (got_dest == 0) { + bcopy(tlv->attr_value, dest, + tlv->attr_len); + queue_prt(mgmtq, Q_ISNS_DBG, + "PROCESS_SCN dest %s\n", dest); + got_dest = 1; + } else { + bcopy(tlv->attr_value, source, + tlv->attr_len); + queue_prt(mgmtq, Q_ISNS_DBG, + "PROCESS_SCN source %s\n", source); + got_source = 1; + } + break; + case ISNS_ISCSI_SCN_BITMAP_ATTR_ID: + bcopy(tlv->attr_value, &bitmap, tlv->attr_len); + bitmap = ntohl(bitmap); + queue_prt(mgmtq, Q_ISNS_DBG, + "PROCESS_SCN bitmap %u\n", bitmap); + got_bitmap = 1; + break; + case ISNS_DELIMITER_ATTR_ID: + queue_prt(mgmtq, Q_ISNS_DBG, + "PROCESS_SCN DELIMIT\n"); + done = 1; + break; + default: + queue_prt(mgmtq, Q_ISNS_DBG, + "PROCESS_SCN DEFAULT\n"); + break; + } + + if (done) + break; + + if (got_source && !got_bitmap) { + queue_prt(mgmtq, Q_ISNS_DBG, + "process_scn: message out-of-order\n"); + return; + } + + if (got_source && got_bitmap) { + switch (bitmap) { + case ISNS_OBJ_ADDED: + case ISNS_OBJ_UPDATED: + queue_prt(mgmtq, Q_ISNS_DBG, + "PROCESS_SCN OBJ ADDED"); + isns_update(); + break; + case ISNS_OBJ_REMOVED: + queue_prt(mgmtq, Q_ISNS_DBG, + "PROCESS_SCN OBJ REMOVED"); + /* logout target */ + if (got_dest == 0) { + syslog(LOG_ALERT, + "ISNS protocol error\n"); + continue; + } + logout_targ(dest); + break; + default: + break; + } + + /* clear got_xxx */ + got_source = 0; + got_bitmap = 1; + } + + /* next attribute */ + len -= ISNS_ATTR_SZ(tlv->attr_len); + ptr += ISNS_ATTR_SZ(tlv->attr_len); + } + queue_prt(mgmtq, Q_ISNS_DBG, "DONE PROCESS_SCN\n"); +} + +/* + * Process ESI requires a success response only + */ +static void +process_esi(int so, isns_pdu_t *esi) +{ + isns_rsp_t *cmd; + int pl_len; + + if (isns_create_pdu(ISNS_ESI_RSP, 0, (isns_pdu_t **)&cmd) != 0) { + return; + } + + pl_len = esi->payload_len + ISNS_STATUS_SZ; + if (pl_len > MAX_PDU_PAYLOAD_SZ) { + syslog(LOG_ALERT, "process_esi: payload size exceeded"); + isns_free_pdu(cmd); + return; + } + + /* change the xid to the request xid */ + cmd->xid = htons(esi->xid); + cmd->status = htonl(ISNS_RSP_SUCCESSFUL); + + /* copy original data */ + bcopy(esi->payload, cmd->data, esi->payload_len); + cmd->pdu_len = htons(pl_len); + + if (isns_send(so, (isns_pdu_t *)cmd) < 0) { + syslog(LOG_ALERT, "process_esi failed to isns_send"); + } + + isns_free_pdu(cmd); +} + +/* + * esi_scn_thr() is the thread creates an end point to receive and process + * ESI & SCN messages. This thread is created when isns_access is enabled + * and for the duration of the iscsi daemon + */ +static void +*esi_scn_thr(void *arg) +{ + struct sockaddr sa, *ai; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + int so, fd; + socklen_t len; + char strport[NI_MAXSERV]; + int pf; + esi_scn_arg_t *args = (esi_scn_arg_t *)arg; + isns_pdu_t *scn = NULL; + + /* + * open isns server connect and determine which PF_INET + * to use + */ + if ((so = isns_open(args->server)) < 0) { + syslog(LOG_ERR, + "esi_scn_thr: isns server %s not found", args->server); + return (NULL); + } + len = sizeof (sa); + if (getsockname(so, &sa, &len) < 0) { + isns_close(so); + syslog(LOG_ALERT, "getsockname failed"); + return (NULL); + } + pf = sa.sa_family; + isns_close(so); + + if (pf != PF_INET && pf != PF_INET6) { + syslog(LOG_ERR, "esi_scn_thr: unknown domain type"); + return (NULL); + } + + /* + * create and bind SCN socket + * save the scn port info + */ + if ((so = socket(pf, SOCK_STREAM, 0)) == -1) { + syslog(LOG_ALERT, "socket failed"); + return (NULL); + } + + if (pf == PF_INET) { + bzero(&sin, sizeof (sin)); + sin.sin_family = PF_INET; + sin.sin_port = htons(0); + sin.sin_addr.s_addr = INADDR_ANY; + ai = (struct sockaddr *)&sin; + len = sizeof (sin); + } else { + bzero(&sin6, sizeof (sin6)); + sin6.sin6_family = PF_INET6; + sin6.sin6_port = htons(0); + sin6.sin6_addr = in6addr_any; + ai = (struct sockaddr *)&sin6; + len = sizeof (sin6); + } + + (void) setsockopt(so, SOL_SOCKET, SO_REUSEADDR, 0, 0); + + if (bind(so, ai, len) < 0) { + syslog(LOG_ALERT, "esi_scn_thr: bind failed"); + return (NULL); + } + + /* get scn port info */ + len = sizeof (sa); + if (getsockname(so, &sa, &len) < 0) { + syslog(LOG_ALERT, "getsockname failed"); + return (NULL); + } + if (getnameinfo(&sa, len, NULL, 0, strport, NI_MAXSERV, + NI_NUMERICSERV) != 0) { + syslog(LOG_ALERT, "getnameinfo failed"); + return (NULL); + } + scn_port = atoi(strport); + + sema_post(&isns_sema); + + if (listen(so, 5) < 0) { + syslog(LOG_ALERT, "esi_scn_thr: failed listen"); + return (NULL); + } + + /* listen for esi or scn messages */ + while (isns_shutdown == False) { + if ((fd = accept(so, &sa, &len)) < 0) { + syslog(LOG_ALERT, "esi_scn_thr: failed accept"); + continue; + } + + if (isns_recv(fd, (isns_rsp_t **)&scn) == 0) { + /* Just return success for ESI */ + switch (scn->func_id) { + case ISNS_ESI: + process_esi(fd, scn); + break; + case ISNS_SCN: + /* call the SCN process function */ + process_scn(fd, scn); + break; + default: + syslog(LOG_ERR, + "esi_scn_thr: Invalid funcid %d\n", + scn->func_id); + break; + } + /* free response resource */ + isns_free_pdu(scn); + } else { + syslog(LOG_ALERT, "esi_scn_thr fails isns_recv "); + } + + close(fd); + } + return (NULL); +} + +/* + * Perform operation on all targets + */ +static int +isns_op_all(uint16_t op) +{ + int so; + tgt_node_t *tgt = NULL; + char *iname; + + if ((so = isns_open(isns_args.server)) == -1) { + syslog(LOG_ERR, "isns_reg failed"); + return (-1); + } + + while ((tgt = tgt_node_next(targets_config, XML_ELEMENT_TARG, tgt)) + != NULL) { + if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &iname) + == FALSE) { + continue; + } + + switch (op) { + case ISNS_DEV_DEREG: + if (isns_dev_attr_dereg(so, iname) == -1) { + syslog(LOG_ERR, + "ISNS de-register failed\n"); + } + num_reg = 0; + break; + case ISNS_SCN_DEREG: + if (isns_scn_dereg(so, iname) == -1) { + syslog(LOG_ERR, + "ISNS SCN de-register failed\n"); + } + break; + case ISNS_SCN_REG: + if (isns_scn_reg(so, iname) == -1) { + syslog(LOG_ERR, + "ISNS SCN register failed\n"); + } + break; + case ISNS_TGT_LOGOUT: + logout_targ(iname); + break; + default: + break; + } + + free(iname); + } + + isns_close(so); + return (0); +} + +/* + * isns_init() needs to be call before all ISNS operations. + * Save the isns_server & entity name. + * Start esi_scn_thr to receive ESI & SCN messages + */ +int +isns_init(target_queue_t *q) +{ + char *isns_srv, *isns_port; + + if (q != NULL) + mgmtq = q; + + if (isns_enabled() == False) + return (0); + + /* initialize */ + sema_init(&isns_sema, 0, USYNC_THREAD, NULL); + + /* get isns server info */ + tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV, &isns_srv); + isns_port = strchr(isns_srv, ':'); + if (isns_port == NULL) { + isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT; + } else { + isns_args.isns_port = strtoul(isns_port + 1, NULL, 0); + if (isns_args.isns_port == 0) { + isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT; + } + *isns_port = '\0'; + } + bcopy(isns_srv, isns_args.server, MAXHOSTNAMELEN); + free(isns_srv); + + /* get local hostname for entity usage */ + if ((gethostname(isns_args.entity, MAXHOSTNAMELEN) < 0) || + (get_ip_addr(isns_args.entity, &eid_ip) < 0)) { + syslog(LOG_ERR, "ISNS fails to get ENTITY properties"); + return (-1); + } + + if (pthread_create(&scn_tid, NULL, esi_scn_thr, (void *)&isns_args) != + 0) { + syslog(LOG_ALERT, "isns_init failed to pthread_create"); + return (-1); + } + + if (sema_wait(&isns_sema) != 0) { + syslog(LOG_ERR, "sema_wait error\n"); + } + + isns_initialized = True; + + /* + * register all targets, what happens if no targets are created yet? + * this should not be a failure, when new target gets created, update + * gets call. + * what if SCN register fails? + */ + if (isns_reg_all() == 0) { + /* scn register all targets */ + if (isns_op_all(ISNS_SCN_REG) != 0) { + syslog(LOG_ERR, "SCN registrations failed\n"); + isns_op_all(ISNS_DEV_DEREG); + return (-1); + } + } + + return (0); +} + +/* + * isns_update gets call on modify_admin, this is changes to + * isns access and/or isns server + */ +int +isns_update() +{ + char *isns_srv = NULL, *isns_port; + + if (isns_initialized == False) { + /* isns enabled after iscsi started */ + if (isns_enabled() == True) { + isns_init(NULL); + } + return (0); + } + + /* + * isns is disabled after enabled, + * log off all targets and fini isns service + */ + if (isns_initialized == True && isns_enabled() == False) { + isns_fini(); + return (0); + } + + /* + * isns is already initialized and isns_access is still enabled, + * let's update the isns_server name + */ + tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV, &isns_srv); + isns_port = strchr(isns_srv, ':'); + if (isns_port == NULL) { + isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT; + } else { + isns_args.isns_port = strtoul(isns_port + 1, NULL, 0); + if (isns_args.isns_port == 0) { + isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT; + } + *isns_port = '\0'; + } + if (strcmp(isns_srv, isns_args.server) != 0) { + /* de-reg from old iSNS server */ + (void) isns_dereg_all(); + } + + bcopy(isns_srv, isns_args.server, MAXHOSTNAMELEN); + free(isns_srv); + + if (isns_reg_all() == 0) { + /* scn register all targets */ + if (isns_op_all(ISNS_SCN_REG) != 0) { + syslog(LOG_ERR, "SCN registrations failed\n"); + isns_op_all(ISNS_DEV_DEREG); + return (-1); + } + } + + return (0); +} + +/* + * isns_fini is called when isns access is disable + */ +void +isns_fini() +{ + /* + * de-register all targets 1st, this prevents initiator from + * logging back in + */ + isns_op_all(ISNS_SCN_DEREG); + isns_op_all(ISNS_DEV_DEREG); + + /* log off all targets */ + isns_op_all(ISNS_TGT_LOGOUT); +} + +static int +get_ip_addr(char *node, ip_t *sa) +{ + struct addrinfo *ai, *aip; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + + if (getaddrinfo(node, NULL, NULL, &ai) != 0) { + syslog(LOG_ALERT, "ISNS server not found"); + return (-1); + } + + bzero(sa, sizeof (ip_t)); + aip = ai; + do { + sa->ai_addrlen = aip->ai_addrlen; + sa->pf_family = aip->ai_family; + switch (aip->ai_family) { + case PF_INET: + /* LINTED */ + sin = (struct sockaddr_in *)aip->ai_addr; + sa->ip_len = sizeof (in_addr_t); + bcopy(&sin->sin_addr, (void *)&sa->ip_adr.in, + sa->ip_len); + return (0); + case PF_INET6: + /* LINTED */ + sin6 = (struct sockaddr_in6 *)aip->ai_addr; + sa->ip_len = sizeof (in6_addr_t); + bcopy(&sin6->sin6_addr, &sa->ip_adr.in6, + sa->ip_len); + return (0); + default: + continue; + } + } while ((aip = aip->ai_next) != NULL); + + return (-1); +} + +/* + * Process isns response, need to verify same transaction id, func_id + * as the isns command, the isns command is in network byte order, + * the isns response is in host byte order + */ +static int +process_rsp(isns_pdu_t *cmd, isns_rsp_t *rsp) +{ + queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_RSP"); + /* + * Process responses: + * -verify sucessful response + * -verify match xid + * -process operating attributes + * For DevAttrReg & DevAttrQry and most isns command, + * the response func_id is command_func_id | 0x8000. + */ + rsp->status = ntohl(rsp->status); + if (rsp->status != ISNS_RSP_SUCCESSFUL || + rsp->xid != ntohs(cmd->xid) || + rsp->func_id != (ntohs(cmd->func_id) | 0x8000)) { + queue_prt(mgmtq, Q_ISNS_DBG, + "cmd failed with: status= %d xid= %d %d "\ + "response attribute %x\n", rsp->status, rsp->xid,\ + ntohs(cmd->xid), rsp->func_id); + return (-1); + } + + return (0); +} + +/* + * DevAttrDereg + */ +static int +isns_dev_attr_dereg(int so, char *node) +{ + isns_pdu_t *cmd = NULL; + isns_rsp_t *rsp = NULL; + uint32_t flags = 0; + int ret = -1; + + queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_DEREG"); + + if (isns_create_pdu(ISNS_DEV_DEREG, flags, &cmd) != 0) { + return (-1); + } + + /* add source attribute */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(node), node, 0) != 0) { + goto error; + } + + /* add delimiter */ + if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) { + goto error; + } + + /* add operation attributes */ + /* EID */ + if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, + STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { + goto error; + } + + /* send pdu */ + if (isns_send(so, cmd) == -1) { + syslog(LOG_ERR, "isns_dev_attr_dereg fails isns_send"); + goto error; + } + + /* get isns response */ + if (isns_recv(so, &rsp) == -1) { + syslog(LOG_ERR, "isns_dev_attr_dereg fails isns_recv "); + goto error; + } + + /* process response */ + if (process_rsp(cmd, rsp) == 0) { + num_reg--; + ret = 0; + } + +error: + /* Free all resouces here */ + if (cmd) + isns_free_pdu(cmd); + if (rsp) + isns_free_pdu(rsp); + return (ret); +} + +/* + * Register a new node, need to find another node that is already registered + * DevAttrReg + * RFC 4171 Section 5.6.5.5 indicated SCN-port-tag (23) needed to be + * included in the registration + * Also need to register ESI-port-tag (20) see Section 6.3.5 + */ +static int +isns_dev_attr_reg(int so, tgt_node_t *tgt, char *node, char *alias) +{ + isns_pdu_t *cmd = NULL; + isns_rsp_t *rsp = NULL; + uint32_t flags = 0; + int ret = 0; + Boolean_t found = False; + tgt_node_t *src = NULL; + char *src_nm = NULL; + + queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_REG"); + + if ((so = isns_open(isns_args.server)) == -1) { + return (-1); + } + + if (num_reg == 0) { + flags |= ISNS_FLAG_REPLACE_REG; + } + + if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) { + return (-1); + } + + if (num_reg == 0) { + /* add new node to source attribute */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(node), node, 0) != 0) { + goto error; + } + } else { + /* find a registered node to use */ + do { + src = find_next_tgt(src, &src_nm); + if (src == NULL) { + syslog(LOG_ALERT, "ISNS out of sync\n"); + goto error; + } + if (tgt == src) { + free(src_nm); + continue; + } else { + found = True; + } + } while (found == False); + + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(src_nm), src_nm, 0) != 0) { + goto error; + } + } + + /* add message key attribute */ + if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, + STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { + goto error; + } + + /* add delimiter */ + if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) { + goto error; + } + + /* add operation attributes */ + + /* entity id */ + if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, + STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { + goto error; + } + + /* entity type */ + if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID, + ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) { + goto error; + } + + /* + * Register entity portal properties the 1st time + */ + if (num_reg == 0) { + /* portal ip-addr */ + if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID, + eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr, + eid_ip.ip_len) != 0) { + goto error; + } + + /* portal port */ + if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID, + ISNS_PORT_SZ, NULL, iscsi_port) != 0) { + goto error; + } + + /* ESI interval */ + if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID, + ISNS_ESI_TICK_SZ, NULL, 10) != 0) { + goto error; + } + + /* scn port */ + if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID, + ISNS_PORT_SZ, NULL, scn_port) != 0) { + goto error; + } + + /* esi port */ + if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID, + ISNS_PORT_SZ, NULL, scn_port) != 0) { + goto error; + } + } + + /* iscsi node name */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(node), node, 0) != 0) { + goto error; + } + + /* iscsi node type */ + if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, + ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE) != 0) { + goto error; + } + + /* iscsi node alias */ + if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID, + STRLEN(alias), alias, 0) != 0) { + goto error; + } + + /* PGT */ + if (append_tpgt(tgt, cmd) != 0) { + goto error; + } + + /* send pdu */ + if (isns_send(so, cmd) == -1) { + goto error; + } + + /* get isns response */ + if (isns_recv(so, &rsp) == -1) { + goto error; + } + + /* process response */ + if ((ret = process_rsp(cmd, rsp)) == 0) { + num_reg++; + } + +error: + /* Free all resouces here */ + if (cmd) + isns_free_pdu(cmd); + if (rsp) + isns_free_pdu(rsp); + if (src_nm) + free(src_nm); + return (ret); +} + +/* + * DevAttrQry for iscsi initiator + * See RFC 4171 Sect. 5.6.5.2 for query detail + */ +static int +isns_dev_attr_qry(int so, char *target, char *initiator) +{ + isns_pdu_t *cmd; + isns_rsp_t *rsp; + uint32_t flags = 0; + int ret = -1; + size_t remain; + isns_tlv_t *tlv; + uint8_t *ptr; + + queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_QRY"); + + if (isns_create_pdu(ISNS_DEV_ATTR_QRY, flags, &cmd) != 0) { + return (-1); + } + + /* source attribute */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(target), target, 0) == -1) { + goto error; + } + + /* message key attribute */ + /* iscsi initiator node type */ + if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, + ISNS_NODE_TYP_SZ, NULL, ISNS_INITIATOR_NODE_TYPE) == -1) { + goto error; + } + + /* delimiter */ + if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) { + goto error; + } + + /* + * operating attributes + * Query Iscsi initiator with zero length TLV operating + * attribute + */ + + /* iscsi name */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + 0, NULL, 0) != 0) { + goto error; + } + + if (isns_send(so, cmd) == -1) { + syslog(LOG_ERR, "isns_dev_attr_qry fails isns_send"); + goto error; + } + + /* recv response */ + if (isns_recv(so, &rsp) == -1) { + syslog(LOG_ERR, "isns_dev_attr_qry fails isns_recv "); + goto error; + } + + /* process response */ + if ((ret = process_rsp(cmd, rsp)) == 0) { + /* compare initiator name to the response, success if found */ + /* subtract out status word */ + remain = rsp->pdu_len - ISNS_STATUS_SZ; + ptr = rsp->data; + + while (remain > 0) { + /* LINTED */ + tlv = (isns_tlv_t *)ptr; + + /* debug only */ + print_ntoh_tlv(tlv); + + /* process tag-len-value */ + ntoh_tlv(tlv); + /* + * let's process the data, only interested + * in iscsi name, skip everything else for + * now. + */ + if (tlv->attr_id == ISNS_ISCSI_NAME_ATTR_ID) { + if (strncmp((char *)tlv->attr_value, initiator, + tlv->attr_len) == 0) { + break; + } + } + /* next tlv */ + remain -= ISNS_ATTR_SZ(tlv->attr_len); + ptr += ISNS_ATTR_SZ(tlv->attr_len); + } + ret = (remain > 0) ? 1 : 0; + } + +error: + if (cmd) + isns_free_pdu(cmd); + if (rsp) + isns_free_pdu(rsp); + return (ret); +} + +/* + * SCNReg + * See RFC 4171 Section 5.6.5.5 + */ +static int +isns_scn_reg(int so, char *node) +{ + isns_pdu_t *cmd; + isns_rsp_t *rsp; + uint32_t flags = 0; + uint32_t bitmap = 0; + int ret = -1; + + queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_SCN_REG"); + + if (isns_create_pdu(ISNS_SCN_REG, flags, &cmd) != 0) { + return (-1); + } + + /* source attribute */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(node), node, 0) == -1) { + goto error; + } + + /* message key attribute */ + /* iscsi initiator node name */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(node), node, 0) != 0) { + goto error; + } + + /* delimiter */ + if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) { + goto error; + } + + /* SCN bitmap */ + bitmap = ISNS_INIT_SELF_INFO_ONLY | ISNS_OBJ_REMOVED | + ISNS_OBJ_ADDED | ISNS_OBJ_UPDATED; + if (isns_append_attr(cmd, ISNS_ISCSI_SCN_BITMAP_ATTR_ID, + ISNS_SCN_BITMAP_SZ, NULL, bitmap) == -1) { + goto error; + } + + if (isns_send(so, cmd) == -1) { + syslog(LOG_ERR, "isns_scn_reg fails isns_send"); + goto error; + } + + if (isns_recv(so, &rsp) == -1) { + syslog(LOG_ERR, "isns_scn_reg fails isns_recv "); + goto error; + } + + /* process response */ + if (process_rsp(cmd, rsp) == 0) { + ret = 0; + } + +error: + if (cmd) + isns_free_pdu(cmd); + if (rsp) + isns_free_pdu(rsp); + return (ret); +} + + +/* + * SCNDereg + */ +static int +isns_scn_dereg(int so, char *node) +{ + isns_pdu_t *cmd = NULL; + isns_rsp_t *rsp = NULL; + uint32_t flags = 0; + int ret = -1; + + queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_SCN_DEREG"); + + if (isns_create_pdu(ISNS_SCN_DEREG, flags, &cmd) != 0) { + return (-1); + } + + /* source attribute */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(node), node, 0) == -1) { + goto error; + } + + /* message key attribute */ + /* iscsi initiator node name */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(node), node, 0) != 0) { + goto error; + } + + if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) { + goto error; + } + + if (isns_send(so, cmd) == -1) { + syslog(LOG_ERR, "isns_scn_reg fails isns_send"); + goto error; + } + + if (isns_recv(so, &rsp) == -1) { + syslog(LOG_ERR, "isns_scn_reg fails isns_recv "); + goto error; + } + + /* process response */ + if (process_rsp(cmd, rsp) == 0) { + ret = 0; + } + +error: + if (cmd) + isns_free_pdu(cmd); + if (rsp) + isns_free_pdu(rsp); + return (ret); +} + +/* + * isns_reg is called to register new target + */ +int +isns_reg(char *targ) +{ + int so; + tgt_node_t *tgt; + char *iqn; + + if ((so = isns_open(isns_args.server)) == -1) { + syslog(LOG_ERR, "isns_reg failed"); + return (-1); + } + + /* + * Open targets_config and devAttrReg all nodes + */ + if ((tgt = find_tgt_by_name(targ, &iqn)) != NULL) { + if (isns_dev_attr_reg(so, tgt, iqn, tgt->x_value) != 0) { + syslog(LOG_ALERT, "ISNS registration failed %s\n", + tgt->x_value); + } + if (isns_scn_reg(so, iqn) == -1) { + syslog(LOG_ERR, "ISNS SCN register failed\n"); + } + free(iqn); + } + + isns_close(so); + return (0); +} + + +/* + * Register all iscsi target nodes from the XML database + * Alway use the ISNS_FLAG_REPLACE_REG flag + */ +int +isns_reg_all() +{ + int so; + uint32_t flags = ISNS_FLAG_REPLACE_REG; + isns_pdu_t *cmd; + isns_rsp_t *rsp; + char *n = NULL; + char *a = NULL; + char alias[MAXNAMELEN]; + char iname[MAXNAMELEN]; + tgt_node_t *tgt = NULL; + int ret = -1; + int tgt_cnt = 0; + + /* + * get the 1st target and use it for the source attribute + */ + if ((tgt = tgt_node_next(targets_config, XML_ELEMENT_TARG, tgt)) + == NULL) { + syslog(LOG_ALERT, "ISNS: no iscsi target found\n"); + return (-1); + } + if (tgt->x_value == NULL) { + syslog(LOG_ALERT, "ISNS: target with NULL local name\n"); + return (-1); + } + if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n) + == FALSE) { + syslog(LOG_ALERT, "ISNS: no XML_ELEMENT_INAME found\n"); + return (-1); + } + strcpy(iname, n); + free(n); + + if ((so = isns_open(isns_args.server)) == -1) { + syslog(LOG_ALERT, "ISNS: fails to connect to %s\n", + isns_args.server); + return (-1); + } + + if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) { + goto error; + } + + /* source attribute */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(iname), iname, 0) != 0) { + goto error; + } + + /* add message key attribute */ + if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, + STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { + goto error; + } + + /* add delimiter */ + if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) { + goto error; + } + + /* entity id */ + if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, + STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { + goto error; + } + + /* entity type */ + if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID, + ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) { + goto error; + } + + /* portal ip-addr */ + if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID, + eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr, + eid_ip.ip_len) != 0) { + goto error; + } + + /* portal port */ + if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID, + ISNS_PORT_SZ, NULL, iscsi_port) != 0) { + goto error; + } + + /* ESI interval */ + if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID, + ISNS_ESI_TICK_SZ, NULL, 10) != 0) { + goto error; + } + + + /* scn port */ + if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID, + ISNS_PORT_SZ, NULL, scn_port) != 0) { + goto error; + } + + /* esi port */ + if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID, + ISNS_PORT_SZ, NULL, scn_port) != 0) { + goto error; + } + + /* + * Open targets_config and devAttrReg all nodes + */ + tgt = NULL; + while ((tgt = tgt_node_next(targets_config, XML_ELEMENT_TARG, tgt)) + != NULL) { + if (tgt->x_value == NULL) { + syslog(LOG_ALERT, "ISNS: target with NULL name\n"); + continue; + } + /* use this value as alias if alias is not set */ + strcpy(alias, tgt->x_value); + + if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n) + == FALSE) { + continue; + } + strcpy(iname, n); + free(n); + + /* find alias */ + if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &a) + == TRUE) { + strcpy(alias, a); + free(a); + } + + tgt_cnt++; /* increment target count */ + + /* operation attributes */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(iname), iname, 0) != 0) { + goto error; + } + if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, + 4, NULL, ISNS_TARGET_NODE_TYPE) != 0) { + goto error; + } + if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID, + STRLEN(alias), alias, 0) != 0) { + goto error; + } + + if (append_tpgt(tgt, cmd) != 0) { + goto error; + } + + } + + /* send pdu */ + if (isns_send(so, cmd) == -1) { + goto error; + } + + /* get isns response */ + if (isns_recv(so, &rsp) == -1) { + goto error; + } + + /* process response */ + if (process_rsp(cmd, rsp) == 0) { + ret = 0; + num_reg = tgt_cnt; + queue_prt(mgmtq, Q_ISNS_DBG, "DevAttrRegAll successful"); + } else { + syslog(LOG_ALERT, "DevAttrReg failed"); + } + +error: + if (cmd) + isns_free_pdu(cmd); + if (rsp) + isns_free_pdu(rsp); + isns_close(so); + return (ret); +} + +/* + * Deregister an iscsi target node + */ +int +isns_dereg(char *name) +{ + int so; + int ret; + + if ((so = isns_open(isns_args.server)) == -1) { + return (-1); + } + + ret = isns_dev_attr_dereg(so, name); + + isns_close(so); + return (ret); +} + +/* + * Update an existing iscsi target property + */ +int +isns_dev_update(char *targ, uint32_t mods) +{ + int so; + int flags = 0; /* update only */ + char *iname = NULL; + char *dummy = NULL; + char alias[MAXNAMELEN]; + tgt_node_t *tgt = NULL; + isns_pdu_t *cmd; + isns_rsp_t *rsp; + int ret = -1; + + if (mods == 0) + return (0); + + if ((tgt = find_tgt_by_name(targ, &iname)) != NULL) { + if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &dummy) == + True) { + strcpy(alias, dummy); + free(dummy); + } else + strcpy(alias, tgt->x_value); + + if ((so = isns_open(isns_args.server)) < 0) { + goto error; + } + + if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd)) { + goto error; + } + /* source attr, msg key, delimiter */ + if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, + STRLEN(iname), iname, 0) != 0) { + goto error; + } + if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, + STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { + goto error; + } + if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) + != 0) { + goto error; + } + + /* + * get current operating attributes, alias & portal group + * objects, these should be the only things that get change + */ + isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, STRLEN(iname), + iname, 0); + isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, + ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE); + + if (mods & ISNS_MOD_ALIAS) + if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID, + STRLEN(alias), alias, 0) != 0) { + goto error; + } + + if (mods & ISNS_MOD_TPGT) + if (append_tpgt(tgt, cmd) != 0) { + goto error; + } + + if (isns_send(so, (isns_pdu_t *)cmd) < 0) { + goto error; + } + + if (isns_recv(so, &rsp) == -1) { + goto error; + } + + /* process response, if failed do a isns_reg_all */ + if ((ret = process_rsp(cmd, rsp)) == -1) { + if (isns_reg_all() != 0 || isns_scn_reg_all() != 0) { + syslog(LOG_ALERT, "ISNS register failed\n"); + goto error; + } + ret = 0; + } else { + if (isns_scn_reg(so, iname) == -1) { + syslog(LOG_ERR, "ISNS SCN register failed\n"); + goto error; + } + ret = 0; + } + } else { + syslog(LOG_ERR, "ISNS: fails to update target %s\n", alias); + } + +error: + if (cmd) + isns_free_pdu(cmd); + if (rsp) + isns_free_pdu(rsp); + if (iname) + free(iname); + isns_close(so); + return (ret); +} + + +/* + * Deregister all iscsi target nodes from the XML database + */ +int +isns_dereg_all() +{ + return (isns_op_all(ISNS_DEV_DEREG)); +} + +int +isns_scn_reg_all() +{ + return (isns_op_all(ISNS_SCN_REG)); +} + +int +isns_scn_dereg_all() +{ + return (isns_op_all(ISNS_SCN_DEREG)); +} + +/* + * Query an iscsi initiator node + */ +Boolean_t +isns_qry_initiator(char *target, char *initiator) +{ + int so; + int ret; + + if ((so = isns_open(isns_args.server)) == -1) { + syslog(LOG_ERR, "isns_qry failed"); + return (-1); + } + + ret = isns_dev_attr_qry(so, target, initiator); + + isns_close(so); + return (ret == 1 ? True : False); +} + +Boolean_t +isns_enabled() +{ + Boolean_t isns_access = False; + char *isns_srv = NULL; + + (void) tgt_find_value_boolean(main_config, XML_ELEMENT_ISNS_ACCESS, + &isns_access); + /* get isns server info */ + if (isns_access == True) { + if (tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV, + &isns_srv) == True) { + free(isns_srv); + return (True); + } + } + return (False); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/iscsi/iscsitgtd/isns_client.h Tue May 29 17:13:54 2007 -0700 @@ -0,0 +1,167 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _ISNS_CLIENT_H +#define _ISNS_CLIENT_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <netdb.h> +#include "queue.h" + +#include "isns_protocol.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* isns update bitmap */ +#define ISNS_MOD_ALIAS 0x1 +#define ISNS_MOD_TPGT 0x2 + +/* iscsi isns protocol */ + +/* + * Attribute size + */ +#define ISNS_ISCSI_TYPE_SZ (4) +#define ISNS_SCN_BITMAP_SZ (4) +#define ISNS_PORT_SZ (4) +#define ISNS_ESI_TICK_SZ (4) +#define ISNS_PG_TAG_SZ (4) +#define ISNS_ENTITY_TYP_SZ (4) +#define ISNS_NODE_TYP_SZ (4) + +/* + * iSNS attribute length: See RFC 4171 Section 6.1 + * iSCSI Name = 4-224 + * iSCSI Alias = 4-256 + */ +#define ISCSI_MAX_NAME 224 +#define ISCSI_MAX_ALIAS 256 + +/* + * Default pdu payload size, this is derived from a typical DevAttrReg + * request, this should be sufficient for all requests. + */ +#define MAX_PDU_SZ (16384) +#define MAX_PDU_PAYLOAD_SZ (MAX_PDU_SZ - ISNSP_HEADER_SIZE) +#define TAG_LEN_SZ (8) + +/* various isns data size */ +#define ISNS_STATUS_SZ (4) +#define ISNS_ATTR_SZ(attr_len) (attr_len + TAG_LEN_SZ) + +/* + * PDU length is 4 bytes aligned. See RFC 4171 Section 5.1.3 + */ +#define PAD4(a) ((a%4) ? ((4-a%4)+a) : a) + +/* + * Macro to check 1st and last pdu + */ +#define IS_1ST_PDU(x) ((x & ISNS_FLAG_FIRST_PDU) ? 1 : 0) +#define IS_LAST_PDU(x) ((x & ISNS_FLAG_LAST_PDU) ? 1 : 0) + +/* RFC 4171 section 6 - null is included in strlen */ +#define STRLEN(x) (strlen(x) + 1) + +typedef struct esi_scn_arg { + char entity[MAXHOSTNAMELEN]; /* iscsi target entity */ + char server[MAXHOSTNAMELEN]; /* isns server */ + int isns_port; /* isns server port */ +} esi_scn_arg_t; + +/* + * ISNS message header + * See RFC 4171 Section 5.0 & 5.1 + */ +typedef struct isns_hdr { + uint16_t version; + uint16_t func_id; + uint16_t pdu_len; + uint16_t flags; + uint16_t xid; + uint16_t seqid; +} isns_hdr_t; + +/* + * ISNS attribute, the attribute is in Tag-Length_Value format + * attr_len: NULLs are included in the length + * attr_value: is variable size and it is 4 bytes aligned + */ +#if 0 +typedef struct isns_attr { + uint32_t tag; + uint32_t len; + uint8_t val[1]; +} isns_attr_t; +#endif + +typedef struct isns_rsp { + uint16_t version; + uint16_t func_id; + uint16_t pdu_len; + uint16_t flags; + uint16_t xid; + uint16_t seqid; + uint32_t status; + uint8_t data[1]; +} isns_rsp_t; + +/* Function prototype */ +int isns_init(target_queue_t *q); +int isns_update(); +void isns_fini(); +Boolean_t isns_qry_initiator(char *, char *); +int isns_reg(char *); +int isns_reg_all(); +int isns_dereg(char *); +int isns_dereg_all(); +int isns_scn_reg_all(); +int isns_scn_dereg_all(); +int isns_dev_update(char *, uint32_t); +Boolean_t isns_enabled(); +void isns_tpgt_update(); +int isns_open(char *); +void isns_close(int); +int isns_append_attr(isns_pdu_t *, uint32_t, uint32_t, void *, + uint32_t); +int isns_create_pdu(uint16_t, uint32_t, isns_pdu_t **); +void isns_free_pdu(void *); +int isns_send(int, isns_pdu_t *); +int isns_recv(int, isns_rsp_t **); +void ntoh_isns_hdr(isns_hdr_t *); +void ntoh_tlv(isns_tlv_t *); +void print_ntoh_tlv(isns_tlv_t *); +void print_attr(isns_tlv_t *attr, void *pval, uint32_t ival); +void print_isns_hdr(isns_hdr_t *); + +#endif /* _ISNS_CLIENT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/iscsi/iscsitgtd/isns_protocol.h Tue May 29 17:13:54 2007 -0700 @@ -0,0 +1,200 @@ + +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _ISNS_PROTOCOL_H +#define _ISNS_PROTOCOL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/types.h> + +#define ISNSP_VERSION (0x01) + +#define ISNS_DEFAULT_SERVER_PORT (3205) + +#define ISNSP_HEADER_SIZE (12) +#define ISNSP_MAX_PAYLOAD_SIZE (65532) +#define ISNSP_MAX_PDU_SIZE (ISNSP_HEADER_SIZE + \ + ISNSP_MAX_PAYLOAD_SIZE) + +#define ISNS_TLV_ATTR_ID_LEN (4) +#define ISNS_TLV_ATTR_LEN_LEN (4) +#define MAX_ISNS_MESG_ATTR_ENTRIES (8) +#define MAX_ISNS_OPER_ATTR_ENTRIES (32) + +/* iSNS Entity Protocol, iSNS Draft - section 6.2.2. */ +#define ISNS_ENTITY_PROTOCOL_NO (1) +#define ISNS_ENTITY_PROTOCOL_ISCSI (2) +#define ISNS_ENTITY_PROTOCOL_FCP (3) + +/* iSNS Function IDs, iSNS Draft - section 4.1.3. */ +#define ISNS_DEV_ATTR_REG (0x0001) +#define ISNS_DEV_ATTR_QRY (0x0002) +#define ISNS_DEV_GET_NEXT (0x0003) +#define ISNS_DEV_DEREG (0x0004) +#define ISNS_SCN_REG (0x0005) +#define ISNS_SCN_DEREG (0x0006) +#define ISNS_SCN (0x0008) +#define ISNS_ESI (0x000D) +#define ISNS_HEARTBEAT (0x000E) +#define ISNS_DEV_ATTR_REG_RSP (0x8001) +#define ISNS_DEV_ATTR_QRY_RSP (0x8002) +#define ISNS_DEV_DEREG_RSP (0x8004) +#define ISNS_SCN_REG_RSP (0x8005) +#define ISNS_SCN_DEREG_RSP (0x8006) +#define ISNS_SCN_RSP (0x8008) +#define ISNS_ESI_RSP (0x800D) + +/* iSNS Flags, iSNS Draft - section 5.1.4. */ +#define ISNS_FLAG_FIRST_PDU (0x0400) +#define ISNS_FLAG_LAST_PDU (0x0800) +#define ISNS_FLAG_REPLACE_REG (0x1000) +#define ISNS_FLAG_AUTH_BLK_PRESENTED (0x2000) +#define ISNS_FLAG_SERVER (0x4000) +#define ISNS_FLAG_CLIENT (0x8000) + +/* iSNS Response Status, iSNS Draft - section 5.4 */ +#define ISNS_RSP_SUCCESSFUL (0x0000) +#define ISNS_RSP_UNKNOWN_ERROR (0x0001) +#define ISNS_RSP_MSG_FORMAT_ERROR (0x0002) +#define ISNS_RSP_INVALID_REGIS (0x0003) +#define ISNS_RSP_INVALID_QRY (0x0005) +#define ISNS_RSP_SRC_UNKNOWN (0x0006) +#define ISNS_RSP_SRC_ABSENT (0x0007) +#define ISNS_RSP_SRC_UNAUTHORIZED (0x0008) +#define ISNS_RSP_NO_SUCH_ENTRY (0x0009) +#define ISNS_RSP_VER_NOT_SUPPORTED (0X0010) +#define ISNS_RSP_INTERNAL_ERROR (0x0011) +#define ISNS_RSP_BUSY (0x0012) +#define ISNS_RSP_OPTION_NOT_UNDERSTOOD (0x0013) +#define ISNS_RSP_INVALID_UPDATE (0x0014) +#define ISNS_RSP_MSG_NOT_SUPPORTED (0x0015) +#define ISNS_RSP_SCN_EVENT_REJECTED (0X0016) +#define ISNS_RSP_SCN_REGIS_REJECTED (0x0017) +#define ISNS_RSP_ATTR_NOT_IMPL (0x0018) +#define ISNS_RSP_ESI_NOT_AVAILABLE (0x0021) +#define ISNS_RSP_INVALID_DEREGIS (0x0022) +#define ISNS_RSP_REGIS_NOT_SUPPORTED (0x0023) + +/* iSCSI Node Type, iSNS Draft - section 6.4.2. */ +#define ISNS_TARGET_NODE_TYPE (0x0001) +#define ISNS_INITIATOR_NODE_TYPE (0x0002) +#define ISNS_CONTROL_NODE_TYPE (0x0004) + +/* iSCSI Node SCN Bitmap, iSNS Draft - section 6.4.4. */ +#define ISNS_INIT_SELF_INFO_ONLY (0x0080) /* Bit 24 */ +#define ISNS_TARGET_SELF_INFO_ONLY (0x0040) /* Bit 25 */ +#define ISNS_MGMT_REG (0x0020) /* Bit 26 */ +#define ISNS_OBJ_REMOVED (0x0010) /* Bit 27 */ +#define ISNS_OBJ_ADDED (0x0008) /* Bit 28 */ +#define ISNS_OBJ_UPDATED (0x0004) /* Bit 29 */ +#define ISNS_OBJ_MEMBER_REMOVED (0x0002) /* Bit 30 */ +#define ISNS_OBJ_MEMBER_ADDED (0x0001) /* Bit 31 */ + +/* iSNS Attribute IDs, iSNS Draft - section 6.1. */ +#define ISNS_DELIMITER_ATTR_ID (0) +#define ISNS_EID_ATTR_ID (1) +#define ISNS_ENTITY_PROTOCOL_ATTR_ID (2) +#define ISNS_TIMESTAMP_ATTR_ID (4) +#define ISNS_PORTAL_IP_ADDR_ATTR_ID (16) +#define ISNS_PORTAL_PORT_ATTR_ID (17) +#define ISNS_PORTAL_NAME_ATTR_ID (18) +#define ISNS_ESI_INTERVAL_ATTR_ID (19) +#define ISNS_ESI_PORT_ATTR_ID (20) +#define ISNS_SCN_PORT_ATTR_ID (23) +#define ISNS_ISCSI_NAME_ATTR_ID (32) +#define ISNS_ISCSI_NODE_TYPE_ATTR_ID (33) +#define ISNS_ISCSI_ALIAS_ATTR_ID (34) +#define ISNS_ISCSI_SCN_BITMAP_ATTR_ID (35) +#define ISNS_PG_ISCSI_NAME_ATTR_ID (48) +#define ISNS_PG_PORTAL_IP_ADDR_ATTR_ID (49) +#define ISNS_PG_PORTAL_PORT_ATTR_ID (50) +#define ISNS_PG_TAG_ATTR_ID (51) +#define ISNS_PG_INDEX_ATTR_ID (52) + +/* iSNS Defaults */ +#define ISNS_DEFAULT_SERVER_PORT (3205) + +typedef struct isns_tlv { + uint32_t attr_id; + uint32_t attr_len; + uint8_t attr_value[1]; +} isns_tlv_t; + +typedef struct isns_packet_data { + uint16_t version; + uint16_t func_id; + uint16_t payload_len; + uint16_t flags; + uint16_t xid; + uint16_t seq; + + int num_of_tlvs; + isns_tlv_t tlvs[MAX_ISNS_OPER_ATTR_ENTRIES]; +} isns_packet_data_t; + +typedef struct isns_reg_mesg { + isns_tlv_t src_attr; + int num_of_mesg_attrs; + isns_tlv_t *mesg_attrs[MAX_ISNS_MESG_ATTR_ENTRIES]; + isns_tlv_t delimiter_attr; + isns_tlv_t *operating_attrs[MAX_ISNS_OPER_ATTR_ENTRIES]; +} isns_reg_mesg_t; + +typedef struct isns_resp_mesg { + uint8_t status[4]; + isns_tlv_t messages_attrs[MAX_ISNS_MESG_ATTR_ENTRIES]; + isns_tlv_t delimiter_attr; + isns_tlv_t operating_attrs[MAX_ISNS_OPER_ATTR_ENTRIES]; +} isns_resp_mesg_t; + +typedef struct isns_pdu { + uint16_t version; + uint16_t func_id; + uint16_t payload_len; + uint16_t flags; + uint16_t xid; + uint16_t seq; + uint8_t payload[1]; +} isns_pdu_t; + +typedef struct isns_resp { + uint32_t status; + uint8_t data[1]; +} isns_resp_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _ISNS_PROTOCOL_H */
--- a/usr/src/cmd/iscsi/iscsitgtd/main.c Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/main.c Tue May 29 17:13:54 2007 -0700 @@ -68,6 +68,8 @@ #include "errcode.h" #include "t10.h" +#include "isns_client.h" + #define EMPTY_CONFIG "<config version='1.0'>\n</config>\n" /* ---- Forward declarations ---- */ @@ -116,6 +118,7 @@ {XML_ELEMENT_RAD_SERV, valid_radius_srv}, {XML_ELEMENT_RAD_SECRET, 0}, {XML_ELEMENT_ISNS_ACCESS, 0}, + {XML_ELEMENT_ISNS_SERV, valid_isns_srv}, {XML_ELEMENT_FAST, 0}, {0, 0} }; @@ -153,11 +156,11 @@ process_target_config() { xmlTextReaderPtr r = NULL; - char path[MAXPATHLEN], - *target = NULL; + char path[MAXPATHLEN]; + char *target = NULL; struct stat ss; - tgt_node_t *node = NULL, - *next = NULL; + tgt_node_t *node = NULL; + tgt_node_t *next = NULL; int xml_fd = -1; if (target_basedir != NULL) { @@ -300,8 +303,8 @@ process_config(char *file) { xmlTextReaderPtr r; - int ret, - xml_fd = -1; + int ret; + int xml_fd = -1; tgt_node_t *node = NULL; #ifndef lint @@ -403,8 +406,7 @@ static void * logout_cleanup(void *v) { - int msg_sent, - i; + int msg_sent, i; char *targ = (char *)v; mgmt_request_t m; iscsi_conn_t *conn; @@ -446,8 +448,7 @@ { mgmt_request_t m; iscsi_conn_t *conn; - int i, - msg_sent; + int i, msg_sent; pthread_t junk; extern pthread_mutex_t port_mutex; @@ -690,8 +691,7 @@ static void setup_door(target_queue_t *q, char *door_name) { - int did, - fd; + int did, fd; struct stat s; door_arg_t d; char *msg = NULL; @@ -810,16 +810,13 @@ int main(int argc, char **argv) { - char c, - *p, - *door_name; + char c, *p, *door_name; msg_t *msg; target_queue_t *q; - port_args_t port1, - port2; - Boolean_t mgmt_up = False, - daemonize = True, - console_output = True; + port_args_t port1, port2; + Boolean_t mgmt_up = False; + Boolean_t daemonize = True; + Boolean_t console_output = True; pthread_t junk; mgmt_request_t *mgmt; struct sigaction act; @@ -971,6 +968,7 @@ port_init(); queue_init(); util_init(); + isns_init(q); /* * If there's no MAC address currently available don't worry about
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c Tue May 29 17:13:54 2007 -0700 @@ -54,6 +54,7 @@ #include "utility.h" #include "errcode.h" #include "t10_spc.h" +#include "isns_client.h" extern char *getfullrawname(); @@ -86,8 +87,8 @@ ucred_t *cred) { tgt_node_t *x; - char msgbuf[80], - *reply_msg = NULL; + char msgbuf[80]; + char *reply_msg = NULL; if (p->x_child == NULL) { xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT); @@ -120,19 +121,17 @@ static char * create_target(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *name = NULL, - *alias = NULL, - *size = NULL, - *type = NULL, - *backing = NULL, - *node_name = NULL, - path[MAXPATHLEN]; - int lun = 0, /* default to LUN 0 */ - i; - tgt_node_t *n, - *c, - *l; + char *msg = NULL; + char *name = NULL; + char *alias = NULL; + char *size = NULL; + char *type = NULL; + char *backing = NULL; + char *node_name = NULL; + char path[MAXPATHLEN]; + int lun = 0; /* default to LUN 0 */ + int i; + tgt_node_t *n, *c, *l; err_code_t code; const priv_set_t *eset; @@ -270,6 +269,14 @@ if (update_config_targets(&msg) == False) goto error; + /* Only isns register on the 1st creation of the target */ + if (lun == 0 && isns_enabled() == True) { + if (isns_reg(node_name) != 0) { + xml_rtn_msg(&msg, ERR_ISNS_ERROR); + goto error; + } + } + } else if ((lun == 0) && (code != ERR_LUN_EXISTS)) { /* @@ -308,12 +315,11 @@ static char * create_initiator(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *name = NULL, - *iscsi_name = NULL; - tgt_node_t *inode = NULL, - *n, - *c; + char *msg = NULL; + char *name = NULL; + char *iscsi_name = NULL; + tgt_node_t *inode = NULL; + tgt_node_t *n, *c; const priv_set_t *eset; eset = ucred_getprivset(cred, PRIV_EFFECTIVE); @@ -364,11 +370,11 @@ static char * create_tpgt(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *tpgt = NULL, - *extra = NULL; - tgt_node_t *tnode = NULL, - *n; + char *msg = NULL; + char *tpgt = NULL; + char *extra = NULL; + tgt_node_t *tnode = NULL; + tgt_node_t *n; int tpgt_val; const priv_set_t *eset; @@ -422,20 +428,20 @@ static char * create_zfs(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *dataset = NULL, - *node_name = NULL, - *prop = NULL, - path[MAXPATHLEN], - *cp, /* current pair */ - *np, /* next pair */ - *vp; /* value pointer */ - tgt_node_t *dnode = NULL, - *n, - *c, - *attr, - *ll, - *l; + char *msg = NULL; + char *dataset = NULL; + char *node_name = NULL; + char *prop = NULL; + char path[MAXPATHLEN]; + char *cp; /* current pair */ + char *np; /* next pair */ + char *vp; /* value pointer */ + tgt_node_t *dnode = NULL; + tgt_node_t *n; + tgt_node_t *c; + tgt_node_t *attr; + tgt_node_t *ll; + tgt_node_t *l; libzfs_handle_t *zh = NULL; zfs_handle_t *zfsh = NULL; uint64_t size; @@ -583,6 +589,7 @@ c = tgt_node_alloc(XML_ELEMENT_INAME, String, node_name); tgt_node_add(n, c); + free(node_name); c = tgt_node_alloc(XML_ELEMENT_LUNLIST, String, ""); tgt_node_add(n, c); @@ -636,6 +643,16 @@ tgt_node_add(targets_config, n); + /* register with iSNS */ + node_name = NULL; + if (isns_enabled() == True) { + (void) tgt_find_value_str(n, XML_ELEMENT_INAME, &node_name); + if (isns_reg(node_name) != 0) { + xml_rtn_msg(&msg, ERR_ISNS_ERROR); + goto error; + } + } + xml_rtn_msg(&msg, ERR_SUCCESS); error: if (zfsh) @@ -666,9 +683,9 @@ create_node_name(char *local_nick, char *alias) { uuid_t id; - char id_str[37], - *p, - *anp; /* alias or nick pointer */ + char id_str[37]; + char *p; + char *anp; /* alias or nick pointer */ if ((p = (char *)malloc(ISCSI_MAX_NAME_LEN)) == NULL) return (NULL); @@ -718,8 +735,8 @@ static Boolean_t create_target_dir(char *targ_name, char *local_name) { - char path[MAXPATHLEN], - sympath[MAXPATHLEN]; + char path[MAXPATHLEN]; + char sympath[MAXPATHLEN]; if ((mkdir(target_basedir, 0777) == -1) && (errno != EEXIST)) return (False); @@ -750,16 +767,16 @@ err_code_t *code) { uint64_t size; - int fd = -1, - rpm = DEFAULT_RPM, - heads = DEFAULT_HEADS, - cylinders = DEFAULT_CYLINDERS, - spt = DEFAULT_SPT, - bytes_sect = DEFAULT_BYTES_PER, - interleave = DEFAULT_INTERLEAVE; - char *vid = DEFAULT_VID, - *pid = DEFAULT_PID, - path[MAXPATHLEN]; + int fd = -1; + int rpm = DEFAULT_RPM; + int heads = DEFAULT_HEADS; + int cylinders = DEFAULT_CYLINDERS; + int spt = DEFAULT_SPT; + int bytes_sect = DEFAULT_BYTES_PER; + int interleave = DEFAULT_INTERLEAVE; + char *vid = DEFAULT_VID; + char *pid = DEFAULT_PID; + char path[MAXPATHLEN]; FILE *fp = NULL; /* @@ -918,11 +935,11 @@ { struct stat s; int fd = -1; - char path[MAXPATHLEN], - buf[512]; + char path[MAXPATHLEN]; + char buf[512]; struct statvfs fs; - tgt_node_t *node = NULL, - *c; + tgt_node_t *node = NULL; + tgt_node_t *c; xmlTextReaderPtr r; /* @@ -1088,12 +1105,10 @@ uint64_t *size) { struct stat s; - char *raw_name, - buf[512]; + char *raw_name, buf[512]; struct vtoc vtoc; struct dk_gpt *efi; - int slice, - fd; + int slice, fd; /* * Error checking regarding size and backing store has already @@ -1293,11 +1308,8 @@ zfs_lun(tgt_node_t *l, uint64_t size, char *dataset) { tgt_node_t *c; - int cylinders, - heads, - spt, - val, - guid; + int cylinders, heads, spt, val, guid; + create_geom(size, &cylinders, &heads, &spt); guid = 0;
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c Tue May 29 17:13:54 2007 -0700 @@ -47,6 +47,7 @@ #include "iscsi_cmd.h" #include "target.h" #include "errcode.h" +#include "isns_client.h" static char *modify_target(tgt_node_t *x, ucred_t *cred); static char *modify_initiator(tgt_node_t *x, ucred_t *cred); @@ -101,28 +102,27 @@ static char * modify_target(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *name = NULL, - *iscsi, - *prop = NULL, - size_str[16], - path[MAXPATHLEN], - *m, - buf[512]; /* one sector size block */ - tgt_node_t *t = NULL, - *list = NULL, - *c = NULL, - *node; + char *msg = NULL; + char *name = NULL; + char *iscsi; + char *prop = NULL; + char size_str[16]; + char path[MAXPATHLEN]; + char *m; + char buf[512]; /* one sector size block */ + tgt_node_t *t = NULL; + tgt_node_t *list = NULL; + tgt_node_t *c = NULL; + tgt_node_t *node; + tgt_node_t *tpgt = NULL; Boolean_t change_made = False; - int lun = 0, - fd, - xml_fd; - uint64_t val, - new_lu_size, - cur_lu_size; + int lun = 0; + int fd, xml_fd; + uint64_t val, new_lu_size, cur_lu_size; struct stat st; xmlTextReaderPtr r; const priv_set_t *eset; + uint32_t isns_mods = 0; eset = ucred_getprivset(cred, PRIV_EFFECTIVE); if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) : @@ -294,7 +294,7 @@ if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) { if (prop == NULL) { - xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL); + xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT); return (msg); } @@ -309,6 +309,21 @@ return (msg); } + /* update isns only if TPGT contains ip_addr */ + while ((tpgt = tgt_node_next(main_config, XML_ELEMENT_TPGT, + tpgt)) != NULL) { + if (strcmp(prop, tpgt->x_value) != 0) + continue; + if (tgt_node_next(tpgt, XML_ELEMENT_IPADDR, NULL) + != NULL) { + isns_mods |= ISNS_MOD_TPGT; + break; + } else { + xml_rtn_msg(&msg, ERR_TPGT_NO_IPADDR); + return (msg); + } + } + if ((c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop)) == NULL) { free(prop); @@ -335,8 +350,10 @@ tgt_node_add(list, c); tgt_node_add(t, list); } + free(prop); prop = NULL; + change_made = True; } @@ -383,6 +400,7 @@ } free(prop); prop = NULL; + isns_mods |= ISNS_MOD_ALIAS; change_made = True; } @@ -417,8 +435,17 @@ } if (change_made == True) { - if (update_config_targets(&msg) == True) - xml_rtn_msg(&msg, ERR_SUCCESS); + if (update_config_targets(&msg) == False) { + xml_rtn_msg(&msg, ERR_UPDATE_TARGCFG_FAILED); + return (msg); + } + if (isns_enabled() == True) { + if (isns_dev_update(t->x_value, isns_mods) != 0) { + xml_rtn_msg(&msg, ERR_UPDATE_TARGCFG_FAILED); + return (msg); + } + } + xml_rtn_msg(&msg, ERR_SUCCESS); } else { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND); } @@ -434,9 +461,9 @@ static char * modify_initiator(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *name = NULL, - *prop = NULL; + char *msg = NULL; + char *name = NULL; + char *prop = NULL; tgt_node_t *inode = NULL; Boolean_t changes_made = False; const priv_set_t *eset; @@ -519,8 +546,8 @@ static char * modify_admin(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *prop; + char *msg = NULL; + char *prop; Boolean_t changes_made = False; admin_table_t *ap; const priv_set_t *eset; @@ -557,6 +584,11 @@ } if (changes_made == True) { + /* isns_update updates isns_access & isns server name */ + if (isns_update() != 0) { + xml_rtn_msg(&msg, ERR_ISNS_ERROR); + return (msg); + } if (update_config_main(&msg) == True) xml_rtn_msg(&msg, ERR_SUCCESS); } else { @@ -575,9 +607,9 @@ modify_tpgt(tgt_node_t *x, ucred_t *cred) { struct addrinfo *res = NULL; - char *msg = NULL, - *name = NULL, - *ip_str = NULL; + char *msg = NULL; + char *name = NULL; + char *ip_str = NULL; tgt_node_t *tnode = NULL; const priv_set_t *eset; @@ -618,6 +650,14 @@ if (update_config_main(&msg) == True) xml_rtn_msg(&msg, ERR_SUCCESS); + /* + * Re-register all targets, currently there's no method to + * update TPGT for individual target + */ + if (isns_enabled() == True) { + isns_reg_all(); + } + error: if (name) free(name); @@ -636,9 +676,9 @@ static char * modify_zfs(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *prop = NULL, - *dataset = NULL; + char *msg = NULL; + char *prop = NULL; + char *dataset = NULL; libzfs_handle_t *zh = NULL; zfs_handle_t *zfsh = NULL; tgt_node_t *n = NULL; @@ -724,8 +764,8 @@ { tgt_node_t *targ = NULL; int count = 0; - char *msg = NULL, - *val = NULL; + char *msg = NULL; + char *val = NULL; if ((prop == NULL) || (strlen(prop) == 0) || (prop[0] != '/')) { xml_rtn_msg(&msg, ERR_INVALID_BASEDIR); @@ -781,9 +821,8 @@ valid_radius_srv(char *name, char *prop) { struct addrinfo *res = NULL; - char *msg = NULL, - *sp, - *p; + char *msg = NULL; + char *sp, *p; int port; if ((sp = strdup(prop)) == NULL) { @@ -805,3 +844,36 @@ free(sp); return (msg); } + +/* + * []---- + * | validate_isns_server -- validate that server[:port] are valid + * []---- + */ +char * +valid_isns_srv(char *name, char *prop) +{ + struct addrinfo *res = NULL; + char *msg = NULL; + char *sp, *p; + int port; + + if ((sp = strdup(prop)) == NULL) { + xml_rtn_msg(&msg, ERR_NO_MEM); + return (msg); + } else if ((p = strrchr(sp, ':')) != NULL) { + *p++ = '\0'; + port = atoi(p); + if ((port < 1) || (port > 65535)) { + xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV); + free(sp); + return (msg); + } + } + if ((getaddrinfo(sp, NULL, NULL, &res) != 0) || (res == NULL)) + xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV); + else + freeaddrinfo(res); + free(sp); + return (msg); +}
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c Tue May 29 17:13:54 2007 -0700 @@ -36,6 +36,7 @@ #include <strings.h> #include <unistd.h> #include <priv.h> +#include <syslog.h> #include <iscsitgt_impl.h> #include "utility.h" @@ -43,6 +44,7 @@ #include "target.h" #include "iscsi_cmd.h" #include "errcode.h" +#include "isns_client.h" static char *remove_target(tgt_node_t *x, ucred_t *cred); static char *remove_initiator(tgt_node_t *x, ucred_t *cred); @@ -56,8 +58,8 @@ ucred_t *cred) { tgt_node_t *x; - char msgbuf[80], - *reply_msg = NULL; + char msgbuf[80]; + char *reply_msg = NULL; if (p->x_child == NULL) { xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT); @@ -90,8 +92,8 @@ static char * remove_zfs(tgt_node_t *x, ucred_t *cred) { - char *prop, - *msg = NULL; + char *prop; + char *msg = NULL; tgt_node_t *targ = NULL; const priv_set_t *eset; @@ -137,6 +139,10 @@ * to issue the logout we'll have removed reference to the target * such that this can't happen. */ + if (isns_enabled() == True) { + if (isns_dereg(prop) != 0) + syslog(LOG_INFO, "ISNS dereg failed\n"); + } logout_targ(prop); free(prop); @@ -147,11 +153,11 @@ static char * remove_target(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *prop = NULL; - tgt_node_t *targ = NULL, - *list, - *c = NULL; + char *msg = NULL; + char *prop = NULL; + tgt_node_t *targ = NULL; + tgt_node_t *list; + tgt_node_t *c = NULL; Boolean_t change_made = False; int lun_num; const priv_set_t *eset; @@ -221,6 +227,13 @@ if (list->x_child == NULL) (void) tgt_node_remove(targ, list, MatchName); free(prop); + + /* update isns */ + if (isns_enabled()) { + if (isns_dev_update(targ->x_value, ISNS_MOD_TPGT) != 0) + syslog(LOG_ALERT, "ISNS register failed\n"); + } + change_made = True; } if (tgt_find_value_int(x, XML_ELEMENT_LUN, &lun_num) == True) { @@ -247,6 +260,12 @@ if (msg != NULL) goto error; + /* ISNS de-register target if it's the last lun */ + if (lun_num == 0 && isns_enabled() == True) { + if (isns_dereg(prop) != 0) + syslog(LOG_INFO, "ISNS dereg failed\n"); + } + iscsi_inventory_change(prop); free(prop); change_made = True; @@ -272,8 +291,8 @@ static char * remove_initiator(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *name; + char *msg = NULL; + char *name; tgt_node_t *node = NULL; const priv_set_t *eset; @@ -314,10 +333,10 @@ static char * remove_tpgt(tgt_node_t *x, ucred_t *cred) { - char *msg = NULL, - *prop = NULL; - tgt_node_t *node = NULL, - *c = NULL; + char *msg = NULL; + char *prop = NULL; + tgt_node_t *node = NULL; + tgt_node_t *c = NULL; Boolean_t change_made = False; const priv_set_t *eset; @@ -364,6 +383,9 @@ } if (change_made == True) { + /* Isns re-register all target */ + if (isns_enabled() == True) + isns_reg_all(); if (update_config_main(&msg) == True) xml_rtn_msg(&msg, ERR_SUCCESS); } else {
--- a/usr/src/cmd/iscsi/iscsitgtd/queue.h Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/queue.h Tue May 29 17:13:54 2007 -0700 @@ -58,6 +58,8 @@ #define Q_GEN_ERRS 0x01000 #define Q_GEN_DETAILS 0x02000 +#define Q_ISNS_DBG 0x10000 + /* * When used the queue request will be place at the head of the queue. */
--- a/usr/src/cmd/iscsi/iscsitgtd/target.h Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/target.h Tue May 29 17:13:54 2007 -0700 @@ -179,6 +179,7 @@ void logout_targ(char *targ); char *update_basedir(char *, char *); char *valid_radius_srv(char *name, char *prop); +char *valid_isns_srv(char *name, char *prop); Boolean_t if_find_mac(target_queue_t *mgmt); void if_target_address(char **text, int *text_length, struct sockaddr *sp); Boolean_t process_target_config(); @@ -195,7 +196,8 @@ extern int main_vers_maj, main_vers_min, targets_vers_maj, - targets_vers_min; + targets_vers_min, + iscsi_port; extern Boolean_t enforce_strict_guid, thin_provisioning, disable_tpgs,
--- a/usr/src/cmd/iscsi/iscsitgtd/util.c Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/util.c Tue May 29 17:13:54 2007 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -46,6 +46,7 @@ #include "target.h" #include "utility.h" #include "errcode.h" +#include "isns_client.h" #include <sys/scsi/generic/commands.h> #define CRC32_STR "CRC32C" @@ -74,12 +75,51 @@ Boolean_t check_access(tgt_node_t *targ, char *initiator_name, Boolean_t req_chap) { - tgt_node_t *acl, - *inode = NULL, - *tgt_initiator = NULL; + tgt_node_t *acl; + tgt_node_t *inode = NULL; + tgt_node_t *tgt_initiator = NULL; char *dummy; - Boolean_t valid = False, - found_chap = False; + Boolean_t valid = False; + Boolean_t found_chap = False; + Boolean_t access = False; + + /* + * If ISNS is enable check for access privilege from isns server + */ + if (isns_enabled() == True) { + if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &dummy) + == False) { + return (False); + } + access = isns_qry_initiator(dummy, initiator_name); + free(dummy); + if (req_chap == False) { + return (access); + } + + /* Need to check if CHAP is needed for initiator */ + while ((inode = tgt_node_next(main_config, XML_ELEMENT_INIT, + inode)) != NULL) { + if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy) + == True) { + if (strcmp(dummy, initiator_name) == 0) { + free(dummy); + if (tgt_find_value_str(inode, + XML_ELEMENT_CHAPSECRET, &dummy) + == True) { + free(dummy); + found_chap = True; + break; + } + } + } + } + if (access == True) { + if ((req_chap == True) && (found_chap == True)) + access = False; + } + return (access); + } /* * If there's no ACL for this target everyone has access. @@ -153,8 +193,8 @@ static Boolean_t convert_local_tpgt(char **text, int *text_length, char *local_tpgt) { - tgt_node_t *tpgt = NULL, - *x; + tgt_node_t *tpgt = NULL; + tgt_node_t *x; char buf[80]; char ipaddr[4]; @@ -207,15 +247,15 @@ add_target_address(iscsi_conn_t *c, char **text, int *text_length, tgt_node_t *targ) { - tgt_node_t *tpgt_list, - *tpgt = NULL; + tgt_node_t *tpgt_list; + tgt_node_t *tpgt = NULL; struct sockaddr_in *sp4; struct sockaddr_in6 *sp6; /* * 7 is enough room for the largest TPGT of "65536", the ',' and a NULL */ - char buf[INET6_ADDRSTRLEN + 7], - net_buf[INET6_ADDRSTRLEN]; + char buf[INET6_ADDRSTRLEN + 7]; + char net_buf[INET6_ADDRSTRLEN]; if ((tpgt_list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL)) == NULL) { @@ -233,16 +273,16 @@ sp4 = (struct sockaddr_in *)&c->c_target_sockaddr; (void) snprintf(buf, sizeof (buf), "%s,%s", inet_ntop(sp4->sin_family, - (void *)&sp4->sin_addr, - net_buf, sizeof (net_buf)), + (void *)&sp4->sin_addr, + net_buf, sizeof (net_buf)), tpgt->x_value); } else { /*CSTYLED*/ sp6 = (struct sockaddr_in6 *)&c->c_target_sockaddr; (void) snprintf(buf, sizeof (buf), "%s,%s", inet_ntop(sp6->sin6_family, - (void *)&sp6->sin6_addr, - net_buf, sizeof (net_buf)), + (void *)&sp6->sin6_addr, + net_buf, sizeof (net_buf)), tpgt->x_value); } (void) add_text(text, text_length, "TargetAddress", @@ -298,8 +338,8 @@ Boolean_t add_text(char **text, int *current_length, char *name, char *val) { - int dlen = *current_length, - plen; + int dlen = *current_length; + int plen; char *p; /* @@ -385,10 +425,10 @@ parse_text(iscsi_conn_t *c, int dlen, char **text, int *text_length, int *errcode) { - char *p = NULL, - *n, - *cur_pair, - param_rsp[32]; + char *p = NULL; + char *n; + char *cur_pair; + char param_rsp[32]; int plen; /* pair length */ Boolean_t rval = True; char param_buf[16]; @@ -544,7 +584,7 @@ if ((rval = connection_parameters_get(c, n)) == False) { *errcode = (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) | - ISCSI_LOGIN_STATUS_TGT_FORBIDDEN; + ISCSI_LOGIN_STATUS_TGT_FORBIDDEN; } else if ((rval = add_text(text, text_length, "TargetAlias", c->c_targ_alias)) == True) { @@ -767,7 +807,7 @@ * for future processing. */ rval = add_text(text, text_length, - cur_pair, "NotUnderstood"); + cur_pair, "NotUnderstood"); /* * Go ahead a log this information in case we see @@ -822,8 +862,8 @@ find_main_tpgt(struct sockaddr_storage *pst) { char ip_addr[16]; - tgt_node_t *tpgt = NULL, - *ip_node = NULL; + tgt_node_t *tpgt = NULL; + tgt_node_t *ip_node = NULL; struct in_addr addr; struct in6_addr addr6; @@ -844,7 +884,7 @@ if (pst->ss_family == AF_INET) { if (inet_pton(AF_INET, ip_node->x_value, - ip_addr) != 1) { + ip_addr) != 1) { continue; } if (bcmp(ip_addr, &addr, @@ -854,7 +894,7 @@ } else if (pst->ss_family == AF_INET6) { if (inet_pton(AF_INET6, ip_node->x_value, - ip_addr) != 1) { + ip_addr) != 1) { continue; } if (bcmp(ip_addr, &addr6, @@ -880,10 +920,9 @@ static int convert_to_tpgt(iscsi_conn_t *c, tgt_node_t *targ) { - tgt_node_t *list, - *tpgt = NULL; - int addr_tpgt, - pos_tpgt; + tgt_node_t *list; + tgt_node_t *tpgt = NULL; + int addr_tpgt, pos_tpgt; /* * If this target doesn't have a list of target portal group tags @@ -938,8 +977,7 @@ static Boolean_t connection_parameters_get(iscsi_conn_t *c, char *targ_name) { - tgt_node_t *targ, - *alias; + tgt_node_t *targ, *alias; Boolean_t rval = False; if ((targ = find_target_node(targ_name)) != NULL) { @@ -973,10 +1011,9 @@ Boolean_t validate_version(tgt_node_t *node, int *maj_p, int *min_p) { - char *vers_str = NULL, - *minor_part; - int maj, - min; + char *vers_str = NULL; + char *minor_part; + int maj, min; if ((tgt_find_attr_str(node, XML_ELEMENT_VERS, &vers_str) == False) || (vers_str == NULL)) @@ -1005,8 +1042,8 @@ sna_lt(uint32_t n1, uint32_t n2) { return ((n1 != n2) && - (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || - ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); + (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || + ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); } /* @@ -1018,8 +1055,8 @@ sna_lte(uint32_t n1, uint32_t n2) { return ((n1 == n2) || - (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || - ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); + (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) || + ((n1 > n2) && ((n2 - n1) < SNA32_CHECK)))); } Boolean_t @@ -1057,8 +1094,7 @@ */ uint32_t tval = (uint_t)time((time_t *)0); size_t guid_size; - int i, - fd; + int i, fd; if ((mac_len == 0) && (if_find_mac(NULL) == False)) { @@ -1126,8 +1162,8 @@ void create_geom(diskaddr_t size, int *cylinder, int *heads, int *spt) { - diskaddr_t sects = size >> 9, - c, h, s, t; + diskaddr_t sects = size >> 9; + diskaddr_t c, h, s, t; int pass; /* @@ -1226,8 +1262,7 @@ util_title(target_queue_t *q, int type, int num, char *title) { char *type_str; - int len, - pad; + int len, pad; len = strlen(title); pad = len & 1; @@ -1475,17 +1510,13 @@ void remove_target_common(char *name, int lun_num, char **msg) { - tgt_node_t *targ = NULL, - *list, - *lun, - *node, - *c; - char path[MAXPATHLEN], - *tname = NULL, - *iname = NULL, - *bs_path = NULL; - int chk, - xml_fd; + tgt_node_t *targ = NULL; + tgt_node_t *list, *lun, *node, *c; + char path[MAXPATHLEN]; + char *tname = NULL; + char *iname = NULL; + char *bs_path = NULL; + int chk, xml_fd; Boolean_t bs_delete = False; xmlTextReaderPtr r;
--- a/usr/src/cmd/iscsi/iscsitgtd/util_err.c Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/cmd/iscsi/iscsitgtd/util_err.c Tue May 29 17:13:54 2007 -0700 @@ -39,7 +39,7 @@ return ((char *)gettext("Null XML message")); case ERR_SYNTAX_EMPTY: return ((char *)gettext("Syntax error: " - "Empty XML message or syntax error")); + "Empty XML message or syntax error")); case ERR_SYNTAX_MISSING_ALL: return ((char *)gettext("Syntax error: Missing --all")); case ERR_SYNTAX_MISSING_BACKING_STORE: @@ -111,10 +111,10 @@ return ((char *)gettext("TPGT not found")); case ERR_ACCESS_RAW_DEVICE_FAILED: return ((char *)gettext("Failed to " - "access direct access device")); + "access direct access device")); case ERR_CREATE_METADATA_FAILED: return ((char *)gettext("Failed to " - "create meta data for tape device")); + "create meta data for tape device")); case ERR_CREATE_SYMLINK_FAILED: return ((char *)gettext("Failed to " "create symbol link to backing store")); @@ -129,19 +129,19 @@ "exists")); case ERR_DISK_BACKING_MUST_BE_REGULAR_FILE: return ((char *)gettext("For type " - "'disk' backing must be a regular file")); + "'disk' backing must be a regular file")); case ERR_DISK_BACKING_NOT_VALID_RAW: return ((char *)gettext("Backing store is not valid raw " "device")); case ERR_STAT_BACKING_FAILED: return ((char *)gettext("Failed to " - "stat(2) backing for 'disk'")); + "stat(2) backing for 'disk'")); case ERR_RAW_PART_NOT_CAP: return ((char *)gettext("Partition size doesn't match capacity" " of device, use p0 or ctd name")); case ERR_CREATE_TARGET_DIR_FAILED: return ((char *)gettext("Failed to " - "create target directory")); + "create target directory")); case ERR_ENCODE_GUID_FAILED: return ((char *)gettext("Failed to encode GUID value")); case ERR_INIT_XML_READER_FAILED: @@ -150,16 +150,16 @@ return ((char *)gettext("Failed to open parameter file")); case ERR_UPDATE_MAINCFG_FAILED: return ((char *)gettext("Failed to " - "update main configuration file")); + "update main configuration file")); case ERR_UPDATE_TARGCFG_FAILED: return ((char *)gettext("Failed to " - "update target configuration file")); + "update target configuration file")); case ERR_VALID_TARG_EXIST: return ((char *)gettext("Valid targets " - "exist under current base directory")); + "exist under current base directory")); case ERR_TARGCFG_MISSING_INAME: return ((char *)gettext("Missing " - "iscsi name in target configuration")); + "iscsi name in target configuration")); case ERR_NO_MATCH: return ((char *)gettext("No match")); case ERR_NO_MEM: @@ -193,6 +193,10 @@ return ((char *)gettext("No credentials available from door")); case ERR_NO_PERMISSION: return ((char *)gettext("Permission denied")); + case ERR_ISNS_ERROR: + return ((char *)gettext("ISNS error")); + case ERR_TPGT_NO_IPADDR: + return ((char *)gettext("TPGT has no ip-addr")); default: return ((char *)gettext("Internal error: unknown message")); }
--- a/usr/src/lib/libiscsitgt/common/iscsitgt_impl.h Tue May 29 17:10:21 2007 -0700 +++ b/usr/src/lib/libiscsitgt/common/iscsitgt_impl.h Tue May 29 17:13:54 2007 -0700 @@ -80,6 +80,7 @@ #define XML_ELEMENT_RAD_SERV "radius-server" #define XML_ELEMENT_RAD_SECRET "radius-secret" #define XML_ELEMENT_ISNS_ACCESS "isns-access" +#define XML_ELEMENT_ISNS_SERV "isns-server" #define XML_ELEMENT_FAST "fast-write-ack" #define XML_ELEMENT_NAME "name" #define XML_ELEMENT_ACL "acl"