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