summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/checksum.c18
-rw-r--r--lib/checksum.h27
-rw-r--r--lib/command.c1
-rw-r--r--lib/command.h1
-rw-r--r--lib/if.c41
-rw-r--r--lib/if.h7
-rw-r--r--lib/ipaddr.h3
-rw-r--r--lib/json.c5
-rw-r--r--lib/json.h2
-rw-r--r--lib/linklist.c15
-rw-r--r--lib/linklist.h20
-rw-r--r--lib/route_types.txt2
-rw-r--r--lib/sockunion.c2
-rw-r--r--lib/sockunion.h1
-rw-r--r--lib/zclient.c22
-rw-r--r--lib/zclient.h4
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 */
};
diff --git a/lib/if.c b/lib/if.c
index 38f3f45ed1..3f489e0c3e 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -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.. \
diff --git a/lib/if.h b/lib/if.h
index d26d4dd68b..2dc1a7b2de 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -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,