Re: [systemd-devel] About DNS servers and search domains in Router Advertisements

2017-09-29 Thread Patrik Flykt

Hi,

On Fri, 2017-09-22 at 17:07 +0200, Lennart Poettering wrote:
> So, of course, people might want arbitrary complex schemes there, but
> I'd probably keep it simple at least in the beginning, and try to be
> as automatic as possible...
> 
> maybe we should have a structure DNSConfiguration or so, which
> carries all DNS servers and search domains acquired from a specific
> source, where "source" refers to either the DNS data attached to an
> interface or DNS data attached to networkd's global configuration or
> DNS data read from /etc/resolv.conf.

That should be the goal. Right now most of the below can be implemented
quite easily:

> When EmitDNS=/EmitDomains= is set we'd try to find the most suitable
> such DNSConfiguration structure and propagate that.

Yes. Here we want to have independent but identical handling of DNS and
Domains.

>  Specifically I figure the most suitable could be the first one we
> find by checking the following list:

The trivial case is that RADV is configured, so as first option we
have:

  0. DNS data configured specifically for RADV

> 1. DNS data configured on the interface the RADV server is on itself,
>    if there is any
> 2. global DNS data configured for networkd in networkd.conf or so, if
>    there is any
> 3. global DNS data configured in /etc/resolv.conf, if there is any
> 4. DNS data of the interface the default route goes to (if this isn't
>    unique, then search through all interfaces and pick the one with
>    the lowest metric on the default route and if that still doesn't 
>help pick the one with the lowest ifindex
> 5. DNS data of any other interface (if there are multiple, use the 
>    with the lowest ifindex)

From this list (0.,) 1. and 4. seem trivial to implement, especially
since there already is an manager_find_uplink(). I'll focus on those
two first.

> Or something like that. I figure initially this could be implemented
> much simpler than the list above, but I think such an automatic logic
> would be highly desirable in the long run, because it maximizes the
> chance we can automatically do the right thing...

Yep, I played around at home, and noticed that one indeed wants to
reuse already added configuration items, at least using 1. and 4.
above.

Patch incoming soonishly.


Cheers,

Patrik
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] About DNS servers and search domains in Router Advertisements

2017-09-22 Thread Patrik Flykt


Hi,

Now that we have Router Advertisements and are able to also send
statically configured DNS servers and DNS search domains, I wonder
which set of DNS servers makes most sense to automatically add in
Router Advertisements.

The current status quo is DHCPv4, where one can configure the use of
the uplink DNS servers by setting EmitDNS=true and leaving DNS= server
list empty in the DHCPServer section. The easy way out is to define the
same variable and behavior for Router Advertisements, but what about
the other DNS servers that may be specified in other interfaces'
.network files or received via DHCP over these interfaces?

For example, there might be an interface that is neither the default
uplink, nor the current interface that is sending Router
Advertisements, but it nevertheless has DNS servers configured. Such
DNS servers are not considered by the DHCPv4 server at the moment,
might there have been a sinister plan behind this behavior?

One thing that cannot be added automatically to networkd are of course
the DNS servers configured directly to resolved.conf or any fallback
DNS servers. In addition, since search domains can also be sent, the
same policy is applicable to them - or is it? If we figure out what the
policy for DNS search domains is, the search domains should of course
also be sent out in DHCPv4 server messages.


Cheers,

Patrik
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 08/11] sd-dhcp6: Support deprecated SNTP Configuration Option

2015-07-10 Thread Patrik Flykt
Although the SNTP option specified in RFC 4075 has been deprecated, some
servers are still sending NTP information with this option. Use the SNTP
information provided only if the NTP option is not present.

Update the test case as SNTP information is also requested.
---
 src/libsystemd-network/dhcp6-lease-internal.h |  2 ++
 src/libsystemd-network/dhcp6-protocol.h   |  2 +-
 src/libsystemd-network/sd-dhcp6-client.c  |  8 ++
 src/libsystemd-network/sd-dhcp6-lease.c   | 36 +++
 src/libsystemd-network/test-dhcp6-client.c|  2 +-
 5 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/src/libsystemd-network/dhcp6-lease-internal.h 
b/src/libsystemd-network/dhcp6-lease-internal.h
index ac7f843..037f580 100644
--- a/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/libsystemd-network/dhcp6-lease-internal.h
@@ -71,6 +71,8 @@ int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t 
*optval, size_t optlen);
 int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
 size_t optlen);
 int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
+int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval,
+ size_t optlen) ;
 
 int dhcp6_lease_new(sd_dhcp6_lease **ret);
 
diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index 9330f23..b3a28f8 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -123,7 +123,7 @@ enum {
 DHCP6_OPTION_DNS_SERVERS= 23,  /* RFC 3646 */
 DHCP6_OPTION_DOMAIN_LIST= 24,  /* RFC 3646 */
 
-DHCP6_OPTION_SNTP_SERVERS   = 31,  /* RFC 4075 */
+DHCP6_OPTION_SNTP_SERVERS   = 31,  /* RFC 4075, deprecated 
*/
 
 /* option code 35 is unassigned */
 
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index e6f0c79..ffab1e4 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -73,6 +73,7 @@ static const uint16_t default_req_opts[] = {
 DHCP6_OPTION_DNS_SERVERS,
 DHCP6_OPTION_DOMAIN_LIST,
 DHCP6_OPTION_NTP_SERVER,
+DHCP6_OPTION_SNTP_SERVERS,
 };
 
 const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
@@ -774,6 +775,13 @@ static int client_parse_message(sd_dhcp6_client *client,
 return r;
 
 break;
+
+case DHCP6_OPTION_SNTP_SERVERS:
+r = dhcp6_lease_set_sntp(lease, optval, optlen);
+if (r < 0)
+return r;
+
+break;
 }
 
 }
diff --git a/src/libsystemd-network/sd-dhcp6-lease.c 
b/src/libsystemd-network/sd-dhcp6-lease.c
index 8631aab..f0494b3 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -257,6 +257,10 @@ int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t 
*optval, size_t optlen)
 assert_return(lease, -EINVAL);
 assert_return(optval, -EINVAL);
 
+free(lease->ntp);
+lease->ntp_count = 0;
+lease->ntp_allocated = 0;
+
 while ((r = dhcp6_option_parse(&optval, &optlen, &subopt, &sublen,
&subval)) >= 0) {
 int s;
@@ -299,6 +303,38 @@ int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t 
*optval, size_t optlen)
 return 0;
 }
 
+int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t 
optlen) {
+int r;
+
+assert_return(lease, -EINVAL);
+assert_return(optval, -EINVAL);
+
+if (!optlen)
+return 0;
+
+if (lease->ntp || lease->ntp_fqdn) {
+log_dhcp6_client(client, "NTP information already provided");
+
+return 0;
+}
+
+log_dhcp6_client(client, "Using deprecated SNTP information");
+
+r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp,
+lease->ntp_count,
+&lease->ntp_allocated);
+if (r < 0) {
+log_dhcp6_client(client, "Invalid SNTP server option: %s",
+ strerror(-r));
+
+return r;
+}
+
+lease->ntp_count = r;
+
+return 0;
+}
+
 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease,
  struct in6_addr **addrs) {
 assert_return(lease, -EINVAL);
diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index 7618547..b61fd38 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -73,7 +73,7 @@ static int test_client_basic(sd_event *e) {
 assert_se(sd

[systemd-devel] [PATCH 07/11] sd-dhcp6: Add support for DHCPv6 NTP Server Option

2015-07-10 Thread Patrik Flykt
Support NTP server and multicast addresses and NTP server domain names
as specified in RFC 5908.
---
 src/libsystemd-network/dhcp6-lease-internal.h |  7 +++
 src/libsystemd-network/dhcp6-protocol.h   |  6 ++
 src/libsystemd-network/sd-dhcp6-client.c  |  7 +++
 src/libsystemd-network/sd-dhcp6-lease.c   | 81 +++
 src/systemd/sd-dhcp6-lease.h  |  3 +
 5 files changed, 104 insertions(+)

diff --git a/src/libsystemd-network/dhcp6-lease-internal.h 
b/src/libsystemd-network/dhcp6-lease-internal.h
index 37e7001..ac7f843 100644
--- a/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/libsystemd-network/dhcp6-lease-internal.h
@@ -46,6 +46,11 @@ struct sd_dhcp6_lease {
 size_t dns_allocated;
 char **domains;
 size_t domains_count;
+struct in6_addr *ntp;
+size_t ntp_count;
+size_t ntp_allocated;
+char **ntp_fqdn;
+size_t ntp_fqdn_count;
 };
 
 int dhcp6_lease_clear_timers(DHCP6IA *ia);
@@ -65,6 +70,8 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
 int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
 int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
 size_t optlen);
+int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
+
 int dhcp6_lease_new(sd_dhcp6_lease **ret);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref);
diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index 3e0f339..9330f23 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -134,6 +134,12 @@ enum {
 };
 
 enum {
+DHCP6_NTP_SUBOPTION_SRV_ADDR= 1,
+DHCP6_NTP_SUBOPTION_MC_ADDR = 2,
+DHCP6_NTP_SUBOPTION_SRV_FQDN= 3,
+};
+
+enum {
 DHCP6_STATUS_SUCCESS= 0,
 DHCP6_STATUS_UNSPEC_FAIL= 1,
 DHCP6_STATUS_NO_ADDRS_AVAIL = 2,
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index bea7a7a..e6f0c79 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -768,7 +768,14 @@ static int client_parse_message(sd_dhcp6_client *client,
 
 break;
 
+case DHCP6_OPTION_NTP_SERVER:
+r = dhcp6_lease_set_ntp(lease, optval, optlen);
+if (r < 0)
+return r;
+
+break;
 }
+
 }
 
 if (r == -ENOMSG)
diff --git a/src/libsystemd-network/sd-dhcp6-lease.c 
b/src/libsystemd-network/sd-dhcp6-lease.c
index ca63800..8631aab 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -26,6 +26,7 @@
 #include "util.h"
 
 #include "dhcp6-lease-internal.h"
+#include "dhcp6-protocol.h"
 
 int dhcp6_lease_clear_timers(DHCP6IA *ia) {
 assert_return(ia, -EINVAL);
@@ -246,6 +247,83 @@ int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char 
***domains) {
 return -ENOENT;
 }
 
+int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen)
+{
+int r;
+uint16_t subopt;
+size_t sublen;
+uint8_t *subval;
+
+assert_return(lease, -EINVAL);
+assert_return(optval, -EINVAL);
+
+while ((r = dhcp6_option_parse(&optval, &optlen, &subopt, &sublen,
+   &subval)) >= 0) {
+int s;
+char **servers;
+
+switch(subopt) {
+case DHCP6_NTP_SUBOPTION_SRV_ADDR:
+case DHCP6_NTP_SUBOPTION_MC_ADDR:
+if (sublen != 16)
+return 0;
+
+s = dhcp6_option_parse_ip6addrs(subval, sublen,
+&lease->ntp,
+lease->ntp_count,
+&lease->ntp_allocated);
+if (s < 0)
+return s;
+
+lease->ntp_count = s;
+
+break;
+
+case DHCP6_NTP_SUBOPTION_SRV_FQDN:
+r = dhcp6_option_parse_domainname(subval, sublen,
+  &servers);
+if (r < 0)
+return 0;
+
+lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
+lease->ntp_fqdn = servers;
+lease->ntp_fqdn_count = r;
+
+break;
+}
+}
+
+if (r != -ENOMSG)
+return r;
+
+return 0;
+}
+
+int sd_dhcp6_lease

[systemd-devel] [PATCH 06/11] sd-dhcp6: Add support for DHCPv6 DNS Domain Search List option

2015-07-10 Thread Patrik Flykt
Support DHCPv6 DNS search list option as specified in RFC 3646. This
option contains a list of DNS search domains encoded without compression
as specified in Section 8. of RFC 3315.
---
 src/libsystemd-network/dhcp6-lease-internal.h |  4 +++
 src/libsystemd-network/sd-dhcp6-client.c  |  8 +
 src/libsystemd-network/sd-dhcp6-lease.c   | 42 ++-
 src/systemd/sd-dhcp6-lease.h  |  1 +
 4 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/src/libsystemd-network/dhcp6-lease-internal.h 
b/src/libsystemd-network/dhcp6-lease-internal.h
index 0dad0a5..37e7001 100644
--- a/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/libsystemd-network/dhcp6-lease-internal.h
@@ -44,6 +44,8 @@ struct sd_dhcp6_lease {
 struct in6_addr *dns;
 size_t dns_count;
 size_t dns_allocated;
+char **domains;
+size_t domains_count;
 };
 
 int dhcp6_lease_clear_timers(DHCP6IA *ia);
@@ -61,6 +63,8 @@ int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool 
*rapid_commit);
 int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
 
 int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
+int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
+size_t optlen);
 int dhcp6_lease_new(sd_dhcp6_lease **ret);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref);
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index f0c7949..bea7a7a 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -760,6 +760,14 @@ static int client_parse_message(sd_dhcp6_client *client,
 return r;
 
 break;
+
+case DHCP6_OPTION_DOMAIN_LIST:
+r = dhcp6_lease_set_domains(lease, optval, optlen);
+if (r < 0)
+return r;
+
+break;
+
 }
 }
 
diff --git a/src/libsystemd-network/sd-dhcp6-lease.c 
b/src/libsystemd-network/sd-dhcp6-lease.c
index 55cefde..ca63800 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -1,8 +1,10 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
 /***
   This file is part of systemd.
 
   Copyright (C) 2014 Tom Gundersen
-  Copyright (C) 2014 Intel Corporation. All rights reserved.
+  Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
 
   systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
@@ -20,6 +22,7 @@
 
 #include 
 
+#include "strv.h"
 #include "util.h"
 
 #include "dhcp6-lease-internal.h"
@@ -209,6 +212,40 @@ int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct 
in6_addr **addrs) {
 return -ENOENT;
 }
 
+int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
+size_t optlen) {
+int r;
+char **domains;
+
+assert_return(lease, -EINVAL);
+assert_return(optval, -EINVAL);
+
+if (!optlen)
+return 0;
+
+r = dhcp6_option_parse_domainname(optval, optlen, &domains);
+if (r < 0)
+return 0;
+
+free(lease->domains);
+lease->domains = domains;
+lease->domains_count = r;
+
+return r;
+}
+
+int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) {
+assert_return(lease, -EINVAL);
+assert_return(domains, -EINVAL);
+
+if (lease->domains_count) {
+*domains = lease->domains;
+return lease->domains_count;
+}
+
+return -ENOENT;
+}
+
 sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
 if (lease)
 assert_se(REFCNT_INC(lease->n_ref) >= 2);
@@ -222,6 +259,9 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) 
{
 dhcp6_lease_free_ia(&lease->ia);
 
 free(lease->dns);
+
+lease->domains = strv_free(lease->domains);
+
 free(lease);
 }
 
diff --git a/src/systemd/sd-dhcp6-lease.h b/src/systemd/sd-dhcp6-lease.h
index c98026b..8fdb48e 100644
--- a/src/systemd/sd-dhcp6-lease.h
+++ b/src/systemd/sd-dhcp6-lease.h
@@ -34,6 +34,7 @@ int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease,
uint32_t *lifetime_valid);
 
 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs);
+int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains);
 
 sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease);
 sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease);
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailma

[systemd-devel] [PATCH 11/11] network: Save DNS and NTP data for a DHCPv6 link

2015-07-10 Thread Patrik Flykt
Append DNS and NTP data obtained via DHCPv6 when the Link is saved.
---
 src/network/networkd-link.c | 62 +
 1 file changed, 62 insertions(+)

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index dff81a5..2f36abe 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2161,6 +2161,14 @@ int link_save(Link *link) {
 if (link->network) {
 char **address, **domain;
 bool space;
+sd_dhcp6_lease *dhcp6_lease = NULL;
+
+if (link->dhcp6_client) {
+r = sd_dhcp6_client_get_lease(link->dhcp6_client,
+  &dhcp6_lease);
+if (r < 0)
+log_link_debug(link, "No DHCPv6 lease");
+}
 
 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
 
@@ -2182,6 +2190,19 @@ int link_save(Link *link) {
 if (space)
 fputc(' ', f);
 serialize_in_addrs(f, addresses, r);
+space = true;
+}
+}
+
+if (link->network->dhcp_dns && dhcp6_lease) {
+struct in6_addr *in6_addrs;
+
+r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
+if (r > 0) {
+if (space)
+fputc(' ', f);
+serialize_in6_addrs(f, in6_addrs, r);
+space = true;
 }
 }
 
@@ -2205,6 +2226,32 @@ int link_save(Link *link) {
 if (space)
 fputc(' ', f);
 serialize_in_addrs(f, addresses, r);
+space = true;
+}
+}
+
+if (link->network->dhcp_ntp && dhcp6_lease) {
+struct in6_addr *in6_addrs;
+char **hosts;
+char **hostname;
+
+r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
+ &in6_addrs);
+if (r > 0) {
+if (space)
+fputc(' ', f);
+serialize_in6_addrs(f, in6_addrs, r);
+space = true;
+}
+
+r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
+if (r > 0) {
+STRV_FOREACH(hostname, hosts) {
+if (space)
+fputc(' ', f);
+fputs(*hostname, f);
+space = true;
+}
 }
 }
 
@@ -2228,6 +2275,21 @@ int link_save(Link *link) {
 if (space)
 fputc(' ', f);
 fputs(domainname, f);
+space = true;
+}
+}
+
+if (link->network->dhcp_domains && dhcp6_lease) {
+char **domains;
+
+r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
+if (r >= 0) {
+STRV_FOREACH(domain, domains) {
+if (space)
+fputc(' ', f);
+fputs(*domain, f);
+space = true;
+}
 }
 }
 
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 02/11] sd-dhcp6-client: Save a DHCPv6 lease also with Information Reply

2015-07-10 Thread Patrik Flykt
As the lease structure contains interesting information, save it also
for the Information Reply.
---
 src/libsystemd-network/sd-dhcp6-client.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 55fb71a..1f8bff1 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -807,10 +807,8 @@ static int client_receive_reply(sd_dhcp6_client *client, 
DHCP6Message *reply,
 client->lease = sd_dhcp6_lease_unref(client->lease);
 }
 
-if (client->state != DHCP6_STATE_INFORMATION_REQUEST) {
-client->lease = lease;
-lease = NULL;
-}
+client->lease = lease;
+lease = NULL;
 
 return DHCP6_STATE_BOUND;
 }
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 09/11] test-dhcp6-client: Add tests for DNS and NTP options

2015-07-10 Thread Patrik Flykt
Test option setting and getting in test_advertise_option(). Verify
that the information provided in DHCPv6 Reply messages is also
available in the Information and Solicit callbacks.
---
 src/libsystemd-network/test-dhcp6-client.c | 63 ++
 1 file changed, 63 insertions(+)

diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index b61fd38..6e62262 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -216,6 +216,8 @@ static int test_advertise_option(sd_event *e) {
 uint32_t lt_pref, lt_valid;
 int r;
 bool opt_clientid = false;
+struct in6_addr *addrs;
+char **domains;
 
 if (verbose)
 printf("* %s\n", __FUNCTION__);
@@ -276,6 +278,24 @@ static int test_advertise_option(sd_event *e) {
 
 break;
 
+case DHCP6_OPTION_DNS_SERVERS:
+assert_se(optlen == 16);
+assert_se(dhcp6_lease_set_dns(lease, optval,
+  optlen) >= 0);
+break;
+
+case DHCP6_OPTION_DOMAIN_LIST:
+assert_se(optlen == 11);
+assert_se(dhcp6_lease_set_domains(lease, optval,
+  optlen) >= 0);
+break;
+
+case DHCP6_OPTION_SNTP_SERVERS:
+assert_se(optlen == 16);
+assert_se(dhcp6_lease_set_sntp(lease, optval,
+   optlen) >= 0);
+break;
+
 default:
 break;
 }
@@ -315,6 +335,19 @@ static int test_advertise_option(sd_event *e) {
 assert_se(dhcp6_lease_get_preference(lease, &preference) >= 0);
 assert_se(preference == 0);
 
+r = sd_dhcp6_lease_get_dns(lease, &addrs);
+assert_se(r == 1);
+assert_se(!memcmp(addrs, &msg_advertise[124], r * 16));
+
+r = sd_dhcp6_lease_get_domains(lease, &domains);
+assert_se(r == 1);
+assert_se(!strcmp("lab.intra", domains[0]));
+assert_se(domains[1] == NULL);
+
+r = sd_dhcp6_lease_get_ntp_addrs(lease, &addrs);
+assert_se(r == 1);
+assert_se(!memcmp(addrs, &msg_advertise[159], r * 16));
+
 return 0;
 }
 
@@ -339,10 +372,25 @@ int detect_virtualization(const char **id) {
 static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
void *userdata) {
 sd_event *e = userdata;
+sd_dhcp6_lease *lease;
+struct in6_addr *addrs;
+char **domains;
 
 assert_se(e);
 assert_se(event == DHCP6_EVENT_IP_ACQUIRE);
 
+assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
+
+assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1);
+assert_se(!strcmp("lab.intra", domains[0]));
+assert_se(domains[1] == NULL);
+
+assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1);
+assert_se(!memcmp(addrs, &msg_advertise[124], 16));
+
+assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1);
+assert_se(!memcmp(addrs, &msg_advertise[159], 16));
+
 assert_se(sd_dhcp6_client_set_request_option(client, 
DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
 
 if (verbose)
@@ -524,10 +572,25 @@ static int test_client_verify_solicit(DHCP6Message 
*solicit, uint8_t *option,
 static void test_client_information_cb(sd_dhcp6_client *client, int event,
void *userdata) {
 sd_event *e = userdata;
+sd_dhcp6_lease *lease;
+struct in6_addr *addrs;
+char **domains;
 
 assert_se(e);
 assert_se(event == DHCP6_EVENT_INFORMATION_REQUEST);
 
+assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
+
+assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1);
+assert_se(!strcmp("lab.intra", domains[0]));
+assert_se(domains[1] == NULL);
+
+assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1);
+assert_se(!memcmp(addrs, &msg_advertise[124], 16));
+
+assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1);
+assert_se(!memcmp(addrs, &msg_advertise[159], 16));
+
 if (verbose)
 printf("  got DHCPv6 event %d\n", event);
 
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 05/11] sd-dhcp6: Add support for DHCPv6 DNS Recursive Name Server option

2015-07-10 Thread Patrik Flykt
Support DHCPv6 DNS server option as specified in RFC 3646. This option
contains a list of IPv6 DNS server addresses.
---
 src/libsystemd-network/dhcp6-lease-internal.h |  7 -
 src/libsystemd-network/sd-dhcp6-client.c  |  9 ++-
 src/libsystemd-network/sd-dhcp6-lease.c   | 37 +++
 src/systemd/sd-dhcp6-lease.h  |  4 ++-
 4 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/src/libsystemd-network/dhcp6-lease-internal.h 
b/src/libsystemd-network/dhcp6-lease-internal.h
index 109e0f4..0dad0a5 100644
--- a/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/libsystemd-network/dhcp6-lease-internal.h
@@ -6,7 +6,7 @@
   This file is part of systemd.
 
   Copyright (C) 2014 Tom Gundersen
-  Copyright (C) 2014 Intel Corporation. All rights reserved.
+  Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
 
   systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
@@ -40,6 +40,10 @@ struct sd_dhcp6_lease {
 DHCP6IA ia;
 
 DHCP6Address *addr_iter;
+
+struct in6_addr *dns;
+size_t dns_count;
+size_t dns_allocated;
 };
 
 int dhcp6_lease_clear_timers(DHCP6IA *ia);
@@ -56,6 +60,7 @@ int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool 
*rapid_commit);
 
 int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
 
+int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
 int dhcp6_lease_new(sd_dhcp6_lease **ret);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref);
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 1f8bff1..f0c7949 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -3,7 +3,7 @@
 /***
   This file is part of systemd.
 
-  Copyright (C) 2014 Intel Corporation. All rights reserved.
+  Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
 
   systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
@@ -753,6 +753,13 @@ static int client_parse_message(sd_dhcp6_client *client,
 return r;
 
 break;
+
+case DHCP6_OPTION_DNS_SERVERS:
+r = dhcp6_lease_set_dns(lease, optval, optlen);
+if (r < 0)
+return r;
+
+break;
 }
 }
 
diff --git a/src/libsystemd-network/sd-dhcp6-lease.c 
b/src/libsystemd-network/sd-dhcp6-lease.c
index 2442269..55cefde 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -173,6 +173,42 @@ void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease 
*lease) {
 lease->addr_iter = lease->ia.addresses;
 }
 
+int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) 
{
+int r;
+
+assert_return(lease, -EINVAL);
+assert_return(optval, -EINVAL);
+
+if (!optlen)
+return 0;
+
+r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns,
+lease->dns_count,
+&lease->dns_allocated);
+if (r < 0) {
+log_dhcp6_client(client, "Invalid DNS server option: %s",
+ strerror(-r));
+
+return r;
+}
+
+lease->dns_count = r;
+
+return 0;
+}
+
+int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs) {
+assert_return(lease, -EINVAL);
+assert_return(addrs, -EINVAL);
+
+if (lease->dns_count) {
+*addrs = lease->dns;
+return lease->dns_count;
+}
+
+return -ENOENT;
+}
+
 sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
 if (lease)
 assert_se(REFCNT_INC(lease->n_ref) >= 2);
@@ -185,6 +221,7 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) 
{
 free(lease->serverid);
 dhcp6_lease_free_ia(&lease->ia);
 
+free(lease->dns);
 free(lease);
 }
 
diff --git a/src/systemd/sd-dhcp6-lease.h b/src/systemd/sd-dhcp6-lease.h
index 716d767..c98026b 100644
--- a/src/systemd/sd-dhcp6-lease.h
+++ b/src/systemd/sd-dhcp6-lease.h
@@ -7,7 +7,7 @@
   This file is part of systemd.
 
   Copyright (C) 2014 Tom Gundersen
-  Copyright (C) 2014 Intel Corporation. All rights reserved.
+  Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
 
   systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
@@ -33,6 +33,8 @@ int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease,

[systemd-devel] [PATCH 10/11] network: Add function to serialize an IPv6 address

2015-07-10 Thread Patrik Flykt
---
 src/libsystemd-network/network-internal.c | 15 +++
 src/libsystemd-network/network-internal.h |  2 ++
 2 files changed, 17 insertions(+)

diff --git a/src/libsystemd-network/network-internal.c 
b/src/libsystemd-network/network-internal.c
index d579755..1db7dd2 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -32,6 +32,7 @@
 #include "conf-parser.h"
 #include "condition.h"
 #include "network-internal.h"
+#include "sd-icmp6-nd.h"
 
 const char *net_get_name(struct udev_device *device) {
 const char *name, *field;
@@ -384,6 +385,20 @@ int deserialize_in_addrs(struct in_addr **ret, const char 
*string) {
 return size;
 }
 
+void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
+ size_t size) {
+unsigned i;
+
+assert(f);
+assert(addresses);
+assert(size);
+
+for (i = 0; i < size; i++)
+fprintf(f, SD_ICMP6_ADDRESS_FORMAT_STR"%s",
+SD_ICMP6_ADDRESS_FORMAT_VAL(addresses[i]),
+(i < (size - 1)) ? " ": "");
+}
+
 int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
 _cleanup_free_ struct in6_addr *addresses = NULL;
 int size = 0;
diff --git a/src/libsystemd-network/network-internal.h 
b/src/libsystemd-network/network-internal.h
index 06aba89..4096eab 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -67,6 +67,8 @@ const char *net_get_name(struct udev_device *device);
 
 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size);
 int deserialize_in_addrs(struct in_addr **addresses, const char *string);
+void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
+ size_t size);
 int deserialize_in6_addrs(struct in6_addr **addresses, const char *string);
 
 /* don't include "dhcp-lease-internal.h" as it causes conflicts between 
netinet/ip.h and linux/ip.h */
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 00/11] DHCPv6 DNS and NTP information

2015-07-10 Thread Patrik Flykt

