1 /* $NetBSD: nis_nw.c,v 1.1.1.2 2012/09/09 16:07:56 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (c) 1996,1999 by Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #if defined(LIBC_SCCS) && !defined(lint) 21 static const char rcsid[] = "Id: nis_nw.c,v 1.4 2005/04/27 04:56:33 sra Exp "; 22 #endif /* LIBC_SCCS and not lint */ 23 24 /* Imports */ 25 26 #include "port_before.h" 27 28 #ifndef WANT_IRS_NIS 29 static int __bind_irs_nis_unneeded; 30 #else 31 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 35 #include <netinet/in.h> 36 #include <arpa/inet.h> 37 #include <arpa/nameser.h> 38 #ifdef T_NULL 39 #undef T_NULL /* Silence re-definition warning of T_NULL. */ 40 #endif 41 #include <rpc/rpc.h> 42 #include <rpc/xdr.h> 43 #include <rpcsvc/yp_prot.h> 44 #include <rpcsvc/ypclnt.h> 45 46 #include <errno.h> 47 #include <resolv.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 52 #include <isc/memcluster.h> 53 #include <irs.h> 54 55 #include "port_after.h" 56 57 #include "irs_p.h" 58 #include "nis_p.h" 59 60 /* Definitions */ 61 62 #define MAXALIASES 35 63 #define MAXADDRSIZE 4 64 65 struct pvt { 66 int needrewind; 67 char * nis_domain; 68 char * curkey_data; 69 int curkey_len; 70 char * curval_data; 71 int curval_len; 72 73 struct nwent nwent; 74 char * nwbuf; 75 76 char * aliases[MAXALIASES + 1]; 77 u_char addr[MAXADDRSIZE]; 78 79 struct __res_state * res; 80 void (*free_res)(void *); 81 }; 82 83 enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; 84 85 static /*const*/ char networks_byname[] = "networks.byname"; 86 static /*const*/ char networks_byaddr[] = "networks.byaddr"; 87 88 /* Forward */ 89 90 static void nw_close(struct irs_nw *); 91 static struct nwent * nw_byname(struct irs_nw *, const char *, int); 92 static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); 93 static struct nwent * nw_next(struct irs_nw *); 94 static void nw_rewind(struct irs_nw *); 95 static void nw_minimize(struct irs_nw *); 96 static struct __res_state * nw_res_get(struct irs_nw *this); 97 static void nw_res_set(struct irs_nw *this, 98 struct __res_state *res, 99 void (*free_res)(void *)); 100 101 static struct nwent * makenwent(struct irs_nw *this); 102 static void nisfree(struct pvt *, enum do_what); 103 static int init(struct irs_nw *this); 104 105 /* Public */ 106 107 struct irs_nw * 108 irs_nis_nw(struct irs_acc *this) { 109 struct irs_nw *nw; 110 struct pvt *pvt; 111 112 if (!(pvt = memget(sizeof *pvt))) { 113 errno = ENOMEM; 114 return (NULL); 115 } 116 memset(pvt, 0, sizeof *pvt); 117 if (!(nw = memget(sizeof *nw))) { 118 memput(pvt, sizeof *pvt); 119 errno = ENOMEM; 120 return (NULL); 121 } 122 memset(nw, 0x5e, sizeof *nw); 123 pvt->needrewind = 1; 124 pvt->nis_domain = ((struct nis_p *)this->private)->domain; 125 nw->private = pvt; 126 nw->close = nw_close; 127 nw->byname = nw_byname; 128 nw->byaddr = nw_byaddr; 129 nw->next = nw_next; 130 nw->rewind = nw_rewind; 131 nw->minimize = nw_minimize; 132 nw->res_get = nw_res_get; 133 nw->res_set = nw_res_set; 134 return (nw); 135 } 136 137 /* Methods */ 138 139 static void 140 nw_close(struct irs_nw *this) { 141 struct pvt *pvt = (struct pvt *)this->private; 142 143 nw_minimize(this); 144 if (pvt->res && pvt->free_res) 145 (*pvt->free_res)(pvt->res); 146 if (pvt->nwbuf) 147 free(pvt->nwbuf); 148 memput(pvt, sizeof *pvt); 149 memput(this, sizeof *this); 150 } 151 152 static struct nwent * 153 nw_byaddr(struct irs_nw *this, void *net, int length, int af) { 154 struct pvt *pvt = (struct pvt *)this->private; 155 char tmp[sizeof "255.255.255.255/32"], *t; 156 int r; 157 158 if (init(this) == -1) 159 return (NULL); 160 161 if (af != AF_INET) { 162 RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 163 errno = EAFNOSUPPORT; 164 return (NULL); 165 } 166 nisfree(pvt, do_val); 167 /* Try it with /CIDR first. */ 168 if (inet_net_ntop(AF_INET, net, length, tmp, sizeof tmp) == NULL) { 169 RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 170 return (NULL); 171 } 172 r = yp_match(pvt->nis_domain, networks_byaddr, tmp, strlen(tmp), 173 &pvt->curval_data, &pvt->curval_len); 174 if (r != 0) { 175 /* Give it a shot without the /CIDR. */ 176 if ((t = strchr(tmp, '/')) != NULL) { 177 *t = '\0'; 178 r = yp_match(pvt->nis_domain, networks_byaddr, 179 tmp, strlen(tmp), 180 &pvt->curval_data, &pvt->curval_len); 181 } 182 if (r != 0) { 183 RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 184 return (NULL); 185 } 186 } 187 return (makenwent(this)); 188 } 189 190 static struct nwent * 191 nw_byname(struct irs_nw *this, const char *name, int af) { 192 struct pvt *pvt = (struct pvt *)this->private; 193 int r; 194 char *tmp; 195 196 if (init(this) == -1) 197 return (NULL); 198 199 if (af != AF_INET) { 200 RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 201 errno = EAFNOSUPPORT; 202 return (NULL); 203 } 204 nisfree(pvt, do_val); 205 DE_CONST(name, tmp); 206 r = yp_match(pvt->nis_domain, networks_byname, tmp, 207 strlen(tmp), &pvt->curval_data, &pvt->curval_len); 208 if (r != 0) { 209 RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 210 return (NULL); 211 } 212 return (makenwent(this)); 213 } 214 215 static void 216 nw_rewind(struct irs_nw *this) { 217 struct pvt *pvt = (struct pvt *)this->private; 218 219 pvt->needrewind = 1; 220 } 221 222 static struct nwent * 223 nw_next(struct irs_nw *this) { 224 struct pvt *pvt = (struct pvt *)this->private; 225 struct nwent *rval; 226 int r; 227 228 if (init(this) == -1) 229 return (NULL); 230 231 do { 232 if (pvt->needrewind) { 233 nisfree(pvt, do_all); 234 r = yp_first(pvt->nis_domain, networks_byaddr, 235 &pvt->curkey_data, &pvt->curkey_len, 236 &pvt->curval_data, &pvt->curval_len); 237 pvt->needrewind = 0; 238 } else { 239 char *newkey_data; 240 int newkey_len; 241 242 nisfree(pvt, do_val); 243 r = yp_next(pvt->nis_domain, networks_byaddr, 244 pvt->curkey_data, pvt->curkey_len, 245 &newkey_data, &newkey_len, 246 &pvt->curval_data, &pvt->curval_len); 247 nisfree(pvt, do_key); 248 pvt->curkey_data = newkey_data; 249 pvt->curkey_len = newkey_len; 250 } 251 if (r != 0) { 252 RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 253 return (NULL); 254 } 255 rval = makenwent(this); 256 } while (rval == NULL); 257 return (rval); 258 } 259 260 static void 261 nw_minimize(struct irs_nw *this) { 262 struct pvt *pvt = (struct pvt *)this->private; 263 264 if (pvt->res) 265 res_nclose(pvt->res); 266 } 267 268 static struct __res_state * 269 nw_res_get(struct irs_nw *this) { 270 struct pvt *pvt = (struct pvt *)this->private; 271 272 if (!pvt->res) { 273 struct __res_state *res; 274 res = (struct __res_state *)malloc(sizeof *res); 275 if (!res) { 276 errno = ENOMEM; 277 return (NULL); 278 } 279 memset(res, 0, sizeof *res); 280 nw_res_set(this, res, free); 281 } 282 283 return (pvt->res); 284 } 285 286 static void 287 nw_res_set(struct irs_nw *this, struct __res_state *res, 288 void (*free_res)(void *)) { 289 struct pvt *pvt = (struct pvt *)this->private; 290 291 if (pvt->res && pvt->free_res) { 292 res_nclose(pvt->res); 293 (*pvt->free_res)(pvt->res); 294 } 295 296 pvt->res = res; 297 pvt->free_res = free_res; 298 } 299 300 /* Private */ 301 302 static struct nwent * 303 makenwent(struct irs_nw *this) { 304 struct pvt *pvt = (struct pvt *)this->private; 305 static const char spaces[] = " \t"; 306 char *t, *cp, **ap; 307 308 if (pvt->nwbuf) 309 free(pvt->nwbuf); 310 pvt->nwbuf = pvt->curval_data; 311 pvt->curval_data = NULL; 312 313 if ((cp = strpbrk(pvt->nwbuf, "#\n")) != NULL) 314 *cp = '\0'; 315 cp = pvt->nwbuf; 316 317 /* Name */ 318 pvt->nwent.n_name = cp; 319 cp += strcspn(cp, spaces); 320 if (!*cp) 321 goto cleanup; 322 *cp++ = '\0'; 323 cp += strspn(cp, spaces); 324 325 /* Network */ 326 pvt->nwent.n_addrtype = AF_INET; 327 t = cp + strcspn(cp, spaces); 328 if (*t) 329 *t++ = '\0'; 330 pvt->nwent.n_length = inet_net_pton(AF_INET, cp, 331 pvt->addr, sizeof pvt->addr); 332 if (pvt->nwent.n_length < 0) 333 goto cleanup; 334 pvt->nwent.n_addr = pvt->addr; 335 cp = t; 336 337 /* Aliases */ 338 ap = pvt->nwent.n_aliases = pvt->aliases; 339 while (*cp) { 340 if (ap >= &pvt->aliases[MAXALIASES]) 341 break; 342 *ap++ = cp; 343 cp += strcspn(cp, spaces); 344 if (!*cp) 345 break; 346 *cp++ = '\0'; 347 cp += strspn(cp, spaces); 348 } 349 *ap = NULL; 350 351 return (&pvt->nwent); 352 353 cleanup: 354 if (pvt->nwbuf) { 355 free(pvt->nwbuf); 356 pvt->nwbuf = NULL; 357 } 358 return (NULL); 359 } 360 361 static void 362 nisfree(struct pvt *pvt, enum do_what do_what) { 363 if ((do_what & do_key) && pvt->curkey_data) { 364 free(pvt->curkey_data); 365 pvt->curkey_data = NULL; 366 } 367 if ((do_what & do_val) && pvt->curval_data) { 368 free(pvt->curval_data); 369 pvt->curval_data = NULL; 370 } 371 } 372 373 static int 374 init(struct irs_nw *this) { 375 struct pvt *pvt = (struct pvt *)this->private; 376 377 if (!pvt->res && !nw_res_get(this)) 378 return (-1); 379 if (((pvt->res->options & RES_INIT) == 0) && 380 res_ninit(pvt->res) == -1) 381 return (-1); 382 return (0); 383 } 384 385 #endif /*WANT_IRS_NIS*/ 386 387 /*! \file */ 388