merge packet socket with trunk
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Mon, 06 Aug 2007 09:59:29 +0200
changeset 1198 ac0801202d42
parent 1157 972fca2f2b04 (current diff)
parent 1197 e5719ed7c7d5 (diff)
child 1199 d9caeae5943c
merge packet socket with trunk
examples/wscript
src/internet-node/arp-header.cc
src/internet-node/arp-header.h
src/internet-node/arp-private.cc
src/internet-node/arp-private.h
src/internet-node/internet-node.cc
src/internet-node/ipv4-private.cc
src/internet-node/ipv4-private.h
src/internet-node/l3-demux.cc
src/internet-node/l3-demux.h
src/internet-node/l3-protocol.cc
src/internet-node/l3-protocol.h
src/node/ethernet-header.cc
src/node/ethernet-header.h
src/node/ipv4-address.cc
src/node/ipv4-address.h
src/node/mac-address.cc
src/node/mac-address.h
--- a/examples/csma-cd-one-subnet.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/examples/csma-cd-one-subnet.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -50,18 +50,14 @@
 #include "ns3/csma-cd-net-device.h"
 #include "ns3/csma-cd-topology.h"
 #include "ns3/csma-cd-ipv4-topology.h"
-#include "ns3/mac-address.h"
+#include "ns3/eui48-address.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
 #include "ns3/ipv4.h"
 #include "ns3/socket.h"
 #include "ns3/ipv4-route.h"
 #include "ns3/onoff-application.h"
 
-#include "ns3/ascii-trace.h"
-
-#include "ns3/trace-context.h"
-#include "ns3/trace-root.h"
-
 
 using namespace ns3;
 
@@ -105,13 +101,13 @@
       DataRate(5000000), MilliSeconds(2));
 
   uint32_t n0ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n0, channel0, 
-                                         MacAddress("10:54:23:54:23:50"));
+                                         Eui48Address("10:54:23:54:23:50"));
   uint32_t n1ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n1, channel0,
-                                         MacAddress("10:54:23:54:23:51"));
+                                         Eui48Address("10:54:23:54:23:51"));
   uint32_t n2ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n2, channel0,
-                                         MacAddress("10:54:23:54:23:52"));
+                                         Eui48Address("10:54:23:54:23:52"));
   uint32_t n3ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n3, channel0,
-                                         MacAddress("10:54:23:54:23:53"));
+                                         Eui48Address("10:54:23:54:23:53"));
 
   // Later, we add IP addresses.  
   CsmaCdIpv4Topology::AddIpv4Address (
@@ -131,8 +127,7 @@
   // from n0 to n1
   Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
     n0, 
-    Ipv4Address("10.1.1.2"), 
-    80, 
+    InetSocketAddress (Ipv4Address("10.1.1.2"), 80).ConvertTo (), 
     "Udp",
     ConstantVariable(1), 
     ConstantVariable(0));
@@ -143,8 +138,7 @@
   // Create a similar flow from n3 to n0, starting at time 1.1 seconds
   ooff = Create<OnOffApplication> (
     n3, 
-    Ipv4Address("10.1.1.1"), 
-    80, 
+    InetSocketAddress (Ipv4Address("10.1.1.1"), 80).ConvertTo (), 
     "Udp",
     ConstantVariable(1), 
     ConstantVariable(0));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/csma-cd-packet-socket.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,136 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+// Port of ns-2/tcl/ex/simple.tcl to ns-3
+//
+// Network topology
+//
+//       n0    n1   n2   n3
+//       |     |    |    |
+//     =====================
+//
+// - CBR/UDP flows from n0 to n1, and from n3 to n0
+// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
+//   (i.e., DataRate of 448,000 bps)
+// - DropTail queues 
+// - Tracing of queues and packet receptions to file "csma-cd-one-subnet.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/debug.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/csma-cd-channel.h"
+#include "ns3/csma-cd-net-device.h"
+#include "ns3/eui48-address.h"
+#include "ns3/packet-socket-address.h"
+#include "ns3/socket.h"
+#include "ns3/onoff-application.h"
+#include "ns3/queue.h"
+
+using namespace ns3;
+
+static Ptr<CsmaCdNetDevice>
+CreateCsmaCdDevice (Ptr<Node> node, Ptr<CsmaCdChannel> channel)
+{
+  Ptr<CsmaCdNetDevice> device = Create<CsmaCdNetDevice> (node);
+  device->Attach (channel);
+  Ptr<Queue> queue = Queue::CreateDefault ();
+  device->AddQueue (queue);
+  return device;
+}
+
+
+int main (int argc, char *argv[])
+{
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create four nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<Node> ();
+  Ptr<Node> n1 = Create<Node> (); 
+  Ptr<Node> n2 = Create<Node> (); 
+  Ptr<Node> n3 = Create<Node> ();
+
+  // create the shared medium used by all csma/cd devices.
+  Ptr<CsmaCdChannel> channel = Create<CsmaCdChannel> (DataRate(5000000), MilliSeconds(2));
+
+  // use a helper function to connect our nodes to the shared channel.
+  Ptr<NetDevice> n0If = CreateCsmaCdDevice (n0, channel);
+  Ptr<NetDevice> n1If = CreateCsmaCdDevice (n1, channel);
+  Ptr<NetDevice> n2If = CreateCsmaCdDevice (n2, channel);
+  Ptr<NetDevice> n3If = CreateCsmaCdDevice (n3, channel);
+
+
+  // create the address which identifies n1 from n0
+  PacketSocketAddress n0ToN1;
+  n0ToN1.SetSingleDevice (n0If->GetIfIndex ());      // set outgoing interface for outgoing packets
+  n0ToN1.SetPhysicalAddress (n1If->GetAddress ()); // set destination address for outgoing packets
+  n0ToN1.SetProtocol (2);            // set arbitrary protocol for outgoing packets
+
+  // create the address which identifies n0 from n3
+  PacketSocketAddress n3ToN0;
+  n3ToN0.SetSingleDevice (n3If->GetIfIndex ());
+  n3ToN0.SetPhysicalAddress (n0If->GetAddress ());
+  n3ToN0.SetProtocol (3);
+  
+  // Create the OnOff application to send raw datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  // from n0 to n1
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    n0ToN1.ConvertTo (),
+    "Packet",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.0));
+  ooff->Stop (Seconds(10.0));
+
+  // Create a similar flow from n3 to n0, starting at time 1.1 seconds
+  ooff = Create<OnOffApplication> (
+    n3, 
+    n3ToN0.ConvertTo (),
+    "Packet",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.1));
+  ooff->Stop (Seconds(10.0));
+ 
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the csma-cd-packet-socket.tr file
+  AsciiTrace asciitrace ("csma-cd-packet-socket.tr");
+  asciitrace.TraceAllNetDeviceRx ();
+  asciitrace.TraceAllQueues ();
+
+  Simulator::Run ();
+    
+  Simulator::Destroy ();
+}
--- a/examples/simple-p2p.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/examples/simple-p2p.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -56,8 +56,8 @@
 #include "ns3/internet-node.h"
 #include "ns3/p2p-channel.h"
 #include "ns3/p2p-net-device.h"
-#include "ns3/mac-address.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
 #include "ns3/ipv4.h"
 #include "ns3/socket.h"
 #include "ns3/ipv4-route.h"
@@ -143,8 +143,7 @@
   // 210 bytes at a rate of 448 Kb/s
   Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
     n0, 
-    Ipv4Address("10.1.3.2"), 
-    80, 
+    InetSocketAddress("10.1.3.2", 80).ConvertTo (), 
     "Udp",
     ConstantVariable(1), 
     ConstantVariable(0));
@@ -155,8 +154,7 @@
   // Create a similar flow from n3 to n1, starting at time 1.1 seconds
   ooff = Create<OnOffApplication> (
     n3, 
-    Ipv4Address("10.1.2.1"), 
-    80, 
+    InetSocketAddress("10.1.2.1", 80).ConvertTo (),
     "Udp",
     ConstantVariable(1), 
     ConstantVariable(0));
--- a/examples/simple-point-to-point.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/examples/simple-point-to-point.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -57,8 +57,8 @@
 #include "ns3/internet-node.h"
 #include "ns3/point-to-point-channel.h"
 #include "ns3/point-to-point-net-device.h"
-#include "ns3/mac-address.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
 #include "ns3/ipv4.h"
 #include "ns3/socket.h"
 #include "ns3/ipv4-route.h"
@@ -144,8 +144,7 @@
   // 210 bytes at a rate of 448 Kb/s
   Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
     n0, 
-    Ipv4Address("10.1.3.2"), 
-    80, 
+    InetSocketAddress (Ipv4Address("10.1.3.2"), 80).ConvertTo (), 
     "Udp",
     ConstantVariable(1), 
     ConstantVariable(0));
@@ -156,8 +155,7 @@
   // Create a similar flow from n3 to n1, starting at time 1.1 seconds
   ooff = Create<OnOffApplication> (
     n3, 
-    Ipv4Address("10.1.2.1"), 
-    80, 
+    InetSocketAddress (Ipv4Address("10.1.2.1"), 80).ConvertTo (), 
     "Udp",
     ConstantVariable(1), 
     ConstantVariable(0));
--- a/examples/wscript	Mon Aug 06 09:58:03 2007 +0200
+++ b/examples/wscript	Mon Aug 06 09:59:29 2007 +0200
@@ -15,4 +15,5 @@
                          deps=['point-to-point', 'internet-node'])
     obj = create_ns_prog('csma-cd-one-subnet', 'csma-cd-one-subnet.cc', 
                          deps=['csma-cd', 'internet-node'])
+    obj = create_ns_prog('csma-cd-packet-socket', 'csma-cd-packet-socket.cc', deps=['csma-cd', 'internet-node'])
 
--- a/samples/main-simple.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/samples/main-simple.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -4,6 +4,7 @@
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
 #include "ns3/socket.h"
+#include "ns3/inet-socket-address.h"
 #include "ns3/nstime.h"
 
 using namespace ns3;
@@ -24,7 +25,7 @@
 }
 
 static void
-SocketPrinter (Ptr<Socket> socket, uint32_t size, const Ipv4Address &from, uint16_t fromPort)
+SocketPrinter (Ptr<Socket> socket, uint32_t size, const Address &from)
 {
   std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << size << std::endl;
 }
@@ -44,10 +45,12 @@
   Ptr<SocketFactory> socketFactory = a->QueryInterface<SocketFactory> (iid);
 
   Ptr<Socket> sink = socketFactory->CreateSocket ();
-  sink->Bind (80);
+  InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
+  sink->Bind (local.ConvertTo ());
 
   Ptr<Socket> source = socketFactory->CreateSocket ();
-  source->Connect (Ipv4Address::GetLoopback (), 80);
+  InetSocketAddress remote = InetSocketAddress (Ipv4Address::GetLoopback (), 80);
+  source->Connect (remote.ConvertTo ());
 
   GenerateTraffic (source, 500);
   PrintTraffic (sink);
--- a/src/applications/onoff-application.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/applications/onoff-application.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -22,7 +22,7 @@
 // George F. Riley, Georgia Tech, Spring 2007
 // Adapted from ApplicationOnOff in GTNetS.
 
-#include "ns3/ipv4-address.h"
+#include "ns3/address.h"
 #include "ns3/node.h"
 #include "ns3/nstime.h"
 #include "ns3/data-rate.h"
@@ -47,22 +47,20 @@
 // Constructors
 
 OnOffApplication::OnOffApplication(Ptr<Node> n, 
-                                   const Ipv4Address  rip,
-                                   uint16_t rport,
+                                   const Address &remote,
                                    std::string iid,
                                    const  RandomVariable& ontime,
                                    const  RandomVariable& offtime)
   :  Application(n),
      m_cbrRate (g_defaultRate.GetValue ())
 {
-  Construct (n, rip, rport, iid,
+  Construct (n, remote, iid,
              ontime, offtime, 
              g_defaultSize.GetValue ());
 }
 
 OnOffApplication::OnOffApplication(Ptr<Node> n, 
-                                   const Ipv4Address  rip,
-                                   uint16_t rport,
+                                   const Address &remote,
                                    std::string iid,
                                    const  RandomVariable& ontime,
                                    const  RandomVariable& offtime,
@@ -71,22 +69,20 @@
   :  Application(n),
      m_cbrRate (rate)
 {
-  Construct (n, rip, rport, iid, 
+  Construct (n, remote, iid, 
              ontime, offtime, size);
 }
 
 void
 OnOffApplication::Construct (Ptr<Node> n, 
-                             const Ipv4Address  rip,
-                             uint16_t rport,
+                             const Address &remote,
                              std::string iid,
                              const  RandomVariable& onTime,
                              const  RandomVariable& offTime,
                              uint32_t size)
 {
   m_socket = 0;
-  m_peerIp = rip;
-  m_peerPort = rport;
+  m_peer = remote;
   m_connected = false;
   m_onTime = onTime.Copy ();
   m_offTime = offTime.Copy ();
@@ -144,7 +140,7 @@
       Ptr<SocketFactory> socketFactory = GetNode ()->QueryInterface<SocketFactory> (iid);
       m_socket = socketFactory->CreateSocket ();
       m_socket->Bind ();
-      m_socket->Connect (m_peerIp, m_peerPort);
+      m_socket->Connect (m_peer);
     }
   // Insure no pending event
   StopApplication();
--- a/src/applications/onoff-application.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/applications/onoff-application.h	Mon Aug 06 09:59:29 2007 +0200
@@ -31,7 +31,7 @@
 
 namespace ns3 {
 
-class Ipv4Address;
+class Address;
 class RandomVariable;
 class Socket;
 class DataRate;
@@ -52,23 +52,20 @@
 public:
   /**
    * \param n node associated to this application
-   * \param rip remote ip address
-   * \param rport remove port number
+   * \param remote remote ip address
    * \param iid
    * \param ontime on time random variable
    * \param offtime off time random variable
    */
   OnOffApplication(Ptr<Node> n,
-                   const Ipv4Address rip,
-                   uint16_t rport,
+                   const Address &remote,
                    std::string iid,
                    const RandomVariable& ontime,
                    const RandomVariable& offtime);
 
   /**
    * \param n node associated to this application
-   * \param rip remote ip address
-   * \param rport remove port number
+   * \param remote remote ip address
    * \param iid
    * \param ontime on time random variable
    * \param offtime off time random variable
@@ -76,8 +73,7 @@
    * \param size size of packets when sending data.
    */
   OnOffApplication(Ptr<Node> n,
-                   const Ipv4Address rip,
-                   uint16_t rport,
+                   const Address &remote,
                    std::string iid,
                    const RandomVariable& ontime,
                    const RandomVariable& offtime,
@@ -112,8 +108,7 @@
   virtual void StopApplication (void);     // Called at time specified by Stop
 
   void Construct (Ptr<Node> n,
-                  const Ipv4Address rip,
-                  uint16_t rport,
+                  const Address &remote,
                   std::string iid,
                   const RandomVariable& ontime,
                   const RandomVariable& offtime,
@@ -126,8 +121,7 @@
   void SendPacket();
 
   Ptr<Socket>     m_socket;       // Associated socket
-  Ipv4Address     m_peerIp;       // Peer IP address
-  uint16_t        m_peerPort;     // Peer port
+  Address         m_peer;         // Peer address
   bool            m_connected;    // True if connected
   RandomVariable* m_onTime;       // rng for On Time
   RandomVariable* m_offTime;      // rng for Off Time
--- a/src/common/array-trace-resolver.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/common/array-trace-resolver.h	Mon Aug 06 09:59:29 2007 +0200
@@ -81,11 +81,11 @@
    */
   ArrayTraceResolver (TraceContext const &context,
                       Callback<uint32_t> getSize, 
-                      Callback<T *, uint32_t> get);
+                      Callback<T, uint32_t> get);
 private:
   virtual TraceResolverList DoLookup (std::string id) const;
   Callback<uint32_t> m_getSize;
-  Callback<T *, uint32_t> m_get;
+  Callback<T, uint32_t> m_get;
 };
 }//namespace ns3
 
@@ -108,7 +108,7 @@
 template <typename T>
 ArrayTraceResolver<T>::ArrayTraceResolver (TraceContext const &context,
                                            Callback<uint32_t> getSize, 
-                                           Callback<T *, uint32_t> get)
+                                           Callback<T, uint32_t> get)
   : TraceResolver (context),
     m_getSize (getSize),
     m_get (get)
@@ -122,10 +122,10 @@
   {
     for (uint32_t i = 0; i < m_getSize (); i++)
     {
-	  TraceContext context = GetContext ();
+      TraceContext context = GetContext ();
       typename ArrayTraceResolver<T>::Index index = typename ArrayTraceResolver<T>::Index (i);
-	  context.Add (index);
-	  list.push_back (m_get (i)->CreateTraceResolver (context));
+      context.Add (index);
+      list.push_back (m_get (i)->CreateTraceResolver (context));
     }
   }
   return list;
--- a/src/devices/csma-cd/csma-cd-ipv4-topology.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/devices/csma-cd/csma-cd-ipv4-topology.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -38,7 +38,7 @@
 uint32_t
 CsmaCdIpv4Topology::AddIpv4CsmaCdNode(Ptr<Node> n1,
                                       Ptr<CsmaCdChannel> ch,
-                                      MacAddress addr)
+                                      Eui48Address addr)
 {
   Ptr<Queue> q = Queue::CreateDefault ();
 
@@ -55,7 +55,7 @@
 void
 CsmaCdIpv4Topology::AddIpv4LlcCsmaCdNode(Ptr<Node> n1,
                                          Ptr<CsmaCdChannel> ch,
-                                         MacAddress addr)
+                                         Eui48Address addr)
 {
   Ptr<Queue> q = Queue::CreateDefault ();
 
@@ -75,7 +75,7 @@
 void
 CsmaCdIpv4Topology::AddIpv4RawCsmaCdNode(Ptr<Node> n1,
                                          Ptr<CsmaCdChannel> ch,
-                                         MacAddress addr)
+                                         Eui48Address addr)
 {
   Ptr<Queue> q = Queue::CreateDefault ();
 
--- a/src/devices/csma-cd/csma-cd-ipv4-topology.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/devices/csma-cd/csma-cd-ipv4-topology.h	Mon Aug 06 09:59:29 2007 +0200
@@ -62,8 +62,8 @@
    * \return ifIndex of the device
    */
   static uint32_t AddIpv4CsmaCdNode( Ptr<Node> n1,
-                                 Ptr<CsmaCdChannel> ch,
-                                 MacAddress addr);
+                                     Ptr<CsmaCdChannel> ch,
+                                     Eui48Address addr);
 
   /**
    * \param n1 Node to be attached to the Csma/Cd channel
@@ -76,7 +76,7 @@
    */
   static void AddIpv4RawCsmaCdNode( Ptr<Node> n1,
                                     Ptr<CsmaCdChannel> ch,
-                                    MacAddress addr);
+                                    Eui48Address addr);
 
   /**
    * \param n1 Node to be attached to the Csma/Cd channel
@@ -89,7 +89,7 @@
    */
   static void AddIpv4LlcCsmaCdNode( Ptr<Node> n1,
                                     Ptr<CsmaCdChannel> ch,
-                                    MacAddress addr);
+                                    Eui48Address addr);
 
 
 
--- a/src/devices/csma-cd/csma-cd-net-device.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/devices/csma-cd/csma-cd-net-device.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -35,9 +35,19 @@
 
 namespace ns3 {
 
-CsmaCdNetDevice::CsmaCdNetDevice (Ptr<Node> node, MacAddress addr, 
+CsmaCdNetDevice::CsmaCdNetDevice (Ptr<Node> node)
+  : NetDevice (node, Eui48Address::Allocate ().ConvertTo ()),
+    m_bps (DataRate (0xffffffff))
+{
+  NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")");
+  m_encapMode = IP_ARP;
+  Init(true, true);
+}
+
+CsmaCdNetDevice::CsmaCdNetDevice (Ptr<Node> node, Eui48Address addr, 
                                   CsmaCdEncapsulationMode encapMode) 
-  : NetDevice(node, addr), m_bps (DataRate (0xffffffff))
+  : NetDevice(node, addr.ConvertTo ()), 
+    m_bps (DataRate (0xffffffff))
 {
   NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")");
   m_encapMode = encapMode;
@@ -45,10 +55,11 @@
   Init(true, true);
 }
 
-CsmaCdNetDevice::CsmaCdNetDevice (Ptr<Node> node, MacAddress addr, 
+CsmaCdNetDevice::CsmaCdNetDevice (Ptr<Node> node, Eui48Address addr, 
                                   CsmaCdEncapsulationMode encapMode,
                                   bool sendEnable, bool receiveEnable) 
-  : NetDevice(node, addr), m_bps (DataRate (0xffffffff))
+  : NetDevice(node, addr.ConvertTo ()), 
+    m_bps (DataRate (0xffffffff))
 {
   NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")");
   m_encapMode = encapMode;
@@ -94,7 +105,7 @@
   m_channel = 0; 
   m_queue = 0;
 
-  EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff"));
+  EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff").ConvertTo ());
   EnableMulticast();
   EnablePointToPoint();
 
@@ -149,7 +160,7 @@
   m_backoff.m_maxRetries = maxRetries;
 }
 void 
-CsmaCdNetDevice::AddHeader (Packet& p, const MacAddress& dest,
+CsmaCdNetDevice::AddHeader (Packet& p, Eui48Address dest,
                             uint16_t protocolNumber)
 {
   if (m_encapMode == RAW)
@@ -158,7 +169,8 @@
     }
   EthernetHeader header (false);
   EthernetTrailer trailer;
-  header.SetSource(this->GetAddress());
+  Eui48Address source = Eui48Address::ConvertFrom (GetAddress ());
+  header.SetSource(source);
   header.SetDestination(dest);
 
   uint16_t lengthType = 0;
@@ -198,8 +210,10 @@
   trailer.CheckFcs(p);
   p.RemoveHeader(header);
 
-  if ((header.GetDestination() != this->GetBroadcast()) &&
-      (header.GetDestination() != this->GetAddress()))
+  Eui48Address broadcast = Eui48Address::ConvertFrom (GetBroadcast ());
+  Eui48Address destination = Eui48Address::ConvertFrom (GetAddress ());
+  if ((header.GetDestination() != broadcast) &&
+      (header.GetDestination() != destination))
     {
       return false;
     }
@@ -236,7 +250,7 @@
 }
 
 bool
-CsmaCdNetDevice::SendTo (Packet& p, const MacAddress& dest, uint16_t protocolNumber)
+CsmaCdNetDevice::SendTo (Packet& p, const Address& dest, uint16_t protocolNumber)
 {
   NS_DEBUG ("CsmaCdNetDevice::SendTo (" << &p << ")");
   NS_DEBUG ("CsmaCdNetDevice::SendTo (): UID is " << p.GetUid () << ")");
@@ -247,7 +261,8 @@
   if (!IsSendEnabled())
     return false;
 
-  AddHeader(p, dest, protocolNumber);
+  Eui48Address address = Eui48Address::ConvertFrom (dest);
+  AddHeader(p, address, protocolNumber);
 
   // Place the packet to be sent on the send queue
   if (m_queue->Enqueue(p) == false )
@@ -451,26 +466,62 @@
 }
 
 void