Hi,

This patch set adds support for DNS and NTP DHCPv6 options. The information
obtained is written to file in link_save() in systemd-networkd in order
to be used by others.

The first patch is a bug fix triggered when going from Information request
to the full DHCPv6 address lease in the test case when the lease was also
stored as a part of the information request exchange in patch two.

Two helper functions are introduced and used when extracting DNS, NTP
address, domain search list and NTP host name options. Support was added
also for the deprecated SNTP option, it can still be discovered in some
semi-ancient networks.

The test case is improved to look for the DNS and NTP information and
ystemd-networkd is enhanced with the functionality to write this information
nto the link state file. I might be missing something with systemd-networkd
n this area, though.

I do feel a bit rusty with systemd, some conventions may have changed since
last time.

Please review,

   Patrik


Patrik Flykt (11):
  sd-dhcp6-client: Fix unreferencing DHCPv6 lease on client reset
  sd-dhcp6-client: Save a DHCPv6 lease also with Information Reply
  dhcp6-option: Add helper function for fetching IPv6 addresses
  dhcp6-option: Add helper function for uncompressed domain names
  sd-dhcp6: Add support for DHCPv6 DNS Recursive Name Server option
  sd-dhcp6: Add support for DHCPv6 DNS Domain Search List option
  sd-dhcp6: Add support for DHCPv6 NTP Server Option
  sd-dhcp6: Support deprecated SNTP Configuration Option
  test-dhcp6-client: Add tests for DNS and NTP options
  network: Add function to serialize an IPv6 address
  network: Save DNS and NTP data for a DHCPv6 link

 src/libsystemd-network/dhcp6-internal.h   |   7 +-
 src/libsystemd-network/dhcp6-lease-internal.h |  20 ++-
 src/libsystemd-network/dhcp6-option.c |  77 +-
 src/libsystemd-network/dhcp6-protocol.h   |   8 +-
 src/libsystemd-network/network-internal.c |  15 ++
 src/libsystemd-network/network-internal.h |   2 +
 src/libsystemd-network/sd-dhcp6-client.c  |  43 +-
 src/libsystemd-network/sd-dhcp6-lease.c   | 196 +-
 src/libsystemd-network/test-dhcp6-client.c|  65 -
 src/network/networkd-link.c   |  62 
 src/systemd/sd-dhcp6-lease.h  |   8 +-
 11 files changed, 491 insertions(+), 12 deletions(-)

-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 03/11] dhcp6-option: Add helper function for fetching IPv6 addresses

2015-07-10 Thread Patrik Flykt
Add a helper function that extracts a block of IPv6 addresses from
the provided option data.
---
 src/libsystemd-network/dhcp6-internal.h |  5 -
 src/libsystemd-network/dhcp6-option.c   | 23 ++-
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/src/libsystemd-network/dhcp6-internal.h 
b/src/libsystemd-network/dhcp6-internal.h
index 4f54ad8..87a3588 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -5,7 +5,7 @@
 /***
   This file is part of systemd.
 
-  Copyright (C) 2014 Intel Corporation. All rights reserved.
+  Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
 
   systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
@@ -68,6 +68,9 @@ int dhcp6_option_parse(uint8_t **buf, size_t *buflen, 
uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
 int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
   DHCP6IA *ia);
+int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
+struct in6_addr **addrs, size_t count,
+size_t *allocated);
 
 int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address);
 int dhcp6_network_send_udp_socket(int s, struct in6_addr *address,
diff --git a/src/libsystemd-network/dhcp6-option.c 
b/src/libsystemd-network/dhcp6-option.c
index ea863f4..f5ed175 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -3,7 +3,7 @@
 /***
   This file is part of systemd.
 
-  Copyright (C) 2014 Intel Corporation. All rights reserved.
+  Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
 
   systemd is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
@@ -317,3 +317,24 @@ error:
 
 return r;
 }
+
+int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
+struct in6_addr **addrs, size_t count,
+size_t *allocated) {
+assert_return(optval, -EINVAL);
+assert_return(addrs, -EINVAL);
+assert_return(allocated, -EINVAL);
+
+if (!optlen || optlen % sizeof(struct in6_addr))
+return -EINVAL;
+
+if (!GREEDY_REALLOC(*addrs, *allocated,
+count * sizeof(struct in6_addr) + optlen))
+return -ENOMEM;
+
+memcpy(*addrs + count, optval, optlen);
+
+count += optlen / sizeof(struct in6_addr);
+
+return count;
+}
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 01/11] sd-dhcp6-client: Fix unreferencing DHCPv6 lease on client reset

2015-07-10 Thread Patrik Flykt
When the DHCPv6 client is started by the library user or stopped for
any reason, unref the DHCPv6 lease when resetting the DHCPv6 client
data structure. This makes the DHCPv6 client always start from a clean
state and not keep unnecessary an lease structure around when stopped.

If this is not done, a previously existing lease information can be
interpreted to be from another server when restarting DHCPv6.
---
 src/libsystemd-network/sd-dhcp6-client.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 85162dc..55fb71a 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -272,6 +272,11 @@ static void client_notify(sd_dhcp6_client *client, int 
event) {
 static int client_reset(sd_dhcp6_client *client) {
 assert_return(client, -EINVAL);
 
+if (client->lease) {
+dhcp6_lease_clear_timers(&client->lease->ia);
+client->lease = sd_dhcp6_lease_unref(client->lease);
+}
+
 client->receive_message =
 sd_event_source_unref(client->receive_message);
 
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 04/11] dhcp6-option: Add helper function for uncompressed domain names

2015-07-10 Thread Patrik Flykt
Add a helper function that extracts a string array of domain names from
the provided option data. The domain names are stored uncompressed as
defined in Section 8. of RFC 3315.
---
 src/libsystemd-network/dhcp6-internal.h |  2 ++
 src/libsystemd-network/dhcp6-option.c   | 54 +
 2 files changed, 56 insertions(+)

diff --git a/src/libsystemd-network/dhcp6-internal.h 
b/src/libsystemd-network/dhcp6-internal.h
index 87a3588..83e8192 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -71,6 +71,8 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, 
uint16_t iatype,
 int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
 struct in6_addr **addrs, size_t count,
 size_t *allocated);
+int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen,
+  char ***str_arr);
 
 int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address);
 int dhcp6_network_send_udp_socket(int s, struct in6_addr *address,
diff --git a/src/libsystemd-network/dhcp6-option.c 
b/src/libsystemd-network/dhcp6-option.c
index f5ed175..1647dd3 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -26,6 +26,7 @@
 #include "sparse-endian.h"
 #include "unaligned.h"
 #include "util.h"
+#include "strv.h"
 
 #include "dhcp6-internal.h"
 #include "dhcp6-protocol.h"
@@ -338,3 +339,56 @@ int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t 
optlen,
 
 return count;
 }
+
+int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen,
+  char ***str_arr)
+{
+size_t pos = 0, idx = 0;
+const char *buf = (const char *)optval;
+_cleanup_free_ char **strs = malloc0(sizeof(char *));
+int r;
+
+assert_return(optlen > 1, -ENODATA);
+assert_return(optval[optlen] == '\0', -EINVAL);
+
+if (!strs)
+return -ENOMEM;
+
+while (pos < optlen) {
+size_t len, i = 0;
+
+r = strv_extend(&strs, &buf[pos + 1]);
+if (r < 0)
+return -EINVAL;
+
+len = buf[pos];
+if (len > 63)
+return -EINVAL;
+
+while (strs[idx][i] != '\0') {
+
+for (i = 0; i < len; i++) {
+if (strs[idx][i] == '\0')
+return -EINVAL;
+}
+
+if (strs[idx][i] != 0) {
+len += strs[idx][i] + 1;
+if (len > 63)
+return -EINVAL;
+
+strs[idx][i] = '.';
+i++;
+}
+}
+i++;
+
+pos += i + 1;
+idx++;
+}
+
+*str_arr = strs;
+strs = NULL;
+
+return idx;
+}
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH v2] network: Implement fallback DHCPv6 prefix handling for older kernels

2015-05-03 Thread Patrik Flykt
On Fri, 2015-04-10 at 14:03 +0300, Patrik Flykt wrote:
> Version 2 attempts to resolve IPv6 address assignment issues at run
> time, first by adding IFA_FLAGS, then without.

Hearing no failure reports, this patch has been applied.

Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH v2] network: Implement fallback DHCPv6 prefix handling for older kernels

2015-04-24 Thread Patrik Flykt

Hi,

On Fri, 2015-04-10 at 14:03 +0300, Patrik Flykt wrote:

> Version 2 attempts to resolve IPv6 address assignment issues at run time,
> first by adding IFA_FLAGS, then without.
> 
> Please test with kernels < 3.14 and >= 3.14.

This may be a case of too few people actually using DHCPv6 these days.
The patch works at least for me, so if I hear no comments I'll just push
this today. And I'm prepared to stay around to fix it should it not
work...

Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH] network: Implement fallback DHCPv6 prefix handling for older kernels

2015-04-09 Thread Patrik Flykt
On Thu, 2015-04-09 at 12:43 +0200, Lennart Poettering wrote:
> Hmm, in general, we really should try to create the same binaries,
> regardless if we are built on an old or new kernel. And the binaries
> should work as good as possible, regardless which kernel version they
> are running on. But with the change above the binary built on a newer
> kernel work differently from an older kernel, even though we added the
> definition to missing.h to make the distinction go away...
> 
> Or in other words: we try to do runtime compat, not just compile time
> compat, so that we don't strictly have to sync kernel and userspace
> updated.

Hmm, I was suspecting that for a moment. I need to come up with a better
runtime solution for version 2 of the patch then.

Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH] network: Implement fallback DHCPv6 prefix handling for older kernels

2015-04-09 Thread Patrik Flykt
When setting IPv6 addresses acquired by DHCPv6, systemd-networkd sets
the IFA_F_NOPREFIXROUTE flag in the IFA_FLAGS netlink attribute. As the
flag and the attribute are present starting with Linux 3.14, older
kernels will need systemd-network to manage prefix route handling.

Support for IFA_FLAGS is done during compile time and implemented as
part of netlink type checking. When IFA_FLAGS is detected in an systemd
external kernel header, HAVE_DECL_IFA_FLAGS is defined and the type
check will be successful. If not, setting the attribute will fail and
systemd-network will record this fact to its Link structure. Later if
a prefix expires, the same Link structure will be queried for the
successful use of IFA_FLAGS, with the DHCPv6 addresses handled either
by the kernel or the systemd-networkd fallback code.

The prefix expiration and IPv6 address updating fallback code is
resurrected from the parts deleted with commit
47d45d3cde45d6545367570264e4e3636bc9e345.

This patch can be removed once the minimum kernel requirements are
greater than or equal to 3.14.
---

Hi,

This patch implements a compile time fix for IFA_FLAGS support. Doing the
fix run time has its difficulties as the kernel discarding DHCPv6 address
assignment in the error path of dhcp6_address_handler() can have been
caused by other error situations.

I got this one working on my machine by commenting IFA_FLAGS out/leaving
IFA_FLAGS defined in the kernel headers, please test against real running
3.8/3.14 Linux versions.


Cheers,

Patrik



 src/libsystemd/sd-rtnl/rtnl-types.c |  2 ++
 src/network/networkd-address.c  |  5 +++-
 src/network/networkd-dhcp6.c| 55 +++--
 src/network/networkd-link.c |  4 +++
 src/network/networkd-link.h |  2 ++
 5 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c 
b/src/libsystemd/sd-rtnl/rtnl-types.c
index 49784bf..407b749 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.c
+++ b/src/libsystemd/sd-rtnl/rtnl-types.c
@@ -360,7 +360,9 @@ static const NLType rtnl_address_types[CONST_MAX(IFA_MAX, 
IFA_FLAGS) + 1] = {
 [IFA_ANYCAST],
 [IFA_MULTICAST],
 */
+#if HAVE_DECL_IFA_FLAGS
 [IFA_FLAGS] = { .type = NLA_U32 },
+#endif
 };
 
 static const NLTypeSystem rtnl_address_type_system = {
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 85acc49..2057d05 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -218,7 +218,10 @@ int address_update(Address *address, Link *link,
 if (address->flags & ~0xff) {
 r = sd_rtnl_message_append_u32(req, IFA_FLAGS, address->flags);
 if (r < 0)
-return log_error_errno(r, "Could not set extended 
flags: %m");
+log_link_warning(link, "Could not set extended flags: 
%s",
+ strerror(-r));
+else
+link->rtnl_extended_flags = true;
 }
 
 r = sd_rtnl_message_addr_set_scope(req, address->scope);
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index e863f4b..6b040bd 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -67,7 +67,7 @@ static int dhcp6_address_update(Link *link, struct in6_addr 
*ip6_addr,
 memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr));
 
 addr->flags = IFA_F_NOPREFIXROUTE;
-addr->prefixlen = 64;
+addr->prefixlen = prefixlen;
 
 addr->cinfo.ifa_prefered = lifetime_preferred;
 addr->cinfo.ifa_valid = lifetime_valid;
@@ -262,6 +262,52 @@ static int dhcp6_configure(Link *link, int event) {
 return r;
 }
 
+static int dhcp6_prefix_expired(Link *link) {
+int r;
+sd_dhcp6_lease *lease;
+struct in6_addr *expired_prefix, ip6_addr;
+uint8_t expired_prefixlen;
+uint32_t lifetime_preferred, lifetime_valid;
+
+r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery,
+&expired_prefix, &expired_prefixlen);
+if (r < 0)
+return r;
+
+r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease);
+if (r < 0)
+return r;
+
+log_link_struct(link, LOG_INFO,
+"MESSAGE=%-*s: IPv6 prefix 
"SD_ICMP6_ADDRESS_FORMAT_STR"/%d expired",
+IFNAMSIZ, link->ifname,
+SD_ICMP6_ADDRESS_FORMAT_VAL(*expired_prefix),
+expired_prefixlen, NULL);
+
+sd_dhcp6_lease_reset_address_iter(lease);
+
+while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
+&lifetime_preferred,
+&lifetime_valid) >= 0) {
+
+r = sd_icmp6_prefix_match(expired_prefix, expired_pref

Re: [systemd-devel] [PATCH 1/3] sd-rtnl: Always enable IFA_FLAGS

2015-04-08 Thread Patrik Flykt
On Tue, 2015-04-07 at 21:13 +0200, Alexander Sverdlin wrote:
> But if the backend code for this flag appears first in Linux 3.14
> (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=479840ffdbe4),
> working around the compilation issue (against older uapi headers) will
> not help with the fact that networkd will fail in 851c9f82736
> (systemd-networkd: Use IFA_F_NOPREFIXROUTE with IPv6 addresses)?

I'll fix that logic now that compilation works.

Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 1/3] sd-rtnl: Always enable IFA_FLAGS

2015-04-07 Thread Patrik Flykt
On Fri, 2015-04-03 at 06:46 +0200, Alexander Sverdlin wrote:
> Hi!
> 
> On 25/03/15 14:36, Patrik Flykt wrote:
> > IFA_FLAGS is a discrete value and has no preprocessor #define defined for
> > it. Fix this by always using the value.
> 
> Seems that fix was not a real fix:
> 
>   CC   src/libsystemd/sd-id128/libsystemd_internal_la-sd-id128.lo
> src/libsystemd/sd-rtnl/rtnl-types.c:361:10: error: ‘IFA_FLAGS’ undeclared 
> here (not in a function)
>  [IFA_FLAGS] = { .type = NLA_U32 },
>   ^
> src/libsystemd/sd-rtnl/rtnl-types.c:361:9: error: array index in initializer 
> not of integer type
>  [IFA_FLAGS] = { .type = NLA_U32 },
>  ^
> src/libsystemd/sd-rtnl/rtnl-types.c:361:9: error: (near initialization for 
> ‘rtnl_address_types’)
> Makefile:15503: recipe for target 
> 'src/libsystemd/sd-rtnl/libsystemd_internal_la-rtnl-types.lo' failed
> make[3]: *** [src/libsystemd/sd-rtnl/libsystemd_internal_la-rtnl-types.lo] 
> Error 1

IFA_FLAGS seems to appear in kernel ~3.13 and the kernel requirements
from README state 3.8/3.7 at the moment.

One could let the sd_rtnl_message_append_u32 for IFA_FLAGS fail in patch
2/3, but then user space has to play tricks with IPv6 DHCPv6 routes as
before this patch and needs to re-add the code just removed because of
this nice feature. Oh well...

Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 3/3] networkd-dhcp6: Do not handle prefix expiry

2015-03-27 Thread Patrik Flykt
On Fri, 2015-03-27 at 12:05 +0100, Tom Gundersen wrote:
> On Wed, Mar 25, 2015 at 2:37 PM, Patrik Flykt
>  wrote:
> > Expiring prefixes need not be handled anymore as the kernel has been
> > instructed not to create routes for DHCPv6 assigned addresses via the
> > IFA_F_NOPREFIXROUTE flag.
> 
> Great stuff. Please push all three!

And pushed!

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 3/3] networkd-dhcp6: Do not handle prefix expiry

2015-03-25 Thread Patrik Flykt
Expiring prefixes need not be handled anymore as the kernel has been
instructed not to create routes for DHCPv6 assigned addresses via the
IFA_F_NOPREFIXROUTE flag.
---
 src/network/networkd-dhcp6.c | 42 +-
 1 file changed, 1 insertion(+), 41 deletions(-)

diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index 283a7d6..e863f4b 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -86,42 +86,6 @@ static int dhcp6_address_update(Link *link, struct in6_addr 
*ip6_addr,
 return r;
 }
 
-static int dhcp6_prefix_expired(Link *link) {
-int r;
-sd_dhcp6_lease *lease;
-struct in6_addr *expired_prefix, ip6_addr;
-uint8_t expired_prefixlen;
-uint32_t lifetime_preferred, lifetime_valid;
-
-r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery,
-&expired_prefix, &expired_prefixlen);
-if (r < 0)
-return r;
-
-r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease);
-if (r < 0)
-return r;
-
-sd_dhcp6_lease_reset_address_iter(lease);
-
-while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
-&lifetime_preferred,
-&lifetime_valid) >= 0) {
-
-r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen,
-&ip6_addr);
-if (r >= 0) {
-r = dhcp6_address_update(link, &ip6_addr, 128,
-lifetime_preferred,
-lifetime_valid);
-
-return r;
-}
-}
-
-return 0;
-}
-
 static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
 int r;
 sd_dhcp6_lease *lease;
@@ -310,6 +274,7 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int 
event, void *userdata) {
 
 switch(event) {
 case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
+case ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED:
 return;
 
 case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
@@ -319,11 +284,6 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int 
event, void *userdata) {
 
 break;
 
-case ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED:
-dhcp6_prefix_expired(link);
-
-break;
-
 default:
 if (event < 0)
 log_link_warning(link, "ICMPv6 error: %s",
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 2/3] systemd-networkd: Use IFA_F_NOPREFIXROUTE with IPv6 addresses

2015-03-25 Thread Patrik Flykt
The IFA_F_NOPREFIXROUTE flag prevents the kernel from creating new onlink
prefixes when a DHCPv6 IPv6 address with a prefix length is set from user
space. IPv6 routing will follow the onlink status from Router Advertisment
Prefix Information options or any manually set route, which is the correct
thing to do.

As this flag has a larger value than what fits into an unsigned char, update
the flag attribute to an uint32_t and set it with an IFA_FLAGS attribute
when writing netlink messages to the kernel.
---
 src/network/networkd-address.c | 20 ++--
 src/network/networkd-dhcp6.c   |  4 +++-
 src/network/networkd-link.c|  4 +++-
 src/network/networkd.h |  2 +-
 4 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 255ff77..85acc49 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -209,10 +209,18 @@ int address_update(Address *address, Link *link,
 if (r < 0)
 return log_error_errno(r, "Could not set prefixlen: %m");
 
-r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
+address->flags |= IFA_F_PERMANENT;
+
+r = sd_rtnl_message_addr_set_flags(req, address->flags & 0xff);
 if (r < 0)
 return log_error_errno(r, "Could not set flags: %m");
 
+if (address->flags & ~0xff) {
+r = sd_rtnl_message_append_u32(req, IFA_FLAGS, address->flags);
+if (r < 0)
+return log_error_errno(r, "Could not set extended 
flags: %m");
+}
+
 r = sd_rtnl_message_addr_set_scope(req, address->scope);
 if (r < 0)
 return log_error_errno(r, "Could not set scope: %m");
@@ -335,10 +343,18 @@ int address_configure(Address *address, Link *link,
 if (r < 0)
 return log_error_errno(r, "Could not set prefixlen: %m");
 
-r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
+address->flags |= IFA_F_PERMANENT;
+
+r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff));
 if (r < 0)
 return log_error_errno(r, "Could not set flags: %m");
 
+if (address->flags & ~0xff) {
+r = sd_rtnl_message_append_u32(req, IFA_FLAGS, address->flags);
+if (r < 0)
+return log_error_errno(r, "Could not set extended 
flags: %m");
+}
+
 r = sd_rtnl_message_addr_set_scope(req, address->scope);
 if (r < 0)
 return log_error_errno(r, "Could not set scope: %m");
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index bcfad4c..283a7d6 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -65,7 +65,9 @@ static int dhcp6_address_update(Link *link, struct in6_addr 
*ip6_addr,
 
 addr->family = AF_INET6;
 memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr));
-addr->prefixlen = prefixlen;
+
+addr->flags = IFA_F_NOPREFIXROUTE;
+addr->prefixlen = 64;
 
 addr->cinfo.ifa_prefered = lifetime_preferred;
 addr->cinfo.ifa_valid = lifetime_valid;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 842ca1c..437c598 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1831,6 +1831,7 @@ int link_rtnl_process_address(sd_rtnl *rtnl, 
sd_rtnl_message *message, void *use
 Link *link = NULL;
 uint16_t type;
 _cleanup_address_free_ Address *address = NULL;
+unsigned char flags;
 Address *existing;
 char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
 const char *valid_str = NULL;
@@ -1894,11 +1895,12 @@ int link_rtnl_process_address(sd_rtnl *rtnl, 
sd_rtnl_message *message, void *use
 return 0;
 }
 
-r = sd_rtnl_message_addr_get_flags(message, &address->flags);
+r = sd_rtnl_message_addr_get_flags(message, &flags);
 if (r < 0) {
 log_link_warning(link, "rtnl: received address with invalid 
flags, ignoring");
 return 0;
 }
+address->flags = flags;
 
 switch (address->family) {
 case AF_INET:
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 8bdc2be..c26d64e 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -173,7 +173,7 @@ struct Address {
 int family;
 unsigned char prefixlen;
 unsigned char scope;
-unsigned char flags;
+uint32_t flags;
 char *label;
 
 struct in_addr broadcast;
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 1/3] sd-rtnl: Always enable IFA_FLAGS

2015-03-25 Thread Patrik Flykt
IFA_FLAGS is a discrete value and has no preprocessor #define defined for
it. Fix this by always using the value.
---
 src/libsystemd/sd-rtnl/rtnl-types.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c 
b/src/libsystemd/sd-rtnl/rtnl-types.c
index bf7278f..5ae4790 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.c
+++ b/src/libsystemd/sd-rtnl/rtnl-types.c
@@ -358,9 +358,7 @@ static const NLType rtnl_address_types[IFA_MAX + 1] = {
 [IFA_ANYCAST],
 [IFA_MULTICAST],
 */
-#ifdef IFA_FLAGS
 [IFA_FLAGS] = { .type = NLA_U32 },
-#endif
 };
 
 static const NLTypeSystem rtnl_address_type_system = {
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 0/3] Let kernel handle prefix expiry

2015-03-25 Thread Patrik Flykt

Hi,

This patch set clears up the code related to prefix handling when setting
IPv6 addresses from DHCPv6. Instead of explicitely tracking prefixes,
instruct the kernel not to create routes based on the IPv6 address and its
prefix length.

The flag value to use is IFA_F_NOPREFIXROUTE, and as it is longer than
the traditional eight bit rtnl flag value, these bigger flag values need
to be set with the auxilliary IFA_FLAGS attribute. For completeness, keep
on setting the lowermost eight bits in the rtnl flag as before.

With this change more code dealing with Router Advertisment prefixes and
their disappearance can be removed. I did not do that yet, though, as the
code may still be useful in the future - let's see.


Please review & test,

   Patrik


Patrik Flykt (3):
  sd-rtnl: Always enable IFA_FLAGS
  systemd-networkd: Use IFA_F_NOPREFIXROUTE with IPv6 addresses
  networkd-dhcp6: Do not handle prefix expiry

 src/libsystemd/sd-rtnl/rtnl-types.c |  2 --
 src/network/networkd-address.c  | 20 ++--
 src/network/networkd-dhcp6.c| 46 -
 src/network/networkd-link.c |  4 +++-
 src/network/networkd.h  |  2 +-
 5 files changed, 26 insertions(+), 48 deletions(-)

-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] slow systemd-networkd DHCP client on wlan0 with systemd v217

2015-02-04 Thread Patrik Flykt

Hi,

On Tue, 2015-02-03 at 17:27 +0100, Lennart Poettering wrote:
> > Is the resume event detected somehow in systemd? 
> 
> The kernel unfortunately provides no API for this right now. However,
> if logind is the one suspending the machine, then it sends out a
> PrepareForSleep() signal before doing so. systemd-resolved already
> hooks into that:
> 
> http://cgit.freedesktop.org/systemd/systemd/tree/src/resolve/resolved-bus.c#n684
> 
> Tom mentioned he's already looking into adding similar code to
> networkd to handle this properly.

Latest upstream works fine for me. Links break at suspend and are
enabled at restore with PrepareForSleep() handled. Both versions of DHCP
properly stop and start at these events.


Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] slow systemd-networkd DHCP client on wlan0 with systemd v217

2015-02-03 Thread Patrik Flykt
On Tue, 2015-02-03 at 11:46 +0100, Lennart Poettering wrote:
> On Mon, 02.02.15 23:12, Charles Devereaux (syst...@guylhem.net) wrote:
> 
> > Another problem with systemd-networkd is that the lease is not renewed
> > after sleep.
> > 
> > This is a basic feature, a laptop is frequently physicially moved, which
> > means another DHCP lease should be acquired, but I don't see how to
> > do that.
> 
> Hmm, I figure all DHCP leases should be refreshed when we come back
> from suspend. Hooking that up should be pretty easy. Added to the TODO
> list.
> 
> That said, isn't the link beat lost anyway during suspend, and thus we
> should refresh automatically, anyway? 
> 
> Either way refreshing on resume can't hurt...

Is the resume event detected somehow in systemd? I'd assume that links
are lost when suspending and reconnected on resume, so maybe that is the
only event needing attention. I'll take a quick look into what my laptop
thinks about the issue...


Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] test-dhcp-client failing in mock builds

2015-02-02 Thread Patrik Flykt

Hi,

On Sat, 2015-01-31 at 15:48 +0100, Zbigniew Jędrzejewski-Szmek wrote:
> DHCP CLIENT (0xa71f5099): STARTED on ifindex 42
> DHCP CLIENT (0xa71f5099): DISCOVER
> DHCP CLIENT (0xa71f5099): OFFER
> DHCP CLIENT (0xa71f5099): REQUEST (requesting)
> DHCP CLIENT (0xa71f5099): ACK
> DHCP CLIENT (0xa71f5099): lease expires in 9min 58.349975s
> DHCP CLIENT (0xa71f5099): T2 expires in 8min 43.759020s
> DHCP CLIENT (0xa71f5099): T1 expires in 4min 59.245773s

Up until here everything is fine, and the proper messages are sent back
and forth between the client code and the test program which pretends to
be the "server" in this scenario.

> DHCP CLIENT (0xa71f5099): STOPPED: Operation not permitted

This printout comes from client_stop(sd_dhcp_client *client, int error)
when given a negative error value.

"Operation not permitted" is what is printed for EPERM. But EPERM is not
present in the client code itself, so I'm inclined towards a "permission
problem" somewhere when running mock.

In function client_handle_message(), the function call to
client_set_lease_timeouts() is the one printing the T2 and T1 expiration
values. After this function, the first possible call to client_stop()
containing a negative value which that does not log additional strings
beforehand happens in client_initialize_io_events(). This if the io
handler cannot be (re?)set for some reason. It seems there already
exists an io handler at this point, but why it should fail only for mock
is something I don't understand. The test program just worksforme too.

It can't really be the following client_notify(client, notify_event)
call either, as notify_event >= 0 or r, where r must have been >= 0 to
begin with. If it was client_handle_ack() that returned < 0 a little bit
earlier, no T2 and T1 timers would have been set.

With the above I was assuming that the latest version was used and not
an older release.


Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH v2 0/9] DHCPv6 address assignment

2015-01-26 Thread Patrik Flykt
On Tue, 2015-01-20 at 19:35 +0200, Patrik Flykt wrote:
> Hi,
> 
> Here is version 2 updated according to comments.
> 
> The trivial debug printout removal being too trivial is no longer
> part of this set. NTP and DNS information I also left off, I think
> there might have been a few bugs so there should be some initial test
> cases done first. And the values so received should be used in
> networkd.
> 
> I'll update the test case verbosity in another patch later. The
> proposed log_link_warning_errno() I also delegated "for later",
> let's try to have the DHCPv6 address assignment done first.

All patches are applied.

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH v2 8/9] sd-icmp6-nd: Add support for fetching the latest expired prefix

2015-01-20 Thread Patrik Flykt
Keep the expired prefix for the duration of the prefix expiration event
and remove it afterwards.
---
 src/libsystemd-network/sd-icmp6-nd.c | 20 
 src/systemd/sd-icmp6-nd.h|  2 ++
 2 files changed, 22 insertions(+)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index 4ebeeef..f09ad60 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -65,6 +65,7 @@ struct sd_icmp6_nd {
 int index;
 struct ether_addr mac_addr;
 uint32_t mtu;
+ICMP6Prefix *expired_prefix;
 LIST_HEAD(ICMP6Prefix, prefixes);
 int fd;
 sd_event_source *recv;
@@ -266,8 +267,11 @@ static int icmp6_ra_prefix_timeout(sd_event_source *s, 
uint64_t usec,
 
 LIST_REMOVE(prefixes, nd->prefixes, prefix);
 
+nd->expired_prefix = prefix;
 icmp6_nd_notify(nd,
 
ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED);
+nd->expired_prefix = NULL;
+
 prefix = icmp6_prefix_unref(prefix);
 
 break;
@@ -372,6 +376,22 @@ int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const 
struct in6_addr *addr,
 return 0;
 }
 
+int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr,
+uint8_t *prefixlen)
+{
+assert_return(nd, -EINVAL);
+assert_return(addr, -EINVAL);
+assert_return(prefixlen, -EINVAL);
+
+if (!nd->expired_prefix)
+return -EADDRNOTAVAIL;
+
+*addr = &nd->expired_prefix->addr;
+*prefixlen = nd->expired_prefix->len;
+
+return 0;
+}
+
 static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
   const struct nd_opt_prefix_info *prefix_opt) 
{
 int r;
diff --git a/src/systemd/sd-icmp6-nd.h b/src/systemd/sd-icmp6-nd.h
index 86cf25a..79b4074 100644
--- a/src/systemd/sd-icmp6-nd.h
+++ b/src/systemd/sd-icmp6-nd.h
@@ -58,6 +58,8 @@ int sd_icmp6_prefix_match(struct in6_addr *prefix, uint8_t 
prefixlen,
 int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu);
 int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const struct in6_addr *addr,
 uint8_t *prefixlen);
