1613a2f6bSGordon Ross /*
2613a2f6bSGordon Ross * CDDL HEADER START
3613a2f6bSGordon Ross *
4613a2f6bSGordon Ross * The contents of this file are subject to the terms of the
5613a2f6bSGordon Ross * Common Development and Distribution License (the "License").
6613a2f6bSGordon Ross * You may not use this file except in compliance with the License.
7613a2f6bSGordon Ross *
8613a2f6bSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9613a2f6bSGordon Ross * or http://www.opensolaris.org/os/licensing.
10613a2f6bSGordon Ross * See the License for the specific language governing permissions
11613a2f6bSGordon Ross * and limitations under the License.
12613a2f6bSGordon Ross *
13613a2f6bSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
14613a2f6bSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15613a2f6bSGordon Ross * If applicable, add the following below this CDDL HEADER, with the
16613a2f6bSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
17613a2f6bSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
18613a2f6bSGordon Ross *
19613a2f6bSGordon Ross * CDDL HEADER END
20613a2f6bSGordon Ross */
21613a2f6bSGordon Ross
22613a2f6bSGordon Ross /*
23613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24613a2f6bSGordon Ross * Use is subject to license terms.
2540c0e231SGordon Ross *
2640c0e231SGordon Ross * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
27613a2f6bSGordon Ross */
28613a2f6bSGordon Ross
29613a2f6bSGordon Ross /*
30613a2f6bSGordon Ross * Functions called by the IO deamon (IOD).
31613a2f6bSGordon Ross * Here in the library to simplify testing.
32613a2f6bSGordon Ross */
33613a2f6bSGordon Ross
34613a2f6bSGordon Ross #include <errno.h>
35613a2f6bSGordon Ross #include <fcntl.h>
36613a2f6bSGordon Ross #include <stdio.h>
37613a2f6bSGordon Ross #include <string.h>
38613a2f6bSGordon Ross #include <stdlib.h>
39613a2f6bSGordon Ross #include <unistd.h>
40613a2f6bSGordon Ross #include <libintl.h>
41613a2f6bSGordon Ross
42613a2f6bSGordon Ross #include <sys/byteorder.h>
43613a2f6bSGordon Ross #include <sys/types.h>
44613a2f6bSGordon Ross #include <sys/fcntl.h>
45613a2f6bSGordon Ross #include <sys/ioctl.h>
46613a2f6bSGordon Ross #include <sys/time.h>
47613a2f6bSGordon Ross #include <sys/socket.h>
48613a2f6bSGordon Ross
49613a2f6bSGordon Ross #include <netinet/in.h>
50613a2f6bSGordon Ross #include <netinet/tcp.h>
51613a2f6bSGordon Ross #include <arpa/inet.h>
52613a2f6bSGordon Ross
53613a2f6bSGordon Ross #include <netsmb/smb.h>
54613a2f6bSGordon Ross #include <netsmb/smb_lib.h>
55613a2f6bSGordon Ross #include <netsmb/netbios.h>
56613a2f6bSGordon Ross #include <netsmb/nb_lib.h>
57613a2f6bSGordon Ross #include <netsmb/smb_dev.h>
58613a2f6bSGordon Ross
59613a2f6bSGordon Ross #include "charsets.h"
60613a2f6bSGordon Ross #include "private.h"
61613a2f6bSGordon Ross
62613a2f6bSGordon Ross /*
6340c0e231SGordon Ross * The user agent (smbiod) calls smb_iod_connect for the first
6440c0e231SGordon Ross * connection to some server, and if that succeeds, will start a
6540c0e231SGordon Ross * thread running this function, passing the smb_ctx_t
6640c0e231SGordon Ross *
6740c0e231SGordon Ross * This thread now enters the driver and stays there, reading
6840c0e231SGordon Ross * network responses as long as the connection is alive.
69613a2f6bSGordon Ross */
70613a2f6bSGordon Ross int
smb_iod_work(smb_ctx_t * ctx)71613a2f6bSGordon Ross smb_iod_work(smb_ctx_t *ctx)
72613a2f6bSGordon Ross {
73613a2f6bSGordon Ross smbioc_ssn_work_t *work = &ctx->ct_work;
7440c0e231SGordon Ross int err = 0;
75613a2f6bSGordon Ross
76613a2f6bSGordon Ross DPRINT("server: %s", ctx->ct_srvname);
77613a2f6bSGordon Ross
78613a2f6bSGordon Ross /*
79613a2f6bSGordon Ross * This is the reader / reconnect loop.
80613a2f6bSGordon Ross *
81613a2f6bSGordon Ross * We could start with state "idle", but
82613a2f6bSGordon Ross * we know someone wants a connection to
83613a2f6bSGordon Ross * this server, so start in "vcactive".
84613a2f6bSGordon Ross *
85613a2f6bSGordon Ross * XXX: Add some syslog calls in here?
86613a2f6bSGordon Ross */
87613a2f6bSGordon Ross
88613a2f6bSGordon Ross for (;;) {
89613a2f6bSGordon Ross
9040c0e231SGordon Ross DPRINT("state: %s",
9140c0e231SGordon Ross smb_iod_state_name(work->wk_out_state));
9240c0e231SGordon Ross
9340c0e231SGordon Ross switch (work->wk_out_state) {
94613a2f6bSGordon Ross case SMBIOD_ST_IDLE:
95613a2f6bSGordon Ross /*
96613a2f6bSGordon Ross * Wait for driver requests to arrive
97613a2f6bSGordon Ross * for this VC, then return here.
98613a2f6bSGordon Ross * Next state is normally RECONNECT.
99613a2f6bSGordon Ross */
10040c0e231SGordon Ross DPRINT("Call _ioc_idle...");
1018329232eSGordon Ross if (nsmb_ioctl(ctx->ct_dev_fd,
10240c0e231SGordon Ross SMBIOC_IOD_IDLE, work) == -1) {
103613a2f6bSGordon Ross err = errno;
104613a2f6bSGordon Ross DPRINT("ioc_idle: err %d", err);
105613a2f6bSGordon Ross goto out;
106613a2f6bSGordon Ross }
107*adee6784SGordon Ross DPRINT("Ret. from _ioc_idle");
108613a2f6bSGordon Ross continue;
109613a2f6bSGordon Ross
110613a2f6bSGordon Ross case SMBIOD_ST_RECONNECT:
11140c0e231SGordon Ross DPRINT("Call _iod_connect...");
112613a2f6bSGordon Ross err = smb_iod_connect(ctx);
11340c0e231SGordon Ross if (err == 0)
114613a2f6bSGordon Ross continue;
11540c0e231SGordon Ross DPRINT("iod_connect: err %d", err);
116613a2f6bSGordon Ross /*
117613a2f6bSGordon Ross * If the error was EAUTH, retry is
118613a2f6bSGordon Ross * not likely to succeed either, so
119613a2f6bSGordon Ross * just exit this thread. The user
120613a2f6bSGordon Ross * will need to run smbutil to get
121613a2f6bSGordon Ross * a new thread with new auth info.
122613a2f6bSGordon Ross */
123*adee6784SGordon Ross if (err == EAUTH) {
124*adee6784SGordon Ross DPRINT("iod_connect: EAUTH (give up)");
125613a2f6bSGordon Ross goto out;
126*adee6784SGordon Ross }
127613a2f6bSGordon Ross /*
128*adee6784SGordon Ross * Reconnect failed. Notify any requests
129*adee6784SGordon Ross * that we're not connected, and delay.
130*adee6784SGordon Ross * Next state will be IDLE or RECONNECT.
131613a2f6bSGordon Ross */
13240c0e231SGordon Ross DPRINT("Call _iod_rcfail...");
1338329232eSGordon Ross if (nsmb_ioctl(ctx->ct_dev_fd,
13440c0e231SGordon Ross SMBIOC_IOD_RCFAIL, work) == -1) {
135613a2f6bSGordon Ross err = errno;
13640c0e231SGordon Ross DPRINT("iod_rcfail: err %d", err);
137613a2f6bSGordon Ross goto out;
138613a2f6bSGordon Ross }
139613a2f6bSGordon Ross continue;
140613a2f6bSGordon Ross
14140c0e231SGordon Ross case SMBIOD_ST_AUTHOK:
14240c0e231SGordon Ross /*
14340c0e231SGordon Ross * This is where we enter the driver and
14440c0e231SGordon Ross * stay there. While the connection is up
14540c0e231SGordon Ross * the VC will have SMBIOD_ST_VCACTIVE
14640c0e231SGordon Ross */
14740c0e231SGordon Ross DPRINT("Call _iod_work...");
1488329232eSGordon Ross if (nsmb_ioctl(ctx->ct_dev_fd,
149613a2f6bSGordon Ross SMBIOC_IOD_WORK, work) == -1) {
150613a2f6bSGordon Ross err = errno;
15140c0e231SGordon Ross DPRINT("iod_work: err %d", err);
152613a2f6bSGordon Ross goto out;
153613a2f6bSGordon Ross }
154*adee6784SGordon Ross DPRINT("Ret. from _ioc_work");
155613a2f6bSGordon Ross continue;
156613a2f6bSGordon Ross
157613a2f6bSGordon Ross case SMBIOD_ST_DEAD:
158*adee6784SGordon Ross DPRINT("got state=DEAD");
159613a2f6bSGordon Ross err = 0;
160613a2f6bSGordon Ross goto out;
161613a2f6bSGordon Ross
162613a2f6bSGordon Ross default:
16340c0e231SGordon Ross DPRINT("Unexpected state: %d (%s)",
16440c0e231SGordon Ross work->wk_out_state,
16540c0e231SGordon Ross smb_iod_state_name(work->wk_out_state));
166613a2f6bSGordon Ross err = EFAULT;
167613a2f6bSGordon Ross goto out;
168613a2f6bSGordon Ross }
169613a2f6bSGordon Ross }
170613a2f6bSGordon Ross
171613a2f6bSGordon Ross out:
172613a2f6bSGordon Ross if (ctx->ct_dev_fd != -1) {
1738329232eSGordon Ross nsmb_close(ctx->ct_dev_fd);
174613a2f6bSGordon Ross ctx->ct_dev_fd = -1;
175613a2f6bSGordon Ross }
176613a2f6bSGordon Ross
177613a2f6bSGordon Ross return (err);
178613a2f6bSGordon Ross }
179