vrrp: fix vrrp_garp_or_na_send()'s memory leak
[vpp.git] / src / plugins / urpf / urpf_dp.h
1 /*
2  * Copyright (c) 2015 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_source_check.c: IP v4 check source address (unicast RPF check)
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 __URPF_DP_H__
41 #define __URPF_DP_H__
42
43 #include <vnet/fib/ip4_fib.h>
44 #include <vnet/fib/ip6_fib.h>
45 #include <vnet/fib/fib_urpf_list.h>
46 #include <vnet/dpo/load_balance.h>
47
48 #include <urpf/urpf.h>
49
50 /**
51  * @file
52  * @brief Unicast Reverse Path forwarding.
53  *
54  * This file contains the interface unicast source check.
55  */
56 typedef struct
57 {
58   index_t urpf;
59 } urpf_trace_t;
60
61 static u8 *
62 format_urpf_trace (u8 * s, va_list * va)
63 {
64   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
65   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
66   urpf_trace_t *t = va_arg (*va, urpf_trace_t *);
67
68   s = format (s, "uRPF:%d", t->urpf);
69
70   return s;
71 }
72
73 #define foreach_urpf_error                 \
74   _(DROP, "uRPF Drop")                     \
75
76 typedef enum urpf_error_t_
77 {
78 #define _(a,b) URPF_ERROR_##a,
79   foreach_urpf_error
80 #undef _
81     URPF_N_ERROR,
82 } urpf_error_t;
83
84 typedef enum
85 {
86   URPF_NEXT_DROP,
87   URPF_N_NEXT,
88 } urpf_next_t;
89
90 static_always_inline uword
91 urpf_inline (vlib_main_t * vm,
92              vlib_node_runtime_t * node,
93              vlib_frame_t * frame,
94              ip_address_family_t af, vlib_dir_t dir, urpf_mode_t mode)
95 {
96   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
97   u16 nexts[VLIB_FRAME_SIZE], *next;
98   u32 n_left, *from;
99
100   from = vlib_frame_vector_args (frame);
101   n_left = frame->n_vectors;
102   b = bufs;
103   next = nexts;
104
105   vlib_get_buffers (vm, from, bufs, n_left);
106
107   while (n_left >= 4)
108     {
109       u32 pass0, lb_index0, pass1, lb_index1;
110       const load_balance_t *lb0, *lb1;
111       u32 fib_index0, fib_index1;
112       const u8 *h0, *h1;
113
114       /* Prefetch next iteration. */
115       {
116         vlib_prefetch_buffer_header (b[2], LOAD);
117         vlib_prefetch_buffer_header (b[3], LOAD);
118         vlib_prefetch_buffer_data (b[2], LOAD);
119         vlib_prefetch_buffer_data (b[3], LOAD);
120       }
121
122       h0 = (u8 *) vlib_buffer_get_current (b[0]);
123       h1 = (u8 *) vlib_buffer_get_current (b[1]);
124
125       if (VLIB_TX == dir)
126         {
127           h0 += vnet_buffer (b[0])->ip.save_rewrite_length;
128           h1 += vnet_buffer (b[1])->ip.save_rewrite_length;
129         }
130
131       fib_index0 =
132         urpf_cfgs[af][dir][vnet_buffer (b[0])->sw_if_index[dir]].fib_index;
133       fib_index1 =
134         urpf_cfgs[af][dir][vnet_buffer (b[1])->sw_if_index[dir]].fib_index;
135
136       if (AF_IP4 == af)
137         {
138           const ip4_header_t *ip0, *ip1;
139
140           ip0 = (ip4_header_t *) h0;
141           ip1 = (ip4_header_t *) h1;
142
143           ip4_fib_forwarding_lookup_x2 (fib_index0,
144                                         fib_index1,
145                                         &ip0->src_address,
146                                         &ip1->src_address,
147                                         &lb_index0, &lb_index1);
148           /* Pass multicast. */
149           pass0 = (ip4_address_is_multicast (&ip0->src_address) ||
150                    ip4_address_is_global_broadcast (&ip0->src_address));
151           pass1 = (ip4_address_is_multicast (&ip1->src_address) ||
152                    ip4_address_is_global_broadcast (&ip1->src_address));
153         }
154       else
155         {
156           const ip6_header_t *ip0, *ip1;
157
158           ip0 = (ip6_header_t *) h0;
159           ip1 = (ip6_header_t *) h1;
160
161           lb_index0 = ip6_fib_table_fwding_lookup (fib_index0,
162                                                    &ip0->src_address);
163           lb_index1 = ip6_fib_table_fwding_lookup (fib_index1,
164                                                    &ip1->src_address);
165           pass0 = ip6_address_is_multicast (&ip0->src_address);
166           pass1 = ip6_address_is_multicast (&ip1->src_address);
167         }
168
169       lb0 = load_balance_get (lb_index0);
170       lb1 = load_balance_get (lb_index1);
171
172       if (URPF_MODE_STRICT == mode)
173         {
174           /* for RX the check is: would this source adddress be forwarded
175            * out of the interface on which it was recieved, if yes allow.
176            * For TX it's; would this source address be forwarded out of the
177            * interface through which it is being sent, if yes drop.
178            */
179           int res0, res1;
180
181           res0 = fib_urpf_check (lb0->lb_urpf,
182                                  vnet_buffer (b[0])->sw_if_index[dir]);
183           res1 = fib_urpf_check (lb1->lb_urpf,
184                                  vnet_buffer (b[1])->sw_if_index[dir]);
185
186           if (VLIB_RX == dir)
187             {
188               pass0 |= res0;
189               pass1 |= res1;
190             }
191           else
192             {
193               pass0 |= !res0 && fib_urpf_check_size (lb0->lb_urpf);
194               pass1 |= !res1 && fib_urpf_check_size (lb1->lb_urpf);
195
196               /* allow locally generated */
197               pass0 |= b[0]->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
198               pass1 |= b[1]->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
199             }
200         }
201       else
202         {
203           pass0 |= fib_urpf_check_size (lb0->lb_urpf);
204           pass1 |= fib_urpf_check_size (lb1->lb_urpf);
205         }
206
207       if (PREDICT_TRUE (pass0))
208         vnet_feature_next_u16 (&next[0], b[0]);
209       else
210         {
211           next[0] = URPF_NEXT_DROP;
212           b[0]->error = node->errors[URPF_ERROR_DROP];
213         }
214       if (PREDICT_TRUE (pass1))
215         vnet_feature_next_u16 (&next[1], b[1]);
216       else
217         {
218           next[1] = URPF_NEXT_DROP;
219           b[1]->error = node->errors[URPF_ERROR_DROP];
220         }
221
222       if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
223         {
224           urpf_trace_t *t;
225
226           t = vlib_add_trace (vm, node, b[0], sizeof (*t));
227           t->urpf = lb0->lb_urpf;
228         }
229       if (b[1]->flags & VLIB_BUFFER_IS_TRACED)
230         {
231           urpf_trace_t *t;
232
233           t = vlib_add_trace (vm, node, b[1], sizeof (*t));
234           t->urpf = lb1->lb_urpf;
235         }
236
237       b += 2;
238       next += 2;
239       n_left -= 2;
240     }
241
242   while (n_left)
243     {
244       u32 pass0, lb_index0, fib_index0;
245       const load_balance_t *lb0;
246       const u8 *h0;
247
248       h0 = (u8 *) vlib_buffer_get_current (b[0]);
249
250       if (VLIB_TX == dir)
251         h0 += vnet_buffer (b[0])->ip.save_rewrite_length;
252
253       fib_index0 =
254         urpf_cfgs[af][dir][vnet_buffer (b[0])->sw_if_index[dir]].fib_index;
255
256       if (AF_IP4 == af)
257         {
258           const ip4_header_t *ip0;
259
260           ip0 = (ip4_header_t *) h0;
261
262           lb_index0 = ip4_fib_forwarding_lookup (fib_index0,
263                                                  &ip0->src_address);
264
265           /* Pass multicast. */
266           pass0 = (ip4_address_is_multicast (&ip0->src_address) ||
267                    ip4_address_is_global_broadcast (&ip0->src_address));
268         }
269       else
270         {
271           const ip6_header_t *ip0;
272
273           ip0 = (ip6_header_t *) h0;
274
275           lb_index0 = ip6_fib_table_fwding_lookup (fib_index0,
276                                                    &ip0->src_address);
277           pass0 = ip6_address_is_multicast (&ip0->src_address);
278         }
279
280       lb0 = load_balance_get (lb_index0);
281
282       if (URPF_MODE_STRICT == mode)
283         {
284           int res0;
285
286           res0 = fib_urpf_check (lb0->lb_urpf,
287                                  vnet_buffer (b[0])->sw_if_index[dir]);
288           if (VLIB_RX == dir)
289             pass0 |= res0;
290           else
291             {
292               pass0 |= !res0 && fib_urpf_check_size (lb0->lb_urpf);
293               pass0 |= b[0]->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
294             }
295         }
296       else
297         pass0 |= fib_urpf_check_size (lb0->lb_urpf);
298
299       if (PREDICT_TRUE (pass0))
300         vnet_feature_next_u16 (&next[0], b[0]);
301       else
302         {
303           next[0] = URPF_NEXT_DROP;
304           b[0]->error = node->errors[URPF_ERROR_DROP];
305         }
306
307       if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
308         {
309           urpf_trace_t *t;
310
311           t = vlib_add_trace (vm, node, b[0], sizeof (*t));
312           t->urpf = lb0->lb_urpf;
313         }
314       b++;
315       next++;
316       n_left--;
317     }
318
319   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
320
321   return frame->n_vectors;
322 }
323
324 #endif
325
326 /*
327  * fd.io coding-style-patch-verification: ON
328  *
329  * Local Variables:
330  * eval: (c-set-style "gnu")
331  * End:
332  */