+int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr,
+uint8_t *prefixlen);
 
 int sd_icmp6_nd_stop(sd_icmp6_nd *nd);
 int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd);
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH v2 5/9] test-icmp6-rs: Add trivial test case for an MTU that is not present

2015-01-20 Thread Patrik Flykt
---
 src/libsystemd-network/test-icmp6-rs.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/libsystemd-network/test-icmp6-rs.c 
b/src/libsystemd-network/test-icmp6-rs.c
index be64d33..9d50c57 100644
--- a/src/libsystemd-network/test-icmp6-rs.c
+++ b/src/libsystemd-network/test-icmp6-rs.c
@@ -93,6 +93,8 @@ static void test_rs_done(sd_icmp6_nd *nd, int event, void 
*userdata) {
 { ND_RA_FLAG_OTHER, ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER },
 { ND_RA_FLAG_MANAGED, ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED }
 };
+uint32_t mtu;
+
 assert_se(nd);
 
 assert_se(event == flag_event[idx].event);
@@ -101,10 +103,14 @@ static void test_rs_done(sd_icmp6_nd *nd, int event, void 
*userdata) {
 if (verbose)
 printf("  got event %d\n", event);
 
-if (idx < 3)
+if (idx < 3) {
 send_ra(flag_event[idx].flag);
-else
-sd_event_exit(e, 0);
+return;
+}
+
+assert_se(sd_icmp6_ra_get_mtu(nd, &mtu) == -ENOMSG);
+
+sd_event_exit(e, 0);
 }
 
 static void test_rs(sd_event *e) {
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH v2 0/9] DHCPv6 address assignment

2015-01-20 Thread Patrik Flykt

Hi,

Here is version 2 updated according to comments.

The trivial debug printout removal being too trivial is no longer
part of this set. NTP and DNS information I also left off, I think
there might have been a few bugs so there should be some initial test
cases done first. And the values so received should be used in
networkd.

I'll update the test case verbosity in another patch later. The
proposed log_link_warning_errno() I also delegated "for later",
let's try to have the DHCPv6 address assignment done first.

Please review,


    Patrik


Patrik Flykt (9):
  sd-dhcp6-lease: Revise address iteration functions
  sd-icmp6-nd: Update Router Advertisement handling
  sd-icmp6-nd: Add link and prefix structures for ICMPv6
  sd-icmp6-nd: Add helper function to get the IPv6 link MTU
  test-icmp6-rs: Add trivial test case for an MTU that is not present
  sd-icmp6-nd: Parse ICMPv6 prefix information
  test-icmp6-nd: Add test cases for prefixes
  sd-icmp6-nd: Add support for fetching the latest expired prefix
  networkd-dhcp6: Assign DHCPv6 addresses and prefix lengths

 src/libsystemd-network/sd-dhcp6-lease.c|  26 +-
 src/libsystemd-network/sd-icmp6-nd.c   | 387 -
 src/libsystemd-network/test-dhcp6-client.c |  45 ++--
 src/libsystemd-network/test-icmp6-rs.c | 219 +++-
 src/network/networkd-dhcp6.c   | 165 +++-
 src/systemd/sd-dhcp6-lease.h   |  13 +-
 src/systemd/sd-icmp6-nd.h  |  30 ++-
 7 files changed, 803 insertions(+), 82 deletions(-)

-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH v2 1/9] sd-dhcp6-lease: Revise address iteration functions

2015-01-20 Thread Patrik Flykt
Revise the address iteration functions so that one helper function
resets the iterator to the start of the address list while the
second one fetches addresses one by one.

The test case is also updated.
---
 src/libsystemd-network/sd-dhcp6-lease.c| 26 -
 src/libsystemd-network/test-dhcp6-client.c | 45 +++---
 src/systemd/sd-dhcp6-lease.h   | 13 -
 3 files changed, 34 insertions(+), 50 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp6-lease.c 
b/src/libsystemd-network/sd-dhcp6-lease.c
index 8960fac..542690e 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -146,10 +146,9 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t 
*iaid) {
 return 0;
 }
 
-int sd_dhcp6_lease_get_next_address(sd_dhcp6_lease *lease,
-struct in6_addr *addr,
-uint32_t *lifetime_preferred,
-uint32_t *lifetime_valid) {
+int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr,
+   uint32_t *lifetime_preferred,
+   uint32_t *lifetime_valid) {
 assert_return(lease, -EINVAL);
 assert_return(addr, -EINVAL);
 assert_return(lifetime_preferred, -EINVAL);
@@ -169,22 +168,9 @@ int sd_dhcp6_lease_get_next_address(sd_dhcp6_lease *lease,
 return 0;
 }
 
-int sd_dhcp6_lease_get_first_address(sd_dhcp6_lease *lease,
- struct in6_addr *addr,
- uint32_t *lifetime_preferred,
- uint32_t *lifetime_valid) {
-assert_return(lease, -EINVAL);
-assert_return(addr, -EINVAL);
-assert_return(lifetime_preferred, -EINVAL);
-assert_return(lifetime_valid, -EINVAL);
-
-if (!lease->ia.addresses)
-return -ENOMSG;
-
-lease->addr_iter = lease->ia.addresses;
-
-return sd_dhcp6_lease_get_next_address(lease, addr, lifetime_preferred,
-   lifetime_valid);
+void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) {
+if (lease)
+lease->addr_iter = lease->ia.addresses;
 }
 
 sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index 7590839..9386f31 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -286,26 +286,27 @@ static int test_advertise_option(sd_event *e) {
 
 assert_se(opt_clientid);
 
-assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, <_pref,
-   <_valid) >= 0);
+sd_dhcp6_lease_reset_address_iter(lease);
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
+ <_valid) >= 0);
 assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
 assert_se(lt_pref == 150);
 assert_se(lt_valid == 180);
-assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, <_pref,
-  <_valid) == -ENOMSG);
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
+ <_valid) == -ENOMSG);
 
-assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, <_pref,
-   <_valid) >= 0);
+sd_dhcp6_lease_reset_address_iter(lease);
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
+ <_valid) >= 0);
 assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
-assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, <_pref,
-  <_valid) == -ENOMSG);
-assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, <_pref,
-  <_valid) == -ENOMSG);
-assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, <_pref,
-   <_valid) >= 0);
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
+ <_valid) == -ENOMSG);
+sd_dhcp6_lease_reset_address_iter(lease);
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
+ <_valid) >= 0);
 assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
-assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, <_pref,
-  <_valid) == -ENOMSG);
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
+ <_valid) == -ENOMSG);
 
 assert_s

[systemd-devel] [PATCH v2 3/9] sd-icmp6-nd: Add link and prefix structures for ICMPv6

2015-01-20 Thread Patrik Flykt
Each ICMPv6 structure has an interface index and will therefore be
associated with an IPv6 link containing a list of of prefixes.
---
v2: Keep the check that 'len' is not equal to zero as the option header
points to the next option that might not exist
One struct CamelCapsed, the other merged into sd_icmp6_nd
Other changes according to comments

 src/libsystemd-network/sd-icmp6-nd.c | 52 
 1 file changed, 52 insertions(+)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index cac431b..85b8ff9 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -44,6 +44,18 @@ enum icmp6_nd_state {
 #define ICMP6_ND_RECV_SIZE (IP6_MIN_MTU - sizeof(struct ip6_hdr))
 #define ICMP6_OPT_LEN_UNITS 8
 
+typedef struct ICMP6Prefix ICMP6Prefix;
+
+struct ICMP6Prefix {
+RefCount n_ref;
+
+LIST_FIELDS(ICMP6Prefix, prefixes);
+
+uint8_t len;
+sd_event_source *timeout_valid;
+struct in6_addr addr;
+};
+
 struct sd_icmp6_nd {
 RefCount n_ref;
 
@@ -52,6 +64,8 @@ struct sd_icmp6_nd {
 int event_priority;
 int index;
 struct ether_addr mac_addr;
+uint32_t mtu;
+LIST_HEAD(ICMP6Prefix, prefixes);
 int fd;
 sd_event_source *recv;
 sd_event_source *timeout;
@@ -62,6 +76,35 @@ struct sd_icmp6_nd {
 
 #define log_icmp6_nd(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, 
__LINE__, __func__, "ICMPv6 CLIENT: " fmt, ##__VA_ARGS__)
 
+static ICMP6Prefix *icmp6_prefix_unref(ICMP6Prefix *prefix) {
+if (prefix && REFCNT_DEC(prefix->n_ref) <= 0) {
+prefix->timeout_valid =
+sd_event_source_unref(prefix->timeout_valid);
+
+free(prefix);
+}
+
+return NULL;
+}
+
+static int icmp6_prefix_new(ICMP6Prefix **ret) {
+_cleanup_free_ ICMP6Prefix *prefix = NULL;
+
+assert(ret);
+
+prefix = new0(ICMP6Prefix, 1);
+if (!prefix)
+return -ENOMEM;
+
+prefix->n_ref = REFCNT_INIT;
+LIST_INIT(prefixes, prefix);
+
+*ret = prefix;
+prefix = NULL;
+
+return 0;
+}
+
 static void icmp6_nd_notify(sd_icmp6_nd *nd, int event)
 {
 if (nd->callback)
@@ -152,10 +195,17 @@ static int icmp6_nd_init(sd_icmp6_nd *nd) {
 
 sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd) {
 if (nd && REFCNT_DEC(nd->n_ref) == 0) {
+ICMP6Prefix *prefix, *p;
 
 icmp6_nd_init(nd);
 sd_icmp6_nd_detach_event(nd);
 
+LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) {
+LIST_REMOVE(prefixes, nd->prefixes, prefix);
+
+prefix = icmp6_prefix_unref(prefix);
+}
+
 free(nd);
 }
 
@@ -179,6 +229,8 @@ int sd_icmp6_nd_new(sd_icmp6_nd **ret) {
 nd->index = -1;
 nd->fd = -1;
 
+LIST_HEAD_INIT(nd->prefixes);
+
 *ret = nd;
 nd = NULL;
 
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH v2 7/9] test-icmp6-nd: Add test cases for prefixes

2015-01-20 Thread Patrik Flykt
Add test cases that feeds an Router Advertisement to the ICMPv6 code
and verify that the correct prefix lengths are returned given an IPv6
address.

Enhance the prefix verification test by adding a shorter prefix and
check that the intended prefix lengths are now updated.
---
 src/libsystemd-network/test-icmp6-rs.c | 207 +++--
 1 file changed, 200 insertions(+), 7 deletions(-)

diff --git a/src/libsystemd-network/test-icmp6-rs.c 
b/src/libsystemd-network/test-icmp6-rs.c
index 9d50c57..8ba2110 100644
--- a/src/libsystemd-network/test-icmp6-rs.c
+++ b/src/libsystemd-network/test-icmp6-rs.c
@@ -34,6 +34,9 @@ static bool verbose = false;
 static sd_event_source *test_hangcheck;
 static int test_fd[2];
 
+typedef int (*send_ra_t)(uint8_t flags);
+static send_ra_t send_ra_function;
+
 static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
  void *userdata) {
 assert_se(false);
@@ -50,6 +53,191 @@ int dhcp_network_icmp6_bind_router_solicitation(int index) {
 return test_fd[0];
 }
 
+static int send_ra_short_prefix(uint8_t flags) {
+uint8_t advertisement[] = {
+0x86, 0x00, 0xbe, 0xd7, 0x40, 0xc0, 0x00, 0xb4,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+0x03, 0x04, 0x34, 0xc0, 0x00, 0x00, 0x01, 0xf4,
+0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
+   sizeof(advertisement));
+
+return 0;
+}
+
+static void test_short_prefix_cb(sd_icmp6_nd *nd, int event, void *userdata) {
+sd_event *e = userdata;
+struct {
+struct in6_addr addr;
+uint8_t prefixlen;
+bool success;
+} addrs[] = {
+{ { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+  52, true },
+{ { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+  64, false },
+{ { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+  60, true },
+{ { { { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+  64, true },
+{ { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xed,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
+  52, true },
+};
+uint8_t prefixlen;
+unsigned int i;
+
+for (i = 0; i < ELEMENTSOF(addrs); i++) {
+printf("  %s prefix %02x%02x:%02x%02x:%02x%02x:%02x%02x",
+__FUNCTION__,
+addrs[i].addr.s6_addr[0], addrs[i].addr.s6_addr[1],
+addrs[i].addr.s6_addr[2], addrs[i].addr.s6_addr[3],
+addrs[i].addr.s6_addr[4], addrs[i].addr.s6_addr[5],
+addrs[i].addr.s6_addr[6], addrs[i].addr.s6_addr[7]);
+
+if (addrs[i].success) {
+assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
+&prefixlen) >= 
0);
+assert_se(addrs[i].prefixlen == prefixlen);
+printf("/%d onlink\n", prefixlen);
+} else {
+assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
+&prefixlen) == 
-EADDRNOTAVAIL);
+printf("/128 offlink\n");
+}
+}
+
+sd_event_exit(e, 0);
+}
+
+static int send_ra_prefixes(uint8_t flags) {
+uint8_t advertisement[] = {
+0x86, 0x00, 0xbe, 0xd7, 0x40, 0xc0, 0x00, 0xb4,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x04, 0x3f, 0xc0, 0x00, 0x00, 0x01, 0xf4,
+0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x04, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58,
+0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x04, 0x3c, 0x80, 0x00, 0x00, 0x03, 0x84,
+0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16

[systemd-devel] [PATCH v2 2/9] sd-icmp6-nd: Update Router Advertisement handling

2015-01-20 Thread Patrik Flykt
As the IPv6 prefixes are needed, update the ICMPv6 Router Advertisement
code to dynamically allocate a suitably sized buffer. Iterate through
the ICMPv6 options one by one returning error if the option length is
too big to fit the buffer.
---
v2: Address iteration fixed accordign to comments in v1, patch 10/11

 src/libsystemd-network/sd-icmp6-nd.c | 86 +++-
 1 file changed, 74 insertions(+), 12 deletions(-)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index fbaf093..2b4c816 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -18,9 +18,11 @@
 ***/
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "socket-util.h"
 #include "refcnt.h"
@@ -38,6 +40,10 @@ enum icmp6_nd_state {
 ICMP6_ROUTER_ADVERTISMENT_LISTEN= 11,
 };
 
+#define IP6_MIN_MTU (unsigned)1280
+#define ICMP6_ND_RECV_SIZE (IP6_MIN_MTU - sizeof(struct ip6_hdr))
+#define ICMP6_OPT_LEN_UNITS 8
+
 struct sd_icmp6_nd {
 RefCount n_ref;
 
@@ -179,44 +185,100 @@ int sd_icmp6_nd_new(sd_icmp6_nd **ret) {
 return 0;
 }
 
+static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
+  ssize_t len) {
+void *opt;
+struct nd_opt_hdr *opt_hdr;
+
+assert_return(nd, -EINVAL);
+assert_return(ra, -EINVAL);
+
+len -= sizeof(*ra);
+if (len < ICMP6_OPT_LEN_UNITS) {
+log_icmp6_nd(nd, "Router Advertisement below minimum length");
+
+return -ENOMSG;
+}
+
+opt = ra + 1;
+opt_hdr = opt;
+
+while (len != 0 && len >= opt_hdr->nd_opt_len * ICMP6_OPT_LEN_UNITS) {
+
+if (opt_hdr->nd_opt_len == 0)
+return -ENOMSG;
+
+switch (opt_hdr->nd_opt_type) {
+
+}
+
+len -= opt_hdr->nd_opt_len * ICMP6_OPT_LEN_UNITS;
+opt = (void *)((char *)opt +
+opt_hdr->nd_opt_len * ICMP6_OPT_LEN_UNITS);
+opt_hdr = opt;
+}
+
+if (len > 0)
+log_icmp6_nd(nd, "Router Advertisement contains %zd bytes of 
trailing garbage", len);
+
+return 0;
+}
+
 static int icmp6_router_advertisment_recv(sd_event_source *s, int fd,
   uint32_t revents, void *userdata)
 {
 sd_icmp6_nd *nd = userdata;
+int r, buflen = 0;
 ssize_t len;
-struct nd_router_advert ra;
+_cleanup_free_ struct nd_router_advert *ra = NULL;
 int event = ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE;
 
 assert(s);
 assert(nd);
 assert(nd->event);
 
-/* only interested in Managed/Other flag */
-len = read(fd, &ra, sizeof(ra));
-if ((size_t)len < sizeof(ra))
+r = ioctl(fd, FIONREAD, &buflen);
+if (r < 0 || buflen <= 0)
+buflen = ICMP6_ND_RECV_SIZE;
+
+ra = malloc(buflen);
+if (!ra)
+return -ENOMEM;
+
+len = read(fd, ra, buflen);
+if (len < 0) {
+log_icmp6_nd(nd, "Could not receive message from UDP socket: 
%m");
 return 0;
+}
 
-if (ra.nd_ra_type != ND_ROUTER_ADVERT)
+if (ra->nd_ra_type != ND_ROUTER_ADVERT)
 return 0;
 
-if (ra.nd_ra_code != 0)
+if (ra->nd_ra_code != 0)
 return 0;
 
 nd->timeout = sd_event_source_unref(nd->timeout);
 
 nd->state = ICMP6_ROUTER_ADVERTISMENT_LISTEN;
 
-if (ra.nd_ra_flags_reserved & ND_RA_FLAG_OTHER )
+if (ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER )
 event = ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER;
 
-if (ra.nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
+if (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
 event = ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED;
 
 log_icmp6_nd(nd, "Received Router Advertisement flags %s/%s",
- (ra.nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)? "MANAGED":
- "none",
- (ra.nd_ra_flags_reserved & ND_RA_FLAG_OTHER)? "OTHER":
- "none");
+ ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED? "MANAGED": 
"none",
+ ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER? "OTHER": 
"none");
+
+if (event != ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE) {
+r = icmp6_ra_parse(nd, ra, len);
+if (r < 0) {
+log_icmp6_nd(nd, "Could not parse Router 
Advertisement: %s",
+ strerror(-r));
+return 0;
+}
+}
 
 icmp6_nd_notify(nd, event);
 
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.or

[systemd-devel] [PATCH v2 6/9] sd-icmp6-nd: Parse ICMPv6 prefix information

2015-01-20 Thread Patrik Flykt
Save each new onlink IPv6 prefix and attach an expiry timer to it.
If the prefixes overlap, take the shorter prefix and write a debug
message about the event. Once the prefix is resent in a Router
Advertisement, update the timer. Add a new event for the expiring
prefix.

Add two helper functions, one for returning a prefix length given a
Router Advertisement and the other for generic prefix matching given
an IPv6 prefix and address.
---
 src/libsystemd-network/sd-icmp6-nd.c | 202 +++
 src/systemd/sd-icmp6-nd.h|  26 -
 2 files changed, 224 insertions(+), 4 deletions(-)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index 0cf2760..4ebeeef 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -249,6 +249,201 @@ int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu) {
 return 0;
 }
 
+static int icmp6_ra_prefix_timeout(sd_event_source *s, uint64_t usec,
+   void *userdata) {
+sd_icmp6_nd *nd = userdata;
+ICMP6Prefix *prefix, *p;
+
+assert(nd);
+
+LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) {
+if (prefix->timeout_valid != s)
+continue;
+
+log_icmp6_nd(nd, "Prefix expired 
"SD_ICMP6_ADDRESS_FORMAT_STR"/%d",
+ SD_ICMP6_ADDRESS_FORMAT_VAL(prefix->addr),
+ prefix->len);
+
+LIST_REMOVE(prefixes, nd->prefixes, prefix);
+
+icmp6_nd_notify(nd,
+
ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED);
+prefix = icmp6_prefix_unref(prefix);
+
+break;
+}
+
+return 0;
+}
+
+static int icmp6_ra_prefix_set_timeout(sd_icmp6_nd *nd,
+   ICMP6Prefix *prefix,
+   usec_t valid) {
+usec_t time_now;
+int r;
+
+assert_return(prefix, -EINVAL);
+
+r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
+if (r < 0)
+return r;
+
+prefix->timeout_valid = sd_event_source_unref(prefix->timeout_valid);
+
+r = sd_event_add_time(nd->event, &prefix->timeout_valid,
+clock_boottime_or_monotonic(), time_now + valid,
+USEC_PER_SEC, icmp6_ra_prefix_timeout, nd);
+if (r < 0)
+goto error;
+
+r = sd_event_source_set_priority(prefix->timeout_valid,
+nd->event_priority);
+if (r < 0)
+goto error;
+
+r = sd_event_source_set_description(prefix->timeout_valid,
+"icmp6-prefix-timeout");
+
+error:
+if (r < 0)
+prefix->timeout_valid =
+sd_event_source_unref(prefix->timeout_valid);
+
+return r;
+}
+
+static int icmp6_prefix_match(const struct in6_addr *prefix, uint8_t prefixlen,
+  const struct in6_addr *addr,
+  uint8_t addr_prefixlen) {
+uint8_t bytes, mask, len;
+
+assert_return(prefix, -EINVAL);
+assert_return(addr, -EINVAL);
+
+len = MIN(prefixlen, addr_prefixlen);
+
+bytes = len / 8;
+mask = 0xff << (8 - len % 8);
+
+if (memcmp(prefix, addr, bytes) != 0 ||
+(prefix->s6_addr[bytes] & mask) != (addr->s6_addr[bytes] & mask))
+return -EADDRNOTAVAIL;
+
+return 0;
+}
+
+static int icmp6_ra_prefix_match(ICMP6Prefix *head, const struct in6_addr 
*addr,
+ uint8_t addr_len, ICMP6Prefix **result) {
+ICMP6Prefix *prefix;
+
+LIST_FOREACH(prefixes, prefix, head) {
+if (icmp6_prefix_match(&prefix->addr, prefix->len, addr,
+   addr_len) >= 0) {
+*result = prefix;
+return 0;
+}
+}
+
+return -EADDRNOTAVAIL;
+}
+
+int sd_icmp6_prefix_match(struct in6_addr *prefix, uint8_t prefixlen,
+  struct in6_addr *addr) {
+return icmp6_prefix_match(prefix, prefixlen, addr,
+  sizeof(addr->s6_addr) * 8);
+}
+
+int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const struct in6_addr *addr,
+  uint8_t *prefixlen) {
+int r;
+ICMP6Prefix *prefix;
+
+assert_return(nd, -EINVAL);
+assert_return(addr, -EINVAL);
+assert_return(prefixlen, -EINVAL);
+
+r = icmp6_ra_prefix_match(nd->prefixes, addr,
+  sizeof(addr->s6_addr) * 8, &prefix);
+if (r < 0)
+return r;
+
+*prefixlen = prefix->len;
+
+return 0;
+}
+
+static int icmp6_ra_prefix_update(sd_icmp6_

[systemd-devel] [PATCH v2 4/9] sd-icmp6-nd: Add helper function to get the IPv6 link MTU

2015-01-20 Thread Patrik Flykt
Update MTU according to the latest value received.
---
 src/libsystemd-network/sd-icmp6-nd.c | 27 +++
 src/systemd/sd-icmp6-nd.h|  2 ++
 2 files changed, 29 insertions(+)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index cff69c5..0cf2760 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -237,6 +237,18 @@ int sd_icmp6_nd_new(sd_icmp6_nd **ret) {
 return 0;
 }
 
+int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu) {
+assert_return(nd, -EINVAL);
+assert_return(mtu, -EINVAL);
+
+if (nd->mtu == 0)
+return -ENOMSG;
+
+*mtu = nd->mtu;
+
+return 0;
+}
+
 static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
   ssize_t len) {
 void *opt;
@@ -256,11 +268,26 @@ static int icmp6_ra_parse(sd_icmp6_nd *nd, struct 
nd_router_advert *ra,
 opt_hdr = opt;
 
 while (len != 0 && len >= opt_hdr->nd_opt_len * ICMP6_OPT_LEN_UNITS) {
+struct nd_opt_mtu *opt_mtu;
+uint32_t mtu;
 
 if (opt_hdr->nd_opt_len == 0)
 return -ENOMSG;
 
 switch (opt_hdr->nd_opt_type) {
+case ND_OPT_MTU:
+opt_mtu = opt;
+
+mtu = be32toh(opt_mtu->nd_opt_mtu_mtu);
+
+if (mtu != nd->mtu) {
+nd->mtu = MAX(mtu, IP6_MIN_MTU);
+
+log_icmp6_nd(nd, "Router Advertisement link 
MTU %d using %d",
+ mtu, nd->mtu);
+}
+
+break;
 
 }
 
diff --git a/src/systemd/sd-icmp6-nd.h b/src/systemd/sd-icmp6-nd.h
index 73f91aa..73ebccf 100644
--- a/src/systemd/sd-icmp6-nd.h
+++ b/src/systemd/sd-icmp6-nd.h
@@ -51,6 +51,8 @@ sd_icmp6_nd *sd_icmp6_nd_ref(sd_icmp6_nd *nd);
 sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd);
 int sd_icmp6_nd_new(sd_icmp6_nd **ret);
 
+int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu);
+
 int sd_icmp6_nd_stop(sd_icmp6_nd *nd);
 int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd);
 
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH v2 9/9] networkd-dhcp6: Assign DHCPv6 addresses and prefix lengths

2015-01-20 Thread Patrik Flykt
Once IPv6 addresses have been acquired, assign these to the interface
with the prefix lengths taken from the ICMPv6 Router Advertisement
handling code. The preferred and valid IPv6 address lifetimes are
handed to the kernel which will clean up them if not renewed in time.

When a prefix announced via Router Advertisements expires, find all
addresses that match that prefix and update the address to have a
prefix length of 128 causing the prefix to be off-link.
---
 src/network/networkd-dhcp6.c | 165 +--
 1 file changed, 159 insertions(+), 6 deletions(-)

diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index c31bd4e..bcfad4c 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -28,7 +28,137 @@
 #include "sd-icmp6-nd.h"
 #include "sd-dhcp6-client.h"
 
+static int dhcp6_lease_information_acquired(sd_dhcp6_client *client,
+Link *link) {
+return 0;
+}
+
+static int dhcp6_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
+ void *userdata) {
+_cleanup_link_unref_ Link *link = userdata;
+int r;
+
+assert(link);
+
+r = sd_rtnl_message_get_errno(m);
+if (r < 0 && r != -EEXIST) {
+log_link_error(link, "Could not set DHCPv6 address: %s",
+   strerror(-r));
+
+link_enter_failed(link);
+
+} else if (r >= 0)
+link_rtnl_process_address(rtnl, m, link->manager);
+
+return 1;
+}
+
+static int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr,
+uint8_t prefixlen, uint32_t lifetime_preferred,
+uint32_t lifetime_valid) {
+int r;
+_cleanup_address_free_ Address *addr = NULL;
+
+r = address_new_dynamic(&addr);
+if (r < 0)
+return r;
+
+addr->family = AF_INET6;
+memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr));
+addr->prefixlen = prefixlen;
+
+addr->cinfo.ifa_prefered = lifetime_preferred;
+addr->cinfo.ifa_valid = lifetime_valid;
+
+log_link_struct(link, LOG_INFO, "MESSAGE=%-*s: DHCPv6 address 
"SD_ICMP6_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d",
+IFNAMSIZ,
+link->ifname, 
SD_ICMP6_ADDRESS_FORMAT_VAL(addr->in_addr.in6),
+addr->prefixlen, lifetime_preferred, lifetime_valid,
+NULL);
+
+r = address_update(addr, link, dhcp6_address_handler);
+if (r < 0)
+log_link_warning(link, "Could not assign DHCPv6 address: %s",
+strerror(-r));
+
+return r;
+}
+
+static int dhcp6_prefix_expired(Link *link) {
+int r;
+sd_dhcp6_lease *lease;
+struct in6_addr *expired_prefix, ip6_addr;
+uint8_t expired_prefixlen;
+uint32_t lifetime_preferred, lifetime_valid;
+
+r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery,
+&expired_prefix, &expired_prefixlen);
+if (r < 0)
+return r;
+
+r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease);
+if (r < 0)
+return r;
+
+sd_dhcp6_lease_reset_address_iter(lease);
+
+while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
+&lifetime_preferred,
+&lifetime_valid) >= 0) {
+
+r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen,
+&ip6_addr);
+if (r >= 0) {
+r = dhcp6_address_update(link, &ip6_addr, 128,
+lifetime_preferred,
+lifetime_valid);
+
+return r;
+}
+}
+
+return 0;
+}
+
+static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
+int r;
+sd_dhcp6_lease *lease;
+struct in6_addr ip6_addr;
+uint32_t lifetime_preferred, lifetime_valid;
+uint8_t prefixlen;
+
+r = sd_dhcp6_client_get_lease(client, &lease);
+if (r < 0)
+return r;
+
+sd_dhcp6_lease_reset_address_iter(lease);
+
+while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
+&lifetime_preferred,
+&lifetime_valid) >= 0) {
+
+r = sd_icmp6_ra_get_prefixlen(link->icmp6_router_discovery,
+&ip6_addr, &prefixlen);
+if (r < 0 && r != -EADDRNOTAVAIL) {
+log_link_warning(link, "Could not get prefix 
information: %s",
+

Re: [systemd-devel] systemd-networkd quietly ignores DHCPv6 leases

2015-01-15 Thread Patrik Flykt

Hi,

On Wed, 2015-01-14 at 16:37 +0100, Barbara Lazarowicz-Steube wrote:
> As you can see in it, having received the RA networkd correctly
> identifies the local network as managed and fires up the DHCPv6
> client. The client then receives a reply from the server and... does
> absolutely nothing with it.

Indeed. I so thought I had a patch applied that set the DHCPv6 address
for the interface. Apparently such functionality has gone into /dev/null
instead, and as a result you will need the next version of the DHCPv6
address assignment patch recently posted on the mailing list.

Anyway it is excellent news that DHCPv6 is being used out there!


Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 00/11] DHCPv6 address assignment

2015-01-14 Thread Patrik Flykt
On Wed, 2015-01-14 at 01:48 +0100, Zbigniew Jędrzejewski-Szmek wrote:
> I replied to individual patches with some comments. Looks good
> in general.

Something has happened to my emacs indentation since last time, and I
have to admit getting a bit rusty also...

I'll update the patch set according to your comments.

Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH] TODO: DHCPv6 Information Request has been implemented

2015-01-14 Thread Patrik Flykt
On Wed, 2015-01-14 at 01:53 +0100, Zbigniew Jędrzejewski-Szmek wrote:
> Yeah, there's no need to sent this to the mailing list. It is unlikely
> to be wrong, and even if it it, we can revert or amend. The same for
> 1/11 in the other series.

If it scares you less that way I'll silently apply future trivialities
like the one above :-)

Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH] TODO: DHCPv6 Information Request has been implemented

