static int get_gateway_description( sd_netlink *rtnl, sd_hwdb *hwdb, int ifindex, int family, union in_addr_union *gateway, char **gateway_description) { _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *m; int r; assert(rtnl); assert(ifindex >= 0); assert(family == AF_INET || family == AF_INET6); assert(gateway); assert(gateway_description); r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_GETNEIGH, ifindex, family); if (r < 0) return r; r = sd_netlink_message_request_dump(req, true); if (r < 0) return r; r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return r; for (m = reply; m; m = sd_netlink_message_next(m)) { union in_addr_union gw = {}; struct ether_addr mac = {}; uint16_t type; int ifi, fam; r = sd_netlink_message_get_errno(m); if (r < 0) { log_error_errno(r, "got error: %m"); continue; } r = sd_netlink_message_get_type(m, &type); if (r < 0) { log_error_errno(r, "could not get type: %m"); continue; } if (type != RTM_NEWNEIGH) { log_error("type is not RTM_NEWNEIGH"); continue; } r = sd_rtnl_message_neigh_get_family(m, &fam); if (r < 0) { log_error_errno(r, "could not get family: %m"); continue; } if (fam != family) { log_error("family is not correct"); continue; } r = sd_rtnl_message_neigh_get_ifindex(m, &ifi); if (r < 0) { log_error_errno(r, "could not get ifindex: %m"); continue; } if (ifindex > 0 && ifi != ifindex) continue; switch (fam) { case AF_INET: r = sd_netlink_message_read_in_addr(m, NDA_DST, &gw.in); if (r < 0) continue; break; case AF_INET6: r = sd_netlink_message_read_in6_addr(m, NDA_DST, &gw.in6); if (r < 0) continue; break; default: continue; } if (!in_addr_equal(fam, &gw, gateway)) continue; r = sd_netlink_message_read_ether_addr(m, NDA_LLADDR, &mac); if (r < 0) continue; r = ieee_oui(hwdb, &mac, gateway_description); if (r < 0) continue; return 0; } return -ENODATA; }
static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool test) { const char *s; const char *p; unsigned int i; const char *devtype; const char *prefix = "en"; struct netnames names = {}; int err; /* handle only ARPHRD_ETHER devices */ s = udev_device_get_sysattr_value(dev, "type"); if (!s) return EXIT_FAILURE; i = strtoul(s, NULL, 0); if (i != 1) return 0; /* skip stacked devices, like VLANs, ... */ s = udev_device_get_sysattr_value(dev, "ifindex"); if (!s) return EXIT_FAILURE; p = udev_device_get_sysattr_value(dev, "iflink"); if (!p) return EXIT_FAILURE; if (strcmp(s, p) != 0) return 0; devtype = udev_device_get_devtype(dev); if (devtype) { if (streq("wlan", devtype)) prefix = "wl"; else if (streq("wwan", devtype)) prefix = "ww"; } err = names_mac(dev, &names); if (err >= 0 && names.mac_valid) { char str[IFNAMSIZ]; snprintf(str, sizeof(str), "%sx%02x%02x%02x%02x%02x%02x", prefix, names.mac[0], names.mac[1], names.mac[2], names.mac[3], names.mac[4], names.mac[5]); udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str); ieee_oui(dev, &names, test); } /* get PCI based path names, we compose only PCI based paths */ err = names_pci(dev, &names); if (err < 0) goto out; /* plain PCI device */ if (names.type == NET_PCI) { char str[IFNAMSIZ]; if (names.pci_onboard[0]) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str); if (names.pci_onboard_label) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard_label) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str); if (names.pci_path[0]) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_path) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); if (names.pci_slot[0]) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_slot) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); goto out; } /* USB device */ err = names_usb(dev, &names); if (err >= 0 && names.type == NET_USB) { char str[IFNAMSIZ]; if (names.pci_path[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.usb_ports) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); if (names.pci_slot[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.usb_ports) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); goto out; } /* Broadcom bus */ err = names_bcma(dev, &names); if (err >= 0 && names.type == NET_BCMA) { char str[IFNAMSIZ]; if (names.pci_path[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.bcma_core) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); if (names.pci_slot[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.bcma_core) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); goto out; } out: return EXIT_SUCCESS; }