/* Interface adding function */ int ifan_read (struct if_announcemsghdr *ifan) { struct interface *ifp; ifp = if_lookup_by_index (ifan->ifan_index); if (ifp == NULL && ifan->ifan_what == IFAN_ARRIVAL) { /* Create Interface */ ifp = if_get_by_name (ifan->ifan_name); ifp->ifindex = ifan->ifan_index; if_add_update (ifp); } else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE) { if_delete_update (ifp); if_delete (ifp); } if_get_flags (ifp); if_get_mtu (ifp); if_get_metric (ifp); if (IS_ZEBRA_DEBUG_KERNEL) zlog_info ("interface %s index %d", ifp->name, ifp->ifindex); return 0; }
/* Interface structure allocation by proc filesystem. */ int interface_list_proc () { FILE *fp; char buf[PROCBUFSIZ]; struct interface *ifp; char *name; /* Open /proc/net/dev. */ fp = fopen (_PATH_PROC_NET_DEV, "r"); if (fp == NULL) { zlog_warn ("Can't open proc file %s: %s", _PATH_PROC_NET_DEV, strerror (errno)); return -1; } /* Drop header lines. */ fgets (buf, PROCBUFSIZ, fp); fgets (buf, PROCBUFSIZ, fp); /* Only allocate interface structure. Other jobs will be done in if_ioctl.c. */ while (fgets (buf, PROCBUFSIZ, fp) != NULL) { interface_name_cut (buf, &name); ifp = if_get_by_name (name); if_add_update (ifp); } return 0; }
/* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ static int netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; struct ifinfomsg *ifi; struct rtattr *tb[IFLA_MAX + 1]; struct interface *ifp; 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; /* 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_DEBUG_HA(kroute, KROUTE)) 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]); /* Add interface. */ ifp = if_get_by_name (name); set_ifindex(ifp, ifi->ifi_index); ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; /* Hardware type and address. */ ifp->hw_type = ifi->ifi_type; netlink_interface_update_hw_addr (tb, ifp); if_add_update (ifp); return 0; }
/* Update interface's statistics. */ int ifstat_update_proc () { FILE *fp; char buf[PROCBUFSIZ]; int version; struct interface *ifp; char *stat; char *name; char *retval; /* Open /proc/net/dev. */ fp = fopen (_PATH_PROC_NET_DEV, "r"); if (fp == NULL) { zlog_warn ("Can't open proc file %s: %s", _PATH_PROC_NET_DEV, strerror (errno)); return -1; } /* Drop header lines. */ retval = fgets (buf, PROCBUFSIZ, fp); retval = fgets (buf, PROCBUFSIZ, fp); /* To detect proc format veresion, parse second line. */ if (strstr (buf, "compressed")) version = 3; else if (strstr (buf, "bytes")) version = 2; else version = 1; /* Update each interface's statistics. */ while (fgets (buf, PROCBUFSIZ, fp) != NULL) { stat = interface_name_cut (buf, &name); ifp = if_get_by_name (name); ifstat_dev_fields (version, stat, ifp); } fclose(fp); return 0; }
void sibling_ctrl_add_ctrl_client(unsigned int hostnum, char * ifname, char * area) { struct ctrl_client * ctrl_client; struct interface * ifp; struct ospf6_interface * oi; struct ospf6_area * oa; u_int32_t area_id; ctrl_client = ctrl_client_new(); ctrl_client->hostnum = hostnum; ctrl_client->inter_con = NULL; list_push_back(&ctrl_clients, &ctrl_client->node); /* find/create ospf6 interface */ ifp = if_get_by_name(ctrl_client->if_list, ifname); oi = (struct ospf6_interface *) ifp->info; if(oi == NULL) { oi = ospf6_interface_create(ifp); } /* parse Area-ID */ if (inet_pton (AF_INET, area, &area_id) != 1) { printf("Invalid Area-ID: %s\n", area); } /* find/create ospf6 area */ oa = ospf6_area_lookup (area_id, ospf6); if(oa == NULL) oa = ospf6_area_create(area_id, ospf6); /* attach interface to area */ list_push_back(&oa->if_list, &oi->node); oi->area = oa; /* start up */ thread_add_event(master, interface_up, oi, 0); }
int recv_features_reply(struct ctrl_client * ctrl_client, struct rfpbuf * buffer) { struct rfp_router_features * rrf = buffer->data; struct interface * ifp; int i; unsigned int ifindex; unsigned int mtu; int offset = offsetof(struct rfp_router_features, ports); size_t n_ports = ((ntohs(rrf->header.length) - offset) / sizeof(*rrf->ports)); if(IS_OSPF6_SIBLING_DEBUG_MSG) { zlog_notice("number of ports: %d", n_ports); } for(i = 0; i < n_ports; i++) { const struct rfp_phy_port * rpp = &rrf->ports[i]; ifindex = ntohs(rpp->port_no); mtu = ntohl(rpp->mtu); if(IS_OSPF6_SIBLING_DEBUG_MSG) { zlog_notice("port #: %d, name: %s, mtu: %d", ifindex, rpp->name, mtu); } /* create new interface if not created */ ifp = if_get_by_name(ctrl_client->if_list, rpp->name); // fill up the interface info ifp->ifindex = ifindex; // fill up the mtu ifp->mtu = mtu; // copy over the flags ifp->state = ntohl(rpp->state); ospf6_interface_if_add(ifp, ctrl_client); } return 0; }
// helper function void schedule_hellos_on_interfaces() { struct interface * ifp; struct ospf6_interface * oi; struct ctrl_client * ctrl_client; // if we already scheduled hellos, dont need to do it again if(scheduled_hellos) { return; } LIST_FOR_EACH(ctrl_client, struct ctrl_client, node, &ctrl_clients) { ifp = if_get_by_name(ctrl_client->if_list, ctrl_client->interface_name); oi = (struct ospf6_interface *)ifp->info; thread_add_event(master, ospf6_hello_send, oi, 0); } scheduled_hellos = true; }
int ifaddr_proc_ipv6 () { FILE *fp; char buf[PROCBUFSIZ]; int n; char addr[33]; char ifname[20]; int ifindex, plen, scope, status; struct interface *ifp; struct prefix_ipv6 p; /* Open proc file system. */ fp = fopen (_PATH_PROC_NET_IF_INET6, "r"); if (fp == NULL) { zlog_warn ("Can't open proc file %s: %s", _PATH_PROC_NET_IF_INET6, strerror (errno)); return -1; } /* Get interface's IPv6 address. */ while (fgets (buf, PROCBUFSIZ, fp) != NULL) { n = sscanf (buf, "%32s %02x %02x %02x %02x %20s", addr, &ifindex, &plen, &scope, &status, ifname); if (n != 6) continue; ifp = if_get_by_name (ifname); /* Fetch interface's IPv6 address. */ str2in6_addr (addr, &p.prefix); p.prefixlen = plen; connected_add_ipv6 (ifp, &p.prefix, p.prefixlen, NULL); } return 0; }
static int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; struct ifinfomsg *ifi; struct rtattr *tb[IFLA_MAX + 1]; struct interface *ifp; char *name; 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\n", h->nlmsg_type); return 0; } len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg)); if (len < 0) return -1; /* 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_DEBUG_HA(kroute, KROUTE)) 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]); /* Add interface. */ if (h->nlmsg_type == RTM_NEWLINK) { ifp = if_lookup_by_name (name); if (ifp == NULL || !CHECK_FLAG (ifp->status, KROUTE_INTERFACE_ACTIVE)) { if (ifp == NULL) ifp = if_get_by_name (name); set_ifindex(ifp, ifi->ifi_index); ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; netlink_interface_update_hw_addr (tb, ifp); /* If new link is added. */ if_add_update (ifp); } else { /* Interface status change. */ set_ifindex(ifp, ifi->ifi_index); ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; netlink_interface_update_hw_addr (tb, ifp); if (if_is_operative (ifp)) { ifp->flags = ifi->ifi_flags & 0x0000fffff; if (!if_is_operative (ifp)) if_down (ifp); else /* Must notify client daemons of new interface status. */ kroute_interface_up_update (ifp); } else { ifp->flags = ifi->ifi_flags & 0x0000fffff; if (if_is_operative (ifp)) if_up (ifp); } } } else { /* RTM_DELLINK. */ ifp = if_lookup_by_name (name); if (ifp == NULL) { zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find", name); return 0; } if_delete_update (ifp); } return 0; }
int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; struct ifinfomsg *ifi; struct rtattr *tb [IFLA_MAX + 1]; struct interface *ifp; char *name; 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\n", h->nlmsg_type); return 0; } len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg)); if (len < 0) return -1; /* Looking up interface name. */ memset (tb, 0, sizeof tb); netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); if (tb[IFLA_IFNAME] == NULL) return -1; name = (char *)RTA_DATA(tb[IFLA_IFNAME]); /* Add interface. */ if (h->nlmsg_type == RTM_NEWLINK) { ifp = if_lookup_by_name (name); if (ifp == NULL || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { if (ifp == NULL) ifp = if_get_by_name (name); ifp->ifindex = ifi->ifi_index; ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; /* If new link is added. */ if_add_update(ifp); } else { /* Interface status change. */ ifp->ifindex = ifi->ifi_index; ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; if (if_is_up (ifp)) { ifp->flags = ifi->ifi_flags & 0x0000fffff; if (! if_is_up (ifp)) if_down (ifp); } else { ifp->flags = ifi->ifi_flags & 0x0000fffff; if (if_is_up (ifp)) if_up (ifp); } } } else { /* RTM_DELLINK. */ ifp = if_lookup_by_name (name); if (ifp == NULL) { zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find", ifp->name); return 0; } if_delete_update (ifp); } return 0; }
/* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ int netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; struct ifinfomsg *ifi; struct rtattr *tb[IFLA_MAX + 1]; struct interface *ifp; char *name; int i; 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; /* Looking up interface name. */ memset (tb, 0, sizeof tb); netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); if (tb[IFLA_IFNAME] == NULL) return -1; name = (char *)RTA_DATA(tb[IFLA_IFNAME]); /* Add interface. */ ifp = if_get_by_name (name); ifp->ifindex = ifi->ifi_index; ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; /* Hardware type and address. */ ifp->hw_type = ifi->ifi_type; 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; } } if_add_update (ifp); return 0; }
/* Interface looking up using infamous SIOCGIFCONF. */ int interface_list_ioctl () { int ret; int sock; #define IFNUM_BASE 32 int ifnum; struct ifreq *ifreq; struct ifconf ifconf; struct interface_FOO *ifp; int n; int lastlen; /* Normally SIOCGIFCONF works with AF_INET socket. */ sock = socket (AF_INET, SOCK_DGRAM, 0); if (sock < 0) { zlog_warn ("Can't make AF_INET socket stream: %s", safe_strerror (errno)); return -1; } /* Set initial ifreq count. This will be double when SIOCGIFCONF fail. Solaris has SIOCGIFNUM. */ #ifdef SIOCGIFNUM ret = ioctl (sock, SIOCGIFNUM, &ifnum); if (ret < 0) ifnum = IFNUM_BASE; else ifnum++; #else ifnum = IFNUM_BASE; #endif /* SIOCGIFNUM */ ifconf.ifc_buf = NULL; lastlen = 0; /* Loop until SIOCGIFCONF success. */ for (;;) { ifconf.ifc_len = sizeof (struct ifreq) * ifnum; ifconf.ifc_buf = XREALLOC(MTYPE_TMP, ifconf.ifc_buf, ifconf.ifc_len); ret = ioctl(sock, SIOCGIFCONF, &ifconf); if (ret < 0) { zlog_warn ("SIOCGIFCONF: %s", safe_strerror(errno)); goto end; } /* Repeatedly get info til buffer fails to grow. */ if (ifconf.ifc_len > lastlen) { lastlen = ifconf.ifc_len; ifnum += 10; continue; } /* Success. */ break; } /* Allocate interface. */ ifreq = ifconf.ifc_req; #ifdef OPEN_BSD for (n = 0; n < ifconf.ifc_len; ) { int size; ifreq = (struct ifreq *)((caddr_t) ifconf.ifc_req + n); ifp = if_get_by_name (ifreq->ifr_name); if_add_update (ifp); size = ifreq->ifr_addr.sa_len; if (size < sizeof (ifreq->ifr_addr)) size = sizeof (ifreq->ifr_addr); size += sizeof (ifreq->ifr_name); n += size; } #else for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) { ifp = if_get_by_name (ifreq->ifr_name); if_add_update (ifp); ifreq++; } #endif /* OPEN_BSD */ end: close (sock); XFREE (MTYPE_TMP, ifconf.ifc_buf); return ret; }
/* * Called from interface_lookup_netlink(). This function is only used * during bootstrap. */ static int netlink_interface(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 *desc = NULL; char *slave_kind = NULL; struct zebra_ns *zns; vrf_id_t vrf_id = VRF_DEFAULT; zebra_iftype_t zif_type = ZEBRA_IF_OTHER; zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; ifindex_t bridge_ifindex = IFINDEX_INTERNAL; ifindex_t link_ifindex = IFINDEX_INTERNAL; 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) { zlog_err("%s: Message received from netlink is of a broken size: %d %zu", __PRETTY_FUNCTION__, h->nlmsg_len, (size_t)NLMSG_LENGTH(sizeof(struct ifinfomsg))); return -1; } /* We are interested in some AF_BRIDGE notifications. */ if (ifi->ifi_family == AF_BRIDGE) return netlink_bridge_interface(h, len, ns_id, startup); /* Looking up interface name. */ memset(tb, 0, sizeof tb); memset(linkinfo, 0, sizeof linkinfo); netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); /* 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; } if (tb[IFLA_IFNAME] == NULL) return -1; name = (char *)RTA_DATA(tb[IFLA_IFNAME]); if (tb[IFLA_IFALIAS]) desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]); if (tb[IFLA_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_SLAVE_KIND]) slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); netlink_determine_zebra_iftype(kind, &zif_type); } /* If VRF, create the VRF structure itself. */ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) { 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_is_backend_netns()) { zif_slave_type = ZEBRA_IF_SLAVE_VRF; vrf_id = *(uint32_t *)RTA_DATA(tb[IFLA_MASTER]); } else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) { zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; bridge_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); } else zif_slave_type = ZEBRA_IF_SLAVE_OTHER; } if (vrf_is_backend_netns()) vrf_id = (vrf_id_t)ns_id; /* If linking to another interface, note it. */ if (tb[IFLA_LINK]) link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); /* Add interface. */ ifp = if_get_by_name(name, vrf_id, 0); set_ifindex(ifp, ifi->ifi_index, zns); ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; ifp->speed = get_iflink_speed(ifp); ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; if (desc) ifp->desc = XSTRDUP(MTYPE_TMP, desc); /* Set zebra interface type */ zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); if (IS_ZEBRA_IF_VRF(ifp)) SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); /* Update link. */ zebra_if_update_link(ifp, link_ifindex); /* 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); /* Extract and save L2 interface information, take additional actions. */ netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], 1); if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) zebra_l2if_update_bridge_slave(ifp, bridge_ifindex); return 0; }
int netlink_link_change(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 *desc = NULL; char *slave_kind = NULL; struct zebra_ns *zns; vrf_id_t vrf_id = VRF_DEFAULT; zebra_iftype_t zif_type = ZEBRA_IF_OTHER; zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; ifindex_t bridge_ifindex = IFINDEX_INTERNAL; ifindex_t link_ifindex = IFINDEX_INTERNAL; zns = zebra_ns_lookup(ns_id); ifi = NLMSG_DATA(h); /* assume if not default zns, then new VRF */ 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; } if (!(ifi->ifi_family == AF_UNSPEC || ifi->ifi_family == AF_BRIDGE || ifi->ifi_family == AF_INET6)) { zlog_warn( "Invalid address family: %u received from kernel link change: %u", ifi->ifi_family, h->nlmsg_type); return 0; } len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg)); if (len < 0) { zlog_err("%s: Message received from netlink is of a broken size %d %zu", __PRETTY_FUNCTION__, h->nlmsg_len, (size_t)NLMSG_LENGTH(sizeof(struct ifinfomsg))); return -1; } /* We are interested in some AF_BRIDGE notifications. */ if (ifi->ifi_family == AF_BRIDGE) return netlink_bridge_interface(h, len, ns_id, startup); /* Looking up interface name. */ memset(tb, 0, sizeof tb); memset(linkinfo, 0, sizeof linkinfo); netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); /* 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; } if (tb[IFLA_IFNAME] == NULL) return -1; name = (char *)RTA_DATA(tb[IFLA_IFNAME]); if (tb[IFLA_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_SLAVE_KIND]) slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); netlink_determine_zebra_iftype(kind, &zif_type); } /* If linking to another interface, note it. */ if (tb[IFLA_LINK]) link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); if (tb[IFLA_IFALIAS]) { desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]); } /* If VRF, create or update the VRF structure itself. */ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) { 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 (ifp) { if (ifp->desc) XFREE(MTYPE_TMP, ifp->desc); if (desc) ifp->desc = XSTRDUP(MTYPE_TMP, desc); } if (h->nlmsg_type == RTM_NEWLINK) { if (tb[IFLA_MASTER]) { if (slave_kind && (strcmp(slave_kind, "vrf") == 0) && !vrf_is_backend_netns()) { zif_slave_type = ZEBRA_IF_SLAVE_VRF; vrf_id = *(uint32_t *)RTA_DATA(tb[IFLA_MASTER]); } else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) { zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; bridge_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); } else zif_slave_type = ZEBRA_IF_SLAVE_OTHER; } if (vrf_is_backend_netns()) vrf_id = (vrf_id_t)ns_id; if (ifp == NULL || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { /* Add interface notification from kernel */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d " "sl_type %d master %u flags 0x%x", name, ifi->ifi_index, vrf_id, zif_type, zif_slave_type, bridge_ifindex, ifi->ifi_flags); if (ifp == NULL) { /* unknown interface */ ifp = if_get_by_name(name, vrf_id, 0); } else { /* pre-configured interface, learnt now */ if (ifp->vrf_id != vrf_id) if_update_to_new_vrf(ifp, vrf_id); } /* Update interface information. */ set_ifindex(ifp, ifi->ifi_index, zns); ifp->flags = ifi->ifi_flags & 0x0000fffff; if (!tb[IFLA_MTU]) { zlog_warn( "RTM_NEWLINK for interface %s(%u) without MTU set", name, ifi->ifi_index); return 0; } ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; /* Set interface type */ zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); if (IS_ZEBRA_IF_VRF(ifp)) SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); /* Update link. */ zebra_if_update_link(ifp, link_ifindex); netlink_interface_update_hw_addr(tb, ifp); /* Inform clients, install any configured addresses. */ if_add_update(ifp); /* Extract and save L2 interface information, take * additional actions. */ netlink_interface_update_l2info( ifp, linkinfo[IFLA_INFO_DATA], 1); if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) zebra_l2if_update_bridge_slave(ifp, bridge_ifindex); if_netlink_check_ifp_instance_consistency(RTM_NEWLINK, ifp, ns_id); } 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 { int was_bridge_slave; /* Interface update. */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "RTM_NEWLINK update for %s(%u) " "sl_type %d master %u flags 0x%x", name, ifp->ifindex, zif_slave_type, bridge_ifindex, ifi->ifi_flags); set_ifindex(ifp, ifi->ifi_index, zns); if (!tb[IFLA_MTU]) { zlog_warn( "RTM_NEWLINK for interface %s(%u) without MTU set", name, ifi->ifi_index); return 0; } ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; /* Update interface type - NOTE: Only slave_type can * change. */ was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp); zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); 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 (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "Intf %s(%u) has gone DOWN", name, ifp->ifindex); if_down(ifp); } else if (if_is_operative(ifp)) { /* Must notify client daemons of new * interface status. */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "Intf %s(%u) PTM up, notifying clients", name, ifp->ifindex); zebra_interface_up_update(ifp); } } else { ifp->flags = ifi->ifi_flags & 0x0000fffff; if (if_is_operative(ifp)) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "Intf %s(%u) has come UP", name, ifp->ifindex); if_up(ifp); } } /* Extract and save L2 interface information, take * additional actions. */ netlink_interface_update_l2info( ifp, linkinfo[IFLA_INFO_DATA], 0); if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave) zebra_l2if_update_bridge_slave(ifp, bridge_ifindex); if_netlink_check_ifp_instance_consistency(RTM_NEWLINK, ifp, ns_id); } } 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); /* Special handling for bridge or VxLAN interfaces. */ if (IS_ZEBRA_IF_BRIDGE(ifp)) zebra_l2_bridge_del(ifp); else if (IS_ZEBRA_IF_VXLAN(ifp)) zebra_l2_vxlanif_del(ifp); if (!IS_ZEBRA_IF_VRF(ifp)) if_delete_update(ifp); if_netlink_check_ifp_instance_consistency(RTM_DELLINK, ifp, ns_id); } return 0; }