2015-01-13 Thread Patrik Flykt
On Tue, 2015-01-13 at 14:32 +0200, Patrik Flykt wrote:
> Just a trivial TODO update, I'll push it right away.

Patch applied.

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH] TODO: DHCPv6 Information Request has been implemented

2015-01-13 Thread Patrik Flykt
---

Hi,

Just a trivial TODO update, I'll push it right away.

Cheers,

Patrik


 TODO | 1 -
 1 file changed, 1 deletion(-)

diff --git a/TODO b/TODO
index 1d497b2..3c2c2c9 100644
--- a/TODO
+++ b/TODO
@@ -792,7 +792,6 @@ Features:
- write more test cases
- implement and do duplicate address detection, see rfc 4862, 5.4.
- implement reconfigure support, see 5.3., 15.11. and 22.20.
-   - implement information request, see 1.2. and 18.1.5.
- implement support for temporary adressess (IA_TA)
- implement dhcpv6 authentication
- investigate the usefulness of Confirm messages; i.e. are there any
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 08/11] test-icmp6-nd: Add test cases for prefixes

2015-01-13 Thread Patrik Flykt
Add test cases that feeds an Router Advertisement to the ICMPv6 code
and verify that the correct prefix lengths are returned given an IPv6
address.

Enhance the prefix verification test by adding a shorter prefix and
check that the intended prefix lengths are now updated.
---
 src/libsystemd-network/test-icmp6-rs.c | 207 +++--
 1 file changed, 200 insertions(+), 7 deletions(-)

diff --git a/src/libsystemd-network/test-icmp6-rs.c 
b/src/libsystemd-network/test-icmp6-rs.c
index 8a42a34..85e0239 100644
--- a/src/libsystemd-network/test-icmp6-rs.c
+++ b/src/libsystemd-network/test-icmp6-rs.c
@@ -34,6 +34,9 @@ static bool verbose = true;
 static sd_event_source *test_hangcheck;
 static int test_fd[2];
 
+typedef int (*send_ra_t)(uint8_t flags);
+static send_ra_t send_ra_function;
+
 static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
  void *userdata) {
 assert_se(false);
@@ -50,6 +53,191 @@ int dhcp_network_icmp6_bind_router_solicitation(int index) {
 return test_fd[0];
 }
 
+static int send_ra_short_prefix(uint8_t flags) {
+uint8_t advertisement[] = {
+0x86, 0x00, 0xbe, 0xd7, 0x40, 0xc0, 0x00, 0xb4,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+0x03, 0x04, 0x34, 0xc0, 0x00, 0x00, 0x01, 0xf4,
+0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
+   sizeof(advertisement));
+
+return 0;
+}
+
+static void test_short_prefix_cb(sd_icmp6_nd *nd, int event, void *userdata) {
+sd_event *e = userdata;
+struct {
+struct in6_addr addr;
+uint8_t prefixlen;
+bool success;
+} addrs[] = {
+{ { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+  52, true },
+{ { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+  64, false },
+{ { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+  60, true },
+{ { { { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
+  64, true },
+{ { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xed,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
+  52, true },
+};
+uint8_t prefixlen;
+unsigned int i;
+
+for (i = 0; i < ELEMENTSOF(addrs); i++) {
+printf("  %s prefix %02x%02x:%02x%02x:%02x%02x:%02x%02x",
+__FUNCTION__,
+addrs[i].addr.s6_addr[0], addrs[i].addr.s6_addr[1],
+addrs[i].addr.s6_addr[2], addrs[i].addr.s6_addr[3],
+addrs[i].addr.s6_addr[4], addrs[i].addr.s6_addr[5],
+addrs[i].addr.s6_addr[6], addrs[i].addr.s6_addr[7]);
+
+if (addrs[i].success) {
+assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
+&prefixlen) >= 
0);
+assert_se(addrs[i].prefixlen == prefixlen);
+printf("/%d onlink\n", prefixlen);
+} else {
+assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
+&prefixlen) == 
-EADDRNOTAVAIL);
+printf("/128 offlink\n");
+}
+}
+
+sd_event_exit(e, 0);
+}
+
+static int send_ra_prefixes(uint8_t flags) {
+uint8_t advertisement[] = {
+0x86, 0x00, 0xbe, 0xd7, 0x40, 0xc0, 0x00, 0xb4,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x04, 0x3f, 0xc0, 0x00, 0x00, 0x01, 0xf4,
+0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x04, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58,
+0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x04, 0x3c, 0x80, 0x00, 0x00, 0x03, 0x84,
+0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16,

[systemd-devel] [PATCH 07/11] sd-icmp6-nd: Parse ICMPv6 prefix information

2015-01-13 Thread Patrik Flykt
Save each new onlink IPv6 prefix and attach an expiry timer to it.
If the prefixes overlap, take the shorter prefix and write a debug
message about the event. Once the prefix is resent in a Router
Advertisement, update the timer. Add a new event for the expiring
prefix.

Add two helper functions, one for returning a prefix length given a
Router Advertisement and the other for generic prefix matching given
an IPv6 prefix and address.
---
 src/libsystemd-network/sd-icmp6-nd.c | 222 +++
 src/systemd/sd-icmp6-nd.h|   6 +
 2 files changed, 228 insertions(+)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index 3501055..4848912 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -283,11 +283,227 @@ int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu) {
 return 0;
 }
 
+static int icmp6_ra_prefix_timeout(sd_event_source *s, uint64_t usec,
+void *userdata) {
+sd_icmp6_nd *nd = userdata;
+struct icmp6_prefix *prefix, *p;
+
+assert(nd);
+assert(nd->link);
+assert(nd->link->prefixes);
+
+LIST_FOREACH_SAFE(prefixes, prefix, p, nd->link->prefixes) {
+if (prefix->timeout_valid != s)
+continue;
+
+log_icmp6_nd(nd, "Prefix expired 
%02x%02x:%02x%02x:%02x%02x:%02x%02x/%d",
+prefix->addr.s6_addr[0], prefix->addr.s6_addr[1],
+prefix->addr.s6_addr[2], prefix->addr.s6_addr[3],
+prefix->addr.s6_addr[4], prefix->addr.s6_addr[5],
+prefix->addr.s6_addr[6], prefix->addr.s6_addr[7],
+prefix->len);
+
+LIST_REMOVE(prefixes, nd->link->prefixes, prefix);
+
+icmp6_nd_notify(nd,
+
ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED);
+prefix = icmp6_prefix_unref(prefix);
+
+break;
+}
+
+return 0;
+}
+
+static int icmp6_ra_prefix_set_timeout(sd_icmp6_nd *nd,
+struct icmp6_prefix *prefix, usec_t valid) {
+usec_t time_now;
+int r;
+
+assert_return(prefix, -EINVAL);
+
+r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
+if (r < 0)
+return r;
+
+prefix->timeout_valid = sd_event_source_unref(prefix->timeout_valid);
+
+r = sd_event_add_time(nd->event, &prefix->timeout_valid,
+clock_boottime_or_monotonic(), time_now + valid,
+USEC_PER_SEC, icmp6_ra_prefix_timeout, nd);
+if (r < 0)
+goto error;
+
+r = sd_event_source_set_priority(prefix->timeout_valid,
+nd->event_priority);
+if (r < 0)
+goto error;
+
+r = sd_event_source_set_description(prefix->timeout_valid,
+"icmp6-prefix-timeout");
+
+error:
+if (r < 0)
+prefix->timeout_valid =
+sd_event_source_unref(prefix->timeout_valid);
+
+return r;
+}
+
+static int icmp6_prefix_match(const struct in6_addr *prefix, uint8_t prefixlen,
+const struct in6_addr *addr, uint8_t addr_prefixlen) {
+uint8_t bytes, mask, len;
+
+assert_return(prefix, -EINVAL);
+assert_return(addr, -EINVAL);
+
+len = (prefixlen < addr_prefixlen)? prefixlen: addr_prefixlen;
+
+bytes = len / 8;
+
+if (memcmp(prefix, addr, bytes))
+return -EADDRNOTAVAIL;
+
+if (len % 8) {
+mask = 0xff << (8 - len % 8);
+
+if ((prefix->s6_addr[bytes] & mask) !=
+(addr->s6_addr[bytes] & mask))
+return -EADDRNOTAVAIL;
+}
+
+return 0;
+}
+
+static int icmp6_ra_prefix_match(struct icmp6_prefix *head,
+const struct in6_addr *addr, uint8_t addr_len,
+struct icmp6_prefix **result) {
+struct icmp6_prefix *prefix;
+
+LIST_FOREACH(prefixes, prefix, head) {
+if (icmp6_prefix_match(&prefix->addr, prefix->len, addr,
+addr_len) >= 0) {
+*result = prefix;
+return 0;
+}
+}
+
+return -EADDRNOTAVAIL;
+}
+
+int sd_icmp6_prefix_match(struct in6_addr *prefix, uint8_t prefixlen,
+struct in6_addr *addr) {
+return icmp6_prefix_match(prefix, prefixlen, addr,
+sizeof(addr->s6_addr) * 8);
+}
+
+int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const struct in6_addr *addr,
+uint8_t *prefixlen) {
+int r;
+struct icmp6_prefix 

[systemd-devel] [PATCH 04/11] sd-icmp6-nd: Add link and prefix structures for ICMPv6

2015-01-13 Thread Patrik Flykt
Each ICMPv6 structure has an interface index and will therefore be
associated with an IPv6 link containing a list of of prefixes.
---
 src/libsystemd-network/sd-icmp6-nd.c | 99 
 1 file changed, 99 insertions(+)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index c9b390e..35d5f5f 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -44,6 +44,23 @@ enum icmp6_nd_state {
 #define ICMP6_ND_RECV_SIZE (IP6_MIN_MTU - sizeof(struct ip6_hdr))
 #define ICMP6_OPT_LEN_UNITS 8
 
+struct icmp6_prefix {
+RefCount n_ref;
+
+LIST_FIELDS(struct icmp6_prefix, prefixes);
+
+uint8_t len;
+sd_event_source *timeout_valid;
+struct in6_addr addr;
+};
+
+struct icmp6_link {
+RefCount n_ref;
+
+uint32_t mtu;
+LIST_HEAD(struct icmp6_prefix, prefixes);
+};
+
 struct sd_icmp6_nd {
 RefCount n_ref;
 
@@ -52,6 +69,7 @@ struct sd_icmp6_nd {
 int event_priority;
 int index;
 struct ether_addr mac_addr;
+struct icmp6_link *link;
 int fd;
 sd_event_source *recv;
 sd_event_source *timeout;
@@ -62,6 +80,72 @@ struct sd_icmp6_nd {
 
 #define log_icmp6_nd(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, 
__LINE__, __func__, "ICMPv6 CLIENT: " fmt, ##__VA_ARGS__)
 
+static struct icmp6_prefix *icmp6_prefix_unref(struct icmp6_prefix *prefix) {
+if (prefix && REFCNT_DEC(prefix->n_ref) <= 0) {
+prefix->timeout_valid =
+sd_event_source_unref(prefix->timeout_valid);
+
+free(prefix);
+}
+
+return NULL;
+}
+
+static int icmp6_prefix_new(struct icmp6_prefix **ret) {
+_cleanup_free_ struct icmp6_prefix *prefix = NULL;
+
+assert(ret);
+
+prefix = new0(struct icmp6_prefix, 1);
+if (!prefix)
+return -ENOMEM;
+
+prefix->n_ref = REFCNT_INIT;
+LIST_INIT(prefixes, prefix);
+
+*ret = prefix;
+prefix = NULL;
+
+return 0;
+}
+
+static struct icmp6_link *icmp6_link_unref(struct icmp6_link *link) {
+if (link && REFCNT_DEC(link->n_ref) <= 0) {
+struct icmp6_prefix *prefix, *p;
+
+LIST_FOREACH_SAFE(prefixes, prefix, p, link->prefixes) {
+LIST_REMOVE(prefixes, link->prefixes, prefix);
+
+prefix = icmp6_prefix_unref(prefix);
+}
+free(link);
+}
+
+return NULL;
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct icmp6_link*, icmp6_link_unref);
+#define _cleanup_icmp6_link_free_ _cleanup_(icmp6_link_unrefp)
+
+static int icmp6_link_new(struct icmp6_link **ret) {
+_cleanup_free_ struct icmp6_link *link = NULL;
+
+assert(ret);
+
+link = new0(struct icmp6_link, 1);
+if (!link)
+return -ENOMEM;
+
+link->n_ref = REFCNT_INIT;
+
+LIST_HEAD_INIT(link->prefixes);
+
+*ret = link;
+link = NULL;
+
+return 0;
+}
+
 static void icmp6_nd_notify(sd_icmp6_nd *nd, int event)
 {
 if (nd->callback)
@@ -156,6 +240,8 @@ sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd) {
 icmp6_nd_init(nd);
 sd_icmp6_nd_detach_event(nd);
 
+nd->link = icmp6_link_unref(nd->link);
+
 free(nd);
 }
 
@@ -191,6 +277,7 @@ static int icmp6_ra_parse(sd_icmp6_nd *nd, struct 
nd_router_advert *ra,
 struct nd_opt_hdr *opt_hdr;
 
 assert_return(nd, -EINVAL);
+assert_return(nd->link, -EINVAL);
 assert_return(ra, -EINVAL);
 
 len -= sizeof(*ra);
@@ -225,6 +312,7 @@ static int icmp6_router_advertisment_recv(sd_event_source 
*s, int fd,
 int r, buflen;
 ssize_t len;
 _cleanup_free_ struct nd_router_advert *ra = NULL;
+_cleanup_icmp6_link_free_ struct icmp6_link *link = NULL;
 int event = ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE;
 
 assert(s);
@@ -251,6 +339,17 @@ static int icmp6_router_advertisment_recv(sd_event_source 
*s, int fd,
 if (ra->nd_ra_code != 0)
 return 0;
 
+if (!nd->link) {
+r = icmp6_link_new(&link);
+if (r < 0) {
+log_icmp6_nd(nd, "Could not allocate ICMP6 link 
struct: %m");
+return 0;
+}
+
+nd->link = link;
+link = NULL;
+}
+
 nd->timeout = sd_event_source_unref(nd->timeout);
 
 nd->state = ICMP6_ROUTER_ADVERTISMENT_LISTEN;
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 06/11] test-icmp6-rs: Add trivial test case for a MTU that is not present

2015-01-13 Thread Patrik Flykt
---
 src/libsystemd-network/test-icmp6-rs.c | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/libsystemd-network/test-icmp6-rs.c 
b/src/libsystemd-network/test-icmp6-rs.c
index be64d33..8a42a34 100644
--- a/src/libsystemd-network/test-icmp6-rs.c
+++ b/src/libsystemd-network/test-icmp6-rs.c
@@ -30,7 +30,7 @@ static struct ether_addr mac_addr = {
 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
 };
 
-static bool verbose = false;
+static bool verbose = true;
 static sd_event_source *test_hangcheck;
 static int test_fd[2];
 
@@ -93,6 +93,8 @@ static void test_rs_done(sd_icmp6_nd *nd, int event, void 
*userdata) {
 { ND_RA_FLAG_OTHER, ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER },
 { ND_RA_FLAG_MANAGED, ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED }
 };
+uint32_t mtu;
+
 assert_se(nd);
 
 assert_se(event == flag_event[idx].event);
@@ -101,10 +103,14 @@ static void test_rs_done(sd_icmp6_nd *nd, int event, void 
*userdata) {
 if (verbose)
 printf("  got event %d\n", event);
 
-if (idx < 3)
+if (idx < 3) {
 send_ra(flag_event[idx].flag);
-else
-sd_event_exit(e, 0);
+return;
+}
+
+assert_se(sd_icmp6_ra_get_mtu(nd, &mtu) == -ENOMSG);
+
+sd_event_exit(e, 0);
 }
 
 static void test_rs(sd_event *e) {
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 10/11] networkd-dhcp6: Assign DHCPv6 addresses and prefix lengths

2015-01-13 Thread Patrik Flykt
Once IPv6 addresses have been acquired, assign these to the interface
with the prefix lengths taken from the ICMPv6 Router Advertisement
handling code. The preferred and valid IPv6 address lifetimes are
handed to the kernel which will clean up them if not renewed in time.

When a prefix announced via Router Advertisements expires, find all
addresses that match that prefix and update the address to have a
prefix lenght of 128 causing the prefix to be off-link.
---
 src/network/networkd-dhcp6.c | 179 +--
 src/network/networkd-link.h  |  10 +++
 src/network/networkd.c   |   1 +
 3 files changed, 184 insertions(+), 6 deletions(-)

diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index c31bd4e..5f78f93 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -28,7 +28,151 @@
 #include "sd-icmp6-nd.h"
 #include "sd-dhcp6-client.h"
 
+static int dhcp6_lease_information_acquired(sd_dhcp6_client *client,
+Link *link) {
+int r;
+uint32_t mtu;
+
+r = sd_icmp6_ra_get_mtu(link->icmp6_router_discovery, &mtu);
+if (r >= 0) {
+r = link_set_mtu(link, mtu);
+if (r < 0)
+log_link_error(link, "Failed to set IPv6 MTU to %" 
PRIu16, mtu);
+}
+
+return 0;
+}
+
+static int dhcp6_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
+ void *userdata) {
+_cleanup_link_unref_ Link *link = userdata;
+int r;
+
+assert(link);
+
+r = sd_rtnl_message_get_errno(m);
+if (r < 0 && r != -EEXIST) {
+log_link_error(link, "Could not set DHCPv6 address: %s",
+   strerror(-r));
+
+link_enter_failed(link);
+
+} else if (r >= 0)
+link_rtnl_process_address(rtnl, m, link->manager);
+
+return 1;
+}
+
+static int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr,
+uint8_t prefixlen, uint32_t lifetime_preferred,
+uint32_t lifetime_valid) {
+int r;
+_cleanup_address_free_ Address *addr = NULL;
+
+r = address_new_dynamic(&addr);
+if (r < 0)
+return r;
+
+addr->family = AF_INET6;
+memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr));
+addr->prefixlen = prefixlen;
+
+addr->cinfo.ifa_prefered = lifetime_preferred;
+addr->cinfo.ifa_valid = lifetime_valid;
+
+log_link_struct(link, LOG_INFO, "MESSAGE=%-*s: DHCPv6 address 
%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x/%d timeout preferred %d valid %d",
+IFNAMSIZ,
+link->ifname, ADDRESS6_FMT_VAL(addr->in_addr.in6),
+addr->prefixlen, lifetime_preferred, lifetime_valid,
+NULL);
+
+r = address_update(addr, link, dhcp6_address_handler);
+if (r < 0)
+log_link_warning(link, "Could not assign DHCPv6 address: %s",
+strerror(-r));
+
+return r;
+}
+
+static int dhcp6_prefix_expired(Link *link) {
+int r;
+sd_dhcp6_lease *lease;
+struct in6_addr *expired_prefix, ip6_addr;
+uint8_t expired_prefixlen;
+uint32_t lifetime_preferred, lifetime_valid;
+
+r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery,
+&expired_prefix, &expired_prefixlen);
+if (r < 0)
+return r;
+
+r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease);
+if (r < 0)
+return r;
+
+r = sd_dhcp6_lease_reset_address_iter(lease);
+if (r < 0 && r != -ENOMSG)
+return r;
+
+while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
+&lifetime_preferred,
+&lifetime_valid) >= 0) {
+
+r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen,
+&ip6_addr);
+if (r >= 0) {
+r = dhcp6_address_update(link, &ip6_addr, 128,
+lifetime_preferred,
+lifetime_valid);
+
+return r;
+}
+}
+
+return 0;
+}
+
+static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
+int r;
+sd_dhcp6_lease *lease;
+struct in6_addr ip6_addr;
+uint32_t lifetime_preferred, lifetime_valid;
+uint8_t prefixlen;
+
+r = sd_dhcp6_client_get_lease(client, &lease);
+if (r < 0)
+return r;
+
+r = sd_dhcp6_lease_reset_address_iter(lease);
+if (r < 0 && r != -ENOMSG)
+ 

[systemd-devel] [PATCH 02/11] sd-dhcp6-lease: Revise address iteration functions

2015-01-13 Thread Patrik Flykt
Revise the address iteration functions so that one helper function
resets the iterator to the start of the address list while the
second one fetches addresses one by one.

The test case is also updated.
---
 src/libsystemd-network/sd-dhcp6-lease.c| 24 +++
 src/libsystemd-network/test-dhcp6-client.c | 37 +++---
 src/systemd/sd-dhcp6-lease.h   |  7 ++
 3 files changed, 29 insertions(+), 39 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp6-lease.c 
b/src/libsystemd-network/sd-dhcp6-lease.c
index 8960fac..b3ae0c0 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -146,10 +146,9 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t 
*iaid) {
 return 0;
 }
 
-int sd_dhcp6_lease_get_next_address(sd_dhcp6_lease *lease,
-struct in6_addr *addr,
-uint32_t *lifetime_preferred,
-uint32_t *lifetime_valid) {
+int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr,
+uint32_t *lifetime_preferred,
+uint32_t *lifetime_valid) {
 assert_return(lease, -EINVAL);
 assert_return(addr, -EINVAL);
 assert_return(lifetime_preferred, -EINVAL);
@@ -169,22 +168,15 @@ int sd_dhcp6_lease_get_next_address(sd_dhcp6_lease *lease,
 return 0;
 }
 
-int sd_dhcp6_lease_get_first_address(sd_dhcp6_lease *lease,
- struct in6_addr *addr,
- uint32_t *lifetime_preferred,
- uint32_t *lifetime_valid) {
+int sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) {
 assert_return(lease, -EINVAL);
-assert_return(addr, -EINVAL);
-assert_return(lifetime_preferred, -EINVAL);
-assert_return(lifetime_valid, -EINVAL);
-
-if (!lease->ia.addresses)
-return -ENOMSG;
 
 lease->addr_iter = lease->ia.addresses;
 
-return sd_dhcp6_lease_get_next_address(lease, addr, lifetime_preferred,
-   lifetime_valid);
+if (!lease->addr_iter)
+return -ENOMSG;
+
+return 0;
 }
 
 sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index 7590839..bc9a9e2 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -286,25 +286,26 @@ static int test_advertise_option(sd_event *e) {
 
 assert_se(opt_clientid);
 
-assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, <_pref,
-   <_valid) >= 0);
+assert_se(sd_dhcp6_lease_reset_address_iter(lease) >= 0);
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
+  <_valid) >= 0);
 assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
 assert_se(lt_pref == 150);
 assert_se(lt_valid == 180);
-assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, <_pref,
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
   <_valid) == -ENOMSG);
 
-assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, <_pref,
-   <_valid) >= 0);
+assert_se(sd_dhcp6_lease_reset_address_iter(lease) >= 0);
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
+  <_valid) >= 0);
 assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
-assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, <_pref,
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
   <_valid) == -ENOMSG);
-assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, <_pref,
-  <_valid) == -ENOMSG);
-assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, <_pref,
-   <_valid) >= 0);
+assert_se(sd_dhcp6_lease_reset_address_iter(lease) >= 0);
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
+  <_valid) >= 0);
 assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
-assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, <_pref,
+assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref,
   <_valid) == -ENOMSG);
 
 assert_se(dhcp6_lease_get_serverid(lease, &opt, &len) >= 0);
@@ -439,13 +440,14 @@ static int test_client_verify_request(DHCP6Message 
*request, uint8_t *o

[systemd-devel] [PATCH 09/11] sd-icmp6-nd: Add support for fetching the latest expired prefix

2015-01-13 Thread Patrik Flykt
Keep the expired prefix for the duration of the prefix expiration event
and remove it afterwards.
---
 src/libsystemd-network/sd-icmp6-nd.c | 23 +++
 src/systemd/sd-icmp6-nd.h|  2 ++
 2 files changed, 25 insertions(+)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index 4848912..ad9bbdb 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -58,6 +58,7 @@ struct icmp6_link {
 RefCount n_ref;
 
 uint32_t mtu;
+struct icmp6_prefix *expired_prefix;
 LIST_HEAD(struct icmp6_prefix, prefixes);
 };
 
@@ -305,8 +306,11 @@ static int icmp6_ra_prefix_timeout(sd_event_source *s, 
uint64_t usec,
 
 LIST_REMOVE(prefixes, nd->link->prefixes, prefix);
 
+nd->link->expired_prefix = prefix;
 icmp6_nd_notify(nd,
 
ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED);
+nd->link->expired_prefix = NULL;
+
 prefix = icmp6_prefix_unref(prefix);
 
 break;
@@ -419,6 +423,25 @@ int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const 
struct in6_addr *addr,
 return 0;
 }
 
+int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr,
+uint8_t *prefixlen)
+{
+assert_return(nd, -EINVAL);
+assert_return(addr, -EINVAL);
+assert_return(prefixlen, -EINVAL);
+
+if (!nd->link)
+return -EADDRNOTAVAIL;
+
+if (!nd->link->expired_prefix)
+return -EADDRNOTAVAIL;
+
+*addr = &nd->link->expired_prefix->addr;
+*prefixlen = nd->link->expired_prefix->len;
+
+return 0;
+}
+
 static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
 const struct nd_opt_prefix_info *prefix_opt) {
 int r;
diff --git a/src/systemd/sd-icmp6-nd.h b/src/systemd/sd-icmp6-nd.h
index 9139c06..acb4107 100644
--- a/src/systemd/sd-icmp6-nd.h
+++ b/src/systemd/sd-icmp6-nd.h
@@ -58,6 +58,8 @@ int sd_icmp6_prefix_match(struct in6_addr *prefix, uint8_t 
prefixlen,
 int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu);
 int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const struct in6_addr *addr,
 uint8_t *prefixlen);
+int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr,
+uint8_t *prefixlen);
 
 int sd_icmp6_nd_stop(sd_icmp6_nd *nd);
 int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd);
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 11/11] sd_dhcp6_lease: Support DNS and NTP options

2015-01-13 Thread Patrik Flykt
Store arrays of found DNS and NTP IPv6 addresses and strings of DNS
search domains and NTP host names as specified in RFC 3646 and RFC
5908.
---
 src/libsystemd-network/dhcp6-internal.h   |   3 +
 src/libsystemd-network/dhcp6-lease-internal.h |  18 
 src/libsystemd-network/dhcp6-option.c |  22 
 src/libsystemd-network/dhcp6-protocol.h   |   6 ++
 src/libsystemd-network/sd-dhcp6-client.c  |  22 
 src/libsystemd-network/sd-dhcp6-lease.c   | 140 ++
 src/systemd/sd-dhcp6-lease.h  |   6 ++
 7 files changed, 217 insertions(+)

diff --git a/src/libsystemd-network/dhcp6-internal.h 
b/src/libsystemd-network/dhcp6-internal.h
index 4f54ad8..fd7deb9 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -68,6 +68,9 @@ int dhcp6_option_parse(uint8_t **buf, size_t *buflen, 
uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
 int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
   DHCP6IA *ia);
+int dhcp6_option_get_ip6addrs(uint8_t *optval, uint16_t optlen,
+struct in6_addr **addrs, size_t *size,
+size_t *allocated);
 
 int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address);
 int dhcp6_network_send_udp_socket(int s, struct in6_addr *address,
diff --git a/src/libsystemd-network/dhcp6-lease-internal.h 
b/src/libsystemd-network/dhcp6-lease-internal.h
index 109e0f4..dcc7913 100644
--- a/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/libsystemd-network/dhcp6-lease-internal.h
@@ -40,6 +40,19 @@ struct sd_dhcp6_lease {
 DHCP6IA ia;
 
 DHCP6Address *addr_iter;
+
+struct in6_addr *dns;
+size_t dns_size;
+size_t dns_allocated;
+char *domain_list;
+size_t domain_list_size;
+size_t domain_list_allocated;
+struct in6_addr *ntp;
+size_t ntp_size;
+size_t ntp_allocated;
+char *ntp_fqdn;
+size_t ntp_fqdn_size;
+size_t ntp_fqdn_allocated;
 };
 
 int dhcp6_lease_clear_timers(DHCP6IA *ia);
@@ -56,6 +69,11 @@ int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool 
*rapid_commit);
 
 int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
 
+int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
+int dhcp6_lease_set_domain_list(sd_dhcp6_lease *lease, uint8_t *optval,
+size_t optlen);
+int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
+
 int dhcp6_lease_new(sd_dhcp6_lease **ret);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref);
diff --git a/src/libsystemd-network/dhcp6-option.c 
b/src/libsystemd-network/dhcp6-option.c
index ea863f4..7a7aad4 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -317,3 +317,25 @@ error:
 
 return r;
 }
+
+int dhcp6_option_get_ip6addrs(uint8_t *optval, uint16_t optlen,
+struct in6_addr **addrs, size_t *size,
+size_t *allocated) {
+size_t in6_size = sizeof(**addrs);
+
+assert_return(optval, -EINVAL);
+assert_return(addrs, -EINVAL);
+assert_return(size, -EINVAL);
+
+if (optlen % in6_size)
+return -EINVAL;
+
+if (!GREEDY_REALLOC0(*addrs, *allocated, *size + optlen))
+return -ENOMEM;
+
+memcpy(*addrs + *size / in6_size, optval, optlen);
+
+*size += optlen;
+
+return 0;
+}
diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index 3e0f339..9330f23 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -134,6 +134,12 @@ enum {
 };
 
 enum {
+DHCP6_NTP_SUBOPTION_SRV_ADDR= 1,
+DHCP6_NTP_SUBOPTION_MC_ADDR = 2,
+DHCP6_NTP_SUBOPTION_SRV_FQDN= 3,
+};
+
+enum {
 DHCP6_STATUS_SUCCESS= 0,
 DHCP6_STATUS_UNSPEC_FAIL= 1,
 DHCP6_STATUS_NO_ADDRS_AVAIL = 2,
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 940a606..ca6f316 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -804,7 +804,29 @@ static int client_parse_message(sd_dhcp6_client *client,
 return r;
 
 break;
+
+case DHCP6_OPTION_DNS_SERVERS:
+r = dhcp6_lease_set_dns(lease, optval, optlen);
+if (r < 0)
+return r;
+
+break;
+
+case DHCP6_OPTION_DOMAIN_LIST:
+r = dhcp6_lease_set_domain_list(lease, optval, optlen);
+if (r < 

[systemd-devel] [PATCH 05/11] sd-icmp6-nd: Add helper function to get the IPv6 link MTU

2015-01-13 Thread Patrik Flykt
Update MTU according to the latest value received.
---
 src/libsystemd-network/sd-icmp6-nd.c | 30 ++
 src/systemd/sd-icmp6-nd.h|  2 ++
 2 files changed, 32 insertions(+)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index 35d5f5f..3501055 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -271,10 +271,24 @@ int sd_icmp6_nd_new(sd_icmp6_nd **ret) {
 return 0;
 }
 
+int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu) {
+assert_return(nd, -EINVAL);
+assert_return(mtu, -EINVAL);
+
+if (!nd->link || !nd->link->mtu)
+return -ENOMSG;
+
+*mtu = nd->link->mtu;
+
+return 0;
+}
+
 static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
 ssize_t len) {
 void *opt;
 struct nd_opt_hdr *opt_hdr;
+struct nd_opt_mtu *opt_mtu;
+uint32_t mtu;
 
 assert_return(nd, -EINVAL);
 assert_return(nd->link, -EINVAL);
@@ -293,6 +307,22 @@ static int icmp6_ra_parse(sd_icmp6_nd *nd, struct 
nd_router_advert *ra,
 return -ENOMSG;
 
 switch (opt_hdr->nd_opt_type) {
+case ND_OPT_MTU:
+opt_mtu = opt;
+
+mtu = be32toh(opt_mtu->nd_opt_mtu_mtu);
+
+if (!nd->link->mtu || mtu < nd->link->mtu) {
+if (mtu < IP6_MIN_MTU)
+nd->link->mtu = IP6_MIN_MTU;
+else
+nd->link->mtu = mtu;
+
+log_icmp6_nd(nd, "Link MTU %d advertised %d",
+nd->link->mtu, mtu);
+}
+
+break;
 
 }
 
diff --git a/src/systemd/sd-icmp6-nd.h b/src/systemd/sd-icmp6-nd.h
index 73f91aa..73ebccf 100644
--- a/src/systemd/sd-icmp6-nd.h
+++ b/src/systemd/sd-icmp6-nd.h
@@ -51,6 +51,8 @@ sd_icmp6_nd *sd_icmp6_nd_ref(sd_icmp6_nd *nd);
 sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd);
 int sd_icmp6_nd_new(sd_icmp6_nd **ret);
 
+int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu);
+
 int sd_icmp6_nd_stop(sd_icmp6_nd *nd);
 int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd);
 
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 00/11] DHCPv6 address assignment

2015-01-13 Thread Patrik Flykt

  Hi,

Here is a patch set covering on-link prefix detection and using the prefix
length information when setting DHCPv6 addresses.

To be able to have a correct prefix for the IPv6 adresses, the prefixes
need to be collected in patches 03 and 04. Prefix handling and matching
happens in patch 07. Patch 08 contains a test case for these.

ICMPv6 Router Advertisement MTU values are collected in patch 05 with an
extremely trivial test in patch 06 - basically there to just ensure some
functionality exists.

If the prefix information ever expires, patch 09 is there to make it
possible to fetch the expired one.

With the help of the revised address iteration functions in patch 02,
patch 10 fetches the proper prefix length and sets the IPv6 address. The
patch also attempts to upgrade the IPv6 address prefix length to 128
should the prefix ever expire, it does so but misses to decrement address
lifetimes. Something to do for a next patch or two, I guess.

In addition, patch 01 clears up a forgotten debug printout while patch 11
fetches DNS and NTP information. Fetching DNS and NTP information have not
been tested or used yet so proceed with caution or leave patch 11 for later.


Please review,

   Patrik


Patrik Flykt (11):
  sd-dhcp6-client: Remove unnecessary debug printout
  sd-dhcp6-lease: Revise address iteration functions
  sd-icmp6-nd: Update Router Advertisement handling
  sd-icmp6-nd: Add link and prefix structures for ICMPv6
  sd-icmp6-nd: Add helper function to get the IPv6 link MTU
  test-icmp6-rs: Add trivial test case for a MTU that is not present
  sd-icmp6-nd: Parse ICMPv6 prefix information
  test-icmp6-nd: Add test cases for prefixes
  sd-icmp6-nd: Add support for fetching the latest expired prefix
  networkd-dhcp6: Assign DHCPv6 addresses and prefix lengths
  sd_dhcp6_lease: Support DNS and NTP options

 src/libsystemd-network/dhcp6-internal.h   |   3 +
 src/libsystemd-network/dhcp6-lease-internal.h |  18 ++
 src/libsystemd-network/dhcp6-option.c |  22 ++
 src/libsystemd-network/dhcp6-protocol.h   |   6 +
 src/libsystemd-network/sd-dhcp6-client.c  |  23 +-
 src/libsystemd-network/sd-dhcp6-lease.c   | 162 +-
 src/libsystemd-network/sd-icmp6-nd.c  | 449 +-
 src/libsystemd-network/test-dhcp6-client.c|  37 +--
 src/libsystemd-network/test-icmp6-rs.c| 221 -
 src/network/networkd-dhcp6.c  | 179 +-
 src/network/networkd-link.h   |  10 +
 src/network/networkd.c|   1 +
 src/systemd/sd-dhcp6-lease.h  |  13 +-
 src/systemd/sd-icmp6-nd.h |  10 +
 14 files changed, 1088 insertions(+), 66 deletions(-)

-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 01/11] sd-dhcp6-client: Remove unnecessary debug printout

2015-01-13 Thread Patrik Flykt
---
 src/libsystemd-network/sd-dhcp6-client.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 017371e..940a606 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -1025,7 +1025,6 @@ static int client_start(sd_dhcp6_client *client, enum 
DHCP6State state)
 assert_return(client->index > 0, -EINVAL);
 assert_return(client->state != state, -EINVAL);
 
-log_dhcp6_client(client, "client state %d new state %d", 
client->state, state);
 client->timeout_resend_expire =
 sd_event_source_unref(client->timeout_resend_expire);
 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 03/11] sd-icmp6-nd: Update Router Advertisement handling

2015-01-13 Thread Patrik Flykt
As the IPv6 prefixes are needed, update the ICMPv6 Router Advertisement
code to dynamically allocate a suitably sized buffer. Iterate through
the ICMPv6 options one by one returning error if the option length is
too big to fit the buffer.
---
 src/libsystemd-network/sd-icmp6-nd.c | 75 +++-
 1 file changed, 65 insertions(+), 10 deletions(-)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index fbaf093..c9b390e 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -18,9 +18,11 @@
 ***/
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "socket-util.h"
 #include "refcnt.h"
@@ -38,6 +40,10 @@ enum icmp6_nd_state {
 ICMP6_ROUTER_ADVERTISMENT_LISTEN= 11,
 };
 
+#define IP6_MIN_MTU 1280
+#define ICMP6_ND_RECV_SIZE (IP6_MIN_MTU - sizeof(struct ip6_hdr))
+#define ICMP6_OPT_LEN_UNITS 8
+
 struct sd_icmp6_nd {
 RefCount n_ref;
 
@@ -179,45 +185,94 @@ int sd_icmp6_nd_new(sd_icmp6_nd **ret) {
 return 0;
 }
 
+static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
+ssize_t len) {
+void *opt;
+struct nd_opt_hdr *opt_hdr;
+
+assert_return(nd, -EINVAL);
+assert_return(ra, -EINVAL);
+
+len -= sizeof(*ra);
+if (len < ICMP6_OPT_LEN_UNITS)
+return 0;
+
+opt = ra + 1;
+opt_hdr = opt;
+
+while (len && len >= opt_hdr->nd_opt_len * ICMP6_OPT_LEN_UNITS) {
+
+if (!opt_hdr->nd_opt_len)
+return -ENOMSG;
+
+switch (opt_hdr->nd_opt_type) {
+
+}
+
+len -= opt_hdr->nd_opt_len * ICMP6_OPT_LEN_UNITS;
+opt = (void *)((char *)opt +
+opt_hdr->nd_opt_len * ICMP6_OPT_LEN_UNITS);
+opt_hdr = opt;
+}
+
+return 0;
+}
+
 static int icmp6_router_advertisment_recv(sd_event_source *s, int fd,
   uint32_t revents, void *userdata)
 {
 sd_icmp6_nd *nd = userdata;
+int r, buflen;
 ssize_t len;
-struct nd_router_advert ra;
+_cleanup_free_ struct nd_router_advert *ra = NULL;
 int event = ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE;
 
 assert(s);
 assert(nd);
 assert(nd->event);
 
-/* only interested in Managed/Other flag */
-len = read(fd, &ra, sizeof(ra));
-if ((size_t)len < sizeof(ra))
+r = ioctl(fd, FIONREAD, &buflen);
+if (r < 0 || buflen <= 0)
+buflen = ICMP6_ND_RECV_SIZE;
+
+ra = malloc0(buflen);
+if (!ra)
+return -ENOMEM;
+
+len = read(fd, ra, buflen);
+if (len < 0) {
+log_icmp6_nd(nd, "Could not receive message from UDP socket: 
%m");
 return 0;
+}
 
-if (ra.nd_ra_type != ND_ROUTER_ADVERT)
+if (ra->nd_ra_type != ND_ROUTER_ADVERT)
 return 0;
 
-if (ra.nd_ra_code != 0)
+if (ra->nd_ra_code != 0)
 return 0;
 
 nd->timeout = sd_event_source_unref(nd->timeout);
 
 nd->state = ICMP6_ROUTER_ADVERTISMENT_LISTEN;
 
-if (ra.nd_ra_flags_reserved & ND_RA_FLAG_OTHER )
+if (ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER )
 event = ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER;
 
-if (ra.nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
+if (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
 event = ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED;
 
 log_icmp6_nd(nd, "Received Router Advertisement flags %s/%s",
- (ra.nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)? "MANAGED":
+ (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)? 
"MANAGED":
  "none",
- (ra.nd_ra_flags_reserved & ND_RA_FLAG_OTHER)? "OTHER":
+ (ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)? "OTHER":
  "none");
 
+if (event != ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE) {
+r = icmp6_ra_parse(nd, ra, len);
+if (r < 0)
+return 0;
+}
+
 icmp6_nd_notify(nd, event);
 
 return 0;
-- 
2.1.4

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 5/6] networkd-dhcp6: Move ICMPv6 and DHCPv6 configuration to new file

2014-12-10 Thread Patrik Flykt
Handle all aspects of ICMPv6 and DHCPv6 in a file of its own as is done
with DHCPv4 and IPv4LL.
---
 Makefile.am  |   1 +
 src/network/networkd-dhcp6.c | 165 +++
 src/network/networkd-link.c  | 122 +---
 src/network/networkd-link.h  |   1 +
 4 files changed, 168 insertions(+), 121 deletions(-)
 create mode 100644 src/network/networkd-dhcp6.c

diff --git a/Makefile.am b/Makefile.am
index 23210ff..6f02c74 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5247,6 +5247,7 @@ libsystemd_networkd_core_la_SOURCES = \
src/network/networkd-link.c \
src/network/networkd-ipv4ll.c \
src/network/networkd-dhcp4.c \
+   src/network/networkd-dhcp6.c \
src/network/networkd-network.c \
src/network/networkd-address.c \
src/network/networkd-route.c \
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
new file mode 100644
index 000..bf8d78b
--- /dev/null
+++ b/src/network/networkd-dhcp6.c
@@ -0,0 +1,165 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 Intel Corporation. All rights reserved.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see .
+***/
+
+#include 
+#include 
+
+#include "networkd-link.h"
+#include "network-internal.h"
+
+#include "sd-icmp6-nd.h"
+#include "sd-dhcp6-client.h"
+
+static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
+Link *link = userdata;
+
+assert(link);
+assert(link->network);
+assert(link->manager);
+
+if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+return;
+
+switch(event) {
+case DHCP6_EVENT_STOP:
+case DHCP6_EVENT_RESEND_EXPIRE:
+case DHCP6_EVENT_RETRANS_MAX:
+case DHCP6_EVENT_IP_ACQUIRE:
+log_link_debug(link, "DHCPv6 event %d", event);
+
+break;
+
+default:
+if (event < 0)
+log_link_warning(link, "DHCPv6 error: %s",
+ strerror(-event));
+else
+log_link_warning(link, "DHCPv6 unknown event: %d",
+ event);
+return;
+}
+}
+
+static int dhcp6_configure(Link *link) {
+int r;
+
+assert_return(link, -EINVAL);
+
+if (link->dhcp6_client)
+return 0;
+
+r = sd_dhcp6_client_new(&link->dhcp6_client);
+if (r < 0)
+return r;
+
+r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
+if (r < 0) {
+link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+return r;
+}
+
+r = sd_dhcp6_client_set_mac(link->dhcp6_client,
+(const uint8_t *) &link->mac,
+sizeof (link->mac), ARPHRD_ETHER);
+if (r < 0) {
+link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+return r;
+}
+
+r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex);
+if (r < 0) {
+link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+return r;
+}
+
+r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
+ link);
+if (r < 0) {
+link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+return r;
+}
+
+r = sd_dhcp6_client_start(link->dhcp6_client);
+if (r < 0)
+link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+
+return r;
+}
+
+static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
+Link *link = userdata;
+
+assert(link);
+assert(link->network);
+assert(link->manager);
+
+if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+return;
+
+switch(event) {
+case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
+case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
+return;
+
+case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
+case ICMP6_EVENT_R

[systemd-devel] [PATCH 6/6] networkd-dhcp6: Support ICMPv6 Other information

2014-12-10 Thread Patrik Flykt
When ICMPv6 Other information is received, enable Information request
in DHCPv6. If the DHCPv6 client already exists, only update the client
if there is a transition from Other to Managed state.
---
 src/network/networkd-dhcp6.c | 55 
 1 file changed, 50 insertions(+), 5 deletions(-)

diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index bf8d78b..c31bd4e 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -43,6 +43,7 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, 
void *userdata) {
 case DHCP6_EVENT_RESEND_EXPIRE:
 case DHCP6_EVENT_RETRANS_MAX:
 case DHCP6_EVENT_IP_ACQUIRE:
+case DHCP6_EVENT_INFORMATION_REQUEST:
 log_link_debug(link, "DHCPv6 event %d", event);
 
 break;
@@ -58,13 +59,47 @@ static void dhcp6_handler(sd_dhcp6_client *client, int 
event, void *userdata) {
 }
 }
 
