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 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 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 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


[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 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 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 

[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 errno.h
 
+#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

[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 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) {
 

[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,
uint32_t 

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

2015-05-04 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


[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_prefixlen,
+ 

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


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
 patrik.fl...@linux.intel.com 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 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


[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 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


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 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 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, lt_pref,
-   lt_valid) = 0);
+sd_dhcp6_lease_reset_address_iter(lease);
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
+ lt_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, lt_pref,
-  lt_valid) == -ENOMSG);
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
+ lt_valid) == -ENOMSG);
 
-assert_se(sd_dhcp6_lease_get_first_address(lease, addr, lt_pref,
-   lt_valid) = 0);
+sd_dhcp6_lease_reset_address_iter(lease);
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
+ lt_valid) = 0);
 assert_se(!memcmp(addr, msg_advertise[42], sizeof(addr)));
-assert_se(sd_dhcp6_lease_get_next_address(lease, addr, lt_pref,
-  lt_valid) == -ENOMSG);
-assert_se(sd_dhcp6_lease_get_next_address(lease, addr, lt_pref,
-  lt_valid) == -ENOMSG);
-assert_se(sd_dhcp6_lease_get_first_address(lease, addr, lt_pref,
-   lt_valid) = 0);
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
+ lt_valid) == -ENOMSG);
+sd_dhcp6_lease_reset_address_iter(lease);
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
+ lt_valid) = 0);
 assert_se(!memcmp(addr, msg_advertise[42], sizeof(addr)));
-assert_se(sd_dhcp6_lease_get_next_address(lease, addr, lt_pref,
-  lt_valid) == -ENOMSG);
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
+ lt_valid) == -ENOMSG);
 
 

[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 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 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


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] 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


[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 netinet/icmp6.h
+#include netinet/ip6.h
 #include string.h
 #include stdbool.h
 #include netinet/in.h
+#include sys/ioctl.h
 
 #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 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 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)
+return r;
+
+while 

[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, lt_pref,
-   lt_valid) = 0);
+assert_se(sd_dhcp6_lease_reset_address_iter(lease) = 0);
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
+  lt_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, lt_pref,
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
   lt_valid) == -ENOMSG);
 
-assert_se(sd_dhcp6_lease_get_first_address(lease, addr, lt_pref,
-   lt_valid) = 0);
+assert_se(sd_dhcp6_lease_reset_address_iter(lease) = 0);
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
+  lt_valid) = 0);
 assert_se(!memcmp(addr, msg_advertise[42], sizeof(addr)));
-assert_se(sd_dhcp6_lease_get_next_address(lease, addr, lt_pref,
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
   lt_valid) == -ENOMSG);
-assert_se(sd_dhcp6_lease_get_next_address(lease, addr, lt_pref,
-  lt_valid) == -ENOMSG);
-assert_se(sd_dhcp6_lease_get_first_address(lease, addr, lt_pref,
-   lt_valid) = 0);
+assert_se(sd_dhcp6_lease_reset_address_iter(lease) = 0);
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
+  lt_valid) = 0);
 assert_se(!memcmp(addr, msg_advertise[42], sizeof(addr)));
