This involves a fair amount of refactoring and will be difficult to
review; apologies in advance. I will try to describe the major changes
here.
rtsold performs five operations that don't work in capability mode:
1 Using sendmsg(2) with a non-NULL msg_name to send Router
Solicitations to the all-routers multicast address of each interface.
This is solved by pre-opening a socket for each interface and pre-setting
the destination address using connect(2). This is the ifi_sock field of
each struct ifinfo. Since the set of interfaces managed by rtsol(d) is
static, this works reasonably well. These sockets are used for nothing
except to send Router Solicitations.
2 When -m is specified, reading the ND6 default router list (exposed by
a sysctl) and sending probes (IPv6 messages with no content) to them
using sendmsg(2) and msg_name.
This is solved using a libcasper service. This is implemented in
cap_probe.c. The probe capability is needed only when -m is specified.
3 Invoking resolvconf(8) and potentially another script (specified with
-O) in response to certain Router Advertisements.
This is solved using a libcasper service. The service is pretty
simplistic; rtsold will only ever invoke two different scripts (just one
if -O is not specified), so the service creates a pipe, does a
fork()+execve(), and returns the write end of the pipe to the main
process. The main process writes its input to the pipe, closes it, and
calls back into the service to reap the child. This service is
implemented in cap_script.c.
4 Calling syslog(3) and related functions.
This is solved using the cap_syslog capability provided by libcasper.
5 In response to a SIGUSR1, rtsold will open /var/run/rtsold.dump and
write its state there.
This is solved by pre-opening the dump file during initialization. One
downside of this is that a dump file will always be left behind after an
rtsol(d) invocation. I think this is a minor defect.
In the process I've done some code cleanup, though I've tried to refrain
from excessively polluting the review. I also switched the main loop
from poll(2) to kevent(2) since I think the result is a bit neater. I
got rid of the #ifndef SMALL conditionals which are used to omit code
from rtsol(8); the savings are minuscule, and the ifdefs hurt
readability and confuse Coverity.