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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * User-space door client for LanMan share management. 31 */ 32 33 #include <syslog.h> 34 #include <door.h> 35 #include <fcntl.h> 36 #include <stdarg.h> 37 #include <errno.h> 38 #include <string.h> 39 #include <strings.h> 40 #include <unistd.h> 41 #include <thread.h> 42 #include <synch.h> 43 44 #include <smbsrv/libsmb.h> 45 #include <smbsrv/smb_share.h> 46 #include <smbsrv/lmerr.h> 47 #include <smbsrv/cifs.h> 48 49 static int smb_share_dfd = -1; 50 static uint64_t smb_share_dncall = 0; 51 static mutex_t smb_share_dmtx; 52 static cond_t smb_share_dcv; 53 54 /* 55 * Open the lmshrd door. This is a private call for use by 56 * smb_share_denter() and must be called with smb_share_dmtx held. 57 * 58 * Returns the door fd on success. Otherwise, -1. 59 */ 60 static int 61 smb_share_dopen(void) 62 { 63 if (smb_share_dfd == -1) { 64 if ((smb_share_dfd = open(SMB_SHARE_DNAME, O_RDONLY)) < 0) 65 smb_share_dfd = -1; 66 else 67 smb_share_dncall = 0; 68 } 69 70 return (smb_share_dfd); 71 } 72 73 /* 74 * Close the lmshrd door. 75 */ 76 void 77 smb_share_dclose(void) 78 { 79 (void) mutex_lock(&smb_share_dmtx); 80 81 if (smb_share_dfd != -1) { 82 while (smb_share_dncall > 0) 83 (void) cond_wait(&smb_share_dcv, &smb_share_dmtx); 84 85 if (smb_share_dfd != -1) { 86 (void) close(smb_share_dfd); 87 smb_share_dfd = -1; 88 } 89 } 90 91 (void) mutex_unlock(&smb_share_dmtx); 92 } 93 94 /* 95 * Entry handler for lmshrd door calls. 96 */ 97 static door_arg_t * 98 smb_share_denter(void) 99 { 100 door_arg_t *arg; 101 char *buf; 102 103 (void) mutex_lock(&smb_share_dmtx); 104 105 if (smb_share_dopen() == -1) { 106 (void) mutex_unlock(&smb_share_dmtx); 107 return (NULL); 108 } 109 110 if ((arg = malloc(sizeof (door_arg_t) + SMB_SHARE_DSIZE)) != NULL) { 111 buf = ((char *)arg) + sizeof (door_arg_t); 112 bzero(arg, sizeof (door_arg_t)); 113 arg->data_ptr = buf; 114 arg->rbuf = buf; 115 arg->rsize = SMB_SHARE_DSIZE; 116 117 ++smb_share_dncall; 118 } 119 120 (void) mutex_unlock(&smb_share_dmtx); 121 return (arg); 122 } 123 124 /* 125 * Exit handler for lmshrd door calls. 126 */ 127 static void 128 smb_share_dexit(door_arg_t *arg, char *errmsg) 129 { 130 if (errmsg) 131 syslog(LOG_DEBUG, "lmshrd_door: %s", errmsg); 132 133 (void) mutex_lock(&smb_share_dmtx); 134 free(arg); 135 --smb_share_dncall; 136 (void) cond_signal(&smb_share_dcv); 137 (void) mutex_unlock(&smb_share_dmtx); 138 } 139 140 /* 141 * Return 0 upon success. Otherwise, -1. 142 */ 143 static int 144 smb_share_dchk(smb_dr_ctx_t *dec_ctx) 145 { 146 int status = smb_dr_get_int32(dec_ctx); 147 148 if (status != SMB_SHARE_DSUCCESS) { 149 if (status == SMB_SHARE_DERROR) 150 (void) smb_dr_get_uint32(dec_ctx); 151 return (-1); 152 } 153 154 return (0); 155 } 156 157 uint32_t 158 smb_share_list(int offset, smb_shrlist_t *list) 159 { 160 door_arg_t *arg; 161 smb_dr_ctx_t *dec_ctx; 162 smb_dr_ctx_t *enc_ctx; 163 uint32_t rc; 164 165 if ((arg = smb_share_denter()) == NULL) 166 return (NERR_InternalError); 167 168 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 169 smb_dr_put_uint32(enc_ctx, SMB_SHROP_LIST); 170 smb_dr_put_int32(enc_ctx, offset); 171 172 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 173 if (rc != 0) { 174 smb_share_dexit(arg, "encode error"); 175 return (NERR_InternalError); 176 } 177 178 if (door_call(smb_share_dfd, arg) < 0) { 179 smb_share_dexit(arg, "door call error"); 180 smb_share_dclose(); 181 return (NERR_InternalError); 182 } 183 184 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 185 if (smb_share_dchk(dec_ctx) != 0) { 186 (void) smb_dr_decode_finish(dec_ctx); 187 smb_share_dexit(arg, "decode error"); 188 return (NERR_InternalError); 189 } 190 191 smb_dr_get_shrlist(dec_ctx, list); 192 if (smb_dr_decode_finish(dec_ctx) != 0) { 193 smb_share_dexit(arg, "decode error"); 194 return (NERR_InternalError); 195 } 196 197 smb_share_dexit(arg, NULL); 198 return (NERR_Success); 199 } 200 201 int 202 smb_share_count(void) 203 { 204 door_arg_t *arg; 205 smb_dr_ctx_t *dec_ctx; 206 smb_dr_ctx_t *enc_ctx; 207 uint32_t num_shares; 208 int rc; 209 210 if ((arg = smb_share_denter()) == NULL) 211 return (-1); 212 213 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 214 smb_dr_put_uint32(enc_ctx, SMB_SHROP_NUM_SHARES); 215 216 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 217 if (rc != 0) { 218 smb_share_dexit(arg, "encode error"); 219 return (-1); 220 } 221 222 if (door_call(smb_share_dfd, arg) < 0) { 223 smb_share_dexit(arg, "door call error"); 224 smb_share_dclose(); 225 return (-1); 226 } 227 228 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 229 if (smb_share_dchk(dec_ctx) != 0) { 230 (void) smb_dr_decode_finish(dec_ctx); 231 smb_share_dexit(arg, "decode error"); 232 return (-1); 233 } 234 235 num_shares = smb_dr_get_uint32(dec_ctx); 236 if (smb_dr_decode_finish(dec_ctx) != 0) { 237 smb_share_dexit(arg, "decode error"); 238 return (-1); 239 } 240 241 smb_share_dexit(arg, NULL); 242 return (num_shares); 243 } 244 245 uint32_t 246 smb_share_del(char *share_name) 247 { 248 door_arg_t *arg; 249 smb_dr_ctx_t *dec_ctx; 250 smb_dr_ctx_t *enc_ctx; 251 uint32_t rc; 252 253 if ((arg = smb_share_denter()) == NULL) 254 return (NERR_InternalError); 255 256 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 257 smb_dr_put_uint32(enc_ctx, SMB_SHROP_DELETE); 258 smb_dr_put_string(enc_ctx, share_name); 259 260 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 261 if (rc != 0) { 262 smb_share_dexit(arg, "encode error"); 263 return (NERR_InternalError); 264 } 265 266 if (door_call(smb_share_dfd, arg) < 0) { 267 smb_share_dexit(arg, "door call error"); 268 smb_share_dclose(); 269 return (NERR_InternalError); 270 } 271 272 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 273 if (smb_share_dchk(dec_ctx) != 0) { 274 (void) smb_dr_decode_finish(dec_ctx); 275 smb_share_dexit(arg, "decode error"); 276 return (NERR_InternalError); 277 } 278 279 rc = smb_dr_get_uint32(dec_ctx); 280 if (smb_dr_decode_finish(dec_ctx) != 0) { 281 smb_share_dexit(arg, "decode error"); 282 return (NERR_InternalError); 283 } 284 285 smb_share_dexit(arg, NULL); 286 return (rc); 287 288 } 289 290 uint32_t 291 smb_share_ren(char *from, char *to) 292 { 293 door_arg_t *arg; 294 smb_dr_ctx_t *dec_ctx; 295 smb_dr_ctx_t *enc_ctx; 296 uint32_t rc; 297 298 if ((arg = smb_share_denter()) == NULL) 299 return (NERR_InternalError); 300 301 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 302 smb_dr_put_uint32(enc_ctx, SMB_SHROP_RENAME); 303 smb_dr_put_string(enc_ctx, from); 304 smb_dr_put_string(enc_ctx, to); 305 306 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 307 if (rc != 0) { 308 smb_share_dexit(arg, "encode error"); 309 return (NERR_InternalError); 310 } 311 312 if (door_call(smb_share_dfd, arg) < 0) { 313 smb_share_dexit(arg, "door call error"); 314 smb_share_dclose(); 315 return (NERR_InternalError); 316 } 317 318 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 319 if (smb_share_dchk(dec_ctx) != 0) { 320 (void) smb_dr_decode_finish(dec_ctx); 321 smb_share_dexit(arg, "decode error"); 322 return (NERR_InternalError); 323 } 324 325 rc = smb_dr_get_uint32(dec_ctx); 326 if (smb_dr_decode_finish(dec_ctx) != 0) { 327 smb_share_dexit(arg, "decode error"); 328 return (NERR_InternalError); 329 } 330 331 smb_share_dexit(arg, NULL); 332 return (rc); 333 } 334 335 uint32_t 336 smb_share_get(char *share_name, smb_share_t *si) 337 { 338 door_arg_t *arg; 339 smb_dr_ctx_t *dec_ctx; 340 smb_dr_ctx_t *enc_ctx; 341 uint32_t rc; 342 343 if ((arg = smb_share_denter()) == NULL) 344 return (NERR_InternalError); 345 346 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 347 smb_dr_put_uint32(enc_ctx, SMB_SHROP_GETINFO); 348 smb_dr_put_string(enc_ctx, share_name); 349 350 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 351 if (rc != 0) { 352 smb_share_dexit(arg, "encode error"); 353 return (NERR_InternalError); 354 } 355 356 if (door_call(smb_share_dfd, arg) < 0) { 357 smb_share_dexit(arg, "door call error"); 358 smb_share_dclose(); 359 return (NERR_InternalError); 360 } 361 362 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 363 if (smb_share_dchk(dec_ctx) != 0) { 364 (void) smb_dr_decode_finish(dec_ctx); 365 smb_share_dexit(arg, "decode error"); 366 return (NERR_InternalError); 367 } 368 369 rc = smb_dr_get_uint32(dec_ctx); 370 smb_dr_get_share(dec_ctx, si); 371 if (smb_dr_decode_finish(dec_ctx) != 0) { 372 smb_share_dexit(arg, "decode error"); 373 return (NERR_InternalError); 374 } 375 376 smb_share_dexit(arg, NULL); 377 return (rc); 378 } 379 380 uint32_t 381 smb_share_add(smb_share_t *si) 382 { 383 door_arg_t *arg; 384 smb_dr_ctx_t *dec_ctx; 385 smb_dr_ctx_t *enc_ctx; 386 uint32_t rc; 387 388 if ((arg = smb_share_denter()) == NULL) 389 return (NERR_InternalError); 390 391 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 392 smb_dr_put_uint32(enc_ctx, SMB_SHROP_ADD); 393 smb_dr_put_share(enc_ctx, si); 394 395 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 396 if (rc != 0) { 397 smb_share_dexit(arg, "encode error"); 398 return (NERR_InternalError); 399 } 400 401 if (door_call(smb_share_dfd, arg) < 0) { 402 smb_share_dexit(arg, "door call error"); 403 smb_share_dclose(); 404 return (NERR_InternalError); 405 } 406 407 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 408 if (smb_share_dchk(dec_ctx) != 0) { 409 (void) smb_dr_decode_finish(dec_ctx); 410 smb_share_dexit(arg, "decode error"); 411 return (NERR_InternalError); 412 } 413 414 rc = smb_dr_get_uint32(dec_ctx); 415 smb_dr_get_share(dec_ctx, si); 416 if (smb_dr_decode_finish(dec_ctx) != 0) { 417 smb_share_dexit(arg, "decode error"); 418 return (NERR_InternalError); 419 } 420 421 smb_share_dexit(arg, NULL); 422 return (rc); 423 } 424 425 uint32_t 426 smb_share_set(smb_share_t *si) 427 { 428 door_arg_t *arg; 429 smb_dr_ctx_t *dec_ctx; 430 smb_dr_ctx_t *enc_ctx; 431 uint32_t rc; 432 433 if ((arg = smb_share_denter()) == NULL) 434 return (NERR_InternalError); 435 436 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 437 smb_dr_put_uint32(enc_ctx, SMB_SHROP_SETINFO); 438 smb_dr_put_share(enc_ctx, si); 439 440 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 441 if (rc != 0) { 442 smb_share_dexit(arg, "encode error"); 443 return (NERR_InternalError); 444 } 445 446 if (door_call(smb_share_dfd, arg) < 0) { 447 smb_share_dexit(arg, "door call error"); 448 smb_share_dclose(); 449 return (NERR_InternalError); 450 } 451 452 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 453 if (smb_share_dchk(dec_ctx) != 0) { 454 (void) smb_dr_decode_finish(dec_ctx); 455 smb_share_dexit(arg, "decode error"); 456 return (NERR_InternalError); 457 } 458 459 rc = smb_dr_get_uint32(dec_ctx); 460 if (smb_dr_decode_finish(dec_ctx) != 0) { 461 smb_share_dexit(arg, "decode error"); 462 return (NERR_InternalError); 463 } 464 465 smb_share_dexit(arg, NULL); 466 return (rc); 467 } 468