Files
m241Neelima/components/ip_net2-6.9/ipnet2/src/ipnet_configd.c
T
2026-07-30 11:19:44 +05:30

1259 lines
38 KiB
C

/*
******************************************************************************
* 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 <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#ifndef IPCOM_KERNEL
#define IPCOM_KERNEL
#endif
#include "ipnet_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_inet.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipcom_type.h>
#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(&ethreq, 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, &ethreq) < 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, &ethreq) < 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,
&ethreq.ethru.inet.addr,
drvaddr,
sizeof(drvaddr));
ipcom_inet_ntop(IP_AF_INET,
&ethreq.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(&ethreq, 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, &ethreq) < 0)
return IP_FALSE;
/*
* The above ioctl must return a valid IPv6 address or fail.
*/
ip_assert(!IP_IN6_IS_ADDR_UNSPECIFIED(&ethreq.ethru.inet6.addr));
ipcom_inet_ntop(IP_AF_INET6,
&ethreq.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(&ethreq, 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, &ethreq) < 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
&&ethreq.ethru.inet.gateway.s_addr != 0xffffffff)
{
char drvgw[IP_INET_ADDRSTRLEN];
ipcom_inet_ntop(IP_AF_INET,
&ethreq.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 <ipnet>/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
* "<key> <value>".
* 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 <ifname>.inet.<N>.addr = <addr>
* Parameters: ip4_spec - string with format "inet <addr>"
* 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 <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.
* <ifname>.inet.<N>.[addr|netmask|gateway]
* <ifname>.inet6.<N.[addr|prefixlen|gateway]
* N number from 1 and up to allow more than one address per interface
*/
ipnet_configd_merge_ifconf(ipnet_conf_interfaces, 0);
if (ipcom_sem_create(&ipnet_configd_sem, 0) != IPCOM_SUCCESS)
IP_PANIC();
if (ipcom_proc_acreate("tNetConf",
ipnet_configd,
IP_NULL,
IP_NULL) != IPCOM_SUCCESS)
{
IP_PANIC();
return -IP_ERRNO_ENOMEM;
}
/*
* Wait for the initial configuration to be applied.
*/
ipcom_sem_wait(ipnet_configd_sem);
ipcom_sem_delete(&ipnet_configd_sem);
return 0;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/