summaryrefslogtreecommitdiff
path: root/odhcp6c-example-script.sh
blob: 00d80560c1a015c967f7bf77eec9081c47a3cfca (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
#!/bin/sh
[ -z "$2" ] && echo "Error: should be run by odhcpc6c" && exit 1

update_resolv() {
	local device="$1"
	local dns="$2"
	
	(
		flock 9
		grep -v "#odhcp6c:$device:" /etc/resolv.conf > /tmp/resolv.conf.tmp
		for c in $dns; do
			echo "nameserver $c #odhcp6c:$device:" >> /tmp/resolv.conf.tmp
		done
		mv /tmp/resolv.conf.tmp /etc/resolv.conf
		chmod 0644 /etc/resolv.conf
	) 9>/tmp/resolv.conf.lock
	rm -f /tmp/resolv.conf.lock /tmp/resolv.conf.tmp
}

setup_interface () {
	local device="$1"

	# Merge RA-DNS
	for radns in $RA_DNS; do
		local duplicate=0
		for dns in $RDNSS; do
			[ "$radns" = "$dns" ] && duplicate=1
		done
		[ "$duplicate" = 0 ] && RDNSS="$RDNSS $radns"
	done

	local dnspart=""
	for dns in $RDNSS; do
		if [ -z "$dnspart" ]; then
			dnspart="\"$dns\""
		else
			dnspart="$dnspart, \"$dns\""
		fi
	done

	update_resolv "$device" "$dns"

	local prefixpart=""
	for entry in $PREFIXES; do
		local addr="${entry%%,*}"
                entry="${entry#*,}"
                local preferred="${entry%%,*}"
                entry="${entry#*,}"
                local valid="${entry%%,*}"
                entry="${entry#*,}"
		[ "$entry" = "$valid" ] && entry=

		local class=""
		local excluded=""

		while [ -n "$entry" ]; do
			local key="${entry%%=*}"
                	entry="${entry#*=}"
			local val="${entry%%,*}"
                	entry="${entry#*,}"
			[ "$entry" = "$val" ] && entry=

			if [ "$key" = "class" ]; then
				class=", \"class\": $val"
			elif [ "$key" = "excluded" ]; then
				excluded=", \"excluded\": \"$val\""
			fi
		done

		local prefix="{\"address\": \"$addr\", \"preferred\": $preferred, \"valid\": $valid $class $excluded}"
		
		if [ -z "$prefixpart" ]; then
			prefixpart="$prefix"
		else
			prefixpart="$prefixpart, $prefix"
		fi

		# TODO: delete this somehow when the prefix disappears
		ip -6 route add unreachable "$addr"
	done

	ip -6 route flush dev "$device"
	ip -6 address flush dev "$device" scope global

	# Merge addresses
	for entry in $RA_ADDRESSES; do
		local duplicate=0
		local addr="${entry%%/*}"
		for dentry in $ADDRESSES; do
			local daddr="${dentry%%/*}"
			[ "$addr" = "$daddr" ] && duplicate=1
		done
		[ "$duplicate" = "0" ] && ADDRESSES="$ADDRESSES $entry"
	done

	for entry in $ADDRESSES; do
		local addr="${entry%%,*}"
		entry="${entry#*,}"
		local preferred="${entry%%,*}"
		entry="${entry#*,}"
		local valid="${entry%%,*}"

		ip -6 address add "$addr" dev "$device" preferred_lft "$preferred" valid_lft "$valid" 
	done

	for entry in $RA_ROUTES; do
		local addr="${entry%%,*}"
		entry="${entry#*,}"
		local gw="${entry%%,*}"
		entry="${entry#*,}"
		local valid="${entry%%,*}"
		entry="${entry#*,}"
		local metric="${entry%%,*}"

		if [ -n "$gw" ]; then
			ip -6 route add "$addr" via "$gw" metric "$metric" dev "$device" from "::/128"
		else
			ip -6 route add "$addr" metric "$metric" dev "$device"
		fi

		for prefix in $PREFIXES; do
			local paddr="${prefix%%,*}"
			[ -n "$gw" ] && ip -6 route add "$addr" via "$gw" metric "$metric" dev "$device" from "$paddr"
		done
	done
}

teardown_interface() {
	local device="$1"
	ip -6 route flush dev "$device"
	ip -6 address flush dev "$device" scope global
	update_resolv "$device" ""
}

(
	flock 9
	case "$2" in
		bound)
			teardown_interface "$1"
			setup_interface "$1"
		;;
		informed|updated|rebound|ra-updated)
			setup_interface "$1"
		;;
		stopped|unbound)
			teardown_interface "$1"
		;;
		started)
			teardown_interface "$1"
		;;
	esac

	# user rules
	[ -f /etc/odhcp6c.user ] && . /etc/odhcp6c.user
) 9>/tmp/odhcp6c.lock.$1
rm -f /tmp/odhcp6c.lock.$1