-CsmaCdNetDevice::Receive (Packet& p)
+CsmaCdNetDevice::Receive (const Packet& packet)
 {
+  EthernetHeader header (false);
+  EthernetTrailer trailer;
+  Eui48Address broadcast;
+  Eui48Address destination;
+  Packet p = packet;
+
   NS_DEBUG ("CsmaCdNetDevice::Receive UID is (" << p.GetUid() << ")");
 
   // Only receive if send side of net device is enabled
   if (!IsReceiveEnabled())
-    return;
+    {
+      goto drop;
+    }
 
-  uint16_t param = 0;
-  Packet packet = p;
+  if (m_encapMode == RAW)
+    {
+      ForwardUp (packet, 0, GetBroadcast ());
+      goto drop;
+    }
+  p.RemoveTrailer(trailer);
+  trailer.CheckFcs(p);
+  p.RemoveHeader(header);
 
-  if (ProcessHeader(packet, param))
+  broadcast = Eui48Address::ConvertFrom (GetBroadcast ());
+  destination = Eui48Address::ConvertFrom (GetAddress ());
+  if ((header.GetDestination() != broadcast) &&
+      (header.GetDestination() != destination))
     {
-      m_rxTrace (packet);
-      ForwardUp (packet, param);
-    } 
-  else 
+      // not for us.
+      goto drop;
+    }
+
+  uint16_t protocol;
+  switch (m_encapMode)
     {
-      m_dropTrace (packet);
+    case ETHERNET_V1:
+    case IP_ARP:
+      protocol = header.GetLengthType();
+      break;
+    case LLC: {
+      LlcSnapHeader llc;
+      p.RemoveHeader (llc);
+      protocol = llc.GetType ();
+    } break;
+    case RAW:
+      NS_ASSERT (false);
+      break;
     }
+  
+  m_rxTrace (p);
+  ForwardUp (p, protocol, header.GetSource ().ConvertTo ());
+  return;
+ drop:
+  m_dropTrace (p);
 }
 
 Ptr<Queue>
--- a/src/devices/csma-cd/csma-cd-net-device.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/devices/csma-cd/csma-cd-net-device.h	Mon Aug 06 09:59:29 2007 +0200
@@ -25,7 +25,7 @@
 #include <string.h>
 #include "ns3/node.h"
 #include "ns3/backoff.h"
-#include "ns3/mac-address.h"
+#include "ns3/address.h"
 #include "ns3/net-device.h"
 #include "ns3/callback.h"
 #include "ns3/packet.h"
@@ -34,6 +34,7 @@
 #include "ns3/data-rate.h"
 #include "ns3/ptr.h"
 #include "ns3/random-variable.h"
+#include "ns3/eui48-address.h"
 
 namespace ns3 {
 
@@ -82,6 +83,7 @@
   LLC,         /**< LLC packet encapsulation */  
 };
 
+  CsmaCdNetDevice (Ptr<Node> node);
   /**
    * Construct a CsmaCdNetDevice
    *
@@ -92,8 +94,8 @@
    * \param node the Node to which this device is connected.
    * \param addr The source MAC address of the net device.
    */
-  CsmaCdNetDevice (Ptr<Node> node, MacAddress addr, CsmaCdEncapsulationMode pktType);
-  CsmaCdNetDevice (Ptr<Node> node, MacAddress addr,
+  CsmaCdNetDevice (Ptr<Node> node, Eui48Address addr, CsmaCdEncapsulationMode pktType);
+  CsmaCdNetDevice (Ptr<Node> node, Eui48Address addr,
                    CsmaCdEncapsulationMode pktType,
                    bool sendEnable, bool receiveEnable);
   /**
@@ -172,7 +174,7 @@
    * @see CsmaCdChannel
    * \param p a reference to the received packet
    */
-  void Receive (Packet& p);
+  void Receive (const Packet& p);
 
   bool IsSendEnabled (void);
   bool IsReceiveEnabled (void);
@@ -210,7 +212,7 @@
    * \param protocolNumber In some protocols, identifies the type of
    * payload contained in this packet.
    */
-  void AddHeader (Packet& p, const MacAddress& dest, 
+  void AddHeader (Packet& p, Eui48Address dest, 
                   uint16_t protocolNumber);
   /**
    * Removes, from a packet of data, all headers and trailers that
@@ -247,7 +249,7 @@
    * \param protocolNumber -- this parameter is not used here
    * \return true if success, false on failure
    */
-  virtual bool SendTo (Packet& p, const MacAddress& dest, uint16_t protocolNumber);
+  virtual bool SendTo (Packet& p, const Address& dest, uint16_t protocolNumber);
 
   /**
    * Start Sending a Packet Down the Wire.
--- a/src/devices/csma-cd/csma-cd-topology.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/devices/csma-cd/csma-cd-topology.h	Mon Aug 06 09:59:29 2007 +0200
@@ -24,12 +24,7 @@
 
 #include "ns3/ptr.h"
 #include "ns3/csma-cd-net-device.h"
-#if 0
-#include "ns3/packet-socket.h"
-#include "ns3/packet-socket-app.h"
-#endif
 #include "ns3/node.h"
-#include "ns3/mac-address.h"
 
 // The topology class consists of only static methods thar are used to
 // create the topology and data flows for an ns3 simulation
--- a/src/devices/point-to-point/point-to-point-net-device.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/devices/point-to-point/point-to-point-net-device.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -26,9 +26,10 @@
 #include "ns3/queue.h"
 #include "ns3/simulator.h"
 #include "ns3/composite-trace-resolver.h"
+#include "ns3/eui48-address.h"
+#include "ns3/llc-snap-header.h"
 #include "point-to-point-net-device.h"
 #include "point-to-point-channel.h"
-#include "ns3/llc-snap-header.h"
 
 NS_DEBUG_COMPONENT_DEFINE ("PointToPointNetDevice");
 
@@ -39,10 +40,10 @@
            "The default data rate for point to point links",
            DataRate ("10Mb/s"));
 
-  PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
-                                                const DataRate& rate) 
+PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
+                                              const DataRate& rate) 
 : 
-  NetDevice(node, MacAddress (6)), 
+  NetDevice(node, Eui48Address::Allocate ().ConvertTo ()), 
   m_txMachineState (READY),
   m_bps (rate),
   m_tInterframeGap (Seconds(0)),
@@ -55,7 +56,7 @@
   // BUGBUG FIXME
   //
   // You _must_ support broadcast to get any sort of packet from the ARP layer.
-  EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff"));
+  EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff").ConvertTo ());
   EnableMulticast();
   EnablePointToPoint();
 }
@@ -66,15 +67,16 @@
   m_queue = 0;
 }
 
-void PointToPointNetDevice::AddHeader(Packet& p, const MacAddress& dest,
-                                      uint16_t protocolNumber)
+void 
+PointToPointNetDevice::AddHeader(Packet& p, uint16_t protocolNumber)
 {
   LlcSnapHeader llc;
   llc.SetType (protocolNumber);
   p.AddHeader (llc);
 }
 
-bool PointToPointNetDevice::ProcessHeader(Packet& p, uint16_t& param)
+bool 
+PointToPointNetDevice::ProcessHeader(Packet& p, uint16_t& param)
 {
   LlcSnapHeader llc;
   p.RemoveHeader (llc);
@@ -100,7 +102,7 @@
   m_tInterframeGap = t;
 }
 
-bool PointToPointNetDevice::SendTo (Packet& p, const MacAddress& dest, 
+bool PointToPointNetDevice::SendTo (Packet& p, const Address& dest, 
                                     uint16_t protocolNumber)
 {
   NS_DEBUG ("PointToPointNetDevice::SendTo (" << &p << ", " << &dest << ")");
@@ -110,7 +112,7 @@
   // "go down" during the simulation?  Shouldn't we just wait for it
   // to come back up?
   NS_ASSERT (IsLinkUp ());
-  AddHeader(p, dest, protocolNumber);
+  AddHeader(p, protocolNumber);
 
 //
 // This class simulates a point to point device.  In the case of a serial
@@ -119,14 +121,14 @@
 //
 // If there's a transmission in progress, we enque the packet for later
 // trnsmission; otherwise we send it now.
-    if (m_txMachineState == READY) 
-      {
-        return TransmitStart (p);
-      }
-    else
-      {
-        return m_queue->Enqueue(p);
-      }
+  if (m_txMachineState == READY) 
+    {
+      return TransmitStart (p);
+    }
+  else
+    {
+      return m_queue->Enqueue(p);
+    }
 }
 
   bool
@@ -218,12 +220,12 @@
 void PointToPointNetDevice::Receive (Packet& p)
 {
   NS_DEBUG ("PointToPointNetDevice::Receive (" << &p << ")");
-  uint16_t param = 0;
+  uint16_t protocol = 0;
   Packet packet = p;
 
-  ProcessHeader(packet, param);
+  ProcessHeader(packet, protocol);
   m_rxTrace (packet);
-  ForwardUp (packet, param);
+  ForwardUp (packet, protocol, GetBroadcast ());
 }
 
 Ptr<Queue> PointToPointNetDevice::GetQueue(void) const 
--- a/src/devices/point-to-point/point-to-point-net-device.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/devices/point-to-point/point-to-point-net-device.h	Mon Aug 06 09:59:29 2007 +0200
@@ -22,7 +22,7 @@
 #define POINT_TO_POINT_NET_DEVICE_H
 
 #include <string.h>
-#include "ns3/mac-address.h"
+#include "ns3/address.h"
 #include "ns3/node.h"
 #include "ns3/net-device.h"
 #include "ns3/callback.h"
@@ -191,7 +191,7 @@
    * Adds the necessary headers and trailers to a packet of data in order to
    * respect the protocol implemented by the agent.
    */
-  void AddHeader(Packet& p, const MacAddress& dest, uint16_t protocolNumber);
+  void AddHeader(Packet& p, uint16_t protocolNumber);
   /**
    * Removes, from a packet of data, all headers and trailers that
    * relate to the protocol implemented by the agent
@@ -208,11 +208,11 @@
    *
    * @see NetDevice
    * @param p a reference to the packet to send
-   * @param dest a reference to the MacAddress of the destination device
+   * @param dest a reference to the Address of the destination device
    * @param protocolNumber Protocol Number used to find protocol touse
    * @returns true if success, false on failure
    */
-  virtual bool SendTo (Packet& p, const MacAddress& dest, 
+  virtual bool SendTo (Packet& p, const Address& dest, 
                        uint16_t protocolNumber);
   /**
    * Start Sending a Packet Down the Wire.
--- a/src/internet-node/arp-cache.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/arp-cache.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -148,7 +148,7 @@
   UpdateSeen ();
 }
 Packet 
-ArpCache::Entry::MarkAlive (MacAddress macAddress) 
+ArpCache::Entry::MarkAlive (Address macAddress) 
 {
   NS_ASSERT (m_state == WAIT_REPLY);
   //NS_ASSERT (m_waiting != 0);
@@ -182,7 +182,7 @@
   UpdateSeen ();
 }
 
-MacAddress
+Address
 ArpCache::Entry::GetMacAddress (void)
 {
   NS_ASSERT (m_state == ALIVE);
--- a/src/internet-node/arp-cache.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/arp-cache.h	Mon Aug 06 09:59:29 2007 +0200
@@ -26,7 +26,7 @@
 #include "ns3/nstime.h"
 #include "ns3/net-device.h"
 #include "ns3/ipv4-address.h"
-#include "ns3/mac-address.h"
+#include "ns3/address.h"
 #include "ns3/ptr.h"
 #include "sgi-hashmap.h"
 
@@ -101,7 +101,7 @@
      * \param macAddress
      * \return 
      */
-    Packet MarkAlive (MacAddress macAddress);
+    Packet MarkAlive (Address macAddress);
     /**
      * \param waiting
      */
@@ -127,7 +127,7 @@
     /**
      * \return The MacAddress of this entry
      */
-    MacAddress GetMacAddress (void);
+    Address GetMacAddress (void);
     /**
      * \return True if this entry has timedout; false otherwise.
      */
@@ -143,7 +143,7 @@
     ArpCache *m_arp;
     ArpCacheEntryState_e m_state;
     Time m_lastSeen;
-    MacAddress m_macAddress;
+    Address m_macAddress;
     Packet m_waiting;
   };
 
--- a/src/internet-node/arp-header.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/arp-header.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -38,9 +38,9 @@
 {}
 
 void 
-ArpHeader::SetRequest (MacAddress sourceHardwareAddress,
+ArpHeader::SetRequest (Address sourceHardwareAddress,
                        Ipv4Address sourceProtocolAddress,
-                       MacAddress destinationHardwareAddress,
+                       Address destinationHardwareAddress,
                        Ipv4Address destinationProtocolAddress)
 {
   m_type = ARP_TYPE_REQUEST;
@@ -50,9 +50,9 @@
   m_ipv4Dest = destinationProtocolAddress;
 }
 void 
-ArpHeader::SetReply (MacAddress sourceHardwareAddress,
+ArpHeader::SetReply (Address sourceHardwareAddress,
                      Ipv4Address sourceProtocolAddress,
-                     MacAddress destinationHardwareAddress,
+                     Address destinationHardwareAddress,
                      Ipv4Address destinationProtocolAddress)
 {
   m_type = ARP_TYPE_REPLY;
@@ -71,12 +71,12 @@
 {
   return (m_type == ARP_TYPE_REPLY)?true:false;
 }
-MacAddress 
+Address 
 ArpHeader::GetSourceHardwareAddress (void)
 {
   return m_macSource;
 }
-MacAddress 
+Address 
 ArpHeader::GetDestinationHardwareAddress (void)
 {
   return m_macDest;
--- a/src/internet-node/arp-header.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/arp-header.h	Mon Aug 06 09:59:29 2007 +0200
@@ -23,7 +23,7 @@
 #define ARP_HEADER_H
 
 #include "ns3/header.h"
-#include "ns3/mac-address.h"
+#include "ns3/address.h"
 #include "ns3/ipv4-address.h"
 #include <string>
 
@@ -38,18 +38,18 @@
 
   virtual ~ArpHeader ();
 
-  void SetRequest (MacAddress sourceHardwareAddress,
+  void SetRequest (Address sourceHardwareAddress,
                    Ipv4Address sourceProtocolAddress,
-                   MacAddress destinationHardwareAddress,
+                   Address destinationHardwareAddress,
                    Ipv4Address destinationProtocolAddress);
-  void SetReply (MacAddress sourceHardwareAddress,
+  void SetReply (Address sourceHardwareAddress,
                  Ipv4Address sourceProtocolAddress,
-                 MacAddress destinationHardwareAddress,
+                 Address destinationHardwareAddress,
                  Ipv4Address destinationProtocolAddress);
   bool IsRequest (void) const;
   bool IsReply (void) const;
-  MacAddress GetSourceHardwareAddress (void);
-  MacAddress GetDestinationHardwareAddress (void);
+  Address GetSourceHardwareAddress (void);
+  Address GetDestinationHardwareAddress (void);
   Ipv4Address GetSourceIpv4Address (void);
   Ipv4Address GetDestinationIpv4Address (void);
 
@@ -78,8 +78,8 @@
     ARP_TYPE_REPLY   = 2
   };
   uint16_t m_type;
-  MacAddress m_macSource;
-  MacAddress m_macDest;
+  Address m_macSource;
+  Address m_macDest;
   Ipv4Address m_ipv4Source;
   Ipv4Address m_ipv4Dest;
 };
--- a/src/internet-node/arp-ipv4-interface.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/arp-ipv4-interface.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -25,10 +25,11 @@
 #include "ns3/composite-trace-resolver.h"
 #include "ns3/node.h"
 #include "ns3/net-device.h"
+#include "ns3/address.h"
 
 #include "arp-ipv4-interface.h"
-#include "arp-private.h"
 #include "ipv4-l3-protocol.h"
+#include "arp-l3-protocol.h"
 
 namespace ns3 {
 
@@ -59,18 +60,17 @@
   NS_ASSERT (GetDevice () != 0);
   if (GetDevice ()->NeedsArp ())
     {
-      Ptr<ArpPrivate> arp = m_node->QueryInterface<ArpPrivate> (ArpPrivate::iid);
-      MacAddress hardwareDestination;
+      Ptr<ArpL3Protocol> arp = m_node->QueryInterface<ArpL3Protocol> (ArpL3Protocol::iid);
+      Address hardwareDestination;
       bool found;
 
       if (dest.IsBroadcast ())
         {
-           hardwareDestination = GetDevice ()->GetBroadcast ();
-           found = true;
+          hardwareDestination = GetDevice ()->GetBroadcast ();
+          found = true;
         }
       else
         {
-          Ptr<ArpPrivate> arp = m_node->QueryInterface<ArpPrivate> (ArpPrivate::iid);
           found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination);
         }
 
--- a/src/internet-node/arp-l3-protocol.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/arp-l3-protocol.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -24,22 +24,24 @@
 #include "ns3/node.h"
 #include "ns3/net-device.h"
 
+#include "ipv4-l3-protocol.h"
 #include "arp-l3-protocol.h"
 #include "arp-header.h"
 #include "arp-cache.h"
 #include "ipv4-interface.h"
-#include "ipv4-private.h"
 
 NS_DEBUG_COMPONENT_DEFINE ("ArpL3Protocol");
 
 namespace ns3 {
 
+const InterfaceId ArpL3Protocol::iid = MakeInterfaceId ("ArpL3Protocol", Object::iid);
 const uint16_t ArpL3Protocol::PROT_NUMBER = 0x0806;
 
 ArpL3Protocol::ArpL3Protocol (Ptr<Node> node)
-  : L3Protocol (PROT_NUMBER, 0/* XXX: correct version number ? */ ),
-    m_node (node)
-{}
+  : m_node (node)
+{
+  SetInterfaceId (ArpL3Protocol::iid);
+}
 
 ArpL3Protocol::~ArpL3Protocol ()
 {}
@@ -53,7 +55,7 @@
     }
   m_cacheList.clear ();
   m_node = 0;
-  L3Protocol::DoDispose ();
+  Object::DoDispose ();
 }
 
 TraceResolver *
@@ -72,7 +74,7 @@
 	  return *i;
 	}
     }
-  Ptr<Ipv4Private> ipv4 = m_node->QueryInterface<Ipv4Private> (Ipv4Private::iid);
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
   Ipv4Interface *interface = ipv4->FindInterfaceForDevice (device);
   ArpCache * cache = new ArpCache (device, interface);
   NS_ASSERT (device->IsBroadcast ());
@@ -82,10 +84,11 @@
 }
 
 void 
-ArpL3Protocol::Receive(Packet& packet, Ptr<NetDevice> device)
+ArpL3Protocol::Receive(Ptr<NetDevice> device, const Packet& p, uint16_t protocol, const Address &from)
 {
   ArpCache *cache = FindCache (device);
   ArpHeader arp;
+  Packet packet = p;
   packet.RemoveHeader (arp);
   
   NS_DEBUG ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") <<
@@ -104,7 +107,7 @@
     } 
   else if (arp.IsReply () &&
            arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress ()) &&
-           arp.GetDestinationHardwareAddress ().IsEqual (device->GetAddress ())) 
+           arp.GetDestinationHardwareAddress () == device->GetAddress ()) 
     {
       Ipv4Address from = arp.GetSourceIpv4Address ();
       ArpCache::Entry *entry = cache->Lookup (from);
@@ -115,7 +118,7 @@
               NS_DEBUG ("node="<<m_node->GetId ()<<", got reply from " << 
                         arp.GetSourceIpv4Address ()
                      << " for waiting entry -- flush");
-              MacAddress from_mac = arp.GetSourceHardwareAddress ();
+              Address from_mac = arp.GetSourceHardwareAddress ();
               Packet waiting = entry->MarkAlive (from_mac);
 	      cache->GetInterface ()->Send (waiting, arp.GetSourceIpv4Address ());
             } 
@@ -144,8 +147,8 @@
 }
 bool 
 ArpL3Protocol::Lookup (Packet &packet, Ipv4Address destination, 
-	     Ptr<NetDevice> device,
-	     MacAddress *hardwareDestination)
+                       Ptr<NetDevice> device,
+                       Address *hardwareDestination)
 {
   ArpCache *cache = FindCache (device);
   ArpCache::Entry *entry = cache->Lookup (destination);
@@ -231,7 +234,7 @@
 }
 
 void
