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
|
#!/bin/sh /etc/rc.common
DHCP6C_REQUEST_OPTIONS='domain_name_servers domain_name ntp_servers sip_server_address sip_domain_name nis_server_address nis_domain_name nisp_server_address nisp_domain_name bcmcs_server_address bcmcs_domain_name'
dhcp6c_write_duid() {
local mac="${1:-$(ifconfig "$client_device" | sed -ne 's/[[:space:]]*$//; s/.*HWaddr //p')}"
local pat="[0-9A-F][0-9A-F]"
case "$mac" in
# exactly 6 octets -> assume type 3 (DUID-LL - RFC3315, 9.4)
$pat:$pat:$pat:$pat:$pat:$pat)
local oIFS="$IFS"; IFS=":"; set -- $mac; IFS="$oIFS"
# low endian
if [ "$(printf \\1 | hexdump -n1 -ve '8/2 "" "%04x" ""')" = "0001" ]; then
printf \\x0a\\x00
# big endian
else
printf \\x00\\x0a
fi
printf \\x00\\x03\\x00\\x06\\x$1\\x$2\\x$3\\x$4\\x$5\\x$6
logger -t dhcp6c "Using MAC address DUID 00:03:00:06:$1:$2:$3:$4:$5:$6"
;;
# at least 7 octets -> could be type 1 or type 2
$pat:$pat:$pat:$pat:$pat:$pat:*)
local len_id=":$(echo "$mac" | sed -e 's/[^:]//g')"
local len_hi=$(printf "%02x" $((${#len_id} / 0xFF)) )
local len_lo=$(printf "%02x" $((${#len_id} % 0xFF)) )
# low endian
if [ "$(printf \\1 | hexdump -n1 -ve '8/2 "" "%04x" ""')" = "0001" ]; then
printf \\x$len_lo\\x$len_hi
# big endian
else
printf \\x$len_hi\\x$len_lo
fi
printf $(echo "$mac" | sed -e 's/^/\\x/; s/:/\\x/g')
logger -t dhcp6c "Using user provided DUID $mac"
;;
*)
logger -t dhcp6c "Unable to derive DUID from interface '$client_device' and no valid user DUID given"
;;
esac
}
dhcp6c_write_interface() {
local cfg=$1
local sla_id
local sla_len
local enabled
local device
config_get_bool enabled "$cfg" enabled 0
if [ $enabled -ne 0 ]; then
config_get sla_id "$cfg" sla_id
config_get sla_len "$cfg" sla_len
network_get_device device "$cfg" && {
printf '\tprefix-interface %s {\n' "$device"
printf '\t\tsla-id %s;\n' "$sla_id"
printf '\t\tsla-len %s;\n' "$sla_len"
printf '\t};\n'
}
fi
}
dhcp6c_write_request() {
printf '\trequest %s;\n' $1 | sed -e s/_/-/g
}
dhcp6c_write_config() {
local pd
local na
config_get_bool pd basic pd 0
config_get_bool na basic na 0
printf 'interface %s {\n' "$client_ifname"
if [ $pd -ne 0 ]; then
printf '\tsend ia-pd 0;\n'
fi
if [ $na -ne 0 ]; then
printf '\tsend ia-na 0;\n'
fi
local rapid_commit
config_get_bool rapid_commit basic rapid_commit 0
[ $rapid_commit -ne 0 ] && printf '\tsend rapid-commit;\n'
local script
config_get script basic script
[ "$script" != "" ] && printf '\tscript "%s";\n' "$script"
local request
local value
for request in $DHCP6C_REQUEST_OPTIONS; do
config_get_bool value basic "$request" 0
[ $value -ne 0 ] && dhcp6c_write_request "$request"
done
printf '};\n\n'
if [ $pd -ne 0 ]; then
printf 'id-assoc pd 0 {\n'
config_foreach dhcp6c_write_interface interface
printf '};\n\n'
fi
if [ $na -ne 0 ]; then
printf 'id-assoc na 0 {\n'
printf '};\n\n'
fi
return 0
}
start() {
[ ! -e /etc/dhcp6cctlkey ] && `dd if=/dev/urandom count=1 2> /dev/null | md5sum | cut -d" " -f1 > /etc/dhcp6cctlkey`
[ -e /var/run/dhcp6c.pid ] && return 0
. /lib/functions/network.sh
config_load "dhcp6c"
local enabled
config_get_bool enabled basic enabled 0
[ $enabled -eq 0 ] && return 0
local user_duid
config_get user_duid basic duid
logger -t dhcp6c starting dhcp6c
local client_interface client_ifname client_device
config_get client_interface basic interface
network_get_device client_ifname "$client_interface"
network_get_physdev client_device "$client_interface" || client_device="$client_ifname"
local config_file="/var/etc/dhcp6c.conf"
local duid_file="/var/dhcp6c_duid"
mkdir -m 755 -p /var/etc
dhcp6c_write_config > $config_file
dhcp6c_write_duid "$user_duid" > $duid_file
local debug
local debug_option
config_get_bool debug basic debug 0
[ $debug -eq 1 ] && debug_option="-D"
/usr/sbin/dhcp6c -c $config_file $debug_option $client_ifname
sleep 3
ACTION=start /sbin/hotplug-call dhcp6c
return 0
}
stop() {
logger -t dhcp6c stopping dhcp6c
service_kill dhcp6c /var/run/dhcp6c.pid
rm -f /var/etc/dhcp6c.conf /var/run/dhcp6c.pid
ACTION=stop /sbin/hotplug-call dhcp6c
return 0
}
|