#include <sys/types.h>
#include "doi.h"
#include "dpd.h"
#include "exchange.h"
#include "isakmp.h"
#include "isakmp_doi.h"
#include "ipsec.h"
#include "log.h"
#include "message.h"
#include "sa.h"
#include "util.h"
static int isakmp_debug_attribute(u_int16_t, u_int8_t *, u_int16_t,
void *);
static void isakmp_finalize_exchange(struct message *);
static struct keystate *isakmp_get_keystate(struct message *);
static int isakmp_initiator(struct message *);
static int isakmp_responder(struct message *);
static void isakmp_setup_situation(u_int8_t *);
static size_t isakmp_situation_size(void);
static u_int8_t isakmp_spi_size(u_int8_t);
static int isakmp_validate_attribute(u_int16_t, u_int8_t *, u_int16_t,
void *);
static int isakmp_validate_exchange(u_int8_t);
static int isakmp_validate_id_information(u_int8_t, u_int8_t *,
u_int8_t *, size_t, struct exchange *);
static int isakmp_validate_key_information(u_int8_t *, size_t);
static int isakmp_validate_notification(u_int16_t);
static int isakmp_validate_proto(u_int8_t);
static int isakmp_validate_situation(u_int8_t *, size_t *, size_t);
static int isakmp_validate_transform_id(u_int8_t, u_int8_t);
static struct doi isakmp_doi = {
{0}, ISAKMP_DOI_ISAKMP, 0, 0, 0,
isakmp_debug_attribute,
0,
0,
isakmp_finalize_exchange,
0,
0,
0,
isakmp_get_keystate,
0,
0,
0,
0,
0,
0,
isakmp_setup_situation,
isakmp_situation_size,
isakmp_spi_size,
isakmp_validate_attribute,
isakmp_validate_exchange,
isakmp_validate_id_information,
isakmp_validate_key_information,
isakmp_validate_notification,
isakmp_validate_proto,
isakmp_validate_situation,
isakmp_validate_transform_id,
isakmp_initiator,
isakmp_responder,
ipsec_decode_ids
};
void
isakmp_doi_init(void)
{
doi_register(&isakmp_doi);
}
int
isakmp_debug_attribute(u_int16_t type, u_int8_t *value, u_int16_t len,
void *vmsg)
{
return 0;
}
static void
isakmp_finalize_exchange(struct message *msg)
{
}
static struct keystate *
isakmp_get_keystate(struct message *msg)
{
return 0;
}
static void
isakmp_setup_situation(u_int8_t *buf)
{
}
static size_t
isakmp_situation_size(void)
{
return 0;
}
static u_int8_t
isakmp_spi_size(u_int8_t proto)
{
return 0;
}
static int
isakmp_validate_attribute(u_int16_t type, u_int8_t *value, u_int16_t len,
void *vmsg)
{
return -1;
}
static int
isakmp_validate_exchange(u_int8_t exch)
{
return -1;
}
static int
isakmp_validate_id_information(u_int8_t type, u_int8_t *extra, u_int8_t *buf,
size_t sz, struct exchange *exchange)
{
return zero_test(extra, ISAKMP_ID_DOI_DATA_LEN);
}
static int
isakmp_validate_key_information(u_int8_t *buf, size_t sz)
{
return 0;
}
static int
isakmp_validate_notification(u_int16_t type)
{
return -1;
}
static int
isakmp_validate_proto(u_int8_t proto)
{
return -1;
}
static int
isakmp_validate_situation(u_int8_t *buf, size_t *sz, size_t len)
{
*sz = 0;
return 0;
}
static int
isakmp_validate_transform_id(u_int8_t proto, u_int8_t transform_id)
{
return -1;
}
static int
isakmp_initiator(struct message *msg)
{
if (msg->exchange->type != ISAKMP_EXCH_INFO) {
log_print("isakmp_initiator: unsupported exchange type %d "
"in phase %d", msg->exchange->type, msg->exchange->phase);
return -1;
}
return message_send_info(msg);
}
static int
isakmp_responder(struct message *msg)
{
struct payload *p;
u_int16_t type;
switch (msg->exchange->type) {
case ISAKMP_EXCH_INFO:
for (p = payload_first(msg, ISAKMP_PAYLOAD_NOTIFY); p;
p = TAILQ_NEXT(p, link)) {
type = GET_ISAKMP_NOTIFY_MSG_TYPE(p->p);
LOG_DBG((LOG_EXCHANGE, 10, "isakmp_responder: "
"got NOTIFY of type %s",
constant_name(isakmp_notify_cst,
type)));
switch (type) {
case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE:
case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK:
dpd_handle_notify(msg, p);
break;
default:
p->flags |= PL_MARK;
break;
}
}
for (p = payload_first(msg, ISAKMP_PAYLOAD_DELETE); p;
p = TAILQ_NEXT(p, link)) {
LOG_DBG((LOG_EXCHANGE, 10,
"isakmp_responder: got DELETE, ignoring"));
p->flags |= PL_MARK;
}
return 0;
case ISAKMP_EXCH_TRANSACTION:
default:
if (payload_first(msg, ISAKMP_PAYLOAD_SA)) {
message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN,
0, 1, 0);
return -1;
}
}
return 0;
}