static void print_rnh (struct route_node *rn, struct vty *vty) { struct rnh *rnh; struct nexthop *nexthop; struct listnode *node; struct zserv *client; char buf[BUFSIZ]; rnh = rn->info; vty_out(vty, "%s%s", inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), VTY_NEWLINE); if (rnh->state) { vty_out(vty, " resolved via %s%s", zebra_route_string(rnh->state->type), VTY_NEWLINE); for (nexthop = rnh->state->nexthop; nexthop; nexthop = nexthop->next) print_nh(nexthop, vty); } else vty_out(vty, " unresolved%s%s", CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : "", VTY_NEWLINE); vty_out(vty, " Client list:"); for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) vty_out(vty, " %s(fd %d)", zebra_route_string(client->proto), client->sock); vty_out(vty, "%s", VTY_NEWLINE); }
void isis_redist_delete(int type, struct prefix *p) { int family = p->family; struct route_table *ei_table = get_ext_info(isis, family); struct route_node *ei_node; struct listnode *node; struct isis_area *area; int level; struct isis_redist *redist; char debug_buf[BUFSIZ]; prefix2str(p, debug_buf, sizeof(debug_buf)); zlog_debug("%s: Removing route %s from %s.", __func__, debug_buf, zebra_route_string(type)); if (is_default(p)) { /* Don't remove default route but add synthetic route for use * by "default-information originate always". Areas without the * "always" setting will ignore routes with origin DEFAULT_ROUTE. */ isis_redist_add(DEFAULT_ROUTE, p, 254, MAX_WIDE_PATH_METRIC); return; } if (!ei_table) { zlog_warn("%s: External information table not initialized.", __func__); return; } ei_node = route_node_lookup(ei_table, p); if (!ei_node || !ei_node->info) { char buf[BUFSIZ]; prefix2str(p, buf, sizeof(buf)); zlog_warn("%s: Got a delete for %s route %s, but that route" " was never added.", __func__, zebra_route_string(type), buf); if (ei_node) route_unlock_node(ei_node); return; } route_unlock_node(ei_node); for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) for (level = 1; level < ISIS_LEVELS; level++) { redist = get_redist_settings(area, family, type, level); if (!redist->redist) continue; isis_redist_uninstall(area, level, p); } XFREE(MTYPE_ISIS, ei_node->info); route_unlock_node(ei_node); }
int zebra_dispatch_rnh_table (vrf_id_t vrfid, int family, struct zserv *client) { struct route_table *ntable; struct route_node *nrn; struct rnh *rnh; ntable = lookup_rnh_table(vrfid, family); if (!ntable) { zlog_debug("dispatch_rnh_table: rnh table not found\n"); return -1; } for (nrn = route_top (ntable); nrn; nrn = route_next (nrn)) { if (!nrn->info) continue; rnh = nrn->info; if (IS_ZEBRA_DEBUG_NHT) { char bufn[INET6_ADDRSTRLEN]; prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); zlog_debug("rnh %s - sending nexthop %s event to client %s", bufn, rnh->state ? "reachable" : "unreachable", zebra_route_string(client->proto)); } send_client(rnh, client, vrfid); } return 1; }
int zebra_cleanup_rnh_client (vrf_id_t vrfid, int family, struct zserv *client) { struct route_table *ntable; struct route_node *nrn; struct rnh *rnh; ntable = lookup_rnh_table(vrfid, family); if (!ntable) { zlog_debug("cleanup_rnh_client: rnh table not found\n"); return -1; } for (nrn = route_top (ntable); nrn; nrn = route_next (nrn)) { if (!nrn->info) continue; rnh = nrn->info; if (IS_ZEBRA_DEBUG_NHT) { char bufn[INET6_ADDRSTRLEN]; prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); zlog_debug("rnh %s - cleaning state for client %s", bufn, zebra_route_string(client->proto)); } zebra_remove_rnh_client(rnh, client); } return 1; }
void pim_zebra_init (struct thread_master *master, char *zebra_sock_path) { int i; if (zebra_sock_path) zclient_serv_path_set(zebra_sock_path); #ifdef HAVE_TCP_ZEBRA zlog_notice("zclient update contacting ZEBRA daemon at socket TCP %s,%d", "127.0.0.1", ZEBRA_PORT); #else zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", zclient_serv_path_get()); #endif /* Socket for receiving updates from Zebra daemon */ qpim_zclient_update = zclient_new (master); qpim_zclient_update->zebra_connected = pim_zebra_connected; qpim_zclient_update->router_id_update = pim_router_id_update_zebra; qpim_zclient_update->interface_add = pim_zebra_if_add; qpim_zclient_update->interface_delete = pim_zebra_if_del; qpim_zclient_update->interface_up = pim_zebra_if_state_up; qpim_zclient_update->interface_down = pim_zebra_if_state_down; qpim_zclient_update->interface_address_add = pim_zebra_if_address_add; qpim_zclient_update->interface_address_delete = pim_zebra_if_address_del; qpim_zclient_update->ipv4_route_add = redist_read_ipv4_route; qpim_zclient_update->ipv4_route_delete = redist_read_ipv4_route; zclient_init(qpim_zclient_update, ZEBRA_ROUTE_PIM); if (PIM_DEBUG_PIM_TRACE) { zlog_info("zclient_init cleared redistribution request"); } zassert(qpim_zclient_update->redist_default == ZEBRA_ROUTE_PIM); /* Request all redistribution */ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (i == qpim_zclient_update->redist_default) continue; vrf_bitmap_set(qpim_zclient_update->redist[i], VRF_DEFAULT); if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: requesting redistribution for %s (%i)", __PRETTY_FUNCTION__, zebra_route_string(i), i); } } /* Request default information */ vrf_bitmap_set(qpim_zclient_update->default_information, VRF_DEFAULT); if (PIM_DEBUG_PIM_TRACE) { zlog_info("%s: requesting default information redistribution", __PRETTY_FUNCTION__); zlog_notice("%s: zclient update socket initialized", __PRETTY_FUNCTION__); } zassert(!qpim_zclient_lookup); qpim_zclient_lookup = zclient_lookup_new(); zassert(qpim_zclient_lookup); }
void rip_show_redistribute_config(struct vty *vty, struct rip *rip) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (i == zclient->redist_default || !rip_redistribute_check(rip, i)) continue; vty_out(vty, " %s", zebra_route_string(i)); } }
void zebra_remove_rnh_client (struct rnh *rnh, struct zserv *client) { if (IS_ZEBRA_DEBUG_NHT) { char buf[INET6_ADDRSTRLEN]; zlog_debug("client %s unregisters rnh %s", zebra_route_string(client->proto), rnh_str(rnh, buf, INET6_ADDRSTRLEN)); } listnode_delete(rnh->client_list, client); if (list_isempty(rnh->client_list)) zebra_delete_rnh(rnh); }
/* If client sent routes of specific type, zebra removes it * and returns number of deleted routes. */ static void zebra_score_rib (int client_sock) { int i; for (i = ZEBRA_ROUTE_RIP; i < ZEBRA_ROUTE_MAX; i++) if (client_sock == route_type_oaths[i]) { zlog_notice ("client %d disconnected. %lu %s routes removed from the rib", client_sock, rib_score_proto (i), zebra_route_string (i)); route_type_oaths[i] = 0; break; } }
/* Tie up route-type and client->sock */ static void zread_hello (struct zserv *client) { /* type of protocol (lib/zebra.h) */ u_char proto; proto = stream_getc (client->ibuf); /* accept only dynamic routing protocols */ if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_STATIC)) { zlog_notice ("client %d says hello and bids fair to announce only %s routes", client->sock, zebra_route_string(proto)); /* if route-type was binded by other client */ if (route_type_oaths[proto]) zlog_warn ("sender of %s routes changed %c->%c", zebra_route_string(proto), route_type_oaths[proto], client->sock); route_type_oaths[proto] = client->sock; } }
/* print current babel configuration on vty */ static int babel_config_write (struct vty *vty) { int lines = 0; int i; /* list enabled debug modes */ lines += debug_babel_config_write (vty); if (!babel_routing_process) return lines; vty_out (vty, "router babel%s", VTY_NEWLINE); if (diversity_kind != DIVERSITY_NONE) { vty_out (vty, " babel diversity%s", VTY_NEWLINE); lines++; } if (diversity_factor != BABEL_DEFAULT_DIVERSITY_FACTOR) { vty_out (vty, " babel diversity-factor %d%s", diversity_factor, VTY_NEWLINE); lines++; } if (resend_delay != BABEL_DEFAULT_RESEND_DELAY) { vty_out (vty, " babel resend-delay %u%s", resend_delay, VTY_NEWLINE); lines++; } if (smoothing_half_life != BABEL_DEFAULT_SMOOTHING_HALF_LIFE) { vty_out (vty, " babel smoothing-half-life %u%s", smoothing_half_life, VTY_NEWLINE); lines++; } lines += babel_auth_config_write (vty); /* list enabled interfaces */ lines = 1 + babel_enable_if_config_write (vty); /* list redistributed protocols */ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) if (i != zclient->redist_default && zclient->redist[i]) { vty_out (vty, " redistribute %s%s", zebra_route_string (i), VTY_NEWLINE); lines++; } lines += config_write_distribute (vty); return lines; }
/* Handle notification about route being added */ void isis_redist_add(int type, struct prefix *p, u_char distance, uint32_t metric) { int family = p->family; struct route_table *ei_table = get_ext_info(isis, family); struct route_node *ei_node; struct isis_ext_info *info; struct listnode *node; struct isis_area *area; int level; struct isis_redist *redist; char debug_buf[BUFSIZ]; prefix2str(p, debug_buf, sizeof(debug_buf)); zlog_debug("%s: New route %s from %s.", __func__, debug_buf, zebra_route_string(type)); if (!ei_table) { zlog_warn("%s: External information table not initialized.", __func__); return; } ei_node = route_node_get(ei_table, p); if (ei_node->info) route_unlock_node(ei_node); else ei_node->info = XCALLOC(MTYPE_ISIS, sizeof(struct isis_ext_info)); info = ei_node->info; info->origin = type; info->distance = distance; info->metric = metric; if (is_default(p)) type = DEFAULT_ROUTE; for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) for (level = 1; level <= ISIS_LEVELS; level++) { redist = get_redist_settings(area, family, type, level); if (!redist->redist) continue; isis_redist_update_ext_reach(area, level, redist, p, info); } }
void zebra_add_rnh_client (struct rnh *rnh, struct zserv *client, vrf_id_t vrf_id) { if (IS_ZEBRA_DEBUG_NHT) { char buf[INET6_ADDRSTRLEN]; zlog_debug("client %s registers rnh %s", zebra_route_string(client->proto), rnh_str(rnh, buf, INET6_ADDRSTRLEN)); } if (!listnode_lookup(rnh->client_list, client)) { listnode_add(rnh->client_list, client); send_client(rnh, client, vrf_id); } }
/* Unset redistribution. */ int bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type) { /* Unset flag from BGP instance. */ bgp->redist[afi][type] = 0; /* Unset route-map. */ if (bgp->rmap[afi][type].name) free (bgp->rmap[afi][type].name); bgp->rmap[afi][type].name = NULL; bgp->rmap[afi][type].map = NULL; /* Unset metric. */ bgp->redist_metric_flag[afi][type] = 0; bgp->redist_metric[afi][type] = 0; /* Return if zebra connection is disabled. */ if (! vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT)) return CMD_WARNING; vrf_bitmap_unset (zclient->redist[type], VRF_DEFAULT); if (bgp->redist[AFI_IP][type] == 0 && bgp->redist[AFI_IP6][type] == 0 && zclient->sock >= 0) { /* Send distribute delete message to zebra. */ if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("Zebra send: redistribute delete %s", zebra_route_string(type)); zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type, VRF_DEFAULT); } /* Withdraw redistributed routes from current BGP's routing table. */ bgp_redistribute_withdraw (bgp, afi, type); return CMD_SUCCESS; }
/* Other routes redistribution into BGP. */ int bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type) { /* Set flag to BGP instance. */ bgp->redist[afi][type] = 1; /* Return if already redistribute flag is set. */ if (zclient->redist[type]) return CMD_WARNING; zclient->redist[type] = 1; /* Return if zebra connection is not established. */ if (zclient->sock < 0) return CMD_WARNING; if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type)); /* Send distribute add message to zebra. */ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type); return CMD_SUCCESS; }
/* Zebra route add and delete treatment. */ static int zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct stream *s; struct zapi_ipv4 api; struct in_addr nexthop; struct prefix_ipv4 p; unsigned char plength = 0; s = zclient->ibuf; nexthop.s_addr = 0; /* Type, flags, message. */ api.type = stream_getc (s); api.flags = stream_getc (s); api.message = stream_getc (s); /* IPv4 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; plength = stream_getc (s); p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, plength); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (s); nexthop.s_addr = stream_get_ipv4 (s); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); stream_getl (s); /* ifindex, unused */ } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) api.tag = stream_getl (s); else api.tag = 0; if (command == ZEBRA_IPV4_ROUTE_ADD) { if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u tag %d", zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), api.metric, api.tag); } bgp_redistribute_add ((struct prefix *)&p, &nexthop, NULL, api.metric, api.type, api.tag); } else { if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d " "nexthop %s metric %u tag %d", zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), api.metric, api.tag); } bgp_redistribute_delete((struct prefix *)&p, api.type); } return 0; }
static int redist_read_ipv4_route(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct stream *s; struct zapi_ipv4 api; unsigned long ifindex; struct in_addr nexthop; struct prefix_ipv4 p; int min_len = 4; if (length < min_len) { zlog_warn("%s %s: short buffer: length=%d min=%d", __FILE__, __PRETTY_FUNCTION__, length, min_len); return -1; } s = zclient->ibuf; ifindex = 0; nexthop.s_addr = 0; /* Type, flags, message. */ api.type = stream_getc(s); api.flags = stream_getc(s); api.message = stream_getc(s); /* IPv4 prefix length. */ memset(&p, 0, sizeof(struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc(s); min_len += PSIZE(p.prefixlen) + CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? 5 : 0 + CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? 5 : 0 + CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? 1 : 0 + CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? 4 : 0; if (PIM_DEBUG_ZEBRA) { zlog_debug("%s %s: length=%d min_len=%d flags=%s%s%s%s", __FILE__, __PRETTY_FUNCTION__, length, min_len, CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? "nh" : "", CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? " ifi" : "", CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? " dist" : "", CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? " metr" : ""); } if (length < min_len) { zlog_warn("%s %s: short buffer: length=%d min_len=%d flags=%s%s%s%s", __FILE__, __PRETTY_FUNCTION__, length, min_len, CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? "nh" : "", CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? " ifi" : "", CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? " dist" : "", CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? " metr" : ""); return -1; } /* IPv4 prefix. */ stream_get(&p.prefix, s, PSIZE(p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc(s); nexthop.s_addr = stream_get_ipv4(s); } if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc(s); ifindex = stream_getl(s); } api.distance = CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? stream_getc(s) : 0; api.metric = CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? stream_getl(s) : 0; switch (command) { case ZEBRA_IPV4_ROUTE_ADD: if (PIM_DEBUG_ZEBRA) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("%s: add %s %s/%d " "nexthop %s ifindex %ld metric%s %u distance%s %u", __PRETTY_FUNCTION__, zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), ifindex, CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? "-recv" : "-miss", api.metric, CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? "-recv" : "-miss", api.distance); } break; case ZEBRA_IPV4_ROUTE_DELETE: if (PIM_DEBUG_ZEBRA) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("%s: delete %s %s/%d " "nexthop %s ifindex %ld metric%s %u distance%s %u", __PRETTY_FUNCTION__, zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), ifindex, CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? "-recv" : "-miss", api.metric, CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? "-recv" : "-miss", api.distance); } break; default: zlog_warn("%s: unknown command=%d", __PRETTY_FUNCTION__, command); return -1; } sched_rpf_cache_refresh(); return 0; }
const char *ospf_redist_string(unsigned int route_type) { return (route_type == ZEBRA_ROUTE_MAX) ? "Default" : zebra_route_string(route_type); }
static int ospf6_zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) { struct stream *s; struct zapi_ipv6 api; unsigned long ifindex; struct prefix_ipv6 p; struct in6_addr *nexthop; s = zclient->ibuf; ifindex = 0; nexthop = NULL; memset (&api, 0, sizeof (api)); /* Type, flags, message. */ api.type = stream_getc (s); api.flags = stream_getc (s); api.message = stream_getc (s); /* IPv6 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = stream_getc (s); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (s); nexthop = (struct in6_addr *) malloc (api.nexthop_num * sizeof (struct in6_addr)); stream_get (nexthop, s, api.nexthop_num * sizeof (struct in6_addr)); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); ifindex = stream_getl (s); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); else api.distance = 0; if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; if (IS_OSPF6_DEBUG_ZEBRA (RECV)) { char prefixstr[128], nexthopstr[128]; prefix2str ((struct prefix *)&p, prefixstr, sizeof (prefixstr)); if (nexthop) inet_ntop (AF_INET6, nexthop, nexthopstr, sizeof (nexthopstr)); else snprintf (nexthopstr, sizeof (nexthopstr), "::"); zlog_debug ("Zebra Receive route %s: %s %s nexthop %s ifindex %ld", (command == ZEBRA_IPV6_ROUTE_ADD ? "add" : "delete"), zebra_route_string(api.type), prefixstr, nexthopstr, ifindex); } if (command == ZEBRA_IPV6_ROUTE_ADD) ospf6_asbr_redistribute_add (api.type, ifindex, (struct prefix *) &p, api.nexthop_num, nexthop); else ospf6_asbr_redistribute_remove (api.type, ifindex, (struct prefix *) &p); if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) free (nexthop); return 0; }
/* Zebra route add and delete treatment. */ static int zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) { struct stream *s; struct zapi_ipv6 api; struct in6_addr nexthop; struct prefix_ipv6 p; s = zclient->ibuf; memset (&nexthop, 0, sizeof (struct in6_addr)); /* Type, flags, message. */ api.type = stream_getc (s); api.flags = stream_getc (s); api.message = stream_getc (s); /* IPv6 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = stream_getc (s); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (s); stream_get (&nexthop, s, 16); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); stream_getl (s); /* ifindex, unused */ } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); else api.distance = 0; if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; /* Simply ignore link-local address. */ if (IN6_IS_ADDR_LINKLOCAL (&p.prefix)) return 0; if (command == ZEBRA_IPV6_ROUTE_ADD) { if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET6_ADDRSTRLEN]; zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u", zebra_route_string(api.type), inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), api.metric); } bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, api.metric, api.type); } else { if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET6_ADDRSTRLEN]; zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d " "nexthop %s metric %u", zebra_route_string(api.type), inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])), api.metric); } bgp_redistribute_delete ((struct prefix *) &p, api.type); } return 0; }