/* `match ipv6 address prefix-list PREFIX_LIST' */ static route_map_result_t route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; if(type == RMAP_ISIS) { plist = prefix_list_lookup(AFI_IP6, (s8 *) rule); if (plist == NULL) { return RMAP_NOMATCH; } if( FILTER_DENY == prefix_list_apply(plist, prefix) ) { return RMAP_NOMATCH; } else { return RMAP_MATCH; } } return RMAP_NOMATCH; }
int ospf_abr_plist_out_check (struct ospf_area *area, struct ospf_route *or, struct prefix *p) { if (PREFIX_NAME_OUT (area)) { if (PREFIX_LIST_OUT (area) == NULL) PREFIX_LIST_OUT (area) = prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area)); if (PREFIX_LIST_OUT (area)) if (prefix_list_apply (PREFIX_LIST_OUT (area), p) != PREFIX_PERMIT) return 0; } return 1; }
static route_map_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; if (type != RMAP_ISIS) return RMAP_NOMATCH; plist = prefix_list_lookup(AFI_IP, (char *)rule); if (prefix_list_apply(plist, prefix) != PREFIX_DENY) return RMAP_MATCH; return RMAP_NOMATCH; }
route_map_result_t route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; if (type == RMAP_RIP) { plist = prefix_list_lookup (AFI_IP, (char *) rule); if (plist == NULL) return RMAP_NOMATCH; return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH : RMAP_MATCH); } return RMAP_NOMATCH; }
static route_map_result_t route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; struct external_info *ei = object; struct prefix_ipv4 p; if (type == RMAP_OSPF) { p.family = AF_INET; p.prefix = ei->nexthop; p.prefixlen = IPV4_MAX_BITLEN; plist = prefix_list_lookup (AFI_IP, (char *) rule); if (plist == NULL) return RMAP_NOMATCH; return (prefix_list_apply (plist, &p) == PREFIX_DENY ? RMAP_NOMATCH : RMAP_MATCH); } return RMAP_NOMATCH; }
static route_map_result_t route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; struct rip_info *rinfo; struct prefix_ipv4 p; if (type == RMAP_RIP) { rinfo = object; p.family = AF_INET; p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; p.prefixlen = IPV4_MAX_BITLEN; plist = prefix_list_lookup (AFI_IP, (char *) rule); if (plist == NULL) return RMAP_NOMATCH; return (prefix_list_apply (plist, &p) == PREFIX_DENY ? RMAP_NOMATCH : RMAP_MATCH); } return RMAP_NOMATCH; }
void ospf6_interface_connected_route_update (struct interface *ifp) { struct ospf6_interface *oi; struct ospf6_route *route; struct connected *c; struct listnode *node, *nnode; oi = (struct ospf6_interface *) ifp->info; if (oi == NULL) return; /* reset linklocal pointer */ oi->linklocal_addr = ospf6_interface_get_linklocal_address (ifp); /* if area is null, do not make connected-route list */ if (oi->area == NULL) return; /* update "route to advertise" interface route table */ ospf6_route_remove_all (oi->route_connected); for (ALL_LIST_ELEMENTS (oi->interface->connected, node, nnode, c)) { if (c->address->family != AF_INET6) continue; CONTINUE_IF_ADDRESS_LINKLOCAL (IS_OSPF6_DEBUG_INTERFACE, c->address); CONTINUE_IF_ADDRESS_UNSPECIFIED (IS_OSPF6_DEBUG_INTERFACE, c->address); CONTINUE_IF_ADDRESS_LOOPBACK (IS_OSPF6_DEBUG_INTERFACE, c->address); CONTINUE_IF_ADDRESS_V4COMPAT (IS_OSPF6_DEBUG_INTERFACE, c->address); CONTINUE_IF_ADDRESS_V4MAPPED (IS_OSPF6_DEBUG_INTERFACE, c->address); /* apply filter */ if (oi->plist_name) { struct prefix_list *plist; enum prefix_list_type ret; char buf[128]; prefix2str (c->address, buf, sizeof (buf)); plist = prefix_list_lookup (AFI_IP6, oi->plist_name); ret = prefix_list_apply (plist, (void *) c->address); if (ret == PREFIX_DENY) { if (IS_OSPF6_DEBUG_INTERFACE) zlog_debug ("%s on %s filtered by prefix-list %s ", buf, oi->interface->name, oi->plist_name); continue; } } route = ospf6_route_create (); memcpy (&route->prefix, c->address, sizeof (struct prefix)); apply_mask (&route->prefix); route->type = OSPF6_DEST_TYPE_NETWORK; route->path.area_id = oi->area->area_id; route->path.type = OSPF6_PATH_TYPE_INTRA; route->path.cost = oi->cost; route->nexthop[0].ifindex = oi->interface->ifindex; inet_pton (AF_INET6, "::1", &route->nexthop[0].address); ospf6_route_add (route, oi->route_connected); } /* create new Link-LSA */ OSPF6_LINK_LSA_SCHEDULE (oi); OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); }
int babel_filter(int output, const unsigned char *prefix, unsigned short plen, unsigned int ifindex) { struct interface *ifp = if_lookup_by_index(ifindex); babel_interface_nfo *babel_ifp = ifp ? babel_get_if_nfo(ifp) : NULL; struct prefix p; struct distribute *dist; struct access_list *alist; struct prefix_list *plist; int filter = output ? BABEL_FILTER_OUT : BABEL_FILTER_IN; int distribute = output ? DISTRIBUTE_OUT : DISTRIBUTE_IN; p.family = v4mapped(prefix) ? AF_INET : AF_INET6; p.prefixlen = v4mapped(prefix) ? plen - 96 : plen; if (p.family == AF_INET) uchar_to_inaddr(&p.u.prefix4, prefix); #ifdef HAVE_IPV6 else uchar_to_in6addr(&p.u.prefix6, prefix); #endif if (babel_ifp != NULL && babel_ifp->list[filter]) { if (access_list_apply (babel_ifp->list[filter], &p) == FILTER_DENY) { debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in", #ifdef HAVE_IPV6 p.family == AF_INET ? inet_ntoa(p.u.prefix4) : inet6_ntoa (p.u.prefix6), #else inet_ntoa(p.u.prefix4), #endif p.prefixlen); return INFINITY; } } if (babel_ifp != NULL && babel_ifp->prefix[filter]) { if (prefix_list_apply (babel_ifp->prefix[filter], &p) == PREFIX_DENY) { debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in", #ifdef HAVE_IPV6 p.family == AF_INET ? inet_ntoa(p.u.prefix4) : inet6_ntoa (p.u.prefix6), #else inet_ntoa(p.u.prefix4), #endif p.prefixlen); return INFINITY; } } /* All interface filter check. */ dist = distribute_lookup (NULL); if (dist) { if (dist->list[distribute]) { alist = access_list_lookup (AFI_IP6, dist->list[distribute]); if (alist) { if (access_list_apply (alist, &p) == FILTER_DENY) { debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in", #ifdef HAVE_IPV6 p.family == AF_INET ? inet_ntoa(p.u.prefix4) : inet6_ntoa (p.u.prefix6), #else inet_ntoa(p.u.prefix4), #endif p.prefixlen); return INFINITY; } } } if (dist->prefix[distribute]) { plist = prefix_list_lookup (AFI_IP6, dist->prefix[distribute]); if (plist) { if (prefix_list_apply (plist, &p) == PREFIX_DENY) { debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in", #ifdef HAVE_IPV6 p.family == AF_INET ? inet_ntoa(p.u.prefix4) : inet6_ntoa (p.u.prefix6), #else inet_ntoa(p.u.prefix4), #endif p.prefixlen); return INFINITY; } } } } return 0; }
/* RFC 2328 16.2. Calculating the inter-area routes */ void ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa) { struct prefix prefix, abr_prefix; struct ospf6_route_table *table = NULL; struct ospf6_route *range, *route, *old = NULL; struct ospf6_route *abr_entry; u_char type = 0; char options[3] = {0, 0, 0}; u_int8_t prefix_options = 0; u_int32_t cost = 0; u_char router_bits = 0; int i; char buf[64]; int is_debug = 0; struct ospf6_inter_prefix_lsa *prefix_lsa = NULL; struct ospf6_inter_router_lsa *router_lsa = NULL; memset (&prefix, 0, sizeof (prefix)); if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX)) { if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX)) { is_debug++; zlog_debug ("Examin %s in area %s", lsa->name, oa->name); } prefix_lsa = (struct ospf6_inter_prefix_lsa *) OSPF6_LSA_HEADER_END (lsa->header); prefix.family = AF_INET6; prefix.prefixlen = prefix_lsa->prefix.prefix_length; ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix); if (is_debug) prefix2str (&prefix, buf, sizeof (buf)); table = oa->ospf6->route_table; type = OSPF6_DEST_TYPE_NETWORK; prefix_options = prefix_lsa->prefix.prefix_options; cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa); } else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER)) { if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER)) { is_debug++; zlog_debug ("Examin %s in area %s", lsa->name, oa->name); } router_lsa = (struct ospf6_inter_router_lsa *) OSPF6_LSA_HEADER_END (lsa->header); ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix); if (is_debug) inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf)); table = oa->ospf6->brouter_table; type = OSPF6_DEST_TYPE_ROUTER; options[0] = router_lsa->options[0]; options[1] = router_lsa->options[1]; options[2] = router_lsa->options[2]; cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa); SET_FLAG (router_bits, OSPF6_ROUTER_BIT_E); } else assert (0); /* Find existing route */ route = ospf6_route_lookup (&prefix, table); if (route) ospf6_route_lock (route); while (route && ospf6_route_is_prefix (&prefix, route)) { if (route->path.area_id == oa->area_id && route->path.origin.type == lsa->header->type && route->path.origin.id == lsa->header->id && route->path.origin.adv_router == lsa->header->adv_router && ! CHECK_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED)) old = route; route = ospf6_route_next (route); } /* (1) if cost == LSInfinity or if the LSA is MaxAge */ if (cost == OSPF_LS_INFINITY) { if (is_debug) zlog_debug ("cost is LS_INFINITY, ignore"); if (old) ospf6_route_remove (old, table); return; } if (OSPF6_LSA_IS_MAXAGE (lsa)) { if (is_debug) zlog_debug ("LSA is MaxAge, ignore"); if (old) ospf6_route_remove (old, table); return; } /* (2) if the LSA is self-originated, ignore */ if (lsa->header->adv_router == oa->ospf6->router_id) { if (is_debug) zlog_debug ("LSA is self-originated, ignore"); if (old) ospf6_route_remove (old, table); return; } /* (3) if the prefix is equal to an active configured address range */ /* or if the NU bit is set in the prefix */ if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX)) { range = ospf6_route_lookup (&prefix, oa->range_table); if (range) { if (is_debug) zlog_debug ("Prefix is equal to address range, ignore"); if (old) ospf6_route_remove (old, table); return; } if (CHECK_FLAG (prefix_lsa->prefix.prefix_options, OSPF6_PREFIX_OPTION_NU) || CHECK_FLAG (prefix_lsa->prefix.prefix_options, OSPF6_PREFIX_OPTION_LA)) { if (is_debug) zlog_debug ("Prefix has NU/LA bit set, ignore"); if (old) ospf6_route_remove (old, table); return; } } if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER)) { /* To pass test suites */ if (! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_R) || ! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_V6)) { if (is_debug) zlog_debug ("Prefix has NU/LA bit set, ignore"); if (old) ospf6_route_remove (old, table); return; } } /* (4) if the routing table entry for the ABR does not exist */ ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix); abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table); if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id || CHECK_FLAG (abr_entry->flag, OSPF6_ROUTE_REMOVE) || ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) { if (is_debug) zlog_debug ("ABR router entry does not exist, ignore"); if (old) ospf6_route_remove (old, table); return; } /* Check import list */ if (IMPORT_NAME (oa)) { if (IMPORT_LIST (oa) == NULL) IMPORT_LIST (oa) = access_list_lookup (AFI_IP6, IMPORT_NAME (oa)); if (IMPORT_LIST (oa)) if (access_list_apply (IMPORT_LIST (oa), &prefix) == FILTER_DENY) { if (is_debug) zlog_debug ("Prefix was denied by import-list"); if (old) ospf6_route_remove (old, table); return; } } /* Check input prefix-list */ if (PREFIX_NAME_IN (oa)) { if (PREFIX_LIST_IN (oa) == NULL) PREFIX_LIST_IN (oa) = prefix_list_lookup (AFI_IP6, PREFIX_NAME_IN (oa)); if (PREFIX_LIST_IN (oa)) if (prefix_list_apply (PREFIX_LIST_IN (oa), &prefix) != PREFIX_PERMIT) { if (is_debug) zlog_debug ("Prefix was denied by prefix-list"); if (old) ospf6_route_remove (old, table); return; } } /* (5),(6),(7) the path preference is handled by the sorting in the routing table. Always install the path by substituting old route (if any). */ if (old) route = ospf6_route_copy (old); else route = ospf6_route_create (); route->type = type; route->prefix = prefix; route->path.origin.type = lsa->header->type; route->path.origin.id = lsa->header->id; route->path.origin.adv_router = lsa->header->adv_router; route->path.router_bits = router_bits; route->path.options[0] = options[0]; route->path.options[1] = options[1]; route->path.options[2] = options[2]; route->path.prefix_options = prefix_options; route->path.area_id = oa->area_id; route->path.type = OSPF6_PATH_TYPE_INTER; route->path.cost = abr_entry->path.cost + cost; for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++) route->nexthop[i] = abr_entry->nexthop[i]; if (is_debug) zlog_debug ("Install route: %s", buf); ospf6_route_add (route, table); }
/* RFC 2328 12.4.3. Summary-LSAs */ void ospf6_abr_originate_summary_to_area (struct ospf6_route *route, struct ospf6_area *area) { struct ospf6_lsa *lsa, *old = NULL; struct ospf6_interface *oi; struct ospf6_route *summary, *range = NULL; struct ospf6_area *route_area; char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa_header *lsa_header; caddr_t p; struct ospf6_inter_prefix_lsa *prefix_lsa; struct ospf6_inter_router_lsa *router_lsa; struct ospf6_route_table *summary_table = NULL; u_int16_t type; char buf[64]; int is_debug = 0; if (route->type == OSPF6_DEST_TYPE_ROUTER) { if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER)) { is_debug++; inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), buf, sizeof (buf)); zlog_debug ("Originating summary in area %s for ASBR %s", area->name, buf); } summary_table = area->summary_router; } else { if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX)) { is_debug++; prefix2str (&route->prefix, buf, sizeof (buf)); zlog_debug ("Originating summary in area %s for %s", area->name, buf); } summary_table = area->summary_prefix; } summary = ospf6_route_lookup (&route->prefix, summary_table); if (summary) old = ospf6_lsdb_lookup (summary->path.origin.type, summary->path.origin.id, area->ospf6->router_id, area->lsdb); /* if this route has just removed, remove corresponding LSA */ if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE)) { if (is_debug) zlog_debug ("The route has just removed, purge previous LSA"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* Only destination type network, range or ASBR are considered */ if (route->type != OSPF6_DEST_TYPE_NETWORK && route->type != OSPF6_DEST_TYPE_RANGE && (route->type != OSPF6_DEST_TYPE_ROUTER || ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E))) { if (is_debug) zlog_debug ("Route type is none of network, range nor ASBR, withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* AS External routes are never considered */ if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 || route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) { if (is_debug) zlog_debug ("Path type is external, withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* do not generate if the path's area is the same as target area */ if (route->path.area_id == area->area_id) { if (is_debug) zlog_debug ("The route is in the area itself, ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* do not generate if the nexthops belongs to the target area */ oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex); if (oi && oi->area && oi->area == area) { if (is_debug) zlog_debug ("The route's nexthop is in the same area, ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* do not generate if the route cost is greater or equal to LSInfinity */ if (route->path.cost >= OSPF_LS_INFINITY) { if (is_debug) zlog_debug ("The cost exceeds LSInfinity, withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* if this is a route to ASBR */ if (route->type == OSPF6_DEST_TYPE_ROUTER) { /* Only the prefered best path is considered */ if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)) { if (is_debug) zlog_debug ("This is the secondary path to the ASBR, ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* Do not generate if the area is stub */ /* XXX */ } /* if this is an intra-area route, this may be suppressed by aggregation */ if (route->type == OSPF6_DEST_TYPE_NETWORK && route->path.type == OSPF6_PATH_TYPE_INTRA) { /* search for configured address range for the route's area */ route_area = ospf6_area_lookup (route->path.area_id, area->ospf6); assert (route_area); range = ospf6_route_lookup_bestmatch (&route->prefix, route_area->range_table); /* ranges are ignored when originate backbone routes to transit area. Otherwise, if ranges are configured, the route is suppressed. */ if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) && (route->path.area_id != OSPF_AREA_BACKBONE || ! IS_AREA_TRANSIT (area))) { if (is_debug) { prefix2str (&range->prefix, buf, sizeof (buf)); zlog_debug ("Suppressed by range %s of area %s", buf, route_area->name); } if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } } /* If this is a configured address range */ if (route->type == OSPF6_DEST_TYPE_RANGE) { /* If DoNotAdvertise is set */ if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) { if (is_debug) zlog_debug ("This is the range with DoNotAdvertise set. ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* Whether the route have active longer prefix */ if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) { if (is_debug) zlog_debug ("The range is not active. withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } } /* Check export list */ if (EXPORT_NAME (area)) { if (EXPORT_LIST (area) == NULL) EXPORT_LIST (area) = access_list_lookup (AFI_IP6, EXPORT_NAME (area)); if (EXPORT_LIST (area)) if (access_list_apply (EXPORT_LIST (area), &route->prefix) == FILTER_DENY) { if (is_debug) { inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), buf, sizeof(buf)); zlog_debug ("prefix %s was denied by export list", buf); } return; } } /* Check filter-list */ if (PREFIX_NAME_OUT (area)) { if (PREFIX_LIST_OUT (area) == NULL) PREFIX_LIST_OUT (area) = prefix_list_lookup(AFI_IP6, PREFIX_NAME_OUT (area)); if (PREFIX_LIST_OUT (area)) if (prefix_list_apply (PREFIX_LIST_OUT (area), &route->prefix) != PREFIX_PERMIT) { if (is_debug) { inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), buf, sizeof (buf)); zlog_debug ("prefix %s was denied by filter-list out", buf); } return; } } /* the route is going to be originated. store it in area's summary_table */ if (summary == NULL) { summary = ospf6_route_copy (route); if (route->type == OSPF6_DEST_TYPE_NETWORK || route->type == OSPF6_DEST_TYPE_RANGE) summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX); else summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER); summary->path.origin.adv_router = area->ospf6->router_id; summary->path.origin.id = ospf6_new_ls_id (summary->path.origin.type, summary->path.origin.adv_router, area->lsdb); summary = ospf6_route_add (summary, summary_table); } else { summary->type = route->type; quagga_gettime (QUAGGA_CLK_MONOTONIC, &summary->changed); } summary->path.router_bits = route->path.router_bits; summary->path.options[0] = route->path.options[0]; summary->path.options[1] = route->path.options[1]; summary->path.options[2] = route->path.options[2]; summary->path.prefix_options = route->path.prefix_options; summary->path.area_id = area->area_id; summary->path.type = OSPF6_PATH_TYPE_INTER; summary->path.cost = route->path.cost; summary->nexthop[0] = route->nexthop[0]; /* prepare buffer */ memset (buffer, 0, sizeof (buffer)); lsa_header = (struct ospf6_lsa_header *) buffer; if (route->type == OSPF6_DEST_TYPE_ROUTER) { router_lsa = (struct ospf6_inter_router_lsa *) ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa); /* Fill Inter-Area-Router-LSA */ router_lsa->options[0] = route->path.options[0]; router_lsa->options[1] = route->path.options[1]; router_lsa->options[2] = route->path.options[2]; OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost); router_lsa->router_id = ADV_ROUTER_IN_PREFIX (&route->prefix); type = htons (OSPF6_LSTYPE_INTER_ROUTER); } else { prefix_lsa = (struct ospf6_inter_prefix_lsa *) ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa); /* Fill Inter-Area-Prefix-LSA */ OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost); prefix_lsa->prefix.prefix_length = route->prefix.prefixlen; prefix_lsa->prefix.prefix_options = route->path.prefix_options; /* set Prefix */ memcpy (p, &route->prefix.u.prefix6, OSPF6_PREFIX_SPACE (route->prefix.prefixlen)); ospf6_prefix_apply_mask (&prefix_lsa->prefix); p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen); type = htons (OSPF6_LSTYPE_INTER_PREFIX); } /* Fill LSA Header */ lsa_header->age = 0; lsa_header->type = type; lsa_header->id = summary->path.origin.id; lsa_header->adv_router = area->ospf6->router_id; lsa_header->seqnum = ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, lsa_header->adv_router, area->lsdb); lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header); /* LSA checksum */ ospf6_lsa_checksum (lsa_header); /* create LSA */ lsa = ospf6_lsa_create (lsa_header); /* Originate */ ospf6_lsa_originate_area (lsa, area); }