-ArpL3Protocol::SendArpReply (ArpCache const *cache, Ipv4Address toIp, MacAddress toMac)
+ArpL3Protocol::SendArpReply (ArpCache const *cache, Ipv4Address toIp, Address toMac)
 {
   ArpHeader arp;
   NS_DEBUG ("ARP: sending reply from node "<<m_node->GetId ()<<
--- a/src/internet-node/arp-l3-protocol.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/arp-l3-protocol.h	Mon Aug 06 09:59:29 2007 +0200
@@ -23,9 +23,8 @@
 
 #include <list>
 #include "ns3/ipv4-address.h"
-#include "ns3/mac-address.h"
+#include "ns3/address.h"
 #include "ns3/ptr.h"
-#include "l3-protocol.h"
 
 namespace ns3 {
 
@@ -38,22 +37,23 @@
 /**
  * \brief An implementation of the ARP protocol
  */
-class ArpL3Protocol : public L3Protocol
+class ArpL3Protocol : public Object
 {
 public:
+  static const InterfaceId iid;
   static const uint16_t PROT_NUMBER;
   /**
    * \brief Constructor
    * \param node The node which this ARP object is associated with
    */
   ArpL3Protocol (Ptr<Node> node);
-  ~ArpL3Protocol ();
+  virtual ~ArpL3Protocol ();
 
   virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
   /**
    * \brief Recieve a packet
    */
-  virtual void Receive(Packet& p, Ptr<NetDevice> device);
+  void Receive(Ptr<NetDevice> device, const Packet& p, uint16_t protocol, const Address &from);
   /**
    * \brief Perform an ARP lookup
    * \param p
@@ -64,14 +64,14 @@
    */
   bool Lookup (Packet &p, Ipv4Address destination, 
 	       Ptr<NetDevice> device,
-	       MacAddress *hardwareDestination);
+	       Address *hardwareDestination);
 protected:
   virtual void DoDispose (void);
 private:
   typedef std::list<ArpCache *> CacheList;
   ArpCache *FindCache (Ptr<NetDevice> device);
   void SendArpRequest (ArpCache const *cache, Ipv4Address to);
-  void SendArpReply (ArpCache const *cache, Ipv4Address toIp, MacAddress toMac);
+  void SendArpReply (ArpCache const *cache, Ipv4Address toIp, Address toMac);
   CacheList m_cacheList;
   Ptr<Node> m_node;
 };
--- a/src/internet-node/arp-private.cc	Mon Aug 06 09:58:03 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "arp-private.h"
-#include "arp-l3-protocol.h"
-#include "ns3/assert.h"
-#include "ns3/net-device.h"
-
-namespace ns3 {
-
-const InterfaceId ArpPrivate::iid = MakeInterfaceId ("ArpPrivate", Object::iid);
-
-ArpPrivate::ArpPrivate (Ptr<ArpL3Protocol> arp)
-  : m_arp (arp)
-{
-  SetInterfaceId (ArpPrivate::iid);
-}
-ArpPrivate::~ArpPrivate ()
-{
-  NS_ASSERT (m_arp == 0);
-}
-
-bool 
-ArpPrivate::Lookup (Packet &p, Ipv4Address destination, 
-		     Ptr<NetDevice> device,
-		     MacAddress *hardwareDestination)
-{
-  return m_arp->Lookup (p, destination, device, hardwareDestination);
-}
-
-void
-ArpPrivate::DoDispose (void)
-{
-  m_arp = 0;
-  Object::DoDispose ();
-}
-
-
-} // namespace ns3
--- a/src/internet-node/arp-private.h	Mon Aug 06 09:58:03 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef ARP_PRIVATE_H
-#define ARP_PRIVATE_H
-
-#include "ns3/object.h"
-#include "ns3/ipv4-address.h"
-
-namespace ns3 {
-
-class NetDevice;
-class MacAddress;
-class Packet;
-class ArpL3Protocol;
-
-class ArpPrivate : public Object
-{
-public:
-  static const InterfaceId iid;
-  ArpPrivate (Ptr<ArpL3Protocol> arp);
-  virtual ~ArpPrivate ();
-  bool Lookup (Packet &p, Ipv4Address destination, 
-	       Ptr<NetDevice> device,
-	       MacAddress *hardwareDestination);
-protected:
-  virtual void DoDispose (void);
-private:
-  Ptr<ArpL3Protocol> m_arp;
-};
-
-} // namespace ns3
-
-#endif /* ARP_PRIVATE_H */
--- a/src/internet-node/ascii-trace.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/ascii-trace.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -26,12 +26,6 @@
 #include "ns3/node.h"
 #include "ns3/queue.h"
 #include "ns3/node-list.h"
-#include "ns3/llc-snap-header.h"
-
-#include "ipv4-l3-protocol.h"
-#include "arp-header.h"
-#include "udp-header.h"
-#include "ipv4-header.h"
 
 namespace ns3 {
 
@@ -47,51 +41,17 @@
 AsciiTrace::TraceAllQueues (void)
 {
   Packet::EnableMetadata ();
-  TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/*",
+  TraceRoot::Connect ("/nodes/*/devices/*/queue/*",
                       MakeCallback (&AsciiTrace::LogDevQueue, this));
 }
 void
 AsciiTrace::TraceAllNetDeviceRx (void)
 {
   Packet::EnableMetadata ();
-  TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/rx",
+  TraceRoot::Connect ("/nodes/*/devices/*/rx",
                       MakeCallback (&AsciiTrace::LogDevRx, this));
 }
 
-void
-AsciiTrace::PrintType (Packet const &packet)
-{
-  Packet p = packet;
-  LlcSnapHeader llc;
-  p.RemoveHeader (llc);
-  switch (llc.GetType ())
-    {
-    case 0x0800: {
-      Ipv4Header ipv4;
-      p.RemoveHeader (ipv4);
-      if (ipv4.GetProtocol () == 17)
-        {
-          UdpHeader udp;
-          p.RemoveHeader (udp);
-          m_os << "udp size=" << p.GetSize ();
-        }
-    } break;
-    case 0x0806: {
-      ArpHeader arp;
-      p.RemoveHeader (arp);
-      m_os << "arp ";
-      if (arp.IsRequest ())
-        {
-          m_os << "request";
-        }
-      else
-        {
-          m_os << "reply ";
-        }
-    } break;
-    }
-} 
-
 void 
 AsciiTrace::LogDevQueue (TraceContext const &context, Packet const &packet)
 {
@@ -113,9 +73,9 @@
   NodeList::NodeIndex nodeIndex;
   context.Get (nodeIndex);
   m_os << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
-  Ipv4L3Protocol::InterfaceIndex interfaceIndex;
-  context.Get (interfaceIndex);
-  m_os << "interface=" << interfaceIndex << " ";
+  Node::NetDeviceIndex deviceIndex;
+  context.Get (deviceIndex);
+  m_os << "device=" << deviceIndex << " ";
   m_os << "pkt-uid=" << packet.GetUid () << " ";
   packet.Print (m_os);
   m_os << std::endl;
@@ -127,9 +87,9 @@
   NodeList::NodeIndex nodeIndex;
   context.Get (nodeIndex);
   m_os << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
-  Ipv4L3Protocol::InterfaceIndex interfaceIndex;
-  context.Get (interfaceIndex);
-  m_os << "interface=" << interfaceIndex << " ";
+  Node::NetDeviceIndex deviceIndex;
+  context.Get (deviceIndex);
+  m_os << "device=" << deviceIndex << " ";
   m_os << "pkt-uid=" << p.GetUid () << " ";
   p.Print (m_os);
   m_os << std::endl;  
--- a/src/internet-node/ascii-trace.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/ascii-trace.h	Mon Aug 06 09:59:29 2007 +0200
@@ -37,7 +37,6 @@
   void TraceAllQueues (void);
   void TraceAllNetDeviceRx (void);
 private:
-  void PrintType (Packet const &p);
   void LogDevQueue (TraceContext const &context, const Packet &p);
   void LogDevRx (TraceContext const &context, Packet &p);
   std::ofstream m_os;
--- a/src/internet-node/internet-node.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/internet-node.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -23,17 +23,15 @@
 
 #include "ns3/composite-trace-resolver.h"
 #include "ns3/net-device.h"
+#include "ns3/callback.h"
 
-#include "l3-demux.h"
 #include "ipv4-l4-demux.h"
 #include "internet-node.h"
 #include "udp-l4-protocol.h"
 #include "ipv4-l3-protocol.h"
 #include "arp-l3-protocol.h"
 #include "udp-impl.h"
-#include "arp-private.h"
 #include "ipv4-impl.h"
-#include "ipv4-private.h"
 
 namespace ns3 {
 
@@ -55,38 +53,35 @@
 {
   Ptr<Ipv4L3Protocol> ipv4 = Create<Ipv4L3Protocol> (this);
   Ptr<ArpL3Protocol> arp = Create<ArpL3Protocol> (this);
-  Ptr<UdpL4Protocol> udp = Create<UdpL4Protocol> (this);
+  // XXX remove the PeekPointer below.
+  RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, PeekPointer (ipv4)), 
+                           Ipv4L3Protocol::PROT_NUMBER, 0);
+  RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (arp)),
+                           ArpL3Protocol::PROT_NUMBER, 0);
 
-  Ptr<L3Demux> l3Demux = Create<L3Demux> (this);
+
   Ptr<Ipv4L4Demux> ipv4L4Demux = Create<Ipv4L4Demux> (this);
-
-  l3Demux->Insert (ipv4);
-  l3Demux->Insert (arp);
+  Ptr<UdpL4Protocol> udp = Create<UdpL4Protocol> (this);
   ipv4L4Demux->Insert (udp);
 
   Ptr<UdpImpl> udpImpl = Create<UdpImpl> (udp);
-  Ptr<ArpPrivate> arpPrivate = Create<ArpPrivate> (arp);
   Ptr<Ipv4Impl> ipv4Impl = Create<Ipv4Impl> (ipv4);
-  Ptr<Ipv4Private> ipv4Private = Create<Ipv4Private> (ipv4);
 
-  Object::AddInterface (ipv4Private);
+  Object::AddInterface (ipv4);
+  Object::AddInterface (arp);
   Object::AddInterface (ipv4Impl);
-  Object::AddInterface (arpPrivate);
   Object::AddInterface (udpImpl);
-  Object::AddInterface (l3Demux);
   Object::AddInterface (ipv4L4Demux);
 }
 
-TraceResolver *
-InternetNode::DoCreateTraceResolver (TraceContext const &context)
+void
+InternetNode::DoFillTraceResolver (CompositeTraceResolver &resolver)
 {
-  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
-  Ptr<Ipv4Private> ipv4 = QueryInterface<Ipv4Private> (Ipv4Private::iid);
-  resolver->Add ("ipv4",
-                 MakeCallback (&Ipv4Private::CreateTraceResolver, PeekPointer (ipv4)),
-                 InternetNode::IPV4);
-
-  return resolver;
+  Node::DoFillTraceResolver (resolver);
+  Ptr<Ipv4L3Protocol> ipv4 = QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
+  resolver.Add ("ipv4",
+                MakeCallback (&Ipv4L3Protocol::CreateTraceResolver, PeekPointer (ipv4)),
+                InternetNode::IPV4);
 }
 
 void 
@@ -95,25 +90,4 @@
   Node::DoDispose ();
 }
 
-void 
-InternetNode::DoAddDevice (Ptr<NetDevice> device)
-{
-  device->SetReceiveCallback (MakeCallback (&InternetNode::ReceiveFromDevice, this));
-}
-
-bool
-InternetNode::ReceiveFromDevice (Ptr<NetDevice> device, const Packet &p, uint16_t protocolNumber) const
-{
-  Ptr<L3Demux> demux = QueryInterface<L3Demux> (L3Demux::iid);
-  Ptr<L3Protocol> target = demux->GetProtocol (protocolNumber);
-  if (target != 0) 
-    {
-      Packet packet = p;
-      target->Receive(packet, device);
-      return true;
-    }
-  return false;
-}
-
-
 }//namespace ns3
--- a/src/internet-node/internet-node.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/internet-node.h	Mon Aug 06 09:59:29 2007 +0200
@@ -46,8 +46,7 @@
 protected:
   virtual void DoDispose(void);
 private:
-  virtual void DoAddDevice (Ptr<NetDevice> device);
-  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
+  virtual void DoFillTraceResolver (CompositeTraceResolver &resolver);
   bool ReceiveFromDevice (Ptr<NetDevice> device, const Packet &p, uint16_t protocolNumber) const;
   void Construct (void);
 };
--- a/src/internet-node/ipv4-l3-protocol.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/ipv4-l3-protocol.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -41,15 +41,16 @@
 
 namespace ns3 {
 
+const InterfaceId Ipv4L3Protocol::iid = MakeInterfaceId ("Ipv4L3Protocol", Object::iid);
 const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800;
 
 Ipv4L3Protocol::Ipv4L3Protocol(Ptr<Node> node)
-  : L3Protocol (PROT_NUMBER, 4),
-    m_nInterfaces (0),
+  : m_nInterfaces (0),
     m_defaultTtl (64),
     m_identification (0),
     m_node (node)
 {
+  SetInterfaceId (Ipv4L3Protocol::iid);
   m_staticRouting = Create<Ipv4StaticRouting> ();
   AddRoutingProtocol (m_staticRouting, 0);
   SetupLoopback ();
@@ -66,9 +67,9 @@
     }
   m_interfaces.clear ();
   m_node = 0;
-  L3Protocol::DoDispose ();
   m_staticRouting->Dispose ();
   m_staticRouting = 0;
+  Object::DoDispose ();
 }
 
 void
@@ -98,8 +99,8 @@
 TraceResolver *
 Ipv4L3Protocol::InterfacesCreateTraceResolver (TraceContext const &context) const
 {
-  ArrayTraceResolver<Ipv4Interface> *resolver = 
-    new ArrayTraceResolver<Ipv4Interface> 
+  ArrayTraceResolver<Ipv4Interface *> *resolver = 
+    new ArrayTraceResolver<Ipv4Interface *> 
     (context,
      MakeCallback (&Ipv4L3Protocol::GetNInterfaces, this),
      MakeCallback (&Ipv4L3Protocol::GetInterface, this));
@@ -240,18 +241,19 @@
 }  
 
 void 
-Ipv4L3Protocol::Receive(Packet& packet, Ptr<NetDevice> device)
+Ipv4L3Protocol::Receive( Ptr<NetDevice> device, const Packet& p, uint16_t protocol, const Address &from)
 {
   uint32_t index = 0;
   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
     {
       if ((*i)->GetDevice () == device)
         {
-          m_rxTrace (packet, index);
+          m_rxTrace (p, index);
           break;
         }
       index++;
     }
+  Packet packet = p;
   Ipv4Header ipHeader;
   packet.RemoveHeader (ipHeader);
 
--- a/src/internet-node/ipv4-l3-protocol.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/ipv4-l3-protocol.h	Mon Aug 06 09:59:29 2007 +0200
@@ -30,7 +30,6 @@
 #include "ipv4-header.h"
 #include "ns3/ptr.h"
 #include "ns3/ipv4.h"
-#include "l3-protocol.h"
 #include "ipv4-static-routing.h"
 
 namespace ns3 {
@@ -46,9 +45,10 @@
 class TraceContext;
 
 
-class Ipv4L3Protocol : public L3Protocol 
+class Ipv4L3Protocol : public Object
 {
 public:
+  static const InterfaceId iid;
   static const uint16_t PROT_NUMBER;
 
   enum TraceType {
@@ -57,7 +57,7 @@
     DROP,
     INTERFACES,
   };
-  typedef ArrayTraceResolver<Ipv4Interface>::Index InterfaceIndex;
+  typedef ArrayTraceResolver<Ipv4Interface *>::Index InterfaceIndex;
 
   Ipv4L3Protocol(Ptr<Node> node);
   virtual ~Ipv4L3Protocol ();
@@ -95,7 +95,7 @@
    *    - implement a per-NetDevice ARP cache
    *    - send back arp replies on the right device
    */
-  virtual void Receive(Packet& p, Ptr<NetDevice> device);
+  void Receive( Ptr<NetDevice> device, const Packet& p, uint16_t protocol, const Address &from);
 
   /**
    * \param packet packet to send
--- a/src/internet-node/ipv4-loopback-interface.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/ipv4-loopback-interface.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -23,7 +23,7 @@
 #include "ns3/net-device.h"
 #include "ns3/node.h"
 #include "ipv4-loopback-interface.h"
-#include "ipv4-private.h"
+#include "ipv4-l3-protocol.h"
 
 namespace ns3 {
 
@@ -43,8 +43,8 @@
 void 
 Ipv4LoopbackInterface::SendTo (Packet packet, Ipv4Address dest)
 {
-  Ptr<Ipv4Private> ipv4 = m_node->QueryInterface<Ipv4Private> (Ipv4Private::iid);
-  ipv4->Receive (packet, GetDevice ());
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
+  ipv4->Receive (GetDevice (), packet, Ipv4L3Protocol::PROT_NUMBER, GetDevice ()->GetAddress ());
 }
 
 }//namespace ns3
--- a/src/internet-node/ipv4-private.cc	Mon Aug 06 09:58:03 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "ipv4-private.h"
-#include "ipv4-l3-protocol.h"
-#include "ns3/assert.h"
-#include "ns3/net-device.h"
-
-namespace ns3 {
-
-const InterfaceId Ipv4Private::iid = MakeInterfaceId ("Ipv4Private", Object::iid);
-
-Ipv4Private::Ipv4Private (Ptr<Ipv4L3Protocol> ipv4)
-  : m_ipv4 (ipv4)
-{
-  SetInterfaceId (Ipv4Private::iid);
-}
-Ipv4Private::~Ipv4Private ()
-{
-  NS_ASSERT (m_ipv4 == 0);
-}
-TraceResolver *
-Ipv4Private::CreateTraceResolver (TraceContext const &context)
-{
-  return m_ipv4->CreateTraceResolver (context);
-}
-void 
-Ipv4Private::Send (Packet const &packet, Ipv4Address source, 
-		    Ipv4Address destination, uint8_t protocol)
-{
-  m_ipv4->Send (packet, source, destination, protocol);
-}
-Ipv4Interface *
-Ipv4Private::FindInterfaceForDevice (Ptr<const NetDevice>device)
-{
-  return m_ipv4->FindInterfaceForDevice (device);
-}
-void 
-Ipv4Private::Receive(Packet& p, Ptr<NetDevice> device)
-{
-  m_ipv4->Receive (p, device);
-}
-void 
-Ipv4Private::DoDispose (void)
-{
-  m_ipv4 = 0;
-  Object::DoDispose ();
-}
-
-} // namespace ns3
--- a/src/internet-node/ipv4-private.h	Mon Aug 06 09:58:03 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef IPV4_PRIVATE_H
-#define IPV4_PRIVATE_H
-
-#include "ns3/object.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ptr.h"
-#include <stdint.h>
-
-namespace ns3 {
-
-class Packet;
-class Ipv4L3Protocol;
-class TraceContext;
-class TraceResolver;
-class Ipv4Interface;
-class NetDevice;
-
-class Ipv4Private : public Object
-{
-public:
-  static const InterfaceId iid;
-  Ipv4Private (Ptr<Ipv4L3Protocol> ipv4);
-  virtual ~Ipv4Private ();
-
-  TraceResolver *CreateTraceResolver (TraceContext const &context);
-  void Send (Packet const &packet, Ipv4Address source, 
-	     Ipv4Address destination, uint8_t protocol);
-  Ipv4Interface *FindInterfaceForDevice (Ptr<const NetDevice>device);
-  void Receive(Packet& p, Ptr<NetDevice> device);
-protected:
-  virtual void DoDispose (void);
-private:
-  Ptr<Ipv4L3Protocol> m_ipv4;
-};
-
-} // namespace ns3
-
-#endif /* IPV4_PRIVATE_H */
--- a/src/internet-node/ipv4-static-routing.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/ipv4-static-routing.h	Mon Aug 06 09:59:29 2007 +0200
@@ -31,7 +31,6 @@
 #include "ipv4-header.h"
 #include "ns3/ptr.h"
 #include "ns3/ipv4.h"
-#include "l3-protocol.h"
 
 namespace ns3 {
 
--- a/src/internet-node/l3-demux.cc	Mon Aug 06 09:58:03 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation;
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// Author: George F. Riley<riley@ece.gatech.edu>
-//
-// Implement the L3Protocols capability for ns3.
-// George F. Riley, Georgia Tech, Fall 2006
-#include <sstream>
-#include <string>
-#include "ns3/composite-trace-resolver.h"
-#include "ns3/node.h"
-#include "l3-demux.h"
-#include "l3-protocol.h"
-
-namespace ns3 {
-
-const InterfaceId L3Demux::iid = MakeInterfaceId ("L3Demux", Object::iid);
-
-L3Demux::L3Demux (Ptr<Node> node)
-  : m_node (node)
-{
-  SetInterfaceId (L3Demux::iid);
-}
-
-L3Demux::~L3Demux()
-{}
-
-void
-L3Demux::DoDispose (void)
-{
-  for (L3Map_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
-    {
-      i->second->Dispose ();
-      i->second = 0;
-    }
-  m_protocols.clear ();
-  m_node = 0;
-  Object::DoDispose ();
-}
-
-TraceResolver *
-L3Demux::CreateTraceResolver (TraceContext const &context) const
-{
-  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
-  for (L3Map_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
-    {
-      std::string protValue;
-      std::ostringstream oss (protValue);
-      oss << i->second->GetProtocolNumber ();
-      ProtocolTraceType context = i->second->GetProtocolNumber ();
-      resolver->Add (protValue, 
-                     MakeCallback (&L3Protocol::CreateTraceResolver, PeekPointer (i->second)),
-                     context);
-    }
-  return resolver;
-}
-  
-void L3Demux::Insert(Ptr<L3Protocol> p)
-{
-  m_protocols.insert(L3Map_t::value_type(p->GetProtocolNumber (), p));
-}
-
-Ptr<L3Protocol>
-L3Demux::GetProtocol (int p)
-{ // Look up a protocol by protocol number
-  L3Map_t::iterator i = m_protocols.find(p);
-  if (i == m_protocols.end()) 
-    {
-      return 0;
-    }
-  return i->second; // Return the protocol
-}
-
-} //namespace ns3  
-  
--- a/src/internet-node/l3-demux.h	Mon Aug 06 09:58:03 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation;
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// Author: George F. Riley<riley@ece.gatech.edu>
-//
-// Define the L3Protocols capability for ns3.
-// George F. Riley, Georgia Tech, Fall 2006
-
-// This object manages the different layer 3 protocols for any ns3
-// node that has this capability.  
-
-#ifndef L3_DEMUX_H
-#define L3_DEMUX_H
-
-#include <map>
-#include "ns3/object.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class L3Protocol;
-class Node;
-class TraceResolver;
-class TraceContext;
-
-/**
- * \brief L3 Demux 
- */
-class L3Demux : public Object
-{
-public:
-  static const InterfaceId iid;
-  typedef int ProtocolTraceType;
-  L3Demux(Ptr<Node> node);
-  virtual ~L3Demux();
-
-  /**
-   * \param context the trace context to use to construct the
-   *        TraceResolver to return
-   * \returns a TraceResolver which can resolve all traces
-   *          performed in this object. The caller must
-   *          delete the returned object.
-   */
-  TraceResolver *CreateTraceResolver (TraceContext const &context) const;
-
-
-  /**
-   * \param protocol a template for the protocol to add to this L3 Demux.
-   *
-   * Invoke Copy on the input template to get a copy of the input
-   * protocol which can be used on the Node on which this L3 Demux 
-   * is running. The new L3Protocol is registered internally as
-   * a working L3 Protocol and returned from this method.
-   * The caller does not get ownership of the returned pointer.
-   */
-  void Insert(Ptr<L3Protocol> protocol);
-  /**
-   * \param protocolNumber number of protocol to lookup
-   *        in this L4 Demux
-   * \returns a matching L3 Protocol
-   *
-   * This method is typically called by lower layers
-   * to forward packets up the stack to the right protocol.
-   * It is also called from NodeImpl::GetIpv4 for example.
-   */
-  Ptr<L3Protocol> GetProtocol (int protocolNumber);
-protected:
-  virtual void DoDispose (void);
-private:
-  typedef std::map<int, Ptr<ns3::L3Protocol> > L3Map_t;
-
-  Ptr<Node> m_node;
-  L3Map_t m_protocols;
-};
-
-} //namespace ns3
-#endif
-
--- a/src/internet-node/l3-protocol.cc	Mon Aug 06 09:58:03 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation;
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// Author: George F. Riley<riley@ece.gatech.edu>
-//
-
-// NS3 - Layer 3 Protocol base class
-// George F. Riley, Georgia Tech, Spring 2007
-
-#include "l3-protocol.h"
-
-
-namespace ns3 {
-
-L3Protocol::L3Protocol(int protocolNumber, int version)
-    : m_protocolNumber (protocolNumber),
-      m_version (version)
-{}
-L3Protocol::~L3Protocol ()
-{}
-
-int 
-L3Protocol::GetProtocolNumber (void) const
-{
-  return m_protocolNumber;
-}
-int 
-L3Protocol::GetVersion() const
-{
-  return m_version;
-}
-
-void
-L3Protocol::DoDispose (void)
-{
-  Object::DoDispose ();
-}
-
-}//namespace ns3
--- a/src/internet-node/l3-protocol.h	Mon Aug 06 09:58:03 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation;
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// Author: George F. Riley<riley@ece.gatech.edu>
-//
-
-// NS3 - Layer 3 Protocol base class
-// George F. Riley, Georgia Tech, Spring 2007
-
-#ifndef L3_PROTOCOL_H
-#define L3_PROTOCOL_H
-
-#include "ns3/object.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class Packet;
-class NetDevice;
-class TraceResolver;
-class TraceContext;
-
-/**
- * ::Send is always defined in subclasses.
- */
-class L3Protocol : public Object {
-public:
-  L3Protocol(int protocolNumber, int version);
-  virtual ~L3Protocol ();
-  /**
-   * \return The protocol number of this Layer 3 protocol
-   */  
-  int GetProtocolNumber (void) const;
-  /**
-   * \return The version number of this protocol
-   */
-  int GetVersion() const;
-
-  virtual TraceResolver *CreateTraceResolver (TraceContext const &context) = 0;
-  /**
-   * Lower layer calls this method after calling L3Demux::Lookup
-   * The ARP subclass needs to know from which NetDevice this
-   * packet is coming to:
-   *    - implement a per-NetDevice ARP cache
-   *    - send back arp replies on the right device
-   */
-  virtual void Receive(Packet& p, Ptr<NetDevice> device) = 0;
-
-protected:
-  virtual void DoDispose (void);
-private:
-  int m_protocolNumber;
-  int m_version;
-};
-
-} // Namespace ns3
-
-#endif
--- a/src/internet-node/udp-l4-protocol.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/udp-l4-protocol.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -29,8 +29,6 @@
 #include "ipv4-end-point-demux.h"
 #include "ipv4-end-point.h"
 #include "ipv4-l3-protocol.h"
-#include "ipv4-private.h"
-#include "l3-demux.h"
 #include "udp-socket.h"
 
 namespace ns3 {
@@ -138,7 +136,7 @@
 
   packet.AddHeader (udpHeader);
 
-  Ptr<Ipv4Private> ipv4 = m_node->QueryInterface<Ipv4Private> (Ipv4Private::iid);
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
   if (ipv4 != 0)
     {
       ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
--- a/src/internet-node/udp-socket.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/udp-socket.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -19,6 +19,7 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
 #include "udp-socket.h"
 #include "udp-l4-protocol.h"
 #include "ipv4-end-point.h"
@@ -72,12 +73,12 @@
 int
 UdpSocket::FinishBind (void)
 {
-  m_endPoint->SetRxCallback (MakeCallback (&UdpSocket::ForwardUp, this));
-  m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocket::Destroy, this));
   if (m_endPoint == 0)
     {
       return -1;
     }
+  m_endPoint->SetRxCallback (MakeCallback (&UdpSocket::ForwardUp, this));
+  m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocket::Destroy, this));
   return 0;
 }
 
@@ -88,21 +89,32 @@
   return FinishBind ();
 }
 int 
-UdpSocket::Bind (Ipv4Address address)
-{
-  m_endPoint = m_udp->Allocate (address);
-  return FinishBind ();
-}
-int 
-UdpSocket::Bind (uint16_t port)
+UdpSocket::Bind (const Address &address)
 {
-  m_endPoint = m_udp->Allocate (port);
-  return FinishBind ();
-}
-int 
-UdpSocket::Bind (Ipv4Address address, uint16_t port)
-{
-  m_endPoint = m_udp->Allocate (address, port);
+  if (!InetSocketAddress::IsMatchingType (address))
+    {
+      return ERROR_INVAL;
+    }
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  Ipv4Address ipv4 = transport.GetIpv4 ();
+  uint16_t port = transport.GetPort ();
+  if (ipv4 == Ipv4Address::GetAny () && port == 0)
+    {
+      m_endPoint = m_udp->Allocate ();
+    }
+  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
+    {
+      m_endPoint = m_udp->Allocate (port);
+    }
+  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
+    {
+      m_endPoint = m_udp->Allocate (ipv4);
+    }
+  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
+    {
+      m_endPoint = m_udp->Allocate (ipv4, port);
+    }
+
   return FinishBind ();
 }
 
@@ -124,34 +136,36 @@
   return 0;
 }
 
-void 
-UdpSocket::DoClose(ns3::Callback<void, Ptr<Socket> > closeCompleted)
+int
+UdpSocket::DoClose(Callback<void, Ptr<Socket> > closeCompleted)
 {
   // XXX: we should set the close state and check it in all API methods.
   if (!closeCompleted.IsNull ())
     {
       closeCompleted (this);
     }
+  return 0;
 }
-void 
-UdpSocket::DoConnect(const Ipv4Address & address,
-                     uint16_t portNumber,
-                     ns3::Callback<void, Ptr<Socket> > connectionSucceeded,
-                     ns3::Callback<void, Ptr<Socket> > connectionFailed,
-                     ns3::Callback<void, Ptr<Socket> > halfClose)
+int
+UdpSocket::DoConnect(const Address & address,
+                     Callback<void, Ptr<Socket> > connectionSucceeded,
+                     Callback<void, Ptr<Socket> > connectionFailed,
+                     Callback<void, Ptr<Socket> > halfClose)
 {
-  m_defaultAddress = address;
-  m_defaultPort = portNumber;
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  m_defaultAddress = transport.GetIpv4 ();
+  m_defaultPort = transport.GetPort ();
   if (!connectionSucceeded.IsNull ())
     {
       connectionSucceeded (this);
     }
   m_connected = true;
+  return 0;
 }
 int
-UdpSocket::DoAccept(ns3::Callback<bool, Ptr<Socket>, const Ipv4Address&, uint16_t> connectionRequest,
-                    ns3::Callback<void, Ptr<Socket>, const Ipv4Address&, uint16_t> newConnectionCreated,
-                    ns3::Callback<void, Ptr<Socket> > closeRequested)
+UdpSocket::DoAccept(Callback<bool, Ptr<Socket>, const Address&> connectionRequest,
+                    Callback<void, Ptr<Socket>, const Address&> newConnectionCreated,
+                    Callback<void, Ptr<Socket> > closeRequested)
 {
   // calling accept on a udp socket is a programming error.
   m_errno = ERROR_OPNOTSUPP;
@@ -160,7 +174,7 @@
 int 
 UdpSocket::DoSend (const uint8_t* buffer,
                    uint32_t size,
-                   ns3::Callback<void, Ptr<Socket>, uint32_t> dataSent)
+                   Callback<void, Ptr<Socket>, uint32_t> dataSent)
 {
   if (!m_connected)
     {
@@ -179,8 +193,17 @@
   return DoSendPacketTo (p, m_defaultAddress, m_defaultPort, dataSent);
 }
 int
-UdpSocket::DoSendPacketTo (const Packet &p, Ipv4Address daddr, uint16_t dport,
-                           ns3::Callback<void, Ptr<Socket>, uint32_t> dataSent)
+UdpSocket::DoSendPacketTo (const Packet &p, const Address &address,
+                           Callback<void, Ptr<Socket>, uint32_t> dataSent)
+{
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  Ipv4Address ipv4 = transport.GetIpv4 ();
+  uint16_t port = transport.GetPort ();
+  return DoSendPacketTo (p, ipv4, port, dataSent);
+}
+int
+UdpSocket::DoSendPacketTo (const Packet &p, Ipv4Address ipv4, uint16_t port,
+                           Callback<void, Ptr<Socket>, uint32_t> dataSent)
 {
   if (m_endPoint == 0)
     {
@@ -196,8 +219,8 @@
       m_errno = ERROR_SHUTDOWN;
       return -1;
     }
-  m_udp->Send (p, m_endPoint->GetLocalAddress (), daddr,
-		   m_endPoint->GetLocalPort (), dport);
+  m_udp->Send (p, m_endPoint->GetLocalAddress (), ipv4,
+		   m_endPoint->GetLocalPort (), port);
   if (!dataSent.IsNull ())
     {
       dataSent (this, p.GetSize ());
@@ -205,11 +228,10 @@
   return 0;
 }
 int 
-UdpSocket::DoSendTo(const Ipv4Address &address,
-                    uint16_t port,
+UdpSocket::DoSendTo(const Address &address,
                     const uint8_t *buffer,
                     uint32_t size,
-                    ns3::Callback<void, Ptr<Socket>, uint32_t> dataSent)
+                    Callback<void, Ptr<Socket>, uint32_t> dataSent)
 {
   if (m_connected)
     {
@@ -225,34 +247,39 @@
     {
       p = Packet (buffer, size);
     }
-  return DoSendPacketTo (p, address, port, dataSent);
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  Ipv4Address ipv4 = transport.GetIpv4 ();
+  uint16_t port = transport.GetPort ();
+  return DoSendPacketTo (p, ipv4, port, dataSent);
 }
 void 
-UdpSocket::DoRecv(ns3::Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Ipv4Address&, uint16_t> callback)
+UdpSocket::DoRecv(Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Address&> callback)
 {
   m_rxCallback = callback;
 }
 void 
-UdpSocket::DoRecvDummy(ns3::Callback<void, Ptr<Socket>, uint32_t,const Ipv4Address&, uint16_t> callback)
+UdpSocket::DoRecvDummy(Callback<void, Ptr<Socket>, uint32_t,const Address&> callback)
 {
   m_dummyRxCallback = callback;
 }
 
 void 
-UdpSocket::ForwardUp (const Packet &packet, Ipv4Address saddr, uint16_t sport)
+UdpSocket::ForwardUp (const Packet &packet, Ipv4Address ipv4, uint16_t port)
 {
   if (m_shutdownRecv)
     {
       return;
     }
+  
+  Address address = InetSocketAddress (ipv4, port).ConvertTo ();
   Packet p = packet;
   if (!m_dummyRxCallback.IsNull ())
     {
-      m_dummyRxCallback (this, p.GetSize (), saddr, sport);
+      m_dummyRxCallback (this, p.GetSize (), address);
     }
   if (!m_rxCallback.IsNull ())
     {
-      m_rxCallback (this, p.PeekData (), p.GetSize (), saddr, sport);
+      m_rxCallback (this, p.PeekData (), p.GetSize (), address);
     }
 }
 
--- a/src/internet-node/udp-socket.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/udp-socket.h	Mon Aug 06 09:59:29 2007 +0200
@@ -25,6 +25,7 @@
 #include "ns3/callback.h"
 #include "ns3/socket.h"
 #include "ns3/ptr.h"
+#include "ns3/ipv4-address.h"
 
 namespace ns3 {
 
@@ -45,49 +46,47 @@
   virtual enum SocketErrno GetErrno (void) const;
   virtual Ptr<Node> GetNode (void) const;
   virtual int Bind (void);
-  virtual int Bind (Ipv4Address address);
-  virtual int Bind (uint16_t port); 
-  virtual int Bind (Ipv4Address address, uint16_t port);
+  virtual int Bind (const Address &address);
   virtual int ShutdownSend (void);
   virtual int ShutdownRecv (void);
 
 private:
-  virtual void DoClose(ns3::Callback<void, Ptr<Socket> > closeCompleted);
-  virtual void DoConnect(const Ipv4Address & address,
-			 uint16_t portNumber,
-			 ns3::Callback<void, Ptr<Socket> > connectionSucceeded,
-			 ns3::Callback<void, Ptr<Socket> > connectionFailed,
-			 ns3::Callback<void, Ptr<Socket> > halfClose);
-  virtual int DoAccept(ns3::Callback<bool, Ptr<Socket>, const Ipv4Address&, uint16_t> connectionRequest,
-		       ns3::Callback<void, Ptr<Socket>, const Ipv4Address&, uint16_t> newConnectionCreated,
-		       ns3::Callback<void, Ptr<Socket> > closeRequested);
+  virtual int DoClose(Callback<void, Ptr<Socket> > closeCompleted);
+  virtual int DoConnect(const Address & address,
+                        Callback<void, Ptr<Socket> > connectionSucceeded,
+                        Callback<void, Ptr<Socket> > connectionFailed,
+                        Callback<void, Ptr<Socket> > halfClose);
+  virtual int DoAccept(Callback<bool, Ptr<Socket>, const Address&> connectionRequest,
+		       Callback<void, Ptr<Socket>, const Address&> newConnectionCreated,
+		       Callback<void, Ptr<Socket> > closeRequested);
   virtual int DoSend (const uint8_t* buffer,
                     uint32_t size,
-                    ns3::Callback<void, Ptr<Socket>, uint32_t> dataSent);
-  virtual int DoSendTo(const Ipv4Address &address,
-                      uint16_t port,
+                    Callback<void, Ptr<Socket>, uint32_t> dataSent);
+  virtual int DoSendTo(const Address &address,
                       const uint8_t *buffer,
                       uint32_t size,
-                      ns3::Callback<void, Ptr<Socket>, uint32_t> dataSent);
-  virtual void DoRecv(ns3::Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Ipv4Address&, uint16_t>);
-  virtual void DoRecvDummy(ns3::Callback<void, Ptr<Socket>, uint32_t,const Ipv4Address&, uint16_t>);
+                      Callback<void, Ptr<Socket>, uint32_t> dataSent);
+  virtual void DoRecv(Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Address&>);
+  virtual void DoRecvDummy(Callback<void, Ptr<Socket>, uint32_t,const Address&>);
 
 private:
   friend class Udp;
   // invoked by Udp class
   int FinishBind (void);
-  void ForwardUp (const Packet &p, Ipv4Address saddr, uint16_t sport);
+  void ForwardUp (const Packet &p, Ipv4Address ipv4, uint16_t port);
   void Destroy (void);
+  int DoSendPacketTo (const Packet &p, const Address &daddr,
+		      Callback<void, Ptr<Socket>, uint32_t> dataSent);
   int DoSendPacketTo (const Packet &p, Ipv4Address daddr, uint16_t dport,
-		      ns3::Callback<void, Ptr<Socket>, uint32_t> dataSent);
+		      Callback<void, Ptr<Socket>, uint32_t> dataSent);
 
   Ipv4EndPoint *m_endPoint;
   Ptr<Node> m_node;
   Ptr<UdpL4Protocol> m_udp;
   Ipv4Address m_defaultAddress;
   uint16_t m_defaultPort;
-  Callback<void,Ptr<Socket>,uint32_t,const Ipv4Address &,uint16_t> m_dummyRxCallback;
-  Callback<void,Ptr<Socket>,uint8_t const*,uint32_t,const Ipv4Address &,uint16_t> m_rxCallback;
+  Callback<void,Ptr<Socket>,uint32_t,const Address &> m_dummyRxCallback;
+  Callback<void,Ptr<Socket>,uint8_t const*,uint32_t,const Address &> m_rxCallback;
   enum SocketErrno m_errno;
   bool m_shutdownSend;
   bool m_shutdownRecv;
--- a/src/internet-node/wscript	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/internet-node/wscript	Mon Aug 06 09:59:29 2007 +0200
@@ -8,8 +8,6 @@
     obj.uselib_local = ['ns3-node', 'ns3-applications']
     obj.source = [
         'internet-node.cc',
-        'l3-demux.cc',
-        'l3-protocol.cc',
         'ipv4-l4-demux.cc',
         'ipv4-l4-protocol.cc',
         'ipv4-header.cc',
@@ -27,9 +25,7 @@
         'ipv4-loopback-interface.cc',
         'udp-socket.cc',
         'ipv4-end-point-demux.cc',
-        'arp-private.cc',
         'ipv4-impl.cc',
-        'ipv4-private.cc',
         'ascii-trace.cc',
         'pcap-trace.cc',
         'udp-impl.cc',
--- a/src/node/address-utils.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/address-utils.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -26,24 +26,34 @@
 {
   i.WriteHtonU32 (ad.GetHostOrder ());
 }
-void WriteTo (Buffer::Iterator &i, MacAddress ad)
+void WriteTo (Buffer::Iterator &i, const Address &ad)
 {
-  uint8_t mac[MacAddress::MAX_LEN];
-  ad.Peek (mac);
+  uint8_t mac[Address::MAX_SIZE];
+  ad.CopyTo (mac);
   i.Write (mac, ad.GetLength ());
 }
+void WriteTo (Buffer::Iterator &i, Eui48Address ad)
+{
+  uint8_t mac[6];
+  ad.CopyTo (mac);
+  i.Write (mac, 6);
+}
 
 void ReadFrom (Buffer::Iterator &i, Ipv4Address &ad)
 {
   ad.SetHostOrder (i.ReadNtohU32 ());
 }
-void ReadFrom (Buffer::Iterator &i, MacAddress &ad, uint32_t len)
+void ReadFrom (Buffer::Iterator &i, Address &ad, uint32_t len)
 {
-  uint8_t mac[MacAddress::MAX_LEN];
+  uint8_t mac[Address::MAX_SIZE];
   i.Read (mac, len);
-  ad.Set (mac, len);
+  ad.CopyFrom (mac, len);
+}
+void ReadFrom (Buffer::Iterator &i, Eui48Address &ad)
+{
+  uint8_t mac[6];
+  i.Read (mac, 6);
+  ad.CopyFrom (mac);
 }
 
-
-
-}; // namespace ns3
+} // namespace ns3
--- a/src/node/address-utils.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/address-utils.h	Mon Aug 06 09:59:29 2007 +0200
@@ -22,16 +22,19 @@
 #define ADDRESS_UTILS_H
 
 #include "ns3/buffer.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/mac-address.h"
+#include "ipv4-address.h"
+#include "address.h"
+#include "eui48-address.h"
 
 namespace ns3 {
 
 void WriteTo (Buffer::Iterator &i, Ipv4Address ad);
-void WriteTo (Buffer::Iterator &i, MacAddress ad);
+void WriteTo (Buffer::Iterator &i, const Address &ad);
+void WriteTo (Buffer::Iterator &i, Eui48Address ad);
 
 void ReadFrom (Buffer::Iterator &i, Ipv4Address &ad);
-void ReadFrom (Buffer::Iterator &i, MacAddress &ad, uint32_t len);
+void ReadFrom (Buffer::Iterator &i, Address &ad, uint32_t len);
+void ReadFrom (Buffer::Iterator &i, Eui48Address &ad);
 
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/address.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,164 @@
+#include "ns3/assert.h"
+#include "address.h"
+#include <iostream>
+#include <iomanip>
+
+namespace ns3 {
+
+Address::Address ()
+  : m_type (0),
+    m_len (0)
+{
+  memset (m_data, 0, m_len);
+}
+
+Address::Address (uint8_t type, const uint8_t *buffer, uint8_t len)
+  : m_type (type),
+    m_len (len)
+{
+  NS_ASSERT (m_len <= MAX_SIZE);
+  memset (m_data, 0, m_len);
+  memcpy (m_data, buffer, m_len);
+}
+Address::Address (const Address & address)
+  : m_type (address.m_type),
+    m_len (address.m_len)
+{
+  NS_ASSERT (m_len <= MAX_SIZE);
+  memset (m_data, 0, m_len);
+  memcpy (m_data, address.m_data, m_len);
+}
+Address &
+Address::operator = (const Address &address)
+{
+  NS_ASSERT (m_len <= MAX_SIZE);
+  m_type = address.m_type;
+  m_len = address.m_len;
+  NS_ASSERT (m_len <= MAX_SIZE);
+  memset (m_data, 0, m_len);
+  memcpy (m_data, address.m_data, m_len);
+  return *this;
+}
+
+bool
+Address::IsInvalid (void) const
+{
+  return m_len == 0 && m_type == 0;
+}
+
+uint8_t 
+Address::GetLength (void) const
+{
+  NS_ASSERT (m_len <= MAX_SIZE);
+  return m_len;
+}
+uint32_t
+Address::CopyTo (uint8_t buffer[MAX_SIZE]) const
+{
+  NS_ASSERT (m_len <= MAX_SIZE);
+  memcpy (buffer, m_data, m_len);
+  return m_len;
+}
+uint32_t
+Address::CopyAllTo (uint8_t *buffer, uint8_t len) const
+{
+  NS_ASSERT (len >= m_len + 2);
+  buffer[0] = m_type;
+  buffer[1] = m_len;
+  memcpy (buffer + 2, m_data, m_len);
+  return m_len + 2;
+}
+
+uint32_t
+Address::CopyFrom (const uint8_t *buffer, uint8_t len)
+{
+  NS_ASSERT (len <= MAX_SIZE);
+  memcpy (m_data, buffer, len);
+  m_len = len;
+  return m_len;
+}
+uint32_t
+Address::CopyAllFrom (const uint8_t *buffer, uint8_t len)
+{
+  NS_ASSERT (len >= 2);
+  m_type = buffer[0];
+  m_len = buffer[1];
+  NS_ASSERT (len >= m_len + 2);
+  memcpy (m_data, buffer + 2, m_len);
+  return m_len + 2;
+}
+bool 
+Address::CheckCompatible (uint8_t type, uint8_t len) const
+{
+  NS_ASSERT (len <= MAX_SIZE);
+  return m_len == len && (m_type == type || m_type == 0);
+}
+bool 
+Address::IsMatchingType (uint8_t type) const
+{
+  return m_type == type;
+}
+
+uint8_t 
+Address::Register (void)
+{
+  static uint8_t type = 1;
+  type++;
+  return type;
+}
+
+bool operator == (const Address &a, const Address &b)
+{
+  NS_ASSERT (a.m_type == b.m_type || 
+	     a.m_type == 0 || 
+	     b.m_type == 0);
+  NS_ASSERT (a.GetLength() == b.GetLength());  
+  return memcmp (a.m_data, b.m_data, a.m_len) == 0;
+}
+bool operator != (const Address &a, const Address &b)
+{
+  return !(a == b);
+}
+bool operator < (const Address &a, const Address &b)
+{
+  NS_ASSERT (a.m_type == b.m_type  || 
+	     a.m_type == 0 || 
+	     b.m_type == 0);
+  NS_ASSERT (a.GetLength() == b.GetLength());
+  for (uint8_t i = 0; i < a.GetLength(); i++) 
+    {
+      if (a.m_data[i] < b.m_data[i]) 
+	{
+	  return true;
+	} 
+      else if (a.m_data[i] > b.m_data[i]) 
+	{
+	  return false;
+	}
+    }
+  return false;
+}
+
+std::ostream& operator<< (std::ostream& os, const Address & address)
+{
+  if (address.m_len == 0) 
+    {
+      os << "NULL-ADDRESS";
+      return os;
+    }
+  os.setf (std::ios::hex, std::ios::basefield);
+  std::cout.fill('0');
+  for (uint8_t i=0; i < (address.m_len-1); i++) 
+    {
+      os << std::setw(2) << (uint32_t)address.m_data[i] << ":";
+    }
+  // Final byte not suffixed by ":"
+  os << std::setw(2) << (uint32_t)address.m_data[address.m_len-1];
+  os.setf (std::ios::dec, std::ios::basefield);
+  std::cout.fill(' ');
+  return os;
+}
+
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/address.h	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,172 @@
+#ifndef ADDRESS_H
+#define ADDRESS_H
+
+#include <stdint.h>
+#include <ostream>
+
+namespace ns3 {
+
+/**
+ * \brief a polymophic address class
+ *
+ * This class is very similar in design and spirit to the BSD sockaddr
+ * structure: they are both used to hold multiple types of addresses
+ * together with the type of the address.
+ *
+ * A new address class defined by a user needs to:
+ *   - allocate a type id with Address::Register
+ *   - provide a method to convert his new address to an Address 
+ *     instance. This method is typically a member method named ConvertTo:
+ *     Address MyAddress::ConvertTo (void) const;
+ *   - provide a method to convert an Address instance back to
+ *     an instance of his new address type. This method is typically
+ *     a static member method of his address class named ConvertFrom:
+ *     static MyAddress MyAddress::ConvertFrom (const Address &address);
+ *   - the ConvertFrom method is expected to check that the type of the
+ *     input Address instance is compatible with its own type.
+ *
+ * Typical code to create a new class type looks like:
+ * \code
+ * // this class represents addresses which are 2 bytes long.
+ * class MyAddress
+ * {
+ * public:
+ *   Address ConvertTo (void) const;
+ *   static MyAddress ConvertFrom (void);
+ * private:
+ *   static uint8_t GetType (void);
+ * };
+ *
+ * Address MyAddress::ConvertTo (void) const
+ * {
+ *   return Address (GetType (), m_buffer, 2);
+ * }
+ * MyAddress MyAddress::ConvertFrom (const Address &address)
+ * {
+ *   MyAddress ad;
+ *   NS_ASSERT (address.CheckCompatible (GetType (), 2));
+ *   address.CopyTo (ad.m_buffer, 2);
+ *   return ad;
+ * }
+ * uint8_t MyAddress::GetType (void)
+ * {
+ *   static uint8_t type = Address::Register ();
+ *   return type;
+ * }
+ * \endcode
+ */
+class Address 
+{
+public:
+  enum {
+    /**
+     * The maximum size of a byte buffer which
+     * can be stored in an Address instance.
+     */
+    MAX_SIZE = 30
+  };
+
+  /**
+   * Create an invalid address
+   */
+  Address ();
+  /**
+   * \param type the type of the Address to create
+   * \param buffer a pointer to a buffer of bytes which hold
+   *        a serialized representation of the address in network
+   *        byte order.
+   * \param len the length of the buffer.
+   * 
+   * Create an address from a type and a buffer. This constructor
+   * is typically invoked from the conversion functions of various
+   * address types when they have to convert themselves to an 
+   * Address instance.
+   */
+  Address (uint8_t type, const uint8_t *buffer, uint8_t len);
+  Address (const Address & address);
+  Address &operator = (const Address &address);
+
+  /**
+   * \returns true if this address is invalid, false otherwise.
+   *
+   * An address is invalid if and only if it was created
+   * through the default constructor and it was never
+   * re-initialized.
+   */
+  bool IsInvalid (void) const;
+  /**
+   * \returns the length of the underlying address.
+   */
+  uint8_t GetLength (void) const;
+  /**
+   * \param buffer buffer to copy the address bytes to.
+   * \returns the number of bytes copied.
+   */
+  uint32_t CopyTo (uint8_t buffer[MAX_SIZE]) const;
+  /**
+   * \param buffer buffer to copy the whole address data structure to
+   * \param len the size of the buffer
+   * \returns the number of bytes copied.
+   */
+  uint32_t CopyAllTo (uint8_t *buffer, uint8_t len) const;
+  /**
+   * \param buffer pointer to a buffer of bytes which contain
+   *        a serialized representation of the address in network
+   *        byte order.
+   * \param len length of buffer
+   * \returns the number of bytes copied.
+   *
+   * Copy the input buffer to the internal buffer of this address 
+   * instance.
+   */
+  uint32_t CopyFrom (const uint8_t *buffer, uint8_t len);
+  /**
+   * \param buffer pointer to a buffer of bytes which contain
+   *        a copy of all the members of this Address class.
+   * \param len the length of the buffer
+   * \returns the number of bytes copied.
+   */
+  uint32_t CopyAllFrom (const uint8_t *buffer, uint8_t len);
+  /**
+   * \param type a type id as returned by Address::Register
+   * \param len the length associated to this type id.
+   *
+   * \returns true if the type of the address stored internally
+   * is compatible with the requested type, false otherwise.
+   */
+  bool CheckCompatible (uint8_t type, uint8_t len) const;
+  /**
+   * \param type a type id as returned by Address::Register
+   * \returns true if the type of the address stored internally
+   * is compatible with the requested type, false otherwise.
+   *
+   * This method checks that the types are _exactly_ equal.
+   * This method is really used only by the PacketSocketAddress
+   * and there is little point in using it otherwise so, 
+   * you have been warned: DO NOT USE THIS METHOD.
+   */
+  bool IsMatchingType (uint8_t type) const;
+  /**
+   * Allocate a new type id for a new type of address.
+   * \returns a new type id.
+   */
+  static uint8_t Register (void);
+private:
+  friend bool operator == (const Address &a, const Address &b);
+  friend bool operator < (const Address &a, const Address &b);
+  friend std::ostream& operator<< (std::ostream& os, const Address & address);
+
+  uint8_t m_type;
+  uint8_t m_len;
+  uint8_t m_data[MAX_SIZE];
+};
+
+bool operator == (const Address &a, const Address &b);
+bool operator != (const Address &a, const Address &b);
+bool operator < (const Address &a, const Address &b);
+std::ostream& operator<< (std::ostream& os, const Address & address);
+
+} // namespace ns3
+
+
+#endif /* ADDRESS_H */
--- a/src/node/ethernet-header.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/ethernet-header.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -74,22 +74,22 @@
 }
 
 void 
-EthernetHeader::SetSource (MacAddress source)
+EthernetHeader::SetSource (Eui48Address source)
 {
   m_source = source;
 }
-MacAddress
+Eui48Address
 EthernetHeader::GetSource (void) const
 {
   return m_source;
 }
 
 void 
-EthernetHeader::SetDestination (MacAddress dst)
+EthernetHeader::SetDestination (Eui48Address dst)
 {
   m_destination = dst;
 }
-MacAddress
+Eui48Address
 EthernetHeader::GetDestination (void) const
 {
   return m_destination;
@@ -147,8 +147,6 @@
     {
       i.WriteU64(m_preambleSfd);
     }
-  NS_ASSERT (m_destination.GetLength () == MAC_ADDR_SIZE);
-  NS_ASSERT (m_source.GetLength () == MAC_ADDR_SIZE);
   WriteTo (i, m_destination);
   WriteTo (i, m_source);
   i.WriteU16 (m_lengthType);
@@ -163,11 +161,11 @@
       m_enPreambleSfd = i.ReadU64 ();
     }
 
-  ReadFrom (i, m_destination, MAC_ADDR_SIZE);
-  ReadFrom (i, m_source, MAC_ADDR_SIZE);
+  ReadFrom (i, m_destination);
+  ReadFrom (i, m_source);
   m_lengthType = i.ReadU16 ();
 
   return GetSerializedSize ();
 }
 
-}; // namespace ns3
+} // namespace ns3
--- a/src/node/ethernet-header.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/ethernet-header.h	Mon Aug 06 09:59:29 2007 +0200
@@ -23,8 +23,8 @@
 #define ETHERNET_HEADER_H
 
 #include "ns3/header.h"
