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