/* Utility function of convert between struct isis_prefix <=> union sockunion. * FIXME This function isn't used anywhere. */ struct isis_prefix * sockunion2prefix (const union sockunion *dest, const union sockunion *mask) { if (dest->sa.sa_family == AF_INET) { struct prefix_ipv4 *p; p = isis_prefix_ipv4_new (); p->family = AF_INET; p->prefix = dest->sin.sin_addr; p->prefixlen = isis_ip_masklen (mask->sin.sin_addr); return (struct isis_prefix *) p; } #ifdef ENABLE_IPV6 if (dest->sa.sa_family == AF_INET6) { struct prefix_ipv6 *p; p = isis_prefix_ipv6_new (); p->family = AF_INET6; p->prefixlen = isis_ip6_masklen (mask->sin6.sin6_addr); memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr)); return (struct isis_prefix *) p; } #endif /* ENABLE_IPV6 */ return NULL; }
/* Utility function to convert ipv4 netmask to prefixes ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16" ex.) "1.0.0.0" NULL => "1.0.0.0/8" */ int netmask_isis_str2prefix_str (const char *net_str, const char *mask_str, char *prefix_str) { struct in_addr network; struct in_addr mask; u_char prefixlen; u_int32_t destination; int ret; ret = inet_aton (net_str, &network); if (! ret) return 0; if (mask_str) { ret = inet_aton (mask_str, &mask); if (! ret) return 0; prefixlen = isis_ip_masklen (mask); } else { destination = ntohl (network.s_addr); if (network.s_addr == 0) prefixlen = 0; else if (IN_CLASSC (destination)) prefixlen = 24; else if (IN_CLASSB (destination)) prefixlen = 16; else if (IN_CLASSA (destination)) prefixlen = 8; else return 0; } sprintf (prefix_str, "%s/%d", net_str, prefixlen); return 1; }
/* * C.2.6 Step 1 */ static int isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, uint32_t cost, uint16_t depth, int family) { struct listnode *node, *fragnode = NULL; u_int16_t dist; struct is_neigh *is_neigh; struct te_is_neigh *te_is_neigh; struct ipv4_reachability *ipreach; struct te_ipv4_reachability *te_ipv4_reach; enum vertextype vtype; struct isis_prefix prefix; #ifdef ENABLE_IPV6 struct ipv6_reachability *ip6reach; #endif /* ENABLE_IPV6 */ if (!lsp->adj) return ISIS_WARNING; if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family)) return ISIS_OK; lspfragloop: if (lsp->lsp_header->seq_num == 0) { Log(LOG_WARNING, "WARN ( default/core/ISIS ): isis_spf_process_lsp(): lsp with 0 seq_num - do not process\n"); return ISIS_WARNING; } if (!ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits)) { if (lsp->tlv_data.is_neighs) { for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh)) { /* C.2.6 a) */ /* Two way connectivity */ if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; dist = cost + is_neigh->metrics.metric_default; vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS : VTYPE_NONPSEUDO_IS; process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist, depth + 1, lsp->adj, family); } } if (lsp->tlv_data.te_is_neighs) { for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node, te_is_neigh)) { uint32_t metric; if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; memcpy (&metric, te_is_neigh->te_metric, 3); dist = cost + ntohl (metric << 8); vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS : VTYPE_NONPSEUDO_TE_IS; process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist, depth + 1, lsp->adj, family); } } if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs) { prefix.family = AF_INET; for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, node, ipreach)) { dist = cost + ipreach->metrics.metric_default; vtype = VTYPE_IPREACH_INTERNAL; prefix.u.prefix4 = ipreach->prefix; prefix.prefixlen = isis_ip_masklen (ipreach->mask); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, lsp->adj, family); } } if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs) { prefix.family = AF_INET; for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, node, ipreach)) { dist = cost + ipreach->metrics.metric_default; vtype = VTYPE_IPREACH_EXTERNAL; /* Set advertising router to the first IP address */ if (lsp->tlv_data.ipv4_addrs) { memcpy(&prefix.adv_router, listnode_head(lsp->tlv_data.ipv4_addrs), sizeof(struct in_addr)); } prefix.u.prefix4 = ipreach->prefix; prefix.prefixlen = isis_ip_masklen (ipreach->mask); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, lsp->adj, family); } }