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 } } }
/* Untie an interface address from its derived subnet list of addresses. */ int if_subnet_delete (struct interface *ifp, struct connected *ifc) { struct route_node *rn; struct zebra_if *zebra_if; struct list *addr_list; assert (ifp && ifp->info && ifc); zebra_if = ifp->info; /* Get address derived subnet node. */ rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address); if (! (rn && rn->info)) return -1; route_unlock_node (rn); /* Untie address from subnet's address list. */ addr_list = rn->info; listnode_delete (addr_list, ifc); route_unlock_node (rn); /* Return list element count, if not empty. */ if (addr_list->count) { /* If deleted address is primary, mark subsequent one as such and distribute. */ if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) { ifc = listgetdata (listhead (addr_list)); zebra_interface_address_delete_update (ifp, ifc); UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); zebra_interface_address_add_update (ifp, ifc); } return addr_list->count; } /* Otherwise, free list and route node. */ list_free (addr_list); rn->info = NULL; route_unlock_node (rn); 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); /*gjd : add for Rtsuit restart, ip address not write show running .So use add flag RTMD_RESTART_IP_CONFIG , when set it by netlink info from kernel through the IFA_BROADCAST. Becaus when setup vrrp , the virtual ip will insert, the IFA_BROADCAST will not get from kenerl . 2011-12-20 pm 7:00*/ if((!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) &&(keep_kernel_mode == 1) &&(CHECK_FLAG(ifc->ip_config,RTMD_RESTART_IP_CONFIG))) { SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); /*zlog_err("%s : line %d ifc->conf(%u), ifc->ipconfig(%u).\n", __func__,__LINE__,ifc->conf,ifc->ip_config);*/ } if(ifp && (strncmp(ifp->name,"lo",2)==0)&&(!LOOPBACK(ifc->address->u.prefix4.s_addr))) SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); zebra_interface_address_add_update (ifp, ifc); if (if_is_up(ifp)) { if (ifc->address->family == AF_INET) connected_up_ipv4 (ifp, ifc); #ifdef HAVE_IPV6 else connected_up_ipv6 (ifp, ifc); #endif } } }
/* 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", strerror(errno)); continue; } SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); zebra_interface_address_add_update (ifp, ifc); if (if_is_up(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", strerror(errno)); continue; } SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); zebra_interface_address_add_update (ifp, ifc); if (if_is_up(ifp)) connected_up_ipv6 (ifp, ifc); } #endif /* HAVE_IPV6 */ } } }
/* 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 */ } } }
/* Untie an interface address from its derived subnet list of addresses. */ int if_subnet_delete (struct interface *ifp, struct connected *ifc) { struct route_node *rn; struct zebra_if *zebra_if; struct list *addr_list; assert (ifp && ifp->info && ifc); zebra_if = ifp->info; /* Get address derived subnet node. */ rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address); if (! (rn && rn->info)) { zlog_warn("Trying to remove an address from an unknown subnet." " (please report this bug)"); return -1; } route_unlock_node (rn); /* Untie address from subnet's address list. */ addr_list = rn->info; /* Deleting an address that is not registered is a bug. * In any case, we shouldn't decrement the lock counter if the address * is unknown. */ if (!listnode_lookup(addr_list, ifc)) { zlog_warn("Trying to remove an address from a subnet where it is not" " currently registered. (please report this bug)"); return -1; } listnode_delete (addr_list, ifc); route_unlock_node (rn); /* Return list element count, if not empty. */ if (addr_list->count) { /* If deleted address is primary, mark subsequent one as such and distribute. */ if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) { ifc = listgetdata (listhead (addr_list)); zebra_interface_address_delete_update (ifp, ifc); UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); /* XXX: Linux kernel removes all the secondary addresses when the primary * address is removed. We could try to work around that, though this is * non-trivial. */ zebra_interface_address_add_update (ifp, ifc); } return addr_list->count; } /* Otherwise, free list and route node. */ list_free (addr_list); rn->info = NULL; route_unlock_node (rn); return 0; }