4 * Copyright (c) 1989, 1993, 1995
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
37 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
38 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
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.
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.
53 #if defined(LIBC_SCCS) && !defined(lint)
54 static const char rcsid
[] = "Id: lcl_sv.c,v 1.4 2005/04/27 04:56:31 sra Exp";
55 #endif /* LIBC_SCCS and not lint */
59 #include "port_before.h"
61 #include <sys/types.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/nameser.h>
78 #include <isc/memcluster.h>
80 #include "port_after.h"
86 # define SPRINTF(x) strlen(sprintf/**/x)
88 # define SPRINTF(x) ((size_t)sprintf x)
103 static void sv_close(struct irs_sv
*);
104 static struct servent
* sv_next(struct irs_sv
*);
105 static struct servent
* sv_byname(struct irs_sv
*, const char *,
107 static struct servent
* sv_byport(struct irs_sv
*, int, const char *);
108 static void sv_rewind(struct irs_sv
*);
109 static void sv_minimize(struct irs_sv
*);
110 /*global*/ struct servent
* irs_lclsv_fnxt(struct lcl_sv
*);
112 static struct servent
* sv_db_rec(struct lcl_sv
*, DBT
*, DBT
*);
124 irs_lcl_sv(struct irs_acc
*this) {
130 if ((sv
= memget(sizeof *sv
)) == NULL
) {
134 memset(sv
, 0x5e, sizeof *sv
);
135 if ((pvt
= memget(sizeof *pvt
)) == NULL
) {
136 memput(sv
, sizeof *sv
);
140 memset(pvt
, 0, sizeof *pvt
);
142 sv
->close
= sv_close
;
144 sv
->byname
= sv_byname
;
145 sv
->byport
= sv_byport
;
146 sv
->rewind
= sv_rewind
;
147 sv
->minimize
= sv_minimize
;
159 sv_close(struct irs_sv
*this) {
160 struct pvt
*pvt
= (struct pvt
*)this->private;
163 if (pvt
->dbh
!= NULL
)
164 (*pvt
->dbh
->close
)(pvt
->dbh
);
168 memput(pvt
, sizeof *pvt
);
169 memput(this, sizeof *this);
172 static struct servent
*
173 sv_byname(struct irs_sv
*this, const char *name
, const char *proto
) {
175 struct pvt
*pvt
= (struct pvt
*)this->private;
182 if (pvt
->dbh
!= NULL
) {
185 /* Note that (sizeof "/") == 2. */
186 if ((strlen(name
) + sizeof "/" + proto
? strlen(proto
) : 0)
187 > sizeof pvt
->sv
.line
)
189 key
.data
= pvt
->sv
.line
;
190 key
.size
= SPRINTF((pvt
->sv
.line
, "%s/%s", name
,
191 proto
? proto
: "")) + 1;
193 if ((*pvt
->dbh
->get
)(pvt
->dbh
, &key
, &data
, 0) != 0)
195 } else if ((*pvt
->dbh
->seq
)(pvt
->dbh
, &key
, &data
, R_CURSOR
)
198 return (sv_db_rec(&pvt
->sv
, &key
, &data
));
203 while ((p
= sv_next(this))) {
204 if (strcmp(name
, p
->s_name
) == 0)
206 for (cp
= p
->s_aliases
; *cp
; cp
++)
207 if (strcmp(name
, *cp
) == 0)
211 if (proto
== NULL
|| strcmp(p
->s_proto
, proto
) == 0)
217 static struct servent
*
218 sv_byport(struct irs_sv
*this, int port
, const char *proto
) {
220 struct pvt
*pvt
= (struct pvt
*)this->private;
226 if (pvt
->dbh
!= NULL
) {
230 ports
= (u_short
*)pvt
->sv
.line
;
234 key
.size
= sizeof(u_short
) * 2;
235 if (proto
&& *proto
) {
236 strncpy((char *)ports
+ key
.size
, proto
,
238 key
.size
+= strlen((char *)ports
+ key
.size
) + 1;
239 if ((*pvt
->dbh
->get
)(pvt
->dbh
, &key
, &data
, 0) != 0)
242 if ((*pvt
->dbh
->seq
)(pvt
->dbh
, &key
, &data
, R_CURSOR
)
246 return (sv_db_rec(&pvt
->sv
, &key
, &data
));
249 while ((p
= sv_next(this))) {
250 if (p
->s_port
!= port
)
252 if (proto
== NULL
|| strcmp(p
->s_proto
, proto
) == 0)
259 sv_rewind(struct irs_sv
*this) {
260 struct pvt
*pvt
= (struct pvt
*)this->private;
263 if (fseek(pvt
->sv
.fp
, 0L, SEEK_SET
) == 0)
265 (void)fclose(pvt
->sv
.fp
);
270 if (pvt
->dbh
!= NULL
)
272 pvt
->dbh
= dbopen(_PATH_SERVICES_DB
, O_RDONLY
,O_RDONLY
,DB_BTREE
, NULL
);
273 if (pvt
->dbh
!= NULL
) {
274 if (fcntl((*pvt
->dbh
->fd
)(pvt
->dbh
), F_SETFD
, 1) < 0) {
275 (*pvt
->dbh
->close
)(pvt
->dbh
);
281 if ((pvt
->sv
.fp
= fopen(_PATH_SERVICES
, "r")) == NULL
)
283 if (fcntl(fileno(pvt
->sv
.fp
), F_SETFD
, 1) < 0) {
284 (void)fclose(pvt
->sv
.fp
);
289 static struct servent
*
290 sv_next(struct irs_sv
*this) {
291 struct pvt
*pvt
= (struct pvt
*)this->private;
294 if (pvt
->dbh
== NULL
&& pvt
->sv
.fp
== NULL
)
296 if (pvt
->sv
.fp
== NULL
)
301 if (pvt
->dbh
!= NULL
) {
304 while ((*pvt
->dbh
->seq
)(pvt
->dbh
, &key
, &data
, pvt
->dbf
) == 0){
306 if (((char *)key
.data
)[0])
308 return (sv_db_rec(&pvt
->sv
, &key
, &data
));
313 if (pvt
->sv
.fp
== NULL
)
315 return (irs_lclsv_fnxt(&pvt
->sv
));
319 sv_minimize(struct irs_sv
*this) {
320 struct pvt
*pvt
= (struct pvt
*)this->private;
323 if (pvt
->dbh
!= NULL
) {
324 (*pvt
->dbh
->close
)(pvt
->dbh
);
328 if (pvt
->sv
.fp
!= NULL
) {
329 (void)fclose(pvt
->sv
.fp
);
337 irs_lclsv_fnxt(struct lcl_sv
*sv
) {
341 if ((p
= fgets(sv
->line
, BUFSIZ
, sv
->fp
)) == NULL
)
346 while (*p
&& *p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '#')
348 if (*p
== '\0' || *p
== '#' || *p
== '\n')
351 while (*p
== ' ' || *p
== '\t')
353 if (*p
== '\0' || *p
== '#' || *p
== '\n')
355 sv
->serv
.s_port
= htons((u_short
)strtol(p
, &cp
, 10));
356 if (cp
== p
|| (*cp
!= '/' && *cp
!= ','))
359 sv
->serv
.s_proto
= p
;
361 q
= sv
->serv
.s_aliases
= sv
->serv_aliases
;
363 while (*p
&& *p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '#')
366 while (*p
== ' ' || *p
== '\t') {
368 while (*p
== ' ' || *p
== '\t')
370 if (*p
== '\0' || *p
== '#' || *p
== '\n')
372 if (q
< &sv
->serv_aliases
[IRS_SV_MAXALIASES
- 1])
374 while (*p
&& *p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '#')
386 static struct servent
*
387 sv_db_rec(struct lcl_sv
*sv
, DBT
*key
, DBT
*data
) {
392 p
[data
->size
- 1] = '\0'; /*%< should be, but we depend on it */
393 if (((char *)key
->data
)[0] == '\0') {
394 if (key
->size
< sizeof(u_short
)*2 || data
->size
< 2)
396 sv
->serv
.s_port
= ((u_short
*)key
->data
)[1];
398 if ((size_t)n
> sizeof(sv
->line
)) {
399 n
= sizeof(sv
->line
);
401 memcpy(sv
->line
, p
, n
);
402 sv
->serv
.s_name
= sv
->line
;
403 if ((sv
->serv
.s_proto
= strchr(sv
->line
, '/')) != NULL
)
404 *(sv
->serv
.s_proto
)++ = '\0';
408 if (data
->size
< sizeof(u_short
) + 1)
410 if (key
->size
> sizeof(sv
->line
))
411 key
->size
= sizeof(sv
->line
);
412 ((char *)key
->data
)[key
->size
- 1] = '\0';
413 memcpy(sv
->line
, key
->data
, key
->size
);
414 sv
->serv
.s_name
= sv
->line
;
415 if ((sv
->serv
.s_proto
= strchr(sv
->line
, '/')) != NULL
)
416 *(sv
->serv
.s_proto
)++ = '\0';
417 sv
->serv
.s_port
= *(u_short
*)data
->data
;
418 p
+= sizeof(u_short
);
419 data
->size
-= sizeof(u_short
);
421 q
= sv
->serv
.s_aliases
= sv
->serv_aliases
;
422 while (data
->size
> 0 && q
< &sv
->serv_aliases
[IRS_SV_MAXALIASES
- 1]) {