original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
@@ -0,0 +1,693 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_attr.c,v $ $Revision: 1.6 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_attr.c,v $
* $Author: jhorteli $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmip_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_clib2.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_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipmip.h>
#include <private/ipmip_util.h>
#include <private/ipmip_buffer.h>
#include <private/ipmip_context.h>
#include <private/ipmip_attr.h>
#include <private/ipmip_cli.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG2
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC Ip_size_t
ipmip_attr_hdr_create(Ipmip_buffer_t *buf,
Ip_u32 subsystem,
Ip_u32 errcode,
Ip_u32 seq,
Ip_u16 type,
Ip_u16 flags)
{
struct Ipmip_attr_header *hdr;
Ip_u32 size = IPMIP_ATTR_HDR_LENGTH(0);
Ip_size_t off = IPMIP_BUFFER_SIZE(buf);
if (!ipmip_buffer_reserve(buf, size))
return 0;
/* Initialize the netlink header */
hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_CURRENT(buf);
IP_SET_HTONS(&hdr->ah_type, type);
IP_SET_HTONS(&hdr->ah_flags, flags);
IP_SET_HTONL(&hdr->ah_len, size);
IP_SET_HTONL(&hdr->ah_subsystem, subsystem);
IP_SET_32ON8(&hdr->ah_sequence, seq);
IP_SET_HTONL(&hdr->ah_errcode, errcode);
/* Move past */
ipmip_buffer_append(buf, IP_NULL, size);
return off;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL int
ipmip_attr_command(struct Ipmip_context *ctx,
struct Ipmip_proc *proc,
struct Ipmip_cli_message *request)
{
struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&request->request);
Ip_size_t rhdr = 0;
struct Ipmip_attr *rta;
switch (IPMIP_ATTR_HDR_TYPE(hdr))
{
case IPMIP_CLI_EVENT_GET:
rhdr = ipmip_log_attr_request_events(ctx, proc, request);
break;
case IPMIP_CLI_EVENT_FLUSH:
rhdr = ipmip_attr_hdr_ack(&request->message, hdr);
ipmip_log_event_flush(ctx, proc);
break;
case IPMIP_CLI_EVENT_HISTORY_SET:
rta = ipmip_attr_hdr_find(hdr, IPMIP_CLI_ITEM_SIZE);
if (rta == IP_NULL)
return -IP_ERRNO_EINVAL;
rhdr = ipmip_attr_hdr_ack(&request->message, hdr);
ipmip_log_event_backlog(ctx, proc, ipmip_attr_get_u32(rta));
break;
case IPMIP_CLI_EVENT_HISTORY_GET:
ipmip_log_attr_request_history(ctx, proc, request);
break;
case IPMIP_CLI_LOG_LEVEL_SET:
rta = ipmip_attr_hdr_find(hdr, IPMIP_CLI_ITEM_SIZE);
if (rta == IP_NULL)
return -IP_ERRNO_EINVAL;
rhdr = ipmip_attr_hdr_ack(&request->message, hdr);
ipmip_log_loglevel(ctx, proc, ipmip_attr_get_u32(rta));
break;
case IPMIP_CLI_LOG_LEVEL_GET:
ipmip_log_attr_request_loglevel(ctx, proc, request);
break;
case IPMIP_CLI_CONFIG_GET:
default:
return -IP_ERRNO_ENOPROTOOPT;
}
/* If we have a reply header; terminate it */
ipmip_attr_hdr_finalize(&request->message, rhdr);
/* Commit the reply */
ipmip_cli_message_commit(ctx, proc, request);
return 0;
}
IP_GLOBAL Ip_size_t
ipmip_attr_put(Ipmip_buffer_t *buf,
Ip_u16 attrtype,
Ip_u32 attrlen,
const void *data)
{
Ip_u16 len = IPMIP_ATTR_LENGTH(attrlen);
Ip_size_t off = ipmip_buffer_append(buf, IP_NULL, len);
struct Ipmip_attr *attr = ipmip_buffer_offset(buf, off);
IP_SET_HTONS(&attr->attr_type, attrtype);
IP_SET_HTONS(&attr->attr_len, len);
if (data)
ipcom_memcpy(IPMIP_ATTR_DATA(attr), data, attrlen);
return off;
}
IP_GLOBAL Ip_size_t
ipmip_attr_put_u32(Ipmip_buffer_t *buf,
Ip_u16 attrtype,
Ip_u32 attrval)
{
attrval = ip_htonl(attrval);
/* Do invoke the real put function */
return ipmip_attr_put(buf, attrtype, sizeof(attrval), &attrval);
}
#ifdef IPCOM_USE_INET
IP_GLOBAL Ip_size_t
ipmip_attr_put_inet(Ipmip_buffer_t *buf,
Ip_u16 attrtype,
Ip_u32 attrval)
{
/* Do invoke the real put function */
return ipmip_attr_put(buf, attrtype, sizeof(attrval), &attrval);
}
#endif
#ifdef IPCOM_USE_INET6
IP_GLOBAL Ip_size_t
ipmip_attr_put_inet6(Ipmip_buffer_t *buf,
Ip_u16 attrtype,
const struct Ip_in6_addr *attrval)
{
/* Do invoke the real put function */
return ipmip_attr_put(buf, attrtype, sizeof(*attrval), attrval);
}
#endif
IP_GLOBAL Ip_size_t
ipmip_attr_put_u64(Ipmip_buffer_t *buf,
Ip_u16 attrtype,
Ip_u64 attrval)
{
attrval = IPMIP_BSWAP64(attrval);
/* Do invoke the real put function */
return ipmip_attr_put(buf, attrtype, sizeof(attrval), &attrval);
}
IP_GLOBAL Ip_size_t
ipmip_attr_put_time_t(Ipmip_buffer_t *buf,
Ip_u16 attrtype,
Ip_time_t attrval)
{
/* Do invoke the real put function */
return ipmip_attr_put_u64(buf, attrtype, (Ip_u64)attrval);
}
IP_GLOBAL Ip_size_t
ipmip_attr_put_strn(Ipmip_buffer_t *buf,
Ip_u16 attrtype,
const char *str,
Ip_size_t size)
{
Ip_size_t off = ipmip_attr_put(buf, attrtype, size + 1, IP_NULL);
struct Ipmip_attr *attr = ipmip_buffer_offset(buf, off);
ipcom_memcpy(IPMIP_ATTR_DATA(attr), str, size);
*(((char *)IPMIP_ATTR_DATA(attr)) + size) = '\0';
return off;
}
IP_GLOBAL Ip_size_t
ipmip_attr_put_str(Ipmip_buffer_t *buf,
Ip_u16 attrtype,
const char *str)
{
/* Add it */
return ipmip_attr_put(buf, attrtype, ipcom_strlen(str) + 1, str);
}
IP_GLOBAL Ip_size_t
ipmip_attr_begin(Ipmip_buffer_t *buf,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_put(buf, attrtype, 0, IP_NULL);
}
IP_GLOBAL void
ipmip_attr_end(Ipmip_buffer_t *buf,
Ip_size_t off)
{
Ip_size_t len = IPMIP_BUFFER_SIZE(buf) - off;
struct Ipmip_attr *attr = ipmip_buffer_offset(buf, off);
IP_SET_HTONS(&attr->attr_len, len);
}
IP_GLOBAL void
ipmip_attr_parse(int maxattr,
struct Ipmip_attr *attr,
Ip_size_t attrlen,
struct Ipmip_attr **attrtable)
{
ipcom_memset(attrtable, 0, sizeof(struct Ipmip_attr *) * maxattr);
while (IPMIP_ATTR_OK(attr, attrlen))
{
Ip_u16 flavor = IPMIP_ATTR_TYPE(attr);
if (flavor)
{
if (flavor < maxattr)
attrtable[flavor] = attr;
}
attr = IPMIP_ATTR_NEXT(attr, attrlen);
}
}
IP_GLOBAL void
ipmip_attr_hdr_parse(int maxattr,
struct Ipmip_attr_header *attrhdr,
struct Ipmip_attr **attrtable)
{
ipmip_attr_parse(maxattr, IPMIP_ATTR_HDR_DATA(attrhdr), IPMIP_ATTR_HDR_PAYLOAD(attrhdr), attrtable);
}
IP_GLOBAL struct Ipmip_attr *
ipmip_attr_find(struct Ipmip_attr *attr,
Ip_size_t attrlen,
Ip_u16 attrtype)
{
while (IPMIP_ATTR_OK(attr, (int)attrlen))
{
if (IPMIP_ATTR_TYPE(attr) == attrtype)
return attr;
attr = IPMIP_ATTR_NEXT(attr, attrlen);
}
return IP_NULL;
}
IP_GLOBAL struct Ipmip_attr *
ipmip_attr_payload_find(struct Ipmip_attr *attr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_find(IPMIP_ATTR_DATA(attr), IPMIP_ATTR_PAYLOAD(attr), attrtype);
}
IP_GLOBAL Ip_u32
ipmip_attr_payload_find_u32(struct Ipmip_attr *attr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_u32(ipmip_attr_payload_find(attr, attrtype));
}
IP_GLOBAL Ip_time_t
ipmip_attr_payload_find_time_t(struct Ipmip_attr *attr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_time_t(ipmip_attr_payload_find(attr, attrtype));
}
IP_GLOBAL Ip_u64
ipmip_attr_payload_find_u64(struct Ipmip_attr *attr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_u64(ipmip_attr_payload_find(attr, attrtype));
}
#ifdef IPCOM_USE_INET
IP_GLOBAL Ip_u32
ipmip_attr_payload_find_inet(struct Ipmip_attr *attr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_inet(ipmip_attr_payload_find(attr, attrtype));
}
#endif
#ifdef IPCOM_USE_INET6
IP_GLOBAL struct Ip_in6_addr *
ipmip_attr_payload_find_inet6(struct Ipmip_attr *attr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_inet6(ipmip_attr_payload_find(attr, attrtype));
}
#endif
IP_GLOBAL char *
ipmip_attr_payload_find_str(struct Ipmip_attr *attr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_str(ipmip_attr_payload_find(attr, attrtype));
}
IP_GLOBAL void *
ipmip_attr_payload_find_data(struct Ipmip_attr *attr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_data(ipmip_attr_payload_find(attr, attrtype));
}
IP_GLOBAL struct Ipmip_attr *
ipmip_attr_hdr_find(struct Ipmip_attr_header *attrhdr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_find(IPMIP_ATTR_HDR_DATA(attrhdr), IPMIP_ATTR_HDR_PAYLOAD(attrhdr), attrtype);
}
IP_GLOBAL Ip_u32
ipmip_attr_hdr_find_u32(struct Ipmip_attr_header *attrhdr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_u32(ipmip_attr_hdr_find(attrhdr, attrtype));
}
IP_GLOBAL Ip_u64
ipmip_attr_hdr_find_u64(struct Ipmip_attr_header *attrhdr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_u64(ipmip_attr_hdr_find(attrhdr, attrtype));
}
IP_GLOBAL char *
ipmip_attr_hdr_find_str(struct Ipmip_attr_header *attrhdr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_str(ipmip_attr_hdr_find(attrhdr, attrtype));
}
IP_GLOBAL void *
ipmip_attr_hdr_find_data(struct Ipmip_attr_header *attrhdr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_data(ipmip_attr_hdr_find(attrhdr, attrtype));
}
#ifdef IPCOM_USE_INET
IP_GLOBAL Ip_u32
ipmip_attr_hdr_find_inet(struct Ipmip_attr_header *attrhdr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_inet(ipmip_attr_hdr_find(attrhdr, attrtype));
}
#endif
#ifdef IPCOM_USE_INET6
IP_GLOBAL struct Ip_in6_addr *
ipmip_attr_hdr_find_inet6(struct Ipmip_attr_header *attrhdr,
Ip_u16 attrtype)
{
/**/
return ipmip_attr_get_inet6(ipmip_attr_hdr_find(attrhdr, attrtype));
}
#endif
IP_GLOBAL Ip_u32
ipmip_attr_get_u32(struct Ipmip_attr *attr)
{
if (attr)
return IP_GET_NTOHL(IPMIP_ATTR_DATA(attr));
return 0;
}
IP_GLOBAL Ip_u64
ipmip_attr_get_u64(struct Ipmip_attr *attr)
{
if (attr)
return ipmip_util_bswap64(IPMIP_ATTR_DATA(attr));
return 0;
}
IP_GLOBAL Ip_time_t
ipmip_attr_get_time_t(struct Ipmip_attr *attr)
{
if (attr)
return (Ip_time_t)ipmip_attr_get_u64(attr);
return 0;
}
#ifdef IPCOM_USE_INET
IP_GLOBAL Ip_u32
ipmip_attr_get_inet(struct Ipmip_attr *attr)
{
if (attr)
return IP_GET_32ON8(IPMIP_ATTR_DATA(attr));
return 0;
}
#endif
#ifdef IPCOM_USE_INET6
IP_GLOBAL struct Ip_in6_addr *
ipmip_attr_get_inet6(struct Ipmip_attr *attr)
{
if (attr)
return (struct Ip_in6_addr *)IPMIP_ATTR_DATA(attr);
return IP_NULL;
}
#endif
IP_GLOBAL char *
ipmip_attr_get_str(struct Ipmip_attr *attr)
{
if (attr)
return (char *)IPMIP_ATTR_DATA(attr);
return IP_NULL;
}
IP_GLOBAL Ip_size_t
ipmip_attr_get_strlen0(struct Ipmip_attr *attr)
{
if (attr)
return ipmip_util_strstrip0(IPMIP_ATTR_DATA(attr), IPMIP_ATTR_PAYLOAD(attr));
return 0;
}
IP_GLOBAL void *
ipmip_attr_get_data(struct Ipmip_attr *attr)
{
if (attr)
return (void *)IPMIP_ATTR_DATA(attr);
return IP_NULL;
}
IP_GLOBAL Ip_size_t
ipmip_attr_hdr_req_create(Ipmip_buffer_t *buf,
Ip_u32 subsystem,
Ip_u32 seq,
Ip_u16 type)
{
return ipmip_attr_hdr_create(buf, subsystem, 0, seq, type, 0);
}
IP_GLOBAL Ip_size_t
ipmip_attr_hdr_ack_create(Ipmip_buffer_t *buf,
Ip_u32 subsystem,
Ip_u32 seq,
Ip_u16 type)
{
return ipmip_attr_hdr_create(buf, subsystem, 0, seq, type, IPMIP_ATTR_HEADER_ACK);
}
IP_GLOBAL Ip_size_t
ipmip_attr_hdr_ack(Ipmip_buffer_t *buf,
struct Ipmip_attr_header *hdr)
{
return ipmip_attr_hdr_ack_create(buf, IPMIP_ATTR_HDR_SYSTEM(hdr), IPMIP_ATTR_HDR_SEQUENCE(hdr), IPMIP_ATTR_HDR_TYPE(hdr));
}
IP_GLOBAL Ip_size_t
ipmip_attr_hdr_err_create(Ipmip_buffer_t *buf,
Ip_u32 subsystem,
Ip_u32 seq,
Ip_u16 type,
Ip_u32 errcode,
const char *errmsg)
{
Ip_size_t off = ipmip_attr_hdr_create(buf, subsystem, errcode, seq, type, IPMIP_ATTR_HEADER_ACK);
if (errmsg)
ipmip_attr_put_str(buf, IPMIP_ATTR_MESSAGE, errmsg);
return off;
}
IP_GLOBAL Ip_size_t
ipmip_attr_hdr_err(Ipmip_buffer_t *buf,
struct Ipmip_attr_header *hdr,
Ip_u32 errcode,
const char *errmsg)
{
return ipmip_attr_hdr_err_create(buf, IPMIP_ATTR_HDR_SYSTEM(hdr),IPMIP_ATTR_HDR_SEQUENCE(hdr), IPMIP_ATTR_HDR_TYPE(hdr), errcode, errmsg);
}
IP_GLOBAL void
ipmip_attr_hdr_finalize(Ipmip_buffer_t *buf,
Ip_size_t off)
{
struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)ipmip_buffer_offset(buf,off);
Ip_u32 size = IPMIP_BUFFER_SIZE(buf) - off;
IP_SET_HTONL(&hdr->ah_len, size);
}
/*
*===========================================================================
* ipmip_cli_daemon_iter_init_request
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ipmip_attr_iter_t *
ipmip_attr_hdr_iter_init(struct Ipmip_attr_header *hdr,
Ipmip_attr_iter_t *iter)
{
iter->rta = IPMIP_ATTR_HDR_DATA(hdr);
iter->rta_size = IPMIP_ATTR_HDR_PAYLOAD(hdr);
/**/
return iter;
}
/*
*===========================================================================
* ipmip_cli_daemon_iter_rta_init
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ipmip_attr_iter_t *
ipmip_attr_payload_iter_init(struct Ipmip_attr *attr,
Ipmip_attr_iter_t *iter)
{
iter->rta = IPMIP_ATTR_DATA(attr);
iter->rta_size = IPMIP_ATTR_PAYLOAD(attr);
/**/
return iter;
}
/*
*===========================================================================
* ipmip_cli_daemon_iter_next
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL struct Ipmip_attr *
ipmip_attr_iter_next(Ipmip_attr_iter_t *iter,
Ip_u16 type)
{
while (IPMIP_ATTR_OK(iter->rta, iter->rta_size))
{
if (IPMIP_ATTR_TYPE(iter->rta) == type)
{
struct Ipmip_attr *rta = iter->rta;
iter->rta = IPMIP_ATTR_NEXT(iter->rta, iter->rta_size);
return rta;
}
iter->rta = IPMIP_ATTR_NEXT(iter->rta, iter->rta_size);
}
/**/
return IP_NULL;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,399 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_buffer.c,v $ $Revision: 1.6.16.1 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_buffer.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 <ipmip_config.h>
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_hash.h>
#include <ipcom_inet.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipmip.h>
#include <private/ipmip_util.h>
#include <private/ipmip_buffer.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmip_buffer_reserve
*===========================================================================
* Description: Increase the available buffer [allocated memory] with the
* provided value if necessary
* Parameters: buf - Buffer pointer.
* size - The size to expand with.
* Returns: IP_TRUE if successful
*
*/
IP_GLOBAL Ip_bool
ipmip_buffer_reserve(Ipmip_buffer_t *buf,
Ip_size_t size)
{
Ip_size_t avail = IPMIP_BUFFER_REMAIN(buf);
if (avail < size)
{
/* Allocate what is required, plus 128 bytes. */
Ip_size_t alloc = size + 128 - avail + buf->size;
Ip_u8 *bptr;
bptr = ipcom_malloc(alloc);
if (bptr)
{
if (buf->size)
{
ipcom_memcpy(bptr, buf->head, buf->offset);
ipcom_free(buf->head);
}
/* Store new values */
buf->head = bptr;
buf->size = alloc;
}
else
{
/* No go */
return IP_FALSE;
}
}
return IP_TRUE;
}
/*
*===========================================================================
* ipmip_buffer_init
*===========================================================================
* Description: Initialize a buffer structure.
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_buffer_init(Ipmip_buffer_t *buf)
{
ipcom_memset(buf, 0, sizeof(*buf));
}
/*
*===========================================================================
* ipmip_buffer_release
*===========================================================================
* Description: Release any resources associated with a buffer
* Parameters: buf - Buffer pointer.
* Returns:
*
*/
IP_GLOBAL void
ipmip_buffer_release(Ipmip_buffer_t *buf)
{
if (buf->head)
ipcom_free(buf->head);
ipmip_buffer_init(buf);
}
/*
*===========================================================================
* ipmip_buffer_append
*===========================================================================
* Description: Append data to a buffer pointer.
* Parameters: buf - Buffer pointer.
* data - Data block
* size - Size of data block.
* Returns: The offset to the stored data if successful, -1 otherwise.
*
*/
IP_GLOBAL int
ipmip_buffer_append(Ipmip_buffer_t *buf,
const void *data,
Ip_size_t size)
{
/* Verify size */
if (ipmip_buffer_reserve(buf, size))
{
Ip_size_t ooffset = buf->offset;
/* Copy the data */
if (data)
ipcom_memcpy(&buf->head[buf->offset], data, size);
/* Move offset forward */
buf->offset += size;
/* Report success */
return (int) ooffset;
}
return -1;
}
/*
*===========================================================================
* ipmip_buffer_zero
*===========================================================================
* Description: Append data to a buffer pointer.
* Parameters: buf - Buffer pointer.
* data - Data block
* size - Size of data block.
* Returns: The offset to the stored data if successful, -1 otherwise.
*
*/
IP_GLOBAL int
ipmip_buffer_zero(Ipmip_buffer_t *buf,
Ip_size_t size)
{
int off = ipmip_buffer_append(buf, IP_NULL, size);
if (off != -1)
ipcom_memset(&buf->head[off], 0, size);
return -1;
}
/*
*===========================================================================
* ipmip_buffer_shrink
*===========================================================================
* Description: Shrink the used buffer space to the provided value
* Parameters: buf - Buffer pointer.
* size - The size of the buffer
* Returns:
*
*/
IP_GLOBAL void
ipmip_buffer_shrink(Ipmip_buffer_t *buf,
Ip_size_t size)
{
/* Reduce if possible */
if (buf->offset > size)
buf->offset = size;
}
/*
*===========================================================================
* ipmip_buffer_delete_header
*===========================================================================
* Description: Remove the size first bytes of the buffer.
* Parameters: buf - Buffer pointer.
* size - The size to remove
* Returns:
*
*/
IP_GLOBAL void
ipmip_buffer_delete_header(Ipmip_buffer_t *buf,
Ip_size_t size)
{
if (buf->offset == size)
ipmip_buffer_shrink(buf, 0);
else if (buf->offset > size)
{
ipcom_memmove(buf->head, &buf->head[size], buf->offset - size);
ipmip_buffer_delete_tail(buf, size);
}
}
/*
*===========================================================================
* ipmip_buffer_delete_tail
*===========================================================================
* Description: Remove the size last bytes of the buffer.
* Parameters: buf - Buffer pointer.
* size - The size to remove
* Returns:
*
*/
IP_GLOBAL void
ipmip_buffer_delete_tail(Ipmip_buffer_t *buf,
Ip_size_t size)
{
if (buf->offset >= size)
ipmip_buffer_shrink(buf, buf->offset - size);
}
/*
*===========================================================================
* ipmip_buffer_assign
*===========================================================================
* Description: Assign the buffer values held by sbuf to dbuf, and
* release anything previously held by dbuf.
* Parameters: dbuf - Buffer pointer.
* sbuf - Buffer pointer
* Returns:
*
*/
IP_GLOBAL void
ipmip_buffer_assign(Ipmip_buffer_t *dbuf,
Ipmip_buffer_t *sbuf)
{
ipmip_buffer_release(dbuf);
/* Move the buffer */
ipcom_memcpy(dbuf, sbuf, sizeof(*dbuf));
ipmip_buffer_init(sbuf);
}
/*
*===========================================================================
* ipmip_buffer_get
*===========================================================================
* Description: Append size bytes and return the pointer to the
* verified block; this pointer is only valid until the next
* append call.
* Parameters: buf - Buffer pointer.
* size - Size of data block.
* Returns: The pointer
*
*/
IP_GLOBAL void *
ipmip_buffer_get(Ipmip_buffer_t *buf,
Ip_size_t size)
{
int off = ipmip_buffer_append(buf, IP_NULL, size);
if(-1 == off)
return IP_NULL;
/* Return the pointer */
return &buf->head[off];
}
/*
*===========================================================================
* ipmip_buffer_get_zero
*===========================================================================
* Description: Append size bytes and return the pointer to the
* verified block; this pointer is only valid until the next
* append call. Memory area will be zeroed
* Parameters: buf - Buffer pointer.
* size - Size of data block.
* Returns: The pointer
*
*/
IP_GLOBAL void *
ipmip_buffer_get_zero(Ipmip_buffer_t *buf,
Ip_size_t size)
{
void *data = ipmip_buffer_get(buf, size);
if (data)
ipcom_memset(data, 0, size);
/* Return the pointer */
return data;
}
/*
*===========================================================================
* ipmip_buffer_offset
*===========================================================================
* Description: Return the offset
* Parameters: buf - Buffer pointer.
* offset - The offset
* Returns: The pointer
*
*/
IP_GLOBAL void *
ipmip_buffer_offset(Ipmip_buffer_t *buf,
int offset)
{
/* Return the offset */
return &buf->head[offset];
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,652 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_context.c,v $ $Revision: 1.16.16.1 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_context.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 <ipmip_config.h>
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_hash.h>
#include <ipcom_inet.h>
#include <ipcom_ipd.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipmip.h>
#include <private/ipmip_sysvar.h>
#include <private/ipmip_util.h>
#include <private/ipmip_context.h>
#include <private/ipmip_pktbuf.h>
#include <private/ipmip_timer.h>
#include <private/ipmip_cli.h>
#include <private/ipmip_log.h>
#include <private/ipmip_dhcp.h>
#include <private/ipmip_inet.h>
#include <private/ipmip_dhcp6.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
struct Ipmip_context_id_hash_cb
{
Ipmip_util_hash_foreach_t func;
void *arg1;
void *arg2;
};
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/* Arguments */
static Ipcom_mutex ipmip_context_proc_lock;
static Ipmip_context_t *ipmip_context_thread_ctx = IP_NULL;
static Ipmip_proc_t *ipmip_context_thread_proc = IP_NULL;
static void *ipmip_context_thread_arg = IP_NULL;
static Ipmip_proc_func_t ipmip_context_thread_func = IP_NULL;
static Ipcom_once_t ipmip_context_once = IPCOM_ONCE_INIT;
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC unsigned
ipmip_context_id_hash(Ip_u32 *ko)
{
return ipcom_hash_update(ko, sizeof(*ko), 0);
}
IP_STATIC Ip_bool
ipmip_context_id_cmp(Ip_u32 *obj, Ip_u32 *key)
{
/* Compare */
return *obj == *key;
}
IP_STATIC void
ipmip_context_id_foreach_func(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_u8 *pident,
Ipmip_context_id_t *idctx,
struct Ipmip_context_id_hash_cb *cbinfo)
{
(*cbinfo->func) (ctx, proc, pident - idctx->identity_offset, cbinfo->arg1, cbinfo->arg2);
}
/*
*===========================================================================
* ipmip_timer_setup
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipmip_context_setup(void *unused)
{
IPMIP_UNUSED_PARAMETER(unused);
(void)ipcom_mutex_create(&ipmip_context_proc_lock);
return IPCOM_SUCCESS;
}
IP_STATIC
IPCOM_PROCESS(ipmip_proc)
{
Ipmip_proc_t *proc;
Ipmip_context_t *ctx;
void *arg;
Ipmip_proc_func_t func;
ipcom_proc_init();
/* Get the argument */
ctx = ipmip_context_thread_ctx;
proc = ipmip_context_thread_proc;
arg = ipmip_context_thread_arg;
func = ipmip_context_thread_func;
ipmip_context_thread_arg = IP_NULL;
ipmip_context_thread_proc = IP_NULL;
ipmip_context_thread_ctx = IP_NULL;
ipmip_context_thread_func = IP_NULL;
proc->pid = ipcom_getpid();
/* Release the start thread */
ipcom_block_post(proc->proc_block);
/* Invoke the callback */
(*func) (ctx, proc, arg);
/* Release the start thread */
ipcom_block_post(proc->proc_block);
/* */
ipcom_proc_exit();
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmip_context_alloc
*===========================================================================
* Description: Allocate the packet context
* Parameters: proc - Process context
* size - Total size of context.
* Returns: The newly allocated packet context on success.
*
*/
IP_GLOBAL Ipmip_context_t *
ipmip_context_alloc(Ipmip_proc_t *proc,
Ip_size_t size,
const char *name,
int loglevel,
int evsize)
{
Ipmip_context_t *ctx;
/* Initialize */
(void)IPMIP_ONCE(&ipmip_context_once, ipmip_context_setup, IP_NULL);
ctx = ipcom_calloc(1, size);
if (!ctx)
return IP_NULL;
#if IPCOM_VR_MAX > 1
ctx->vr = ipcom_proc_vr_get();
#endif
(void)ipcom_mutex_create(&ctx->log.events_lock);
ipcom_list_init(&ctx->log.events);
ipmip_log_loglevel(ctx, proc, loglevel);
ipmip_log_event_backlog(ctx, proc, evsize);
ctx->name = ipcom_strdup(name);
/* Request handle */
ctx->nl_req = ipmip_netlink_open(IP_NETLINK_ROUTE, 0);
/* Allocate an ioctl socket */
#ifdef IPMIP_USE_INET6
ctx->fd_ioctl = ipcom_socket(IP_AF_INET6, IP_SOCK_DGRAM, IP_IPPROTO_UDP);
#else
ctx->fd_ioctl = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, IP_IPPROTO_UDP);
#endif
if (!ipmip_timer_context_create(ctx, proc))
goto fail;
return ctx;
fail:
ipmip_context_destroy(ctx, proc);
return IP_NULL;
}
/*
*===========================================================================
* ipmip_context_start
*===========================================================================
* Description: Start the context
* Parameters: ctx - The context
* proc - Current thead context
* Returns:
*
*/
IP_GLOBAL void
ipmip_context_start(Ipmip_context_t *ctx,
Ipmip_proc_t *proc)
{
/* Start the context */
ipmip_timer_context_start(ctx, proc);
ipmip_cli_context_start(ctx, proc);
ipmip_netlink_context_start(ctx, proc);
}
/*
*===========================================================================
* ipmip_context_stop
*===========================================================================
* Description: Stop the context
* Parameters: ctx - The context
* proc - Process context
* Returns:
*
*/
IP_GLOBAL void
ipmip_context_stop(Ipmip_context_t *ctx,
Ipmip_proc_t *proc)
{
ipmip_netlink_context_stop(ctx, proc);
ipmip_cli_context_stop(ctx, proc);
ipmip_timer_context_stop(ctx, proc);
}
/*
*===========================================================================
* ipmip_context_destroy
*===========================================================================
* Description: Destroy the context
* Parameters: ctx - The context
* Returns:
*
*/
IP_GLOBAL void
ipmip_context_destroy(Ipmip_context_t *ctx,
Ipmip_proc_t *proc)
{
/**/
ipmip_log_event_flush(ctx, proc);
ipcom_mutex_delete(&ctx->log.events_lock);
ipmip_cli_context_destroy(ctx, proc);
#ifdef IPMIP_USE_INET
ipmip_dhcp_context_destroy(ctx, proc);
ipmip_inet_arp_context_destroy(ctx, proc);
#endif
#ifdef IPMIP_USE_INET6
ipmip_dhcp6_context_destroy(ctx, proc);
#endif
ipmip_netlink_context_destroy(ctx, proc);
ipmip_pktbuf_context_destroy(ctx, proc);
ipmip_timer_context_destroy(ctx, proc);
if (ctx->fd_ioctl != IP_INVALID_SOCKET)
ipcom_socketclose(ctx->fd_ioctl);
ipmip_netlink_close(ctx->nl_req);
ipcom_free(ctx->name);
ipcom_free(ctx);
}
/*
*===========================================================================
* ipmip_proc_alloc
*===========================================================================
* Description: Create the process context
* Parameters:
* Returns: A process context on success
*
*/
IP_GLOBAL Ipmip_proc_t *
ipmip_proc_alloc(void)
{
Ipmip_proc_t *proc = ipcom_calloc(1, sizeof(Ipmip_proc_t));
if (proc)
{
/* Create semaphore */
ipcom_block_create(&proc->proc_block);
}
return proc;
}
/*
*===========================================================================
* ipmip_proc_destroy
*===========================================================================
* Description: Destroy the process context
* Parameters: proc - Context
* Returns:
*
*/
IP_GLOBAL void
ipmip_proc_destroy(Ipmip_proc_t *proc)
{
if (proc != IP_NULL)
{
ipcom_block_delete(&proc->proc_block);
ipcom_free(proc);
}
}
/*
*===========================================================================
* ipmip_proc_start
*===========================================================================
* Description: Start a specific function with the provided arguments.
* Parameters: ctx - Context
* proc - The process
* proc_name - Name of the process
* func - Thread start function
* arg - Opaque argument
* Returns: Thread context, if successful.
*
*/
IP_GLOBAL Ipmip_proc_t *
ipmip_proc_start(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
const char *proc_name,
Ipmip_proc_func_t func,
void *arg)
{
Ipmip_proc_t *nproc = ipmip_proc_alloc();
IPMIP_UNUSED_PARAMETER(proc);
if (nproc)
{
Ipcom_proc_attr attr;
Ip_err err;
/**/
ipcom_proc_attr_init(&attr);
attr.stacksize = IPCOM_PROC_STACK_LARGE;
ipcom_snprintf(proc->ntop.ntop_pbuf,
sizeof(proc->ntop.ntop_pbuf),
"%s_%s",
ctx->name,
proc_name);
/* Lock down contexts */
ipcom_mutex_lock(ipmip_context_proc_lock);
/* Setup the start values */
ipmip_context_thread_arg = arg;
ipmip_context_thread_proc = nproc;
ipmip_context_thread_ctx = ctx;
ipmip_context_thread_func = func;
err = ipcom_proc_acreate(proc->ntop.ntop_pbuf, ipmip_proc, &attr, IP_NULL);
if (err != IPCOM_SUCCESS)
{
ipmip_proc_destroy(nproc);
ipcom_mutex_unlock(ipmip_context_proc_lock);
return IP_NULL;
}
/* Wait until were signalled */
ipcom_block_wait(nproc->proc_block, -1);
ipcom_mutex_unlock(ipmip_context_proc_lock);
}
return nproc;
}
/*
*===========================================================================
* ipmip_proc_stop
*===========================================================================
* Description: Stop a specific thread.
* Parameters: ctx - Context
* proc - Thread context
* stop_proc - Thread context
* func - Wakeup function
* arg - Opaque argument
* Returns:
*
*/
IP_GLOBAL void
ipmip_proc_stop(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_proc_t *stop_proc,
Ipmip_proc_func_t func,
void *arg)
{
IPMIP_UNUSED_PARAMETER(proc);
/* Lock the global mutex */
ipcom_mutex_lock(ipmip_context_proc_lock);
/* Mark it as 'quit' */
stop_proc->quit = IP_TRUE;
/* Trigger the thread */
if (func != IP_NULL)
(*func) (ctx, stop_proc, arg);
/* Unlock the global lock */
ipcom_mutex_unlock(ipmip_context_proc_lock);
/* Wait for it to report that its fallen out of the loop */
(void)ipcom_block_wait(stop_proc->proc_block, -1);
/**/
ipmip_proc_destroy(stop_proc);
}
/*
*===========================================================================
* ipmip_proc_collect
*===========================================================================
* Description: See if a particular process has been stopped
* Parameters: ctx - Context
* proc - Thread context
* stop_proc - Thread context
* Returns: IP_TRUE if the process was collected.
*
*/
IP_GLOBAL Ip_bool
ipmip_proc_collect(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_proc_t *stop_proc)
{
Ip_err err;
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
ipcom_mutex_lock(ipmip_context_proc_lock);
/* Wait for it to report that its fallen out of the loop */
err = ipcom_block_wait(stop_proc->proc_block, 0);
/* Unlock the global lock */
ipcom_mutex_unlock(ipmip_context_proc_lock);
/* If successful; quit */
if (err == IPCOM_SUCCESS)
{
ipmip_proc_destroy(stop_proc);
return IP_TRUE;
}
return IP_FALSE;
}
IP_GLOBAL Ipmip_context_id_t *
ipmip_context_id_create(Ip_ptrdiff_t offset,
Ip_u32 mask)
{
Ipmip_context_id_t *idctx = ipcom_calloc(1, sizeof(*idctx));
if (idctx == IP_NULL)
return IP_NULL;
idctx->identity_mask = mask;
idctx->identity_offset = offset;
idctx->identity_table = ipcom_hash_new((Ipcom_hash_obj_func) ipmip_context_id_hash,
(Ipcom_hash_key_func) ipmip_context_id_hash,
(Ipcom_hash_cmp_func) ipmip_context_id_cmp);
(void)ipcom_mutex_create(&idctx->identity_lock);
ipcom_block_create(&idctx->identity_empty);
/* Start with it available */
ipcom_block_post(idctx->identity_empty);
return idctx;
}
IP_GLOBAL void
ipmip_context_id_destroy(Ipmip_context_id_t *idctx)
{
if (idctx != IP_NULL)
{
ipcom_mutex_delete(&idctx->identity_lock);
ipcom_hash_delete(idctx->identity_table);
ipcom_block_delete(&idctx->identity_empty);
ipcom_free(idctx);
}
}
IP_GLOBAL void
ipmip_context_id_allocate(Ipmip_context_id_t *idctx,
void *node)
{
Ip_u32 *pident = (Ip_u32 *) (((Ip_u8 *)node) + idctx->identity_offset);
Ip_u32 ident;
ipcom_mutex_lock(idctx->identity_lock);
for (;;)
{
ident = ++idctx->identity;
ident &= idctx->identity_mask;
if (ident == 0)
continue;
if (ipcom_hash_get(idctx->identity_table, &ident) == IP_NULL)
break;
}
*pident = ident;
ipcom_hash_add(idctx->identity_table, pident);
if (idctx->identity_table->elem == 1)
(void)ipcom_block_wait(idctx->identity_empty, -1);
ipcom_mutex_unlock(idctx->identity_lock);
}
IP_GLOBAL void
ipmip_context_id_release(Ipmip_context_id_t *idctx,
void *node)
{
Ip_u32 *pident = (Ip_u32 *) (((Ip_u8 *)node) + idctx->identity_offset);
if (ipcom_hash_remove(idctx->identity_table, pident) == IPCOM_SUCCESS)
{
if (idctx->identity_table->elem == 0)
ipcom_block_post(idctx->identity_empty);
}
}
IP_GLOBAL void *
ipmip_context_id_get(Ipmip_context_id_t *idctx,
Ip_u32 ident)
{
Ip_u32 *pident;
pident = ipcom_hash_get(idctx->identity_table, &ident);
if (pident)
return (void *)(((Ip_u8*)pident) - idctx->identity_offset);
return IP_NULL;
}
IP_GLOBAL Ip_bool
ipmip_context_id_empty(Ipmip_context_id_t *idctx,
int wait_timeout)
{
if (ipcom_block_wait(idctx->identity_empty, wait_timeout) != IPCOM_SUCCESS)
return IP_FALSE;
ipcom_block_post(idctx->identity_empty);
return IP_TRUE;
}
IP_GLOBAL void
ipmip_context_id_foreach(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_context_id_t *idctx,
Ipmip_util_hash_foreach_t func,
void *arg1,
void *arg2)
{
struct Ipmip_context_id_hash_cb cbinfo;
cbinfo.arg1 = arg1;
cbinfo.arg2 = arg2;
cbinfo.func = func;
/**/
ipmip_util_hash_foreach(ctx, proc, idctx->identity_table, (Ipmip_util_hash_foreach_t)ipmip_context_id_foreach_func, idctx, &cbinfo);
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,650 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_dhcp6.c,v $ $Revision: 1.7 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_dhcp6.c,v $
* $Author: jhorteli $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include <ipmip_config.h>
#ifdef IPMIP_USE_INET6
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_hash.h>
#include <ipcom_inet.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipcom_ipd.h>
#include <ipmip.h>
#include <private/ipmip_context.h>
#include <private/ipmip_timer.h>
#include <private/ipmip_buffer.h>
#include <private/ipmip_pktbuf.h>
#include <private/ipmip_sysvar.h>
#include <private/ipmip_lladdr.h>
#include <private/ipmip_if.h>
#include <private/ipmip_util.h>
#include <private/ipmip_dhcp6.h>
#include <private/ipmip_inet6.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMIP_DHCP6_SERVER_PORT 547
#define IPMIP_DHCP6_CLIENT_PORT 546
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
struct Ip_in6_addr ipmip_dhcp6_all_dhcp_relay_agents_and_servers =
{
{ { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02 } }
};
struct Ip_in6_addr ipmip_dhcp6_all_dhcp_servers =
{
{ { 0xFF, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03 } }
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC unsigned
ipmip_dhcp6_key_ifindex(Ip_u32 *ifindex)
{
return ipcom_hash_update(ifindex, sizeof(*ifindex), 0);
}
IP_STATIC unsigned
ipmip_dhcp6_obj_ifindex(Ipmip_dhcp6_node_t *node)
{
return ipmip_dhcp6_key_ifindex(&node->ifindex);
}
IP_STATIC Ip_bool
ipmip_dhcp6_cmp_ifindex(Ipmip_dhcp6_node_t *node, Ip_u32 *ifindex)
{
/* Compare */
return node->ifindex == *ifindex;
}
IP_STATIC Ip_u32
ipmip_dhcp6_header_size(Ipmip_buffer_t *dhcp)
{
Ipmip_dhcp6_hdr_t *pkt = (Ipmip_dhcp6_hdr_t *)IPMIP_BUFFER_PTR(dhcp);
/* */
switch (pkt->msg_type)
{
/**/
case IPMIP_DHCP6_MSG_RELAY_REPLY:
case IPMIP_DHCP6_MSG_RELAY_FORWARD:
return sizeof(Ipmip_dhcp6_relay_hdr_t);
default:
return sizeof(Ipmip_dhcp6_hdr_t);
}
}
IP_STATIC Ip_fd
ipmip_dhcp6_socket_server_alloc(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
struct Ip_sockaddr_in6 *sin6)
{
Ip_fd fd;
int i;
Ip_socklen_t slen;
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
/* Create raw IP socket for all IPv4 input on this interface */
if ((fd = ipcom_socket(IP_AF_INET6, IP_SOCK_DGRAM, IP_IPPROTO_UDP)) == IP_INVALID_SOCKET)
goto fail;
/* Allow reusage of address */
i = 1;
if (ipcom_setsockopt(fd, IP_SOL_SOCKET, IP_SO_REUSEADDR, &i, sizeof(i)))
goto fail;
/* Allow reusage of ports */
i = 1;
if (ipcom_setsockopt(fd, IP_SOL_SOCKET, IP_SO_REUSEPORT, &i, sizeof(i)))
goto fail;
/* */
if (ipcom_bind(fd, (struct Ip_sockaddr *) sin6, sizeof(*sin6)) < 0)
goto fail;
/* I want to receive PACKET INFO as ancillary data */
i = 1;
if (ipcom_setsockopt(fd, IP_IPPROTO_IPV6, IP_IPV6_RECVPKTINFO, &i, sizeof(i)) < 0)
goto fail;
i = 1;
if (ipcom_setsockopt(fd, IP_IPPROTO_IPV6, IP_IPV6_RECVHOPLIMIT, &i, sizeof(i)) < 0)
goto fail;
slen = sizeof(*sin6);
if (ipcom_getsockname(fd, (struct Ip_sockaddr *) sin6, &slen) < 0)
goto fail;
return fd;
fail:
ipcom_socketclose(fd);
return IP_INVALID_SOCKET;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL void
ipmip_dhcp6_context_create(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
struct Ip_sockaddr_in6 sin6;
if (ctx->dhcp6 != IP_NULL)
return;
ctx->dhcp6 = ipcom_calloc(1, sizeof(*ctx->dhcp6));
if (ctx->dhcp6 == IP_NULL)
return;
ipcom_mutex_create(&ctx->dhcp6->mutex);
ipcom_memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = IP_AF_INET6;
IPCOM_SA_LEN_SET(&sin6, sizeof(sin6));
sin6.sin6_port = ip_htons(IPMIP_DHCP6_SERVER_PORT);
ctx->dhcp6->fd_udp = ipmip_dhcp6_socket_server_alloc(ctx, proc, &sin6);
ctx->dhcp6->ifindex_table = ipcom_hash_new((Ipcom_hash_obj_func) ipmip_dhcp6_obj_ifindex,
(Ipcom_hash_key_func) ipmip_dhcp6_key_ifindex,
(Ipcom_hash_cmp_func) ipmip_dhcp6_cmp_ifindex);
}
IP_GLOBAL void
ipmip_dhcp6_context_destroy(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
if (ctx->dhcp6 != IP_NULL)
{
ipcom_mutex_delete(&ctx->dhcp6->mutex);
if (ctx->dhcp6->fd_udp != IP_INVALID_SOCKET)
ipcom_socketclose(ctx->dhcp6->fd_udp);
if (ctx->dhcp6->ifindex_table)
ipcom_hash_delete(ctx->dhcp6->ifindex_table);
ipcom_free(ctx->dhcp6);
ctx->dhcp6 = IP_NULL;
}
}
IP_GLOBAL void
ipmip_dhcp6_process(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
Ipmip_pktbuf_t *pbuf = ipmip_inet6_udp_recvmsg(ctx, proc, 1500, ctx->dhcp6->fd_udp);
/* Invoke callback */
if (pbuf)
{
Ipmip_dhcp6_hdr_t *pkt = (Ipmip_dhcp6_hdr_t *)IPMIP_BUFFER_PTR(&pbuf->packet);
Ipmip_dhcp6_node_t *node = IP_NULL;
/* Sanity process */
if (IPMIP_BUFFER_SIZE(&pbuf->packet) > 0 && IPMIP_BUFFER_SIZE(&pbuf->packet) >= ipmip_dhcp6_header_size(&pbuf->packet))
{
Ip_u32 ifindex;
/* */
switch (pkt->msg_type)
{
/**/
case IPMIP_DHCP6_MSG_RELAY_REPLY:
/* Lookup based on interface identifier */
{
Ipmip_dhcp6_option_hdr_t *ifopt = ipmip_dhcp6_option_buffer_find(&pbuf->packet, IPMIP_DHCP6_OPTION_INTERFACE_ID);
if (ifopt == IP_NULL)
goto error_out;
if (IP_GET_NTOHS(&ifopt->length) < 4)
goto error_out;
ifindex = IP_GET_32ON8((ifopt + 1));
}
break;
default:
ifindex = pbuf->srcinfo.dst->ifindex;
break;
}
ipcom_mutex_lock(ctx->dhcp6->mutex);
/* Find it on the interface we've received it on */
node = ipcom_hash_get(ctx->dhcp6->ifindex_table, &ifindex);
/* Time to invoke function */
if (node != IP_NULL)
ipmip_timer_request(ctx, proc, &pbuf->timeout, node->lock, node->process_func, node, pbuf, 0);
ipcom_mutex_unlock(ctx->dhcp6->mutex);
}
error_out:
if (node == IP_NULL)
ipmip_pktbuf_release(ctx, proc, pbuf);
}
}
IP_GLOBAL void
ipmip_dhcp6_register(struct Ipmip_context *ctx,
struct Ipmip_proc *proc,
Ipmip_dhcp6_node_t *node)
{
IPMIP_UNUSED_PARAMETER(proc);
/* We're going to relay */
ipcom_mutex_lock(ctx->dhcp6->mutex);
ipcom_hash_add(ctx->dhcp6->ifindex_table, node);
ipcom_mutex_unlock(ctx->dhcp6->mutex);
/* Join up */
ipmip_inet6_multicast_join(ctx, proc, ctx->dhcp6->fd_udp, node->ifindex, &ipmip_dhcp6_all_dhcp_relay_agents_and_servers);
}
IP_GLOBAL void
ipmip_dhcp6_unregister(struct Ipmip_context *ctx,
struct Ipmip_proc *proc,
Ipmip_dhcp6_node_t *node)
{
IPMIP_UNUSED_PARAMETER(proc);
/* We're going to relay */
ipcom_mutex_lock(ctx->dhcp6->mutex);
ipcom_hash_remove(ctx->dhcp6->ifindex_table, node);
ipcom_mutex_unlock(ctx->dhcp6->mutex);
ipmip_inet6_multicast_leave(ctx, proc, ctx->dhcp6->fd_udp, node->ifindex, &ipmip_dhcp6_all_dhcp_relay_agents_and_servers);
}
IP_GLOBAL void
ipmip_dhcp6_add_option(Ipmip_buffer_t *dhcp,
Ip_u16 code,
Ip_u16 length,
void *data)
{
Ipmip_dhcp6_option_hdr_t *hdr = ipmip_buffer_offset(dhcp, ipmip_buffer_append(dhcp, IP_NULL, sizeof(*hdr)));
IP_SET_HTONS(&hdr->code, code);
IP_SET_HTONS(&hdr->length, length);
if (length)
ipmip_buffer_append(dhcp, data, length);
}
IP_GLOBAL Ipmip_pktbuf_t *
ipmip_dhcp6_relay_msg(struct Ipmip_context *ctx,
struct Ipmip_proc *proc,
struct Ip_in6_addr *link_addr,
Ip_u8 hop_count,
Ipmip_pktbuf_t *req)
{
Ipmip_pktbuf_t *relay = (Ipmip_pktbuf_t *)ipmip_pktbuf_alloc(ctx, proc, IPMIP_BUFFER_SIZE(&req->packet) + 128);
if (relay != IP_NULL)
{
Ipmip_dhcp6_relay_hdr_t *hdr;
ipmip_buffer_append(&relay->packet, IP_NULL, sizeof(*hdr));
hdr = IPMIP_BUFFER_PTR(&relay->packet);
hdr->msg_type = IPMIP_DHCP6_MSG_RELAY_FORWARD;
hdr->hop_count = hop_count + 1;
/* Source */
ipcom_memcpy(&hdr->peer_addr, &req->srcinfo.src->sin6.sin6_addr, sizeof(struct Ip_in6_addr));
/* :: */
ipcom_memcpy(&hdr->link_addr, link_addr? link_addr : &ip_in6addr_any, sizeof(struct Ip_in6_addr));
ipmip_dhcp6_add_option(&relay->packet, IPMIP_DHCP6_OPTION_RELAY_MSG, IPMIP_BUFFER_SIZE(&req->packet), IPMIP_BUFFER_PTR(&req->packet));
ipmip_dhcp6_add_option(&relay->packet, IPMIP_DHCP6_OPTION_INTERFACE_ID, sizeof(Ip_u32), &req->srcinfo.dst->ifindex);
}
return relay;
}
IP_GLOBAL Ipmip_dhcp6_option_hdr_t *
ipmip_dhcp6_option_next(Ipmip_dhcp6_option_hdr_t *hdr,
Ip_u8 *optstart,
int optsize)
{
Ip_u8 *options = (Ip_u8 *)hdr;
Ip_u16 hdr_len;
/* Remove header */
optsize -= (int) (options - optstart);
/* This header and next */
optsize -= sizeof(*hdr) * 2;
if (optsize < 0)
return IP_NULL;
options += sizeof(*hdr);
hdr_len = IP_GET_NTOHS(&hdr->length);
optsize -= hdr_len;
options += hdr_len;
if (optsize < 0)
return IP_NULL;
/* Next header; its valid since we've already subtracted two headers */
hdr = (Ipmip_dhcp6_option_hdr_t*) options;
/* Check length */
hdr_len = IP_GET_NTOHS(&hdr->length);
optsize -= hdr_len;
if (optsize < 0)
return IP_NULL;
return hdr;
}
IP_GLOBAL Ipmip_dhcp6_option_hdr_t *
ipmip_dhcp6_option_first(Ip_u8 *options,
int optsize)
{
Ipmip_dhcp6_option_hdr_t *hdr = (Ipmip_dhcp6_option_hdr_t*) options;
/* This header */
optsize -= sizeof(*hdr);
if (optsize < 0)
return IP_NULL;
optsize -= IP_GET_NTOHS(&hdr->length);
if (optsize < 0)
return IP_NULL;
return hdr;
}
IP_GLOBAL Ipmip_dhcp6_option_hdr_t *
ipmip_dhcp6_option_find(Ip_u8 *options,
int optsize,
Ip_u16 code)
{
Ipmip_dhcp6_option_hdr_t *hdr;
for (hdr = ipmip_dhcp6_option_first(options, optsize); hdr != IP_NULL; hdr = ipmip_dhcp6_option_next(hdr, options, optsize))
{
if (IP_GET_HTONS(&hdr->code) == code)
return hdr;
}
return IP_NULL;
}
IP_GLOBAL Ipmip_dhcp6_option_hdr_t *
ipmip_dhcp6_option_buffer_find(struct Ipmip_buffer *dhcp,
Ip_u16 code)
{
Ip_u32 hdr_size = ipmip_dhcp6_header_size(dhcp);
return ipmip_dhcp6_option_find(ipmip_buffer_offset(dhcp, hdr_size), IPMIP_BUFFER_SIZE(dhcp) - hdr_size, code);
}
IP_GLOBAL Ipmip_dhcp6_option_hdr_t *
ipmip_dhcp6_option_buffer_first(struct Ipmip_buffer *dhcp)
{
Ip_u32 hdr_size = ipmip_dhcp6_header_size(dhcp);
return ipmip_dhcp6_option_first(ipmip_buffer_offset(dhcp, hdr_size), IPMIP_BUFFER_SIZE(dhcp) - hdr_size);
}
IP_GLOBAL Ipmip_dhcp6_option_hdr_t *
ipmip_dhcp6_option_buffer_next(Ipmip_dhcp6_option_hdr_t *hdr,
struct Ipmip_buffer *dhcp)
{
Ip_u32 hdr_size = ipmip_dhcp6_header_size(dhcp);
return ipmip_dhcp6_option_next(hdr, ipmip_buffer_offset(dhcp, hdr_size), IPMIP_BUFFER_SIZE(dhcp) - hdr_size);
}
IP_GLOBAL int
ipmip_dhcp6_send_msg(struct Ipmip_context *ctx,
struct Ipmip_proc *proc,
void *data,
Ip_size_t size,
struct Ip_in6_addr *dst,
Ip_u32 ifscope)
{
Ip_u8 cmsg_buf[IP_CMSG_SPACE(sizeof(struct Ip_in6_pktinfo))];
struct Ip_msghdr msg;
struct Ip_iovec iov[1];
struct Ip_sockaddr_in6 sin6;
Ipmip_dhcp6_hdr_t *pkt = (Ipmip_dhcp6_hdr_t *)data;
IPMIP_UNUSED_PARAMETER(proc);
ipcom_memset(&msg, 0, sizeof(msg));
iov[0].iov_base = data;
iov[0].iov_len = size;
sin6.sin6_family = IP_AF_INET6;
IPCOM_SA_LEN_SET(&sin6, sizeof(sin6));
ipcom_memcpy(&sin6.sin6_addr, dst? dst : &ipmip_dhcp6_all_dhcp_servers, sizeof(struct Ip_in6_addr));
sin6.sin6_flowinfo = 0;
msg.msg_name = &sin6;
msg.msg_namelen = sizeof(sin6);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
switch (pkt->msg_type)
{
case IPMIP_DHCP6_MSG_RELAY_REPLY:
case IPMIP_DHCP6_MSG_RELAY_FORWARD:
sin6.sin6_port = ip_htons(IPMIP_DHCP6_SERVER_PORT);
break;
default:
sin6.sin6_port = ip_htons(IPMIP_DHCP6_CLIENT_PORT);
break;
}
if (IP_IN6_IS_ADDR_LINK_LOCAL(&sin6.sin6_addr))
sin6.sin6_scope_id = ifscope;
else
{
sin6.sin6_scope_id = 0;
if (ifscope)
{
struct Ip_cmsghdr *cmptr;
struct Ip_in6_pktinfo *pktinfo;
msg.msg_control = cmsg_buf;
cmptr = (struct Ip_cmsghdr *) cmsg_buf;
cmptr->cmsg_len = IP_CMSG_LEN(sizeof(struct Ip_in6_pktinfo));
cmptr->cmsg_level = IP_IPPROTO_IPV6;
cmptr->cmsg_type = IP_IPV6_PKTINFO;
pktinfo = IP_CMSG_DATA(cmptr);
ipcom_memset(&pktinfo->ipi6_addr, 0, sizeof(pktinfo->ipi6_addr));
pktinfo->ipi6_ifindex = ifscope;
msg.msg_controllen = IP_CMSG_SPACE(sizeof(struct Ip_in6_pktinfo));
}
}
if (ipcom_sendmsg(ctx->dhcp6->fd_udp, &msg, 0) < 0)
return -ipcom_errno;
return IPCOM_SUCCESS;
}
#if defined(IP_PORT_LAS) && defined(IPDHCPS6)
extern void ipdhcps6_create();
extern void ipdhcps6_dhcps6d_proc(void);
extern void ipdhcps6_duid_initialize(void);
extern void ipdhcps6_configure(void);
#endif
IP_GLOBAL void
ipmip_dhcp6_embedded_server_init(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
#if defined(IP_PORT_LAS) && defined(IPDHCPS6)
/* Invoke the create hook */
ipdhcps6_create();
ipdhcps6_configure();
ctx->dhcps6 = ipcom_calloc(1, sizeof(*ctx->dhcps6));
#else
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
#endif
}
#if defined(IP_PORT_LAS) && defined(IPDHCPS6)
IP_STATIC void
ipmip_dhcp6_embedded_server_proc(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
void *arg)
{
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
IPMIP_UNUSED_PARAMETER(arg);
/* Invoke*/
ipdhcps6_dhcps6d_proc();
}
#endif
IP_GLOBAL void
ipmip_dhcp6_embedded_server_start(struct Ipmip_context *ctx,
struct Ipmip_proc *proc,
const char *ifname)
{
#if defined(IP_PORT_LAS) && defined(IPDHCPS6)
if (ctx->dhcps6->proc == IP_NULL)
{
ipmip_sysvar_set(ifname, "ipdhcps6.duid.ifname");
ipdhcps6_duid_initialize();
/**/
ctx->dhcps6->refcount = 1;
ctx->dhcps6->proc = ipmip_proc_start(ctx, proc, "ipdhcps6", ipmip_dhcp6_embedded_server_proc, IP_NULL);
}
else
{
ctx->dhcps6->refcount++;
}
#else
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
IPMIP_UNUSED_PARAMETER(ifname);
#endif
}
IP_GLOBAL void
ipmip_dhcp6_embedded_server_stop(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
#if defined(IP_PORT_LAS) && defined(IPDHCPS6)
if (ctx->dhcps6->proc != IP_NULL)
{
if (--ctx->dhcps6->refcount == 0)
{
ipcom_ipd_kill("ipdhcps6");
/**/
ipmip_proc_destroy(ctx->dhcps6->proc);
ctx->dhcps6->proc = IP_NULL;
}
}
#else
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
#endif
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
#else /* IPMIP_USE_INET6 */
int ipmip_dhcp6_empty_file = 0;
#endif /* IPMIP_USE_INET6 */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
+472
View File
@@ -0,0 +1,472 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_if.c,v $ $Revision: 1.7.16.4 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_if.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 <ipmip_config.h>
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipmip.h>
#include <private/ipmip_context.h>
#include <private/ipmip_if.h>
#include <private/ipmip_util.h>
#include <private/ipmip_buffer.h>
#include <private/ipmip_netlink.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG2
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmip_if_alloc
*===========================================================================
* Description: Allocate and initialize the interface structure
* Parameters: ctx - Context
* proc - Process
* ifsize - the size of the interface structure
* ifname - The interface name
* ifindex - The interface index.
* cleanup - Function to be invoked prior to free.
* Returns: The interface structure on success.
*/
IP_GLOBAL Ipmip_if_t *
ipmip_if_alloc(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_size_t ifsize,
const char *ifname,
Ip_u32 ifindex,
Ip_u8 type,
Ip_u8 identity,
Ipmip_if_cleanup_t cleanup)
{
Ipmip_if_t *iff = ipcom_calloc(1, ifsize);
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
if (iff == IP_NULL)
return IP_NULL;
iff->ifindex = ifindex;
if (ifname)
ipcom_strncpy(iff->ifname, ifname, IP_IFNAMSIZ);
iff->type = type;
iff->identity = identity;
iff->lladdr = IP_NULL;
iff->cleanup = cleanup;
return iff;
}
/*
*===========================================================================
* ipmip_if_free
*===========================================================================
* Description: Destroy and free the interface specific data.
* Parameters: ctx - Context
* proc - Process
* iff - the interface to destroy
* Returns:
*/
IP_GLOBAL void
ipmip_if_free(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_if_t *iff)
{
/* If we're in any list; remove us */
if (iff->next.head != IP_NULL)
ipcom_list_remove(&iff->next);
/* Invoke cleanup functionality */
if (iff->cleanup)
(*iff->cleanup) (ctx, proc, iff);
if (iff->lladdr)
{
ipcom_free(iff->lladdr);
iff->lladdr = IP_NULL;
}
ipcom_free(iff);
}
/*
*===========================================================================
* ipmip4_if_ioctl
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL int
ipmip_if_ioctl(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_if_t *iff,
unsigned long ioctl,
struct Ip_ifreq *ifreq)
{
if((IP_IFNAMSIZ - 1) < strlen(iff->ifname))
{
return -1;
}
ipcom_strcpy(ifreq->ifr_name, iff->ifname);
return ipmip_util_ioctl(ctx, proc, ioctl, ifreq);
}
/*
*===========================================================================
* ipmip_if_get_flags
*===========================================================================
* Description: Get the current interface flags.
* Parameters: ctx - The context
* proc - The process.
* iff - The interface
* flags - Where to store the flags.
* Returns: IP_TRUE on success
*
*/
IP_GLOBAL Ip_bool
ipmip_if_get_flags(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_if_t *iff,
Ip_u16 *flags)
{
struct Ip_ifreq ifreq;
if (ipmip_if_ioctl(ctx, proc, iff, IP_SIOCGIFFLAGS, &ifreq) < 0)
return IP_FALSE;
*flags = ifreq.ifr_ifru.ifru_flags;
return IP_TRUE;
}
/*
*===========================================================================
* ipmip_if_set_flags
*===========================================================================
* Description: Set the current interface flags.
* Parameters: ctx - The context
* proc - The process
* iff - The interface
* flags - The flags to set
* Returns: IP_TRUE on success
*
*/
IP_GLOBAL Ip_bool
ipmip_if_set_flags(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_if_t *iff,
Ip_u16 flags)
{
struct Ip_ifreq ifreq;
if (ipmip_if_ioctl(ctx, proc, iff, IP_SIOCGIFFLAGS, &ifreq) < 0)
return IP_FALSE;
IP_BIT_SET(ifreq.ifr_ifru.ifru_flags, flags);
if (ipmip_util_ioctl(ctx, proc, IP_SIOCSIFFLAGS, &ifreq) < 0)
return IP_FALSE;
return IP_TRUE;
}
/*
*===========================================================================
* ipmip_if_clear_flags
*===========================================================================
* Description: Clear the current interface flags.
* Parameters: iff - The interface
* flags - The flags to clear
* Returns: IP_TRUE on success
*
*/
IP_GLOBAL Ip_bool
ipmip_if_clear_flags(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_if_t *iff,
Ip_u16 flags)
{
struct Ip_ifreq ifreq;
if (ipmip_if_ioctl(ctx, proc, iff, IP_SIOCGIFFLAGS, &ifreq) < 0)
return IP_FALSE;
IP_BIT_CLR(ifreq.ifr_ifru.ifru_flags, flags);
if (ipmip_util_ioctl(ctx, proc, IP_SIOCSIFFLAGS, &ifreq) < 0)
return IP_FALSE;
return IP_TRUE;
}
/*
*===========================================================================
* ipmip_if_resolve_lla
*===========================================================================
* Description: Resolve the LLA of the interface
* Parameters: ctx - Context
* proc - Process
* iff - Interface
* Returns: IP_TRUE on success; IP_FALSE otherwise.
*
*/
IP_GLOBAL Ip_bool
ipmip_if_resolve_lla(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_if_t *iff)
{
Ipmip_buffer_t req;
Ipmip_buffer_t answer;
struct Ip_ifinfomsg *ifi;
struct Ip_nlmsghdr *nlh;
int ret;
Ip_size_t nlh_size;
Ip_size_t addr_size = 0;
Ip_u8 *addr_data = IP_NULL;
ipmip_buffer_init(&req);
ipmip_buffer_init(&answer);
/**/
ipmip_netlink_nlmsghdr_request(&req, 0, 0, IP_RTM_GETLINK, 0);
ifi = (struct Ip_ifinfomsg *)ipmip_buffer_offset(&req, ipmip_netlink_nlmsghdr_put(&req, IP_NULL, sizeof(*ifi)));
ipcom_memset(ifi, 0, sizeof(*ifi));
ifi->ifi_family = IP_AF_LINK;
ifi->ifi_index = iff->ifindex;
ipmip_netlink_nlmsghdr_done(&req, 0);
ret = ipmip_netlink_request(ctx, proc, ctx->nl_req, 0, 0, IPMIP_BUFFER_PTR(&req), &answer);
ipmip_buffer_release(&req);
if (ret < 0)
return IP_FALSE;
/* We've gotten an answer */
nlh = IPMIP_BUFFER_PTR(&answer);
nlh_size = IPMIP_BUFFER_SIZE(&answer);
/**/
while (IP_NLMSG_OK(nlh, nlh_size))
{
/**/
if (nlh->nlmsg_type == IP_RTM_NEWLINK)
{
struct Ip_rtattr *iflap[IP_IFLA_MAX + 1];
Ip_u8 ll_type;
Ip_u8 ll_subtype;
/* Resolve this entry; I want the prefix length and the address */
ifi = IP_NLMSG_DATA(nlh);
/* Parse */
ipmip_netlink_nlmsghdr_rta_parse(IP_IFLA_MAX + 1,
IP_IFLA_RTA(ifi),
IP_IFLA_PAYLOAD(nlh),
iflap);
if (ipmip_lladdr_arphdr_to_lltype(ifi->ifi_type, &ll_type, &ll_subtype))
{
/* Need to subresolve any ethernet? */
if (ll_type == IPMIP_LLADDR_TYPE_MAC && ll_subtype == IPMIP_LLADDR_SUBTYPE_MAC_802_3)
{
struct Ip_rtattr *linfo = iflap[IP_IFLA_LINKINFO];
if (linfo)
{
linfo = ipmip_netlink_nlmsghdr_rta_find(IP_RTA_DATA(linfo), IP_RTA_PAYLOAD(linfo), IP_IFLA_INFO_KIND);
if (linfo != IP_NULL)
{
if (ipcom_strcmp("vlan", IP_RTA_DATA(linfo)) == 0)
ll_subtype = IPMIP_LLADDR_SUBTYPE_MAC_802_1Q;
}
}
}
/* Found one */
if (iflap[IP_IFLA_ADDRESS])
{
/* Found a LLA address */
addr_size = IP_RTA_PAYLOAD(iflap[IP_IFLA_ADDRESS]);
addr_data = IP_RTA_DATA(iflap[IP_IFLA_ADDRESS]);
}
/* Time to create */
/* Free old */
if (iff->lladdr != IP_NULL)
ipcom_free(iff->lladdr);
/* Initialize the structure; used in router advertisements */
iff->lladdr = ipmip_lladdr_build(IP_NULL,
ll_type,
ll_subtype,
addr_data,
addr_size);
ipmip_buffer_release(&answer);
return IP_TRUE;
}
else
{
IPCOM_LOG1(ERR, "UNSUCCESSFUL ARPHRD FOR %s", iff->ifname);
}
}
/**/
nlh = IP_NLMSG_NEXT(nlh, nlh_size);
}
IPCOM_LOG1(ERR, "FAILED TO RESOLVE MAC FOR %s", iff->ifname);
ipmip_buffer_release(&answer);
return IP_FALSE;
}
/*
*===========================================================================
* ipmip_if_findbyindex
*===========================================================================
* Description: Locate an interface in our configuration based on index
* Parameters: iflist - The list of interfaces
* idx - The interface index
* Returns: The interface pointer if it exists, IP_NULL otherwise.
*/
IP_GLOBAL Ipmip_if_t *
ipmip_if_findbyindex(Ipcom_list *iflist,
Ip_u32 idx)
{
Ipmip_if_t *iff;
for (iff = IPCOM_LIST_FIRST(iflist); iff; iff = IPCOM_LIST_NEXT(&iff->next))
{
if (iff->ifindex == 0)
continue;
if (iff->ifindex == idx)
return iff;
}
return IP_NULL;
}
/*
*===========================================================================
* ipmip_if_findbyname
*===========================================================================
* Description: Locate an interface in our configuration based on name.
* Parameters: iflist - The list of interfaces.
* ifname - The interface name
* Returns: The interface pointer if it exists, IP_NULL otherwise.
*/
IP_GLOBAL Ipmip_if_t *
ipmip_if_findbyname(Ipcom_list *iflist,
const char *ifname)
{
Ipmip_if_t *iff;
ip_assert(ifname);
for (iff = IPCOM_LIST_FIRST(iflist); iff; iff = IPCOM_LIST_NEXT(&iff->next))
{
if (*ifname == '\0' || ipcom_strcmp(iff->ifname, ifname) == 0)
return iff;
}
return IP_NULL;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,954 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_inet.c,v $ $Revision: 1.11.10.3 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_inet.c,v $
* $Author: jsheng $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_inet.c,v $ $Revision: 1.11.10.3 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_inet.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 "ipmip_config.h"
#ifdef IPMIP_USE_INET
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_clib2.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_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipcom_cmd.h>
#include <ipcom_getopt.h>
#include <ipcom_netif.h>
#include <ipmip.h>
#include <private/ipmip_buffer.h>
#include <private/ipmip_context.h>
#include <private/ipmip_pktbuf.h>
#include <private/ipmip_cli.h>
#include <private/ipmip_util.h>
#include <private/ipmip_sysvar.h>
#include <private/ipmip_inet.h>
#include <private/ipmip_lladdr.h>
#include <private/ipmip_netlink.h>
#include <private/ipmip_if.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMIP_INET_PKT_CLEN 128
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG2
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
static Ip_u16 ipmip_pkt_ipid = 1;
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC unsigned
ipmip_inet_arp_key_ifindex(Ip_u32 *ifindex)
{
return ipcom_hash_update(ifindex, sizeof(*ifindex), 0);
}
IP_STATIC unsigned
ipmip_inet_arp_obj_ifindex(Ipmip_arp_node_t *node)
{
return ipmip_inet_arp_key_ifindex(&node->ifindex);
}
IP_STATIC Ip_bool
ipmip_inet_arp_cmp_ifindex(Ipmip_arp_node_t *node, Ip_u32 *ifindex)
{
/* Compare */
return node->ifindex == *ifindex;
}
IP_STATIC void
ipmip_inet_arp_context_create(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
IPMIP_UNUSED_PARAMETER(proc);
if (ctx->arp != IP_NULL)
return;
ctx->arp = ipcom_calloc(1, sizeof(*ctx->arp));
if(IP_NULL == ctx->arp)
{
return;
}
ctx->arp->fd_arp_in = IP_INVALID_SOCKET;
ctx->arp->fd_arp_out = IP_INVALID_SOCKET;
(void)ipcom_mutex_create(&ctx->arp->mutex);
ctx->arp->ifindex_table = ipcom_hash_new((Ipcom_hash_obj_func) ipmip_inet_arp_obj_ifindex,
(Ipcom_hash_key_func) ipmip_inet_arp_key_ifindex,
(Ipcom_hash_cmp_func) ipmip_inet_arp_cmp_ifindex);
}
IP_STATIC Ipmip_pktbuf_t *
ipmip_inet_arp_recvmsg(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_size_t vlen,
Ip_fd fd)
{
int len;
struct Ip_sockaddr_ll ll;
struct Ip_msghdr msg;
struct Ip_iovec vec;
/* Set when the option is located */
Ipmip_pktbuf_t *pbuf = IP_NULL;
/* Allocate pktbuf */
pbuf = (Ipmip_pktbuf_t *)ipmip_pktbuf_alloc(ctx, proc, vlen);
/* Failed to allocate buffer? */
if (pbuf == IP_NULL)
return IP_NULL;
/* Initialize vector */
vec.iov_base = IPMIP_BUFFER_DATA(&pbuf->packet);
vec.iov_len = vlen;
/* Initialize name */
msg.msg_name = &ll;
msg.msg_namelen = sizeof(ll);
/* Initialize io */
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
/* Initialize control */
msg.msg_control = IP_NULL;
msg.msg_controllen = 0;
/* Clear flags */
msg.msg_flags = 0;
/* Read and process a Mobile Header message */
if ((len = ipcom_recvmsg(fd, &msg, 0)) < 0)
{
/* Failure */
IPCOM_LOG2(ERR,
"%s: Failed to receive from ARP socket = %x",
ctx->name, ipcom_errno);
ipmip_util_sock_clear(fd);
goto error_out;
}
/* Sanity, must be atleast the mobility header */
if ((Ip_size_t)len < sizeof(Ipmip_arp_hdr_t))
{
/* Failure */
IPCOM_LOG1(INFO,
"%s: ARP Received packet was too short", ctx->name);
goto error_out;
}
/* We've gotten something */
if ((msg.msg_flags & (IP_MSG_TRUNC | IP_MSG_CTRUNC)) != 0)
{
/* Failure */
IPCOM_LOG1(INFO,
"%s: ARP TRUNC or CTRUNC set, not all data read. Discarding",
ctx->name);
goto error_out;
}
/* Store value */
ipmip_util_dup(&pbuf->srcinfo.ll, &ll, sizeof(ll));
/**/
pbuf->srcinfo.lladdr = ipmip_lladdr_ll_to_lladdr(pbuf->srcinfo.ll);
/* Move past the read length */
ipmip_buffer_append(&pbuf->packet, IP_NULL, len);
/* */
return pbuf;
error_out:
ipmip_pktbuf_release(ctx, proc, pbuf);
return IP_NULL;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL void
ipmip_inet_arp_write(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_u32 from,
Ip_u32 to,
Ipmip_if_t *iff,
Ipmip_lladdr_t *lladdr)
{
IPMIP_UNUSED_PARAMETER(proc);
/* Only do MAC */
if (lladdr->type == IPMIP_LLADDR_TYPE_MAC && iff->lladdr != IP_NULL && iff->lladdr->type == lladdr->type)
{
struct Ip_iovec iov;
struct Ip_msghdr m;
Ipmip_arp_hdr_t arp;
struct Ip_sockaddr_ll to_ll;
ipcom_memset(&m, 0, sizeof(m));
/* Set the base values */
arp.hrd = IPMIP_ARP_HRD_ETHER;
arp.pro = IPMIP_ARP_PRO_IP;
arp.hln_pln = IPMIP_ARP_HLN_PLN;
arp.op = IPMIP_ARP_OP_REPLY;
/* Setup the structures */
ipcom_memcpy(arp.eth_src, iff->lladdr->lla, IPMIP_ETH_ADDR_SIZE);
ipcom_memcpy(arp.eth_dst, lladdr->lla, IPMIP_ETH_ADDR_SIZE);
IP_SET_32ON8(arp.ip_src, from);
IP_SET_32ON8(arp.ip_dst, to);
IPCOM_SA_LEN_SET(&to_ll, sizeof(to_ll));
to_ll.sll_family = IP_AF_PACKET;
to_ll.sll_protocol = ip_htons(IPMIP_ETH_P_ARP);
to_ll.sll_ifindex = iff->ifindex;
to_ll.sll_halen = IPMIP_ETH_ADDR_SIZE;
ipcom_memcpy(to_ll.sll_addr, lladdr->lla, IPMIP_ETH_ADDR_SIZE);
iov.iov_base = &arp;
iov.iov_len = sizeof(arp);
m.msg_iov = &iov;
m.msg_iovlen = 1;
m.msg_name = &to_ll;
m.msg_namelen = sizeof(to_ll);
/* */
if (ipcom_sendmsg(ctx->arp->fd_arp_out, &m, 0) < 0)
ipmip_util_sock_clear(ctx->arp->fd_arp_out);
}
}
IP_GLOBAL void
ipmip_inet_arp_reply(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_arp_hdr_t *arp_req,
Ipmip_if_t *iff)
{
IPMIP_UNUSED_PARAMETER(proc);
/* Only do MAC */
if (iff->lladdr != IP_NULL && iff->lladdr->type == IPMIP_LLADDR_TYPE_MAC)
{
Ipmip_lladdr_t *lla = ipmip_lladdr_build((Ipmip_lladdr_t *)proc->ntop.ntop_pbuf, iff->lladdr->type, iff->lladdr->type, &arp_req->eth_src[0], IPMIP_ETH_ADDR_SIZE);
ipmip_inet_arp_write(ctx, proc, IP_GET_32ON8(&arp_req->ip_dst), IP_GET_32ON8(&arp_req->ip_src), iff, lla);
}
}
IP_GLOBAL Ipmip_pktbuf_t *
ipmip_inet_udp_recvmsg(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_size_t vlen,
Ip_fd fd)
{
struct Ip_cmsghdr *cmsghdr;
int len;
/* Destination Option & Packet Info */
struct Ip_msghdr msg;
struct Ip_iovec vec;
Ipmip_pktbuf_t *pbuf = IP_NULL;
struct Ip_sockaddr_in src;
/* Allocate pktbuf */
pbuf = (Ipmip_pktbuf_t *)ipmip_pktbuf_alloc(ctx, proc, vlen + IPMIP_INET_PKT_CLEN);
/* Failed to allocate buffer? */
if (pbuf == IP_NULL)
return IP_NULL;
/* Initialize vector */
vec.iov_base = IPMIP_BUFFER_DATA(&pbuf->packet);
vec.iov_len = vlen;
/* Initialize name */
msg.msg_name = &src;
msg.msg_namelen = sizeof(src);
/* Initialize io */
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
/* Initialize control */
msg.msg_control = ipmip_buffer_offset(&pbuf->packet, vlen);
msg.msg_controllen = IPMIP_INET_PKT_CLEN;
/* Clear flags */
msg.msg_flags = 0;
/* Read and process a Mobile Header message */
if ((len = ipcom_recvmsg(fd, &msg, 0)) <= 0)
{
ipmip_util_sock_clear(fd);
goto error_out;
}
/* We've gotten something */
if ((msg.msg_flags & (IP_MSG_TRUNC | IP_MSG_CTRUNC)) != 0)
goto error_out;
/* Store value */
ipmip_util_dup(&pbuf->srcinfo.src, &src, sizeof(src));
/* Move past the read length */
ipmip_buffer_append(&pbuf->packet, IP_NULL, len);
/* Did we get any ancillary data? */
if (msg.msg_controllen > 0)
{
/* Loop the ancillary data, see what we find */
for (cmsghdr = IP_CMSG_FIRSTHDR(&msg); cmsghdr != 0; cmsghdr = IP_CMSG_NXTHDR(&msg, cmsghdr))
{
/* Correct level? */
if (cmsghdr->cmsg_level == IP_IPPROTO_IP)
{
/* Type? */
switch (cmsghdr->cmsg_type)
{
case IP_IP_X_SENDERLINKADDR:
{
struct Ip_sockaddr_dl *dl = IP_CMSG_DATA(cmsghdr);
ipmip_util_dup(&pbuf->srcinfo.dl, dl, IPCOM_SA_LEN_GET(dl));
}
break;
case IP_IP_PKTINFO:
{
struct Ip_in_pktinfo *pktinfo = IP_CMSG_DATA(cmsghdr);
ipmip_pktbuf_srcinfo_dst_inet(pbuf, pktinfo);
}
break;
case IP_IP_TTL:
{
int *ttl = IP_CMSG_DATA(cmsghdr);
pbuf->srcinfo.ttl = IP_GET_32ON8(ttl);
}
break;
default:
break;
}
}
}
}
if (pbuf->srcinfo.dst == IP_NULL)
goto error_out;
pbuf->srcinfo.lladdr = ipmip_lladdr_dl_to_lladdr(pbuf->srcinfo.dl, pbuf->srcinfo.dst->ifindex);
return pbuf;
error_out:
ipmip_pktbuf_release(ctx, proc, pbuf);
return IP_NULL;
}
/*
*===========================================================================
* ipmip4_pkt_udp_write
*===========================================================================
* Description: Send a UDP message to a link local host with the
* indicated MAC address.
* Parameters: ctx - The context
* proc - Process context
* payload - The payload buffer
* from - The source address
* from_port - The source port in netwrok byte order
* to - The destination address
* to_port - The destination port in network byte order
* iff - Outgoing interface
* lla - MAC address
* Returns: The resulting return code.
*
*/
IP_GLOBAL int
ipmip_inet_udp_write(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_fd fd_pkt,
Ip_fd fd_raw,
Ipmip_buffer_t *payload,
Ip_u32 from,
Ip_u16 from_port,
Ip_u32 to,
Ip_u16 to_port,
Ipmip_if_t *iff,
Ipmip_lladdr_t *lladdr)
{
int ret = -IP_ERRNO_EINVAL;
Ip_u32 chk;
Ip_size_t tot_size = 0;
struct Ip_iovec iov[3];
Ipcom_ip_header iph;
Ipcom_udp_header udph;
struct Ip_msghdr m;
IPMIP_UNUSED_PARAMETER(proc);
/* */
if (fd_raw != IP_INVALID_SOCKET)
{
if (lladdr == IP_NULL || fd_pkt == IP_INVALID_SOCKET || lladdr->type != IPMIP_LLADDR_TYPE_MAC)
return ipmip_inet_udp_sendmsg(ctx, proc, fd_raw, payload, from, from_port, to, to_port, iff);
}
else if (lladdr == IP_NULL)
return -IP_ERRNO_EINVAL;
chk = 0;
/* Create the IO vector */
iov[0].iov_base = &iph;
iov[0].iov_len = sizeof(iph);
iov[1].iov_base = &udph;
iov[1].iov_len = sizeof(udph);
iov[2].iov_base = IPMIP_BUFFER_DATA(payload);
iov[2].iov_len = IPMIP_BUFFER_SIZE(payload);
/* Start with the payload as total size */
tot_size = IPMIP_BUFFER_SIZE(payload);
/* Zero the memory */
ipcom_memset(&iph, 0, sizeof(iph));
ipcom_memset(&udph, 0, sizeof(udph));
ipcom_memset(&m, 0, sizeof(m));
/* Include the UDP header */
tot_size += sizeof(udph);
if (to == 0)
/* Send to world wide broadcast */
to = IP_INADDR_BROADCAST;
/* Create the UDP packet */
udph.src_port = from_port;
udph.dst_port = to_port;
udph.length = ip_htons((Ip_u16) tot_size);
/* IPv4 header */
tot_size += sizeof(iph);
iph.vers_len = 0x45;
iph.id = ip_htons(ipmip_pkt_ipid);
iph.ttl = 255;
iph.protocol = IP_IPPROTO_UDP;
iph.src.addr32 = from;
iph.dst.addr32 = to;
ipmip_pkt_ipid++;
/* UDP checksum (including pseudo-header) */
chk = ((Ip_u16 *) &iph.src)[0];
chk += ((Ip_u16 *) &iph.src)[1];
chk += ((Ip_u16 *) &iph.dst)[0];
chk += ((Ip_u16 *) &iph.dst)[1];
chk += udph.length;
{
Ip_u16 tmp = iph.protocol;
chk += ip_htons(tmp);
}
chk += ipcom_in_checksum_update(&udph, sizeof(udph));
/* Do the checksum calculation */
chk += ipcom_in_checksum_update(iov[2].iov_base,
iov[2].iov_len);
udph.checksum = ipcom_in_checksum_finish(chk);
m.msg_iov = iov;
m.msg_iovlen = 3;
/* Is it a local packet or routed packet? */
iph.length = ip_htons(((Ip_u16)tot_size));
/* Local; build IP & UDP header */
chk = ipcom_in_checksum_update(&iph, sizeof(iph));
iph.checksum = ipcom_in_checksum_finish(chk);
/**/
if (fd_pkt != IP_INVALID_SOCKET)
{
/* Only deal with MAC's right now */
if (lladdr->type == IPMIP_LLADDR_TYPE_MAC)
{
struct Ip_sockaddr_ll to_ll;
IPCOM_SA_LEN_SET(&to_ll, sizeof(to_ll));
to_ll.sll_family = IP_AF_PACKET;
to_ll.sll_protocol = ip_htons(0x800);
to_ll.sll_ifindex = iff->ifindex;
to_ll.sll_halen = 6;
ipcom_memcpy(to_ll.sll_addr, lladdr->lla, IPMIP_ETH_ADDR_SIZE);
m.msg_name = &to_ll;
m.msg_namelen = sizeof(to_ll);
if ((ipcom_sendmsg(fd_pkt, &m, 0)) < 0)
{
ret = -ipcom_errno;
ipmip_util_sock_clear(fd_pkt);
}
else
{
ret = IPCOM_SUCCESS;
}
goto done_out;
}
}
/**/
done_out:
return ret;
}
IP_GLOBAL Ip_fd
ipmip_inet_udp_socket(struct Ip_sockaddr_in *s_in)
{
Ip_fd s;
int i = 1;
Ip_socklen_t slen;
/* Create raw IP socket for all IPv4 input on this interface */
if ((s = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, IP_IPPROTO_UDP)) == IP_INVALID_SOCKET)
return IP_INVALID_SOCKET;
/* Allow reusage of address */
if (ipcom_setsockopt(s, IP_SOL_SOCKET, IP_SO_REUSEADDR, &i, sizeof(i)))
goto fail;
/* Allow reusage of ports */
if (ipcom_setsockopt(s, IP_SOL_SOCKET, IP_SO_REUSEPORT, &i, sizeof(i)))
goto fail;
/* I want to receive PACKET INFO as ancillary data */
if (ipcom_setsockopt(s, IP_IPPROTO_IP, IP_IP_PKTINFO, &i, sizeof(i)) < 0)
goto fail;
if (ipcom_setsockopt(s, IP_IPPROTO_IP, IP_IP_RECVTTL, &i, sizeof(i)))
goto fail;
/* Enable IP_X_SENDERLINKADDR to get source link address */
if (ipcom_setsockopt(s, IP_IPPROTO_IP, IP_IP_X_SENDERLINKADDR, &i, sizeof(i)) < 0)
goto fail;
if (s_in != IP_NULL)
{
/* */
if (ipcom_bind(s, (struct Ip_sockaddr *) s_in, sizeof(*s_in)) < 0)
goto fail;
slen = sizeof(*s_in);
if (ipcom_getsockname(s, (struct Ip_sockaddr *) s_in, &slen) < 0)
goto fail;
}
return s;
fail:
ipcom_socketclose(s);
return IP_INVALID_SOCKET;
}
/*
*===========================================================================
* ipmip_inet_udp_sendmsg
*===========================================================================
* Description: Send a UDP message to a remote host
* Parameters: ctx - The context
* proc - Process context
* payload - The payload buffer
* from - The source address
* from_port - The source port in network byte order
* to - The destination address
* to_port - The destination port in network byte order
* iff - If set; the interface to force the output on.
* Returns: The resulting return code.
*
*/
IP_GLOBAL int
ipmip_inet_udp_sendmsg(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_fd fd_raw,
Ipmip_buffer_t *payload,
Ip_u32 from,
Ip_u16 from_port,
Ip_u32 to,
Ip_u16 to_port,
Ipmip_if_t *iff)
{
int ret = IPCOM_SUCCESS;
Ip_u32 chk;
Ip_size_t tot_size = 0;
struct Ip_iovec iov[3];
Ipcom_ip_header iph;
Ipcom_udp_header udph;
struct Ip_msghdr m;
Ip_u8 cmsg_buf[IP_CMSG_SPACE(sizeof(struct Ip_in_pktinfo))];
struct Ip_cmsghdr *c;
struct Ip_in_pktinfo *pktinfo;
struct Ip_sockaddr_in sin4;
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
chk = 0;
/* Create the IO vector */
iov[0].iov_base = &iph;
iov[0].iov_len = sizeof(iph);
iov[1].iov_base = &udph;
iov[1].iov_len = sizeof(udph);
iov[2].iov_base = IPMIP_BUFFER_DATA(payload);
iov[2].iov_len = IPMIP_BUFFER_SIZE(payload);
/* Start with the payload as total size */
tot_size = IPMIP_BUFFER_SIZE(payload);
/* Zero the memory */
ipcom_memset(&iph, 0, sizeof(iph));
ipcom_memset(&udph, 0, sizeof(udph));
ipcom_memset(&m, 0, sizeof(m));
/* Include the UDP header */
tot_size += sizeof(udph);
if (to == 0)
to = IP_INADDR_BROADCAST;
/* Create the UDP packet */
udph.src_port = from_port;
udph.dst_port = to_port;
udph.length = ip_htons((Ip_u16) tot_size);
/* IPv4 header */
tot_size += sizeof(iph);
iph.vers_len = 0x45;
iph.id = ip_htons(ipmip_pkt_ipid);
iph.ttl = 255;
iph.protocol = IP_IPPROTO_UDP;
iph.src.addr32 = from;
iph.dst.addr32 = to;
ipcom_memset(&sin4, 0, sizeof(sin4));
sin4.sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(&sin4, sizeof(sin4));
sin4.sin_port = to_port;
sin4.sin_addr.s_addr = to;
ipmip_pkt_ipid++;
/* UDP checksum (including pseudo-header) */
chk = ((Ip_u16 *) &iph.src)[0];
chk += ((Ip_u16 *) &iph.src)[1];
chk += ((Ip_u16 *) &iph.dst)[0];
chk += ((Ip_u16 *) &iph.dst)[1];
chk += udph.length;
{
Ip_u16 tmp = iph.protocol;
chk += ip_htons(tmp);
}
chk += ipcom_in_checksum_update(&udph, sizeof(udph));
/* Do the checksum calculation */
chk += ipcom_in_checksum_update(iov[2].iov_base,
iov[2].iov_len);
udph.checksum = ipcom_in_checksum_finish(chk);
m.msg_iov = iov;
m.msg_iovlen = 3;
/* Is it a local packet or routed packet? */
iph.length = (Ip_u16) tot_size;
m.msg_name = &sin4;
m.msg_namelen = sizeof(sin4);
/* Force it out the indicated interface */
if (iff != IP_NULL)
{
/* Use ancillary data to specify outgoing interface and address. */
c = (struct Ip_cmsghdr *) cmsg_buf;
c->cmsg_len = IP_CMSG_LEN(sizeof(struct Ip_in_pktinfo));
c->cmsg_level = IP_IPPROTO_IP;
c->cmsg_type = IP_IP_PKTINFO;
pktinfo = IP_CMSG_DATA(c);
ipcom_memset(pktinfo, 0, sizeof(*pktinfo));
/* Bind to the correct interface */
pktinfo->ipi_ifindex = iff->ifindex;
m.msg_control = c;
m.msg_controllen = sizeof(cmsg_buf);
}
/* Do send */
if (ipcom_sendmsg(fd_raw, &m, 0) <0)
{
ret = -ipcom_errno;
ipmip_util_sock_clear(fd_raw);
}
/**/
return ret;
}
IP_GLOBAL void
ipmip_inet_arp_context_in_create(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
ipmip_inet_arp_context_create(ctx, proc);
if (ctx->arp->fd_arp_in == IP_INVALID_SOCKET)
{
ctx->arp->fd_arp_in = ipcom_socket(IP_AF_PACKET, IP_SOCK_DGRAM, ip_htons(0x0806));
ipcom_shutdown(ctx->arp->fd_arp_in, IP_SHUT_WR);
}
}
IP_GLOBAL void
ipmip_inet_arp_context_out_create(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
ipmip_inet_arp_context_create(ctx, proc);
if (ctx->arp->fd_arp_out == IP_INVALID_SOCKET)
{
ctx->arp->fd_arp_out = ipcom_socket(IP_AF_PACKET, IP_SOCK_DGRAM, ip_htons(0x0806));
ipcom_shutdown(ctx->arp->fd_arp_out, IP_SHUT_RD);
}
}
IP_GLOBAL void
ipmip_inet_arp_context_destroy(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
IPMIP_UNUSED_PARAMETER(proc);
if (ctx->arp != IP_NULL)
{
if (ctx->arp->fd_arp_in != IP_INVALID_SOCKET)
ipcom_socketclose(ctx->arp->fd_arp_in);
if (ctx->arp->fd_arp_out != IP_INVALID_SOCKET)
ipcom_socketclose(ctx->arp->fd_arp_out);
if (ctx->arp->ifindex_table)
ipcom_hash_delete(ctx->arp->ifindex_table);
ipcom_mutex_delete(&ctx->arp->mutex);
ipcom_free(ctx->arp);
ctx->arp = IP_NULL;
}
}
IP_GLOBAL void
ipmip_inet_arp_process(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
Ipmip_pktbuf_t *pbuf = ipmip_inet_arp_recvmsg(ctx, proc, 1024, ctx->arp->fd_arp_in);
/* Invoke callback */
if (pbuf)
{
Ipmip_arp_node_t *node = IP_NULL;
ipcom_mutex_lock(ctx->arp->mutex);
node = ipcom_hash_get(ctx->arp->ifindex_table, &pbuf->srcinfo.ll->sll_ifindex);
/* Time to invoke function */
if (node != IP_NULL)
ipmip_timer_request(ctx, proc, &pbuf->timeout, node->lock, node->process_func, node, pbuf, 0);
else
ipmip_pktbuf_release(ctx, proc, pbuf);
ipcom_mutex_unlock(ctx->arp->mutex);
}
}
IP_GLOBAL void
ipmip_inet_arp_register(struct Ipmip_context *ctx,
struct Ipmip_proc *proc,
Ipmip_arp_node_t *node)
{
IPMIP_UNUSED_PARAMETER(proc);
/* We're going to relay */
ipcom_mutex_lock(ctx->arp->mutex);
if (node->ifindex)
ipcom_hash_add(ctx->arp->ifindex_table, node);
ipcom_mutex_unlock(ctx->arp->mutex);
}
IP_GLOBAL void
ipmip_inet_arp_unregister(struct Ipmip_context *ctx,
struct Ipmip_proc *proc,
Ipmip_arp_node_t *node)
{
IPMIP_UNUSED_PARAMETER(proc);
/* We're going to relay */
ipcom_mutex_lock(ctx->arp->mutex);
if (node->ifindex)
ipcom_hash_remove(ctx->arp->ifindex_table, node);
ipcom_mutex_unlock(ctx->arp->mutex);
}
/*
*===========================================================================
* ipmip_inet_arp_proxy
*===========================================================================
* Description: This is run when initiating proxying for an address
* Sets(/deletes) a static, permanent, public and blackholed arp entry,
* plus sends out a gratuitous arp.
* Parameters:
* Returns: IP_TRUE on success.
*
*/
IP_GLOBAL Ip_bool
ipmip_inet_arp_proxy(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_u32 ifindex,
Ip_u32 address,
Ip_bool set)
{
return ipmip_netlink_inX_neigh(ctx, proc, IP_AF_INET, set? IP_RTM_NEWNEIGH : IP_RTM_DELNEIGH, IP_NLM_F_CREATE, ifindex, IP_NTF_PROXY|IP_NTF_GRAT, IP_NUD_PERMANENT|IP_NUD_REACHABLE, &address, IP_NULL) == 0;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
#else
int ipmip_inet_empty_file = 0;
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,331 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_inet6.c,v $ $Revision: 1.2 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_inet6.c,v $
* $Author: jhorteli $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmip_config.h"
#ifdef IPMIP_USE_INET6
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_clib2.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_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipcom_cmd.h>
#include <ipcom_getopt.h>
#include <ipcom_netif.h>
#include <ipmip.h>
#include <private/ipmip_buffer.h>
#include <private/ipmip_context.h>
#include <private/ipmip_pktbuf.h>
#include <private/ipmip_cli.h>
#include <private/ipmip_util.h>
#include <private/ipmip_sysvar.h>
#include <private/ipmip_inet6.h>
#include <private/ipmip_lladdr.h>
#include <private/ipmip_if.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMIP_INET6_PKT_CLEN 128
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_bool
ipmip_inet6_multicast_join(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_fd fd,
Ip_u32 ifindex,
struct Ip_in6_addr *mcast)
{
struct Ip_ipv6_mreq mreq;
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
/* Clear it all */
ipcom_memset(&mreq, 0, sizeof(mreq));
/* Set the correct solicited address */
ipcom_memcpy(&mreq.ipv6mr_multiaddr, mcast, sizeof(*mcast));
mreq.ipv6mr_interface = ifindex;
if (ipcom_setsockopt(fd, IP_IPPROTO_IPV6, IP_IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0)
return IP_FALSE;
return IP_TRUE;
}
IP_GLOBAL Ip_bool
ipmip_inet6_multicast_leave(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_fd fd,
Ip_u32 ifindex,
struct Ip_in6_addr *mcast)
{
struct Ip_ipv6_mreq mreq;
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
/* Clear it all */
ipcom_memset(&mreq, 0, sizeof(mreq));
/* Set the correct solicited address */
ipcom_memcpy(&mreq.ipv6mr_multiaddr, mcast, sizeof(*mcast));
mreq.ipv6mr_interface = ifindex;
if (ipcom_setsockopt(fd, IP_IPPROTO_IPV6, IP_IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)) < 0)
return IP_FALSE;
return IP_TRUE;
}
IP_GLOBAL Ip_bool
ipmip_inet6_anycast_join(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_fd fd,
Ip_u32 ifindex,
struct Ip_in6_addr *anycast)
{
struct Ip_ipv6_mreq mreq;
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
/* Clear it all */
ipcom_memset(&mreq, 0, sizeof(mreq));
/* Set the correct solicited address */
ipcom_memcpy(&mreq.ipv6mr_multiaddr, anycast, sizeof(*anycast));
mreq.ipv6mr_interface = ifindex;
if (ipcom_setsockopt(fd, IP_IPPROTO_IPV6, IP_IPV6_JOIN_ANYCAST, &mreq, sizeof(mreq)) < 0)
return IP_FALSE;
return IP_TRUE;
}
IP_GLOBAL Ip_bool
ipmip_inet6_anycast_leave(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_fd fd,
Ip_u32 ifindex,
struct Ip_in6_addr *anycast)
{
struct Ip_ipv6_mreq mreq;
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
/* Clear it all */
ipcom_memset(&mreq, 0, sizeof(mreq));
/* Set the correct solicited address */
ipcom_memcpy(&mreq.ipv6mr_multiaddr, anycast, sizeof(*anycast));
mreq.ipv6mr_interface = ifindex;
if (ipcom_setsockopt(fd, IP_IPPROTO_IPV6, IP_IPV6_LEAVE_ANYCAST, &mreq, sizeof(mreq)) < 0)
return IP_FALSE;
return IP_TRUE;
}
/*
*===========================================================================
* ipmip6_icmp_recv
*===========================================================================
* Description: Receive and process an ICMP message.
* Parameters: context - The context
* Returns: IP_TRUE if successful.
*
*/
IP_GLOBAL Ipmip_pktbuf_t *
ipmip_inet6_udp_recvmsg(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_size_t vlen,
Ip_fd fd)
{
struct Ip_cmsghdr *cmsghdr;
int len;
struct Ip_sockaddr_in6 src;
struct Ip_msghdr msg;
struct Ip_iovec vec;
/* Set when the option is located */
Ipmip_pktbuf_t *pbuf = IP_NULL;
/* Allocate pktbuf */
pbuf = (Ipmip_pktbuf_t *)ipmip_pktbuf_alloc(ctx, proc, vlen + IPMIP_INET6_PKT_CLEN);
/* Failed to allocate buffer? */
if (pbuf == IP_NULL)
return IP_NULL;
/* Initialize vector */
vec.iov_base = IPMIP_BUFFER_DATA(&pbuf->packet);
vec.iov_len = vlen;
/* Initialize name */
msg.msg_name = &src;
msg.msg_namelen = sizeof(src);
/* Initialize io */
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
/* Initialize control */
msg.msg_control = ipmip_buffer_offset(&pbuf->packet, vlen);
msg.msg_controllen = IPMIP_INET6_PKT_CLEN;
/* Clear flags */
msg.msg_flags = 0;
/* Read and process a Mobile Header message */
if ((len = ipcom_recvmsg(fd, &msg, 0)) < 0)
{
ipmip_util_sock_clear(fd);
goto error_out;
}
/* We've gotten something */
if ((msg.msg_flags & (IP_MSG_TRUNC | IP_MSG_CTRUNC)) != 0)
goto error_out;
/* Store value */
ipmip_util_dup(&pbuf->srcinfo.src, &src, sizeof(src));
/* Move past the read length */
ipmip_buffer_append(&pbuf->packet, IP_NULL, len);
/* Did we get any ancillary data? */
if (msg.msg_controllen > 0)
{
/* Loop the ancillary data, see what we find */
for (cmsghdr = IP_CMSG_FIRSTHDR(&msg); cmsghdr != 0;
cmsghdr = IP_CMSG_NXTHDR(&msg, cmsghdr))
{
/* Correct level? */
if (cmsghdr->cmsg_level == IP_IPPROTO_IPV6)
{
/* Type? */
switch (cmsghdr->cmsg_type)
{
case IP_IPV6_RECVPKTINFO: /* LKM */
case IP_IPV6_PKTINFO: /* IPNET */
ipmip_pktbuf_srcinfo_dst_inet6(pbuf, (struct Ip_in6_pktinfo *)IP_CMSG_DATA(cmsghdr));
break;
default:
break;
}
}
}
}
/* Do sanity */
if (pbuf->srcinfo.dst == IP_NULL)
goto error_out;
/* */
return pbuf;
error_out:
ipmip_pktbuf_release(ctx, proc, pbuf);
return IP_NULL;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
#else /* IPMIP_USE_INET6 */
int ipmip_inet6_empty_file = 0;
#endif /* IPMIP_USE_INET6 */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,714 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_lladdr.c,v $ $Revision: 1.10.16.2 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_lladdr.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 <ipmip_config.h>
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_list.h>
#include <ipcom_inet.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipcom_netif.h>
#include <ipcom_arphrd.h>
#include <ipmip.h>
#include <private/ipmip_lladdr.h>
#include <private/ipmip_context.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG2
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
Ipmip_lladdr_parse_t ipmip_lladdr_parse_defs[] =
{
/* Ethernet Type */
{ "802.3", 5, IPMIP_LLADDR_TYPE_MAC, IPMIP_LLADDR_SUBTYPE_MAC_802_3, IPMIP_LLADDR_FORMAT_HEX },
/* Aliases */
{ "MAC", 3, IPMIP_LLADDR_TYPE_MAC, IPMIP_LLADDR_SUBTYPE_MAC_802_3, IPMIP_LLADDR_FORMAT_HEX },
{ "ETH", 3, IPMIP_LLADDR_TYPE_MAC, IPMIP_LLADDR_SUBTYPE_MAC_802_3, IPMIP_LLADDR_FORMAT_HEX },
{ "ETHERNET", 8, IPMIP_LLADDR_TYPE_MAC, IPMIP_LLADDR_SUBTYPE_MAC_802_3, IPMIP_LLADDR_FORMAT_HEX },
/* VLAN Type */
{ "802.1Q", 6, IPMIP_LLADDR_TYPE_MAC, IPMIP_LLADDR_SUBTYPE_MAC_802_1Q, IPMIP_LLADDR_FORMAT_HEX },
/* Aliases */
{ "VLAN", 4, IPMIP_LLADDR_TYPE_MAC, IPMIP_LLADDR_SUBTYPE_MAC_802_1Q, IPMIP_LLADDR_FORMAT_HEX },
/* WLAN Type */
{ "802.11", 6, IPMIP_LLADDR_TYPE_MAC, IPMIP_LLADDR_SUBTYPE_MAC_802_11, IPMIP_LLADDR_FORMAT_HEX },
/* Aliases */
{ "WLAN", 4, IPMIP_LLADDR_TYPE_MAC, IPMIP_LLADDR_SUBTYPE_MAC_802_11, IPMIP_LLADDR_FORMAT_HEX },
/* WIMAX Type */
{ "802.16E", 7, IPMIP_LLADDR_TYPE_MAC, IPMIP_LLADDR_SUBTYPE_MAC_802_16E, IPMIP_LLADDR_FORMAT_HEX },
{ "802.16M", 7, IPMIP_LLADDR_TYPE_MAC, IPMIP_LLADDR_SUBTYPE_MAC_802_16M, IPMIP_LLADDR_FORMAT_HEX },
/* Internet Address Type */
{ "INET", 4, IPMIP_LLADDR_TYPE_INET, 0, IPMIP_LLADDR_FORMAT_INET },
/* Aliases */
{ "IP", 2, IPMIP_LLADDR_TYPE_INET, 0, IPMIP_LLADDR_FORMAT_INET },
/* Internet Address v6 Type */
{ "INET6", 5, IPMIP_LLADDR_TYPE_INET6, 0, IPMIP_LLADDR_FORMAT_INET6 },
/* Aliases */
{ "IP6", 3, IPMIP_LLADDR_TYPE_INET6, 0, IPMIP_LLADDR_FORMAT_INET6 },
/* IMEI */
{ "IMEI", 3, IPMIP_LLADDR_TYPE_IMEI, 0, IPMIP_LLADDR_FORMAT_DEC_DIGIT },
/* MEID */
{ "MEID", 4, IPMIP_LLADDR_TYPE_MEID, 0, IPMIP_LLADDR_FORMAT_HEX_DIGIT },
{ IP_NULL, 0, 0, 0 },
};
const char *ipmip_lladdr_mac_subtypes[IPMIP_LLADDR_SUBTYPE_MAC_MAX] =
{
"none",
"802.3",
"802.1q",
"802.11",
"802.16e",
"802.16m"
};
const char *ipmip_lladdr_tunnel_subtypes[IPMIP_LLADDR_SUBTYPE_TUNNEL_MAX] =
{
"none",
"ipip",
"ip6ip6",
"sit",
"gre",
"gre6",
"6to4",
"6over4"
};
const char *ipmip_lladdr_inet_subtypes[IPMIP_LLADDR_SUBTYPE_INET_MAX] =
{
"none",
"fa",
"solicited"
};
const char *ipmip_lladdr_3gpp2_subtypes[IPMIP_LLADDR_SUBTYPE_3GPP2_MAX] =
{
"none",
"1xRTT HRPD",
"UMB"
};
const char *ipmip_lladdr_3gpp_subtypes[IPMIP_LLADDR_SUBTYPE_3GPP_MAX] =
{
"none",
"eutran lte",
"utran geran"
};
Ipmip_lladdr_typedef_t ipmip_lladdr_type_defs[IPMIP_LLADDR_TYPE_MAX] =
{
{ "UNSPEC", 0, IPMIP_LLADDR_FORMAT_NONE, 0, IP_NULL },
{ "MAC", 6, IPMIP_LLADDR_FORMAT_HEX, IPMIP_LLADDR_SUBTYPE_MAC_MAX - 1, &ipmip_lladdr_mac_subtypes[0] },
{ "EUID64", 8, IPMIP_LLADDR_FORMAT_HEX, 0, IP_NULL },
{ "MEID", 0, IPMIP_LLADDR_FORMAT_NONE, 0, IP_NULL },
{ "ESN", 0, IPMIP_LLADDR_FORMAT_NONE, 0, IP_NULL },
{ "IMEI", 0, IPMIP_LLADDR_FORMAT_NONE, 0, IP_NULL },
{ "INET", 0, IPMIP_LLADDR_TYPE_INET, IPMIP_LLADDR_SUBTYPE_INET_MAX - 1, &ipmip_lladdr_inet_subtypes[0] },
{ "INET6", 0, IPMIP_LLADDR_TYPE_INET6, 0, IP_NULL },
{ "3GPP", 0, IPMIP_LLADDR_FORMAT_NONE, IPMIP_LLADDR_SUBTYPE_3GPP_MAX - 1, &ipmip_lladdr_3gpp_subtypes[0] },
{ "3GPP2", 0, IPMIP_LLADDR_FORMAT_NONE, IPMIP_LLADDR_SUBTYPE_3GPP2_MAX - 1, &ipmip_lladdr_3gpp2_subtypes[0] },
{ "BSSID", 0, IPMIP_LLADDR_FORMAT_U32, 0, IP_NULL },
{ "TUNNEL", 0, IPMIP_LLADDR_FORMAT_NONE, IPMIP_LLADDR_SUBTYPE_TUNNEL_MAX - 1, &ipmip_lladdr_tunnel_subtypes[0] },
{ "PPP", 0, IPMIP_LLADDR_FORMAT_NONE, 0, IP_NULL },
{ "LOOPBACK", 0, IPMIP_LLADDR_FORMAT_NONE, 0, IP_NULL }
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_STATIC Ipmip_lladdr_parse_t *
ipmip_lladdr_find_parse_def(const char *str,
Ip_u8 type,
Ip_u8 subtype,
Ip_size_t *off)
{
int i;
const char *delim;
if ((delim = ipcom_strchr(str, '=')) != IP_NULL ||
(delim = ipcom_strchr(str, ':')) != IP_NULL)
{
Ip_size_t doff = (Ip_size_t) (delim - str);
for (i = 0; ipmip_lladdr_parse_defs[i].pre != IP_NULL; i++)
{
if (doff != ipmip_lladdr_parse_defs[i].pre_len)
continue;
if (ipcom_strncasecmp(ipmip_lladdr_parse_defs[i].pre, str, doff) == 0)
{
*off = doff + 1;
return &ipmip_lladdr_parse_defs[i];
}
}
}
if (type)
{
for (i = 0; ipmip_lladdr_parse_defs[i].pre != IP_NULL; i++)
{
if (ipmip_lladdr_parse_defs[i].type == type)
{
Ipmip_lladdr_parse_t *cpdef = &ipmip_lladdr_parse_defs[i];
if (subtype)
{
for (; ipmip_lladdr_parse_defs[i].pre != IP_NULL && ipmip_lladdr_parse_defs[i].type == cpdef->type; i++)
{
if (subtype == ipmip_lladdr_parse_defs[i].subtype)
return &ipmip_lladdr_parse_defs[i];
}
}
return cpdef;
}
}
}
return IP_NULL;
}
/*
*===========================================================================
* ipmip_lladdr_build
*===========================================================================
* Description: Initialize a LLA extension based on the provided parameters
* Parameters: lla_ext - The extension; must be large enough
* subtype - The subtype.
* lla - The link layer address
* lla_len - The link layer address length
* Returns: A pointer to the icmp_lla_ext if created; IP_NULL otherwise.
*
*/
IP_GLOBAL Ipmip_lladdr_t *
ipmip_lladdr_build(Ipmip_lladdr_t *lladdr,
Ip_u8 type,
Ip_u8 subtype,
void *lla,
int lla_len)
{
if (lladdr == IP_NULL)
{
lladdr = ipcom_calloc(1, IPMIP_LLADDR_LEN_TOTAL(lla_len));
if(IP_NULL == lladdr)
return IP_NULL;
}
/* Store values */
lladdr->type = type;
lladdr->subtype = subtype;
lladdr->len = IPMIP_LLADDR_LEN_TOTAL(lla_len);
ipcom_memcpy(&lladdr->lla[0], lla, lla_len);
return lladdr;
}
/*
*===========================================================================
* ipmip_lladdr_cmp
*===========================================================================
* Description: Compares two LLA's
* Parameters: lla1 - The first lla
* lla2 - The second lla
* Returns: IP_TRUE if they're identical.
*
*/
IP_GLOBAL Ip_bool
ipmip_lladdr_cmp(Ipmip_lladdr_t *lla1,
Ipmip_lladdr_t *lla2)
{
/* Pointers are identical? */
if (lla1 == lla2)
return IP_TRUE;
/* One of them is unspecified */
if (lla1 == IP_NULL || lla2 == IP_NULL)
return IP_FALSE;
/* Subtype or length different? */
if (lla1->len != lla2->len)
return IP_FALSE;
/* Compare the LLA portion */
return ipcom_memcmp(lla1, lla2, lla1->len) == 0;
}
/*
*===========================================================================
* ipmip_lladdr_dup
*===========================================================================
* Description: Duplicate a LLA
* Parameters: lla - The lla to duplicate
* Returns: A pointer to the new LLA
*
*/
IP_GLOBAL Ipmip_lladdr_t *
ipmip_lladdr_dup(Ipmip_lladdr_t *lla)
{
Ipmip_lladdr_t *nlla = ipcom_malloc(lla->len);
if (nlla != IP_NULL)
ipcom_memcpy(nlla, lla, lla->len);
return nlla;
}
IP_GLOBAL Ip_bool
ipmip_lladdr_arphdr_to_lltype(Ip_u16 type,
Ip_u8 *ll_type,
Ip_u8 *ll_subtype)
{
switch (type)
{
case IP_ARPHRD_ETHER:
*ll_type = IPMIP_LLADDR_TYPE_MAC;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_MAC_802_3;
return IP_TRUE;
case IP_ARPHRD_LOOPBACK:
*ll_type = IPMIP_LLADDR_TYPE_LOOPBACK;
*ll_subtype = 0;
return IP_TRUE;
case IP_ARPHRD_TUNNEL:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_IPIP;
return IP_TRUE;
case IP_ARPHRD_SIT:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_GRE;
return IP_TRUE;
case IP_ARPHRD_TUNNEL6:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_IP6IP6;
return IP_TRUE;
case IP_ARPHRD_IPGRE:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_GRE;
return IP_TRUE;
case IP_ARPHRD_IPGRE6:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_GRE6;
return IP_TRUE;
case IP_ARPHRD_TUNNEL6OVER4:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_6OVER4;
return IP_TRUE;
case IP_ARPHRD_TUNNEL6TO4:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_6TO4;
return IP_TRUE;
case IP_ARPHRD_PPP:
*ll_type = IPMIP_LLADDR_TYPE_PPP;
*ll_subtype = 0;
return IP_TRUE;
case IP_ARPHRD_IEEE80211:
*ll_type = IPMIP_LLADDR_TYPE_MAC;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_MAC_802_11;
return IP_TRUE;
default:
return IP_FALSE;
}
}
IP_GLOBAL Ip_bool
ipmip_lladdr_ift_to_lltype(Ip_u16 type,
Ip_u8 *ll_type,
Ip_u8 *ll_subtype)
{
switch (type)
{
case IP_IFT_ETHER:
*ll_type = IPMIP_LLADDR_TYPE_MAC;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_MAC_802_3;
return IP_TRUE;
case IP_IFT_L2VLAN:
*ll_type = IPMIP_LLADDR_TYPE_MAC;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_MAC_802_1Q;
return IP_TRUE;
case IP_IFT_LOOP:
*ll_type = IPMIP_LLADDR_TYPE_LOOPBACK;
*ll_subtype = 0;
return IP_TRUE;
case IP_IFT_TUNNEL:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_IPIP;
return IP_TRUE;
case IP_IFT_SIT:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_GRE;
return IP_TRUE;
case IP_IFT_TUNNEL6:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_IP6IP6;
return IP_TRUE;
case IP_IFT_IPGRE:
*ll_type = IPMIP_LLADDR_TYPE_TUNNEL;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_TUNNEL_GRE;
return IP_TRUE;
case IP_IFT_PPPOE:
case IP_IFT_PPP:
*ll_type = IPMIP_LLADDR_TYPE_PPP;
*ll_subtype = 0;
return IP_TRUE;
case IP_IFT_IEEE80211:
*ll_type = IPMIP_LLADDR_TYPE_MAC;
*ll_subtype = IPMIP_LLADDR_SUBTYPE_MAC_802_11;
return IP_TRUE;
default:
return IP_FALSE;
}
}
/*
*===========================================================================
* ipmip_lladdr_dl_to_lladdr
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ipmip_lladdr_t *
ipmip_lladdr_dl_to_lladdr(struct Ip_sockaddr_dl *dl,
Ip_u32 ifindex)
{
IPMIP_UNUSED_PARAMETER(ifindex);
if (dl != IP_NULL)
{
Ip_u8 ll_type, ll_subtype;
if (ipmip_lladdr_ift_to_lltype(dl->sdl_type, &ll_type, &ll_subtype))
{
return ipmip_lladdr_build(IP_NULL,
ll_type,
ll_subtype,
(Ip_u8 *)IP_SOCKADDR_DL_LLADDR(dl),
dl->sdl_alen);
}
else
{
return ipmip_lladdr_build(IP_NULL,
0,
0,
(Ip_u8 *)IP_SOCKADDR_DL_LLADDR(dl),
dl->sdl_alen);
}
}
return IP_NULL;
}
IP_GLOBAL Ipmip_lladdr_t *
ipmip_lladdr_ll_to_lladdr(struct Ip_sockaddr_ll *ll)
{
if (ll != IP_NULL)
{
Ip_u8 ll_type, ll_subtype;
if (ipmip_lladdr_ift_to_lltype(ll->sll_hatype, &ll_type, &ll_subtype))
return ipmip_lladdr_build(IP_NULL,
ll_type,
ll_subtype,
&ll->sll_addr[0],
ll->sll_halen);
}
return IP_NULL;
}
/*
*===========================================================================
* ipmip_lladdr_dl_to_lladdr
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ipmip_lladdr_t *
ipmip_lladdr_sanitize(Ipmip_lladdr_t *iflla,
Ipmip_lladdr_t *lla)
{
/* If major match; set subtype */
if (iflla->type == lla->type)
{
switch (lla->type)
{
case IPMIP_LLADDR_TYPE_EUID64:
case IPMIP_LLADDR_TYPE_MEID:
case IPMIP_LLADDR_TYPE_ESN:
case IPMIP_LLADDR_TYPE_IMEI:
case IPMIP_LLADDR_TYPE_INET:
case IPMIP_LLADDR_TYPE_INET6:
case IPMIP_LLADDR_TYPE_3GPP:
case IPMIP_LLADDR_TYPE_3GPP2:
case IPMIP_LLADDR_TYPE_BSSID:
case IPMIP_LLADDR_TYPE_PPP:
case IPMIP_LLADDR_TYPE_LOOPBACK:
break;
case IPMIP_LLADDR_TYPE_TUNNEL:
case IPMIP_LLADDR_TYPE_MAC:
default:
lla->subtype = iflla->subtype;
break;
}
}
return lla;
}
/*
*===========================================================================
* ipmip_lladdr_parse
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ipmip_lladdr_t *
ipmip_lladdr_parse(Ipmip_proc_t *proc,
Ip_u8 type_hint,
Ip_u8 subtype_hint,
const char *llstr)
{
Ip_u8 ll_type = IPMIP_LLADDR_TYPE_MAC;
Ip_u8 ll_subtype = 0;
Ip_u8 ll_len = 0;
Ip_u8 *dptr;
dptr = (Ip_u8 *)proc->ntop.ntop_pbuf;
if (ipcom_strncmp(llstr, "0x", 2) == 0)
{
const char *ptr;
Ip_u8 i;
ll_len = ipcom_strlen(llstr + 2) / 2;
ptr = llstr + 2;
for (i = 0; i < ll_len; i++)
{
unsigned char value;
char buf[3];
/* Copy the first two bytes */
ipcom_strncpy(buf, ptr, sizeof(buf));
/* Add null terminator for the upcoming parse */
buf[2] = '\0';
/* Parse them */
value = (unsigned char)ipcom_strtoul(buf, IP_NULL, 16);
/**/
dptr[i] = value;
/* Read next two */
ptr += 2;
}
if (type_hint == 0)
{
if (ll_len == 8)
ll_type = IPMIP_LLADDR_TYPE_EUID64;
else if (ll_len != 6)
return IP_NULL;
}
else
{
ll_type = type_hint;
ll_subtype = subtype_hint;
}
}
else
{
Ip_size_t off = 0;
Ipmip_lladdr_parse_t *pdef = ipmip_lladdr_find_parse_def(llstr, type_hint, subtype_hint, &off);
#ifdef IPMIP_USE_INET6
struct Ip_sockaddr_in6 sa6;
#endif
struct Ip_sockaddr_dl dl;
#ifdef IPMIP_USE_INET
struct Ip_sockaddr_in sa;
#endif
if (pdef != IP_NULL)
{
if (pdef->format == IPMIP_LLADDR_FORMAT_HEX)
{
if (ipcom_getsockaddrbyaddr(IP_AF_LINK, llstr + off, (struct Ip_sockaddr *)&dl) != 0)
return IP_NULL;
ipcom_memcpy(dptr, IP_SOCKADDR_DL_LLADDR(&dl), dl.sdl_alen);
ll_len = dl.sdl_alen;
}
else if (pdef->format == IPMIP_LLADDR_FORMAT_INET)
{
#ifdef IPMIP_USE_INET
if (ipcom_getsockaddrbyaddr(IP_AF_INET, llstr + off, (struct Ip_sockaddr *)&sa) != 0)
return IP_NULL;
ipcom_memcpy(dptr, &sa.sin_addr, sizeof(sa.sin_addr));
ll_len = sizeof(sa.sin_addr);
#else
return IP_NULL;
#endif
}
else if (pdef->format == IPMIP_LLADDR_FORMAT_INET6)
{
#ifdef IPMIP_USE_INET6
if (ipcom_getsockaddrbyaddr(IP_AF_INET6, llstr + off, (struct Ip_sockaddr *)&sa6) != 0)
return IP_NULL;
ipcom_memcpy(dptr, &sa6.sin6_addr, sizeof(struct Ip_in6_addr));
ll_len = sizeof(struct Ip_in6_addr);
#else
return IP_NULL;
#endif
}
else if (pdef->format == IPMIP_LLADDR_FORMAT_U32)
{
Ip_u32 v = (Ip_u32)ipcom_strtoul(llstr + off, IP_NULL, 0);
ipcom_memcpy(dptr, &v, sizeof(v));
ll_len = sizeof(v);
}
else if (pdef->format == IPMIP_LLADDR_FORMAT_DEC_DIGIT || pdef->format == IPMIP_LLADDR_FORMAT_HEX_DIGIT)
{
unsigned i;
char buf[2];
Ip_u8 base = pdef->format == IPMIP_LLADDR_FORMAT_DEC_DIGIT? 10 : 16;
ll_len = 0;
buf[1] = '\0';
for (i = off; llstr[i] != '\0'; i++)
{
buf[0] = llstr[i];
dptr[ll_len++] = (unsigned char)ipcom_strtoul(buf, IP_NULL, base);
}
}
ll_type = pdef->type;
ll_subtype = pdef->subtype;
}
else
{
if (ipcom_getsockaddrbyaddr(IP_AF_LINK, llstr, (struct Ip_sockaddr *)&dl) == 0)
{
if (dl.sdl_alen == 8)
ll_type = IPMIP_LLADDR_TYPE_EUID64;
ipcom_memcpy(dptr, IP_SOCKADDR_DL_LLADDR(&dl), dl.sdl_alen);
ll_len = dl.sdl_alen;
}
#ifdef IPMIP_USE_INET
else if (ipcom_getsockaddrbyaddr(IP_AF_INET, llstr, (struct Ip_sockaddr *)&sa) == 0)
{
ipcom_memcpy(dptr, &sa.sin_addr, sizeof(sa.sin_addr));
ll_len = sizeof(sa.sin_addr);
ll_type = IPMIP_LLADDR_TYPE_INET;
}
#endif
#ifdef IPMIP_USE_INET6
else if (ipcom_getsockaddrbyaddr(IP_AF_INET6, llstr, (struct Ip_sockaddr *)&sa6) == 0)
{
ipcom_memcpy(dptr, &sa6.sin6_addr, sizeof(struct Ip_in6_addr));
ll_len = sizeof(struct Ip_in6_addr);
ll_type = IPMIP_LLADDR_TYPE_INET6;
}
#endif
else
{
/* No success */
return IP_NULL;
}
}
}
/**/
return ipmip_lladdr_build(IP_NULL, ll_type, ll_subtype, dptr, ll_len);
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,367 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_log.c,v $ $Revision: 1.5 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_log.c,v $
* $Author: jhorteli $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmip_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_drv_eth_filter.h>
#include <ipcom_err.h>
#include <ipcom_hash.h>
#include <ipcom_inet.h>
#include <ipcom_ipd.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_netif.h>
#include <ipcom_sysvar.h>
#include <ipmip.h>
#include <private/ipmip_context.h>
#include <private/ipmip_ntop.h>
#include <private/ipmip_cli.h>
#include <private/ipmip_util.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC void
ipmip_log_event_delete_locked(Ipmip_context_t *ctx)
{
Ipmip_log_event_t *ev = IPCOM_LIST_LAST(&ctx->log.events);
if (ev)
{
ipcom_list_remove(&ev->next);
if (ev->event)
ipcom_free(ev->event);
ipcom_free(ev);
}
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmip_log_event_add
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_log_event_add(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
const char *format,
...)
{
va_list ap;
va_start(ap, format);
ipmip_log_event_vadd(ctx, proc, format, ap);
va_end(ap);
}
/*
*===========================================================================
* ipmip_log_event_vadd
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_log_event_vadd(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
const char *format,
va_list ap)
{
if (ctx->log.events_max > 0)
{
Ip_u32 loglevel = IPCOM_LOG_PRI(proc->args.arg32);
if (loglevel <= ctx->log.loglevel)
{
Ipmip_log_event_t *ev = ipcom_calloc(1, sizeof(*ev));
if (ev)
{
ev->event = ipmip_util_vstrdup(format, ap);
if (ev->event == IP_NULL)
{
ipcom_free(ev);
return;
}
ev->when = ipmip_util_time();
ev->level = loglevel;
ipcom_mutex_lock(ctx->log.events_lock);
ipcom_list_insert_first(&ctx->log.events, &ev->next);
if (ctx->log.events.size > ctx->log.events_max)
ipmip_log_event_delete_locked(ctx);
ipcom_syslog(proc->args.arg32, "%s#%d: %s", ctx->name, ctx->vr, ev->event);
ipcom_mutex_unlock(ctx->log.events_lock);
}
}
}
}
/*
*===========================================================================
* ipmip_log_event_delete
*===========================================================================
* Description: Delete an error from the system
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_log_event_delete(Ipmip_context_t *ctx,
Ipmip_proc_t *proc)
{
IPMIP_UNUSED_PARAMETER(proc);
ipcom_mutex_lock(ctx->log.events_lock);
ipmip_log_event_delete_locked(ctx);
ipcom_mutex_unlock(ctx->log.events_lock);
}
/*
*===========================================================================
* ipmip_log_event_flush
*===========================================================================
* Description: Flush all events from the system
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_log_event_flush(Ipmip_context_t *ctx,
Ipmip_proc_t *proc)
{
IPMIP_UNUSED_PARAMETER(proc);
ipcom_mutex_lock(ctx->log.events_lock);
while (ctx->log.events.size > 0)
ipmip_log_event_delete_locked(ctx);
ipcom_mutex_unlock(ctx->log.events_lock);
}
/*
*===========================================================================
* ipmip_log_attr_request_events
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_size_t
ipmip_log_attr_request_events(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
struct Ipmip_cli_message *request)
{
struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&request->request);
Ip_size_t rhdr;
Ipmip_log_event_t *ev;
IPMIP_UNUSED_PARAMETER(proc);
rhdr = ipmip_attr_hdr_ack(&request->message, hdr);
ipcom_mutex_lock(ctx->log.events_lock);
/**/
for (ev = IPCOM_LIST_LAST(&ctx->log.events); ev != IP_NULL; ev = IPCOM_LIST_PREV(&ev->next))
{
Ip_size_t rta = ipmip_attr_begin(&request->message, IPMIP_CLI_ITEM_EVENT);
ipmip_attr_put_time_t(&request->message, IPMIP_CLI_ITEM_EVENT_TIME, ev->when);
ipmip_attr_put_u32(&request->message, IPMIP_CLI_ITEM_EVENT_LEVEL, ev->level);
ipmip_attr_put_str(&request->message, IPMIP_CLI_ITEM_EVENT_MESSAGE, ev->event);
ipmip_attr_end(&request->message, rta);
}
ipcom_mutex_unlock(ctx->log.events_lock);
return rhdr;
}
/*
*===========================================================================
* ipmip_log_attr_request_history
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_size_t
ipmip_log_attr_request_history(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
struct Ipmip_cli_message *request)
{
struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&request->request);
Ip_size_t rhdr;
IPMIP_UNUSED_PARAMETER(proc);
rhdr = ipmip_attr_hdr_ack(&request->message, hdr);
ipmip_attr_put_u32(&request->message, IPMIP_CLI_ITEM_SIZE, ctx->log.events_max);
return rhdr;
}
/*
*===========================================================================
* ipmip_log_attr_request_loglevel
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_size_t
ipmip_log_attr_request_loglevel(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
struct Ipmip_cli_message *request)
{
struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&request->request);
Ip_size_t rhdr;
IPMIP_UNUSED_PARAMETER(proc);
rhdr = ipmip_attr_hdr_ack(&request->message, hdr);
ipmip_attr_put_u32(&request->message, IPMIP_CLI_ITEM_SIZE, ctx->log.loglevel);
return rhdr;
}
/*
*===========================================================================
* ipmip_log_event_backlog
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_log_event_backlog(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_u32 backlog)
{
IPMIP_UNUSED_PARAMETER(proc);
ipcom_mutex_lock(ctx->log.events_lock);
while (ctx->log.events.size > backlog)
ipmip_log_event_delete_locked(ctx);
ctx->log.events_max = backlog;
ipcom_mutex_unlock(ctx->log.events_lock);
}
/*
*===========================================================================
* ipmip_log_event_backlog
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_log_loglevel(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ip_u32 loglevel)
{
IPMIP_UNUSED_PARAMETER(proc);
ctx->log.loglevel = loglevel;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,397 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_netlink_kern.c,v $ $Revision: 1.7.10.1 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_netlink_kern.c,v $
* $Author: jsheng $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#ifndef IPCOM_KERNEL
#define IPCOM_KERNEL
#endif
#include "ipnet_config.h"
#if defined(IPNET)
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_clib.h>
#include <ipcom_sysvar.h>
#include <ipcom_inet.h>
#include <ipcom_syslog.h>
#include <ipcom_hash.h>
#include "ipnet_h.h"
#include "ipnet.h"
#ifdef IPTCP
#include "iptcp.h"
#endif
#include <private/ipmip_netlink_kern.h>
#ifdef IPMIP6
#include <private/ipmip6_netlink_kern.h>
#endif
#ifdef IPMIP4
#include <private/ipmip4_netlink_kern.h>
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMIP_PKT_HAS_INFO(pkt) (pkt->next_extra_data != 0)
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipmip_netlink_kern
{
Ipcom_hash *handles[IPCOM_VR_MAX];
} Ipmip_netlink_kern_t;
/**/
IP_STATIC Ipmip_netlink_kern_t *ipmip_netlink_kern = IP_NULL;
IP_STATIC unsigned
ipmip_netlink_kern_handle_obj_hash(Ipmip_netlink_kern_handle_t *hdr)
{
return ipcom_hash_update(hdr, sizeof(*hdr), 0);
}
IP_STATIC Ip_bool
ipmip_netlink_kern_handle_cmp_hash(Ipmip_netlink_kern_handle_t *obj1,
Ipmip_netlink_kern_handle_t *obj2)
{
/**/
return obj1->mip_facility == obj2->mip_facility && obj1->mip_ident == obj2->mip_ident;
}
IP_STATIC Ip_bool
ipmip_netlink_kern_rt_flow_cmp(struct Ipnet_route_entry_struct *rtentry,
struct Ipnet_dst_cache_struct *dst)
{
struct Ipnet_route_func_info *rtinfo = rtentry->rt_func_info;
Ipmip_netlink_route_flow_info_t *rtflow = (Ipmip_netlink_route_flow_info_t *)(rtinfo + 1);
if (IP_BIT_ISSET(rtflow->type, IPMIP_NETLINK_KERN_INGRESS_IFINDEX))
{
if (dst->flow_spec.ingress_ifindex == 0)
{
IPCOM_LOG0(DEBUG2, "FLOW compare missed on INGRESS");
return IP_FALSE;
}
else if (rtflow->ifindex != 0 && rtflow->ifindex != dst->flow_spec.ingress_ifindex)
{
IPCOM_LOG0(DEBUG2, "FLOW compare missed on INGRESS IFINDEX");
return IP_FALSE;
}
}
if (IP_BIT_ISSET(rtflow->type, IPMIP_NETLINK_KERN_EGRESS_IFINDEX))
{
if (dst->flow_spec.ingress_ifindex != 0)
{
IPCOM_LOG0(DEBUG2, "FLOW compare missed on EGRESS");
return IP_FALSE;
}
else if (rtflow->ifindex != 0 && rtflow->ifindex != dst->flow_spec.egress_ifindex)
{
IPCOM_LOG0(DEBUG2, "FLOW compare missed on EGRESS IFINDEX");
return IP_FALSE;
}
}
if ((rtflow->flow.key.u64[0] != (dst->flow_spec.mip.key.u64[0] & rtflow->flow.mask.u64[0])) ||
(rtflow->flow.key.u64[1] != (dst->flow_spec.mip.key.u64[1] & rtflow->flow.mask.u64[1])) ||
(rtflow->flow.key.u64[2] != (dst->flow_spec.mip.key.u64[2] & rtflow->flow.mask.u64[2])))
{
IPCOM_LOG0(DEBUG2, "FLOW compare missed on FLOW");
return IP_FALSE;
}
/* Clear the flow spec values from this dst cache that arent used, just to speed up the cmps a bit */
dst->flow_spec.mip.key.u64[0] = dst->flow_spec.mip.key.u64[0] & rtflow->flow.mask.u64[0];
dst->flow_spec.mip.key.u64[1] = dst->flow_spec.mip.key.u64[1] & rtflow->flow.mask.u64[1];
dst->flow_spec.mip.key.u64[2] = dst->flow_spec.mip.key.u64[2] & rtflow->flow.mask.u64[2];
/* Store the mask */
ipcom_memcpy(&dst->flow_spec.mip.mask, &rtflow->flow.mask, sizeof(rtflow->flow.mask));
/* Setup the MIP DST cache init routine based on the Route's callbacks */
if (rtflow->flow_handle != IP_NULL)
{
dst->mip.flow_handle = rtflow->flow_handle;
dst->mip.flow_aux = ipcom_malloc(rtinfo->rt_info_size);
if(IP_NULL == dst->mip.flow_aux)
return IP_FALSE;
ipcom_memcpy(dst->mip.flow_aux, rtinfo, rtinfo->rt_info_size);
}
/**/
return IP_TRUE;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_bool
ipmip_netlink_kern_rt_flow_set(struct Ipnet_route_func_info *rtinfo,
Ipmip_netlink_kern_compare_t *srccmp,
Ipnet_dst_cache_mip_handle flow_handle)
{
Ipmip_netlink_route_flow_info_t *rtflow = (Ipmip_netlink_route_flow_info_t *)(rtinfo + 1);
/* Set compare function */
rtinfo->rt_flow_cmp = (Ipnet_route_flow_spec_cmp_t)ipmip_netlink_kern_rt_flow_cmp;
/* Set init function */
rtflow->flow_handle = flow_handle;
if (IP_LIKELY(srccmp != IP_NULL))
{
if (IP_BIT_ISSET(srccmp->srcmac_type, IPMIP_NETLINK_KERN_PROTO))
{
rtflow->flow.mask.u8[1] = 0xFF;
rtflow->flow.key.u8[1] = srccmp->srcmac.proto;
}
/* Create the flow MASK */
if (IP_BIT_ISSET(srccmp->srcmac_type, IPMIP_NETLINK_KERN_TUNNEL|IPMIP_NETLINK_KERN_SRCMAC))
{
/* First field is ENCAP size */
rtflow->flow.mask.u8[0] = 0xFF;
rtflow->flow.key.u8[0] = srccmp->srcmac.srcmac_len;
ipcom_memcpy(&rtflow->flow.key.u32[1], &srccmp->srcmac.hdr.opaque[0], srccmp->srcmac.srcmac_len);
ipcom_memset(&rtflow->flow.mask.u32[1], 0xFF, srccmp->srcmac.srcmac_len);
}
if (IP_BIT_ISSET(srccmp->srcmac_type, IPMIP_NETLINK_KERN_INGRESS_IFINDEX|IPMIP_NETLINK_KERN_EGRESS_IFINDEX))
rtflow->ifindex = srccmp->srcmac.ifindex;
if (IP_BIT_ISSET(srccmp->srcmac_type, IPMIP_NETLINK_KERN_GREKEY))
{
rtflow->flow.key.u32[5] = srccmp->srcmac.gre_key;
rtflow->flow.mask.u32[5] = 0xFFFFFFFF;
}
rtflow->type = srccmp->srcmac_type;
}
return IP_TRUE;
}
IP_GLOBAL Ipmip_netlink_kern_handle_t *
ipmip_netlink_kern_handle_get(Ip_u32 vr, Ipmip_netlink_kern_handle_t *handle)
{
/**/
return (Ipmip_netlink_kern_handle_t *)ipcom_hash_get(ipmip_netlink_kern->handles[vr], handle);
}
IP_GLOBAL void
ipmip_netlink_kern_handle_add(Ip_u32 vr, Ipmip_netlink_kern_handle_t *handle)
{
ipcom_hash_add(ipmip_netlink_kern->handles[vr], handle);
}
IP_GLOBAL Ipmip_netlink_kern_handle_t *
ipmip_netlink_kern_handle_del(Ip_u32 vr, Ipmip_netlink_kern_handle_t *handle)
{
Ipmip_netlink_kern_handle_t *rhandle = ipmip_netlink_kern_handle_get(vr, handle);
if (rhandle)
ipcom_hash_remove(ipmip_netlink_kern->handles[vr], rhandle);
/**/
return rhandle;
}
IP_GLOBAL void
ipmip_netlink_kern_handle_free(Ip_u32 vr, Ipmip_netlink_kern_handle_t *handle)
{
handle = ipmip_netlink_kern_handle_del(vr, handle);
if (handle)
ipcom_free(handle);
}
IP_GLOBAL void
ipmip_netlink_kern_if_include(Ipnet_netif *netif)
{
IP_BIT_CLR(netif->flags2, IPNET_IFF2_NO_GLOBAL_SRC);
}
IP_GLOBAL void
ipmip_netlink_kern_if_exclude(Ipnet_netif *netif)
{
IP_BIT_SET(netif->flags2, IPNET_IFF2_NO_GLOBAL_SRC);
}
IP_GLOBAL void
ipmip_netlink_kern_hoa_activate(Ipnet_netif *netif,
struct Ip_rtattr *rta)
{
Ipnet_socket *sock = IP_NULL;
Ipnet_socket *next_sock;
#ifdef IPCOM_USE_INET6
if (IP_RTA_PAYLOAD(rta) == sizeof(struct Ip_in6_addr))
{
Ipnet_ip6_addr_entry *entry = ipnet_ip6_get_addr_entry(IP_RTA_DATA(rta), netif->vr_index, netif);
/* Loop through all addresses */
if (entry != IP_NULL && IP_BIT_ISTRUE(entry->flags, IPNET_IP6_ADDR_FLAG_HOMEADDRESS))
{
/* Kickstart list */
#ifdef IPTCP
sock = entry->socket_list;
#endif
}
}
#endif
#ifdef IPCOM_USE_INET
if (IP_RTA_PAYLOAD(rta) == sizeof(struct Ip_in_addr))
{
Ipnet_ip4_addr_entry *entry = ipnet_ip4_get_addr_entry(IP_GET_32ON8(IP_RTA_DATA(rta)), netif->vr_index, netif);
/* Loop through all addresses */
if (entry != IP_NULL && IP_BIT_ISTRUE(entry->flags, IPNET_IP4_ADDR_FLAG_HOMEADDRESS))
{
#ifdef IPTCP
sock = entry->socket_list;
#endif
IP_BIT_SET(entry->flags, IPNET_IP4_ADDR_FLAG_PREFERRED);
}
}
#endif
#ifdef IPTCP
while (sock != IP_NULL)
{
/* Locate next socket with the same address */
next_sock = sock->addr_next;
/* Do we have a notify CB */
if (sock->notify_cb != IP_NULL)
{
/* Kickstart it */
(*sock->notify_cb) (sock, IPTCP_SOCKET_EVENT_KICKSTART);
}
/* Do next socket */
sock = next_sock;
}
#endif
}
IP_GLOBAL void
ipmip_netlink_kern_hoa_deactivate(Ipnet_netif *netif,
struct Ip_rtattr *rta)
{
#ifdef IPCOM_USE_INET6
if (IP_RTA_PAYLOAD(rta) == sizeof(struct Ip_in6_addr))
{
Ipnet_ip6_addr_entry *entry = ipnet_ip6_get_addr_entry(IP_RTA_DATA(rta), netif->vr_index, netif);
/* Loop through all addresses */
if (entry != IP_NULL && IP_BIT_ISTRUE(entry->flags, IPNET_IP6_ADDR_FLAG_HOMEADDRESS))
{
/* Kickstart list */
}
}
#endif
#ifdef IPCOM_USE_INET
if (IP_RTA_PAYLOAD(rta) == sizeof(struct Ip_in_addr))
{
Ipnet_ip4_addr_entry *entry = ipnet_ip4_get_addr_entry(IP_GET_32ON8(IP_RTA_DATA(rta)), netif->vr_index, netif);
/* Loop through all addresses */
if (entry != IP_NULL && IP_BIT_ISTRUE(entry->flags, IPNET_IP4_ADDR_FLAG_HOMEADDRESS))
{
IP_BIT_CLR(entry->flags, IPNET_IP4_ADDR_FLAG_PREFERRED);
}
}
#endif
}
IP_GLOBAL void
ipmip_rtnetlink_init(void)
{
int i;
/* Create the handles */
ipmip_netlink_kern = ipcom_calloc(1, sizeof(*ipmip_netlink_kern));
for (i = 0; i < IPCOM_VR_MAX; i++)
{
ipmip_netlink_kern->handles[i] = ipcom_hash_new((Ipcom_hash_obj_func) ipmip_netlink_kern_handle_obj_hash,
(Ipcom_hash_key_func) ipmip_netlink_kern_handle_obj_hash,
(Ipcom_hash_cmp_func) ipmip_netlink_kern_handle_cmp_hash);
}
#ifdef IPMIP6
ipmip6_rtnetlink_init();
#endif
#ifdef IPMIP4
ipmip4_rtnetlink_init();
#endif
}
#else
int ipmip_netlink_kern_empty_file = 0;
#endif
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,444 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_ntop.c,v $ $Revision: 1.7 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_ntop.c,v $
* $Author: jhorteli $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include <ipmip_config.h>
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_drv_eth_filter.h>
#include <ipcom_err.h>
#include <ipcom_hash.h>
#include <ipcom_inet.h>
#include <ipcom_ipd.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_netif.h>
#include <ipcom_sysvar.h>
#include <ipmip.h>
#include <private/ipmip_ntop.h>
#include <private/ipmip_lladdr.h>
#include <private/ipmip_if.h>
#include <private/ipmip_context.h>
#include <private/ipmip_util.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmip_ntop
*===========================================================================
* Description: Converts a ip address to a human readable text
* representation. The text representation resides
* in a static buffer capable of holding up to four
* different results.
* Parameters: proc - The process context
* addr - The IP address to convert.
* Returns: A pointer to the static buffer holding the result.
*
*/
IP_GLOBAL const char *
ipmip_ntop(struct Ipmip_proc *proc,
Ip_u8 family,
const void *un,
struct Ipmip_if *ifp)
{
/* Current buffer */
char* buf = proc->ntop.ntop_buffer[proc->ntop.ntop_index];
proc->ntop.ntop_index = (Ip_u8) ((proc->ntop.ntop_index + 1) & IPMIP_ADDRESS_ADDRMASK);
ipcom_inet_ntop(family, un, buf, IPMIP_ADDRESS_ADDRSIZE);
/* Scope */
if (ifp)
{
ipcom_strncat(buf, "@", IPMIP_ADDRESS_ADDRSIZE);
ipcom_strncat(buf, ifp->ifname, IPMIP_ADDRESS_ADDRSIZE);
}
return buf;
}
/*
*===========================================================================
* ipmip_ntop_sa
*===========================================================================
* Description: Converts a ip address to a human readable text
* representation. The text representation resides
* in a static buffer capable of holding up to four
* different results.
* Parameters: proc - The process context
* addr - The IP address to convert.
* Returns: A pointer to the static buffer holding the result.
*
*/
IP_GLOBAL const char *
ipmip_ntop_sa(struct Ipmip_proc *proc,
union Ip_sockaddr_union *un)
{
switch (un->sa.sa_family)
{
#ifdef IPMIP_USE_INET
case IP_AF_INET:
return ipmip_ntop(proc, IP_AF_INET, &un->sin.sin_addr, IP_NULL);
#endif
#ifdef IPMIP_USE_INET6
case IP_AF_INET6:
return ipmip_ntop(proc, IP_AF_INET6, &un->sin6.sin6_addr, IP_NULL);
#endif
default:
return "<err family>";
}
}
#ifdef IPMIP_USE_INET
/*
*===========================================================================
* ipmip_ntop_inet
*===========================================================================
* Description: Converts a ip address to a human readable text
* representation. The text representation resides
* in a static buffer capable of holding up to four
* different results.
* Parameters: proc - The process context
* addr - The IP address to convert.
* Returns: A pointer to the static buffer holding the result.
*
*/
IP_GLOBAL const char *
ipmip_ntop_inet(struct Ipmip_proc *proc,
Ip_u32 addr)
{
return ipmip_ntop(proc, IP_AF_INET, &addr, IP_NULL);
}
#endif
/*******************************************************************************
*
* ipmip_ntop_lladdr_type - ipmip_ntop_lladdr_type
*
* Try to convert a LLA represented L2/SOL address to
* some form of human readable output
*
* Parameters:
* \is
* \i proc
* The process context
* \i type
* The MAC type
* \i mac
* The MAC
* \ie
*
* RETURNS: A pointer to a static buffer containing the LLA output.
*
* ERRNO:
*
*/
IP_GLOBAL const char *
ipmip_ntop_lladdr_type(struct Ipmip_proc *proc,
Ip_u8 type,
Ip_u8 subtype,
void *mac,
Ip_size_t mac_len)
{
Ipmip_lladdr_typedef_t *def;
int off;
if (type >= IPMIP_LLADDR_TYPE_MAX)
return "INVALID";
def = &ipmip_lladdr_type_defs[type];
off = ipcom_snprintf(proc->ntop.ntop_lla, sizeof(proc->ntop.ntop_lla), def->name);
if (def->max_subtypes > 0 && subtype <= def->max_subtypes)
off += ipcom_snprintf(&proc->ntop.ntop_lla[off], sizeof(proc->ntop.ntop_lla) - off, "[%s]", def->subtypes[subtype]);
switch (def->format)
{
case IPMIP_LLADDR_FORMAT_HEX:
{
unsigned i;
for (i = 0; i < mac_len; i++)
off += ipcom_snprintf(&proc->ntop.ntop_lla[off], sizeof(proc->ntop.ntop_lla) - off, ":%02x", ((Ip_u8 *)mac)[i]);
}
break;
case IPMIP_LLADDR_FORMAT_DEC_DIGIT:
{
unsigned i;
for (i = 0; i < mac_len; i++)
off += ipcom_snprintf(&proc->ntop.ntop_lla[off], sizeof(proc->ntop.ntop_lla) - off, "%s%u", i == 0? ":" : "", ((Ip_u8 *)mac)[i]);
}
break;
case IPMIP_LLADDR_FORMAT_HEX_DIGIT:
{
unsigned i;
for (i = 0; i < mac_len; i++)
off += ipcom_snprintf(&proc->ntop.ntop_lla[off], sizeof(proc->ntop.ntop_lla) - off, "%s%x", i == 0? ":" : "", ((Ip_u8 *)mac)[i]);
}
break;
#ifdef IPMIP_USE_INET
case IPMIP_LLADDR_FORMAT_INET:
off += ipcom_snprintf(&proc->ntop.ntop_lla[off], sizeof(proc->ntop.ntop_lla) - off, ":%s", ipmip_ntop_inet(proc, IP_GET_32ON8(mac)));
break;
#endif
#ifdef IPMIP_USE_INET6
case IPMIP_LLADDR_FORMAT_INET6:
off += ipcom_snprintf(&proc->ntop.ntop_lla[off], sizeof(proc->ntop.ntop_lla) - off, ":%s", ipmip_ntop_inet6(proc, (void *)mac, IP_NULL));
break;
#endif
case IPMIP_LLADDR_FORMAT_U32:
off += ipcom_snprintf(&proc->ntop.ntop_lla[off], sizeof(proc->ntop.ntop_lla) - off, ":%08x", IP_GET_32ON8(mac));
break;
}
return proc->ntop.ntop_lla;
}
/*
*===========================================================================
* ipmip_ntop_lladdr
*===========================================================================
* Description: Try to convert a LLA represented L2/SOL address to
* some form of human readable output
* Parameters: proc - The process context
* lla - The LLA extension
* Returns: A pointer to a static buffer containing the LLA output.
*
*/
IP_GLOBAL const char *
ipmip_ntop_lladdr(Ipmip_proc_t *proc,
Ipmip_lladdr_t *lla)
{
/* If it's NULL */
if (lla == IP_NULL)
return "n/a";
/**/
return ipmip_ntop_lladdr_type(proc, lla->type, lla->subtype, IPMIP_LLADDR_DATA(lla), IPMIP_LLADDR_LEN_LLA(lla));
}
/*
*===========================================================================
* ipmip_ntop_hex
*===========================================================================
* Description: Try to convert a binary value to readable hexadecimal output
* Parameters: proc - Process context
* hxarr - The array
* sz - Size of the array
* Returns: A pointer to a static buffer containing the hex output.
*
*/
IP_GLOBAL const char *
ipmip_ntop_hex(Ipmip_proc_t *proc,
Ip_u8 *hxarr,
Ip_size_t sz)
{
char *ptr = proc->ntop.ntop_lla;
Ip_size_t i;
*ptr = '\0';
for (i = 0; i < sz; i++)
{
ipcom_snprintf(ptr, sizeof(proc->ntop.ntop_lla) - (ptr - proc->ntop.ntop_lla), "%02x", hxarr[i]);
ptr += ipcom_strlen(ptr);
}
return proc->ntop.ntop_lla;
}
/*
*===========================================================================
* ipmip_ntop_time
*===========================================================================
* Description: Try to convert a time value to human readable
* Parameters: proc - The process context
* tval - The time
* Returns: A pointer to a static buffer containing the time output
*
*/
IP_GLOBAL const char *
ipmip_ntop_time(struct Ipmip_proc *proc,
Ip_time_t tval)
{
/* Current buffer */
char* buf = proc->ntop.ntop_buffer[proc->ntop.ntop_index];
proc->ntop.ntop_index = (Ip_u8) ((proc->ntop.ntop_index + 1) & IPMIP_ADDRESS_ADDRMASK);
return ipcom_ctime_r((Ip_time_t *)&tval, buf);
}
/*
*===========================================================================
* ipmip_ntop_tm
*===========================================================================
* Description: Try to convert a time value to human readable
* Parameters: proc - The process context
* tval - The time
* Returns: A pointer to a static buffer containing the time output
*
*/
IP_GLOBAL const char *
ipmip_ntop_tm(struct Ipmip_proc *proc,
Ip_time_t tval)
{
struct Ip_tm tm;
ipcom_localtime_r((Ip_time_t *)&tval, &tm);
ipcom_strftime(proc->ntop.ntop_name, sizeof(proc->ntop.ntop_name), "%b %d %H:%M:%S", &tm);
return proc->ntop.ntop_name;
}
/*
*===========================================================================
* ipmip_ntop_tv
*===========================================================================
* Description: Try to convert a time value to human readable
* Parameters: proc - The process context
* tval - The time
* Returns: A pointer to a static buffer containing the time output
*
*/
IP_GLOBAL const char *
ipmip_ntop_tv(struct Ipmip_proc *proc,
struct Ip_timeval *tv)
{
return ipmip_ntop_tm(proc, tv->tv_sec);
}
/*
*===========================================================================
* ipmip_ntop_strn
*===========================================================================
* Description: Create a zero terminated string representation.
* Parameters: proc - The process context
* str - The string
* strlen - The length of the string
* Returns: A pointer to a static buffer containing the time output
*
*/
IP_GLOBAL const char *
ipmip_ntop_strn(struct Ipmip_proc *proc,
const char *str,
Ip_size_t str_len)
{
Ip_size_t sz = IP_MIN(str_len, (sizeof(proc->ntop.ntop_pbuf) - 1));
/* Current buffer */
ipcom_strncpy(proc->ntop.ntop_pbuf, str, sz);
proc->ntop.ntop_pbuf[sz] = '\0';
return proc->ntop.ntop_pbuf;
}
#ifdef IPMIP_USE_INET6
/*
*===========================================================================
* ipmip_ntop_inet6
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL const char *
ipmip_ntop_inet6(struct Ipmip_proc *proc,
const struct Ip_in6_addr *addr,
struct Ipmip_if *ifp)
{
return ipmip_ntop(proc, IP_AF_INET6, addr, ifp);
}
#endif
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,466 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_pktbuf.c,v $ $Revision: 1.8.10.1 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_pktbuf.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 <ipmip_config.h>
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_hash.h>
#include <ipcom_inet.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipcom_clib2.h>
#include <ipmip.h>
#include <private/ipmip_if.h>
#include <private/ipmip_pktbuf.h>
#include <private/ipmip_context.h>
#include <private/ipmip_util.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmip_pktbuf_alloc
*===========================================================================
* Description: Allocate a pktbuf
* Parameters: context - The pkt context
* proc - The process context
* pkt_size - The initial size of the packet buffer
* Returns: A newly allocated and initialized pktbuf on success
*
*/
IP_GLOBAL Ipmip_pktbuf_t *
ipmip_pktbuf_alloc(struct Ipmip_context *ctx,
struct Ipmip_proc *proc,
Ip_size_t pkt_size)
{
Ipmip_pktbuf_t *pbuf;
IPMIP_UNUSED_PARAMETER(proc);
if (ctx->pktbuf->bufalloc != IP_NULL)
{
pbuf = (*ctx->pktbuf->bufalloc) (ctx, proc, ctx->pktaux? ctx->pktaux->pktdata_payload : 0);
}
else
{
pbuf = ipcom_calloc(1, sizeof(*pbuf) + (ctx->pktaux? ctx->pktaux->pktdata_payload : 0));
}
if (pbuf)
{
pbuf->pktarr = (void *)pbuf->pktend;
pbuf->pktend += ctx->pktaux? ctx->pktaux->pktdata_header : 0;
ipmip_buffer_init(&pbuf->packet);
IPMIP_TIMER_INIT(&pbuf->timeout);
IPMIP_TIMER_INIT(&pbuf->pending);
/* Initial reserves */
if (ipmip_buffer_reserve(&pbuf->packet, pkt_size) == IP_FALSE)
{
ipmip_pktbuf_free(ctx, proc, pbuf);
return IP_NULL;
}
/**/
ipcom_atomic_set(&pbuf->refcnt, 1);
}
return pbuf;
}
/*
*===========================================================================
* ipmip_pktbuf_free
*===========================================================================
* Description: Free a previously allocated pktbuf
* Parameters: pbuf - The pktbuf
* Returns:
*
*/
IP_GLOBAL void
ipmip_pktbuf_free(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_pktbuf_t *pbuf)
{
unsigned i;
/* Clear any stage timeouts */
ipmip_timer_cancel(ctx, proc, &pbuf->timeout);
ipmip_timer_cancel(ctx, proc, &pbuf->pending);
/* Release all resources */
ipmip_buffer_release(&pbuf->packet);
if (pbuf->srcinfo.dl)
ipcom_free(pbuf->srcinfo.dl);
if (pbuf->srcinfo.ll)
ipcom_free(pbuf->srcinfo.ll);
if (pbuf->srcinfo.lladdr)
ipcom_free(pbuf->srcinfo.lladdr);
if (pbuf->srcinfo.dst)
ipcom_free(pbuf->srcinfo.dst);
if (pbuf->srcinfo.src)
ipcom_free(pbuf->srcinfo.src);
if (pbuf->message)
ipcom_free(pbuf->message);
/* Free any allocated memory */
if (pbuf->pktoff != 0 && ctx->pktaux != IP_NULL)
{
for (i = 0; i < ctx->pktaux->pktdata_num; i++)
{
if (pbuf->pktarr[i] != IP_NULL && ctx->pktaux->pktdata[i]->pktbuf_data_free != IP_NULL)
(*ctx->pktaux->pktdata[i]->pktbuf_data_free) (ctx, proc, pbuf, pbuf->pktarr[i]);
}
}
if (ctx->pktbuf->buffree != IP_NULL)
{
(*ctx->pktbuf->buffree) (ctx, proc, pbuf);
}
else
{
ipcom_free(pbuf);
}
}
/*
*===========================================================================
* ipmip_pktbuf_release
*===========================================================================
* Description: Release the pktbuf, and if possible, free it.
* Parameters: ctx - The context
* proc - The process
* pbuf - The buffer
* Returns:
*
*/
IP_GLOBAL void
ipmip_pktbuf_release(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_pktbuf_t *pbuf)
{
if (pbuf && ipcom_atomic_sub_and_return(&pbuf->refcnt, 1) == 0)
{
/**/
if (pbuf->released != IP_NULL)
(*pbuf->released) (ctx, proc, pbuf);
ipmip_pktbuf_free(ctx, proc, pbuf);
}
}
/*
*===========================================================================
* ipmip_pktbuf_reference
*===========================================================================
* Description: Reference the packet buffer
* Parameters: ctx - The context
* proc - The process
* pbuf - The buffer
* Returns:
*
*/
IP_GLOBAL void
ipmip_pktbuf_reference(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_pktbuf_t *pbuf)
{
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
/* Deref */
if (pbuf)
ipcom_atomic_inc(&pbuf->refcnt);
}
/*
*===========================================================================
* ipmip_pktbuf_context_create
*===========================================================================
* Description: Allocate the packet context
* Parameters: ctx - The context
* proc - Process context
* bufalloc - Pkt buffer allocation function; If NULL a
* straight Ipmip_pktbuf_t will be allocated.
* buffree - Overriding free function for packet buffers;
* if none, ordinary free will be used.
* Returns: IP_TRUE on success.
*
*/
IP_GLOBAL Ip_bool
ipmip_pktbuf_context_create(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_pkt_buf_alloc_t bufalloc,
Ipmip_pkt_buf_free_t buffree)
{
/* Init */
IPMIP_UNUSED_PARAMETER(proc);
if (ctx == IP_NULL)
return IP_FALSE;
ctx->pktbuf = ipcom_calloc(1, sizeof(struct Ipmip_pktbuf_context));
if(IP_NULL == ctx->pktbuf)
return IP_FALSE;
/* Store pktbuf allocation functions */
ctx->pktbuf->bufalloc = bufalloc;
ctx->pktbuf->buffree = buffree;
return IP_TRUE;
}
/*
*===========================================================================
* ipmip_pktbuf_context_destroy
*===========================================================================
* Description: Destroy the buffer context
* Parameters: ctx - The context
* proc - The process context
* Returns:
*
*/
IP_GLOBAL void
ipmip_pktbuf_context_destroy(Ipmip_context_t *ctx,
Ipmip_proc_t *proc)
{
IPMIP_UNUSED_PARAMETER(proc);
if (ctx->pktbuf != IP_NULL)
{
ipcom_free(ctx->pktbuf);
ctx->pktbuf = IP_NULL;
}
}
/*
*===========================================================================
* ipmip_pktbuf_error
*===========================================================================
* Description: Set an error
* Parameters: pbuf - The pktbuf
* error_code - Error code
* error_msg - Static string containing error message. MUST be
* specified if error_code is specified.
* Returns:
*
*/
IP_GLOBAL void
ipmip_pktbuf_error(Ipmip_pktbuf_t *pbuf,
Ip_u8 error_code,
const char *format,
...)
{
va_list ap;
char *buf = IP_NULL;
if (format != IP_NULL)
{
va_start(ap, format);
buf = ipmip_util_vstrdup(format, ap);
va_end(ap);
}
/* Set the error */
pbuf->error_code = error_code;
if (pbuf->message != IP_NULL)
ipcom_free(pbuf->message);
pbuf->message = buf;
}
#ifdef IPMIP_USE_INET
/*
*===========================================================================
* ipmip_pktbuf_srcinfo_dst_inet
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_pktbuf_srcinfo_dst_inet(Ipmip_pktbuf_t *pbuf,
struct Ip_in_pktinfo *pktinfo)
{
pbuf->srcinfo.dst = ipcom_calloc(1, sizeof(*pbuf->srcinfo.dst));
if(IP_NULL == pbuf->srcinfo.dst)
return;
pbuf->srcinfo.dst->dst.sin.sin_family = IP_AF_INET;
pbuf->srcinfo.dst->dst.sin.sin_addr.s_addr = pktinfo->ipi_addr.s_addr;
IPCOM_SA_LEN_SET(&pbuf->srcinfo.dst->dst.sin, sizeof(struct Ip_sockaddr_in));
pbuf->srcinfo.dst->ifindex = pktinfo->ipi_ifindex;
}
#endif
#ifdef IPMIP_USE_INET6
/*
*===========================================================================
* ipmip_pktbuf_srcinfo_dst_inet6
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_pktbuf_srcinfo_dst_inet6(Ipmip_pktbuf_t *pbuf,
struct Ip_in6_pktinfo *pktinfo)
{
pbuf->srcinfo.dst = ipcom_calloc(1, sizeof(*pbuf->srcinfo.dst));
if(IP_NULL == pbuf->srcinfo.dst)
return;
pbuf->srcinfo.dst->dst.sin.sin_family = IP_AF_INET6;
ipcom_memcpy(&pbuf->srcinfo.dst->dst.sin6.sin6_addr, &pktinfo->ipi6_addr, sizeof(pktinfo->ipi6_addr));
IPCOM_SA_LEN_SET(&pbuf->srcinfo.dst->dst.sin6, sizeof(struct Ip_sockaddr_in6));
pbuf->srcinfo.dst->ifindex = pktinfo->ipi6_ifindex;
}
#endif
IP_GLOBAL Ip_u32
ipmip_pktbuf_pktaux_add(Ipmip_pktbuf_pktaux_t *aux,
Ipmip_pktbuf_payload_t *pktaux)
{
if (aux->pktdata_num == IPMIP_PKTBUF_PKTAUX_SIZE)
return 0;
/* Update parameters */
aux->pktdata[aux->pktdata_num] = pktaux;
/* Align it */
pktaux->pktbuf_data_size = (pktaux->pktbuf_data_size + (sizeof(Ip_ptrdiff_t) - 1)) & ~(sizeof(Ip_ptrdiff_t) - 1);
pktaux->pktbuf_data_index = ++aux->pktdata_num;
/* Update counters */
aux->pktdata_payload += pktaux->pktbuf_data_size + sizeof(void *);
aux->pktdata_header += sizeof(void *);
return pktaux->pktbuf_data_index;
}
IP_GLOBAL void *
ipmip_pktbuf_pktaux_data_get(Ipmip_context_t *ctx,
Ipmip_pktbuf_t *pbuf,
Ip_u32 payload_index,
Ip_bool payload_create)
{
if (ctx->pktaux == IP_NULL)
return IP_NULL;
/* Sanity */
if (payload_index-- == 0)
return IP_NULL;
/* Sanity */
if (payload_index >= ctx->pktaux->pktdata_num)
return IP_NULL;
if (payload_create)
{
if (pbuf->pktarr[payload_index] == IP_NULL)
{
pbuf->pktarr[payload_index] = (void *)&pbuf->pktend[pbuf->pktoff];
pbuf->pktoff += ctx->pktaux->pktdata[payload_index]->pktbuf_data_size;
}
}
return pbuf->pktarr[payload_index];
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,501 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_rtab.c,v $ $Revision: 1.4 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_rtab.c,v $
* $Author: jhorteli $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include <ipmip_config.h>
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_hash.h>
#include <ipcom_inet.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipcom_clib2.h>
#include <ipmip.h>
#include <private/ipmip_if.h>
#include <private/ipmip_pktbuf.h>
#include <private/ipmip_context.h>
#include <private/ipmip_util.h>
#include <private/ipmip_rtab.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG2
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC void
ipmip_route_replace_node(Ipmip_route_t *new_rt,
Ipmip_route_t *old_rt)
{
Ipcom_route_entry *internal = old_rt->hdr.parent;
/* Insert the new route in the radix tree */
new_rt->hdr.parent = internal;
new_rt->widen = IP_NULL;
if (old_rt->narrow && old_rt->narrow != new_rt)
{
new_rt->narrow = old_rt->narrow;
new_rt->narrow->widen = new_rt;
}
old_rt->widen = IP_NULL;
old_rt->narrow = IP_NULL;
if (internal->on == &old_rt->hdr)
internal->on = &new_rt->hdr;
else
{
ip_assert(internal->off == &old_rt->hdr);
internal->off = &new_rt->hdr;
}
/* Remove all references to the old mask */
while (internal)
{
if (old_rt->hdr.mask == internal->mask)
internal->mask = IP_NULL;
internal = internal->parent;
}
/* Initialize internal nodes with the new mask */
ipcom_route_init_subtree_mask(&new_rt->hdr);
}
struct Ipmip_route_walk_info
{
struct Ipmip_context *ctx;
struct Ipmip_proc *proc;
Ipmip_rtab_t *rtab;
void *opaque;
Ipmip_route_walk_t walk_func;
};
IP_STATIC Ip_bool
ipmip_route_walk_internal(Ipmip_route_t *rt,
struct Ipmip_route_walk_info *info)
{
Ip_bool ret = (*info->walk_func) (info->ctx, info->proc, info->rtab, rt, info->opaque);
Ipmip_route_t *nrt, *nnrt;
for (nrt = rt->narrow; nrt != IP_NULL; nrt = nnrt)
{
nnrt = nrt->narrow;
if ((*info->walk_func) (info->ctx, info->proc, info->rtab, nrt, info->opaque))
ipmip_route_delete(info->rtab, nrt);
}
if (ret)
ipmip_route_delete(info->rtab, rt);
return IP_FALSE;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL int
ipmip_route_lookup(Ipmip_rtab_t *rtab,
void *key,
Ipmip_route_t **rtp)
{
Ip_bool pm;
Ipmip_route_t *rt = (Ipmip_route_t *)ipcom_route_lookup(rtab, key, &pm);
if (rt)
{
Ipmip_route_t *nrt;
for (nrt = rt->narrow; nrt != IP_NULL; nrt = nrt->narrow)
{
if (ipcom_route_key_cmp(rtab->bit_count, key, nrt->hdr.key, nrt->hdr.mask) == IPCOM_ROUTE_KEY_CMP_NO_MATCH)
break;
rt = nrt;
}
*rtp = rt;
/* Return value */
return pm? IPMIP_ROUTE_LOOKUP_MATCH : IPMIP_ROUTE_LOOKUP_MASK;
}
return IPMIP_ROUTE_LOOKUP_MISS;
}
IP_GLOBAL Ipmip_route_t *
ipmip_route_lookup_exact(Ipmip_rtab_t *rtab,
void *key,
Ip_u8 bits)
{
Ip_bool pm;
Ipmip_route_t *rt = (Ipmip_route_t *)ipcom_route_lookup(rtab, key, &pm);
if (rt && pm)
{
for (; rt != IP_NULL; rt = rt->narrow)
{
if (rt->bits == bits)
return rt;
}
}
return IP_NULL;
}
IP_GLOBAL Ipmip_route_t *
ipmip_route_lookup_any(Ipmip_rtab_t *rtab,
void *key)
{
Ipmip_route_t *rt;
if (ipmip_route_lookup(rtab, key, &rt) != IPMIP_ROUTE_LOOKUP_MISS)
return rt;
return IP_NULL;
}
IP_GLOBAL int
ipmip_route_add(Ipmip_rtab_t *rtab,
Ipmip_route_t *rt)
{
Ipmip_route_t *prt;
int ret;
rt->bits = rt->hdr.mask? ipcom_mask_to_prefixlen(rt->hdr.mask, rtab->bit_count) : rtab->bit_count;
if (rt->bits == rtab->bit_count)
rt->hdr.mask = IP_NULL;
/* Sort it in */
ret = ipmip_route_lookup(rtab, rt->hdr.key, &prt);
if (ret == IPMIP_ROUTE_LOOKUP_MATCH)
{
if (rt->bits == prt->bits)
return -IP_ERRNO_EEXIST;
rt->hdr.parent = prt->hdr.parent;
rt->hdr.on = prt->hdr.on;
rt->hdr.off = prt->hdr.off;
/* Sort it in */
if (rt->bits < prt->bits)
{
if (prt->widen == IP_NULL)
{
Ipmip_route_t *ort = rt;
/* First in tree */
ipmip_route_replace_node(rt, prt);
/* Insert it */
rt = prt;
prt = ort;
}
else
{
rt->narrow = prt;
rt->widen = prt->widen;
rt->widen->narrow = rt;
prt->widen = rt;
return IPCOM_SUCCESS;
}
}
for (;; prt = prt->narrow)
{
if (rt->bits < prt->bits)
{
rt->narrow = prt;
rt->widen = prt->widen;
rt->widen->narrow = rt;
prt->widen = rt;
break;
}
else if (prt->narrow == IP_NULL)
{
rt->widen = prt;
prt->narrow = rt;
break;
}
}
return IPCOM_SUCCESS;
}
/* Insert it */
return ipcom_route_add(rtab, &rt->hdr);
}
IP_GLOBAL void
ipmip_route_notify(Ipmip_rtab_t *rtab,
Ipmip_route_t *rt,
int code)
{
(void) rtab;
if (code == IPCOM_ROUTE_CODE_REMOVE || code == IPCOM_ROUTE_CODE_DUPLICATE)
{
Ipmip_route_t *nrt = rt->narrow;
while (nrt != IP_NULL)
{
Ipmip_route_t *nnrt = nrt->narrow;
/* Ugh - Delete all narrow routes */
nrt->widen = IP_NULL;
nrt->narrow = IP_NULL;
/* Invoke */
rtab->notify_func(rtab, &nrt->hdr, IPCOM_ROUTE_CODE_REMOVE);
/* Next */
nrt = nnrt;
}
/* Free data */
ipcom_free(rt);
}
}
IP_GLOBAL void
ipmip_route_delete(Ipmip_rtab_t *rtab,
Ipmip_route_t *rt)
{
if (rt->widen != IP_NULL)
{
rt->widen->narrow = rt->narrow;
if (rt->narrow)
rt->narrow->widen = rt->widen;
rt->widen = IP_NULL;
rt->narrow = IP_NULL;
rtab->notify_func(rtab, &rt->hdr, IPCOM_ROUTE_CODE_REMOVE);
}
else if (rt->narrow != IP_NULL)
{
ipmip_route_replace_node(rt->narrow, rt);
rt->narrow = IP_NULL;
rtab->notify_func(rtab, &rt->hdr, IPCOM_ROUTE_CODE_REMOVE);
}
else
{
ipcom_route_remove(rtab, &rt->hdr);
}
}
IP_GLOBAL void
ipmip_route_walk(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip_rtab_t *rtab,
void *opaque,
Ipmip_route_walk_t walk_func)
{
struct Ipmip_route_walk_info cb;
cb.ctx = ctx;
cb.proc = proc;
cb.rtab = rtab;
cb.opaque = opaque;
cb.walk_func = walk_func;
ipcom_route_walk_tree(rtab,
(Ipcom_route_walk_cb)ipmip_route_walk_internal,
&cb);
}
IP_GLOBAL Ipmip_route_t *
ipmip_route_lookup_parent(Ipmip_rtab_t *rtab,
Ipmip_route_t *rt)
{
Ipcom_route_entry *current;
Ipcom_route_entry *bt;
Ipmip_route_t *wrt;
/* Go wider */
for (wrt = rt->widen; wrt != IP_NULL; wrt = wrt->widen)
{
if (wrt->bits != rt->bits)
return wrt;
rt = wrt;
}
/* Start backtracking */
current = &rt->hdr;
for (;;)
{
do
{
/* Go up to the next node with a netmask. */
current = current->parent;
if (current == IP_NULL)
return IP_NULL;
} while (current->mask == IP_NULL);
bt = current;
if (bt->mask != rt->hdr.mask)
{
/* Check */
while (bt->off != IP_NULL)
bt = bt->off;
if (IP_BIT_ISSET(bt->flags, IPCOM_ROUTE_FLAG_INIT))
return IP_NULL;
if (ipcom_route_key_cmp(rtab->bit_count, rt->hdr.key, bt->key, bt->mask) != IPCOM_ROUTE_KEY_CMP_NO_MATCH)
{
Ipmip_route_t *nrt = (Ipmip_route_t *)bt;
for (; nrt->narrow != IP_NULL; nrt = nrt->narrow)
{
if (ipcom_route_key_cmp(rtab->bit_count, rt->hdr.key, nrt->narrow->hdr.key, nrt->narrow->hdr.mask) == IPCOM_ROUTE_KEY_CMP_NO_MATCH)
break;
}
return nrt;
}
}
}
}
IP_GLOBAL Ipmip_route_t *
ipmip_route_lookup_child(Ipmip_rtab_t *rtab,
Ipmip_route_t *rt)
{
Ipcom_route_entry *current;
Ipmip_route_t *nrt;
/* Check if there's a narrow */
for (nrt = rt->narrow; nrt != IP_NULL; nrt = nrt->narrow)
{
if (nrt->bits > rt->bits)
return nrt;
}
/* Must go out to the widest */
while (rt->widen)
rt = rt->widen;
current = &rt->hdr;
for (;;)
{
if (current->parent->off == current)
{
current = current->parent;
if (current->bit >= rt->bits && current->on != IP_NULL)
{
current = current->on;
for (;;)
{
if (current->off == IP_NULL)
{
/**/
if (IP_BIT_ISSET(current->flags, IPCOM_ROUTE_FLAG_INIT))
return IP_NULL;
/* Have something here */
if (ipcom_route_key_cmp(rtab->bit_count, rt->hdr.key, current->key, rt->hdr.mask) != IPCOM_ROUTE_KEY_CMP_NO_MATCH)
return (Ipmip_route_t *)current;
/* Wasn't covered */
return IP_NULL;
}
current = current->off;
}
}
return IP_NULL;
}
current = current->parent;
}
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff