On Tue, Jan 13, 2015 at 1:02 PM, Patrik Flykt <patrik.fl...@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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/systemd-devel _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel