/[vps]/baselayout-vserver/branches/baselayout-1_12/net-scripts/net.modules.d/helpers.d/functions
Gentoo

Contents of /baselayout-vserver/branches/baselayout-1_12/net-scripts/net.modules.d/helpers.d/functions

Parent Directory Parent Directory | Revision Log Revision Log


Revision 206 - (show annotations) (download)
Sun Jan 15 10:27:03 2006 UTC (8 years, 11 months ago) by phreak
File size: 14447 byte(s)
Merging r1822 for branches/baselayout-1_12
1 #!/bin/bash
2 # Copyright (c) 2004-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4
5 # We will be loaded after conf.d/rc and conf.d/net so we can set a default
6 # here.
7 RC_AUTO_INTERFACE="${RC_AUTO_INTERFACE:-no}"
8
9 netdir="/var/lib/net-scripts"
10 statedir="${netdir}/state"
11
12 # Contributed by Roy Marples (uberlord@gentoo.org)
13
14 # char* interface_device(char *iface)
15 #
16 # Gets the base device of the interface
17 # Can handle eth0:1 and eth0.1
18 # Which returns eth0 in this case
19 interface_device() {
20 local dev="${1%%.*}"
21 [[ ${dev} == "$1" ]] && dev="${1%%:*}"
22 echo "${dev}"
23 }
24
25 # char* interface_type(char* iface)
26 #
27 # Returns the base type of the interface
28 # eth, ippp, etc
29 interface_type() {
30 echo "${1%%[0-9]*}"
31 }
32
33 # void save_state(char *interface)
34 #
35 # Saves state information regarding the interface
36 save_state() {
37 local iface="$1"
38 local d="${statedir}/${iface}"
39
40 [[ ! -d ${d} ]] && mkdir -m 0755 -p "${d}"
41 cp -p /etc/resolv.conf /etc/ntp.conf /etc/yp.conf "${d}" 2>/dev/null
42 }
43
44 # void remove_state(char *interface)
45 #
46 # Removes state information regarding the interface
47 remove_state() {
48 local d="${statedir}/$1"
49
50 [[ -d ${d} ]] && rm -Rf "${d}" 2>/dev/null
51 [[ ! ${2:-true} ]] && mkdir -m 0755 -p "${d}"
52 }
53
54 # void apply_state(char *interface)
55 #
56 # Apply's state information about the interface to the system
57 # If the files in the state dir are not links back to etc then
58 # we create them if RC_AUTO_INTERFACE="yes"
59 #
60 apply_state() {
61 local iface="$1"
62
63 if [[ -z ${iface} ]]; then
64 iface=$( select_best_interface )
65 [[ -z ${iface} ]] && return
66 fi
67
68 local d="${statedir}/${iface}"
69 if [[ -d ${d} ]]; then
70 local files=$( ls "${d}" )
71 if [[ -n ${files} ]] ; then
72 if [[ ${RC_AUTO_INTERFACE} == "yes" ]]; then
73 cp -pPR "${d}"/* "${netdir}"
74 local file
75 for file in ${files} ; do
76 # Skip .sv files
77 [[ ${file} == *".sv" ]] && contine
78 local link=$( readlink "/etc/${file}" 2>/dev/null )
79 if [[ ${link} != "${netdir}/${file}" ]]; then
80 [[ -e "/etc/${file}" ]] && rm -f "/etc/${file}"
81 ln -snf "${netdir}/${file}" "/etc/${file}"
82 fi
83 done
84 else
85 cp -pPR "${d}"/* /etc
86 fi
87 fi
88 fi
89
90 [[ ${RC_AUTO_INTERFACE} == "yes" ]] && merge_configs
91 }
92
93 # char* order_interfaces(bool require_gateway)
94 #
95 # Lists the interfaces in route metric order that we have configured
96 # (ie a state dir exists)
97 # require_gateway defaults to false
98 order_interfaces() {
99 local ifaces extra
100
101 ${1:-false} && extra=' && $2=="00000000"'
102 ifaces=$(awk '{if (NR>1 && $1!="lo"'"${extra}"') print $7, $1}' /proc/net/route \
103 | sort -n | cut -d' ' -f2 | uniq)
104
105 # Append lo if it's up
106 if ! ${1:-false} ; then
107 if grep -q "^lo[ \t]*" /proc/net/route ; then
108 ifaces="${ifaces} lo"
109 fi
110 fi
111
112 local i order
113 for i in ${ifaces}; do
114 [[ -d "${statedir}/${i}" ]] && order="${order}${i} "
115 done
116
117 echo "${order}"
118 }
119
120 # void merge_resolv()
121 #
122 # Merges the resolv.conf info from active interfaces
123 merge_resolv() {
124 local -a ifaces=( $(order_interfaces) )
125 local i j f
126
127 # We only work for ifaces with a resolv.conf
128 j=${#ifaces[@]}
129 for (( i=0; i<j; i++ )); do
130 [[ ! -e "${statedir}/${ifaces[i]}/resolv.conf" ]] && unset ifaces[i]
131 done
132 ifaces=( "${ifaces[@]}" )
133
134 # No point merging unless there are two or more interfaces
135 [[ ${#ifaces[@]} -lt 2 ]] && return
136
137 veinfo "Merging resolv.conf from interfaces ${ifaces[@]}"
138
139 local -a search srvs opts sortlist
140 j=0
141 for (( i=0; i<${#ifaces[@]}; i++ )); do
142 f="${statedir}/${ifaces[i]}/resolv.conf"
143 srvs[i]=$( sed -n -e 's/^[ \t]*nameserver[ \t]*\([^#]*\).*/\1/p' "${f}" \
144 | sed 2q )
145
146 search[i]=$( sed -n -e 's/^[ \t]*\(domain\|search\)[ \t]*\([^#]*\).*/\2/p' \
147 "${f}" | sed -e '$!d' )
148
149 opts[i]=$( sed -n -e 's/^[ \t]*options[ \t]*\([^#]*\).*/\1#/p;' "${f}" | xargs )
150 sortlist[i]=$( sed -n -e 's/^[ \t]*sortlist[ \t]*\([^#]*\).*/\1/p' "${f}" )
151
152 if [[ -z ${srvs[i]} && -z ${opts[i]} && -z ${sortlist[i]} && -z ${search[i]} ]]; then
153 unset srvs[i]
154 unset search[i]
155 unset opts[i]
156 unset sortlist[i]
157 continue
158 fi
159
160 # No point in handling more than 3 interfaces due to libc limits
161 (( j++ ))
162 [[ ${j} -gt 2 ]] && break
163 done
164 srvs=( "${srvs[@]}" )
165 search=( ${search[@]} )
166 opts=( "${opts[@]}" )
167 sortlist=( ${sortlist[@]} )
168
169 local new_srvs
170 j=0
171 # Add interface primary nameservers
172 for (( i=0;i<${#srvs[@]}; i++ )); do
173 local -a n=( ${srvs[i]} )
174 if [[ " ${new_srvs} " != *" ${n[0]} "* ]]; then
175 new_srvs="${new_srvs} ${n[0]}"
176 # libc can only handle 3 name servers
177 (( j++ ))
178 [[ ${j} -gt 2 ]] && break
179 fi
180 done
181
182 # Add interface secondary nameservers
183 if [[ ${j} -lt 3 ]]; then
184 for (( i=0;i<${#srvs[@]}; i++ )); do
185 local -a n=( ${srvs[i]} )
186 [[ -z ${n[1]} ]] && continue
187 if [[ " ${new_srvs} " != *" ${n[1]} "* ]]; then
188 new_srvs="${new_srvs} ${n[1]}"
189 # libc can only handle 3 name servers
190 (( j++ ))
191 [[ ${j} -gt 2 ]] && break
192 fi
193 done
194 fi
195
196 local new_search n_search=0
197 for i in ${search[@]}; do
198 if [[ " ${new_search} " != *" ${i} "* ]]; then
199 new_search="${new_search} ${i}"
200 # libc limits us to 6 search domains
201 (( n_search++ ))
202 [[ ${n_search} -gt 5 ]] && break
203 fi
204 done
205
206 local new_opts
207 for i in "${opts[@]}"; do
208 new_opts="${new_opts}#${i}"
209 done
210
211 # Remove duplicate options
212 new_opts=$(
213 echo -e "${new_opts//\#/\n}" \
214 | sort -u | sed -e 's/^/#/g' | xargs
215 )
216
217 local new_sortlist n_sortlist=0
218 for i in ${sortlist[@]}; do
219 if [[ " ${new_sortlist} " != *" ${i} "* ]]; then
220 new_sortlist="${new_sortlist} ${i}"
221 # libc limits us to 10 items
222 (( n_sortlist++ ))
223 [[ ${n_sortlist} -gt 9 ]] && break
224 fi
225 done
226
227 # Now we create a new resolv.conf to use
228 local f="${netdir}/resolv.conf.$$"
229 echo "# Generated by net-scripts from interfaces ${ifaces[@]}" > "${f}"
230 chmod 644 "${f}"
231 for i in ${new_srvs[@]}; do
232 echo "nameserver ${i}" >> "${f}"
233 done
234 if [[ -n ${new_search} ]]; then
235 if [[ ${n_search} == "1" ]]; then
236 echo "domain${new_search}" >> "${f}"
237 else
238 echo "search${new_search}" >> "${f}"
239 fi
240 fi
241
242 [[ -n ${new_sortlist} ]] && echo "sortlist${new_sortlist}" >> "${f}"
243
244 # We seperated the options out using # in our sed call above
245 # so we set IFS here. If you do any spliting futher down in this function
246 # then you will need to reset IFS.
247 local IFS="#"
248 for i in ${new_opts}; do
249 [[ -n ${i# } ]] && echo "options ${i# }" >> "${f}"
250 done
251
252 mv "${f}" "${netdir}/resolv.conf"
253 }
254
255
256 # void merge_ntp()
257 #
258 # Merges the ntp.conf info from active interfaces
259 merge_ntp() {
260 local -a ifaces=( $(order_interfaces) )
261 local i j f
262
263 # We only work for ifaces with a ntp.conf
264 j=${#ifaces[@]}
265 for (( i=0; i<j; i++ )); do
266 [[ ! -e "${statedir}/${ifaces[i]}/ntp.conf" ]] && unset ifaces[i]
267 done
268 ifaces=( "${ifaces[@]}" )
269
270 # No point merging unless there are two or more interfaces
271 [[ ${#ifaces[@]} -lt 2 ]] && return
272
273 veinfo "Merging ntp.conf from interfaces ${ifaces[@]}"
274
275 local srvs
276 for (( i=0; i<${#ifaces[@]}; i++ )); do
277 f="${statedir}/${ifaces[i]}/ntp.conf"
278 srvs="${srvs} $( sed -n -e 's/^[ \t]*server[ \t]*\([^#]\)/\1/p' "${f}" )"
279 done
280
281 # ntp does it's own preference list, so we just remove duplicates
282 sort_unique() {
283 set -- " ${@/%/\n}"
284 echo -e "$@" | sort -u
285 }
286
287 srvs=$( sort_unique ${srvs} )
288
289 f="${netdir}/ntp.conf.$$"
290 echo "# Generated by net-scripts for interfaces ${ifaces[@]}" > "${f}"
291 chmod 644 "${f}"
292
293 echo "restrict default noquery notrust nomodify" >> "${f}"
294 echo "restrict 127.0.0.1" >> "${f}"
295
296 for i in ${srvs}; do
297 echo "restrict ${i} nomodify notrap noquery" >> "${f}"
298 echo "server ${i}" >> "${f}"
299 done
300
301 echo "driftfile /var/lib/ntp/ntp.drift" >> "${f}"
302 echo "logfile /var/log/ntp.log" >> "${f}"
303
304 mv "${f}" "${netdir}/ntp.conf"
305 }
306
307 # void merge_configs()
308 #
309 # Merge config files together
310 merge_configs() {
311 merge_resolv
312 merge_ntp
313 }
314
315 # char* select_best_interface()
316 #
317 # Selects the best interface to apply state information to
318 # This is currently based on routing metrics
319 select_best_interface() {
320 local -a ifs=( $(order_interfaces) )
321
322 # Move lo to the back of the pecking order of it's active
323 local x=" ${ifs[@]} "
324 [[ ${x// lo / } != "${x}" ]] && ifs=( ${x// lo / } lo )
325
326 local iface
327 for iface in ${ifs[@]} ; do
328 if [[ -e "${statedir}/${iface}/resolv.conf" ]]; then
329 echo "${iface}"
330 return 0
331 fi
332 done
333
334 echo "${ifs[0]}"
335 }
336
337 # int calculate_metric(char *interface)
338 #
339 # Calculates the best metric for the interface
340 # The Linux kernel does not use this at the moment, but we use it so that
341 # default routes remain and we can work out the "best" interface
342 calculate_metric() {
343 local iface="$1" exclude='$1!="Iface" && $1!="lo"'
344
345 # Have we already got a metric?
346 local m=$( awk '$1=="'${iface}'" && $2=="00000000" { print $7 }' \
347 /proc/net/route )
348 if [[ -n ${m} ]]; then
349 echo "${m}"
350 return 0
351 fi
352
353 local itype=$( interface_type "${iface}" ) x i
354
355 # If we're not a wireless device then exclude wireless from the
356 # routing table so we stay < 1000
357 if [[ -e /proc/net/wireless ]]; then
358 if ! grep -q "^[ \t]*${iface}:[ \t]" /proc/net/wireless ; then
359 local i=$( sed -n -e 's/^[ \t]*\(.*\):.*/\1/p' /proc/net/wireless )
360 for x in ${i} ; do
361 exclude="${exclude} && "'$1'"!=\"${x}\""
362 done
363 fi
364 fi
365
366 # Exclude ppp and ippp as well
367 local ix="ppp|ippp"
368 [[ ${itype} == "ppp" ]] && ix="ippp"
369 [[ ${itype} == "ippp" ]] && ix="ppp"
370 i=$( sed -n -e 's/^[ ]*\('${ix}'[0-9]*\):.*$/\1/p' /proc/net/dev )
371 for x in ${i} ; do
372 exclude="${exclude} && "'$1'"!=\"${x}\""
373 done
374
375 local m=$( awk "${exclude} { print "'$7'" }" /proc/net/route \
376 | sort -rn | head -n 1 | cut -d' ' -f2 )
377 m="${m:--1}"
378 (( m ++ ))
379
380 # If we're a wireless device then add 1000 so that wired interfaces take preference
381 if [[ -e /proc/net/wireless ]]; then
382 grep -q "^[ \t]*${iface}:[ \t]" /proc/net/wireless && (( m+= 1000 ))
383 fi
384
385 # If we're a ppp device then we add 2000 for ISDN, otherwise 3000
386 [[ ${itype} == "ippp" ]] && (( m+= 2000 ))
387 [[ ${itype} == "ppp" ]] && (( m+= 3000 ))
388
389 echo "${m}"
390 }
391
392 # int netmask2cidr(char *netmask)
393 #
394 # Returns the CIDR of a given netmask
395 netmask2cidr() {
396 local binary="" i bin
397
398 for i in ${1//./ }; do
399 bin=""
400 while [[ ${i} != "0" ]]; do
401 bin=$[${i}%2]${bin}
402 (( i=i>>1 ))
403 done
404 binary="${binary}${bin}"
405 done
406 binary="${binary%%0*}"
407 echo "${#binary}"
408 }
409
410 # char* netmask2cidr(int cidr)
411 #
412 # Returns the netmask of a given CIDR
413 cidr2netmask() {
414 local cidr="$1" netmask="" done=0 i sum=0 cur=128
415 local octets frac
416
417 (( octets=cidr/8 ))
418 (( frac=cidr%8 ))
419 while [[ octets -gt 0 ]]; do
420 netmask="${netmask}.255"
421 (( octets-- ))
422 (( done++ ))
423 done
424
425 if [[ ${done} -lt 4 ]]; then
426 for (( i=0; i<${frac}; i++ )); do
427 (( sum+=cur ))
428 (( cur/=2 ))
429 done
430 netmask="${netmask}.${sum}"
431 (( done++ ))
432
433 while [[ ${done} -lt 4 ]]; do
434 netmask="${netmask}.0"
435 (( done++ ))
436 done
437 fi
438
439 echo "${netmask:1}"
440 }
441
442 # char* ip_network(char *ip, char *netmask)
443 #
444 # Returns the network of the ip address
445 # ip can be 192.168.0.51/24
446 # or
447 # ip can be 192.168.0.51 and netmask is 255.255.255.0
448 ip_network() {
449 local ip="$1" mask="$2" i network x
450
451 # We only work for IPv4 addresses
452 [[ ${ip} != *.*.*.* ]] && return
453
454 # If we didn't get parameter 2 then assume we have a CIDR
455 if [[ -z ${mask} ]]; then
456 mask="${ip##*/}"
457 [[ -z ${mask} || ${mask} == ${ip} ]] && return 1
458 mask=$( cidr2netmask "${mask}" )
459 ip="${ip%%/*}"
460 fi
461
462 ip=( ${ip//./ } )
463 mask=( ${mask//./ } )
464
465 for (( i=0; i<4; i++ )); do
466 (( x=ip[i] & mask[i] ))
467 network="${network}${x}"
468 [[ ${i} -lt 3 ]] && network="${network}."
469 done
470
471 echo "${network}"
472 }
473
474 # bool clean_pidfile(char *file)
475 #
476 # Removes the given pidfile if the process is not running
477 # Returns 1 if the process is still running otherwise 0
478 clean_pidfile() {
479 local pidfile="$1"
480
481 [[ ! -f ${pidfile} ]] && return 0
482 local pid=$( < "${pidfile}" )
483
484 if [[ -n ${pid} ]]; then
485 local cmd="${pidfile##*/}"
486 cmd="${cmd%%-*}"
487 ps -p "${pid}" 2>/dev/null | grep -q "${cmd}" && return 1
488 fi
489
490 rm -f "${pidfile}"
491 return 0
492 }
493
494 # bool process_finished(int pid, char* cmd)
495 #
496 # We wait for 10 seconds until the command ${cmd}
497 # stops running on the process ${pid}
498 process_finished() {
499 local i pid="$1" cmd="$2" secs="${3:-9}"
500
501 for (( i=0; i<secs; i++ )); do
502 ps -p "${pid}" 2>/dev/null | grep -q "${cmd}" || return 0
503 sleep 1
504 done
505
506 return 1
507 }
508
509 # bool is_function(char* name)
510 #
511 # Returns 0 if the given name is a shell function, otherwise 1
512 is_function() {
513 [[ -z $1 ]] && return 1
514 [[ $(type -t "$1") == "function" ]]
515 }
516
517 # void function_wrap(char* source, char* target)
518 #
519 # wraps function calls - for example function_wrap(this, that)
520 # maps function names this_* to that_*
521 function_wrap() {
522 local i
523
524 is_function "${2}_depend" && return
525
526 for i in $( typeset -f | grep -o '^'"${1}"'_[^ ]*' ); do
527 eval "${2}${i#${1}}() { ${i} \"\$@\"; }"
528 done
529 }
530
531 # char[] * expand_parameters(char *cmd)
532 #
533 # Returns an array after expanding parameters. For example
534 # "192.168.{1..3}.{1..3}/24 brd +"
535 # will return
536 # "192.168.1.1/24 brd +"
537 # "192.168.1.2/24 brd +"
538 # "192.168.1.3/24 brd +"
539 # "192.168.2.1/24 brd +"
540 # "192.168.2.2/24 brd +"
541 # "192.168.2.3/24 brd +"
542 # "192.168.3.1/24 brd +"
543 # "192.168.3.2/24 brd +"
544 # "192.168.3.3/24 brd +"
545 expand_parameters() {
546 local x="$( eval echo ${@// /_} )"
547 local -a a=( ${x} )
548
549 a=( "${a[@]/#/\"}" )
550 a=( "${a[@]/%/\"}" )
551 echo "${a[*]//_/ }"
552 }
553
554 # void configure_variables(char *interface, char *option1, [char *option2])
555 #
556 # Maps configuration options from <variable>_<option> to <variable>_<iface>
557 # option2 takes precedence over option1
558 configure_variables() {
559 local iface="$1" option1="$2" option2="$3"
560
561 local mod func x i
562 local -a ivars ovars1 ovars2
563 local ifvar=$( bash_variable "${iface}" )
564
565 for mod in ${MODULES[@]}; do
566 is_function ${mod}_variables || continue
567 for v in $(${mod}_variables) ; do
568 x=""
569 [[ -n ${option2} ]] && x="${v}_${option2}[@]"
570 [[ -z ${!x} ]] && x="${v}_${option1}[@]"
571 [[ -n ${!x} ]] && eval "${v}_${ifvar}=( \"\${!x}\" )"
572 done
573 done
574
575 return 0
576 }
577
578 # Provide a wrapper for hostname if it's not available
579 if [[ -z $(type -p hostname) ]]; then
580 hostname() {
581 # Linux and *BSD seem to differ
582 local kernel="kern" ctl="hostname"
583 [[ $(uname) == "Linux" ]] && kernel="kernel"
584
585 if [[ $1 == "-y" || $1 == "--yp" || $1 == "nis" ]]; then
586 ctl="domainname"
587 shift
588 fi
589
590 if [[ -n $1 ]]; then
591 sysctl -q -w "${kernel}.${ctl}=$1"
592 else
593 sysctl -n "${kernel}.${ctl}"
594 fi
595 }
596 fi
597
598 # vim:ts=4

  ViewVC Help
Powered by ViewVC 1.1.20