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