[ Team LiB ] Previous Section Next Section

19.3 Dumping the Security Association Database (SADB)

To dump the current SADB, a process uses the SADB_DUMP message. This is the simplest message to send since the message does not require any extensions, simply the 16-byte sadb_msg header. After the process sends the SADB_DUMP message to the kernel on a key management socket, the kernel replies with a series of SADB_DUMP messages back to the same socket, each with one entry from the SADB. The end of the list is indicated by a message with a value of 0 for the sadb_msg_seq field.

The type of SA can be limited by setting the sadb_msg_satype field in the request to one of the values in Figure 19.3. If it is set to SADB_SATYPE_UNSPEC, then all SAs in the database are returned. Otherwise, only SAs of the specified type are returned. Not all types of security associations are supported by all implementations. The KAME implementation only supports IPsec SAs (SADB_SATYPE_AH and SADB_SATYPE_ESP), so an attempt to dump SADB_SATYPE_RIPV2 SADB entries will get an error reply with errno EINVAL. When requesting a specific type whose table is empty, the errno ENOENT is returned.

Our program to dump the SADB follows in Figure 19.5.

Figure 19.5 Program to issue SADB_DUMP command on key management socket.

key/dump.c

 1 void
 2 sadb_dump(int type)
 3 {
 4     int     s;
 5     char    buf[4096];
 6     struct sadb_msg msg;
 7     int     goteof;

 8     s = Socket(PF_KEY, SOCK_RAW, PF_KEY_V2);

 9     /* Build and write SADB_DUMP request */
10     bzero(&msg, sizeof (msg));
        11     msg.sadb_msg_version = PF_KEY_V2;
12     msg.sadb_msg_type = SADB_DUMP;
13     msg.sadb_msg_satype = type;
14     msg.sadb_msg_len = sizeof (msg) / 8;
15     msg.sadb_msg_pid = getpid();
16     printf("Sending dump message:\n");
17     print_sadb_msg (&msg, sizeof (msg));
18     Write(s, &msg, sizeof (msg));

19     printf("\nMessages returned:\n");
20     /* Read and print SADB_DUMP replies until done */
21     goteof = 0;
22     while (goteof == 0) {
23         int     msglen;
24         struct sadb_msg *msgp;

25         msglen = Read(s, &buf, sizeof (buf));
26         msgp = (struct sadb_msg *) &buf;
27         print_sadb_msg(msgp, msglen);
28         if (msgp->sadb_msg_seq == 0)
29             goteof = 1;
30     }
31     close(s);
32 }
33 int
34 main(int argc, char **argv)
35 {
36     int     satype = SADB_SATYPE_UNSPEC;
37     int     c;

38     opterr = 0;                  /* don't want getopt () writing to stderr */
39     while ( (c = getopt(argc, argv, "t:")) !=  -1) {
40         switch (c) {
41         case 't':
42             if ( (satype = getsatypebyname (optarg) ) == -1)
43                 err_quit("invalid -t option %s", optarg);
44             break;

45         default:
46             err_quit("unrecognized option: %c", c);
47         }
48     }
49     sadb_dump(satype);
50 }

This is our first encounter with the POSIX getopt function. The third argument is a character string specifying the characters that we allow as command-line arguments, just t in this example. It is followed by a colon, indicating that the option takes an argument. In programs that take more than one option, they are concatenated together; for example, Figure 29.7 passes 0i:l:v to indicate that it accepts four options; i and l take an argument and 0 and v don't. This function works with four global variables that are defined by including <unistd.h>.


extern char   *optarg;
extern int     optind, opterr, optopt;

Before calling getopt, we set opterr to 0 to prevent the function from writing error messages to standard error in case of an error, because we want to handle these. POSIX states that if the first character of the third argument is a colon, this also prevents the function from writing to standard error, but not all implementations support this.

Open PF_KEY socket

18 We first open a PF_KEY socket. This requires system privileges, as described earlier, since this allows access to sensitive keying material.

Build SADB_DUMP request

915 We first zero out the sadb_msg struct so that we can skip initializing the fields that we wish to remain zero. We fill in each remaining field in the sadb_msg struct individually. All messages on sockets opened with PF_KEY_V2 as the third argument must also use PF_KEY_V2 as the message version. The message type is SADB_DUMP. We set the length to the length of the base header with no extensions since the dump message does not take extensions. Finally, we set the process ID (PID) to our own PID since all messages must be identified by the PID of the sender.

Display and write SADB_DUMP message

1618 We display the message using our print_sadb_msg routine. We don't show this routine since it is long and uninteresting, but it is included in the freely available source code. This routine accepts a message that is being written to or has been received from a key management socket and prints all the information from the message in a human-readable form. We then write the message to the socket.

Read replies

1930 We loop, reading replies and printing them using our print_sadb_msg function. The last message in the dump sequence has a message sequence number of zero, so we use this as our "end-of-file" indication.

Close PF_KEY socket

31 Finally, we close the socket that we opened.

Handle command-line arguments

3848 The main function has very little work to do. This program takes a single optional argument, which is the type of SA to dump. By default, the type is SADB_SATYPE_UNSPEC, which dumps all SAs of any type. By specifying a command-line argument, the user can select which type of SAs to dump. This program uses our getsatypebyname function, which returns the type value for a text string.

Call sadb_dump routine

49 Finally, we call the sadb_dump function we defined above to do all the work.

Sample Run

The following is a sample run of the dump program on a system with two static SAs.


macosx % dump
Sending dump message:
SADB Message Dump, errno 0, satype Unspecified, seq 0, pid 20623

Messages returned:
SADB Message Dump, errno 0, satype IPsec AH, seq 1, pid 20623
 SA: SPI=258 Replay Window=0 State=Mature
  Authentication Algorithm: HMAC-MD5
   Encryption Algorithm: None
  [unknown extension 19]
  Current lifetime:
   0 allocations, 0 bytes
   added at Sun May 18 16:28:11 2003, never used
  Source address:     2.3.4.5/128 (IP proto 255)
  Dest address:     6.7.8.9/128 (IP proto 255)
  Authentication key, 128 bits: 0x20202020202020200202020202020202
SADB Message Dump, errno 0, satype IPsec AH, seq 0, pid 20623
 SA: SPI=257 Replay Window=0 State=Mature
  Authentication Algorithm: HMAC-MD5
  Encryption Algorithm: None
 [unknown extension 19]
 Current lifetime:
  0 allocations, 0 bytes
  added at Sun May 18 16:26:24 2003, never used
 Source address:     1.2.3.4/128 (IP proto 255)
 Dest address:     5.6.7.8/128 (IP proto 255)
 Authentication key, 128 bits: 0x10101010101010100101010101010101



    [ Team LiB ] Previous Section Next Section