FD.io VPP  v18.04-17-g3a0d853
Vector Packet Processing
ip4_input.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  * ip/ip4_input.c: IP v4 input node
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #ifndef included_ip_input_h
41 #define included_ip_input_h
42 
43 #include <vnet/ip/ip.h>
44 #include <vnet/ethernet/ethernet.h>
45 
46 extern char *ip4_error_strings[];
47 
48 typedef enum
49 {
58 
59 always_inline void
61  vlib_node_runtime_t * error_node,
62  vlib_buffer_t * p0, vlib_buffer_t * p1,
63  ip4_header_t * ip0, ip4_header_t * ip1,
64  u32 * next0, u32 * next1, int verify_checksum)
65 {
66  u8 error0, error1;
67  u32 ip_len0, cur_len0;
68  u32 ip_len1, cur_len1;
69  i32 len_diff0, len_diff1;
70 
71  error0 = error1 = IP4_ERROR_NONE;
72 
73  /* Punt packets with options or wrong version. */
75  error0 = (ip0->ip_version_and_header_length & 0xf) != 5 ?
76  IP4_ERROR_OPTIONS : IP4_ERROR_VERSION;
77 
79  error1 = (ip1->ip_version_and_header_length & 0xf) != 5 ?
80  IP4_ERROR_OPTIONS : IP4_ERROR_VERSION;
81 
82  if (PREDICT_FALSE (ip0->ttl < 1))
83  error0 = IP4_ERROR_TIME_EXPIRED;
84  if (PREDICT_FALSE (ip1->ttl < 1))
85  error1 = IP4_ERROR_TIME_EXPIRED;
86 
87  /* Verify header checksum. */
88  if (verify_checksum)
89  {
90  ip_csum_t sum0, sum1;
91 
94 
95  error0 = 0xffff != ip_csum_fold (sum0) ?
96  IP4_ERROR_BAD_CHECKSUM : error0;
97  error1 = 0xffff != ip_csum_fold (sum1) ?
98  IP4_ERROR_BAD_CHECKSUM : error1;
99  }
100 
101  /* Drop fragmentation offset 1 packets. */
102  error0 = ip4_get_fragment_offset (ip0) == 1 ?
103  IP4_ERROR_FRAGMENT_OFFSET_ONE : error0;
104  error1 = ip4_get_fragment_offset (ip1) == 1 ?
105  IP4_ERROR_FRAGMENT_OFFSET_ONE : error1;
106 
107  /* Verify lengths. */
108  ip_len0 = clib_net_to_host_u16 (ip0->length);
109  ip_len1 = clib_net_to_host_u16 (ip1->length);
110 
111  /* IP length must be at least minimal IP header. */
112  error0 = ip_len0 < sizeof (ip0[0]) ? IP4_ERROR_TOO_SHORT : error0;
113  error1 = ip_len1 < sizeof (ip1[0]) ? IP4_ERROR_TOO_SHORT : error1;
114 
115  cur_len0 = vlib_buffer_length_in_chain (vm, p0);
116  cur_len1 = vlib_buffer_length_in_chain (vm, p1);
117 
118  len_diff0 = cur_len0 - ip_len0;
119  len_diff1 = cur_len1 - ip_len1;
120 
121  error0 = len_diff0 < 0 ? IP4_ERROR_BAD_LENGTH : error0;
122  error1 = len_diff1 < 0 ? IP4_ERROR_BAD_LENGTH : error1;
123 
124  if (PREDICT_FALSE (error0 != IP4_ERROR_NONE))
125  {
126  if (error0 == IP4_ERROR_TIME_EXPIRED)
127  {
128  icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
129  ICMP4_time_exceeded_ttl_exceeded_in_transit,
130  0);
131  *next0 = IP4_INPUT_NEXT_ICMP_ERROR;
132  }
133  else
134  *next0 = error0 != IP4_ERROR_OPTIONS ?
136  }
137  if (PREDICT_FALSE (error1 != IP4_ERROR_NONE))
138  {
139  if (error1 == IP4_ERROR_TIME_EXPIRED)
140  {
141  icmp4_error_set_vnet_buffer (p1, ICMP4_time_exceeded,
142  ICMP4_time_exceeded_ttl_exceeded_in_transit,
143  0);
144  *next1 = IP4_INPUT_NEXT_ICMP_ERROR;
145  }
146  else
147  *next1 = error1 != IP4_ERROR_OPTIONS ?
149  }
150 
151  p0->error = error_node->errors[error0];
152  p1->error = error_node->errors[error1];
153 }
154 
155 always_inline void
157  vlib_node_runtime_t * error_node,
158  vlib_buffer_t * p0,
159  ip4_header_t * ip0, u32 * next0, int verify_checksum)
160 {
161  u32 ip_len0, cur_len0;
162  i32 len_diff0;
163  u8 error0;
164 
165  error0 = IP4_ERROR_NONE;
166 
167  /* Punt packets with options or wrong version. */
168  if (PREDICT_FALSE (ip0->ip_version_and_header_length != 0x45))
169  error0 = (ip0->ip_version_and_header_length & 0xf) != 5 ?
170  IP4_ERROR_OPTIONS : IP4_ERROR_VERSION;
171 
172  /* Verify header checksum. */
173  if (verify_checksum)
174  {
175  ip_csum_t sum0;
176 
177  ip4_partial_header_checksum_x1 (ip0, sum0);
178 
179  error0 = 0xffff != ip_csum_fold (sum0) ?
180  IP4_ERROR_BAD_CHECKSUM : error0;
181  }
182 
183  /* Drop fragmentation offset 1 packets. */
184  error0 = ip4_get_fragment_offset (ip0) == 1 ?
185  IP4_ERROR_FRAGMENT_OFFSET_ONE : error0;
186 
187  /* Verify lengths. */
188  ip_len0 = clib_net_to_host_u16 (ip0->length);
189 
190  /* IP length must be at least minimal IP header. */
191  error0 = ip_len0 < sizeof (ip0[0]) ? IP4_ERROR_TOO_SHORT : error0;
192 
193  cur_len0 = vlib_buffer_length_in_chain (vm, p0);
194 
195  len_diff0 = cur_len0 - ip_len0;
196 
197  error0 = len_diff0 < 0 ? IP4_ERROR_BAD_LENGTH : error0;
198 
199  if (PREDICT_FALSE (error0 != IP4_ERROR_NONE))
200  {
201  if (error0 == IP4_ERROR_TIME_EXPIRED)
202  {
203  icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
204  ICMP4_time_exceeded_ttl_exceeded_in_transit,
205  0);
206  *next0 = IP4_INPUT_NEXT_ICMP_ERROR;
207  }
208  else
209  *next0 = error0 != IP4_ERROR_OPTIONS ?
211  }
212 
213  p0->error = error_node->errors[error0];
214 }
215 
216 /*
217  * fd.io coding-style-patch-verification: ON
218  *
219  * Local Variables:
220  * eval: (c-set-style "gnu")
221  * End:
222  */
223 
224 #endif
uword ip_csum_t
Definition: ip_packet.h:90
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:415
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:107
#define always_inline
Definition: clib.h:92
static int ip4_get_fragment_offset(ip4_header_t *i)
Definition: ip4_packet.h:192
int i32
Definition: types.h:81
static void ip4_input_check_x1(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, ip4_header_t *ip0, u32 *next0, int verify_checksum)
Definition: ip4_input.h:156
#define PREDICT_FALSE(x)
Definition: clib.h:105
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:130
vlib_main_t * vm
Definition: buffer.c:294
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.c:431
unsigned int u32
Definition: types.h:88
ip4_input_next_t
Definition: ip4_input.h:48
char * ip4_error_strings[]
Definition: ip4_input.c:270
static void ip4_input_check_x2(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, vlib_buffer_t *p1, ip4_header_t *ip0, ip4_header_t *ip1, u32 *next0, u32 *next1, int verify_checksum)
Definition: ip4_input.h:60
unsigned char u8
Definition: types.h:56
#define ip4_partial_header_checksum_x1(ip0, sum0)
Definition: ip4_packet.h:265
u8 ip_version_and_header_length
Definition: ip4_packet.h:132
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:145