Hello,

I have a problem with relayd and redirects. If I disable a table, redirect 
stays down only for a while.
After a few seconds, redirect gets active again and forwards to the disabled 
table.

Same happens for redirect with a backup forward table.
Redirect points momentarily to backup table but after a while forwards to the 
disabled table.

This happens only with a combination of a table with parent hosts.

patch at bottom

regards,

Giannis

table <dir> { dir1 retry 2, dir2 retry 2 }
table <dir_> { dir1 parent 1 retry 2, dir2 parent 2 retry 2 }

table <dir_backup> { foo1 retry 2, foo2 retry 2 }


redirect dir-imap {
   listen on $dir_addr port imaps
   pftag RELAYD_dir
   sticky-address
   forward to <dir> port 993 mode least-states check icmp
}

redirect dir-pop {
   listen on $dir_addr port pop3s
   pftag RELAYD_dir
   sticky-address
   forward to <dir_> port 995 mode least-states check icmp
}

redirect dir-lmtp {
   listen on $dir_addr port 24
   pftag RELAYD_dir
   sticky-address
   forward to <dir_> port 24 mode least-states check icmp
   forward to <dir_backup> port 24 mode least-states check icmp
}

# relayctl show sum
Id      Type            Name                            Avlblty Status
1       redirect        dir-imap                                active
1       table           dir:993                                 active (2 hosts)
1       host            dir1                            100.00% up
2       host            dir2                            100.00% up
2       redirect        dir-pop                                 active
2       table           dir_:995                                active (2 hosts)
3       host            dir1 parent 1                   100.00% up
4       host            dir2 parent 2                   100.00% up
3       redirect        dir-lmtp                                active
3       table           dir_:24                                 active (2 hosts)
5       host            dir1 parent 1                   100.00% up
6       host            dir2 parent 2                   100.00% up
4       table           dir_backup:24                           active (2 hosts)
7       host            foo1                            100.00% up
8       host            foo2                            100.00% up

# relayctl table dis dir_:995

disable_table: table 2
flush_table: flushed table dir-pop
pfe_sync: disabling ruleset
sync_ruleset: rules removed

pfe_dispatch_hce: state 1 for host 4 dir2
pfe_dispatch_hce: state 1 for host 3 dir1

# relayctl show sum
Id      Type            Name                            Avlblty Status
2       redirect        dir-pop                                 down
2       table           dir_:995                                disabled

# pfctl -a 'relayd/*' -sr
anchor "dir-pop" all {
} // empty as it should

But after a while:

table dir-pop: 2 added, 0 deleted, 0 changed, 0 killed
pfe_sync: enabling ruleset
sync_ruleset: rule added to anchor "relayd/dir-pop"

# relayctl show sum
Id      Type            Name                            Avlblty Status
2       redirect        dir-pop                                 active
2       table           dir_:995                                disabled

Although table is disabled, redirect comes active, 
pf rule in anchor is active and <dir-pop> table has dir1 and dir2 inside.

# pfctl -a 'relayd/*' -sr
anchor "dir-pop" all {
  pass in quick on rdomain 0 inet proto tcp from any to $dir_addr port = 995 
flags S/SA keep state (tcp.established 600) tag RELAYD_dir rdr-to <dir-pop> 
port 995 least-states sticky-address
}


Same happens with the backup table on last dir-lmtp redirect.

Table is updated momentarily with the backup hosts, 
but after a while traffic is forwarded back to primary hosts although their 
table is disabled.

# relayctl show sum
Id      Type            Name                            Avlblty Status
3       redirect        dir-lmtp                                active
3       table           dir_:24                                 active (2 hosts)
5       host            dir1 parent 1                   100.00% up
6       host            dir2 parent 2                   100.00% up
4       table           dir_backup:24                           active (2 hosts)
7       host            foo1                            100.00% up
8       host            foo2                            100.00% up

# relayctl table dis dir_:24

disable_table: table 3
table dir-lmtp: 2 added, 2 deleted, 0 changed, 0 killed

pfe_dispatch_hce: state 1 for host 6 dir2
pfe_dispatch_hce: state 1 for host 5 dir1

# relayctl show sum
Id      Type            Name                            Avlblty Status
3       redirect        dir-lmtp                                active (using 
backup table)
3       table           dir_:24                                 disabled
4       table           dir_backup:24                           active (2 hosts)
7       host            foo1                            100.00% up
8       host            foo2                            100.00% up

# pfctl -a relayd/dir-lmtp -t dir-lmtp -vTshow
lists correctly foo1 and foo2 which are the backup hosts.

But after a while:
table dir-lmtp: 2 added, 2 deleted, 0 changed, 0 killed

# relayctl show sum
Id      Type            Name                            Avlblty Status
3       redirect        dir-lmtp                                active
3       table           dir_:24                                 disabled
4       table           dir_backup:24                           active (2 hosts)
7       host            foo1                            100.00% up
8       host            foo2                            100.00% up

# pfctl -a relayd/dir-lmtp -t dir-lmtp -vTshow
lists dir1 and dir2 and NOT foo1, foo2

I believe the following diff fixes this problem:

Index: pfe.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/pfe.c,v
retrieving revision 1.90
diff -u -p -r1.90 pfe.c
--- pfe.c       14 Sep 2020 11:30:25 -0000      1.90
+++ pfe.c       10 Jul 2023 13:39:44 -0000
@@ -171,7 +171,8 @@ pfe_dispatch_hce(int fd, struct privsep_
                 */
                if (HOST_ISUP(st.up)) {
                        table->conf.flags |= F_CHANGED;
-                       table->up++;
+                       if (!(table->conf.flags & F_DISABLE))
+                               table->up++;
                        host->flags |= F_ADD;
                        host->flags &= ~(F_DEL);
                } else if (HOST_ISUP(host->up)) {

Reply via email to