examples/ipsec-secgw: support configuration file
This patch adds the configuration file support to ipsec_secgw sample application. Instead of hard-coded rules, the users can specify their own SP, SA, and routing rules in the configuration file. A command line option "-f" is added to pass the configuration file location to the application. Configuration item formats: SP rule format: sp <ip_ver> <dir> esp <action> <priority> <src_ip> <dst_ip> \ <proto> <sport> <dport> SA rule format: sa <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key> \ <mode> <src_ip> <dst_ip> Routing rule format: rt <ip_ver> <src_ip> <dst_ip> <port> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com> Acked-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
This commit is contained in:
parent
77debbbfdf
commit
0d547ed037
@ -78,6 +78,10 @@ New Features
|
||||
* C3XXX device
|
||||
* C62XX device
|
||||
|
||||
* **Updated the IPsec example with following support:**
|
||||
|
||||
* configuration file
|
||||
|
||||
|
||||
Resolved Issues
|
||||
---------------
|
||||
|
@ -122,7 +122,7 @@ The application has a number of command line options::
|
||||
-p PORTMASK -P -u PORTMASK
|
||||
--config (port,queue,lcore)[,(port,queue,lcore]
|
||||
--single-sa SAIDX
|
||||
--ep0|--ep1
|
||||
-f CONFIG_FILE_PATH
|
||||
|
||||
Where:
|
||||
|
||||
@ -142,14 +142,11 @@ Where:
|
||||
on both Inbound and Outbound. This option is meant for debugging/performance
|
||||
purposes.
|
||||
|
||||
* ``--ep0``: configure the app as Endpoint 0.
|
||||
* ``-f CONFIG_FILE_PATH``: the full path of text-based file containing all
|
||||
configuration items for running the application (See Configuration file
|
||||
syntax section below). ``-f CONFIG_FILE_PATH`` **must** be specified.
|
||||
**ONLY** the UNIX format configuration file is accepted.
|
||||
|
||||
* ``--ep1``: configure the app as Endpoint 1.
|
||||
|
||||
Either one of ``--ep0`` or ``--ep1`` **must** be specified.
|
||||
The main purpose of these options is to easily configure two systems
|
||||
back-to-back that would forward traffic through an IPsec tunnel (see
|
||||
:ref:`figure_ipsec_endpoints`).
|
||||
|
||||
The mapping of lcores to port/queues is similar to other l3fwd applications.
|
||||
|
||||
@ -157,7 +154,8 @@ For example, given the following command line::
|
||||
|
||||
./build/ipsec-secgw -l 20,21 -n 4 --socket-mem 0,2048 \
|
||||
--vdev "cryptodev_null_pmd" -- -p 0xf -P -u 0x3 \
|
||||
--config="(0,0,20),(1,0,20),(2,0,21),(3,0,21)" --ep0 \
|
||||
--config="(0,0,20),(1,0,20),(2,0,21),(3,0,21)" \
|
||||
-f /path/to/config_file \
|
||||
|
||||
where each options means:
|
||||
|
||||
@ -194,8 +192,12 @@ where each options means:
|
||||
| | | | |
|
||||
+----------+-----------+-----------+---------------------------------------+
|
||||
|
||||
* The ``--ep0`` options configures the app with a given set of SP, SA and Routing
|
||||
entries as explained below in more detail.
|
||||
* The ``-f /path/to/config_file`` option enables the application read and
|
||||
parse the configuration file specified, and configures the application
|
||||
with a given set of SP, SA and Routing entries accordingly. The syntax of
|
||||
the configuration file will be explained below in more detail. Please
|
||||
**note** the parser only accepts UNIX format text file. Other formats
|
||||
such as DOS/MAC format will cause a parse error.
|
||||
|
||||
Refer to the *DPDK Getting Started Guide* for general information on running
|
||||
applications and the Environment Abstraction Layer (EAL) options.
|
||||
@ -219,496 +221,357 @@ For example, something like the following command line:
|
||||
--vdev "cryptodev_aesni_mb_pmd" --vdev "cryptodev_null_pmd" \
|
||||
-- \
|
||||
-p 0xf -P -u 0x3 --config="(0,0,20),(1,0,20),(2,0,21),(3,0,21)" \
|
||||
--ep0
|
||||
-f sample.cfg
|
||||
|
||||
|
||||
Configurations
|
||||
--------------
|
||||
|
||||
The following sections provide some details on the default values used to
|
||||
initialize the SP, SA and Routing tables.
|
||||
Currently all configuration information is hard coded into the application.
|
||||
|
||||
The following image illustrate a few of the concepts regarding IPSec, such
|
||||
as protected/unprotected and inbound/outbound traffic, from the point of
|
||||
view of two back-to-back endpoints:
|
||||
|
||||
.. _figure_ipsec_endpoints:
|
||||
|
||||
.. figure:: img/ipsec_endpoints.*
|
||||
|
||||
IPSec Inbound/Outbound traffic
|
||||
|
||||
Note that the above image only displays unidirectional traffic per port
|
||||
for illustration purposes.
|
||||
The application supports bidirectional traffic on all ports,
|
||||
The following sections provide the syntax of configurations to initialize
|
||||
your SP, SA and Routing tables.
|
||||
Configurations shall be specified in the configuration file to be passed to
|
||||
the application. The file is then parsed by the application. The successful
|
||||
parsing will result in the appropriate rules being applied to the tables
|
||||
accordingly.
|
||||
|
||||
|
||||
Security Policy Initialization
|
||||
Configuration File Syntax
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As mention in the overview, the Security Policies are ACL rules.
|
||||
The application defines two ACLs, one each of Inbound and Outbound, and
|
||||
it replicates them per socket in use.
|
||||
The application parsers the rules specified in the configuration file and
|
||||
passes them to the ACL table, and replicates them per socket in use.
|
||||
|
||||
Following are the default rules which show only the relevant information,
|
||||
assuming ANY value is valid for the fields not mentioned (src ip, proto,
|
||||
src/dst ports).
|
||||
Following are the configuration file syntax.
|
||||
|
||||
.. _table_ipsec_endpoint_outbound_sp:
|
||||
General rule syntax
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. table:: Endpoint 0 Outbound Security Policies
|
||||
The parse treats one line in the configuration file as one configuration
|
||||
item (unless the line concatenation symbol exists). Every configuration
|
||||
item shall follow the syntax of either SP, SA, or Routing rules specified
|
||||
below.
|
||||
|
||||
+-----------------------------------+------------+
|
||||
| **Dst** | **SA idx** |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.105.0/24 | 5 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.106.0/24 | 6 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.175.0/24 | 10 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.176.0/24 | 11 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.200.0/24 | 15 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.201.0/24 | 16 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.55.0/24 | 25 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.56.0/24 | 26 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.240.0/24 | BYPASS |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.241.0/24 | BYPASS |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 0:0:0:0:5555:5555:0:0/96 | 5 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 0:0:0:0:6666:6666:0:0/96 | 6 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 0:0:1111:1111:0:0:0:0/96 | 10 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 0:0:1111:1111:1111:1111:0:0/96 | 11 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 0:0:0:0:aaaa:aaaa:0:0/96 | 25 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 0:0:0:0:bbbb:bbbb:0:0/96 | 26 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
The configuration parser supports the following special symbols:
|
||||
|
||||
.. _table_ipsec_endpoint_inbound_sp:
|
||||
* Comment symbol **#**. Any character from this symbol to the end of
|
||||
line is treated as comment and will not be parsed.
|
||||
|
||||
.. table:: Endpoint 0 Inbound Security Policies
|
||||
|
||||
+-----------------------------------+------------+
|
||||
| **Dst** | **SA idx** |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.115.0/24 | 105 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.116.0/24 | 106 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.185.0/24 | 110 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.186.0/24 | 111 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.210.0/24 | 115 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.211.0/24 | 116 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.65.0/24 | 125 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.66.0/24 | 126 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.245.0/24 | BYPASS |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| 192.168.246.0/24 | BYPASS |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| ffff:0:0:0:5555:5555:0:0/96 | 105 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| ffff:0:0:0:6666:6666:0:0/96 | 106 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| ffff:0:1111:1111:0:0:0:0/96 | 110 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| ffff:0:1111:1111:1111:1111:0:0/96 | 111 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| ffff:0:0:0:aaaa:aaaa:0:0/96 | 125 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
| ffff:0:0:0:bbbb:bbbb:0:0/96 | 126 |
|
||||
| | |
|
||||
+-----------------------------------+------------+
|
||||
|
||||
For Endpoint 1, we use the same policies in reverse, meaning the Inbound SP
|
||||
entries are set as Outbound and vice versa.
|
||||
* Line concatenation symbol **\\**. This symbol shall be placed in the end
|
||||
of the line to be concatenated to the line below. Multiple lines'
|
||||
concatenation is supported.
|
||||
|
||||
|
||||
Security Association Initialization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
SP rule syntax
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
The SAs are kept in a array table.
|
||||
The SP rule syntax is shown as follows:
|
||||
|
||||
For Inbound, the SPI is used as index modulo the table size.
|
||||
This means that on a table for 100 SA, SPI 5 and 105 would use the same index
|
||||
and that is not currently supported.
|
||||
.. code-block:: console
|
||||
|
||||
Notice that it is not an issue for Outbound traffic as we store the index and
|
||||
not the SPI in the Security Policy.
|
||||
|
||||
All SAs configured with AES-CBC and HMAC-SHA1 share the same values for cipher
|
||||
block size and key, and authentication digest size and key.
|
||||
|
||||
The following are the default values:
|
||||
|
||||
.. _table_ipsec_endpoint_outbound_sa:
|
||||
|
||||
.. table:: Endpoint 0 Outbound Security Associations
|
||||
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| **SPI** | **Mode** | **Cipher** | **Auth** | **Tunnel src** | **Tunnel dst** |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 5 | Tunnel | AES-CBC | HMAC-SHA1 | 172.16.1.5 | 172.16.2.5 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 6 | Tunnel | AES-CBC | HMAC-SHA1 | 172.16.1.6 | 172.16.2.6 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 10 | Trans | AES-CBC | HMAC-SHA1 | N/A | N/A |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 11 | Trans | AES-CBC | HMAC-SHA1 | N/A | N/A |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 15 | Tunnel | NULL | NULL | 172.16.1.5 | 172.16.2.5 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 16 | Tunnel | NULL | NULL | 172.16.1.6 | 172.16.2.6 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 25 | Tunnel | AES-CBC | HMAC-SHA1 | 1111:1111: | 2222:2222: |
|
||||
| | | | | 1111:1111: | 2222:2222: |
|
||||
| | | | | 1111:1111: | 2222:2222: |
|
||||
| | | | | 1111:5555 | 2222:5555 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 26 | Tunnel | AES-CBC | HMAC-SHA1 | 1111:1111: | 2222:2222: |
|
||||
| | | | | 1111:1111: | 2222:2222: |
|
||||
| | | | | 1111:1111: | 2222:2222: |
|
||||
| | | | | 1111:6666 | 2222:6666 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
|
||||
.. _table_ipsec_endpoint_inbound_sa:
|
||||
|
||||
.. table:: Endpoint 0 Inbound Security Associations
|
||||
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| **SPI** | **Mode** | **Cipher** | **Auth** | **Tunnel src** | **Tunnel dst** |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 105 | Tunnel | AES-CBC | HMAC-SHA1 | 172.16.2.5 | 172.16.1.5 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 106 | Tunnel | AES-CBC | HMAC-SHA1 | 172.16.2.6 | 172.16.1.6 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 110 | Trans | AES-CBC | HMAC-SHA1 | N/A | N/A |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 111 | Trans | AES-CBC | HMAC-SHA1 | N/A | N/A |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 115 | Tunnel | NULL | NULL | 172.16.2.5 | 172.16.1.5 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 116 | Tunnel | NULL | NULL | 172.16.2.6 | 172.16.1.6 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 125 | Tunnel | AES-CBC | HMAC-SHA1 | 2222:2222: | 1111:1111: |
|
||||
| | | | | 2222:2222: | 1111:1111: |
|
||||
| | | | | 2222:2222: | 1111:1111: |
|
||||
| | | | | 2222:5555 | 1111:5555 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
| 126 | Tunnel | AES-CBC | HMAC-SHA1 | 2222:2222: | 1111:1111: |
|
||||
| | | | | 2222:2222: | 1111:1111: |
|
||||
| | | | | 2222:2222: | 1111:1111: |
|
||||
| | | | | 2222:6666 | 1111:6666 |
|
||||
| | | | | | |
|
||||
+---------+----------+------------+-----------+----------------+----------------+
|
||||
|
||||
For Endpoint 1, we use the same policies in reverse, meaning the Inbound SP
|
||||
entries are set as Outbound and vice versa.
|
||||
sp <ip_ver> <dir> esp <action> <priority> <src_ip> <dst_ip>
|
||||
<proto> <sport> <dport>
|
||||
|
||||
|
||||
Routing Initialization
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
where each options means:
|
||||
|
||||
The Routing is implemented using an LPM table.
|
||||
``<ip_ver>``
|
||||
|
||||
Following default values:
|
||||
* IP protocol version
|
||||
|
||||
.. _table_ipsec_endpoint_outbound_routing:
|
||||
* Optional: No
|
||||
|
||||
.. table:: Endpoint 0 Routing Table
|
||||
* Available options:
|
||||
|
||||
+------------------+----------+
|
||||
| **Dst addr** | **Port** |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 172.16.2.5/32 | 0 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 172.16.2.6/32 | 1 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.175.0/24 | 0 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.176.0/24 | 1 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.240.0/24 | 0 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.241.0/24 | 1 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.115.0/24 | 2 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.116.0/24 | 3 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.65.0/24 | 2 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.66.0/24 | 3 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.185.0/24 | 2 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.186.0/24 | 3 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.210.0/24 | 2 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.211.0/24 | 3 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.245.0/24 | 2 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.246.0/24 | 3 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 2222:2222: | 0 |
|
||||
| 2222:2222: | |
|
||||
| 2222:2222: | |
|
||||
| 2222:5555/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 2222:2222: | 1 |
|
||||
| 2222:2222: | |
|
||||
| 2222:2222: | |
|
||||
| 2222:6666/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 0000:0000: | 0 |
|
||||
| 1111:1111: | |
|
||||
| 0000:0000: | |
|
||||
| 0000:0000/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 0000:0000: | 1 |
|
||||
| 1111:1111: | |
|
||||
| 1111:1111: | |
|
||||
| 0000:0000/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| ffff:0000: | 2 |
|
||||
| 0000:0000: | |
|
||||
| aaaa:aaaa: | |
|
||||
| 0000:0/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| ffff:0000: | 3 |
|
||||
| 0000:0000: | |
|
||||
| bbbb:bbbb: | |
|
||||
| 0000:0/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| ffff:0000: | 2 |
|
||||
| 0000:0000: | |
|
||||
| 5555:5555: | |
|
||||
| 0000:0/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| ffff:0000: | 3 |
|
||||
| 0000:0000: | |
|
||||
| 6666:6666: | |
|
||||
| 0000:0/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| ffff:0000: | 2 |
|
||||
| 1111:1111: | |
|
||||
| 0000:0000: | |
|
||||
| 0000:0000/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| ffff:0000: | 3 |
|
||||
| 1111:1111: | |
|
||||
| 1111:1111: | |
|
||||
| 0000:0000/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
* *ipv4*: IP protocol version 4
|
||||
* *ipv6*: IP protocol version 6
|
||||
|
||||
.. _table_ipsec_endpoint_inbound_routing:
|
||||
``<dir>``
|
||||
|
||||
.. table:: Endpoint 1 Routing Table
|
||||
* The traffic direction
|
||||
|
||||
+------------------+----------+
|
||||
| **Dst addr** | **Port** |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 172.16.1.5/32 | 0 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 172.16.1.6/32 | 1 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.185.0/24 | 0 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.186.0/24 | 1 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.245.0/24 | 0 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.246.0/24 | 1 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.105.0/24 | 2 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.106.0/24 | 3 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.55.0/24 | 2 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.56.0/24 | 3 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.175.0/24 | 2 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.176.0/24 | 3 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.200.0/24 | 2 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.201.0/24 | 3 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.240.0/24 | 2 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 192.168.241.0/24 | 3 |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 1111:1111: | 0 |
|
||||
| 1111:1111: | |
|
||||
| 1111:1111: | |
|
||||
| 1111:5555/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 1111:1111: | 1 |
|
||||
| 1111:1111: | |
|
||||
| 1111:1111: | |
|
||||
| 1111:6666/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| ffff:0000: | 0 |
|
||||
| 1111:1111: | |
|
||||
| 0000:0000: | |
|
||||
| 0000:0000/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| ffff:0000: | 1 |
|
||||
| 1111:1111: | |
|
||||
| 1111:1111: | |
|
||||
| 0000:0000/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 0000:0000: | 2 |
|
||||
| 0000:0000: | |
|
||||
| aaaa:aaaa: | |
|
||||
| 0000:0/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 0000:0000: | 3 |
|
||||
| 0000:0000: | |
|
||||
| bbbb:bbbb: | |
|
||||
| 0000:0/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 0000:0000: | 2 |
|
||||
| 0000:0000: | |
|
||||
| 5555:5555: | |
|
||||
| 0000:0/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 0000:0000: | 3 |
|
||||
| 0000:0000: | |
|
||||
| 6666:6666: | |
|
||||
| 0000:0/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 0000:0000: | 2 |
|
||||
| 1111:1111: | |
|
||||
| 0000:0000: | |
|
||||
| 0000:0000/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
| 0000:0000: | 3 |
|
||||
| 1111:1111: | |
|
||||
| 1111:1111: | |
|
||||
| 0000:0000/116 | |
|
||||
| | |
|
||||
+------------------+----------+
|
||||
* Optional: No
|
||||
|
||||
* Available options:
|
||||
|
||||
* *in*: inbound traffic
|
||||
* *out*: outbound traffic
|
||||
|
||||
``<action>``
|
||||
|
||||
* IPsec action
|
||||
|
||||
* Optional: No
|
||||
|
||||
* Available options:
|
||||
|
||||
* *protect <SA_idx>*: the specified traffic is protected by SA rule
|
||||
with id SA_idx
|
||||
* *bypass*: the specified traffic traffic is bypassed
|
||||
* *discard*: the specified traffic is discarded
|
||||
|
||||
``<priority>``
|
||||
|
||||
* Rule priority
|
||||
|
||||
* Optional: Yes, default priority 0 will be used
|
||||
|
||||
* Syntax: *pri <id>*
|
||||
|
||||
``<src_ip>``
|
||||
|
||||
* The source IP address and mask
|
||||
|
||||
* Optional: Yes, default address 0.0.0.0 and mask of 0 will be used
|
||||
|
||||
* Syntax:
|
||||
|
||||
* *src X.X.X.X/Y* for IPv4
|
||||
* *src XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX/Y* for IPv6
|
||||
|
||||
``<dst_ip>``
|
||||
|
||||
* The destination IP address and mask
|
||||
|
||||
* Optional: Yes, default address 0.0.0.0 and mask of 0 will be used
|
||||
|
||||
* Syntax:
|
||||
|
||||
* *dst X.X.X.X/Y* for IPv4
|
||||
* *dst XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX/Y* for IPv6
|
||||
|
||||
``<proto>``
|
||||
|
||||
* The protocol start and end range
|
||||
|
||||
* Optional: yes, default range of 0 to 0 will be used
|
||||
|
||||
* Syntax: *proto X:Y*
|
||||
|
||||
``<sport>``
|
||||
|
||||
* The source port start and end range
|
||||
|
||||
* Optional: yes, default range of 0 to 0 will be used
|
||||
|
||||
* Syntax: *sport X:Y*
|
||||
|
||||
``<dport>``
|
||||
|
||||
* The destination port start and end range
|
||||
|
||||
* Optional: yes, default range of 0 to 0 will be used
|
||||
|
||||
* Syntax: *dport X:Y*
|
||||
|
||||
Example SP rules:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
sp ipv4 out esp protect 105 pri 1 dst 192.168.115.0/24 sport 0:65535 \
|
||||
dport 0:65535
|
||||
|
||||
sp ipv6 in esp bypass pri 1 dst 0000:0000:0000:0000:5555:5555:\
|
||||
0000:0000/96 sport 0:65535 dport 0:65535
|
||||
|
||||
|
||||
SA rule syntax
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
The successfully parsed SA rules will be stored in an array table.
|
||||
|
||||
All SAs configured with AES-CBC and HMAC-SHA1 share the same values for
|
||||
cipher block size and key, and authentication digest size and key.
|
||||
|
||||
The SA rule syntax is shown as follows:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
sa <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key>
|
||||
<mode> <src_ip> <dst_ip>
|
||||
|
||||
where each options means:
|
||||
|
||||
``<dir>``
|
||||
|
||||
* The traffic direction
|
||||
|
||||
* Optional: No
|
||||
|
||||
* Available options:
|
||||
|
||||
* *in*: inbound traffic
|
||||
* *out*: outbound traffic
|
||||
|
||||
``<spi>``
|
||||
|
||||
* The SPI number
|
||||
|
||||
* Optional: No
|
||||
|
||||
* Syntax: unsigned integer number
|
||||
|
||||
``<cipher_algo>``
|
||||
|
||||
* Cipher algorithm
|
||||
|
||||
* Optional: No
|
||||
|
||||
* Available options:
|
||||
|
||||
* *null*: NULL algorithm
|
||||
* *aes-128-cbc*: AES-CBC 128-bit algorithm
|
||||
|
||||
* Syntax: *cipher_algo <your algorithm>*
|
||||
|
||||
``<cipher_key>``
|
||||
|
||||
* Cipher key, NOT available when 'null' algorithm is used
|
||||
|
||||
* Optional: No, must followed by <cipher_algo> option
|
||||
|
||||
* Syntax: Hexadecimal bytes (0x0-0xFF) concatenate by colon symbol ':'.
|
||||
The number of bytes should be as same as the specified cipher algorithm
|
||||
key size.
|
||||
|
||||
For example: *cipher_key A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:
|
||||
A1:B2:C3:D4*
|
||||
|
||||
``<auth_algo>``
|
||||
|
||||
* Authentication algorithm
|
||||
|
||||
* Optional: No
|
||||
|
||||
* Available options:
|
||||
|
||||
* *null*: NULL algorithm
|
||||
* *sha1-hmac*: HMAC SHA1 algorithm
|
||||
|
||||
``<auth_key>``
|
||||
|
||||
* Authentication key, NOT available when 'null' algorithm is used
|
||||
|
||||
* Optional: No, must followed by <auth_algo> option
|
||||
|
||||
* Syntax: Hexadecimal bytes (0x0-0xFF) concatenate by colon symbol ':'.
|
||||
The number of bytes should be as same as the specified authentication
|
||||
algorithm key size.
|
||||
|
||||
For example: *auth_key A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:A1:B2:C3:D4:
|
||||
A1:B2:C3:D4*
|
||||
|
||||
``<mode>``
|
||||
|
||||
* The operation mode
|
||||
|
||||
* Optional: No
|
||||
|
||||
* Available options:
|
||||
|
||||
* *ipv4-tunnel*: Tunnel mode for IPv4 packets
|
||||
* *ipv6-tunnel*: Tunnel mode for IPv6 packets
|
||||
* *transport*: transport mode
|
||||
|
||||
* Syntax: mode XXX
|
||||
|
||||
``<src_ip>``
|
||||
|
||||
* The source IP address. This option is not available when
|
||||
transport mode is used
|
||||
|
||||
* Optional: Yes, default address 0.0.0.0 will be used
|
||||
|
||||
* Syntax:
|
||||
|
||||
* *src X.X.X.X* for IPv4
|
||||
* *src XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX* for IPv6
|
||||
|
||||
``<dst_ip>``
|
||||
|
||||
* The destination IP address. This option is not available when
|
||||
transport mode is used
|
||||
|
||||
* Optional: Yes, default address 0.0.0.0 will be used
|
||||
|
||||
* Syntax:
|
||||
|
||||
* *dst X.X.X.X* for IPv4
|
||||
* *dst XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX* for IPv6
|
||||
|
||||
Example SA rules:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
sa out 5 cipher_algo null auth_algo null mode ipv4-tunnel \
|
||||
src 172.16.1.5 dst 172.16.2.5
|
||||
|
||||
sa out 25 cipher_algo aes-128-cbc \
|
||||
cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3 \
|
||||
auth_algo sha1-hmac \
|
||||
auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3 \
|
||||
mode ipv6-tunnel \
|
||||
src 1111:1111:1111:1111:1111:1111:1111:5555 \
|
||||
dst 2222:2222:2222:2222:2222:2222:2222:5555
|
||||
|
||||
|
||||
Routing rule syntax
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The Routing rule syntax is shown as follows:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
rt <ip_ver> <src_ip> <dst_ip> <port>
|
||||
|
||||
|
||||
where each options means:
|
||||
|
||||
``<ip_ver>``
|
||||
|
||||
* IP protocol version
|
||||
|
||||
* Optional: No
|
||||
|
||||
* Available options:
|
||||
|
||||
* *ipv4*: IP protocol version 4
|
||||
* *ipv6*: IP protocol version 6
|
||||
|
||||
``<src_ip>``
|
||||
|
||||
* The source IP address and mask
|
||||
|
||||
* Optional: Yes, default address 0.0.0.0 and mask of 0 will be used
|
||||
|
||||
* Syntax:
|
||||
|
||||
* *src X.X.X.X/Y* for IPv4
|
||||
* *src XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX/Y* for IPv6
|
||||
|
||||
``<dst_ip>``
|
||||
|
||||
* The destination IP address and mask
|
||||
|
||||
* Optional: Yes, default address 0.0.0.0 and mask of 0 will be used
|
||||
|
||||
* Syntax:
|
||||
|
||||
* *dst X.X.X.X/Y* for IPv4
|
||||
* *dst XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX/Y* for IPv6
|
||||
|
||||
``<port>``
|
||||
|
||||
* The traffic output port id
|
||||
|
||||
* Optional: yes, default output port 0 will be used
|
||||
|
||||
* Syntax: *port X*
|
||||
|
||||
Example SP rules:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
rt ipv4 dst 172.16.1.5/32 port 0
|
||||
|
||||
rt ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 0
|
||||
|
@ -53,6 +53,7 @@ endif
|
||||
#
|
||||
# all source are stored in SRCS-y
|
||||
#
|
||||
SRCS-y += parser.c
|
||||
SRCS-y += ipsec.c
|
||||
SRCS-y += esp.c
|
||||
SRCS-y += sp4.c
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include <rte_cryptodev.h>
|
||||
|
||||
#include "ipsec.h"
|
||||
#include "parser.h"
|
||||
|
||||
#define RTE_LOGTYPE_IPSEC RTE_LOGTYPE_USER1
|
||||
|
||||
@ -88,8 +89,6 @@
|
||||
|
||||
#define OPTION_CONFIG "config"
|
||||
#define OPTION_SINGLE_SA "single-sa"
|
||||
#define OPTION_EP0 "ep0"
|
||||
#define OPTION_EP1 "ep1"
|
||||
|
||||
#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
|
||||
|
||||
@ -158,7 +157,6 @@ static uint32_t enabled_port_mask;
|
||||
static uint32_t unprotected_port_mask;
|
||||
static int32_t promiscuous_on = 1;
|
||||
static int32_t numa_on = 1; /**< NUMA is enabled by default. */
|
||||
static int32_t ep = -1; /**< Endpoint configuration (0 or 1) */
|
||||
static uint32_t nb_lcores;
|
||||
static uint32_t single_sa;
|
||||
static uint32_t single_sa_idx;
|
||||
@ -838,7 +836,7 @@ print_usage(const char *prgname)
|
||||
{
|
||||
printf("%s [EAL options] -- -p PORTMASK -P -u PORTMASK"
|
||||
" --"OPTION_CONFIG" (port,queue,lcore)[,(port,queue,lcore]"
|
||||
" --single-sa SAIDX --ep0|--ep1\n"
|
||||
" --single-sa SAIDX -f CONFIG_FILE\n"
|
||||
" -p PORTMASK: hexadecimal bitmask of ports to configure\n"
|
||||
" -P : enable promiscuous mode\n"
|
||||
" -u PORTMASK: hexadecimal bitmask of unprotected ports\n"
|
||||
@ -846,8 +844,8 @@ print_usage(const char *prgname)
|
||||
"rx queues configuration\n"
|
||||
" --single-sa SAIDX: use single SA index for outbound, "
|
||||
"bypassing the SP\n"
|
||||
" --ep0: Configure as Endpoint 0\n"
|
||||
" --ep1: Configure as Endpoint 1\n", prgname);
|
||||
" -f CONFIG_FILE: Configuration file path\n",
|
||||
prgname);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
@ -960,18 +958,6 @@ parse_args_long_options(struct option *lgopts, int32_t option_index)
|
||||
}
|
||||
}
|
||||
|
||||
if (__STRNCMP(optname, OPTION_EP0)) {
|
||||
printf("endpoint 0\n");
|
||||
ep = 0;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (__STRNCMP(optname, OPTION_EP1)) {
|
||||
printf("endpoint 1\n");
|
||||
ep = 1;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#undef __STRNCMP
|
||||
@ -986,14 +972,13 @@ parse_args(int32_t argc, char **argv)
|
||||
static struct option lgopts[] = {
|
||||
{OPTION_CONFIG, 1, 0, 0},
|
||||
{OPTION_SINGLE_SA, 1, 0, 0},
|
||||
{OPTION_EP0, 0, 0, 0},
|
||||
{OPTION_EP1, 0, 0, 0},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
int32_t f_present = 0;
|
||||
|
||||
argvopt = argv;
|
||||
|
||||
while ((opt = getopt_long(argc, argvopt, "p:Pu:",
|
||||
while ((opt = getopt_long(argc, argvopt, "p:Pu:f:",
|
||||
lgopts, &option_index)) != EOF) {
|
||||
|
||||
switch (opt) {
|
||||
@ -1017,6 +1002,21 @@ parse_args(int32_t argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
if (f_present == 1) {
|
||||
printf("\"-f\" option present more than "
|
||||
"once!\n");
|
||||
print_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
if (parse_cfg_file(optarg) < 0) {
|
||||
printf("parsing file \"%s\" failed\n",
|
||||
optarg);
|
||||
print_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
f_present = 1;
|
||||
break;
|
||||
case 0:
|
||||
if (parse_args_long_options(lgopts, option_index)) {
|
||||
print_usage(prgname);
|
||||
@ -1029,6 +1029,11 @@ parse_args(int32_t argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (f_present == 0) {
|
||||
printf("Mandatory option \"-f\" not present\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (optind >= 0)
|
||||
argv[optind-1] = prgname;
|
||||
|
||||
@ -1411,9 +1416,6 @@ main(int32_t argc, char **argv)
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Invalid parameters\n");
|
||||
|
||||
if (ep < 0)
|
||||
rte_exit(EXIT_FAILURE, "need to choose either EP0 or EP1\n");
|
||||
|
||||
if ((unprotected_port_mask & enabled_port_mask) !=
|
||||
unprotected_port_mask)
|
||||
rte_exit(EXIT_FAILURE, "Invalid unprotected portmask 0x%x\n",
|
||||
@ -1443,13 +1445,13 @@ main(int32_t argc, char **argv)
|
||||
if (socket_ctx[socket_id].mbuf_pool)
|
||||
continue;
|
||||
|
||||
sa_init(&socket_ctx[socket_id], socket_id, ep);
|
||||
sa_init(&socket_ctx[socket_id], socket_id);
|
||||
|
||||
sp4_init(&socket_ctx[socket_id], socket_id, ep);
|
||||
sp4_init(&socket_ctx[socket_id], socket_id);
|
||||
|
||||
sp6_init(&socket_ctx[socket_id], socket_id, ep);
|
||||
sp6_init(&socket_ctx[socket_id], socket_id);
|
||||
|
||||
rt_init(&socket_ctx[socket_id], socket_id, ep);
|
||||
rt_init(&socket_ctx[socket_id], socket_id);
|
||||
|
||||
pool_init(&socket_ctx[socket_id], socket_id, NB_MBUF);
|
||||
}
|
||||
|
@ -90,6 +90,8 @@ struct ip_addr {
|
||||
} ip;
|
||||
};
|
||||
|
||||
#define MAX_KEY_SIZE 20
|
||||
|
||||
struct ipsec_sa {
|
||||
uint32_t spi;
|
||||
uint32_t cdev_id_qp;
|
||||
@ -106,6 +108,10 @@ struct ipsec_sa {
|
||||
#define TRANSPORT (1 << 2)
|
||||
struct ip_addr src;
|
||||
struct ip_addr dst;
|
||||
uint8_t cipher_key[MAX_KEY_SIZE];
|
||||
uint16_t cipher_key_len;
|
||||
uint8_t auth_key[MAX_KEY_SIZE];
|
||||
uint16_t auth_key_len;
|
||||
struct rte_crypto_sym_xform *xforms;
|
||||
} __rte_cache_aligned;
|
||||
|
||||
@ -183,15 +189,15 @@ outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
|
||||
struct ipsec_sa *sa[], uint16_t nb_pkts);
|
||||
|
||||
void
|
||||
sp4_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
|
||||
sp4_init(struct socket_ctx *ctx, int32_t socket_id);
|
||||
|
||||
void
|
||||
sp6_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
|
||||
sp6_init(struct socket_ctx *ctx, int32_t socket_id);
|
||||
|
||||
void
|
||||
sa_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
|
||||
sa_init(struct socket_ctx *ctx, int32_t socket_id);
|
||||
|
||||
void
|
||||
rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep);
|
||||
rt_init(struct socket_ctx *ctx, int32_t socket_id);
|
||||
|
||||
#endif /* __IPSEC_H__ */
|
||||
|
599
examples/ipsec-secgw/parser.c
Normal file
599
examples/ipsec-secgw/parser.c
Normal file
@ -0,0 +1,599 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <rte_common.h>
|
||||
#include <rte_crypto.h>
|
||||
|
||||
#include <cmdline_parse_string.h>
|
||||
#include <cmdline_parse_num.h>
|
||||
#include <cmdline_parse_ipaddr.h>
|
||||
#include <cmdline_socket.h>
|
||||
#include <cmdline.h>
|
||||
|
||||
#include "ipsec.h"
|
||||
#include "parser.h"
|
||||
|
||||
#define PARSE_DELIMITER " \f\n\r\t\v"
|
||||
static int
|
||||
parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if ((string == NULL) ||
|
||||
(tokens == NULL) ||
|
||||
(*n_tokens < 1))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < *n_tokens; i++) {
|
||||
tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
|
||||
if (tokens[i] == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((i == *n_tokens) &&
|
||||
(NULL != strtok_r(string, PARSE_DELIMITER, &string)))
|
||||
return -E2BIG;
|
||||
|
||||
*n_tokens = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define INADDRSZ 4
|
||||
#define IN6ADDRSZ 16
|
||||
|
||||
/* int
|
||||
* inet_pton4(src, dst)
|
||||
* like inet_aton() but without all the hexadecimal and shorthand.
|
||||
* return:
|
||||
* 1 if `src' is a valid dotted quad, else 0.
|
||||
* notice:
|
||||
* does not touch `dst' unless it's returning 1.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton4(const char *src, unsigned char *dst)
|
||||
{
|
||||
static const char digits[] = "0123456789";
|
||||
int saw_digit, octets, ch;
|
||||
unsigned char tmp[INADDRSZ], *tp;
|
||||
|
||||
saw_digit = 0;
|
||||
octets = 0;
|
||||
*(tp = tmp) = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
pch = strchr(digits, ch);
|
||||
if (pch != NULL) {
|
||||
unsigned int new = *tp * 10 + (pch - digits);
|
||||
|
||||
if (new > 255)
|
||||
return 0;
|
||||
if (!saw_digit) {
|
||||
if (++octets > 4)
|
||||
return 0;
|
||||
saw_digit = 1;
|
||||
}
|
||||
*tp = (unsigned char)new;
|
||||
} else if (ch == '.' && saw_digit) {
|
||||
if (octets == 4)
|
||||
return 0;
|
||||
*++tp = 0;
|
||||
saw_digit = 0;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
if (octets < 4)
|
||||
return 0;
|
||||
|
||||
memcpy(dst, tmp, INADDRSZ);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* int
|
||||
* inet_pton6(src, dst)
|
||||
* convert presentation level address to network order binary form.
|
||||
* return:
|
||||
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
|
||||
* notice:
|
||||
* (1) does not touch `dst' unless it's returning 1.
|
||||
* (2) :: in a full address is silently ignored.
|
||||
* credit:
|
||||
* inspired by Mark Andrews.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton6(const char *src, unsigned char *dst)
|
||||
{
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
|
||||
const char *xdigits = 0, *curtok = 0;
|
||||
int ch = 0, saw_xdigit = 0, count_xdigit = 0;
|
||||
unsigned int val = 0;
|
||||
unsigned dbloct_count = 0;
|
||||
|
||||
memset((tp = tmp), '\0', IN6ADDRSZ);
|
||||
endp = tp + IN6ADDRSZ;
|
||||
colonp = NULL;
|
||||
/* Leading :: requires some special handling. */
|
||||
if (*src == ':')
|
||||
if (*++src != ':')
|
||||
return 0;
|
||||
curtok = src;
|
||||
saw_xdigit = count_xdigit = 0;
|
||||
val = 0;
|
||||
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
pch = strchr((xdigits = xdigits_l), ch);
|
||||
if (pch == NULL)
|
||||
pch = strchr((xdigits = xdigits_u), ch);
|
||||
if (pch != NULL) {
|
||||
if (count_xdigit >= 4)
|
||||
return 0;
|
||||
val <<= 4;
|
||||
val |= (pch - xdigits);
|
||||
if (val > 0xffff)
|
||||
return 0;
|
||||
saw_xdigit = 1;
|
||||
count_xdigit++;
|
||||
continue;
|
||||
}
|
||||
if (ch == ':') {
|
||||
curtok = src;
|
||||
if (!saw_xdigit) {
|
||||
if (colonp)
|
||||
return 0;
|
||||
colonp = tp;
|
||||
continue;
|
||||
} else if (*src == '\0') {
|
||||
return 0;
|
||||
}
|
||||
if (tp + sizeof(int16_t) > endp)
|
||||
return 0;
|
||||
*tp++ = (unsigned char) ((val >> 8) & 0xff);
|
||||
*tp++ = (unsigned char) (val & 0xff);
|
||||
saw_xdigit = 0;
|
||||
count_xdigit = 0;
|
||||
val = 0;
|
||||
dbloct_count++;
|
||||
continue;
|
||||
}
|
||||
if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
|
||||
inet_pton4(curtok, tp) > 0) {
|
||||
tp += INADDRSZ;
|
||||
saw_xdigit = 0;
|
||||
dbloct_count += 2;
|
||||
break; /* '\0' was seen by inet_pton4(). */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (saw_xdigit) {
|
||||
if (tp + sizeof(int16_t) > endp)
|
||||
return 0;
|
||||
*tp++ = (unsigned char) ((val >> 8) & 0xff);
|
||||
*tp++ = (unsigned char) (val & 0xff);
|
||||
dbloct_count++;
|
||||
}
|
||||
if (colonp != NULL) {
|
||||
/* if we already have 8 double octets, having a colon
|
||||
* means error */
|
||||
if (dbloct_count == 8)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
const int n = tp - colonp;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
endp[-i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
if (tp != endp)
|
||||
return 0;
|
||||
memcpy(dst, tmp, IN6ADDRSZ);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
|
||||
{
|
||||
char ip_str[256] = {0};
|
||||
char *pch;
|
||||
|
||||
pch = strchr(token, '/');
|
||||
if (pch != NULL) {
|
||||
strncpy(ip_str, token, pch - token);
|
||||
pch += 1;
|
||||
if (is_str_num(pch) != 0)
|
||||
return -EINVAL;
|
||||
if (mask)
|
||||
*mask = atoi(pch);
|
||||
} else {
|
||||
strncpy(ip_str, token, sizeof(ip_str));
|
||||
if (mask)
|
||||
*mask = 0;
|
||||
}
|
||||
|
||||
if (strlen(ip_str) >= INET_ADDRSTRLEN)
|
||||
return -EINVAL;
|
||||
|
||||
if (inet_pton4(ip_str, (unsigned char *)ipv4) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask)
|
||||
{
|
||||
char ip_str[256] = {0};
|
||||
char *pch;
|
||||
|
||||
pch = strchr(token, '/');
|
||||
if (pch != NULL) {
|
||||
strncpy(ip_str, token, pch - token);
|
||||
pch += 1;
|
||||
if (is_str_num(pch) != 0)
|
||||
return -EINVAL;
|
||||
if (mask)
|
||||
*mask = atoi(pch);
|
||||
} else {
|
||||
strncpy(ip_str, token, sizeof(ip_str));
|
||||
if (mask)
|
||||
*mask = 0;
|
||||
}
|
||||
|
||||
if (strlen(ip_str) >= INET6_ADDRSTRLEN)
|
||||
return -EINVAL;
|
||||
|
||||
if (inet_pton6(ip_str, (unsigned char *)ipv6) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parse_range(const char *token, uint16_t *low, uint16_t *high)
|
||||
{
|
||||
char ch;
|
||||
char num_str[20];
|
||||
uint32_t pos;
|
||||
int range_low = -1;
|
||||
int range_high = -1;
|
||||
|
||||
if (!low || !high)
|
||||
return -1;
|
||||
|
||||
memset(num_str, 0, 20);
|
||||
pos = 0;
|
||||
|
||||
while ((ch = *token++) != '\0') {
|
||||
if (isdigit(ch)) {
|
||||
if (pos >= 19)
|
||||
return -1;
|
||||
num_str[pos++] = ch;
|
||||
} else if (ch == ':') {
|
||||
if (range_low != -1)
|
||||
return -1;
|
||||
range_low = atoi(num_str);
|
||||
memset(num_str, 0, 20);
|
||||
pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(num_str) == 0)
|
||||
return -1;
|
||||
|
||||
range_high = atoi(num_str);
|
||||
|
||||
*low = (uint16_t)range_low;
|
||||
*high = (uint16_t)range_high;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** sp add parse */
|
||||
struct cfg_sp_add_cfg_item {
|
||||
cmdline_fixed_string_t sp_keyword;
|
||||
cmdline_multi_string_t multi_string;
|
||||
};
|
||||
|
||||
static void
|
||||
cfg_sp_add_cfg_item_parsed(void *parsed_result,
|
||||
__rte_unused struct cmdline *cl, void *data)
|
||||
{
|
||||
struct cfg_sp_add_cfg_item *params = parsed_result;
|
||||
char *tokens[32];
|
||||
uint32_t n_tokens = RTE_DIM(tokens);
|
||||
struct parse_status *status = (struct parse_status *)data;
|
||||
|
||||
APP_CHECK((parse_tokenize_string(params->multi_string, tokens,
|
||||
&n_tokens) == 0), status, "too many arguments");
|
||||
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
if (strcmp(tokens[0], "ipv4") == 0) {
|
||||
parse_sp4_tokens(tokens, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
} else if (strcmp(tokens[0], "ipv6") == 0) {
|
||||
parse_sp6_tokens(tokens, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
} else {
|
||||
APP_CHECK(0, status, "unrecognizable input %s\n",
|
||||
tokens[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static cmdline_parse_token_string_t cfg_sp_add_sp_str =
|
||||
TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item,
|
||||
sp_keyword, "sp");
|
||||
|
||||
static cmdline_parse_token_string_t cfg_sp_add_multi_str =
|
||||
TOKEN_STRING_INITIALIZER(struct cfg_sp_add_cfg_item, multi_string,
|
||||
TOKEN_STRING_MULTI);
|
||||
|
||||
cmdline_parse_inst_t cfg_sp_add_rule = {
|
||||
.f = cfg_sp_add_cfg_item_parsed,
|
||||
.data = NULL,
|
||||
.help_str = "",
|
||||
.tokens = {
|
||||
(void *) &cfg_sp_add_sp_str,
|
||||
(void *) &cfg_sp_add_multi_str,
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
||||
/* sa add parse */
|
||||
struct cfg_sa_add_cfg_item {
|
||||
cmdline_fixed_string_t sa_keyword;
|
||||
cmdline_multi_string_t multi_string;
|
||||
};
|
||||
|
||||
static void
|
||||
cfg_sa_add_cfg_item_parsed(void *parsed_result,
|
||||
__rte_unused struct cmdline *cl, void *data)
|
||||
{
|
||||
struct cfg_sa_add_cfg_item *params = parsed_result;
|
||||
char *tokens[32];
|
||||
uint32_t n_tokens = RTE_DIM(tokens);
|
||||
struct parse_status *status = (struct parse_status *)data;
|
||||
|
||||
APP_CHECK(parse_tokenize_string(params->multi_string, tokens,
|
||||
&n_tokens) == 0, status, "too many arguments\n");
|
||||
|
||||
parse_sa_tokens(tokens, n_tokens, status);
|
||||
}
|
||||
|
||||
static cmdline_parse_token_string_t cfg_sa_add_sa_str =
|
||||
TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item,
|
||||
sa_keyword, "sa");
|
||||
|
||||
static cmdline_parse_token_string_t cfg_sa_add_multi_str =
|
||||
TOKEN_STRING_INITIALIZER(struct cfg_sa_add_cfg_item, multi_string,
|
||||
TOKEN_STRING_MULTI);
|
||||
|
||||
cmdline_parse_inst_t cfg_sa_add_rule = {
|
||||
.f = cfg_sa_add_cfg_item_parsed,
|
||||
.data = NULL,
|
||||
.help_str = "",
|
||||
.tokens = {
|
||||
(void *) &cfg_sa_add_sa_str,
|
||||
(void *) &cfg_sa_add_multi_str,
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
||||
/* rt add parse */
|
||||
struct cfg_rt_add_cfg_item {
|
||||
cmdline_fixed_string_t rt_keyword;
|
||||
cmdline_multi_string_t multi_string;
|
||||
};
|
||||
|
||||
static void
|
||||
cfg_rt_add_cfg_item_parsed(void *parsed_result,
|
||||
__rte_unused struct cmdline *cl, void *data)
|
||||
{
|
||||
struct cfg_rt_add_cfg_item *params = parsed_result;
|
||||
char *tokens[32];
|
||||
uint32_t n_tokens = RTE_DIM(tokens);
|
||||
struct parse_status *status = (struct parse_status *)data;
|
||||
|
||||
APP_CHECK(parse_tokenize_string(
|
||||
params->multi_string, tokens, &n_tokens) == 0,
|
||||
status, "too many arguments\n");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
parse_rt_tokens(tokens, n_tokens, status);
|
||||
}
|
||||
|
||||
static cmdline_parse_token_string_t cfg_rt_add_rt_str =
|
||||
TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item,
|
||||
rt_keyword, "rt");
|
||||
|
||||
static cmdline_parse_token_string_t cfg_rt_add_multi_str =
|
||||
TOKEN_STRING_INITIALIZER(struct cfg_rt_add_cfg_item, multi_string,
|
||||
TOKEN_STRING_MULTI);
|
||||
|
||||
cmdline_parse_inst_t cfg_rt_add_rule = {
|
||||
.f = cfg_rt_add_cfg_item_parsed,
|
||||
.data = NULL,
|
||||
.help_str = "",
|
||||
.tokens = {
|
||||
(void *) &cfg_rt_add_rt_str,
|
||||
(void *) &cfg_rt_add_multi_str,
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
||||
/** set of cfg items */
|
||||
cmdline_parse_ctx_t ipsec_ctx[] = {
|
||||
(cmdline_parse_inst_t *)&cfg_sp_add_rule,
|
||||
(cmdline_parse_inst_t *)&cfg_sa_add_rule,
|
||||
(cmdline_parse_inst_t *)&cfg_rt_add_rule,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int
|
||||
parse_cfg_file(const char *cfg_filename)
|
||||
{
|
||||
struct cmdline *cl = cmdline_stdin_new(ipsec_ctx, "");
|
||||
FILE *f = fopen(cfg_filename, "r");
|
||||
char str[1024] = {0}, *get_s = NULL;
|
||||
uint32_t line_num = 0;
|
||||
struct parse_status status = {0};
|
||||
|
||||
if (f == NULL) {
|
||||
rte_panic("Error: invalid file descriptor %s\n",
|
||||
cfg_filename);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (cl == NULL) {
|
||||
rte_panic("Error: cannot create cmdline instance\n");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
cfg_sp_add_rule.data = &status;
|
||||
cfg_sa_add_rule.data = &status;
|
||||
cfg_rt_add_rule.data = &status;
|
||||
|
||||
do {
|
||||
char oneline[1024];
|
||||
|
||||
get_s = fgets(oneline, 1024, f);
|
||||
if (get_s) {
|
||||
char *pos;
|
||||
|
||||
line_num++;
|
||||
|
||||
if (strlen(oneline) > 1022) {
|
||||
rte_panic("%s:%u: error: the line "
|
||||
"contains more characters the "
|
||||
"parser can handle\n",
|
||||
cfg_filename, line_num);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* process comment char '#' */
|
||||
if (oneline[0] == '#')
|
||||
continue;
|
||||
|
||||
pos = strchr(oneline, '#');
|
||||
if (pos != NULL)
|
||||
*pos = '\0';
|
||||
|
||||
/* process line concatenator '\' */
|
||||
pos = strchr(oneline, 92);
|
||||
if (pos != NULL) {
|
||||
if (pos != oneline+strlen(oneline) - 2) {
|
||||
rte_panic("%s:%u: error: no "
|
||||
"character should exist "
|
||||
"after '\\' symbol\n",
|
||||
cfg_filename, line_num);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
*pos = '\0';
|
||||
|
||||
if (strlen(oneline) + strlen(str) > 1022) {
|
||||
rte_panic("%s:%u: error: the "
|
||||
"concatenated line "
|
||||
"contains more characters "
|
||||
"the parser can handle\n",
|
||||
cfg_filename, line_num);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
strncpy(str + strlen(str), oneline,
|
||||
strlen(oneline));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* copy the line to str and process */
|
||||
if (strlen(oneline) + strlen(str) > 1022) {
|
||||
rte_panic("%s:%u: error: the line "
|
||||
"contains more characters the "
|
||||
"parser can handle\n",
|
||||
cfg_filename, line_num);
|
||||
goto error_exit;
|
||||
}
|
||||
strncpy(str + strlen(str), oneline,
|
||||
strlen(oneline));
|
||||
|
||||
str[strlen(str)] = '\n';
|
||||
if (cmdline_parse(cl, str) < 0) {
|
||||
rte_panic("%s:%u: error: parsing \"%s\" "
|
||||
"failed\n", cfg_filename,
|
||||
line_num, str);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (status.status < 0) {
|
||||
rte_panic("%s:%u: error: %s",
|
||||
cfg_filename, line_num,
|
||||
status.parse_msg);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
memset(str, 0, 1024);
|
||||
}
|
||||
} while (get_s != NULL);
|
||||
|
||||
cmdline_stdin_exit(cl);
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
|
||||
error_exit:
|
||||
if (cl)
|
||||
cmdline_stdin_exit(cl);
|
||||
if (f)
|
||||
fclose(f);
|
||||
|
||||
return -1;
|
||||
}
|
116
examples/ipsec-secgw/parser.h
Normal file
116
examples/ipsec-secgw/parser.h
Normal file
@ -0,0 +1,116 @@
|
||||
/* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#ifndef __PARSER_H
|
||||
#define __PARSER_H
|
||||
|
||||
struct parse_status {
|
||||
int status;
|
||||
char parse_msg[256];
|
||||
};
|
||||
|
||||
#define APP_CHECK(exp, status, fmt, ...) \
|
||||
do { \
|
||||
if (!(exp)) { \
|
||||
sprintf(status->parse_msg, fmt "\n", \
|
||||
## __VA_ARGS__); \
|
||||
status->status = -1; \
|
||||
} else \
|
||||
status->status = 0; \
|
||||
} while (0)
|
||||
|
||||
#define APP_CHECK_PRESENCE(val, str, status) \
|
||||
APP_CHECK(val == 0, status, \
|
||||
"item \"%s\" already present", str)
|
||||
|
||||
#define APP_CHECK_TOKEN_EQUAL(tokens, index, ref, status) \
|
||||
APP_CHECK(strcmp(tokens[index], ref) == 0, status, \
|
||||
"unrecognized input \"%s\": expect \"%s\"\n", \
|
||||
tokens[index], ref)
|
||||
|
||||
static inline int
|
||||
is_str_num(const char *str)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < strlen(str); i++)
|
||||
if (!isdigit(str[i]))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define APP_CHECK_TOKEN_IS_NUM(tokens, index, status) \
|
||||
APP_CHECK(is_str_num(tokens[index]) == 0, status, \
|
||||
"input \"%s\" is not valid number string", tokens[index])
|
||||
|
||||
|
||||
#define INCREMENT_TOKEN_INDEX(index, max_num, status) \
|
||||
do { \
|
||||
APP_CHECK(index + 1 < max_num, status, "reaching the end of " \
|
||||
"the token array"); \
|
||||
index++; \
|
||||
} while (0)
|
||||
|
||||
int
|
||||
parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask);
|
||||
|
||||
int
|
||||
parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask);
|
||||
|
||||
int
|
||||
parse_range(const char *token, uint16_t *low, uint16_t *high);
|
||||
|
||||
void
|
||||
parse_sp4_tokens(char **tokens, uint32_t n_tokens,
|
||||
struct parse_status *status);
|
||||
|
||||
void
|
||||
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
|
||||
struct parse_status *status);
|
||||
|
||||
void
|
||||
parse_sa_tokens(char **tokens, uint32_t n_tokens,
|
||||
struct parse_status *status);
|
||||
|
||||
void
|
||||
parse_rt_tokens(char **tokens, uint32_t n_tokens,
|
||||
struct parse_status *status);
|
||||
|
||||
int
|
||||
parse_cfg_file(const char *cfg_filename);
|
||||
|
||||
#endif
|
@ -41,6 +41,7 @@
|
||||
#include <rte_ip.h>
|
||||
|
||||
#include "ipsec.h"
|
||||
#include "parser.h"
|
||||
|
||||
#define RT_IPV4_MAX_RULES 1024
|
||||
#define RT_IPV6_MAX_RULES 1024
|
||||
@ -57,135 +58,106 @@ struct ip6_route {
|
||||
uint8_t if_out;
|
||||
};
|
||||
|
||||
static struct ip4_route rt_ip4_ep0[] = {
|
||||
/* Outbound */
|
||||
/* Tunnels */
|
||||
{ IPv4(172, 16, 2, 5), 32, 0 },
|
||||
{ IPv4(172, 16, 2, 6), 32, 1 },
|
||||
/* Transport */
|
||||
{ IPv4(192, 168, 175, 0), 24, 0 },
|
||||
{ IPv4(192, 168, 176, 0), 24, 1 },
|
||||
/* Bypass */
|
||||
{ IPv4(192, 168, 240, 0), 24, 0 },
|
||||
{ IPv4(192, 168, 241, 0), 24, 1 },
|
||||
struct ip4_route rt_ip4[RT_IPV4_MAX_RULES];
|
||||
uint32_t nb_rt_ip4;
|
||||
|
||||
/* Inbound */
|
||||
/* Tunnels */
|
||||
{ IPv4(192, 168, 115, 0), 24, 2 },
|
||||
{ IPv4(192, 168, 116, 0), 24, 3 },
|
||||
{ IPv4(192, 168, 65, 0), 24, 2 },
|
||||
{ IPv4(192, 168, 66, 0), 24, 3 },
|
||||
/* Transport */
|
||||
{ IPv4(192, 168, 185, 0), 24, 2 },
|
||||
{ IPv4(192, 168, 186, 0), 24, 3 },
|
||||
/* NULL */
|
||||
{ IPv4(192, 168, 210, 0), 24, 2 },
|
||||
{ IPv4(192, 168, 211, 0), 24, 3 },
|
||||
/* Bypass */
|
||||
{ IPv4(192, 168, 245, 0), 24, 2 },
|
||||
{ IPv4(192, 168, 246, 0), 24, 3 },
|
||||
};
|
||||
|
||||
static struct ip6_route rt_ip6_ep0[] = {
|
||||
/* Outbound */
|
||||
/* Tunnels */
|
||||
{ { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x55, 0x55 }, 116, 0 },
|
||||
{ { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x66, 0x66 }, 116, 1 },
|
||||
/* Transport */
|
||||
{ { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 0 },
|
||||
{ { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 1 },
|
||||
/* Inbound */
|
||||
/* Tunnels */
|
||||
{ { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
|
||||
{ { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
|
||||
{ { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
|
||||
0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
|
||||
{ { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66,
|
||||
0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
|
||||
/* Transport */
|
||||
{ { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
|
||||
{ { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
|
||||
};
|
||||
|
||||
static struct ip4_route rt_ip4_ep1[] = {
|
||||
/* Outbound */
|
||||
/* Tunnels */
|
||||
{ IPv4(172, 16, 1, 5), 32, 0 },
|
||||
{ IPv4(172, 16, 1, 6), 32, 1 },
|
||||
/* Transport */
|
||||
{ IPv4(192, 168, 185, 0), 24, 0 },
|
||||
{ IPv4(192, 168, 186, 0), 24, 1 },
|
||||
/* Bypass */
|
||||
{ IPv4(192, 168, 245, 0), 24, 0 },
|
||||
{ IPv4(192, 168, 246, 0), 24, 1 },
|
||||
|
||||
/* Inbound */
|
||||
/* Tunnels */
|
||||
{ IPv4(192, 168, 105, 0), 24, 2 },
|
||||
{ IPv4(192, 168, 106, 0), 24, 3 },
|
||||
{ IPv4(192, 168, 55, 0), 24, 2 },
|
||||
{ IPv4(192, 168, 56, 0), 24, 3 },
|
||||
/* Transport */
|
||||
{ IPv4(192, 168, 175, 0), 24, 2 },
|
||||
{ IPv4(192, 168, 176, 0), 24, 3 },
|
||||
/* NULL */
|
||||
{ IPv4(192, 168, 200, 0), 24, 2 },
|
||||
{ IPv4(192, 168, 201, 0), 24, 3 },
|
||||
/* Bypass */
|
||||
{ IPv4(192, 168, 240, 0), 24, 2 },
|
||||
{ IPv4(192, 168, 241, 0), 24, 3 },
|
||||
};
|
||||
|
||||
static struct ip6_route rt_ip6_ep1[] = {
|
||||
/* Outbound */
|
||||
/* Tunnels */
|
||||
{ { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x55, 0x55 }, 116, 0 },
|
||||
{ { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x66, 0x66 }, 116, 1 },
|
||||
/* Transport */
|
||||
{ { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 0 },
|
||||
{ { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 1 },
|
||||
|
||||
/* Inbound */
|
||||
/* Tunnels */
|
||||
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
|
||||
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
|
||||
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
|
||||
0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
|
||||
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66,
|
||||
0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
|
||||
/* Transport */
|
||||
{ { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 2 },
|
||||
{ { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 3 },
|
||||
};
|
||||
struct ip6_route rt_ip6[RT_IPV4_MAX_RULES];
|
||||
uint32_t nb_rt_ip6;
|
||||
|
||||
void
|
||||
rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
|
||||
parse_rt_tokens(char **tokens, uint32_t n_tokens,
|
||||
struct parse_status *status)
|
||||
{
|
||||
uint32_t ti;
|
||||
uint32_t *n_rts = NULL;
|
||||
struct ip4_route *route_ipv4 = NULL;
|
||||
struct ip6_route *route_ipv6 = NULL;
|
||||
|
||||
if (strcmp(tokens[0], "ipv4") == 0) {
|
||||
n_rts = &nb_rt_ip4;
|
||||
route_ipv4 = &rt_ip4[*n_rts];
|
||||
|
||||
APP_CHECK(*n_rts <= RT_IPV4_MAX_RULES - 1, status,
|
||||
"too many rt rules, abort insertion\n");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
} else if (strcmp(tokens[0], "ipv6") == 0) {
|
||||
n_rts = &nb_rt_ip6;
|
||||
route_ipv6 = &rt_ip6[*n_rts];
|
||||
|
||||
APP_CHECK(*n_rts <= RT_IPV6_MAX_RULES - 1, status,
|
||||
"too many rt rules, abort insertion\n");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
} else {
|
||||
APP_CHECK(0, status, "unrecognized input \"%s\"",
|
||||
tokens[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
for (ti = 1; ti < n_tokens; ti++) {
|
||||
if (strcmp(tokens[ti], "dst") == 0) {
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
if (route_ipv4 != NULL) {
|
||||
struct in_addr ip;
|
||||
uint32_t depth = 0;
|
||||
|
||||
APP_CHECK(parse_ipv4_addr(tokens[ti],
|
||||
&ip, &depth) == 0, status,
|
||||
"unrecognized input \"%s\", "
|
||||
"expect valid ipv4 addr",
|
||||
tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
route_ipv4->ip = rte_bswap32(
|
||||
(uint32_t)ip.s_addr);
|
||||
route_ipv4->depth = (uint8_t)depth;
|
||||
} else {
|
||||
struct in6_addr ip;
|
||||
uint32_t depth;
|
||||
|
||||
APP_CHECK(parse_ipv6_addr(tokens[ti],
|
||||
&ip, &depth) == 0, status,
|
||||
"unrecognized input \"%s\", "
|
||||
"expect valid ipv6 address",
|
||||
tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
memcpy(route_ipv6->ip, ip.s6_addr, 16);
|
||||
route_ipv6->depth = (uint8_t)depth;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "port") == 0) {
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
if (route_ipv4 != NULL)
|
||||
route_ipv4->if_out = atoi(tokens[ti]);
|
||||
else
|
||||
route_ipv6->if_out = atoi(tokens[ti]);
|
||||
}
|
||||
}
|
||||
|
||||
*n_rts = *n_rts + 1;
|
||||
}
|
||||
|
||||
void
|
||||
rt_init(struct socket_ctx *ctx, int32_t socket_id)
|
||||
{
|
||||
char name[PATH_MAX];
|
||||
uint32_t i;
|
||||
int32_t ret;
|
||||
struct rte_lpm *lpm;
|
||||
struct rte_lpm6 *lpm6;
|
||||
struct ip4_route *rt;
|
||||
struct ip6_route *rt6;
|
||||
char a, b, c, d;
|
||||
uint32_t nb_routes, nb_routes6;
|
||||
struct rte_lpm_config conf = { 0 };
|
||||
struct rte_lpm6_config conf6 = { 0 };
|
||||
|
||||
@ -200,23 +172,12 @@ rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
|
||||
rte_exit(EXIT_FAILURE, "IPv6 Routing Table for socket %u "
|
||||
"already initialized\n", socket_id);
|
||||
|
||||
if (nb_rt_ip4 == 0 && nb_rt_ip6 == 0)
|
||||
RTE_LOG(WARNING, IPSEC, "No Routing rule specified\n");
|
||||
|
||||
printf("Creating IPv4 Routing Table (RT) context with %u max routes\n",
|
||||
RT_IPV4_MAX_RULES);
|
||||
|
||||
if (ep == 0) {
|
||||
rt = rt_ip4_ep0;
|
||||
nb_routes = RTE_DIM(rt_ip4_ep0);
|
||||
rt6 = rt_ip6_ep0;
|
||||
nb_routes6 = RTE_DIM(rt_ip6_ep0);
|
||||
} else if (ep == 1) {
|
||||
rt = rt_ip4_ep1;
|
||||
nb_routes = RTE_DIM(rt_ip4_ep1);
|
||||
rt6 = rt_ip6_ep1;
|
||||
nb_routes6 = RTE_DIM(rt_ip6_ep1);
|
||||
} else
|
||||
rte_exit(EXIT_FAILURE, "Invalid EP value %u. Only 0 or 1 "
|
||||
"supported.\n", ep);
|
||||
|
||||
/* create the LPM table */
|
||||
snprintf(name, sizeof(name), "%s_%u", "rt_ip4", socket_id);
|
||||
conf.max_rules = RT_IPV4_MAX_RULES;
|
||||
@ -227,15 +188,17 @@ rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
|
||||
"on socket %d\n", name, socket_id);
|
||||
|
||||
/* populate the LPM table */
|
||||
for (i = 0; i < nb_routes; i++) {
|
||||
ret = rte_lpm_add(lpm, rt[i].ip, rt[i].depth, rt[i].if_out);
|
||||
for (i = 0; i < nb_rt_ip4; i++) {
|
||||
ret = rte_lpm_add(lpm, rt_ip4[i].ip, rt_ip4[i].depth,
|
||||
rt_ip4[i].if_out);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Fail to add entry num %u to %s "
|
||||
"LPM table on socket %d\n", i, name, socket_id);
|
||||
|
||||
uint32_t_to_char(rt[i].ip, &a, &b, &c, &d);
|
||||
uint32_t_to_char(rt_ip4[i].ip, &a, &b, &c, &d);
|
||||
printf("LPM: Adding route %hhu.%hhu.%hhu.%hhu/%hhu (%hhu)\n",
|
||||
a, b, c, d, rt[i].depth, rt[i].if_out);
|
||||
a, b, c, d, rt_ip4[i].depth,
|
||||
rt_ip4[i].if_out);
|
||||
}
|
||||
|
||||
snprintf(name, sizeof(name), "%s_%u", "rt_ip6", socket_id);
|
||||
@ -247,24 +210,24 @@ rt_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
|
||||
"on socket %d\n", name, socket_id);
|
||||
|
||||
/* populate the LPM table */
|
||||
for (i = 0; i < nb_routes6; i++) {
|
||||
ret = rte_lpm6_add(lpm6, rt6[i].ip, rt6[i].depth,
|
||||
rt6[i].if_out);
|
||||
for (i = 0; i < nb_rt_ip6; i++) {
|
||||
ret = rte_lpm6_add(lpm6, rt_ip6[i].ip, rt_ip6[i].depth,
|
||||
rt_ip6[i].if_out);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Fail to add entry num %u to %s "
|
||||
"LPM table on socket %d\n", i, name, socket_id);
|
||||
|
||||
printf("LPM6: Adding route "
|
||||
" %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hhx (%hhx)\n",
|
||||
(uint16_t)((rt6[i].ip[0] << 8) | rt6[i].ip[1]),
|
||||
(uint16_t)((rt6[i].ip[2] << 8) | rt6[i].ip[3]),
|
||||
(uint16_t)((rt6[i].ip[4] << 8) | rt6[i].ip[5]),
|
||||
(uint16_t)((rt6[i].ip[6] << 8) | rt6[i].ip[7]),
|
||||
(uint16_t)((rt6[i].ip[8] << 8) | rt6[i].ip[9]),
|
||||
(uint16_t)((rt6[i].ip[10] << 8) | rt6[i].ip[11]),
|
||||
(uint16_t)((rt6[i].ip[12] << 8) | rt6[i].ip[13]),
|
||||
(uint16_t)((rt6[i].ip[14] << 8) | rt6[i].ip[15]),
|
||||
rt6[i].depth, rt6[i].if_out);
|
||||
(uint16_t)((rt_ip6[i].ip[0] << 8) | rt_ip6[i].ip[1]),
|
||||
(uint16_t)((rt_ip6[i].ip[2] << 8) | rt_ip6[i].ip[3]),
|
||||
(uint16_t)((rt_ip6[i].ip[4] << 8) | rt_ip6[i].ip[5]),
|
||||
(uint16_t)((rt_ip6[i].ip[6] << 8) | rt_ip6[i].ip[7]),
|
||||
(uint16_t)((rt_ip6[i].ip[8] << 8) | rt_ip6[i].ip[9]),
|
||||
(uint16_t)((rt_ip6[i].ip[10] << 8) | rt_ip6[i].ip[11]),
|
||||
(uint16_t)((rt_ip6[i].ip[12] << 8) | rt_ip6[i].ip[13]),
|
||||
(uint16_t)((rt_ip6[i].ip[14] << 8) | rt_ip6[i].ip[15]),
|
||||
rt_ip6[i].depth, rt_ip6[i].if_out);
|
||||
}
|
||||
|
||||
ctx->rt_ip4 = (struct rt_ctx *)lpm;
|
||||
|
@ -48,243 +48,457 @@
|
||||
|
||||
#include "ipsec.h"
|
||||
#include "esp.h"
|
||||
#include "parser.h"
|
||||
|
||||
/* SAs Outbound */
|
||||
const struct ipsec_sa sa_out[] = {
|
||||
struct supported_cipher_algo {
|
||||
const char *keyword;
|
||||
enum rte_crypto_cipher_algorithm algo;
|
||||
uint16_t iv_len;
|
||||
uint16_t block_size;
|
||||
uint16_t key_len;
|
||||
};
|
||||
|
||||
struct supported_auth_algo {
|
||||
const char *keyword;
|
||||
enum rte_crypto_auth_algorithm algo;
|
||||
uint16_t digest_len;
|
||||
uint16_t key_len;
|
||||
};
|
||||
|
||||
const struct supported_cipher_algo cipher_algos[] = {
|
||||
{
|
||||
.spi = 5,
|
||||
.src.ip.ip4 = IPv4(172, 16, 1, 5),
|
||||
.dst.ip.ip4 = IPv4(172, 16, 2, 5),
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = IP4_TUNNEL
|
||||
},
|
||||
{
|
||||
.spi = 6,
|
||||
.src.ip.ip4 = IPv4(172, 16, 1, 6),
|
||||
.dst.ip.ip4 = IPv4(172, 16, 2, 6),
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = IP4_TUNNEL
|
||||
},
|
||||
{
|
||||
.spi = 10,
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = TRANSPORT
|
||||
},
|
||||
{
|
||||
.spi = 11,
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = TRANSPORT
|
||||
},
|
||||
{
|
||||
.spi = 15,
|
||||
.src.ip.ip4 = IPv4(172, 16, 1, 5),
|
||||
.dst.ip.ip4 = IPv4(172, 16, 2, 5),
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_NULL,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_NULL,
|
||||
.digest_len = 0,
|
||||
.keyword = "null",
|
||||
.algo = RTE_CRYPTO_CIPHER_NULL,
|
||||
.iv_len = 0,
|
||||
.block_size = 4,
|
||||
.flags = IP4_TUNNEL
|
||||
.key_len = 0
|
||||
},
|
||||
{
|
||||
.spi = 16,
|
||||
.src.ip.ip4 = IPv4(172, 16, 1, 6),
|
||||
.dst.ip.ip4 = IPv4(172, 16, 2, 6),
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_NULL,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_NULL,
|
||||
.keyword = "aes-128-cbc",
|
||||
.algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.key_len = 16
|
||||
}
|
||||
};
|
||||
|
||||
const struct supported_auth_algo auth_algos[] = {
|
||||
{
|
||||
.keyword = "null",
|
||||
.algo = RTE_CRYPTO_AUTH_NULL,
|
||||
.digest_len = 0,
|
||||
.iv_len = 0,
|
||||
.block_size = 4,
|
||||
.flags = IP4_TUNNEL
|
||||
.key_len = 0
|
||||
},
|
||||
{
|
||||
.spi = 25,
|
||||
.src.ip.ip6.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x55, 0x55 },
|
||||
.dst.ip.ip6.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x55, 0x55 },
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.keyword = "sha1-hmac",
|
||||
.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = IP6_TUNNEL
|
||||
},
|
||||
{
|
||||
.spi = 26,
|
||||
.src.ip.ip6.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x66, 0x66 },
|
||||
.dst.ip.ip6.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x66, 0x66 },
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = IP6_TUNNEL
|
||||
},
|
||||
};
|
||||
|
||||
/* SAs Inbound */
|
||||
const struct ipsec_sa sa_in[] = {
|
||||
{
|
||||
.spi = 105,
|
||||
.src.ip.ip4 = IPv4(172, 16, 2, 5),
|
||||
.dst.ip.ip4 = IPv4(172, 16, 1, 5),
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = IP4_TUNNEL
|
||||
},
|
||||
{
|
||||
.spi = 106,
|
||||
.src.ip.ip4 = IPv4(172, 16, 2, 6),
|
||||
.dst.ip.ip4 = IPv4(172, 16, 1, 6),
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = IP4_TUNNEL
|
||||
},
|
||||
{
|
||||
.spi = 110,
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = TRANSPORT
|
||||
},
|
||||
{
|
||||
.spi = 111,
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = TRANSPORT
|
||||
},
|
||||
{
|
||||
.spi = 115,
|
||||
.src.ip.ip4 = IPv4(172, 16, 2, 5),
|
||||
.dst.ip.ip4 = IPv4(172, 16, 1, 5),
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_NULL,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_NULL,
|
||||
.digest_len = 0,
|
||||
.iv_len = 0,
|
||||
.block_size = 4,
|
||||
.flags = IP4_TUNNEL
|
||||
},
|
||||
{
|
||||
.spi = 116,
|
||||
.src.ip.ip4 = IPv4(172, 16, 2, 6),
|
||||
.dst.ip.ip4 = IPv4(172, 16, 1, 6),
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_NULL,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_NULL,
|
||||
.digest_len = 0,
|
||||
.iv_len = 0,
|
||||
.block_size = 4,
|
||||
.flags = IP4_TUNNEL
|
||||
},
|
||||
{
|
||||
.spi = 125,
|
||||
.src.ip.ip6.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x55, 0x55 },
|
||||
.dst.ip.ip6.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x55, 0x55 },
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = IP6_TUNNEL
|
||||
},
|
||||
{
|
||||
.spi = 126,
|
||||
.src.ip.ip6.ip6_b = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x66, 0x66 },
|
||||
.dst.ip.ip6.ip6_b = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x66, 0x66 },
|
||||
.cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.digest_len = 12,
|
||||
.iv_len = 16,
|
||||
.block_size = 16,
|
||||
.flags = IP6_TUNNEL
|
||||
},
|
||||
};
|
||||
|
||||
static uint8_t cipher_key[256] = "sixteenbytes key";
|
||||
|
||||
/* AES CBC xform */
|
||||
const struct rte_crypto_sym_xform aescbc_enc_xf = {
|
||||
NULL,
|
||||
RTE_CRYPTO_SYM_XFORM_CIPHER,
|
||||
{.cipher = { RTE_CRYPTO_CIPHER_OP_ENCRYPT, RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.key = { cipher_key, 16 } }
|
||||
.key_len = 20
|
||||
}
|
||||
};
|
||||
|
||||
const struct rte_crypto_sym_xform aescbc_dec_xf = {
|
||||
NULL,
|
||||
RTE_CRYPTO_SYM_XFORM_CIPHER,
|
||||
{.cipher = { RTE_CRYPTO_CIPHER_OP_DECRYPT, RTE_CRYPTO_CIPHER_AES_CBC,
|
||||
.key = { cipher_key, 16 } }
|
||||
}
|
||||
};
|
||||
struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
|
||||
uint32_t nb_sa_out;
|
||||
|
||||
static uint8_t auth_key[256] = "twentybytes hash key";
|
||||
struct ipsec_sa sa_in[IPSEC_SA_MAX_ENTRIES];
|
||||
uint32_t nb_sa_in;
|
||||
|
||||
/* SHA1 HMAC xform */
|
||||
const struct rte_crypto_sym_xform sha1hmac_gen_xf = {
|
||||
NULL,
|
||||
RTE_CRYPTO_SYM_XFORM_AUTH,
|
||||
{.auth = { RTE_CRYPTO_AUTH_OP_GENERATE, RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.key = { auth_key, 20 }, 12, 0 }
|
||||
}
|
||||
};
|
||||
static const struct supported_cipher_algo *
|
||||
find_match_cipher_algo(const char *cipher_keyword)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
const struct rte_crypto_sym_xform sha1hmac_verify_xf = {
|
||||
NULL,
|
||||
RTE_CRYPTO_SYM_XFORM_AUTH,
|
||||
{.auth = { RTE_CRYPTO_AUTH_OP_VERIFY, RTE_CRYPTO_AUTH_SHA1_HMAC,
|
||||
.key = { auth_key, 20 }, 12, 0 }
|
||||
}
|
||||
};
|
||||
for (i = 0; i < RTE_DIM(cipher_algos); i++) {
|
||||
const struct supported_cipher_algo *algo =
|
||||
&cipher_algos[i];
|
||||
|
||||
/* AES CBC xform */
|
||||
const struct rte_crypto_sym_xform null_cipher_xf = {
|
||||
NULL,
|
||||
RTE_CRYPTO_SYM_XFORM_CIPHER,
|
||||
{.cipher = { .algo = RTE_CRYPTO_CIPHER_NULL }
|
||||
if (strcmp(cipher_keyword, algo->keyword) == 0)
|
||||
return algo;
|
||||
}
|
||||
};
|
||||
|
||||
const struct rte_crypto_sym_xform null_auth_xf = {
|
||||
NULL,
|
||||
RTE_CRYPTO_SYM_XFORM_AUTH,
|
||||
{.auth = { .algo = RTE_CRYPTO_AUTH_NULL }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct supported_auth_algo *
|
||||
find_match_auth_algo(const char *auth_keyword)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < RTE_DIM(auth_algos); i++) {
|
||||
const struct supported_auth_algo *algo =
|
||||
&auth_algos[i];
|
||||
|
||||
if (strcmp(auth_keyword, algo->keyword) == 0)
|
||||
return algo;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** parse_key_string
|
||||
* parse x:x:x:x.... hex number key string into uint8_t *key
|
||||
* return:
|
||||
* > 0: number of bytes parsed
|
||||
* 0: failed
|
||||
*/
|
||||
static uint32_t
|
||||
parse_key_string(const char *key_str, uint8_t *key)
|
||||
{
|
||||
const char *pt_start = key_str, *pt_end = key_str;
|
||||
char sub_str[3];
|
||||
uint32_t nb_bytes = 0;
|
||||
|
||||
while (pt_end != NULL) {
|
||||
pt_end = strchr(pt_start, ':');
|
||||
|
||||
if (pt_end == NULL)
|
||||
strncpy(sub_str, pt_start, strlen(pt_start));
|
||||
else {
|
||||
if (pt_end - pt_start > 2)
|
||||
return 0;
|
||||
|
||||
strncpy(sub_str, pt_start, pt_end - pt_start);
|
||||
pt_start = pt_end + 1;
|
||||
}
|
||||
|
||||
key[nb_bytes++] = strtol(sub_str, NULL, 16);
|
||||
}
|
||||
|
||||
return nb_bytes;
|
||||
}
|
||||
|
||||
void
|
||||
parse_sa_tokens(char **tokens, uint32_t n_tokens,
|
||||
struct parse_status *status)
|
||||
{
|
||||
struct ipsec_sa *rule = NULL;
|
||||
uint32_t ti; /*token index*/
|
||||
uint32_t *ri /*rule index*/;
|
||||
uint32_t cipher_algo_p = 0;
|
||||
uint32_t auth_algo_p = 0;
|
||||
uint32_t src_p = 0;
|
||||
uint32_t dst_p = 0;
|
||||
uint32_t mode_p = 0;
|
||||
|
||||
if (strcmp(tokens[0], "in") == 0) {
|
||||
ri = &nb_sa_in;
|
||||
|
||||
APP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status,
|
||||
"too many sa rules, abort insertion\n");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule = &sa_in[*ri];
|
||||
} else {
|
||||
ri = &nb_sa_out;
|
||||
|
||||
APP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status,
|
||||
"too many sa rules, abort insertion\n");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule = &sa_out[*ri];
|
||||
}
|
||||
|
||||
/* spi number */
|
||||
APP_CHECK_TOKEN_IS_NUM(tokens, 1, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
rule->spi = atoi(tokens[1]);
|
||||
|
||||
for (ti = 2; ti < n_tokens; ti++) {
|
||||
if (strcmp(tokens[ti], "mode") == 0) {
|
||||
APP_CHECK_PRESENCE(mode_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
if (strcmp(tokens[ti], "ipv4-tunnel") == 0)
|
||||
rule->flags = IP4_TUNNEL;
|
||||
else if (strcmp(tokens[ti], "ipv6-tunnel") == 0)
|
||||
rule->flags = IP6_TUNNEL;
|
||||
else if (strcmp(tokens[ti], "transport") == 0)
|
||||
rule->flags = TRANSPORT;
|
||||
else {
|
||||
APP_CHECK(0, status, "unrecognized "
|
||||
"input \"%s\"", tokens[ti]);
|
||||
return;
|
||||
}
|
||||
|
||||
mode_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "cipher_algo") == 0) {
|
||||
const struct supported_cipher_algo *algo;
|
||||
uint32_t key_len;
|
||||
|
||||
APP_CHECK_PRESENCE(cipher_algo_p, tokens[ti],
|
||||
status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
algo = find_match_cipher_algo(tokens[ti]);
|
||||
|
||||
APP_CHECK(algo != NULL, status, "unrecognized "
|
||||
"input \"%s\"", tokens[ti]);
|
||||
|
||||
rule->cipher_algo = algo->algo;
|
||||
rule->block_size = algo->block_size;
|
||||
rule->iv_len = algo->iv_len;
|
||||
rule->cipher_key_len = algo->key_len;
|
||||
|
||||
/* for NULL algorithm, no cipher key should
|
||||
* exist */
|
||||
if (rule->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
|
||||
cipher_algo_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(strcmp(tokens[ti], "cipher_key") == 0,
|
||||
status, "unrecognized input \"%s\", "
|
||||
"expect \"cipher_key\"", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
key_len = parse_key_string(tokens[ti],
|
||||
rule->cipher_key);
|
||||
APP_CHECK(key_len == rule->cipher_key_len, status,
|
||||
"unrecognized input \"%s\"", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
cipher_algo_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "auth_algo") == 0) {
|
||||
const struct supported_auth_algo *algo;
|
||||
uint32_t key_len;
|
||||
|
||||
APP_CHECK_PRESENCE(auth_algo_p, tokens[ti],
|
||||
status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
algo = find_match_auth_algo(tokens[ti]);
|
||||
APP_CHECK(algo != NULL, status, "unrecognized "
|
||||
"input \"%s\"", tokens[ti]);
|
||||
|
||||
rule->auth_algo = algo->algo;
|
||||
rule->auth_key_len = algo->key_len;
|
||||
rule->digest_len = algo->digest_len;
|
||||
|
||||
/* for NULL algorithm, no auth key should exist */
|
||||
if (rule->auth_algo == RTE_CRYPTO_AUTH_NULL) {
|
||||
auth_algo_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(strcmp(tokens[ti], "auth_key") == 0,
|
||||
status, "unrecognized input \"%s\", "
|
||||
"expect \"auth_key\"", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
key_len = parse_key_string(tokens[ti],
|
||||
rule->auth_key);
|
||||
APP_CHECK(key_len == rule->auth_key_len, status,
|
||||
"unrecognized input \"%s\"", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
auth_algo_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "src") == 0) {
|
||||
APP_CHECK_PRESENCE(src_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
if (rule->flags == IP4_TUNNEL) {
|
||||
struct in_addr ip;
|
||||
|
||||
APP_CHECK(parse_ipv4_addr(tokens[ti],
|
||||
&ip, NULL) == 0, status,
|
||||
"unrecognized input \"%s\", "
|
||||
"expect valid ipv4 addr",
|
||||
tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
rule->src.ip.ip4 = rte_bswap32(
|
||||
(uint32_t)ip.s_addr);
|
||||
} else if (rule->flags == IP6_TUNNEL) {
|
||||
struct in6_addr ip;
|
||||
|
||||
APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
|
||||
NULL) == 0, status,
|
||||
"unrecognized input \"%s\", "
|
||||
"expect valid ipv6 addr",
|
||||
tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
memcpy(rule->src.ip.ip6.ip6_b,
|
||||
ip.s6_addr, 16);
|
||||
} else if (rule->flags == TRANSPORT) {
|
||||
APP_CHECK(0, status, "unrecognized input "
|
||||
"\"%s\"", tokens[ti]);
|
||||
return;
|
||||
}
|
||||
|
||||
src_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "dst") == 0) {
|
||||
APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
if (rule->flags == IP4_TUNNEL) {
|
||||
struct in_addr ip;
|
||||
|
||||
APP_CHECK(parse_ipv4_addr(tokens[ti],
|
||||
&ip, NULL) == 0, status,
|
||||
"unrecognized input \"%s\", "
|
||||
"expect valid ipv4 addr",
|
||||
tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
rule->dst.ip.ip4 = rte_bswap32(
|
||||
(uint32_t)ip.s_addr);
|
||||
} else if (rule->flags == IP6_TUNNEL) {
|
||||
struct in6_addr ip;
|
||||
|
||||
APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
|
||||
NULL) == 0, status,
|
||||
"unrecognized input \"%s\", "
|
||||
"expect valid ipv6 addr",
|
||||
tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
memcpy(rule->dst.ip.ip6.ip6_b, ip.s6_addr, 16);
|
||||
} else if (rule->flags == TRANSPORT) {
|
||||
APP_CHECK(0, status, "unrecognized "
|
||||
"input \"%s\"", tokens[ti]);
|
||||
return;
|
||||
}
|
||||
|
||||
dst_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* unrecognizeable input */
|
||||
APP_CHECK(0, status, "unrecognized input \"%s\"",
|
||||
tokens[ti]);
|
||||
return;
|
||||
}
|
||||
|
||||
APP_CHECK(cipher_algo_p == 1, status, "missing cipher options");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(auth_algo_p == 1, status, "missing auth options");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(mode_p == 1, status, "missing mode option");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
*ri = *ri + 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t a, b, c, d;
|
||||
|
||||
printf("\tspi_%s(%3u):", inbound?"in":"out", sa->spi);
|
||||
|
||||
for (i = 0; i < RTE_DIM(cipher_algos); i++) {
|
||||
if (cipher_algos[i].algo == sa->cipher_algo) {
|
||||
printf("%s ", cipher_algos[i].keyword);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < RTE_DIM(auth_algos); i++) {
|
||||
if (auth_algos[i].algo == sa->auth_algo) {
|
||||
printf("%s ", auth_algos[i].keyword);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("mode:");
|
||||
|
||||
switch (sa->flags) {
|
||||
case IP4_TUNNEL:
|
||||
printf("IP4Tunnel ");
|
||||
uint32_t_to_char(sa->src.ip.ip4, &a, &b, &c, &d);
|
||||
printf("%hhu.%hhu.%hhu.%hhu ", d, c, b, a);
|
||||
uint32_t_to_char(sa->dst.ip.ip4, &a, &b, &c, &d);
|
||||
printf("%hhu.%hhu.%hhu.%hhu", d, c, b, a);
|
||||
break;
|
||||
case IP6_TUNNEL:
|
||||
printf("IP6Tunnel ");
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (i % 2 && i != 15)
|
||||
printf("%.2x:", sa->src.ip.ip6.ip6_b[i]);
|
||||
else
|
||||
printf("%.2x", sa->src.ip.ip6.ip6_b[i]);
|
||||
}
|
||||
printf(" ");
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (i % 2 && i != 15)
|
||||
printf("%.2x:", sa->dst.ip.ip6.ip6_b[i]);
|
||||
else
|
||||
printf("%.2x", sa->dst.ip.ip6.ip6_b[i]);
|
||||
}
|
||||
break;
|
||||
case TRANSPORT:
|
||||
printf("Transport");
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
};
|
||||
|
||||
struct sa_ctx {
|
||||
struct ipsec_sa sa[IPSEC_SA_MAX_ENTRIES];
|
||||
@ -347,25 +561,53 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
|
||||
}
|
||||
|
||||
if (inbound) {
|
||||
if (sa->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
|
||||
sa_ctx->xf[idx].a = null_auth_xf;
|
||||
sa_ctx->xf[idx].b = null_cipher_xf;
|
||||
} else {
|
||||
sa_ctx->xf[idx].a = sha1hmac_verify_xf;
|
||||
sa_ctx->xf[idx].b = aescbc_dec_xf;
|
||||
}
|
||||
sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
|
||||
sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo;
|
||||
sa_ctx->xf[idx].b.cipher.key.data = sa->cipher_key;
|
||||
sa_ctx->xf[idx].b.cipher.key.length =
|
||||
sa->cipher_key_len;
|
||||
sa_ctx->xf[idx].b.cipher.op =
|
||||
RTE_CRYPTO_CIPHER_OP_DECRYPT;
|
||||
sa_ctx->xf[idx].b.next = NULL;
|
||||
|
||||
sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AUTH;
|
||||
sa_ctx->xf[idx].a.auth.algo = sa->auth_algo;
|
||||
sa_ctx->xf[idx].a.auth.add_auth_data_length = 0;
|
||||
sa_ctx->xf[idx].a.auth.key.data = sa->auth_key;
|
||||
sa_ctx->xf[idx].a.auth.key.length =
|
||||
sa->auth_key_len;
|
||||
sa_ctx->xf[idx].a.auth.digest_length =
|
||||
sa->digest_len;
|
||||
sa_ctx->xf[idx].a.auth.op =
|
||||
RTE_CRYPTO_AUTH_OP_VERIFY;
|
||||
|
||||
} else { /* outbound */
|
||||
if (sa->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
|
||||
sa_ctx->xf[idx].a = null_cipher_xf;
|
||||
sa_ctx->xf[idx].b = null_auth_xf;
|
||||
} else {
|
||||
sa_ctx->xf[idx].a = aescbc_enc_xf;
|
||||
sa_ctx->xf[idx].b = sha1hmac_gen_xf;
|
||||
}
|
||||
sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
|
||||
sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo;
|
||||
sa_ctx->xf[idx].a.cipher.key.data = sa->cipher_key;
|
||||
sa_ctx->xf[idx].a.cipher.key.length =
|
||||
sa->cipher_key_len;
|
||||
sa_ctx->xf[idx].a.cipher.op =
|
||||
RTE_CRYPTO_CIPHER_OP_ENCRYPT;
|
||||
sa_ctx->xf[idx].a.next = NULL;
|
||||
|
||||
sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_AUTH;
|
||||
sa_ctx->xf[idx].b.auth.algo = sa->auth_algo;
|
||||
sa_ctx->xf[idx].b.auth.add_auth_data_length = 0;
|
||||
sa_ctx->xf[idx].b.auth.key.data = sa->auth_key;
|
||||
sa_ctx->xf[idx].b.auth.key.length =
|
||||
sa->auth_key_len;
|
||||
sa_ctx->xf[idx].b.auth.digest_length =
|
||||
sa->digest_len;
|
||||
sa_ctx->xf[idx].b.auth.op =
|
||||
RTE_CRYPTO_AUTH_OP_GENERATE;
|
||||
}
|
||||
|
||||
sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
|
||||
sa_ctx->xf[idx].b.next = NULL;
|
||||
sa->xforms = &sa_ctx->xf[idx].a;
|
||||
|
||||
print_one_sa_rule(sa, inbound);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -386,10 +628,8 @@ sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
|
||||
}
|
||||
|
||||
void
|
||||
sa_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
|
||||
sa_init(struct socket_ctx *ctx, int32_t socket_id)
|
||||
{
|
||||
const struct ipsec_sa *sa_out_entries, *sa_in_entries;
|
||||
uint32_t nb_out_entries, nb_in_entries;
|
||||
const char *name;
|
||||
|
||||
if (ctx == NULL)
|
||||
@ -403,35 +643,30 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
|
||||
rte_exit(EXIT_FAILURE, "Outbound SA DB for socket %u already "
|
||||
"initialized\n", socket_id);
|
||||
|
||||
if (ep == 0) {
|
||||
sa_out_entries = sa_out;
|
||||
nb_out_entries = RTE_DIM(sa_out);
|
||||
sa_in_entries = sa_in;
|
||||
nb_in_entries = RTE_DIM(sa_in);
|
||||
} else if (ep == 1) {
|
||||
sa_out_entries = sa_in;
|
||||
nb_out_entries = RTE_DIM(sa_in);
|
||||
sa_in_entries = sa_out;
|
||||
nb_in_entries = RTE_DIM(sa_out);
|
||||
} else
|
||||
rte_exit(EXIT_FAILURE, "Invalid EP value %u. "
|
||||
"Only 0 or 1 supported.\n", ep);
|
||||
|
||||
if (nb_sa_in > 0) {
|
||||
name = "sa_in";
|
||||
ctx->sa_in = sa_create(name, socket_id);
|
||||
if (ctx->sa_in == NULL)
|
||||
rte_exit(EXIT_FAILURE, "Error [%d] creating SA context %s "
|
||||
"in socket %d\n", rte_errno, name, socket_id);
|
||||
rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
|
||||
"context %s in socket %d\n", rte_errno,
|
||||
name, socket_id);
|
||||
|
||||
sa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in);
|
||||
} else
|
||||
RTE_LOG(WARNING, IPSEC, "No SA Inbound rule specified\n");
|
||||
|
||||
if (nb_sa_out > 0) {
|
||||
name = "sa_out";
|
||||
ctx->sa_out = sa_create(name, socket_id);
|
||||
if (ctx->sa_out == NULL)
|
||||
rte_exit(EXIT_FAILURE, "Error [%d] creating SA context %s "
|
||||
"in socket %d\n", rte_errno, name, socket_id);
|
||||
rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
|
||||
"context %s in socket %d\n", rte_errno,
|
||||
name, socket_id);
|
||||
|
||||
sa_in_add_rules(ctx->sa_in, sa_in_entries, nb_in_entries);
|
||||
|
||||
sa_out_add_rules(ctx->sa_out, sa_out_entries, nb_out_entries);
|
||||
sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out);
|
||||
} else
|
||||
RTE_LOG(WARNING, IPSEC, "No SA Outbound rule "
|
||||
"specified\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -42,8 +42,9 @@
|
||||
#include <rte_ip.h>
|
||||
|
||||
#include "ipsec.h"
|
||||
#include "parser.h"
|
||||
|
||||
#define MAX_ACL_RULE_NUM 1000
|
||||
#define MAX_ACL_RULE_NUM 1024
|
||||
|
||||
/*
|
||||
* Rule and trace formats definitions.
|
||||
@ -113,211 +114,306 @@ struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = {
|
||||
|
||||
RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs));
|
||||
|
||||
const struct acl4_rules acl4_rules_out[] = {
|
||||
{
|
||||
.data = {.userdata = PROTECT(5), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 105, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(6), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 106, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(10), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 175, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(11), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 176, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(15), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 200, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(16), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 201, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(25), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 55, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(26), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 56, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 240, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 241, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
}
|
||||
};
|
||||
struct acl4_rules acl4_rules_out[MAX_ACL_RULE_NUM];
|
||||
uint32_t nb_acl4_rules_out;
|
||||
|
||||
const struct acl4_rules acl4_rules_in[] = {
|
||||
struct acl4_rules acl4_rules_in[MAX_ACL_RULE_NUM];
|
||||
uint32_t nb_acl4_rules_in;
|
||||
|
||||
void
|
||||
parse_sp4_tokens(char **tokens, uint32_t n_tokens,
|
||||
struct parse_status *status)
|
||||
{
|
||||
.data = {.userdata = PROTECT(105), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 115, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(106), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 116, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(110), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 185, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(111), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 186, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(115), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 210, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(116), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 211, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(125), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 65, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(126), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 66, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 245, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = BYPASS, .category_mask = 1, .priority = 1},
|
||||
/* destination IPv4 */
|
||||
.field[2] = {.value.u32 = IPv4(192, 168, 246, 0),
|
||||
.mask_range.u32 = 24,},
|
||||
/* source port */
|
||||
.field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
struct acl4_rules *rule_ipv4 = NULL;
|
||||
|
||||
uint32_t *ri = NULL; /* rule index */
|
||||
uint32_t ti = 0; /* token index */
|
||||
|
||||
uint32_t esp_p = 0;
|
||||
uint32_t protect_p = 0;
|
||||
uint32_t bypass_p = 0;
|
||||
uint32_t discard_p = 0;
|
||||
uint32_t pri_p = 0;
|
||||
uint32_t src_p = 0;
|
||||
uint32_t dst_p = 0;
|
||||
uint32_t proto_p = 0;
|
||||
uint32_t sport_p = 0;
|
||||
uint32_t dport_p = 0;
|
||||
|
||||
if (strcmp(tokens[1], "in") == 0) {
|
||||
ri = &nb_acl4_rules_in;
|
||||
|
||||
APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
|
||||
"too many sp rules, abort insertion\n");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4 = &acl4_rules_in[*ri];
|
||||
|
||||
} else if (strcmp(tokens[1], "out") == 0) {
|
||||
ri = &nb_acl4_rules_out;
|
||||
|
||||
APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
|
||||
"too many sp rules, abort insertion\n");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4 = &acl4_rules_out[*ri];
|
||||
} else {
|
||||
APP_CHECK(0, status, "unrecognized input \"%s\", expect"
|
||||
" \"in\" or \"out\"\n", tokens[ti]);
|
||||
return;
|
||||
}
|
||||
|
||||
rule_ipv4->data.category_mask = 1;
|
||||
|
||||
for (ti = 2; ti < n_tokens; ti++) {
|
||||
if (strcmp(tokens[ti], "esp") == 0) {
|
||||
/* currently do nothing */
|
||||
APP_CHECK_PRESENCE(esp_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
esp_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "protect") == 0) {
|
||||
APP_CHECK_PRESENCE(protect_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(bypass_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"bypass");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(discard_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"discard");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4->data.userdata =
|
||||
PROTECT(atoi(tokens[ti]));
|
||||
|
||||
protect_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "bypass") == 0) {
|
||||
APP_CHECK_PRESENCE(bypass_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(protect_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"protect");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(discard_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"discard");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4->data.userdata = BYPASS;
|
||||
|
||||
bypass_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "discard") == 0) {
|
||||
APP_CHECK_PRESENCE(discard_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(protect_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"protect");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(bypass_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"discard");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4->data.userdata = DISCARD;
|
||||
|
||||
discard_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "pri") == 0) {
|
||||
APP_CHECK_PRESENCE(pri_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4->data.priority = atoi(tokens[ti]);
|
||||
|
||||
pri_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "src") == 0) {
|
||||
struct in_addr ip;
|
||||
uint32_t depth;
|
||||
|
||||
APP_CHECK_PRESENCE(src_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(parse_ipv4_addr(tokens[ti], &ip,
|
||||
&depth) == 0, status, "unrecognized "
|
||||
"input \"%s\", expect valid ipv4 addr",
|
||||
tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4->field[1].value.u32 =
|
||||
rte_bswap32(ip.s_addr);
|
||||
rule_ipv4->field[1].mask_range.u32 =
|
||||
depth;
|
||||
|
||||
src_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "dst") == 0) {
|
||||
struct in_addr ip;
|
||||
uint32_t depth;
|
||||
|
||||
APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(parse_ipv4_addr(tokens[ti], &ip,
|
||||
&depth) == 0, status, "unrecognized "
|
||||
"input \"%s\", expect valid ipv4 addr",
|
||||
tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4->field[2].value.u32 =
|
||||
rte_bswap32(ip.s_addr);
|
||||
rule_ipv4->field[2].mask_range.u32 =
|
||||
depth;
|
||||
|
||||
dst_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "proto") == 0) {
|
||||
uint16_t low, high;
|
||||
|
||||
APP_CHECK_PRESENCE(proto_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(parse_range(tokens[ti], &low, &high)
|
||||
== 0, status, "unrecognized input \"%s\""
|
||||
", expect \"from:to\"", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(low <= 0xff, status, "proto low "
|
||||
"over-limit");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(high <= 0xff, status, "proto high "
|
||||
"over-limit");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4->field[0].value.u8 = (uint8_t)low;
|
||||
rule_ipv4->field[0].mask_range.u8 = (uint8_t)high;
|
||||
|
||||
proto_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "sport") == 0) {
|
||||
uint16_t port_low, port_high;
|
||||
|
||||
APP_CHECK_PRESENCE(sport_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(parse_range(tokens[ti], &port_low,
|
||||
&port_high) == 0, status, "unrecognized "
|
||||
"input \"%s\", expect \"port_from:"
|
||||
"port_to\"", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4->field[3].value.u16 = port_low;
|
||||
rule_ipv4->field[3].mask_range.u16 = port_high;
|
||||
|
||||
sport_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "dport") == 0) {
|
||||
uint16_t port_low, port_high;
|
||||
|
||||
APP_CHECK_PRESENCE(dport_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(parse_range(tokens[ti], &port_low,
|
||||
&port_high) == 0, status, "unrecognized "
|
||||
"input \"%s\", expect \"port_from:"
|
||||
"port_to\"", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv4->field[4].value.u16 = port_low;
|
||||
rule_ipv4->field[4].mask_range.u16 = port_high;
|
||||
|
||||
dport_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* unrecognizeable input */
|
||||
APP_CHECK(0, status, "unrecognized input \"%s\"",
|
||||
tokens[ti]);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check if argument(s) are missing */
|
||||
APP_CHECK(esp_p == 1, status, "missing argument \"esp\"");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(protect_p | bypass_p | discard_p, status, "missing "
|
||||
"argument \"protect\", \"bypass\", or \"discard\"");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
*ri = *ri + 1;
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
print_one_ip4_rule(const struct acl4_rules *rule, int32_t extra)
|
||||
@ -406,11 +502,9 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
|
||||
}
|
||||
|
||||
void
|
||||
sp4_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
|
||||
sp4_init(struct socket_ctx *ctx, int32_t socket_id)
|
||||
{
|
||||
const char *name;
|
||||
const struct acl4_rules *rules_out, *rules_in;
|
||||
uint32_t nb_out_rules, nb_in_rules;
|
||||
|
||||
if (ctx == NULL)
|
||||
rte_exit(EXIT_FAILURE, "NULL context.\n");
|
||||
@ -423,25 +517,19 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
|
||||
rte_exit(EXIT_FAILURE, "Outbound SP DB for socket %u already "
|
||||
"initialized\n", socket_id);
|
||||
|
||||
if (ep == 0) {
|
||||
rules_out = acl4_rules_out;
|
||||
nb_out_rules = RTE_DIM(acl4_rules_out);
|
||||
rules_in = acl4_rules_in;
|
||||
nb_in_rules = RTE_DIM(acl4_rules_in);
|
||||
} else if (ep == 1) {
|
||||
rules_out = acl4_rules_in;
|
||||
nb_out_rules = RTE_DIM(acl4_rules_in);
|
||||
rules_in = acl4_rules_out;
|
||||
nb_in_rules = RTE_DIM(acl4_rules_out);
|
||||
} else
|
||||
rte_exit(EXIT_FAILURE, "Invalid EP value %u. "
|
||||
"Only 0 or 1 supported.\n", ep);
|
||||
|
||||
if (nb_acl4_rules_in > 0) {
|
||||
name = "sp_ip4_in";
|
||||
ctx->sp_ip4_in = (struct sp_ctx *)acl4_init(name, socket_id,
|
||||
rules_in, nb_in_rules);
|
||||
ctx->sp_ip4_in = (struct sp_ctx *)acl4_init(name,
|
||||
socket_id, acl4_rules_in, nb_acl4_rules_in);
|
||||
} else
|
||||
RTE_LOG(WARNING, IPSEC, "No IPv4 SP Inbound rule "
|
||||
"specified\n");
|
||||
|
||||
if (nb_acl4_rules_out > 0) {
|
||||
name = "sp_ip4_out";
|
||||
ctx->sp_ip4_out = (struct sp_ctx *)acl4_init(name, socket_id,
|
||||
rules_out, nb_out_rules);
|
||||
ctx->sp_ip4_out = (struct sp_ctx *)acl4_init(name,
|
||||
socket_id, acl4_rules_out, nb_acl4_rules_out);
|
||||
} else
|
||||
RTE_LOG(WARNING, IPSEC, "No IPv4 SP Outbound rule "
|
||||
"specified\n");
|
||||
}
|
||||
|
@ -42,8 +42,9 @@
|
||||
#include <rte_ip.h>
|
||||
|
||||
#include "ipsec.h"
|
||||
#include "parser.h"
|
||||
|
||||
#define MAX_ACL_RULE_NUM 1000
|
||||
#define MAX_ACL_RULE_NUM 1024
|
||||
|
||||
enum {
|
||||
IP6_PROTO,
|
||||
@ -144,155 +145,363 @@ struct rte_acl_field_def ip6_defs[IP6_NUM] = {
|
||||
|
||||
RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs));
|
||||
|
||||
const struct acl6_rules acl6_rules_out[] = {
|
||||
{
|
||||
.data = {.userdata = PROTECT(5), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0x55555555, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(6), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0x66666666, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(10), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0x00000000, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(11), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(25), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0xaaaaaaaa, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(26), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0xbbbbbbbb, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
}
|
||||
};
|
||||
struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM];
|
||||
uint32_t nb_acl6_rules_out;
|
||||
|
||||
const struct acl6_rules acl6_rules_in[] = {
|
||||
struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM];
|
||||
uint32_t nb_acl6_rules_in;
|
||||
|
||||
void
|
||||
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
|
||||
struct parse_status *status)
|
||||
{
|
||||
.data = {.userdata = PROTECT(15), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0x55555555, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(16), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0x66666666, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(110), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0x00000000, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(111), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(125), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0xaaaaaaaa, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
},
|
||||
{
|
||||
.data = {.userdata = PROTECT(126), .category_mask = 1, .priority = 1},
|
||||
/* destination IPv6 */
|
||||
.field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},
|
||||
.field[6] = {.value.u32 = 0x0, .mask_range.u32 = 32,},
|
||||
.field[7] = {.value.u32 = 0xbbbbbbbb, .mask_range.u32 = 32,},
|
||||
.field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,},
|
||||
/* source port */
|
||||
.field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,},
|
||||
/* destination port */
|
||||
.field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}
|
||||
struct acl6_rules *rule_ipv6 = NULL;
|
||||
|
||||
uint32_t *ri = NULL; /* rule index */
|
||||
uint32_t ti = 0; /* token index */
|
||||
|
||||
uint32_t esp_p = 0;
|
||||
uint32_t protect_p = 0;
|
||||
uint32_t bypass_p = 0;
|
||||
uint32_t discard_p = 0;
|
||||
uint32_t pri_p = 0;
|
||||
uint32_t src_p = 0;
|
||||
uint32_t dst_p = 0;
|
||||
uint32_t proto_p = 0;
|
||||
uint32_t sport_p = 0;
|
||||
uint32_t dport_p = 0;
|
||||
|
||||
if (strcmp(tokens[1], "in") == 0) {
|
||||
ri = &nb_acl6_rules_in;
|
||||
|
||||
APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
|
||||
"many sp rules, abort insertion\n");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6 = &acl6_rules_in[*ri];
|
||||
|
||||
} else if (strcmp(tokens[1], "out") == 0) {
|
||||
ri = &nb_acl6_rules_out;
|
||||
|
||||
APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
|
||||
"many sp rules, abort insertion\n");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6 = &acl6_rules_out[*ri];
|
||||
|
||||
} else {
|
||||
APP_CHECK(0, status, "unrecognized input \"%s\", expect"
|
||||
" \"in\" or \"out\"\n", tokens[ti]);
|
||||
return;
|
||||
}
|
||||
|
||||
rule_ipv6->data.category_mask = 1;
|
||||
|
||||
|
||||
for (ti = 2; ti < n_tokens; ti++) {
|
||||
if (strcmp(tokens[ti], "esp") == 0) {
|
||||
/* currently do nothing */
|
||||
APP_CHECK_PRESENCE(esp_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
esp_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "protect") == 0) {
|
||||
APP_CHECK_PRESENCE(protect_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(bypass_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"bypass");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(discard_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"discard");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6->data.userdata =
|
||||
PROTECT(atoi(tokens[ti]));
|
||||
|
||||
protect_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "bypass") == 0) {
|
||||
APP_CHECK_PRESENCE(bypass_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(protect_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"protect");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(discard_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"discard");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6->data.userdata = BYPASS;
|
||||
|
||||
bypass_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "discard") == 0) {
|
||||
APP_CHECK_PRESENCE(discard_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(protect_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"protect");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(bypass_p == 0, status, "conflict item "
|
||||
"between \"%s\" and \"%s\"", tokens[ti],
|
||||
"discard");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6->data.userdata = DISCARD;
|
||||
|
||||
discard_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "pri") == 0) {
|
||||
APP_CHECK_PRESENCE(pri_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6->data.priority = atoi(tokens[ti]);
|
||||
|
||||
pri_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "src") == 0) {
|
||||
struct in6_addr ip;
|
||||
uint32_t depth;
|
||||
|
||||
APP_CHECK_PRESENCE(src_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
|
||||
&depth) == 0, status, "unrecognized "
|
||||
"input \"%s\", expect valid ipv6 "
|
||||
"addr", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6->field[1].value.u32 =
|
||||
(uint32_t)ip.s6_addr[0] << 24 |
|
||||
(uint32_t)ip.s6_addr[1] << 16 |
|
||||
(uint32_t)ip.s6_addr[2] << 8 |
|
||||
(uint32_t)ip.s6_addr[3];
|
||||
rule_ipv6->field[1].mask_range.u32 =
|
||||
(depth > 32) ? 32 : depth;
|
||||
depth = (depth > 32) ? (depth - 32) : 0;
|
||||
rule_ipv6->field[2].value.u32 =
|
||||
(uint32_t)ip.s6_addr[4] << 24 |
|
||||
(uint32_t)ip.s6_addr[5] << 16 |
|
||||
(uint32_t)ip.s6_addr[6] << 8 |
|
||||
(uint32_t)ip.s6_addr[7];
|
||||
rule_ipv6->field[2].mask_range.u32 =
|
||||
(depth > 32) ? 32 : depth;
|
||||
depth = (depth > 32) ? (depth - 32) : 0;
|
||||
rule_ipv6->field[3].value.u32 =
|
||||
(uint32_t)ip.s6_addr[8] << 24 |
|
||||
(uint32_t)ip.s6_addr[9] << 16 |
|
||||
(uint32_t)ip.s6_addr[10] << 8 |
|
||||
(uint32_t)ip.s6_addr[11];
|
||||
rule_ipv6->field[3].mask_range.u32 =
|
||||
(depth > 32) ? 32 : depth;
|
||||
depth = (depth > 32) ? (depth - 32) : 0;
|
||||
rule_ipv6->field[4].value.u32 =
|
||||
(uint32_t)ip.s6_addr[12] << 24 |
|
||||
(uint32_t)ip.s6_addr[13] << 16 |
|
||||
(uint32_t)ip.s6_addr[14] << 8 |
|
||||
(uint32_t)ip.s6_addr[15];
|
||||
rule_ipv6->field[4].mask_range.u32 =
|
||||
(depth > 32) ? 32 : depth;
|
||||
|
||||
src_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "dst") == 0) {
|
||||
struct in6_addr ip;
|
||||
uint32_t depth;
|
||||
|
||||
APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
|
||||
&depth) == 0, status, "unrecognized "
|
||||
"input \"%s\", expect valid ipv6 "
|
||||
"addr", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6->field[5].value.u32 =
|
||||
(uint32_t)ip.s6_addr[0] << 24 |
|
||||
(uint32_t)ip.s6_addr[1] << 16 |
|
||||
(uint32_t)ip.s6_addr[2] << 8 |
|
||||
(uint32_t)ip.s6_addr[3];
|
||||
rule_ipv6->field[5].mask_range.u32 =
|
||||
(depth > 32) ? 32 : depth;
|
||||
depth = (depth > 32) ? (depth - 32) : 0;
|
||||
rule_ipv6->field[6].value.u32 =
|
||||
(uint32_t)ip.s6_addr[4] << 24 |
|
||||
(uint32_t)ip.s6_addr[5] << 16 |
|
||||
(uint32_t)ip.s6_addr[6] << 8 |
|
||||
(uint32_t)ip.s6_addr[7];
|
||||
rule_ipv6->field[6].mask_range.u32 =
|
||||
(depth > 32) ? 32 : depth;
|
||||
depth = (depth > 32) ? (depth - 32) : 0;
|
||||
rule_ipv6->field[7].value.u32 =
|
||||
(uint32_t)ip.s6_addr[8] << 24 |
|
||||
(uint32_t)ip.s6_addr[9] << 16 |
|
||||
(uint32_t)ip.s6_addr[10] << 8 |
|
||||
(uint32_t)ip.s6_addr[11];
|
||||
rule_ipv6->field[7].mask_range.u32 =
|
||||
(depth > 32) ? 32 : depth;
|
||||
depth = (depth > 32) ? (depth - 32) : 0;
|
||||
rule_ipv6->field[8].value.u32 =
|
||||
(uint32_t)ip.s6_addr[12] << 24 |
|
||||
(uint32_t)ip.s6_addr[13] << 16 |
|
||||
(uint32_t)ip.s6_addr[14] << 8 |
|
||||
(uint32_t)ip.s6_addr[15];
|
||||
rule_ipv6->field[8].mask_range.u32 =
|
||||
(depth > 32) ? 32 : depth;
|
||||
|
||||
dst_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "proto") == 0) {
|
||||
uint16_t low, high;
|
||||
|
||||
APP_CHECK_PRESENCE(proto_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(parse_range(tokens[ti], &low, &high)
|
||||
== 0, status, "unrecognized input \"%s\""
|
||||
", expect \"from:to\"", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(low <= 0xff, status, "proto low "
|
||||
"over-limit");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
APP_CHECK(high <= 0xff, status, "proto high "
|
||||
"over-limit");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6->field[0].value.u8 = (uint8_t)low;
|
||||
rule_ipv6->field[0].mask_range.u8 = (uint8_t)high;
|
||||
|
||||
proto_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "sport") == 0) {
|
||||
uint16_t port_low, port_high;
|
||||
|
||||
APP_CHECK_PRESENCE(sport_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(parse_range(tokens[ti], &port_low,
|
||||
&port_high) == 0, status, "unrecognized "
|
||||
"input \"%s\", expect \"port_from:"
|
||||
"port_to\"", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6->field[9].value.u16 = port_low;
|
||||
rule_ipv6->field[9].mask_range.u16 = port_high;
|
||||
|
||||
sport_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[ti], "dport") == 0) {
|
||||
uint16_t port_low, port_high;
|
||||
|
||||
APP_CHECK_PRESENCE(dport_p, tokens[ti], status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(parse_range(tokens[ti], &port_low,
|
||||
&port_high) == 0, status, "unrecognized "
|
||||
"input \"%s\", expect \"port_from:"
|
||||
"port_to\"", tokens[ti]);
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
rule_ipv6->field[10].value.u16 = port_low;
|
||||
rule_ipv6->field[10].mask_range.u16 = port_high;
|
||||
|
||||
dport_p = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* unrecognizeable input */
|
||||
APP_CHECK(0, status, "unrecognized input \"%s\"",
|
||||
tokens[ti]);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check if argument(s) are missing */
|
||||
APP_CHECK(esp_p == 1, status, "missing argument \"esp\"");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
APP_CHECK(protect_p | bypass_p | discard_p, status, "missing "
|
||||
"argument \"protect\", \"bypass\", or \"discard\"");
|
||||
if (status->status < 0)
|
||||
return;
|
||||
|
||||
*ri = *ri + 1;
|
||||
}
|
||||
};
|
||||
|
||||
static inline void
|
||||
print_one_ip6_rule(const struct acl6_rules *rule, int32_t extra)
|
||||
@ -407,11 +616,9 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
|
||||
}
|
||||
|
||||
void
|
||||
sp6_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
|
||||
sp6_init(struct socket_ctx *ctx, int32_t socket_id)
|
||||
{
|
||||
const char *name;
|
||||
const struct acl6_rules *rules_out, *rules_in;
|
||||
uint32_t nb_out_rules, nb_in_rules;
|
||||
|
||||
if (ctx == NULL)
|
||||
rte_exit(EXIT_FAILURE, "NULL context.\n");
|
||||
@ -424,25 +631,19 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep)
|
||||
rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
|
||||
"already initialized\n", socket_id);
|
||||
|
||||
if (ep == 0) {
|
||||
rules_out = acl6_rules_out;
|
||||
nb_out_rules = RTE_DIM(acl6_rules_out);
|
||||
rules_in = acl6_rules_in;
|
||||
nb_in_rules = RTE_DIM(acl6_rules_in);
|
||||
} else if (ep == 1) {
|
||||
rules_out = acl6_rules_in;
|
||||
nb_out_rules = RTE_DIM(acl6_rules_in);
|
||||
rules_in = acl6_rules_out;
|
||||
nb_in_rules = RTE_DIM(acl6_rules_out);
|
||||
} else
|
||||
rte_exit(EXIT_FAILURE, "Invalid EP value %u. "
|
||||
"Only 0 or 1 supported.\n", ep);
|
||||
|
||||
if (nb_acl6_rules_in > 0) {
|
||||
name = "sp_ip6_in";
|
||||
ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name, socket_id,
|
||||
rules_in, nb_in_rules);
|
||||
ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name,
|
||||
socket_id, acl6_rules_in, nb_acl6_rules_in);
|
||||
} else
|
||||
RTE_LOG(WARNING, IPSEC, "No IPv6 SP Inbound rule "
|
||||
"specified\n");
|
||||
|
||||
if (nb_acl6_rules_out > 0) {
|
||||
name = "sp_ip6_out";
|
||||
ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name, socket_id,
|
||||
rules_out, nb_out_rules);
|
||||
ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name,
|
||||
socket_id, acl6_rules_out, nb_acl6_rules_out);
|
||||
} else
|
||||
RTE_LOG(WARNING, IPSEC, "No IPv6 SP Outbound rule "
|
||||
"specified\n");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user