-static int dhcp6_configure(Link *link) {
+static int dhcp6_configure(Link *link, int event) {
 int r;
+bool information_request;
 
 assert_return(link, -EINVAL);
 
-if (link->dhcp6_client)
-return 0;
+if (link->dhcp6_client) {
+if (event != ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED)
+return 0;
+
+r = sd_dhcp6_client_get_information_request(link->dhcp6_client,
+&information_request);
+if (r < 0) {
+log_link_warning(link, "Could not get DHCPv6 
Information request setting");
+link->dhcp6_client =
+sd_dhcp6_client_unref(link->dhcp6_client);
+return r;
+}
+
+if (!information_request)
+return r;
+
+r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
+false);
+if (r < 0) {
+log_link_warning(link, "Could not unset DHCPv6 
Information request");
+link->dhcp6_client =
+sd_dhcp6_client_unref(link->dhcp6_client);
+return r;
+}
+
+r = sd_dhcp6_client_start(link->dhcp6_client);
+if (r < 0) {
+log_link_warning(link, "Could not restart DHCPv6 after 
enabling Information request");
+link->dhcp6_client =
+sd_dhcp6_client_unref(link->dhcp6_client);
+return r;
+}
+
+return r;
+}
 
 r = sd_dhcp6_client_new(&link->dhcp6_client);
 if (r < 0)
@@ -97,6 +132,16 @@ static int dhcp6_configure(Link *link) {
 return r;
 }
 
+if (event == ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER) {
+r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
+true);
+if (r < 0) {
+link->dhcp6_client =
+sd_dhcp6_client_unref(link->dhcp6_client);
+return r;
+}
+}
+
 r = sd_dhcp6_client_start(link->dhcp6_client);
 if (r < 0)
 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
@@ -116,10 +161,10 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int 
event, void *userdata) {
 
 switch(event) {
 case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
-case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
 return;
 
 case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
+case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
 case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
 break;
 
@@ -134,7 +179,7 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int 
event, void *userdata) {
 return;
 }
 
-dhcp6_configure(link);
+dhcp6_configure(link, event);
 }
 
 int icmp6_configure(Link *link) {
-- 
2.1.3

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 0/6] DHCPv6 Information request

2014-12-10 Thread Patrik Flykt

Hi,

This patch set implements DHCPv6 Information request, i.e. the situation
where Router Advertisments announce that only 'Other' information, not
IPv6 addresses, is available via DHCPv6. This patch doesn't have anything
to do with the prefix delegation discussed earlier; it was simply left
half implemented for a while on my machine.

The first two patches clean up the code a bit, so that later additions
are easier to implement.

The third patch adds support for requesting additional information and
ignores any addresses that should not have been sent by the DHCPv6
server anyway. Patch 04 makes a simple test case verifying also that it
is possible to switch from Information request to a normal DHCPv6 address
acquisition procedure.

Patch 05 moves systemd-networkd DHCPv6 initialization and handling into
a file of its own following what's been done for DHCPv4 and IPv4 link
local. Finally patch 06 adds the necessary logic to request the addtional
information from the DHCPv6 server and possibly upgrading the procedure
to the normal IPv6 address aquisition process should the 'Managed' bit
become set in the Router Advertisments. Reversing this procedure, i.e.
"downgrading" it back to fetching additional information only is not
possible according to RFCs.


Please review,

Patrik


Patrik Flykt (6):
  sd-dhcp6-client: Make end of successfull option parsing explicit
  sd-dhcp6-lease: Return only -EINVAL when a NULL lease is supplied
  sd-dhcp6-client: Implement Information Request message
  test-dhcp6-client: Add a simple Information Request test case
  networkd-dhcp6: Move ICMPv6 and DHCPv6 configuration to new file
  networkd-dhcp6: Support ICMPv6 Other information

 Makefile.am|   1 +
 src/libsystemd-network/dhcp6-protocol.h|   3 +
 src/libsystemd-network/sd-dhcp6-client.c   | 150 -
 src/libsystemd-network/sd-dhcp6-lease.c|   4 +-
 src/libsystemd-network/test-dhcp6-client.c | 126 ++---
 src/network/networkd-dhcp6.c   | 210 +
 src/network/networkd-link.c| 122 +
 src/network/networkd-link.h|   1 +
 src/systemd/sd-dhcp6-client.h  |   5 +
 9 files changed, 445 insertions(+), 177 deletions(-)
 create mode 100644 src/network/networkd-dhcp6.c

-- 
2.1.3

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 3/6] sd-dhcp6-client: Implement Information Request message

2014-12-10 Thread Patrik Flykt
Implement Information Request message according to RFC 3315, section
18.1.5. with the excepion that the first message is not delayed by a
random amount. Instead systemd-networkd is supposed to take care of
desynchronizing between other clients.

Initialize the DHCPv6 client structure in sd_dhcp6_client_start()
as this allows toggling between information request and normal
DHCPv6 address aquisition modes.
---
 src/libsystemd-network/dhcp6-protocol.h  |   3 +
 src/libsystemd-network/sd-dhcp6-client.c | 144 +++
 src/systemd/sd-dhcp6-client.h|   5 ++
 3 files changed, 117 insertions(+), 35 deletions(-)

diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index eaa6717..3e0f339 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -51,6 +51,8 @@ enum {
 DHCP6_PORT_CLIENT   = 546,
 };
 
+#define DHCP6_INF_TIMEOUT   1 * USEC_PER_SEC
+#define DHCP6_INF_MAX_RT120 * USEC_PER_SEC
 #define DHCP6_SOL_MAX_DELAY 1 * USEC_PER_SEC
 #define DHCP6_SOL_TIMEOUT   1 * USEC_PER_SEC
 #define DHCP6_SOL_MAX_RT120 * USEC_PER_SEC
@@ -71,6 +73,7 @@ enum {
 
 enum DHCP6State {
 DHCP6_STATE_STOPPED = 0,
+DHCP6_STATE_INFORMATION_REQUEST = 1,
 DHCP6_STATE_SOLICITATION= 2,
 DHCP6_STATE_REQUEST = 3,
 DHCP6_STATE_BOUND   = 4,
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index cc5b744..940a606 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -62,6 +62,7 @@ struct sd_dhcp6_client {
 usec_t transaction_start;
 struct sd_dhcp6_lease *lease;
 int fd;
+bool information_request;
 be16_t *req_opts;
 size_t req_opts_allocated;
 size_t req_opts_len;
@@ -227,6 +228,25 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, 
uint16_t type, uint8_t *du
 return 0;
 }
 
+int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client,
+bool enabled) {
+assert_return(client, -EINVAL);
+
+client->information_request = enabled;
+
+return 0;
+}
+
+int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client,
+bool *enabled) {
+assert_return(client, -EINVAL);
+assert_return(enabled, -EINVAL);
+
+*enabled = client->information_request;
+
+return 0;
+}
+
 int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
uint16_t option) {
 size_t t;
@@ -333,6 +353,11 @@ static int client_send_message(sd_dhcp6_client *client, 
usec_t time_now) {
 message->transaction_id = client->transaction_id;
 
 switch(client->state) {
+case DHCP6_STATE_INFORMATION_REQUEST:
+message->type = DHCP6_INFORMATION_REQUEST;
+
+break;
+
 case DHCP6_STATE_SOLICITATION:
 message->type = DHCP6_SOLICIT;
 
@@ -494,6 +519,12 @@ static int client_timeout_resend(sd_event_source *s, 
uint64_t usec,
 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
 
 switch (client->state) {
+case DHCP6_STATE_INFORMATION_REQUEST:
+init_retransmit_time = DHCP6_INF_TIMEOUT;
+max_retransmit_time = DHCP6_INF_MAX_RT;
+
+break;
+
 case DHCP6_STATE_SOLICITATION:
 
 if (client->retransmit_count && client->lease) {
@@ -744,6 +775,12 @@ static int client_parse_message(sd_dhcp6_client *client,
 break;
 
 case DHCP6_OPTION_IA_NA:
+if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
+log_dhcp6_client(client, "Information request 
ignoring IA NA option");
+
+break;
+}
+
 r = dhcp6_option_parse_ia(&optval, &optlen, optcode,
   &lease->ia);
 if (r < 0 && r != -ENOMSG)
@@ -779,10 +816,12 @@ static int client_parse_message(sd_dhcp6_client *client,
 return -EINVAL;
 }
 
-r = dhcp6_lease_get_serverid(lease, &id, &id_len);
-if (r < 0)
-log_dhcp6_client(client, "%s has no server id",
- dhcp6_message_type_to_string(message->type));
+if (client->state != DHCP6_STATE_INFORMATION_REQUEST) {
+r = dhcp6_lease_get_serverid(lease, &id, &id_len);
+if (r < 0)
+log_dhcp6_client(client, "%s has no serv

[systemd-devel] [PATCH 1/6] sd-dhcp6-client: Make end of successfull option parsing explicit

2014-12-10 Thread Patrik Flykt
When all DHCPv6 options have been parsed, dhcp6_option_parse() returns
-ENOMSG. Explicitely set the return value to indicate success so that
later code does not need to take this special value into account.
---
 src/libsystemd-network/sd-dhcp6-client.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 8537d7c..cc5b744 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -770,7 +770,10 @@ static int client_parse_message(sd_dhcp6_client *client,
 }
 }
 
-if ((r < 0 && r != -ENOMSG) || !clientid) {
+if (r == -ENOMSG)
+r = 0;
+
+if (r < 0 || !clientid) {
 log_dhcp6_client(client, "%s has incomplete options",
  dhcp6_message_type_to_string(message->type));
 return -EINVAL;
-- 
2.1.3

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 4/6] test-dhcp6-client: Add a simple Information Request test case

2014-12-10 Thread Patrik Flykt
Start the DHCPv6 test case by sending an Information Request, verifying
the reply and continuing at once with the normal address acquisition
procedure. Reuse the DHCPv6 Solicit Reply so that the client code is
verified to ignore any erroneously added IPv6 address information.
---
 src/libsystemd-network/sd-dhcp6-client.c   |   1 +
 src/libsystemd-network/test-dhcp6-client.c | 126 -
 2 files changed, 108 insertions(+), 19 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 940a606..017371e 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -1025,6 +1025,7 @@ static int client_start(sd_dhcp6_client *client, enum 
DHCP6State state)
 assert_return(client->index > 0, -EINVAL);
 assert_return(client->state != state, -EINVAL);
 
+log_dhcp6_client(client, "client state %d new state %d", 
client->state, state);
 client->timeout_resend_expire =
 sd_event_source_unref(client->timeout_resend_expire);
 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index 26b28a2..7590839 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -41,7 +41,7 @@ static struct ether_addr mac_addr = {
 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
 };
 
-static bool verbose = false;
+static bool verbose = true;
 
 static sd_event_source *hangcheck;
 static int test_dhcp_fd[2];
@@ -335,13 +335,19 @@ int detect_virtualization(const char **id) {
 return 1;
 }
 
-int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
-assert_se(index == test_index);
+static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
+   void *userdata) {
+sd_event *e = userdata;
 
-if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_dhcp_fd) < 0)
-return -errno;
+assert_se(e);
+assert_se(event == DHCP6_EVENT_IP_ACQUIRE);
 
-return test_dhcp_fd[0];
+assert_se(sd_dhcp6_client_set_request_option(client, 
DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
+
+if (verbose)
+printf("  got DHCPv6 event %d\n", event);
+
+sd_event_exit(e, 0);
 }
 
 static int test_client_send_reply(DHCP6Message *request) {
@@ -513,6 +519,83 @@ static int test_client_verify_solicit(DHCP6Message 
*solicit, uint8_t *option,
 return 0;
 }
 
+static void test_client_information_cb(sd_dhcp6_client *client, int event,
+   void *userdata) {
+sd_event *e = userdata;
+
+assert_se(e);
+assert_se(event == DHCP6_EVENT_INFORMATION_REQUEST);
+
+if (verbose)
+printf("  got DHCPv6 event %d\n", event);
+
+assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0);
+assert_se(sd_dhcp6_client_set_callback(client,
+   test_client_solicit_cb, e) >= 
0);
+
+assert_se(sd_dhcp6_client_start(client) >= 0);
+}
+
+static int test_client_verify_information_request(DHCP6Message 
*information_request,
+  uint8_t *option, size_t len) 
{
+
+_cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+uint8_t *optval;
+uint16_t optcode;
+size_t optlen;
+bool found_clientid = false, found_elapsed_time = false;
+int r;
+struct in6_addr addr;
+uint32_t lt_pref, lt_valid;
+
+assert_se(information_request->type == DHCP6_INFORMATION_REQUEST);
+
+assert_se(dhcp6_lease_new(&lease) >= 0);
+
+while ((r = dhcp6_option_parse(&option, &len,
+   &optcode, &optlen, &optval)) >= 0) {
+switch(optcode) {
+case DHCP6_OPTION_CLIENTID:
+assert_se(!found_clientid);
+found_clientid = true;
+
+assert_se(optlen == sizeof(test_duid));
+memcpy(&test_duid, optval, sizeof(test_duid));
+
+break;
+
+case DHCP6_OPTION_IA_NA:
+assert_not_reached("IA TA option must not be present");
+
+break;
+
+case DHCP6_OPTION_SERVERID:
+assert_not_reached("Server ID option must not be 
present");
+
+break;
+
+case DHCP6_OPTION_ELAPSED_TIME:
+assert_se(!found_elapsed_time);
+found_elapsed_time = true;
+
+assert_se(optlen == 2);
+
+break;
+}
+}
+
+assert_se(r == -ENOMSG);
+ass

[systemd-devel] [PATCH 2/6] sd-dhcp6-lease: Return only -EINVAL when a NULL lease is supplied

2014-12-10 Thread Patrik Flykt
Suppyling a NULL lease is not a condition that needs to be asserted,
returning -EINVAL is informative enough to the caller. This simplifies
calling code and doesn't falsely indicate that something erroneous was
attempted.
---
 src/libsystemd-network/sd-dhcp6-lease.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/libsystemd-network/sd-dhcp6-lease.c 
b/src/libsystemd-network/sd-dhcp6-lease.c
index e2715ea..8960fac 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -110,9 +110,11 @@ int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, 
uint8_t preference) {
 }
 
 int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference) {
-assert_return(lease, -EINVAL);
 assert_return(preference, -EINVAL);
 
+if (!lease)
+return -EINVAL;
+
 *preference = lease->preference;
 
 return 0;
-- 
2.1.3

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] systemd-networkd & DHCPv6 Prefix Delegation

2014-12-04 Thread Patrik Flykt
On Thu, 2014-12-04 at 03:27 +0100, Tom Gundersen wrote:
> Patrik, do you have any plans for this? I agree, this is likely
> something we want.

I'm tempted to do something about it. Give me time until mid next week
and we'll see what happens.

Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH] sd-dhcp-client: fix REBOOT state handling

2014-11-19 Thread Patrik Flykt
On Tue, 2014-11-18 at 18:41 +0100, Tom Gundersen wrote:

> (but cc'ing Patrik just to make sure)

> > RFC 2131:
> >
> >  secs   2  Filled in by client, seconds elapsed since client
> >began address acquisition or renewal process.

> > @@ -422,7 +423,15 @@ static int client_message_init(sd_dhcp_client *client, 
> > DHCPPacket **ret,
> >
> >  /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP 
> > servers
> > refuse to issue an DHCP lease if 'secs' is set to zero */
> > -packet->dhcp.secs = htobe16(client->secs);
> > +r = sd_event_now(client->event, clock_boottime_or_monotonic(), 
> > &time_now);
> > +if (r < 0)
> > +return r;
> > +assert(time_now >= client->start_time);
> > +
> > +/* seconds between sending first and last DISCOVER
> > + * must always be strictly positive to deal with broken servers */
> > +secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
> > +packet->dhcp.secs = htobe16(secs);

The previous code assumed that resending a message mean really sending
an identical one in place of the lost one. This change actually nags on
the other end that time has really passed, be it a clue to a DHCP relay
that it should do something else than before. Looking at the RFC snippet
and the patch, I think this is what the RFC actually tried to say.

Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH] sd-dhcp-client: support non-Ethernet hardware addresses

2014-10-06 Thread Patrik Flykt
On Fri, 2014-10-03 at 10:04 -0500, Dan Williams wrote:
> sd_dhcp_client_set_mac() does have an 'arp_type' parameter that's
> cached
> in the client struct, so that could be changed to:
> 
> if (client->arp_type == ARPHRD_ETHER)
> 
> if you'd like.

If it's there already, it is a good thing to use. It does look clearer
in the code that way.

Thanks,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH] sd-dhcp-client: support non-Ethernet hardware addresses

2014-10-03 Thread Patrik Flykt
On Fri, 2014-10-03 at 15:48 +0300, Patrik Flykt wrote:
> On Fri, 2014-09-26 at 15:15 -0500, Dan Williams wrote:
> >  /* RFC2132 section 4.1.1:
> > The client MUST include its hardware address in the ’chaddr’ 
> > field, if
> > -   necessary for delivery of DHCP reply messages.
> > +   necessary for delivery of DHCP reply messages.  Non-Ethernet
> > +   interfaces will leave 'chaddr' empty and use the client 
> > identifier
> > +   instead (eg, RFC 4390 section 2.1).
> >   */
> > -memcpy(&packet->dhcp.chaddr, &client->client_id.mac_addr, 
> > ETH_ALEN);
> > +if (client->mac_addr_len == ETH_ALEN)
> > +memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
> 
> Sorry about the late review, but shouldn't this be more generic if
> written:
> if (client->mac_addr_len)
> memcpy(&packet->dhcp.chaddr, &client->mac_addr, 
> client->mac_addr_len);
> 
> With that, all cases are covered. Which, AFAIK, are none in addition to
> ethernet. An assert() should check the given MAC address length at some
> point in the code so that it cannot be > 16.

And then I notice that infiniband has a MAC address length of 20. For
all practical purposes this works as expected. Except if we want to go
nitpicking when setting the MAC address and also require the address
type to be supplied? Probably not...

Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH] sd-dhcp-client: support non-Ethernet hardware addresses

2014-10-03 Thread Patrik Flykt

Hi,

On Fri, 2014-09-26 at 15:15 -0500, Dan Williams wrote:
>  /* RFC2132 section 4.1.1:
> The client MUST include its hardware address in the ’chaddr’ 
> field, if
> -   necessary for delivery of DHCP reply messages.
> +   necessary for delivery of DHCP reply messages.  Non-Ethernet
> +   interfaces will leave 'chaddr' empty and use the client identifier
> +   instead (eg, RFC 4390 section 2.1).
>   */
> -memcpy(&packet->dhcp.chaddr, &client->client_id.mac_addr, ETH_ALEN);
> +if (client->mac_addr_len == ETH_ALEN)
> +memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);

Sorry about the late review, but shouldn't this be more generic if
written:
if (client->mac_addr_len)
memcpy(&packet->dhcp.chaddr, &client->mac_addr, 
client->mac_addr_len);

With that, all cases are covered. Which, AFAIK, are none in addition to
ethernet. An assert() should check the given MAC address length at some
point in the code so that it cannot be > 16.

...

> diff --git a/src/libsystemd-network/sd-dhcp-server.c 
> b/src/libsystemd-network/sd-dhcp-server.c
> index a6d6178..24fedd2 100644
> --- a/src/libsystemd-network/sd-dhcp-server.c
> +++ b/src/libsystemd-network/sd-dhcp-server.c
> @@ -388,16 +388,16 @@ static int server_message_init(sd_dhcp_server *server, 
> DHCPPacket **ret,
>  assert(IN_SET(type, DHCP_OFFER, DHCP_ACK, DHCP_NAK));
>  
>  packet = malloc0(sizeof(DHCPPacket) + req->max_optlen);
>  if (!packet)
>  return -ENOMEM;
>  
>  r = dhcp_message_init(&packet->dhcp, BOOTREPLY,
> -  be32toh(req->message->xid), type, 
> req->max_optlen,
> -  &optoffset);
> +  be32toh(req->message->xid), type, ARPHRD_ETHER,
> +  req->max_optlen, &optoffset);
>  if (r < 0)
>  return r;
>  
>  packet->dhcp.flags = req->message->flags;
>  packet->dhcp.giaddr = req->message->giaddr;
>  memcpy(&packet->dhcp.chaddr, &req->message->chaddr, ETH_ALEN);

Unrelated to your patch, I think a bug is lurking on the last line. I
believe the full 16 bytes of dhcp.chaddr should be copied from the
client's message according to the table in Section 4.3.1 in RFC 2131.
Including any possible garbage the client left in its message. I wonder
how many client implementation break due to such a change, though...

Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH] sd-dhcp-client: support non-Ethernet hardware addresses

2014-10-03 Thread Patrik Flykt

Hi,

On Thu, 2014-10-02 at 20:05 +0200, Tom Gundersen wrote:
> > The DHCPv4 header is the same format no matter what the LL address size,
> > but for non-ethernet the hlen is 0 and the chaddr is zeroed.  The BPF is
> > seeded with an hlen of 0 and a valid ETH_ALEN sized buffer of all zeros.
> > So both the hlen and chaddr comparisons comparison should succeed.
> >
> > Does that make sense?  I might have missed something too though...
> 
> So that sounds fine, but my concern was: are we guaranteed that all
> implementations properly zero out the remaining bytes past the hlen
> first ones? Sounds weird to reject a package if it has hlen == 0 and
> garbage in chaddr, or is the zeroing something we can rely on? (In
> that case I guess we should extend the check to check all 16 bytes,
> and not only the 6 first ones to make it truly agnostic).
> 
> Patrik, any thoughts?

At least RFC2131 says that the DHCP server uses the 'chaddr' supplied by
the client without considering hardware address length in 'hlen'.
Apparently both client and server need to use the same hardware
addressing, so 'hlen' on both ends match anyway.

Since our client implementation has properly zeroed out the DHCP header
before filling it with information, there should be no problem just
comparing all 16 bytes of 'chaddr' where the first 'hlen' bytes is the
hardware address and the rest should definitely be zero, since that was
what was sent in the first place. Currently the client side
implementation only checks that the N first bytes containing the MAC
address, so technically that is a bug. For a hardware address length of
zero, 'chaddr' should match what the client sent, in our case 16 bytes
of zeroes.


Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 1/3] sd-dhcp6-client: Implement Elapsed Time option

2014-09-10 Thread Patrik Flykt
On Tue, 2014-09-09 at 13:39 +0200, Tom Gundersen wrote:
> Hi Patrik,
> 
> These all look good. Please push!

Done that.

Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 0/3] Add DHCPv6 Elapsed Time option

2014-09-01 Thread Patrik Flykt

Hi,

This patch implements the DHCPv6 Elapsed Time option. RFC 3315 says
that this option is a MUST, so it'd be better to have it implemented.

The patch is quite straight forward, the time at transaction start is
recorded and the elapsed time calculated when the message is sent. In
order to work in a situation where the main loop is not yet running,
the start time in the stopped state is read directly from the clock.
All other states are entered via callbacks attached to the main loop,
which means they can request the current time from the sd_event itself.

The test case for this option verifies that the option is present and
has a proper length.


Cheers,

Patrik


Patrik Flykt (3):
  sd-dhcp6-client: Implement Elapsed Time option
  test-dhcp6-client: Add checks for Elapsed Time option
  TODO: Remove Elapsed Time DHCPv6 option as it is done

 TODO   |  1 -
 src/libsystemd-network/sd-dhcp6-client.c   | 40 ++
 src/libsystemd-network/test-dhcp6-client.c | 32 +---
 3 files changed, 58 insertions(+), 15 deletions(-)

-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 2/3] test-dhcp6-client: Add checks for Elapsed Time option

2014-09-01 Thread Patrik Flykt
Verify that the Elapsed Time option is present.
---
 src/libsystemd-network/test-dhcp6-client.c | 32 ++
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index d102a79..37ddfc2 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -269,6 +269,11 @@ static int test_advertise_option(sd_event *e) {
  *optval) >= 0);
 break;
 
+case DHCP6_OPTION_ELAPSED_TIME:
+assert_se(optlen == 2);
+
+break;
+
 default:
 break;
 }
@@ -361,7 +366,8 @@ static int test_client_verify_request(DHCP6Message 
*request, uint8_t *option,
 uint8_t *optval;
 uint16_t optcode;
 size_t optlen;
-bool found_clientid = false, found_iana = false, found_serverid = 
false;
+bool found_clientid = false, found_iana = false, found_serverid = 
false,
+found_elapsed_time = false;
 int r;
 struct in6_addr addr;
 be32_t val;
@@ -410,11 +416,20 @@ static int test_client_verify_request(DHCP6Message 
*request, uint8_t *option,
 assert_se(!memcmp(&msg_advertise[179], optval, 
optlen));
 
 break;
+
+case DHCP6_OPTION_ELAPSED_TIME:
+assert_se(!found_elapsed_time);
+found_elapsed_time = true;
+
+assert_se(optlen == 2);
+
+break;
 }
 }
 
 assert_se(r == -ENOMSG);
-assert_se(found_clientid && found_iana && found_serverid);
+assert_se(found_clientid && found_iana && found_serverid &&
+  found_elapsed_time);
 
 assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, <_pref,
<_valid) >= 0);
@@ -452,7 +467,8 @@ static int test_client_verify_solicit(DHCP6Message 
*solicit, uint8_t *option,
 uint8_t *optval;
 uint16_t optcode;
 size_t optlen;
-bool found_clientid = false, found_iana = false;
+bool found_clientid = false, found_iana = false,
+found_elapsed_time = false;
 int r;
 
 assert_se(solicit->type == DHCP6_SOLICIT);
@@ -478,11 +494,19 @@ static int test_client_verify_solicit(DHCP6Message 
*solicit, uint8_t *option,
 memcpy(&test_iaid, optval, sizeof(test_iaid));
 
 break;
+
+case DHCP6_OPTION_ELAPSED_TIME:
+assert_se(!found_elapsed_time);
+found_elapsed_time = true;
+
+assert_se(optlen == 2);
+
+break;
 }
 }
 
 assert_se(r == -ENOMSG);
-assert_se(found_clientid && found_iana);
+assert_se(found_clientid && found_iana && found_elapsed_time);
 
 return 0;
 }
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 1/3] sd-dhcp6-client: Implement Elapsed Time option

2014-09-01 Thread Patrik Flykt
Implement Elapsed Time option as it is defined as MUST in RFC 3315,
section 22.9. The elapsed time value is a 1/100th of a second with
a max value of 0x, i.e. 655.35 seconds.

As the main loop might not be running yet when sd_dhcp6_client_start() is
called, fetch the monotonic time directly and not from the event loop
while in state DHCP6_STATE_STOPPED.
---
 src/libsystemd-network/sd-dhcp6-client.c | 40 
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 6860c66..c190b56 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -49,6 +49,7 @@ struct sd_dhcp6_client {
 struct ether_addr mac_addr;
 DHCP6IA ia_na;
 be32_t transaction_id;
+usec_t transaction_start;
 struct sd_dhcp6_lease *lease;
 int fd;
 be16_t *req_opts;
@@ -203,6 +204,7 @@ static int client_reset(sd_dhcp6_client *client) {
 client->fd = safe_close(client->fd);
 
 client->transaction_id = 0;
+client->transaction_start = 0;
 
 client->ia_na.timeout_t1 =
 sd_event_source_unref(client->ia_na.timeout_t1);
@@ -230,13 +232,15 @@ static void client_stop(sd_dhcp6_client *client, int 
error) {
 client_reset(client);
 }
 
-static int client_send_message(sd_dhcp6_client *client) {
+static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
 _cleanup_free_ DHCP6Message *message = NULL;
 struct in6_addr all_servers =
 IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
 size_t len, optlen = 512;
 uint8_t *opt;
 int r;
+usec_t elapsed_usec;
+be16_t elapsed_time;
 
 len = sizeof(DHCP6Message) + optlen;
 
@@ -308,6 +312,17 @@ static int client_send_message(sd_dhcp6_client *client) {
 if (r < 0)
 return r;
 
+elapsed_usec = time_now - client->transaction_start;
+if (elapsed_usec < 0x * USEC_PER_MSEC * 10)
+elapsed_time = htobe16(elapsed_usec / USEC_PER_MSEC / 10);
+else
+elapsed_time = 0x;
+
+r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ELAPSED_TIME,
+sizeof(elapsed_time), &elapsed_time);
+if (r < 0)
+return r;
+
 r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
   len - optlen);
 if (r < 0)
@@ -455,15 +470,14 @@ static int client_timeout_resend(sd_event_source *s, 
uint64_t usec,
 return 0;
 }
 
-r = client_send_message(client);
-if (r >= 0)
-client->retransmit_count++;
-
-
 r = sd_event_now(client->event, clock_boottime_or_monotonic(), 
&time_now);
 if (r < 0)
 goto error;
 
+r = client_send_message(client, time_now);
+if (r >= 0)
+client->retransmit_count++;
+
 if (!client->retransmit_time) {
 client->retransmit_time =
 client_timeout_compute_random(init_retransmit_time);
@@ -882,6 +896,15 @@ static int client_start(sd_dhcp6_client *client, enum 
DHCP6State state)
 client->retransmit_time = 0;
 client->retransmit_count = 0;
 
+if (client->state == DHCP6_STATE_STOPPED) {
+time_now = now(clock_boottime_or_monotonic());
+} else {
+r = sd_event_now(client->event, clock_boottime_or_monotonic(),
+ &time_now);
+if (r < 0)
+return r;
+}
+
 switch (state) {
 case DHCP6_STATE_STOPPED:
 case DHCP6_STATE_SOLICITATION:
@@ -926,10 +949,6 @@ static int client_start(sd_dhcp6_client *client, enum 
DHCP6State state)
 
 case DHCP6_STATE_BOUND:
 
-r = sd_event_now(client->event, clock_boottime_or_monotonic(), 
&time_now);
-if (r < 0)
-return r;
-
 if (client->lease->ia.lifetime_t1 == 0x ||
 client->lease->ia.lifetime_t2 == 0x) {
 
@@ -996,6 +1015,7 @@ static int client_start(sd_dhcp6_client *client, enum 
DHCP6State state)
 }
 
 client->transaction_id = random_u32() & htobe32(0x00ff);
+client->transaction_start = time_now;
 
 r = sd_event_add_time(client->event, &client->timeout_resend,
   clock_boottime_or_monotonic(), 0, 0, 
client_timeout_resend,
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 3/3] TODO: Remove Elapsed Time DHCPv6 option as it is done

2014-09-01 Thread Patrik Flykt
---
 TODO | 1 -
 1 file changed, 1 deletion(-)

diff --git a/TODO b/TODO
index 221b39f..4aebcc4 100644
--- a/TODO
+++ b/TODO
@@ -697,7 +697,6 @@ Features:
- implement reconfigure support, see 5.3., 15.11. and 22.20.
- implement information request, see 1.2. and 18.1.5.
- implement support for temporary adressess (IA_TA)
-   - implement elapsed time option
- implement dhcpv6 authentication
- investigate the usefulness of Confirm messages; i.e. are there any
  situations where the link changes without any loss in carrier detection
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH] test-dhcp6-client: Fix option length

2014-08-28 Thread Patrik Flykt
The whole DHCPv6 test message length was incorrectly used as the length
of DHCPv6 options causing the following bad memory access:

$ build/test-dhcp6-client
Assertion 'interface_index >= -1' failed at 
../src/libsystemd-network/sd-dhcp6-client.c:129, function 
sd_dhcp6_client_set_index(). Ignoring.
=
==29135==ERROR: AddressSanitizer: global-buffer-overflow on address 
0x7fe204aa9148 at pc 0x7fe204a5958f bp 0x7fff3e47d470 sp 0x7fff3e47d460
READ of size 1 at 0x7fe204aa9148 thread T0
#0 0x7fe204a5958e in option_parse_hdr 
../src/libsystemd-network/dhcp6-option.c:145
#1 0x7fe204a59884 in dhcp6_option_parse 
../src/libsystemd-network/dhcp6-option.c:165
#2 0x7fe204a4eb9c in test_advertise_option 
../src/libsystemd-network/test-dhcp6-client.c:227
#3 0x7fe204a51c58 in main ../src/libsystemd-network/test-dhcp6-client.c:584
#4 0x7fe2031590df in __libc_start_main (/lib64/libc.so.6+0x200df)
#5 0x7fe204a4cc5b (/home/test/systemd/build/test-dhcp6-client+0x25c5b)

0x7fe204aa9148 is located 2 bytes to the right of global variable 
'msg_advertise' from '../src/libsystemd-network/test-dhcp6-client.c' 
(0x7fe204aa9080) of size 198
0x7fe204aa9148 is located 56 bytes to the left of global variable 'msg_reply' 
from '../src/libsystemd-network/test-dhcp6-client.c' (0x7fe204aa9180) of size 
173
SUMMARY: AddressSanitizer: global-buffer-overflow 
../src/libsystemd-network/dhcp6-option.c:145 option_parse_hdr
---

This seems to be the cause of the bad memory access, please test.

Cheers,

Patrik


 src/libsystemd-network/test-dhcp6-client.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index 96c68e1..259db33 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -207,7 +207,7 @@ static int test_advertise_option(sd_event *e) {
 DHCP6Message *advertise = (DHCP6Message *)msg_advertise;
 uint8_t *optval, *opt = &msg_advertise[sizeof(DHCP6Message)];
 uint16_t optcode;
-size_t optlen, len = sizeof(msg_advertise);
+size_t optlen, len = sizeof(msg_advertise) - sizeof(DHCP6Message);
 be32_t val;
 uint8_t preference = 255;
 struct in6_addr addr;
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 0/8] Basic DHCPv6 client implementation

2014-06-26 Thread Patrik Flykt
On Thu, 2014-06-26 at 13:24 +0300, Patrik Flykt wrote:
> With this patch set it looks like basic DHCPv6 client functionality
> should be covered as Renew and Rebind are now also handled.

Patch set updated according to Zbyszek's comments and pushed.

Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 5/8] sd-dhcp6-lease: Add helper function to compute remaining expiry time

2014-06-26 Thread Patrik Flykt
On Thu, 2014-06-26 at 14:07 +0200, Zbigniew Jędrzejewski-Szmek wrote:
> No comments, the rest looks great, as usual. I think you can push it.

Thanks. And pushed.

Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 5/8] sd-dhcp6-lease: Add helper function to compute remaining expiry time

2014-06-26 Thread Patrik Flykt
On Thu, 2014-06-26 at 13:01 +0200, Zbigniew Jędrzejewski-Szmek wrote:
> > +*expire = 0;
> > +
> > +LIST_FOREACH(addresses, addr, ia->addresses) {
> > +t = be32toh(addr->lifetime_valid);
> > +if (*expire < t)
> > +*expire = t;
> > +}
> > +
> > +t = be32toh(ia->lifetime_t2);
> > +if (t > *expire)
> > +return -EINVAL;
> > +
> > +*expire -= t;
> > +
> > +return 0;
> Please use a temporary variable so that *expire is only written to
> when 0 is returned.

And fixed as well. Any more comments or shall I send an updated version?


Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 4/8] sd-dhcp6-client: Add Option Request Option support

