2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
36 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
38 * Permission to use, copy, modify, and distribute this software for any
39 * purpose with or without fee is hereby granted, provided that the above
40 * copyright notice and this permission notice appear in all copies.
42 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
48 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51 #if defined(LIBC_SCCS) && !defined(lint)
52 static const char rcsid
[] = "$Id: lcl_sv.c,v 1.2.206.1 2004/03/09 08:33:38 marka Exp $";
53 #endif /* LIBC_SCCS and not lint */
57 #include "port_before.h"
59 #include <sys/types.h>
60 #include <sys/socket.h>
61 #include <netinet/in.h>
62 #include <arpa/nameser.h>
76 #include <isc/memcluster.h>
78 #include "port_after.h"
84 # define SPRINTF(x) strlen(sprintf/**/x)
86 # define SPRINTF(x) ((size_t)sprintf x)
101 static void sv_close(struct irs_sv
*);
102 static struct servent
* sv_next(struct irs_sv
*);
103 static struct servent
* sv_byname(struct irs_sv
*, const char *,
105 static struct servent
* sv_byport(struct irs_sv
*, int, const char *);
106 static void sv_rewind(struct irs_sv
*);
107 static void sv_minimize(struct irs_sv
*);
108 /*global*/ struct servent
* irs_lclsv_fnxt(struct lcl_sv
*);
110 static struct servent
* sv_db_rec(struct lcl_sv
*, DBT
*, DBT
*);
122 irs_lcl_sv(struct irs_acc
*this) {
128 if ((sv
= memget(sizeof *sv
)) == NULL
) {
132 memset(sv
, 0x5e, sizeof *sv
);
133 if ((pvt
= memget(sizeof *pvt
)) == NULL
) {
134 memput(sv
, sizeof *sv
);
138 memset(pvt
, 0, sizeof *pvt
);
140 sv
->close
= sv_close
;
142 sv
->byname
= sv_byname
;
143 sv
->byport
= sv_byport
;
144 sv
->rewind
= sv_rewind
;
145 sv
->minimize
= sv_minimize
;
157 sv_close(struct irs_sv
*this) {
158 struct pvt
*pvt
= (struct pvt
*)this->private;
161 if (pvt
->dbh
!= NULL
)
162 (*pvt
->dbh
->close
)(pvt
->dbh
);
166 memput(pvt
, sizeof *pvt
);
167 memput(this, sizeof *this);
170 static struct servent
*
171 sv_byname(struct irs_sv
*this, const char *name
, const char *proto
) {
173 struct pvt
*pvt
= (struct pvt
*)this->private;
180 if (pvt
->dbh
!= NULL
) {
183 /* Note that (sizeof "/") == 2. */
184 if ((strlen(name
) + sizeof "/" + proto
? strlen(proto
) : 0)
185 > sizeof pvt
->sv
.line
)
187 key
.data
= pvt
->sv
.line
;
188 key
.size
= SPRINTF((pvt
->sv
.line
, "%s/%s", name
,
189 proto
? proto
: "")) + 1;
191 if ((*pvt
->dbh
->get
)(pvt
->dbh
, &key
, &data
, 0) != 0)
193 } else if ((*pvt
->dbh
->seq
)(pvt
->dbh
, &key
, &data
, R_CURSOR
)
196 return (sv_db_rec(&pvt
->sv
, &key
, &data
));
201 while ((p
= sv_next(this))) {
202 if (strcmp(name
, p
->s_name
) == 0)
204 for (cp
= p
->s_aliases
; *cp
; cp
++)
205 if (strcmp(name
, *cp
) == 0)
209 if (proto
== NULL
|| strcmp(p
->s_proto
, proto
) == 0)
215 static struct servent
*
216 sv_byport(struct irs_sv
*this, int port
, const char *proto
) {
218 struct pvt
*pvt
= (struct pvt
*)this->private;
224 if (pvt
->dbh
!= NULL
) {
228 ports
= (u_short
*)pvt
->sv
.line
;
232 key
.size
= sizeof(u_short
) * 2;
233 if (proto
&& *proto
) {
234 strncpy((char *)ports
+ key
.size
, proto
,
236 key
.size
+= strlen((char *)ports
+ key
.size
) + 1;
237 if ((*pvt
->dbh
->get
)(pvt
->dbh
, &key
, &data
, 0) != 0)
240 if ((*pvt
->dbh
->seq
)(pvt
->dbh
, &key
, &data
, R_CURSOR
)
244 return (sv_db_rec(&pvt
->sv
, &key
, &data
));
247 while ((p
= sv_next(this))) {
248 if (p
->s_port
!= port
)
250 if (proto
== NULL
|| strcmp(p
->s_proto
, proto
) == 0)
257 sv_rewind(struct irs_sv
*this) {
258 struct pvt
*pvt
= (struct pvt
*)this->private;
261 if (fseek(pvt
->sv
.fp
, 0L, SEEK_SET
) == 0)
263 (void)fclose(pvt
->sv
.fp
);
268 if (pvt
->dbh
!= NULL
)
270 pvt
->dbh
= dbopen(_PATH_SERVICES_DB
, O_RDONLY
,O_RDONLY
,DB_BTREE
, NULL
);
271 if (pvt
->dbh
!= NULL
) {
272 if (fcntl((*pvt
->dbh
->fd
)(pvt
->dbh
), F_SETFD
, 1) < 0) {
273 (*pvt
->dbh
->close
)(pvt
->dbh
);
279 if ((pvt
->sv
.fp
= fopen(_PATH_SERVICES
, "r")) == NULL
)
281 if (fcntl(fileno(pvt
->sv
.fp
), F_SETFD
, 1) < 0) {
282 (void)fclose(pvt
->sv
.fp
);
287 static struct servent
*
288 sv_next(struct irs_sv
*this) {
289 struct pvt
*pvt
= (struct pvt
*)this->private;
292 if (pvt
->dbh
== NULL
&& pvt
->sv
.fp
== NULL
)
294 if (pvt
->sv
.fp
== NULL
)
299 if (pvt
->dbh
!= NULL
) {
302 while ((*pvt
->dbh
->seq
)(pvt
->dbh
, &key
, &data
, pvt
->dbf
) == 0){
304 if (((char *)key
.data
)[0])
306 return (sv_db_rec(&pvt
->sv
, &key
, &data
));
311 if (pvt
->sv
.fp
== NULL
)
313 return (irs_lclsv_fnxt(&pvt
->sv
));
317 sv_minimize(struct irs_sv
*this) {
318 struct pvt
*pvt
= (struct pvt
*)this->private;
321 if (pvt
->dbh
!= NULL
) {
322 (*pvt
->dbh
->close
)(pvt
->dbh
);
326 if (pvt
->sv
.fp
!= NULL
) {
327 (void)fclose(pvt
->sv
.fp
);
335 irs_lclsv_fnxt(struct lcl_sv
*sv
) {
339 if ((p
= fgets(sv
->line
, BUFSIZ
, sv
->fp
)) == NULL
)
344 while (*p
&& *p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '#')
346 if (*p
== '\0' || *p
== '#' || *p
== '\n')
349 while (*p
== ' ' || *p
== '\t')
351 if (*p
== '\0' || *p
== '#' || *p
== '\n')
353 sv
->serv
.s_port
= htons((u_short
)strtol(p
, &cp
, 10));
354 if (cp
== p
|| (*cp
!= '/' && *cp
!= ','))
357 sv
->serv
.s_proto
= p
;
359 q
= sv
->serv
.s_aliases
= sv
->serv_aliases
;
361 while (*p
&& *p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '#')
364 while (*p
== ' ' || *p
== '\t') {
366 while (*p
== ' ' || *p
== '\t')
368 if (*p
== '\0' || *p
== '#' || *p
== '\n')
370 if (q
< &sv
->serv_aliases
[IRS_SV_MAXALIASES
- 1])
372 while (*p
&& *p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '#')
384 static struct servent
*
385 sv_db_rec(struct lcl_sv
*sv
, DBT
*key
, DBT
*data
) {
390 p
[data
->size
- 1] = '\0'; /* should be, but we depend on it */
392 if (((char *)key
->data
)[0] == '\0') {
393 if (key
->size
< sizeof(u_short
)*2 || data
->size
< 2)
395 sv
->serv
.s_port
= ((u_short
*)key
->data
)[1];
397 if ((size_t)n
> sizeof(sv
->line
)) {
398 n
= sizeof(sv
->line
);
400 memcpy(sv
->line
, p
, n
);
401 sv
->serv
.s_name
= sv
->line
;
402 if ((sv
->serv
.s_proto
= strchr(sv
->line
, '/')) != NULL
)
403 *(sv
->serv
.s_proto
)++ = '\0';
407 if (data
->size
< sizeof(u_short
) + 1)
409 if (key
->size
> sizeof(sv
->line
))
410 key
->size
= sizeof(sv
->line
);
411 ((char *)key
->data
)[key
->size
- 1] = '\0';
412 memcpy(sv
->line
, key
->data
, key
->size
);
413 sv
->serv
.s_name
= sv
->line
;
414 if ((sv
->serv
.s_proto
= strchr(sv
->line
, '/')) != NULL
)
415 *(sv
->serv
.s_proto
)++ = '\0';
416 sv
->serv
.s_port
= *(u_short
*)data
->data
;
417 p
+= sizeof(u_short
);
418 data
->size
-= sizeof(u_short
);
420 q
= sv
->serv
.s_aliases
= sv
->serv_aliases
;
421 while (data
->size
> 0 && q
< &sv
->serv_aliases
[IRS_SV_MAXALIASES
- 1]) {