1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29/* 30 | $Id: pdu.c,v 2.2 2006/12/01 09:11:56 danny Exp danny $ 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD: stable/11/sbin/iscontrol/pdu.c 330449 2018-03-05 07:26:05Z eadler $"); 35 36#include <sys/types.h> 37#include <sys/time.h> 38#include <sys/uio.h> 39#include <sys/ioctl.h> 40#include <unistd.h> 41#include <stdlib.h> 42#include <string.h> 43#include <errno.h> 44#include <stdio.h> 45#include <stdarg.h> 46#include <camlib.h> 47 48#include <dev/iscsi_initiator/iscsi.h> 49#include "iscontrol.h" 50 51static void pukeText(char *it, pdu_t *pp); 52 53int 54xmitpdu(isess_t *sess, pdu_t *pp) 55{ 56 if(ioctl(sess->fd, ISCSISEND, pp)) { 57 perror("xmitpdu"); 58 return -1; 59 } 60 if(vflag) 61 pukeText("I-", pp); 62 63 return 0; 64} 65 66int 67recvpdu(isess_t *sess, pdu_t *pp) 68{ 69 if(ioctl(sess->fd, ISCSIRECV, pp)) { 70 perror("recvpdu"); 71 return -1; 72 } 73 // XXX: return error if truncated via 74 // the FUDGE factor. 75 if(vflag) 76 pukeText("T-", pp); 77 78 return 0; 79} 80 81int 82sendPDU(isess_t *sess, pdu_t *pp, handler_t *hdlr) 83{ 84 if(xmitpdu(sess, pp)) 85 return 0; 86 if(hdlr) { 87 int res; 88 89 pp->ahs_size = 8 * 1024; 90 if((pp->ahs_addr = malloc(pp->ahs_size)) == NULL) { 91 fprintf(stderr, "out of mem!"); 92 return -1; 93 } 94 pp->ds_size = 0; 95 if((res = recvpdu(sess, pp)) != 0) { 96 fprintf(stderr, "recvpdu failed\n"); 97 return res; 98 } 99 res = hdlr(sess, pp); 100 freePDU(pp); 101 return res; 102 } 103 return 1; 104} 105 106 107#define FUDGE (512 * 8) 108/* 109 | We use the same memory for the response 110 | so make enough room ... 111 | XXX: must find a better way. 112 */ 113int 114addText(pdu_t *pp, char *fmt, ...) 115{ 116 u_int len; 117 char *str; 118 va_list ap; 119 120 va_start(ap, fmt); 121 len = vasprintf(&str, fmt, ap) + 1; 122 if((pp->ds_len + len) > 0xffffff) { 123 printf("ds overflow\n"); 124 free(str); 125 return 0; 126 } 127 128 if((pp->ds_len + len) > pp->ds_size) { 129 u_char *np; 130 131 np = realloc(pp->ds_addr, pp->ds_size + len + FUDGE); 132 if(np == NULL) { 133 free(str); 134 //XXX: out of memory! 135 return -1; 136 } 137 pp->ds_addr = np; 138 pp->ds_size += len + FUDGE; 139 } 140 memcpy(pp->ds_addr + pp->ds_len, str, len); 141 pp->ds_len += len; 142 free(str); 143 return len; 144} 145 146void 147freePDU(pdu_t *pp) 148{ 149 if(pp->ahs_size) 150 free(pp->ahs_addr); 151 if(pp->ds_size) 152 free(pp->ds_addr); 153 bzero(&pp->ipdu, sizeof(union ipdu_u)); 154 pp->ahs_addr = NULL; 155 pp->ds_addr = NULL; 156 pp->ahs_size = 0; 157 pp->ds_size = pp->ds_len = 0; 158} 159 160static void 161pukeText(char *it, pdu_t *pp) 162{ 163 char *ptr; 164 int cmd; 165 size_t len, n; 166 167 len = pp->ds_len; 168 ptr = (char *)pp->ds_addr; 169 cmd = pp->ipdu.bhs.opcode; 170 171 printf("%s: cmd=0x%x len=%d\n", it, cmd, (int)len); 172 while(len > 0) { 173 printf("\t%s\n", ptr); 174 n = strlen(ptr) + 1; 175 len -= n; 176 ptr += n; 177 } 178} 179