]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.c
Scrubbed more.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Option.c
1 /** @file
2
3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Ip4Option.c
15
16 Abstract:
17
18 IP4 option support functions
19
20
21 **/
22
23 #include "Ip4Impl.h"
24
25
26 /**
27 Validate the IP4 option format for both the packets we received
28 and will transmit. It will compute the ICMP error message fields
29 if the option is mal-formated. But this information isn't used.
30
31 @param Option The first byte of the option
32 @param OptionLen The length of the whole option
33 @param Rcvd The option is from the packet we received if TRUE,
34 otherwise the option we wants to transmit.
35
36 @retval TRUE The option is properly formatted
37 @retval FALSE The option is mal-formated
38
39 **/
40 BOOLEAN
41 Ip4OptionIsValid (
42 IN UINT8 *Option,
43 IN UINT32 OptionLen,
44 IN BOOLEAN Rcvd
45 )
46 {
47 UINT32 Cur;
48 UINT32 Len;
49 UINT32 Point;
50 volatile UINT8 IcmpType;
51 volatile UINT8 IcmpCode;
52 volatile UINT32 IcmpPoint;
53
54 IcmpType = ICMP_PARAMETER_PROBLEM;
55 IcmpCode = 0;
56 IcmpPoint = 0;
57
58 Cur = 0;
59
60 while (Cur < OptionLen) {
61 switch (Option[Cur]) {
62 case IP4_OPTION_NOP:
63 Cur++;
64 break;
65
66 case IP4_OPTION_EOP:
67 Cur = OptionLen;
68 break;
69
70 case IP4_OPTION_LSRR:
71 case IP4_OPTION_SSRR:
72 case IP4_OPTION_RR:
73 Len = Option[Cur + 1];
74 Point = Option[Cur + 2];
75
76 //
77 // SRR/RR options are formatted as |Type|Len|Point|Ip1|Ip2|...
78 //
79 if ((OptionLen - Cur < Len) || (Len < 3) || ((Len - 3) % 4 != 0)) {
80 IcmpPoint = Cur + 1;
81 return FALSE;
82 }
83
84 if ((Point > Len + 1) || (Point % 4 != 0)) {
85 IcmpPoint = Cur + 2;
86 return FALSE;
87 }
88
89 //
90 // The Point must point pass the last entry if the packet is received
91 // by us. It must point to 4 if the packet is to be sent by us for
92 // source route option.
93 //
94 if ((Option[Cur] != IP4_OPTION_RR) &&
95 ((Rcvd && (Point != Len + 1)) || (!Rcvd && (Point != 4)))) {
96
97 IcmpType = ICMP_DEST_UNREACHABLE;
98 IcmpCode = ICMP_SOURCEROUTE_FAILED;
99 return FALSE;
100 }
101
102 Cur += Len;
103 break;
104
105 default:
106 Len = Option[Cur + 1];
107
108 if ((OptionLen - Cur < Len) || (Len < 2)) {
109 IcmpPoint = Cur + 1;
110 return FALSE;
111 }
112
113 Cur = Cur + Len;
114 break;
115 }
116
117 }
118
119 return TRUE;
120 }
121
122
123 /**
124 Copy the option from the original option to buffer. It
125 handles the details such as:
126 1. whether copy the single IP4 option to the first/non-first
127 fragments.
128 2. Pad the options copied over to aligned to 4 bytes.
129
130 @param Option The original option to copy from
131 @param OptionLen The length of the original option
132 @param FirstFragment Whether it is the first fragment
133 @param Buf The buffer to copy options to. NULL
134 @param BufLen The length of the buffer
135
136 @retval EFI_SUCCESS The options are copied over
137 @retval EFI_BUFFER_TOO_SMALL Buf is NULL or BufLen provided is too small.
138
139 **/
140 EFI_STATUS
141 Ip4CopyOption (
142 IN UINT8 *Option,
143 IN UINT32 OptionLen,
144 IN BOOLEAN FirstFragment,
145 IN OUT UINT8 *Buf, OPTIONAL
146 IN OUT UINT32 *BufLen
147 )
148 {
149 UINT8 OptBuf[40];
150 UINT32 Cur;
151 UINT32 Next;
152 UINT8 Type;
153 UINT32 Len;
154
155 ASSERT ((BufLen != NULL) && (OptionLen <= 40));
156
157 Cur = 0;
158 Next = 0;
159
160 while (Cur < OptionLen) {
161 Type = Option[Cur];
162 Len = Option[Cur + 1];
163
164 if (Type == IP4_OPTION_NOP) {
165 //
166 // Keep the padding, in case that the sender wants to align
167 // the option, say, to 4 bytes
168 //
169 OptBuf[Next] = IP4_OPTION_NOP;
170 Next++;
171 Cur++;
172
173 } else if (Type == IP4_OPTION_EOP) {
174 //
175 // Don't append the EOP to avoid including only a EOP option
176 //
177 break;
178
179 } else {
180 //
181 // don't copy options that is only valid for the first fragment
182 //
183 if (FirstFragment || (Type & IP4_OPTION_COPY_MASK) != 0) {
184 CopyMem (OptBuf + Next, Option + Cur, Len);
185 Next += Len;
186 }
187
188 Cur += Len;
189 }
190 }
191
192 //
193 // Don't append an EOP only option.
194 //
195 if (Next == 0) {
196 *BufLen = 0;
197 return EFI_SUCCESS;
198 }
199
200 //
201 // Append an EOP if the end of option doesn't coincide with the
202 // end of the IP header, that is, isn't aligned to 4 bytes..
203 //
204 if ((Next % 4) != 0) {
205 OptBuf[Next] = IP4_OPTION_EOP;
206 Next++;
207 }
208
209 //
210 // Head length is in the unit of 4 bytes. Now, Len is the
211 // acutal option length to appear in the IP header.
212 //
213 Len = ((Next + 3) &~0x03);
214
215 //
216 // If the buffer is too small, set the BufLen then return
217 //
218 if ((Buf == NULL) || (*BufLen < Len)) {
219 *BufLen = Len;
220 return EFI_BUFFER_TOO_SMALL;
221 }
222
223 //
224 // Copy the option to the Buf, zero the buffer first to pad
225 // the options with NOP to align to 4 bytes.
226 //
227 ZeroMem (Buf, Len);
228 CopyMem (Buf, OptBuf, Next);
229 *BufLen = Len;
230 return EFI_SUCCESS;
231 }