mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-02-16 15:20:42 +01:00
netconfig: Start RA & DHCPv6 clients
For now the RA client is ran automatically when DHCPv6 client starts. RA takes care of installing / deleting prefix routes and installing the default gateway. If Router Advertisements indicate support DHCPv6, then DHCPv6 transactions are kicked off and the address is set / removed automatically. Stateless configuration is not yet supported.
This commit is contained in:
parent
8d76cae6b1
commit
bb876953ac
138
src/netconfig.c
138
src/netconfig.c
@ -30,6 +30,12 @@
|
|||||||
#include <netinet/if_ether.h>
|
#include <netinet/if_ether.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <ell/ell.h>
|
#include <ell/ell.h>
|
||||||
|
|
||||||
@ -45,6 +51,7 @@
|
|||||||
struct netconfig {
|
struct netconfig {
|
||||||
uint32_t ifindex;
|
uint32_t ifindex;
|
||||||
struct l_dhcp_client *dhcp_client;
|
struct l_dhcp_client *dhcp_client;
|
||||||
|
struct l_dhcp6_client *dhcp6_client;
|
||||||
struct l_queue *ifaddr_list;
|
struct l_queue *ifaddr_list;
|
||||||
uint8_t rtm_protocol;
|
uint8_t rtm_protocol;
|
||||||
uint8_t rtm_v6_protocol;
|
uint8_t rtm_v6_protocol;
|
||||||
@ -80,6 +87,38 @@ static void do_debug(const char *str, void *user_data)
|
|||||||
l_info("%s%s", prefix, str);
|
l_info("%s%s", prefix, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int write_string(const char *file, const char *value)
|
||||||
|
{
|
||||||
|
size_t l = strlen(value);
|
||||||
|
int fd;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
fd = L_TFR(open(file, O_WRONLY));
|
||||||
|
if (fd < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
r = L_TFR(write(fd, value, l));
|
||||||
|
L_TFR(close(fd));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sysfs_write_ipv6_setting(const char *ifname, const char *setting,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
L_AUTO_FREE_VAR(char *, file) =
|
||||||
|
l_strdup_printf("/proc/sys/net/ipv6/conf/%s/%s",
|
||||||
|
ifname, setting);
|
||||||
|
|
||||||
|
r = write_string(file, value);
|
||||||
|
if (r < 0)
|
||||||
|
l_error("Unable to write %s to %s", setting, file);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static void netconfig_ifaddr_destroy(void *data)
|
static void netconfig_ifaddr_destroy(void *data)
|
||||||
{
|
{
|
||||||
struct netconfig_ifaddr *ifaddr = data;
|
struct netconfig_ifaddr *ifaddr = data;
|
||||||
@ -95,6 +134,7 @@ static void netconfig_free(void *data)
|
|||||||
struct netconfig *netconfig = data;
|
struct netconfig *netconfig = data;
|
||||||
|
|
||||||
l_dhcp_client_destroy(netconfig->dhcp_client);
|
l_dhcp_client_destroy(netconfig->dhcp_client);
|
||||||
|
l_dhcp6_client_destroy(netconfig->dhcp6_client);
|
||||||
|
|
||||||
l_queue_destroy(netconfig->ifaddr_list, netconfig_ifaddr_destroy);
|
l_queue_destroy(netconfig->ifaddr_list, netconfig_ifaddr_destroy);
|
||||||
|
|
||||||
@ -582,6 +622,10 @@ static void netconfig_ifaddr_ipv6_added(struct netconfig *netconfig,
|
|||||||
uint32_t len)
|
uint32_t len)
|
||||||
{
|
{
|
||||||
struct netconfig_ifaddr *ifaddr;
|
struct netconfig_ifaddr *ifaddr;
|
||||||
|
struct in6_addr in6;
|
||||||
|
|
||||||
|
if (ifa->ifa_flags & IFA_F_TENTATIVE)
|
||||||
|
return;
|
||||||
|
|
||||||
ifaddr = l_new(struct netconfig_ifaddr, 1);
|
ifaddr = l_new(struct netconfig_ifaddr, 1);
|
||||||
ifaddr->family = ifa->ifa_family;
|
ifaddr->family = ifa->ifa_family;
|
||||||
@ -593,6 +637,22 @@ static void netconfig_ifaddr_ipv6_added(struct netconfig *netconfig,
|
|||||||
ifaddr->prefix_len);
|
ifaddr->prefix_len);
|
||||||
|
|
||||||
l_queue_push_tail(netconfig->ifaddr_list, ifaddr);
|
l_queue_push_tail(netconfig->ifaddr_list, ifaddr);
|
||||||
|
|
||||||
|
if (netconfig->rtm_v6_protocol != RTPROT_DHCP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
inet_pton(AF_INET6, ifaddr->ip, &in6);
|
||||||
|
if (!IN6_IS_ADDR_LINKLOCAL(&in6))
|
||||||
|
return;
|
||||||
|
|
||||||
|
l_dhcp6_client_set_link_local_address(netconfig->dhcp6_client,
|
||||||
|
ifaddr->ip);
|
||||||
|
|
||||||
|
if (l_dhcp6_client_start(netconfig->dhcp6_client))
|
||||||
|
return;
|
||||||
|
|
||||||
|
l_error("netconfig: Failed to start DHCPv6 client for "
|
||||||
|
"interface %u", netconfig->ifindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netconfig_ifaddr_ipv6_deleted(struct netconfig *netconfig,
|
static void netconfig_ifaddr_ipv6_deleted(struct netconfig *netconfig,
|
||||||
@ -998,19 +1058,25 @@ static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool netconfig_ipv4_dhcp_create(struct netconfig *netconfig)
|
static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client,
|
||||||
|
enum l_dhcp6_client_event event,
|
||||||
|
void *userdata)
|
||||||
{
|
{
|
||||||
netconfig->dhcp_client = l_dhcp_client_new(netconfig->ifindex);
|
struct netconfig *netconfig = userdata;
|
||||||
|
|
||||||
l_dhcp_client_set_event_handler(netconfig->dhcp_client,
|
switch (event) {
|
||||||
netconfig_ipv4_dhcp_event_handler,
|
case L_DHCP6_CLIENT_EVENT_IP_CHANGED:
|
||||||
netconfig, NULL);
|
case L_DHCP6_CLIENT_EVENT_LEASE_OBTAINED:
|
||||||
|
case L_DHCP6_CLIENT_EVENT_LEASE_RENEWED:
|
||||||
if (getenv("IWD_DHCP_DEBUG"))
|
break;
|
||||||
l_dhcp_client_set_debug(netconfig->dhcp_client, do_debug,
|
case L_DHCP6_CLIENT_EVENT_LEASE_EXPIRED:
|
||||||
"[DHCPv4] ", NULL);
|
l_debug("Lease for interface %u expired", netconfig->ifindex);
|
||||||
|
break;
|
||||||
return true;
|
case L_DHCP6_CLIENT_EVENT_NO_LEASE:
|
||||||
|
l_error("netconfig: Failed to obtain DHCPv6 lease "
|
||||||
|
"for interface %u", netconfig->ifindex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netconfig_ipv4_select_and_install(struct netconfig *netconfig)
|
static void netconfig_ipv4_select_and_install(struct netconfig *netconfig)
|
||||||
@ -1061,17 +1127,7 @@ static void netconfig_ipv6_select_and_install(struct netconfig *netconfig)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
netconfig->rtm_v6_protocol = RTPROT_DHCP;
|
||||||
* TODO
|
|
||||||
*
|
|
||||||
* netconfig->rtm_v6_protocol = RTPROT_DHCP;
|
|
||||||
*
|
|
||||||
* if (l_dhcp_v6_client_start(netconfig->l_dhcp_v6_client))
|
|
||||||
* return;
|
|
||||||
*
|
|
||||||
* l_error("netconfig: Failed to start DHCPv6 client for "
|
|
||||||
* "interface %u", netconfig->ifindex);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netconfig_ipv6_select_and_uninstall(struct netconfig *netconfig)
|
static void netconfig_ipv6_select_and_uninstall(struct netconfig *netconfig)
|
||||||
@ -1079,6 +1135,8 @@ static void netconfig_ipv6_select_and_uninstall(struct netconfig *netconfig)
|
|||||||
struct netconfig_ifaddr *ifaddr;
|
struct netconfig_ifaddr *ifaddr;
|
||||||
char *gateway;
|
char *gateway;
|
||||||
|
|
||||||
|
l_dhcp6_client_stop(netconfig->dhcp6_client);
|
||||||
|
|
||||||
ifaddr = netconfig_ipv6_get_ifaddr(netconfig,
|
ifaddr = netconfig_ipv6_get_ifaddr(netconfig,
|
||||||
netconfig->rtm_v6_protocol);
|
netconfig->rtm_v6_protocol);
|
||||||
if (ifaddr) {
|
if (ifaddr) {
|
||||||
@ -1086,11 +1144,6 @@ static void netconfig_ipv6_select_and_uninstall(struct netconfig *netconfig)
|
|||||||
netconfig_ifaddr_destroy(ifaddr);
|
netconfig_ifaddr_destroy(ifaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO
|
|
||||||
* l_dhcp_v6_client_stop(netconfig->l_dhcp_v6_client);
|
|
||||||
*/
|
|
||||||
|
|
||||||
gateway = netconfig_ipv6_get_gateway(netconfig);
|
gateway = netconfig_ipv6_get_gateway(netconfig);
|
||||||
if (!gateway)
|
if (!gateway)
|
||||||
return;
|
return;
|
||||||
@ -1117,6 +1170,8 @@ bool netconfig_configure(struct netconfig *netconfig,
|
|||||||
|
|
||||||
l_dhcp_client_set_address(netconfig->dhcp_client, ARPHRD_ETHER,
|
l_dhcp_client_set_address(netconfig->dhcp_client, ARPHRD_ETHER,
|
||||||
mac_address, ETH_ALEN);
|
mac_address, ETH_ALEN);
|
||||||
|
l_dhcp6_client_set_address(netconfig->dhcp6_client, ARPHRD_ETHER,
|
||||||
|
mac_address, ETH_ALEN);
|
||||||
|
|
||||||
netconfig_ipv4_select_and_install(netconfig);
|
netconfig_ipv4_select_and_install(netconfig);
|
||||||
|
|
||||||
@ -1167,7 +1222,9 @@ char *netconfig_get_dhcp_server_ipv4(struct netconfig *netconfig)
|
|||||||
|
|
||||||
struct netconfig *netconfig_new(uint32_t ifindex)
|
struct netconfig *netconfig_new(uint32_t ifindex)
|
||||||
{
|
{
|
||||||
|
struct netdev *netdev = netdev_find(ifindex);
|
||||||
struct netconfig *netconfig;
|
struct netconfig *netconfig;
|
||||||
|
struct l_icmp6_client *icmp6;
|
||||||
|
|
||||||
if (!netconfig_list)
|
if (!netconfig_list)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1183,10 +1240,35 @@ struct netconfig *netconfig_new(uint32_t ifindex)
|
|||||||
netconfig->ifaddr_list = l_queue_new();
|
netconfig->ifaddr_list = l_queue_new();
|
||||||
netconfig->resolve = resolve_new(ifindex);
|
netconfig->resolve = resolve_new(ifindex);
|
||||||
|
|
||||||
netconfig_ipv4_dhcp_create(netconfig);
|
netconfig->dhcp_client = l_dhcp_client_new(ifindex);
|
||||||
|
l_dhcp_client_set_event_handler(netconfig->dhcp_client,
|
||||||
|
netconfig_ipv4_dhcp_event_handler,
|
||||||
|
netconfig, NULL);
|
||||||
|
|
||||||
|
if (getenv("IWD_DHCP_DEBUG"))
|
||||||
|
l_dhcp_client_set_debug(netconfig->dhcp_client, do_debug,
|
||||||
|
"[DHCPv4] ", NULL);
|
||||||
|
|
||||||
|
netconfig->dhcp6_client = l_dhcp6_client_new(ifindex);
|
||||||
|
l_dhcp6_client_set_event_handler(netconfig->dhcp6_client,
|
||||||
|
netconfig_dhcp6_event_handler,
|
||||||
|
netconfig, NULL);
|
||||||
|
l_dhcp6_client_set_lla_randomized(netconfig->dhcp6_client, true);
|
||||||
|
l_dhcp6_client_set_nodelay(netconfig->dhcp6_client, true);
|
||||||
|
l_dhcp6_client_set_rtnl(netconfig->dhcp6_client, rtnl);
|
||||||
|
|
||||||
|
if (getenv("IWD_DHCP_DEBUG"))
|
||||||
|
l_dhcp6_client_set_debug(netconfig->dhcp6_client, do_debug,
|
||||||
|
"[DHCPv6] ", NULL);
|
||||||
|
|
||||||
|
icmp6 = l_dhcp6_client_get_icmp6(netconfig->dhcp6_client);
|
||||||
|
l_icmp6_client_set_rtnl(icmp6, rtnl);
|
||||||
|
l_icmp6_client_set_route_priority(icmp6, ROUTE_PRIORITY_OFFSET);
|
||||||
|
|
||||||
l_queue_push_tail(netconfig_list, netconfig);
|
l_queue_push_tail(netconfig_list, netconfig);
|
||||||
|
|
||||||
|
sysfs_write_ipv6_setting(netdev_get_name(netdev), "accept_ra", "0");
|
||||||
|
|
||||||
return netconfig;
|
return netconfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user