1295212Sjceel/*- 2295212Sjceel * Copyright (c) 2015 iXsystems Inc. 3295212Sjceel * All rights reserved. 4295212Sjceel * 5295212Sjceel * This software was developed by Jakub Klama <jceel@FreeBSD.org> 6295212Sjceel * under sponsorship from iXsystems Inc. 7295212Sjceel * 8295212Sjceel * Redistribution and use in source and binary forms, with or without 9295212Sjceel * modification, are permitted provided that the following conditions 10295212Sjceel * are met: 11295212Sjceel * 1. Redistributions of source code must retain the above copyright 12295212Sjceel * notice, this list of conditions and the following disclaimer. 13295212Sjceel * 2. Redistributions in binary form must reproduce the above copyright 14295212Sjceel * notice, this list of conditions and the following disclaimer in the 15295212Sjceel * documentation and/or other materials provided with the distribution. 16295212Sjceel * 17295212Sjceel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18295212Sjceel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19295212Sjceel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20295212Sjceel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21295212Sjceel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22295212Sjceel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23295212Sjceel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24295212Sjceel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25295212Sjceel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26295212Sjceel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27295212Sjceel * SUCH DAMAGE. 28295212Sjceel * 29295212Sjceel * $FreeBSD: releng/11.0/usr.sbin/ctld/uclparse.c 296808 2016-03-13 19:50:17Z jceel $ 30295212Sjceel */ 31295212Sjceel 32295212Sjceel#include <sys/queue.h> 33295212Sjceel#include <sys/types.h> 34295212Sjceel#include <assert.h> 35295212Sjceel#include <stdio.h> 36295212Sjceel#include <stdint.h> 37295212Sjceel#include <stdlib.h> 38295212Sjceel#include <string.h> 39295212Sjceel#include <ucl.h> 40295212Sjceel 41295212Sjceel#include "ctld.h" 42295212Sjceel 43295212Sjceelstatic struct conf *conf = NULL; 44295212Sjceel 45295212Sjceelstatic int uclparse_toplevel(const ucl_object_t *); 46295212Sjceelstatic int uclparse_chap(struct auth_group *, const ucl_object_t *); 47295212Sjceelstatic int uclparse_chap_mutual(struct auth_group *, const ucl_object_t *); 48295212Sjceelstatic int uclparse_lun(const char *, const ucl_object_t *); 49295212Sjceelstatic int uclparse_auth_group(const char *, const ucl_object_t *); 50295212Sjceelstatic int uclparse_portal_group(const char *, const ucl_object_t *); 51295212Sjceelstatic int uclparse_target(const char *, const ucl_object_t *); 52295212Sjceelstatic int uclparse_target_portal_group(struct target *, const ucl_object_t *); 53295212Sjceelstatic int uclparse_target_lun(struct target *, const ucl_object_t *); 54295212Sjceel 55295212Sjceelstatic int 56295212Sjceeluclparse_chap(struct auth_group *auth_group, const ucl_object_t *obj) 57295212Sjceel{ 58295212Sjceel const struct auth *ca; 59295212Sjceel const ucl_object_t *user, *secret; 60295212Sjceel 61295212Sjceel user = ucl_object_find_key(obj, "user"); 62295212Sjceel if (!user || user->type != UCL_STRING) { 63295212Sjceel log_warnx("chap section in auth-group \"%s\" is missing " 64295212Sjceel "\"user\" string key", auth_group->ag_name); 65295212Sjceel return (1); 66295212Sjceel } 67295212Sjceel 68295212Sjceel secret = ucl_object_find_key(obj, "secret"); 69295212Sjceel if (!secret || secret->type != UCL_STRING) { 70295212Sjceel log_warnx("chap section in auth-group \"%s\" is missing " 71295212Sjceel "\"secret\" string key", auth_group->ag_name); 72295212Sjceel } 73295212Sjceel 74295212Sjceel ca = auth_new_chap(auth_group, 75295212Sjceel ucl_object_tostring(user), 76295212Sjceel ucl_object_tostring(secret)); 77295212Sjceel 78295212Sjceel if (ca == NULL) 79295212Sjceel return (1); 80295212Sjceel 81295212Sjceel return (0); 82295212Sjceel} 83295212Sjceel 84295212Sjceelstatic int 85295212Sjceeluclparse_chap_mutual(struct auth_group *auth_group, const ucl_object_t *obj) 86295212Sjceel{ 87295212Sjceel const struct auth *ca; 88295212Sjceel const ucl_object_t *user, *secret, *mutual_user; 89295212Sjceel const ucl_object_t *mutual_secret; 90295212Sjceel 91295212Sjceel user = ucl_object_find_key(obj, "user"); 92295212Sjceel if (!user || user->type != UCL_STRING) { 93295212Sjceel log_warnx("chap-mutual section in auth-group \"%s\" is missing " 94295212Sjceel "\"user\" string key", auth_group->ag_name); 95295212Sjceel return (1); 96295212Sjceel } 97295212Sjceel 98295212Sjceel secret = ucl_object_find_key(obj, "secret"); 99295212Sjceel if (!secret || secret->type != UCL_STRING) { 100295212Sjceel log_warnx("chap-mutual section in auth-group \"%s\" is missing " 101295212Sjceel "\"secret\" string key", auth_group->ag_name); 102295212Sjceel return (1); 103295212Sjceel } 104295212Sjceel 105295212Sjceel mutual_user = ucl_object_find_key(obj, "mutual-user"); 106295212Sjceel if (!user || user->type != UCL_STRING) { 107295212Sjceel log_warnx("chap-mutual section in auth-group \"%s\" is missing " 108295212Sjceel "\"mutual-user\" string key", auth_group->ag_name); 109295212Sjceel return (1); 110295212Sjceel } 111295212Sjceel 112295212Sjceel mutual_secret = ucl_object_find_key(obj, "mutual-secret"); 113295212Sjceel if (!secret || secret->type != UCL_STRING) { 114295212Sjceel log_warnx("chap-mutual section in auth-group \"%s\" is missing " 115295212Sjceel "\"mutual-secret\" string key", auth_group->ag_name); 116295212Sjceel return (1); 117295212Sjceel } 118295212Sjceel 119295212Sjceel ca = auth_new_chap_mutual(auth_group, 120295212Sjceel ucl_object_tostring(user), 121295212Sjceel ucl_object_tostring(secret), 122295212Sjceel ucl_object_tostring(mutual_user), 123295212Sjceel ucl_object_tostring(mutual_secret)); 124295212Sjceel 125295212Sjceel if (ca == NULL) 126295212Sjceel return (1); 127295212Sjceel 128295212Sjceel return (0); 129295212Sjceel} 130295212Sjceel 131295212Sjceelstatic int 132295212Sjceeluclparse_target_portal_group(struct target *target, const ucl_object_t *obj) 133295212Sjceel{ 134295212Sjceel struct portal_group *tpg; 135295212Sjceel struct auth_group *tag = NULL; 136295212Sjceel struct port *tp; 137295212Sjceel const ucl_object_t *portal_group, *auth_group; 138295212Sjceel 139295212Sjceel portal_group = ucl_object_find_key(obj, "name"); 140295212Sjceel if (!portal_group || portal_group->type != UCL_STRING) { 141295212Sjceel log_warnx("portal-group section in target \"%s\" is missing " 142295212Sjceel "\"name\" string key", target->t_name); 143295212Sjceel return (1); 144295212Sjceel } 145295212Sjceel 146295212Sjceel auth_group = ucl_object_find_key(obj, "auth-group-name"); 147295212Sjceel if (auth_group && auth_group->type != UCL_STRING) { 148295212Sjceel log_warnx("portal-group section in target \"%s\" is missing " 149295212Sjceel "\"auth-group-name\" string key", target->t_name); 150295212Sjceel return (1); 151295212Sjceel } 152295212Sjceel 153295212Sjceel 154295212Sjceel tpg = portal_group_find(conf, ucl_object_tostring(portal_group)); 155295212Sjceel if (tpg == NULL) { 156295212Sjceel log_warnx("unknown portal-group \"%s\" for target " 157295212Sjceel "\"%s\"", ucl_object_tostring(portal_group), target->t_name); 158295212Sjceel return (1); 159295212Sjceel } 160295212Sjceel 161295212Sjceel if (auth_group) { 162295212Sjceel tag = auth_group_find(conf, ucl_object_tostring(auth_group)); 163295212Sjceel if (tag == NULL) { 164295212Sjceel log_warnx("unknown auth-group \"%s\" for target " 165295212Sjceel "\"%s\"", ucl_object_tostring(auth_group), 166295212Sjceel target->t_name); 167295212Sjceel return (1); 168295212Sjceel } 169295212Sjceel } 170295212Sjceel 171295212Sjceel tp = port_new(conf, target, tpg); 172295212Sjceel if (tp == NULL) { 173295212Sjceel log_warnx("can't link portal-group \"%s\" to target " 174295212Sjceel "\"%s\"", ucl_object_tostring(portal_group), target->t_name); 175295212Sjceel return (1); 176295212Sjceel } 177295212Sjceel tp->p_auth_group = tag; 178295212Sjceel 179295212Sjceel return (0); 180295212Sjceel} 181295212Sjceel 182295212Sjceelstatic int 183295212Sjceeluclparse_target_lun(struct target *target, const ucl_object_t *obj) 184295212Sjceel{ 185295212Sjceel struct lun *lun; 186295212Sjceel 187295212Sjceel if (obj->type == UCL_INT) { 188295212Sjceel char *name; 189295212Sjceel 190295212Sjceel asprintf(&name, "%s,lun,%ju", target->t_name, 191295212Sjceel ucl_object_toint(obj)); 192295212Sjceel lun = lun_new(conf, name); 193295212Sjceel if (lun == NULL) 194295212Sjceel return (1); 195295212Sjceel 196295212Sjceel lun_set_scsiname(lun, name); 197295212Sjceel target->t_luns[ucl_object_toint(obj)] = lun; 198295212Sjceel return (0); 199295212Sjceel } 200295212Sjceel 201295212Sjceel if (obj->type == UCL_OBJECT) { 202295212Sjceel const ucl_object_t *num = ucl_object_find_key(obj, "number"); 203295212Sjceel const ucl_object_t *name = ucl_object_find_key(obj, "name"); 204295212Sjceel 205295212Sjceel if (num == NULL || num->type != UCL_INT) { 206295212Sjceel log_warnx("lun section in target \"%s\" is missing " 207295212Sjceel "\"number\" integer property", target->t_name); 208295212Sjceel return (1); 209295212Sjceel } 210295212Sjceel 211295212Sjceel if (name == NULL || name->type != UCL_STRING) { 212295212Sjceel log_warnx("lun section in target \"%s\" is missing " 213295212Sjceel "\"name\" string property", target->t_name); 214295212Sjceel return (1); 215295212Sjceel } 216295212Sjceel 217295212Sjceel lun = lun_find(conf, ucl_object_tostring(name)); 218295212Sjceel if (lun == NULL) 219295212Sjceel return (1); 220295212Sjceel 221295212Sjceel target->t_luns[ucl_object_toint(num)] = lun; 222295212Sjceel } 223295212Sjceel 224295212Sjceel return (0); 225295212Sjceel} 226295212Sjceel 227295212Sjceelstatic int 228295212Sjceeluclparse_toplevel(const ucl_object_t *top) 229295212Sjceel{ 230295212Sjceel ucl_object_iter_t it = NULL, iter = NULL; 231295212Sjceel const ucl_object_t *obj = NULL, *child = NULL; 232295212Sjceel int err = 0; 233295212Sjceel 234295212Sjceel /* Pass 1 - everything except targets */ 235295212Sjceel while ((obj = ucl_iterate_object(top, &it, true))) { 236295212Sjceel const char *key = ucl_object_key(obj); 237295212Sjceel 238295212Sjceel if (!strcmp(key, "debug")) { 239295212Sjceel if (obj->type == UCL_INT) 240295212Sjceel conf->conf_debug = ucl_object_toint(obj); 241295212Sjceel else { 242295212Sjceel log_warnx("\"debug\" property value is not integer"); 243295212Sjceel return (1); 244295212Sjceel } 245295212Sjceel } 246295212Sjceel 247295212Sjceel if (!strcmp(key, "timeout")) { 248295212Sjceel if (obj->type == UCL_INT) 249295212Sjceel conf->conf_timeout = ucl_object_toint(obj); 250295212Sjceel else { 251295212Sjceel log_warnx("\"timeout\" property value is not integer"); 252295212Sjceel return (1); 253295212Sjceel } 254295212Sjceel } 255295212Sjceel 256295212Sjceel if (!strcmp(key, "maxproc")) { 257295212Sjceel if (obj->type == UCL_INT) 258295212Sjceel conf->conf_maxproc = ucl_object_toint(obj); 259295212Sjceel else { 260295212Sjceel log_warnx("\"maxproc\" property value is not integer"); 261295212Sjceel return (1); 262295212Sjceel } 263295212Sjceel } 264295212Sjceel 265295212Sjceel if (!strcmp(key, "pidfile")) { 266295212Sjceel if (obj->type == UCL_STRING) 267295212Sjceel conf->conf_pidfile_path = strdup( 268295212Sjceel ucl_object_tostring(obj)); 269295212Sjceel else { 270295212Sjceel log_warnx("\"pidfile\" property value is not string"); 271295212Sjceel return (1); 272295212Sjceel } 273295212Sjceel } 274295212Sjceel 275295212Sjceel if (!strcmp(key, "isns-server")) { 276295212Sjceel if (obj->type == UCL_ARRAY) { 277295212Sjceel iter = NULL; 278295212Sjceel while ((child = ucl_iterate_object(obj, &iter, 279295212Sjceel true))) { 280295212Sjceel if (child->type != UCL_STRING) 281295212Sjceel return (1); 282295212Sjceel 283295212Sjceel err = isns_new(conf, 284295212Sjceel ucl_object_tostring(child)); 285295212Sjceel if (err != 0) { 286295212Sjceel return (1); 287295212Sjceel } 288295212Sjceel } 289295212Sjceel } else { 290295212Sjceel log_warnx("\"isns-server\" property value is " 291295212Sjceel "not an array"); 292295212Sjceel return (1); 293295212Sjceel } 294295212Sjceel } 295295212Sjceel 296295212Sjceel if (!strcmp(key, "isns-period")) { 297295212Sjceel if (obj->type == UCL_INT) 298295212Sjceel conf->conf_timeout = ucl_object_toint(obj); 299295212Sjceel else { 300295212Sjceel log_warnx("\"isns-period\" property value is not integer"); 301295212Sjceel return (1); 302295212Sjceel } 303295212Sjceel } 304295212Sjceel 305295212Sjceel if (!strcmp(key, "isns-timeout")) { 306295212Sjceel if (obj->type == UCL_INT) 307295212Sjceel conf->conf_timeout = ucl_object_toint(obj); 308295212Sjceel else { 309295212Sjceel log_warnx("\"isns-timeout\" property value is not integer"); 310295212Sjceel return (1); 311295212Sjceel } 312295212Sjceel } 313295212Sjceel 314295212Sjceel if (!strcmp(key, "auth-group")) { 315295212Sjceel if (obj->type == UCL_OBJECT) { 316295212Sjceel iter = NULL; 317295212Sjceel while ((child = ucl_iterate_object(obj, &iter, true))) { 318295212Sjceel uclparse_auth_group(ucl_object_key(child), child); 319295212Sjceel } 320295212Sjceel } else { 321295212Sjceel log_warnx("\"auth-group\" section is not an object"); 322295212Sjceel return (1); 323295212Sjceel } 324295212Sjceel } 325295212Sjceel 326295212Sjceel if (!strcmp(key, "portal-group")) { 327295212Sjceel if (obj->type == UCL_OBJECT) { 328295212Sjceel iter = NULL; 329295212Sjceel while ((child = ucl_iterate_object(obj, &iter, true))) { 330295212Sjceel uclparse_portal_group(ucl_object_key(child), child); 331295212Sjceel } 332295212Sjceel } else { 333295212Sjceel log_warnx("\"portal-group\" section is not an object"); 334295212Sjceel return (1); 335295212Sjceel } 336295212Sjceel } 337295212Sjceel 338295212Sjceel if (!strcmp(key, "lun")) { 339295212Sjceel if (obj->type == UCL_OBJECT) { 340295212Sjceel iter = NULL; 341295212Sjceel while ((child = ucl_iterate_object(obj, &iter, true))) { 342295212Sjceel uclparse_lun(ucl_object_key(child), child); 343295212Sjceel } 344295212Sjceel } else { 345295212Sjceel log_warnx("\"lun\" section is not an object"); 346295212Sjceel return (1); 347295212Sjceel } 348295212Sjceel } 349295212Sjceel } 350295212Sjceel 351295212Sjceel /* Pass 2 - targets */ 352295212Sjceel it = NULL; 353295212Sjceel while ((obj = ucl_iterate_object(top, &it, true))) { 354295212Sjceel const char *key = ucl_object_key(obj); 355295212Sjceel 356295212Sjceel if (!strcmp(key, "target")) { 357295212Sjceel if (obj->type == UCL_OBJECT) { 358295212Sjceel iter = NULL; 359295212Sjceel while ((child = ucl_iterate_object(obj, &iter, 360295212Sjceel true))) { 361295212Sjceel uclparse_target(ucl_object_key(child), 362295212Sjceel child); 363295212Sjceel } 364295212Sjceel } else { 365295212Sjceel log_warnx("\"target\" section is not an object"); 366295212Sjceel return (1); 367295212Sjceel } 368295212Sjceel } 369295212Sjceel } 370295212Sjceel 371295212Sjceel return (0); 372295212Sjceel} 373295212Sjceel 374295212Sjceelstatic int 375295212Sjceeluclparse_auth_group(const char *name, const ucl_object_t *top) 376295212Sjceel{ 377295212Sjceel struct auth_group *auth_group; 378295212Sjceel const struct auth_name *an; 379295212Sjceel const struct auth_portal *ap; 380295212Sjceel ucl_object_iter_t it = NULL, it2 = NULL; 381295212Sjceel const ucl_object_t *obj = NULL, *tmp = NULL; 382295212Sjceel const char *key; 383295212Sjceel int err; 384295212Sjceel 385295212Sjceel if (!strcmp(name, "default") && 386295212Sjceel conf->conf_default_ag_defined == false) { 387295212Sjceel auth_group = auth_group_find(conf, name); 388295212Sjceel conf->conf_default_ag_defined = true; 389295212Sjceel } else { 390295212Sjceel auth_group = auth_group_new(conf, name); 391295212Sjceel } 392295212Sjceel 393295212Sjceel if (auth_group == NULL) 394295212Sjceel return (1); 395295212Sjceel 396295212Sjceel while ((obj = ucl_iterate_object(top, &it, true))) { 397295212Sjceel key = ucl_object_key(obj); 398295212Sjceel 399295212Sjceel if (!strcmp(key, "auth-type")) { 400295212Sjceel const char *value = ucl_object_tostring(obj); 401295212Sjceel 402295212Sjceel err = auth_group_set_type(auth_group, value); 403295212Sjceel if (err) 404295212Sjceel return (1); 405295212Sjceel } 406295212Sjceel 407295212Sjceel if (!strcmp(key, "chap")) { 408295212Sjceel if (obj->type != UCL_ARRAY) { 409295212Sjceel log_warnx("\"chap\" property of " 410295212Sjceel "auth-group \"%s\" is not an array", 411295212Sjceel name); 412295212Sjceel return (1); 413295212Sjceel } 414295212Sjceel 415295212Sjceel it2 = NULL; 416295212Sjceel while ((tmp = ucl_iterate_object(obj, &it2, true))) { 417295212Sjceel if (uclparse_chap(auth_group, tmp) != 0) 418295212Sjceel return (1); 419295212Sjceel } 420295212Sjceel } 421295212Sjceel 422295212Sjceel if (!strcmp(key, "chap-mutual")) { 423295212Sjceel if (obj->type != UCL_ARRAY) { 424295212Sjceel log_warnx("\"chap-mutual\" property of " 425295212Sjceel "auth-group \"%s\" is not an array", 426295212Sjceel name); 427295212Sjceel return (1); 428295212Sjceel } 429295212Sjceel 430295212Sjceel it2 = NULL; 431295212Sjceel while ((tmp = ucl_iterate_object(obj, &it2, true))) { 432295212Sjceel if (uclparse_chap_mutual(auth_group, tmp) != 0) 433295212Sjceel return (1); 434295212Sjceel } 435295212Sjceel } 436295212Sjceel 437295212Sjceel if (!strcmp(key, "initiator-name")) { 438295212Sjceel if (obj->type != UCL_ARRAY) { 439295212Sjceel log_warnx("\"initiator-name\" property of " 440295212Sjceel "auth-group \"%s\" is not an array", 441295212Sjceel name); 442295212Sjceel return (1); 443295212Sjceel } 444295212Sjceel 445295212Sjceel it2 = NULL; 446295212Sjceel while ((tmp = ucl_iterate_object(obj, &it2, true))) { 447295212Sjceel const char *value = ucl_object_tostring(tmp); 448295212Sjceel 449295212Sjceel an = auth_name_new(auth_group, value); 450295212Sjceel if (an == NULL) 451295212Sjceel return (1); 452295212Sjceel } 453295212Sjceel } 454295212Sjceel 455295212Sjceel if (!strcmp(key, "initiator-portal")) { 456295212Sjceel if (obj->type != UCL_ARRAY) { 457295212Sjceel log_warnx("\"initiator-portal\" property of " 458295212Sjceel "auth-group \"%s\" is not an array", 459295212Sjceel name); 460295212Sjceel return (1); 461295212Sjceel } 462295212Sjceel 463295212Sjceel it2 = NULL; 464295212Sjceel while ((tmp = ucl_iterate_object(obj, &it2, true))) { 465295212Sjceel const char *value = ucl_object_tostring(tmp); 466295212Sjceel 467295212Sjceel ap = auth_portal_new(auth_group, value); 468295212Sjceel if (ap == NULL) 469295212Sjceel return (1); 470295212Sjceel } 471295212Sjceel } 472295212Sjceel } 473295212Sjceel 474295212Sjceel return (0); 475295212Sjceel} 476295212Sjceel 477295212Sjceelstatic int 478295212Sjceeluclparse_portal_group(const char *name, const ucl_object_t *top) 479295212Sjceel{ 480295212Sjceel struct portal_group *portal_group; 481295212Sjceel ucl_object_iter_t it = NULL, it2 = NULL; 482295212Sjceel const ucl_object_t *obj = NULL, *tmp = NULL; 483295212Sjceel const char *key; 484295212Sjceel 485295212Sjceel if (strcmp(name, "default") == 0 && 486295212Sjceel conf->conf_default_pg_defined == false) { 487295212Sjceel portal_group = portal_group_find(conf, name); 488295212Sjceel conf->conf_default_pg_defined = true; 489295212Sjceel } else { 490295212Sjceel portal_group = portal_group_new(conf, name); 491295212Sjceel } 492295212Sjceel 493295212Sjceel if (portal_group == NULL) 494295212Sjceel return (1); 495295212Sjceel 496295212Sjceel while ((obj = ucl_iterate_object(top, &it, true))) { 497295212Sjceel key = ucl_object_key(obj); 498295212Sjceel 499295212Sjceel if (!strcmp(key, "discovery-auth-group")) { 500295212Sjceel portal_group->pg_discovery_auth_group = 501295212Sjceel auth_group_find(conf, ucl_object_tostring(obj)); 502295212Sjceel if (portal_group->pg_discovery_auth_group == NULL) { 503295212Sjceel log_warnx("unknown discovery-auth-group \"%s\" " 504295212Sjceel "for portal-group \"%s\"", 505295212Sjceel ucl_object_tostring(obj), 506295212Sjceel portal_group->pg_name); 507295212Sjceel return (1); 508295212Sjceel } 509295212Sjceel } 510295212Sjceel 511295212Sjceel if (!strcmp(key, "discovery-filter")) { 512295212Sjceel if (obj->type != UCL_STRING) { 513295212Sjceel log_warnx("\"discovery-filter\" property of " 514295212Sjceel "portal-group \"%s\" is not a string", 515295212Sjceel portal_group->pg_name); 516295212Sjceel return (1); 517295212Sjceel } 518295212Sjceel 519295212Sjceel if (portal_group_set_filter(portal_group, 520295212Sjceel ucl_object_tostring(obj)) != 0) 521295212Sjceel return (1); 522295212Sjceel } 523295212Sjceel 524295212Sjceel if (!strcmp(key, "listen")) { 525295212Sjceel if (obj->type == UCL_STRING) { 526295212Sjceel if (portal_group_add_listen(portal_group, 527295212Sjceel ucl_object_tostring(obj), false) != 0) 528295212Sjceel return (1); 529295212Sjceel } else if (obj->type == UCL_ARRAY) { 530295212Sjceel while ((tmp = ucl_iterate_object(obj, &it2, 531295212Sjceel true))) { 532295212Sjceel if (portal_group_add_listen( 533295212Sjceel portal_group, 534295212Sjceel ucl_object_tostring(tmp), 535295212Sjceel false) != 0) 536295212Sjceel return (1); 537295212Sjceel } 538295212Sjceel } else { 539295212Sjceel log_warnx("\"listen\" property of " 540295212Sjceel "portal-group \"%s\" is not a string", 541295212Sjceel portal_group->pg_name); 542295212Sjceel return (1); 543295212Sjceel } 544295212Sjceel } 545295212Sjceel 546295212Sjceel if (!strcmp(key, "listen-iser")) { 547295212Sjceel if (obj->type == UCL_STRING) { 548295212Sjceel if (portal_group_add_listen(portal_group, 549295212Sjceel ucl_object_tostring(obj), true) != 0) 550295212Sjceel return (1); 551295212Sjceel } else if (obj->type == UCL_ARRAY) { 552295212Sjceel while ((tmp = ucl_iterate_object(obj, &it2, 553295212Sjceel true))) { 554295212Sjceel if (portal_group_add_listen( 555295212Sjceel portal_group, 556295212Sjceel ucl_object_tostring(tmp), 557295212Sjceel true) != 0) 558295212Sjceel return (1); 559295212Sjceel } 560295212Sjceel } else { 561295212Sjceel log_warnx("\"listen\" property of " 562295212Sjceel "portal-group \"%s\" is not a string", 563295212Sjceel portal_group->pg_name); 564295212Sjceel return (1); 565295212Sjceel } 566295212Sjceel } 567295212Sjceel 568295212Sjceel if (!strcmp(key, "redirect")) { 569295212Sjceel if (obj->type != UCL_STRING) { 570295212Sjceel log_warnx("\"listen\" property of " 571295212Sjceel "portal-group \"%s\" is not a string", 572295212Sjceel portal_group->pg_name); 573295212Sjceel return (1); 574295212Sjceel } 575295212Sjceel 576295212Sjceel if (portal_group_set_redirection(portal_group, 577295212Sjceel ucl_object_tostring(obj)) != 0) 578295212Sjceel return (1); 579295212Sjceel } 580295212Sjceel 581295212Sjceel if (!strcmp(key, "options")) { 582295212Sjceel if (obj->type != UCL_OBJECT) { 583295212Sjceel log_warnx("\"options\" property of portal group " 584295212Sjceel "\"%s\" is not an object", portal_group->pg_name); 585295212Sjceel return (1); 586295212Sjceel } 587295212Sjceel 588295212Sjceel while ((tmp = ucl_iterate_object(obj, &it2, 589295212Sjceel true))) { 590295212Sjceel option_new(&portal_group->pg_options, 591295212Sjceel ucl_object_key(tmp), 592295212Sjceel ucl_object_tostring_forced(tmp)); 593295212Sjceel } 594295212Sjceel } 595295212Sjceel } 596295212Sjceel 597295212Sjceel return (0); 598295212Sjceel} 599295212Sjceel 600295212Sjceelstatic int 601295212Sjceeluclparse_target(const char *name, const ucl_object_t *top) 602295212Sjceel{ 603295212Sjceel struct target *target; 604295212Sjceel ucl_object_iter_t it = NULL, it2 = NULL; 605295212Sjceel const ucl_object_t *obj = NULL, *tmp = NULL; 606295212Sjceel const char *key; 607295212Sjceel 608295212Sjceel target = target_new(conf, name); 609295212Sjceel 610295212Sjceel while ((obj = ucl_iterate_object(top, &it, true))) { 611295212Sjceel key = ucl_object_key(obj); 612295212Sjceel 613295212Sjceel if (!strcmp(key, "alias")) { 614295212Sjceel if (obj->type != UCL_STRING) { 615295212Sjceel log_warnx("\"alias\" property of target " 616295212Sjceel "\"%s\" is not a string", target->t_name); 617295212Sjceel return (1); 618295212Sjceel } 619295212Sjceel 620295212Sjceel target->t_alias = strdup(ucl_object_tostring(obj)); 621295212Sjceel } 622295212Sjceel 623295212Sjceel if (!strcmp(key, "auth-group")) { 624295212Sjceel if (target->t_auth_group != NULL) { 625295212Sjceel if (target->t_auth_group->ag_name != NULL) 626295212Sjceel log_warnx("auth-group for target \"%s\" " 627295212Sjceel "specified more than once", 628295212Sjceel target->t_name); 629295212Sjceel else 630295212Sjceel log_warnx("cannot use both auth-group " 631295212Sjceel "and explicit authorisations for " 632295212Sjceel "target \"%s\"", target->t_name); 633295212Sjceel return (1); 634295212Sjceel } 635295212Sjceel target->t_auth_group = auth_group_find(conf, 636295212Sjceel ucl_object_tostring(obj)); 637295212Sjceel if (target->t_auth_group == NULL) { 638295212Sjceel log_warnx("unknown auth-group \"%s\" for target " 639295212Sjceel "\"%s\"", ucl_object_tostring(obj), 640295212Sjceel target->t_name); 641295212Sjceel return (1); 642295212Sjceel } 643295212Sjceel } 644295212Sjceel 645295212Sjceel if (!strcmp(key, "auth-type")) { 646295212Sjceel int error; 647295212Sjceel 648295212Sjceel if (target->t_auth_group != NULL) { 649295212Sjceel if (target->t_auth_group->ag_name != NULL) { 650295212Sjceel log_warnx("cannot use both auth-group and " 651295212Sjceel "auth-type for target \"%s\"", 652295212Sjceel target->t_name); 653295212Sjceel return (1); 654295212Sjceel } 655295212Sjceel } else { 656295212Sjceel target->t_auth_group = auth_group_new(conf, NULL); 657295212Sjceel if (target->t_auth_group == NULL) 658295212Sjceel return (1); 659295212Sjceel 660295212Sjceel target->t_auth_group->ag_target = target; 661295212Sjceel } 662295212Sjceel error = auth_group_set_type(target->t_auth_group, 663295212Sjceel ucl_object_tostring(obj)); 664295212Sjceel if (error != 0) 665295212Sjceel return (1); 666295212Sjceel } 667295212Sjceel 668295212Sjceel if (!strcmp(key, "chap")) { 669295212Sjceel if (uclparse_chap(target->t_auth_group, obj) != 0) 670295212Sjceel return (1); 671295212Sjceel } 672295212Sjceel 673295212Sjceel if (!strcmp(key, "chap-mutual")) { 674295212Sjceel if (uclparse_chap_mutual(target->t_auth_group, obj) != 0) 675295212Sjceel return (1); 676295212Sjceel } 677295212Sjceel 678295212Sjceel if (!strcmp(key, "initiator-name")) { 679295212Sjceel const struct auth_name *an; 680295212Sjceel 681295212Sjceel if (target->t_auth_group != NULL) { 682295212Sjceel if (target->t_auth_group->ag_name != NULL) { 683295212Sjceel log_warnx("cannot use both auth-group and " 684295212Sjceel "initiator-name for target \"%s\"", 685295212Sjceel target->t_name); 686295212Sjceel return (1); 687295212Sjceel } 688295212Sjceel } else { 689295212Sjceel target->t_auth_group = auth_group_new(conf, NULL); 690295212Sjceel if (target->t_auth_group == NULL) 691295212Sjceel return (1); 692295212Sjceel 693295212Sjceel target->t_auth_group->ag_target = target; 694295212Sjceel } 695295212Sjceel an = auth_name_new(target->t_auth_group, 696295212Sjceel ucl_object_tostring(obj)); 697295212Sjceel if (an == NULL) 698295212Sjceel return (1); 699295212Sjceel } 700295212Sjceel 701295212Sjceel if (!strcmp(key, "initiator-portal")) { 702295212Sjceel const struct auth_portal *ap; 703295212Sjceel 704295212Sjceel if (target->t_auth_group != NULL) { 705295212Sjceel if (target->t_auth_group->ag_name != NULL) { 706295212Sjceel log_warnx("cannot use both auth-group and " 707295212Sjceel "initiator-portal for target \"%s\"", 708295212Sjceel target->t_name); 709295212Sjceel return (1); 710295212Sjceel } 711295212Sjceel } else { 712295212Sjceel target->t_auth_group = auth_group_new(conf, NULL); 713295212Sjceel if (target->t_auth_group == NULL) 714295212Sjceel return (1); 715295212Sjceel 716295212Sjceel target->t_auth_group->ag_target = target; 717295212Sjceel } 718295212Sjceel ap = auth_portal_new(target->t_auth_group, 719295212Sjceel ucl_object_tostring(obj)); 720295212Sjceel if (ap == NULL) 721295212Sjceel return (1); 722295212Sjceel } 723295212Sjceel 724295212Sjceel if (!strcmp(key, "portal-group")) { 725295212Sjceel if (obj->type == UCL_OBJECT) { 726295212Sjceel if (uclparse_target_portal_group(target, obj) != 0) 727295212Sjceel return (1); 728295212Sjceel } 729295212Sjceel 730295212Sjceel if (obj->type == UCL_ARRAY) { 731295212Sjceel while ((tmp = ucl_iterate_object(obj, &it2, 732295212Sjceel true))) { 733295212Sjceel if (uclparse_target_portal_group(target, 734295212Sjceel tmp) != 0) 735295212Sjceel return (1); 736295212Sjceel } 737295212Sjceel } 738295212Sjceel } 739295212Sjceel 740295212Sjceel if (!strcmp(key, "port")) { 741295212Sjceel struct pport *pp; 742295212Sjceel struct port *tp; 743295212Sjceel const char *value = ucl_object_tostring(obj); 744295212Sjceel 745295212Sjceel pp = pport_find(conf, value); 746295212Sjceel if (pp == NULL) { 747295212Sjceel log_warnx("unknown port \"%s\" for target \"%s\"", 748295212Sjceel value, target->t_name); 749295212Sjceel return (1); 750295212Sjceel } 751295212Sjceel if (!TAILQ_EMPTY(&pp->pp_ports)) { 752295212Sjceel log_warnx("can't link port \"%s\" to target \"%s\", " 753295212Sjceel "port already linked to some target", 754295212Sjceel value, target->t_name); 755295212Sjceel return (1); 756295212Sjceel } 757295212Sjceel tp = port_new_pp(conf, target, pp); 758295212Sjceel if (tp == NULL) { 759295212Sjceel log_warnx("can't link port \"%s\" to target \"%s\"", 760295212Sjceel value, target->t_name); 761295212Sjceel return (1); 762295212Sjceel } 763295212Sjceel } 764295212Sjceel 765295212Sjceel if (!strcmp(key, "redirect")) { 766295212Sjceel if (obj->type != UCL_STRING) { 767295212Sjceel log_warnx("\"redirect\" property of target " 768295212Sjceel "\"%s\" is not a string", target->t_name); 769295212Sjceel return (1); 770295212Sjceel } 771295212Sjceel 772295212Sjceel if (target_set_redirection(target, 773295212Sjceel ucl_object_tostring(obj)) != 0) 774295212Sjceel return (1); 775295212Sjceel } 776295212Sjceel 777295212Sjceel if (!strcmp(key, "lun")) { 778295212Sjceel while ((tmp = ucl_iterate_object(obj, &it2, true))) { 779295212Sjceel if (uclparse_target_lun(target, tmp) != 0) 780295212Sjceel return (1); 781295212Sjceel } 782295212Sjceel } 783295212Sjceel } 784295212Sjceel 785295212Sjceel return (0); 786295212Sjceel} 787295212Sjceel 788295212Sjceelstatic int 789295212Sjceeluclparse_lun(const char *name, const ucl_object_t *top) 790295212Sjceel{ 791295212Sjceel struct lun *lun; 792295212Sjceel ucl_object_iter_t it = NULL, child_it = NULL; 793295212Sjceel const ucl_object_t *obj = NULL, *child = NULL; 794295212Sjceel const char *key; 795295212Sjceel 796295212Sjceel lun = lun_new(conf, name); 797295212Sjceel 798295212Sjceel while ((obj = ucl_iterate_object(top, &it, true))) { 799295212Sjceel key = ucl_object_key(obj); 800295212Sjceel 801295212Sjceel if (!strcmp(key, "backend")) { 802295212Sjceel if (obj->type != UCL_STRING) { 803295212Sjceel log_warnx("\"backend\" property of lun " 804295212Sjceel "\"%s\" is not a string", 805295212Sjceel lun->l_name); 806295212Sjceel return (1); 807295212Sjceel } 808295212Sjceel 809295212Sjceel lun_set_backend(lun, ucl_object_tostring(obj)); 810295212Sjceel } 811295212Sjceel 812295212Sjceel if (!strcmp(key, "blocksize")) { 813295212Sjceel if (obj->type != UCL_INT) { 814295212Sjceel log_warnx("\"blocksize\" property of lun " 815295212Sjceel "\"%s\" is not an integer", lun->l_name); 816295212Sjceel return (1); 817295212Sjceel } 818295212Sjceel 819295212Sjceel lun_set_blocksize(lun, ucl_object_toint(obj)); 820295212Sjceel } 821295212Sjceel 822295212Sjceel if (!strcmp(key, "device-id")) { 823295212Sjceel if (obj->type != UCL_STRING) { 824295212Sjceel log_warnx("\"device-id\" property of lun " 825295212Sjceel "\"%s\" is not an integer", lun->l_name); 826295212Sjceel return (1); 827295212Sjceel } 828295212Sjceel 829295212Sjceel lun_set_device_id(lun, ucl_object_tostring(obj)); 830295212Sjceel } 831295212Sjceel 832295212Sjceel if (!strcmp(key, "options")) { 833295212Sjceel if (obj->type != UCL_OBJECT) { 834295212Sjceel log_warnx("\"options\" property of lun " 835295212Sjceel "\"%s\" is not an object", lun->l_name); 836295212Sjceel return (1); 837295212Sjceel } 838295212Sjceel 839295212Sjceel while ((child = ucl_iterate_object(obj, &child_it, 840295212Sjceel true))) { 841295212Sjceel option_new(&lun->l_options, 842295212Sjceel ucl_object_key(child), 843295212Sjceel ucl_object_tostring_forced(child)); 844295212Sjceel } 845295212Sjceel } 846295212Sjceel 847295212Sjceel if (!strcmp(key, "path")) { 848295212Sjceel if (obj->type != UCL_STRING) { 849295212Sjceel log_warnx("\"path\" property of lun " 850295212Sjceel "\"%s\" is not a string", lun->l_name); 851295212Sjceel return (1); 852295212Sjceel } 853295212Sjceel 854295212Sjceel lun_set_path(lun, ucl_object_tostring(obj)); 855295212Sjceel } 856295212Sjceel 857295212Sjceel if (!strcmp(key, "serial")) { 858295212Sjceel if (obj->type != UCL_STRING) { 859295212Sjceel log_warnx("\"serial\" property of lun " 860295212Sjceel "\"%s\" is not a string", lun->l_name); 861295212Sjceel return (1); 862295212Sjceel } 863295212Sjceel 864295212Sjceel lun_set_serial(lun, ucl_object_tostring(obj)); 865295212Sjceel } 866295212Sjceel 867295212Sjceel if (!strcmp(key, "size")) { 868295212Sjceel if (obj->type != UCL_INT) { 869295212Sjceel log_warnx("\"size\" property of lun " 870295212Sjceel "\"%s\" is not an integer", lun->l_name); 871295212Sjceel return (1); 872295212Sjceel } 873295212Sjceel 874295212Sjceel lun_set_size(lun, ucl_object_toint(obj)); 875295212Sjceel } 876295212Sjceel } 877295212Sjceel 878295212Sjceel return (0); 879295212Sjceel} 880295212Sjceel 881295212Sjceelint 882295212Sjceeluclparse_conf(struct conf *newconf, const char *path) 883295212Sjceel{ 884295212Sjceel struct ucl_parser *parser; 885295212Sjceel int error; 886295212Sjceel 887295212Sjceel conf = newconf; 888295212Sjceel parser = ucl_parser_new(0); 889295212Sjceel 890296808Sjceel if (!ucl_parser_add_file(parser, path)) { 891295212Sjceel log_warn("unable to parse configuration file %s: %s", path, 892295212Sjceel ucl_parser_get_error(parser)); 893295212Sjceel return (1); 894295212Sjceel } 895295212Sjceel 896295212Sjceel error = uclparse_toplevel(ucl_parser_get_object(parser)); 897295212Sjceel 898295212Sjceel return (error); 899295212Sjceel} 900