1 
2 /***************************************************************************
3  * ICMPv6Header.h -- The ICMPv6Header Class represents an ICMP version 6   *
4  * packet. It contains methods to set any header field. In general, these  *
5  * methods do error checkings and byte order conversion.                   *
6  *                                                                         *
7  ***********************IMPORTANT NMAP LICENSE TERMS************************
8  *                                                                         *
9  * The Nmap Security Scanner is (C) 1996-2020 Insecure.Com LLC ("The Nmap  *
10  * Project"). Nmap is also a registered trademark of the Nmap Project.     *
11  *                                                                         *
12  * This program is distributed under the terms of the Nmap Public Source   *
13  * License (NPSL). The exact license text applying to a particular Nmap    *
14  * release or source code control revision is contained in the LICENSE     *
15  * file distributed with that version of Nmap or source code control       *
16  * revision. More Nmap copyright/legal information is available from       *
17  * https://nmap.org/book/man-legal.html, and further information on the    *
18  * NPSL license itself can be found at https://nmap.org/npsl. This header  *
19  * summarizes some key points from the Nmap license, but is no substitute  *
20  * for the actual license text.                                            *
21  *                                                                         *
22  * Nmap is generally free for end users to download and use themselves,    *
23  * including commercial use. It is available from https://nmap.org.        *
24  *                                                                         *
25  * The Nmap license generally prohibits companies from using and           *
26  * redistributing Nmap in commercial products, but we sell a special Nmap  *
27  * OEM Edition with a more permissive license and special features for     *
28  * this purpose. See https://nmap.org/oem                                  *
29  *                                                                         *
30  * If you have received a written Nmap license agreement or contract       *
31  * stating terms other than these (such as an Nmap OEM license), you may   *
32  * choose to use and redistribute Nmap under those terms instead.          *
33  *                                                                         *
34  * The official Nmap Windows builds include the Npcap software             *
35  * (https://npcap.org) for packet capture and transmission. It is under    *
36  * separate license terms which forbid redistribution without special      *
37  * permission. So the official Nmap Windows builds may not be              *
38  * redistributed without special permission (such as an Nmap OEM           *
39  * license).                                                               *
40  *                                                                         *
41  * Source is provided to this software because we believe users have a     *
42  * right to know exactly what a program is going to do before they run it. *
43  * This also allows you to audit the software for security holes.          *
44  *                                                                         *
45  * Source code also allows you to port Nmap to new platforms, fix bugs,    *
46  * and add new features.  You are highly encouraged to submit your         *
47  * changes as a Github PR or by email to the dev@nmap.org mailing list     *
48  * for possible incorporation into the main distribution. Unless you       *
49  * specify otherwise, it is understood that you are offering us very       *
50  * broad rights to use your submissions as described in the Nmap Public    *
51  * Source License Contributor Agreement. This is important because we      *
52  * fund the project by selling licenses with various terms, and also       *
53  * because the inability to relicense code has caused devastating          *
54  * problems for other Free Software projects (such as KDE and NASM).       *
55  *                                                                         *
56  * The free version of Nmap is distributed in the hope that it will be     *
57  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of  *
58  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties,        *
59  * indemnification and commercial support are all available through the    *
60  * Npcap OEM program--see https://nmap.org/oem.                            *
61  *                                                                         *
62  ***************************************************************************/
63 /* This code was originally part of the Nping tool.                        */
64 
65 #ifndef ICMPv6HEADER_H
66 #define ICMPv6HEADER_H 1
67 
68 #include "ICMPHeader.h"
69 
70 /******************************************************************************/
71 /*               IMPORTANT INFORMATION ON HOW TO USE THIS CLASS.              */
72 /******************************************************************************/
73 /* This class represents an ICMPv6 messages. ICMPv6 messages may be of
74  * different types. Each type has its own header and possibly a variable
75  * length data field. Information messages have an "invoking packet" field
76  * which is the IP packet that triggered the emission of the ICMPv6 message.
77  * Other messages may contain a "data" field, like echo requests an replies.
78  * Some others may contain ICMPv6 Options.
79  *
80  * So the thing is, that this class only represents fixed-length ICMPv6
81  * headers and does NOT offer storage for ANY variable-length field. This
82  * fields may be added to the ICMPv6 header using instances of the RawData
83  * class the ICMPv6Option class or even the IPv6Header class (in those cases
84  * where a whole packet is appendend to the ICMPv6 message).
85  *
86  * So, how does this work? Let's look at some examples.
87  *
88  * 1. Imagine we need to build an ICMP echo request message that includes some
89  *    arbitrary data to be echoed. We could do the following:
90  *
91  *    u8 final_packet[1024];         <-- Buffer to store the resulting packet
92  *    u32 final_packet_len=0;        <-- Length of the resulting packet
93  *    ICMPv6Header header;           <-- The ICMPv6 fixed-length part
94  *    RawData data;                  <-- The data to append to the echo message
95  *
96  *    header.setType(ICMPv6_ECHO);   <-- Set ICMPv6 type to "Echo request"
97  *    data.store("1234567890");      <-- Store data we need to send.
98  *    header.setNextElement(&data);  <-- Tell ICMPv6Header what's after it
99  *    header.setSum();               <-- Compute the checksum
100  *
101  *    final_packet_len=header.dumpToBinaryBuffer(fina_packet, 1024);
102  *    send_packet(final_packet, final_packet_len)
103  *
104  * 2. If we are sending a parameter problem message and we need to include the
105  *    invoking datagram, we can call setNextElement() passing an IPv6Header
106  *    pointer.
107  *
108  *    u8 final_packet[1024];         <-- Buffer to store the resulting packet
109  *    u32 final_packet_len=0;        <-- Length of the resulting packet
110  *    ICMPv6Header header;           <-- The ICMPv6 fixed-length part
111  *    IPv6Header ipv6;               <-- The IPv6 packet that triggered ICMPv6
112  *
113  *    header.setType(ICMPv6_PARAMPROB); <-- Set ICMPv6 type to "Param Problem"
114  *    header.setNextElement(&ipv6);  <-- Tell ICMPv6Header what's after it
115  *    header.setSum();               <-- Compute the checksum
116  *
117  *    Note that here we don't show how the ipv6 object is set.
118  *
119  * 3. If we are sending a router solicitation message, we'll call
120  *    setNextElement() passing an IPv6Options Pointer.
121  *
122  *    u8 final_packet[1024];         <-- Buffer to store the resulting packet
123  *    u32 final_packet_len=0;        <-- Length of the resulting packet
124  *    ICMPv6Header header;           <-- The ICMPv6 fixed-length part
125  *    IPv6Options opts1;              <-- IPv6 options
126  *    IPv6Options opts2;              <-- IPv6 options
127  *    IPv6Options opts3;              <-- IPv6 options
128  *
129  *    header.setType(ICMPv6_ROUTERSOLICIT); <-- Set ICMPv6 type
130  *
131  *    opts1.setXXXX();   <-- Set up the options
132  *    .
133  *    .
134  *    .
135  *    opts3.setYYYY();
136  *
137  *    opts2.setNextElement(&opts3);  <-- Link the options
138  *    opts1.setNextElement(&opts2);
139  *    header.setNextElement(&opts1);
140  *    header.setNextElement(&ipv6);  <-- Link the first option to the ICMPv6
141  *    header.setSum();               <-- Compute the checksum
142  *
143  *    And so on...
144  *
145  */
146 
147 
148 /* Packet header diagrams included in this file have been taken from the
149  * following IETF RFC documents: RFC 4443, RFC 2461, RFC 2894 */
150 
151 /* ICMP types and codes.
152  * The following types and codes have been defined by IANA. A complete list
153  * may be found at http://www.iana.org/assignments/icmpv6-parameters
154  *
155  * Definitions on the first level of indentation are ICMPv6 Types.
156  * Definitions on the second level of indentation (values enclosed in
157  * parenthesis) are ICMPv6 Codes */
158 #define ICMPv6_UNREACH                      1    /* Destination unreachable  [RFC 2463, 4443] */
159 #define     ICMPv6_UNREACH_NO_ROUTE        (0)   /*  --> No route to destination */
160 #define     ICMPv6_UNREACH_PROHIBITED      (1)   /*  --> Communication administratively prohibited */
161 #define     ICMPv6_UNREACH_BEYOND_SCOPE    (2)   /*  --> Beyond scope of source address  [RFC4443] */
162 #define     ICMPv6_UNREACH_ADDR_UNREACH    (3)   /*  --> Address unreachable */
163 #define     ICMPv6_UNREACH_PORT_UNREACH    (4)   /*  --> Port unreachable */
164 #define     ICMPv6_UNREACH_SRC_ADDR_FAILED (5)   /*  --> Source address failed ingress/egress policy [RFC4443] */
165 #define     ICMPv6_UNREACH_REJECT_ROUTE    (6)   /*  --> Reject route to destination  [RFC4443] */
166 #define ICMPv6_PKTTOOBIG                    2    /* Packet too big  [RFC 2463, 4443] */
167 #define ICMPv6_TIMXCEED                     3    /* Time exceeded  [RFC 2463, 4443] */
168 #define     ICMPv6_TIMXCEED_HOP_EXCEEDED   (0)   /*  --> Hop limit exceeded in transit */
169 #define     ICMPv6_TIMXCEED_REASS_EXCEEDED (1)   /*  --> Fragment reassembly time exceeded */
170 #define ICMPv6_PARAMPROB                    4    /* Parameter problem  [RFC 2463, 4443] */
171 #define     ICMPv6_PARAMPROB_FIELD         (0)   /*  --> Erroneous header field encountered */
172 #define     ICMPv6_PARAMPROB_NEXT_HDR      (1)   /*  --> Unrecognized Next Header type encountered */
173 #define     ICMPv6_PARAMPROB_OPTION        (2)   /*  --> Unrecognized IPv6 option encountered */
174 #define ICMPv6_ECHO                        128   /* Echo request  [RFC 2463, 4443] */
175 #define ICMPv6_ECHOREPLY                   129   /* Echo reply  [RFC 2463, 4443] */
176 #define ICMPv6_GRPMEMBQUERY                130   /* Group Membership Query  [RFC 2710] */
177 #define ICMPv6_GRPMEMBREP                  131   /* Group Membership Report  [RFC 2710] */
178 #define ICMPv6_GRPMEMBRED                  132   /* Group Membership Reduction  [RFC 2710] */
179 #define ICMPv6_ROUTERSOLICIT               133   /* Router Solicitation  [RFC 2461] */
180 #define ICMPv6_ROUTERADVERT                134   /* Router Advertisement  [RFC 2461] */
181 #define ICMPv6_NGHBRSOLICIT                135   /* Neighbor Solicitation  [RFC 2461] */
182 #define ICMPv6_NGHBRADVERT                 136   /* Neighbor Advertisement  [RFC 2461] */
183 #define ICMPv6_REDIRECT                    137   /* Redirect  [RFC 2461] */
184 #define ICMPv6_RTRRENUM                    138   /* Router Renumbering  [RFC 2894] */
185 #define     ICMPv6_RTRRENUM_COMMAND        (0)   /*  --> Router Renumbering Command */
186 #define     ICMPv6_RTRRENUM_RESULT         (1)   /*  --> Router Renumbering Result */
187 #define     ICMPv6_RTRRENUM_SEQ_RESET      (255) /* Sequence Number Reset */
188 #define ICMPv6_NODEINFOQUERY               139   /* ICMP Node Information Query  [RFC 4620] */
189 #define     ICMPv6_NODEINFOQUERY_IPv6ADDR  (0)   /*  --> The Data field contains an IPv6 address */
190 #define     ICMPv6_NODEINFOQUERY_NAME      (1)   /*  --> The Data field contains a name */
191 #define     ICMPv6_NODEINFOQUERY_IPv4ADDR  (2)   /*  --> The Data field contains an IPv4 address */
192 #define ICMPv6_NODEINFORESP                140   /* ICMP Node Information Response  [RFC 4620] */
193 #define     ICMPv6_NODEINFORESP_SUCCESS    (0)   /*  --> A successful reply.   */
194 #define     ICMPv6_NODEINFORESP_REFUSED    (1)   /*  --> The Responder refuses to supply the answer */
195 #define     ICMPv6_NODEINFORESP_UNKNOWN    (2)   /*  --> The Qtype of the Query is unknown */
196 #define ICMPv6_INVNGHBRSOLICIT             141   /* Inverse Neighbor Discovery Solicitation Message  [RFC 3122] */
197 #define ICMPv6_INVNGHBRADVERT              142   /* Inverse Neighbor Discovery Advertisement Message  [RFC 3122] */
198 #define ICMPv6_MLDV2                       143   /* MLDv2 Multicast Listener Report  [RFC 3810] */
199 #define ICMPv6_AGENTDISCOVREQ              144   /* Home Agent Address Discovery Request Message  [RFC 3775] */
200 #define ICMPv6_AGENTDISCOVREPLY            145   /* Home Agent Address Discovery Reply Message  [RFC 3775] */
201 #define ICMPv6_MOBPREFIXSOLICIT            146   /* Mobile Prefix Solicitation  [RFC 3775] */
202 #define ICMPv6_MOBPREFIXADVERT             147   /* Mobile Prefix Advertisement  [RFC 3775] */
203 #define ICMPv6_CERTPATHSOLICIT             148   /* Certification Path Solicitation  [RFC 3971] */
204 #define ICMPv6_CERTPATHADVERT              149   /* Certification Path Advertisement  [RFC 3971] */
205 #define ICMPv6_EXPMOBILITY                 150   /* Experimental mobility protocols  [RFC 4065] */
206 #define ICMPv6_MRDADVERT                   151   /* MRD, Multicast Router Advertisement  [RFC 4286] */
207 #define ICMPv6_MRDSOLICIT                  152   /* MRD, Multicast Router Solicitation  [RFC 4286] */
208 #define ICMPv6_MRDTERMINATE                153   /* MRD, Multicast Router Termination  [RFC 4286] */
209 #define ICMPv6_FMIPV6                      154   /* FMIPv6 messages  [RFC 5568] */
210 
211 /* Node Information parameters */
212 /* -> Query types */
213 #define NI_QTYPE_NOOP      0
214 #define NI_QTYPE_UNUSED    1
215 #define NI_QTYPE_NODENAME  2
216 #define NI_QTYPE_NODEADDRS 3
217 #define NI_QTYPE_IPv4ADDRS 4
218 /* -> Misc */
219 #define NI_NONCE_LEN 8
220 
221 /* Nping ICMPv6Header Class internal definitions */
222 #define ICMPv6_COMMON_HEADER_LEN    4
223 #define ICMPv6_MIN_HEADER_LEN       8
224 #define ICMPv6_UNREACH_LEN          (ICMPv6_COMMON_HEADER_LEN+4)
225 #define ICMPv6_PKTTOOBIG_LEN        (ICMPv6_COMMON_HEADER_LEN+4)
226 #define ICMPv6_TIMXCEED_LEN         (ICMPv6_COMMON_HEADER_LEN+4)
227 #define ICMPv6_PARAMPROB_LEN        (ICMPv6_COMMON_HEADER_LEN+4)
228 #define ICMPv6_ECHO_LEN             (ICMPv6_COMMON_HEADER_LEN+4)
229 #define ICMPv6_ECHOREPLY_LEN        (ICMPv6_COMMON_HEADER_LEN+4)
230 #define ICMPv6_ROUTERSOLICIT_LEN    (ICMPv6_COMMON_HEADER_LEN+4)
231 #define ICMPv6_ROUTERADVERT_LEN     (ICMPv6_COMMON_HEADER_LEN+12)
232 #define ICMPv6_NGHBRSOLICIT_LEN     (ICMPv6_COMMON_HEADER_LEN+20)
233 #define ICMPv6_NGHBRADVERT_LEN      (ICMPv6_COMMON_HEADER_LEN+20)
234 #define ICMPv6_REDIRECT_LEN         (ICMPv6_COMMON_HEADER_LEN+36)
235 #define ICMPv6_RTRRENUM_LEN         (ICMPv6_COMMON_HEADER_LEN+12)
236 #define ICMPv6_NODEINFO_LEN         (ICMPv6_COMMON_HEADER_LEN+12)
237 #define ICMPv6_MLD_LEN              (ICMPv6_COMMON_HEADER_LEN+20)
238 /* This must the MAX() of all values defined above*/
239 #define ICMPv6_MAX_MESSAGE_BODY     (ICMPv6_REDIRECT_LEN-ICMPv6_COMMON_HEADER_LEN)
240 
241 
242 
243 /* Node Information flag bitmaks */
244 #define ICMPv6_NI_FLAG_T    0x01
245 #define ICMPv6_NI_FLAG_A    0x02
246 #define ICMPv6_NI_FLAG_C    0x04
247 #define ICMPv6_NI_FLAG_L    0x08
248 #define ICMPv6_NI_FLAG_G    0x10
249 #define ICMPv6_NI_FLAG_S    0x20
250 
251 class ICMPv6Header : public ICMPHeader {
252 
253         /**********************************************************************/
254         /* COMMON ICMPv6 packet HEADER                                        */
255         /**********************************************************************/
256         /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
257            |     Type      |     Code      |          Checksum             |
258            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
259            |                                                               |
260            +                         Message Body                          +
261            |                                                               | */
262         struct nping_icmpv6_hdr{
263             u8 type;
264             u8 code;
265             u16 checksum;
266             u8 data[ICMPv6_MAX_MESSAGE_BODY];
267         }__attribute__((__packed__));
268         typedef struct nping_icmpv6_hdr nping_icmpv6_hdr_t;
269 
270 
271         /**********************************************************************/
272         /* ICMPv6 MESSAGE SPECIFIC HEADERS                                    */
273         /**********************************************************************/
274 
275         /* Destination Unreachable Message
276           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277           |     Type      |     Code      |          Checksum             |
278           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
279           |                             Unused                            |
280           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
281           |                    As much of invoking packet                 |
282           +                as possible without the ICMPv6 packet          +
283           |                exceeding the minimum IPv6 MTU [IPv6]          | */
284         struct dest_unreach_msg{
285             u32 unused;
286             //u8 invoking_pkt[?];
287         }__attribute__((__packed__));
288         typedef struct dest_unreach_msg dest_unreach_msg_t;
289 
290 
291         /* Packet Too Big Message
292           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
293           |     Type      |     Code      |          Checksum             |
294           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
295           |                             MTU                               |
296           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
297           |                    As much of invoking packet                 |
298           +               as possible without the ICMPv6 packet           +
299           |               exceeding the minimum IPv6 MTU [IPv6]           | */
300         struct pkt_too_big_msg{
301             u32 mtu;
302             //u8 invoking_pkt[?];
303         }__attribute__((__packed__));
304         typedef struct pkt_too_big_msg pkt_too_big_msg_t;
305 
306 
307         /* Time Exceeded Message
308           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
309           |     Type      |     Code      |          Checksum             |
310           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311           |                             Unused                            |
312           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
313           |                    As much of invoking packet                 |
314           +               as possible without the ICMPv6 packet           +
315           |               exceeding the minimum IPv6 MTU [IPv6]           | */
316         struct time_exceeded_msg{
317             u32 unused;
318             //u8 invoking_pkt[?];
319         }__attribute__((__packed__));
320         typedef struct time_exceeded_msg time_exceeded_msg_t;
321 
322 
323         /* Parameter Problem Message
324           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
325           |     Type      |     Code      |          Checksum             |
326           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
327           |                            Pointer                            |
328           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
329           |                    As much of invoking packet                 |
330           +               as possible without the ICMPv6 packet           +
331           |               exceeding the minimum IPv6 MTU [IPv6]           | */
332         struct parameter_problem_msg{
333             u32 pointer;
334             //u8 invoking_pkt[?];
335         }__attribute__((__packed__));
336         typedef struct parameter_problem_msg parameter_problem_msg_t;
337 
338 
339         /* Echo Request/Response Messages
340           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
341           |     Type      |     Code      |          Checksum             |
342           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
343           |           Identifier          |        Sequence Number        |
344           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
345           |     Data ...
346           +-+-+-+-+-                                                        */
347         struct echo_msg{
348             u16 id;
349             u16 seq;
350             //u8 data[?];
351         }__attribute__((__packed__));
352         typedef struct echo_msg echo_msg_t;
353 
354         /* Router Advertisement Message
355           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
356           |     Type      |     Code      |          Checksum             |
357           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
358           | Cur Hop Limit |M|O|H|Prf|P|R|R|       Router Lifetime         |
359           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
360           |                         Reachable Time                        |
361           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
362           |                          Retrans Timer                        |
363           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
364           |   Options ...
365           +-+-+-+-+-+-+-+-+-+-+-+-                                          */
366         struct router_advert_msg{
367             u8 current_hop_limit;
368             u8 autoconfig_flags; /* See RFC 5175 */
369             u16 router_lifetime;
370             u32 reachable_time;
371             u32 retransmission_timer;
372             //u8 icmpv6_options[?];
373         }__attribute__((__packed__));
374         typedef struct router_advert_msg router_advert_msg_t;
375 
376 
377         /* Router Solicitation Message
378           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
379           |     Type      |     Code      |          Checksum             |
380           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
381           |                            Reserved                           |
382           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
383           |   Options ...
384           +-+-+-+-+-+-+-+-+-+-+-+-                                          */
385         struct router_solicit_msg{
386             u32 reserved;
387             //u8 icmpv6_options[?];
388         }__attribute__((__packed__));
389         typedef struct router_solicit_msg router_solicit_msg_t;
390 
391 
392         /* Neighbor Advertisement Message
393           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
394           |     Type      |     Code      |          Checksum             |
395           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
396           |R|S|O|                     Reserved                            |
397           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
398           |                                                               |
399           +                                                               +
400           |                                                               |
401           +                       Target Address                          +
402           |                                                               |
403           +                                                               +
404           |                                                               |
405           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
406           |   Options ...
407           +-+-+-+-+-+-+-+-+-+-+-+-                                          */
408         struct neighbor_advert_msg{
409             u8 flags;
410             u8 reserved[3];
411             u8 target_address[16];
412             //u8 icmpv6_options[?];
413         }__attribute__((__packed__));
414         typedef struct neighbor_advert_msg neighbor_advert_msg_t;
415 
416 
417         /* Neighbor Solicitation Message
418           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
419           |     Type      |     Code      |          Checksum             |
420           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
421           |                           Reserved                            |
422           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
423           |                                                               |
424           +                                                               +
425           |                                                               |
426           +                       Target Address                          +
427           |                                                               |
428           +                                                               +
429           |                                                               |
430           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
431           |   Options ...
432           +-+-+-+-+-+-+-+-+-+-+-+- */
433         struct neighbor_solicit_msg{
434             u32 reserved;
435             u8 target_address[16];
436             //u8 icmpv6_options[?];
437         }__attribute__((__packed__));
438         typedef struct neighbor_solicit_msg neighbor_solicit_msg_t;
439 
440 
441         /* Redirect Message
442           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
443           |     Type      |     Code      |          Checksum             |
444           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
445           |                           Reserved                            |
446           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
447           |                                                               |
448           +                                                               +
449           |                                                               |
450           +                       Target Address                          +
451           |                                                               |
452           +                                                               +
453           |                                                               |
454           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
455           |                                                               |
456           +                                                               +
457           |                                                               |
458           +                     Destination Address                       +
459           |                                                               |
460           +                                                               +
461           |                                                               |
462           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
463           |   Options ...
464           +-+-+-+-+-+-+-+-+-+-+-+-                                          */
465         struct redirect_msg{
466             u32 reserved;
467             u8 target_address[16];
468             u8 destination_address[16];
469             //u8 icmpv6_options[?];
470         }__attribute__((__packed__));
471         typedef struct redirect_msg redirect_msg_t;
472 
473 
474         /* Router Renumbering Header
475           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
476           |     Type      |     Code      |            Checksum           |
477           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
478           |                        SequenceNumber                         |
479           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
480           | SegmentNumber |     Flags     |            MaxDelay           |
481           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
482           |                           reserved                            |
483           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
484           |                                                               |
485           /                       RR Message Body                         /
486           |                                                               |
487           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
488         struct router_renumbering_msg{
489             u32 seq;
490             u8 segment_number;
491             u8 flags;
492             u16 max_delay;
493             u32 reserved;
494             //u8 rr_msg_body[?];
495         }__attribute__((__packed__));
496         typedef struct router_renumbering_msg router_renumbering_msg_t;
497 
498 
499          /* Node Information Queries
500            0                   1                   2                   3
501            0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
502           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
503           |     Type      |     Code      |           Checksum            |
504           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
505           |             Qtype             |       unused      |G|S|L|C|A|T|
506           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
507           |                                                               |
508           +                             Nonce                             +
509           |                                                               |
510           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
511           |                                                               |
512           /                             Data                              /
513           |                                                               |
514           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
515         struct nodeinfo_msg{
516             u16 qtype;
517             u16 flags;
518             u64 nonce;
519             //u8 data[?];
520         }__attribute__((__packed__));
521         typedef struct nodeinfo_msg nodeinfo_msg_t;
522 
523 
524         /* Multicast Listener Discovery
525           0                   1                   2                   3
526           0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
527          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
528          |     Type      |     Code      |          Checksum             |
529          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
530          |     Maximum Response Delay    |          Reserved             |
531          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
532          |                                                               |
533          +                                                               +
534          |                                                               |
535          +                       Multicast Address                       +
536          |                                                               |
537          +                                                               +
538          |                                                               |
539          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
540         struct mld_msg{
541             u16 max_response_delay;
542             u16 reserved;
543             u8 mcast_address[16];
544         }__attribute__((__packed__));
545         typedef struct mld_msg mld_msg_t;
546 
547 
548         nping_icmpv6_hdr_t h;
549 
550         /* Helper pointers */
551         dest_unreach_msg_t       *h_du;
552         pkt_too_big_msg_t        *h_ptb;
553         time_exceeded_msg_t      *h_te;
554         parameter_problem_msg_t  *h_pp;
555         echo_msg_t               *h_e;
556         router_advert_msg_t      *h_ra;
557         router_solicit_msg_t     *h_rs;
558         neighbor_advert_msg_t    *h_na;
559         neighbor_solicit_msg_t   *h_ns;
560         redirect_msg_t           *h_r;
561         router_renumbering_msg_t *h_rr;
562         nodeinfo_msg_t           *h_ni;
563         mld_msg_t                *h_mld;
564 
565     public:
566         ICMPv6Header();
567         ~ICMPv6Header();
568         void reset();
569         u8 *getBufferPointer();
570         int storeRecvData(const u8 *buf, size_t len);
571         int protocol_id() const;
572         int validate();
573         int print(FILE *output, int detail) const;
574 
575         /* ICMP Type */
576         int setType(u8 val);
577         u8 getType() const;
578         bool validateType();
579         bool validateType(u8 val);
580 
581         /* Code */
582         int setCode(u8 c);
583         u8 getCode() const;
584         bool validateCode();
585         bool validateCode(u8 type, u8 code);
586 
587         /* Checksum */
588         int setSum();
589         int setSum(u16 s);
590         int setSumRandom();
591         u16 getSum() const;
592 
593         int setReserved(u32 val);
594         u32 getReserved() const;
595         int setUnused(u32 val);
596         u32 getUnused() const;
597 
598         int setFlags(u8 val);
599         u8 getFlags() const;
600 
601         int setMTU(u32 mtu);
602         u32 getMTU() const;
603 
604         /* Parameter problem */
605         int setPointer(u32 val);
606         u32 getPointer() const;
607 
608         /* Echo */
609         int setIdentifier(u16 val);
610         u16 getIdentifier() const;
611         int setSequence(u16 val);
612         int setSequence(u32 val);
613         u32 getSequence() const;
614 
615         /* Router Advertisement */
616         int setCurrentHopLimit(u8 val);
617         u8 getCurrentHopLimit() const;
618 
619         int setRouterLifetime(u16 val);
620         u16 getRouterLifetime() const;
621 
622         int setReachableTime(u32 val);
623         u32 getReachableTime() const;
624 
625         int setRetransmissionTimer(u32 val);
626         u32 getRetransmissionTimer() const;
627 
628         int setTargetAddress(struct in6_addr addr);
629         struct in6_addr getTargetAddress() const;
630 
631         int setDestinationAddress(struct in6_addr addr);
632         struct in6_addr getDestinationAddress() const;
633 
634         int setSegmentNumber(u8 val);
635         u8 getSegmentNumber() const;
636 
637         int setMaxDelay(u16 val);
638         u16 getMaxDelay() const;
639 
640         /* Node Information Queries */
641         int setQtype(u16 val);
642         u16 getQtype() const;
643         int setNodeInfoFlags(u16 val);
644         u16 getNodeInfoFlags() const;
645         int  setG(bool flag_value=true);
646         bool getG() const;
647         int  setS(bool flag_value=true);
648         bool getS() const;
649         int  setL(bool flag_value=true);
650         bool getL() const;
651         int  setC(bool flag_value=true);
652         bool getC() const;
653         int  setA(bool flag_value=true);
654         bool getA() const;
655         int  setT(bool flag_value=true);
656         bool getT() const;
657         int setNonce(u64 nonce_value);
658         int setNonce(const u8 *nonce);
659         u64 getNonce() const;
660 
661         /* Multicast Listener Discovery */
662         int setMulticastAddress(struct in6_addr addr);
663         struct in6_addr getMulticastAddress() const;
664 
665         /* Misc */
666         int getHeaderLengthFromType(u8 type) const;
667         bool isError() const;
668         const char *type2string(int type, int code) const;
669 
670 }; /* End of class ICMPv6Header */
671 
672 #endif
673