redirect-manager: Add helper function to create and parse REDIRECT notify data
The same encoding is also used for the REDIRECT_FROM notifies.
This commit is contained in:
@@ -17,6 +17,8 @@
|
||||
|
||||
#include <collections/linked_list.h>
|
||||
#include <threading/rwlock.h>
|
||||
#include <bio/bio_reader.h>
|
||||
#include <bio/bio_writer.h>
|
||||
|
||||
typedef struct private_redirect_manager_t private_redirect_manager_t;
|
||||
|
||||
@@ -41,6 +43,57 @@ struct private_redirect_manager_t {
|
||||
rwlock_t *lock;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gateway identify types
|
||||
*
|
||||
* The encoding is the same as that for corresponding ID payloads.
|
||||
*/
|
||||
typedef enum {
|
||||
/** IPv4 address of the VPN gateway */
|
||||
GATEWAY_ID_TYPE_IPV4 = 1,
|
||||
/** IPv6 address of the VPN gateway */
|
||||
GATEWAY_ID_TYPE_IPV6 = 2,
|
||||
/** FQDN of the VPN gateway */
|
||||
GATEWAY_ID_TYPE_FQDN = 3,
|
||||
} gateway_id_type_t;
|
||||
|
||||
/**
|
||||
* Mapping of gateway identity types to identity types
|
||||
*/
|
||||
static id_type_t gateway_to_id_type(gateway_id_type_t type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GATEWAY_ID_TYPE_IPV4:
|
||||
return ID_IPV4_ADDR;
|
||||
case GATEWAY_ID_TYPE_IPV6:
|
||||
return ID_IPV6_ADDR;
|
||||
case GATEWAY_ID_TYPE_FQDN:
|
||||
return ID_FQDN;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping of identity types to gateway identity types
|
||||
*/
|
||||
static gateway_id_type_t id_type_to_gateway(id_type_t type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ID_IPV4_ADDR:
|
||||
return GATEWAY_ID_TYPE_IPV4;
|
||||
case ID_IPV6_ADDR:
|
||||
return GATEWAY_ID_TYPE_IPV6;
|
||||
case ID_FQDN:
|
||||
return GATEWAY_ID_TYPE_FQDN;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(redirect_manager_t, add_provider, void,
|
||||
private_redirect_manager_t *this, redirect_provider_t *provider)
|
||||
{
|
||||
@@ -75,19 +128,16 @@ static bool should_redirect(private_redirect_manager_t *this, ike_sa_t *ike_sa,
|
||||
bool (**method)(void*,ike_sa_t*,identification_t**) = provider + offset;
|
||||
if (*method && (*method)(provider, ike_sa, gateway))
|
||||
{
|
||||
switch (*gateway ? (*gateway)->get_type(*gateway) : 0)
|
||||
if (*gateway && id_type_to_gateway((*gateway)->get_type(*gateway)))
|
||||
{
|
||||
case ID_IPV4_ADDR:
|
||||
case ID_IPV6_ADDR:
|
||||
case ID_FQDN:
|
||||
redirect = TRUE;
|
||||
break;
|
||||
default:
|
||||
DBG1(DBG_CFG, "redirect provider returned invalid gateway");
|
||||
DESTROY_IF(*gateway);
|
||||
continue;
|
||||
redirect = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_CFG, "redirect provider returned invalid gateway ID");
|
||||
DESTROY_IF(*gateway);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
@@ -140,3 +190,85 @@ redirect_manager_t *redirect_manager_create()
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encoding of a REDIRECT or REDIRECTED_FROM notify
|
||||
*
|
||||
1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Next Payload |C| RESERVED | Payload Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|Protocol ID(=0)| SPI Size (=0) | Notify Message Type |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| GW Ident Type | GW Ident Len | |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~
|
||||
~ New Responder GW Identity ~
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
~ Nonce Data ~
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
chunk_t redirect_data_create(identification_t *gw, chunk_t nonce)
|
||||
{
|
||||
gateway_id_type_t type;
|
||||
bio_writer_t *writer;
|
||||
chunk_t data;
|
||||
|
||||
type = id_type_to_gateway(gw->get_type(gw));
|
||||
if (!type)
|
||||
{
|
||||
return chunk_empty;
|
||||
}
|
||||
|
||||
writer = bio_writer_create(0);
|
||||
writer->write_uint8(writer, type);
|
||||
writer->write_data8(writer, gw->get_encoding(gw));
|
||||
if (nonce.ptr)
|
||||
{
|
||||
writer->write_data(writer, nonce);
|
||||
}
|
||||
|
||||
data = writer->extract_buf(writer);
|
||||
writer->destroy(writer);
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
identification_t *redirect_data_parse(chunk_t data, chunk_t *nonce)
|
||||
{
|
||||
bio_reader_t *reader;
|
||||
id_type_t id_type;
|
||||
chunk_t gateway;
|
||||
u_int8_t type;
|
||||
|
||||
reader = bio_reader_create(data);
|
||||
if (!reader->read_uint8(reader, &type) ||
|
||||
!reader->read_data8(reader, &gateway))
|
||||
{
|
||||
DBG1(DBG_ENC, "invalid REDIRECT notify data");
|
||||
reader->destroy(reader);
|
||||
return NULL;
|
||||
}
|
||||
id_type = gateway_to_id_type(type);
|
||||
if (!id_type)
|
||||
{
|
||||
DBG1(DBG_ENC, "invalid gateway ID type (%d) in REDIRECT notify", type);
|
||||
reader->destroy(reader);
|
||||
return NULL;
|
||||
}
|
||||
if (nonce)
|
||||
{
|
||||
*nonce = chunk_clone(reader->peek(reader));
|
||||
}
|
||||
reader->destroy(reader);
|
||||
return identification_create_from_encoding(id_type, gateway);
|
||||
}
|
||||
|
||||
@@ -87,4 +87,23 @@ struct redirect_manager_t {
|
||||
*/
|
||||
redirect_manager_t *redirect_manager_create();
|
||||
|
||||
/**
|
||||
* Create notification data of a REDIRECT or REDIRECT_FROM payload using the
|
||||
* given gateway identity and optional nonce (only used during IKE_SA_INIT).
|
||||
*
|
||||
* @param gw gateway identity (IP or FQDN), gets cloned
|
||||
* @param nonce nonce value, or chunk_empty, gets cloned
|
||||
* @return notify data, chunk_empty if ID type is not supported
|
||||
*/
|
||||
chunk_t redirect_data_create(identification_t *gw, chunk_t nonce);
|
||||
|
||||
/**
|
||||
* Parse notification data of a REDIRECT or REDIRECTED_FROM notify payload.
|
||||
*
|
||||
* @param data notification data to parse
|
||||
* @param nonce[out] nonce data (allocated), if any was provided
|
||||
* @return gateway identity, NULL if data is invalid
|
||||
*/
|
||||
identification_t *redirect_data_parse(chunk_t data, chunk_t *nonce);
|
||||
|
||||
#endif /** REDIRECT_MANAGER_H_ @}*/
|
||||
|
||||
Reference in New Issue
Block a user