diff options
Diffstat (limited to 'usr/src/cmd/iscsi/iscsitgtd/isns.c')
-rw-r--r-- | usr/src/cmd/iscsi/iscsitgtd/isns.c | 702 |
1 files changed, 0 insertions, 702 deletions
diff --git a/usr/src/cmd/iscsi/iscsitgtd/isns.c b/usr/src/cmd/iscsi/iscsitgtd/isns.c deleted file mode 100644 index c5548f4ac1..0000000000 --- a/usr/src/cmd/iscsi/iscsitgtd/isns.c +++ /dev/null @@ -1,702 +0,0 @@ -/* - * 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 2008 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 <fcntl.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; - - (void) pthread_mutex_lock(&xid_lock); - tmp = xid++; - (void) 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)); - (void) 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; - (void) 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; - fd_set rfdset; - fd_set wfdset; - fd_set errfdset; - struct timeval timeout; - Boolean_t shouldsockblock = False; - int socket_ready = 0; - timeout.tv_sec = 5; /* 5 Secs Timeout */ - timeout.tv_usec = 0; /* 0 uSecs Timeout */ - - if (server == NULL) { - syslog(LOG_ERR, "ISNS server ID required"); - return (-1); - } - - bzero(&hints, sizeof (struct addrinfo)); - hints.ai_family = AF_UNSPEC; - if ((ret = getaddrinfo(server, NULL, NULL, &ai)) != 0) { - syslog(LOG_ALERT, "getaddrinfo failed on server %s: %s", server, - gai_strerror(ret)); - return (-1); - } - - aip = ai; - do { - so = socket(aip->ai_family, SOCK_STREAM, 0); - if (so != -1) { - - /* set it to non blocking so connect wont hang */ - if (setsocknonblocking(so) == -1) { - (void) close(so); - continue; - } - - 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: - syslog(LOG_ALERT, "Bad protocol"); - (void) close(so); - continue; - } - - ret = connect(so, sa, sa_len); - if (ret == 0) { - /* - * connection succeeded with out - * blocking - */ - shouldsockblock = True; - } - - if (ret < 0) { - if (errno == EINPROGRESS) { - FD_ZERO(&rfdset); - FD_ZERO(&wfdset); - FD_ZERO(&errfdset); - FD_SET(so, &rfdset); - FD_SET(so, &wfdset); - FD_SET(so, &errfdset); - socket_ready = - select(so + 1, &rfdset, &wfdset, - &errfdset, &timeout); - if (socket_ready < 0) { - syslog(LOG_ALERT, - "failed to connect with" - " isns, err=%d", errno); - (void) close(so); - } else if (socket_ready == 0) { - syslog(LOG_ALERT, - "time out failed" - " to connect with isns"); - (void) close(so); - } else { /* Socket is ready */ - /* - * Check if socket is ready - */ - if (is_socket_ready(so, - &rfdset, &wfdset, - &errfdset) == True) - shouldsockblock = True; - else - (void) close(so); - } - } else { - syslog(LOG_WARNING, - "Connect failed no progress"); - (void) close(so); - } - } - - if (shouldsockblock == True) { - if (-1 == setsockblocking(so)) { - (void) close(so); - shouldsockblock = False; - } else { - freeaddrinfo(ai); - return (so); - } - } - - } - } while ((aip = aip->ai_next) != NULL); - - if (ai != NULL) - freeaddrinfo(ai); - return (-1); -} - -/* - * According to: - * UNIX Network Programming Volume 1, Third Edition: - * The Sockets Networking APIBOOK: - * - * When the connection completes successfully, the descriptor becomes - * writable (p. 531 of TCPv2). - * When the connection establishment encounters an error, the descriptor - * becomes both readable and writable (p. 530 of TCPv2). - */ -Boolean_t -is_socket_ready(int so, fd_set *rfdset, fd_set *wfdset, - fd_set *errfdset) -{ - if ((FD_ISSET(so, wfdset) && - FD_ISSET(so, rfdset)) || - FD_ISSET(so, errfdset)) { - return (False); - } else { - return (True); - } -} - -int -setsocknonblocking(int so) -{ - int flags; - /* set it to non blocking */ - if (-1 == (flags = fcntl(so, F_GETFL, 0))) { - syslog(LOG_WARNING, - "Failed to get socket flags. Blocking.."); - return (-1); - } - - if (fcntl(so, F_SETFL, flags | O_NONBLOCK) == -1) { - syslog(LOG_WARNING, - "Failed to set socket in non blocking mode"); - return (-1); - } - return (0); -} - -int -setsockblocking(int so) -{ - int flags; - /* set it to non blocking */ - if (-1 == (flags = fcntl(so, F_GETFL, 0))) { - syslog(LOG_WARNING, " Failed to get flags on socket.."); - return (-1); - } - - flags &= ~O_NONBLOCK; - if (fcntl(so, F_SETFL, flags) == -1) { - syslog(LOG_WARNING, " failed to set socket to blocking"); - return (-1); - } - return (0); -} - - -void -isns_close(int so) -{ - if (so) { - (void) 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); -} |