/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_dynamic_ip.c,v $ $Revision: 1.23.10.7 $ * $Source: /home/interpeak/CVSRoot/ipike/src/ipike_dynamic_ip.c,v $ * $Author: zan $ $Date: 2013-08-08 09:53:45 $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipike_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #include "ipike_h.h" #include "ipike.h" #include "ipike_util.h" #include "ipike_dynamic_ip.h" /* **************************************************************************** * 4 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 5 DEFINES **************************************************************************** */ /* **************************************************************************** * 6 TYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 LOCAL FUNCTIONS **************************************************************************** */ /* **************************************************************************** * 10 PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipike_initiate_address_reference *=========================================================================== */ IP_GLOBAL void ipike_initiate_address_reference( const char *id, const char *ifname, union Ip_sockaddr_union *addr, union Ip_sockaddr_union *netmask) { char entry[64] = {0}; char value[16] = {0}; const char* name = IP_NULL; int count = 0; /* Format: * * ipike.added_addresses.id.= * ipike.added_addresses..id= * ipike.added_addresses..interface= * ipike.added_addresses..count=0 * ipike.added_addresses..netmask= */ name = ipike_addr_to_str(addr); if (name==IP_NULL) return IP_NULL; if (ipcom_strlen(name) < (sizeof(entry)-32)) { ipcom_sprintf(entry, "ipike.added_addresses.id.%s", id); (void)ipcom_sysvar_set(entry, name, IPCOM_SYSVAR_FLAG_OVERWRITE); ipcom_sprintf(entry, "ipike.added_addresses.%s.id", name); (void)ipcom_sysvar_set(entry, id, IPCOM_SYSVAR_FLAG_OVERWRITE); ipcom_sprintf(entry, "ipike.added_addresses.%s.interface", name); (void)ipcom_sysvar_set(entry, ifname, IPCOM_SYSVAR_FLAG_OVERWRITE); ipcom_sprintf(entry, "ipike.added_addresses.%s.count", name); /* Read old if renew got same address */ count = ipcom_sysvar_get_as_int(entry, 0); ipcom_sprintf(value, "%d", count); (void)ipcom_sysvar_set(entry, value, IPCOM_SYSVAR_FLAG_OVERWRITE); ipcom_sprintf(entry, "ipike.added_addresses.%s.netmask", name); name = ipike_addr_to_str(netmask); if (name != IP_NULL) (void)ipcom_sysvar_set(entry, name, IPCOM_SYSVAR_FLAG_OVERWRITE); } return; } /* *=========================================================================== * ipike_has_valid_address_reference *=========================================================================== */ IP_GLOBAL Ip_bool ipike_has_valid_address_reference(const char *id) { Ip_bool has = IP_FALSE; char entry[64] = {0}; char value[64] = {0}; Ip_size_t len = 0; union Ip_sockaddr_union addr; if (ipcom_strlen(id) < (sizeof(entry)-25)) { ipcom_sprintf(entry, "ipike.added_addresses.id.%s", id); len = sizeof(value); if ( ipcom_sysvar_get(entry, value, &len) != IP_NULL && value[0] != 0 ) { if ( ipike_addr_set(&addr,value) != IPIKE_SUCCESS || ipike_addr_is_zero(&addr)) { IPCOM_LOG0(DEBUG, "ipike_has_valid_address_reference: bad address"); (void)ipcom_sysvar_unset(entry); } else { IPCOM_LOG1(DEBUG2, "ipike_has_valid_address_reference: got address %s", value); has = IP_TRUE; } } } return has; } /* *=========================================================================== * ipike_remove_address_reference *=========================================================================== */ IP_GLOBAL void ipike_remove_address_reference(const char *id) { char entry[64] = {0}; if (ipcom_strlen(id) < (sizeof(entry)-25)) { ipcom_sprintf(entry, "ipike.added_addresses.id.%s", id); (void)ipcom_sysvar_unset(entry); } return; } /* *=========================================================================== * ipike_increase_address_reference *=========================================================================== */ IP_GLOBAL void ipike_increase_address_reference(union Ip_sockaddr_union *addr) { char entry[64] = {0}; char value[64] = {0}; const char* name = IP_NULL; Ip_size_t len = 0; int count = 0; union Ip_sockaddr_union netmask; name = ipike_addr_to_str(addr); if (name==IP_NULL) return; if (ipcom_strlen(name) < (sizeof(entry)-32)) { ipcom_sprintf(entry, "ipike.added_addresses.%s.count", name); count = ipcom_sysvar_get_as_int(entry, 0); count++; ipcom_sprintf(value, "%d", count); (void)ipcom_sysvar_set(entry, value, IPCOM_SYSVAR_FLAG_OVERWRITE); if (count == 1) { ipcom_sprintf(entry, "ipike.added_addresses.%s.netmask", name); len = sizeof(value); if (((ipcom_sysvar_get(entry, value, &len)) != IP_NULL) && (value[0] != 0)) { (void)ipike_addr_set(&netmask,value); } ipcom_sprintf(entry, "ipike.added_addresses.%s.interface", name); len = sizeof(value); if (((ipcom_sysvar_get(entry, value, &len)) == IP_NULL) || (value[0] == 0) || ipike_add_delete_address(IP_TRUE, value, addr, &netmask)) { IPCOM_LOG0(DEBUG, "ipike_increase_address_reference: failed to add address"); } } } return; } /* *=========================================================================== * ipike_decrease_address_reference *=========================================================================== */ IP_GLOBAL void ipike_decrease_address_reference(union Ip_sockaddr_union *addr) { char entry[64] = {0}; char value[64] = {0}; const char* id = IP_NULL; const char* name = IP_NULL; int count = 0; Ip_size_t len = 0; name = ipike_addr_to_str(addr); if (name==IP_NULL) return; if (ipcom_strlen(name) < (sizeof(entry)-32)) { ipcom_sprintf(entry, "ipike.added_addresses.%s.count", name); count = ipcom_sysvar_get_as_int(entry, 0); if (count == 1) { /* Do cleanup and delete dynamic ip address */ (void)ipcom_sysvar_unset(entry); ipcom_sprintf(entry, "ipike.added_addresses.%s.id", name); len = sizeof(value); id = ipcom_sysvar_get(entry, value, &len); (void)ipcom_sysvar_unset(entry); ipcom_sprintf(entry, "ipike.added_addresses.id.%s", id); (void)ipcom_sysvar_unset(entry); ipcom_sprintf(entry, "ipike.added_addresses.%s.netmask", name); (void)ipcom_sysvar_unset(entry); ipcom_sprintf(entry, "ipike.added_addresses.%s.interface", name); len = sizeof(value); name = ipcom_sysvar_get(entry, value, &len); (void)ipcom_sysvar_unset(entry); if (ipike_add_delete_address(IP_FALSE, name, addr, IP_NULL)) { IPCOM_LOG0(DEBUG, "ipike_decrease_address_reference: failed to delete address"); } } else if (count > 1) { count--; ipcom_sprintf(value, "%d", count); (void)ipcom_sysvar_set(entry, value, IPCOM_SYSVAR_FLAG_OVERWRITE); } } return; } /* *=========================================================================== * ipike_update_interface_addresses *=========================================================================== */ IP_GLOBAL Ipike_error ipike_update_interface_addresses( const char *id, const char *ifname, union Ip_sockaddr_union *addr, union Ip_sockaddr_union *netmask, union Ip_sockaddr_union **dns, union Ip_sockaddr_union **nbns) { Ipike_error err = IPIKE_SUCCESS; const char *str = IP_NULL; (void)nbns; /* not supported */ /* Set dns server if specified */ if (dns != IP_NULL) { if (dns[0] != IP_NULL) { if (dns[0]->sa.sa_family != 0) { str = ipike_addr_to_str(dns[0]); if (ipcom_sysvar_set("ipdnsc.primaryns", str, IPCOM_SYSVAR_FLAG_OVERWRITE)) err = IPIKE_FAILED; } if ( dns[1] != IP_NULL && err == IPIKE_SUCCESS ) { if (dns[1]->sa.sa_family != 0) { str = ipike_addr_to_str(dns[1]); if (ipcom_sysvar_set("ipdnsc.secondaryns", str, IPCOM_SYSVAR_FLAG_OVERWRITE)) err = IPIKE_FAILED; } } } } /* Initiate the reference counter for ip address */ if (err == IPIKE_SUCCESS) ipike_initiate_address_reference(id, ifname, addr, netmask); return err; } /* *=========================================================================== * ipike_get_interface_addresses *=========================================================================== */ IP_GLOBAL Ipike_error ipike_get_interface_addresses( Ip_bool ip4, Ipike_value *peer_id, Ip_u32 counter, union Ip_sockaddr_union *addr, union Ip_sockaddr_union *netmask, union Ip_sockaddr_union ***dns, union Ip_sockaddr_union ***nbns) { Ipike_error err = IPIKE_SUCCESS; char *name = IP_NULL; char str[128] = {0}; Ip_size_t len = 0; Ip_u32 n = 0; char **vec = IP_NULL; union Ip_sockaddr_union *tmp = IP_NULL; char *addrstr = IP_NULL; /* This is a sample implementation to get dynamic addresses. This * implementation only support IPv4 and does not support multiple * addresses and expire (infinite). */ if (!ip4) { #ifdef IPCOM_USE_INET6 char *prefixptr = IP_NULL; int n1; int prefixlen = 128; name = (char*)ipcom_malloc(peer_id->len*2+1+28+4); if (name == IP_NULL) { IP_PANIC(); err = IPIKE_OUT_OF_MEMORY; } else { ipcom_strcpy(name, "ipike.address_pool.used.ip6."); ipike_bin2hex(peer_id->value, peer_id->len, &name[ipcom_strlen(name)]); ipcom_sprintf(&name[ipcom_strlen(name)], "%.2x", (Ip_u16)counter); /* Possible to reuse old? */ len = sizeof(str); if ((ipcom_sysvar_get(name, str, &len) == IP_NULL) || (ipike_addr_load_subnet(str, addr, netmask) != IPIKE_SUCCESS)) { /* Allocate new */ len = sizeof(str); if (ipcom_sysvar_get("ipike.address_pool.network6", str, &len) == IP_NULL) { IPCOM_LOG0(ERR, "Dynamic address: No pool available, set sysvar ipike.address_pool.network6"); err = IPIKE_FAILED; } /* Find prefix len before all processing if configured*/ if (IP_NULL != (prefixptr = ipcom_strchr(str, '/'))) { n1 = atoi(prefixptr+1); if( (n1 / 8) > 16) { IPCOM_LOG1(ERR, "Dynamic address: Invalid pool: bad netmask (%d)", n1); } prefixlen = n1; } if ( (err == IPIKE_SUCCESS) && ( (ipike_addr_load_subnet(str, addr, netmask) != IPIKE_SUCCESS) || (ipcom_sysvar_set(name, str, IPCOM_SYSVAR_FLAG_OVERWRITE) != IPCOM_SUCCESS) ) ) { IPCOM_LOG0(ERR, "Dynamic address: Invalid pool, check sysvar ipike.address_pool.network6"); err = IPIKE_FAILED; } if (err == IPIKE_SUCCESS) { if ( (err = ipike_addr_increment_v6(addr, prefixlen) != IPIKE_SUCCESS) ) { IPCOM_LOG0(ERR, "Dynamic address: Failed to increment IPv6 address"); } else { addrstr=ipike_addr_subnet_to_str(addr, netmask); if (addrstr==IP_NULL) { IPCOM_LOG0(ERR, "Failed to update dynamic address pool"); err = IPIKE_FAILED; } else { ipcom_strncpy(str, addrstr,127); if (ipcom_sysvar_set("ipike.address_pool.network6", str, IPCOM_SYSVAR_FLAG_OVERWRITE)) { IPCOM_LOG0(ERR, "Dynamic address: Failed to update dynamic address pool"); err = IPIKE_FAILED; } } } } } } #endif } else { #ifdef IPCOM_USE_INET name = (char*)ipcom_malloc(peer_id->len*2+1+28+4); if (name == IP_NULL) { IP_PANIC(); err = IPIKE_OUT_OF_MEMORY; } else { ipcom_strcpy(name, "ipike.address_pool.used.ip4."); ipike_bin2hex(peer_id->value, peer_id->len, &name[ipcom_strlen(name)]); ipcom_sprintf(&name[ipcom_strlen(name)], "%.2x", (Ip_u16)counter); /* Possible to reuse old? */ len = sizeof(str); if ((ipcom_sysvar_get(name, str, &len) == IP_NULL) || (ipike_addr_load_subnet(str, addr, netmask) != IPIKE_SUCCESS)) { /* Allocate new */ len = sizeof(str); if ((ipcom_sysvar_get("ipike.address_pool.network4", str, &len) == IP_NULL) || (ipike_addr_load_subnet(str, addr, netmask) != IPIKE_SUCCESS) || (ipcom_sysvar_set(name, str, IPCOM_SYSVAR_FLAG_OVERWRITE) != IPCOM_SUCCESS)) { IPCOM_LOG0(ERR, "No dynamic address pool available, set sysvar ipike.address_pool.network4"); err = IPIKE_FAILED; } else { n = addr->sin.sin_addr.s_addr; addr->sin.sin_addr.s_addr = ip_ntohl(addr->sin.sin_addr.s_addr); if ((++addr->sin.sin_addr.s_addr & 0xff) == 0) addr->sin.sin_addr.s_addr++; addr->sin.sin_addr.s_addr = ip_htonl(addr->sin.sin_addr.s_addr); addrstr=ipike_addr_subnet_to_str(addr, netmask); if (addrstr==IP_NULL) { IPCOM_LOG0(ERR, "Failed to update dynamic address pool"); err = IPIKE_FAILED; } else { ipcom_strncpy(str, addrstr,127); if (ipcom_sysvar_set("ipike.address_pool.network4", str, IPCOM_SYSVAR_FLAG_OVERWRITE)) { IPCOM_LOG0(ERR, "Failed to update dynamic address pool"); err = IPIKE_FAILED; } } addr->sin.sin_addr.s_addr = n; } } } if ((IPIKE_SUCCESS == err) && (IP_NULL != dns)) { len = sizeof(str); if (ipcom_sysvar_get("ipike.address_pool.dns4", str, &len) != IP_NULL) { if (IP_NULL == (vec = ipike_strvec(str, ", "))) { IP_PANIC(); err = IPIKE_OUT_OF_MEMORY; } else { n = 0; while ((err == IPIKE_SUCCESS) && (vec[n] != IP_NULL)) { if (IP_NULL == (tmp = ipcom_calloc(1, sizeof(*tmp)))) { IP_PANIC(); err = IPIKE_OUT_OF_MEMORY; } else { err = ipike_addr_set(tmp, vec[n]); if (err == IPIKE_SUCCESS) err = ipike_array_add((void***)dns, tmp); if (err != IPIKE_SUCCESS) ipcom_free(tmp); } n++; } ipike_array_free((void**)vec, ipcom_free); } } } if ((IPIKE_SUCCESS == err) && (IP_NULL != nbns)) { len = sizeof(str); if (ipcom_sysvar_get("ipike.address_pool.nbns4", str, &len) != IP_NULL) { if (IP_NULL == (vec = ipike_strvec(str, ", "))) { IP_PANIC(); err = IPIKE_OUT_OF_MEMORY; } else { n = 0; while ((err == IPIKE_SUCCESS) && (vec[n] != IP_NULL)) { if (IP_NULL == (tmp = ipcom_calloc(1, sizeof(*tmp)))) { IP_PANIC(); err = IPIKE_OUT_OF_MEMORY; } else { err = ipike_addr_set(tmp, vec[n]); if (err == IPIKE_SUCCESS) err = ipike_array_add((void***)nbns, tmp); if (err != IPIKE_SUCCESS) ipcom_free(tmp); } n++; } ipike_array_free((void**)vec, ipcom_free); } } } #endif } if ( name != IP_NULL ) ipcom_free(name); return err; } /* **************************************************************************** * END OF FILE **************************************************************************** */