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 /* 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 * Copyright (c) 2016 by Delphix. All rights reserved. 27 */ 28 29 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 30 /* All Rights Reserved */ 31 32 /* 33 * Portions of this source code were derived from Berkeley 34 * under license from the Regents of the University of 35 * California. 36 */ 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 #include "mt.h" 41 #include <stdlib.h> 42 #include <unistd.h> 43 #include <rpc/rpc.h> 44 #include <sys/types.h> 45 #include "yp_b.h" 46 #include <rpcsvc/yp_prot.h> 47 #include <rpcsvc/ypclnt.h> 48 #include <string.h> 49 50 static int domaster(char *, char *, struct dom_binding *, struct timeval, 51 char **); 52 extern int __yp_master_rsvdport(char *, char *, char **); 53 54 /* 55 * This checks parameters, and implements the outer "until binding success" 56 * loop. 57 */ 58 int 59 yp_master(char *domain, char *map, char **master) 60 { 61 size_t domlen; 62 size_t maplen; 63 int reason; 64 struct dom_binding *pdomb; 65 66 if ((map == NULL) || (domain == NULL)) 67 return (YPERR_BADARGS); 68 69 domlen = strlen(domain); 70 maplen = strlen(map); 71 72 if ((domlen == 0) || (domlen > YPMAXDOMAIN) || 73 (maplen == 0) || (maplen > YPMAXMAP) || 74 (master == NULL)) 75 return (YPERR_BADARGS); 76 77 for (;;) { 78 79 if (reason = __yp_dobind(domain, &pdomb)) 80 return (reason); 81 82 if (pdomb->dom_binding->ypbind_hi_vers >= YPVERS) { 83 84 reason = domaster(domain, map, pdomb, _ypserv_timeout, 85 master); 86 87 __yp_rel_binding(pdomb); 88 if (reason == YPERR_RPC) { 89 yp_unbind(domain); 90 (void) sleep(_ypsleeptime); 91 } else { 92 break; 93 } 94 } else { 95 __yp_rel_binding(pdomb); 96 return (YPERR_VERS); 97 } 98 } 99 100 if (reason == YPERR_MAP && geteuid() == 0) { 101 /* 102 * Lookup could be for a secure map; fail over to retry 103 * from a reserved port. Only useful to try this if we're 104 * the super user. 105 */ 106 int rsvdreason; 107 rsvdreason = __yp_master_rsvdport(domain, map, master); 108 if (rsvdreason == 0) 109 reason = rsvdreason; 110 } 111 112 return (reason); 113 } 114 115 116 /* 117 * This function is identical to 'yp_master' with the exception that it calls 118 * '__yp_dobind_rsvdport' rather than '__yp_dobind' 119 */ 120 int 121 __yp_master_rsvdport(char *domain, char *map, char **master) 122 { 123 size_t domlen; 124 size_t maplen; 125 int reason; 126 struct dom_binding *pdomb; 127 128 if ((map == NULL) || (domain == NULL)) 129 return (YPERR_BADARGS); 130 131 domlen = strlen(domain); 132 maplen = strlen(map); 133 134 if ((domlen == 0) || (domlen > YPMAXDOMAIN) || 135 (maplen == 0) || (maplen > YPMAXMAP) || 136 (master == NULL)) 137 return (YPERR_BADARGS); 138 139 for (;;) { 140 141 if (reason = __yp_dobind_rsvdport(domain, &pdomb)) 142 return (reason); 143 144 if (pdomb->dom_binding->ypbind_hi_vers >= YPVERS) { 145 146 reason = domaster(domain, map, pdomb, _ypserv_timeout, 147 master); 148 149 /* 150 * Have to free the binding since the reserved 151 * port bindings are not cached. 152 */ 153 __yp_rel_binding(pdomb); 154 free_dom_binding(pdomb); 155 if (reason == YPERR_RPC) { 156 yp_unbind(domain); 157 (void) sleep(_ypsleeptime); 158 } else { 159 break; 160 } 161 } else { 162 /* 163 * Have to free the binding since the reserved 164 * port bindings are not cached. 165 */ 166 __yp_rel_binding(pdomb); 167 free_dom_binding(pdomb); 168 return (YPERR_VERS); 169 } 170 } 171 return (reason); 172 } 173 174 /* 175 * This talks v2 to ypserv 176 */ 177 static int 178 domaster(char *domain, char *map, struct dom_binding *pdomb, 179 struct timeval timeout, char **master) 180 { 181 struct ypreq_nokey req; 182 struct ypresp_master resp; 183 unsigned int retval = 0; 184 185 req.domain = domain; 186 req.map = map; 187 (void) memset(&resp, 0, sizeof (struct ypresp_master)); 188 189 /* 190 * Do the get_master request. If the rpc call failed, return with 191 * status from this point. 192 */ 193 194 if (clnt_call(pdomb->dom_client, 195 YPPROC_MASTER, (xdrproc_t)xdr_ypreq_nokey, 196 (char *)&req, (xdrproc_t)xdr_ypresp_master, (char *)&resp, 197 timeout) != RPC_SUCCESS) 198 return (YPERR_RPC); 199 200 /* See if the request succeeded */ 201 202 if (resp.status != YP_TRUE) 203 retval = ypprot_err(resp.status); 204 205 /* Get some memory which the user can get rid of as they like */ 206 207 if (!retval && ((*master = malloc(strlen(resp.master) + 1)) == NULL)) 208 retval = YPERR_RESRC; 209 210 if (!retval) 211 (void) strcpy(*master, resp.master); 212 213 CLNT_FREERES(pdomb->dom_client, 214 (xdrproc_t)xdr_ypresp_master, (char *)&resp); 215 return (retval); 216 } 217