ctld.c revision 279006
11592Srgrimes/*- 21592Srgrimes * Copyright (c) 2012 The FreeBSD Foundation 31592Srgrimes * All rights reserved. 41592Srgrimes * 51592Srgrimes * This software was developed by Edward Tomasz Napierala under sponsorship 61592Srgrimes * from the FreeBSD Foundation. 71592Srgrimes * 81592Srgrimes * Redistribution and use in source and binary forms, with or without 91592Srgrimes * modification, are permitted provided that the following conditions 101592Srgrimes * are met: 111592Srgrimes * 1. Redistributions of source code must retain the above copyright 121592Srgrimes * notice, this list of conditions and the following disclaimer. 131592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141592Srgrimes * notice, this list of conditions and the following disclaimer in the 151592Srgrimes * documentation and/or other materials provided with the distribution. 161592Srgrimes * 171592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 181592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21262136Sbrueffer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271592Srgrimes * SUCH DAMAGE. 281592Srgrimes * 291592Srgrimes */ 301592Srgrimes 311592Srgrimes#include <sys/cdefs.h> 321592Srgrimes__FBSDID("$FreeBSD: stable/10/usr.sbin/ctld/ctld.c 279006 2015-02-19 14:52:01Z mav $"); 331592Srgrimes 341592Srgrimes#include <sys/types.h> 351592Srgrimes#include <sys/time.h> 361592Srgrimes#include <sys/socket.h> 3727077Ssteve#include <sys/wait.h> 381592Srgrimes#include <netinet/in.h> 3927077Ssteve#include <arpa/inet.h> 401592Srgrimes#include <assert.h> 411592Srgrimes#include <ctype.h> 421592Srgrimes#include <errno.h> 431592Srgrimes#include <netdb.h> 4427077Ssteve#include <signal.h> 451592Srgrimes#include <stdbool.h> 461592Srgrimes#include <stdio.h> 471592Srgrimes#include <stdint.h> 481592Srgrimes#include <stdlib.h> 491592Srgrimes#include <string.h> 5031386Scharnier#include <unistd.h> 5127077Ssteve 5231386Scharnier#include "ctld.h" 531592Srgrimes#include "isns.h" 54216583Scharnier 55216583Scharnierbool proxy_mode = false; 561592Srgrimes 571592Srgrimesstatic volatile bool sighup_received = false; 581592Srgrimesstatic volatile bool sigterm_received = false; 591592Srgrimesstatic volatile bool sigalrm_received = false; 6027077Ssteve 611592Srgrimesstatic int nchildren = 0; 621592Srgrimesstatic uint16_t last_portal_group_tag = 0; 631592Srgrimes 641592Srgrimesstatic void 651592Srgrimesusage(void) 661592Srgrimes{ 671592Srgrimes 681592Srgrimes fprintf(stderr, "usage: ctld [-d][-f config-file]\n"); 691592Srgrimes exit(1); 701592Srgrimes} 7190377Simp 721592Srgrimeschar * 731592Srgrimeschecked_strdup(const char *s) 7490377Simp{ 751592Srgrimes char *c; 761592Srgrimes 771592Srgrimes c = strdup(s); 781592Srgrimes if (c == NULL) 791592Srgrimes log_err(1, "strdup"); 801592Srgrimes return (c); 811592Srgrimes} 821592Srgrimes 831592Srgrimesstruct conf * 841592Srgrimesconf_new(void) 851592Srgrimes{ 861592Srgrimes struct conf *conf; 871592Srgrimes 881592Srgrimes conf = calloc(1, sizeof(*conf)); 891592Srgrimes if (conf == NULL) 901592Srgrimes log_err(1, "calloc"); 911592Srgrimes TAILQ_INIT(&conf->conf_luns); 921592Srgrimes TAILQ_INIT(&conf->conf_targets); 931592Srgrimes TAILQ_INIT(&conf->conf_auth_groups); 941592Srgrimes TAILQ_INIT(&conf->conf_ports); 951592Srgrimes TAILQ_INIT(&conf->conf_portal_groups); 9624349Simp TAILQ_INIT(&conf->conf_isns); 971592Srgrimes 981592Srgrimes conf->conf_isns_period = 900; 991592Srgrimes conf->conf_isns_timeout = 5; 1001592Srgrimes conf->conf_debug = 0; 1011592Srgrimes conf->conf_timeout = 60; 1021592Srgrimes conf->conf_maxproc = 30; 1031592Srgrimes 1041592Srgrimes return (conf); 1051592Srgrimes} 1061592Srgrimes 10731386Scharniervoid 10831386Scharnierconf_delete(struct conf *conf) 1091592Srgrimes{ 1101592Srgrimes struct lun *lun, *ltmp; 1111592Srgrimes struct target *targ, *tmp; 1121592Srgrimes struct auth_group *ag, *cagtmp; 1131592Srgrimes struct portal_group *pg, *cpgtmp; 11431386Scharnier struct isns *is, *istmp; 11527077Ssteve 1161592Srgrimes assert(conf->conf_pidfh == NULL); 1171592Srgrimes 1181592Srgrimes TAILQ_FOREACH_SAFE(lun, &conf->conf_luns, l_next, ltmp) 1191592Srgrimes lun_delete(lun); 1201592Srgrimes TAILQ_FOREACH_SAFE(targ, &conf->conf_targets, t_next, tmp) 1211592Srgrimes target_delete(targ); 1221592Srgrimes TAILQ_FOREACH_SAFE(ag, &conf->conf_auth_groups, ag_next, cagtmp) 1231592Srgrimes auth_group_delete(ag); 1241592Srgrimes TAILQ_FOREACH_SAFE(pg, &conf->conf_portal_groups, pg_next, cpgtmp) 1251592Srgrimes portal_group_delete(pg); 1261592Srgrimes TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp) 12727077Ssteve isns_delete(is); 1281592Srgrimes assert(TAILQ_EMPTY(&conf->conf_ports)); 12927077Ssteve free(conf->conf_pidfile_path); 13027077Ssteve free(conf); 1311592Srgrimes} 1321592Srgrimes 1331592Srgrimesstatic struct auth * 1341592Srgrimesauth_new(struct auth_group *ag) 1351592Srgrimes{ 13631386Scharnier struct auth *auth; 1371592Srgrimes 1381592Srgrimes auth = calloc(1, sizeof(*auth)); 1391592Srgrimes if (auth == NULL) 1401592Srgrimes log_err(1, "calloc"); 1411592Srgrimes auth->a_auth_group = ag; 1421592Srgrimes TAILQ_INSERT_TAIL(&ag->ag_auths, auth, a_next); 1431592Srgrimes return (auth); 1441592Srgrimes} 1451592Srgrimes 1461592Srgrimesstatic void 1471592Srgrimesauth_delete(struct auth *auth) 1481592Srgrimes{ 1491592Srgrimes TAILQ_REMOVE(&auth->a_auth_group->ag_auths, auth, a_next); 150134102Smaxim 151134102Smaxim free(auth->a_user); 15268894Skris free(auth->a_secret); 15368894Skris free(auth->a_mutual_user); 1541592Srgrimes free(auth->a_mutual_secret); 1551592Srgrimes free(auth); 1561592Srgrimes} 1571592Srgrimes 1581592Srgrimesconst struct auth * 1591592Srgrimesauth_find(const struct auth_group *ag, const char *user) 1601592Srgrimes{ 1611592Srgrimes const struct auth *auth; 1621592Srgrimes 1631592Srgrimes TAILQ_FOREACH(auth, &ag->ag_auths, a_next) { 1641592Srgrimes if (strcmp(auth->a_user, user) == 0) 1651592Srgrimes return (auth); 1661592Srgrimes } 16745422Sbrian 1681592Srgrimes return (NULL); 1691592Srgrimes} 1701592Srgrimes 17145422Sbrianstatic void 1721592Srgrimesauth_check_secret_length(struct auth *auth) 1731592Srgrimes{ 1741592Srgrimes size_t len; 1751592Srgrimes 1761592Srgrimes len = strlen(auth->a_secret); 1771592Srgrimes if (len > 16) { 1781592Srgrimes if (auth->a_auth_group->ag_name != NULL) 1791592Srgrimes log_warnx("secret for user \"%s\", auth-group \"%s\", " 1801592Srgrimes "is too long; it should be at most 16 characters " 1811592Srgrimes "long", auth->a_user, auth->a_auth_group->ag_name); 18227077Ssteve else 1831592Srgrimes log_warnx("secret for user \"%s\", target \"%s\", " 1841592Srgrimes "is too long; it should be at most 16 characters " 1851592Srgrimes "long", auth->a_user, 1861592Srgrimes auth->a_auth_group->ag_target->t_name); 1871592Srgrimes } 1881592Srgrimes if (len < 12) { 1891592Srgrimes if (auth->a_auth_group->ag_name != NULL) 1901592Srgrimes log_warnx("secret for user \"%s\", auth-group \"%s\", " 1911592Srgrimes "is too short; it should be at least 12 characters " 1921592Srgrimes "long", auth->a_user, 1931592Srgrimes auth->a_auth_group->ag_name); 1941592Srgrimes else 1951592Srgrimes log_warnx("secret for user \"%s\", target \"%s\", " 1961592Srgrimes "is too short; it should be at least 16 characters " 1971592Srgrimes "long", auth->a_user, 1981592Srgrimes auth->a_auth_group->ag_target->t_name); 1991592Srgrimes } 2001592Srgrimes 2011592Srgrimes if (auth->a_mutual_secret != NULL) { 2021592Srgrimes len = strlen(auth->a_secret); 2031592Srgrimes if (len > 16) { 2041592Srgrimes if (auth->a_auth_group->ag_name != NULL) 2051592Srgrimes log_warnx("mutual secret for user \"%s\", " 2061592Srgrimes "auth-group \"%s\", is too long; it should " 2071592Srgrimes "be at most 16 characters long", 2081592Srgrimes auth->a_user, auth->a_auth_group->ag_name); 2091592Srgrimes else 2101592Srgrimes log_warnx("mutual secret for user \"%s\", " 2111592Srgrimes "target \"%s\", is too long; it should " 2121592Srgrimes "be at most 16 characters long", 2131592Srgrimes auth->a_user, 2141592Srgrimes auth->a_auth_group->ag_target->t_name); 2151592Srgrimes } 2161592Srgrimes if (len < 12) { 2171592Srgrimes if (auth->a_auth_group->ag_name != NULL) 2181592Srgrimes log_warnx("mutual secret for user \"%s\", " 2191592Srgrimes "auth-group \"%s\", is too short; it " 2201592Srgrimes "should be at least 12 characters long", 2211592Srgrimes auth->a_user, auth->a_auth_group->ag_name); 2221592Srgrimes else 2231592Srgrimes log_warnx("mutual secret for user \"%s\", " 2241592Srgrimes "target \"%s\", is too short; it should be " 2251592Srgrimes "at least 16 characters long", 2261592Srgrimes auth->a_user, 2271592Srgrimes auth->a_auth_group->ag_target->t_name); 2281592Srgrimes } 2291592Srgrimes } 230229780Suqs} 23127077Ssteve 2321592Srgrimesconst struct auth * 2331592Srgrimesauth_new_chap(struct auth_group *ag, const char *user, 2341592Srgrimes const char *secret) 23527077Ssteve{ 2361592Srgrimes struct auth *auth; 2371592Srgrimes 2381592Srgrimes if (ag->ag_type == AG_TYPE_UNKNOWN) 2391592Srgrimes ag->ag_type = AG_TYPE_CHAP; 2401592Srgrimes if (ag->ag_type != AG_TYPE_CHAP) { 2411592Srgrimes if (ag->ag_name != NULL) 2421592Srgrimes log_warnx("cannot mix \"chap\" authentication with " 2431592Srgrimes "other types for auth-group \"%s\"", ag->ag_name); 2441592Srgrimes else 2451592Srgrimes log_warnx("cannot mix \"chap\" authentication with " 2461592Srgrimes "other types for target \"%s\"", 2471592Srgrimes ag->ag_target->t_name); 2481592Srgrimes return (NULL); 2491592Srgrimes } 2501592Srgrimes 2511592Srgrimes auth = auth_new(ag); 2521592Srgrimes auth->a_user = checked_strdup(user); 2531592Srgrimes auth->a_secret = checked_strdup(secret); 2541592Srgrimes 2551592Srgrimes auth_check_secret_length(auth); 2561592Srgrimes 2571592Srgrimes return (auth); 2581592Srgrimes} 2591592Srgrimes 2601592Srgrimesconst struct auth * 2611592Srgrimesauth_new_chap_mutual(struct auth_group *ag, const char *user, 2621592Srgrimes const char *secret, const char *user2, const char *secret2) 2631592Srgrimes{ 2641592Srgrimes struct auth *auth; 2651592Srgrimes 2661592Srgrimes if (ag->ag_type == AG_TYPE_UNKNOWN) 2671592Srgrimes ag->ag_type = AG_TYPE_CHAP_MUTUAL; 2681592Srgrimes if (ag->ag_type != AG_TYPE_CHAP_MUTUAL) { 2691592Srgrimes if (ag->ag_name != NULL) 2701592Srgrimes log_warnx("cannot mix \"chap-mutual\" authentication " 2711592Srgrimes "with other types for auth-group \"%s\"", 2721592Srgrimes ag->ag_name); 2731592Srgrimes else 2741592Srgrimes log_warnx("cannot mix \"chap-mutual\" authentication " 2751592Srgrimes "with other types for target \"%s\"", 2761592Srgrimes ag->ag_target->t_name); 2771592Srgrimes return (NULL); 2781592Srgrimes } 2791592Srgrimes 2801592Srgrimes auth = auth_new(ag); 2811592Srgrimes auth->a_user = checked_strdup(user); 2821592Srgrimes auth->a_secret = checked_strdup(secret); 2831592Srgrimes auth->a_mutual_user = checked_strdup(user2); 2841592Srgrimes auth->a_mutual_secret = checked_strdup(secret2); 2851592Srgrimes 28631386Scharnier auth_check_secret_length(auth); 28790377Simp 28831386Scharnier return (auth); 28931386Scharnier} 29031386Scharnier 29131386Scharnierconst struct auth_name * 29231386Scharnierauth_name_new(struct auth_group *ag, const char *name) 2931592Srgrimes{ 2941592Srgrimes struct auth_name *an; 2951592Srgrimes 2961592Srgrimes an = calloc(1, sizeof(*an)); 2971592Srgrimes if (an == NULL) 2981592Srgrimes log_err(1, "calloc"); 2991592Srgrimes an->an_auth_group = ag; 3001592Srgrimes an->an_initator_name = checked_strdup(name); 3011592Srgrimes TAILQ_INSERT_TAIL(&ag->ag_names, an, an_next); 3021592Srgrimes return (an); 3031592Srgrimes} 3041592Srgrimes 3051592Srgrimesstatic void 30690377Simpauth_name_delete(struct auth_name *an) 3071592Srgrimes{ 30827079Ssteve TAILQ_REMOVE(&an->an_auth_group->ag_names, an, an_next); 309239991Sed 3101592Srgrimes free(an->an_initator_name); 3111592Srgrimes free(an); 3121592Srgrimes} 3131592Srgrimes 3141592Srgrimesbool 315239991Sedauth_name_defined(const struct auth_group *ag) 3161592Srgrimes{ 317239991Sed if (TAILQ_EMPTY(&ag->ag_names)) 3181592Srgrimes return (false); 3191592Srgrimes return (true); 3201592Srgrimes} 3211592Srgrimes 3221592Srgrimesconst struct auth_name * 3231592Srgrimesauth_name_find(const struct auth_group *ag, const char *name) 3241592Srgrimes{ 3251592Srgrimes const struct auth_name *auth_name; 3261592Srgrimes 3271592Srgrimes TAILQ_FOREACH(auth_name, &ag->ag_names, an_next) { 3288870Srgrimes if (strcmp(auth_name->an_initator_name, name) == 0) 3291592Srgrimes return (auth_name); 3301592Srgrimes } 3311592Srgrimes 3321592Srgrimes return (NULL); 3331592Srgrimes} 3341592Srgrimes 3351592Srgrimesint 3361592Srgrimesauth_name_check(const struct auth_group *ag, const char *initiator_name) 3371592Srgrimes{ 3381592Srgrimes if (!auth_name_defined(ag)) 3391592Srgrimes return (0); 3401592Srgrimes 3411592Srgrimes if (auth_name_find(ag, initiator_name) == NULL) 34290377Simp return (1); 3431592Srgrimes 34427079Ssteve return (0); 3451592Srgrimes} 3461592Srgrimes 3471592Srgrimesconst struct auth_portal * 3481592Srgrimesauth_portal_new(struct auth_group *ag, const char *portal) 3491592Srgrimes{ 3501592Srgrimes struct auth_portal *ap; 3511592Srgrimes char *net, *mask, *str, *tmp; 3521592Srgrimes int len, dm, m; 3531592Srgrimes 3541592Srgrimes ap = calloc(1, sizeof(*ap)); 3551592Srgrimes if (ap == NULL) 3561592Srgrimes log_err(1, "calloc"); 3571592Srgrimes ap->ap_auth_group = ag; 3581592Srgrimes ap->ap_initator_portal = checked_strdup(portal); 3591592Srgrimes mask = str = checked_strdup(portal); 3601592Srgrimes net = strsep(&mask, "/"); 3611592Srgrimes if (net[0] == '[') 3621592Srgrimes net++; 3631592Srgrimes len = strlen(net); 3641592Srgrimes if (len == 0) 3651592Srgrimes goto error; 3661592Srgrimes if (net[len - 1] == ']') 36790377Simp net[len - 1] = 0; 3681592Srgrimes if (strchr(net, ':') != NULL) { 3691592Srgrimes struct sockaddr_in6 *sin6 = 3701592Srgrimes (struct sockaddr_in6 *)&ap->ap_sa; 3711592Srgrimes 3721592Srgrimes sin6->sin6_len = sizeof(*sin6); 3731592Srgrimes sin6->sin6_family = AF_INET6; 3741592Srgrimes if (inet_pton(AF_INET6, net, &sin6->sin6_addr) <= 0) 3751592Srgrimes goto error; 3761592Srgrimes dm = 128; 3771592Srgrimes } else { 3781592Srgrimes struct sockaddr_in *sin = 3791592Srgrimes (struct sockaddr_in *)&ap->ap_sa; 3801592Srgrimes 3811592Srgrimes sin->sin_len = sizeof(*sin); 3821592Srgrimes sin->sin_family = AF_INET; 3831592Srgrimes if (inet_pton(AF_INET, net, &sin->sin_addr) <= 0) 3841592Srgrimes goto error; 3851592Srgrimes dm = 32; 3861592Srgrimes } 3871592Srgrimes if (mask != NULL) { 3881592Srgrimes m = strtol(mask, &tmp, 0); 3891592Srgrimes if (m < 0 || m > dm || tmp[0] != 0) 3901592Srgrimes goto error; 3911592Srgrimes } else 3921592Srgrimes m = dm; 3931592Srgrimes ap->ap_mask = m; 3941592Srgrimes free(str); 395216583Scharnier TAILQ_INSERT_TAIL(&ag->ag_portals, ap, ap_next); 3961592Srgrimes return (ap); 3971592Srgrimes 3981592Srgrimeserror: 3991592Srgrimes log_errx(1, "Incorrect initiator portal '%s'", portal); 4001592Srgrimes return (NULL); 4011592Srgrimes} 4021592Srgrimes 4031592Srgrimesstatic void 4041592Srgrimesauth_portal_delete(struct auth_portal *ap) 4051592Srgrimes{ 4061592Srgrimes TAILQ_REMOVE(&ap->ap_auth_group->ag_portals, ap, ap_next); 4071592Srgrimes 4081592Srgrimes free(ap->ap_initator_portal); 4091592Srgrimes free(ap); 4101592Srgrimes} 4111592Srgrimes 4121592Srgrimesbool 4131592Srgrimesauth_portal_defined(const struct auth_group *ag) 4141592Srgrimes{ 4151592Srgrimes if (TAILQ_EMPTY(&ag->ag_portals)) 4161592Srgrimes return (false); 4171592Srgrimes return (true); 4181592Srgrimes} 4191592Srgrimes 4201592Srgrimesconst struct auth_portal * 421216583Scharnierauth_portal_find(const struct auth_group *ag, const struct sockaddr_storage *ss) 4221592Srgrimes{ 4231592Srgrimes const struct auth_portal *ap; 4241592Srgrimes const uint8_t *a, *b; 4251592Srgrimes int i; 4261592Srgrimes uint8_t bmask; 4271592Srgrimes 4281592Srgrimes TAILQ_FOREACH(ap, &ag->ag_portals, ap_next) { 4291592Srgrimes if (ap->ap_sa.ss_family != ss->ss_family) 4301592Srgrimes continue; 4311592Srgrimes if (ss->ss_family == AF_INET) { 4321592Srgrimes a = (const uint8_t *) 4331592Srgrimes &((const struct sockaddr_in *)ss)->sin_addr; 4341592Srgrimes b = (const uint8_t *) 4351592Srgrimes &((const struct sockaddr_in *)&ap->ap_sa)->sin_addr; 4361592Srgrimes } else { 4371592Srgrimes a = (const uint8_t *) 4381592Srgrimes &((const struct sockaddr_in6 *)ss)->sin6_addr; 4391592Srgrimes b = (const uint8_t *) 4401592Srgrimes &((const struct sockaddr_in6 *)&ap->ap_sa)->sin6_addr; 4411592Srgrimes } 4421592Srgrimes for (i = 0; i < ap->ap_mask / 8; i++) { 443216583Scharnier if (a[i] != b[i]) 4441592Srgrimes goto next; 4451592Srgrimes } 4461592Srgrimes if (ap->ap_mask % 8) { 4471592Srgrimes bmask = 0xff << (8 - (ap->ap_mask % 8)); 4481592Srgrimes if ((a[i] & bmask) != (b[i] & bmask)) 4491592Srgrimes goto next; 450 } 451 return (ap); 452next: 453 ; 454 } 455 456 return (NULL); 457} 458 459int 460auth_portal_check(const struct auth_group *ag, const struct sockaddr_storage *sa) 461{ 462 463 if (!auth_portal_defined(ag)) 464 return (0); 465 466 if (auth_portal_find(ag, sa) == NULL) 467 return (1); 468 469 return (0); 470} 471 472struct auth_group * 473auth_group_new(struct conf *conf, const char *name) 474{ 475 struct auth_group *ag; 476 477 if (name != NULL) { 478 ag = auth_group_find(conf, name); 479 if (ag != NULL) { 480 log_warnx("duplicated auth-group \"%s\"", name); 481 return (NULL); 482 } 483 } 484 485 ag = calloc(1, sizeof(*ag)); 486 if (ag == NULL) 487 log_err(1, "calloc"); 488 if (name != NULL) 489 ag->ag_name = checked_strdup(name); 490 TAILQ_INIT(&ag->ag_auths); 491 TAILQ_INIT(&ag->ag_names); 492 TAILQ_INIT(&ag->ag_portals); 493 ag->ag_conf = conf; 494 TAILQ_INSERT_TAIL(&conf->conf_auth_groups, ag, ag_next); 495 496 return (ag); 497} 498 499void 500auth_group_delete(struct auth_group *ag) 501{ 502 struct auth *auth, *auth_tmp; 503 struct auth_name *auth_name, *auth_name_tmp; 504 struct auth_portal *auth_portal, *auth_portal_tmp; 505 506 TAILQ_REMOVE(&ag->ag_conf->conf_auth_groups, ag, ag_next); 507 508 TAILQ_FOREACH_SAFE(auth, &ag->ag_auths, a_next, auth_tmp) 509 auth_delete(auth); 510 TAILQ_FOREACH_SAFE(auth_name, &ag->ag_names, an_next, auth_name_tmp) 511 auth_name_delete(auth_name); 512 TAILQ_FOREACH_SAFE(auth_portal, &ag->ag_portals, ap_next, 513 auth_portal_tmp) 514 auth_portal_delete(auth_portal); 515 free(ag->ag_name); 516 free(ag); 517} 518 519struct auth_group * 520auth_group_find(const struct conf *conf, const char *name) 521{ 522 struct auth_group *ag; 523 524 TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) { 525 if (ag->ag_name != NULL && strcmp(ag->ag_name, name) == 0) 526 return (ag); 527 } 528 529 return (NULL); 530} 531 532int 533auth_group_set_type(struct auth_group *ag, const char *str) 534{ 535 int type; 536 537 if (strcmp(str, "none") == 0) { 538 type = AG_TYPE_NO_AUTHENTICATION; 539 } else if (strcmp(str, "deny") == 0) { 540 type = AG_TYPE_DENY; 541 } else if (strcmp(str, "chap") == 0) { 542 type = AG_TYPE_CHAP; 543 } else if (strcmp(str, "chap-mutual") == 0) { 544 type = AG_TYPE_CHAP_MUTUAL; 545 } else { 546 if (ag->ag_name != NULL) 547 log_warnx("invalid auth-type \"%s\" for auth-group " 548 "\"%s\"", str, ag->ag_name); 549 else 550 log_warnx("invalid auth-type \"%s\" for target " 551 "\"%s\"", str, ag->ag_target->t_name); 552 return (1); 553 } 554 555 if (ag->ag_type != AG_TYPE_UNKNOWN && ag->ag_type != type) { 556 if (ag->ag_name != NULL) { 557 log_warnx("cannot set auth-type to \"%s\" for " 558 "auth-group \"%s\"; already has a different " 559 "type", str, ag->ag_name); 560 } else { 561 log_warnx("cannot set auth-type to \"%s\" for target " 562 "\"%s\"; already has a different type", 563 str, ag->ag_target->t_name); 564 } 565 return (1); 566 } 567 568 ag->ag_type = type; 569 570 return (0); 571} 572 573static struct portal * 574portal_new(struct portal_group *pg) 575{ 576 struct portal *portal; 577 578 portal = calloc(1, sizeof(*portal)); 579 if (portal == NULL) 580 log_err(1, "calloc"); 581 TAILQ_INIT(&portal->p_targets); 582 portal->p_portal_group = pg; 583 TAILQ_INSERT_TAIL(&pg->pg_portals, portal, p_next); 584 return (portal); 585} 586 587static void 588portal_delete(struct portal *portal) 589{ 590 591 TAILQ_REMOVE(&portal->p_portal_group->pg_portals, portal, p_next); 592 if (portal->p_ai != NULL) 593 freeaddrinfo(portal->p_ai); 594 free(portal->p_listen); 595 free(portal); 596} 597 598struct portal_group * 599portal_group_new(struct conf *conf, const char *name) 600{ 601 struct portal_group *pg; 602 603 pg = portal_group_find(conf, name); 604 if (pg != NULL) { 605 log_warnx("duplicated portal-group \"%s\"", name); 606 return (NULL); 607 } 608 609 pg = calloc(1, sizeof(*pg)); 610 if (pg == NULL) 611 log_err(1, "calloc"); 612 pg->pg_name = checked_strdup(name); 613 TAILQ_INIT(&pg->pg_portals); 614 TAILQ_INIT(&pg->pg_ports); 615 pg->pg_conf = conf; 616 pg->pg_tag = 0; /* Assigned later in conf_apply(). */ 617 TAILQ_INSERT_TAIL(&conf->conf_portal_groups, pg, pg_next); 618 619 return (pg); 620} 621 622void 623portal_group_delete(struct portal_group *pg) 624{ 625 struct portal *portal, *tmp; 626 struct port *port, *tport; 627 628 TAILQ_FOREACH_SAFE(port, &pg->pg_ports, p_pgs, tport) 629 port_delete(port); 630 TAILQ_REMOVE(&pg->pg_conf->conf_portal_groups, pg, pg_next); 631 632 TAILQ_FOREACH_SAFE(portal, &pg->pg_portals, p_next, tmp) 633 portal_delete(portal); 634 free(pg->pg_name); 635 free(pg->pg_redirection); 636 free(pg); 637} 638 639struct portal_group * 640portal_group_find(const struct conf *conf, const char *name) 641{ 642 struct portal_group *pg; 643 644 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 645 if (strcmp(pg->pg_name, name) == 0) 646 return (pg); 647 } 648 649 return (NULL); 650} 651 652static int 653parse_addr_port(char *arg, const char *def_port, struct addrinfo **ai) 654{ 655 struct addrinfo hints; 656 char *str, *addr, *ch; 657 const char *port; 658 int error, colons = 0; 659 660 str = arg = strdup(arg); 661 if (arg[0] == '[') { 662 /* 663 * IPv6 address in square brackets, perhaps with port. 664 */ 665 arg++; 666 addr = strsep(&arg, "]"); 667 if (arg == NULL) 668 return (1); 669 if (arg[0] == '\0') { 670 port = def_port; 671 } else if (arg[0] == ':') { 672 port = arg + 1; 673 } else { 674 free(str); 675 return (1); 676 } 677 } else { 678 /* 679 * Either IPv6 address without brackets - and without 680 * a port - or IPv4 address. Just count the colons. 681 */ 682 for (ch = arg; *ch != '\0'; ch++) { 683 if (*ch == ':') 684 colons++; 685 } 686 if (colons > 1) { 687 addr = arg; 688 port = def_port; 689 } else { 690 addr = strsep(&arg, ":"); 691 if (arg == NULL) 692 port = def_port; 693 else 694 port = arg; 695 } 696 } 697 698 memset(&hints, 0, sizeof(hints)); 699 hints.ai_family = PF_UNSPEC; 700 hints.ai_socktype = SOCK_STREAM; 701 hints.ai_flags = AI_PASSIVE; 702 error = getaddrinfo(addr, port, &hints, ai); 703 free(str); 704 return ((error != 0) ? 1 : 0); 705} 706 707int 708portal_group_add_listen(struct portal_group *pg, const char *value, bool iser) 709{ 710 struct portal *portal; 711 712 portal = portal_new(pg); 713 portal->p_listen = checked_strdup(value); 714 portal->p_iser = iser; 715 716 if (parse_addr_port(portal->p_listen, "3260", &portal->p_ai)) { 717 log_warnx("invalid listen address %s", portal->p_listen); 718 portal_delete(portal); 719 return (1); 720 } 721 722 /* 723 * XXX: getaddrinfo(3) may return multiple addresses; we should turn 724 * those into multiple portals. 725 */ 726 727 return (0); 728} 729 730int 731isns_new(struct conf *conf, const char *addr) 732{ 733 struct isns *isns; 734 735 isns = calloc(1, sizeof(*isns)); 736 if (isns == NULL) 737 log_err(1, "calloc"); 738 isns->i_conf = conf; 739 TAILQ_INSERT_TAIL(&conf->conf_isns, isns, i_next); 740 isns->i_addr = checked_strdup(addr); 741 742 if (parse_addr_port(isns->i_addr, "3205", &isns->i_ai)) { 743 log_warnx("invalid iSNS address %s", isns->i_addr); 744 isns_delete(isns); 745 return (1); 746 } 747 748 /* 749 * XXX: getaddrinfo(3) may return multiple addresses; we should turn 750 * those into multiple servers. 751 */ 752 753 return (0); 754} 755 756void 757isns_delete(struct isns *isns) 758{ 759 760 TAILQ_REMOVE(&isns->i_conf->conf_isns, isns, i_next); 761 free(isns->i_addr); 762 if (isns->i_ai != NULL) 763 freeaddrinfo(isns->i_ai); 764 free(isns); 765} 766 767static int 768isns_do_connect(struct isns *isns) 769{ 770 int s; 771 772 s = socket(isns->i_ai->ai_family, isns->i_ai->ai_socktype, 773 isns->i_ai->ai_protocol); 774 if (s < 0) { 775 log_warn("socket(2) failed for %s", isns->i_addr); 776 return (-1); 777 } 778 if (connect(s, isns->i_ai->ai_addr, isns->i_ai->ai_addrlen)) { 779 log_warn("connect(2) failed for %s", isns->i_addr); 780 close(s); 781 return (-1); 782 } 783 return(s); 784} 785 786static int 787isns_do_register(struct isns *isns, int s, const char *hostname) 788{ 789 struct conf *conf = isns->i_conf; 790 struct target *target; 791 struct portal *portal; 792 struct portal_group *pg; 793 struct port *port; 794 struct isns_req *req; 795 int res = 0; 796 uint32_t error; 797 798 req = isns_req_create(ISNS_FUNC_DEVATTRREG, ISNS_FLAG_CLIENT); 799 isns_req_add_str(req, 32, TAILQ_FIRST(&conf->conf_targets)->t_name); 800 isns_req_add_delim(req); 801 isns_req_add_str(req, 1, hostname); 802 isns_req_add_32(req, 2, 2); /* 2 -- iSCSI */ 803 isns_req_add_32(req, 6, conf->conf_isns_period); 804 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 805 if (pg->pg_unassigned) 806 continue; 807 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) { 808 isns_req_add_addr(req, 16, portal->p_ai); 809 isns_req_add_port(req, 17, portal->p_ai); 810 } 811 } 812 TAILQ_FOREACH(target, &conf->conf_targets, t_next) { 813 isns_req_add_str(req, 32, target->t_name); 814 isns_req_add_32(req, 33, 1); /* 1 -- Target*/ 815 if (target->t_alias != NULL) 816 isns_req_add_str(req, 34, target->t_alias); 817 TAILQ_FOREACH(port, &target->t_ports, p_ts) { 818 if ((pg = port->p_portal_group) == NULL) 819 continue; 820 isns_req_add_32(req, 51, pg->pg_tag); 821 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) { 822 isns_req_add_addr(req, 49, portal->p_ai); 823 isns_req_add_port(req, 50, portal->p_ai); 824 } 825 } 826 } 827 res = isns_req_send(s, req); 828 if (res < 0) { 829 log_warn("send(2) failed for %s", isns->i_addr); 830 goto quit; 831 } 832 res = isns_req_receive(s, req); 833 if (res < 0) { 834 log_warn("receive(2) failed for %s", isns->i_addr); 835 goto quit; 836 } 837 error = isns_req_get_status(req); 838 if (error != 0) { 839 log_warnx("iSNS register error %d for %s", error, isns->i_addr); 840 res = -1; 841 } 842quit: 843 isns_req_free(req); 844 return (res); 845} 846 847static int 848isns_do_check(struct isns *isns, int s, const char *hostname) 849{ 850 struct conf *conf = isns->i_conf; 851 struct isns_req *req; 852 int res = 0; 853 uint32_t error; 854 855 req = isns_req_create(ISNS_FUNC_DEVATTRQRY, ISNS_FLAG_CLIENT); 856 isns_req_add_str(req, 32, TAILQ_FIRST(&conf->conf_targets)->t_name); 857 isns_req_add_str(req, 1, hostname); 858 isns_req_add_delim(req); 859 isns_req_add(req, 2, 0, NULL); 860 res = isns_req_send(s, req); 861 if (res < 0) { 862 log_warn("send(2) failed for %s", isns->i_addr); 863 goto quit; 864 } 865 res = isns_req_receive(s, req); 866 if (res < 0) { 867 log_warn("receive(2) failed for %s", isns->i_addr); 868 goto quit; 869 } 870 error = isns_req_get_status(req); 871 if (error != 0) { 872 log_warnx("iSNS check error %d for %s", error, isns->i_addr); 873 res = -1; 874 } 875quit: 876 isns_req_free(req); 877 return (res); 878} 879 880static int 881isns_do_deregister(struct isns *isns, int s, const char *hostname) 882{ 883 struct conf *conf = isns->i_conf; 884 struct isns_req *req; 885 int res = 0; 886 uint32_t error; 887 888 req = isns_req_create(ISNS_FUNC_DEVDEREG, ISNS_FLAG_CLIENT); 889 isns_req_add_str(req, 32, TAILQ_FIRST(&conf->conf_targets)->t_name); 890 isns_req_add_delim(req); 891 isns_req_add_str(req, 1, hostname); 892 res = isns_req_send(s, req); 893 if (res < 0) { 894 log_warn("send(2) failed for %s", isns->i_addr); 895 goto quit; 896 } 897 res = isns_req_receive(s, req); 898 if (res < 0) { 899 log_warn("receive(2) failed for %s", isns->i_addr); 900 goto quit; 901 } 902 error = isns_req_get_status(req); 903 if (error != 0) { 904 log_warnx("iSNS deregister error %d for %s", error, isns->i_addr); 905 res = -1; 906 } 907quit: 908 isns_req_free(req); 909 return (res); 910} 911 912void 913isns_register(struct isns *isns, struct isns *oldisns) 914{ 915 struct conf *conf = isns->i_conf; 916 int s; 917 char hostname[256]; 918 919 if (TAILQ_EMPTY(&conf->conf_targets) || 920 TAILQ_EMPTY(&conf->conf_portal_groups)) 921 return; 922 set_timeout(conf->conf_isns_timeout, false); 923 s = isns_do_connect(isns); 924 if (s < 0) { 925 set_timeout(0, false); 926 return; 927 } 928 gethostname(hostname, sizeof(hostname)); 929 930 if (oldisns == NULL || TAILQ_EMPTY(&oldisns->i_conf->conf_targets)) 931 oldisns = isns; 932 isns_do_deregister(oldisns, s, hostname); 933 isns_do_register(isns, s, hostname); 934 close(s); 935 set_timeout(0, false); 936} 937 938void 939isns_check(struct isns *isns) 940{ 941 struct conf *conf = isns->i_conf; 942 int s, res; 943 char hostname[256]; 944 945 if (TAILQ_EMPTY(&conf->conf_targets) || 946 TAILQ_EMPTY(&conf->conf_portal_groups)) 947 return; 948 set_timeout(conf->conf_isns_timeout, false); 949 s = isns_do_connect(isns); 950 if (s < 0) { 951 set_timeout(0, false); 952 return; 953 } 954 gethostname(hostname, sizeof(hostname)); 955 956 res = isns_do_check(isns, s, hostname); 957 if (res < 0) { 958 isns_do_deregister(isns, s, hostname); 959 isns_do_register(isns, s, hostname); 960 } 961 close(s); 962 set_timeout(0, false); 963} 964 965void 966isns_deregister(struct isns *isns) 967{ 968 struct conf *conf = isns->i_conf; 969 int s; 970 char hostname[256]; 971 972 if (TAILQ_EMPTY(&conf->conf_targets) || 973 TAILQ_EMPTY(&conf->conf_portal_groups)) 974 return; 975 set_timeout(conf->conf_isns_timeout, false); 976 s = isns_do_connect(isns); 977 if (s < 0) 978 return; 979 gethostname(hostname, sizeof(hostname)); 980 981 isns_do_deregister(isns, s, hostname); 982 close(s); 983 set_timeout(0, false); 984} 985 986int 987portal_group_set_filter(struct portal_group *pg, const char *str) 988{ 989 int filter; 990 991 if (strcmp(str, "none") == 0) { 992 filter = PG_FILTER_NONE; 993 } else if (strcmp(str, "portal") == 0) { 994 filter = PG_FILTER_PORTAL; 995 } else if (strcmp(str, "portal-name") == 0) { 996 filter = PG_FILTER_PORTAL_NAME; 997 } else if (strcmp(str, "portal-name-auth") == 0) { 998 filter = PG_FILTER_PORTAL_NAME_AUTH; 999 } else { 1000 log_warnx("invalid discovery-filter \"%s\" for portal-group " 1001 "\"%s\"; valid values are \"none\", \"portal\", " 1002 "\"portal-name\", and \"portal-name-auth\"", 1003 str, pg->pg_name); 1004 return (1); 1005 } 1006 1007 if (pg->pg_discovery_filter != PG_FILTER_UNKNOWN && 1008 pg->pg_discovery_filter != filter) { 1009 log_warnx("cannot set discovery-filter to \"%s\" for " 1010 "portal-group \"%s\"; already has a different " 1011 "value", str, pg->pg_name); 1012 return (1); 1013 } 1014 1015 pg->pg_discovery_filter = filter; 1016 1017 return (0); 1018} 1019 1020int 1021portal_group_set_redirection(struct portal_group *pg, const char *addr) 1022{ 1023 1024 if (pg->pg_redirection != NULL) { 1025 log_warnx("cannot set redirection to \"%s\" for " 1026 "portal-group \"%s\"; already defined", 1027 addr, pg->pg_name); 1028 return (1); 1029 } 1030 1031 pg->pg_redirection = checked_strdup(addr); 1032 1033 return (0); 1034} 1035 1036static bool 1037valid_hex(const char ch) 1038{ 1039 switch (ch) { 1040 case '0': 1041 case '1': 1042 case '2': 1043 case '3': 1044 case '4': 1045 case '5': 1046 case '6': 1047 case '7': 1048 case '8': 1049 case '9': 1050 case 'a': 1051 case 'A': 1052 case 'b': 1053 case 'B': 1054 case 'c': 1055 case 'C': 1056 case 'd': 1057 case 'D': 1058 case 'e': 1059 case 'E': 1060 case 'f': 1061 case 'F': 1062 return (true); 1063 default: 1064 return (false); 1065 } 1066} 1067 1068bool 1069valid_iscsi_name(const char *name) 1070{ 1071 int i; 1072 1073 if (strlen(name) >= MAX_NAME_LEN) { 1074 log_warnx("overlong name for target \"%s\"; max length allowed " 1075 "by iSCSI specification is %d characters", 1076 name, MAX_NAME_LEN); 1077 return (false); 1078 } 1079 1080 /* 1081 * In the cases below, we don't return an error, just in case the admin 1082 * was right, and we're wrong. 1083 */ 1084 if (strncasecmp(name, "iqn.", strlen("iqn.")) == 0) { 1085 for (i = strlen("iqn."); name[i] != '\0'; i++) { 1086 /* 1087 * XXX: We should verify UTF-8 normalisation, as defined 1088 * by 3.2.6.2: iSCSI Name Encoding. 1089 */ 1090 if (isalnum(name[i])) 1091 continue; 1092 if (name[i] == '-' || name[i] == '.' || name[i] == ':') 1093 continue; 1094 log_warnx("invalid character \"%c\" in target name " 1095 "\"%s\"; allowed characters are letters, digits, " 1096 "'-', '.', and ':'", name[i], name); 1097 break; 1098 } 1099 /* 1100 * XXX: Check more stuff: valid date and a valid reversed domain. 1101 */ 1102 } else if (strncasecmp(name, "eui.", strlen("eui.")) == 0) { 1103 if (strlen(name) != strlen("eui.") + 16) 1104 log_warnx("invalid target name \"%s\"; the \"eui.\" " 1105 "should be followed by exactly 16 hexadecimal " 1106 "digits", name); 1107 for (i = strlen("eui."); name[i] != '\0'; i++) { 1108 if (!valid_hex(name[i])) { 1109 log_warnx("invalid character \"%c\" in target " 1110 "name \"%s\"; allowed characters are 1-9 " 1111 "and A-F", name[i], name); 1112 break; 1113 } 1114 } 1115 } else if (strncasecmp(name, "naa.", strlen("naa.")) == 0) { 1116 if (strlen(name) > strlen("naa.") + 32) 1117 log_warnx("invalid target name \"%s\"; the \"naa.\" " 1118 "should be followed by at most 32 hexadecimal " 1119 "digits", name); 1120 for (i = strlen("naa."); name[i] != '\0'; i++) { 1121 if (!valid_hex(name[i])) { 1122 log_warnx("invalid character \"%c\" in target " 1123 "name \"%s\"; allowed characters are 1-9 " 1124 "and A-F", name[i], name); 1125 break; 1126 } 1127 } 1128 } else { 1129 log_warnx("invalid target name \"%s\"; should start with " 1130 "either \".iqn\", \"eui.\", or \"naa.\"", 1131 name); 1132 } 1133 return (true); 1134} 1135 1136struct port * 1137port_new(struct conf *conf, struct target *target, struct portal_group *pg) 1138{ 1139 struct port *port; 1140 1141 port = calloc(1, sizeof(*port)); 1142 if (port == NULL) 1143 log_err(1, "calloc"); 1144 asprintf(&port->p_name, "%s-%s", pg->pg_name, target->t_name); 1145 if (port_find(conf, port->p_name) != NULL) { 1146 log_warnx("duplicate port \"%s\"", port->p_name); 1147 free(port); 1148 return (NULL); 1149 } 1150 port->p_conf = conf; 1151 TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next); 1152 TAILQ_INSERT_TAIL(&target->t_ports, port, p_ts); 1153 port->p_target = target; 1154 TAILQ_INSERT_TAIL(&pg->pg_ports, port, p_pgs); 1155 port->p_portal_group = pg; 1156 return (port); 1157} 1158 1159struct port * 1160port_find(const struct conf *conf, const char *name) 1161{ 1162 struct port *port; 1163 1164 TAILQ_FOREACH(port, &conf->conf_ports, p_next) { 1165 if (strcasecmp(port->p_name, name) == 0) 1166 return (port); 1167 } 1168 1169 return (NULL); 1170} 1171 1172struct port * 1173port_find_in_pg(const struct portal_group *pg, const char *target) 1174{ 1175 struct port *port; 1176 1177 TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) { 1178 if (strcasecmp(port->p_target->t_name, target) == 0) 1179 return (port); 1180 } 1181 1182 return (NULL); 1183} 1184 1185void 1186port_delete(struct port *port) 1187{ 1188 1189 if (port->p_portal_group) 1190 TAILQ_REMOVE(&port->p_portal_group->pg_ports, port, p_pgs); 1191 if (port->p_target) 1192 TAILQ_REMOVE(&port->p_target->t_ports, port, p_ts); 1193 TAILQ_REMOVE(&port->p_conf->conf_ports, port, p_next); 1194 free(port->p_name); 1195 free(port); 1196} 1197 1198struct target * 1199target_new(struct conf *conf, const char *name) 1200{ 1201 struct target *targ; 1202 int i, len; 1203 1204 targ = target_find(conf, name); 1205 if (targ != NULL) { 1206 log_warnx("duplicated target \"%s\"", name); 1207 return (NULL); 1208 } 1209 if (valid_iscsi_name(name) == false) { 1210 log_warnx("target name \"%s\" is invalid", name); 1211 return (NULL); 1212 } 1213 targ = calloc(1, sizeof(*targ)); 1214 if (targ == NULL) 1215 log_err(1, "calloc"); 1216 targ->t_name = checked_strdup(name); 1217 1218 /* 1219 * RFC 3722 requires us to normalize the name to lowercase. 1220 */ 1221 len = strlen(name); 1222 for (i = 0; i < len; i++) 1223 targ->t_name[i] = tolower(targ->t_name[i]); 1224 1225 targ->t_conf = conf; 1226 TAILQ_INIT(&targ->t_ports); 1227 TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next); 1228 1229 return (targ); 1230} 1231 1232void 1233target_delete(struct target *targ) 1234{ 1235 struct port *port, *tport; 1236 1237 TAILQ_FOREACH_SAFE(port, &targ->t_ports, p_ts, tport) 1238 port_delete(port); 1239 TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next); 1240 1241 free(targ->t_name); 1242 free(targ->t_redirection); 1243 free(targ); 1244} 1245 1246struct target * 1247target_find(struct conf *conf, const char *name) 1248{ 1249 struct target *targ; 1250 1251 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) { 1252 if (strcasecmp(targ->t_name, name) == 0) 1253 return (targ); 1254 } 1255 1256 return (NULL); 1257} 1258 1259int 1260target_set_redirection(struct target *target, const char *addr) 1261{ 1262 1263 if (target->t_redirection != NULL) { 1264 log_warnx("cannot set redirection to \"%s\" for " 1265 "target \"%s\"; already defined", 1266 addr, target->t_name); 1267 return (1); 1268 } 1269 1270 target->t_redirection = checked_strdup(addr); 1271 1272 return (0); 1273} 1274 1275struct lun * 1276lun_new(struct conf *conf, const char *name) 1277{ 1278 struct lun *lun; 1279 1280 lun = lun_find(conf, name); 1281 if (lun != NULL) { 1282 log_warnx("duplicated lun \"%s\"", name); 1283 return (NULL); 1284 } 1285 1286 lun = calloc(1, sizeof(*lun)); 1287 if (lun == NULL) 1288 log_err(1, "calloc"); 1289 lun->l_conf = conf; 1290 lun->l_name = checked_strdup(name); 1291 TAILQ_INIT(&lun->l_options); 1292 TAILQ_INSERT_TAIL(&conf->conf_luns, lun, l_next); 1293 1294 return (lun); 1295} 1296 1297void 1298lun_delete(struct lun *lun) 1299{ 1300 struct target *targ; 1301 struct lun_option *lo, *tmp; 1302 int i; 1303 1304 TAILQ_FOREACH(targ, &lun->l_conf->conf_targets, t_next) { 1305 for (i = 0; i < MAX_LUNS; i++) { 1306 if (targ->t_luns[i] == lun) 1307 targ->t_luns[i] = NULL; 1308 } 1309 } 1310 TAILQ_REMOVE(&lun->l_conf->conf_luns, lun, l_next); 1311 1312 TAILQ_FOREACH_SAFE(lo, &lun->l_options, lo_next, tmp) 1313 lun_option_delete(lo); 1314 free(lun->l_name); 1315 free(lun->l_backend); 1316 free(lun->l_device_id); 1317 free(lun->l_path); 1318 free(lun->l_scsiname); 1319 free(lun->l_serial); 1320 free(lun); 1321} 1322 1323struct lun * 1324lun_find(const struct conf *conf, const char *name) 1325{ 1326 struct lun *lun; 1327 1328 TAILQ_FOREACH(lun, &conf->conf_luns, l_next) { 1329 if (strcmp(lun->l_name, name) == 0) 1330 return (lun); 1331 } 1332 1333 return (NULL); 1334} 1335 1336void 1337lun_set_backend(struct lun *lun, const char *value) 1338{ 1339 free(lun->l_backend); 1340 lun->l_backend = checked_strdup(value); 1341} 1342 1343void 1344lun_set_blocksize(struct lun *lun, size_t value) 1345{ 1346 1347 lun->l_blocksize = value; 1348} 1349 1350void 1351lun_set_device_id(struct lun *lun, const char *value) 1352{ 1353 free(lun->l_device_id); 1354 lun->l_device_id = checked_strdup(value); 1355} 1356 1357void 1358lun_set_path(struct lun *lun, const char *value) 1359{ 1360 free(lun->l_path); 1361 lun->l_path = checked_strdup(value); 1362} 1363 1364void 1365lun_set_scsiname(struct lun *lun, const char *value) 1366{ 1367 free(lun->l_scsiname); 1368 lun->l_scsiname = checked_strdup(value); 1369} 1370 1371void 1372lun_set_serial(struct lun *lun, const char *value) 1373{ 1374 free(lun->l_serial); 1375 lun->l_serial = checked_strdup(value); 1376} 1377 1378void 1379lun_set_size(struct lun *lun, size_t value) 1380{ 1381 1382 lun->l_size = value; 1383} 1384 1385void 1386lun_set_ctl_lun(struct lun *lun, uint32_t value) 1387{ 1388 1389 lun->l_ctl_lun = value; 1390} 1391 1392struct lun_option * 1393lun_option_new(struct lun *lun, const char *name, const char *value) 1394{ 1395 struct lun_option *lo; 1396 1397 lo = lun_option_find(lun, name); 1398 if (lo != NULL) { 1399 log_warnx("duplicated lun option \"%s\" for lun \"%s\"", 1400 name, lun->l_name); 1401 return (NULL); 1402 } 1403 1404 lo = calloc(1, sizeof(*lo)); 1405 if (lo == NULL) 1406 log_err(1, "calloc"); 1407 lo->lo_name = checked_strdup(name); 1408 lo->lo_value = checked_strdup(value); 1409 lo->lo_lun = lun; 1410 TAILQ_INSERT_TAIL(&lun->l_options, lo, lo_next); 1411 1412 return (lo); 1413} 1414 1415void 1416lun_option_delete(struct lun_option *lo) 1417{ 1418 1419 TAILQ_REMOVE(&lo->lo_lun->l_options, lo, lo_next); 1420 1421 free(lo->lo_name); 1422 free(lo->lo_value); 1423 free(lo); 1424} 1425 1426struct lun_option * 1427lun_option_find(const struct lun *lun, const char *name) 1428{ 1429 struct lun_option *lo; 1430 1431 TAILQ_FOREACH(lo, &lun->l_options, lo_next) { 1432 if (strcmp(lo->lo_name, name) == 0) 1433 return (lo); 1434 } 1435 1436 return (NULL); 1437} 1438 1439void 1440lun_option_set(struct lun_option *lo, const char *value) 1441{ 1442 1443 free(lo->lo_value); 1444 lo->lo_value = checked_strdup(value); 1445} 1446 1447static struct connection * 1448connection_new(struct portal *portal, int fd, const char *host, 1449 const struct sockaddr *client_sa) 1450{ 1451 struct connection *conn; 1452 1453 conn = calloc(1, sizeof(*conn)); 1454 if (conn == NULL) 1455 log_err(1, "calloc"); 1456 conn->conn_portal = portal; 1457 conn->conn_socket = fd; 1458 conn->conn_initiator_addr = checked_strdup(host); 1459 memcpy(&conn->conn_initiator_sa, client_sa, client_sa->sa_len); 1460 1461 /* 1462 * Default values, from RFC 3720, section 12. 1463 */ 1464 conn->conn_max_data_segment_length = 8192; 1465 conn->conn_max_burst_length = 262144; 1466 conn->conn_immediate_data = true; 1467 1468 return (conn); 1469} 1470 1471#if 0 1472static void 1473conf_print(struct conf *conf) 1474{ 1475 struct auth_group *ag; 1476 struct auth *auth; 1477 struct auth_name *auth_name; 1478 struct auth_portal *auth_portal; 1479 struct portal_group *pg; 1480 struct portal *portal; 1481 struct target *targ; 1482 struct lun *lun; 1483 struct lun_option *lo; 1484 1485 TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) { 1486 fprintf(stderr, "auth-group %s {\n", ag->ag_name); 1487 TAILQ_FOREACH(auth, &ag->ag_auths, a_next) 1488 fprintf(stderr, "\t chap-mutual %s %s %s %s\n", 1489 auth->a_user, auth->a_secret, 1490 auth->a_mutual_user, auth->a_mutual_secret); 1491 TAILQ_FOREACH(auth_name, &ag->ag_names, an_next) 1492 fprintf(stderr, "\t initiator-name %s\n", 1493 auth_name->an_initator_name); 1494 TAILQ_FOREACH(auth_portal, &ag->ag_portals, an_next) 1495 fprintf(stderr, "\t initiator-portal %s\n", 1496 auth_portal->an_initator_portal); 1497 fprintf(stderr, "}\n"); 1498 } 1499 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 1500 fprintf(stderr, "portal-group %s {\n", pg->pg_name); 1501 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) 1502 fprintf(stderr, "\t listen %s\n", portal->p_listen); 1503 fprintf(stderr, "}\n"); 1504 } 1505 TAILQ_FOREACH(lun, &conf->conf_luns, l_next) { 1506 fprintf(stderr, "\tlun %s {\n", lun->l_name); 1507 fprintf(stderr, "\t\tpath %s\n", lun->l_path); 1508 TAILQ_FOREACH(lo, &lun->l_options, lo_next) 1509 fprintf(stderr, "\t\toption %s %s\n", 1510 lo->lo_name, lo->lo_value); 1511 fprintf(stderr, "\t}\n"); 1512 } 1513 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) { 1514 fprintf(stderr, "target %s {\n", targ->t_name); 1515 if (targ->t_alias != NULL) 1516 fprintf(stderr, "\t alias %s\n", targ->t_alias); 1517 fprintf(stderr, "}\n"); 1518 } 1519} 1520#endif 1521 1522static int 1523conf_verify_lun(struct lun *lun) 1524{ 1525 const struct lun *lun2; 1526 1527 if (lun->l_backend == NULL) 1528 lun_set_backend(lun, "block"); 1529 if (strcmp(lun->l_backend, "block") == 0) { 1530 if (lun->l_path == NULL) { 1531 log_warnx("missing path for lun \"%s\"", 1532 lun->l_name); 1533 return (1); 1534 } 1535 } else if (strcmp(lun->l_backend, "ramdisk") == 0) { 1536 if (lun->l_size == 0) { 1537 log_warnx("missing size for ramdisk-backed lun \"%s\"", 1538 lun->l_name); 1539 return (1); 1540 } 1541 if (lun->l_path != NULL) { 1542 log_warnx("path must not be specified " 1543 "for ramdisk-backed lun \"%s\"", 1544 lun->l_name); 1545 return (1); 1546 } 1547 } 1548 if (lun->l_blocksize == 0) { 1549 lun_set_blocksize(lun, DEFAULT_BLOCKSIZE); 1550 } else if (lun->l_blocksize < 0) { 1551 log_warnx("invalid blocksize for lun \"%s\"; " 1552 "must be larger than 0", lun->l_name); 1553 return (1); 1554 } 1555 if (lun->l_size != 0 && lun->l_size % lun->l_blocksize != 0) { 1556 log_warnx("invalid size for lun \"%s\"; " 1557 "must be multiple of blocksize", lun->l_name); 1558 return (1); 1559 } 1560 TAILQ_FOREACH(lun2, &lun->l_conf->conf_luns, l_next) { 1561 if (lun == lun2) 1562 continue; 1563 if (lun->l_path != NULL && lun2->l_path != NULL && 1564 strcmp(lun->l_path, lun2->l_path) == 0) { 1565 log_debugx("WARNING: path \"%s\" duplicated " 1566 "between lun \"%s\", and " 1567 "lun \"%s\"", lun->l_path, 1568 lun->l_name, lun2->l_name); 1569 } 1570 } 1571 1572 return (0); 1573} 1574 1575int 1576conf_verify(struct conf *conf) 1577{ 1578 struct auth_group *ag; 1579 struct portal_group *pg; 1580 struct port *port; 1581 struct target *targ; 1582 struct lun *lun; 1583 bool found; 1584 int error, i; 1585 1586 if (conf->conf_pidfile_path == NULL) 1587 conf->conf_pidfile_path = checked_strdup(DEFAULT_PIDFILE); 1588 1589 TAILQ_FOREACH(lun, &conf->conf_luns, l_next) { 1590 error = conf_verify_lun(lun); 1591 if (error != 0) 1592 return (error); 1593 } 1594 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) { 1595 if (targ->t_auth_group == NULL) { 1596 targ->t_auth_group = auth_group_find(conf, 1597 "default"); 1598 assert(targ->t_auth_group != NULL); 1599 } 1600 if (TAILQ_EMPTY(&targ->t_ports)) { 1601 pg = portal_group_find(conf, "default"); 1602 assert(pg != NULL); 1603 port_new(conf, targ, pg); 1604 } 1605 found = false; 1606 for (i = 0; i < MAX_LUNS; i++) { 1607 if (targ->t_luns[i] != NULL) 1608 found = true; 1609 } 1610 if (!found && targ->t_redirection == NULL) { 1611 log_warnx("no LUNs defined for target \"%s\"", 1612 targ->t_name); 1613 } 1614 if (found && targ->t_redirection != NULL) { 1615 log_debugx("target \"%s\" contains luns, " 1616 " but configured for redirection", 1617 targ->t_name); 1618 } 1619 } 1620 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 1621 assert(pg->pg_name != NULL); 1622 if (pg->pg_discovery_auth_group == NULL) { 1623 pg->pg_discovery_auth_group = 1624 auth_group_find(conf, "default"); 1625 assert(pg->pg_discovery_auth_group != NULL); 1626 } 1627 1628 if (pg->pg_discovery_filter == PG_FILTER_UNKNOWN) 1629 pg->pg_discovery_filter = PG_FILTER_NONE; 1630 1631 if (!TAILQ_EMPTY(&pg->pg_ports)) { 1632 if (pg->pg_redirection != NULL) { 1633 log_debugx("portal-group \"%s\" assigned " 1634 "to target, but configured " 1635 "for redirection", 1636 pg->pg_name); 1637 } 1638 pg->pg_unassigned = false; 1639 } else { 1640 if (strcmp(pg->pg_name, "default") != 0) 1641 log_warnx("portal-group \"%s\" not assigned " 1642 "to any target", pg->pg_name); 1643 pg->pg_unassigned = true; 1644 } 1645 } 1646 TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) { 1647 if (ag->ag_name == NULL) 1648 assert(ag->ag_target != NULL); 1649 else 1650 assert(ag->ag_target == NULL); 1651 1652 found = false; 1653 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) { 1654 if (targ->t_auth_group == ag) { 1655 found = true; 1656 break; 1657 } 1658 } 1659 TAILQ_FOREACH(port, &conf->conf_ports, p_next) { 1660 if (port->p_auth_group == ag) { 1661 found = true; 1662 break; 1663 } 1664 } 1665 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 1666 if (pg->pg_discovery_auth_group == ag) { 1667 found = true; 1668 break; 1669 } 1670 } 1671 if (!found && ag->ag_name != NULL && 1672 strcmp(ag->ag_name, "default") != 0 && 1673 strcmp(ag->ag_name, "no-authentication") != 0 && 1674 strcmp(ag->ag_name, "no-access") != 0) { 1675 log_warnx("auth-group \"%s\" not assigned " 1676 "to any target", ag->ag_name); 1677 } 1678 } 1679 1680 return (0); 1681} 1682 1683static int 1684conf_apply(struct conf *oldconf, struct conf *newconf) 1685{ 1686 struct lun *oldlun, *newlun, *tmplun; 1687 struct portal_group *oldpg, *newpg; 1688 struct portal *oldp, *newp; 1689 struct port *oldport, *newport, *tmpport; 1690 struct isns *oldns, *newns; 1691 pid_t otherpid; 1692 int changed, cumulated_error = 0, error, sockbuf; 1693 int one = 1; 1694 1695 if (oldconf->conf_debug != newconf->conf_debug) { 1696 log_debugx("changing debug level to %d", newconf->conf_debug); 1697 log_init(newconf->conf_debug); 1698 } 1699 1700 if (oldconf->conf_pidfh != NULL) { 1701 assert(oldconf->conf_pidfile_path != NULL); 1702 if (newconf->conf_pidfile_path != NULL && 1703 strcmp(oldconf->conf_pidfile_path, 1704 newconf->conf_pidfile_path) == 0) { 1705 newconf->conf_pidfh = oldconf->conf_pidfh; 1706 oldconf->conf_pidfh = NULL; 1707 } else { 1708 log_debugx("removing pidfile %s", 1709 oldconf->conf_pidfile_path); 1710 pidfile_remove(oldconf->conf_pidfh); 1711 oldconf->conf_pidfh = NULL; 1712 } 1713 } 1714 1715 if (newconf->conf_pidfh == NULL && newconf->conf_pidfile_path != NULL) { 1716 log_debugx("opening pidfile %s", newconf->conf_pidfile_path); 1717 newconf->conf_pidfh = 1718 pidfile_open(newconf->conf_pidfile_path, 0600, &otherpid); 1719 if (newconf->conf_pidfh == NULL) { 1720 if (errno == EEXIST) 1721 log_errx(1, "daemon already running, pid: %jd.", 1722 (intmax_t)otherpid); 1723 log_err(1, "cannot open or create pidfile \"%s\"", 1724 newconf->conf_pidfile_path); 1725 } 1726 } 1727 1728 /* 1729 * Go through the new portal groups, assigning tags or preserving old. 1730 */ 1731 TAILQ_FOREACH(newpg, &newconf->conf_portal_groups, pg_next) { 1732 oldpg = portal_group_find(oldconf, newpg->pg_name); 1733 if (oldpg != NULL) 1734 newpg->pg_tag = oldpg->pg_tag; 1735 else 1736 newpg->pg_tag = ++last_portal_group_tag; 1737 } 1738 1739 /* Deregister on removed iSNS servers. */ 1740 TAILQ_FOREACH(oldns, &oldconf->conf_isns, i_next) { 1741 TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) { 1742 if (strcmp(oldns->i_addr, newns->i_addr) == 0) 1743 break; 1744 } 1745 if (newns == NULL) 1746 isns_deregister(oldns); 1747 } 1748 1749 /* 1750 * XXX: If target or lun removal fails, we should somehow "move" 1751 * the old lun or target into newconf, so that subsequent 1752 * conf_apply() would try to remove them again. That would 1753 * be somewhat hairy, though, and lun deletion failures don't 1754 * really happen, so leave it as it is for now. 1755 */ 1756 /* 1757 * First, remove any ports present in the old configuration 1758 * and missing in the new one. 1759 */ 1760 TAILQ_FOREACH_SAFE(oldport, &oldconf->conf_ports, p_next, tmpport) { 1761 newport = port_find(newconf, oldport->p_name); 1762 if (newport != NULL) 1763 continue; 1764 error = kernel_port_remove(oldport); 1765 if (error != 0) { 1766 log_warnx("failed to remove port %s", 1767 oldport->p_name); 1768 /* 1769 * XXX: Uncomment after fixing the root cause. 1770 * 1771 * cumulated_error++; 1772 */ 1773 } 1774 } 1775 1776 /* 1777 * Second, remove any LUNs present in the old configuration 1778 * and missing in the new one. 1779 */ 1780 TAILQ_FOREACH_SAFE(oldlun, &oldconf->conf_luns, l_next, tmplun) { 1781 newlun = lun_find(newconf, oldlun->l_name); 1782 if (newlun == NULL) { 1783 log_debugx("lun \"%s\", CTL lun %d " 1784 "not found in new configuration; " 1785 "removing", oldlun->l_name, oldlun->l_ctl_lun); 1786 error = kernel_lun_remove(oldlun); 1787 if (error != 0) { 1788 log_warnx("failed to remove lun \"%s\", " 1789 "CTL lun %d", 1790 oldlun->l_name, oldlun->l_ctl_lun); 1791 cumulated_error++; 1792 } 1793 continue; 1794 } 1795 1796 /* 1797 * Also remove the LUNs changed by more than size. 1798 */ 1799 changed = 0; 1800 assert(oldlun->l_backend != NULL); 1801 assert(newlun->l_backend != NULL); 1802 if (strcmp(newlun->l_backend, oldlun->l_backend) != 0) { 1803 log_debugx("backend for lun \"%s\", " 1804 "CTL lun %d changed; removing", 1805 oldlun->l_name, oldlun->l_ctl_lun); 1806 changed = 1; 1807 } 1808 if (oldlun->l_blocksize != newlun->l_blocksize) { 1809 log_debugx("blocksize for lun \"%s\", " 1810 "CTL lun %d changed; removing", 1811 oldlun->l_name, oldlun->l_ctl_lun); 1812 changed = 1; 1813 } 1814 if (newlun->l_device_id != NULL && 1815 (oldlun->l_device_id == NULL || 1816 strcmp(oldlun->l_device_id, newlun->l_device_id) != 1817 0)) { 1818 log_debugx("device-id for lun \"%s\", " 1819 "CTL lun %d changed; removing", 1820 oldlun->l_name, oldlun->l_ctl_lun); 1821 changed = 1; 1822 } 1823 if (newlun->l_path != NULL && 1824 (oldlun->l_path == NULL || 1825 strcmp(oldlun->l_path, newlun->l_path) != 0)) { 1826 log_debugx("path for lun \"%s\", " 1827 "CTL lun %d, changed; removing", 1828 oldlun->l_name, oldlun->l_ctl_lun); 1829 changed = 1; 1830 } 1831 if (newlun->l_serial != NULL && 1832 (oldlun->l_serial == NULL || 1833 strcmp(oldlun->l_serial, newlun->l_serial) != 0)) { 1834 log_debugx("serial for lun \"%s\", " 1835 "CTL lun %d changed; removing", 1836 oldlun->l_name, oldlun->l_ctl_lun); 1837 changed = 1; 1838 } 1839 if (changed) { 1840 error = kernel_lun_remove(oldlun); 1841 if (error != 0) { 1842 log_warnx("failed to remove lun \"%s\", " 1843 "CTL lun %d", 1844 oldlun->l_name, oldlun->l_ctl_lun); 1845 cumulated_error++; 1846 } 1847 lun_delete(oldlun); 1848 continue; 1849 } 1850 1851 lun_set_ctl_lun(newlun, oldlun->l_ctl_lun); 1852 } 1853 1854 TAILQ_FOREACH_SAFE(newlun, &newconf->conf_luns, l_next, tmplun) { 1855 oldlun = lun_find(oldconf, newlun->l_name); 1856 if (oldlun != NULL) { 1857 if (newlun->l_size != oldlun->l_size || 1858 newlun->l_size == 0) { 1859 log_debugx("resizing lun \"%s\", CTL lun %d", 1860 newlun->l_name, newlun->l_ctl_lun); 1861 error = kernel_lun_resize(newlun); 1862 if (error != 0) { 1863 log_warnx("failed to " 1864 "resize lun \"%s\", CTL lun %d", 1865 newlun->l_name, 1866 newlun->l_ctl_lun); 1867 cumulated_error++; 1868 } 1869 } 1870 continue; 1871 } 1872 log_debugx("adding lun \"%s\"", newlun->l_name); 1873 error = kernel_lun_add(newlun); 1874 if (error != 0) { 1875 log_warnx("failed to add lun \"%s\"", newlun->l_name); 1876 lun_delete(newlun); 1877 cumulated_error++; 1878 } 1879 } 1880 1881 /* 1882 * Now add new ports or modify existing ones. 1883 */ 1884 TAILQ_FOREACH(newport, &newconf->conf_ports, p_next) { 1885 oldport = port_find(oldconf, newport->p_name); 1886 1887 if (oldport == NULL) { 1888 error = kernel_port_add(newport); 1889 } else { 1890 newport->p_ctl_port = oldport->p_ctl_port; 1891 error = kernel_port_update(newport); 1892 } 1893 if (error != 0) { 1894 log_warnx("failed to %s port %s", 1895 (oldport == NULL) ? "add" : "update", 1896 newport->p_name); 1897 /* 1898 * XXX: Uncomment after fixing the root cause. 1899 * 1900 * cumulated_error++; 1901 */ 1902 } 1903 } 1904 1905 /* 1906 * Go through the new portals, opening the sockets as neccessary. 1907 */ 1908 TAILQ_FOREACH(newpg, &newconf->conf_portal_groups, pg_next) { 1909 if (newpg->pg_unassigned) { 1910 log_debugx("not listening on portal-group \"%s\", " 1911 "not assigned to any target", 1912 newpg->pg_name); 1913 continue; 1914 } 1915 TAILQ_FOREACH(newp, &newpg->pg_portals, p_next) { 1916 /* 1917 * Try to find already open portal and reuse 1918 * the listening socket. We don't care about 1919 * what portal or portal group that was, what 1920 * matters is the listening address. 1921 */ 1922 TAILQ_FOREACH(oldpg, &oldconf->conf_portal_groups, 1923 pg_next) { 1924 TAILQ_FOREACH(oldp, &oldpg->pg_portals, 1925 p_next) { 1926 if (strcmp(newp->p_listen, 1927 oldp->p_listen) == 0 && 1928 oldp->p_socket > 0) { 1929 newp->p_socket = 1930 oldp->p_socket; 1931 oldp->p_socket = 0; 1932 break; 1933 } 1934 } 1935 } 1936 if (newp->p_socket > 0) { 1937 /* 1938 * We're done with this portal. 1939 */ 1940 continue; 1941 } 1942 1943#ifdef ICL_KERNEL_PROXY 1944 if (proxy_mode) { 1945 newpg->pg_conf->conf_portal_id++; 1946 newp->p_id = newpg->pg_conf->conf_portal_id; 1947 log_debugx("listening on %s, portal-group " 1948 "\"%s\", portal id %d, using ICL proxy", 1949 newp->p_listen, newpg->pg_name, newp->p_id); 1950 kernel_listen(newp->p_ai, newp->p_iser, 1951 newp->p_id); 1952 continue; 1953 } 1954#endif 1955 assert(proxy_mode == false); 1956 assert(newp->p_iser == false); 1957 1958 log_debugx("listening on %s, portal-group \"%s\"", 1959 newp->p_listen, newpg->pg_name); 1960 newp->p_socket = socket(newp->p_ai->ai_family, 1961 newp->p_ai->ai_socktype, 1962 newp->p_ai->ai_protocol); 1963 if (newp->p_socket < 0) { 1964 log_warn("socket(2) failed for %s", 1965 newp->p_listen); 1966 cumulated_error++; 1967 continue; 1968 } 1969 sockbuf = SOCKBUF_SIZE; 1970 if (setsockopt(newp->p_socket, SOL_SOCKET, SO_RCVBUF, 1971 &sockbuf, sizeof(sockbuf)) == -1) 1972 log_warn("setsockopt(SO_RCVBUF) failed " 1973 "for %s", newp->p_listen); 1974 sockbuf = SOCKBUF_SIZE; 1975 if (setsockopt(newp->p_socket, SOL_SOCKET, SO_SNDBUF, 1976 &sockbuf, sizeof(sockbuf)) == -1) 1977 log_warn("setsockopt(SO_SNDBUF) failed " 1978 "for %s", newp->p_listen); 1979 error = setsockopt(newp->p_socket, SOL_SOCKET, 1980 SO_REUSEADDR, &one, sizeof(one)); 1981 if (error != 0) { 1982 log_warn("setsockopt(SO_REUSEADDR) failed " 1983 "for %s", newp->p_listen); 1984 close(newp->p_socket); 1985 newp->p_socket = 0; 1986 cumulated_error++; 1987 continue; 1988 } 1989 error = bind(newp->p_socket, newp->p_ai->ai_addr, 1990 newp->p_ai->ai_addrlen); 1991 if (error != 0) { 1992 log_warn("bind(2) failed for %s", 1993 newp->p_listen); 1994 close(newp->p_socket); 1995 newp->p_socket = 0; 1996 cumulated_error++; 1997 continue; 1998 } 1999 error = listen(newp->p_socket, -1); 2000 if (error != 0) { 2001 log_warn("listen(2) failed for %s", 2002 newp->p_listen); 2003 close(newp->p_socket); 2004 newp->p_socket = 0; 2005 cumulated_error++; 2006 continue; 2007 } 2008 } 2009 } 2010 2011 /* 2012 * Go through the no longer used sockets, closing them. 2013 */ 2014 TAILQ_FOREACH(oldpg, &oldconf->conf_portal_groups, pg_next) { 2015 TAILQ_FOREACH(oldp, &oldpg->pg_portals, p_next) { 2016 if (oldp->p_socket <= 0) 2017 continue; 2018 log_debugx("closing socket for %s, portal-group \"%s\"", 2019 oldp->p_listen, oldpg->pg_name); 2020 close(oldp->p_socket); 2021 oldp->p_socket = 0; 2022 } 2023 } 2024 2025 /* (Re-)Register on remaining/new iSNS servers. */ 2026 TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) { 2027 TAILQ_FOREACH(oldns, &oldconf->conf_isns, i_next) { 2028 if (strcmp(oldns->i_addr, newns->i_addr) == 0) 2029 break; 2030 } 2031 isns_register(newns, oldns); 2032 } 2033 2034 /* Schedule iSNS update */ 2035 if (!TAILQ_EMPTY(&newconf->conf_isns)) 2036 set_timeout((newconf->conf_isns_period + 2) / 3, false); 2037 2038 return (cumulated_error); 2039} 2040 2041bool 2042timed_out(void) 2043{ 2044 2045 return (sigalrm_received); 2046} 2047 2048static void 2049sigalrm_handler_fatal(int dummy __unused) 2050{ 2051 /* 2052 * It would be easiest to just log an error and exit. We can't 2053 * do this, though, because log_errx() is not signal safe, since 2054 * it calls syslog(3). Instead, set a flag checked by pdu_send() 2055 * and pdu_receive(), to call log_errx() there. Should they fail 2056 * to notice, we'll exit here one second later. 2057 */ 2058 if (sigalrm_received) { 2059 /* 2060 * Oh well. Just give up and quit. 2061 */ 2062 _exit(2); 2063 } 2064 2065 sigalrm_received = true; 2066} 2067 2068static void 2069sigalrm_handler(int dummy __unused) 2070{ 2071 2072 sigalrm_received = true; 2073} 2074 2075void 2076set_timeout(int timeout, int fatal) 2077{ 2078 struct sigaction sa; 2079 struct itimerval itv; 2080 int error; 2081 2082 if (timeout <= 0) { 2083 log_debugx("session timeout disabled"); 2084 bzero(&itv, sizeof(itv)); 2085 error = setitimer(ITIMER_REAL, &itv, NULL); 2086 if (error != 0) 2087 log_err(1, "setitimer"); 2088 sigalrm_received = false; 2089 return; 2090 } 2091 2092 sigalrm_received = false; 2093 bzero(&sa, sizeof(sa)); 2094 if (fatal) 2095 sa.sa_handler = sigalrm_handler_fatal; 2096 else 2097 sa.sa_handler = sigalrm_handler; 2098 sigfillset(&sa.sa_mask); 2099 error = sigaction(SIGALRM, &sa, NULL); 2100 if (error != 0) 2101 log_err(1, "sigaction"); 2102 2103 /* 2104 * First SIGALRM will arive after conf_timeout seconds. 2105 * If we do nothing, another one will arrive a second later. 2106 */ 2107 log_debugx("setting session timeout to %d seconds", timeout); 2108 bzero(&itv, sizeof(itv)); 2109 itv.it_interval.tv_sec = 1; 2110 itv.it_value.tv_sec = timeout; 2111 error = setitimer(ITIMER_REAL, &itv, NULL); 2112 if (error != 0) 2113 log_err(1, "setitimer"); 2114} 2115 2116static int 2117wait_for_children(bool block) 2118{ 2119 pid_t pid; 2120 int status; 2121 int num = 0; 2122 2123 for (;;) { 2124 /* 2125 * If "block" is true, wait for at least one process. 2126 */ 2127 if (block && num == 0) 2128 pid = wait4(-1, &status, 0, NULL); 2129 else 2130 pid = wait4(-1, &status, WNOHANG, NULL); 2131 if (pid <= 0) 2132 break; 2133 if (WIFSIGNALED(status)) { 2134 log_warnx("child process %d terminated with signal %d", 2135 pid, WTERMSIG(status)); 2136 } else if (WEXITSTATUS(status) != 0) { 2137 log_warnx("child process %d terminated with exit status %d", 2138 pid, WEXITSTATUS(status)); 2139 } else { 2140 log_debugx("child process %d terminated gracefully", pid); 2141 } 2142 num++; 2143 } 2144 2145 return (num); 2146} 2147 2148static void 2149handle_connection(struct portal *portal, int fd, 2150 const struct sockaddr *client_sa, bool dont_fork) 2151{ 2152 struct connection *conn; 2153 int error; 2154 pid_t pid; 2155 char host[NI_MAXHOST + 1]; 2156 struct conf *conf; 2157 2158 conf = portal->p_portal_group->pg_conf; 2159 2160 if (dont_fork) { 2161 log_debugx("incoming connection; not forking due to -d flag"); 2162 } else { 2163 nchildren -= wait_for_children(false); 2164 assert(nchildren >= 0); 2165 2166 while (conf->conf_maxproc > 0 && nchildren >= conf->conf_maxproc) { 2167 log_debugx("maxproc limit of %d child processes hit; " 2168 "waiting for child process to exit", conf->conf_maxproc); 2169 nchildren -= wait_for_children(true); 2170 assert(nchildren >= 0); 2171 } 2172 log_debugx("incoming connection; forking child process #%d", 2173 nchildren); 2174 nchildren++; 2175 pid = fork(); 2176 if (pid < 0) 2177 log_err(1, "fork"); 2178 if (pid > 0) { 2179 close(fd); 2180 return; 2181 } 2182 } 2183 pidfile_close(conf->conf_pidfh); 2184 2185 error = getnameinfo(client_sa, client_sa->sa_len, 2186 host, sizeof(host), NULL, 0, NI_NUMERICHOST); 2187 if (error != 0) 2188 log_errx(1, "getnameinfo: %s", gai_strerror(error)); 2189 2190 log_debugx("accepted connection from %s; portal group \"%s\"", 2191 host, portal->p_portal_group->pg_name); 2192 log_set_peer_addr(host); 2193 setproctitle("%s", host); 2194 2195 conn = connection_new(portal, fd, host, client_sa); 2196 set_timeout(conf->conf_timeout, true); 2197 kernel_capsicate(); 2198 login(conn); 2199 if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) { 2200 kernel_handoff(conn); 2201 log_debugx("connection handed off to the kernel"); 2202 } else { 2203 assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY); 2204 discovery(conn); 2205 } 2206 log_debugx("nothing more to do; exiting"); 2207 exit(0); 2208} 2209 2210static int 2211fd_add(int fd, fd_set *fdset, int nfds) 2212{ 2213 2214 /* 2215 * Skip sockets which we failed to bind. 2216 */ 2217 if (fd <= 0) 2218 return (nfds); 2219 2220 FD_SET(fd, fdset); 2221 if (fd > nfds) 2222 nfds = fd; 2223 return (nfds); 2224} 2225 2226static void 2227main_loop(struct conf *conf, bool dont_fork) 2228{ 2229 struct portal_group *pg; 2230 struct portal *portal; 2231 struct sockaddr_storage client_sa; 2232 socklen_t client_salen; 2233#ifdef ICL_KERNEL_PROXY 2234 int connection_id; 2235 int portal_id; 2236#endif 2237 fd_set fdset; 2238 int error, nfds, client_fd; 2239 2240 pidfile_write(conf->conf_pidfh); 2241 2242 for (;;) { 2243 if (sighup_received || sigterm_received || timed_out()) 2244 return; 2245 2246#ifdef ICL_KERNEL_PROXY 2247 if (proxy_mode) { 2248 client_salen = sizeof(client_sa); 2249 kernel_accept(&connection_id, &portal_id, 2250 (struct sockaddr *)&client_sa, &client_salen); 2251 assert(client_salen >= client_sa.ss_len); 2252 2253 log_debugx("incoming connection, id %d, portal id %d", 2254 connection_id, portal_id); 2255 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 2256 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) { 2257 if (portal->p_id == portal_id) { 2258 goto found; 2259 } 2260 } 2261 } 2262 2263 log_errx(1, "kernel returned invalid portal_id %d", 2264 portal_id); 2265 2266found: 2267 handle_connection(portal, connection_id, 2268 (struct sockaddr *)&client_sa, dont_fork); 2269 } else { 2270#endif 2271 assert(proxy_mode == false); 2272 2273 FD_ZERO(&fdset); 2274 nfds = 0; 2275 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 2276 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) 2277 nfds = fd_add(portal->p_socket, &fdset, nfds); 2278 } 2279 error = select(nfds + 1, &fdset, NULL, NULL, NULL); 2280 if (error <= 0) { 2281 if (errno == EINTR) 2282 return; 2283 log_err(1, "select"); 2284 } 2285 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 2286 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) { 2287 if (!FD_ISSET(portal->p_socket, &fdset)) 2288 continue; 2289 client_salen = sizeof(client_sa); 2290 client_fd = accept(portal->p_socket, 2291 (struct sockaddr *)&client_sa, 2292 &client_salen); 2293 if (client_fd < 0) 2294 log_err(1, "accept"); 2295 assert(client_salen >= client_sa.ss_len); 2296 2297 handle_connection(portal, client_fd, 2298 (struct sockaddr *)&client_sa, 2299 dont_fork); 2300 break; 2301 } 2302 } 2303#ifdef ICL_KERNEL_PROXY 2304 } 2305#endif 2306 } 2307} 2308 2309static void 2310sighup_handler(int dummy __unused) 2311{ 2312 2313 sighup_received = true; 2314} 2315 2316static void 2317sigterm_handler(int dummy __unused) 2318{ 2319 2320 sigterm_received = true; 2321} 2322 2323static void 2324sigchld_handler(int dummy __unused) 2325{ 2326 2327 /* 2328 * The only purpose of this handler is to make SIGCHLD 2329 * interrupt the ISCSIDWAIT ioctl(2), so we can call 2330 * wait_for_children(). 2331 */ 2332} 2333 2334static void 2335register_signals(void) 2336{ 2337 struct sigaction sa; 2338 int error; 2339 2340 bzero(&sa, sizeof(sa)); 2341 sa.sa_handler = sighup_handler; 2342 sigfillset(&sa.sa_mask); 2343 error = sigaction(SIGHUP, &sa, NULL); 2344 if (error != 0) 2345 log_err(1, "sigaction"); 2346 2347 sa.sa_handler = sigterm_handler; 2348 error = sigaction(SIGTERM, &sa, NULL); 2349 if (error != 0) 2350 log_err(1, "sigaction"); 2351 2352 sa.sa_handler = sigterm_handler; 2353 error = sigaction(SIGINT, &sa, NULL); 2354 if (error != 0) 2355 log_err(1, "sigaction"); 2356 2357 sa.sa_handler = sigchld_handler; 2358 error = sigaction(SIGCHLD, &sa, NULL); 2359 if (error != 0) 2360 log_err(1, "sigaction"); 2361} 2362 2363int 2364main(int argc, char **argv) 2365{ 2366 struct conf *oldconf, *newconf, *tmpconf; 2367 struct isns *newns; 2368 const char *config_path = DEFAULT_CONFIG_PATH; 2369 int debug = 0, ch, error; 2370 bool dont_daemonize = false; 2371 2372 while ((ch = getopt(argc, argv, "df:R")) != -1) { 2373 switch (ch) { 2374 case 'd': 2375 dont_daemonize = true; 2376 debug++; 2377 break; 2378 case 'f': 2379 config_path = optarg; 2380 break; 2381 case 'R': 2382#ifndef ICL_KERNEL_PROXY 2383 log_errx(1, "ctld(8) compiled without ICL_KERNEL_PROXY " 2384 "does not support iSER protocol"); 2385#endif 2386 proxy_mode = true; 2387 break; 2388 case '?': 2389 default: 2390 usage(); 2391 } 2392 } 2393 argc -= optind; 2394 if (argc != 0) 2395 usage(); 2396 2397 log_init(debug); 2398 kernel_init(); 2399 2400 oldconf = conf_new_from_kernel(); 2401 newconf = conf_new_from_file(config_path); 2402 if (newconf == NULL) 2403 log_errx(1, "configuration error; exiting"); 2404 if (debug > 0) { 2405 oldconf->conf_debug = debug; 2406 newconf->conf_debug = debug; 2407 } 2408 2409 error = conf_apply(oldconf, newconf); 2410 if (error != 0) 2411 log_errx(1, "failed to apply configuration; exiting"); 2412 2413 conf_delete(oldconf); 2414 oldconf = NULL; 2415 2416 register_signals(); 2417 2418 if (dont_daemonize == false) { 2419 log_debugx("daemonizing"); 2420 if (daemon(0, 0) == -1) { 2421 log_warn("cannot daemonize"); 2422 pidfile_remove(newconf->conf_pidfh); 2423 exit(1); 2424 } 2425 } 2426 2427 /* Schedule iSNS update */ 2428 if (!TAILQ_EMPTY(&newconf->conf_isns)) 2429 set_timeout((newconf->conf_isns_period + 2) / 3, false); 2430 2431 for (;;) { 2432 main_loop(newconf, dont_daemonize); 2433 if (sighup_received) { 2434 sighup_received = false; 2435 log_debugx("received SIGHUP, reloading configuration"); 2436 tmpconf = conf_new_from_file(config_path); 2437 if (tmpconf == NULL) { 2438 log_warnx("configuration error, " 2439 "continuing with old configuration"); 2440 } else { 2441 if (debug > 0) 2442 tmpconf->conf_debug = debug; 2443 oldconf = newconf; 2444 newconf = tmpconf; 2445 error = conf_apply(oldconf, newconf); 2446 if (error != 0) 2447 log_warnx("failed to reload " 2448 "configuration"); 2449 conf_delete(oldconf); 2450 oldconf = NULL; 2451 } 2452 } else if (sigterm_received) { 2453 log_debugx("exiting on signal; " 2454 "reloading empty configuration"); 2455 2456 log_debugx("removing CTL iSCSI ports " 2457 "and terminating all connections"); 2458 2459 oldconf = newconf; 2460 newconf = conf_new(); 2461 if (debug > 0) 2462 newconf->conf_debug = debug; 2463 error = conf_apply(oldconf, newconf); 2464 if (error != 0) 2465 log_warnx("failed to apply configuration"); 2466 conf_delete(oldconf); 2467 oldconf = NULL; 2468 2469 log_warnx("exiting on signal"); 2470 exit(0); 2471 } else { 2472 nchildren -= wait_for_children(false); 2473 assert(nchildren >= 0); 2474 if (timed_out()) { 2475 set_timeout(0, false); 2476 TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) 2477 isns_check(newns); 2478 /* Schedule iSNS update */ 2479 if (!TAILQ_EMPTY(&newconf->conf_isns)) { 2480 set_timeout((newconf->conf_isns_period 2481 + 2) / 3, 2482 false); 2483 } 2484 } 2485 } 2486 } 2487 /* NOTREACHED */ 2488} 2489