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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <sys/ioccom.h> 29 #include <sys/param.h> 30 #include <stddef.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <strings.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <fcntl.h> 37 #include <errno.h> 38 39 #include <smbsrv/smb_xdr.h> 40 #include <smbsrv/smbinfo.h> 41 #include <smbsrv/smb_ioctl.h> 42 #include <smbsrv/smb_ioctl.h> 43 #include <smbsrv/libsmb.h> 44 45 #define SMBDRV_DEVICE_PATH "/devices/pseudo/smbsrv@0:smbsrv" 46 #define SMB_IOC_DATA_SIZE (256 * 1024) 47 48 static int smb_kmod_ioctl(int, smb_ioc_header_t *, uint32_t); 49 50 51 int smbdrv_fd = -1; 52 53 int 54 smb_kmod_bind(void) 55 { 56 if (smbdrv_fd != -1) 57 (void) close(smbdrv_fd); 58 59 if ((smbdrv_fd = open(SMBDRV_DEVICE_PATH, 0)) < 0) { 60 smbdrv_fd = -1; 61 return (errno); 62 } 63 64 return (0); 65 } 66 67 int 68 smb_kmod_setcfg(smb_kmod_cfg_t *cfg) 69 { 70 smb_ioc_cfg_t ioc; 71 72 ioc.maxworkers = cfg->skc_maxworkers; 73 ioc.maxconnections = cfg->skc_maxconnections; 74 ioc.keepalive = cfg->skc_keepalive; 75 ioc.restrict_anon = cfg->skc_restrict_anon; 76 ioc.signing_enable = cfg->skc_signing_enable; 77 ioc.signing_required = cfg->skc_signing_required; 78 ioc.oplock_enable = cfg->skc_oplock_enable; 79 ioc.sync_enable = cfg->skc_sync_enable; 80 ioc.secmode = cfg->skc_secmode; 81 ioc.ipv6_enable = cfg->skc_ipv6_enable; 82 83 (void) strlcpy(ioc.nbdomain, cfg->skc_nbdomain, sizeof (ioc.nbdomain)); 84 (void) strlcpy(ioc.fqdn, cfg->skc_fqdn, sizeof (ioc.fqdn)); 85 (void) strlcpy(ioc.hostname, cfg->skc_hostname, sizeof (ioc.hostname)); 86 (void) strlcpy(ioc.system_comment, cfg->skc_system_comment, 87 sizeof (ioc.system_comment)); 88 89 return (smb_kmod_ioctl(SMB_IOC_CONFIG, &ioc.hdr, sizeof (ioc))); 90 } 91 92 int 93 smb_kmod_setgmtoff(int32_t gmtoff) 94 { 95 smb_ioc_gmt_t ioc; 96 97 ioc.offset = gmtoff; 98 return (smb_kmod_ioctl(SMB_IOC_GMTOFF, &ioc.hdr, 99 sizeof (ioc))); 100 } 101 102 int 103 smb_kmod_start(int opipe, int lmshr, int udoor) 104 { 105 smb_ioc_start_t ioc; 106 107 ioc.opipe = opipe; 108 ioc.lmshrd = lmshr; 109 ioc.udoor = udoor; 110 return (smb_kmod_ioctl(SMB_IOC_START, &ioc.hdr, sizeof (ioc))); 111 } 112 113 int 114 smb_kmod_tcplisten(int error) 115 { 116 smb_ioc_listen_t ioc; 117 118 ioc.error = error; 119 return (smb_kmod_ioctl(SMB_IOC_TCP_LISTEN, &ioc.hdr, sizeof (ioc))); 120 } 121 122 int 123 smb_kmod_nbtlisten(int error) 124 { 125 smb_ioc_listen_t ioc; 126 127 ioc.error = error; 128 return (smb_kmod_ioctl(SMB_IOC_NBT_LISTEN, &ioc.hdr, sizeof (ioc))); 129 } 130 131 int 132 smb_kmod_tcpreceive(void) 133 { 134 smb_ioc_header_t ioc; 135 136 return (smb_kmod_ioctl(SMB_IOC_TCP_RECEIVE, &ioc, sizeof (ioc))); 137 } 138 139 int 140 smb_kmod_nbtreceive(void) 141 { 142 smb_ioc_header_t ioc; 143 144 return (smb_kmod_ioctl(SMB_IOC_NBT_RECEIVE, &ioc, sizeof (ioc))); 145 } 146 147 int 148 smb_kmod_share(char *path, char *name) 149 { 150 smb_ioc_share_t *ioc; 151 int rc = ENOMEM; 152 153 ioc = malloc(sizeof (smb_ioc_share_t)); 154 155 if (ioc != NULL) { 156 (void) strlcpy(ioc->path, path, sizeof (ioc->path)); 157 (void) strlcpy(ioc->name, name, sizeof (ioc->name)); 158 rc = smb_kmod_ioctl(SMB_IOC_SHARE, &ioc->hdr, 159 sizeof (smb_ioc_share_t)); 160 free(ioc); 161 } 162 return (rc); 163 } 164 165 int 166 smb_kmod_unshare(char *name) 167 { 168 smb_ioc_share_t *ioc; 169 int rc = ENOMEM; 170 171 ioc = malloc(sizeof (smb_ioc_share_t)); 172 173 if (ioc != NULL) { 174 (void) strlcpy(ioc->name, name, sizeof (ioc->name)); 175 rc = smb_kmod_ioctl(SMB_IOC_UNSHARE, &ioc->hdr, 176 sizeof (smb_ioc_share_t)); 177 free(ioc); 178 } 179 return (rc); 180 } 181 182 int 183 smb_kmod_get_usernum(uint32_t *punum) 184 { 185 smb_ioc_usernum_t ioc; 186 int rc; 187 188 ioc.num = 0; 189 rc = smb_kmod_ioctl(SMB_IOC_USER_NUMBER, &ioc.hdr, sizeof (ioc)); 190 if (rc == 0) 191 *punum = ioc.num; 192 193 return (rc); 194 } 195 196 int 197 smb_kmod_get_userlist(smb_ulist_t *ulist) 198 { 199 smb_opipe_context_t *ctx; 200 smb_ioc_ulist_t *ioc; 201 uint32_t ioc_len; 202 uint8_t *data; 203 uint32_t data_len; 204 uint32_t unum; 205 int rc; 206 207 smb_ulist_cleanup(ulist); 208 209 rc = smb_kmod_get_usernum(&unum); 210 if ((rc != 0) || (unum == 0)) 211 return (rc); 212 213 ioc_len = sizeof (smb_ioc_ulist_t) + SMB_IOC_DATA_SIZE; 214 ioc = malloc(ioc_len); 215 if (ioc == NULL) 216 return (ENOMEM); 217 218 ctx = malloc(sizeof (smb_opipe_context_t) * unum); 219 if (ctx == NULL) { 220 free(ioc); 221 return (ENOMEM); 222 } 223 ulist->ul_users = ctx; 224 225 while (ulist->ul_cnt < unum) { 226 ioc->cookie = ulist->ul_cnt; 227 ioc->data_len = SMB_IOC_DATA_SIZE; 228 rc = smb_kmod_ioctl(SMB_IOC_USER_LIST, &ioc->hdr, 229 ioc_len); 230 if (rc != 0) 231 break; 232 233 if ((ulist->ul_cnt + ioc->num) > unum) 234 ioc->num = unum - ulist->ul_cnt; 235 236 if (ioc->num == 0) 237 break; 238 239 data = ioc->data; 240 data_len = ioc->data_len; 241 while (ioc->num > 0) { 242 uint_t bd = 0; 243 244 rc = smb_opipe_context_decode(ctx, data, data_len, &bd); 245 if (rc != 0) 246 break; 247 248 ctx++; 249 ioc->num--; 250 ulist->ul_cnt++; 251 data += bd; 252 data_len -= bd; 253 } 254 } 255 256 if (rc != 0) 257 smb_ulist_cleanup(ulist); 258 259 free(ioc); 260 return (rc); 261 } 262 263 void 264 smb_kmod_unbind(void) 265 { 266 if (smbdrv_fd != -1) { 267 (void) close(smbdrv_fd); 268 smbdrv_fd = -1; 269 } 270 } 271 272 static int 273 smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len) 274 { 275 int rc = EINVAL; 276 277 ioc->version = SMB_IOC_VERSION; 278 ioc->cmd = cmd; 279 ioc->len = len; 280 ioc->crc = 0; 281 ioc->crc = smb_crc_gen((uint8_t *)ioc, sizeof (smb_ioc_header_t)); 282 283 if (smbdrv_fd != -1) { 284 if (ioctl(smbdrv_fd, cmd, ioc) < 0) 285 rc = errno; 286 else 287 rc = 0; 288 } 289 return (rc); 290 } 291