-/* $OpenBSD: ip_input.c,v 1.378 2022/08/12 14:49:15 bluhm Exp $ */
+/* $OpenBSD: ip_input.c,v 1.379 2022/08/15 16:15:36 bluhm Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
int
ip_local(struct mbuf **mp, int *offp, int nxt, int af)
{
- struct ip *ip;
+ if (*offp == 0) {
+ struct ip *ip;
- ip = mtod(*mp, struct ip *);
- *offp = ip->ip_hl << 2;
- nxt = ip->ip_p;
+ ip = mtod(*mp, struct ip *);
+ *offp = ip->ip_hl << 2;
+ nxt = ip->ip_p;
+ }
/* Check whether we are already in a IPv4/IPv6 local deliver loop. */
if (af == AF_UNSPEC)
-/* $OpenBSD: ip6_input.c,v 1.252 2022/08/12 14:49:15 bluhm Exp $ */
+/* $OpenBSD: ip6_input.c,v 1.253 2022/08/15 16:15:37 bluhm Exp $ */
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
/*
#endif
}
+struct ip6_offnxt {
+ int ion_off;
+ int ion_nxt;
+};
+
/*
* Enqueue packet for local delivery. Queuing is used as a boundary
* between the network layer (input/forward path) running with
int
ip6_ours(struct mbuf **mp, int *offp, int nxt, int af)
{
+ /* ip6_hbhchcheck() may be run before, then off and nxt are set */
+ if (*offp == 0) {
+ nxt = ip6_hbhchcheck(mp, offp, NULL);
+ if (nxt == IPPROTO_DONE)
+ return IPPROTO_DONE;
+ }
+
/* We are already in a IPv4/IPv6 local deliver loop. */
if (af != AF_UNSPEC)
return ip6_local(mp, offp, nxt, af);
+ /* save values for later, use after dequeue */
+ if (*offp != sizeof(struct ip6_hdr)) {
+ struct m_tag *mtag;
+ struct ip6_offnxt *ion;
+
+ /* mbuf tags are expensive, but only used for header options */
+ mtag = m_tag_get(PACKET_TAG_IP6_OFFNXT, sizeof(*ion),
+ M_NOWAIT);
+ if (mtag == NULL) {
+ ip6stat_inc(ip6s_idropped);
+ m_freemp(mp);
+ return IPPROTO_DONE;
+ }
+ ion = (struct ip6_offnxt *)(mtag + 1);
+ ion->ion_off = *offp;
+ ion->ion_nxt = nxt;
+
+ m_tag_prepend(*mp, mtag);
+ }
+
niq_enqueue(&ip6intrq, *mp);
*mp = NULL;
return IPPROTO_DONE;
int
ip6_local(struct mbuf **mp, int *offp, int nxt, int af)
{
- nxt = ip6_hbhchcheck(mp, offp, NULL);
- if (nxt == IPPROTO_DONE)
- return IPPROTO_DONE;
+ if (*offp == 0) {
+ struct m_tag *mtag;
+
+ mtag = m_tag_find(*mp, PACKET_TAG_IP6_OFFNXT, NULL);
+ if (mtag != NULL) {
+ struct ip6_offnxt *ion;
+
+ ion = (struct ip6_offnxt *)(mtag + 1);
+ *offp = ion->ion_off;
+ nxt = ion->ion_nxt;
+
+ m_tag_delete(*mp, mtag);
+ } else {
+ struct ip6_hdr *ip6;
+
+ ip6 = mtod(*mp, struct ip6_hdr *);
+ *offp = sizeof(struct ip6_hdr);
+ nxt = ip6->ip6_nxt;
+
+ }
+ }
/* Check whether we are already in a IPv4/IPv6 local deliver loop. */
if (af == AF_UNSPEC)
-/* $OpenBSD: mbuf.h,v 1.254 2022/02/14 04:33:18 dlg Exp $ */
+/* $OpenBSD: mbuf.h,v 1.255 2022/08/15 16:15:37 bluhm Exp $ */
/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */
/*
#define PACKET_TAG_SRCROUTE 0x1000 /* IPv4 source routing options */
#define PACKET_TAG_TUNNEL 0x2000 /* Tunnel endpoint address */
#define PACKET_TAG_CARP_BAL_IP 0x4000 /* carp(4) ip balanced marker */
+#define PACKET_TAG_IP6_OFFNXT 0x8000 /* IPv6 offset and next proto */
#define MTAG_BITS \
("\20\1IPSEC_IN_DONE\2IPSEC_OUT_DONE\3IPSEC_FLOWINFO" \