-acl_packet_match (acl_main_t * am, u32 acl_index, vlib_buffer_t * b0,
- u8 * r_action, int *r_is_ip6, u32 * r_acl_match_p,
- u32 * r_rule_match_p, u32 * trace_bitmap)
-{
- ethernet_header_t *h0;
- u16 type0;
-
- ip46_address_t src, dst;
- int is_ip6;
- int is_ip4;
- u8 proto;
- u16 src_port = 0;
- u16 dst_port = 0;
- u8 tcp_flags = 0;
- int i;
- acl_list_t *a;
- acl_rule_t *r;
-
- h0 = vlib_buffer_get_current (b0);
- type0 = clib_net_to_host_u16 (h0->type);
- is_ip4 = (type0 == ETHERNET_TYPE_IP4);
- is_ip6 = (type0 == ETHERNET_TYPE_IP6);
-
- if (!(is_ip4 || is_ip6))
- {
- return 0;
- }
- /* The bunch of hardcoded offsets here is intentional to get rid of them
- ASAP, when getting to a faster matching code */
- if (is_ip4)
- {
- clib_memcpy (&src.ip4, get_ptr_to_offset (b0, 26), 4);
- clib_memcpy (&dst.ip4, get_ptr_to_offset (b0, 30), 4);
- proto = acl_get_l4_proto (b0, 0);
- if (1 == proto)
- {
- *trace_bitmap |= 0x00000001;
- /* type */
- src_port = ((u16) (*(u8 *) get_ptr_to_offset (b0, 34)));
- /* code */
- dst_port = ((u16) (*(u8 *) get_ptr_to_offset (b0, 35)));
- } else {
- /* assume TCP/UDP */
- src_port = ntohs ((u16) (*(u16 *) get_ptr_to_offset (b0, 34)));
- dst_port = ntohs ((u16) (*(u16 *) get_ptr_to_offset (b0, 36)));
- /* UDP gets ability to check on an oddball data byte as a bonus */
- tcp_flags = *(u8 *) get_ptr_to_offset (b0, 14 + 20 + 13);
- }
- }
- else /* is_ipv6 implicitly */
- {
- clib_memcpy (&src, get_ptr_to_offset (b0, 22), 16);
- clib_memcpy (&dst, get_ptr_to_offset (b0, 38), 16);
- proto = acl_get_l4_proto (b0, 1);
- if (58 == proto)
- {
- *trace_bitmap |= 0x00000002;
- /* type */
- src_port = (u16) (*(u8 *) get_ptr_to_offset (b0, 54));
- /* code */
- dst_port = (u16) (*(u8 *) get_ptr_to_offset (b0, 55));
- }
- else
- {
- /* assume TCP/UDP */
- src_port = ntohs ((u16) (*(u16 *) get_ptr_to_offset (b0, 54)));
- dst_port = ntohs ((u16) (*(u16 *) get_ptr_to_offset (b0, 56)));
- tcp_flags = *(u8 *) get_ptr_to_offset (b0, 14 + 40 + 13);
- }
- }
- if (pool_is_free_index (am->acls, acl_index))
- {
- if (r_acl_match_p)
- *r_acl_match_p = acl_index;
- if (r_rule_match_p)
- *r_rule_match_p = -1;
- /* the ACL does not exist but is used for policy. Block traffic. */
- return 0;
- }
- a = am->acls + acl_index;
- for (i = 0; i < a->count; i++)
- {
- r = a->rules + i;
- if (is_ip6 != r->is_ipv6)
- {
- continue;
- }
- if (!acl_match_addr (&dst, &r->dst, r->dst_prefixlen, is_ip6))
- continue;
- if (!acl_match_addr (&src, &r->src, r->src_prefixlen, is_ip6))
- continue;
- if (r->proto)
- {
- if (proto != r->proto)
- continue;
- if (!acl_match_port
- (src_port, r->src_port_or_type_first, r->src_port_or_type_last,
- is_ip6))
- continue;
- if (!acl_match_port
- (dst_port, r->dst_port_or_code_first, r->dst_port_or_code_last,
- is_ip6))
- continue;
- /* No need for check of proto == TCP, since in other rules both fields should be zero, so this match will succeed */
- if ((tcp_flags & r->tcp_flags_mask) != r->tcp_flags_value)
- continue;
- }
- /* everything matches! */
- *r_action = r->is_permit;
- *r_is_ip6 = is_ip6;
- if (r_acl_match_p)
- *r_acl_match_p = acl_index;
- if (r_rule_match_p)
- *r_rule_match_p = i;
- return 1;
- }
- return 0;
-}
-
-void
-input_acl_packet_match (u32 sw_if_index, vlib_buffer_t * b0, u32 * nextp,
- u32 * acl_match_p, u32 * rule_match_p,
- u32 * trace_bitmap)
-{
- acl_main_t *am = &acl_main;
- uint8_t action = 0;
- int is_ip6 = 0;
- int i;
- vec_validate (am->input_acl_vec_by_sw_if_index, sw_if_index);
- for (i = 0; i < vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]);
- i++)
- {
- if (acl_packet_match
- (am, am->input_acl_vec_by_sw_if_index[sw_if_index][i], b0, &action,
- &is_ip6, acl_match_p, rule_match_p, trace_bitmap))
- {
- if (is_ip6)
- {
- *nextp = am->acl_in_ip6_match_next[action];
- }
- else
- {
- *nextp = am->acl_in_ip4_match_next[action];
- }
- return;
- }
- }
- if (vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]) > 0)
- {
- /* If there are ACLs and none matched, deny by default */
- *nextp = 0;
- }
-
-}
-
-void
-output_acl_packet_match (u32 sw_if_index, vlib_buffer_t * b0, u32 * nextp,
- u32 * acl_match_p, u32 * rule_match_p,
- u32 * trace_bitmap)
-{
- acl_main_t *am = &acl_main;
- uint8_t action = 0;
- int is_ip6 = 0;
- int i;
- vec_validate (am->output_acl_vec_by_sw_if_index, sw_if_index);
- for (i = 0; i < vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]);
- i++)
- {
- if (acl_packet_match
- (am, am->output_acl_vec_by_sw_if_index[sw_if_index][i], b0, &action,
- &is_ip6, acl_match_p, rule_match_p, trace_bitmap))
- {
- if (is_ip6)
- {
- *nextp = am->acl_out_ip6_match_next[action];
- }
- else
- {
- *nextp = am->acl_out_ip4_match_next[action];
- }
- return;
- }
- }
- if (vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]) > 0)
- {
- /* If there are ACLs and none matched, deny by default */
- *nextp = 0;
- }
-}
-
-typedef struct
-{
- u8 is_ipv6;
- u8 mac_mask[6];
- u8 prefix_len;
- u32 count;
- u32 table_index;
- u32 arp_table_index;
-} macip_match_type_t;
-
-static u32
-macip_find_match_type (macip_match_type_t * mv, u8 * mac_mask, u8 prefix_len,
- u8 is_ipv6)
-{
- u32 i;
- if (mv)
- {
- for (i = 0; i < vec_len (mv); i++)
- {
- if ((mv[i].prefix_len == prefix_len) && (mv[i].is_ipv6 == is_ipv6)
- && (0 == memcmp (mv[i].mac_mask, mac_mask, 6)))
- {
- return i;
- }
- }
- }
- return ~0;
-}
-
-
-/* Get metric used to sort match types.
- The more specific and the more often seen - the bigger the metric */
-static int
-match_type_metric (macip_match_type_t * m)
-{
- /* FIXME: count the ones in the MAC mask as well, check how well this heuristic works in real life */
- return m->prefix_len + m->is_ipv6 + 10 * m->count;
-}
-
-static int
-match_type_compare (macip_match_type_t * m1, macip_match_type_t * m2)
-{
- /* Ascending sort based on the metric values */
- return match_type_metric (m1) - match_type_metric (m2);
-}
-
-/* Get the offset of L3 source within ethernet packet */
-static int
-get_l3_src_offset(int is6)
-{
- if(is6)
- return (sizeof(ethernet_header_t) + offsetof(ip6_header_t, src_address));
- else
- return (sizeof(ethernet_header_t) + offsetof(ip4_header_t, src_address));
-}