diff options
Diffstat (limited to 'sys/net/if_ethersubr.c')
-rw-r--r-- | sys/net/if_ethersubr.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 3fb702c453f..9c28a1c172e 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ethersubr.c,v 1.284 2022/06/29 09:08:07 mvs Exp $ */ +/* $OpenBSD: if_ethersubr.c,v 1.285 2023/01/24 22:35:47 jan Exp $ */ /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ /* @@ -98,6 +98,10 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet/ip_ipsp.h> +#include <netinet/ip.h> +#include <netinet/ip6.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> #if NBPFILTER > 0 #include <net/bpf.h> @@ -1034,3 +1038,56 @@ ether_e64_to_addr(struct ether_addr *ea, uint64_t e64) e64 >>= 8; } while (i > 0); } + +/* Parse different TCP/IP protocol headers for a quick view inside an mbuf. */ +void +ether_extract_headers(struct mbuf *mp, struct ether_extracted *ext) +{ + struct mbuf *m; + uint64_t hlen; + int hoff; + uint8_t ipproto; + + /* Return NULL if header was not recognized. */ + memset(ext, 0, sizeof *ext); + + ext->eh = mtod(mp, struct ether_header *); + switch (ntohs(ext->eh->ether_type)) { + case ETHERTYPE_IP: + m = m_getptr(mp, sizeof(*ext->eh), &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ext->ip4)); + ext->ip4 = (struct ip *)(mtod(m, caddr_t) + hoff); + + hlen = ext->ip4->ip_hl << 2; + ipproto = ext->ip4->ip_p; + + break; +#ifdef INET6 + case ETHERTYPE_IPV6: + m = m_getptr(mp, sizeof(*ext->eh), &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ext->ip6)); + ext->ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + hoff); + + hlen = sizeof(*ext->ip6); + ipproto = ext->ip6->ip6_nxt; + + break; +#endif + default: + return; + } + + switch (ipproto) { + case IPPROTO_TCP: + m = m_getptr(m, hoff + hlen, &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ext->tcp)); + ext->tcp = (struct tcphdr *)(mtod(m, caddr_t) + hoff); + break; + + case IPPROTO_UDP: + m = m_getptr(m, hoff + hlen, &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ext->udp)); + ext->udp = (struct udphdr *)(mtod(m, caddr_t) + hoff); + break; + } +} |