]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Option.c
BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Option.c
1 /** @file
2 IP4 option support functions.
3
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-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 **/
25 BOOLEAN
26 Ip4OptionIsValid (
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 **/
113 EFI_STATUS
114 Ip4CopyOption (
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 }