/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_configd.c,v $ $Revision: 1.83.10.10 $ * $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_configd.c,v $ * $Author: jsheng $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #ifndef IPCOM_KERNEL #define IPCOM_KERNEL #endif #include "ipnet_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include "ipnet.h" #include "ipnet_h.h" #include "ipnet_loopback.h" #include "ipnet_route.h" #include "ipnet_routesock.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ #ifdef IPCOM_USE_INET6 #define IPNET_CONFIGD_ADDRSTRLEN_BASE IP_INET6_ADDRSTRLEN #else #define IPNET_CONFIGD_ADDRSTRLEN_BASE IP_INET_ADDRSTRLEN #endif /* Make room for flags */ #define IPNET_CONFIGD_ADDRSTRLEN (IPNET_CONFIGD_ADDRSTRLEN_BASE + 32) /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ #ifdef IP_PORT_VXWORKS IP_GLOBAL char * ipcom_vxworks_boot_devname(void); #endif /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ IP_STATIC void ipnet_configd_new_if(int rt_sock, Ip_u32 ifindex, const char *ifname); /* **************************************************************************** * 8 DATA **************************************************************************** */ /* * Will be posted when the initial configuration has been applied. */ static Ipcom_sem ipnet_configd_sem; #if defined(IPWRNAD) && defined(IP_PORT_UNIX) IP_EXTERN volatile Ip_bool wrnad_mon_running; #endif /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_config_set_if_up *=========================================================================== * Description: Bring up the specified interface. * Parameters: sock - a valid socket descriptor * ifname - name of the interface to bring up. * Returns: * */ IP_STATIC void ipnet_config_set_if_up(int sock, const char *ifname) { struct Ip_ifreq ifreq; ipcom_memset(&ifreq, 0, sizeof(struct Ip_ifreq)); ipcom_strncpy(ifreq.ifr_name, ifname, sizeof(ifreq.ifr_name)); ifreq.ifr_name[sizeof(ifreq.ifr_name)-1] = '\0'; /* * Read the current interface flags */ if (ipcom_socketioctl(sock, IP_SIOCGIFFLAGS, &ifreq) < 0) { IPCOM_LOG2(ERR, "Failed to read the interface flags for %s: %s", ifname, ipcom_strerror(ipcom_errno)); return; } /* * Set the IFF_UP flag */ IP_BIT_SET(ifreq.ip_ifr_flags, IP_IFF_UP); /* * Write the interface flags */ if (ipcom_socketioctl(sock, IP_SIOCSIFFLAGS, &ifreq) < 0) IPCOM_LOG2(ERR, "Failed to write the interface flags for %s: %s", ifname, ipcom_strerror(ipcom_errno)); } /* *=========================================================================== * ipnet_configd_set_ip4_addr *=========================================================================== * Description: Sets the IPv4 address on a network interface. * Parameters: sock - a valid socket descriptor. * ifindex - index of the interface to set address on * addr - IPv4 address in presentation format * mask - IPv4 mask in presentation format or IP_NULL to * use default mask. * Returns: IP_TRUE if the address was added successfully * */ #ifdef IPCOM_USE_INET IP_STATIC Ip_bool ipnet_configd_set_ip4_addr(int sock, Ip_u32 ifindex, const char *addr, const char *mask) { struct Ip_sockaddr_in *in; struct Ip_ifaliasreq ifa; struct Ip_ethreq ethreq; ipcom_memset(ðreq, 0, sizeof(struct Ip_ethreq)); (void)ipcom_if_indextoname(ifindex, ethreq.ethr_name); #ifdef IPNET_USE_RARP if (ipcom_strcmp(addr, "rarp") == 0) { ethreq.ethru.rarp = -1; if (ipcom_socketioctl(sock, IP_SIOCXETHSRARP, ðreq) < 0) IPCOM_LOG1(ERR, "Failed to enable RARPP on %s", ethreq.ethr_name); return IP_FALSE; } #endif /* IPNET_USE_RARP */ if (ipcom_strcmp(addr, "driver") == 0) { char drvaddr[IP_INET_ADDRSTRLEN]; char drvmask[IP_INET_ADDRSTRLEN]; /* * Get the IPv4 address to use from the driver */ if (ipcom_socketioctl(sock, IP_SIOCXETHGINET, ðreq) < 0) return IP_FALSE; /* * The above ioctl must return a valid IPv4 address or fail. */ ip_assert(ethreq.ethru.inet.addr.s_addr != IP_INADDR_ANY); if (ethreq.ethru.inet.addr.s_addr == 0xffffffff) return ipnet_configd_set_ip4_addr(sock, ifindex, "dhcp", IP_NULL); ipcom_inet_ntop(IP_AF_INET, ðreq.ethru.inet.addr, drvaddr, sizeof(drvaddr)); ipcom_inet_ntop(IP_AF_INET, ðreq.ethru.inet.mask, drvmask, sizeof(drvmask)); return ipnet_configd_set_ip4_addr(sock, ifindex, drvaddr, drvmask); } /* Support dhcp */ if (ipcom_strcmp(addr, "dhcp") == 0) { struct Ip_ifreq ifr; ipcom_memset(&ifr, 0, sizeof(struct Ip_ifreq)); (void)ipcom_if_indextoname(ifindex, ifr.ifr_name); ifr.ifr_ifru.ifru_opt = 1; if (ipcom_socketioctl(sock, IP_SIOCXSDHCPRUNNING, &ifr) < 0) { IPCOM_LOG1(ERR, "Failed to enable DHCP on %s", ifr.ifr_name); return IP_FALSE; } return IP_TRUE; } ipcom_memset(&ifa, 0, sizeof(ifa)); (void)ipcom_if_indextoname(ifindex, ifa.ifra_name); in = (struct Ip_sockaddr_in *) &ifa.ifra_addr; in->sin_family = IP_AF_INET; IPCOM_SA_LEN_SET(in, sizeof(struct Ip_sockaddr_in)); (void)ipcom_inet_pton(IP_AF_INET, addr, &in->sin_addr); if (mask != IP_NULL) { in = (struct Ip_sockaddr_in *) &ifa.ifra_mask; in->sin_family = IP_AF_INET; IPCOM_SA_LEN_SET(in, sizeof(struct Ip_sockaddr_in)); (void)ipcom_inet_pton(IP_AF_INET, mask, &in->sin_addr); } if (ipcom_socketioctl(sock, IP_SIOCAIFADDR, &ifa) < 0) { IPCOM_LOG3(ERR, "Failed to set IPv4 address %s on %s: %s", addr, ifa.ifra_name, ipcom_strerror(ipcom_errno)); return IP_FALSE; } return IP_TRUE; } #endif /* IPCOM_USE_INET */ /* *=========================================================================== * ipnet_configd_set_ip6_addr *=========================================================================== * Description: Sets the IPv6 address on a network interface. * Parameters: sock - a valid socket descriptor. * ifindex - index of the interface to set address on * addr_and_flags - IPv6 address in presentation format * mask - IPv6 mask in presentation format or IP_NULL to * use default mask. * Returns: IP_TRUE if the address was added successfully * */ #ifdef IPCOM_USE_INET6 IP_STATIC Ip_bool ipnet_configd_set_ip6_addr(int sock, Ip_u32 ifindex, const char *addr, const char *mask) { struct Ip_in6_aliasreq ifareq; struct Ip_ethreq ethreq; char drvaddr[IP_INET6_ADDRSTRLEN]; char drvmask[IP_INET6_ADDRSTRLEN]; ipcom_memset(&ifareq, 0, sizeof(ifareq)); ipcom_memset(ðreq, 0, sizeof(struct Ip_ethreq)); (void)ipcom_if_indextoname(ifindex, ethreq.ethr_name); for (;;) { /* Kill initial spaces */ addr += ipcom_strspn(addr, " \t"); /* Check for flags */ if (ipcom_strncmp(addr, "tentative", 9) == 0) { ifareq.ifra_flags |= IP_IN6_IFF_TENTATIVE; addr += 9; } else break; } if (ipcom_strcmp(addr, "driver") == 0) { struct Ip_in6_addr netmask; /* * Get the IPv6 address to use from the driver */ if (ipcom_socketioctl(sock, IP_SIOCXETHGINET6, ðreq) < 0) return IP_FALSE; /* * The above ioctl must return a valid IPv6 address or fail. */ ip_assert(!IP_IN6_IS_ADDR_UNSPECIFIED(ðreq.ethru.inet6.addr)); ipcom_inet_ntop(IP_AF_INET6, ðreq.ethru.inet6.addr, drvaddr, sizeof(drvaddr)); ipcom_memset(&netmask, 0, sizeof(netmask)); ipnet_route_create_mask(&netmask, ethreq.ethru.inet6.prefixlen); ipcom_inet_ntop(IP_AF_INET6, &netmask, drvmask, sizeof(drvmask)); /* return ipnet_configd_set_ip6_addr(sock, ifindex, drvaddr, drvmask); */ addr = drvaddr; mask = drvmask; } (void)ipcom_if_indextoname(ifindex, ifareq.ifra_name); ifareq.ifra_addr.sin6_family = IP_AF_INET6; IPCOM_SA_LEN_SET(&ifareq.ifra_addr, sizeof(struct Ip_sockaddr_in6)); if (ipcom_inet_pton(IP_AF_INET6, addr, &ifareq.ifra_addr.sin6_addr) != 1) { IPCOM_LOG2(ERR, "Failed to set IPv6 address %s on %s since the address format is invalid", addr, ifareq.ifra_name); return IP_FALSE; } if (mask == IP_NULL) { /* * Use default mask */ if (IP_IN6_IS_ADDR_MULTICAST(&ifareq.ifra_addr.sin6_addr)) mask = "ffff::"; else if (IP_IN6_IS_ADDR_LOOPBACK(&ifareq.ifra_addr.sin6_addr)) mask = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; else mask = "ffff:ffff:ffff:ffff::"; } ifareq.ifra_prefixmask.sin6_family = IP_AF_INET6; IPCOM_SA_LEN_SET(&ifareq.ifra_prefixmask, sizeof(struct Ip_sockaddr_in6)); (void)ipcom_inet_pton(IP_AF_INET6, mask, &ifareq.ifra_prefixmask.sin6_addr); /* TODO: make it configurable as to when tentative should be used */ /* ifareq.ifra_flags = IP_IN6_IFF_TENTATIVE; */ ifareq.ifra_lifetime.ia6t_preferred = (Ip_time_t)IPCOM_ADDR_INFINITE; ifareq.ifra_lifetime.ia6t_expire = (Ip_time_t)IPCOM_ADDR_INFINITE; if (ipcom_socketioctl(sock, IP_SIOCAIFADDR_IN6, &ifareq) < 0) { IPCOM_LOG3(ERR, "Failed to set IPv6 address %s on %s: %s", addr, ifareq.ifra_name, ipcom_strerror(ipcom_errno)); return IP_FALSE; } return IP_TRUE; } #endif /* IPCOM_USE_INET6 */ /* *=========================================================================== * ipnet_configd_set_addr *=========================================================================== * Description: Sets an IP address to an network interface. * Parameters: rt_sock - route socket * domain - IP_AF_INET or IP_AF_INET6 * ifindex - interface index of the interface to set * address on * addr - IP address to set * mask - network mask to set or IP_NULL * Returns: IP_TRUE if the address was successfully added. * */ IP_STATIC Ip_bool ipnet_configd_set_addr(int rt_sock, int domain, Ip_u32 ifindex, const char *addr, const char *mask) { switch (domain) { #ifdef IPCOM_USE_INET case IP_AF_INET: return ipnet_configd_set_ip4_addr(rt_sock, ifindex, addr, mask); #endif #ifdef IPCOM_USE_INET6 case IP_AF_INET6: return ipnet_configd_set_ip6_addr(rt_sock, ifindex, addr, mask); #endif } return IP_FALSE; } /* *=========================================================================== * ipnet_configd_add_default_gw *=========================================================================== * Description: Adds a default gateway route entry * Parameters: rt_sock - AF_ROUTE socket. * domain - IP_AF_INET or IP_AF_INET6 * ifindex - egress interface used to reach the gateway * gateway - presentation form of the gateway address. * Returns: * */ IP_STATIC void ipnet_configd_add_default_gw(int rt_sock, int domain, Ip_u32 ifindex, const char *gateway) { Ip_pid_t pid; Ip_u32 seq; Ip_size_t sa_len; struct Ipnet_rt_msghdr *rt; union Ip_sockaddr_union *dst; union Ip_sockaddr_union *mask; union Ip_sockaddr_union *gw; char buf[sizeof(struct Ipnet_rt_msghdr) + 3 * sizeof(union Ip_sockaddr_union)]; #ifdef IPCOM_USE_INET if (domain == IP_AF_INET && ipcom_strcmp("driver", gateway) == 0) { struct Ip_ethreq ethreq; ipcom_memset(ðreq, 0, sizeof(struct Ip_ethreq)); (void)ipcom_if_indextoname(ifindex, ethreq.ethr_name); /* * Get the IPv4 gateway from the driver */ if (ipcom_socketioctl(rt_sock, IP_SIOCXETHGINET, ðreq) < 0) /* * Return silently, setting the gateway to "driver" just * means that we should check if the driver has specified * a gateway. */ return; if (ethreq.ethru.inet.gateway.s_addr != IP_INADDR_ANY &ðreq.ethru.inet.gateway.s_addr != 0xffffffff) { char drvgw[IP_INET_ADDRSTRLEN]; ipcom_inet_ntop(IP_AF_INET, ðreq.ethru.inet.gateway, drvgw, sizeof(drvgw)); ipnet_configd_add_default_gw(rt_sock, IP_AF_INET, ifindex, drvgw); } /* * else: static configuration says gateway should be read from * the driver/BSP/persistant storage, but no gateway has been * specified there. */ return; } #endif /* IPCOM_USE_INET */ #ifdef IPCOM_USE_INET6 if (domain == IP_AF_INET6 && ipcom_strcmp("driver", gateway) == 0) /* * No support for reading the IPv6 gateway from the driver * yet. */ return; #endif /* IPCOM_USE_INET6 */ pid = ipcom_getpid(); seq = ipcom_random(); ipcom_memset(buf, 0, sizeof(buf)); /* * Initialize the route message header. */ rt = (struct Ipnet_rt_msghdr *) buf; rt->rtm_msglen = sizeof(struct Ipnet_rt_msghdr); rt->rtm_version = IPNET_RTM_VERSION; rt->rtm_type = IPNET_RTM_ADD; rt->rtm_flags = (IPNET_RTF_UP | IPNET_RTF_DONE | IPNET_RTF_STATIC | IPNET_RTF_GATEWAY); rt->rtm_addrs = (IPNET_RTA_DST | IPNET_RTA_NETMASK | IPNET_RTA_GATEWAY); rt->rtm_index = ifindex; rt->rtm_pid = pid; rt->rtm_seq = seq; rt->rtm_table = IPCOM_ROUTE_TABLE_DEFAULT; dst = (union Ip_sockaddr_union *) (rt + 1); switch (domain) { #ifdef IPCOM_USE_INET case IP_AF_INET: gw = (union Ip_sockaddr_union *) (&dst->sin + 1); mask = (union Ip_sockaddr_union *) (&gw->sin + 1); sa_len = sizeof(struct Ip_sockaddr_in); break; #endif #ifdef IPCOM_USE_INET6 case IP_AF_INET6: gw = (union Ip_sockaddr_union *) (&dst->sin6 + 1); mask = (union Ip_sockaddr_union *) (&gw->sin6 + 1); sa_len = sizeof(struct Ip_sockaddr_in6); break; #endif default: gw = IP_NULL; mask = IP_NULL; sa_len = 0; IP_PANIC(); } /* * The message contains 3 socket addresses: dst, netmask and * gateway. */ rt->rtm_msglen = (Ip_u16) (rt->rtm_msglen + (3 * sa_len)); /* * Set destination address (0.0.0.0 or ::) */ dst->sa.sa_family = (Ip_sa_family_t)domain; IPCOM_SA_LEN_SET(&dst->sa, sa_len); /* * Set mask (0.0.0.0 or /0) */ /* mask points to the wanted buffer address correctly */ /* coverity[overrun-local] */ mask->sa.sa_family = (Ip_sa_family_t)domain; IPCOM_SA_LEN_SET(&mask->sa, sa_len); /* * Set the gateway address */ if(ipcom_getsockaddrbyaddr(domain, gateway, &gw->sa)) { IPCOM_LOG1(ERR, "ipcom_getsockaddrbyaddr failed gw: %s",gateway); return; } if (ipcom_send(rt_sock, rt, rt->rtm_msglen, 0) < 0) { IPCOM_LOG1(ERR, "Failed send to AF_ROUTE socket: %s", ipcom_strerror(ipcom_errno)); IP_PANIC(); return; } do { Ip_ssize_t bytes_read; bytes_read = ipcom_recv(rt_sock, rt, sizeof(buf), 0); if (bytes_read < 0) { IPCOM_LOG1(ERR, "Failed read from AF_ROUTE socket: %s", ipcom_strerror(ipcom_errno)); return; } if (rt->rtm_type == IPNET_RTM_IFANNOUNCE) { struct Ipnet_if_announcemsghdr *if_announce; /* * New interface attached while waiting for result of * gateway add. */ if_announce = (struct Ipnet_if_announcemsghdr *) rt; ipnet_configd_new_if(rt_sock, if_announce->ifan_index, if_announce->ifan_name); } } while (rt->rtm_type != IPNET_RTM_ADD || rt->rtm_seq != seq || rt->rtm_pid != pid); } /* *=========================================================================== * ipnet_configd_new_if *=========================================================================== * Description: Configures a network interface that just got attached. * Parameters: rt_sock - an AF_ROUTE socket * ifindex - interface index of the new interface * ifname - interface name of the new interface. * Returns: * */ IP_STATIC void ipnet_configd_new_if(int rt_sock, Ip_u32 ifindex, const char *ifname) { char sysvar_name[IP_IFNAMSIZ + 20]; char addr[IPNET_CONFIGD_ADDRSTRLEN]; char mask_buf[IPNET_CONFIGD_ADDRSTRLEN]; char *mask; char gateway[IPNET_CONFIGD_ADDRSTRLEN]; Ip_size_t len; int family[] = { #ifdef IPCOM_USE_INET IP_AF_INET, #endif #ifdef IPCOM_USE_INET6 IP_AF_INET6, #endif 0 }; int f; Ip_bool bring_if_up = IP_FALSE; for (f = 0; family[f] > 0; f++) { const char *family_str; unsigned n; if (family[f] == IP_AF_INET) family_str = "inet"; else family_str = "inet6"; for (n = 1; ; n++) { /* * Configure IP address and mask */ ipcom_sprintf(sysvar_name, "%s.%s.%u.addr", ifname, family_str, n); len = sizeof(addr); if (ipcom_sysvar_get(sysvar_name, addr, &len) == IP_NULL) { #ifdef IP_PORT_UNIX /* * No address configured for this interface, default * to ask the driver for the configuration. This is * done so that any configuration that is passed to * the simulator on the command line will be used if * no override is specified in ipnet_conf_interfaces * in file /config/ipnet_config.c */ if (n == 1) { /* * Check if the driver can return the IP * configuration. */ bring_if_up |= ipnet_configd_set_addr(rt_sock, family[f], ifindex, "driver", "driver"); ipnet_configd_add_default_gw(rt_sock, family[f], ifindex, "driver"); } #endif /* IP_PORT_UNIX */ break; } /* * Check for prefixlen/netmask */ ipcom_sprintf(sysvar_name, "%s.%s.%u.netmask", ifname, family_str, n); len = sizeof(mask_buf); mask = mask_buf; if (ipcom_sysvar_get(sysvar_name, mask, &len) == IP_NULL) { union Ip_in_addr_union mask_addr; ipcom_sprintf(sysvar_name, "%s.%s.%u.prefixlen", ifname, family_str, n); len = sizeof(mask_buf); if (ipcom_sysvar_get(sysvar_name, mask, &len) == IP_NULL) { /* * Use default mask */ mask = IP_NULL; } else { /* * Convert prefix length to dotted quad (IPv4) or hex * sequence (IPv6) */ ipcom_memset(&mask_addr, 0, sizeof(mask_addr)); ipnet_route_create_mask(&mask_addr, ipcom_atoi(mask)); ipcom_inet_ntop(family[f], &mask_addr, mask, sizeof(mask_buf)); } } bring_if_up |= ipnet_configd_set_addr(rt_sock, family[f], ifindex, addr, mask); /* * Add default gateway, if specified */ ipcom_sprintf(sysvar_name, "%s.%s.%u.gateway", ifname, family_str, n); len = sizeof(gateway); if (ipcom_sysvar_get(sysvar_name, gateway, &len)) ipnet_configd_add_default_gw(rt_sock, family[f], ifindex, gateway); } } if (!bring_if_up) { ipcom_sprintf(sysvar_name, "%s.up", ifname); bring_if_up = ipcom_sysvar_get_as_int(sysvar_name, IP_FALSE); } if (bring_if_up) ipnet_config_set_if_up(rt_sock, ifname); } /* *=========================================================================== * ipnet_configd *=========================================================================== * Description: Daemon that listens for interfaces being attached to * the stack. Tries to configure them as soons as they * are attached. * Parameters: * Returns: * */ IP_STATIC IPCOM_PROCESS(ipnet_configd) { int rt_sock; struct Ip_if_nameindex *ni; Ip_ssize_t r; ipcom_proc_init(); rt_sock = ipcom_socket(IP_AF_ROUTE, IP_SOCK_RAW, 0); if (rt_sock < 0) /* * The configuration daemon requires support for AF_ROUTE. */ IP_PANIC(); r = 65535; (void)ipcom_setsockopt(rt_sock, IP_SOL_SOCKET, IP_SO_RCVBUF, &r, sizeof(r)); ni = ipcom_if_nameindex(); if (ni == IP_NULL) /* * Out-of-memory */ IP_PANIC(); /* * Configure all interfaces that has been attached before this * daemon started. */ for (r = 0; ni[r].if_index > 0; r++) ipnet_configd_new_if(rt_sock, ni[r].if_index, ni[r].if_name); /* * Initial configuration is done */ ipcom_sem_post(ipnet_configd_sem); for (;;) { struct Ipnet_if_announcemsghdr msg; r = ipcom_recv(rt_sock, &msg, sizeof(msg), 0); if (r < 0) { IPCOM_LOG1(ERR, "Failed to read AF_ROUTE socket: %s", ipcom_strerror(ipcom_errno)); break; } if (r != sizeof(msg) || msg.ifan_type != IPNET_RTM_IFANNOUNCE) /* * Wrong message type */ continue; if (ni != IP_NULL) { /* * First time an if announce message is seen, check if * this interface has already been configured before * entering the for(;;) loop. */ for (r = 0; ni[r].if_index > 0; r++) if (ni[r].if_index == msg.ifan_index) /* * Don't configure this interface since it has * already been configured. */ msg.ifan_what = IPNET_IFAN_DEPARTURE; ipcom_if_freenameindex(ni); ni = IP_NULL; } if (msg.ifan_what == IPNET_IFAN_ARRIVAL) { #if defined(IPWRNAD) && defined(IP_PORT_UNIX) while (!wrnad_mon_running) ipcom_sleep(1); #endif ipnet_configd_new_if(rt_sock, msg.ifan_index, msg.ifan_name); } } ipcom_socketclose(rt_sock); ipcom_proc_exit(); } /* *=========================================================================== * ipnet_configd_bring_if_up *=========================================================================== * Description: Makes sure that the interface is brough put if attached. * Parameters: ifname - an interface name * Returns: * */ IP_STATIC void ipnet_configd_bring_if_up(const char *ifname) { char sysvar_name[IP_IFNAMSIZ + 4]; Ip_err errno; ipcom_sprintf(sysvar_name, "%s.up", ifname); errno = ipcom_sysvar_set(sysvar_name, "1", IPCOM_SYSVAR_FLAG_OVERWRITE); if(errno) IPCOM_LOG3(ERR, "set sysvar '%s' for %s failed errno %d", sysvar_name, "1", errno); } /* *=========================================================================== * ipnet_configd_get_next_n *=========================================================================== * Description: Returns the next available address sequence number * Parameters: ifname - an interface name * family_name - "inet" or "inet6" * Returns: next available address sequence number * */ IP_STATIC unsigned ipnet_configd_get_next_n(const char *ifname, const char *family_name) { char sysvar_name[IP_IFNAMSIZ + 20]; char addr[IPNET_CONFIGD_ADDRSTRLEN]; Ip_size_t len; unsigned n; for (n = 1; ;n++) { ipcom_sprintf(sysvar_name, "%s.%s.%u.addr", ifname, family_name, n); len = sizeof(addr); if (ipcom_sysvar_get(sysvar_name, addr, &len) == IP_NULL) break; } return n; } /* *=========================================================================== * ipnet_configd_get_value *=========================================================================== * Description: Returns the value part from a string with format * " ". * Parameters: key_and_value - a key or key + value string. * Returns: A pointer to the value or IP_NULL if no value is present. * */ IP_STATIC const char * ipnet_configd_get_value(const char *key_and_value) { while (*key_and_value != '\0' && !ipcom_isspace(*key_and_value)) key_and_value++; if (*key_and_value == '\0') /* * No value present. */ return IP_NULL; while (ipcom_isspace(*key_and_value)) key_and_value++; if (ipcom_strlen(key_and_value) == 0) /* * No value present. */ return IP_NULL; return key_and_value; } /* *=========================================================================== * ipnet_configd_tr_value *=========================================================================== * Description: Translates an IPv4 address specification to a sysvar * with format .inet..addr = * Parameters: ip4_spec - string with format "inet " * ifname - name of the interface * Returns: * */ IP_STATIC void ipnet_configd_tr_value(const char *key_and_value, const char *family_name, const char *value_name, const char *ifname) { const char *value; char sysvar_name[IP_IFNAMSIZ + 20]; Ip_err errno; value = ipnet_configd_get_value(key_and_value); if (value == IP_NULL) { IPCOM_LOG2(ERR, "Invalid specification '%s' for %s", key_and_value, ifname); return; } ipcom_sprintf(sysvar_name, "%s.%s.1.%s", ifname, family_name, value_name); errno = ipcom_sysvar_set(sysvar_name, value, IPCOM_SYSVAR_FLAG_OVERWRITE); if(errno) IPCOM_LOG3(ERR, "set sysvar '%s' for %s failed errno %d", sysvar_name, value, errno); } /* *=========================================================================== * ipnet_configd_tr_addr *=========================================================================== * Description: Translates the old IP address specification to the new model * Parameters: key_and_value - address specification * family_name - 'inet' or 'inet6' for IPv4 or IPv6 * ifname - name of the network interface. * Returns: * */ IP_STATIC void ipnet_configd_tr_addr(const char *key_and_value, const char *family_name, const char *ifname) { const char *prefixlen; char addr[IPNET_CONFIGD_ADDRSTRLEN]; char sysvar_name[IP_IFNAMSIZ + 20]; int i = 0; unsigned n = ipnet_configd_get_next_n(ifname, family_name); Ip_err errno; prefixlen = ipnet_configd_get_value(key_and_value); if (prefixlen == IP_NULL) { IPCOM_LOG2(ERR, "Invalid address specification '%s' for %s", key_and_value, ifname); return; } while (*prefixlen != '\0' && *prefixlen != '/') /* * Copy the address part */ addr[i++] = *(prefixlen++); addr[i] = '\0'; /* * Set the address */ ipcom_sprintf(sysvar_name, "%s.%s.%u.addr", ifname, family_name, n); errno = ipcom_sysvar_set(sysvar_name, addr, IPCOM_SYSVAR_FLAG_OVERWRITE); if(errno) IPCOM_LOG3(ERR, "set sysvar '%s' for %s failed errno %d", sysvar_name, addr, errno); if (*prefixlen == '/') { /* * Set the prefixlen */ ipcom_sprintf(sysvar_name, "%s.%s.%u.prefixlen", ifname, family_name, n); errno = ipcom_sysvar_set(sysvar_name, ++prefixlen, IPCOM_SYSVAR_FLAG_OVERWRITE); if(errno) IPCOM_LOG3(ERR, "set sysvar '%s' for %s failed errno %d", sysvar_name, prefixlen, errno); } } /* *=========================================================================== * ipnet_configd_get_devname *=========================================================================== * Description: Returns the name of the device driver to use. * Parameters: devname_spec - device name specification. * Returns: * */ IP_STATIC const char * ipnet_configd_get_devname(const char *devname_spec) { const char *devname; devname = ipnet_configd_get_value(devname_spec); #ifdef IP_PORT_VXWORKS if (devname != IP_NULL && ipcom_strcmp(devname, "driver") == 0) { /* * Use the driver name of the boot device */ devname = ipcom_vxworks_boot_devname(); } #endif /* IP_PORT_VXWORKS */ return devname; } /* *=========================================================================== * ipnet_configd_merge_ifconf *=========================================================================== * Description: Merges the configuration in ipnet_conf_interfaces with * the sysvar configuration. The union of the configurations * is stored as sysvars. * Parameters: if_conf - pointer to the old interface specification * line - the current line we are processing in 'if_conf' * Returns: * */ IP_STATIC void ipnet_configd_merge_ifconf(const char **if_conf, int line) { const char *ifname; if (if_conf[line] == IP_NULL) /* * No more interface definitions to process */ return; if (ipcom_strncmp("ifname", if_conf[line], 6) != 0) { /* * First line of an interface definition must be * "ifname " */ IPCOM_LOG2(ERR, "Interface definition at line %d (%s) does not start with \"ifname\"", line, if_conf[line]); return; } ifname = ipnet_configd_get_value(if_conf[line]); if (ifname == IP_NULL) { /* * No explicit interface name, it should be same as the name * of the driver. */ ifname = ipnet_configd_get_devname(if_conf[++line]); if (ifname == IP_NULL) { IPCOM_LOG1(ERR, "No interface name specified for '%s' and 'devname' was not found", if_conf[line-1]); return; } } ipnet_configd_bring_if_up(ifname); /* * Translate addresses */ while (if_conf[++line] != IP_NULL) { #ifdef IPCOM_USE_INET if (ipcom_strncmp(if_conf[line], "inet ", 5) == 0) ipnet_configd_tr_addr(if_conf[line], "inet", ifname); if (ipcom_strncmp(if_conf[line], "gateway ", 8) == 0) ipnet_configd_tr_value(if_conf[line], "inet", "gateway", ifname); #endif /* IPCOM_USE_INET */ #ifdef IPCOM_USE_INET6 if (ipcom_strncmp(if_conf[line], "inet6 ", 6) == 0) ipnet_configd_tr_addr(if_conf[line], "inet6", ifname); if (ipcom_strncmp(if_conf[line], "gateway6 ", 9) == 0) ipnet_configd_tr_value(if_conf[line], "inet6", "gateway", ifname); #endif } /* * Check for more interfaces */ ipnet_configd_merge_ifconf(if_conf, line + 1); } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_configd_start *=========================================================================== * Description: Starts the stack configuration daemon. * Parameters: * Returns: * */ IP_GLOBAL int ipnet_configd_start() { /* * Merge the configuration information into the new, sysvar * based, method. * .inet..[addr|netmask|gateway] * .inet6.