void connected_down_ipv4(struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) return; PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ apply_mask_ipv4(&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ if (prefix_ipv4_any(&p)) return; /* Same logic as for connected_up_ipv4(): push the changes into the head. */ rib_delete_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST); rib_delete_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_MULTICAST); rib_update(); }
/* Lookup interface by IPv4 address. */ struct interface * if_lookup_address (struct in_addr src) { struct prefix addr; int bestlen = 0; struct listnode *cnode; struct interface *ifp = NULL; struct connected *c; struct interface *match = NULL; int idx = 0; addr.family = AF_INET; addr.u.prefix4 = src; addr.prefixlen = IPV4_MAX_BITLEN; while (idx < get_max_port ()) { for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) { if (c->address && (c->address->family == AF_INET) && prefix_match(CONNECTED_PREFIX(c), &addr) && (c->address->prefixlen > bestlen)) { bestlen = c->address->prefixlen; match = ifp; } } idx++; } return match; }
/* determine receiving interface by source of packet */ struct ospf_interface * ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src) { struct listnode *node; struct prefix_ipv4 addr; struct ospf_interface *oi, *match; addr.family = AF_INET; addr.prefix = src; addr.prefixlen = IPV4_MAX_BITLEN; match = NULL; for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) { if (oi->type == OSPF_IFTYPE_VIRTUALLINK) continue; if (if_is_loopback (oi->ifp)) continue; if (prefix_match (CONNECTED_PREFIX(oi->connected), (struct prefix *) &addr)) { if ( (match == NULL) || (match->address->prefixlen < oi->address->prefixlen) ) match = oi; } } return match; }
/* Called from if_up(). */ void connected_up_ipv4(struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) return; PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ apply_mask_ipv4(&p); /* In case of connected address is 0.0.0.0/0 we treat it tunnel address. */ if (prefix_ipv4_any(&p)) return; rib_add_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); rib_add_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST); rib_update(); }
/* * check if interface with given address is configured and * return it if yes. special treatment for PtP networks. */ struct ospf_interface * ospf_if_is_configured (struct ospf *ospf, struct in_addr *address) { struct listnode *node, *nnode; struct ospf_interface *oi; struct prefix_ipv4 addr; addr.family = AF_INET; addr.prefix = *address; addr.prefixlen = IPV4_MAX_PREFIXLEN; for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) if (oi->type != OSPF_IFTYPE_VIRTUALLINK) { if (oi->type == OSPF_IFTYPE_POINTOPOINT) { /* special leniency: match if addr is anywhere on peer subnet */ if (prefix_match(CONNECTED_PREFIX(oi->connected), (struct prefix *)&addr)) return oi; } else { if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4)) return oi; } } return NULL; }
/* Lookup interface by IPv4 address. */ struct interface * if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id) { struct listnode *node; struct prefix addr; int bestlen = 0; struct listnode *cnode; struct interface *ifp; struct connected *c; struct interface *match; addr.family = AF_INET; addr.u.prefix4 = src; addr.prefixlen = IPV4_MAX_BITLEN; match = NULL; for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) { if (c->address && (c->address->family == AF_INET) && prefix_match(CONNECTED_PREFIX(c), &addr) && (c->address->prefixlen > bestlen)) { bestlen = c->address->prefixlen; match = ifp; } } } return match; }
void connected_down_ipv6(struct interface *ifp, struct connected *ifc) { struct prefix_ipv6 p; if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) return; PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv6(&p); if (IN6_IS_ADDR_UNSPECIFIED(&p.prefix)) return; rib_delete_ipv6(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST); rib_update(); }
struct ospf_interface *ospf_if_lookup_by_prefix(struct ospf *ospf, struct prefix_ipv4 *p) { struct listnode *node; struct ospf_interface *oi; /* Check each Interface. */ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { if (oi->type != OSPF_IFTYPE_VIRTUALLINK) { struct prefix ptmp; prefix_copy(&ptmp, CONNECTED_PREFIX(oi->connected)); apply_mask(&ptmp); if (prefix_same(&ptmp, (struct prefix *)p)) return oi; } } return NULL; }
/* determine receiving interface by ifp and source address */ struct ospf_interface * ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src, struct interface *ifp) { struct route_node *rn; struct prefix_ipv4 addr; struct ospf_interface *oi, *match; addr.family = AF_INET; addr.prefix = src; addr.prefixlen = IPV4_MAX_BITLEN; match = NULL; for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) { oi = rn->info; if (!oi) /* oi can be NULL for PtP aliases */ continue; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) continue; if (if_is_loopback (oi->ifp)) continue; if (prefix_match (CONNECTED_PREFIX(oi->connected), (struct prefix *) &addr)) { if ( (match == NULL) || (match->address->prefixlen < oi->address->prefixlen) ) match = oi; } } return match; }
void connected_up_ipv6(struct interface *ifp, struct connected *ifc) { struct prefix_ipv6 p; if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) return; PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ apply_mask_ipv6(&p); #ifndef LINUX /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */ if (IN6_IS_ADDR_UNSPECIFIED(&p.prefix)) return; #endif rib_add_ipv6(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); rib_update(); }
/* Find the IPv4 address on our side that will be used when packets are sent to dst. */ struct connected * connected_lookup_address (struct interface *ifp, struct in_addr dst) { struct prefix addr; struct listnode *cnode; struct connected *c; struct connected *match; addr.family = AF_INET; addr.u.prefix4 = dst; addr.prefixlen = IPV4_MAX_BITLEN; match = NULL; for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) { if (c->address && (c->address->family == AF_INET) && prefix_match(CONNECTED_PREFIX(c), &addr) && (!match || (c->address->prefixlen > match->address->prefixlen))) match = c; } return match; }
void bgp_connected_delete (struct connected *ifc) { struct prefix p; struct prefix *addr; struct interface *ifp; struct bgp_node *rn; struct bgp_connected_ref *bc; ifp = ifc->ifp; if (if_is_loopback (ifp)) return; addr = ifc->address; if (addr->family == AF_INET) { PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv4 ((struct prefix_ipv4 *) &p); if (prefix_ipv4_any ((struct prefix_ipv4 *) &p)) return; bgp_address_del (addr); rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p); if (! rn) return; bc = rn->info; bc->refcnt--; if (bc->refcnt == 0) { XFREE (MTYPE_BGP_CONN, bc); rn->info = NULL; } bgp_unlock_node (rn); bgp_unlock_node (rn); } #ifdef HAVE_IPV6 else if (addr->family == AF_INET6) { PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv6 ((struct prefix_ipv6 *) &p); if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) return; if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) return; rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p); if (! rn) return; bc = rn->info; bc->refcnt--; if (bc->refcnt == 0) { XFREE (MTYPE_BGP_CONN, bc); rn->info = NULL; } bgp_unlock_node (rn); bgp_unlock_node (rn); } #endif /* HAVE_IPV6 */ }
void bgp_connected_add (struct connected *ifc) { struct prefix p; struct prefix *addr; struct interface *ifp; struct bgp_node *rn; struct bgp_connected_ref *bc; ifp = ifc->ifp; if (! ifp) return; if (if_is_loopback (ifp)) return; addr = ifc->address; if (addr->family == AF_INET) { PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv4 ((struct prefix_ipv4 *) &p); if (prefix_ipv4_any ((struct prefix_ipv4 *) &p)) return; bgp_address_add (addr); rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p); if (rn->info) { bc = rn->info; bc->refcnt++; } else { bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref)); bc->refcnt = 1; rn->info = bc; } } #ifdef HAVE_IPV6 else if (addr->family == AF_INET6) { PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv6 ((struct prefix_ipv6 *) &p); if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) return; if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) return; rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p); if (rn->info) { bc = rn->info; bc->refcnt++; } else { bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref)); bc->refcnt = 1; rn->info = bc; } } #endif /* HAVE_IPV6 */ }