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