2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1996-1999 by Internet Software Consortium.
11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 * this is the top level dispatcher
28 * The dispatcher is implemented as an accessor class; it is an
29 * accessor class that calls other accessor classes, as controlled by a
32 * A big difference between this accessor class and others is that the
33 * map class initializers are NULL, and the map classes are already
34 * filled in with method functions that will do the right thing.
39 #include "port_before.h"
41 #include <isc/assertions.h>
48 #include <sys/types.h>
49 #include <netinet/in.h>
50 #include <arpa/nameser.h>
53 #include <isc/memcluster.h>
56 #include "port_after.h"
61 #ifdef SUNW_HOSTS_FALLBACK
62 extern int __res_no_hosts_fallback(void);
63 #endif /* SUNW_HOSTS_FALLBACK */
72 static const struct nameval acc_names
[irs_nacc
+1] = {
80 typedef struct irs_acc
*(*accinit
) __P((const char *options
));
82 static const accinit accs
[irs_nacc
+1] = {
94 static const struct nameval map_names
[irs_nmap
+1] = {
97 { "services", irs_sv
},
98 { "protocols", irs_pr
},
100 { "networks", irs_nw
},
101 { "netgroup", irs_ng
},
105 static const struct nameval option_names
[] = {
106 { "merge", IRS_MERGE
},
107 { "continue", IRS_CONTINUE
},
113 static void gen_close(struct irs_acc
*);
114 static struct __res_state
* gen_res_get(struct irs_acc
*);
115 static void gen_res_set(struct irs_acc
*, struct __res_state
*,
117 static int find_name(const char *, const struct nameval nv
[]);
118 static void init_map_rules(struct gen_p
*, const char *conf_file
);
119 static struct irs_rule
*release_rule(struct irs_rule
*);
120 static int add_rule(struct gen_p
*,
121 enum irs_map_id
, enum irs_acc_id
,
127 irs_gen_acc(const char *options
, const char *conf_file
) {
131 if (!(acc
= memget(sizeof *acc
))) {
135 memset(acc
, 0x5e, sizeof *acc
);
136 if (!(irs
= memget(sizeof *irs
))) {
138 memput(acc
, sizeof *acc
);
141 memset(irs
, 0x5e, sizeof *irs
);
142 irs
->options
= strdup(options
);
144 irs
->free_res
= NULL
;
145 memset(irs
->accessors
, 0, sizeof irs
->accessors
);
146 memset(irs
->map_rules
, 0, sizeof irs
->map_rules
);
147 init_map_rules(irs
, conf_file
);
150 acc
->gr_map
= irs_gen_gr
;
155 acc
->pw_map
= irs_gen_pw
;
159 acc
->sv_map
= irs_gen_sv
;
160 acc
->pr_map
= irs_gen_pr
;
161 acc
->ho_map
= irs_gen_ho
;
162 acc
->nw_map
= irs_gen_nw
;
163 acc
->ng_map
= irs_gen_ng
;
164 acc
->res_get
= gen_res_get
;
165 acc
->res_set
= gen_res_set
;
166 acc
->close
= gen_close
;
172 static struct __res_state
*
173 gen_res_get(struct irs_acc
*this) {
174 struct gen_p
*irs
= (struct gen_p
*)this->private;
176 if (irs
->res
== NULL
) {
177 struct __res_state
*res
;
178 res
= (struct __res_state
*)malloc(sizeof *res
);
181 memset(res
, 0, sizeof *res
);
182 gen_res_set(this, res
, free
);
185 if (((irs
->res
->options
& RES_INIT
) == 0U) && res_ninit(irs
->res
) < 0)
192 gen_res_set(struct irs_acc
*this, struct __res_state
*res
,
193 void (*free_res
)(void *)) {
194 struct gen_p
*irs
= (struct gen_p
*)this->private;
196 struct irs_rule
*rule
;
201 if (irs
->res
&& irs
->free_res
) {
202 res_nclose(irs
->res
);
203 (*irs
->free_res
)(irs
->res
);
207 irs
->free_res
= free_res
;
210 for (rule
= irs
->map_rules
[irs_ho
]; rule
; rule
= rule
->next
) {
213 (*ho
->res_set
)(ho
, res
, NULL
);
215 for (rule
= irs
->map_rules
[irs_nw
]; rule
; rule
= rule
->next
) {
218 (*nw
->res_set
)(nw
, res
, NULL
);
224 gen_close(struct irs_acc
*this) {
225 struct gen_p
*irs
= (struct gen_p
*)this->private;
229 for (n
= 0; n
< irs_nmap
; n
++)
230 while (irs
->map_rules
[n
] != NULL
)
231 irs
->map_rules
[n
] = release_rule(irs
->map_rules
[n
]);
233 /* Access methods. */
234 for (n
= 0; n
< irs_nacc
; n
++) {
236 if (irs
->accessors
[n
].gr
!= NULL
)
237 (*irs
->accessors
[n
].gr
->close
)(irs
->accessors
[n
].gr
);
238 if (irs
->accessors
[n
].pw
!= NULL
)
239 (*irs
->accessors
[n
].pw
->close
)(irs
->accessors
[n
].pw
);
240 if (irs
->accessors
[n
].sv
!= NULL
)
241 (*irs
->accessors
[n
].sv
->close
)(irs
->accessors
[n
].sv
);
242 if (irs
->accessors
[n
].pr
!= NULL
)
243 (*irs
->accessors
[n
].pr
->close
)(irs
->accessors
[n
].pr
);
244 if (irs
->accessors
[n
].ho
!= NULL
)
245 (*irs
->accessors
[n
].ho
->close
)(irs
->accessors
[n
].ho
);
246 if (irs
->accessors
[n
].nw
!= NULL
)
247 (*irs
->accessors
[n
].nw
->close
)(irs
->accessors
[n
].nw
);
248 if (irs
->accessors
[n
].ng
!= NULL
)
249 (*irs
->accessors
[n
].ng
->close
)(irs
->accessors
[n
].ng
);
250 /* Enclosing accessor. */
251 if (irs
->accessors
[n
].acc
!= NULL
)
252 (*irs
->accessors
[n
].acc
->close
)(irs
->accessors
[n
].acc
);
255 /* The options string was strdup'd. */
256 free((void*)irs
->options
);
258 if (irs
->res
&& irs
->free_res
)
259 (*irs
->free_res
)(irs
->res
);
261 /* The private data container. */
262 memput(irs
, sizeof *irs
);
265 memput(this, sizeof *this);
271 find_name(const char *name
, const struct nameval names
[]) {
274 for (n
= 0; names
[n
].name
!= NULL
; n
++)
275 if (strcmp(name
, names
[n
].name
) == 0)
276 return (names
[n
].val
);
280 static struct irs_rule
*
281 release_rule(struct irs_rule
*rule
) {
282 struct irs_rule
*next
= rule
->next
;
284 memput(rule
, sizeof *rule
);
289 add_rule(struct gen_p
*irs
,
290 enum irs_map_id map
, enum irs_acc_id acc
,
293 struct irs_rule
**rules
, *last
, *tmp
, *new;
294 struct irs_inst
*inst
;
310 new = memget(sizeof *new);
313 memset(new, 0x5e, sizeof *new);
316 new->inst
= &irs
->accessors
[acc
];
321 char option
[50], *next
;
323 next
= strchr(cp
, ',');
328 if ((size_t)n
> sizeof option
- 1)
329 n
= sizeof option
- 1;
330 strncpy(option
, cp
, n
);
333 n
= find_name(option
, option_names
);
340 rules
= &irs
->map_rules
[map
];
341 for (last
= NULL
, tmp
= *rules
;
343 last
= tmp
, tmp
= tmp
->next
)
350 /* Try to instantiate map accessors for this if necessary & approp. */
351 inst
= &irs
->accessors
[acc
];
352 if (inst
->acc
== NULL
&& accs
[acc
] != NULL
)
353 inst
->acc
= (*accs
[acc
])(irs
->options
);
354 if (inst
->acc
!= NULL
) {
355 if (inst
->gr
== NULL
&& inst
->acc
->gr_map
!= NULL
)
356 inst
->gr
= (*inst
->acc
->gr_map
)(inst
->acc
);
357 if (inst
->pw
== NULL
&& inst
->acc
->pw_map
!= NULL
)
358 inst
->pw
= (*inst
->acc
->pw_map
)(inst
->acc
);
359 if (inst
->sv
== NULL
&& inst
->acc
->sv_map
!= NULL
)
360 inst
->sv
= (*inst
->acc
->sv_map
)(inst
->acc
);
361 if (inst
->pr
== NULL
&& inst
->acc
->pr_map
!= NULL
)
362 inst
->pr
= (*inst
->acc
->pr_map
)(inst
->acc
);
363 if (inst
->ho
== NULL
&& inst
->acc
->ho_map
!= NULL
)
364 inst
->ho
= (*inst
->acc
->ho_map
)(inst
->acc
);
365 if (inst
->nw
== NULL
&& inst
->acc
->nw_map
!= NULL
)
366 inst
->nw
= (*inst
->acc
->nw_map
)(inst
->acc
);
367 if (inst
->ng
== NULL
&& inst
->acc
->ng_map
!= NULL
)
368 inst
->ng
= (*inst
->acc
->ng_map
)(inst
->acc
);
375 default_map_rules(struct gen_p
*irs
) {
376 /* Install time honoured and proved BSD style rules as default. */
377 add_rule(irs
, irs_gr
, irs_lcl
, "");
378 add_rule(irs
, irs_pw
, irs_lcl
, "");
379 add_rule(irs
, irs_sv
, irs_lcl
, "");
380 add_rule(irs
, irs_pr
, irs_lcl
, "");
381 #ifdef SUNW_HOSTS_FALLBACK
382 if (__res_no_hosts_fallback())
383 add_rule(irs
, irs_ho
, irs_dns
, "");
385 add_rule(irs
, irs_ho
, irs_dns
, "continue");
386 add_rule(irs
, irs_ho
, irs_lcl
, "");
388 #else /* SUNW_HOSTS_FALLBACK */
389 add_rule(irs
, irs_ho
, irs_dns
, "continue");
390 add_rule(irs
, irs_ho
, irs_lcl
, "");
391 #endif /* SUNW_HOSTS_FALLBACK */
392 add_rule(irs
, irs_nw
, irs_dns
, "continue");
393 add_rule(irs
, irs_nw
, irs_lcl
, "");
394 add_rule(irs
, irs_ng
, irs_lcl
, "");
398 init_map_rules(struct gen_p
*irs
, const char *conf_file
) {
399 char line
[1024], pattern
[40], mapname
[20], accname
[20], options
[100];
402 #ifdef SUNW_HOSTS_FALLBACK
403 if (__res_no_hosts_fallback()) {
404 default_map_rules(irs
);
407 #endif /* SUNW_HOSTS_FALLBACK */
409 if (conf_file
== NULL
)
410 conf_file
= _PATH_IRS_CONF
;
412 /* A conf file of "" means compiled in defaults. Irpd wants this */
413 if (conf_file
[0] == '\0' || (conf
= fopen(conf_file
, "r")) == NULL
) {
414 default_map_rules(irs
);
417 (void) sprintf(pattern
, "%%%lus %%%lus %%%lus\n",
418 (unsigned long)sizeof mapname
,
419 (unsigned long)sizeof accname
,
420 (unsigned long)sizeof options
);
421 while (fgets(line
, sizeof line
, conf
)) {
428 isascii((unsigned char)*tmp
) &&
429 isspace((unsigned char)*tmp
);
432 if (*tmp
== '#' || *tmp
== '\n' || *tmp
== '\0')
434 n
= sscanf(tmp
, pattern
, mapname
, accname
, options
);
440 n
= find_name(mapname
, map_names
);
441 INSIST(n
< irs_nmap
);
444 map
= (enum irs_map_id
) n
;
446 n
= find_name(accname
, acc_names
);
447 INSIST(n
< irs_nacc
);
450 acc
= (enum irs_acc_id
) n
;
452 add_rule(irs
, map
, acc
, options
);