/* Match function should return 1 if match is success else return zero. */ static route_map_result_t route_match_ipv6_address (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct access_list *alist; /* struct prefix_ipv6 match; */ if(type == RMAP_ISIS) { alist = access_list_lookup (AFI_IP6, (s8 *) rule); if (alist == NULL) { return RMAP_NOMATCH; } if( FILTER_DENY == access_list_apply(alist, prefix) ) { return RMAP_NOMATCH; } else { return RMAP_MATCH; } } return RMAP_NOMATCH; }
int ospf_abr_should_accept (struct prefix *p, struct ospf_area *area) { if (IMPORT_NAME (area)) { if (IMPORT_LIST (area) == NULL) IMPORT_LIST (area) = access_list_lookup (AFI_IP, IMPORT_NAME (area)); if (IMPORT_LIST (area)) if (access_list_apply (IMPORT_LIST (area), p) == FILTER_DENY) return 0; } return 1; }
static route_map_result_t route_match_ip_address(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct access_list *alist; if (type != RMAP_ISIS) return RMAP_NOMATCH; alist = access_list_lookup(AFI_IP, (char *)rule); if (access_list_apply(alist, prefix) != FILTER_DENY) return RMAP_MATCH; return RMAP_NOMATCH; }
/* Match function should return 1 if match is success else return zero. */ route_map_result_t route_match_ip_address (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct access_list *alist; if (type == RMAP_RIP) { alist = access_list_lookup (AFI_IP, (char *) rule); if (alist == NULL) return RMAP_NOMATCH; return (access_list_apply (alist, prefix) == FILTER_DENY ? RMAP_NOMATCH : RMAP_MATCH); } return RMAP_NOMATCH; }
int ospf_abr_should_announce (struct ospf *ospf, struct prefix *p, struct ospf_route *or) { struct ospf_area *area; area = ospf_area_lookup_by_area_id (ospf, or->u.std.area_id); assert (area); if (EXPORT_NAME (area)) { if (EXPORT_LIST (area) == NULL) EXPORT_LIST (area) = access_list_lookup (AFI_IP, EXPORT_NAME (area)); if (EXPORT_LIST (area)) if (access_list_apply (EXPORT_LIST (area), p) == FILTER_DENY) return 0; } return 1; }
/* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_nexthop (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct access_list *alist; 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; alist = access_list_lookup (AFI_IP, (char *) rule); if (alist == NULL) return RMAP_NOMATCH; return (access_list_apply (alist, &p) == FILTER_DENY ? RMAP_NOMATCH : RMAP_MATCH); } return RMAP_NOMATCH; }
/* Match function return 1 if match is success else return zero. */ static route_map_result_t route_match_ip_next_hop (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct access_list *alist; 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; alist = access_list_lookup (AFI_IP, (char *) rule); if (alist == NULL) return RMAP_NOMATCH; return (access_list_apply (alist, &p) == FILTER_DENY ? RMAP_NOMATCH : RMAP_MATCH); } return RMAP_NOMATCH; }
/** * @fn eigrp_update_send_GR_part * * @param[in] nbr contains neighbor who would receive Graceful restart * * @return void * * @par * Function used for sending Graceful restart Update packet * and if there are multiple chunks, send only one of them. * It is called from thread. Do not call it directly. * * Uses nbr_gr_packet_type from neighbor. */ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) { struct eigrp_packet *ep; u_int16_t length = EIGRP_HEADER_LEN; struct listnode *node, *nnode; struct eigrp_prefix_entry *pe; struct prefix_ipv4 *dest_addr; struct eigrp *e; struct access_list *alist, *alist_i; struct prefix_list *plist, *plist_i; struct list *prefixes; u_int32_t flags; unsigned int send_prefixes; struct TLV_IPv4_Internal_type *tlv_max; /* get prefixes to send to neighbor */ prefixes = nbr->nbr_gr_prefixes_send; send_prefixes = 0; length = EIGRP_HEADER_LEN; /* if there already were last packet chunk, we won't continue */ if(nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_LAST) return; /* if this is first packet chunk, we need to decide, * if there will be one or more chunks */ if(nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_FIRST) { if(prefixes->count <= EIGRP_TLV_MAX_IPv4) { /* there will be only one chunk */ flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG + EIGRP_EOT_FLAG; nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST; } else { /* there will be more chunks */ flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG; nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA; } } else { /* this is not first chunk, and we need to decide, * if there will be more chunks */ if(prefixes->count <= EIGRP_TLV_MAX_IPv4) { /* this is last chunk */ flags = EIGRP_EOT_FLAG; nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST; } else { /* there will be more chunks */ flags = 0; nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA; } } ep = eigrp_packet_new(nbr->ei->ifp->mtu); /* Prepare EIGRP Graceful restart UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, flags, nbr->ei->eigrp->sequence_number, nbr->recv_sequence_number); // encode Authentication TLV, if needed if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) { length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei); } for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe)) { /* * Filtering */ dest_addr = pe->destination_ipv4; /* get list from eigrp process */ e = eigrp_lookup(); /* Get access-lists and prefix-lists from process and interface */ alist = e->list[EIGRP_FILTER_OUT]; plist = e->prefix[EIGRP_FILTER_OUT]; alist_i = nbr->ei->list[EIGRP_FILTER_OUT]; plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT]; /* Check if any list fits */ if ((alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY)|| (plist && prefix_list_apply (plist, (struct prefix *) dest_addr) == FILTER_DENY)|| (alist_i && access_list_apply (alist_i, (struct prefix *) dest_addr) == FILTER_DENY)|| (plist_i && prefix_list_apply (plist_i, (struct prefix *) dest_addr) == FILTER_DENY)) { /* do not send filtered route */ zlog_info("Filtered prefix %s won't be sent out.", inet_ntoa(dest_addr->prefix)); } else { /* sending route which wasn't filtered */ length += eigrp_add_internalTLV_to_stream(ep->s, pe); send_prefixes++; } alist = e->list[EIGRP_FILTER_IN]; plist = e->prefix[EIGRP_FILTER_IN]; alist_i = nbr->ei->list[EIGRP_FILTER_IN]; plist_i = nbr->ei->prefix[EIGRP_FILTER_IN]; /* Check if any list fits */ if ((alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY)|| (plist && prefix_list_apply (plist, (struct prefix *) dest_addr) == FILTER_DENY)|| (alist_i && access_list_apply (alist_i, (struct prefix *) dest_addr) == FILTER_DENY)|| (plist_i && prefix_list_apply (plist_i, (struct prefix *) dest_addr) == FILTER_DENY)) { /* do not send filtered route */ zlog_info("Filtered prefix %s will be removed.", inet_ntoa(dest_addr->prefix)); tlv_max = eigrp_IPv4_InternalTLV_new(); tlv_max->type = EIGRP_TLV_IPv4_INT; tlv_max->length = 28U; tlv_max->metric = pe->reported_metric; /* set delay to MAX */ tlv_max->metric.delay = EIGRP_MAX_METRIC; tlv_max->destination = pe->destination_ipv4->prefix; tlv_max->prefix_length = pe->destination_ipv4->prefixlen; /* prepare message for FSM */ struct eigrp_fsm_action_message *fsm_msg; fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, sizeof(struct eigrp_fsm_action_message)); struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(pe->entries, nbr); fsm_msg->packet_type = EIGRP_OPC_UPDATE; fsm_msg->eigrp = e; fsm_msg->data_type = EIGRP_TLV_IPv4_INT; fsm_msg->adv_router = nbr; fsm_msg->data.ipv4_int_type = tlv_max; fsm_msg->entry = entry; fsm_msg->prefix = pe; /* send message to FSM */ int event = eigrp_get_fsm_event(fsm_msg); eigrp_fsm_event(fsm_msg, event); /* free memory used by TLV */ eigrp_IPv4_InternalTLV_free (tlv_max); } /* * End of filtering */ /* NULL the pointer */ dest_addr = NULL; /* delete processed prefix from list */ listnode_delete(prefixes, pe); /* if there are enough prefixes, send packet */ if(send_prefixes >= EIGRP_TLV_MAX_IPv4) break; } /* compute Auth digest */ if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) { eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG); } /* EIGRP Checksum */ eigrp_packet_checksum(nbr->ei, ep->s, length); ep->length = length; ep->dst.s_addr = nbr->src.s_addr; /*This ack number we await from neighbor*/ ep->sequence_number = nbr->ei->eigrp->sequence_number; if (IS_DEBUG_EIGRP_PACKET(0, RECV)) zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]", ep->length, ep->sequence_number, inet_ntoa(ep->dst)); /*Put packet to retransmission queue*/ eigrp_fifo_push_head(nbr->retrans_queue, ep); if (nbr->retrans_queue->count == 1) { eigrp_send_packet_reliably(nbr); } }
void eigrp_update_send (struct eigrp_interface *ei) { struct eigrp_packet *ep; struct listnode *node, *nnode, *nnode2; struct eigrp_neighbor *nbr; struct eigrp_prefix_entry *pe; u_char has_tlv; struct access_list *alist; struct prefix_list *plist; struct access_list *alist_i; struct prefix_list *plist_i; struct eigrp *e; struct prefix_ipv4 *dest_addr; u_int16_t length = EIGRP_HEADER_LEN; ep = eigrp_packet_new(ei->ifp->mtu); /* Prepare EIGRP INIT UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0, ei->eigrp->sequence_number, 0); // encode Authentication TLV, if needed if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL)) { length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei); } has_tlv = 0; for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe)) { if(pe->req_action & EIGRP_FSM_NEED_UPDATE) { /* Get destination address from prefix */ dest_addr = pe->destination_ipv4; /* * Filtering */ //TODO: Work in progress /* get list from eigrp process */ e = eigrp_lookup(); /* Get access-lists and prefix-lists from process and interface */ alist = e->list[EIGRP_FILTER_OUT]; plist = e->prefix[EIGRP_FILTER_OUT]; alist_i = ei->list[EIGRP_FILTER_OUT]; plist_i = ei->prefix[EIGRP_FILTER_OUT]; /* Check if any list fits */ if ((alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY)|| (plist && prefix_list_apply (plist, (struct prefix *) dest_addr) == FILTER_DENY)|| (alist_i && access_list_apply (alist_i, (struct prefix *) dest_addr) == FILTER_DENY)|| (plist_i && prefix_list_apply (plist_i, (struct prefix *) dest_addr) == FILTER_DENY)) { zlog_info("PROC OUT: Skipping"); //pe->reported_metric.delay = EIGRP_MAX_METRIC; zlog_info("PROC OUT Prefix: %s", inet_ntoa(dest_addr->prefix)); continue; } else { zlog_info("PROC OUT: NENastavujem metriku "); length += eigrp_add_internalTLV_to_stream(ep->s, pe); has_tlv = 1; } /* * End of filtering */ /* NULL the pointer */ dest_addr = NULL; } } if(!has_tlv) { eigrp_packet_free(ep); return; } if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL)) { eigrp_make_md5_digest(ei,ep->s, EIGRP_AUTH_UPDATE_FLAG); } /* EIGRP Checksum */ eigrp_packet_checksum(ei, ep->s, length); ep->length = length; ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS); /*This ack number we await from neighbor*/ ep->sequence_number = ei->eigrp->sequence_number; if (IS_DEBUG_EIGRP_PACKET(0, RECV)) zlog_debug("Enqueuing Update length[%u] Seq [%u]", length, ep->sequence_number); for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) { if (nbr->state == EIGRP_NEIGHBOR_UP) { /*Put packet to retransmission queue*/ eigrp_fifo_push_head(nbr->retrans_queue, ep); if (nbr->retrans_queue->count == 1) { eigrp_send_packet_reliably(nbr); } } } }
void eigrp_update_send_EOT (struct eigrp_neighbor *nbr) { struct eigrp_packet *ep; // struct eigrp_packet *ep_multicast; u_int16_t length = EIGRP_HEADER_LEN; struct eigrp_neighbor_entry *te; struct eigrp_prefix_entry *pe; struct listnode *node, *node2, *nnode, *nnode2; struct access_list *alist; struct prefix_list *plist; struct access_list *alist_i; struct prefix_list *plist_i; struct eigrp *e; struct prefix_ipv4 *dest_addr; ep = eigrp_packet_new(nbr->ei->ifp->mtu); /* Prepare EIGRP EOT UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG, nbr->ei->eigrp->sequence_number, nbr->recv_sequence_number); // encode Authentication TLV, if needed if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) { length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei); } for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe)) { for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) { if ((te->ei == nbr->ei) && (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE)) continue; /* Get destination address from prefix */ dest_addr = pe->destination_ipv4; /* * Filtering */ //TODO: Work in progress /* get list from eigrp process */ e = eigrp_lookup(); /* Get access-lists and prefix-lists from process and interface */ alist = e->list[EIGRP_FILTER_OUT]; plist = e->prefix[EIGRP_FILTER_OUT]; alist_i = nbr->ei->list[EIGRP_FILTER_OUT]; plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT]; /* Check if any list fits */ if ((alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY)|| (plist && prefix_list_apply (plist, (struct prefix *) dest_addr) == FILTER_DENY)|| (alist_i && access_list_apply (alist_i, (struct prefix *) dest_addr) == FILTER_DENY)|| (plist_i && prefix_list_apply (plist_i, (struct prefix *) dest_addr) == FILTER_DENY)) { zlog_info("PROC OUT EOT: Skipping"); //pe->reported_metric.delay = EIGRP_MAX_METRIC; zlog_info("PROC OUT EOT Prefix: %s", inet_ntoa(dest_addr->prefix)); continue; } else { zlog_info("PROC OUT EOT: NENastavujem metriku "); length += eigrp_add_internalTLV_to_stream(ep->s, pe); } /* * End of filtering */ /* NULL the pointer */ dest_addr = NULL; } } if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) { eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG); } /* EIGRP Checksum */ eigrp_packet_checksum(nbr->ei, ep->s, length); ep->length = length; ep->dst.s_addr = nbr->src.s_addr; /*This ack number we await from neighbor*/ ep->sequence_number = nbr->ei->eigrp->sequence_number; if (IS_DEBUG_EIGRP_PACKET(0, RECV)) zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]", ep->length, ep->sequence_number, inet_ntoa(ep->dst)); /*Put packet to retransmission queue*/ eigrp_fifo_push_head(nbr->retrans_queue, ep); if (nbr->retrans_queue->count == 1) { eigrp_send_packet_reliably(nbr); } }
/* * EIGRP UPDATE read function */ void eigrp_update_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph, struct stream * s, struct eigrp_interface *ei, int size) { struct eigrp_neighbor *nbr; struct TLV_IPv4_Internal_type *tlv; struct eigrp_prefix_entry *pe; struct eigrp_neighbor_entry *ne; u_int32_t flags; u_int16_t type; uint16_t length; u_char same; struct access_list *alist; struct prefix_list *plist; struct eigrp *e; u_char graceful_restart; u_char graceful_restart_final; struct list *nbr_prefixes; int ret; /* increment statistics. */ ei->update_in++; /* get neighbor struct */ nbr = eigrp_nbr_get(ei, eigrph, iph); /* neighbor must be valid, eigrp_nbr_get creates if none existed */ assert(nbr); flags = ntohl(eigrph->flags); if (flags & EIGRP_CR_FLAG) { return; } same = 0; graceful_restart = 0; graceful_restart_final = 0; if((nbr->recv_sequence_number) == (ntohl(eigrph->sequence))) same = 1; nbr->recv_sequence_number = ntohl(eigrph->sequence); if (IS_DEBUG_EIGRP_PACKET(0, RECV)) zlog_debug("Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]", size, ifindex2ifname(nbr->ei->ifp->ifindex), inet_ntoa(nbr->src), nbr->recv_sequence_number, flags); if((flags == (EIGRP_INIT_FLAG+EIGRP_RS_FLAG+EIGRP_EOT_FLAG)) && (!same)) { /* Graceful restart Update received with all routes */ zlog_info("Neighbor %s (%s) is resync: peer graceful-restart", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); /* get all prefixes from neighbor from topology table */ nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr); graceful_restart = 1; graceful_restart_final = 1; } else if((flags == (EIGRP_INIT_FLAG+EIGRP_RS_FLAG)) && (!same)) { /* Graceful restart Update received, routes also in next packet */ zlog_info("Neighbor %s (%s) is resync: peer graceful-restart", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); /* get all prefixes from neighbor from topology table */ nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr); /* save prefixes to neighbor for later use */ nbr->nbr_gr_prefixes = nbr_prefixes; graceful_restart = 1; graceful_restart_final = 0; } else if((flags == (EIGRP_EOT_FLAG)) && (!same)) { /* If there was INIT+RS Update packet before, * consider this as GR EOT */ if(nbr->nbr_gr_prefixes != NULL) { /* this is final packet of GR */ nbr_prefixes = nbr->nbr_gr_prefixes; nbr->nbr_gr_prefixes = NULL; graceful_restart = 1; graceful_restart_final = 1; } } else if((flags == (0)) && (!same)) { /* If there was INIT+RS Update packet before, * consider this as GR not final packet */ if(nbr->nbr_gr_prefixes != NULL) { /* this is GR not final route packet */ nbr_prefixes = nbr->nbr_gr_prefixes; graceful_restart = 1; graceful_restart_final = 0; } } else if((flags & EIGRP_INIT_FLAG) && (!same)) { /* When in pending state, send INIT update only if it wasn't already sent before (only if init_sequence is 0) */ if((nbr->state == EIGRP_NEIGHBOR_PENDING) && (nbr->init_sequence_number == 0)) eigrp_update_send_init(nbr); if (nbr->state == EIGRP_NEIGHBOR_UP) { eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN); eigrp_topology_neighbor_down(nbr->ei->eigrp,nbr); nbr->recv_sequence_number = ntohl(eigrph->sequence); zlog_info("Neighbor %s (%s) is down: peer restarted", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING); zlog_info("Neighbor %s (%s) is pending: new adjacency", inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex)); eigrp_update_send_init(nbr); } } /*If there is topology information*/ while (s->endp > s->getp) { type = stream_getw(s); if (type == EIGRP_TLV_IPv4_INT) { stream_set_getp(s, s->getp - sizeof(u_int16_t)); tlv = eigrp_read_ipv4_tlv(s); /*searching if destination exists */ struct prefix_ipv4 *dest_addr; dest_addr = prefix_ipv4_new(); dest_addr->prefix = tlv->destination; dest_addr->prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( eigrp->topology_table, dest_addr); /*if exists it comes to DUAL*/ if (dest != NULL) { /* remove received prefix from neighbor prefix list if in GR */ if(graceful_restart) remove_received_prefix_gr(nbr_prefixes, dest); struct eigrp_fsm_action_message *msg; msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, sizeof(struct eigrp_fsm_action_message)); struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); msg->packet_type = EIGRP_OPC_UPDATE; msg->eigrp = eigrp; msg->data_type = EIGRP_TLV_IPv4_INT; msg->adv_router = nbr; msg->data.ipv4_int_type = tlv; msg->entry = entry; msg->prefix = dest; int event = eigrp_get_fsm_event(msg); eigrp_fsm_event(msg, event); } else { /*Here comes topology information save*/ pe = eigrp_prefix_entry_new(); pe->serno = eigrp->serno; pe->destination_ipv4 = dest_addr; pe->af = AF_INET; pe->state = EIGRP_FSM_STATE_PASSIVE; pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE; ne = eigrp_neighbor_entry_new(); ne->ei = ei; ne->adv_router = nbr; ne->reported_metric = tlv->metric; ne->reported_distance = eigrp_calculate_metrics(eigrp, &tlv->metric); //TODO: Work in progress /* * Filtering */ e = eigrp_lookup(); /* get access-list from eigrp process */ alist = e->list[EIGRP_FILTER_IN]; zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix)); if (alist) { zlog_info ("ALIST PROC IN: %s", alist->name); } else { zlog_info("ALIST PROC IN je prazdny"); } /* Check if access-list fits */ if (alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ zlog_info("PROC alist IN: Skipping"); //ne->reported_metric.delay = EIGRP_MAX_METRIC; zlog_info("PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix)); eigrp_IPv4_InternalTLV_free (tlv); continue; } else { zlog_info("PROC alist IN: NENastavujem metriku "); } plist = e->prefix[EIGRP_FILTER_IN]; if (plist) { zlog_info ("PLIST PROC IN: %s", plist->name); } else { zlog_info("PLIST PROC IN je prazdny"); } /* Check if prefix-list fits */ if (plist && prefix_list_apply (plist, (struct prefix *) dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ zlog_info("PLIST PROC IN: Skipping"); //ne->reported_metric.delay = EIGRP_MAX_METRIC; zlog_info("PLIST PROC IN Prefix: %s", inet_ntoa(dest_addr->prefix)); eigrp_IPv4_InternalTLV_free (tlv); continue; } else { zlog_info("PLIST PROC IN: NENastavujem metriku "); } //Check route-map /*if (e->routemap[EIGRP_FILTER_IN]) { ret = route_map_apply (e->routemap[EIGRP_FILTER_IN], (struct prefix *)dest_addr, RMAP_EIGRP, NULL); if (ret == RMAP_DENYMATCH) { zlog_debug ("%s is filtered by route-map",inet_ntoa (dest_addr->prefix)); continue; } }*/ /*Get access-list from current interface */ zlog_info("Checking access_list on interface: %s",ei->ifp->name); alist = ei->list[EIGRP_FILTER_IN]; if (alist) { zlog_info ("ALIST INT IN: %s", alist->name); } else { zlog_info("ALIST INT IN je prazdny"); } /* Check if access-list fits */ if (alist && access_list_apply (alist, (struct prefix *) dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ zlog_info("INT alist IN: Skipping"); //ne->reported_metric.delay = EIGRP_MAX_METRIC; zlog_info("INT IN Prefix: %s", inet_ntoa(dest_addr->prefix)); eigrp_IPv4_InternalTLV_free (tlv); continue; } else { zlog_info("INT IN: NENastavujem metriku "); } plist = ei->prefix[EIGRP_FILTER_IN]; if (plist) { zlog_info ("PLIST INT IN: %s", plist->name); } else { zlog_info("PLIST INT IN je prazdny"); } /* Check if prefix-list fits */ if (plist && prefix_list_apply (plist, (struct prefix *) dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ zlog_info("PLIST INT IN: Skipping"); //ne->reported_metric.delay = EIGRP_MAX_METRIC; zlog_info("PLIST INT IN Prefix: %s", inet_ntoa(dest_addr->prefix)); eigrp_IPv4_InternalTLV_free (tlv); continue; } else { zlog_info("PLIST INT IN: NENastavujem metriku "); } //Check route-map /*if (ei->routemap[EIGRP_FILTER_IN]) { ret = route_map_apply (ei->routemap[EIGRP_FILTER_IN], (struct prefix *)dest_addr, RMAP_EIGRP, NULL); if (ret == RMAP_DENYMATCH) { zlog_debug ("%s is filtered by route-map",inet_ntoa (dest_addr->prefix)); continue; } }*/ /* * End of filtering */ ne->distance = eigrp_calculate_total_metrics(eigrp, ne); zlog_info("<DEBUG PROC IN Distance: %x", ne->distance); zlog_info("<DEBUG PROC IN Delay: %x", ne->total_metric.delay); pe->fdistance = pe->distance = pe->rdistance = ne->distance; ne->prefix = pe; ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; eigrp_prefix_entry_add(eigrp->topology_table, pe); eigrp_neighbor_entry_add(pe, ne); pe->distance = pe->fdistance = pe->rdistance = ne->distance; pe->reported_metric = ne->total_metric; eigrp_topology_update_node_flags(pe); pe->req_action |= EIGRP_FSM_NEED_UPDATE; listnode_add(eigrp->topology_changes_internalIPV4, pe); } eigrp_IPv4_InternalTLV_free (tlv); } } /* ask about prefixes not present in GR update, * if this is final GR packet */ if(graceful_restart_final) { eigrp_update_receive_GR_ask(eigrp, nbr, nbr_prefixes); } /* * We don't need to send separate Ack for INIT Update. INIT will be acked in EOT Update. */ if ((nbr->state == EIGRP_NEIGHBOR_UP) && !(flags == EIGRP_INIT_FLAG)) { eigrp_hello_send_ack(nbr); } eigrp_query_send_all(eigrp); eigrp_update_send_all(eigrp, ei); }
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); }