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