VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/Ip4Dxe/Ip4Option.c@ 80721

Last change on this file since 80721 was 80721, checked in by vboxsync, 5 years ago

Devices/EFI/FirmwareNew: Start upgrade process to edk2-stable201908 (compiles on Windows and works to some extent), bugref:4643

  • Property svn:eol-style set to native
File size: 4.8 KB
Line 
1/** @file
2 IP4 option support functions.
3
4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include "Ip4Impl.h"
10
11
12/**
13 Validate the IP4 option format for both the packets we received
14 and will transmit.
15
16 @param[in] Option The first byte of the option
17 @param[in] OptionLen The length of the whole option
18 @param[in] Rcvd The option is from the packet we received if TRUE,
19 otherwise the option we wants to transmit.
20
21 @retval TRUE The option is properly formatted
22 @retval FALSE The option is mal-formated
23
24**/
25BOOLEAN
26Ip4OptionIsValid (
27 IN UINT8 *Option,
28 IN UINT32 OptionLen,
29 IN BOOLEAN Rcvd
30 )
31{
32 UINT32 Cur;
33 UINT32 Len;
34 UINT32 Point;
35
36 Cur = 0;
37
38 while (Cur < OptionLen) {
39 switch (Option[Cur]) {
40 case IP4_OPTION_NOP:
41 Cur++;
42 break;
43
44 case IP4_OPTION_EOP:
45 Cur = OptionLen;
46 break;
47
48 case IP4_OPTION_LSRR:
49 case IP4_OPTION_SSRR:
50 case IP4_OPTION_RR:
51 Len = Option[Cur + 1];
52 Point = Option[Cur + 2];
53
54 //
55 // SRR/RR options are formatted as |Type|Len|Point|Ip1|Ip2|...
56 //
57 if ((OptionLen - Cur < Len) || (Len < 3) || ((Len - 3) % 4 != 0)) {
58 return FALSE;
59 }
60
61 if ((Point > Len + 1) || (Point % 4 != 0)) {
62 return FALSE;
63 }
64
65 //
66 // The Point must point pass the last entry if the packet is received
67 // by us. It must point to 4 if the packet is to be sent by us for
68 // source route option.
69 //
70 if ((Option[Cur] != IP4_OPTION_RR) &&
71 ((Rcvd && (Point != Len + 1)) || (!Rcvd && (Point != 4)))) {
72
73 return FALSE;
74 }
75
76 Cur += Len;
77 break;
78
79 default:
80 Len = Option[Cur + 1];
81
82 if ((OptionLen - Cur < Len) || (Len < 2)) {
83 return FALSE;
84 }
85
86 Cur = Cur + Len;
87 break;
88 }
89
90 }
91
92 return TRUE;
93}
94
95
96/**
97 Copy the option from the original option to buffer. It
98 handles the details such as:
99 1. whether copy the single IP4 option to the first/non-first
100 fragments.
101 2. Pad the options copied over to aligned to 4 bytes.
102
103 @param[in] Option The original option to copy from
104 @param[in] OptionLen The length of the original option
105 @param[in] FirstFragment Whether it is the first fragment
106 @param[in, out] Buf The buffer to copy options to. NULL
107 @param[in, out] BufLen The length of the buffer
108
109 @retval EFI_SUCCESS The options are copied over
110 @retval EFI_BUFFER_TOO_SMALL Buf is NULL or BufLen provided is too small.
111
112**/
113EFI_STATUS
114Ip4CopyOption (
115 IN UINT8 *Option,
116 IN UINT32 OptionLen,
117 IN BOOLEAN FirstFragment,
118 IN OUT UINT8 *Buf, OPTIONAL
119 IN OUT UINT32 *BufLen
120 )
121{
122 UINT8 OptBuf[40];
123 UINT32 Cur;
124 UINT32 Next;
125 UINT8 Type;
126 UINT32 Len;
127
128 ASSERT ((BufLen != NULL) && (OptionLen <= 40));
129
130 Cur = 0;
131 Next = 0;
132
133 while (Cur < OptionLen) {
134 Type = Option[Cur];
135 Len = Option[Cur + 1];
136
137 if (Type == IP4_OPTION_NOP) {
138 //
139 // Keep the padding, in case that the sender wants to align
140 // the option, say, to 4 bytes
141 //
142 OptBuf[Next] = IP4_OPTION_NOP;
143 Next++;
144 Cur++;
145
146 } else if (Type == IP4_OPTION_EOP) {
147 //
148 // Don't append the EOP to avoid including only a EOP option
149 //
150 break;
151
152 } else {
153 //
154 // don't copy options that is only valid for the first fragment
155 //
156 if (FirstFragment || (Type & IP4_OPTION_COPY_MASK) != 0) {
157 CopyMem (OptBuf + Next, Option + Cur, Len);
158 Next += Len;
159 }
160
161 Cur += Len;
162 }
163 }
164
165 //
166 // Don't append an EOP only option.
167 //
168 if (Next == 0) {
169 *BufLen = 0;
170 return EFI_SUCCESS;
171 }
172
173 //
174 // Append an EOP if the end of option doesn't coincide with the
175 // end of the IP header, that is, isn't aligned to 4 bytes..
176 //
177 if ((Next % 4) != 0) {
178 OptBuf[Next] = IP4_OPTION_EOP;
179 Next++;
180 }
181
182 //
183 // Head length is in the unit of 4 bytes. Now, Len is the
184 // acutal option length to appear in the IP header.
185 //
186 Len = ((Next + 3) &~0x03);
187
188 //
189 // If the buffer is too small, set the BufLen then return
190 //
191 if ((Buf == NULL) || (*BufLen < Len)) {
192 *BufLen = Len;
193 return EFI_BUFFER_TOO_SMALL;
194 }
195
196 //
197 // Copy the option to the Buf, zero the buffer first to pad
198 // the options with NOP to align to 4 bytes.
199 //
200 ZeroMem (Buf, Len);
201 CopyMem (Buf, OptBuf, Next);
202 *BufLen = Len;
203 return EFI_SUCCESS;
204}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette