1/* $NetBSD: lcl_nw.c,v 1.1.1.2 2012/09/09 16:07:59 christos Exp $ */ 2 3/* 4 * Copyright (c) 1989, 1993, 1995 5 * The Regents of the University of California. 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36/* 37 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 38 * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 39 * 40 * Permission to use, copy, modify, and distribute this software for any 41 * purpose with or without fee is hereby granted, provided that the above 42 * copyright notice and this permission notice appear in all copies. 43 * 44 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 45 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 46 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 47 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 48 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 49 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 50 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 51 */ 52 53#if defined(LIBC_SCCS) && !defined(lint) 54static const char rcsid[] = "Id: lcl_nw.c,v 1.4 2005/04/27 04:56:31 sra Exp "; 55/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ 56/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ 57#endif /* LIBC_SCCS and not lint */ 58 59/* Imports */ 60 61#include "port_before.h" 62 63#include <sys/types.h> 64#include <sys/socket.h> 65 66#include <netinet/in.h> 67#include <arpa/inet.h> 68#include <arpa/nameser.h> 69 70#include <errno.h> 71#include <fcntl.h> 72#include <resolv.h> 73#include <stdio.h> 74#include <stdlib.h> 75#include <string.h> 76 77#include <irs.h> 78#include <isc/memcluster.h> 79 80#include "port_after.h" 81 82#include <isc/misc.h> 83#include "irs_p.h" 84#include "lcl_p.h" 85 86#define MAXALIASES 35 87#define MAXADDRSIZE 4 88 89struct pvt { 90 FILE * fp; 91 char line[BUFSIZ+1]; 92 struct nwent net; 93 char * aliases[MAXALIASES]; 94 char addr[MAXADDRSIZE]; 95 struct __res_state * res; 96 void (*free_res)(void *); 97}; 98 99/* Forward */ 100 101static void nw_close(struct irs_nw *); 102static struct nwent * nw_byname(struct irs_nw *, const char *, int); 103static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); 104static struct nwent * nw_next(struct irs_nw *); 105static void nw_rewind(struct irs_nw *); 106static void nw_minimize(struct irs_nw *); 107static struct __res_state * nw_res_get(struct irs_nw *this); 108static void nw_res_set(struct irs_nw *this, 109 struct __res_state *res, 110 void (*free_res)(void *)); 111 112static int init(struct irs_nw *this); 113 114/* Portability. */ 115 116#ifndef SEEK_SET 117# define SEEK_SET 0 118#endif 119 120/* Public */ 121 122struct irs_nw * 123irs_lcl_nw(struct irs_acc *this) { 124 struct irs_nw *nw; 125 struct pvt *pvt; 126 127 UNUSED(this); 128 129 if (!(pvt = memget(sizeof *pvt))) { 130 errno = ENOMEM; 131 return (NULL); 132 } 133 memset(pvt, 0, sizeof *pvt); 134 if (!(nw = memget(sizeof *nw))) { 135 memput(pvt, sizeof *pvt); 136 errno = ENOMEM; 137 return (NULL); 138 } 139 memset(nw, 0x5e, sizeof *nw); 140 nw->private = pvt; 141 nw->close = nw_close; 142 nw->byname = nw_byname; 143 nw->byaddr = nw_byaddr; 144 nw->next = nw_next; 145 nw->rewind = nw_rewind; 146 nw->minimize = nw_minimize; 147 nw->res_get = nw_res_get; 148 nw->res_set = nw_res_set; 149 return (nw); 150} 151 152/* Methods */ 153 154static void 155nw_close(struct irs_nw *this) { 156 struct pvt *pvt = (struct pvt *)this->private; 157 158 nw_minimize(this); 159 if (pvt->res && pvt->free_res) 160 (*pvt->free_res)(pvt->res); 161 if (pvt->fp) 162 (void)fclose(pvt->fp); 163 memput(pvt, sizeof *pvt); 164 memput(this, sizeof *this); 165} 166 167static struct nwent * 168nw_byaddr(struct irs_nw *this, void *net, int length, int type) { 169 struct nwent *p; 170 171 if (init(this) == -1) 172 return(NULL); 173 174 nw_rewind(this); 175 while ((p = nw_next(this)) != NULL) 176 if (p->n_addrtype == type && p->n_length == length) 177 if (bitncmp(p->n_addr, net, length) == 0) 178 break; 179 return (p); 180} 181 182static struct nwent * 183nw_byname(struct irs_nw *this, const char *name, int type) { 184 struct nwent *p; 185 char **ap; 186 187 if (init(this) == -1) 188 return(NULL); 189 190 nw_rewind(this); 191 while ((p = nw_next(this)) != NULL) { 192 if (ns_samename(p->n_name, name) == 1 && 193 p->n_addrtype == type) 194 break; 195 for (ap = p->n_aliases; *ap; ap++) 196 if ((ns_samename(*ap, name) == 1) && 197 (p->n_addrtype == type)) 198 goto found; 199 } 200 found: 201 return (p); 202} 203 204static void 205nw_rewind(struct irs_nw *this) { 206 struct pvt *pvt = (struct pvt *)this->private; 207 208 if (pvt->fp) { 209 if (fseek(pvt->fp, 0L, SEEK_SET) == 0) 210 return; 211 (void)fclose(pvt->fp); 212 } 213 if (!(pvt->fp = fopen(_PATH_NETWORKS, "r"))) 214 return; 215 if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { 216 (void)fclose(pvt->fp); 217 pvt->fp = NULL; 218 } 219} 220 221static struct nwent * 222nw_next(struct irs_nw *this) { 223 struct pvt *pvt = (struct pvt *)this->private; 224 struct nwent *ret = NULL; 225 char *p, *cp, **q; 226 char *bufp, *ndbuf, *dbuf = NULL; 227 int c, bufsiz, offset = 0; 228 229 if (init(this) == -1) 230 return(NULL); 231 232 if (pvt->fp == NULL) 233 nw_rewind(this); 234 if (pvt->fp == NULL) { 235 RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 236 return (NULL); 237 } 238 bufp = pvt->line; 239 bufsiz = sizeof(pvt->line); 240 241 again: 242 p = fgets(bufp + offset, bufsiz - offset, pvt->fp); 243 if (p == NULL) 244 goto cleanup; 245 if (!strchr(p, '\n') && !feof(pvt->fp)) { 246#define GROWBUF 1024 247 /* allocate space for longer line */ 248 if (dbuf == NULL) { 249 if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) 250 strcpy(ndbuf, bufp); 251 } else 252 ndbuf = realloc(dbuf, bufsiz + GROWBUF); 253 if (ndbuf) { 254 dbuf = ndbuf; 255 bufp = dbuf; 256 bufsiz += GROWBUF; 257 offset = strlen(dbuf); 258 } else { 259 /* allocation failed; skip this long line */ 260 while ((c = getc(pvt->fp)) != EOF) 261 if (c == '\n') 262 break; 263 if (c != EOF) 264 ungetc(c, pvt->fp); 265 } 266 goto again; 267 } 268 269 p -= offset; 270 offset = 0; 271 272 if (*p == '#') 273 goto again; 274 275 cp = strpbrk(p, "#\n"); 276 if (cp != NULL) 277 *cp = '\0'; 278 pvt->net.n_name = p; 279 cp = strpbrk(p, " \t"); 280 if (cp == NULL) 281 goto again; 282 *cp++ = '\0'; 283 while (*cp == ' ' || *cp == '\t') 284 cp++; 285 p = strpbrk(cp, " \t"); 286 if (p != NULL) 287 *p++ = '\0'; 288 pvt->net.n_length = inet_net_pton(AF_INET, cp, pvt->addr, 289 sizeof pvt->addr); 290 if (pvt->net.n_length < 0) 291 goto again; 292 pvt->net.n_addrtype = AF_INET; 293 pvt->net.n_addr = pvt->addr; 294 q = pvt->net.n_aliases = pvt->aliases; 295 if (p != NULL) { 296 cp = p; 297 while (cp && *cp) { 298 if (*cp == ' ' || *cp == '\t') { 299 cp++; 300 continue; 301 } 302 if (q < &pvt->aliases[MAXALIASES - 1]) 303 *q++ = cp; 304 cp = strpbrk(cp, " \t"); 305 if (cp != NULL) 306 *cp++ = '\0'; 307 } 308 } 309 *q = NULL; 310 ret = &pvt->net; 311 312 cleanup: 313 if (dbuf) 314 free(dbuf); 315 316 return (ret); 317} 318 319static void 320nw_minimize(struct irs_nw *this) { 321 struct pvt *pvt = (struct pvt *)this->private; 322 323 if (pvt->res) 324 res_nclose(pvt->res); 325 if (pvt->fp != NULL) { 326 (void)fclose(pvt->fp); 327 pvt->fp = NULL; 328 } 329} 330 331static struct __res_state * 332nw_res_get(struct irs_nw *this) { 333 struct pvt *pvt = (struct pvt *)this->private; 334 335 if (!pvt->res) { 336 struct __res_state *res; 337 res = (struct __res_state *)malloc(sizeof *res); 338 if (!res) { 339 errno = ENOMEM; 340 return (NULL); 341 } 342 memset(res, 0, sizeof *res); 343 nw_res_set(this, res, free); 344 } 345 346 return (pvt->res); 347} 348 349static void 350nw_res_set(struct irs_nw *this, struct __res_state *res, 351 void (*free_res)(void *)) { 352 struct pvt *pvt = (struct pvt *)this->private; 353 354 if (pvt->res && pvt->free_res) { 355 res_nclose(pvt->res); 356 (*pvt->free_res)(pvt->res); 357 } 358 359 pvt->res = res; 360 pvt->free_res = free_res; 361} 362 363static int 364init(struct irs_nw *this) { 365 struct pvt *pvt = (struct pvt *)this->private; 366 367 if (!pvt->res && !nw_res_get(this)) 368 return (-1); 369 if (((pvt->res->options & RES_INIT) == 0U) && 370 res_ninit(pvt->res) == -1) 371 return (-1); 372 return (0); 373} 374 375/*! \file */ 376