blob: 4f73cb6df416132db3b9f0eef8c707c45360dce6 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
|
#!/bin/sh /etc/rc.common
# Copyright (C) 2007-2015 OpenWrt.org
START=70
STOP=01
USE_PROCD=1
KEEPALIVED_CONF=/tmp/keepalived.conf
INDENT_1="\t"
INDENT_2="${INDENT_1}${INDENT_1}"
INDENT_3="${INDENT_1}${INDENT_1}${INDENT_1}"
INDENT_4="${INDENT_1}${INDENT_1}${INDENT_1}${INDENT_1}"
config_section_open() {
local tag="$1"
local name="$2"
printf '%s' "$tag" >> "$KEEPALIVED_CONF"
[ -n "$name" ] && printf ' %s' "$name" >> "$KEEPALIVED_CONF"
printf ' {\n' >> "$KEEPALIVED_CONF"
}
config_section_close() {
printf '}\n\n' >> "$KEEPALIVED_CONF"
}
config_foreach_wrapper() {
local section="$1"
local function="$1"
# Convention is that 'function' and 'section' are the same
config_foreach "$function" "$section"
}
print_elems_indent() {
local config="$1"
shift
local indent="$1"
shift
[ -z "$indent" ] && indent="$INDENT_1"
for opt in "$@"; do
local "$opt"
local optval
local no_val=0
if [ "${opt:0:7}" = "no_val_" ]; then
opt="${opt:7}"
no_val=1
fi
config_get "$opt" "$config" "$opt"
eval optval=\$"$opt"
[ -z "$optval" ] && continue
printf '%b%s' "$indent" "$opt" >> "$KEEPALIVED_CONF"
[ "$no_val" = "0" ] && {
local words=0
words="$(echo "$optval" | wc -w)"
if [ "$words" -gt 1 ]; then
printf ' "%s"' "$optval" >> "$KEEPALIVED_CONF"
else
printf ' %s' "$optval" >> "$KEEPALIVED_CONF"
fi
}
printf '\n' >> "$KEEPALIVED_CONF"
done
unset optval
}
print_list_indent() {
local lst="$1"
local indent="$2"
local lst_elems
[ -z "$indent" ] && indent="$INDENT_1"
eval lst_elems=\$"$lst"
[ -z "$lst_elems" ] && return 0
printf '%b%s {\n' "$indent" "$lst" >> "$KEEPALIVED_CONF"
for e in $lst_elems; do
printf '%b%s\n' "${indent}${INDENT_1}" "$e">> "$KEEPALIVED_CONF"
done
printf '%b}\n' "$indent" >> "$KEEPALIVED_CONF"
}
print_notify() {
local type="$1"
shift
local name="$1"
shift
for notify in "$@"; do
printf '%b%s' "${INDENT_1}" "$notify">> "$KEEPALIVED_CONF"
notify="$(echo "$notify" | tr 'a-z' 'A-Z')"
printf ' "/bin/busybox env -i ACTION=%s TYPE=%s NAME=%s /sbin/hotplug-call keepalived"\n' "$notify" "$type" "$name" >> "$KEEPALIVED_CONF"
done
}
globals() {
local notification_email
printf '%bscript_user root\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
printf '%benable_script_security\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
config_get notification_email "$1" notification_email
print_list_indent notification_email
print_elems_indent "$1" "$INDENT_1" \
notification_email_from \
smtp_server \
smtp_connect_timeout \
router_id \
vrrp_mcast_group4 \
vrrp_mcast_group6 \
vrrp_startup_delay
}
print_ipaddress_indent() {
local section="$1"
local curr_ipaddr="$2"
local indent="$3"
local address device scope name
config_get name "$section" name
[ "$name" != "$curr_ipaddr" ] && return 0
config_get address "$section" address
config_get device "$section" device
config_get scope "$section" scope
# Default indent
[ -z "$indent" ] && indent="$INDENT_1"
# If no address exit
[ -z "$address" ] && return 0
if [ -z "$device" ]; then
printf '%b%s' "$indent" "$address" >> "$KEEPALIVED_CONF"
else
# Add IP address/netmask and device
printf '%b%s dev %s' "$indent" "$address" "$device">> "$KEEPALIVED_CONF"
# Add scope
[ -n "$scope" ] && printf ' scope %s' "$scope" >> "$KEEPALIVED_CONF"
fi
printf '\n' >> "$KEEPALIVED_CONF"
}
static_ipaddress() {
local address
config_get address "$1" address
for a in $address; do
config_foreach print_ipaddress_indent ipaddress "$a"
done
}
print_route_indent() {
local section="$1"
local curr_route="$2"
local indent="$3"
local name blackhole address src_addr gateway device scope table
config_get name "$section" name
[ "$name" != "$curr_route" ] && return 0
config_get_bool blackhole "$section" blackhole 0
config_get address "$section" address
config_get src_addr "$section" src_addr
config_get gateway "$section" gateway
config_get device "$section" device
config_get table "$section" table
# If no address exit
[ -z "$address" ] && return 0
# Default indent
[ -z "$indent" ] && indent="$INDENT_1"
[ "$blackhole" -gt 0 ] && {
printf '%bblackhole %s\n' "$indent" "$address" >> "$KEEPALIVED_CONF"
return 0
}
# Add src addr or address
if [ -n "$src_addr" ]; then
printf '%bsrc %s %s' "$indent" "$src_addr" "$address" >> "$KEEPALIVED_CONF"
else
[ -z "$device" ] && return 0
printf '%b%s' "$indent" "$address" >> "$KEEPALIVED_CONF"
fi
# Add route/gateway
[ -n "$gateway" ] && printf ' via %s' "$gateway" >> "$KEEPALIVED_CONF"
# Add device
printf ' dev %s' "$device" >> "$KEEPALIVED_CONF"
# Add scope
[ -n "$scope" ] && printf ' scope %s' "$scope" >> "$KEEPALIVED_CONF"
# Add table
[ -n "$table" ] && printf ' table %s' "$table" >> "$KEEPALIVED_CONF"
printf '\n' >> "$KEEPALIVED_CONF"
}
print_track_elem_indent() {
local section="$1"
local curr_track_elem="$2"
local indent="$3"
local name value
config_get name "$section" name
[ "$name" != "$curr_track_elem" ] && return 0
config_get value "$section" value
config_get weight "$section" weight
[ -z "$value" ] && return 0
printf '%b%s' "$indent" "$value" >> "$KEEPALIVED_CONF"
[ -n "$weight" ] && printf ' weight %s' "$weight" >> "$KEEPALIVED_CONF"
printf '\n' >> "$KEEPALIVED_CONF"
}
print_track_bfd_indent() {
local section="$1"
local curr_track_elem="$2"
local indent="$3"
local name
config_get name "$section" name
[ "$name" != "$curr_track_elem" ] && return 0
config_get weight "$section" weight
printf '%b%s' "$indent" "$name" >> "$KEEPALIVED_CONF"
[ -n "$weight" ] && printf ' weight %s' "$weight" >> "$KEEPALIVED_CONF"
printf '\n' >> "$KEEPALIVED_CONF"
}
static_routes() {
local route
config_get route "$1" route
for r in $route; do
config_foreach print_route_indent route "$r"
done
}
# Count 'vrrp_instance' with the given name ; called by vrrp_instance_check()
vrrp_instance_name_count() {
local name
config_get name "$1" name
[ "$name" = "$2" ] && count="$((count + 1))"
}
# Check if there's a 'vrrp_instance' section with the given name
vrrp_instance_check() {
local count="0"
local name="$1"
config_foreach vrrp_instance_name_count vrrp_instance "$name"
[ $count -gt 0 ] && return 0 || return 1
}
vrrp_sync_group() {
local group name
local valid_group
# No name for group, exit
config_get name "$1" name
[ -z "$name" ] && return 0
# No members for group, exit
config_get group "$1" group
[ -z "$group" ] && return 0
# Check if we have 'vrrp_instance's defined for
# each member and remove names with not vrrp_instance defined
for m in $group; do
vrrp_instance_check "$m" && valid_group="$valid_group $m"
done
[ -z "$valid_group" ] && return 0
config_section_open "vrrp_sync_group" "$name"
group="$valid_group"
print_list_indent group
print_elems_indent "$1" "$INDENT_1" no_val_smtp_alert no_val_global_tracking
print_notify "GROUP" "$name" notify_backup notify_master \
notify_fault notify
config_section_close
}
vrrp_instance() {
local name auth_type auth_pass
config_get name "$1" name
[ -z "$name" ] && return 0
config_section_open "vrrp_instance" "$name"
config_get auth_type "$1" auth_type
config_get auth_pass "$1" auth_pass
[ -n "$auth_type" ] && [ -n "$auth_pass" ] && {
printf '%bauthentication {\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
printf '%bauth_type %s\n' "${INDENT_2}" "$auth_type" >> "$KEEPALIVED_CONF"
printf '%bauth_pass %s\n' "${INDENT_2}" "$auth_pass" >> "$KEEPALIVED_CONF"
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
}
print_elems_indent "$1" "$INDENT_1" state interface \
mcast_src_ip unicast_src_ip virtual_router_id version priority \
advert_int preempt_delay debug \
lvs_sync_daemon_interface garp_master_delay garp_master_refresh \
garp_master_repeat garp_master_refresh_repeat \
no_val_vmac_xmit_base no_val_native_ipv6 no_val_accept \
no_val_dont_track_primary no_val_smtp_alert no_val_nopreempt \
no_val_use_vmac
print_notify "INSTANCE" "$name" notify_backup notify_master \
notify_fault notify_stop
# Handle virtual_ipaddress & virtual_ipaddress_excluded lists
for opt in virtual_ipaddress virtual_ipaddress_excluded; do
config_get "$opt" "$1" "$opt"
eval optval=\$$opt
[ -z "$optval" ] && continue
printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
for a in $optval; do
config_foreach print_ipaddress_indent ipaddress "$a" "$INDENT_2"
done
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
done
# Handle virtual_routes
for opt in virtual_routes; do
config_get "$opt" "$1" "$opt"
eval optval=\$$opt
[ -z "$optval" ] && continue
printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
for r in $optval; do
config_foreach print_route_indent route "$r" "$INDENT_2"
done
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
done
# Handle track_script lists
for opt in track_script; do
config_get "$opt" "$1" "$opt"
eval optval=\$$opt
[ -z "$optval" ] && continue
printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
for t in $optval; do
printf '%b%s\n' "${INDENT_2}" "$optval" >> "$KEEPALIVED_CONF"
done
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
done
# Handle track_interface lists
for opt in track_interface; do
config_get "$opt" "$1" "$opt"
eval optval=\$$opt
[ -z "$optval" ] && continue
printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
for t in $optval; do
config_foreach print_track_elem_indent track_interface "$t" "$INDENT_2"
done
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
done
# Handle track_bfd lists
for opt in track_bfd; do
config_get "$opt" "$1" "$opt"
eval optval=\$$opt
[ -z "$optval" ] && continue
printf '%b%s {\n' "${INDENT_1}" "$opt" >> "$KEEPALIVED_CONF"
for t in $optval; do
config_foreach print_track_bfd_indent bfd_instance "$t" "$INDENT_2"
done
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
done
# Handle simple lists of strings (with no spaces in between)
for opt in unicast_peer; do
config_get "$opt" "$1" "$opt"
print_list_indent "$opt"
done
unset optval
config_section_close
}
vrrp_script() {
local name
config_get name "$1" name
[ -z "$name" ] && return 0
config_section_open "vrrp_script" "$name"
print_elems_indent "$1" "$INDENT_1" script interval weight fall rise
config_section_close
}
bfd_instance() {
local name
config_get name "$1" name
[ -z "$name" ] && return 0
config_section_open "bfd_instance" "$name"
print_elems_indent "$1" "$INDENT_1" neighbor_ip source_ip min_rx min_tx idle_tx hoplimit max_hops
config_section_close
}
url() {
local url="$2"
local name path digest
config_get name "$1" name
[ "$url" = "$name" ] || return 0
config_get path "$1" path
config_get digest "$1" digest
[ -n "$digest" ] && [ -n "$path" ] && {
printf '%burl {\n' "${INDENT_3}" >> "$KEEPALIVED_CONF"
printf '%bpath %s\n' "${INDENT_4}" "$path" >> "$KEEPALIVED_CONF"
printf '%bdigest %s\n' "${INDENT_4}" "$digest" >> "$KEEPALIVED_CONF"
printf '%b}\n' "${INDENT_3}" >> "$KEEPALIVED_CONF"
}
}
url_list() {
config_foreach url url "$1"
}
real_server() {
local server="$2"
local enabled name weight ipaddr port check
config_get_bool enabled "$1" enabled 1
[ "$enabled" -eq 1 ] || return 0
config_get name "$1" name
[ "$server" = "$name" ] || return 0
config_get weight "$1" weight
[ -n "$weight" ] || return 0
config_get ipaddr "$1" ipaddr
config_get port "$1" port
config_get check "$1" check
[ -n "$ipaddr" ] && [ -n "$port" ] && {
printf '%breal_server %s %d {\n' "${INDENT_1}" "$ipaddr" "$port" >> "$KEEPALIVED_CONF"
printf '%bweight %d\n' "${INDENT_2}" "$weight" >> "$KEEPALIVED_CONF"
case "$check" in
TCP_CHECK)
printf '%b%s {\n' "${INDENT_2}" "$check" >> "$KEEPALIVED_CONF"
print_elems_indent "$1" "$INDENT_3" connect_timeout \
connect_port
printf '%b}\n' "${INDENT_2}" >> "$KEEPALIVED_CONF"
;;
MISC_CHECK)
printf '%b%s {\n' "${INDENT_2}" "$check" >> "$KEEPALIVED_CONF"
print_elems_indent "$1" "$INDENT_3" misc_path
printf '%b}\n' "${INDENT_2}" >> "$KEEPALIVED_CONF"
;;
HTTP_GET | SSL_GET)
printf '%b%s {\n' "${INDENT_2}" "$check" >> "$KEEPALIVED_CONF"
print_elems_indent "$1" "$INDENT_3" connect_timeout \
connect_port nb_get_retry delay_before_retry
# Handle url list
config_list_foreach "$1" url url_list
printf '%b}\n' "${INDENT_2}" >> "$KEEPALIVED_CONF"
;;
esac
printf '%b}\n' "${INDENT_1}" >> "$KEEPALIVED_CONF"
}
}
real_server_list() {
config_foreach real_server real_server "$1"
}
virtual_server() {
local enabled ipaddr port lb_algo sorry_server_ip sorry_server_port
config_get_bool enabled "$1" enabled 1
[ "$enabled" -eq 1 ] || return 0
config_get ipaddr "$1" ipaddr
[ -z "$ipaddr" ] && return 0
config_get port "$1" port
[ -z "$port" ] && return 0
config_section_open "virtual_server" "$ipaddr $port"
print_elems_indent "$1" "$INDENT_1" fwmark delay_loop \
lb_kind persistence_timeout persistence_granularity \
virtualhost protocol
config_get lb_algo "$1" lb_algo
[ -z "$lb_algo" ] && lb_algo="rr"
modprobe ip_vs_${lb_algo} 1>/dev/null 2>&1
printf '%blb_algo %s\n' "${INDENT_1}" "${lb_algo}" >> "$KEEPALIVED_CONF"
config_get sorry_server_ip "$1" sorry_server_ip
config_get sorry_server_port "$1" sorry_server_port
[ -n "$sorry_server_ip" ] && [ -n "$sorry_server_port" ] && {
printf '%bsorry_server %s %s\n' "${INDENT_1}" "$sorry_server_ip" "$sorry_server_port" >> "$KEEPALIVED_CONF"
}
# Handle real_server list
config_list_foreach "$1" real_server real_server_list
config_section_close
}
process_config() {
local alt_config_file linkbeat_use_polling
rm -f "$KEEPALIVED_CONF"
# First line
printf '! Configuration file for keepalived (autogenerated via init script)\n' > "$KEEPALIVED_CONF"
printf '! Written %s\n\n' "$(date +'%c')" >> "$KEEPALIVED_CONF"
[ -f /etc/config/keepalived ] || return 0
config_load 'keepalived'
config_get alt_config_file globals alt_config_file
# If "alt_config_file" specified, use that instead
[ -n "$alt_config_file" ] && [ -f "$alt_config_file" ] && {
rm -f "$KEEPALIVED_CONF"
# Symlink "alt_config_file" since it's a bit easier and safer
ln -s "$alt_config_file" "$KEEPALIVED_CONF"
return 0
}
config_get_bool linkbeat_use_polling globals linkbeat_use_polling 0
[ "$linkbeat_use_polling" -gt 0 ] && printf 'linkbeat_use_polling\n\n' >> "$KEEPALIVED_CONF"
config_section_open "global_defs"
config_foreach_wrapper globals
config_section_close
config_section_open "static_ipaddress"
config_foreach_wrapper static_ipaddress
config_section_close
config_section_open "static_routes"
config_foreach_wrapper static_routes
config_section_close
config_foreach_wrapper vrrp_script
config_foreach_wrapper bfd_instance
config_foreach_wrapper vrrp_sync_group
config_foreach_wrapper vrrp_instance
config_foreach_wrapper virtual_server
return 0
}
service_triggers() {
procd_add_reload_trigger "keepalived"
}
reload_service() {
process_config
#SIGHUP is used by keepalived to do init.d reload
procd_send_signal keepalived
}
start_service() {
procd_open_instance
procd_set_param command /usr/sbin/keepalived
procd_append_param command -n # don't daemonize, procd will handle that for us
procd_append_param command -f "$KEEPALIVED_CONF"
process_config
# set auto respawn behavior
procd_set_param respawn
procd_close_instance
}
|