On Tue, Nov 09, 2021 at 02:00:01PM +0100, Denis Fondras wrote:
> > @@ -352,19 +343,19 @@ ipsec_common_input(struct mbuf **mp, int
> >      * Call appropriate transform and return -- callback takes care of
> >      * everything else.
> >      */
> > -   error = (*(tdbp->tdb_xform->xf_input))(mp, tdbp, skip, protoff);
> > -   if (error) {
> > +   prot = (*(tdbp->tdb_xform->xf_input))(mp, tdbp, skip, protoff);
> > +   if (prot == IPPROTO_DONE) {
> >             ipsecstat_inc(ipsec_idrops);
> >             tdbp->tdb_idrops++;
> >     }
> > -   return error;
> > +   return prot;
> >  
> 
> As I read & understand, prot is always IPPROTO_DONE and ipsec_idrops is always
> incremented. Can you explain in which case it is not ?

For ESP it works this way.

esp_input()
        /* Save the last three bytes of decrypted data */
        m_copydata(m, m->m_pkthdr.len - 3, 3, lastthree);
        ...
        /* Restore the Next Protocol field */
        m_copyback(m, protoff, sizeof(u_int8_t), lastthree + 2, M_NOWAIT);
ipsec_common_input_cb()
                prot = ip->ip_p;
                ...
                /* Save protocol */
                m_copydata(m, protoff, 1, (caddr_t) &prot);
        ...
        /* Return to the appropriate protocol handler in deliver loop. */
        return prot;
esp_input()
        /* Back to generic IPsec input processing */
        return ipsec_common_input_cb(mp, tdb, skip, protoff);

The protocol is stored in the mbuf to print it correctly in tcpdump -i enc0 .

I just realized that I forgot to include the bridge(4) part in my diff.
As I have no IPsec bridge(4) setup, could someone test this?

New diff.  ok?

bluhm

Index: net/if_bridge.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if_bridge.c,v
retrieving revision 1.357
diff -u -p -r1.357 if_bridge.c
--- net/if_bridge.c     23 Oct 2021 22:19:37 -0000      1.357
+++ net/if_bridge.c     1 Nov 2021 09:21:14 -0000
@@ -1487,7 +1487,7 @@ bridge_ipsec(struct ifnet *ifp, struct e
        struct tdb *tdb;
        u_int32_t spi;
        u_int16_t cpi;
-       int error, off;
+       int error, off, prot;
        u_int8_t proto = 0;
        struct ip *ip;
 #ifdef INET6
@@ -1575,7 +1575,10 @@ bridge_ipsec(struct ifnet *ifp, struct e
                                            tdb->tdb_soft_first_use);
                        }
 
-                       (*(tdb->tdb_xform->xf_input))(&m, tdb, hlen, off);
+                       prot = (*(tdb->tdb_xform->xf_input))(&m, tdb, hlen,
+                           off);
+                       if (prot != IPPROTO_DONE)
+                               ip_deliver(&m, &hlen, prot, af);
                        return (1);
                } else {
  skiplookup:
Index: netinet/ip_ah.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ah.c,v
retrieving revision 1.165
diff -u -p -r1.165 ip_ah.c
--- netinet/ip_ah.c     25 Oct 2021 09:47:02 -0000      1.165
+++ netinet/ip_ah.c     1 Nov 2021 09:21:14 -0000
@@ -563,21 +563,18 @@ ah_input(struct mbuf **mp, struct tdb *t
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        ahstat_inc(ahs_wrap);
-                       error = ENOBUFS;
                        goto drop;
                case 2:
                        DPRINTF("old packet received in SA %s/%08x",
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        ahstat_inc(ahs_replay);
-                       error = ENOBUFS;
                        goto drop;
                case 3:
                        DPRINTF("duplicate packet received in SA %s/%08x",
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        ahstat_inc(ahs_replay);
-                       error = ENOBUFS;
                        goto drop;
                default:
                        DPRINTF("bogus value from checkreplaywindow() "
@@ -585,7 +582,6 @@ ah_input(struct mbuf **mp, struct tdb *t
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        ahstat_inc(ahs_replay);
-                       error = ENOBUFS;
                        goto drop;
                }
        }
@@ -597,7 +593,6 @@ ah_input(struct mbuf **mp, struct tdb *t
                    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                    ntohl(tdb->tdb_spi));
                ahstat_inc(ahs_badauthl);
-               error = EACCES;
                goto drop;
        }
        if (skip + ahx->authsize + rplen > m->m_pkthdr.len) {
@@ -607,7 +602,6 @@ ah_input(struct mbuf **mp, struct tdb *t
                    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                    ntohl(tdb->tdb_spi));
                ahstat_inc(ahs_badauthl);
-               error = EACCES;
                goto drop;
        }
 
@@ -622,7 +616,6 @@ ah_input(struct mbuf **mp, struct tdb *t
            tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) {
                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
                tdb_delete(tdb);
-               error = ENXIO;
                goto drop;
        }
 
@@ -638,7 +631,6 @@ ah_input(struct mbuf **mp, struct tdb *t
        if (crp == NULL) {
                DPRINTF("failed to acquire crypto descriptors");
                ahstat_inc(ahs_crypto);
-               error = ENOBUFS;
                goto drop;
        }
 
@@ -664,7 +656,6 @@ ah_input(struct mbuf **mp, struct tdb *t
        if (ptr == NULL) {
                DPRINTF("failed to allocate buffer");
                ahstat_inc(ahs_crypto);
-               error = ENOBUFS;
                goto drop;
        }
 
@@ -720,7 +711,6 @@ ah_input(struct mbuf **mp, struct tdb *t
                    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                    ntohl(tdb->tdb_spi));
                ahstat_inc(ahs_badauth);
-               error = -1;
                goto drop;
        }
 
@@ -750,21 +740,18 @@ ah_input(struct mbuf **mp, struct tdb *t
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        ahstat_inc(ahs_wrap);
-                       error = -1;
                        goto drop;
                case 2:
                        DPRINTF("old packet received in SA %s/%08x",
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        ahstat_inc(ahs_replay);
-                       error = -1;
                        goto drop;
                case 3:
                        DPRINTF("duplicate packet received in SA %s/%08x",
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        ahstat_inc(ahs_replay);
-                       error = -1;
                        goto drop;
                default:
                        DPRINTF("bogus value from checkreplaywindow() "
@@ -772,7 +759,6 @@ ah_input(struct mbuf **mp, struct tdb *t
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        ahstat_inc(ahs_replay);
-                       error = -1;
                        goto drop;
                }
        }
@@ -784,7 +770,6 @@ ah_input(struct mbuf **mp, struct tdb *t
                    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                    ntohl(tdb->tdb_spi));
                ahstat_inc(ahs_hdrops);
-               error = -1;
                goto drop;
        }
 
@@ -863,7 +848,7 @@ ah_input(struct mbuf **mp, struct tdb *t
        free(ptr, M_XDATA, 0);
        m_freemp(mp);
        crypto_freereq(crp);
-       return error;
+       return IPPROTO_DONE;
 }
 
 /*
Index: netinet/ip_esp.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_esp.c,v
retrieving revision 1.184
diff -u -p -r1.184 ip_esp.c
--- netinet/ip_esp.c    24 Oct 2021 23:33:37 -0000      1.184
+++ netinet/ip_esp.c    1 Nov 2021 09:21:14 -0000
@@ -362,7 +362,6 @@ esp_input(struct mbuf **mp, struct tdb *
        if (plen <= 0) {
                DPRINTF("invalid payload length");
                espstat_inc(esps_badilen);
-               error = EINVAL;
                goto drop;
        }
 
@@ -378,7 +377,6 @@ esp_input(struct mbuf **mp, struct tdb *
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        espstat_inc(esps_badilen);
-                       error = EINVAL;
                        goto drop;
                }
        }
@@ -397,21 +395,18 @@ esp_input(struct mbuf **mp, struct tdb *
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        espstat_inc(esps_wrap);
-                       error = EACCES;
                        goto drop;
                case 2:
                        DPRINTF("old packet received in SA %s/%08x",
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        espstat_inc(esps_replay);
-                       error = EACCES;
                        goto drop;
                case 3:
                        DPRINTF("duplicate packet received in SA %s/%08x",
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        espstat_inc(esps_replay);
-                       error = EACCES;
                        goto drop;
                default:
                        DPRINTF("bogus value from checkreplaywindow() "
@@ -419,7 +414,6 @@ esp_input(struct mbuf **mp, struct tdb *
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        espstat_inc(esps_replay);
-                       error = EACCES;
                        goto drop;
                }
        }
@@ -434,7 +428,6 @@ esp_input(struct mbuf **mp, struct tdb *
            (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
                tdb_delete(tdb);
-               error = ENXIO;
                goto drop;
        }
 
@@ -450,7 +443,6 @@ esp_input(struct mbuf **mp, struct tdb *
        if (crp == NULL) {
                DPRINTF("failed to acquire crypto descriptors");
                espstat_inc(esps_crypto);
-               error = ENOBUFS;
                goto drop;
        }
 
@@ -537,7 +529,6 @@ esp_input(struct mbuf **mp, struct tdb *
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        espstat_inc(esps_badauth);
-                       error = -1;
                        goto drop;
                }
 
@@ -563,21 +554,18 @@ esp_input(struct mbuf **mp, struct tdb *
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        espstat_inc(esps_wrap);
-                       error = -1;
                        goto drop;
                case 2:
                        DPRINTF("old packet received in SA %s/%08x",
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        espstat_inc(esps_replay);
-                       error = -1;
                        goto drop;
                case 3:
                        DPRINTF("duplicate packet received in SA %s/%08x",
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        espstat_inc(esps_replay);
-                       error = -1;
                        goto drop;
                default:
                        DPRINTF("bogus value from checkreplaywindow() "
@@ -585,7 +573,6 @@ esp_input(struct mbuf **mp, struct tdb *
                            ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                            ntohl(tdb->tdb_spi));
                        espstat_inc(esps_replay);
-                       error = -1;
                        goto drop;
                }
        }
@@ -597,7 +584,6 @@ esp_input(struct mbuf **mp, struct tdb *
                    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                    ntohl(tdb->tdb_spi));
                espstat_inc(esps_hdrops);
-               error = -1;
                goto drop;
        }
 
@@ -668,7 +654,6 @@ esp_input(struct mbuf **mp, struct tdb *
                    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                    ntohl(tdb->tdb_spi));
                espstat_inc(esps_badilen);
-               error = -1;
                goto drop;
        }
 
@@ -678,7 +663,6 @@ esp_input(struct mbuf **mp, struct tdb *
                    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                    ntohl(tdb->tdb_spi));
                espstat_inc(esps_badenc);
-               error = -1;
                goto drop;
        }
 
@@ -694,7 +678,7 @@ esp_input(struct mbuf **mp, struct tdb *
  drop:
        m_freemp(mp);
        crypto_freereq(crp);
-       return error;
+       return IPPROTO_DONE;
 }
 
 /*
Index: netinet/ip_ipcomp.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipcomp.c,v
retrieving revision 1.86
diff -u -p -r1.86 ip_ipcomp.c
--- netinet/ip_ipcomp.c 24 Oct 2021 18:15:58 -0000      1.86
+++ netinet/ip_ipcomp.c 1 Nov 2021 09:21:14 -0000
@@ -154,7 +154,6 @@ ipcomp_input(struct mbuf **mp, struct td
        if (crp == NULL) {
                DPRINTF("failed to acquire crypto descriptors");
                ipcompstat_inc(ipcomps_crypto);
-               error = ENOBUFS;
                goto drop;
        }
        crdc = &crp->crp_desc[0];
@@ -202,7 +201,6 @@ ipcomp_input(struct mbuf **mp, struct td
            (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) {
                pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
                tdb_delete(tdb);
-               error = -1;
                goto drop;
        }
        /* Notify on soft expiration */
@@ -218,7 +216,6 @@ ipcomp_input(struct mbuf **mp, struct td
        if (m->m_len < skip + hlen &&
            (m = *mp = m_pullup(m, skip + hlen)) == NULL) {
                ipcompstat_inc(ipcomps_hdrops);
-               error = -1;
                goto drop;
        }
 
@@ -229,7 +226,6 @@ ipcomp_input(struct mbuf **mp, struct td
                    ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
                    ntohl(tdb->tdb_spi));
                ipcompstat_inc(ipcomps_hdrops);
-               error = -1;
                goto drop;
        }
        /* Keep the next protocol field */
@@ -295,7 +291,7 @@ ipcomp_input(struct mbuf **mp, struct td
  drop:
        m_freemp(mp);
        crypto_freereq(crp);
-       return error;
+       return IPPROTO_DONE;
 }
 
 /*
Index: netinet/ipsec_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.190
diff -u -p -r1.190 ipsec_input.c
--- netinet/ipsec_input.c       1 Nov 2021 09:19:10 -0000       1.190
+++ netinet/ipsec_input.c       1 Nov 2021 09:21:14 -0000
@@ -194,7 +194,7 @@ ipsec_common_input(struct mbuf **mp, int
        struct ifnet *encif;
        u_int32_t spi;
        u_int16_t cpi;
-       int error;
+       int prot;
 #ifdef ENCDEBUG
        char buf[INET6_ADDRSTRLEN];
 #endif
@@ -207,14 +207,12 @@ ipsec_common_input(struct mbuf **mp, int
        if ((sproto == IPPROTO_IPCOMP) && (m->m_flags & M_COMP)) {
                DPRINTF("repeated decompression");
                ipcompstat_inc(ipcomps_pdrops);
-               error = EINVAL;
                goto drop;
        }
 
        if (m->m_pkthdr.len - skip < 2 * sizeof(u_int32_t)) {
                DPRINTF("packet too small");
                IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops);
-               error = EINVAL;
                goto drop;
        }
 
@@ -268,7 +266,6 @@ ipsec_common_input(struct mbuf **mp, int
        default:
                DPRINTF("unsupported protocol family %d", af);
                IPSEC_ISTAT(esps_nopf, ahs_nopf, ipcomps_nopf);
-               error = EPFNOSUPPORT;
                goto drop;
        }
 
@@ -278,7 +275,6 @@ ipsec_common_input(struct mbuf **mp, int
                DPRINTF("could not find SA for packet to %s, spi %08x",
                    ipsp_address(&dst_address, buf, sizeof(buf)), ntohl(spi));
                IPSEC_ISTAT(esps_notdb, ahs_notdb, ipcomps_notdb);
-               error = ENOENT;
                goto drop;
        }
 
@@ -287,7 +283,6 @@ ipsec_common_input(struct mbuf **mp, int
                    ipsp_address(&dst_address, buf, sizeof(buf)),
                    ntohl(spi), tdbp->tdb_sproto);
                IPSEC_ISTAT(esps_invalid, ahs_invalid, ipcomps_invalid);
-               error = EINVAL;
                goto drop;
        }
 
@@ -296,7 +291,6 @@ ipsec_common_input(struct mbuf **mp, int
                    ipsp_address(&dst_address, buf, sizeof(buf)),
                    ntohl(spi), tdbp->tdb_sproto);
                espstat_inc(esps_udpinval);
-               error = EINVAL;
                goto drop;
        }
 
@@ -305,7 +299,6 @@ ipsec_common_input(struct mbuf **mp, int
                    ipsp_address(&dst_address, buf, sizeof(buf)),
                    ntohl(spi), tdbp->tdb_sproto);
                espstat_inc(esps_udpneeded);
-               error = EINVAL;
                goto drop;
        }
 
@@ -314,7 +307,6 @@ ipsec_common_input(struct mbuf **mp, int
                    ipsp_address(&dst_address, buf, sizeof(buf)),
                    ntohl(spi), tdbp->tdb_sproto);
                IPSEC_ISTAT(esps_noxform, ahs_noxform, ipcomps_noxform);
-               error = ENXIO;
                goto drop;
        }
 
@@ -326,7 +318,6 @@ ipsec_common_input(struct mbuf **mp, int
                            ipsp_address(&dst_address, buf, sizeof(buf)),
                            ntohl(spi), tdbp->tdb_sproto);
                        IPSEC_ISTAT(esps_pdrops, ahs_pdrops, ipcomps_pdrops);
-                       error = EACCES;
                        goto drop;
                }
 
@@ -352,19 +343,19 @@ ipsec_common_input(struct mbuf **mp, int
         * Call appropriate transform and return -- callback takes care of
         * everything else.
         */
-       error = (*(tdbp->tdb_xform->xf_input))(mp, tdbp, skip, protoff);
-       if (error) {
+       prot = (*(tdbp->tdb_xform->xf_input))(mp, tdbp, skip, protoff);
+       if (prot == IPPROTO_DONE) {
                ipsecstat_inc(ipsec_idrops);
                tdbp->tdb_idrops++;
        }
-       return error;
+       return prot;
 
  drop:
        m_freemp(mp);
        ipsecstat_inc(ipsec_idrops);
        if (tdbp != NULL)
                tdbp->tdb_idrops++;
-       return error;
+       return IPPROTO_DONE;
 }
 
 /*
@@ -630,16 +621,15 @@ ipsec_common_input_cb(struct mbuf **mp, 
                m = *mp;
                if_put(ifp);
                if (m == NULL)
-                       return 0;
+                       return IPPROTO_DONE;
        }
 #endif
-       /* Call the appropriate IPsec transform callback. */
-       ip_deliver(mp, &skip, prot, af);
-       return 0;
+       /* Return to the appropriate protocol handler in deliver loop. */
+       return prot;
 
  baddone:
        m_freemp(mp);
-       return -1;
+       return IPPROTO_DONE;
 #undef IPSEC_ISTAT
 }
 
@@ -829,8 +819,7 @@ ah46_input(struct mbuf **mp, int *offp, 
                return IPPROTO_DONE;
        }
 
-       ipsec_common_input(mp, *offp, protoff, af, proto, 0);
-       return IPPROTO_DONE;
+       return ipsec_common_input(mp, *offp, protoff, af, proto, 0);
 }
 
 void
@@ -863,8 +852,7 @@ esp46_input(struct mbuf **mp, int *offp,
                return IPPROTO_DONE;
        }
 
-       ipsec_common_input(mp, *offp, protoff, af, proto, 0);
-       return IPPROTO_DONE;
+       return ipsec_common_input(mp, *offp, protoff, af, proto, 0);
 }
 
 /* IPv4 IPCOMP wrapper */
@@ -888,8 +876,7 @@ ipcomp46_input(struct mbuf **mp, int *of
                return IPPROTO_DONE;
        }
 
-       ipsec_common_input(mp, *offp, protoff, af, proto, 0);
-       return IPPROTO_DONE;
+       return ipsec_common_input(mp, *offp, protoff, af, proto, 0);
 }
 
 void
Index: netinet/tcp_subr.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.181
diff -u -p -r1.181 tcp_subr.c
--- netinet/tcp_subr.c  23 Oct 2021 22:19:37 -0000      1.181
+++ netinet/tcp_subr.c  1 Nov 2021 09:26:48 -0000
@@ -964,7 +964,7 @@ tcp_signature_tdb_input(struct mbuf **mp
     int protoff)
 {
        m_freemp(mp);
-       return (EINVAL);
+       return (IPPROTO_DONE);
 }
 
 int
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.263
diff -u -p -r1.263 udp_usrreq.c
--- netinet/udp_usrreq.c        23 Oct 2021 22:19:37 -0000      1.263
+++ netinet/udp_usrreq.c        2 Nov 2021 09:49:29 -0000
@@ -305,9 +305,8 @@ udp_input(struct mbuf **mp, int *offp, i
                        espstat_inc(esps_udpencin);
                        protoff = af == AF_INET ? offsetof(struct ip, ip_p) :
                            offsetof(struct ip6_hdr, ip6_nxt);
-                       ipsec_common_input(mp, skip, protoff,
+                       return ipsec_common_input(mp, skip, protoff,
                            af, IPPROTO_ESP, 1);
-                       return IPPROTO_DONE;
                }
        }
 #endif

Reply via email to