From a0aa2307322cd47bbf416810ac0292925e03be87 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:39:49 +0200 Subject: Adding upstream version 1:7.0.3. Signed-off-by: Daniel Baumann --- src/decode-icmpv6.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 src/decode-icmpv6.h (limited to 'src/decode-icmpv6.h') diff --git a/src/decode-icmpv6.h b/src/decode-icmpv6.h new file mode 100644 index 0000000..aa66c1f --- /dev/null +++ b/src/decode-icmpv6.h @@ -0,0 +1,270 @@ +/* Copyright (C) 2007-2022 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Victor Julien + */ + +#ifndef __DECODE_ICMPV6_H__ +#define __DECODE_ICMPV6_H__ + +#include "decode-tcp.h" +#include "decode-udp.h" +#include "decode-ipv6.h" + +#define ICMPV6_HEADER_LEN 8 +#define ICMPV6_HEADER_PKT_OFFSET 8 + +/** ICMPV6 Message Types: */ +/** Error Messages: (type <128) */ +#define ICMP6_DST_UNREACH 1 +#define ICMP6_PACKET_TOO_BIG 2 +#define ICMP6_TIME_EXCEEDED 3 +#define ICMP6_PARAM_PROB 4 + +/** Informational Messages (type>=128) */ +#define ICMP6_ECHO_REQUEST 128 +#define ICMP6_ECHO_REPLY 129 + +#define MLD_LISTENER_QUERY 130 +#define MLD_LISTENER_REPORT 131 +#define MLD_LISTENER_REDUCTION 132 + +#define ND_ROUTER_SOLICIT 133 +#define ND_ROUTER_ADVERT 134 +#define ND_NEIGHBOR_SOLICIT 135 +#define ND_NEIGHBOR_ADVERT 136 +#define ND_REDIRECT 137 + +#define ICMP6_RR 138 +#define ICMP6_NI_QUERY 139 +#define ICMP6_NI_REPLY 140 +#define ND_INVERSE_SOLICIT 141 +#define ND_INVERSE_ADVERT 142 +#define MLD_V2_LIST_REPORT 143 +#define HOME_AGENT_AD_REQUEST 144 +#define HOME_AGENT_AD_REPLY 145 +#define MOBILE_PREFIX_SOLICIT 146 +#define MOBILE_PREFIX_ADVERT 147 +#define CERT_PATH_SOLICIT 148 +#define CERT_PATH_ADVERT 149 +#define ICMP6_MOBILE_EXPERIMENTAL 150 +#define MC_ROUTER_ADVERT 151 +#define MC_ROUTER_SOLICIT 152 +#define MC_ROUTER_TERMINATE 153 +#define FMIPV6_MSG 154 +#define RPL_CONTROL_MSG 155 +#define LOCATOR_UDATE_MSG 156 +#define DUPL_ADDR_REQUEST 157 +#define DUPL_ADDR_CONFIRM 158 +#define MPL_CONTROL_MSG 159 + +/** Destination Unreachable Message (type=1) Code: */ + +#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */ +#define ICMP6_DST_UNREACH_ADMIN 1 /* communication with destination */ + /* administratively prohibited */ +#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */ +#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */ +#define ICMP6_DST_UNREACH_NOPORT 4 /* bad port */ +#define ICMP6_DST_UNREACH_FAILEDPOLICY 5 /* Source address failed ingress/egress policy */ +#define ICMP6_DST_UNREACH_REJECTROUTE 6 /* Reject route to destination */ + + +/** Time Exceeded Message (type=3) Code: */ +#define ICMP6_TIME_EXCEED_TRANSIT 0 /* Hop Limit == 0 in transit */ +#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */ + +/** Parameter Problem Message (type=4) Code: */ +#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */ +#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */ +#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized IPv6 option */ + + +/** macro for icmpv6 "type" access */ +#define ICMPV6_GET_TYPE(p) (p)->icmpv6h->type +/** macro for icmpv6 "code" access */ +#define ICMPV6_GET_CODE(p) (p)->icmpv6h->code +/** macro for icmpv6 "csum" access */ +#define ICMPV6_GET_RAW_CSUM(p) SCNtohs((p)->icmpv6h->csum) +#define ICMPV6_GET_CSUM(p) (p)->icmpv6h->csum + +/** If message is informational */ +/** macro for icmpv6 "id" access */ +#define ICMPV6_GET_ID(p) (p)->icmpv6vars.id +/** macro for icmpv6 "seq" access */ +#define ICMPV6_GET_SEQ(p) (p)->icmpv6vars.seq + +/** If message is Error */ +/** macro for icmpv6 "unused" access */ +#define ICMPV6_GET_UNUSED(p) (p)->icmpv6h->icmpv6b.icmpv6e.unused +/** macro for icmpv6 "error_ptr" access */ +#define ICMPV6_GET_ERROR_PTR(p) (p)->icmpv6h->icmpv6b.icmpv6e.error_ptr +/** macro for icmpv6 "mtu" accessibility */ +// ICMPv6 has MTU only for type too big +#define ICMPV6_HAS_MTU(p) ((p)->icmpv6h->type == ICMP6_PACKET_TOO_BIG) +/** macro for icmpv6 "mtu" access */ +#define ICMPV6_GET_MTU(p) SCNtohl((p)->icmpv6h->icmpv6b.icmpv6e.mtu) + +/** macro for icmpv6 embedded "protocol" access */ +#define ICMPV6_GET_EMB_PROTO(p) (p)->icmpv6vars.emb_ip6_proto_next +/** macro for icmpv6 embedded "ipv6h" header access */ +#define ICMPV6_GET_EMB_IPV6(p) (p)->icmpv6vars.emb_ipv6h +/** macro for icmpv6 embedded "tcph" header access */ +#define ICMPV6_GET_EMB_TCP(p) (p)->icmpv6vars.emb_tcph +/** macro for icmpv6 embedded "udph" header access */ +#define ICMPV6_GET_EMB_UDP(p) (p)->icmpv6vars.emb_udph +/** macro for icmpv6 embedded "icmpv6h" header access */ +#define ICMPV6_GET_EMB_icmpv6h(p) (p)->icmpv6vars.emb_icmpv6h + +typedef struct ICMPV6Info_ +{ + uint16_t id; + uint16_t seq; +} ICMPV6Info; + +/** ICMPv6 header structure */ +typedef struct ICMPV6Hdr_ +{ + uint8_t type; + uint8_t code; + uint16_t csum; + + union { + ICMPV6Info icmpv6i; /** Informational message */ + union + { + uint32_t unused; /** for types 1 and 3, should be zero */ + uint32_t error_ptr; /** for type 4, pointer to the octet that originate the error */ + uint32_t mtu; /** for type 2, the Maximum Transmission Unit of the next-hop link */ + } icmpv6e; /** Error Message */ + } icmpv6b; +} ICMPV6Hdr; + +/** Data available from the decoded packet */ +typedef struct ICMPV6Vars_ { + /* checksum of the icmpv6 packet */ + uint16_t id; + uint16_t seq; + uint32_t mtu; + uint32_t error_ptr; + + /** Pointers to the embedded packet headers */ + IPV6Hdr *emb_ipv6h; + TCPHdr *emb_tcph; + UDPHdr *emb_udph; + ICMPV6Hdr *emb_icmpv6h; + + /** IPv6 src and dst address */ + uint32_t emb_ip6_src[4]; + uint32_t emb_ip6_dst[4]; + uint8_t emb_ip6_proto_next; + + /** TCP/UDP ports */ + uint16_t emb_sport; + uint16_t emb_dport; + +} ICMPV6Vars; + + +#define CLEAR_ICMPV6_PACKET(p) do { \ + (p)->level4_comp_csum = -1; \ + PACKET_CLEAR_L4VARS((p)); \ + (p)->icmpv6h = NULL; \ +} while(0) + +void DecodeICMPV6RegisterTests(void); + +int ICMPv6GetCounterpart(uint8_t type); + +/** -------- Inline functions --------- */ + +/** + * \brief Calculates the checksum for the ICMPV6 packet + * + * \param shdr Pointer to source address field from the IPV6 packet. Used as a + * part of the psuedoheader for computing the checksum + * \param pkt Pointer to the start of the ICMPV6 packet + * \param tlen Total length of the ICMPV6 packet(header + payload) + * + * \retval csum Checksum for the ICMPV6 packet + */ +static inline uint16_t ICMPV6CalculateChecksum( + const uint16_t *shdr, const uint16_t *pkt, uint16_t tlen) +{ + uint16_t pad = 0; + uint32_t csum = shdr[0]; + + csum += shdr[1] + shdr[2] + shdr[3] + shdr[4] + shdr[5] + shdr[6] + + shdr[7] + shdr[8] + shdr[9] + shdr[10] + shdr[11] + shdr[12] + + shdr[13] + shdr[14] + shdr[15] + htons(58 + tlen); + + csum += pkt[0]; + + tlen -= 4; + pkt += 2; + + while (tlen >= 64) { + csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + + pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] + + pkt[14] + pkt[15] + pkt[16] + pkt[17] + pkt[18] + pkt[19] + + pkt[20] + pkt[21] + pkt[22] + pkt[23] + pkt[24] + pkt[25] + + pkt[26] + pkt[27] + pkt[28] + pkt[29] + pkt[30] + pkt[31]; + tlen -= 64; + pkt += 32; + } + + while (tlen >= 32) { + csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] + + pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] + + pkt[14] + pkt[15]; + tlen -= 32; + pkt += 16; + } + + while(tlen >= 8) { + csum += pkt[0] + pkt[1] + pkt[2] + pkt[3]; + tlen -= 8; + pkt += 4; + } + + while(tlen >= 4) { + csum += pkt[0] + pkt[1]; + tlen -= 4; + pkt += 2; + } + + while (tlen > 1) { + csum += pkt[0]; + tlen -= 2; + pkt += 1; + } + + if (tlen == 1) { + *(uint8_t *)(&pad) = (*(uint8_t *)pkt); + csum += pad; + } + + csum = (csum >> 16) + (csum & 0x0000FFFF); + csum += (csum >> 16); + + return (uint16_t) ~csum; +} + +#endif /* __DECODE_ICMPV6_H__ */ -- cgit v1.2.3