Deleted Added
sdiff udiff text old ( 274871 ) new ( 274939 )
full compact
1/*-
2 * Copyright (c) 2012 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Edward Tomasz Napierala under sponsorship
6 * from the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 15 unchanged lines hidden (view full) ---

24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: stable/10/usr.sbin/ctld/ctld.c 274871 2014-11-22 17:52:33Z trasz $");
33
34#include <sys/types.h>
35#include <sys/time.h>
36#include <sys/socket.h>
37#include <sys/wait.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
40#include <assert.h>

--- 4 unchanged lines hidden (view full) ---

45#include <stdbool.h>
46#include <stdio.h>
47#include <stdint.h>
48#include <stdlib.h>
49#include <string.h>
50#include <unistd.h>
51
52#include "ctld.h"
53
54bool proxy_mode = false;
55
56static volatile bool sighup_received = false;
57static volatile bool sigterm_received = false;
58static volatile bool sigalrm_received = false;
59
60static int nchildren = 0;

--- 23 unchanged lines hidden (view full) ---

84 struct conf *conf;
85
86 conf = calloc(1, sizeof(*conf));
87 if (conf == NULL)
88 log_err(1, "calloc");
89 TAILQ_INIT(&conf->conf_targets);
90 TAILQ_INIT(&conf->conf_auth_groups);
91 TAILQ_INIT(&conf->conf_portal_groups);
92
93 conf->conf_debug = 0;
94 conf->conf_timeout = 60;
95 conf->conf_maxproc = 30;
96
97 return (conf);
98}
99
100void
101conf_delete(struct conf *conf)
102{
103 struct target *targ, *tmp;
104 struct auth_group *ag, *cagtmp;
105 struct portal_group *pg, *cpgtmp;
106
107 assert(conf->conf_pidfh == NULL);
108
109 TAILQ_FOREACH_SAFE(targ, &conf->conf_targets, t_next, tmp)
110 target_delete(targ);
111 TAILQ_FOREACH_SAFE(ag, &conf->conf_auth_groups, ag_next, cagtmp)
112 auth_group_delete(ag);
113 TAILQ_FOREACH_SAFE(pg, &conf->conf_portal_groups, pg_next, cpgtmp)
114 portal_group_delete(pg);
115 free(conf->conf_pidfile_path);
116 free(conf);
117}
118
119static struct auth *
120auth_new(struct auth_group *ag)
121{
122 struct auth *auth;

--- 491 unchanged lines hidden (view full) ---

614 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
615 if (strcmp(pg->pg_name, name) == 0)
616 return (pg);
617 }
618
619 return (NULL);
620}
621
622int
623portal_group_add_listen(struct portal_group *pg, const char *value, bool iser)
624{
625 struct addrinfo hints;
626 struct portal *portal;
627 char *addr, *ch, *arg;
628 const char *port;
629 int error, colons = 0;
630
631 portal = portal_new(pg);
632 portal->p_listen = checked_strdup(value);
633 portal->p_iser = iser;
634
635 arg = portal->p_listen;
636 if (arg[0] == '\0') {
637 log_warnx("empty listen address");
638 portal_delete(portal);
639 return (1);
640 }
641 if (arg[0] == '[') {
642 /*
643 * IPv6 address in square brackets, perhaps with port.
644 */
645 arg++;
646 addr = strsep(&arg, "]");
647 if (arg == NULL) {
648 log_warnx("invalid listen address %s",
649 portal->p_listen);
650 portal_delete(portal);
651 return (1);
652 }
653 if (arg[0] == '\0') {
654 port = "3260";
655 } else if (arg[0] == ':') {
656 port = arg + 1;
657 } else {
658 log_warnx("invalid listen address %s",
659 portal->p_listen);
660 portal_delete(portal);
661 return (1);
662 }
663 } else {
664 /*
665 * Either IPv6 address without brackets - and without
666 * a port - or IPv4 address. Just count the colons.
667 */
668 for (ch = arg; *ch != '\0'; ch++) {
669 if (*ch == ':')
670 colons++;
671 }
672 if (colons > 1) {
673 addr = arg;
674 port = "3260";
675 } else {
676 addr = strsep(&arg, ":");
677 if (arg == NULL)
678 port = "3260";
679 else
680 port = arg;
681 }
682 }
683
684 memset(&hints, 0, sizeof(hints));
685 hints.ai_family = PF_UNSPEC;
686 hints.ai_socktype = SOCK_STREAM;
687 hints.ai_flags = AI_PASSIVE;
688
689 error = getaddrinfo(addr, port, &hints, &portal->p_ai);
690 if (error != 0) {
691 log_warnx("getaddrinfo for %s failed: %s",
692 portal->p_listen, gai_strerror(error));
693 portal_delete(portal);
694 return (1);
695 }
696
697 /*
698 * XXX: getaddrinfo(3) may return multiple addresses; we should turn
699 * those into multiple portals.
700 */
701
702 return (0);
703}
704
705static bool
706valid_hex(const char ch)
707{
708 switch (ch) {
709 case '0':
710 case '1':
711 case '2':
712 case '3':

--- 533 unchanged lines hidden (view full) ---

1246
1247static int
1248conf_apply(struct conf *oldconf, struct conf *newconf)
1249{
1250 struct target *oldtarg, *newtarg, *tmptarg;
1251 struct lun *oldlun, *newlun, *tmplun;
1252 struct portal_group *oldpg, *newpg;
1253 struct portal *oldp, *newp;
1254 pid_t otherpid;
1255 int changed, cumulated_error = 0, error;
1256 int one = 1;
1257
1258 if (oldconf->conf_debug != newconf->conf_debug) {
1259 log_debugx("changing debug level to %d", newconf->conf_debug);
1260 log_init(newconf->conf_debug);
1261 }

--- 21 unchanged lines hidden (view full) ---

1283 if (errno == EEXIST)
1284 log_errx(1, "daemon already running, pid: %jd.",
1285 (intmax_t)otherpid);
1286 log_err(1, "cannot open or create pidfile \"%s\"",
1287 newconf->conf_pidfile_path);
1288 }
1289 }
1290
1291 /*
1292 * XXX: If target or lun removal fails, we should somehow "move"
1293 * the old lun or target into newconf, so that subsequent
1294 * conf_apply() would try to remove them again. That would
1295 * be somewhat hairy, though, and lun deletion failures don't
1296 * really happen, so leave it as it is for now.
1297 */
1298 TAILQ_FOREACH_SAFE(oldtarg, &oldconf->conf_targets, t_next, tmptarg) {

--- 13 unchanged lines hidden (view full) ---

1312 error = kernel_lun_remove(oldlun);
1313 if (error != 0) {
1314 log_warnx("failed to remove lun %d, "
1315 "target %s, CTL lun %d",
1316 oldlun->l_lun, oldtarg->t_name,
1317 oldlun->l_ctl_lun);
1318 cumulated_error++;
1319 }
1320 lun_delete(oldlun);
1321 }
1322 kernel_port_remove(oldtarg);
1323 target_delete(oldtarg);
1324 continue;
1325 }
1326
1327 /*
1328 * Second, remove any LUNs present in the old target
1329 * and missing in the new one.
1330 */
1331 TAILQ_FOREACH_SAFE(oldlun, &oldtarg->t_luns, l_next, tmplun) {

--- 6 unchanged lines hidden (view full) ---

1338 error = kernel_lun_remove(oldlun);
1339 if (error != 0) {
1340 log_warnx("failed to remove lun %d, "
1341 "target %s, CTL lun %d",
1342 oldlun->l_lun, oldtarg->t_name,
1343 oldlun->l_ctl_lun);
1344 cumulated_error++;
1345 }
1346 lun_delete(oldlun);
1347 continue;
1348 }
1349
1350 /*
1351 * Also remove the LUNs changed by more than size.
1352 */
1353 changed = 0;
1354 assert(oldlun->l_backend != NULL);

