PF - Must set FW_MBUF_REDISPATCH when translating input packets
authorMatthew Dillon <dillon@apollo.backplane.com>
Sun, 23 Aug 2009 10:19:02 +0000 (03:19 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sun, 23 Aug 2009 10:57:01 +0000 (03:57 -0700)
* If a TCP or UDP input packet is translated and happens to be
  destined to the local host, FW_MBUF_REDISPATCH must be set
  or it may end up on the wrong protocol stack and generate a
  (e.g.) TCP RST.

* This fixes 'nat' rulesets, and probably others.

sys/net/pf/pf.c

index f3df6f8..e09622b 100644 (file)
@@ -4136,14 +4136,21 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
 
        /* translate source/destination address, if necessary */
        if (STATE_TRANSLATE(*state)) {
-               if (direction == PF_OUT)
+               if (direction == PF_OUT) {
                        pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
                            &th->th_sum, &(*state)->gwy.addr,
                            (*state)->gwy.port, 0, pd->af);
-               else
+               } else {
+                       /*
+                        * If we don't redispatch the packet will go into
+                        * the protocol stack on the wrong cpu for the
+                        * post-translated address.
+                        */
+                       m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH;
                        pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
                            &th->th_sum, &(*state)->lan.addr,
                            (*state)->lan.port, 0, pd->af);
+               }
                m_copyback(m, off, sizeof(*th), (caddr_t)th);
        } else if (copyback) {
                /* Copyback sequence modulation or stateful scrub changes */
@@ -4200,14 +4207,21 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
 
        /* translate source/destination address, if necessary */
        if (STATE_TRANSLATE(*state)) {
-               if (direction == PF_OUT)
+               if (direction == PF_OUT) {
                        pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
                            &uh->uh_sum, &(*state)->gwy.addr,
                            (*state)->gwy.port, 1, pd->af);
-               else
+               } else {
+                       /*
+                        * If we don't redispatch the packet will go into
+                        * the protocol stack on the wrong cpu for the
+                        * post-translated address.
+                        */
+                       m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH;
                        pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
                            &uh->uh_sum, &(*state)->lan.addr,
                            (*state)->lan.port, 1, pd->af);
+               }
                m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
        }