1 /* $NetBSD: yp_first.c,v 1.16 2012/06/25 22:32:46 abs Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca> 5 * 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 #if defined(LIBC_SCCS) && !defined(lint) 31 __RCSID("$NetBSD: yp_first.c,v 1.16 2012/06/25 22:32:46 abs Exp $"); 32 #endif 33 34 #include "namespace.h" 35 #include <stdlib.h> 36 #include <string.h> 37 #include <rpc/rpc.h> 38 #include <rpcsvc/yp_prot.h> 39 #include <rpcsvc/ypclnt.h> 40 #include "local.h" 41 42 extern struct timeval _yplib_timeout; 43 extern int _yplib_nerrs; 44 extern int _yplib_bindtries; 45 46 #ifdef __weak_alias 47 __weak_alias(yp_first,_yp_first) 48 __weak_alias(yp_next,_yp_next) 49 #endif 50 51 int 52 yp_first(const char *indomain, const char *inmap, char **outkey, 53 int *outkeylen, char **outval, int *outvallen) 54 { 55 struct ypresp_key_val yprkv; 56 struct ypreq_nokey yprnk; 57 struct dom_binding *ysd; 58 int r, nerrs = 0; 59 60 if (outkey == NULL || outkeylen == NULL || \ 61 outval == NULL || outvallen == NULL) 62 return YPERR_BADARGS; 63 *outkey = *outval = NULL; 64 *outkeylen = *outvallen = 0; 65 if (_yp_invalid_domain(indomain)) 66 return YPERR_BADARGS; 67 if (inmap == NULL || *inmap == '\0' 68 || strlen(inmap) > YPMAXMAP) 69 return YPERR_BADARGS; 70 71 again: 72 if (_yp_dobind(indomain, &ysd) != 0) 73 return YPERR_DOMAIN; 74 75 yprnk.domain = indomain; 76 yprnk.map = inmap; 77 (void)memset(&yprkv, 0, sizeof yprkv); 78 79 r = clnt_call(ysd->dom_client, (rpcproc_t)YPPROC_FIRST, 80 (xdrproc_t)xdr_ypreq_nokey, 81 &yprnk, (xdrproc_t)xdr_ypresp_key_val, &yprkv, _yplib_timeout); 82 if (r != RPC_SUCCESS) { 83 if (_yplib_bindtries <= 0 && ++nerrs == _yplib_nerrs) { 84 clnt_perror(ysd->dom_client, "yp_first: clnt_call"); 85 nerrs = 0; 86 } else if (_yplib_bindtries > 0 && ++nerrs == _yplib_bindtries) 87 return YPERR_YPSERV; 88 ysd->dom_vers = -1; 89 goto again; 90 } 91 if (!(r = ypprot_err(yprkv.status))) { 92 *outkeylen = yprkv.keydat.dsize; 93 if ((*outkey = malloc((size_t)(*outkeylen + 1))) == NULL) 94 r = YPERR_RESRC; 95 else { 96 (void)memcpy(*outkey, yprkv.keydat.dptr, 97 (size_t)*outkeylen); 98 (*outkey)[*outkeylen] = '\0'; 99 } 100 *outvallen = yprkv.valdat.dsize; 101 if ((*outval = malloc((size_t)(*outvallen + 1))) == NULL) 102 r = YPERR_RESRC; 103 else { 104 (void)memcpy(*outval, yprkv.valdat.dptr, 105 (size_t)*outvallen); 106 (*outval)[*outvallen] = '\0'; 107 } 108 } 109 xdr_free((xdrproc_t)xdr_ypresp_key_val, (char *)(void *)&yprkv); 110 __yp_unbind(ysd); 111 if (r != 0) { 112 if (*outkey) { 113 free(*outkey); 114 *outkey = NULL; 115 } 116 if (*outval) { 117 free(*outval); 118 *outval = NULL; 119 } 120 } 121 return r; 122 } 123 124 int 125 yp_next(const char *indomain, const char *inmap, const char *inkey, 126 int inkeylen, char **outkey, int *outkeylen, char **outval, int *outvallen) 127 { 128 struct ypresp_key_val yprkv; 129 struct ypreq_key yprk; 130 struct dom_binding *ysd; 131 int r, nerrs = 0; 132 133 if (outkey == NULL || outkeylen == NULL || \ 134 outval == NULL || outvallen == NULL || \ 135 inkey == NULL) 136 return YPERR_BADARGS; 137 *outkey = *outval = NULL; 138 *outkeylen = *outvallen = 0; 139 140 if (_yp_invalid_domain(indomain)) 141 return YPERR_BADARGS; 142 if (inmap == NULL || *inmap == '\0' 143 || strlen(inmap) > YPMAXMAP) 144 return YPERR_BADARGS; 145 146 again: 147 if (_yp_dobind(indomain, &ysd) != 0) 148 return YPERR_DOMAIN; 149 150 yprk.domain = indomain; 151 yprk.map = inmap; 152 yprk.keydat.dptr = inkey; 153 yprk.keydat.dsize = inkeylen; 154 (void)memset(&yprkv, 0, sizeof yprkv); 155 156 r = clnt_call(ysd->dom_client, (rpcproc_t)YPPROC_NEXT, 157 (xdrproc_t)xdr_ypreq_key, 158 &yprk, (xdrproc_t)xdr_ypresp_key_val, &yprkv, _yplib_timeout); 159 if (r != RPC_SUCCESS) { 160 if (_yplib_bindtries <= 0 && ++nerrs == _yplib_nerrs) { 161 clnt_perror(ysd->dom_client, "yp_next: clnt_call"); 162 nerrs = 0; 163 } else if (_yplib_bindtries > 0 && ++nerrs == _yplib_bindtries) 164 return YPERR_YPSERV; 165 ysd->dom_vers = -1; 166 goto again; 167 } 168 if (!(r = ypprot_err(yprkv.status))) { 169 *outkeylen = yprkv.keydat.dsize; 170 if ((*outkey = malloc((size_t)(*outkeylen + 1))) == NULL) 171 r = YPERR_RESRC; 172 else { 173 (void)memcpy(*outkey, yprkv.keydat.dptr, 174 (size_t)*outkeylen); 175 (*outkey)[*outkeylen] = '\0'; 176 } 177 *outvallen = yprkv.valdat.dsize; 178 if ((*outval = malloc((size_t)(*outvallen + 1))) == NULL) 179 r = YPERR_RESRC; 180 else { 181 (void)memcpy(*outval, yprkv.valdat.dptr, 182 (size_t)*outvallen); 183 (*outval)[*outvallen] = '\0'; 184 } 185 } 186 xdr_free((xdrproc_t)xdr_ypresp_key_val, (char *)(void *)&yprkv); 187 __yp_unbind(ysd); 188 if (r != 0) { 189 if (*outkey) { 190 free(*outkey); 191 *outkey = NULL; 192 } 193 if (*outval) { 194 free(*outval); 195 *outval = NULL; 196 } 197 } 198 return r; 199 } 200