531 lines
14 KiB
C
531 lines
14 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcps_leasedump.c,v $ $Revision: 1.13.16.4 $
|
|
* $Source: /home/interpeak/CVSRoot/ipdhcps/src/ipdhcps_leasedump.c,v $
|
|
* $Author: svc-cmnet $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
*
|
|
* Design and implementation by Jonas Rendel <jonas@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipdhcps_config.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_tmo2.h>
|
|
#include <ipcom_type.h>
|
|
|
|
#include "ipdhcps.h"
|
|
#include "ipdhcps_h.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Magic number used to verify a lease dump
|
|
*===========================================================================
|
|
*/
|
|
|
|
#define IPDHCPS_DUMP_MAGIC (0x47111881)
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Version of lease dump format
|
|
*===========================================================================
|
|
*/
|
|
|
|
#define IPDHCPS_DUMP_VERSION (1)
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Size of memory chunk allocated for lease dumping
|
|
*===========================================================================
|
|
*/
|
|
|
|
#define IPDHCPS_LEASE_MALLOC_SZ (512)
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Ipdhcps_lease_info_struct
|
|
*===========================================================================
|
|
* Lease descriptor data structure.
|
|
*/
|
|
|
|
typedef IP_PACKED struct Ipdhcps_lease_info_struct
|
|
{
|
|
Ip_u32 yiaddr;
|
|
Ip_u8 binding_state;
|
|
Ip_time_t lease_time;
|
|
Ip_time_t expires;
|
|
Ip_u8 hlen;
|
|
Ip_u8 haddr[20];
|
|
Ip_u8 cid_len;
|
|
Ip_u8 cid[1];
|
|
}
|
|
Ipdhcps_lease_info;
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Ipdhcps_lease_buf_struct
|
|
*===========================================================================
|
|
* Data structure used when collecting lease info from the database.
|
|
*/
|
|
|
|
typedef IP_PACKED struct Ipdhcps_lease_buf_struct
|
|
{
|
|
struct Ipdhcps_lease_buf_struct *next;
|
|
Ip_u32 n_entries;
|
|
Ip_u32 n_bytes;
|
|
Ip_u8 *current;
|
|
Ip_u8 lease_info[1];
|
|
}
|
|
Ipdhcps_lease_buf;
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Ipdhcps_lease_dump_struct
|
|
*===========================================================================
|
|
* Structure describing a lease dump.
|
|
*/
|
|
|
|
typedef IP_PACKED struct Ipdhcps_lease_dump_struct
|
|
{
|
|
Ip_u32 magic;
|
|
Ip_u8 version;
|
|
Ip_time_t timestamp;
|
|
Ip_u32 checksum;
|
|
Ip_u32 n_words;
|
|
Ip_u32 n_entries;
|
|
Ip_u8 lease_info[1];
|
|
}
|
|
Ipdhcps_lease_dump;
|
|
|
|
IP_STATIC char logbuf[50];
|
|
IP_EXTERN const char *ipdhcps_binding_state_str[];
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_EXTERN Ipdhcps_data ipdhcpsc;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC void ipdhcps_lease_dump_cb(void* obj, void* data);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcps_lease_db_dump
|
|
*===========================================================================
|
|
* Description: Callback function applied when traversing the lease database
|
|
*
|
|
* Parameters: obj - Pointer to lease descriptor.
|
|
* data - Pointer to lease buf descriptor (partial dump)
|
|
*
|
|
* Returns: -
|
|
*/
|
|
IP_STATIC void
|
|
ipdhcps_lease_dump_cb(void* obj, void* data)
|
|
{
|
|
Ipdhcps_lease *l = (Ipdhcps_lease*)obj;
|
|
Ipdhcps_lease_buf *b = (Ipdhcps_lease_buf*)data;
|
|
Ipdhcps_lease_info *current;
|
|
Ip_size_t len;
|
|
|
|
if(l->binding_state != IPDHCPS_BINDING_STATE_PERMANENT)
|
|
{
|
|
len = l->cid_len + sizeof(Ipdhcps_lease_info);
|
|
|
|
for(; b->next != IP_NULL; b = b->next);
|
|
|
|
if((len + b->n_bytes) > IPDHCPS_LEASE_MALLOC_SZ)
|
|
{
|
|
/* coverity[suspicious_sizeof] */
|
|
b->next = (Ipdhcps_lease_buf *)ipcom_malloc(IPDHCPS_LEASE_MALLOC_SZ);
|
|
|
|
if(b->next == IP_NULL)
|
|
return;
|
|
|
|
b = b->next;
|
|
ipcom_memset(b, 0 , IPDHCPS_LEASE_MALLOC_SZ);
|
|
b->current = &b->lease_info[0];
|
|
}
|
|
|
|
current =(Ipdhcps_lease_info*)b->current;
|
|
|
|
current->yiaddr = l->yiaddr;
|
|
current->binding_state = l->binding_state;
|
|
current->expires = l->expires;
|
|
current->lease_time = l->lease_time;
|
|
current->hlen = (Ip_u8)l->chaddr.hlen;
|
|
current->cid_len = (Ip_u8)l->cid_len;
|
|
|
|
ipcom_memcpy(current->haddr, l->chaddr.haddr, l->chaddr.hlen);
|
|
ipcom_memcpy(current->cid, l->cid, l->cid_len);
|
|
|
|
b->n_entries++;
|
|
b->n_bytes += (Ip_u32)len;
|
|
b->current += len;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcps_lease_db_dump
|
|
*===========================================================================
|
|
* Description: Dumps the current entries in the lease database to a buffer
|
|
* that can be saved to a file system or flash by user
|
|
* supplied code;
|
|
*
|
|
* NOTE! The returned buffer must be freed by a calling
|
|
* ipcom_free.
|
|
*
|
|
* Parameters: -
|
|
*
|
|
* Returns: Pointer to dump buffer - success
|
|
* IP_NULL - failure or empry lease database.
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipdhcps_lease_db_dump(void *obj)
|
|
{
|
|
int retval;
|
|
Ipdhcps_lease_buf *head, *l;
|
|
Ipdhcps_lease_dump **dump;
|
|
Ip_u32 n_bytes, w;
|
|
Ip_size_t dumpsize;
|
|
Ip_u8 *ptr;
|
|
|
|
dump = obj;
|
|
|
|
/* coverity[suspicious_sizeof] */
|
|
head = (Ipdhcps_lease_buf *)ipcom_malloc(IPDHCPS_LEASE_MALLOC_SZ);
|
|
|
|
if(head == IP_NULL)
|
|
IPDHCPS_LEAVE(-1);
|
|
|
|
ipcom_memset(head, 0, IPDHCPS_LEASE_MALLOC_SZ);
|
|
|
|
head->current = head->lease_info;
|
|
|
|
(void)ipdhcps_lease_for_each(ipdhcps_lease_dump_cb, head);
|
|
|
|
for(l = head, n_bytes = 0; l != IP_NULL; l = l->next)
|
|
n_bytes += l->n_bytes;
|
|
|
|
if(n_bytes & 0x03)
|
|
n_bytes = (n_bytes & 0xfffffffc) + 4;
|
|
|
|
dumpsize = n_bytes + sizeof(Ipdhcps_lease_dump);
|
|
*dump = ipcom_malloc(dumpsize);
|
|
|
|
if(*dump == IP_NULL)
|
|
IPDHCPS_LEAVE(-1);
|
|
|
|
ipcom_memset(*dump, 0, dumpsize);
|
|
|
|
ptr = (*dump)->lease_info;
|
|
for(l = head; l != IP_NULL; l = l->next)
|
|
{
|
|
ipcom_memcpy(ptr, l->lease_info, l->n_bytes);
|
|
ptr += l->n_bytes;
|
|
(*dump)->n_entries += l->n_entries;
|
|
}
|
|
|
|
(*dump)->magic = IPDHCPS_DUMP_MAGIC;
|
|
(*dump)->version = IPDHCPS_DUMP_VERSION;
|
|
(*dump)->n_words = n_bytes/4;
|
|
(*dump)->timestamp = ipcom_time(0);
|
|
|
|
/* Checksum 32-bitwise */
|
|
for(w = 0; w < (*dump)->n_words; w += 4)
|
|
(*dump)->checksum += *(Ip_u32*)&(*dump)->lease_info[w];
|
|
|
|
retval = (int)dumpsize;
|
|
|
|
leave:
|
|
|
|
for(; head != IP_NULL; head = l)
|
|
{
|
|
l = (Ipdhcps_lease_buf*)head->next;
|
|
ipcom_free(head);
|
|
}
|
|
|
|
return (retval);
|
|
}
|
|
|
|
IP_STATIC Ipdhcps_lease*
|
|
ipdhcps_host_lease_checkout_for_restore(Ipdhcps_subnet* subnet,
|
|
Ip_u32 req_addr)
|
|
{
|
|
Ipdhcps_pool *p;
|
|
Ipdhcps_lease *requested_lease = IP_NULL;
|
|
Ipdhcps_lease *first_free_lease = IP_NULL;
|
|
Ipdhcps_lease *first_avail_lease = IP_NULL;
|
|
Ipdhcps_lease *returned_lease;
|
|
Ip_u32 i;
|
|
|
|
|
|
req_addr = ip_ntohl(req_addr);
|
|
|
|
/* Check if requested address is valid and not occupied */
|
|
IPDHCPS_LIST_FOREACH(p, (&subnet->pools), Ipdhcps_pool*)
|
|
{
|
|
#if 0
|
|
/* Do some class verifications */
|
|
if (client_class == IP_NULL && p->class_id != IP_NULL)
|
|
continue;
|
|
|
|
if (client_class != IP_NULL && p->class_id == IP_NULL)
|
|
continue;
|
|
|
|
if (client_class != IP_NULL && p->class_id != IP_NULL)
|
|
{
|
|
if ((client_class[IPDHCPS_OPT_CODE] != p->class_id[IPDHCPS_OPT_CODE])
|
|
|| (client_class[IPDHCPS_OPT_LEN] != p->class_id[IPDHCPS_OPT_LEN])
|
|
|| (ipcom_memcmp(&client_class[IPDHCPS_OPT_DATA], &p->class_id[IPDHCPS_OPT_DATA], (Ip_size_t)p->class_id[IPDHCPS_OPT_LEN]) != 0))
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
if((req_addr <= p->yiaddr_max) && (req_addr >= p->yiaddr_min))
|
|
{
|
|
/* Found requested lease */
|
|
if(p->leases[req_addr - p->yiaddr_min]->binding_state
|
|
== IPDHCPS_BINDING_STATE_FREE)
|
|
{
|
|
/* Lease can be used by client */
|
|
requested_lease = p->leases[req_addr - p->yiaddr_min];
|
|
first_free_lease = requested_lease;
|
|
break;
|
|
}
|
|
else if(first_free_lease != IP_NULL)
|
|
{
|
|
/* Requested lease can not be used, but we have found a free one */
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if(first_free_lease == IP_NULL)
|
|
{
|
|
for(i = 0; i <= (p->yiaddr_max - p->yiaddr_min); i++)
|
|
{
|
|
if(p->leases[i]->binding_state == IPDHCPS_BINDING_STATE_FREE)
|
|
{
|
|
first_free_lease = p->leases[i];
|
|
break;
|
|
}
|
|
else if((first_avail_lease == IP_NULL) &&
|
|
((p->leases[i]->binding_state == IPDHCPS_BINDING_STATE_EXPIRED) ||
|
|
(p->leases[i]->binding_state == IPDHCPS_BINDING_STATE_RELEASED)))
|
|
{
|
|
first_avail_lease = p->leases[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
returned_lease = requested_lease != IP_NULL ? requested_lease : first_free_lease;
|
|
returned_lease = returned_lease != IP_NULL ? returned_lease : first_avail_lease;
|
|
|
|
if(returned_lease == IP_NULL)
|
|
{
|
|
/* We have no leases to offer */
|
|
IPCOM_LOG0(DEBUG,"ipdhcps_daemon :: no leases to offer client");
|
|
}
|
|
else if(returned_lease == first_avail_lease)
|
|
{
|
|
/* This lease was not free. Print a warning */
|
|
IPCOM_LOG2(WARNING,
|
|
"ipdhcps_daemon :: reusing %s lease with address %s for new client",
|
|
ipdhcps_binding_state_str[returned_lease->binding_state],
|
|
ipcom_inet_ntop(IP_AF_INET,
|
|
&returned_lease->yiaddr,
|
|
logbuf,
|
|
sizeof(logbuf)));
|
|
|
|
/* Delete it from lease database */
|
|
(void)ipdhcps_lease_delete(returned_lease);
|
|
}
|
|
|
|
return(returned_lease);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcps_lease_db_restore
|
|
*===========================================================================
|
|
* Description: Initiates the lease database with data from a user
|
|
* supplied data buffer.
|
|
*
|
|
* NOTE! The buffer must be freed by the caller.
|
|
*
|
|
* Parameters: Pointer to lease dump data buffer.
|
|
*
|
|
* Returns: IPCOM_SUCCESS - success
|
|
* other - failure
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipdhcps_lease_db_restore(void *obj)
|
|
{
|
|
Ip_err retval;
|
|
Ipdhcps_lease_dump *dump = (Ipdhcps_lease_dump*)obj;
|
|
Ip_u32 checksum;
|
|
Ip_u32 i;
|
|
Ipdhcps_lease_info *b;
|
|
Ipdhcps_subnet *s;
|
|
Ipdhcps_lease *l;
|
|
char buf [20];
|
|
|
|
|
|
if(dump->magic != IPDHCPS_DUMP_MAGIC)
|
|
IPDHCPS_LEAVE(IPCOM_ERR_INVALID_CONFIG);
|
|
|
|
if(dump->version != IPDHCPS_DUMP_VERSION)
|
|
IPDHCPS_LEAVE(IPCOM_ERR_INVALID_VERSION);
|
|
|
|
for(checksum = 0, i = 0; i < dump->n_words; i+=4)
|
|
checksum += *(Ip_u32*)&dump->lease_info[i];
|
|
|
|
if(checksum != dump->checksum)
|
|
IPDHCPS_LEAVE(IPCOM_ERR_FAILED);
|
|
|
|
for(i = 0;
|
|
(i <(dump->n_words*4)) && (dump->n_entries > 0);
|
|
i += ((Ip_u8)sizeof(Ipdhcps_lease_info) + b->cid_len))
|
|
{
|
|
b = (Ipdhcps_lease_info*)&dump->lease_info[i];
|
|
dump->n_entries--;
|
|
|
|
s = ipdhcps_subnet_find_matching(b->yiaddr);
|
|
s = s == IP_NULL ? ipdhcpsc.default_net : s;
|
|
|
|
l = ipdhcps_host_lease_checkout_for_restore(s, b->yiaddr);
|
|
|
|
if((l == IP_NULL) || (l->yiaddr != b->yiaddr))
|
|
{
|
|
(void)ipcom_inet_ntop(IP_AF_INET, &b->yiaddr, buf, sizeof(buf));
|
|
IPCOM_LOG1(DEBUG,
|
|
"ipdhcps lease readback :: no lease found for address %s, ignoring",
|
|
buf);
|
|
continue;
|
|
}
|
|
|
|
if(l->binding_state != IPDHCPS_BINDING_STATE_FREE)
|
|
{
|
|
(void)ipcom_inet_ntop(IP_AF_INET, &b->yiaddr, buf, sizeof(buf));
|
|
IPCOM_LOG1(DEBUG,
|
|
"ipdhcps lease readback :: lease found for address %s is not free, ignoring",
|
|
buf);
|
|
continue;
|
|
}
|
|
|
|
if(b->cid_len > 0)
|
|
{
|
|
l->cid = ipcom_malloc(b->cid_len);
|
|
|
|
if(l->cid == IP_NULL)
|
|
IPDHCPS_LEAVE(IPCOM_ERR_NO_MEMORY);
|
|
|
|
ipcom_memcpy(l->cid, b->cid, b->cid_len);
|
|
}
|
|
|
|
l->binding_state = b->binding_state;
|
|
l->expires = b->expires;
|
|
l->lease_time = b->lease_time;
|
|
l->chaddr.hlen = b->hlen;
|
|
l->cid_len = b->cid_len;
|
|
|
|
ipcom_memcpy(l->chaddr.haddr, b->haddr, b->hlen);
|
|
|
|
(void)ipdhcps_lease_add(l);
|
|
}
|
|
|
|
retval = IPCOM_SUCCESS;
|
|
|
|
leave:
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|