-#include "ns3/mac-address.h"
 #include <string>
+#include "ns3/eui48-address.h"
 
 namespace ns3 {
 
@@ -70,11 +70,11 @@
   /**
    * \param source The source address of this packet
    */
-  void SetSource (MacAddress source);
+  void SetSource (Eui48Address source);
   /**
    * \param destination The destination address of this packet.
    */
-  void SetDestination (MacAddress destination);
+  void SetDestination (Eui48Address destination);
   /**
    * \param preambleSfd The value that the preambleSfd field should take
    */
@@ -90,11 +90,11 @@
   /**
    * \return The source address of this packet
    */
-  MacAddress GetSource (void) const;
+  Eui48Address GetSource (void) const;
   /**
    * \return The destination address of this packet
    */
-  MacAddress GetDestination (void) const;  
+  Eui48Address GetDestination (void) const;  
   /**
    * \return The value of the PreambleSfd field
    */
@@ -121,8 +121,8 @@
   bool m_enPreambleSfd;
   uint64_t m_preambleSfd;     /// Value of the Preamble/SFD fields
   uint16_t m_lengthType;      /// Length or type of the packet
-  MacAddress m_source;        /// Source address
-  MacAddress m_destination;   /// Destination address
+  Eui48Address m_source;        /// Source address
+  Eui48Address m_destination;   /// Destination address
 };
 
 }; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/eui48-address.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,164 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "eui48-address.h"
