2600 lines
134 KiB
C
2600 lines
134 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmipha_reg.c,v $ $Revision: 1.26.10.2 $
|
|
* $Source: /home/interpeak/CVSRoot/ipmipha/src/ipmipha_reg.c,v $
|
|
* $Author: jsheng $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipmipha_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_inet.h>
|
|
#include <ipcom_ipd.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_hash.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock2.h>
|
|
#include <ipcom_syslog.h>
|
|
|
|
#include <ipmip.h>
|
|
#include <private/ipmip_sysvar.h>
|
|
#include <private/ipmip_timer.h>
|
|
|
|
#include <ipmip4.h>
|
|
#include <private/ipmip4_context.h>
|
|
#include <private/ipmip4_util.h>
|
|
#include <private/ipmip4_sysext.h>
|
|
#include <private/ipmip4_auth.h>
|
|
#include <private/ipmip4_pkt.h>
|
|
#include <private/ipmip4_util.h>
|
|
|
|
#include "ipmipha.h"
|
|
#include "ipmip4_mib.h"
|
|
#include "ipmipha_h.h"
|
|
#include "ipmipha_attr_h.h"
|
|
#include "ipmipha_reg.h"
|
|
#include "ipmipha_if.h"
|
|
#include "ipmipha_node.h"
|
|
#include "ipmipha_agent.h"
|
|
#include "ipmipha_pktbuf.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_revoke_ack
|
|
*===========================================================================
|
|
* Description: Send a revocation request for this particular binding
|
|
* Parameters: data - Data
|
|
* proc - Process
|
|
* node - Node
|
|
* binding - Binding
|
|
* pbuf - Packet buffer
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmipha_reg_revoke_ack(struct Ipmipha_data *data,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmipha_node *node,
|
|
struct Ipmipha_node_binding *binding,
|
|
struct Ipmipha_pktbuf *pbuf)
|
|
{
|
|
/**/
|
|
Ipmip4_regrevack_t regrev;
|
|
|
|
IPMIP_UNUSED_PARAMETER(node);
|
|
|
|
ipcom_memset(®rev, 0, sizeof(regrev));
|
|
|
|
if (pbuf->pktinfo.haBindingSPIForeignHome == IP_NULL)
|
|
goto error_out;
|
|
|
|
regrev.type = IPMIP4_TYPE_REG_REGREVACK;
|
|
regrev.home_address = pbuf->pktinfo.haBindingHomeAddress;
|
|
regrev.identifier = ip_htonl(pbuf->pktinfo.haBindingRevocationTimeStamp);
|
|
|
|
/**/
|
|
if ((binding == IP_NULL || IP_BIT_ISSET(binding->haBindingTunnelFlags, IPMIP4_TUNNELMODE_REVOCATION_INFORM)) && IP_BIT_ISTRUE(pbuf->pktinfo.haBindingOptions, IPMIP4_REG_EXT_REGREV_FLAG_INFORM))
|
|
regrev.flags |= ip_htons(IPMIP4_REG_EXT_REGREV_FLAG_INFORM);
|
|
|
|
/* Reset the buffer */
|
|
ipmip_buffer_shrink(&pbuf->ipmip4.ipmip.packet, 0);
|
|
/* Add the header */
|
|
ipmip_buffer_append(&pbuf->ipmip4.ipmip.packet, ®rev, sizeof(regrev));
|
|
|
|
/* Add the foreign to home authentication */
|
|
if (ipmip4_auth_append_foreign_to_home(&pbuf->ipmip4.ipmip.packet, pbuf->pktinfo.haBindingSPIForeignHome) == IP_FALSE)
|
|
goto error_out;
|
|
|
|
/* Send packet using UDP socket */
|
|
if (ipmip4_pkt_udp_sendmsg(&data->ipmip4,
|
|
proc,
|
|
&pbuf->ipmip4.ipmip.packet,
|
|
pbuf->iff.pub->ifaddr,
|
|
data->ipmip4.pkt->s_udp_out.sin_port,
|
|
pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_addr.s_addr,
|
|
pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_port,
|
|
IP_NULL) == IP_FALSE)
|
|
{
|
|
/**/
|
|
}
|
|
|
|
error_out:
|
|
/* Remove the reference */
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_tunnel_type
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_u8
|
|
ipmipha_reg_tunnel_type(Ipmipha_pktbuf_t *pbuf)
|
|
{
|
|
if (IP_BIT_ISSET(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_MINIMAL_ENC))
|
|
return IPMIP_TUNNELTYPE_MINENC;
|
|
else if (IP_BIT_ISSET(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_GRE_ENC))
|
|
return IPMIP_TUNNELTYPE_GRE;
|
|
|
|
return IPMIP_TUNNELTYPE_IPIP;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_spi_lookup_home_sa
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipmip4_auth_spi_t *
|
|
ipmipha_reg_spi_lookup_home_sa(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_pktbuf_t *pbuf)
|
|
{
|
|
int i;
|
|
Ipmip4_auth_spi_t *spi = IP_NULL;
|
|
|
|
IPMIP_UNUSED_PARAMETER(data);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
for (i = 0; pbuf->iff.priv->security.spi_mn_lookup_order[i] != IPMIPHA_SPI_MN_NONE; i++)
|
|
{
|
|
switch (pbuf->iff.priv->security.spi_mn_lookup_order[i])
|
|
{
|
|
case IPMIPHA_SPI_MN_HOA:
|
|
if (pbuf->pktinfo.haBindingHomeAddress != 0)
|
|
spi = ipmip4_auth_spi_table_get(pbuf->iff.priv->security.spi_mn, pbuf->pktinfo.haBindingHomeAddress);
|
|
break;
|
|
case IPMIPHA_SPI_MN_NAI:
|
|
if (pbuf->ipmip4.ext.mobile.nai_mobile)
|
|
spi = ipmip4_auth_spi_hash_get(pbuf->iff.priv->security.spi_nai,
|
|
(char *)IPMIP4_MSGEXT_SHDR_EXT_DATA(pbuf->ipmip4.ext.mobile.nai_mobile),
|
|
IPMIP4_MSGEXT_SHDR_EXT_SIZE(pbuf->ipmip4.ext.mobile.nai_mobile));
|
|
break;
|
|
}
|
|
|
|
if (spi)
|
|
return spi;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_spi_lookup_home_sa
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipmip4_auth_spi_t *
|
|
ipmipha_reg_spi_lookup_foreign_sa(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_pktbuf_t *pbuf)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(data);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
if (pbuf->pktinfo.haBindingCOA != 0)
|
|
return ipmip4_auth_spi_table_get(pbuf->iff.priv->security.spi_fa, pbuf->pktinfo.haBindingCOA);
|
|
return IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_reply
|
|
*===========================================================================
|
|
* Description: Send a reply based on the parameters in the packet buffer.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmipha_reg_reply(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_node_t *node,
|
|
Ipmipha_pktbuf_t *pbuf)
|
|
{
|
|
/**/
|
|
Ipmipha_pktbuf_t *rpbuf = (Ipmipha_pktbuf_t *)ipmip_pktbuf_alloc(&data->ipmip4.ipmip, proc, 512);
|
|
Ipmip4_regrep_t reply;
|
|
|
|
|
|
reply.type = IPMIP4_TYPE_REG_REPLY;
|
|
reply.code = pbuf->pktinfo.haBindingHAErrorCode;
|
|
reply.lifetime = ip_htons(pbuf->pktinfo.haBindingTimeGranted);
|
|
reply.home_addr = pbuf->pktinfo.haBindingHomeAddress;
|
|
reply.home_agent = pbuf->iff.pub->ifaddr;
|
|
reply.id[0] = ip_htonl( ((Ip_u32)pbuf->haBindingTimeStamp) + IPMIP4_JAN_1970);
|
|
reply.id[1] = pbuf->pktinfo.haBindingRegIDLow;
|
|
|
|
/* Add the header */
|
|
ipmip_buffer_append(&rpbuf->ipmip4.ipmip.packet, &reply, sizeof(reply));
|
|
|
|
/* Add the home agent's NAI, if applicable */
|
|
if (pbuf->iff.priv->nai_ha)
|
|
ipmip4_msgext_buffer_append_shdr(&rpbuf->ipmip4.ipmip.packet, pbuf->iff.priv->nai_ha);
|
|
|
|
/* If there's a mobile NAI; add it */
|
|
if (pbuf->ipmip4.ext.mobile.nai_mobile)
|
|
ipmip4_msgext_buffer_append_shdr(&rpbuf->ipmip4.ipmip.packet, pbuf->ipmip4.ext.mobile.nai_mobile);
|
|
|
|
/* We're DHAAD redirecting */
|
|
if (pbuf->pktinfo.haBindingHAErrorCode == IPMIP4_CODE_REP_HA_REGISTER_REDIRECTED)
|
|
{
|
|
Ip_u8 redir[8];
|
|
redir[0] = IPMIP4_EXT_TYPE_DYNAMIC_HA;
|
|
redir[1] = IPMIP4_DYNAMIC_HA_SUBTYPE_REDIRECTED;
|
|
IP_SET_HTONS(&redir[2], 4);
|
|
IP_SET_32ON8(&redir[4], pbuf->pktinfo.haBindingHomeAgentAddress);
|
|
|
|
ipmip4_msgext_buffer_append_lhdr(&rpbuf->ipmip4.ipmip.packet, (void *)redir);
|
|
}
|
|
|
|
/* Do we have a mobile node UDP tunneling request */
|
|
if (pbuf->pktinfo.haBindingHAErrorCode < 2)
|
|
ipmip_buffer_append(&rpbuf->ipmip4.ipmip.packet, IPMIP_BUFFER_DATA(&pbuf->reply_mn), IPMIP_BUFFER_SIZE(&pbuf->reply_mn));
|
|
|
|
/* Do we have a selected AAAH home server? */
|
|
if (node != IP_NULL)
|
|
{
|
|
if (node->nai_aaah != IP_NULL)
|
|
ipmip4_msgext_buffer_append_shdr(&rpbuf->ipmip4.ipmip.packet, node->nai_aaah);
|
|
}
|
|
|
|
/* Add any mobile node specific external extensions */
|
|
ipmipha_node_function_rep_mobile_home(data, proc, node, pbuf, rpbuf);
|
|
|
|
/* Try append mobile to home; if set */
|
|
if (pbuf->pktinfo.haBindingSPIMobileHome == IP_NULL)
|
|
{
|
|
Ipmip4_auth_spi_t *spi = IP_NULL;
|
|
/**/
|
|
if (pbuf->ipmip4.ext.mobile.mobile_home)
|
|
{
|
|
Ipmip4_ext_auth_t *auth = (Ipmip4_ext_auth_t *) pbuf->ipmip4.ext.mobile.mobile_home;
|
|
spi = ipmip4_auth_spi_get(pbuf->iff.priv->security.spi_ctx, IP_GET_HTONL(auth->spi));
|
|
}
|
|
|
|
if (pbuf->iff.priv->security.spi_mn_lookup_required || (pbuf->pktinfo.haBindingSPIMobileHome = spi) == IP_NULL)
|
|
pbuf->pktinfo.haBindingSPIMobileHome = ipmipha_reg_spi_lookup_home_sa(data, proc, pbuf);
|
|
|
|
if (pbuf->pktinfo.haBindingSPIMobileHome == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Failed locating mobile-home extension SPI for RegReply (%d) to %s:%d",
|
|
pbuf->pktinfo.haBindingHAErrorCode,
|
|
ipmip_ntop_sa(proc, pbuf->ipmip4.ipmip.srcinfo.src),
|
|
ip_ntohs(pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_port)));
|
|
goto error_out;
|
|
}
|
|
}
|
|
|
|
if (!ipmip4_auth_append_mobile_to_home(&rpbuf->ipmip4.ipmip.packet, pbuf->pktinfo.haBindingSPIMobileHome))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Failed adding mobile-home extension to RegReply (%d) to %s:%d",
|
|
pbuf->pktinfo.haBindingHAErrorCode,
|
|
ipmip_ntop_sa(proc, pbuf->ipmip4.ipmip.srcinfo.src),
|
|
ip_ntohs(pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_port)));
|
|
goto error_out;
|
|
}
|
|
|
|
/* Time to add any HA <-> FA */
|
|
if (IP_BIT_ISFALSE(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_DECAPSULATION))
|
|
{
|
|
/* Do we have a mobile node UDP tunneling request */
|
|
if (pbuf->pktinfo.haBindingHAErrorCode < 2)
|
|
ipmip_buffer_append(&rpbuf->ipmip4.ipmip.packet, IPMIP_BUFFER_DATA(&pbuf->reply_fa), IPMIP_BUFFER_SIZE(&pbuf->reply_fa));
|
|
|
|
/* Add any challenges */
|
|
if (pbuf->ipmip4.ext.mobile.challenge != IP_NULL)
|
|
ipmip4_msgext_buffer_append_shdr(&rpbuf->ipmip4.ipmip.packet, (void *)pbuf->ipmip4.ext.mobile.challenge);
|
|
|
|
/* Add any mobile node specific external extensions */
|
|
ipmipha_node_function_rep_mobile_foreign(data, proc, node, pbuf, rpbuf);
|
|
|
|
if (pbuf->pktinfo.haBindingSPIForeignHome == IP_NULL)
|
|
pbuf->pktinfo.haBindingSPIForeignHome = ipmip4_auth_spi_table_get(pbuf->iff.priv->security.spi_fa, pbuf->pktinfo.haBindingCOA);
|
|
if (pbuf->pktinfo.haBindingSPIForeignHome == IP_NULL && pbuf->ipmip4.ext.mobile.foreign_home != IP_NULL)
|
|
{
|
|
Ipmip4_ext_auth_t *auth = (Ipmip4_ext_auth_t *) pbuf->ipmip4.ext.mobile.foreign_home;
|
|
pbuf->pktinfo.haBindingSPIForeignHome = ipmip4_auth_spi_get(pbuf->iff.priv->security.spi_ctx, IP_GET_HTONL(auth->spi));
|
|
}
|
|
|
|
if (pbuf->pktinfo.haBindingSPIForeignHome != IP_NULL)
|
|
{
|
|
if (!ipmip4_auth_append_foreign_to_home(&rpbuf->ipmip4.ipmip.packet, pbuf->pktinfo.haBindingSPIForeignHome))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Failed adding foreign-home extension to RegReply (%d) to %s:%d",
|
|
pbuf->pktinfo.haBindingHAErrorCode,
|
|
ipmip_ntop_sa(proc, pbuf->ipmip4.ipmip.srcinfo.src),
|
|
ip_ntohs(pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_port)));
|
|
goto error_out;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**/
|
|
if (pbuf->reply_transport != IP_NULL)
|
|
(*pbuf->reply_transport->pkt_rep_transport) (data, proc, data->conf->extdata[pbuf->reply_transport->func][pbuf->reply_transport->type], pbuf->iff.priv->extdata[pbuf->reply_transport->func][pbuf->reply_transport->type], node->extdata[pbuf->reply_transport->func][pbuf->reply_transport->type], node, pbuf, rpbuf);
|
|
else
|
|
{
|
|
/* Send packet using UDP socket */
|
|
if (ipmip4_pkt_udp_sendmsg(&data->ipmip4,
|
|
proc,
|
|
&rpbuf->ipmip4.ipmip.packet,
|
|
pbuf->iff.pub->ifaddr,
|
|
data->ipmip4.pkt->s_udp_out.sin_port,
|
|
pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_addr.s_addr,
|
|
pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_port,
|
|
IP_NULL) == IP_FALSE)
|
|
{
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haReasonUnspecified, 1);
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Failed Sending RegReply (%d) to %s:%d",
|
|
pbuf->pktinfo.haBindingHAErrorCode,
|
|
ipmip_ntop_sa(proc, pbuf->ipmip4.ipmip.srcinfo.src),
|
|
ip_ntohs(pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_port)));
|
|
|
|
}
|
|
else
|
|
{
|
|
if (pbuf->pktinfo.haBindingTimeGranted == 0)
|
|
{
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haDeRegRepliesSent, 1);
|
|
}
|
|
else
|
|
{
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haRegRepliesSent, 1);
|
|
}
|
|
|
|
IPMIP4_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Sending RegReply id=0x%08x (%d) to %s:%d",
|
|
pbuf->pktinfo.haBindingRegIDLow,
|
|
pbuf->pktinfo.haBindingHAErrorCode,
|
|
ipmip_ntop_sa(proc, pbuf->ipmip4.ipmip.srcinfo.src),
|
|
ip_ntohs(pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_port)));
|
|
}
|
|
}
|
|
|
|
error_out:
|
|
/* Remove the reference */
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &rpbuf->ipmip4.ipmip);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_request_error
|
|
*===========================================================================
|
|
* Description: Error stage
|
|
* Parameters: pbuf - The packet buffer
|
|
* req - Type of major request
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipmipha_reg_request_error(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_pktbuf_t *pbuf,
|
|
Ip_u8 code)
|
|
{
|
|
if (code != 0)
|
|
{
|
|
pbuf->ipmip4.ipmip.error_code = code;
|
|
pbuf->pktinfo.haBindingHAErrorCode = pbuf->ipmip4.ipmip.error_code;
|
|
|
|
switch (pbuf->ipmip4.ipmip.error_code)
|
|
{
|
|
case IPMIP4_CODE_REP_HA_POORLY_FORMED_REQUEST:
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haPoorlyFormedRequest, 1);
|
|
break;
|
|
case IPMIP4_CODE_REP_HA_ADMIN_PROHIBIT:
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haAdmProhibited, 1);
|
|
break;
|
|
case IPMIP4_CODE_REP_HA_INSUFFICIENT_RESOURCES:
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haInsufficientResource, 1);
|
|
break;
|
|
case IPMIP4_CODE_REP_HA_MN_FAILED_AUTH:
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haMNAuthenticationFailure, 1);
|
|
break;
|
|
case IPMIP4_CODE_REP_HA_FA_FAILED_AUTH:
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haFAAuthenticationFailure, 1);
|
|
break;
|
|
case IPMIP4_CODE_REP_HA_REG_ID_MISMATCH:
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haIDMismatch, 1);
|
|
break;
|
|
case IPMIP4_CODE_REP_HA_UNKNOWN_HOME_AGENT_ADDR:
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haUnknownHA, 1);
|
|
break;
|
|
case IPMIP4_CODE_REP_HA_TOO_MANY_SIM:
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haTooManyBindings, 1);
|
|
break;
|
|
default:
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haReasonUnspecified, 1);
|
|
break;
|
|
}
|
|
|
|
/* Reg reply consumes the buffer */
|
|
ipmipha_reg_reply(data, proc, (Ipmipha_node_t *)pbuf->node, pbuf);
|
|
}
|
|
else
|
|
{
|
|
/* Free it */
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
}
|
|
|
|
return IPMIP_TIMER_RET_DONE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_verify_keygen
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipmipha_reg_verify_keygen(Ipmip4_auth_spi_t *spi,
|
|
Ipmip4_ext_auth_t *auth)
|
|
{
|
|
/* No generated SPI */
|
|
/* No auth; we do have a generated SPI. Auth must be set */
|
|
if (auth == IP_NULL)
|
|
return IP_FALSE;
|
|
|
|
/* Does the SPI match? */
|
|
return IP_GET_HTONL(auth->spi) == spi->spi;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_input_request
|
|
*===========================================================================
|
|
* Description: Handles registration request packages.
|
|
* Either forwards a request from mn -> ha,
|
|
* or replies to mn cause of mn's bad request.
|
|
* Parameters: pbuf - Packet buffer
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmipha_reg_input_request(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_pktbuf_t *pbuf)
|
|
{
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haRegRequestsReceived, 1);
|
|
|
|
if (!ipmipha_reg_input_parse_request(data, proc, pbuf))
|
|
return;
|
|
|
|
if (pbuf->pktinfo.haBindingTimeGranted == 0)
|
|
{
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haDeRegRequestsReceived, 1);
|
|
}
|
|
else
|
|
{
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haRegRequestsReceived, 1);
|
|
}
|
|
|
|
/* Update pending information */
|
|
IPMIP4_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Received RegReq id=0x%08x lifetime=%u CoA=%s from %s:%d",
|
|
pbuf->pktinfo.haBindingRegIDLow,
|
|
pbuf->pktinfo.haBindingTimeGranted,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
ipmip_ntop_sa(proc, pbuf->ipmip4.ipmip.srcinfo.src),
|
|
ip_ntohs(pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_port)));
|
|
|
|
/* Try locate the mobile node */
|
|
ipmipha_node_lookup(data,
|
|
proc,
|
|
pbuf->iff.priv,
|
|
pbuf->pktinfo.haBindingHomeAddress,
|
|
&pbuf->ipmip4.ipmip.timeout,
|
|
(Ipmip_timer_func_t)ipmipha_reg_request_process,
|
|
pbuf);
|
|
return;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
IPMIPHA_REG_REGREVACK_INIT,
|
|
IPMIPHA_REG_REGREVACK_VERIFY
|
|
};
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_ret_process
|
|
*===========================================================================
|
|
* Description: Process a container stage
|
|
* Parameters: pbuf - The packet buffer
|
|
* req - Type of major request
|
|
* Returns: IP_FALSE
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipmipha_reg_regrevack_process(int event,
|
|
Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_pktbuf_t *pbuf,
|
|
Ipmipha_node_t *node)
|
|
{
|
|
if (event == IPMIP_TIMER_EVENT_RUN)
|
|
{
|
|
Ipmipha_node_binding_t *binding = IP_NULL;
|
|
|
|
if (node == IP_NULL)
|
|
node = (Ipmipha_node_t *)pbuf->node;
|
|
|
|
|
|
if (node == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded due to unknown node specified in registration revocation ack",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
switch (pbuf->pktinfo.haBindingParsingState)
|
|
{
|
|
case IPMIPHA_REG_REGREVACK_INIT:
|
|
pbuf->node = node;
|
|
{
|
|
Ipmip4_ext_auth_t *auth = (Ipmip4_ext_auth_t *) pbuf->ipmip4.ext.mobile.foreign_home;
|
|
Ipmip4_auth_spi_t *spi_fa;
|
|
|
|
/* Verify the SPI we should use for foreign agent */
|
|
spi_fa = ipmip4_auth_spi_get(pbuf->iff.priv->security.spi_ctx, IP_GET_HTONL(auth->spi));
|
|
if (spi_fa == IP_NULL)
|
|
{
|
|
/* Unknown security association */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded due to foreign agent requested a non-existant security association",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
if (pbuf->iff.priv->security.spi_fa_lookup_required)
|
|
{
|
|
Ipmip4_auth_spi_t *spi = ipmipha_reg_spi_lookup_foreign_sa(data, proc, pbuf);
|
|
if (spi == IP_NULL)
|
|
{
|
|
/* Unknown security association */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded due to foreign agent lacks configured security association with this home agent",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
else if(spi->spi != spi_fa->spi)
|
|
{
|
|
/* Go use the configured value */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded due to foreign agent used an invalid security association SPI %d, configured to use %d",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
spi_fa->spi,
|
|
spi->spi));
|
|
goto done_out;
|
|
}
|
|
}
|
|
|
|
pbuf->pktinfo.haBindingParsingState = IPMIPHA_REG_REGREVACK_VERIFY;
|
|
if (ipmip4_auth_verify(&data->ipmip4,
|
|
proc,
|
|
&pbuf->ipmip4,
|
|
pbuf->ipmip4.ext.mobile.foreign_home,
|
|
spi_fa,
|
|
node->lock,
|
|
(Ipmip_timer_func_t)ipmipha_reg_regrevack_process))
|
|
return IPMIP_TIMER_RET_PENDING;
|
|
}
|
|
|
|
/* this is an intentional fall through to the next case */
|
|
case IPMIPHA_REG_REGREVACK_VERIFY:
|
|
if (pbuf->ipmip4.ipmip.message != 0)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded due to %s",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->ipmip4.ipmip.message));
|
|
goto done_out;
|
|
}
|
|
|
|
binding = ipmipha_node_binding_revoked(data, proc, node, pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_addr.s_addr, pbuf->pktinfo.haBindingRevocationTimeStamp);
|
|
if (binding == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded due to unknown binding requested in registration revocation ack",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
ipmipha_node_binding_revoked_complete(data, proc, node, binding);
|
|
|
|
IPMIP4_EVENT_IF(INFO, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request successful",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
|
|
}
|
|
}
|
|
|
|
done_out:
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
return IPMIP_TIMER_RET_DONE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_input_regrevack
|
|
*===========================================================================
|
|
* Description: Handles registration request packages.
|
|
* Either forwards a request from mn -> ha,
|
|
* or replies to mn cause of mn's bad request.
|
|
* Parameters: pbuf - Packet buffer
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmipha_reg_input_regrevack(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_pktbuf_t *pbuf)
|
|
{
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haRegRequestsReceived, 1);
|
|
|
|
/* Check length */
|
|
if (IPMIP_BUFFER_SIZE(&pbuf->ipmip4.ipmip.packet) < IPMIP4_REGREVACK_LENGTH)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Truncated registration revocation ack [%d]", IPMIP_BUFFER_SIZE(&pbuf->ipmip4.ipmip.packet)));
|
|
goto done_out;
|
|
}
|
|
else
|
|
{
|
|
/* Pointers to the packet */
|
|
Ipmip4_regrevack_t *regrev = IPMIP_BUFFER_PTR(&pbuf->ipmip4.ipmip.packet);
|
|
|
|
/* Store pending reg information */
|
|
pbuf->pktinfo.haBindingRevocationTimeStamp = IP_GET_HTONL(®rev->identifier);
|
|
pbuf->pktinfo.haBindingOptions = IP_GET_HTONS(®rev->flags);
|
|
pbuf->pktinfo.haBindingHomeAddress = IP_GET_32ON8(®rev->home_address);
|
|
}
|
|
|
|
/* OK */
|
|
pbuf->ipmip4.ext.mobile.result = ipmip4_msgext_mobile_parse_ext(&data->ipmip4, proc, &pbuf->ipmip4, IPMIP4_REGREVACK_LENGTH);
|
|
|
|
|
|
/* Parse extensions */
|
|
switch (pbuf->ipmip4.ext.mobile.result)
|
|
{
|
|
case IPMIP4_REG_EXT_UNKNOWN_VSE:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded due to bad or unknown VSE",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
|
|
case IPMIP4_REG_EXT_FAILED_AUTH:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded due to bad or duplicate authentication extensions",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
case IPMIP4_REG_EXT_POORLY_FORMED:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded due to poorly formed request",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
case IPMIP4_REG_EXT_DISCARD:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
/* Do we have a foreign-home authentication? */
|
|
if (pbuf->ipmip4.ext.mobile.foreign_home == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation ack silently discarded due to no foreign-home extension in revocation acknowledgement",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
/* Try locate the mobile node */
|
|
ipmipha_node_lookup(data,
|
|
proc,
|
|
pbuf->iff.priv,
|
|
pbuf->pktinfo.haBindingHomeAddress,
|
|
&pbuf->ipmip4.ipmip.timeout,
|
|
(Ipmip_timer_func_t)ipmipha_reg_regrevack_process,
|
|
pbuf);
|
|
return;
|
|
|
|
done_out:
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
IPMIPHA_REG_REGREVREQ_INIT,
|
|
IPMIPHA_REG_REGREVREQ_VERIFY
|
|
};
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_ret_process
|
|
*===========================================================================
|
|
* Description: Process a container stage
|
|
* Parameters: pbuf - The packet buffer
|
|
* req - Type of major request
|
|
* Returns: IP_FALSE
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipmipha_reg_regrevreq_process(int event,
|
|
Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_pktbuf_t *pbuf,
|
|
Ipmipha_node_t *node)
|
|
{
|
|
if (event == IPMIP_TIMER_EVENT_RUN)
|
|
{
|
|
Ipmipha_node_binding_t *binding = IP_NULL;
|
|
|
|
if (node == IP_NULL)
|
|
node = (Ipmipha_node_t *)pbuf->node;
|
|
|
|
binding = (Ipmipha_node_binding_t *)pbuf->binding;
|
|
|
|
switch (pbuf->pktinfo.haBindingParsingState)
|
|
{
|
|
case IPMIPHA_REG_REGREVREQ_INIT:
|
|
{
|
|
Ipmip4_ext_auth_t *auth = (Ipmip4_ext_auth_t *) pbuf->ipmip4.ext.mobile.foreign_home;
|
|
|
|
/* Verify the SPI we should use for foreign agent */
|
|
pbuf->pktinfo.haBindingSPIForeignHome = ipmip4_auth_spi_get(pbuf->iff.priv->security.spi_ctx, IP_GET_HTONL(auth->spi));
|
|
|
|
if (node == IP_NULL)
|
|
{
|
|
ipmipha_reg_revoke_ack(data, proc, IP_NULL, IP_NULL, pbuf);
|
|
return IPMIP_TIMER_RET_DONE;
|
|
}
|
|
|
|
pbuf->node = node;
|
|
|
|
binding = ipmipha_node_binding_coa(data, proc, node, pbuf->pktinfo.haBindingCOA);
|
|
if (binding == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to unknown binding requested in registration revocation ack",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
pbuf->binding = binding;
|
|
|
|
/* Found node & binding */
|
|
if (binding->haBindingForeignSA != IP_NULL)
|
|
{
|
|
pbuf->pktinfo.haBindingSPIForeignHome = binding->haBindingForeignSA;
|
|
if (pbuf->pktinfo.haBindingSPIForeignHome->spi != IP_GET_HTONL(auth->spi))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to foreign agent used a security association that does not match AAA generated",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pbuf->pktinfo.haBindingSPIForeignHome == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to foreign agent requested a non-existant security association",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
if (pbuf->iff.priv->security.spi_fa_lookup_required)
|
|
{
|
|
Ipmip4_auth_spi_t *spi = ipmipha_reg_spi_lookup_foreign_sa(data, proc, pbuf);
|
|
if (spi == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to foreign agent lacks configured security association with this home agent",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
else if(spi->spi != pbuf->pktinfo.haBindingSPIForeignHome->spi)
|
|
{
|
|
/* Go use the configured value */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to foreign agent used an invalid security association SPI %d, configured to use %d",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->pktinfo.haBindingSPIForeignHome->spi,
|
|
spi->spi));
|
|
goto done_out;
|
|
}
|
|
}
|
|
}
|
|
|
|
pbuf->pktinfo.haBindingParsingState = IPMIPHA_REG_REGREVREQ_VERIFY;
|
|
if (ipmip4_auth_verify(&data->ipmip4,
|
|
proc,
|
|
&pbuf->ipmip4,
|
|
pbuf->ipmip4.ext.mobile.foreign_home,
|
|
pbuf->pktinfo.haBindingSPIForeignHome,
|
|
node->lock,
|
|
(Ipmip_timer_func_t)ipmipha_reg_regrevreq_process))
|
|
return IPMIP_TIMER_RET_PENDING;
|
|
}
|
|
|
|
/* this is an intentional fall through to the next case */
|
|
case IPMIPHA_REG_REGREVREQ_VERIFY:
|
|
if (pbuf->ipmip4.ipmip.message != 0)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to %s",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->ipmip4.ipmip.message));
|
|
goto done_out;
|
|
|
|
}
|
|
|
|
if (!IP_BIT_ARESET(binding->haBindingTunnelFlags, IPMIP4_TUNNELMODE_REVOCATION_CONFIRMED))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to this binding does not accept revocation usage",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
/**/
|
|
if (binding->haBindingRevocationTimeStamp >= pbuf->pktinfo.haBindingRevocationTimeStamp)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to bad revocation time stamp",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
/* Time to revoke */
|
|
IPMIP4_EVENT_IF(INFO, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request acknowledged",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
|
|
ipmipha_reg_revoke_ack(data, proc, node, binding, pbuf);
|
|
ipmipha_node_binding_delete(data, proc, node, binding);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
done_out:
|
|
/* Cancelled or aborted */
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
}
|
|
return IPMIP_TIMER_RET_DONE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_input_regrevreq
|
|
*===========================================================================
|
|
* Description: Handles registration request packages.
|
|
* Either forwards a request from mn -> ha,
|
|
* or replies to mn cause of mn's bad request.
|
|
* Parameters: pbuf - Packet buffer
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmipha_reg_input_regrevreq(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_pktbuf_t *pbuf)
|
|
{
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haRegRequestsReceived, 1);
|
|
|
|
/* Check length */
|
|
if (IPMIP_BUFFER_SIZE(&pbuf->ipmip4.ipmip.packet) < IPMIP4_REGREVREQ_LENGTH)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Truncated registration revocation request [%d]", IPMIP_BUFFER_SIZE(&pbuf->ipmip4.ipmip.packet)));
|
|
goto done_out;
|
|
}
|
|
else
|
|
{
|
|
/* Pointers to the packet */
|
|
Ipmip4_regrevreq_t *regrev = IPMIP_BUFFER_PTR(&pbuf->ipmip4.ipmip.packet);
|
|
|
|
/* Store pending reg information */
|
|
pbuf->pktinfo.haBindingHomeAgentAddress = IP_GET_32ON8(®rev->home_domain);
|
|
pbuf->pktinfo.haBindingRevocationTimeStamp = IP_GET_HTONL(®rev->identifier);
|
|
pbuf->pktinfo.haBindingOptions = IP_GET_HTONS(®rev->flags);
|
|
pbuf->pktinfo.haBindingHomeAddress = IP_GET_32ON8(®rev->home_address);
|
|
pbuf->pktinfo.haBindingCOA = IP_GET_32ON8(®rev->foreign_domain);
|
|
|
|
}
|
|
|
|
/* OK */
|
|
pbuf->ipmip4.ext.mobile.result = ipmip4_msgext_mobile_parse_ext(&data->ipmip4, proc, &pbuf->ipmip4, IPMIP4_REGREVREQ_LENGTH);
|
|
|
|
|
|
/* Parse extensions */
|
|
switch (pbuf->ipmip4.ext.mobile.result)
|
|
{
|
|
case IPMIP4_REG_EXT_UNKNOWN_VSE:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to bad or unknown VSE",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
|
|
case IPMIP4_REG_EXT_FAILED_AUTH:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to bad or duplicate authentication extensions",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
case IPMIP4_REG_EXT_POORLY_FORMED:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to poorly formed request",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
case IPMIP4_REG_EXT_DISCARD:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
if (IP_BIT_ISTRUE(pbuf->pktinfo.haBindingOptions, IPMIP4_REG_EXT_REGREV_FLAG_AGENT))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to home agent flag set in revocation request",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
/* Do we have a foreign-home authentication? */
|
|
if (pbuf->ipmip4.ext.mobile.foreign_home == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration revocation request silently discarded due to no foreign-home extension in revocation request",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
goto done_out;
|
|
}
|
|
|
|
/* Try locate the mobile node */
|
|
ipmipha_node_lookup(data,
|
|
proc,
|
|
pbuf->iff.priv,
|
|
pbuf->pktinfo.haBindingHomeAddress,
|
|
&pbuf->ipmip4.ipmip.timeout,
|
|
(Ipmip_timer_func_t)ipmipha_reg_regrevreq_process,
|
|
pbuf);
|
|
return;
|
|
|
|
done_out:
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_recv
|
|
*===========================================================================
|
|
* Description: Handles registration request packages.
|
|
* Parameters: data - Context
|
|
* proc - Current process.
|
|
* pbuf - Packet buffer
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmipha_reg_recv(struct Ipmipha_data *data,
|
|
struct Ipmip_proc *proc,
|
|
Ipmipha_pktbuf_t *pbuf,
|
|
void *arg)
|
|
{
|
|
/* Locate the interface */
|
|
IPMIP_UNUSED_PARAMETER(arg);
|
|
if (data->conf == IP_NULL)
|
|
{
|
|
/* Failure */
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"No valid configuration availble, discarding registration request"));
|
|
goto error_out;
|
|
}
|
|
|
|
if (pbuf->ipmip4.ipmip.srcinfo.lladdr == IP_NULL)
|
|
{
|
|
/* Failure */
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"No MAC found in message, discarding registration request"));
|
|
goto error_out;
|
|
}
|
|
|
|
/* Try locate the interface */
|
|
pbuf->iff.pub = ipmip4_if_findbypktinfo(&data->conf->if_head, pbuf->ipmip4.ipmip.srcinfo.dst);
|
|
if (pbuf->iff.priv == IP_NULL)
|
|
{
|
|
/* Failure */
|
|
IPMIP4_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"No configured interface found in message, discarding registration request"));
|
|
goto error_out;
|
|
}
|
|
|
|
/* Retrieve the first byte */
|
|
pbuf->pktinfo.haBindingRegType = *(Ip_u8 *)IPMIP_BUFFER_DATA(&pbuf->ipmip4.ipmip.packet);
|
|
pbuf->haBindingTimeStamp = ipmip_util_time();
|
|
switch (pbuf->pktinfo.haBindingRegType)
|
|
{
|
|
case IPMIP4_TYPE_REG_REQUEST:
|
|
if (IP_BIT_ISFALSE(data->shutdown, IPMIPHA_SHUTDOWN_REG))
|
|
{
|
|
ipmipha_reg_input_request(data, proc, pbuf);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case IPMIP4_TYPE_REG_REGREVACK:
|
|
ipmipha_reg_input_regrevack(data, proc, pbuf);
|
|
return;
|
|
|
|
case IPMIP4_TYPE_REG_REGREVREQ:
|
|
ipmipha_reg_input_regrevreq(data, proc, pbuf);
|
|
return;
|
|
|
|
case IPMIP4_TYPE_REG_NAT_ENCAP:
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"NAT Encapsulation registration type %d received on %s from %s [%d]",
|
|
pbuf->pktinfo.haBindingRegType,
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_sa(proc, pbuf->ipmip4.ipmip.srcinfo.src),
|
|
((Ip_u8 *)IPMIP_BUFFER_DATA(&pbuf->ipmip4.ipmip.packet))[1]));
|
|
goto error_out;
|
|
case IPMIP4_TYPE_REG_REPLY:
|
|
case IPMIP4_TYPE_REG_HRQST:
|
|
case IPMIP4_TYPE_REG_HRPLY:
|
|
default:
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Unknown registration type %d received on %s from %s, discarding registration message",
|
|
pbuf->pktinfo.haBindingRegType,
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_sa(proc, pbuf->ipmip4.ipmip.srcinfo.src)));
|
|
goto error_out;
|
|
}
|
|
|
|
error_out:
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_revoke_request
|
|
*===========================================================================
|
|
* Description: Send a revocation request for this particular binding
|
|
* Parameters: data - Data
|
|
* proc - Process
|
|
* node - Node
|
|
* binding - Binding
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmipha_reg_revoke_request(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_node_t *node,
|
|
Ipmipha_node_binding_t *binding)
|
|
{
|
|
/**/
|
|
Ipmip_buffer_t rbuf;
|
|
Ipmip4_regrevreq_t regrev;
|
|
ipcom_memset(®rev, 0, sizeof(regrev));
|
|
|
|
regrev.type = IPMIP4_TYPE_REG_REGREVREQ;
|
|
regrev.home_address = node->haNodeHomeAddress.prefix;
|
|
regrev.home_domain = node->ifp->iff.ifaddr;
|
|
regrev.foreign_domain = binding->mib.haMobilityBindingCOA.s_addr;
|
|
|
|
binding->haBindingRevocationTimeStamp = ipmip4_util_now() + 1;
|
|
regrev.identifier = ip_htonl(binding->haBindingRevocationTimeStamp);
|
|
|
|
regrev.flags = ip_htons(IPMIP4_REG_EXT_REGREV_FLAG_AGENT);
|
|
if (IP_BIT_ISSET(binding->haBindingTunnelFlags, IPMIP4_TUNNELMODE_REVOCATION_INFORM))
|
|
regrev.flags |= ip_htons(IPMIP4_REG_EXT_REGREV_FLAG_INFORM);
|
|
ipmip_buffer_init(&rbuf);
|
|
|
|
/* Add the header */
|
|
ipmip_buffer_append(&rbuf, ®rev, sizeof(regrev));
|
|
|
|
if (IP_BIT_ISTRUE(binding->mib.haMobilityBindingRegFlags, IPMIP4_CODE_REQ_DECAPSULATION))
|
|
{
|
|
if (node->haLastHomeSA == IP_NULL)
|
|
goto error_out;
|
|
|
|
if (!ipmip4_auth_append_mobile_to_home(&rbuf, node->haLastHomeSA))
|
|
goto error_out;
|
|
}
|
|
else
|
|
{
|
|
if (binding->haLastForeignSA == IP_NULL)
|
|
goto error_out;
|
|
|
|
if (!ipmip4_auth_append_foreign_to_home(&rbuf, binding->haLastForeignSA))
|
|
goto error_out;
|
|
}
|
|
|
|
/* Send packet using UDP socket */
|
|
if (ipmip4_pkt_udp_sendmsg(&data->ipmip4,
|
|
proc,
|
|
&rbuf,
|
|
node->ifp->iff.ifaddr,
|
|
data->ipmip4.pkt->s_udp_out.sin_port,
|
|
binding->haBindingTunnelingEndpoint,
|
|
binding->haBindingTunnelingPort,
|
|
IP_NULL) == IP_TRUE)
|
|
{
|
|
ipmip_buffer_release(&rbuf);
|
|
return IP_TRUE;
|
|
}
|
|
|
|
error_out:
|
|
/* Remove the reference */
|
|
ipmip_buffer_release(&rbuf);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
IPMIPHA_REG_REQUEST_INIT,
|
|
IPMIPHA_REG_REQUEST_CREATE,
|
|
IPMIPHA_REG_REQUEST_PROCESS,
|
|
IPMIPHA_REG_REQUEST_AAA,
|
|
IPMIPHA_REG_REQUEST_FA_AUTH,
|
|
IPMIPHA_REG_REQUEST_HA_AUTH,
|
|
IPMIPHA_REG_REQUEST_AUTH_DONE,
|
|
IPMIPHA_REG_REQUEST_EXT,
|
|
IPMIPHA_REG_REQUEST_PARAMS,
|
|
IPMIPHA_REG_REQUEST_HOME_ADDRESS,
|
|
IPMIPHA_REG_REQUEST_BINDING_UPDATE,
|
|
IPMIPHA_REG_REQUEST_ENABLE
|
|
};
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_request_process
|
|
*===========================================================================
|
|
* Description: Process a container stage
|
|
* Parameters: pbuf - The packet buffer
|
|
* req - Type of major request
|
|
* Returns: IP_FALSE
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipmipha_reg_request_process(int event,
|
|
Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_pktbuf_t *pbuf,
|
|
Ipmipha_node_t *node)
|
|
{
|
|
if (event == IPMIP_TIMER_EVENT_RUN)
|
|
{
|
|
Ipmipha_node_binding_t *binding = IP_NULL;
|
|
|
|
if (node != IP_NULL)
|
|
pbuf->node = node;
|
|
else
|
|
{
|
|
/* Restore any stored values */
|
|
node = (Ipmipha_node_t *)pbuf->node;
|
|
}
|
|
|
|
/* Always init binding */
|
|
binding = (Ipmipha_node_binding_t *)pbuf->binding;
|
|
|
|
if (node)
|
|
ipmip_timer_prepare(&data->ipmip4.ipmip, proc, &node->service, node->lock, (Ipmip_timer_func_t)ipmipha_reg_request_process, pbuf, node);
|
|
|
|
switch (pbuf->pktinfo.haBindingParsingState)
|
|
{
|
|
case IPMIPHA_REG_REQUEST_INIT:
|
|
if (node == IP_NULL)
|
|
{
|
|
/* Are we trying to use address allocation? */
|
|
if (pbuf->pktinfo.haBindingHomeAddress == 0)
|
|
{
|
|
/* Check if there's a NAI already matching this particular node */
|
|
pbuf->pktinfo.haBindingParsingState = IPMIPHA_REG_REQUEST_CREATE;
|
|
if (ipmipha_node_nai_lookup(data,
|
|
proc,
|
|
pbuf->iff.priv,
|
|
pbuf->ipmip4.ext.mobile.nai_mobile,
|
|
&pbuf->ipmip4.ipmip.timeout,
|
|
(Ipmip_timer_func_t)ipmipha_reg_request_process,
|
|
pbuf))
|
|
return IPMIP_TIMER_RET_DONE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Flag up the last SA used for mobile home bindings; */
|
|
pbuf->pktinfo.haBindingSPIMobileHome = node->haLastHomeSA;
|
|
}
|
|
|
|
/* this is an intentional fall through to the next case */
|
|
case IPMIPHA_REG_REQUEST_CREATE:
|
|
if (node == IP_NULL)
|
|
{
|
|
/* Silently discard */
|
|
if (IP_BIT_ISSET(data->shutdown, IPMIPHA_SHUTDOWN_NODE))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request silently discarded due to agent being paused",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
}
|
|
|
|
if (pbuf->pktinfo.haBindingHomeAddress == 0 &&
|
|
pbuf->ipmip4.ext.mobile.nai_mobile == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to neither nai nor home address is specified (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_POORLY_FORMED_REQUEST));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_POORLY_FORMED_REQUEST);
|
|
}
|
|
|
|
/* No node found; create one */
|
|
node = ipmipha_node_create(data,
|
|
proc,
|
|
pbuf->iff.priv,
|
|
pbuf->pktinfo.haBindingHomeAddress,
|
|
pbuf->ipmip4.ext.mobile.nai_mobile);
|
|
if (node == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to out of memory allocating node (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_INSUFFICIENT_RESOURCES));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
/* Store the node */
|
|
pbuf->node = node;
|
|
|
|
/* Invoke recursively */
|
|
pbuf->pktinfo.haBindingParsingState = IPMIPHA_REG_REQUEST_PROCESS;
|
|
ipmip_timer_call(&data->ipmip4.ipmip, proc, node->lock, (Ipmip_timer_func_t)ipmipha_reg_request_process, pbuf, node);
|
|
return IPMIP_TIMER_RET_DONE;
|
|
}
|
|
|
|
/* FALL THROUGH */
|
|
case IPMIPHA_REG_REQUEST_PROCESS:
|
|
if (pbuf->ipmip4.ipmip.message != 0)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to %s (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->ipmip4.ipmip.message,
|
|
pbuf->ipmip4.ipmip.error_code));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, pbuf->ipmip4.ipmip.error_code);
|
|
}
|
|
|
|
/* Try find the appropriate binding */
|
|
if (binding == IP_NULL)
|
|
{
|
|
if ((binding = ipmipha_node_binding_coa(data, proc, node, pbuf->pktinfo.haBindingCOA)) != IP_NULL)
|
|
pbuf->binding = binding;
|
|
}
|
|
|
|
/* No keyreq's */
|
|
if (node->haBindingHomeSA != IP_NULL)
|
|
pbuf->pktinfo.haBindingMobileHomeSAPolicyOK = ipmipha_reg_verify_keygen(node->haBindingHomeSA, (Ipmip4_ext_auth_t*)pbuf->ipmip4.ext.mobile.mobile_home);
|
|
|
|
/* FALL THROUGH */
|
|
case IPMIPHA_REG_REQUEST_AAA:
|
|
pbuf->pktinfo.haBindingParsingState = IPMIPHA_REG_REQUEST_AAA;
|
|
if (ipmipha_node_function_request_validate(data, proc, node, pbuf, IPMIPHA_FUNCTION_AAA))
|
|
return IPMIP_TIMER_RET_PENDING;
|
|
|
|
if (pbuf->ipmip4.ipmip.message != IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to %s (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->ipmip4.ipmip.message,
|
|
IPMIP4_CODE_REP_HA_BAD_AAA_AUTH));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_BAD_AAA_AUTH);
|
|
}
|
|
|
|
if (pbuf->haBindingAAAVerified == IP_TRUE)
|
|
node->haNodeAAAVerificationTime = pbuf->haBindingTimeStamp;
|
|
else if (pbuf->pktinfo.haBindingForeignHomeSAPolicyOK == 0 || pbuf->pktinfo.haBindingMobileHomeSAPolicyOK == 0)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request silently discarded due to Insufficient security extensions supplied, and the mn-aaa extension could not be processed (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
}
|
|
|
|
/* FALL THROUGH */
|
|
case IPMIPHA_REG_REQUEST_HA_AUTH:
|
|
/* If there's a security association created due to AAA; indicate it */
|
|
if (node->haBindingHomeSA != IP_NULL)
|
|
pbuf->pktinfo.haBindingSPIMobileHome = node->haBindingHomeSA;
|
|
|
|
/* Verify */
|
|
if (pbuf->ipmip4.ext.mobile.mobile_home)
|
|
{
|
|
/**/
|
|
Ipmip4_ext_auth_t *auth = (Ipmip4_ext_auth_t *) pbuf->ipmip4.ext.mobile.mobile_home;
|
|
|
|
/* We have SPI's assigned to this particular node; these SPI's has been created
|
|
* due to AAA, and aren't globally available -- If they exist, the MUST be matched */
|
|
if (pbuf->pktinfo.haBindingSPIMobileHome != IP_NULL)
|
|
{
|
|
/* Use packet buffer's new SA first; fall back on nodes otherwise */
|
|
if (pbuf->pktinfo.haBindingSPIMobileHome->spi != IP_GET_HTONL(auth->spi))
|
|
{
|
|
/* Bad SPI */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to bad SPI %d in mobile-home authentication extension, do not match AAA generated SPI %d (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IP_GET_HTONL(auth->spi),
|
|
pbuf->pktinfo.haBindingSPIMobileHome->spi,
|
|
IPMIP4_CODE_REP_HA_MN_FAILED_AUTH));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_MN_FAILED_AUTH);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (node->haLastHomeSA == IP_NULL || node->haLastHomeSA->spi != IP_GET_HTONL(auth->spi))
|
|
{
|
|
pbuf->pktinfo.haBindingSPIMobileHome = ipmip4_auth_spi_get(pbuf->iff.priv->security.spi_ctx, IP_GET_HTONL(auth->spi));
|
|
if (pbuf->pktinfo.haBindingSPIMobileHome == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to bad SPI in mobile-home authentication extension, do not match any configured security association SPI %d (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IP_GET_HTONL(auth->spi),
|
|
IPMIP4_CODE_REP_HA_MN_FAILED_AUTH));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_MN_FAILED_AUTH);
|
|
}
|
|
|
|
if (pbuf->iff.priv->security.spi_mn_lookup_required)
|
|
{
|
|
if (node->haLastHomeSA != IP_NULL)
|
|
{
|
|
/* Go use the configured value */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to mobile node used an invalid security association SPI %d, configured to use %d (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->pktinfo.haBindingSPIMobileHome->spi,
|
|
node->haLastHomeSA->spi,
|
|
IPMIP4_CODE_REP_HA_MN_FAILED_AUTH));
|
|
pbuf->pktinfo.haBindingSPIMobileHome = node->haLastHomeSA;
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_MN_FAILED_AUTH);
|
|
}
|
|
else
|
|
{
|
|
Ipmip4_auth_spi_t *spi = ipmipha_reg_spi_lookup_home_sa(data, proc, pbuf);
|
|
if (spi == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request silently discarded due to mobile node lacks configured security association with this home agent",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
pbuf->pktinfo.haBindingSPIMobileHome = IP_NULL;
|
|
return ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
}
|
|
else if(spi->spi != pbuf->pktinfo.haBindingSPIMobileHome->spi)
|
|
{
|
|
/* Go use the configured value */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to mobile node used an invalid security association SPI %d, configured to use %d (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->pktinfo.haBindingSPIMobileHome->spi,
|
|
spi->spi,
|
|
IPMIP4_CODE_REP_HA_MN_FAILED_AUTH));
|
|
pbuf->pktinfo.haBindingSPIMobileHome = spi;
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_MN_FAILED_AUTH);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Use the cached SPI */
|
|
pbuf->pktinfo.haBindingSPIMobileHome = node->haLastHomeSA;
|
|
}
|
|
}
|
|
|
|
pbuf->pktinfo.haBindingParsingState = IPMIPHA_REG_REQUEST_FA_AUTH;
|
|
if (ipmip4_auth_verify(&data->ipmip4,
|
|
proc,
|
|
&pbuf->ipmip4,
|
|
pbuf->ipmip4.ext.mobile.mobile_home,
|
|
pbuf->pktinfo.haBindingSPIMobileHome,
|
|
node->lock,
|
|
(Ipmip_timer_func_t)ipmipha_reg_request_process))
|
|
return IPMIP_TIMER_RET_PENDING;
|
|
}
|
|
else if (pbuf->pktinfo.haBindingSPIMobileHome == IP_NULL)
|
|
{
|
|
/* Set it to the binding SA */
|
|
if ((pbuf->pktinfo.haBindingSPIMobileHome = ipmipha_reg_spi_lookup_home_sa(data, proc, pbuf)) == IP_NULL)
|
|
{
|
|
/* Unknown security association */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request silently discarded due to mobile node lacks security association with home agent",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
}
|
|
}
|
|
|
|
/* FALL THROUGH */
|
|
/* this is an intentional fall through to the next case */
|
|
case IPMIPHA_REG_REQUEST_FA_AUTH:
|
|
if (pbuf->ipmip4.ipmip.message != IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to %s (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->ipmip4.ipmip.message,
|
|
IPMIP4_CODE_REP_HA_FA_FAILED_AUTH));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_FA_FAILED_AUTH);
|
|
}
|
|
|
|
/* Verify */
|
|
if (pbuf->pktinfo.haBindingTimeGranted != 0)
|
|
{
|
|
if (pbuf->ipmip4.ext.mobile.foreign_home)
|
|
{
|
|
Ipmip4_ext_auth_t *auth = (Ipmip4_ext_auth_t *) pbuf->ipmip4.ext.mobile.foreign_home;
|
|
|
|
/* Verify the SPI we should use for foreign agent */
|
|
if (pbuf->haBindingForeignSA != IP_NULL || (binding != IP_NULL && binding->haBindingForeignSA != IP_NULL))
|
|
{
|
|
pbuf->pktinfo.haBindingSPIForeignHome = pbuf->haBindingForeignSA? pbuf->haBindingForeignSA : binding->haBindingForeignSA;
|
|
if(IP_GET_HTONL(auth->spi) != pbuf->pktinfo.haBindingSPIForeignHome->spi)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to foreign agent used an invalid security association SPI %d, should use generated %d (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IP_GET_HTONL(auth->spi),
|
|
pbuf->pktinfo.haBindingSPIForeignHome->spi,
|
|
IPMIP4_CODE_REP_HA_FA_FAILED_AUTH));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_FA_FAILED_AUTH);
|
|
}
|
|
}
|
|
else if (binding == IP_NULL || binding->haLastForeignSA == IP_NULL || binding->haLastForeignSA->spi != IP_GET_HTONL(auth->spi))
|
|
{
|
|
pbuf->pktinfo.haBindingSPIForeignHome = ipmip4_auth_spi_get(pbuf->iff.priv->security.spi_ctx, IP_GET_HTONL(auth->spi));
|
|
if (pbuf->pktinfo.haBindingSPIForeignHome == IP_NULL)
|
|
{
|
|
/* Unknown security association */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to foreign agent requested a non-existant security association (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_FA_FAILED_AUTH));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_FA_FAILED_AUTH);
|
|
}
|
|
|
|
if (pbuf->iff.priv->security.spi_fa_lookup_required)
|
|
{
|
|
Ipmip4_auth_spi_t *spi = ipmipha_reg_spi_lookup_foreign_sa(data, proc, pbuf);
|
|
if (spi == IP_NULL)
|
|
{
|
|
/* Unknown security association */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to foreign agent lacks configured security association with this home agent (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_FA_FAILED_AUTH));
|
|
pbuf->pktinfo.haBindingSPIForeignHome = IP_NULL;
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_FA_FAILED_AUTH);
|
|
}
|
|
else if(spi->spi != pbuf->pktinfo.haBindingSPIForeignHome->spi)
|
|
{
|
|
/* Go use the configured value */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to foreign agent used an invalid security association SPI %d, configured to use %d (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->pktinfo.haBindingSPIForeignHome->spi,
|
|
spi->spi,
|
|
IPMIP4_CODE_REP_HA_FA_FAILED_AUTH));
|
|
pbuf->pktinfo.haBindingSPIForeignHome = spi;
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_FA_FAILED_AUTH);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pbuf->pktinfo.haBindingSPIForeignHome = binding->haLastForeignSA;
|
|
}
|
|
|
|
pbuf->pktinfo.haBindingParsingState = IPMIPHA_REG_REQUEST_AUTH_DONE;
|
|
if (ipmip4_auth_verify(&data->ipmip4,
|
|
proc,
|
|
&pbuf->ipmip4,
|
|
pbuf->ipmip4.ext.mobile.foreign_home,
|
|
pbuf->pktinfo.haBindingSPIForeignHome,
|
|
node->lock,
|
|
(Ipmip_timer_func_t)ipmipha_reg_request_process))
|
|
return IPMIP_TIMER_RET_PENDING;
|
|
}
|
|
else
|
|
{
|
|
/* Store the SA */
|
|
if (pbuf->haBindingForeignSA != IP_NULL || (binding != IP_NULL && binding->haBindingForeignSA != IP_NULL))
|
|
pbuf->pktinfo.haBindingSPIForeignHome = pbuf->haBindingForeignSA? pbuf->haBindingForeignSA : binding->haBindingForeignSA;
|
|
}
|
|
}
|
|
|
|
/* this is an intentional fall through to the next case */
|
|
case IPMIPHA_REG_REQUEST_AUTH_DONE:
|
|
if (pbuf->ipmip4.ipmip.message != 0)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to %s (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->ipmip4.ipmip.message,
|
|
IPMIP4_CODE_REP_HA_MN_FAILED_AUTH));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_MN_FAILED_AUTH);
|
|
}
|
|
|
|
if (pbuf->ipmip4.ext.mobile.nai_mobile == IP_NULL && pbuf->iff.priv->mn_nai_require)
|
|
{
|
|
/* Go use the configured value */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to mobile node did not provide mobile NAI, and home agent configured to require it (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_ADMIN_PROHIBIT));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_ADMIN_PROHIBIT);
|
|
}
|
|
|
|
/* Deal with the CVSE; */
|
|
switch (pbuf->ipmip4.ext.mobile.result)
|
|
{
|
|
case IPMIP4_REG_EXT_UNKNOWN_VSE:
|
|
if (IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.erronous, pbuf->pktinfo.haBindingAAAAuth))
|
|
{
|
|
/* Mobile node provided VSE */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to invalid or unsupported CVSE sent by the mobile node (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_ERROR_HA_1));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_ERROR_HA_1);
|
|
}
|
|
else
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to invalid or unsupported CVSE sent by the foreign agent (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_ERROR_HA_2));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_ERROR_HA_2);
|
|
}
|
|
}
|
|
|
|
if (IP_BIT_ISTRUE(node->state, IPMIPHA_NODE_STATE_HOME_ADDRESS))
|
|
pbuf->pktinfo.haBindingResolvedHomeAddress = node->haNodeHomeAddress.prefix;
|
|
|
|
/* this is an intentional fall through to the next case */
|
|
case IPMIPHA_REG_REQUEST_EXT:
|
|
pbuf->pktinfo.haBindingParsingState = IPMIPHA_REG_REQUEST_EXT;
|
|
if (ipmipha_node_function_request_validate(data, proc, node, pbuf, IPMIPHA_FUNCTION_REGEXT))
|
|
return IPMIP_TIMER_RET_PENDING;
|
|
|
|
if (node->registrations == 0)
|
|
{
|
|
if (pbuf->pktinfo.haBindingResolvedHomeAgentAddress)
|
|
pbuf->pktinfo.haBindingHomeAgentAddress = pbuf->pktinfo.haBindingResolvedHomeAgentAddress;
|
|
}
|
|
else
|
|
{
|
|
/**/
|
|
pbuf->pktinfo.haBindingHomeAgentAddress = pbuf->iff.pub->ifaddr;
|
|
}
|
|
|
|
if (pbuf->ipmip4.ipmip.message != 0)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to %s (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
pbuf->ipmip4.ipmip.message,
|
|
pbuf->ipmip4.ipmip.error_code));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, pbuf->ipmip4.ipmip.error_code);
|
|
}
|
|
|
|
if (pbuf->pktinfo.haBindingHomeAgentAddress != pbuf->iff.pub->ifaddr)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to request not destined for this home agent(discovery?) (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_UNKNOWN_HOME_AGENT_ADDR));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_UNKNOWN_HOME_AGENT_ADDR);
|
|
}
|
|
|
|
/* FALL THROUGH */
|
|
case IPMIPHA_REG_REQUEST_PARAMS:
|
|
/* Set the agent bit */
|
|
if (pbuf->iff.priv->replay_diff != 0)
|
|
{
|
|
Ip_time_t packet_time = (Ip_time_t) (ip_ntohl(pbuf->pktinfo.haBindingRegIDHigh) - IPMIP4_JAN_1970);
|
|
|
|
if ((unsigned)(pbuf->haBindingTimeStamp - packet_time) > pbuf->iff.priv->replay_diff)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to replay protection: request time = %s, HA time = %s, diff=%d seconds (allowed=%d) (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
ipmip_ntop_time(proc, packet_time),
|
|
ipmip_ntop_time(proc, pbuf->haBindingTimeStamp),
|
|
pbuf->haBindingTimeStamp - packet_time,
|
|
pbuf->iff.priv->replay_diff,
|
|
IPMIP4_CODE_REP_HA_REG_ID_MISMATCH));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_REG_ID_MISMATCH);
|
|
}
|
|
}
|
|
|
|
if (pbuf->pktinfo.haBindingTimeGranted != 0)
|
|
{
|
|
pbuf->pktinfo.haBindingTunnelType = ipmipha_reg_tunnel_type(pbuf);
|
|
if (pbuf->iff.priv->tunnel.enabled[pbuf->pktinfo.haBindingTunnelType] == IP_FALSE)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to encapsulation %s unavailable (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
ipmip_util_tunnel_to_name(pbuf->pktinfo.haBindingTunnelType),
|
|
IPMIP4_CODE_REP_HA_ENCAP_UNAVAIL));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_ENCAP_UNAVAIL);
|
|
}
|
|
|
|
/* Reverse tunneling required but not set */
|
|
if (IP_BIT_ISFALSE(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_REVERSE_TUNNELING) &&
|
|
pbuf->iff.priv->tunnel.reverse == IPMIP_SYSVAR_MODE_REQUIRED)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to reverse tunneling required - T bit not set (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_REV_TUNNEL_MANDATORY));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_REV_TUNNEL_MANDATORY);
|
|
}
|
|
/* Reverse tunneling forbidden but set */
|
|
else if (IP_BIT_ISTRUE(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_REVERSE_TUNNELING) &&
|
|
pbuf->iff.priv->tunnel.reverse == IPMIP_SYSVAR_MODE_DISABLED)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to reverse tunneling forbidden - T bit is set (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_REV_TUNNEL_UNAVAIL));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_REV_TUNNEL_UNAVAIL);
|
|
}
|
|
}
|
|
|
|
if (pbuf->ipmip4.ext.mobile.revocation != IP_NULL)
|
|
{
|
|
IP_BIT_SET(pbuf->pktinfo.haBindingTunnelFlags, IPMIP4_TUNNELMODE_REVOCATION_REQUESTED);
|
|
|
|
if (pbuf->iff.priv->revocation)
|
|
{
|
|
Ipmip4_reg_ext_revocation_t *req = (Ipmip4_reg_ext_revocation_t *)pbuf->ipmip4.ext.mobile.revocation;
|
|
Ip_u16 flags;
|
|
|
|
/* Mobile node 'extension', but no 'D' flag set? */
|
|
if (IP_BIT_ISFALSE(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_DECAPSULATION))
|
|
{
|
|
if (IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.revocation, pbuf->pktinfo.haBindingInnerAuth))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to 'D' flag not set in request, but mobile node appended revocation extension (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_POORLY_FORMED_REQUEST));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_POORLY_FORMED_REQUEST);
|
|
}
|
|
|
|
if (IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.revocation, pbuf->pktinfo.haBindingOuterAuth))
|
|
IP_BIT_SET(pbuf->pktinfo.haBindingTunnelFlags, IPMIP4_TUNNELMODE_REVOCATION_RECEIVED);
|
|
|
|
}
|
|
else
|
|
{
|
|
if (IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.revocation, pbuf->pktinfo.haBindingInnerAuth))
|
|
IP_BIT_SET(pbuf->pktinfo.haBindingTunnelFlags, IPMIP4_TUNNELMODE_REVOCATION_RECEIVED);
|
|
}
|
|
|
|
if (IP_BIT_ARESET(pbuf->pktinfo.haBindingTunnelFlags, IPMIP4_TUNNELMODE_REVOCATION_CONFIRMED))
|
|
{
|
|
Ipmip4_reg_ext_revocation_t rev_rep;
|
|
|
|
ipcom_memset(&rev_rep, 0, sizeof(rev_rep));
|
|
|
|
flags = IP_GET_NTOHS(&req->flags);
|
|
pbuf->pktinfo.haBindingRevocationInform = IP_BIT_ISTRUE(flags, IPMIP4_REG_EXT_REVOCATION_INFORM);
|
|
pbuf->pktinfo.haBindingRevocationTimeStamp = IP_GET_NTOHL(&req->timestamp);
|
|
|
|
rev_rep.type = IPMIP4_EXT_TYPE_REVOCATION;
|
|
rev_rep.length = sizeof(rev_rep) - 2;
|
|
rev_rep.timestamp = ipmip4_util_now();
|
|
rev_rep.timestamp = ip_htonl(rev_rep.timestamp);
|
|
|
|
/* */
|
|
if (pbuf->pktinfo.haBindingRevocationInform)
|
|
rev_rep.flags |= ip_htons(IPMIP4_REG_EXT_REVOCATION_INFORM);
|
|
|
|
if (IP_BIT_ISFALSE(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_DECAPSULATION))
|
|
ipmip4_msgext_buffer_append_shdr(&pbuf->reply_fa, (void *)&rev_rep);
|
|
else
|
|
ipmip4_msgext_buffer_append_shdr(&pbuf->reply_mn, (void *)&rev_rep);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pbuf->ipmip4.ext.mobile.udp_tunnel_req != IP_NULL)
|
|
{
|
|
IP_BIT_SET(pbuf->pktinfo.haBindingTunnelFlags, IPMIP4_TUNNELMODE_NAT_T_REQUESTED);
|
|
/* UDP encapsulation requested */
|
|
if (pbuf->iff.priv->nat_t)
|
|
{
|
|
Ipmip4_reg_ext_udp_tunnel_req_t *req = (Ipmip4_reg_ext_udp_tunnel_req_t *) pbuf->ipmip4.ext.mobile.udp_tunnel_req;
|
|
Ip_u8 encap;
|
|
|
|
|
|
encap = ipmip_util_proto_to_tunnel(req->encap);
|
|
|
|
/**/
|
|
if (IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.udp_tunnel_req, pbuf->pktinfo.haBindingInnerAuth))
|
|
{
|
|
/* Mobile node 'extension', but no 'D' flag set? */
|
|
if (IP_BIT_ISFALSE(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_DECAPSULATION))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to 'D' flag not set in request, but mobile node used NAT-T (RFC3519) UDP Tunnel request (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_POORLY_FORMED_REQUEST));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_POORLY_FORMED_REQUEST);
|
|
}
|
|
/* This registration is done through the FA; co-located forced registration */
|
|
if (IP_BIT_ISTRUE(req->flags, IPMIP4_REG_EXT_UDP_FLAG_REGREQ))
|
|
{
|
|
/* Mark it as a pending NAT-T */
|
|
IP_BIT_SET(pbuf->pktinfo.haBindingTunnelFlags, IPMIP4_TUNNELMODE_NAT_T_UNRESOLVED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Foreign agent 'extension', but co-located flag set? */
|
|
if (IP_BIT_ISTRUE(req->flags, IPMIP4_REG_EXT_UDP_FLAG_REGREQ))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to 'R' flag set in NAT-T (RFC3519) UDP Tunnel requests, but extension outside MN-HA authentication (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_POORLY_FORMED_REQUEST));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_POORLY_FORMED_REQUEST);
|
|
}
|
|
}
|
|
|
|
pbuf->pktinfo.haBindingTunnelEndpoint = pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_addr.s_addr;
|
|
|
|
{
|
|
Ipmip4_reg_ext_udp_tunnel_rep_t rep;
|
|
|
|
ipcom_memset(&rep, 0, sizeof(rep));
|
|
if (pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_addr.s_addr == pbuf->pktinfo.haBindingCOA && IP_BIT_ISFALSE(req->flags, IPMIP4_REG_EXT_UDP_FLAG_FORCED))
|
|
rep.code = 64;
|
|
else
|
|
{
|
|
IP_BIT_SET(pbuf->pktinfo.haBindingTunnelFlags, IPMIP4_TUNNELMODE_NAT_T_RECEIVED);
|
|
|
|
if (encap != IPMIP_TUNNELTYPE_NONE &&
|
|
encap != pbuf->pktinfo.haBindingTunnelType)
|
|
{
|
|
if (pbuf->iff.priv->tunnel.enabled[encap] == IP_FALSE)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to nat traversal encapsulation %s unavailable (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
ipmip_util_tunnel_to_name(encap),
|
|
IPMIP4_CODE_REP_HA_ENCAP_UNAVAIL));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_ENCAP_UNAVAIL);
|
|
}
|
|
|
|
pbuf->pktinfo.haBindingTunnelType = encap;
|
|
}
|
|
}
|
|
|
|
rep.keep_alive = ip_htons(pbuf->iff.priv->nat_t_keepalive);
|
|
rep.type = IPMIP4_EXT_TYPE_UDP_TUNNEL_REP;
|
|
rep.length = sizeof(rep) - 2;
|
|
rep.flags = req->flags & IPMIP4_REG_EXT_UDP_FLAG_FORCED;
|
|
|
|
if (IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.udp_tunnel_req, pbuf->pktinfo.haBindingInnerAuth))
|
|
ipmip4_msgext_buffer_append_shdr(&pbuf->reply_mn, (void *)&rep);
|
|
else
|
|
ipmip4_msgext_buffer_append_shdr(&pbuf->reply_fa, (void *)&rep);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* FALL THROUGH */
|
|
case IPMIPHA_REG_REQUEST_HOME_ADDRESS:
|
|
if (node->haNodeHomeAddress.prefix != 0)
|
|
pbuf->pktinfo.haBindingHomeAddress = node->haNodeHomeAddress.prefix;
|
|
else if (pbuf->pktinfo.haBindingResolvedHomeAddress != 0)
|
|
pbuf->pktinfo.haBindingHomeAddress = pbuf->pktinfo.haBindingResolvedHomeAddress;
|
|
|
|
if (pbuf->pktinfo.haBindingHomeAddress == 0)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to unable to assign home address to request (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_ADMIN_PROHIBIT));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_ADMIN_PROHIBIT);
|
|
}
|
|
|
|
if (IP_BIT_ISFALSE(node->state, IPMIPHA_NODE_STATE_HOME_ADDRESS))
|
|
{
|
|
/**/
|
|
if (node->haNodeHomeAddress.prefix == 0 && !ipmipha_node_home_address_assign(data, proc, node, pbuf->pktinfo.haBindingHomeAddress))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to home address collision in dynamic assignment (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_ADMIN_PROHIBIT));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_ADMIN_PROHIBIT);
|
|
}
|
|
|
|
IP_BIT_SET(node->state, IPMIPHA_NODE_STATE_HOME_ADDRESS);
|
|
}
|
|
|
|
/* FALL THROUGH */
|
|
case IPMIPHA_REG_REQUEST_BINDING_UPDATE:
|
|
/* */
|
|
if (pbuf->pktinfo.haBindingTimeGranted == 0)
|
|
{
|
|
if (pbuf->pktinfo.haBindingCOA == node->haNodeHomeAddress.prefix)
|
|
{
|
|
/* Complete de-registration */
|
|
ipmipha_node_binding_delete(data, proc, node, IP_NULL);
|
|
ipmipha_node_silence(data, proc, node);
|
|
}
|
|
else if (binding != IP_NULL)
|
|
{
|
|
/* Delete this particular binding */
|
|
ipmipha_node_binding_delete(data, proc, node, binding);
|
|
}
|
|
|
|
/* Remove the pointers to this binding */
|
|
pbuf->binding = IP_NULL;
|
|
binding = IP_NULL;
|
|
}
|
|
else
|
|
{
|
|
/**/
|
|
if (binding == IP_NULL)
|
|
{
|
|
if (pbuf->iff.priv->simbind_enabled && IP_BIT_ISSET(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_SIM_BINDINGS))
|
|
{
|
|
Ipmipha_node_binding_t *collission;
|
|
/* Too many simbinds? */
|
|
if (node->bindings.size >= pbuf->iff.priv->simbind_max)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to too many simultaneous bindings (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_TOO_MANY_SIM));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_TOO_MANY_SIM);
|
|
}
|
|
|
|
collission = ipmipha_node_binding_endpoint(data, proc, node, pbuf->pktinfo.haBindingTunnelEndpoint);
|
|
|
|
/* If we collide; revoke the colliding endpoint */
|
|
if (collission)
|
|
{
|
|
IPMIP4_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Node %s registration of binding collided with a previous binding due to NAT-T. Old binding deleted",
|
|
ipmipha_node_describe(proc, node, binding)));
|
|
ipmipha_node_binding_delete(data, proc, node, collission);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IP_BIT_ISSET(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_SIM_BINDINGS))
|
|
{
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haMultiBindingUnsupported, 1);
|
|
pbuf->pktinfo.haBindingHAErrorCode = IPMIP4_CODE_REP_REG_ACCEPTED_BUT_NO_SIM_BINDS;
|
|
}
|
|
|
|
/* No SIM binds; revoke all other */
|
|
IPMIP4_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Node %s is moving, revoke old bindings",
|
|
ipmipha_node_describe(proc, node, binding)));
|
|
|
|
ipmipha_node_binding_revoke(data, proc, node, IP_NULL, IPMIP_SYSVAR_MODE_OPTIONAL, IP_TRUE);
|
|
}
|
|
|
|
/**/
|
|
binding = ipmipha_node_binding_create(data, proc, node, pbuf);
|
|
|
|
/* */
|
|
if (binding == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to out of memory allocating binding (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_INSUFFICIENT_RESOURCES));
|
|
return ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
|
|
/* reregister */
|
|
IPMIP4_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Node %s registered",
|
|
ipmipha_node_describe(proc, node, binding)));
|
|
}
|
|
else
|
|
{
|
|
/* reregister */
|
|
IPMIP4_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Node %s re-registered",
|
|
ipmipha_node_describe(proc, node, binding)));
|
|
ipmipha_node_binding_update(data, proc, node, binding, pbuf);
|
|
}
|
|
|
|
/**/
|
|
ipmipha_node_function_request_accept(data, proc, node, binding, pbuf);
|
|
}
|
|
|
|
/* */
|
|
IPMIPHA_MIB_COUNTER_ADD(data, data->mibRegCounters.haRegistrationAccepted, 1);
|
|
|
|
/* Update security associations */
|
|
ipmipha_node_security_associations(data, proc, node, binding, pbuf);
|
|
|
|
case IPMIPHA_REG_REQUEST_ENABLE:
|
|
pbuf->pktinfo.haBindingParsingState = IPMIPHA_REG_REQUEST_ENABLE;
|
|
if (ipmipha_node_enable(data, proc, node))
|
|
return IPMIP_TIMER_RET_PENDING;
|
|
|
|
/* Reply */
|
|
ipmipha_reg_reply(data, proc, node, pbuf);
|
|
break;
|
|
}
|
|
|
|
return IPMIP_TIMER_RET_DONE;
|
|
}
|
|
else
|
|
{
|
|
/* Cancelled or aborted */
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
return IPMIP_TIMER_RET_DONE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_reg_input_parse_request
|
|
*===========================================================================
|
|
* Description: Parses basic values in a registration request.
|
|
* Parameters: data - Data context
|
|
* proc - Process
|
|
* pbuf - Packet buffer.
|
|
* Returns: IP_TRUE on success
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmipha_reg_input_parse_request(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_pktbuf_t *pbuf)
|
|
{
|
|
/* Check length */
|
|
if (IPMIP_BUFFER_SIZE(&pbuf->ipmip4.ipmip.packet) < IPMIP4_REGREQ_LENGTH)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Truncated registration request [%d]", IPMIP_BUFFER_SIZE(&pbuf->ipmip4.ipmip.packet)));
|
|
ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
return IP_FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* Pointers to the packet */
|
|
Ipmip4_regreq_t *regreq = IPMIP_BUFFER_PTR(&pbuf->ipmip4.ipmip.packet);
|
|
|
|
/* Store pending reg information */
|
|
pbuf->pktinfo.haBindingRegIDLow = IP_GET_32ON8(®req->id[1]);
|
|
pbuf->pktinfo.haBindingRegIDHigh = IP_GET_32ON8(®req->id[0]);
|
|
pbuf->pktinfo.haBindingHomeAgentAddress = IP_GET_32ON8(®req->home_agent);
|
|
pbuf->pktinfo.haBindingHomeAddress = IP_GET_32ON8(®req->home_addr);
|
|
pbuf->pktinfo.haBindingHomeAddressRequested = pbuf->pktinfo.haBindingHomeAddress;
|
|
pbuf->pktinfo.haBindingTimeGranted = IP_GET_HTONS(®req->lifetime);
|
|
pbuf->pktinfo.haBindingTimeGranted = IP_MIN(pbuf->pktinfo.haBindingTimeGranted, pbuf->iff.priv->lifetime);
|
|
|
|
/* Store vital registration information */
|
|
pbuf->pktinfo.haBindingCOA = IP_GET_32ON8(®req->care_of_addr);
|
|
pbuf->pktinfo.haBindingTunnelEndpoint = pbuf->pktinfo.haBindingCOA;
|
|
pbuf->pktinfo.haBindingRegFlags = regreq->code;
|
|
|
|
/* If its a DHAA request; make certain to home address isn't explicitly set */
|
|
if ((pbuf->pktinfo.haBindingHomeAgentAddress == 0 || pbuf->pktinfo.haBindingHomeAgentAddress == 0xffffffff))
|
|
{
|
|
/* This home address is tentative; dont be too certain about it */
|
|
pbuf->pktinfo.haBindingHomeAddress = 0;
|
|
}
|
|
}
|
|
|
|
/* OK */
|
|
pbuf->ipmip4.ext.mobile.result = ipmip4_msgext_mobile_parse_ext(&data->ipmip4, proc, &pbuf->ipmip4, IPMIP4_REGREQ_LENGTH);
|
|
|
|
|
|
/* Parse extensions */
|
|
switch (pbuf->ipmip4.ext.mobile.result)
|
|
{
|
|
case IPMIP4_REG_EXT_FAILED_AUTH:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to bad or duplicate authentication extensions (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_FA_MN_FAILED_AUTH));
|
|
|
|
ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_MN_FAILED_AUTH);
|
|
return IP_FALSE;
|
|
case IPMIP4_REG_EXT_POORLY_FORMED:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to poorly formed request (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_FA_MN_FAILED_AUTH));
|
|
ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_POORLY_FORMED_REQUEST);
|
|
return IP_FALSE;
|
|
case IPMIP4_REG_EXT_DISCARD:
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request silently discarded",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/* Do we have an error code? */
|
|
if (pbuf->ipmip4.ipmip.message != 0)
|
|
return IP_FALSE;
|
|
|
|
/* Process this packet buffer */
|
|
/* No mobile home? */
|
|
/* No mobile home? */
|
|
if (pbuf->ipmip4.ext.mobile.mobile_home == IP_NULL && pbuf->ipmip4.ext.mobile.mn_aaa == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request silently discarded due to no mobile-home authentication or mn-aaa extension header found",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
return IP_FALSE;
|
|
}
|
|
else if (pbuf->ipmip4.ext.mobile.mobile_home && pbuf->ipmip4.ext.mobile.mn_aaa && IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.mn_aaa, pbuf->ipmip4.ext.mobile.mobile_home))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request silently discarded due to mn-aaa extension within mobile-home authentication",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
if (pbuf->ipmip4.ext.mobile.mobile_home != IP_NULL)
|
|
{
|
|
pbuf->pktinfo.haBindingInnerAuth = pbuf->ipmip4.ext.mobile.mobile_home;
|
|
pbuf->pktinfo.haBindingInnerAuthSize = IPMIP4_MSGEXT_SHDR_TOT_SIZE(pbuf->ipmip4.ext.mobile.mobile_home);
|
|
pbuf->pktinfo.haBindingMobileHomeSAPolicyOK = IP_TRUE;
|
|
}
|
|
|
|
if (pbuf->ipmip4.ext.mobile.foreign_home != IP_NULL)
|
|
{
|
|
pbuf->pktinfo.haBindingOuterAuth = pbuf->ipmip4.ext.mobile.foreign_home;
|
|
pbuf->pktinfo.haBindingOuterAuthSize = IPMIP4_MSGEXT_SHDR_TOT_SIZE(pbuf->ipmip4.ext.mobile.foreign_home);
|
|
pbuf->pktinfo.haBindingForeignHomeSAPolicyOK = IP_TRUE;
|
|
}
|
|
|
|
/**/
|
|
if (pbuf->ipmip4.ext.mobile.mn_aaa != IP_NULL)
|
|
{
|
|
pbuf->pktinfo.haBindingAAAAuth = pbuf->ipmip4.ext.mobile.mn_aaa;
|
|
pbuf->pktinfo.haBindingAAAAuthSize = IPMIP4_MSGEXT_LHDR_TOT_SIZE(pbuf->ipmip4.ext.mobile.mn_aaa);
|
|
|
|
if (pbuf->pktinfo.haBindingInnerAuth == IP_NULL)
|
|
{
|
|
pbuf->pktinfo.haBindingInnerAuth = pbuf->pktinfo.haBindingAAAAuth;
|
|
pbuf->pktinfo.haBindingInnerAuthSize = pbuf->pktinfo.haBindingAAAAuthSize;
|
|
}
|
|
|
|
if (pbuf->pktinfo.haBindingOuterAuth == IP_NULL)
|
|
{
|
|
pbuf->pktinfo.haBindingOuterAuth = pbuf->pktinfo.haBindingAAAAuth;
|
|
pbuf->pktinfo.haBindingOuterAuthSize = pbuf->pktinfo.haBindingAAAAuthSize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pbuf->pktinfo.haBindingAAAAuth = pbuf->ipmip4.ext.mobile.mobile_home;
|
|
pbuf->pktinfo.haBindingAAAAuthSize = IPMIP4_MSGEXT_SHDR_TOT_SIZE(pbuf->ipmip4.ext.mobile.mobile_home);
|
|
}
|
|
|
|
/* Truncate; remove any mobile to foreign data */
|
|
ipmip_buffer_shrink(&pbuf->ipmip4.ipmip.packet,
|
|
((Ip_u8 *)pbuf->pktinfo.haBindingAAAAuth - (Ip_u8 *)IPMIP_BUFFER_DATA(&pbuf->ipmip4.ipmip.packet)) + pbuf->pktinfo.haBindingAAAAuthSize);
|
|
|
|
/* Dont use a NAI that's not authenticated */
|
|
if (pbuf->ipmip4.ext.mobile.nai_mobile != IP_NULL && IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.nai_mobile, pbuf->pktinfo.haBindingInnerAuth) == IP_FALSE)
|
|
pbuf->ipmip4.ext.mobile.nai_mobile = IP_NULL;
|
|
|
|
/* Do we have a foreign-home authentication? */
|
|
if (pbuf->pktinfo.haBindingForeignHomeSAPolicyOK == IP_FALSE)
|
|
{
|
|
/* Do we require it? */
|
|
if (pbuf->pktinfo.haBindingTimeGranted != 0 &&
|
|
pbuf->iff.priv->fa_auth != 0 &&
|
|
IP_BIT_ISFALSE(pbuf->pktinfo.haBindingRegFlags, IPMIP4_CODE_REQ_DECAPSULATION))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request discarded due to required foreign-home authentication extension header not found (%d)",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA),
|
|
IPMIP4_CODE_REP_HA_FA_FAILED_AUTH));
|
|
ipmipha_reg_request_error(data, proc, pbuf, IPMIP4_CODE_REP_HA_FA_FAILED_AUTH);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
pbuf->pktinfo.haBindingForeignHomeSAPolicyOK = IP_TRUE;
|
|
}
|
|
|
|
if (pbuf->ipmip4.ext.mobile.challenge)
|
|
{
|
|
if (IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.challenge, pbuf->ipmip4.ext.mobile.mobile_home))
|
|
{
|
|
/* The challenge is not part of the MF authentication extension */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request silently discarded due to challenge extension within mobile-home authentication",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
if (IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.challenge, pbuf->pktinfo.haBindingAAAAuth) == IP_FALSE)
|
|
{
|
|
/* The challenge is not part of the MF authentication extension */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request silently discarded due to challenge extension not properly protected with mobile-foreign authentication",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
return IP_FALSE;
|
|
}
|
|
}
|
|
|
|
/* Verify keyreq */
|
|
if (pbuf->ipmip4.ext.mobile.mn_ha_keyreq != IP_NULL && !IPMIP4_MSGEXT_AUTHENTICATED(pbuf->ipmip4.ext.mobile.mn_ha_keyreq, pbuf->ipmip4.ext.mobile.mn_aaa))
|
|
{
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"%s@%s[%s] registration request silently discarded due to mn-ha key generation request not protected by mn-aaa authentication extension",
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingHomeAddress),
|
|
pbuf->iff.pub->ipmip.ifname,
|
|
ipmip_ntop_inet(proc, pbuf->pktinfo.haBindingCOA)));
|
|
ipmipha_reg_request_error(data, proc, pbuf, 0);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|