diff options
author | Maria Matejka <mq@ucw.cz> | 2022-04-13 17:05:12 +0200 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2022-04-13 17:05:12 +0200 |
commit | 98fd158e28d89f10ee7a41b4f6a14fbd0021ef35 (patch) | |
tree | 577347901debd9bba7d2bfad5f85afc67375e6db /proto/rip | |
parent | d39ef961d1dde230c55fcc931b53f44cb34a1e63 (diff) |
RIP: fixed the EA_RIP_FROM attribute
The interface pointer was improperly converted to u32 and back. Fixing
this by explicitly allocating an adata structure for it. It's not so
memory efficient, we'll optimize this later.
Diffstat (limited to 'proto/rip')
-rw-r--r-- | proto/rip/rip.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 9d8b9849..6ca7a6b5 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -124,6 +124,11 @@ static inline int rip_same_rte(struct rip_rte *a, struct rip_rte *b) static inline int rip_valid_rte(struct rip_rte *rt) { return rt->from->ifa != NULL; } +struct rip_iface_adata { + struct adata ad; + struct iface *iface; +}; + /** * rip_announce_rte - announce route from RIP routing table to the core * @p: RIP instance @@ -188,25 +193,37 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) a0.nh.iface = rt->from->ifa->iface; } - a0.eattrs = alloca(sizeof(ea_list) + 3*sizeof(eattr)); - memset(a0.eattrs, 0, sizeof(ea_list)); /* Zero-ing only the ea_list header */ - a0.eattrs->count = 3; - a0.eattrs->attrs[0] = (eattr) { - .id = EA_RIP_METRIC, - .type = EAF_TYPE_INT, - .u.data = rt_metric, - }; - a0.eattrs->attrs[1] = (eattr) { - .id = EA_RIP_TAG, - .type = EAF_TYPE_INT, - .u.data = rt_tag, - }; - a0.eattrs->attrs[2] = (eattr) { - .id = EA_RIP_FROM, - .type = EAF_TYPE_PTR, - .u.data = (uintptr_t) a0.nh.iface, + struct { + ea_list l; + eattr e[3]; + struct rip_iface_adata riad; + } ea_block = { + .l = { .count = 3, }, + .e = { + { + .id = EA_RIP_METRIC, + .type = EAF_TYPE_INT, + .u.data = rt_metric, + }, + { + .id = EA_RIP_TAG, + .type = EAF_TYPE_INT, + .u.data = rt_tag, + }, + { + .id = EA_RIP_FROM, + .type = EAF_TYPE_IFACE, + .u.ptr = &ea_block.riad.ad, + } + }, + .riad = { + .ad = { .length = sizeof(struct rip_iface_adata) - sizeof(struct adata) }, + .iface = a0.nh.iface, + }, }; + a0.eattrs = &ea_block.l; + rta *a = rta_lookup(&a0); rte *e = rte_get_temp(a, p->p.main_source); @@ -323,7 +340,8 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s /* Update */ u32 rt_tag = ea_get_int(new->attrs->eattrs, EA_RIP_TAG, 0); u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1); - struct iface *rt_from = (struct iface *) ea_get_int(new->attrs->eattrs, EA_RIP_FROM, 0); + const eattr *rie = ea_find(new->attrs->eattrs, EA_RIP_FROM); + struct iface *rt_from = rie ? ((struct rip_iface_adata *) rie->u.ptr)->iface : NULL; if (rt_metric > p->infinity) { |