summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/iscsid/connection.c43
-rw-r--r--usr.sbin/iscsid/initiator.c65
-rw-r--r--usr.sbin/iscsid/iscsid.c29
-rw-r--r--usr.sbin/iscsid/iscsid.h29
-rw-r--r--usr.sbin/iscsid/session.c158
5 files changed, 255 insertions, 69 deletions
diff --git a/usr.sbin/iscsid/connection.c b/usr.sbin/iscsid/connection.c
index cb76c158090..6102ddd3110 100644
--- a/usr.sbin/iscsid/connection.c
+++ b/usr.sbin/iscsid/connection.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: connection.c,v 1.11 2011/04/28 18:32:01 claudio Exp $ */
+/* $OpenBSD: connection.c,v 1.12 2011/05/02 06:32:56 claudio Exp $ */
/*
* Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org>
@@ -17,7 +17,6 @@
*/
#include <sys/types.h>
-#include <sys/ioctl.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/uio.h>
@@ -26,8 +25,6 @@
#include <netinet/tcp.h>
#include <scsi/iscsi.h>
-#include <scsi/scsi_all.h>
-#include <dev/vscsivar.h>
#include <errno.h>
#include <event.h>
@@ -181,31 +178,16 @@ conn_write_dispatch(int fd, short event, void *arg)
}
void
-conn_logout(struct connection *c)
-{
- conn_fsm(c, CONN_EV_LOGOUT);
-}
-
-void
conn_fail(struct connection *c)
{
log_debug("conn_fail");
conn_fsm(c, CONN_EV_FAIL);
}
-void
-conn_loggedin(struct connection *c)
-{
- if (c->session->config.SessionType == SESSION_TYPE_DISCOVERY)
- conn_fsm(c, CONN_EV_DISCOVERY);
- else
- conn_fsm(c, CONN_EV_LOGGED_IN);
-}
-
int
conn_task_ready(struct connection *c)
{
- if ((c->state & CONN_LOGGED_IN) && TAILQ_EMPTY(&c->tasks))
+ if ((c->state & CONN_RUNNING) && TAILQ_EMPTY(&c->tasks))
return 1;
return 0;
}
@@ -291,12 +273,12 @@ struct {
{ CONN_FREE, CONN_EV_CONNECT, c_do_connect }, /* T1 */
{ CONN_XPT_WAIT, CONN_EV_CONNECTED, c_do_login }, /* T4 */
{ CONN_IN_LOGIN, CONN_EV_LOGGED_IN, c_do_loggedin }, /* T5 */
- { CONN_IN_LOGIN, CONN_EV_DISCOVERY, c_do_loggedin }, /* T5 */
{ CONN_LOGGED_IN, CONN_EV_LOGOUT, c_do_logout }, /* T9 */
{ CONN_LOGOUT_REQ, CONN_EV_LOGOUT, c_do_logout }, /* T10 */
{ CONN_IN_LOGOUT, CONN_EV_LOGGED_OUT, c_do_loggedout }, /* T13 */
{ CONN_ANYSTATE, CONN_EV_CLOSED, c_do_fail },
{ CONN_ANYSTATE, CONN_EV_FAIL, c_do_fail },
+ { CONN_ANYSTATE, CONN_EV_FREE, c_do_fail },
{ 0, 0, NULL }
};
@@ -363,18 +345,15 @@ c_do_login(struct connection *c, enum c_event ev)
int
c_do_loggedin(struct connection *c, enum c_event ev)
{
- if (ev == CONN_EV_LOGGED_IN)
- vscsi_event(VSCSI_REQPROBE, c->session->target, -1);
- else
- initiator_discovery(c->session);
+ session_fsm(c->session, SESS_EV_CONN_LOGGED_IN, c);
+
return (CONN_LOGGED_IN);
}
int
c_do_logout(struct connection *c, enum c_event ev)
{
- /* do full logout */
- initiator_logout(c, ISCSI_LOGOUT_CLOSE_SESS, 1);
+ /* logout is in progress ... */
return (CONN_IN_LOGOUT);
}
@@ -386,8 +365,7 @@ c_do_loggedout(struct connection *c, enum c_event ev)
event_del(&c->wev);
close(c->fd);
- session_fsm(c->session, SESS_EV_CONN_CLOSED, c);
-
+ /* session is informed by the logout handler */
return (CONN_FREE);
}
@@ -401,12 +379,11 @@ c_do_fail(struct connection *c, enum c_event ev)
session_fsm(c->session, SESS_EV_CONN_FAIL, c);
- if (c->state & CONN_NOT_LOGGED_IN)
+ if (ev == CONN_EV_FREE || c->state & CONN_NEVER_LOGGED_IN)
return (CONN_FREE);
return (CONN_CLEANUP_WAIT);
}
-
const char *
conn_state(int s)
{
@@ -452,14 +429,14 @@ conn_event(enum c_event e)
return "connected";
case CONN_EV_LOGGED_IN:
return "logged in";
- case CONN_EV_DISCOVERY:
- return "discovery";
case CONN_EV_LOGOUT:
return "logout";
case CONN_EV_LOGGED_OUT:
return "logged out";
case CONN_EV_CLOSED:
return "closed";
+ case CONN_EV_FREE:
+ return "forced free";
}
snprintf(buf, sizeof(buf), "UKNWN %d", e);
diff --git a/usr.sbin/iscsid/initiator.c b/usr.sbin/iscsid/initiator.c
index 7d7975e8e85..7510baffed4 100644
--- a/usr.sbin/iscsid/initiator.c
+++ b/usr.sbin/iscsid/initiator.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: initiator.c,v 1.7 2011/04/27 19:02:07 claudio Exp $ */
+/* $OpenBSD: initiator.c,v 1.8 2011/05/02 06:32:56 claudio Exp $ */
/*
* Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org>
@@ -47,7 +47,7 @@ initiator_init(void)
arc4random_uniform(0xffffff) | ISCSI_ISID_RAND;
initiator->config.isid_qual = arc4random_uniform(0xffff);
TAILQ_INIT(&initiator->sessions);
- return (initiator);
+ return initiator;
}
void
@@ -62,6 +62,30 @@ initiator_cleanup(struct initiator *i)
free(initiator);
}
+void
+initiator_shutdown(struct initiator *i)
+{
+ struct session *s;
+
+ log_debug("initiator_shutdown: going down");
+
+ TAILQ_FOREACH(s, &initiator->sessions, entry)
+ session_shutdown(s);
+}
+
+int
+initiator_isdown(struct initiator *i)
+{
+ struct session *s;
+ int inprogres = 0;
+
+ TAILQ_FOREACH(s, &initiator->sessions, entry) {
+ if ((s->state & SESS_RUNNING) && !(s->state & SESS_FREE))
+ inprogres = 1;
+ }
+ return !inprogres;
+}
+
struct session *
initiator_t2s(u_int target)
{
@@ -205,7 +229,7 @@ initiator_login_cb(struct connection *c, void *arg, struct pdu *p)
}
conn_task_cleanup(c, &tl->task);
- conn_loggedin(c);
+ conn_fsm(c, CONN_EV_LOGGED_IN);
free(tl);
pdu_free(p);
}
@@ -254,7 +278,7 @@ initiator_discovery_cb(struct connection *c, void *arg, struct pdu *p)
lresp->datalen[2];
if (size == 0) {
/* empty response */
- conn_logout(c);
+ session_shutdown(c->session);
break;
}
buf = pdu_getbuf(p, &n, PDU_DATA);
@@ -268,7 +292,7 @@ initiator_discovery_cb(struct connection *c, void *arg, struct pdu *p)
log_debug("%s\t=>\t%s", k->key, k->value);
}
free(kvp);
- conn_logout(c);
+ session_shutdown(c->session);
break;
default:
log_debug("initiator_discovery_cb: unexpected message type %x",
@@ -282,7 +306,7 @@ fail:
}
void
-initiator_logout(struct connection *c, u_int8_t reason, int onconn)
+initiator_logout(struct session *s, struct connection *c, u_int8_t reason)
{
struct task_logout *tl;
struct pdu *p;
@@ -290,7 +314,7 @@ initiator_logout(struct connection *c, u_int8_t reason, int onconn)
if (!(tl = calloc(1, sizeof(*tl)))) {
log_warn("initiator_logout");
- conn_fail(c);
+ /* XXX sess_fail */
return;
}
tl->c = c;
@@ -298,26 +322,29 @@ initiator_logout(struct connection *c, u_int8_t reason, int onconn)
if (!(p = pdu_new())) {
log_warn("initiator_logout");
- conn_fail(c);
+ /* XXX sess_fail */
+ free(tl);
return;
}
if (!(loreq = pdu_gethdr(p))) {
log_warn("initiator_logout");
- conn_fail(c);
+ /* XXX sess_fail */
+ pdu_free(p);
+ free(tl);
return;
}
loreq->opcode = ISCSI_OP_LOGOUT_REQUEST;
loreq->flags = ISCSI_LOGOUT_F | reason;
- if (reason != 0)
+ if (reason != ISCSI_LOGOUT_CLOSE_SESS)
loreq->cid = c->cid;
- task_init(&tl->task, c->session, 0, tl, initiator_logout_cb, NULL);
+ task_init(&tl->task, s, 0, tl, initiator_logout_cb, NULL);
task_pdu_add(&tl->task, p);
- if (onconn)
+ if (c && (c->state & CONN_RUNNING))
conn_task_issue(c, &tl->task);
else
- session_task_issue(c->session, &tl->task);
+ session_logout_issue(s, &tl->task);
}
void
@@ -326,21 +353,27 @@ initiator_logout_cb(struct connection *c, void *arg, struct pdu *p)
struct task_logout *tl = arg;
struct iscsi_pdu_logout_response *loresp;
- c = tl->c;
loresp = pdu_getbuf(p, NULL, PDU_HEADER);
log_debug("initiator_logout_cb: "
- "reason %d, Time2Wait %d, Time2Retain %d",
+ "response %d, Time2Wait %d, Time2Retain %d",
loresp->response, loresp->time2wait, loresp->time2retain);
switch (loresp->response) {
case ISCSI_LOGOUT_RESP_SUCCESS:
- conn_fsm(tl->c, CONN_EV_LOGGED_OUT);
+ if (tl->reason == ISCSI_LOGOUT_CLOSE_SESS) {
+ conn_fsm(c, CONN_EV_LOGGED_OUT);
+ session_fsm(c->session, SESS_EV_CLOSED, NULL);
+ } else {
+ conn_fsm(tl->c, CONN_EV_LOGGED_OUT);
+ session_fsm(c->session, SESS_EV_CONN_CLOSED, tl->c);
+ }
break;
case ISCSI_LOGOUT_RESP_UNKN_CID:
/* connection ID not found, retry will not help */
log_warnx("%s: logout failed, cid %d unknown, giving up\n",
tl->c->session->config.SessionName,
tl->c->cid);
+ conn_fsm(tl->c, CONN_EV_FREE);
break;
case ISCSI_LOGOUT_RESP_NO_SUPPORT:
case ISCSI_LOGOUT_RESP_ERROR:
diff --git a/usr.sbin/iscsid/iscsid.c b/usr.sbin/iscsid/iscsid.c
index fe34cf72886..1989c5775ea 100644
--- a/usr.sbin/iscsid/iscsid.c
+++ b/usr.sbin/iscsid/iscsid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: iscsid.c,v 1.5 2011/04/27 19:16:15 claudio Exp $ */
+/* $OpenBSD: iscsid.c,v 1.6 2011/05/02 06:32:56 claudio Exp $ */
/*
* Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org>
@@ -36,8 +36,12 @@
void main_sig_handler(int, short, void *);
__dead void usage(void);
+void shutdown_cb(int, short, void *);
struct initiator *initiator;
+struct event exit_ev;
+int exit_rounds;
+#define ISCSI_EXIT_WAIT 5
int
main(int argc, char *argv[])
@@ -127,12 +131,18 @@ main(int argc, char *argv[])
void
main_sig_handler(int sig, short event, void *arg)
{
+ struct timeval tv;
+
/* signal handler rules don't apply, libevent decouples for us */
switch (sig) {
case SIGTERM:
case SIGINT:
case SIGHUP:
- event_loopexit(NULL);
+ initiator_shutdown(initiator);
+ evtimer_set(&exit_ev, shutdown_cb, NULL);
+ timerclear(&tv);
+ if (evtimer_add(&exit_ev, &tv) == -1)
+ fatal("main_sig_handler");
break;
default:
fatalx("unexpected signal");
@@ -227,3 +237,18 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu)
done:
pdu_free(pdu);
}
+
+void
+shutdown_cb(int fd, short event, void *arg)
+{
+ struct timeval tv;
+
+ if (exit_rounds++ >= ISCSI_EXIT_WAIT || initiator_isdown(initiator))
+ event_loopexit(NULL);
+
+ timerclear(&tv);
+ tv.tv_sec = 1;
+
+ if (evtimer_add(&exit_ev, &tv) == -1)
+ fatal("shutdown_cb");
+}
diff --git a/usr.sbin/iscsid/iscsid.h b/usr.sbin/iscsid/iscsid.h
index 4eaf77598bd..42ec7c5237c 100644
--- a/usr.sbin/iscsid/iscsid.h
+++ b/usr.sbin/iscsid/iscsid.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iscsid.h,v 1.7 2011/04/27 19:02:07 claudio Exp $ */
+/* $OpenBSD: iscsid.h,v 1.8 2011/05/02 06:32:56 claudio Exp $ */
/*
* Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org>
@@ -67,11 +67,12 @@ TAILQ_HEAD(taskq, task);
#define SESS_INIT 0x0001
#define SESS_FREE 0x0002
-#define SESS_LOGGED_IN 0x0003
-#define SESS_FAILED 0x0004
+#define SESS_LOGGED_IN 0x0004
+#define SESS_FAILED 0x0008
+#define SESS_DOWN 0x0010
#define SESS_ANYSTATE 0xffff
+#define SESS_RUNNING (SESS_FREE | SESS_LOGGED_IN | SESS_FAILED)
-#define CONN_DONE 0x0000 /* no real state just return value */
#define CONN_FREE 0x0001
#define CONN_XPT_WAIT 0x0002
#define CONN_XPT_UP 0x0004
@@ -82,14 +83,16 @@ TAILQ_HEAD(taskq, task);
#define CONN_CLEANUP_WAIT 0x0080
#define CONN_IN_CLEANUP 0x0100
#define CONN_ANYSTATE 0xffff
-#define CONN_NOT_LOGGED_IN (CONN_FREE | CONN_XPT_WAIT | CONN_XPT_UP)
+#define CONN_RUNNING (CONN_LOGGED_IN | CONN_LOGOUT_REQ)
+#define CONN_FAILED (CONN_CLEANUP_WAIT | CONN_IN_CLEANUP)
+#define CONN_NEVER_LOGGED_IN (CONN_FREE | CONN_XPT_WAIT | CONN_XPT_UP)
enum c_event {
CONN_EV_FAIL,
+ CONN_EV_FREE,
CONN_EV_CONNECT,
CONN_EV_CONNECTED,
CONN_EV_LOGGED_IN,
- CONN_EV_DISCOVERY,
CONN_EV_LOGOUT,
CONN_EV_LOGGED_OUT,
CONN_EV_CLOSED
@@ -97,11 +100,16 @@ enum c_event {
enum s_event {
SESS_EV_START,
+ SESS_EV_CONN_LOGGED_IN,
SESS_EV_CONN_FAIL,
SESS_EV_CONN_CLOSED,
+ SESS_EV_CLOSED,
SESS_EV_FAIL
};
+#define SESS_ACT_UP 0
+#define SESS_ACT_DOWN 1
+
struct pdu {
TAILQ_ENTRY(pdu) entry;
struct iovec iov[PDU_MAXIOV];
@@ -220,6 +228,7 @@ struct session {
u_int16_t tsih; /* target session id handle */
u_int target;
int state;
+ int action;
};
struct connection {
@@ -264,10 +273,12 @@ void iscsid_ctrl_dispatch(void *, struct pdu *);
struct initiator *initiator_init(void);
void initiator_cleanup(struct initiator *);
+void initiator_shutdown(struct initiator *);
+int initiator_isdown(struct initiator *);
struct session *initiator_t2s(u_int);
void initiator_login(struct connection *);
void initiator_discovery(struct session *);
-void initiator_logout(struct connection *, u_int8_t, int);
+void initiator_logout(struct session *, struct connection *, u_int8_t);
void initiator_nop_in_imm(struct connection *, struct pdu *);
char *default_initiator_name(void);
@@ -280,8 +291,10 @@ int control_compose(void *, u_int16_t, void *, size_t);
struct session *session_find(struct initiator *, char *);
struct session *session_new(struct initiator *, u_int8_t);
void session_cleanup(struct session *);
+int session_shutdown(struct session *);
void session_config(struct session *, struct session_config *);
void session_task_issue(struct session *, struct task *);
+void session_logout_issue(struct session *, struct task *);
void session_schedule(struct session *);
void session_task_login(struct connection *);
void session_fsm(struct session *, enum s_event, struct connection *);
@@ -293,9 +306,7 @@ void conn_task_issue(struct connection *, struct task *);
void conn_task_schedule(struct connection *);
void conn_task_cleanup(struct connection *c, struct task *);
void conn_pdu_write(struct connection *, struct pdu *);
-void conn_logout(struct connection *);
void conn_fail(struct connection *);
-void conn_loggedin(struct connection *);
void conn_fsm(struct connection *, enum c_event);
void *pdu_gethdr(struct pdu *);
diff --git a/usr.sbin/iscsid/session.c b/usr.sbin/iscsid/session.c
index ad570f47503..5ce56b1fd36 100644
--- a/usr.sbin/iscsid/session.c
+++ b/usr.sbin/iscsid/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.2 2011/04/27 07:25:26 claudio Exp $ */
+/* $OpenBSD: session.c,v 1.3 2011/05/02 06:32:56 claudio Exp $ */
/*
* Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org>
@@ -16,13 +16,15 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h>
#include <sys/types.h>
+#include <sys/ioctl.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <scsi/iscsi.h>
+#include <scsi/scsi_all.h>
+#include <dev/vscsivar.h>
#include <event.h>
#include <stdio.h>
@@ -35,7 +37,10 @@
void session_fsm_callback(int, short, void *);
int sess_do_start(struct session *, struct sessev *);
-int sess_do_fail(struct session *, struct sessev *);
+int sess_do_conn_loggedin(struct session *, struct sessev *);
+int sess_do_conn_fail(struct session *, struct sessev *);
+int sess_do_conn_closed(struct session *, struct sessev *);
+int sess_do_down(struct session *, struct sessev *);
const char *sess_state(int);
const char *sess_event(enum s_event);
@@ -87,6 +92,8 @@ session_cleanup(struct session *s)
{
struct connection *c;
+ taskq_cleanup(&s->tasks);
+
while ((c = TAILQ_FIRST(&s->connections)) != NULL)
conn_free(c);
@@ -95,6 +102,26 @@ session_cleanup(struct session *s)
free(s);
}
+int
+session_shutdown(struct session *s)
+{
+ log_debug("session[%s] going down", s->config.SessionName);
+
+ s->action = SESS_ACT_DOWN;
+ if (s->state & (SESS_INIT | SESS_FREE | SESS_DOWN)) {
+ struct connection *c;
+ while ((c = TAILQ_FIRST(&s->connections)) != NULL)
+ conn_free(c);
+ return 0;
+ }
+
+ /* cleanup task queue and issue a logout */
+ taskq_cleanup(&s->tasks);
+ initiator_logout(s, NULL, ISCSI_LOGOUT_CLOSE_SESS);
+
+ return 1;
+}
+
void
session_config(struct session *s, struct session_config *sc)
{
@@ -128,6 +155,32 @@ session_task_issue(struct session *s, struct task *t)
}
void
+session_logout_issue(struct session *s, struct task *t)
+{
+ struct connection *c, *rc = NULL;
+
+ /* find first free session or first available session */
+ TAILQ_FOREACH(c, &s->connections, entry) {
+ if (conn_task_ready(c)) {
+ conn_fsm(c, CONN_EV_LOGOUT);
+ conn_task_issue(c, t);
+ return;
+ }
+ if (c->state & CONN_RUNNING)
+ rc = c;
+ }
+
+ if (rc) {
+ conn_fsm(rc, CONN_EV_LOGOUT);
+ conn_task_issue(rc, t);
+ return;
+ }
+
+ /* XXX must open new connection, gulp */
+ fatalx("session_logout_issue needs more work");
+}
+
+void
session_schedule(struct session *s)
{
struct task *t = TAILQ_FIRST(&s->tasks);
@@ -154,7 +207,7 @@ session_schedule(struct session *s)
void
session_fsm(struct session *s, enum s_event ev, struct connection *c)
{
- struct timeval tv;
+ struct timeval tv;
struct sessev *sev;
if ((sev = malloc(sizeof(*sev))) == NULL)
@@ -174,8 +227,11 @@ struct {
int (*action)(struct session *, struct sessev *);
} s_fsm[] = {
{ SESS_INIT, SESS_EV_START, sess_do_start },
- { SESS_FREE, SESS_EV_CONN_FAIL, sess_do_fail },
- { SESS_FREE, SESS_EV_CONN_CLOSED, sess_do_fail },
+ { SESS_FREE, SESS_EV_CONN_LOGGED_IN, sess_do_conn_loggedin },
+ { SESS_LOGGED_IN, SESS_EV_CONN_LOGGED_IN, sess_do_conn_loggedin },
+ { SESS_RUNNING, SESS_EV_CONN_FAIL, sess_do_conn_fail },
+ { SESS_RUNNING, SESS_EV_CONN_CLOSED, sess_do_conn_closed },
+ { SESS_RUNNING, SESS_EV_CLOSED, sess_do_down },
{ 0, 0, NULL }
};
@@ -223,12 +279,34 @@ sess_do_start(struct session *s, struct sessev *sev)
log_sockaddr(&s->config.connection.TargetAddr));
conn_new(s, &s->config.connection);
- return (SESS_FREE);
+ return SESS_FREE;
+}
+
+int
+sess_do_conn_loggedin(struct session *s, struct sessev *sev)
+{
+ if (s->state & SESS_LOGGED_IN)
+ return SESS_LOGGED_IN;
+
+ if (s->config.SessionType == SESSION_TYPE_DISCOVERY)
+ initiator_discovery(s);
+ else
+ vscsi_event(VSCSI_REQPROBE, s->target, -1);
+
+ return SESS_LOGGED_IN;
}
int
-sess_do_fail(struct session *s, struct sessev *sev)
+sess_do_conn_fail(struct session *s, struct sessev *sev)
{
+ struct connection *c = sev->conn;
+ int state = SESS_FREE;
+
+ if (sev->conn == NULL) {
+ log_warnx("Just what do you think you're doing, Dave?");
+ return -1;
+ }
+
/*
* cleanup connections:
* Connections in state FREE can be removed.
@@ -236,7 +314,63 @@ sess_do_fail(struct session *s, struct sessev *sev)
* the FAILED state. If no sessions are left and the session was
* not already FREE then explicit recovery needs to be done.
*/
- return (SESS_FREE);
+
+ switch (c->state) {
+ case CONN_FREE:
+ conn_free(c);
+ break;
+ case CONN_CLEANUP_WAIT:
+ break;
+ default:
+ log_warnx("It can only be attributable to human error.");
+ return -1;
+ }
+
+ TAILQ_FOREACH(c, &s->connections, entry) {
+ if (c->state & CONN_FAILED) {
+ state = SESS_FAILED;
+ break;
+ } else if (c->state & CONN_RUNNING)
+ state = SESS_LOGGED_IN;
+ }
+
+ return state;
+}
+
+int
+sess_do_conn_closed(struct session *s, struct sessev *sev)
+{
+ struct connection *c = sev->conn;
+ int state = SESS_FREE;
+
+ if (c == NULL || c->state != CONN_FREE) {
+ log_warnx("Just what do you think you're doing, Dave?");
+ return -1;
+ }
+ conn_free(c);
+
+ TAILQ_FOREACH(c, &s->connections, entry) {
+ if (c->state & CONN_FAILED) {
+ state = SESS_FAILED;
+ break;
+ } else if (c->state & CONN_RUNNING)
+ state = SESS_LOGGED_IN;
+ }
+
+ return state;
+}
+
+int
+sess_do_down(struct session *s, struct sessev *sev)
+{
+ struct connection *c;
+
+ while ((c = TAILQ_FIRST(&s->connections)) != NULL)
+ conn_free(c);
+
+ /* XXX anything else to reset to initial state? */
+
+ return SESS_DOWN;
}
const char *
@@ -253,6 +387,8 @@ sess_state(int s)
return "LOGGED_IN";
case SESS_FAILED:
return "FAILED";
+ case SESS_DOWN:
+ return "DOWN";
default:
snprintf(buf, sizeof(buf), "UKNWN %x", s);
return buf;
@@ -268,10 +404,14 @@ sess_event(enum s_event e)
switch (e) {
case SESS_EV_START:
return "start";
+ case SESS_EV_CONN_LOGGED_IN:
+ return "connection logged in";
case SESS_EV_CONN_FAIL:
return "connection fail";
case SESS_EV_CONN_CLOSED:
return "connection closed";
+ case SESS_EV_CLOSED:
+ return "session closed";
case SESS_EV_FAIL:
return "fail";
}