anchor.diff:  %% @doc Starts the server
   %% @end
   %%--------------------------------------------------------------------
  -start_link() ->
  -    gen_server:start_link(?MODULE, [], []).
  +start() ->
  +    gen_server:start(?MODULE, [], []).
   
   attach(Interface) ->
  -    {ok, Pid} = start_link(),
  +    {ok, Pid} = start(),
       attach(Pid, Interface).
   
   attach(Dumper, Interface) ->
       gen_server:call(Dumper, {sub, Interface}),
       {ok, Dumper}.
   
  -eth_addr(Cache, IpAddr) ->
  -    gen_server:call(Cache, {eth_addr, IpAddr}).
  +eth_addr(Pid, IpAddr) ->
  +    gen_server:call(Pid, {eth_addr, IpAddr}).
   
  -ip_addr(Cache, EthAddr) ->
  -    gen_server:call(Cache, {ip_addr, EthAddr}).
  +ip_addr(Pid, EthAddr) ->
  +    gen_server:call(Pid, {ip_addr, EthAddr}).
   
  +publish(Pid, EthAddr, IpAddr) ->
  +    gen_server:call(Pid, {publish, EthAddr, IpAddr}).
  +
  +arp_filter({enet, _, {rx, _, #eth{type=arp}}}) -> true;
  +arp_filter(_) -> false.
   
   %%====================================================================
   %% gen_server callbacks
   %%====================================================================
   
  -%%--------------------------------------------------------------------
   %% @private
  -%% @spec init(Args) -> {ok, State} |
  -%%                     {ok, State, Timeout} |
  -%%                     ignore               |
  -%%                     {stop, Reason}
  -%% @doc Initialises the server's state
  -%% @end
  -%%--------------------------------------------------------------------
   init([]) ->
  -    Tid = ets:new(?MODULE, []),
  -    {ok, #state{tid=Tid}}.
  +    {ok, #state{cache = enet_arp_cache:new()}}.
   
  -%%--------------------------------------------------------------------
   %% @private
  -%% @spec 
  -%% handle_call(Request, From, State) -> {reply, Reply, State} |
  -%%                                      {reply, Reply, State, Timeout} |
  -%%                                      {noreply, State} |
  -%%                                      {noreply, State, Timeout} |
  -%%                                      {stop, Reason, Reply, State} |
  -%%                                      {stop, Reason, State}
  -%% @doc Call message handler callbacks
  -%% @end
  -%%--------------------------------------------------------------------
  +handle_call({publish, EthAddr, IpAddr}, _From,
  +            State = #state{cache = OldCache}) ->
  +    NewCache = enet_arp_cache:publish(EthAddr, IpAddr, OldCache),
  +    {reply, ok, State#state{cache = NewCache}};
  +handle_call({eth_addr, IpAddr}, _From, State = #state{cache = Cache}) ->
  +    case enet_arp_cache:lookup_ip_addr(IpAddr, Cache) of
  +        not_found ->
  +            {reply, not_found, State};
  +        #entry{ethaddr = Addr} ->
  +            {reply, Addr, State}
  +    end;
  +
  +handle_call({ip_addr, EthAddr}, _From, State = #state{cache = Cache}) ->
  +    case enet_arp_cache:lookup_eth_addr(EthAddr, Cache) of
  +        not_found ->
  +            {reply, not_found, State};
  +        #entry{ipaddr = Addr} ->
  +            {reply, Addr, State}
  +    end;
   
   handle_call({sub, Interface}, _From, State) ->
  -    {reply, pubsub:sync_subscribe(Interface), State};
  +    {reply, pubsub:sync_subscribe(Interface, fun ?MODULE:arp_filter/1), State};
   
   handle_call(Call, _From, State) ->
       ?WARN("Unexpected call ~p.", [Call]),
       {noreply, State}.
   
  -%%--------------------------------------------------------------------
   %% @private
  -%% @spec 
  -%% handle_cast(Msg, State) -> {noreply, State} |
  -%%                            {noreply, State, Timeout} |
  -%%                            {stop, Reason, State}
  -%% @doc Cast message handler callbacks
  -%% @end
  -%%--------------------------------------------------------------------
   handle_cast(Msg, State) ->
       ?WARN("Unexpected cast ~p", [Msg]),
       {noreply, State}.
   
  -%%--------------------------------------------------------------------
  -%% @private
  -%% @spec 
  -%% handle_info(Info, State) -> {noreply, State} |
  -%%                             {noreply, State, Timeout} |
  -%%                             {stop, Reason, State}
  -%% @doc Non gen-server message handler callbacks
  -%% @end
  -%%--------------------------------------------------------------------
  -
  -%% handle_info({enet, _IF, {tx, Frame}}, State) ->
  -%%     P = enet_codec:decode(eth, Frame, [all]),
  -%%     print([{dir, send}, {raw, Frame}, {packet, P}], State),
  -%%     {noreply, State};
  -%% handle_info({enet, _IF, {RX, Frame}}, State)
  -%%   when RX =:= rx;
  -%%        RX =:= promisc_rx ->
  -%%     print([{dir, recv}, {raw, Frame}], State),
  -%%     {noreply, State};
  -handle_info({enet, IF, {RX, Frame, Pkt = #eth{type=arp}}}, State)
  +handle_info({enet, IF, {RX, _Frame, Pkt = #eth{type=arp}}}, State)
     when RX =:= rx;
          RX =:= promisc_rx ->
       handle_arp_rx(IF, Pkt, State),
       {noreply, State};
   
  +
   handle_info(Info, State) ->
       ?WARN("Unexpected info ~p", [Info]),
       {noreply, State}.
   
  -%%--------------------------------------------------------------------
   %% @private
  -%% @spec terminate(Reason, State) -> void()
  -%% @doc This function is called by a gen_server when it is about to
  -%% terminate. It should be the opposite of Module:init/1 and do any necessary
  -%% cleaning up. When it returns, the gen_server terminates with Reason.
  -%% The return value is ignored.
  -%% @end
  -%%--------------------------------------------------------------------
   terminate(_Reason, _State) ->
       ok.
   
  -%%--------------------------------------------------------------------
   %% @private
  -%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
  -%% @doc Convert process state when code is changed
  -%% @end
  -%%--------------------------------------------------------------------
   code_change(_OldVsn, State, _Extra) ->
       {ok, State}.
   
  
positive.code: %%--------------------------------------------------------------------
  
  handle_arp_rx(IF, #eth{type=arp,data=Pkt}, State) ->
      try enet_codec:decode(arp, Pkt) of
          {error, bad_packet} ->
              %% XXX - log corrupt arp packet somehow?
              ignore;
          #arp{} = Q ->
              handle_arp_rx(IF, Q, State)
      catch
          _Type:_Error ->
              %% XXX - couldn't decode Pkt, Type:Error.
              ignore
      end;
  
  handle_arp_rx(IF,
                Q = #arp{htype = ethernet,
                         ptype = Type,
                         op = request,
                         sender = Sender = {SMac, SAddr},
                         target = {TMac, TAddr}
                        },
                State) ->
      case cache_lookup(TAddr, State) of
          [] ->
              ignore;
          [?ARP_ENTRY(CMac, CAddr)] ->
              R = #arp{op = reply,
                       htype = ethernet,
                       ptype = Type,
                       sender = {CMac, CAddr},
                       target = Sender
                      },
              Reply = #eth{dst=SMac, type=arp, data=enet_codec:encode(arp, R)},
              enet_host:send(Reply)
      end.
  
  
  cache_lookup(Key, #state{tid=T}) ->
      ets:lookup(T, Key).
  
negative.code: 
  -behaviour(gen_server).
  
  -include("../include/logging.hrl").
  -include("../include/enet_types.hrl").
  -include("enet_arp_cache.hrl").
  -include_lib("eunit/include/eunit.hrl").
  
  %% API
  -export([start/0]).
  -export([attach/1
           ,eth_addr/2
           ,ip_addr/2
           ,arp_filter/1
           ,publish/3
           ]).
  
  %% gen_server callbacks
  -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
           terminate/2, code_change/3]).
  
  -record(state, {cache}).
  
  %%====================================================================
  %% API
  