static int pim_zebra_if_add(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct interface *ifp; /* zebra api adds/dels interfaces using the same call interface_add_read below, see comments in lib/zclient.c */ ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); if (!ifp) return 0; if (PIM_DEBUG_ZEBRA) { zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu, if_is_operative(ifp)); } if (if_is_operative(ifp)) pim_if_addr_add_all(ifp); return 0; }
static int pim_zebra_if_del(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct interface *ifp; /* zebra api adds/dels interfaces using the same call interface_add_read below, see comments in lib/zclient.c comments in lib/zclient.c seem to indicate that calling zebra_interface_add_read is the correct call, but that results in an attemted out of bounds read which causes pimd to assert. Other clients use zebra_interface_state_read and it appears to work just fine. */ ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); if (!ifp) return 0; if (PIM_DEBUG_ZEBRA) { zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu, if_is_operative(ifp)); } if (!if_is_operative(ifp)) pim_if_addr_del_all(ifp); return 0; }
static int pim_zebra_if_state_up(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct interface *ifp; /* zebra api notifies interface up/down events by using the same call zebra_interface_state_read below, see comments in lib/zclient.c */ ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); if (!ifp) return 0; if (PIM_DEBUG_ZEBRA) { zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu, if_is_operative(ifp)); } if (if_is_operative(ifp)) { /* pim_if_addr_add_all() suffices for bringing up both IGMP and PIM */ pim_if_addr_add_all(ifp); } return 0; }
/* Multicast packet receive socket. */ static int rip_multicast_join (struct interface *ifp, int sock) { struct listnode *cnode; struct connected *ifc; if (if_is_operative (ifp) && if_is_multicast (ifp)) { if (IS_RIP_DEBUG_EVENT) zlog_debug ("multicast join at %s", ifp->name); for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc)) { struct prefix_ipv4 *p; struct in_addr group; p = (struct prefix_ipv4 *) ifc->address; if (p->family != AF_INET) continue; group.s_addr = htonl (INADDR_RIP_GROUP); if (ipv4_multicast_join (sock, group, p->prefix, ifp->ifindex) < 0) return -1; else return 0; } } return 0; }
/* This will be executed when interface goes up. */ static void rip_request_interface (struct interface *ifp) { struct rip_interface *ri; /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */ if (if_is_loopback (ifp)) return; /* If interface is down, don't send RIP packet. */ if (! if_is_operative (ifp)) return; /* Fetch RIP interface information. */ ri = ifp->info; /* If there is no version configuration in the interface, use rip's version setting. */ { int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? rip->version_send : ri->ri_send); if (vsend & RIPv1) rip_request_interface_send (ifp, RIPv1); if (vsend & RIPv2) rip_request_interface_send (ifp, RIPv2); } }
static int isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length) { struct interface *ifp; struct stream *s; s = zclient->ibuf; ifp = zebra_interface_state_read (s); if (!ifp) return 0; if (if_is_operative (ifp)) zlog_warn ("Zebra: got delete of %s, but interface is still up", ifp->name); if (isis->debugs & DEBUG_ZEBRA) zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d", ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu); /* Cannot call if_delete because we should retain the pseudo interface in case there is configuration info attached to it. */ if_delete_retain(ifp); isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp); ifp->ifindex = IFINDEX_INTERNAL; return 0; }
int isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length) { struct interface *ifp; struct stream *s; s = zclient->ibuf; ifp = zebra_interface_state_read (s); if (!ifp) return 0; if (if_is_operative (ifp)) zlog_warn ("Zebra: got delete of %s, but interface is still up", ifp->name); zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d", ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); if_delete (ifp); isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp); return 0; }
int isis_zebra_if_state_up (int command, struct zclient *zclient, zebra_size_t length) { struct interface *ifp; ifp = zebra_interface_if_lookup (zclient->ibuf); if (!ifp) return 0; if (if_is_operative (ifp)) { zebra_interface_if_set_value (zclient->ibuf, ifp); /* HT: This is wrong actually. We can't assume that circuit exist * if we delete circuit during if_state_down event. Needs rethink. * TODO */ isis_circuit_update_params (circuit_scan_by_ifp (ifp), ifp); return 0; } zebra_interface_if_set_value (zclient->ibuf, ifp); isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp); return 0; }
void if_refresh (struct interface *ifp) { if (if_is_operative (ifp)) { if_get_flags (ifp); if (! if_is_operative (ifp)) if_down (ifp); } else { if_get_flags (ifp); if (if_is_operative (ifp)) if_up (ifp); } }
static int bgp_interface_address_delete (int command, struct zclient *zclient, zebra_size_t length) { struct connected *ifc; ifc = zebra_interface_address_read (command, zclient->ibuf); if (ifc == NULL) return 0; if (BGP_DEBUG(zebra, ZEBRA)) { char buf[128]; prefix2str(ifc->address, buf, sizeof(buf)); zlog_debug("Zebra rcvd: interface %s address delete %s", ifc->ifp->name, buf); } if (if_is_operative (ifc->ifp)) bgp_connected_delete (ifc); connected_free (ifc); return 0; }
static void connected_announce (struct interface *ifp, struct connected *ifc) { if (!ifc) return; listnode_add (ifp->connected, ifc); /* Update interface address information to protocol daemon. */ if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) { if (ifc->address->family == AF_INET) if_subnet_add (ifp, ifc); SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); zebra_interface_address_add_update (ifp, ifc); if (if_is_operative(ifp)) { if (ifc->address->family == AF_INET) connected_up_ipv4 (ifp, ifc); #ifdef HAVE_IPV6 else connected_up_ipv6 (ifp, ifc); #endif } } }
int isis_zebra_if_address_add (int command, struct zclient *zclient, zebra_size_t length) { struct connected *c; struct prefix *p; char buf[BUFSIZ]; c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, zclient->ibuf); if (c == NULL) return 0; p = c->address; prefix2str (p, buf, BUFSIZ); #ifdef EXTREME_DEBUG if (p->family == AF_INET) zlog_debug ("connected IP address %s", buf); #ifdef HAVE_IPV6 if (p->family == AF_INET6) zlog_debug ("connected IPv6 address %s", buf); #endif /* HAVE_IPV6 */ #endif /* EXTREME_DEBUG */ if (if_is_operative (c->ifp)) isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c); return 0; }
/* Update the flags field of the ifp with the new flag set provided. * Take whatever actions are required for any changes in flags we care * about. * * newflags should be the raw value, as obtained from the OS. */ void if_flags_update (struct interface *ifp, uint64_t newflags) { if_flags_mangle (ifp, &newflags); if (if_is_operative (ifp)) { /* operative -> inoperative? */ ifp->flags = newflags; if (!if_is_operative (ifp)) if_down (ifp); } else { /* inoperative -> operative? */ ifp->flags = newflags; if (if_is_operative (ifp)) if_up (ifp); } }
static int pim_zebra_if_state_down(int command, struct zclient *zclient, zebra_size_t length) { struct interface *ifp; /* zebra api notifies interface up/down events by using the same call zebra_interface_state_read below, see comments in lib/zclient.c */ ifp = zebra_interface_state_read(zclient->ibuf); if (!ifp) return 0; zlog_info("INTERFACE DOWN: %s ifindex=%d", ifp->name, ifp->ifindex); if (PIM_DEBUG_ZEBRA) { zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu, if_is_operative(ifp)); } if (!if_is_operative(ifp)) { /* pim_if_addr_del_all() suffices for shutting down IGMP, but not for shutting down PIM */ pim_if_addr_del_all(ifp); /* pim_sock_delete() closes the socket, stops read and timer threads, and kills all neighbors. */ if (ifp->info) { pim_sock_delete(ifp, "link down"); } } return 0; }
/* This will be executed when interface goes up. */ static void stp_request_interface (struct interface *ifp) { /* In default stpd doesn't send RIP_REQUEST to the loopback interface. */ if (if_is_loopback (ifp)) return; /* If interface is down, don't send RIP packet. */ if (! if_is_operative (ifp)) return; }
static int isis_kroute_if_add (int command, struct zclient *zclient, kroute_size_t length) { struct interface *ifp; ifp = kroute_interface_add_read (zclient->ibuf); if (isis->debugs & DEBUG_KROUTE) zlog_debug ("Kroute I/F add: %s index %d flags %ld metric %d mtu %d", ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu); if (if_is_operative (ifp)) isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp); return 0; }
int isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length) { struct interface *ifp; ifp = zebra_interface_add_read (zclient->ibuf); zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d", ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); if (if_is_operative (ifp)) isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp); return 0; }
int isis_zebra_if_state_down (int command, struct zclient *zclient, zebra_size_t length) { struct interface *ifp; ifp = zebra_interface_if_lookup (zclient->ibuf); if (ifp == NULL) return 0; if (if_is_operative (ifp)) { zebra_interface_if_set_value (zclient->ibuf, ifp); isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp); } return 0; }
static int isis_zebra_if_address_del (int command, struct zclient *client, zebra_size_t length, vrf_id_t vrf_id) { struct connected *c; struct interface *ifp; #ifdef EXTREME_DEBUG struct prefix *p; u_char buf[BUFSIZ]; #endif /* EXTREME_DEBUG */ c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE, zclient->ibuf, vrf_id); if (c == NULL) return 0; ifp = c->ifp; #ifdef EXTREME_DEBUG p = c->address; prefix2str (p, buf, BUFSIZ); if (p->family == AF_INET) zlog_debug ("disconnected IP address %s", buf); #ifdef HAVE_IPV6 if (p->family == AF_INET6) zlog_debug ("disconnected IPv6 address %s", buf); #endif /* HAVE_IPV6 */ #endif /* EXTREME_DEBUG */ if (if_is_operative (ifp)) isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c); connected_free (c); return 0; }
static int rsvp_interface_state_up (int command, struct zclient *zclient, zebra_size_t length) { struct interface *ifp; ifp = zebra_interface_if_lookup (zclient->ibuf); if (ifp == NULL) return 0; /* Interface is already up. */ if (if_is_operative (ifp)) { /* Temporarily keep ifp values. */ struct interface if_tmp; memcpy (&if_tmp, ifp, sizeof (struct interface)); zebra_interface_if_set_value (zclient->ibuf, ifp); zlog_debug ("Zebra: Interface[%s] state update.", ifp->name); if (if_tmp.bandwidth != ifp->bandwidth) { zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.", ifp->name, if_tmp.bandwidth, ifp->bandwidth); } return 0; } zebra_interface_if_set_value (zclient->ibuf, ifp); zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name); 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; }
/* Update interface status. */ void rip_enable_apply (struct interface *ifp) { int ret; struct rip_interface *ri = NULL; /* Check interface. */ if (! if_is_operative (ifp)) return; ri = ifp->info; /* Check network configuration. */ ret = rip_enable_network_lookup_if (ifp); /* If the interface is matched. */ if (ret > 0) ri->enable_network = 1; else ri->enable_network = 0; /* Check interface name configuration. */ ret = rip_enable_if_lookup (ifp->name); if (ret >= 0) ri->enable_interface = 1; else ri->enable_interface = 0; /* any interface MUST have an IPv4 address */ if ( ! rip_if_ipv4_address_check (ifp) ) { ri->enable_network = 0; ri->enable_interface = 0; } /* Update running status of the interface. */ if (ri->enable_network || ri->enable_interface) { { if (IS_RIP_DEBUG_EVENT) zlog_debug ("turn on %s", ifp->name); /* Add interface wake up thread. */ if (! ri->t_wakeup) ri->t_wakeup = thread_add_timer (master, rip_interface_wakeup, ifp, 1); rip_connect_set (ifp, 1); } } else { if (ri->running) { /* Might as well clean up the route table as well * rip_if_down sets to 0 ri->running, and displays "turn off %s" **/ rip_if_down(ifp); rip_connect_set (ifp, 0); } } }
void eigrp_zebra_init(void) { struct zclient_options opt = {.receive_notify = false}; zclient = zclient_new_notify(master, &opt); zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs); zclient->zebra_connected = eigrp_zebra_connected; zclient->router_id_update = eigrp_router_id_update_zebra; zclient->interface_add = eigrp_interface_add; zclient->interface_delete = eigrp_interface_delete; zclient->interface_up = eigrp_interface_state_up; zclient->interface_down = eigrp_interface_state_down; zclient->interface_address_add = eigrp_interface_address_add; zclient->interface_address_delete = eigrp_interface_address_delete; zclient->redistribute_route_add = eigrp_zebra_read_route; zclient->redistribute_route_del = eigrp_zebra_read_route; zclient->route_notify_owner = eigrp_zebra_route_notify_owner; } /* Zebra route add and delete treatment. */ static int eigrp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct zapi_route api; struct eigrp *eigrp; if (zapi_route_decode(zclient->ibuf, &api) < 0) return -1; if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr))) return 0; eigrp = eigrp_lookup(); if (eigrp == NULL) return 0; if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ { } return 0; } /* Inteface addition message from zebra. */ static int eigrp_interface_add(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct interface *ifp; struct eigrp_interface *ei; ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); if (!ifp->info) return 0; ei = ifp->info; ei->params.type = eigrp_default_iftype(ifp); eigrp_if_update(ifp); return 0; } static int eigrp_interface_delete(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct interface *ifp; struct stream *s; s = zclient->ibuf; /* zebra_interface_state_read () updates interface structure in iflist */ ifp = zebra_interface_state_read(s, vrf_id); if (ifp == NULL) return 0; if (if_is_up(ifp)) zlog_warn("Zebra: got delete of %s, but interface is still up", ifp->name); if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) zlog_debug( "Zebra: interface delete %s index %d flags %llx metric %d mtu %d", ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); if (ifp->info) eigrp_if_free(ifp->info, INTERFACE_DOWN_BY_ZEBRA); if_set_index(ifp, IFINDEX_INTERNAL); return 0; } static int eigrp_interface_address_add(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct connected *c; c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); if (c == NULL) return 0; if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) { char buf[128]; prefix2str(c->address, buf, sizeof(buf)); zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf); } eigrp_if_update(c->ifp); return 0; } static int eigrp_interface_address_delete(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct connected *c; struct interface *ifp; struct eigrp_interface *ei; c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); if (c == NULL) return 0; if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) { char buf[128]; prefix2str(c->address, buf, sizeof(buf)); zlog_debug("Zebra: interface %s address delete %s", c->ifp->name, buf); } ifp = c->ifp; ei = ifp->info; if (!ei) return 0; /* Call interface hook functions to clean up */ eigrp_if_free(ei, INTERFACE_DOWN_BY_ZEBRA); connected_free(c); return 0; } static int eigrp_interface_state_up(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct interface *ifp; ifp = zebra_interface_if_lookup(zclient->ibuf); if (ifp == NULL) return 0; /* Interface is already up. */ if (if_is_operative(ifp)) { /* Temporarily keep ifp values. */ struct interface if_tmp; memcpy(&if_tmp, ifp, sizeof(struct interface)); zebra_interface_if_set_value(zclient->ibuf, ifp); if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) zlog_debug("Zebra: Interface[%s] state update.", ifp->name); if (if_tmp.bandwidth != ifp->bandwidth) { if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) zlog_debug( "Zebra: Interface[%s] bandwidth change %d -> %d.", ifp->name, if_tmp.bandwidth, ifp->bandwidth); // eigrp_if_recalculate_output_cost (ifp); } if (if_tmp.mtu != ifp->mtu) { if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) zlog_debug( "Zebra: Interface[%s] MTU change %u -> %u.", ifp->name, if_tmp.mtu, ifp->mtu); /* Must reset the interface (simulate down/up) when MTU * changes. */ eigrp_if_reset(ifp); } return 0; } zebra_interface_if_set_value(zclient->ibuf, ifp); if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) zlog_debug("Zebra: Interface[%s] state change to up.", ifp->name); if (ifp->info) eigrp_if_up(ifp->info); return 0; } static int eigrp_interface_state_down(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct interface *ifp; ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); if (ifp == NULL) return 0; if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) zlog_debug("Zebra: Interface[%s] state change to down.", ifp->name); if (ifp->info) eigrp_if_down(ifp->info); return 0; } static struct interface *zebra_interface_if_lookup(struct stream *s) { char ifname_tmp[INTERFACE_NAMSIZ]; /* Read interface name. */ stream_get(ifname_tmp, s, INTERFACE_NAMSIZ); /* And look it up. */ return if_lookup_by_name(ifname_tmp, VRF_DEFAULT); }
/* Wake up configured address if it is not in current kernel address. */ void if_addr_wakeup (struct interface *ifp) { struct listnode *node; struct connected *ifc; struct prefix *p; int ret; for (node = listhead (ifp->connected); node; nextnode (node)) { ifc = getdata (node); p = ifc->address; if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED) && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) { /* Address check. */ if (p->family == AF_INET) { if (! if_is_up (ifp)) { if_set_flags (ifp, IFF_UP | IFF_RUNNING); if_refresh (ifp); } ret = if_set_prefix (ifp, ifc); if (ret < 0) { zlog_warn ("Can't set interface's address: %s", safe_strerror(errno)); continue; } SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); zebra_interface_address_add_update (ifp, ifc); if (if_is_operative(ifp)) connected_up_ipv4 (ifp, ifc); } #ifdef HAVE_IPV6 if (p->family == AF_INET6) { if (! if_is_up (ifp)) { if_set_flags (ifp, IFF_UP | IFF_RUNNING); if_refresh (ifp); } ret = if_prefix_add_ipv6 (ifp, ifc); if (ret < 0) { zlog_warn ("Can't set interface's address: %s", safe_strerror(errno)); continue; } SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); zebra_interface_address_add_update (ifp, ifc); if (if_is_operative(ifp)) connected_up_ipv6 (ifp, ifc); } #endif /* HAVE_IPV6 */ } } }
static int ospf_interface_state_up (int command, struct zclient *zclient, zebra_size_t length) { struct interface *ifp; struct ospf_interface *oi; struct route_node *rn; ifp = zebra_interface_if_lookup (zclient->ibuf); if (ifp == NULL) return 0; /* Interface is already up. */ if (if_is_operative (ifp)) { /* Temporarily keep ifp values. */ struct interface if_tmp; memcpy (&if_tmp, ifp, sizeof (struct interface)); zebra_interface_if_set_value (zclient->ibuf, ifp); if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_debug ("Zebra: Interface[%s] state update.", ifp->name); if (if_tmp.bandwidth != ifp->bandwidth) { if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.", ifp->name, if_tmp.bandwidth, ifp->bandwidth); ospf_if_recalculate_output_cost (ifp); } if (if_tmp.mtu != ifp->mtu) { if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.", ifp->name, if_tmp.mtu, ifp->mtu); /* Must reset the interface (simulate down/up) when MTU changes. */ ospf_if_reset(ifp); } return 0; } zebra_interface_if_set_value (zclient->ibuf, ifp); if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name); for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) { if ((oi = rn->info) == NULL) continue; ospf_if_up (oi); } 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; }
void pim_if_addr_add(struct connected *ifc) { struct pim_interface *pim_ifp; struct interface *ifp; struct in_addr ifaddr; zassert(ifc); ifp = ifc->ifp; zassert(ifp); pim_ifp = ifp->info; if (!pim_ifp) return; if (!if_is_operative(ifp)) return; /* if (PIM_DEBUG_ZEBRA) */ { char buf[BUFSIZ]; prefix2str(ifc->address, buf, BUFSIZ); zlog_debug("%s: %s ifindex=%d connected IP address %s %s", __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf, CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary"); } ifaddr = ifc->address->u.prefix4; detect_address_change(ifp, 0, __PRETTY_FUNCTION__); if (PIM_IF_TEST_IGMP(pim_ifp->options)) { struct igmp_sock *igmp; /* lookup IGMP socket */ igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); if (!igmp) { /* if addr new, add IGMP socket */ pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp); } } /* igmp */ if (PIM_IF_TEST_PIM(pim_ifp->options)) { /* Interface has a valid primary address ? */ if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { /* Interface has a valid socket ? */ if (pim_ifp->pim_sock_fd < 0) { if (pim_sock_add(ifp)) { zlog_warn("Failure creating PIM socket for interface %s", ifp->name); } } } } /* pim */ if (PIM_MROUTE_IS_ENABLED) { /* PIM or IGMP is enabled on interface, and there is at least one address assigned, then try to create a vif_index. */ if (pim_ifp->mroute_vif_index < 0) { pim_if_add_vif(ifp); } } }
/* Wake up configured address if it is not in current kernel address. */ static void if_addr_wakeup (struct interface *ifp) { struct listnode *node, *nnode; struct connected *ifc; struct prefix *p; int ret; for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc)) { p = ifc->address; if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED) && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) { /* Address check. */ if (p->family == AF_INET) { if (! if_is_up (ifp)) { /* XXX: WTF is it trying to set flags here? * caller has just gotten a new interface, has been * handed the flags already. This code has no business * trying to override administrative status of the interface. * The only call path to here which doesn't originate from * kernel event is irdp - what on earth is it trying to do? * * further RUNNING is not a settable flag on any system * I (paulj) am aware of. */ if_set_flags (ifp, IFF_UP | IFF_RUNNING); if_refresh (ifp); } ret = if_set_prefix (ifp, ifc); if (ret < 0) { zlog_warn ("Can't set interface's address: %s", safe_strerror(errno)); continue; } /* Add to subnet chain list. */ if_subnet_add (ifp, ifc); SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); zebra_interface_address_add_update (ifp, ifc); if (if_is_operative(ifp)) connected_up_ipv4 (ifp, ifc); } #ifdef HAVE_IPV6 if (p->family == AF_INET6) { if (! if_is_up (ifp)) { /* XXX: See long comment above */ if_set_flags (ifp, IFF_UP | IFF_RUNNING); if_refresh (ifp); } ret = if_prefix_add_ipv6 (ifp, ifc); if (ret < 0) { zlog_warn ("Can't set interface's address: %s", safe_strerror(errno)); continue; } SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); zebra_interface_address_add_update (ifp, ifc); if (if_is_operative(ifp)) connected_up_ipv6 (ifp, ifc); } #endif /* HAVE_IPV6 */ } } }