/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipdhcps_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #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 **************************************************************************** */