1 /* $OpenBSD: yplib_host.c,v 1.18 2015/01/16 06:40:22 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com> 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 #include <sys/param.h> 31 #include <sys/socket.h> 32 #include <sys/types.h> 33 #include <sys/uio.h> 34 #include <sys/file.h> 35 36 #include <ctype.h> 37 #include <err.h> 38 #include <errno.h> 39 #include <netdb.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <unistd.h> 44 45 #include <netinet/in.h> 46 #include <arpa/inet.h> 47 48 #include <rpc/rpc.h> 49 #include <rpc/xdr.h> 50 #include <rpcsvc/yp.h> 51 #include <rpcsvc/ypclnt.h> 52 53 #include "yplib_host.h" 54 55 extern bool_t xdr_ypresp_all_seq(XDR *, unsigned long *); 56 57 extern int (*ypresp_allfn)(u_long, char *, int, char *, int, void *); 58 extern void *ypresp_data; 59 60 static int _yplib_host_timeout = 10; 61 62 CLIENT * 63 yp_bind_host(char *server, u_long program, u_long version, u_short port, 64 int usetcp) 65 { 66 struct sockaddr_in rsrv_sin; 67 static CLIENT *client; 68 struct hostent *h; 69 struct timeval tv; 70 int rsrv_sock; 71 72 memset(&rsrv_sin, 0, sizeof rsrv_sin); 73 rsrv_sin.sin_len = sizeof rsrv_sin; 74 rsrv_sin.sin_family = AF_INET; 75 rsrv_sock = RPC_ANYSOCK; 76 if (port != 0) 77 rsrv_sin.sin_port = htons(port); 78 79 if (*server >= '0' && *server <= '9') { 80 if (inet_aton(server, &rsrv_sin.sin_addr) == 0) { 81 errx(1, "inet_aton: invalid address %s.", 82 server); 83 } 84 } else { 85 h = gethostbyname(server); 86 if (h == NULL) { 87 errx(1, "gethostbyname: unknown host %s.", 88 server); 89 } 90 rsrv_sin.sin_addr.s_addr = *(u_int32_t *)h->h_addr; 91 } 92 93 tv.tv_sec = 10; 94 tv.tv_usec = 0; 95 96 if (usetcp) 97 client = clnttcp_create(&rsrv_sin, program, version, 98 &rsrv_sock, 0, 0); 99 else 100 client = clntudp_create(&rsrv_sin, program, version, tv, 101 &rsrv_sock); 102 103 if (client == NULL) { 104 errx(1, "clntudp_create: no contact with host %s.", 105 server); 106 } 107 108 return (client); 109 } 110 111 CLIENT * 112 yp_bind_local(u_long program, u_long version) 113 { 114 struct sockaddr_in rsrv_sin; 115 static CLIENT *client; 116 struct timeval tv; 117 int rsrv_sock; 118 119 memset(&rsrv_sin, 0, sizeof rsrv_sin); 120 rsrv_sin.sin_len = sizeof rsrv_sin; 121 rsrv_sin.sin_family = AF_INET; 122 rsrv_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 123 rsrv_sock = RPC_ANYSOCK; 124 125 tv.tv_sec = 10; 126 tv.tv_usec = 0; 127 128 client = clntudp_create(&rsrv_sin, program, version, tv, &rsrv_sock); 129 if (client == NULL) { 130 errx(1, "clntudp_create: no contact with localhost."); 131 } 132 133 return (client); 134 } 135 136 int 137 yp_match_host(CLIENT *client, char *indomain, char *inmap, const char *inkey, 138 int inkeylen, char **outval, int *outvallen) 139 { 140 struct ypresp_val yprv; 141 struct ypreq_key yprk; 142 struct timeval tv; 143 int r; 144 145 *outval = NULL; 146 *outvallen = 0; 147 148 tv.tv_sec = _yplib_host_timeout; 149 tv.tv_usec = 0; 150 151 yprk.domain = indomain; 152 yprk.map = inmap; 153 yprk.key.keydat_val = (char *)inkey; 154 yprk.key.keydat_len = inkeylen; 155 156 memset(&yprv, 0, sizeof yprv); 157 158 r = clnt_call(client, YPPROC_MATCH, 159 (xdrproc_t)xdr_ypreq_key, &yprk, 160 (xdrproc_t)xdr_ypresp_val, &yprv, tv); 161 if (r != RPC_SUCCESS) 162 clnt_perror(client, "yp_match_host: clnt_call"); 163 if ( !(r = ypprot_err(yprv.stat)) ) { 164 *outvallen = yprv.val.valdat_len; 165 *outval = malloc(*outvallen + 1); 166 memcpy(*outval, yprv.val.valdat_val, *outvallen); 167 (*outval)[*outvallen] = '\0'; 168 } 169 xdr_free((xdrproc_t)xdr_ypresp_val, (char *)&yprv); 170 171 return (r); 172 } 173 174 int 175 yp_first_host(CLIENT *client, char *indomain, char *inmap, char **outkey, 176 int *outkeylen, char **outval, int *outvallen) 177 { 178 struct ypresp_key_val yprkv; 179 struct ypreq_nokey yprnk; 180 struct timeval tv; 181 int r; 182 183 *outkey = *outval = NULL; 184 *outkeylen = *outvallen = 0; 185 186 tv.tv_sec = _yplib_host_timeout; 187 tv.tv_usec = 0; 188 189 yprnk.domain = indomain; 190 yprnk.map = inmap; 191 memset(&yprkv, 0, sizeof yprkv); 192 193 r = clnt_call(client, YPPROC_FIRST, 194 (xdrproc_t)xdr_ypreq_nokey, &yprnk, 195 (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv); 196 if (r != RPC_SUCCESS) 197 clnt_perror(client, "yp_first_host: clnt_call"); 198 if ( !(r = ypprot_err(yprkv.stat)) ) { 199 *outkeylen = yprkv.key.keydat_len; 200 *outkey = malloc(*outkeylen+1); 201 memcpy(*outkey, yprkv.key.keydat_val, *outkeylen); 202 (*outkey)[*outkeylen] = '\0'; 203 *outvallen = yprkv.val.valdat_len; 204 *outval = malloc(*outvallen+1); 205 memcpy(*outval, yprkv.val.valdat_val, *outvallen); 206 (*outval)[*outvallen] = '\0'; 207 } 208 xdr_free((xdrproc_t)xdr_ypresp_key_val, (char *)&yprkv); 209 210 return (r); 211 } 212 213 int 214 yp_next_host(CLIENT *client, char *indomain, char *inmap, char *inkey, 215 int inkeylen, char **outkey, int *outkeylen, char **outval, int *outvallen) 216 { 217 struct ypresp_key_val yprkv; 218 struct ypreq_key yprk; 219 struct timeval tv; 220 int r; 221 222 *outkey = *outval = NULL; 223 *outkeylen = *outvallen = 0; 224 225 tv.tv_sec = _yplib_host_timeout; 226 tv.tv_usec = 0; 227 228 yprk.domain = indomain; 229 yprk.map = inmap; 230 yprk.key.keydat_val = inkey; 231 yprk.key.keydat_len = inkeylen; 232 memset(&yprkv, 0, sizeof yprkv); 233 234 r = clnt_call(client, YPPROC_NEXT, 235 (xdrproc_t)xdr_ypreq_key, &yprk, 236 (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv); 237 if (r != RPC_SUCCESS) 238 clnt_perror(client, "yp_next_host: clnt_call"); 239 if ( !(r = ypprot_err(yprkv.stat)) ) { 240 *outkeylen = yprkv.key.keydat_len; 241 *outkey = malloc(*outkeylen+1); 242 memcpy(*outkey, yprkv.key.keydat_val, *outkeylen); 243 (*outkey)[*outkeylen] = '\0'; 244 *outvallen = yprkv.val.valdat_len; 245 *outval = malloc(*outvallen+1); 246 memcpy(*outval, yprkv.val.valdat_val, *outvallen); 247 (*outval)[*outvallen] = '\0'; 248 } 249 xdr_free((xdrproc_t)xdr_ypresp_key_val, (char *)&yprkv); 250 251 return (r); 252 } 253 254 int 255 yp_all_host(CLIENT *client, char *indomain, char *inmap, 256 struct ypall_callback *incallback) 257 { 258 struct ypreq_nokey yprnk; 259 struct timeval tv; 260 u_long status; 261 262 tv.tv_sec = _yplib_host_timeout; 263 tv.tv_usec = 0; 264 265 yprnk.domain = indomain; 266 yprnk.map = inmap; 267 ypresp_allfn = incallback->foreach; 268 ypresp_data = (void *)incallback->data; 269 270 (void) clnt_call(client, YPPROC_ALL, 271 (xdrproc_t)xdr_ypreq_nokey, &yprnk, 272 (xdrproc_t)xdr_ypresp_all_seq, &status, tv); 273 if (status != YP_FALSE) 274 return ypprot_err(status); 275 276 return (0); 277 } 278 279 int 280 yp_order_host(CLIENT *client, char *indomain, char *inmap, u_int32_t *outorder) 281 { 282 struct ypresp_order ypro; 283 struct ypreq_nokey yprnk; 284 struct timeval tv; 285 int r; 286 287 tv.tv_sec = _yplib_host_timeout; 288 tv.tv_usec = 0; 289 290 yprnk.domain = indomain; 291 yprnk.map = inmap; 292 293 memset(&ypro, 0, sizeof ypro); 294 295 r = clnt_call(client, YPPROC_ORDER, 296 (xdrproc_t)xdr_ypreq_nokey, &yprnk, 297 (xdrproc_t)xdr_ypresp_order, &ypro, tv); 298 if (r != RPC_SUCCESS) 299 clnt_perror(client, "yp_order_host: clnt_call"); 300 *outorder = ypro.ordernum; 301 xdr_free((xdrproc_t)xdr_ypresp_order, (char *)&ypro); 302 303 return ypprot_err(ypro.stat); 304 } 305 306 int 307 yp_master_host(CLIENT *client, char *indomain, char *inmap, char **outname) 308 { 309 struct ypresp_master yprm; 310 struct ypreq_nokey yprnk; 311 struct timeval tv; 312 int r; 313 314 tv.tv_sec = _yplib_host_timeout; 315 tv.tv_usec = 0; 316 yprnk.domain = indomain; 317 yprnk.map = inmap; 318 319 memset(&yprm, 0, sizeof yprm); 320 321 r = clnt_call(client, YPPROC_MASTER, 322 (xdrproc_t)xdr_ypreq_nokey, &yprnk, 323 (xdrproc_t)xdr_ypresp_master, &yprm, tv); 324 if (r != RPC_SUCCESS) 325 clnt_perror(client, "yp_master: clnt_call"); 326 if (!(r = ypprot_err(yprm.stat))) 327 *outname = strdup(yprm.peer); 328 xdr_free((xdrproc_t)xdr_ypresp_master, (char *)&yprm); 329 330 return (r); 331 } 332 333 int 334 yp_maplist_host(CLIENT *client, char *indomain, struct ypmaplist **outmaplist) 335 { 336 struct ypresp_maplist ypml; 337 struct timeval tv; 338 int r; 339 340 tv.tv_sec = _yplib_host_timeout; 341 tv.tv_usec = 0; 342 343 memset(&ypml, 0, sizeof ypml); 344 345 r = clnt_call(client, YPPROC_MAPLIST, 346 (xdrproc_t)xdr_domainname, &indomain, 347 (xdrproc_t)xdr_ypresp_maplist, &ypml, tv); 348 if (r != RPC_SUCCESS) 349 clnt_perror(client, "yp_maplist: clnt_call"); 350 *outmaplist = ypml.maps; 351 /* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/ 352 353 return ypprot_err(ypml.stat); 354 } 355