2014-06-26 Thread Patrik Flykt
On Thu, 2014-06-26 at 12:59 +0200, Zbigniew Jędrzejewski-Szmek wrote:
> > +if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
> > +(client->req_opts_len + 1) * sizeof(option)))
> > +return -ENOMEM;
> GREEDY_REALLOC takes the number of *items*, so this will overallocated if I'm
> not mistaken (since commit ca2d3784147).

Fixed not to multiply with sizeof.


Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 1/8] sd-dhcp6-client: return NULL from _unref() like the other sd-* libraries

2014-06-26 Thread Patrik Flykt
In order to keep the refcounting working, a DONT_DESTROY macro similar
to the one in sd-bus has been added also to DHCPv6.
---
 src/libsystemd-network/sd-dhcp6-client.c | 37 +++-
 1 file changed, 17 insertions(+), 20 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index ab4d9e8..928f562 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -95,6 +95,12 @@ const char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = 
{
 
 DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
 
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
+#define _cleanup_dhcp6_client_unref_ _cleanup_(sd_dhcp6_client_unrefp)
+
+#define DHCP6_CLIENT_DONT_DESTROY(client) \
+_cleanup_dhcp6_client_unref_ _unused_ sd_dhcp6_client 
*_dont_destroy_##client = sd_dhcp6_client_ref(client)
+
 static int client_start(sd_dhcp6_client *client, enum DHCP6State state);
 
 int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
@@ -143,14 +149,9 @@ int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, 
sd_dhcp6_lease **ret) {
 return 0;
 }
 
-static sd_dhcp6_client *client_notify(sd_dhcp6_client *client, int event) {
-if (client->cb) {
-client = sd_dhcp6_client_ref(client);
+static void client_notify(sd_dhcp6_client *client, int event) {
+if (client->cb)
 client->cb(client, event, client->userdata);
-client = sd_dhcp6_client_unref(client);
-}
-
-return client;
 }
 
 static int client_reset(sd_dhcp6_client *client) {
@@ -179,14 +180,14 @@ static int client_reset(sd_dhcp6_client *client) {
 return 0;
 }
 
-static sd_dhcp6_client *client_stop(sd_dhcp6_client *client, int error) {
-assert_return(client, NULL);
+static void client_stop(sd_dhcp6_client *client, int error) {
+DHCP6_CLIENT_DONT_DESTROY(client);
 
-client = client_notify(client, error);
-if (client)
-client_reset(client);
+assert(client);
 
-return client;
+client_notify(client, error);
+
+client_reset(client);
 }
 
 static int client_send_message(sd_dhcp6_client *client) {
@@ -633,6 +634,7 @@ static int client_receive_advertise(sd_dhcp6_client *client,
 static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
   void *userdata) {
 sd_dhcp6_client *client = userdata;
+DHCP6_CLIENT_DONT_DESTROY(client);
 _cleanup_free_ DHCP6Message *message;
 int r, buflen, len;
 
@@ -704,9 +706,7 @@ static int client_receive_message(sd_event_source *s, int 
fd, uint32_t revents,
 return 0;
 }
 
-client = client_notify(client, DHCP6_EVENT_IP_ACQUIRE);
-if (!client)
-return 0;
+client_notify(client, DHCP6_EVENT_IP_ACQUIRE);
 }
 
 break;
@@ -935,12 +935,9 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client 
*client) {
 return client;
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
-#define _cleanup_dhcp6_client_free_ _cleanup_(sd_dhcp6_client_unrefp)
-
 int sd_dhcp6_client_new(sd_dhcp6_client **ret)
 {
-_cleanup_dhcp6_client_free_ sd_dhcp6_client *client = NULL;
+_cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL;
 sd_id128_t machine_id;
 int r;
 
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 2/8] sd-icmp6-nd: Add function to stop ongoing ICMPv6 discovery

2014-06-26 Thread Patrik Flykt
In some use cases stopping an ongoing ICMPv6 discovery is more
useful than always unreferencing the whole structure.
---
 src/libsystemd-network/sd-icmp6-nd.c   | 13 +
 src/libsystemd-network/test-icmp6-rs.c |  4 
 src/systemd/sd-icmp6-nd.h  |  1 +
 3 files changed, 18 insertions(+)

diff --git a/src/libsystemd-network/sd-icmp6-nd.c 
b/src/libsystemd-network/sd-icmp6-nd.c
index 10c5e5e..80915c3 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -282,6 +282,19 @@ static int 
icmp6_router_solicitation_timeout(sd_event_source *s, uint64_t usec,
 return 0;
 }
 
+int sd_icmp6_nd_stop(sd_icmp6_nd *nd) {
+assert_return(nd, -EINVAL);
+assert_return(nd->event, -EINVAL);
+
+log_icmp6_nd(client, "Stop ICMPv6");
+
+icmp6_nd_init(nd);
+
+nd->state = ICMP6_NEIGHBOR_DISCOVERY_IDLE;
+
+return 0;
+}
+
 int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd) {
 int r;
 
diff --git a/src/libsystemd-network/test-icmp6-rs.c 
b/src/libsystemd-network/test-icmp6-rs.c
index cd5c476..b81211f 100644
--- a/src/libsystemd-network/test-icmp6-rs.c
+++ b/src/libsystemd-network/test-icmp6-rs.c
@@ -127,6 +127,10 @@ static void test_rs(sd_event *e) {
  time_now + 2 *USEC_PER_SEC, 0,
  test_rs_hangcheck, NULL) >= 0);
 
+assert(sd_icmp6_nd_stop(nd) >= 0);
+assert(sd_icmp6_router_solicitation_start(nd) >= 0);
+assert(sd_icmp6_nd_stop(nd) >= 0);
+
 assert(sd_icmp6_router_solicitation_start(nd) >= 0);
 
 sd_event_loop(e);
diff --git a/src/systemd/sd-icmp6-nd.h b/src/systemd/sd-icmp6-nd.h
index 5e9dc0a..73f91aa 100644
--- a/src/systemd/sd-icmp6-nd.h
+++ b/src/systemd/sd-icmp6-nd.h
@@ -51,6 +51,7 @@ sd_icmp6_nd *sd_icmp6_nd_ref(sd_icmp6_nd *nd);
 sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd);
 int sd_icmp6_nd_new(sd_icmp6_nd **ret);
 
+int sd_icmp6_nd_stop(sd_icmp6_nd *nd);
 int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd);
 
 #endif
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 6/8] sd-dhcp6-client: Implement Renew and Rebind

2014-06-26 Thread Patrik Flykt
Start sending Renew and Rebind DHCPv6 messages when respective timers T1
and T2 expire. Rebind messages do not include a Server ID option and the
Rebind procedure ends when the last IPv6 address valid lifetime expires,
whereafter the client restarts the address acquisition procedure by
Soliciting for available servers.

See RFC 3315, sections 18.1.3. and 18.1.4. for details.
---
 src/libsystemd-network/dhcp6-protocol.h  |  6 +++
 src/libsystemd-network/sd-dhcp6-client.c | 68 +++-
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index 37a8671..e9ae598 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -57,6 +57,10 @@ enum {
 #define DHCP6_REQ_TIMEOUT   1 * USEC_PER_SEC
 #define DHCP6_REQ_MAX_RT120 * USEC_PER_SEC
 #define DHCP6_REQ_MAX_RC10
+#define DHCP6_REN_TIMEOUT   10 * USEC_PER_SEC
+#define DHCP6_REN_MAX_RT600 * USEC_PER_SEC
+#define DHCP6_REB_TIMEOUT   10 * USEC_PER_SEC
+#define DHCP6_REB_MAX_RT600 * USEC_PER_SEC
 
 enum {
 DHCP6_DUID_LLT  = 1,
@@ -71,6 +75,8 @@ enum DHCP6State {
 DHCP6_STATE_SOLICITATION= 2,
 DHCP6_STATE_REQUEST = 3,
 DHCP6_STATE_BOUND   = 4,
+DHCP6_STATE_RENEW   = 5,
+DHCP6_STATE_REBIND  = 6,
 };
 
 enum {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index f6709da..63e852b 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -259,7 +259,12 @@ static int client_send_message(sd_dhcp6_client *client) {
 break;
 
 case DHCP6_STATE_REQUEST:
-message->type = DHCP6_REQUEST;
+case DHCP6_STATE_RENEW:
+
+if (client->state == DHCP6_STATE_REQUEST)
+message->type = DHCP6_REQUEST;
+else
+message->type = DHCP6_RENEW;
 
 r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_SERVERID,
 client->lease->serverid_len,
@@ -273,6 +278,15 @@ static int client_send_message(sd_dhcp6_client *client) {
 
 break;
 
+case DHCP6_STATE_REBIND:
+message->type = DHCP6_REBIND;
+
+r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
+if (r < 0)
+return r;
+
+break;
+
 case DHCP6_STATE_STOPPED:
 case DHCP6_STATE_RS:
 case DHCP6_STATE_BOUND:
@@ -314,6 +328,8 @@ static int client_timeout_t2(sd_event_source *s, uint64_t 
usec,
 
 log_dhcp6_client(client, "Timeout T2");
 
+client_start(client, DHCP6_STATE_REBIND);
+
 return 0;
 }
 
@@ -330,19 +346,30 @@ static int client_timeout_t1(sd_event_source *s, uint64_t 
usec,
 
 log_dhcp6_client(client, "Timeout T1");
 
+client_start(client, DHCP6_STATE_RENEW);
+
 return 0;
 }
 
 static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
 void *userdata) {
 sd_dhcp6_client *client = userdata;
+DHCP6_CLIENT_DONT_DESTROY(client);
+enum DHCP6State state;
 
 assert(s);
 assert(client);
 assert(client->event);
 
+state = client->state;
+
 client_stop(client, DHCP6_EVENT_RESEND_EXPIRE);
 
+/* RFC 3315, section 18.1.4., says that "...the client may choose to
+   use a Solicit message to locate a new DHCP server..." */
+if (state == DHCP6_STATE_REBIND)
+client_start(client, DHCP6_STATE_SOLICITATION);
+
 return 0;
 }
 
@@ -359,6 +386,7 @@ static int client_timeout_resend(sd_event_source *s, 
uint64_t usec,
 usec_t max_retransmit_duration;
 uint8_t max_retransmit_count = 0;
 char time_string[FORMAT_TIMESPAN_MAX];
+uint32_t expire = 0;
 
 assert(s);
 assert(client);
@@ -389,6 +417,37 @@ static int client_timeout_resend(sd_event_source *s, 
uint64_t usec,
 
 break;
 
+case DHCP6_STATE_RENEW:
+init_retransmit_time = DHCP6_REN_TIMEOUT;
+max_retransmit_time = DHCP6_REN_MAX_RT;
+max_retransmit_count = 0;
+
+/* RFC 3315, section 18.1.3. says max retransmit duration will
+   be the remaining time until T2. Instead of setting MRD,
+   wait for T2 to trigger with the same end result */
+max_retransmit_duration = 0;
+
+break;
+
+case DHCP6_STATE_REBIND:
+in

[systemd-devel] [PATCH 7/8] sd-dhcp6-client: Implement Rapid Commit

2014-06-26 Thread Patrik Flykt
Add a Rapid Commit option to Solicit messages and expect a Reply to
be received instead of an Advertise. When receiving a DHCPv6 message
from the server in state Solicit, continue testing whether the
message is a Reply. Ease up the message type checking, it's not fatal
if the message is of a wrong type.

Add helper functions to set/get the rapid commit of a lease. See
RFC 3315, sections 17., 17.1.2., 17.1.4. and 18.1.8.
---
 src/libsystemd-network/dhcp6-lease-internal.h |  4 
 src/libsystemd-network/dhcp6-option.c |  5 +++--
 src/libsystemd-network/sd-dhcp6-client.c  | 30 +++
 src/libsystemd-network/sd-dhcp6-lease.c   | 17 +++
 4 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/src/libsystemd-network/dhcp6-lease-internal.h 
b/src/libsystemd-network/dhcp6-lease-internal.h
index 62c16c5..109e0f4 100644
--- a/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/libsystemd-network/dhcp6-lease-internal.h
@@ -35,6 +35,7 @@ struct sd_dhcp6_lease {
 uint8_t *serverid;
 size_t serverid_len;
 uint8_t preference;
+bool rapid_commit;
 
 DHCP6IA ia;
 
@@ -50,6 +51,9 @@ int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const 
uint8_t *id,
 int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len);
 int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference);
 int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference);
+int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease);
+int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit);
+
 int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
 
 int dhcp6_lease_new(sd_dhcp6_lease **ret);
diff --git a/src/libsystemd-network/dhcp6-option.c 
b/src/libsystemd-network/dhcp6-option.c
index f488832..e9b382c 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -58,13 +58,14 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, 
uint16_t code,
 size_t optlen, const void *optval) {
 int r;
 
-assert_return(optval, -EINVAL);
+assert_return(optval || optlen == 0, -EINVAL);
 
 r = option_append_hdr(buf, buflen, code, optlen);
 if (r < 0)
 return r;
 
-memcpy(*buf, optval, optlen);
+if (optval)
+memcpy(*buf, optval, optlen);
 
 *buf += optlen;
 *buflen -= optlen;
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 63e852b..8f0166f 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -252,6 +252,9 @@ static int client_send_message(sd_dhcp6_client *client) {
 case DHCP6_STATE_SOLICITATION:
 message->type = DHCP6_SOLICIT;
 
+r = dhcp6_option_append(&opt, &optlen,
+DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
+
 r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na);
 if (r < 0)
 return r;
@@ -658,6 +661,13 @@ static int client_parse_message(sd_dhcp6_client *client,
 }
 
 break;
+
+case DHCP6_OPTION_RAPID_COMMIT:
+r = dhcp6_lease_set_rapid_commit(lease);
+if (r < 0)
+return r;
+
+break;
 }
 }
 
@@ -680,9 +690,10 @@ static int client_receive_reply(sd_dhcp6_client *client, 
DHCP6Message *reply,
 {
 int r;
 _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+bool rapid_commit;
 
 if (reply->type != DHCP6_REPLY)
-return -EINVAL;
+return 0;
 
 r = dhcp6_lease_new(&lease);
 if (r < 0)
@@ -692,6 +703,15 @@ static int client_receive_reply(sd_dhcp6_client *client, 
DHCP6Message *reply,
 if (r < 0)
 return r;
 
+if (client->state == DHCP6_STATE_SOLICITATION) {
+r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
+if (r < 0)
+return r;
+
+if (!rapid_commit)
+return 0;
+}
+
 dhcp6_lease_clear_timers(&client->lease->ia);
 
 client->lease = sd_dhcp6_lease_unref(client->lease);
@@ -708,7 +728,7 @@ static int client_receive_advertise(sd_dhcp6_client *client,
 uint8_t pref_advertise = 0, pref_lease = 0;
 
 if (advertise->type != DHCP6_ADVERTISE)
-return -EINVAL;
+return 0;
 
 r = dhcp6_lease_new(&lease);
 if (r < 0)
@@ -793,11 +813,13 @@ static int client_receive_message(sd_event_source *s, int 
fd, uint32_t revents,
 case DHCP6_STATE_SOLICITATION:
 r = client_receive_advertise(client, message, len);
 
-

[systemd-devel] [PATCH 8/8] TODO: Add items for the DHCPv6 implementation

2014-06-26 Thread Patrik Flykt
---
 TODO | 16 
 1 file changed, 16 insertions(+)

diff --git a/TODO b/TODO
index a5f482b..8d8d694 100644
--- a/TODO
+++ b/TODO
@@ -624,6 +624,22 @@ Features:
- export timezone information
- FORCERENEW
 
+* dhcp6:
+   - add functions to set previously stored IPv6 addresses on startup and get
+ them at shutdown; store them in client->ia_na
+   - write more test cases
+   - implement and do duplicate address detection, see rfc 4862, 5.4.
+   - implement reconfigure support, see 5.3., 15.11. and 22.20.
+   - implement information request, see 1.2. and 18.1.5.
+   - implement support for temporary adressess (IA_TA)
+   - implement elapsed time option
+   - implement dhcpv6 authentication
+   - investigate the usefulness of Confirm messages; i.e. are there any
+ situations where the link changes without any loss in carrier detection
+ or interface down
+   - some servers don't do rapid commit without a filled in IA_NA, verify
+ this behavior
+
 External:
 
 * dbus:
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 0/8] Basic DHCPv6 client implementation

2014-06-26 Thread Patrik Flykt

Hi,

With this patch set it looks like basic DHCPv6 client functionality
should be covered as Renew and Rebind are now also handled.

The first patch in the series clears up dhcpv6 unref handling, after
this it works like the rest of the code in systemd.

Patches 02 and 03 add support for stopping ICMP Router Discovery.
This is what networkd actually wants to have done when the link
is not used anymore.

Patch 04 adds support for requesting options, currently none of the
requested options are going to be used, but it's always fun to request
things.

Patches 05 and 06 add the missing pieces for Renew and Rebind support.
Once Rebind state hits its timeout, the procedure is started all over
again with a new Solicitation. It should be discussed if the behavior
described in the RFC is the best possible, in there it is said that
Solicitation is restarted after all addresses have expired. It looks
a bit interesting, as one could at that point have lost all but the
last IPv6 address, and that one will be gone too about the same time
as the Solicitation is sent. Maybe someone with more knowledge will
pop in on some media and share their wisdom with this situation?

Rapid commit is done in patch 07, seems that the DHCP server I'm using
doesn't want to rapid commit anything here, perhaps due to a missing
IPv6 address to request or something.

Last but not least the TODO file lists a few items that are left for
later.


Cheers,

    Patrik



Patrik Flykt (8):
  sd-dhcp6-client: return NULL from _unref() like the other sd-*
libraries
  sd-icmp6-nd: Add function to stop ongoing ICMPv6 discovery
  networkd: Properly stop router solicitation and DHCPv6 client
  sd-dhcp6-client: Add Option Request Option support
  sd-dhcp6-lease: Add helper function to compute remaining expiry time
  sd-dhcp6-client: Implement Renew and Rebind
  sd-dhcp6-client: Implement Rapid Commit
  TODO: Add items for the DHCPv6 implementation

 TODO  |  16 +++
 src/libsystemd-network/dhcp6-lease-internal.h |   5 +
 src/libsystemd-network/dhcp6-option.c |   5 +-
 src/libsystemd-network/dhcp6-protocol.h   |  18 +++
 src/libsystemd-network/sd-dhcp6-client.c  | 192 ++
 src/libsystemd-network/sd-dhcp6-lease.c   |  41 ++
 src/libsystemd-network/sd-icmp6-nd.c  |  13 ++
 src/libsystemd-network/test-dhcp6-client.c|   9 ++
 src/libsystemd-network/test-icmp6-rs.c|   4 +
 src/network/networkd-link.c   |  14 +-
 src/systemd/sd-dhcp6-client.h |   2 +
 src/systemd/sd-icmp6-nd.h |   1 +
 12 files changed, 290 insertions(+), 30 deletions(-)

-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 3/8] networkd: Properly stop router solicitation and DHCPv6 client

2014-06-26 Thread Patrik Flykt
When a link fails or looses carrier, always stop ongoing router
solicitation and any DHCPv6 client that may be running.
---
 src/network/networkd-link.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 44147b2..9296a59 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -236,11 +236,19 @@ static int link_stop_clients(Link *link) {
 }
 
 if (link->network->dhcp6) {
-assert(link->dhcp6_client);
+assert(link->icmp6_router_discovery);
+
+if (link->dhcp6_client) {
+k = sd_dhcp6_client_stop(link->dhcp6_client);
+if (k < 0) {
+log_warning_link(link, "Could not stop DHCPv6 
client: %s", strerror(-r));
+r = k;
+}
+}
 
-k = sd_dhcp6_client_stop(link->dhcp6_client);
+k = sd_icmp6_nd_stop(link->icmp6_router_discovery);
 if (k < 0) {
-log_warning_link(link, "Could not stop DHCPv6 client: 
%s", strerror(-r));
+log_warning_link(link, "Could not stop ICMPv6 router 
discovery: %s", strerror(-r));
 r = k;
 }
 }
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 4/8] sd-dhcp6-client: Add Option Request Option support

2014-06-26 Thread Patrik Flykt
Provide a function to request more options from the DHCPv6 server.
Provide a sensible default set at startup and add test basic test
cases for the intended usage.

Define DNS and NTP related option codes and add comments for the
unassigned codes.
---
 src/libsystemd-network/dhcp6-protocol.h| 12 +++
 src/libsystemd-network/sd-dhcp6-client.c   | 57 ++
 src/libsystemd-network/test-dhcp6-client.c |  9 +
 src/systemd/sd-dhcp6-client.h  |  2 ++
 4 files changed, 80 insertions(+)

diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index 8b3a819..37a8671 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -111,6 +111,18 @@ enum {
 DHCP6_OPTION_INTERFACE_ID   = 18,
 DHCP6_OPTION_RECONF_MSG = 19,
 DHCP6_OPTION_RECONF_ACCEPT  = 20,
+
+DHCP6_OPTION_DNS_SERVERS= 23,  /* RFC 3646 */
+DHCP6_OPTION_DOMAIN_LIST= 24,  /* RFC 3646 */
+
+DHCP6_OPTION_SNTP_SERVERS   = 31,  /* RFC 4075 */
+
+/* option code 35 is unassigned */
+
+DHCP6_OPTION_NTP_SERVER = 56,  /* RFC 5908 */
+
+/* option codes 89-142 are unassigned */
+/* option codes 144-65535 are unassigned */
 };
 
 enum {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 928f562..f6709da 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -51,6 +51,9 @@ struct sd_dhcp6_client {
 be32_t transaction_id;
 struct sd_dhcp6_lease *lease;
 int fd;
+be16_t *req_opts;
+size_t req_opts_allocated;
+size_t req_opts_len;
 sd_event_source *receive_message;
 usec_t retransmit_time;
 uint8_t retransmit_count;
@@ -66,6 +69,12 @@ struct sd_dhcp6_client {
 } _packed_ duid;
 };
 
+static const uint16_t default_req_opts[] = {
+DHCP6_OPTION_DNS_SERVERS,
+DHCP6_OPTION_DOMAIN_LIST,
+DHCP6_OPTION_NTP_SERVER,
+};
+
 const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
 [DHCP6_SOLICIT] = "SOLICIT",
 [DHCP6_ADVERTISE] = "ADVERTISE",
@@ -137,6 +146,37 @@ int sd_dhcp6_client_set_mac(sd_dhcp6_client *client,
 return 0;
 }
 
+int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
+   uint16_t option) {
+size_t t;
+
+assert_return(client, -EINVAL);
+assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
+
+switch(option) {
+case DHCP6_OPTION_DNS_SERVERS:
+case DHCP6_OPTION_DOMAIN_LIST:
+case DHCP6_OPTION_SNTP_SERVERS:
+case DHCP6_OPTION_NTP_SERVER:
+break;
+
+default:
+return -EINVAL;
+}
+
+for (t = 0; t < client->req_opts_len; t++)
+if (client->req_opts[t] == htobe16(option))
+return -EEXIST;
+
+if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
+(client->req_opts_len + 1) * sizeof(option)))
+return -ENOMEM;
+
+client->req_opts[client->req_opts_len++] = htobe16(option);
+
+return 0;
+}
+
 int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
 assert_return(client, -EINVAL);
 assert_return(ret, -EINVAL);
@@ -239,6 +279,12 @@ static int client_send_message(sd_dhcp6_client *client) {
 return -EINVAL;
 }
 
+r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ORO,
+client->req_opts_len * sizeof(be16_t),
+client->req_opts);
+if (r < 0)
+return r;
+
 r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID,
 sizeof(client->duid), &client->duid);
 if (r < 0)
@@ -927,6 +973,7 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client 
*client) {
 
 sd_dhcp6_client_detach_event(client);
 
+free(client->req_opts);
 free(client);
 
 return NULL;
@@ -940,6 +987,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret)
 _cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL;
 sd_id128_t machine_id;
 int r;
+size_t t;
 
 assert_return(ret, -EINVAL);
 
@@ -968,6 +1016,15 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret)
 siphash24(client->duid.id, &machine_id, sizeof(machine_id),
   HASH_KEY.bytes);
 
+client->req_opts_len = ELEMENTSOF(default_req_opts);
+
+client->req_opts = new0(be16_t, client->req_opts_len);
+if (!client->req_opts)
+return -ENOMEM;
+
+for (t = 0; t < client->req_opts_len; t++

[systemd-devel] [PATCH 5/8] sd-dhcp6-lease: Add helper function to compute remaining expiry time

2014-06-26 Thread Patrik Flykt
Create a helper function to compute the remaining time in seconds from
time T2 to the IPv6 address with the longest lifetime. The computed
time is used as the Maximum Retransmission Duration in Rebinding state.
See RFC 3315, section 18.1.4. for details.
---
 src/libsystemd-network/dhcp6-lease-internal.h |  1 +
 src/libsystemd-network/sd-dhcp6-lease.c   | 24 
 2 files changed, 25 insertions(+)

diff --git a/src/libsystemd-network/dhcp6-lease-internal.h 
b/src/libsystemd-network/dhcp6-lease-internal.h
index 295c223..62c16c5 100644
--- a/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/libsystemd-network/dhcp6-lease-internal.h
@@ -42,6 +42,7 @@ struct sd_dhcp6_lease {
 };
 
 int dhcp6_lease_clear_timers(DHCP6IA *ia);
+int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire);
 DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia);
 
 int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id,
diff --git a/src/libsystemd-network/sd-dhcp6-lease.c 
b/src/libsystemd-network/sd-dhcp6-lease.c
index cbda7d8..9426b52 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -33,6 +33,30 @@ int dhcp6_lease_clear_timers(DHCP6IA *ia) {
 return 0;
 }
 
+int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) {
+DHCP6Address *addr;
+uint32_t t;
+
+assert_return(ia, -EINVAL);
+assert_return(expire, -EINVAL);
+
+*expire = 0;
+
+LIST_FOREACH(addresses, addr, ia->addresses) {
+t = be32toh(addr->lifetime_valid);
+if (*expire < t)
+*expire = t;
+}
+
+t = be32toh(ia->lifetime_t2);
+if (t > *expire)
+return -EINVAL;
+
+*expire -= t;
+
+return 0;
+}
+
 DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) {
 DHCP6Address *address;
 
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 02/24] sd-dhcp6-client: Add Router Solicitation and Advertisement support