+#include "address.h"
+#include "ns3/assert.h"
+#include <iomanip>
+#include <iostream>
+
+namespace ns3 {
+
+#define ASCII_a (0x41)
+#define ASCII_z (0x5a)
+#define ASCII_A (0x61)
+#define ASCII_Z (0x7a)
+#define ASCII_COLON (0x3a)
+#define ASCII_ZERO (0x30)
+
+static char
+AsciiToLowCase (char c)
+{
+  if (c >= ASCII_a && c <= ASCII_z) {
+    return c;
+  } else if (c >= ASCII_A && c <= ASCII_Z) {
+    return c + (ASCII_a - ASCII_A);
+  } else {
+    return c;
+  }
+}
+
+
+Eui48Address::Eui48Address ()
+{
+  memset (m_address, 0, 6);
+}
+Eui48Address::Eui48Address (const char *str)
+{
+  int i = 0;
+  while (*str != 0 && i < 6) 
+    {
+      uint8_t byte = 0;
+      while (*str != ASCII_COLON && *str != 0) 
+	{
+	  byte <<= 4;
+	  char low = AsciiToLowCase (*str);
+	  if (low >= ASCII_a) 
+	    {
+	      byte |= low - ASCII_a + 10;
+	    } 
+	  else 
+	    {
+	      byte |= low - ASCII_ZERO;
+	    }
+	  str++;
+	}
+      m_address[i] = byte;
+      i++;
+      if (*str == 0) 
+	{
+	  break;
+	}
+      str++;
+    }
+  NS_ASSERT (i == 6);
+}
+void 
+Eui48Address::CopyFrom (const uint8_t buffer[6])
+{
+  memcpy (m_address, buffer, 6);
+}
+void 
+Eui48Address::CopyTo (uint8_t buffer[6]) const
+{
+  memcpy (buffer, m_address, 6);
+}
+
+bool 
+Eui48Address::IsMatchingType (const Address &address)
+{
+  return address.CheckCompatible (GetType (), 6);
+}
+Address 
+Eui48Address::ConvertTo (void) const
+{
+  return Address (GetType (), m_address, 6);
+}
+Eui48Address 
+Eui48Address::ConvertFrom (const Address &address)
+{
+  NS_ASSERT (address.CheckCompatible (GetType (), 6));
+  Eui48Address retval;
+  address.CopyTo (retval.m_address);
+  return retval;
+}
+Eui48Address 
+Eui48Address::Allocate (void)
+{
+  static uint64_t id = 0;
+  id++;
+  Eui48Address address;
+  address.m_address[0] = (id >> 40) & 0xff;
+  address.m_address[1] = (id >> 32) & 0xff;
+  address.m_address[2] = (id >> 24) & 0xff;
+  address.m_address[3] = (id >> 16) & 0xff;
+  address.m_address[4] = (id >> 8) & 0xff;
+  address.m_address[5] = (id >> 0) & 0xff;
+  return address;
+}
+uint8_t 
+Eui48Address::GetType (void)
+{
+  static uint8_t type = Address::Register ();
+  return type;
+}
+
+bool operator == (const Eui48Address &a, const Eui48Address &b)
+{
+  uint8_t ada[6];
+  uint8_t adb[6];
+  a.CopyTo (ada);
+  b.CopyTo (adb);
+  return memcmp (ada, adb, 6) == 0;
+}
+bool operator != (const Eui48Address &a, const Eui48Address &b)
+{
+  return ! (a == b);
+}
+
+std::ostream& operator<< (std::ostream& os, const Eui48Address & address)
+{
+  uint8_t ad[6];
+  address.CopyTo (ad);
+
+  os.setf (std::ios::hex, std::ios::basefield);
+  std::cout.fill('0');
+  for (uint8_t i=0; i < 5; i++) 
+    {
+      os << std::setw(2) << (uint32_t)ad[i] << ":";
+    }
+  // Final byte not suffixed by ":"
+  os << std::setw(2) << (uint32_t)ad[5];
+  os.setf (std::ios::dec, std::ios::basefield);
+  std::cout.fill(' ');
+  return os;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/eui48-address.h	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,90 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef EUI48_ADDRESS_H
+#define EUI48_ADDRESS_H
+
+#include <stdint.h>
+#include <ostream>
+
+namespace ns3 {
+
+class Address;
+
+/**
+ * \brief an EUI-48 address
+ *
+ * This class can contain 48 bit IEEE addresses.
+ */
+class Eui48Address
+{
+public:
+  Eui48Address ();
+  /**
+   * \param str a string representing the new Eui48Address
+   *
+   * The format of the string is "xx:xx:xx:xx:xx:xx"
+   */
+  Eui48Address (const char *str);
+
+  /**
+   * \param buffer address in network order
+   *
+   * Copy the input address to our internal buffer.
+   */
+  void CopyFrom (const uint8_t buffer[6]);
+  /**
+   * \param buffer address in network order
+   *
+   * Copy the internal address to the input buffer.
+   */
+  void CopyTo (uint8_t buffer[6]) const;
+  /**
+   * \returns a new Address instance
+   *
+   * Convert an instance of this class to a polymorphic Address instance.
+   */
+  Address ConvertTo (void) const;
+  /**
+   * \returns true if the address matches, false otherwise.
+   */
+  static bool IsMatchingType (const Address &address);
+  /**
+   * \param address a polymorphic address
+   *
+   * Convert a polymorphic address to an Eui48Address instance.
+   * The conversion performs a type check.
+   */
+  static Eui48Address ConvertFrom (const Address &address);
+  /**
+   * Allocate a new Eui48Address.
+   */
+  static Eui48Address Allocate (void);
+private:
+  static uint8_t GetType (void);
+  uint8_t m_address[6];
+};
+
+bool operator == (const Eui48Address &a, const Eui48Address &b);
+bool operator != (const Eui48Address &a, const Eui48Address &b);
+std::ostream& operator<< (std::ostream& os, const Eui48Address & address);
+
+} // namespace ns3
+
+#endif /* EUI48_ADDRESS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/eui64-address.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,166 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "eui64-address.h"
+#include "address.h"
+#include "ns3/assert.h"
+#include <iomanip>
+#include <iostream>
+
+namespace ns3 {
+
+#define ASCII_a (0x41)
+#define ASCII_z (0x5a)
+#define ASCII_A (0x61)
+#define ASCII_Z (0x7a)
+#define ASCII_COLON (0x3a)
+#define ASCII_ZERO (0x30)
+
+static char
+AsciiToLowCase (char c)
+{
+  if (c >= ASCII_a && c <= ASCII_z) {
+    return c;
+  } else if (c >= ASCII_A && c <= ASCII_Z) {
+    return c + (ASCII_a - ASCII_A);
+  } else {
+    return c;
+  }
+}
+
+
+Eui64Address::Eui64Address ()
+{
+  memset (m_address, 0, 8);
+}
+Eui64Address::Eui64Address (const char *str)
+{
+  int i = 0;
+  while (*str != 0 && i < 8) 
+    {
+      uint8_t byte = 0;
+      while (*str != ASCII_COLON && *str != 0) 
+	{
+	  byte <<= 4;
+	  char low = AsciiToLowCase (*str);
+	  if (low >= ASCII_a) 
+	    {
+	      byte |= low - ASCII_a + 10;
+	    } 
+	  else 
+	    {
+	      byte |= low - ASCII_ZERO;
+	    }
+	  str++;
+	}
+      m_address[i] = byte;
+      i++;
+      if (*str == 0) 
+	{
+	  break;
+	}
+      str++;
+    }
+  NS_ASSERT (i == 6);
+}
+void 
+Eui64Address::CopyFrom (const uint8_t buffer[8])
+{
+  memcpy (m_address, buffer, 8);
+}
+void 
+Eui64Address::CopyTo (uint8_t buffer[8]) const
+{
+  memcpy (buffer, m_address, 8);
+}
+
+bool 
+Eui64Address::IsMatchingType (const Address &address)
+{
+  return address.CheckCompatible (GetType (), 8);
+}
+Address 
+Eui64Address::ConvertTo (void) const
+{
+  return Address (GetType (), m_address, 8);
+}
+Eui64Address 
+Eui64Address::ConvertFrom (const Address &address)
+{
+  NS_ASSERT (address.CheckCompatible (GetType (), 8));
+  Eui64Address retval;
+  address.CopyTo (retval.m_address);
+  return retval;
+}
+Eui64Address 
+Eui64Address::Allocate (void)
+{
+  static uint64_t id = 0;
+  id++;
+  Eui64Address address;
+  address.m_address[0] = (id >> 56) & 0xff;
+  address.m_address[1] = (id >> 48) & 0xff;
+  address.m_address[2] = (id >> 40) & 0xff;
+  address.m_address[3] = (id >> 32) & 0xff;
+  address.m_address[4] = (id >> 24) & 0xff;
+  address.m_address[5] = (id >> 16) & 0xff;
+  address.m_address[6] = (id >> 8) & 0xff;
+  address.m_address[7] = (id >> 0) & 0xff;
+  return address;
+}
+uint8_t 
+Eui64Address::GetType (void)
+{
+  static uint8_t type = Address::Register ();
+  return type;
+}
+
+bool operator == (const Eui64Address &a, const Eui64Address &b)
+{
+  uint8_t ada[8];
+  uint8_t adb[8];
+  a.CopyTo (ada);
+  b.CopyTo (adb);
+  return memcmp (ada, adb, 8) == 0;
+}
+bool operator != (const Eui64Address &a, const Eui64Address &b)
+{
+  return ! (a == b);
+}
+
+std::ostream& operator<< (std::ostream& os, const Eui64Address & address)
+{
+  uint8_t ad[8];
+  address.CopyTo (ad);
+
+  os.setf (std::ios::hex, std::ios::basefield);
+  std::cout.fill('0');
+  for (uint8_t i=0; i < 7; i++) 
+    {
+      os << std::setw(2) << (uint32_t)ad[i] << ":";
+    }
+  // Final byte not suffixed by ":"
+  os << std::setw(2) << (uint32_t)ad[7];
+  os.setf (std::ios::dec, std::ios::basefield);
+  std::cout.fill(' ');
+  return os;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/eui64-address.h	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,90 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef EUI64_ADDRESS_H
+#define EUI64_ADDRESS_H
+
+#include <stdint.h>
+#include <ostream>
+
+namespace ns3 {
+
+class Address;
+
+/**
+ * \brief an EUI-48 address
+ *
+ * This class can contain 48 bit IEEE addresses.
+ */
+class Eui64Address
+{
+public:
+  Eui64Address ();
+  /**
+   * \param str a string representing the new Eui64Address
+   *
+   * The format of the string is "xx:xx:xx:xx:xx:xx"
+   */
+  Eui64Address (const char *str);
+
+  /**
+   * \param buffer address in network order
+   *
+   * Copy the input address to our internal buffer.
+   */
+  void CopyFrom (const uint8_t buffer[8]);
+  /**
+   * \param buffer address in network order
+   *
+   * Copy the internal address to the input buffer.
+   */
+  void CopyTo (uint8_t buffer[8]) const;
+  /**
+   * \returns a new Address instance
+   *
+   * Convert an instance of this class to a polymorphic Address instance.
+   */
+  Address ConvertTo (void) const;
+  /**
+   * \returns true if the address matches, false otherwise.
+   */
+  static bool IsMatchingType (const Address &address);
+  /**
+   * \param address a polymorphic address
+   *
+   * Convert a polymorphic address to an Eui64Address instance.
+   * The conversion performs a type check.
+   */
+  static Eui64Address ConvertFrom (const Address &address);
+  /**
+   * Allocate a new Eui64Address.
+   */
+  static Eui64Address Allocate (void);
+private:
+  static uint8_t GetType (void);
+  uint8_t m_address[8];
+};
+
+bool operator == (const Eui64Address &a, const Eui64Address &b);
+bool operator != (const Eui64Address &a, const Eui64Address &b);
+std::ostream& operator<< (std::ostream& os, const Eui64Address & address);
+
+} // namespace ns3
+
+#endif /* EUI64_ADDRESS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/inet-socket-address.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,80 @@
+#include "inet-socket-address.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+InetSocketAddress::InetSocketAddress (Ipv4Address ipv4, uint16_t port)
+  : m_ipv4 (ipv4),
+    m_port (port)
+{}
+InetSocketAddress::InetSocketAddress (Ipv4Address ipv4)
+  : m_ipv4 (ipv4),
+    m_port (0)
+{}
+InetSocketAddress::InetSocketAddress (const char *ipv4, uint16_t port)
+  : m_ipv4 (Ipv4Address (ipv4)),
+    m_port (port)
+{}
+InetSocketAddress::InetSocketAddress (const char * ipv4)
+  : m_ipv4 (Ipv4Address (ipv4)),
+    m_port (0)
+{}
+InetSocketAddress::InetSocketAddress (uint16_t port)
+  : m_ipv4 (Ipv4Address::GetAny ()),
+    m_port (port)
+{}
+uint16_t 
+InetSocketAddress::GetPort (void) const
+{
+  return m_port;
+}
+Ipv4Address 
+InetSocketAddress::GetIpv4 (void) const
+{
+  return m_ipv4;
+}
+
+void 
+InetSocketAddress::SetPort (uint16_t port)
+{
+  m_port = port;
+}
+void 
+InetSocketAddress::SetIpv4 (Ipv4Address address)
+{
+  m_ipv4 = address;
+}
+
+bool 
+InetSocketAddress::IsMatchingType (const Address &address)
+{
+  return address.CheckCompatible (GetType (), 6);
+}
+
+Address 
+InetSocketAddress::ConvertTo (void) const
+{
+  uint8_t buf[6];
+  m_ipv4.Serialize (buf);
+  buf[4] = m_port & 0xff;
+  buf[5] = (m_port >> 8) & 0xff;
+  return Address (GetType (), buf, 6);
+}
+InetSocketAddress 
+InetSocketAddress::ConvertFrom (const Address &address)
+{
+  NS_ASSERT (address.CheckCompatible (GetType (), 6));
+  uint8_t buf[6];
+  address.CopyTo (buf);
+  Ipv4Address ipv4 = Ipv4Address::Deserialize (buf);
+  uint16_t port = buf[0] | (buf[1] << 8);
+  return InetSocketAddress (ipv4, port);
+}
+uint8_t 
+InetSocketAddress::GetType (void)
+{
+  static uint8_t type = Address::Register ();
+  return type;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/inet-socket-address.h	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,92 @@
+#ifndef IPV4_TRANSPORT_ADDRESS_H
+#define IPV4_TRANSPORT_ADDRESS_H
+
+#include "address.h"
+#include "ipv4-address.h"
+#include <stdint.h>
+
+namespace ns3 {
+
+
+/**
+ * \brief an Inet address class
+ *
+ * This class is similar to inet_sockaddr in the BSD socket
+ * API. i.e., this class holds an Ipv4Address and a port number
+ * to form an ipv4 transport endpoint.
+ */
+class InetSocketAddress
+{
+public:
+  /**
+   * \param ipv4 the ipv4 address
+   * \param port the port number
+   */
+  InetSocketAddress (Ipv4Address ipv4, uint16_t port);
+  /**
+   * \param ipv4 the ipv4 address
+   *
+   * The port number is set to zero by default.
+   */
+  InetSocketAddress (Ipv4Address ipv4);
+  /**
+   * \param port the port number
+   *
+   * The ipv4 address is set to the "Any" address by default.
+   */
+  InetSocketAddress (uint16_t port);
+  /**
+   * \param ipv4 string which represents an ipv4 address
+   * \param port the port number
+   */
+  InetSocketAddress (const char *ipv4, uint16_t port);
+  /**
+   * \param ipv4 string which represents an ipv4 address
+   *
+   * The port number is set to zero.
+   */
+  InetSocketAddress (const char *ipv4);
+  /**
+   * \returns the port number
+   */
+  uint16_t GetPort (void) const;
+  /**
+   * \returns the ipv4 address
+   */
+  Ipv4Address GetIpv4 (void) const;
+
+  /**
+   * \param port the new port number.
+   */
+  void SetPort (uint16_t port);
+  /**
+   * \param address the new ipv4 address
+   */
+  void SetIpv4 (Ipv4Address address);
+
+  /**
+   * \returns true if the address matches, false otherwise.
+   */
+  static bool IsMatchingType (const Address &address);
+
+  /**
+   * \returns an Address instance which represents this
+   * InetSocketAddress instance.
+   */
+  Address ConvertTo (void) const;
+  /**
+   * \param address the Address instance to convert from.
+   * \returns an InetSocketAddress which corresponds to the input
+   * Address
+   */
+  static InetSocketAddress ConvertFrom (const Address &address);
+private:
+  static uint8_t GetType (void);
+  Ipv4Address m_ipv4;
+  uint16_t m_port;
+};
+
+} // namespace ns3
+
+
+#endif /* IPV4_TRANSPORT_ADDRESS_H */
--- a/src/node/ipv4-address.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/ipv4-address.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -19,11 +19,11 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "ns3/debug.h"
+#include "ipv4-address.h"
+#include "ns3/assert.h"
 
 NS_DEBUG_COMPONENT_DEFINE("Ipv4Address");
 
-#include "ipv4-address.h"
-
 
 namespace ns3 {
 
@@ -193,6 +193,20 @@
   buf[2] = (m_address >> 8) & 0xff;
   buf[3] = (m_address >> 0) & 0xff;
 }
+Ipv4Address 
+Ipv4Address::Deserialize (const uint8_t buf[4])
+{
+  Ipv4Address ipv4;
+  ipv4.m_address = 0;
+  ipv4.m_address |= buf[0];
+  ipv4.m_address <<= 8;
+  ipv4.m_address |= buf[1];
+  ipv4.m_address <<= 8;
+  ipv4.m_address |= buf[2];
+  ipv4.m_address <<= 8;
+  ipv4.m_address |= buf[3];
+  return ipv4;
+}
 
 void 
 Ipv4Address::Print (std::ostream &os) const
@@ -203,7 +217,34 @@
      << ((m_address >> 0) & 0xff);
 }
 
+bool 
+Ipv4Address::IsMatchingType (const Address &address)
+{
+  return address.CheckCompatible (GetType (), 4);
+}
+Address 
+Ipv4Address::ConvertTo (void) const
+{
+  uint8_t buf[4];
+  Serialize (buf);
+  return Address (GetType (), buf, 4);
+}
 
+Ipv4Address
+Ipv4Address::ConvertFrom (const Address &address)
+{
+  NS_ASSERT (address.CheckCompatible (GetType (), 4));
+  uint8_t buf[4];
+  address.CopyTo (buf);
+  return Deserialize (buf);
+}
+
+uint8_t 
+Ipv4Address::GetType (void)
+{
+  static uint8_t type = Address::Register ();
+  return type;
+}
 
 Ipv4Address 
 Ipv4Address::GetZero (void)
--- a/src/node/ipv4-address.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/ipv4-address.h	Mon Aug 06 09:59:29 2007 +0200
@@ -24,6 +24,7 @@
 
 #include <stdint.h>
 #include <ostream>
+#include "address.h"
 
 namespace ns3 {
 
@@ -86,11 +87,19 @@
   void SetHostOrder (uint32_t ip);
   /**
    * Serialize this address to a 4-byte buffer
+   *
    * \param buf output buffer to which this address gets overwritten with this
    * Ipv4Address
    */
   void Serialize (uint8_t buf[4]) const;
   /**
+   * \param buf buffer to read address from
+   * \returns an Ipv4Address
+   * 
+   * The input address is expected to be in network byte order format.
+   */
+  static Ipv4Address Deserialize (const uint8_t buf[4]);
+  /**
    * \brief Print this address to the given output stream
    *
    * The print format is in the typical "192.168.1.1"
@@ -111,11 +120,16 @@
    */
   Ipv4Address CombineMask (Ipv4Mask const &mask) const;
 
+  static bool IsMatchingType (const Address &address);
+  Address ConvertTo (void) const;
+  static Ipv4Address ConvertFrom (const Address &address);
+
   static Ipv4Address GetZero (void);
   static Ipv4Address GetAny (void);
   static Ipv4Address GetBroadcast (void);
   static Ipv4Address GetLoopback (void);
 private:
+  static uint8_t GetType (void);
   uint32_t m_address;
 };
 
--- a/src/node/mac-address.cc	Mon Aug 06 09:58:03 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/* -*-	Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include <iostream>
-#include <iomanip>
-#include "ns3/assert.h"
-#include "mac-address.h"
-
-#define ASCII_a (0x41)
-#define ASCII_z (0x5a)
-#define ASCII_A (0x61)
-#define ASCII_Z (0x7a)
-#define ASCII_COLON (0x3a)
-#define ASCII_ZERO (0x30)
-
-namespace ns3 {
-
-// Static variables
-uint8_t MacAddress::g_nextAddress[MacAddress::MAX_LEN];
-
-static char
-AsciiToLowCase (char c)
-{
-  if (c >= ASCII_a && c <= ASCII_z) {
-    return c;
-  } else if (c >= ASCII_A && c <= ASCII_Z) {
-    return c + (ASCII_a - ASCII_A);
-  } else {
-    return c;
-  }
-}
-
-
-MacAddress::MacAddress () : m_len(0)
-{
-  for (int i=0; i < MacAddress::MAX_LEN; i++) 
-    {
-      m_address[i] = 0;
-    }
-}
-
-MacAddress::MacAddress(uint8_t len) : m_len(len)
-{
-  NS_ASSERT (len <= MacAddress::MAX_LEN);
-  AdvanceAddress();
-  memcpy(m_address, g_nextAddress, len);
-}
-
-MacAddress::MacAddress (uint8_t const *address, uint8_t len)
-{
-  NS_ASSERT (len <= MacAddress::MAX_LEN);
-  for (int i=0; i < len; i++) 
-    {
-      m_address[i] = address[i];
-    }
-  for (int i=len; i < MacAddress::MAX_LEN; i++) 
-    {
-      m_address[i] = 0;
-    } 
-  m_len = len;
-}
-
-MacAddress::MacAddress (char const *str)
-{       
-  int i = 0;
-  while (*str != 0 && i < MacAddress::MAX_LEN) {
-    uint8_t byte = 0;
-    while (*str != ASCII_COLON && *str != 0) {
-      byte <<= 4;
-      char low = AsciiToLowCase (*str);
-      if (low >= ASCII_a) {
-        byte |= low - ASCII_a + 10;
-      } else {
-        byte |= low - ASCII_ZERO;
-      }
-      str++;
-    }
-    m_address[i] = byte;
-    i++;
-    if (*str == 0) {
-      break;
-    }
-    str++;
-  }
-  m_len = i;
-}
-
-MacAddress::~MacAddress ()
-{}
-
-bool 
-MacAddress::IsEqual (MacAddress other) const
-{
-    if (memcmp(other.m_address, m_address, m_len)) 
-      {
-        return false;
-      } 
-    else 
-      {
-        return true;
-      } 
-}
-
-void
-MacAddress::Print (std::ostream &os) const
-{
-    int i;
-    if (m_len == 0) 
-      {
-        os << "NULL-ADDRESS";
-        return;
-      }
-    os.setf (std::ios::hex, std::ios::basefield);
-    std::cout.fill('0');
-    for (i=0; i< (m_len-1); i++) 
-      {
-	os << std::setw(2) << (uint32_t)m_address[i] << ":";
-      }
-    // Final byte not suffixed by ":"
-    os << std::setw(2) << (uint32_t)m_address[i];
-    os.setf (std::ios::dec, std::ios::basefield);
-    std::cout.fill(' ');
-}
-
-uint8_t
-MacAddress::GetLength () const
-{
-    return m_len;
-}
-
-void
-MacAddress::Peek (uint8_t ad[MacAddress::MAX_LEN]) const
-{
-	memcpy (ad, m_address, MacAddress::MAX_LEN);
-}
-void
-MacAddress::Set (uint8_t const ad[MacAddress::MAX_LEN], uint8_t len)
-{
-	memcpy (m_address, ad, MacAddress::MAX_LEN);
-        m_len = len;
-}
-
-// Static methods
-void MacAddress::AdvanceAddress()
-  {
-    // Advance to next address, little end first
-    for(size_t i = 0; i < MAX_LEN; ++i)
-      {
-        if (++g_nextAddress[i] != 0) break;
-      }
-  }
-
-// Non-member operators
-bool operator == (MacAddress const&a, MacAddress const&b)
-{
-	return a.IsEqual (b);
-}
-
-bool operator != (MacAddress const&a, MacAddress const&b)
-{
-	return !a.IsEqual (b);
-}
-
-bool operator < (MacAddress const&a, MacAddress const&b)
-{
-        uint8_t a_p[MacAddress::MAX_LEN];
-        uint8_t b_p[MacAddress::MAX_LEN];
-        a.Peek (a_p);
-        b.Peek (b_p);
-        NS_ASSERT (a.GetLength() == b.GetLength());
-        for (uint8_t i = 0; i < a.GetLength(); i++) 
-          {
-            if (a_p[i] < b_p[i]) 
-              {
-                return true;
-              } 
-            else if (a_p[i] > b_p[i]) 
-              {
-                return false;
-              }
-          }
-        return false;
-}
-
-std::ostream& operator<< (std::ostream& os, MacAddress const& address)
-{
-	address.Print (os);
-	return os;
-}
-
-
-}; // namespace ns3
--- a/src/node/mac-address.h	Mon Aug 06 09:58:03 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/* -*-	Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#ifndef MAC_ADDRESS_H
-#define MAC_ADDRESS_H
-
-#include <stdint.h>
-#include <ostream>
-
-namespace ns3 {
-
-/**
- * \brief base class for Network Device addresses
- *
- * This class is a base class for different types of Network
- * Device addresses.  It generically stores an address of 
- * MAX_ADDR_LEN bytes, and provides methods to compare, print, and set
- * the address.
- */
-class MacAddress {
-public:
-  enum {
-    MAX_LEN = 32
-  };
-  /**
-   * \brief Construct a null MacAddress
-   *
-   * This MacAddress has length of zero, and is internally all zeros
-   */
-  MacAddress (void);
-  /**
-   * \brief Construct a MacAddress using the next available
-   * address.
-   * \see MacAddres::Next
-   * \param len length, in bytes, of the desired address
-   */
-  MacAddress(uint8_t len);
-  /**
-   * \brief Construct a MacAddress from a byte-array
-   *
-   * low byte should be first.
-   * \param address a byte array indicating the address
-   * \param len length, in bytes, of the address points to
-   */
-  MacAddress (uint8_t const *address, uint8_t len);
-  /**
-   * \brief Construct a MacAddress from a C-string
-   *
-   * The string should look like this:
-   * hh:xx:xx:xx:xx:ll
-   * where hh is the high byte and ll is
-   * the low byte.
-   * \param address the C-string representation of the address
-   */
-  MacAddress (char const *address);
-  ~MacAddress ();
-  
-  /**
-   * \brief Comparison operation between MacAddresses
-   * \param other The address against which to compare this one
-   * \return True if they are equal, false otherwise.
-   */   
-  bool IsEqual (MacAddress other) const;
-  /**
-   * \brief Print this MacAddress to a stream
-   *
-   * The format is colon seperated groups of two hexadecimal digits
-   * \param os The output stream desired
-   */ 
-  void Print (std::ostream &os) const;
-  
-  /**
-   * \return The length in bytes of this MacAddress
-   */
-  uint8_t GetLength() const;
-  /**
-   * \brief Copy routine to peek the contents of the MacAddress
-   *
-   * \param ad Output parameter which holds a copy of this MacAddress
-   */
-  void Peek (uint8_t ad[MAX_LEN]) const;
-  /**
-   * \brief Sets this MacAddress to a specific value
-   * \param ad byte buffer to set the MacAddress to
-   * \param len the length of the buffer
-   */
-  void Set (uint8_t const ad[MAX_LEN], uint8_t len);
-
-  // Static methods/members
-  /**
-   *
-   * Advance the global to the next available mac address.
-   */
-  static void AdvanceAddress();
-  static uint8_t g_nextAddress[MAX_LEN];
-
-private:
-  uint8_t m_address[MAX_LEN];
-  uint8_t m_len;
-};
-
-bool operator == (MacAddress const&a, MacAddress const&b);
-bool operator != (MacAddress const&a, MacAddress const&b);
-bool operator < (MacAddress const&a, MacAddress const&b);
-
-std::ostream& operator<< (std::ostream& os, MacAddress const& address);
-
-}; // namespace ns3
-
-#endif /* MAC_ADDRESS_H */
--- a/src/node/net-device.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/net-device.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -35,7 +35,7 @@
 
 const InterfaceId NetDevice::iid = MakeInterfaceId ("NetDevice", Object::iid);
 
-NetDevice::NetDevice(Ptr<Node> node, const MacAddress& addr) : 
+NetDevice::NetDevice(Ptr<Node> node, const Address& addr) : 
   m_node (node), 
   m_name(""), 
   m_ifIndex (0), 
@@ -53,7 +53,7 @@
 NetDevice::~NetDevice ()
 {}
 
-MacAddress 
+Address 
 NetDevice::GetAddress (void) const
 {
   return m_address;
@@ -113,7 +113,7 @@
 {
   return m_isBroadcast;
 }
-MacAddress const &
+Address const &
 NetDevice::GetBroadcast (void) const
 {
   NS_ASSERT (m_isBroadcast);
@@ -121,7 +121,7 @@
 }
 
 void
-NetDevice::EnableBroadcast (MacAddress broadcast)
+NetDevice::EnableBroadcast (Address broadcast)
 {
   m_isBroadcast = true;
   m_broadcast = broadcast;
@@ -171,7 +171,7 @@
 
 // Receive packet from above
 bool 
-NetDevice::Send(Packet& p, const MacAddress& dest, uint16_t protocolNumber)
+NetDevice::Send(Packet& p, const Address& dest, uint16_t protocolNumber)
 {
   if (m_isUp)
     {
@@ -197,18 +197,19 @@
 
 // Receive packets from below
 bool
-NetDevice::ForwardUp(Packet& p, uint32_t param)
+NetDevice::ForwardUp(const Packet& p, uint32_t param, const Address &from)
 {
   bool retval = false;
-  Packet packet = p;
 
-  NS_DEBUG ("NetDevice::ForwardUp: UID is " << packet.GetUid()
+  NS_DEBUG ("NetDevice::ForwardUp: UID is " << p.GetUid()
             << " device is: " << GetName());
   
   if (!m_receiveCallback.IsNull ())
     {
-      retval = m_receiveCallback (this, packet, param);
-    } else {
+      retval = m_receiveCallback (this, p, param, from);
+    } 
+  else 
+    {
       NS_DEBUG ("NetDevice::Receive call back is NULL");
     }
 
@@ -248,7 +249,7 @@
 }
 
 void 
-NetDevice::SetReceiveCallback (Callback<bool,Ptr<NetDevice>,const Packet &,uint16_t> cb)
+NetDevice::SetReceiveCallback (ReceiveCallback cb)
 {
   m_receiveCallback = cb;
 }
--- a/src/node/net-device.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/net-device.h	Mon Aug 06 09:59:29 2007 +0200
@@ -28,7 +28,7 @@
 #include "ns3/packet.h"
 #include "ns3/object.h"
 #include "ns3/ptr.h"
-#include "mac-address.h"
+#include "address.h"
 
 namespace ns3 {
 
@@ -79,9 +79,9 @@
   Ptr<Channel> GetChannel (void) const;
 
   /**
-   * \return the current MacAddress of this interface.
+   * \return the current Address of this interface.
    */
-  MacAddress GetAddress (void) const;
+  Address GetAddress (void) const;
   /**
    * \param mtu MTU value, in bytes, to set for the device
    * \return whether the MTU value was within legal bounds
@@ -137,7 +137,7 @@
    * Calling this method is invalid if IsBroadcast returns
    * not true.
    */
-  MacAddress const &GetBroadcast (void) const;
+  Address const &GetBroadcast (void) const;
   /**
    * \return value of m_isMulticast flag
    */
@@ -154,11 +154,11 @@
    *        is received.
    * 
    *  Called from higher layer to send packet into Network Device
-   *  to the specified destination MacAddress
+   *  to the specified destination Address
    * 
    * \return whether the Send operation succeeded 
    */
-  bool Send(Packet& p, const MacAddress& dest, uint16_t protocolNumber);
+  bool Send(Packet& p, const Address& dest, uint16_t protocolNumber);
   /**
    * \returns the node base class which contains this network
    *          interface.
@@ -178,22 +178,35 @@
   bool NeedsArp (void) const;
 
   /**
+   * \param device a pointer to the net device which is calling this callback
+   * \param packet the packet received
+   * \param protocol the 16 bit protocol number associated with this packet.
+   *        This protocol number is expected to be the same protocol number
+   *        given to the Send method by the user on the sender side.
+   * \param address the address of the sender
+   * \returns true if the callback could handle the packet successfully, false
+   *          otherwise.
+   */
+  typedef Callback<bool,Ptr<NetDevice>,const Packet &,uint16_t,const Address &> ReceiveCallback;
+
+  /**
    * \param cb callback to invoke whenever a packet has been received and must
    *        be forwarded to the higher layers.
+   *
    */
-  void SetReceiveCallback (Callback<bool,Ptr<NetDevice>,const Packet &,uint16_t> cb);
+  void SetReceiveCallback (ReceiveCallback cb);
 
  protected:
   /**
    * \param node base class node pointer of device's node 
    * \param addr MAC address of this device.
    */
-  NetDevice(Ptr<Node> node, const MacAddress& addr);
+  NetDevice(Ptr<Node> node, const Address& addr);
   /**
    * Enable broadcast support. This method should be
    * called by subclasses from their constructor
    */
-  void EnableBroadcast (MacAddress broadcast);
+  void EnableBroadcast (Address broadcast);
   /**
    * Set m_isBroadcast flag to false
    */
@@ -230,6 +243,7 @@
    * \param p packet sent from below up to Network Device
    * \param param Extra parameter extracted from header and needed by
    * some protocols
+   * \param address the address of the sender of this packet.
    * \returns true if the packet was forwarded successfully,
    *          false otherwise.
    *
@@ -237,7 +251,7 @@
    * forwards it to the higher layers by calling this method
    * which is responsible for passing it up to the Rx callback.
    */
-  bool ForwardUp (Packet& p, uint32_t param);
+  bool ForwardUp (const Packet& p, uint32_t param, const Address &address);
 
 
   /**
@@ -248,8 +262,6 @@
    */
   virtual void DoDispose (void);
 
-  Callback<bool,Ptr<NetDevice>,const Packet &,uint16_t> m_receiveCallback;
-
  private:
   /**
    * \param p packet to send
@@ -262,7 +274,7 @@
    * method.  When the link is Up, this method is invoked to ask 
    * subclasses to forward packets. Subclasses MUST override this method.
    */
-  virtual bool SendTo (Packet& p, const MacAddress &dest, uint16_t protocolNumber) = 0;
+  virtual bool SendTo (Packet& p, const Address &dest, uint16_t protocolNumber) = 0;
   /**
    * \returns true if this NetDevice needs the higher-layers
    *          to perform ARP over it, false otherwise.
@@ -289,14 +301,15 @@
   Ptr<Node>     m_node;
   std::string   m_name;
   uint16_t      m_ifIndex;
-  MacAddress    m_address;
-  MacAddress    m_broadcast;
+  Address       m_address;
+  Address       m_broadcast;
   uint16_t      m_mtu;
   bool          m_isUp;
   bool          m_isBroadcast;
   bool          m_isMulticast;
   bool          m_isPointToPoint;
   Callback<void> m_linkChangeCallback;
+  ReceiveCallback m_receiveCallback;
 };
 
 }; // namespace ns3
--- a/src/node/node-list.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/node-list.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -53,7 +53,6 @@
   NodeList::Iterator Begin (void);
   NodeList::Iterator End (void);
   TraceResolver *CreateTraceResolver (TraceContext const &context);
-  Node *PeekNode (uint32_t n);
   Ptr<Node> GetNode (uint32_t n);
   uint32_t GetNNodes (void);
 
@@ -99,11 +98,6 @@
 {
   return m_nodes.size ();
 }
-Node *
-NodeListPriv::PeekNode (uint32_t n)
-{
-  return PeekPointer (m_nodes[n]);
-}
 
 Ptr<Node>
 NodeListPriv::GetNode (uint32_t n)
@@ -115,11 +109,11 @@
 TraceResolver *
 NodeListPriv::CreateTraceResolver (TraceContext const &context)
 {
-  ArrayTraceResolver<Node> *resolver =
-    new ArrayTraceResolver<Node>
+  ArrayTraceResolver<Ptr<Node> > *resolver =
+    new ArrayTraceResolver<Ptr<Node> >
     (context, 
      MakeCallback (&NodeListPriv::GetNNodes, this),
-     MakeCallback (&NodeListPriv::PeekNode, this));
+     MakeCallback (&NodeListPriv::GetNode, this));
   return resolver;
 }
 
--- a/src/node/node-list.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/node-list.h	Mon Aug 06 09:59:29 2007 +0200
@@ -40,7 +40,7 @@
 class NodeList
 {
 public:
-  typedef ArrayTraceResolver<Node>::Index NodeIndex;
+  typedef ArrayTraceResolver<Ptr<Node> >::Index NodeIndex;
   typedef std::vector< Ptr<Node> >::iterator Iterator;
 
   /**
--- a/src/node/node.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/node.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -1,32 +1,30 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation;
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// Author: George F. Riley<riley@ece.gatech.edu>
-//
-
-// Implement the basic Node object for ns3.
-// George F. Riley, Georgia Tech, Fall 2006
-
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 Georgia Tech Research Corporation, INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: George F. Riley<riley@ece.gatech.edu>
+ *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #include "node.h"
 #include "node-list.h"
 #include "net-device.h"
 #include "application.h"
+#include "packet-socket-factory.h"
 #include "ns3/simulator.h"
+#include "ns3/composite-trace-resolver.h"
 
 namespace ns3{
 
@@ -36,16 +34,23 @@
   : m_id(0), 
     m_sid(0)
 {
-  SetInterfaceId (Node::iid);
-  m_id = NodeList::Add (this);
+  Construct ();
 }
 
 Node::Node(uint32_t sid)
   : m_id(0), 
     m_sid(sid)
 { 
+  Construct ();
+}
+
+void
+Node::Construct (void)
+{
   SetInterfaceId (Node::iid);
   m_id = NodeList::Add (this);
+  Ptr<PacketSocketFactory> socketFactory = Create<PacketSocketFactory> ();
+  AddInterface (socketFactory);
 }
   
 Node::~Node ()
@@ -54,7 +59,9 @@
 TraceResolver *
 Node::CreateTraceResolver (TraceContext const &context)
 {
-  return DoCreateTraceResolver (context);
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  DoFillTraceResolver (*resolver);
+  return resolver;
 }
 
 uint32_t 
@@ -74,8 +81,9 @@
 {
   uint32_t index = m_devices.size ();
   m_devices.push_back (device);
-  DoAddDevice (device);
   device->SetIfIndex(index);
+  device->SetReceiveCallback (MakeCallback (&Node::ReceiveFromDevice, this));
+  NotifyDeviceAdded (device);
   return index;
 }
 Ptr<NetDevice>
@@ -107,8 +115,27 @@
   return m_applications.size ();
 }
 
+TraceResolver *
+Node::CreateDevicesTraceResolver (const TraceContext &context)
+{
+  ArrayTraceResolver<Ptr<NetDevice> > *resolver = 
+    new ArrayTraceResolver<Ptr<NetDevice> > (context,
+                                             MakeCallback (&Node::GetNDevices, this), 
+                                             MakeCallback (&Node::GetDevice, this));
+  
+  return resolver;
+}
 
-void Node::DoDispose()
+void
+Node::DoFillTraceResolver (CompositeTraceResolver &resolver)
+{
+  resolver.Add ("devices", 
+                MakeCallback (&Node::CreateDevicesTraceResolver, this),
+                Node::DEVICES);
+}
+
+void 
+Node::DoDispose()
 {
   for (std::vector<Ptr<NetDevice> >::iterator i = m_devices.begin ();
        i != m_devices.end (); i++)
@@ -129,4 +156,56 @@
   Object::DoDispose ();
 }
 
+void 
+Node::NotifyDeviceAdded (Ptr<NetDevice> device)
+{}
+
+void
+Node::RegisterProtocolHandler (ProtocolHandler handler, 
+                               uint16_t protocolType,
+                               Ptr<NetDevice> device)
+{
+  struct Node::ProtocolHandlerEntry entry;
+  entry.handler = handler;
+  entry.protocol = protocolType;
+  entry.device = device;
+  m_handlers.push_back (entry);
+}
+
+void
+Node::UnregisterProtocolHandler (ProtocolHandler handler)
+{
+  for (ProtocolHandlerList::iterator i = m_handlers.begin ();
+       i != m_handlers.end (); i++)
+    {
+      if (i->handler.IsEqual (handler))
+        {
+          m_handlers.erase (i);
+          break;
+        }
+    }
+}
+
+bool
+Node::ReceiveFromDevice (Ptr<NetDevice> device, const Packet &packet, 
+                         uint16_t protocol, const Address &from)
+{
+  bool found = false;
+  for (ProtocolHandlerList::iterator i = m_handlers.begin ();
+       i != m_handlers.end (); i++)
+    {
+      if (i->device == 0 ||
+          (i->device != 0 && i->device == device))
+        {
+          if (i->protocol == 0 || 
+              i->protocol == protocol)
+            {
+              i->handler (device, packet, protocol, from);
+              found = true;
+            }
+        }
+    }
+  return found;
+}
+
 }//namespace ns3
--- a/src/node/node.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/node.h	Mon Aug 06 09:59:29 2007 +0200
@@ -1,33 +1,31 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation;
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// Author: George F. Riley<riley@ece.gatech.edu>
-//
-
-// Define the basic Node object for ns3.
-// George F. Riley, Georgia Tech, Fall 2006
-
-#ifndef I_NODE_H
-#define I_NODE_H
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 Georgia Tech Research Corporation, INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: George F. Riley<riley@ece.gatech.edu>
+ *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef NODE_H
+#define NODE_H
 
 #include <vector>
 
 #include "ns3/object.h"
+#include "ns3/callback.h"
+#include "ns3/array-trace-resolver.h"
 
 namespace ns3 {
 
@@ -35,6 +33,9 @@
 class TraceResolver;
 class NetDevice;
 class Application;
+class Packet;
+class Address;
+class CompositeTraceResolver;
 
 /**
  * \brief A network Node.
@@ -57,6 +58,18 @@
 {
 public:
   static const InterfaceId iid;
+  typedef ArrayTraceResolver<Ptr<NetDevice> >::Index NetDeviceIndex;
+
+  /**
+   * Must be invoked by subclasses only.
+   */
+  Node();
+  /**
+   * \param systemId a unique integer used for parallel simulations.
+   *
+   * Must be invoked by subclasses only.
+   */
+  Node(uint32_t systemId);
 
   virtual ~Node();
 
@@ -93,11 +106,15 @@
    * Associate this device to this node.
    * This method is called automatically from NetDevice::NetDevice
    * so the user has little reason to call this method himself.
+   * The index returned is always non-zero.
    */
   uint32_t AddDevice (Ptr<NetDevice> device);
   /**
    * \param index the index of the requested NetDevice
    * \returns the requested NetDevice associated to this Node.
+   *
+   * The indexes used by the GetDevice method start at one and
+   * end at GetNDevices ()
    */
   Ptr<NetDevice> GetDevice (uint32_t index) const;
   /**
@@ -127,32 +144,52 @@
    */
   uint32_t GetNApplications (void) const;
 
-protected:
   /**
-   * Must be invoked by subclasses only.
+   * A protocol handler
    */
-  Node();
+  typedef Callback<void,Ptr<NetDevice>, const Packet &,uint16_t,const Address &> ProtocolHandler;
   /**
-   * \param systemId a unique integer used for parallel simulations.
+   * \param handler the handler to register
+   * \param protocolType the type of protocol this handler is 
+   *        interested in. This protocol type is a so-called
+   *        EtherType, as registered here:
+   *        http://standards.ieee.org/regauth/ethertype/eth.txt
+   *        the value zero is interpreted as matching all
+   *        protocols.
+   * \param device the device attached to this handler. If the
+   *        value is zero, the handler is attached to all
+   *        devices on this node.
+   */
+  void RegisterProtocolHandler (ProtocolHandler handler, 
+                                uint16_t protocolType,
+                                Ptr<NetDevice> device);
+  /**
+   * \param handler the handler to unregister
    *
-   * Must be invoked by subclasses only.
+   * After this call returns, the input handler will never
+   * be invoked anymore.
    */
-  Node(uint32_t systemId);
+  void UnregisterProtocolHandler (ProtocolHandler handler);
+
+protected:
   /**
    * The dispose method. Subclasses must override this method
    * and must chain up to it by calling Node::DoDispose at the
    * end of their own DoDispose method.
    */
   virtual void DoDispose (void);
+  /**
+   * \param resolver the resolver to store trace sources in.
+   *
+   * If a subclass wants to add new traces to a Node, it needs
+   * to override this method and record the new trace sources
+   * in the input resolver. Subclasses also _must_ chain up to
+   * their parent's DoFillTraceResolver method prior
+   * to recording they own trace sources.
+   */
+  virtual void DoFillTraceResolver (CompositeTraceResolver &resolver);
 private:
   /**
-   * \param context the trace context
-   * \returns a trace resolver to the user. The user must delete it.
-   *
-   * Subclasses must implement this method.
-   */
-  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context) = 0;
-  /**
    * \param device the device added to this Node.
    *
    * This method is invoked whenever a user calls Node::AddDevice.
@@ -160,14 +197,29 @@
    * at this point to setup the node's receive function for
    * the NetDevice packets.
    */
-  virtual void DoAddDevice (Ptr<NetDevice> device) = 0;
+  virtual void NotifyDeviceAdded (Ptr<NetDevice> device);
+
+  bool ReceiveFromDevice (Ptr<NetDevice> device, const Packet &packet, 
+                          uint16_t protocol, const Address &from);
+  void Construct (void);
+  TraceResolver *CreateDevicesTraceResolver (const TraceContext &context);
 
+  enum TraceSource {
+    DEVICES
+  };
+  struct ProtocolHandlerEntry {
+    ProtocolHandler handler;
+    uint16_t protocol;
+    Ptr<NetDevice> device;
+  };
+  typedef std::vector<struct Node::ProtocolHandlerEntry> ProtocolHandlerList;
   uint32_t    m_id;         // Node id for this node
   uint32_t    m_sid;        // System id for this node
   std::vector<Ptr<NetDevice> > m_devices;
   std::vector<Ptr<Application> > m_applications;
+  ProtocolHandlerList m_handlers;
 };
 
 } //namespace ns3
 
-#endif /* I_NODE_H */
+#endif /* NODE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/packet-socket-address.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,129 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "packet-socket-address.h"
+#include "net-device.h"
+
+namespace ns3 {
+
+PacketSocketAddress::PacketSocketAddress ()
+{}
+void 
+PacketSocketAddress::SetProtocol (uint16_t protocol)
+{
+  m_protocol = protocol;
+}
+void
+PacketSocketAddress::SetAllDevices (void)
+{
+  m_isSingleDevice = false;
+  m_device = 0;
+}
+void 
+PacketSocketAddress::SetSingleDevice (uint32_t index)
+{
+  m_isSingleDevice = true;
+  m_device = index;
+}
+void 
+PacketSocketAddress::SetPhysicalAddress (const Address address)
+{
+  m_address = address;
+}
+
+uint16_t 
+PacketSocketAddress::GetProtocol (void) const
+{
+  return m_protocol;
+}
+bool
+PacketSocketAddress::IsSingleDevice (void) const
+{
+  return m_isSingleDevice;
+}
+uint32_t
+PacketSocketAddress::GetSingleDevice (void) const
+{
+  return m_device;
+}
+Address 
+PacketSocketAddress::GetPhysicalAddress (void) const
+{
+  return m_address;
+}
+
+Address 
+PacketSocketAddress::ConvertTo (void) const
+{
+  Address address;
+  uint8_t buffer[Address::MAX_SIZE];
+  buffer[0] = m_protocol & 0xff;
+  buffer[1] = (m_protocol >> 8) & 0xff;
+  buffer[2] = (m_device >> 24) & 0xff;
+  buffer[3] = (m_device >> 16) & 0xff;
+  buffer[4] = (m_device >> 8) & 0xff;
+  buffer[5] = (m_device >> 0) & 0xff;
+  buffer[6] = m_isSingleDevice?1:0;
+  uint32_t copied = m_address.CopyAllTo (buffer + 7, Address::MAX_SIZE - 7);
+  return Address (GetType (), buffer, 7 + copied);
+}
+PacketSocketAddress 
+PacketSocketAddress::ConvertFrom (const Address &address)
+{
+  NS_ASSERT (IsMatchingType (address));
+  uint8_t buffer[Address::MAX_SIZE];
+  address.CopyTo (buffer);
+  uint16_t protocol = buffer[0] | (buffer[1] << 8);
+  uint32_t device = 0;
+  device |= buffer[2];
+  device <<= 8;
+  device |= buffer[3];
+  device <<= 8;
+  device |= buffer[4];
+  device <<= 8;
+  device |= buffer[5];
+  bool isSingleDevice = (buffer[6] == 1)?true:false;
+  Address physical;
+  physical.CopyAllFrom (buffer + 7, Address::MAX_SIZE - 7);
+  PacketSocketAddress ad;
+  ad.SetProtocol (protocol);
+  if (isSingleDevice)
+    {
+      ad.SetSingleDevice (device);
+    }
+  else
+    {
+      ad.SetAllDevices ();
+    }
+  ad.SetPhysicalAddress (physical);
+  return ad;
+}
+bool 
+PacketSocketAddress::IsMatchingType (const Address &address)
+{
+  return address.IsMatchingType (GetType ());
+}
+uint8_t 
+PacketSocketAddress::GetType (void)
+{
+  static uint8_t type = Address::Register ();
+  return type;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/packet-socket-address.h	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,76 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef PACKET_SOCKET_ADDRESS_H
+#define PACKET_SOCKET_ADDRESS_H
+
+#include "ns3/ptr.h"
+#include "address.h"
+#include "eui48-address.h"
+#include "eui64-address.h"
+#include "net-device.h"
+
+namespace ns3 {
+
+class NetDevice;
+
+class PacketSocketAddress
+{
+ public:
+  PacketSocketAddress ();
+  void SetProtocol (uint16_t protocol);
+
+  void SetAllDevices (void);
+  void SetSingleDevice (uint32_t device);
+  void SetPhysicalAddress (const Address address);
+
+  uint16_t GetProtocol (void) const;
+  uint32_t GetSingleDevice (void) const;
+  bool IsSingleDevice (void) const;
+  Address GetPhysicalAddress (void) const;
+
+  /**
+   * \returns a new Address instance
+   *
+   * Convert an instance of this class to a polymorphic Address instance.
+   */
+  Address ConvertTo (void) const;
+  /**
+   * \param address a polymorphic address
+   *
+   * Convert a polymorphic address to an Eui48Address instance.
+   * The conversion performs a type check.
+   */
+  static PacketSocketAddress ConvertFrom (const Address &address);
+  /**
+   * \returns true if the address matches, false otherwise.
+   */
+  static bool IsMatchingType (const Address &address);
+ private:
+  static uint8_t GetType (void);
+  uint16_t m_protocol;
+  bool m_isSingleDevice;
+  uint32_t m_device;
+  Address m_address;
+};
+
+
+} // namespace ns3
+
+#endif /* PACKET_SOCKET_ADDRESS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/packet-socket-factory.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,40 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ */
+#include "packet-socket-factory.h"
+#include "node.h"
+
+namespace ns3 {
+
+const InterfaceId PacketSocketFactory::iid = MakeInterfaceId ("Packet", 
+                                                              SocketFactory::iid);
+
+PacketSocketFactory::PacketSocketFactory ()
+{
+  SetInterfaceId (PacketSocketFactory::iid);
+}
+
+Ptr<Socket> PacketSocketFactory::CreateSocket (void)
+{
+  Ptr<Node> node = QueryInterface<Node> (Node::iid);
+  Ptr<PacketSocket> socket = Create<PacketSocket> (node);
+  return socket;
+} 
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/packet-socket-factory.h	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,52 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ */
+#ifndef PACKET_SOCKET_FACTORY_H
+#define PACKET_SOCKET_FACTORY_H
+
+#include "socket-factory.h"
+#include "packet-socket.h"
+
+namespace ns3 {
+
+class Socket;
+
+/**
+ * This can be used as an interface in a node in order for the node to
+ * generate PacketSockets that can connect to net devices.
+ */
+class PacketSocketFactory : public SocketFactory
+{
+public:
+  static const InterfaceId iid; /// Interface identifier
+
+  PacketSocketFactory ();
+
+  /**
+   * Creates a PacketSocket and returns a pointer to it.
+   *
+   * \return a pointer to the created socket
+   */
+  virtual Ptr<Socket> CreateSocket (void);
+};
+
+} // namespace ns3
+
+#endif /* PACKET_SOCKET_FACTORY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/packet-socket.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,341 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise, INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "packet-socket.h"
+#include "packet-socket-address.h"
+#include "ns3/debug.h"
+#include "ns3/node.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("PacketSocket");
+
+namespace ns3 {
+
+PacketSocket::PacketSocket (Ptr<Node> node)
+  : m_node (node)
+{
+  Init();
+}
+
+void 
+PacketSocket::Init()
+{
+  m_state = STATE_OPEN;
+  m_shutdownSend = false;
+  m_shutdownRecv = false;
+  m_errno = ERROR_NOTERROR;
+}
+
+PacketSocket::~PacketSocket ()
+{}
+
+void 
+PacketSocket::DoDispose (void)
+{
+  m_device = 0;
+}
+
+Ptr<Node>
+PacketSocket::GetNode (void) const
+{
+  return m_node;
+}
+
+
+int
+PacketSocket::Bind (void)
+{
+  PacketSocketAddress address;
+  address.SetProtocol (0);
+  address.SetAllDevices ();
+  return DoBind (address);
+}
+int
+PacketSocket::Bind (const Address &address)
+{
+  if (!PacketSocketAddress::IsMatchingType (address))
+    {
+      m_errno = ERROR_INVAL;
+      return -1;
+    }
+  PacketSocketAddress ad = PacketSocketAddress::ConvertFrom (address);
+  return DoBind (ad);
+}
+
+int
+PacketSocket::DoBind (const PacketSocketAddress &address)
+{
+  if (m_state == STATE_BOUND ||
+      m_state == STATE_CONNECTED)
+    {
+      m_errno = ERROR_INVAL;
+      return -1;
+    }
+  if (m_state == STATE_CLOSED)
+    {
+      m_errno = ERROR_BADF;
+      return -1;
+    }
+  Ptr<NetDevice> dev ;
+  if (address.IsSingleDevice ())
+    {
+      dev = 0;
+    }
+  else
+    {
+      m_node->GetDevice (address.GetSingleDevice ());
+    }
+  m_node->RegisterProtocolHandler (MakeCallback (&PacketSocket::ForwardUp, this),
+                                   address.GetProtocol (), dev);
+  m_state = STATE_BOUND;
+  m_protocol = address.GetProtocol ();
+  m_isSingleDevice = address.IsSingleDevice ();
+  m_device = address.GetSingleDevice ();
+  return 0;
+}
+
+enum Socket::SocketErrno
+PacketSocket::GetErrno (void) const
+{
+  return m_errno;
+}
+int
+PacketSocket::ShutdownSend (void)
+{
+  if (m_state == STATE_CLOSED)
+    {
+      m_errno = ERROR_BADF;
+      return -1;
+    }
+  m_shutdownSend = true;
+  return 0;
+}
+int
+PacketSocket::ShutdownRecv (void)
+{
+  if (m_state == STATE_CLOSED)
+    {
+      m_errno = ERROR_BADF;
+      return -1;
+    }
+  m_shutdownRecv = false;
+  return 0;
+}
+int
+PacketSocket::DoClose(ns3::Callback<void, Ptr<Socket> > closeCompleted)
+{
+  if (m_state == STATE_CLOSED)
+    {
+      m_errno = ERROR_BADF;
+      return -1;
+    }
+  if (!closeCompleted.IsNull ())
+    {
+      closeCompleted (this);
+    }
+  m_state = STATE_CLOSED;
+  return 0;
+}
+
+int
+PacketSocket::DoConnect(const Address &ad,
+                        ns3::Callback<void, Ptr<Socket> > connectionSucceeded,
+                        ns3::Callback<void, Ptr<Socket> > connectionFailed,
+                        ns3::Callback<void, Ptr<Socket> > halfClose)
+{
+  PacketSocketAddress address;
+  if (m_state == STATE_CLOSED)
+    {
+      m_errno = ERROR_BADF;
+      goto error;
+    }
+  if (m_state == STATE_OPEN)
+    {
+      // connect should happen _after_ bind.
+      m_errno = ERROR_INVAL; // generic error condition.
+      goto error;
+    }
+  if (m_state == STATE_CONNECTED)
+    {
+      m_errno = ERROR_ISCONN;
+      goto error;
+    }
+  if (!PacketSocketAddress::IsMatchingType (ad))
+    {
+      m_errno = ERROR_AFNOSUPPORT;
+      goto error;
+    }
+  m_destAddr = ad;
+  m_state = STATE_CONNECTED;
+  if (!connectionSucceeded.IsNull ())
+    {
+      connectionSucceeded (this);
+    }
+  return 0;
+ error:
+  if (!connectionFailed.IsNull ())
+    {
+      connectionFailed (this);
+    }
+  return -1;
+}
+
+int
+PacketSocket::DoAccept(ns3::Callback<bool, Ptr<Socket>, const Address &> connectionRequest,
+                       ns3::Callback<void, Ptr<Socket>, const Address &> newConnectionCreated,
+                       ns3::Callback<void, Ptr<Socket> > closeRequested)
+{
+  // calling accept on a packet socket is a programming error.
+  m_errno = ERROR_OPNOTSUPP;
+  return -1;
+}
+
+int
+PacketSocket::DoSend (const uint8_t* buffer,
+                      uint32_t size,
+                      ns3::Callback<void, Ptr<Socket>, uint32_t> dataSent)
+{
+  if (m_state == STATE_OPEN ||
+      m_state == STATE_BOUND)
+    {
+      m_errno = ERROR_NOTCONN;
+      return -1;
+    }
+  return DoSendTo (m_destAddr, buffer, size, dataSent);
+}
+
+int
+PacketSocket::DoSendTo(const Address &address,
+                       const uint8_t *buffer,
+                       uint32_t size,
+                       Callback<void, Ptr<Socket>, uint32_t> dataSent)
+{
+  PacketSocketAddress ad;
+  if (m_state == STATE_CLOSED)
+    {
+      m_errno = ERROR_BADF;
+      return -1;
+    }
+  if (m_state == STATE_OPEN)
+    {
+      // XXX should return another error here.
+      m_errno = ERROR_INVAL;
+      return -1;
+    }
+  if (m_shutdownSend)
+    {
+      m_errno = ERROR_SHUTDOWN;
+      return -1;
+    }
+  if (!PacketSocketAddress::IsMatchingType (address))
+    {
+      m_errno = ERROR_AFNOSUPPORT;
+      return -1;
+    }
+  ad = PacketSocketAddress::ConvertFrom (address);
+
+  Packet p;
+  if (buffer == 0)
+    {
+      p = Packet (size);
+    }
+  else
+    {
+      p = Packet (buffer, size);
+    }
+  
+  bool error = false;
+  Address dest = ad.GetPhysicalAddress ();
+  if (ad.IsSingleDevice ())
+    {
+      Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
+      if (!device->Send (p, dest, ad.GetProtocol ()))
+        {
+          error = true;
+        }
+    }
+  else
+    {
+      for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
+        {
+          Ptr<NetDevice> device = m_node->GetDevice (i);
+          if (!device->Send (p, dest, ad.GetProtocol ()))
+            {
+              error = true;
+            }
+        }
+    }
+  if (!error && !dataSent.IsNull ())
+    {
+      dataSent (this, p.GetSize ());
+    }
+
+  if (error)
+    {
+      m_errno = ERROR_INVAL;
+      return -1;
+    }
+  else
+    {
+      return 0;
+    }
+}
+
+void 
+PacketSocket::DoRecv(ns3::Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Address &> callback)
+{
+  m_rxCallback = callback;
+}
+
+void 
+PacketSocket::DoRecvDummy(ns3::Callback<void, Ptr<Socket>, uint32_t, const Address &> callback)
+{
+  m_dummyRxCallback = callback;
+}
+
+void 
+PacketSocket::ForwardUp (Ptr<NetDevice> device, const Packet &packet, 
+                         uint16_t protocol, const Address &from)
+{
+  if (m_shutdownRecv)
+    {
+      return;
+    }
+
+  Packet p = packet;
+
+  PacketSocketAddress address;
+  address.SetPhysicalAddress (from);
+  address.SetSingleDevice (device->GetIfIndex ());
+  address.SetProtocol (protocol);
+
+  NS_DEBUG ("PacketSocket::ForwardUp: UID is " << packet.GetUid()
+            << " PacketSocket " << this);
+  if (!m_dummyRxCallback.IsNull ())
+    {
+      m_dummyRxCallback (this, p.GetSize (), address.ConvertTo ());
+    }
+  if (!m_rxCallback.IsNull ())
+    {
+      m_rxCallback (this, p.PeekData (), p.GetSize (), address.ConvertTo ());
+    }
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/packet-socket.h	Mon Aug 06 09:59:29 2007 +0200
@@ -0,0 +1,133 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise, INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>,
+ *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef PACKET_SOCKET_H
+#define PACKET_SOCKET_H
+
+#include <stdint.h>
+#include "ns3/callback.h"
+#include "ns3/ptr.h"
+#include "ns3/socket.h"
+
+namespace ns3 {
+
+class Node;
+class Packet;
+class NetDevice;
+class PacketSocketAddress;
+
+/**
+ * \brief A PacketSocket is a link between an application and a net device.
+ *
+ * A PacketSocket can be used to connect an application to a net
+ * device. The application provides the buffers of data, the socket
+ * conserts them to a raw packet and the net device then adds the
+ * protocol specific headers and trailers. This socket type
+ * is very similar to the linux and BSD "packet" sockets.
+ *
+ * Here is a summary of the semantics of this class:
+ * - Bind: Bind uses only the protocol and device fields of the 
+ *       PacketSocketAddress. If none are provided, Bind uses 
+ *       zero for both, which means that the socket is bound
+ *       to all protocols on all devices on the node.
+ *
+ * - Connect: uses only the protocol, device and "physical address" 
+ *       field of the PacketSocketAddress. It is used to set the default
+ *       destination address for outgoing packets.
+ *
+ * - Send: send the input packet to the underlying NetDevices
+ *       with the default destination address. The socket must
+ *       be bound and connected.
+ *
+ * - SendTo: uses the protocol, device, and "physical address" 
+ *       fields of the PacketSocketAddress. The device value is 
+ *       used to specialize the packet transmission to a single 
+ *       device, the protocol value specifies the protocol of this
+ *       packet only and the "physical address" field is used to override the 
+ *       default destination address. The socket must be bound.
+ *
+ * - Recv: The address represents the address of the packer originator.
+ *       The fields "physical address", device, and protocol are filled.
+ *
+ * - Accept: not allowed
+ */
+class PacketSocket : public Socket
+{
+public:
+  PacketSocket (Ptr<Node> node);
+  virtual ~PacketSocket ();
+
+  virtual enum SocketErrno GetErrno (void) const;
+  virtual Ptr<Node> GetNode (void) const;
+  virtual int Bind (void);
+  virtual int Bind (const Address & address);
+  virtual int ShutdownSend (void);
+  virtual int ShutdownRecv (void);
+
+private:
+  virtual int DoClose(Callback<void, Ptr<Socket> > closeCompleted);
+  virtual int DoConnect(const Address & address,
+                        Callback<void, Ptr<Socket> > connectionSucceeded,
+                        Callback<void, Ptr<Socket> > connectionFailed,
+                        Callback<void, Ptr<Socket> > halfClose);
+  virtual int DoAccept(Callback<bool, Ptr<Socket>, const Address&> connectionRequest,
+                       Callback<void, Ptr<Socket>, const Address&> newConnectionCreated,
+                       Callback<void, Ptr<Socket> > closeRequested);
+  virtual int DoSend (const uint8_t* buffer,
+                      uint32_t size,
+                      Callback<void, Ptr<Socket>, uint32_t> dataSent);
+  virtual int DoSendTo(const Address &address,
+                       const uint8_t *buffer,
+                       uint32_t size,
+                       Callback<void, Ptr<Socket>, uint32_t> dataSent);
+  virtual void DoRecv(Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Address&> receive);
+  virtual void DoRecvDummy(Callback<void, Ptr<Socket>, uint32_t,const Address&>);
+
+private:
+  void Init (void);
+  void ForwardUp (Ptr<NetDevice> device, const Packet &packet, 
+                  uint16_t protocol, const Address &from);
+  int DoBind (const PacketSocketAddress &address);
+  virtual void DoDispose (void);
+
+  enum State {
+    STATE_OPEN,
+    STATE_BOUND,     // open and bound
+    STATE_CONNECTED, // open, bound and connected
+    STATE_CLOSED
+  };
+  Ptr<Node> m_node;
+  Callback<void,Ptr<Socket>,uint32_t,const Address &> m_dummyRxCallback;
+  Callback<void,Ptr<Socket>,uint8_t const*,uint32_t, const Address &> m_rxCallback;
+  enum SocketErrno m_errno;
+  bool m_shutdownSend;
+  bool m_shutdownRecv;
+  enum State m_state;
+  uint16_t m_protocol;
+  bool m_isSingleDevice;
+  uint32_t m_device;
+  Address m_destAddr; /// Default destination address
+};
+
+}//namespace ns3
+
+#endif /* PACKET_SOCKET_H */
+
+
--- a/src/node/socket.cc	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/socket.cc	Mon Aug 06 09:59:29 2007 +0200
@@ -5,24 +5,23 @@
 Socket::~Socket ()
 {}
 
-void 
+int
 Socket::Close(Callback<void, Ptr<Socket> > closeCompleted)
 {
-  DoClose (closeCompleted);
+  return DoClose (closeCompleted);
 }
 
-void 
-Socket::Connect(const Ipv4Address & address,
-               uint16_t portNumber,
+int
+Socket::Connect(const Address & address,
                Callback<void, Ptr<Socket> > connectionSucceeded,
                Callback<void, Ptr<Socket> > connectionFailed,
                Callback<void, Ptr<Socket> > halfClose)
 {
-  DoConnect (address, portNumber, connectionSucceeded, connectionFailed, halfClose);
+  return DoConnect (address, connectionSucceeded, connectionFailed, halfClose);
 }
 int
-Socket::Accept(Callback<bool, Ptr<Socket>, const Ipv4Address&, uint16_t> connectionRequest,
-	       Callback<void, Ptr<Socket>, const Ipv4Address&, uint16_t> newConnectionCreated,
+Socket::Accept(Callback<bool, Ptr<Socket>, const Address&> connectionRequest,
+	       Callback<void, Ptr<Socket>, const Address&> newConnectionCreated,
 	       Callback<void, Ptr<Socket> > closeRequested)
 {
   return DoAccept (connectionRequest, newConnectionCreated, closeRequested);
@@ -35,28 +34,27 @@
   return DoSend (buffer, size, dataSent);
 }
 int 
-Socket::SendTo(const Ipv4Address &address,
-	       uint16_t port,
+Socket::SendTo(const Address &address,
 	       const uint8_t *buffer,
 	       uint32_t size,
 	       Callback<void, Ptr<Socket>, uint32_t> dataSent)
 {
-  return DoSendTo (address, port, buffer, size, dataSent);
+  return DoSendTo (address, buffer, size, dataSent);
 }
 void 
-Socket::Recv(Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Ipv4Address&, uint16_t> callback)
+Socket::Recv(Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Address&> callback)
 {
   DoRecv (callback);
 }
 void 
-Socket::RecvDummy(Callback<void, Ptr<Socket>, uint32_t,const Ipv4Address&, uint16_t> callback)
+Socket::RecvDummy(Callback<void, Ptr<Socket>, uint32_t,const Address&> callback)
 {
   DoRecvDummy (callback);
 }
 
 
 bool 
-Socket::RefuseAllConnections (Ptr<Socket> socket, const Ipv4Address& address, uint16_t port)
+Socket::RefuseAllConnections (Ptr<Socket> socket, const Address& address)
 {
   return false;
 }
@@ -67,14 +65,14 @@
 Socket::DummyCallbackVoidSocketUi32 (Ptr<Socket> socket, uint32_t)
 {}
 void 
-Socket::DummyCallbackVoidSocketUi32Ipv4AddressUi16 (Ptr<Socket> socket, uint32_t, const Ipv4Address &, uint16_t)
+Socket::DummyCallbackVoidSocketUi32Address (Ptr<Socket> socket, uint32_t, const Address &)
 {}
 void 
-Socket::DummyCallbackVoidSocketBufferUi32Ipv4AddressUi16 (Ptr<Socket> socket, const uint8_t *, uint32_t,
-							  const Ipv4Address &, uint16_t)
+Socket::DummyCallbackVoidSocketBufferUi32Address (Ptr<Socket> socket, const uint8_t *, uint32_t,
+						  const Address &)
 {}
 void 
-Socket::DummyCallbackVoidSocketIpv4AddressUi16 (Ptr<Socket> socket, const Ipv4Address &, uint16_t)
+Socket::DummyCallbackVoidSocketAddress (Ptr<Socket> socket, const Address &)
 {}
 
 
--- a/src/node/socket.h	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/socket.h	Mon Aug 06 09:59:29 2007 +0200
@@ -23,8 +23,8 @@
 
 #include "ns3/callback.h"
 #include "ns3/ptr.h"
-#include "ipv4-address.h"
 #include "ns3/object.h"
+#include "address.h"
 #include <stdint.h>
 
 namespace ns3 {
@@ -35,8 +35,7 @@
  * \brief Define a Socket API based on the BSD Socket API.
  *
  * Contrary to the original BSD socket API, this API is asynchronous:
- * it does not contain blocking calls. This API also does not use
- * the dreaded BSD sockaddr_t type. Other than that, it tries to stick
+ * it does not contain blocking calls. Other than that, it tries to stick
  * to the BSD API to make it easier those who know the BSD API to use
  * this API.
  */
@@ -53,6 +52,9 @@
     ERROR_AGAIN,
     ERROR_SHUTDOWN,
     ERROR_OPNOTSUPP,
+    ERROR_AFNOSUPPORT,
+    ERROR_INVAL,
+    ERROR_BADF,
     SOCKET_ERRNO_LAST
   };
 
@@ -69,42 +71,20 @@
   virtual Ptr<Node> GetNode (void) const = 0;
 
   /** 
-   * Allocate a free port number and
-   * bind this socket to this port number on all
-   * interfaces of this system.
+   * \param address the address to try to allocate
+   * \returns 0 on success, -1 on failure.
+   *
+   * Allocate a local endpoint for this socket.
+   */
+  virtual int Bind (const Address &address) = 0;
+
+  /** 
+   * Allocate a local endpoint for this socket.
    *
    * \returns 0 on success, -1 on failure.
    */
-  virtual int Bind (void) = 0;
-
-  /** 
-   * Allocate a free port number and
-   * bind this socket to this port number on the
-   * specified interface.
-   *
-   * \param address address of interface to bind to.
-   * \returns 0 on success, -1 on failure.
-   */
-  virtual int Bind (Ipv4Address address) = 0;
+  virtual int Bind () = 0;
 
-  /**
-   * Bind this socket to this port number
-   * on all interfaces of this system.
-   *
-   * \param port port to bind to on all interfaces
-   * \returns 0 on success, -1 on failure.
-   */
-  virtual int Bind (uint16_t port) = 0; 
-
-  /**
-   * Bind this socket to this port number
-   * on the interface specified by address.
-   *
-   * \param address address of interface to bind to.
-   * \param port port to bind to on specified interface
-   * \returns 0 on success, -1 on failure.
-   */
-  virtual int Bind (Ipv4Address address, uint16_t port) = 0;
 
   /** 
    * \brief Close a socket.
@@ -114,7 +94,7 @@
    * After the Close call, the socket is no longer valid, and cannot
    * safely be used for subsequent operations.
    */
-  void Close(Callback<void, Ptr<Socket> > closeCompleted = MakeCallback (&Socket::DummyCallbackVoidSocket));
+  int Close(Callback<void, Ptr<Socket> > closeCompleted = MakeCallback (&Socket::DummyCallbackVoidSocket));
 
   /**
    * \returns zero on success, -1 on failure.
@@ -134,8 +114,7 @@
 
   /**
    * \brief Initiate a connection to a remote host
-   * \param address IP Address of remote.
-   * \param portNumber Port number of remote
+   * \param address Address of remote.
    * \param connectionSucceeded this callback is invoked when the connection request
    *        initiated by the user is successfully completed. The callback is passed
    *        back a pointer to the same socket object.
@@ -145,11 +124,10 @@
    * \param halfClose XXX When exactly is this callback invoked ? If it invoked when the
    *        other side closes the connection ? Or when I call Close ?
    */
-  void Connect(const Ipv4Address & address,
-               uint16_t portNumber,
-               Callback<void, Ptr<Socket> > connectionSucceeded = MakeCallback(&Socket::DummyCallbackVoidSocket),
-               Callback<void, Ptr<Socket> > connectionFailed = MakeCallback(&Socket::DummyCallbackVoidSocket),
-               Callback<void, Ptr<Socket> > halfClose = MakeCallback(&Socket::DummyCallbackVoidSocket));
+  int Connect(const Address &address,
+              Callback<void, Ptr<Socket> > connectionSucceeded = MakeCallback(&Socket::DummyCallbackVoidSocket),
+              Callback<void, Ptr<Socket> > connectionFailed = MakeCallback(&Socket::DummyCallbackVoidSocket),
+              Callback<void, Ptr<Socket> > halfClose = MakeCallback(&Socket::DummyCallbackVoidSocket));
     
   /**
    * \brief Accept connection requests from remote hosts
@@ -170,10 +148,10 @@
    * \param closeRequested Callback for connection close request from peer.
    *        XXX: when is this callback invoked ?
    */
-  int Accept(Callback<bool, Ptr<Socket>, const Ipv4Address&, uint16_t> connectionRequest = 
+  int Accept(Callback<bool, Ptr<Socket>, const Address &> connectionRequest = 
              MakeCallback(&Socket::RefuseAllConnections),
-             Callback<void, Ptr<Socket>, const Ipv4Address&, uint16_t> newConnectionCreated = 
-             MakeCallback (&Socket::DummyCallbackVoidSocketIpv4AddressUi16),
+             Callback<void, Ptr<Socket>, const Address&> newConnectionCreated = 
+             MakeCallback (&Socket::DummyCallbackVoidSocketAddress),
              Callback<void, Ptr<Socket> > closeRequested = MakeCallback (&Socket::DummyCallbackVoidSocket));
 
   /**
@@ -191,15 +169,13 @@
   /**
    * \brief Send data to a specified peer.
    * \param address IP Address of remote host
-   * \param port port number
    * \param buffer Data to send (nil if dummy data).
    * \param size Number of bytes to send.
    * \param dataSent Data sent callback.
    * \returns -1 in case of error or the number of bytes copied in the 
    *          internal buffer and accepted for transmission.
    */
-  int SendTo(const Ipv4Address &address,
-             uint16_t port,
+  int SendTo(const Address &address,
              const uint8_t *buffer,
              uint32_t size,
              Callback<void, Ptr<Socket>, uint32_t> dataSent = MakeCallback (&Socket::DummyCallbackVoidSocketUi32));
@@ -213,8 +189,8 @@
    * allocation to hold the dummy memory into a buffer which can be passed
    * to the user. Instead, consider using the RecvDummy method.
    */
-  void Recv(Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Ipv4Address&, uint16_t> receivedData = 
-            MakeCallback (&Socket::DummyCallbackVoidSocketBufferUi32Ipv4AddressUi16));
+  void Recv(Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Address&> receivedData = 
+            MakeCallback (&Socket::DummyCallbackVoidSocketBufferUi32Address));
   
   /**
    * \brief Receive data
@@ -223,38 +199,36 @@
    * This method is included because it is vastly more efficient than the 
    * Recv method when you use dummy payload.
    */
-  void RecvDummy(Callback<void, Ptr<Socket>, uint32_t,const Ipv4Address&, uint16_t> receivedData =
-                 MakeCallback (&Socket::DummyCallbackVoidSocketUi32Ipv4AddressUi16));
+  void RecvDummy(Callback<void, Ptr<Socket>, uint32_t,const Address&> receivedData =
+                 MakeCallback (&Socket::DummyCallbackVoidSocketUi32Address));
 
 private:
-  virtual void DoClose(Callback<void, Ptr<Socket> > closeCompleted) = 0;
-  virtual void DoConnect(const Ipv4Address & address,
-                         uint16_t portNumber,
-                         Callback<void, Ptr<Socket> > connectionSucceeded,
-                         Callback<void, Ptr<Socket> > connectionFailed,
-                         Callback<void, Ptr<Socket> > halfClose) = 0;
-  virtual int DoAccept(Callback<bool, Ptr<Socket>, const Ipv4Address&, uint16_t> connectionRequest,
-                       Callback<void, Ptr<Socket>, const Ipv4Address&, uint16_t> newConnectionCreated,
+  virtual int DoClose(Callback<void, Ptr<Socket> > closeCompleted) = 0;
+  virtual int DoConnect(const Address & address,
+                        Callback<void, Ptr<Socket> > connectionSucceeded,
+                        Callback<void, Ptr<Socket> > connectionFailed,
+                        Callback<void, Ptr<Socket> > halfClose) = 0;
+  virtual int DoAccept(Callback<bool, Ptr<Socket>, const Address&> connectionRequest,
+                       Callback<void, Ptr<Socket>, const Address&> newConnectionCreated,
                        Callback<void, Ptr<Socket> > closeRequested) = 0;
   virtual int DoSend (const uint8_t* buffer,
-                    uint32_t size,
-                    Callback<void, Ptr<Socket>, uint32_t> dataSent) = 0;
-  virtual int DoSendTo(const Ipv4Address &address,
-                       uint16_t port,
+                      uint32_t size,
+                      Callback<void, Ptr<Socket>, uint32_t> dataSent) = 0;
+  virtual int DoSendTo(const Address &address,
                        const uint8_t *buffer,
                        uint32_t size,
                        Callback<void, Ptr<Socket>, uint32_t> dataSent) = 0;
-  virtual void DoRecv(Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Ipv4Address&, uint16_t> receive) = 0;
-  virtual void DoRecvDummy(Callback<void, Ptr<Socket>, uint32_t,const Ipv4Address&, uint16_t>) = 0;
+  virtual void DoRecv(Callback<void, Ptr<Socket>, const uint8_t*, uint32_t,const Address&> receive) = 0;
+  virtual void DoRecvDummy(Callback<void, Ptr<Socket>, uint32_t,const Address&>) = 0;
 
 
-  static bool RefuseAllConnections (Ptr<Socket> socket, const Ipv4Address& address, uint16_t port);
+  static bool RefuseAllConnections (Ptr<Socket> socket, const Address& address);
   static void DummyCallbackVoidSocket (Ptr<Socket> socket);
   static void DummyCallbackVoidSocketUi32 (Ptr<Socket> socket, uint32_t);
-  static void DummyCallbackVoidSocketUi32Ipv4AddressUi16 (Ptr<Socket> socket, uint32_t, const Ipv4Address &, uint16_t);
-  static void DummyCallbackVoidSocketBufferUi32Ipv4AddressUi16 (Ptr<Socket> socket, const uint8_t *, uint32_t, 
-                                                                const Ipv4Address &, uint16_t);
-  static void DummyCallbackVoidSocketIpv4AddressUi16 (Ptr<Socket> socket, const Ipv4Address &, uint16_t);
+  static void DummyCallbackVoidSocketUi32Address (Ptr<Socket> socket, uint32_t, const Address &);
+  static void DummyCallbackVoidSocketBufferUi32Address (Ptr<Socket> socket, const uint8_t *, uint32_t, 
+                                                                const Address &);
+  static void DummyCallbackVoidSocketAddress (Ptr<Socket> socket, const Address &);
 };
 
 } //namespace ns3
--- a/src/node/wscript	Mon Aug 06 09:58:03 2007 +0200
+++ b/src/node/wscript	Mon Aug 06 09:59:29 2007 +0200
@@ -6,11 +6,15 @@
     node.target = node.name
     node.uselib_local = ['ns3-core', 'ns3-common', 'ns3-simulator']
     node.source = [
+        'address.cc',
+        'eui48-address.cc',
+        'eui64-address.cc',
+        'inet-socket-address.cc',
+        'packet-socket-address.cc',
         'node.cc',
         'ipv4-address.cc',
         'net-device.cc',
-        'mac-address.cc',
-        'address-utils.cc',
+	'address-utils.cc',
         'llc-snap-header.cc',
         'ethernet-header.cc',
         'ethernet-trailer.cc',
@@ -21,6 +25,8 @@
         'node-list.cc',
         'socket.cc',
         'socket-factory.cc',
+        'packet-socket-factory.cc',
+        'packet-socket.cc',
         'udp.cc',
         'ipv4.cc',
         'application.cc',
@@ -28,11 +34,15 @@
 
     headers = bld.create_obj('ns3header')
     headers.source = [
+        'address.h',
+        'eui48-address.h',
+        'eui64-address.h',
+        'inet-socket-address.h',
+        'packet-socket-address.h',
         'node.h',
         'ipv4-address.h',
         'net-device.h',
-        'mac-address.h',
-        'address-utils.h',
+	'address-utils.h',
         'ipv4-route.h',
         'queue.h',
         'drop-tail-queue.h',
@@ -43,6 +53,7 @@
         'node-list.h',
         'socket.h',
         'socket-factory.h',
+        'packet-socket-factory.h',
         'udp.h',
         'ipv4.h',
         'application.h',