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