Document setting /etc/resolv.conf to list the local nameserver.
[openresolv] / libc.in
1 #!/bin/sh
2 # Copyright 2007-2008 Roy Marples
3 # All rights reserved
4
5 # libc subscriber for resolvconf
6 # You could symlink /etc/resolv.conf to resolvconf/run/resolv.conf
7 # for a read only etc, if resolvconf/run is linked to /var/run/resolvconf.
8
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions
11 # are met:
12 #     * Redistributions of source code must retain the above copyright
13 #       notice, this list of conditions and the following disclaimer.
14 #     * Redistributions in binary form must reproduce the above
15 #       copyright notice, this list of conditions and the following
16 #       disclaimer in the documentation and/or other materials provided
17 #       with the distribution.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 RESOLVCONF=/etc/resolv.conf
32 PREFIX=@PREFIX@
33 SYSCONFDIR=@SYSCONFDIR@
34 RESOLVCONFS="$(resolvconf -l)"
35 BASE="${SYSCONFDIR}/resolv.conf.d/base"
36
37 uniqify()
38 {
39     local result=
40     while [ -n "$1" ]; do
41                 case " ${result} " in
42                 *" $1 "*);;
43                 *) result="${result} $1";;
44                 esac
45                 shift
46         done
47     echo "${result# *}"
48 }
49
50 # sed may not be available, and this is faster on small files
51 key_get_value()
52 {
53         local key="$1" value= x= line=
54
55         shift
56         if [ $# -eq 0 ]; then
57                 while read line; do
58                         case "${line}" in
59                         "${key}"*) echo "${line##${key}}";;
60                         esac
61                 done
62         else
63                 for x; do
64                         while read line; do
65                                 case "${line}" in
66                                 "${key}"*) echo "${line##${key}}";;
67                                 esac
68                         done < "${x}"
69                 done
70         fi
71 }
72
73 OUR_NS=
74 if [ -e "${BASE}" ]; then
75         OUR_NS="$(key_get_value "nameserver " "${BASE}")"
76 fi
77 OUR_NS="$(uniqify \
78         ${OUR_NS} \
79         $(echo "${RESOLVCONFS}" | key_get_value "nameserver "))"
80
81 # libc only allows for 3 nameservers
82 # truncate after 127 as well
83 i=0
84 NS=
85 LOCALH=false
86 for N in ${OUR_NS}; do
87         i=$((${i} + 1))
88         NS="${NS} ${N}"
89         [ "${i}" = "3" ] && break
90         case "${N}" in
91                 127.*) LOCALH=true; break;;
92         esac
93 done
94
95 # This is nasty!
96 # If we have a local nameserver then assume they are intelligent enough
97 # to be forwarding domain requests to the correct nameserver and not search
98 # ones. This means we prefer search then domain, otherwise, we use them in
99 # the order given to us.
100 OUR_SEARCH=
101 if ${LOCALH}; then
102         if [ -e "${BASE}" ]; then
103                 OUR_SEARCH="$(key_get_value "search " "${BASE}")"
104         fi
105         RESS="$(echo "${RESOLVCONFS}" | key_get_value "search ")"
106         OUR_SEARCH="${OUR_SEARCH} ${RESS}"
107         if [ -e "${BASE}" ]; then
108                 RESD="$(key_get_value "domain " "${BASE}")"
109                 OUR_SEARCH="${OUR_SEARCH} ${RESD}"
110         fi
111         RESD="$(echo "${RESOLVCONFS}" | key_get_value "domain ")"
112         OUR_SEARCH="${OUR_SEARCH} ${RESD}"
113 else
114         if [ -e "${BASE}" ]; then
115                 RESS="$(key_get_value "search " "${BASE}")"
116                 RESD="$(key_get_value "domain " "${BASE}")"
117                 OUR_SEARCH="${RESS} ${RESD}"
118         fi
119         RESS="$(echo "${RESOLVCONFS}" | key_get_value "search ")"
120         RESD="$(echo "${RESOLVCONFS}" | key_get_value "domain ")"
121         OUR_SEARCH="${OUR_SEARCH} ${RESS} ${RESD}"
122 fi
123
124 # libc only allows for 6 search domains 
125 i=0
126 SEARCH=
127 for S in $(uniqify ${OUR_SEARCH}); do
128         i=$((${i} + 1))
129         SEARCH="${SEARCH} ${S}"
130         [ "${i}" = "6" ] && break
131 done
132 [ -n "${SEARCH}" ] && SEARCH="search${SEARCH}"
133
134 # Hold our new resolv.conf in a variable to save on temporary files
135 NEWCONF=""
136 [ -e "${SYSCONFDIR}"/resolv.conf.d/head ] \
137         && NEWCONF="${NEWCONF}$(cat "${SYSCONFDIR}"/resolv.conf.d/head)\n"
138 [ -n "${SEARCH}" ] && NEWCONF="${NEWCONF}${SEARCH}\n"
139 for N in ${NS}; do
140         NEWCONF="${NEWCONF}nameserver ${N}\n"
141 done
142
143 # Now get any configured options
144 OPTS=
145 if [ -e "${BASE}" ]; then
146         OPTS="$(key_get_value "options " "${BASE}")"
147 fi
148 OPTS="${OPTS}${OPTS:+ }$(echo ${RESOLVCONFS} | key_get_value "options ")"
149 if [ -n "${OPTS}" ]; then
150         NEWCONF="${NEWCONF}options"
151         for OPT in $(uniqify ${OPTS}); do
152                 NEWCONF="${NEWCONF} ${OPT}"
153         done
154         NEWCONF="${NEWCONF}\n"
155 fi
156
157 [ -e "${SYSCONFDIR}"/resolv.conf.d/tail ] \
158         && NEWCONF="${NEWCONF}$(cat "${SYSCONFDIR}"/resolv.conf.d/tail)\n"
159
160 # Check if the file has actually changed or not
161 if [ -e "${RESOLVCONF}" ]; then
162         [ "$(cat "${RESOLVCONF}")" = "$(printf "${NEWCONF}")" ] && exit 0
163 fi
164
165 # Create our resolv.conf now
166 (umask 022; printf "${NEWCONF}" > "${RESOLVCONF}")
167
168 resolvconf -s nscd restart
169 retval=$?
170
171 # Notify users of the resolver
172 for x in "${SYSCONFDIR}"/update-libc.d/*; do
173         if [ -e "${x}" ]; then
174                 "${x}" "$@"
175                 retval=$((${retval} + $?))
176         fi
177 done
178 exit ${retval}