original files of m241
This commit is contained in:
@@ -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
|
||||
****************************************************************************
|
||||
*/
|
||||
@@ -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 = ≪
|
||||
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
Reference in New Issue
Block a user