On Thu, Dec 04, 2025 at 06:03:51PM +0100, Claudio Jeker wrote:
> On Thu, Dec 04, 2025 at 07:49:51PM +0300, Alexander Mukhin wrote:
> > >Synopsis:  eigrpd: multiple issues
> > >Category:  user
> > >Environment:
> >     System      : OpenBSD 7.8
> >     Details     : OpenBSD 7.8 (GENERIC) #54: Sun Oct 12 12:45:58 MDT 2025
> >                      
> > [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC
> > 
> >     Architecture: OpenBSD.amd64
> >     Machine     : amd64
> > >Description:
> >     eigrpd: multiple issues
> > >How-To-Repeat:
> >     At first, eigrp daemon exited with error just after start:
> > 
> >     # cat eigrpd.conf
> >     address-family ipv4 {
> >             autonomous-system 1 {
> >                     interface vio1
> >                     interface vio2
> >             }
> >     }
> >     # eigrpd -d -v -f eigrpd.conf
> >     startup
> >     ...
> >     fatal in eigrpe: in_cksum: packet too big
> >     ...
> >     waiting for children to terminate
> >     terminating
> > 
> >     I found that in_cksum() is called with uninitialized data
> >     because of swapped source and destination in ibuf_from_ibuf().
> >     I fixed that. Then the daemon started but was unable to make
> >     an adjacency with a Cisco router. Cisco complained on wrong
> >     checksum in incoming EIGRP packets. In fact, the checksums were
> >     in wrong byte order. I added a call to htons(). Then eigrpd and
> >     Cisco made an adjacency and exchanged routes.
> > 
> >     Unfortunately, redistribution of static routes didn't work.
> >     It looks like children processes get configuration with
> >     empty redist_list despite of that list being correctly filled
> >     in the master process. I was unable to fix this issue.
> > >Fix:
> >     (partial fix) 
> > --- packet.c
> > +++ packet.c
> > @@ -175,7 +175,7 @@ send_packet(struct eigrp_iface *ei, struct nbr *nbr, 
> > uint32_t flags,
> >             rtp_ack_stop_timer(nbr);
> >     }
> >  
> > -   ibuf_from_ibuf(buf, &ebuf);
> > +   ibuf_from_ibuf(&ebuf, buf);
> 
> Doh! I think that's the 2nd ibuf_from_ibuf I messed up.
> 
> >     if (ibuf_get(&ebuf, &eigrp_hdr, sizeof(eigrp_hdr)) == -1)
> >             fatalx("send_packet: get hdr failed");
> >  
> > @@ -189,7 +189,7 @@ send_packet(struct eigrp_iface *ei, struct nbr *nbr, 
> > uint32_t flags,
> >     if (ibuf_set_n16(buf, offsetof(struct eigrp_hdr, chksum), 0) == -1)
> >             fatalx("send_packet: set of chksum failed");
> >     if (ibuf_set_n16(buf, offsetof(struct eigrp_hdr, chksum),
> > -       in_cksum(ibuf_data(buf), ibuf_size(buf))) == -1)
> > +       htons(in_cksum(ibuf_data(buf), ibuf_size(buf)))) == -1)
> 
> Here you could just use ibuf_set_h16() instead of ibuf_set_n16() to
> prevent the value to be double converted.
> 
> >             fatalx("send_packet: set of chksum failed");
> >  
> >     /* log packet being sent */
> > 
> 
> Thanks for finding these issues. It is tricky for me to test eigrpd since
> I have no cisco gear to test against.
> 
> -- 
> :wq Claudio

I improved the patch for the checksum issue, and tried to fix
the redistribution problem:

--- eigrpd.c
+++ eigrpd.c
@@ -584,14 +584,42 @@
 {
        struct eigrp            *eigrp;
        struct eigrp_iface      *ei;
+       struct redistribute     *r;
+       char *tmp;
+       size_t s1,s2;
 
        if (eigrp_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1)
                return (-1);
 
        TAILQ_FOREACH(eigrp, &xconf->instances, entry) {
-               if (eigrp_sendboth(IMSG_RECONF_INSTANCE, eigrp,
-                   sizeof(*eigrp)) == -1)
-                       return (-1);
+               if (eigrp->dflt_metric) {
+                       s1 = sizeof(*eigrp);
+                       s2 = sizeof(*eigrp->dflt_metric);
+                       tmp = malloc(s1+s2);
+                       memcpy(tmp, eigrp, s1);
+                       memcpy(tmp+s1, eigrp->dflt_metric, s2);
+                       if (eigrp_sendboth(IMSG_RECONF_INSTANCE,
+                       tmp, s1+s2) == -1)
+                               return (-1);
+                       free(tmp);
+               } else
+                       if (eigrp_sendboth(IMSG_RECONF_INSTANCE,
+                       eigrp, sizeof(*eigrp)) == -1)
+                               return (-1);
+
+               SIMPLEQ_FOREACH(r, &eigrp->redist_list, entry)
+                       if (r->metric) {
+                               s1 = sizeof(*r);
+                               s2 = sizeof(*r->metric);
+                               tmp = malloc(s1+s2);
+                               memcpy(tmp, r, s1);
+                               memcpy(tmp+s1, r->metric, s2);
+                               main_imsg_compose_rde(IMSG_RECONF_REDIST, 0,
+                               tmp, s1+s2);
+                               free(tmp);
+                       } else
+                               main_imsg_compose_rde(IMSG_RECONF_REDIST, 0,
+                               r, sizeof(*r));
 
                TAILQ_FOREACH(ei, &eigrp->ei_list, e_entry) {
                        if (eigrp_sendboth(IMSG_RECONF_IFACE, ei->iface,
--- eigrpd.h
+++ eigrpd.h
@@ -112,6 +112,7 @@
        IMSG_SEND_MQUERY_END,
        IMSG_SOCKET_IPC,
        IMSG_RECONF_CONF,
+       IMSG_RECONF_REDIST,
        IMSG_RECONF_IFACE,
        IMSG_RECONF_INSTANCE,
        IMSG_RECONF_EIGRP_IFACE,
--- packet.c
+++ packet.c
@@ -175,7 +175,7 @@
                rtp_ack_stop_timer(nbr);
        }
 
-       ibuf_from_ibuf(buf, &ebuf);
+       ibuf_from_ibuf(&ebuf, buf);
        if (ibuf_get(&ebuf, &eigrp_hdr, sizeof(eigrp_hdr)) == -1)
                fatalx("send_packet: get hdr failed");
 
@@ -188,7 +188,7 @@
 
        if (ibuf_set_n16(buf, offsetof(struct eigrp_hdr, chksum), 0) == -1)
                fatalx("send_packet: set of chksum failed");
-       if (ibuf_set_n16(buf, offsetof(struct eigrp_hdr, chksum),
+       if (ibuf_set_h16(buf, offsetof(struct eigrp_hdr, chksum),
            in_cksum(ibuf_data(buf), ibuf_size(buf))) == -1)
                fatalx("send_packet: set of chksum failed");
 
--- rde.c
+++ rde.c
@@ -301,6 +301,7 @@
 rde_dispatch_parent(int fd, short event, void *bula)
 {
        static struct eigrpd_conf *nconf;
+       static struct redistribute *nred;
        static struct iface     *niface;
        static struct eigrp     *neigrp;
        struct eigrp_iface      *nei;
@@ -391,6 +392,12 @@
                        if ((neigrp = malloc(sizeof(struct eigrp))) == NULL)
                                fatal(NULL);
                        memcpy(neigrp, imsg.data, sizeof(struct eigrp));
+                       if (neigrp->dflt_metric) {
+                               size_t s = sizeof(struct redist_metric);
+                               neigrp->dflt_metric = malloc(s);
+                               memcpy(neigrp->dflt_metric,
+                               (char*)imsg.data+sizeof(*neigrp), s);
+                       }
 
                        SIMPLEQ_INIT(&neigrp->redist_list);
                        TAILQ_INIT(&neigrp->ei_list);
@@ -398,6 +405,19 @@
                        RB_INIT(&neigrp->topology);
                        TAILQ_INSERT_TAIL(&nconf->instances, neigrp, entry);
                        break;
+               case IMSG_RECONF_REDIST:
+                       if ((nred = malloc(sizeof(*nred))) == NULL)
+                               fatal(NULL);
+                       memcpy(nred, imsg.data, sizeof(*nred));
+                       if (nred->metric) {
+                               size_t s = sizeof(struct redist_metric);
+                               nred->metric = malloc(s);
+                               memcpy(nred->metric,
+                               (char*)imsg.data+sizeof(*nred), s);
+                       }
+                       SIMPLEQ_INSERT_TAIL(&neigrp->redist_list, nred, entry);
+                       break;
+                       
                case IMSG_RECONF_IFACE:
                        niface = imsg.data;
                        niface = if_lookup(nconf, niface->ifindex);

Any ideas?

-- 
Alexander.

Reply via email to