--- 209 unchanged lines hidden (view full) ---

1564 continue;
1565 log_debugx("closing socket for %s, portal-group \"%s\"",
1566 oldp->p_listen, oldpg->pg_name);
1567 close(oldp->p_socket);
1568 oldp->p_socket = 0;
1569 }
1570 }
1571
1572 return (cumulated_error);
1573}
1574
1575bool
1576timed_out(void)
1577{
1578
1579 return (sigalrm_received);
1580}
1581
1582static void
1583sigalrm_handler(int dummy __unused)
1584{
1585 /*
1586 * It would be easiest to just log an error and exit. We can't
1587 * do this, though, because log_errx() is not signal safe, since
1588 * it calls syslog(3). Instead, set a flag checked by pdu_send()
1589 * and pdu_receive(), to call log_errx() there. Should they fail
1590 * to notice, we'll exit here one second later.
1591 */
1592 if (sigalrm_received) {
1593 /*
1594 * Oh well. Just give up and quit.
1595 */
1596 _exit(2);
1597 }
1598
1599 sigalrm_received = true;
1600}
1601
1602static void
1603set_timeout(const struct conf *conf)
1604{
1605 struct sigaction sa;
1606 struct itimerval itv;
1607 int error;
1608
1609 if (conf->conf_timeout <= 0) {
1610 log_debugx("session timeout disabled");
1611 return;
1612 }
1613
1614 bzero(&sa, sizeof(sa));
1615 sa.sa_handler = sigalrm_handler;
1616 sigfillset(&sa.sa_mask);
1617 error = sigaction(SIGALRM, &sa, NULL);
1618 if (error != 0)
1619 log_err(1, "sigaction");
1620
1621 /*
1622 * First SIGALRM will arive after conf_timeout seconds.
1623 * If we do nothing, another one will arrive a second later.
1624 */
1625 bzero(&itv, sizeof(itv));
1626 itv.it_interval.tv_sec = 1;
1627 itv.it_value.tv_sec = conf->conf_timeout;
1628
1629 log_debugx("setting session timeout to %d seconds",
1630 conf->conf_timeout);
1631 error = setitimer(ITIMER_REAL, &itv, NULL);
1632 if (error != 0)
1633 log_err(1, "setitimer");
1634}
1635
1636static int
1637wait_for_children(bool block)
1638{

--- 69 unchanged lines hidden (view full) ---

1708 log_errx(1, "getnameinfo: %s", gai_strerror(error));
1709
1710 log_debugx("accepted connection from %s; portal group \"%s\"",
1711 host, portal->p_portal_group->pg_name);
1712 log_set_peer_addr(host);
1713 setproctitle("%s", host);
1714
1715 conn = connection_new(portal, fd, host, client_sa);
1716 set_timeout(conf);
1717 kernel_capsicate();
1718 login(conn);
1719 if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
1720 kernel_handoff(conn);
1721 log_debugx("connection handed off to the kernel");
1722 } else {
1723 assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
1724 discovery(conn);

--- 30 unchanged lines hidden (view full) ---

1755 int portal_id;
1756#endif
1757 fd_set fdset;
1758 int error, nfds, client_fd;
1759
1760 pidfile_write(conf->conf_pidfh);
1761
1762 for (;;) {
1763 if (sighup_received || sigterm_received)
1764 return;
1765
1766#ifdef ICL_KERNEL_PROXY
1767 if (proxy_mode) {
1768 client_salen = sizeof(client_sa);
1769 kernel_accept(&connection_id, &portal_id,
1770 (struct sockaddr *)&client_sa, &client_salen);
1771 assert(client_salen >= client_sa.ss_len);

--- 107 unchanged lines hidden (view full) ---

1879 if (error != 0)
1880 log_err(1, "sigaction");
1881}
1882
1883int
1884main(int argc, char **argv)
1885{
1886 struct conf *oldconf, *newconf, *tmpconf;
1887 const char *config_path = DEFAULT_CONFIG_PATH;
1888 int debug = 0, ch, error;
1889 bool dont_daemonize = false;
1890
1891 while ((ch = getopt(argc, argv, "df:R")) != -1) {
1892 switch (ch) {
1893 case 'd':
1894 dont_daemonize = true;

--- 43 unchanged lines hidden (view full) ---

1938 log_debugx("daemonizing");
1939 if (daemon(0, 0) == -1) {
1940 log_warn("cannot daemonize");
1941 pidfile_remove(newconf->conf_pidfh);
1942 exit(1);
1943 }
1944 }
1945
1946 for (;;) {
1947 main_loop(newconf, dont_daemonize);
1948 if (sighup_received) {
1949 sighup_received = false;
1950 log_debugx("received SIGHUP, reloading configuration");
1951 tmpconf = conf_new_from_file(config_path);
1952 if (tmpconf == NULL) {
1953 log_warnx("configuration error, "

--- 19 unchanged lines hidden (view full) ---

1973
1974 oldconf = newconf;
1975 newconf = conf_new();
1976 if (debug > 0)
1977 newconf->conf_debug = debug;
1978 error = conf_apply(oldconf, newconf);
1979 if (error != 0)
1980 log_warnx("failed to apply configuration");
1981
1982 log_warnx("exiting on signal");
1983 exit(0);
1984 } else {
1985 nchildren -= wait_for_children(false);
1986 assert(nchildren >= 0);
1987 }
1988 }
1989 /* NOTREACHED */
1990}