]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind/lib/irs/lcl_sv.c
This commit was generated by cvs2svn to compensate for changes in r57416,
[FreeBSD/FreeBSD.git] / contrib / bind / lib / irs / lcl_sv.c
1 /*
2  * Copyright (c) 1989, 1993, 1995
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
20  *
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
31  * SUCH DAMAGE.
32  */
33
34 /*
35  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
36  *
37  * Permission to use, copy, modify, and distribute this software for any
38  * purpose with or without fee is hereby granted, provided that the above
39  * copyright notice and this permission notice appear in all copies.
40  *
41  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
42  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
43  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
44  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
45  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
46  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
47  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
48  * SOFTWARE.
49  */
50
51 #if defined(LIBC_SCCS) && !defined(lint)
52 static const char rcsid[] = "$Id: lcl_sv.c,v 1.20 1999/10/07 20:44:03 vixie Exp $";
53 #endif /* LIBC_SCCS and not lint */
54
55 /* extern */
56
57 #include "port_before.h"
58
59 #include <sys/types.h>
60 #include <sys/socket.h>
61 #include <netinet/in.h>
62 #include <arpa/nameser.h>
63 #include <resolv.h>
64
65 #ifdef IRS_LCL_SV_DB
66 #include <db.h>
67 #endif
68 #include <errno.h>
69 #include <fcntl.h>
70 #include <limits.h>
71 #include <stdio.h>
72 #include <string.h>
73 #include <stdlib.h>
74
75 #include <irs.h>
76 #include <isc/memcluster.h>
77
78 #include "port_after.h"
79
80 #include "irs_p.h"
81 #include "lcl_p.h"
82
83 #ifdef SPRINTF_CHAR
84 # define SPRINTF(x) strlen(sprintf/**/x)
85 #else
86 # define SPRINTF(x) ((size_t)sprintf x)
87 #endif
88
89 /* Types */
90
91 struct pvt {
92 #ifdef IRS_LCL_SV_DB
93         DB *            dbh;
94         int             dbf;
95 #endif
96         struct lcl_sv   sv;
97 };
98
99 /* Forward */
100
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 *,
104                                           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 *);
109 #ifdef IRS_LCL_SV_DB
110 static struct servent *         sv_db_rec(struct lcl_sv *, DBT *, DBT *);
111 #endif
112
113 /* Portability */
114
115 #ifndef SEEK_SET
116 # define SEEK_SET 0
117 #endif
118
119 /* Public */
120
121 struct irs_sv *
122 irs_lcl_sv(struct irs_acc *this) {
123         struct irs_sv *sv;
124         struct pvt *pvt;
125         
126         if ((sv = memget(sizeof *sv)) == NULL) {
127                 errno = ENOMEM;
128                 return (NULL);
129         }
130         memset(sv, 0x5e, sizeof *sv);
131         if ((pvt = memget(sizeof *pvt)) == NULL) {
132                 memput(sv, sizeof *sv);
133                 errno = ENOMEM;
134                 return (NULL);
135         }
136         memset(pvt, 0, sizeof *pvt);
137         sv->private = pvt;
138         sv->close = sv_close;
139         sv->next = sv_next;
140         sv->byname = sv_byname;
141         sv->byport = sv_byport;
142         sv->rewind = sv_rewind;
143         sv->minimize = sv_minimize;
144         sv->res_get = NULL;
145         sv->res_set = NULL;
146 #ifdef IRS_LCL_SV_DB
147         pvt->dbf = R_FIRST;
148 #endif
149         return (sv);
150 }
151
152 /* Methods */
153
154 static void
155 sv_close(struct irs_sv *this) {
156         struct pvt *pvt = (struct pvt *)this->private;
157         
158 #ifdef IRS_LCL_SV_DB
159         if (pvt->dbh != NULL)
160                 (*pvt->dbh->close)(pvt->dbh);
161 #endif
162         if (pvt->sv.fp)
163                 fclose(pvt->sv.fp);
164         memput(pvt, sizeof *pvt);
165         memput(this, sizeof *this);
166 }
167
168 static struct servent *
169 sv_byname(struct irs_sv *this, const char *name, const char *proto) {
170 #ifdef IRS_LCL_SV_DB
171         struct pvt *pvt = (struct pvt *)this->private;
172 #endif
173         struct servent *p;
174         char **cp;
175
176         sv_rewind(this);
177 #ifdef IRS_LCL_SV_DB
178         if (pvt->dbh != NULL) {
179                 DBT key, data;
180
181                 /* Note that (sizeof "/") == 2. */
182                 if ((strlen(name) + sizeof "/" + proto ? strlen(proto) : 0)
183                     > sizeof pvt->sv.line)
184                         goto try_local;
185                 key.data = pvt->sv.line;
186                 key.size = SPRINTF((pvt->sv.line, "%s/%s", name,
187                                     proto ? proto : "")) + 1;
188                 if (proto != NULL) {
189                         if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0)
190                                 return (NULL);
191                 } else if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR)
192                            != 0)
193                         return (NULL);
194                 return (sv_db_rec(&pvt->sv, &key, &data));
195         }
196  try_local:
197 #endif
198
199         while ((p = sv_next(this))) {
200                 if (strcmp(name, p->s_name) == 0)
201                         goto gotname;
202                 for (cp = p->s_aliases; *cp; cp++)
203                         if (strcmp(name, *cp) == 0)
204                                 goto gotname;
205                 continue;
206  gotname:
207                 if (proto == NULL || strcmp(p->s_proto, proto) == 0)
208                         break;
209         }
210         return (p);
211 }
212
213 static struct servent *
214 sv_byport(struct irs_sv *this, int port, const char *proto) {
215 #ifdef IRS_LCL_SV_DB
216         struct pvt *pvt = (struct pvt *)this->private;
217 #endif
218         struct servent *p;
219
220         sv_rewind(this);
221 #ifdef IRS_LCL_SV_DB
222         if (pvt->dbh != NULL) {
223                 DBT key, data;
224                 u_short *ports;
225
226                 ports = (u_short *)pvt->sv.line;
227                 ports[0] = 0;
228                 ports[1] = port;
229                 key.data = ports;
230                 key.size = sizeof(u_short) * 2;
231                 if (proto && *proto) {
232                         strncpy((char *)ports + key.size, proto,
233                                 BUFSIZ - key.size);
234                         key.size += strlen((char *)ports + key.size) + 1;
235                         if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0)
236                                 return (NULL);
237                 } else {
238                         if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR)
239                             != 0)
240                                 return (NULL);
241                 }
242                 return (sv_db_rec(&pvt->sv, &key, &data));
243         }
244 #endif
245         while ((p = sv_next(this))) {
246                 if (p->s_port != port)
247                         continue;
248                 if (proto == NULL || strcmp(p->s_proto, proto) == 0)
249                         break;
250         }
251         return (p);
252 }
253
254 static void
255 sv_rewind(struct irs_sv *this) {
256         struct pvt *pvt = (struct pvt *)this->private;
257
258         if (pvt->sv.fp) {
259                 if (fseek(pvt->sv.fp, 0L, SEEK_SET) == 0)
260                         return;
261                 (void)fclose(pvt->sv.fp);
262                 pvt->sv.fp = NULL;
263         }
264 #ifdef IRS_LCL_SV_DB
265         pvt->dbf = R_FIRST;
266         if (pvt->dbh != NULL)
267                 return;
268         pvt->dbh = dbopen(_PATH_SERVICES_DB, O_RDONLY,O_RDONLY,DB_BTREE, NULL);
269         if (pvt->dbh != NULL) {
270                 if (fcntl((*pvt->dbh->fd)(pvt->dbh), F_SETFD, 1) < 0) {
271                         (*pvt->dbh->close)(pvt->dbh);
272                         pvt->dbh = NULL;
273                 }
274                 return;
275         }
276 #endif
277         if ((pvt->sv.fp = fopen(_PATH_SERVICES, "r")) == NULL)
278                 return;
279         if (fcntl(fileno(pvt->sv.fp), F_SETFD, 1) < 0) {
280                 (void)fclose(pvt->sv.fp);
281                 pvt->sv.fp = NULL;
282         }
283 }
284
285 static struct servent *
286 sv_next(struct irs_sv *this) {
287         struct pvt *pvt = (struct pvt *)this->private;
288
289 #ifdef IRS_LCL_SV_DB
290         if (pvt->dbh != NULL)
291                 NULL;
292         else
293 #endif
294              if (pvt->sv.fp != NULL)
295                 NULL;
296         else
297                 sv_rewind(this);
298
299 #ifdef IRS_LCL_SV_DB
300         if (pvt->dbh != NULL) {
301                 DBT key, data;
302
303                 while ((*pvt->dbh->seq)(pvt->dbh, &key, &data, pvt->dbf) == 0){
304                         pvt->dbf = R_NEXT;
305                         if (((char *)key.data)[0])
306                                 continue;
307                         return (sv_db_rec(&pvt->sv, &key, &data));
308                 }
309         }
310 #endif
311
312         if (pvt->sv.fp == NULL)
313                 return (NULL);
314         return (irs_lclsv_fnxt(&pvt->sv));
315 }
316
317 static void
318 sv_minimize(struct irs_sv *this) {
319         struct pvt *pvt = (struct pvt *)this->private;
320
321 #ifdef IRS_LCL_SV_DB
322         if (pvt->dbh != NULL) {
323                 (*pvt->dbh->close)(pvt->dbh);
324                 pvt->dbh = NULL;
325         }
326 #endif
327         if (pvt->sv.fp != NULL) {
328                 (void)fclose(pvt->sv.fp);
329                 pvt->sv.fp = NULL;
330         }
331 }
332
333 /* Quasipublic. */
334
335 struct servent *
336 irs_lclsv_fnxt(struct lcl_sv *sv) {
337         char *p, *cp, **q;
338
339  again:
340         if ((p = fgets(sv->line, BUFSIZ, sv->fp)) == NULL)
341                 return (NULL);
342         if (*p == '#')
343                 goto again;
344         sv->serv.s_name = p;
345         while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
346                 ++p;
347         if (*p == '\0' || *p == '#' || *p == '\n')
348                 goto again;
349         *p++ = '\0';
350         while (*p == ' ' || *p == '\t')
351                 p++;
352         if (*p == '\0' || *p == '#' || *p == '\n')
353                 goto again;
354         sv->serv.s_port = htons((u_short)strtol(p, &cp, 10));
355         if (cp == p || (*cp != '/' && *cp != ','))
356                 goto again;
357         p = cp + 1;
358         sv->serv.s_proto = p;
359
360         q = sv->serv.s_aliases = sv->serv_aliases;
361
362         while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
363                 ++p;
364
365         while (*p == ' ' || *p == '\t') {
366                 *p++ = '\0';
367                 while (*p == ' ' || *p == '\t')
368                         ++p;
369                 if (*p == '\0' || *p == '#' || *p == '\n')
370                         break;
371                 if (q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1])
372                         *q++ = p;
373                 while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
374                         ++p;
375         }
376                 
377         *p = '\0';
378         *q = NULL;
379         return (&sv->serv);
380 }
381
382 /* Private. */
383
384 #ifdef IRS_LCL_SV_DB
385 static struct servent *
386 sv_db_rec(struct lcl_sv *sv, DBT *key, DBT *data) {
387         char *p, **q;
388         int n;
389
390         p = data->data;
391         p[data->size - 1] = '\0';       /* should be, but we depend on it */
392
393         if (((char *)key->data)[0] == '\0') {
394                 if (key->size < sizeof(u_short)*2 || data->size < 2)
395                         return (NULL);
396                 sv->serv.s_port = ((u_short *)key->data)[1];
397                 n = strlen(p) + 1;
398                 if (n > sizeof(sv->line)) {
399                         n = sizeof(sv->line);
400                 }
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';
405                 p += n;
406                 data->size -= n;
407         } else {
408                 if (data->size < sizeof(u_short) + 1)
409                         return (NULL);
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);
420         }
421         q = sv->serv.s_aliases = sv->serv_aliases;
422         while (data->size > 0 && q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) {
423
424                 *q++ = p;
425                 n = strlen(p) + 1;
426                 data->size -= n;
427                 p += n;
428         }
429         *q = NULL;
430         return (&sv->serv);
431 }
432 #endif