static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMIP6Config *self = NM_IP6_CONFIG (object); NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); _nm_object_ensure_inited (NM_OBJECT (object)); switch (prop_id) { case PROP_GATEWAY: g_value_set_string (value, nm_ip6_config_get_gateway (self)); break; case PROP_ADDRESSES: nm_utils_ip6_addresses_to_gvalue (priv->addresses, value); break; case PROP_ROUTES: nm_utils_ip6_routes_to_gvalue (priv->routes, value); break; case PROP_NAMESERVERS: g_value_set_boxed (value, nm_ip6_config_get_nameservers (self)); break; case PROP_DOMAINS: g_value_set_boxed (value, nm_ip6_config_get_domains (self)); break; case PROP_SEARCHES: g_value_set_boxed (value, nm_ip6_config_get_searches (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
NMIP6Config * nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex) { NMIP6ManagerPrivate *priv; NMIP6Device *device; NMIP6Config *config; struct rtnl_addr *rtnladdr; struct nl_addr *nladdr; struct in6_addr *addr; NMIP6Address *ip6addr; struct rtnl_route *rtnlroute; struct nl_addr *nldest, *nlgateway; const struct in6_addr *dest, *gateway; uint32_t metric; NMIP6Route *ip6route; int i; g_return_val_if_fail (NM_IS_IP6_MANAGER (manager), NULL); g_return_val_if_fail (ifindex > 0, NULL); priv = NM_IP6_MANAGER_GET_PRIVATE (manager); device = (NMIP6Device *) g_hash_table_lookup (priv->devices, GINT_TO_POINTER (ifindex)); if (!device) { nm_log_warn (LOGD_IP6, "(%d): addrconf not started.", ifindex); return NULL; } config = nm_ip6_config_new (); if (!config) { nm_log_err (LOGD_IP6, "(%s): out of memory creating IP6 config object.", device->iface); return NULL; } /* Make sure we refill the route and address caches, otherwise we won't get * up-to-date information here since the netlink route/addr change messages * may be lagging a bit. */ nl_cache_refill (priv->nlh, priv->route_cache); nl_cache_refill (priv->nlh, priv->addr_cache); /* Add routes */ for (rtnlroute = FIRST_ROUTE (priv->route_cache); rtnlroute; rtnlroute = NEXT_ROUTE (rtnlroute)) { /* Make sure it's an IPv6 route for this device */ if (rtnl_route_get_oif (rtnlroute) != device->ifindex) continue; if (rtnl_route_get_family (rtnlroute) != AF_INET6) continue; /* And ignore cache/cloned routes as they aren't part of the interface's * permanent routing configuration. */ if (rtnl_route_get_flags (rtnlroute) & RTM_F_CLONED) continue; nldest = rtnl_route_get_dst (rtnlroute); if (!nldest || nl_addr_get_family (nldest) != AF_INET6) continue; dest = nl_addr_get_binary_addr (nldest); nlgateway = rtnl_route_get_gateway (rtnlroute); if (!nlgateway || nl_addr_get_family (nlgateway) != AF_INET6) continue; gateway = nl_addr_get_binary_addr (nlgateway); if (rtnl_route_get_dst_len (rtnlroute) == 0) { /* Default gateway route; cache the router's address for later */ if (!nm_ip6_config_get_gateway (config)) nm_ip6_config_set_gateway (config, gateway); continue; } /* Also ignore link-local routes where the destination and gateway are * the same, which apparently get added by the kernel but return -EINVAL * when we try to add them via netlink. */ if (gateway && IN6_ARE_ADDR_EQUAL (dest, gateway)) continue; ip6route = nm_ip6_route_new (); nm_ip6_route_set_dest (ip6route, dest); nm_ip6_route_set_prefix (ip6route, rtnl_route_get_dst_len (rtnlroute)); nm_ip6_route_set_next_hop (ip6route, gateway); rtnl_route_get_metric(rtnlroute, 1, &metric); if (metric != UINT_MAX) nm_ip6_route_set_metric (ip6route, metric); nm_ip6_config_take_route (config, ip6route); } /* Add addresses */ for (rtnladdr = FIRST_ADDR (priv->addr_cache); rtnladdr; rtnladdr = NEXT_ADDR (rtnladdr)) { if (rtnl_addr_get_ifindex (rtnladdr) != device->ifindex) continue; nladdr = rtnl_addr_get_local (rtnladdr); if (!nladdr || nl_addr_get_family (nladdr) != AF_INET6) continue; addr = nl_addr_get_binary_addr (nladdr); ip6addr = nm_ip6_address_new (); nm_ip6_address_set_prefix (ip6addr, rtnl_addr_get_prefixlen (rtnladdr)); nm_ip6_address_set_address (ip6addr, addr); nm_ip6_config_take_address (config, ip6addr); gateway = nm_ip6_config_get_gateway (config); if (gateway) nm_ip6_address_set_gateway (ip6addr, gateway); } /* Add DNS servers */ if (device->rdnss_servers) { NMIP6RDNSS *rdnss = (NMIP6RDNSS *)(device->rdnss_servers->data); for (i = 0; i < device->rdnss_servers->len; i++) nm_ip6_config_add_nameserver (config, &rdnss[i].addr); } /* Add DNS domains */ if (device->dnssl_domains) { NMIP6DNSSL *dnssl = (NMIP6DNSSL *)(device->dnssl_domains->data); for (i = 0; i < device->dnssl_domains->len; i++) nm_ip6_config_add_domain (config, dnssl[i].domain); } return config; }
static void dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder) { GVariantBuilder int_builder; guint n, i; const NMPlatformIP6Address *addr; const struct in6_addr *gw_bytes; const NMPlatformIP6Route *route; GVariant *ip, *gw; /* Addresses */ g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuay)")); n = nm_ip6_config_get_num_addresses (ip6); for (i = 0; i < n; i++) { addr = nm_ip6_config_get_address (ip6, i); gw_bytes = nm_ip6_config_get_gateway (ip6); ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &addr->address, sizeof (struct in6_addr), 1); gw = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, (i == 0 && gw_bytes) ? gw_bytes : &in6addr_any, sizeof (struct in6_addr), 1); g_variant_builder_add (&int_builder, "(@ayu@ay)", ip, addr->plen, gw); } g_variant_builder_add (builder, "{sv}", "addresses", g_variant_builder_end (&int_builder)); /* DNS servers */ g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aay")); n = nm_ip6_config_get_num_nameservers (ip6); for (i = 0; i < n; i++) { ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, nm_ip6_config_get_nameserver (ip6, i), sizeof (struct in6_addr), 1); g_variant_builder_add (&int_builder, "@ay", ip); } g_variant_builder_add (builder, "{sv}", "nameservers", g_variant_builder_end (&int_builder)); /* Search domains */ g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("as")); n = nm_ip6_config_get_num_domains (ip6); for (i = 0; i < n; i++) g_variant_builder_add (&int_builder, "s", nm_ip6_config_get_domain (ip6, i)); g_variant_builder_add (builder, "{sv}", "domains", g_variant_builder_end (&int_builder)); /* Static routes */ g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuayu)")); n = nm_ip6_config_get_num_routes (ip6); for (i = 0; i < n; i++) { route = nm_ip6_config_get_route (ip6, i); ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &route->network, sizeof (struct in6_addr), 1); gw = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &route->gateway, sizeof (struct in6_addr), 1); g_variant_builder_add (&int_builder, "(@ayu@ayu)", ip, route->plen, gw, route->metric); } g_variant_builder_add (builder, "{sv}", "routes", g_variant_builder_end (&int_builder)); }