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