Hi,
Goal is to ref count the tdb in ipsec. For that the counters that
access the tdb have to be pushed down the function hierarchie.
While there adjust the error handling. Output functions should
generate an errno.
ok?
bluhm
Index: netinet/ip_ah.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ah.c,v
retrieving revision 1.156
diff -u -p -r1.156 ip_ah.c
--- netinet/ip_ah.c 13 Oct 2021 22:43:44 -0000 1.156
+++ netinet/ip_ah.c 15 Oct 2021 14:11:23 -0000
@@ -877,6 +877,7 @@ ah_input_cb(struct tdb *tdb, struct tdb_
baddone:
m_freem(m);
free(tc, M_XDATA, 0);
+ tdb->tdb_idrops++;
return -1;
}
@@ -1152,6 +1153,7 @@ ah_output(struct mbuf *m, struct tdb *td
m_freem(m);
crypto_freereq(crp);
free(tc, M_XDATA, 0);
+ tdb->tdb_odrops++;
return error;
}
@@ -1164,6 +1166,7 @@ ah_output_cb(struct tdb *tdb, struct tdb
{
int skip = tc->tc_skip;
caddr_t ptr = (caddr_t) (tc + 1);
+ int error;
/*
* Copy original headers (with the new protocol number) back
@@ -1175,10 +1178,8 @@ ah_output_cb(struct tdb *tdb, struct tdb
free(tc, M_XDATA, 0);
/* Call the IPsec input callback. */
- if (ipsp_process_done(m, tdb)) {
+ error = ipsp_process_done(m, tdb);
+ if (error)
ahstat_inc(ahs_outfail);
- return -1;
- }
-
- return 0;
+ return error;
}
Index: netinet/ip_esp.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_esp.c,v
retrieving revision 1.174
diff -u -p -r1.174 ip_esp.c
--- netinet/ip_esp.c 13 Oct 2021 22:43:44 -0000 1.174
+++ netinet/ip_esp.c 15 Oct 2021 14:11:23 -0000
@@ -733,6 +733,7 @@ esp_input_cb(struct tdb *tdb, struct tdb
baddone:
m_freem(m);
free(tc, M_XDATA, 0);
+ tdb->tdb_idrops++;
return -1;
}
@@ -1019,6 +1020,7 @@ esp_output(struct mbuf *m, struct tdb *t
m_freem(m);
crypto_freereq(crp);
free(tc, M_XDATA, 0);
+ tdb->tdb_odrops++;
return error;
}
@@ -1026,16 +1028,16 @@ int
esp_output_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int ilen,
int olen)
{
+ int error;
+
/* Release crypto descriptors. */
free(tc, M_XDATA, 0);
/* Call the IPsec input callback. */
- if (ipsp_process_done(m, tdb)) {
+ error = ipsp_process_done(m, tdb);
+ if (error)
espstat_inc(esps_outfail);
- return -1;
- }
-
- return 0;
+ return error;
}
#define SEEN_SIZE howmany(TDB_REPLAYMAX, 32)
Index: netinet/ip_ipcomp.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipcomp.c,v
retrieving revision 1.76
diff -u -p -r1.76 ip_ipcomp.c
--- netinet/ip_ipcomp.c 13 Oct 2021 22:43:44 -0000 1.76
+++ netinet/ip_ipcomp.c 15 Oct 2021 14:11:23 -0000
@@ -313,6 +313,7 @@ ipcomp_input_cb(struct tdb *tdb, struct
baddone:
m_freem(m);
free(tc, M_XDATA, 0);
+ tdb->tdb_idrops++;
return -1;
}
@@ -488,6 +489,7 @@ ipcomp_output(struct mbuf *m, struct tdb
drop:
m_freem(m);
crypto_freereq(crp);
+ tdb->tdb_odrops++;
return error;
}
@@ -509,6 +511,7 @@ ipcomp_output_cb(struct tdb *tdb, struct
#ifdef ENCDEBUG
char buf[INET6_ADDRSTRLEN];
#endif
+ int error;
skip = tc->tc_skip;
rlen = ilen - skip;
@@ -527,7 +530,8 @@ ipcomp_output_cb(struct tdb *tdb, struct
ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
ntohl(tdb->tdb_spi));
ipcompstat_inc(ipcomps_wrap);
- goto baddone;
+ error = ENOBUFS;
+ goto drop;
}
/* Initialize the IPCOMP header */
@@ -556,21 +560,22 @@ ipcomp_output_cb(struct tdb *tdb, struct
ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
ntohl(tdb->tdb_spi));
ipcompstat_inc(ipcomps_nopf);
- goto baddone;
+ error = EPFNOSUPPORT;
+ goto drop;
}
skiphdr:
/* Release the crypto descriptor. */
free(tc, M_XDATA, 0);
- if (ipsp_process_done(m, tdb)) {
+ error = ipsp_process_done(m, tdb);
+ if (error)
ipcompstat_inc(ipcomps_outfail);
- return -1;
- }
- return 0;
+ return error;
- baddone:
+ drop:
m_freem(m);
free(tc, M_XDATA, 0);
- return -1;
+ tdb->tdb_odrops++;
+ return error;
}
Index: netinet/ip_ipip.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipip.c,v
retrieving revision 1.95
diff -u -p -r1.95 ip_ipip.c
--- netinet/ip_ipip.c 13 Oct 2021 14:36:31 -0000 1.95
+++ netinet/ip_ipip.c 15 Oct 2021 15:33:25 -0000
@@ -524,7 +524,7 @@ ipip_output(struct mbuf **mp, struct tdb
DPRINTF("unsupported protocol family %d",
tdb->tdb_dst.sa.sa_family);
ipipstat_inc(ipips_family);
- error = EAFNOSUPPORT;
+ error = EPFNOSUPPORT;
goto drop;
}
@@ -533,6 +533,7 @@ ipip_output(struct mbuf **mp, struct tdb
drop:
m_freemp(mp);
+ tdb->tdb_odrops++;
return error;
}
Index: netinet/ip_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.374
diff -u -p -r1.374 ip_output.c
--- netinet/ip_output.c 27 Jul 2021 17:13:03 -0000 1.374
+++ netinet/ip_output.c 15 Oct 2021 14:11:23 -0000
@@ -644,10 +644,8 @@ ip_output_ipsec_send(struct tdb *tdb, st
/* Callee frees mbuf */
error = ipsp_process_packet(m, tdb, AF_INET, 0);
- if (error) {
+ if (error)
ipsecstat_inc(ipsec_odrops);
- tdb->tdb_odrops++;
- }
return error;
}
#endif /* IPSEC */
Index: netinet/ipsec_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.184
diff -u -p -r1.184 ipsec_input.c
--- netinet/ipsec_input.c 13 Oct 2021 22:49:11 -0000 1.184
+++ netinet/ipsec_input.c 15 Oct 2021 14:25:53 -0000
@@ -352,17 +352,15 @@ ipsec_common_input(struct mbuf *m, int s
* everything else.
*/
error = (*(tdbp->tdb_xform->xf_input))(m, tdbp, skip, protoff);
- if (error) {
+ if (error)
ipsecstat_inc(ipsec_idrops);
- tdbp->tdb_idrops++;
- }
return error;
drop:
- ipsecstat_inc(ipsec_idrops);
+ m_freem(m);
if (tdbp != NULL)
tdbp->tdb_idrops++;
- m_freem(m);
+ ipsecstat_inc(ipsec_idrops);
return error;
}
@@ -423,20 +421,17 @@ ipsec_input_cb(struct cryptop *crp)
panic("%s: unknown/unsupported security protocol %d",
__func__, tdb->tdb_sproto);
}
-
- if (error) {
+ if (error)
ipsecstat_inc(ipsec_idrops);
- tdb->tdb_idrops++;
- }
return;
drop:
- ipsecstat_inc(ipsec_idrops);
- if (tdb != NULL)
- tdb->tdb_idrops++;
- free(tc, M_XDATA, 0);
m_freem(m);
+ free(tc, M_XDATA, 0);
crypto_freereq(crp);
+ if (tdb != NULL)
+ tdb->tdb_idrops++;
+ ipsecstat_inc(ipsec_idrops);
}
/*
@@ -448,19 +443,15 @@ ipsec_common_input_cb(struct mbuf *m, st
{
int af, sproto;
u_int8_t prot;
-
#if NBPFILTER > 0
struct ifnet *encif;
#endif
-
struct ip *ip, ipn;
-
#ifdef INET6
struct ip6_hdr *ip6, ip6n;
#endif /* INET6 */
struct m_tag *mtag;
struct tdb_ident *tdbi;
-
#ifdef ENCDEBUG
char buf[INET6_ADDRSTRLEN];
#endif
@@ -477,7 +468,7 @@ ipsec_common_input_cb(struct mbuf *m, st
ipsp_address(&tdbp->tdb_dst, buf, sizeof(buf)),
ntohl(tdbp->tdb_spi));
IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops);
- return -1;
+ goto baddone;
}
ip = mtod(m, struct ip *);
@@ -489,10 +480,9 @@ ipsec_common_input_cb(struct mbuf *m, st
/* IP-in-IP encapsulation */
if (prot == IPPROTO_IPIP) {
if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
- m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return -1;
+ goto baddone;
}
/* ipn will now contain the inner IPv4 header */
m_copydata(m, skip, sizeof(struct ip),
@@ -503,10 +493,9 @@ ipsec_common_input_cb(struct mbuf *m, st
/* IPv6-in-IP encapsulation. */
if (prot == IPPROTO_IPV6) {
if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
- m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return -1;
+ goto baddone;
}
/* ip6n will now contain the inner IPv6 header. */
m_copydata(m, skip, sizeof(struct ip6_hdr),
@@ -517,8 +506,7 @@ ipsec_common_input_cb(struct mbuf *m, st
#ifdef INET6
/* Fix IPv6 header */
- if (af == AF_INET6)
- {
+ if (af == AF_INET6) {
if (m->m_len < sizeof(struct ip6_hdr) &&
(m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
@@ -526,7 +514,7 @@ ipsec_common_input_cb(struct mbuf *m, st
ipsp_address(&tdbp->tdb_dst, buf, sizeof(buf)),
ntohl(tdbp->tdb_spi));
IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops);
- return -1;
+ goto baddone;
}
ip6 = mtod(m, struct ip6_hdr *);
@@ -538,10 +526,9 @@ ipsec_common_input_cb(struct mbuf *m, st
/* IP-in-IP encapsulation */
if (prot == IPPROTO_IPIP) {
if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
- m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return -1;
+ goto baddone;
}
/* ipn will now contain the inner IPv4 header */
m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn);
@@ -550,10 +537,9 @@ ipsec_common_input_cb(struct mbuf *m, st
/* IPv6-in-IP encapsulation */
if (prot == IPPROTO_IPV6) {
if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
- m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return -1;
+ goto baddone;
}
/* ip6n will now contain the inner IPv6 header. */
m_copydata(m, skip, sizeof(struct ip6_hdr),
@@ -574,10 +560,9 @@ ipsec_common_input_cb(struct mbuf *m, st
switch (prot) {
case IPPROTO_UDP:
if (m->m_pkthdr.len < skip + sizeof(struct udphdr)) {
- m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return -1;
+ goto baddone;
}
cksum = 0;
m_copyback(m, skip + offsetof(struct udphdr, uh_sum),
@@ -593,10 +578,9 @@ ipsec_common_input_cb(struct mbuf *m, st
break;
case IPPROTO_TCP:
if (m->m_pkthdr.len < skip + sizeof(struct tcphdr)) {
- m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return -1;
+ goto baddone;
}
cksum = 0;
m_copyback(m, skip + offsetof(struct tcphdr, th_sum),
@@ -623,10 +607,9 @@ ipsec_common_input_cb(struct mbuf *m, st
mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
sizeof(struct tdb_ident), M_NOWAIT);
if (mtag == NULL) {
- m_freem(m);
DPRINTF("failed to get tag");
IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops);
- return -1;
+ goto baddone;
}
tdbi = (struct tdb_ident *)(mtag + 1);
@@ -703,22 +686,25 @@ ipsec_common_input_cb(struct mbuf *m, st
/* This is the enc0 interface unless for ipcomp. */
if ((ifp = if_get(m->m_pkthdr.ph_ifidx)) == NULL) {
- m_freem(m);
- return -1;
+ goto baddone;
}
if (pf_test(af, PF_IN, ifp, &m) != PF_PASS) {
if_put(ifp);
- m_freem(m);
- return -1;
+ goto baddone;
}
if_put(ifp);
if (m == NULL)
- return -1;
+ return 0;
}
#endif
/* Call the appropriate IPsec transform callback. */
ip_deliver(&m, &skip, prot, af);
return 0;
+
+ baddone:
+ m_freem(m);
+ tdbp->tdb_idrops++;
+ return -1;
#undef IPSEC_ISTAT
}
Index: netinet/ipsec_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ipsec_output.c,v
retrieving revision 1.89
diff -u -p -r1.89 ipsec_output.c
--- netinet/ipsec_output.c 13 Oct 2021 22:43:44 -0000 1.89
+++ netinet/ipsec_output.c 15 Oct 2021 14:11:23 -0000
@@ -130,7 +130,7 @@ ipsp_process_packet(struct mbuf *m, stru
ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
ntohl(tdb->tdb_spi), tdb->tdb_sproto,
tdb->tdb_dst.sa.sa_family);
- error = ENXIO;
+ error = EPFNOSUPPORT;
goto drop;
}
@@ -348,7 +348,7 @@ ipsp_process_packet(struct mbuf *m, stru
break;
#endif /* INET6 */
default:
- error = EINVAL;
+ error = EPFNOSUPPORT;
goto drop;
}
@@ -434,22 +434,19 @@ ipsec_output_cb(struct cryptop *crp)
error = ipcomp_output_cb(tdb, tc, m, ilen, olen);
break;
default:
- panic("%s: unknown/unsupported security protocol %d",
+ panic("%s: unhandled security protocol %d",
__func__, tdb->tdb_sproto);
}
-
- if (error) {
+ if (error)
ipsecstat_inc(ipsec_odrops);
- tdb->tdb_odrops++;
- }
return;
drop:
- if (tdb != NULL)
- tdb->tdb_odrops++;
m_freem(m);
free(tc, M_XDATA, 0);
crypto_freereq(crp);
+ if (tdb != NULL)
+ tdb->tdb_odrops++;
ipsecstat_inc(ipsec_odrops);
}
@@ -494,7 +491,7 @@ ipsp_process_done(struct mbuf *m, struct
default:
DPRINTF("unknown protocol family (%d)",
tdb->tdb_dst.sa.sa_family);
- error = ENXIO;
+ error = EPFNOSUPPORT;
goto drop;
}
@@ -548,7 +545,7 @@ ipsp_process_done(struct mbuf *m, struct
default:
DPRINTF("unknown protocol family (%d)",
tdb->tdb_dst.sa.sa_family);
- error = ENXIO;
+ error = EPFNOSUPPORT;
goto drop;
}
@@ -596,21 +593,28 @@ ipsp_process_done(struct mbuf *m, struct
*/
switch (tdb->tdb_dst.sa.sa_family) {
case AF_INET:
- return (ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL, 0));
-
+ error = ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL, 0);
+ break;
#ifdef INET6
case AF_INET6:
/*
* We don't need massage, IPv6 header fields are always in
* net endian.
*/
- return (ip6_output(m, NULL, NULL, 0, NULL, NULL));
+ error = ip6_output(m, NULL, NULL, 0, NULL, NULL);
+ break;
#endif /* INET6 */
+ default:
+ error = EPFNOSUPPORT;
+ break;
}
- error = EINVAL; /* Not reached. */
+ if (error)
+ tdb->tdb_odrops++;
+ return error;
drop:
m_freem(m);
+ tdb->tdb_odrops++;
return error;
}
Index: netinet6/ip6_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.260
diff -u -p -r1.260 ip6_output.c
--- netinet6/ip6_output.c 27 Jul 2021 17:13:03 -0000 1.260
+++ netinet6/ip6_output.c 15 Oct 2021 14:11:23 -0000
@@ -2870,10 +2870,8 @@ ip6_output_ipsec_send(struct tdb *tdb, s
/* Callee frees mbuf */
error = ipsp_process_packet(m, tdb, AF_INET6, tunalready);
- if (error) {
+ if (error)
ipsecstat_inc(ipsec_odrops);
- tdb->tdb_odrops++;
- }
return error;
}
#endif /* IPSEC */