1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 1995 5 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Bill Paul. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #include <stdio.h> 37 #include <string.h> 38 #include <stdlib.h> 39 #include <unistd.h> 40 #include <sys/param.h> 41 #include <rpc/rpc.h> 42 #include <rpcsvc/yp.h> 43 #include <rpcsvc/ypclnt.h> 44 #include "ypxfr_extern.h" 45 46 const char * 47 ypxfrerr_string(ypxfrstat code) 48 { 49 switch (code) { 50 case YPXFR_SUCC: 51 return ("Map successfully transferred"); 52 break; 53 case YPXFR_AGE: 54 return ("Master's version not newer"); 55 break; 56 case YPXFR_NOMAP: 57 return ("No such map in server's domain"); 58 break; 59 case YPXFR_NODOM: 60 return ("Domain not supported by server"); 61 break; 62 case YPXFR_RSRC: 63 return ("Local resource allocation failure"); 64 break; 65 case YPXFR_RPC: 66 return ("RPC failure talking to server"); 67 break; 68 case YPXFR_MADDR: 69 return ("Could not get master server address"); 70 break; 71 case YPXFR_YPERR: 72 return ("NIS server/map database error"); 73 break; 74 case YPXFR_BADARGS: 75 return ("Request arguments bad"); 76 break; 77 case YPXFR_DBM: 78 return ("Local database operation failed"); 79 break; 80 case YPXFR_FILE: 81 return ("Local file I/O operation failed"); 82 break; 83 case YPXFR_SKEW: 84 return ("Map version skew during transfer"); 85 break; 86 case YPXFR_CLEAR: 87 return ("Couldn't send \"clear\" request to local ypserv"); 88 break; 89 case YPXFR_FORCE: 90 return ("No local order number in map -- use -f flag"); 91 break; 92 case YPXFR_XFRERR: 93 return ("General ypxfr error"); 94 break; 95 case YPXFR_REFUSED: 96 return ("Transfer request refused by ypserv"); 97 break; 98 default: 99 return ("Unknown error code"); 100 break; 101 } 102 } 103 104 /* 105 * These are wrappers for the usual yp_master() and yp_order() functions. 106 * They can use either local yplib functions (the real yp_master() and 107 * yp_order()) or do direct RPCs to a specified server. The latter is 108 * necessary if ypxfr is run on a machine that isn't configured as an 109 * NIS client (this can happen very easily: a given machine need not be 110 * an NIS client in order to be an NIS server). 111 */ 112 113 /* 114 * Careful: yp_master() returns a pointer to a dynamically allocated 115 * buffer. Calling ypproc_master_2() ourselves also returns a pointer 116 * to dynamically allocated memory, though this time it's memory 117 * allocated by the XDR routines. We have to rememver to free() or 118 * xdr_free() the memory as required to avoid leaking memory. 119 */ 120 char * 121 ypxfr_get_master(char *domain, char *map, char *source, const int yplib) 122 { 123 static char mastername[MAXPATHLEN + 2]; 124 125 bzero((char *)&mastername, sizeof(mastername)); 126 127 if (yplib) { 128 int res; 129 char *master; 130 if ((res = yp_master(domain, map, &master))) { 131 switch (res) { 132 case YPERR_DOMAIN: 133 yp_errno = (enum ypstat)YPXFR_NODOM; 134 break; 135 case YPERR_MAP: 136 yp_errno = (enum ypstat)YPXFR_NOMAP; 137 break; 138 case YPERR_YPERR: 139 default: 140 yp_errno = (enum ypstat)YPXFR_YPERR; 141 break; 142 } 143 return(NULL); 144 } else { 145 snprintf(mastername, sizeof(mastername), "%s", master); 146 free(master); 147 return((char *)&mastername); 148 } 149 } else { 150 CLIENT *clnt; 151 ypresp_master *resp; 152 ypreq_nokey req; 153 154 if ((clnt = clnt_create(source,YPPROG,YPVERS,"udp")) == NULL) { 155 yp_error("%s",clnt_spcreateerror("failed to \ 156 create udp handle to ypserv")); 157 yp_errno = (enum ypstat)YPXFR_RPC; 158 return(NULL); 159 } 160 161 req.map = map; 162 req.domain = domain; 163 if ((resp = ypproc_master_2(&req, clnt)) == NULL) { 164 yp_error("%s",clnt_sperror(clnt,"YPPROC_MASTER \ 165 failed")); 166 clnt_destroy(clnt); 167 yp_errno = (enum ypstat)YPXFR_RPC; 168 return(NULL); 169 } 170 clnt_destroy(clnt); 171 if (resp->stat != YP_TRUE) { 172 switch (resp->stat) { 173 case YP_NODOM: 174 yp_errno = (enum ypstat)YPXFR_NODOM; 175 break; 176 case YP_NOMAP: 177 yp_errno = (enum ypstat)YPXFR_NOMAP; 178 break; 179 case YP_YPERR: 180 default: 181 yp_errno = (enum ypstat)YPXFR_YPERR; 182 break; 183 } 184 return(NULL); 185 } 186 snprintf(mastername, sizeof(mastername), "%s", resp->peer); 187 /* xdr_free(xdr_ypresp_master, (char *)&resp); */ 188 return((char *)&mastername); 189 } 190 } 191 192 unsigned long 193 ypxfr_get_order(char *domain, char *map, char *source, const int yplib) 194 { 195 if (yplib) { 196 unsigned int order; 197 int res; 198 if ((res = yp_order(domain, map, &order))) { 199 switch (res) { 200 case YPERR_DOMAIN: 201 yp_errno = (enum ypstat)YPXFR_NODOM; 202 break; 203 case YPERR_MAP: 204 yp_errno = (enum ypstat)YPXFR_NOMAP; 205 break; 206 case YPERR_YPERR: 207 default: 208 yp_errno = (enum ypstat)YPXFR_YPERR; 209 break; 210 } 211 return(0); 212 } else 213 return(order); 214 } else { 215 CLIENT *clnt; 216 ypresp_order *resp; 217 ypreq_nokey req; 218 219 if ((clnt = clnt_create(source,YPPROG,YPVERS,"udp")) == NULL) { 220 yp_error("%s",clnt_spcreateerror("couldn't create \ 221 udp handle to ypserv")); 222 yp_errno = (enum ypstat)YPXFR_RPC; 223 return(0); 224 } 225 req.map = map; 226 req.domain = domain; 227 if ((resp = ypproc_order_2(&req, clnt)) == NULL) { 228 yp_error("%s", clnt_sperror(clnt, "YPPROC_ORDER \ 229 failed")); 230 clnt_destroy(clnt); 231 yp_errno = (enum ypstat)YPXFR_RPC; 232 return(0); 233 } 234 clnt_destroy(clnt); 235 if (resp->stat != YP_TRUE) { 236 switch (resp->stat) { 237 case YP_NODOM: 238 yp_errno = (enum ypstat)YPXFR_NODOM; 239 break; 240 case YP_NOMAP: 241 yp_errno = (enum ypstat)YPXFR_NOMAP; 242 break; 243 case YP_YPERR: 244 default: 245 yp_errno = (enum ypstat)YPXFR_YPERR; 246 break; 247 } 248 return(0); 249 } 250 return(resp->ordernum); 251 } 252 } 253 254 int 255 ypxfr_match(char *server, char *domain, char *map, char *key, 256 unsigned long keylen) 257 { 258 ypreq_key ypkey; 259 ypresp_val *ypval; 260 CLIENT *clnt; 261 static char buf[YPMAXRECORD + 2]; 262 263 bzero(buf, sizeof(buf)); 264 265 if ((clnt = clnt_create(server, YPPROG,YPVERS,"udp")) == NULL) { 266 yp_error("failed to create UDP handle: %s", 267 clnt_spcreateerror(server)); 268 return(0); 269 } 270 271 ypkey.domain = domain; 272 ypkey.map = map; 273 ypkey.key.keydat_len = keylen; 274 ypkey.key.keydat_val = key; 275 276 if ((ypval = ypproc_match_2(&ypkey, clnt)) == NULL) { 277 clnt_destroy(clnt); 278 yp_error("%s: %s", server, 279 clnt_sperror(clnt,"YPPROC_MATCH failed")); 280 return(0); 281 } 282 283 clnt_destroy(clnt); 284 285 if (ypval->stat != YP_TRUE) { 286 xdr_free((xdrproc_t)xdr_ypresp_val, ypval); 287 return(0); 288 } 289 290 xdr_free((xdrproc_t)xdr_ypresp_val, ypval); 291 292 return(1); 293 } 294