1*fcd50198Smbuhl /* $OpenBSD: iscsictl.c,v 1.13 2023/02/21 15:45:40 mbuhl Exp $ */
2208af722Sclaudio
3208af722Sclaudio /*
4208af722Sclaudio * Copyright (c) 2010 Claudio Jeker <claudio@openbsd.org>
5208af722Sclaudio *
6208af722Sclaudio * Permission to use, copy, modify, and distribute this software for any
7208af722Sclaudio * purpose with or without fee is hereby granted, provided that the above
8208af722Sclaudio * copyright notice and this permission notice appear in all copies.
9208af722Sclaudio *
10208af722Sclaudio * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11208af722Sclaudio * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12208af722Sclaudio * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13208af722Sclaudio * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14208af722Sclaudio * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15208af722Sclaudio * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16208af722Sclaudio * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17208af722Sclaudio */
18208af722Sclaudio
19208af722Sclaudio #include <sys/queue.h>
20208af722Sclaudio #include <sys/socket.h>
21208af722Sclaudio #include <sys/uio.h>
22208af722Sclaudio #include <sys/un.h>
23208af722Sclaudio
24208af722Sclaudio #include <event.h>
25208af722Sclaudio #include <err.h>
26208af722Sclaudio #include <errno.h>
27208af722Sclaudio #include <stdio.h>
28208af722Sclaudio #include <stdlib.h>
29208af722Sclaudio #include <string.h>
30208af722Sclaudio #include <unistd.h>
312fe39d32Sclaudio #include <util.h>
32208af722Sclaudio
33208af722Sclaudio #include "iscsid.h"
34208af722Sclaudio #include "iscsictl.h"
35208af722Sclaudio
36208af722Sclaudio __dead void usage(void);
37d9ff5473Sclaudio void run(void);
38d9ff5473Sclaudio void run_command(struct pdu *);
39208af722Sclaudio struct pdu *ctl_getpdu(char *, size_t);
40208af722Sclaudio int ctl_sendpdu(int, struct pdu *);
41d9ff5473Sclaudio void show_config(struct ctrlmsghdr *, struct pdu *);
42cf4672e7Sclaudio void show_vscsi_stats(struct ctrlmsghdr *, struct pdu *);
432f8c4829Sclaudio void poll_and_wait(void);
442f8c4829Sclaudio void poll_session_status(void);
452f8c4829Sclaudio void register_poll(struct ctrlmsghdr *, struct pdu *);
462f8c4829Sclaudio void poll_print(struct session_poll *);
47208af722Sclaudio
48208af722Sclaudio char cbuf[CONTROL_READ_SIZE];
49208af722Sclaudio
50d9ff5473Sclaudio struct control {
51d9ff5473Sclaudio struct pduq channel;
52d9ff5473Sclaudio int fd;
53d9ff5473Sclaudio } control;
54d9ff5473Sclaudio
552f8c4829Sclaudio
562f8c4829Sclaudio struct session_poll poll_result;
572f8c4829Sclaudio #define POLL_DELAY_SEC 1
582f8c4829Sclaudio #define POLL_ATTEMPTS 10
592f8c4829Sclaudio
60208af722Sclaudio __dead void
usage(void)61208af722Sclaudio usage(void)
62208af722Sclaudio {
63208af722Sclaudio extern char *__progname;
64208af722Sclaudio
65208af722Sclaudio fprintf(stderr,"usage: %s [-s socket] command [argument ...]\n",
66208af722Sclaudio __progname);
67208af722Sclaudio exit(1);
68208af722Sclaudio }
69208af722Sclaudio
70208af722Sclaudio int
main(int argc,char * argv[])71208af722Sclaudio main (int argc, char* argv[])
72208af722Sclaudio {
73208af722Sclaudio struct sockaddr_un sun;
74d9ff5473Sclaudio struct session_config sc;
75208af722Sclaudio struct parse_result *res;
76208af722Sclaudio char *confname = ISCSID_CONFIG;
77208af722Sclaudio char *sockname = ISCSID_CONTROL;
78208af722Sclaudio struct session_ctlcfg *s;
79208af722Sclaudio struct iscsi_config *cf;
802f8c4829Sclaudio int ch, poll = 0, val = 0;
81208af722Sclaudio
82208af722Sclaudio /* check flags */
83208af722Sclaudio while ((ch = getopt(argc, argv, "f:s:")) != -1) {
84208af722Sclaudio switch (ch) {
85208af722Sclaudio case 'f':
86208af722Sclaudio confname = optarg;
87208af722Sclaudio break;
88208af722Sclaudio case 's':
89208af722Sclaudio sockname = optarg;
90208af722Sclaudio break;
91208af722Sclaudio default:
92208af722Sclaudio usage();
93208af722Sclaudio /* NOTREACHED */
94208af722Sclaudio }
95208af722Sclaudio }
96208af722Sclaudio argc -= optind;
97208af722Sclaudio argv += optind;
98208af722Sclaudio
99208af722Sclaudio /* parse options */
100208af722Sclaudio if ((res = parse(argc, argv)) == NULL)
101208af722Sclaudio exit(1);
102208af722Sclaudio
103761f0b52Sgsoares /* connect to iscsid control socket */
104d9ff5473Sclaudio TAILQ_INIT(&control.channel);
105d9ff5473Sclaudio if ((control.fd = socket(AF_UNIX, SOCK_SEQPACKET, 0)) == -1)
106208af722Sclaudio err(1, "socket");
107208af722Sclaudio
108208af722Sclaudio bzero(&sun, sizeof(sun));
109208af722Sclaudio sun.sun_family = AF_UNIX;
110208af722Sclaudio strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path));
111208af722Sclaudio
112d9ff5473Sclaudio if (connect(control.fd, (struct sockaddr *)&sun, sizeof(sun)) == -1)
113208af722Sclaudio err(1, "connect: %s", sockname);
114208af722Sclaudio
115ed720fabSderaadt if (pledge("stdio rpath dns", NULL) == -1)
116ed720fabSderaadt err(1, "pledge");
117ed720fabSderaadt
118208af722Sclaudio switch (res->action) {
119208af722Sclaudio case NONE:
120208af722Sclaudio case LOG_VERBOSE:
1213471b912Sclaudio val = 1;
1223471b912Sclaudio /* FALLTHROUGH */
123208af722Sclaudio case LOG_BRIEF:
124d9ff5473Sclaudio if (control_compose(NULL, CTRL_LOG_VERBOSE,
125d9ff5473Sclaudio &val, sizeof(int)) == -1)
126d9ff5473Sclaudio err(1, "control_compose");
1273471b912Sclaudio break;
128208af722Sclaudio case SHOW_SUM:
129d9ff5473Sclaudio if (control_compose(NULL, CTRL_SHOW_SUM, NULL, 0) == -1)
130d9ff5473Sclaudio err(1, "control_compose");
131d9ff5473Sclaudio break;
132d9ff5473Sclaudio case SHOW_SESS:
133208af722Sclaudio usage();
134208af722Sclaudio /* NOTREACHED */
135cf4672e7Sclaudio case SHOW_VSCSI_STATS:
136d9ff5473Sclaudio if (control_compose(NULL, CTRL_VSCSI_STATS, NULL, 0) == -1)
137d9ff5473Sclaudio err(1, "control_compose");
138cf4672e7Sclaudio break;
139208af722Sclaudio case RELOAD:
140208af722Sclaudio if ((cf = parse_config(confname)) == NULL)
141208af722Sclaudio errx(1, "errors while loading configuration file.");
1423471b912Sclaudio if (cf->initiator.isid_base != 0) {
143d9ff5473Sclaudio if (control_compose(NULL, CTRL_INITIATOR_CONFIG,
144d9ff5473Sclaudio &cf->initiator, sizeof(cf->initiator)) == -1)
145d9ff5473Sclaudio err(1, "control_compose");
1463471b912Sclaudio }
1472f8c4829Sclaudio
148208af722Sclaudio SIMPLEQ_FOREACH(s, &cf->sessions, entry) {
149d9ff5473Sclaudio struct ctrldata cdv[3];
150d9ff5473Sclaudio bzero(cdv, sizeof(cdv));
151d9ff5473Sclaudio
152d9ff5473Sclaudio cdv[0].buf = &s->session;
153d9ff5473Sclaudio cdv[0].len = sizeof(s->session);
154d9ff5473Sclaudio
155d9ff5473Sclaudio if (s->session.TargetName) {
156d9ff5473Sclaudio cdv[1].buf = s->session.TargetName;
157d9ff5473Sclaudio cdv[1].len =
158d9ff5473Sclaudio strlen(s->session.TargetName) + 1;
159d9ff5473Sclaudio }
160d9ff5473Sclaudio if (s->session.InitiatorName) {
161d9ff5473Sclaudio cdv[2].buf = s->session.InitiatorName;
162d9ff5473Sclaudio cdv[2].len =
163d9ff5473Sclaudio strlen(s->session.InitiatorName) + 1;
164d9ff5473Sclaudio }
165d9ff5473Sclaudio
166d9ff5473Sclaudio if (control_build(NULL, CTRL_SESSION_CONFIG,
167d9ff5473Sclaudio nitems(cdv), cdv) == -1)
168d9ff5473Sclaudio err(1, "control_build");
169208af722Sclaudio }
1702f8c4829Sclaudio
1712f8c4829Sclaudio /* Reloading, so poll for connection establishment. */
1722f8c4829Sclaudio poll = 1;
173208af722Sclaudio break;
174208af722Sclaudio case DISCOVERY:
175208af722Sclaudio printf("discover %s\n", log_sockaddr(&res->addr));
176208af722Sclaudio
177d9ff5473Sclaudio bzero(&sc, sizeof(sc));
178d9ff5473Sclaudio snprintf(sc.SessionName, sizeof(sc.SessionName),
179d9ff5473Sclaudio "discovery.%d", (int)getpid());
180d9ff5473Sclaudio bcopy(&res->addr, &sc.connection.TargetAddr, res->addr.ss_len);
181d9ff5473Sclaudio sc.SessionType = SESSION_TYPE_DISCOVERY;
182d9ff5473Sclaudio
183d9ff5473Sclaudio if (control_compose(NULL, CTRL_SESSION_CONFIG,
184d9ff5473Sclaudio &sc, sizeof(sc)) == -1)
185d9ff5473Sclaudio err(1, "control_compose");
186208af722Sclaudio }
187208af722Sclaudio
188d9ff5473Sclaudio run();
189d9ff5473Sclaudio
1902f8c4829Sclaudio if (poll)
1912f8c4829Sclaudio poll_and_wait();
192208af722Sclaudio
1932f8c4829Sclaudio close(control.fd);
194208af722Sclaudio return (0);
195208af722Sclaudio }
196208af722Sclaudio
197208af722Sclaudio void
control_queue(void * ch,struct pdu * pdu)198d9ff5473Sclaudio control_queue(void *ch, struct pdu *pdu)
199d9ff5473Sclaudio {
200d9ff5473Sclaudio TAILQ_INSERT_TAIL(&control.channel, pdu, entry);
201d9ff5473Sclaudio }
202d9ff5473Sclaudio
203d9ff5473Sclaudio void
run(void)204d9ff5473Sclaudio run(void)
205d9ff5473Sclaudio {
206d9ff5473Sclaudio struct pdu *pdu;
207d9ff5473Sclaudio
208d9ff5473Sclaudio while ((pdu = TAILQ_FIRST(&control.channel)) != NULL) {
209d9ff5473Sclaudio TAILQ_REMOVE(&control.channel, pdu, entry);
210d9ff5473Sclaudio run_command(pdu);
211d9ff5473Sclaudio }
212d9ff5473Sclaudio }
213d9ff5473Sclaudio
214d9ff5473Sclaudio void
run_command(struct pdu * pdu)215d9ff5473Sclaudio run_command(struct pdu *pdu)
216208af722Sclaudio {
217208af722Sclaudio struct ctrlmsghdr *cmh;
218208af722Sclaudio int done = 0;
219208af722Sclaudio ssize_t n;
220208af722Sclaudio
221d9ff5473Sclaudio if (ctl_sendpdu(control.fd, pdu) == -1)
222208af722Sclaudio err(1, "send");
223208af722Sclaudio while (!done) {
224d9ff5473Sclaudio if ((n = recv(control.fd, cbuf, sizeof(cbuf), 0)) == -1 &&
225208af722Sclaudio !(errno == EAGAIN || errno == EINTR))
226208af722Sclaudio err(1, "recv");
227208af722Sclaudio
228208af722Sclaudio if (n == 0)
229208af722Sclaudio errx(1, "connection to iscsid closed");
230208af722Sclaudio
231208af722Sclaudio pdu = ctl_getpdu(cbuf, n);
232208af722Sclaudio cmh = pdu_getbuf(pdu, NULL, 0);
233208af722Sclaudio if (cmh == NULL)
234208af722Sclaudio break;
235208af722Sclaudio switch (cmh->type) {
236208af722Sclaudio case CTRL_SUCCESS:
237208af722Sclaudio printf("command successful\n");
238208af722Sclaudio done = 1;
239208af722Sclaudio break;
240208af722Sclaudio case CTRL_FAILURE:
241208af722Sclaudio printf("command failed\n");
242208af722Sclaudio done = 1;
243208af722Sclaudio break;
2443471b912Sclaudio case CTRL_INPROGRESS:
2453471b912Sclaudio printf("command in progress...\n");
2463471b912Sclaudio break;
247d9ff5473Sclaudio case CTRL_INITIATOR_CONFIG:
248d9ff5473Sclaudio case CTRL_SESSION_CONFIG:
249d9ff5473Sclaudio show_config(cmh, pdu);
250d9ff5473Sclaudio break;
251cf4672e7Sclaudio case CTRL_VSCSI_STATS:
252cf4672e7Sclaudio show_vscsi_stats(cmh, pdu);
253cf4672e7Sclaudio done = 1;
254cf4672e7Sclaudio break;
2552f8c4829Sclaudio case CTRL_SESS_POLL:
2562f8c4829Sclaudio register_poll(cmh, pdu);
2572f8c4829Sclaudio done = 1;
2582f8c4829Sclaudio break;
2592f8c4829Sclaudio
260208af722Sclaudio }
261208af722Sclaudio }
262208af722Sclaudio }
263208af722Sclaudio
264208af722Sclaudio struct pdu *
ctl_getpdu(char * buf,size_t len)265208af722Sclaudio ctl_getpdu(char *buf, size_t len)
266208af722Sclaudio {
267208af722Sclaudio struct pdu *p;
268208af722Sclaudio struct ctrlmsghdr *cmh;
269208af722Sclaudio void *data;
270208af722Sclaudio size_t n;
271208af722Sclaudio int i;
272208af722Sclaudio
273208af722Sclaudio if (len < sizeof(*cmh))
274208af722Sclaudio return NULL;
275208af722Sclaudio
276208af722Sclaudio if (!(p = pdu_new()))
277208af722Sclaudio return NULL;
278208af722Sclaudio
279208af722Sclaudio n = sizeof(*cmh);
280208af722Sclaudio cmh = pdu_alloc(n);
281208af722Sclaudio bcopy(buf, cmh, n);
282208af722Sclaudio buf += n;
283208af722Sclaudio len -= n;
284208af722Sclaudio
285208af722Sclaudio if (pdu_addbuf(p, cmh, n, 0)) {
286208af722Sclaudio free(cmh);
287208af722Sclaudio fail:
288208af722Sclaudio pdu_free(p);
289208af722Sclaudio return NULL;
290208af722Sclaudio }
291208af722Sclaudio
292208af722Sclaudio for (i = 0; i < 3; i++) {
293208af722Sclaudio n = cmh->len[i];
294208af722Sclaudio if (n == 0)
295208af722Sclaudio continue;
296208af722Sclaudio if (PDU_LEN(n) > len)
297208af722Sclaudio goto fail;
298208af722Sclaudio if (!(data = pdu_alloc(n)))
299208af722Sclaudio goto fail;
300208af722Sclaudio bcopy(buf, data, n);
301208af722Sclaudio if (pdu_addbuf(p, data, n, i + 1)) {
302208af722Sclaudio free(data);
303208af722Sclaudio goto fail;
304208af722Sclaudio }
305208af722Sclaudio buf += PDU_LEN(n);
306208af722Sclaudio len -= PDU_LEN(n);
307208af722Sclaudio }
308208af722Sclaudio
309208af722Sclaudio return p;
310208af722Sclaudio }
311208af722Sclaudio
312208af722Sclaudio int
ctl_sendpdu(int fd,struct pdu * pdu)313208af722Sclaudio ctl_sendpdu(int fd, struct pdu *pdu)
314208af722Sclaudio {
315208af722Sclaudio struct iovec iov[PDU_MAXIOV];
316208af722Sclaudio struct msghdr msg;
317208af722Sclaudio unsigned int niov = 0;
318208af722Sclaudio
319208af722Sclaudio for (niov = 0; niov < PDU_MAXIOV; niov++) {
320208af722Sclaudio iov[niov].iov_base = pdu->iov[niov].iov_base;
321208af722Sclaudio iov[niov].iov_len = pdu->iov[niov].iov_len;
322208af722Sclaudio }
323208af722Sclaudio bzero(&msg, sizeof(msg));
324208af722Sclaudio msg.msg_iov = iov;
325208af722Sclaudio msg.msg_iovlen = niov;
326208af722Sclaudio if (sendmsg(fd, &msg, 0) == -1)
327208af722Sclaudio return -1;
328208af722Sclaudio return 0;
329208af722Sclaudio }
330cf4672e7Sclaudio
331cf4672e7Sclaudio void
show_config(struct ctrlmsghdr * cmh,struct pdu * pdu)332d9ff5473Sclaudio show_config(struct ctrlmsghdr *cmh, struct pdu *pdu)
333d9ff5473Sclaudio {
334d9ff5473Sclaudio struct initiator_config *ic;
335d9ff5473Sclaudio struct session_config *sc;
3360ffafa02Sclaudio char *name;
337d9ff5473Sclaudio
338d9ff5473Sclaudio switch (cmh->type) {
339d9ff5473Sclaudio case CTRL_INITIATOR_CONFIG:
340d9ff5473Sclaudio if (cmh->len[0] != sizeof(*ic))
341d9ff5473Sclaudio errx(1, "bad size of response");
342d9ff5473Sclaudio ic = pdu_getbuf(pdu, NULL, 1);
343d9ff5473Sclaudio if (ic == NULL)
344d9ff5473Sclaudio return;
345d9ff5473Sclaudio
346*fcd50198Smbuhl printf("Initiator: ISID base %x qualifier %hx\n",
347d9ff5473Sclaudio ic->isid_base, ic->isid_qual);
348d9ff5473Sclaudio break;
349d9ff5473Sclaudio case CTRL_SESSION_CONFIG:
350d9ff5473Sclaudio if (cmh->len[0] != sizeof(*sc))
351d9ff5473Sclaudio errx(1, "bad size of response");
352d9ff5473Sclaudio sc = pdu_getbuf(pdu, NULL, 1);
353d9ff5473Sclaudio if (sc == NULL)
354d9ff5473Sclaudio return;
355d9ff5473Sclaudio
356d9ff5473Sclaudio printf("\nSession '%s':%s\n", sc->SessionName,
357d9ff5473Sclaudio sc->disabled ? " disabled" : "");
358d9ff5473Sclaudio printf(" SessionType: %s\tMaxConnections: %hd\n",
359d9ff5473Sclaudio sc->SessionType == SESSION_TYPE_DISCOVERY ? "discovery" :
360d9ff5473Sclaudio "normal", sc->MaxConnections);
3610ffafa02Sclaudio if ((name = pdu_getbuf(pdu, NULL, 2)))
3620ffafa02Sclaudio printf(" TargetName: %s\n", name);
363d9ff5473Sclaudio printf(" TargetAddr: %s\n",
364d9ff5473Sclaudio log_sockaddr(&sc->connection.TargetAddr));
3650ffafa02Sclaudio if ((name = pdu_getbuf(pdu, NULL, 3)))
3660ffafa02Sclaudio printf(" InitiatorName: %s\n", name);
3670ffafa02Sclaudio printf(" InitiatorAddr: %s\n",
3680ffafa02Sclaudio log_sockaddr(&sc->connection.LocalAddr));
369d9ff5473Sclaudio break;
370d9ff5473Sclaudio }
371d9ff5473Sclaudio }
372d9ff5473Sclaudio
373d9ff5473Sclaudio void
show_vscsi_stats(struct ctrlmsghdr * cmh,struct pdu * pdu)374cf4672e7Sclaudio show_vscsi_stats(struct ctrlmsghdr *cmh, struct pdu *pdu)
375cf4672e7Sclaudio {
376cf4672e7Sclaudio struct vscsi_stats *vs;
3772fe39d32Sclaudio char buf[FMT_SCALED_STRSIZE];
378cf4672e7Sclaudio
379cf4672e7Sclaudio if (cmh->len[0] != sizeof(struct vscsi_stats))
380cf4672e7Sclaudio errx(1, "bad size of response");
381cf4672e7Sclaudio vs = pdu_getbuf(pdu, NULL, 1);
382cf4672e7Sclaudio if (vs == NULL)
383cf4672e7Sclaudio return;
384cf4672e7Sclaudio
385cf4672e7Sclaudio printf("VSCSI ioctl statistics:\n");
386cf4672e7Sclaudio printf("%u probe calls and %u detach calls\n",
387cf4672e7Sclaudio vs->cnt_probe, vs->cnt_detach);
388cf4672e7Sclaudio printf("%llu I2T calls (%llu read, %llu writes)\n",
389cf4672e7Sclaudio vs->cnt_i2t,
390cf4672e7Sclaudio vs->cnt_i2t_dir[1],
391cf4672e7Sclaudio vs->cnt_i2t_dir[2]);
392cf4672e7Sclaudio
3932fe39d32Sclaudio if (fmt_scaled(vs->bytes_rd, buf) != 0)
3942fe39d32Sclaudio (void)strlcpy(buf, "NaN", sizeof(buf));
3952fe39d32Sclaudio printf("%llu data reads (%s bytes read)\n", vs->cnt_read, buf);
3962fe39d32Sclaudio if (fmt_scaled(vs->bytes_wr, buf) != 0)
3972fe39d32Sclaudio (void)strlcpy(buf, "NaN", sizeof(buf));
3982fe39d32Sclaudio printf("%llu data writes (%s bytes written)\n", vs->cnt_write, buf);
399cf4672e7Sclaudio
400cf4672e7Sclaudio printf("%llu T2I calls (%llu done, %llu sense errors, %llu errors)\n",
401cf4672e7Sclaudio vs->cnt_t2i,
402cf4672e7Sclaudio vs->cnt_t2i_status[0],
403cf4672e7Sclaudio vs->cnt_t2i_status[1],
404cf4672e7Sclaudio vs->cnt_t2i_status[2]);
405cf4672e7Sclaudio }
4062f8c4829Sclaudio
4072f8c4829Sclaudio void
poll_session_status(void)4082f8c4829Sclaudio poll_session_status(void)
4092f8c4829Sclaudio {
4102f8c4829Sclaudio struct pdu *pdu;
4112f8c4829Sclaudio
4122f8c4829Sclaudio if (control_compose(NULL, CTRL_SESS_POLL, NULL, 0) == -1)
4132f8c4829Sclaudio err(1, "control_compose");
4142f8c4829Sclaudio
4152f8c4829Sclaudio while ((pdu = TAILQ_FIRST(&control.channel)) != NULL) {
4162f8c4829Sclaudio TAILQ_REMOVE(&control.channel, pdu, entry);
4172f8c4829Sclaudio run_command(pdu);
4182f8c4829Sclaudio }
4192f8c4829Sclaudio }
4202f8c4829Sclaudio
4212f8c4829Sclaudio void
poll_and_wait(void)4222f8c4829Sclaudio poll_and_wait(void)
4232f8c4829Sclaudio {
4242f8c4829Sclaudio int attempts;
4252f8c4829Sclaudio
4262f8c4829Sclaudio printf("waiting for config to settle..");
4272f8c4829Sclaudio fflush(stdout);
4282f8c4829Sclaudio
4292f8c4829Sclaudio for (attempts = 0; attempts < POLL_ATTEMPTS; attempts++) {
4302f8c4829Sclaudio
4312f8c4829Sclaudio poll_session_status();
4322f8c4829Sclaudio
4332f8c4829Sclaudio /* Poll says we are good to go. */
4342f8c4829Sclaudio if (poll_result.sess_conn_status != 0) {
4352f8c4829Sclaudio printf("ok\n");
4362f8c4829Sclaudio /* wait a bit longer so all is settled. */
4372f8c4829Sclaudio sleep(POLL_DELAY_SEC);
4382f8c4829Sclaudio return;
4392f8c4829Sclaudio }
4402f8c4829Sclaudio
4412f8c4829Sclaudio /* Poll says we should wait... */
4422f8c4829Sclaudio printf(".");
4432f8c4829Sclaudio fflush(stdout);
4442f8c4829Sclaudio sleep(POLL_DELAY_SEC);
4452f8c4829Sclaudio }
4462f8c4829Sclaudio
4472f8c4829Sclaudio printf("giving up.\n");
4482f8c4829Sclaudio
4492f8c4829Sclaudio poll_print(&poll_result);
4502f8c4829Sclaudio }
4512f8c4829Sclaudio
4522f8c4829Sclaudio void
register_poll(struct ctrlmsghdr * cmh,struct pdu * pdu)4532f8c4829Sclaudio register_poll(struct ctrlmsghdr *cmh, struct pdu *pdu)
4542f8c4829Sclaudio {
4552f8c4829Sclaudio if (cmh->len[0] != sizeof(poll_result))
4562f8c4829Sclaudio errx(1, "poll: bad size of response");
4572f8c4829Sclaudio
4582f8c4829Sclaudio poll_result = *((struct session_poll *)pdu_getbuf(pdu, NULL, 1));
4592f8c4829Sclaudio }
4602f8c4829Sclaudio
4612f8c4829Sclaudio void
poll_print(struct session_poll * p)4622f8c4829Sclaudio poll_print(struct session_poll *p)
4632f8c4829Sclaudio {
4642f8c4829Sclaudio printf("Configured sessions: %d\n", p->session_count);
4652f8c4829Sclaudio printf("Sessions initializing: %d\n", p->session_init_count);
4662f8c4829Sclaudio printf("Sessions started/failed: %d\n", p->session_running_count);
4672f8c4829Sclaudio printf("Sessions logged in: %d\n", p->conn_logged_in_count);
4682f8c4829Sclaudio printf("Sessions with failed connections: %d\n", p->conn_failed_count);
4692f8c4829Sclaudio printf("Sessions still attempting to connect: %d\n",
4702f8c4829Sclaudio p->conn_waiting_count);
4712f8c4829Sclaudio }
472