static int zebra_route(proto_tree *tree, tvbuff_t *tvb, int offset, guint16 len, guint8 family) { guint32 prefix4; guint8 message, prefixlen, buffer6[16]; proto_tree_add_item(tree, hf_zebra_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_zebra_rtflags, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; message = tvb_get_guint8(tvb, offset); offset = zebra_route_message(tree, tvb, offset, message); prefixlen = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_zebra_prefixlen, tvb, offset, 1, prefixlen); offset += 1; if (family == ZEBRA_FAMILY_IPV6) { memset(buffer6, '\0', sizeof buffer6); tvb_memcpy(tvb, buffer6, offset, MIN((unsigned) PSIZE(prefixlen), sizeof buffer6)); proto_tree_add_ipv6(tree, hf_zebra_prefix6, tvb, offset, PSIZE(prefixlen), buffer6); }else { prefix4 = 0; tvb_memcpy(tvb, (guint8 *)&prefix4, offset, MIN((unsigned) PSIZE(prefixlen), sizeof prefix4)); proto_tree_add_ipv4(tree, hf_zebra_prefix4, tvb, offset, PSIZE(prefixlen), prefix4); } offset += PSIZE(prefixlen); if (message & ZEBRA_ZAPI_MESSAGE_NEXTHOP) { offset = zebra_route_nexthop(tree, tvb, offset, len); } if (message & ZEBRA_ZAPI_MESSAGE_IFINDEX) { offset = zebra_route_ifindex(tree, tvb, offset, len); } if (message & ZEBRA_ZAPI_MESSAGE_DISTANCE) { proto_tree_add_item(tree, hf_zebra_distance, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } if (message & ZEBRA_ZAPI_MESSAGE_METRIC) { proto_tree_add_item(tree, hf_zebra_metric, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } return offset; }
/* * "xdr_encode"-like interface that allows daemon (client) to send * a message to zebra server for a route that needs to be * added/deleted to the kernel. Info about the route is specified * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes * the info down the zclient socket using the stream_* functions. * * The corresponding read ("xdr_decode") function on the server * side is zread_ipv4_add()/zread_ipv4_delete(). * * 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Length (2) | Command | Route Type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ZEBRA Flags | Message Flags | Prefix length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Destination IPv4 Prefix for route | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nexthop count | * +-+-+-+-+-+-+-+-+ * * * A number of IPv4 nexthop(s) or nexthop interface index(es) are then * described, as per the Nexthop count. Each nexthop described as: * * +-+-+-+-+-+-+-+-+ * | Nexthop Type | Set to one of ZEBRA_NEXTHOP_* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | IPv4 Nexthop address or Interface Index number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Alternatively, if the flags field has ZEBRA_FLAG_BLACKHOLE or * ZEBRA_FLAG_REJECT is set then Nexthop count is set to 1, then _no_ * nexthop information is provided, and the message describes a prefix * to blackhole or reject route. * * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1 * byte value. * * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8 * byte value. * * XXX: No attention paid to alignment. */ int zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, struct zapi_ipv4 *api) { int i; int psize; struct stream *s; /* Reset stream. */ s = zclient->obuf; stream_reset (s); zclient_create_header (s, cmd); /* Put type and nexthop. */ stream_putc (s, api->type); stream_putc (s, api->flags); stream_putc (s, api->message); stream_putw (s, api->safi); /* Put prefix information. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *) & p->prefix, psize); /* Nexthop, ifindex, distance and metric information. */ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) { if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) { stream_putc (s, 1); stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); /* XXX assert(api->nexthop_num == 0); */ /* XXX assert(api->ifindex_num == 0); */ } else stream_putc (s, api->nexthop_num + api->ifindex_num); for (i = 0; i < api->nexthop_num; i++) { stream_putc (s, ZEBRA_NEXTHOP_IPV4); stream_put_in_addr (s, api->nexthop[i]); } for (i = 0; i < api->ifindex_num; i++) { stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); stream_putl (s, api->ifindex[i]); } } if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE)) stream_putc (s, api->distance); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) stream_putl (s, api->metric); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); return zclient_send_message(zclient); }
s32 bgp_nlri_parse_6pe (struct peer *peer, struct attr *attr, struct bgp_nlri *packet) { u_char *pnt; u_char *lim; struct prefix p; int psize; int prefixlen; u_int32_t label; u_char *tagpnt; /* Check peer status. */ if (peer->status != Established) return 0; pnt = packet->nlri; lim = pnt + packet->length; for (; pnt < lim; pnt += psize) { /* Clear prefix structure. */ memset (&p, 0, sizeof (struct prefix)); /* Fetch prefix length. */ prefixlen = *pnt++; p.family = AF_INET6; psize = PSIZE (prefixlen); if (prefixlen < 24) { zlog_err ("prefix length is less than 88: %d", prefixlen); return -1; } label = decode_label (pnt); /* Copyr label to prefix. */ tagpnt = pnt; p.prefixlen = prefixlen - 24; memcpy (&p.u.prefix, pnt + 3, psize - 3); if (pnt + psize > lim) return -1; if (attr) bgp_update (peer, &p, attr, AFI_IP6, SAFI_UNICAST, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, tagpnt, 0); else bgp_withdraw (peer, &p, attr, AFI_IP6, SAFI_UNICAST, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, tagpnt); } /* Packet length consistency check. */ if (pnt != lim) return -1; return 0; }
check_entry(u64 va, u64 ps, char *str) { va &= ~ (PSIZE(ps)-1); if ( va == 0x2000000002908000UL || va == 0x600000000000C000UL ) { stop(); } if (tlb_debug) printk("%s at %lx %lx\n", str, va, 1UL<<ps); }
/* Zebra route add and delete treatment. */ static int rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) { struct stream *s; struct zapi_ipv4 api; unsigned long ifindex; struct in_addr nexthop; struct prefix_ipv4 p; 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. */ memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; 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.s_addr = stream_get_ipv4 (s); } 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 = 255; if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; /* Then fetch IPv4 prefixes. */ if (command == ZEBRA_IPV4_ROUTE_ADD) rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop, api.metric, api.distance); else rip_redistribute_delete (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex); return 0; }
int zapi_ipv6_route (u_char cmd, struct_zclient *zclient, struct prefix_ipv6 *p, struct zapi_ipv6 *api) { int i; int psize; struct stream *s; /* Reset stream. */ s = zclient->obuf; stream_reset (s); /* Length place holder. */ stream_putw (s, 0); /* Put command, type and nexthop. */ stream_putc (s, cmd); stream_putc (s, api->type); stream_putc (s, api->flags); stream_putc (s, api->message); /* Put prefix information. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *)&p->prefix, psize); /* Nexthop, ifindex, distance and metric information. */ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) { stream_putc (s, api->nexthop_num + api->ifindex_num); for (i = 0; i < api->nexthop_num; i++) { stream_putc (s, ZEBRA_NEXTHOP_IPV6); stream_write (s, (u_char *)api->nexthop[i], 16); } for (i = 0; i < api->ifindex_num; i++) { stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); stream_putl (s, api->ifindex[i]); } } if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE)) stream_putc (s, api->distance); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) stream_putl (s, api->metric); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); return writen (zclient->sock, s->data, stream_get_endp (s)); }
/* Zebra route add and delete treatment. */ int ripng_zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) { struct stream *s; struct zapi_ipv6 api; unsigned long ifindex; struct in6_addr nexthop; struct prefix_ipv6 p; s = zclient->ibuf; ifindex = 0; 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); 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 (command == ZEBRA_IPV6_ROUTE_ADD) ripng_redistribute_add (api.type, 0, &p, ifindex); else ripng_redistribute_delete (api.type, 0, &p, ifindex); return 0; }
static int babel_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) { struct stream *s; struct zapi_ipv4 api; unsigned long ifindex = -1; struct in_addr nexthop; struct prefix_ipv4 prefix; s = zclient->ibuf; ifindex = 0; memset (&nexthop, 0, sizeof (struct in_addr)); memset (&api, 0, sizeof(struct zapi_ipv4)); memset (&prefix, 0, sizeof (struct prefix_ipv4)); /* Type, flags, message. */ api.type = stream_getc (s); api.flags = stream_getc (s); api.message = stream_getc (s); /* IPv6 prefix. */ prefix.family = AF_INET; prefix.prefixlen = stream_getc (s); stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (s); stream_get (&nexthop, s, sizeof(nexthop)); } 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 (command == ZEBRA_IPV6_ROUTE_ADD) { babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop); } else { babel_ipv4_route_delete(&api, &prefix, ifindex); } return 0; }
int isis_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) { struct stream *stream; struct zapi_ipv4 api; struct prefix_ipv4 p; unsigned long ifindex; struct in_addr nexthop; stream = zclient->ibuf; memset (&p, 0, sizeof (struct prefix_ipv4)); ifindex = 0; api.type = stream_getc (stream); api.flags = stream_getc (stream); api.message = stream_getc (stream); p.family = AF_INET; p.prefixlen = stream_getc (stream); stream_get (&p.prefix, stream, PSIZE (p.prefixlen)); if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (stream); nexthop.s_addr = stream_get_ipv4 (stream); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (stream); ifindex = stream_getl (stream); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (stream); if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (stream); else api.metric = 0; if (command == ZEBRA_IPV4_ROUTE_ADD) { zlog_debug ("IPv4 Route add from Z"); } return 0; }
static struct isis_vertex * isis_find_vertex (struct list *list, void *id, enum vertextype vtype) { struct listnode *node; struct isis_vertex *vertex; struct prefix *p1, *p2; for (ALL_LIST_ELEMENTS_RO (list, node, vertex)) { if (vertex->type != vtype) continue; switch (vtype) { case VTYPE_ES: case VTYPE_NONPSEUDO_IS: case VTYPE_NONPSEUDO_TE_IS: if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN) == 0) return vertex; break; case VTYPE_PSEUDO_IS: case VTYPE_PSEUDO_TE_IS: if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0) return vertex; break; case VTYPE_IPREACH_INTERNAL: case VTYPE_IPREACH_EXTERNAL: case VTYPE_IPREACH_TE: #ifdef HAVE_IPV6 case VTYPE_IP6REACH_INTERNAL: case VTYPE_IP6REACH_EXTERNAL: #endif /* HAVE_IPV6 */ p1 = (struct prefix *) id; p2 = (struct prefix *) &vertex->N.id; if (p1->family == p2->family && p1->prefixlen == p2->prefixlen && memcmp (&p1->u.prefix, &p2->u.prefix, PSIZE (p1->prefixlen)) == 0) return vertex; break; } } return NULL; }
unsigned logic_pinger_http_get_data(unsigned pkt, unsigned more_data) { char buf[1024]; char *dest = buf; if(more_data == 0) { dest+=sprintf((char*)dest,"var pinger_packfmt={"); PLINK(dest, logic_pinger_setup[0], ip); PLINK(dest, logic_pinger_setup[0], period); PLINK(dest, logic_pinger_setup[0], timeout); #ifdef DNS_MODULE PLINK(dest, logic_pinger_setup[0], hostname); #endif PSIZE(dest, sizeof logic_pinger_setup[0]); // must be the last // size must be word-aligned! dest += sprintf(dest, "}; var pinger_data=["); } struct logic_pinger_setup_s *setup; for(;more_data<LOGIC_MAX_PINGER;) { setup = &logic_pinger_setup[more_data]; *dest++ = '{'; PDATA_IP(dest, (*setup), ip); PDATA(dest, (*setup), period); PDATA(dest, (*setup), timeout); #ifdef DNS_MODULE PDATA_PASC_STR(dest, (*setup), hostname); #endif --dest; // clear last PDATA-created comma *dest++ = '}'; *dest++ = ','; ++more_data; if(dest - buf > sizeof buf - 128) break; // data buffer capacity used up to 80% } if(more_data == LOGIC_MAX_PINGER) { more_data = 0; // reset pumping --dest; // remove last comma *dest++ = ']'; *dest++ = ';'; } tcp_put_tx_body(pkt, (unsigned char*)buf, dest - buf); return more_data; }
void zebra_read_ipv6 (int command, struct zserv *client, u_short length) { u_char type; u_char flags; struct in6_addr nexthop, *gate; u_char *lim; u_char *pnt; unsigned int ifindex; pnt = stream_pnt (client->ibuf); lim = pnt + length; type = stream_getc (client->ibuf); flags = stream_getc (client->ibuf); stream_get (&nexthop, client->ibuf, sizeof (struct in6_addr)); while (stream_pnt (client->ibuf) < lim) { int size; struct prefix_ipv6 p; ifindex = stream_getl (client->ibuf); memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = stream_getc (client->ibuf); size = PSIZE(p.prefixlen); stream_get (&p.prefix, client->ibuf, size); if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) gate = NULL; else gate = &nexthop; if (command == ZEBRA_IPV6_ROUTE_ADD) rib_add_ipv6 (type, flags, &p, gate, ifindex, 0, 0, 0); else rib_delete_ipv6 (type, flags, &p, gate, ifindex, 0); } }
unsigned logic_http_get_data(unsigned pkt, unsigned more_data) { char buf[1024]; char *dest = buf; if(more_data == 0) { dest+=sprintf((char*)dest,"var packfmt={"); PLINK(dest, logic_setup[0], flags); PLINK(dest, logic_setup[0], input); PLINK(dest, logic_setup[0], condition); PLINK(dest, logic_setup[0], action); PLINK(dest, logic_setup[0], output); PSIZE(dest, sizeof logic_setup[0]); // must be the last // size must be word-aligned! dest += sprintf(dest, "}; var data_logic_flags=%u; var data=[", logic_flags); } struct logic_setup_s *setup; for(;more_data<LOGIC_MAX_RULES;) { setup = &logic_setup[more_data]; *dest++ = '{'; PDATA(dest, (*setup), flags); PDATA(dest, (*setup), input); PDATA(dest, (*setup), condition); PDATA(dest, (*setup), action); PDATA(dest, (*setup), output); --dest; // clear last PDATA-created comma *dest++ = '}'; *dest++ = ','; ++more_data; if(dest - buf > sizeof buf - 128) break; // data buffer capacity used up to 80% } if(more_data == LOGIC_MAX_RULES) { more_data = 0; // reset pumping --dest; // remove last comma *dest++ = ']'; *dest++ = ';'; } tcp_put_tx_body(pkt, (unsigned char*)buf, dest - buf); return more_data; }
unsigned tstat_http_get_data(unsigned pkt, unsigned more_data) { char buf[1024]; char *dest = buf; if(more_data == 0) { dest+=sprintf((char*)dest,"var tstat_packfmt={"); PLINK(dest, tstat_setup[0], setpoint); PLINK(dest, tstat_setup[0], hyst); PLINK(dest, tstat_setup[0], sensor_no); PSIZE(dest, sizeof tstat_setup[0]); // must be the last // size must be word-aligned! dest += sprintf(dest, "}; var tstat_data=["); } struct tstat_setup_s *setup; for(;more_data<TSTAT_MAX_CHANNEL;) { setup = &tstat_setup[more_data]; *dest++ = '{'; PDATA_SIGNED(dest, (*setup), setpoint); PDATA(dest, (*setup), hyst); PDATA(dest, (*setup), sensor_no); --dest; // clear last PDATA-created comma *dest++ = '}'; *dest++ = ','; ++more_data; if(dest - buf > sizeof buf - 128) break; // data buffer capacity used up to 80% } if(more_data == TSTAT_MAX_CHANNEL) { more_data = 0; // reset pumping --dest; // remove last comma dest += sprintf(dest, "]; var termo_n_ch=%u;", TERMO_N_CH); } tcp_put_tx_body(pkt, (unsigned char*)buf, dest - buf); return more_data; }
/* * The zebra server sends the clients a ZEBRA_IPV4_ROUTE_ADD or a * ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following * situations: * - when the client starts up, and requests default information * by sending a ZEBRA_REDISTRIBUTE_DEFAULT_ADD to the zebra server, in the * - case of rip, ripngd, ospfd and ospf6d, when the client sends a * ZEBRA_REDISTRIBUTE_ADD as a result of the "redistribute" vty cmd, * - when the zebra server redistributes routes after it updates its rib * * The zebra server sends clients a ZEBRA_IPV4_ROUTE_DELETE or a * ZEBRA_IPV6_ROUTE_DELETE via zsend_route_multipath when: * - a "ip route" or "ipv6 route" vty command is issued, a prefix is * - deleted from zebra's rib, and this info * has to be redistributed to the clients * * XXX The ZEBRA_IPV*_ROUTE_ADD message is also sent by the client to the * zebra server when the client wants to tell the zebra server to add a * route to the kernel (zapi_ipv4_add etc. ). Since it's essentially the * same message being sent back and forth, this function and * zapi_ipv{4,6}_{add, delete} should be re-written to avoid code * duplication. */ int zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p, struct rib *rib) { int psize; struct stream *s; struct nexthop *nexthop; unsigned long nhnummark = 0; int nhnum = 0; u_char zapi_flags = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_IFINDEX; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Put command, type and nexthop. */ stream_putc (s, cmd); stream_putc (s, rib->type); stream_putc (s, rib->flags); /* * XXX no need to set ZAPI_MESSAGE_NEXTHOP if we are going to * send empty nexthop? */ if (cmd == ZEBRA_IPV4_ROUTE_ADD || ZEBRA_IPV6_ROUTE_ADD) zapi_flags |= ZAPI_MESSAGE_METRIC; stream_putc (s, zapi_flags); /* Prefix. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *) & p->u.prefix, psize); /* * XXX The message format sent by zebra below does not match the format * of the corresponding message expected by the zebra server * itself (e.g., see zread_ipv4_add). The nexthop_num is not set correctly, * (is there a bug on the client side if more than one segment is sent?) * nexthop ZEBRA_NEXTHOP_IPV4 is never set, ZEBRA_NEXTHOP_IFINDEX * is hard-coded. */ /* Nexthop */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) { nhnummark = stream_get_putp (s); stream_putc (s, 1); /* placeholder */ nhnum++; switch(nexthop->type) { case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); break; #ifdef HAVE_IPV6 case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: case NEXTHOP_TYPE_IPV6_IFNAME: stream_write (s, (u_char *) &nexthop->gate.ipv6, 16); break; #endif default: if (cmd == ZEBRA_IPV4_ROUTE_ADD || cmd == ZEBRA_IPV4_ROUTE_DELETE) { struct in_addr empty; memset (&empty, 0, sizeof (struct in_addr)); stream_write (s, (u_char *) &empty, IPV4_MAX_BYTELEN); } else { struct in6_addr empty; memset (&empty, 0, sizeof (struct in6_addr)); stream_write (s, (u_char *) &empty, IPV6_MAX_BYTELEN); } } /* Interface index. */ stream_putc (s, 1); stream_putl (s, nexthop->ifindex); break; } } /* Metric */ stream_putl (s, rib->metric); /* Write next-hop number */ if (nhnummark) stream_putc_at (s, nhnummark, nhnum); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0; }
static int dissect_zebra_request(proto_tree *tree, gboolean request, tvbuff_t *tvb, int offset, guint16 len, guint8 command) { guint32 prefix4; guint16 i; guint8 buffer6[16], prefixlen, message; proto_item *ti; proto_tree *msg_tree; proto_tree_add_uint(tree, hf_zebra_len, tvb, offset, 2, len); offset += 2; proto_tree_add_uint(tree, hf_zebra_command, tvb, offset, 1, command); offset += 1; switch(command) { case ZEBRA_INTERFACE_ADD: case ZEBRA_INTERFACE_UP: case ZEBRA_INTERFACE_DOWN: if (request) break; /* Request just subscribes to messages */ proto_tree_add_item(tree, hf_zebra_interface, tvb, offset, INTERFACE_NAMSIZ, ENC_ASCII|ENC_NA); offset += INTERFACE_NAMSIZ; proto_tree_add_item(tree, hf_zebra_index, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_zebra_intflags, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_zebra_metric, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_zebra_mtu, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_zebra_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case ZEBRA_INTERFACE_DELETE: proto_tree_add_item(tree, hf_zebra_interface, tvb, offset, INTERFACE_NAMSIZ, ENC_ASCII|ENC_NA); offset += INTERFACE_NAMSIZ; proto_tree_add_item(tree, hf_zebra_index, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case ZEBRA_INTERFACE_ADDRESS_ADD: case ZEBRA_INTERFACE_ADDRESS_DELETE: proto_tree_add_item(tree, hf_zebra_index, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_zebra_family, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* XXX - switch on the address family here, instead? */ if (len == 17) { /* IPv4 */ proto_tree_add_item(tree, hf_zebra_prefix4, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } else if (len == 41) { /* IPv6 */ proto_tree_add_item(tree, hf_zebra_prefix6, tvb, offset, 16, ENC_NA); offset += 16; } else break; proto_tree_add_item(tree, hf_zebra_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (len == 17) { /* IPv4 */ proto_tree_add_item(tree, hf_zebra_dest4, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } else if (len == 41) { /* IPv6 */ proto_tree_add_item(tree, hf_zebra_dest6, tvb, offset, 16, ENC_NA); offset += 16; } break; case ZEBRA_IPV4_ROUTE_ADD: case ZEBRA_IPV4_ROUTE_DELETE: proto_tree_add_item(tree, hf_zebra_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_zebra_rtflags, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; message = tvb_get_guint8(tvb, offset); ti = proto_tree_add_uint(tree, hf_zebra_message, tvb, offset, 1, message); msg_tree = proto_item_add_subtree(ti, ett_message); proto_tree_add_boolean(msg_tree, hf_zebra_msg_nexthop, tvb, offset, 1, message); proto_tree_add_boolean(msg_tree, hf_zebra_msg_index, tvb, offset, 1, message); proto_tree_add_boolean(msg_tree, hf_zebra_msg_distance, tvb, offset, 1, message); proto_tree_add_boolean(msg_tree, hf_zebra_msg_metric, tvb, offset, 1, message); offset += 1; prefixlen = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_zebra_prefixlen, tvb, offset, 1, prefixlen); offset += 1; prefix4 = 0; tvb_memcpy(tvb, (guint8 *)&prefix4, offset, MIN((unsigned) PSIZE(prefixlen), sizeof prefix4)); proto_tree_add_ipv4(tree, hf_zebra_prefix4, tvb, offset, PSIZE(prefixlen), prefix4); offset += PSIZE(prefixlen); if (message & ZEBRA_ZAPI_MESSAGE_NEXTHOP) { i = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_zebra_nexthopnum, tvb, offset, 1, i); offset += 1; if (i>len) break; /* Sanity */ while (i--) { proto_tree_add_item(tree, hf_zebra_nexthop4, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } } if (message & ZEBRA_ZAPI_MESSAGE_IFINDEX) { i = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_zebra_indexnum, tvb, offset, 1, i); offset += 1; if (i>len) break; /* Sanity */ while (i--) { proto_tree_add_item(tree, hf_zebra_index, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } } if (message & ZEBRA_ZAPI_MESSAGE_DISTANCE) { proto_tree_add_item(tree, hf_zebra_distance, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } if (message & ZEBRA_ZAPI_MESSAGE_METRIC) { proto_tree_add_item(tree, hf_zebra_metric, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } break; case ZEBRA_IPV6_ROUTE_ADD: case ZEBRA_IPV6_ROUTE_DELETE: proto_tree_add_item(tree, hf_zebra_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_zebra_rtflags, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; message = tvb_get_guint8(tvb, offset); ti = proto_tree_add_uint(tree, hf_zebra_message, tvb, offset, 1, message); msg_tree = proto_item_add_subtree(ti, ett_message); proto_tree_add_boolean(msg_tree, hf_zebra_msg_nexthop, tvb, offset, 1, message); proto_tree_add_boolean(msg_tree, hf_zebra_msg_index, tvb, offset, 1, message); proto_tree_add_boolean(msg_tree, hf_zebra_msg_distance, tvb, offset, 1, message); proto_tree_add_boolean(msg_tree, hf_zebra_msg_metric, tvb, offset, 1, message); offset += 1; prefixlen = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_zebra_prefixlen, tvb, offset, 1, prefixlen); offset += 1; memset(buffer6, '\0', sizeof buffer6); tvb_memcpy(tvb, buffer6, offset, MIN((unsigned) PSIZE(prefixlen), sizeof buffer6)); proto_tree_add_ipv6(tree, hf_zebra_prefix6, tvb, offset, PSIZE(prefixlen), buffer6); offset += PSIZE(prefixlen); if (message & ZEBRA_ZAPI_MESSAGE_NEXTHOP) { i = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_zebra_nexthopnum, tvb, offset, 1, i); offset += 1; if (i>len) break; /* Sanity */ while (i--) { proto_tree_add_item(tree, hf_zebra_nexthop6, tvb, offset, 16, ENC_NA); offset += 16; } } if (message & ZEBRA_ZAPI_MESSAGE_IFINDEX) { i = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_zebra_indexnum, tvb, offset, 1, i); offset += 1; if (i>len) break; /* Sanity */ while (i--) { proto_tree_add_item(tree, hf_zebra_index, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } } if (message & ZEBRA_ZAPI_MESSAGE_DISTANCE) { proto_tree_add_item(tree, hf_zebra_distance, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } if (message & ZEBRA_ZAPI_MESSAGE_METRIC) { proto_tree_add_item(tree, hf_zebra_metric, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } break; case ZEBRA_REDISTRIBUTE_ADD: case ZEBRA_REDISTRIBUTE_DELETE: proto_tree_add_item(tree, hf_zebra_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case ZEBRA_REDISTRIBUTE_DEFAULT_ADD: case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE: break; case ZEBRA_IPV4_NEXTHOP_LOOKUP: proto_tree_add_item(tree, hf_zebra_nexthop4, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_zebra_metric, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case ZEBRA_IPV6_NEXTHOP_LOOKUP: /* Not yet implemeted in ZEBRA */ break; } return offset; }
void ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) { u_char message; u_char distance; u_char flags; int psize; struct stream *s; struct ospf_path *path; struct listnode *node; if (zclient->redist[ZEBRA_ROUTE_OSPF]) { message = 0; flags = 0; /* OSPF pass nexthop and metric */ SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (message, ZAPI_MESSAGE_METRIC); /* Distance value. */ distance = ospf_distance_apply (p, or); if (distance) SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); /* Make packet. */ s = zclient->obuf; stream_reset (s); /* Put command, type, flags, message. */ zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD); stream_putc (s, ZEBRA_ROUTE_OSPF); stream_putc (s, flags); stream_putc (s, message); stream_putw (s, SAFI_UNICAST); /* Put prefix information. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *) & p->prefix, psize); /* Nexthop count. */ stream_putc (s, or->paths->count); /* Nexthop, ifindex, distance and metric information. */ for (ALL_LIST_ELEMENTS_RO (or->paths, node, path)) { if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX); stream_put_in_addr (s, &path->nexthop); stream_putl (s, path->ifindex); } else if (path->nexthop.s_addr != INADDR_ANY) { stream_putc (s, ZEBRA_NEXTHOP_IPV4); stream_put_in_addr (s, &path->nexthop); } else { stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); if (path->ifindex) stream_putl (s, path->ifindex); else stream_putl (s, 0); } if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("Zebra: Route add %s/%d nexthop %s", inet_ntop(AF_INET, &p->prefix, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET, &path->nexthop, buf[1], sizeof(buf[1]))); } } if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) stream_putc (s, distance); if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) { if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) stream_putl (s, or->cost + or->u.ext.type2_cost); else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) stream_putl (s, or->u.ext.type2_cost); else stream_putl (s, or->cost); } stream_putw_at (s, 0, stream_get_endp (s)); zclient_send_message(zclient); }
/* Zebra server IPv4 prefix delete function. */ static void zread_ipv4_delete (struct zserv *client, u_short length) { int i; struct stream *s; struct zapi_ipv4 api; struct in_addr nexthop; unsigned long ifindex; struct prefix_ipv4 p; u_char nexthop_num; u_char nexthop_type; u_char ifname_len; s = client->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. */ memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; 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)) { nexthop_num = stream_getc (s); for (i = 0; i < nexthop_num; i++) { nexthop_type = stream_getc (s); switch (nexthop_type) { case ZEBRA_NEXTHOP_IFINDEX: ifindex = stream_getl (s); break; case ZEBRA_NEXTHOP_IFNAME: ifname_len = stream_getc (s); stream_forward (s, ifname_len); break; case ZEBRA_NEXTHOP_IPV4: nexthop.s_addr = stream_get_ipv4 (s); break; case ZEBRA_NEXTHOP_IPV6: stream_forward (s, IPV6_MAX_BYTELEN); break; } } } /* Distance. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); else api.distance = 0; /* Metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; rib_delete_ipv4 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table); }
/* Zebra server IPv6 prefix add function. */ static void zread_ipv6_add (struct zserv *client, u_short length) { int i; struct stream *s; struct zapi_ipv6 api; struct in6_addr nexthop; unsigned long ifindex; struct prefix_ipv6 p; s = client->ibuf; ifindex = 0; 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); /* IPv4 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)) { u_char nexthop_type; api.nexthop_num = stream_getc (s); for (i = 0; i < api.nexthop_num; i++) { nexthop_type = stream_getc (s); switch (nexthop_type) { case ZEBRA_NEXTHOP_IPV6: stream_get (&nexthop, s, 16); break; case ZEBRA_NEXTHOP_IFINDEX: ifindex = stream_getl (s); break; } } } 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 (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, 0, api.metric, api.distance); else rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, 0, api.metric, api.distance); }
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; }
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; char prefixstr[128], nexthopstr[128]; 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; /* log */ if (IS_OSPF6_DUMP_ZEBRA) { prefix2str ((struct prefix *)&p, prefixstr, sizeof (prefixstr)); inet_ntop (AF_INET6, &nexthop, nexthopstr, sizeof (nexthopstr)); if (command == ZEBRA_IPV6_ROUTE_ADD) zlog_info ("ZEBRA: Receive add %s route: %s nexthop:%s ifindex:%ld", zebra_route_name [api.type], prefixstr, nexthopstr, ifindex); else zlog_info ("ZEBRA: Receive remove %s route: %s nexthop:%s ifindex:%ld", zebra_route_name [api.type], prefixstr, nexthopstr, ifindex); } if (command == ZEBRA_IPV6_ROUTE_ADD) ospf6_asbr_route_add (api.type, ifindex, (struct prefix *) &p, api.nexthop_num, nexthop); else ospf6_asbr_route_remove (api.type, ifindex, (struct prefix *) &p); if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) free (nexthop); return 0; }
void menuModelSensor(uint8_t event) { TelemetrySensor * sensor = & g_model.telemetrySensors[s_currIdx]; SUBMENU(STR_MENUSENSOR, SENSOR_FIELD_MAX, {0, 0, sensor->type == TELEM_TYPE_CALCULATED ? (uint8_t)0 : (uint8_t)1, SENSOR_UNIT_ROWS, SENSOR_PREC_ROWS, SENSOR_PARAM1_ROWS, SENSOR_PARAM2_ROWS, SENSOR_PARAM3_ROWS, SENSOR_PARAM4_ROWS, SENSOR_AUTOOFFSET_ROWS, SENSOR_FILTER_ROWS, SENSOR_PERSISTENT_ROWS, 0 }); lcd_outdezAtt(PSIZE(TR_MENUSENSOR)*FW+1, 0, s_currIdx+1, INVERS|LEFT); putsTelemetryChannelValue(SENSOR_2ND_COLUMN, 0, s_currIdx, getValue(MIXSRC_FIRST_TELEM+3*s_currIdx), LEFT); int8_t sub = m_posVert; for (uint8_t i=0; i<LCD_LINES-1; i++) { coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH; uint8_t k = i + s_pgOfs; for (int j=0; j<k; j++) { if (mstate_tab[j+1] == HIDDEN_ROW) k++; } uint8_t attr = (sub==k ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0); switch (k) { case SENSOR_FIELD_NAME: editSingleName(SENSOR_2ND_COLUMN, y, STR_NAME, sensor->label, TELEM_LABEL_LEN, event, attr); break; case SENSOR_FIELD_TYPE: sensor->type = selectMenuItem(SENSOR_2ND_COLUMN, y, NO_INDENT(STR_TYPE), STR_VSENSORTYPES, sensor->type, 0, 1, attr, event); if (attr && checkIncDec_Ret) { sensor->instance = 0; if (sensor->type == TELEM_TYPE_CALCULATED) { sensor->param = 0; sensor->autoOffset = 0; sensor->filter = 0; } } break; case SENSOR_FIELD_ID: if (sensor->type == TELEM_TYPE_CUSTOM) { lcd_putsLeft(y, STR_ID); lcd_outhex4(SENSOR_2ND_COLUMN, y, sensor->id, LEFT|(m_posHorz==0 ? attr : 0)); lcd_outdezAtt(SENSOR_3RD_COLUMN, y, sensor->instance, LEFT|(m_posHorz==1 ? attr : 0)); if (attr) { switch (m_posHorz) { case 0: CHECK_INCDEC_MODELVAR_ZERO(event, sensor->id, 0xffff); break; case 1: CHECK_INCDEC_MODELVAR_ZERO(event, sensor->instance, 0xff); break; } } } else { sensor->formula = selectMenuItem(SENSOR_2ND_COLUMN, y, STR_FORMULA, STR_VFORMULAS, sensor->formula, 0, TELEM_FORMULA_LAST, attr, event); if (attr && checkIncDec_Ret) { sensor->param = 0; if (sensor->formula == TELEM_FORMULA_CELL) { sensor->unit = UNIT_VOLTS; sensor->prec = 2; } else if (sensor->formula == TELEM_FORMULA_DIST) { sensor->unit = UNIT_DIST; sensor->prec = 0; } else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) { sensor->unit = UNIT_MAH; sensor->prec = 0; } } } break; case SENSOR_FIELD_UNIT: lcd_putsLeft(y, "Unit"); // TODO flash saving with selectMenuItem where I copied those 2 lines? lcd_putsiAtt(SENSOR_2ND_COLUMN, y, STR_VTELEMUNIT, sensor->unit, attr); if (attr) { CHECK_INCDEC_MODELVAR_ZERO(event, sensor->unit, UNIT_MAX); if (checkIncDec_Ret) { telemetryItems[s_currIdx].clear(); } } break; case SENSOR_FIELD_PRECISION: sensor->prec = selectMenuItem(SENSOR_2ND_COLUMN, y, STR_PRECISION, STR_VPREC, sensor->prec, 0, 2, attr, event); if (attr && checkIncDec_Ret) { telemetryItems[s_currIdx].clear(); } break; case SENSOR_FIELD_PARAM1: if (sensor->type == TELEM_TYPE_CALCULATED) { if (sensor->formula == TELEM_FORMULA_CELL) { lcd_putsLeft(y, STR_CELLSENSOR); putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->cell.source ? MIXSRC_FIRST_TELEM+3*(sensor->cell.source-1) : 0, attr); if (attr) { sensor->cell.source = checkIncDec(event, sensor->cell.source, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isCellsSensor); } break; } else if (sensor->formula == TELEM_FORMULA_DIST) { lcd_putsLeft(y, STR_GPSSENSOR); putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->dist.gps ? MIXSRC_FIRST_TELEM+3*(sensor->dist.gps-1) : 0, attr); if (attr) { sensor->dist.gps = checkIncDec(event, sensor->dist.gps, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isGPSSensor); } break; } else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) { lcd_putsLeft(y, STR_CURRENTSENSOR); putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->consumption.source ? MIXSRC_FIRST_TELEM+3*(sensor->consumption.source-1) : 0, attr); if (attr) { sensor->consumption.source = checkIncDec(event, sensor->consumption.source, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isCurrentSensor); } break; } } else { if (sensor->unit == UNIT_RPMS) { lcd_putsLeft(y, NO_INDENT(STR_BLADES)); if (attr) CHECK_INCDEC_MODELVAR(event, sensor->custom.ratio, 1, 30000); lcd_outdezAtt(SENSOR_2ND_COLUMN, y, sensor->custom.ratio, LEFT|attr); break; } else { lcd_putsLeft(y, STR_RATIO); if (attr) CHECK_INCDEC_MODELVAR(event, sensor->custom.ratio, 0, 30000); if (sensor->custom.ratio == 0) lcd_putcAtt(SENSOR_2ND_COLUMN, y, '-', attr); else lcd_outdezAtt(SENSOR_2ND_COLUMN, y, sensor->custom.ratio, LEFT|attr|PREC1); break; } } // no break case SENSOR_FIELD_PARAM2: if (sensor->type == TELEM_TYPE_CALCULATED) { if (sensor->formula == TELEM_FORMULA_CELL) { sensor->cell.index = selectMenuItem(SENSOR_2ND_COLUMN, y, STR_CELLINDEX, STR_VCELLINDEX, sensor->cell.index, 0, 8, attr, event); break; } else if (sensor->formula == TELEM_FORMULA_DIST) { lcd_putsLeft(y, STR_ALTSENSOR); putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->dist.alt ? MIXSRC_FIRST_TELEM+3*(sensor->dist.alt-1) : 0, attr); if (attr) { sensor->dist.alt = checkIncDec(event, sensor->dist.alt, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isAltSensor); } break; } } else { lcd_putsLeft(y, NO_INDENT(STR_OFFSET)); if (attr) CHECK_INCDEC_MODELVAR(event, sensor->custom.offset, -30000, +30000); if (sensor->prec > 0) attr |= (sensor->prec == 2 ? PREC2 : PREC1); lcd_outdezAtt(SENSOR_2ND_COLUMN, y, sensor->custom.offset, LEFT|attr); break; } // no break case SENSOR_FIELD_PARAM3: // no break case SENSOR_FIELD_PARAM4: { putsStrIdx(0, y, NO_INDENT(STR_SOURCE), k-SENSOR_FIELD_PARAM1+1); int8_t & source = sensor->calc.sources[k-SENSOR_FIELD_PARAM1]; if (attr) { source = checkIncDec(event, source, -MAX_SENSORS, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable); } if (source < 0) { lcd_putcAtt(SENSOR_2ND_COLUMN, y, '-', attr); putsMixerSource(lcdNextPos, y, MIXSRC_FIRST_TELEM+3*(-1-source), attr); } else { putsMixerSource(SENSOR_2ND_COLUMN, y, source ? MIXSRC_FIRST_TELEM+3*(source-1) : 0, attr); } break; } case SENSOR_FIELD_AUTOOFFSET: ON_OFF_MENU_ITEM(sensor->autoOffset, SENSOR_2ND_COLUMN, y, STR_AUTOOFFSET, attr, event); break; case SENSOR_FIELD_ONLYPOSITIVE: ON_OFF_MENU_ITEM(sensor->onlyPositive, SENSOR_2ND_COLUMN, y, STR_ONLYPOSITIVE, attr, event); break; case SENSOR_FIELD_FILTER: ON_OFF_MENU_ITEM(sensor->filter, SENSOR_2ND_COLUMN, y, STR_FILTER, attr, event); break; case SENSOR_FIELD_PERSISTENT: ON_OFF_MENU_ITEM(sensor->persistent, SENSOR_2ND_COLUMN, y, NO_INDENT(STR_PERSISTENT), attr, event); break; case SENSOR_FIELD_LOGS: ON_OFF_MENU_ITEM(sensor->logs, SENSOR_2ND_COLUMN, y, STR_LOGS, attr, event); break; } } }
/* 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; }
static void isis_zebra_route_add_ipv4 (struct prefix *prefix, struct isis_route_info *route_info) { u_char message, flags; int psize; struct stream *stream; struct isis_nexthop *nexthop; struct listnode *node; if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) return; if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_ISIS], VRF_DEFAULT)) { message = 0; flags = 0; SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (message, ZAPI_MESSAGE_METRIC); #if 0 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); #endif stream = zclient->obuf; stream_reset (stream); zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); /* type */ stream_putc (stream, ZEBRA_ROUTE_ISIS); /* flags */ stream_putc (stream, flags); /* message */ stream_putc (stream, message); /* SAFI */ stream_putw (stream, SAFI_UNICAST); /* prefix information */ psize = PSIZE (prefix->prefixlen); stream_putc (stream, prefix->prefixlen); stream_write (stream, (u_char *) & prefix->u.prefix4, psize); stream_putc (stream, listcount (route_info->nexthops)); /* Nexthop, ifindex, distance and metric information */ for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop)) { /* FIXME: can it be ? */ if (nexthop->ip.s_addr != INADDR_ANY) { stream_putc (stream, ZEBRA_NEXTHOP_IPV4); stream_put_in_addr (stream, &nexthop->ip); } else { stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX); stream_putl (stream, nexthop->ifindex); } } #if 0 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) stream_putc (stream, route_info->depth); #endif if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) stream_putl (stream, route_info->cost); stream_putw_at (stream, 0, stream_get_endp (stream)); zclient_send_message(zclient); SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); }
void bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi, int type, unsigned int seq) { struct stream *obuf; struct attr *attr; struct peer *peer; int plen; int safi = 0; /* Make dump stream. */ obuf = bgp_dump_obuf; stream_reset (obuf); attr = info->attr; peer = info->peer; /* We support MRT's old format. */ if (type == MSG_TABLE_DUMP) { bgp_dump_header (obuf, MSG_TABLE_DUMP, afi); stream_putw (obuf, 0); /* View # */ stream_putw (obuf, seq); /* Sequence number. */ } else { bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY); stream_putl (obuf, info->uptime); /* Time Last Change */ stream_putw (obuf, afi); /* Address Family */ stream_putc (obuf, safi); /* SAFI */ } if (afi == AFI_IP) { if (type == MSG_TABLE_DUMP) { /* Prefix */ stream_put_in_addr (obuf, &p->u.prefix4); stream_putc (obuf, p->prefixlen); /* Status */ stream_putc (obuf, 1); /* Originated */ stream_putl (obuf, info->uptime); /* Peer's IP address */ stream_put_in_addr (obuf, &peer->su.sin.sin_addr); /* Peer's AS number. */ stream_putw (obuf, peer->as); /* Dump attribute. */ bgp_dump_routes_attr (obuf, attr, p); } else { /* Next-Hop-Len */ stream_putc (obuf, IPV4_MAX_BYTELEN); stream_put_in_addr (obuf, &attr->nexthop); stream_putc (obuf, p->prefixlen); plen = PSIZE (p->prefixlen); stream_put (obuf, &p->u.prefix4, plen); bgp_dump_routes_attr (obuf, attr, p); } } #ifdef HAVE_IPV6 else if (afi == AFI_IP6) { if (type == MSG_TABLE_DUMP) { /* Prefix */ stream_write (obuf, (u_char *)&p->u.prefix6, IPV6_MAX_BYTELEN); stream_putc (obuf, p->prefixlen); /* Status */ stream_putc (obuf, 1); /* Originated */ stream_putl (obuf, info->uptime); /* Peer's IP address */ stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN); /* Peer's AS number. */ stream_putw (obuf, peer->as); /* Dump attribute. */ bgp_dump_routes_attr (obuf, attr, p); } else { ; } } #endif /* HAVE_IPV6 */ /* Set length. */ bgp_dump_set_size (obuf, type); fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_routes.fp); fflush (bgp_dump_routes.fp); }
const pm_char *openLogs() { // Determine and set log file filename FRESULT result; DIR folder; char filename[34]; // /LOGS/modelnamexxx-2013-01-01.log if (!sdMounted()) return STR_NO_SDCARD; if (sdGetFreeSectors() == 0) return STR_SDCARD_FULL; // check and create folder here strcpy_P(filename, STR_LOGS_PATH); result = f_opendir(&folder, filename); if (result != FR_OK) { if (result == FR_NO_PATH) result = f_mkdir(filename); if (result != FR_OK) return SDCARD_ERROR(result); } filename[sizeof(LOGS_PATH)-1] = '/'; memcpy(&filename[sizeof(LOGS_PATH)], g_model.header.name, sizeof(g_model.header.name)); filename[sizeof(LOGS_PATH)+sizeof(g_model.header.name)] = '\0'; uint8_t i = sizeof(LOGS_PATH)+sizeof(g_model.header.name)-1; uint8_t len = 0; while (i>sizeof(LOGS_PATH)-1) { if (!len && filename[i]) len = i+1; if (len) { if (filename[i]) filename[i] = idx2char(filename[i]); else filename[i] = '_'; } i--; } if (len == 0) { uint8_t num = g_eeGeneral.currModel + 1; strcpy_P(&filename[sizeof(LOGS_PATH)], STR_MODEL); filename[sizeof(LOGS_PATH) + PSIZE(TR_MODEL)] = (char)((num / 10) + '0'); filename[sizeof(LOGS_PATH) + PSIZE(TR_MODEL) + 1] = (char)((num % 10) + '0'); len = sizeof(LOGS_PATH) + PSIZE(TR_MODEL) + 2; } char * tmp = &filename[len]; #if defined(RTCLOCK) tmp = strAppendDate(&filename[len]); #endif strcpy_P(tmp, STR_LOGS_EXT); result = f_open(&g_oLogFile, filename, FA_OPEN_ALWAYS | FA_WRITE); if (result != FR_OK) { return SDCARD_ERROR(result); } if (f_size(&g_oLogFile) == 0) { writeHeader(); } else { result = f_lseek(&g_oLogFile, f_size(&g_oLogFile)); // append if (result != FR_OK) { return SDCARD_ERROR(result); } } return NULL; }
void isis_zebra_route_add_ipv4 (struct prefix *prefix, struct isis_route_info *route_info) { u_char message, flags; int psize; struct stream *stream; struct isis_nexthop *nexthop; struct listnode *node; if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC)) return; if (zclient->redist[ZEBRA_ROUTE_ISIS]) { message = 0; flags = 0; SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (message, ZAPI_MESSAGE_METRIC); #if 0 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); #endif stream = zclient->obuf; stream_reset (stream); /* Length place holder. */ stream_putw (stream, 0); /* command */ stream_putc (stream, ZEBRA_IPV4_ROUTE_ADD); /* type */ stream_putc (stream, ZEBRA_ROUTE_ISIS); /* flags */ stream_putc (stream, flags); /* message */ stream_putc (stream, message); /* prefix information */ psize = PSIZE (prefix->prefixlen); stream_putc (stream, prefix->prefixlen); stream_write (stream, (u_char *) & prefix->u.prefix4, psize); stream_putc (stream, listcount (route_info->nexthops)); /* Nexthop, ifindex, distance and metric information */ for (node = listhead (route_info->nexthops); node; nextnode (node)) { nexthop = getdata (node); /* FIXME: can it be ? */ if (nexthop->ip.s_addr != INADDR_ANY) { stream_putc (stream, ZEBRA_NEXTHOP_IPV4); stream_put_in_addr (stream, &nexthop->ip); } else { stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX); stream_putl (stream, nexthop->ifindex); } } #if 0 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) stream_putc (stream, route_info->depth); #endif if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) stream_putl (stream, route_info->cost); stream_putw_at (stream, 0, stream_get_endp (stream)); writen (zclient->sock, stream->data, stream_get_endp (stream)); } }
/* * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update rib and * add kernel route. */ static void zread_ipv4_add (struct zserv *client, u_short length) { int i; struct rib *rib; struct prefix_ipv4 p; u_char message; struct in_addr nexthop; u_char nexthop_num; u_char nexthop_type; struct stream *s; unsigned int ifindex; u_char ifname_len; /* Get input stream. */ s = client->ibuf; /* Allocate new rib. */ rib = XMALLOC (MTYPE_RIB, sizeof (struct rib)); memset (rib, 0, sizeof (struct rib)); /* Type, flags, message. */ rib->type = stream_getc (s); rib->flags = stream_getc (s); message = stream_getc (s); rib->uptime = time (NULL); /* IPv4 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc (s); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop parse. */ if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) { nexthop_num = stream_getc (s); for (i = 0; i < nexthop_num; i++) { nexthop_type = stream_getc (s); switch (nexthop_type) { case ZEBRA_NEXTHOP_IFINDEX: ifindex = stream_getl (s); nexthop_ifindex_add (rib, ifindex); break; case ZEBRA_NEXTHOP_IFNAME: ifname_len = stream_getc (s); stream_forward (s, ifname_len); break; case ZEBRA_NEXTHOP_IPV4: nexthop.s_addr = stream_get_ipv4 (s); nexthop_ipv4_add (rib, &nexthop); break; case ZEBRA_NEXTHOP_IPV6: stream_forward (s, IPV6_MAX_BYTELEN); break; case ZEBRA_NEXTHOP_BLACKHOLE: nexthop_blackhole_add (rib); break; } } } /* Distance. */ if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) rib->distance = stream_getc (s); /* Metric. */ if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) rib->metric = stream_getl (s); rib_add_ipv4_multipath (&p, rib); }
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_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; }