Home | History | Annotate | Line # | Download | only in net
getservent_r.c revision 1.12
      1  1.12       nia /*	$NetBSD: getservent_r.c,v 1.12 2022/03/12 08:43:11 nia Exp $	*/
      2   1.1  christos 
      3   1.1  christos /*
      4   1.1  christos  * Copyright (c) 1983, 1993
      5   1.1  christos  *	The Regents of the University of California.  All rights reserved.
      6   1.1  christos  *
      7   1.1  christos  * Redistribution and use in source and binary forms, with or without
      8   1.1  christos  * modification, are permitted provided that the following conditions
      9   1.1  christos  * are met:
     10   1.1  christos  * 1. Redistributions of source code must retain the above copyright
     11   1.1  christos  *    notice, this list of conditions and the following disclaimer.
     12   1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     14   1.1  christos  *    documentation and/or other materials provided with the distribution.
     15   1.1  christos  * 3. Neither the name of the University nor the names of its contributors
     16   1.1  christos  *    may be used to endorse or promote products derived from this software
     17   1.1  christos  *    without specific prior written permission.
     18   1.1  christos  *
     19   1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20   1.1  christos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21   1.1  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22   1.1  christos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23   1.1  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24   1.1  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25   1.1  christos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26   1.1  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27   1.1  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28   1.1  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29   1.1  christos  * SUCH DAMAGE.
     30   1.1  christos  */
     31   1.1  christos 
     32   1.1  christos #include <sys/cdefs.h>
     33   1.1  christos #if defined(LIBC_SCCS) && !defined(lint)
     34   1.1  christos #if 0
     35   1.1  christos static char sccsid[] = "@(#)getservent.c	8.1 (Berkeley) 6/4/93";
     36   1.1  christos #else
     37  1.12       nia __RCSID("$NetBSD: getservent_r.c,v 1.12 2022/03/12 08:43:11 nia Exp $");
     38   1.1  christos #endif
     39   1.1  christos #endif /* LIBC_SCCS and not lint */
     40   1.1  christos 
     41   1.1  christos #include "namespace.h"
     42  1.10     joerg #include <cdbr.h>
     43  1.10     joerg #include <errno.h>
     44  1.10     joerg #include <fcntl.h>
     45   1.1  christos #include <netdb.h>
     46   1.1  christos #include <stdio.h>
     47  1.10     joerg #include <stdlib.h>
     48   1.1  christos #include <string.h>
     49   1.1  christos 
     50   1.5    kleink #include "servent.h"
     51   1.5    kleink 
     52   1.1  christos #ifdef __weak_alias
     53   1.1  christos __weak_alias(endservent_r,_endservent_r)
     54   1.1  christos __weak_alias(getservent_r,_getservent_r)
     55   1.1  christos __weak_alias(setservent_r,_setservent_r)
     56   1.1  christos #endif
     57   1.1  christos 
     58   1.6  christos int
     59   1.6  christos _servent_open(struct servent_data *sd)
     60   1.1  christos {
     61  1.10     joerg 	if (sd->flags & (_SV_CDB | _SV_PLAINFILE)) {
     62  1.10     joerg 		sd->flags |= _SV_FIRST;
     63  1.10     joerg 		return 0;
     64  1.10     joerg 	}
     65  1.10     joerg 
     66  1.10     joerg 	free(sd->line);
     67  1.10     joerg 	sd->line = NULL;
     68  1.10     joerg 	free(sd->cdb_buf);
     69  1.10     joerg 	sd->cdb_buf = NULL;
     70  1.10     joerg 	sd->cdb_buf_len = 0;
     71  1.10     joerg 	free(sd->aliases);
     72  1.10     joerg 	sd->aliases = NULL;
     73  1.10     joerg 	sd->maxaliases = 0;
     74   1.8  christos 	sd->flags |= _SV_FIRST;
     75  1.10     joerg 
     76  1.10     joerg 	sd->cdb = cdbr_open(_PATH_SERVICES_CDB, CDBR_DEFAULT);
     77  1.10     joerg 	if (sd->cdb != NULL) {
     78  1.10     joerg 		sd->flags |= _SV_CDB;
     79  1.10     joerg 		return 0;
     80  1.10     joerg 	}
     81  1.10     joerg 
     82  1.11  christos 	sd->plainfile = fopen(_PATH_SERVICES, "re");
     83  1.10     joerg 	if (sd->plainfile != NULL) {
     84  1.10     joerg 		sd->flags |= _SV_PLAINFILE;
     85  1.10     joerg 		return 0;
     86   1.6  christos 	}
     87  1.10     joerg 	return -1;
     88   1.1  christos }
     89   1.1  christos 
     90   1.1  christos void
     91   1.6  christos _servent_close(struct servent_data *sd)
     92   1.1  christos {
     93  1.10     joerg 	if (sd->flags & _SV_CDB) {
     94  1.10     joerg 		cdbr_close(sd->cdb);
     95  1.10     joerg 		sd->cdb = NULL;
     96  1.10     joerg 		sd->flags &= ~_SV_CDB;
     97  1.10     joerg 	}
     98  1.10     joerg 
     99  1.10     joerg 	if (sd->flags & _SV_PLAINFILE) {
    100  1.10     joerg 		(void)fclose(sd->plainfile);
    101  1.10     joerg 		sd->plainfile = NULL;
    102  1.10     joerg 		sd->flags &= ~_SV_PLAINFILE;
    103   1.1  christos 	}
    104   1.6  christos 	sd->flags &= ~_SV_STAYOPEN;
    105   1.6  christos }
    106   1.6  christos 
    107   1.6  christos 
    108   1.6  christos int
    109   1.6  christos _servent_getline(struct servent_data *sd)
    110   1.6  christos {
    111   1.9  christos 
    112  1.10     joerg 	if (sd->flags & _SV_CDB)
    113  1.10     joerg 		return -1;
    114  1.10     joerg 
    115  1.10     joerg 	if ((sd->flags & _SV_PLAINFILE) == 0)
    116   1.9  christos 		return -1;
    117   1.9  christos 
    118  1.10     joerg 	free(sd->line);
    119  1.10     joerg 	sd->line = NULL;
    120  1.10     joerg 
    121  1.10     joerg 	if (sd->flags & _SV_FIRST) {
    122  1.10     joerg 		(void)rewind((FILE *)sd->plainfile);
    123  1.10     joerg 		sd->flags &= ~_SV_FIRST;
    124   1.6  christos 	}
    125  1.10     joerg 	sd->line = fparseln(sd->plainfile, NULL, NULL, NULL,
    126  1.10     joerg 	    FPARSELN_UNESCALL);
    127   1.6  christos 	return sd->line == NULL ? -1 : 0;
    128   1.1  christos }
    129   1.1  christos 
    130   1.1  christos struct servent *
    131   1.6  christos _servent_parseline(struct servent_data *sd, struct servent *sp)
    132   1.1  christos {
    133   1.1  christos 	size_t i = 0;
    134   1.1  christos 	int oerrno;
    135   1.6  christos 	char *p, *cp, **q;
    136   1.1  christos 
    137   1.6  christos 	if (sd->line == NULL)
    138   1.1  christos 		return NULL;
    139   1.1  christos 
    140   1.6  christos 	sp->s_name = p = sd->line;
    141   1.6  christos 	p = strpbrk(p, " \t");
    142   1.6  christos 	if (p == NULL)
    143   1.6  christos 		return NULL;
    144   1.6  christos 	*p++ = '\0';
    145   1.6  christos 	while (*p == ' ' || *p == '\t')
    146   1.6  christos 		p++;
    147   1.6  christos 	cp = strpbrk(p, ",/");
    148   1.6  christos 	if (cp == NULL)
    149   1.6  christos 		return NULL;
    150   1.6  christos 	*cp++ = '\0';
    151   1.6  christos 	sp->s_port = htons((u_short)atoi(p));
    152   1.6  christos 	sp->s_proto = cp;
    153   1.6  christos 	if (sd->aliases == NULL) {
    154   1.6  christos 		sd->maxaliases = 10;
    155  1.10     joerg 		sd->aliases = calloc(sd->maxaliases, sizeof(*sd->aliases));
    156   1.6  christos 		if (sd->aliases == NULL) {
    157   1.6  christos 			oerrno = errno;
    158   1.6  christos 			endservent_r(sd);
    159   1.6  christos 			errno = oerrno;
    160   1.1  christos 			return NULL;
    161   1.6  christos 		}
    162   1.6  christos 	}
    163  1.10     joerg 	sp->s_aliases = sd->aliases;
    164   1.6  christos 	cp = strpbrk(cp, " \t");
    165   1.6  christos 	if (cp != NULL)
    166   1.6  christos 		*cp++ = '\0';
    167   1.6  christos 	while (cp && *cp) {
    168   1.6  christos 		if (*cp == ' ' || *cp == '\t') {
    169   1.6  christos 			cp++;
    170   1.1  christos 			continue;
    171   1.6  christos 		}
    172   1.6  christos 		if (i == sd->maxaliases - 2) {
    173   1.6  christos 			sd->maxaliases *= 2;
    174  1.10     joerg 			q = realloc(sd->aliases, sd->maxaliases * sizeof(*q));
    175   1.6  christos 			if (q == NULL) {
    176   1.1  christos 				oerrno = errno;
    177   1.1  christos 				endservent_r(sd);
    178   1.1  christos 				errno = oerrno;
    179   1.1  christos 				return NULL;
    180   1.1  christos 			}
    181   1.6  christos 			sp->s_aliases = sd->aliases = q;
    182   1.1  christos 		}
    183  1.10     joerg 		sp->s_aliases[i++] = cp;
    184   1.1  christos 		cp = strpbrk(cp, " \t");
    185   1.1  christos 		if (cp != NULL)
    186   1.1  christos 			*cp++ = '\0';
    187   1.6  christos 	}
    188  1.10     joerg 	sp->s_aliases[i] = NULL;
    189   1.6  christos 	return sp;
    190   1.6  christos }
    191   1.6  christos 
    192   1.6  christos void
    193   1.6  christos setservent_r(int f, struct servent_data *sd)
    194   1.6  christos {
    195   1.6  christos 	(void)_servent_open(sd);
    196   1.6  christos 	sd->flags |= f ? _SV_STAYOPEN : 0;
    197   1.6  christos }
    198   1.6  christos 
    199   1.6  christos void
    200   1.6  christos endservent_r(struct servent_data *sd)
    201   1.6  christos {
    202   1.6  christos 	_servent_close(sd);
    203  1.10     joerg 	free(sd->aliases);
    204  1.10     joerg 	sd->aliases = NULL;
    205  1.10     joerg 	sd->maxaliases = 0;
    206  1.10     joerg 	free(sd->line);
    207  1.10     joerg 	sd->line = NULL;
    208  1.10     joerg 	free(sd->cdb_buf);
    209  1.10     joerg 	sd->cdb_buf = NULL;
    210  1.10     joerg 	sd->cdb_buf_len = 0;
    211   1.6  christos }
    212   1.6  christos 
    213   1.6  christos struct servent *
    214   1.6  christos getservent_r(struct servent *sp, struct servent_data *sd)
    215   1.6  christos {
    216  1.10     joerg 
    217  1.10     joerg 	if ((sd->flags & (_SV_CDB | _SV_PLAINFILE)) == 0 &&
    218  1.10     joerg 	    _servent_open(sd) == -1)
    219   1.6  christos 		return NULL;
    220   1.6  christos 
    221  1.10     joerg 	if (sd->flags & _SV_CDB) {
    222  1.10     joerg 		const void *data;
    223  1.10     joerg 		size_t len;
    224  1.10     joerg 
    225  1.10     joerg 		if (sd->flags & _SV_FIRST) {
    226  1.10     joerg 			sd->cdb_index = 0;
    227  1.10     joerg 			sd->flags &= ~_SV_FIRST;
    228  1.10     joerg 		}
    229  1.10     joerg 
    230  1.10     joerg 		if (cdbr_get(sd->cdb, sd->cdb_index, &data, &len))
    231   1.6  christos 			return NULL;
    232  1.10     joerg 		++sd->cdb_index;
    233  1.10     joerg 		return _servent_parsedb(sd, sp, data, len);
    234  1.10     joerg 	}
    235  1.10     joerg 	if (sd->flags & _SV_PLAINFILE) {
    236  1.10     joerg 		for (;;) {
    237  1.10     joerg 			if (_servent_getline(sd) == -1)
    238  1.10     joerg 				return NULL;
    239  1.10     joerg 			if (_servent_parseline(sd, sp) == NULL)
    240  1.10     joerg 				continue;
    241  1.10     joerg 			return sp;
    242  1.10     joerg 		}
    243  1.10     joerg 	}
    244  1.10     joerg 	return NULL;
    245  1.10     joerg }
    246  1.10     joerg 
    247  1.10     joerg struct servent *
    248  1.10     joerg _servent_parsedb(struct servent_data *sd, struct servent *sp,
    249  1.10     joerg     const uint8_t *data, size_t len)
    250  1.10     joerg {
    251  1.10     joerg 	char **q;
    252  1.10     joerg 	size_t i;
    253  1.10     joerg 	int oerrno;
    254  1.10     joerg 
    255  1.10     joerg 	if ((sd->flags & _SV_STAYOPEN) == 0) {
    256  1.10     joerg 		if (len > sd->cdb_buf_len) {
    257  1.10     joerg 			void *tmp = realloc(sd->cdb_buf, len);
    258  1.10     joerg 			if (tmp == NULL)
    259  1.10     joerg 				goto fail;
    260  1.10     joerg 			sd->cdb_buf = tmp;
    261  1.10     joerg 			sd->cdb_buf_len = len;
    262  1.10     joerg 		}
    263  1.10     joerg 		memcpy(sd->cdb_buf, data, len);
    264  1.10     joerg 		data = sd->cdb_buf;
    265  1.10     joerg 	}
    266  1.10     joerg 
    267  1.10     joerg 	if (len < 2)
    268  1.10     joerg 		goto fail;
    269  1.10     joerg 	sp->s_port = htobe16(be16dec(data));
    270  1.10     joerg 	data += 2;
    271  1.10     joerg 	len -= 2;
    272  1.10     joerg 
    273  1.10     joerg 	if (len == 0 || len < (size_t)data[0] + 2)
    274  1.10     joerg 		goto fail;
    275  1.10     joerg 	sp->s_proto = __UNCONST(data + 1);
    276  1.10     joerg 
    277  1.10     joerg 	if (sp->s_proto[data[0]] != '\0')
    278  1.10     joerg 		goto fail;
    279  1.10     joerg 
    280  1.10     joerg 	len -= 2 + data[0];
    281  1.10     joerg 	data += 2 + data[0];
    282  1.10     joerg 
    283  1.10     joerg 	if (len == 0)
    284  1.10     joerg 		goto fail;
    285  1.10     joerg 	if (len < (size_t)data[0] + 2)
    286  1.10     joerg 		goto fail;
    287  1.10     joerg 
    288  1.10     joerg 	sp->s_name = __UNCONST(data + 1);
    289  1.10     joerg 	len -= 2 + data[0];
    290  1.10     joerg 	data += 2 + data[0];
    291  1.10     joerg 
    292  1.10     joerg 	if (sd->aliases == NULL) {
    293  1.10     joerg 		sd->maxaliases = 10;
    294  1.12       nia 		sd->aliases = NULL;
    295  1.12       nia 		if (reallocarr(&sd->aliases,
    296  1.12       nia 		    sd->maxaliases, sizeof(char *)) != 0) {
    297  1.12       nia 			errno = ENOMEM;
    298  1.10     joerg 			goto fail;
    299  1.12       nia 		}
    300  1.10     joerg 	}
    301  1.10     joerg 	sp->s_aliases = sd->aliases;
    302  1.10     joerg 	i = 0;
    303  1.10     joerg 	while (len) {
    304  1.10     joerg 		if (len < (size_t)data[0] + 2)
    305  1.10     joerg 			goto fail;
    306  1.10     joerg 		if (i == sd->maxaliases - 2) {
    307  1.10     joerg 			sd->maxaliases *= 2;
    308  1.12       nia 			q = sd->aliases;
    309  1.12       nia 			if (reallocarr(&q, sd->maxaliases, sizeof(*q)) != 0) {
    310  1.12       nia 				errno = ENOMEM;
    311  1.10     joerg 				goto fail;
    312  1.12       nia 			}
    313  1.10     joerg 			sp->s_aliases = sd->aliases = q;
    314  1.10     joerg 		}
    315  1.10     joerg 		sp->s_aliases[i++] = __UNCONST(data + 1);
    316  1.10     joerg 		len -= 2 + data[0];
    317  1.10     joerg 		data += 2 + data[0];
    318   1.1  christos 	}
    319  1.10     joerg 	sp->s_aliases[i] = NULL;
    320  1.10     joerg 	return sp;
    321  1.10     joerg 
    322  1.10     joerg fail:
    323  1.10     joerg 	oerrno = errno;
    324  1.10     joerg 	endservent_r(sd);
    325  1.10     joerg 	errno = oerrno;
    326  1.10     joerg 	return NULL;
    327   1.1  christos }
    328  1.10     joerg 
    329