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 #include "port_before.h"
53 #include <sys/types.h>
54 #include <sys/socket.h>
55 #include <netinet/in.h>
56 #include <arpa/nameser.h>
70 #include <isc/memcluster.h>
72 #include "port_after.h"
78 # define SPRINTF(x) strlen(sprintf/**/x)
80 # define SPRINTF(x) ((size_t)sprintf x)
95 static void sv_close(struct irs_sv
*);
96 static struct servent
* sv_next(struct irs_sv
*);
97 static struct servent
* sv_byname(struct irs_sv
*, const char *,
99 static struct servent
* sv_byport(struct irs_sv
*, int, const char *);
100 static void sv_rewind(struct irs_sv
*);
101 static void sv_minimize(struct irs_sv
*);
102 /*global*/ struct servent
* irs_lclsv_fnxt(struct lcl_sv
*);
104 static struct servent
* sv_db_rec(struct lcl_sv
*, DBT
*, DBT
*);
116 irs_lcl_sv(struct irs_acc
*this) {
122 if ((sv
= memget(sizeof *sv
)) == NULL
) {
126 memset(sv
, 0x5e, sizeof *sv
);
127 if ((pvt
= memget(sizeof *pvt
)) == NULL
) {
128 memput(sv
, sizeof *sv
);
132 memset(pvt
, 0, sizeof *pvt
);
134 sv
->close
= sv_close
;
136 sv
->byname
= sv_byname
;
137 sv
->byport
= sv_byport
;
138 sv
->rewind
= sv_rewind
;
139 sv
->minimize
= sv_minimize
;
151 sv_close(struct irs_sv
*this) {
152 struct pvt
*pvt
= (struct pvt
*)this->private;
155 if (pvt
->dbh
!= NULL
)
156 (*pvt
->dbh
->close
)(pvt
->dbh
);
160 memput(pvt
, sizeof *pvt
);
161 memput(this, sizeof *this);
164 static struct servent
*
165 sv_byname(struct irs_sv
*this, const char *name
, const char *proto
) {
167 struct pvt
*pvt
= (struct pvt
*)this->private;
174 if (pvt
->dbh
!= NULL
) {
177 /* Note that (sizeof "/") == 2. */
178 if ((strlen(name
) + sizeof "/" + proto
? strlen(proto
) : 0)
179 > sizeof pvt
->sv
.line
)
181 key
.data
= pvt
->sv
.line
;
182 key
.size
= SPRINTF((pvt
->sv
.line
, "%s/%s", name
,
183 proto
? proto
: "")) + 1;
185 if ((*pvt
->dbh
->get
)(pvt
->dbh
, &key
, &data
, 0) != 0)
187 } else if ((*pvt
->dbh
->seq
)(pvt
->dbh
, &key
, &data
, R_CURSOR
)
190 return (sv_db_rec(&pvt
->sv
, &key
, &data
));
195 while ((p
= sv_next(this))) {
196 if (strcmp(name
, p
->s_name
) == 0)
198 for (cp
= p
->s_aliases
; *cp
; cp
++)
199 if (strcmp(name
, *cp
) == 0)
203 if (proto
== NULL
|| strcmp(p
->s_proto
, proto
) == 0)
209 static struct servent
*
210 sv_byport(struct irs_sv
*this, int port
, const char *proto
) {
212 struct pvt
*pvt
= (struct pvt
*)this->private;
218 if (pvt
->dbh
!= NULL
) {
222 ports
= (u_short
*)pvt
->sv
.line
;
226 key
.size
= sizeof(u_short
) * 2;
227 if (proto
&& *proto
) {
228 strncpy((char *)ports
+ key
.size
, proto
,
230 key
.size
+= strlen((char *)ports
+ key
.size
) + 1;
231 if ((*pvt
->dbh
->get
)(pvt
->dbh
, &key
, &data
, 0) != 0)
234 if ((*pvt
->dbh
->seq
)(pvt
->dbh
, &key
, &data
, R_CURSOR
)
238 return (sv_db_rec(&pvt
->sv
, &key
, &data
));
241 while ((p
= sv_next(this))) {
242 if (p
->s_port
!= port
)
244 if (proto
== NULL
|| strcmp(p
->s_proto
, proto
) == 0)
251 sv_rewind(struct irs_sv
*this) {
252 struct pvt
*pvt
= (struct pvt
*)this->private;
255 if (fseek(pvt
->sv
.fp
, 0L, SEEK_SET
) == 0)
257 (void)fclose(pvt
->sv
.fp
);
262 if (pvt
->dbh
!= NULL
)
264 pvt
->dbh
= dbopen(_PATH_SERVICES_DB
, O_RDONLY
,O_RDONLY
,DB_BTREE
, NULL
);
265 if (pvt
->dbh
!= NULL
) {
266 if (fcntl((*pvt
->dbh
->fd
)(pvt
->dbh
), F_SETFD
, 1) < 0) {
267 (*pvt
->dbh
->close
)(pvt
->dbh
);
273 if ((pvt
->sv
.fp
= fopen(_PATH_SERVICES
, "r")) == NULL
)
275 if (fcntl(fileno(pvt
->sv
.fp
), F_SETFD
, 1) < 0) {
276 (void)fclose(pvt
->sv
.fp
);
281 static struct servent
*
282 sv_next(struct irs_sv
*this) {
283 struct pvt
*pvt
= (struct pvt
*)this->private;
286 if (pvt
->dbh
== NULL
&& pvt
->sv
.fp
== NULL
)
288 if (pvt
->sv
.fp
== NULL
)
293 if (pvt
->dbh
!= NULL
) {
296 while ((*pvt
->dbh
->seq
)(pvt
->dbh
, &key
, &data
, pvt
->dbf
) == 0){
298 if (((char *)key
.data
)[0])
300 return (sv_db_rec(&pvt
->sv
, &key
, &data
));
305 if (pvt
->sv
.fp
== NULL
)
307 return (irs_lclsv_fnxt(&pvt
->sv
));
311 sv_minimize(struct irs_sv
*this) {
312 struct pvt
*pvt
= (struct pvt
*)this->private;
315 if (pvt
->dbh
!= NULL
) {
316 (*pvt
->dbh
->close
)(pvt
->dbh
);
320 if (pvt
->sv
.fp
!= NULL
) {
321 (void)fclose(pvt
->sv
.fp
);
329 irs_lclsv_fnxt(struct lcl_sv
*sv
) {
333 if ((p
= fgets(sv
->line
, BUFSIZ
, sv
->fp
)) == NULL
)
338 while (*p
&& *p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '#')
340 if (*p
== '\0' || *p
== '#' || *p
== '\n')
343 while (*p
== ' ' || *p
== '\t')
345 if (*p
== '\0' || *p
== '#' || *p
== '\n')
347 sv
->serv
.s_port
= htons((u_short
)strtol(p
, &cp
, 10));
348 if (cp
== p
|| (*cp
!= '/' && *cp
!= ','))
351 sv
->serv
.s_proto
= p
;
353 q
= sv
->serv
.s_aliases
= sv
->serv_aliases
;
355 while (*p
&& *p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '#')
358 while (*p
== ' ' || *p
== '\t') {
360 while (*p
== ' ' || *p
== '\t')
362 if (*p
== '\0' || *p
== '#' || *p
== '\n')
364 if (q
< &sv
->serv_aliases
[IRS_SV_MAXALIASES
- 1])
366 while (*p
&& *p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '#')
378 static struct servent
*
379 sv_db_rec(struct lcl_sv
*sv
, DBT
*key
, DBT
*data
) {
384 p
[data
->size
- 1] = '\0'; /*%< should be, but we depend on it */
385 if (((char *)key
->data
)[0] == '\0') {
386 if (key
->size
< sizeof(u_short
)*2 || data
->size
< 2)
388 sv
->serv
.s_port
= ((u_short
*)key
->data
)[1];
390 if ((size_t)n
> sizeof(sv
->line
)) {
391 n
= sizeof(sv
->line
);
393 memcpy(sv
->line
, p
, n
);
394 sv
->serv
.s_name
= sv
->line
;
395 if ((sv
->serv
.s_proto
= strchr(sv
->line
, '/')) != NULL
)
396 *(sv
->serv
.s_proto
)++ = '\0';
400 if (data
->size
< sizeof(u_short
) + 1)
402 if (key
->size
> sizeof(sv
->line
))
403 key
->size
= sizeof(sv
->line
);
404 ((char *)key
->data
)[key
->size
- 1] = '\0';
405 memcpy(sv
->line
, key
->data
, key
->size
);
406 sv
->serv
.s_name
= sv
->line
;
407 if ((sv
->serv
.s_proto
= strchr(sv
->line
, '/')) != NULL
)
408 *(sv
->serv
.s_proto
)++ = '\0';
409 sv
->serv
.s_port
= *(u_short
*)data
->data
;
410 p
+= sizeof(u_short
);
411 data
->size
-= sizeof(u_short
);
413 q
= sv
->serv
.s_aliases
= sv
->serv_aliases
;
414 while (data
->size
> 0 && q
< &sv
->serv_aliases
[IRS_SV_MAXALIASES
- 1]) {