original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
@@ -0,0 +1,233 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcps6.c,v $ $Revision: 1.43.42.1 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6.c,v $
* $Author: ulf $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_sock.h>
#include <ipcom_sock6.h>
#ifdef IPNET
#include <ipnet_netif.h>
#endif
#include "ipdhcps6_h.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
Ip_u16 ipdhcps6_client_port = 546;
Ip_u16 ipdhcps6_server_port = 547;
char *ipdhcps6_log_id = "dhcps6";
struct Ip_in6_addr ipdhcps6_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 ipdhcps6_all_dhcp_servers =
{
{ { 0xFF, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03 } }
};
struct Ipdhcps6_data *ipdhcps6 = IP_NULL;
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_get_u16
*===========================================================================
* Description: Returns the value in host byte order.
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_u16
ipdhcps6_get_u16(const Ip_u16 *u16)
{
Ip_u16 val;
ipcom_memcpy(&val, u16, sizeof(val));
return ip_ntohs(val);
}
/*
*===========================================================================
* ipdhcps6_set_u16
*===========================================================================
* Description: Sets the value in network byte order
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipdhcps6_set_u16(Ip_u16 *u16, Ip_u16 val)
{
val = ip_htons(val);
ipcom_memcpy(u16, &val, sizeof(val));
}
/*
*===========================================================================
* ipdhcps6_get_u16
*===========================================================================
* Description: Returns the value in host byte order.
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_u32
ipdhcps6_get_u32(const Ip_u32 *u32)
{
Ip_u32 val;
ipcom_memcpy(&val, u32, sizeof(val));
return ip_ntohl(val);
}
/*
*===========================================================================
* ipdhcps6_set_u16
*===========================================================================
* Description: Sets the value in network byte order
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipdhcps6_set_u32(Ip_u32 *u32, Ip_u32 val)
{
val = ip_htonl(val);
ipcom_memcpy(u32, &val, sizeof(val));
}
/*
*===========================================================================
* ipdhcps6_delete_hash_db_cb
*===========================================================================
* Description: Deletes each element in a hash based database.
* Parameters: obj - The hash element to delete.
* Returns:
*
*/
IP_GLOBAL void
ipdhcps6_delete_hash_db_cb(void *obj, void *not_used)
{
(void) not_used;
ipcom_free(obj);
}
/*
*===========================================================================
* ipdhcps6_get_netifbyindex
*===========================================================================
* Description: Get Ipcom_netif.
* Parameters: ifindex - interface index.
* Returns:
*
*/
IP_GLOBAL Ipcom_netif *
ipdhcps6_get_netifbyindex(Ip_u32 ifindex)
{
#ifdef IPNET
Ipnet_netif *netif = IP_NULL;
netif = ipnet_if_indextonetif(IPCOM_VR_ANY, ifindex);
return (netif ? &netif->ipcom : IP_NULL);
#else
return IP_NULL; /* current NO support IPLITE */
#endif
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,893 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Copyright (C) 2007 Wind River Systems
*
******************************************************************************
*/
/*
modification history
--------------------
01a,17jul07,ps initial checkin of dhcpv6 authentication key database module
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_list.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipnet.h>
#include <ipnet_routesock.h>
#include "ipdhcps6.h"
#include "ipdhcps6_h.h"
#include "ipdhcps6_host.h"
#include "ipdhcps6_prefix.h"
#include "ipdhcps6_subnet.h"
#include "ipdhcps6_duid.h"
#include "ipdhcps6_cvthex.h"
#include "ipdhcps6_authhash.h"
#define IPDHCPS6_DUID_LL_ACTUALSIZE 10
#define IPDHCPS6_DUID_LLT_ACTUALSIZE 14
#define IPDHCPS6_DUID_EN_ACTUALSIZE 14
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_authdata_obj_hash
*===========================================================================
* Description: Returns a hash value based on an authkey value.
* Parameters: dbentry - The option to return a hash value for.
* Returns:
*
*/
IP_STATIC unsigned
ipdhcps6_authdb_obj_hash (Ipdhcps6_authkey_dbentry *dbentry)
{
#ifdef DEBUG_DHCPV6_AUTH
int i;
unsigned char *cptr;
printf ("ipdhcps6_authdb_obj_hash called: ");
cptr = (unsigned char *) &(dbentry->duid.data.ll.link_addr);
for (i = 0 ; i < 6 ; i++)
{ printf ("%2x ", cptr [i]);
}
printf ("\n");
#endif
return ipcom_hash_update(&(dbentry->duid.data), dbentry->duid.len, 0);
}
/*
*===========================================================================
* ipdhcps6_authdb_key_hash
*===========================================================================
* Description: Returns a hash value for a DUID key.
* Parameters: key - Pointer to the Ipdhcps6_authkey_duid structure
* Returns:
*
*/
IP_STATIC unsigned
ipdhcps6_authdb_key_hash(Ipdhcps6_duid *key)
{
#ifdef DEBUG_DHCPV6_AUTH
int i;
unsigned char *cptr;
printf ("ipdhcps6_authdb_key_hash called: ");
cptr = (unsigned char *) &(key->data.ll.link_addr);
for (i = 0 ; i < 6 ; i++)
{ printf ("%2x ", cptr [i]);
}
printf ("\n");
#endif
return ipcom_hash_update(&(key->data), key->len, 0);
}
/*
*===========================================================================
* ipdhcps6_authdb_hash_cmp
*===========================================================================
* Description: Compares a hash object and a hash key for equality.
* Parameters: dbentry - An authkey_dbentry structure.
* key - A pointer to the search key.
* Returns: IP_TRUE if the search key matches the prefix entry.
*
*/
IP_STATIC Ip_bool
ipdhcps6_authdb_hash_cmp(Ipdhcps6_authkey_dbentry *dbentry, Ipdhcps6_duid *key)
{
#ifdef DEBUG_DHCPV6_AUTH
printf ("ipdhcps6_authdb_hash_cmp called\n");
#endif
if (dbentry->duid.len != key->len)
return IP_FALSE;
return ipcom_memcmp(&(dbentry->duid.data), &(key->data),
key->len) == 0;
}
/*************/
/*
*===========================================================================
* ipdhcps6_authtrans_obj_hash
*===========================================================================
* Description: Returns a hash value based on an authkey value.
* Parameters: dbentry - The option to return a hash value for.
* Returns:
*
*/
IP_STATIC unsigned
ipdhcps6_authtrans_obj_hash (Ipdhcps6_authtrans_dbentry *dbentry)
{
#ifdef DEBUG_DHCPV6_AUTH
int i;
unsigned char *cptr;
printf ("ipdhcps6_authtrans_obj_hash called: ");
cptr = (unsigned char *) &(dbentry->duid.data);
switch (dbentry->duid.data.generic.content)
{ case IPDHCPS6_DUID_LL:
printf ("LL content\n");
break;
case IPDHCPS6_DUID_LLT:
printf ("LLT content\n");
break;
case IPDHCPS6_DUID_EN:
printf ("EN content\n");
break;
default:
printf ("default case content\n");
}
for (i = 0 ; i < dbentry->duid.len ; i++)
{ printf ("%2x ", cptr [i]);
}
printf ("\n");
#endif
return ipcom_hash_update(&(dbentry->duid.data), dbentry->duid.len, 0);
}
/*
*===========================================================================
* ipdhcps6_authtrans_key_hash
*===========================================================================
* Description: Returns a hash value for a DUID key.
* Parameters: key - Pointer to the Ipdhcps6_authkey_duid structure
* Returns:
*
*/
IP_STATIC unsigned
ipdhcps6_authtrans_key_hash(Ipdhcps6_duid *key)
{
#ifdef DEBUG_DHCPV6_AUTH
int i;
unsigned char *cptr;
printf ("ipdhcps6_authtrans_key_hash called: ");
cptr = (unsigned char *) &(key->data);
switch (key->data.generic.content)
{ case IPDHCPS6_DUID_LL:
printf ("LL content\n");
break;
case IPDHCPS6_DUID_LLT:
printf ("LLT content\n");
break;
case IPDHCPS6_DUID_EN:
printf ("EN content\n");
break;
default:
printf ("default case content\n");
}
for (i = 0 ; i < key->len ; i++)
{ printf ("%2x ", cptr [i]);
}
printf ("\n");
#endif
return ipcom_hash_update(&(key->data), key->len, 0);
}
/*
*===========================================================================
* ipdhcps6_authtrans_hash_cmp
*===========================================================================
* Description: Compares a hash object and a hash key for equality.
* Parameters: prefix - A prefix structure.
* key - A pointer to the search key.
* Returns: IP_TRUE if the search key matches the prefix entry.
*
*/
IP_STATIC Ip_bool
ipdhcps6_authtrans_hash_cmp(Ipdhcps6_authtrans_dbentry *dbentry, Ipdhcps6_duid *key)
{
#ifdef DEBUG_DHCPV6_AUTH
printf ("ipdhcps6_authtrans_hash_cmp called\n");
#endif
if (dbentry->duid.len != key->len)
return IP_FALSE;
return ipcom_memcmp(&(dbentry->duid.data), &(key->data),
key->len) == 0;
}
/*****************/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_STATIC Ipcom_hash *client_authkey_db;
IP_STATIC Ipcom_hash *client_transaction_db;
IP_GLOBAL Ipcom_hash *
ipdhcps6_authdb_hash_create(void)
{
return ipcom_hash_new ((Ipcom_hash_obj_func) ipdhcps6_authdb_obj_hash,
(Ipcom_hash_key_func) ipdhcps6_authdb_key_hash,
(Ipcom_hash_cmp_func) ipdhcps6_authdb_hash_cmp);
}
IP_GLOBAL Ipcom_hash *
ipdhcps6_authtrans_hash_create(void)
{
return ipcom_hash_new ((Ipcom_hash_obj_func) ipdhcps6_authtrans_obj_hash,
(Ipcom_hash_key_func) ipdhcps6_authtrans_key_hash,
(Ipcom_hash_cmp_func) ipdhcps6_authtrans_hash_cmp);
}
IP_GLOBAL Ipdhcps6_duid *ipdhcps6_authdb_create_ll_duid (int len, Ip_u16 hwtype, Ip_u8 *link_addr)
{
Ipdhcps6_duid *retval = (Ipdhcps6_duid *)
ipcom_malloc (sizeof (struct Ipdhcps6_duid_struct));
(void)len;
if (IP_NULL == retval)
return IP_NULL;
retval->len = IPDHCPS6_DUID_LL_ACTUALSIZE;
retval->data.ll.content = IPDHCPS6_DUID_LL;
retval->data.ll.hardware_type = hwtype;
ipcom_memcpy (retval->data.ll.link_addr, link_addr, 6);
return retval;
}
IP_GLOBAL Ip_err ipdhcps6_add_client_authkey (Ipdhcps6_duid *client_duid,
Ip_u8 *key, int keylen)
{
Ip_u16 duid_content;
Ipdhcps6_authkey_dbentry *new_authdb_entry = (Ipdhcps6_authkey_dbentry *)
ipcom_malloc (sizeof (struct Ipdhcps6_authkey_dbentry));
if (IP_NULL == new_authdb_entry)
return IPCOM_ERR_FAILED;
new_authdb_entry->secret.key = (Ip_u8 *) ipcom_malloc ((Ip_size_t)keylen);
if (IP_NULL == new_authdb_entry->secret.key)
{ ipcom_free (new_authdb_entry);
IPCOM_LOG0 (DEBUG, "ipdhcps6_add_client_authkey: no memory!\n");
return IPCOM_ERR_NO_MEMORY;
}
/*
* copy in key
*/
ipcom_memcpy (new_authdb_entry->secret.key, key, (Ip_size_t)keylen);
new_authdb_entry->secret.len = keylen;
/*
* copy in duid data
*/
new_authdb_entry->duid.len = client_duid->len;
duid_content = client_duid->data.ll.content;
switch (duid_content)
{
case IPDHCPS6_DUID_LL:
new_authdb_entry->duid.data.ll.hardware_type = client_duid->data.ll.hardware_type;
new_authdb_entry->duid.data.ll.content = IPDHCPS6_DUID_LL;
ipcom_memcpy (new_authdb_entry->duid.data.ll.link_addr,
client_duid->data.ll.link_addr, 6);
break;
case IPDHCPS6_DUID_EN: /* not yet implemented */
case IPDHCPS6_DUID_LLT: /* not yet implemented */
default:
/* Coverity defect fix for RESOURCE_LEAK */
ipcom_free( new_authdb_entry->secret.key);
ipcom_free (new_authdb_entry);
return IPCOM_ERR_FAILED;
}
if (IPCOM_SUCCESS != ipcom_hash_add (client_authkey_db, new_authdb_entry))
{
return IPCOM_ERR_FAILED;
}
return IPCOM_SUCCESS;
}
IP_GLOBAL Ip_err ipdhcps6_client_wants_auth (union Ipdhcps6_duid_data *client, int len)
{
Ip_u16 client_duid_content;
Ipdhcps6_authtrans_dbentry *client_dbentry = IP_NULL;
client_dbentry = (Ipdhcps6_authtrans_dbentry *)
ipcom_malloc (sizeof (struct Ipdhcps6_authtrans_dbentry));
if (IP_NULL == client_dbentry)
return IPCOM_ERR_NO_MEMORY;
client_duid_content = ip_ntohs (client->generic.content);
switch (client_duid_content)
{ case IPDHCPS6_DUID_LLT:
client_dbentry->duid.len = IPDHCPS6_DUID_LLT_ACTUALSIZE;
client_dbentry->duid.data.llt.content = IPDHCPS6_DUID_LLT;
client_dbentry->duid.data.llt.hardware_type = client->llt.hardware_type;
client_dbentry->duid.data.llt.time = client->llt.time;
ipcom_memcpy (client_dbentry->duid.data.llt.link_addr,
client->llt.link_addr, 6);
break;
case IPDHCPS6_DUID_EN:
/*
* FIXME
* using the duid union structure we have, we know we will have
* enough space to copy in the first 8 bytes of the enterprise
* ID. This may or may not be enough to be unique; we'll need
* to revisit this later. Look at "len" to see if we were given
* less than 8 bytes for the ID; if so, only copy the bytes
* given.
*/
client_dbentry->duid.len =
(Ip_u16)(len < IPDHCPS6_DUID_EN_ACTUALSIZE ?
len : IPDHCPS6_DUID_EN_ACTUALSIZE);
client_dbentry->duid.data.en.content = IPDHCPS6_DUID_EN;
client_dbentry->duid.data.en.enterprise_number_1 =
client->en.enterprise_number_1;
client_dbentry->duid.data.en.enterprise_number_2 =
client->en.enterprise_number_2;
ipcom_memcpy (client_dbentry->duid.data.en.id,
client->en.id, (Ip_size_t)(8 - (IPDHCPS6_DUID_EN_ACTUALSIZE - len)));
break;
case IPDHCPS6_DUID_LL:
client_dbentry->duid.len = IPDHCPS6_DUID_LL_ACTUALSIZE;
client_dbentry->duid.data.ll.content = IPDHCPS6_DUID_LL;
client_dbentry->duid.data.ll.hardware_type = client->ll.hardware_type;
ipcom_memcpy (client_dbentry->duid.data.ll.link_addr,
client->ll.link_addr, 6);
break;
default:
break;
}
/*
* set replay counters
*/
client_dbentry->server_replay1 = 0xdeadbeef;
client_dbentry->server_replay2 = 0x0;
client_dbentry->client_replay1 = 0x0;
client_dbentry->client_replay2 = 0x0;
if (IPCOM_SUCCESS != ipcom_hash_add (client_transaction_db, client_dbentry))
return IPCOM_ERR_FAILED;
return IPCOM_SUCCESS;
}
IP_GLOBAL Ip_err ipdhcps6_client_no_auth (union Ipdhcps6_duid_data *client, int len)
{
Ip_u16 client_duid_content;
Ipdhcps6_duid client_dbkey;
Ipdhcps6_authkey_dbentry *client_dbobj = IP_NULL;
client_duid_content = ip_ntohs (client->generic.content);
switch (client_duid_content)
{ case IPDHCPS6_DUID_LLT:
client_dbkey.len = IPDHCPS6_DUID_LLT_ACTUALSIZE;
client_dbkey.data.llt.content = IPDHCPS6_DUID_LLT;
client_dbkey.data.llt.hardware_type = client->llt.hardware_type;
client_dbkey.data.llt.time = client->llt.time;
ipcom_memcpy (client_dbkey.data.llt.link_addr,
client->llt.link_addr, 6);
break;
case IPDHCPS6_DUID_EN:
/*
* FIXME
* using the duid union structure we have, we know we will have
* enough space to copy in the first 8 bytes of the enterprise
* ID. This may or may not be enough to be unique; we'll need
* to revisit this later. Look at "len" to see if we were given
* less than 8 bytes for the ID; if so, only copy the bytes
* given.
*/
client_dbkey.len =
(Ip_u16)(len < IPDHCPS6_DUID_EN_ACTUALSIZE ?
len : IPDHCPS6_DUID_EN_ACTUALSIZE);
client_dbkey.data.en.content = IPDHCPS6_DUID_EN;
client_dbkey.data.en.enterprise_number_1 =
client->en.enterprise_number_1;
client_dbkey.data.en.enterprise_number_2 =
client->en.enterprise_number_2;
ipcom_memcpy (client_dbkey.data.en.id,
client->en.id, (Ip_size_t)(8 - (IPDHCPS6_DUID_EN_ACTUALSIZE - len)));
break;
case IPDHCPS6_DUID_LL:
client_dbkey.len = IPDHCPS6_DUID_LL_ACTUALSIZE;
client_dbkey.data.ll.content = IPDHCPS6_DUID_LL;
client_dbkey.data.ll.hardware_type = client->ll.hardware_type;
ipcom_memcpy (client_dbkey.data.ll.link_addr,
client->ll.link_addr, 6);
break;
default:
return IPCOM_ERR_FAILED;
}
client_dbobj = ipcom_hash_get (client_transaction_db, &client_dbkey);
if (IP_NULL == client_dbobj)
{
return IPCOM_SUCCESS;
}
else
{
ipcom_hash_remove (client_transaction_db, client_dbobj);
return IPCOM_SUCCESS;
}
}
IP_GLOBAL Ipdhcps6_authtrans_dbentry *
ipdhcps6_client_requested_auth (union Ipdhcps6_duid_data *client, int len)
{
Ip_u16 client_duid_content;
Ipdhcps6_duid client_dbkey;
Ipdhcps6_authtrans_dbentry *client_dbobj = IP_NULL;
client_duid_content = ip_ntohs (client->generic.content);
switch (client_duid_content)
{ case IPDHCPS6_DUID_LLT:
client_dbkey.len = IPDHCPS6_DUID_LLT_ACTUALSIZE;
client_dbkey.data.llt.content = IPDHCPS6_DUID_LLT;
client_dbkey.data.llt.hardware_type = client->llt.hardware_type;
client_dbkey.data.llt.time = client->llt.time;
ipcom_memcpy (client_dbkey.data.llt.link_addr,
client->llt.link_addr, 6);
break;
case IPDHCPS6_DUID_EN:
/*
* FIXME
* using the duid union structure we have, we know we will have
* enough space to copy in the first 8 bytes of the enterprise
* ID. This may or may not be enough to be unique; we'll need
* to revisit this later. Look at "len" to see if we were given
* less than 8 bytes for the ID; if so, only copy the bytes
* given.
*/
client_dbkey.len =
(Ip_u16)(len < IPDHCPS6_DUID_EN_ACTUALSIZE ?
len : IPDHCPS6_DUID_EN_ACTUALSIZE);
client_dbkey.data.en.content = IPDHCPS6_DUID_EN;
client_dbkey.data.en.enterprise_number_1 =
client->en.enterprise_number_1;
client_dbkey.data.en.enterprise_number_2 =
client->en.enterprise_number_2;
ipcom_memcpy (client_dbkey.data.en.id,
client->en.id, (Ip_size_t)(8 - (IPDHCPS6_DUID_EN_ACTUALSIZE - len)));
break;
case IPDHCPS6_DUID_LL:
client_dbkey.len = IPDHCPS6_DUID_LL_ACTUALSIZE;
client_dbkey.data.ll.content = IPDHCPS6_DUID_LL;
client_dbkey.data.ll.hardware_type = client->ll.hardware_type;
ipcom_memcpy (client_dbkey.data.ll.link_addr,
client->ll.link_addr, 6);
break;
default:
/* invalid DUID type; ignore it and return failure */
return IP_NULL;
}
client_dbobj = ipcom_hash_get (client_transaction_db, &client_dbkey);
if (IP_NULL == client_dbobj)
return IP_NULL;
return client_dbobj;
}
#define MAX_IPDHCPV6_AUTH_KEY_SIZE 128
IP_STATIC int authKeyInitialized = 0;
IP_STATIC int authRealmInitialized = 0;
IP_STATIC Ip_u8 authKeyFromSysVars [256];
IP_STATIC Ip_size_t authKeyLenFromSysVars = 0;
IP_STATIC Ip_u8 authKey [128];
IP_STATIC Ip_size_t authKeyLen = 0;
IP_STATIC Ip_u8 authRealmFromSysVars [128];
IP_STATIC Ip_size_t authRealmLenFromSysVars = 0;
IP_STATIC Ip_err ipdhcps6_set_default_auth_key_from_sysvars (void)
{
authKeyLenFromSysVars = sizeof (authKeyFromSysVars);
(void)ipcom_sysvar_get("ipdhcps6.authkey", (char *) authKeyFromSysVars,
&authKeyLenFromSysVars);
/*
* check if the value we read is a valid hex key; convert to
* a key buffer.
*/
if (ipdhcps6_check_is_hex_string ((char *) authKeyFromSysVars))
{
/* we need at least 4 characters to proceed here; "0x--" or more */
if (authKeyLenFromSysVars >= 4)
{ char *kptr = (char *) authKeyFromSysVars;
kptr += 2; /* get past leading "0x" */
authKeyLen = (authKeyLenFromSysVars - 2) / 2;
if (! ipdhcps6_cvt_hex_to_membuf (kptr, authKey, (int)authKeyLen) )
{ authKeyLen = 0;
return IPCOM_ERR_FAILED;
}
}
}
else
{
authKeyLen = 0;
return IPCOM_ERR_FAILED;
}
authKeyInitialized = 1;
return IPCOM_SUCCESS;
}
IP_GLOBAL Ip_err ipdhcps6_set_default_auth_key (char *authkey)
{
Ip_size_t auth_key_len;
auth_key_len = strlen (authkey);
if (auth_key_len > ((MAX_IPDHCPV6_AUTH_KEY_SIZE + 1) * 2))
{ return IPCOM_ERR_FAILED; /* given key is too large */
}
/*
* check if the value we read is a valid hex key; convert to
* a key buffer.
*/
if (ipdhcps6_check_is_hex_string (authkey))
{
/* we need at least 4 characters to proceed here; "0x--" or more */
if (auth_key_len >= 4)
{ char *kptr = authkey;
kptr += 2; /* get past leading "0x" */
authKeyLen = (auth_key_len - 2) / 2;
if (! ipdhcps6_cvt_hex_to_membuf (kptr, authKey, (int)authKeyLen) )
{ authKeyLen = 0;
return IPCOM_ERR_FAILED;
}
}
}
else
{
authKeyLen = 0;
return IPCOM_ERR_FAILED;
}
authKeyInitialized = 1;
return IPCOM_SUCCESS;
}
IP_GLOBAL Ip_err ipdhcps6_get_default_auth_key (Ip_size_t *len, Ip_u8 **key)
{
if (authKeyInitialized)
{
*len = authKeyLen;
*key = authKey;
return IPCOM_SUCCESS;
}
else
{
if (IPCOM_SUCCESS == ipdhcps6_set_default_auth_key_from_sysvars ())
{
*len = authKeyLen;
*key = authKey;
return IPCOM_SUCCESS;
}
}
*key = IP_NULL;
*len = 0;
return IPCOM_ERR_FAILED;
}
IP_STATIC Ip_err ipdhcps6_set_auth_realm_from_sysvars ()
{
authRealmLenFromSysVars = sizeof (authRealmFromSysVars);
if (ipcom_sysvar_get("ipdhcps6.authrealm", (char *) authRealmFromSysVars,
&authRealmLenFromSysVars) == IP_NULL)
{
/* Don't set it if we dont got it */
authRealmLenFromSysVars = 0;
}
if (authRealmLenFromSysVars > 0)
{
authRealmInitialized = 1;
return IPCOM_SUCCESS;
}
return IPCOM_ERR_FAILED;
}
IP_GLOBAL Ip_err ipdhcps6_set_auth_realm (char *auth_realm)
{
Ip_size_t realm_len;
authRealmInitialized = 0;
realm_len = strlen (auth_realm);
if ((unsigned)realm_len > (sizeof (authRealmFromSysVars) - 1))
{ /* passed in realm is too large. */
return IPCOM_ERR_FAILED;
}
strncpy ((char *) authRealmFromSysVars, auth_realm, realm_len);
authRealmFromSysVars [realm_len] = '\0';
authRealmLenFromSysVars = realm_len;
authRealmInitialized = 1;
return IPCOM_SUCCESS;
}
IP_GLOBAL Ip_err ipdhcps6_get_auth_realm (Ip_size_t *len, Ip_u8 **realm)
{
if (authRealmInitialized)
{ *len = authRealmLenFromSysVars;
*realm = authRealmFromSysVars;
return IPCOM_SUCCESS;
}
else
{ if (IPCOM_SUCCESS == ipdhcps6_set_auth_realm_from_sysvars ())
{
*len = authRealmLenFromSysVars;
*realm = authRealmFromSysVars;
return IPCOM_SUCCESS;
}
}
*len = 0;
return IPCOM_ERR_FAILED;
}
IP_GLOBAL void ipdhcps6_authdb_init (void)
{
client_authkey_db = ipdhcps6_authdb_hash_create ();
client_transaction_db = ipdhcps6_authtrans_hash_create ();
}
IP_GLOBAL Ip_err ipdhcps6_find_key_for_client (union Ipdhcps6_duid_data *client,
int duid_len,
Ip_u8 **key, Ip_size_t *key_len)
{
Ip_u16 client_duid_content;
Ipdhcps6_duid client_dbkey;
Ipdhcps6_authkey_dbentry *client_dbobj = IP_NULL;
client_duid_content = ip_ntohs (client->generic.content);
switch (client_duid_content)
{ case IPDHCPS6_DUID_LLT:
client_dbkey.len = IPDHCPS6_DUID_LL_ACTUALSIZE;
client_dbkey.data.ll.content = IPDHCPS6_DUID_LL;
client_dbkey.data.ll.hardware_type = client->llt.hardware_type;
ipcom_memcpy (client_dbkey.data.ll.link_addr,
client->llt.link_addr, 6);
break;
case IPDHCPS6_DUID_EN:
/*
* FIXME
* using the duid union structure we have, we know we will have
* enough space to copy in the first 8 bytes of the enterprise
* ID. This may or may not be enough to be unique; we'll need
* to revisit this later. Look at "len" to see if we were given
* less than 8 bytes for the ID; if so, only copy the bytes
* given.
*/
client_dbkey.len =
(Ip_u16)(duid_len < IPDHCPS6_DUID_EN_ACTUALSIZE ?
duid_len : IPDHCPS6_DUID_EN_ACTUALSIZE);
client_dbkey.data.en.content = IPDHCPS6_DUID_EN;
client_dbkey.data.en.enterprise_number_1 =
client->en.enterprise_number_1;
client_dbkey.data.en.enterprise_number_2 =
client->en.enterprise_number_2;
ipcom_memcpy (client_dbkey.data.en.id,
client->en.id, (Ip_size_t)(8 - (IPDHCPS6_DUID_EN_ACTUALSIZE - duid_len)));
break;
case IPDHCPS6_DUID_LL:
client_dbkey.len = IPDHCPS6_DUID_LL_ACTUALSIZE;
client_dbkey.data.ll.content = IPDHCPS6_DUID_LL;
client_dbkey.data.ll.hardware_type = client->ll.hardware_type;
ipcom_memcpy (client_dbkey.data.ll.link_addr,
client->ll.link_addr, 6);
break;
default:
return IPCOM_ERR_FAILED;
}
client_dbobj = ipcom_hash_get (client_authkey_db, &client_dbkey);
if (IP_NULL == client_dbobj)
{
/* use default system auth key */
return IPCOM_ERR_FAILED;
}
else
{
/* use client specific key */
*key_len = (Ip_size_t)client_dbobj->secret.len;
*key = client_dbobj->secret.key;
return IPCOM_SUCCESS;
}
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,120 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Copyright 2007 Wind River Systems
******************************************************************************
*/
/*
modification history
--------------------
01a,17jul07,ps initial checkin of dhcpv6 authentication key database module
*/
#ifndef IPDHCPS6_AUTHHASH_H
#define IPDHCPS6_AUTHHASH_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
#include "ipdhcps6_duid.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_hash.h>
#ifdef __cplusplus
extern "C" {
#endif
struct Ipdhcps6_authkey_secret
{
int len;
Ip_u8 *key;
};
typedef struct Ipdhcps6_authkey_secret Ipdhcps6_authkey_secret;
struct Ipdhcps6_authkey_duid
{
int len;
Ip_u8 *duid;
};
typedef struct Ipdhcps6_authkey_duid Ipdhcps6_authkey_duid;
struct Ipdhcps6_authkey_dbentry
{
Ipdhcps6_duid duid;
Ipdhcps6_authkey_secret secret;
};
typedef struct Ipdhcps6_authkey_dbentry Ipdhcps6_authkey_dbentry;
struct Ipdhcps6_authtrans_dbentry
{
Ipdhcps6_duid duid;
Ip_u16 flags;
Ip_u32 client_replay1;
Ip_u32 client_replay2;
Ip_u32 server_replay1;
Ip_u32 server_replay2;
};
typedef struct Ipdhcps6_authtrans_dbentry Ipdhcps6_authtrans_dbentry;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ipdhcps6_duid *ipdhcps6_authdb_create_ll_duid (int len, Ip_u16 hwtype, Ip_u8 *link_addr);
IP_GLOBAL Ip_err ipdhcps6_client_wants_auth (union Ipdhcps6_duid_data *client, int len);
IP_GLOBAL Ip_err ipdhcps6_client_no_auth (union Ipdhcps6_duid_data *client, int len);
IP_GLOBAL Ipdhcps6_authtrans_dbentry
*ipdhcps6_client_requested_auth (union Ipdhcps6_duid_data *client, int len);
IP_GLOBAL Ip_err ipdhcps6_get_auth_realm (Ip_size_t *len, Ip_u8 **realm);
IP_GLOBAL Ip_err ipdhcps6_get_default_auth_key (Ip_size_t *len, Ip_u8 **key);
IP_GLOBAL Ip_err ipdhcps6_find_key_for_client (union Ipdhcps6_duid_data *client,
int duid_len,
Ip_u8 **key, Ip_size_t *key_len);
IP_GLOBAL Ipcom_hash *ipdhcps6_authdb_hash_create(void);
IP_GLOBAL Ipcom_hash *ipdhcps6_authtrans_hash_create(void);
IP_GLOBAL Ip_err ipdhcps6_add_client_authkey (Ipdhcps6_duid *client_duid,Ip_u8 *key, int keylen);
IP_GLOBAL Ip_err ipdhcps6_set_default_auth_key (char *authkey);
IP_GLOBAL Ip_err ipdhcps6_set_auth_realm (char *auth_realm);
IP_GLOBAL void ipdhcps6_authdb_init (void);
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,79 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcps6_cmd.h,v $ $Revision: 1.2 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_cmd.h,v $
* $Author: kenneth $ $Date: 2005-05-09 18:58:10 $
* $State: Exp $ $Locker: $
*
* Copyright Interpeak AB 2000-2004 <www.interpeak.se>. All rights reserved.
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#ifndef IPDHCPS6_CMD_H
#define IPDHCPS6_CMD_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/* Shell commands for DHCPv6 server */
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_os.h>
#include "ipdhcps6_cmd.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL int ipdhcps6_cmd_dhcps6(int argc, char **argv);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,157 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Copyright (C) 2007 Wind River Systems
*
******************************************************************************
*/
/*
modification history
--------------------
01a,17jul07,ps initial checkin of dhcpv6 authentication key database module
01b,20jul07,ten Remove unused local variable
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include "ipdhcps6_cvthex.h"
/*
* convert two hex digits into an unsigned char value.
* returns: 1 if successful, 0 if not
*/
IP_STATIC int ipdhcps6_cvt_two_hexdigits_to_unsigned (char *str, unsigned char *result)
{
unsigned char r;
switch (*str)
{ case '0': r = 0x0; break;
case '1': r = 0x1; break;
case '2': r = 0x2; break;
case '3': r = 0x3; break;
case '4': r = 0x4; break;
case '5': r = 0x5; break;
case '6': r = 0x6; break;
case '7': r = 0x7; break;
case '8': r = 0x8; break;
case '9': r = 0x9; break;
case 'A':
case 'a':
r = 0xA; break;
case 'B':
case 'b':
r = 0xB; break;
case 'C':
case 'c':
r = 0xC; break;
case 'D':
case 'd':
r = 0xD; break;
case 'E':
case 'e':
r = 0xE; break;
case 'F':
case 'f':
r = 0xF; break;
default:
return 0;
}
str++;
r <<= 4;
switch (*str)
{ case '0': r += 0x0; break;
case '1': r += 0x1; break;
case '2': r += 0x2; break;
case '3': r += 0x3; break;
case '4': r += 0x4; break;
case '5': r += 0x5; break;
case '6': r += 0x6; break;
case '7': r += 0x7; break;
case '8': r += 0x8; break;
case '9': r += 0x9; break;
case 'A':
case 'a':
r += 0xA; break;
case 'B':
case 'b':
r += 0xB; break;
case 'C':
case 'c':
r += 0xC; break;
case 'D':
case 'd':
r += 0xD; break;
case 'E':
case 'e':
r += 0xE; break;
case 'F':
case 'f':
r += 0xF; break;
default:
return 0;
}
*result = r;
return 1;
}
/*
* Convert a hex digit string into a buffer of unsigned chars.
* returns 1 if successful, 0 if not.
*/
int ipdhcps6_cvt_hex_to_membuf (char *str, unsigned char *buf, int len)
{
char *cptr;
if (ipcom_strlen (str) < (unsigned)(2 * len))
return 0;
cptr = str;
while (len--)
{
if (1 != ipdhcps6_cvt_two_hexdigits_to_unsigned (cptr, buf))
return 0;
cptr += 2;
buf++;
}
return 1;
}
/*
* see if a char string is a string of hex digits starting with "0x"
*/
int ipdhcps6_check_is_hex_string (char *str)
{
Ip_size_t len;
unsigned char c;
if (0 != ipcom_strncmp (str, "0x", 2))
return 0;
str += 2;
len = ipcom_strlen (str);
if ( !len || (0 != (len % 2)) )
return 0;
while (len--)
{ c = (unsigned char) (*str);
if (! ipcom_isxdigit(c))
return 0;
str++;
}
return 1;
}
@@ -0,0 +1,19 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Copyright (C) 2007 Wind River Systems
*
******************************************************************************
*/
/*
modification history
--------------------
01a,17jul07,ps initial checkin of dhcpv6 authentication key database module
*/
IP_GLOBAL int ipdhcps6_cvt_hex_to_membuf (char *str, unsigned char *buf, int len);
IP_GLOBAL int ipdhcps6_check_is_hex_string (char *str);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,202 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcps6_duid.c,v $ $Revision: 1.20 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_duid.c,v $
* $Author: kenneth $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_netif.h>
#include <ipcom_sock.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipcom_type.h>
#include <ipnet_ctrl.h>
#include "ipdhcps6.h"
#include "ipdhcps6_h.h"
#include "ipdhcps6_duid.h"
#include "ipnet_routesock.h"
#include "ipcom_sysctl.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_duid_initialize
*===========================================================================
* Description: Initializes the DUID for the server.
* Parameters:
* Returns: IPCOM_SUCCESS - operation completed successfully
* IPCOM_ERR_INVALID_INTERFACE - the specified network
* interface was not found
* IPCOM_ERR_FAILED - Could not read the MAC address from the
*
*/
IP_GLOBAL Ip_err
ipdhcps6_duid_initialize(void)
{
char ifname[IP_IFNAMSIZ];
Ip_size_t ifname_size = sizeof(ifname);
Ip_u32 ifindex;
Ipdhcps6_option *duid;
Ip_u16 duid_len;
union Ipdhcps6_duid_data *serverid;
int name[6];
Ip_u8 *if_data;
Ip_size_t if_data_len;
struct Ipnet_if_msghdr *ifm;
struct Ip_sockaddr_dl *hwaddr;
if (ipcom_sysvar_get("ipdhcps6.duid.ifname", ifname, &ifname_size) == IP_NULL)
{
IPCOM_LOG0(ERR, "No interface specified to calculate server ID (use sysvar ipdhcps6.duid.ifname)");
return IPCOM_ERR_INVALID_INTERFACE;
}
ifindex = ipcom_if_nametoindex(ifname);
if (ifindex == 0)
{
IPCOM_LOG1(ERR, "Interface %s was not found", ifname);
return IPCOM_ERR_INVALID_INTERFACE;
}
name[0] = IP_CTL_NET;
name[1] = IP_AF_ROUTE;
name[2] = 0;
name[3] = IP_AF_INET6;
name[4] = IP_NET_RT_IFLIST;
name[5] = (int)ifindex;
if (ipcom_sysctl(name, 6, IP_NULL, &if_data_len, IP_NULL, 0) < 0)
{
IPCOM_LOG1(CRIT, "ipcom_sysctl failed: %s", ipcom_strerror(ipcom_errno));
return IPCOM_ERR_FAILED;
}
if_data = ipcom_malloc(if_data_len);
if (if_data == IP_NULL)
{
IPCOM_LOG0(CRIT, "out of memory");
return IPCOM_ERR_NO_MEMORY;
}
if (ipcom_sysctl(name, 6, if_data, &if_data_len, IP_NULL, 0) < 0)
{
IPCOM_LOG1(CRIT, "ipcom_sysctl failed: %s", ipcom_strerror(ipcom_errno));
goto errout;
}
ifm = (struct Ipnet_if_msghdr *) if_data;
hwaddr = (struct Ip_sockaddr_dl *) &if_data[sizeof(struct Ipnet_if_msghdr)];
duid_len = sizeof(struct Ipdhcps6_duid_ll_data);
duid = ipcom_malloc((Ip_size_t)(duid_len + IPDHCPS6_OPTION_HDR_LEN));
if (duid == IP_NULL)
{
IPCOM_LOG0(CRIT, "ipdhcps6_duid_initialize: out of memory");
goto errout;
}
ipdhcps6_set_u16(&duid->len, duid_len);
ipdhcps6_set_u16(&duid->code, IPDHCPS6_OPTION_SERVERID);
serverid = &duid->data.serverid;
serverid->ll.content = ip_htons(IPDHCPS6_DUID_LL);
if ((IP_IFT_ETHER == ifm->ifm_data.ifi_type) || (IP_IFT_IEEE80211 == ifm->ifm_data.ifi_type))
ipdhcps6_set_u16(&serverid->ll.hardware_type , 1);
ipcom_memcpy(serverid->ll.link_addr, IP_SOCKADDR_DL_LLADDR(hwaddr), hwaddr->sdl_alen);
ipdhcps6->duid = duid;
ipcom_free(if_data);
return IPCOM_SUCCESS;
errout:
ipcom_free(if_data);
return IPCOM_ERR_FAILED;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,284 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcps6_h.h,v $ $Revision: 1.15.14.1 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_h.h,v $
* $Author: ulf $ $Date: 2011-11-16 10:33:28 $
* $State: Exp $ $Locker: $
*
* Copyright Interpeak AB 2000-2004 <www.interpeak.se>. All rights reserved.
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#ifndef IPDHCPS6_H_H
#define IPDHCPS6_H_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_cstyle.h>
#include <ipcom_hash.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_route.h>
#include <ipcom_type.h>
#include <ipcom_tmo2.h>
#include "ipdhcps6.h"
#include "ipdhcps6_h.h"
#include "ipdhcps6_option.h"
#include "ipdhcps6_host.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#ifdef IPCOM_SYSLOG_PRIORITY /* for 64-bit compile warning */
#undef IPCOM_SYSLOG_PRIORITY
#endif
#if defined(_WRS_CONFIG_IPDHCPS6_SYSLOG_PRIORITY)
#define IPCOM_SYSLOG_PRIORITY _WRS_CONFIG_IPDHCPS6_SYSLOG_PRIORITY
#else
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG
#endif
#ifdef IPCOM_SYSLOG_FACILITY /* for 64-bit compile warning */
#undef IPCOM_SYSLOG_FACILITY
#endif
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPDHCPS6
#if !defined(IPCOM_RELEASE) || IPCOM_RELEASE < 50900
#define Ip_ipv6_mreq Ip_ip6_mreq
#define ipv6mr_multiaddr imr_multiaddr
#define Ipcom_hash_foreach_cb_func Ipcom_hash_forech_cb_func
#endif
#define IPDHCPS6_SET_IN6_ADDR(dst, src) ipcom_memcpy(dst, src, sizeof(struct Ip_in6_addr))
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
struct Ipdhcps6_host_struct;
struct Ipdhcps6_message_struct;
struct Ipdhcps6_subnet_entry_struct;
/* A pool of addresses to hand out */
typedef struct Ipdhcps6_addr_pool_struct
{
struct Ipdhcps6_addr_pool_struct *next;
/* Pool description */
Ipdhcps6_poolinfo info;
}
Ipdhcps6_addr_pool;
/* Address that is currently leased by a client */
typedef struct Ipdhcps6_active_lease_addr_struct
{
/* The IPv6 address value */
struct Ip_in6_addr addr;
/* The IAID specified by the client for this address */
Ip_u32 iaid;
/* The host that is using (or has been using) this address */
struct Ipdhcps6_host_struct *host;
/* Points back to pool where this address has been drawn */
Ipcom_hash *active_leases;
/* Timeout handler when this entry will expire */
Ipcom_tmo2 tmo;
/* Can't store a backpointer to the pool, since due to construct it may
* disappear at any time */
Ip_u32 valid;
Ip_u32 preferred;
/* Prefix information */
Ip_u16 ia_type;
Ip_u8 prefix_len;
/* The same host lease list */
Ipcom_list next;
}
Ipdhcps6_lease_addr;
/* The database structure.
Access to this structure is only allowed when holding the mutex
*/
struct Ipdhcps6_database
{
/* Mutext use to protect data in this structure */
Ipcom_mutex mutex;
/* Contains all configured subnets (key is subnet) */
Ipcom_route *subnets;
/* Contains all configured prefixes (key is ID number) */
Ipcom_hash *prefixes;
/* Contains all configured hosts (key is DUID) */
Ipcom_hash *hosts;
/* Contains the options that applies to all subnets and hosts (key is option ID) */
Ipcom_hash *options;
/* Contains the prefix information to send to a PPP interface */
Ipcom_hash *if_prefix_info;
};
/* Global data structure for the DHCPv6 server. */
struct Ipdhcps6_data
{
/* IPDHCPS6_FLAG_xxx flags */
Ip_u32 flags;
/* Socket used for UDP communication */
int sock;
/* Socket used to listen for stack events */
int rt_sock;
/* Socket used for IPD communication */
int ipd;
/* Buffer where received packets can be stored */
Ip_u8 recv_buf[IPDHCPS6_RECV_BUF_SIZE];
/* Buffer where the response message can be stored */
Ip_u8 send_buf[IPDHCPS6_RECV_BUF_SIZE];
/* Last prefix key created */
int prefix_key;
/* The number of allowed hops for relayed packets */
Ip_u8 hop_count_limit;
/* The server DUID */
const Ipdhcps6_option *duid;
/* The DHCP database */
struct Ipdhcps6_database db;
/* Queue of pending timeouts */
Ipcom_pqueue *timeouts;
/* Buffer to convert IPv6 addresses to strings when logging */
char addr_str[40];
};
#define IPDHCPS6_FLAG_OPEN (1 << 0) /* The server has been opened (started) */
#define IPDHCPS6_FLAG_RELAY (1 << 1) /* Running as DHCPv6 relay (server otherwise) */
/* If the relay agent relays messages to the All_DHCP_Servers multicast
* address or other multicast addresses, it sets the Hop Limit field to
* 32.
*/
#define IPDHCP6_RELAY_MULTICAST_HOPS 32
IP_EXTERN struct Ipdhcps6_data *ipdhcps6;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL void ipdhcps6_delete_hash_db_cb(void *obj, void *not_used);
IP_GLOBAL Ipcom_netif *
ipdhcps6_get_netifbyindex(Ip_u32 ifindex);
IP_GLOBAL Ip_u16
ipdhcps6_get_u16(const Ip_u16 *u16);
IP_GLOBAL void
ipdhcps6_set_u16(Ip_u16 *u16, Ip_u16 val);
IP_GLOBAL Ip_u32
ipdhcps6_get_u32(const Ip_u32 *u32);
IP_GLOBAL void
ipdhcps6_set_u32(Ip_u32 *u32, Ip_u32 val);
IP_GLOBAL void
ipdhcps6_create_mask(struct Ip_in6_addr *mask, int netbits);
IP_GLOBAL void
ipdhcps6_msg_next_response_opt(Ip_u16 written, struct Ipdhcps6_message_struct *msg,
Ipdhcps6_option **next_response_opt, Ip_u16 *opt_buf_left);
IP_GLOBAL Ip_err
ipdhcps6_user_get(Ipdhcps6_user *user);
IP_GLOBAL Ip_err
ipdhcps6_relay_do_forward_client(struct Ipdhcps6_message_struct *msg);
IP_GLOBAL Ip_err
ipdhcps6_relay_do_forward_relay(struct Ipdhcps6_message_struct *msg);
IP_GLOBAL Ip_err
ipdhcps6_relay_process_reply(struct Ipdhcps6_message_struct *msg,
Ipdhcps6_option *options,
Ip_u16 optslen);
IP_GLOBAL Ip_err
ipdhcps6_pool_process_non_temporary_addr_request(Ip_u8 msg_type,
struct Ipdhcps6_subnet_entry_struct *subnet,
struct Ipdhcps6_host_struct *host,
struct Ipdhcps6_option_struct *opt,
struct Ipdhcps6_option_struct *response_opt,
Ip_u16 response_optlen,
Ip_u16 *bytes_written);
IP_GLOBAL Ip_err
ipdhcps6_pool_process_prefix_delegation_request(Ip_u8 msg_type,
struct Ipdhcps6_subnet_entry_struct *subnet,
struct Ipdhcps6_host_struct *host,
struct Ipdhcps6_option_struct *in_opt,
struct Ipdhcps6_option_struct *out_opt,
Ip_u16 out_opt_buf_len,
Ip_u16 *bytes_written);
IP_GLOBAL void
ipdhcps6_pool_delete_from_subnet(struct Ipdhcps6_subnet_entry_struct *sn_entry);
IP_GLOBAL Ip_err
ipdhcps6_process_message(struct Ipdhcps6_message_struct *msg);
IP_GLOBAL void
ipdhcps6_dns_free(Ipdhcps6_host *host);
IP_GLOBAL char*
ipdhcps6_dns_get_domain(char* domainname);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,660 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_RCPL8_2024030303 $ $RCSfile: ipdhcps6_host.c,v $ $Revision: 1.26.12.3 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_host.c,v $
* $Author: jchang1 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_time.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_hash.h>
#include <ipcom_list.h>
#include <ipcom_netif.h>
#include <ipcom_type.h>
#ifdef IPPPP
#include <ipppp.h>
#endif
#include <ipnet.h>
#include "ipdhcps6.h"
#include "ipdhcps6_h.h"
#include "ipdhcps6_host.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
struct Ipdhcps6_host_list_cb_data
{
/* The error code */
Ip_err err;
/* Number of options stored in the 'clientid' buffer */
int total_bytes;
/* Number of elements that can fit into 'clientid' */
int buf_len;
/* Points to where the next client ID should be written */
Ipdhcps6_option *clientid;
};
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_host_obj_hash
*===========================================================================
* Description: Returns a hash value based on a DHCP host.
* Parameters: opt - The host to return a hash value for.
* Returns:
*
*/
IP_STATIC unsigned
ipdhcps6_host_obj_hash(Ipdhcps6_host *host)
{
return ipcom_hash_update(host->duid,
ipdhcps6_get_u16(&host->duid->len) + IPDHCPS6_OPTION_HDR_LEN,
0);
}
/*
*===========================================================================
* ipdhcps6_host_key_hash
*===========================================================================
* Description: Returns a hash value for a client id (DUID).
* Parameters: code - Pointer to a host client id option.
* Returns:
*
*/
IP_STATIC unsigned
ipdhcps6_host_key_hash(Ipdhcps6_option *duid)
{
return ipcom_hash_update(duid,
ipdhcps6_get_u16(&duid->len) + IPDHCPS6_OPTION_HDR_LEN,
0);
}
/*
*===========================================================================
* ipdhcps6_host_cmp
*===========================================================================
* Description: Checks if the client id options matches the host entry.
* Parameters: host - A host entry.
* duid - The client id to match.
* Returns: IP_TRUE if the client id in the host matches.
*
*/
IP_STATIC Ip_bool
ipdhcps6_host_cmp(Ipdhcps6_host *host, Ipdhcps6_option *duid)
{
Ip_u16 duid_len;
duid_len = ipdhcps6_get_u16(&duid->len);
if (duid_len != ipdhcps6_get_u16(&host->duid->len))
return IP_FALSE;
return ipcom_memcmp(host->duid, duid, (Ip_size_t)(duid_len + IPDHCPS6_OPTION_HDR_LEN)) == 0;
}
/*
*===========================================================================
* ipdhcps6_host_list_cb
*===========================================================================
* Description: Stores pointers to all options in the hash table.
* Parameters: opt - The option to add.
* ol - Callback paramters
* Returns:
*
*/
IP_STATIC void
ipdhcps6_host_list_cb(Ipdhcps6_host *host, struct Ipdhcps6_host_list_cb_data *hl)
{
Ip_u16 len;
len = (Ip_u16) (ipdhcps6_get_u16(&host->duid->len) + IPDHCPS6_OPTION_HDR_LEN);
hl->total_bytes += len;
if (hl->clientid == IP_NULL || hl->err != IPCOM_SUCCESS)
/* Just calculate the number of elements */
return;
if (hl->total_bytes <= hl->buf_len)
{
ipcom_memcpy(hl->clientid, host->duid, len);
hl->clientid = (Ipdhcps6_option *) ((Ip_u8 *) hl->clientid + len);
}
else
hl->err = IPCOM_ERR_NO_MEMORY;
}
/*
*===========================================================================
* ipdhcps6_delete_host_db_cb
*===========================================================================
* Description: Deletes all elements in a host database.
* Parameters: host - The host to be deleted.
* Returns:
*
*/
IP_STATIC void
ipdhcps6_delete_host_db_cb(Ipdhcps6_host *host, void *not_used)
{
(void) not_used;
if(host != IP_NULL)
{
ipdhcps6_option_delete_db(host->options);
ipcom_free(host);
}
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_host_new
*===========================================================================
* Description: Creates a new host entry.
* Parameters: duid - The client ID of the host entry.
* Returns: The host entry or IP_NULL if out of memory.
*
*/
IP_GLOBAL Ipdhcps6_host *
ipdhcps6_host_new(Ipdhcps6_option *duid, struct Ip_sockaddr_in6 *addr)
{
Ipdhcps6_host *host;
Ip_u16 duid_len;
duid_len = (Ip_u16) (ipdhcps6_get_u16(&duid->len) + IPDHCPS6_OPTION_HDR_LEN);
host = (Ipdhcps6_host *) ipcom_calloc(1, sizeof(Ipdhcps6_host) + duid_len);
if (host == IP_NULL)
goto out_of_memory;
host->options = ipdhcps6_option_new_db();
if (host->options == IP_NULL)
goto out_of_memory;
host->duid = (Ipdhcps6_option *) (host + 1);
ipcom_memcpy(host->duid, duid, duid_len);
host->last_servered = ipcom_time(IP_NULL);
host->is_allowed_to_use_unicast = IP_FALSE;
ipcom_list_init(&host->leases_head);
if (addr != IP_NULL)
ipcom_memcpy(&host->addr, addr, sizeof(struct Ip_sockaddr_in6));
ipcom_memset(&host->user, 0, sizeof(host->user));
if (ipcom_hash_add(ipdhcps6->db.hosts, host) != IPCOM_SUCCESS)
goto out_of_memory;
return host;
out_of_memory:
if (host != IP_NULL)
{
if (host->options != IP_NULL)
ipcom_hash_delete(host->options);
ipcom_free(host);
}
return IP_NULL;
}
/*
*===========================================================================
* ipdhcps6_host_try_get_user
*===========================================================================
* Description: Creates a new host entry.
* Parameters: duid - The client ID of the host entry.
* Returns: The host entry or IP_NULL if out of memory.
*
*/
IP_GLOBAL void
ipdhcps6_host_try_get_user(Ipdhcps6_host *host, Ipcom_netif *netif)
{
ip_assert(IP_NULL != host);
ip_assert(IP_NULL != netif);
/* change "debug" to "\0", confuse if configured the prefix name with "debug" */
ipcom_strncpy(host->user.name, "\0", IPCOM_AUTH_USERNAME_MAX);
switch (netif->type)
{
#ifdef IPPPP
case IP_IFT_PPP:
{
struct Ip_pppreq pppreq;
Ip_fd tmp_fd = IP_INVALID_SOCKET;
host->ifindex = (int)netif->ifindex;
ipcom_memcpy(pppreq.pppr_name, netif->name, IP_IFNAMSIZ);
tmp_fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0);
if (ipcom_socketioctl(tmp_fd,IP_SIOCXPPPGPEERUSER, &pppreq) >= 0)
{
ipcom_strncpy(host->user.name, pppreq.pppru.username, IPCOM_AUTH_USERNAME_MAX);
(void)ipdhcps6_user_get(&host->user);
}
break;
}
#endif /* IPPPP */
/* more type if needed */
default:
break;
}
}
/*
*===========================================================================
* ipdhcps6_host_get
*===========================================================================
* Description: Returns the host matching DUID.
* Parameters: duid - The client ID of the host entry to return.
* Returns: The host entry or IP_NULL if no matching host exist.
*
*/
IP_GLOBAL Ipdhcps6_host *
ipdhcps6_host_get(Ipdhcps6_option *duid)
{
return (Ipdhcps6_host *) ipcom_hash_get(ipdhcps6->db.hosts, duid);
}
/*
*===========================================================================
* ipdhcps6_host_new_db
*===========================================================================
* Description: Creates a new host database.
* Parameters:
* Returns: An empty host database, or IP_NULL if out of memory.
*
*/
IP_GLOBAL Ipcom_hash *
ipdhcps6_host_new_db(void)
{
return ipcom_hash_new((Ipcom_hash_obj_func)ipdhcps6_host_obj_hash,
(Ipcom_hash_key_func)ipdhcps6_host_key_hash,
(Ipcom_hash_cmp_func)ipdhcps6_host_cmp);
}
/*
*===========================================================================
* ipdhcps6_host_delete_db
*===========================================================================
* Description: Deletes all elements in the host database, memory for
* the hash table holding the entries is also deleted.
* Parameters: options - The host database to delete.
* Returns:
*
*/
IP_GLOBAL void
ipdhcps6_host_delete_db(Ipcom_hash *hosts)
{
if (hosts != IP_NULL)
{
ipcom_hash_for_each(hosts, ipdhcps6_delete_host_db_cb, IP_NULL);
ipcom_hash_delete(hosts);
}
}
/*
*===========================================================================
* ipdhcps6_host_has_prefix
*===========================================================================
* Description: Returns if this host has at least 1 prefix.
* Parameters: host - Host to look in.
* Returns:
*
*/
IP_GLOBAL Ip_bool
ipdhcps6_host_has_prefix(const Ipdhcps6_host *host)
{
return host->user.prefix_ids[0][0] != '\0';
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_host_add
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_host_add(Ipdhcps6_option *duid)
{
Ipdhcps6_host *host;
if (ipdhcps6 == IP_NULL || IP_BIT_ISFALSE(ipdhcps6->flags, IPDHCPS6_FLAG_OPEN))
return IPCOM_ERR_NOT_OPENED;
ipcom_mutex_lock(ipdhcps6->db.mutex);
if (ipcom_hash_get(ipdhcps6->db.hosts, duid) != IP_NULL)
{
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_ERR_DUPLICATE;
}
host = ipdhcps6_host_new(duid, IP_NULL);
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return host != IP_NULL ? IPCOM_SUCCESS : IPCOM_ERR_NO_MEMORY;
}
/*
*===========================================================================
* ipdhcps6_host_delete
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_host_delete(Ipdhcps6_option *duid)
{
Ipdhcps6_host *host;
if (ipdhcps6 == IP_NULL || !IP_BIT_ISSET(ipdhcps6->flags, IPDHCPS6_FLAG_OPEN))
return IPCOM_ERR_NOT_OPENED;
ipcom_mutex_lock(ipdhcps6->db.mutex);
host = (Ipdhcps6_host *) ipcom_hash_get(ipdhcps6->db.hosts, duid);
if (host == IP_NULL)
{
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_ERR_NOT_FOUND;
}
ipcom_hash_remove(ipdhcps6->db.hosts, host);
ipcom_free(host);
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipdhcps6_host_list
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_host_list(Ipdhcps6_option *duid, int *duid_len)
{
struct Ipdhcps6_host_list_cb_data lc;
if (ipdhcps6 == IP_NULL || !IP_BIT_ISSET(ipdhcps6->flags, IPDHCPS6_FLAG_OPEN))
return IPCOM_ERR_NOT_OPENED;
ipcom_mutex_lock(ipdhcps6->db.mutex);
lc.err = IPCOM_SUCCESS;
lc.total_bytes = 0;
lc.buf_len = *duid_len;
lc.clientid = duid;
ipcom_hash_for_each(ipdhcps6->db.hosts,
(void(*)(void *, void *)) ipdhcps6_host_list_cb,
&lc);
ipcom_mutex_unlock(ipdhcps6->db.mutex);
*duid_len = lc.total_bytes;
return lc.err;
}
/*
*===========================================================================
* ipdhcps6_host_to_string
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_host_to_string(Ipdhcps6_option *duid, char *str, int str_len)
{
Ipdhcps6_host *host;
Ip_err err;
Ip_size_t len;
char ifname[IP_IFNAMSIZ];
Ipcom_list *cur = IP_NULL;
Ipdhcps6_lease_addr *le = IP_NULL;
char domain[128];
if (ipdhcps6 == IP_NULL || IP_BIT_ISFALSE(ipdhcps6->flags, IPDHCPS6_FLAG_OPEN))
return IPCOM_ERR_NOT_OPENED;
ipcom_mutex_lock(ipdhcps6->db.mutex);
host = (Ipdhcps6_host *) ipcom_hash_get(ipdhcps6->db.hosts, duid);
if (host == IP_NULL)
{
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_ERR_NOT_FOUND;
}
err = ipdhcps6_option_to_string(duid, str, str_len);
if (err != IPCOM_SUCCESS)
goto buf_to_small;
len = ipcom_strlen(str);
str += len;
str_len -= len;
if (IP_IN6_IS_ADDR_UNSPECIFIED(&host->addr))
{
err = ipcom_snprintf(str, (Ip_size_t)str_len, IP_LF "\taddr: unknown" IP_LF);
}
else
{
err = ipcom_snprintf(str, (Ip_size_t)str_len, IP_LF "\taddr: %s",
ipcom_inet_ntop(IP_AF_INET6,
&host->addr.sin6_addr,
ipdhcps6->addr_str,
sizeof(ipdhcps6->addr_str)));
if (err > 0 && host->addr.sin6_scope_id != 0)
{
len = ipcom_strlen(str);
str += len;
str_len -= len;
err = ipcom_snprintf(str, (Ip_size_t)str_len, "%s%s" IP_LF, "%%",
ipcom_if_indextoname(host->addr.sin6_scope_id, ifname));
}
}
if (err < 0)
goto buf_to_small;
len = ipcom_strlen(str);
str += len;
str_len -= len;
if(host->fqdn.fullName[0]!='\0')
{
err = ipcom_snprintf(str, (Ip_size_t)str_len, "\tFQDN:%s.%s"IP_LF,host->fqdn.fullName, ipdhcps6_dns_get_domain(domain));
if (err < 0)
goto buf_to_small;
len = ipcom_strlen(str);
str += len;
str_len -= len;
}
err = ipcom_snprintf(str, (Ip_size_t)str_len, "\tlast served %d seconds ago" IP_LF,
ipcom_time(IP_NULL) - host->last_servered);
if (err < 0)
goto buf_to_small;
len = ipcom_strlen(str);
str += len;
str_len -= len;
for (cur = ipcom_list_first(&host->leases_head);
IP_NULL != cur;
cur = ipcom_list_next(cur))
{
le = ipcom_list_entry(cur, Ipdhcps6_lease_addr, next);
ip_assert(IP_NULL != le);
if (le->prefix_len)
err = ipcom_snprintf(str, (Ip_size_t)str_len, "\tlease addr: %s/%d, preferred: %ds, valid: %ds" IP_LF,
ipcom_inet_ntop(IP_AF_INET6,
&le->addr,
ipdhcps6->addr_str,
sizeof(ipdhcps6->addr_str)),
le->prefix_len,
le->preferred,
le->valid);
else
err = ipcom_snprintf(str, (Ip_size_t)str_len, "\tlease addr: %s, preferred: %ds, valid: %ds" IP_LF,
ipcom_inet_ntop(IP_AF_INET6,
&le->addr,
ipdhcps6->addr_str,
sizeof(ipdhcps6->addr_str)),
le->preferred,
le->valid);
if (err < 0)
goto buf_to_small;
}
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_SUCCESS;
buf_to_small:
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_ERR_NO_MEMORY;
}
/*
*===========================================================================
* ipdhcps6_host_get_user
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_host_get_user(Ipdhcps6_option *duid, char *username, int username_len)
{
Ipdhcps6_host *host;
Ip_err err = IPCOM_SUCCESS;
ipcom_mutex_lock(ipdhcps6->db.mutex);
host = (Ipdhcps6_host *) ipcom_hash_get(ipdhcps6->db.hosts, duid);
if (host == IP_NULL)
{
err = IPCOM_ERR_NOT_FOUND;
goto cleanup;
}
if (ipcom_strlen(host->user.name) == 0)
{
err = IPCOM_ERR_NOT_SUPPORTED;
goto cleanup;
}
ipcom_strncpy(username, host->user.name, (Ip_size_t)username_len);
cleanup:
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return err;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,129 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcps6_host.h,v $ $Revision: 1.7.18.1 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_host.h,v $
* $Author: ulf $ $Date: 2011-11-16 10:33:28 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#ifndef IPDHCPS6_HOST_H
#define IPDHCPS6_HOST_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_netif.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
struct Ipdhcps6_active_lease_addr_struct;
typedef struct Ipdhcps6_fqdn
{
char fullName[255];
Ip_bool ptr_status;
/*Ptr update successfully or not*/
Ip_bool aaaa_status;
/*AAAA update successfully or not*/
Ip_bool agent;
Ip_bool oro;
struct Ip_in6_addr addr;
} Ipdhcps6_fqdn;
/* DHCP host structure */
typedef struct Ipdhcps6_host_struct
{
/* The client ID for this host */
Ipdhcps6_option *duid;
/* The currently leased by a client with this host */
Ipcom_list leases_head;
/* The interface used to communicate with this host */
int ifindex;
/* The unicast address for this host */
struct Ip_sockaddr_in6 addr;
/* Last time this host contacted the DHCP server */
Ip_time_t last_servered;
/* Is IP_TRUE if a Server Unicast Option has been sent to this host */
Ip_bool is_allowed_to_use_unicast;
/* Options for this host */
Ipcom_hash *options;
/* User associated with this host, ipcom_strlen(user.name) != 0 only if the user is known */
Ipdhcps6_user user;
Ipdhcps6_fqdn fqdn;
}
Ipdhcps6_host;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ipdhcps6_host *
ipdhcps6_host_new(Ipdhcps6_option *duid, struct Ip_sockaddr_in6 *addr);
IP_GLOBAL Ipdhcps6_host *
ipdhcps6_host_get(Ipdhcps6_option *duid);
IP_GLOBAL Ipcom_hash *
ipdhcps6_host_new_db(void);
IP_GLOBAL void
ipdhcps6_host_delete_db(Ipcom_hash *hosts);
IP_GLOBAL Ip_bool
ipdhcps6_host_has_prefix(const Ipdhcps6_host *host);
IP_GLOBAL void
ipdhcps6_host_try_get_user(Ipdhcps6_host *host, Ipcom_netif *netif);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,363 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcps6_msg.h,v $ $Revision: 1.9.16.1 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_msg.h,v $
* $Author: ulf $ $Date: 2011-11-16 10:33:28 $
* $State: Exp $ $Locker: $
*
* Copyright Interpeak AB 2000-2004 <www.interpeak.se>. All rights reserved.
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#ifndef IPDHCPS6_MSG_H
#define IPDHCPS6_MSG_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include "ipdhcps6_option.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* DHCP Message Types */
/* A client sends a Solicit message to locate servers. */
#define IPDHCPS6_MSG_SOLICIT 1
/* A server sends an Advertise message to indicate
that it is available for DHCP service, in
response to a Solicit message received from a
client. */
#define IPDHCPS6_MSG_ADVERTISE 2
/* A client sends a Request message to request
configuration parameters, including IP
addresses, from a specific server. */
#define IPDHCPS6_MSG_REQUEST 3
/* A client sends a Confirm message to any
available server to determine whether the
addresses it was assigned are still appropriate
to the link to which the client is connected. */
#define IPDHCPS6_MSG_CONFIRM 4
/* A client sends a Renew message to the server
that originally provided the client's addresses
and configuration parameters to extend the
lifetimes on the addresses assigned to the
client and to update other configuration
parameters. */
#define IPDHCPS6_MSG_RENEW 5
/* A client sends a Rebind message to any
available server to extend the lifetimes on the
addresses assigned to the client and to update
other configuration parameters; this message is
sent after a client receives no response to a
Renew message. */
#define IPDHCPS6_MSG_REBIND 6
/* A server sends a Reply message containing
assigned addresses and configuration parameters
in response to a Solicit, Request, Renew,
Rebind message received from a client. A
server sends a Reply message containing
configuration parameters in response to an
Information-request message. A server sends a
Reply message in response to a Confirm message
confirming or denying that the addresses
assigned to the client are appropriate to the
link to which the client is connected. A
server sends a Reply message to acknowledge
receipt of a Release or Decline message. */
#define IPDHCPS6_MSG_REPLY 7
/* A client sends a Release message to the server
that assigned addresses to the client to
indicate that the client will no longer use one
or more of the assigned addresses. */
#define IPDHCPS6_MSG_RELEASE 8
/* A client sends a Decline message to a server to
indicate that the client has determined that
one or more addresses assigned by the server
are already in use on the link to which the
client is connected. */
#define IPDHCPS6_MSG_DECLINE 9
/* A server sends a Reconfigure message to a
client to inform the client that the server has
new or updated configuration parameters, and
that the client is to initiate a Renew/Reply
or Information-request/Reply transaction with
the server in order to receive the updated
information. */
#define IPDHCPS6_MSG_RECONFIGURE 10
/* A client sends an Information-request
message to a server to request configuration
parameters without the assignment of any IP
addresses to the client. */
#define IPDHCPS6_MSG_INFORMATION_REQUEST 11
/* A relay agent sends a Relay-forward message
to relay messages to servers, either directly
or through another relay agent. The received
message, either a client message or a
Relay-forward message from another relay
agent, is encapsulated in an option in the
Relay-forward message. */
#define IPDHCPS6_MSG_RELAY_FORW 12
/* A server sends a Relay-reply message to a relay
agent containing a message that the relay
agent delivers to a client. The Relay-reply
message may be relayed by other relay agents
for delivery to the destination relay agent.
The server encapsulates the client message as
an option in the Relay-reply message, which the
relay agent extracts and relays to the client. */
#define IPDHCPS6_MSG_RELAY_REPL 13
/* Status Codes */
/* Success */
#define IPDHCPS6_CODE_SUCCESS 0
/* Failure, reason unspecified; this status code is sent by either a client
or a server to indicate a failure not explicitly specified in the DHCPv6
protocol specification */
#define IPDHCPS6_CODE_UNSPEC_FAIL 1
/* Server has no addresses available to assign to the IA(s) */
#define IPDHCPS6_CODE_NO_ADDRS_AVAIL 2
/* Client record (binding) unavailable */
#define IPDHCPS6_CODE_NO_BINDING 3
/* The prefix for the address is not appropriate to the link to which the
client is attached */
#define IPDHCPS6_CODE_NOT_ON_LINK 4
/* Sent by a server to a client to force the client to send messages to the
server using the All_DHCP_Relay_Agents_and_Servers address */
#define IPDHCPS6_CODE_USE_MULTICAST 5
/* The deligating server (this DHCPv6 server) will not give any prefixes
to the requesting router */
#define IPDHCPS6_CODE_NO_PREFIX_AVAIL 6
/*FLAGS used for FQDN*/
#define IPDHCPS6_DNS_AAAA 0
#define IPDHCPS6_DNS_PTR 1
#define IPDHCPS6_DNS_MAX_NAME_LEN 255
#define IPDHCPS6_DNS_DEFAULT_TTL 3600
#define IPDHCPS6_DNS_MIN_TTL 60*10
#define IPDHCPS6_FQDN_FLAG_S 0x01
#define IPDHCPS6_FQDN_FLAG_O 0x02
#define IPDHCPS6_FQDN_FLAG_N 0x04
#define IPDHCPS6_DNS_MD5_VALUE_LEN 16
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
struct Ipdhcps6_subnet_entry_struct;
typedef struct Ipdhcps6_message_struct
{
/* The interface to use for send response,
also the interface the request was received on */
Ip_u32 ifindex;
/* The address the request was sent to */
struct Ip_sockaddr_in6 local_addr;
/* The address the request was sent from */
struct Ip_sockaddr_in6 peer_addr;
/* The address the response should be sent to */
struct Ip_sockaddr_in6 response_addr;
/* Will be != if the response must be sent on a specific interface */
Ip_u32 response_ifindex;
/* The subnet that maches this message */
struct Ipdhcps6_subnet_entry_struct *subnet;
/* The length of the received message */
Ip_u16 recv_buf_len;
/* Pointer to the recieved message */
Ip_u8 *recv_buf;
/* Set to IP_TRUE if a response should be sent */
Ip_bool send_response;
/* The maximum length of the send buffer */
Ip_u16 send_buf_maxlen;
/* The actual length of data written to the send buffer */
Ip_u16 send_buf_len;
/* The send buffer */
Ip_u8 *send_buf;
/* Set to IP_TRUE if hop limit field should be set when
* relay agent relays messages to the All_DHCP_Servers multicast
* address or other multicast addresses. Fix for WIND00195425.
*/
Ip_bool mhop_limit;
}
Ipdhcps6_message;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| msg-type | transaction-id |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
. options .
. (variable) .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
msg-type Identifies the DHCP message type; the
available message types are listed in
section 5.3.
transaction-id The transaction ID for this message exchange.
options Options carried in this message.
*/
#include "ipcom_align16.h"
typedef IP_PACKED1 struct Ipdhcps6_msg_hdr_struct
{
Ip_u8 type;
Ip_u8 transaction_id_1;
Ip_u8 transaction_id_2;
Ip_u8 transaction_id_3;
/* The options (header is 4 bytes so the this is the smallest possible size) */
Ip_u8 options[4];
}
IP_PACKED2 Ipdhcps6_msg_hdr;
#include "ipcom_align16.h"
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| msg-type | hop-count | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| link-address |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
| | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| peer-address |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
| | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
. .
. options (variable number and length) .... .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#include "ipcom_align16.h"
typedef IP_PACKED1 struct Ipdhcps6_relay_msg_hdr_struct
{
Ip_u8 type;
Ip_u8 hop_count;
struct Ip_in6_addr link_addr;
struct Ip_in6_addr peer_addr;
Ip_u8 options[1];
}
IP_PACKED2 Ipdhcps6_relay_msg_hdr;
#include "ipcom_align16.h"
#define IPDHCPS6_MSG_HDR_LEN 4
#define IPDHCP_RELAY_MSG_HDR_LEN 34
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL const char *
ipdhcps6_msg_type_to_string(Ip_u8 type);
IP_GLOBAL Ip_err
ipdhcps6_msg_process_solicit(Ipdhcps6_message *msg,
Ipdhcps6_option *options, Ip_u16 optlen);
IP_GLOBAL Ip_err
ipdhcps6_msg_process_confirm(Ipdhcps6_message *msg,
Ipdhcps6_option *options, Ip_u16 optlen);
IP_GLOBAL Ip_err
ipdhcps6_msg_process_request(Ipdhcps6_message *msg,
Ipdhcps6_option *options, Ip_u16 optlen);
IP_GLOBAL Ip_err
ipdhcps6_msg_process_renew(Ipdhcps6_message *msg,
Ipdhcps6_option *options, Ip_u16 optlen);
IP_GLOBAL Ip_err
ipdhcps6_msg_process_rebind(Ipdhcps6_message *msg,
Ipdhcps6_option *options, Ip_u16 optlen);
IP_GLOBAL Ip_err
ipdhcps6_msg_process_release(Ipdhcps6_message *msg,
Ipdhcps6_option *options, Ip_u16 optlen);
IP_GLOBAL Ip_err
ipdhcps6_msg_process_decline(Ipdhcps6_message * msg,
Ipdhcps6_option *options,
Ip_u16 optslen);
IP_GLOBAL Ip_err
ipdhcps6_msg_process_relay_forw(Ipdhcps6_message *msg,
Ipdhcps6_option *options, Ip_u16 optlen);
IP_GLOBAL Ip_err
ipdhcps6_msg_process_information_request(Ipdhcps6_message *msg,
Ipdhcps6_option *options,
Ip_u16 optlen);
IP_GLOBAL void
ipdhcps6_msg_get_first_option(Ipdhcps6_msg_hdr *msg,
Ip_u16 msg_len,
Ipdhcps6_option **poptions,
Ip_u16 *poptslen);
IP_GLOBAL void
ipdhcps6_msg_first_response_opt(Ipdhcps6_message *msg,
Ipdhcps6_option **response_opt,
Ip_u16 *optlen);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,752 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_RCPL8_2024030303 $ $RCSfile: ipdhcps6_prefix.c,v $ $Revision: 1.25.12.2 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_prefix.c,v $
* $Author: jchang1 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_list.h>
#include <ipcom_syslog.h>
#include <ipnet.h>
#include <ipnet_routesock.h>
#include "ipdhcps6.h"
#include "ipdhcps6_h.h"
#include "ipdhcps6_host.h"
#include "ipdhcps6_prefix.h"
#include "ipdhcps6_subnet.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipdhcps6_prefix_list_data_struct
{
Ipdhcps6_prefix *prefix;
int index;
}
Ipdhcps6_prefix_list_data;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_prefix_obj_hash
*===========================================================================
* Description: Returns a hash value based on a DHCP option.
* Parameters: opt - The option to return a hash value for.
* Returns:
*
*/
IP_STATIC unsigned
ipdhcps6_prefix_obj_hash(Ipdhcps6_prefix *prefix)
{
return ipcom_hash_update(prefix->key, ipcom_strlen(prefix->key), 0);
}
/*
*===========================================================================
* ipdhcps6_prefix_key_hash
*===========================================================================
* Description: Returns a hash value for a prefix key.
* Parameters: key - The prefix ID number.
* Returns:
*
*/
IP_STATIC unsigned
ipdhcps6_prefix_key_hash(char *key)
{
return ipcom_hash_update(key, ipcom_strlen(key), 0);
}
/*
*===========================================================================
* ipdhcps6_prefix_hash_cmp
*===========================================================================
* Description: Compares a hash object and a hash key for equality.
* Parameters: prefix - A prefix structure.
* key - A pointer to the search key.
* Returns: IP_TRUE if the search key matches the prefix entry.
*
*/
IP_STATIC Ip_bool
ipdhcps6_prefix_hash_cmp(Ipdhcps6_prefix *prefix, char *key)
{
return ipcom_strcmp(prefix->key, key) == 0;
}
/*
*===========================================================================
* ipdhcps6_prefix_free_cb
*===========================================================================
* Description: Frees the specified prefix.
* Parameters: prefix - A prefix structure.
* Returns:
*
*/
IP_STATIC void
ipdhcps6_prefix_free_cb(Ipdhcps6_prefix *prefix, void *unused)
{
(void) unused;
ipcom_free(prefix);
}
/*
*===========================================================================
* ipdhcps6_prefix_list_cb
*===========================================================================
* Description: Makes a deep copy of all prefix entries.
* Parameters: prefix - A prefix structure.
* Returns:
*
*/
IP_STATIC void
ipdhcps6_prefix_list_cb(Ipdhcps6_prefix *prefix, Ipdhcps6_prefix_list_data *list_data)
{
ipcom_memcpy(&list_data->prefix[list_data->index++], prefix, sizeof(Ipdhcps6_prefix));
}
/*
*===========================================================================
* ipdhcps6_prefix_get_ptr
*===========================================================================
* Description: Returns the prefix entry corrensponding to the specified key.
* Parameters: key - The ID number for the prefix to return
* Returns: The matching prefix entry or IP_NULL if no match was found.
*
*/
IP_STATIC Ipdhcps6_prefix *
ipdhcps6_prefix_get_ptr(IP_CONST char *key)
{
return ipcom_hash_get(ipdhcps6->db.prefixes, (void *) key);
}
/*
*===========================================================================
* ipdhcps6_prefix_get_ptr_from_host
*===========================================================================
* Description: Returns the prefix entry on a specific host.
* Parameters: host - The host to which this prefix must be assigned.
* prefix - The address of the prefix to find.
* prefix_len - The length of the prefix to find.
* Returns: The matching prefix entry or IP_NULL if no match was found.
*
*/
IP_STATIC Ipdhcps6_prefix *
ipdhcps6_prefix_get_ptr_from_host(Ipdhcps6_host *host,
struct Ip_in6_addr *prefix,
int prefix_len)
{
Ipdhcps6_prefix *p;
int i;
for (i = 0; i < IPDHCPS6_PREFIX_PER_USER; i++)
{
if (host->user.prefix_ids[i][0] == '\0')
continue;
p = ipdhcps6_prefix_get_ptr(host->user.prefix_ids[i]);
if (p == IP_NULL)
continue;
if (prefix_len == p->prefix_len
&& IP_IN6_ARE_ADDR_EQUAL(prefix, &p->prefix))
return p;
}
return IP_NULL;
}
/*
*===========================================================================
* ipdhcps6_prefix_add_del_rt
*===========================================================================
* Description: Adds/deletes a route to the prefix that is beeing handed out.
* Parameters: ifindex - The interface that have to be used to reach this prefix.
* prefix - The prefix that is beeing handed out.
* prefixlen - The prefix length.
* add - IP_TRUE if the route should be added, it will be deleted
* otherwise.
* Returns: IPCOM_SUCCESS - operation was successful.
* IPCOM_ERR_NO_MEMORY - could not allocate enough memory.
*
*/
IP_STATIC Ip_err
ipdhcps6_prefix_add_del_rt(int ifindex, struct Ip_in6_addr *prefix, int prefixlen , Ip_bool add)
{
struct Ip_sockaddr_in6 *gw;
struct Ip_sockaddr_in6 *net;
struct Ip_sockaddr_in6 *mask;
struct Ipnet_rt_msghdr *rtm = IP_NULL;
Ip_u16 rtm_len;
int rt_sock;
struct Ip_in6_ifreq ifreq6;
Ip_err err;
rt_sock = ipcom_socket(IP_AF_ROUTE, IP_SOCK_RAW, 0);
if (rt_sock == IP_INVALID_SOCKET)
{
IPCOM_LOG0(ERR, "Failed to open routing socket");
err = IPCOM_ERR_SOCKCALLFAILED;
/* Coverity defect fix for NEGATIVE_RETURNS */
return err;
}
(void)ipcom_if_indextoname((Ip_u32)ifindex, ifreq6.ifr_name);
if (ipcom_socketioctl(rt_sock, IP_SIOCGIFDSTADDR_IN6, &ifreq6) < 0)
/* Not a point-to-point interface or no peer address set, ignore t */
return IPCOM_SUCCESS;
/* Peer address present, route any packets destinated to the network defined
by the prefix to the PPP peer */
rtm_len = sizeof(struct Ipnet_rt_msghdr) + sizeof(struct Ip_sockaddr_in6) * 3;
rtm = ipcom_calloc(1, rtm_len);
if (rtm == IP_NULL)
{
IPCOM_LOG0(ERR, "Out of memory while adding route.");
err = IPCOM_ERR_NO_MEMORY;
goto cleanup;
}
net = (struct Ip_sockaddr_in6 *) (rtm + 1);
gw = (struct Ip_sockaddr_in6 *) (net + 1);
mask = (struct Ip_sockaddr_in6 *) (gw + 1);
rtm->rtm_msglen = rtm_len;
rtm->rtm_version = IPNET_RTM_VERSION;
rtm->rtm_type = (Ip_u8)(add ? IPNET_RTM_ADD : IPNET_RTM_DELETE);
rtm->rtm_index = (Ip_u32)ifindex;
rtm->rtm_flags = IPNET_RTF_UP | IPNET_RTF_GATEWAY | IPNET_RTF_DONE
| IPNET_RTF_MASK | IPNET_RTF_DYNAMIC;
rtm->rtm_addrs = IPNET_RTA_DST | IPNET_RTA_GATEWAY | IPNET_RTA_NETMASK;
rtm->rtm_pid = ipcom_getpid();
rtm->rtm_rmx.rmx_expire = IPCOM_ADDR_INFINITE;
/* Network */
IPCOM_SA_LEN_SET(net, sizeof(*net));
net->sin6_family = IP_AF_INET6;
IPDHCPS6_SET_IN6_ADDR(&net->sin6_addr, prefix);
/* Mask */
IPCOM_SA_LEN_SET(mask, sizeof(*mask));
mask->sin6_family = IP_AF_INET6;
ipdhcps6_create_mask(&mask->sin6_addr, prefixlen);
/* Gateway */
ipcom_memcpy(gw, &ifreq6.ifr_ifru.ifru_dstaddr, IPCOM_SA_LEN_GET(&ifreq6.ifr_ifru.ifru_dstaddr));
if (ipcom_send(rt_sock, rtm, rtm->rtm_msglen, 0) < 0)
{
IPCOM_LOG1(ERR, "Failed to send route socket message: %s",
ipcom_strerror(ipcom_errno));
}
err = IPCOM_SUCCESS;
cleanup:
ipcom_socketclose(rt_sock);
ipcom_free(rtm);
return err;
}
/*
*===========================================================================
* ipdhcps6_prefix_add_del_prefixes
*===========================================================================
* Description: Adds or deletes all prefixes that this host should get.
* Parameters: subnet - The subnet the requesting router is located at.
* host - The host entry for the requesting router.
* response_opt - Buffer to where all OPTION_IAPREFIX options
* will be copied.
* response_optlen - Length of the 'response_opt' buffer.
* bytes_written - Number of bytes written to 'opt' or the requeried
* length of 'opt' if failed with IPCOM_ERR_NO_MEMORY.
* Returns: IPCOM_SUCCESS - operation was successful.
* IPCOM_ERR_NO_MEMORY - the 'response_opt' buffer was not large enough.
*
*/
IP_STATIC Ip_err
ipdhcps6_prefix_add_del_prefixes(Ipdhcps6_subnet_entry *subnet,
Ipdhcps6_host *host,
Ipdhcps6_option_iaprefix *response_opt,
Ip_u16 response_optlen,
Ip_u16 *bytes_written,
Ip_bool add)
{
Ipdhcps6_prefix *prefix;
Ip_u16 written;
Ip_err err;
int i;
(void) subnet;
*bytes_written = 0;
for (i = 0; i < IPDHCPS6_PREFIX_PER_USER; i++)
{
if (host->user.prefix_ids[i][0] == '\0')
continue;
prefix = ipdhcps6_prefix_get_ptr(host->user.prefix_ids[i]);
if (prefix == IP_NULL)
{
IPCOM_LOG2(WARNING, "Prefix %s was specified for user %s but not found in the prefix database",
host->user.prefix_ids[i], host->user.name);
continue;
}
if (add)
{
err = ipdhcps6_option_add_iaprefix(response_opt,
(Ip_u16) (response_optlen - *bytes_written),
&written,
prefix);
if (err != IPCOM_SUCCESS)
return err;
*bytes_written += written;
response_opt = (Ipdhcps6_option_iaprefix *) ((Ip_u8 *) response_opt + written);
}
err = ipdhcps6_prefix_add_del_rt(host->ifindex, &prefix->prefix, prefix->prefix_len, add);
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipdhcps6_prefix_renew_prefixes
*===========================================================================
* Description:
* Parameters:
* Returns: IPCOM_SUCCESS - operation was successful.
* IPCOM_ERR_NO_MEMORY - the 'response_opt' buffer was not large enough.
*
*/
IP_STATIC Ip_err
ipdhcps6_prefix_renew_prefixes(Ipdhcps6_subnet_entry *subnet,
Ipdhcps6_host *host,
Ipdhcps6_option *request_ia_pd_opt,
Ipdhcps6_option_iaprefix *response_opt,
Ip_u16 response_optlen,
Ip_u16 *bytes_written)
{
Ipdhcps6_prefix *prefix;
Ipdhcps6_option_iaprefix *response_ptr;
Ipdhcps6_option_iaprefix *request_ptr;
Ipdhcps6_option_iaprefix iaprefix;
const Ip_u16 iaprefix_len = 25;
Ip_u16 id_pd_opt_len;
Ip_u16 request_offset;
Ip_u16 request_iaprefix_len;
(void)subnet;
id_pd_opt_len = (Ip_u16) (ipdhcps6_get_u16(&request_ia_pd_opt->len)
- ip_offsetof(struct Ipdhcps6_option_prefix_delegation_data, options)
- IPDHCPS6_OPTION_HDR_LEN);
ipcom_memset(&prefix, 0, sizeof(prefix));
ipdhcps6_set_u16(&iaprefix.code, IPDHCPS6_OPTION_IAPREFIX);
ipdhcps6_set_u16(&iaprefix.len, iaprefix_len);
*bytes_written = 0;
for (request_offset = 0; request_offset < id_pd_opt_len;)
{
/* Point to the IAPREFIX option to process in the reqeust */
request_ptr = (Ipdhcps6_option_iaprefix *)
((Ip_u8 *) request_ia_pd_opt->data.ia_pd.options + request_offset);
if (response_optlen < *bytes_written + iaprefix_len + IPDHCPS6_OPTION_HDR_LEN)
/* The OPTION_IAPREFIX does not fit into the response buffer */
return IPCOM_ERR_NO_MEMORY;
ipcom_memcpy(IPDHCPS6_OPTION_IAPREFIX_GET_PREFIX_PTR(&iaprefix),
IPDHCPS6_OPTION_IAPREFIX_GET_PREFIX_PTR(request_ptr),
sizeof(struct Ip_in6_addr));
IPDHCPS6_OPTION_IAPREFIX_SET_LEN(&iaprefix, IPDHCPS6_OPTION_IAPREFIX_GET_LEN(request_ptr));
prefix = ipdhcps6_prefix_get_ptr_from_host(host,
IPDHCPS6_OPTION_IAPREFIX_GET_PREFIX_PTR(&iaprefix),
IPDHCPS6_OPTION_IAPREFIX_GET_LEN(&iaprefix));
if (prefix == IP_NULL)
{
/* This prefix is no longer used by the subnet */
iaprefix.preferred_lifetime = 0;
iaprefix.valid_lifetime = 0;
}
else
{
/* Extend the lifetime another period */
ipdhcps6_set_u32(&iaprefix.preferred_lifetime, prefix->preferred);
ipdhcps6_set_u32(&iaprefix.valid_lifetime, prefix->valid);
}
/* Point to where the this IAPREFIX should be written into the response buffer */
response_ptr = (Ipdhcps6_option_iaprefix *) ((Ip_u8 *) response_opt + *bytes_written);
/* Add the option to the response */
ipcom_memcpy(response_ptr, &iaprefix, iaprefix_len + IPDHCPS6_OPTION_HDR_LEN);
*bytes_written += iaprefix_len + IPDHCPS6_OPTION_HDR_LEN;
/* Move to the next IAPREFIX in the reqeust buffer */
request_iaprefix_len = ipdhcps6_get_u16(&request_ptr->len);
request_offset += request_iaprefix_len + IPDHCPS6_OPTION_HDR_LEN;
}
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_prefix_process_request
*===========================================================================
* Description: Adds prefix to the requesting router (using OPTION_IA_PD).
* Parameters: msg - The message type in the request.
* host - The entry for the requesting router.
* opt - The OPTION_IA_PD option sent by the requesting router.
* response_opt - Pointer into the response buffer where the
* OPTION_IA_PD options containing the prefixes should be written.
* response_optlen - The length of the 'reponse_opt'
* bytes_written - Number of bytes written to 'opt' or the requeried
* length of 'opt' if failed with IPCOM_ERR_NO_MEMORY.
* Returns: IPCOM_SUCCESS - operation was successful.
* IPCOM_ERR_NO_MEMORY - the 'response_opt'. was to small.
*
*/
IP_GLOBAL Ip_err
ipdhcps6_prefix_process_request(Ip_u16 msg_type,
Ipdhcps6_subnet_entry *subnet,
Ipdhcps6_host *host,
Ipdhcps6_option *opt,
Ipdhcps6_option *response_opt,
Ip_u16 response_optlen,
Ip_u16 *bytes_written)
{
Ip_u16 ia_pd_opt_len;
Ipdhcps6_option_iaprefix *iaprefix;
Ip_err err;
Ip_u16 hdr_len;
*bytes_written = 0;
ia_pd_opt_len = ipdhcps6_get_u16(&opt->len);
hdr_len = ip_offsetof(struct Ipdhcps6_option_prefix_delegation_data, options);
if (ia_pd_opt_len != hdr_len)
{
if (ia_pd_opt_len < hdr_len
|| ipdhcps6_option_check((Ipdhcps6_option *) opt->data.ia_pd.options,
(Ip_u16) (ia_pd_opt_len - hdr_len)))
{
/* Error in length field in the OPTION_IA_PD option, drop the message */
return IPCOM_ERR_FAILED;
}
}
if (subnet == IP_NULL)
{
/* No configuration for the subnet the requesting router is located at */
return ipdhcps6_option_add_status_code(response_opt, response_optlen,
bytes_written, IPDHCPS6_CODE_NO_PREFIX_AVAIL,
"No configuration create for the subnet from where the request originates.");
}
if (ipdhcps6_host_has_prefix(host) == IP_FALSE)
{
return ipdhcps6_option_add_status_code(response_opt, response_optlen,
bytes_written, IPDHCPS6_CODE_NO_PREFIX_AVAIL,
"The host has not been given any prefixes.");
}
ia_pd_opt_len = ip_offsetof(struct Ipdhcps6_option_prefix_delegation_data, options);
if (response_optlen < ia_pd_opt_len + IPDHCPS6_OPTION_HDR_LEN)
/* Not the response buffer is not big enough to hold the IPDHCPS6_OPTION_IA_PD header */
return IPCOM_ERR_NO_MEMORY;
/* Add the IPDHCPS6_OPTION_IA_PD header */
ipdhcps6_set_u16(&response_opt->code, IPDHCPS6_OPTION_IA_PD);
ipcom_memcpy(&response_opt->data.ia_pd.iaid, opt->data.ia_pd.iaid, sizeof(response_opt->data.ia_pd.iaid));
/* Let the client calculate the T1 and T2 times */
ipdhcps6_set_u32(&response_opt->data.ia_pd.t1, 0);
ipdhcps6_set_u32(&response_opt->data.ia_pd.t2, 0);
response_optlen -= ia_pd_opt_len + IPDHCPS6_OPTION_HDR_LEN;
/* Pointer to where the first IPDHCPS6_OPTION_IAPREFIX should be written */
iaprefix = response_opt->data.ia_pd.options;
switch (msg_type)
{
case IPDHCPS6_MSG_SOLICIT:
case IPDHCPS6_MSG_REQUEST:
err = ipdhcps6_prefix_add_del_prefixes(subnet, host, iaprefix, response_optlen, bytes_written, IP_TRUE);
break;
case IPDHCPS6_MSG_RELEASE:
err = ipdhcps6_prefix_add_del_prefixes(subnet, host, iaprefix, response_optlen, bytes_written, IP_FALSE);
break;
case IPDHCPS6_MSG_RENEW:
case IPDHCPS6_MSG_REBIND:
err = ipdhcps6_prefix_renew_prefixes(subnet, host, opt, iaprefix, response_optlen, bytes_written);
break;
default:
/* This message type should not forward here */
return IPCOM_ERR_INVALID_ARG;
}
*bytes_written += ia_pd_opt_len;
ipdhcps6_set_u16(&response_opt->len, *bytes_written);
*bytes_written += IPDHCPS6_OPTION_HDR_LEN;
return err;
}
/*
*===========================================================================
* ipdhcps6_prefix_new_db
*===========================================================================
* Description: Deletes all elements in the subnet database, memory for
* the route table holding the entries is also deleted.
* Parameters: subnets - The subnet database to delete.
* Returns:
*
*/
IP_GLOBAL Ipcom_hash *
ipdhcps6_prefix_new_db(void)
{
return ipcom_hash_new((Ipcom_hash_obj_func) ipdhcps6_prefix_obj_hash,
(Ipcom_hash_key_func) ipdhcps6_prefix_key_hash,
(Ipcom_hash_cmp_func) ipdhcps6_prefix_hash_cmp);
}
/*
*===========================================================================
* ipdhcps6_prefix_delete_db
*===========================================================================
* Description: Frees all prefix entries in the list.
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipdhcps6_prefix_delete_db(Ipcom_hash *prefix_db)
{
if(prefix_db != IP_NULL)
{
ipcom_hash_for_each(prefix_db,
(Ipcom_hash_foreach_cb_func) ipdhcps6_prefix_free_cb,
IP_NULL);
ipcom_hash_delete(prefix_db);
}
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_prefix_add
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_prefix_add(Ipdhcps6_prefix *prefix)
{
Ipdhcps6_prefix *p = IP_NULL;
Ip_err err;
if (ipdhcps6 == IP_NULL || IP_BIT_ISFALSE(ipdhcps6->flags, IPDHCPS6_FLAG_OPEN))
return IPCOM_ERR_NOT_OPENED;
ipcom_mutex_lock(ipdhcps6->db.mutex);
if (ipdhcps6_prefix_get_ptr(prefix->key) != IP_NULL)
{
err = IPCOM_ERR_DUPLICATE;
goto errout;
}
p = ipcom_malloc(sizeof(Ipdhcps6_prefix));
if (p == IP_NULL)
{
err = IPCOM_ERR_NO_MEMORY;
goto errout;
}
ipcom_memcpy(p, prefix, sizeof(Ipdhcps6_prefix));
if ((err = ipcom_hash_add(ipdhcps6->db.prefixes, p)) != IPCOM_SUCCESS)
goto errout;
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_SUCCESS;
errout:
ipcom_free(p);
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return err;
}
/*
*===========================================================================
* ipdhcps6_subnet_delete
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_prefix_delete(Ipdhcps6_prefix *prefix)
{
Ipdhcps6_prefix *p;
Ip_err err = IPCOM_SUCCESS;
if (ipdhcps6 == IP_NULL || IP_BIT_ISFALSE(ipdhcps6->flags, IPDHCPS6_FLAG_OPEN))
return IPCOM_ERR_NOT_OPENED;
ipcom_mutex_lock(ipdhcps6->db.mutex);
if ((p = ipdhcps6_prefix_get_ptr(prefix->key)) == IP_NULL)
{
err = IPCOM_ERR_NOT_FOUND;
goto cleanup;
}
(void) ipcom_hash_remove(ipdhcps6->db.prefixes, p);
ipcom_free(p);
cleanup:
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return err;
}
/*
*===========================================================================
* ipdhcps6_subnet_list
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_prefix_list(Ipdhcps6_prefix prefix[], int *num_elem)
{
Ipdhcps6_prefix_list_data cb_data;
if (ipdhcps6 == IP_NULL || IP_BIT_ISFALSE(ipdhcps6->flags, IPDHCPS6_FLAG_OPEN))
return IPCOM_ERR_NOT_OPENED;
ipcom_mutex_lock(ipdhcps6->db.mutex);
if (prefix == IP_NULL)
{
*num_elem = (int)ipdhcps6->db.prefixes->elem;
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_SUCCESS;
}
if (*num_elem < (int) ipdhcps6->db.prefixes->elem)
{
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_ERR_NO_MEMORY;
}
*num_elem = (int)ipdhcps6->db.prefixes->elem;
cb_data.prefix = prefix;
cb_data.index = 0;
ipcom_hash_for_each(ipdhcps6->db.prefixes,
(Ipcom_hash_foreach_cb_func) ipdhcps6_prefix_list_cb,
&cb_data);
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,96 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcps6_prefix.h,v $ $Revision: 1.2.56.1 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_prefix.h,v $
* $Author: ulf $ $Date: 2011-11-16 10:33:28 $
* $State: Exp $ $Locker: $
*
* Copyright Interpeak AB 2000-2002 <www.interpeak.se>. All rights reserved.
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#ifndef IPDHCPS6_PREFIX_H
#define IPDHCPS6_PREFIX_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_list.h>
#include "ipdhcps6.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/* Forward declarations */
struct Ipdhcps6_subnet_entry_struct;
struct Ipdhcps6_host_struct;
struct Ipdhcps6_option_struct;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_err
ipdhcps6_prefix_process_request(Ip_u16 msg_type,
struct Ipdhcps6_subnet_entry_struct *subnet,
struct Ipdhcps6_host_struct *host,
struct Ipdhcps6_option_struct *opt,
struct Ipdhcps6_option_struct *response_opt,
Ip_u16 response_optlen,
Ip_u16 *bytes_written);
IP_GLOBAL Ipcom_hash *
ipdhcps6_prefix_new_db(void);
IP_GLOBAL void
ipdhcps6_prefix_delete_db(Ipcom_hash *prefix_db);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,525 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcps6_relay.c,v $ $Revision: 1.13 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_relay.c,v $
* $Author: fguo $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_inet.h>
#include <ipcom_sock.h>
#include <ipcom_sock6.h>
#include <ipcom_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipnet_routesock.h>
#include "ipdhcps6_h.h"
#include "ipdhcps6_msg.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_relay_route_init_addrs
*===========================================================================
* Description: Sets the address pointer to point to the correct entry
* in the 'rt' buffer.
* Parameters: msg - The first socket address in the route socket message.
* addrs - The IPNET_RTA_xxx from the message.
* sas - Will contain the route pointer.
* Returns:
*
*/
IP_STATIC void
ipdhcps6_relay_route_init_addrs(void *msg, Ip_u32 addrs, struct Ip_sockaddr_in6 **sas)
{
int i;
Ip_size_t offset = 0;
for (i = 0; i < IPNET_RTAX_MAX; i++)
{
if (IP_BIT_ISSET(addrs, 1 << i))
{
sas[i] = (struct Ip_sockaddr_in6 *) &((Ip_u8 *) msg)[offset];
offset += IPCOM_SA_LEN_GET(sas[i]);
}
else
sas[i] = IP_NULL;
}
}
/*
*===========================================================================
* ipdhcps6_relay_get_scope_weight
*===========================================================================
* Description: Return relative scope.
* Parameters: addr - An IPv6 address
* Returns: An integer where bigger value means higher scope.
*
*/
IP_STATIC int
ipdhcps6_relay_get_scope_weight(IP_CONST struct Ip_in6_addr *addr)
{
if (IP_IN6_IS_ADDR_AGGR_GLOB_UNICAST(addr))
return 2;
if (IP_IN6_IS_ADDR_SITE_LOCAL(addr))
return 1;
if (IP_IN6_IS_ADDR_LINK_LOCAL(addr) || IP_IN6_IS_ADDR_UNSPECIFIED(addr))
return 0;
return -1;
}
/*
*===========================================================================
* ipdhcps6_relay_get_link_address
*===========================================================================
* Description: Returns the interface address with the broadest scope on the
* specified link.
* Parameters: ifindex - Interface index of a local interface.
* link_addr - Buffer where the link local address will
* be stored.
* Returns: 0 = success
* -1 = address could not be returned
*
*/
IP_STATIC int
ipdhcps6_relay_get_link_address(Ip_u32 ifindex, struct Ip_in6_addr *link_addr)
{
int name[6];
int ret = -1;
Ip_u8 *if_data = IP_NULL;
struct Ipnet_ifa_msghdr *ifa;
struct Ipnet_if_msghdr *ifm;
struct Ip_sockaddr_in6 *addrs[IPNET_RTAX_MAX];
Ip_size_t if_data_len;
Ip_size_t if_data_offset;
Ip_size_t offset;
int scope_weight;
IP_CONST struct Ip_in6_addr *selected_addr = &ip_in6addr_any;
/* Find out our link local address on this interface */
name[0] = IP_CTL_NET;
name[1] = IP_AF_ROUTE;
name[2] = 0;
name[3] = IP_AF_INET6;
name[4] = IP_NET_RT_IFLIST;
name[5] = (int)ifindex;
if (ipcom_sysctl(name, 6, IP_NULL, &if_data_len, IP_NULL, 0) < 0)
{
IPCOM_LOG1(ERR, "ipdhcps6_relay_get_link_address: ipcom_sysctl() failed: %s",
ipcom_strerror(ipcom_errno));
goto cleanup;
}
if_data = ipcom_malloc(if_data_len);
if (if_data == IP_NULL)
{
IPCOM_LOG0(ERR, "ipdhcps6_relay_get_link_address: out of memory");
goto cleanup;
}
if (ipcom_sysctl(name, 6, if_data, &if_data_len, IP_NULL, 0) < 0)
{
IPCOM_LOG1(ERR, "ipdhcps6_relay_get_link_address: ipcom_sysctl() failed: %s",
ipcom_strerror(ipcom_errno));
ret = -1;
goto cleanup;
}
ifm = (struct Ipnet_if_msghdr *) &if_data[0];
if_data_offset = ifm->ifm_msglen;
offset = 0;
while (offset < if_data_len - if_data_offset)
{
ifa = (struct Ipnet_ifa_msghdr *) &if_data[if_data_offset + offset];
ipdhcps6_relay_route_init_addrs(ifa + 1, ifa->ifam_addrs, addrs);
offset += ifa->ifam_msglen;
scope_weight = ipdhcps6_relay_get_scope_weight(&addrs[IPNET_RTAX_IFA]->sin6_addr);
if (scope_weight > ipdhcps6_relay_get_scope_weight(selected_addr))
/* This address has broader scope the last selected address */
selected_addr = &addrs[IPNET_RTAX_IFA]->sin6_addr;
}
if (selected_addr == IP_NULL)
{
IPCOM_LOG1(INFO, "ipdhcps6_relay_get_link_address: no address found address on interface %u using ::",
ifindex);
selected_addr = &ip_in6addr_any;
}
IPDHCPS6_SET_IN6_ADDR(link_addr, selected_addr);
ret = 0;
cleanup:
ipcom_free(if_data);
return ret;
}
/*
*===========================================================================
* ipdhcps6_relay_get_next_hop_addr
*===========================================================================
* Description: Sets the IPv6 address and UDP port of the next hop server/relay.
* Parameters: ifindex - The interface the request was received at.
* response_addr - Will contain the response address.
* response_ifindex - Will be set if 'response_addr' contains a
* multicast address.
* Returns:
*
*/
IP_STATIC Ip_err
ipdhcps6_relay_get_next_hop_addr(Ip_u32 ifindex,
struct Ip_sockaddr_in6 *response_addr,
Ip_u32 *response_ifindex)
{
char *sysvar_name = ipdhcps6->addr_str;
char *ifname;
char next_hop_addr[IP_INET6_ADDRSTRLEN];
Ip_size_t next_hop_addr_size = sizeof(next_hop_addr);
ipcom_strcpy(sysvar_name, "ipdhcps6.relay.map.");
ifname = sysvar_name + ipcom_strlen(sysvar_name);
if (ipcom_if_indextoname(ifindex, ifname) == IP_NULL)
/* The interface has been detached */
return IPCOM_ERR_FAILED;
if (ipcom_sysvar_get(sysvar_name, next_hop_addr, &next_hop_addr_size)
== IP_NULL)
{
IPCOM_LOG1(INFO,
"Did not relay message since no relay mapping was specified for interface %d",
ifindex);
return IPCOM_ERR_FAILED;
}
*response_ifindex = ipcom_if_nametoindex(next_hop_addr);
if (*response_ifindex)
/* The next hop address was an interface name */
IPDHCPS6_SET_IN6_ADDR(&response_addr->sin6_addr,
&ipdhcps6_all_dhcp_servers);
else if (ipcom_getsockaddrbyaddr(IP_AF_INET6,
next_hop_addr,
(struct Ip_sockaddr *) response_addr) < 0)
{
IPCOM_LOG1(INFO,
"'%s' is not a valid unicast IPv6 address, discarding message",
response_addr);
return IPCOM_ERR_FAILED;
}
response_addr->sin6_port = ip_htons(ipdhcps6_server_port);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipdhcps6_relay_do_forward
*===========================================================================
* Description: Relays a request from a client or another relay agent.
* Parameters: msg - The received message, will contain the reply if such
* should be sent.
* hop_count - The number of times the request has already been
* forwarded.
* Returns: IPCOM_SUCCESS - message was processed successfully (dropped
* messages also counts as successful processing).
* IPCOM_ERR_FAILED - critical error encountered.
*
*/
IP_STATIC Ip_err
ipdhcps6_relay_do_forward(Ipdhcps6_message *msg, Ip_u8 hop_count)
{
Ipdhcps6_relay_msg_hdr *relay_msg;
Ip_u16 opts_buf_len;
Ipdhcps6_option *opt;
Ip_u16 bytes_written;
Ip_err err;
if (hop_count >= ipdhcps6->hop_count_limit)
{
IPCOM_LOG2(INFO, "Discarding message since the hop count (%u) is too high (%u)",
hop_count, ipdhcps6->hop_count_limit);
return IPCOM_SUCCESS;
}
if (msg->recv_buf_len + IPDHCP_RELAY_MSG_HDR_LEN + 8
> IPDHCPS6_RECV_BUF_SIZE)
{
IPCOM_LOG1(WARNING,
"Discarding message since it is too big to be relayed, increase IPDHCPS6_RECV_BUF_SIZE (%d)",
IPDHCPS6_RECV_BUF_SIZE);
return IPCOM_SUCCESS;
}
err = ipdhcps6_relay_get_next_hop_addr(msg->ifindex,
&msg->response_addr,
&msg->response_ifindex);
if (err != IPCOM_SUCCESS)
return err;
/* Fix for WIND00195425 start */
if (IP_TRUE == IP_IN6_IS_ADDR_MULTICAST(&msg->response_addr.sin6_addr))
{
msg->mhop_limit = IP_TRUE;
}
/* Fix for WIND00195425 end */
/* Add a relay header */
relay_msg = (Ipdhcps6_relay_msg_hdr *) msg->send_buf;
relay_msg->type = IPDHCPS6_MSG_RELAY_FORW;
if (IPDHCPS6_MSG_RELAY_FORW == ((Ipdhcps6_relay_msg_hdr *) msg->recv_buf)->type)
{
relay_msg->hop_count = hop_count + 1;
}
else
{
/* If the relay agent received the message to be relayed from a client,
* the hop-count in the Relay-forward message is set to 0 (defect WIND00190002)
*/
relay_msg->hop_count = 0;
}
ipdhcps6_relay_get_link_address(msg->ifindex, &relay_msg->link_addr);
IPDHCPS6_SET_IN6_ADDR(&relay_msg->peer_addr,
&msg->peer_addr.sin6_addr);
ipdhcps6_msg_first_response_opt(msg, &opt, &opts_buf_len);
err = ipdhcps6_option_add_relay_message(opt,
opts_buf_len,
&bytes_written,
msg->recv_buf,
msg->recv_buf_len);
if (err != IPCOM_SUCCESS)
return err;
ipdhcps6_msg_next_response_opt(bytes_written,
msg,
&opt,
&opts_buf_len);
err = ipdhcps6_option_add_interface_id(opt,
opts_buf_len,
&bytes_written,
msg->ifindex);
if (err != IPCOM_SUCCESS)
return err;
ipdhcps6_msg_next_response_opt(bytes_written,
msg,
&opt,
&opts_buf_len);
msg->send_response = IP_TRUE;
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_relay_do_forward_client
*===========================================================================
* Description: Relays a request from a client.
* Parameters: msg - The received message, will contain the reply if such
* should be sent.
* Returns: IPCOM_SUCCESS - message was processed successfully (dropped
* messages also counts as successful processing).
* IPCOM_ERR_FAILED - critical error encountered.
*
*/
IP_GLOBAL Ip_err
ipdhcps6_relay_do_forward_client(Ipdhcps6_message *msg)
{
return ipdhcps6_relay_do_forward(msg, 0);
}
/*
*===========================================================================
* ipdhcps6_relay_do_forward_relay
*===========================================================================
* Description: Relays a request from another relay agent.
* Parameters: msg - The received message, will contain the reply if such
* should be sent.
* Returns: IPCOM_SUCCESS - message was processed successfully (dropped
* messages also counts as successful processing).
* IPCOM_ERR_FAILED - critical error encountered.
*
*/
IP_GLOBAL Ip_err
ipdhcps6_relay_do_forward_relay(Ipdhcps6_message *msg)
{
Ipdhcps6_relay_msg_hdr *recv_relay_msg;
recv_relay_msg = (Ipdhcps6_relay_msg_hdr *) msg->recv_buf;
return ipdhcps6_relay_do_forward(msg, recv_relay_msg->hop_count);
}
/*
*===========================================================================
* ipdhcps6_relay_process_reply
*===========================================================================
* Description: Processes a response on a previously relayed message.
* Parameters: msg - The received message, will contain the reply if such
* should be sent.
* in_opts - Points to the first option included in the incoming
* message. All options are packed into this buffer without padding.
* in_opts_len - The length of all options in the buffer pointer to
* by 'in_opts'.
* Returns: IPCOM_SUCCESS - message was processed successfully (dropped
* messages also counts as successful processing).
* IPCOM_ERR_FAILED - critical error encountered.
*
*/
IP_GLOBAL Ip_err
ipdhcps6_relay_process_reply(Ipdhcps6_message *msg,
Ipdhcps6_option *in_opts,
Ip_u16 in_opts_len)
{
Ipdhcps6_relay_msg_hdr *relay_msg = (Ipdhcps6_relay_msg_hdr *) msg->recv_buf;
Ipdhcps6_option *relay_message_opt;
Ipdhcps6_option *interface_id_opt;
relay_message_opt = ipdhcps6_option_get_ptr(in_opts,
in_opts_len,
IPDHCPS6_OPTION_RELAY_MSG);
interface_id_opt = ipdhcps6_option_get_ptr(in_opts,
in_opts_len,
IPDHCPS6_OPTION_INTERFACE_ID);
if (relay_message_opt == IP_NULL || interface_id_opt == IP_NULL)
{
/* This relay always includes the interface ID option */
IPCOM_LOG0(INFO,
"Ignoring relay-reply packet since it does not contain a "
"relay message option and interface ID option");
return IPCOM_ERR_IGNORED_PACKET;
}
if (ipdhcps6_get_u16(&interface_id_opt->len) != sizeof(Ip_u32))
{
/* This relay always includes the interface ID option */
IPCOM_LOG0(INFO,
"Ignoring relay-reply packet since the length of the interface ID options is not 4");
return IPCOM_ERR_IGNORED_PACKET;
}
msg->send_buf_len = ipdhcps6_get_u16(&relay_message_opt->len);
ip_assert(msg->send_buf_len <= msg->send_buf_maxlen);
ipcom_memcpy(msg->send_buf,
&relay_message_opt->data,
msg->send_buf_len);
msg->response_ifindex = ipdhcps6_get_u32((Ip_u32 *) &interface_id_opt->data);
IPDHCPS6_SET_IN6_ADDR(&msg->response_addr.sin6_addr, &relay_msg->peer_addr);
if (IP_IN6_IS_ADDR_LINK_LOCAL(&msg->response_addr.sin6_addr))
msg->response_addr.sin6_scope_id = msg->response_ifindex;
else
msg->response_addr.sin6_scope_id = 0;
/* Don't change port if we're forwarding to another relay */
if (((Ipdhcps6_msg_hdr *) msg->send_buf)->type == IPDHCPS6_MSG_RELAY_REPL)
msg->response_addr.sin6_port = ip_htons(ipdhcps6_server_port);
else
msg->response_addr.sin6_port = ip_htons(ipdhcps6_client_port);
msg->send_response = IP_TRUE;
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,512 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_RCPL8_2024030303 $ $RCSfile: ipdhcps6_subnet.c,v $ $Revision: 1.23.18.1 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_subnet.c,v $
* $Author: jchang1 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_list.h>
#include <ipcom_hash.h>
#include <ipcom_route.h>
#include <ipcom_syslog.h>
#include <ipnet.h>
#include "ipdhcps6.h"
#include "ipdhcps6_h.h"
#include "ipdhcps6_subnet.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
struct Ipdhcps6_subnet_list_cb_data
{
/* The result of the operation */
Ip_err err;
/* Number of elements in the route table */
int num_elements;
/* The size of the 'subnets' array */
int subnet_elements;
/* Array of subnet structures, can be IP_NULL in which case the number
of elements is stored in 'num_elements' */
Ipdhcps6_subnet *subnets;
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_subnet_notify_func
*===========================================================================
* Description: Handles callbacks from the subnet table.
* Parameters: rtab - The table head.
* e - The entry that caused this function to be called.
* code - The reason why this function was called.
* Returns:
*
*/
IP_STATIC void
ipdhcps6_subnet_notify_func(Ipcom_route *rtab, Ipdhcps6_subnet_entry *sn, int code)
{
(void) rtab;
if (code == IPCOM_ROUTE_CODE_REMOVE || code == IPCOM_ROUTE_CODE_DUPLICATE)
{
ipdhcps6_option_delete_db(sn->options);
ipdhcps6_pool_delete_from_subnet(sn);
ipcom_free(sn);
}
}
/*
*===========================================================================
* ipdhcps6_subnet_delete_db
*===========================================================================
* Description: Deletes all elements in the subnet database, memory for
* the route table holding the entries is also deleted.
* Parameters: subnets - The subnet database to delete.
* Returns:
*
*/
IP_STATIC Ip_bool
ipdhcps6_subnet_list_cb(Ipdhcps6_subnet_entry *sn,
struct Ipdhcps6_subnet_list_cb_data *data)
{
int i;
i = data->num_elements++;
if (data->subnets == IP_NULL)
return IP_FALSE;
if (data->num_elements > data->subnet_elements)
{
data->err = IPCOM_ERR_NO_MEMORY;
return IP_FALSE;
}
ipcom_memcpy(&data->subnets[i], &sn->subnet, sizeof(sn->subnet));
data->subnets[i].prefix = sn->subnet.addr;
data->subnets[i].ifindex = (Ip_u32)sn->subnet.ifindex;
data->subnets[i].prefix_len = sn->prefix_len;
return IP_FALSE;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_create_mask
*===========================================================================
* Description: Creates a mask which contains 'netbits' number of '1' bits
* staring with the most significant bit.
* Parameters: mask - Mask buffer.
* netbits - Number of bits.
* Returns:
*
*/
IP_GLOBAL void
ipdhcps6_create_mask(struct Ip_in6_addr *mask, int netbits)
{
int i;
int j;
for (i = 0; i < netbits / 8; i++)
mask->in6.addr8[i] = 0xff;
for (j = 0; j < netbits % 8; j++)
IP_BIT_SET(mask->in6.addr8[i], 0x80 >> j);
}
/*
*===========================================================================
* ipdhcps6_subnet_get_from_addr
*===========================================================================
* Description: Returns the subnet entry matching the sender of this message
* (DHCPv6 client address, not relay address).
* Parameters: addr - The address of the requesting DHCPv6 client.
* ifindex - The interface this message was received on.
* Returns: The matching subnet or IP_NULL if no match was found.
*
*/
IP_GLOBAL Ipdhcps6_subnet_entry *
ipdhcps6_subnet_get_from_addr(struct Ip_in6_addr *addr, int ifindex)
{
Ipdhcps6_subnet_key key;
IPDHCPS6_SET_IN6_ADDR(&key.addr, addr);
key.ifindex = ifindex;
return (Ipdhcps6_subnet_entry *)
ipcom_route_lookup(ipdhcps6->db.subnets, &key, IP_NULL);
}
/*
*===========================================================================
* ipdhcps6_subnet_get
*===========================================================================
* Description: Returns the subnet entry matching the sender of this message
* (DHCPv6 client address, not relay address).
* Parameters: addr - The address of the requesting DHCPv6 client.
* ifindex - The interface this message was received on.
* Returns: The matching subnet or IP_NULL if no match was found.
*
*/
IP_GLOBAL Ipdhcps6_subnet_entry *
ipdhcps6_subnet_get(struct Ip_in6_addr *subnet, int ifindex)
{
Ip_bool perfect_match;
Ipdhcps6_subnet_entry *sn;
Ipdhcps6_subnet_key key;
IPDHCPS6_SET_IN6_ADDR(&key.addr, subnet);
key.ifindex = ifindex;
sn = (Ipdhcps6_subnet_entry *)
ipcom_route_lookup(ipdhcps6->db.subnets, &key, &perfect_match);
if (sn != IP_NULL && perfect_match)
return sn;
return IP_NULL;
}
/*
*===========================================================================
* ipdhcps6_subnet_new_db
*===========================================================================
* Description: Creates a new radix tree to store subnet entries in.
* Parameters:
* Returns: A empty radix tree.
*
*/
IP_GLOBAL Ipcom_route *
ipdhcps6_subnet_new_db(void)
{
return ipcom_route_new_table(sizeof(Ipdhcps6_subnet_key) * 8,
(Ipcom_route_notify_func) ipdhcps6_subnet_notify_func);
}
/*
*===========================================================================
* ipdhcps6_subnet_remove_subnets
*===========================================================================
* Description: Remove all subnets in radix tree.
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipdhcps6_subnet_remove_subnets(void)
{
struct Ip_if_nameindex *ni;
int i;
Ipdhcps6_subnet subnet;
ni = ipcom_if_nameindex();
if (ni == IP_NULL)
{
return IPCOM_ERR_FAILED;
}
for (i = 0; ni[i].if_index != 0; i++)
{
ipdhcps6_subnet_from_ifindex(&subnet, ni[i].if_index);
ipdhcps6_subnet_delete(&subnet);
}
ipcom_if_freenameindex(ni);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipdhcps6_subnet_delete_db
*===========================================================================
* Description: Deletes all elements in the subnet database, memory for
* the route table holding the entries is also deleted.
* Parameters: subnets - The subnet database to delete.
* Returns:
*
*/
IP_GLOBAL void
ipdhcps6_subnet_delete_db(Ipcom_route *subnets)
{
if (subnets != IP_NULL)
ipcom_route_free_table(subnets);
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_subnet_from_ifname
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC void
ipdhcps6_subnet_from_ifindex(Ipdhcps6_subnet *subnet,
Ip_u32 ifindex)
{
/* The link local addresses are defined by the fe80::/10
prefix in RFC 3315 chapter 4.1 */
(void)ipcom_inet_pton(IP_AF_INET6, "fe80::", &subnet->prefix);
subnet->ifindex = ifindex;
subnet->prefix_len = 10;
}
/*
*===========================================================================
* ipdhcps6_subnet_add
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_subnet_add(Ipdhcps6_subnet *subnet)
{
Ipdhcps6_subnet_entry *sn_entry;
char str[40];
if (ipdhcps6 == IP_NULL || IP_BIT_ISFALSE(ipdhcps6->flags, IPDHCPS6_FLAG_OPEN))
return IPCOM_ERR_NOT_OPENED;
ipcom_mutex_lock(ipdhcps6->db.mutex);
if (ipdhcps6_subnet_get(&subnet->prefix, (int)subnet->ifindex) != IP_NULL)
{
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_ERR_DUPLICATE;
}
sn_entry = ipcom_calloc(1, sizeof(*sn_entry));
if (sn_entry == IP_NULL)
goto out_of_memory;
sn_entry->subnet.addr = subnet->prefix;
sn_entry->subnet.ifindex = (int)subnet->ifindex;
sn_entry->hdr.key = &sn_entry->subnet;
sn_entry->hdr.mask = &sn_entry->mask;
sn_entry->prefix_len = subnet->prefix_len;
if (IP_IN6_IS_ADDR_LINK_LOCAL(&subnet->prefix))
sn_entry->mask.ifindex = ~0u;
else
sn_entry->mask.ifindex = 0;
ipdhcps6_create_mask(&sn_entry->mask.addr, subnet->prefix_len);
sn_entry->options = ipdhcps6_option_new_db();
if (sn_entry->options == IP_NULL)
goto out_of_memory;
if (ipcom_route_add(ipdhcps6->db.subnets, &sn_entry->hdr) != IPCOM_SUCCESS)
goto out_of_memory;
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_SUCCESS;
out_of_memory:
ipcom_mutex_unlock(ipdhcps6->db.mutex);
if (sn_entry != IP_NULL)
{
if (sn_entry->options != IP_NULL)
ipcom_hash_delete(sn_entry->options);
ipcom_free(sn_entry);
}
IPCOM_LOG1(CRIT, "Out of memory when adding subnet %s",
ipcom_inet_ntop(IP_AF_INET6, &subnet->prefix, str, sizeof(str)));
return IPCOM_ERR_NO_MEMORY;
}
/*
*===========================================================================
* ipdhcps6_subnet_delete
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_subnet_delete(Ipdhcps6_subnet *subnet)
{
Ip_bool perfect_match;
Ipcom_route_entry *sn_elem;
Ipdhcps6_subnet_key key;
if (ipdhcps6 == IP_NULL || !IP_BIT_ISSET(ipdhcps6->flags, IPDHCPS6_FLAG_OPEN))
return IPCOM_ERR_NOT_OPENED;
ipcom_mutex_lock(ipdhcps6->db.mutex);
key.addr = subnet->prefix;
key.ifindex = (int)subnet->ifindex;
sn_elem = ipcom_route_lookup(ipdhcps6->db.subnets, &key, &perfect_match);
if (sn_elem == IP_NULL || perfect_match == IP_FALSE)
{
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_ERR_NOT_FOUND;
}
(void) ipcom_route_remove(ipdhcps6->db.subnets, sn_elem);
ipcom_mutex_unlock(ipdhcps6->db.mutex);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipdhcps6_subnet_delete
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_subnet_list(Ipdhcps6_subnet subnets[], int *num_subnets)
{
struct Ipdhcps6_subnet_list_cb_data cb_data;
if (ipdhcps6 == IP_NULL || !IP_BIT_ISSET(ipdhcps6->flags, IPDHCPS6_FLAG_OPEN))
return IPCOM_ERR_NOT_OPENED;
cb_data.num_elements = 0;
cb_data.subnet_elements = *num_subnets;
cb_data.subnets = subnets;
cb_data.err = IPCOM_SUCCESS;
ipcom_route_walk_tree(ipdhcps6->db.subnets,
(Ip_bool(*)(Ipcom_route_entry *, void *)) ipdhcps6_subnet_list_cb,
&cb_data);
*num_subnets = cb_data.num_elements;
return cb_data.err;
}
/*
*===========================================================================
* ipdhcps6_subnet_to_string
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipdhcps6_subnet_to_string(const Ipdhcps6_subnet *subnet, char *str, int str_len)
{
int ret;
char ifname[IP_IFNAMSIZ];
char addr[40];
if (IP_IN6_IS_ADDR_LINK_LOCAL(&subnet->prefix))
ret = ipcom_snprintf(str, (Ip_size_t)str_len, "%s (%s/%d)",
ipcom_if_indextoname(subnet->ifindex, ifname),
ipcom_inet_ntop(IP_AF_INET6, &subnet->prefix, addr, sizeof(addr)),
subnet->prefix_len);
else
ret = ipcom_snprintf(str, (Ip_size_t)str_len, "%s/%d",
ipcom_inet_ntop(IP_AF_INET6, &subnet->prefix, addr, sizeof(addr)),
subnet->prefix_len);
if (ret < 0)
return IPCOM_ERR_NO_MEMORY;
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,122 @@
/*
******************************************************************************
* INTERPEAK API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_RCPL8_2024030303 $ $RCSfile: ipdhcps6_subnet.h,v $ $Revision: 1.4.36.1 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_subnet.h,v $
* $Author: jchang1 $ $Date: 2022-09-22 09:39:18 $
* $State: Exp $ $Locker: $
*
* Copyright Interpeak AB 2000-2002 <www.interpeak.se>. All rights reserved.
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
#ifndef IPDHCPS6_SUBNET_H
#define IPDHCPS6_SUBNET_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include "ipdhcps6_msg.h"
#include "ipdhcps6_subnet.h"
#include "ipdhcps6_prefix.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipdhcps6_subnet_key_struct
{
struct Ip_in6_addr addr;
int ifindex;
}
Ipdhcps6_subnet_key;
/* Subnet structure */
typedef struct Ipdhcps6_subnet_entry_struct
{
Ipcom_route_entry hdr;
/* The IPv6 subnet */
Ipdhcps6_subnet_key subnet;
/* Subnet mask */
Ipdhcps6_subnet_key mask;
/* Prefix length */
int prefix_len;
/* Options for this subnet */
Ipcom_hash *options;
/* Will be !=IP_NULL if an address pool has been assigned to this subnet */
Ipdhcps6_addr_pool *pools;
/* Hash table of leases that is currently assigned from the pools
The elements are of type Ipdhcps6_lease_addr */
Ipcom_hash *active_leases;
}
Ipdhcps6_subnet_entry;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ipdhcps6_subnet_entry *
ipdhcps6_subnet_get_from_addr(struct Ip_in6_addr *addr, int ifindex);
IP_GLOBAL Ipdhcps6_subnet_entry *
ipdhcps6_subnet_get(struct Ip_in6_addr *subnet, int ifindex);
IP_GLOBAL Ipcom_route *
ipdhcps6_subnet_new_db(void);
IP_GLOBAL void
ipdhcps6_subnet_remove_subnets(void);
IP_GLOBAL void
ipdhcps6_subnet_delete_db(Ipcom_route *subnets);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,313 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcps6_user.c,v $ $Revision: 1.7.54.1 $
* $Source: /home/interpeak/CVSRoot/ipdhcps6/src/ipdhcps6_user.c,v $
* $Author: ulf $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipdhcps6_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_sysvar.h>
#include <ipcom_type.h>
#include <ipcom_syslog.h>
#include "ipdhcps6.h"
#include "ipdhcps6_h.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPDHCPS6_USER_SYSVAR_NAME (36 + IPCOM_AUTH_USERNAME_MAX)
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipdhcps6_list_cb_data_struct
{
Ipdhcps6_user *users;
int users_len;
int num_users;
}
Ipdhcps6_list_cb_data;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_user_prefix_ids_from_str
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipdhcps6_user_prefix_ids_from_str(Ipdhcps6_user *user, const char *str_prefixes)
{
int i, j;
for (i = 0; i < IPDHCPS6_PREFIX_PER_USER; i++)
ipcom_memset(user->prefix_ids[i], 0, IPDHCPS6_KEY_LEN);
for (i = 0, j = 0; *str_prefixes != '\0'; str_prefixes++)
{
if (*str_prefixes == ' ')
{
i = 0;
j++;
continue;
}
if (j >= IPDHCPS6_PREFIX_PER_USER)
{
IPCOM_LOG2(ERR, "Too many prefixes for user %s, max is %d",
user->name, IPDHCPS6_PREFIX_PER_USER);
return IPCOM_ERR_NO_MEMORY;
}
user->prefix_ids[j][i++] = *str_prefixes;
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipdhcps6_user_list_cb
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipdhcps6_user_list_cb(const char *name, const char *value, int flags,
Ipdhcps6_list_cb_data *cb_data)
{
const char *username;
const char *username_end;
(void) flags;
username_end = ipcom_strstr(name, ".ipdhcps6.prefix");
if (username_end == IP_NULL)
return 0;
if (++cb_data->num_users * sizeof(Ipdhcps6_user) >= (Ip_size_t) cb_data->users_len
&& cb_data->users)
{
Ipdhcps6_user *user = &cb_data->users[cb_data->num_users - 1];
int i = 0;
username = username_end - 1;
while (*username != '.')
--username;
while (++username != username_end)
user->name[i++] = *username;
user->name[i] = '\0';
(void) ipdhcps6_user_prefix_ids_from_str(user, value);
}
return 0;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_user_get
*===========================================================================
* Description: Adds a DHCPv6 host to the database.
* Parameters: user - The username must be filled in, this function will
* fill in all prefixes assigned to this user.
* Returns: IPCOM_SUCCESS - operation was successful.
* IPCOM_ERR_NOT_FOUND - the user was not found.
*
*/
IP_GLOBAL Ip_err
ipdhcps6_user_get(Ipdhcps6_user *user)
{
char sysvar_name[IPDHCPS6_USER_SYSVAR_NAME];
char prefix_ids[IPDHCPS6_PREFIX_PER_USER * IPDHCPS6_KEY_LEN];
Ip_size_t ids_len = sizeof(prefix_ids);
if (user->name[0] == '\0')
return IPCOM_ERR_INVALID_ARG;
ipcom_sprintf(sysvar_name, "ipcom.users.%s.ipdhcps6.prefix_list", user->name);
if (ipcom_sysvar_get(sysvar_name, prefix_ids, &ids_len) == IP_NULL)
{
IPCOM_LOG1(DEBUG, "No prefix configuration found for user %s", user->name);
return IPCOM_ERR_NOT_FOUND;
}
return ipdhcps6_user_prefix_ids_from_str(user, prefix_ids);
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipdhcps6_user_add
*===========================================================================
* Description: Fills in all user information for the user 'user->name'.
* Parameters: user - The user to find information for.
* Returns: IPCOM_SUCCESS - operation was successful.
*
*/
IP_PUBLIC Ip_err
ipdhcps6_user_add(Ipdhcps6_user *user)
{
char sysvar_name[IPDHCPS6_USER_SYSVAR_NAME];
char prefix_ids[IPDHCPS6_PREFIX_PER_USER * IPDHCPS6_KEY_LEN];
int i;
ipcom_sprintf(sysvar_name, "ipcom.users.%s.ipdhcps6.prefix_list", user->name);
prefix_ids[0] = '\0';
for (i = 0; i < IPDHCPS6_PREFIX_PER_USER; i++)
{
if (ipcom_strlen(user->prefix_ids[i]) == 0)
continue;
if (prefix_ids[0] != '\0')
ipcom_strcat(prefix_ids, " ");
ipcom_strcat(prefix_ids, user->prefix_ids[i]);
}
return ipcom_sysvar_set(sysvar_name, prefix_ids, IPCOM_SYSVAR_FLAG_OVERWRITE);
}
/*
*===========================================================================
* ipdhcps6_user_delete
*===========================================================================
* Description: Deletes a DHCPv6 user from the database.
* Parameters: username - The name of the user to delete DHCPv6 config for.
* Returns: IPCOM_SUCCESS - operation was successful.
* IPCOM_ERR_NOT_FOUND - the subnet or option was not found.
*
*/
IP_PUBLIC Ip_err
ipdhcps6_user_delete(const char *username)
{
char sysvar_name[IPDHCPS6_USER_SYSVAR_NAME];
ipcom_sprintf(sysvar_name, "ipcom.users.%s.ipdhcps6.prefix_list", username);
return ipcom_sysvar_unset(sysvar_name);
}
/*
*===========================================================================
* ipdhcps6_user_list
*===========================================================================
* Description: Lists all DHCPv6 users in the database.
* Parameters: users - Buffer that will contain the client ID:s.
* Can be IP_NULL if the required length of the 'user' buffer
* (in bytes) should be returned in 'user_len'.
* users_len - The length of the 'users' buffer. Will contain
* the actual number of bytes copied to 'user' after return.
* Returns: IPCOM_SUCCESS - operation was successful.
* IPCOM_ERR_NO_MEMORY - the 'users' buffer was not large enough.
*
*/
IP_PUBLIC Ip_err
ipdhcps6_user_list(Ipdhcps6_user *users, int *users_len)
{
Ipdhcps6_list_cb_data cb_data;
Ip_err err = IPCOM_SUCCESS;
cb_data.users = users;
cb_data.users_len = *users_len;
cb_data.num_users = 0;
ipcom_sysvar_for_each("ipcom.users",
(int (*)(const char *, const char *, int, void *)) ipdhcps6_user_list_cb,
&cb_data);
if (users && (Ip_size_t) *users_len < cb_data.num_users * sizeof(Ipdhcps6_user))
err = IPCOM_ERR_NO_MEMORY;
*users_len = cb_data.num_users * sizeof(Ipdhcps6_user);
return err;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/