Implement serialisation of our current forwarding rules in conf.c,
deserialising it to display in the pesto client.
Signed-off-by: David Gibson
---
conf.c | 44 +++++++++++++++++++++++++++++++
fwd_rule.c | 40 ++++++++++++++++++++++++++++
fwd_rule.h | 3 +++
pesto.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 160 insertions(+), 4 deletions(-)
diff --git a/conf.c b/conf.c
index 603ca2ac..b235221f 100644
--- a/conf.c
+++ b/conf.c
@@ -2339,6 +2339,47 @@ static int conf_send_pifs(const struct ctx *c, int fd)
return 0;
}
+/**
+ * conf_send_rules() - Send current forwarding rules to dynamic update client (pesto)
+ * @c: Execution context
+ * @fd: Socket to the client
+ *
+ * Return: 0 on success, -1 on failure
+ */
+static int conf_send_rules(const struct ctx *c, int fd)
+{
+ unsigned pif;
+
+ for (pif = 0; pif < PIF_NUM_TYPES; pif++) {
+ const struct fwd_table *fwd = c->fwd[pif];
+ unsigned i;
+
+ if (!fwd)
+ continue;
+
+ assert(pif);
+
+ /* PIF id */
+ if (sewrite_u8(fd, pif))
+ return -1;
+
+ /* Number of rules */
+ if (sewrite_u32(fd, fwd->count))
+ return -1;
+
+ for (i = 0; i < fwd->count; i++) {
+ if (fwd_rule_sewrite(fd, &fwd->rules[i].rule))
+ return -1;
+ }
+ }
+
+ /* Write 0 PIF id to finish */
+ if (sewrite_u8(fd, 0))
+ return -1;
+
+ return 0;
+}
+
/**
* conf_listen_handler() - Handle events on configuration listening socket
* @c: Execution context
@@ -2398,6 +2439,9 @@ void conf_listen_handler(struct ctx *c, uint32_t events)
if (conf_send_pifs(c, fd) < 0)
goto fail;
+ if (conf_send_rules(c, fd) < 0)
+ goto fail;
+
return;
fail:
diff --git a/fwd_rule.c b/fwd_rule.c
index dfbdf683..3e39b4f9 100644
--- a/fwd_rule.c
+++ b/fwd_rule.c
@@ -17,6 +17,8 @@
#include
+#include "serialise.h"
+
#include "fwd_rule.h"
/**
@@ -71,3 +73,41 @@ const char *fwd_rule_ntop(const struct fwd_rule *rule, char *dst, size_t size)
return dst;
}
+
+/**
+ * fwd_rule_seread() - Read erialised rule from an fd
+ * @fd: fd to serialise to
+ * @rule: Buffer to store rule into
+ *
+ * Return: 0 on success, -1 on error (with errno set)
+ */
+int fwd_rule_seread(int fd, struct fwd_rule *rule)
+{
+ if (seread_var(fd, rule))
+ return -1;
+
+ /* Byteswap for host */
+ rule->first = ntohs(rule->first);
+ rule->last = ntohs(rule->last);
+ rule->to = htons(rule->to);
+ return 0;
+}
+
+/**
+ * fwd_rule_sewrite() - Serialise rule to an fd
+ * @fd: fd to serialise to
+ * @rule: Rule to send
+ *
+ * Return: 0 on success, -1 on error (with errno set)
+ */
+int fwd_rule_sewrite(int fd, const struct fwd_rule *rule)
+{
+ struct fwd_rule tmp = *rule;
+
+ /* Byteswap for transport */
+ tmp.first = htons(tmp.first);
+ tmp.last = htons(tmp.last);
+ tmp.to = htons(tmp.to);
+
+ return sewrite_var(fd, &tmp);
+}
diff --git a/fwd_rule.h b/fwd_rule.h
index 59db0e95..500b955d 100644
--- a/fwd_rule.h
+++ b/fwd_rule.h
@@ -53,4 +53,7 @@ const union inany_addr *fwd_rule_addr(const struct fwd_rule *rule);
+ 15)
const char *fwd_rule_ntop(const struct fwd_rule *rule, char *dst, size_t size);
+int fwd_rule_seread(int fd, struct fwd_rule *rule);
+int fwd_rule_sewrite(int fd, const struct fwd_rule *rule);
+
#endif /* FWD_RULE_H */
diff --git a/pesto.c b/pesto.c
index dbc27a58..f021cdb6 100644
--- a/pesto.c
+++ b/pesto.c
@@ -34,6 +34,7 @@
#include "common.h"
#include "seccomp_pesto.h"
#include "serialise.h"
+#include "fwd_rule.h"
#include "pesto.h"
static int verbosity = 1;
@@ -108,6 +109,8 @@ static const char *pesto_recv_str(int fd)
struct pif_state {
uint8_t pif;
const char *name;
+ uint32_t count;
+ struct fwd_rule *rule;
};
struct conf_state {
@@ -119,7 +122,7 @@ struct conf_state {
* pesto_read_pifs() - Read pif names and IDs from passt/pasta
* @fd: Control socket
*/
-static const struct conf_state *pesto_read_pifs(int fd)
+static struct conf_state *pesto_read_pifs(int fd)
{
uint32_t num;
struct conf_state *state;
@@ -146,18 +149,81 @@ static const struct conf_state *pesto_read_pifs(int fd)
return state;
}
+/**
+ * find_pif_state() - Find the pif state structure for a given pif id
+ * @state: Rule state information
+ * @pif: pif id
+ *
+ * Return: pointer to the pif_state for @pif, or NULL if not found
+ */
+static struct pif_state *find_pif_state(struct conf_state *state, uint8_t pif)
+{
+ unsigned i;
+
+ for (i = 0; i < state->npifs; i++) {
+ if (state->pif[i].pif == pif)
+ return &state->pif[i];
+ }
+
+ return NULL;
+}
+
+/**
+ * pesto_read_rules() - Read a set of rules for one pif
+ * @fd: Control socket
+ * @state: Rule state information to update
+ *
+ * Return: true if there may be more rules to read, false if finished
+ */
+static bool pesto_read_rules(int fd, struct conf_state *state)
+{
+ struct pif_state *ps;
+ uint8_t pif;
+ unsigned i;
+
+ if (seread_u8(fd, &pif) < 0)
+ die("Error reading from control socket");
+
+ if (!pif)
+ return false;
+
+ ps = find_pif_state(state, pif);
+ if (!ps)
+ die("Received rules for an unknown pif");
+
+ if (seread_u32(fd, &ps->count) < 0)
+ die("Error reading from control socket");
+
+ debug("Receiving rules %"PRIu32" rules for %s", ps->count, ps->name);
+
+ ps->rule = xmalloc(sizeof(*ps->rule) * ps->count);
+
+ for (i = 0; i < ps->count; i++) {
+ if (fwd_rule_seread(fd, &ps->rule[i]) < 0)
+ die("Error reading from control socket");
+ }
+
+ return true;
+}
+
/**
* show_state() - Show current rule state obtained from passt/pasta
* @pifs: PIF name information
*/
static void show_state(const struct conf_state *state)
{
- unsigned i;
+ unsigned i, j;
for (i = 0; i < state->npifs; i++) {
const struct pif_state *ps = &state->pif[i];
printf("Forwarding rules for %s interface\n", ps->name);
- printf("\tTBD\n");
+ for (j = 0; j < ps->count; j++) {
+ const struct fwd_rule *rule = &ps->rule[j];
+ char rulestr[FWD_RULE_STRLEN];
+
+ printf(" %s\n", fwd_rule_ntop(rule, rulestr,
+ sizeof(rulestr)));
+ }
}
}
@@ -183,9 +249,9 @@ int main(int argc, char **argv)
{ 0 },
};
struct sockaddr_un a = { AF_UNIX, "" };
- const struct conf_state *state;
const char *optstring = "vh";
struct pesto_hello hello;
+ struct conf_state *state;
struct sock_fprog prog;
int optname, ret, s;
uint32_t s_version;
@@ -266,6 +332,9 @@ int main(int argc, char **argv)
state = pesto_read_pifs(s);
+ while (pesto_read_rules(s, state))
+ ;
+
show_state(state);
exit(0);
--
2.53.0