-assert_se(sd_dhcp6_lease_get_next_address(lease, addr, lt_pref,
+assert_se(sd_dhcp6_lease_get_address(lease, addr, lt_pref,
   lt_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 *option,
 

[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 *prefix;
+
+assert_return(nd, -EINVAL);

[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 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 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, 0xd0, 

[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


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 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


[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);
+assert_se(found_clientid  

[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 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 server id,
+   

[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 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 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 http://www.gnu.org/licenses/.
+***/
+
+#include netinet/ether.h
+#include linux/if.h
+
+#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 

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

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] 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 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 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 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 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, lt_pref,
lt_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] test-dhcp6-client: Fix option length

2014-08-29 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


[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


[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:
+init_retransmit_time = 

[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 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


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


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 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 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 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 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
  zbys...@in.waw.pl 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 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 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-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 03/24] sd-dhcp6-client: Add initial Router Advertisement test case

2014-06-13 Thread Patrik Flykt
Feed a Router Advertisement to the code and expect proper events
each time. The sending part is ignored, as all of it is static code
in the real dhcp_network_icmp6_send_rs() function.
---
 Makefile.am|  13 ++-
 src/libsystemd-network/test-dhcp6-rs.c | 155 +
 2 files changed, 167 insertions(+), 1 deletion(-)
 create mode 100644 src/libsystemd-network/test-dhcp6-rs.c

diff --git a/Makefile.am b/Makefile.am
index a8b5b79..96ef9ce 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2566,10 +2566,21 @@ test_ipv4ll_LDADD = \
libsystemd-internal.la \
libsystemd-shared.la
 
+test_dhcp6_rs_SOURCES = \
+   src/libsystemd-network/dhcp6-icmp6.h \
+   src/libsystemd-network/dhcp6-internal.h \
+   src/libsystemd-network/test-dhcp6-rs.c
+
+test_dhcp6_rs_LDADD = \
+   libsystemd-network.la \
+   libsystemd-internal.la \
+   libsystemd-shared.la
+
 tests += \
test-dhcp-option \
test-dhcp-client \
-   test-ipv4ll
+   test-ipv4ll \
+   test-dhcp6-rs
 
 # 
--
 if ENABLE_GTK_DOC
diff --git a/src/libsystemd-network/test-dhcp6-rs.c 
b/src/libsystemd-network/test-dhcp6-rs.c
new file mode 100644
index 000..c59dd32
--- /dev/null
+++ b/src/libsystemd-network/test-dhcp6-rs.c
@@ -0,0 +1,155 @@
+/*-*- 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 http://www.gnu.org/licenses/.
+***/
+
+#include netinet/icmp6.h
+
+#include socket-util.h
+
+#include dhcp6-internal.h
+#include icmp6-nd.h
+
+static struct ether_addr mac_addr = {
+.ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
+};
+
+static bool verbose = false;
+static sd_event_source *test_hangcheck;
+static int test_fd[2];
+
+static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
+ void *userdata) {
+assert(false);
+
+return 0;
+}
+
+int dhcp_network_icmp6_bind_router_solicitation(int index) {
+assert(index == 42);
+
+if (socketpair(AF_UNIX, SOCK_DGRAM, 0, test_fd)  0)
+return -errno;
+
+return test_fd[0];
+}
+
+static int send_ra(uint8_t flags) {
+uint8_t advertisement[] = {
+0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x04, 0x40, 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,
+0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
+0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
+};
+
+advertisement[5] = flags;
+
+assert(write(test_fd[1], advertisement, sizeof(advertisement)) ==
+   sizeof(advertisement));
+
+if (verbose)
+printf(  sent RA with flag 0x%02x\n, flags);
+
+return 0;
+}
+
+int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr 
*ether_addr) {
+return send_ra(0);
+}
+
+static void test_rs_done(icmp6_nd *nd, int event, void *userdata) {
+sd_event *e = userdata;
+static int idx = 0;
+struct {
+uint8_t flag;
+int event;
+} flag_event[] = {
+{ 0, ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE },
+{ ND_RA_FLAG_OTHER, ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER },
+{ ND_RA_FLAG_MANAGED, ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED }
+};
+assert(nd);
+
+assert(event == flag_event[idx].event);
+idx++;
+
+if (verbose)
+printf(  got event %d\n, event);
+
+if (idx  3)
+send_ra(flag_event[idx].flag);
+else
+sd_event_exit(e, 0);
+}
+
+static 

[systemd-devel] [PATCH 04/24] sd-dhcp6-client: Initialize Router Solicitation on startup

2014-06-13 Thread Patrik Flykt
Try DHCPv6 if router solicitation times out as a link without routers
may use DHCPv6 according to RFC 4862 section 5.5.2.
---
 src/libsystemd-network/sd-dhcp6-client.c | 70 +++-
 src/systemd/sd-dhcp6-client.h|  1 +
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 5063d4a..fbf3211 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -27,6 +27,8 @@
 
 #include sd-dhcp6-client.h
 #include dhcp6-protocol.h
+#include dhcp6-internal.h
+#include icmp6-nd.h
 
 struct sd_dhcp6_client {
 RefCount n_ref;
@@ -36,6 +38,7 @@ struct sd_dhcp6_client {
 int event_priority;
 int index;
 struct ether_addr mac_addr;
+icmp6_nd *ra;
 sd_dhcp6_client_cb_t cb;
 void *userdata;
 };
@@ -103,6 +106,30 @@ static sd_dhcp6_client *client_stop(sd_dhcp6_client 
*client, int error) {
 return client;
 }
 
+static void dhcp6_receive_router_advertisment(icmp6_nd *nd, int event,
+  void *userdata)
+{
+sd_dhcp6_client *client = userdata;
+
+if (event  0) {
+log_dhcp6_client(client, Router Advertisment failed with 
+ %d %s, event, strerror(-event));
+client_notify(client, event);
+return;
+}
+
+switch (event) {
+case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
+case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
+client_stop(client, DHCP6_EVENT_NO_STATEFUL_CONFIGURATION);
+return;
+
+case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
+case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
+break;
+}
+}
+
 int sd_dhcp6_client_stop(sd_dhcp6_client *client)
 {
 client_stop(client, DHCP6_EVENT_STOP);
@@ -112,13 +139,50 @@ int sd_dhcp6_client_stop(sd_dhcp6_client *client)
 
 int sd_dhcp6_client_start(sd_dhcp6_client *client)
 {
-int r = 0;
+_cleanup_icmp6_nd_free_ icmp6_nd *nd = NULL;
+int r;
+struct ether_addr *mac_addr = NULL;
+struct ether_addr unset = { };
 
 assert_return(client, -EINVAL);
 assert_return(client-event, -EINVAL);
 assert_return(client-index  0, -EINVAL);
 
-return r;
+r = icmp6_nd_new(nd);
+if (r  0)
+return r;
+
+r = icmp6_nd_attach_event(nd, client-event, client-event_priority);
+if (r  0)
+return r;
+
+r = icmp6_nd_set_index(nd, client-index);
+if (r  0)
+return r;
+
+if (memcmp(client-mac_addr, unset, sizeof(unset)))
+mac_addr = client-mac_addr;
+
+r = icmp6_nd_set_mac(nd, mac_addr);
+if (r  0)
+return r;
+
+r = icmp6_nd_set_callback(nd, dhcp6_receive_router_advertisment,
+  client);
+if (r  0)
+return r;
+
+r = icmp6_router_solicitation_start(nd);
+if (r  0)
+return r;
+
+client-ra = icmp6_nd_unref(client-ra);
+client-ra = nd;
+nd = NULL;
+
+client-state = DHCP6_STATE_RS;
+
+return 0;
 }
 
 int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
@@ -171,6 +235,8 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client 
*client) {
 
 sd_dhcp6_client_detach_event(client);
 
+client-ra = icmp6_nd_unref(client-ra);
+
 free(client);
 
 return NULL;
diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
index 4965011..c64ad16 100644
--- a/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/sd-dhcp6-client.h
@@ -28,6 +28,7 @@
 
 enum {
 DHCP6_EVENT_STOP= 0,
+DHCP6_EVENT_NO_STATEFUL_CONFIGURATION   = 10,
 };
 
 typedef struct sd_dhcp6_client sd_dhcp6_client;
-- 
1.9.1

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


[systemd-devel] [PATCH 14/24] sd-dhcp6-lease: Add DHCPv6 lease handling

2014-06-13 Thread Patrik Flykt
Create a structure describing a DHCPv6 lease. Add internal functions
for creating a new lease and accessing the server ID, preference and
IAID. Provide functions for clearing addresses and associated timers.

External users are initially given only the capabilities of
referencing and unreferencing the lease structure.
---
 Makefile.am   |   5 +-
 src/libsystemd-network/dhcp6-lease-internal.h |  55 ++
 src/libsystemd-network/sd-dhcp6-lease.c   | 139 ++
 src/systemd/sd-dhcp6-lease.h  |  31 ++
 4 files changed, 229 insertions(+), 1 deletion(-)
 create mode 100644 src/libsystemd-network/dhcp6-lease-internal.h
 create mode 100644 src/libsystemd-network/sd-dhcp6-lease.c
 create mode 100644 src/systemd/sd-dhcp6-lease.h

diff --git a/Makefile.am b/Makefile.am
index 87ac728..3c2d73a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2520,12 +2520,15 @@ libsystemd_network_la_SOURCES = \
src/libsystemd-network/network-internal.c \
src/libsystemd-network/network-internal.h \
src/systemd/sd-dhcp6-client.h \
+   src/systemd/sd-dhcp6-lease.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 \
-   src/libsystemd-network/dhcp6-option.c
+   src/libsystemd-network/dhcp6-option.c \
+   src/libsystemd-network/dhcp6-lease-internal.h \
+   src/libsystemd-network/sd-dhcp6-lease.c
 
 libsystemd_network_la_LIBADD = \
libudev-internal.la \
diff --git a/src/libsystemd-network/dhcp6-lease-internal.h 
b/src/libsystemd-network/dhcp6-lease-internal.h
new file mode 100644
index 000..f4f1488
--- /dev/null
+++ b/src/libsystemd-network/dhcp6-lease-internal.h
@@ -0,0 +1,55 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 Tom Gundersen
+  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 http://www.gnu.org/licenses/.
+***/
+
+#include stdint.h
+
+#include refcnt.h
+
+#include sd-dhcp6-lease.h
+#include dhcp6-internal.h
+
+struct sd_dhcp6_lease {
+RefCount n_ref;
+
+uint8_t *serverid;
+size_t serverid_len;
+uint8_t preference;
+
+DHCP6IA ia;
+};
+
+int dhcp6_lease_clear_timers(DHCP6IA *ia);
+DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia);
+
+int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id,
+ size_t len);
+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_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
+
+int dhcp6_lease_new(sd_dhcp6_lease **ret);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref);
+#define _cleanup_dhcp6_lease_free_ _cleanup_(sd_dhcp6_lease_unrefp)
diff --git a/src/libsystemd-network/sd-dhcp6-lease.c 
b/src/libsystemd-network/sd-dhcp6-lease.c
new file mode 100644
index 000..41d6a5a
--- /dev/null
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -0,0 +1,139 @@
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 Tom Gundersen
+  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 http://www.gnu.org/licenses/.
+***/
+
+#include errno.h
+
+#include util.h
+
+#include dhcp6-lease-internal.h
+
+int dhcp6_lease_clear_timers(DHCP6IA *ia) {
+assert_return(ia, -EINVAL);
+
+ia-timeout_t1 = sd_event_source_unref(ia-timeout_t1);
+ia-timeout_t2 = 

[systemd-devel] [PATCH 11/24] sd-dhcp6-client: Add functions to bind to DHCPv6 UDP socket

2014-06-13 Thread Patrik Flykt
Add a function that creates a UDP socket bound to the given interface
and optionally to an IPv6 address. Add another function that will
send the DHCPv6 UDP packet to its destination.

Using IPV6_PKTINFO in setsockopt to bind the IPv6 socket to an
interface is documented in section 4. of RFC 3542, Advanced Sockets
Application Program Interface (API) for IPv6

Add a define for DHCPv6 Relay Agents and Servers multicast address as
its not available elsewhere.
---
 src/libsystemd-network/dhcp6-internal.h |  4 +++
 src/libsystemd-network/dhcp6-network.c  | 63 +
 src/libsystemd-network/dhcp6-protocol.h |  4 +++
 3 files changed, 71 insertions(+)

diff --git a/src/libsystemd-network/dhcp6-internal.h 
b/src/libsystemd-network/dhcp6-internal.h
index 30b624d..7a491fb 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -65,3 +65,7 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, 
uint16_t code,
 int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia);
 int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
+
+int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address);
+int dhcp6_network_send_udp_socket(int s, struct in6_addr *address,
+  const void *packet, size_t len);
diff --git a/src/libsystemd-network/dhcp6-network.c 
b/src/libsystemd-network/dhcp6-network.c
index 53ce23d..fe56c10 100644
--- a/src/libsystemd-network/dhcp6-network.c
+++ b/src/libsystemd-network/dhcp6-network.c
@@ -31,6 +31,7 @@
 #include socket-util.h
 
 #include dhcp6-internal.h
+#include dhcp6-protocol.h
 
 #define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \
 { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
@@ -129,3 +130,65 @@ int dhcp_network_icmp6_send_router_solicitation(int s, 
const struct ether_addr *
 
 return 0;
 }
+
+int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
+struct in6_pktinfo pktinfo = {
+.ipi6_ifindex = index,
+};
+union sockaddr_union src = {
+.in6.sin6_family = AF_INET6,
+.in6.sin6_port = htobe16(DHCP6_PORT_CLIENT),
+.in6.sin6_addr = IN6ADDR_ANY_INIT,
+};
+_cleanup_close_ int s = -1;
+int r, off = 0, on = 1;
+
+if (local_address)
+memcpy(src.in6.sin6_addr, local_address,
+   sizeof(src.in6.sin6_addr));
+
+s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
+   IPPROTO_UDP);
+if (s  0)
+return -errno;
+
+r = setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, pktinfo,
+   sizeof(pktinfo));
+if (r  0)
+return -errno;
+
+r = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, on, sizeof(on));
+if (r  0)
+return -errno;
+
+r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, off, 
sizeof(off));
+if (r  0)
+return -errno;
+
+r = bind(s, src.sa, sizeof(src.in6));
+if (r  0)
+return -errno;
+
+r = s;
+s = -1;
+return r;
+}
+
+int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
+  const void *packet, size_t len) {
+union sockaddr_union dest = {
+.in6.sin6_family = AF_INET6,
+.in6.sin6_port = htobe16(DHCP6_PORT_SERVER),
+};
+int r;
+
+assert(server_address);
+
+memcpy(dest.in6.sin6_addr, server_address, 
sizeof(dest.in6.sin6_addr));
+
+r = sendto(s, packet, len, 0, dest.sa, sizeof(dest.in6));
+if (r  0)
+return -errno;
+
+return 0;
+}
diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index 442418d..de100d7 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -36,6 +36,10 @@ struct DHCP6Message {
 
 typedef struct DHCP6Message DHCP6Message;
 
+#define IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT \
+{ { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02 } } }
+
 enum {
 DHCP6_PORT_SERVER   = 547,
 DHCP6_PORT_CLIENT   = 546,
-- 
1.9.1

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


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

2014-06-13 Thread Patrik Flykt
Add the core of DHCPv6 client message retransmission and upper bound
timer and message count handling according to RFC 3315 Secions 7.1.2
and 14. Omit the DHCPv6 initial delay; for now it is assumed that
systemd-networkd will provide decent startup randomization that will
desynchronize the clients.

When reinitializing the client, clear all timers.
---
 src/libsystemd-network/dhcp6-protocol.h  |   5 ++
 src/libsystemd-network/sd-dhcp6-client.c | 136 +++
 src/systemd/sd-dhcp6-client.h|   2 +
 3 files changed, 143 insertions(+)

diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index afe1413..442418d 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -41,6 +41,10 @@ enum {
 DHCP6_PORT_CLIENT   = 546,
 };
 
+#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
+
 enum {
 DHCP6_DUID_LLT  = 1,
 DHCP6_DUID_EN   = 2,
@@ -51,6 +55,7 @@ enum {
 enum DHCP6State {
 DHCP6_STATE_STOPPED = 0,
 DHCP6_STATE_RS  = 1,
+DHCP6_STATE_SOLICITATION= 2,
 };
 
 enum {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index f61442b..048b4ea 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -48,6 +48,10 @@ struct sd_dhcp6_client {
 struct ether_addr mac_addr;
 icmp6_nd *ra;
 DHCP6IA ia_na;
+usec_t retransmit_time;
+uint8_t retransmit_count;
+sd_event_source *timeout_resend;
+sd_event_source *timeout_resend_expire;
 sd_dhcp6_client_cb_t cb;
 void *userdata;
 
@@ -111,6 +115,12 @@ static int client_initialize(sd_dhcp6_client *client)
 client-ia_na.timeout_t2 =
 sd_event_source_unref(client-ia_na.timeout_t2);
 
+client-retransmit_time = 0;
+client-retransmit_count = 0;
+client-timeout_resend = sd_event_source_unref(client-timeout_resend);
+client-timeout_resend_expire =
+sd_event_source_unref(client-timeout_resend_expire);
+
 client-state = DHCP6_STATE_STOPPED;
 
 return 0;
@@ -126,6 +136,119 @@ static sd_dhcp6_client *client_stop(sd_dhcp6_client 
*client, int error) {
 return client;
 }
 
+static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
+void *userdata) {
+sd_dhcp6_client *client = userdata;
+
+assert(s);
+assert(client);
+assert(client-event);
+
+client_stop(client, DHCP6_EVENT_RESEND_EXPIRE);
+
+return 0;
+}
+
+static usec_t client_timeout_compute_random(usec_t val) {
+return val - val / 10 +
+(random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC;
+}
+
+static int client_timeout_resend(sd_event_source *s, uint64_t usec,
+ void *userdata) {
+int r = 0;
+sd_dhcp6_client *client = userdata;
+usec_t time_now, init_retransmit_time, max_retransmit_time;
+usec_t max_retransmit_duration;
+uint8_t max_retransmit_count;
+char time_string[FORMAT_TIMESPAN_MAX];
+
+assert(s);
+assert(client);
+assert(client-event);
+
+client-timeout_resend = sd_event_source_unref(client-timeout_resend);
+
+switch (client-state) {
+case DHCP6_STATE_SOLICITATION:
+init_retransmit_time = DHCP6_SOL_TIMEOUT;
+max_retransmit_time = DHCP6_SOL_MAX_RT;
+max_retransmit_count = 0;
+max_retransmit_duration = 0;
+
+break;
+
+case DHCP6_STATE_STOPPED:
+case DHCP6_STATE_RS:
+return 0;
+}
+
+if (max_retransmit_count 
+client-retransmit_count = max_retransmit_count) {
+client_stop(client, DHCP6_EVENT_RETRANS_MAX);
+return 0;
+}
+
+r = sd_event_now(client-event, CLOCK_MONOTONIC, time_now);
+if (r  0)
+goto error;
+
+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);
+}
+
+log_dhcp6_client(client, Next 

[systemd-devel] [PATCH 10/24] sd-dhcp6-client: Add basic DHCPv6 option handling

2014-06-13 Thread Patrik Flykt
Add option appending and parsing. DHCPv6 options are not aligned, thus
the option handling code must be able to handle options starting at
any byte boundary.

Add a test case for the basic option handling.
---
 Makefile.am|   4 +-
 src/libsystemd-network/dhcp6-internal.h|   6 ++
 src/libsystemd-network/dhcp6-option.c  | 150 +
 src/libsystemd-network/test-dhcp6-client.c |  70 ++
 4 files changed, 229 insertions(+), 1 deletion(-)
 create mode 100644 src/libsystemd-network/dhcp6-option.c

diff --git a/Makefile.am b/Makefile.am
index d50c23b..f6340dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2524,7 +2524,8 @@ libsystemd_network_la_SOURCES = \
src/libsystemd-network/icmp6-nd.h \
src/libsystemd-network/icmp6-nd.c \
src/libsystemd-network/dhcp6-internal.h \
-   src/libsystemd-network/dhcp6-network.c
+   src/libsystemd-network/dhcp6-network.c \
+   src/libsystemd-network/dhcp6-option.c
 
 libsystemd_network_la_LIBADD = \
libudev-internal.la \
@@ -2579,6 +2580,7 @@ test_dhcp6_rs_LDADD = \
 
 test_dhcp6_client_SOURCES = \
src/systemd/sd-dhcp6-client.h \
+   src/libsystemd-network/dhcp6-internal.h \
src/libsystemd-network/test-dhcp6-client.c
 
 test_dhcp6_client_LDADD = \
diff --git a/src/libsystemd-network/dhcp6-internal.h 
b/src/libsystemd-network/dhcp6-internal.h
index 1cdb912..30b624d 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -59,3 +59,9 @@ typedef struct DHCP6IA DHCP6IA;
 
 int dhcp_network_icmp6_bind_router_solicitation(int index);
 int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr 
*ether_addr);
+
+int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
+size_t optlen, const void *optval);
+int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia);
+int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
+   size_t *optlen, uint8_t **optvalue);
diff --git a/src/libsystemd-network/dhcp6-option.c 
b/src/libsystemd-network/dhcp6-option.c
new file mode 100644
index 000..cc4d261
--- /dev/null
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -0,0 +1,150 @@
+/*-*- 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 http://www.gnu.org/licenses/.
+***/
+
+#include netinet/in.h
+#include errno.h
+#include string.h
+
+#include sparse-endian.h
+#include util.h
+
+#include dhcp6-internal.h
+#include dhcp6-protocol.h
+
+#define DHCP6_OPTION_HDR_LEN4
+#define DHCP6_OPTION_IA_NA_LEN  12
+#define DHCP6_OPTION_IA_TA_LEN  4
+#define DHCP6_OPTION_IAADDR_LEN 24
+
+static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode,
+ size_t optlen) {
+assert_return(buf, -EINVAL);
+assert_return(*buf, -EINVAL);
+assert_return(buflen, -EINVAL);
+
+if (optlen  0x || *buflen  optlen + DHCP6_OPTION_HDR_LEN)
+return -ENOBUFS;
+
+(*buf)[0] = optcode  8;
+(*buf)[1] = optcode  0xff;
+(*buf)[2] = optlen  8;
+(*buf)[3] = optlen  0xff;
+
+*buf += DHCP6_OPTION_HDR_LEN;
+*buflen -= DHCP6_OPTION_HDR_LEN;
+
+return 0;
+}
+
+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);
+
+r = option_append_hdr(buf, buflen, code, optlen);
+if (r  0)
+return r;
+
+memcpy(*buf, optval, optlen);
+
+*buf += optlen;
+*buflen -= optlen;
+
+return 0;
+}
+
+int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
+uint16_t len;
+uint8_t *ia_hdr;
+size_t ia_buflen, ia_addrlen = 0;
+DHCP6Address *addr;
+int r;
+
+assert_return(buf  *buf  buflen  ia, -EINVAL);
+
+switch (ia-type) {
+case DHCP6_OPTION_IA_NA:
+len = DHCP6_OPTION_IA_NA_LEN;
+break;
+
+case DHCP6_OPTION_IA_TA:
+len = 

[systemd-devel] [PATCH 16/24] sd-dhcp6-client: Receive and parse Advertise messages

2014-06-13 Thread Patrik Flykt
When receiving DHCPv6 messages, discard the ones that are not meant
for DHCPv6 clients and verify the transaction id. Once that is done,
process the Advertise message and select the Advertise with the
highest preference.

Create a separate function for lease information parsing so that it
can be reused in other parts of the protocol. Verify both DUID and
IAID in the received message and store other necessary information
with the lease structure.
---
 src/libsystemd-network/dhcp6-internal.h  |   2 +
 src/libsystemd-network/dhcp6-protocol.h  |   6 +
 src/libsystemd-network/sd-dhcp6-client.c | 219 ++-
 3 files changed, 225 insertions(+), 2 deletions(-)

diff --git a/src/libsystemd-network/dhcp6-internal.h 
b/src/libsystemd-network/dhcp6-internal.h
index ec1d82a..94e3a5d 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -75,3 +75,5 @@ int dhcp6_network_send_udp_socket(int s, struct in6_addr 
*address,
 
 const char *dhcp6_message_type_to_string(int s) _const_;
 int dhcp6_message_type_from_string(const char *s) _pure_;
+const char *dhcp6_message_status_to_string(int s) _const_;
+int dhcp6_message_status_from_string(const char *s) _pure_;
diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index de100d7..e8df509 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -21,6 +21,9 @@
   along with systemd; If not, see http://www.gnu.org/licenses/.
 ***/
 
+#include netinet/ip6.h
+#include netinet/udp.h
+
 #include macro.h
 #include sparse-endian.h
 
@@ -36,6 +39,9 @@ struct DHCP6Message {
 
 typedef struct DHCP6Message DHCP6Message;
 
+#define DHCP6_MIN_OPTIONS_SIZE \
+1280 - sizeof(struct ip6_hdr) - sizeof(struct udphdr)
+
 #define IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT \
 { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
   0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02 } } }
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index bdd9177..a18698c 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -21,6 +21,7 @@
 
 #include errno.h
 #include string.h
+#include sys/ioctl.h
 
 #include udev.h
 #include udev-util.h
@@ -34,6 +35,7 @@
 #include dhcp6-protocol.h
 #include dhcp6-internal.h
 #include icmp6-nd.h
+#include dhcp6-lease-internal.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)
@@ -49,6 +51,7 @@ struct sd_dhcp6_client {
 icmp6_nd *ra;
 DHCP6IA ia_na;
 be32_t transaction_id;
+struct sd_dhcp6_lease *lease;
 int fd;
 sd_event_source *receive_message;
 usec_t retransmit_time;
@@ -83,6 +86,17 @@ const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int);
 
+const char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
+[DHCP6_STATUS_SUCCESS] = Success,
+[DHCP6_STATUS_UNSPEC_FAIL] = Unspecified failure,
+[DHCP6_STATUS_NO_ADDRS_AVAIL] = No addresses available,
+[DHCP6_STATUS_NO_BINDING] = Binding unavailable,
+[DHCP6_STATUS_NOT_ON_LINK] = Not on link,
+[DHCP6_STATUS_USE_MULTICAST] = Use multicast,
+};
+
+DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
+
 int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
  sd_dhcp6_client_cb_t cb, void *userdata)
 {
@@ -381,9 +395,210 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
 return 0;
 }
 
