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