diff options
Diffstat (limited to 'zebra/if_netlink.c')
| -rw-r--r-- | zebra/if_netlink.c | 1389 |
1 files changed, 714 insertions, 675 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 006fcf16f4..c75d96ac76 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * 02111-1307, USA. */ #include <zebra.h> @@ -57,126 +57,176 @@ /* Note: on netlink systems, there should be a 1-to-1 mapping between interface names and ifindex values. */ -static void -set_ifindex(struct interface *ifp, ifindex_t ifi_index, struct zebra_ns *zns) +static void set_ifindex(struct interface *ifp, ifindex_t ifi_index, + struct zebra_ns *zns) { - struct interface *oifp; - - if (((oifp = if_lookup_by_index_per_ns (zns, ifi_index)) != NULL) && (oifp != ifp)) - { - if (ifi_index == IFINDEX_INTERNAL) - zlog_err("Netlink is setting interface %s ifindex to reserved " - "internal value %u", ifp->name, ifi_index); - else - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("interface index %d was renamed from %s to %s", - ifi_index, oifp->name, ifp->name); - if (if_is_up(oifp)) - zlog_err("interface rename detected on up interface: index %d " - "was renamed from %s to %s, results are uncertain!", - ifi_index, oifp->name, ifp->name); - if_delete_update(oifp); - } - } - ifp->ifindex = ifi_index; + struct interface *oifp; + + if (((oifp = if_lookup_by_index_per_ns(zns, ifi_index)) != NULL) + && (oifp != ifp)) { + if (ifi_index == IFINDEX_INTERNAL) + zlog_err( + "Netlink is setting interface %s ifindex to reserved " + "internal value %u", + ifp->name, ifi_index); + else { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "interface index %d was renamed from %s to %s", + ifi_index, oifp->name, ifp->name); + if (if_is_up(oifp)) + zlog_err( + "interface rename detected on up interface: index %d " + "was renamed from %s to %s, results are uncertain!", + ifi_index, oifp->name, ifp->name); + if_delete_update(oifp); + } + } + ifp->ifindex = ifi_index; } /* Utility function to parse hardware link-layer address and update ifp */ -static void -netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp) +static void netlink_interface_update_hw_addr(struct rtattr **tb, + struct interface *ifp) { - int i; - - if (tb[IFLA_ADDRESS]) - { - int hw_addr_len; - - hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]); - - if (hw_addr_len > INTERFACE_HWADDR_MAX) - zlog_warn ("Hardware address is too large: %d", 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; - } - } + int i; + + if (tb[IFLA_ADDRESS]) { + int hw_addr_len; + + hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]); + + if (hw_addr_len > INTERFACE_HWADDR_MAX) + zlog_warn("Hardware address is too large: %d", + 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; + } + } } -static enum zebra_link_type -netlink_to_zebra_link_type (unsigned int hwt) +static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt) { - switch (hwt) - { - case ARPHRD_ETHER: return ZEBRA_LLT_ETHER; - case ARPHRD_EETHER: return ZEBRA_LLT_EETHER; - case ARPHRD_AX25: return ZEBRA_LLT_AX25; - case ARPHRD_PRONET: return ZEBRA_LLT_PRONET; - case ARPHRD_IEEE802: return ZEBRA_LLT_IEEE802; - case ARPHRD_ARCNET: return ZEBRA_LLT_ARCNET; - case ARPHRD_APPLETLK: return ZEBRA_LLT_APPLETLK; - case ARPHRD_DLCI: return ZEBRA_LLT_DLCI; - case ARPHRD_ATM: return ZEBRA_LLT_ATM; - case ARPHRD_METRICOM: return ZEBRA_LLT_METRICOM; - case ARPHRD_IEEE1394: return ZEBRA_LLT_IEEE1394; - case ARPHRD_EUI64: return ZEBRA_LLT_EUI64; - case ARPHRD_INFINIBAND: return ZEBRA_LLT_INFINIBAND; - case ARPHRD_SLIP: return ZEBRA_LLT_SLIP; - case ARPHRD_CSLIP: return ZEBRA_LLT_CSLIP; - case ARPHRD_SLIP6: return ZEBRA_LLT_SLIP6; - case ARPHRD_CSLIP6: return ZEBRA_LLT_CSLIP6; - case ARPHRD_RSRVD: return ZEBRA_LLT_RSRVD; - case ARPHRD_ADAPT: return ZEBRA_LLT_ADAPT; - case ARPHRD_ROSE: return ZEBRA_LLT_ROSE; - case ARPHRD_X25: return ZEBRA_LLT_X25; - case ARPHRD_PPP: return ZEBRA_LLT_PPP; - case ARPHRD_CISCO: return ZEBRA_LLT_CHDLC; - case ARPHRD_LAPB: return ZEBRA_LLT_LAPB; - case ARPHRD_RAWHDLC: return ZEBRA_LLT_RAWHDLC; - case ARPHRD_TUNNEL: return ZEBRA_LLT_IPIP; - case ARPHRD_TUNNEL6: return ZEBRA_LLT_IPIP6; - case ARPHRD_FRAD: return ZEBRA_LLT_FRAD; - case ARPHRD_SKIP: return ZEBRA_LLT_SKIP; - case ARPHRD_LOOPBACK: return ZEBRA_LLT_LOOPBACK; - case ARPHRD_LOCALTLK: return ZEBRA_LLT_LOCALTLK; - case ARPHRD_FDDI: return ZEBRA_LLT_FDDI; - case ARPHRD_SIT: return ZEBRA_LLT_SIT; - case ARPHRD_IPDDP: return ZEBRA_LLT_IPDDP; - case ARPHRD_IPGRE: return ZEBRA_LLT_IPGRE; - case ARPHRD_PIMREG: return ZEBRA_LLT_PIMREG; - case ARPHRD_HIPPI: return ZEBRA_LLT_HIPPI; - case ARPHRD_ECONET: return ZEBRA_LLT_ECONET; - case ARPHRD_IRDA: return ZEBRA_LLT_IRDA; - case ARPHRD_FCPP: return ZEBRA_LLT_FCPP; - case ARPHRD_FCAL: return ZEBRA_LLT_FCAL; - case ARPHRD_FCPL: return ZEBRA_LLT_FCPL; - case ARPHRD_FCFABRIC: return ZEBRA_LLT_FCFABRIC; - case ARPHRD_IEEE802_TR: return ZEBRA_LLT_IEEE802_TR; - case ARPHRD_IEEE80211: return ZEBRA_LLT_IEEE80211; - case ARPHRD_IEEE802154: return ZEBRA_LLT_IEEE802154; + switch (hwt) { + case ARPHRD_ETHER: + return ZEBRA_LLT_ETHER; + case ARPHRD_EETHER: + return ZEBRA_LLT_EETHER; + case ARPHRD_AX25: + return ZEBRA_LLT_AX25; + case ARPHRD_PRONET: + return ZEBRA_LLT_PRONET; + case ARPHRD_IEEE802: + return ZEBRA_LLT_IEEE802; + case ARPHRD_ARCNET: + return ZEBRA_LLT_ARCNET; + case ARPHRD_APPLETLK: + return ZEBRA_LLT_APPLETLK; + case ARPHRD_DLCI: + return ZEBRA_LLT_DLCI; + case ARPHRD_ATM: + return ZEBRA_LLT_ATM; + case ARPHRD_METRICOM: + return ZEBRA_LLT_METRICOM; + case ARPHRD_IEEE1394: + return ZEBRA_LLT_IEEE1394; + case ARPHRD_EUI64: + return ZEBRA_LLT_EUI64; + case ARPHRD_INFINIBAND: + return ZEBRA_LLT_INFINIBAND; + case ARPHRD_SLIP: + return ZEBRA_LLT_SLIP; + case ARPHRD_CSLIP: + return ZEBRA_LLT_CSLIP; + case ARPHRD_SLIP6: + return ZEBRA_LLT_SLIP6; + case ARPHRD_CSLIP6: + return ZEBRA_LLT_CSLIP6; + case ARPHRD_RSRVD: + return ZEBRA_LLT_RSRVD; + case ARPHRD_ADAPT: + return ZEBRA_LLT_ADAPT; + case ARPHRD_ROSE: + return ZEBRA_LLT_ROSE; + case ARPHRD_X25: + return ZEBRA_LLT_X25; + case ARPHRD_PPP: + return ZEBRA_LLT_PPP; + case ARPHRD_CISCO: + return ZEBRA_LLT_CHDLC; + case ARPHRD_LAPB: + return ZEBRA_LLT_LAPB; + case ARPHRD_RAWHDLC: + return ZEBRA_LLT_RAWHDLC; + case ARPHRD_TUNNEL: + return ZEBRA_LLT_IPIP; + case ARPHRD_TUNNEL6: + return ZEBRA_LLT_IPIP6; + case ARPHRD_FRAD: + return ZEBRA_LLT_FRAD; + case ARPHRD_SKIP: + return ZEBRA_LLT_SKIP; + case ARPHRD_LOOPBACK: + return ZEBRA_LLT_LOOPBACK; + case ARPHRD_LOCALTLK: + return ZEBRA_LLT_LOCALTLK; + case ARPHRD_FDDI: + return ZEBRA_LLT_FDDI; + case ARPHRD_SIT: + return ZEBRA_LLT_SIT; + case ARPHRD_IPDDP: + return ZEBRA_LLT_IPDDP; + case ARPHRD_IPGRE: + return ZEBRA_LLT_IPGRE; + case ARPHRD_PIMREG: + return ZEBRA_LLT_PIMREG; + case ARPHRD_HIPPI: + return ZEBRA_LLT_HIPPI; + case ARPHRD_ECONET: + return ZEBRA_LLT_ECONET; + case ARPHRD_IRDA: + return ZEBRA_LLT_IRDA; + case ARPHRD_FCPP: + return ZEBRA_LLT_FCPP; + case ARPHRD_FCAL: + return ZEBRA_LLT_FCAL; + case ARPHRD_FCPL: + return ZEBRA_LLT_FCPL; + case ARPHRD_FCFABRIC: + return ZEBRA_LLT_FCFABRIC; + case ARPHRD_IEEE802_TR: + return ZEBRA_LLT_IEEE802_TR; + case ARPHRD_IEEE80211: + return ZEBRA_LLT_IEEE80211; + case ARPHRD_IEEE802154: + return ZEBRA_LLT_IEEE802154; #ifdef ARPHRD_IP6GRE - case ARPHRD_IP6GRE: return ZEBRA_LLT_IP6GRE; + case ARPHRD_IP6GRE: + return ZEBRA_LLT_IP6GRE; #endif #ifdef ARPHRD_IEEE802154_PHY - case ARPHRD_IEEE802154_PHY: return ZEBRA_LLT_IEEE802154_PHY; + case ARPHRD_IEEE802154_PHY: + return ZEBRA_LLT_IEEE802154_PHY; #endif - default: return ZEBRA_LLT_UNKNOWN; - } + default: + return ZEBRA_LLT_UNKNOWN; + } } -//Temporary Assignments to compile on older platforms. +// Temporary Assignments to compile on older platforms. #ifndef IFLA_BR_MAX #define IFLA_BR_MAX 39 #endif @@ -217,644 +267,633 @@ netlink_to_zebra_link_type (unsigned int hwt) #define IFLA_BR_VLAN_FILTERING 7 #endif -#define parse_rtattr_nested(tb, max, rta) \ - netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) +#define parse_rtattr_nested(tb, max, rta) \ + netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) -static void -netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name) +static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb, + const char *name) { - struct ifinfomsg *ifi; - struct rtattr *linkinfo[IFLA_INFO_MAX+1]; - struct rtattr *attr[IFLA_VRF_MAX+1]; - struct vrf *vrf; - struct zebra_vrf *zvrf; - u_int32_t nl_table_id; - - ifi = NLMSG_DATA (h); - - memset (linkinfo, 0, sizeof linkinfo); - parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); - - if (!linkinfo[IFLA_INFO_DATA]) { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: IFLA_INFO_DATA missing from VRF message: %s", __func__, name); - return; - } - - memset (attr, 0, sizeof attr); - parse_rtattr_nested(attr, IFLA_VRF_MAX, linkinfo[IFLA_INFO_DATA]); - if (!attr[IFLA_VRF_TABLE]) { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: IFLA_VRF_TABLE missing from VRF message: %s", __func__, name); - return; - } - - nl_table_id = *(u_int32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]); - - if (h->nlmsg_type == RTM_NEWLINK) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK for VRF %s(%u) table %u", - name, ifi->ifi_index, nl_table_id); - - /* - * vrf_get is implied creation if it does not exist - */ - vrf = vrf_get((vrf_id_t)ifi->ifi_index, name); // It would create vrf - if (!vrf) - { - zlog_err ("VRF %s id %u not created", name, ifi->ifi_index); - return; - } - - /* Enable the created VRF. */ - if (!vrf_enable (vrf)) - { - zlog_err ("Failed to enable VRF %s id %u", name, ifi->ifi_index); - return; - } - - /* - * This is the only place that we get the actual kernel table_id - * being used. We need it to set the table_id of the routes - * we are passing to the kernel.... And to throw some totally - * awesome parties. that too. - */ - zvrf = (struct zebra_vrf *)vrf->info; - zvrf->table_id = nl_table_id; - } - else //h->nlmsg_type == RTM_DELLINK - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_DELLINK for VRF %s(%u)", name, ifi->ifi_index); - - vrf = vrf_lookup_by_id ((vrf_id_t)ifi->ifi_index); - - if (!vrf) - { - zlog_warn ("%s: vrf not found", __func__); - return; + struct ifinfomsg *ifi; + struct rtattr *linkinfo[IFLA_INFO_MAX + 1]; + struct rtattr *attr[IFLA_VRF_MAX + 1]; + struct vrf *vrf; + struct zebra_vrf *zvrf; + u_int32_t nl_table_id; + + ifi = NLMSG_DATA(h); + + memset(linkinfo, 0, sizeof linkinfo); + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); + + if (!linkinfo[IFLA_INFO_DATA]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: IFLA_INFO_DATA missing from VRF message: %s", + __func__, name); + return; } - vrf_delete (vrf); - } + memset(attr, 0, sizeof attr); + parse_rtattr_nested(attr, IFLA_VRF_MAX, linkinfo[IFLA_INFO_DATA]); + if (!attr[IFLA_VRF_TABLE]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: IFLA_VRF_TABLE missing from VRF message: %s", + __func__, name); + return; + } + + nl_table_id = *(u_int32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]); + + if (h->nlmsg_type == RTM_NEWLINK) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("RTM_NEWLINK for VRF %s(%u) table %u", name, + ifi->ifi_index, nl_table_id); + + /* + * vrf_get is implied creation if it does not exist + */ + vrf = vrf_get((vrf_id_t)ifi->ifi_index, + name); // It would create vrf + if (!vrf) { + zlog_err("VRF %s id %u not created", name, + ifi->ifi_index); + return; + } + + /* Enable the created VRF. */ + if (!vrf_enable(vrf)) { + zlog_err("Failed to enable VRF %s id %u", name, + ifi->ifi_index); + return; + } + + /* + * This is the only place that we get the actual kernel table_id + * being used. We need it to set the table_id of the routes + * we are passing to the kernel.... And to throw some totally + * awesome parties. that too. + */ + zvrf = (struct zebra_vrf *)vrf->info; + zvrf->table_id = nl_table_id; + } else // h->nlmsg_type == RTM_DELLINK + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("RTM_DELLINK for VRF %s(%u)", name, + ifi->ifi_index); + + vrf = vrf_lookup_by_id((vrf_id_t)ifi->ifi_index); + + if (!vrf) { + zlog_warn("%s: vrf not found", __func__); + return; + } + + vrf_delete(vrf); + } } -static int -get_iflink_speed (const char *ifname) +static int get_iflink_speed(const char *ifname) { - struct ifreq ifdata; - struct ethtool_cmd ecmd; - int sd; - int rc; - - /* initialize struct */ - memset(&ifdata, 0, sizeof(ifdata)); - - /* set interface name */ - strcpy(ifdata.ifr_name, ifname); - - /* initialize ethtool interface */ - memset(&ecmd, 0, sizeof(ecmd)); - ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */ - ifdata.ifr_data = (__caddr_t) &ecmd; - - /* use ioctl to get IP address of an interface */ - sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); - if(sd < 0) { - zlog_debug ("Failure to read interface %s speed: %d %s", - ifname, errno, safe_strerror(errno)); - return 0; - } - - /* Get the current link state for the interface */ - rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata); - if(rc < 0) { - zlog_debug("IOCTL failure to read interface %s speed: %d %s", - ifname, errno, safe_strerror(errno)); - ecmd.speed_hi = 0; - ecmd.speed = 0; - } - - close(sd); - - return (ecmd.speed_hi << 16 ) | ecmd.speed; + struct ifreq ifdata; + struct ethtool_cmd ecmd; + int sd; + int rc; + + /* initialize struct */ + memset(&ifdata, 0, sizeof(ifdata)); + + /* set interface name */ + strcpy(ifdata.ifr_name, ifname); + + /* initialize ethtool interface */ + memset(&ecmd, 0, sizeof(ecmd)); + ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */ + ifdata.ifr_data = (__caddr_t)&ecmd; + + /* use ioctl to get IP address of an interface */ + sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sd < 0) { + zlog_debug("Failure to read interface %s speed: %d %s", ifname, + errno, safe_strerror(errno)); + return 0; + } + + /* Get the current link state for the interface */ + rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata); + if (rc < 0) { + zlog_debug("IOCTL failure to read interface %s speed: %d %s", + ifname, errno, safe_strerror(errno)); + ecmd.speed_hi = 0; + ecmd.speed = 0; + } + + close(sd); + + return (ecmd.speed_hi << 16) | ecmd.speed; } /* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ -static int -netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_interface(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ifinfomsg *ifi; - struct rtattr *tb[IFLA_MAX + 1]; - struct rtattr *linkinfo[IFLA_MAX + 1]; - struct interface *ifp; - char *name = NULL; - char *kind = NULL; - char *slave_kind = NULL; - int vrf_device = 0; - struct zebra_ns *zns; - vrf_id_t vrf_id = VRF_DEFAULT; - - zns = zebra_ns_lookup (ns_id); - 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; - - if (ifi->ifi_family == AF_BRIDGE) - return 0; - - /* Looking up interface name. */ - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); + int len; + struct ifinfomsg *ifi; + struct rtattr *tb[IFLA_MAX + 1]; + struct rtattr *linkinfo[IFLA_MAX + 1]; + struct interface *ifp; + char *name = NULL; + char *kind = NULL; + char *slave_kind = NULL; + int vrf_device = 0; + struct zebra_ns *zns; + vrf_id_t vrf_id = VRF_DEFAULT; + + zns = zebra_ns_lookup(ns_id); + 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; + + if (ifi->ifi_family == AF_BRIDGE) + return 0; + + /* Looking up interface name. */ + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); #ifdef IFLA_WIRELESS - /* check for wireless messages to ignore */ - if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); - return 0; - } + /* check for wireless messages to ignore */ + if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: ignoring IFLA_WIRELESS message", + __func__); + return 0; + } #endif /* IFLA_WIRELESS */ - if (tb[IFLA_IFNAME] == NULL) - return -1; - name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + if (tb[IFLA_IFNAME] == NULL) + return -1; + name = (char *)RTA_DATA(tb[IFLA_IFNAME]); - if (tb[IFLA_LINKINFO]) - { - memset (linkinfo, 0, sizeof linkinfo); - parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + if (tb[IFLA_LINKINFO]) { + memset(linkinfo, 0, sizeof linkinfo); + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); - if (linkinfo[IFLA_INFO_KIND]) - kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); + if (linkinfo[IFLA_INFO_KIND]) + kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); #if HAVE_DECL_IFLA_INFO_SLAVE_KIND - if (linkinfo[IFLA_INFO_SLAVE_KIND]) - slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); + if (linkinfo[IFLA_INFO_SLAVE_KIND]) + slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); #endif - if (kind && strcmp(kind, "vrf") == 0) - { - vrf_device = 1; - netlink_vrf_change(h, tb[IFLA_LINKINFO], name); - vrf_id = (vrf_id_t)ifi->ifi_index; - } - } - - if (tb[IFLA_MASTER]) - { - if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) - vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); - } - - /* Add interface. */ - ifp = if_get_by_name (name, vrf_id); - set_ifindex(ifp, ifi->ifi_index, zns); - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (vrf_device) - SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 0; - ifp->speed = get_iflink_speed (name); - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - - /* Hardware type and address. */ - ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type); - netlink_interface_update_hw_addr (tb, ifp); - - if_add_update (ifp); - - return 0; + if (kind && strcmp(kind, "vrf") == 0) { + vrf_device = 1; + netlink_vrf_change(h, tb[IFLA_LINKINFO], name); + vrf_id = (vrf_id_t)ifi->ifi_index; + } + } + + if (tb[IFLA_MASTER]) { + if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) + vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + } + + /* Add interface. */ + ifp = if_get_by_name(name, vrf_id); + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (vrf_device) + SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); + ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); + ifp->metric = 0; + ifp->speed = get_iflink_speed(name); + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + + /* Hardware type and address. */ + ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type); + netlink_interface_update_hw_addr(tb, ifp); + + if_add_update(ifp); + + return 0; } /* Interface lookup by netlink socket. */ -int -interface_lookup_netlink (struct zebra_ns *zns) +int interface_lookup_netlink(struct zebra_ns *zns) { - int ret; - - /* Get interface information. */ - ret = netlink_request (AF_PACKET, RTM_GETLINK, &zns->netlink_cmd); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - /* Get IPv4 address of the interfaces. */ - ret = netlink_request (AF_INET, RTM_GETADDR, &zns->netlink_cmd); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - /* Get IPv6 address of the interfaces. */ - ret = netlink_request (AF_INET6, RTM_GETADDR, &zns->netlink_cmd); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - return 0; + int ret; + + /* Get interface information. */ + ret = netlink_request(AF_PACKET, RTM_GETLINK, &zns->netlink_cmd); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0, + 1); + if (ret < 0) + return ret; + + /* Get IPv4 address of the interfaces. */ + ret = netlink_request(AF_INET, RTM_GETADDR, &zns->netlink_cmd); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface_addr, &zns->netlink_cmd, zns, + 0, 1); + if (ret < 0) + return ret; + + /* Get IPv6 address of the interfaces. */ + ret = netlink_request(AF_INET6, RTM_GETADDR, &zns->netlink_cmd); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface_addr, &zns->netlink_cmd, zns, + 0, 1); + if (ret < 0) + return ret; + + return 0; } /* Interface address modification. */ -static int -netlink_address (int cmd, int family, struct interface *ifp, - struct connected *ifc) +static int netlink_address(int cmd, int family, struct interface *ifp, + struct connected *ifc) { - int bytelen; - struct prefix *p; + int bytelen; + struct prefix *p; - struct - { - struct nlmsghdr n; - struct ifaddrmsg ifa; - char buf[NL_PKT_BUF_SIZE]; - } req; + struct { + struct nlmsghdr n; + struct ifaddrmsg ifa; + char buf[NL_PKT_BUF_SIZE]; + } req; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); - p = ifc->address; - memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); + p = ifc->address; + memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); - bytelen = (family == AF_INET ? 4 : 16); + bytelen = (family == AF_INET ? 4 : 16); - req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = cmd; - req.ifa.ifa_family = family; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = cmd; + req.ifa.ifa_family = family; - req.ifa.ifa_index = ifp->ifindex; - req.ifa.ifa_prefixlen = p->prefixlen; + req.ifa.ifa_index = ifp->ifindex; + req.ifa.ifa_prefixlen = p->prefixlen; - addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen); + addattr_l(&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen); - if (family == AF_INET && cmd == RTM_NEWADDR) - { - if (!CONNECTED_PEER(ifc) && ifc->destination) - { - p = ifc->destination; - addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, - bytelen); - } - } + if (family == AF_INET && cmd == RTM_NEWADDR) { + if (!CONNECTED_PEER(ifc) && ifc->destination) { + p = ifc->destination; + addattr_l(&req.n, sizeof req, IFA_BROADCAST, + &p->u.prefix, bytelen); + } + } - if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) - SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY); + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) + SET_FLAG(req.ifa.ifa_flags, IFA_F_SECONDARY); - if (ifc->label) - addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, - strlen (ifc->label) + 1); + if (ifc->label) + addattr_l(&req.n, sizeof req, IFA_LABEL, ifc->label, + strlen(ifc->label) + 1); - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } -int -kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc) +int kernel_address_add_ipv4(struct interface *ifp, struct connected *ifc) { - return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc); + return netlink_address(RTM_NEWADDR, AF_INET, ifp, ifc); } -int -kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc) +int kernel_address_delete_ipv4(struct interface *ifp, struct connected *ifc) { - return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc); + return netlink_address(RTM_DELADDR, AF_INET, ifp, ifc); } -int -netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +int netlink_interface_addr(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ifaddrmsg *ifa; - struct rtattr *tb[IFA_MAX + 1]; - struct interface *ifp; - void *addr; - void *broad; - u_char flags = 0; - char *label = NULL; - struct zebra_ns *zns; - - zns = zebra_ns_lookup (ns_id); - ifa = NLMSG_DATA (h); - - if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) - return 0; - - if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) - return 0; - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg)); - if (len < 0) - return -1; - - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len); - - ifp = if_lookup_by_index_per_ns (zns, ifa->ifa_index); - if (ifp == NULL) - { - zlog_err ("netlink_interface_addr can't find interface by index %d", - ifa->ifa_index); - return -1; - } - - if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ - { - char buf[BUFSIZ]; - zlog_debug ("netlink_interface_addr %s %s flags 0x%x:", - nl_msg_type_to_str (h->nlmsg_type), ifp->name, - ifa->ifa_flags); - if (tb[IFA_LOCAL]) - zlog_debug (" IFA_LOCAL %s/%d", - inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]), - buf, BUFSIZ), ifa->ifa_prefixlen); - if (tb[IFA_ADDRESS]) - zlog_debug (" IFA_ADDRESS %s/%d", - inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]), - buf, BUFSIZ), ifa->ifa_prefixlen); - if (tb[IFA_BROADCAST]) - zlog_debug (" IFA_BROADCAST %s/%d", - inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]), - buf, BUFSIZ), ifa->ifa_prefixlen); - if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL]))) - zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL])); - - if (tb[IFA_CACHEINFO]) - { - struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]); - zlog_debug (" IFA_CACHEINFO pref %d, valid %d", - ci->ifa_prefered, ci->ifa_valid); - } - } - - /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */ - if (tb[IFA_LOCAL] == NULL) - tb[IFA_LOCAL] = tb[IFA_ADDRESS]; - if (tb[IFA_ADDRESS] == NULL) - tb[IFA_ADDRESS] = tb[IFA_LOCAL]; - - /* local interface address */ - addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL); - - /* is there a peer address? */ - if (tb[IFA_ADDRESS] && - memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS]))) - { - broad = RTA_DATA(tb[IFA_ADDRESS]); - SET_FLAG (flags, ZEBRA_IFA_PEER); - } - else - /* seeking a broadcast address */ - broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL); - - /* addr is primary key, SOL if we don't have one */ - if (addr == NULL) - { - zlog_debug ("%s: NULL address", __func__); - return -1; - } - - /* Flags. */ - if (ifa->ifa_flags & IFA_F_SECONDARY) - SET_FLAG (flags, ZEBRA_IFA_SECONDARY); - - /* Label */ - if (tb[IFA_LABEL]) - label = (char *) RTA_DATA (tb[IFA_LABEL]); - - if (ifp && label && strcmp (ifp->name, label) == 0) - label = NULL; - - /* Register interface address to the interface. */ - if (ifa->ifa_family == AF_INET) - { - if (h->nlmsg_type == RTM_NEWADDR) - connected_add_ipv4 (ifp, flags, - (struct in_addr *) addr, ifa->ifa_prefixlen, - (struct in_addr *) broad, label); - else - connected_delete_ipv4 (ifp, flags, - (struct in_addr *) addr, ifa->ifa_prefixlen, - (struct in_addr *) broad); - } - if (ifa->ifa_family == AF_INET6) - { - if (h->nlmsg_type == RTM_NEWADDR) - { - /* Only consider valid addresses; we'll not get a notification from - * the kernel till IPv6 DAD has completed, but at init time, Quagga - * does query for and will receive all addresses. - */ - if (!(ifa->ifa_flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))) - connected_add_ipv6 (ifp, flags, (struct in6_addr *) addr, - ifa->ifa_prefixlen, (struct in6_addr *) broad, label); - } - else - connected_delete_ipv6 (ifp, - (struct in6_addr *) addr, ifa->ifa_prefixlen, - (struct in6_addr *) broad); - } - - return 0; + int len; + struct ifaddrmsg *ifa; + struct rtattr *tb[IFA_MAX + 1]; + struct interface *ifp; + void *addr; + void *broad; + u_char flags = 0; + char *label = NULL; + struct zebra_ns *zns; + + zns = zebra_ns_lookup(ns_id); + ifa = NLMSG_DATA(h); + + if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) + return 0; + + if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + if (len < 0) + return -1; + + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len); + + ifp = if_lookup_by_index_per_ns(zns, ifa->ifa_index); + if (ifp == NULL) { + zlog_err( + "netlink_interface_addr can't find interface by index %d", + ifa->ifa_index); + return -1; + } + + if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ + { + char buf[BUFSIZ]; + zlog_debug("netlink_interface_addr %s %s flags 0x%x:", + nl_msg_type_to_str(h->nlmsg_type), ifp->name, + ifa->ifa_flags); + if (tb[IFA_LOCAL]) + zlog_debug(" IFA_LOCAL %s/%d", + inet_ntop(ifa->ifa_family, + RTA_DATA(tb[IFA_LOCAL]), buf, + BUFSIZ), + ifa->ifa_prefixlen); + if (tb[IFA_ADDRESS]) + zlog_debug(" IFA_ADDRESS %s/%d", + inet_ntop(ifa->ifa_family, + RTA_DATA(tb[IFA_ADDRESS]), buf, + BUFSIZ), + ifa->ifa_prefixlen); + if (tb[IFA_BROADCAST]) + zlog_debug(" IFA_BROADCAST %s/%d", + inet_ntop(ifa->ifa_family, + RTA_DATA(tb[IFA_BROADCAST]), buf, + BUFSIZ), + ifa->ifa_prefixlen); + if (tb[IFA_LABEL] && strcmp(ifp->name, RTA_DATA(tb[IFA_LABEL]))) + zlog_debug(" IFA_LABEL %s", + (char *)RTA_DATA(tb[IFA_LABEL])); + + if (tb[IFA_CACHEINFO]) { + struct ifa_cacheinfo *ci = RTA_DATA(tb[IFA_CACHEINFO]); + zlog_debug(" IFA_CACHEINFO pref %d, valid %d", + ci->ifa_prefered, ci->ifa_valid); + } + } + + /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */ + if (tb[IFA_LOCAL] == NULL) + tb[IFA_LOCAL] = tb[IFA_ADDRESS]; + if (tb[IFA_ADDRESS] == NULL) + tb[IFA_ADDRESS] = tb[IFA_LOCAL]; + + /* local interface address */ + addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL); + + /* is there a peer address? */ + if (tb[IFA_ADDRESS] + && memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), + RTA_PAYLOAD(tb[IFA_ADDRESS]))) { + broad = RTA_DATA(tb[IFA_ADDRESS]); + SET_FLAG(flags, ZEBRA_IFA_PEER); + } else + /* seeking a broadcast address */ + broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) + : NULL); + + /* addr is primary key, SOL if we don't have one */ + if (addr == NULL) { + zlog_debug("%s: NULL address", __func__); + return -1; + } + + /* Flags. */ + if (ifa->ifa_flags & IFA_F_SECONDARY) + SET_FLAG(flags, ZEBRA_IFA_SECONDARY); + + /* Label */ + if (tb[IFA_LABEL]) + label = (char *)RTA_DATA(tb[IFA_LABEL]); + + if (ifp && label && strcmp(ifp->name, label) == 0) + label = NULL; + + /* Register interface address to the interface. */ + if (ifa->ifa_family == AF_INET) { + if (h->nlmsg_type == RTM_NEWADDR) + connected_add_ipv4(ifp, flags, (struct in_addr *)addr, + ifa->ifa_prefixlen, + (struct in_addr *)broad, label); + else + connected_delete_ipv4( + ifp, flags, (struct in_addr *)addr, + ifa->ifa_prefixlen, (struct in_addr *)broad); + } + if (ifa->ifa_family == AF_INET6) { + if (h->nlmsg_type == RTM_NEWADDR) { + /* Only consider valid addresses; we'll not get a + * notification from + * the kernel till IPv6 DAD has completed, but at init + * time, Quagga + * does query for and will receive all addresses. + */ + if (!(ifa->ifa_flags + & (IFA_F_DADFAILED | IFA_F_TENTATIVE))) + connected_add_ipv6( + ifp, flags, (struct in6_addr *)addr, + ifa->ifa_prefixlen, + (struct in6_addr *)broad, label); + } else + connected_delete_ipv6(ifp, (struct in6_addr *)addr, + ifa->ifa_prefixlen, + (struct in6_addr *)broad); + } + + return 0; } -int -netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ifinfomsg *ifi; - struct rtattr *tb[IFLA_MAX + 1]; - struct rtattr *linkinfo[IFLA_MAX + 1]; - struct interface *ifp; - char *name = NULL; - char *kind = NULL; - char *slave_kind = NULL; - int vrf_device = 0; - struct zebra_ns *zns; - vrf_id_t vrf_id = VRF_DEFAULT; - - zns = zebra_ns_lookup (ns_id); - ifi = NLMSG_DATA (h); - - if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) - { - /* If this is not link add/delete message so print warning. */ - zlog_warn ("netlink_link_change: wrong kernel message %d", - h->nlmsg_type); - return 0; - } - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg)); - if (len < 0) - return -1; - - if (ifi->ifi_family == AF_BRIDGE) - return 0; - - /* Looking up interface name. */ - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); + int len; + struct ifinfomsg *ifi; + struct rtattr *tb[IFLA_MAX + 1]; + struct rtattr *linkinfo[IFLA_MAX + 1]; + struct interface *ifp; + char *name = NULL; + char *kind = NULL; + char *slave_kind = NULL; + int vrf_device = 0; + struct zebra_ns *zns; + vrf_id_t vrf_id = VRF_DEFAULT; + + zns = zebra_ns_lookup(ns_id); + ifi = NLMSG_DATA(h); + + if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) { + /* If this is not link add/delete message so print warning. */ + zlog_warn("netlink_link_change: wrong kernel message %d", + h->nlmsg_type); + return 0; + } + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg)); + if (len < 0) + return -1; + + if (ifi->ifi_family == AF_BRIDGE) + return 0; + + /* Looking up interface name. */ + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); #ifdef IFLA_WIRELESS - /* check for wireless messages to ignore */ - if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); - return 0; - } + /* check for wireless messages to ignore */ + if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: ignoring IFLA_WIRELESS message", + __func__); + return 0; + } #endif /* IFLA_WIRELESS */ - if (tb[IFLA_IFNAME] == NULL) - return -1; - name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + if (tb[IFLA_IFNAME] == NULL) + return -1; + name = (char *)RTA_DATA(tb[IFLA_IFNAME]); - if (tb[IFLA_LINKINFO]) - { - memset (linkinfo, 0, sizeof linkinfo); - parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + if (tb[IFLA_LINKINFO]) { + memset(linkinfo, 0, sizeof linkinfo); + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); - if (linkinfo[IFLA_INFO_KIND]) - kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); + if (linkinfo[IFLA_INFO_KIND]) + kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); #if HAVE_DECL_IFLA_INFO_SLAVE_KIND - if (linkinfo[IFLA_INFO_SLAVE_KIND]) - slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); + if (linkinfo[IFLA_INFO_SLAVE_KIND]) + slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); #endif - if (kind && strcmp(kind, "vrf") == 0) - { - vrf_device = 1; - netlink_vrf_change(h, tb[IFLA_LINKINFO], name); - vrf_id = (vrf_id_t)ifi->ifi_index; - } - } - - /* See if interface is present. */ - ifp = if_lookup_by_name_per_ns (zns, name); + if (kind && strcmp(kind, "vrf") == 0) { + vrf_device = 1; + netlink_vrf_change(h, tb[IFLA_LINKINFO], name); + vrf_id = (vrf_id_t)ifi->ifi_index; + } + } - if (h->nlmsg_type == RTM_NEWLINK) - { - if (tb[IFLA_MASTER]) - { - if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) - vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + /* See if interface is present. */ + ifp = if_lookup_by_name_per_ns(zns, name); + + if (h->nlmsg_type == RTM_NEWLINK) { + if (tb[IFLA_MASTER]) { + if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) + vrf_id = + *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + } + + if (ifp == NULL + || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + /* Add interface notification from kernel */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK for %s(%u) (ifp %p) vrf_id %u flags 0x%x", + name, ifi->ifi_index, ifp, vrf_id, + ifi->ifi_flags); + + if (ifp == NULL) { + /* unknown interface */ + ifp = if_get_by_name(name, vrf_id); + } else { + /* pre-configured interface, learnt now */ + if (ifp->vrf_id != vrf_id) + if_update(ifp, name, strlen(name), + vrf_id); + } + + /* Update interface information. */ + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (vrf_device) + SET_FLAG(ifp->status, + ZEBRA_INTERFACE_VRF_LOOPBACK); + ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); + ifp->metric = 0; + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + + netlink_interface_update_hw_addr(tb, ifp); + + /* Inform clients, install any configured addresses. */ + if_add_update(ifp); + } else if (ifp->vrf_id != vrf_id) { + /* VRF change for an interface. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK vrf-change for %s(%u) " + "vrf_id %u -> %u flags 0x%x", + name, ifp->ifindex, ifp->vrf_id, vrf_id, + ifi->ifi_flags); + + if_handle_vrf_change(ifp, vrf_id); + } else { + /* Interface status change. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK status for %s(%u) flags 0x%x", + name, ifp->ifindex, ifi->ifi_flags); + + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); + ifp->metric = 0; + + netlink_interface_update_hw_addr(tb, ifp); + + if (if_is_no_ptm_operative(ifp)) { + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (!if_is_no_ptm_operative(ifp)) + if_down(ifp); + else if (if_is_operative(ifp)) + /* Must notify client daemons of new + * interface status. */ + zebra_interface_up_update(ifp); + } else { + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (if_is_operative(ifp)) + if_up(ifp); + } + } + } else { + /* Delete interface notification from kernel */ + if (ifp == NULL) { + zlog_warn("RTM_DELLINK for unknown interface %s(%u)", + name, ifi->ifi_index); + return 0; + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("RTM_DELLINK for %s(%u)", name, + ifp->ifindex); + + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); + + if (!vrf_device) + if_delete_update(ifp); } - if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - /* Add interface notification from kernel */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK for %s(%u) (ifp %p) vrf_id %u flags 0x%x", - name, ifi->ifi_index, ifp, vrf_id, ifi->ifi_flags); - - if (ifp == NULL) - { - /* unknown interface */ - ifp = if_get_by_name (name, vrf_id); - } - else - { - /* pre-configured interface, learnt now */ - if (ifp->vrf_id != vrf_id) - if_update (ifp, name, strlen(name), vrf_id); - } - - /* Update interface information. */ - set_ifindex(ifp, ifi->ifi_index, zns); - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (vrf_device) - SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 0; - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - - netlink_interface_update_hw_addr (tb, ifp); - - /* Inform clients, install any configured addresses. */ - if_add_update (ifp); - } - else if (ifp->vrf_id != vrf_id) - { - /* VRF change for an interface. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK vrf-change for %s(%u) " - "vrf_id %u -> %u flags 0x%x", - name, ifp->ifindex, ifp->vrf_id, - vrf_id, ifi->ifi_flags); - - if_handle_vrf_change (ifp, vrf_id); - } - else - { - /* Interface status change. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK status for %s(%u) flags 0x%x", - name, ifp->ifindex, ifi->ifi_flags); - - set_ifindex(ifp, ifi->ifi_index, zns); - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 0; - - netlink_interface_update_hw_addr (tb, ifp); - - if (if_is_no_ptm_operative (ifp)) - { - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (!if_is_no_ptm_operative (ifp)) - if_down (ifp); - else if (if_is_operative (ifp)) - /* Must notify client daemons of new interface status. */ - zebra_interface_up_update (ifp); - } - else - { - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (if_is_operative (ifp)) - if_up (ifp); - } - } - } - else - { - /* Delete interface notification from kernel */ - if (ifp == NULL) - { - zlog_warn ("RTM_DELLINK for unknown interface %s(%u)", - name, ifi->ifi_index); - return 0; - } - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_DELLINK for %s(%u)", name, ifp->ifindex); - - UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - - if (!vrf_device) - if_delete_update (ifp); - } - - return 0; + return 0; } /* Interface information read by netlink. */ -void -interface_list (struct zebra_ns *zns) +void interface_list(struct zebra_ns *zns) { - interface_lookup_netlink (zns); + interface_lookup_netlink(zns); } |
