1cb5caa98Sdjl /* 2cb5caa98Sdjl * CDDL HEADER START 3cb5caa98Sdjl * 4cb5caa98Sdjl * The contents of this file are subject to the terms of the 5cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6cb5caa98Sdjl * You may not use this file except in compliance with the License. 7cb5caa98Sdjl * 8cb5caa98Sdjl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9cb5caa98Sdjl * or http://www.opensolaris.org/os/licensing. 10cb5caa98Sdjl * See the License for the specific language governing permissions 11cb5caa98Sdjl * and limitations under the License. 12cb5caa98Sdjl * 13cb5caa98Sdjl * When distributing Covered Code, include this CDDL HEADER in each 14cb5caa98Sdjl * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15cb5caa98Sdjl * If applicable, add the following below this CDDL HEADER, with the 16cb5caa98Sdjl * fields enclosed by brackets "[]" replaced with your own identifying 17cb5caa98Sdjl * information: Portions Copyright [yyyy] [name of copyright owner] 18cb5caa98Sdjl * 19cb5caa98Sdjl * CDDL HEADER END 20cb5caa98Sdjl */ 21cb5caa98Sdjl 22cb5caa98Sdjl /* 23606f6aa3Smichen * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24cb5caa98Sdjl * Use is subject to license terms. 25*7d7551bcSMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved. 26cb5caa98Sdjl */ 27cb5caa98Sdjl 28cb5caa98Sdjl #include <sys/param.h> 29cb5caa98Sdjl #include <string.h> 30cb5caa98Sdjl #include <door.h> 31cb5caa98Sdjl #include <sys/mman.h> 32cb5caa98Sdjl #include "nscd_door.h" 33cb5caa98Sdjl #include "nscd_log.h" 34cb5caa98Sdjl #include <getxby_door.h> 35cb5caa98Sdjl #include <sys/types.h> 36cb5caa98Sdjl #include <errno.h> 37cb5caa98Sdjl #include <fcntl.h> 38cb5caa98Sdjl 39cb5caa98Sdjl static void 40cb5caa98Sdjl initdoor(void *buf, int *doorfd) 41cb5caa98Sdjl { 42cb5caa98Sdjl nss_pheader_t *phdr = (nss_pheader_t *)buf; 43cb5caa98Sdjl door_info_t doori; 44cb5caa98Sdjl char *me = "initdoor"; 45cb5caa98Sdjl 46cb5caa98Sdjl *doorfd = open64(NAME_SERVICE_DOOR, O_RDONLY, 0); 47cb5caa98Sdjl 48cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 49cb5caa98Sdjl (me, "door is %s (fd is %d)\n", NAME_SERVICE_DOOR, 50cb5caa98Sdjl *doorfd); 51cb5caa98Sdjl 52*7d7551bcSMilan Jurik if (*doorfd == -1) { 53*7d7551bcSMilan Jurik NSCD_SET_STATUS(phdr, NSS_ERROR, errno); 54*7d7551bcSMilan Jurik return; 55*7d7551bcSMilan Jurik } 56cb5caa98Sdjl 57cb5caa98Sdjl if (door_info(*doorfd, &doori) < 0 || 58cb5caa98Sdjl (doori.di_attributes & DOOR_REVOKED) || 59cb5caa98Sdjl doori.di_data != (uintptr_t)NAME_SERVICE_DOOR_COOKIE) { 60cb5caa98Sdjl 61cb5caa98Sdjl /* 62cb5caa98Sdjl * we should close doorfd because we just opened it 63cb5caa98Sdjl */ 64cb5caa98Sdjl (void) close(*doorfd); 65cb5caa98Sdjl 66cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 67cb5caa98Sdjl (me, "door %d not valid\n", *doorfd); 68cb5caa98Sdjl 69*7d7551bcSMilan Jurik NSCD_SET_STATUS(phdr, NSS_ERROR, ECONNREFUSED); 70*7d7551bcSMilan Jurik return; 71cb5caa98Sdjl } 72cb5caa98Sdjl 73*7d7551bcSMilan Jurik NSCD_SET_STATUS_SUCCESS(phdr); 74cb5caa98Sdjl } 75cb5caa98Sdjl 76cb5caa98Sdjl /* general door call functions used by nscd */ 77cb5caa98Sdjl 78cb5caa98Sdjl static nss_status_t 79cb5caa98Sdjl copy_output(void *outdata, int outdlen, 80cb5caa98Sdjl nss_pheader_t *phdr, nss_pheader_t *outphdr) 81cb5caa98Sdjl { 82cb5caa98Sdjl void *dp; 83cb5caa98Sdjl nss_status_t ret = NSS_SUCCESS; 84cb5caa98Sdjl char *me = "copy_output"; 85cb5caa98Sdjl 86cb5caa98Sdjl if (outdata != NULL && phdr->data_off > 0 && phdr->data_len > 0) { 87cb5caa98Sdjl if (phdr->data_len <= outdlen) { 88cb5caa98Sdjl dp = (char *)phdr + phdr->data_off; 89cb5caa98Sdjl (void) memmove(outdata, dp, phdr->data_len); 90cb5caa98Sdjl } else { 91cb5caa98Sdjl 92*7d7551bcSMilan Jurik _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 93cb5caa98Sdjl (me, "output buffer not large enough " 94cb5caa98Sdjl " should be > %d but is %d\n", 95cb5caa98Sdjl phdr->data_len, outdlen); 96cb5caa98Sdjl 97cb5caa98Sdjl if (outphdr != NULL) { 98cb5caa98Sdjl NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 99cb5caa98Sdjl 0, NSCD_INVALID_ARGUMENT); 100cb5caa98Sdjl NSCD_COPY_STATUS(outphdr, phdr); 101cb5caa98Sdjl } 102cb5caa98Sdjl ret = NSS_NSCD_PRIV; 103cb5caa98Sdjl } 104cb5caa98Sdjl } 105cb5caa98Sdjl 106cb5caa98Sdjl return (ret); 107cb5caa98Sdjl } 108cb5caa98Sdjl 109cb5caa98Sdjl nss_status_t 110cb5caa98Sdjl _nscd_doorcall(int callnum) 111cb5caa98Sdjl { 112606f6aa3Smichen size_t buflen; 113606f6aa3Smichen nss_pheader_t *phdr; 114cb5caa98Sdjl void *dptr; 115cb5caa98Sdjl size_t ndata; 116cb5caa98Sdjl size_t adata; 117cb5caa98Sdjl int ret; 118cb5caa98Sdjl char *me = "_nscd_doorcall"; 119cb5caa98Sdjl 120cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 121cb5caa98Sdjl (me, "processing door call %d ...\n", callnum); 122cb5caa98Sdjl 123606f6aa3Smichen /* allocate door buffer from the stack */ 124606f6aa3Smichen NSCD_ALLOC_DOORBUF(callnum, 0, dptr, buflen); 125606f6aa3Smichen ndata = buflen; 126606f6aa3Smichen adata = buflen; 127606f6aa3Smichen 128cb5caa98Sdjl ret = _nsc_trydoorcall(&dptr, &ndata, &adata); 129cb5caa98Sdjl 130cb5caa98Sdjl if (ret != NSS_SUCCESS) { 131606f6aa3Smichen phdr = (nss_pheader_t *)dptr; 132cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 133cb5caa98Sdjl (me, "door call (%d) failed (status = %d, error = %s)\n", 134606f6aa3Smichen callnum, ret, strerror(NSCD_GET_ERRNO(phdr))); 135cb5caa98Sdjl } 136cb5caa98Sdjl 137cb5caa98Sdjl return (ret); 138cb5caa98Sdjl } 139cb5caa98Sdjl 140606f6aa3Smichen 141cb5caa98Sdjl nss_status_t 142cb5caa98Sdjl _nscd_doorcall_data(int callnum, void *indata, int indlen, 143cb5caa98Sdjl void *outdata, int outdlen, nss_pheader_t *phdr) 144cb5caa98Sdjl { 145cb5caa98Sdjl void *uptr; 146cb5caa98Sdjl size_t buflen; 147cb5caa98Sdjl void *dptr; 148cb5caa98Sdjl void *datap; 149cb5caa98Sdjl size_t ndata; 150cb5caa98Sdjl size_t adata; 151cb5caa98Sdjl nss_pheader_t *phdr_d; 152cb5caa98Sdjl int ret; 153cb5caa98Sdjl char *me = "_nscd_doorcall_data"; 154cb5caa98Sdjl 155cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 156cb5caa98Sdjl (me, "processing door call %d ...\n", callnum); 157cb5caa98Sdjl 158cb5caa98Sdjl /* allocate door buffer from the stack */ 159cb5caa98Sdjl NSCD_ALLOC_DOORBUF(callnum, indlen, uptr, buflen); 160cb5caa98Sdjl dptr = uptr; 161cb5caa98Sdjl ndata = buflen; 162cb5caa98Sdjl adata = buflen; 163cb5caa98Sdjl datap = NSCD_N2N_DOOR_DATA(void, dptr); 164cb5caa98Sdjl if (indata != NULL) 165cb5caa98Sdjl (void) memmove(datap, indata, indlen); 166cb5caa98Sdjl 167cb5caa98Sdjl ret = _nsc_trydoorcall(&dptr, &ndata, &adata); 168cb5caa98Sdjl 169cb5caa98Sdjl phdr_d = (nss_pheader_t *)dptr; 170cb5caa98Sdjl if (ret != NSS_SUCCESS) { 171cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 172cb5caa98Sdjl (me, "door call (%d) failed (status = %d, error = %s)\n", 173cb5caa98Sdjl callnum, ret, strerror(NSCD_GET_ERRNO(phdr_d))); 174cb5caa98Sdjl } else { 175cb5caa98Sdjl if (phdr != NULL) { 176cb5caa98Sdjl NSCD_COPY_STATUS(phdr, phdr_d); 177cb5caa98Sdjl } 178cb5caa98Sdjl ret = copy_output(outdata, outdlen, phdr_d, phdr); 179cb5caa98Sdjl } 180cb5caa98Sdjl 181cb5caa98Sdjl /* if new buffer allocated for this door call, free it */ 182cb5caa98Sdjl if (dptr != uptr) 183cb5caa98Sdjl (void) munmap(dptr, ndata); 184cb5caa98Sdjl 185cb5caa98Sdjl return (ret); 186cb5caa98Sdjl } 187cb5caa98Sdjl 188cb5caa98Sdjl nss_status_t 189cb5caa98Sdjl _nscd_doorcall_fd(int fd, int callnum, void *indata, int indlen, 190cb5caa98Sdjl void *outdata, int outdlen, nss_pheader_t *phdr) 191cb5caa98Sdjl { 192cb5caa98Sdjl void *uptr; 193cb5caa98Sdjl void *dptr; 194cb5caa98Sdjl void *datap; 195cb5caa98Sdjl size_t ndata; 196cb5caa98Sdjl size_t adata; 197cb5caa98Sdjl size_t buflen; 198cb5caa98Sdjl door_arg_t param; 199cb5caa98Sdjl int ret, errnum; 200cb5caa98Sdjl nss_pheader_t *phdr_d; 201cb5caa98Sdjl char *me = "_nscd_doorcall_fd"; 202cb5caa98Sdjl 203cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 204cb5caa98Sdjl (me, "processing door call %d (fd = %d)...\n", callnum, fd); 205cb5caa98Sdjl 206cb5caa98Sdjl /* allocate door buffer from the stack */ 207cb5caa98Sdjl NSCD_ALLOC_DOORBUF(callnum, indlen, uptr, buflen); 208cb5caa98Sdjl dptr = uptr; 209cb5caa98Sdjl ndata = buflen; 210cb5caa98Sdjl adata = buflen; 211cb5caa98Sdjl datap = NSCD_N2N_DOOR_DATA(void, dptr); 212cb5caa98Sdjl if (indata != NULL) 213cb5caa98Sdjl (void) memmove(datap, indata, indlen); 214cb5caa98Sdjl 215cb5caa98Sdjl param.rbuf = (char *)dptr; 216cb5caa98Sdjl param.rsize = ndata; 217cb5caa98Sdjl param.data_ptr = (char *)dptr; 218cb5caa98Sdjl param.data_size = adata; 219cb5caa98Sdjl param.desc_ptr = NULL; 220cb5caa98Sdjl param.desc_num = 0; 221cb5caa98Sdjl ret = door_call(fd, ¶m); 222cb5caa98Sdjl if (ret < 0) { 223cb5caa98Sdjl errnum = errno; 224cb5caa98Sdjl /* 225cb5caa98Sdjl * door call did not get through, return errno 226cb5caa98Sdjl * if requested 227cb5caa98Sdjl */ 228cb5caa98Sdjl if (phdr != NULL) { 229cb5caa98Sdjl NSCD_SET_STATUS(phdr, NSS_ERROR, errnum); 230cb5caa98Sdjl } 231cb5caa98Sdjl 232cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 233cb5caa98Sdjl (me, "door call (%d to %d) did not get through (%s)\n", 234cb5caa98Sdjl callnum, fd, strerror(errnum)); 235cb5caa98Sdjl 236cb5caa98Sdjl return (NSS_ERROR); 237cb5caa98Sdjl } 238cb5caa98Sdjl ndata = param.rsize; 239cb5caa98Sdjl dptr = (void *)param.data_ptr; 240cb5caa98Sdjl 241cb5caa98Sdjl /* 242cb5caa98Sdjl * door call got through, check if operation failed. 243cb5caa98Sdjl * if so, return error info if requested 244cb5caa98Sdjl */ 245cb5caa98Sdjl phdr_d = (nss_pheader_t *)dptr; 246cb5caa98Sdjl ret = NSCD_GET_STATUS(phdr_d); 247cb5caa98Sdjl if (ret != NSS_SUCCESS) { 248cb5caa98Sdjl if (phdr != NULL) { 249cb5caa98Sdjl NSCD_COPY_STATUS(phdr, phdr_d); 250cb5caa98Sdjl } 251cb5caa98Sdjl 252cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 253cb5caa98Sdjl (me, "door call (%d to %d) failed: p_status = %d, " 254cb5caa98Sdjl "p_errno = %s, nscd status = %d\n", callnum, fd, 255cb5caa98Sdjl ret, strerror(NSCD_GET_ERRNO(phdr_d)), 256cb5caa98Sdjl NSCD_GET_NSCD_STATUS(phdr_d)); 257cb5caa98Sdjl } else 258cb5caa98Sdjl ret = copy_output(outdata, outdlen, phdr_d, phdr); 259cb5caa98Sdjl 260cb5caa98Sdjl /* if new buffer allocated for this door call, free it */ 261cb5caa98Sdjl if (dptr != uptr) 262cb5caa98Sdjl (void) munmap(dptr, param.rsize); 263cb5caa98Sdjl 264cb5caa98Sdjl 265cb5caa98Sdjl return (ret); 266cb5caa98Sdjl } 267cb5caa98Sdjl 268cb5caa98Sdjl static void 269cb5caa98Sdjl send_doorfd(void **dptr, size_t *ndata, size_t *adata, 270cb5caa98Sdjl door_desc_t *pdesc) 271cb5caa98Sdjl { 272cb5caa98Sdjl nss_pheader_t *phdr = (nss_pheader_t *)*dptr; 273cb5caa98Sdjl door_arg_t param; 274cb5caa98Sdjl int ret; 275cb5caa98Sdjl int doorfd; 276cb5caa98Sdjl int errnum; 277cb5caa98Sdjl char *me = "send_doorfd"; 278cb5caa98Sdjl 279cb5caa98Sdjl initdoor(*dptr, &doorfd); 280cb5caa98Sdjl if (NSCD_STATUS_IS_NOT_OK(phdr)) 281cb5caa98Sdjl return; 282cb5caa98Sdjl 283cb5caa98Sdjl param.rbuf = (char *)*dptr; 284cb5caa98Sdjl param.rsize = *ndata; 285cb5caa98Sdjl param.data_ptr = (char *)*dptr; 286cb5caa98Sdjl param.data_size = *adata; 287cb5caa98Sdjl param.desc_ptr = pdesc; 288cb5caa98Sdjl param.desc_num = 1; 289cb5caa98Sdjl ret = door_call(doorfd, ¶m); 290cb5caa98Sdjl if (ret < 0) { 291cb5caa98Sdjl errnum = errno; 292cb5caa98Sdjl 293cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 294cb5caa98Sdjl (me, "door call (to fd %d) failed (%s)\n", 295cb5caa98Sdjl doorfd, strerror(errnum)); 296cb5caa98Sdjl (void) close(doorfd); 297*7d7551bcSMilan Jurik NSCD_SET_STATUS(phdr, NSS_ERROR, errnum); 298*7d7551bcSMilan Jurik return; 299cb5caa98Sdjl } 300cb5caa98Sdjl *adata = param.data_size; 301cb5caa98Sdjl *ndata = param.rsize; 302cb5caa98Sdjl *dptr = (void *)param.data_ptr; 303cb5caa98Sdjl 304cb5caa98Sdjl if (*adata == 0 || *dptr == NULL) { 305cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 306cb5caa98Sdjl (me, "no data\n"); 307cb5caa98Sdjl 308*7d7551bcSMilan Jurik NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTCONN); 309cb5caa98Sdjl } 310cb5caa98Sdjl 311cb5caa98Sdjl (void) close(doorfd); 312cb5caa98Sdjl } 313cb5caa98Sdjl 314cb5caa98Sdjl nss_status_t 315cb5caa98Sdjl _nscd_doorcall_sendfd(int fd, int callnum, void *indata, int indlen, 316cb5caa98Sdjl nss_pheader_t *phdr) 317cb5caa98Sdjl { 318cb5caa98Sdjl void *uptr; 319cb5caa98Sdjl void *dptr; 320cb5caa98Sdjl void *datap; 321cb5caa98Sdjl size_t ndata; 322cb5caa98Sdjl size_t adata; 323cb5caa98Sdjl size_t buflen; 324cb5caa98Sdjl nss_pheader_t *phdr_d; 325cb5caa98Sdjl door_desc_t desc; 326cb5caa98Sdjl char *me = "_nscd_doorcall_sendfd"; 327cb5caa98Sdjl 328cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 329cb5caa98Sdjl (me, "processing door call %d (fd = %d)...\n", callnum, fd); 330cb5caa98Sdjl 331cb5caa98Sdjl /* allocate door buffer from the stack */ 332cb5caa98Sdjl NSCD_ALLOC_DOORBUF(callnum, indlen, uptr, buflen); 333cb5caa98Sdjl dptr = uptr; 334cb5caa98Sdjl ndata = buflen; 335cb5caa98Sdjl adata = buflen; 336cb5caa98Sdjl datap = NSCD_N2N_DOOR_DATA(void, dptr); 337cb5caa98Sdjl if (indata != NULL) 338cb5caa98Sdjl (void) memmove(datap, indata, indlen); 339cb5caa98Sdjl desc.d_attributes = DOOR_DESCRIPTOR; 340cb5caa98Sdjl desc.d_data.d_desc.d_descriptor = fd; 341cb5caa98Sdjl 342cb5caa98Sdjl send_doorfd(&dptr, &ndata, &adata, &desc); 343cb5caa98Sdjl 344cb5caa98Sdjl phdr_d = (nss_pheader_t *)dptr; 345cb5caa98Sdjl if (NSCD_STATUS_IS_NOT_OK(phdr_d)) { 346cb5caa98Sdjl if (phdr != NULL) 347cb5caa98Sdjl *phdr = *phdr_d; 348cb5caa98Sdjl 349cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 350cb5caa98Sdjl (me, "door call (%d) failed (status = %d, error = %s)\n", 351cb5caa98Sdjl callnum, NSCD_GET_STATUS(phdr_d), 352cb5caa98Sdjl strerror(NSCD_GET_ERRNO(phdr_d))); 353cb5caa98Sdjl } 354cb5caa98Sdjl 355cb5caa98Sdjl return (NSCD_GET_STATUS(phdr_d)); 356cb5caa98Sdjl } 357