2014-06-19 Thread Patrik Flykt
On Wed, 2014-06-18 at 16:27 +0200, Zbigniew Jędrzejewski-Szmek wrote:
> > Go ahead and push. It is probably simpler to make further
> > suggestions/comments in terms of patches anyway.
> Agreed. I made some small comments, but the patch set looks great.

Polished a bit more and pushed, enjoy!

Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 02/24] sd-dhcp6-client: Add Router Solicitation and Advertisement support

2014-06-19 Thread Patrik Flykt
On Wed, 2014-06-18 at 16:27 +0200, Zbigniew Jędrzejewski-Szmek wrote:
> > Go ahead and push. It is probably simpler to make further
> > suggestions/comments in terms of patches anyway.
> Agreed. I made some small comments, but the patch set looks great.

Patch set fixed according to your comments except that I skipped the
parentheses in 10/24, as they were gone anyway with 15/24. And I'll make
the test cases more verbose next week or so.

Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 12/24] sd-dhcp6-client: Add DHCPv6 Solicit message creation and sending

2014-06-19 Thread Patrik Flykt
On Wed, 2014-06-18 at 16:25 +0200, Zbigniew Jędrzejewski-Szmek wrote:
> On Wed, Jun 18, 2014 at 07:05:35AM -0700, Filipe Brandenburger wrote:
> > On Wed, Jun 18, 2014 at 6:58 AM, Zbigniew Jędrzejewski-Szmek
> >  wrote:
> > >> +if (client->fd > 0)
> > >> +safe_close(client->fd);
> > >> +client->fd = -1;
> > > client->fd = safe_close(client->fd);
> > >
> > > That's what safe_close is for :)
> > 
> > And shouldn't the check be for client->fd >= 0? Zero is a valid file 
> > descriptor.
> Yeah... but note that safe_close already has the fd >= 0 check, so the
> replacement line replaces the if too.

If I omit the client->fd > 0 check I get the following in the test case:

Assertion 'close_nointr(fd) != -EBADF' failed at src/shared/util.c:205,
function safe_close(). Aborting.


Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 09/24] sd-dhcp6-client: Add DHCPv6 client Solicitation timeout handling

2014-06-19 Thread Patrik Flykt

Hi,

On Wed, 2014-06-18 at 15:50 +0200, Zbigniew Jędrzejewski-Szmek wrote:
> > +if (!client->retransmit_time) {
> > +client->retransmit_time =
> > +
> > client_timeout_compute_random(init_retransmit_time);
> > +} else {
> > +if (max_retransmit_time &&
> > +client->retransmit_time > max_retransmit_time / 2)
> > +client->retransmit_time = 
> > client_timeout_compute_random(max_retransmit_time);
> > +else
> > +client->retransmit_time = 
> > client_timeout_compute_random(client->retransmit_time);

There is a bug in here, this latter one should be += so that the value
actually doubles, thanks for noticing!

> > +}
> Hm, I don't understand why the " / 2" is here. It seems that the
> retransmit time suddenly jumps from max_retransmit_time/2 to
> max_retransmit_time.

The existing client->retransmit_time contains the value calculated for
the current timeout. With the above bug fixed, this value is going to be
doubled with some randomness added. Instead of wasting expensive(?) CPU
cycles on computing the new, properly doubled value with randomness
added and see it thrown away immediately if found to be greater than the
given max_retransmit_time, I tried to be smart and avoid the computation
by checking it against half the value up front. After that the code only
needs to do the proper computation once.

It may have been clearer to multiply the retransmit_time by two instead.
Here I also rely on the compiler being smart enough to replace
multiplications or divisions by two with a bit shift to get it done
quickly enough.


Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 02/24] sd-dhcp6-client: Add Router Solicitation and Advertisement support

2014-06-18 Thread Patrik Flykt
On Mon, 2014-06-16 at 12:39 +0300, Patrik Flykt wrote:
> > 1) usage of struct ether_addr may prevent correct operation on
> > non-ethernet links, like Infiniband or PPP or GRE.  They don't have
> > 6-byte MAC addresses, so anywhere that currently uses a MAC address
> > I'd suggest passing "u8*, u8 len" instead, to allow for non-ethernet
> > links. See ndisc_fill_addr_option() in the kernel...

This one I have left for a bit later as no harm is done if the MAC
address is not set.

> > 2) as I replied to Tom, could we keep RS/RA code together and not
> > tie it with DHCP stuff, since they aren't really related?  DHCP is
> > the consumer of the M/O bits, but if DHCP isn't requested at all by
> > the router via the M/O bits, there's no reason for DHCP to ever be
> > involved in the process.  I think it would be better to keep them
> > fully separate.
> 
> That I can do.

This is now done and the interface looks like the following:

$ cat src/systemd/sd-icmp6-nd.h 
...
enum {
ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE= 0,
ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT = 1,
ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER   = 2,
ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED = 3,
};

typedef struct sd_icmp6_nd sd_icmp6_nd;

typedef void(*sd_icmp6_nd_callback_t)(sd_icmp6_nd *nd, int event,
  void *userdata);

int sd_icmp6_nd_set_callback(sd_icmp6_nd *nd, sd_icmp6_nd_callback_t cb,
 void *userdata);
int sd_icmp6_nd_set_index(sd_icmp6_nd *nd, int interface_index);
int sd_icmp6_nd_set_mac(sd_icmp6_nd *nd, const struct ether_addr *mac_addr);

int sd_icmp6_nd_attach_event(sd_icmp6_nd *nd, sd_event *event, int priority);
int sd_icmp6_nd_detach_event(sd_icmp6_nd *nd);
sd_event *sd_icmp6_nd_get_event(sd_icmp6_nd *nd);

sd_icmp6_nd *sd_icmp6_nd_ref(sd_icmp6_nd *nd);
sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd);
int sd_icmp6_nd_new(sd_icmp6_nd **ret);

int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd);


Did anyone have further comments on this initial patch set? Shall I send
the updated version to the mailing list or how do we want to proceed?

Cheers,

Patrik


___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH 02/24] sd-dhcp6-client: Add Router Solicitation and Advertisement support

2014-06-16 Thread Patrik Flykt

Hi,

On Fri, 2014-06-13 at 12:17 -0500, Dan Williams wrote:

> 1) usage of struct ether_addr may prevent correct operation on
> non-ethernet links, like Infiniband or PPP or GRE.  They don't have
> 6-byte MAC addresses, so anywhere that currently uses a MAC address I'd
> suggest passing "u8*, u8 len" instead, to allow for non-ethernet links.
> See ndisc_fill_addr_option() in the kernel...

Currently the MAC address is used as a fallback method for IAID creation
if the client runs in a container and can't access udev. If set, the MAC
address is also optionally sent in the router solicitation link address
option. Is the link address option mandatory for the links you listed
above?

The router solicitation code uses an IPPROTO_ICMPV6 socket bound to the
interface so that it avoids link-local IPv6 and MAC addresses
altogether.

> 2) as I replied to Tom, could we keep RS/RA code together and not tie it
> with DHCP stuff, since they aren't really related?  DHCP is the consumer
> of the M/O bits, but if DHCP isn't requested at all by the router via
> the M/O bits, there's no reason for DHCP to ever be involved in the
> process.  I think it would be better to keep them fully separate.

That I can do. Besides, such an API can then be extended to supply
networkd with DNS server information from the router advertisments. Once
someone has the time to write such code, that is.


Cheers,

Patrik

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 23/24] sd-dhcp6-client: Add reply sending for test

2014-06-13 Thread Patrik Flykt
Enhance the test case by generating a Reply. With a properly formed
Reply the callback function will be called and the additional
earlier event loop exit can now be removed.
---
 src/libsystemd-network/test-dhcp6-client.c | 45 ++
 1 file changed, 40 insertions(+), 5 deletions(-)

diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index 1acbf95..d1d147a 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -50,7 +50,6 @@ static int test_index = 42;
 static int test_client_message_num;
 static be32_t test_iaid = 0;
 static uint8_t test_duid[14] = { };
-static sd_event *e_solicit;
 
 static int test_client_basic(sd_event *e) {
 sd_dhcp6_client *client;
@@ -172,6 +171,31 @@ static uint8_t msg_advertise[198] = {
 0x53, 0x00, 0x07, 0x00, 0x01, 0x00
 };
 
+static uint8_t msg_reply[173] = {
+0x07, 0xf7, 0x4e, 0x57, 0x00, 0x02, 0x00, 0x0e,
+0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53,
+0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, 0x00, 0x01,
+0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b,
+0xf3, 0x30, 0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d,
+0x00, 0x03, 0x00, 0x4a, 0x0e, 0xcf, 0xa3, 0x7d,
+0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x78,
+0x00, 0x05, 0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8,
+0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3,
+0x09, 0x3c, 0x55, 0xad, 0x00, 0x00, 0x00, 0x96,
+0x00, 0x00, 0x00, 0xb4, 0x00, 0x0d, 0x00, 0x1e,
+0x00, 0x00, 0x41, 0x6c, 0x6c, 0x20, 0x61, 0x64,
+0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20,
+0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x73, 0x73,
+0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x00, 0x17,
+0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad,
+0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x00, 0x18, 0x00, 0x0b, 0x03, 0x6c,
+0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61,
+0x00, 0x00, 0x1f, 0x00, 0x10, 0x20, 0x01, 0x0d,
+0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01
+};
+
 static int test_advertise_option(sd_event *e) {
 _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
 DHCP6Message *advertise = (DHCP6Message *)msg_advertise;
@@ -349,6 +373,20 @@ int dhcp6_network_bind_udp_socket(int index, struct 
in6_addr *local_address) {
 }
 
 static int test_client_send_reply(DHCP6Message *request) {
+DHCP6Message reply;
+
+reply.transaction_id = request->transaction_id;
+reply.type = DHCP6_REPLY;
+
+memcpy(msg_reply, &reply.transaction_id, 4);
+
+memcpy(&msg_reply[26], test_duid, sizeof(test_duid));
+
+memcpy(&msg_reply[44], &test_iaid, sizeof(test_iaid));
+
+assert_se(write(test_dhcp_fd[1], msg_reply, sizeof(msg_reply))
+  == sizeof(msg_reply));
+
 return 0;
 }
 
@@ -422,8 +460,6 @@ static int test_client_verify_request(DHCP6Message 
*request, uint8_t *option,
 assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, <_pref,
   <_valid) == -ENOMSG);
 
-sd_event_exit(e_solicit, 0);
-
 return 0;
 }
 
@@ -524,6 +560,7 @@ static void test_client_solicit_cb(sd_dhcp6_client *client, 
int event,
 sd_event *e = userdata;
 
 assert_se(e);
+assert_se(event == DHCP6_EVENT_IP_ACQUIRE);
 
 if (verbose)
 printf("  got DHCPv6 event %d\n", event);
@@ -553,8 +590,6 @@ static int test_client_solicit(sd_event *e) {
 time_now + 2 * USEC_PER_SEC, 0,
 test_hangcheck, NULL) >= 0);
 
-e_solicit = e;
-
 assert_se(sd_dhcp6_client_start(client) >= 0);
 
 sd_event_loop(e);
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 05/24] sd-dhcp6-client: Initialize DUID

2014-06-13 Thread Patrik Flykt
From: Tom Gundersen 

Initialize DHCP Unique Identifier when creating the client. The
DUID is generated based on the machine-id, which satisfies all the
requirements of what an DUID should be. The DUID type is DUID-EN.

Based on patch by Patrik Flykt.
---
 src/libsystemd-network/sd-dhcp6-client.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index fbf3211..a785fa6 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 
+#include "siphash24.h"
 #include "util.h"
 #include "refcnt.h"
 
@@ -30,6 +31,9 @@
 #include "dhcp6-internal.h"
 #include "icmp6-nd.h"
 
+#define SYSTEMD_PEN 43793
+#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
+
 struct sd_dhcp6_client {
 RefCount n_ref;
 
@@ -41,6 +45,12 @@ struct sd_dhcp6_client {
 icmp6_nd *ra;
 sd_dhcp6_client_cb_t cb;
 void *userdata;
+
+struct duid_en {
+uint16_t type; /* DHCP6_DUID_EN */
+uint32_t pen;
+uint8_t id[8];
+} _packed_ duid;
 };
 
 int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
@@ -251,6 +261,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, 
sd_dhcp6_client_unref);
 int sd_dhcp6_client_new(sd_dhcp6_client **ret)
 {
 _cleanup_dhcp6_client_free_ sd_dhcp6_client *client = NULL;
+sd_id128_t machine_id;
+int r;
 
 assert_return(ret, -EINVAL);
 
@@ -262,6 +274,19 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret)
 
 client->index = -1;
 
+/* initialize DUID */
+client->duid.type = htobe16(DHCP6_DUID_EN);
+client->duid.pen = htobe32(SYSTEMD_PEN);
+
+r = sd_id128_get_machine(&machine_id);
+if (r < 0)
+return r;
+
+/* a bit of snake-oil perhaps, but no need to expose the machine-id
+   directly */
+siphash24(client->duid.id, &machine_id, sizeof(machine_id),
+  HASH_KEY.bytes);
+
 *ret = client;
 client = NULL;
 
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 02/24] sd-dhcp6-client: Add Router Solicitation and Advertisement support

2014-06-13 Thread Patrik Flykt
Provide functions to bind the ICMPv6 socket to the approriate interface
and set multicast sending and receiving according to RFC 3493, section
5.2. and RFC 3542, sections 3. and 3.3. Filter out all ICMPv6 messages
except Router Advertisements for the socket in question according to
RFC 3542, section 3.2.

Send Router Solicitations to the all routers multicast group as
described in RFC 4861, section 6. and act on the received Router
Advertisments according to section 6.3.7.

Implement a similar API for ICMPv6 handling as is done for DHCPv4 and
DHCPv6.
---
 Makefile.am |   8 +-
 src/libsystemd-network/dhcp6-internal.h |  29 +++
 src/libsystemd-network/dhcp6-network.c  | 131 +
 src/libsystemd-network/icmp6-nd.c   | 317 
 src/libsystemd-network/icmp6-nd.h   |  59 ++
 5 files changed, 543 insertions(+), 1 deletion(-)
 create mode 100644 src/libsystemd-network/dhcp6-internal.h
 create mode 100644 src/libsystemd-network/dhcp6-network.c
 create mode 100644 src/libsystemd-network/icmp6-nd.c
 create mode 100644 src/libsystemd-network/icmp6-nd.h

diff --git a/Makefile.am b/Makefile.am
index 4ff9f5a..a8b5b79 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2518,7 +2518,13 @@ libsystemd_network_la_SOURCES = \
src/libsystemd-network/ipv4ll-packet.c \
src/libsystemd-network/ipv4ll-internal.h \
src/libsystemd-network/network-internal.c \
-   src/libsystemd-network/network-internal.h
+   src/libsystemd-network/network-internal.h \
+   src/systemd/sd-dhcp6-client.h \
+   src/libsystemd-network/sd-dhcp6-client.c \
+   src/libsystemd-network/icmp6-nd.h \
+   src/libsystemd-network/icmp6-nd.c \
+   src/libsystemd-network/dhcp6-internal.h \
+   src/libsystemd-network/dhcp6-network.c
 
 libsystemd_network_la_LIBADD = \
libudev-internal.la \
diff --git a/src/libsystemd-network/dhcp6-internal.h 
b/src/libsystemd-network/dhcp6-internal.h
new file mode 100644
index 000..52283d7
--- /dev/null
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -0,0 +1,29 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 Intel Corporation. All rights reserved.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see .
+***/
+
+#include 
+
+#define log_dhcp6_client(p, fmt, ...) log_meta(LOG_DEBUG, __FILE__, __LINE__, 
__func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__)
+
+int dhcp_network_icmp6_bind_router_solicitation(int index);
+int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr 
*ether_addr);
diff --git a/src/libsystemd-network/dhcp6-network.c 
b/src/libsystemd-network/dhcp6-network.c
new file mode 100644
index 000..53ce23d
--- /dev/null
+++ b/src/libsystemd-network/dhcp6-network.c
@@ -0,0 +1,131 @@
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 Intel Corporation. All rights reserved.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see .
+***/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "socket-util.h"
+
+#include "dhcp6-internal.h"
+
+#define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \
+{ { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } } }
+
+#define IN6ADDR_ALL_NODES_MULTICAST_INIT \
+{ { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
+
+int dhcp_network_icmp6_bind_router_solicitation(int index)
+{
+struct icmp6_filter filter = { };
+struct ipv6_mreq mreq = {
+.ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
+.ipv6mr

[systemd-devel] [PATCH 00/24] Initial DHCPv6 client support

2014-06-13 Thread Patrik Flykt
Hi,

This patch set provides initial DHCPv6 client support for
systemd-networkd. It adds support for ICMPv6 Router Solicitation sending
and Router Advertisment receiving and the very basic Solicit, Advertise,
Request and Reply message transactions. Networkd is able to start DHCPv6
negotiation for a link, but doesn't yet do anything with the result.

As only the initial DHCPv6 client side support is implemented, this patch
set omits the following features specified in RFC 3315:
 - Rapid Commit in the Solicit message
 - Information Request, should the router only announce the availability
   of "Other" information
 - Reacquiring of an address, i.e. Renew, Rebind, etc.
 - Temporary adresses, option requesting, elapsed time options
 - DHCPv6 authentication

...and a few more that I for sure have forgotten from this list. The
intent is to have the remaining parts essential for the protocol
functionality to be done as quickly as possible after this patch set.

On startup, the DHCPv6 client implementation sends Router Soliciations
in order to receive Router Advertisments. Only the Managed/Other flags
in the Router Advertisment are currently used, any prefix information
is currently ignored. ICMPv6 and a basic test case is handled by patches
02-04 with the basic DHCPv6 library and test case provided in patches 01
and 08.

Machine-specific DUID and IAID identifiers are created in patches 05-07.
The DUID is used to uniquely identify the machine with the IAID
identifying a particular interface. The DUID is based on the machine ID
and the IAID on interface name from udev or, if run in a container, the
interface MAC address. Credits for implementing this part of the code
goes to Tom.

With identifiers created, the DHCPv6 message (re)transmission is provided
by patch 09 and enhanced in turn with patches 12 and 22 where Solicit
and Reply message handling is implemented, respectively. Support for DHCPv6
option appending and parsing is provided in patches 10 and 15, separated
due to implementation complexity of the IA option and need of DHCPv6 lease
handling code provided by patch 14.

The remaining patches add DHCPv6 message processing one message at a time
with the required state changes and retransmission restarting. A client
test program is provided, it should hopefully prevent possible bugs with
later commits.

As with the DHCPv4 code, also with DHCPv6 it again became evident that
borrowing code 1:1 from ConnMan wasn't really an option. The main loop
syntax and systemd coding style is different enough to prevent any direct
copying. On the positive side the ConnMan implementation exists and works
very well making it possible to thoroughly dissect the DHCPv6 messaging
going back and forth between the client and the server.


Have fun while reviewing,


     Patrik 



Patrik Flykt (22):
  sd-dhcp6-client: Add initial DHCPv6 client files
  sd-dhcp6-client: Add Router Solicitation and Advertisement support
  sd-dhcp6-client: Add initial Router Advertisement test case
  sd-dhcp6-client: Initialize Router Solicitation on startup
  sd-dhcp6-client: Add DHCPv6 IAID functionality
  sd-dhcp6-client: Add basic DHCPv6 test cases
  sd-dhcp6-client: Add DHCPv6 client Solicitation timeout handling
  sd-dhcp6-client: Add basic DHCPv6 option handling
  sd-dhcp6-client: Add functions to bind to DHCPv6 UDP socket
  sd-dhcp6-client: Add DHCPv6 Solicit message creation and sending
  sd-dhcp6-client: Add RA and DHCPv6 Solicit test case
  sd-dhcp6-lease: Add DHCPv6 lease handling
  sd-dhcp6-client: Add IA Address option parsing
  sd-dhcp6-client: Receive and parse Advertise messages
  sd-dhcp6-lease: Add functions for accessing lease and addresses
  sd-dhcp6-client: Add test case for Advertise message parsing
  sd-dhcp6-client: Update start function to take a state
  sd-dhcp6-client: Add Request message sending
  sd-dhcp6-client: Add Advertise sending for test cases
  sd-dhcp6-client: Receive and parse a reply and set T1 and T2 timers
  sd-dhcp6-client: Add reply sending for test
  networkd: Add initial DHCPv6 support

Tom Gundersen (2):
  sd-dhcp6-client: Initialize DUID
  network-internal: split out net_get_name()

 Makefile.am   |   38 +-
 src/libsystemd-network/dhcp6-internal.h   |   79 ++
 src/libsystemd-network/dhcp6-lease-internal.h |   57 ++
 src/libsystemd-network/dhcp6-network.c|  194 +
 src/libsystemd-network/dhcp6-option.c |  314 
 src/libsystemd-network/dhcp6-protocol.h   |  124 +++
 src/libsystemd-network/icmp6-nd.c |  317 
 src/libsystemd-network/icmp6-nd.h |   59 ++
 src/libsystemd-network/network-internal.c |   26 +-
 src/libsystemd-network/network-internal.h |1 +
 src/libsystemd-network/sd-dhcp6-client.c  | 1056 +
 src/libsystemd-network/sd-dhcp6-lease.c   |  178 +
 src/libsystemd-network/test-dhcp6-client.c|  624 +++
 src/libsystem

[systemd-devel] [PATCH 08/24] sd-dhcp6-client: Add basic DHCPv6 test cases

2014-06-13 Thread Patrik Flykt
Add test cases for basic DHCPv6 client handling, e.g. setting
interface index, mac address and attaching event loop.
---
 Makefile.am| 13 -
 src/libsystemd-network/test-dhcp6-client.c | 76 ++
 2 files changed, 88 insertions(+), 1 deletion(-)
 create mode 100644 src/libsystemd-network/test-dhcp6-client.c

diff --git a/Makefile.am b/Makefile.am
index 96ef9ce..d50c23b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2567,6 +2567,7 @@ test_ipv4ll_LDADD = \
libsystemd-shared.la
 
 test_dhcp6_rs_SOURCES = \
+   src/systemd/sd-dhcp6-client.h \
src/libsystemd-network/dhcp6-icmp6.h \
src/libsystemd-network/dhcp6-internal.h \
src/libsystemd-network/test-dhcp6-rs.c
@@ -2576,11 +2577,21 @@ test_dhcp6_rs_LDADD = \
libsystemd-internal.la \
libsystemd-shared.la
 
+test_dhcp6_client_SOURCES = \
+   src/systemd/sd-dhcp6-client.h \
+   src/libsystemd-network/test-dhcp6-client.c
+
+test_dhcp6_client_LDADD = \
+   libsystemd-network.la \
+   libsystemd-internal.la \
+   libsystemd-shared.la
+
 tests += \
test-dhcp-option \
test-dhcp-client \
test-ipv4ll \
-   test-dhcp6-rs
+   test-dhcp6-rs \
+   test-dhcp6-client
 
 # 
--
 if ENABLE_GTK_DOC
diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
new file mode 100644
index 000..b2dc8ba
--- /dev/null
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -0,0 +1,76 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 Intel Corporation. All rights reserved.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see .
+***/
+
+#include 
+#include 
+
+#include "macro.h"
+#include "sd-event.h"
+#include "event-util.h"
+
+#include "sd-dhcp6-client.h"
+#include "dhcp6-protocol.h"
+
+static struct ether_addr mac_addr = {
+.ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
+};
+
+static bool verbose = false;
+
+static int test_client_basic(sd_event *e) {
+sd_dhcp6_client *client;
+
+if (verbose)
+printf("* %s\n", __FUNCTION__);
+
+assert_se(sd_dhcp6_client_new(&client) >= 0);
+assert_se(client);
+
+assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
+
+assert_se(sd_dhcp6_client_set_index(client, 15) == 0);
+assert_se(sd_dhcp6_client_set_index(client, -42) == -EINVAL);
+assert_se(sd_dhcp6_client_set_index(client, -1) == 0);
+assert_se(sd_dhcp6_client_set_index(client, 42) >= 0);
+
+assert_se(sd_dhcp6_client_set_mac(client, &mac_addr) >= 0);
+
+assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0);
+
+assert_se(sd_dhcp6_client_detach_event(client) >= 0);
+assert_se(!sd_dhcp6_client_unref(client));
+
+return 0;
+}
+
+int main(int argc, char *argv[]) {
+_cleanup_event_unref_ sd_event *e;
+
+assert_se(sd_event_new(&e) >= 0);
+
+log_set_max_level(LOG_DEBUG);
+log_parse_environment();
+log_open();
+
+test_client_basic(e);
+
+return 0;
+}
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH 19/24] sd-dhcp6-client: Update start function to take a state

2014-06-13 Thread Patrik Flykt
Updated the start function so that the client state can be conveniently
changed with the previous message resend timers cleared. On initial
startup also create and bind to the UDP socket.
---
 src/libsystemd-network/sd-dhcp6-client.c | 62 +---
 1 file changed, 42 insertions(+), 20 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 52f4e10..98835f7 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -97,6 +97,8 @@ const char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
 
+static int client_start(sd_dhcp6_client *client, enum DHCP6State state);
+
 int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
  sd_dhcp6_client_cb_t cb, void *userdata)
 {
@@ -164,7 +166,7 @@ static int client_initialize(sd_dhcp6_client *client)
 safe_close(client->fd);
 client->fd = -1;
 
-client->transaction_id = random_u32() & 0x00ff;
+client->transaction_id = 0;
 
 client->ia_na.timeout_t1 =
 sd_event_source_unref(client->ia_na.timeout_t1);
@@ -614,36 +616,53 @@ static int client_receive_message(sd_event_source *s, int 
fd, uint32_t revents,
 return 0;
 }
 
-static int client_start(sd_dhcp6_client *client)
+static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
 {
 int r;
 
 assert_return(client, -EINVAL);
 assert_return(client->event, -EINVAL);
 assert_return(client->index > 0, -EINVAL);
+assert_return(client->state != state, -EINVAL);
 
-r = client_ensure_iaid(client);
-if (r < 0)
-return r;
+client->timeout_resend_expire =
+sd_event_source_unref(client->timeout_resend_expire);
+client->timeout_resend = sd_event_source_unref(client->timeout_resend);
+client->retransmit_time = 0;
+client->retransmit_count = 0;
 
-r = dhcp6_network_bind_udp_socket(client->index, NULL);
-if (r < 0)
-return r;
+switch (state) {
+case DHCP6_STATE_STOPPED:
+case DHCP6_STATE_RS:
+case DHCP6_STATE_SOLICITATION:
 
-client->fd = r;
+r = client_ensure_iaid(client);
+if (r < 0)
+return r;
 
-r = sd_event_add_io(client->event, &client->receive_message,
-client->fd, EPOLLIN, client_receive_message,
-client);
-if (r < 0)
-return r;
+r = dhcp6_network_bind_udp_socket(client->index, NULL);
+if (r < 0)
+return r;
 
-r = sd_event_source_set_priority(client->receive_message,
- client->event_priority);
-if (r < 0)
-return r;
+client->fd = r;
 
-client->state = DHCP6_STATE_SOLICITATION;
+r = sd_event_add_io(client->event, &client->receive_message,
+client->fd, EPOLLIN, 
client_receive_message,
+client);
+if (r < 0)
+return r;
+
+r = sd_event_source_set_priority(client->receive_message,
+ client->event_priority);
+if (r < 0)
+return r;
+
+client->state = DHCP6_STATE_SOLICITATION;
+
+break;
+}
+
+client->transaction_id = random_u32() & htobe32(0x00ff);
 
 r = sd_event_add_time(client->event, &client->timeout_resend,
   CLOCK_MONOTONIC, 0, 0, client_timeout_resend,
@@ -680,7 +699,10 @@ static void dhcp6_receive_router_advertisment(icmp6_nd 
*nd, int event,
 
 case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
 case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
-r = client_start(client);
+if (!IN_SET(client->state, DHCP6_STATE_STOPPED, 
DHCP6_STATE_RS))
+break;
+
+r = client_start(client, DHCP6_STATE_SOLICITATION);
 if (r < 0)
 client_stop(client, r);
 break;
-- 
1.9.1

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


  1   2   3   >