1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
</*
* Copyright (c) 2015 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __ESP_H__
#define __ESP_H__
#include <vnet/ip/ip.h>
#include <vnet/crypto/crypto.h>
#include <vnet/ipsec/ipsec.h>
typedef struct
{
union
{
u32 spi;
u8 spi_bytes[4];
};
u32 seq;
u8 data[0];
} esp_header_t;
typedef struct
{
u8 pad_length;
u8 next_header;
} esp_footer_t;
/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
ip4_header_t ip4;
esp_header_t esp;
}) ip4_and_esp_header_t;
/* *INDENT-ON* */
/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
ip4_header_t ip4;
udp_header_t udp;
esp_header_t esp;
}) ip4_and_udp_and_esp_header_t;
/* *INDENT-ON* */
/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
ip6_header_t ip6;
esp_header_t esp;
}) ip6_and_esp_header_t;
/* *INDENT-ON* */
/**
* AES GCM Additional Authentication data
*/
typedef struct esp_aead_t_
{
/**
* for GCM: when using ESN it's:
* SPI, seq-hi, seg-low
* else
* SPI, seq-low
*/
u32 data[3];
} __clib_packed esp_aead_t;
#define ESP_SEQ_MAX (4294967295UL)
#define ESP_MAX_BLOCK_SIZE (16)
#define ESP_MAX_IV_SIZE (16)
#define ESP_MAX_ICV_SIZE (32)
u8 *format_esp_header (u8 * s, va_list * args);
/* TODO seq increment should be atomic to be accessed by multiple workers */
always_inline int
esp_seq_advance (ipsec_sa_t * sa)
{
if (PREDICT_TRUE (ipsec_sa_is_set_USE_ESN (sa)))
{
if (PREDICT_FALSE (sa->seq == ESP_SEQ_MAX))
{
if (PREDICT_FALSE (ipsec_sa_is_set_USE_ANTI_REPLAY (sa) &&
sa->seq_hi == ESP_SEQ_MAX))
return 1;
sa->seq_hi++;
}
sa->seq++;
}
else
{
if (PREDICT_FALSE (ipsec_sa_is_set_USE_ANTI_REPLAY (sa) &&
sa->seq == ESP_SEQ_MAX))
return 1;
sa->seq++;
}
return 0;
}
always_inline unsigned int
hmac_calc (vlib_main_t * vm, ipsec_sa_t * sa, u8 * data, int data_len,
u8 * signature)
{
vnet_crypto_op_t _op, *op = &_op;
if (PREDICT_FALSE (sa->integ_op_id == 0))
return 0;
vnet_crypto_op_init (op, sa->integ_op_id);
op->key_index = sa->integ_key_index;
op->src = data;
op->len = data_len;
op->digest = signature;
op->digest_len = sa->integ_icv_size;
if (ipsec_sa_is_set_USE_ESN (sa))
{
u32 seq_hi = clib_host_to_net_u32 (sa->seq_hi);
op->len += 4;
clib_memcpy (data + data_len, &seq_hi, 4);
}
vnet_crypto_process_ops (vm, op, 1);
return sa->integ_icv_size;
}
always_inline void
esp_aad_fill (vnet_crypto_op_t * op,
const esp_header_t * esp, const ipsec_sa_t * sa)
{
esp_aead_t *aad;
aad = (esp_aead_t *) op->aad;
aad->data[0] = esp->spi;
if (ipsec_sa_is_set_USE_ESN (sa))
{
/* SPI, seq-hi, seq-low */
aad->data[1] = clib_host_to_net_u32 (sa->seq_hi);
aad->data[2] = esp->seq;
op->aad_len = 12;
}
else
{
/* SPI, seq-low */
aad->data[1] = esp->seq;
op->aad_len = 8;
}
}
#endif /* __ESP_H__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
ip[46] address in the packet is matched
* against src_ip_addr, with src_ip_prefix_len set to 0.
*
* For better performance, minimize the number of
* (src_mac_mask, src_ip_prefix_len) combinations
* in a MACIP ACL.
*/
u8 src_mac[6];
u8 src_mac_mask[6];
u8 src_ip_addr[16];
u8 src_ip_prefix_len;
};
/** \brief Replace an existing ACL in-place or create a new ACL
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param acl_index - an existing ACL entry (0..0xfffffffe) to replace, or 0xffffffff to make new ACL
@param tag - a string value stored along with the ACL, for descriptive purposes
@param count - number of ACL rules
@r - Rules for this access-list
*/
manual_print manual_endian define acl_add_replace
{
u32 client_index;
u32 context;
u32 acl_index; /* ~0 to add, existing ACL# to replace */
u8 tag[64]; /* What gets in here gets out in the corresponding tag field when dumping the ACLs. */
u32 count;
vl_api_acl_rule_t r[count];
};
/** \brief Reply to add/replace ACL
@param context - returned sender context, to match reply w/ request
@param acl_index - index of the updated or newly created ACL
@param retval 0 - no error
*/
define acl_add_replace_reply
{
u32 context;
u32 acl_index;
i32 retval;
};
/** \brief Delete an ACL
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param acl_index - ACL index to delete
*/
autoreply manual_print define acl_del
{
u32 client_index;
u32 context;
u32 acl_index;
};
/* acl_interface_add_del(_reply) to be deprecated in lieu of acl_interface_set_acl_list */
/** \brief Use acl_interface_set_acl_list instead
Append/remove an ACL index to/from the list of ACLs checked for an interface
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param is_add - add or delete the ACL index from the list
@param is_input - check the ACL on input (1) or output (0)
@param sw_if_index - the interface to alter the list of ACLs on
@param acl_index - index of ACL for the operation
*/
autoreply manual_print define acl_interface_add_del
{
u32 client_index;
u32 context;
u8 is_add;
/*
* is_input = 0 => ACL applied on interface egress
* is_input = 1 => ACL applied on interface ingress
*/
u8 is_input;
u32 sw_if_index;
u32 acl_index;
};
/** \brief Set the vector of input/output ACLs checked for an interface
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param sw_if_index - the interface to alter the list of ACLs on
@param count - total number of ACL indices in the vector
@param n_input - this many first elements correspond to input ACLs, the rest - output
@param acls - vector of ACL indices
*/
autoreply manual_print define acl_interface_set_acl_list
{
u32 client_index;
u32 context;
u32 sw_if_index;
u8 count;
u8 n_input; /* First n_input ACLs are set as a list of input ACLs, the rest are applied as output */
u32 acls[count];
};
/** \brief Reply to set the ACL list on an interface
@param context - returned sender context, to match reply w/ request
@param retval 0 - no error
*/
/** \brief Dump the specific ACL contents or all of the ACLs' contents
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param acl_index - ACL index to dump, ~0 to dump all ACLs
*/
define acl_dump
{
u32 client_index;
u32 context;
u32 acl_index; /* ~0 for all ACLs */
};
/** \brief Details about a single ACL contents
@param context - returned sender context, to match reply w/ request
@param acl_index - ACL index whose contents are being sent in this message
@param tag - Descriptive tag value which was supplied at ACL creation
@param count - Number of rules in this ACL
@param r - Array of rules within this ACL
*/
manual_endian manual_print define acl_details
{
u32 context;
u32 acl_index;
u8 tag[64]; /* Same blob that was supplied to us when creating the ACL, one hopes. */
u32 count;
vl_api_acl_rule_t r[count];
};
/** \brief Dump the list(s) of ACL applied to specific or all interfaces
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param sw_if_index - interface to dump the ACL list for
*/
define acl_interface_list_dump
{
u32 client_index;
u32 context;
u32 sw_if_index; /* ~0 for all interfaces */
};
/** \brief Details about a single ACL contents
@param context - returned sender context, to match reply w/ request
@param sw_if_index - interface for which the list of ACLs is applied
@param count - total length of acl indices vector
@param n_input - this many of indices in the beginning are input ACLs, the rest - output
@param acls - the vector of ACL indices
*/
define acl_interface_list_details
{
u32 context;
u32 sw_if_index;
u8 count;
u8 n_input;
u32 acls[count];
};
/** \brief Add a MACIP ACL
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param tag - descriptive value for this MACIP ACL
@param count - number of rules in this MACIP ACL
@param r - vector of MACIP ACL rules
*/
manual_endian manual_print define macip_acl_add
{
u32 client_index;
u32 context;
u8 tag[64];
u32 count;
vl_api_macip_acl_rule_t r[count];
};
/** \brief Reply to add MACIP ACL
@param context - returned sender context, to match reply w/ request
@param acl_index - index of the newly created MACIP ACL
@param retval 0 - no error
*/
define macip_acl_add_reply
{
u32 context;
u32 acl_index;
i32 retval;
};
/** \brief Add/Replace a MACIP ACL
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param acl_index - an existing MACIP ACL entry (0..0xfffffffe) to replace, or 0xffffffff to make new MACIP ACL
@param tag - descriptive value for this MACIP ACL
@param count - number of rules in this MACIP ACL
@param r - vector of MACIP ACL rules
*/
manual_endian manual_print define macip_acl_add_replace
{
u32 client_index;
u32 context;
u32 acl_index; /* ~0 to add, existing MACIP ACL# to replace */
u8 tag[64];
u32 count;
vl_api_macip_acl_rule_t r[count];
};
/** \brief Reply to add/replace MACIP ACL
@param context - returned sender context, to match reply w/ request
@param acl_index - index of the newly created MACIP ACL
@param retval 0 - no error
*/
define macip_acl_add_replace_reply
{
u32 context;
u32 acl_index;
i32 retval;
};
/** \brief Delete a MACIP ACL
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param acl_index - MACIP ACL index to delete
*/
autoreply manual_print define macip_acl_del
{
u32 client_index;
u32 context;
u32 acl_index;
};
/** \brief Add or delete a MACIP ACL to/from interface
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param is_add - add (1) or delete (0) MACIP ACL from being used on an interface
@param sw_if_index - interface to apply the action to
@param acl_index - MACIP ACL index
*/
autoreply manual_print define macip_acl_interface_add_del
{
u32 client_index;
u32 context;
u8 is_add;
/* MACIP ACLs are always input */
u32 sw_if_index;
u32 acl_index;
};
/** \brief Dump one or all defined MACIP ACLs
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param acl_index - MACIP ACL index or ~0 to dump all MACIP ACLs
*/
define macip_acl_dump
{
u32 client_index;
u32 context;
u32 acl_index; /* ~0 for all ACLs */
};
/** \brief Details about one MACIP ACL
@param context - returned sender context, to match reply w/ request
@param acl_index - index of this MACIP ACL
@param tag - descriptive tag which was supplied during the creation
@param count - length of the vector of MACIP ACL rules
@param r - rules comprising this MACIP ACL
*/
manual_endian manual_print define macip_acl_details
{
u32 context;
u32 acl_index;
u8 tag[64];
u32 count;
vl_api_macip_acl_rule_t r[count];
};
/** \brief Get the vector of MACIP ACL IDs applied to the interfaces
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
*/
define macip_acl_interface_get
{
u32 client_index;
u32 context;
};
/** \brief Reply with the vector of MACIP ACLs by sw_if_index
@param context - returned sender context, to match reply w/ request
@param count - total number of elements in the vector
@param acls - the vector of active MACIP ACL indices per sw_if_index
*/
define macip_acl_interface_get_reply
{
u32 context;
u32 count;
u32 acls[count];
};
/** \brief Dump the list(s) of MACIP ACLs applied to specific or all interfaces
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param sw_if_index - interface to dump the MACIP ACL list for
*/
define macip_acl_interface_list_dump
{
u32 client_index;
u32 context;
u32 sw_if_index; /* ~0 for all interfaces */
};
/** \brief Details about a single MACIP ACL contents
@param context - returned sender context, to match reply w/ request
@param sw_if_index - interface for which the list of MACIP ACLs is applied
@param count - total length of acl indices vector
@param acls - the vector of MACIP ACL indices
*/
define macip_acl_interface_list_details
{
u32 context;
u32 sw_if_index;
u8 count;
u32 acls[count];
};
|