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