summaryrefslogtreecommitdiffstats
path: root/package/network/services/lldpd/files/lldpd.init
blob: 67ee011ae235416e0cc108e896ef474ad8115662 (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
#!/bin/sh /etc/rc.common
# Copyright (C) 2008-2015 OpenWrt.org
# shellcheck disable=1091,2034,3037,3043,3045

START=90
STOP=01

CONFIG_LLDPD_WITH_CDP=y
CONFIG_LLDPD_WITH_EDP=y
CONFIG_LLDPD_WITH_FDP=y
CONFIG_LLDPD_WITH_LLDPMED=y
CONFIG_LLDPD_WITH_SNMP=y
CONFIG_LLDPD_WITH_SONMP=y

USE_PROCD=1
LLDPDBIN=/usr/sbin/lldpd
LLDPCLI=/usr/sbin/lldpcli
LLDPSOCKET=/var/run/lldpd.socket
LLDPD_CONF=/tmp/lldpd.conf
LLDPD_CONFS_DIR=/tmp/lldpd.d

LLDPD_RUN=/var/run/lldpd
LLDPD_RESTART_HASH=${LLDPD_RUN}/lldpd.restart_hash

. "$IPKG_INSTROOT/lib/functions/network.sh"

find_release_info()
{
	[ -s /etc/os-release ] && . /etc/os-release
	[ -z "$PRETTY_NAME" ] && [ -s /etc/openwrt_version ] && \
		PRETTY_NAME="$(cat /etc/openwrt_version)"

	echo "${PRETTY_NAME:-Unknown OpenWrt release} @ $(cat /proc/sys/kernel/hostname)"
}

get_config_restart_hash() {
	local var="$1"
	local _string _hash v

	config_load 'lldpd'

	config_get      v 'config' 'lldp_class'; append _string "$v" ","
	if [ "$CONFIG_LLDPD_WITH_SNMP" = "y" ]; then
		config_get      v 'config' 'agentxsocket'; append _string "$v" ","
	fi
	config_get      v 'config' 'cid_interface'; append _string "$v" ","
	config_get      v 'config' 'filter'; append _string "$v" ","
	config_get_bool v 'config' 'readonly_mode'; append _string "$v" ","
	config_get_bool v 'config' 'lldp_no_version'; append _string "$v" ","
	if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then
		config_get_bool v 'config' 'lldpmed_no_inventory'; append _string "$v" ","
	fi
	config_get_bool v 'config' 'enable_lldp' 1; append _string "$v" ","
	config_get_bool v 'config' 'force_lldp'; append _string "$v" ","
	if [ "$CONFIG_LLDPD_WITH_CDP" = "y" ]; then
		config_get_bool v 'config' 'enable_cdp'; append _string "$v" ","
		config_get      v 'config' 'cdp_version'; append _string "$v" ","
		config_get_bool v 'config' 'force_cdp'; append _string "$v" ","
		config_get_bool v 'config' 'force_cdpv2'; append _string "$v" ","
	fi
	if [ "$CONFIG_LLDPD_WITH_EDP" = "y" ]; then
		config_get_bool v 'config' 'enable_edp'; append _string "$v" ","
		config_get_bool v 'config' 'force_edp'; append _string "$v" ","
	fi
	if [ "$CONFIG_LLDPD_WITH_FDP" = "y" ]; then
		config_get_bool v 'config' 'enable_fdp'; append _string "$v" ","
		config_get_bool v 'config' 'force_fdp'; append _string "$v" ","
	fi
	if [ "$CONFIG_LLDPD_WITH_SONMP" = "y" ]; then
		config_get_bool v 'config' 'enable_sonmp'; append _string "$v" ","
		config_get_bool v 'config' 'force_sonmp'; append _string "$v" ","
	fi

	_hash=$(echo -n "${_string}" | md5sum | awk '{ print $1 }')
	export -n "$var=$_hash"
}

get_config_cid_ifaces() {
	local _ifaces
	config_get _ifaces 'config' "$2"

	local _iface _ifnames=""
	for _iface in $_ifaces; do
		local _ifname=""
		if network_get_device _ifname "$_iface" || [ -e "/sys/class/net/$_iface" ]; then
			append _ifnames "${_ifname:-$_iface}" ","
		fi
	done

	export -n "${1}=$_ifnames"
}

write_lldpd_conf()
{
	local lldp_description

	config_load 'lldpd'
	config_get lldp_description 'config' 'lldp_description' "$(find_release_info)"

	local lldp_hostname
	config_get lldp_hostname 'config' 'lldp_hostname' "$(cat /proc/sys/kernel/hostname)"

	local ifnames
	get_config_cid_ifaces ifnames "interface"

	local lldp_mgmt_ip
	config_get lldp_mgmt_ip 'config' 'lldp_mgmt_ip'

	local lldp_syscapabilities
	config_get lldp_syscapabilities 'config' 'lldp_syscapabilities'

	if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then
		local lldpmed_fast_start
		config_get_bool lldpmed_fast_start 'config' 'lldpmed_fast_start' 0

		local lldpmed_fast_start_tx_interval
		config_get lldpmed_fast_start_tx_interval 'config' 'lldpmed_fast_start_tx_interval' 0

		local lldp_location
		config_get lldp_location 'config' 'lldp_location'

		local lldp_class
		config_get lldp_class 'config' 'lldp_class'

		local lldp_policy
		config_get lldp_policy 'config' 'lldp_policy'

	fi

	local lldp_agenttype
	config_get lldp_agenttype 'config' 'lldp_agenttype' 'nearest-bridge'

	local lldp_portidsubtype
	config_get lldp_portidsubtype 'config' 'lldp_portidsubtype' 'macaddress'

	local lldp_platform
	config_get lldp_platform 'config' 'lldp_platform' ""

	local lldp_tx_interval
	config_get lldp_tx_interval 'config' 'lldp_tx_interval' 0

	local lldp_tx_hold
	config_get lldp_tx_hold 'config' 'lldp_tx_hold' 0

	# Clear out the config file first
	echo -n > "$LLDPD_CONF"
	[ -n "$ifnames" ] && echo "configure system interface pattern $ifnames" >> "$LLDPD_CONF"
	[ -n "$lldp_description" ] && echo "configure system description" "\"$lldp_description\"" >> "$LLDPD_CONF"
	[ -n "$lldp_hostname" ] && echo "configure system hostname" "\"$lldp_hostname\"" >> "$LLDPD_CONF"
	[ -n "$lldp_mgmt_ip" ] && echo "configure system ip management pattern" "\"$lldp_mgmt_ip\"" >> "$LLDPD_CONF"
	[ -n "$lldp_syscapabilities" ] && echo "configure system capabilities enabled $lldp_syscapabilities" >> "$LLDPD_CONF"
	if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ] && [ "$lldpmed_fast_start" -gt 0 ]; then
		if [ "$lldpmed_fast_start_tx_interval" -gt 0 ]; then
			echo "configure med fast-start tx-interval $lldpmed_fast_start_tx_interval" >> "$LLDPD_CONF"
		else
			echo "configure med fast-start enable" >> "$LLDPD_CONF"
		fi
	fi
	if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then
		# other 'configure med xxx' statements go here

		[ -n "$lldp_location" ] && echo "configure med location" "$lldp_location" >> "$LLDPD_CONF"

		# Manual states that if Class (-M) is 2 or 3, at least one network policy must be defined
		case "$lldp_class" in
			2 | 3 ) [ -n "$lldp_policy" ] && echo "configure med policy $lldp_policy" >> "$LLDPD_CONF"
			;;
		esac

	fi

	[ -n "$lldp_agenttype" ] && echo "configure lldp agent-type" "\"$lldp_agenttype\"" >> "$LLDPD_CONF"
	[ -n "$lldp_portidsubtype" ] && echo "configure lldp portidsubtype" "\"$lldp_portidsubtype\"" >> "$LLDPD_CONF"
	[ -n "$lldp_platform" ] && echo "configure system platform" "\"$lldp_platform\"" >> "$LLDPD_CONF"
	[ -n "$lldp_tx_interval" ] && echo "configure lldp tx-interval $lldp_tx_interval" >> "$LLDPD_CONF"
	[ "$lldp_tx_hold" -gt 0 ] && echo "configure lldp tx-hold $lldp_tx_hold" >> "$LLDPD_CONF"

	# Since lldpd's sysconfdir is /tmp, we'll symlink /etc/lldpd.d to /tmp/$LLDPD_CONFS_DIR
	[ -e "$LLDPD_CONFS_DIR" ] || ln -s /etc/lldpd.d "$LLDPD_CONFS_DIR"
}

