[Swan-dev] pfkey2 extension sets

D. Hugh Redelmeier hugh at mimosa.com
Tue Mar 25 06:04:36 EET 2014

PF_Key messages are made up of lumps called "extensions".

Each extension has a type which is essentially a value from an enum 
sadb_extension_t (defined in linux/include/libreswan/pfkeyv2.h).

A comment before the definition of that enum says:

 * NOTE that there is a limit of 31 extensions due to current implementation
 * in pfkeyv2_ext_bits.c

It means that there is a limit on "extension types", not extensions.  I'll 
go fix that...


1) in linux/net/ipsec/pfkey_v2_ext_bits.c, the key table has entries of 
type pfkey_ext_track which is used to represent a set of extension types 
(a mechanism similar to lset_t in Pluto).

2) in linux/include/libreswan/pfkey.h, pfkey_ext_track is typedefed to
be the type uint64_t.

So: the limit mentioned in the comment would appear to be 64, not 32.


The table in linux/net/ipsec/pfkey_v2_ext_bits.c is initialized with
expressions like
                 	1ULL << SADB_EXT_RESERVED |
                                1ULL << SADB_EXT_ADDRESS_SRC |
whereas this would be more correct:
                 	(pfkey_ext_track)1 << SADB_EXT_RESERVED |
                                (pfkey_ext_track)1 << SADB_EXT_ADDRESS_SRC |


===> the pfkey code should have and use a macro like LELEM


Still other places compute a set from an element like this:
Example: linux/net/ipsec/pfkey_v2_parse.c.
Notice that this is a signed int expression: not very sensible for a


Formatted printing of these set values seems to cast them to unsigned
long long to format them.  This may or may not be a 64-bit type.  Why
not use PRIx64 for the format?  Oh and give it a name, defined
adjacent to pfkey_ext_track, so that the two definitions can be
updated in concert.

==> I suspect that 32 bits are actually enough.  But I haven't checked
very carefully.

Oh, and SADB_EXT_SA is defined in
whereas K_SADB_EXT_SA is defined in
to be the same value.  Luckily, by reference.  This pattern holds for
all extension types.

==> why do we have two sets of symbols for the same values?

==> why do we have two headers with the same basename?

The two sets of names are NOT co-extensive.  They differ from 20 on.

#define SADB_X_EXT_NAT_T_TYPE           20
        K_SADB_X_EXT_ADDRESS_DST2=  20,
        K_SADB_X_EXT_NAT_T_TYPE=    27,

==> how did this mess happen?  Can we fix it?

And another thing.  Lots of expressions on the sets seem to be

Example (notice odd use of arithmentic "-" as a set operation):
	(unsigned long long)(1 << SADB_EXT_SA) -
		(extensions_seen & (1 << SADB_EXT_SA))
	LELEM(SADB_EXT_SA) & ~extensions_seen

	(unsigned long long)K_SADB_X_EXT_ADDRESS_DELFLOW -
		(extensions_seen & K_SADB_X_EXT_ADDRESS_DELFLOW),
	K_SADB_X_EXT_ADDRESS_DELFLOW & ~extensions_seen

	extensions_seen =  1;
	extensions_seen = LELEM(K_SADB_EXT_RESERVED);

And another thing.
#define SADB_RESERVED	    0




=> surely K_SADB_EXT_RESERVED should be defined as SADB_EXT_RESERVED,
not SADB_RESERVED.  I'll fix that..

And I've only started looking.

More information about the Swan-dev mailing list