[systemd-devel] [PATCH 04/11] sd-icmp6-nd: Add link and prefix structures for ICMPv6
Tom Gundersen
teg at jklm.no
Wed Jan 14 05:03:41 PST 2015
On Tue, Jan 13, 2015 at 1:02 PM, Patrik Flykt
<patrik.flykt at linux.intel.com> wrote:
> 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;
> +};
Structs that we don't export we usually use CamelCase for the name (and typedef)
So
typedef ICMP6Prefix {
...
} ICMP6Prefix;
> +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;
This looks a bit strange to me. The sd_icmp6_nd struct is anyway
per-link, so why not just embed the members from icmp6_link directly
in sd_icmp6_nd?
> 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
More information about the systemd-devel
mailing list