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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Client-side interface to the IO Daemon (IOD) 29 */ 30 31 #include <errno.h> 32 #include <fcntl.h> 33 #include <stdio.h> 34 #include <string.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <netdb.h> 38 #include <libintl.h> 39 #include <door.h> 40 41 #include <sys/byteorder.h> 42 #include <sys/types.h> 43 #include <sys/fcntl.h> 44 #include <sys/ioctl.h> 45 #include <sys/time.h> 46 #include <sys/socket.h> 47 48 #include <netinet/in.h> 49 #include <netinet/tcp.h> 50 #include <arpa/inet.h> 51 52 #include <netsmb/smb_lib.h> 53 #include <netsmb/netbios.h> 54 #include <netsmb/nb_lib.h> 55 #include <netsmb/smb_dev.h> 56 57 #include "charsets.h" 58 #include "private.h" 59 60 static const char smbiod_path[] = "/usr/lib/smbfs/smbiod"; 61 62 /* 63 * This is constant for the life of a process, 64 * and initialized at startup, so no locks. 65 */ 66 static char door_path[40]; 67 static int iod_start_timeout = 10; /* seconds */ 68 69 char * 70 smb_iod_door_path(void) 71 { 72 static const char fmtR[] = "/var/run/smbiod-%d"; 73 static const char fmtU[] = "/tmp/.smbiod-%d"; 74 const char *fmt; 75 uid_t uid; 76 77 if (door_path[0] == '\0') { 78 uid = getuid(); 79 fmt = (uid == 0) ? fmtR : fmtU; 80 snprintf(door_path, sizeof (door_path), fmt, uid); 81 } 82 83 return (door_path); 84 } 85 86 /* 87 * Open the door (client side) and 88 * find out if the service is there. 89 */ 90 int 91 smb_iod_open_door(int *fdp) 92 { 93 door_arg_t da; 94 char *path; 95 int fd, rc; 96 int err = 0; 97 98 path = smb_iod_door_path(); 99 fd = open(path, O_RDONLY, 0); 100 if (fd < 0) 101 return (errno); 102 103 /* 104 * Make sure the IOD is running. 105 * Pass NULL args. 106 */ 107 memset(&da, 0, sizeof (da)); 108 da.rbuf = (void *) &err; 109 da.rsize = sizeof (err); 110 rc = door_call(fd, &da); 111 if (rc < 0) { 112 err = errno; 113 close(fd); 114 return (err); 115 } 116 if (err != 0) { 117 close(fd); 118 return (err); 119 } 120 121 /* This handle controls per-process resources. */ 122 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 123 124 *fdp = fd; 125 return (0); 126 } 127 128 /* 129 * Start the IOD (if not already running) and 130 * wait until its door service is ready. 131 * On success, sets ctx->ct_door_fd 132 */ 133 int 134 smb_iod_start(smb_ctx_t *ctx) 135 { 136 int err, pid, tmo; 137 int fd = -1; 138 139 err = smb_iod_open_door(&fd); 140 if (err == 0) 141 goto OK; 142 143 pid = vfork(); 144 if (pid < 0) 145 return (errno); 146 147 /* 148 * child: start smbiod 149 */ 150 if (pid == 0) { 151 char *argv[2]; 152 argv[0] = "smbiod"; 153 argv[1] = NULL; 154 (void) execv(smbiod_path, argv); 155 _exit(1); 156 } 157 158 /* 159 * parent: wait for smbiod to start 160 */ 161 tmo = iod_start_timeout; 162 while (--tmo >= 0) { 163 (void) sleep(1); 164 err = smb_iod_open_door(&fd); 165 if (err == 0) 166 goto OK; 167 } 168 return (err); 169 170 OK: 171 /* Save the door fd. */ 172 if (ctx->ct_door_fd != -1) 173 close(ctx->ct_door_fd); 174 ctx->ct_door_fd = fd; 175 176 return (0); 177 } 178 179 180 /* 181 * Ask the IOD to connect using the info in ctx. 182 * Called by newvc. 183 */ 184 int 185 smb_iod_cl_newvc(smb_ctx_t *ctx) 186 { 187 door_arg_t da; 188 int err = 0; 189 190 /* Should already have the IOD door. */ 191 if (ctx->ct_door_fd < 0) 192 return (EINVAL); 193 194 da.data_ptr = (void *) &ctx->ct_iod_ssn; 195 da.data_size = sizeof (ctx->ct_iod_ssn); 196 da.desc_ptr = NULL; 197 da.desc_num = 0; 198 da.rbuf = (void *) &err; 199 da.rsize = sizeof (err); 200 if (door_call(ctx->ct_door_fd, &da) < 0) { 201 err = errno; 202 DPRINT("door_call, err=%d", err); 203 } 204 205 return (err); 206 } 207