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; struct in6_addr *dest, *gateway; gboolean defgw_set = FALSE; struct in6_addr defgw; 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; 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; don't add to normal routes but to each address */ if (!defgw_set) { memcpy (&defgw, gateway, sizeof (defgw)); defgw_set = TRUE; } 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); if (defgw_set) nm_ip6_address_set_gateway (ip6addr, &defgw); } /* 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 route_proc_cb(struct nl_object *c, void *arg) { struct ip_lookup_res *res = (struct ip_lookup_res*) arg; struct rtnl_route *route = (struct rtnl_route *) c; struct nl_cache *link_cache; struct nl_addr *addr; struct rtnl_nexthop *nh; int prefix_len; int oif; char buf[64]; link_cache = nl_cache_mngt_require("route/link"); addr = rtnl_route_get_dst(route); if (addr) { printf("%s", nl_addr2str(addr, buf, sizeof(buf))); res->dstaddr = *(uint32_t *) nl_addr_get_binary_addr(addr); } prefix_len = rtnl_route_get_dst_len(route); if (prefix_len) printf("/%d ", prefix_len); else printf("default "); addr = rtnl_route_get_src(route); if (addr) printf("src %s ", nl_addr2str(addr, buf, sizeof(buf))); addr = rtnl_route_get_pref_src(route); if (addr) printf("preferred src %s ", nl_addr2str(addr, buf, sizeof(buf))); addr = rtnl_route_get_gateway(route); if (addr) { printf("via %s ", nl_addr2str(addr, buf, sizeof(buf))); res->nh_addr = *(uint32_t*) nl_addr_get_binary_addr(addr); } else { res->nh_addr = 0; } oif = rtnl_route_get_oif(route); res->oif = oif; if (oif != RTNL_LINK_NOT_FOUND && link_cache) { printf("dev %s ", rtnl_link_i2name(link_cache, oif, buf, sizeof(buf))); rtnl_link_i2name(link_cache, oif, res->oifname, sizeof(res->oifname)); } /* Declaration of rtnl_route_nh_get_gateway() is missing from * include/netlink/route/nexthop.h, there is no way to inspect * each nexthop for gateway information, will just use gateway * info stored in rtnl_route struct. The probem is only present * libnl 1 */ /* nl_list_for_each_entry(nh, rtnl_route_get_nexthops(route), rtnh_list) { } */ printf("\n"); }