Skip to content

Commit 4db8ddd

Browse files
committed
route: Don't spam route changes for lifetime
Fixes #459
1 parent 44e4ac6 commit 4db8ddd

File tree

1 file changed

+70
-64
lines changed

1 file changed

+70
-64
lines changed

src/route.c

Lines changed: 70 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <stddef.h>
3434
#include <stdlib.h>
3535
#include <string.h>
36+
#include <syslog.h>
3637
#include <unistd.h>
3738

3839
#include "config.h"
@@ -255,7 +256,7 @@ rt_is_default(const struct rt *rt)
255256
}
256257

257258
static void
258-
rt_desc(const char *cmd, const struct rt *rt)
259+
rt_desc(int loglevel, const char *cmd, const struct rt *rt)
259260
{
260261
char dest[INET_MAX_ADDRSTRLEN], gateway[INET_MAX_ADDRSTRLEN];
261262
int prefix;
@@ -273,25 +274,25 @@ rt_desc(const char *cmd, const struct rt *rt)
273274

274275
if (rt->rt_flags & RTF_HOST) {
275276
if (gateway_unspec)
276-
loginfox("%s: %s host route to %s",
277+
logmessage(loglevel, "%s: %s host route to %s",
277278
ifname, cmd, dest);
278279
else
279-
loginfox("%s: %s host route to %s via %s",
280+
logmessage(loglevel, "%s: %s host route to %s via %s",
280281
ifname, cmd, dest, gateway);
281282
} else if (rt_is_default(rt)) {
282283
if (gateway_unspec)
283-
loginfox("%s: %s default route",
284+
logmessage(loglevel, "%s: %s default route",
284285
ifname, cmd);
285286
else
286-
loginfox("%s: %s default route via %s",
287+
logmessage(loglevel, "%s: %s default route via %s",
287288
ifname, cmd, gateway);
288289
} else if (gateway_unspec)
289-
loginfox("%s: %s%s route to %s/%d",
290+
logmessage(loglevel, "%s: %s%s route to %s/%d",
290291
ifname, cmd,
291292
rt->rt_flags & RTF_REJECT ? " reject" : "",
292293
dest, prefix);
293294
else
294-
loginfox("%s: %s%s route to %s/%d via %s",
295+
logmessage(loglevel, "%s: %s%s route to %s/%d via %s",
295296
ifname, cmd,
296297
rt->rt_flags & RTF_REJECT ? " reject" : "",
297298
dest, prefix, gateway);
@@ -490,7 +491,7 @@ rt_recvrt(int cmd, const struct rt *rt, pid_t pid)
490491

491492
rb_tree_remove_node(&ctx->routes, f);
492493
snprintf(buf, sizeof(buf), "pid %d deleted", pid);
493-
rt_desc(buf, f);
494+
rt_desc(LOG_WARNING, buf, f);
494495
rt_free(f);
495496
}
496497
break;
@@ -503,8 +504,8 @@ rt_recvrt(int cmd, const struct rt *rt, pid_t pid)
503504
}
504505

505506
/* Compare miscellaneous route details */
506-
static bool
507-
rt_cmp_misc(struct rt *nrt, struct rt *ort)
507+
static int
508+
rt_cmp_mtu(struct rt *nrt, struct rt *ort)
508509
{
509510
#if defined(__FreeBSD__) || defined(__DragonFly__)
510511
/* FreeBSD puts the interface MTU into the route MTU
@@ -514,13 +515,19 @@ rt_cmp_misc(struct rt *nrt, struct rt *ort)
514515
nmtu = nrt->rt_mtu ? nrt->rt_mtu : (unsigned int)nrt->rt_ifp->mtu;
515516
omtu = ort->rt_mtu ? ort->rt_mtu : (unsigned int)ort->rt_ifp->mtu;
516517
if (omtu != nmtu)
517-
return false;
518+
return 1;
518519
#else
519520
if (ort->rt_mtu != nrt->rt_mtu)
520-
return false;
521+
return 1;
521522
#endif
522523

524+
return 0;
525+
}
526+
523527
#ifdef HAVE_ROUTE_LIFETIME
528+
static int
529+
rt_cmp_lifetime(struct rt *nrt, struct rt *ort)
530+
{
524531
/* There might be a minor difference between kernel route
525532
* lifetime and our lifetime due to processing times.
526533
* We allow a small deviation to avoid needless route changes.
@@ -533,23 +540,25 @@ rt_cmp_misc(struct rt *nrt, struct rt *ort)
533540
if (ts.tv_sec < 0)
534541
ts.tv_sec = -ts.tv_sec;
535542
if (ts.tv_sec > RTLIFETIME_DEV_MAX)
536-
return false;
543+
return 1;
537544
if (nrt->rt_lifetime > ort->rt_lifetime)
538545
deviation = nrt->rt_lifetime - ort->rt_lifetime;
539546
else
540547
deviation = ort->rt_lifetime - nrt->rt_lifetime;
541548
if (deviation > RTLIFETIME_DEV_MAX)
542-
return false;
543-
#endif
549+
return 1;
544550

545-
return true;
551+
return 0;
546552
}
553+
#endif
547554

548555
static bool
549556
rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
550557
{
551558
struct dhcpcd_ctx *ctx;
552-
bool change, kroute, result;
559+
struct rt *krt;
560+
int loglevel = LOG_INFO;
561+
bool change, result;
553562

554563
assert(nrt != NULL);
555564
ctx = nrt->rt_ifp->ctx;
@@ -569,46 +578,40 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
569578
sa_is_unspecified(&nrt->rt_netmask))
570579
return false;
571580

572-
rt_desc(ort == NULL ? "adding" : "changing", nrt);
573-
574-
change = kroute = result = false;
575-
if (ort == NULL) {
576-
ort = rb_tree_find_node(kroutes, nrt);
577-
if (ort != NULL &&
578-
((ort->rt_flags & RTF_REJECT &&
579-
nrt->rt_flags & RTF_REJECT) ||
580-
(ort->rt_ifp == nrt->rt_ifp &&
581+
krt = rb_tree_find_node(kroutes, nrt);
582+
if (krt != NULL &&
583+
krt->rt_ifp == nrt->rt_ifp &&
584+
/* Only test flags dhcpcd controls */
585+
(krt->rt_flags & (RTF_HOST | RTF_REJECT)) == nrt->rt_flags &&
581586
#ifdef HAVE_ROUTE_METRIC
582-
ort->rt_metric == nrt->rt_metric &&
587+
krt->rt_metric == nrt->rt_metric &&
583588
#endif
584-
sa_cmp(&ort->rt_gateway, &nrt->rt_gateway) == 0)))
585-
{
586-
if (rt_cmp_misc(nrt, ort))
587-
return true;
588-
change = true;
589-
kroute = true;
590-
}
591-
} else if (ort->rt_dflags & RTDF_FAKE &&
592-
!(nrt->rt_dflags & RTDF_FAKE) &&
593-
ort->rt_ifp == nrt->rt_ifp &&
594-
#ifdef HAVE_ROUTE_METRIC
595-
ort->rt_metric == nrt->rt_metric &&
596-
#endif
597-
sa_cmp(&ort->rt_dest, &nrt->rt_dest) == 0 &&
598-
rt_cmp_netmask(ort, nrt) == 0 &&
599-
sa_cmp(&ort->rt_gateway, &nrt->rt_gateway) == 0)
589+
sa_cmp(&krt->rt_dest, &nrt->rt_dest) == 0 &&
590+
rt_cmp_netmask(krt, nrt) == 0 &&
591+
sa_cmp(&krt->rt_gateway, &nrt->rt_gateway) == 0 &&
592+
rt_cmp_mtu(krt, nrt) == 0)
600593
{
601-
if (rt_cmp_misc(nrt, ort))
594+
#ifdef HAVE_ROUTE_LIFETIME
595+
if (rt_cmp_lifetime(krt, nrt) == 0) {
596+
rt_desc(LOG_DEBUG, "keeping", krt);
602597
return true;
603-
change = true;
598+
} else
599+
loglevel = LOG_DEBUG;
600+
#else
601+
rt_desc(LOG_DEBUG, "keeping", krt);
602+
return true;
603+
#endif
604604
}
605605

606+
rt_desc(loglevel, ort == NULL ? "adding" : "changing", nrt);
607+
608+
change = krt != NULL;
606609
#ifdef RTF_CLONING
607610
/* BSD can set routes to be cloning routes.
608611
* Cloned routes inherit the parent flags.
609612
* As such, we need to delete and re-add the route to flush children
610613
* to correct the flags. */
611-
if (change && ort != NULL && ort->rt_flags & RTF_CLONING)
614+
if (change && krt != NULL && krt->rt_flags & RTF_CLONING)
612615
change = false;
613616
#endif
614617

@@ -625,8 +628,8 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
625628
/* With route metrics, we can safely add the new route before
626629
* deleting the old route. */
627630
if (if_route(RTM_ADD, nrt) != -1) {
628-
if (ort != NULL) {
629-
if (if_route(RTM_DELETE, ort) == -1 && errno != ESRCH)
631+
if (krt != NULL) {
632+
if (if_route(RTM_DELETE, krt) == -1 && errno != ESRCH)
630633
logerr("if_route (DEL)");
631634
}
632635
result = true;
@@ -644,19 +647,17 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
644647
#ifdef ROUTE_PER_GATEWAY
645648
errno = 0;
646649
#endif
647-
if (ort != NULL) {
648-
if (if_route(RTM_DELETE, ort) == -1 && errno != ESRCH)
650+
if (krt != NULL) {
651+
if (if_route(RTM_DELETE, krt) == -1 && errno != ESRCH)
649652
logerr("if_route (DEL)");
650-
else
651-
kroute = false;
652653
}
653654
#ifdef ROUTE_PER_GATEWAY
654655
/* The OS allows many routes to the same dest with different gateways.
655656
* dhcpcd does not support this yet, so for the time being just keep on
656657
* deleting the route until there is an error. */
657-
if (ort != NULL && errno == 0) {
658+
if (krt != NULL && errno == 0) {
658659
for (;;) {
659-
if (if_route(RTM_DELETE, ort) == -1)
660+
if (if_route(RTM_DELETE, krt) == -1)
660661
break;
661662
}
662663
}
@@ -675,9 +676,9 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
675676
logerr("if_route (ADD)");
676677

677678
out:
678-
if (kroute) {
679-
rb_tree_remove_node(kroutes, ort);
680-
rt_free(ort);
679+
if (krt != NULL) {
680+
rb_tree_remove_node(kroutes, krt);
681+
rt_free(krt);
681682
}
682683
return result;
683684
}
@@ -687,22 +688,24 @@ rt_delete(struct rt *rt)
687688
{
688689
int retval;
689690

690-
rt_desc("deleting", rt);
691+
rt_desc(LOG_INFO, "deleting", rt);
691692
retval = if_route(RTM_DELETE, rt) == -1 ? false : true;
692693
if (!retval && errno != ENOENT && errno != ESRCH)
693694
logerr(__func__);
694695
return retval;
695696
}
696697

697-
static bool
698+
static int
698699
rt_cmp(const struct rt *r1, const struct rt *r2)
699700
{
700701

701-
return (r1->rt_ifp == r2->rt_ifp &&
702+
if (r1->rt_ifp == r2->rt_ifp &&
702703
#ifdef HAVE_ROUTE_METRIC
703704
r1->rt_metric == r2->rt_metric &&
704705
#endif
705-
sa_cmp(&r1->rt_gateway, &r2->rt_gateway) == 0);
706+
sa_cmp(&r1->rt_gateway, &r2->rt_gateway) == 0)
707+
return 0;
708+
return 1;
706709
}
707710

708711
static bool
@@ -718,10 +721,13 @@ rt_doroute(rb_tree_t *kroutes, struct rt *rt)
718721
if (rt->rt_dflags & RTDF_FAKE)
719722
return true;
720723
if (or->rt_dflags & RTDF_FAKE ||
721-
!rt_cmp(rt, or) ||
724+
rt_cmp(rt, or) != 0 ||
722725
(rt->rt_ifa.sa_family != AF_UNSPEC &&
723726
sa_cmp(&or->rt_ifa, &rt->rt_ifa) != 0) ||
724-
!rt_cmp_misc(rt, or))
727+
#ifdef HAVE_ROUTE_LIFETIME
728+
rt_cmp_lifetime(rt, or) != 0 ||
729+
#endif
730+
rt_cmp_mtu(rt, or) != 0)
725731
{
726732
if (!rt_add(kroutes, rt, or))
727733
return false;
@@ -733,7 +739,7 @@ rt_doroute(rb_tree_t *kroutes, struct rt *rt)
733739
or = rb_tree_find_node(kroutes, rt);
734740
if (or == NULL)
735741
return false;
736-
if (!rt_cmp(rt, or))
742+
if (rt_cmp(rt, or) == 0)
737743
return false;
738744
} else {
739745
if (!rt_add(kroutes, rt, NULL))

0 commit comments

Comments
 (0)