]> git.ipfire.org Git - thirdparty/lldpd.git/blob - README.md
build: update two additional docker actions
[thirdparty/lldpd.git] / README.md
1 # lldpd: implementation of IEEE 802.1ab (LLDP)
2
3 ![Build Status](https://github.com/lldpd/lldpd/workflows/CI/badge.svg)
4
5 https://lldpd.github.io/
6
7 ## Features
8
9 LLDP (Link Layer Discovery Protocol) is an industry standard protocol
10 designed to supplant proprietary Link-Layer protocols such as
11 Extreme's EDP (Extreme Discovery Protocol) and CDP (Cisco Discovery
12 Protocol). The goal of LLDP is to provide an inter-vendor compatible
13 mechanism to deliver Link-Layer notifications to adjacent network
14 devices.
15
16 lldpd implements both reception and sending. It also implements an
17 SNMP subagent for net-snmp to get local and remote LLDP
18 information. The LLDP-MIB is partially implemented but the most useful
19 tables are here. lldpd also partially implements LLDP-MED.
20
21 lldpd supports bridge, vlan and bonding.
22
23 The following OS are supported:
24
25 * FreeBSD
26 * GNU/Linux
27 * macOS
28 * NetBSD
29 * OpenBSD
30 * Solaris
31
32 Windows is not supported but you can use
33 [WinLLDPService](https://github.com/raspi/WinLLDPService/) as a
34 transmit-only agent.
35
36 ## Installation
37
38 For general instructions [prefer the
39 website](https://lldpd.github.io/installation.html),
40 including building from released tarballs.
41
42 To compile lldpd from Git, use the following commands:
43
44 ./autogen.sh
45 ./configure
46 make
47 sudo make install
48
49 lldpd uses privilege separation to increase its security. Two
50 processes, one running as root and doing minimal stuff and the other
51 running as an unprivileged user into a chroot doing most of the stuff,
52 are cooperating. You need to create a user called `_lldpd` in a group
53 `_lldpd` (this can be change with `./configure`). You also need to
54 create an empty directory `/usr/local/var/run/lldpd` (it needs to be
55 owned by root, not `_lldpd`!). If you get fuzzy timestamps from
56 syslog, copy `/etc/locatime` into the chroot.
57
58 `lldpcli` lets one query information collected through the command
59 line. If you don't want to run it as root, just install it setuid or
60 setgid `_lldpd`.
61
62 ## Installation (Docker)
63
64 You can use Docker to run `lldpd`:
65
66 docker run --rm --net=host --uts=host \
67 -v /etc/os-release:/etc/os-release \
68 --cap-add=NET_RAW --cap-add=NET_ADMIN \
69 --name lldpd \
70 ghcr.io/lldpd/lldpd:latest
71
72 In place of `latest` which provides you with the latest stable
73 version, you may use `1`, `1.0`, `1.0.12` to match specific versions,
74 or `master` to get the development version.
75
76 To execute `lldpcli`, use:
77
78 docker exec lldpd lldpcli show neighbors
79
80 Or to get the command-line:
81
82 docker exec -it lldpd lldpcli
83
84 ## Installation (macOS)
85
86 The same procedure as above applies for macOS. However, there are
87 simpler alternatives:
88
89 1. Use [Homebrew](https://brew.sh):
90
91 brew install lldpd
92 # Or, for the latest version:
93 brew install https://raw.github.com/lldpd/lldpd/master/osx/lldpd.rb
94
95 2. Build an OS X installer package which should work on the same
96 version of OS X (it is important to use a separate build
97 directory):
98
99 mkdir build && cd build
100 ../configure --prefix=/usr/local --localstatedir=/var --sysconfdir=/private/etc --with-embedded-libevent \
101 --without-snmp
102 make -C osx pkg
103
104 If you want to compile for an older version of macOS, you need
105 commands like those:
106
107 mkdir build && cd build
108 ../configure --prefix=/usr/local --localstatedir=/var --sysconfdir=/private/etc --with-embedded-libevent \
109 --without-snmp \
110 CFLAGS="-mmacosx-version-min=11.1" \
111 LDFLAGS="-mmacosx-version-min=11.1"
112 make -C osx pkg
113
114 You can check with `otool -l` that you got what you expected in
115 term of supported versions. If you are running on ARM64, you can
116 configure a binary supporting both architectures by adding
117 `ARCHS="arm64 x86_64"` to the arguments of the `make` command.
118
119 If you don't follow the above procedures, you will have to create the
120 user/group `_lldpd`. Have a look at how this is done in
121 `osx/scripts/postinstall`.
122
123 ## Installation (Android)
124
125 1. Don't clone the repo or download the master branch from GitHub. Instead, download the official release from the website [https://lldpd.github.io/](https://lldpd.github.io/installation.html#install-from-source). Unpack into a working directory.
126
127 2. Download the [Android NDK](https://developer.android.com/ndk/downloads#stable-downloads) (version 22 or later). Unpack into a working directory next to the `lldpd` directory.
128
129 3. Install `automake`, `libtool`, and `pkg-config`. (`sudo apt-get install automake libtool pkg-config`)
130
131 4. In the root of the `lldpd` directory, make a `compile.sh` file containing this script:
132 ```sh
133 export TOOLCHAIN=$PWD/android-ndk/toolchains/llvm/prebuilt/linux-x86_64
134 export TARGET=armv7a-linux-androideabi
135 export API=30
136 # DO NOT TOUCH BELOW
137 export AR=$TOOLCHAIN/bin/llvm-ar
138 export CC=$TOOLCHAIN/bin/$TARGET$API-clang
139 export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
140 export LD=$TOOLCHAIN/bin/ld
141 export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
142 export STRIP=$TOOLCHAIN/bin/llvm-strip
143 export AS=$CC
144 ./autogen.sh
145 mkdir -p build && cd build
146 ../configure \
147 --host=$TARGET \
148 --with-sysroot=$TOOLCHAIN/sysroot \
149 --prefix=/system \
150 --sbindir=/system/bin \
151 --runstatedir=/data/data/lldpd \
152 --with-privsep-user=root \
153 --with-privsep-group=root \
154 PKG_CONFIG=/bin/false
155 make
156 make install DESTDIR=$PWD/install
157 ```
158
159 5. In the **Android NDK** directory, locate the `toolchains/llvm/prebuilt/linux-x86_64` directory and change the `TOOLCHAIN` variable of the above script to match the path where the `linux-x86_64` directory resides.
160
161 ```sh
162 export TOOLCHAIN=$PWD/android-ndk-r22b-linux-x86_64/android-ndk-r22b/toolchains/llvm/prebuilt/linux-x86_64
163 ```
164
165 6. Determine the CPU architecture target (`adb shell getprop ro.product.cpu.abi`). Change the `TARGET` variable in the above script to match the target architecture. The target name will not exactly match the output of the `adb` command as there will be a trailing suffix to the target name, so look in the `linux-x86_64/bin` directory for the `clang` file that starts with the CPU architecture target. Don't include the API version in the target name.
166 ```sh
167 $ adb shell getprop ro.product.cpu.abi
168 armeabi-v7a
169 ```
170 ```sh
171 linux-x86_64/bin$ ls *-clang
172 aarch64-linux-android21-clang armv7a-linux-androideabi23-clang i686-linux-android26-clang
173 aarch64-linux-android22-clang armv7a-linux-androideabi24-clang i686-linux-android27-clang
174 aarch64-linux-android23-clang armv7a-linux-androideabi26-clang i686-linux-android28-clang
175 aarch64-linux-android24-clang armv7a-linux-androideabi27-clang i686-linux-android29-clang
176 aarch64-linux-android26-clang armv7a-linux-androideabi28-clang i686-linux-android30-clang
177 aarch64-linux-android27-clang armv7a-linux-androideabi29-clang x86_64-linux-android21-clang
178 aarch64-linux-android28-clang armv7a-linux-androideabi30-clang x86_64-linux-android22-clang
179 aarch64-linux-android29-clang i686-linux-android16-clang x86_64-linux-android23-clang
180 aarch64-linux-android30-clang i686-linux-android17-clang x86_64-linux-android24-clang
181 armv7a-linux-androideabi16-clang i686-linux-android18-clang x86_64-linux-android26-clang
182 armv7a-linux-androideabi17-clang i686-linux-android19-clang x86_64-linux-android27-clang
183 armv7a-linux-androideabi18-clang i686-linux-android21-clang x86_64-linux-android28-clang
184 armv7a-linux-androideabi19-clang i686-linux-android22-clang x86_64-linux-android29-clang
185 armv7a-linux-androideabi21-clang i686-linux-android23-clang x86_64-linux-android30-clang
186 armv7a-linux-androideabi22-clang i686-linux-android24-clang
187 ```
188 ```sh
189 export TARGET=armv7a-linux-androideabi
190 ```
191
192 7. Set the `API` variable in the script above to your target API version. Check in the same `linux-x86_64/bin` to ensure the API you are targeting has a supported `clang` file for that CPU architecture and version. As of this writing, there is support for API `21-30` included for all architectures and some CPU architectures supported back to version `16`.
193 ```sh
194 export API=30
195 ```
196
197 8. Run the compile script (`./compile.sh`).
198
199 9. Copy the `./bin/*` and `./lib/*.so` files from `lldpd/build/install/system` to the target system (`./bin/*` to `/system/bin`, `./lib/*.so` to `/system/lib64`):
200 ```sh
201 # Push files to target
202 cd build/install/system
203 adb shell mkdir -p /sdcard/Download/lldpd/bin
204 adb push bin/lldpcli /sdcard/Download/lldpd/bin/lldpcli
205 adb push bin/lldpd /sdcard/Download/lldpd/bin/lldpd
206 adb shell mkdir -p /sdcard/Download/lldpd/lib64
207 adb push lib/liblldpctl.so /sdcard/Download/lldpd/lib64/liblldpctl.so
208
209 # Enter target shell and move files
210 adb shell
211 # Run as root for all commands
212 $ su
213 # Make /system writeable
214 $ mount -o rw,remount /system
215 $ mv /sdcard/Download/lldpd/bin/lldpcli /system/bin/lldpcli
216 $ chmod 755 /system/bin/lldpcli
217 $ chown root:shell /system/bin/lldpcli
218 $ mv /sdcard/Download/lldpd/bin/lldpd /system/bin/lldpd
219 $ chmod 755 /system/bin/lldpd
220 $ chown root:shell /system/bin/lldpd
221 # $ touch /system/bin/lldpctl
222 # $ chmod 755 /system/bin/lldpctl
223 # $ chown root:shell /system/bin/lldpctl
224 $ mv /sdcard/Download/lldpd/lib64/liblldpctl.so /system/lib64/liblldpctl.so
225 $ chmod 644 /system/lib64/liblldpctl.so
226 $ chown root:root /system/lib64/liblldpctl.so
227 # Make /system readonly again
228 $ mount -o ro,remount /system
229 # Might not be necessary on some systems
230 $ mkdir /data/data/lldpd
231 $ chmod 700 /data/data/lldpd
232 $ chown shell:shell /data/data/lldpd
233 # Clean up
234 $ rm -rf /sdcard/Download/lldpd
235 ```
236
237 ## Usage
238
239 lldpd also implements CDP (Cisco Discovery Protocol), FDP (Foundry
240 Discovery Protocol), SONMP (Nortel Discovery Protocol) and EDP
241 (Extreme Discovery Protocol). However, recent versions of IOS should
242 support LLDP and most Extreme stuff support LLDP. When a EDP, CDP or
243 SONMP frame is received on a given interface, lldpd starts sending
244 EDP, CDP, FDP or SONMP frame on this interface. Informations collected
245 through EDP/CDP/FDP/SONMP are integrated with other informations and
246 can be queried with `lldpcli` or through SNMP.
247
248 More information:
249 * http://en.wikipedia.org/wiki/Link_Layer_Discovery_Protocol
250 * http://standards.ieee.org/getieee802/download/802.1AB-2005.pdf
251 * https://gitlab.com/wireshark/wireshark/-/wikis/LinkLayerDiscoveryProtocol
252
253 ## Compatibility with older kernels
254
255 If you have a kernel older than Linux 2.6.39, you need to compile
256 lldpd with `--enable-oldies` to enable some compatibility functions:
257 otherwise, lldpd will only rely on Netlink to receive bridge, bond and
258 VLAN information.
259
260 For bonding, you need 2.6.24 (in previous version, PACKET_ORIGDEV
261 affected only non multicast packets). See:
262
263 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=80feaacb8a6400a9540a961b6743c69a5896b937
264 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=8032b46489e50ef8f3992159abd0349b5b8e476c
265
266 Otherwise, a packet received on a bond will be affected to all
267 interfaces of the bond. In this case, lldpd will affect a received
268 randomly to one of the interface (so a neighbor may be affected to the
269 wrong interface).
270
271 On 2.6.27, we are able to receive packets on real interface for enslaved
272 devices. This allows one to get neighbor information on active/backup
273 bonds. Without the 2.6.27, lldpd won't receive any information on
274 inactive slaves. Here are the patchs (thanks to Joe Eykholt):
275
276 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0d7a3681232f545c6a59f77e60f7667673ef0e93
277 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=cc9bd5cebc0825e0fabc0186ab85806a0891104f
278 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f982307f22db96201e41540295f24e8dcc10c78f
279
280 On FreeBSD, only a recent 9 kernel (9.1 or more recent) will allow to
281 send LLDP frames on enslaved devices. See this bug report for more
282 information:
283
284 * http://www.freebsd.org/cgi/query-pr.cgi?pr=138620
285
286 Some devices (notably Cisco IOS) send frames tagged with the native
287 VLAN while they should send them untagged. If your network card does
288 not support accelerated VLAN, you will receive those frames as long as
289 the corresponding interface exists (see below). However, if your
290 network card handles VLAN encapsulation/decapsulation (check with
291 `ethtool -k`), you need a recent kernel to be able to receive those
292 frames without listening on all available VLAN. Starting from Linux
293 2.6.27, lldpd is able to capture VLAN frames when VLAN acceleration is
294 supported by the network card. Here is the patch:
295
296 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=bc1d0411b804ad190cdadabac48a10067f17b9e6
297
298 On some other versions, frames are sent on VLAN 1. If this is not the
299 native VLAN and if your network card support accelerated VLAN, you
300 need to subscribe to this VLAN as well. The Linux kernel does not
301 provide any interface for this. The easiest way is to create the VLAN
302 for each port:
303
304 ip link add link eth0 name eth0.1 type vlan id 1
305 ip link set up dev eth0.1
306
307 You can check both cases using tcpdump:
308
309 tcpdump -epni eth0 ether host 01:80:c2:00:00:0e
310 tcpdump -eni eth0 ether host 01:80:c2:00:00:0e
311
312 If the first command does not display received LLDP packets but the
313 second one does, LLDP packets are likely encapsulated into a VLAN:
314
315 10:54:06.431154 f0:29:29:1d:7c:01 > 01:80:c2:00:00:0e, ethertype 802.1Q (0x8100), length 363: vlan 1, p 7, ethertype LLDP, LLDP, name SW-APP-D07.VTY, length 345
316
317 In this case, just create VLAN 1 will fix the situation. There are
318 other solutions:
319
320 1. Disable VLAN acceleration on the receive side (`ethtool -K eth0
321 rxvlan off`) but this may or may not work. Check if there are
322 similar properties that could apply with `ethtool -k eth0`.
323 2. Put the interface in promiscuous mode with `ip link set
324 promisc on dev eth0`.
325
326 The last solution can be done directly by `lldpd` (on Linux only) by
327 using the option `configure system interface promiscuous`.
328
329 On modern networks, the performance impact should be nonexistent.
330
331 ## Development
332
333 During development, you may want to execute lldpd at its current
334 location instead of doing `make install`. The correct way to do this is
335 to issue the following command:
336
337 sudo libtool execute src/daemon/lldpd -L $PWD/src/client/lldpcli -d
338
339 You can append any further arguments. If lldpd is unable to find
340 `lldpcli` it will start in an unconfigured mode and won't send or
341 accept LLDP frames.
342
343 There is a general test suite with `make check`. It's also possible to
344 run integration tests. They need [pytest](http://pytest.org/latest/)
345 and rely on Linux containers to be executed.
346
347 To enable code coverage, use:
348
349 ../configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
350 --enable-sanitizers --enable-gcov --with-snmp \
351 CFLAGS="-O0 -g"
352 make
353 make check
354 # maybe, run integration tests
355 lcov --base-directory $PWD/src/lib \
356 --directory src --capture --output-file gcov.info
357 genhtml gcov.info --output-directory coverage
358
359 ## Fuzzing
360
361 ### With libfuzzer
362
363 ```
364 ./tests/fuzzer/build.sh ASan
365 ./tests/fuzzer/build.sh run
366 ```
367
368 ### With AFL
369
370 You can use [afl](http://lcamtuf.coredump.cx/afl/) to test some
371 aspects of lldpd. To test frame decoding, you can do something like
372 that:
373
374 export AFL_USE_ASAN=1 # only on 32bit arch
375 ./configure CC=afl-gcc
376 make clean check
377 cd tests
378 mkdir inputs
379 mv *.pcap inputs
380 afl-fuzz -i inputs -o outputs ./decode @@
381
382 ## Embedding
383
384 To embed lldpd into an existing system, there are two point of entries:
385
386 1. If your system does not use standard Linux interface, you can
387 support additional interfaces by implementing the appropriate
388 `struct lldpd_ops`. You can look at
389 `src/daemon/interfaces-linux.c` for examples. Also, have a look at
390 `interfaces_update()` which is responsible for discovering and
391 registering interfaces.
392
393 2. `lldpcli` provides a convenient way to query `lldpd`. It also
394 comes with various outputs, including XML which allows one to
395 parse its output for integration and automation purpose. Another
396 way is to use SNMP support. A third way is to write your own
397 controller using `liblldpctl.so`. Its API is described in
398 `src/lib/lldpctl.h`. The custom binary protocol between
399 `liblldpctl.so` and `lldpd` is not stable. Therefore, the library
400 should always be shipped with `lldpd`. On the other hand, programs
401 using `liblldpctl.so` can rely on the classic ABI rules.
402
403 ## Troubleshooting
404
405 You can use `tcpdump` to look after the packets received and send by
406 `lldpd`. To look after LLDPU, use:
407
408 tcpdump -s0 -vv -pni eth0 ether dst 01:80:c2:00:00:0e
409
410 Intel X710 cards may handle LLDP themselves, intercepting any incoming
411 packets. If you don't see anything through `tcpdump`, check if you
412 have such a card (with `lspci`) and stop the embedded LLDP daemon:
413
414 for f in /sys/kernel/debug/i40e/*/command; do
415 echo lldp stop > $f
416 done
417
418 This may also apply to the `ice` (Intel E8xx cards) driver. These
419 steps are not necessary with a recent version of `lldpd` (1.0.11+).
420
421 ## License
422
423 lldpd is distributed under the ISC license:
424
425 > Permission to use, copy, modify, and/or distribute this software for any
426 > purpose with or without fee is hereby granted, provided that the above
427 > copyright notice and this permission notice appear in all copies.
428 >
429 > THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
430 > WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
431 > MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
432 > ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
433 > WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
434 > ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
435 > OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
436
437 Also, `lldpcli` will be linked to GNU Readline (which is GPL licensed)
438 if available. To avoid this, use `--without-readline` as a configure
439 option.