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.