start_service() {

	local enable_lldp
	local force_lldp
	local enable_cdp
	local cdp_version
	local force_cdp
	local force_cdpv2
	local enable_fdp
	local force_fdp
	local enable_sonmp
	local force_sonmp
	local enable_edp
	local force_edp
	local lldp_class
	local lldp_no_version
	local lldpmed_no_inventory
	local readonly_mode
	local agentxsocket
	local filter

	config_load 'lldpd'
	config_get_bool enable_lldp 'config' 'enable_lldp' 1
	config_get_bool force_lldp 'config' 'force_lldp' 0
	if [ "$CONFIG_LLDPD_WITH_CDP" = "y" ]; then
		config_get_bool enable_cdp 'config' 'enable_cdp' 0
		config_get cdp_version 'config' 'cdp_version' 'cdpv1v2'
		config_get_bool force_cdp 'config' 'force_cdp' 0
		config_get_bool force_cdpv2 'config' 'force_cdpv2' 0
	fi
	if [ "$CONFIG_LLDPD_WITH_FDP" = "y" ]; then
		config_get_bool enable_fdp 'config' 'enable_fdp' 0
		config_get_bool force_fdp 'config' 'force_fdp' 0
	fi
	if [ "$CONFIG_LLDPD_WITH_SONMP" = "y" ]; then
		config_get_bool enable_sonmp 'config' 'enable_sonmp' 0
		config_get_bool force_sonmp 'config' 'force_sonmp' 0
	fi
	if [ "$CONFIG_LLDPD_WITH_EDP" = "y" ]; then
		config_get_bool enable_edp 'config' 'enable_edp' 0
		config_get_bool force_edp 'config' 'force_edp' 0
	fi
	config_get lldp_class 'config' 'lldp_class'
	config_get_bool lldp_no_version 'config' 'lldp_no_version' 0
	if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then
		config_get_bool lldpmed_no_inventory 'config' 'lldpmed_no_inventory' 0
	fi
	config_get_bool readonly_mode 'config' 'readonly_mode' 0
	if [ "$CONFIG_LLDPD_WITH_SNMP" = "y" ]; then
		config_get agentxsocket 'config' 'agentxsocket'
	fi
	config_get filter 'config' 'filter' 15

	mkdir -p ${LLDPD_RUN}
	chown lldp:lldp ${LLDPD_RUN}

	# When lldpd starts, it also loads up what we write in this config file
	write_lldpd_conf

	procd_open_instance
	procd_set_param command ${LLDPDBIN}
	procd_append_param command -d

	if [ "$enable_lldp" -gt 0 ]; then
		if [ "$force_lldp" -gt 0 ]; then
			procd_append_param command '-l'
		fi
	else
		# Disable LLDP
		procd_append_param command '-ll'
	fi

	if [ "$CONFIG_LLDPD_WITH_CDP" = "y" ] && [ "$enable_cdp" -gt 0 ]; then
		if [ "$cdp_version" = "cdpv2" ]; then
			if [ "$force_cdp" -gt 0 ]; then
				# CDPv1 disabled, CDPv2 forced
				procd_append_param command '-ccccc'
			else
				# CDPv1 disabled, CDPv2 enabled
				procd_append_param command '-cccc'
			fi
		elif [ "$cdp_version" = "cdpv1v2" ]; then
			if [ "$force_cdp" -gt 0 ] && [ "$force_cdpv2" -gt 0 ]; then
				# CDPv1 enabled, CDPv2 forced
				procd_append_param command '-ccc'
			elif [ "$force_cdp" -gt 0 ]; then
				# CDPv1 forced, CDPv2 enabled
				procd_append_param command '-cc'
			else
				# CDPv1 and CDPv2 enabled
				procd_append_param command '-c'
			fi
		fi
	fi

	if [ "$CONFIG_LLDPD_WITH_FDP" = "y" ] && [ "$enable_fdp" -gt 0 ]; then
		if [ "$force_fdp" -gt 0 ]; then
			# FDP enabled and forced
			procd_append_param command '-ff'
		else
			# FDP enabled
			procd_append_param command '-f'
		fi
	fi

	if [ "$CONFIG_LLDPD_WITH_SONMP" = "y" ] && [ "$enable_sonmp" -gt 0 ]; then
		if [ "$force_sonmp" -gt 0 ]; then
			# SONMP enabled and forced
			procd_append_param command '-ss'
		else
			# SONMP enabled
			procd_append_param command '-s'
		fi
	fi

	if [ "$CONFIG_LLDPD_WITH_EDP" = "y" ] && [ "$enable_edp" -gt 0 ]; then
		if [ "$force_edp" -gt 0 ]; then
			# EDP enabled and forced
			procd_append_param command '-ee'
		else
			# EDP enabled
			procd_append_param command '-e'
		fi
	fi

	[ "$readonly_mode" -gt 0 ] && procd_append_param command '-r'
	[ "$lldp_no_version" -gt 0 ] && procd_append_param command '-k'
	[ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ] && [ "$lldpmed_no_inventory" -gt 0 ] && procd_append_param command '-i'
	[ -n "$lldp_class" ] && procd_append_param command -M "$lldp_class"
	[ "$CONFIG_LLDPD_WITH_SNMP" = "y" ] && [ -n "$agentxsocket" ] && procd_append_param command -x -X "$agentxsocket"
	[ -n "$filter" ] && procd_append_param command -H "$filter"

    # ChassisID interfaces
	local ifnames
	get_config_cid_ifaces ifnames "cid_interface"

	[ -n "$ifnames" ] && procd_append_param command -C "$ifnames"

    # Overwrite default configuration locations processed by lldpcli at start
	procd_append_param command -O "$LLDPD_CONF"

	local restart_hash
	get_config_restart_hash restart_hash
	echo -n "$restart_hash" > "$LLDPD_RESTART_HASH"

	# set auto respawn behavior
	procd_set_param respawn
	procd_close_instance
}

