FD.io VPP  v18.01.2-1-g9b554f3
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 {
57 
58 always_inline void
60  vlib_node_runtime_t * error_node,
61  vlib_buffer_t * p0, vlib_buffer_t * p1,
62  ip4_header_t * ip0, ip4_header_t * ip1,
63  u32 * next0, u32 * next1, int verify_checksum)
64 {
65  u8 error0, error1;
66  u32 ip_len0, cur_len0;
67  u32 ip_len1, cur_len1;
68  i32 len_diff0, len_diff1;
69 
70  error0 = error1 = IP4_ERROR_NONE;
71 
72  /* Punt packets with options or wrong version. */
74  error0 = (ip0->ip_version_and_header_length & 0xf) != 5 ?
75  IP4_ERROR_OPTIONS : IP4_ERROR_VERSION;
76 
78  error1 = (ip1->ip_version_and_header_length & 0xf) != 5 ?
79  IP4_ERROR_OPTIONS : IP4_ERROR_VERSION;
80 
81  if (PREDICT_FALSE (ip0->ttl < 1))
82  error0 = IP4_ERROR_TIME_EXPIRED;
83  if (PREDICT_FALSE (ip1->ttl < 1))
84  error1 = IP4_ERROR_TIME_EXPIRED;
85 
86  /* Verify header checksum. */
87  if (verify_checksum)
88  {
89  ip_csum_t sum0, sum1;
90 
93 
94  error0 = 0xffff != ip_csum_fold (sum0) ?
95  IP4_ERROR_BAD_CHECKSUM : error0;
96  error1 = 0xffff != ip_csum_fold (sum1) ?
97  IP4_ERROR_BAD_CHECKSUM : error1;
98  }
99 
100  /* Drop fragmentation offset 1 packets. */
101  error0 = ip4_get_fragment_offset (ip0) == 1 ?
102  IP4_ERROR_FRAGMENT_OFFSET_ONE : error0;
103  error1 = ip4_get_fragment_offset (ip1) == 1 ?
104  IP4_ERROR_FRAGMENT_OFFSET_ONE : error1;
105 
106  /* Verify lengths. */
107  ip_len0 = clib_net_to_host_u16 (ip0->length);
108  ip_len1 = clib_net_to_host_u16 (ip1->length);
109 
110  /* IP length must be at least minimal IP header. */
111  error0 = ip_len0 < sizeof (ip0[0]) ? IP4_ERROR_TOO_SHORT : error0;
112  error1 = ip_len1 < sizeof (ip1[0]) ? IP4_ERROR_TOO_SHORT : error1;
113 
114  cur_len0 = vlib_buffer_length_in_chain (vm, p0);
115  cur_len1 = vlib_buffer_length_in_chain (vm, p1);
116 
117  len_diff0 = cur_len0 - ip_len0;
118  len_diff1 = cur_len1 - ip_len1;
119 
120  error0 = len_diff0 < 0 ? IP4_ERROR_BAD_LENGTH : error0;
121  error1 = len_diff1 < 0 ? IP4_ERROR_BAD_LENGTH : error1;
122 
123  if (PREDICT_FALSE (error0 != IP4_ERROR_NONE))
124  {
125  if (error0 == IP4_ERROR_TIME_EXPIRED)
126  {
127  icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
128  ICMP4_time_exceeded_ttl_exceeded_in_transit,
129  0);
130  *next0 = IP4_INPUT_NEXT_ICMP_ERROR;
131  }
132  else
133  *next0 = error0 != IP4_ERROR_OPTIONS ?
135  }
136  if (PREDICT_FALSE (error1 != IP4_ERROR_NONE))
137  {
138  if (error1 == IP4_ERROR_TIME_EXPIRED)
139  {
140  icmp4_error_set_vnet_buffer (p1, ICMP4_time_exceeded,
141  ICMP4_time_exceeded_ttl_exceeded_in_transit,
142  0);
143  *next1 = IP4_INPUT_NEXT_ICMP_ERROR;
144  }
145  else
146  *next1 = error1 != IP4_ERROR_OPTIONS ?
148  }
149 
150  p0->error = error_node->errors[error0];
151  p1->error = error_node->errors[error1];
152 }
153 
154 always_inline void
156  vlib_node_runtime_t * error_node,
157  vlib_buffer_t * p0,
158  ip4_header_t * ip0, u32 * next0, int verify_checksum)
159 {
160  u32 ip_len0, cur_len0;
161  i32 len_diff0;
162  u8 error0;
163 
164  error0 = IP4_ERROR_NONE;
165 
166  /* Punt packets with options or wrong version. */
167  if (PREDICT_FALSE (ip0->ip_version_and_header_length != 0x45))
168  error0 = (ip0->ip_version_and_header_length & 0xf) != 5 ?
169  IP4_ERROR_OPTIONS : IP4_ERROR_VERSION;
170 
171  /* Verify header checksum. */
172  if (verify_checksum)
173  {
174  ip_csum_t sum0;
175 
176  ip4_partial_header_checksum_x1 (ip0, sum0);
177 
178  error0 = 0xffff != ip_csum_fold (sum0) ?
179  IP4_ERROR_BAD_CHECKSUM : error0;
180  }
181 
182  /* Drop fragmentation offset 1 packets. */
183  error0 = ip4_get_fragment_offset (ip0) == 1 ?
184  IP4_ERROR_FRAGMENT_OFFSET_ONE : error0;
185 
186  /* Verify lengths. */
187  ip_len0 = clib_net_to_host_u16 (ip0->length);
188 
189  /* IP length must be at least minimal IP header. */
190  error0 = ip_len0 < sizeof (ip0[0]) ? IP4_ERROR_TOO_SHORT : error0;
191 
192  cur_len0 = vlib_buffer_length_in_chain (vm, p0);
193 
194  len_diff0 = cur_len0 - ip_len0;
195 
196  error0 = len_diff0 < 0 ? IP4_ERROR_BAD_LENGTH : error0;
197 
198  if (PREDICT_FALSE (error0 != IP4_ERROR_NONE))
199  {
200  if (error0 == IP4_ERROR_TIME_EXPIRED)
201  {
202  icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
203  ICMP4_time_exceeded_ttl_exceeded_in_transit,
204  0);
205  *next0 = IP4_INPUT_NEXT_ICMP_ERROR;
206  }
207  else
208  *next0 = error0 != IP4_ERROR_OPTIONS ?
210  }
211 
212  p0->error = error_node->errors[error0];
213 }
214 
215 /*
216  * fd.io coding-style-patch-verification: ON
217  *
218  * Local Variables:
219  * eval: (c-set-style "gnu")
220  * End:
221  */
222 
223 #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:155
#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:113
vlib_main_t * vm
Definition: buffer.c:283
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:59
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