15331Samw /*
25331Samw * CDDL HEADER START
35331Samw *
45331Samw * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
75331Samw *
85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw * or http://www.opensolaris.org/os/licensing.
105331Samw * See the License for the specific language governing permissions
115331Samw * and limitations under the License.
125331Samw *
135331Samw * When distributing Covered Code, include this CDDL HEADER in each
145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw * If applicable, add the following below this CDDL HEADER, with the
165331Samw * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw *
195331Samw * CDDL HEADER END
205331Samw */
215331Samw
225331Samw /*
23*12508Samw@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
245331Samw */
255331Samw
265331Samw /*
275331Samw * User-space door client for LanMan share management.
285331Samw */
295331Samw
305331Samw #include <syslog.h>
315331Samw #include <door.h>
325331Samw #include <fcntl.h>
335331Samw #include <stdarg.h>
345331Samw #include <errno.h>
355331Samw #include <string.h>
365331Samw #include <strings.h>
375772Sas200622 #include <unistd.h>
385772Sas200622 #include <thread.h>
395772Sas200622 #include <synch.h>
405331Samw
415331Samw #include <smbsrv/libsmb.h>
427052Samw #include <smbsrv/smb_share.h>
4310966SJordan.Brown@Sun.COM #include <smbsrv/smb.h>
445331Samw
457588Samw@Sun.COM #define SMB_SHARE_DOOR_CALL_RETRIES 3
467588Samw@Sun.COM
477052Samw static int smb_share_dfd = -1;
487052Samw static uint64_t smb_share_dncall = 0;
497052Samw static mutex_t smb_share_dmtx;
507052Samw static cond_t smb_share_dcv;
515331Samw
527588Samw@Sun.COM static int smb_share_door_clnt_open(void);
537588Samw@Sun.COM static void smb_share_door_clnt_close(void);
547588Samw@Sun.COM
557588Samw@Sun.COM void
smb_share_door_clnt_init(void)567588Samw@Sun.COM smb_share_door_clnt_init(void)
577588Samw@Sun.COM {
587588Samw@Sun.COM (void) mutex_lock(&smb_share_dmtx);
597588Samw@Sun.COM (void) smb_share_door_clnt_open();
607588Samw@Sun.COM (void) mutex_unlock(&smb_share_dmtx);
617588Samw@Sun.COM }
627588Samw@Sun.COM
637588Samw@Sun.COM void
smb_share_door_clnt_fini(void)647588Samw@Sun.COM smb_share_door_clnt_fini(void)
657588Samw@Sun.COM {
667588Samw@Sun.COM (void) mutex_lock(&smb_share_dmtx);
677588Samw@Sun.COM smb_share_door_clnt_close();
687588Samw@Sun.COM (void) mutex_unlock(&smb_share_dmtx);
697588Samw@Sun.COM }
707588Samw@Sun.COM
715331Samw /*
727588Samw@Sun.COM * Open smb_share_door. This is a private call for use by
737588Samw@Sun.COM * smb_share_door_clnt_enter() and must be called with smb_share_dmtx held.
745772Sas200622 *
755772Sas200622 * Returns the door fd on success. Otherwise, -1.
765331Samw */
775331Samw static int
smb_share_door_clnt_open(void)787588Samw@Sun.COM smb_share_door_clnt_open(void)
795331Samw {
807052Samw if (smb_share_dfd == -1) {
817052Samw if ((smb_share_dfd = open(SMB_SHARE_DNAME, O_RDONLY)) < 0)
827052Samw smb_share_dfd = -1;
835772Sas200622 else
847052Samw smb_share_dncall = 0;
855772Sas200622 }
865772Sas200622
877052Samw return (smb_share_dfd);
885772Sas200622 }
895772Sas200622
905772Sas200622 /*
917588Samw@Sun.COM * Close smb_share_door.
927588Samw@Sun.COM * Private call that must be called with smb_share_dmtx held.
935772Sas200622 */
947588Samw@Sun.COM static void
smb_share_door_clnt_close(void)957588Samw@Sun.COM smb_share_door_clnt_close(void)
965772Sas200622 {
977052Samw if (smb_share_dfd != -1) {
987052Samw while (smb_share_dncall > 0)
997052Samw (void) cond_wait(&smb_share_dcv, &smb_share_dmtx);
1005772Sas200622
1017052Samw if (smb_share_dfd != -1) {
1027052Samw (void) close(smb_share_dfd);
1037052Samw smb_share_dfd = -1;
1045772Sas200622 }
1055772Sas200622 }
1065772Sas200622 }
1075331Samw
1085772Sas200622 /*
1097588Samw@Sun.COM * Entry handler for smb_share_door calls.
1105772Sas200622 */
1115772Sas200622 static door_arg_t *
smb_share_door_clnt_enter(void)1127588Samw@Sun.COM smb_share_door_clnt_enter(void)
1135772Sas200622 {
1145772Sas200622 door_arg_t *arg;
1155772Sas200622 char *buf;
1165772Sas200622
1177052Samw (void) mutex_lock(&smb_share_dmtx);
1185772Sas200622
1197588Samw@Sun.COM if (smb_share_door_clnt_open() == -1) {
1207052Samw (void) mutex_unlock(&smb_share_dmtx);
1215772Sas200622 return (NULL);
1225331Samw }
1235772Sas200622
1247052Samw if ((arg = malloc(sizeof (door_arg_t) + SMB_SHARE_DSIZE)) != NULL) {
1255772Sas200622 buf = ((char *)arg) + sizeof (door_arg_t);
1265772Sas200622 bzero(arg, sizeof (door_arg_t));
1275772Sas200622 arg->data_ptr = buf;
1285772Sas200622 arg->rbuf = buf;
1297052Samw arg->rsize = SMB_SHARE_DSIZE;
1305772Sas200622
1317052Samw ++smb_share_dncall;
1325772Sas200622 }
1335772Sas200622
1347052Samw (void) mutex_unlock(&smb_share_dmtx);
1355772Sas200622 return (arg);
1365772Sas200622 }
1375772Sas200622
1385772Sas200622 /*
1397588Samw@Sun.COM * Exit handler for smb_share_door calls.
1405772Sas200622 */
1415772Sas200622 static void
smb_share_door_clnt_exit(door_arg_t * arg,boolean_t must_close,char * errmsg)1427588Samw@Sun.COM smb_share_door_clnt_exit(door_arg_t *arg, boolean_t must_close, char *errmsg)
1435772Sas200622 {
1445772Sas200622 if (errmsg)
1457588Samw@Sun.COM syslog(LOG_DEBUG, "smb_share_door: %s failed", errmsg);
1465772Sas200622
1477052Samw (void) mutex_lock(&smb_share_dmtx);
1485772Sas200622 free(arg);
1497052Samw --smb_share_dncall;
1507052Samw (void) cond_signal(&smb_share_dcv);
1517588Samw@Sun.COM
1527588Samw@Sun.COM if (must_close)
1537588Samw@Sun.COM smb_share_door_clnt_close();
1547588Samw@Sun.COM
1557052Samw (void) mutex_unlock(&smb_share_dmtx);
1565331Samw }
1575331Samw
1587588Samw@Sun.COM static int
smb_share_door_call(int fd,door_arg_t * arg)1597588Samw@Sun.COM smb_share_door_call(int fd, door_arg_t *arg)
1607588Samw@Sun.COM {
1617588Samw@Sun.COM int rc;
1627588Samw@Sun.COM int i;
1637588Samw@Sun.COM
1647588Samw@Sun.COM for (i = 0; i < SMB_SHARE_DOOR_CALL_RETRIES; ++i) {
1657588Samw@Sun.COM errno = 0;
1667588Samw@Sun.COM
1677588Samw@Sun.COM if ((rc = door_call(fd, arg)) == 0)
1687588Samw@Sun.COM break;
1697588Samw@Sun.COM
1707588Samw@Sun.COM if (errno != EAGAIN && errno != EINTR)
1717588Samw@Sun.COM break;
1727588Samw@Sun.COM }
1737588Samw@Sun.COM
1747588Samw@Sun.COM return (rc);
1757588Samw@Sun.COM }
1767588Samw@Sun.COM
1775331Samw static int
smb_share_dchk(smb_dr_ctx_t * dec_ctx)1787052Samw smb_share_dchk(smb_dr_ctx_t *dec_ctx)
1795331Samw {
1805331Samw int status = smb_dr_get_int32(dec_ctx);
1815331Samw
1827052Samw if (status != SMB_SHARE_DSUCCESS) {
1837052Samw if (status == SMB_SHARE_DERROR)
1845772Sas200622 (void) smb_dr_get_uint32(dec_ctx);
1855772Sas200622 return (-1);
1865331Samw }
1875331Samw
1885772Sas200622 return (0);
1895331Samw }
1905331Samw
1917052Samw uint32_t
smb_share_list(int offset,smb_shrlist_t * list)1927052Samw smb_share_list(int offset, smb_shrlist_t *list)
1935331Samw {
1945772Sas200622 door_arg_t *arg;
1955331Samw smb_dr_ctx_t *dec_ctx;
1965331Samw smb_dr_ctx_t *enc_ctx;
1977052Samw uint32_t rc;
1985331Samw
1997348SJose.Borrego@Sun.COM bzero(list, sizeof (smb_shrlist_t));
2007348SJose.Borrego@Sun.COM
2017588Samw@Sun.COM if ((arg = smb_share_door_clnt_enter()) == NULL)
2025331Samw return (NERR_InternalError);
2035331Samw
2047052Samw enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
2057052Samw smb_dr_put_uint32(enc_ctx, SMB_SHROP_LIST);
2065331Samw smb_dr_put_int32(enc_ctx, offset);
2075331Samw
2085772Sas200622 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
2095772Sas200622 if (rc != 0) {
2107588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "encode");
2115331Samw return (NERR_InternalError);
2125331Samw }
2135331Samw
2147588Samw@Sun.COM if (smb_share_door_call(smb_share_dfd, arg) < 0) {
2157588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_TRUE, "door call");
2165331Samw return (NERR_InternalError);
2175331Samw }
2185331Samw
2195772Sas200622 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
2207052Samw if (smb_share_dchk(dec_ctx) != 0) {
2215772Sas200622 (void) smb_dr_decode_finish(dec_ctx);
2227588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
2235331Samw return (NERR_InternalError);
2245331Samw }
2255331Samw
2267348SJose.Borrego@Sun.COM (void) smb_dr_get_buf(dec_ctx, (unsigned char *)list,
2277348SJose.Borrego@Sun.COM sizeof (smb_shrlist_t));
2285772Sas200622 if (smb_dr_decode_finish(dec_ctx) != 0) {
2297588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
2305331Samw return (NERR_InternalError);
2315331Samw }
2325331Samw
2337588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, NULL);
2346771Sjb150015 return (NERR_Success);
2355331Samw }
2365331Samw
2375331Samw int
smb_share_count(void)2387052Samw smb_share_count(void)
2395331Samw {
2405772Sas200622 door_arg_t *arg;
2415331Samw smb_dr_ctx_t *dec_ctx;
2425331Samw smb_dr_ctx_t *enc_ctx;
2437052Samw uint32_t num_shares;
2445772Sas200622 int rc;
2455331Samw
2467588Samw@Sun.COM if ((arg = smb_share_door_clnt_enter()) == NULL)
2475331Samw return (-1);
2485331Samw
2497052Samw enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
2507052Samw smb_dr_put_uint32(enc_ctx, SMB_SHROP_NUM_SHARES);
2515331Samw
2525772Sas200622 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
2535772Sas200622 if (rc != 0) {
2547588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "encode");
2555331Samw return (-1);
2565331Samw }
2575331Samw
2587588Samw@Sun.COM if (smb_share_door_call(smb_share_dfd, arg) < 0) {
2597588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_TRUE, "door call");
2605331Samw return (-1);
2615331Samw }
2625331Samw
2635772Sas200622 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
2647052Samw if (smb_share_dchk(dec_ctx) != 0) {
2655772Sas200622 (void) smb_dr_decode_finish(dec_ctx);
2667588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
2675331Samw return (-1);
2685331Samw }
2695331Samw
2705331Samw num_shares = smb_dr_get_uint32(dec_ctx);
2715772Sas200622 if (smb_dr_decode_finish(dec_ctx) != 0) {
2727588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
2735331Samw return (-1);
2745331Samw }
2755331Samw
2767588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, NULL);
2775331Samw return (num_shares);
2785331Samw }
2795331Samw
2807052Samw uint32_t
smb_share_delete(char * share_name)2817348SJose.Borrego@Sun.COM smb_share_delete(char *share_name)
2825331Samw {
2835772Sas200622 door_arg_t *arg;
2845331Samw smb_dr_ctx_t *dec_ctx;
2855331Samw smb_dr_ctx_t *enc_ctx;
2867052Samw uint32_t rc;
2875331Samw
2887588Samw@Sun.COM if ((arg = smb_share_door_clnt_enter()) == NULL)
2895331Samw return (NERR_InternalError);
2905331Samw
2917052Samw enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
2927052Samw smb_dr_put_uint32(enc_ctx, SMB_SHROP_DELETE);
2935331Samw smb_dr_put_string(enc_ctx, share_name);
2945331Samw
2955772Sas200622 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
2965772Sas200622 if (rc != 0) {
2977588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "encode");
2985331Samw return (NERR_InternalError);
2995331Samw }
3005331Samw
3017588Samw@Sun.COM if (smb_share_door_call(smb_share_dfd, arg) < 0) {
3027588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_TRUE, "door call");
3035331Samw return (NERR_InternalError);
3045331Samw }
3055331Samw
3065772Sas200622 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
3077052Samw if (smb_share_dchk(dec_ctx) != 0) {
3085772Sas200622 (void) smb_dr_decode_finish(dec_ctx);
3097588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
3105331Samw return (NERR_InternalError);
3115331Samw }
3125331Samw
3135331Samw rc = smb_dr_get_uint32(dec_ctx);
3145772Sas200622 if (smb_dr_decode_finish(dec_ctx) != 0) {
3157588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
3165331Samw return (NERR_InternalError);
3175331Samw }
3185331Samw
3197588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, NULL);
3205331Samw return (rc);
3217052Samw
3225331Samw }
3235331Samw
3247052Samw uint32_t
smb_share_rename(char * from,char * to)3257348SJose.Borrego@Sun.COM smb_share_rename(char *from, char *to)
3265331Samw {
3275772Sas200622 door_arg_t *arg;
3285331Samw smb_dr_ctx_t *dec_ctx;
3295331Samw smb_dr_ctx_t *enc_ctx;
3307052Samw uint32_t rc;
3315331Samw
3327588Samw@Sun.COM if ((arg = smb_share_door_clnt_enter()) == NULL)
3335331Samw return (NERR_InternalError);
3345331Samw
3357052Samw enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
3367052Samw smb_dr_put_uint32(enc_ctx, SMB_SHROP_RENAME);
3377052Samw smb_dr_put_string(enc_ctx, from);
3387052Samw smb_dr_put_string(enc_ctx, to);
3395331Samw
3405772Sas200622 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
3415772Sas200622 if (rc != 0) {
3427588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "encode");
3435331Samw return (NERR_InternalError);
3445331Samw }
3455331Samw
3467588Samw@Sun.COM if (smb_share_door_call(smb_share_dfd, arg) < 0) {
3477588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_TRUE, "door call");
3485331Samw return (NERR_InternalError);
3495331Samw }
3505331Samw
3515772Sas200622 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
3527052Samw if (smb_share_dchk(dec_ctx) != 0) {
3535772Sas200622 (void) smb_dr_decode_finish(dec_ctx);
3547588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
3555331Samw return (NERR_InternalError);
3565331Samw }
3575331Samw
3585331Samw rc = smb_dr_get_uint32(dec_ctx);
3595772Sas200622 if (smb_dr_decode_finish(dec_ctx) != 0) {
3607588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
3615331Samw return (NERR_InternalError);
3625331Samw }
3635331Samw
3647588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, NULL);
3655331Samw return (rc);
3665331Samw }
3675331Samw
3687052Samw uint32_t
smb_share_create(smb_share_t * si)3697348SJose.Borrego@Sun.COM smb_share_create(smb_share_t *si)
3705331Samw {
3717052Samw door_arg_t *arg;
3727052Samw smb_dr_ctx_t *dec_ctx;
3737052Samw smb_dr_ctx_t *enc_ctx;
3747052Samw uint32_t rc;
3757052Samw
3767588Samw@Sun.COM if ((arg = smb_share_door_clnt_enter()) == NULL)
3777052Samw return (NERR_InternalError);
3787052Samw
3797052Samw enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
3807052Samw smb_dr_put_uint32(enc_ctx, SMB_SHROP_ADD);
3817052Samw smb_dr_put_share(enc_ctx, si);
3827052Samw
3837052Samw rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
3847052Samw if (rc != 0) {
3857588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "encode");
3867052Samw return (NERR_InternalError);
3877052Samw }
3885331Samw
3897588Samw@Sun.COM if (smb_share_door_call(smb_share_dfd, arg) < 0) {
3907588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_TRUE, "door call");
3917052Samw return (NERR_InternalError);
3927052Samw }
3935331Samw
3947052Samw dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
3957052Samw if (smb_share_dchk(dec_ctx) != 0) {
3967052Samw (void) smb_dr_decode_finish(dec_ctx);
3977588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
3987052Samw return (NERR_InternalError);
3997052Samw }
4007052Samw
4017052Samw rc = smb_dr_get_uint32(dec_ctx);
4027052Samw smb_dr_get_share(dec_ctx, si);
4037052Samw if (smb_dr_decode_finish(dec_ctx) != 0) {
4047588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
4057052Samw return (NERR_InternalError);
4067052Samw }
4077052Samw
4087588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, NULL);
4097052Samw return (rc);
4105331Samw }
4115331Samw
4127052Samw uint32_t
smb_share_modify(smb_share_t * si)4137961SNatalie.Li@Sun.COM smb_share_modify(smb_share_t *si)
4145331Samw {
4157052Samw door_arg_t *arg;
4167052Samw smb_dr_ctx_t *dec_ctx;
4177052Samw smb_dr_ctx_t *enc_ctx;
4187052Samw uint32_t rc;
4197052Samw
4207588Samw@Sun.COM if ((arg = smb_share_door_clnt_enter()) == NULL)
4217052Samw return (NERR_InternalError);
4227052Samw
4237052Samw enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
4247348SJose.Borrego@Sun.COM smb_dr_put_uint32(enc_ctx, SMB_SHROP_MODIFY);
4257961SNatalie.Li@Sun.COM smb_dr_put_share(enc_ctx, si);
4267052Samw
4277052Samw rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
4287052Samw if (rc != 0) {
4297588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "encode");
4307052Samw return (NERR_InternalError);
4317052Samw }
4325331Samw
4337588Samw@Sun.COM if (smb_share_door_call(smb_share_dfd, arg) < 0) {
4347588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_TRUE, "door call");
4357052Samw return (NERR_InternalError);
4367052Samw }
4377052Samw
4387052Samw dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
4397052Samw if (smb_share_dchk(dec_ctx) != 0) {
4407052Samw (void) smb_dr_decode_finish(dec_ctx);
4417588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
4427052Samw return (NERR_InternalError);
4437052Samw }
4447052Samw
4457052Samw rc = smb_dr_get_uint32(dec_ctx);
4467052Samw if (smb_dr_decode_finish(dec_ctx) != 0) {
4477588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, "decode");
4487052Samw return (NERR_InternalError);
4497052Samw }
4507052Samw
4517588Samw@Sun.COM smb_share_door_clnt_exit(arg, B_FALSE, NULL);
4527052Samw return (rc);
4535331Samw }
454