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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1988-1997, by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <rpc/rpc.h> 30 #include <errno.h> 31 #include <syslog.h> 32 #include <rpc/nettype.h> 33 #include <netconfig.h> 34 #include <netdir.h> 35 #include <tiuser.h> 36 #include <fcntl.h> 37 #include <string.h> 38 #include <rpc/svc.h> 39 #include <locale.h> 40 41 extern int __rpc_negotiate_uid(int); 42 43 /* 44 * The highest level interface for server creation. 45 * Copied from svc_generic.c and cmd/keyserv/key_generic.c, but adapted 46 * to work only for TPI_CLTS semantics, and to be called only once 47 * from gssd.c. Returns 1 (interface created) on success and 0 48 * (no interfaces created) on failure. 49 */ 50 int 51 svc_create_local_service(dispatch, prognum, versnum, nettype, servname) 52 void (*dispatch) (); /* Dispatch function */ 53 u_long prognum; /* Program number */ 54 u_long versnum; /* Version number */ 55 char *nettype; /* Networktype token */ 56 char *servname; /* name of the service */ 57 { 58 int num = 0; 59 SVCXPRT *xprt; 60 struct netconfig *nconf; 61 struct t_bind *bind_addr; 62 void *net; 63 int fd; 64 struct nd_hostserv ns; 65 struct nd_addrlist *nas; 66 67 if ((net = __rpc_setconf(nettype)) == 0) { 68 (void) syslog(LOG_ERR, 69 gettext("svc_create: could not read netconfig database")); 70 return (0); 71 } 72 while (nconf = __rpc_getconf(net)) { 73 if ((strcmp(nconf->nc_protofmly, NC_LOOPBACK)) || 74 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 75 continue; 76 77 if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) < 0) { 78 (void) syslog(LOG_ERR, 79 gettext("svc_create: %s: cannot open connection: %s"), 80 nconf->nc_netid, t_errlist[t_errno]); 81 break; 82 } 83 84 /* 85 * Negotiate for returning the uid of the caller. 86 * This should be done before enabling the endpoint for 87 * service via t_bind() (called in svc_tli_create()) 88 * so that requests to gssd contain the uid. 89 */ 90 if (__rpc_negotiate_uid(fd) != 0) { 91 syslog(LOG_ERR, 92 gettext("Could not negotiate for" 93 " uid with loopback transport %s"), 94 nconf->nc_netid); 95 t_close(fd); 96 break; 97 } 98 99 /* LINTED pointer alignment */ 100 bind_addr = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR); 101 if ((bind_addr == NULL)) { 102 (void) t_close(fd); 103 (void) syslog(LOG_ERR, 104 gettext("svc_create: t_alloc failed\n")); 105 break; 106 } 107 ns.h_host = HOST_SELF; 108 ns.h_serv = servname; 109 if (!netdir_getbyname(nconf, &ns, &nas)) { 110 /* Copy the address */ 111 bind_addr->addr.len = nas->n_addrs->len; 112 (void) memcpy(bind_addr->addr.buf, nas->n_addrs->buf, 113 (int) nas->n_addrs->len); 114 bind_addr->qlen = 8; 115 netdir_free((char *) nas, ND_ADDRLIST); 116 } else { 117 (void) syslog(LOG_ERR, 118 gettext("svc_create: no well known " 119 "address for %s on %s\n"), 120 servname, nconf->nc_netid); 121 (void) t_free((char *) bind_addr, T_BIND); 122 bind_addr = NULL; 123 } 124 125 xprt = svc_tli_create(fd, nconf, bind_addr, 0, 0); 126 if (bind_addr) 127 (void) t_free((char *) bind_addr, T_BIND); 128 if (xprt == NULL) { 129 (void) t_close(fd); 130 (void) syslog(LOG_ERR, 131 gettext("svc_create: svc_tli_create failed\n")); 132 break; 133 } else { 134 (void) rpcb_unset(prognum, versnum, nconf); 135 if (svc_reg(xprt, prognum, versnum, dispatch, nconf) 136 == FALSE) { 137 (void) syslog(LOG_ERR, 138 gettext("svc_create: cannot" 139 " register %d vers %d on %s"), 140 prognum, versnum, nconf->nc_netid); 141 SVC_DESTROY(xprt); /* also t_closes fd */ 142 break; 143 } 144 num = 1; 145 break; 146 } 147 } 148 __rpc_endconf(net); 149 return (num); 150 } 151