// SPDX-License-Identifier: GPL-2.0-or-later /* * qpb.h * * @copyright Copyright (C) 2016 Sproute Networks, Inc. * * @author Avneesh Sachdev */ /* * Main public header file for the quagga protobuf library. */ #ifndef _QPB_H #define _QPB_H #include "nexthop.h" #include "prefix.h" #include "qpb/qpb.pb-c.h" #include "qpb/qpb_allocator.h" /* * qpb__address_family__set */ #define qpb_address_family_set qpb__address_family__set static inline int qpb__address_family__set(Qpb__AddressFamily *pb_family, uint8_t family) { switch (family) { case AF_INET: *pb_family = QPB__ADDRESS_FAMILY__IPV4; return 1; case AF_INET6: *pb_family = QPB__ADDRESS_FAMILY__IPV6; return 1; default: *pb_family = QPB__ADDRESS_FAMILY__UNKNOWN_AF; } return 0; } /* * qpb__address_family__get */ #define qpb_address_family_get qpb__address_family__get static inline int qpb__address_family__get(Qpb__AddressFamily pb_family, uint8_t *family) { switch (pb_family) { case QPB__ADDRESS_FAMILY__IPV4: *family = AF_INET; return 1; case QPB__ADDRESS_FAMILY__IPV6: *family = AF_INET6; return 1; case QPB__ADDRESS_FAMILY__UNKNOWN_AF: return 0; case _QPB__ADDRESS_FAMILY_IS_INT_SIZE: return 0; } return 0; } /* * qpb__l3_prefix__create */ #define qpb_l3_prefix_create qpb__l3_prefix__create static inline Qpb__L3Prefix *qpb__l3_prefix__create(qpb_allocator_t *allocator, struct prefix *p) { Qpb__L3Prefix *prefix; prefix = QPB_ALLOC(allocator, typeof(*prefix)); if (!prefix) { return NULL; } qpb__l3_prefix__init(prefix); prefix->length = p->prefixlen; prefix->bytes.len = (p->prefixlen + 7) / 8; prefix->bytes.data = qpb_alloc(allocator, prefix->bytes.len); if (!prefix->bytes.data) { return NULL; } memcpy(prefix->bytes.data, &p->u.prefix, prefix->bytes.len); return prefix; } /* * qpb__l3_prefix__get */ #define qpb_l3_prefix_get qpb__l3_prefix__get static inline int qpb__l3_prefix__get(const Qpb__L3Prefix *pb_prefix, uint8_t family, struct prefix *prefix) { switch (family) { case AF_INET: memset((struct prefix_ipv4 *)prefix, 0, sizeof(struct prefix_ipv4)); break; case AF_INET6: memset((struct prefix_ipv6 *)prefix, 0, sizeof(struct prefix_ipv6)); break; default: memset(prefix, 0, sizeof(*prefix)); } prefix->prefixlen = pb_prefix->length; prefix->family = family; memcpy(&prefix->u.prefix, pb_prefix->bytes.data, pb_prefix->bytes.len); return 1; } /* * qpb__protocol__set * * Translate a quagga route type to a protobuf protocol. */ #define qpb_protocol_set qpb__protocol__set static inline int qpb__protocol__set(Qpb__Protocol *pb_proto, int route_type) { switch (route_type) { case ZEBRA_ROUTE_KERNEL: *pb_proto = QPB__PROTOCOL__KERNEL; break; case ZEBRA_ROUTE_CONNECT: *pb_proto = QPB__PROTOCOL__CONNECTED; break; case ZEBRA_ROUTE_STATIC: *pb_proto = QPB__PROTOCOL__STATIC; break; case ZEBRA_ROUTE_RIP: *pb_proto = QPB__PROTOCOL__RIP; break; case ZEBRA_ROUTE_RIPNG: *pb_proto = QPB__PROTOCOL__RIPNG; break; case ZEBRA_ROUTE_OSPF: case ZEBRA_ROUTE_OSPF6: *pb_proto = QPB__PROTOCOL__OSPF; break; case ZEBRA_ROUTE_ISIS: *pb_proto = QPB__PROTOCOL__ISIS; break; case ZEBRA_ROUTE_BGP: *pb_proto = QPB__PROTOCOL__BGP; break; case ZEBRA_ROUTE_HSLS: case ZEBRA_ROUTE_OLSR: case ZEBRA_ROUTE_MAX: case ZEBRA_ROUTE_SYSTEM: default: *pb_proto = QPB__PROTOCOL__OTHER; } return 1; } /* * qpb__ipv4_address__create */ static inline Qpb__Ipv4Address * qpb__ipv4_address__create(qpb_allocator_t *allocator, struct in_addr *addr) { Qpb__Ipv4Address *v4; v4 = QPB_ALLOC(allocator, typeof(*v4)); if (!v4) { return NULL; } qpb__ipv4_address__init(v4); v4->value = ntohl(addr->s_addr); return v4; } /* * qpb__ipv4_address__get */ static inline int qpb__ipv4_address__get(const Qpb__Ipv4Address *v4, struct in_addr *addr) { addr->s_addr = htonl(v4->value); return 1; } /* * qpb__ipv6_address__create */ static inline Qpb__Ipv6Address * qpb__ipv6_address__create(qpb_allocator_t *allocator, struct in6_addr *addr) { Qpb__Ipv6Address *v6; v6 = QPB_ALLOC(allocator, typeof(*v6)); if (!v6) return NULL; qpb__ipv6_address__init(v6); v6->bytes.len = 16; v6->bytes.data = qpb_alloc(allocator, 16); if (!v6->bytes.data) return NULL; memcpy(v6->bytes.data, addr->s6_addr, v6->bytes.len); return v6; } /* * qpb__ipv6_address__get * * Read out information from a protobuf ipv6 address structure. */ static inline int qpb__ipv6_address__get(const Qpb__Ipv6Address *v6, struct in6_addr *addr) { if (v6->bytes.len != 16) return 0; memcpy(addr->s6_addr, v6->bytes.data, v6->bytes.len); return 1; } /* * qpb__l3_address__create */ #define qpb_l3_address_create qpb__l3_address__create static inline Qpb__L3Address * qpb__l3_address__create(qpb_allocator_t *allocator, union g_addr *addr, uint8_t family) { Qpb__L3Address *l3_addr; l3_addr = QPB_ALLOC(allocator, typeof(*l3_addr)); if (!l3_addr) return NULL; qpb__l3_address__init(l3_addr); switch (family) { case AF_INET: l3_addr->v4 = qpb__ipv4_address__create(allocator, &addr->ipv4); if (!l3_addr->v4) return NULL; break; case AF_INET6: l3_addr->v6 = qpb__ipv6_address__create(allocator, &addr->ipv6); if (!l3_addr->v6) return NULL; break; } return l3_addr; } /* * qpb__l3_address__get * * Read out a gateway address from a protobuf l3 address. */ #define qpb_l3_address_get qpb__l3_address__get static inline int qpb__l3_address__get(const Qpb__L3Address *l3_addr, uint8_t *family, union g_addr *addr) { if (l3_addr->v4) { qpb__ipv4_address__get(l3_addr->v4, &addr->ipv4); *family = AF_INET; return 1; } if (l3_addr->v6) { qpb__ipv6_address__get(l3_addr->v6, &addr->ipv6); *family = AF_INET6; return 1; } return 0; } /* * qpb__if_identifier__create */ #define qpb_if_identifier_create qpb__if_identifier__create static inline Qpb__IfIdentifier * qpb__if_identifier__create(qpb_allocator_t *allocator, uint if_index) { Qpb__IfIdentifier *if_id; if_id = QPB_ALLOC(allocator, typeof(*if_id)); if (!if_id) { return NULL; } qpb__if_identifier__init(if_id); if_id->has_index = 1; if_id->index = if_index; return if_id; } /* * qpb__if_identifier__get * * Get interface name and/or if_index from an if identifier. */ #define qpb_if_identifier_get qpb__if_identifier__get static inline int qpb__if_identifier__get(Qpb__IfIdentifier *if_id, uint *if_index, char **name) { char *str; uint ix; if (!if_index) if_index = &ix; if (!name) name = &str; if (if_id->has_index) *if_index = if_id->index; else *if_index = 0; *name = if_id->name; return 1; } #endif