Contributed by weerd on from the discovery-of-layered-links dept.
In this article we'll have a quick look at this nice little tool, and find out some of the design decisions that went into it.
ladvd is, according to the port's descripton, a "link advertisement (LLDP/CDP etc) daemon". The software is ISC licensed and somewhat similar in design to many standard OpenBSD daemons. It can announce certain host-specific details to the network via several link advertisement protocols (such as LLDP, CDP, EDP and others).
This version adds (amongst others) support to receive announcements from connected equipment (usually a switch). On OpenBSD, the received data can then be stored in the interface description via the SIOCSIFDESCR ioctl.
I spoke with Sten Spans, author of ladvd, about its design and planned developments :
OpenBSD Journal: How much of ladvd development is done on OpenBSD ?
Sten Spans: The BSD codepaths are written and tested primarily on OpenBSD and afterwards verified on FreeBSD. Most of the software interfaces I talk to originate on OpenBSD (trunk(4), bridge(4), ifdescr).
OJ: What sort of security issues are apparent with this sort of Link Advertisement protocol and how does ladvd cope with these issues ?
Sten: The fundametal problem here is that, because we are dealing with raw ethernet protocols (LLDP, CDP, EDP, etc), ladvd needs raw Ethernet sockets. Sending Link Advertisement packets securely isn't too difficult to do, since the traffic is always sent to specific MAC addresses and the BPF(4) filedescriptor can be opened write-only, fitted with an outgoing BPF filter and then secured via BIOCLOCK. Receiving link state announcements is more dangerous since you have to parse (possibly malicious) network data.
The current design locates the critical raw-sockets in a minimal master running as root, chrooted to /var/empty. A strict BPF filter is used and all parsing is done in the non-privileged child. The child talks to the master using a fixed protocol via a socketpair. Any violation will result in an abort of the master. Each protocol has a check routine which makes sure that the child can only send valid discovery packets.
OJ: In the previous version that was in the OpenBSD portstree (0.6), ladvd used privilege dropping and now you moved to privilege separation. Why this move, and did you use OpenBSD's source as an example or a source of inspiration while writing this code ?
Sten: Privdrop is safer because all the code runs without privileges. But to achieve optimal security for receive mode I needed to seperate the code into two processes. If both processes would run under the same uid then they could still influence each other (ptrace). The handling of untrusted input is now handled via a clear separation between the privileged and non-privileged code. While developing this implementation I examined sshd and syslogd. Like portable OpenSSH, I have a 'compat dir' with strlcpy(3) and friends (some of which are direct copies from the OpenBSD tree).
OJ: What was your experience in porting ladvd to OpenBSD ?
Sten: Having libevent in base is very nice. The privilege seperated design and receive mode added a lot of sockets to the daemon, so I used libevent to make those manageble. The advanced signal-handlers were a nice bonus, and also important for security.
In the buffering area (pipes and bpf), OpenBSD is a bit less friendly than FreeBSD and Linux, but this was not a serious problem given the large amount of sample code in the tree. My only real complaint is that OpenBSD does not have a tool to see ethernet multicast memberships, I ended up rebuilding NetBSD's ifmcstat.
OJ: Why would you need such a tool during your development ?
Sten: Ladvd needs to do multicast ethernet registrations to actually receive LLDP / CDP / etc packets. These packets are sent to special multicast ethernet addesses and normally discarded by the MAC filter on network interfaces. While testing the ladvd code, I needed to verify that these registrations were successful.
OJ: What is on the agenda for the next ladvd release ?
Sten: As requested by some OpenBSD developers, I'm improving the ifdescr support, adding port details and some general cleanups. The new version allows you to see what port on a switch you are connected to, and improves support for running in an environment with multiple link advertisement protocols. For future releases I have plans for a cli to display all the received information, and (the horror) SNMP support to fully implement the LLDP specification.
The coolest feature to add would be custom LLDP fields, but that would require an IEEE OUI which costs money. Another feature still missing is vlan support, some of the supported discovery protocols have support for this kind of information, but ladvd currently lacks code to do useful stuff in this area. The fundamental problem here is that Unix deals with vlans quite differently than a switch (vlan 3 on one interface doesn't automatically exchange traffic with vlan 3 on another interface).
OJ: Thanks, Sten, for your time and for a nice tool.
Running ladvd on a -current machine gives the following interface descriptions :
[weerd@doom] $ ifconfig bge0 bge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500 lladdr 00:03:ba:5a:58:b9 description: connected to sw1.bit-1.network.bit.nl (CDP) priority: 0 groups: egress media: Ethernet autoselect (1000baseT full-duplex) status: active inet 22.214.171.124 netmask 0xffffffc0 broadcast 126.96.36.199 inet6 fe80::203:baff:fe5a:58b9%bge0 prefixlen 64 scopeid 0x1 inet6 2001:7b8:3:47:203:baff:fe5a:58b9 prefixlen 64 autoconf pltime 604790 vltime 2591990
And on the switch we see :
Device ID Local Intrfce Holdtme Capability Platform Port ID doom.weirdnet.nl Gig 0/23 173 H OpenBSD bge0
Obviously, this tool is not very useful for small home setups with two or three machines connected via a simple unmanaged switch. Larger networks, with multiple OpenBSD machines and managable switches, however, can benefit from a simple daemon like this.
(Comments are closed)