1171568Sscottl/*-
2234233Sjpaetzel * Copyright (c) 2005-2011 Daniel Braniss <danny@cs.huji.ac.il>
3171568Sscottl * All rights reserved.
4171568Sscottl *
5171568Sscottl * Redistribution and use in source and binary forms, with or without
6171568Sscottl * modification, are permitted provided that the following conditions
7171568Sscottl * are met:
8171568Sscottl * 1. Redistributions of source code must retain the above copyright
9171568Sscottl *    notice, this list of conditions and the following disclaimer.
10171568Sscottl * 2. Redistributions in binary form must reproduce the above copyright
11171568Sscottl *    notice, this list of conditions and the following disclaimer in the
12171568Sscottl *    documentation and/or other materials provided with the distribution.
13171568Sscottl *
14171568Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15171568Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16171568Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17171568Sscottl * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18171568Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19171568Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20171568Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21171568Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22171568Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23171568Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24171568Sscottl * SUCH DAMAGE.
25171568Sscottl *
26171568Sscottl */
27171568Sscottl/*
28171568Sscottl | iSCSI
29211095Sdes | $Id: isc_subr.c 560 2009-05-07 07:37:49Z danny $
30171568Sscottl */
31171568Sscottl
32171568Sscottl#include <sys/cdefs.h>
33171568Sscottl__FBSDID("$FreeBSD$");
34171568Sscottl
35171568Sscottl#include "opt_iscsi_initiator.h"
36171568Sscottl
37171568Sscottl#include <sys/param.h>
38171568Sscottl#include <sys/kernel.h>
39171568Sscottl#include <sys/conf.h>
40171568Sscottl#include <sys/systm.h>
41171568Sscottl#include <sys/malloc.h>
42171568Sscottl#include <sys/ctype.h>
43171568Sscottl#include <sys/errno.h>
44171568Sscottl#include <sys/sysctl.h>
45171568Sscottl#include <sys/file.h>
46171568Sscottl#include <sys/uio.h>
47171568Sscottl#include <sys/socketvar.h>
48171568Sscottl#include <sys/socket.h>
49171568Sscottl#include <sys/protosw.h>
50171568Sscottl#include <sys/proc.h>
51171568Sscottl#include <sys/ioccom.h>
52171568Sscottl#include <sys/queue.h>
53171568Sscottl#include <sys/kthread.h>
54171568Sscottl#include <sys/syslog.h>
55171568Sscottl#include <sys/mbuf.h>
56171568Sscottl#include <sys/libkern.h>
57171568Sscottl
58254657Strasz#include <dev/iscsi_initiator/iscsi.h>
59254657Strasz#include <dev/iscsi_initiator/iscsivar.h>
60171568Sscottl
61227293Sedstatic MALLOC_DEFINE(M_ISC, "iSC", "iSCSI driver options");
62211095Sdes
63171568Sscottlstatic char *
64171568Sscottli_strdupin(char *s, size_t maxlen)
65171568Sscottl{
66171568Sscottl     size_t	len;
67171568Sscottl     char	*p, *q;
68171568Sscottl
69211095Sdes     p = malloc(maxlen, M_ISC, M_WAITOK);
70171568Sscottl     if(copyinstr(s, p, maxlen, &len)) {
71211095Sdes	  free(p, M_ISC);
72171568Sscottl	  return NULL;
73171568Sscottl     }
74211095Sdes     q = malloc(len, M_ISC, M_WAITOK);
75171568Sscottl     bcopy(p, q, len);
76211095Sdes     free(p, M_ISC);
77171568Sscottl
78171568Sscottl     return q;
79171568Sscottl}
80234233Sjpaetzel#if __FreeBSD_version < 800000
81234233Sjpaetzel/*****************************************************************/
82234233Sjpaetzel/*                                                               */
83234233Sjpaetzel/* CRC LOOKUP TABLE                                              */
84234233Sjpaetzel/* ================                                              */
85234233Sjpaetzel/* The following CRC lookup table was generated automagically    */
86234233Sjpaetzel/* by the Rocksoft^tm Model CRC Algorithm Table Generation       */
87234233Sjpaetzel/* Program V1.0 using the following model parameters:            */
88234233Sjpaetzel/*                                                               */
89234233Sjpaetzel/*    Width   : 4 bytes.                                         */
90234233Sjpaetzel/*    Poly    : 0x1EDC6F41L                                      */
91234233Sjpaetzel/*    Reverse : TRUE.                                            */
92234233Sjpaetzel/*                                                               */
93234233Sjpaetzel/* For more information on the Rocksoft^tm Model CRC Algorithm,  */
94234233Sjpaetzel/* see the document titled "A Painless Guide to CRC Error        */
95234233Sjpaetzel/* Detection Algorithms" by Ross Williams                        */
96234233Sjpaetzel/* (ross@guest.adelaide.edu.au.). This document is likely to be  */
97234233Sjpaetzel/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft".        */
98234233Sjpaetzel/*                                                               */
99234233Sjpaetzel/*****************************************************************/
100171568Sscottl
101234233Sjpaetzelstatic uint32_t crc32Table[256] = {
102234233Sjpaetzel    0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
103234233Sjpaetzel    0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
104234233Sjpaetzel    0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
105234233Sjpaetzel    0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
106234233Sjpaetzel    0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
107234233Sjpaetzel    0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
108234233Sjpaetzel    0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
109234233Sjpaetzel    0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
110234233Sjpaetzel    0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
111234233Sjpaetzel    0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
112234233Sjpaetzel    0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
113234233Sjpaetzel    0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
114234233Sjpaetzel    0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
115234233Sjpaetzel    0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
116234233Sjpaetzel    0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
117234233Sjpaetzel    0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
118234233Sjpaetzel    0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
119234233Sjpaetzel    0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
120234233Sjpaetzel    0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
121234233Sjpaetzel    0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
122234233Sjpaetzel    0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
123234233Sjpaetzel    0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
124234233Sjpaetzel    0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
125234233Sjpaetzel    0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
126234233Sjpaetzel    0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
127234233Sjpaetzel    0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
128234233Sjpaetzel    0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
129234233Sjpaetzel    0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
130234233Sjpaetzel    0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
131234233Sjpaetzel    0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
132234233Sjpaetzel    0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
133234233Sjpaetzel    0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
134234233Sjpaetzel    0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
135234233Sjpaetzel    0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
136234233Sjpaetzel    0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
137234233Sjpaetzel    0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
138234233Sjpaetzel    0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
139234233Sjpaetzel    0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
140234233Sjpaetzel    0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
141234233Sjpaetzel    0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
142234233Sjpaetzel    0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
143234233Sjpaetzel    0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
144234233Sjpaetzel    0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
145234233Sjpaetzel    0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
146234233Sjpaetzel    0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
147234233Sjpaetzel    0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
148234233Sjpaetzel    0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
149234233Sjpaetzel    0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
150234233Sjpaetzel    0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
151234233Sjpaetzel    0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
152234233Sjpaetzel    0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
153234233Sjpaetzel    0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
154234233Sjpaetzel    0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
155234233Sjpaetzel    0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
156234233Sjpaetzel    0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
157234233Sjpaetzel    0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
158234233Sjpaetzel    0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
159234233Sjpaetzel    0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
160234233Sjpaetzel    0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
161234233Sjpaetzel    0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
162234233Sjpaetzel    0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
163234233Sjpaetzel    0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
164234233Sjpaetzel    0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
165234233Sjpaetzel    0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
166234233Sjpaetzel};
167234233Sjpaetzel
168234233Sjpaetzelstatic __inline int
169234233Sjpaetzelcalculate_crc32c(uint32_t crc, const void *buf, size_t size)
170234233Sjpaetzel{
171234233Sjpaetzel     const uint8_t *p = buf;
172234233Sjpaetzel
173234233Sjpaetzel     while (size--)
174234233Sjpaetzel	  crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
175234233Sjpaetzel     return crc;
176234233Sjpaetzel}
177234233Sjpaetzel#endif
178234233Sjpaetzel
179171568Sscottlstatic uint32_t
180171568Sscottli_crc32c(const void *buf, size_t size, uint32_t crc)
181171568Sscottl{
182171568Sscottl     crc = crc ^ 0xffffffff;
183188605Srrs     crc = calculate_crc32c(crc, buf, size);
184171568Sscottl     crc = crc ^ 0xffffffff;
185171568Sscottl     return crc;
186171568Sscottl}
187171568Sscottl
188171568Sscottl/*
189171568Sscottl | XXX: not finished coding
190171568Sscottl */
191171568Sscottlint
192171568Sscottli_setopt(isc_session_t *sp, isc_opt_t *opt)
193171568Sscottl{
194171568Sscottl     if(opt->maxRecvDataSegmentLength > 0) {
195171568Sscottl	  sp->opt.maxRecvDataSegmentLength = opt->maxRecvDataSegmentLength;
196171568Sscottl	  sdebug(2, "maxRecvDataSegmentLength=%d", sp->opt.maxRecvDataSegmentLength);
197171568Sscottl     }
198171568Sscottl     if(opt->maxXmitDataSegmentLength > 0) {
199171568Sscottl	  // danny's RFC
200171568Sscottl	  sp->opt.maxXmitDataSegmentLength = opt->maxXmitDataSegmentLength;
201211095Sdes	  sdebug(2, "opt.maXmitDataSegmentLength=%d", sp->opt.maxXmitDataSegmentLength);
202171568Sscottl     }
203171568Sscottl     if(opt->maxBurstLength != 0) {
204171568Sscottl	  sp->opt.maxBurstLength = opt->maxBurstLength;
205211095Sdes	  sdebug(2, "opt.maxBurstLength=%d", sp->opt.maxBurstLength);
206171568Sscottl     }
207171568Sscottl
208171568Sscottl     if(opt->targetAddress != NULL) {
209171568Sscottl	  if(sp->opt.targetAddress != NULL)
210211095Sdes	       free(sp->opt.targetAddress, M_ISC);
211171568Sscottl	  sp->opt.targetAddress = i_strdupin(opt->targetAddress, 128);
212211095Sdes	  sdebug(2, "opt.targetAddress='%s'", sp->opt.targetAddress);
213171568Sscottl     }
214171568Sscottl     if(opt->targetName != NULL) {
215171568Sscottl	  if(sp->opt.targetName != NULL)
216211095Sdes	       free(sp->opt.targetName, M_ISC);
217171568Sscottl	  sp->opt.targetName = i_strdupin(opt->targetName, 128);
218211095Sdes	  sdebug(2, "opt.targetName='%s'", sp->opt.targetName);
219171568Sscottl     }
220171568Sscottl     if(opt->initiatorName != NULL) {
221171568Sscottl	  if(sp->opt.initiatorName != NULL)
222211095Sdes	       free(sp->opt.initiatorName, M_ISC);
223171568Sscottl	  sp->opt.initiatorName = i_strdupin(opt->initiatorName, 128);
224211095Sdes	  sdebug(2, "opt.initiatorName='%s'", sp->opt.initiatorName);
225171568Sscottl     }
226171568Sscottl
227171568Sscottl     if(opt->maxluns > 0) {
228171568Sscottl	  if(opt->maxluns > ISCSI_MAX_LUNS)
229171568Sscottl	       sp->opt.maxluns = ISCSI_MAX_LUNS; // silently chop it down ...
230171568Sscottl	  sp->opt.maxluns = opt->maxluns;
231211095Sdes	  sdebug(2, "opt.maxluns=%d", sp->opt.maxluns);
232171568Sscottl     }
233171568Sscottl
234171568Sscottl     if(opt->headerDigest != NULL) {
235171568Sscottl	  sdebug(2, "opt.headerDigest='%s'", opt->headerDigest);
236171568Sscottl	  if(strcmp(opt->headerDigest, "CRC32C") == 0) {
237171568Sscottl	       sp->hdrDigest = (digest_t *)i_crc32c;
238211095Sdes	       sdebug(2, "opt.headerDigest set");
239171568Sscottl	  }
240171568Sscottl     }
241171568Sscottl     if(opt->dataDigest != NULL) {
242211095Sdes	  sdebug(2, "opt.dataDigest='%s'", opt->headerDigest);
243171568Sscottl	  if(strcmp(opt->dataDigest, "CRC32C") == 0) {
244171568Sscottl	       sp->dataDigest = (digest_t *)i_crc32c;
245211095Sdes	       sdebug(2, "opt.dataDigest set");
246171568Sscottl	  }
247171568Sscottl     }
248171568Sscottl
249171568Sscottl     return 0;
250171568Sscottl}
251171568Sscottl
252171568Sscottlvoid
253171568Sscottli_freeopt(isc_opt_t *opt)
254171568Sscottl{
255211095Sdes     debug_called(8);
256211095Sdes
257171568Sscottl     if(opt->targetAddress != NULL) {
258211095Sdes	  free(opt->targetAddress, M_ISC);
259171568Sscottl	  opt->targetAddress = NULL;
260171568Sscottl     }
261171568Sscottl     if(opt->targetName != NULL) {
262211095Sdes	  free(opt->targetName, M_ISC);
263171568Sscottl	  opt->targetName = NULL;
264171568Sscottl     }
265171568Sscottl     if(opt->initiatorName != NULL) {
266211095Sdes	  free(opt->initiatorName, M_ISC);
267171568Sscottl	  opt->initiatorName = NULL;
268171568Sscottl     }
269171568Sscottl}
270