/* *=========================================================================== * ipcom_hash_for_each *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC void ipcom_hash_for_each(Ipcom_hash *head, Ipcom_hash_foreach_cb_func cb_func, void *data) { unsigned i; unsigned x; void **elems; if (head->elem == 0) return; elems = IPCOM_MALLOC_DYNAMIC(head->elem * sizeof(void*)); /*lint !e647 */ if (elems == IP_NULL) { IP_PANIC(); return; } for (i = 0, x = 0; i < head->size; i++) if (head->table[i] != IP_NULL) elems[x++] = head->table[i]; ip_assert(x == head->elem); for (i = 0; i < x; i++) cb_func(elems[i], data); IPCOM_FREE_DYNAMIC(elems); }
/* *=========================================================================== * ipcom_clearenv *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int ipcom_clearenv(void) { #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM Ip_err retval; Ipcom_proc *proc; 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_proc_clearenv(proc); return 0; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5)) /*!! Are all environment variables cleaned up by OS automatically? */ return 0; #elif defined(IPCOM_USE_SYSVAR) && IPCOM_VR_MAX == 1 /*! Hmmmm */ return -1; #else return -1; #endif /* #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM */ }
/* *=========================================================================== * ipcom_drv_ppp_exit *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int /*D!!*/ ipcom_drv_ppp_exit(Ipcom_drv_ppp_link *plink) { Ipcom_drv_ppp_ipc *ipcbuf; int fd; fd = plink->fd; if (fd != -1) { plink->fd = -1; /* will make input daemon exit */ (void)close(fd); } /* Kill output daemon */ ipcbuf = ipcom_ipc_malloc(sizeof(Ipcom_drv_ppp_ipc)); if (ipcbuf == IP_NULL) { IP_PANIC(); return 0; } ipcbuf->netif = plink->netif; ipcbuf->pkt = IP_NULL; /* Send IPC buf to output task */ (void)ipcom_ipc_send(&plink->out_ipc, ipcbuf); (void)ipcom_ipc_close(&plink->out_ipc); return 0; }
/* *=========================================================================== * ipcom_proc_copyenv *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL void ipcom_proc_copyenv(Ipcom_proc *proc_c) { Ipcom_proc *proc_p; Ip_err retval; proc_p = ipcom_proc_self(); ip_assert(proc_p != IP_NULL); ip_assert(proc_c != IP_NULL); if (proc_p->env_tree == IP_NULL) /* Parent process has no environment variables */ return; /* Create child environment semaphore and tree */ retval = ipcom_once(&proc_c->env_once, ipcom_env_init, proc_c); if (retval != IPCOM_SUCCESS) { IP_PANIC(); return; } ipcom_mutex_lock(proc_p->env_mutex); ipcom_hash_for_each(proc_p->env_tree, (Ipcom_hash_foreach_cb_func) ipcom_env_clone, proc_c->env_tree); ipcom_mutex_unlock(proc_p->env_mutex); }
/********************************************************************* * * IP_OS_AddTickHook() * * Function description * Add tick hook. This is a function which is called from the tick handler, typically because the driver's * interrupt handler is not called via it's own hardware ISR. (We poll 1000 times per second) * * Context * Function is called from a task, not an ISR */ void IP_OS_AddTickHook(void (* pfHook)(void)) { #if OS_VERSION >= 36000 static OS_TICK_HOOK _cb; OS_AddTickHook(&_cb, pfHook); #else IP_PANIC("IP_OS_AddTickHook() requires an OS version >= 3.60"); // This requires a newer version of the OS. #endif }
/* *=========================================================================== * ipcom_getenv *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC char * ipcom_getenv(const char *name) { #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM Ip_err retval; Ipcom_proc *proc; Ipcom_env_entry *env; char *value = IP_NULL; 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 IP_NULL; } ipcom_mutex_lock(proc->env_mutex); env = ipcom_hash_get(proc->env_tree, name); if (env != IP_NULL) value = (char *)env->value; ipcom_mutex_unlock(proc->env_mutex); return value; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5)) char *env; static char buf[256]; env = get_env(current_process(), name); if (env != IP_NULL) { ipcom_strncpy(buf, env, sizeof(buf)); free_buf((union SIGNAL **)&env); return (char *)buf; } return IP_NULL; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE return getenv(name); #elif defined(IPCOM_USE_SYSVAR) && IPCOM_VR_MAX == 1 static char buf[256]; Ip_size_t buf_size = sizeof(buf); return ipcom_sysvar_get(name, buf, &buf_size); #else return IP_NULL; #endif /* #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM */ }
/* *=========================================================================== * ipcom_unsetenv *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int ipcom_unsetenv(const char *name) { #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); env = ipcom_hash_get(proc->env_tree, name); if (env != IP_NULL) ipcom_env_delete(env, proc->env_tree); ipcom_mutex_unlock(proc->env_mutex); return 0; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5)) set_env(current_process(), name, NULL); return 0; #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && defined(IP_PORT_VXWORKS) { char buf[256]; int ret; ipcom_snprintf(buf, sizeof(buf), "%s=", name); ret = (int)putenv(buf); return ret == 0 ? 0 : -1; } #elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE return unsetenv(name); #elif defined(IPCOM_USE_SYSVAR) && IPCOM_VR_MAX == 1 (void)ipcom_sysvar_unset(name); return 0; #else return 0; #endif /* #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM */ }
IP_PUBLIC void ipcom_abort(void) { IP_PANIC(); #if defined(IP_PORT_OSE5) efs_abort(__FILE__, __LINE__); #elif defined(IP_PORT_RTCORE) ipcom_proc_exit(); #elif !defined(IP_PORT_ITRON) && \ (!defined(IP_PORT_INTEGRITY) || !defined(INT_178B)) abort(); #endif }
/* *=========================================================================== * ipnet_config_run_boot_cmd *=========================================================================== * Description: Configures one route entry. * Parameters: * Returns: * */ IP_STATIC int ipnet_config_run_boot_cmd(const char *conf) { char *option_org; char *option; char *argv[20]; char *arg; int argc = 0; int ret = -IP_ERRNO_EINVAL; option_org = option = ipcom_strdup(conf); if (option == IP_NULL) return -IP_ERRNO_ENOMEM; while (IP_NULL != (arg = ipcom_strtok_r(option, " \t", &option))) { if (argc == 1) argv[argc++] = "-silent"; argv[argc++] = arg; if (argc >= (int) (sizeof(argv) / sizeof(*argv))) { IPCOM_LOG1(ERR, "Too many arguments in command %s", conf); IP_PANIC(); } } argv[argc] = IP_NULL; if (argc > 2) { if (ipcom_strcmp(argv[0], "route") == 0) ret = ipnet_config_cmd_route(argc, argv); else if (ipcom_strcmp(argv[0], "ifconfig") == 0) ret = ipnet_config_cmd_ifconfig(argc, argv); else if (ipcom_strcmp(argv[0], "qc") == 0) ret = ipnet_config_cmd_qc(argc, argv); #if defined(IPNET_USE_NAT) && !defined(IP_PORT_LKM) && !defined(IP_PORT_VXWORKS) else if (ipcom_strcmp(argv[0], "nat") == 0) ret = ipnet_cmd_nat(argc, argv); #endif } ipcom_free(option_org); return ret; }
/* *=========================================================================== * ipnet_config_add_gateway *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipnet_config_add_gateway(Ip_fd fd, char *ifname, char *option) { char gw_str[IP_INET_ADDRSTRLEN]; char *gw; gw = ipcom_strtok_r(option, " \t", &option); if (gw == IP_NULL) { IPCOM_LOG1(ERR, "Wrong gateway format specified for interface %s, must be 'gateway <driver|gw_address>", ifname); IP_PANIC(); return -IP_ERRNO_EINVAL; } if (ipcom_strcmp(gw, "driver") == 0) { /* Get the IPv4 gateway address to use from the driver */ struct Ip_ethreq ethreq; ipcom_strcpy(ethreq.ethr_name, ifname); if (ipcom_socketioctl(fd, IP_SIOCXETHGINET, ðreq) < 0) { IPCOM_LOG1(ERR, "Failed to read the IPv4 gateway address " "from the driver for %s", ifname); return ipcom_errno; } if (ethreq.ethru.inet.gateway.s_addr == 0xffffffff) return 0; /* using dhcp, ignore gateway */ if (ethreq.ethru.inet.gateway.s_addr == 0) { IPCOM_LOG1(NOTICE, "No IPv4 gateway address set in driver for %s", ifname); return 0; } (void) ipcom_inet_ntop(IP_AF_INET, ðreq.ethru.inet.gateway, gw_str, sizeof(gw_str)); gw = gw_str; } return ipnet_config_add_route(IP_AF_INET, "0.0.0.0", 0, gw); }
/* *=========================================================================== * ipcom_hash_can_move_obj *=========================================================================== * Description: Returns if the object with the specified ideal index can * be move to the specified new index. * Parameters: ideal_index - The index the object would have the table had * no collisions. * new_index - The new index this object would be moved to. * size - The size of the current hash array. * Returns: IP_TRUE if the object can be moved. * */ IP_STATIC Ip_bool ipcom_hash_can_move_obj(unsigned ideal_index, unsigned new_index, unsigned size) { int half_size = size >> 1; #if IPCOM_HASH_HIGH_WATER_MARK > 50 /* NOTE: this algorithm will break if IPCOM_HASH_HIGH_WATER_MARK is 50 or higher */ IP_PANIC(); #endif if (IP_ABS((int) (ideal_index - new_index)) > half_size) { ideal_index = (ideal_index + half_size) % size; new_index = (new_index + half_size) % size; } return ideal_index <= new_index; }
IP_STATIC Ip_err ipcom_sysvar_setvr(const char *name, const char *value, int flags, int vr) { Ip_err retval; Ipcom_sysvar_tree *tree; if (value == IP_NULL) return IPCOM_SUCCESS; /* simply ignore it silently */ #ifdef IP_PORT_OSE5 if (IP_BIT_ISFALSE(flags, IPCOM_SYSVAR_FLAG_OVERWRITE)) { Ip_size_t test_size = 1; char test[1]; if (ipcom_sysvar_get_ose5(name, test, &test_size) || test_size > 1) return IPCOM_ERR_DUPLICATE; } #endif /* IP_PORT_OSE5 */ retval = ipcom_once(&ipcom_sysvar_once, ipcom_sysvar_init, IP_NULL); if (retval != IPCOM_SUCCESS) { IP_PANIC(); return retval; } IPCOM_CODE_LOCK(); tree = ipcom_sysvar_tree_get(vr); if (tree == IP_NULL) retval = IPCOM_ERR_NO_MEMORY; else retval = ipcom_sysvar_set_tree(name, value, flags, tree); ipcom_sysvar_tree_done(tree); IPCOM_CODE_UNLOCK(); return retval; }
/* *=========================================================================== * ipppp_work_schedule *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipppp_work_schedule(struct Ipppp_action_work *work) { if (ipcom_once(&ipppp_work_once, ipppp_work_init, IP_NULL) != IPCOM_SUCCESS) { IP_PANIC(); return -1; } ipcom_mutex_lock(ipppp_work_lock); ipcom_list_insert_last(&ipppp_work_queue, &work->list); ipcom_mutex_unlock(ipppp_work_lock); ipcom_sem_post(ipppp_work_sem); return 0; }
/* *=========================================================================== * ipcom_usr_create *=========================================================================== * Description: * Parameters: * Returns: */ IP_PUBLIC Ip_err ipcom_usr_create(void) { Ip_err err; /*!!RACE CONDITION*/ if (ipcom_usr_created) return IPCOM_SUCCESS; ipcom_usr_created = IP_TRUE; err = ipcom_mutex_create(&ipcom_once_mutex); if (err != IPCOM_SUCCESS) goto fail; /****** SUCCESS *****/ return err; /****** Create fail *****/ fail: IP_PANIC(); return err; }
/* *=========================================================================== * ipnet_sock_sockdev_register *=========================================================================== * Description: Registers the IP_AF_SOCKDEV domain. * Parameters: * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_sock_sockdev_register(void) { Ipnet_sock_ops *ops; ops = ipcom_calloc(1, sizeof(*ops)); if (ops == IP_NULL) { IPCOM_LOG0(CRIT, "Could not register the IP_AF_SOCKDEV domain, out of memory"); IP_PANIC(); return -IP_ERRNO_ENOMEM; } ops->domain = IP_AF_SOCKDEV; ops->type = IP_SOCK_RAW; ops->proto = -1; ops->destroy = ipnet_sockdev_destroy; ops->init = ipnet_sockdev_init; ops->recv = ipnet_sock_pkt_recv; ops->send = ipnet_sockdev_send; return ipnet_sock_register_ops(ops); }
IP_GLOBAL IP_CONST char * ipnet_nd_state_to_string(int state) { switch (state) { case IPNET_ND_UNINITIALIZED: return "UNINITIALIZED"; case IPNET_ND_INCOMPLETE: return "INCOMPLETE"; case IPNET_ND_REACHABLE: return "REACHABLE"; case IPNET_ND_STALE: return "STALE"; case IPNET_ND_DELAY: return "DELAY"; case IPNET_ND_PROBE: return "PROBE"; case IPNET_ND_PROXY: return "PROXY"; default: IP_PANIC(); return "Unknown ND state"; } }
/* *=========================================================================== * ipcom_once *=========================================================================== * Description: * Parameters: * Returns: */ IP_PUBLIC Ip_err ipcom_once(Ipcom_once_t *once, Ip_err (*init)(void *param), void *param) { Ip_err ret = IPCOM_SUCCESS; int old_state; Ipcom_wait_queue wq; if (once->state == IPCOM_ONCE_STATE_DONE) return IPCOM_SUCCESS; /* Enter the once monitor */ ip_assert(ipcom_once_mutex != IPCOM_MUTEX_INVALID); ipcom_mutex_lock(ipcom_once_mutex); /* Check state */ switch (old_state = once->state) { case IPCOM_ONCE_STATE_UNINITIALIZED: /* First call, will do the init */ ipcom_wait_queue_init(&wq); once->wq = &wq; once->state = IPCOM_ONCE_STATE_RUNNING; break; case IPCOM_ONCE_STATE_RUNNING: /* Sleep until the init() function has been run */ ret = ipcom_wait_queue_add_current_proc(once->wq, IPC_TIMEOUT_INFINITE, ipcom_mutex_unlock, ipcom_mutex_lock, ipcom_once_mutex); break; case IPCOM_ONCE_STATE_DONE: break; default: IP_PANIC(); break; } /* Exit the once monitor */ ipcom_mutex_unlock(ipcom_once_mutex); if (old_state == IPCOM_ONCE_STATE_UNINITIALIZED) { /* Do init call */ ret = init(param); /* Enter the once monitor again */ ipcom_mutex_lock(ipcom_once_mutex); /* Update the state to done */ once->state = IPCOM_ONCE_STATE_DONE; /* All pending processes are unlinked from the wait-queue by this call, so it is safe to set once->wq to IP_NULL */ ipcom_wait_queue_wakeup_all_procs(once->wq); once->wq = IP_NULL; /* Exit the once monitor */ ipcom_mutex_unlock(ipcom_once_mutex); } return ret; }
/* *=========================================================================== * ipnet_sock_tcp_register *=========================================================================== * Description: Registers the TCP protocol for IPv4 and/or IPv6. * Parameters: * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_sock_tcp_register(void) { Ipnet_sock_tcp_ops *ops; int domains[] = { #ifdef IPCOM_USE_INET IP_AF_INET, #endif #ifdef IPCOM_USE_INET6 IP_AF_INET6, #endif }; int protos[] = { 0, IP_IPPROTO_TCP }; Ip_size_t p, d; int ret; for (d = 0; d < sizeof(domains) / sizeof(domains[0]); d++) for (p = 0; p < sizeof(protos) / sizeof(protos[0]); p++) { ops = ipcom_calloc(1, sizeof(*ops)); if (ops == IP_NULL) { IPCOM_LOG0(CRIT, "Could not register the TCP protocol, out of memory"); IP_PANIC(); return -IP_ERRNO_ENOMEM; } switch (domains[d]) { #ifdef IPCOM_USE_INET case IP_AF_INET: ipnet_sock_ip4_get_ops(&ops->inet); break; #endif #ifdef IPCOM_USE_INET6 case IP_AF_INET6: ipnet_sock_ip6_get_ops(&ops->inet); break; #endif default: break; } ops->network_bind = ops->inet.network_bind; ops->inet.network_bind = ipnet_sock_tcp_bind; ops->network_init = ops->inet.sock.init; ops->inet.sock.init = ipnet_sock_tcp_init; ops->network_destroy = ops->inet.sock.destroy; ops->inet.sock.destroy = ipnet_sock_tcp_destroy; ops->network_connect = ops->inet.sock.connect; ops->inet.sock.connect = ipnet_sock_tcp_connect; ops->inet.sock.type = IP_SOCK_STREAM; ops->inet.sock.proto = protos[p]; ops->inet.sock.allow_async_send = IP_TRUE; ops->inet.sock.accept = iptcp_accept; ops->inet.sock.close = iptcp_close; ops->inet.sock.listen = iptcp_listen; ops->inet.sock.usr_recv = ipnet_usr_sock_tcp_recv; ops->inet.sock.pkts_from_iov = ipnet_usr_sock_tcp_pkts_from_iov; ops->inet.sock.send = iptcp_send; ops->inet.sock.shutdown = iptcp_shutdown; ops->inet.sock.getopt = iptcp_getsockopt; ops->inet.sock.setopt = iptcp_setsockopt; ops->inet.sock.ioctl = iptcp_ioctl; ops->inet.sock.hdr_space += IPTCP_TCP_HDR_SIZE; ops->inet.sock.extra_sock_space += sizeof(Iptcp_tcb); ret = ipnet_sock_register_ops(&ops->inet.sock); if (ret < 0) return ret; } return 0; }
/* *=========================================================================== * 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_sysvar_getvr *=========================================================================== * Description: * Parameters: * Returns: */ IP_GLOBAL char * ipcom_sysvar_getvr(const char *name, char *value, Ip_size_t *value_size, Ip_bool usr, int vr) { Ipcom_sysvar_entry *sysvar; Ip_size_t value_length; char *ret_value = IP_NULL; Ip_err retval; Ipcom_sysvar_tree *tree; if (name == IP_NULL) return IP_NULL; retval = ipcom_once(&ipcom_sysvar_once, ipcom_sysvar_init, IP_NULL); if (retval != IPCOM_SUCCESS) { IP_PANIC(); return IP_NULL; } IPCOM_CODE_LOCK(); tree = ipcom_sysvar_tree_get(vr); if (tree == IP_NULL) goto leave; sysvar = ipcom_hash_get(tree->sysvars, name); if (sysvar) { if (value == IP_NULL) { #ifdef IP_PORT_OSE5 if (usr) ret_value = ipcom_strdup_usr(sysvar->value); else #else (void)usr; #endif ret_value = ipcom_strdup(sysvar->value); } else { value_length = ipcom_strlen(sysvar->value) + 1; if (value_length > *value_size) { ret_value = IP_NULL; *value_size = value_length; } else { ret_value = value; ipcom_memcpy(ret_value, sysvar->value, value_length); *value_size = value_length - 1; } } } #ifdef IP_PORT_OSE5 else { ret_value = ipcom_sysvar_get_ose5(name, value, value_size); } #endif /* IP_PORT_OSE5 */ leave: ipcom_sysvar_tree_done(tree); IPCOM_CODE_UNLOCK(); return ret_value; }
/* *=========================================================================== * ipnet_ip_forward_mib_handler_ipCidrRouteTable *=========================================================================== * Description: MIB handler for ipCidrRouteDest * Parameters: See file 'ipsnmp.h' * Returns: IPSNMP_ERROR_XXX * */ IP_STATIC Ip_s32 ipnet_ip_forward_mib_handler_ipCidrRouteTable(Ip_s32 cmd, char *id, Ipsnmp_varbind *vb, Ip_s32 magic, struct Ipsnmp_node_object *nodeobj) { Ip_s32 lid, bestindex, ret = -1; char *iid; char *buf = ipcom_malloc(IPSNMP_CONFIG_MAX_OBJECT_ID); char *best = ipcom_malloc(IPSNMP_CONFIG_MAX_OBJECT_ID); if(buf == IP_NULL || best == IP_NULL) { ret = IPSNMP_ERROR_GENERROR; goto exit; } lid = ipsnmp_util_last_subid(nodeobj->id); ip_assert(lid >= 1 && lid <= 16); bestindex = ipnet_ip_forward_mib_table_search_ipCidrRouteTable(id, buf, best, cmd); if(bestindex == -2) { ret = IPSNMP_ERROR_GENERROR; goto exit; } else if(bestindex == -1) { ret = IPSNMP_ERROR_NOSUCHNAME; goto exit; } if(cmd == IPSNMP_MIB_COMMAND_GET || cmd == IPSNMP_MIB_COMMAND_NEXT) { iid = ipsnmp_create_iid_direct(nodeobj->id, best); if(iid == IP_NULL) { ret = IPSNMP_ERROR_GENERROR; goto exit; } ip_assert(routewalk.bestrt != IP_NULL); switch(lid) { case 1: /* ipCidrRouteDest */ ret = ipsnmp_util_put_ipaddress(magic, iid, ip_ntohl(*(Ip_u32 *)routewalk.bestrt->hdr.key)); break; case 2: /* ipCidrRouteMask */ if(routewalk.bestrt->hdr.mask != IP_NULL) ret = ipsnmp_util_put_ipaddress(magic, iid, ip_ntohl(*(Ip_u32 *)routewalk.bestrt->hdr.mask)); else ret = ipsnmp_util_put_ipaddress(magic, iid, 0xffffffff); break; case 3: /* ipCidrRouteTos */ ret = ipsnmp_util_put_integer(magic, iid, 0); break; case 4: /* ipCidrRouteNextHop */ if(IP_BIT_ISSET(routewalk.bestrt->hdr.flags, IPNET_RTF_GATEWAY)) { struct Ip_sockaddr_in *sa = (struct Ip_sockaddr_in *)routewalk.bestrt->gateway; ret = ipsnmp_util_put_ipaddress(magic, iid, ip_ntohl(sa->sin_addr.s_addr)); } else ret = ipsnmp_util_put_ipaddress(magic, iid, 0); break; case 5: /* ipCidrRouteIfIndex */ ret = ipsnmp_util_put_integer(magic, iid, routewalk.bestrt->netif->ipcom.ifindex); break; case 6: /* ipCidrRouteType */ if(IP_BIT_ISSET(routewalk.bestrt->hdr.flags, IPNET_RTF_GATEWAY)) ret = ipsnmp_util_put_integer(magic, iid, 4); /* remote */ else ret = ipsnmp_util_put_integer(magic, iid, 3); /* local */ break; case 7: /* ipCidrRouteProto */ ret = ipsnmp_util_put_integer(magic, iid, 2); /* local */ break; case 8: /* ipCidrRouteAge */ ret = ipsnmp_util_put_integer(magic, iid, 0); break; case 9: /* ipCidrRouteInfo */ ret = ipsnmp_util_put_oid(magic, iid, "0.0"); break; case 10: /* ipCidrRouteNextHopAS */ ret = ipsnmp_util_put_integer(magic, iid, 0); break; case 11: /* ipCidrRouteMetric1 */ ret = ipsnmp_util_put_integer(magic, iid, -1); break; case 12: /* ipCidrRouteMetric2 */ ret = ipsnmp_util_put_integer(magic, iid, -1); break; case 13: /* ipCidrRouteMetric3 */ ret = ipsnmp_util_put_integer(magic, iid, -1); break; case 14: /* ipCidrRouteMetric4 */ ret = ipsnmp_util_put_integer(magic, iid, -1); break; case 15: /* ipCidrRouteMetric5 */ ret = ipsnmp_util_put_integer(magic, iid, -1); break; case 16: /* ipCidrRouteStatus */ ret = ipsnmp_util_put_integer(magic, iid, 1); /* active */ break; default: IP_PANIC(); ret = IPSNMP_ERROR_GENERROR; break; } ipcom_free(iid); } if(cmd == IPSNMP_MIB_COMMAND_TEST || cmd == IPSNMP_MIB_COMMAND_SET) { (void)vb; switch(lid) { case 5: /* ipCidrRouteIfIndex */ case 6: /* ipCidrRouteType */ case 9: /* ipCidrRouteInfo */ case 10: /* ipCidrRouteNextHopAS */ case 11: /* ipCidrRouteMetric1 */ case 12: /* ipCidrRouteMetric2 */ case 13: /* ipCidrRouteMetric3 */ case 14: /* ipCidrRouteMetric4 */ case 15: /* ipCidrRouteMetric5 */ case 16: /* ipCidrRouteStatus */ ret = IPSNMP_ERROR_NOSUCHNAME; break; default: IP_PANIC(); ret = IPSNMP_ERROR_GENERROR; break; } } exit: if(buf != IP_NULL) ipcom_free(buf); if(best != IP_NULL) ipcom_free(best); return ret; }
/* *=========================================================================== * ipnet_sock_udp_register *=========================================================================== * Description: Registers the UDP protocol for IPv4 and/or IPv6. * Parameters: * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_sock_udp_register(void) { Ipnet_sock_udp_ops *ops; int domains[] = { #ifdef IPCOM_USE_INET IP_AF_INET, #endif #ifdef IPCOM_USE_INET6 IP_AF_INET6, #endif }; int protos[] = { 0, IP_IPPROTO_UDP }; Ip_size_t d, p; int ret; for (d = 0; d < sizeof(domains) / sizeof(domains[0]); d++) for (p = 0; p < sizeof(protos) / sizeof(protos[0]); p++) { ops = ipcom_calloc(1, sizeof(*ops)); if (ops == IP_NULL) { IPCOM_LOG0(CRIT, "Could not register the UDP protocol, out of memory"); IP_PANIC(); return -IP_ERRNO_ENOMEM; } switch (domains[d]) { #ifdef IPCOM_USE_INET case IP_AF_INET: ipnet_sock_ip4_get_ops(&ops->inet); break; #endif #ifdef IPCOM_USE_INET6 case IP_AF_INET6: ipnet_sock_ip6_get_ops(&ops->inet); break; #endif default: break; } ops->network_bind = ops->inet.network_bind; ops->inet.network_bind = ipnet_sock_udp_bind; ops->network_init = ops->inet.sock.init; ops->network_connect = ops->inet.sock.connect; ops->inet.sock.init = ipnet_sock_udp_init; ops->inet.sock.connect = ipnet_sock_udp_connect; ops->inet.sock.type = IP_SOCK_DGRAM; ops->inet.sock.proto = protos[p]; ops->inet.sock.allow_async_send = IP_TRUE; ops->inet.sock.usr_recv = ipnet_usr_sock_recvmsg; ops->inet.sock.send = ipnet_sock_udp_send; ops->inet.sock.hdr_space += IPNET_UDP_HDR_SIZE; ret = ipnet_sock_register_ops(&ops->inet.sock); if (ret < 0) return ret; } return 0; }
/* *=========================================================================== * ipcom_shell_run_extcmd *=========================================================================== * Description: Starts a shell command process and delivers the command arguments * and stdio socket to that process. * Parameters: argc, argv - traditional command arguments * stdio_fd - the standard input, output and error sock * ppid - parent pid * cmd_pid - shell command process id * * Returns: 1 : command process started * 0 : not an external command * -1 : error * */ IP_PUBLIC Ip_err ipcom_shell_run_extcmd(int argc, char **argv, Ip_fd *stdio_fd, Ip_pid_t ppid, Ip_u32 seqno, Ip_pid_t *cmd_pid, int *proc_index) { Ipcom_proc_attr attr; Ipcom_ipc ipc; Ipcom_shellcmd_info *sinfo; Ipcom_shell_cmd *cmd = IP_NULL; Ipcom_shell_cmd *tcmd; Ip_err retval; char procname[40]; Ip_u32 stack = IPCOM_PROC_STACK_DEFAULT; Ip_pid_t pid; pid = ipcom_getpid(); ipcom_sprintf(procname, "ipcom_sc_0x%lx_%d", (Ip_u32)pid, *proc_index); /* Find command and max stack size (since we are reusing the process). */ if (argc > 0) { for (tcmd = IPCOM_LIST_FIRST(&ipcom_shell_cmd_head); tcmd; tcmd = IPCOM_LIST_NEXT(&tcmd->cmd_list)) { stack = (Ip_u32)IP_MAX(stack, tcmd->stack_size); if (cmd == IP_NULL && ipcom_strcmp(tcmd->name, argv[0]) == 0) { cmd = tcmd; if (*cmd_pid != 0) break; } } if (cmd == IP_NULL) return 0; /* Start the shell_cmd process. */ if (*cmd_pid == 0) { ipcom_proc_attr_init(&attr); attr.priority = (Ip_u32)cmd->priority; attr.stacksize = stack; attr.flags |= IPCOM_PROC_FLAG_FP; if (ipcom_proc_acreate(procname, (Ipcom_proc_func)ipcom_shell_cmd, &attr, cmd_pid)) { IPCOM_LOG0(ERR, "ipcom_shell_run_extcmd :: ipcom_proc_acreate() failed"); goto fail; } ip_assert(*cmd_pid != 0); } } else { /* argc == 0 is used to kill the shell_cmd process. */ ip_assert(*cmd_pid != 0); } /* Open IPC with ipcom_shell. */ retval = ipcom_ipc_open(&ipc, procname, -1); if (retval != IPCOM_SUCCESS) { IPCOM_LOG2(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_open(%s) failed, ret = %d", procname, retval); goto fail; } /* Send a message to ipcom_shell. */ sinfo = ipcom_ipc_malloc(sizeof(Ipcom_shellcmd_info)); if (sinfo == IP_NULL) { IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_malloc() failed, ret = %d", retval); goto fail; } /* Fill in IPC info. */ sinfo->argc = argc; if (argc > 0) { sinfo->hook = cmd->hook; sinfo->argv = argv; sinfo->fd = *stdio_fd; sinfo->pid = pid; sinfo->ppid = ppid; sinfo->seqno = seqno; #if IPCOM_USE_FILE != IPCOM_FILE_NONE if (ipcom_getcwd(sinfo->cwd, sizeof(sinfo->cwd)) == IP_NULL) ipcom_memset(sinfo->cwd, 0, sizeof(sinfo->cwd)); else sinfo->cwd[sizeof(sinfo->cwd)-1] = '\0'; #endif sinfo->prio = cmd->priority; } /* Send the IPC info. */ retval = ipcom_ipc_send(&ipc, sinfo); if (retval != IPCOM_SUCCESS) { IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_send() failed, ret = %d", retval); ipcom_ipc_free(sinfo); goto fail; } (void)ipcom_ipc_close(&ipc); #ifdef IP_PORT_OSE5 if (argc > 0) { /* OSE5 has process specific sockets -> donate child fd */ ip_assert(*cmd_pid != 0); retval = (Ip_err)efs_donate_fd(*stdio_fd, *cmd_pid); if (retval != 0) { IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: efs_donate_fd, ret = %d", retval); goto fail; } } #endif /* IP_PORT_OSE5 */ /* Wait for exit message from shell_cmd process. */ retval = ipcom_ipc_receive(IP_NULL, &sinfo, -1); if (retval != IPCOM_SUCCESS) { IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_receive(shell_cmd) failed, ret = %d", retval); goto fail; } ip_assert(argc > 0 || *(Ip_u32 *)sinfo == 1); if (*(Ip_u32 *)sinfo == 1) { *cmd_pid = 0; /* shell command called ipcom_exit(). */ (*proc_index)++; } else { #ifdef IP_PORT_OSE5 *stdio_fd = efs_receive_fd(0); if (*stdio_fd == -1) { IP_PANIC(); goto fail; } #endif #if defined(IP_PORT_OSE) || defined(IP_PORT_OSE5) /* Change child socket owner (A must for OSE to work due to poor ipcom_block impl). */ pid = ipcom_getpid(); if (ipcom_socketioctl(*stdio_fd, IP_SIOCSPGRP, &pid) < 0) { IP_PANIC2(); IPCOM_LOG1(WARNING, "ipcom_shell_run_extcmd :: ipcom_socketioctl(IP_SIOCSPGRP) failed, errno = %d", ipcom_errno); } #endif } ipcom_ipc_free(sinfo); return 1; fail: if (ipcom_ipc_isopen(&ipc)) (void)ipcom_ipc_close(&ipc); return -1; }
/* *=========================================================================== * ipnet_if_mib_handler_ifXTable *=========================================================================== * Description: MIB handler for variables in ifXTable * Parameters: See file 'ipsnmp.h' * Returns: IPSNMP_ERROR_XXX * */ IP_STATIC Ip_s32 ipnet_if_mib_handler_ifXTable(Ip_s32 cmd, char *id, Ipsnmp_varbind *vb, Ip_s32 magic, struct Ipsnmp_node_object *nodeobj) { Ip_s32 lid, ret = -1; Ip_s32 ifLinkUpDownTrapEnable = 0; char *iid; char *buf = ipcom_malloc(IPSNMP_CONFIG_MAX_OBJECT_ID); char *best = ipcom_malloc(IPSNMP_CONFIG_MAX_OBJECT_ID); Ipnet_netif *best_netif; if (buf == IP_NULL || best == IP_NULL) { ret = IPSNMP_ERROR_GENERROR; goto exit; } lid = ipsnmp_util_last_subid(nodeobj->id); ip_assert((lid >= 1 && lid <= 5) || (lid >= 14 && lid <= 19)); best_netif = ipnet_if_mib_table_search_ifTable(id, buf, best, cmd, &ret); if (best_netif == IP_NULL) goto exit; if (cmd == IPSNMP_MIB_COMMAND_GET || cmd == IPSNMP_MIB_COMMAND_NEXT) { iid = ipsnmp_create_iid_direct(nodeobj->id, best); if (iid == IP_NULL) { ret = IPSNMP_ERROR_GENERROR; goto exit; } switch(lid) { case 1: /* ifName */ ret = ipsnmp_util_put_octetstring(magic, iid, (Ip_u8 *)best_netif->ipcom.name, ipcom_strlen(best_netif->ipcom.name)); break; case 2: /* ifInMulticastPkts */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifInMulticastPkts); break; case 3: /* ifInBroadcastPkts */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifInBroadcastPkts); break; case 4: /* ifOutMulticastPkts */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifOutMulticastPkts); break; case 5: /* ifOutBroadcastPkts */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifOutBroadcastPkts); break; case 14: /* ifLinkUpDownTrapEnable */ if (best_netif->ipcom.mib2.ifLinkUpDownTrapEnable == 0) best_netif->ipcom.mib2.ifLinkUpDownTrapEnable = 1; ret = ipsnmp_util_put_integer(magic, iid, best_netif->ipcom.mib2.ifLinkUpDownTrapEnable); break; case 15: /* ifHighSpeed */ if (best_netif->ipcom.type == IP_IFT_PPP) ret = ipsnmp_util_put_gauge32(magic, iid, 0); else ret = ipsnmp_util_put_gauge32(magic, iid, 100); break; case 16: /* ifPromiscuousMode */ if (IP_BIT_ISSET(best_netif->ipcom.flags, IP_IFF_PROMISC)) ret = ipsnmp_util_put_integer(magic, iid, 1); else ret = ipsnmp_util_put_integer(magic, iid, 2); break; case 17: /* ifConnectorPresent */ ret = ipsnmp_util_put_integer(magic, iid, 2); break; case 18: /* ifAlias */ ret = ipsnmp_util_put_octetstring(magic, iid, IP_NULL, 0); break; case 19: /* ifCounterDiscontinuityTime */ ret = ipsnmp_util_put_timeticks(magic, iid, 0); break; default: IP_PANIC(); ret = IPSNMP_ERROR_GENERROR; break; } ipcom_free(iid); } if (cmd == IPSNMP_MIB_COMMAND_TEST || cmd == IPSNMP_MIB_COMMAND_SET) { switch(lid) { case 14: /* ifLinkUpDownTrapEnable */ ret = ipsnmp_util_get_integer(vb, &ifLinkUpDownTrapEnable); if (ret == IPSNMP_ERROR_NOERROR) { if (ifLinkUpDownTrapEnable != 1 && ifLinkUpDownTrapEnable != 2) { ret = IPSNMP_ERROR_WRONGVALUE; } } if (ret == IPSNMP_ERROR_NOERROR && cmd == IPSNMP_MIB_COMMAND_SET) { best_netif->ipcom.mib2.ifLinkUpDownTrapEnable = ifLinkUpDownTrapEnable; } break; case 16: /* ifPromiscuousMode */ case 18: /* ifAlias */ ret = IPSNMP_ERROR_NOSUCHNAME; break; default: IP_PANIC(); ret = IPSNMP_ERROR_GENERROR; break; } } exit: if (buf != IP_NULL) ipcom_free(buf); if (best != IP_NULL) ipcom_free(best); return ret; }
/* *=========================================================================== * ipnet_if_mib_handler_ifTable *=========================================================================== * Description: MIB handler for variables in ifTable * Parameters: See file 'ipsnmp.h' * Returns: IPSNMP_ERROR_XXX * */ IP_STATIC Ip_s32 ipnet_if_mib_handler_ifTable(Ip_s32 cmd, char *id, Ipsnmp_varbind *vb, Ip_s32 magic, struct Ipsnmp_node_object *nodeobj) { Ip_s32 lid, ret = -1; Ipnet_netif *best_netif; Ip_s32 ifAdminStatus = 0; char *iid; char *buf = ipcom_malloc(IPSNMP_CONFIG_MAX_OBJECT_ID); char *best = ipcom_malloc(IPSNMP_CONFIG_MAX_OBJECT_ID); struct Ip_ifreq ifreq; Ip_fd fd; if (buf == IP_NULL || best == IP_NULL) { ret = IPSNMP_ERROR_GENERROR; goto exit; } lid = ipsnmp_util_last_subid(nodeobj->id); ip_assert(lid >= 1 && lid <= 20); ip_assert(lid != 12 && lid != 18); best_netif = ipnet_if_mib_table_search_ifTable(id, buf, best, cmd, &ret); if (best_netif == IP_NULL) goto exit; if (cmd == IPSNMP_MIB_COMMAND_GET || cmd == IPSNMP_MIB_COMMAND_NEXT) { iid = ipsnmp_create_iid_direct(nodeobj->id, best); if (iid == IP_NULL) { ret = IPSNMP_ERROR_GENERROR; goto exit; } switch(lid) { case 1: /* ifIndex */ ret = ipsnmp_util_put_integer(magic, iid, best_netif->ipcom.ifindex); break; case 2: /* ifDescr */ ret = ipsnmp_util_put_octetstring(magic, iid, (Ip_u8 *)best_netif->ipcom.name, ipcom_strlen(best_netif->ipcom.name)); break; case 3: /* ifType */ ret = ipsnmp_util_put_integer(magic, iid, best_netif->ipcom.type); break; case 4: /* ifMtu */ ret = ipsnmp_util_put_integer(magic, iid, best_netif->ipcom.mtu); break; case 5: /* ifSpeed */ if (best_netif->ipcom.type == IP_IFT_PPP) ret = ipsnmp_util_put_gauge32(magic, iid, IPCOM_DRV_PPP_BAUDRATE); else ret = ipsnmp_util_put_gauge32(magic, iid, 100000000); break; case 6: /* ifPhysAddr */ ret = ipsnmp_util_put_octetstring(magic, iid, best_netif->ipcom.link_addr, best_netif->ipcom.link_addr_size); break; case 7: /* ifAdminStatus */ if (IP_BIT_ISSET(best_netif->ipcom.flags, IP_IFF_UP)) ret = ipsnmp_util_put_integer(magic, iid, 1); else ret = ipsnmp_util_put_integer(magic, iid, 2); break; case 8: /* ifOperStatus */ if (IP_BIT_ISSET(best_netif->ipcom.flags, IP_IFF_UP)) ret = ipsnmp_util_put_integer(magic, iid, 1); else ret = ipsnmp_util_put_integer(magic, iid, 2); break; case 9: /* ifLastChange */ ret = ipsnmp_util_put_timeticks(magic, iid, best_netif->ipcom.mib2.ifLastChange); break; case 10: /* ifInOctets */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifInOctets); break; case 11: /* ifInUcastPkts */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifInUcastPkts); break; case 13: /* ifInDiscards */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifInDiscards); break; case 14: /* ifInErrors */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifInErrors); break; case 15: /* ifInUnknownProtos */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifInUnknownProtos); break; case 16: /* ifOutOctets */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifOutOctets); break; case 17: /* ifOutUcastPkts */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifOutUcastPkts); break; case 19: /* ifOutDiscards */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifOutDiscards); break; case 20: /* ifOutErrors */ ret = ipsnmp_util_put_counter32(magic, iid, best_netif->ipcom.mib2.ifOutErrors); break; default: IP_PANIC(); ret = IPSNMP_ERROR_GENERROR; break; } ipcom_free(iid); } if (cmd == IPSNMP_MIB_COMMAND_TEST || cmd == IPSNMP_MIB_COMMAND_SET) { switch(lid) { case 7: /* ifAdminStatus */ ret = ipsnmp_util_get_integer(vb, &ifAdminStatus); if (ret == IPSNMP_ERROR_NOERROR) { if (ifAdminStatus != 1 && ifAdminStatus != 2) { ret = IPSNMP_ERROR_WRONGVALUE; } } if (ret == IPSNMP_ERROR_NOERROR && cmd == IPSNMP_MIB_COMMAND_SET) { fd = ipnet_do_socket(IP_AF_INET, IP_SOCK_DGRAM, IP_IPPROTO_UDP, IP_FALSE); if(fd != IP_INVALID_SOCKET) { /* Change interface status */ ipcom_memset(&ifreq, 0, sizeof(struct Ip_ifreq)); ipcom_strcpy(ifreq.ifr_name, best_netif->ipcom.name); if (ipnet_sys_socketioctl(fd, IP_SIOCGIFFLAGS, &ifreq) < 0) { IPCOM_LOG1(ERR, "Failed to get interface flags: %s", ipcom_strerror(ipcom_errno)); ret = IPSNMP_ERROR_GENERROR; } if (ifAdminStatus == 1) IP_BIT_SET(ifreq.ip_ifr_flags, IP_IFF_UP); else IP_BIT_CLR(ifreq.ip_ifr_flags, IP_IFF_UP); if (ipnet_sys_socketioctl(fd, IP_SIOCSIFFLAGS, &ifreq) < 0) { IPCOM_LOG1(ERR, "Failed to set interface flags: %s", ipcom_strerror(ipcom_errno)); ret = IPSNMP_ERROR_GENERROR; } ipnet_sys_socketclose(fd); } else { IPCOM_LOG0(ERR, "Failed to create socket for ioctl call"); ret = IPSNMP_ERROR_GENERROR; } } break; default: IP_PANIC(); ret = IPSNMP_ERROR_GENERROR; break; } } exit: if (buf != IP_NULL) ipcom_free(buf); if (best != IP_NULL) ipcom_free(best); return ret; }
/* *=========================================================================== * ipnet_rtnetlink_route_foreach_vr *=========================================================================== * Description: Hash table foreach callback. Called once for each virtual * router that exists in the system. * Parameters: rtab - route table * param - callback parameters. * Returns: - * */ IP_STATIC void ipnet_rtnetlink_route_foreach_vr_family(Ipcom_route *rtab, Ipnet_rtnetlink_route_family_t *param) { int new_offs = 0; Ip_ptrdiff_t table = IPNET_ROUTE_GET_TABLE(rtab); Ip_u16 vr = IPNET_ROUTE_GET_VR(rtab); Ipnet_route_entry *rt = IP_NULL; /* This traversal is already aborted */ if (param->state.aborted) return; /* Only handle rtabs of selected address family */ if (IPNET_ROUTE_GET_FAMILY(rtab) != param->family) return; /* Check if specific VR shall be dumped */ if (IP_BIT_ISFALSE(param->nlmsg->nlmsg_flags, IP_NLM_F_VR_UNSPEC) && (param->mem->vr != IPCOM_VR_ANY) && (param->mem->vr != vr)) return; /* * If this is a trailer message buffer, make sure it * starts dumping where the last message ended */ if (param->state.cont) { Ipnet_route_entry *rtt = (Ipnet_route_entry*)(*param->state.rt); /* Verify current state */ if (*param->state.vr != vr || *param->state.table != table) return; if (rtt != IP_NULL) { rt = ipnet_route_first_entry(IPNET_ROUTE_GET_FAMILY(rtab), vr, table); while (rt != IP_NULL) { if (rt == rtt) break; rt = ipnet_route_next_entry(rt); } } } /* Reset the continue variable; we're on the move again */ param->state.cont = 0; /* Get first unless we've found one to continue from */ if (rt == IP_NULL) rt = ipnet_route_first_entry(IPNET_ROUTE_GET_FAMILY(rtab), vr, table); /* */ while (rt) { /* Do not dump the 255.255.255.255, 224.0.0.0/4 or IPv6 multicast routes. */ /* Do not dump routes that are part of multipath routes either */ if (IP_BIT_ISFALSE(rt->hdr.flags, IPNET_RTF_X_MCAST_RO | IPNET_RTF_X_BCAST_RO | IPNET_RTF_X_HIDDEN) && (rt->prev == IP_NULL)) { #ifdef IPCOM_USE_INET if (param->family == IP_AF_INET) { new_offs = ipnet_rtnetlink_ip4_route_fill_info (param->mem, rt, param->nlmsg->nlmsg_seq, IP_RTM_NEWROUTE, IP_NLM_F_MULTI); } else #endif #ifdef IPCOM_USE_INET6 if (param->family == IP_AF_INET6) { new_offs = ipnet_rtnetlink_ip6_route_fill_info (param->mem, rt, param->nlmsg->nlmsg_seq, IP_RTM_NEWROUTE, IP_NLM_F_MULTI); } else #endif { IP_PANIC(); } if (new_offs < 0) goto aborted; } rt = ipnet_route_next_entry(rt); /* */ if (rt && new_offs) goto aborted; } return; aborted: param->state.aborted = 1; *param->state.rt = (Ip_ptrdiff_t)rt; *param->state.table = (Ip_ptrdiff_t)table; *param->state.vr = (Ip_ptrdiff_t)vr; }
/* *=========================================================================== * ipnet_config_interface *=========================================================================== * Description: Configures one interface if it exists and is UP. * Parameters: fd - A socket descriptor * ifname - The name of the interface to configure * conf - The configuration to apply to the interface * conf_len - Number of valid entries in the "conf" array * pass - First pass (1) will add all addresses * second pass (2) will add other things like gateways * Returns: 0 = success * <0 = error code * */ IP_STATIC int ipnet_config_interface(Ip_fd fd, char *ifname, char *conf[], int conf_len, int pass) { char *option; char *option_org; char *token; int i; int err; ip_assert(pass == 1 || pass == 2); if (ipcom_if_nametoindex(ifname) == 0) { /* Interface does not exist */ IPCOM_LOG1(INFO, "%s not attached - skipping", ifname); return 0; } if (0 > (err = ipnet_config_bring_up_if(ifname))) { IPCOM_LOG1(INFO, "Failed to bring UP %s", ifname); return 0; } for (i = 0; i < conf_len; i++) { option_org = option = ipcom_strdup(conf[i]); if (option == IP_NULL) return -IP_ERRNO_ENOMEM; token = ipcom_strtok_r(option, " \t/", &option); if (token == IP_NULL || ipcom_strcmp(token, "ifname") == 0) { /* Ignore */ err = 0; } #ifdef IPCOM_USE_INET else if (ipcom_strcmp(token, "inet") == 0) { if (pass == 1) err = ipnet_config_add_inet_addr(fd, ifname, option); } else if (ipcom_strcmp(token, "gateway") == 0) { if (pass == 2) err = ipnet_config_add_gateway(fd, ifname, option); } #else else if (ipcom_strcmp(token, "inet") == 0 || ipcom_strcmp(token, "gateway") == 0) IP_NOOP; #endif /* IPCOM_USE_INET */ #ifdef IPCOM_USE_INET6 else if (ipcom_strcmp(token, "inet6") == 0) { if (pass == 1) err = ipnet_config_add_inet6_addr(fd, ifname, option); } else if (ipcom_strcmp(token, "gateway6") == 0) { if (pass == 2) err = ipnet_config_add_gateway6(ifname, option); } #else else if (ipcom_strcmp(token, "inet6") == 0 || ipcom_strcmp(token, "gateway6") == 0) IP_NOOP; #endif /* IPCOM_USE_INET6 */ else if (ipcom_strcmp(token, "devname") != 0) /* Invalid configuration */ err = -IP_ERRNO_EINVAL; ipcom_free(option_org); if (err != 0) { if (err < 0) err = -err; IPCOM_LOG4(ERR, "failed on '%s' when configuring %s: %s (%d)", conf[i], ifname, ipcom_strerror(err), err); IP_PANIC(); break; } } return err; }