When pf(4) forwards incoming packets with route-to or reply-to,
authorbluhm <bluhm@openbsd.org>
Mon, 15 Jan 2018 12:25:03 +0000 (12:25 +0000)
committerbluhm <bluhm@openbsd.org>
Mon, 15 Jan 2018 12:25:03 +0000 (12:25 +0000)
decrement the time-to-live or hop-limit field to prevent routing
loops.  Sending an ICMP time exceeded error makes traceroute work.
For outgoing packets ip_forward() has already done this.
OK visa@ sashan@

sys/net/pf.c

index 185d969..fa0a913 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf.c,v 1.1055 2018/01/10 13:57:17 bluhm Exp $ */
+/*     $OpenBSD: pf.c,v 1.1056 2018/01/15 12:25:03 bluhm Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -5912,6 +5912,17 @@ pf_route(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s)
        dst->sin_addr = ip->ip_dst;
        rtableid = m0->m_pkthdr.ph_rtableid;
 
+       if (pd->dir == PF_IN) {
+               if (ip->ip_ttl <= IPTTLDEC) {
+                       if (r->rt != PF_DUPTO)
+                               pf_send_icmp(m0, ICMP_TIMXCEED,
+                                   ICMP_TIMXCEED_INTRANS, 0,
+                                   pd->af, r, pd->rdomain);
+                       goto bad;
+               }
+               ip->ip_ttl -= IPTTLDEC;
+       }
+
        if (s == NULL) {
                bzero(sns, sizeof(sns));
                if (pf_map_addr(AF_INET, r,
@@ -6054,6 +6065,17 @@ pf_route6(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s)
        dst->sin6_addr = ip6->ip6_dst;
        rtableid = m0->m_pkthdr.ph_rtableid;
 
+       if (pd->dir == PF_IN) {
+               if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
+                       if (r->rt != PF_DUPTO)
+                               pf_send_icmp(m0, ICMP6_TIME_EXCEEDED,
+                                   ICMP6_TIME_EXCEED_TRANSIT, 0,
+                                   pd->af, r, pd->rdomain);
+                       goto bad;
+               }
+               ip6->ip6_hlim -= IPV6_HLIMDEC;
+       }
+
        if (s == NULL) {
                bzero(sns, sizeof(sns));
                if (pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src,