xref: /illumos-gate/usr/src/lib/libsmbfs/smb/iod_wk.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
27  */
28 
29 /*
30  * Functions called by the IO deamon (IOD).
31  * Here in the library to simplify testing.
32  */
33 
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <libintl.h>
41 
42 #include <sys/byteorder.h>
43 #include <sys/types.h>
44 #include <sys/fcntl.h>
45 #include <sys/ioctl.h>
46 #include <sys/time.h>
47 #include <sys/socket.h>
48 
49 #include <netinet/in.h>
50 #include <netinet/tcp.h>
51 #include <arpa/inet.h>
52 
53 #include <netsmb/smb.h>
54 #include <netsmb/smb_lib.h>
55 #include <netsmb/netbios.h>
56 #include <netsmb/nb_lib.h>
57 #include <netsmb/smb_dev.h>
58 
59 #include "charsets.h"
60 #include "private.h"
61 
62 /*
63  * The user agent (smbiod) calls smb_iod_connect for the first
64  * connection to some server, and if that succeeds, will start a
65  * thread running this function, passing the smb_ctx_t
66  *
67  * This thread now enters the driver and stays there, reading
68  * network responses as long as the connection is alive.
69  */
70 int
71 smb_iod_work(smb_ctx_t *ctx)
72 {
73 	smbioc_ssn_work_t *work = &ctx->ct_work;
74 	int	err = 0;
75 
76 	DPRINT("server: %s", ctx->ct_srvname);
77 
78 	/*
79 	 * This is the reader / reconnect loop.
80 	 *
81 	 * We could start with state "idle", but
82 	 * we know someone wants a connection to
83 	 * this server, so start in "vcactive".
84 	 *
85 	 * XXX: Add some syslog calls in here?
86 	 */
87 
88 	for (;;) {
89 
90 		DPRINT("state: %s",
91 		    smb_iod_state_name(work->wk_out_state));
92 
93 		switch (work->wk_out_state) {
94 		case SMBIOD_ST_IDLE:
95 			/*
96 			 * Wait for driver requests to arrive
97 			 * for this VC, then return here.
98 			 * Next state is normally RECONNECT.
99 			 */
100 			DPRINT("Call _ioc_idle...");
101 			if (nsmb_ioctl(ctx->ct_dev_fd,
102 			    SMBIOC_IOD_IDLE, work) == -1) {
103 				err = errno;
104 				DPRINT("ioc_idle: err %d", err);
105 				goto out;
106 			}
107 			DPRINT("Ret. from _ioc_idle");
108 			continue;
109 
110 		case SMBIOD_ST_RECONNECT:
111 			DPRINT("Call _iod_connect...");
112 			err = smb_iod_connect(ctx);
113 			if (err == 0)
114 				continue;
115 			DPRINT("iod_connect: err %d", err);
116 			/*
117 			 * If the error was EAUTH, retry is
118 			 * not likely to succeed either, so
119 			 * just exit this thread.  The user
120 			 * will need to run smbutil to get
121 			 * a new thread with new auth info.
122 			 */
123 			if (err == EAUTH) {
124 				DPRINT("iod_connect: EAUTH (give up)");
125 				goto out;
126 			}
127 			/*
128 			 * Reconnect failed.  Notify any requests
129 			 * that we're not connected, and delay.
130 			 * Next state will be IDLE or RECONNECT.
131 			 */
132 			DPRINT("Call _iod_rcfail...");
133 			if (nsmb_ioctl(ctx->ct_dev_fd,
134 			    SMBIOC_IOD_RCFAIL, work) == -1) {
135 				err = errno;
136 				DPRINT("iod_rcfail: err %d", err);
137 				goto out;
138 			}
139 			continue;
140 
141 		case SMBIOD_ST_AUTHOK:
142 			/*
143 			 * This is where we enter the driver and
144 			 * stay there.  While the connection is up
145 			 * the VC will have SMBIOD_ST_VCACTIVE
146 			 */
147 			DPRINT("Call _iod_work...");
148 			if (nsmb_ioctl(ctx->ct_dev_fd,
149 			    SMBIOC_IOD_WORK, work) == -1) {
150 				err = errno;
151 				DPRINT("iod_work: err %d", err);
152 				goto out;
153 			}
154 			DPRINT("Ret. from _ioc_work");
155 			continue;
156 
157 		case SMBIOD_ST_DEAD:
158 			DPRINT("got state=DEAD");
159 			err = 0;
160 			goto out;
161 
162 		default:
163 			DPRINT("Unexpected state: %d (%s)",
164 			    work->wk_out_state,
165 			    smb_iod_state_name(work->wk_out_state));
166 			err = EFAULT;
167 			goto out;
168 		}
169 	}
170 
171 out:
172 	if (ctx->ct_dev_fd != -1) {
173 		nsmb_close(ctx->ct_dev_fd);
174 		ctx->ct_dev_fd = -1;
175 	}
176 
177 	return (err);
178 }
179