interface: fix check in set_interface_name api
[vpp.git] / src / plugins / acl / acl_test.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  *------------------------------------------------------------------
17  * acl_test.c - test harness plugin
18  *------------------------------------------------------------------
19  */
20
21 #include <byteswap.h>
22
23 #include <vat/vat.h>
24 #include <vlibapi/api.h>
25 #include <vlibmemory/api.h>
26 #include <vppinfra/error.h>
27 #include <vnet/ip/ip.h>
28 #include <arpa/inet.h>
29
30 #include <vnet/ip/ip_format_fns.h>
31 #include <vnet/ethernet/ethernet_format_fns.h>
32
33 #define __plugin_msg_base acl_test_main.msg_id_base
34 #include <vlibapi/vat_helper_macros.h>
35
36 uword unformat_sw_if_index (unformat_input_t * input, va_list * args);
37
38 /* Declare message IDs */
39 #include <acl/acl.api_enum.h>
40 #include <acl/acl.api_types.h>
41 #define vl_endianfun            /* define message structures */
42 #include <acl/acl.api.h>
43 #undef vl_endianfun
44
45 typedef struct {
46     /* API message ID base */
47     u16 msg_id_base;
48     vat_main_t *vat_main;
49 } acl_test_main_t;
50
51 acl_test_main_t acl_test_main;
52
53 #define foreach_reply_retval_aclindex_handler  \
54 _(acl_add_replace_reply) \
55 _(macip_acl_add_reply) \
56 _(macip_acl_add_replace_reply)
57
58 #define _(n)                                            \
59     static void vl_api_##n##_t_handler                  \
60     (vl_api_##n##_t * mp)                               \
61     {                                                   \
62         vat_main_t * vam = acl_test_main.vat_main;   \
63         i32 retval = ntohl(mp->retval);                 \
64         if (vam->async_mode) {                          \
65             vam->async_errors += (retval < 0);          \
66         } else {                                        \
67             clib_warning("ACL index: %d", ntohl(mp->acl_index)); \
68             vam->retval = retval;                       \
69             vam->result_ready = 1;                      \
70         }                                               \
71     }
72 foreach_reply_retval_aclindex_handler;
73 #undef _
74
75 /* These two ought to be in a library somewhere but they aren't */
76 static uword
77 my_unformat_mac_address (unformat_input_t * input, va_list * args)
78 {
79   u8 *a = va_arg (*args, u8 *);
80   return unformat (input, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3],
81                    &a[4], &a[5]);
82 }
83
84 static u8 *
85 my_format_mac_address (u8 * s, va_list * args)
86 {
87   u8 *a = va_arg (*args, u8 *);
88   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
89                  a[0], a[1], a[2], a[3], a[4], a[5]);
90 }
91
92
93
94 static void vl_api_acl_plugin_get_version_reply_t_handler
95     (vl_api_acl_plugin_get_version_reply_t * mp)
96     {
97         vat_main_t * vam = acl_test_main.vat_main;
98         clib_warning("ACL plugin version: %d.%d", ntohl(mp->major), ntohl(mp->minor));
99         vam->result_ready = 1;
100     }
101
102     static void
103     vl_api_acl_plugin_use_hash_lookup_get_reply_t_handler (
104       vl_api_acl_plugin_use_hash_lookup_get_reply_t *mp)
105     {
106       vat_main_t *vam = acl_test_main.vat_main;
107       clib_warning ("ACL hash lookups enabled: %d", mp->enable);
108       vam->result_ready = 1;
109     }
110
111 static void vl_api_acl_interface_list_details_t_handler
112     (vl_api_acl_interface_list_details_t * mp)
113     {
114         int i;
115         vat_main_t * vam = acl_test_main.vat_main;
116         u8 *out = 0;
117         vl_api_acl_interface_list_details_t_endian(mp);
118         out = format(out, "sw_if_index: %d, count: %d, n_input: %d\n", mp->sw_if_index, mp->count, mp->n_input);
119         out = format(out, "   input ");
120         for(i=0; i<mp->count; i++) {
121           if (i == mp->n_input)
122             out = format(out, "\n  output ");
123           out = format(out, "%d ", ntohl (mp->acls[i]));
124         }
125         out = format(out, "\n");
126         clib_warning("%s", out);
127         vec_free(out);
128         vam->result_ready = 1;
129     }
130
131 static void vl_api_macip_acl_interface_list_details_t_handler
132 (vl_api_macip_acl_interface_list_details_t * mp)
133 {
134   // NOT YET IMPLEMENTED
135 }
136
137
138 static void vl_api_acl_interface_etype_whitelist_details_t_handler
139     (vl_api_acl_interface_etype_whitelist_details_t * mp)
140     {
141         int i;
142         vat_main_t * vam = acl_test_main.vat_main;
143         u8 *out = 0;
144         vl_api_acl_interface_etype_whitelist_details_t_endian(mp);
145         out = format(out, "sw_if_index: %d, count: %d, n_input: %d\n", mp->sw_if_index, mp->count, mp->n_input);
146         out = format(out, "   input ");
147         for(i=0; i<mp->count; i++) {
148           if (i == mp->n_input)
149             out = format(out, "\n  output ");
150           out = format(out, "%04x ", ntohs(mp->whitelist[i]));
151         }
152         out = format(out, "\n");
153         clib_warning("%s", out);
154         vec_free(out);
155         vam->result_ready = 1;
156     }
157
158 static void vl_api_acl_plugin_get_conn_table_max_entries_reply_t_handler
159     (vl_api_acl_plugin_get_conn_table_max_entries_reply_t * mp)
160     {
161         vat_main_t * vam = acl_test_main.vat_main;
162         clib_warning ("\nConn table max entries: %d",
163                       clib_net_to_host_u64 (mp->conn_table_max_entries));
164         vam->result_ready = 1;
165     }
166
167 static inline u8 *
168 vl_api_acl_rule_t_pretty_format (u8 *out, vl_api_acl_rule_t * a)
169 {
170   int af = a->src_prefix.address.af ? AF_INET6 : AF_INET;
171   u8 src[INET6_ADDRSTRLEN];
172   u8 dst[INET6_ADDRSTRLEN];
173   inet_ntop(af, &a->src_prefix.address.un, (void *)src, sizeof(src));
174   inet_ntop(af, &a->dst_prefix.address.un, (void *)dst, sizeof(dst));
175
176   out = format(out, "%s action %d src %s/%d dst %s/%d proto %d sport %d-%d dport %d-%d tcpflags %d mask %d",
177                      a->src_prefix.address.af ? "ipv6" : "ipv4", a->is_permit,
178                      src, a->src_prefix.len,
179                      dst, a->dst_prefix.len,
180                      a->proto,
181                      a->srcport_or_icmptype_first, a->srcport_or_icmptype_last,
182                      a->dstport_or_icmpcode_first, a->dstport_or_icmpcode_last,
183                      a->tcp_flags_value, a->tcp_flags_mask);
184   return(out);
185 }
186
187
188
189 static void vl_api_acl_details_t_handler
190     (vl_api_acl_details_t * mp)
191     {
192         int i;
193         vat_main_t * vam = acl_test_main.vat_main;
194         vl_api_acl_details_t_endian(mp);
195         u8 *out = 0;
196         out = format(0, "acl_index: %d, count: %d\n   tag {%s}\n", mp->acl_index, mp->count, mp->tag);
197         for(i=0; i<mp->count; i++) {
198           out = format(out, "   ");
199           out = vl_api_acl_rule_t_pretty_format(out, &mp->r[i]);
200           out = format(out, "%s\n", i<mp->count-1 ? "," : "");
201         }
202         clib_warning("%s", out);
203         vec_free(out);
204         vam->result_ready = 1;
205     }
206
207 static inline u8 *
208 vl_api_macip_acl_rule_t_pretty_format (u8 *out, vl_api_macip_acl_rule_t * a)
209 {
210   int af = a->src_prefix.address.af ? AF_INET6 : AF_INET;
211   u8 src[INET6_ADDRSTRLEN];
212   inet_ntop(af, &a->src_prefix.address.un, (void *)src, sizeof(src));
213
214   out = format(out, "%s action %d ip %s/%d mac %U mask %U",
215                      a->src_prefix.address.af ? "ipv6" : "ipv4", a->is_permit,
216                      src, a->src_prefix.len,
217                      my_format_mac_address, a->src_mac,
218                      my_format_mac_address, a->src_mac_mask);
219   return(out);
220 }
221
222
223 static void vl_api_macip_acl_details_t_handler
224     (vl_api_macip_acl_details_t * mp)
225     {
226         int i;
227         vat_main_t * vam = acl_test_main.vat_main;
228         vl_api_macip_acl_details_t_endian(mp);
229         u8 *out = format(0,"MACIP acl_index: %d, count: %d\n   tag {%s}\n", mp->acl_index, mp->count, mp->tag);
230         for(i=0; i<mp->count; i++) {
231           out = format(out, "   ");
232           out = vl_api_macip_acl_rule_t_pretty_format(out, &mp->r[i]);
233           out = format(out, "%s\n", i<mp->count-1 ? "," : "");
234         }
235         clib_warning("%s", out);
236         vec_free(out);
237         vam->result_ready = 1;
238     }
239
240 static void vl_api_macip_acl_interface_get_reply_t_handler
241     (vl_api_macip_acl_interface_get_reply_t * mp)
242     {
243         int i;
244         vat_main_t * vam = acl_test_main.vat_main;
245         u8 *out = format(0, "sw_if_index with MACIP ACL count: %d\n", ntohl(mp->count));
246         for(i=0; i<ntohl(mp->count); i++) {
247           out = format(out, "  macip_acl_interface_add_del sw_if_index %d add acl %d\n", i, ntohl(mp->acls[i]));
248         }
249         out = format(out, "\n");
250         clib_warning("%s", out);
251         vec_free(out);
252         vam->result_ready = 1;
253     }
254
255 static void vl_api_acl_plugin_control_ping_reply_t_handler
256   (vl_api_acl_plugin_control_ping_reply_t * mp)
257 {
258   vat_main_t *vam = &vat_main;
259   i32 retval = ntohl (mp->retval);
260   if (vam->async_mode)
261     {
262       vam->async_errors += (retval < 0);
263     }
264   else
265     {
266       vam->retval = retval;
267       vam->result_ready = 1;
268     }
269 }
270
271 static int api_acl_plugin_get_version (vat_main_t * vam)
272 {
273     acl_test_main_t * sm = &acl_test_main;
274     vl_api_acl_plugin_get_version_t * mp;
275     u32 msg_size = sizeof(*mp);
276     int ret;
277
278     vam->result_ready = 0;
279     mp = vl_msg_api_alloc_as_if_client(msg_size);
280     clib_memset (mp, 0, msg_size);
281     mp->_vl_msg_id = ntohs (VL_API_ACL_PLUGIN_GET_VERSION + sm->msg_id_base);
282     mp->client_index = vam->my_client_index;
283
284     /* send it... */
285     S(mp);
286
287     /* Wait for a reply... */
288     W (ret);
289     return ret;
290 }
291
292 static int api_macip_acl_interface_get (vat_main_t * vam)
293 {
294     acl_test_main_t * sm = &acl_test_main;
295     vl_api_acl_plugin_get_version_t * mp;
296     u32 msg_size = sizeof(*mp);
297     int ret;
298
299     vam->result_ready = 0;
300     mp = vl_msg_api_alloc_as_if_client(msg_size);
301     clib_memset (mp, 0, msg_size);
302     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_INTERFACE_GET + sm->msg_id_base);
303     mp->client_index = vam->my_client_index;
304
305     /* send it... */
306     S(mp);
307
308     /* Wait for a reply... */
309     W (ret);
310     return ret;
311 }
312
313 #define vec_validate_acl_rules(v, idx) \
314   do {                                 \
315     if (vec_len(v) < idx+1) {  \
316       vec_validate(v, idx); \
317       v[idx].is_permit = 0x1; \
318       v[idx].srcport_or_icmptype_last = 0xffff; \
319       v[idx].dstport_or_icmpcode_last = 0xffff; \
320     } \
321   } while (0)
322
323
324 /* NOT YET IMPLEMENTED */
325 static int api_acl_plugin_control_ping (vat_main_t * vam)
326 {
327   return 0;
328 }
329 static int api_macip_acl_interface_list_dump (vat_main_t * vam)
330 {
331   return 0;
332 }
333
334 static int api_acl_add_replace (vat_main_t * vam)
335 {
336     acl_test_main_t * sm = &acl_test_main;
337     unformat_input_t * i = vam->input;
338     vl_api_acl_add_replace_t * mp;
339     u32 acl_index = ~0;
340     u32 msg_size = sizeof (*mp); /* without the rules */
341
342     vl_api_acl_rule_t *rules = 0;
343     int rule_idx = 0;
344     int n_rules = 0;
345     int n_rules_override = -1;
346     u32 proto = 0;
347     u32 port1 = 0;
348     u32 port2 = 0;
349     u32 action = 0;
350     u32 tcpflags, tcpmask;
351     u32 src_prefix_length = 0, dst_prefix_length = 0;
352     ip4_address_t src_v4address, dst_v4address;
353     ip6_address_t src_v6address, dst_v6address;
354     u8 *tag = 0;
355     int ret;
356
357     if (!unformat (i, "%d", &acl_index)) {
358         /* Just assume -1 */
359     }
360
361     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
362     {
363         if (unformat (i, "permit+reflect"))
364           {
365             vec_validate_acl_rules(rules, rule_idx);
366             rules[rule_idx].is_permit = 2;
367           }
368         else if (unformat (i, "permit"))
369           {
370             vec_validate_acl_rules(rules, rule_idx);
371             rules[rule_idx].is_permit = 1;
372           }
373         else if (unformat (i, "deny"))
374           {
375             vec_validate_acl_rules(rules, rule_idx);
376             rules[rule_idx].is_permit = 0;
377           }
378         else if (unformat (i, "count %d", &n_rules_override))
379           {
380             /* we will use this later */
381           }
382         else if (unformat (i, "action %d", &action))
383           {
384             vec_validate_acl_rules(rules, rule_idx);
385             rules[rule_idx].is_permit = action;
386           }
387         else if (unformat (i, "src %U/%d",
388          unformat_ip4_address, &src_v4address, &src_prefix_length))
389           {
390             vec_validate_acl_rules(rules, rule_idx);
391             memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v4address, 4);
392             rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
393             rules[rule_idx].src_prefix.len = src_prefix_length;
394           }
395         else if (unformat (i, "src %U/%d",
396          unformat_ip6_address, &src_v6address, &src_prefix_length))
397           {
398             vec_validate_acl_rules(rules, rule_idx);
399             memcpy (rules[rule_idx].src_prefix.address.un.ip6, &src_v6address, 16);
400             rules[rule_idx].src_prefix.address.af = ADDRESS_IP6;
401             rules[rule_idx].src_prefix.len = src_prefix_length;
402           }
403         else if (unformat (i, "dst %U/%d",
404          unformat_ip4_address, &dst_v4address, &dst_prefix_length))
405           {
406             vec_validate_acl_rules(rules, rule_idx);
407             memcpy (rules[rule_idx].dst_prefix.address.un.ip4, &dst_v4address, 4);
408             rules[rule_idx].dst_prefix.address.af = ADDRESS_IP4;
409             rules[rule_idx].dst_prefix.len = dst_prefix_length;
410           }
411         else if (unformat (i, "dst %U/%d",
412          unformat_ip6_address, &dst_v6address, &dst_prefix_length))
413           {
414             vec_validate_acl_rules(rules, rule_idx);
415             memcpy (rules[rule_idx].dst_prefix.address.un.ip6, &dst_v6address, 16);
416             rules[rule_idx].dst_prefix.address.af = ADDRESS_IP6;
417             rules[rule_idx].dst_prefix.len = dst_prefix_length;
418           }
419         else if (unformat (i, "sport %d-%d", &port1, &port2))
420           {
421             vec_validate_acl_rules(rules, rule_idx);
422             rules[rule_idx].srcport_or_icmptype_first = htons(port1);
423             rules[rule_idx].srcport_or_icmptype_last = htons(port2);
424           }
425         else if (unformat (i, "sport %d", &port1))
426           {
427             vec_validate_acl_rules(rules, rule_idx);
428             rules[rule_idx].srcport_or_icmptype_first = htons(port1);
429             rules[rule_idx].srcport_or_icmptype_last = htons(port1);
430           }
431         else if (unformat (i, "dport %d-%d", &port1, &port2))
432           {
433             vec_validate_acl_rules(rules, rule_idx);
434             rules[rule_idx].dstport_or_icmpcode_first = htons(port1);
435             rules[rule_idx].dstport_or_icmpcode_last = htons(port2);
436           }
437         else if (unformat (i, "dport %d", &port1))
438           {
439             vec_validate_acl_rules(rules, rule_idx);
440             rules[rule_idx].dstport_or_icmpcode_first = htons(port1);
441             rules[rule_idx].dstport_or_icmpcode_last = htons(port1);
442           }
443         else if (unformat (i, "tcpflags %d %d", &tcpflags, &tcpmask))
444           {
445             vec_validate_acl_rules(rules, rule_idx);
446             rules[rule_idx].tcp_flags_value = tcpflags;
447             rules[rule_idx].tcp_flags_mask = tcpmask;
448           }
449         else if (unformat (i, "tcpflags %d mask %d", &tcpflags, &tcpmask))
450           {
451             vec_validate_acl_rules(rules, rule_idx);
452             rules[rule_idx].tcp_flags_value = tcpflags;
453             rules[rule_idx].tcp_flags_mask = tcpmask;
454           }
455         else if (unformat (i, "proto %d", &proto))
456           {
457             vec_validate_acl_rules(rules, rule_idx);
458             rules[rule_idx].proto = proto;
459           }
460         else if (unformat (i, "tag %s", &tag))
461           {
462           }
463         else if (unformat (i, ","))
464           {
465             rule_idx++;
466             vec_validate_acl_rules(rules, rule_idx);
467           }
468         else
469     break;
470     }
471
472     /* Construct the API message */
473     vam->result_ready = 0;
474
475     if(rules)
476       n_rules = vec_len(rules);
477     else
478       n_rules = 0;
479
480     if (n_rules_override >= 0)
481       n_rules = n_rules_override;
482
483     msg_size += n_rules*sizeof(rules[0]);
484
485     mp = vl_msg_api_alloc_as_if_client(msg_size);
486     clib_memset (mp, 0, msg_size);
487     mp->_vl_msg_id = ntohs (VL_API_ACL_ADD_REPLACE + sm->msg_id_base);
488     mp->client_index = vam->my_client_index;
489     if ((n_rules > 0) && rules)
490       clib_memcpy(mp->r, rules, n_rules*sizeof (vl_api_acl_rule_t));
491     if (tag)
492       {
493         if (vec_len(tag) >= sizeof(mp->tag))
494           {
495             tag[sizeof(mp->tag)-1] = 0;
496             vec_set_len (tag, sizeof (mp->tag));
497           }
498         clib_memcpy (mp->tag, tag, vec_len (tag));
499         vec_free (tag);
500       }
501     mp->acl_index = ntohl(acl_index);
502     mp->count = htonl(n_rules);
503
504     /* send it... */
505     S(mp);
506
507     /* Wait for a reply... */
508     W (ret);
509     return ret;
510 }
511
512 static int api_acl_plugin_get_conn_table_max_entries (vat_main_t * vam)
513 {
514     acl_test_main_t * sm = &acl_test_main;
515     vl_api_acl_plugin_get_conn_table_max_entries_t * mp;
516     u32 msg_size = sizeof(*mp);
517     int ret;
518
519     vam->result_ready = 0;
520     mp = vl_msg_api_alloc_as_if_client(msg_size);
521     memset (mp, 0, msg_size);
522     mp->_vl_msg_id = ntohs (VL_API_ACL_PLUGIN_GET_CONN_TABLE_MAX_ENTRIES + sm->msg_id_base);
523     mp->client_index = vam->my_client_index;
524
525     /* send it... */
526     S(mp);
527
528     /* Wait for a reply... */
529     W (ret);
530     return ret;
531 }
532
533 static int api_acl_stats_intf_counters_enable (vat_main_t * vam)
534 {
535     acl_test_main_t * sm = &acl_test_main;
536     unformat_input_t * i = vam->input;
537     vl_api_acl_stats_intf_counters_enable_t * mp;
538     u32 msg_size = sizeof(*mp);
539     int ret;
540
541     vam->result_ready = 0;
542     mp = vl_msg_api_alloc_as_if_client(msg_size);
543     memset (mp, 0, msg_size);
544     mp->_vl_msg_id = ntohs (VL_API_ACL_STATS_INTF_COUNTERS_ENABLE + sm->msg_id_base);
545     mp->client_index = vam->my_client_index;
546     mp->enable = 1;
547
548     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
549         if (unformat (i, "disable"))
550             mp->enable = 0;
551         else
552             break;
553     }
554
555     /* send it... */
556     S(mp);
557
558     /* Wait for a reply... */
559     W (ret);
560     return ret;
561 }
562
563 static int
564 api_acl_plugin_use_hash_lookup_set (vat_main_t *vam)
565 {
566   acl_test_main_t *sm = &acl_test_main;
567   unformat_input_t *i = vam->input;
568   vl_api_acl_plugin_use_hash_lookup_set_t *mp;
569   u32 msg_size = sizeof (*mp);
570   int ret;
571
572   vam->result_ready = 0;
573   mp = vl_msg_api_alloc_as_if_client (msg_size);
574   memset (mp, 0, msg_size);
575   mp->_vl_msg_id =
576     ntohs (VL_API_ACL_PLUGIN_USE_HASH_LOOKUP_SET + sm->msg_id_base);
577   mp->client_index = vam->my_client_index;
578   mp->enable = 1;
579
580   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
581     {
582       if (unformat (i, "disable"))
583         mp->enable = 0;
584       else if (unformat (i, "enable"))
585         mp->enable = 1;
586       else
587         break;
588     }
589
590   /* send it... */
591   S (mp);
592
593   /* Wait for a reply... */
594   W (ret);
595   return ret;
596 }
597
598 static int
599 api_acl_plugin_use_hash_lookup_get (vat_main_t *vam)
600 {
601   acl_test_main_t *sm = &acl_test_main;
602   vl_api_acl_plugin_use_hash_lookup_set_t *mp;
603   u32 msg_size = sizeof (*mp);
604   int ret;
605
606   vam->result_ready = 0;
607   mp = vl_msg_api_alloc_as_if_client (msg_size);
608   memset (mp, 0, msg_size);
609   mp->_vl_msg_id =
610     ntohs (VL_API_ACL_PLUGIN_USE_HASH_LOOKUP_GET + sm->msg_id_base);
611   mp->client_index = vam->my_client_index;
612
613   /* send it... */
614   S (mp);
615
616   /* Wait for a reply... */
617   W (ret);
618   return ret;
619 }
620
621 /*
622  * Read the series of ACL entries from file in the following format:
623  *
624
625 @0.0.0.0/1      131.179.121.0/24        0 : 65535       0 : 65535       0x00/0x00       0x0000/0x0000
626 @128.0.0.0/1    85.54.226.0/23  0 : 65535       0 : 65535       0x00/0x00       0x0000/0x0000
627 @128.0.0.0/1    85.54.48.0/23   0 : 65535       0 : 65535       0x00/0x00       0x0000/0x0000
628 @128.0.0.0/1    31.237.44.0/23  0 : 65535       0 : 65535       0x00/0x00       0x0000/0x0000
629 @0.0.0.0/1      255.84.184.0/23 0 : 65535       0 : 65535       0x00/0x00       0x0000/0x0000
630 @132.92.0.0/16  0.0.0.0/0       0 : 65535       0 : 65535       0x01/0xFF       0x0000/0x0000
631
632  *
633  */
634
635 static int
636 api_acl_add_replace_from_file (vat_main_t * vam)
637 {
638     int ret = -1;
639     unformat_input_t * input = vam->input;
640     acl_test_main_t * sm = &acl_test_main;
641     vl_api_acl_add_replace_t * mp;
642     u32 acl_index = ~0;
643     u32 msg_size = sizeof (*mp); /* without the rules */
644
645     vl_api_acl_rule_t *rules = 0;
646     int rule_idx = -1;
647     int n_rules = 0;
648     int is_permit = 0;
649     int append_default_permit = 0;
650     u32 tcpflags = 0, tcpmask = 0;
651     ip4_address_t src_v4address, dst_v4address;
652     int fd = -1;
653
654     char *file_name = NULL;
655     unformat_input_t file_input;
656
657     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
658       {
659         if (unformat (input, "filename %s", &file_name))
660           {
661             /* we will use this later */
662           }
663         else if (unformat (input, "acl-index %d", &acl_index))
664           {
665             /* we will try to replace an existing ACL */
666           }
667         else if (unformat (input, "permit+reflect"))
668           {
669             is_permit = 2;
670           }
671         else if (unformat (input, "permit"))
672           {
673             is_permit = 1;
674           }
675         else if (unformat (input, "append-default-permit"))
676           {
677             append_default_permit = 1;
678           }
679         else
680           break;
681       }
682
683     if (file_name == NULL)
684         goto done;
685
686     fd = open(file_name, O_RDONLY);
687     if (fd < 0)
688       {
689         clib_warning("Could not open file '%s'", file_name);
690         goto done;
691       }
692
693     /* input from file */
694     input =  &file_input;
695     unformat_init_clib_file(input, fd);
696
697     unsigned sport_low, sport_high, dport_low, dport_high;
698     unsigned proto, protomask;
699     u32 src_prefix_length, dst_prefix_length;
700     u32 unused1, unused2;
701
702     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
703       {
704             if (!unformat(input, "@%U/%d\t%U/%d\t%d : %d\t%d : %d\t0x%x/0x%x\t0x%x/0x%x",
705                                  unformat_ip4_address, &src_v4address, &src_prefix_length,
706                                  unformat_ip4_address, &dst_v4address, &dst_prefix_length,
707                                  &sport_low, &sport_high, &dport_low, &dport_high, &proto, &protomask, &unused1, &unused2)) {
708               clib_warning("Error parsing");
709               break;
710             }
711
712             rule_idx++;
713             vec_validate_acl_rules(rules, rule_idx);
714
715             rules[rule_idx].is_permit = is_permit;
716             memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v4address, 4);
717             rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
718             rules[rule_idx].src_prefix.len = src_prefix_length;
719             memcpy (rules[rule_idx].dst_prefix.address.un.ip4, &dst_v4address, 4);
720             rules[rule_idx].dst_prefix.address.af = ADDRESS_IP4;
721             rules[rule_idx].dst_prefix.len = dst_prefix_length;
722             rules[rule_idx].srcport_or_icmptype_first = htons(sport_low);
723             rules[rule_idx].srcport_or_icmptype_last = htons(sport_high);
724             rules[rule_idx].dstport_or_icmpcode_first = htons(dport_low);
725             rules[rule_idx].dstport_or_icmpcode_last = htons(dport_high);
726             rules[rule_idx].tcp_flags_value = tcpflags;
727             rules[rule_idx].tcp_flags_mask = tcpmask;
728             rules[rule_idx].proto = proto;
729
730       }
731
732     if (append_default_permit) {
733         rule_idx++;
734         vec_validate_acl_rules(rules, rule_idx);
735
736         rules[rule_idx].is_permit = is_permit == 2 ? 2 : 1;
737
738         src_v4address.data[0]=0;
739         src_v4address.data[1]=0;
740         src_v4address.data[2]=0;
741         src_v4address.data[3]=0;
742         memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v4address, 4);
743         rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
744         rules[rule_idx].src_prefix.len = 0;
745
746         dst_v4address.data[0]=0;
747         dst_v4address.data[1]=0;
748         dst_v4address.data[2]=0;
749         dst_v4address.data[3]=0;
750         memcpy (rules[rule_idx].dst_prefix.address.un.ip4, &dst_v4address, 4);
751         rules[rule_idx].dst_prefix.address.af = ADDRESS_IP4;
752         rules[rule_idx].dst_prefix.len = 0;
753
754         rules[rule_idx].srcport_or_icmptype_first = htons(0);
755         rules[rule_idx].srcport_or_icmptype_last = htons(65535);
756         rules[rule_idx].dstport_or_icmpcode_first = htons(0);
757         rules[rule_idx].dstport_or_icmpcode_last = htons(65535);
758         rules[rule_idx].tcp_flags_value = 0;
759         rules[rule_idx].tcp_flags_mask = 0;
760         rules[rule_idx].proto = 0;
761     }
762
763     /* Construct the API message */
764
765     vam->result_ready = 0;
766
767     n_rules = vec_len(rules);
768
769     msg_size += n_rules*sizeof(rules[0]);
770
771     mp = vl_msg_api_alloc_as_if_client(msg_size);
772     clib_memset (mp, 0, msg_size);
773     mp->_vl_msg_id = ntohs (VL_API_ACL_ADD_REPLACE + sm->msg_id_base);
774     mp->client_index = vam->my_client_index;
775     if (n_rules > 0)
776       clib_memcpy(mp->r, rules, n_rules*sizeof (vl_api_acl_rule_t));
777     mp->acl_index = ntohl(acl_index);
778     mp->count = htonl(n_rules);
779
780     /* send it... */
781     S(mp);
782
783     /* Wait for a reply... */
784     W (ret);
785 done:
786     if (fd > 0)
787       close (fd);
788     vec_free(file_name);
789
790     return ret;
791 }
792
793
794 static int api_acl_del (vat_main_t * vam)
795 {
796     unformat_input_t * i = vam->input;
797     vl_api_acl_del_t * mp;
798     u32 acl_index = ~0;
799     int ret;
800
801     if (!unformat (i, "%d", &acl_index)) {
802       errmsg ("missing acl index\n");
803       return -99;
804     }
805
806     /* Construct the API message */
807     M(ACL_DEL, mp);
808     mp->acl_index = ntohl(acl_index);
809
810     /* send it... */
811     S(mp);
812
813     /* Wait for a reply... */
814     W (ret);
815     return ret;
816 }
817
818 static int api_macip_acl_del (vat_main_t * vam)
819 {
820     unformat_input_t * i = vam->input;
821     vl_api_acl_del_t * mp;
822     u32 acl_index = ~0;
823     int ret;
824
825     if (!unformat (i, "%d", &acl_index)) {
826       errmsg ("missing acl index\n");
827       return -99;
828     }
829
830     /* Construct the API message */
831     M(MACIP_ACL_DEL, mp);
832     mp->acl_index = ntohl(acl_index);
833
834     /* send it... */
835     S(mp);
836
837     /* Wait for a reply... */
838     W (ret);
839     return ret;
840 }
841
842 static int api_acl_interface_add_del (vat_main_t * vam)
843 {
844     unformat_input_t * i = vam->input;
845     vl_api_acl_interface_add_del_t * mp;
846     u32 sw_if_index = ~0;
847     u32 acl_index = ~0;
848     u8 is_input = 0;
849     u8 is_add = 0;
850     int ret;
851
852 //    acl_interface_add_del <intfc> | sw_if_index <if-idx> acl_index <acl-idx> [out] [del]
853
854     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
855     {
856         if (unformat (i, "%d", &acl_index))
857     ;
858         else
859     break;
860     }
861
862
863     /* Parse args required to build the message */
864     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
865         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
866             ;
867         else if (unformat (i, "sw_if_index %d", &sw_if_index))
868             ;
869         else if (unformat (i, "add"))
870             is_add = 1;
871         else if (unformat (i, "del"))
872             is_add = 0;
873         else if (unformat (i, "acl %d", &acl_index))
874             ;
875         else if (unformat (i, "input"))
876             is_input = 1;
877         else if (unformat (i, "output"))
878             is_input = 0;
879         else
880             break;
881     }
882
883     if (sw_if_index == ~0) {
884         errmsg ("missing interface name / explicit sw_if_index number \n");
885         return -99;
886     }
887
888     if (acl_index == ~0) {
889         errmsg ("missing ACL index\n");
890         return -99;
891     }
892
893
894
895     /* Construct the API message */
896     M(ACL_INTERFACE_ADD_DEL, mp);
897     mp->acl_index = ntohl(acl_index);
898     mp->sw_if_index = ntohl(sw_if_index);
899     mp->is_add = is_add;
900     mp->is_input = is_input;
901
902     /* send it... */
903     S(mp);
904
905     /* Wait for a reply... */
906     W (ret);
907     return ret;
908 }
909
910 static int api_macip_acl_interface_add_del (vat_main_t * vam)
911 {
912     unformat_input_t * i = vam->input;
913     vl_api_macip_acl_interface_add_del_t * mp;
914     u32 sw_if_index = ~0;
915     u32 acl_index = ~0;
916     u8 is_add = 0;
917     int ret;
918
919     /* Parse args required to build the message */
920     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
921         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
922             ;
923         else if (unformat (i, "sw_if_index %d", &sw_if_index))
924             ;
925         else if (unformat (i, "add"))
926             is_add = 1;
927         else if (unformat (i, "del"))
928             is_add = 0;
929         else if (unformat (i, "acl %d", &acl_index))
930             ;
931         else
932             break;
933     }
934
935     if (sw_if_index == ~0) {
936         errmsg ("missing interface name / explicit sw_if_index number \n");
937         return -99;
938     }
939
940     if (acl_index == ~0) {
941         errmsg ("missing ACL index\n");
942         return -99;
943     }
944
945
946
947     /* Construct the API message */
948     M(MACIP_ACL_INTERFACE_ADD_DEL, mp);
949     mp->acl_index = ntohl(acl_index);
950     mp->sw_if_index = ntohl(sw_if_index);
951     mp->is_add = is_add;
952
953     /* send it... */
954     S(mp);
955
956     /* Wait for a reply... */
957     W (ret);
958     return ret;
959 }
960
961 static int api_acl_interface_set_acl_list (vat_main_t * vam)
962 {
963     unformat_input_t * i = vam->input;
964     vl_api_acl_interface_set_acl_list_t * mp;
965     u32 sw_if_index = ~0;
966     u32 acl_index = ~0;
967     u32 *inacls = 0;
968     u32 *outacls = 0;
969     u8 is_input = 0;
970     int ret;
971
972 //  acl_interface_set_acl_list <intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]
973
974     /* Parse args required to build the message */
975     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
976         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
977             ;
978         else if (unformat (i, "sw_if_index %d", &sw_if_index))
979             ;
980         else if (unformat (i, "%d", &acl_index))
981           {
982             if(is_input)
983               vec_add1(inacls, htonl(acl_index));
984             else
985               vec_add1(outacls, htonl(acl_index));
986           }
987         else if (unformat (i, "acl %d", &acl_index))
988             ;
989         else if (unformat (i, "input"))
990             is_input = 1;
991         else if (unformat (i, "output"))
992             is_input = 0;
993         else
994             break;
995     }
996
997     if (sw_if_index == ~0) {
998         errmsg ("missing interface name / explicit sw_if_index number \n");
999         return -99;
1000     }
1001
1002     /* Construct the API message */
1003     M2(ACL_INTERFACE_SET_ACL_LIST, mp, sizeof(u32) * (vec_len(inacls) + vec_len(outacls)));
1004     mp->sw_if_index = ntohl(sw_if_index);
1005     mp->n_input = vec_len(inacls);
1006     mp->count = vec_len(inacls) + vec_len(outacls);
1007     vec_append(inacls, outacls);
1008     if (vec_len(inacls) > 0)
1009       clib_memcpy(mp->acls, inacls, vec_len(inacls)*sizeof(u32));
1010
1011     /* send it... */
1012     S(mp);
1013
1014     /* Wait for a reply... */
1015     W (ret);
1016     return ret;
1017 }
1018
1019 static int api_acl_interface_set_etype_whitelist (vat_main_t * vam)
1020 {
1021     unformat_input_t * i = vam->input;
1022     vl_api_acl_interface_set_etype_whitelist_t * mp;
1023     u32 sw_if_index = ~0;
1024     u32 ethertype = ~0;
1025     u16 *etypes_in = 0;
1026     u16 *etypes_out = 0;
1027     u8 is_input = 1;
1028     int ret;
1029
1030 //  acl_interface_set_etype_whitelist <intfc> | sw_if_index <if-idx> input [ethertype list] output [ethertype list]
1031
1032     /* Parse args required to build the message */
1033     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1034         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
1035             ;
1036         else if (unformat (i, "sw_if_index %d", &sw_if_index))
1037             ;
1038         else if (unformat (i, "%x", &ethertype))
1039           {
1040             ethertype = ethertype & 0xffff;
1041             if(is_input)
1042               vec_add1(etypes_in, htons(ethertype));
1043             else
1044               vec_add1(etypes_out, htons(ethertype));
1045           }
1046         else if (unformat (i, "input"))
1047             is_input = 1;
1048         else if (unformat (i, "output"))
1049             is_input = 0;
1050         else
1051             break;
1052     }
1053
1054     if (sw_if_index == ~0) {
1055         errmsg ("missing interface name / explicit sw_if_index number \n");
1056         return -99;
1057     }
1058
1059     /* Construct the API message */
1060     M2(ACL_INTERFACE_SET_ETYPE_WHITELIST, mp, sizeof(u32) * (vec_len(etypes_in) + vec_len(etypes_out)));
1061     mp->sw_if_index = ntohl(sw_if_index);
1062     mp->n_input = vec_len(etypes_in);
1063     mp->count = vec_len(etypes_in) + vec_len(etypes_out);
1064     vec_append(etypes_in, etypes_out);
1065     if (vec_len(etypes_in) > 0)
1066       clib_memcpy(mp->whitelist, etypes_in, vec_len(etypes_in)*sizeof(etypes_in[0]));
1067
1068     /* send it... */
1069     S(mp);
1070
1071     /* Wait for a reply... */
1072     W (ret);
1073     return ret;
1074 }
1075
1076 static void
1077 api_acl_send_control_ping(vat_main_t *vam)
1078 {
1079   vl_api_acl_plugin_control_ping_t *mp_ping;
1080
1081   M(ACL_PLUGIN_CONTROL_PING, mp_ping);
1082   S(mp_ping);
1083 }
1084
1085
1086 static int api_acl_interface_list_dump (vat_main_t * vam)
1087 {
1088     unformat_input_t * i = vam->input;
1089     u32 sw_if_index = ~0;
1090     vl_api_acl_interface_list_dump_t * mp;
1091     int ret;
1092
1093     /* Parse args required to build the message */
1094     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1095         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
1096             ;
1097         else if (unformat (i, "sw_if_index %d", &sw_if_index))
1098             ;
1099         else
1100             break;
1101     }
1102
1103     /* Construct the API message */
1104     M(ACL_INTERFACE_LIST_DUMP, mp);
1105     mp->sw_if_index = ntohl (sw_if_index);
1106
1107     /* send it... */
1108     S(mp);
1109
1110     /* Use control ping for synchronization */
1111     api_acl_send_control_ping(vam);
1112
1113     /* Wait for a reply... */
1114     W (ret);
1115     return ret;
1116 }
1117
1118 static int api_acl_dump (vat_main_t * vam)
1119 {
1120     unformat_input_t * i = vam->input;
1121     u32 acl_index = ~0;
1122     vl_api_acl_dump_t * mp;
1123     int ret;
1124
1125     /* Parse args required to build the message */
1126     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1127         if (unformat (i, "%d", &acl_index))
1128             ;
1129         else
1130             break;
1131     }
1132
1133     /* Construct the API message */
1134     M(ACL_DUMP, mp);
1135     mp->acl_index = ntohl (acl_index);
1136
1137     /* send it... */
1138     S(mp);
1139
1140     /* Use control ping for synchronization */
1141     api_acl_send_control_ping(vam);
1142
1143     /* Wait for a reply... */
1144     W (ret);
1145     return ret;
1146 }
1147
1148 static int api_macip_acl_dump (vat_main_t * vam)
1149 {
1150     unformat_input_t * i = vam->input;
1151     u32 acl_index = ~0;
1152     vl_api_acl_dump_t * mp;
1153     int ret;
1154
1155     /* Parse args required to build the message */
1156     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1157         if (unformat (i, "%d", &acl_index))
1158             ;
1159         else
1160             break;
1161     }
1162
1163     /* Construct the API message */
1164     M(MACIP_ACL_DUMP, mp);
1165     mp->acl_index = ntohl (acl_index);
1166
1167     /* send it... */
1168     S(mp);
1169
1170     /* Use control ping for synchronization */
1171     api_acl_send_control_ping(vam);
1172
1173     /* Wait for a reply... */
1174     W (ret);
1175     return ret;
1176 }
1177
1178 static int api_acl_interface_etype_whitelist_dump (vat_main_t * vam)
1179 {
1180     unformat_input_t * i = vam->input;
1181     u32 sw_if_index = ~0;
1182     vl_api_acl_interface_etype_whitelist_dump_t * mp;
1183     int ret;
1184
1185     /* Parse args required to build the message */
1186     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1187         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
1188             ;
1189         else if (unformat (i, "sw_if_index %d", &sw_if_index))
1190             ;
1191         else
1192             break;
1193     }
1194
1195     /* Construct the API message */
1196     M(ACL_INTERFACE_ETYPE_WHITELIST_DUMP, mp);
1197     mp->sw_if_index = ntohl (sw_if_index);
1198
1199     /* send it... */
1200     S(mp);
1201
1202     /* Use control ping for synchronization */
1203     api_acl_send_control_ping(vam);
1204
1205     /* Wait for a reply... */
1206     W (ret);
1207     return ret;
1208 }
1209
1210
1211 #define vec_validate_macip_acl_rules(v, idx) \
1212   do {                                 \
1213     if (vec_len(v) < idx+1) {  \
1214       vec_validate(v, idx); \
1215       v[idx].is_permit = 0x1; \
1216     } \
1217   } while (0)
1218
1219
1220 static int api_macip_acl_add (vat_main_t * vam)
1221 {
1222     acl_test_main_t * sm = &acl_test_main;
1223     unformat_input_t * i = vam->input;
1224     vl_api_macip_acl_add_t * mp;
1225     u32 msg_size = sizeof (*mp); /* without the rules */
1226
1227     vl_api_macip_acl_rule_t *rules = 0;
1228     int rule_idx = 0;
1229     int n_rules = 0;
1230     int n_rules_override = -1;
1231     u32 src_prefix_length = 0;
1232     u32 action = 0;
1233     ip4_address_t src_v4address;
1234     ip6_address_t src_v6address;
1235     u8 src_mac[6];
1236     u8 *tag = 0;
1237     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1238     int ret;
1239
1240     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1241     {
1242         if (unformat (i, "permit"))
1243           {
1244             vec_validate_macip_acl_rules(rules, rule_idx);
1245             rules[rule_idx].is_permit = 1;
1246           }
1247         else if (unformat (i, "deny"))
1248           {
1249             vec_validate_macip_acl_rules(rules, rule_idx);
1250             rules[rule_idx].is_permit = 0;
1251           }
1252         else if (unformat (i, "count %d", &n_rules_override))
1253           {
1254             /* we will use this later */
1255           }
1256         else if (unformat (i, "action %d", &action))
1257           {
1258             vec_validate_macip_acl_rules(rules, rule_idx);
1259             rules[rule_idx].is_permit = action;
1260           }
1261         else if (unformat (i, "ip %U/%d",
1262          unformat_ip4_address, &src_v4address, &src_prefix_length) ||
1263                  unformat (i, "ip %U",
1264          unformat_ip4_address, &src_v4address))
1265           {
1266             if (src_prefix_length == 0)
1267               src_prefix_length = 32;
1268             vec_validate_macip_acl_rules(rules, rule_idx);
1269             memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v4address, 4);
1270             rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
1271             rules[rule_idx].src_prefix.len = src_prefix_length;
1272           }
1273         else if (unformat (i, "src"))
1274           {
1275             /* Everything in MACIP is "source" but allow this verbosity */
1276           }
1277         else if (unformat (i, "ip %U/%d",
1278          unformat_ip6_address, &src_v6address, &src_prefix_length) ||
1279                  unformat (i, "ip %U",
1280          unformat_ip6_address, &src_v6address))
1281           {
1282             if (src_prefix_length == 0)
1283               src_prefix_length = 128;
1284             vec_validate_macip_acl_rules(rules, rule_idx);
1285             memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v6address, 4);
1286             rules[rule_idx].src_prefix.address.af = ADDRESS_IP6;
1287             rules[rule_idx].src_prefix.len = src_prefix_length;
1288           }
1289         else if (unformat (i, "mac %U",
1290          my_unformat_mac_address, &src_mac))
1291           {
1292             vec_validate_macip_acl_rules(rules, rule_idx);
1293             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
1294             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
1295           }
1296         else if (unformat (i, "mask %U",
1297          my_unformat_mac_address, &src_mac))
1298           {
1299             vec_validate_macip_acl_rules(rules, rule_idx);
1300             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
1301           }
1302         else if (unformat (i, "tag %s", &tag))
1303           {
1304           }
1305         else if (unformat (i, ","))
1306           {
1307             rule_idx++;
1308             vec_validate_macip_acl_rules(rules, rule_idx);
1309           }
1310         else
1311     break;
1312     }
1313
1314     /* Construct the API message */
1315     vam->result_ready = 0;
1316
1317     if(rules)
1318       n_rules = vec_len(rules);
1319
1320     if (n_rules_override >= 0)
1321       n_rules = n_rules_override;
1322
1323     msg_size += n_rules*sizeof(rules[0]);
1324
1325     mp = vl_msg_api_alloc_as_if_client(msg_size);
1326     clib_memset (mp, 0, msg_size);
1327     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD + sm->msg_id_base);
1328     mp->client_index = vam->my_client_index;
1329     if ((n_rules > 0) && rules)
1330       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
1331     if (tag)
1332       {
1333         if (vec_len(tag) >= sizeof(mp->tag))
1334           {
1335             tag[sizeof(mp->tag)-1] = 0;
1336             vec_set_len (tag, sizeof (mp->tag));
1337           }
1338         clib_memcpy (mp->tag, tag, vec_len (tag));
1339         vec_free (tag);
1340       }
1341
1342     mp->count = htonl(n_rules);
1343
1344     /* send it... */
1345     S(mp);
1346
1347     /* Wait for a reply... */
1348     W (ret);
1349     return ret;
1350 }
1351
1352 static int api_macip_acl_add_replace (vat_main_t * vam)
1353 {
1354     acl_test_main_t * sm = &acl_test_main;
1355     unformat_input_t * i = vam->input;
1356     vl_api_macip_acl_add_replace_t * mp;
1357     u32 acl_index = ~0;
1358     u32 msg_size = sizeof (*mp); /* without the rules */
1359
1360     vl_api_macip_acl_rule_t *rules = 0;
1361     int rule_idx = 0;
1362     int n_rules = 0;
1363     int n_rules_override = -1;
1364     u32 src_prefix_length = 0;
1365     u32 action = 0;
1366     ip4_address_t src_v4address;
1367     ip6_address_t src_v6address;
1368     u8 src_mac[6];
1369     u8 *tag = 0;
1370     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1371     int ret;
1372
1373     if (!unformat (i, "%d", &acl_index)) {
1374         /* Just assume -1 */
1375     }
1376
1377     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1378     {
1379         if (unformat (i, "permit"))
1380           {
1381             vec_validate_macip_acl_rules(rules, rule_idx);
1382             rules[rule_idx].is_permit = 1;
1383           }
1384         else if (unformat (i, "deny"))
1385           {
1386             vec_validate_macip_acl_rules(rules, rule_idx);
1387             rules[rule_idx].is_permit = 0;
1388           }
1389         else if (unformat (i, "count %d", &n_rules_override))
1390           {
1391             /* we will use this later */
1392           }
1393         else if (unformat (i, "action %d", &action))
1394           {
1395             vec_validate_macip_acl_rules(rules, rule_idx);
1396             rules[rule_idx].is_permit = action;
1397           }
1398         else if (unformat (i, "ip %U/%d",
1399             unformat_ip4_address, &src_v4address, &src_prefix_length) ||
1400                    unformat (i, "ip %U",
1401             unformat_ip4_address, &src_v4address))
1402           {
1403               if (src_prefix_length == 0)
1404                 src_prefix_length = 32;
1405               vec_validate_macip_acl_rules(rules, rule_idx);
1406               memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v4address, 4);
1407               rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
1408               rules[rule_idx].src_prefix.len = src_prefix_length;
1409           }
1410         else if (unformat (i, "src"))
1411           {
1412               /* Everything in MACIP is "source" but allow this verbosity */
1413           }
1414         else if (unformat (i, "ip %U/%d",
1415            unformat_ip6_address, &src_v6address, &src_prefix_length) ||
1416                    unformat (i, "ip %U",
1417            unformat_ip6_address, &src_v6address))
1418           {
1419             if (src_prefix_length == 0)
1420              src_prefix_length = 128;
1421             vec_validate_macip_acl_rules(rules, rule_idx);
1422             memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v6address, 4);
1423             rules[rule_idx].src_prefix.address.af = ADDRESS_IP6;
1424             rules[rule_idx].src_prefix.len = src_prefix_length;
1425           }
1426         else if (unformat (i, "mac %U",
1427          my_unformat_mac_address, &src_mac))
1428           {
1429             vec_validate_macip_acl_rules(rules, rule_idx);
1430             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
1431             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
1432           }
1433         else if (unformat (i, "mask %U",
1434          my_unformat_mac_address, &src_mac))
1435           {
1436             vec_validate_macip_acl_rules(rules, rule_idx);
1437             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
1438           }
1439         else if (unformat (i, "tag %s", &tag))
1440           {
1441           }
1442         else if (unformat (i, ","))
1443           {
1444             rule_idx++;
1445             vec_validate_macip_acl_rules(rules, rule_idx);
1446           }
1447         else
1448     break;
1449     }
1450
1451     if (!rules)
1452       {
1453       errmsg ("rule/s required\n");
1454       return -99;
1455       }
1456     /* Construct the API message */
1457     vam->result_ready = 0;
1458
1459     if(rules)
1460       n_rules = vec_len(rules);
1461
1462     if (n_rules_override >= 0)
1463       n_rules = n_rules_override;
1464
1465     msg_size += n_rules*sizeof(rules[0]);
1466
1467     mp = vl_msg_api_alloc_as_if_client(msg_size);
1468     clib_memset (mp, 0, msg_size);
1469     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD_REPLACE + sm->msg_id_base);
1470     mp->client_index = vam->my_client_index;
1471     if ((n_rules > 0) && rules)
1472       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
1473     if (tag)
1474       {
1475         if (vec_len(tag) >= sizeof(mp->tag))
1476           {
1477             tag[sizeof(mp->tag)-1] = 0;
1478             vec_set_len (tag, sizeof (mp->tag));
1479           }
1480         clib_memcpy (mp->tag, tag, vec_len (tag));
1481         vec_free (tag);
1482       }
1483
1484     mp->acl_index = ntohl(acl_index);
1485     mp->count = htonl(n_rules);
1486
1487     /* send it... */
1488     S(mp);
1489
1490     /* Wait for a reply... */
1491     W (ret);
1492     return ret;
1493 }
1494
1495 #define VL_API_LOCAL_SETUP_MESSAGE_ID_TABLE local_setup_message_id_table
1496 static void local_setup_message_id_table (vat_main_t * vam)
1497 {
1498   hash_set_mem (vam->function_by_name, "acl_add_replace_from_file", api_acl_add_replace_from_file);
1499   hash_set_mem (vam->help_by_name, "acl_add_replace_from_file",
1500                 "filename <file> [permit] [append-default-permit]");
1501 }
1502
1503 #include <acl/acl.api_test.c>