kernel.c revision 279880
1152851Sariff/*- 2152851Sariff * Copyright (c) 2003, 2004 Silicon Graphics International Corp. 3152851Sariff * Copyright (c) 1997-2007 Kenneth D. Merry 4152851Sariff * Copyright (c) 2012 The FreeBSD Foundation 5152851Sariff * All rights reserved. 6152851Sariff * 7152851Sariff * Portions of this software were developed by Edward Tomasz Napierala 8152851Sariff * under sponsorship from the FreeBSD Foundation. 9152851Sariff * 10152851Sariff * Redistribution and use in source and binary forms, with or without 11152851Sariff * modification, are permitted provided that the following conditions 12152851Sariff * are met: 13152851Sariff * 1. Redistributions of source code must retain the above copyright 14152851Sariff * notice, this list of conditions, and the following disclaimer, 15152851Sariff * without modification. 16152851Sariff * 2. Redistributions in binary form must reproduce at minimum a disclaimer 17152851Sariff * substantially similar to the "NO WARRANTY" disclaimer below 18152851Sariff * ("Disclaimer") and any redistribution must be conditioned upon 19152851Sariff * including a substantially similar Disclaimer requirement for further 20152851Sariff * binary redistribution. 21152851Sariff * 22152851Sariff * NO WARRANTY 23152851Sariff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24152851Sariff * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25152851Sariff * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 26152851Sariff * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27152851Sariff * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28152851Sariff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29152851Sariff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30152851Sariff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31152851Sariff * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 32152851Sariff * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33155800Sariff * POSSIBILITY OF SUCH DAMAGES. 34152851Sariff * 35152851Sariff */ 36152851Sariff 37152851Sariff#include <sys/cdefs.h> 38152851Sariff__FBSDID("$FreeBSD: stable/10/usr.sbin/ctld/kernel.c 279880 2015-03-11 09:52:54Z mav $"); 39155800Sariff 40155800Sariff#include <sys/ioctl.h> 41152851Sariff#include <sys/types.h> 42152851Sariff#include <sys/stat.h> 43152851Sariff#include <sys/param.h> 44152851Sariff#include <sys/linker.h> 45152851Sariff#include <sys/queue.h> 46152851Sariff#include <sys/callout.h> 47152851Sariff#include <sys/sbuf.h> 48152851Sariff#include <sys/capability.h> 49152851Sariff#include <assert.h> 50152851Sariff#include <bsdxml.h> 51152851Sariff#include <ctype.h> 52152851Sariff#include <errno.h> 53152851Sariff#include <fcntl.h> 54152851Sariff#include <stdint.h> 55152851Sariff#include <stdio.h> 56193640Sariff#include <stdlib.h> 57193640Sariff#include <string.h> 58193640Sariff#include <strings.h> 59193640Sariff#include <cam/scsi/scsi_all.h> 60152851Sariff#include <cam/scsi/scsi_message.h> 61152851Sariff#include <cam/ctl/ctl.h> 62152851Sariff#include <cam/ctl/ctl_io.h> 63152851Sariff#include <cam/ctl/ctl_frontend_internal.h> 64152851Sariff#include <cam/ctl/ctl_backend.h> 65152851Sariff#include <cam/ctl/ctl_ioctl.h> 66152851Sariff#include <cam/ctl/ctl_backend_block.h> 67152851Sariff#include <cam/ctl/ctl_util.h> 68152851Sariff#include <cam/ctl/ctl_scsi_all.h> 69152851Sariff 70152851Sariff#include "ctld.h" 71152851Sariff 72167648Sariff#ifdef ICL_KERNEL_PROXY 73162931Sariff#include <netdb.h> 74167648Sariff#endif 75167648Sariff 76167648Sariffextern bool proxy_mode; 77162931Sariff 78167648Sariffstatic int ctl_fd = 0; 79167648Sariff 80167648Sariffvoid 81171329Sariffkernel_init(void) 82171329Sariff{ 83171329Sariff int retval, saved_errno; 84152851Sariff 85155800Sariff ctl_fd = open(CTL_DEFAULT_DEV, O_RDWR); 86155800Sariff if (ctl_fd < 0 && errno == ENOENT) { 87155800Sariff saved_errno = errno; 88155800Sariff retval = kldload("ctl"); 89152851Sariff if (retval != -1) 90152851Sariff ctl_fd = open(CTL_DEFAULT_DEV, O_RDWR); 91152851Sariff else 92152851Sariff errno = saved_errno; 93152851Sariff } 94152851Sariff if (ctl_fd < 0) 95152851Sariff log_err(1, "failed to open %s", CTL_DEFAULT_DEV); 96152851Sariff} 97152851Sariff 98152851Sariff/* 99164614Sariff * Name/value pair used for per-LUN attributes. 100164614Sariff */ 101164614Sariffstruct cctl_lun_nv { 102153708Sariff char *name; 103171329Sariff char *value; 104171329Sariff STAILQ_ENTRY(cctl_lun_nv) links; 105152851Sariff}; 106152851Sariff 107152851Sariff/* 108152851Sariff * Backend LUN information. 109152851Sariff */ 110152851Sariffstruct cctl_lun { 111152851Sariff uint64_t lun_id; 112152851Sariff char *backend_type; 113152851Sariff uint64_t size_blocks; 114152851Sariff uint32_t blocksize; 115152851Sariff char *serial_number; 116152851Sariff char *device_id; 117152851Sariff char *ctld_name; 118152851Sariff STAILQ_HEAD(,cctl_lun_nv) attr_list; 119152851Sariff STAILQ_ENTRY(cctl_lun) links; 120152851Sariff}; 121152851Sariff 122152851Sariffstruct cctl_port { 123152851Sariff uint32_t port_id; 124152851Sariff char *port_name; 125152851Sariff int cfiscsi_state; 126152851Sariff char *cfiscsi_target; 127152851Sariff uint16_t cfiscsi_portal_group_tag; 128152851Sariff char *ctld_portal_group_name; 129164614Sariff STAILQ_HEAD(,cctl_lun_nv) attr_list; 130152851Sariff STAILQ_ENTRY(cctl_port) links; 131152851Sariff}; 132152851Sariff 133164614Sariffstruct cctl_devlist_data { 134164614Sariff int num_luns; 135152851Sariff STAILQ_HEAD(,cctl_lun) lun_list; 136152851Sariff struct cctl_lun *cur_lun; 137152851Sariff int num_ports; 138152851Sariff STAILQ_HEAD(,cctl_port) port_list; 139152851Sariff struct cctl_port *cur_port; 140152851Sariff int level; 141152851Sariff struct sbuf *cur_sb[32]; 142152851Sariff}; 143152851Sariff 144152851Sariffstatic void 145152851Sariffcctl_start_element(void *user_data, const char *name, const char **attr) 146152851Sariff{ 147193640Sariff int i; 148193640Sariff struct cctl_devlist_data *devlist; 149152851Sariff struct cctl_lun *cur_lun; 150152851Sariff 151152851Sariff devlist = (struct cctl_devlist_data *)user_data; 152152851Sariff cur_lun = devlist->cur_lun; 153193640Sariff devlist->level++; 154152851Sariff if ((u_int)devlist->level >= (sizeof(devlist->cur_sb) / 155152851Sariff sizeof(devlist->cur_sb[0]))) 156152851Sariff log_errx(1, "%s: too many nesting levels, %zd max", __func__, 157152851Sariff sizeof(devlist->cur_sb) / sizeof(devlist->cur_sb[0])); 158152851Sariff 159152851Sariff devlist->cur_sb[devlist->level] = sbuf_new_auto(); 160152851Sariff if (devlist->cur_sb[devlist->level] == NULL) 161152851Sariff log_err(1, "%s: unable to allocate sbuf", __func__); 162152851Sariff 163152851Sariff if (strcmp(name, "lun") == 0) { 164152851Sariff if (cur_lun != NULL) 165162931Sariff log_errx(1, "%s: improper lun element nesting", 166152851Sariff __func__); 167152851Sariff 168152851Sariff cur_lun = calloc(1, sizeof(*cur_lun)); 169152851Sariff if (cur_lun == NULL) 170152851Sariff log_err(1, "%s: cannot allocate %zd bytes", __func__, 171152851Sariff sizeof(*cur_lun)); 172152851Sariff 173152851Sariff devlist->num_luns++; 174152851Sariff devlist->cur_lun = cur_lun; 175152851Sariff 176152851Sariff STAILQ_INIT(&cur_lun->attr_list); 177173329Sariff STAILQ_INSERT_TAIL(&devlist->lun_list, cur_lun, links); 178152851Sariff 179152851Sariff for (i = 0; attr[i] != NULL; i += 2) { 180152851Sariff if (strcmp(attr[i], "id") == 0) { 181152851Sariff cur_lun->lun_id = strtoull(attr[i+1], NULL, 0); 182152851Sariff } else { 183162931Sariff log_errx(1, "%s: invalid LUN attribute %s = %s", 184162931Sariff __func__, attr[i], attr[i+1]); 185162931Sariff } 186152851Sariff } 187152851Sariff } 188152851Sariff} 189152851Sariff 190152851Sariffstatic void 191152851Sariffcctl_end_element(void *user_data, const char *name) 192152851Sariff{ 193152851Sariff struct cctl_devlist_data *devlist; 194193640Sariff struct cctl_lun *cur_lun; 195193640Sariff char *str; 196193640Sariff 197152851Sariff devlist = (struct cctl_devlist_data *)user_data; 198152851Sariff cur_lun = devlist->cur_lun; 199162931Sariff 200193640Sariff if ((cur_lun == NULL) 201152851Sariff && (strcmp(name, "ctllunlist") != 0)) 202152851Sariff log_errx(1, "%s: cur_lun == NULL! (name = %s)", __func__, name); 203152851Sariff 204152851Sariff if (devlist->cur_sb[devlist->level] == NULL) 205152851Sariff log_errx(1, "%s: no valid sbuf at level %d (name %s)", __func__, 206152851Sariff devlist->level, name); 207157026Sariff 208152851Sariff sbuf_finish(devlist->cur_sb[devlist->level]); 209152851Sariff str = checked_strdup(sbuf_data(devlist->cur_sb[devlist->level])); 210152851Sariff 211153708Sariff if (strlen(str) == 0) { 212153708Sariff free(str); 213152851Sariff str = NULL; 214152851Sariff } 215152851Sariff 216152851Sariff sbuf_delete(devlist->cur_sb[devlist->level]); 217152851Sariff devlist->cur_sb[devlist->level] = NULL; 218152851Sariff devlist->level--; 219152851Sariff 220152851Sariff if (strcmp(name, "backend_type") == 0) { 221152851Sariff cur_lun->backend_type = str; 222152851Sariff str = NULL; 223152851Sariff } else if (strcmp(name, "size") == 0) { 224152851Sariff cur_lun->size_blocks = strtoull(str, NULL, 0); 225152851Sariff } else if (strcmp(name, "blocksize") == 0) { 226152851Sariff cur_lun->blocksize = strtoul(str, NULL, 0); 227152851Sariff } else if (strcmp(name, "serial_number") == 0) { 228152851Sariff cur_lun->serial_number = str; 229152851Sariff str = NULL; 230152851Sariff } else if (strcmp(name, "device_id") == 0) { 231152851Sariff cur_lun->device_id = str; 232152851Sariff str = NULL; 233152851Sariff } else if (strcmp(name, "ctld_name") == 0) { 234162931Sariff cur_lun->ctld_name = str; 235162931Sariff str = NULL; 236164614Sariff } else if (strcmp(name, "lun") == 0) { 237162931Sariff devlist->cur_lun = NULL; 238152851Sariff } else if (strcmp(name, "ctllunlist") == 0) { 239152851Sariff /* Nothing. */ 240152851Sariff } else { 241152851Sariff struct cctl_lun_nv *nv; 242152851Sariff 243152851Sariff nv = calloc(1, sizeof(*nv)); 244152851Sariff if (nv == NULL) 245152851Sariff log_err(1, "%s: can't allocate %zd bytes for nv pair", 246152851Sariff __func__, sizeof(*nv)); 247152851Sariff 248152851Sariff nv->name = checked_strdup(name); 249152851Sariff 250152851Sariff nv->value = str; 251152851Sariff str = NULL; 252152851Sariff STAILQ_INSERT_TAIL(&cur_lun->attr_list, nv, links); 253152851Sariff } 254152851Sariff 255152851Sariff free(str); 256152851Sariff} 257152851Sariff 258152851Sariffstatic void 259152851Sariffcctl_start_pelement(void *user_data, const char *name, const char **attr) 260152851Sariff{ 261152851Sariff int i; 262152851Sariff struct cctl_devlist_data *devlist; 263152851Sariff struct cctl_port *cur_port; 264152851Sariff 265152851Sariff devlist = (struct cctl_devlist_data *)user_data; 266152851Sariff cur_port = devlist->cur_port; 267152851Sariff devlist->level++; 268152851Sariff if ((u_int)devlist->level >= (sizeof(devlist->cur_sb) / 269152851Sariff sizeof(devlist->cur_sb[0]))) 270152851Sariff log_errx(1, "%s: too many nesting levels, %zd max", __func__, 271152851Sariff sizeof(devlist->cur_sb) / sizeof(devlist->cur_sb[0])); 272162931Sariff 273152851Sariff devlist->cur_sb[devlist->level] = sbuf_new_auto(); 274152851Sariff if (devlist->cur_sb[devlist->level] == NULL) 275152851Sariff log_err(1, "%s: unable to allocate sbuf", __func__); 276152851Sariff 277152851Sariff if (strcmp(name, "targ_port") == 0) { 278152851Sariff if (cur_port != NULL) 279152851Sariff log_errx(1, "%s: improper port element nesting (%s)", 280152851Sariff __func__, name); 281152851Sariff 282152851Sariff cur_port = calloc(1, sizeof(*cur_port)); 283152851Sariff if (cur_port == NULL) 284152851Sariff log_err(1, "%s: cannot allocate %zd bytes", __func__, 285152851Sariff sizeof(*cur_port)); 286152851Sariff 287152851Sariff devlist->num_ports++; 288152851Sariff devlist->cur_port = cur_port; 289152851Sariff 290152851Sariff STAILQ_INIT(&cur_port->attr_list); 291164614Sariff STAILQ_INSERT_TAIL(&devlist->port_list, cur_port, links); 292153708Sariff 293152851Sariff for (i = 0; attr[i] != NULL; i += 2) { 294153708Sariff if (strcmp(attr[i], "id") == 0) { 295152851Sariff cur_port->port_id = strtoul(attr[i+1], NULL, 0); 296152851Sariff } else { 297152851Sariff log_errx(1, "%s: invalid LUN attribute %s = %s", 298152851Sariff __func__, attr[i], attr[i+1]); 299152851Sariff } 300152851Sariff } 301152851Sariff } 302152851Sariff} 303152851Sariff 304152851Sariffstatic void 305152851Sariffcctl_end_pelement(void *user_data, const char *name) 306152851Sariff{ 307152851Sariff struct cctl_devlist_data *devlist; 308152851Sariff struct cctl_port *cur_port; 309152851Sariff char *str; 310152851Sariff 311152851Sariff devlist = (struct cctl_devlist_data *)user_data; 312162931Sariff cur_port = devlist->cur_port; 313152851Sariff 314152851Sariff if ((cur_port == NULL) 315152851Sariff && (strcmp(name, "ctlportlist") != 0)) 316153708Sariff log_errx(1, "%s: cur_port == NULL! (name = %s)", __func__, name); 317152851Sariff 318152851Sariff if (devlist->cur_sb[devlist->level] == NULL) 319153708Sariff log_errx(1, "%s: no valid sbuf at level %d (name %s)", __func__, 320152851Sariff devlist->level, name); 321152851Sariff 322152851Sariff sbuf_finish(devlist->cur_sb[devlist->level]); 323152851Sariff str = checked_strdup(sbuf_data(devlist->cur_sb[devlist->level])); 324152851Sariff 325152851Sariff if (strlen(str) == 0) { 326152851Sariff free(str); 327152851Sariff str = NULL; 328162931Sariff } 329152851Sariff 330162931Sariff sbuf_delete(devlist->cur_sb[devlist->level]); 331152851Sariff devlist->cur_sb[devlist->level] = NULL; 332152851Sariff devlist->level--; 333152851Sariff 334162931Sariff if (strcmp(name, "port_name") == 0) { 335152851Sariff cur_port->port_name = str; 336152851Sariff str = NULL; 337152851Sariff } else if (strcmp(name, "cfiscsi_target") == 0) { 338162931Sariff cur_port->cfiscsi_target = str; 339152851Sariff str = NULL; 340152851Sariff } else if (strcmp(name, "cfiscsi_state") == 0) { 341162931Sariff cur_port->cfiscsi_state = strtoul(str, NULL, 0); 342152851Sariff } else if (strcmp(name, "cfiscsi_portal_group_tag") == 0) { 343152851Sariff cur_port->cfiscsi_portal_group_tag = strtoul(str, NULL, 0); 344152851Sariff } else if (strcmp(name, "ctld_portal_group_name") == 0) { 345162931Sariff cur_port->ctld_portal_group_name = str; 346162931Sariff str = NULL; 347152851Sariff } else if (strcmp(name, "targ_port") == 0) { 348152851Sariff devlist->cur_port = NULL; 349152851Sariff } else if (strcmp(name, "ctlportlist") == 0) { 350162931Sariff /* Nothing. */ 351152851Sariff } else { 352152851Sariff struct cctl_lun_nv *nv; 353162931Sariff 354152851Sariff nv = calloc(1, sizeof(*nv)); 355152851Sariff if (nv == NULL) 356152851Sariff log_err(1, "%s: can't allocate %zd bytes for nv pair", 357152851Sariff __func__, sizeof(*nv)); 358152851Sariff 359152851Sariff nv->name = checked_strdup(name); 360152851Sariff 361152851Sariff nv->value = str; 362152851Sariff str = NULL; 363152851Sariff STAILQ_INSERT_TAIL(&cur_port->attr_list, nv, links); 364152851Sariff } 365152851Sariff 366152851Sariff free(str); 367164614Sariff} 368162931Sariff 369152851Sariffstatic void 370162931Sariffcctl_char_handler(void *user_data, const XML_Char *str, int len) 371152851Sariff{ 372162931Sariff struct cctl_devlist_data *devlist; 373152851Sariff 374152851Sariff devlist = (struct cctl_devlist_data *)user_data; 375152851Sariff 376152851Sariff sbuf_bcat(devlist->cur_sb[devlist->level], str, len); 377152851Sariff} 378152851Sariff 379152851Sariffstruct conf * 380152851Sariffconf_new_from_kernel(void) 381152851Sariff{ 382152851Sariff struct conf *conf = NULL; 383162931Sariff struct target *targ; 384152851Sariff struct portal_group *pg; 385152851Sariff struct pport *pp; 386164614Sariff struct port *cp; 387152851Sariff struct lun *cl; 388152851Sariff struct lun_option *lo; 389152851Sariff struct ctl_lun_list list; 390152851Sariff struct cctl_devlist_data devlist; 391162931Sariff struct cctl_lun *lun; 392152851Sariff struct cctl_port *port; 393152851Sariff XML_Parser parser; 394152851Sariff char *str; 395152851Sariff int len, retval; 396152851Sariff 397162931Sariff bzero(&devlist, sizeof(devlist)); 398152851Sariff STAILQ_INIT(&devlist.lun_list); 399162931Sariff STAILQ_INIT(&devlist.port_list); 400152851Sariff 401152851Sariff log_debugx("obtaining previously configured CTL luns from the kernel"); 402152851Sariff 403152851Sariff str = NULL; 404162931Sariff len = 4096; 405152851Sariffretry: 406152851Sariff str = realloc(str, len); 407152851Sariff if (str == NULL) 408152851Sariff log_err(1, "realloc"); 409152851Sariff 410152851Sariff bzero(&list, sizeof(list)); 411152851Sariff list.alloc_len = len; 412152851Sariff list.status = CTL_LUN_LIST_NONE; 413162931Sariff list.lun_xml = str; 414152851Sariff 415152851Sariff if (ioctl(ctl_fd, CTL_LUN_LIST, &list) == -1) { 416164614Sariff log_warn("error issuing CTL_LUN_LIST ioctl"); 417164614Sariff free(str); 418152851Sariff return (NULL); 419152851Sariff } 420152851Sariff 421162931Sariff if (list.status == CTL_LUN_LIST_ERROR) { 422152851Sariff log_warnx("error returned from CTL_LUN_LIST ioctl: %s", 423152851Sariff list.error_str); 424152851Sariff free(str); 425164614Sariff return (NULL); 426164614Sariff } 427193640Sariff 428152851Sariff if (list.status == CTL_LUN_LIST_NEED_MORE_SPACE) { 429152851Sariff len = len << 1; 430152851Sariff goto retry; 431152851Sariff } 432152851Sariff 433152851Sariff parser = XML_ParserCreate(NULL); 434152851Sariff if (parser == NULL) { 435152851Sariff log_warnx("unable to create XML parser"); 436152851Sariff free(str); 437152851Sariff return (NULL); 438152851Sariff } 439152851Sariff 440152851Sariff XML_SetUserData(parser, &devlist); 441152851Sariff XML_SetElementHandler(parser, cctl_start_element, cctl_end_element); 442152851Sariff XML_SetCharacterDataHandler(parser, cctl_char_handler); 443152851Sariff 444152851Sariff retval = XML_Parse(parser, str, strlen(str), 1); 445152851Sariff XML_ParserFree(parser); 446152851Sariff free(str); 447152851Sariff if (retval != 1) { 448152851Sariff log_warnx("XML_Parse failed"); 449164614Sariff return (NULL); 450152851Sariff } 451152851Sariff 452152851Sariff str = NULL; 453152851Sariff len = 4096; 454152851Sariffretry_port: 455164614Sariff str = realloc(str, len); 456152851Sariff if (str == NULL) 457164614Sariff log_err(1, "realloc"); 458152851Sariff 459154595Sariff bzero(&list, sizeof(list)); 460152851Sariff list.alloc_len = len; 461152851Sariff list.status = CTL_LUN_LIST_NONE; 462152851Sariff list.lun_xml = str; 463152851Sariff 464152851Sariff if (ioctl(ctl_fd, CTL_PORT_LIST, &list) == -1) { 465152851Sariff log_warn("error issuing CTL_PORT_LIST ioctl"); 466164614Sariff free(str); 467164614Sariff return (NULL); 468152851Sariff } 469152851Sariff 470152851Sariff if (list.status == CTL_PORT_LIST_ERROR) { 471168847Sariff log_warnx("error returned from CTL_PORT_LIST ioctl: %s", 472162931Sariff list.error_str); 473152851Sariff free(str); 474152851Sariff return (NULL); 475152851Sariff } 476167648Sariff 477167648Sariff if (list.status == CTL_LUN_LIST_NEED_MORE_SPACE) { 478164614Sariff len = len << 1; 479162931Sariff goto retry_port; 480152851Sariff } 481152851Sariff 482162931Sariff parser = XML_ParserCreate(NULL); 483152851Sariff if (parser == NULL) { 484152851Sariff log_warnx("unable to create XML parser"); 485152851Sariff free(str); 486152851Sariff return (NULL); 487152851Sariff } 488152851Sariff 489152851Sariff XML_SetUserData(parser, &devlist); 490152851Sariff XML_SetElementHandler(parser, cctl_start_pelement, cctl_end_pelement); 491152851Sariff XML_SetCharacterDataHandler(parser, cctl_char_handler); 492152851Sariff 493152851Sariff retval = XML_Parse(parser, str, strlen(str), 1); 494152851Sariff XML_ParserFree(parser); 495152851Sariff free(str); 496155800Sariff if (retval != 1) { 497152851Sariff log_warnx("XML_Parse failed"); 498152851Sariff return (NULL); 499152851Sariff } 500152851Sariff 501152851Sariff conf = conf_new(); 502152851Sariff 503152851Sariff STAILQ_FOREACH(port, &devlist.port_list, links) { 504164614Sariff 505152851Sariff if (port->cfiscsi_target == NULL) { 506152851Sariff log_debugx("CTL port %u \"%s\" wasn't managed by ctld; ", 507152851Sariff port->port_id, port->port_name); 508152851Sariff pp = pport_find(conf, port->port_name); 509155800Sariff if (pp == NULL) { 510152851Sariff#if 0 511152851Sariff log_debugx("found new kernel port %u \"%s\"", 512152851Sariff port->port_id, port->port_name); 513152851Sariff#endif 514152851Sariff pp = pport_new(conf, port->port_name, port->port_id); 515152851Sariff if (pp == NULL) { 516153708Sariff log_warnx("pport_new failed"); 517152851Sariff continue; 518152851Sariff } 519162931Sariff } 520152851Sariff continue; 521152851Sariff } 522193640Sariff if (port->cfiscsi_state != 1) { 523152851Sariff log_debugx("CTL port %ju is not active (%d); ignoring", 524152851Sariff (uintmax_t)port->port_id, port->cfiscsi_state); 525152851Sariff continue; 526162931Sariff } 527152851Sariff 528152851Sariff targ = target_find(conf, port->cfiscsi_target); 529152851Sariff if (targ == NULL) { 530167648Sariff#if 0 531167648Sariff log_debugx("found new kernel target %s for CTL port %ld", 532152851Sariff port->cfiscsi_target, port->port_id); 533152851Sariff#endif 534152851Sariff targ = target_new(conf, port->cfiscsi_target); 535152851Sariff if (targ == NULL) { 536167648Sariff log_warnx("target_new failed"); 537152851Sariff continue; 538167648Sariff } 539167648Sariff } 540167648Sariff 541167648Sariff if (port->ctld_portal_group_name == NULL) 542167648Sariff continue; 543167648Sariff pg = portal_group_find(conf, port->ctld_portal_group_name); 544167648Sariff if (pg == NULL) { 545167648Sariff#if 0 546167648Sariff log_debugx("found new kernel portal group %s for CTL port %ld", 547167648Sariff port->ctld_portal_group_name, port->port_id); 548167648Sariff#endif 549167648Sariff pg = portal_group_new(conf, port->ctld_portal_group_name); 550167648Sariff if (pg == NULL) { 551167648Sariff log_warnx("portal_group_new failed"); 552167648Sariff continue; 553167648Sariff } 554167648Sariff } 555167648Sariff pg->pg_tag = port->cfiscsi_portal_group_tag; 556164614Sariff cp = port_new(conf, targ, pg); 557167648Sariff if (cp == NULL) { 558167648Sariff log_warnx("port_new failed"); 559164614Sariff continue; 560167648Sariff } 561152851Sariff cp->p_ctl_port = port->port_id; 562164614Sariff } 563167648Sariff 564164614Sariff STAILQ_FOREACH(lun, &devlist.lun_list, links) { 565193640Sariff struct cctl_lun_nv *nv; 566167648Sariff 567167648Sariff if (lun->ctld_name == NULL) { 568193640Sariff log_debugx("CTL lun %ju wasn't managed by ctld; " 569167648Sariff "ignoring", (uintmax_t)lun->lun_id); 570167648Sariff continue; 571167648Sariff } 572167648Sariff 573167648Sariff cl = lun_find(conf, lun->ctld_name); 574167648Sariff if (cl != NULL) { 575167648Sariff log_warnx("found CTL lun %ju \"%s\", " 576164614Sariff "also backed by CTL lun %d; ignoring", 577152851Sariff (uintmax_t)lun->lun_id, lun->ctld_name, 578152851Sariff cl->l_ctl_lun); 579152851Sariff continue; 580152851Sariff } 581152851Sariff 582164614Sariff log_debugx("found CTL lun %ju \"%s\"", 583164614Sariff (uintmax_t)lun->lun_id, lun->ctld_name); 584152851Sariff 585152851Sariff cl = lun_new(conf, lun->ctld_name); 586152851Sariff if (cl == NULL) { 587152851Sariff log_warnx("lun_new failed"); 588164614Sariff continue; 589164614Sariff } 590164614Sariff lun_set_backend(cl, lun->backend_type); 591164614Sariff lun_set_blocksize(cl, lun->blocksize); 592164614Sariff lun_set_device_id(cl, lun->device_id); 593164614Sariff lun_set_serial(cl, lun->serial_number); 594164614Sariff lun_set_size(cl, lun->size_blocks * cl->l_blocksize); 595164614Sariff lun_set_ctl_lun(cl, lun->lun_id); 596164614Sariff 597164614Sariff STAILQ_FOREACH(nv, &lun->attr_list, links) { 598152851Sariff if (strcmp(nv->name, "file") == 0 || 599164614Sariff strcmp(nv->name, "dev") == 0) { 600162931Sariff lun_set_path(cl, nv->value); 601164614Sariff continue; 602152851Sariff } 603152851Sariff lo = lun_option_new(cl, nv->name, nv->value); 604152851Sariff if (lo == NULL) 605162931Sariff log_warnx("unable to add CTL lun option %s " 606162931Sariff "for CTL lun %ju \"%s\"", 607152851Sariff nv->name, (uintmax_t) lun->lun_id, 608152851Sariff cl->l_name); 609162931Sariff } 610155800Sariff } 611152851Sariff 612164614Sariff return (conf); 613155800Sariff} 614164614Sariff 615162931Sariffstatic void 616155800Sariffstr_arg(struct ctl_be_arg *arg, const char *name, const char *value) 617155800Sariff{ 618162931Sariff 619155800Sariff arg->namelen = strlen(name) + 1; 620155800Sariff arg->name = __DECONST(char *, name); 621155800Sariff arg->vallen = strlen(value) + 1; 622162931Sariff arg->value = __DECONST(char *, value); 623164614Sariff arg->flags = CTL_BEARG_ASCII | CTL_BEARG_RD; 624162931Sariff} 625164614Sariff 626162931Sariffint 627152851Sariffkernel_lun_add(struct lun *lun) 628164614Sariff{ 629162931Sariff struct lun_option *lo; 630164614Sariff struct ctl_lun_req req; 631155800Sariff int error, i, num_options; 632162931Sariff 633162931Sariff bzero(&req, sizeof(req)); 634164614Sariff 635164614Sariff strlcpy(req.backend, lun->l_backend, sizeof(req.backend)); 636164614Sariff req.reqtype = CTL_LUNREQ_CREATE; 637162931Sariff 638162931Sariff req.reqdata.create.blocksize_bytes = lun->l_blocksize; 639162931Sariff 640164614Sariff if (lun->l_size != 0) 641164614Sariff req.reqdata.create.lun_size_bytes = lun->l_size; 642164614Sariff 643164614Sariff req.reqdata.create.flags |= CTL_LUN_FLAG_DEV_TYPE; 644162931Sariff req.reqdata.create.device_type = T_DIRECT; 645164614Sariff 646162931Sariff if (lun->l_serial != NULL) { 647164614Sariff strncpy(req.reqdata.create.serial_num, lun->l_serial, 648162931Sariff sizeof(req.reqdata.create.serial_num)); 649164614Sariff req.reqdata.create.flags |= CTL_LUN_FLAG_SERIAL_NUM; 650162931Sariff } 651162931Sariff 652162931Sariff if (lun->l_device_id != NULL) { 653155800Sariff strncpy(req.reqdata.create.device_id, lun->l_device_id, 654162931Sariff sizeof(req.reqdata.create.device_id)); 655164614Sariff req.reqdata.create.flags |= CTL_LUN_FLAG_DEVID; 656162931Sariff } 657162931Sariff 658152851Sariff if (lun->l_path != NULL) { 659152851Sariff lo = lun_option_find(lun, "file"); 660164614Sariff if (lo != NULL) { 661164614Sariff lun_option_set(lo, lun->l_path); 662164614Sariff } else { 663164614Sariff lo = lun_option_new(lun, "file", lun->l_path); 664164614Sariff assert(lo != NULL); 665164614Sariff } 666171329Sariff } 667164614Sariff 668164614Sariff lo = lun_option_find(lun, "ctld_name"); 669164614Sariff if (lo != NULL) { 670164614Sariff lun_option_set(lo, lun->l_name); 671164614Sariff } else { 672164614Sariff lo = lun_option_new(lun, "ctld_name", lun->l_name); 673164614Sariff assert(lo != NULL); 674164614Sariff } 675164614Sariff 676164614Sariff lo = lun_option_find(lun, "scsiname"); 677164614Sariff if (lo == NULL && lun->l_scsiname != NULL) { 678164614Sariff lo = lun_option_new(lun, "scsiname", lun->l_scsiname); 679164614Sariff assert(lo != NULL); 680164614Sariff } 681164614Sariff 682164614Sariff num_options = 0; 683164614Sariff TAILQ_FOREACH(lo, &lun->l_options, lo_next) 684171329Sariff num_options++; 685171329Sariff 686164614Sariff req.num_be_args = num_options; 687164614Sariff if (num_options > 0) { 688164614Sariff req.be_args = malloc(num_options * sizeof(*req.be_args)); 689164614Sariff if (req.be_args == NULL) { 690164614Sariff log_warn("error allocating %zd bytes", 691164614Sariff num_options * sizeof(*req.be_args)); 692164614Sariff return (1); 693164614Sariff } 694164614Sariff 695164614Sariff i = 0; 696164614Sariff TAILQ_FOREACH(lo, &lun->l_options, lo_next) { 697164614Sariff str_arg(&req.be_args[i], lo->lo_name, lo->lo_value); 698164614Sariff i++; 699164614Sariff } 700164614Sariff assert(i == num_options); 701164614Sariff } 702164614Sariff 703164614Sariff error = ioctl(ctl_fd, CTL_LUN_REQ, &req); 704164614Sariff free(req.be_args); 705164614Sariff if (error != 0) { 706164614Sariff log_warn("error issuing CTL_LUN_REQ ioctl"); 707164614Sariff return (1); 708164614Sariff } 709164614Sariff 710164614Sariff switch (req.status) { 711164614Sariff case CTL_LUN_ERROR: 712164614Sariff log_warnx("LUN creation error: %s", req.error_str); 713164614Sariff return (1); 714164614Sariff case CTL_LUN_WARNING: 715164614Sariff log_warnx("LUN creation warning: %s", req.error_str); 716164614Sariff break; 717162931Sariff case CTL_LUN_OK: 718164614Sariff break; 719164614Sariff default: 720164614Sariff log_warnx("unknown LUN creation status: %d", 721164614Sariff req.status); 722164614Sariff return (1); 723164614Sariff } 724164614Sariff 725170521Sariff lun_set_ctl_lun(lun, req.reqdata.create.req_lun_id); 726170521Sariff return (0); 727170521Sariff} 728164614Sariff 729164614Sariffint 730164614Sariffkernel_lun_resize(struct lun *lun) 731164614Sariff{ 732164614Sariff struct ctl_lun_req req; 733164614Sariff 734164614Sariff bzero(&req, sizeof(req)); 735164614Sariff 736164614Sariff strlcpy(req.backend, lun->l_backend, sizeof(req.backend)); 737164614Sariff req.reqtype = CTL_LUNREQ_MODIFY; 738164614Sariff 739164614Sariff req.reqdata.modify.lun_id = lun->l_ctl_lun; 740164614Sariff req.reqdata.modify.lun_size_bytes = lun->l_size; 741164614Sariff 742193640Sariff if (ioctl(ctl_fd, CTL_LUN_REQ, &req) == -1) { 743164614Sariff log_warn("error issuing CTL_LUN_REQ ioctl"); 744164614Sariff return (1); 745164614Sariff } 746164614Sariff 747164614Sariff switch (req.status) { 748164614Sariff case CTL_LUN_ERROR: 749164614Sariff log_warnx("LUN modification error: %s", req.error_str); 750164614Sariff return (1); 751164614Sariff case CTL_LUN_WARNING: 752164614Sariff log_warnx("LUN modification warning: %s", req.error_str); 753164614Sariff break; 754164614Sariff case CTL_LUN_OK: 755164614Sariff break; 756164614Sariff default: 757164614Sariff log_warnx("unknown LUN modification status: %d", 758164614Sariff req.status); 759164614Sariff return (1); 760164614Sariff } 761164614Sariff 762164614Sariff return (0); 763164614Sariff} 764164614Sariff 765164614Sariffint 766164614Sariffkernel_lun_remove(struct lun *lun) 767171329Sariff{ 768164614Sariff struct ctl_lun_req req; 769164614Sariff 770164614Sariff bzero(&req, sizeof(req)); 771164614Sariff 772164614Sariff strlcpy(req.backend, lun->l_backend, sizeof(req.backend)); 773171329Sariff req.reqtype = CTL_LUNREQ_RM; 774164614Sariff 775164614Sariff req.reqdata.rm.lun_id = lun->l_ctl_lun; 776164614Sariff 777164614Sariff if (ioctl(ctl_fd, CTL_LUN_REQ, &req) == -1) { 778164614Sariff log_warn("error issuing CTL_LUN_REQ ioctl"); 779171329Sariff return (1); 780164614Sariff } 781164614Sariff 782164614Sariff switch (req.status) { 783164614Sariff case CTL_LUN_ERROR: 784193640Sariff log_warnx("LUN removal error: %s", req.error_str); 785164614Sariff return (1); 786164614Sariff case CTL_LUN_WARNING: 787164614Sariff log_warnx("LUN removal warning: %s", req.error_str); 788164614Sariff break; 789164614Sariff case CTL_LUN_OK: 790164614Sariff break; 791164614Sariff default: 792164614Sariff log_warnx("unknown LUN removal status: %d", req.status); 793164614Sariff return (1); 794164614Sariff } 795164614Sariff 796164614Sariff return (0); 797164614Sariff} 798164614Sariff 799164614Sariffvoid 800164614Sariffkernel_handoff(struct connection *conn) 801164614Sariff{ 802164614Sariff struct ctl_iscsi req; 803164614Sariff 804164614Sariff bzero(&req, sizeof(req)); 805164614Sariff 806164614Sariff req.type = CTL_ISCSI_HANDOFF; 807164614Sariff strlcpy(req.data.handoff.initiator_name, 808164614Sariff conn->conn_initiator_name, sizeof(req.data.handoff.initiator_name)); 809164614Sariff strlcpy(req.data.handoff.initiator_addr, 810164614Sariff conn->conn_initiator_addr, sizeof(req.data.handoff.initiator_addr)); 811164614Sariff if (conn->conn_initiator_alias != NULL) { 812164614Sariff strlcpy(req.data.handoff.initiator_alias, 813164614Sariff conn->conn_initiator_alias, sizeof(req.data.handoff.initiator_alias)); 814164614Sariff } 815164614Sariff memcpy(req.data.handoff.initiator_isid, conn->conn_initiator_isid, 816164614Sariff sizeof(req.data.handoff.initiator_isid)); 817164614Sariff strlcpy(req.data.handoff.target_name, 818164614Sariff conn->conn_target->t_name, sizeof(req.data.handoff.target_name)); 819164614Sariff#ifdef ICL_KERNEL_PROXY 820164614Sariff if (proxy_mode) 821164614Sariff req.data.handoff.connection_id = conn->conn_socket; 822164614Sariff else 823164614Sariff req.data.handoff.socket = conn->conn_socket; 824164614Sariff#else 825193640Sariff req.data.handoff.socket = conn->conn_socket; 826162931Sariff#endif 827162931Sariff req.data.handoff.portal_group_tag = 828162931Sariff conn->conn_portal->p_portal_group->pg_tag; 829162931Sariff if (conn->conn_header_digest == CONN_DIGEST_CRC32C) 830162931Sariff req.data.handoff.header_digest = CTL_ISCSI_DIGEST_CRC32C; 831162931Sariff if (conn->conn_data_digest == CONN_DIGEST_CRC32C) 832162931Sariff req.data.handoff.data_digest = CTL_ISCSI_DIGEST_CRC32C; 833164614Sariff req.data.handoff.cmdsn = conn->conn_cmdsn; 834164614Sariff req.data.handoff.statsn = conn->conn_statsn; 835164614Sariff req.data.handoff.max_recv_data_segment_length = 836164614Sariff conn->conn_max_data_segment_length; 837162931Sariff req.data.handoff.max_burst_length = conn->conn_max_burst_length; 838162931Sariff req.data.handoff.immediate_data = conn->conn_immediate_data; 839162931Sariff 840162931Sariff if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) { 841162931Sariff log_err(1, "error issuing CTL_ISCSI ioctl; " 842152851Sariff "dropping connection"); 843152851Sariff } 844152851Sariff 845152851Sariff if (req.status != CTL_ISCSI_OK) { 846152851Sariff log_errx(1, "error returned from CTL iSCSI handoff request: " 847152851Sariff "%s; dropping connection", req.error_str); 848162931Sariff } 849162931Sariff} 850152851Sariff 851152851Sariffint 852152851Sariffkernel_port_add(struct port *port) 853152851Sariff{ 854152851Sariff struct ctl_port_entry entry; 855152851Sariff struct ctl_req req; 856152851Sariff struct ctl_lun_map lm; 857167648Sariff struct target *targ = port->p_target; 858152851Sariff struct portal_group *pg = port->p_portal_group; 859152851Sariff char tagstr[16]; 860152851Sariff int error, i, n; 861193640Sariff 862152851Sariff /* Create iSCSI port. */ 863152851Sariff if (port->p_portal_group) { 864152851Sariff bzero(&req, sizeof(req)); 865152851Sariff strlcpy(req.driver, "iscsi", sizeof(req.driver)); 866152851Sariff req.reqtype = CTL_REQ_CREATE; 867152851Sariff req.num_args = 5; 868152851Sariff req.args = malloc(req.num_args * sizeof(*req.args)); 869152851Sariff if (req.args == NULL) 870152851Sariff log_err(1, "malloc"); 871152851Sariff n = 0; 872152851Sariff req.args[n].namelen = sizeof("port_id"); 873164614Sariff req.args[n].name = __DECONST(char *, "port_id"); 874152851Sariff req.args[n].vallen = sizeof(port->p_ctl_port); 875152851Sariff req.args[n].value = &port->p_ctl_port; 876164614Sariff req.args[n++].flags = CTL_BEARG_WR; 877164614Sariff str_arg(&req.args[n++], "cfiscsi_target", targ->t_name); 878164614Sariff snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag); 879164614Sariff str_arg(&req.args[n++], "cfiscsi_portal_group_tag", tagstr); 880152851Sariff if (targ->t_alias) 881152851Sariff str_arg(&req.args[n++], "cfiscsi_target_alias", targ->t_alias); 882152851Sariff str_arg(&req.args[n++], "ctld_portal_group_name", pg->pg_name); 883152851Sariff req.num_args = n; 884152851Sariff error = ioctl(ctl_fd, CTL_PORT_REQ, &req); 885152851Sariff free(req.args); 886152851Sariff if (error != 0) { 887171329Sariff log_warn("error issuing CTL_PORT_REQ ioctl"); 888171329Sariff return (1); 889164614Sariff } 890171329Sariff if (req.status == CTL_LUN_ERROR) { 891171329Sariff log_warnx("error returned from port creation request: %s", 892164614Sariff req.error_str); 893152851Sariff return (1); 894152851Sariff } 895152851Sariff if (req.status != CTL_LUN_OK) { 896152851Sariff log_warnx("unknown port creation request status %d", 897152851Sariff req.status); 898152851Sariff return (1); 899152851Sariff } 900152851Sariff } else if (port->p_pport) { 901152851Sariff port->p_ctl_port = port->p_pport->pp_ctl_port; 902152851Sariff 903152851Sariff if (strncmp(targ->t_name, "naa.", 4) == 0 && 904152851Sariff strlen(targ->t_name) == 20) { 905152851Sariff bzero(&entry, sizeof(entry)); 906152851Sariff entry.port_type = CTL_PORT_NONE; 907152851Sariff entry.targ_port = port->p_ctl_port; 908152851Sariff entry.flags |= CTL_PORT_WWNN_VALID; 909152851Sariff entry.wwnn = strtoull(targ->t_name + 4, NULL, 16); 910172568Skevlo if (ioctl(ctl_fd, CTL_SET_PORT_WWNS, &entry) == -1) 911152851Sariff log_warn("CTL_SET_PORT_WWNS ioctl failed"); 912152851Sariff } 913152851Sariff } 914170720Sariff 915152851Sariff /* Explicitly enable mapping to block any access except allowed. */ 916152851Sariff lm.port = port->p_ctl_port; 917152851Sariff lm.plun = UINT32_MAX; 918152851Sariff lm.lun = 0; 919152851Sariff error = ioctl(ctl_fd, CTL_LUN_MAP, &lm); 920164614Sariff if (error != 0) 921164614Sariff log_warn("CTL_LUN_MAP ioctl failed"); 922164614Sariff 923164614Sariff /* Map configured LUNs */ 924164614Sariff for (i = 0; i < MAX_LUNS; i++) { 925152851Sariff if (targ->t_luns[i] == NULL) 926152851Sariff continue; 927152851Sariff lm.port = port->p_ctl_port; 928152851Sariff lm.plun = i; 929152851Sariff lm.lun = targ->t_luns[i]->l_ctl_lun; 930152851Sariff error = ioctl(ctl_fd, CTL_LUN_MAP, &lm); 931152851Sariff if (error != 0) 932152851Sariff log_warn("CTL_LUN_MAP ioctl failed"); 933152851Sariff } 934152851Sariff 935152851Sariff /* Enable port */ 936152851Sariff bzero(&entry, sizeof(entry)); 937152851Sariff entry.targ_port = port->p_ctl_port; 938152851Sariff error = ioctl(ctl_fd, CTL_ENABLE_PORT, &entry); 939152851Sariff if (error != 0) { 940152851Sariff log_warn("CTL_ENABLE_PORT ioctl failed"); 941152851Sariff return (-1); 942152851Sariff } 943152851Sariff 944152851Sariff return (0); 945152851Sariff} 946152851Sariff 947164614Sariffint 948152851Sariffkernel_port_update(struct port *port) 949152851Sariff{ 950152851Sariff struct ctl_lun_map lm; 951152851Sariff struct target *targ = port->p_target; 952152851Sariff int error, i; 953152851Sariff 954152851Sariff /* Map configured LUNs and unmap others */ 955152851Sariff for (i = 0; i < MAX_LUNS; i++) { 956152851Sariff lm.port = port->p_ctl_port; 957152851Sariff lm.plun = i; 958152851Sariff if (targ->t_luns[i] == NULL) 959152851Sariff lm.lun = UINT32_MAX; 960152851Sariff else 961164614Sariff lm.lun = targ->t_luns[i]->l_ctl_lun; 962164614Sariff error = ioctl(ctl_fd, CTL_LUN_MAP, &lm); 963164614Sariff if (error != 0) 964164614Sariff log_warn("CTL_LUN_MAP ioctl failed"); 965164614Sariff } 966164614Sariff return (0); 967164614Sariff} 968164614Sariff 969164614Sariffint 970164614Sariffkernel_port_remove(struct port *port) 971164614Sariff{ 972164614Sariff struct ctl_port_entry entry; 973164614Sariff struct ctl_lun_map lm; 974164614Sariff struct ctl_req req; 975170289Sdwmalone char tagstr[16]; 976164614Sariff struct target *targ = port->p_target; 977164614Sariff struct portal_group *pg = port->p_portal_group; 978164614Sariff int error; 979164614Sariff 980164614Sariff /* Disable port */ 981164614Sariff bzero(&entry, sizeof(entry)); 982164614Sariff entry.targ_port = port->p_ctl_port; 983164614Sariff error = ioctl(ctl_fd, CTL_DISABLE_PORT, &entry); 984164614Sariff if (error != 0) { 985164614Sariff log_warn("CTL_DISABLE_PORT ioctl failed"); 986164614Sariff return (-1); 987164614Sariff } 988164614Sariff 989164614Sariff /* Remove iSCSI port. */ 990164614Sariff if (port->p_portal_group) { 991164614Sariff bzero(&req, sizeof(req)); 992164614Sariff strlcpy(req.driver, "iscsi", sizeof(req.driver)); 993164614Sariff req.reqtype = CTL_REQ_REMOVE; 994164614Sariff req.num_args = 2; 995164614Sariff req.args = malloc(req.num_args * sizeof(*req.args)); 996164614Sariff if (req.args == NULL) 997164614Sariff log_err(1, "malloc"); 998164614Sariff str_arg(&req.args[0], "cfiscsi_target", targ->t_name); 999164614Sariff snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag); 1000164614Sariff str_arg(&req.args[1], "cfiscsi_portal_group_tag", tagstr); 1001152851Sariff error = ioctl(ctl_fd, CTL_PORT_REQ, &req); 1002152851Sariff free(req.args); 1003152851Sariff if (error != 0) { 1004152851Sariff log_warn("error issuing CTL_PORT_REQ ioctl"); 1005155800Sariff return (1); 1006164614Sariff } 1007152851Sariff if (req.status == CTL_LUN_ERROR) { 1008152851Sariff log_warnx("error returned from port removal request: %s", 1009152851Sariff req.error_str); 1010152851Sariff return (1); 1011152851Sariff } 1012152851Sariff if (req.status != CTL_LUN_OK) { 1013152851Sariff log_warnx("unknown port removal request status %d", 1014152851Sariff req.status); 1015152851Sariff return (1); 1016164614Sariff } 1017164614Sariff } else { 1018164614Sariff /* Disable LUN mapping. */ 1019170720Sariff lm.port = port->p_ctl_port; 1020170720Sariff lm.plun = UINT32_MAX; 1021170720Sariff lm.lun = UINT32_MAX; 1022170720Sariff error = ioctl(ctl_fd, CTL_LUN_MAP, &lm); 1023170720Sariff if (error != 0) 1024170720Sariff log_warn("CTL_LUN_MAP ioctl failed"); 1025170720Sariff } 1026170720Sariff return (0); 1027170720Sariff} 1028152851Sariff 1029164614Sariff#ifdef ICL_KERNEL_PROXY 1030152851Sariffvoid 1031152851Sariffkernel_listen(struct addrinfo *ai, bool iser, int portal_id) 1032170720Sariff{ 1033152851Sariff struct ctl_iscsi req; 1034152851Sariff 1035152851Sariff bzero(&req, sizeof(req)); 1036152851Sariff 1037157026Sariff req.type = CTL_ISCSI_LISTEN; 1038152851Sariff req.data.listen.iser = iser; 1039152851Sariff req.data.listen.domain = ai->ai_family; 1040152851Sariff req.data.listen.socktype = ai->ai_socktype; 1041152851Sariff req.data.listen.protocol = ai->ai_protocol; 1042152851Sariff req.data.listen.addr = ai->ai_addr; 1043152851Sariff req.data.listen.addrlen = ai->ai_addrlen; 1044152851Sariff req.data.listen.portal_id = portal_id; 1045152851Sariff 1046164614Sariff if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) 1047152851Sariff log_err(1, "error issuing CTL_ISCSI ioctl"); 1048152851Sariff 1049152851Sariff if (req.status != CTL_ISCSI_OK) { 1050152851Sariff log_errx(1, "error returned from CTL iSCSI listen: %s", 1051152851Sariff req.error_str); 1052152851Sariff } 1053164614Sariff} 1054152851Sariff 1055152851Sariffvoid 1056152851Sariffkernel_accept(int *connection_id, int *portal_id, 1057152851Sariff struct sockaddr *client_sa, socklen_t *client_salen) 1058164614Sariff{ 1059152851Sariff struct ctl_iscsi req; 1060152851Sariff struct sockaddr_storage ss; 1061152851Sariff 1062152851Sariff bzero(&req, sizeof(req)); 1063152851Sariff 1064152851Sariff req.type = CTL_ISCSI_ACCEPT; 1065152851Sariff req.data.accept.initiator_addr = (struct sockaddr *)&ss; 1066157026Sariff 1067152851Sariff if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) 1068152851Sariff log_err(1, "error issuing CTL_ISCSI ioctl"); 1069152851Sariff 1070152851Sariff if (req.status != CTL_ISCSI_OK) { 1071152851Sariff log_errx(1, "error returned from CTL iSCSI accept: %s", 1072152851Sariff req.error_str); 1073164614Sariff } 1074164614Sariff 1075155800Sariff *connection_id = req.data.accept.connection_id; 1076167502Sariff *portal_id = req.data.accept.portal_id; 1077155800Sariff *client_salen = req.data.accept.initiator_addrlen; 1078164614Sariff memcpy(client_sa, &ss, *client_salen); 1079164614Sariff} 1080155800Sariff 1081155800Sariffvoid 1082155800Sariffkernel_send(struct pdu *pdu) 1083155800Sariff{ 1084155800Sariff struct ctl_iscsi req; 1085152851Sariff 1086152851Sariff bzero(&req, sizeof(req)); 1087152851Sariff 1088152851Sariff req.type = CTL_ISCSI_SEND; 1089152851Sariff req.data.send.connection_id = pdu->pdu_connection->conn_socket; 1090152851Sariff req.data.send.bhs = pdu->pdu_bhs; 1091152851Sariff req.data.send.data_segment_len = pdu->pdu_data_len; 1092152851Sariff req.data.send.data_segment = pdu->pdu_data; 1093152851Sariff 1094152851Sariff if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) { 1095164614Sariff log_err(1, "error issuing CTL_ISCSI ioctl; " 1096164614Sariff "dropping connection"); 1097164614Sariff } 1098164614Sariff 1099164614Sariff if (req.status != CTL_ISCSI_OK) { 1100162931Sariff log_errx(1, "error returned from CTL iSCSI send: " 1101164614Sariff "%s; dropping connection", req.error_str); 1102164614Sariff } 1103152851Sariff} 1104152851Sariff 1105152851Sariffvoid 1106152851Sariffkernel_receive(struct pdu *pdu) 1107164614Sariff{ 1108164614Sariff struct ctl_iscsi req; 1109152851Sariff 1110152851Sariff pdu->pdu_data = malloc(MAX_DATA_SEGMENT_LENGTH); 1111152851Sariff if (pdu->pdu_data == NULL) 1112152851Sariff log_err(1, "malloc"); 1113152851Sariff 1114157026Sariff bzero(&req, sizeof(req)); 1115157026Sariff 1116157026Sariff req.type = CTL_ISCSI_RECEIVE; 1117157026Sariff req.data.receive.connection_id = pdu->pdu_connection->conn_socket; 1118157026Sariff req.data.receive.bhs = pdu->pdu_bhs; 1119157026Sariff req.data.receive.data_segment_len = MAX_DATA_SEGMENT_LENGTH; 1120157026Sariff req.data.receive.data_segment = pdu->pdu_data; 1121157026Sariff 1122170721Sariff if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) { 1123170721Sariff log_err(1, "error issuing CTL_ISCSI ioctl; " 1124170721Sariff "dropping connection"); 1125170721Sariff } 1126170721Sariff 1127170721Sariff if (req.status != CTL_ISCSI_OK) { 1128170721Sariff log_errx(1, "error returned from CTL iSCSI receive: " 1129157026Sariff "%s; dropping connection", req.error_str); 1130152851Sariff } 1131157026Sariff 1132157026Sariff} 1133157026Sariff 1134152851Sariff#endif /* ICL_KERNEL_PROXY */ 1135167773Sariff 1136157026Sariff/* 1137157026Sariff * XXX: I CANT INTO LATIN 1138152851Sariff */ 1139167773Sariffvoid 1140157026Sariffkernel_capsicate(void) 1141157026Sariff{ 1142152851Sariff int error; 1143167773Sariff cap_rights_t rights; 1144157026Sariff const unsigned long cmds[] = { CTL_ISCSI }; 1145157026Sariff 1146152851Sariff cap_rights_init(&rights, CAP_IOCTL); 1147167773Sariff error = cap_rights_limit(ctl_fd, &rights); 1148157026Sariff if (error != 0 && errno != ENOSYS) 1149167773Sariff log_err(1, "cap_rights_limit"); 1150152851Sariff 1151167773Sariff error = cap_ioctls_limit(ctl_fd, cmds, 1152167773Sariff sizeof(cmds) / sizeof(cmds[0])); 1153167773Sariff if (error != 0 && errno != ENOSYS) 1154157026Sariff log_err(1, "cap_ioctls_limit"); 1155167773Sariff 1156157026Sariff error = cap_enter(); 1157152851Sariff if (error != 0 && errno != ENOSYS) 1158167773Sariff log_err(1, "cap_enter"); 1159157026Sariff 1160157026Sariff if (cap_sandboxed()) 1161152851Sariff log_debugx("Capsicum capability mode enabled"); 1162157026Sariff else 1163157026Sariff log_warnx("Capsicum capability mode not supported"); 1164170721Sariff} 1165152851Sariff 1166152851Sariff