anchor.diff:    inject(RemoteIp, Ip, Data),
     ok.
   
  -syn_pre(S, [Ip, Port, _, _, _]) ->
  +syn_pre(Ss, [Ip, Port, _, _, _, Id]) ->
  +  [ S ] = [ S || S<-Ss, S#state.id == Id ],
     S#state.ip   == Ip andalso
  -  S#state.port == Port.
  -
  -syn_adapt(S, [_, _ | Args]) ->
  -  [S#state.ip, S#state.port | Args].
  -
  -syn_callouts(_S, [_Ip,  _Port, RemoteIp, RemotePort, RemoteSeq]) ->
  -  ?SET(rip, RemoteIp),
  -  ?SET(rport, RemotePort),
  -  ?SET(rseq, {RemoteSeq, 1}),
  -  ?APPLY(sent_syn_ack, []),
  -  ?SET(tcp_state, syn_rcvd).
  +  S#state.port == Port andalso
  +    in_tcp_state(Ss, Id, listen).
  +
  +syn_adapt(Ss, [_, _, Ip, Port, Seq, Id]) ->
  +  [ S ] = [ S || S<-Ss, S#state.id == Id ],
  +  [S#state.ip, S#state.port, Ip, Port, Seq, Id].
  +
  +syn_callouts(_S, [_Ip,  _Port, RemoteIp, RemotePort, RemoteSeq, Id]) ->
  +  ?SET(Id, rip, RemoteIp),
  +  ?SET(Id, rport, RemotePort),
  +  ?SET(Id, rseq, {RemoteSeq, 1}),
  +  ?APPLY(sent_syn_ack, [Id]),
  +  ?SET(Id, tcp_state, syn_rcvd).
   
   
   %% --- syn_ack ---
   
  -syn_ack_pre(S) ->
  -  in_tcp_state(S, syn_sent) andalso
  -  S#state.rcvd == S#state.seq.
  -
  -syn_ack_args(S) ->
  +%% syn_ack_pre(S) ->
  +%%   in_tcp_state(S, syn_sent) andalso
  +%%   S#state.rcvd == S#state.seq.
  +
  +syn_ack_args(Ss) ->
  +  ?LET(S, elements(Ss),
  +       [S#state.ip, S#state.port, S#state.rip,
  +        S#state.rport, uint32(), S#state.seq, S#state.id]).
  +
  +syn_ack_pre(Ss, [Ip, Port, RIp, RPort, _, Seq, Id]) ->
  +  [ S ] = [ S || S<-Ss, S#state.id == Id ],
  +  in_tcp_state(Ss, Id, syn_sent) andalso
  +    S#state.rcvd == S#state.seq andalso
  +    Ip    == S#state.ip    andalso
  +    Port  == S#state.port  andalso
  +    RIp   == S#state.rip   andalso
  +    RPort == S#state.rport andalso
  +    Seq   == S#state.seq.
  +
  +syn_ack_adapt(Ss, [_, _, _, _, Seq, _, Id]) ->
  +  [ S ] = [ S || S<-Ss, S#state.id == Id ],
     [S#state.ip, S#state.port, S#state.rip,
  -   S#state.rport, uint32(), S#state.seq].
  -
  -syn_ack_pre(S, [Ip, Port, RIp, RPort, _, Seq]) ->
  -  Ip    == S#state.ip    andalso
  -  Port  == S#state.port  andalso
  -  RIp   == S#state.rip   andalso
  -  RPort == S#state.rport andalso
  -  Seq   == S#state.seq.
  -
  -syn_ack_adapt(S, [_, _, _, _, Seq, _]) ->
  -  [S#state.ip, S#state.port, S#state.rip,
  -   S#state.rport, Seq, S#state.seq].
  -
  -syn_ack(Ip, Port, RemoteIp, RemotePort, Seq, Ack) ->
  +   S#state.rport, Seq, S#state.seq, Id].
  +
  +syn_ack(Ip, Port, RemoteIp, RemotePort, Seq, Ack, _) ->
     Packet =
       #pkt{sport = RemotePort,
           dport  = Port,
  
positive.code:   inject(RemoteIp, Ip, Data),
    ok.
  
  fin_callouts(S, [_Ip, _Port, _RemoteIp, _RemotePort, _Seq, _]) ->
    ?INC(rseq),
    ?APPLY(sent_ack, []),
    case S#state.tcp_state of
      established ->
        ?SET(tcp_state, close_wait);
      fin_wait_1 ->
        case S#state.seq == S#state.rcvd of %% FIN+ACK ?
          true ->
            ?UNBLOCK(close, ok),
            ?SET(tcp_state, time_wait);
          false ->
            ?SET(tcp_state, closing)
        end;
      fin_wait_2  ->
        ?UNBLOCK(close, ok),
        ?SET(tcp_state, time_wait)
    end.
  
  %% --- deliver ---
  
  deliver_pre(S) ->
    S#state.rcvd /= S#state.seq.
  
  deliver_args(_S) -> [].
  
  deliver() -> timer:sleep(1).
  
  deliver_callouts(S, []) ->
    ?SET(rcvd, S#state.seq).
  
  %% -- Local operations -------------------------------------------------------
  
  reset_callouts(_S, []) ->
    ?SET(port,  undefined),
    ?SET(rport, undefined),
    ?SET(seq,   undefined),
    ?SET(rseq,  undefined).
  
  sent_syn_callouts(_S, []) ->
    ?MATCH(Packet, ?APPLY(sent, [])),
    Port = {call, erlang, element, [#pkt.sport, Packet]},
    ?ASSERT(?MODULE, check_packet, [Packet, '_', '_', [syn]]),
    ?SET(seq, {{call, erlang, element, [#pkt.seq, Packet]}, 1}),
    ?RET(Port).
  
  sent_ack_callouts(S, []) ->
    ?MATCH(Packet, ?APPLY(sent, [])),
    ?ASSERT(?MODULE, check_packet, [Packet, S#state.seq, S#state.rseq, [ack]]),
    ?RET(ok).
  
  sent_fin_callouts(S, []) ->
    ?MATCH(Packet, ?APPLY(sent, [])),
    ?ASSERT(?MODULE, check_packet, [Packet, S#state.seq, S#state.rseq, [ack, fin]]),
    ?INC(seq),
    ?RET(ok).
  
  sent_syn_ack_callouts(S, []) ->
    ?MATCH(Packet, ?APPLY(sent, [])),
    ?ASSERT(?MODULE, check_packet, [Packet, '_', S#state.rseq, [ack, syn]]),
    ?SET(seq, {{call, erlang, element, [#pkt.seq, Packet]}, 1}),
    ?RET(ok).
  
  sent_callouts(S, []) ->
    ?MATCH({Packet, ok}, ?CALLOUT(ip, send_pkt, [?VAR, S#state.rip], ok)),
    ?ASSERT(?MODULE, verify_checksum, [S#state.ip, S#state.rip, Packet]),
    ?ASSERT(?MODULE, check_ports,     [S#state.port, S#state.rport, Packet]),
    ?RET(Packet).
  
  set_socket_callouts(_, []) ->
    ?MATCH({Socket, ok}, ?CALLOUT(mock, set_socket, [?VAR], ok)),
    ?SET(socket, Socket).
  
  set_next(S, _, [Key, Value]) ->
    setelement(Key, S, Value).
  
  inc_next(S, _, [Key]) ->
    N = case element(Key, S) of
          {Init, Offs}         -> {Init, Offs + 1};
          M when is_integer(M) -> M + 1;
          undefined -> undefined
        end,
    setelement(Key, S, N).
  
  check_ports(SPort, DPort, Packet) ->
    conj([tag(source_port,      match(Packet#pkt.sport, SPort)),
  
negative.code:   inject(RemoteIp, Ip, Data),
    ok.
  
  syn_ack_callouts(_S, [_Ip, _Port, _RemoteIp, _RemotePort, Seq, _Ack, Id]) ->
    ?SET(Id, rseq, {Seq, 1}),
    ?UNBLOCK({syn_sent, Id}, ok).
  
  
  %% --- ack ---
  
  %% ack_pre(S) ->
  %%   in_tcp_state(S, [syn_rcvd, last_ack, fin_wait_1, closing]) andalso
  %%   S#state.seq == S#state.rcvd.
  
  ack_args(Ss) ->
    ?LET(S, elements(Ss),
         [S#state.ip, S#state.port,
          S#state.rip,
          S#state.rport,
          S#state.rseq,
          S#state.seq, S#state.id]).
  
  ack_pre(Ss, [Ip,  Port, RIp, RPort, Seq, Ack, Id]) ->
    [ S ] = [ S || S<-Ss, S#state.id == Id ],
    in_tcp_state(Ss, Id, [syn_rcvd, last_ack, fin_wait_1, closing]) andalso
      S#state.seq == S#state.rcvd andalso
      Ip    == S#state.ip    andalso
      Port  == S#state.port  andalso
      RIp   == S#state.rip   andalso
      RPort == S#state.rport andalso
      Seq   == S#state.rseq andalso
      Ack   == S#state.seq.
  
  ack_adapt(Ss, [_, _, _, _, _, _, Id]) ->
    [ S ] = [ S || S<-Ss, S#state.id == Id ],
    [S#state.ip, S#state.port,
     S#state.rip,
     S#state.rport,
     S#state.rseq,
     S#state.seq, Id].
  
  ack(Ip,  Port, RemoteIp, RemotePort, Seq, Ack, _) ->
    Packet =
      #pkt{sport = RemotePort,
           dport = Port,
  