-*- emacs-wiki -*-

The document describes the steps that a packet goes through when it is
received by pluto.  This is not a state machine, but rather a call graph,
in general each run through the process causes a single state change.

* read_packet()

The packet is received from the network and the origin and destination
address and the ports of the packet are recorded. Based upon the destination
port, a particular interface definition is chosen.

The packet is stored into an object called the "msg_digest"

A single common (statically allocated) msg_digest is used to receive all
packets, if it needs to be saved (not the common case), it is copied.

* process_packet()

process_packet() is the primary function which parses the incoming packet.
In the diagram, this is why all other functions appear to be called from this
function. 

* de-marshal payloads (in_struct)

The first step is to take the packet apart. This is done by the in_struct()
routine, which turns the wire format into a structure, found in md->hdr.

* examine isa_xchg

The first step is to look at the exchange type. Many exchange types are not
supported.  In general each type will cause a new state to be created when
the msgid is different than a different code was done.

* find/create state object

Each type will search for a state object that matches the set of cookies, and
the message id. If no state object is found, a new one may be created.

If the state is not found by the message ID, then we look for state with a
zero message ID. If that is found, then the state is adjusted to now be for
this message ID. 

* determine valid transitions

Once we have a state object, it can determined what are valid transitions
from this state to another state. The selection is typically based upon what
payloads are present in the message. The transition microcode has a bit for
each payload type, and based upon this we determine if there would be a valid
state transition. 

This microcode also then indicates things such as whether or not the message
should be encrypted, and whether or not additional options payloads may appear.

* verify state is not suspended

The state may be suspended. This will occur if there is computation (such as
a Diffie-Hellman exponentiation) occuring or a network lookup is occuring
(DNS). If so, the packet will be dropped. Likely, it is a retransmission
anyway. 

Retransmissions are also detected --- if we have already replied to this
message, then we will have saved the outgoing packet, and it is simply
resent. 

* decrypt packet if appropriate

The message may have been encrypted. The state transition may be valid only
with an encrypted message. These two conditions are compared, and if they
match, then the message is decrypted. 

The resulting new data will have new payloads, and these will be
de-marshalled.
 
* calculate hash if appropriate

Prior to losing track of the newly decrypted message, we calculate 
over the plaintext, which may be used later on to authenticate the message.

* enforce ordering of payloads

Some ordering of payloads is mandated, and without this ordering the message
may not make sense. This is then checked.

* state specific func

The state transition microcode ("smc") will have designated a particular
function handle the state transition.  The function will be passed a pointer
to the pointer to the message digest, and a pointer to the microcode.

The reason a pointer to a pointer is passed is so that the state specific
function can set the message digest to NULL. It will do this in situations
where it needs to keep a copy of the message for later examination by a
continuation function. Since the pointer will now be NULL, the enclosing
read_packet() function will not free the message digest, and a new one will
be allocated for the next packet.

State specific functions are named for the exchange type, and message number
they expect. For instance, [[quick_inI1_outR1]] is part of a QuickMode (aka
"Phase 2") exchange, and is called by the responder when it receives message
I1 in order to prepare the R1 message 

A typical negotiation looks like this:

     [[main_outI1]]
                       ------I1----->
                                       [[main_inI1_outR1]]
                       <-----R1------
     [[main_inR1_outI2]]
                       ------I2----->
                                       [[main_inI2_outR2]]
                       <-----R2------
     [[main_inR2_outI3]]
                       ------I3----->
                                       [[main_inI3_outR3]]
                       <-----R3------
     [[main_inR3]]
         |             PHASE 1 ESTABLISHED            
         | 
         V
     [[quick_outI1]]
                       ------I1----->
                                      [[quick_inI1_outR1]]
                       <-----R1------
     [[quick_inR1_outI2]]
         |             ------I2----->
         |                            [[quick_inI2]]
         |                                 |
         V                                 V
     PHASE 2 ESTABLISHED            PHASE 2 ESTABLISHED


Details about each state transition is covered in additional pages above.

* complete_state_transition()

The state specific function is expected to return one of the following
returns of type stf_status (State Transition Function Status).

** STF_IGNORE

An ignore value means that this message should not cause any change to the
current stat. No further processing is done.

** STF_INLINE

A return of INLINE is a meta value, and means that the state transition has
already been performed.

** STF_SUSPEND

A return of SUSPEND means that the state transition function could not (yet)
complete the state transition. A continuation function (to be called later)
will likely complete the transition.

** STF_FATAL

A return of FATAL means that something is wrong in the configuration of this
connection pluto, and likely that it will be unable to continue processing. 

** STF_INTERNAL_ERROR

An internal error means that a system wide resource is misconfigured, and it
is likely that no connection will succeed.

** STF_FAIL

A simple failure means that the message was not successfully processed. This
could be due to inability to authenticate the message, mismatches in policy,
etc. It may also be due to malicious corruption of the exchange.

** STF_TOO_MUCH_CRYPTO

The message could not be processed at this time because the system is too
busy processing other (more important) messages. The message is dropped, and
retransmission will take care of resending it.

** STF_OK

The message was successfully processed, and the state should be advanced.
The received message is record (in case it is retransmitted), and if this
state requires a response, any response message will then be sent.

*** send_packet()

The send_packet() process actually transmits the reply. It uses the remote
address and port that has been stored in the state structure, since the
NAT-traversal code may have updated these values.

* encrypt packet

The state specific function, if it prepares a reply packet, may need to
encrypt it. This is done in a single function.

* continuation

Many state specific functions require that some work be done: this may
involve one or more DNS or LDAP lookups to retrieve public keys, or may
involve performing lengthy cryptographic operations. In this case, the state
specific function will arrange to have the operation started. A continuation
structure is created when the operation is started, and the state specific
function will return STF_SUSPENDED.

When the asynchronous operation is completed, a continuation function (often
called the _tail function) is called, it is provided with the continuation
structure, and a reply message is fashioned. Typically, the continuation
function will then call complete_state_transition() itself.

