fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or http://www.opensolaris.org/os/licensing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iSCSI Software Initiator
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/socket.h> /* networking stuff */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/strsubr.h> /* networking stuff */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <netinet/tcp.h> /* TCP_NODELAY */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/socketvar.h> /* _ALLOC_SLEEP */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/pathname.h> /* declares: lookupname */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/fs/snode.h> /* defines: VTOS */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/fs/dv_node.h> /* declares: devfs_lookupname */
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng#include <sys/bootconf.h>
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng#include <sys/bootprops.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <netinet/in.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "iscsi.h"
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/ksocket.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This is a high level description of the default
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net transport interfaces. These are used
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to create, send, recv, and close standard TCP/IP
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * messages. In addition there are extensions to send
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and recv iSCSI PDU data.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * NOTE: It would be very easy for an iSCSI HBA vendor
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to register their own functions over the top of
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the default interfaces. This would allow an iSCSI
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * HBA to use the same iscsiadm management interfaces
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and the Solaris iSCSI session / connection management.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The current problem with this approach is we only
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * allow one one registered transport table. This
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * would be pretty easy to correct although will require
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * additional CLI changes to manage multiple interfaces.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If a vendor can present compelling performance data,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * then Sun will be willing to enhance this support for
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * multiple interface tables and better CLI management.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The following listing describes the iscsi_net
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * entry points:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * socket - Creates TCP/IP socket connection. In the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * default implementation creates a sonode
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * via the sockfs kernel layer.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * bind - Performs standard TCP/IP BSD operation. In
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * the default implementation this only act
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * as a soft binding based on the IP and routing
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * tables. It would be preferred if this was
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * a hard binding but that is currently not
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * possible with Solaris's networking stack.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * connect - Performs standard TCP/IP BSD operation. This
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * establishes the TCP SYN to the peer IP address.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * listen - Performs standard TCP/IP BSD operation. This
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * listens for incoming peer connections.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * accept - Performs standard TCP/IP BSD operation. This
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * accepts incoming peer connections.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * shutdown - This disconnects the TCP/IP connection while
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * maintaining the resources.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * close - This disconnects the TCP/IP connection and
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * releases the resources.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * getsockopt - Gets socket option for specified socket.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * setsockopt - Sets socket option for specified socket.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The current socket options that are used by the initiator
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * are listed below.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * TCP_CONN_NOTIFY_THRESHOLD
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * TCP_CONN_ABORT_THRESHOLD
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * TCP_ABORT_THRESHOLD
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * TCP_NODELAY
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * SO_RCVBUF
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * SO_SNDBUF
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_poll - Poll socket interface for a specified amount
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * of data. If data not received in timeout
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * period fail request.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_sendmsg - Send message on socket connection
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_recvmsg - Receive message on socket connection
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_sendpdu - Send iSCSI PDU on socket connection
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_recvhdr - Receive iSCSI header on socket connection
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_recvdata - Receive iSCSI data on socket connection
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The iSCSI interfaces have the below optional flags.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ISCSI_NET_HEADER_DIGEST - The interface should either
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * generate or validate the iSCSI
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * header digest CRC.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ISCSI_NET_DATA_DIGESt - The interface should either
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * generate or validate the iSCSI
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * data digest CRC.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* global */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_network_t *iscsi_net;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* consts */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This table is used for quick validation of incoming
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iSCSI PDU opcodes. A value of '0' in the table below
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * indicated that the opcode is invalid for an iSCSI
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * initiator to receive.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteconst int is_incoming_opcode_invalid[256] = {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x0X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x1X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x2X */ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x3X */ 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x4X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x5X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x6X */ 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x7X */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x8X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0x9X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0xAX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0xBX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0xCX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0xDX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0xEX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* 0xFX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte};
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng#define IP_4_BITS 32
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng#define IP_6_BITS 128
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Mengextern int modrootloaded;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningextern ib_boot_prop_t *iscsiboot_prop;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* prototypes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void * iscsi_net_socket(int domain, int type, int protocol);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int iscsi_net_bind(void *socket, struct sockaddr *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte name, int name_len, int backlog, int flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int iscsi_net_connect(void *socket, struct sockaddr *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte name, int name_len, int fflag, int flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int iscsi_net_listen(void *socket, int backlog);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void * iscsi_net_accept(void *socket, struct sockaddr *addr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int *addr_len);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningstatic int iscsi_net_getsockname(void *socket, struct sockaddr *, socklen_t *);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int iscsi_net_getsockopt(void *socket, int level,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int option_name, void *option_val, int *option_len, int flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int iscsi_net_setsockopt(void *socket, int level,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int option_name, void *option_val, int option_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int iscsi_net_shutdown(void *socket, int how);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void iscsi_net_close(void *socket);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic size_t iscsi_net_poll(void *socket, clock_t timeout);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic size_t iscsi_net_sendmsg(void *socket, struct msghdr *msg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic size_t iscsi_net_recvmsg(void *socket,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct msghdr *msg, int timeout);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t iscsi_net_sendpdu(void *socket, iscsi_hdr_t *ihp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char *data, int flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t iscsi_net_recvdata(void *socket, iscsi_hdr_t *ihp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char *data, int max_data_length, int timeout, int flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t iscsi_net_recvhdr(void *socket, iscsi_hdr_t *ihp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int header_length, int timeout, int flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
9ad4dd06b7412662d855e0be267b66193dfe7277Sheng-Liang Eric Zhangstatic void iscsi_net_set_connect_options(void *socket);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * | network interface registration functions |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_init - initialize network interface
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_init()
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net = kmem_zalloc(sizeof (*iscsi_net), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->socket = iscsi_net_socket;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->bind = iscsi_net_bind;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->connect = iscsi_net_connect;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->listen = iscsi_net_listen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->accept = iscsi_net_accept;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->shutdown = iscsi_net_shutdown;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->close = iscsi_net_close;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->getsockname = iscsi_net_getsockname;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->getsockopt = iscsi_net_getsockopt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->setsockopt = iscsi_net_setsockopt;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->poll = iscsi_net_poll;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->sendmsg = iscsi_net_sendmsg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->recvmsg = iscsi_net_recvmsg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->sendpdu = iscsi_net_sendpdu;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->recvhdr = iscsi_net_recvhdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net->recvdata = iscsi_net_recvdata;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_fini - release network interface
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_fini()
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(iscsi_net, sizeof (*iscsi_net));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iscsi_net = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
9ad4dd06b7412662d855e0be267b66193dfe7277Sheng-Liang Eric Zhang * iscsi_net_set_connect_options -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
9ad4dd06b7412662d855e0be267b66193dfe7277Sheng-Liang Eric Zhangiscsi_net_set_connect_options(void *socket)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int ret = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret += iscsi_net->setsockopt(socket, IPPROTO_TCP,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte TCP_CONN_NOTIFY_THRESHOLD, (char *)&iscsi_net->tweaks.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte conn_notify_threshold, sizeof (int));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret += iscsi_net->setsockopt(socket, IPPROTO_TCP,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte TCP_CONN_ABORT_THRESHOLD, (char *)&iscsi_net->tweaks.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte conn_abort_threshold, sizeof (int));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret += iscsi_net->setsockopt(socket, IPPROTO_TCP, TCP_ABORT_THRESHOLD,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (char *)&iscsi_net->tweaks.abort_threshold, sizeof (int));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret += iscsi_net->setsockopt(socket, IPPROTO_TCP, TCP_NODELAY,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (char *)&iscsi_net->tweaks.nodelay, sizeof (int));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret += iscsi_net->setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (char *)&iscsi_net->tweaks.rcvbuf, sizeof (int));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret += iscsi_net->setsockopt(socket, SOL_SOCKET, SO_SNDBUF,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (char *)&iscsi_net->tweaks.sndbuf, sizeof (int));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ret != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_NOTE, "iscsi connection failed to set socket option"
9ad4dd06b7412662d855e0be267b66193dfe7277Sheng-Liang Eric Zhang "TCP_CONN_NOTIFY_THRESHOLD, TCP_CONN_ABORT_THRESHOLD,"
9ad4dd06b7412662d855e0be267b66193dfe7277Sheng-Liang Eric Zhang "TCP_ABORT_THRESHOLD, TCP_NODELAY, SO_RCVBUF or SO_SNDBUF");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * | register network interfaces |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +--------------------------------------------------------------------+
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_socket - create socket
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_socket(int domain, int type, int protocol)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int err = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning err = ksocket_socket(&socket, domain, type, protocol, KSOCKET_SLEEP,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning CRED());
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!err)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return ((void *)socket);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_bind - bind socket to a specific sockaddr
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_bind(void *socket, struct sockaddr *name, int name_len,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int backlog, int flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = ksocket_bind(ks, name, name_len, CRED());
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error == 0 && backlog != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = ksocket_listen(ks, backlog, CRED());
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_connect - connect socket to peer sockaddr
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_connect(void *socket, struct sockaddr *name, int name_len,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int fflag, int flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int rval;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
9ad4dd06b7412662d855e0be267b66193dfe7277Sheng-Liang Eric Zhang iscsi_net_set_connect_options(socket);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning rval = ksocket_connect(ks, name, name_len, CRED());
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (rval);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_listen - listen to socket for peer connections
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_listen(void *socket, int backlog)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (ksocket_listen(ks, backlog, CRED()));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_accept - accept peer socket connections
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_accept(void *socket, struct sockaddr *addr, int *addr_len)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t listen_ks;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
c1374a13e412c4ec42cba867e57347a0e049a822Surya Prakki (void) ksocket_accept(ks, addr, (socklen_t *)addr_len, &listen_ks,
c1374a13e412c4ec42cba867e57347a0e049a822Surya Prakki CRED());
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return ((void *)listen_ks);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_getsockname -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningiscsi_net_getsockname(void *socket, struct sockaddr *addr, socklen_t *addrlen)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (ksocket_getsockname(ks, addr, addrlen, CRED()));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_getsockopt - get value of option on socket
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_getsockopt(void *socket, int level, int option_name,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte void *option_val, int *option_len, int flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (ksocket_getsockopt(ks, level, option_name, option_val,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning option_len, CRED()));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_setsockopt - set value for option on socket
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_setsockopt(void *socket, int level, int option_name,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte void *option_val, int option_len)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (ksocket_setsockopt(ks, level, option_name, option_val,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning option_len, CRED()));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_shutdown - shutdown socket connection
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_shutdown(void *socket, int how)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (ksocket_shutdown(ks, how, CRED()));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_close - shutdown socket connection and release resources
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_close(void *socket)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_close(ks, CRED());
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_poll - poll socket for data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic size_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_poll(void *socket, clock_t timeout)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int pflag;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning char msg[64];
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size_t recv = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian if (get_udatamodel() == DATAMODEL_NONE ||
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian get_udatamodel() == DATAMODEL_NATIVE) {
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian struct timeval tl;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian /* timeout is millisecond */
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian tl.tv_sec = timeout / 1000;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian tl.tv_usec = (timeout % 1000) * 1000;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian if (ksocket_setsockopt(ks, SOL_SOCKET, SO_RCVTIMEO, &tl,
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian sizeof (struct timeval), CRED()))
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian return (0);
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian } else {
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian struct timeval32 tl;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian /* timeout is millisecond */
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian tl.tv_sec = timeout / 1000;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian tl.tv_usec = (timeout % 1000) * 1000;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian if (ksocket_setsockopt(ks, SOL_SOCKET, SO_RCVTIMEO, &tl,
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian sizeof (struct timeval32), CRED()))
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian return (0);
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pflag = MSG_ANY;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning bzero(msg, sizeof (msg));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (ksocket_recv(ks, msg, sizeof (msg), pflag, &recv, CRED()));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_sendmsg - send message on socket
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic size_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_sendmsg(void *socket, struct msghdr *msg)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size_t sent = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int flag = msg->msg_flags;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_sendmsg(ks, msg, flag, &sent, CRED());
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning DTRACE_PROBE1(ksocket_sendmsg, size_t, sent);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (sent);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_recvmsg - receive message on socket
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic size_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_recvmsg(void *socket, struct msghdr *msg, int timeout)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int prflag = msg->msg_flags;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks = (ksocket_t)socket;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size_t recv = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Set recv timeout */
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian if (get_udatamodel() == DATAMODEL_NONE ||
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian get_udatamodel() == DATAMODEL_NATIVE) {
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian struct timeval tl;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian tl.tv_sec = timeout;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian tl.tv_usec = 0;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian if (ksocket_setsockopt(ks, SOL_SOCKET, SO_RCVTIMEO, &tl,
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian sizeof (struct timeval), CRED()))
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian return (0);
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian } else {
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian struct timeval32 tl;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian tl.tv_sec = timeout;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian tl.tv_usec = 0;
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian if (ksocket_setsockopt(ks, SOL_SOCKET, SO_RCVTIMEO, &tl,
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian sizeof (struct timeval32), CRED()))
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian return (0);
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Receive the requested data. Block until all
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * data is received or timeout.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
912e288b51cca49c24bd9f8b0a5ba07e7210204aJack Meng ksocket_hold(ks);
c1374a13e412c4ec42cba867e57347a0e049a822Surya Prakki (void) ksocket_recvmsg(ks, msg, prflag, &recv, CRED());
912e288b51cca49c24bd9f8b0a5ba07e7210204aJack Meng ksocket_rele(ks);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning DTRACE_PROBE1(ksocket_recvmsg, size_t, recv);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (recv);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_sendpdu - send iscsi pdu on socket
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_sendpdu(void *socket, iscsi_hdr_t *ihp, char *data, int flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t pad;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t crc_hdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t crc_data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t pad_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t data_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec_t iovec[ISCSI_MAX_IOVEC];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int iovlen = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size_t total_len = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size_t send_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct msghdr msg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(socket != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(ihp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Let's send the header first. 'hlength' is in 32-bit
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * quantities, so we need to multiply by four to get bytes
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(iovlen < ISCSI_MAX_IOVEC);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec[iovlen].iov_base = (void *)ihp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec[iovlen].iov_len = sizeof (*ihp) + ihp->hlength * 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_len += sizeof (*ihp) + ihp->hlength * 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovlen++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Let's transmit the header digest if we have to. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((flags & ISCSI_NET_HEADER_DIGEST) != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(iovlen < ISCSI_MAX_IOVEC);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Converting the calculated CRC via htonl is not
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * necessary because iscsi_crc32c calculates
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the value as it expects to be written
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte crc_hdr = iscsi_crc32c((char *)ihp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sizeof (iscsi_hdr_t) + ihp->hlength * 4);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec[iovlen].iov_base = (void *)&crc_hdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec[iovlen].iov_len = sizeof (crc_hdr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_len += sizeof (crc_hdr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovlen++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Let's transmit the data if any. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte data_len = ntoh24(ihp->dlength);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (data_len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(iovlen < ISCSI_MAX_IOVEC);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec[iovlen].iov_base = (void *)data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec[iovlen].iov_len = data_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_len += data_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovlen++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pad_len = ((ISCSI_PAD_WORD_LEN -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (data_len & (ISCSI_PAD_WORD_LEN - 1))) &
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ISCSI_PAD_WORD_LEN - 1));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Let's transmit the data pad if any. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pad_len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(iovlen < ISCSI_MAX_IOVEC);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pad = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec[iovlen].iov_base = (void *)&pad;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec[iovlen].iov_len = pad_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_len += pad_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovlen++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Let's transmit the data digest if we have to. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((flags & ISCSI_NET_DATA_DIGEST) != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(iovlen < ISCSI_MAX_IOVEC);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Converting the calculated CRC via htonl is not
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * necessary because iscsi_crc32c calculates the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * value as it expects to be written
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte crc_data = iscsi_crc32c(data, data_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte crc_data = iscsi_crc32c_continued(
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (char *)&pad, pad_len, crc_data);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec[iovlen].iov_base = (void *)&crc_data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec[iovlen].iov_len = sizeof (crc_data);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_len += sizeof (crc_data);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovlen++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DTRACE_PROBE4(tx, void *, socket, iovec_t *, &iovec[0],
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int, iovlen, int, total_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Initialization of the message header. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(&msg, sizeof (msg));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iov = &iovec[0];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_flags = MSG_WAITALL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iovlen = iovlen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning send_len = iscsi_net->sendmsg(socket, &msg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DTRACE_PROBE2(sendmsg, size_t, total_len, size_t, send_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (total_len != send_len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_TCP_TX_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_recvhdr - receive iscsi hdr on socket
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_recvhdr(void *socket, iscsi_hdr_t *ihp, int header_length,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int timeout, int flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec_t iov[ISCSI_MAX_IOVEC];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int iovlen = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int total_len = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t crc_actual = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t crc_calculated = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char *adhdr = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int adhdr_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct msghdr msg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size_t recv_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(socket != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(ihp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (header_length < sizeof (iscsi_hdr_t)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(FALSE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Receive primary header
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[0].iov_base = (char *)ihp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[0].iov_len = sizeof (iscsi_hdr_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(&msg, sizeof (msg));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iov = iov;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_flags = MSG_WAITALL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iovlen = iovlen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte recv_len = iscsi_net->recvmsg(socket, &msg, timeout);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (recv_len != sizeof (iscsi_hdr_t)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_TCP_RX_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DTRACE_PROBE2(rx_hdr, void *, socket, iovec_t *iop, &iov[0]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* verify incoming opcode is a valid operation */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (is_incoming_opcode_invalid[ihp->opcode]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi connection(%p) protocol error - "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "received an unsupported opcode:0x%02x",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte socket, ihp->opcode);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Setup receipt of additional header
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ihp->hlength > 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte adhdr = ((char *)ihp) + sizeof (iscsi_hdr_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte adhdr_length = header_length - sizeof (iscsi_hdr_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* make sure enough space is available for adhdr */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ihp->hlength > adhdr_length) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(FALSE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(iovlen < ISCSI_MAX_IOVEC);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[iovlen].iov_base = adhdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[iovlen].iov_len = adhdr_length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_len += adhdr_length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovlen++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Setup receipt of header digest if enabled and connection
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is in full feature mode.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((flags & ISCSI_NET_HEADER_DIGEST) != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(iovlen < ISCSI_MAX_IOVEC);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[iovlen].iov_base = (char *)&crc_actual;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[iovlen].iov_len = sizeof (uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_len += sizeof (uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovlen++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read additional header and/or header digest if pieces
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * are available
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iovlen > 1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(&msg, sizeof (msg));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iov = iov;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_flags = MSG_WAITALL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iovlen = iovlen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte recv_len = iscsi_net->recvmsg(socket, &msg, timeout);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (recv_len != total_len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_TCP_RX_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DTRACE_PROBE4(rx_adhdr_digest, void *, socket,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovec_t *iop, &iov[0], int, iovlen, int, total_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Verify header digest if enabled and connection
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is in full feature mode
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((flags & ISCSI_NET_HEADER_DIGEST) != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte crc_calculated = iscsi_crc32c((uchar_t *)ihp,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sizeof (iscsi_hdr_t) + ihp->hlength * 4);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Converting actual CRC read via ntohl is not
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * necessary because iscsi_crc32c calculates the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * value as it expect to be read
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (crc_calculated != crc_actual) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Invalid Header Digest */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi connection(%p) "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "protocol error - encountered a header "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "digest error expected:0x%08x "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "received:0x%08x", socket,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte crc_calculated, crc_actual);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_HEADER_DIGEST_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * iscsi_net_recvdata - receive iscsi data payload from socket
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic iscsi_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteiscsi_net_recvdata(void *socket, iscsi_hdr_t *ihp, char *data,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int max_data_length, int timeout, int flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct iovec iov[3];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int iovlen = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int total_len = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int dlength = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int pad_len = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t pad[ISCSI_PAD_WORD_LEN];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t crc_calculated = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t crc_actual = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct msghdr msg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size_t recv_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(socket != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(ihp != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(data != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* short hand dlength */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dlength = ntoh24(ihp->dlength);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* verify dlength is valid */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dlength > max_data_length) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi connection(%p) protocol error - "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "invalid data lengths itt:0x%x received:0x%x "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "max expected:0x%x", socket, ihp->itt,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dlength, max_data_length);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_PROTOCOL_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dlength) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* calculate pad */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pad_len = ((ISCSI_PAD_WORD_LEN -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (dlength & (ISCSI_PAD_WORD_LEN - 1))) &
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ISCSI_PAD_WORD_LEN - 1));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* setup data iovec */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[0].iov_base = (char *)data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[0].iov_len = dlength;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_len = dlength;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* if pad setup pad iovec */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pad_len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[iovlen].iov_base = (char *)&pad;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[iovlen].iov_len = pad_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_len += pad_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovlen++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* setup data digest */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((flags & ISCSI_NET_DATA_DIGEST) != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[iovlen].iov_base = (char *)&crc_actual;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[iovlen].iov_len = sizeof (crc_actual);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_len += sizeof (crc_actual);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iovlen++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(&msg, sizeof (msg));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iov = iov;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_flags = MSG_WAITALL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iovlen = iovlen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte recv_len = iscsi_net->recvmsg(socket, &msg, timeout);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (recv_len != total_len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_TCP_RX_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DTRACE_PROBE4(rx_data, void *, socket, iovec_t *iop,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &iov[0], int, iovlen, int, total_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* verify data digest is present */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((flags & ISCSI_NET_DATA_DIGEST) != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte crc_calculated = iscsi_crc32c(data, dlength);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte crc_calculated = iscsi_crc32c_continued(
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (char *)&pad, pad_len, crc_calculated);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Converting actual CRC read via ntohl is not
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * necessary because iscsi_crc32c calculates the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * value as it expects to be read
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (crc_calculated != crc_actual) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "iscsi connection(%p) "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "protocol error - encountered a data "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "digest error itt:0x%x expected:0x%08x "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "received:0x%08x", socket,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ihp->itt, crc_calculated, crc_actual);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_DATA_DIGEST_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (ISCSI_STATUS_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng/*
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng * Convert a prefix length to a mask.
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng */
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Mengstatic iscsi_status_t
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Mengiscsi_prefixlentomask(int prefixlen, int maxlen, uchar_t *mask)
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng{
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng if (prefixlen < 0 || prefixlen > maxlen || mask == NULL) {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng return (ISCSI_STATUS_INTERNAL_ERROR);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng }
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng while (prefixlen > 0) {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng if (prefixlen >= 8) {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng *mask = 0xff;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng mask++;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng prefixlen = prefixlen - 8;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng continue;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng }
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng *mask = *mask | (1 << (8 - prefixlen));
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng prefixlen--;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng }
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng return (ISCSI_STATUS_SUCCESS);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng}
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapiscsi_status_t
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Mengiscsi_net_interface(boolean_t reset)
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng{
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng struct in_addr braddr;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng struct in_addr subnet;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng struct in_addr myaddr;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng struct in_addr defgateway;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng struct in6_addr myaddr6;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng struct in6_addr subnet6;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng uchar_t mask_prefix = 0;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng int mask_bits = 1;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng TIUSER *tiptr;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng TIUSER *tiptr6;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng char ifname[16] = {0};
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng iscsi_status_t status;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng struct knetconfig dl_udp_netconf = {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng NC_TPI_CLTS,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng NC_INET,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng NC_UDP,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng 0, };
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng struct knetconfig dl_udp6_netconf = {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng NC_TPI_CLTS,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng NC_INET6,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng NC_UDP,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng 0, };
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng (void) strlcpy(ifname, rootfs.bo_ifname, sizeof (ifname));
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng if (iscsiboot_prop->boot_nic.sin_family == AF_INET) {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng /*
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng * Assumes only one linkage array element.
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng */
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng dl_udp_netconf.knc_rdev =
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng makedevice(clone_major, ddi_name_to_major("udp"));
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng myaddr.s_addr =
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng iscsiboot_prop->boot_nic.nic_ip_u.u_in4.s_addr;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng mask_prefix = iscsiboot_prop->boot_nic.sub_mask_prefix;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng (void) memset(&subnet.s_addr, 0, sizeof (subnet));
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng status = iscsi_prefixlentomask(mask_prefix, IP_4_BITS,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng (uchar_t *)&subnet.s_addr);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng if (status != ISCSI_STATUS_SUCCESS) {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng return (status);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng }
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng mask_bits = mask_bits << (IP_4_BITS - mask_prefix);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng mask_bits = mask_bits - 1;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng /*
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng * Set the last mask bits of the ip address with 1, then
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng * we can get the broadcast address.
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng */
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng braddr.s_addr = myaddr.s_addr | mask_bits;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng defgateway.s_addr =
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng iscsiboot_prop->boot_nic.nic_gw_u.u_in4.s_addr;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng /* initialize interface */
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng if (t_kopen((file_t *)NULL, dl_udp_netconf.knc_rdev,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng FREAD|FWRITE, &tiptr, CRED()) == 0) {
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng int ret = 0;
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng if (reset == B_TRUE) {
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng ret = kdlifconfig(tiptr, AF_INET, &myaddr,
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng &subnet, NULL, NULL, ifname);
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng } else if (defgateway.s_addr == 0) {
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng /* No default gate way specified */
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng ret = kdlifconfig(tiptr, AF_INET, &myaddr,
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng &subnet, &braddr, NULL, ifname);
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng } else {
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng ret = kdlifconfig(tiptr, AF_INET, &myaddr,
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng &subnet, &braddr, &defgateway, ifname);
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng }
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng if (ret != 0) {
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng (void) t_kclose(tiptr, 0);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng cmn_err(CE_WARN, "Failed to configure"
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng " iSCSI boot nic");
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng return (ISCSI_STATUS_INTERNAL_ERROR);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng }
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng (void) t_kclose(tiptr, 0);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng } else {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng cmn_err(CE_WARN, "Failed to configure"
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng " iSCSI boot nic");
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng return (ISCSI_STATUS_INTERNAL_ERROR);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng }
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng return (ISCSI_STATUS_SUCCESS);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng } else {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng dl_udp6_netconf.knc_rdev =
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng makedevice(clone_major, ddi_name_to_major("udp6"));
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng bcopy(&iscsiboot_prop->boot_nic.nic_ip_u.u_in6.s6_addr,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng &myaddr6.s6_addr, 16);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng (void) memset(&subnet6, 0, sizeof (subnet6));
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng mask_prefix = iscsiboot_prop->boot_nic.sub_mask_prefix;
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng status = iscsi_prefixlentomask(mask_prefix, IP_6_BITS,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng (uchar_t *)&subnet6.s6_addr);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng if (status != ISCSI_STATUS_SUCCESS) {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng return (status);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng }
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng if (t_kopen((file_t *)NULL, dl_udp6_netconf.knc_rdev,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng FREAD|FWRITE, &tiptr6, CRED()) == 0) {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng if (kdlifconfig(tiptr6, AF_INET6, &myaddr6,
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng &subnet6, NULL, NULL, ifname)) {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng cmn_err(CE_WARN, "Failed to configure"
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng " iSCSI boot nic");
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng (void) t_kclose(tiptr6, 0);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng return (ISCSI_STATUS_INTERNAL_ERROR);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng }
bbe725837bc5e084e6762c7984672bc05d76baf1Jack Meng (void) t_kclose(tiptr6, 0);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng } else {
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng cmn_err(CE_WARN, "Failed to configure"
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng " iSCSI boot nic");
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng return (ISCSI_STATUS_INTERNAL_ERROR);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng }
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng return (ISCSI_STATUS_SUCCESS);
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng }
6cefaae1e90a413ba01560575bb3998e1a3df40eJack Meng}