diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/checksum.c | 18 | ||||
| -rw-r--r-- | lib/checksum.h | 27 | ||||
| -rw-r--r-- | lib/command.c | 1 | ||||
| -rw-r--r-- | lib/command.h | 1 | ||||
| -rw-r--r-- | lib/if.c | 41 | ||||
| -rw-r--r-- | lib/if.h | 7 | ||||
| -rw-r--r-- | lib/ipaddr.h | 3 | ||||
| -rw-r--r-- | lib/json.c | 5 | ||||
| -rw-r--r-- | lib/json.h | 2 | ||||
| -rw-r--r-- | lib/linklist.c | 15 | ||||
| -rw-r--r-- | lib/linklist.h | 20 | ||||
| -rw-r--r-- | lib/route_types.txt | 2 | ||||
| -rw-r--r-- | lib/sockunion.c | 2 | ||||
| -rw-r--r-- | lib/sockunion.h | 1 | ||||
| -rw-r--r-- | lib/zclient.c | 22 | ||||
| -rw-r--r-- | lib/zclient.h | 4 |
16 files changed, 169 insertions, 2 deletions
diff --git a/lib/checksum.c b/lib/checksum.c index 18e3850474..3473370041 100644 --- a/lib/checksum.c +++ b/lib/checksum.c @@ -46,6 +46,24 @@ int /* return checksum in low-order 16 bits */ return (answer); } +int in_cksum_with_ph4(struct ipv4_ph *ph, void *data, int nbytes) +{ + uint8_t dat[sizeof(struct ipv4_ph) + nbytes]; + + memcpy(dat, ph, sizeof(struct ipv4_ph)); + memcpy(dat + sizeof(struct ipv4_ph), data, nbytes); + return in_cksum(dat, sizeof(dat)); +} + +int in_cksum_with_ph6(struct ipv6_ph *ph, void *data, int nbytes) +{ + uint8_t dat[sizeof(struct ipv6_ph) + nbytes]; + + memcpy(dat, ph, sizeof(struct ipv6_ph)); + memcpy(dat + sizeof(struct ipv6_ph), data, nbytes); + return in_cksum(dat, sizeof(dat)); +} + /* Fletcher Checksum -- Refer to RFC1008. */ #define MODX 4102U /* 5802 should be fine */ diff --git a/lib/checksum.h b/lib/checksum.h index 7d50371439..56771d4f24 100644 --- a/lib/checksum.h +++ b/lib/checksum.h @@ -1,8 +1,33 @@ +#include <stdint.h> +#include <netinet/in.h> + #ifdef __cplusplus extern "C" { #endif -extern int in_cksum(void *, int); + +/* IPv4 pseudoheader */ +struct ipv4_ph { + struct in_addr src; + struct in_addr dst; + uint8_t rsvd; + uint8_t proto; + uint16_t len; +} __attribute__((packed)); + +/* IPv6 pseudoheader */ +struct ipv6_ph { + struct in6_addr src; + struct in6_addr dst; + uint32_t ulpl; + uint8_t zero[3]; + uint8_t next_hdr; +} __attribute__((packed)); + +extern int in_cksum(void *data, int nbytes); +extern int in_cksum_with_ph4(struct ipv4_ph *ph, void *data, int nbytes); +extern int in_cksum_with_ph6(struct ipv6_ph *ph, void *data, int nbytes); + #define FLETCHER_CHECKSUM_VALIDATE 0xffff extern uint16_t fletcher_checksum(uint8_t *, const size_t len, const uint16_t offset); diff --git a/lib/command.c b/lib/command.c index b7a323e358..18426e0c51 100644 --- a/lib/command.c +++ b/lib/command.c @@ -149,6 +149,7 @@ const char *node_names[] = { "bfd", /* BFD_NODE */ "bfd peer", /* BFD_PEER_NODE */ "openfabric", // OPENFABRIC_NODE + "vrrp", /* VRRP_NODE */ }; /* clang-format on */ diff --git a/lib/command.h b/lib/command.h index a5f9616dbf..d96ec97e67 100644 --- a/lib/command.h +++ b/lib/command.h @@ -147,6 +147,7 @@ enum node_type { BFD_NODE, /* BFD protocol mode. */ BFD_PEER_NODE, /* BFD peer configuration mode. */ OPENFABRIC_NODE, /* OpenFabric router configuration node */ + VRRP_NODE, /* VRRP node */ NODE_TYPE_MAX, /* maximum */ }; @@ -389,6 +389,34 @@ struct interface *if_lookup_prefix(struct prefix *prefix, vrf_id_t vrf_id) return NULL; } +size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz, + struct interface ***result, vrf_id_t vrf_id) +{ + struct vrf *vrf = vrf_lookup_by_id(vrf_id); + + struct list *rs = list_new(); + struct interface *ifp; + + FOR_ALL_INTERFACES (vrf, ifp) { + if (ifp->hw_addr_len == (int)addrsz + && !memcmp(hw_addr, ifp->hw_addr, addrsz)) + listnode_add(rs, ifp); + } + + if (rs->count) { + *result = XCALLOC(MTYPE_TMP, + sizeof(struct interface *) * rs->count); + list_to_array(rs, (void **)*result, rs->count); + } + + int count = rs->count; + + list_delete(&rs); + + return count; +} + + /* Get interface by name if given name interface doesn't exist create one. */ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id) @@ -876,6 +904,19 @@ struct connected *connected_add_by_prefix(struct interface *ifp, return ifc; } +struct connected *connected_get_linklocal(struct interface *ifp) +{ + struct listnode *n; + struct connected *c = NULL; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) { + if (c->address->family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) + break; + } + return c; +} + #if 0 /* this route_table of struct connected's is unused \ * however, it would be good to use a route_table rather than \ * a list.. \ @@ -225,6 +225,10 @@ struct interface { not work as expected. */ ifindex_t ifindex; + /* + * ifindex of parent interface, if any + */ + ifindex_t link_ifindex; #define IFINDEX_INTERNAL 0 /* Zebra internal interface status */ @@ -482,6 +486,8 @@ extern struct connected *if_lookup_address(void *matchaddr, int family, vrf_id_t vrf_id); extern struct interface *if_lookup_prefix(struct prefix *prefix, vrf_id_t vrf_id); +size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz, + struct interface ***result, vrf_id_t vrf_id); /* These 3 functions are to be used when the ifname argument is terminated by a '\0' character: */ @@ -540,6 +546,7 @@ extern struct connected *connected_lookup_prefix_exact(struct interface *, extern struct nbr_connected *nbr_connected_new(void); extern void nbr_connected_free(struct nbr_connected *); struct nbr_connected *nbr_connected_check(struct interface *, struct prefix *); +struct connected *connected_get_linklocal(struct interface *ifp); /* link parameters */ struct if_link_params *if_link_params_get(struct interface *); diff --git a/lib/ipaddr.h b/lib/ipaddr.h index f4ddadc66e..1c2399fdd3 100644 --- a/lib/ipaddr.h +++ b/lib/ipaddr.h @@ -56,6 +56,9 @@ struct ipaddr { #define SET_IPADDR_V4(p) (p)->ipa_type = IPADDR_V4 #define SET_IPADDR_V6(p) (p)->ipa_type = IPADDR_V6 +#define IPADDRSZ(p) \ + (IS_IPADDR_V4((p)) ? sizeof(struct in_addr) : sizeof(struct in6_addr)) + static inline int str2ipaddr(const char *str, struct ipaddr *ip) { int ret; diff --git a/lib/json.c b/lib/json.c index 4ea20ba178..efc3794040 100644 --- a/lib/json.c +++ b/lib/json.c @@ -64,6 +64,11 @@ void json_object_boolean_true_add(struct json_object *obj, const char *key) json_object_object_add(obj, key, json_object_new_boolean(1)); } +void json_object_boolean_add(struct json_object *obj, const char *key, bool val) +{ + json_object_object_add(obj, key, json_object_new_boolean(val)); +} + struct json_object *json_object_lock(struct json_object *obj) { return json_object_get(obj); diff --git a/lib/json.h b/lib/json.h index a5251662be..c4d566b318 100644 --- a/lib/json.h +++ b/lib/json.h @@ -61,6 +61,8 @@ extern void json_object_string_add(struct json_object *obj, const char *key, const char *s); extern void json_object_int_add(struct json_object *obj, const char *key, int64_t i); +void json_object_boolean_add(struct json_object *obj, const char *key, + bool val); extern void json_object_boolean_false_add(struct json_object *obj, const char *key); extern void json_object_boolean_true_add(struct json_object *obj, diff --git a/lib/linklist.c b/lib/linklist.c index 40c4b27169..43bc709325 100644 --- a/lib/linklist.c +++ b/lib/linklist.c @@ -334,3 +334,18 @@ struct listnode *listnode_add_force(struct list **list, void *val) *list = list_new(); return listnode_add(*list, val); } + +void **list_to_array(struct list *list, void **arr, size_t arrlen) +{ + struct listnode *ln; + void *vp; + size_t idx = 0; + + for (ALL_LIST_ELEMENTS_RO(list, ln, vp)) { + arr[idx++] = vp; + if (idx == arrlen) + break; + } + + return arr; +} diff --git a/lib/linklist.h b/lib/linklist.h index c30d8d314a..c2b289596d 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -240,6 +240,26 @@ extern void list_sort(struct list *list, int (*cmp)(const void **, const void **)); /* + * Convert a list to an array of void pointers. + * + * Starts from the list head and ends either on the last node of the list or + * when the provided array cannot store any more elements. + * + * list + * list to convert + * + * arr + * Pre-allocated array of void * + * + * arrlen + * Number of elements in arr + * + * Returns: + * arr + */ +void **list_to_array(struct list *list, void **arr, size_t arrlen); + +/* * Delete a list and NULL its pointer. * * If non-null, list->del is called with each data element. diff --git a/lib/route_types.txt b/lib/route_types.txt index c5eff44ca7..59f3a91cf0 100644 --- a/lib/route_types.txt +++ b/lib/route_types.txt @@ -83,6 +83,7 @@ ZEBRA_ROUTE_SHARP, sharp, sharpd, 'D', 1, 1, 1, "SHARP" ZEBRA_ROUTE_PBR, pbr, pbrd, 'F', 1, 1, 0, "PBR" ZEBRA_ROUTE_BFD, bfd, bfdd, '-', 0, 0, 0, "BFD" ZEBRA_ROUTE_OPENFABRIC, openfabric, fabricd, 'f', 1, 1, 1, "OpenFabric" +ZEBRA_ROUTE_VRRP, vrrp, vrrpd, '-', 0, 0, 0, "VRRP" ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, 0, "-" @@ -110,4 +111,5 @@ ZEBRA_ROUTE_BABEL, "Babel routing protocol (Babel)" ZEBRA_ROUTE_SHARP, "Super Happy Advanced Routing Protocol (sharpd)" ZEBRA_ROUTE_PBR, "Policy Based Routing (PBR)" ZEBRA_ROUTE_BFD, "Bidirectional Fowarding Detection (BFD)" +ZEBRA_ROUTE_VRRP, "Virtual Router Redundancy Protocol (VRRP)" ZEBRA_ROUTE_OPENFABRIC, "OpenFabric Routing Protocol" diff --git a/lib/sockunion.c b/lib/sockunion.c index bb5426d74a..5afd10eb48 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -163,7 +163,7 @@ int sockunion_accept(int sock, union sockunion *su) } /* Return sizeof union sockunion. */ -static int sockunion_sizeof(const union sockunion *su) +int sockunion_sizeof(const union sockunion *su) { int ret; diff --git a/lib/sockunion.h b/lib/sockunion.h index d7d26ba85a..b996735550 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -83,6 +83,7 @@ extern void sockunion_set(union sockunion *, int family, const uint8_t *addr, extern union sockunion *sockunion_str2su(const char *str); extern int sockunion_accept(int sock, union sockunion *); +extern int sockunion_sizeof(const union sockunion *su); extern int sockunion_stream_socket(union sockunion *); extern int sockopt_reuseaddr(int); extern int sockopt_reuseport(int); diff --git a/lib/zclient.c b/lib/zclient.c index 96a78efad6..0972590ca6 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -555,6 +555,25 @@ void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, zclient_send_message(zclient); } +int zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id, + struct interface *ifp, bool down) +{ + struct stream *s; + + if (zclient->sock < 0) + return -1; + + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, ZEBRA_INTERFACE_SET_PROTODOWN, vrf_id); + stream_putl(s, ifp->ifindex); + stream_putc(s, !!down); + stream_putw_at(s, 0, stream_get_endp(s)); + zclient_send_message(zclient); + + return 0; +} + /* Make connection to zebra daemon. */ int zclient_start(struct zclient *zclient) { @@ -1381,6 +1400,8 @@ stream_failure: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | bandwidth | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | parent ifindex | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Link Layer Type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Harware Address Length | @@ -1561,6 +1582,7 @@ void zebra_interface_if_set_value(struct stream *s, struct interface *ifp) ifp->mtu = stream_getl(s); ifp->mtu6 = stream_getl(s); ifp->bandwidth = stream_getl(s); + ifp->link_ifindex = stream_getl(s); ifp->ll_type = stream_getl(s); ifp->hw_addr_len = stream_getl(s); if (ifp->hw_addr_len) diff --git a/lib/zclient.h b/lib/zclient.h index c46d63bfab..09f0acad84 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -76,6 +76,7 @@ typedef enum { ZEBRA_INTERFACE_UP, ZEBRA_INTERFACE_DOWN, ZEBRA_INTERFACE_SET_MASTER, + ZEBRA_INTERFACE_SET_PROTODOWN, ZEBRA_ROUTE_ADD, ZEBRA_ROUTE_DELETE, ZEBRA_ROUTE_NOTIFY_OWNER, @@ -466,6 +467,9 @@ extern void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, struct interface *ifp, int enable, int ra_interval); +extern int zclient_send_interface_protodown(struct zclient *zclient, + vrf_id_t vrf_id, + struct interface *ifp, bool down); /* Send redistribute command to zebra daemon. Do not update zclient state. */ extern int zebra_redistribute_send(int command, struct zclient *, afi_t, |
