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 2012 Nexenta Systems, Inc. All rights reserved. 24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* 29 * Functions called by the IO deamon (IOD). 30 * Here in the library to simplify testing. 31 */ 32 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <stdio.h> 36 #include <string.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <libintl.h> 40 41 #include <sys/byteorder.h> 42 #include <sys/types.h> 43 #include <sys/fcntl.h> 44 #include <sys/ioctl.h> 45 #include <sys/time.h> 46 #include <sys/socket.h> 47 48 #include <netinet/in.h> 49 #include <netinet/tcp.h> 50 #include <arpa/inet.h> 51 52 #include <netsmb/smb.h> 53 #include <netsmb/smb_lib.h> 54 #include <netsmb/netbios.h> 55 #include <netsmb/nb_lib.h> 56 #include <netsmb/smb_dev.h> 57 58 #include "charsets.h" 59 #include "private.h" 60 61 /* 62 * Be the reader thread for this VC. 63 */ 64 int 65 smb_iod_work(smb_ctx_t *ctx) 66 { 67 smbioc_ssn_work_t *work = &ctx->ct_work; 68 int vcst, err = 0; 69 70 DPRINT("server: %s", ctx->ct_srvname); 71 72 /* Calle should have opened these */ 73 if (ctx->ct_tran_fd == -1 || ctx->ct_dev_fd == -1) { 74 err = EINVAL; 75 goto out; 76 } 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 vcst = SMBIOD_ST_VCACTIVE; 88 89 for (;;) { 90 91 switch (vcst) { 92 case SMBIOD_ST_IDLE: 93 /* 94 * Wait for driver requests to arrive 95 * for this VC, then return here. 96 * Next state is normally RECONNECT. 97 */ 98 DPRINT("state: idle"); 99 if (ioctl(ctx->ct_dev_fd, 100 SMBIOC_IOD_IDLE, &vcst) == -1) { 101 err = errno; 102 DPRINT("ioc_idle: err %d", err); 103 goto out; 104 } 105 continue; 106 107 case SMBIOD_ST_RECONNECT: 108 DPRINT("state: reconnect"); 109 err = smb_iod_connect(ctx); 110 if (err == 0) { 111 vcst = SMBIOD_ST_VCACTIVE; 112 continue; 113 } 114 DPRINT("_iod_connect: err %d", err); 115 /* 116 * If the error was EAUTH, retry is 117 * not likely to succeed either, so 118 * just exit this thread. The user 119 * will need to run smbutil to get 120 * a new thread with new auth info. 121 */ 122 if (err == EAUTH) 123 goto out; 124 vcst = SMBIOD_ST_RCFAILED; 125 continue; 126 127 case SMBIOD_ST_RCFAILED: 128 DPRINT("state: rcfailed"); 129 /* 130 * Reconnect failed. Kill off any 131 * requests waiting in the driver, 132 * then get ready to try again. 133 * Next state is normally IDLE. 134 */ 135 if (ioctl(ctx->ct_dev_fd, 136 SMBIOC_IOD_RCFAIL, &vcst) == -1) { 137 err = errno; 138 DPRINT("ioc_rcfail: err %d", err); 139 goto out; 140 } 141 continue; 142 143 case SMBIOD_ST_VCACTIVE: 144 DPRINT("state: active"); 145 if (ioctl(ctx->ct_dev_fd, 146 SMBIOC_IOD_WORK, work) == -1) { 147 err = errno; 148 DPRINT("ioc_work: err %d", err); 149 goto out; 150 } 151 vcst = work->wk_out_state; 152 /* 153 * Go ahead and close the transport now, 154 * rather than wait until reconnect to 155 * this server. 156 */ 157 close(ctx->ct_tran_fd); 158 ctx->ct_tran_fd = -1; 159 continue; 160 161 case SMBIOD_ST_DEAD: 162 DPRINT("state: dead"); 163 err = 0; 164 goto out; 165 166 default: 167 DPRINT("state: BAD(%d)", vcst); 168 err = EFAULT; 169 goto out; 170 } 171 } 172 173 out: 174 if (ctx->ct_tran_fd != -1) { 175 close(ctx->ct_tran_fd); 176 ctx->ct_tran_fd = -1; 177 } 178 if (ctx->ct_dev_fd != -1) { 179 close(ctx->ct_dev_fd); 180 ctx->ct_dev_fd = -1; 181 } 182 183 return (err); 184 } 185