static NMIP6Device * process_address_change (NMIP6Manager *manager, struct nl_msg *msg) { NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); NMIP6Device *device; struct nlmsghdr *hdr; struct rtnl_addr *rtnladdr; int old_size; hdr = nlmsg_hdr (msg); rtnladdr = NULL; nl_msg_parse (msg, ref_object, &rtnladdr); if (!rtnladdr) { nm_log_dbg (LOGD_IP6, "error processing netlink new/del address message"); return NULL; } device = nm_ip6_manager_get_device (manager, rtnl_addr_get_ifindex (rtnladdr)); old_size = nl_cache_nitems (priv->addr_cache); nl_cache_include (priv->addr_cache, (struct nl_object *)rtnladdr, NULL, NULL); /* The kernel will re-notify us of automatically-added addresses * every time it gets another router advertisement. We only want * to notify higher levels if we actually changed something. */ nm_log_dbg (LOGD_IP6, "(%s): address cache size: %d -> %d:", device_get_iface (device), old_size, nl_cache_nitems (priv->addr_cache)); dump_address_change (device, hdr, rtnladdr); rtnl_addr_put (rtnladdr); if (nl_cache_nitems (priv->addr_cache) == old_size) return NULL; return device; }
/** * Print information about cache manager * @arg mngr Cache manager * @arg p Dumping parameters * * Prints information about the cache manager including all managed caches. * * @note This is a debugging function. */ void nl_cache_mngr_info(struct nl_cache_mngr *mngr, struct nl_dump_params *p) { char buf[128]; int i; nl_dump_line(p, "cache-manager <%p>\n", mngr); nl_dump_line(p, " .protocol = %s\n", nl_nlfamily2str(mngr->cm_protocol, buf, sizeof(buf))); nl_dump_line(p, " .flags = %#x\n", mngr->cm_flags); nl_dump_line(p, " .nassocs = %u\n", mngr->cm_nassocs); nl_dump_line(p, " .sock = <%p>\n", mngr->cm_sock); for (i = 0; i < mngr->cm_nassocs; i++) { struct nl_cache_assoc *assoc = &mngr->cm_assocs[i]; if (assoc->ca_cache) { nl_dump_line(p, " .cache[%d] = <%p> {\n", i, assoc->ca_cache); nl_dump_line(p, " .name = %s\n", assoc->ca_cache->c_ops->co_name); nl_dump_line(p, " .change_func = <%p>\n", assoc->ca_change); nl_dump_line(p, " .change_data = <%p>\n", assoc->ca_change_data); nl_dump_line(p, " .nitems = %u\n", nl_cache_nitems(assoc->ca_cache)); nl_dump_line(p, " .objects = {\n"); p->dp_prefix += 6; nl_cache_dump(assoc->ca_cache, p); p->dp_prefix -= 6; nl_dump_line(p, " }\n"); nl_dump_line(p, " }\n"); } } }
static NMIP6Device * process_route_change (NMIP6Manager *manager, struct nl_msg *msg) { NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); NMIP6Device *device; struct nlmsghdr *hdr; struct rtnl_route *rtnlroute; int old_size; hdr = nlmsg_hdr (msg); rtnlroute = NULL; nl_msg_parse (msg, ref_object, &rtnlroute); if (!rtnlroute) { nm_log_dbg (LOGD_IP6, "error processing netlink new/del route message"); return NULL; } /* Cached/cloned routes are created by the kernel for specific operations * and aren't part of the interface's permanent routing configuration. */ if (rtnl_route_get_flags (rtnlroute) & RTM_F_CLONED) { rtnl_route_put (rtnlroute); return NULL; } device = nm_ip6_manager_get_device (manager, rtnl_route_get_oif (rtnlroute)); old_size = nl_cache_nitems (priv->route_cache); nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL, NULL); /* As above in process_address_change */ nm_log_dbg (LOGD_IP6, "(%s): route cache size: %d -> %d:", device_get_iface (device), old_size, nl_cache_nitems (priv->route_cache)); dump_route_change (device, hdr, rtnlroute); rtnl_route_put (rtnlroute); if (nl_cache_nitems (priv->route_cache) == old_size) return NULL; return device; }
static NMIP6Device * process_route (NMIP6Manager *manager, struct nl_msg *msg) { NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); NMIP6Device *device; struct rtnl_route *rtnlroute; int old_size; nm_log_dbg (LOGD_IP6, "processing netlink new/del route message"); rtnlroute = NULL; nl_msg_parse (msg, ref_object, &rtnlroute); if (!rtnlroute) { nm_log_dbg (LOGD_IP6, "error processing netlink new/del route message"); return NULL; } device = nm_ip6_manager_get_device (manager, rtnl_route_get_oif (rtnlroute)); if (!device) { nm_log_dbg (LOGD_IP6, "ignoring message for unknown device"); rtnl_route_put (rtnlroute); return NULL; } old_size = nl_cache_nitems (priv->route_cache); nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL, NULL); rtnl_route_put (rtnlroute); /* As above in process_addr */ if (nl_cache_nitems (priv->route_cache) == old_size) { nm_log_dbg (LOGD_IP6, "(%s): route cache unchanged, ignoring message", device->iface); return NULL; } return device; }
/* Given an interface's MAC address, return the name (e.g., eth0) in human * readable format. Return NULL for no match */ char *iface_mac2device(char *mac) { struct nl_handle *handle = NULL; struct nl_cache *cache = NULL; struct rtnl_link *link = NULL; struct nl_addr *mac_as_nl_addr = NULL; char *retval = NULL; int i, n; if (mac == NULL) { return NULL; } if ((mac_as_nl_addr = nl_addr_parse(mac, AF_LLC)) == NULL) { return NULL; } if ((cache = _iface_get_link_cache(&handle)) == NULL) { return NULL; } n = nl_cache_nitems(cache); for (i = 0; i <= n; i++) { struct nl_addr *addr; if ((link = rtnl_link_get(cache, i)) == NULL) { continue; } addr = rtnl_link_get_addr(link); if (!nl_addr_cmp(mac_as_nl_addr, addr)) { retval = strdup(rtnl_link_get_name(link)); rtnl_link_put(link); break; } rtnl_link_put(link); } nl_close(handle); nl_handle_destroy(handle); return retval; }