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 *path, 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->path, path, sizeof (ioc->path)); 175 (void) strlcpy(ioc->name, name, sizeof (ioc->name)); 176 rc = smb_kmod_ioctl(SMB_IOC_UNSHARE, &ioc->hdr, 177 sizeof (smb_ioc_share_t)); 178 free(ioc); 179 } 180 return (rc); 181 } 182 183 int 184 smb_kmod_get_usernum(uint32_t *punum) 185 { 186 smb_ioc_usernum_t ioc; 187 int rc; 188 189 ioc.num = 0; 190 rc = smb_kmod_ioctl(SMB_IOC_USER_NUMBER, &ioc.hdr, sizeof (ioc)); 191 if (rc == 0) 192 *punum = ioc.num; 193 194 return (rc); 195 } 196 197 int 198 smb_kmod_get_userlist(smb_ulist_t *ulist) 199 { 200 smb_opipe_context_t *ctx; 201 smb_ioc_ulist_t *ioc; 202 uint32_t ioc_len; 203 uint8_t *data; 204 uint32_t data_len; 205 uint32_t unum; 206 int rc; 207 208 smb_ulist_cleanup(ulist); 209 210 rc = smb_kmod_get_usernum(&unum); 211 if ((rc != 0) || (unum == 0)) 212 return (rc); 213 214 ioc_len = sizeof (smb_ioc_ulist_t) + SMB_IOC_DATA_SIZE; 215 ioc = malloc(ioc_len); 216 if (ioc == NULL) 217 return (ENOMEM); 218 219 ctx = malloc(sizeof (smb_opipe_context_t) * unum); 220 if (ctx == NULL) { 221 free(ioc); 222 return (ENOMEM); 223 } 224 ulist->ul_users = ctx; 225 226 while (ulist->ul_cnt < unum) { 227 ioc->cookie = ulist->ul_cnt; 228 ioc->data_len = SMB_IOC_DATA_SIZE; 229 rc = smb_kmod_ioctl(SMB_IOC_USER_LIST, &ioc->hdr, 230 ioc_len); 231 if (rc != 0) 232 break; 233 234 if ((ulist->ul_cnt + ioc->num) > unum) 235 ioc->num = unum - ulist->ul_cnt; 236 237 if (ioc->num == 0) 238 break; 239 240 data = ioc->data; 241 data_len = ioc->data_len; 242 while (ioc->num > 0) { 243 uint_t bd = 0; 244 245 rc = smb_opipe_context_decode(ctx, data, data_len, &bd); 246 if (rc != 0) 247 break; 248 249 ctx++; 250 ioc->num--; 251 ulist->ul_cnt++; 252 data += bd; 253 data_len -= bd; 254 } 255 } 256 257 if (rc != 0) 258 smb_ulist_cleanup(ulist); 259 260 free(ioc); 261 return (rc); 262 } 263 264 void 265 smb_kmod_unbind(void) 266 { 267 if (smbdrv_fd != -1) { 268 (void) close(smbdrv_fd); 269 smbdrv_fd = -1; 270 } 271 } 272 273 static int 274 smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len) 275 { 276 int rc = EINVAL; 277 278 ioc->version = SMB_IOC_VERSION; 279 ioc->cmd = cmd; 280 ioc->len = len; 281 ioc->crc = 0; 282 ioc->crc = smb_crc_gen((uint8_t *)ioc, sizeof (smb_ioc_header_t)); 283 284 if (smbdrv_fd != -1) { 285 if (ioctl(smbdrv_fd, cmd, ioc) < 0) 286 rc = errno; 287 else 288 rc = 0; 289 } 290 return (rc); 291 } 292