netconfig: Subscribe for IPv6 address changes
PATCH v3 1/5 netconfig: Subscribe for IPv6 address changes
The IPv6 addresses changes are maintained in ifaddr_list.
--- src/netconfig.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 7 deletions(-)
src/netconfig.c +98 -7
@@ -224,6 +224,23 @@ static char **netconfig_ipv4_get_dns(struct netconfig *netconfig, uint8_t proto)return NULL ; } +static bool netconfig_ifaddr_match (const void *a,const void *b) +{ +const struct netconfig_ifaddr *entry = a; +const struct netconfig_ifaddr *query = b; + +if (entry->family != query->family) +return false; + +if (entry->prefix_len != query->prefix_len) +return false; + +if (strcmp (entry->ip, query->ip)) +return false; + +return true; +} + static struct netconfig_ifaddr *netconfig_ifaddr_find( const struct netconfig *netconfig, uint8_t family, uint8_t prefix_len,
@@ -276,22 +293,22 @@ static void netconfig_ifaddr_deleted(struct netconfig *netconfig, uint32_t len) {struct netconfig_ifaddr *ifaddr; -char *ip; +struct netconfig_ifaddr query; -rtnl_ifaddr_extract (ifa, len,NULL , &ip,NULL ); +rtnl_ifaddr_extract (ifa, len,NULL , &query.ip,NULL ); - ifaddr =netconfig_ifaddr_find (netconfig, ifa->ifa_family, - ifa->ifa_prefixlen, ip); + query.family = ifa->ifa_family; + query.prefix_len = ifa->ifa_prefixlen; -l_free (ip); + ifaddr =l_queue_remove_if (netconfig->ifaddr_list, + netconfig_ifaddr_match, &query); +l_free (query.ip);if (!ifaddr)return ;l_debug ("ifaddr %s/%u" , ifaddr->ip, ifaddr->prefix_len); -l_queue_remove (netconfig->ifaddr_list, ifaddr); -netconfig_ifaddr_destroy (ifaddr); }
@@ -335,6 +352,72 @@ static void netconfig_ifaddr_cmd_cb(int error, uint16_t type,netconfig_ifaddr_notify (type, data, len, user_data); } +static void netconfig_ifaddr_ipv6_added (struct netconfig *netconfig, +const struct ifaddrmsg *ifa, +uint32_t len) +{ +struct netconfig_ifaddr *ifaddr; + + ifaddr = l_new(struct netconfig_ifaddr, 1); + ifaddr->family = ifa->ifa_family; + ifaddr->prefix_len = ifa->ifa_prefixlen; + +rtnl_ifaddr_ipv6_extract (ifa, len, &ifaddr->ip); + +l_debug ("ifindex %u: ifaddr %s/%u" , netconfig->ifindex, ifaddr->ip, + ifaddr->prefix_len); + +l_queue_push_tail (netconfig->ifaddr_list, ifaddr); +} + +static void netconfig_ifaddr_ipv6_deleted (struct netconfig *netconfig, +const struct ifaddrmsg *ifa, +uint32_t len) +{ +struct netconfig_ifaddr *ifaddr; +char *ip; + +rtnl_ifaddr_ipv6_extract (ifa, len, &ip); + + ifaddr =netconfig_ifaddr_find (netconfig, ifa->ifa_family, + ifa->ifa_prefixlen, ip); + +l_free (ip); + +if (!ifaddr) +return ; + +l_debug ("ifaddr %s/%u" , ifaddr->ip, ifaddr->prefix_len); + +l_queue_remove (netconfig->ifaddr_list, ifaddr); + +netconfig_ifaddr_destroy (ifaddr); +} + +static void netconfig_ifaddr_ipv6_notify (uint16_t type,const void *data, +uint32_t len,void *user_data) +{ +const struct ifaddrmsg *ifa = data; +struct netconfig *netconfig; +uint32_t bytes; + + netconfig =netconfig_find (ifa->ifa_index); +if (!netconfig) +/* Ignore the interfaces which aren't managed by iwd. */ +return ; + + bytes = len -NLMSG_ALIGN (sizeof (struct ifaddrmsg )); + +switch (type) { +case RTM_NEWADDR : +netconfig_ifaddr_ipv6_added (netconfig, ifa, bytes); +break ; +case RTM_DELADDR : +netconfig_ifaddr_ipv6_deleted (netconfig, ifa, bytes); +break ; + } +} +static void netconfig_route_cmd_cb (int error,uint16_t type,const void *data,uint32_t len,void *user_data)
@@ -757,6 +840,14 @@ static int netconfig_init(void) goto error; } + r =l_netlink_register (rtnl,RTNLGRP_IPV6_IFADDR , + netconfig_ifaddr_ipv6_notify,NULL ,NULL ); +if (!r) { +l_error ("netconfig: Failed to register for RTNL link IPv6 " +"address notifications." ); + goto error; + } +if (!l_settings_get_uint (iwd_get_config (),"General" ,"route_priority_offset" , &ROUTE_PRIORITY_OFFSET ))
Signature · 1 line
2.13.6
PATCH v3 2/5 netconfig: Request all known IPv6 addresses
--- src/netconfig.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
src/netconfig.c +24 -0
@@ -418,6 +418,22 @@ static void netconfig_ifaddr_ipv6_notify(uint16_t type, const void *data, } } +static void netconfig_ifaddr_ipv6_cmd_cb (int error,uint16_t type, +const void *data,uint32_t len, +void *user_data) +{ +if (error) { +l_error ("netconfig: ifaddr IPv6 command failure. " +"Error %d: %s" , error,strerror (-error)); +return ; + } + +if (type !=RTM_NEWADDR ) +return ; + +netconfig_ifaddr_ipv6_notify (type, data, len, user_data); +} +static void netconfig_route_cmd_cb (int error,uint16_t type,const void *data,uint32_t len,void *user_data)
@@ -848,6 +864,14 @@ static int netconfig_init(void) goto error; } + r =rtnl_ifaddr_ipv6_get (rtnl, netconfig_ifaddr_ipv6_cmd_cb,NULL , +NULL ); +if (!r) { +l_error ("netconfig: Failed to get IPv6 addresses from RTNL" +" link." ); + goto error; + } +if (!l_settings_get_uint (iwd_get_config (),"General" ,"route_priority_offset" , &ROUTE_PRIORITY_OFFSET ))
Signature · 1 line
2.13.6
PATCH v3 3/5 netconfig: Add IPv6 static address installation/removal
In reply to Tim KourtThe network configuration options for IPv6 are grouped under [IPv6] and include the following:
ip= ADDRESS/PREFIX
gateway=ADDRESS
dns=ADDRESS
The placeholders for DHCPv6 are placed along the way and marked as TODO items.
--- src/netconfig.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 163 insertions(+), 9 deletions(-)
src/netconfig.c +163 -9
@@ -48,6 +48,7 @@ struct netconfig {struct l_dhcp_client *dhcp_client;struct l_queue *ifaddr_list;uint8_t rtm_protocol; +uint8_t rtm_v6_protocol;const struct l_settings *active_settings; };
@@ -224,6 +225,70 @@ static char **netconfig_ipv4_get_dns(struct netconfig *netconfig, uint8_t proto)return NULL ; } +static struct netconfig_ifaddr *netconfig_ipv6_get_ifaddr ( +struct netconfig *netconfig, +uint8_t proto) +{ +struct in6_addr in6_addr; +struct netconfig_ifaddr *ifaddr; +char *ip; +char *p; + +switch (proto) { +case RTPROT_STATIC : +if (!netconfig->active_settings) +return NULL ; + + ip =l_settings_get_string (netconfig->active_settings,"IPv6" , +"ip" ); +if (!ip) +return NULL ; + + ifaddr = l_new(struct netconfig_ifaddr, 1); + ifaddr->ip = ip; + + p =strrchr (ifaddr->ip,'/' ); +if (!p) + goto no_prefix_len; + + *p ='\0' ; + +if (inet_pton (AF_INET6 , ifaddr->ip, &in6_addr) <1 ) { +l_error ("netconfig: Invalid IPv6 address %s is " +"provided in network configuration file." , + ifaddr->ip); + +netconfig_ifaddr_destroy (ifaddr); + +return NULL ; + } + +if (*++p =='\0' ) + goto no_prefix_len; + + ifaddr->prefix_len =strtoul (p,NULL ,10 ); + +if (!unlikely (errno ==EINVAL || errno ==ERANGE || + !ifaddr->prefix_len || + ifaddr->prefix_len >128 )) + goto proceed; + +no_prefix_len: + ifaddr->prefix_len =128 ; +proceed: + ifaddr->family =AF_INET6 ; + +return ifaddr; + +case RTPROT_DHCP : +/* TODO */ + +return NULL ; + } + +return NULL ; +} +static bool netconfig_ifaddr_match (const void *a,const void *b) {const struct netconfig_ifaddr *entry = a;
@@ -540,6 +605,19 @@ done:netconfig_ifaddr_destroy (ifaddr); } +static void netconfig_ipv6_ifaddr_add_cmd_cb (int error,uint16_t type, +const void *data,uint32_t len, +void *user_data) +{ +if (error && error != -EEXIST ) { +l_error ("netconfig: Failed to add IPv6 address. " +"Error %d: %s" , error,strerror (-error)); +return ; + } + +/* TODO Install routes and DNS */ +} +static void netconfig_install_address (struct netconfig *netconfig,struct netconfig_ifaddr *ifaddr) {
@@ -559,6 +637,16 @@ static void netconfig_install_address(struct netconfig *netconfig,l_error ("netconfig: Failed to set IP %s/%u." , ifaddr->ip, ifaddr->prefix_len);break ; +case AF_INET6 : +if (rtnl_ifaddr_ipv6_add (rtnl, netconfig->ifindex, + ifaddr->prefix_len, ifaddr->ip, + netconfig_ipv6_ifaddr_add_cmd_cb, + netconfig,NULL )) +return ; + +l_error ("netconfig: Failed to set IPv6 address %s/%u." , + ifaddr->ip, ifaddr->prefix_len); +break ;default :l_error ("netconfig: Unsupported address family: %u" , ifaddr->family);
@@ -605,6 +693,16 @@ static void netconfig_uninstall_address(struct netconfig *netconfig,l_error ("netconfig: Failed to delete IP %s/%u." , ifaddr->ip, ifaddr->prefix_len);break ; +case AF_INET6 : +if (rtnl_ifaddr_ipv6_delete (rtnl, netconfig->ifindex, + ifaddr->prefix_len, ifaddr->ip, + netconfig_ifaddr_del_cmd_cb, netconfig, +NULL )) +return ; + +l_error ("netconfig: Failed to delete IPv6 address %s/%u." , + ifaddr->ip, ifaddr->prefix_len); +break ;default :l_error ("netconfig: Unsupported address family: %u" , ifaddr->family);
@@ -725,6 +823,51 @@ static void netconfig_ipv4_select_and_uninstall(struct netconfig *netconfig)l_dhcp_client_stop (netconfig->dhcp_client); } +static void netconfig_ipv6_select_and_install (struct netconfig *netconfig) +{ +struct netconfig_ifaddr *ifaddr; + + ifaddr =netconfig_ipv6_get_ifaddr (netconfig,RTPROT_STATIC ); +if (ifaddr) { + netconfig->rtm_v6_protocol =RTPROT_STATIC ; +netconfig_install_address (netconfig, ifaddr); +netconfig_ifaddr_destroy (ifaddr); + +return ; + } + +/* +* TODO +* +* netconfig->rtm_v6_protocol = RTPROT_DHCP; +* +* netconfig_ipv6_dhcp_set_mac_address(netconfig); +* +* 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) +{ +struct netconfig_ifaddr *ifaddr; + + ifaddr =netconfig_ipv6_get_ifaddr (netconfig, + netconfig->rtm_v6_protocol); +if (ifaddr) { +netconfig_uninstall_address (netconfig, ifaddr); +netconfig_ifaddr_destroy (ifaddr); + } + +/* +* TODO +* l_dhcp_v6_client_stop(netconfig->l_dhcp_v6_client); +*/ +} +bool netconfig_configure (struct netconfig *netconfig,const struct l_settings *active_settings,const uint8_t *mac_address)
@@ -736,7 +879,7 @@ bool netconfig_configure(struct netconfig *netconfig,netconfig_ipv4_select_and_install (netconfig); -/* TODO: IPv6 addressing */ +netconfig_ipv6_select_and_install (netconfig);return true; }
@@ -749,13 +892,23 @@ bool netconfig_reconfigure(struct netconfig *netconfig)* TODO l_dhcp_client to try to request a * previously used address. * -* return; +* goto ipv6; */ }netconfig_ipv4_select_and_install (netconfig); -/* TODO: IPv6 addressing */ +if (netconfig->rtm_v6_protocol ==RTPROT_DHCP ) { +/* +* +* TODO l_dhcp_v6_client to try to request a +* previously used address. +* +* return +*/ + } + +netconfig_ipv6_select_and_install (netconfig);return true; }
@@ -763,13 +916,13 @@ bool netconfig_reconfigure(struct netconfig *netconfig)bool netconfig_reset (struct netconfig *netconfig) {netconfig_ipv4_select_and_uninstall (netconfig); + netconfig->rtm_protocol =0 ; -/* TODO: IPv6 addressing */ +netconfig_ipv6_select_and_uninstall (netconfig); + netconfig->rtm_v6_protocol =0 ;resolve_remove (netconfig->ifindex); - netconfig->rtm_protocol =0 ; -return true; }
@@ -806,13 +959,14 @@ void netconfig_destroy(struct netconfig *netconfig)l_queue_remove (netconfig_list, netconfig); -if (netconfig->rtm_protocol) { +if (netconfig->rtm_protocol)netconfig_ipv4_select_and_uninstall (netconfig); -/* TODO Uninstall IPv6 addresses. */ +if (netconfig->rtm_v6_protocol) +netconfig_ipv6_select_and_uninstall (netconfig); +if (netconfig->rtm_protocol || netconfig->rtm_v6_protocol)resolve_remove (netconfig->ifindex); - }netconfig_free (netconfig); }
Signature · 1 line
2.13.6
PATCH v3 4/5 netconfig: Install IPv6 default route
In reply to Tim Kourt--- src/netconfig.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-)
src/netconfig.c +70 -1
@@ -289,6 +289,40 @@ proceed:return NULL ; } +static char *netconfig_ipv6_get_gateway (struct netconfig *netconfig) +{ +struct in6_addr in6_addr; +char *gateway; + +switch (netconfig->rtm_v6_protocol) { +case RTPROT_STATIC : +if (!netconfig->active_settings) +return NULL ; + + gateway =l_settings_get_string (netconfig->active_settings, +"IPv6" ,"gateway" ); + +if (inet_pton (AF_INET6 , gateway, &in6_addr) <1 ) { +l_error ("netconfig: Invalid IPv6 gateway address %s is " +"provided in network configuration file." , + gateway); + +l_free (gateway); + +return NULL ; + } + +return gateway; + +case RTPROT_DHCP : +/* TODO */ + +return NULL ; + } + +return NULL ; +} +static bool netconfig_ifaddr_match (const void *a,const void *b) {const struct netconfig_ifaddr *entry = a;
@@ -605,17 +639,52 @@ done:netconfig_ifaddr_destroy (ifaddr); } +static bool netconfig_ipv6_routes_install (struct netconfig *netconfig) +{ + L_AUTO_FREE_VAR(char *, gateway) = NULL; + + gateway =netconfig_ipv6_get_gateway (netconfig); +if (!gateway) { +l_error ("netconfig: Failed to obtain gateway from %s." , + netconfig->rtm_v6_protocol ==RTPROT_STATIC ? +"settings file" :"DHCPv6 lease" ); + +return false; + } + +if (!rtnl_route_ipv6_add_gateway (rtnl, netconfig->ifindex, gateway, +ROUTE_PRIORITY_OFFSET , + netconfig->rtm_v6_protocol, + netconfig_route_cmd_cb, +NULL ,NULL )) { +l_error ("netconfig: Failed to add route for: %s gateway." , + gateway); + +return false; + } + +return true; +} +static void netconfig_ipv6_ifaddr_add_cmd_cb (int error,uint16_t type,const void *data,uint32_t len,void *user_data) { +struct netconfig *netconfig = user_data; +if (error && error != -EEXIST ) {l_error ("netconfig: Failed to add IPv6 address. " "Error %d: %s" , error,strerror (-error));return ; } -/* TODO Install routes and DNS */ +if (!netconfig_ipv6_routes_install (netconfig)) { +l_error ("netconfig: Failed to install IPv6 routes." ); + +return ; + } + +/* TODO Install DNS */ } static void netconfig_install_address(struct netconfig *netconfig,
Signature · 1 line
2.13.6
PATCH v3 5/5 netconfig: Install IPv6 DNS
In reply to Tim Kourt--- src/netconfig.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-)
src/netconfig.c +55 -1
@@ -323,6 +323,50 @@ static char *netconfig_ipv6_get_gateway(struct netconfig *netconfig)return NULL ; } +static char **netconfig_ipv6_get_dns (struct netconfig *netconfig,uint8_t proto) +{ +struct in6_addr in6_addr; +char **dns_list; +char **p; + +switch (proto) { +case RTPROT_STATIC : +if (!netconfig->active_settings) +return NULL ; + + p = dns_list = +l_settings_get_string_list (netconfig->active_settings, +"IPv6" ,"dns" ,' ' ); + +if (!dns_list || !*dns_list) { +l_strv_free (dns_list); + +return NULL ; + } + +for (; *p; p++) { +if (inet_pton (AF_INET6 , *p, &in6_addr) ==1 ) +continue ; + +l_error ("netconfig: Invalid IPv6 DNS address %s is " +"provided in network configuration file." , *p); + +l_strv_free (dns_list); + +return NULL ; + } + +return dns_list; + +case RTPROT_DHCP : +/* TODO */ + +return NULL ; + } + +return NULL ; +} +static bool netconfig_ifaddr_match (const void *a,const void *b) {const struct netconfig_ifaddr *entry = a;
@@ -671,6 +715,7 @@ static void netconfig_ipv6_ifaddr_add_cmd_cb(int error, uint16_t type, void *user_data) {struct netconfig *netconfig = user_data; +char **dns;if (error && error != -EEXIST ) { l_error("netconfig: Failed to add IPv6 address. "
@@ -684,7 +729,16 @@ static void netconfig_ipv6_ifaddr_add_cmd_cb(int error, uint16_t type,return ; } -/* TODO Install DNS */ + dns =netconfig_ipv6_get_dns (netconfig, netconfig->rtm_v6_protocol); +if (!dns) { +l_error ("netconfig: Failed to obtain the DNS addresses from " +"%s." , netconfig->rtm_v6_protocol ==RTPROT_STATIC ? +"setting file" :"DHCPv6 lease" ); +return ; + } + +resolve_add_dns (netconfig->ifindex,AF_INET6 , dns); +l_strv_free (dns); } static void netconfig_install_address(struct netconfig *netconfig,
Signature · 1 line
2.13.6