+static int client_parse_message(sd_dhcp6_client *client,
+DHCP6Message *message, size_t len,
+sd_dhcp6_lease *lease) {
+int r;
+uint8_t *optval, *option = (uint8_t *)(message + 1), *id = NULL;
+uint16_t optcode, status;
+size_t optlen, id_len;
+bool clientid = false;
+be32_t iaid_lease;
+
+while ((r = dhcp6_option_parse(option, len, optcode, optlen,
+   optval)) = 0) {
+switch (optcode) {
+case DHCP6_OPTION_CLIENTID:
+if (clientid) {
+log_dhcp6_client(client, %s contains multiple 
clientids,
+ 
dhcp6_message_type_to_string(message-type));
+return -EINVAL;
+}
+
+if (optlen != sizeof(client-duid) ||
+memcmp(client-duid, optval, optlen) != 0) {
+log_dhcp6_client(client, %s DUID does not 
match,
+ 
dhcp6_message_type_to_string(message-type));
+
+return -EINVAL;
+}
+  

[systemd-devel] [PATCH 20/24] sd-dhcp6-client: Add Request message sending

2014-06-13 Thread Patrik Flykt
As described in RFC 3315, Section 17.1.2, a client has to wait until the
first timeout has elapsed before it is allowed to request IPv6 addresses
from the DHCPv6 server. This is indicated by a non-NULL lease and a
non-zero resend count. Should the Advertisement contain a preference
value of 255 or be received after the first timeout, IPv6 address
requesting is started immediately.

In response to these events, create a Request message and set up proper
resend timers to send the message to the server.
---
 src/libsystemd-network/dhcp6-protocol.h  |  4 +++
 src/libsystemd-network/sd-dhcp6-client.c | 47 ++--
 2 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index e8df509..a3a8be1 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -54,6 +54,9 @@ enum {
 #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
+#define DHCP6_REQ_TIMEOUT   1 * USEC_PER_SEC
+#define DHCP6_REQ_MAX_RT120 * USEC_PER_SEC
+#define DHCP6_REQ_MAX_RC10
 
 enum {
 DHCP6_DUID_LLT  = 1,
@@ -66,6 +69,7 @@ enum DHCP6State {
 DHCP6_STATE_STOPPED = 0,
 DHCP6_STATE_RS  = 1,
 DHCP6_STATE_SOLICITATION= 2,
+DHCP6_STATE_REQUEST = 3,
 };
 
 enum {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 98835f7..312c84c 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -216,12 +216,22 @@ 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_CLIENTID,
-sizeof(client-duid), client-duid);
+r = dhcp6_option_append_ia(opt, optlen, client-ia_na);
 if (r  0)
 return r;
 
-r = dhcp6_option_append_ia(opt, optlen, client-ia_na);
+break;
+
+case DHCP6_STATE_REQUEST:
+message-type = DHCP6_REQUEST;
+
+r = dhcp6_option_append(opt, optlen, DHCP6_OPTION_SERVERID,
+client-lease-serverid_len,
+client-lease-serverid);
+if (r  0)
+return r;
+
+r = dhcp6_option_append_ia(opt, optlen, client-lease-ia);
 if (r  0)
 return r;
 
@@ -232,6 +242,11 @@ static int client_send_message(sd_dhcp6_client *client) {
 return -EINVAL;
 }
 
+r = dhcp6_option_append(opt, optlen, DHCP6_OPTION_CLIENTID,
+sizeof(client-duid), client-duid);
+if (r  0)
+return r;
+
 r = dhcp6_network_send_udp_socket(client-fd, all_servers, message,
   len - optlen);
 if (r  0)
@@ -278,6 +293,12 @@ static int client_timeout_resend(sd_event_source *s, 
uint64_t usec,
 
 switch (client-state) {
 case DHCP6_STATE_SOLICITATION:
+
+if (client-retransmit_count  client-lease) {
+client_start(client, DHCP6_STATE_REQUEST);
+return 0;
+}
+
 init_retransmit_time = DHCP6_SOL_TIMEOUT;
 max_retransmit_time = DHCP6_SOL_MAX_RT;
 max_retransmit_count = 0;
@@ -285,6 +306,14 @@ static int client_timeout_resend(sd_event_source *s, 
uint64_t usec,
 
 break;
 
+case DHCP6_STATE_REQUEST:
+init_retransmit_time = DHCP6_REQ_TIMEOUT;
+max_retransmit_time = DHCP6_REQ_MAX_RT;
+max_retransmit_count = DHCP6_REQ_MAX_RC;
+max_retransmit_duration = 0;
+
+break;
+
 case DHCP6_STATE_STOPPED:
 case DHCP6_STATE_RS:
 return 0;
@@ -541,6 +570,9 @@ static int client_receive_advertise(sd_dhcp6_client *client,
 r = 0;
 }
 
+if (pref_advertise == 255 || client-retransmit_count  1)
+r = DHCP6_STATE_REQUEST;
+
 return r;
 }
 
@@ -601,8 +633,12 @@ 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);
 
+if (r == DHCP6_STATE_REQUEST)
+client_start(client, r);
+
 break;
 
+case 

[systemd-devel] [PATCH 13/24] sd-dhcp6-client: Add RA and DHCPv6 Solicit test case

2014-06-13 Thread Patrik Flykt
Copy Router Advertisement functions and data from the previous
test case and verify the created Solicit message. The test will
take some non-trivial time to run due to the DHCPv6 initial delay.
---
 Makefile.am|   1 +
 src/libsystemd-network/test-dhcp6-client.c | 181 +
 2 files changed, 182 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index f6340dc..87ac728 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2580,6 +2580,7 @@ test_dhcp6_rs_LDADD = \
 
 test_dhcp6_client_SOURCES = \
src/systemd/sd-dhcp6-client.h \
+   src/libsystemd-network/dhcp6-icmp6.h \
src/libsystemd-network/dhcp6-internal.h \
src/libsystemd-network/test-dhcp6-client.c
 
diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index b52f407..e8cc07d 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -21,7 +21,12 @@
 
 #include stdbool.h
 #include stdio.h
+#include sys/types.h
+#include sys/socket.h
+#include unistd.h
+#include netinet/icmp6.h
 
+#include socket-util.h
 #include macro.h
 #include sd-event.h
 #include event-util.h
@@ -36,6 +41,12 @@ static struct ether_addr mac_addr = {
 
 static bool verbose = false;
 
+static sd_event_source *hangcheck;
+static int test_rs_fd[2];
+static int test_dhcp_fd[2];
+static int test_index = 42;
+static sd_event *e_solicit;
+
 static int test_client_basic(sd_event *e) {
 sd_dhcp6_client *client;
 
@@ -128,6 +139,175 @@ static int test_option(sd_event *e) {
 return 0;
 }
 
+static int test_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {
+assert_not_reached(Test case should have completed in 2 seconds);
+
+return 0;
+}
+
+int dhcp_network_icmp6_bind_router_solicitation(int index) {
+assert(index == 42);
+
+if (socketpair(AF_UNIX, SOCK_DGRAM, 0, test_rs_fd)  0)
+return -errno;
+
+return test_rs_fd[0];
+}
+
+static int send_ra(uint8_t flags) {
+uint8_t advertisement[] = {
+0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x03, 0x04, 0x40, 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,
+0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
+0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
+};
+
+advertisement[5] = flags;
+
+assert(write(test_rs_fd[1], advertisement, sizeof(advertisement)) ==
+   sizeof(advertisement));
+
+if (verbose)
+printf(  sent RA with flag 0x%02x\n, flags);
+
+return 0;
+}
+
+int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr 
*ether_addr) {
+return send_ra(ND_RA_FLAG_MANAGED);
+}
+
+int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
+assert_se(index == test_index);
+
+if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_dhcp_fd)  0)
+return -errno;
+
+return test_dhcp_fd[0];
+}
+
+static int verify_solicit(DHCP6Message *solicit, uint8_t *option, size_t len) {
+uint8_t *optval;
+uint16_t optcode;
+size_t optlen;
+bool found_clientid = false, found_iana = false;
+int r;
+
+assert_se(solicit-type == DHCP6_SOLICIT);
+
+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 == 14);
+
+break;
+
+case DHCP6_OPTION_IA_NA:
+assert_se(!found_iana);
+found_iana = true;
+
+assert_se(optlen == 12);
+
+break;
+}
+}
+
+assert_se(r == -ENOMSG);
+assert_se(found_clientid  found_iana);
+
+sd_event_exit(e_solicit, 0);
+
+return 0;
+}
+
+int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
+  const void *packet, size_t len) {
+struct in6_addr mcast =
+IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
+DHCP6Message *message;
+   

[systemd-devel] [PATCH 21/24] sd-dhcp6-client: Add Advertise sending for test cases

2014-06-13 Thread Patrik Flykt
Enhance the test case by replying with an Advertise message to the
client. Copy the transaction id, IAID and DUID from the Solicit
message. Verify the Request message created by the DHCPv6 client
implementation and move the main loop exit to the end of the Request
message verification.

Provide local variants for detect_vm(), detect_container() and
detect_virtualization() defined in virt.h. This makes the DHCPv6
library believe it is run in a container and does not try to request
interface information from udev for the non-existing interface index
used by the test case code.
---
 src/libsystemd-network/test-dhcp6-client.c | 134 +++--
 1 file changed, 129 insertions(+), 5 deletions(-)

diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index afc19b6..1acbf95 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -30,6 +30,7 @@
 #include macro.h
 #include sd-event.h
 #include event-util.h
+#include virt.h
 
 #include sd-dhcp6-client.h
 #include dhcp6-protocol.h
@@ -46,6 +47,9 @@ static sd_event_source *hangcheck;
 static int test_rs_fd[2];
 static int test_dhcp_fd[2];
 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) {
@@ -282,6 +286,18 @@ static int test_hangcheck(sd_event_source *s, uint64_t 
usec, void *userdata) {
 return 0;
 }
 
+int detect_vm(const char **id) {
+return 1;
+}
+
+int detect_container(const char **id) {
+return 1;
+}
+
+int detect_virtualization(const char **id) {
+return 1;
+}
+
 int dhcp_network_icmp6_bind_router_solicitation(int index) {
 assert(index == 42);
 
@@ -332,7 +348,106 @@ int dhcp6_network_bind_udp_socket(int index, struct 
in6_addr *local_address) {
 return test_dhcp_fd[0];
 }
 
-static int verify_solicit(DHCP6Message *solicit, uint8_t *option, size_t len) {
+static int test_client_send_reply(DHCP6Message *request) {
+return 0;
+}
+
+static int test_client_verify_request(DHCP6Message *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_iana = false, found_serverid = 
false;
+int r;
+struct in6_addr addr;
+be32_t val;
+uint32_t lt_pref, lt_valid;
+
+assert_se(request-type == DHCP6_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(!memcmp(optval, test_duid,
+  sizeof(test_duid)));
+
+break;
+
+case DHCP6_OPTION_IA_NA:
+assert_se(!found_iana);
+found_iana = true;
+
+
+assert_se(optlen == 40);
+assert_se(!memcmp(optval, test_iaid, 
sizeof(test_iaid)));
+
+val = htobe32(80);
+assert_se(!memcmp(optval + 4, val, sizeof(val)));
+
+val = htobe32(120);
+assert_se(!memcmp(optval + 8, val, sizeof(val)));
+
+assert_se(!dhcp6_option_parse_ia(optval, optlen,
+ optcode, lease-ia));
+
+break;
+
+case DHCP6_OPTION_SERVERID:
+assert_se(!found_serverid);
+found_serverid = true;
+
+assert_se(optlen == 14);
+assert_se(!memcmp(msg_advertise[179], optval, 
optlen));
+
+break;
+}
+}
+
+assert_se(r == -ENOMSG);
+assert_se(found_clientid  found_iana  found_serverid);
+
+assert_se(sd_dhcp6_lease_get_first_address(lease, addr, lt_pref,
+   lt_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, lt_pref,
+  lt_valid) == -ENOMSG);
+
+sd_event_exit(e_solicit, 0);
+
+return 0;
+}
+
+static int test_client_send_advertise(DHCP6Message *solicit)
+{
+DHCP6Message advertise;
+
+advertise.transaction_id = solicit-transaction_id;
+

[systemd-devel] [PATCH 18/24] sd-dhcp6-client: Add test case for Advertise message parsing

2014-06-13 Thread Patrik Flykt
Add a basic test case excersising once more option parsing function
in addition to lease handling. Check that the address iteration
functions return the correct IPv6 address and lifetimes and that
only one address is returned. Also verify that the server ID and
preference values are read correctly.
---
 src/libsystemd-network/test-dhcp6-client.c | 138 +
 1 file changed, 138 insertions(+)

diff --git a/src/libsystemd-network/test-dhcp6-client.c 
b/src/libsystemd-network/test-dhcp6-client.c
index e8cc07d..afc19b6 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -34,6 +34,7 @@
 #include sd-dhcp6-client.h
 #include dhcp6-protocol.h
 #include dhcp6-internal.h
+#include dhcp6-lease-internal.h
 
 static struct ether_addr mac_addr = {
 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
@@ -139,6 +140,142 @@ static int test_option(sd_event *e) {
 return 0;
 }
 
+static uint8_t msg_advertise[198] = {
+0x02, 0x0f, 0xb4, 0xe5, 0x00, 0x01, 0x00, 0x0e,
+0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b, 0xf3, 0x30,
+0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x03,
+0x00, 0x5e, 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, 0x32, 0x00, 0x00,
+0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x28,
+0x65, 0x73, 0x29, 0x20, 0x72, 0x65, 0x6e, 0x65,
+0x77, 0x65, 0x64, 0x2e, 0x20, 0x47, 0x72, 0x65,
+0x65, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66,
+0x72, 0x6f, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e,
+0x65, 0x74, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68,
+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, 0x00,
+0x02, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x19,
+0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d,
+0x53, 0x00, 0x07, 0x00, 0x01, 0x00
+};
+
+static int test_advertise_option(sd_event *e) {
+_cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+DHCP6Message *advertise = (DHCP6Message *)msg_advertise;
+uint8_t *optval, *opt = msg_advertise[sizeof(DHCP6Message)];
+uint16_t optcode;
+size_t optlen, len = sizeof(msg_advertise);
+be32_t val;
+uint8_t preference = 255;
+struct in6_addr addr;
+uint32_t lt_pref, lt_valid;
+int r;
+bool opt_clientid = false;
+
+if (verbose)
+printf(* %s\n, __FUNCTION__);
+
+assert_se(dhcp6_lease_new(lease) = 0);
+
+assert_se(advertise-type == DHCP6_ADVERTISE);
+assert_se((be32toh(advertise-transaction_id)  0x00ff) ==
+  0x0fb4e5);
+
+while ((r = dhcp6_option_parse(opt, len, optcode, optlen,
+   optval)) = 0) {
+
+switch(optcode) {
+case DHCP6_OPTION_CLIENTID:
+assert_se(optlen == 14);
+
+opt_clientid = true;
+break;
+
+case DHCP6_OPTION_IA_NA:
+assert_se(optlen == 94);
+assert_se(!memcmp(optval, msg_advertise[26], optlen));
+
+val = htobe32(0x0ecfa37d);
+assert_se(!memcmp(optval, val, sizeof(val)));
+
+val = htobe32(80);
+assert_se(!memcmp(optval + 4, val, sizeof(val)));
+
+val = htobe32(120);
+assert_se(!memcmp(optval + 8, val, sizeof(val)));
+
+assert_se(dhcp6_option_parse_ia(optval, optlen,
+optcode,
+lease-ia) = 0);
+
+break;
+
+case DHCP6_OPTION_SERVERID:
+assert_se(optlen == 14);
+assert_se(!memcmp(optval, msg_advertise[179], 
optlen));
+
+assert_se(dhcp6_lease_set_serverid(lease, optval,
+   optlen) = 0);
+break;
+
+case DHCP6_OPTION_PREFERENCE:
+assert_se(optlen == 1);
+assert_se(!*optval);
+
+assert_se(dhcp6_lease_set_preference(lease,
+ *optval) = 0);
+   

[systemd-devel] [PATCH 01/24] sd-dhcp6-client: Add initial DHCPv6 client files

2014-06-13 Thread Patrik Flykt
Add initial structure definition and functions for setting index, MAC
address, callback and event loop. Define protocol values and states.
---
 src/libsystemd-network/dhcp6-protocol.h  | 104 
 src/libsystemd-network/sd-dhcp6-client.c | 203 +++
 src/systemd/sd-dhcp6-client.h|  54 
 3 files changed, 361 insertions(+)
 create mode 100644 src/libsystemd-network/dhcp6-protocol.h
 create mode 100644 src/libsystemd-network/sd-dhcp6-client.c
 create mode 100644 src/systemd/sd-dhcp6-client.h

diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
new file mode 100644
index 000..afe1413
--- /dev/null
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -0,0 +1,104 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2013 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 http://www.gnu.org/licenses/.
+***/
+
+#include macro.h
+#include sparse-endian.h
+
+struct DHCP6Message {
+union {
+struct {
+uint8_t type;
+uint8_t _pad[3];
+} _packed_;
+be32_t transaction_id;
+};
+} _packed_;
+
+typedef struct DHCP6Message DHCP6Message;
+
+enum {
+DHCP6_PORT_SERVER   = 547,
+DHCP6_PORT_CLIENT   = 546,
+};
+
+enum {
+DHCP6_DUID_LLT  = 1,
+DHCP6_DUID_EN   = 2,
+DHCP6_DUID_LL   = 3,
+DHCP6_DUID_UUID = 4,
+};
+
+enum DHCP6State {
+DHCP6_STATE_STOPPED = 0,
+DHCP6_STATE_RS  = 1,
+};
+
+enum {
+DHCP6_SOLICIT   = 1,
+DHCP6_ADVERTISE = 2,
+DHCP6_REQUEST   = 3,
+DHCP6_CONFIRM   = 4,
+DHCP6_RENEW = 5,
+DHCP6_REBIND= 6,
+DHCP6_REPLY = 7,
+DHCP6_RELEASE   = 8,
+DHCP6_DECLINE   = 9,
+DHCP6_RECONFIGURE   = 10,
+DHCP6_INFORMATION_REQUEST   = 11,
+DHCP6_RELAY_FORW= 12,
+DHCP6_RELAY_REPL= 13,
+_DHCP6_MESSAGE_MAX  = 14,
+};
+
+enum {
+DHCP6_OPTION_CLIENTID   = 1,
+DHCP6_OPTION_SERVERID   = 2,
+DHCP6_OPTION_IA_NA  = 3,
+DHCP6_OPTION_IA_TA  = 4,
+DHCP6_OPTION_IAADDR = 5,
+DHCP6_OPTION_ORO= 6,
+DHCP6_OPTION_PREFERENCE = 7,
+DHCP6_OPTION_ELAPSED_TIME   = 8,
+DHCP6_OPTION_RELAY_MSG  = 9,
+/* option code 10 is unassigned */
+DHCP6_OPTION_AUTH   = 11,
+DHCP6_OPTION_UNICAST= 12,
+DHCP6_OPTION_STATUS_CODE= 13,
+DHCP6_OPTION_RAPID_COMMIT   = 14,
+DHCP6_OPTION_USER_CLASS = 15,
+DHCP6_OPTION_VENDOR_CLASS   = 16,
+DHCP6_OPTION_VENDOR_OPTS= 17,
+DHCP6_OPTION_INTERFACE_ID   = 18,
+DHCP6_OPTION_RECONF_MSG = 19,
+DHCP6_OPTION_RECONF_ACCEPT  = 20,
+};
+
+enum {
+DHCP6_STATUS_SUCCESS= 0,
+DHCP6_STATUS_UNSPEC_FAIL= 1,
+DHCP6_STATUS_NO_ADDRS_AVAIL = 2,
+DHCP6_STATUS_NO_BINDING = 3,
+DHCP6_STATUS_NOT_ON_LINK= 4,
+DHCP6_STATUS_USE_MULTICAST  = 5,
+_DHCP6_STATUS_MAX   = 6,
+};
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
new file mode 100644
index 000..5063d4a
--- /dev/null
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -0,0 +1,203 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This 

[systemd-devel] [PATCH 22/24] sd-dhcp6-client: Receive and parse a reply and set T1 and T2 timers

2014-06-13 Thread Patrik Flykt
Receive and parse a Reply from the server. Set up T1 and T2 timers and
notify the library user of an acquired DHCPv6 lease.
---
 src/libsystemd-network/dhcp6-protocol.h  |   1 +
 src/libsystemd-network/sd-dhcp6-client.c | 145 +++
 src/systemd/sd-dhcp6-client.h|   1 +
 3 files changed, 147 insertions(+)

diff --git a/src/libsystemd-network/dhcp6-protocol.h 
b/src/libsystemd-network/dhcp6-protocol.h
index a3a8be1..95d37f7 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -70,6 +70,7 @@ enum DHCP6State {
 DHCP6_STATE_RS  = 1,
 DHCP6_STATE_SOLICITATION= 2,
 DHCP6_STATE_REQUEST = 3,
+DHCP6_STATE_BOUND   = 4,
 };
 
 enum {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c 
b/src/libsystemd-network/sd-dhcp6-client.c
index 312c84c..15e5ea0 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -239,6 +239,7 @@ static int client_send_message(sd_dhcp6_client *client) {
 
 case DHCP6_STATE_STOPPED:
 case DHCP6_STATE_RS:
+case DHCP6_STATE_BOUND:
 return -EINVAL;
 }
 
@@ -258,6 +259,38 @@ static int client_send_message(sd_dhcp6_client *client) {
 return 0;
 }
 
+static int client_timeout_t2(sd_event_source *s, uint64_t usec,
+ void *userdata) {
+sd_dhcp6_client *client = userdata;
+
+assert_return(s, -EINVAL);
+assert_return(client, -EINVAL);
+assert_return(client-lease, -EINVAL);
+
+client-lease-ia.timeout_t2 =
+sd_event_source_unref(client-lease-ia.timeout_t2);
+
+log_dhcp6_client(client, Timeout T2);
+
+return 0;
+}
+
+static int client_timeout_t1(sd_event_source *s, uint64_t usec,
+ void *userdata) {
+sd_dhcp6_client *client = userdata;
+
+assert_return(s, -EINVAL);
+assert_return(client, -EINVAL);
+assert_return(client-lease, -EINVAL);
+
+client-lease-ia.timeout_t1 =
+sd_event_source_unref(client-lease-ia.timeout_t1);
+
+log_dhcp6_client(client, Timeout T1);
+
+return 0;
+}
+
 static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
 void *userdata) {
 sd_dhcp6_client *client = userdata;
@@ -316,6 +349,7 @@ static int client_timeout_resend(sd_event_source *s, 
uint64_t usec,
 
 case DHCP6_STATE_STOPPED:
 case DHCP6_STATE_RS:
+case DHCP6_STATE_BOUND:
 return 0;
 }
 
@@ -541,6 +575,32 @@ static int client_parse_message(sd_dhcp6_client *client,
 return r;
 }
 
+static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,
+size_t len)
+{
+int r;
+_cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+
+if (reply-type != DHCP6_REPLY)
+return -EINVAL;
+
+r = dhcp6_lease_new(lease);
+if (r  0)
+return -ENOMEM;
+
+r = client_parse_message(client, reply, len, lease);
+if (r  0)
+return r;
+
+dhcp6_lease_clear_timers(client-lease-ia);
+
+client-lease = sd_dhcp6_lease_unref(client-lease);
+client-lease = lease;
+lease = NULL;
+
+return DHCP6_STATE_BOUND;
+}
+
 static int client_receive_advertise(sd_dhcp6_client *client,
 DHCP6Message *advertise, size_t len) {
 int r;
@@ -639,6 +699,29 @@ static int client_receive_message(sd_event_source *s, int 
fd, uint32_t revents,
 break;
 
 case DHCP6_STATE_REQUEST:
+r = client_receive_reply(client, message, len);
+if (r  0)
+return 0;
+
+if (r == DHCP6_STATE_BOUND) {
+
+r = client_start(client, DHCP6_STATE_BOUND);
+if (r  0) {
+client_stop(client, r);
+return 0;
+}
+
+client = client_notify(client, DHCP6_EVENT_IP_ACQUIRE);
+if (!client)
+return 0;
+}
+
+break;
+
+case DHCP6_STATE_BOUND:
+
+break;
+
 case DHCP6_STATE_STOPPED:
 case DHCP6_STATE_RS:
 return 0;
@@ -655,6 +738,8 @@ static int client_receive_message(sd_event_source *s, int 
fd, uint32_t revents,
 static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
 {
 int r;
+usec_t timeout, time_now;
+char time_string[FORMAT_TIMESPAN_MAX];
 
 assert_return(client, -EINVAL);
 assert_return(client-event, -EINVAL);
@@ -698,9 +783,69 @@ static 

[systemd-devel] [PATCH 15/24] sd-dhcp6-client: Add IA Address option parsing

2014-06-13 Thread Patrik Flykt
Add functionality to parse DHCPv6 Identity Association for
Non-temporary (IA_NA) and Temporary Addresses (IA_TA) options.
Both of them contain one or more IA Address (IAADDR) options
and optinally a status code option. Only the IA_NA option
contains lease lifetimes. See RFC 3315, sections 22.4., 22.5.,
22.6., 22.13. and appendix B. for details. If the lease
timeouts are not set, use the ones recommended for servers in
section 22.4.

Factor out common code in the form of an option header parsing
helper function.
---
 src/libsystemd-network/dhcp6-internal.h |   2 +
 src/libsystemd-network/dhcp6-option.c   | 182 ++--
 2 files changed, 175 insertions(+), 9 deletions(-)

diff --git a/src/libsystemd-network/dhcp6-internal.h 
b/src/libsystemd-network/dhcp6-internal.h
index 31f5bd2..ec1d82a 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -66,6 +66,8 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, 
uint16_t code,
 int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia);
 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_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 cc4d261..55fd872 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -129,22 +129,186 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t 
*buflen, DHCP6IA *ia) {
 return 0;
 }
 
+
+static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *opt,
+size_t *optlen) {
+uint16_t len;
+
+assert_return(buf, -EINVAL);
+assert_return(opt, -EINVAL);
+assert_return(optlen, -EINVAL);
+
+if (*buflen  4)
+return -ENOMSG;
+
+len = (*buf)[2]  8 | (*buf)[3];
+
+if (len  *buflen)
+return -ENOMSG;
+
+*opt = (*buf)[0]  8 | (*buf)[1];
+*optlen = len;
+
+(*buf) += 4;
+(*buflen) -= 4;
+
+return 0;
+}
+
 int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue) {
-assert_return(buf  buflen  optcode  optlen  optvalue, -EINVAL);
+int r;
 
-if (*buflen == 0)
-return -ENOMSG;
+assert_return(buf  buflen  optcode  optlen  optvalue, -EINVAL);
 
-*optcode = (*buf)[0]  8 | (*buf)[1];
-*optlen = (*buf)[2]  8 | (*buf)[3];
+r = option_parse_hdr(buf, buflen, optcode, optlen);
+if (r  0)
+return r;
 
-if (*optlen  *buflen - 4)
+if (*optlen  *buflen)
 return -ENOBUFS;
 
-*optvalue = (*buf)[4];
-*buflen -= (*optlen + 4);
-(*buf) += (*optlen + 4);
+*optvalue = *buf;
+*buflen -= *optlen;
+(*buf) += *optlen;
 
 return 0;
 }
+
+int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
+  DHCP6IA *ia) {
+int r;
+uint16_t opt, status;
+size_t optlen;
+size_t iaaddr_offset;
+DHCP6Address *addr;
+uint32_t lt_t1, lt_t2, lt_valid, lt_pref, lt_min = ~0;
+
+assert_return(ia, -EINVAL);
+assert_return(!ia-addresses, -EINVAL);
+
+switch (iatype) {
+case DHCP6_OPTION_IA_NA:
+
+if (*buflen  DHCP6_OPTION_IA_NA_LEN + DHCP6_OPTION_HDR_LEN +
+DHCP6_OPTION_IAADDR_LEN) {
+r = -ENOBUFS;
+goto error;
+}
+
+iaaddr_offset = DHCP6_OPTION_IA_NA_LEN;
+memcpy(ia-id, *buf, iaaddr_offset);
+
+lt_t1 = be32toh(ia-lifetime_t1);
+lt_t2 = be32toh(ia-lifetime_t2);
+
+if (lt_t1  lt_t2  lt_t1  lt_t2) {
+log_dhcp6_client(client, IA T1 %ds  T2 %ds,
+ lt_t1, lt_t2);
+r = -EINVAL;
+goto error;
+}
+
+break;
+
+case DHCP6_OPTION_IA_TA:
+if (*buflen  DHCP6_OPTION_IA_TA_LEN + DHCP6_OPTION_HDR_LEN +
+DHCP6_OPTION_IAADDR_LEN) {
+r = -ENOBUFS;
+goto error;
+}
+
+iaaddr_offset = DHCP6_OPTION_IA_TA_LEN;
+memcpy(ia-id, *buf, iaaddr_offset);
+
+ia-lifetime_t1 = 0;
+ia-lifetime_t2 = 0;
+
+break;
+
+default:
+r = -ENOMSG;
+goto 

[systemd-devel] [PATCH 06/24] network-internal: split out net_get_name()

2014-06-13 Thread Patrik Flykt
From: Tom Gundersen t...@jklm.no

---
 src/libsystemd-network/network-internal.c | 26 +++---
 src/libsystemd-network/network-internal.h |  1 +
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/libsystemd-network/network-internal.c 
b/src/libsystemd-network/network-internal.c
index e9146d0..68d7f1b 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -34,21 +34,33 @@
 #include conf-parser.h
 #include condition.h
 
-#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
-
-int net_get_unique_predictable_data(struct udev_device *device, uint8_t 
result[8]) {
-size_t l, sz = 0;
+const char *net_get_name(struct udev_device *device) {
 const char *name = NULL, *field = NULL;
-int r;
-uint8_t *v;
+
+assert(device);
 
 /* fetch some persistent data unique (on this machine) to this device 
*/
-FOREACH_STRING(field, ID_NET_NAME_ONBOARD, ID_NET_NAME_SLOT, 
ID_NET_NAME_PATH, ID_NET_NAME_MAC) {
+FOREACH_STRING(field, ID_NET_NAME_ONBOARD, ID_NET_NAME_SLOT,
+   ID_NET_NAME_PATH, ID_NET_NAME_MAC) {
 name = udev_device_get_property_value(device, field);
 if (name)
 break;
 }
 
+return name;
+}
+
+#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
+
+int net_get_unique_predictable_data(struct udev_device *device, uint8_t 
result[8]) {
+size_t l, sz = 0;
+const char *name = NULL;
+int r;
+uint8_t *v;
+
+assert(device);
+
+name = net_get_name(device);
 if (!name)
 return -ENOENT;
 
diff --git a/src/libsystemd-network/network-internal.h 
b/src/libsystemd-network/network-internal.h
index 2aeecf0..db48c2c 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -65,6 +65,7 @@ int config_parse_ifalias(const char *unit, const char 
*filename, unsigned line,
 int net_parse_inaddr(const char *address, unsigned char *family, void *dst);
 
 int net_get_unique_predictable_data(struct udev_device *device, uint8_t 
result[8]);
+const char *net_get_name(struct udev_device *device);
 
 void serialize_in_addrs(FILE *f, const char *key, struct in_addr *addresses, 
size_t size);
 int deserialize_in_addrs(struct in_addr **addresses, size_t *size, const char 
*string);
-- 
1.9.1

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


  1   2   3   >