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 "@(#)smb_share_doorclnt.c 1.5 08/08/05 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 bzero(list, sizeof (smb_shrlist_t)); 166 167 if ((arg = smb_share_denter()) == NULL) 168 return (NERR_InternalError); 169 170 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 171 smb_dr_put_uint32(enc_ctx, SMB_SHROP_LIST); 172 smb_dr_put_int32(enc_ctx, offset); 173 174 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 175 if (rc != 0) { 176 smb_share_dexit(arg, "encode error"); 177 return (NERR_InternalError); 178 } 179 180 if (door_call(smb_share_dfd, arg) < 0) { 181 smb_share_dexit(arg, "door call error"); 182 smb_share_dclose(); 183 return (NERR_InternalError); 184 } 185 186 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 187 if (smb_share_dchk(dec_ctx) != 0) { 188 (void) smb_dr_decode_finish(dec_ctx); 189 smb_share_dexit(arg, "decode error"); 190 return (NERR_InternalError); 191 } 192 193 (void) smb_dr_get_buf(dec_ctx, (unsigned char *)list, 194 sizeof (smb_shrlist_t)); 195 if (smb_dr_decode_finish(dec_ctx) != 0) { 196 smb_share_dexit(arg, "decode error"); 197 return (NERR_InternalError); 198 } 199 200 smb_share_dexit(arg, NULL); 201 return (NERR_Success); 202 } 203 204 int 205 smb_share_count(void) 206 { 207 door_arg_t *arg; 208 smb_dr_ctx_t *dec_ctx; 209 smb_dr_ctx_t *enc_ctx; 210 uint32_t num_shares; 211 int rc; 212 213 if ((arg = smb_share_denter()) == NULL) 214 return (-1); 215 216 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 217 smb_dr_put_uint32(enc_ctx, SMB_SHROP_NUM_SHARES); 218 219 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 220 if (rc != 0) { 221 smb_share_dexit(arg, "encode error"); 222 return (-1); 223 } 224 225 if (door_call(smb_share_dfd, arg) < 0) { 226 smb_share_dexit(arg, "door call error"); 227 smb_share_dclose(); 228 return (-1); 229 } 230 231 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 232 if (smb_share_dchk(dec_ctx) != 0) { 233 (void) smb_dr_decode_finish(dec_ctx); 234 smb_share_dexit(arg, "decode error"); 235 return (-1); 236 } 237 238 num_shares = smb_dr_get_uint32(dec_ctx); 239 if (smb_dr_decode_finish(dec_ctx) != 0) { 240 smb_share_dexit(arg, "decode error"); 241 return (-1); 242 } 243 244 smb_share_dexit(arg, NULL); 245 return (num_shares); 246 } 247 248 uint32_t 249 smb_share_delete(char *share_name) 250 { 251 door_arg_t *arg; 252 smb_dr_ctx_t *dec_ctx; 253 smb_dr_ctx_t *enc_ctx; 254 uint32_t rc; 255 256 if ((arg = smb_share_denter()) == NULL) 257 return (NERR_InternalError); 258 259 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 260 smb_dr_put_uint32(enc_ctx, SMB_SHROP_DELETE); 261 smb_dr_put_string(enc_ctx, share_name); 262 263 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 264 if (rc != 0) { 265 smb_share_dexit(arg, "encode error"); 266 return (NERR_InternalError); 267 } 268 269 if (door_call(smb_share_dfd, arg) < 0) { 270 smb_share_dexit(arg, "door call error"); 271 smb_share_dclose(); 272 return (NERR_InternalError); 273 } 274 275 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 276 if (smb_share_dchk(dec_ctx) != 0) { 277 (void) smb_dr_decode_finish(dec_ctx); 278 smb_share_dexit(arg, "decode error"); 279 return (NERR_InternalError); 280 } 281 282 rc = smb_dr_get_uint32(dec_ctx); 283 if (smb_dr_decode_finish(dec_ctx) != 0) { 284 smb_share_dexit(arg, "decode error"); 285 return (NERR_InternalError); 286 } 287 288 smb_share_dexit(arg, NULL); 289 return (rc); 290 291 } 292 293 uint32_t 294 smb_share_rename(char *from, char *to) 295 { 296 door_arg_t *arg; 297 smb_dr_ctx_t *dec_ctx; 298 smb_dr_ctx_t *enc_ctx; 299 uint32_t rc; 300 301 if ((arg = smb_share_denter()) == NULL) 302 return (NERR_InternalError); 303 304 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 305 smb_dr_put_uint32(enc_ctx, SMB_SHROP_RENAME); 306 smb_dr_put_string(enc_ctx, from); 307 smb_dr_put_string(enc_ctx, to); 308 309 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 310 if (rc != 0) { 311 smb_share_dexit(arg, "encode error"); 312 return (NERR_InternalError); 313 } 314 315 if (door_call(smb_share_dfd, arg) < 0) { 316 smb_share_dexit(arg, "door call error"); 317 smb_share_dclose(); 318 return (NERR_InternalError); 319 } 320 321 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 322 if (smb_share_dchk(dec_ctx) != 0) { 323 (void) smb_dr_decode_finish(dec_ctx); 324 smb_share_dexit(arg, "decode error"); 325 return (NERR_InternalError); 326 } 327 328 rc = smb_dr_get_uint32(dec_ctx); 329 if (smb_dr_decode_finish(dec_ctx) != 0) { 330 smb_share_dexit(arg, "decode error"); 331 return (NERR_InternalError); 332 } 333 334 smb_share_dexit(arg, NULL); 335 return (rc); 336 } 337 338 uint32_t 339 smb_share_get(char *share_name, smb_share_t *si) 340 { 341 door_arg_t *arg; 342 smb_dr_ctx_t *dec_ctx; 343 smb_dr_ctx_t *enc_ctx; 344 uint32_t rc; 345 346 if ((arg = smb_share_denter()) == NULL) 347 return (NERR_InternalError); 348 349 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 350 smb_dr_put_uint32(enc_ctx, SMB_SHROP_GETINFO); 351 smb_dr_put_string(enc_ctx, share_name); 352 353 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 354 if (rc != 0) { 355 smb_share_dexit(arg, "encode error"); 356 return (NERR_InternalError); 357 } 358 359 if (door_call(smb_share_dfd, arg) < 0) { 360 smb_share_dexit(arg, "door call error"); 361 smb_share_dclose(); 362 return (NERR_InternalError); 363 } 364 365 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 366 if (smb_share_dchk(dec_ctx) != 0) { 367 (void) smb_dr_decode_finish(dec_ctx); 368 smb_share_dexit(arg, "decode error"); 369 return (NERR_InternalError); 370 } 371 372 rc = smb_dr_get_uint32(dec_ctx); 373 smb_dr_get_share(dec_ctx, si); 374 if (smb_dr_decode_finish(dec_ctx) != 0) { 375 smb_share_dexit(arg, "decode error"); 376 return (NERR_InternalError); 377 } 378 379 smb_share_dexit(arg, NULL); 380 return (rc); 381 } 382 383 uint32_t 384 smb_share_create(smb_share_t *si) 385 { 386 door_arg_t *arg; 387 smb_dr_ctx_t *dec_ctx; 388 smb_dr_ctx_t *enc_ctx; 389 uint32_t rc; 390 391 if ((arg = smb_share_denter()) == NULL) 392 return (NERR_InternalError); 393 394 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 395 smb_dr_put_uint32(enc_ctx, SMB_SHROP_ADD); 396 smb_dr_put_share(enc_ctx, si); 397 398 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 399 if (rc != 0) { 400 smb_share_dexit(arg, "encode error"); 401 return (NERR_InternalError); 402 } 403 404 if (door_call(smb_share_dfd, arg) < 0) { 405 smb_share_dexit(arg, "door call error"); 406 smb_share_dclose(); 407 return (NERR_InternalError); 408 } 409 410 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 411 if (smb_share_dchk(dec_ctx) != 0) { 412 (void) smb_dr_decode_finish(dec_ctx); 413 smb_share_dexit(arg, "decode error"); 414 return (NERR_InternalError); 415 } 416 417 rc = smb_dr_get_uint32(dec_ctx); 418 smb_dr_get_share(dec_ctx, si); 419 if (smb_dr_decode_finish(dec_ctx) != 0) { 420 smb_share_dexit(arg, "decode error"); 421 return (NERR_InternalError); 422 } 423 424 smb_share_dexit(arg, NULL); 425 return (rc); 426 } 427 428 uint32_t 429 smb_share_modify(char *sharename, char *cmnt, char *ad_container) 430 { 431 door_arg_t *arg; 432 smb_dr_ctx_t *dec_ctx; 433 smb_dr_ctx_t *enc_ctx; 434 uint32_t rc; 435 436 if ((arg = smb_share_denter()) == NULL) 437 return (NERR_InternalError); 438 439 enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE); 440 smb_dr_put_uint32(enc_ctx, SMB_SHROP_MODIFY); 441 smb_dr_put_string(enc_ctx, sharename); 442 smb_dr_put_string(enc_ctx, cmnt); 443 smb_dr_put_string(enc_ctx, ad_container); 444 445 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 446 if (rc != 0) { 447 smb_share_dexit(arg, "encode error"); 448 return (NERR_InternalError); 449 } 450 451 if (door_call(smb_share_dfd, arg) < 0) { 452 smb_share_dexit(arg, "door call error"); 453 smb_share_dclose(); 454 return (NERR_InternalError); 455 } 456 457 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 458 if (smb_share_dchk(dec_ctx) != 0) { 459 (void) smb_dr_decode_finish(dec_ctx); 460 smb_share_dexit(arg, "decode error"); 461 return (NERR_InternalError); 462 } 463 464 rc = smb_dr_get_uint32(dec_ctx); 465 if (smb_dr_decode_finish(dec_ctx) != 0) { 466 smb_share_dexit(arg, "decode error"); 467 return (NERR_InternalError); 468 } 469 470 smb_share_dexit(arg, NULL); 471 return (rc); 472 } 473