]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
RIP: fixed the EA_RIP_FROM attribute
authorMaria Matejka <mq@ucw.cz>
Wed, 13 Apr 2022 15:05:12 +0000 (17:05 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 13 Apr 2022 15:05:12 +0000 (17:05 +0200)
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.

nest/route.h
proto/rip/rip.c

index bf25dcf94766961b73f0b3529a0934c551fc0048..80c53ba6aaf09aa8e0073f5fbaf866e39bc43879 100644 (file)
@@ -538,9 +538,9 @@ const char *ea_custom_name(uint ea);
 #define EAF_TYPE_AS_PATH 0x06          /* BGP AS path (encoding per RFC 1771:4.3) */
 #define EAF_TYPE_BITFIELD 0x09         /* 32-bit embedded bitfield */
 #define EAF_TYPE_INT_SET 0x0a          /* Set of u32's (e.g., a community list) */
-#define EAF_TYPE_PTR 0x0d              /* Pointer to an object */
 #define EAF_TYPE_EC_SET 0x0e           /* Set of pairs of u32's - ext. community list */
 #define EAF_TYPE_LC_SET 0x12           /* Set of triplets of u32's - large community list */
+#define EAF_TYPE_IFACE 0x16            /* Interface pointer stored in adata */
 #define EAF_EMBEDDED 0x01              /* Data stored in eattr.u.data (part of type spec) */
 #define EAF_VAR_LENGTH 0x02            /* Attribute length is variable (part of type spec) */
 
index 9d8b9849fbf5c8edb9bc9d1241abc638aa6268f9..6ca7a6b5383a3dd97857e2874bb246e7b18c330b 100644 (file)
@@ -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)
     {