service_triggers() {
	procd_add_config_trigger "config.change" "lldpd" /etc/init.d/lldpd reload
}

reload_service() {
	running || return 1
	
	local running_hash=""
	local config_hash=""

	get_config_restart_hash config_hash
	[ -f ${LLDPD_RESTART_HASH} ] && running_hash=$(cat "$LLDPD_RESTART_HASH")

	if [ "x$running_hash" != "x$config_hash" ]; then
		# Restart LLDPd
		# Some parameters can't be configured at runtime
		restart
		return 0
	fi

	$LLDPCLI -u "$LLDPSOCKET" 2>&1 /dev/null <<-EOF
		pause
		unconfigure lldp custom-tlv
		unconfigure system interface pattern
		unconfigure system description
		unconfigure system hostname
		unconfigure system ip management pattern
		unconfigure system platform
	EOF
	if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then
		$LLDPCLI -u "$LLDPSOCKET" 2>&1 /dev/null <<-EOF
			unconfigure med fast-start
		EOF

	fi
	# Rewrite lldpd.conf
	# If something changed it should be included by the lldpcli call
	write_lldpd_conf
	$LLDPCLI -u "$LLDPSOCKET" -c "$LLDPD_CONF" -c "$LLDPD_CONFS_DIR" 2>&1 /dev/null
	# Broadcast update over the wire
	$LLDPCLI -u "$LLDPSOCKET" 2>&1 /dev/null <<-EOF
		resume
		update
	EOF
	return 0
}

stop_service() {
	rm -rf ${LLDPD_RUN} "$LLDPSOCKET" 2> /dev/null
}