/* Netlink interface link lookup filter */ static int netlink_if_link_filter(struct sockaddr_nl *snl, struct nlmsghdr *h) { struct ifinfomsg *ifi; struct rtattr *tb[IFLA_MAX + 1]; interface_t *ifp; int len, status; char *name; ifi = NLMSG_DATA(h); if (h->nlmsg_type != RTM_NEWLINK) return 0; len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg)); if (len < 0) return -1; /* Interface name lookup */ memset(tb, 0, sizeof (tb)); parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL) return -1; name = (char *) RTA_DATA(tb[IFLA_IFNAME]); /* Return if loopback */ if (ifi->ifi_type == ARPHRD_LOOPBACK) return 0; /* Skip it if already exist */ ifp = if_get_by_ifname(name); if (ifp) { #ifdef _HAVE_VRRP_VMAC_ if (!ifp->vmac) #endif { #ifdef _HAVE_VRRP_VMAC_ if_vmac_reflect_flags(ifi->ifi_index, ifi->ifi_flags); #endif ifp->flags = ifi->ifi_flags; } return 0; } /* Fill the interface structure */ ifp = (interface_t *) MALLOC(sizeof(interface_t)); status = netlink_if_link_populate(ifp, tb, ifi); if (status < 0) { FREE(ifp); return -1; } /* Queue this new interface_t */ if_add_queue(ifp); return 0; }
/* Netlink interface link lookup filter */ static int netlink_if_link_filter(struct sockaddr_nl *snl, struct nlmsghdr *h) { struct ifinfomsg *ifi; struct rtattr *tb[IFLA_MAX + 1]; interface_t *ifp; int i, len; char *name; ifi = NLMSG_DATA(h); if (h->nlmsg_type != RTM_NEWLINK) return 0; len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg)); if (len < 0) return -1; /* Interface name lookup */ memset(tb, 0, sizeof (tb)); parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL) return -1; name = (char *) RTA_DATA(tb[IFLA_IFNAME]); /* Return if loopback */ if (ifi->ifi_type == ARPHRD_LOOPBACK) return 0; /* Skip it if already exist */ ifp = if_get_by_ifname(name); if (ifp) { ifp->flags = ifi->ifi_flags; return 0; } /* Fill the interface structure */ ifp = (interface_t *) MALLOC(sizeof(interface_t)); memcpy(ifp->ifname, name, strlen(name)); ifp->ifindex = ifi->ifi_index; ifp->base_ifindex = ifi->ifi_index; ifp->flags = ifi->ifi_flags; ifp->mtu = *(int *) RTA_DATA(tb[IFLA_MTU]); ifp->hw_type = ifi->ifi_type; if (tb[IFLA_ADDRESS]) { int hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]); if (hw_addr_len > IF_HWADDR_MAX) log_message(LOG_ERR, "MAC address for %s is too large: %d", name, hw_addr_len); else { ifp->hw_addr_len = hw_addr_len; memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), hw_addr_len); for (i = 0; i < hw_addr_len; i++) if (ifp->hw_addr[i] != 0) break; if (i == hw_addr_len) ifp->hw_addr_len = 0; else ifp->hw_addr_len = hw_addr_len; } } /* Queue this new interface_t */ if_add_queue(ifp); return 0; }
/* Netlink flag Link update */ static int netlink_reflect_filter(struct sockaddr_nl *snl, struct nlmsghdr *h) { struct ifinfomsg *ifi; struct rtattr *tb[IFLA_MAX + 1]; interface_t *ifp; int len, status; ifi = NLMSG_DATA(h); if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) return 0; len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg)); if (len < 0) return -1; /* Interface name lookup */ memset(tb, 0, sizeof (tb)); parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL) return -1; /* ignore loopback device */ if (ifi->ifi_type == ARPHRD_LOOPBACK) return 0; /* find the interface_t. If the interface doesn't exist in the interface * list and this is a new interface add it to the interface list. * If an interface with the same name exists overwrite the older * structure and fill it with the new interface information. */ ifp = if_get_by_ifindex(ifi->ifi_index); if (!ifp) { if (h->nlmsg_type == RTM_NEWLINK) { char *name; name = (char *) RTA_DATA(tb[IFLA_IFNAME]); ifp = if_get_by_ifname(name); if (!ifp) { ifp = (interface_t *) MALLOC(sizeof(interface_t)); if_add_queue(ifp); } else { memset(ifp, 0, sizeof(interface_t)); } status = netlink_if_link_populate(ifp, tb, ifi); if (status < 0) return -1; } else { if (__test_bit(LOG_DETAIL_BIT, &debug)) log_message(LOG_INFO, "Unknown interface %s deleted", (char *)tb[IFLA_IFNAME]); return 0; } } /* * Update flags. * VMAC interfaces should never update it own flags, only be reflected * by the base interface flags. */ #ifdef _HAVE_VRRP_VMAC_ if (!ifp->vmac) #endif { #ifdef _HAVE_VRRP_VMAC_ if_vmac_reflect_flags(ifi->ifi_index, ifi->ifi_flags); #endif ifp->flags = ifi->ifi_flags; } return 0; }