1613a2f6bSGordon Ross /* 2613a2f6bSGordon Ross * CDDL HEADER START 3613a2f6bSGordon Ross * 4613a2f6bSGordon Ross * The contents of this file are subject to the terms of the 5613a2f6bSGordon Ross * Common Development and Distribution License (the "License"). 6613a2f6bSGordon Ross * You may not use this file except in compliance with the License. 7613a2f6bSGordon Ross * 8613a2f6bSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9613a2f6bSGordon Ross * or http://www.opensolaris.org/os/licensing. 10613a2f6bSGordon Ross * See the License for the specific language governing permissions 11613a2f6bSGordon Ross * and limitations under the License. 12613a2f6bSGordon Ross * 13613a2f6bSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14613a2f6bSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15613a2f6bSGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16613a2f6bSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17613a2f6bSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18613a2f6bSGordon Ross * 19613a2f6bSGordon Ross * CDDL HEADER END 20613a2f6bSGordon Ross */ 21613a2f6bSGordon Ross 22613a2f6bSGordon Ross /* 23*a547be5dSGordon Ross * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24613a2f6bSGordon Ross */ 25613a2f6bSGordon Ross 26613a2f6bSGordon Ross /* 27613a2f6bSGordon Ross * Client-side interface to the IO Daemon (IOD) 28613a2f6bSGordon Ross */ 29613a2f6bSGordon Ross 30613a2f6bSGordon Ross #include <errno.h> 31613a2f6bSGordon Ross #include <fcntl.h> 32613a2f6bSGordon Ross #include <stdio.h> 33613a2f6bSGordon Ross #include <string.h> 34613a2f6bSGordon Ross #include <stdlib.h> 35613a2f6bSGordon Ross #include <unistd.h> 36613a2f6bSGordon Ross #include <netdb.h> 37613a2f6bSGordon Ross #include <libintl.h> 38613a2f6bSGordon Ross #include <door.h> 39613a2f6bSGordon Ross 40613a2f6bSGordon Ross #include <sys/byteorder.h> 41613a2f6bSGordon Ross #include <sys/types.h> 42613a2f6bSGordon Ross #include <sys/fcntl.h> 43613a2f6bSGordon Ross #include <sys/ioctl.h> 44613a2f6bSGordon Ross #include <sys/time.h> 45613a2f6bSGordon Ross #include <sys/socket.h> 46613a2f6bSGordon Ross 47613a2f6bSGordon Ross #include <netinet/in.h> 48613a2f6bSGordon Ross #include <netinet/tcp.h> 49613a2f6bSGordon Ross #include <arpa/inet.h> 50613a2f6bSGordon Ross 51613a2f6bSGordon Ross #include <netsmb/smb_lib.h> 52613a2f6bSGordon Ross #include <netsmb/netbios.h> 53613a2f6bSGordon Ross #include <netsmb/nb_lib.h> 54613a2f6bSGordon Ross #include <netsmb/smb_dev.h> 55613a2f6bSGordon Ross 56*a547be5dSGordon Ross #include <assert.h> 57*a547be5dSGordon Ross 58613a2f6bSGordon Ross #include "charsets.h" 59613a2f6bSGordon Ross #include "private.h" 60613a2f6bSGordon Ross 61613a2f6bSGordon Ross /* 62613a2f6bSGordon Ross * This is constant for the life of a process, 63613a2f6bSGordon Ross * and initialized at startup, so no locks. 64613a2f6bSGordon Ross */ 65*a547be5dSGordon Ross static char door_path[64]; 666b2bcd8eSGordon Ross static int iod_start_timeout = 10; /* seconds */ 67613a2f6bSGordon Ross 68613a2f6bSGordon Ross char * 69613a2f6bSGordon Ross smb_iod_door_path(void) 70613a2f6bSGordon Ross { 71613a2f6bSGordon Ross uid_t uid; 72*a547be5dSGordon Ross int x; 73613a2f6bSGordon Ross 74613a2f6bSGordon Ross if (door_path[0] == '\0') { 75613a2f6bSGordon Ross uid = getuid(); 76*a547be5dSGordon Ross x = snprintf(door_path, sizeof (door_path), 77*a547be5dSGordon Ross SMBIOD_USR_DOOR, uid); 78*a547be5dSGordon Ross assert(x <= sizeof (door_path)); 79613a2f6bSGordon Ross } 80613a2f6bSGordon Ross 81613a2f6bSGordon Ross return (door_path); 82613a2f6bSGordon Ross } 83613a2f6bSGordon Ross 84613a2f6bSGordon Ross /* 85613a2f6bSGordon Ross * Open the door (client side) and 86613a2f6bSGordon Ross * find out if the service is there. 87613a2f6bSGordon Ross */ 88613a2f6bSGordon Ross int 89613a2f6bSGordon Ross smb_iod_open_door(int *fdp) 90613a2f6bSGordon Ross { 91613a2f6bSGordon Ross door_arg_t da; 92613a2f6bSGordon Ross char *path; 93613a2f6bSGordon Ross int fd, rc; 94613a2f6bSGordon Ross int err = 0; 95613a2f6bSGordon Ross 96613a2f6bSGordon Ross path = smb_iod_door_path(); 97613a2f6bSGordon Ross fd = open(path, O_RDONLY, 0); 98613a2f6bSGordon Ross if (fd < 0) 99613a2f6bSGordon Ross return (errno); 100613a2f6bSGordon Ross 101613a2f6bSGordon Ross /* 102613a2f6bSGordon Ross * Make sure the IOD is running. 103613a2f6bSGordon Ross * Pass NULL args. 104613a2f6bSGordon Ross */ 105613a2f6bSGordon Ross memset(&da, 0, sizeof (da)); 106613a2f6bSGordon Ross da.rbuf = (void *) &err; 107613a2f6bSGordon Ross da.rsize = sizeof (err); 108613a2f6bSGordon Ross rc = door_call(fd, &da); 109613a2f6bSGordon Ross if (rc < 0) { 110613a2f6bSGordon Ross err = errno; 111613a2f6bSGordon Ross close(fd); 112613a2f6bSGordon Ross return (err); 113613a2f6bSGordon Ross } 114613a2f6bSGordon Ross if (err != 0) { 115613a2f6bSGordon Ross close(fd); 116613a2f6bSGordon Ross return (err); 117613a2f6bSGordon Ross } 118613a2f6bSGordon Ross 119613a2f6bSGordon Ross /* This handle controls per-process resources. */ 120613a2f6bSGordon Ross (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 121613a2f6bSGordon Ross 122613a2f6bSGordon Ross *fdp = fd; 123613a2f6bSGordon Ross return (0); 124613a2f6bSGordon Ross } 125613a2f6bSGordon Ross 126613a2f6bSGordon Ross /* 127*a547be5dSGordon Ross * Request the creation of our per-user smbiod 128*a547be5dSGordon Ross * via door call to the "main" IOD service. 129*a547be5dSGordon Ross */ 130*a547be5dSGordon Ross static int 131*a547be5dSGordon Ross start_iod(void) 132*a547be5dSGordon Ross { 133*a547be5dSGordon Ross const char *svc_door = SMBIOD_SVC_DOOR; 134*a547be5dSGordon Ross door_arg_t da; 135*a547be5dSGordon Ross int32_t cmd, err; 136*a547be5dSGordon Ross int fd, rc; 137*a547be5dSGordon Ross 138*a547be5dSGordon Ross fd = open(svc_door, O_RDONLY, 0); 139*a547be5dSGordon Ross if (fd < 0) { 140*a547be5dSGordon Ross err = errno; 141*a547be5dSGordon Ross DPRINT("%s: open failed, err %d", svc_door, err); 142*a547be5dSGordon Ross return (err); 143*a547be5dSGordon Ross } 144*a547be5dSGordon Ross cmd = SMBIOD_START; 145*a547be5dSGordon Ross memset(&da, 0, sizeof (da)); 146*a547be5dSGordon Ross da.data_ptr = (void *) &cmd; 147*a547be5dSGordon Ross da.data_size = sizeof (cmd); 148*a547be5dSGordon Ross da.rbuf = (void *) &err; 149*a547be5dSGordon Ross da.rsize = sizeof (err); 150*a547be5dSGordon Ross rc = door_call(fd, &da); 151*a547be5dSGordon Ross close(fd); 152*a547be5dSGordon Ross if (rc < 0) { 153*a547be5dSGordon Ross err = errno; 154*a547be5dSGordon Ross DPRINT("door_call, err %d", err); 155*a547be5dSGordon Ross return (err); 156*a547be5dSGordon Ross } 157*a547be5dSGordon Ross 158*a547be5dSGordon Ross return (err); 159*a547be5dSGordon Ross } 160*a547be5dSGordon Ross 161*a547be5dSGordon Ross /* 162*a547be5dSGordon Ross * Get a door handle to the IOD, starting it if necessary. 1636b2bcd8eSGordon Ross * On success, sets ctx->ct_door_fd 164613a2f6bSGordon Ross */ 1656b2bcd8eSGordon Ross int 1666b2bcd8eSGordon Ross smb_iod_start(smb_ctx_t *ctx) 167613a2f6bSGordon Ross { 168*a547be5dSGordon Ross int err, tmo; 1696b2bcd8eSGordon Ross int fd = -1; 1706b2bcd8eSGordon Ross 1716b2bcd8eSGordon Ross tmo = iod_start_timeout; 172*a547be5dSGordon Ross while ((err = smb_iod_open_door(&fd)) != 0) { 173*a547be5dSGordon Ross if (--tmo <= 0) 174*a547be5dSGordon Ross goto errout; 1756b2bcd8eSGordon Ross 176*a547be5dSGordon Ross /* 177*a547be5dSGordon Ross * We have no per-user IOD yet. Request one. 178*a547be5dSGordon Ross * Do this request every time through the loop 179*a547be5dSGordon Ross * because the master IOD will only start our 180*a547be5dSGordon Ross * per-user IOD if we don't have one, and our 181*a547be5dSGordon Ross * first requst could have happened while we 182*a547be5dSGordon Ross * had an IOD that was doing shutdown. 183*a547be5dSGordon Ross * (Prevents a shutdown/startup race). 184*a547be5dSGordon Ross */ 185*a547be5dSGordon Ross err = start_iod(); 186*a547be5dSGordon Ross if (err != 0) 187*a547be5dSGordon Ross goto errout; 188*a547be5dSGordon Ross /* 189*a547be5dSGordon Ross * Wait for it to get ready. 190*a547be5dSGordon Ross */ 191*a547be5dSGordon Ross (void) sleep(1); 192*a547be5dSGordon Ross } 193*a547be5dSGordon Ross 1946b2bcd8eSGordon Ross /* Save the door fd. */ 1956b2bcd8eSGordon Ross if (ctx->ct_door_fd != -1) 1966b2bcd8eSGordon Ross close(ctx->ct_door_fd); 1976b2bcd8eSGordon Ross ctx->ct_door_fd = fd; 1986b2bcd8eSGordon Ross 1996b2bcd8eSGordon Ross return (0); 200613a2f6bSGordon Ross 201*a547be5dSGordon Ross errout: 202*a547be5dSGordon Ross smb_error(dgettext(TEXT_DOMAIN, 203*a547be5dSGordon Ross "Could not contact service: %s"), 204*a547be5dSGordon Ross 0, "svc:/network/smb/client"); 205*a547be5dSGordon Ross return (ENOTACTIVE); 206*a547be5dSGordon Ross } 207613a2f6bSGordon Ross 208613a2f6bSGordon Ross /* 2096b2bcd8eSGordon Ross * Ask the IOD to connect using the info in ctx. 2106b2bcd8eSGordon Ross * Called by newvc. 211613a2f6bSGordon Ross */ 212613a2f6bSGordon Ross int 213613a2f6bSGordon Ross smb_iod_cl_newvc(smb_ctx_t *ctx) 214613a2f6bSGordon Ross { 215613a2f6bSGordon Ross door_arg_t da; 2166b2bcd8eSGordon Ross int err = 0; 217613a2f6bSGordon Ross 2186b2bcd8eSGordon Ross /* Should already have the IOD door. */ 2196b2bcd8eSGordon Ross if (ctx->ct_door_fd < 0) 2206b2bcd8eSGordon Ross return (EINVAL); 221613a2f6bSGordon Ross 222613a2f6bSGordon Ross da.data_ptr = (void *) &ctx->ct_iod_ssn; 223613a2f6bSGordon Ross da.data_size = sizeof (ctx->ct_iod_ssn); 224613a2f6bSGordon Ross da.desc_ptr = NULL; 225613a2f6bSGordon Ross da.desc_num = 0; 226613a2f6bSGordon Ross da.rbuf = (void *) &err; 227613a2f6bSGordon Ross da.rsize = sizeof (err); 2286b2bcd8eSGordon Ross if (door_call(ctx->ct_door_fd, &da) < 0) { 229613a2f6bSGordon Ross err = errno; 230613a2f6bSGordon Ross DPRINT("door_call, err=%d", err); 231613a2f6bSGordon Ross } 232613a2f6bSGordon Ross 233613a2f6bSGordon Ross return (err); 234613a2f6bSGordon Ross } 235