Deleted Added
full compact
32c32
< __FBSDID("$FreeBSD: stable/10/usr.sbin/ctld/ctld.c 274871 2014-11-22 17:52:33Z trasz $");
---
> __FBSDID("$FreeBSD: stable/10/usr.sbin/ctld/ctld.c 274939 2014-11-24 00:47:04Z mav $");
52a53
> #include "isns.h"
91a93
> TAILQ_INIT(&conf->conf_isns);
92a95,96
> conf->conf_isns_period = 900;
> conf->conf_isns_timeout = 5;
105a110
> struct isns *is, *istmp;
114a120,121
> TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp)
> isns_delete(is);
622,623c629,630
< int
< portal_group_add_listen(struct portal_group *pg, const char *value, bool iser)
---
> static int
> parse_addr_port(char *arg, const char *def_port, struct addrinfo **ai)
626,627c633
< struct portal *portal;
< char *addr, *ch, *arg;
---
> char *addr, *ch;
631,640d636
< portal = portal_new(pg);
< portal->p_listen = checked_strdup(value);
< portal->p_iser = iser;
<
< arg = portal->p_listen;
< if (arg[0] == '\0') {
< log_warnx("empty listen address");
< portal_delete(portal);
< return (1);
< }
647,650c643
< if (arg == NULL) {
< log_warnx("invalid listen address %s",
< portal->p_listen);
< portal_delete(portal);
---
> if (arg == NULL)
652d644
< }
654c646
< port = "3260";
---
> port = def_port;
657,660c649
< } else {
< log_warnx("invalid listen address %s",
< portal->p_listen);
< portal_delete(portal);
---
> } else
662d650
< }
674c662
< port = "3260";
---
> port = def_port;
678c666
< port = "3260";
---
> port = def_port;
687a676,680
> error = getaddrinfo(addr, port, &hints, ai);
> if (error != 0)
> return (1);
> return (0);
> }
689,692c682,692
< error = getaddrinfo(addr, port, &hints, &portal->p_ai);
< if (error != 0) {
< log_warnx("getaddrinfo for %s failed: %s",
< portal->p_listen, gai_strerror(error));
---
> int
> portal_group_add_listen(struct portal_group *pg, const char *value, bool iser)
> {
> struct portal *portal;
>
> portal = portal_new(pg);
> portal->p_listen = checked_strdup(value);
> portal->p_iser = iser;
>
> if (parse_addr_port(portal->p_listen, "3260", &portal->p_ai)) {
> log_warnx("invalid listen address %s", portal->p_listen);
704a705,956
> int
> isns_new(struct conf *conf, const char *addr)
> {
> struct isns *isns;
>
> isns = calloc(1, sizeof(*isns));
> if (isns == NULL)
> log_err(1, "calloc");
> isns->i_conf = conf;
> TAILQ_INSERT_TAIL(&conf->conf_isns, isns, i_next);
> isns->i_addr = checked_strdup(addr);
>
> if (parse_addr_port(isns->i_addr, "3205", &isns->i_ai)) {
> log_warnx("invalid iSNS address %s", isns->i_addr);
> isns_delete(isns);
> return (1);
> }
>
> /*
> * XXX: getaddrinfo(3) may return multiple addresses; we should turn
> * those into multiple servers.
> */
>
> return (0);
> }
>
> void
> isns_delete(struct isns *isns)
> {
>
> TAILQ_REMOVE(&isns->i_conf->conf_isns, isns, i_next);
> free(isns->i_addr);
> if (isns->i_ai != NULL)
> freeaddrinfo(isns->i_ai);
> free(isns);
> }
>
> static int
> isns_do_connect(struct isns *isns)
> {
> int s;
>
> s = socket(isns->i_ai->ai_family, isns->i_ai->ai_socktype,
> isns->i_ai->ai_protocol);
> if (s < 0) {
> log_warn("socket(2) failed for %s", isns->i_addr);
> return (-1);
> }
> if (connect(s, isns->i_ai->ai_addr, isns->i_ai->ai_addrlen)) {
> log_warn("connect(2) failed for %s", isns->i_addr);
> close(s);
> return (-1);
> }
> return(s);
> }
>
> static int
> isns_do_register(struct isns *isns, int s, const char *hostname)
> {
> struct conf *conf = isns->i_conf;
> struct target *target;
> struct portal *portal;
> struct portal_group *pg;
> struct isns_req *req;
> int res = 0;
> uint32_t error;
>
> req = isns_req_create(ISNS_FUNC_DEVATTRREG, ISNS_FLAG_CLIENT);
> isns_req_add_str(req, 32, TAILQ_FIRST(&conf->conf_targets)->t_name);
> isns_req_add_delim(req);
> isns_req_add_str(req, 1, hostname);
> isns_req_add_32(req, 2, 2); /* 2 -- iSCSI */
> isns_req_add_32(req, 6, conf->conf_isns_period);
> TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
> if (pg->pg_unassigned)
> continue;
> TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
> isns_req_add_addr(req, 16, portal->p_ai);
> isns_req_add_port(req, 17, portal->p_ai);
> }
> }
> TAILQ_FOREACH(target, &conf->conf_targets, t_next) {
> isns_req_add_str(req, 32, target->t_name);
> isns_req_add_32(req, 33, 1); /* 1 -- Target*/
> if (target->t_alias != NULL)
> isns_req_add_str(req, 34, target->t_alias);
> pg = target->t_portal_group;
> isns_req_add_32(req, 51, pg->pg_tag);
> TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
> isns_req_add_addr(req, 49, portal->p_ai);
> isns_req_add_port(req, 50, portal->p_ai);
> }
> }
> res = isns_req_send(s, req);
> if (res < 0) {
> log_warn("send(2) failed for %s", isns->i_addr);
> goto quit;
> }
> res = isns_req_receive(s, req);
> if (res < 0) {
> log_warn("receive(2) failed for %s", isns->i_addr);
> goto quit;
> }
> error = isns_req_get_status(req);
> if (error != 0) {
> log_warnx("iSNS register error %d for %s", error, isns->i_addr);
> res = -1;
> }
> quit:
> isns_req_free(req);
> return (res);
> }
>
> static int
> isns_do_check(struct isns *isns, int s, const char *hostname)
> {
> struct conf *conf = isns->i_conf;
> struct isns_req *req;
> int res = 0;
> uint32_t error;
>
> req = isns_req_create(ISNS_FUNC_DEVATTRQRY, ISNS_FLAG_CLIENT);
> isns_req_add_str(req, 32, TAILQ_FIRST(&conf->conf_targets)->t_name);
> isns_req_add_str(req, 1, hostname);
> isns_req_add_delim(req);
> isns_req_add(req, 2, 0, NULL);
> res = isns_req_send(s, req);
> if (res < 0) {
> log_warn("send(2) failed for %s", isns->i_addr);
> goto quit;
> }
> res = isns_req_receive(s, req);
> if (res < 0) {
> log_warn("receive(2) failed for %s", isns->i_addr);
> goto quit;
> }
> error = isns_req_get_status(req);
> if (error != 0) {
> log_warnx("iSNS check error %d for %s", error, isns->i_addr);
> res = -1;
> }
> quit:
> isns_req_free(req);
> return (res);
> }
>
> static int
> isns_do_deregister(struct isns *isns, int s, const char *hostname)
> {
> struct conf *conf = isns->i_conf;
> struct isns_req *req;
> int res = 0;
> uint32_t error;
>
> req = isns_req_create(ISNS_FUNC_DEVDEREG, ISNS_FLAG_CLIENT);
> isns_req_add_str(req, 32, TAILQ_FIRST(&conf->conf_targets)->t_name);
> isns_req_add_delim(req);
> isns_req_add_str(req, 1, hostname);
> res = isns_req_send(s, req);
> if (res < 0) {
> log_warn("send(2) failed for %s", isns->i_addr);
> goto quit;
> }
> res = isns_req_receive(s, req);
> if (res < 0) {
> log_warn("receive(2) failed for %s", isns->i_addr);
> goto quit;
> }
> error = isns_req_get_status(req);
> if (error != 0) {
> log_warnx("iSNS deregister error %d for %s", error, isns->i_addr);
> res = -1;
> }
> quit:
> isns_req_free(req);
> return (res);
> }
>
> void
> isns_register(struct isns *isns, struct isns *oldisns)
> {
> struct conf *conf = isns->i_conf;
> int s, res;
> char hostname[256];
>
> if (TAILQ_EMPTY(&conf->conf_targets) ||
> TAILQ_EMPTY(&conf->conf_portal_groups))
> return;
> set_timeout(conf->conf_isns_timeout, false);
> s = isns_do_connect(isns);
> if (s < 0) {
> set_timeout(0, false);
> return;
> }
> gethostname(hostname, sizeof(hostname));
>
> if (oldisns == NULL || TAILQ_EMPTY(&oldisns->i_conf->conf_targets))
> oldisns = isns;
> res = isns_do_deregister(oldisns, s, hostname);
> res = isns_do_register(isns, s, hostname);
> close(s);
> set_timeout(0, false);
> }
>
> void
> isns_check(struct isns *isns)
> {
> struct conf *conf = isns->i_conf;
> int s, res;
> char hostname[256];
>
> if (TAILQ_EMPTY(&conf->conf_targets) ||
> TAILQ_EMPTY(&conf->conf_portal_groups))
> return;
> set_timeout(conf->conf_isns_timeout, false);
> s = isns_do_connect(isns);
> if (s < 0) {
> set_timeout(0, false);
> return;
> }
> gethostname(hostname, sizeof(hostname));
>
> res = isns_do_check(isns, s, hostname);
> if (res < 0) {
> res = isns_do_deregister(isns, s, hostname);
> res = isns_do_register(isns, s, hostname);
> }
> close(s);
> set_timeout(0, false);
> }
>
> void
> isns_deregister(struct isns *isns)
> {
> struct conf *conf = isns->i_conf;
> int s, res;
> char hostname[256];
>
> if (TAILQ_EMPTY(&conf->conf_targets) ||
> TAILQ_EMPTY(&conf->conf_portal_groups))
> return;
> set_timeout(conf->conf_isns_timeout, false);
> s = isns_do_connect(isns);
> if (s < 0)
> return;
> gethostname(hostname, sizeof(hostname));
>
> res = isns_do_deregister(isns, s, hostname);
> close(s);
> set_timeout(0, false);
> }
>
1253a1506
> struct isns *oldns, *newns;
1290a1544,1553
> /* Deregister on removed iSNS servers. */
> TAILQ_FOREACH(oldns, &oldconf->conf_isns, i_next) {
> TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) {
> if (strcmp(oldns->i_addr, newns->i_addr) == 0)
> break;
> }
> if (newns == NULL)
> isns_deregister(oldns);
> }
>
1320d1582
< lun_delete(oldlun);
1323d1584
< target_delete(oldtarg);
1346d1606
< lun_delete(oldlun);
1571a1832,1844
> /* (Re-)Register on remaining/new iSNS servers. */
> TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) {
> TAILQ_FOREACH(oldns, &oldconf->conf_isns, i_next) {
> if (strcmp(oldns->i_addr, newns->i_addr) == 0)
> break;
> }
> isns_register(newns, oldns);
> }
>
> /* Schedule iSNS update */
> if (!TAILQ_EMPTY(&newconf->conf_isns))
> set_timeout((newconf->conf_isns_period + 2) / 3, false);
>
1583c1856
< sigalrm_handler(int dummy __unused)
---
> sigalrm_handler_fatal(int dummy __unused)
1603c1876
< set_timeout(const struct conf *conf)
---
> sigalrm_handler(int dummy __unused)
1604a1878,1884
>
> sigalrm_received = true;
> }
>
> void
> set_timeout(int timeout, int fatal)
> {
1609c1889
< if (conf->conf_timeout <= 0) {
---
> if (timeout <= 0) {
1610a1891,1895
> bzero(&itv, sizeof(itv));
> error = setitimer(ITIMER_REAL, &itv, NULL);
> if (error != 0)
> log_err(1, "setitimer");
> sigalrm_received = false;
1613a1899
> sigalrm_received = false;
1615c1901,1904
< sa.sa_handler = sigalrm_handler;
---
> if (fatal)
> sa.sa_handler = sigalrm_handler_fatal;
> else
> sa.sa_handler = sigalrm_handler;
1624a1914
> log_debugx("setting session timeout to %d seconds", timeout);
1627,1630c1917
< itv.it_value.tv_sec = conf->conf_timeout;
<
< log_debugx("setting session timeout to %d seconds",
< conf->conf_timeout);
---
> itv.it_value.tv_sec = timeout;
1716c2003
< set_timeout(conf);
---
> set_timeout(conf->conf_timeout, true);
1763c2050
< if (sighup_received || sigterm_received)
---
> if (sighup_received || sigterm_received || timed_out())
1886a2174
> struct isns *newns;
1945a2234,2237
> /* Schedule iSNS update */
> if (!TAILQ_EMPTY(&newconf->conf_isns))
> set_timeout((newconf->conf_isns_period + 2) / 3, false);
>
1980a2273,2274
> conf_delete(oldconf);
> oldconf = NULL;
1986a2281,2291
> if (timed_out()) {
> set_timeout(0, false);
> TAILQ_FOREACH(newns, &newconf->conf_isns, i_next)
> isns_check(newns);
> /* Schedule iSNS update */
> if (!TAILQ_EMPTY(&newconf->conf_isns)) {
> set_timeout((newconf->conf_isns_period
> + 2) / 3,
> false);
> }
> }