[Swan-dev] printing IP addresses; reentrancy
D. Hugh Redelmeier
hugh at mimosa.com
Sun Jun 22 07:00:31 EEST 2014
I just spent a bunch of time to simplify how IP addresses get
formatted in libreswan.
- addrtot, while complete and powerful, is tedious to invoke.
- ip_str was easy to invoke in common cases but had problems
- it used a static buffer so
-it wasn't safe to use in more than one thread.
- It also wasn't safe to use more than once in the parameter list
of a call to a function, something easy to do accidentally.
- it was declared and defined several odd places.
lib/libswan/id.c (as pluto_ip_str)
programs/pluto/log.h (as a macro expanding to pluto_ip_str)
include/id.h (as pluto_ip_str)
The replacement is ipstr().
It is defined in linux/net/ipsec/addrtot.c. It is tiny and needs
addrtot() to function, so this seemed natural. It adds no
dependencies to addrtot.c.
It is declared in linux/include/libreswan.h, just like addrtot().
One slightly novel thing is the way memory for the resulting formatted
string is handled. The caller of ipstr has to provide an object of
type ipstr_buf that lasts as long as the string needs to be valid.
This type is not a string, but is considered opaque to the caller. It
happens to have enough space for the longest possible string.
Typically, the string needs to live as long as the call to a function.
So a local variable of type ipstr_buf does the job. One for each
ipstr result string live during a call.
We should try to avoid non-reentrant formatting routines, even though
they are convenient. It is sometimes hard to notice when they cause
enum_showb (the reentrant version of enum_show) is a little more
intricate to use than ipstr because the buffer needed doesn't have a
simple known compile-time bound. That applies to bitnamesofb too.
Using malloc to solve the problem seems expensive, awkward, and
Please use the reentrant versions of these routines when it isn't too
difficult or awkward.
More information about the Swan-dev