ipsec_set_policy()

Updated: April 19, 2023

Generate an IPsec policy specification structure from a readable string

Synopsis:

#include <netinet6/ipsec.h>

char* ipsec_set_policy( char *policy, 
                        int len );

Arguments:

policy
A string that describes a struct sadb_x_policy and optionally a struct sadb_x_ipsecrequest, formatted as described below.
len
The length of the policy string.

Library:

libipsec

Use the -l ipsec option to qcc to link against this library.

Description:

The ipsec_set_policy() function generates an IPsec policy specification structure, namely a struct sadb_x_policy and potentially a struct sadb_x_ipsecrequest from a policy specification given as a C string. The ipsec_set_policy() function allocates a buffer, stores the corresponding IPsec policy specification structure in it, and returns a pointer to the buffer.

Note: You should release the buffer returned by ipsec_set_policy() by calling free(). See the example below.

The policy specifications can include the following variables:

direction
The direction in which to apply the policy. This must be in or out
priority_specification
The priority for the policy. This is a signed integer that controls the placement of the policy within the security policy database (SPD). Policies with higher priorities are placed closer to the beginning of the list, and those with lower priorities are placed closer to the end of the list. Policies with equal priorities are added at the end of the group of such policies. You can specify the priority only when libipsec has been compiled.

The policy specifications include the following:

direction [priority_specification] discard
Drop any packets that match the policy.
direction [priority_specification] entrust
Consult the SPD defined by setkey.
direction [priority_specification] bypass
Bypass the IPsec processing (i.e., transmit packets in clear). This is for privileged sockets.
direction [priority_specification] ipsec request ...
The matching packets are subject to IPsec processing. The ipsec string is followed by one or more request strings, which are formatted as below:

protocol / mode / src - dst [/level]

The elements of the string are as follows:

protocol
Either ah, esp, or ipcomp.
mode
Either transport or tunnel.
src and dst
The IPsec endpoints; src is the sending node and dst is the receiving node. Therefore, when the direction is in, dst is this node and src is the other node (peer). If the mode is transport, you can omit both src and dst.
level
Either default, use, require or unique.
  • defaultio-pkt should consult the system default policy defined by sysctl().
  • use — a relevant SA (security association) is used when available, since io-pkt may perform IPsec operation against packets when possible. In this case, packets are transmitted in clear (when SA isn't available), or encrypted (when SA is available).
  • require — a relevant SA is required, since io-pkt must perform IPsec operation against packets.
  • unique is similar to require, but it adds the restriction that the SA for outbound traffic be used only for this policy. You may need the identifier in order to relate the policy and the SA when you define the SA by manual keying. You put the decimal number as the identifier like:

    unique: number

    where number must be between 1 and 32767.

If the request string is nonambiguous, you can omit the level and the slash (/) before it. However, it's best specify the level explicitly, in order to avoid unintended behavior.

If you omit the level, the default (which you can use sysctl to get or set) is used. For example:

  • If sysctl shows net.inet.ipsec.esp_net_deflev = 1, then by default, the IPsec policy is required for tunnelling mode. That is, if you define a rule specifying IPSec tunnelling from A to B, then the level is require.
  • If you use sysctl to disable net.inet.ipsec.esp_net_deflev, then if you define a rule specifying IPSec tunnelling from A to B, the IPSec rule isn't applied from A to B.

Here's an example of policy information:

in discard
out ipsec esp/transport//require
in ipsec ah/transport//require
out ipsec esp/tunnel/10.1.1.2-10.1.1.1/use
in ipsec ipcom/transport//use esp/transport//use
Note: This differs from the specification of setkey, which doesn't use entrust or bypass.

Returns:

A pointer to the allocated buffer for policy specification, or NULL if an error occurred.

Examples:

#include <netinet6/ipsec.h>
#include <sys/socket.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>

int   
main(void)
{
   char *sadb;
   char *policy = "in discard";
   int len;
   
   sadb = ipsec_set_policy(policy, strlen(policy));

   if (sadb == NULL) {
      fprintf(stderr, "ipsec_set_policy: %s\n", ipsec_strerror());
      return 1;
   }
   
   len = ipsec_get_policylen(sadb);
   printf("len: %d\n", len);

   policy = NULL;
   policy = ipsec_dump_policy(sadb, NULL);

   if (policy == NULL) {
      fprintf(stderr, "ipsec_dump_policy: %s\n", ipsec_strerror());
      return 1;
   }

   printf("policy: %s\n", policy);

   free(policy);
   free(sadb);

   return 0;
}

Classification:

Unix

Safety:  
Cancellation point No
Interrupt handler No
Signal handler No
Thread Yes