/* *=========================================================================== * ipnet_vrrp_add_addr *=========================================================================== * Description: Adds a virtual router address. * Parameters: netif - The network interface the VRIP will be assigned to. * vrid - The VRID the address will be assigned to. * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_vrrp_add_addr(Ipnet_netif *netif, Ip_u8 vrid, struct Ip_in_addr addr) { Ipnet_vrrp_addr_t *addr_entry; if (ipnet->vrrp_addrs == IP_NULL) { ipnet->vrrp_addrs = ipcom_hash_new((Ipcom_hash_obj_func) ipnet_vrrp_obj_hash, (Ipcom_hash_key_func) ipnet_vrrp_obj_hash, (Ipcom_hash_cmp_func) ipnet_vrrp_hash_cmp); if (ipnet->vrrp_addrs == IP_NULL) return -IP_ERRNO_ENOMEM; } addr_entry = ipnet_vrrp_get_addr_entry(netif, vrid); if (addr_entry == IP_NULL) { addr_entry = ipcom_malloc(sizeof(Ipnet_vrrp_addr_t)); if (addr_entry == IP_NULL) return -IP_ERRNO_ENOMEM; IPNET_IF_LOCK(netif); addr_entry->netif = netif; addr_entry->vrid = vrid; addr_entry->num_addrs = 1; addr_entry->addrs[0] = addr; } else { Ipnet_vrrp_addr_t *a; int i; i = ipnet_vrrp_addr_index(addr_entry, addr); if (i >= 0) return -IP_ERRNO_EEXIST; (void)ipcom_hash_remove(ipnet->vrrp_addrs, addr_entry); a = ipcom_realloc(addr_entry, sizeof(Ipnet_vrrp_addr_t) + addr_entry->num_addrs * sizeof(Ipnet_vrrp_addr_t)); if (a == IP_NULL) return -IP_ERRNO_ENOMEM; a->addrs[a->num_addrs++] = addr; addr_entry = a; } if (ipcom_hash_add(ipnet->vrrp_addrs, addr_entry) != IPCOM_SUCCESS) { ipcom_free(addr_entry); return -IP_ERRNO_ENOMEM; } IPCOM_LOG2(INFO, "VRRP: added address %s on %s", ipcom_inet_ntop(IP_AF_INET, &addr, ipnet->log_buf, sizeof(ipnet->log_buf)), netif->ipcom.name); return 0; }
/* *=========================================================================== * ipcom_hash_resize *=========================================================================== * Description: Doubles the size or cuts the size in half. * Parameters: head - The head of the hash table. * increase - Set to IP_TRUE to double the size, IP_FALSE * to half the size. * Returns: IPCOM_SUCCESS or IPCOM_ERR_NO_MEMORY if not enough memory * could be allocated. * */ IP_STATIC Ip_err ipcom_hash_resize(Ipcom_hash *head, Ip_bool increase) { void **old_hash_table; int old_size; int i; Ip_err err; old_hash_table = head->table; old_size = head->size; /* Keep the size odd since that will increase the chance of the high bits of the hash value to affect the low bits which is used as index in the hash table */ if (increase) head->size = (head->size << 1) + 3; else head->size = (head->size >> 1) - 1; head->table = IPCOM_CALLOC_STATIC(head->size, sizeof(*head->table)); if (head->table == IP_NULL) { IPCOM_LOG2(ERR, "ipcom_hash_resize :: ipcom_calloc(%d, %d) failed", head->size, sizeof(*head->table)); head->size = old_size; head->table = old_hash_table; return IPCOM_ERR_NO_MEMORY; } head->elem = 0; for (i = 0; i < old_size; i++) if (old_hash_table[i] != IP_NULL) { err = ipcom_hash_add(head, old_hash_table[i]); ip_assert(err == IPCOM_SUCCESS); (void)err; } IPCOM_FREE_STATIC(old_hash_table); return IPCOM_SUCCESS; }
/* *=========================================================================== * ipcom_sysvar_set_internal *=========================================================================== * Description: * Parameters: * Returns: */ IP_GLOBAL Ip_err ipcom_sysvar_set_tree(const char *name, const char *value, int flags, Ipcom_sysvar_tree *tree) { Ip_size_t name_length; Ip_size_t value_length; Ipcom_sysvar_entry *sysvar; Ip_err retval = IPCOM_SUCCESS; /* Check for duplicate. */ sysvar = ipcom_hash_get(tree->sysvars, name); if (sysvar) { if (IP_BIT_ISSET(sysvar->flags, IPCOM_SYSVAR_FLAG_READONLY)) { retval = IPCOM_ERR_READONLY; goto leave; } else if (IP_BIT_ISFALSE(flags, IPCOM_SYSVAR_FLAG_OVERWRITE)) { retval = IPCOM_ERR_DUPLICATE; goto leave; } else { flags |= sysvar->flags & IPCOM_SYSVAR_FLAG_KERNEL; ipcom_hash_remove(tree->sysvars, sysvar); ipcom_free(sysvar); goto set; } } /* No current entry found and not allowed to create a new entry. */ if(IP_BIT_ISSET(flags, IPCOM_SYSVAR_FLAG_NOCREATE)) { retval = IPCOM_ERR_FAILED; goto leave; } /* Add the new sysvar. */ set: name_length = ipcom_strlen(name) + 1; value_length = ipcom_strlen(value) + 1; sysvar = ipcom_malloc(sizeof(Ipcom_sysvar_entry) + name_length + value_length); if(sysvar == IP_NULL) { retval = IPCOM_ERR_NO_MEMORY; goto leave; } sysvar->refcount = 1; sysvar->flags = flags; if (IP_BIT_ISFALSE(flags, IPCOM_SYSVAR_FLAG_INIT)) { tree->modified = IP_TRUE; sysvar->flags |= IPCOM_SYSVAR_FLAG_MODIFIED; } sysvar->name = (const char *)sysvar + sizeof(Ipcom_sysvar_entry); ipcom_memcpy((void *)sysvar->name, name, name_length); sysvar->value = sysvar->name + name_length; ipcom_memcpy((void *)sysvar->value, value, value_length); retval = ipcom_hash_add(tree->sysvars, sysvar); leave: return retval; /*lint !e429 Custodial pointer 'sysvar' has not been freed or returned */ }
/* *=========================================================================== * ipcom_setenv *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int ipcom_setenv(const char *name, const char *value, int rewrite) { #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM Ip_err retval; Ipcom_proc *proc; Ipcom_env_entry *env; proc = ipcom_proc_self(); ip_assert(proc != IP_NULL); retval = ipcom_once(&proc->env_once, ipcom_env_init, proc); if (retval != IPCOM_SUCCESS) { IP_PANIC(); return -1; } ipcom_mutex_lock(proc->env_mutex); /* Check for duplicate. */ env = ipcom_hash_get(proc->env_tree, name); if (env != IP_NULL) { if (rewrite == 0) goto leave; ipcom_env_delete(env, proc->env_tree); } /* Create environment variable. */ env = ipcom_env_create(name, value); if (env == IP_NULL) { ipcom_mutex_unlock(proc->env_mutex); return -1; } (void)ipcom_hash_add(proc->env_tree, env); leave: ipcom_mutex_unlock(proc->env_mutex); return 0; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5)) (void)rewrite; set_env(current_process(), name, value); return 0; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && defined(IP_PORT_VXWORKS) char buf[256]; int ret; (void)rewrite; ipcom_snprintf(buf, sizeof(buf), "%s=%s", name, value); ret = (int)putenv(buf); return ret == 0 ? 0 : -1; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE return setenv(name, value, rewrite); #elif defined(IPCOM_USE_SYSVAR) && IPCOM_VR_MAX == 1 (void)ipcom_sysvar_set(name, value, rewrite ? IPCOM_SYSVAR_FLAG_OVERWRITE : 0); return 0; #else (void)name; (void)value; (void)rewrite; return -1; #endif /* #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM */ }
/* *=========================================================================== * ipcom_env_clone *=========================================================================== * Description: Clones an env entry and adds it to the specified hash table. * Parameters: env - entry to clone * hash - hash table the cloned entry should be added to. * Returns: * */ IP_STATIC void ipcom_env_clone(Ipcom_env_entry *env, Ipcom_hash *hash) { Ipcom_env_entry *clone = ipcom_env_create(env->name, env->value); ipcom_hash_add(hash, clone); }