0a576595a5a374938073e9249830c033ecbdde99
[vpp.git] / src / vnet / ipsec / ipsec_spd_policy.c
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 #include <vnet/ipsec/ipsec.h>
17
18 static int
19 ipsec_spd_entry_sort (void *a1, void *a2)
20 {
21   u32 *id1 = a1;
22   u32 *id2 = a2;
23   ipsec_spd_t *spd = ipsec_main.spd_to_sort;
24   ipsec_policy_t *p1, *p2;
25
26   p1 = pool_elt_at_index (spd->policies, *id1);
27   p2 = pool_elt_at_index (spd->policies, *id2);
28   if (p1 && p2)
29     return p2->priority - p1->priority;
30
31   return 0;
32 }
33
34 int
35 ipsec_add_del_policy (vlib_main_t * vm, ipsec_policy_t * policy, int is_add)
36 {
37   ipsec_main_t *im = &ipsec_main;
38   ipsec_spd_t *spd = 0;
39   ipsec_policy_t *vp;
40   uword *p;
41   u32 spd_index;
42
43   clib_warning ("policy-id %u priority %d is_outbound %u", policy->id,
44                 policy->priority, policy->is_outbound);
45
46   if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
47     {
48       p = hash_get (im->sa_index_by_sa_id, policy->sa_id);
49       if (!p)
50         return VNET_API_ERROR_SYSCALL_ERROR_1;
51       policy->sa_index = p[0];
52     }
53
54   p = hash_get (im->spd_index_by_spd_id, policy->id);
55
56   if (!p)
57     return VNET_API_ERROR_SYSCALL_ERROR_1;
58
59   spd_index = p[0];
60   spd = pool_elt_at_index (im->spds, spd_index);
61   if (!spd)
62     return VNET_API_ERROR_SYSCALL_ERROR_1;
63
64   if (is_add)
65     {
66       u32 policy_index;
67
68       pool_get (spd->policies, vp);
69       clib_memcpy (vp, policy, sizeof (*vp));
70       policy_index = vp - spd->policies;
71
72       ipsec_main.spd_to_sort = spd;
73
74       if (policy->is_outbound)
75         {
76           if (policy->is_ipv6)
77             {
78               vec_add1 (spd->ipv6_outbound_policies, policy_index);
79               vec_sort_with_function (spd->ipv6_outbound_policies,
80                                       ipsec_spd_entry_sort);
81             }
82           else
83             {
84               vec_add1 (spd->ipv4_outbound_policies, policy_index);
85               vec_sort_with_function (spd->ipv4_outbound_policies,
86                                       ipsec_spd_entry_sort);
87             }
88         }
89       else
90         {
91           if (policy->is_ipv6)
92             {
93               if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
94                 {
95                   vec_add1 (spd->ipv6_inbound_protect_policy_indices,
96                             policy_index);
97                   vec_sort_with_function
98                     (spd->ipv6_inbound_protect_policy_indices,
99                      ipsec_spd_entry_sort);
100                 }
101               else
102                 {
103                   vec_add1
104                     (spd->ipv6_inbound_policy_discard_and_bypass_indices,
105                      policy_index);
106                   vec_sort_with_function
107                     (spd->ipv6_inbound_policy_discard_and_bypass_indices,
108                      ipsec_spd_entry_sort);
109                 }
110             }
111           else
112             {
113               if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
114                 {
115                   vec_add1 (spd->ipv4_inbound_protect_policy_indices,
116                             policy_index);
117                   vec_sort_with_function
118                     (spd->ipv4_inbound_protect_policy_indices,
119                      ipsec_spd_entry_sort);
120                 }
121               else
122                 {
123                   vec_add1
124                     (spd->ipv4_inbound_policy_discard_and_bypass_indices,
125                      policy_index);
126                   vec_sort_with_function
127                     (spd->ipv4_inbound_policy_discard_and_bypass_indices,
128                      ipsec_spd_entry_sort);
129                 }
130             }
131         }
132
133       ipsec_main.spd_to_sort = NULL;
134     }
135   else
136     {
137       u32 i, j;
138       /* *INDENT-OFF* */
139       pool_foreach_index(i, spd->policies, ({
140         vp = pool_elt_at_index(spd->policies, i);
141         if (vp->priority != policy->priority)
142           continue;
143         if (vp->is_outbound != policy->is_outbound)
144           continue;
145         if (vp->policy != policy->policy)
146           continue;
147         if (vp->sa_id != policy->sa_id)
148           continue;
149         if (vp->protocol != policy->protocol)
150           continue;
151         if (vp->lport.start != policy->lport.start)
152           continue;
153         if (vp->lport.stop != policy->lport.stop)
154           continue;
155         if (vp->rport.start != policy->rport.start)
156           continue;
157         if (vp->rport.stop != policy->rport.stop)
158           continue;
159         if (vp->is_ipv6 != policy->is_ipv6)
160           continue;
161         if (policy->is_ipv6)
162           {
163             if (vp->laddr.start.ip6.as_u64[0] != policy->laddr.start.ip6.as_u64[0])
164               continue;
165             if (vp->laddr.start.ip6.as_u64[1] != policy->laddr.start.ip6.as_u64[1])
166               continue;
167             if (vp->laddr.stop.ip6.as_u64[0] != policy->laddr.stop.ip6.as_u64[0])
168               continue;
169             if (vp->laddr.stop.ip6.as_u64[1] != policy->laddr.stop.ip6.as_u64[1])
170               continue;
171             if (vp->raddr.start.ip6.as_u64[0] != policy->raddr.start.ip6.as_u64[0])
172               continue;
173             if (vp->raddr.start.ip6.as_u64[1] != policy->raddr.start.ip6.as_u64[1])
174               continue;
175             if (vp->raddr.stop.ip6.as_u64[0] != policy->raddr.stop.ip6.as_u64[0])
176               continue;
177            if (vp->laddr.stop.ip6.as_u64[1] != policy->laddr.stop.ip6.as_u64[1])
178               continue;
179            if (policy->is_outbound)
180              {
181                vec_foreach_index(j, spd->ipv6_outbound_policies) {
182                  if (vec_elt(spd->ipv6_outbound_policies, j) == i) {
183                    vec_del1 (spd->ipv6_outbound_policies, j);
184                    break;
185                  }
186                }
187              }
188            else
189              {
190                if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
191                  {
192                    vec_foreach_index(j, spd->ipv6_inbound_protect_policy_indices) {
193                      if (vec_elt(spd->ipv6_inbound_protect_policy_indices, j) == i) {
194                        vec_del1 (spd->ipv6_inbound_protect_policy_indices, j);
195                        break;
196                      }
197                    }
198                  }
199                else
200                  {
201                    vec_foreach_index(j, spd->ipv6_inbound_policy_discard_and_bypass_indices) {
202                      if (vec_elt(spd->ipv6_inbound_policy_discard_and_bypass_indices, j) == i) {
203                        vec_del1 (spd->ipv6_inbound_policy_discard_and_bypass_indices, j);
204                        break;
205                      }
206                    }
207                  }
208              }
209           }
210         else
211           {
212             if (vp->laddr.start.ip4.as_u32 != policy->laddr.start.ip4.as_u32)
213               continue;
214             if (vp->laddr.stop.ip4.as_u32 != policy->laddr.stop.ip4.as_u32)
215               continue;
216             if (vp->raddr.start.ip4.as_u32 != policy->raddr.start.ip4.as_u32)
217               continue;
218             if (vp->raddr.stop.ip4.as_u32 != policy->raddr.stop.ip4.as_u32)
219               continue;
220             if (policy->is_outbound)
221               {
222                 vec_foreach_index(j, spd->ipv4_outbound_policies) {
223                   if (vec_elt(spd->ipv4_outbound_policies, j) == i) {
224                     vec_del1 (spd->ipv4_outbound_policies, j);
225                     break;
226                   }
227                 }
228               }
229             else
230               {
231                 if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
232                   {
233                     vec_foreach_index(j, spd->ipv4_inbound_protect_policy_indices) {
234                       if (vec_elt(spd->ipv4_inbound_protect_policy_indices, j) == i) {
235                         vec_del1 (spd->ipv4_inbound_protect_policy_indices, j);
236                         break;
237                       }
238                     }
239                   }
240                 else
241                   {
242                     vec_foreach_index(j, spd->ipv4_inbound_policy_discard_and_bypass_indices) {
243                       if (vec_elt(spd->ipv4_inbound_policy_discard_and_bypass_indices, j) == i) {
244                         vec_del1 (spd->ipv4_inbound_policy_discard_and_bypass_indices, j);
245                         break;
246                       }
247                     }
248                   }
249               }
250           }
251           pool_put (spd->policies, vp);
252           break;
253       }));
254       /* *INDENT-ON* */
255     }
256
257   return 0;
258 }
259
260 /*
261  * fd.io coding-style-patch-verification: ON
262  *
263  * Local Variables:
264  * eval: (c-set-style "gnu")
265  * End:
266  */