Gentoo Archives: gentoo-commits

From: "Alin Nastac (mrness)" <mrness@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in net-dns/pdnsd/files: pdnsd.resolvconf-r1
Date: Sun, 20 Apr 2008 05:07:42
Message-Id: E1JnRm8-0000d0-1x@stork.gentoo.org
1 mrness 08/04/20 05:07:40
2
3 Added: pdnsd.resolvconf-r1
4 Log:
5 Make resolvconf script compatible with baselayout-2 (#218031).
6 (Portage version: 2.1.4.4)
7
8 Revision Changes Path
9 1.1 net-dns/pdnsd/files/pdnsd.resolvconf-r1
10
11 file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-dns/pdnsd/files/pdnsd.resolvconf-r1?rev=1.1&view=markup
12 plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-dns/pdnsd/files/pdnsd.resolvconf-r1?rev=1.1&content-type=text/plain
13
14 Index: pdnsd.resolvconf-r1
15 ===================================================================
16 #!/bin/bash
17 # Copyright 2006 Gentoo Foundation
18 # Distributed under the terms of the GNU General Public License v2
19
20 # /etc/pdnsd/pdnsd.conf updater
21 # Written by Oldrich Jedlicka (oldium.pro@××××××.cz)
22
23 # Implementation notes:
24 # * The assumptions are same as for other scripts like bind and dnsmasq:
25 # - We assume that we are a local dns cache - after all, why would a server
26 # use resolvconf?
27 # - Now that we have assumed this, we also assume that generic DHCP clients
28 # will enter their domains and search domains ONLY in the "search" field
29 # in their resolv.confs and VPN clients will put the domain they are for
30 # into the domain field only.
31 # - This allows pdnsd to forward domains for a specific VPN domain to the
32 # VPN nameserver and everything else to the standard name servers.
33 #
34 # HOW-TO CONFIGURE:
35 #
36 # To get this working, you need to do only two steps
37 #
38 # 1. Create a basic configuration of /etc/pdnsd/pdnsd.conf, you can use
39 # /etc/pdnsd/pdnsd.conf.example to start.
40 #
41 # Additional configuration will be created automatically be resolvconf.
42 # The generated server sections has labels starting with "resolvconf", so
43 #
44 # DO NOT USE "resolvconf" IN YOUR LABELS!
45 #
46 # Check if the status_ctl is set to "on", otherwise the configuration
47 # will not be automatically reloaded - see sample config file.
48 #
49 # You are free to edit automatically created server sections, but always
50 # write one option per line. There are few options that are always recreated
51 # and your changes in them will be lost. Here is the list (with example
52 # values):
53 #
54 # preset=on;
55 # ip="192.168.0.1","192.168.0.2";
56 # include=".net",".com";'
57 #
58 # The exclude directive in "resolvconf" server section is partly recreated.
59 # Known (configured) domains in the form ".<domain>" or ".<domain>." are
60 # added and removed automatically, unknown domains (also those not in
61 # the format above) found in this directive are kept.
62 #
63 # The sample configuration file /etc/pdnsd/pdnsd.conf prepared to work
64 # with resolvconf would look like this:
65 #
66 #global {
67 # perm_cache=2048;
68 # run_as="pdnsd";
69 # status_ctl = on; # Important to enable status control
70 # run_ipv4=on;
71 # par_queries=2; # How many servers are probed in parallel
72 # interface = "lo"; # Interface on which the pdnsd listens
73 #}
74 #
75 # 2. The last step is to configure dns configuration for /etc/resolv.conf
76 # for the lo interface. In Gentoo we set it up like so in /etc/conf.d/net
77 #
78 # dns_servers_lo=( "127.0.0.1" )
79
80 # pdnsd config file
81 PDNSDCONFIG="/etc/pdnsd/pdnsd.conf"
82
83 # Backup suffix
84 BACKUPSUFFIX=".backup"
85
86 # Load our variables from resolvconf
87 VARS="$(resolvconf -v)"
88 eval "${VARS}"
89
90 COMMENT='
91 # Automatically generated by resolvconf.
92 #
93 # Following server sections are automatically enabled and disabled.
94 #
95 # !!! WARNING !!!
96 # DO NOT RENAME LABELS!
97 #
98 # No section will be deleted and only some options are automatically changed.
99 # Feel free to add your own options, but do not use pair comments /* */ as they
100 # are not recognised.
101 #
102 # DO NOT USE resolvconf ANYWHERE IN YOUR LABELS!
103 #
104 # Automatically changed options are (with examples):
105 # preset=on;
106 # ip="192.168.0.1","192.168.0.2";
107 # include=".net",".com";
108 # exclude=".domain.net",".domain.com";
109 # policy=excluded;
110 #
111 # The exclude directive is changed automatically only in "resolvconf" server
112 # section. Not handled servers are kept in the directive.
113 #'
114 BASIC_SETTINGS='server {
115 label="resolvconf";
116 preset=off;
117 }'
118
119 INSTALLATION_CHECK='^[[:space:]]*label[[:space:]]*=[[:space:]]*"resolvconf"'
120
121 ###
122 # Sed script configuration
123 #
124 # Composed sequence of lines:
125 #
126 # (1) SED_LOOP with @MATCH_LABELS@ substituted by several SED_MATCH_ONE_LABEL
127 # (2) SED_EDIT_ONE_SERVER several times
128 # (3) SED_ADDING with new servers
129 #
130 # Notes:
131 #
132 # * @LABEL@ is a string "resolvconf-<domain>" or "resolvconf" for global
133 # section
134 # * @RULE@ is @LABEL@ with translated characters '-' and '.' into '_'.
135 ###
136
137 ###
138 # Main loop with label match - it will redirect the processing to
139 # SED_EDIT_ONE_SERVER, when the label match is found. Special match is
140 # for "resolvconf" label - the control flow is redirected to SED_ADDING to
141 # allow adding new sections.
142 #
143 # To summarize: Old sections are edited as they appear in the file and new
144 # sections are added before the "resolvconf" section.
145 SED_LOOP=\
146 '/^[[:space:]]*server[[:space:]]*[\{]/ b server;
147 p; d;
148 :server; h;
149 :server_loop; n;
150 /^[[:space:]]*server[[:space:]]*[\{]/ { x; p; b server_loop; };
151 @MATCH_LABELS@
152 /^[[:space:]]*label[[:space:]]*=[[:space:]]*"resolvconf"/ { H; b adding; };
153 /^[[:space:]]*[\}]/ { H; x; p; d; };
154 H;
155 b server_loop;
156 '
157
158 ###
159 # Match for one label with a jump to SED_EDIT_ONE_SERVER
160 SED_MATCH_ONE_LABEL=\
161 '/^[[:space:]]*label[[:space:]]*=[[:space:]]*"@LABEL@"/ { H; x; b main_@RULE@; };
162 '
163
164 ###
165 # Editing one server. New lines are put into @SETUP@, lines are composed
166 # in function compose_lines(). After the new lines are added, all "preset",
167 # "ip" and "include" options are removed (not printed).
168 #
169 # Sanity checks: Check if there is a second label or another server directive.
170 # In both cases, there is some error in the file, so go to the beginning by
171 # jumping to SED_LOOP's :server.
172 SED_EDIT_ONE_SERVER=\
173 ':main_@RULE@;
174 p; @SETUP@
175 :loop_@RULE@;
176 n;
177 /^[[:space:]]*server[[:space:]]*[\{]/ b server;
178 /^[[:space:]]*label[[:space:]]*=/ b server;
179 /^[[:space:]]*preset[[:space:]]*=/ b loop_@RULE@;
180 /^[[:space:]]*ip[[:space:]]*=/ b loop_@RULE@;
181 /^[[:space:]]*include[[:space:]]*=/ b loop_@RULE@;
182 /^[[:space:]]*policy[[:space:]]*=/ b loop_@RULE@;
183 /^[[:space:]]*exclude[[:space:]]*=/ b exclude_logic_@RULE;
184 p;
185 /^[[:space:]]*[\}]/ d;
186 b loop_@RULE@;
187
188 :exclude_logic_@RULE;
189 @EXCLUDE_LOGIC@
190 b loop_@RULE@;
191 '
192
193 ###
194 # Add new servers. All lines composed by function compose_lines() are put into
195 # @SETUP@. Then the control flow is returned to one special SED_EDIT_ONE_SERVER
196 # section with label "resolvconf".
197 SED_ADDING=\
198 ':adding;
199 @SETUP@
200 x; b main_resolvconf;
201 '
202
203
204 ###
205 # Edit the domain list (include/exclude). All empty fields and matching domains
206 # are removed. Unmaintained domains (not in resolvconf-<domain>) are kept. All
207 # domains should be in a pipe (|) separated list and should begin, but not end
208 # with a dot. The list is put into @DOMAINS@. The control flow continues, where
209 # it ended in SED_EDIT_ONE_SERVER.
210 #
211 SED_DOMAIN_LIST_LOGIC=\
212 'h;
213 s/^([[:space:]]*@DIRECTIVE@[[:space:]]*=[[:space:]]*).*/\\1/;
214 x;
215 s/^[[:space:]]*@DIRECTIVE@[[:space:]]*=[[:space:]]*//;
216
217 :@DIRECTIVE@_loop_@RULE@;
218 /([[:space:]]*("[^"]"*|[^,;]*)[[:space:]]*,)*[[:space:]]*("(@DOMAINS@|)\.?"|(@DOMAINS@)\.?|,)[[:space:]]*[,;]/ {
219 s/(([[:space:]]*("[^"]"*|[^,;]*)[[:space:]]*,)*[[:space:]]*)("(@DOMAINS@|)\.?"|(@DOMAINS@)\.?|,)[[:space:]]*([,;])/\\1\\7/;
220 b @DIRECTIVE@_loop_@RULE@;
221 };
222
223 s/^[,;]//g;
224 /^[[:space:]]*$/ b @DIRECTIVE@_end_@RULE@;
225 H; x; s/\\n//; p;
226 :@DIRECTIVE@_end_@RULE@;
227 '
228
229 ################################################################################
230 # Functions
231
232 ###
233 # char* [] uniqify(char* list[])
234 #
235 # Uniqify the items in the list
236 uniqify() {
237 local result=
238 while [ -n "$1" ] ; do
239 case " ${result} " in
240 *" $1 "*) ;;
241 *) result="${result} $1" ;;
242 esac
243 shift
244 done
245 echo "${result# *}"
246 }
247
248 ###
249 # char *make_pdnsd_label(char *domain)
250 #
251 # Translate domain name into pdnsd's label
252 make_pdnsd_label() {
253 local domain=$1
254 if [[ -n ${domain} ]] ; then
255 echo -n "resolvconf-${domain}"
256 else
257 echo -n "resolvconf"
258 fi
259 }
260
261 ###
262 # char *make_sed_label(char *pdnsd_label)
263 #
264 # Translate pdnsd's label into sed's label
265 make_sed_label() {
266 local label="$1"
267 label="${label//-/_}"
268 label="${label//./_}"
269 echo -n "${label}"
270 }
271
272 # char *compose_lines(...)
273 #
274 # Compose a sed command that prints lines
275 compose_lines() {
276 local line result
277 for line in "$@" ; do
278 result="${result}i\\\\\\n${line// /\\t}\\n"
279 done
280 echo "${result}"
281 }
282
283 ###
284 # char *build_settings(char *nameservers, char *domains, char *directive)
285 #
286 # Builds configuration part @SETUP@ of sed script. The directive parameter denotes
287 # if the domains are to be included ("include") or excluded ("exclude"). This
288 # involves options like
289 #
290 # (1) # [nameserver list is empty]
291 # preset=off;
292 #
293 # (2) # [domain list is empty]
294 # preset=on;
295 # ip="address","address"...;
296 #
297 # (3) # [directive=="include"]
298 # preset=on;
299 # ip="address","address"...;
300 # include=".domain.",".domain."...;
301 # policy=excluded;
302 #
303 # (4) # [directive=="exclude"]
304 # preset=on;
305 # ip="address","address"...;
306 # exclude=".domain.",".domain."...;
307 # policy=included;
308 #
309 # Note: Currently there will always be only one domain in "include" directive.
310 #
311 build_settings() {
312 local ns="$1" domains="$2" directive="$3"
313 if [[ -n ${ns} ]] ; then
314 local x list_ns list_domains
315 for x in ${ns} ; do
316 list_ns="${list_ns},\"${x}\""
317 done
318 list_ns="${list_ns#,}"
319 if [[ -n ${domains} ]] ; then
320 for x in ${domains} ; do
321 list_domains="${list_domains},\".${x}.\""
322 done
323 list_domains="${list_domains#,}"
324 if [[ $directive == "include" ]]; then
325 compose_lines \
326 " preset=on;" \
327 " ip=${list_ns};" \
328 " include=${list_domains};" \
329 " policy=excluded;"
330 else
331 compose_lines \
332 " preset=on;" \
333 " ip=${list_ns};" \
334 " exclude=${list_domains};" \
335 " policy=included;"
336 fi
337 else
338 compose_lines \
339 " preset=on;" \
340 " ip=${list_ns};"
341 fi
342 else
343 compose_lines \
344 " preset=off;"
345 fi
346 }
347
348 ###
349 # char *build_match_labels(char *domains...)
350 #
351 # Build the label match part of the sed script
352 #
353 build_match_labels() {
354 local domain result label destination new_match
355 for domain in "$@" ; do
356 label="$(make_pdnsd_label "${domain}")"
357 rule="$(make_sed_label "${label}")"
358 new_match="${SED_MATCH_ONE_LABEL//@LABEL@/${label}}"
359 new_match="${new_match//@RULE@/${rule}}"
360 result="${result}${new_match}"
361 done
362 echo "${result}"
363 }
364
365 ###
366 # char *build_domain_list_logic(char *domains, char *directive)
367 #
368 # Build a logic for changing (removing) domains from a directive.
369 #
370 build_domain_list_logic() {
371 local domains="$1" directive="$2"
372 local x domain_list logic
373
374 # Domains should be pipe separated list
375 for x in ${domains}; do
376 x=".${x%.}"
377 x="${x//./\.}"
378 domain_list="${domain_list}|${x}"
379 done
380 domain_list="${domain_list#|}"
381
382 if [[ -z ${domain_list} ]]; then
383 logic="p;"
384 else
385 logic="${SED_DOMAIN_LIST_LOGIC//@DOMAINS@/${domain_list}}"
386 logic="${logic//@DIRECTIVE@/${directive}}"
387 fi
388 echo "${logic}"
389 }
390
391 ###
392 # char *build_edit_part(char *domain, char *nameservers, \
393 # char *add_domains, char *remove_domains,
394 # char *directive)
395 #
396 # Build edit part of the sed script for a particular domain. Domain can be
397 # empty in the case it is the "resolvconf" server part.
398 #
399 build_edit_part() {
400 local domain="$1" nameservers="$2" add_domains="$3" remove_domains="$4"
401 local directive="$5"
402 local setup label rule logic result
403
404 setup="$(build_settings "${nameservers}" "${add_domains}" "${directive}")"
405 label="$(make_pdnsd_label "${domain}")"
406 rule="$(make_sed_label "${label}")"
407 logic="$(build_domain_list_logic "${remove_domains}" "${directive}")"
408 result="${SED_EDIT_ONE_SERVER//@SETUP@/${setup}}"
409 result="${result//@EXCLUDE_LOGIC@/${logic}}"
410 result="${result//@RULE@/${rule}}"
411 echo "${result}"
412 }
413
414 ###
415 # char *get_domain_nameservers(char *domain, char *domain_config...)
416 #
417 # Get the list of nameservers belonging to one particular domain.
418 #
419 # Domain configuration is a space separated list of pair <domain>,<ip>.
420 #
421 get_domain_nameservers() {
422 local domain="$1" ns
423 shift
424 for x in "$@" ; do
425 if [[ ${x%,*} == ${domain} ]] ; then
426 ns="${ns} ${x#*,}"
427 fi
428 done
429 ns="$(uniqify ${ns})"
430 echo -n "${ns}"
431 }
432
433 ###
434 # char *build_domain_edit_part(char *domain, char *domain_config...)
435 #
436 # Parse the list of domain configurations and build settings for one particular
437 # domain for the sed script.
438 #
439 # Domain configuration is a space separated list of pair <domain>,<ip>.
440 #
441 build_domain_edit_part() {
442 local domain="$1" ns
443 shift
444 ns="$(get_domain_nameservers "${domain}" "$@")"
445 build_edit_part "${domain}" "${ns}" "${domain}" "" "include"
446 }
447
448 ###
449 # char *build_add_part(char *add, char *domains...)
450 #
451 # Build add part of the sed script for all domains that needs to be added
452 #
453 build_add_part() {
454 local add="$1" x label rule add_part new_part result
455 shift
456 for x in ${add} ; do
457 local domain="${x}" ns
458 ns="$(get_domain_nameservers "${domain}" "$@")"
459 label="$(make_pdnsd_label "${domain}")"
460 rule="$(make_sed_label ${label})"
461 new_part="$(compose_lines "server {" " label=\"${label}\";")"
462 new_part="${new_part}$(build_settings "${ns}" "${domain}" "include")"
463 new_part="${new_part}$(compose_lines "}" "")"
464 add_part="${add_part}${new_part}"
465 done
466 result="${SED_ADDING//@SETUP@/${add_part}}"
467 echo "${result}"
468 }
469
470 ###
471 # char *build_sed_script(char *nameservers, char *domain_config,
472 # char *change, char *add,
473 # char *active_domains, char *known_domains)
474 #
475 # Build the full sed script from the list of nameservers, list of domains
476 # (in format <domain>,<ip>), list of changed domains, list of added domains,
477 # list of activly used domains and a list of all known domains.
478 #
479 build_sed_script() {
480 local ns="$1" domain_config="$2" change="$3" add="$4"
481 local active_domains="$5" known_domains="$6"
482
483 local match_labels="$(build_match_labels ${change})"
484
485 local edit_changed x
486 for x in ${change} ; do
487 edit_changed="${edit_changed}$( \
488 build_domain_edit_part "${x}" ${domain_config})"
489 done
490 edit_changed="${edit_changed}$( \
491 build_edit_part "" "${ns}" "${active_domains}" "${known_domains}" "exclude")"
492
493 local added
494 added="$(build_add_part "${add}" ${domain_config})"
495
496 local full
497 full="${SED_LOOP//@MATCH_LABELS@/${match_labels}}"
498 echo -ne "${full}"
499 echo -ne "${edit_changed}"
500 echo -ne "${added}"
501 }
502
503 ###
504 # char *read_configured_domains(char *config_file)
505 #
506 # Reads labels of servers starting with resolvconf* from the configuration file.
507 #
508 read_configured_domains() {
509 local config_file="$1" result
510 result="\
511 $(sed -nre 's/^[[:space:]]+label=\"?resolvconf-([^;\"]*)\";.*/\1/p' \
512 ${config_file})"
513 echo -n "${result}"
514 }
515
516 ###
517 # void installation_check(char *config_file)
518 #
519 # Check if the pdnsd is installed and can be configured. Prepare also the file
520 # for resolvconf.
521 #
522 installation_check() {
523 local config_file="$1"
524 if [[ -e ${config_file} ]] ; then
525 if ! grep ${INSTALLATION_CHECK} ${config_file} &>/dev/null ; then
526 echo -e "${COMMENT}" >> ${config_file}
527 echo -e "\n${BASIC_SETTINGS}" >> ${config_file}
528 fi
529 return 0
530 else
531 return 1
532 fi
533 }
534
535 ###
536 # void initialization(char *config_file)
537 #
538 # Setup basic variables NAMESERVERS, DOMAINS an CONFIGURED_DOMAINS
539 #
540 initialization() {
541 local config_file="$1"
542
543 for N in ${NEWNS} ; do
544 NAMESERVERS="${NAMESERVERS} ${N}"
545 done
546
547 for N in ${NEWSEARCH} ; do
548 NAMESERVERS="${NAMESERVERS} ${N#*,}"
549 done
550
551 for DN in ${NEWDOMAIN} ; do
552 DOMAINS="${DOMAINS} ${DN%,*}"
553 done
554
555 CONFIGURED_DOMAINS=$(read_configured_domains ${config_file})
556
557 NAMESERVERS=$(uniqify ${NAMESERVERS})
558 DOMAINS=$(uniqify ${DOMAINS})
559 CONFIGURED_DOMAINS=$(uniqify ${CONFIGURED_DOMAINS})
560 }
561
562 ###
563 # void find_changed_and_added(char *configured, char *domains)
564 #
565 # Find already configured and newly added domains. Sets variables
566 # CHANGE_DOMAINS, ADD_DOMAINS and KNOWN_DOMAINS.
567 #
568 find_changed_and_added() {
569 local configured="$1" domains="$2" x
570
571 KNOWN_DOMAINS="${CONFIGURED_DOMAINS} ${DOMAINS}"
572
573 # Find what has to be disabled
574 for x in ${configured} ; do
575 if [[ " ${domains} " != *" ${x} "* ]] ; then
576 CHANGE_DOMAINS="${CHANGE_DOMAINS} ${x}"
577 fi
578 done
579
580 # Find what has to be added
581 for x in ${domains} ; do
582 if [[ " ${configured} " != *" ${x} "* ]] ; then
583 ADD_DOMAINS="${ADD_DOMAINS} ${x}"
584 else
585 CHANGE_DOMAINS="${CHANGE_DOMAINS} ${x}"
586 fi
587 done
588
589 ADD_DOMAINS=$(uniqify ${ADD_DOMAINS})
590 CHANGE_DOMAINS=$(uniqify ${CHANGE_DOMAINS})
591 KNOWN_DOMAINS=$(uniqify ${KNOWN_DOMAINS})
592 }
593
594 ###
595 # bool make_configuration_change(char *config_file, char *backup_suffix,
596 # char *sed_script)
597 #
598 # Applies any configuration change. Returns true, if there was a change.
599 #
600 make_configuration_change() {
601 local config_file="$1" backup_suffix="$2" sed_script="$3"
602 local old_config new_config
603
604 old_config=$(< ${config_file})
605
606 # Sanity check: add '}' at the end of the file
607 new_config=$( (echo -n "${old_config}" && echo -ne "\n}" ) | \
608 sed -nre "${sed_script}")
609 # Now remove what we added
610 new_config=${new_config%?\}}
611
612 if [[ "${old_config}" != "${new_config}" ]] ; then
613 cp ${config_file} ${config_file}${backup_suffix}
614 echo "${new_config}" > "${config_file}"
615 return 0
616 else
617 return 1
618 fi
619 }
620
621 ################################################################################
622 # Main part
623
624 # Check, if pdnsd configuration file is installed and possibly prepare it
625 installation_check "${PDNSDCONFIG}" || exit 0
626
627 # Basic initialization of NAMESERVERS, DOMAINS and CONFIGURED_DOMAINS
628 initialization "${PDNSDCONFIG}"
629
630 find_changed_and_added "${CONFIGURED_DOMAINS}" "${DOMAINS}"
631
632 sed_script="$(build_sed_script "${NAMESERVERS}" "${NEWDOMAIN}" \
633 "${CHANGE_DOMAINS}" "${ADD_DOMAINS}" \
634 "${DOMAINS}" "${KNOWN_DOMAINS}")"
635
636 # Check if the config changed
637 if make_configuration_change "${PDNSDCONFIG}" "${BACKUPSUFFIX}" "${sed_script}" ; then
638 # Checks for running pdnsd
639 [ -x /usr/sbin/pdnsd-ctl ] || exit 0
640 [ -e /var/cache/pdnsd/pdnsd.status ] || exit 0
641
642 # Reload config files
643 /usr/sbin/pdnsd-ctl config &>/dev/null
644 fi
645
646 exit 0
647
648
649
650 --
651 gentoo-commits@l.g.o mailing list