1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Component */
16 /** */
17 /** Internet Control Message Protocol (ICMP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "nx_api.h"
28 #include "nx_ipv6.h"
29 #include "nx_icmpv6.h"
30
31 #ifdef FEATURE_NX_IPV6
32
33
34 /**************************************************************************/
35 /* */
36 /* FUNCTION RELEASE */
37 /* */
38 /* _nx_icmpv6_validate_neighbor_message PORTABLE C */
39 /* 6.1 */
40 /* AUTHOR */
41 /* */
42 /* Yuxin Zhou, Microsoft Corporation */
43 /* */
44 /* DESCRIPTION */
45 /* */
46 /* This internal function validates incoming neighbor advertisement */
47 /* message and neighbor solicitation message. */
48 /* */
49 /* INPUT */
50 /* */
51 /* packet_ptr ICMPv6 packet to validate */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* NX_SUCCESS ICMPv6 options are valid */
56 /* NX_NOT_SUCCESS ICMPv6 options are invalid */
57 /* */
58 /* CALLS */
59 /* */
60 /* IPv6_Address_Type Determine address type (e.g. unicast) */
61 /* _nx_icmpv6_validate_options Validate option fields in ICMP header */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* _nx_icmpv6_process_ns Process received NS packet */
66 /* _nx_icmpv6_process_na Process received NA packet */
67 /* */
68 /* RELEASE HISTORY */
69 /* */
70 /* DATE NAME DESCRIPTION */
71 /* */
72 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
73 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
74 /* resulting in version 6.1 */
75 /* */
76 /**************************************************************************/
_nx_icmpv6_validate_neighbor_message(NX_PACKET * packet_ptr)77 UINT _nx_icmpv6_validate_neighbor_message(NX_PACKET *packet_ptr)
78 {
79
80 NX_ICMPV6_ND *nd_header_ptr;
81 NX_IPV6_HEADER *ipv6_header;
82 NX_ICMPV6_OPTION *option_ptr;
83 UINT option_length;
84 UINT option_check;
85 ULONG source_address_type;
86 ULONG dest_address_type;
87
88
89 /* Points to the IPv6 header. */
90 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
91 ipv6_header = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
92
93 /*
94 * Validate the IP header information.
95 * The following validation procedure is defined in RFC2461
96 * 7.1.1: Validation of Neighbor Solicitations
97 * 7.1.2: Validation of Neighbor Advertisements
98 */
99
100 /* Hop limit must be 255, I.e., the packet could not possibly have been forwarded by a router. */
101 if ((ipv6_header -> nx_ip_header_word_1 & 0xFF) != 0xFF)
102 {
103 return(NX_NOT_SUCCESSFUL);
104 }
105
106 /* Points to the ICMP message header. */
107 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
108 nd_header_ptr = (NX_ICMPV6_ND *)packet_ptr -> nx_packet_prepend_ptr;
109
110 /* ICMP code must be 0 */
111 if (nd_header_ptr -> nx_icmpv6_nd_header.nx_icmpv6_header_code != 0)
112 {
113 return(NX_NOT_SUCCESSFUL);
114 }
115
116 /* ICMP length (derived from the IP Length) is 24 or more. */
117 if (packet_ptr -> nx_packet_length < 24)
118 {
119 return(NX_NOT_SUCCESSFUL);
120 }
121
122 /* Target Address must not be a multicast address. */
123 if ((nd_header_ptr -> nx_icmpv6_nd_targetAddress[0] & (ULONG)0xFF000000) == (ULONG)0xFF000000)
124 {
125 return(NX_NOT_SUCCESSFUL);
126 }
127
128 /* Find out the destination IP address type. */
129 dest_address_type = IPv6_Address_Type(ipv6_header -> nx_ip_header_destination_ip);
130
131 option_check = 0;
132
133 if (nd_header_ptr -> nx_icmpv6_nd_header.nx_icmpv6_header_type == NX_ICMPV6_NEIGHBOR_SOLICITATION_TYPE)
134 {
135
136 /* Find out the source IP address type. */
137 source_address_type = IPv6_Address_Type(ipv6_header -> nx_ip_header_source_ip);
138
139 /* If the IP source address is the unspecified address, the IP destination address
140 is a solicated-node multicast address. */
141 if (source_address_type == IPV6_ADDRESS_UNSPECIFIED)
142 {
143
144 if ((dest_address_type & IPV6_SOLICITED_NODE_MCAST) != IPV6_SOLICITED_NODE_MCAST)
145 {
146 return(NX_NOT_SUCCESSFUL);
147 }
148
149 /* if the IP source address is the unspecified address, it must not contain
150 source link-layer address option in the message. */
151 option_check = NX_NO_SLLA;
152 }
153 }
154 else
155 {
156
157 /* If the IP Destination Address is a multicast address, the
158 Solicted flag must be zero. */
159 if (((ipv6_header -> nx_ip_header_destination_ip[0] & (ULONG)0xFF000000) == (ULONG)0xFF000000) &&
160 nd_header_ptr -> nx_icmpv6_nd_flag & 0x40000000)
161 {
162
163 return(NX_NOT_SUCCESSFUL);
164 }
165 }
166
167 /* Locate the option field. */
168 /*lint -e{923} suppress cast between pointer and ULONG, since it is necessary */
169 option_ptr = (NX_ICMPV6_OPTION *)NX_UCHAR_POINTER_ADD(nd_header_ptr, sizeof(NX_ICMPV6_ND));
170 option_length = (UINT)(packet_ptr -> nx_packet_length - sizeof(NX_ICMPV6_ND));
171
172 /* Validate option fields if there are any. */
173 if (option_length)
174 {
175 return(_nx_icmpv6_validate_options(option_ptr, (INT)option_length, (INT)option_check));
176 }
177
178 return(NX_SUCCESS);
179 }
180
181
182 #endif /* FEATURE_NX_IPV6 */
183
184