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 /*
23*3d804dabSGordon Ross * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
24613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25613a2f6bSGordon Ross * Use is subject to license terms.
26613a2f6bSGordon Ross */
27613a2f6bSGordon Ross
28613a2f6bSGordon Ross /*
29613a2f6bSGordon Ross * Functions called by the IO deamon (IOD).
30613a2f6bSGordon Ross * Here in the library to simplify testing.
31613a2f6bSGordon Ross */
32613a2f6bSGordon Ross
33613a2f6bSGordon Ross #include <errno.h>
34613a2f6bSGordon Ross #include <fcntl.h>
35613a2f6bSGordon Ross #include <stdio.h>
36613a2f6bSGordon Ross #include <string.h>
37613a2f6bSGordon Ross #include <stdlib.h>
38613a2f6bSGordon Ross #include <unistd.h>
39613a2f6bSGordon Ross #include <libintl.h>
40613a2f6bSGordon Ross
41613a2f6bSGordon Ross #include <sys/byteorder.h>
42613a2f6bSGordon Ross #include <sys/types.h>
43613a2f6bSGordon Ross #include <sys/fcntl.h>
44613a2f6bSGordon Ross #include <sys/ioctl.h>
45613a2f6bSGordon Ross #include <sys/time.h>
46613a2f6bSGordon Ross #include <sys/socket.h>
47613a2f6bSGordon Ross
48613a2f6bSGordon Ross #include <netinet/in.h>
49613a2f6bSGordon Ross #include <netinet/tcp.h>
50613a2f6bSGordon Ross #include <arpa/inet.h>
51613a2f6bSGordon Ross
52613a2f6bSGordon Ross #include <netsmb/smb.h>
53613a2f6bSGordon Ross #include <netsmb/smb_lib.h>
54613a2f6bSGordon Ross #include <netsmb/netbios.h>
55613a2f6bSGordon Ross #include <netsmb/nb_lib.h>
56613a2f6bSGordon Ross #include <netsmb/smb_dev.h>
57613a2f6bSGordon Ross
58613a2f6bSGordon Ross #include "charsets.h"
59613a2f6bSGordon Ross #include "private.h"
60613a2f6bSGordon Ross
61613a2f6bSGordon Ross /*
62613a2f6bSGordon Ross * Be the reader thread for this VC.
63613a2f6bSGordon Ross */
64613a2f6bSGordon Ross int
smb_iod_work(smb_ctx_t * ctx)65613a2f6bSGordon Ross smb_iod_work(smb_ctx_t *ctx)
66613a2f6bSGordon Ross {
67613a2f6bSGordon Ross smbioc_ssn_work_t *work = &ctx->ct_work;
68613a2f6bSGordon Ross int vcst, err = 0;
69613a2f6bSGordon Ross
70613a2f6bSGordon Ross DPRINT("server: %s", ctx->ct_srvname);
71613a2f6bSGordon Ross
72613a2f6bSGordon Ross /* Calle should have opened these */
73613a2f6bSGordon Ross if (ctx->ct_tran_fd == -1 || ctx->ct_dev_fd == -1) {
74613a2f6bSGordon Ross err = EINVAL;
75613a2f6bSGordon Ross goto out;
76613a2f6bSGordon Ross }
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 vcst = SMBIOD_ST_VCACTIVE;
88613a2f6bSGordon Ross
89613a2f6bSGordon Ross for (;;) {
90613a2f6bSGordon Ross
91613a2f6bSGordon Ross switch (vcst) {
92613a2f6bSGordon Ross case SMBIOD_ST_IDLE:
93613a2f6bSGordon Ross /*
94613a2f6bSGordon Ross * Wait for driver requests to arrive
95613a2f6bSGordon Ross * for this VC, then return here.
96613a2f6bSGordon Ross * Next state is normally RECONNECT.
97613a2f6bSGordon Ross */
98613a2f6bSGordon Ross DPRINT("state: idle");
99613a2f6bSGordon Ross if (ioctl(ctx->ct_dev_fd,
100613a2f6bSGordon Ross SMBIOC_IOD_IDLE, &vcst) == -1) {
101613a2f6bSGordon Ross err = errno;
102613a2f6bSGordon Ross DPRINT("ioc_idle: err %d", err);
103613a2f6bSGordon Ross goto out;
104613a2f6bSGordon Ross }
105613a2f6bSGordon Ross continue;
106613a2f6bSGordon Ross
107613a2f6bSGordon Ross case SMBIOD_ST_RECONNECT:
108613a2f6bSGordon Ross DPRINT("state: reconnect");
109613a2f6bSGordon Ross err = smb_iod_connect(ctx);
110613a2f6bSGordon Ross if (err == 0) {
111613a2f6bSGordon Ross vcst = SMBIOD_ST_VCACTIVE;
112613a2f6bSGordon Ross continue;
113613a2f6bSGordon Ross }
114613a2f6bSGordon Ross DPRINT("_iod_connect: err %d", err);
115613a2f6bSGordon Ross /*
116613a2f6bSGordon Ross * If the error was EAUTH, retry is
117613a2f6bSGordon Ross * not likely to succeed either, so
118613a2f6bSGordon Ross * just exit this thread. The user
119613a2f6bSGordon Ross * will need to run smbutil to get
120613a2f6bSGordon Ross * a new thread with new auth info.
121613a2f6bSGordon Ross */
122613a2f6bSGordon Ross if (err == EAUTH)
123613a2f6bSGordon Ross goto out;
124613a2f6bSGordon Ross vcst = SMBIOD_ST_RCFAILED;
125613a2f6bSGordon Ross continue;
126613a2f6bSGordon Ross
127613a2f6bSGordon Ross case SMBIOD_ST_RCFAILED:
128613a2f6bSGordon Ross DPRINT("state: rcfailed");
129613a2f6bSGordon Ross /*
130613a2f6bSGordon Ross * Reconnect failed. Kill off any
131613a2f6bSGordon Ross * requests waiting in the driver,
132613a2f6bSGordon Ross * then get ready to try again.
133613a2f6bSGordon Ross * Next state is normally IDLE.
134613a2f6bSGordon Ross */
135613a2f6bSGordon Ross if (ioctl(ctx->ct_dev_fd,
136613a2f6bSGordon Ross SMBIOC_IOD_RCFAIL, &vcst) == -1) {
137613a2f6bSGordon Ross err = errno;
138613a2f6bSGordon Ross DPRINT("ioc_rcfail: err %d", err);
139613a2f6bSGordon Ross goto out;
140613a2f6bSGordon Ross }
141613a2f6bSGordon Ross continue;
142613a2f6bSGordon Ross
143613a2f6bSGordon Ross case SMBIOD_ST_VCACTIVE:
144613a2f6bSGordon Ross DPRINT("state: active");
145613a2f6bSGordon Ross if (ioctl(ctx->ct_dev_fd,
146613a2f6bSGordon Ross SMBIOC_IOD_WORK, work) == -1) {
147613a2f6bSGordon Ross err = errno;
148613a2f6bSGordon Ross DPRINT("ioc_work: err %d", err);
149613a2f6bSGordon Ross goto out;
150613a2f6bSGordon Ross }
151613a2f6bSGordon Ross vcst = work->wk_out_state;
152*3d804dabSGordon Ross /*
153*3d804dabSGordon Ross * Go ahead and close the transport now,
154*3d804dabSGordon Ross * rather than wait until reconnect to
155*3d804dabSGordon Ross * this server.
156*3d804dabSGordon Ross */
157*3d804dabSGordon Ross close(ctx->ct_tran_fd);
158*3d804dabSGordon Ross ctx->ct_tran_fd = -1;
159613a2f6bSGordon Ross continue;
160613a2f6bSGordon Ross
161613a2f6bSGordon Ross case SMBIOD_ST_DEAD:
162613a2f6bSGordon Ross DPRINT("state: dead");
163613a2f6bSGordon Ross err = 0;
164613a2f6bSGordon Ross goto out;
165613a2f6bSGordon Ross
166613a2f6bSGordon Ross default:
167613a2f6bSGordon Ross DPRINT("state: BAD(%d)", vcst);
168613a2f6bSGordon Ross err = EFAULT;
169613a2f6bSGordon Ross goto out;
170613a2f6bSGordon Ross }
171613a2f6bSGordon Ross }
172613a2f6bSGordon Ross
173613a2f6bSGordon Ross out:
174613a2f6bSGordon Ross if (ctx->ct_tran_fd != -1) {
175613a2f6bSGordon Ross close(ctx->ct_tran_fd);
176613a2f6bSGordon Ross ctx->ct_tran_fd = -1;
177613a2f6bSGordon Ross }
178613a2f6bSGordon Ross if (ctx->ct_dev_fd != -1) {
179613a2f6bSGordon Ross close(ctx->ct_dev_fd);
180613a2f6bSGordon Ross ctx->ct_dev_fd = -1;
181613a2f6bSGordon Ross }
182613a2f6bSGordon Ross
183613a2f6bSGordon Ross return (err);
184613a2f6bSGordon Ross }
185