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